Bug 1638670 - Replace BCEScriptStencil with ScriptStencil. r=mgaudet
authorTed Campbell <tcampbell@mozilla.com>
Wed, 20 May 2020 14:50:02 +0000
changeset 531254 1ab68e0e1e794a1290c4570c58735333627b96eb
parent 531253 0a89ee7a4082dffa7f2a5382871fb932bb6b3f45
child 531255 b6bd6cb99d28fa9cb1bfc379b473af5b337137f1
push id37436
push userncsoregi@mozilla.com
push dateWed, 20 May 2020 21:30:50 +0000
treeherdermozilla-central@6c10970490f3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmgaudet
bugs1638670
milestone78.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 1638670 - Replace BCEScriptStencil with ScriptStencil. r=mgaudet The BCE is no longer needed to instantiate a Stencil, so we can directly use the ScriptStencil type. Add an `intoStencil` method to the BCE to do the setup. This replaces the old `BCEScriptStencil::init` method. Differential Revision: https://phabricator.services.mozilla.com/D76023
js/src/frontend/BCEScriptStencil.cpp
js/src/frontend/BCEScriptStencil.h
js/src/frontend/BytecodeEmitter.cpp
js/src/frontend/BytecodeEmitter.h
js/src/frontend/Frontend2.cpp
js/src/frontend/FunctionEmitter.cpp
js/src/frontend/Stencil.h
js/src/frontend/moz.build
js/src/vm/JSScript.cpp
deleted file mode 100644
--- a/js/src/frontend/BCEScriptStencil.cpp
+++ /dev/null
@@ -1,54 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- * vim: set ts=8 sts=2 et sw=2 tw=80:
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "frontend/BCEScriptStencil.h"
-
-#include "frontend/AbstractScopePtr.h"  // AbstractScope
-#include "frontend/BytecodeEmitter.h"   // BytecodeEmitter
-#include "frontend/BytecodeSection.h"   // BytecodeSection, PerScriptData
-#include "vm/SharedStencil.h"
-
-using namespace js;
-using namespace js::frontend;
-
-BCEScriptStencil::BCEScriptStencil(BytecodeEmitter& bce,
-                                   UniquePtr<ImmutableScriptData> immutableData)
-    : ScriptStencil(bce.cx) {
-  init(bce, std::move(immutableData));
-}
-
-void BCEScriptStencil::init(BytecodeEmitter& bce,
-                            UniquePtr<ImmutableScriptData> immutableData) {
-  immutableFlags = bce.sc->immutableFlags();
-
-  MOZ_ASSERT(bce.outermostScope().hasOnChain(ScopeKind::NonSyntactic) ==
-             immutableFlags.hasFlag(ImmutableFlags::HasNonSyntacticScope));
-
-  gcThings = bce.perScriptData().gcThingList().stealGCThings();
-
-  // Hand over the ImmutableScriptData instance generated by BCE.
-  immutableScriptData = std::move(immutableData);
-
-  // Update flags specific to functions.
-  if (isFunction()) {
-    FunctionBox* funbox = bce.sc->asFunctionBox();
-    functionIndex.emplace(funbox->index());
-    fieldInitializers = funbox->fieldInitializers;
-
-    // Set flags that don't have direct flag representation within the
-    // FunctionBox.
-    immutableFlags.setFlag(ImmutableFlags::HasMappedArgsObj,
-                           funbox->hasMappedArgsObj());
-
-    // While IsLikelyConstructorWrapper is required to be the same between
-    // syntax and normal parsing, BinAST cannot ensure this. Work around this by
-    // using the existing value if this is delazification.
-    if (bce.emitterMode != BytecodeEmitter::LazyFunction) {
-      immutableFlags.setFlag(ImmutableFlags::IsLikelyConstructorWrapper,
-                             funbox->isLikelyConstructorWrapper());
-    }
-  } /* isFunctionBox */
-}
deleted file mode 100644
--- a/js/src/frontend/BCEScriptStencil.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- * vim: set ts=8 sts=2 et sw=2 tw=80:
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef frontend_BCEScriptStencil_h
-#define frontend_BCEScriptStencil_h
-
-#include "mozilla/Span.h"  // mozilla::Span
-
-#include "frontend/Stencil.h"  // ScriptStencil
-#include "gc/Barrier.h"        // GCPtrAtom
-#include "js/HeapAPI.h"        // JS::GCCellPtr
-#include "js/TypeDecls.h"      // JSContext
-#include "js/UniquePtr.h"      // js::UniquePtr
-#include "vm/SharedStencil.h"  // js::ImmutableScriptData
-
-namespace js::frontend {
-
-struct BytecodeEmitter;
-
-class BCEScriptStencil : public ScriptStencil {
-  void init(BytecodeEmitter& bce, UniquePtr<ImmutableScriptData> immutableData);
-
- public:
-  BCEScriptStencil(BytecodeEmitter& bce,
-                   UniquePtr<ImmutableScriptData> immutableData);
-};
-
-} /* namespace js::frontend */
-
-#endif /* frontend_BCEScriptStencil_h */
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -22,17 +22,16 @@
 
 #include <algorithm>
 #include <string.h>
 
 #include "jstypes.h"  // JS_BIT
 
 #include "ds/Nestable.h"  // Nestable
 #include "frontend/AbstractScopePtr.h"
