From ab384724ae4a27b10cd95c230fb3d13908cb9a2f Mon Sep 17 00:00:00 2001 From: Johannes Schulte Date: Tue, 7 Apr 2015 17:49:36 +0200 Subject: [PATCH] Bug 1038859 - Add symbol-support to Baseline GetElem ICs. r=djvj --- js/src/jit/BaselineDebugModeOSR.cpp | 6 +- js/src/jit/BaselineIC.cpp | 508 ++++++++++++++++++---------- js/src/jit/BaselineIC.h | 268 ++++++++++----- js/src/jit/BaselineICList.h | 14 +- js/src/jit/BaselineInspector.cpp | 14 +- js/src/jit/SharedIC.cpp | 68 ++-- js/src/jit/SharedIC.h | 14 +- 7 files changed, 590 insertions(+), 302 deletions(-) diff --git a/js/src/jit/BaselineDebugModeOSR.cpp b/js/src/jit/BaselineDebugModeOSR.cpp index 8471a4a19b59..c366da8e755c 100644 --- a/js/src/jit/BaselineDebugModeOSR.cpp +++ b/js/src/jit/BaselineDebugModeOSR.cpp @@ -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) \ diff --git a/js/src/jit/BaselineIC.cpp b/js/src/jit/BaselineIC.cpp index db41f17d3318..d3befacc0fdc 100644 --- a/js/src/jit/BaselineIC.cpp +++ b/js/src/jit/BaselineIC.cpp @@ -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(LookupNoSuchMethodHandler); + +template static bool GetElemNativeStubExists(ICGetElem_Fallback* stub, HandleObject obj, HandleObject holder, - HandlePropertyName propName, bool needsAtomize) + Handle 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(*iter); - if (propName != getElemNativeStub->name()) + if(mozilla::IsSame::value != + static_cast(*iter)->isSymbol()) + { + continue; + } + + ICGetElemNativeStubImpl* getElemNativeStub = + reinterpret_cast*>(*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* protoStub = + reinterpret_cast*>(*iter); if (holder != protoStub->holder()) continue; @@ -3016,11 +3033,13 @@ GetElemNativeStubExists(ICGetElem_Fallback* stub, HandleObject obj, HandleObject if (holder->as().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(*iter); + ICGetElemNativePrototypeCallStub* protoStub = + reinterpret_cast*>(*iter); if (holder != protoStub->holder()) continue; @@ -3035,29 +3054,40 @@ GetElemNativeStubExists(ICGetElem_Fallback* stub, HandleObject obj, HandleObject return false; } +template static void RemoveExistingGetElemNativeStubs(JSContext* cx, ICGetElem_Fallback* stub, HandleObject obj, - HandleObject holder, HandlePropertyName propName, - bool needsAtomize) + HandleObject holder, Handle 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(*iter); - if (propName != getElemNativeStub->name()) + if(mozilla::IsSame::value != + static_cast(*iter)->isSymbol()) + { + continue; + } + + ICGetElemNativeStubImpl* getElemNativeStub = + reinterpret_cast*>(*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* protoStub = + reinterpret_cast*>(*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(*iter); + MOZ_ASSERT(iter->isGetElem_NativePrototypeCallNativeName() || + iter->isGetElem_NativePrototypeCallNativeSymbol() || + iter->isGetElem_NativePrototypeCallScriptedName() || + iter->isGetElem_NativePrototypeCallScriptedSymbol()); + ICGetElemNativePrototypeCallStub* protoStub = + reinterpret_cast*>(*iter); if (holder != protoStub->holder()) continue; @@ -3133,6 +3166,31 @@ ArgumentsGetElemStubExists(ICGetElem_Fallback* stub, ICGetElem_Arguments::Which return false; } +template +static T +getKey(jsid id) +{ + MOZ_ASSERT_UNREACHABLE("Key has to be PropertyName or Symbol"); + return false; +} + +template <> +JS::Symbol* getKey(jsid id) +{ + if (!JSID_IS_SYMBOL(id)) + return nullptr; + return JSID_TO_SYMBOL(id); +} + +template <> +PropertyName* getKey(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 +static bool +checkAtomize(HandleValue key) +{ + MOZ_ASSERT_UNREACHABLE("Key has to be PropertyName or Symbol"); + return false; +} + +template <> +bool checkAtomize(HandleValue key) +{ + return false; +} + +template <> +bool checkAtomize(HandleValue key) +{ + return !key.toString()->isAtom(); +} + +template 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(cx, keyVal, &id)) + return false; + + Rooted key(cx, getKey(id)); + if (!key) + return true; + bool needsAtomize = checkAtomize(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(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(cx, stub, obj, holder, key, needsAtomize); ICStub* monitorStub = stub->fallbackMonitorStub()->firstMonitorStub(); if (obj->is() && holder == obj) { - const UnboxedLayout::Property* property = - obj->as().layout().lookup(propName); + const UnboxedLayout::Property* property = obj->as().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 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().maybeExpando()->lookup(cx, propName); + Shape* shape = obj->as().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 compiler(cx, getGetElemStubKind(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(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().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 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 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(cx, keyVal, &id)) + return false; - RootedPropertyName propName(cx, JSID_TO_ATOM(id)->asPropertyName()); - bool needsAtomize = !key.toString()->isAtom(); + Rooted key(cx, getKey(id)); + if (!key) + return true; + bool needsAtomize = checkAtomize(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(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(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(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 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()) && rhs.isString()) { + if (obj->isNative() || obj->is()) { RootedScript rootedScript(cx, script); - if (!TryAttachNativeOrUnboxedGetValueElemStub(cx, rootedScript, pc, stub, - obj, rhs, attached)) - { - return false; + if (rhs.isString()) { + if (!TryAttachNativeOrUnboxedGetValueElemStub(cx, rootedScript, pc, stub, + obj, rhs, attached)) + { + return false; + } + } else if (rhs.isSymbol()) { + if (!TryAttachNativeOrUnboxedGetValueElemStub(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()); - 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()); + if (!TryAttachNativeGetAccessorElemStub(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()); + if (!TryAttachNativeGetAccessorElemStub(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(DoAtomizeString); +template bool -ICGetElemNativeCompiler::emitCallNative(MacroAssembler& masm, Register objReg) +ICGetElemNativeCompiler::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::offsetOfGetter()), objReg); masm.push(objReg); regs.add(objReg); @@ -3707,8 +3825,9 @@ ICGetElemNativeCompiler::emitCallNative(MacroAssembler& masm, Register objReg) return true; } +template bool -ICGetElemNativeCompiler::emitCallScripted(MacroAssembler& masm, Register objReg) +ICGetElemNativeCompiler::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::offsetOfGetter()), callee); // Push argc, callee, and descriptor. { @@ -3774,31 +3893,34 @@ ICGetElemNativeCompiler::emitCallScripted(MacroAssembler& masm, Register objReg) return true; } +template bool -ICGetElemNativeCompiler::generateStubCode(MacroAssembler& masm) +ICGetElemNativeCompiler::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::emitCheckKey(MacroAssembler& masm, Label& failure) +{ + MOZ_ASSERT(!needsAtomize_); + masm.branchTestSymbol(Assembler::NotEqual, R1, &failure); + Address symbolAddr(ICStubReg, ICGetElemNativeStubImpl::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::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::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 +bool +ICGetElemNativeCompiler::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::offsetOfHolder()), holderReg); masm.loadPtr(Address(ICStubReg, - ICGetElemNativePrototypeCallStub::offsetOfHolderShape()), + ICGetElemNativePrototypeCallStub::offsetOfHolderShape()), scratchReg); } else { masm.loadPtr(Address(ICStubReg, - ICGetElem_NativePrototypeSlot::offsetOfHolder()), + ICGetElem_NativePrototypeSlot::offsetOfHolder()), holderReg); masm.loadPtr(Address(ICStubReg, - ICGetElem_NativePrototypeSlot::offsetOfHolderShape()), + ICGetElem_NativePrototypeSlot::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::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::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::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(acctype) << ACCESSTYPE_SHIFT) | - (static_cast(needsAtomize) << NEEDS_ATOMIZE_SHIFT); + (static_cast(needsAtomize) << NEEDS_ATOMIZE_SHIFT) | + (static_cast(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 +ICGetElemNativeGetterStub::ICGetElemNativeGetterStub( + ICStub::Kind kind, JitCode* stubCode, ICStub* firstMonitorStub, + ReceiverGuard guard, const T* key, AccType acctype, bool needsAtomize, + JSFunction* getter, uint32_t pcOffset) + : ICGetElemNativeStubImpl(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 +ICGetElem_NativePrototypeSlot::ICGetElem_NativePrototypeSlot( + JitCode* stubCode, ICStub* firstMonitorStub, ReceiverGuard guard, + const T* key, AccType acctype, bool needsAtomize, uint32_t offset, + JSObject* holder, Shape* holderShape) + : ICGetElemNativeSlotStub(getGetElemStubKind(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 +ICGetElemNativePrototypeCallStub::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(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 +/* static */ ICGetElem_NativePrototypeCallNative* +ICGetElem_NativePrototypeCallNative::Clone(JSContext* cx, + ICStubSpace* space, + ICStub* firstMonitorStub, + ICGetElem_NativePrototypeCallNative& other) { - return New(cx, space, other.jitCode(), firstMonitorStub, - other.receiverGuard(), other.name(), other.accessType(), - other.needsAtomize(), other.getter(), other.pcOffset_, - other.holder(), other.holderShape()); + return ICStub::New>(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 +/* static */ ICGetElem_NativePrototypeCallScripted* +ICGetElem_NativePrototypeCallScripted::Clone(JSContext* cx, + ICStubSpace* space, + ICStub* firstMonitorStub, + ICGetElem_NativePrototypeCallScripted& other) { - return New(cx, space, other.jitCode(), firstMonitorStub, - other.receiverGuard(), other.name(), - other.accessType(), other.needsAtomize(), other.getter(), - other.pcOffset_, other.holder(), other.holderShape()); + return ICStub::New>(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) diff --git a/js/src/jit/BaselineIC.h b/js/src/jit/BaselineIC.h index 3761195ddf19..4cbd4de69dc6 100644 --- a/js/src/jit/BaselineIC.h +++ b/js/src/jit/BaselineIC.h @@ -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((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 ICGetElemNativeStubImpl : public ICGetElemNativeStub +{ + protected: + HeapPtr 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::value), + key_(*key) + {} + + public: + HeapPtr& key() { + return key_; + } + static size_t offsetOfKey() { + return offsetof(ICGetElemNativeStubImpl, key_); + } +}; + +typedef ICGetElemNativeStub::AccessType AccType; + +template +class ICGetElemNativeSlotStub : public ICGetElemNativeStubImpl { 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(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 ICGetElemNativeGetterStub : public ICGetElemNativeStubImpl { 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 +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(kind + mozilla::IsSame::value); +} + +template +class ICGetElem_NativeSlot : public ICGetElemNativeSlotStub { 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(getGetElemStubKind(ICStub::GetElem_NativeSlotName), + stubCode, firstMonitorStub, guard, + key, acctype, needsAtomize, offset) {} }; -class ICGetElem_UnboxedProperty : public ICGetElemNativeSlotStub +class ICGetElem_NativeSlotName : + public ICGetElem_NativeSlot +{}; +class ICGetElem_NativeSlotSymbol : + public ICGetElem_NativeSlot +{}; + +template +class ICGetElem_UnboxedProperty : public ICGetElemNativeSlotStub { 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(ICStub::GetElem_UnboxedPropertyName, stubCode, firstMonitorStub, + guard, key, acctype, needsAtomize, offset) + {} }; -class ICGetElem_NativePrototypeSlot : public ICGetElemNativeSlotStub +class ICGetElem_UnboxedPropertyName : + public ICGetElem_UnboxedProperty +{}; + +template +class ICGetElem_NativePrototypeSlot : public ICGetElemNativeSlotStub { 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 +{}; +class ICGetElem_NativePrototypeSlotSymbol : + public ICGetElem_NativePrototypeSlot +{}; + +template +class ICGetElemNativePrototypeCallStub : public ICGetElemNativeGetterStub { 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 ICGetElem_NativePrototypeCallNative : public ICGetElemNativePrototypeCallStub { 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(getGetElemStubKind( + 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* Clone(JSContext* cx, ICStubSpace* space, + ICStub* firstMonitorStub, + ICGetElem_NativePrototypeCallNative& other); }; -class ICGetElem_NativePrototypeCallScripted : public ICGetElemNativePrototypeCallStub +class ICGetElem_NativePrototypeCallNativeName : + public ICGetElem_NativePrototypeCallNative +{}; +class ICGetElem_NativePrototypeCallNativeSymbol : + public ICGetElem_NativePrototypeCallNative +{}; + +template +class ICGetElem_NativePrototypeCallScripted : public ICGetElemNativePrototypeCallStub { 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(getGetElemStubKind( + ICStub::GetElem_NativePrototypeCallScriptedName), + stubCode, firstMonitorStub, guard, key, acctype, + needsAtomize, getter, pcOffset, holder, holderShape) {} public: - static ICGetElem_NativePrototypeCallScripted* + static ICGetElem_NativePrototypeCallScripted* Clone(JSContext* cx, ICStubSpace* space, ICStub* firstMonitorStub, - ICGetElem_NativePrototypeCallScripted& other); + ICGetElem_NativePrototypeCallScripted& other); }; +class ICGetElem_NativePrototypeCallScriptedName : + public ICGetElem_NativePrototypeCallScripted +{}; +class ICGetElem_NativePrototypeCallScriptedSymbol : + public ICGetElem_NativePrototypeCallScripted +{}; + // Compiler for GetElem_NativeSlot and GetElem_NativePrototypeSlot stubs. +template class ICGetElemNativeCompiler : public ICStubCompiler { bool isCallElem_; ICStub* firstMonitorStub_; HandleObject obj_; HandleObject holder_; - HandlePropertyName name_; - ICGetElemNativeStub::AccessType acctype_; + Handle 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(needsAtomize_) << 18) | (static_cast(acctype_) << 19) | (static_cast(unboxedType_) << 22) | - (HeapReceiverGuard::keyBits(obj_) << 26); + (static_cast(mozilla::IsSame::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 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 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( - space, getStubCode(), firstMonitorStub_, guard, name_, acctype_, needsAtomize_, - offset_); + return newStub>( + 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( - space, getStubCode(), firstMonitorStub_, guard, name_, acctype_, needsAtomize_, - offset_); + return newStub>( + space, getStubCode(), firstMonitorStub_, guard, key_.address(), acctype_, + needsAtomize_, offset_); } MOZ_ASSERT(obj_ != holder_); RootedShape holderShape(cx, holder_->as().lastProperty()); - if (kind == ICStub::GetElem_NativePrototypeSlot) { - return newStub( - space, getStubCode(), firstMonitorStub_, guard, name_, acctype_, needsAtomize_, - offset_, holder_, holderShape); + if (kind == ICStub::GetElem_NativePrototypeSlotName || + kind == ICStub::GetElem_NativePrototypeSlotSymbol) + { + return newStub>( + space, getStubCode(), firstMonitorStub_, guard, key_.address(), acctype_, + needsAtomize_, offset_, holder_, holderShape); } - if (kind == ICStub::GetElem_NativePrototypeCallNative) { - return newStub( - space, getStubCode(), firstMonitorStub_, guard, name_, acctype_, needsAtomize_, - getter_, pcOffset_, holder_, holderShape); + if (kind == ICStub::GetElem_NativePrototypeCallNativeSymbol || + kind == ICStub::GetElem_NativePrototypeCallNativeName) { + return newStub>( + 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( - 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>( + space, getStubCode(), firstMonitorStub_, guard, key_.address(), acctype_, + needsAtomize_, getter_, pcOffset_, holder_, holderShape); } MOZ_CRASH("Invalid kind."); diff --git a/js/src/jit/BaselineICList.h b/js/src/jit/BaselineICList.h index e135910eea7b..698b1cf7fb01 100644 --- a/js/src/jit/BaselineICList.h +++ b/js/src/jit/BaselineICList.h @@ -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) \ diff --git a/js/src/jit/BaselineInspector.cpp b/js/src/jit/BaselineInspector.cpp index ee2217a4c7ca..965db229869e 100644 --- a/js/src/jit/BaselineInspector.cpp +++ b/js/src/jit/BaselineInspector.cpp @@ -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: diff --git a/js/src/jit/SharedIC.cpp b/js/src/jit/SharedIC.cpp index 6418445b6883..57cbc839fdd0 100644 --- a/js/src/jit/SharedIC.cpp +++ b/js/src/jit/SharedIC.cpp @@ -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(this); + case ICStub::GetElem_NativeSlotName: + case ICStub::GetElem_NativeSlotSymbol: + case ICStub::GetElem_UnboxedPropertyName: { + ICGetElemNativeStub* getElemStub = static_cast(this); getElemStub->receiverGuard().trace(trc); - TraceEdge(trc, &getElemStub->name(), "baseline-getelem-native-name"); + if (getElemStub->isSymbol()) { + ICGetElem_NativeSlot* typedGetElemStub = toGetElem_NativeSlotSymbol(); + TraceEdge(trc, &typedGetElemStub->key(), "baseline-getelem-native-key"); + } else { + ICGetElemNativeSlotStub* typedGetElemStub = + reinterpret_cast*>(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(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* 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* 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(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(this); + getElemStub->receiverGuard().trace(trc); + if (getElemStub->isSymbol()) { + ICGetElemNativePrototypeCallStub* callStub = + reinterpret_cast*>(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* callStub = + reinterpret_cast*>(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: { diff --git a/js/src/jit/SharedIC.h b/js/src/jit/SharedIC.h index 87afda163cf7..c69f299cede6 100644 --- a/js/src/jit/SharedIC.h +++ b/js/src/jit/SharedIC.h @@ -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: