Bug 1562102 - Use more Handle in BytecodeEmitter methods and helper classes. r=jorendorff,jonco a=RyanVM
authorTooru Fujisawa <arai_a@mac.com>
Wed, 31 Jul 2019 13:43:50 +0000
changeset 544868 22a134bc52b0639d91d586ccb40d72fd6e293649
parent 544867 e87edf3a81c691599bbb5d75175fef5f9ea8a73c
child 544869 7baf87d8c07f35f72587c81663e49ccc35887b93
push id2131
push userffxbld-merge
push dateMon, 26 Aug 2019 18:30:20 +0000
treeherdermozilla-release@b19ffb3ca153 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjorendorff, jonco, RyanVM
bugs1562102
milestone69.0
Bug 1562102 - Use more Handle in BytecodeEmitter methods and helper classes. r=jorendorff,jonco a=RyanVM Depends on D36695 Differential Revision: https://phabricator.services.mozilla.com/D36696
js/src/frontend/BytecodeEmitter.cpp
js/src/frontend/BytecodeEmitter.h
js/src/frontend/CallOrNewEmitter.cpp
js/src/frontend/CallOrNewEmitter.h
js/src/frontend/NameOpEmitter.cpp
js/src/frontend/NameOpEmitter.h
js/src/frontend/ObjectEmitter.cpp
js/src/gc/Barrier.h
--- a/js/src/frontend/BytecodeEmitter.cpp
+++ b/js/src/frontend/BytecodeEmitter.cpp
@@ -1741,28 +1741,29 @@ bool BytecodeEmitter::emitFinishIterator
     return false;
   }
   if (!emitIndex32(JSOP_INITPROP, done_id)) {
     return false;
   }
   return true;
 }
 
