mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1038859 - Add symbol-support to Baseline GetElem ICs. r=djvj
This commit is contained in:
parent
3ae4431867
commit
7feca651b8
@ -688,8 +688,10 @@ RecompileBaselineScriptForDebugMode(JSContext* cx, JSScript* script,
|
||||
_(Call_ScriptedApplyArray) \
|
||||
_(Call_ScriptedApplyArguments) \
|
||||
_(Call_ScriptedFunCall) \
|
||||
_(GetElem_NativePrototypeCallNative) \
|
||||
_(GetElem_NativePrototypeCallScripted) \
|
||||
_(GetElem_NativePrototypeCallNativeName) \
|
||||
_(GetElem_NativePrototypeCallNativeSymbol) \
|
||||
_(GetElem_NativePrototypeCallScriptedName) \
|
||||
_(GetElem_NativePrototypeCallScriptedSymbol) \
|
||||
_(GetProp_CallScripted) \
|
||||
_(GetProp_CallNative) \
|
||||
_(GetProp_CallDOMProxyNative) \
|
||||
|
@ -2653,7 +2653,7 @@ CheckDOMProxyExpandoDoesNotShadow(JSContext* cx, MacroAssembler& masm, Register
|
||||
// operations. This procedure not yielding a shape should not be taken as a lack of
|
||||
// existence of the property on the object.
|
||||
static bool
|
||||
EffectlesslyLookupProperty(JSContext* cx, HandleObject obj, HandlePropertyName name,
|
||||
EffectlesslyLookupProperty(JSContext* cx, HandleObject obj, HandleId id,
|
||||
MutableHandleObject holder, MutableHandleShape shape,
|
||||
bool* checkDOMProxy=nullptr,
|
||||
DOMProxyShadowsResult* shadowsResult=nullptr,
|
||||
@ -2677,7 +2677,6 @@ EffectlesslyLookupProperty(JSContext* cx, HandleObject obj, HandlePropertyName n
|
||||
if (obj->hasUncacheableProto())
|
||||
return true;
|
||||
|
||||
RootedId id(cx, NameToId(name));
|
||||
*shadowsResult = GetDOMProxyShadowsCheck()(cx, obj, id);
|
||||
if (*shadowsResult == ShadowCheckFailed)
|
||||
return false;
|
||||
@ -2694,7 +2693,7 @@ EffectlesslyLookupProperty(JSContext* cx, HandleObject obj, HandlePropertyName n
|
||||
return true;
|
||||
}
|
||||
|
||||
if (LookupPropertyPure(cx, checkObj, NameToId(name), holder.address(), shape.address()))
|
||||
if (LookupPropertyPure(cx, checkObj, id, holder.address(), shape.address()))
|
||||
return true;
|
||||
|
||||
holder.set(nullptr);
|
||||
@ -2970,31 +2969,47 @@ typedef bool (*LookupNoSuchMethodHandlerFn)(JSContext*, HandleObject, HandleValu
|
||||
static const VMFunction LookupNoSuchMethodHandlerInfo =
|
||||
FunctionInfo<LookupNoSuchMethodHandlerFn>(LookupNoSuchMethodHandler);
|
||||
|
||||
|
||||
template <class T>
|
||||
static bool
|
||||
GetElemNativeStubExists(ICGetElem_Fallback* stub, HandleObject obj, HandleObject holder,
|
||||
HandlePropertyName propName, bool needsAtomize)
|
||||
Handle<T> key, bool needsAtomize)
|
||||
{
|
||||
bool indirect = (obj.get() != holder.get());
|
||||
MOZ_ASSERT_IF(indirect, holder->isNative());
|
||||
|
||||
for (ICStubConstIterator iter = stub->beginChainConst(); !iter.atEnd(); iter++) {
|
||||
if (iter->kind() != ICStub::GetElem_NativeSlot &&
|
||||
iter->kind() != ICStub::GetElem_NativePrototypeSlot &&
|
||||
iter->kind() != ICStub::GetElem_NativePrototypeCallNative &&
|
||||
iter->kind() != ICStub::GetElem_NativePrototypeCallScripted)
|
||||
if (iter->kind() != ICStub::GetElem_NativeSlotName &&
|
||||
iter->kind() != ICStub::GetElem_NativeSlotSymbol &&
|
||||
iter->kind() != ICStub::GetElem_NativePrototypeSlotName &&
|
||||
iter->kind() != ICStub::GetElem_NativePrototypeSlotSymbol &&
|
||||
iter->kind() != ICStub::GetElem_NativePrototypeCallNativeName &&
|
||||
iter->kind() != ICStub::GetElem_NativePrototypeCallNativeSymbol &&
|
||||
iter->kind() != ICStub::GetElem_NativePrototypeCallScriptedName &&
|
||||
iter->kind() != ICStub::GetElem_NativePrototypeCallScriptedSymbol)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (indirect && (iter->kind() != ICStub::GetElem_NativePrototypeSlot &&
|
||||
iter->kind() != ICStub::GetElem_NativePrototypeCallNative &&
|
||||
iter->kind() != ICStub::GetElem_NativePrototypeCallScripted))
|
||||
if (indirect && (iter->kind() != ICStub::GetElem_NativePrototypeSlotName &&
|
||||
iter->kind() != ICStub::GetElem_NativePrototypeSlotSymbol &&
|
||||
iter->kind() != ICStub::GetElem_NativePrototypeCallNativeName &&
|
||||
iter->kind() != ICStub::GetElem_NativePrototypeCallNativeSymbol &&
|
||||
iter->kind() != ICStub::GetElem_NativePrototypeCallScriptedName &&
|
||||
iter->kind() != ICStub::GetElem_NativePrototypeCallScriptedSymbol))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
ICGetElemNativeStub* getElemNativeStub = reinterpret_cast<ICGetElemNativeStub*>(*iter);
|
||||
if (propName != getElemNativeStub->name())
|
||||
if(mozilla::IsSame<T, JS::Symbol*>::value !=
|
||||
static_cast<ICGetElemNativeStub*>(*iter)->isSymbol())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
ICGetElemNativeStubImpl<T>* getElemNativeStub =
|
||||
reinterpret_cast<ICGetElemNativeStubImpl<T>*>(*iter);
|
||||
if (key != getElemNativeStub->key())
|
||||
continue;
|
||||
|
||||
if (ReceiverGuard(obj) != getElemNativeStub->receiverGuard())
|
||||
@ -3007,8 +3022,10 @@ GetElemNativeStubExists(ICGetElem_Fallback* stub, HandleObject obj, HandleObject
|
||||
|
||||
// For prototype gets, check the holder and holder shape.
|
||||
if (indirect) {
|
||||
if (iter->isGetElem_NativePrototypeSlot()) {
|
||||
ICGetElem_NativePrototypeSlot* protoStub = iter->toGetElem_NativePrototypeSlot();
|
||||
if (iter->isGetElem_NativePrototypeSlotName() ||
|
||||
iter->isGetElem_NativePrototypeSlotSymbol()) {
|
||||
ICGetElem_NativePrototypeSlot<T>* protoStub =
|
||||
reinterpret_cast<ICGetElem_NativePrototypeSlot<T>*>(*iter);
|
||||
|
||||
if (holder != protoStub->holder())
|
||||
continue;
|
||||
@ -3016,11 +3033,13 @@ GetElemNativeStubExists(ICGetElem_Fallback* stub, HandleObject obj, HandleObject
|
||||
if (holder->as<NativeObject>().lastProperty() != protoStub->holderShape())
|
||||
continue;
|
||||
} else {
|
||||
MOZ_ASSERT(iter->isGetElem_NativePrototypeCallNative() ||
|
||||
iter->isGetElem_NativePrototypeCallScripted());
|
||||
MOZ_ASSERT(iter->isGetElem_NativePrototypeCallNativeName() ||
|
||||
iter->isGetElem_NativePrototypeCallNativeSymbol() ||
|
||||
iter->isGetElem_NativePrototypeCallScriptedName() ||
|
||||
iter->isGetElem_NativePrototypeCallScriptedSymbol());
|
||||
|
||||
ICGetElemNativePrototypeCallStub* protoStub =
|
||||
reinterpret_cast<ICGetElemNativePrototypeCallStub*>(*iter);
|
||||
ICGetElemNativePrototypeCallStub<T>* protoStub =
|
||||
reinterpret_cast<ICGetElemNativePrototypeCallStub<T>*>(*iter);
|
||||
|
||||
if (holder != protoStub->holder())
|
||||
continue;
|
||||
@ -3035,29 +3054,40 @@ GetElemNativeStubExists(ICGetElem_Fallback* stub, HandleObject obj, HandleObject
|
||||
return false;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static void
|
||||
RemoveExistingGetElemNativeStubs(JSContext* cx, ICGetElem_Fallback* stub, HandleObject obj,
|
||||
HandleObject holder, HandlePropertyName propName,
|
||||
bool needsAtomize)
|
||||
HandleObject holder, Handle<T> key, bool needsAtomize)
|
||||
{
|
||||
bool indirect = (obj.get() != holder.get());
|
||||
MOZ_ASSERT_IF(indirect, holder->isNative());
|
||||
|
||||
for (ICStubIterator iter = stub->beginChain(); !iter.atEnd(); iter++) {
|
||||
switch (iter->kind()) {
|
||||
case ICStub::GetElem_NativeSlot:
|
||||
case ICStub::GetElem_NativeSlotName:
|
||||
case ICStub::GetElem_NativeSlotSymbol:
|
||||
if (indirect)
|
||||
continue;
|
||||
case ICStub::GetElem_NativePrototypeSlot:
|
||||
case ICStub::GetElem_NativePrototypeCallNative:
|
||||
case ICStub::GetElem_NativePrototypeCallScripted:
|
||||
case ICStub::GetElem_NativePrototypeSlotName:
|
||||
case ICStub::GetElem_NativePrototypeSlotSymbol:
|
||||
case ICStub::GetElem_NativePrototypeCallNativeName:
|
||||
case ICStub::GetElem_NativePrototypeCallNativeSymbol:
|
||||
case ICStub::GetElem_NativePrototypeCallScriptedName:
|
||||
case ICStub::GetElem_NativePrototypeCallScriptedSymbol:
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
|
||||
ICGetElemNativeStub* getElemNativeStub = reinterpret_cast<ICGetElemNativeStub*>(*iter);
|
||||
if (propName != getElemNativeStub->name())
|
||||
if(mozilla::IsSame<T, JS::Symbol*>::value !=
|
||||
static_cast<ICGetElemNativeStub*>(*iter)->isSymbol())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
ICGetElemNativeStubImpl<T>* getElemNativeStub =
|
||||
reinterpret_cast<ICGetElemNativeStubImpl<T>*>(*iter);
|
||||
if (key != getElemNativeStub->key())
|
||||
continue;
|
||||
|
||||
if (ReceiverGuard(obj) != getElemNativeStub->receiverGuard())
|
||||
@ -3065,8 +3095,10 @@ RemoveExistingGetElemNativeStubs(JSContext* cx, ICGetElem_Fallback* stub, Handle
|
||||
|
||||
// For prototype gets, check the holder and holder shape.
|
||||
if (indirect) {
|
||||
if (iter->isGetElem_NativePrototypeSlot()) {
|
||||
ICGetElem_NativePrototypeSlot* protoStub = iter->toGetElem_NativePrototypeSlot();
|
||||
if (iter->isGetElem_NativePrototypeSlotName() ||
|
||||
iter->isGetElem_NativePrototypeSlotSymbol()) {
|
||||
ICGetElem_NativePrototypeSlot<T>* protoStub =
|
||||
reinterpret_cast<ICGetElem_NativePrototypeSlot<T>*>(*iter);
|
||||
|
||||
if (holder != protoStub->holder())
|
||||
continue;
|
||||
@ -3078,11 +3110,12 @@ RemoveExistingGetElemNativeStubs(JSContext* cx, ICGetElem_Fallback* stub, Handle
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
MOZ_ASSERT(iter->isGetElem_NativePrototypeCallNative() ||
|
||||
iter->isGetElem_NativePrototypeCallScripted());
|
||||
|
||||
ICGetElemNativePrototypeCallStub* protoStub =
|
||||
reinterpret_cast<ICGetElemNativePrototypeCallStub*>(*iter);
|
||||
MOZ_ASSERT(iter->isGetElem_NativePrototypeCallNativeName() ||
|
||||
iter->isGetElem_NativePrototypeCallNativeSymbol() ||
|
||||
iter->isGetElem_NativePrototypeCallScriptedName() ||
|
||||
iter->isGetElem_NativePrototypeCallScriptedSymbol());
|
||||
ICGetElemNativePrototypeCallStub<T>* protoStub =
|
||||
reinterpret_cast<ICGetElemNativePrototypeCallStub<T>*>(*iter);
|
||||
|
||||
if (holder != protoStub->holder())
|
||||
continue;
|
||||
@ -3133,6 +3166,31 @@ ArgumentsGetElemStubExists(ICGetElem_Fallback* stub, ICGetElem_Arguments::Which
|
||||
return false;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static T
|
||||
getKey(jsid id)
|
||||
{
|
||||
MOZ_ASSERT_UNREACHABLE("Key has to be PropertyName or Symbol");
|
||||
return false;
|
||||
}
|
||||
|
||||
template <>
|
||||
JS::Symbol* getKey<JS::Symbol*>(jsid id)
|
||||
{
|
||||
if (!JSID_IS_SYMBOL(id))
|
||||
return nullptr;
|
||||
return JSID_TO_SYMBOL(id);
|
||||
}
|
||||
|
||||
template <>
|
||||
PropertyName* getKey<PropertyName*>(jsid id)
|
||||
{
|
||||
uint32_t dummy;
|
||||
if (!JSID_IS_ATOM(id) || JSID_TO_ATOM(id)->isIndex(&dummy))
|
||||
return nullptr;
|
||||
return JSID_TO_ATOM(id)->asPropertyName();
|
||||
}
|
||||
|
||||
static bool
|
||||
IsOptimizableElementPropertyName(JSContext* cx, HandleValue key, MutableHandleId idp)
|
||||
{
|
||||
@ -3150,47 +3208,79 @@ IsOptimizableElementPropertyName(JSContext* cx, HandleValue key, MutableHandleId
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static bool
|
||||
checkAtomize(HandleValue key)
|
||||
{
|
||||
MOZ_ASSERT_UNREACHABLE("Key has to be PropertyName or Symbol");
|
||||
return false;
|
||||
}
|
||||
|
||||
template <>
|
||||
bool checkAtomize<JS::Symbol*>(HandleValue key)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
template <>
|
||||
bool checkAtomize<PropertyName*>(HandleValue key)
|
||||
{
|
||||
return !key.toString()->isAtom();
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static bool
|
||||
TryAttachNativeOrUnboxedGetValueElemStub(JSContext* cx, HandleScript script, jsbytecode* pc,
|
||||
ICGetElem_Fallback* stub, HandleObject obj,
|
||||
HandleValue key, bool* attached)
|
||||
HandleValue keyVal, bool* attached)
|
||||
{
|
||||
RootedId id(cx);
|
||||
if (!IsOptimizableElementPropertyName(cx, key, &id))
|
||||
return true;
|
||||
MOZ_ASSERT(keyVal.isString() || keyVal.isSymbol());
|
||||
|
||||
RootedPropertyName propName(cx, JSID_TO_ATOM(id)->asPropertyName());
|
||||
bool needsAtomize = !key.toString()->isAtom();
|
||||
// Convert to id.
|
||||
RootedId id(cx);
|
||||
if (!ValueToId<CanGC>(cx, keyVal, &id))
|
||||
return false;
|
||||
|
||||
Rooted<T> key(cx, getKey<T>(id));
|
||||
if (!key)
|
||||
return true;
|
||||
bool needsAtomize = checkAtomize<T>(keyVal);
|
||||
bool isCallElem = (JSOp(*pc) == JSOP_CALLELEM);
|
||||
|
||||
RootedShape shape(cx);
|
||||
RootedObject holder(cx);
|
||||
if (!EffectlesslyLookupProperty(cx, obj, propName, &holder, &shape))
|
||||
if (!EffectlesslyLookupProperty(cx, obj, id, &holder, &shape))
|
||||
return false;
|
||||
if (!holder || (holder != obj && !holder->isNative()))
|
||||
return true;
|
||||
|
||||
// If a suitable stub already exists, nothing else to do.
|
||||
if (GetElemNativeStubExists(stub, obj, holder, propName, needsAtomize))
|
||||
if (GetElemNativeStubExists<T>(stub, obj, holder, key, needsAtomize))
|
||||
return true;
|
||||
|
||||
// Remove any existing stubs that may interfere with the new stub being added.
|
||||
RemoveExistingGetElemNativeStubs(cx, stub, obj, holder, propName, needsAtomize);
|
||||
RemoveExistingGetElemNativeStubs<T>(cx, stub, obj, holder, key, needsAtomize);
|
||||
|
||||
ICStub* monitorStub = stub->fallbackMonitorStub()->firstMonitorStub();
|
||||
|
||||
if (obj->is<UnboxedPlainObject>() && holder == obj) {
|
||||
const UnboxedLayout::Property* property =
|
||||
obj->as<UnboxedPlainObject>().layout().lookup(propName);
|
||||
const UnboxedLayout::Property* property = obj->as<UnboxedPlainObject>().layout().lookup(id);
|
||||
|
||||
// Once unboxed objects support symbol-keys, we need to change the following accordingly
|
||||
MOZ_ASSERT_IF(!keyVal.isString(), !property);
|
||||
|
||||
if (property) {
|
||||
if (!cx->runtime()->jitSupportsFloatingPoint)
|
||||
return true;
|
||||
|
||||
ICGetElemNativeCompiler compiler(cx, ICStub::GetElem_UnboxedProperty, isCallElem,
|
||||
monitorStub, obj, holder, propName,
|
||||
ICGetElemNativeStub::UnboxedProperty, needsAtomize,
|
||||
property->offset + UnboxedPlainObject::offsetOfData(),
|
||||
property->type);
|
||||
RootedPropertyName name(cx, JSID_TO_ATOM(id)->asPropertyName());
|
||||
ICGetElemNativeCompiler<PropertyName*> compiler(cx, ICStub::GetElem_UnboxedPropertyName,
|
||||
isCallElem, monitorStub, obj, holder,
|
||||
name,
|
||||
ICGetElemNativeStub::UnboxedProperty,
|
||||
needsAtomize, property->offset +
|
||||
UnboxedPlainObject::offsetOfData(),
|
||||
property->type);
|
||||
ICStub* newStub = compiler.getStub(compiler.getStubSpace(script));
|
||||
if (!newStub)
|
||||
return false;
|
||||
@ -3200,7 +3290,7 @@ TryAttachNativeOrUnboxedGetValueElemStub(JSContext* cx, HandleScript script, jsb
|
||||
return true;
|
||||
}
|
||||
|
||||
Shape* shape = obj->as<UnboxedPlainObject>().maybeExpando()->lookup(cx, propName);
|
||||
Shape* shape = obj->as<UnboxedPlainObject>().maybeExpando()->lookup(cx, id);
|
||||
if (!shape->hasDefaultGetter() || !shape->hasSlot())
|
||||
return true;
|
||||
|
||||
@ -3211,9 +3301,9 @@ TryAttachNativeOrUnboxedGetValueElemStub(JSContext* cx, HandleScript script, jsb
|
||||
ICGetElemNativeStub::AccessType acctype =
|
||||
isFixedSlot ? ICGetElemNativeStub::FixedSlot
|
||||
: ICGetElemNativeStub::DynamicSlot;
|
||||
ICGetElemNativeCompiler compiler(cx, ICStub::GetElem_NativeSlot, isCallElem,
|
||||
monitorStub, obj, holder, propName,
|
||||
acctype, needsAtomize, offset);
|
||||
ICGetElemNativeCompiler<T> compiler(cx, getGetElemStubKind<T>(ICStub::GetElem_NativeSlotName),
|
||||
isCallElem, monitorStub, obj, holder, key,
|
||||
acctype, needsAtomize, offset);
|
||||
ICStub* newStub = compiler.getStub(compiler.getStubSpace(script));
|
||||
if (!newStub)
|
||||
return false;
|
||||
@ -3231,8 +3321,9 @@ TryAttachNativeOrUnboxedGetValueElemStub(JSContext* cx, HandleScript script, jsb
|
||||
uint32_t offset;
|
||||
GetFixedOrDynamicSlotOffset(shape, &isFixedSlot, &offset);
|
||||
|
||||
ICStub::Kind kind = (obj == holder) ? ICStub::GetElem_NativeSlot
|
||||
: ICStub::GetElem_NativePrototypeSlot;
|
||||
ICStub::Kind kind = (obj == holder) ? ICStub::GetElem_NativeSlotName
|
||||
: ICStub::GetElem_NativePrototypeSlotName;
|
||||
kind = getGetElemStubKind<T>(kind);
|
||||
|
||||
JitSpew(JitSpew_BaselineIC, " Generating GetElem(Native %s%s slot) stub "
|
||||
"(obj=%p, holder=%p, holderShape=%p)",
|
||||
@ -3240,10 +3331,10 @@ TryAttachNativeOrUnboxedGetValueElemStub(JSContext* cx, HandleScript script, jsb
|
||||
needsAtomize ? " atomizing" : "",
|
||||
obj.get(), holder.get(), holder->as<NativeObject>().lastProperty());
|
||||
|
||||
ICGetElemNativeStub::AccessType acctype = isFixedSlot ? ICGetElemNativeStub::FixedSlot
|
||||
: ICGetElemNativeStub::DynamicSlot;
|
||||
ICGetElemNativeCompiler compiler(cx, kind, isCallElem, monitorStub, obj, holder, propName,
|
||||
acctype, needsAtomize, offset);
|
||||
AccType acctype = isFixedSlot ? ICGetElemNativeStub::FixedSlot
|
||||
: ICGetElemNativeStub::DynamicSlot;
|
||||
ICGetElemNativeCompiler<T> compiler(cx, kind, isCallElem, monitorStub, obj, holder, key,
|
||||
acctype, needsAtomize, offset);
|
||||
ICStub* newStub = compiler.getStub(compiler.getStubSpace(script));
|
||||
if (!newStub)
|
||||
return false;
|
||||
@ -3256,24 +3347,29 @@ TryAttachNativeOrUnboxedGetValueElemStub(JSContext* cx, HandleScript script, jsb
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static bool
|
||||
TryAttachNativeGetAccessorElemStub(JSContext* cx, HandleScript script, jsbytecode* pc,
|
||||
ICGetElem_Fallback* stub, HandleNativeObject obj,
|
||||
HandleValue key, bool* attached, bool* isTemporarilyUnoptimizable)
|
||||
HandleValue keyVal, bool* attached,
|
||||
bool* isTemporarilyUnoptimizable)
|
||||
{
|
||||
MOZ_ASSERT(!*attached);
|
||||
MOZ_ASSERT(keyVal.isString() || keyVal.isSymbol());
|
||||
|
||||
RootedId id(cx);
|
||||
if (!IsOptimizableElementPropertyName(cx, key, &id))
|
||||
return true;
|
||||
if (!ValueToId<CanGC>(cx, keyVal, &id))
|
||||
return false;
|
||||
|
||||
RootedPropertyName propName(cx, JSID_TO_ATOM(id)->asPropertyName());
|
||||
bool needsAtomize = !key.toString()->isAtom();
|
||||
Rooted<T> key(cx, getKey<T>(id));
|
||||
if (!key)
|
||||
return true;
|
||||
bool needsAtomize = checkAtomize<T>(keyVal);
|
||||
bool isCallElem = (JSOp(*pc) == JSOP_CALLELEM);
|
||||
|
||||
RootedShape shape(cx);
|
||||
RootedObject baseHolder(cx);
|
||||
if (!EffectlesslyLookupProperty(cx, obj, propName, &baseHolder, &shape))
|
||||
if (!EffectlesslyLookupProperty(cx, obj, id, &baseHolder, &shape))
|
||||
return false;
|
||||
if (!baseHolder || baseHolder->isNative())
|
||||
return true;
|
||||
@ -3298,15 +3394,16 @@ TryAttachNativeGetAccessorElemStub(JSContext* cx, HandleScript script, jsbytecod
|
||||
return true;
|
||||
|
||||
// If a suitable stub already exists, nothing else to do.
|
||||
if (GetElemNativeStubExists(stub, obj, holder, propName, needsAtomize))
|
||||
if (GetElemNativeStubExists<T>(stub, obj, holder, key, needsAtomize))
|
||||
return true;
|
||||
|
||||
// Remove any existing stubs that may interfere with the new stub being added.
|
||||
RemoveExistingGetElemNativeStubs(cx, stub, obj, holder, propName, needsAtomize);
|
||||
RemoveExistingGetElemNativeStubs<T>(cx, stub, obj, holder, key, needsAtomize);
|
||||
|
||||
ICStub* monitorStub = stub->fallbackMonitorStub()->firstMonitorStub();
|
||||
ICStub::Kind kind = getterIsScripted ? ICStub::GetElem_NativePrototypeCallScripted
|
||||
: ICStub::GetElem_NativePrototypeCallNative;
|
||||
ICStub::Kind kind = getterIsScripted ? ICStub::GetElem_NativePrototypeCallScriptedName
|
||||
: ICStub::GetElem_NativePrototypeCallNativeName;
|
||||
kind = getGetElemStubKind<T>(kind);
|
||||
|
||||
if (getterIsScripted) {
|
||||
JitSpew(JitSpew_BaselineIC,
|
||||
@ -3325,10 +3422,9 @@ TryAttachNativeGetAccessorElemStub(JSContext* cx, HandleScript script, jsbytecod
|
||||
obj.get(), obj->lastProperty(), holder.get(), holder->lastProperty());
|
||||
}
|
||||
|
||||
ICGetElemNativeStub::AccessType acctype = getterIsScripted
|
||||
? ICGetElemNativeStub::ScriptedGetter
|
||||
: ICGetElemNativeStub::NativeGetter;
|
||||
ICGetElemNativeCompiler compiler(cx, kind, monitorStub, obj, holder, propName, acctype,
|
||||
AccType acctype = getterIsScripted ? ICGetElemNativeStub::ScriptedGetter
|
||||
: ICGetElemNativeStub::NativeGetter;
|
||||
ICGetElemNativeCompiler<T> compiler(cx, kind, monitorStub, obj, holder, key, acctype,
|
||||
needsAtomize, getter, script->pcToOffset(pc), isCallElem);
|
||||
ICStub* newStub = compiler.getStub(compiler.getStubSpace(script));
|
||||
if (!newStub)
|
||||
@ -3476,12 +3572,20 @@ TryAttachGetElemStub(JSContext* cx, JSScript* script, jsbytecode* pc, ICGetElem_
|
||||
}
|
||||
|
||||
// Check for NativeObject[id] and UnboxedPlainObject[id] shape-optimizable accesses.
|
||||
if ((obj->isNative() || obj->is<UnboxedPlainObject>()) && rhs.isString()) {
|
||||
if (obj->isNative() || obj->is<UnboxedPlainObject>()) {
|
||||
RootedScript rootedScript(cx, script);
|
||||
if (!TryAttachNativeOrUnboxedGetValueElemStub(cx, rootedScript, pc, stub,
|
||||
obj, rhs, attached))
|
||||
{
|
||||
return false;
|
||||
if (rhs.isString()) {
|
||||
if (!TryAttachNativeOrUnboxedGetValueElemStub<PropertyName*>(cx, rootedScript, pc, stub,
|
||||
obj, rhs, attached))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
} else if (rhs.isSymbol()) {
|
||||
if (!TryAttachNativeOrUnboxedGetValueElemStub<JS::Symbol*>(cx, rootedScript, pc, stub,
|
||||
obj, rhs, attached))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (*attached)
|
||||
return true;
|
||||
@ -3587,15 +3691,28 @@ DoGetElemFallback(JSContext* cx, BaselineFrame* frame, ICGetElem_Fallback* stub_
|
||||
|
||||
// Try to attach an optimized getter stub.
|
||||
bool isTemporarilyUnoptimizable = false;
|
||||
if (!attached && lhs.isObject() && lhs.toObject().isNative() && rhs.isString()){
|
||||
RootedScript rootedScript(cx, frame->script());
|
||||
RootedNativeObject obj(cx, &lhs.toObject().as<NativeObject>());
|
||||
if (!TryAttachNativeGetAccessorElemStub(cx, rootedScript, pc, stub, obj, rhs, &attached,
|
||||
&isTemporarilyUnoptimizable))
|
||||
{
|
||||
return false;
|
||||
if (!attached && lhs.isObject() && lhs.toObject().isNative()){
|
||||
if (rhs.isString()) {
|
||||
RootedScript rootedScript(cx, frame->script());
|
||||
RootedNativeObject obj(cx, &lhs.toObject().as<NativeObject>());
|
||||
if (!TryAttachNativeGetAccessorElemStub<PropertyName*>(cx, rootedScript, pc, stub,
|
||||
obj, rhs, &attached,
|
||||
&isTemporarilyUnoptimizable))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
script = rootedScript;
|
||||
} else if (rhs.isSymbol()) {
|
||||
RootedScript rootedScript(cx, frame->script());
|
||||
RootedNativeObject obj(cx, &lhs.toObject().as<NativeObject>());
|
||||
if (!TryAttachNativeGetAccessorElemStub<JS::Symbol*>(cx, rootedScript, pc, stub,
|
||||
obj, rhs, &attached,
|
||||
&isTemporarilyUnoptimizable))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
script = rootedScript;
|
||||
}
|
||||
script = rootedScript;
|
||||
}
|
||||
|
||||
if (!isOptimizedArgs) {
|
||||
@ -3680,8 +3797,9 @@ DoAtomizeString(JSContext* cx, HandleString string, MutableHandleValue result)
|
||||
typedef bool (*DoAtomizeStringFn)(JSContext*, HandleString, MutableHandleValue);
|
||||
static const VMFunction DoAtomizeStringInfo = FunctionInfo<DoAtomizeStringFn>(DoAtomizeString);
|
||||
|
||||
template <class T>
|
||||
bool
|
||||
ICGetElemNativeCompiler::emitCallNative(MacroAssembler& masm, Register objReg)
|
||||
ICGetElemNativeCompiler<T>::emitCallNative(MacroAssembler& masm, Register objReg)
|
||||
{
|
||||
AllocatableGeneralRegisterSet regs(availableGeneralRegs(0));
|
||||
regs.takeUnchecked(objReg);
|
||||
@ -3693,7 +3811,7 @@ ICGetElemNativeCompiler::emitCallNative(MacroAssembler& masm, Register objReg)
|
||||
masm.push(objReg);
|
||||
|
||||
// Push native callee.
|
||||
masm.loadPtr(Address(ICStubReg, ICGetElemNativeGetterStub::offsetOfGetter()), objReg);
|
||||
masm.loadPtr(Address(ICStubReg, ICGetElemNativeGetterStub<T>::offsetOfGetter()), objReg);
|
||||
masm.push(objReg);
|
||||
|
||||
regs.add(objReg);
|
||||
@ -3707,8 +3825,9 @@ ICGetElemNativeCompiler::emitCallNative(MacroAssembler& masm, Register objReg)
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool
|
||||
ICGetElemNativeCompiler::emitCallScripted(MacroAssembler& masm, Register objReg)
|
||||
ICGetElemNativeCompiler<T>::emitCallScripted(MacroAssembler& masm, Register objReg)
|
||||
{
|
||||
AllocatableGeneralRegisterSet regs(availableGeneralRegs(0));
|
||||
regs.takeUnchecked(objReg);
|
||||
@ -3732,7 +3851,7 @@ ICGetElemNativeCompiler::emitCallScripted(MacroAssembler& masm, Register objReg)
|
||||
regs.add(objReg);
|
||||
|
||||
Register callee = regs.takeAny();
|
||||
masm.loadPtr(Address(ICStubReg, ICGetElemNativeGetterStub::offsetOfGetter()), callee);
|
||||
masm.loadPtr(Address(ICStubReg, ICGetElemNativeGetterStub<T>::offsetOfGetter()), callee);
|
||||
|
||||
// Push argc, callee, and descriptor.
|
||||
{
|
||||
@ -3774,31 +3893,34 @@ ICGetElemNativeCompiler::emitCallScripted(MacroAssembler& masm, Register objReg)
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool
|
||||
ICGetElemNativeCompiler::generateStubCode(MacroAssembler& masm)
|
||||
ICGetElemNativeCompiler<T>::emitCheckKey(MacroAssembler& masm, Label& failure)
|
||||
{
|
||||
MOZ_ASSERT(engine_ == Engine::Baseline);
|
||||
MOZ_ASSERT_UNREACHABLE("Key has to be PropertyName or Symbol");
|
||||
return false;
|
||||
}
|
||||
|
||||
Label failure;
|
||||
Label failurePopR1;
|
||||
bool popR1 = false;
|
||||
template <>
|
||||
bool
|
||||
ICGetElemNativeCompiler<JS::Symbol*>::emitCheckKey(MacroAssembler& masm, Label& failure)
|
||||
{
|
||||
MOZ_ASSERT(!needsAtomize_);
|
||||
masm.branchTestSymbol(Assembler::NotEqual, R1, &failure);
|
||||
Address symbolAddr(ICStubReg, ICGetElemNativeStubImpl<JS::Symbol*>::offsetOfKey());
|
||||
Register symExtract = masm.extractObject(R1, ExtractTemp1);
|
||||
masm.branchPtr(Assembler::NotEqual, symbolAddr, symExtract, &failure);
|
||||
return true;
|
||||
}
|
||||
|
||||
masm.branchTestObject(Assembler::NotEqual, R0, &failure);
|
||||
template <>
|
||||
bool
|
||||
ICGetElemNativeCompiler<PropertyName*>::emitCheckKey(MacroAssembler& masm, Label& failure)
|
||||
{
|
||||
masm.branchTestString(Assembler::NotEqual, R1, &failure);
|
||||
|
||||
AllocatableGeneralRegisterSet regs(availableGeneralRegs(2));
|
||||
Register scratchReg = regs.takeAny();
|
||||
|
||||
// Unbox object.
|
||||
Register objReg = masm.extractObject(R0, ExtractTemp0);
|
||||
|
||||
// Check object shape/group.
|
||||
GuardReceiverObject(masm, ReceiverGuard(obj_), objReg, scratchReg,
|
||||
ICGetElemNativeStub::offsetOfReceiverGuard(), &failure);
|
||||
|
||||
// Check key identity. Don't automatically fail if this fails, since the incoming
|
||||
// key maybe a non-interned string. Switch to a slowpath vm-call based check.
|
||||
Address nameAddr(ICStubReg, ICGetElemNativeStub::offsetOfName());
|
||||
Address nameAddr(ICStubReg, ICGetElemNativeStubImpl<PropertyName*>::offsetOfKey());
|
||||
Register strExtract = masm.extractString(R1, ExtractTemp1);
|
||||
|
||||
// If needsAtomize_ is true, and the string is not already an atom, then atomize the
|
||||
@ -3838,13 +3960,40 @@ ICGetElemNativeCompiler::generateStubCode(MacroAssembler& masm)
|
||||
masm.bind(&skipAtomize);
|
||||
}
|
||||
|
||||
// Key has been atomized if necessary. Do identity check on string pointer.
|
||||
masm.branchPtr(Assembler::NotEqual, nameAddr, strExtract, &failure);
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool
|
||||
ICGetElemNativeCompiler<T>::generateStubCode(MacroAssembler& masm)
|
||||
{
|
||||
MOZ_ASSERT(engine_ == Engine::Baseline);
|
||||
|
||||
Label failure;
|
||||
Label failurePopR1;
|
||||
bool popR1 = false;
|
||||
|
||||
masm.branchTestObject(Assembler::NotEqual, R0, &failure);
|
||||
|
||||
AllocatableGeneralRegisterSet regs(availableGeneralRegs(2));
|
||||
Register scratchReg = regs.takeAny();
|
||||
|
||||
// Unbox object.
|
||||
Register objReg = masm.extractObject(R0, ExtractTemp0);
|
||||
|
||||
// Check object shape/group.
|
||||
GuardReceiverObject(masm, ReceiverGuard(obj_), objReg, scratchReg,
|
||||
ICGetElemNativeStub::offsetOfReceiverGuard(), &failure);
|
||||
|
||||
// Since this stub sometimes enters a stub frame, we manually set this to true (lie).
|
||||
#ifdef DEBUG
|
||||
entersStubFrame_ = true;
|
||||
#endif
|
||||
|
||||
// Key has been atomized if necessary. Do identity check on string pointer.
|
||||
masm.branchPtr(Assembler::NotEqual, nameAddr, strExtract, &failure);
|
||||
if (!emitCheckKey(masm, failure))
|
||||
return false;
|
||||
|
||||
Register holderReg;
|
||||
if (obj_ == holder_) {
|
||||
@ -3867,21 +4016,23 @@ ICGetElemNativeCompiler::generateStubCode(MacroAssembler& masm)
|
||||
holderReg = regs.takeAny();
|
||||
}
|
||||
|
||||
if (kind == ICStub::GetElem_NativePrototypeCallNative ||
|
||||
kind == ICStub::GetElem_NativePrototypeCallScripted)
|
||||
if (kind == ICStub::GetElem_NativePrototypeCallNativeName ||
|
||||
kind == ICStub::GetElem_NativePrototypeCallNativeSymbol ||
|
||||
kind == ICStub::GetElem_NativePrototypeCallScriptedName ||
|
||||
kind == ICStub::GetElem_NativePrototypeCallScriptedSymbol)
|
||||
{
|
||||
masm.loadPtr(Address(ICStubReg,
|
||||
ICGetElemNativePrototypeCallStub::offsetOfHolder()),
|
||||
ICGetElemNativePrototypeCallStub<T>::offsetOfHolder()),
|
||||
holderReg);
|
||||
masm.loadPtr(Address(ICStubReg,
|
||||
ICGetElemNativePrototypeCallStub::offsetOfHolderShape()),
|
||||
ICGetElemNativePrototypeCallStub<T>::offsetOfHolderShape()),
|
||||
scratchReg);
|
||||
} else {
|
||||
masm.loadPtr(Address(ICStubReg,
|
||||
ICGetElem_NativePrototypeSlot::offsetOfHolder()),
|
||||
ICGetElem_NativePrototypeSlot<T>::offsetOfHolder()),
|
||||
holderReg);
|
||||
masm.loadPtr(Address(ICStubReg,
|
||||
ICGetElem_NativePrototypeSlot::offsetOfHolderShape()),
|
||||
ICGetElem_NativePrototypeSlot<T>::offsetOfHolderShape()),
|
||||
scratchReg);
|
||||
}
|
||||
masm.branchTestObjShape(Assembler::NotEqual, holderReg, scratchReg,
|
||||
@ -3891,7 +4042,7 @@ ICGetElemNativeCompiler::generateStubCode(MacroAssembler& masm)
|
||||
if (acctype_ == ICGetElemNativeStub::DynamicSlot ||
|
||||
acctype_ == ICGetElemNativeStub::FixedSlot)
|
||||
{
|
||||
masm.load32(Address(ICStubReg, ICGetElemNativeSlotStub::offsetOfOffset()),
|
||||
masm.load32(Address(ICStubReg, ICGetElemNativeSlotStub<T>::offsetOfOffset()),
|
||||
scratchReg);
|
||||
|
||||
// Load from object.
|
||||
@ -3956,7 +4107,7 @@ ICGetElemNativeCompiler::generateStubCode(MacroAssembler& masm)
|
||||
#endif
|
||||
|
||||
} else if (acctype_ == ICGetElemNativeStub::UnboxedProperty) {
|
||||
masm.load32(Address(ICStubReg, ICGetElemNativeSlotStub::offsetOfOffset()),
|
||||
masm.load32(Address(ICStubReg, ICGetElemNativeSlotStub<T>::offsetOfOffset()),
|
||||
scratchReg);
|
||||
masm.loadUnboxedProperty(BaseIndex(objReg, scratchReg, TimesOne), unboxedType_,
|
||||
TypedOrValueRegister(R0));
|
||||
@ -3965,8 +4116,10 @@ ICGetElemNativeCompiler::generateStubCode(MacroAssembler& masm)
|
||||
} else {
|
||||
MOZ_ASSERT(acctype_ == ICGetElemNativeStub::NativeGetter ||
|
||||
acctype_ == ICGetElemNativeStub::ScriptedGetter);
|
||||
MOZ_ASSERT(kind == ICStub::GetElem_NativePrototypeCallNative ||
|
||||
kind == ICStub::GetElem_NativePrototypeCallScripted);
|
||||
MOZ_ASSERT(kind == ICStub::GetElem_NativePrototypeCallNativeName ||
|
||||
kind == ICStub::GetElem_NativePrototypeCallNativeSymbol ||
|
||||
kind == ICStub::GetElem_NativePrototypeCallScriptedName ||
|
||||
kind == ICStub::GetElem_NativePrototypeCallScriptedSymbol);
|
||||
|
||||
if (acctype_ == ICGetElemNativeStub::NativeGetter) {
|
||||
// If calling a native getter, there is no chance of failure now.
|
||||
@ -3981,7 +4134,7 @@ ICGetElemNativeCompiler::generateStubCode(MacroAssembler& masm)
|
||||
MOZ_ASSERT(acctype_ == ICGetElemNativeStub::ScriptedGetter);
|
||||
|
||||
// Load function in scratchReg and ensure that it has a jit script.
|
||||
masm.loadPtr(Address(ICStubReg, ICGetElemNativeGetterStub::offsetOfGetter()),
|
||||
masm.loadPtr(Address(ICStubReg, ICGetElemNativeGetterStub<T>::offsetOfGetter()),
|
||||
scratchReg);
|
||||
masm.branchIfFunctionHasNoScript(scratchReg, popR1 ? &failurePopR1 : &failure);
|
||||
masm.loadPtr(Address(scratchReg, JSFunction::offsetOfNativeOrScript()), scratchReg);
|
||||
@ -5485,7 +5638,7 @@ TryAttachNativeInStub(JSContext* cx, HandleScript script, ICIn_Fallback* stub,
|
||||
RootedPropertyName name(cx, JSID_TO_ATOM(id)->asPropertyName());
|
||||
RootedShape shape(cx);
|
||||
RootedObject holder(cx);
|
||||
if (!EffectlesslyLookupProperty(cx, obj, name, &holder, &shape))
|
||||
if (!EffectlesslyLookupProperty(cx, obj, id, &holder, &shape))
|
||||
return false;
|
||||
|
||||
if (IsCacheableGetPropReadSlot(obj, holder, shape)) {
|
||||
@ -6605,7 +6758,8 @@ TryAttachNativeGetValuePropStub(JSContext* cx, HandleScript script, jsbytecode*
|
||||
|
||||
RootedShape shape(cx);
|
||||
RootedObject holder(cx);
|
||||
if (!EffectlesslyLookupProperty(cx, obj, name, &holder, &shape))
|
||||
RootedId id(cx, NameToId(name));
|
||||
if (!EffectlesslyLookupProperty(cx, obj, id, &holder, &shape))
|
||||
return false;
|
||||
|
||||
bool isCallProp = (JSOp(*pc) == JSOP_CALLPROP);
|
||||
@ -6663,7 +6817,8 @@ TryAttachNativeGetAccessorPropStub(JSContext* cx, HandleScript script, jsbytecod
|
||||
DOMProxyShadowsResult domProxyShadowsResult;
|
||||
RootedShape shape(cx);
|
||||
RootedObject holder(cx);
|
||||
if (!EffectlesslyLookupProperty(cx, obj, name, &holder, &shape, &isDOMProxy,
|
||||
RootedId id(cx, NameToId(name));
|
||||
if (!EffectlesslyLookupProperty(cx, obj, id, &holder, &shape, &isDOMProxy,
|
||||
&domProxyShadowsResult, &domProxyHasGeneration))
|
||||
{
|
||||
return false;
|
||||
@ -6740,7 +6895,7 @@ TryAttachNativeGetAccessorPropStub(JSContext* cx, HandleScript script, jsbytecod
|
||||
return true;
|
||||
// ICGetProp_CallNative*::Compiler::generateStubCode depends on this.
|
||||
MOZ_ASSERT(&((GetProxyDataLayout(outer)->values->privateSlot).toObject()) == obj);
|
||||
if (!EffectlesslyLookupProperty(cx, obj, name, &holder, &shape, &isDOMProxy,
|
||||
if (!EffectlesslyLookupProperty(cx, obj, id, &holder, &shape, &isDOMProxy,
|
||||
&domProxyShadowsResult, &domProxyHasGeneration))
|
||||
{
|
||||
return false;
|
||||
@ -8224,7 +8379,7 @@ TryAttachSetValuePropStub(JSContext* cx, HandleScript script, jsbytecode* pc, IC
|
||||
|
||||
RootedShape shape(cx);
|
||||
RootedObject holder(cx);
|
||||
if (!EffectlesslyLookupProperty(cx, obj, name, &holder, &shape))
|
||||
if (!EffectlesslyLookupProperty(cx, obj, id, &holder, &shape))
|
||||
return false;
|
||||
if (obj != holder)
|
||||
return true;
|
||||
@ -8333,7 +8488,7 @@ TryAttachSetAccessorPropStub(JSContext* cx, HandleScript script, jsbytecode* pc,
|
||||
|
||||
RootedShape shape(cx);
|
||||
RootedObject holder(cx);
|
||||
if (!EffectlesslyLookupProperty(cx, obj, name, &holder, &shape))
|
||||
if (!EffectlesslyLookupProperty(cx, obj, id, &holder, &shape))
|
||||
return false;
|
||||
|
||||
bool isScripted = false;
|
||||
@ -12010,76 +12165,83 @@ ICTypeUpdate_ObjectGroup::ICTypeUpdate_ObjectGroup(JitCode* stubCode, ObjectGrou
|
||||
|
||||
ICGetElemNativeStub::ICGetElemNativeStub(ICStub::Kind kind, JitCode* stubCode,
|
||||
ICStub* firstMonitorStub,
|
||||
ReceiverGuard guard, PropertyName* name,
|
||||
AccessType acctype, bool needsAtomize)
|
||||
ReceiverGuard guard, AccessType acctype,
|
||||
bool needsAtomize, bool isSymbol)
|
||||
: ICMonitoredStub(kind, stubCode, firstMonitorStub),
|
||||
receiverGuard_(guard),
|
||||
name_(name)
|
||||
receiverGuard_(guard)
|
||||
{
|
||||
extra_ = (static_cast<uint16_t>(acctype) << ACCESSTYPE_SHIFT) |
|
||||
(static_cast<uint16_t>(needsAtomize) << NEEDS_ATOMIZE_SHIFT);
|
||||
(static_cast<uint16_t>(needsAtomize) << NEEDS_ATOMIZE_SHIFT) |
|
||||
(static_cast<uint16_t>(isSymbol) << ISSYMBOL_SHIFT);
|
||||
}
|
||||
|
||||
ICGetElemNativeStub::~ICGetElemNativeStub()
|
||||
{ }
|
||||
|
||||
ICGetElemNativeGetterStub::ICGetElemNativeGetterStub(
|
||||
ICStub::Kind kind, JitCode* stubCode, ICStub* firstMonitorStub,
|
||||
ReceiverGuard guard, PropertyName* name, AccessType acctype,
|
||||
bool needsAtomize, JSFunction* getter, uint32_t pcOffset)
|
||||
: ICGetElemNativeStub(kind, stubCode, firstMonitorStub, guard, name, acctype, needsAtomize),
|
||||
template <class T>
|
||||
ICGetElemNativeGetterStub<T>::ICGetElemNativeGetterStub(
|
||||
ICStub::Kind kind, JitCode* stubCode, ICStub* firstMonitorStub,
|
||||
ReceiverGuard guard, const T* key, AccType acctype, bool needsAtomize,
|
||||
JSFunction* getter, uint32_t pcOffset)
|
||||
: ICGetElemNativeStubImpl<T>(kind, stubCode, firstMonitorStub, guard, key, acctype, needsAtomize),
|
||||
getter_(getter),
|
||||
pcOffset_(pcOffset)
|
||||
{
|
||||
MOZ_ASSERT(kind == GetElem_NativePrototypeCallNative ||
|
||||
kind == GetElem_NativePrototypeCallScripted);
|
||||
MOZ_ASSERT(acctype == NativeGetter || acctype == ScriptedGetter);
|
||||
MOZ_ASSERT(kind == ICStub::GetElem_NativePrototypeCallNativeName ||
|
||||
kind == ICStub::GetElem_NativePrototypeCallNativeSymbol ||
|
||||
kind == ICStub::GetElem_NativePrototypeCallScriptedName ||
|
||||
kind == ICStub::GetElem_NativePrototypeCallScriptedSymbol);
|
||||
MOZ_ASSERT(acctype == ICGetElemNativeStub::NativeGetter ||
|
||||
acctype == ICGetElemNativeStub::ScriptedGetter);
|
||||
}
|
||||
|
||||
ICGetElem_NativePrototypeSlot::ICGetElem_NativePrototypeSlot(
|
||||
JitCode* stubCode, ICStub* firstMonitorStub,
|
||||
ReceiverGuard guard, PropertyName* name,
|
||||
AccessType acctype, bool needsAtomize, uint32_t offset,
|
||||
JSObject* holder, Shape* holderShape)
|
||||
: ICGetElemNativeSlotStub(ICStub::GetElem_NativePrototypeSlot, stubCode, firstMonitorStub, guard,
|
||||
name, acctype, needsAtomize, offset),
|
||||
template <class T>
|
||||
ICGetElem_NativePrototypeSlot<T>::ICGetElem_NativePrototypeSlot(
|
||||
JitCode* stubCode, ICStub* firstMonitorStub, ReceiverGuard guard,
|
||||
const T* key, AccType acctype, bool needsAtomize, uint32_t offset,
|
||||
JSObject* holder, Shape* holderShape)
|
||||
: ICGetElemNativeSlotStub<T>(getGetElemStubKind<T>(ICStub::GetElem_NativePrototypeSlotName),
|
||||
stubCode, firstMonitorStub, guard, key, acctype, needsAtomize, offset),
|
||||
holder_(holder),
|
||||
holderShape_(holderShape)
|
||||
{ }
|
||||
|
||||
ICGetElemNativePrototypeCallStub::ICGetElemNativePrototypeCallStub(
|
||||
ICStub::Kind kind, JitCode* stubCode, ICStub* firstMonitorStub,
|
||||
ReceiverGuard guard, PropertyName* name,
|
||||
AccessType acctype, bool needsAtomize, JSFunction* getter,
|
||||
uint32_t pcOffset, JSObject* holder, Shape* holderShape)
|
||||
: ICGetElemNativeGetterStub(kind, stubCode, firstMonitorStub, guard, name, acctype, needsAtomize,
|
||||
getter, pcOffset),
|
||||
template <class T>
|
||||
ICGetElemNativePrototypeCallStub<T>::ICGetElemNativePrototypeCallStub(
|
||||
ICStub::Kind kind, JitCode* stubCode, ICStub* firstMonitorStub,
|
||||
ReceiverGuard guard, const T* key, AccType acctype,
|
||||
bool needsAtomize, JSFunction* getter, uint32_t pcOffset,
|
||||
JSObject* holder, Shape* holderShape)
|
||||
: ICGetElemNativeGetterStub<T>(kind, stubCode, firstMonitorStub, guard, key, acctype, needsAtomize,
|
||||
getter, pcOffset),
|
||||
holder_(holder),
|
||||
holderShape_(holderShape)
|
||||
{}
|
||||
|
||||
/* static */ ICGetElem_NativePrototypeCallNative*
|
||||
ICGetElem_NativePrototypeCallNative::Clone(JSContext* cx,
|
||||
ICStubSpace* space,
|
||||
ICStub* firstMonitorStub,
|
||||
ICGetElem_NativePrototypeCallNative& other)
|
||||
template <class T>
|
||||
/* static */ ICGetElem_NativePrototypeCallNative<T>*
|
||||
ICGetElem_NativePrototypeCallNative<T>::Clone(JSContext* cx,
|
||||
ICStubSpace* space,
|
||||
ICStub* firstMonitorStub,
|
||||
ICGetElem_NativePrototypeCallNative<T>& other)
|
||||
{
|
||||
return New<ICGetElem_NativePrototypeCallNative>(cx, space, other.jitCode(), firstMonitorStub,
|
||||
other.receiverGuard(), other.name(), other.accessType(),
|
||||
other.needsAtomize(), other.getter(), other.pcOffset_,
|
||||
other.holder(), other.holderShape());
|
||||
return ICStub::New<ICGetElem_NativePrototypeCallNative<T>>(cx, space, other.jitCode(),
|
||||
firstMonitorStub, other.receiverGuard(), other.key().unsafeGet(), other.accessType(),
|
||||
other.needsAtomize(), other.getter(), other.pcOffset_, other.holder(),
|
||||
other.holderShape());
|
||||
}
|
||||
|
||||
/* static */ ICGetElem_NativePrototypeCallScripted*
|
||||
ICGetElem_NativePrototypeCallScripted::Clone(JSContext* cx,
|
||||
ICStubSpace* space,
|
||||
ICStub* firstMonitorStub,
|
||||
ICGetElem_NativePrototypeCallScripted& other)
|
||||
template <class T>
|
||||
/* static */ ICGetElem_NativePrototypeCallScripted<T>*
|
||||
ICGetElem_NativePrototypeCallScripted<T>::Clone(JSContext* cx,
|
||||
ICStubSpace* space,
|
||||
ICStub* firstMonitorStub,
|
||||
ICGetElem_NativePrototypeCallScripted<T>& other)
|
||||
{
|
||||
return New<ICGetElem_NativePrototypeCallScripted>(cx, space, other.jitCode(), firstMonitorStub,
|
||||
other.receiverGuard(), other.name(),
|
||||
other.accessType(), other.needsAtomize(), other.getter(),
|
||||
other.pcOffset_, other.holder(), other.holderShape());
|
||||
return ICStub::New<ICGetElem_NativePrototypeCallScripted<T>>(cx, space, other.jitCode(),
|
||||
firstMonitorStub, other.receiverGuard(), other.key().unsafeGet(), other.accessType(),
|
||||
other.needsAtomize(), other.getter(), other.pcOffset_, other.holder(),
|
||||
other.holderShape());
|
||||
}
|
||||
|
||||
ICGetElem_Dense::ICGetElem_Dense(JitCode* stubCode, ICStub* firstMonitorStub, Shape* shape)
|
||||
|
@ -1532,7 +1532,6 @@ class ICGetElemNativeStub : public ICMonitoredStub
|
||||
|
||||
protected:
|
||||
HeapReceiverGuard receiverGuard_;
|
||||
HeapPtrPropertyName name_;
|
||||
|
||||
static const unsigned NEEDS_ATOMIZE_SHIFT = 0;
|
||||
static const uint16_t NEEDS_ATOMIZE_MASK = 0x1;
|
||||
@ -1540,9 +1539,11 @@ class ICGetElemNativeStub : public ICMonitoredStub
|
||||
static const unsigned ACCESSTYPE_SHIFT = 1;
|
||||
static const uint16_t ACCESSTYPE_MASK = 0x3;
|
||||
|
||||
static const unsigned ISSYMBOL_SHIFT = 3;
|
||||
static const uint16_t ISSYMBOL_MASK = 0x1;
|
||||
|
||||
ICGetElemNativeStub(ICStub::Kind kind, JitCode* stubCode, ICStub* firstMonitorStub,
|
||||
ReceiverGuard guard, PropertyName* name, AccessType acctype,
|
||||
bool needsAtomize);
|
||||
ReceiverGuard guard, AccessType acctype, bool needsAtomize, bool isSymbol);
|
||||
|
||||
~ICGetElemNativeStub();
|
||||
|
||||
@ -1554,13 +1555,6 @@ class ICGetElemNativeStub : public ICMonitoredStub
|
||||
return offsetof(ICGetElemNativeStub, receiverGuard_);
|
||||
}
|
||||
|
||||
HeapPtrPropertyName& name() {
|
||||
return name_;
|
||||
}
|
||||
static size_t offsetOfName() {
|
||||
return offsetof(ICGetElemNativeStub, name_);
|
||||
}
|
||||
|
||||
AccessType accessType() const {
|
||||
return static_cast<AccessType>((extra_ >> ACCESSTYPE_SHIFT) & ACCESSTYPE_MASK);
|
||||
}
|
||||
@ -1568,22 +1562,56 @@ class ICGetElemNativeStub : public ICMonitoredStub
|
||||
bool needsAtomize() const {
|
||||
return (extra_ >> NEEDS_ATOMIZE_SHIFT) & NEEDS_ATOMIZE_MASK;
|
||||
}
|
||||
|
||||
bool isSymbol() const {
|
||||
return (extra_ >> ISSYMBOL_SHIFT) & ISSYMBOL_MASK;
|
||||
}
|
||||
};
|
||||
|
||||
class ICGetElemNativeSlotStub : public ICGetElemNativeStub
|
||||
template <class T>
|
||||
class ICGetElemNativeStubImpl : public ICGetElemNativeStub
|
||||
{
|
||||
protected:
|
||||
HeapPtr<T> key_;
|
||||
|
||||
ICGetElemNativeStubImpl(ICStub::Kind kind, JitCode* stubCode, ICStub* firstMonitorStub,
|
||||
ReceiverGuard guard, const T* key, AccessType acctype, bool needsAtomize)
|
||||
: ICGetElemNativeStub(kind, stubCode, firstMonitorStub, guard, acctype, needsAtomize,
|
||||
mozilla::IsSame<T, JS::Symbol*>::value),
|
||||
key_(*key)
|
||||
{}
|
||||
|
||||
public:
|
||||
HeapPtr<T>& key() {
|
||||
return key_;
|
||||
}
|
||||
static size_t offsetOfKey() {
|
||||
return offsetof(ICGetElemNativeStubImpl, key_);
|
||||
}
|
||||
};
|
||||
|
||||
typedef ICGetElemNativeStub::AccessType AccType;
|
||||
|
||||
template <class T>
|
||||
class ICGetElemNativeSlotStub : public ICGetElemNativeStubImpl<T>
|
||||
{
|
||||
protected:
|
||||
uint32_t offset_;
|
||||
|
||||
ICGetElemNativeSlotStub(ICStub::Kind kind, JitCode* stubCode, ICStub* firstMonitorStub,
|
||||
ReceiverGuard guard, PropertyName* name,
|
||||
AccessType acctype, bool needsAtomize, uint32_t offset)
|
||||
: ICGetElemNativeStub(kind, stubCode, firstMonitorStub, guard, name, acctype, needsAtomize),
|
||||
ReceiverGuard guard, const T* key, AccType acctype, bool needsAtomize,
|
||||
uint32_t offset)
|
||||
: ICGetElemNativeStubImpl<T>(kind, stubCode, firstMonitorStub, guard, key, acctype, needsAtomize),
|
||||
offset_(offset)
|
||||
{
|
||||
MOZ_ASSERT(kind == GetElem_NativeSlot || kind == GetElem_NativePrototypeSlot ||
|
||||
kind == GetElem_UnboxedProperty);
|
||||
MOZ_ASSERT(acctype == FixedSlot || acctype == DynamicSlot || acctype == UnboxedProperty);
|
||||
MOZ_ASSERT(kind == ICStub::GetElem_NativeSlotName ||
|
||||
kind == ICStub::GetElem_NativeSlotSymbol ||
|
||||
kind == ICStub::GetElem_NativePrototypeSlotName ||
|
||||
kind == ICStub::GetElem_NativePrototypeSlotSymbol ||
|
||||
kind == ICStub::GetElem_UnboxedPropertyName);
|
||||
MOZ_ASSERT(acctype == ICGetElemNativeStub::FixedSlot ||
|
||||
acctype == ICGetElemNativeStub::DynamicSlot ||
|
||||
acctype == ICGetElemNativeStub::UnboxedProperty);
|
||||
}
|
||||
|
||||
public:
|
||||
@ -1596,15 +1624,16 @@ class ICGetElemNativeSlotStub : public ICGetElemNativeStub
|
||||
}
|
||||
};
|
||||
|
||||
class ICGetElemNativeGetterStub : public ICGetElemNativeStub
|
||||
template <class T>
|
||||
class ICGetElemNativeGetterStub : public ICGetElemNativeStubImpl<T>
|
||||
{
|
||||
protected:
|
||||
HeapPtrFunction getter_;
|
||||
uint32_t pcOffset_;
|
||||
|
||||
ICGetElemNativeGetterStub(ICStub::Kind kind, JitCode* stubCode, ICStub* firstMonitorStub,
|
||||
ReceiverGuard guard, PropertyName* name, AccessType acctype,
|
||||
bool needsAtomize, JSFunction* getter, uint32_t pcOffset);
|
||||
ReceiverGuard guard, const T* key, AccType acctype, bool needsAtomize,
|
||||
JSFunction* getter, uint32_t pcOffset);
|
||||
|
||||
public:
|
||||
HeapPtrFunction& getter() {
|
||||
@ -1619,37 +1648,61 @@ class ICGetElemNativeGetterStub : public ICGetElemNativeStub
|
||||
}
|
||||
};
|
||||
|
||||
class ICGetElem_NativeSlot : public ICGetElemNativeSlotStub
|
||||
template <class T>
|
||||
ICStub::Kind
|
||||
getGetElemStubKind(ICStub::Kind kind)
|
||||
{
|
||||
MOZ_ASSERT(kind == ICStub::GetElem_NativeSlotName ||
|
||||
kind == ICStub::GetElem_NativePrototypeSlotName ||
|
||||
kind == ICStub::GetElem_NativePrototypeCallNativeName ||
|
||||
kind == ICStub::GetElem_NativePrototypeCallScriptedName);
|
||||
return static_cast<ICStub::Kind>(kind + mozilla::IsSame<T, JS::Symbol*>::value);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
class ICGetElem_NativeSlot : public ICGetElemNativeSlotStub<T>
|
||||
{
|
||||
friend class ICStubSpace;
|
||||
ICGetElem_NativeSlot(JitCode* stubCode, ICStub* firstMonitorStub,
|
||||
ReceiverGuard guard, PropertyName* name,
|
||||
AccessType acctype, bool needsAtomize, uint32_t offset)
|
||||
: ICGetElemNativeSlotStub(ICStub::GetElem_NativeSlot, stubCode, firstMonitorStub, guard,
|
||||
name, acctype, needsAtomize, offset)
|
||||
ICGetElem_NativeSlot(JitCode* stubCode, ICStub* firstMonitorStub, ReceiverGuard guard,
|
||||
const T* key, AccType acctype, bool needsAtomize, uint32_t offset)
|
||||
: ICGetElemNativeSlotStub<T>(getGetElemStubKind<T>(ICStub::GetElem_NativeSlotName),
|
||||
stubCode, firstMonitorStub, guard,
|
||||
key, acctype, needsAtomize, offset)
|
||||
{}
|
||||
};
|
||||
|
||||
class ICGetElem_UnboxedProperty : public ICGetElemNativeSlotStub
|
||||
class ICGetElem_NativeSlotName :
|
||||
public ICGetElem_NativeSlot<PropertyName*>
|
||||
{};
|
||||
class ICGetElem_NativeSlotSymbol :
|
||||
public ICGetElem_NativeSlot<JS::Symbol*>
|
||||
{};
|
||||
|
||||
template <class T>
|
||||
class ICGetElem_UnboxedProperty : public ICGetElemNativeSlotStub<T>
|
||||
{
|
||||
friend class ICStubSpace;
|
||||
ICGetElem_UnboxedProperty(JitCode* stubCode, ICStub* firstMonitorStub,
|
||||
ReceiverGuard guard, PropertyName* name,
|
||||
AccessType acctype, bool needsAtomize, uint32_t offset)
|
||||
: ICGetElemNativeSlotStub(ICStub::GetElem_UnboxedProperty, stubCode, firstMonitorStub, guard,
|
||||
name, acctype, needsAtomize, offset)
|
||||
{}
|
||||
ReceiverGuard guard, const T* key, AccType acctype,
|
||||
bool needsAtomize, uint32_t offset)
|
||||
: ICGetElemNativeSlotStub<T>(ICStub::GetElem_UnboxedPropertyName, stubCode, firstMonitorStub,
|
||||
guard, key, acctype, needsAtomize, offset)
|
||||
{}
|
||||
};
|
||||
|
||||
class ICGetElem_NativePrototypeSlot : public ICGetElemNativeSlotStub
|
||||
class ICGetElem_UnboxedPropertyName :
|
||||
public ICGetElem_UnboxedProperty<PropertyName*>
|
||||
{};
|
||||
|
||||
template <class T>
|
||||
class ICGetElem_NativePrototypeSlot : public ICGetElemNativeSlotStub<T>
|
||||
{
|
||||
friend class ICStubSpace;
|
||||
HeapPtrObject holder_;
|
||||
HeapPtrShape holderShape_;
|
||||
|
||||
ICGetElem_NativePrototypeSlot(JitCode* stubCode, ICStub* firstMonitorStub,
|
||||
ReceiverGuard guard, PropertyName* name,
|
||||
AccessType acctype, bool needsAtomize, uint32_t offset,
|
||||
ICGetElem_NativePrototypeSlot(JitCode* stubCode, ICStub* firstMonitorStub, ReceiverGuard guard,
|
||||
const T* key, AccType acctype, bool needsAtomize, uint32_t offset,
|
||||
JSObject* holder, Shape* holderShape);
|
||||
|
||||
public:
|
||||
@ -1668,7 +1721,15 @@ class ICGetElem_NativePrototypeSlot : public ICGetElemNativeSlotStub
|
||||
}
|
||||
};
|
||||
|
||||
class ICGetElemNativePrototypeCallStub : public ICGetElemNativeGetterStub
|
||||
class ICGetElem_NativePrototypeSlotName :
|
||||
public ICGetElem_NativePrototypeSlot<PropertyName*>
|
||||
{};
|
||||
class ICGetElem_NativePrototypeSlotSymbol :
|
||||
public ICGetElem_NativePrototypeSlot<JS::Symbol*>
|
||||
{};
|
||||
|
||||
template <class T>
|
||||
class ICGetElemNativePrototypeCallStub : public ICGetElemNativeGetterStub<T>
|
||||
{
|
||||
friend class ICStubSpace;
|
||||
HeapPtrObject holder_;
|
||||
@ -1676,10 +1737,9 @@ class ICGetElemNativePrototypeCallStub : public ICGetElemNativeGetterStub
|
||||
|
||||
protected:
|
||||
ICGetElemNativePrototypeCallStub(ICStub::Kind kind, JitCode* stubCode, ICStub* firstMonitorStub,
|
||||
ReceiverGuard guard, PropertyName* name,
|
||||
AccessType acctype, bool needsAtomize, JSFunction* getter,
|
||||
uint32_t pcOffset, JSObject* holder,
|
||||
Shape* holderShape);
|
||||
ReceiverGuard guard, const T* key, AccType acctype,
|
||||
bool needsAtomize, JSFunction* getter, uint32_t pcOffset,
|
||||
JSObject* holder, Shape* holderShape);
|
||||
|
||||
public:
|
||||
HeapPtrObject& holder() {
|
||||
@ -1697,64 +1757,81 @@ class ICGetElemNativePrototypeCallStub : public ICGetElemNativeGetterStub
|
||||
}
|
||||
};
|
||||
|
||||
class ICGetElem_NativePrototypeCallNative : public ICGetElemNativePrototypeCallStub
|
||||
template <class T>
|
||||
class ICGetElem_NativePrototypeCallNative : public ICGetElemNativePrototypeCallStub<T>
|
||||
{
|
||||
friend class ICStubSpace;
|
||||
|
||||
ICGetElem_NativePrototypeCallNative(JitCode* stubCode, ICStub* firstMonitorStub,
|
||||
ReceiverGuard guard, PropertyName* name,
|
||||
AccessType acctype, bool needsAtomize,
|
||||
JSFunction* getter, uint32_t pcOffset,
|
||||
ReceiverGuard guard, const T* key, AccType acctype,
|
||||
bool needsAtomize, JSFunction* getter, uint32_t pcOffset,
|
||||
JSObject* holder, Shape* holderShape)
|
||||
: ICGetElemNativePrototypeCallStub(GetElem_NativePrototypeCallNative,
|
||||
stubCode, firstMonitorStub, guard, name,
|
||||
acctype, needsAtomize, getter, pcOffset, holder,
|
||||
holderShape)
|
||||
: ICGetElemNativePrototypeCallStub<T>(getGetElemStubKind<T>(
|
||||
ICStub::GetElem_NativePrototypeCallNativeName),
|
||||
stubCode, firstMonitorStub, guard, key,
|
||||
acctype, needsAtomize, getter, pcOffset, holder,
|
||||
holderShape)
|
||||
{}
|
||||
|
||||
public:
|
||||
static ICGetElem_NativePrototypeCallNative* Clone(JSContext* cx, ICStubSpace* space,
|
||||
ICStub* firstMonitorStub,
|
||||
ICGetElem_NativePrototypeCallNative& other);
|
||||
static ICGetElem_NativePrototypeCallNative<T>* Clone(JSContext* cx, ICStubSpace* space,
|
||||
ICStub* firstMonitorStub,
|
||||
ICGetElem_NativePrototypeCallNative<T>& other);
|
||||
};
|
||||
|
||||
class ICGetElem_NativePrototypeCallScripted : public ICGetElemNativePrototypeCallStub
|
||||
class ICGetElem_NativePrototypeCallNativeName :
|
||||
public ICGetElem_NativePrototypeCallNative<PropertyName*>
|
||||
{};
|
||||
class ICGetElem_NativePrototypeCallNativeSymbol :
|
||||
public ICGetElem_NativePrototypeCallNative<JS::Symbol*>
|
||||
{};
|
||||
|
||||
template <class T>
|
||||
class ICGetElem_NativePrototypeCallScripted : public ICGetElemNativePrototypeCallStub<T>
|
||||
{
|
||||
friend class ICStubSpace;
|
||||
|
||||
ICGetElem_NativePrototypeCallScripted(JitCode* stubCode, ICStub* firstMonitorStub,
|
||||
ReceiverGuard guard, PropertyName* name,
|
||||
AccessType acctype, bool needsAtomize,
|
||||
JSFunction* getter, uint32_t pcOffset,
|
||||
ReceiverGuard guard, const T* key, AccType acctype,
|
||||
bool needsAtomize, JSFunction* getter, uint32_t pcOffset,
|
||||
JSObject* holder, Shape* holderShape)
|
||||
: ICGetElemNativePrototypeCallStub(GetElem_NativePrototypeCallScripted,
|
||||
stubCode, firstMonitorStub, guard, name,
|
||||
acctype, needsAtomize, getter, pcOffset, holder,
|
||||
holderShape)
|
||||
: ICGetElemNativePrototypeCallStub<T>(getGetElemStubKind<T>(
|
||||
ICStub::GetElem_NativePrototypeCallScriptedName),
|
||||
stubCode, firstMonitorStub, guard, key, acctype,
|
||||
needsAtomize, getter, pcOffset, holder, holderShape)
|
||||
{}
|
||||
|
||||
public:
|
||||
static ICGetElem_NativePrototypeCallScripted*
|
||||
static ICGetElem_NativePrototypeCallScripted<T>*
|
||||
Clone(JSContext* cx, ICStubSpace* space,
|
||||
ICStub* firstMonitorStub,
|
||||
ICGetElem_NativePrototypeCallScripted& other);
|
||||
ICGetElem_NativePrototypeCallScripted<T>& other);
|
||||
};
|
||||
|
||||
class ICGetElem_NativePrototypeCallScriptedName :
|
||||
public ICGetElem_NativePrototypeCallScripted<PropertyName*>
|
||||
{};
|
||||
class ICGetElem_NativePrototypeCallScriptedSymbol :
|
||||
public ICGetElem_NativePrototypeCallScripted<JS::Symbol*>
|
||||
{};
|
||||
|
||||
// Compiler for GetElem_NativeSlot and GetElem_NativePrototypeSlot stubs.
|
||||
template <class T>
|
||||
class ICGetElemNativeCompiler : public ICStubCompiler
|
||||
{
|
||||
bool isCallElem_;
|
||||
ICStub* firstMonitorStub_;
|
||||
HandleObject obj_;
|
||||
HandleObject holder_;
|
||||
HandlePropertyName name_;
|
||||
ICGetElemNativeStub::AccessType acctype_;
|
||||
Handle<T> key_;
|
||||
AccType acctype_;
|
||||
bool needsAtomize_;
|
||||
uint32_t offset_;
|
||||
JSValueType unboxedType_;
|
||||
HandleFunction getter_;
|
||||
uint32_t pcOffset_;
|
||||
|
||||
bool emitCheckKey(MacroAssembler& masm, Label& failure);
|
||||
bool emitCallNative(MacroAssembler& masm, Register objReg);
|
||||
bool emitCallScripted(MacroAssembler& masm, Register objReg);
|
||||
bool generateStubCode(MacroAssembler& masm);
|
||||
@ -1771,21 +1848,21 @@ class ICGetElemNativeCompiler : public ICStubCompiler
|
||||
(static_cast<int32_t>(needsAtomize_) << 18) |
|
||||
(static_cast<int32_t>(acctype_) << 19) |
|
||||
(static_cast<int32_t>(unboxedType_) << 22) |
|
||||
(HeapReceiverGuard::keyBits(obj_) << 26);
|
||||
(static_cast<int32_t>(mozilla::IsSame<JS::Symbol*, T>::value) << 26) |
|
||||
(HeapReceiverGuard::keyBits(obj_) << 27);
|
||||
}
|
||||
|
||||
public:
|
||||
ICGetElemNativeCompiler(JSContext* cx, ICStub::Kind kind, bool isCallElem,
|
||||
ICStub* firstMonitorStub, HandleObject obj, HandleObject holder,
|
||||
HandlePropertyName name, ICGetElemNativeStub::AccessType acctype,
|
||||
bool needsAtomize, uint32_t offset,
|
||||
Handle<T> key, AccType acctype, bool needsAtomize, uint32_t offset,
|
||||
JSValueType unboxedType = JSVAL_TYPE_MAGIC)
|
||||
: ICStubCompiler(cx, kind, Engine::Baseline),
|
||||
isCallElem_(isCallElem),
|
||||
firstMonitorStub_(firstMonitorStub),
|
||||
obj_(obj),
|
||||
holder_(holder),
|
||||
name_(name),
|
||||
key_(key),
|
||||
acctype_(acctype),
|
||||
needsAtomize_(needsAtomize),
|
||||
offset_(offset),
|
||||
@ -1795,15 +1872,15 @@ class ICGetElemNativeCompiler : public ICStubCompiler
|
||||
{}
|
||||
|
||||
ICGetElemNativeCompiler(JSContext* cx, ICStub::Kind kind, ICStub* firstMonitorStub,
|
||||
HandleObject obj, HandleObject holder, HandlePropertyName name,
|
||||
ICGetElemNativeStub::AccessType acctype, bool needsAtomize,
|
||||
HandleFunction getter, uint32_t pcOffset, bool isCallElem)
|
||||
HandleObject obj, HandleObject holder, Handle<T> key, AccType acctype,
|
||||
bool needsAtomize, HandleFunction getter, uint32_t pcOffset,
|
||||
bool isCallElem)
|
||||
: ICStubCompiler(cx, kind, Engine::Baseline),
|
||||
isCallElem_(false),
|
||||
firstMonitorStub_(firstMonitorStub),
|
||||
obj_(obj),
|
||||
holder_(holder),
|
||||
name_(name),
|
||||
key_(key),
|
||||
acctype_(acctype),
|
||||
needsAtomize_(needsAtomize),
|
||||
offset_(0),
|
||||
@ -1814,39 +1891,44 @@ class ICGetElemNativeCompiler : public ICStubCompiler
|
||||
|
||||
ICStub* getStub(ICStubSpace* space) {
|
||||
RootedReceiverGuard guard(cx, ReceiverGuard(obj_));
|
||||
if (kind == ICStub::GetElem_NativeSlot) {
|
||||
if (kind == ICStub::GetElem_NativeSlotName || kind == ICStub::GetElem_NativeSlotSymbol) {
|
||||
MOZ_ASSERT(obj_ == holder_);
|
||||
return newStub<ICGetElem_NativeSlot>(
|
||||
space, getStubCode(), firstMonitorStub_, guard, name_, acctype_, needsAtomize_,
|
||||
offset_);
|
||||
return newStub<ICGetElem_NativeSlot<T>>(
|
||||
space, getStubCode(), firstMonitorStub_, guard, key_.address(), acctype_,
|
||||
needsAtomize_, offset_);
|
||||
}
|
||||
|
||||
if (kind == ICStub::GetElem_UnboxedProperty) {
|
||||
if (kind == ICStub::GetElem_UnboxedPropertyName) {
|
||||
MOZ_ASSERT(obj_ == holder_);
|
||||
return newStub<ICGetElem_UnboxedProperty>(
|
||||
space, getStubCode(), firstMonitorStub_, guard, name_, acctype_, needsAtomize_,
|
||||
offset_);
|
||||
return newStub<ICGetElem_UnboxedProperty<T>>(
|
||||
space, getStubCode(), firstMonitorStub_, guard, key_.address(), acctype_,
|
||||
needsAtomize_, offset_);
|
||||
}
|
||||
|
||||
MOZ_ASSERT(obj_ != holder_);
|
||||
RootedShape holderShape(cx, holder_->as<NativeObject>().lastProperty());
|
||||
if (kind == ICStub::GetElem_NativePrototypeSlot) {
|
||||
return newStub<ICGetElem_NativePrototypeSlot>(
|
||||
space, getStubCode(), firstMonitorStub_, guard, name_, acctype_, needsAtomize_,
|
||||
offset_, holder_, holderShape);
|
||||
if (kind == ICStub::GetElem_NativePrototypeSlotName ||
|
||||
kind == ICStub::GetElem_NativePrototypeSlotSymbol)
|
||||
{
|
||||
return newStub<ICGetElem_NativePrototypeSlot<T>>(
|
||||
space, getStubCode(), firstMonitorStub_, guard, key_.address(), acctype_,
|
||||
needsAtomize_, offset_, holder_, holderShape);
|
||||
}
|
||||
|
||||
if (kind == ICStub::GetElem_NativePrototypeCallNative) {
|
||||
return newStub<ICGetElem_NativePrototypeCallNative>(
|
||||
space, getStubCode(), firstMonitorStub_, guard, name_, acctype_, needsAtomize_,
|
||||
getter_, pcOffset_, holder_, holderShape);
|
||||
if (kind == ICStub::GetElem_NativePrototypeCallNativeSymbol ||
|
||||
kind == ICStub::GetElem_NativePrototypeCallNativeName) {
|
||||
return newStub<ICGetElem_NativePrototypeCallNative<T>>(
|
||||
space, getStubCode(), firstMonitorStub_, guard, key_.address(), acctype_,
|
||||
needsAtomize_, getter_, pcOffset_, holder_, holderShape);
|
||||
}
|
||||
|
||||
MOZ_ASSERT(kind == ICStub::GetElem_NativePrototypeCallScripted);
|
||||
if (kind == ICStub::GetElem_NativePrototypeCallScripted) {
|
||||
return newStub<ICGetElem_NativePrototypeCallScripted>(
|
||||
space, getStubCode(), firstMonitorStub_, guard, name_, acctype_, needsAtomize_,
|
||||
getter_, pcOffset_, holder_, holderShape);
|
||||
MOZ_ASSERT(kind == ICStub::GetElem_NativePrototypeCallScriptedName ||
|
||||
kind == ICStub::GetElem_NativePrototypeCallScriptedSymbol);
|
||||
if (kind == ICStub::GetElem_NativePrototypeCallScriptedName ||
|
||||
kind == ICStub::GetElem_NativePrototypeCallScriptedSymbol) {
|
||||
return newStub<ICGetElem_NativePrototypeCallScripted<T>>(
|
||||
space, getStubCode(), firstMonitorStub_, guard, key_.address(), acctype_,
|
||||
needsAtomize_, getter_, pcOffset_, holder_, holderShape);
|
||||
}
|
||||
|
||||
MOZ_CRASH("Invalid kind.");
|
||||
|
@ -73,11 +73,15 @@ namespace jit {
|
||||
_(Call_IsSuspendedStarGenerator) \
|
||||
\
|
||||
_(GetElem_Fallback) \
|
||||
_(GetElem_NativeSlot) \
|
||||
_(GetElem_NativePrototypeSlot) \
|
||||
_(GetElem_NativePrototypeCallNative) \
|
||||
_(GetElem_NativePrototypeCallScripted) \
|
||||
_(GetElem_UnboxedProperty) \
|
||||
_(GetElem_NativeSlotName) \
|
||||
_(GetElem_NativeSlotSymbol) \
|
||||
_(GetElem_NativePrototypeSlotName) \
|
||||
_(GetElem_NativePrototypeSlotSymbol) \
|
||||
_(GetElem_NativePrototypeCallNativeName) \
|
||||
_(GetElem_NativePrototypeCallNativeSymbol) \
|
||||
_(GetElem_NativePrototypeCallScriptedName) \
|
||||
_(GetElem_NativePrototypeCallScriptedSymbol) \
|
||||
_(GetElem_UnboxedPropertyName) \
|
||||
_(GetElem_String) \
|
||||
_(GetElem_Dense) \
|
||||
_(GetElem_UnboxedArray) \
|
||||
|
@ -744,11 +744,15 @@ BaselineInspector::expectedPropertyAccessInputType(jsbytecode* pc)
|
||||
case ICStub::GetProp_CallDOMProxyNative:
|
||||
case ICStub::GetProp_CallDOMProxyWithGenerationNative:
|
||||
case ICStub::GetProp_DOMProxyShadowed:
|
||||
case ICStub::GetElem_NativeSlot:
|
||||
case ICStub::GetElem_NativePrototypeSlot:
|
||||
case ICStub::GetElem_NativePrototypeCallNative:
|
||||
case ICStub::GetElem_NativePrototypeCallScripted:
|
||||
case ICStub::GetElem_UnboxedProperty:
|
||||
case ICStub::GetElem_NativeSlotName:
|
||||
case ICStub::GetElem_NativeSlotSymbol:
|
||||
case ICStub::GetElem_NativePrototypeSlotName:
|
||||
case ICStub::GetElem_NativePrototypeSlotSymbol:
|
||||
case ICStub::GetElem_NativePrototypeCallNativeName:
|
||||
case ICStub::GetElem_NativePrototypeCallNativeSymbol:
|
||||
case ICStub::GetElem_NativePrototypeCallScriptedName:
|
||||
case ICStub::GetElem_NativePrototypeCallScriptedSymbol:
|
||||
case ICStub::GetElem_UnboxedPropertyName:
|
||||
case ICStub::GetElem_String:
|
||||
case ICStub::GetElem_Dense:
|
||||
case ICStub::GetElem_TypedArray:
|
||||
|
@ -189,31 +189,61 @@ ICStub::trace(JSTracer* trc)
|
||||
TraceEdge(trc, &callStub->expectedThis(), "baseline-callstringsplit-this");
|
||||
break;
|
||||
}
|
||||
case ICStub::GetElem_NativeSlot:
|
||||
case ICStub::GetElem_UnboxedProperty: {
|
||||
ICGetElemNativeSlotStub* getElemStub =
|
||||
reinterpret_cast<ICGetElemNativeSlotStub*>(this);
|
||||
case ICStub::GetElem_NativeSlotName:
|
||||
case ICStub::GetElem_NativeSlotSymbol:
|
||||
case ICStub::GetElem_UnboxedPropertyName: {
|
||||
ICGetElemNativeStub* getElemStub = static_cast<ICGetElemNativeStub*>(this);
|
||||
getElemStub->receiverGuard().trace(trc);
|
||||
TraceEdge(trc, &getElemStub->name(), "baseline-getelem-native-name");
|
||||
if (getElemStub->isSymbol()) {
|
||||
ICGetElem_NativeSlot<JS::Symbol*>* typedGetElemStub = toGetElem_NativeSlotSymbol();
|
||||
TraceEdge(trc, &typedGetElemStub->key(), "baseline-getelem-native-key");
|
||||
} else {
|
||||
ICGetElemNativeSlotStub<PropertyName*>* typedGetElemStub =
|
||||
reinterpret_cast<ICGetElemNativeSlotStub<PropertyName*>*>(this);
|
||||
TraceEdge(trc, &typedGetElemStub->key(), "baseline-getelem-native-key");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ICStub::GetElem_NativePrototypeSlot: {
|
||||
ICGetElem_NativePrototypeSlot* getElemStub = toGetElem_NativePrototypeSlot();
|
||||
case ICStub::GetElem_NativePrototypeSlotName:
|
||||
case ICStub::GetElem_NativePrototypeSlotSymbol: {
|
||||
ICGetElemNativeStub* getElemStub = static_cast<ICGetElemNativeStub*>(this);
|
||||
getElemStub->receiverGuard().trace(trc);
|
||||
TraceEdge(trc, &getElemStub->name(), "baseline-getelem-nativeproto-name");
|
||||
TraceEdge(trc, &getElemStub->holder(), "baseline-getelem-nativeproto-holder");
|
||||
TraceEdge(trc, &getElemStub->holderShape(), "baseline-getelem-nativeproto-holdershape");
|
||||
if (getElemStub->isSymbol()) {
|
||||
ICGetElem_NativePrototypeSlot<JS::Symbol*>* typedGetElemStub
|
||||
= toGetElem_NativePrototypeSlotSymbol();
|
||||
TraceEdge(trc, &typedGetElemStub->key(), "baseline-getelem-nativeproto-key");
|
||||
TraceEdge(trc, &typedGetElemStub->holder(), "baseline-getelem-nativeproto-holder");
|
||||
TraceEdge(trc, &typedGetElemStub->holderShape(), "baseline-getelem-nativeproto-holdershape");
|
||||
} else {
|
||||
ICGetElem_NativePrototypeSlot<PropertyName*>* typedGetElemStub
|
||||
= toGetElem_NativePrototypeSlotName();
|
||||
TraceEdge(trc, &typedGetElemStub->key(), "baseline-getelem-nativeproto-key");
|
||||
TraceEdge(trc, &typedGetElemStub->holder(), "baseline-getelem-nativeproto-holder");
|
||||
TraceEdge(trc, &typedGetElemStub->holderShape(), "baseline-getelem-nativeproto-holdershape");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ICStub::GetElem_NativePrototypeCallNative:
|
||||
case ICStub::GetElem_NativePrototypeCallScripted: {
|
||||
ICGetElemNativePrototypeCallStub* callStub =
|
||||
reinterpret_cast<ICGetElemNativePrototypeCallStub*>(this);
|
||||
callStub->receiverGuard().trace(trc);
|
||||
TraceEdge(trc, &callStub->name(), "baseline-getelem-nativeprotocall-name");
|
||||
TraceEdge(trc, &callStub->getter(), "baseline-getelem-nativeprotocall-getter");
|
||||
TraceEdge(trc, &callStub->holder(), "baseline-getelem-nativeprotocall-holder");
|
||||
TraceEdge(trc, &callStub->holderShape(), "baseline-getelem-nativeprotocall-holdershape");
|
||||
case ICStub::GetElem_NativePrototypeCallNativeName:
|
||||
case ICStub::GetElem_NativePrototypeCallNativeSymbol:
|
||||
case ICStub::GetElem_NativePrototypeCallScriptedName:
|
||||
case ICStub::GetElem_NativePrototypeCallScriptedSymbol: {
|
||||
ICGetElemNativeStub* getElemStub = static_cast<ICGetElemNativeStub*>(this);
|
||||
getElemStub->receiverGuard().trace(trc);
|
||||
if (getElemStub->isSymbol()) {
|
||||
ICGetElemNativePrototypeCallStub<JS::Symbol*>* callStub =
|
||||
reinterpret_cast<ICGetElemNativePrototypeCallStub<JS::Symbol*>*>(this);
|
||||
TraceEdge(trc, &callStub->key(), "baseline-getelem-nativeprotocall-key");
|
||||
TraceEdge(trc, &callStub->getter(), "baseline-getelem-nativeprotocall-getter");
|
||||
TraceEdge(trc, &callStub->holder(), "baseline-getelem-nativeprotocall-holder");
|
||||
TraceEdge(trc, &callStub->holderShape(), "baseline-getelem-nativeprotocall-holdershape");
|
||||
} else {
|
||||
ICGetElemNativePrototypeCallStub<PropertyName*>* callStub =
|
||||
reinterpret_cast<ICGetElemNativePrototypeCallStub<PropertyName*>*>(this);
|
||||
TraceEdge(trc, &callStub->key(), "baseline-getelem-nativeprotocall-key");
|
||||
TraceEdge(trc, &callStub->getter(), "baseline-getelem-nativeprotocall-getter");
|
||||
TraceEdge(trc, &callStub->holder(), "baseline-getelem-nativeprotocall-holder");
|
||||
TraceEdge(trc, &callStub->holderShape(), "baseline-getelem-nativeprotocall-holdershape");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ICStub::GetElem_Dense: {
|
||||
|
@ -690,11 +690,15 @@ class ICStub
|
||||
case Call_ScriptedFunCall:
|
||||
case Call_StringSplit:
|
||||
case WarmUpCounter_Fallback:
|
||||
case GetElem_NativeSlot:
|
||||
case GetElem_NativePrototypeSlot:
|
||||
case GetElem_NativePrototypeCallNative:
|
||||
case GetElem_NativePrototypeCallScripted:
|
||||
case GetElem_UnboxedProperty:
|
||||
case GetElem_NativeSlotName:
|
||||
case GetElem_NativeSlotSymbol:
|
||||
case GetElem_NativePrototypeSlotName:
|
||||
case GetElem_NativePrototypeSlotSymbol:
|
||||
case GetElem_NativePrototypeCallNativeName:
|
||||
case GetElem_NativePrototypeCallNativeSymbol:
|
||||
case GetElem_NativePrototypeCallScriptedName:
|
||||
case GetElem_NativePrototypeCallScriptedSymbol:
|
||||
case GetElem_UnboxedPropertyName:
|
||||
case GetProp_CallScripted:
|
||||
case GetProp_CallNative:
|
||||
case GetProp_CallDOMProxyNative:
|
||||
|
Loading…
Reference in New Issue
Block a user