Bug 1433959: Convert GetIntrinsic inline cache to CacheIR r=tcampbell
authorMatthew Gaudet <mgaudet@mozilla.com>
Tue, 06 Feb 2018 11:43:25 -0500
changeset 402843 96333b8e8e2586295b11a05ec9eae868f47957c4
parent 402790 3e3cfa85d219e7d166f268474c1e38780e38be85
child 402844 1564fec091b4cccc4b2fd652132e8c9dcdbbdb91
push id33405
push usershindli@mozilla.com
push dateThu, 08 Feb 2018 10:04:47 +0000
treeherdermozilla-central@0ac953fcddf1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstcampbell
bugs1433959
milestone60.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 1433959: Convert GetIntrinsic inline cache to CacheIR r=tcampbell
js/src/jit/BaselineCacheIRCompiler.cpp
js/src/jit/BaselineIC.cpp
js/src/jit/BaselineIC.h
js/src/jit/BaselineICList.h
js/src/jit/CacheIR.cpp
js/src/jit/CacheIR.h
js/src/jit/CodeGenerator.cpp
js/src/jit/IonCacheIRCompiler.cpp
js/src/jit/IonIC.cpp
js/src/jit/SharedIC.cpp
--- a/js/src/jit/BaselineCacheIRCompiler.cpp
+++ b/js/src/jit/BaselineCacheIRCompiler.cpp
@@ -473,16 +473,24 @@ BaselineCacheIRCompiler::emitGuardFuncti
     masm.branchPtr(Assembler::NotEqual,
                    prototypeObject,
                    scratch1, failure->label());
 
     return true;
 }
 
 bool
