Bug 1428489 - Support JSOP_IMPLICITTHIS in Ion using VMCall. r=jandem draft
authorTed Campbell <tcampbell@mozilla.com>
Sat, 06 Jan 2018 12:09:47 -0500
changeset 722228 3fede2fc7662eba78dd4aafe60095d886653a8fa
parent 722181 0a543687fd36bc0dc4188c3d33d117b0a8174721
child 746569 cb295ef69deb50a7c48618fbd5be9d0f19920f40
push id96100
push userbmo:tcampbell@mozilla.com
push dateThu, 18 Jan 2018 17:50:47 +0000
reviewersjandem
bugs1428489
milestone59.0a1
Bug 1428489 - Support JSOP_IMPLICITTHIS in Ion using VMCall. r=jandem MozReview-Commit-ID: CJsNr6U1whs
js/src/jit/BaselineCompiler.cpp
js/src/jit/BaselineCompiler.h
js/src/jit/BytecodeAnalysis.cpp
js/src/jit/CodeGenerator.cpp
js/src/jit/CodeGenerator.h
js/src/jit/IonBuilder.cpp
js/src/jit/IonBuilder.h
js/src/jit/Lowering.cpp
js/src/jit/Lowering.h
js/src/jit/MIR.h
js/src/jit/MOpcodes.h
js/src/jit/shared/LIR-shared.h
js/src/jit/shared/LOpcodes-shared.h
--- a/js/src/jit/BaselineCompiler.cpp
+++ b/js/src/jit/BaselineCompiler.cpp
@@ -3544,17 +3544,17 @@ BaselineCompiler::emit_JSOP_OPTIMIZE_SPR
 
     masm.boxNonDouble(JSVAL_TYPE_BOOLEAN, ReturnReg, R0);
     frame.push(R0);
     return true;
 }
 
 typedef bool (*ImplicitThisFn)(JSContext*, HandleObject, HandlePropertyName,
                                MutableHandleValue);
-static const VMFunction ImplicitThisInfo =
+const VMFunction jit::ImplicitThisInfo =
     FunctionInfo<ImplicitThisFn>(ImplicitThisOperation, "ImplicitThisOperation");
 
 bool
 BaselineCompiler::emit_JSOP_IMPLICITTHIS()
 {
     frame.syncStack(0);
     masm.loadPtr(frame.addressOfEnvironmentChain(), R0.scratchReg());
 
--- a/js/src/jit/BaselineCompiler.h
+++ b/js/src/jit/BaselineCompiler.h
@@ -374,13 +374,14 @@ class BaselineCompiler : public Baseline
     void getEnvironmentCoordinateObject(Register reg);
     Address getEnvironmentCoordinateAddressFromObject(Register objReg, Register reg);
     Address getEnvironmentCoordinateAddress(Register reg);
 
     void getThisEnvironmentCallee(Register reg);
 };
 
 extern const VMFunction NewArrayCopyOnWriteInfo;
+extern const VMFunction ImplicitThisInfo;
 
 } // namespace jit
 } // namespace js
 
 #endif /* jit_BaselineCompiler_h */
--- a/js/src/jit/BytecodeAnalysis.cpp
+++ b/js/src/jit/BytecodeAnalysis.cpp
@@ -169,22 +169,24 @@ BytecodeAnalysis::init(TempAllocator& al
           case JSOP_GETALIASEDVAR:
           case JSOP_SETALIASEDVAR:
           case JSOP_LAMBDA:
           case JSOP_LAMBDA_ARROW:
           case JSOP_DEFFUN:
           case JSOP_DEFVAR:
           case JSOP_PUSHLEXICALENV:
           case JSOP_POPLEXICALENV:
+          case JSOP_IMPLICITTHIS:
             usesEnvironmentChain_ = true;
             break;
 
           case JSOP_GETGNAME:
           case JSOP_SETGNAME:
           case JSOP_STRICTSETGNAME:
+          case JSOP_GIMPLICITTHIS:
             if (script_->hasNonSyntacticScope())
                 usesEnvironmentChain_ = true;
             break;
 
           default:
             break;
         }
 
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -6577,16 +6577,24 @@ CodeGenerator::visitComputeThis(LCompute
     OutOfLineCode* ool = oolCallVM(BoxNonStrictThisInfo, lir, ArgList(value), StoreValueTo(output));
 
     masm.branchTestObject(Assembler::NotEqual, value, ool->entry());
     masm.moveValue(value, output);
     masm.bind(ool->rejoin());
 }
 
 void
