Bug 1533003 - Split out inner-function scope linking in script compile r=jandem
authorTed Campbell <tcampbell@mozilla.com>
Wed, 06 Mar 2019 18:04:10 +0000
changeset 520615 62ba39ca25a211f46f5180e6f33f3af8008a963d
parent 520614 154ce749b8e1913ff4393a9e1e12d3a74941ec09
child 520616 e993e4a050b059ebb7dd022bd88b58534758ca44
push id10862
push userffxbld-merge
push dateMon, 11 Mar 2019 13:01:11 +0000
treeherdermozilla-beta@a2e7f5c935da [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjandem
bugs1533003
milestone67.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1533003 - Split out inner-function scope linking in script compile r=jandem When compiling a script with lazy inner functions, we now know the scopes that those inner functions belong too and need to save this information on the inner function itself (as enclosingScope). This patch makes that process more explicit in JSScript initialization so we can better reason about error / OOM paths. Depends on D22319 Differential Revision: https://phabricator.services.mozilla.com/D22320
js/src/frontend/BytecodeEmitter.cpp
js/src/frontend/BytecodeEmitter.h
js/src/vm/JSScript.cpp
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -9688,20 +9688,27 @@ unsigned CGObjectList::add(ObjectBox* ob
 void CGObjectList::finish(mozilla::Span<GCPtrObject> array) {
   MOZ_ASSERT(length <= INDEX_LIMIT);
   MOZ_ASSERT(length == array.size());
 
   ObjectBox* objbox = lastbox;
   for (GCPtrObject& obj : mozilla::Reversed(array)) {
     MOZ_ASSERT(obj == nullptr);
     MOZ_ASSERT(objbox->object()->isTenured());
+    obj.init(objbox->object());
+    objbox = objbox->emitLink;
+  }
+}
+
+void CGObjectList::finishInnerFunctions() {
+  ObjectBox* objbox = lastbox;
+  while (objbox) {
     if (objbox->isFunctionBox()) {
       objbox->asFunctionBox()->finish();
     }
-    obj.init(objbox->object());
     objbox = objbox->emitLink;
   }
 }
 
 void CGScopeList::finish(mozilla::Span<GCPtrScope> array) {
   MOZ_ASSERT(length() <= INDEX_LIMIT);
   MOZ_ASSERT(length() == array.size());
 
--- a/js/src/frontend/BytecodeEmitter.h
+++ b/js/src/frontend/BytecodeEmitter.h
@@ -41,16 +41,17 @@ class CGNumberList {
 struct CGObjectList {
   uint32_t length;    /* number of emitted so far objects */
   ObjectBox* lastbox; /* last emitted object */
 
   CGObjectList() : length(0), lastbox(nullptr) {}
 
   unsigned add(ObjectBox* objbox);
   void finish(mozilla::Span<GCPtrObject> array);
+  void finishInnerFunctions();
 };
 
 struct MOZ_STACK_CLASS CGScopeList {
   Rooted<GCVector<Scope*>> vector;
 
   explicit CGScopeList(JSContext* cx) : vector(cx, GCVector<Scope*>(cx)) {}
 
   bool append(Scope* scope) { return vector.append(scope); }
--- a/js/src/vm/JSScript.cpp
+++ b/js/src/vm/JSScript.cpp
@@ -3621,16 +3621,21 @@ bool JSScript::fullyInitFromEmitter(JSCo
 
   // There shouldn't be any fallible operation after initFromFunctionBox,
   // JSFunction::hasUncompletedScript relies on the fact that the existence
   // of the pointer to JSScript means the pointed JSScript is complete.
   if (bce->sc->isFunctionBox()) {
     initFromFunctionBox(script, bce->sc->asFunctionBox());
   }
 
+  // Part of the parse result – the scope containing each inner function – must
+  // be stored in the inner function itself. Do this now that compilation is
+  // complete and can no longer fail.
+  bce->objectList.finishInnerFunctions();
+
 #ifdef JS_STRUCTURED_SPEW
   // We want this to happen after line number initialization to allow filtering
   // to work.
   script->setSpewEnabled(StructuredSpewer::enabled(script));
 #endif
 
 #ifdef DEBUG
   script->assertValidJumpTargets();