Back out 74728e99dc47 (bug 1049290) for causing the same hazard build timeouts it caused on Try

CLOSED TREE
This commit is contained in:
Phil Ringnalda 2014-09-11 23:27:39 -07:00
parent 5621efe898
commit 7730277de2
2 changed files with 44 additions and 685 deletions

View File

@ -287,43 +287,6 @@ ICStub::trace(JSTracer *trc)
MarkScript(trc, &pushFunStub->script(), "baseline-profilerpushfunction-stub-script");
break;
}
case ICStub::In_Native: {
ICIn_Native *inStub = toIn_Native();
MarkShape(trc, &inStub->shape(), "baseline-innative-stub-shape");
MarkString(trc, &inStub->name(), "baseline-innative-stub-name");
break;
}
case ICStub::In_NativePrototype: {
ICIn_NativePrototype *inStub = toIn_NativePrototype();
MarkShape(trc, &inStub->shape(), "baseline-innativeproto-stub-shape");
MarkString(trc, &inStub->name(), "baseline-innativeproto-stub-name");
MarkObject(trc, &inStub->holder(), "baseline-innativeproto-stub-holder");
MarkShape(trc, &inStub->holderShape(), "baseline-innativeproto-stub-holdershape");
break;
}
case ICStub::In_NativeDoesNotExist: {
ICIn_NativeDoesNotExist *inStub = toIn_NativeDoesNotExist();
MarkString(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_ASSUME_UNREACHABLE("Invalid proto stub.");
}
break;
}
case ICStub::In_Dense: {
ICIn_Dense *inStub = toIn_Dense();
MarkShape(trc, &inStub->shape(), "baseline-in-dense-shape");
break;
}
case ICStub::GetName_Global: {
ICGetName_Global *globalStub = toGetName_Global();
MarkShape(trc, &globalStub->shape(), "baseline-global-stub-shape");
@ -3774,29 +3737,22 @@ 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 TryAttachNativeGetElemStub(JSContext *cx, HandleScript script, jsbytecode *pc,
ICGetElem_Fallback *stub, HandleObject 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());
@ -3910,14 +3866,6 @@ TypedArrayRequiresFloatingPoint(TypedArrayObject *tarr)
type == Scalar::Float64;
}
static bool
IsNativeDenseElementAccess(HandleObject obj, HandleValue key)
{
if (obj->isNative() && key.isInt32() && key.toInt32() >= 0 && !obj->is<TypedArrayObject>())
return true;
return false;
}
static bool
TryAttachGetElemStub(JSContext *cx, JSScript *script, jsbytecode *pc, ICGetElem_Fallback *stub,
HandleValue lhs, HandleValue rhs, HandleValue res)
@ -3981,25 +3929,27 @@ 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->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 && !obj->is<TypedArrayObject>()) {
JitSpew(JitSpew_BaselineIC, " Generating GetElem(Native[Int32] dense) stub");
ICGetElem_Dense::Compiler compiler(cx, stub->fallbackMonitorStub()->firstMonitorStub(),
obj->lastProperty(), isCallElem);
ICStub *denseStub = compiler.getStub(compiler.getStubSpace(script));
if (!denseStub)
return false;
stub->addNewStub(denseStub);
return true;
}
stub->addNewStub(denseStub);
return true;
}
// Check for NativeObject[id] shape-optimizable accesses.
if (obj->isNative() && rhs.isString()) {
RootedScript rootedScript(cx, script);
if (!TryAttachNativeGetElemStub(cx, rootedScript, pc, stub, obj, rhs))
return false;
script = rootedScript;
// Check for NativeObject[id] shape-optimizable accesses.
if (rhs.isString()) {
RootedScript rootedScript(cx, script);
if (!TryAttachNativeGetElemStub(cx, rootedScript, pc, stub, obj, rhs))
return false;
script = rootedScript;
}
}
// Check for TypedArray[int] => Number accesses.
@ -5075,7 +5025,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() &&
!obj->is<TypedArrayObject>() &&
index.isInt32() && index.toInt32() >= 0 &&
!rhs.isMagic(JS_ELEMENTS_HOLE))
{
bool addingCase;
size_t protoDepth;
@ -5659,96 +5612,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->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");
@ -5762,33 +5627,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, PopValues(2));
@ -5805,182 +5650,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);
GeneralRegisterSet 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_->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_ASSUME_UNREACHABLE("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);
GeneralRegisterSet 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);
GeneralRegisterSet 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, JSObject::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;
}
// Attach an optimized stub for a GETGNAME/CALLGNAME op.
static bool
TryAttachGlobalNameStub(JSContext *cx, HandleScript script, jsbytecode *pc,
@ -6780,10 +6453,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);
@ -6807,6 +6479,8 @@ TryAttachNativeGetPropDoesNotExistStub(JSContext *cx, HandleScript script,
return true;
ICStub *monitorStub = stub->fallbackMonitorStub()->firstMonitorStub();
RootedShape objShape(cx, obj->lastProperty());
RootedShape lastShape(cx, lastProto->lastProperty());
// Confirmed no-such-property. Add stub.
JitSpew(JitSpew_BaselineIC, " Generating GetProp_NativeDoesNotExist stub");
@ -6928,7 +6602,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;
@ -10771,64 +10445,6 @@ ICSetElem_TypedArray::ICSetElem_TypedArray(JitCode *stubCode, HandleShape shape,
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, HandleShape shape,
uint32_t slot)
: ICMonitoredStub(GetName_Global, stubCode, firstMonitorStub),

View File

@ -391,10 +391,6 @@ class ICEntry
_(SetElem_TypedArray) \
\
_(In_Fallback) \
_(In_Native) \
_(In_NativePrototype) \
_(In_NativeDoesNotExist) \
_(In_Dense) \
\
_(GetName_Fallback) \
_(GetName_Global) \
@ -3814,259 +3810,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)
{}
public:
static inline ICIn_Native *New(ICStubSpace *space, JitCode *code, HandleShape shape,
HandlePropertyName name)
{
if (!code)
return nullptr;
return space->allocate<ICIn_Native>(code, 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:
static inline ICIn_NativePrototype *New(ICStubSpace *space, JitCode *code,
HandleShape shape, HandlePropertyName name,
HandleObject holder, HandleShape holderShape)
{
if (!code)
return nullptr;
return space->allocate<ICIn_NativePrototype>(code, shape, name, holder, holderShape);
}
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_->lastProperty());
if (kind == ICStub::In_Native) {
JS_ASSERT(obj_ == holder_);
return ICIn_Native::New(space, getStubCode(), shape, name_);
}
JS_ASSERT(obj_ != holder_);
JS_ASSERT(kind == ICStub::In_NativePrototype);
RootedShape holderShape(cx, holder_->lastProperty());
return ICIn_NativePrototype::New(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:
static inline ICIn_NativeDoesNotExistImpl<ProtoChainDepth> *New(
ICStubSpace *space, JitCode *code, const AutoShapeVector *shapes,
HandlePropertyName name)
{
if (!code)
return nullptr;
return space->allocate<ICIn_NativeDoesNotExistImpl<ProtoChainDepth>>(
code, shapes, name);
}
void traceShapes(JSTracer *trc) {
for (size_t i = 0; i < NumShapes; i++)
MarkShape(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 ICIn_NativeDoesNotExistImpl<ProtoChainDepth>::New(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:
static inline ICIn_Dense *New(ICStubSpace *space, JitCode *code, HandleShape shape)
{
if (!code)
return nullptr;
return space->allocate<ICIn_Dense>(code, shape);
}
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 ICIn_Dense::New(space, getStubCode(), shape_);
}
};
};
// GetName
// JSOP_NAME
// JSOP_GETGNAME