+CodeGenerator::visitImplicitThis(LImplicitThis* lir)
+{
+    pushArg(ImmGCPtr(lir->mir()->name()));
+    pushArg(ToRegister(lir->env()));
+    callVM(ImplicitThisInfo, lir);
+}
+
+void
 CodeGenerator::visitArrowNewTarget(LArrowNewTarget* lir)
 {
     Register callee = ToRegister(lir->callee());
     ValueOperand output = ToOutValue(lir);
     masm.loadValue(Address(callee, FunctionExtended::offsetOfArrowNewTargetSlot()), output);
 }
 
 void
--- a/js/src/jit/CodeGenerator.h
+++ b/js/src/jit/CodeGenerator.h
@@ -227,16 +227,17 @@ class CodeGenerator final : public CodeG
     void visitCreateThis(LCreateThis* lir) override;
     void visitCreateThisWithProto(LCreateThisWithProto* lir) override;
     void visitCreateThisWithTemplate(LCreateThisWithTemplate* lir) override;
     void visitCreateArgumentsObject(LCreateArgumentsObject* lir) override;
     void visitGetArgumentsObjectArg(LGetArgumentsObjectArg* lir) override;
     void visitSetArgumentsObjectArg(LSetArgumentsObjectArg* lir) override;
     void visitReturnFromCtor(LReturnFromCtor* lir) override;
     void visitComputeThis(LComputeThis* lir) override;
+    void visitImplicitThis(LImplicitThis* lir) override;
     void visitArrayLength(LArrayLength* lir) override;
     void visitSetArrayLength(LSetArrayLength* lir) override;
     void visitGetNextEntryForIterator(LGetNextEntryForIterator* lir) override;
     void visitTypedArrayLength(LTypedArrayLength* lir) override;
     void visitTypedArrayElements(LTypedArrayElements* lir) override;
     void visitSetDisjointTypedElements(LSetDisjointTypedElements* lir) override;
     void visitTypedObjectElements(LTypedObjectElements* lir) override;
     void visitSetTypedObjectOffset(LSetTypedObjectOffset* lir) override;
--- a/js/src/jit/IonBuilder.cpp
+++ b/js/src/jit/IonBuilder.cpp
@@ -2336,19 +2336,23 @@ IonBuilder::inspectOpcode(JSOp op)
       case JSOP_DEBUGGER:
         return jsop_debugger();
 
       case JSOP_GIMPLICITTHIS:
         if (!script()->hasNonSyntacticScope()) {
             pushConstant(UndefinedValue());
             return Ok();
         }
-
-        // Just fall through to the unsupported bytecode case.
-        break;
+        // Fallthrough to IMPLICITTHIS in non-syntactic scope case
+        MOZ_FALLTHROUGH;
+      case JSOP_IMPLICITTHIS:
+      {
+        PropertyName* name = info().getAtom(pc)->asPropertyName();
+        return jsop_implicitthis(name);
+      }
 
       case JSOP_NEWTARGET:
         return jsop_newtarget();
 
       case JSOP_CHECKISOBJ:
         return jsop_checkisobj(GET_UINT8(pc));
 
       case JSOP_CHECKISCALLABLE:
@@ -2438,17 +2442,16 @@ IonBuilder::inspectOpcode(JSOp op)
       case JSOP_AWAIT:
       case JSOP_GENERATOR:
 
       // Misc
       case JSOP_DELNAME:
       case JSOP_FINALLY:
       case JSOP_GETRVAL:
       case JSOP_GOSUB:
-      case JSOP_IMPLICITTHIS:
       case JSOP_RETSUB:
       case JSOP_SETINTRINSIC:
       case JSOP_THROWMSG:
         // === !! WARNING WARNING WARNING !! ===
         // Do you really want to sacrifice performance by not implementing this
         // operation in the optimizing compiler?
         break;
 
@@ -13207,16 +13210,28 @@ IonBuilder::jsop_debugger()
     current->add(debugger);
 
     // The |debugger;| statement will always bail out to baseline if
     // cx->compartment()->isDebuggee(). Resume in-place and have baseline
     // handle the details.
     return resumeAt(debugger, pc);
 }
 
