}
+void StoreArrayLengthStub::Generate(MacroAssembler* masm) {
+ // This accepts as a receiver anything JSArray::SetElementsLength accepts
+ // (currently anything except for external arrays which means anything with
+ // elements of FixedArray type). Value must be a number, but only smis are
+ // accepted as the most common case.
+ Label miss;
+
+ Register receiver;
+ Register value;
+ if (kind() == Code::KEYED_STORE_IC) {
+ // ----------- S t a t e -------------
+ // -- lr : return address
+ // -- r0 : value
+ // -- r1 : key
+ // -- r2 : receiver
+ // -----------------------------------
+ __ cmp(r1, Operand(masm->isolate()->factory()->length_symbol()));
+ __ b(ne, &miss);
+ receiver = r2;
+ value = r0;
+ } else {
+ ASSERT(kind() == Code::STORE_IC);
+ // ----------- S t a t e -------------
+ // -- lr : return address
+ // -- r0 : value
+ // -- r1 : receiver
+ // -- r2 : key
+ // -----------------------------------
+ receiver = r1;
+ value = r0;
+ }
+ Register scratch = r3;
+
+ // Check that the receiver isn't a smi.
+ __ JumpIfSmi(receiver, &miss);
+
+ // Check that the object is a JS array.
+ __ CompareObjectType(receiver, scratch, scratch, JS_ARRAY_TYPE);
+ __ b(ne, &miss);
+
+ // Check that elements are FixedArray.
+ // We rely on StoreIC_ArrayLength below to deal with all types of
+ // fast elements (including COW).
+ __ ldr(scratch, FieldMemOperand(receiver, JSArray::kElementsOffset));
+ __ CompareObjectType(scratch, scratch, scratch, FIXED_ARRAY_TYPE);
+ __ b(ne, &miss);
+
+ // Check that the array has fast properties, otherwise the length
+ // property might have been redefined.
+ __ ldr(scratch, FieldMemOperand(receiver, JSArray::kPropertiesOffset));
+ __ ldr(scratch, FieldMemOperand(scratch, FixedArray::kMapOffset));
+ __ CompareRoot(scratch, Heap::kHashTableMapRootIndex);
+ __ b(eq, &miss);
+
+ // Check that value is a smi.
+ __ JumpIfNotSmi(value, &miss);
+
+ // Prepare tail call to StoreIC_ArrayLength.
+ __ Push(receiver, value);
+
+ ExternalReference ref =
+ ExternalReference(IC_Utility(IC::kStoreIC_ArrayLength), masm->isolate());
+ __ TailCallExternalReference(ref, 2, 1);
+
+ __ bind(&miss);
+
+ StubCompiler::GenerateStoreMiss(masm, kind());
+}
+
+
Register InstanceofStub::left() { return r0; }
}
-void StoreIC::GenerateArrayLength(MacroAssembler* masm) {
- // ----------- S t a t e -------------
- // -- r0 : value
- // -- r1 : receiver
- // -- r2 : name
- // -- lr : return address
- // -----------------------------------
- //
- // This accepts as a receiver anything JSArray::SetElementsLength accepts
- // (currently anything except for external arrays which means anything with
- // elements of FixedArray type). Value must be a number, but only smis are
- // accepted as the most common case.
-
- Label miss;
-
- Register receiver = r1;
- Register value = r0;
- Register scratch = r3;
-
- // Check that the receiver isn't a smi.
- __ JumpIfSmi(receiver, &miss);
-
- // Check that the object is a JS array.
- __ CompareObjectType(receiver, scratch, scratch, JS_ARRAY_TYPE);
- __ b(ne, &miss);
-
- // Check that elements are FixedArray.
- // We rely on StoreIC_ArrayLength below to deal with all types of
- // fast elements (including COW).
- __ ldr(scratch, FieldMemOperand(receiver, JSArray::kElementsOffset));
- __ CompareObjectType(scratch, scratch, scratch, FIXED_ARRAY_TYPE);
- __ b(ne, &miss);
-
- // Check that the array has fast properties, otherwise the length
- // property might have been redefined.
- __ ldr(scratch, FieldMemOperand(receiver, JSArray::kPropertiesOffset));
- __ ldr(scratch, FieldMemOperand(scratch, FixedArray::kMapOffset));
- __ CompareRoot(scratch, Heap::kHashTableMapRootIndex);
- __ b(eq, &miss);
-
- // Check that value is a smi.
- __ JumpIfNotSmi(value, &miss);
-
- // Prepare tail call to StoreIC_ArrayLength.
- __ Push(receiver, value);
-
- ExternalReference ref =
- ExternalReference(IC_Utility(kStoreIC_ArrayLength), masm->isolate());
- __ TailCallExternalReference(ref, 2, 1);
-
- __ bind(&miss);
-
- GenerateMiss(masm);
-}
-
-
void StoreIC::GenerateNormal(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- r0 : value
}
+void StubCompiler::GenerateStoreMiss(MacroAssembler* masm, Code::Kind kind) {
+ ASSERT(kind == Code::STORE_IC || kind == Code::KEYED_STORE_IC);
+ Handle<Code> code = (kind == Code::STORE_IC)
+ ? masm->isolate()->builtins()->StoreIC_Miss()
+ : masm->isolate()->builtins()->KeyedStoreIC_Miss();
+ __ Jump(code, RelocInfo::CODE_TARGET);
+}
+
+
static void GenerateCallFunction(MacroAssembler* masm,
Handle<Object> object,
const ParameterCount& arguments,
}
-static void Generate_StoreIC_ArrayLength(MacroAssembler* masm) {
- StoreIC::GenerateArrayLength(masm);
-}
-
-
-static void Generate_StoreIC_ArrayLength_Strict(MacroAssembler* masm) {
- StoreIC::GenerateArrayLength(masm);
-}
-
-
static void Generate_StoreIC_GlobalProxy(MacroAssembler* masm) {
StoreIC::GenerateGlobalProxy(masm, kNonStrictMode);
}
\
V(StoreIC_Initialize, STORE_IC, UNINITIALIZED, \
Code::kNoExtraICState) \
- V(StoreIC_ArrayLength, STORE_IC, MONOMORPHIC, \
- Code::kNoExtraICState) \
V(StoreIC_Normal, STORE_IC, MONOMORPHIC, \
Code::kNoExtraICState) \
V(StoreIC_Megamorphic, STORE_IC, MEGAMORPHIC, \
Code::kNoExtraICState) \
V(StoreIC_Initialize_Strict, STORE_IC, UNINITIALIZED, \
kStrictMode) \
- V(StoreIC_ArrayLength_Strict, STORE_IC, MONOMORPHIC, \
- kStrictMode) \
V(StoreIC_Normal_Strict, STORE_IC, MONOMORPHIC, \
kStrictMode) \
V(StoreIC_Megamorphic_Strict, STORE_IC, MEGAMORPHIC, \
// Copy the generated code into a heap object.
Code::Flags flags = Code::ComputeFlags(
- static_cast<Code::Kind>(GetCodeKind()), GetICState());
+ static_cast<Code::Kind>(GetCodeKind()), GetICState(), GetExtraICState());
Handle<Code> new_object = factory->NewCode(
desc, flags, masm.CodeObject(), NeedsImmovableCode());
return new_object;
V(ArrayLength) \
V(StringLength) \
V(FunctionPrototype) \
+ V(StoreArrayLength) \
V(RecordWrite) \
V(StoreBufferOverflow) \
V(RegExpExec) \
virtual InlineCacheState GetICState() {
return UNINITIALIZED;
}
+ virtual Code::ExtraICState GetExtraICState() {
+ return Code::kNoExtraICState;
+ }
// Returns whether the code generated for this stub needs to be allocated as
// a fixed (non-moveable) code object.
};
+class StoreICStub: public ICStub {
+ public:
+ StoreICStub(Code::Kind kind, StrictModeFlag strict_mode)
+ : ICStub(kind), strict_mode_(strict_mode) { }
+
+ protected:
+ virtual Code::ExtraICState GetExtraICState() {
+ return strict_mode_;
+ }
+
+ private:
+ class StrictModeBits: public BitField<bool, 4, 1> {};
+ virtual int MinorKey() {
+ return KindBits::encode(kind()) | StrictModeBits::encode(strict_mode_);
+ }
+
+ StrictModeFlag strict_mode_;
+};
+
+
+class StoreArrayLengthStub: public StoreICStub {
+ public:
+ explicit StoreArrayLengthStub(Code::Kind kind, StrictModeFlag strict_mode)
+ : StoreICStub(kind, strict_mode) { }
+ virtual void Generate(MacroAssembler* masm);
+
+ private:
+ virtual CodeStub::Major MajorKey() { return StoreArrayLength; }
+};
+
+
class BinaryOpStub: public PlatformCodeStub {
public:
BinaryOpStub(Token::Value op, OverwriteMode mode)
}
+void StoreArrayLengthStub::Generate(MacroAssembler* masm) {
+ // ----------- S t a t e -------------
+ // -- eax : value
+ // -- ecx : name
+ // -- edx : receiver
+ // -- esp[0] : return address
+ // -----------------------------------
+ //
+ // This accepts as a receiver anything JSArray::SetElementsLength accepts
+ // (currently anything except for external arrays which means anything with
+ // elements of FixedArray type). Value must be a number, but only smis are
+ // accepted as the most common case.
+
+ Label miss;
+
+ Register receiver = edx;
+ Register value = eax;
+ Register scratch = ebx;
+
+ if (kind() == Code::KEYED_LOAD_IC) {
+ __ cmp(ecx, Immediate(masm->isolate()->factory()->length_symbol()));
+ __ j(not_equal, &miss);
+ }
+
+ // Check that the receiver isn't a smi.
+ __ JumpIfSmi(receiver, &miss);
+
+ // Check that the object is a JS array.
+ __ CmpObjectType(receiver, JS_ARRAY_TYPE, scratch);
+ __ j(not_equal, &miss);
+
+ // Check that elements are FixedArray.
+ // We rely on StoreIC_ArrayLength below to deal with all types of
+ // fast elements (including COW).
+ __ mov(scratch, FieldOperand(receiver, JSArray::kElementsOffset));
+ __ CmpObjectType(scratch, FIXED_ARRAY_TYPE, scratch);
+ __ j(not_equal, &miss);
+
+ // Check that the array has fast properties, otherwise the length
+ // property might have been redefined.
+ __ mov(scratch, FieldOperand(receiver, JSArray::kPropertiesOffset));
+ __ CompareRoot(FieldOperand(scratch, FixedArray::kMapOffset),
+ Heap::kHashTableMapRootIndex);
+ __ j(equal, &miss);
+
+ // Check that value is a smi.
+ __ JumpIfNotSmi(value, &miss);
+
+ // Prepare tail call to StoreIC_ArrayLength.
+ __ pop(scratch);
+ __ push(receiver);
+ __ push(value);
+ __ push(scratch); // return address
+
+ ExternalReference ref =
+ ExternalReference(IC_Utility(IC::kStoreIC_ArrayLength), masm->isolate());
+ __ TailCallExternalReference(ref, 2, 1);
+
+ __ bind(&miss);
+
+ StubCompiler::GenerateStoreMiss(masm, kind());
+}
+
+
void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) {
// The key is in edx and the parameter count is in eax.
}
-void StoreIC::GenerateArrayLength(MacroAssembler* masm) {
- // ----------- S t a t e -------------
- // -- eax : value
- // -- ecx : name
- // -- edx : receiver
- // -- esp[0] : return address
- // -----------------------------------
- //
- // This accepts as a receiver anything JSArray::SetElementsLength accepts
- // (currently anything except for external arrays which means anything with
- // elements of FixedArray type). Value must be a number, but only smis are
- // accepted as the most common case.
-
- Label miss;
-
- Register receiver = edx;
- Register value = eax;
- Register scratch = ebx;
-
- // Check that the receiver isn't a smi.
- __ JumpIfSmi(receiver, &miss);
-
- // Check that the object is a JS array.
- __ CmpObjectType(receiver, JS_ARRAY_TYPE, scratch);
- __ j(not_equal, &miss);
-
- // Check that elements are FixedArray.
- // We rely on StoreIC_ArrayLength below to deal with all types of
- // fast elements (including COW).
- __ mov(scratch, FieldOperand(receiver, JSArray::kElementsOffset));
- __ CmpObjectType(scratch, FIXED_ARRAY_TYPE, scratch);
- __ j(not_equal, &miss);
-
- // Check that the array has fast properties, otherwise the length
- // property might have been redefined.
- __ mov(scratch, FieldOperand(receiver, JSArray::kPropertiesOffset));
- __ CompareRoot(FieldOperand(scratch, FixedArray::kMapOffset),
- Heap::kHashTableMapRootIndex);
- __ j(equal, &miss);
-
- // Check that value is a smi.
- __ JumpIfNotSmi(value, &miss);
-
- // Prepare tail call to StoreIC_ArrayLength.
- __ pop(scratch);
- __ push(receiver);
- __ push(value);
- __ push(scratch); // return address
-
- ExternalReference ref =
- ExternalReference(IC_Utility(kStoreIC_ArrayLength), masm->isolate());
- __ TailCallExternalReference(ref, 2, 1);
-
- __ bind(&miss);
-
- GenerateMiss(masm);
-}
-
-
void StoreIC::GenerateNormal(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- eax : value
}
+void StubCompiler::GenerateStoreMiss(MacroAssembler* masm, Code::Kind kind) {
+ ASSERT(kind == Code::STORE_IC || kind == Code::KEYED_STORE_IC);
+ Handle<Code> code = (kind == Code::STORE_IC)
+ ? masm->isolate()->builtins()->StoreIC_Miss()
+ : masm->isolate()->builtins()->KeyedStoreIC_Miss();
+ __ jmp(code, RelocInfo::CODE_TARGET);
+}
+
+
void StubCompiler::GenerateKeyedLoadMissForceGeneric(MacroAssembler* masm) {
Handle<Code> code =
masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
return TypeError("non_object_property_call", object, key);
}
- if (FLAG_use_ic && state != MEGAMORPHIC && object->IsHeapObject()) {
- ASSERT(state != GENERIC);
+ bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded();
+ ASSERT(!(use_ic && object->IsJSGlobalProxy()));
+
+ if (use_ic && state != MEGAMORPHIC) {
int argc = target()->arguments_count();
- Handle<Map> map =
- isolate()->factory()->non_strict_arguments_elements_map();
- if (object->IsJSObject() &&
- Handle<JSObject>::cast(object)->elements()->map() == *map) {
- Handle<Code> code = isolate()->stub_cache()->ComputeCallArguments(
- argc, Code::KEYED_CALL_IC);
- set_target(*code);
- TRACE_IC("KeyedCallIC", key, state, target());
- } else if (!object->IsAccessCheckNeeded()) {
- Handle<Code> code = isolate()->stub_cache()->ComputeCallMegamorphic(
- argc, Code::KEYED_CALL_IC, Code::kNoExtraICState);
- set_target(*code);
- TRACE_IC("KeyedCallIC", key, state, target());
+ Handle<Code> stub = isolate()->stub_cache()->ComputeCallMegamorphic(
+ argc, Code::KEYED_CALL_IC, Code::kNoExtraICState);
+ if (object->IsJSObject()) {
+ Handle<JSObject> receiver = Handle<JSObject>::cast(object);
+ if (receiver->elements()->map() ==
+ isolate()->heap()->non_strict_arguments_elements_map()) {
+ stub = isolate()->stub_cache()->ComputeCallArguments(argc);
+ }
}
+ ASSERT(!stub.is_null());
+ set_target(*stub);
+ TRACE_IC("KeyedCallIC", key, state, target());
}
Handle<Object> result = GetProperty(object, key);
return LoadIC::Load(state, object, Handle<String>::cast(key));
}
- // Do not use ICs for objects that require access checks (including
- // the global object).
bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded();
+ ASSERT(!(use_ic && object->IsJSGlobalProxy()));
if (use_ic) {
Handle<Code> stub = generic_stub();
} else {
TRACE_GENERIC_IC("KeyedLoadIC", "force generic");
}
- if (!stub.is_null()) set_target(*stub);
+ ASSERT(!stub.is_null());
+ set_target(*stub);
+ TRACE_IC("KeyedLoadIC", key, state, target());
}
- TRACE_IC("KeyedLoadIC", key, state, target());
- // Get the property.
return Runtime::GetObjectProperty(isolate(), object, key);
}
receiver->IsJSArray() &&
name->Equals(isolate()->heap()->length_symbol()) &&
Handle<JSArray>::cast(receiver)->AllowsSetElementsLength() &&
- receiver->HasFastProperties() &&
- kind() != Code::KEYED_STORE_IC) {
- Handle<Code> stub = (strict_mode == kStrictMode)
- ? isolate()->builtins()->StoreIC_ArrayLength_Strict()
- : isolate()->builtins()->StoreIC_ArrayLength();
+ receiver->HasFastProperties()) {
+ Handle<Code> stub = StoreArrayLengthStub(kind(), strict_mode).GetCode();
set_target(*stub);
TRACE_IC("StoreIC", name, state, *stub);
return receiver->SetProperty(*name, *value, NONE, strict_mode, store_mode);
key = TryConvertKey(key, isolate());
if (key->IsSymbol()) {
- Handle<String> name = Handle<String>::cast(key);
return StoreIC::Store(state,
strict_mode,
object,
- name,
+ Handle<String>::cast(key),
value,
JSReceiver::MAY_BE_STORE_FROM_KEYED);
}
- // Do not use ICs for objects that require access checks (including
- // the global object), or are observed.
bool use_ic = FLAG_use_ic && !object->IsAccessCheckNeeded() &&
!(FLAG_harmony_observation && object->IsJSObject() &&
JSObject::cast(*object)->map()->is_observed());
Handle<Code> stub = (strict_mode == kStrictMode)
? generic_stub_strict()
: generic_stub();
- if (object->IsJSObject()) {
- Handle<JSObject> receiver = Handle<JSObject>::cast(object);
- if (receiver->elements()->map() ==
- isolate()->heap()->non_strict_arguments_elements_map()) {
- stub = non_strict_arguments_stub();
- } else if (miss_mode != MISS_FORCE_GENERIC) {
- if (key->IsSmi() && (target() != *non_strict_arguments_stub())) {
+ if (miss_mode != MISS_FORCE_GENERIC) {
+ if (object->IsJSObject()) {
+ Handle<JSObject> receiver = Handle<JSObject>::cast(object);
+ if (receiver->elements()->map() ==
+ isolate()->heap()->non_strict_arguments_elements_map()) {
+ stub = non_strict_arguments_stub();
+ } else if (key->IsSmi() && (target() != *non_strict_arguments_stub())) {
StubKind stub_kind = GetStubKind(receiver, key, value);
stub = StoreElementStub(receiver, stub_kind, strict_mode);
}
- } else {
- TRACE_GENERIC_IC("KeyedStoreIC", "force generic");
}
+ } else {
+ TRACE_GENERIC_IC("KeyedStoreIC", "force generic");
}
- if (!stub.is_null()) set_target(*stub);
+ ASSERT(!stub.is_null());
+ set_target(*stub);
+ TRACE_IC("KeyedStoreIC", key, state, target());
}
- TRACE_IC("KeyedStoreIC", key, state, target());
-
- // Set the property.
return Runtime::SetObjectProperty(
isolate(), object , key, value, NONE, strict_mode);
}
#endif
Object* result;
- { MaybeObject* maybe_result = receiver->SetElementsLength(len);
- if (!maybe_result->ToObject(&result)) return maybe_result;
- }
+ MaybeObject* maybe_result = receiver->SetElementsLength(len);
+ if (!maybe_result->To(&result)) return maybe_result;
+
return len;
}
static void GenerateMegamorphic(MacroAssembler* masm);
static void GenerateNormal(MacroAssembler* masm);
- // Specialized code generator routines.
- static void GenerateArrayLength(MacroAssembler* masm);
- static void GenerateFunctionPrototype(MacroAssembler* masm);
-
MUST_USE_RESULT MaybeObject* Load(State state,
Handle<Object> object,
Handle<String> name);
static void GenerateMiss(MacroAssembler* masm);
static void GenerateMegamorphic(MacroAssembler* masm,
StrictModeFlag strict_mode);
- static void GenerateArrayLength(MacroAssembler* masm);
static void GenerateNormal(MacroAssembler* masm);
static void GenerateGlobalProxy(MacroAssembler* masm,
StrictModeFlag strict_mode);
kind() == COMPARE_IC ||
kind() == LOAD_IC ||
kind() == KEYED_LOAD_IC ||
+ kind() == STORE_IC ||
+ kind() == KEYED_STORE_IC ||
kind() == TO_BOOLEAN_IC);
ASSERT(0 <= major && major < 256);
int previous = READ_UINT32_FIELD(this, kKindSpecificFlags2Offset);
ASSERT(kind() == COMPARE_IC ||
kind() == BINARY_OP_IC ||
kind() == LOAD_IC ||
- kind() == KEYED_LOAD_IC);
+ kind() == KEYED_LOAD_IC ||
+ kind() == STORE_IC ||
+ kind() == KEYED_STORE_IC);
WRITE_FIELD(this, kTypeFeedbackInfoOffset, Smi::FromInt(value));
}
}
-Handle<Code> StubCache::ComputeCallArguments(int argc, Code::Kind kind) {
- ASSERT(kind == Code::KEYED_CALL_IC);
+Handle<Code> StubCache::ComputeCallArguments(int argc) {
Code::Flags flags =
- Code::ComputeFlags(kind, MEGAMORPHIC, Code::kNoExtraICState,
- Code::NORMAL, argc);
+ Code::ComputeFlags(Code::KEYED_CALL_IC, MEGAMORPHIC,
+ Code::kNoExtraICState, Code::NORMAL, argc);
Handle<UnseededNumberDictionary> cache =
isolate_->factory()->non_monomorphic_cache();
int entry = cache->FindEntry(isolate_, flags);
Code::Kind kind,
Code::ExtraICState state);
- Handle<Code> ComputeCallArguments(int argc, Code::Kind kind);
+ Handle<Code> ComputeCallArguments(int argc);
Handle<Code> ComputeCallMegamorphic(int argc,
Code::Kind kind,
Register scratch2,
Label* miss_label);
- static void GenerateLoadMiss(MacroAssembler* masm,
- Code::Kind kind);
+ static void GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind);
+ static void GenerateStoreMiss(MacroAssembler* masm, Code::Kind kind);
static void GenerateKeyedLoadMissForceGeneric(MacroAssembler* masm);
}
+void StoreArrayLengthStub::Generate(MacroAssembler* masm) {
+ // ----------- S t a t e -------------
+ // -- rax : value
+ // -- rcx : key
+ // -- rdx : receiver
+ // -- rsp[0] : return address
+ // -----------------------------------
+ //
+ // This accepts as a receiver anything JSArray::SetElementsLength accepts
+ // (currently anything except for external arrays which means anything with
+ // elements of FixedArray type). Value must be a number, but only smis are
+ // accepted as the most common case.
+
+ Label miss;
+
+ Register receiver = rdx;
+ Register value = rax;
+ Register scratch = rbx;
+ if (kind() == Code::KEYED_STORE_IC) {
+ __ Cmp(rcx, masm->isolate()->factory()->length_symbol());
+ }
+
+ // Check that the receiver isn't a smi.
+ __ JumpIfSmi(receiver, &miss);
+
+ // Check that the object is a JS array.
+ __ CmpObjectType(receiver, JS_ARRAY_TYPE, scratch);
+ __ j(not_equal, &miss);
+
+ // Check that elements are FixedArray.
+ // We rely on StoreIC_ArrayLength below to deal with all types of
+ // fast elements (including COW).
+ __ movq(scratch, FieldOperand(receiver, JSArray::kElementsOffset));
+ __ CmpObjectType(scratch, FIXED_ARRAY_TYPE, scratch);
+ __ j(not_equal, &miss);
+
+ // Check that the array has fast properties, otherwise the length
+ // property might have been redefined.
+ __ movq(scratch, FieldOperand(receiver, JSArray::kPropertiesOffset));
+ __ CompareRoot(FieldOperand(scratch, FixedArray::kMapOffset),
+ Heap::kHashTableMapRootIndex);
+ __ j(equal, &miss);
+
+ // Check that value is a smi.
+ __ JumpIfNotSmi(value, &miss);
+
+ // Prepare tail call to StoreIC_ArrayLength.
+ __ pop(scratch);
+ __ push(receiver);
+ __ push(value);
+ __ push(scratch); // return address
+
+ ExternalReference ref =
+ ExternalReference(IC_Utility(IC::kStoreIC_ArrayLength), masm->isolate());
+ __ TailCallExternalReference(ref, 2, 1);
+
+ __ bind(&miss);
+
+ StubCompiler::GenerateStoreMiss(masm, kind());
+}
+
+
void ArgumentsAccessStub::GenerateReadElement(MacroAssembler* masm) {
// The key is in rdx and the parameter count is in rax.
}
-void StoreIC::GenerateArrayLength(MacroAssembler* masm) {
- // ----------- S t a t e -------------
- // -- rax : value
- // -- rcx : name
- // -- rdx : receiver
- // -- rsp[0] : return address
- // -----------------------------------
- //
- // This accepts as a receiver anything JSArray::SetElementsLength accepts
- // (currently anything except for external arrays which means anything with
- // elements of FixedArray type). Value must be a number, but only smis are
- // accepted as the most common case.
-
- Label miss;
-
- Register receiver = rdx;
- Register value = rax;
- Register scratch = rbx;
-
- // Check that the receiver isn't a smi.
- __ JumpIfSmi(receiver, &miss);
-
- // Check that the object is a JS array.
- __ CmpObjectType(receiver, JS_ARRAY_TYPE, scratch);
- __ j(not_equal, &miss);
-
- // Check that elements are FixedArray.
- // We rely on StoreIC_ArrayLength below to deal with all types of
- // fast elements (including COW).
- __ movq(scratch, FieldOperand(receiver, JSArray::kElementsOffset));
- __ CmpObjectType(scratch, FIXED_ARRAY_TYPE, scratch);
- __ j(not_equal, &miss);
-
- // Check that the array has fast properties, otherwise the length
- // property might have been redefined.
- __ movq(scratch, FieldOperand(receiver, JSArray::kPropertiesOffset));
- __ CompareRoot(FieldOperand(scratch, FixedArray::kMapOffset),
- Heap::kHashTableMapRootIndex);
- __ j(equal, &miss);
-
- // Check that value is a smi.
- __ JumpIfNotSmi(value, &miss);
-
- // Prepare tail call to StoreIC_ArrayLength.
- __ pop(scratch);
- __ push(receiver);
- __ push(value);
- __ push(scratch); // return address
-
- ExternalReference ref =
- ExternalReference(IC_Utility(kStoreIC_ArrayLength), masm->isolate());
- __ TailCallExternalReference(ref, 2, 1);
-
- __ bind(&miss);
-
- GenerateMiss(masm);
-}
-
-
void StoreIC::GenerateNormal(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- rax : value
}
+void StubCompiler::GenerateStoreMiss(MacroAssembler* masm, Code::Kind kind) {
+ ASSERT(kind == Code::STORE_IC || kind == Code::KEYED_STORE_IC);
+ Handle<Code> code = (kind == Code::STORE_IC)
+ ? masm->isolate()->builtins()->StoreIC_Miss()
+ : masm->isolate()->builtins()->KeyedStoreIC_Miss();
+ __ Jump(code, RelocInfo::CODE_TARGET);
+}
+
+
void StubCompiler::GenerateKeyedLoadMissForceGeneric(MacroAssembler* masm) {
Handle<Code> code =
masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();