| Index: src/arm/stub-cache-arm.cc
|
| diff --git a/src/arm/stub-cache-arm.cc b/src/arm/stub-cache-arm.cc
|
| index eca3e453c0e42780ef645837a872c928215f0fbf..21b77e1bcb216e8cab13a3780163da2dc06e6bfe 100644
|
| --- a/src/arm/stub-cache-arm.cc
|
| +++ b/src/arm/stub-cache-arm.cc
|
| @@ -3091,52 +3091,56 @@ MaybeObject* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) {
|
| }
|
|
|
|
|
| -MaybeObject* KeyedLoadStubCompiler::CompileLoadSpecialized(JSObject* receiver) {
|
| +MaybeObject* KeyedLoadStubCompiler::CompileLoadFastElement(Map* receiver_map) {
|
| // ----------- S t a t e -------------
|
| // -- lr : return address
|
| // -- r0 : key
|
| // -- r1 : receiver
|
| // -----------------------------------
|
| - Label miss;
|
| -
|
| - // Check that the receiver isn't a smi.
|
| - __ tst(r1, Operand(kSmiTagMask));
|
| - __ b(eq, &miss);
|
| -
|
| - // Check that the map matches.
|
| - __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
|
| - __ cmp(r2, Operand(Handle<Map>(receiver->map())));
|
| - __ b(ne, &miss);
|
| + MaybeObject* maybe_stub = KeyedLoadFastElementStub().TryGetCode();
|
| + Code* stub;
|
| + if (!maybe_stub->To(&stub)) return maybe_stub;
|
| + __ DispatchMap(r1,
|
| + r2,
|
| + Handle<Map>(receiver_map),
|
| + Handle<Code>(stub),
|
| + DO_SMI_CHECK);
|
| +
|
| + Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Miss();
|
| + __ Jump(ic, RelocInfo::CODE_TARGET);
|
|
|
| - // Check that the key is a smi.
|
| - __ tst(r0, Operand(kSmiTagMask));
|
| - __ b(ne, &miss);
|
| + // Return the generated code.
|
| + return GetCode(NORMAL, NULL);
|
| +}
|
|
|
| - // Get the elements array.
|
| - __ ldr(r2, FieldMemOperand(r1, JSObject::kElementsOffset));
|
| - __ AssertFastElements(r2);
|
|
|
| - // Check that the key is within bounds.
|
| - __ ldr(r3, FieldMemOperand(r2, FixedArray::kLengthOffset));
|
| - __ cmp(r0, Operand(r3));
|
| - __ b(hs, &miss);
|
| +MaybeObject* KeyedLoadStubCompiler::CompileLoadMegamorphic(
|
| + MapList* receiver_maps,
|
| + CodeList* handler_ics) {
|
| + // ----------- S t a t e -------------
|
| + // -- lr : return address
|
| + // -- r0 : key
|
| + // -- r1 : receiver
|
| + // -----------------------------------
|
| + Label miss;
|
| + __ JumpIfSmi(r1, &miss);
|
|
|
| - // Load the result and make sure it's not the hole.
|
| - __ add(r3, r2, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
|
| - ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2);
|
| - __ ldr(r4,
|
| - MemOperand(r3, r0, LSL, kPointerSizeLog2 - kSmiTagSize));
|
| - __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
|
| - __ cmp(r4, ip);
|
| - __ b(eq, &miss);
|
| - __ mov(r0, r4);
|
| - __ Ret();
|
| + int receiver_count = receiver_maps->length();
|
| + __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
|
| + for (int current = 0; current < receiver_count; ++current) {
|
| + Handle<Map> map(receiver_maps->at(current));
|
| + Handle<Code> code(handler_ics->at(current));
|
| + __ mov(ip, Operand(map));
|
| + __ cmp(r2, ip);
|
| + __ Jump(code, RelocInfo::CODE_TARGET, eq);
|
| + }
|
|
|
| __ bind(&miss);
|
| - GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
|
| + Handle<Code> miss_ic = isolate()->builtins()->KeyedLoadIC_Miss();
|
| + __ Jump(miss_ic, RelocInfo::CODE_TARGET, al);
|
|
|
| // Return the generated code.
|
| - return GetCode(NORMAL, NULL);
|
| + return GetCode(NORMAL, NULL, MEGAMORPHIC);
|
| }
|
|
|
|
|
| @@ -3178,73 +3182,63 @@ MaybeObject* KeyedStoreStubCompiler::CompileStoreField(JSObject* object,
|
| }
|
|
|
|
|
| -MaybeObject* KeyedStoreStubCompiler::CompileStoreSpecialized(
|
| - JSObject* receiver) {
|
| +MaybeObject* KeyedStoreStubCompiler::CompileStoreFastElement(
|
| + Map* receiver_map) {
|
| // ----------- S t a t e -------------
|
| // -- r0 : value
|
| // -- r1 : key
|
| // -- r2 : receiver
|
| // -- lr : return address
|
| // -- r3 : scratch
|
| - // -- r4 : scratch (elements)
|
| // -----------------------------------
|
| - Label miss;
|
| -
|
| - Register value_reg = r0;
|
| - Register key_reg = r1;
|
| - Register receiver_reg = r2;
|
| - Register scratch = r3;
|
| - Register elements_reg = r4;
|
| -
|
| - // Check that the receiver isn't a smi.
|
| - __ tst(receiver_reg, Operand(kSmiTagMask));
|
| - __ b(eq, &miss);
|
| -
|
| - // Check that the map matches.
|
| - __ ldr(scratch, FieldMemOperand(receiver_reg, HeapObject::kMapOffset));
|
| - __ cmp(scratch, Operand(Handle<Map>(receiver->map())));
|
| - __ b(ne, &miss);
|
| + bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE;
|
| + MaybeObject* maybe_stub =
|
| + KeyedStoreFastElementStub(is_js_array).TryGetCode();
|
| + Code* stub;
|
| + if (!maybe_stub->To(&stub)) return maybe_stub;
|
| + __ DispatchMap(r2,
|
| + r3,
|
| + Handle<Map>(receiver_map),
|
| + Handle<Code>(stub),
|
| + DO_SMI_CHECK);
|
| +
|
| + Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss();
|
| + __ Jump(ic, RelocInfo::CODE_TARGET);
|
|
|
| - // Check that the key is a smi.
|
| - __ tst(key_reg, Operand(kSmiTagMask));
|
| - __ b(ne, &miss);
|
| + // Return the generated code.
|
| + return GetCode(NORMAL, NULL);
|
| +}
|
|
|
| - // Get the elements array and make sure it is a fast element array, not 'cow'.
|
| - __ ldr(elements_reg,
|
| - FieldMemOperand(receiver_reg, JSObject::kElementsOffset));
|
| - __ ldr(scratch, FieldMemOperand(elements_reg, HeapObject::kMapOffset));
|
| - __ cmp(scratch, Operand(Handle<Map>(factory()->fixed_array_map())));
|
| - __ b(ne, &miss);
|
|
|
| - // Check that the key is within bounds.
|
| - if (receiver->IsJSArray()) {
|
| - __ ldr(scratch, FieldMemOperand(receiver_reg, JSArray::kLengthOffset));
|
| - } else {
|
| - __ ldr(scratch, FieldMemOperand(elements_reg, FixedArray::kLengthOffset));
|
| +MaybeObject* KeyedStoreStubCompiler::CompileStoreMegamorphic(
|
| + MapList* receiver_maps,
|
| + CodeList* handler_ics) {
|
| + // ----------- S t a t e -------------
|
| + // -- r0 : value
|
| + // -- r1 : key
|
| + // -- r2 : receiver
|
| + // -- lr : return address
|
| + // -- r3 : scratch
|
| + // -----------------------------------
|
| + Label miss;
|
| + __ JumpIfSmi(r2, &miss);
|
| +
|
| + int receiver_count = receiver_maps->length();
|
| + __ ldr(r3, FieldMemOperand(r2, HeapObject::kMapOffset));
|
| + for (int current = 0; current < receiver_count; ++current) {
|
| + Handle<Map> map(receiver_maps->at(current));
|
| + Handle<Code> code(handler_ics->at(current));
|
| + __ mov(ip, Operand(map));
|
| + __ cmp(r3, ip);
|
| + __ Jump(code, RelocInfo::CODE_TARGET, eq);
|
| }
|
| - // Compare smis.
|
| - __ cmp(key_reg, scratch);
|
| - __ b(hs, &miss);
|
| -
|
| - __ add(scratch,
|
| - elements_reg, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
|
| - ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2);
|
| - __ str(value_reg,
|
| - MemOperand(scratch, key_reg, LSL, kPointerSizeLog2 - kSmiTagSize));
|
| - __ RecordWrite(scratch,
|
| - Operand(key_reg, LSL, kPointerSizeLog2 - kSmiTagSize),
|
| - receiver_reg , elements_reg);
|
| -
|
| - // value_reg (r0) is preserved.
|
| - // Done.
|
| - __ Ret();
|
|
|
| __ bind(&miss);
|
| - Handle<Code> ic = masm()->isolate()->builtins()->KeyedStoreIC_Miss();
|
| - __ Jump(ic, RelocInfo::CODE_TARGET);
|
| + Handle<Code> miss_ic = isolate()->builtins()->KeyedStoreIC_Miss();
|
| + __ Jump(miss_ic, RelocInfo::CODE_TARGET, al);
|
|
|
| // Return the generated code.
|
| - return GetCode(NORMAL, NULL);
|
| + return GetCode(NORMAL, NULL, MEGAMORPHIC);
|
| }
|
|
|
|
|
| @@ -3392,6 +3386,60 @@ MaybeObject* ConstructStubCompiler::CompileConstructStub(JSFunction* function) {
|
| }
|
|
|
|
|
| +MaybeObject* ExternalArrayLoadStubCompiler::CompileLoad(
|
| + JSObject*receiver, ExternalArrayType array_type) {
|
| + // ----------- S t a t e -------------
|
| + // -- lr : return address
|
| + // -- r0 : key
|
| + // -- r1 : receiver
|
| + // -----------------------------------
|
| + MaybeObject* maybe_stub =
|
| + KeyedLoadExternalArrayStub(array_type).TryGetCode();
|
| + Code* stub;
|
| + if (!maybe_stub->To(&stub)) return maybe_stub;
|
| + __ DispatchMap(r1,
|
| + r2,
|
| + Handle<Map>(receiver->map()),
|
| + Handle<Code>(stub),
|
| + DO_SMI_CHECK);
|
| +
|
| + Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Miss();
|
| + __ Jump(ic, RelocInfo::CODE_TARGET);
|
| +
|
| + // Return the generated code.
|
| + return GetCode();
|
| +}
|
| +
|
| +
|
| +MaybeObject* ExternalArrayStoreStubCompiler::CompileStore(
|
| + JSObject* receiver, ExternalArrayType array_type) {
|
| + // ----------- S t a t e -------------
|
| + // -- r0 : value
|
| + // -- r1 : name
|
| + // -- r2 : receiver
|
| + // -- lr : return address
|
| + // -----------------------------------
|
| + MaybeObject* maybe_stub =
|
| + KeyedStoreExternalArrayStub(array_type).TryGetCode();
|
| + Code* stub;
|
| + if (!maybe_stub->To(&stub)) return maybe_stub;
|
| + __ DispatchMap(r2,
|
| + r3,
|
| + Handle<Map>(receiver->map()),
|
| + Handle<Code>(stub),
|
| + DONT_DO_SMI_CHECK);
|
| +
|
| + Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss();
|
| + __ Jump(ic, RelocInfo::CODE_TARGET);
|
| +
|
| + return GetCode();
|
| +}
|
| +
|
| +
|
| +#undef __
|
| +#define __ ACCESS_MASM(masm)
|
| +
|
| +
|
| static bool IsElementTypeSigned(ExternalArrayType array_type) {
|
| switch (array_type) {
|
| case kExternalByteArray:
|
| @@ -3411,30 +3459,24 @@ static bool IsElementTypeSigned(ExternalArrayType array_type) {
|
| }
|
|
|
|
|
| -MaybeObject* ExternalArrayStubCompiler::CompileKeyedLoadStub(
|
| - JSObject* receiver_object,
|
| - ExternalArrayType array_type,
|
| - Code::Flags flags) {
|
| +void KeyedLoadStubCompiler::GenerateLoadExternalArray(
|
| + MacroAssembler* masm,
|
| + ExternalArrayType array_type) {
|
| // ---------- S t a t e --------------
|
| // -- lr : return address
|
| // -- r0 : key
|
| // -- r1 : receiver
|
| // -----------------------------------
|
| - Label slow, failed_allocation;
|
| + Label miss_force_generic, slow, failed_allocation;
|
|
|
| Register key = r0;
|
| Register receiver = r1;
|
|
|
| - // Check that the object isn't a smi
|
| - __ JumpIfSmi(receiver, &slow);
|
| + // This stub is meant to be tail-jumped to, the receiver must already
|
| + // have been verified by the caller to not be a smi.
|
|
|
| // Check that the key is a smi.
|
| - __ JumpIfNotSmi(key, &slow);
|
| -
|
| - // Make sure that we've got the right map.
|
| - __ ldr(r2, FieldMemOperand(receiver, HeapObject::kMapOffset));
|
| - __ cmp(r2, Operand(Handle<Map>(receiver_object->map())));
|
| - __ b(ne, &slow);
|
| + __ JumpIfNotSmi(key, &miss_force_generic);
|
|
|
| __ ldr(r3, FieldMemOperand(receiver, JSObject::kElementsOffset));
|
| // r3: elements array
|
| @@ -3443,7 +3485,7 @@ MaybeObject* ExternalArrayStubCompiler::CompileKeyedLoadStub(
|
| __ ldr(ip, FieldMemOperand(r3, ExternalArray::kLengthOffset));
|
| __ cmp(ip, Operand(key, ASR, kSmiTagSize));
|
| // Unsigned comparison catches both negative and too-large values.
|
| - __ b(lo, &slow);
|
| + __ b(lo, &miss_force_generic);
|
|
|
| __ ldr(r3, FieldMemOperand(r3, ExternalArray::kExternalPointerOffset));
|
| // r3: base pointer of external storage
|
| @@ -3535,8 +3577,7 @@ MaybeObject* ExternalArrayStubCompiler::CompileKeyedLoadStub(
|
| __ Ret();
|
| } else {
|
| WriteInt32ToHeapNumberStub stub(value, r0, r3);
|
| - MaybeObject* stub_code = masm()->TryTailCallStub(&stub);
|
| - if (stub_code->IsFailure()) return stub_code;
|
| + __ TailCallStub(&stub);
|
| }
|
| } else if (array_type == kExternalUnsignedIntArray) {
|
| // The test is different for unsigned int values. Since we need
|
| @@ -3581,12 +3622,12 @@ MaybeObject* ExternalArrayStubCompiler::CompileKeyedLoadStub(
|
|
|
| __ bind(&box_int_0);
|
| // Integer does not have leading zeros.
|
| - GenerateUInt2Double(masm(), hiword, loword, r4, 0);
|
| + GenerateUInt2Double(masm, hiword, loword, r4, 0);
|
| __ b(&done);
|
|
|
| __ bind(&box_int_1);
|
| // Integer has one leading zero.
|
| - GenerateUInt2Double(masm(), hiword, loword, r4, 1);
|
| + GenerateUInt2Double(masm, hiword, loword, r4, 1);
|
|
|
|
|
| __ bind(&done);
|
| @@ -3708,7 +3749,7 @@ MaybeObject* ExternalArrayStubCompiler::CompileKeyedLoadStub(
|
| // Slow case, key and receiver still in r0 and r1.
|
| __ bind(&slow);
|
| __ IncrementCounter(
|
| - masm()->isolate()->counters()->keyed_load_external_array_slow(),
|
| + masm->isolate()->counters()->keyed_load_external_array_slow(),
|
| 1, r2, r3);
|
|
|
| // ---------- S t a t e --------------
|
| @@ -3721,21 +3762,23 @@ MaybeObject* ExternalArrayStubCompiler::CompileKeyedLoadStub(
|
|
|
| __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1);
|
|
|
| - return GetCode(flags);
|
| + __ bind(&miss_force_generic);
|
| + Code* stub = masm->isolate()->builtins()->builtin(
|
| + Builtins::kKeyedLoadIC_MissForceGeneric);
|
| + __ Jump(Handle<Code>(stub), RelocInfo::CODE_TARGET);
|
| }
|
|
|
|
|
| -MaybeObject* ExternalArrayStubCompiler::CompileKeyedStoreStub(
|
| - JSObject* receiver_object,
|
| - ExternalArrayType array_type,
|
| - Code::Flags flags) {
|
| +void KeyedStoreStubCompiler::GenerateStoreExternalArray(
|
| + MacroAssembler* masm,
|
| + ExternalArrayType array_type) {
|
| // ---------- S t a t e --------------
|
| // -- r0 : value
|
| // -- r1 : key
|
| // -- r2 : receiver
|
| // -- lr : return address
|
| // -----------------------------------
|
| - Label slow, check_heap_number;
|
| + Label slow, check_heap_number, miss_force_generic;
|
|
|
| // Register usage.
|
| Register value = r0;
|
| @@ -3743,25 +3786,20 @@ MaybeObject* ExternalArrayStubCompiler::CompileKeyedStoreStub(
|
| Register receiver = r2;
|
| // r3 mostly holds the elements array or the destination external array.
|
|
|
| - // Check that the object isn't a smi.
|
| - __ JumpIfSmi(receiver, &slow);
|
| -
|
| - // Make sure that we've got the right map.
|
| - __ ldr(r3, FieldMemOperand(receiver, HeapObject::kMapOffset));
|
| - __ cmp(r3, Operand(Handle<Map>(receiver_object->map())));
|
| - __ b(ne, &slow);
|
| + // This stub is meant to be tail-jumped to, the receiver must already
|
| + // have been verified by the caller to not be a smi.
|
|
|
| __ ldr(r3, FieldMemOperand(receiver, JSObject::kElementsOffset));
|
|
|
| // Check that the key is a smi.
|
| - __ JumpIfNotSmi(key, &slow);
|
| + __ JumpIfNotSmi(key, &miss_force_generic);
|
|
|
| // Check that the index is in range
|
| __ SmiUntag(r4, key);
|
| __ ldr(ip, FieldMemOperand(r3, ExternalArray::kLengthOffset));
|
| __ cmp(r4, ip);
|
| // Unsigned comparison catches both negative and too-large values.
|
| - __ b(hs, &slow);
|
| + __ b(hs, &miss_force_generic);
|
|
|
| // Handle both smis and HeapNumbers in the fast path. Go to the
|
| // runtime for all other kinds of values.
|
| @@ -3799,7 +3837,7 @@ MaybeObject* ExternalArrayStubCompiler::CompileKeyedStoreStub(
|
| break;
|
| case kExternalFloatArray:
|
| // Perform int-to-float conversion and store to memory.
|
| - StoreIntAsFloat(masm(), r3, r4, r5, r6, r7, r9);
|
| + StoreIntAsFloat(masm, r3, r4, r5, r6, r7, r9);
|
| break;
|
| case kExternalDoubleArray:
|
| __ add(r3, r3, Operand(r4, LSL, 3));
|
| @@ -3811,7 +3849,7 @@ MaybeObject* ExternalArrayStubCompiler::CompileKeyedStoreStub(
|
| destination = FloatingPointHelper::kCoreRegisters;
|
| }
|
| FloatingPointHelper::ConvertIntToDouble(
|
| - masm(), r5, destination,
|
| + masm, r5, destination,
|
| d0, r6, r7, // These are: double_dst, dst1, dst2.
|
| r4, s2); // These are: scratch2, single_scratch.
|
| if (destination == FloatingPointHelper::kVFPRegisters) {
|
| @@ -4038,28 +4076,137 @@ MaybeObject* ExternalArrayStubCompiler::CompileKeyedStoreStub(
|
| }
|
| }
|
|
|
| - // Slow case: call runtime.
|
| + // Slow case, key and receiver still in r0 and r1.
|
| __ bind(&slow);
|
| + __ IncrementCounter(
|
| + masm->isolate()->counters()->keyed_load_external_array_slow(),
|
| + 1, r2, r3);
|
|
|
| - // Entry registers are intact.
|
| // ---------- S t a t e --------------
|
| - // -- r0 : value
|
| - // -- r1 : key
|
| - // -- r2 : receiver
|
| // -- lr : return address
|
| + // -- r0 : key
|
| + // -- r1 : receiver
|
| // -----------------------------------
|
| + Handle<Code> slow_ic =
|
| + masm->isolate()->builtins()->KeyedStoreIC_Slow();
|
| + __ Jump(slow_ic, RelocInfo::CODE_TARGET);
|
|
|
| - // Push receiver, key and value for runtime call.
|
| - __ Push(r2, r1, r0);
|
| + // Miss case, call the runtime.
|
| + __ bind(&miss_force_generic);
|
|
|
| - __ mov(r1, Operand(Smi::FromInt(NONE))); // PropertyAttributes
|
| - __ mov(r0, Operand(Smi::FromInt(
|
| - Code::ExtractExtraICStateFromFlags(flags) & kStrictMode)));
|
| - __ Push(r1, r0);
|
| + // ---------- S t a t e --------------
|
| + // -- lr : return address
|
| + // -- r0 : key
|
| + // -- r1 : receiver
|
| + // -----------------------------------
|
| +
|
| + Handle<Code> miss_ic =
|
| + masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
|
| + __ Jump(miss_ic, RelocInfo::CODE_TARGET);
|
| +}
|
| +
|
| +
|
| +void KeyedLoadStubCompiler::GenerateLoadFastElement(MacroAssembler* masm) {
|
| + // ----------- S t a t e -------------
|
| + // -- lr : return address
|
| + // -- r0 : key
|
| + // -- r1 : receiver
|
| + // -----------------------------------
|
| + Label miss_force_generic;
|
|
|
| - __ TailCallRuntime(Runtime::kSetProperty, 5, 1);
|
| + // This stub is meant to be tail-jumped to, the receiver must already
|
| + // have been verified by the caller to not be a smi.
|
|
|
| - return GetCode(flags);
|
| + // Check that the key is a smi.
|
| + __ JumpIfNotSmi(r0, &miss_force_generic);
|
| +
|
| + // Get the elements array.
|
| + __ ldr(r2, FieldMemOperand(r1, JSObject::kElementsOffset));
|
| + __ AssertFastElements(r2);
|
| +
|
| + // Check that the key is within bounds.
|
| + __ ldr(r3, FieldMemOperand(r2, FixedArray::kLengthOffset));
|
| + __ cmp(r0, Operand(r3));
|
| + __ b(hs, &miss_force_generic);
|
| +
|
| + // Load the result and make sure it's not the hole.
|
| + __ add(r3, r2, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
|
| + ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2);
|
| + __ ldr(r4,
|
| + MemOperand(r3, r0, LSL, kPointerSizeLog2 - kSmiTagSize));
|
| + __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
|
| + __ cmp(r4, ip);
|
| + __ b(eq, &miss_force_generic);
|
| + __ mov(r0, r4);
|
| + __ Ret();
|
| +
|
| + __ bind(&miss_force_generic);
|
| + Code* stub = masm->isolate()->builtins()->builtin(
|
| + Builtins::kKeyedLoadIC_MissForceGeneric);
|
| + __ Jump(Handle<Code>(stub), RelocInfo::CODE_TARGET);
|
| +}
|
| +
|
| +
|
| +void KeyedStoreStubCompiler::GenerateStoreFastElement(MacroAssembler* masm,
|
| + bool is_js_array) {
|
| + // ----------- S t a t e -------------
|
| + // -- r0 : value
|
| + // -- r1 : key
|
| + // -- r2 : receiver
|
| + // -- lr : return address
|
| + // -- r3 : scratch
|
| + // -- r4 : scratch (elements)
|
| + // -----------------------------------
|
| + Label miss_force_generic;
|
| +
|
| + Register value_reg = r0;
|
| + Register key_reg = r1;
|
| + Register receiver_reg = r2;
|
| + Register scratch = r3;
|
| + Register elements_reg = r4;
|
| +
|
| + // This stub is meant to be tail-jumped to, the receiver must already
|
| + // have been verified by the caller to not be a smi.
|
| +
|
| + // Check that the key is a smi.
|
| + __ JumpIfNotSmi(r0, &miss_force_generic);
|
| +
|
| + // Get the elements array and make sure it is a fast element array, not 'cow'.
|
| + __ ldr(elements_reg,
|
| + FieldMemOperand(receiver_reg, JSObject::kElementsOffset));
|
| + __ CheckMap(elements_reg,
|
| + scratch,
|
| + Heap::kFixedArrayMapRootIndex,
|
| + &miss_force_generic,
|
| + DONT_DO_SMI_CHECK);
|
| +
|
| + // Check that the key is within bounds.
|
| + if (is_js_array) {
|
| + __ ldr(scratch, FieldMemOperand(receiver_reg, JSArray::kLengthOffset));
|
| + } else {
|
| + __ ldr(scratch, FieldMemOperand(elements_reg, FixedArray::kLengthOffset));
|
| + }
|
| + // Compare smis.
|
| + __ cmp(key_reg, scratch);
|
| + __ b(hs, &miss_force_generic);
|
| +
|
| + __ add(scratch,
|
| + elements_reg, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
|
| + ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2);
|
| + __ str(value_reg,
|
| + MemOperand(scratch, key_reg, LSL, kPointerSizeLog2 - kSmiTagSize));
|
| + __ RecordWrite(scratch,
|
| + Operand(key_reg, LSL, kPointerSizeLog2 - kSmiTagSize),
|
| + receiver_reg , elements_reg);
|
| +
|
| + // value_reg (r0) is preserved.
|
| + // Done.
|
| + __ Ret();
|
| +
|
| + __ bind(&miss_force_generic);
|
| + Handle<Code> ic =
|
| + masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
|
| + __ Jump(ic, RelocInfo::CODE_TARGET);
|
| }
|
|
|
|
|
|
|