Bug 1322091 part 2 - Port Baseline lazy arguments GETELEM stub to CacheIR. r=evilpie
authorJan de Mooij <jdemooij@mozilla.com>
Fri, 09 Dec 2016 12:20:11 -1000
changeset 325613 b3249dd222cabf22cdf1f10a06d442ea5118db53
parent 325612 16720e74a36fed6a0df2843d83d72a9141ea0368
child 325614 ff00ebb732744d3196d30b8c1ce1c4feaf20db1a
push id24
push usermaklebus@msu.edu
push dateTue, 20 Dec 2016 03:11:33 +0000
reviewersevilpie
bugs1322091
milestone53.0a1
Bug 1322091 part 2 - Port Baseline lazy arguments GETELEM stub to CacheIR. r=evilpie
js/src/jit/BaselineCacheIR.cpp
js/src/jit/BaselineIC.cpp
js/src/jit/BaselineIC.h
js/src/jit/CacheIR.cpp
js/src/jit/CacheIR.h
--- a/js/src/jit/BaselineCacheIR.cpp
+++ b/js/src/jit/BaselineCacheIR.cpp
@@ -1601,16 +1601,35 @@ BaselineCacheIRCompiler::emitLoadStringC
     masm.movePtr(ImmPtr(&cx_->staticStrings().unitStaticTable), R0.scratchReg());
     masm.loadPtr(BaseIndex(R0.scratchReg(), scratch, ScalePointer), R0.scratchReg());
 
     masm.tagValue(JSVAL_TYPE_STRING, R0.scratchReg(), R0);
     return true;
 }
 
 bool
+BaselineCacheIRCompiler::emitLoadFrameArgumentResult()
+{
+    Register index = allocator.useRegister(masm, reader.int32OperandId());
+    AutoScratchRegister scratch(allocator, masm);
+
+    FailurePath* failure;
+    if (!addFailurePath(&failure))
+        return false;
+
+    // Bounds check.
+    masm.loadPtr(Address(BaselineFrameReg, BaselineFrame::offsetOfNumActualArgs()), scratch);
+    masm.branch32(Assembler::AboveOrEqual, index, scratch, failure->label());
+
+    // Load the argument.
+    masm.loadValue(BaseValueIndex(BaselineFrameReg, index, BaselineFrame::offsetOfArg(0)), R0);
+    return true;
+}
+
+bool
 BaselineCacheIRCompiler::emitTypeMonitorResult()
 {
     allocator.discardStack(masm);
     EmitEnterTypeMonitorIC(masm);
     return true;
 }
 
 bool
