Bug 1505181 - Use canonical function in TypeNewScript::rollbackPartiallyInitializedObjects. r=bhackett, a=RyanVM
authorJan de Mooij <jdemooij@mozilla.com>
Tue, 13 Nov 2018 14:14:51 +0100
changeset 450465 ee204e26690e07dd6afe445ed30c7a026c2c29c0
parent 450464 a08c8493ba193add59c6236d6a1b4af4a64358d8
child 450466 1cab3104b7a66866c907d41438ab45532fcdc8ef
push id237
push userryanvm@gmail.com
push dateTue, 13 Nov 2018 17:47:47 +0000
treeherdermozilla-esr60@ee204e26690e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbhackett, RyanVM
bugs1505181
milestone60.3.1
Bug 1505181 - Use canonical function in TypeNewScript::rollbackPartiallyInitializedObjects. r=bhackett, a=RyanVM
js/src/vm/JSFunction.h
js/src/vm/ObjectGroup.cpp
js/src/vm/TypeInference.cpp
--- a/js/src/vm/JSFunction.h
+++ b/js/src/vm/JSFunction.h
@@ -496,16 +496,29 @@ class JSFunction : public js::NativeObje
             JSScript* script = existingScriptNonDelazifying();
             flags_ &= ~INTERPRETED_LAZY;
             flags_ |= INTERPRETED;
             initScript(script);
         }
         return nonLazyScript();
     }
 
+    // If this is a scripted function, returns its canonical function (the
+    // original function allocated by the frontend). Note that lazy self-hosted
+    // builtins don't have a lazy script so in that case we also return nullptr.
+    JSFunction* maybeCanonicalFunction() const {
+        if (hasScript()) {
+            return nonLazyScript()->functionNonDelazifying();
+        }
+        if (isInterpretedLazy() && !isSelfHostedBuiltin()) {
+            return lazyScript()->functionNonDelazifying();
+        }
+        return nullptr;
+    }
+
     // The state of a JSFunction whose script errored out during bytecode
     // compilation. Such JSFunctions are only reachable via GC iteration and
     // not from script.
     bool hasUncompiledScript() const {
         MOZ_ASSERT(hasScript());
         return !u.scripted.s.script_;
     }
 
--- a/js/src/vm/ObjectGroup.cpp
+++ b/js/src/vm/ObjectGroup.cpp
@@ -479,23 +479,17 @@ ObjectGroup::defaultNewGroup(JSContext* 
     // unboxed plain object.
     MOZ_ASSERT_IF(!clasp, !!associated);
 
     if (associated && !associated->is<TypeDescr>()) {
         MOZ_ASSERT(!clasp);
         if (associated->is<JSFunction>()) {
 
             // Canonicalize new functions to use the original one associated with its script.
-            JSFunction* fun = &associated->as<JSFunction>();
-            if (fun->hasScript())
-                associated = fun->nonLazyScript()->functionNonDelazifying();
-            else if (fun->isInterpretedLazy() && !fun->isSelfHostedBuiltin())
-                associated = fun->lazyScript()->functionNonDelazifying();
-            else
-                associated = nullptr;
+            associated = associated->as<JSFunction>().maybeCanonicalFunction();
 
             // If we have previously cleared the 'new' script information for this
             // function, don't try to construct another one.
             if (associated && associated->as<JSFunction>().wasNewScriptCleared())
                 associated = nullptr;
 
         } else {
             associated = nullptr;
--- a/js/src/vm/TypeInference.cpp
+++ b/js/src/vm/TypeInference.cpp
@@ -3623,16 +3623,20 @@ PreliminaryObjectArrayWithTemplate::mayb
 // objects created with the group.
 /* static */ bool
 TypeNewScript::make(JSContext* cx, ObjectGroup* group, JSFunction* fun)
 {
     MOZ_ASSERT(cx->zone()->types.activeAnalysis);
     MOZ_ASSERT(!group->newScript());
     MOZ_ASSERT(!group->maybeUnboxedLayout());
 
+    // rollbackPartiallyInitializedObjects expects function_ to be
+    // canonicalized.
+    MOZ_ASSERT(fun->maybeCanonicalFunction() == fun);
+
     if (group->unknownProperties())
         return true;
 
     ScopedJSDeletePtr<TypeNewScript> newScript(cx->new_<TypeNewScript>());
     if (!newScript)
         return false;
 
     newScript->function_ = fun;
@@ -3985,18 +3989,25 @@ TypeNewScript::rollbackPartiallyInitiali
     for (const CooperatingContext& target : cx->runtime()->cooperatingContexts()) {
         for (AllScriptFramesIter iter(cx, target); !iter.done(); ++iter) {
             {
                 AutoEnterOOMUnsafeRegion oomUnsafe;
                 if (!pcOffsets.append(iter.script()->pcToOffset(iter.pc())))
                     oomUnsafe.crash("rollbackPartiallyInitializedObjects");
             }
 
-            if (!iter.isConstructing() || !iter.matchCallee(cx, function))
+            if (!iter.isConstructing()) {
                 continue;
+            }
+
+            MOZ_ASSERT(iter.calleeTemplate()->maybeCanonicalFunction());
+
+            if (iter.calleeTemplate()->maybeCanonicalFunction() != function) {
+                continue;
+            }
 
             // Derived class constructors initialize their this-binding later and
             // we shouldn't run the definite properties analysis on them.
             MOZ_ASSERT(!iter.script()->isDerivedClassConstructor());
 
             Value thisv = iter.thisArgument(cx);
             if (!thisv.isObject() ||
                 thisv.toObject().hasLazyGroup() ||