+BaselineCacheIRCompiler::emitLoadValueResult()
+{
+    AutoOutputRegister output(*this);
+    masm.loadValue(stubAddress(reader.stubOffset()), output.valueReg());
+    return true;
+}
+
+bool
 BaselineCacheIRCompiler::emitLoadFixedSlotResult()
 {
     AutoOutputRegister output(*this);
     Register obj = allocator.useRegister(masm, reader.objOperandId());
     AutoScratchRegisterMaybeOutput scratch(allocator, masm, output);
 
     masm.load32(stubAddress(reader.stubOffset()), scratch);
     masm.loadValue(BaseIndex(obj, scratch, TimesOne), output.valueReg());
@@ -2087,16 +2095,19 @@ BaselineCacheIRCompiler::init(CacheKind 
     size_t numInputs = writer_.numInputOperands();
 
     // Baseline passes the first 2 inputs in R0/R1, other Values are stored on
     // the stack.
     size_t numInputsInRegs = std::min(numInputs, size_t(2));
     AllocatableGeneralRegisterSet available(ICStubCompiler::availableGeneralRegs(numInputsInRegs));
 
     switch (kind) {
+      case CacheKind::GetIntrinsic:
+        MOZ_ASSERT(numInputs == 0);
+        break;
       case CacheKind::GetProp:
       case CacheKind::TypeOf:
       case CacheKind::GetIterator:
       case CacheKind::ToBool:
         MOZ_ASSERT(numInputs == 1);
         allocator.initInputLocation(0, R0);
         break;
       case CacheKind::Compare:
--- a/js/src/jit/BaselineIC.cpp
+++ b/js/src/jit/BaselineIC.cpp
@@ -1387,23 +1387,35 @@ DoGetIntrinsicFallback(JSContext* cx, Ba
     // directly.
 
     TypeScript::Monitor(cx, script, pc, res);
 
     // Check if debug mode toggling made the stub invalid.
     if (stub.invalid())
         return true;
 
-    JitSpew(JitSpew_BaselineIC, "  Generating GetIntrinsic optimized stub");
-    ICGetIntrinsic_Constant::Compiler compiler(cx, res);
-    ICStub* newStub = compiler.getStub(compiler.getStubSpace(script));
-    if (!newStub)
-        return false;
-
-    stub->addNewStub(newStub);
+    if (stub->state().maybeTransition())
+        stub->discardStubs(cx);
+
+    if (stub->state().canAttachStub()) {
+        bool attached = false;
+        RootedScript script(cx, frame->script());
+        GetIntrinsicIRGenerator gen(cx, script, pc, stub->state().mode(), res);
+        if (gen.tryAttachStub()) {
+            ICStub* newStub = AttachBaselineCacheIRStub(cx, gen.writerRef(), gen.cacheKind(),
+                                                        BaselineCacheIRStubKind::Regular,
+                                                        ICStubEngine::Baseline, script, stub,
+                                                        &attached);
+            if (newStub)
+                JitSpew(JitSpew_BaselineIC, "  Attached CacheIR stub");
+        }
+        if (!attached)
+            stub->state().trackNotAttached();
+    }
+
     return true;
 }
 
 typedef bool (*DoGetIntrinsicFallbackFn)(JSContext*, BaselineFrame*, ICGetIntrinsic_Fallback*,
                                          MutableHandleValue);
 static const VMFunction DoGetIntrinsicFallbackInfo =
     FunctionInfo<DoGetIntrinsicFallbackFn>(DoGetIntrinsicFallback, "DoGetIntrinsicFallback",
                                            TailCall);
@@ -1416,27 +1428,16 @@ ICGetIntrinsic_Fallback::Compiler::gener
     EmitRestoreTailCallReg(masm);
 
     masm.push(ICStubReg);
     pushStubPayload(masm, R0.scratchReg());
 
     return tailCallVM(DoGetIntrinsicFallbackInfo, masm);
 }
 
-bool
-ICGetIntrinsic_Constant::Compiler::generateStubCode(MacroAssembler& masm)
-{
-    MOZ_ASSERT(engine_ == Engine::Baseline);
-
-    masm.loadValue(Address(ICStubReg, ICGetIntrinsic_Constant::offsetOfValue()), R0);
-
-    EmitReturnFromIC(masm);
-    return true;
-}
-
 //
 // SetProp_Fallback
 //
 
 static bool
 DoSetPropFallback(JSContext* cx, BaselineFrame* frame, ICSetProp_Fallback* stub_, Value* stack,
                   HandleValue lhs, HandleValue rhs)
 {
@@ -4377,24 +4378,16 @@ ICTypeUpdate_SingleObject::ICTypeUpdate_
     obj_(obj)
 { }
 
 ICTypeUpdate_ObjectGroup::ICTypeUpdate_ObjectGroup(JitCode* stubCode, ObjectGroup* group)
   : ICStub(TypeUpdate_ObjectGroup, stubCode),
     group_(group)
 { }
 
-ICGetIntrinsic_Constant::ICGetIntrinsic_Constant(JitCode* stubCode, const Value& value)
-  : ICStub(GetIntrinsic_Constant, stubCode),
-    value_(value)
-{ }
-
-ICGetIntrinsic_Constant::~ICGetIntrinsic_Constant()
-{ }
-
 ICCall_Scripted::ICCall_Scripted(JitCode* stubCode, ICStub* firstMonitorStub,
                                  JSFunction* callee, JSObject* templateObject,
                                  uint32_t pcOffset)
   : ICMonitoredStub(ICStub::Call_Scripted, stubCode, firstMonitorStub),
     callee_(callee),
     templateObject_(templateObject),
     pcOffset_(pcOffset)
 { }
--- a/js/src/jit/BaselineIC.h
+++ b/js/src/jit/BaselineIC.h
@@ -494,51 +494,16 @@ class ICGetIntrinsic_Fallback : public I
         { }
 
         ICStub* getStub(ICStubSpace* space) override {
             return newStub<ICGetIntrinsic_Fallback>(space, getStubCode());
         }
     };
 };
 
-// Stub that loads the constant result of a GETINTRINSIC operation.
-class ICGetIntrinsic_Constant : public ICStub
-{
-    friend class ICStubSpace;
-
-    GCPtrValue value_;
-
-    ICGetIntrinsic_Constant(JitCode* stubCode, const Value& value);
-    ~ICGetIntrinsic_Constant();
-
-  public:
-    GCPtrValue& value() {
-        return value_;
-    }
-    static size_t offsetOfValue() {
-        return offsetof(ICGetIntrinsic_Constant, value_);
-    }
-
-    class Compiler : public ICStubCompiler {
-        MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm) override;
-
-        HandleValue value_;
-
-      public:
-        Compiler(JSContext* cx, HandleValue value)
-          : ICStubCompiler(cx, ICStub::GetIntrinsic_Constant, Engine::Baseline),
-            value_(value)
-        {}
-
-        ICStub* getStub(ICStubSpace* space) override {
-            return newStub<ICGetIntrinsic_Constant>(space, getStubCode(), value_);
-        }
-    };
-};
-
 // SetProp
 //     JSOP_SETPROP
 //     JSOP_SETNAME
 //     JSOP_SETGNAME
 //     JSOP_INITPROP
 
 class ICSetProp_Fallback : public ICFallbackStub
 {
--- a/js/src/jit/BaselineICList.h
+++ b/js/src/jit/BaselineICList.h
@@ -51,17 +51,16 @@ namespace jit {
     _(In_Fallback)                               \
     _(HasOwn_Fallback)                           \
                                                  \
     _(GetName_Fallback)                          \
                                                  \
     _(BindName_Fallback)                         \
                                                  \
     _(GetIntrinsic_Fallback)                     \
-    _(GetIntrinsic_Constant)                     \
                                                  \
     _(SetProp_Fallback)                          \
                                                  \
     _(TableSwitch)                               \
                                                  \
     _(GetIterator_Fallback)                      \
     _(IteratorMore_Fallback)                     \
     _(IteratorMore_Native)                       \
--- a/js/src/jit/CacheIR.cpp
+++ b/js/src/jit/CacheIR.cpp
@@ -4827,9 +4827,53 @@ ToBoolIRGenerator::tryAttachObject()
         return false;
 
     ValOperandId valId(writer.setInputOperandId(0));
     ObjOperandId objId = writer.guardIsObject(valId);
     writer.loadObjectTruthyResult(objId);
     writer.returnFromIC();
     trackAttached("ToBoolObject");
     return true;
+}
+
+GetIntrinsicIRGenerator::GetIntrinsicIRGenerator(JSContext* cx, HandleScript script, jsbytecode* pc, ICState::Mode mode,
+                                                 HandleValue val)
+  : IRGenerator(cx, script, pc, CacheKind::GetIntrinsic, mode)
+  , val_(val)
+{}
+
+void
+GetIntrinsicIRGenerator::trackAttached(const char* name)
+{
+#ifdef JS_CACHEIR_SPEW
+    CacheIRSpewer& sp = CacheIRSpewer::singleton();
+    if (sp.enabled()) {
+        LockGuard<Mutex> guard(sp.lock());
+        sp.beginCache(guard, *this);
+        sp.valueProperty(guard, "val", val_);
+        sp.attached(guard, name);
+        sp.endCache(guard);
+    }
+#endif
+}
+
+void
+GetIntrinsicIRGenerator::trackNotAttached()
+{
+#ifdef JS_CACHEIR_SPEW
+    CacheIRSpewer& sp = CacheIRSpewer::singleton();
+    if (sp.enabled()) {
+        LockGuard<Mutex> guard(sp.lock());
+        sp.beginCache(guard, *this);
+        sp.valueProperty(guard, "val", val_);
+        sp.endCache(guard);
+    }
+#endif
+}
+
+bool
+GetIntrinsicIRGenerator::tryAttachStub()
+{
+    writer.loadValueResult(val_);
+    writer.returnFromIC();
+    trackAttached("GetIntrinsic");
+    return true;
 }
\ No newline at end of file
--- a/js/src/jit/CacheIR.h
+++ b/js/src/jit/CacheIR.h
@@ -137,16 +137,17 @@ class TypedOperandId : public OperandId
 };
 
 #define CACHE_IR_KINDS(_)   \
     _(GetProp)              \
     _(GetElem)              \
     _(GetName)              \
     _(GetPropSuper)         \
     _(GetElemSuper)         \