--- a/js/src/jit/BaselineIC.cpp
+++ b/js/src/jit/BaselineIC.cpp
@@ -946,32 +946,16 @@ IsNativeOrUnboxedDenseElementAccess(Hand
         return true;
     return false;
 }
 
 static bool
 TryAttachGetElemStub(JSContext* cx, JSScript* script, jsbytecode* pc, ICGetElem_Fallback* stub,
                      HandleValue lhs, HandleValue rhs, HandleValue res, bool* attached)
 {
-    if (lhs.isMagic(JS_OPTIMIZED_ARGUMENTS) && rhs.isInt32() &&
-        !ArgumentsGetElemStubExists(stub, ICGetElem_Arguments::Magic))
-    {
-        JitSpew(JitSpew_BaselineIC, "  Generating GetElem(MagicArgs[Int32]) stub");
-        ICGetElem_Arguments::Compiler compiler(cx, stub->fallbackMonitorStub()->firstMonitorStub(),
-                                               ICGetElem_Arguments::Magic);
-        ICStub* argsStub = compiler.getStub(compiler.getStubSpace(script));
-        if (!argsStub)
-            return false;
-
-        stub->addNewStub(argsStub);
-        *attached = true;
-        return true;
-    }
-
-    // Otherwise, GetElem is only optimized on objects.
     if (!lhs.isObject())
         return true;
     RootedObject obj(cx, &lhs.toObject());
 
     // Check for ArgumentsObj[int] accesses
     if (obj->is<ArgumentsObject>() && rhs.isInt32() &&
         !obj->as<ArgumentsObject>().hasOverriddenElement())
     {
@@ -1359,54 +1343,16 @@ ICGetElem_TypedArray::Compiler::generate
 // GetElem_Arguments
 //
 bool
 ICGetElem_Arguments::Compiler::generateStubCode(MacroAssembler& masm)
 {
     MOZ_ASSERT(engine_ == Engine::Baseline);
 
     Label failure;
-    if (which_ == ICGetElem_Arguments::Magic) {
-        // Ensure that this is a magic arguments value.
-        masm.branchTestMagicValue(Assembler::NotEqual, R0, JS_OPTIMIZED_ARGUMENTS, &failure);
-
-        // Ensure that frame has not loaded different arguments object since.
-        masm.branchTest32(Assembler::NonZero,
-                          Address(BaselineFrameReg, BaselineFrame::reverseOffsetOfFlags()),
-                          Imm32(BaselineFrame::HAS_ARGS_OBJ),
-                          &failure);
-
-        // Ensure that index is an integer.
-        masm.branchTestInt32(Assembler::NotEqual, R1, &failure);
-        Register idx = masm.extractInt32(R1, ExtractTemp1);
-
-        AllocatableGeneralRegisterSet regs(availableGeneralRegs(2));
-        Register scratch = regs.takeAny();
-
-        // Load num actual arguments
-        Address actualArgs(BaselineFrameReg, BaselineFrame::offsetOfNumActualArgs());
-        masm.loadPtr(actualArgs, scratch);
-
-        // Ensure idx < argc
-        masm.branch32(Assembler::AboveOrEqual, idx, scratch, &failure);
-
-        // Load argval
-        masm.movePtr(BaselineFrameReg, scratch);
-        masm.addPtr(Imm32(BaselineFrame::offsetOfArg(0)), scratch);
-        BaseValueIndex element(scratch, idx);
-        masm.loadValue(element, R0);
-
-        // Enter type monitor IC to type-check result.
-        EmitEnterTypeMonitorIC(masm);
-
-        masm.bind(&failure);
-        EmitStubGuardFailure(masm);
-        return true;
-    }
-
     MOZ_ASSERT(which_ == ICGetElem_Arguments::Mapped ||
                which_ == ICGetElem_Arguments::Unmapped);
 
     const Class* clasp = (which_ == ICGetElem_Arguments::Mapped)
                          ? &MappedArgumentsObject::class_
                          : &UnmappedArgumentsObject::class_;
 
     AllocatableGeneralRegisterSet regs(availableGeneralRegs(2));
--- a/js/src/jit/BaselineIC.h
+++ b/js/src/jit/BaselineIC.h
@@ -559,17 +559,17 @@ class ICGetElem_TypedArray : public ICSt
         }
     };
 };
 
 class ICGetElem_Arguments : public ICMonitoredStub
 {
     friend class ICStubSpace;
   public:
-    enum Which { Mapped, Unmapped, Magic };
+    enum Which { Mapped, Unmapped };
 
   private:
     ICGetElem_Arguments(JitCode* stubCode, ICStub* firstMonitorStub, Which which)
       : ICMonitoredStub(ICStub::GetElem_Arguments, stubCode, firstMonitorStub)
     {
         extra_ = static_cast<uint16_t>(which);
     }
 
--- a/js/src/jit/CacheIR.cpp
+++ b/js/src/jit/CacheIR.cpp
@@ -89,23 +89,26 @@ GetPropIRGenerator::tryAttachStub()
         return false;
     }
 
     if (nameOrSymbol) {
         if (tryAttachPrimitive(valId, id))
             return true;
         if (tryAttachStringLength(valId, id))
             return true;
-        if (tryAttachMagicArguments(valId, id))
+        if (tryAttachMagicArgumentsName(valId, id))
             return true;
         return false;
     }
 
     if (idVal_.isInt32()) {
-        if (tryAttachStringChar(valId, getElemKeyValueId()))
+        ValOperandId indexId = getElemKeyValueId();
+        if (tryAttachStringChar(valId, indexId))
+            return true;
+        if (tryAttachMagicArgument(valId, indexId))
             return true;
         return false;
     }
 
     return false;
 }
 
 static bool
@@ -801,17 +804,17 @@ GetPropIRGenerator::tryAttachStringChar(
     StringOperandId strId = writer.guardIsString(valId);
     Int32OperandId int32IndexId = writer.guardIsInt32(indexId);
     writer.loadStringCharResult(strId, int32IndexId);
     writer.returnFromIC();
     return true;
 }
 
 bool
-GetPropIRGenerator::tryAttachMagicArguments(ValOperandId valId, HandleId id)
+GetPropIRGenerator::tryAttachMagicArgumentsName(ValOperandId valId, HandleId id)
 {
     if (!val_.isMagic(JS_OPTIMIZED_ARGUMENTS))
         return false;
 
     if (!JSID_IS_ATOM(id, cx_->names().length) && !JSID_IS_ATOM(id, cx_->names().callee))
         return false;
 
     maybeEmitIdGuard(id);
@@ -825,16 +828,33 @@ GetPropIRGenerator::tryAttachMagicArgume
         MOZ_ASSERT(JSID_IS_ATOM(id, cx_->names().callee));
         writer.loadFrameCalleeResult();
         writer.typeMonitorResult();
     }
 
     return true;
 }
 
