Bug 1266180 - Port unboxed object getprop stub to CacheIR. r=efaust

This commit is contained in:
Jan de Mooij 2016-05-02 10:22:53 +02:00
Родитель b21b1c955b
Коммит 6e76c672f2
7 изменённых файлов: 80 добавлений и 143 удалений

Просмотреть файл

@ -843,6 +843,26 @@ BaselineCacheIRCompiler::emitLoadDynamicSlotResult()
return true; 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 bool
BaselineCacheIRCompiler::emitLoadUndefinedResult() BaselineCacheIRCompiler::emitLoadUndefinedResult()
{ {

Просмотреть файл

@ -108,8 +108,6 @@ AddReceiver(const ReceiverGuard& receiver,
static bool static bool
GetCacheIRReceiverForNativeReadSlot(ICCacheIR_Monitored* stub, ReceiverGuard* receiver) GetCacheIRReceiverForNativeReadSlot(ICCacheIR_Monitored* stub, ReceiverGuard* receiver)
{ {
// If this is a getprop stub to get an own object's read-slot stub.
//
// We match either: // We match either:
// //
// GuardIsObject 0 // GuardIsObject 0
@ -125,6 +123,7 @@ GetCacheIRReceiverForNativeReadSlot(ICCacheIR_Monitored* stub, ReceiverGuard* re
// LoadUnboxedExpando 0 // LoadUnboxedExpando 0
// LoadFixedSlotResult or LoadDynamicSlotResult // LoadFixedSlotResult or LoadDynamicSlotResult
*receiver = ReceiverGuard();
CacheIRReader reader(stub->stubInfo()); CacheIRReader reader(stub->stubInfo());
ObjOperandId objId = ObjOperandId(0); ObjOperandId objId = ObjOperandId(0);
@ -154,6 +153,29 @@ GetCacheIRReceiverForNativeReadSlot(ICCacheIR_Monitored* stub, ReceiverGuard* re
return false; 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<ObjectGroup*>(stub, reader.stubOffset());
return reader.matchOp(CacheOp::LoadUnboxedPropertyResult, objId);
}
bool bool
BaselineInspector::maybeInfoForPropertyOp(jsbytecode* pc, ReceiverVector& receivers, BaselineInspector::maybeInfoForPropertyOp(jsbytecode* pc, ReceiverVector& receivers,
ObjectGroupVector& convertUnboxedGroups) ObjectGroupVector& convertUnboxedGroups)
@ -176,15 +198,15 @@ BaselineInspector::maybeInfoForPropertyOp(jsbytecode* pc, ReceiverVector& receiv
while (stub->next()) { while (stub->next()) {
ReceiverGuard receiver; ReceiverGuard receiver;
if (stub->isCacheIR_Monitored()) { if (stub->isCacheIR_Monitored()) {
if (!GetCacheIRReceiverForNativeReadSlot(stub->toCacheIR_Monitored(), &receiver)) { if (!GetCacheIRReceiverForNativeReadSlot(stub->toCacheIR_Monitored(), &receiver) &&
!GetCacheIRReceiverForUnboxedProperty(stub->toCacheIR_Monitored(), &receiver))
{
receivers.clear(); receivers.clear();
return true; return true;
} }
} else if (stub->isSetProp_Native()) { } else if (stub->isSetProp_Native()) {
receiver = ReceiverGuard(stub->toSetProp_Native()->group(), receiver = ReceiverGuard(stub->toSetProp_Native()->group(),
stub->toSetProp_Native()->shape()); stub->toSetProp_Native()->shape());
} else if (stub->isGetProp_Unboxed()) {
receiver = ReceiverGuard(stub->toGetProp_Unboxed()->group(), nullptr);
} else if (stub->isSetProp_Unboxed()) { } else if (stub->isSetProp_Unboxed()) {
receiver = ReceiverGuard(stub->toSetProp_Unboxed()->group(), nullptr); receiver = ReceiverGuard(stub->toSetProp_Unboxed()->group(), nullptr);
} else { } else {
@ -805,7 +827,6 @@ BaselineInspector::expectedPropertyAccessInputType(jsbytecode* pc)
// Either an object or magic arguments. // Either an object or magic arguments.
return MIRType::Value; return MIRType::Value;
case ICStub::GetProp_Unboxed:
case ICStub::GetProp_TypedObject: case ICStub::GetProp_TypedObject:
case ICStub::GetProp_CallScripted: case ICStub::GetProp_CallScripted:
case ICStub::GetProp_CallNative: case ICStub::GetProp_CallNative:

Просмотреть файл

@ -60,6 +60,8 @@ GetPropIRGenerator::tryAttachStub(Maybe<CacheIRWriter>& writer)
return false; return false;
if (!emitted_ && !tryAttachNative(*writer, obj, objId)) if (!emitted_ && !tryAttachNative(*writer, obj, objId))
return false; return false;
if (!emitted_ && !tryAttachUnboxed(*writer, obj, objId))
return false;
if (!emitted_ && !tryAttachUnboxedExpando(*writer, obj, objId)) if (!emitted_ && !tryAttachUnboxedExpando(*writer, obj, objId))
return false; return false;
if (!emitted_ && !tryAttachModuleNamespace(*writer, obj, objId)) if (!emitted_ && !tryAttachModuleNamespace(*writer, obj, objId))
@ -257,6 +259,29 @@ GetPropIRGenerator::tryAttachNative(CacheIRWriter& writer, HandleObject obj, Obj
return true; return true;
} }
bool
GetPropIRGenerator::tryAttachUnboxed(CacheIRWriter& writer, HandleObject obj, ObjOperandId objId)
{
MOZ_ASSERT(!emitted_);
if (!obj->is<UnboxedPlainObject>())
return true;
const UnboxedLayout::Property* property = obj->as<UnboxedPlainObject>().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 bool
GetPropIRGenerator::tryAttachUnboxedExpando(CacheIRWriter& writer, HandleObject obj, ObjOperandId objId) GetPropIRGenerator::tryAttachUnboxedExpando(CacheIRWriter& writer, HandleObject obj, ObjOperandId objId)
{ {

Просмотреть файл

@ -91,6 +91,7 @@ class ObjOperandId : public OperandId
_(LoadUnboxedExpando) \ _(LoadUnboxedExpando) \
_(LoadFixedSlotResult) \ _(LoadFixedSlotResult) \
_(LoadDynamicSlotResult) \ _(LoadDynamicSlotResult) \
_(LoadUnboxedPropertyResult) \
_(LoadInt32ArrayLengthResult) \ _(LoadInt32ArrayLengthResult) \
_(LoadUnboxedArrayLengthResult) \ _(LoadUnboxedArrayLengthResult) \
_(LoadArgumentsObjectLengthResult) \ _(LoadArgumentsObjectLengthResult) \
@ -304,6 +305,11 @@ class MOZ_RAII CacheIRWriter
writeOpWithOperandId(CacheOp::LoadDynamicSlotResult, obj); writeOpWithOperandId(CacheOp::LoadDynamicSlotResult, obj);
addStubWord(offset, StubField::GCType::NoGCThing); 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) { void loadInt32ArrayLengthResult(ObjOperandId obj) {
writeOpWithOperandId(CacheOp::LoadInt32ArrayLengthResult, obj); writeOpWithOperandId(CacheOp::LoadInt32ArrayLengthResult, obj);
} }
@ -349,6 +355,7 @@ class MOZ_RAII CacheIRReader
uint32_t stubOffset() { return buffer_.readByte(); } uint32_t stubOffset() { return buffer_.readByte(); }
GuardClassKind guardClassKind() { return GuardClassKind(buffer_.readByte()); } GuardClassKind guardClassKind() { return GuardClassKind(buffer_.readByte()); }
JSValueType valueType() { return JSValueType(buffer_.readByte()); }
bool matchOp(CacheOp op) { bool matchOp(CacheOp op) {
const uint8_t* pos = buffer_.currentPosition(); const uint8_t* pos = buffer_.currentPosition();
@ -388,6 +395,7 @@ class MOZ_RAII GetPropIRGenerator
PreliminaryObjectAction preliminaryObjectAction_; PreliminaryObjectAction preliminaryObjectAction_;
bool tryAttachNative(CacheIRWriter& writer, HandleObject obj, ObjOperandId objId); 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 tryAttachUnboxedExpando(CacheIRWriter& writer, HandleObject obj, ObjOperandId objId);
bool tryAttachObjectLength(CacheIRWriter& writer, HandleObject obj, ObjOperandId objId); bool tryAttachObjectLength(CacheIRWriter& writer, HandleObject obj, ObjOperandId objId);
bool tryAttachModuleNamespace(CacheIRWriter& writer, HandleObject obj, ObjOperandId objId); bool tryAttachModuleNamespace(CacheIRWriter& writer, HandleObject obj, ObjOperandId objId);

Просмотреть файл

@ -404,11 +404,6 @@ ICStub::trace(JSTracer* trc)
TraceEdge(trc, &propStub->protoShape(), "baseline-getprop-primitive-stub-shape"); TraceEdge(trc, &propStub->protoShape(), "baseline-getprop-primitive-stub-shape");
break; break;
} }
case ICStub::GetProp_Unboxed: {
ICGetProp_Unboxed* propStub = toGetProp_Unboxed();
TraceEdge(trc, &propStub->group(), "baseline-getprop-unboxed-stub-group");
break;
}
case ICStub::GetProp_TypedObject: { case ICStub::GetProp_TypedObject: {
ICGetProp_TypedObject* propStub = toGetProp_TypedObject(); ICGetProp_TypedObject* propStub = toGetProp_TypedObject();
TraceEdge(trc, &propStub->shape(), "baseline-getprop-typedobject-stub-shape"); TraceEdge(trc, &propStub->shape(), "baseline-getprop-typedobject-stub-shape");
@ -2554,40 +2549,6 @@ TryAttachNativeGetAccessorPropStub(JSContext* cx, SharedStubInfo* info,
return true; 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<UnboxedPlainObject>())
return true;
Rooted<UnboxedPlainObject*> obj(cx, &val.toObject().as<UnboxedPlainObject>());
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 static bool
TryAttachTypedObjectGetPropStub(JSContext* cx, SharedStubInfo* info, TryAttachTypedObjectGetPropStub(JSContext* cx, SharedStubInfo* info,
ICGetProp_Fallback* stub, HandlePropertyName name, ICGetProp_Fallback* stub, HandlePropertyName name,
@ -2861,11 +2822,6 @@ DoGetPropFallback(JSContext* cx, void* payload, ICGetProp_Fallback* stub_,
return true; return true;
if (!TryAttachUnboxedGetPropStub(cx, &info, stub, name, val, &attached))
return false;
if (attached)
return true;
if (!TryAttachTypedObjectGetPropStub(cx, &info, stub, name, val, &attached)) if (!TryAttachTypedObjectGetPropStub(cx, &info, stub, name, val, &attached))
return false; return false;
if (attached) if (attached)
@ -3754,39 +3710,6 @@ ICGetProp_Generic::Compiler::generateStubCode(MacroAssembler& masm)
return true; 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 void
CheckForTypedObjectWithDetachedStorage(JSContext* cx, MacroAssembler& masm, Label* failure) CheckForTypedObjectWithDetachedStorage(JSContext* cx, MacroAssembler& masm, Label* failure)
{ {

Просмотреть файл

@ -2595,65 +2595,6 @@ class ICGetPropNativeCompiler : public ICStubCompiler
ICGetPropNativeStub* getStub(ICStubSpace* space); 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<int32_t>(engine_) |
(static_cast<int32_t>(kind) << 1) |
(static_cast<int32_t>(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<ICGetProp_Unboxed>(space, getStubCode(), firstMonitorStub_, group_,
fieldOffset_);
}
};
};
static uint32_t static uint32_t
SimpleTypeDescrKey(SimpleTypeDescr* descr) SimpleTypeDescrKey(SimpleTypeDescr* descr)
{ {

Просмотреть файл

@ -37,7 +37,6 @@ namespace jit {
_(GetProp_Fallback) \ _(GetProp_Fallback) \
_(GetProp_Primitive) \ _(GetProp_Primitive) \
_(GetProp_StringLength) \ _(GetProp_StringLength) \
_(GetProp_Unboxed) \
_(GetProp_TypedObject) \ _(GetProp_TypedObject) \
_(GetProp_CallScripted) \ _(GetProp_CallScripted) \
_(GetProp_CallNative) \ _(GetProp_CallNative) \