+AbortReasonOr<Ok>
+IonBuilder::jsop_implicitthis(PropertyName* name)
+{
+    MOZ_ASSERT(usesEnvironmentChain());
+
+    MImplicitThis* implicitThis = MImplicitThis::New(alloc(), current->environmentChain(), name);
+    current->add(implicitThis);
+    current->push(implicitThis);
+
+    return resumeAfter(implicitThis);
+}
+
 MInstruction*
 IonBuilder::addConvertElementsToDoubles(MDefinition* elements)
 {
     MInstruction* convert = MConvertElementsToDoubles::New(alloc(), elements);
     current->add(convert);
     return convert;
 }
 
--- a/js/src/jit/IonBuilder.h
+++ b/js/src/jit/IonBuilder.h
@@ -589,16 +589,17 @@ class IonBuilder
     AbortReasonOr<Ok> jsop_getaliasedvar(EnvironmentCoordinate ec);
     AbortReasonOr<Ok> jsop_setaliasedvar(EnvironmentCoordinate ec);
     AbortReasonOr<Ok> jsop_debugger();
     AbortReasonOr<Ok> jsop_newtarget();
     AbortReasonOr<Ok> jsop_checkisobj(uint8_t kind);
     AbortReasonOr<Ok> jsop_checkiscallable(uint8_t kind);
     AbortReasonOr<Ok> jsop_checkobjcoercible();
     AbortReasonOr<Ok> jsop_pushcallobj();
+    AbortReasonOr<Ok> jsop_implicitthis(PropertyName* name);
 
     /* Inlining. */
 
     enum InliningStatus
     {
         InliningStatus_NotInlined,
         InliningStatus_WarmUpCountTooLow,
         InliningStatus_Inlined
--- a/js/src/jit/Lowering.cpp
+++ b/js/src/jit/Lowering.cpp
@@ -445,16 +445,27 @@ LIRGenerator::visitComputeThis(MComputeT
     // have its inputs in different registers than its return value so that
     // they aren't clobbered.
     LComputeThis* lir = new(alloc()) LComputeThis(useBox(ins->input()));
     defineBox(lir, ins);
     assignSafepoint(lir, ins);
 }
 
 void
+LIRGenerator::visitImplicitThis(MImplicitThis* ins)
+{
+    MDefinition* env = ins->envChain();
+    MOZ_ASSERT(env->type() == MIRType::Object);
+
+    LImplicitThis* lir = new(alloc()) LImplicitThis(useRegisterAtStart(env));
+    defineReturn(lir, ins);
+    assignSafepoint(lir, ins);
+}
+
+void
 LIRGenerator::visitArrowNewTarget(MArrowNewTarget* ins)
 {
     MOZ_ASSERT(ins->type() == MIRType::Value);
     MOZ_ASSERT(ins->callee()->type() == MIRType::Object);
 
     LArrowNewTarget* lir = new(alloc()) LArrowNewTarget(useRegister(ins->callee()));
     defineBox(lir, ins);
 }
--- a/js/src/jit/Lowering.h
+++ b/js/src/jit/Lowering.h
@@ -99,16 +99,17 @@ class LIRGenerator : public LIRGenerator
     void visitCreateThisWithTemplate(MCreateThisWithTemplate* ins) override;
     void visitCreateThisWithProto(MCreateThisWithProto* ins) override;
     void visitCreateThis(MCreateThis* ins) override;
     void visitCreateArgumentsObject(MCreateArgumentsObject* ins) override;
     void visitGetArgumentsObjectArg(MGetArgumentsObjectArg* ins) override;
     void visitSetArgumentsObjectArg(MSetArgumentsObjectArg* ins) override;
     void visitReturnFromCtor(MReturnFromCtor* ins) override;
     void visitComputeThis(MComputeThis* ins) override;
+    void visitImplicitThis(MImplicitThis* ins) override;
     void visitCall(MCall* call) override;
     void visitApplyArgs(MApplyArgs* apply) override;
     void visitApplyArray(MApplyArray* apply) override;
     void visitBail(MBail* bail) override;
     void visitUnreachable(MUnreachable* unreachable) override;
     void visitEncodeSnapshot(MEncodeSnapshot* ins) override;
     void visitAssertFloat32(MAssertFloat32* ins) override;
     void visitAssertRecoveredOnBailout(MAssertRecoveredOnBailout* ins) override;
--- a/js/src/jit/MIR.h
+++ b/js/src/jit/MIR.h
@@ -7746,16 +7746,47 @@ class MComputeThis
 
     bool possiblyCalls() const override {
         return true;
     }
 
     // Note: don't override getAliasSet: the thisValue hook can be effectful.
 };
 
