Commit 09d6ecca authored by verwaest@chromium.org's avatar verwaest@chromium.org

Replace store array length builtin with codestub.

Also includes some other minor cleanup to make Keyed related IC code
more uniform.

Review URL: https://chromiumcodereview.appspot.com/11896091

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@13506 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent b5cb682b
......@@ -4601,6 +4601,76 @@ void StringLengthStub::Generate(MacroAssembler* masm) {
}
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; }
......
......@@ -1538,62 +1538,6 @@ void StoreIC::GenerateMiss(MacroAssembler* masm) {
}
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
......
......@@ -592,6 +592,15 @@ void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) {
}
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,
......
......@@ -1560,16 +1560,6 @@ static void Generate_StoreIC_Megamorphic_Strict(MacroAssembler* masm) {
}
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);
}
......
......@@ -154,8 +154,6 @@ enum BuiltinExtraArguments {
\
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, \
......@@ -164,8 +162,6 @@ enum BuiltinExtraArguments {
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, \
......
......@@ -98,7 +98,7 @@ Handle<Code> PlatformCodeStub::GenerateCode() {
// 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;
......
......@@ -50,6 +50,7 @@ namespace internal {
V(ArrayLength) \
V(StringLength) \
V(FunctionPrototype) \
V(StoreArrayLength) \
V(RecordWrite) \
V(StoreBufferOverflow) \
V(RegExpExec) \
......@@ -179,6 +180,9 @@ class CodeStub BASE_EMBEDDED {
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.
......@@ -605,6 +609,37 @@ class StringLengthStub: public ICStub {
};
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)
......
......@@ -3317,6 +3317,70 @@ void StringLengthStub::Generate(MacroAssembler* masm) {
}
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.
......
......@@ -1426,65 +1426,6 @@ void StoreIC::GenerateMiss(MacroAssembler* masm) {
}
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
......
......@@ -737,6 +737,15 @@ void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) {
}
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();
......
......@@ -795,23 +795,23 @@ MaybeObject* KeyedCallIC::LoadFunction(State state,
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);
......@@ -1243,9 +1243,8 @@ MaybeObject* KeyedLoadIC::Load(State state,
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();
......@@ -1268,12 +1267,12 @@ MaybeObject* KeyedLoadIC::Load(State state,
} 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);
}
......@@ -1407,11 +1406,8 @@ MaybeObject* StoreIC::Store(State state,
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);
......@@ -1728,17 +1724,14 @@ MaybeObject* KeyedStoreIC::Store(State state,
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());
......@@ -1748,26 +1741,25 @@ MaybeObject* KeyedStoreIC::Store(State state,
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);
}
......@@ -1936,9 +1928,9 @@ RUNTIME_FUNCTION(MaybeObject*, StoreIC_ArrayLength) {
#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;
}
......
......@@ -347,10 +347,6 @@ class LoadIC: public IC {
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);
......@@ -483,7 +479,6 @@ class StoreIC: public IC {
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);
......
......@@ -3522,6 +3522,8 @@ void Code::set_major_key(int major) {
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);
......@@ -4927,7 +4929,9 @@ void Code::set_stub_info(int value) {
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));
}
......
......@@ -774,11 +774,10 @@ Handle<Code> StubCache::ComputeCallNormal(int argc,
}
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);
......
......@@ -227,7 +227,7 @@ class StubCache {
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,
......@@ -485,8 +485,8 @@ class StubCompiler BASE_EMBEDDED {
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);
......
......@@ -2442,6 +2442,68 @@ void StringLengthStub::Generate(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.
......
......@@ -1455,65 +1455,6 @@ void StoreIC::GenerateMiss(MacroAssembler* masm) {
}
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
......
......@@ -723,6 +723,15 @@ void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) {
}
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();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment