--- a/js/src/jit/BaselineIC.cpp
+++ b/js/src/jit/BaselineIC.cpp
@@ -732,33 +732,16 @@ ICToNumber_Fallback::Compiler::generateS
return tailCallVM(DoToNumberFallbackInfo, masm);
}
//
// GetElem_Fallback
//
-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;
-}
-
bool
IsPrimitiveArrayTypedObject(JSObject* obj)
{
if (!obj->is<TypedObject>())
return false;
TypeDescr& descr = obj->as<TypedObject>().typeDescr();
return descr.is<ArrayTypeDescr>() &&
descr.as<ArrayTypeDescr>().elementType().is<ScalarTypeDescr>();
@@ -1958,50 +1941,16 @@ ICSetElem_TypedArray::Compiler::generate
return true;
}
//
// In_Fallback
//
static bool
-TryAttachNativeInDoesNotExistStub(JSContext* cx, HandleScript outerScript,
- 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.get(), id, lastProto.address(), &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(outerScript));
- 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)
{
// This fallback stub may trigger debug mode toggling.
DebugModeOSRVolatileStub<ICIn_Fallback*> stub(frame, stub_);
FallbackICSpew(cx, stub, "In");
@@ -2031,33 +1980,16 @@ DoInFallback(JSContext* cx, BaselineFram
}
}
bool cond = false;
if (!OperatorIn(cx, key, obj, &cond))
return false;
res.setBoolean(cond);
- if (stub.invalid())
- return true;
-
- if (attached)
- return true;
-
- if (obj->isNative()) {
- RootedScript script(cx, frame->script());
- bool attached = false;
- if (!cond) {
- 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);
static const VMFunction DoInFallbackInfo =
FunctionInfo<DoInFallbackFn>(DoInFallback, "DoInFallback", TailCall, PopValues(2));
@@ -2076,105 +2008,16 @@ ICIn_Fallback::Compiler::generateStubCod
masm.pushValue(R1);
masm.pushValue(R0);
masm.push(ICStubReg);
pushStubPayload(masm, R0.scratchReg());
return tailCallVM(DoInFallbackInfo, masm);
}
-ICStub*
-ICInNativeDoesNotExistCompiler::getStub(ICStubSpace* space)
-{
- Rooted<ShapeVector> shapes(cx, ShapeVector(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)
-{
- MOZ_ASSERT(engine_ == Engine::Baseline);
-
- 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(ICStubReg, 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(ICStubReg, 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(ICStubReg, 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, &failurePopR0Scratch);
- size_t shapeOffset = ICIn_NativeDoesNotExistImpl<0>::offsetOfShape(i + 1);
- masm.loadPtr(Address(ICStubReg, shapeOffset), scratch);
- masm.branchTestObjShape(Assembler::NotEqual, protoReg, scratch, &failurePopR0Scratch);
- }
- masm.addToStackPtr(Imm32(sizeof(size_t)));
-
- // 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;
-}
-
static bool
DoGetNameFallback(JSContext* cx, BaselineFrame* frame, ICGetName_Fallback* stub_,
HandleObject envChain, MutableHandleValue res)
{
SharedStubInfo info(cx, frame, stub_->icEntry());
// This fallback stub may trigger debug mode toggling.
DebugModeOSRVolatileStub<ICGetName_Fallback*> stub(frame, stub_);
@@ -5464,54 +5307,16 @@ ICSetElem_TypedArray::ICSetElem_TypedArr
: ICStub(SetElem_TypedArray, stubCode),
shape_(shape)
{
extra_ = uint8_t(type);
MOZ_ASSERT(extra_ == type);
extra_ |= (static_cast<uint16_t>(expectOutOfBounds) << 8);
}
-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, Handle<ShapeVector> 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, Engine::Baseline),
- obj_(cx, obj),
- name_(cx, name),
- protoChainDepth_(protoChainDepth)
-{
- MOZ_ASSERT(protoChainDepth_ <= ICIn_NativeDoesNotExist::MAX_PROTO_CHAIN_DEPTH);
-}
-
ICGetIntrinsic_Constant::ICGetIntrinsic_Constant(JitCode* stubCode, const Value& value)
: ICStub(GetIntrinsic_Constant, stubCode),
value_(value)
{ }
ICGetIntrinsic_Constant::~ICGetIntrinsic_Constant()
{ }
--- a/js/src/jit/BaselineIC.h
+++ b/js/src/jit/BaselineIC.h
@@ -708,104 +708,16 @@ class ICIn_Fallback : public ICFallbackS
{ }
ICStub* getStub(ICStubSpace* space) {
return newStub<ICIn_Fallback>(space, getStubCode());
}
};
};
-template <size_t ProtoChainDepth> class ICIn_NativeDoesNotExistImpl;
-
-class ICIn_NativeDoesNotExist : public ICStub
-{
- friend class ICStubSpace;
-
- GCPtrPropertyName 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_;
- }
- GCPtrPropertyName& 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<GCPtrShape, NumShapes> shapes_;
-
- ICIn_NativeDoesNotExistImpl(JitCode* stubCode, Handle<ShapeVector> 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(GCPtrShape));
- }
-};
-
-class ICInNativeDoesNotExistCompiler : public ICStubCompiler
-{
- RootedObject obj_;
- RootedPropertyName name_;
- size_t protoChainDepth_;
-
- protected:
- virtual int32_t getKey() const {
- return static_cast<int32_t>(engine_) |
- (static_cast<int32_t>(kind) << 1) |
- (static_cast<int32_t>(protoChainDepth_) << 17);
- }
-
- MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm);
-
- public:
- ICInNativeDoesNotExistCompiler(JSContext* cx, HandleObject obj, HandlePropertyName name,
- size_t protoChainDepth);
-
- template <size_t ProtoChainDepth>
- ICStub* getStubSpecific(ICStubSpace* space, Handle<ShapeVector> shapes) {
- return newStub<ICIn_NativeDoesNotExistImpl<ProtoChainDepth>>(space, getStubCode(), shapes,
- name_);}
-
- ICStub* getStub(ICStubSpace* space);
-};
// GetName
// JSOP_GETNAME
// JSOP_GETGNAME
class ICGetName_Fallback : public ICMonitoredFallbackStub
{
friend class ICStubSpace;
--- a/js/src/jit/BaselineICList.h
+++ b/js/src/jit/BaselineICList.h
@@ -51,17 +51,16 @@ namespace jit {
_(GetElem_Fallback) \
\
_(SetElem_Fallback) \
_(SetElem_DenseOrUnboxedArray) \
_(SetElem_DenseOrUnboxedArrayAdd) \
_(SetElem_TypedArray) \
\
_(In_Fallback) \
- _(In_NativeDoesNotExist) \
\
_(GetName_Fallback) \
\
_(BindName_Fallback) \
\
_(GetIntrinsic_Fallback) \
_(GetIntrinsic_Constant) \
\
--- a/js/src/jit/CacheIR.cpp
+++ b/js/src/jit/CacheIR.cpp
@@ -1612,16 +1612,32 @@ InIRGenerator::tryAttachNativeIn(HandleI
EmitReadSlotGuard(writer, obj, holder, prop.maybeShape(), objId, &holderId);
writer.loadBooleanResult(true);
writer.returnFromIC();
return true;
}
bool
+InIRGenerator::tryAttachNativeInDoesNotExist(HandleId key, ValOperandId keyId,
+ HandleObject obj, ObjOperandId objId)
+{
+ if (!CheckHasNoSuchProperty(cx_, obj, key))
+ return false;
+
+ Maybe<ObjOperandId> holderId;
+ emitIdGuard(keyId, key);
+ EmitReadSlotGuard(writer, obj, nullptr, nullptr, objId, &holderId);
+ writer.loadBooleanResult(false);
+ writer.returnFromIC();
+
+ return true;
+}
+
+bool
InIRGenerator::tryAttachStub()
{
MOZ_ASSERT(cacheKind_ == CacheKind::In);
AutoAssertNoPendingException aanpe(cx_);
ValOperandId keyId(writer.setInputOperandId(0));
ValOperandId valId(writer.setInputOperandId(1));
@@ -1632,16 +1648,18 @@ InIRGenerator::tryAttachStub()
if (!ValueToNameOrSymbolId(cx_, key_, &id, &nameOrSymbol)) {
cx_->clearPendingException();
return false;
}
if (nameOrSymbol) {
if (tryAttachNativeIn(id, keyId, obj_, objId))
return true;
+ if (tryAttachNativeInDoesNotExist(id, keyId, obj_, objId))
+ return true;
return false;
}
uint32_t index;
Int32OperandId indexId;
if (maybeGuardInt32Index(key_, keyId, &index, &indexId)) {
if (tryAttachDenseIn(index, indexId, obj_, objId))
return true;
--- a/js/src/jit/CacheIR.h
+++ b/js/src/jit/CacheIR.h
@@ -1041,16 +1041,18 @@ class MOZ_RAII InIRGenerator : public IR
{
HandleValue key_;
HandleObject obj_;
bool tryAttachDenseIn(uint32_t index, Int32OperandId indexId,
HandleObject obj, ObjOperandId objId);
bool tryAttachNativeIn(HandleId key, ValOperandId keyId,
HandleObject obj, ObjOperandId objId);
+ bool tryAttachNativeInDoesNotExist(HandleId key, ValOperandId keyId,
+ HandleObject obj, ObjOperandId objId);
public:
InIRGenerator(JSContext* cx, jsbytecode* pc, HandleValue key, HandleObject obj);
bool tryAttachStub();
};
} // namespace jit
--- a/js/src/jit/SharedIC.cpp
+++ b/js/src/jit/SharedIC.cpp
@@ -309,34 +309,16 @@ ICStub::trace(JSTracer* trc)
TraceEdge(trc, &updateStub->object(), "baseline-update-singleton");
break;
}
case ICStub::TypeUpdate_ObjectGroup: {
ICTypeUpdate_ObjectGroup* updateStub = toTypeUpdate_ObjectGroup();
TraceEdge(trc, &updateStub->group(), "baseline-update-group");
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::GetIntrinsic_Constant: {
ICGetIntrinsic_Constant* constantStub = toGetIntrinsic_Constant();
TraceEdge(trc, &constantStub->value(), "baseline-getintrinsic-constant-value");
break;
}
case ICStub::InstanceOf_Function: {
ICInstanceOf_Function* instanceofStub = toInstanceOf_Function();
TraceEdge(trc, &instanceofStub->shape(), "baseline-instanceof-fun-shape");