Index: src/mips/stub-cache-mips.cc |
diff --git a/src/mips/stub-cache-mips.cc b/src/mips/stub-cache-mips.cc |
index 5ab8e119815dfe9cfe86eb954265343d766ddc8d..cb65d88dd586e9361a52c915e843356db559d910 100644 |
--- a/src/mips/stub-cache-mips.cc |
+++ b/src/mips/stub-cache-mips.cc |
@@ -1561,8 +1561,11 @@ MaybeObject* CallStubCompiler::CompileArrayPushCall(Object* object, |
__ lw(elements, FieldMemOperand(receiver, JSArray::kElementsOffset)); |
// Check that the elements are in fast mode and writable. |
- __ CheckMap(elements, v0, |
- Heap::kFixedArrayMapRootIndex, &call_builtin, true); |
+ __ CheckMap(elements, |
+ v0, |
+ Heap::kFixedArrayMapRootIndex, |
+ &call_builtin, |
+ DONT_DO_SMI_CHECK); |
if (argc == 1) { // Otherwise fall through to call the builtin. |
Label exit, with_write_barrier, attempt_to_grow_elements; |
@@ -1710,7 +1713,11 @@ MaybeObject* CallStubCompiler::CompileArrayPopCall(Object* object, |
__ lw(elements, FieldMemOperand(receiver, JSArray::kElementsOffset)); |
// Check that the elements are in fast mode and writable. |
- __ CheckMap(elements, v0, Heap::kFixedArrayMapRootIndex, &call_builtin, true); |
+ __ CheckMap(elements, |
+ v0, |
+ Heap::kFixedArrayMapRootIndex, |
+ &call_builtin, |
+ DONT_DO_SMI_CHECK); |
// Get the array's length into t0 and calculate new length. |
__ lw(t0, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
@@ -2049,7 +2056,7 @@ MaybeObject* CallStubCompiler::CompileMathFloorCall(Object* object, |
__ Drop(argc + 1, eq, t0, Operand(zero_reg)); |
__ Ret(eq, t0, Operand(zero_reg)); |
- __ CheckMap(v0, a1, Heap::kHeapNumberMapRootIndex, &slow, true); |
+ __ CheckMap(v0, a1, Heap::kHeapNumberMapRootIndex, &slow, DONT_DO_SMI_CHECK); |
Label wont_fit_smi, no_fpu_error, restore_fcsr_and_return; |
@@ -2200,7 +2207,7 @@ MaybeObject* CallStubCompiler::CompileMathAbsCall(Object* object, |
// Check if the argument is a heap number and load its exponent and |
// sign. |
__ bind(¬_smi); |
- __ CheckMap(v0, a1, Heap::kHeapNumberMapRootIndex, &slow, true); |
+ __ CheckMap(v0, a1, Heap::kHeapNumberMapRootIndex, &slow, DONT_DO_SMI_CHECK); |
__ lw(a1, FieldMemOperand(v0, HeapNumber::kExponentOffset)); |
// Check the sign of the argument. If the argument is positive, |
@@ -2246,19 +2253,17 @@ MaybeObject* CallStubCompiler::CompileFastApiCall( |
JSFunction* function, |
String* name) { |
- Isolate* isolate = masm()->isolate(); |
- Heap* heap = isolate->heap(); |
- Counters* counters = isolate->counters(); |
+ Counters* counters = isolate()->counters(); |
ASSERT(optimization.is_simple_api_call()); |
// Bail out if object is a global object as we don't want to |
// repatch it to global receiver. |
- if (object->IsGlobalObject()) return heap->undefined_value(); |
- if (cell != NULL) return heap->undefined_value(); |
+ if (object->IsGlobalObject()) return heap()->undefined_value(); |
+ if (cell != NULL) return heap()->undefined_value(); |
if (!object->IsJSObject()) return heap()->undefined_value(); |
int depth = optimization.GetPrototypeDepthOfExpectedType( |
JSObject::cast(object), holder); |
- if (depth == kInvalidProtoDepth) return heap->undefined_value(); |
+ if (depth == kInvalidProtoDepth) return heap()->undefined_value(); |
Label miss, miss_before_stack_reserved; |
@@ -3067,48 +3072,54 @@ MaybeObject* KeyedLoadStubCompiler::CompileLoadFunctionPrototype(String* name) { |
} |
-MaybeObject* KeyedLoadStubCompiler::CompileLoadSpecialized(JSObject* receiver) { |
+MaybeObject* KeyedLoadStubCompiler::CompileLoadFastElement(Map* receiver_map) { |
// ----------- S t a t e ------------- |
// -- ra : return address |
// -- a0 : key |
// -- a1 : receiver |
// ----------------------------------- |
- Label miss; |
- |
- // Check that the receiver isn't a smi. |
- __ JumpIfSmi(a1, &miss); |
- |
- // Check that the map matches. |
- __ lw(a2, FieldMemOperand(a1, HeapObject::kMapOffset)); |
- __ Branch(&miss, ne, a2, Operand(Handle<Map>(receiver->map()))); |
+ MaybeObject* maybe_stub = KeyedLoadFastElementStub().TryGetCode(); |
+ Code* stub; |
+ if (!maybe_stub->To(&stub)) return maybe_stub; |
+ __ DispatchMap(a1, |
+ a2, |
+ 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. |
- __ JumpIfNotSmi(a0, &miss); |
+ // Return the generated code. |
+ return GetCode(NORMAL, NULL); |
+} |
- // Get the elements array. |
- __ lw(a2, FieldMemOperand(a1, JSObject::kElementsOffset)); |
- __ AssertFastElements(a2); |
- // Check that the key is within bounds. |
- __ lw(a3, FieldMemOperand(a2, FixedArray::kLengthOffset)); |
- __ Branch(&miss, hs, a0, Operand(a3)); |
+MaybeObject* KeyedLoadStubCompiler::CompileLoadMegamorphic( |
+ MapList* receiver_maps, |
+ CodeList* handler_ics) { |
+ // ----------- S t a t e ------------- |
+ // -- ra : return address |
+ // -- a0 : key |
+ // -- a1 : receiver |
+ // ----------------------------------- |
+ Label miss; |
+ __ JumpIfSmi(a1, &miss); |
- // Load the result and make sure it's not the hole. |
- __ Addu(a3, a2, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); |
- ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2); |
- __ sll(t1, a0, kPointerSizeLog2 - kSmiTagSize); |
- __ Addu(t1, t1, a3); |
- __ lw(t0, MemOperand(t1)); |
- __ LoadRoot(t1, Heap::kTheHoleValueRootIndex); |
- __ Branch(&miss, eq, t0, Operand(t1)); |
- __ mov(v0, t0); |
- __ Ret(); |
+ int receiver_count = receiver_maps->length(); |
+ __ lw(a2, FieldMemOperand(a1, HeapObject::kMapOffset)); |
+ for (int current = 0; current < receiver_count; ++current) { |
+ Handle<Map> map(receiver_maps->at(current)); |
+ Handle<Code> code(handler_ics->at(current)); |
+ __ Jump(code, RelocInfo::CODE_TARGET, eq, a2, Operand(map)); |
+ } |
__ bind(&miss); |
- GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
+ Handle<Code> miss_ic = isolate()->builtins()->KeyedLoadIC_Miss(); |
+ __ Jump(miss_ic, RelocInfo::CODE_TARGET); |
// Return the generated code. |
- return GetCode(NORMAL, NULL); |
+ return GetCode(NORMAL, NULL, MEGAMORPHIC); |
} |
@@ -3150,67 +3161,61 @@ MaybeObject* KeyedStoreStubCompiler::CompileStoreField(JSObject* object, |
} |
-MaybeObject* KeyedStoreStubCompiler::CompileStoreSpecialized( |
- JSObject* receiver) { |
+MaybeObject* KeyedStoreStubCompiler::CompileStoreFastElement( |
+ Map* receiver_map) { |
// ----------- S t a t e ------------- |
// -- a0 : value |
// -- a1 : key |
// -- a2 : receiver |
// -- ra : return address |
// -- a3 : scratch |
- // -- t0 : scratch (elements) |
// ----------------------------------- |
- Label miss; |
- Register value_reg = a0; |
- Register key_reg = a1; |
- Register receiver_reg = a2; |
- Register scratch = a3; |
- Register elements_reg = t0; |
- |
- // Check that the receiver isn't a smi. |
- __ JumpIfSmi(receiver_reg, &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(a2, |
+ a3, |
+ 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 map matches. |
- __ lw(scratch, FieldMemOperand(receiver_reg, HeapObject::kMapOffset)); |
- __ Branch(&miss, ne, scratch, Operand(Handle<Map>(receiver->map()))); |
+ // Return the generated code. |
+ return GetCode(NORMAL, NULL); |
+} |
- // Check that the key is a smi. |
- __ JumpIfNotSmi(key_reg, &miss); |
- // Get the elements array and make sure it is a fast element array, not 'cow'. |
- __ lw(elements_reg, |
- FieldMemOperand(receiver_reg, JSObject::kElementsOffset)); |
- __ lw(scratch, FieldMemOperand(elements_reg, HeapObject::kMapOffset)); |
- __ Branch(&miss, ne, scratch, |
- Operand(Handle<Map>(FACTORY->fixed_array_map()))); |
- |
- // Check that the key is within bounds. |
- if (receiver->IsJSArray()) { |
- __ lw(scratch, FieldMemOperand(receiver_reg, JSArray::kLengthOffset)); |
- } else { |
- __ lw(scratch, FieldMemOperand(elements_reg, FixedArray::kLengthOffset)); |
+MaybeObject* KeyedStoreStubCompiler::CompileStoreMegamorphic( |
+ MapList* receiver_maps, |
+ CodeList* handler_ics) { |
+ // ----------- S t a t e ------------- |
+ // -- a0 : value |
+ // -- a1 : key |
+ // -- a2 : receiver |
+ // -- ra : return address |
+ // -- a3 : scratch |
+ // ----------------------------------- |
+ Label miss; |
+ __ JumpIfSmi(a2, &miss); |
+ |
+ int receiver_count = receiver_maps->length(); |
+ __ lw(a3, FieldMemOperand(a2, HeapObject::kMapOffset)); |
+ for (int current = 0; current < receiver_count; ++current) { |
+ Handle<Map> map(receiver_maps->at(current)); |
+ Handle<Code> code(handler_ics->at(current)); |
+ __ Jump(code, RelocInfo::CODE_TARGET, eq, a3, Operand(map)); |
} |
- // Compare smis. |
- __ Branch(&miss, hs, key_reg, Operand(scratch)); |
- __ Addu(scratch, |
- elements_reg, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); |
- ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2); |
- __ sll(key_reg, key_reg, kPointerSizeLog2 - kSmiTagSize); |
- __ Addu(v0, scratch, key_reg); |
- __ sw(value_reg, MemOperand(v0)); |
- __ RecordWrite(scratch, Operand(key_reg), receiver_reg , elements_reg); |
- |
- // value_reg (a0) is preserved. |
- // Done. |
- __ mov(v0, value_reg); |
- __ 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); |
// Return the generated code. |
- return GetCode(NORMAL, NULL); |
+ return GetCode(NORMAL, NULL, MEGAMORPHIC); |
} |
@@ -3364,6 +3369,60 @@ MaybeObject* ConstructStubCompiler::CompileConstructStub(JSFunction* function) { |
} |
+MaybeObject* ExternalArrayLoadStubCompiler::CompileLoad( |
+ JSObject*receiver, ExternalArrayType array_type) { |
+ // ----------- S t a t e ------------- |
+ // -- ra : return address |
+ // -- a0 : key |
+ // -- a1 : receiver |
+ // ----------------------------------- |
+ MaybeObject* maybe_stub = |
+ KeyedLoadExternalArrayStub(array_type).TryGetCode(); |
+ Code* stub; |
+ if (!maybe_stub->To(&stub)) return maybe_stub; |
+ __ DispatchMap(a1, |
+ a2, |
+ 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 ------------- |
+ // -- a0 : value |
+ // -- a1 : name |
+ // -- a2 : receiver |
+ // -- ra : return address |
+ // ----------------------------------- |
+ MaybeObject* maybe_stub = |
+ KeyedStoreExternalArrayStub(array_type).TryGetCode(); |
+ Code* stub; |
+ if (!maybe_stub->To(&stub)) return maybe_stub; |
+ __ DispatchMap(a2, |
+ a3, |
+ 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: |
@@ -3383,29 +3442,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 -------------- |
// -- ra : return address |
// -- a0 : key |
// -- a1 : receiver |
// ----------------------------------- |
- Label slow, failed_allocation; |
+ Label miss_force_generic, slow, failed_allocation; |
Register key = a0; |
Register receiver = a1; |
- // 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. |
- __ lw(a2, FieldMemOperand(receiver, HeapObject::kMapOffset)); |
- __ Branch(&slow, ne, a2, Operand(Handle<Map>(receiver_object->map()))); |
+ __ JumpIfNotSmi(key, &miss_force_generic); |
__ lw(a3, FieldMemOperand(receiver, JSObject::kElementsOffset)); |
// a3: elements array |
@@ -3414,8 +3468,7 @@ MaybeObject* ExternalArrayStubCompiler::CompileKeyedLoadStub( |
__ lw(t1, FieldMemOperand(a3, ExternalArray::kLengthOffset)); |
__ sra(t2, key, kSmiTagSize); |
// Unsigned comparison catches both negative and too-large values. |
- __ Branch(&slow, Uless, t1, Operand(t2)); |
- |
+ __ Branch(&miss_force_generic, Uless, t1, Operand(t2)); |
__ lw(a3, FieldMemOperand(a3, ExternalArray::kExternalPointerOffset)); |
// a3: base pointer of external storage |
@@ -3565,12 +3618,12 @@ MaybeObject* ExternalArrayStubCompiler::CompileKeyedLoadStub( |
__ bind(&box_int_0); |
// Integer does not have leading zeros. |
- GenerateUInt2Double(masm(), hiword, loword, t0, 0); |
+ GenerateUInt2Double(masm, hiword, loword, t0, 0); |
__ Branch(&done); |
__ bind(&box_int_1); |
// Integer has one leading zero. |
- GenerateUInt2Double(masm(), hiword, loword, t0, 1); |
+ GenerateUInt2Double(masm, hiword, loword, t0, 1); |
__ bind(&done); |
@@ -3686,7 +3739,7 @@ MaybeObject* ExternalArrayStubCompiler::CompileKeyedLoadStub( |
// Slow case, key and receiver still in a0 and a1. |
__ bind(&slow); |
__ IncrementCounter( |
- masm()->isolate()->counters()->keyed_load_external_array_slow(), |
+ masm->isolate()->counters()->keyed_load_external_array_slow(), |
1, a2, a3); |
// ---------- S t a t e -------------- |
@@ -3699,16 +3752,16 @@ 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 -------------- |
// -- a0 : value |
// -- a1 : key |
@@ -3716,7 +3769,7 @@ MaybeObject* ExternalArrayStubCompiler::CompileKeyedStoreStub( |
// -- ra : return address |
// ----------------------------------- |
- Label slow, check_heap_number; |
+ Label slow, check_heap_number, miss_force_generic; |
// Register usage. |
Register value = a0; |
@@ -3724,23 +3777,19 @@ MaybeObject* ExternalArrayStubCompiler::CompileKeyedStoreStub( |
Register receiver = a2; |
// a3 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. |
- __ lw(a3, FieldMemOperand(receiver, HeapObject::kMapOffset)); |
- __ Branch(&slow, ne, a3, Operand(Handle<Map>(receiver_object->map()))); |
+ // This stub is meant to be tail-jumped to, the receiver must already |
+ // have been verified by the caller to not be a smi. |
__ lw(a3, 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(t0, key); |
__ lw(t1, FieldMemOperand(a3, ExternalArray::kLengthOffset)); |
// Unsigned comparison catches both negative and too-large values. |
- __ Branch(&slow, Ugreater_equal, t0, Operand(t1)); |
+ __ Branch(&miss_force_generic, Ugreater_equal, t0, Operand(t1)); |
// Handle both smis and HeapNumbers in the fast path. Go to the |
// runtime for all other kinds of values. |
@@ -3797,7 +3846,7 @@ MaybeObject* ExternalArrayStubCompiler::CompileKeyedStoreStub( |
break; |
case kExternalFloatArray: |
// Perform int-to-float conversion and store to memory. |
- StoreIntAsFloat(masm(), a3, t0, t1, t2, t3, t4); |
+ StoreIntAsFloat(masm, a3, t0, t1, t2, t3, t4); |
break; |
case kExternalDoubleArray: |
__ sll(t8, t0, 3); |
@@ -3810,7 +3859,7 @@ MaybeObject* ExternalArrayStubCompiler::CompileKeyedStoreStub( |
destination = FloatingPointHelper::kCoreRegisters; |
} |
FloatingPointHelper::ConvertIntToDouble( |
- masm(), t1, destination, |
+ masm, t1, destination, |
f0, t2, t3, // These are: double_dst, dst1, dst2. |
t0, f2); // These are: scratch2, single_scratch. |
if (destination == FloatingPointHelper::kFPURegisters) { |
@@ -4072,27 +4121,136 @@ MaybeObject* ExternalArrayStubCompiler::CompileKeyedStoreStub( |
} |
} |
- // Slow case: call runtime. |
+ // Slow case, key and receiver still in a0 and a1. |
__ bind(&slow); |
+ __ IncrementCounter( |
+ masm->isolate()->counters()->keyed_load_external_array_slow(), |
+ 1, a2, a3); |
// Entry registers are intact. |
// ---------- S t a t e -------------- |
- // -- a0 : value |
- // -- a1 : key |
- // -- a2 : receiver |
// -- ra : return address |
+ // -- a0 : key |
+ // -- a1 : 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(a2, a1, a0); |
+ // Miss case, call the runtime. |
+ __ bind(&miss_force_generic); |
- __ li(a1, Operand(Smi::FromInt(NONE))); // PropertyAttributes. |
- __ li(a0, Operand(Smi::FromInt( |
- Code::ExtractExtraICStateFromFlags(flags) & kStrictMode))); |
- __ Push(a1, a0); |
+ // ---------- S t a t e -------------- |
+ // -- ra : return address |
+ // -- a0 : key |
+ // -- a1 : 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 ------------- |
+ // -- ra : return address |
+ // -- a0 : key |
+ // -- a1 : receiver |
+ // ----------------------------------- |
+ Label miss_force_generic; |
+ |
+ // 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(a0, &miss_force_generic); |
+ |
+ // Get the elements array. |
+ __ lw(a2, FieldMemOperand(a1, JSObject::kElementsOffset)); |
+ __ AssertFastElements(a2); |
+ |
+ // Check that the key is within bounds. |
+ __ lw(a3, FieldMemOperand(a2, FixedArray::kLengthOffset)); |
+ __ Branch(&miss_force_generic, hs, a0, Operand(a3)); |
+ |
+ // Load the result and make sure it's not the hole. |
+ __ Addu(a3, a2, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); |
+ ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2); |
+ __ sll(t0, a0, kPointerSizeLog2 - kSmiTagSize); |
+ __ Addu(t0, t0, a3); |
+ __ lw(t0, MemOperand(t0)); |
+ __ LoadRoot(t1, Heap::kTheHoleValueRootIndex); |
+ __ Branch(&miss_force_generic, eq, t0, Operand(t1)); |
+ __ mov(v0, t0); |
+ __ 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 ------------- |
+ // -- a0 : value |
+ // -- a1 : key |
+ // -- a2 : receiver |
+ // -- ra : return address |
+ // -- a3 : scratch |
+ // -- a4 : scratch (elements) |
+ // ----------------------------------- |
+ Label miss_force_generic; |
- __ TailCallRuntime(Runtime::kSetProperty, 5, 1); |
+ Register value_reg = a0; |
+ Register key_reg = a1; |
+ Register receiver_reg = a2; |
+ Register scratch = a3; |
+ Register elements_reg = t0; |
+ Register scratch2 = t1; |
+ Register scratch3 = t2; |
- return GetCode(flags); |
+ // 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(a0, &miss_force_generic); |
+ |
+ // Get the elements array and make sure it is a fast element array, not 'cow'. |
+ __ lw(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) { |
+ __ lw(scratch, FieldMemOperand(receiver_reg, JSArray::kLengthOffset)); |
+ } else { |
+ __ lw(scratch, FieldMemOperand(elements_reg, FixedArray::kLengthOffset)); |
+ } |
+ // Compare smis. |
+ __ Branch(&miss_force_generic, hs, key_reg, Operand(scratch)); |
+ |
+ __ Addu(scratch, |
+ elements_reg, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); |
+ ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2); |
+ __ sll(scratch2, key_reg, kPointerSizeLog2 - kSmiTagSize); |
+ __ Addu(scratch3, scratch2, scratch); |
+ __ sw(value_reg, MemOperand(scratch3)); |
+ __ RecordWrite(scratch, Operand(scratch2), receiver_reg , elements_reg); |
+ |
+ // value_reg (a0) is preserved. |
+ // Done. |
+ __ Ret(); |
+ |
+ __ bind(&miss_force_generic); |
+ Handle<Code> ic = |
+ masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); |
+ __ Jump(ic, RelocInfo::CODE_TARGET); |
} |