+    _(GetIntrinsic)         \
     _(SetProp)              \
     _(SetElem)              \
     _(BindName)             \
     _(In)                   \
     _(HasOwn)               \
     _(TypeOf)               \
     _(InstanceOf)           \
     _(GetIterator)          \
@@ -270,16 +271,17 @@ extern const char* CacheKindNames[];
     _(LoadBooleanResult)                  \
     _(LoadStringResult)                   \
     _(LoadInstanceOfObjectResult)         \
     _(LoadTypeOfObjectResult)             \
     _(LoadInt32TruthyResult)              \
     _(LoadDoubleTruthyResult)             \
     _(LoadStringTruthyResult)             \
     _(LoadObjectTruthyResult)             \
+    _(LoadValueResult)                    \
                                           \
     _(CallStringSplitResult)              \
                                           \
     _(CompareStringResult)                \
     _(CompareObjectResult)                \
     _(CompareSymbolResult)                \
                                           \
     _(CallPrintString)                    \
@@ -1029,16 +1031,20 @@ class MOZ_RAII CacheIRWriter : public JS
         writeOpWithOperandId(CacheOp::LoadDoubleTruthyResult, dbl);
     }
     void loadStringTruthyResult(StringOperandId str) {
         writeOpWithOperandId(CacheOp::LoadStringTruthyResult, str);
     }
     void loadObjectTruthyResult(ObjOperandId obj) {
         writeOpWithOperandId(CacheOp::LoadObjectTruthyResult, obj);
     }
+    void loadValueResult(const Value& val) {
+        writeOp(CacheOp::LoadValueResult);
+        addStubField(val.asRawBits(), StubField::Type::Value);
+    }
     void callStringSplitResult(StringOperandId str, StringOperandId sep, ObjectGroup* group) {
         writeOp(CacheOp::CallStringSplitResult);
         writeOperandId(str);
         writeOperandId(sep);
         addStubField(uintptr_t(group), StubField::Type::ObjectGroup);
     }
 
     void compareStringResult(uint32_t op, StringOperandId lhs, StringOperandId rhs) {
@@ -1637,12 +1643,26 @@ class MOZ_RAII ToBoolIRGenerator : publi
 
   public:
     ToBoolIRGenerator(JSContext* cx, HandleScript, jsbytecode* pc, ICState::Mode mode,
                       HandleValue val);
 
     bool tryAttachStub();
 };
 