+class MImplicitThis
+  : public MUnaryInstruction,
+    public SingleObjectPolicy::Data
+{
+    CompilerPropertyName name_;
+
+    MImplicitThis(MDefinition* envChain, PropertyName* name)
+      : MUnaryInstruction(classOpcode, envChain),
+        name_(name)
+    {
+        setResultType(MIRType::Value);
+    }
+
+  public:
+    INSTRUCTION_HEADER(ImplicitThis)
+    TRIVIAL_NEW_WRAPPERS
+    NAMED_OPERANDS((0, envChain))
+
+    PropertyName* name() const {
+        return name_;
+    }
+
+    bool appendRoots(MRootList& roots) const override {
+        return roots.append(name_);
+    }
+
+    bool possiblyCalls() const override {
+        return true;
+    }
+};
+
 // Load an arrow function's |new.target| value.
 class MArrowNewTarget
   : public MUnaryInstruction,
     public SingleObjectPolicy::Data
 {
     explicit MArrowNewTarget(MDefinition* callee)
       : MUnaryInstruction(classOpcode, callee)
     {
--- a/js/src/jit/MOpcodes.h
+++ b/js/src/jit/MOpcodes.h
@@ -61,16 +61,17 @@ namespace jit {
     _(DefFun)                                                               \
     _(CreateThis)                                                           \
     _(CreateThisWithProto)                                                  \
     _(CreateThisWithTemplate)                                               \
     _(CreateArgumentsObject)                                                \
     _(GetArgumentsObjectArg)                                                \
     _(SetArgumentsObjectArg)                                                \
     _(ComputeThis)                                                          \
+    _(ImplicitThis)                                                         \
     _(Call)                                                                 \
     _(ApplyArgs)                                                            \
     _(ApplyArray)                                                           \
     _(Bail)                                                                 \
     _(Unreachable)                                                          \
     _(EncodeSnapshot)                                                       \
     _(AssertFloat32)                                                        \
     _(AssertRecoveredOnBailout)                                             \
--- a/js/src/jit/shared/LIR-shared.h
+++ b/js/src/jit/shared/LIR-shared.h
@@ -1850,16 +1850,34 @@ class LComputeThis : public LInstruction
         return getDef(0);
     }
 
     MComputeThis* mir() const {
         return mir_->toComputeThis();
     }
 };
 
+class LImplicitThis : public LCallInstructionHelper<BOX_PIECES, 1, 0>
+{
+  public:
+    LIR_HEADER(ImplicitThis)
+
+    explicit LImplicitThis(const LAllocation& env) {
+        setOperand(0, env);
+    }
+
+    const LAllocation* env() {
+        return getOperand(0);
+    }
+
+    MImplicitThis* mir() const {
+        return mir_->toImplicitThis();
+    }
+};
+
 // Writes a typed argument for a function call to the frame's argument vector.
 class LStackArgT : public LInstructionHelper<0, 1, 0>
 {
     uint32_t argslot_; // Index into frame-scope argument vector.
     MIRType type_;
 
   public:
     LIR_HEADER(StackArgT)
--- a/js/src/jit/shared/LOpcodes-shared.h
+++ b/js/src/jit/shared/LOpcodes-shared.h
@@ -100,16 +100,17 @@
     _(CreateThis)                   \
     _(CreateThisWithProto)          \
     _(CreateThisWithTemplate)       \
     _(CreateArgumentsObject)        \
     _(GetArgumentsObjectArg)        \
     _(SetArgumentsObjectArg)        \
     _(ReturnFromCtor)               \
     _(ComputeThis)                  \
+    _(ImplicitThis)                 \
     _(BitNotI)                      \
     _(BitNotV)                      \
     _(BitOpI)                       \
     _(BitOpI64)                     \
     _(BitOpV)                       \
     _(ShiftI)                       \
     _(ShiftI64)                     \
     _(SignExtendInt32)              \