Bug 1428489 - Support JSOP_IMPLICITTHIS in Ion using VMCall. r=jandem
MozReview-Commit-ID: CJsNr6U1whs
--- 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) \