+class MOZ_RAII GetIntrinsicIRGenerator : public IRGenerator
+{
+    HandleValue val_;
+
+    void trackAttached(const char* name);
+    void trackNotAttached();
+
+  public:
+    GetIntrinsicIRGenerator(JSContext* cx, HandleScript, jsbytecode* pc, ICState::Mode,
+                            HandleValue val);
+
+    bool tryAttachStub();
+};
+
 } // namespace jit
 } // namespace js
 
 #endif /* jit_CacheIR_h */
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -354,16 +354,17 @@ CodeGenerator::visitOutOfLineICFallback(
 
         masm.jump(ool->rejoin());
         return;
       }
       case CacheKind::Call:
       case CacheKind::Compare:
       case CacheKind::TypeOf:
       case CacheKind::ToBool:
+      case CacheKind::GetIntrinsic:
         MOZ_CRASH("Unsupported IC");
     }
     MOZ_CRASH();
 }
 
 StringObject*
 MNewStringObject::templateObj() const
 {
--- a/js/src/jit/IonCacheIRCompiler.cpp
+++ b/js/src/jit/IonCacheIRCompiler.cpp
@@ -542,16 +542,17 @@ IonCacheIRCompiler::init()
         allocator.initInputLocation(1, TypedOrValueRegister(MIRType::Object,
                                                             AnyRegister(ic->rhs())));
         break;
       }
       case CacheKind::Call:
       case CacheKind::Compare:
       case CacheKind::TypeOf:
       case CacheKind::ToBool:
+      case CacheKind::GetIntrinsic:
         MOZ_CRASH("Unsupported IC");
     }
 
     if (liveRegs_)
         liveFloatRegs_ = LiveFloatRegisterSet(liveRegs_->fpus());
 
     allocator.initAvailableRegs(available);
     allocator.initAvailableRegsAfterSpill();
@@ -883,16 +884,23 @@ IonCacheIRCompiler::emitGuardFunctionPro
     masm.branchPtr(Assembler::NotEqual,
                    prototypeObject,
                    scratch1, failure->label());
 
     return true;
 }
 
 bool
+IonCacheIRCompiler::emitLoadValueResult()
+{
+   MOZ_CRASH("Baseline-specific op");
+}
+
+
+bool
 IonCacheIRCompiler::emitLoadFixedSlotResult()
 {
     AutoOutputRegister output(*this);
     Register obj = allocator.useRegister(masm, reader.objOperandId());
     int32_t offset = int32StubField(reader.stubOffset());
     masm.loadTypedOrValue(Address(obj, offset), output);
     return true;
 }
--- a/js/src/jit/IonIC.cpp
+++ b/js/src/jit/IonIC.cpp
@@ -59,16 +59,17 @@ IonIC::scratchRegisterForEntryJump()
       case CacheKind::GetIterator:
         return asGetIteratorIC()->temp1();
       case CacheKind::InstanceOf:
         return asInstanceOfIC()->output();
       case CacheKind::Call:
       case CacheKind::Compare:
       case CacheKind::TypeOf:
       case CacheKind::ToBool:
+      case CacheKind::GetIntrinsic:
         MOZ_CRASH("Unsupported IC");
     }
 
     MOZ_CRASH("Invalid kind");
 }
 
 void
 IonIC::discardStubs(Zone* zone)
--- a/js/src/jit/SharedIC.cpp
+++ b/js/src/jit/SharedIC.cpp
@@ -287,21 +287,16 @@ ICStub::trace(JSTracer* trc)
         TraceEdge(trc, &updateStub->object(), "baseline-update-singleton");
         break;
       }
       case ICStub::TypeUpdate_ObjectGroup: {
         ICTypeUpdate_ObjectGroup* updateStub = toTypeUpdate_ObjectGroup();
         TraceEdge(trc, &updateStub->group(), "baseline-update-group");
         break;
       }
-      case ICStub::GetIntrinsic_Constant: {
-        ICGetIntrinsic_Constant* constantStub = toGetIntrinsic_Constant();
-        TraceEdge(trc, &constantStub->value(), "baseline-getintrinsic-constant-value");
-        break;
-      }
       case ICStub::NewArray_Fallback: {
         ICNewArray_Fallback* stub = toNewArray_Fallback();
         TraceNullableEdge(trc, &stub->templateObject(), "baseline-newarray-template");
         TraceEdge(trc, &stub->templateGroup(), "baseline-newarray-template-group");
         break;
       }
       case ICStub::NewObject_Fallback: {
         ICNewObject_Fallback* stub = toNewObject_Fallback();