}
+void LoadIndexedInterceptorStub::Generate(MacroAssembler* masm) {
+ // Return address is in lr.
+ Label slow;
+
+ Register receiver = LoadDescriptor::ReceiverRegister();
+ Register key = LoadDescriptor::NameRegister();
+
+ // Check that the key is an array index, that is Uint32.
+ __ NonNegativeSmiTst(key);
+ __ b(ne, &slow);
+
+ // Everything is fine, call runtime.
+ __ Push(receiver, key); // Receiver, key.
+
+ // Perform tail call to the entry.
+ __ TailCallExternalReference(
+ ExternalReference(IC_Utility(IC::kLoadElementWithInterceptor),
+ masm->isolate()),
+ 2, 1);
+
+ __ bind(&slow);
+ PropertyAccessCompiler::TailCallBuiltin(
+ masm, PropertyAccessCompiler::MissBuiltin(Code::KEYED_LOAD_IC));
+}
+
+
void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) {
// sp[0] : number of parameters
// sp[4] : receiver displacement
}
+void LoadIndexedInterceptorStub::Generate(MacroAssembler* masm) {
+ // Return address is in lr.
+ Label slow;
+
+ Register receiver = LoadDescriptor::ReceiverRegister();
+ Register key = LoadDescriptor::NameRegister();
+
+ // Check that the key is an array index, that is Uint32.
+ __ TestAndBranchIfAnySet(key, kSmiTagMask | kSmiSignMask, &slow);
+
+ // Everything is fine, call runtime.
+ __ Push(receiver, key);
+ __ TailCallExternalReference(
+ ExternalReference(IC_Utility(IC::kLoadElementWithInterceptor),
+ masm->isolate()),
+ 2, 1);
+
+ __ Bind(&slow);
+ PropertyAccessCompiler::TailCallBuiltin(
+ masm, PropertyAccessCompiler::MissBuiltin(Code::KEYED_LOAD_IC));
+}
+
+
void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) {
// Stack layout on entry.
// jssp[0]: number of parameters (tagged)
}
-static void Generate_KeyedLoadIC_IndexedInterceptor(MacroAssembler* masm) {
- KeyedLoadIC::GenerateIndexedInterceptor(masm);
-}
-
-
static void Generate_KeyedLoadIC_SloppyArguments(MacroAssembler* masm) {
KeyedLoadIC::GenerateSloppyArguments(masm);
}
kNoExtraICState) \
V(KeyedLoadIC_Generic, KEYED_LOAD_IC, GENERIC, kNoExtraICState) \
V(KeyedLoadIC_String, KEYED_LOAD_IC, MEGAMORPHIC, kNoExtraICState) \
- V(KeyedLoadIC_IndexedInterceptor, KEYED_LOAD_IC, MONOMORPHIC, \
- kNoExtraICState) \
V(KeyedLoadIC_SloppyArguments, KEYED_LOAD_IC, MONOMORPHIC, kNoExtraICState) \
\
V(StoreIC_Setter_ForDeopt, STORE_IC, MONOMORPHIC, StoreIC::kStrictModeState) \
V(JSEntry) \
V(KeyedLoadICTrampoline) \
V(LoadICTrampoline) \
+ V(LoadIndexedInterceptor) \
V(MathPow) \
V(ProfileEntryHook) \
V(RecordWrite) \
};
+// TODO(mvstanton): Translate to hydrogen code stub.
+class LoadIndexedInterceptorStub : public PlatformCodeStub {
+ public:
+ explicit LoadIndexedInterceptorStub(Isolate* isolate)
+ : PlatformCodeStub(isolate) {}
+
+ virtual Code::Kind GetCodeKind() const { return Code::HANDLER; }
+ virtual Code::StubType GetStubType() { return Code::FAST; }
+
+ DEFINE_CALL_INTERFACE_DESCRIPTOR(Load);
+ DEFINE_PLATFORM_CODE_STUB(LoadIndexedInterceptor, PlatformCodeStub);
+};
+
+
class HandlerStub : public HydrogenCodeStub {
public:
virtual Code::Kind GetCodeKind() const { return Code::HANDLER; }
}
+void LoadIndexedInterceptorStub::Generate(MacroAssembler* masm) {
+ // Return address is on the stack.
+ Label slow;
+
+ Register receiver = LoadDescriptor::ReceiverRegister();
+ Register key = LoadDescriptor::NameRegister();
+ Register scratch = eax;
+ DCHECK(!scratch.is(receiver) && !scratch.is(key));
+
+ // Check that the key is an array index, that is Uint32.
+ __ test(key, Immediate(kSmiTagMask | kSmiSignMask));
+ __ j(not_zero, &slow);
+
+ // Everything is fine, call runtime.
+ __ pop(scratch);
+ __ push(receiver); // receiver
+ __ push(key); // key
+ __ push(scratch); // return address
+
+ // Perform tail call to the entry.
+ ExternalReference ref = ExternalReference(
+ IC_Utility(IC::kLoadElementWithInterceptor), masm->isolate());
+ __ TailCallExternalReference(ref, 2, 1);
+
+ __ bind(&slow);
+ PropertyAccessCompiler::TailCallBuiltin(
+ masm, PropertyAccessCompiler::MissBuiltin(Code::KEYED_LOAD_IC));
+}
+
+
void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) {
// The key is in edx and the parameter count is in eax.
DCHECK(edx.is(ArgumentsAccessReadDescriptor::index()));
}
-void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) {
- // Return address is in lr.
- Label slow;
-
- Register receiver = LoadDescriptor::ReceiverRegister();
- Register key = LoadDescriptor::NameRegister();
- Register scratch1 = r3;
- Register scratch2 = r4;
- DCHECK(!scratch1.is(receiver) && !scratch1.is(key));
- DCHECK(!scratch2.is(receiver) && !scratch2.is(key));
-
- // Check that the receiver isn't a smi.
- __ JumpIfSmi(receiver, &slow);
-
- // Check that the key is an array index, that is Uint32.
- __ NonNegativeSmiTst(key);
- __ b(ne, &slow);
-
- // Get the map of the receiver.
- __ ldr(scratch1, FieldMemOperand(receiver, HeapObject::kMapOffset));
-
- // Check that it has indexed interceptor and access checks
- // are not enabled for this object.
- __ ldrb(scratch2, FieldMemOperand(scratch1, Map::kBitFieldOffset));
- __ and_(scratch2, scratch2, Operand(kSlowCaseBitFieldMask));
- __ cmp(scratch2, Operand(1 << Map::kHasIndexedInterceptor));
- __ b(ne, &slow);
-
- // Everything is fine, call runtime.
- __ Push(receiver, key); // Receiver, key.
-
- // Perform tail call to the entry.
- __ TailCallExternalReference(
- ExternalReference(IC_Utility(kLoadElementWithInterceptor),
- masm->isolate()),
- 2, 1);
-
- __ bind(&slow);
- GenerateMiss(masm);
-}
-
-
void KeyedStoreIC::GenerateMiss(MacroAssembler* masm) {
// Push receiver, key and value for runtime call.
__ Push(StoreDescriptor::ReceiverRegister(), StoreDescriptor::NameRegister(),
}
-void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) {
- // Return address is in lr.
- Label slow;
-
- Register receiver = LoadDescriptor::ReceiverRegister();
- Register key = LoadDescriptor::NameRegister();
- Register scratch1 = x3;
- Register scratch2 = x4;
- DCHECK(!AreAliased(scratch1, scratch2, receiver, key));
-
- // Check that the receiver isn't a smi.
- __ JumpIfSmi(receiver, &slow);
-
- // Check that the key is an array index, that is Uint32.
- __ TestAndBranchIfAnySet(key, kSmiTagMask | kSmiSignMask, &slow);
-
- // Get the map of the receiver.
- Register map = scratch1;
- __ Ldr(map, FieldMemOperand(receiver, HeapObject::kMapOffset));
-
- // Check that it has indexed interceptor and access checks
- // are not enabled for this object.
- __ Ldrb(scratch2, FieldMemOperand(map, Map::kBitFieldOffset));
- DCHECK(kSlowCaseBitFieldMask == ((1 << Map::kIsAccessCheckNeeded) |
- (1 << Map::kHasIndexedInterceptor)));
- __ Tbnz(scratch2, Map::kIsAccessCheckNeeded, &slow);
- __ Tbz(scratch2, Map::kHasIndexedInterceptor, &slow);
-
- // Everything is fine, call runtime.
- __ Push(receiver, key);
- __ TailCallExternalReference(
- ExternalReference(IC_Utility(kLoadElementWithInterceptor),
- masm->isolate()),
- 2, 1);
-
- __ Bind(&slow);
- GenerateMiss(masm);
-}
-
-
void KeyedStoreIC::GenerateMiss(MacroAssembler* masm) {
ASM_LOCATION("KeyedStoreIC::GenerateMiss");
} else {
bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE;
ElementsKind elements_kind = receiver_map->elements_kind();
-
- if (IsFastElementsKind(elements_kind) ||
- IsExternalArrayElementsKind(elements_kind) ||
- IsFixedTypedArrayElementsKind(elements_kind)) {
+ if (receiver_map->has_indexed_interceptor()) {
+ cached_stub = LoadIndexedInterceptorStub(isolate()).GetCode();
+ } else if (IsFastElementsKind(elements_kind) ||
+ IsExternalArrayElementsKind(elements_kind) ||
+ IsFixedTypedArrayElementsKind(elements_kind)) {
cached_stub = LoadFastElementStub(isolate(), is_js_array, elements_kind)
.GetCode();
} else if (elements_kind == SLOPPY_ARGUMENTS_ELEMENTS) {
}
-void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) {
- // Return address is on the stack.
- Label slow;
-
- Register receiver = LoadDescriptor::ReceiverRegister();
- Register key = LoadDescriptor::NameRegister();
- Register scratch = eax;
- DCHECK(!scratch.is(receiver) && !scratch.is(key));
-
- // Check that the receiver isn't a smi.
- __ JumpIfSmi(receiver, &slow);
-
- // Check that the key is an array index, that is Uint32.
- __ test(key, Immediate(kSmiTagMask | kSmiSignMask));
- __ j(not_zero, &slow);
-
- // Get the map of the receiver.
- __ mov(scratch, FieldOperand(receiver, HeapObject::kMapOffset));
-
- // Check that it has indexed interceptor and access checks
- // are not enabled for this object.
- __ movzx_b(scratch, FieldOperand(scratch, Map::kBitFieldOffset));
- __ and_(scratch, Immediate(kSlowCaseBitFieldMask));
- __ cmp(scratch, Immediate(1 << Map::kHasIndexedInterceptor));
- __ j(not_zero, &slow);
-
- // Everything is fine, call runtime.
- __ pop(scratch);
- __ push(receiver); // receiver
- __ push(key); // key
- __ push(scratch); // return address
-
- // Perform tail call to the entry.
- ExternalReference ref = ExternalReference(
- IC_Utility(kLoadElementWithInterceptor), masm->isolate());
- __ TailCallExternalReference(ref, 2, 1);
-
- __ bind(&slow);
- GenerateMiss(masm);
-}
-
-
void KeyedLoadIC::GenerateSloppyArguments(MacroAssembler* masm) {
// The return address is on the stack.
Register receiver = LoadDescriptor::ReceiverRegister();
ElementsKind elements_kind = receiver_map->elements_kind();
Handle<Code> stub;
- if (receiver_map->has_fast_elements() ||
- receiver_map->has_external_array_elements() ||
- receiver_map->has_fixed_typed_array_elements()) {
+ if (receiver_map->has_indexed_interceptor()) {
+ stub = LoadIndexedInterceptorStub(isolate).GetCode();
+ } else if (receiver_map->has_fast_elements() ||
+ receiver_map->has_external_array_elements() ||
+ receiver_map->has_fixed_typed_array_elements()) {
stub = LoadFastElementStub(isolate,
receiver_map->instance_type() == JS_ARRAY_TYPE,
elements_kind).GetCode();
Handle<Code> KeyedLoadIC::LoadElementStub(Handle<JSObject> receiver) {
- // Don't handle megamorphic property accesses for INTERCEPTORS or CALLBACKS
- // via megamorphic stubs, since they don't have a map in their relocation info
- // and so the stubs can't be harvested for the object needed for a map check.
- if (target()->type() != Code::NORMAL) {
- TRACE_GENERIC_IC(isolate(), "KeyedIC", "non-NORMAL target type");
- return generic_stub();
- }
-
Handle<Map> receiver_map(receiver->map(), isolate());
MapHandleList target_receiver_maps;
if (target().is_identical_to(string_stub())) {
if (receiver->elements()->map() ==
isolate()->heap()->sloppy_arguments_elements_map()) {
stub = sloppy_arguments_stub();
- } else if (receiver->HasIndexedInterceptor()) {
- stub = indexed_interceptor_stub();
} else if (!Object::ToSmi(isolate(), key).is_null() &&
(!target().is_identical_to(sloppy_arguments_stub()))) {
stub = LoadElementStub(receiver);
}
static void GenerateGeneric(MacroAssembler* masm);
static void GenerateString(MacroAssembler* masm);
- static void GenerateIndexedInterceptor(MacroAssembler* masm);
static void GenerateSloppyArguments(MacroAssembler* masm);
// Bit mask to be tested against bit field for the cases when
private:
Handle<Code> generic_stub() const { return generic_stub(isolate()); }
- Handle<Code> indexed_interceptor_stub() {
- return isolate()->builtins()->KeyedLoadIC_IndexedInterceptor();
- }
Handle<Code> sloppy_arguments_stub() {
return isolate()->builtins()->KeyedLoadIC_SloppyArguments();
}
}
-void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) {
- // Return address is in ra.
- Label slow;
-
- Register receiver = LoadDescriptor::ReceiverRegister();
- Register key = LoadDescriptor::NameRegister();
- Register scratch1 = a3;
- Register scratch2 = t0;
- DCHECK(!scratch1.is(receiver) && !scratch1.is(key));
- DCHECK(!scratch2.is(receiver) && !scratch2.is(key));
-
- // Check that the receiver isn't a smi.
- __ JumpIfSmi(receiver, &slow);
-
- // Check that the key is an array index, that is Uint32.
- __ And(t0, key, Operand(kSmiTagMask | kSmiSignMask));
- __ Branch(&slow, ne, t0, Operand(zero_reg));
-
- // Get the map of the receiver.
- __ lw(scratch1, FieldMemOperand(receiver, HeapObject::kMapOffset));
-
- // Check that it has indexed interceptor and access checks
- // are not enabled for this object.
- __ lbu(scratch2, FieldMemOperand(scratch1, Map::kBitFieldOffset));
- __ And(scratch2, scratch2, Operand(kSlowCaseBitFieldMask));
- __ Branch(&slow, ne, scratch2, Operand(1 << Map::kHasIndexedInterceptor));
- // Everything is fine, call runtime.
- __ Push(receiver, key); // Receiver, key.
-
- // Perform tail call to the entry.
- __ TailCallExternalReference(
- ExternalReference(IC_Utility(kLoadElementWithInterceptor),
- masm->isolate()),
- 2, 1);
-
- __ bind(&slow);
- GenerateMiss(masm);
-}
-
-
void KeyedStoreIC::GenerateMiss(MacroAssembler* masm) {
// Push receiver, key and value for runtime call.
__ Push(StoreDescriptor::ReceiverRegister(), StoreDescriptor::NameRegister(),
}
-void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) {
- // Return address is on the stack.
- Label slow;
-
- Register receiver = LoadDescriptor::ReceiverRegister();
- Register key = LoadDescriptor::NameRegister();
- Register scratch = rax;
- DCHECK(!scratch.is(receiver) && !scratch.is(key));
-
- // Check that the receiver isn't a smi.
- __ JumpIfSmi(receiver, &slow);
-
- // Check that the key is an array index, that is Uint32.
- STATIC_ASSERT(kSmiValueSize <= 32);
- __ JumpUnlessNonNegativeSmi(key, &slow);
-
- // Get the map of the receiver.
- __ movp(scratch, FieldOperand(receiver, HeapObject::kMapOffset));
-
- // Check that it has indexed interceptor and access checks
- // are not enabled for this object.
- __ movb(scratch, FieldOperand(scratch, Map::kBitFieldOffset));
- __ andb(scratch, Immediate(kSlowCaseBitFieldMask));
- __ cmpb(scratch, Immediate(1 << Map::kHasIndexedInterceptor));
- __ j(not_zero, &slow);
-
- // Everything is fine, call runtime.
- __ PopReturnAddressTo(scratch);
- __ Push(receiver); // receiver
- __ Push(key); // key
- __ PushReturnAddressFrom(scratch);
-
- // Perform tail call to the entry.
- __ TailCallExternalReference(
- ExternalReference(IC_Utility(kLoadElementWithInterceptor),
- masm->isolate()),
- 2, 1);
-
- __ bind(&slow);
- GenerateMiss(masm);
-}
-
-
static void KeyedStoreGenerateGenericHelper(
MacroAssembler* masm, Label* fast_object, Label* fast_double, Label* slow,
KeyedStoreCheckMap check_map, KeyedStoreIncrementLength increment_length) {
}
+void LoadIndexedInterceptorStub::Generate(MacroAssembler* masm) {
+ // Return address is in ra.
+ Label slow;
+
+ Register receiver = LoadDescriptor::ReceiverRegister();
+ Register key = LoadDescriptor::NameRegister();
+
+ // Check that the key is an array index, that is Uint32.
+ __ And(t0, key, Operand(kSmiTagMask | kSmiSignMask));
+ __ Branch(&slow, ne, t0, Operand(zero_reg));
+
+ // Everything is fine, call runtime.
+ __ Push(receiver, key); // Receiver, key.
+
+ // Perform tail call to the entry.
+ __ TailCallExternalReference(
+ ExternalReference(IC_Utility(IC::kLoadElementWithInterceptor),
+ masm->isolate()),
+ 2, 1);
+
+ __ bind(&slow);
+ PropertyAccessCompiler::TailCallBuiltin(
+ masm, PropertyAccessCompiler::MissBuiltin(Code::KEYED_LOAD_IC));
+}
+
+
void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) {
// sp[0] : number of parameters
// sp[4] : receiver displacement
}
+void LoadIndexedInterceptorStub::Generate(MacroAssembler* masm) {
+ // Return address is on the stack.
+ Label slow;
+
+ Register receiver = LoadDescriptor::ReceiverRegister();
+ Register key = LoadDescriptor::NameRegister();
+ Register scratch = rax;
+ DCHECK(!scratch.is(receiver) && !scratch.is(key));
+
+ // Check that the key is an array index, that is Uint32.
+ STATIC_ASSERT(kSmiValueSize <= 32);
+ __ JumpUnlessNonNegativeSmi(key, &slow);
+
+ // Everything is fine, call runtime.
+ __ PopReturnAddressTo(scratch);
+ __ Push(receiver); // receiver
+ __ Push(key); // key
+ __ PushReturnAddressFrom(scratch);
+
+ // Perform tail call to the entry.
+ __ TailCallExternalReference(
+ ExternalReference(IC_Utility(IC::kLoadElementWithInterceptor),
+ masm->isolate()),
+ 2, 1);
+
+ __ bind(&slow);
+ PropertyAccessCompiler::TailCallBuiltin(
+ masm, PropertyAccessCompiler::MissBuiltin(Code::KEYED_LOAD_IC));
+}
+
+
void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) {
// rsp[0] : return address
// rsp[8] : number of parameters