diff --git a/js/src/jit/BaselineCacheIR.cpp b/js/src/jit/BaselineCacheIR.cpp index 0093b95386b9..27173207c0e1 100644 --- a/js/src/jit/BaselineCacheIR.cpp +++ b/js/src/jit/BaselineCacheIR.cpp @@ -843,6 +843,26 @@ BaselineCacheIRCompiler::emitLoadDynamicSlotResult() return true; } +bool +BaselineCacheIRCompiler::emitLoadUnboxedPropertyResult() +{ + Register obj = allocator.useRegister(masm, reader.objOperandId()); + AutoScratchRegister scratch(allocator, masm); + + JSValueType fieldType = reader.valueType(); + + Address fieldOffset(stubAddress(reader.stubOffset())); + masm.load32(fieldOffset, scratch); + masm.loadUnboxedProperty(BaseIndex(obj, scratch, TimesOne), fieldType, R0); + + if (fieldType == JSVAL_TYPE_OBJECT) + emitEnterTypeMonitorIC(); + else + emitReturnFromIC(); + + return true; +} + bool BaselineCacheIRCompiler::emitLoadUndefinedResult() { diff --git a/js/src/jit/BaselineInspector.cpp b/js/src/jit/BaselineInspector.cpp index 4ef7c42c1671..e17ac7695828 100644 --- a/js/src/jit/BaselineInspector.cpp +++ b/js/src/jit/BaselineInspector.cpp @@ -108,8 +108,6 @@ AddReceiver(const ReceiverGuard& receiver, static bool GetCacheIRReceiverForNativeReadSlot(ICCacheIR_Monitored* stub, ReceiverGuard* receiver) { - // If this is a getprop stub to get an own object's read-slot stub. - // // We match either: // // GuardIsObject 0 @@ -125,6 +123,7 @@ GetCacheIRReceiverForNativeReadSlot(ICCacheIR_Monitored* stub, ReceiverGuard* re // LoadUnboxedExpando 0 // LoadFixedSlotResult or LoadDynamicSlotResult + *receiver = ReceiverGuard(); CacheIRReader reader(stub->stubInfo()); ObjOperandId objId = ObjOperandId(0); @@ -154,6 +153,29 @@ GetCacheIRReceiverForNativeReadSlot(ICCacheIR_Monitored* stub, ReceiverGuard* re return false; } +static bool +GetCacheIRReceiverForUnboxedProperty(ICCacheIR_Monitored* stub, ReceiverGuard* receiver) +{ + // We match: + // + // GuardIsObject 0 + // GuardGroup 0 + // LoadUnboxedPropertyResult 0 .. + + *receiver = ReceiverGuard(); + CacheIRReader reader(stub->stubInfo()); + + ObjOperandId objId = ObjOperandId(0); + if (!reader.matchOp(CacheOp::GuardIsObject, objId)) + return false; + + if (!reader.matchOp(CacheOp::GuardGroup, objId)) + return false; + receiver->group = stub->stubInfo()->getStubField(stub, reader.stubOffset()); + + return reader.matchOp(CacheOp::LoadUnboxedPropertyResult, objId); +} + bool BaselineInspector::maybeInfoForPropertyOp(jsbytecode* pc, ReceiverVector& receivers, ObjectGroupVector& convertUnboxedGroups) @@ -176,15 +198,15 @@ BaselineInspector::maybeInfoForPropertyOp(jsbytecode* pc, ReceiverVector& receiv while (stub->next()) { ReceiverGuard receiver; if (stub->isCacheIR_Monitored()) { - if (!GetCacheIRReceiverForNativeReadSlot(stub->toCacheIR_Monitored(), &receiver)) { + if (!GetCacheIRReceiverForNativeReadSlot(stub->toCacheIR_Monitored(), &receiver) && + !GetCacheIRReceiverForUnboxedProperty(stub->toCacheIR_Monitored(), &receiver)) + { receivers.clear(); return true; } } else if (stub->isSetProp_Native()) { receiver = ReceiverGuard(stub->toSetProp_Native()->group(), stub->toSetProp_Native()->shape()); - } else if (stub->isGetProp_Unboxed()) { - receiver = ReceiverGuard(stub->toGetProp_Unboxed()->group(), nullptr); } else if (stub->isSetProp_Unboxed()) { receiver = ReceiverGuard(stub->toSetProp_Unboxed()->group(), nullptr); } else { @@ -805,7 +827,6 @@ BaselineInspector::expectedPropertyAccessInputType(jsbytecode* pc) // Either an object or magic arguments. return MIRType::Value; - case ICStub::GetProp_Unboxed: case ICStub::GetProp_TypedObject: case ICStub::GetProp_CallScripted: case ICStub::GetProp_CallNative: diff --git a/js/src/jit/CacheIR.cpp b/js/src/jit/CacheIR.cpp index 83e6b1f700ca..ddf1a478a48b 100644 --- a/js/src/jit/CacheIR.cpp +++ b/js/src/jit/CacheIR.cpp @@ -60,6 +60,8 @@ GetPropIRGenerator::tryAttachStub(Maybe& writer) return false; if (!emitted_ && !tryAttachNative(*writer, obj, objId)) return false; + if (!emitted_ && !tryAttachUnboxed(*writer, obj, objId)) + return false; if (!emitted_ && !tryAttachUnboxedExpando(*writer, obj, objId)) return false; if (!emitted_ && !tryAttachModuleNamespace(*writer, obj, objId)) @@ -257,6 +259,29 @@ GetPropIRGenerator::tryAttachNative(CacheIRWriter& writer, HandleObject obj, Obj return true; } +bool +GetPropIRGenerator::tryAttachUnboxed(CacheIRWriter& writer, HandleObject obj, ObjOperandId objId) +{ + MOZ_ASSERT(!emitted_); + + if (!obj->is()) + return true; + + const UnboxedLayout::Property* property = obj->as().layout().lookup(name_); + if (!property) + return true; + + if (!cx_->runtime()->jitSupportsFloatingPoint) + return true; + + writer.guardGroup(objId, obj->group()); + writer.loadUnboxedPropertyResult(objId, property->type, + UnboxedPlainObject::offsetOfData() + property->offset); + emitted_ = true; + preliminaryObjectAction_ = PreliminaryObjectAction::Unlink; + return true; +} + bool GetPropIRGenerator::tryAttachUnboxedExpando(CacheIRWriter& writer, HandleObject obj, ObjOperandId objId) { diff --git a/js/src/jit/CacheIR.h b/js/src/jit/CacheIR.h index d79b949b1fbf..54dfac6090d1 100644 --- a/js/src/jit/CacheIR.h +++ b/js/src/jit/CacheIR.h @@ -91,6 +91,7 @@ class ObjOperandId : public OperandId _(LoadUnboxedExpando) \ _(LoadFixedSlotResult) \ _(LoadDynamicSlotResult) \ + _(LoadUnboxedPropertyResult) \ _(LoadInt32ArrayLengthResult) \ _(LoadUnboxedArrayLengthResult) \ _(LoadArgumentsObjectLengthResult) \ @@ -304,6 +305,11 @@ class MOZ_RAII CacheIRWriter writeOpWithOperandId(CacheOp::LoadDynamicSlotResult, obj); addStubWord(offset, StubField::GCType::NoGCThing); } + void loadUnboxedPropertyResult(ObjOperandId obj, JSValueType type, size_t offset) { + writeOpWithOperandId(CacheOp::LoadUnboxedPropertyResult, obj); + buffer_.writeByte(uint32_t(type)); + addStubWord(offset, StubField::GCType::NoGCThing); + } void loadInt32ArrayLengthResult(ObjOperandId obj) { writeOpWithOperandId(CacheOp::LoadInt32ArrayLengthResult, obj); } @@ -349,6 +355,7 @@ class MOZ_RAII CacheIRReader uint32_t stubOffset() { return buffer_.readByte(); } GuardClassKind guardClassKind() { return GuardClassKind(buffer_.readByte()); } + JSValueType valueType() { return JSValueType(buffer_.readByte()); } bool matchOp(CacheOp op) { const uint8_t* pos = buffer_.currentPosition(); @@ -388,6 +395,7 @@ class MOZ_RAII GetPropIRGenerator PreliminaryObjectAction preliminaryObjectAction_; bool tryAttachNative(CacheIRWriter& writer, HandleObject obj, ObjOperandId objId); + bool tryAttachUnboxed(CacheIRWriter& writer, HandleObject obj, ObjOperandId objId); bool tryAttachUnboxedExpando(CacheIRWriter& writer, HandleObject obj, ObjOperandId objId); bool tryAttachObjectLength(CacheIRWriter& writer, HandleObject obj, ObjOperandId objId); bool tryAttachModuleNamespace(CacheIRWriter& writer, HandleObject obj, ObjOperandId objId); diff --git a/js/src/jit/SharedIC.cpp b/js/src/jit/SharedIC.cpp index d4084e7b76b6..19772c45bab8 100644 --- a/js/src/jit/SharedIC.cpp +++ b/js/src/jit/SharedIC.cpp @@ -404,11 +404,6 @@ ICStub::trace(JSTracer* trc) TraceEdge(trc, &propStub->protoShape(), "baseline-getprop-primitive-stub-shape"); break; } - case ICStub::GetProp_Unboxed: { - ICGetProp_Unboxed* propStub = toGetProp_Unboxed(); - TraceEdge(trc, &propStub->group(), "baseline-getprop-unboxed-stub-group"); - break; - } case ICStub::GetProp_TypedObject: { ICGetProp_TypedObject* propStub = toGetProp_TypedObject(); TraceEdge(trc, &propStub->shape(), "baseline-getprop-typedobject-stub-shape"); @@ -2554,40 +2549,6 @@ TryAttachNativeGetAccessorPropStub(JSContext* cx, SharedStubInfo* info, return true; } -static bool -TryAttachUnboxedGetPropStub(JSContext* cx, SharedStubInfo* info, - ICGetProp_Fallback* stub, HandlePropertyName name, - HandleValue val, bool* attached) -{ - MOZ_ASSERT(!*attached); - - if (!cx->runtime()->jitSupportsFloatingPoint) - return true; - - if (!val.isObject() || !val.toObject().is()) - return true; - Rooted obj(cx, &val.toObject().as()); - - const UnboxedLayout::Property* property = obj->layout().lookup(name); - if (!property) - return true; - - ICStub* monitorStub = stub->fallbackMonitorStub()->firstMonitorStub(); - - ICGetProp_Unboxed::Compiler compiler(cx, info->engine(), monitorStub, obj->group(), - property->offset + UnboxedPlainObject::offsetOfData(), - property->type); - ICStub* newStub = compiler.getStub(compiler.getStubSpace(info->outerScript(cx))); - if (!newStub) - return false; - stub->addNewStub(newStub); - - StripPreliminaryObjectStubs(cx, stub); - - *attached = true; - return true; -} - static bool TryAttachTypedObjectGetPropStub(JSContext* cx, SharedStubInfo* info, ICGetProp_Fallback* stub, HandlePropertyName name, @@ -2861,11 +2822,6 @@ DoGetPropFallback(JSContext* cx, void* payload, ICGetProp_Fallback* stub_, return true; - if (!TryAttachUnboxedGetPropStub(cx, &info, stub, name, val, &attached)) - return false; - if (attached) - return true; - if (!TryAttachTypedObjectGetPropStub(cx, &info, stub, name, val, &attached)) return false; if (attached) @@ -3754,39 +3710,6 @@ ICGetProp_Generic::Compiler::generateStubCode(MacroAssembler& masm) return true; } -bool -ICGetProp_Unboxed::Compiler::generateStubCode(MacroAssembler& masm) -{ - Label failure; - - AllocatableGeneralRegisterSet regs(availableGeneralRegs(1)); - - Register scratch = regs.takeAnyExcluding(ICTailCallReg); - - // Object and group guard. - masm.branchTestObject(Assembler::NotEqual, R0, &failure); - Register object = masm.extractObject(R0, ExtractTemp0); - masm.loadPtr(Address(ICStubReg, ICGetProp_Unboxed::offsetOfGroup()), scratch); - masm.branchPtr(Assembler::NotEqual, Address(object, JSObject::offsetOfGroup()), scratch, - &failure); - - // Get the address being read from. - masm.load32(Address(ICStubReg, ICGetProp_Unboxed::offsetOfFieldOffset()), scratch); - - masm.loadUnboxedProperty(BaseIndex(object, scratch, TimesOne), fieldType_, TypedOrValueRegister(R0)); - - // Only monitor the result if its type might change. - if (fieldType_ == JSVAL_TYPE_OBJECT) - EmitEnterTypeMonitorIC(masm); - else - EmitReturnFromIC(masm); - - masm.bind(&failure); - EmitStubGuardFailure(masm); - - return true; -} - void CheckForTypedObjectWithDetachedStorage(JSContext* cx, MacroAssembler& masm, Label* failure) { diff --git a/js/src/jit/SharedIC.h b/js/src/jit/SharedIC.h index 7be779f002ab..1c7065064583 100644 --- a/js/src/jit/SharedIC.h +++ b/js/src/jit/SharedIC.h @@ -2595,65 +2595,6 @@ class ICGetPropNativeCompiler : public ICStubCompiler ICGetPropNativeStub* getStub(ICStubSpace* space); }; -class ICGetProp_Unboxed : public ICMonitoredStub -{ - friend class ICStubSpace; - - HeapPtrObjectGroup group_; - uint32_t fieldOffset_; - - ICGetProp_Unboxed(JitCode* stubCode, ICStub* firstMonitorStub, ObjectGroup* group, - uint32_t fieldOffset) - : ICMonitoredStub(ICStub::GetProp_Unboxed, stubCode, firstMonitorStub), - group_(group), fieldOffset_(fieldOffset) - { - (void) fieldOffset_; // Silence clang warning - } - - public: - HeapPtrObjectGroup& group() { - return group_; - } - - static size_t offsetOfGroup() { - return offsetof(ICGetProp_Unboxed, group_); - } - static size_t offsetOfFieldOffset() { - return offsetof(ICGetProp_Unboxed, fieldOffset_); - } - - class Compiler : public ICStubCompiler { - protected: - ICStub* firstMonitorStub_; - RootedObjectGroup group_; - uint32_t fieldOffset_; - JSValueType fieldType_; - - bool generateStubCode(MacroAssembler& masm); - - virtual int32_t getKey() const { - return static_cast(engine_) | - (static_cast(kind) << 1) | - (static_cast(fieldType_) << 17); - } - - public: - Compiler(JSContext* cx, Engine engine, ICStub* firstMonitorStub, - ObjectGroup* group, uint32_t fieldOffset, JSValueType fieldType) - : ICStubCompiler(cx, ICStub::GetProp_Unboxed, engine), - firstMonitorStub_(firstMonitorStub), - group_(cx, group), - fieldOffset_(fieldOffset), - fieldType_(fieldType) - {} - - ICStub* getStub(ICStubSpace* space) { - return newStub(space, getStubCode(), firstMonitorStub_, group_, - fieldOffset_); - } - }; -}; - static uint32_t SimpleTypeDescrKey(SimpleTypeDescr* descr) { diff --git a/js/src/jit/SharedICList.h b/js/src/jit/SharedICList.h index 1a67dfba5e46..600854c1a405 100644 --- a/js/src/jit/SharedICList.h +++ b/js/src/jit/SharedICList.h @@ -37,7 +37,6 @@ namespace jit { _(GetProp_Fallback) \ _(GetProp_Primitive) \ _(GetProp_StringLength) \ - _(GetProp_Unboxed) \ _(GetProp_TypedObject) \ _(GetProp_CallScripted) \ _(GetProp_CallNative) \