mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 609296 - Make accessing properties like toString on numbers/booleans fast. r=bhackett
This commit is contained in:
parent
f322dc55d3
commit
d4bfe37616
@ -316,9 +316,9 @@ ICStub::trace(JSTracer *trc)
|
||||
gc::MarkValue(trc, &constantStub->value(), "baseline-getintrinsic-constant-value");
|
||||
break;
|
||||
}
|
||||
case ICStub::GetProp_String: {
|
||||
ICGetProp_String *propStub = toGetProp_String();
|
||||
MarkShape(trc, &propStub->stringProtoShape(), "baseline-getpropstring-stub-shape");
|
||||
case ICStub::GetProp_Primitive: {
|
||||
ICGetProp_Primitive *propStub = toGetProp_Primitive();
|
||||
MarkShape(trc, &propStub->protoShape(), "baseline-getprop-primitive-stub-shape");
|
||||
break;
|
||||
}
|
||||
case ICStub::GetProp_Native: {
|
||||
@ -6156,35 +6156,47 @@ TryAttachNativeGetPropStub(JSContext *cx, HandleScript script, jsbytecode *pc,
|
||||
}
|
||||
|
||||
static bool
|
||||
TryAttachStringGetPropStub(JSContext *cx, HandleScript script, jsbytecode *pc,
|
||||
ICGetProp_Fallback *stub, HandlePropertyName name, HandleValue val,
|
||||
HandleValue res, bool *attached)
|
||||
TryAttachPrimitiveGetPropStub(JSContext *cx, HandleScript script, jsbytecode *pc,
|
||||
ICGetProp_Fallback *stub, HandlePropertyName name, HandleValue val,
|
||||
HandleValue res, bool *attached)
|
||||
{
|
||||
JS_ASSERT(!*attached);
|
||||
JS_ASSERT(val.isString());
|
||||
|
||||
RootedObject stringProto(cx, script->global().getOrCreateStringPrototype(cx));
|
||||
if (!stringProto)
|
||||
JSValueType primitiveType;
|
||||
RootedObject proto(cx);
|
||||
if (val.isString()) {
|
||||
primitiveType = JSVAL_TYPE_STRING;
|
||||
proto = script->global().getOrCreateStringPrototype(cx);
|
||||
} else if (val.isNumber()) {
|
||||
primitiveType = JSVAL_TYPE_DOUBLE;
|
||||
proto = script->global().getOrCreateNumberPrototype(cx);
|
||||
} else {
|
||||
JS_ASSERT(val.isBoolean());
|
||||
primitiveType = JSVAL_TYPE_BOOLEAN;
|
||||
proto = script->global().getOrCreateBooleanPrototype(cx);
|
||||
}
|
||||
if (!proto)
|
||||
return false;
|
||||
|
||||
// Instantiate this property, for use during Ion compilation.
|
||||
RootedId id(cx, NameToId(name));
|
||||
if (IsIonEnabled(cx))
|
||||
types::EnsureTrackPropertyTypes(cx, stringProto, NameToId(name));
|
||||
types::EnsureTrackPropertyTypes(cx, proto, id);
|
||||
|
||||
// For now, only look for properties directly set on String.prototype
|
||||
RootedId propId(cx, NameToId(name));
|
||||
RootedShape shape(cx, stringProto->nativeLookup(cx, propId));
|
||||
// For now, only look for properties directly set on the prototype.
|
||||
RootedShape shape(cx, proto->nativeLookup(cx, id));
|
||||
if (!shape || !shape->hasSlot() || !shape->hasDefaultGetter())
|
||||
return true;
|
||||
|
||||
bool isFixedSlot;
|
||||
uint32_t offset;
|
||||
GetFixedOrDynamicSlotOffset(stringProto, shape->slot(), &isFixedSlot, &offset);
|
||||
GetFixedOrDynamicSlotOffset(proto, shape->slot(), &isFixedSlot, &offset);
|
||||
|
||||
ICStub *monitorStub = stub->fallbackMonitorStub()->firstMonitorStub();
|
||||
|
||||
IonSpew(IonSpew_BaselineIC, " Generating GetProp(String.ID from prototype) stub");
|
||||
ICGetProp_String::Compiler compiler(cx, monitorStub, stringProto, isFixedSlot, offset);
|
||||
IonSpew(IonSpew_BaselineIC, " Generating GetProp_Primitive stub");
|
||||
ICGetProp_Primitive::Compiler compiler(cx, monitorStub, primitiveType, proto,
|
||||
isFixedSlot, offset);
|
||||
ICStub *newStub = compiler.getStub(compiler.getStubSpace(script));
|
||||
if (!newStub)
|
||||
return false;
|
||||
@ -6267,8 +6279,8 @@ DoGetPropFallback(JSContext *cx, BaselineFrame *frame, ICGetProp_Fallback *stub,
|
||||
if (attached)
|
||||
return true;
|
||||
|
||||
if (val.isString()) {
|
||||
if (!TryAttachStringGetPropStub(cx, script, pc, stub, name, val, res, &attached))
|
||||
if (val.isString() || val.isNumber() || val.isBoolean()) {
|
||||
if (!TryAttachPrimitiveGetPropStub(cx, script, pc, stub, name, val, res, &attached))
|
||||
return false;
|
||||
if (attached)
|
||||
return true;
|
||||
@ -6409,19 +6421,31 @@ ICGetProp_StringLength::Compiler::generateStubCode(MacroAssembler &masm)
|
||||
}
|
||||
|
||||
bool
|
||||
ICGetProp_String::Compiler::generateStubCode(MacroAssembler &masm)
|
||||
ICGetProp_Primitive::Compiler::generateStubCode(MacroAssembler &masm)
|
||||
{
|
||||
Label failure;
|
||||
masm.branchTestString(Assembler::NotEqual, R0, &failure);
|
||||
switch (primitiveType_) {
|
||||
case JSVAL_TYPE_STRING:
|
||||
masm.branchTestString(Assembler::NotEqual, R0, &failure);
|
||||
break;
|
||||
case JSVAL_TYPE_DOUBLE: // Also used for int32.
|
||||
masm.branchTestNumber(Assembler::NotEqual, R0, &failure);
|
||||
break;
|
||||
case JSVAL_TYPE_BOOLEAN:
|
||||
masm.branchTestBoolean(Assembler::NotEqual, R0, &failure);
|
||||
break;
|
||||
default:
|
||||
MOZ_ASSUME_UNREACHABLE("unexpected type");
|
||||
}
|
||||
|
||||
GeneralRegisterSet regs(availableGeneralRegs(1));
|
||||
Register holderReg = regs.takeAny();
|
||||
Register scratchReg = regs.takeAny();
|
||||
|
||||
// Verify the shape of |String.prototype|
|
||||
masm.movePtr(ImmGCPtr(stringPrototype_.get()), holderReg);
|
||||
// Verify the shape of the prototype.
|
||||
masm.movePtr(ImmGCPtr(prototype_.get()), holderReg);
|
||||
|
||||
Address shapeAddr(BaselineStubReg, ICGetProp_String::offsetOfStringProtoShape());
|
||||
Address shapeAddr(BaselineStubReg, ICGetProp_Primitive::offsetOfProtoShape());
|
||||
masm.loadPtr(Address(holderReg, JSObject::offsetOfShape()), scratchReg);
|
||||
masm.branchPtr(Assembler::NotEqual, shapeAddr, scratchReg, &failure);
|
||||
|
||||
@ -9593,10 +9617,10 @@ ICGetIntrinsic_Constant::ICGetIntrinsic_Constant(IonCode *stubCode, HandleValue
|
||||
ICGetIntrinsic_Constant::~ICGetIntrinsic_Constant()
|
||||
{ }
|
||||
|
||||
ICGetProp_String::ICGetProp_String(IonCode *stubCode, ICStub *firstMonitorStub,
|
||||
HandleShape stringProtoShape, uint32_t offset)
|
||||
: ICMonitoredStub(GetProp_String, stubCode, firstMonitorStub),
|
||||
stringProtoShape_(stringProtoShape),
|
||||
ICGetProp_Primitive::ICGetProp_Primitive(IonCode *stubCode, ICStub *firstMonitorStub,
|
||||
HandleShape protoShape, uint32_t offset)
|
||||
: ICMonitoredStub(GetProp_Primitive, stubCode, firstMonitorStub),
|
||||
protoShape_(protoShape),
|
||||
offset_(offset)
|
||||
{ }
|
||||
|
||||
|
@ -362,7 +362,7 @@ class ICEntry
|
||||
_(GetProp_Fallback) \
|
||||
_(GetProp_ArrayLength) \
|
||||
_(GetProp_TypedArrayLength) \
|
||||
_(GetProp_String) \
|
||||
_(GetProp_Primitive) \
|
||||
_(GetProp_StringLength) \
|
||||
_(GetProp_Native) \
|
||||
_(GetProp_NativePrototype) \
|
||||
@ -4105,44 +4105,45 @@ class ICGetProp_TypedArrayLength : public ICStub
|
||||
};
|
||||
};
|
||||
|
||||
// Stub for accessing a string's length.
|
||||
class ICGetProp_String : public ICMonitoredStub
|
||||
// Stub for accessing a property on a primitive's prototype.
|
||||
class ICGetProp_Primitive : public ICMonitoredStub
|
||||
{
|
||||
friend class ICStubSpace;
|
||||
|
||||
protected: // Protected to silence Clang warning.
|
||||
// Shape of String.prototype to check for.
|
||||
HeapPtrShape stringProtoShape_;
|
||||
// Shape of String.prototype/Number.prototype to check for.
|
||||
HeapPtrShape protoShape_;
|
||||
|
||||
// Fixed or dynamic slot offset.
|
||||
uint32_t offset_;
|
||||
|
||||
ICGetProp_String(IonCode *stubCode, ICStub *firstMonitorStub,
|
||||
HandleShape stringProtoShape, uint32_t offset);
|
||||
ICGetProp_Primitive(IonCode *stubCode, ICStub *firstMonitorStub,
|
||||
HandleShape protoShape, uint32_t offset);
|
||||
|
||||
public:
|
||||
static inline ICGetProp_String *New(ICStubSpace *space, IonCode *code, ICStub *firstMonitorStub,
|
||||
HandleShape stringProtoShape, uint32_t offset)
|
||||
static inline ICGetProp_Primitive *New(ICStubSpace *space, IonCode *code, ICStub *firstMonitorStub,
|
||||
HandleShape protoShape, uint32_t offset)
|
||||
{
|
||||
if (!code)
|
||||
return nullptr;
|
||||
return space->allocate<ICGetProp_String>(code, firstMonitorStub, stringProtoShape, offset);
|
||||
return space->allocate<ICGetProp_Primitive>(code, firstMonitorStub, protoShape, offset);
|
||||
}
|
||||
|
||||
HeapPtrShape &stringProtoShape() {
|
||||
return stringProtoShape_;
|
||||
HeapPtrShape &protoShape() {
|
||||
return protoShape_;
|
||||
}
|
||||
static size_t offsetOfStringProtoShape() {
|
||||
return offsetof(ICGetProp_String, stringProtoShape_);
|
||||
static size_t offsetOfProtoShape() {
|
||||
return offsetof(ICGetProp_Primitive, protoShape_);
|
||||
}
|
||||
|
||||
static size_t offsetOfOffset() {
|
||||
return offsetof(ICGetProp_String, offset_);
|
||||
return offsetof(ICGetProp_Primitive, offset_);
|
||||
}
|
||||
|
||||
class Compiler : public ICStubCompiler {
|
||||
ICStub *firstMonitorStub_;
|
||||
RootedObject stringPrototype_;
|
||||
JSValueType primitiveType_;
|
||||
RootedObject prototype_;
|
||||
bool isFixedSlot_;
|
||||
uint32_t offset_;
|
||||
|
||||
@ -4150,23 +4151,27 @@ class ICGetProp_String : public ICMonitoredStub
|
||||
|
||||
protected:
|
||||
virtual int32_t getKey() const {
|
||||
return static_cast<int32_t>(kind) | (static_cast<int32_t>(isFixedSlot_) << 16);
|
||||
static_assert(sizeof(JSValueType) == 1, "JSValueType should fit in one byte");
|
||||
return static_cast<int32_t>(kind)
|
||||
| (static_cast<int32_t>(isFixedSlot_) << 16)
|
||||
| (static_cast<int32_t>(primitiveType_) << 24);
|
||||
}
|
||||
|
||||
public:
|
||||
Compiler(JSContext *cx, ICStub *firstMonitorStub, HandleObject stringPrototype,
|
||||
bool isFixedSlot, uint32_t offset)
|
||||
: ICStubCompiler(cx, ICStub::GetProp_String),
|
||||
Compiler(JSContext *cx, ICStub *firstMonitorStub, JSValueType primitiveType,
|
||||
HandleObject prototype, bool isFixedSlot, uint32_t offset)
|
||||
: ICStubCompiler(cx, ICStub::GetProp_Primitive),
|
||||
firstMonitorStub_(firstMonitorStub),
|
||||
stringPrototype_(cx, stringPrototype),
|
||||
primitiveType_(primitiveType),
|
||||
prototype_(cx, prototype),
|
||||
isFixedSlot_(isFixedSlot),
|
||||
offset_(offset)
|
||||
{}
|
||||
|
||||
ICStub *getStub(ICStubSpace *space) {
|
||||
RootedShape stringProtoShape(cx, stringPrototype_->lastProperty());
|
||||
return ICGetProp_String::New(space, getStubCode(), firstMonitorStub_,
|
||||
stringProtoShape, offset_);
|
||||
RootedShape protoShape(cx, prototype_->lastProperty());
|
||||
return ICGetProp_Primitive::New(space, getStubCode(), firstMonitorStub_,
|
||||
protoShape, offset_);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
@ -6051,10 +6051,6 @@ IonBuilder::testSingletonPropertyTypes(MDefinition *obj, JSObject *singleton, Pr
|
||||
*testString = false;
|
||||
|
||||
types::TemporaryTypeSet *types = obj->resultTypeSet();
|
||||
|
||||
if (!types && obj->type() != MIRType_String)
|
||||
return false;
|
||||
|
||||
if (types && types->unknownObject())
|
||||
return false;
|
||||
|
||||
@ -6079,6 +6075,9 @@ IonBuilder::testSingletonPropertyTypes(MDefinition *obj, JSObject *singleton, Pr
|
||||
|
||||
case MIRType_Object:
|
||||
case MIRType_Value: {
|
||||
if (!types)
|
||||
return false;
|
||||
|
||||
if (types->hasType(types::Type::StringType())) {
|
||||
key = JSProto_String;
|
||||
*testString = true;
|
||||
|
Loading…
Reference in New Issue
Block a user