Bug 1533003 - Cleanup JSScript::fullyInitFromEmitter error handling r=jandem
authorTed Campbell <tcampbell@mozilla.com>
Wed, 06 Mar 2019 17:59:06 +0000
changeset 520612 ce7559041ffa76ffc14a77b6f6e7d730c9fa544d
parent 520611 a8cbb44ae49bb90f786bce6ee5f3589ee5e13e18
child 520613 a826392776b54edaf2bbbac81f2183db854035d1
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 - Cleanup JSScript::fullyInitFromEmitter error handling r=jandem Use an ExitScope similar to to XDRScript for more consistency. Depends on D22316 Differential Revision: https://phabricator.services.mozilla.com/D22317
js/src/vm/JSScript.cpp
--- a/js/src/vm/JSScript.cpp
+++ b/js/src/vm/JSScript.cpp
@@ -3525,16 +3525,24 @@ void JSScript::initFromFunctionBox(Handl
 
   script->setFlag(ImmutableFlags::HasInnerFunctions,
                   funbox->hasInnerFunctions());
 }
 
 /* static */
 bool JSScript::fullyInitFromEmitter(JSContext* cx, HandleScript script,
                                     frontend::BytecodeEmitter* bce) {
+  MOZ_ASSERT(!script->data_, "JSScript already initialized");
+
+  // If initialization fails, we must call JSScript::freeScriptData in order to
+  // neuter the script. Various things that iterate raw scripts in a GC arena
+  // use the presense of this data to detect if initialization is complete.
+  auto scriptDataGuard =
+      mozilla::MakeScopeExit([&] { script->freeScriptData(); });
+
   /* The counts of indexed things must be checked during code generation. */
   MOZ_ASSERT(bce->atomIndices->count() <= INDEX_LIMIT);
   MOZ_ASSERT(bce->objectList.length <= INDEX_LIMIT);
 
   uint64_t nslots =
       bce->maxFixedSlots + static_cast<uint64_t>(bce->maxStackDepth);
   if (nslots > UINT32_MAX) {
     bce->reportError(nullptr, JSMSG_NEED_DIET, js_script_str);
@@ -3557,21 +3565,16 @@ bool JSScript::fullyInitFromEmitter(JSCo
   // The + 1 is to account for the final SN_MAKE_TERMINATOR that is appended
   // when the notes are copied to their final destination by copySrcNotes.
   uint32_t nsrcnotes = bce->notes().length() + 1;
   uint32_t codeLength = bce->code().length();
   if (!script->createSharedScriptData(cx, codeLength, nsrcnotes, natoms)) {
     return false;
   }
 
-  // Any fallible operation after JSScript::createSharedScriptData should
-  // reset JSScript.scriptData_, in order to treat this script as
-  // uncompleted, in JSScript::isUncompleted.  JSScript::shareScriptData
-  // resets it before returning false.
-
   jsbytecode* code = script->code();
   PodCopy<jsbytecode>(code, bce->code().begin(), codeLength);
   bce->copySrcNotes((jssrcnote*)(code + script->length()), nsrcnotes);
   InitAtomMap(*bce->atomIndices, script->atoms());
 
   if (!script->shareScriptData(cx)) {
     return false;
   }
@@ -3627,16 +3630,17 @@ bool JSScript::fullyInitFromEmitter(JSCo
   // to work.
   script->setSpewEnabled(StructuredSpewer::enabled(script));
 #endif
 
 #ifdef DEBUG
   script->assertValidJumpTargets();
 #endif
 
+  scriptDataGuard.release();
   return true;
 }
 
 #ifdef DEBUG
 void JSScript::assertValidJumpTargets() const {
   BytecodeLocation mainLoc = mainLocation();
   BytecodeLocation endLoc = endLocation();
   AllBytecodesIterable iter(this);