-#include "frontend/BCEScriptStencil.h"           // BCEScriptStencil
 #include "frontend/BytecodeControlStructures.h"  // NestableControl, BreakableControl, LabelControl, LoopControl, TryFinallyControl
 #include "frontend/CallOrNewEmitter.h"           // CallOrNewEmitter
 #include "frontend/CForEmitter.h"                // CForEmitter
 #include "frontend/DefaultEmitter.h"             // DefaultEmitter
 #include "frontend/DoWhileEmitter.h"             // DoWhileEmitter
 #include "frontend/ElemOpEmitter.h"              // ElemOpEmitter
 #include "frontend/EmitterScope.h"               // EmitterScope
 #include "frontend/ExpressionStatementEmitter.h"  // ExpressionStatementEmitter
@@ -2422,25 +2421,22 @@ bool BytecodeEmitter::emitScript(ParseNo
   if (!emitterScope.leave(this)) {
     return false;
   }
 
   if (!NameFunctions(cx, body)) {
     return false;
   }
 
-  js::UniquePtr<ImmutableScriptData> immutableScriptData =
-      createImmutableScriptData(cx);
-  if (!immutableScriptData) {
-    return false;
-  }
-
   // Create a Stencil and convert it into a JSScript.
   SourceExtent extent = sc->getScriptExtent();
-  BCEScriptStencil stencil(*this, std::move(immutableScriptData));
+  ScriptStencil stencil(cx);
+  if (!intoScriptStencil(&stencil)) {
+    return false;
+  }
   outputScript = stencil.intoScript(cx, compilationInfo, extent);
 
   return !!outputScript;
 }
 
 js::UniquePtr<ImmutableScriptData> BytecodeEmitter::createImmutableScriptData(
     JSContext* cx) {
   uint32_t nslots;
@@ -10759,8 +10755,51 @@ bool BytecodeEmitter::newSrcNoteOperand(
     if (!AllocSrcNote(cx, notes, size, &index)) {
       return nullptr;
     }
     return &notes[index];
   };
 
   return SrcNoteWriter::writeOperand(operand, allocator);
 }
+
+bool BytecodeEmitter::intoScriptStencil(ScriptStencil* stencil) {
+  using ImmutableFlags = ImmutableScriptFlagsEnum;
+
+  js::UniquePtr<ImmutableScriptData> immutableScriptData =
+      createImmutableScriptData(cx);
+  if (!immutableScriptData) {
+    return false;
+  }
+
+  stencil->immutableFlags = sc->immutableFlags();
+
+  MOZ_ASSERT(outermostScope().hasOnChain(ScopeKind::NonSyntactic) ==
+             sc->hasNonSyntacticScope());
+
+  stencil->gcThings = perScriptData().gcThingList().stealGCThings();
+
+  // Hand over the ImmutableScriptData instance generated by BCE.
+  stencil->immutableScriptData = std::move(immutableScriptData);
+
+  // Update flags specific to functions.
+  if (sc->isFunctionBox()) {
+    FunctionBox* funbox = sc->asFunctionBox();
+    stencil->functionIndex.emplace(funbox->index());
+    stencil->fieldInitializers = funbox->fieldInitializers;
+
+    // Set flags that don't have direct flag representation within the
+    // FunctionBox.
+    stencil->immutableFlags.setFlag(ImmutableFlags::HasMappedArgsObj,
+                                    funbox->hasMappedArgsObj());
+
+    // While IsLikelyConstructorWrapper is required to be the same between
+    // syntax and normal parsing, BinAST cannot ensure this. Work around this by
+    // using the existing value if this is delazification.
+    if (emitterMode != BytecodeEmitter::LazyFunction) {
+      stencil->immutableFlags.setFlag(
+          ImmutableFlags::IsLikelyConstructorWrapper,
+          funbox->isLikelyConstructorWrapper());
+    }
+  } /* isFunctionBox */
+
+  return true;
+}
--- a/js/src/frontend/BytecodeEmitter.h
+++ b/js/src/frontend/BytecodeEmitter.h
@@ -61,16 +61,17 @@ class ClassEmitter;
 class ElemOpEmitter;
 class EmitterScope;
 class NestableControl;
 class PropertyEmitter;
 class PropOpEmitter;
 class OptionalEmitter;
 class TDZCheckCache;
 class TryEmitter;
+class ScriptStencil;
 
 enum class ValueIsOnStack { Yes, No };
 
 struct MOZ_STACK_CLASS BytecodeEmitter {
   // Context shared between parsing and bytecode generation.
   SharedContext* const sc = nullptr;
 
   JSContext* const cx = nullptr;
@@ -304,16 +305,19 @@ struct MOZ_STACK_CLASS BytecodeEmitter {
       scriptStartOffset = mozilla::Some(pos);
     }
   }
 
   void reportError(ParseNode* pn, unsigned errorNumber, ...);
   void reportError(const mozilla::Maybe<uint32_t>& maybeOffset,
                    unsigned errorNumber, ...);
 
+  // Fill in a ScriptStencil using this BCE data.
+  bool intoScriptStencil(ScriptStencil* stencil);
+
   // If pn contains a useful expression, return true with *answer set to true.
   // If pn contains a useless expression, return true with *answer set to
   // false. Return false on error.
   //
   // The caller should initialize *answer to false and invoke this function on
   // an expression statement or similar subtree to decide whether the tree
   // could produce code that has any side effects.  For an expression
   // statement, we define useless code as code with no side effects, because