-bool BytecodeEmitter::emitGetNameAtLocation(JSAtom* name,
+bool BytecodeEmitter::emitGetNameAtLocation(Handle<JSAtom*> name,
                                             const NameLocation& loc) {
   NameOpEmitter noe(this, name, loc, NameOpEmitter::Kind::Get);
   if (!noe.emitGet()) {
     return false;
   }
 
   return true;
 }
 
 bool BytecodeEmitter::emitGetName(NameNode* name) {
-  return emitGetName(name->name());
+  RootedAtom nameAtom(cx, name->name());
+  return emitGetName(nameAtom);
 }
 
 bool BytecodeEmitter::emitTDZCheckIfNeeded(HandleAtom name,
                                            const NameLocation& loc) {
   // Dynamic accesses have TDZ checks built into their VM code and should
   // never emit explicit TDZ checks.
   MOZ_ASSERT(loc.hasKnownSlot());
   MOZ_ASSERT(loc.isLexical());
@@ -1880,17 +1881,18 @@ bool BytecodeEmitter::emitPropIncDec(Una
   return true;
 }
 
 bool BytecodeEmitter::emitNameIncDec(UnaryNode* incDec) {
   MOZ_ASSERT(incDec->kid()->isKind(ParseNodeKind::Name));
 
   ParseNodeKind kind = incDec->getKind();
   NameNode* name = &incDec->kid()->as<NameNode>();
-  NameOpEmitter noe(this, name->atom(),
+  RootedAtom nameAtom(cx, name->atom());
+  NameOpEmitter noe(this, nameAtom,
                     kind == ParseNodeKind::PostIncrementExpr
                         ? NameOpEmitter::Kind::PostIncrement
                         : kind == ParseNodeKind::PreIncrementExpr
                               ? NameOpEmitter::Kind::PreIncrement
                               : kind == ParseNodeKind::PostDecrementExpr
                                     ? NameOpEmitter::Kind::PostDecrement
                                     : NameOpEmitter::Kind::PreDecrement);
   if (!noe.emitIncDec()) {
@@ -4011,17 +4013,18 @@ bool BytecodeEmitter::emitSingleDeclarat
                                             ParseNode* initializer) {
   MOZ_ASSERT(decl->isKind(ParseNodeKind::Name));
 
   // Nothing to do for initializer-less 'var' declarations, as there's no TDZ.
   if (!initializer && declList->isKind(ParseNodeKind::VarStmt)) {
     return true;
   }
 
-  NameOpEmitter noe(this, decl->name(), NameOpEmitter::Kind::Initialize);
+  RootedAtom nameAtom(cx, decl->name());
+  NameOpEmitter noe(this, nameAtom, NameOpEmitter::Kind::Initialize);
   if (!noe.prepareForRhs()) {
     //              [stack] ENV?
     return false;
   }
   if (!initializer) {
     // Lexical declarations are initialized to undefined without an
     // initializer.
     MOZ_ASSERT(declList->isKind(ParseNodeKind::LetDecl),
@@ -5318,17 +5321,18 @@ bool BytecodeEmitter::emitInitializeForI
              target->isKind(ParseNodeKind::InitExpr)) {
     BinaryNode* assignNode = &target->as<BinaryNode>();
     if (assignNode->left()->is<NameNode>()) {
       nameNode = &assignNode->left()->as<NameNode>();
     }
   }
 
   if (nameNode) {
-    NameOpEmitter noe(this, nameNode->name(), NameOpEmitter::Kind::Initialize);
+    RootedAtom nameAtom(cx, nameNode->name());
+    NameOpEmitter noe(this, nameAtom, NameOpEmitter::Kind::Initialize);
     if (!noe.prepareForRhs()) {
       return false;
     }
     if (noe.emittedBindOp()) {
       // Per-iteration initialization in for-in/of loops computes the
       // iteration value *before* initializing.  Thus the initializing
       // value may be buried under a bind-specific value on the stack.
       // Swap it to the top of the stack.
@@ -5463,18 +5467,18 @@ bool BytecodeEmitter::emitForIn(ForNode*
         MOZ_ASSERT(
             forInTarget->isKind(ParseNodeKind::VarStmt),
             "for-in initializers are only permitted for |var| declarations");
 
         if (!updateSourceCoordNotes(decl->pn_pos.begin)) {
           return false;
         }
 
-        NameOpEmitter noe(this, nameNode->name(),
-                          NameOpEmitter::Kind::Initialize);
+        RootedAtom nameAtom(cx, nameNode->name());
+        NameOpEmitter noe(this, nameAtom, NameOpEmitter::Kind::Initialize);
         if (!noe.prepareForRhs()) {
           return false;
         }
         if (!emitInitializer(initializer, nameNode)) {
           return false;
         }
         if (!noe.emitAssignment()) {
           return false;
@@ -7208,22 +7212,24 @@ bool BytecodeEmitter::isRestParameter(Pa
   }
 
   return false;
 }
 
 bool BytecodeEmitter::emitCalleeAndThis(ParseNode* callee, ParseNode* call,
                                         CallOrNewEmitter& cone) {
   switch (callee->getKind()) {
-    case ParseNodeKind::Name:
-      if (!cone.emitNameCallee(callee->as<NameNode>().name())) {
+    case ParseNodeKind::Name: {
+      RootedAtom nameAtom(cx, callee->as<NameNode>().name());
+      if (!cone.emitNameCallee(nameAtom)) {
         //          [stack] CALLEE THIS
         return false;
       }
       break;
+    }
     case ParseNodeKind::DotExpr: {
       MOZ_ASSERT(emitterMode != BytecodeEmitter::SelfHosting);
       PropertyAccess* prop = &callee->as<PropertyAccess>();
       bool isSuper = prop->isSuper();
 
       PropOpEmitter& poe = cone.prepareForPropCallee(isSuper);
       if (!poe.prepareForObj()) {
         return false;
@@ -8033,17 +8039,17 @@ bool BytecodeEmitter::emitCreateFieldKey
       }
     }
   }
 
   if (numFieldKeys == 0) {
     return true;
   }
 
-  NameOpEmitter noe(this, cx->names().dotFieldKeys,
+  NameOpEmitter noe(this, cx->names().dotFieldKeys.toHandle(),
                     NameOpEmitter::Kind::Initialize);
   if (!noe.prepareForRhs()) {
     return false;
   }
 
   if (!emitUint32Operand(JSOP_NEWARRAY, numFieldKeys)) {
     //              [stack] ARRAY
     return false;
@@ -8646,20 +8652,21 @@ bool BytecodeEmitter::emitInitializeFunc
       //            [stack]
       return false;
     }
   }
   return true;
 }
 
 bool BytecodeEmitter::emitLexicalInitialization(NameNode* name) {
-  return emitLexicalInitialization(name->name());
-}
-
-bool BytecodeEmitter::emitLexicalInitialization(JSAtom* name) {
+  RootedAtom nameAtom(cx, name->name());
+  return emitLexicalInitialization(nameAtom);
+}
+
+bool BytecodeEmitter::emitLexicalInitialization(Handle<JSAtom*> name) {
   NameOpEmitter noe(this, name, NameOpEmitter::Kind::Initialize);
   if (!noe.prepareForRhs()) {
     return false;
   }
 
   // The caller has pushed the RHS to the top of the stack. Assert that the
   // name is lexical and no BIND[G]NAME ops were emitted.
   MOZ_ASSERT(noe.loc().isLexical());
--- a/js/src/frontend/BytecodeEmitter.h
+++ b/js/src/frontend/BytecodeEmitter.h
@@ -514,19 +514,26 @@ struct MOZ_STACK_CLASS BytecodeEmitter {
   // instead be emitted using EmitVarOp. In special cases, when the caller
   // definitely knows that a given local slot is unaliased, this function may be
   // used as a non-asserting version of emitUint16Operand.
   MOZ_MUST_USE bool emitLocalOp(JSOp op, uint32_t slot);
 
   MOZ_MUST_USE bool emitArgOp(JSOp op, uint16_t slot);
   MOZ_MUST_USE bool emitEnvCoordOp(JSOp op, EnvironmentCoordinate ec);
 
-  MOZ_MUST_USE bool emitGetNameAtLocation(JSAtom* name,
+  MOZ_MUST_USE bool emitGetNameAtLocation(Handle<JSAtom*> name,
                                           const NameLocation& loc);
-  MOZ_MUST_USE bool emitGetName(JSAtom* name) {
+  MOZ_MUST_USE bool emitGetNameAtLocation(ImmutablePropertyNamePtr name,
+                                          const NameLocation& loc) {
+    return emitGetNameAtLocation(name.toHandle(), loc);
+  }
+  MOZ_MUST_USE bool emitGetName(Handle<JSAtom*> name) {
+    return emitGetNameAtLocation(name, lookupName(name));
+  }
+  MOZ_MUST_USE bool emitGetName(ImmutablePropertyNamePtr name) {
     return emitGetNameAtLocation(name, lookupName(name));
   }
   MOZ_MUST_USE bool emitGetName(NameNode* name);
 
   MOZ_MUST_USE bool emitTDZCheckIfNeeded(HandleAtom name,
                                          const NameLocation& loc);
 
   MOZ_MUST_USE bool emitNameIncDec(UnaryNode* incDec);
@@ -740,17 +747,17 @@ struct MOZ_STACK_CLASS BytecodeEmitter {
   MOZ_MUST_USE bool emitInitializeForInOrOfTarget(TernaryNode* forHead);
 
   MOZ_MUST_USE bool emitBreak(PropertyName* label);
   MOZ_MUST_USE bool emitContinue(PropertyName* label);
 
   MOZ_MUST_USE bool emitFunctionFormalParameters(ListNode* paramsBody);
   MOZ_MUST_USE bool emitInitializeFunctionSpecialNames();
   MOZ_MUST_USE bool emitLexicalInitialization(NameNode* name);
-  MOZ_MUST_USE bool emitLexicalInitialization(JSAtom* name);
+  MOZ_MUST_USE bool emitLexicalInitialization(Handle<JSAtom*> name);
 
   // Emit bytecode for the spread operator.
   //
   // emitSpread expects the current index (I) of the array, the array itself
   // and the iterator to be on the stack in that order (iterator on the bottom).
   // It will pop the iterator and I, then iterate over the iterator by calling
   // |.next()| and put the results into the I-th element of array with
   // incrementing I, then push the result I (it will be original I +
--- a/js/src/frontend/CallOrNewEmitter.cpp
+++ b/js/src/frontend/CallOrNewEmitter.cpp
@@ -33,17 +33,17 @@ CallOrNewEmitter::CallOrNewEmitter(Bytec
     : bce_(bce), op_(op), argumentsKind_(argumentsKind) {
   if (op_ == JSOP_CALL && valueUsage == ValueUsage::IgnoreValue) {
     op_ = JSOP_CALL_IGNORES_RV;
   }
 
   MOZ_ASSERT(isCall() || isNew() || isSuperCall());
 }
 
-bool CallOrNewEmitter::emitNameCallee(JSAtom* name) {
+bool CallOrNewEmitter::emitNameCallee(Handle<JSAtom*> name) {
   MOZ_ASSERT(state_ == State::Start);
 
   NameOpEmitter noe(
       bce_, name,
       isCall() ? NameOpEmitter::Kind::Call : NameOpEmitter::Kind::Get);
   if (!noe.emitGet()) {
     //              [stack] CALLEE THIS
     return false;
--- a/js/src/frontend/CallOrNewEmitter.h
+++ b/js/src/frontend/CallOrNewEmitter.h
@@ -285,17 +285,17 @@ class MOZ_STACK_CLASS CallOrNewEmitter {
 
   MOZ_MUST_USE bool isSpread() const { return JOF_OPTYPE(op_) == JOF_BYTE; }
 
   MOZ_MUST_USE bool isSingleSpreadRest() const {
     return argumentsKind_ == ArgumentsKind::SingleSpreadRest;
   }
 
  public:
-  MOZ_MUST_USE bool emitNameCallee(JSAtom* name);
+  MOZ_MUST_USE bool emitNameCallee(Handle<JSAtom*> name);
   MOZ_MUST_USE PropOpEmitter& prepareForPropCallee(bool isSuperProp);
   MOZ_MUST_USE ElemOpEmitter& prepareForElemCallee(bool isSuperElem);
   MOZ_MUST_USE bool prepareForFunctionCallee();
   MOZ_MUST_USE bool emitSuperCallee();
   MOZ_MUST_USE bool prepareForOtherCallee();
 
   MOZ_MUST_USE bool emitThis();
 
--- a/js/src/frontend/NameOpEmitter.cpp
+++ b/js/src/frontend/NameOpEmitter.cpp
@@ -11,25 +11,23 @@
 #include "frontend/TDZCheckCache.h"
 #include "vm/Opcodes.h"
 #include "vm/Scope.h"
 #include "vm/StringType.h"
 
 using namespace js;
 using namespace js::frontend;
 
-NameOpEmitter::NameOpEmitter(BytecodeEmitter* bce, JSAtom* name, Kind kind)
-    : bce_(bce),
-      kind_(kind),
-      name_(bce_->cx, name),
-      loc_(bce_->lookupName(name_)) {}
+NameOpEmitter::NameOpEmitter(BytecodeEmitter* bce, Handle<JSAtom*> name,
+                             Kind kind)
+    : bce_(bce), kind_(kind), name_(name), loc_(bce_->lookupName(name_)) {}
 
-NameOpEmitter::NameOpEmitter(BytecodeEmitter* bce, JSAtom* name,
+NameOpEmitter::NameOpEmitter(BytecodeEmitter* bce, Handle<JSAtom*> name,
                              const NameLocation& loc, Kind kind)
-    : bce_(bce), kind_(kind), name_(bce_->cx, name), loc_(loc) {}
+    : bce_(bce), kind_(kind), name_(name), loc_(loc) {}
 
 bool NameOpEmitter::emitGet() {
   MOZ_ASSERT(state_ == State::Start);
 
   switch (loc_.kind()) {
     case NameLocation::Kind::Dynamic:
       if (!bce_->emitAtomOp(name_, JSOP_GETNAME)) {
         //          [stack] VAL
--- a/js/src/frontend/NameOpEmitter.h
+++ b/js/src/frontend/NameOpEmitter.h
@@ -74,17 +74,17 @@ class MOZ_STACK_CLASS NameOpEmitter {
 
  private:
   BytecodeEmitter* bce_;
 
   Kind kind_;
 
   bool emittedBindOp_ = false;
 
-  RootedAtom name_;
+  Handle<JSAtom*> name_;
 
   uint32_t atomIndex_;
 
   NameLocation loc_;
 
 #ifdef DEBUG
   // The state of this emitter.
   //
@@ -127,19 +127,19 @@ class MOZ_STACK_CLASS NameOpEmitter {
 
     // After calling emitAssignment.
     Assignment,
   };
   State state_ = State::Start;
 #endif
 
  public:
-  NameOpEmitter(BytecodeEmitter* bce, JSAtom* name, Kind kind);
-  NameOpEmitter(BytecodeEmitter* bce, JSAtom* name, const NameLocation& loc,
-                Kind kind);
+  NameOpEmitter(BytecodeEmitter* bce, Handle<JSAtom*> name, Kind kind);
+  NameOpEmitter(BytecodeEmitter* bce, Handle<JSAtom*> name,
+                const NameLocation& loc, Kind kind);
 
  private:
   MOZ_MUST_USE bool isCall() const { return kind_ == Kind::Call; }
 
   MOZ_MUST_USE bool isSimpleAssignment() const {
     return kind_ == Kind::SimpleAssignment;
   }
 
--- a/js/src/frontend/ObjectEmitter.cpp
+++ b/js/src/frontend/ObjectEmitter.cpp
@@ -756,17 +756,18 @@ bool ClassEmitter::initProtoAndCtor() {
 }
 
 bool ClassEmitter::prepareForFieldInitializers(size_t numFields) {
   MOZ_ASSERT(classState_ == ClassState::Class);
 
   // .initializers is a variable that stores an array of lambdas containing
   // code (the initializer) for each field. Upon an object's construction,
   // these lambdas will be called, defining the values.
-  initializersAssignment_.emplace(bce_, bce_->cx->names().dotInitializers,
+  initializersAssignment_.emplace(bce_,
+                                  bce_->cx->names().dotInitializers.toHandle(),
                                   NameOpEmitter::Kind::Initialize);
   if (!initializersAssignment_->prepareForRhs()) {
     return false;
   }
 
   if (!bce_->emitUint32Operand(JSOP_NEWARRAY, numFields)) {
     //              [stack] HOMEOBJ HERITAGE? ARRAY
     return false;
--- a/js/src/gc/Barrier.h
+++ b/js/src/gc/Barrier.h
@@ -846,17 +846,23 @@ static inline void BarrieredSetPair(Zone
 template <typename T>
 class ImmutableTenuredPtr {
   T value;
 
  public:
   operator T() const { return value; }
   T operator->() const { return value; }
 
-  operator Handle<T>() const { return Handle<T>::fromMarkedLocation(&value); }
+  // `ImmutableTenuredPtr<T>` is implicitly convertible to `Handle<T>`.
+  //
+  // In case you need to convert to `Handle<U>` where `U` is base class of `T`,
+  // convert this to `Handle<T>` by `toHandle()` and then use implicit
+  // conversion from `Handle<T>` to `Handle<U>`.
+  operator Handle<T>() const { return toHandle(); }
+  Handle<T> toHandle() const { return Handle<T>::fromMarkedLocation(&value); }
 
   void init(T ptr) {
     MOZ_ASSERT(ptr->isTenured());
     AssertTargetIsNotGray(ptr);
     value = ptr;
   }
 
   T get() const { return value; }