+bool
+GetPropIRGenerator::tryAttachMagicArgument(ValOperandId valId, ValOperandId indexId)
+{
+    MOZ_ASSERT(idVal_.isInt32());
+
+    if (!val_.isMagic(JS_OPTIMIZED_ARGUMENTS))
+        return false;
+
+    writer.guardMagicValue(valId, JS_OPTIMIZED_ARGUMENTS);
+    writer.guardFrameHasNoArgumentsObject();
+
+    Int32OperandId int32IndexId = writer.guardIsInt32(indexId);
+    writer.loadFrameArgumentResult(int32IndexId);
+    writer.typeMonitorResult();
+    return true;
+}
+
 void
 GetPropIRGenerator::maybeEmitIdGuard(jsid id)
 {
     if (cacheKind_ == CacheKind::GetProp) {
         // Constant PropertyName, no guards necessary.
         MOZ_ASSERT(&idVal_.toString()->asAtom() == JSID_TO_ATOM(id));
         return;
     }
--- a/js/src/jit/CacheIR.h
+++ b/js/src/jit/CacheIR.h
@@ -161,16 +161,17 @@ enum class CacheKind : uint8_t
     _(LoadTypedObjectResult)              \
     _(LoadInt32ArrayLengthResult)         \
     _(LoadUnboxedArrayLengthResult)       \
     _(LoadArgumentsObjectLengthResult)    \
     _(LoadStringCharResult)               \
     _(LoadStringLengthResult)             \
     _(LoadFrameCalleeResult)              \
     _(LoadFrameNumActualArgsResult)       \
+    _(LoadFrameArgumentResult)            \
     _(CallScriptedGetterResult)           \
     _(CallNativeGetterResult)             \
     _(CallProxyGetResult)                 \
     _(CallProxyGetByValueResult)          \
     _(LoadUndefinedResult)                \
                                           \
     _(TypeMonitorResult)                  \
     _(ReturnFromIC)
@@ -436,16 +437,19 @@ class MOZ_RAII CacheIRWriter : public JS
         writeOp(CacheOp::GuardFrameHasNoArgumentsObject);
     }
     void loadFrameCalleeResult() {
         writeOp(CacheOp::LoadFrameCalleeResult);
     }
     void loadFrameNumActualArgsResult() {
         writeOp(CacheOp::LoadFrameNumActualArgsResult);
     }
+    void loadFrameArgumentResult(Int32OperandId index) {
+        writeOpWithOperandId(CacheOp::LoadFrameArgumentResult, index);
+    }
     void guardNoUnboxedExpando(ObjOperandId obj) {
         writeOpWithOperandId(CacheOp::GuardNoUnboxedExpando, obj);
     }
     ObjOperandId guardAndLoadUnboxedExpando(ObjOperandId obj) {
         ObjOperandId res(nextOperandId_++);
         writeOpWithOperandId(CacheOp::GuardAndLoadUnboxedExpando, obj);
         writeOperandId(res);
         return res;
@@ -641,17 +645,18 @@ class MOZ_RAII GetPropIRGenerator
     bool tryAttachGenericProxy(HandleObject obj, ObjOperandId objId, HandleId id);
     bool tryAttachDOMProxyShadowed(HandleObject obj, ObjOperandId objId, HandleId id);
     bool tryAttachDOMProxyUnshadowed(HandleObject obj, ObjOperandId objId, HandleId id);
     bool tryAttachProxy(HandleObject obj, ObjOperandId objId, HandleId id);
 
     bool tryAttachPrimitive(ValOperandId valId, HandleId id);
     bool tryAttachStringChar(ValOperandId valId, ValOperandId indexId);
     bool tryAttachStringLength(ValOperandId valId, HandleId id);
-    bool tryAttachMagicArguments(ValOperandId valId, HandleId id);
+    bool tryAttachMagicArgumentsName(ValOperandId valId, HandleId id);
+    bool tryAttachMagicArgument(ValOperandId valId, ValOperandId indexId);
 
     ValOperandId getElemKeyValueId() const {
         MOZ_ASSERT(cacheKind_ == CacheKind::GetElem);
         return ValOperandId(1);
     }
 
     // If this is a GetElem cache, emit instructions to guard the incoming Value
     // matches |id|.