зеркало из https://github.com/mozilla/gecko-dev.git
Backed out f3da454330a5 (bug 1049290) for adblock plus hangs
This commit is contained in:
Родитель
0455f5bbb5
Коммит
62590c615c
|
@ -350,43 +350,6 @@ ICStub::trace(JSTracer* trc)
|
|||
TraceEdge(trc, &updateStub->group(), "baseline-update-group");
|
||||
break;
|
||||
}
|
||||
case ICStub::In_Native: {
|
||||
ICIn_Native *inStub = toIn_Native();
|
||||
TraceEdge(trc, &inStub->shape(), "baseline-innative-stub-shape");
|
||||
TraceEdge(trc, &inStub->name(), "baseline-innative-stub-name");
|
||||
break;
|
||||
}
|
||||
case ICStub::In_NativePrototype: {
|
||||
ICIn_NativePrototype *inStub = toIn_NativePrototype();
|
||||
TraceEdge(trc, &inStub->shape(), "baseline-innativeproto-stub-shape");
|
||||
TraceEdge(trc, &inStub->name(), "baseline-innativeproto-stub-name");
|
||||
TraceEdge(trc, &inStub->holder(), "baseline-innativeproto-stub-holder");
|
||||
TraceEdge(trc, &inStub->holderShape(), "baseline-innativeproto-stub-holdershape");
|
||||
break;
|
||||
}
|
||||
case ICStub::In_NativeDoesNotExist: {
|
||||
ICIn_NativeDoesNotExist *inStub = toIn_NativeDoesNotExist();
|
||||
TraceEdge(trc, &inStub->name(), "baseline-innativedoesnotexist-stub-name");
|
||||
JS_STATIC_ASSERT(ICIn_NativeDoesNotExist::MAX_PROTO_CHAIN_DEPTH == 8);
|
||||
switch (inStub->protoChainDepth()) {
|
||||
case 0: inStub->toImpl<0>()->traceShapes(trc); break;
|
||||
case 1: inStub->toImpl<1>()->traceShapes(trc); break;
|
||||
case 2: inStub->toImpl<2>()->traceShapes(trc); break;
|
||||
case 3: inStub->toImpl<3>()->traceShapes(trc); break;
|
||||
case 4: inStub->toImpl<4>()->traceShapes(trc); break;
|
||||
case 5: inStub->toImpl<5>()->traceShapes(trc); break;
|
||||
case 6: inStub->toImpl<6>()->traceShapes(trc); break;
|
||||
case 7: inStub->toImpl<7>()->traceShapes(trc); break;
|
||||
case 8: inStub->toImpl<8>()->traceShapes(trc); break;
|
||||
default: MOZ_CRASH("Invalid proto stub.");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ICStub::In_Dense: {
|
||||
ICIn_Dense *inStub = toIn_Dense();
|
||||
TraceEdge(trc, &inStub->shape(), "baseline-in-dense-shape");
|
||||
break;
|
||||
}
|
||||
case ICStub::GetName_Global: {
|
||||
ICGetName_Global* globalStub = toGetName_Global();
|
||||
TraceEdge(trc, &globalStub->shape(), "baseline-global-stub-shape");
|
||||
|
@ -3805,30 +3768,23 @@ ArgumentsGetElemStubExists(ICGetElem_Fallback* stub, ICGetElem_Arguments::Which
|
|||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
IsOptimizableElementPropertyName(JSContext *cx, HandleValue key, MutableHandleId idp)
|
||||
{
|
||||
if (!key.isString())
|
||||
return false;
|
||||
|
||||
// Convert to interned property name.
|
||||
if (!ValueToId<CanGC>(cx, key, idp))
|
||||
return false;
|
||||
|
||||
uint32_t dummy;
|
||||
if (!JSID_IS_ATOM(idp) || JSID_TO_ATOM(idp)->isIndex(&dummy))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
TryAttachNativeGetValueElemStub(JSContext* cx, HandleScript script, jsbytecode* pc,
|
||||
ICGetElem_Fallback* stub, HandleNativeObject obj,
|
||||
HandleValue key)
|
||||
{
|
||||
// Native-object GetElem stubs can't deal with non-string keys.
|
||||
if (!key.isString())
|
||||
return true;
|
||||
|
||||
// Convert to interned property name.
|
||||
RootedId id(cx);
|
||||
if (!IsOptimizableElementPropertyName(cx, key, &id))
|
||||
if (!ValueToId<CanGC>(cx, key, &id))
|
||||
return false;
|
||||
|
||||
uint32_t dummy;
|
||||
if (!JSID_IS_ATOM(id) || JSID_TO_ATOM(id)->isIndex(&dummy))
|
||||
return true;
|
||||
|
||||
RootedPropertyName propName(cx, JSID_TO_ATOM(id)->asPropertyName());
|
||||
|
@ -3885,9 +3841,17 @@ TryAttachNativeGetAccessorElemStub(JSContext* cx, HandleScript script, jsbytecod
|
|||
HandleValue key, bool* attached)
|
||||
{
|
||||
MOZ_ASSERT(!*attached);
|
||||
// Native-object GetElem stubs can't deal with non-string keys.
|
||||
if (!key.isString())
|
||||
return true;
|
||||
|
||||
// Convert to interned property name.
|
||||
RootedId id(cx);
|
||||
if (!IsOptimizableElementPropertyName(cx, key, &id))
|
||||
if (!ValueToId<CanGC>(cx, key, &id))
|
||||
return false;
|
||||
|
||||
uint32_t dummy;
|
||||
if (!JSID_IS_ATOM(id) || JSID_TO_ATOM(id)->isIndex(&dummy))
|
||||
return true;
|
||||
|
||||
RootedPropertyName propName(cx, JSID_TO_ATOM(id)->asPropertyName());
|
||||
|
@ -4000,14 +3964,6 @@ TypedThingRequiresFloatingPoint(JSObject* obj)
|
|||
type == Scalar::Float64;
|
||||
}
|
||||
|
||||
static bool
|
||||
IsNativeDenseElementAccess(HandleObject obj, HandleValue key)
|
||||
{
|
||||
if (obj->isNative() && key.isInt32() && key.toInt32() >= 0 && !IsAnyTypedArray(obj.get()))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
TryAttachGetElemStub(JSContext* cx, JSScript* script, jsbytecode* pc, ICGetElem_Fallback* stub,
|
||||
HandleValue lhs, HandleValue rhs, HandleValue res)
|
||||
|
@ -4071,28 +4027,30 @@ TryAttachGetElemStub(JSContext* cx, JSScript* script, jsbytecode* pc, ICGetElem_
|
|||
}
|
||||
}
|
||||
|
||||
// Check for NativeObject[int] dense accesses.
|
||||
if (IsNativeDenseElementAccess(obj, rhs)) {
|
||||
JitSpew(JitSpew_BaselineIC, " Generating GetElem(Native[Int32] dense) stub");
|
||||
ICGetElem_Dense::Compiler compiler(cx, stub->fallbackMonitorStub()->firstMonitorStub(),
|
||||
obj->as<NativeObject>().lastProperty(), isCallElem);
|
||||
ICStub* denseStub = compiler.getStub(compiler.getStubSpace(script));
|
||||
if (!denseStub)
|
||||
return false;
|
||||
if (obj->isNative()) {
|
||||
// Check for NativeObject[int] dense accesses.
|
||||
if (rhs.isInt32() && rhs.toInt32() >= 0 && !IsAnyTypedArray(obj.get())) {
|
||||
JitSpew(JitSpew_BaselineIC, " Generating GetElem(Native[Int32] dense) stub");
|
||||
ICGetElem_Dense::Compiler compiler(cx, stub->fallbackMonitorStub()->firstMonitorStub(),
|
||||
obj->as<NativeObject>().lastProperty(), isCallElem);
|
||||
ICStub* denseStub = compiler.getStub(compiler.getStubSpace(script));
|
||||
if (!denseStub)
|
||||
return false;
|
||||
|
||||
stub->addNewStub(denseStub);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check for NativeObject[id] shape-optimizable accesses.
|
||||
if (obj->isNative() && rhs.isString()) {
|
||||
RootedScript rootedScript(cx, script);
|
||||
if (!TryAttachNativeGetValueElemStub(cx, rootedScript, pc, stub,
|
||||
obj.as<NativeObject>(), rhs))
|
||||
{
|
||||
return false;
|
||||
stub->addNewStub(denseStub);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check for NativeObject[id] shape-optimizable accesses.
|
||||
if (rhs.isString()) {
|
||||
RootedScript rootedScript(cx, script);
|
||||
if (!TryAttachNativeGetValueElemStub(cx, rootedScript, pc, stub,
|
||||
obj.as<NativeObject>(), rhs))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
script = rootedScript;
|
||||
}
|
||||
script = rootedScript;
|
||||
}
|
||||
|
||||
// Check for TypedArray[int] => Number and TypedObject[int] => Number accesses.
|
||||
|
@ -5235,7 +5193,10 @@ DoSetElemFallback(JSContext* cx, BaselineFrame* frame, ICSetElem_Fallback* stub_
|
|||
}
|
||||
|
||||
// Try to generate new stubs.
|
||||
if (IsNativeDenseElementAccess(obj, index) && !rhs.isMagic(JS_ELEMENTS_HOLE))
|
||||
if (obj->isNative() &&
|
||||
!IsAnyTypedArray(obj.get()) &&
|
||||
index.isInt32() && index.toInt32() >= 0 &&
|
||||
!rhs.isMagic(JS_ELEMENTS_HOLE))
|
||||
{
|
||||
HandleNativeObject nobj = obj.as<NativeObject>();
|
||||
|
||||
|
@ -5856,96 +5817,8 @@ ICSetElem_TypedArray::Compiler::generateStubCode(MacroAssembler& masm)
|
|||
//
|
||||
|
||||
static bool
|
||||
TryAttachDenseInStub(JSContext *cx, HandleScript script, ICIn_Fallback *stub,
|
||||
HandleValue key, HandleObject obj, bool *attached)
|
||||
{
|
||||
MOZ_ASSERT(!*attached);
|
||||
|
||||
if (!IsNativeDenseElementAccess(obj, key))
|
||||
return true;
|
||||
|
||||
JitSpew(JitSpew_BaselineIC, " Generating In(Native[Int32] dense) stub");
|
||||
ICIn_Dense::Compiler compiler(cx, obj->as<NativeObject>().lastProperty());
|
||||
ICStub *denseStub = compiler.getStub(compiler.getStubSpace(script));
|
||||
if (!denseStub)
|
||||
return false;
|
||||
|
||||
*attached = true;
|
||||
stub->addNewStub(denseStub);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
TryAttachNativeInStub(JSContext *cx, HandleScript script, ICIn_Fallback *stub,
|
||||
HandleValue key, HandleObject obj, bool *attached)
|
||||
{
|
||||
MOZ_ASSERT(!*attached);
|
||||
|
||||
RootedId id(cx);
|
||||
if (!IsOptimizableElementPropertyName(cx, key, &id))
|
||||
return true;
|
||||
|
||||
RootedPropertyName name(cx, JSID_TO_ATOM(id)->asPropertyName());
|
||||
RootedShape shape(cx);
|
||||
RootedObject holder(cx);
|
||||
if (!EffectlesslyLookupProperty(cx, obj, name, &holder, &shape))
|
||||
return false;
|
||||
|
||||
if (IsCacheableGetPropReadSlot(obj, holder, shape)) {
|
||||
ICStub::Kind kind = (obj == holder) ? ICStub::In_Native
|
||||
: ICStub::In_NativePrototype;
|
||||
JitSpew(JitSpew_BaselineIC, " Generating In(Native %s) stub",
|
||||
(obj == holder) ? "direct" : "prototype");
|
||||
ICInNativeCompiler compiler(cx, kind, obj, holder, name);
|
||||
ICStub *newStub = compiler.getStub(compiler.getStubSpace(script));
|
||||
if (!newStub)
|
||||
return false;
|
||||
|
||||
*attached = true;
|
||||
stub->addNewStub(newStub);
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
TryAttachNativeInDoesNotExistStub(JSContext *cx, HandleScript script,
|
||||
ICIn_Fallback *stub, HandleValue key,
|
||||
HandleObject obj, bool *attached)
|
||||
{
|
||||
MOZ_ASSERT(!*attached);
|
||||
|
||||
RootedId id(cx);
|
||||
if (!IsOptimizableElementPropertyName(cx, key, &id))
|
||||
return true;
|
||||
|
||||
// Check if does-not-exist can be confirmed on property.
|
||||
RootedPropertyName name(cx, JSID_TO_ATOM(id)->asPropertyName());
|
||||
RootedObject lastProto(cx);
|
||||
size_t protoChainDepth = SIZE_MAX;
|
||||
if (!CheckHasNoSuchProperty(cx, obj, name, &lastProto, &protoChainDepth))
|
||||
return true;
|
||||
MOZ_ASSERT(protoChainDepth < SIZE_MAX);
|
||||
|
||||
if (protoChainDepth > ICIn_NativeDoesNotExist::MAX_PROTO_CHAIN_DEPTH)
|
||||
return true;
|
||||
|
||||
// Confirmed no-such-property. Add stub.
|
||||
JitSpew(JitSpew_BaselineIC, " Generating In_NativeDoesNotExist stub");
|
||||
ICInNativeDoesNotExistCompiler compiler(cx, obj, name, protoChainDepth);
|
||||
ICStub *newStub = compiler.getStub(compiler.getStubSpace(script));
|
||||
if (!newStub)
|
||||
return false;
|
||||
|
||||
*attached = true;
|
||||
stub->addNewStub(newStub);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
DoInFallback(JSContext *cx, BaselineFrame *frame, ICIn_Fallback *stub,
|
||||
HandleValue key, HandleValue objValue, MutableHandleValue res)
|
||||
DoInFallback(JSContext* cx, ICIn_Fallback* stub, HandleValue key, HandleValue objValue,
|
||||
MutableHandleValue res)
|
||||
{
|
||||
FallbackICSpew(cx, stub, "In");
|
||||
|
||||
|
@ -5959,33 +5832,13 @@ DoInFallback(JSContext *cx, BaselineFrame *frame, ICIn_Fallback *stub,
|
|||
bool cond = false;
|
||||
if (!OperatorIn(cx, key, obj, &cond))
|
||||
return false;
|
||||
|
||||
res.setBoolean(cond);
|
||||
|
||||
if (obj->isNative()) {
|
||||
RootedScript script(cx, frame->script());
|
||||
bool attached = false;
|
||||
if (cond) {
|
||||
if (!TryAttachDenseInStub(cx, script, stub, key, obj, &attached))
|
||||
return false;
|
||||
if (attached)
|
||||
return true;
|
||||
if (!TryAttachNativeInStub(cx, script, stub, key, obj, &attached))
|
||||
return false;
|
||||
if (attached)
|
||||
return true;
|
||||
} else {
|
||||
if (!TryAttachNativeInDoesNotExistStub(cx, script, stub, key, obj, &attached))
|
||||
return false;
|
||||
if (attached)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
typedef bool (*DoInFallbackFn)(JSContext *, BaselineFrame *, ICIn_Fallback *, HandleValue,
|
||||
HandleValue, MutableHandleValue);
|
||||
typedef bool (*DoInFallbackFn)(JSContext*, ICIn_Fallback*, HandleValue, HandleValue,
|
||||
MutableHandleValue);
|
||||
static const VMFunction DoInFallbackInfo =
|
||||
FunctionInfo<DoInFallbackFn>(DoInFallback, TailCall, PopValues(2));
|
||||
|
||||
|
@ -6002,182 +5855,10 @@ ICIn_Fallback::Compiler::generateStubCode(MacroAssembler& masm)
|
|||
masm.pushValue(R1);
|
||||
masm.pushValue(R0);
|
||||
masm.push(BaselineStubReg);
|
||||
masm.pushBaselineFramePtr(BaselineFrameReg, R0.scratchReg());
|
||||
|
||||
return tailCallVM(DoInFallbackInfo, masm);
|
||||
}
|
||||
|
||||
bool
|
||||
ICInNativeCompiler::generateStubCode(MacroAssembler &masm)
|
||||
{
|
||||
Label failure, failurePopR0Scratch;
|
||||
|
||||
masm.branchTestString(Assembler::NotEqual, R0, &failure);
|
||||
masm.branchTestObject(Assembler::NotEqual, R1, &failure);
|
||||
|
||||
AllocatableGeneralRegisterSet regs(availableGeneralRegs(2));
|
||||
Register scratch = regs.takeAny();
|
||||
|
||||
// Check key identity.
|
||||
Register strExtract = masm.extractString(R0, ExtractTemp0);
|
||||
masm.loadPtr(Address(BaselineStubReg, ICInNativeStub::offsetOfName()), scratch);
|
||||
masm.branchPtr(Assembler::NotEqual, strExtract, scratch, &failure);
|
||||
|
||||
// Unbox and shape guard object.
|
||||
Register objReg = masm.extractObject(R1, ExtractTemp0);
|
||||
masm.loadPtr(Address(BaselineStubReg, ICInNativeStub::offsetOfShape()), scratch);
|
||||
masm.branchTestObjShape(Assembler::NotEqual, objReg, scratch, &failure);
|
||||
|
||||
if (kind == ICStub::In_NativePrototype) {
|
||||
// Shape guard holder. Use R0 scrachReg since on x86 there're not enough registers.
|
||||
Register holderReg = R0.scratchReg();
|
||||
masm.push(R0.scratchReg());
|
||||
masm.loadPtr(Address(BaselineStubReg, ICIn_NativePrototype::offsetOfHolder()),
|
||||
holderReg);
|
||||
masm.loadPtr(Address(BaselineStubReg, ICIn_NativePrototype::offsetOfHolderShape()),
|
||||
scratch);
|
||||
masm.branchTestObjShape(Assembler::NotEqual, holderReg, scratch, &failurePopR0Scratch);
|
||||
masm.addPtr(Imm32(sizeof(size_t)), StackPointer);
|
||||
}
|
||||
|
||||
masm.moveValue(BooleanValue(true), R0);
|
||||
|
||||
EmitReturnFromIC(masm);
|
||||
|
||||
// Failure case - jump to next stub
|
||||
masm.bind(&failurePopR0Scratch);
|
||||
masm.pop(R0.scratchReg());
|
||||
masm.bind(&failure);
|
||||
EmitStubGuardFailure(masm);
|
||||
return true;
|
||||
}
|
||||
|
||||
ICStub *
|
||||
ICInNativeDoesNotExistCompiler::getStub(ICStubSpace *space)
|
||||
{
|
||||
AutoShapeVector shapes(cx);
|
||||
if (!shapes.append(obj_->as<NativeObject>().lastProperty()))
|
||||
return nullptr;
|
||||
|
||||
if (!GetProtoShapes(obj_, protoChainDepth_, &shapes))
|
||||
return nullptr;
|
||||
|
||||
JS_STATIC_ASSERT(ICIn_NativeDoesNotExist::MAX_PROTO_CHAIN_DEPTH == 8);
|
||||
|
||||
ICStub *stub = nullptr;
|
||||
switch (protoChainDepth_) {
|
||||
case 0: stub = getStubSpecific<0>(space, &shapes); break;
|
||||
case 1: stub = getStubSpecific<1>(space, &shapes); break;
|
||||
case 2: stub = getStubSpecific<2>(space, &shapes); break;
|
||||
case 3: stub = getStubSpecific<3>(space, &shapes); break;
|
||||
case 4: stub = getStubSpecific<4>(space, &shapes); break;
|
||||
case 5: stub = getStubSpecific<5>(space, &shapes); break;
|
||||
case 6: stub = getStubSpecific<6>(space, &shapes); break;
|
||||
case 7: stub = getStubSpecific<7>(space, &shapes); break;
|
||||
case 8: stub = getStubSpecific<8>(space, &shapes); break;
|
||||
default: MOZ_CRASH("ProtoChainDepth too high.");
|
||||
}
|
||||
if (!stub)
|
||||
return nullptr;
|
||||
return stub;
|
||||
}
|
||||
|
||||
bool
|
||||
ICInNativeDoesNotExistCompiler::generateStubCode(MacroAssembler &masm)
|
||||
{
|
||||
Label failure, failurePopR0Scratch;
|
||||
|
||||
masm.branchTestString(Assembler::NotEqual, R0, &failure);
|
||||
masm.branchTestObject(Assembler::NotEqual, R1, &failure);
|
||||
|
||||
AllocatableGeneralRegisterSet regs(availableGeneralRegs(2));
|
||||
Register scratch = regs.takeAny();
|
||||
|
||||
#ifdef DEBUG
|
||||
// Ensure that protoChainDepth_ matches the protoChainDepth stored on the stub.
|
||||
{
|
||||
Label ok;
|
||||
masm.load16ZeroExtend(Address(BaselineStubReg, ICStub::offsetOfExtra()), scratch);
|
||||
masm.branch32(Assembler::Equal, scratch, Imm32(protoChainDepth_), &ok);
|
||||
masm.assumeUnreachable("Non-matching proto chain depth on stub.");
|
||||
masm.bind(&ok);
|
||||
}
|
||||
#endif // DEBUG
|
||||
|
||||
// Check key identity.
|
||||
Register strExtract = masm.extractString(R0, ExtractTemp0);
|
||||
masm.loadPtr(Address(BaselineStubReg, ICIn_NativeDoesNotExist::offsetOfName()), scratch);
|
||||
masm.branchPtr(Assembler::NotEqual, strExtract, scratch, &failure);
|
||||
|
||||
// Unbox and guard against old shape.
|
||||
Register objReg = masm.extractObject(R1, ExtractTemp0);
|
||||
masm.loadPtr(Address(BaselineStubReg, ICIn_NativeDoesNotExist::offsetOfShape(0)),
|
||||
scratch);
|
||||
masm.branchTestObjShape(Assembler::NotEqual, objReg, scratch, &failure);
|
||||
|
||||
// Check the proto chain.
|
||||
Register protoReg = R0.scratchReg();
|
||||
masm.push(R0.scratchReg());
|
||||
for (size_t i = 0; i < protoChainDepth_; ++i) {
|
||||
masm.loadObjProto(i == 0 ? objReg : protoReg, protoReg);
|
||||
masm.branchTestPtr(Assembler::Zero, protoReg, protoReg, &failure);
|
||||
size_t shapeOffset = ICIn_NativeDoesNotExistImpl<0>::offsetOfShape(i + 1);
|
||||
masm.loadPtr(Address(BaselineStubReg, shapeOffset), scratch);
|
||||
masm.branchTestObjShape(Assembler::NotEqual, protoReg, scratch, &failurePopR0Scratch);
|
||||
}
|
||||
masm.addPtr(Imm32(sizeof(size_t)), StackPointer);
|
||||
|
||||
// Shape and type checks succeeded, ok to proceed.
|
||||
masm.moveValue(BooleanValue(false), R0);
|
||||
|
||||
EmitReturnFromIC(masm);
|
||||
|
||||
masm.bind(&failurePopR0Scratch);
|
||||
masm.pop(R0.scratchReg());
|
||||
masm.bind(&failure);
|
||||
EmitStubGuardFailure(masm);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ICIn_Dense::Compiler::generateStubCode(MacroAssembler &masm)
|
||||
{
|
||||
Label failure;
|
||||
|
||||
masm.branchTestInt32(Assembler::NotEqual, R0, &failure);
|
||||
masm.branchTestObject(Assembler::NotEqual, R1, &failure);
|
||||
|
||||
AllocatableGeneralRegisterSet regs(availableGeneralRegs(2));
|
||||
Register scratch = regs.takeAny();
|
||||
|
||||
// Unbox and shape guard object.
|
||||
Register obj = masm.extractObject(R1, ExtractTemp0);
|
||||
masm.loadPtr(Address(BaselineStubReg, ICIn_Dense::offsetOfShape()), scratch);
|
||||
masm.branchTestObjShape(Assembler::NotEqual, obj, scratch, &failure);
|
||||
|
||||
// Load obj->elements.
|
||||
masm.loadPtr(Address(obj, NativeObject::offsetOfElements()), scratch);
|
||||
|
||||
// Unbox key and bounds check.
|
||||
Address initLength(scratch, ObjectElements::offsetOfInitializedLength());
|
||||
Register key = masm.extractInt32(R0, ExtractTemp0);
|
||||
masm.branch32(Assembler::BelowOrEqual, initLength, key, &failure);
|
||||
|
||||
// Hole check.
|
||||
JS_STATIC_ASSERT(sizeof(Value) == 8);
|
||||
BaseIndex element(scratch, key, TimesEight);
|
||||
masm.branchTestMagic(Assembler::Equal, element, &failure);
|
||||
|
||||
masm.moveValue(BooleanValue(true), R0);
|
||||
|
||||
EmitReturnFromIC(masm);
|
||||
|
||||
// Failure case - jump to next stub
|
||||
masm.bind(&failure);
|
||||
EmitStubGuardFailure(masm);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Try to update all existing GetProp/GetName getter call stubs that match the
|
||||
// given holder in place with a new shape and getter. fallbackStub can be
|
||||
// either an ICGetProp_Fallback or an ICGetName_Fallback.
|
||||
|
@ -7326,10 +7007,9 @@ TryAttachPrimitiveGetPropStub(JSContext* cx, HandleScript script, jsbytecode* pc
|
|||
}
|
||||
|
||||
static bool
|
||||
TryAttachNativeGetPropDoesNotExistStub(JSContext *cx, HandleScript script,
|
||||
jsbytecode *pc, ICGetProp_Fallback *stub,
|
||||
HandlePropertyName name, HandleValue val,
|
||||
bool *attached)
|
||||
TryAttachNativeDoesNotExistStub(JSContext* cx, HandleScript script, jsbytecode* pc,
|
||||
ICGetProp_Fallback* stub, HandlePropertyName name,
|
||||
HandleValue val, bool* attached)
|
||||
{
|
||||
MOZ_ASSERT(!*attached);
|
||||
|
||||
|
@ -7514,7 +7194,7 @@ DoGetPropFallback(JSContext* cx, BaselineFrame* frame, ICGetProp_Fallback* stub_
|
|||
|
||||
if (res.isUndefined()) {
|
||||
// Try attaching property-not-found optimized stub for undefined results.
|
||||
if (!TryAttachNativeGetPropDoesNotExistStub(cx, script, pc, stub, name, val, &attached))
|
||||
if (!TryAttachNativeDoesNotExistStub(cx, script, pc, stub, name, val, &attached))
|
||||
return false;
|
||||
if (attached)
|
||||
return true;
|
||||
|
@ -12363,64 +12043,6 @@ ICSetElem_TypedArray::ICSetElem_TypedArray(JitCode* stubCode, Shape* shape, Scal
|
|||
extra_ |= (static_cast<uint16_t>(expectOutOfBounds) << 8);
|
||||
}
|
||||
|
||||
ICInNativeStub::ICInNativeStub(ICStub::Kind kind, JitCode *stubCode, HandleShape shape,
|
||||
HandlePropertyName name)
|
||||
: ICStub(kind, stubCode),
|
||||
shape_(shape),
|
||||
name_(name)
|
||||
{ }
|
||||
|
||||
ICIn_NativePrototype::ICIn_NativePrototype(JitCode *stubCode, HandleShape shape,
|
||||
HandlePropertyName name, HandleObject holder,
|
||||
HandleShape holderShape)
|
||||
: ICInNativeStub(In_NativePrototype, stubCode, shape, name),
|
||||
holder_(holder),
|
||||
holderShape_(holderShape)
|
||||
{ }
|
||||
|
||||
ICIn_NativeDoesNotExist::ICIn_NativeDoesNotExist(JitCode *stubCode, size_t protoChainDepth,
|
||||
HandlePropertyName name)
|
||||
: ICStub(In_NativeDoesNotExist, stubCode),
|
||||
name_(name)
|
||||
{
|
||||
MOZ_ASSERT(protoChainDepth <= MAX_PROTO_CHAIN_DEPTH);
|
||||
extra_ = protoChainDepth;
|
||||
}
|
||||
|
||||
/* static */ size_t
|
||||
ICIn_NativeDoesNotExist::offsetOfShape(size_t idx)
|
||||
{
|
||||
MOZ_ASSERT(ICIn_NativeDoesNotExistImpl<0>::offsetOfShape(idx) ==
|
||||
ICIn_NativeDoesNotExistImpl<
|
||||
ICIn_NativeDoesNotExist::MAX_PROTO_CHAIN_DEPTH>::offsetOfShape(idx));
|
||||
return ICIn_NativeDoesNotExistImpl<0>::offsetOfShape(idx);
|
||||
}
|
||||
|
||||
template <size_t ProtoChainDepth>
|
||||
ICIn_NativeDoesNotExistImpl<ProtoChainDepth>::ICIn_NativeDoesNotExistImpl(
|
||||
JitCode *stubCode, const AutoShapeVector *shapes, HandlePropertyName name)
|
||||
: ICIn_NativeDoesNotExist(stubCode, ProtoChainDepth, name)
|
||||
{
|
||||
MOZ_ASSERT(shapes->length() == NumShapes);
|
||||
for (size_t i = 0; i < NumShapes; i++)
|
||||
shapes_[i].init((*shapes)[i]);
|
||||
}
|
||||
|
||||
ICInNativeDoesNotExistCompiler::ICInNativeDoesNotExistCompiler(
|
||||
JSContext *cx, HandleObject obj, HandlePropertyName name, size_t protoChainDepth)
|
||||
: ICStubCompiler(cx, ICStub::In_NativeDoesNotExist),
|
||||
obj_(cx, obj),
|
||||
name_(cx, name),
|
||||
protoChainDepth_(protoChainDepth)
|
||||
{
|
||||
MOZ_ASSERT(protoChainDepth_ <= ICIn_NativeDoesNotExist::MAX_PROTO_CHAIN_DEPTH);
|
||||
}
|
||||
|
||||
ICIn_Dense::ICIn_Dense(JitCode *stubCode, HandleShape shape)
|
||||
: ICStub(In_Dense, stubCode),
|
||||
shape_(shape)
|
||||
{ }
|
||||
|
||||
ICGetName_Global::ICGetName_Global(JitCode* stubCode, ICStub* firstMonitorStub, Shape* shape,
|
||||
uint32_t slot)
|
||||
: ICMonitoredStub(GetName_Global, stubCode, firstMonitorStub),
|
||||
|
|
|
@ -409,10 +409,6 @@ class ICEntry
|
|||
_(SetElem_TypedArray) \
|
||||
\
|
||||
_(In_Fallback) \
|
||||
_(In_Native) \
|
||||
_(In_NativePrototype) \
|
||||
_(In_NativeDoesNotExist) \
|
||||
_(In_Dense) \
|
||||
\
|
||||
_(GetName_Fallback) \
|
||||
_(GetName_Global) \
|
||||
|
@ -3416,225 +3412,6 @@ class ICIn_Fallback : public ICFallbackStub
|
|||
};
|
||||
};
|
||||
|
||||
// Base class for In_Native and In_NativePrototype stubs.
|
||||
class ICInNativeStub : public ICStub
|
||||
{
|
||||
HeapPtrShape shape_;
|
||||
HeapPtrPropertyName name_;
|
||||
|
||||
protected:
|
||||
ICInNativeStub(ICStub::Kind kind, JitCode *stubCode, HandleShape shape,
|
||||
HandlePropertyName name);
|
||||
|
||||
public:
|
||||
HeapPtrShape &shape() {
|
||||
return shape_;
|
||||
}
|
||||
static size_t offsetOfShape() {
|
||||
return offsetof(ICInNativeStub, shape_);
|
||||
}
|
||||
|
||||
HeapPtrPropertyName &name() {
|
||||
return name_;
|
||||
}
|
||||
static size_t offsetOfName() {
|
||||
return offsetof(ICInNativeStub, name_);
|
||||
}
|
||||
};
|
||||
|
||||
// Stub for confirming an own property on a native object.
|
||||
class ICIn_Native : public ICInNativeStub
|
||||
{
|
||||
friend class ICStubSpace;
|
||||
|
||||
ICIn_Native(JitCode *stubCode, HandleShape shape, HandlePropertyName name)
|
||||
: ICInNativeStub(In_Native, stubCode, shape, name)
|
||||
{}
|
||||
};
|
||||
|
||||
// Stub for confirming a property on a native object's prototype. Note that due to
|
||||
// the shape teleporting optimization, we only have to guard on the object's shape
|
||||
// and the holder's shape.
|
||||
class ICIn_NativePrototype : public ICInNativeStub
|
||||
{
|
||||
friend class ICStubSpace;
|
||||
|
||||
HeapPtrObject holder_;
|
||||
HeapPtrShape holderShape_;
|
||||
|
||||
ICIn_NativePrototype(JitCode *stubCode, HandleShape shape, HandlePropertyName name,
|
||||
HandleObject holder, HandleShape holderShape);
|
||||
|
||||
public:
|
||||
HeapPtrObject &holder() {
|
||||
return holder_;
|
||||
}
|
||||
HeapPtrShape &holderShape() {
|
||||
return holderShape_;
|
||||
}
|
||||
static size_t offsetOfHolder() {
|
||||
return offsetof(ICIn_NativePrototype, holder_);
|
||||
}
|
||||
static size_t offsetOfHolderShape() {
|
||||
return offsetof(ICIn_NativePrototype, holderShape_);
|
||||
}
|
||||
};
|
||||
|
||||
// Compiler for In_Native and In_NativePrototype stubs.
|
||||
class ICInNativeCompiler : public ICStubCompiler
|
||||
{
|
||||
RootedObject obj_;
|
||||
RootedObject holder_;
|
||||
RootedPropertyName name_;
|
||||
|
||||
bool generateStubCode(MacroAssembler &masm);
|
||||
|
||||
public:
|
||||
ICInNativeCompiler(JSContext *cx, ICStub::Kind kind, HandleObject obj, HandleObject holder,
|
||||
HandlePropertyName name)
|
||||
: ICStubCompiler(cx, kind),
|
||||
obj_(cx, obj),
|
||||
holder_(cx, holder),
|
||||
name_(cx, name)
|
||||
{}
|
||||
|
||||
ICStub *getStub(ICStubSpace *space) {
|
||||
RootedShape shape(cx, obj_->as<NativeObject>().lastProperty());
|
||||
if (kind == ICStub::In_Native) {
|
||||
MOZ_ASSERT(obj_ == holder_);
|
||||
return ICStub::New<ICIn_Native>(space, getStubCode(), shape, name_);
|
||||
}
|
||||
|
||||
MOZ_ASSERT(obj_ != holder_);
|
||||
MOZ_ASSERT(kind == ICStub::In_NativePrototype);
|
||||
RootedShape holderShape(cx, holder_->as<NativeObject>().lastProperty());
|
||||
return ICStub::New<ICIn_NativePrototype>(space, getStubCode(), shape, name_, holder_,
|
||||
holderShape);
|
||||
}
|
||||
};
|
||||
|
||||
template <size_t ProtoChainDepth> class ICIn_NativeDoesNotExistImpl;
|
||||
|
||||
class ICIn_NativeDoesNotExist : public ICStub
|
||||
{
|
||||
friend class ICStubSpace;
|
||||
|
||||
HeapPtrPropertyName name_;
|
||||
|
||||
public:
|
||||
static const size_t MAX_PROTO_CHAIN_DEPTH = 8;
|
||||
|
||||
protected:
|
||||
ICIn_NativeDoesNotExist(JitCode *stubCode, size_t protoChainDepth,
|
||||
HandlePropertyName name);
|
||||
|
||||
public:
|
||||
size_t protoChainDepth() const {
|
||||
MOZ_ASSERT(extra_ <= MAX_PROTO_CHAIN_DEPTH);
|
||||
return extra_;
|
||||
}
|
||||
HeapPtrPropertyName &name() {
|
||||
return name_;
|
||||
}
|
||||
|
||||
template <size_t ProtoChainDepth>
|
||||
ICIn_NativeDoesNotExistImpl<ProtoChainDepth> *toImpl() {
|
||||
MOZ_ASSERT(ProtoChainDepth == protoChainDepth());
|
||||
return static_cast<ICIn_NativeDoesNotExistImpl<ProtoChainDepth> *>(this);
|
||||
}
|
||||
|
||||
static size_t offsetOfShape(size_t idx);
|
||||
static size_t offsetOfName() {
|
||||
return offsetof(ICIn_NativeDoesNotExist, name_);
|
||||
}
|
||||
};
|
||||
|
||||
template <size_t ProtoChainDepth>
|
||||
class ICIn_NativeDoesNotExistImpl : public ICIn_NativeDoesNotExist
|
||||
{
|
||||
friend class ICStubSpace;
|
||||
|
||||
public:
|
||||
static const size_t MAX_PROTO_CHAIN_DEPTH = 8;
|
||||
static const size_t NumShapes = ProtoChainDepth + 1;
|
||||
|
||||
private:
|
||||
mozilla::Array<HeapPtrShape, NumShapes> shapes_;
|
||||
|
||||
ICIn_NativeDoesNotExistImpl(JitCode *stubCode, const AutoShapeVector *shapes,
|
||||
HandlePropertyName name);
|
||||
|
||||
public:
|
||||
void traceShapes(JSTracer *trc) {
|
||||
for (size_t i = 0; i < NumShapes; i++)
|
||||
TraceEdge(trc, &shapes_[i], "baseline-innativedoesnotexist-stub-shape");
|
||||
}
|
||||
|
||||
static size_t offsetOfShape(size_t idx) {
|
||||
return offsetof(ICIn_NativeDoesNotExistImpl, shapes_) + (idx * sizeof(HeapPtrShape));
|
||||
}
|
||||
};
|
||||
|
||||
class ICInNativeDoesNotExistCompiler : public ICStubCompiler
|
||||
{
|
||||
RootedObject obj_;
|
||||
RootedPropertyName name_;
|
||||
size_t protoChainDepth_;
|
||||
|
||||
protected:
|
||||
virtual int32_t getKey() const {
|
||||
return static_cast<int32_t>(kind) | (static_cast<int32_t>(protoChainDepth_) << 16);
|
||||
}
|
||||
|
||||
bool generateStubCode(MacroAssembler &masm);
|
||||
|
||||
public:
|
||||
ICInNativeDoesNotExistCompiler(JSContext *cx, HandleObject obj, HandlePropertyName name,
|
||||
size_t protoChainDepth);
|
||||
|
||||
template <size_t ProtoChainDepth>
|
||||
ICStub *getStubSpecific(ICStubSpace *space, const AutoShapeVector *shapes) {
|
||||
return ICStub::New<ICIn_NativeDoesNotExistImpl<ProtoChainDepth>>(space, getStubCode(),
|
||||
shapes, name_);
|
||||
}
|
||||
|
||||
ICStub *getStub(ICStubSpace *space);
|
||||
};
|
||||
|
||||
class ICIn_Dense : public ICStub
|
||||
{
|
||||
friend class ICStubSpace;
|
||||
|
||||
HeapPtrShape shape_;
|
||||
|
||||
ICIn_Dense(JitCode *stubCode, HandleShape shape);
|
||||
|
||||
public:
|
||||
HeapPtrShape &shape() {
|
||||
return shape_;
|
||||
}
|
||||
static size_t offsetOfShape() {
|
||||
return offsetof(ICIn_Dense, shape_);
|
||||
}
|
||||
|
||||
class Compiler : public ICStubCompiler {
|
||||
RootedShape shape_;
|
||||
|
||||
protected:
|
||||
bool generateStubCode(MacroAssembler &masm);
|
||||
|
||||
public:
|
||||
Compiler(JSContext *cx, Shape *shape)
|
||||
: ICStubCompiler(cx, ICStub::In_Dense),
|
||||
shape_(cx, shape)
|
||||
{}
|
||||
|
||||
ICStub *getStub(ICStubSpace *space) {
|
||||
return ICStub::New<ICIn_Dense>(space, getStubCode(), shape_);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// GetName
|
||||
// JSOP_GETNAME
|
||||
// JSOP_GETGNAME
|
||||
|
|
Загрузка…
Ссылка в новой задаче