Bug 956156 - Fix FinishDefinitePropertiesAnalysis to not assert if a script is compiled more than once. r=shu, a=bajaj
authorJan de Mooij <jdemooij@mozilla.com>
Thu, 09 Jan 2014 11:15:26 +0100
changeset 175640 4e912655c7f6de0dcbb0e29eeb31a9ba73b74f71
parent 175639 c716b93520c490fcbd3fcb8d7b0fe59b1535b6dc
child 175641 ab13ac48d6dcfc38276377dbbf87f93c083422fa
push id445
push userffxbld
push dateMon, 10 Mar 2014 22:05:19 +0000
treeherdermozilla-release@dc38b741b04e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersshu, bajaj
bugs956156
milestone28.0a2
Bug 956156 - Fix FinishDefinitePropertiesAnalysis to not assert if a script is compiled more than once. r=shu, a=bajaj
js/src/jit-test/tests/ion/bug956156.js
js/src/jsinfer.cpp
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/ion/bug956156.js
@@ -0,0 +1,7 @@
+// |jit-test| error:TypeError
+function f() {
+    ((function g(x) {
+        g(x.slice)
+    })([]))
+}
+new f
--- a/js/src/jsinfer.cpp
+++ b/js/src/jsinfer.cpp
@@ -997,40 +997,62 @@ types::FinishCompilation(JSContext *cx, 
 static void
 CheckDefinitePropertiesTypeSet(JSContext *cx, TemporaryTypeSet *frozen, StackTypeSet *actual)
 {
     // The definite properties analysis happens on the main thread, so no new
     // types can have been added to actual. The analysis may have updated the
     // contents of |frozen| though with new speculative types, and these need
     // to be reflected in |actual| for AddClearDefiniteFunctionUsesInScript
     // to work.
-    JS_ASSERT(actual->isSubset(frozen));
-
     if (!frozen->isSubset(actual)) {
         TypeSet::TypeList list;
         frozen->enumerateTypes(&list);
 
         for (size_t i = 0; i < list.length(); i++)
             actual->addType(cx, list[i]);
     }
 }
 
 void
 types::FinishDefinitePropertiesAnalysis(JSContext *cx, CompilerConstraintList *constraints)
 {
+#ifdef DEBUG
+    // Assert no new types have been added to the StackTypeSets. Do this before
+    // calling CheckDefinitePropertiesTypeSet, as it may add new types to the
+    // StackTypeSets and break these invariants if a script is inlined more
+    // than once. See also CheckDefinitePropertiesTypeSet.
     for (size_t i = 0; i < constraints->numFrozenScripts(); i++) {
         const CompilerConstraintList::FrozenScript &entry = constraints->frozenScript(i);
-        JS_ASSERT(entry.script->types);
-
-        CheckDefinitePropertiesTypeSet(cx, entry.thisTypes, types::TypeScript::ThisTypes(entry.script));
-        unsigned nargs = entry.script->function() ? entry.script->function()->nargs : 0;
-        for (size_t i = 0; i < nargs; i++)
-            CheckDefinitePropertiesTypeSet(cx, &entry.argTypes[i], types::TypeScript::ArgTypes(entry.script, i));
-        for (size_t i = 0; i < entry.script->nTypeSets; i++)
-            CheckDefinitePropertiesTypeSet(cx, &entry.bytecodeTypes[i], &entry.script->types->typeArray()[i]);
+        JSScript *script = entry.script;
+        JS_ASSERT(script->types);
+
+        JS_ASSERT(TypeScript::ThisTypes(script)->isSubset(entry.thisTypes));
+
+        unsigned nargs = script->function() ? script->function()->nargs : 0;
+        for (size_t j = 0; j < nargs; j++)
+            JS_ASSERT(TypeScript::ArgTypes(script, j)->isSubset(&entry.argTypes[j]));
+
+        for (size_t j = 0; j < script->nTypeSets; j++)
+            JS_ASSERT(script->types->typeArray()[j].isSubset(&entry.bytecodeTypes[j]));
+    }
+#endif
+
+    for (size_t i = 0; i < constraints->numFrozenScripts(); i++) {
+        const CompilerConstraintList::FrozenScript &entry = constraints->frozenScript(i);
+        JSScript *script = entry.script;
+        JS_ASSERT(script->types);
+
+        CheckDefinitePropertiesTypeSet(cx, entry.thisTypes, TypeScript::ThisTypes(script));
+
+        unsigned nargs = script->function() ? script->function()->nargs : 0;
+        for (size_t j = 0; j < nargs; j++)
+            CheckDefinitePropertiesTypeSet(cx, &entry.argTypes[j], TypeScript::ArgTypes(script, j));
+
+        for (size_t j = 0; j < script->nTypeSets; j++)
+            CheckDefinitePropertiesTypeSet(cx, &entry.bytecodeTypes[j], &script->types->typeArray()[j]);
     }
 }
 
 namespace {
 
 // Constraint which triggers recompilation of a script if any type is added to a type set. */
 class ConstraintDataFreeze
 {