--- a/js/src/frontend/Frontend2.cpp
+++ b/js/src/frontend/Frontend2.cpp
@@ -65,16 +65,18 @@ class SmooshScriptStencil : public Scrip
   SmooshScriptStencil(const SmooshResult& result,
                       CompilationInfo& compilationInfo)
       : ScriptStencil(compilationInfo.cx),
         result_(result),
         compilationInfo_(compilationInfo) {}
 
   MOZ_MUST_USE bool init(JSContext* cx,
                          UniquePtr<ImmutableScriptData> immutableData) {
+    using ImmutableFlags = js::ImmutableScriptFlagsEnum;
+
     // A global script is a top-level context.
     bool isTopLevelContext = true;
     const JS::ReadOnlyCompileOptions& options = compilationInfo_.options;
 
     // The "input" flags are derived from options.
     immutableFlags.setFlag(ImmutableFlags::IsForEval, result_.is_for_eval);
     immutableFlags.setFlag(ImmutableFlags::IsModule, result_.is_module);
     immutableFlags.setFlag(ImmutableFlags::IsFunction, false);
--- a/js/src/frontend/FunctionEmitter.cpp
+++ b/js/src/frontend/FunctionEmitter.cpp
@@ -4,17 +4,16 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "frontend/FunctionEmitter.h"
 
 #include "mozilla/Assertions.h"  // MOZ_ASSERT
 
 #include "builtin/ModuleObject.h"          // ModuleObject
-#include "frontend/BCEScriptStencil.h"     // BCEScriptStencil
 #include "frontend/BytecodeEmitter.h"      // BytecodeEmitter
 #include "frontend/FunctionSyntaxKind.h"   // FunctionSyntaxKind
 #include "frontend/ModuleSharedContext.h"  // ModuleSharedContext
 #include "frontend/NameAnalysisTypes.h"    // NameLocation
 #include "frontend/NameOpEmitter.h"        // NameOpEmitter
 #include "frontend/ParseContext.h"         // BindingIter
 #include "frontend/PropOpEmitter.h"        // PropOpEmitter
 #include "frontend/SharedContext.h"        // SharedContext
@@ -701,36 +700,31 @@ bool FunctionScriptEmitter::emitEndBody(
 }
 
 bool FunctionScriptEmitter::initScript() {
   MOZ_ASSERT(state_ == State::EndBody);
   MOZ_ASSERT(!bce_->outputScript);
 
   JSContext* cx = bce_->cx;
 
-  js::UniquePtr<ImmutableScriptData> immutableScriptData =
-      bce_->createImmutableScriptData(cx);
-  if (!immutableScriptData) {
+  ScriptStencil stencil(cx);
+  if (!bce_->intoScriptStencil(&stencil)) {
     return false;
   }
 
   if (bce_->emitterMode == BytecodeEmitter::LazyFunction) {
-    BCEScriptStencil stencil(*bce_, std::move(immutableScriptData));
     RootedScript script(cx, JSScript::CastFromLazy(bce_->compilationInfo.lazy));
-
     if (!JSScript::fullyInitFromStencil(cx, bce_->compilationInfo, script,
                                         stencil)) {
       return false;
     }
 
     bce_->outputScript = script;
   } else {
     SourceExtent extent = funbox_->getScriptExtent();
-    BCEScriptStencil stencil(*bce_, std::move(immutableScriptData));
-
     RootedScript script(cx,
                         stencil.intoScript(cx, bce_->compilationInfo, extent));
     if (!script) {
       return false;
     }
 
     bce_->outputScript = script;
   }
--- a/js/src/frontend/Stencil.h
+++ b/js/src/frontend/Stencil.h
@@ -360,24 +360,18 @@ class ScriptStencilBase {
   // This traces any JSAtoms in the gcThings array. This will be removed once
   // atoms are deferred from parsing.
   void trace(JSTracer* trc);
 };
 
 // Data used to instantiate the non-lazy script.
 class ScriptStencil : public ScriptStencilBase {
  public:
-  using ImmutableFlags = ImmutableScriptFlagsEnum;
-
   explicit ScriptStencil(JSContext* cx) : ScriptStencilBase(cx) {}
 
-  bool isFunction() const {
-    return immutableFlags.hasFlag(ImmutableFlags::IsFunction);
-  }
-
   // Allocate a JSScript and initialize it with bytecode. This consumes
   // allocations within this stencil.
   JSScript* intoScript(JSContext* cx, CompilationInfo& compilationInfo,
                        SourceExtent extent);
 };
 
 } /* namespace js::frontend */
 
--- a/js/src/frontend/moz.build
+++ b/js/src/frontend/moz.build
@@ -25,17 +25,16 @@ if CONFIG['JS_ENABLE_SMOOSH']:
                   script='/build/RunCbindgen.py',
                   entry_point='generate_with_same_crate',
                   inputs=[
                       '/js/src/frontend/smoosh',
                   ])
 
 UNIFIED_SOURCES += [
     'AbstractScopePtr.cpp',
-    'BCEScriptStencil.cpp',
     'BytecodeCompiler.cpp',
     'BytecodeControlStructures.cpp',
     'BytecodeEmitter.cpp',
     'BytecodeSection.cpp',
     'CallOrNewEmitter.cpp',
     'CForEmitter.cpp',
     'DefaultEmitter.cpp',
     'DoWhileEmitter.cpp',
--- a/js/src/vm/JSScript.cpp
+++ b/js/src/vm/JSScript.cpp
@@ -4256,17 +4256,17 @@ bool JSScript::fullyInitFromStencil(JSCo
   if (!script->shareScriptData(cx)) {
     return false;
   }
 
   // NOTE: JSScript is now constructed and should be linked in.
   rollbackGuard.release();
 
   // Link JSFunction to this JSScript.
-  if (stencil.isFunction()) {
+  if (stencil.functionIndex) {
     JSFunction* fun =
         compilationInfo.funcData[*stencil.functionIndex].as<JSFunction*>();
     if (fun->isIncomplete()) {
       fun->initScript(script);
     } else {
       // We are delazifying in-place.
       MOZ_ASSERT(fun->baseScript() == script);
     }