Index: src/ia32/ic-ia32.cc |
=================================================================== |
--- src/ia32/ic-ia32.cc (revision 9531) |
+++ src/ia32/ic-ia32.cc (working copy) |
@@ -212,7 +212,7 @@ |
// Update write barrier. Make sure not to clobber the value. |
__ mov(r1, value); |
- __ RecordWrite(elements, r0, r1); |
+ __ RecordWrite(elements, r0, r1, kDontSaveFPRegs); |
} |
@@ -326,7 +326,7 @@ |
// Fast case: Do the load. |
STATIC_ASSERT((kPointerSize == 4) && (kSmiTagSize == 1) && (kSmiTag == 0)); |
__ mov(scratch, FieldOperand(scratch, key, times_2, FixedArray::kHeaderSize)); |
- __ cmp(Operand(scratch), Immediate(FACTORY->the_hole_value())); |
+ __ cmp(scratch, Immediate(FACTORY->the_hole_value())); |
// In case the loaded value is the_hole we have to consult GetProperty |
// to ensure the prototype chain is searched. |
__ j(equal, out_of_range); |
@@ -394,8 +394,8 @@ |
// Check if element is in the range of mapped arguments. If not, jump |
// to the unmapped lookup with the parameter map in scratch1. |
__ mov(scratch2, FieldOperand(scratch1, FixedArray::kLengthOffset)); |
- __ sub(Operand(scratch2), Immediate(Smi::FromInt(2))); |
- __ cmp(key, Operand(scratch2)); |
+ __ sub(scratch2, Immediate(Smi::FromInt(2))); |
+ __ cmp(key, scratch2); |
__ j(greater_equal, unmapped_case); |
// Load element index and check whether it is the hole. |
@@ -432,7 +432,7 @@ |
Handle<Map> fixed_array_map(masm->isolate()->heap()->fixed_array_map()); |
__ CheckMap(backing_store, fixed_array_map, slow_case, DONT_DO_SMI_CHECK); |
__ mov(scratch, FieldOperand(backing_store, FixedArray::kLengthOffset)); |
- __ cmp(key, Operand(scratch)); |
+ __ cmp(key, scratch); |
__ j(greater_equal, slow_case); |
return FieldOperand(backing_store, |
key, |
@@ -534,7 +534,7 @@ |
__ shr(ecx, KeyedLookupCache::kMapHashShift); |
__ mov(edi, FieldOperand(eax, String::kHashFieldOffset)); |
__ shr(edi, String::kHashShift); |
- __ xor_(ecx, Operand(edi)); |
+ __ xor_(ecx, edi); |
__ and_(ecx, KeyedLookupCache::kCapacityMask); |
// Load the key (consisting of map and symbol) from the cache and |
@@ -545,7 +545,7 @@ |
__ shl(edi, kPointerSizeLog2 + 1); |
__ cmp(ebx, Operand::StaticArray(edi, times_1, cache_keys)); |
__ j(not_equal, &slow); |
- __ add(Operand(edi), Immediate(kPointerSize)); |
+ __ add(edi, Immediate(kPointerSize)); |
__ cmp(eax, Operand::StaticArray(edi, times_1, cache_keys)); |
__ j(not_equal, &slow); |
@@ -559,12 +559,12 @@ |
__ mov(edi, |
Operand::StaticArray(ecx, times_pointer_size, cache_field_offsets)); |
__ movzx_b(ecx, FieldOperand(ebx, Map::kInObjectPropertiesOffset)); |
- __ sub(edi, Operand(ecx)); |
+ __ sub(edi, ecx); |
__ j(above_equal, &property_array_property); |
// Load in-object property. |
__ movzx_b(ecx, FieldOperand(ebx, Map::kInstanceSizeOffset)); |
- __ add(ecx, Operand(edi)); |
+ __ add(ecx, edi); |
__ mov(eax, FieldOperand(edx, ecx, times_pointer_size, 0)); |
__ IncrementCounter(counters->keyed_load_generic_lookup_cache(), 1); |
__ ret(0); |
@@ -651,8 +651,8 @@ |
// Check that it has indexed interceptor and access checks |
// are not enabled for this object. |
__ movzx_b(ecx, FieldOperand(ecx, Map::kBitFieldOffset)); |
- __ and_(Operand(ecx), Immediate(kSlowCaseBitFieldMask)); |
- __ cmp(Operand(ecx), Immediate(1 << Map::kHasIndexedInterceptor)); |
+ __ and_(ecx, Immediate(kSlowCaseBitFieldMask)); |
+ __ cmp(ecx, Immediate(1 << Map::kHasIndexedInterceptor)); |
__ j(not_zero, &slow); |
// Everything is fine, call runtime. |
@@ -710,7 +710,7 @@ |
__ mov(mapped_location, eax); |
__ lea(ecx, mapped_location); |
__ mov(edx, eax); |
- __ RecordWrite(ebx, ecx, edx); |
+ __ RecordWrite(ebx, ecx, edx, kDontSaveFPRegs); |
__ Ret(); |
__ bind(¬in); |
// The unmapped lookup expects that the parameter map is in ebx. |
@@ -719,7 +719,7 @@ |
__ mov(unmapped_location, eax); |
__ lea(edi, unmapped_location); |
__ mov(edx, eax); |
- __ RecordWrite(ebx, edi, edx); |
+ __ RecordWrite(ebx, edi, edx, kDontSaveFPRegs); |
__ Ret(); |
__ bind(&slow); |
GenerateMiss(masm, false); |
@@ -734,7 +734,9 @@ |
// -- edx : receiver |
// -- esp[0] : return address |
// ----------------------------------- |
- Label slow, fast, array, extra; |
+ Label slow, fast_object_with_map_check, fast_object_without_map_check; |
+ Label fast_double_with_map_check, fast_double_without_map_check; |
+ Label check_if_double_array, array, extra; |
// Check that the object isn't a smi. |
__ JumpIfSmi(edx, &slow); |
@@ -750,22 +752,18 @@ |
__ CmpInstanceType(edi, JS_ARRAY_TYPE); |
__ j(equal, &array); |
// Check that the object is some kind of JSObject. |
- __ CmpInstanceType(edi, FIRST_JS_RECEIVER_TYPE); |
+ __ CmpInstanceType(edi, FIRST_JS_OBJECT_TYPE); |
__ j(below, &slow); |
- __ CmpInstanceType(edi, JS_PROXY_TYPE); |
- __ j(equal, &slow); |
- __ CmpInstanceType(edi, JS_FUNCTION_PROXY_TYPE); |
- __ j(equal, &slow); |
// Object case: Check key against length in the elements array. |
// eax: value |
// edx: JSObject |
// ecx: key (a smi) |
- __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); |
- // Check that the object is in fast mode and writable. |
- __ CheckMap(edi, FACTORY->fixed_array_map(), &slow, DONT_DO_SMI_CHECK); |
- __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset)); |
- __ j(below, &fast); |
+ // edi: receiver map |
+ __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset)); |
+ // Check array bounds. Both the key and the length of FixedArray are smis. |
+ __ cmp(ecx, FieldOperand(ebx, FixedArray::kLengthOffset)); |
+ __ j(below, &fast_object_with_map_check); |
// Slow case: call runtime. |
__ bind(&slow); |
@@ -778,17 +776,29 @@ |
// eax: value |
// edx: receiver, a JSArray |
// ecx: key, a smi. |
- // edi: receiver->elements, a FixedArray |
+ // ebx: receiver->elements, a FixedArray |
+ // edi: receiver map |
// flags: compare (ecx, edx.length()) |
// do not leave holes in the array: |
__ j(not_equal, &slow); |
- __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset)); |
+ __ cmp(ecx, FieldOperand(ebx, FixedArray::kLengthOffset)); |
__ j(above_equal, &slow); |
- // Add 1 to receiver->length, and go to fast array write. |
+ __ mov(edi, FieldOperand(ebx, HeapObject::kMapOffset)); |
+ __ cmp(edi, masm->isolate()->factory()->fixed_array_map()); |
+ __ j(not_equal, &check_if_double_array); |
+ // Add 1 to receiver->length, and go to common element store code for Objects. |
__ add(FieldOperand(edx, JSArray::kLengthOffset), |
Immediate(Smi::FromInt(1))); |
- __ jmp(&fast); |
+ __ jmp(&fast_object_without_map_check); |
+ __ bind(&check_if_double_array); |
+ __ cmp(edi, masm->isolate()->factory()->fixed_double_array_map()); |
+ __ j(not_equal, &slow); |
+ // Add 1 to receiver->length, and go to common element store code for doubles. |
+ __ add(FieldOperand(edx, JSArray::kLengthOffset), |
+ Immediate(Smi::FromInt(1))); |
+ __ jmp(&fast_double_without_map_check); |
+ |
// Array case: Get the length and the elements array from the JS |
// array. Check that the array is in fast mode (and writable); if it |
// is the length is always a smi. |
@@ -796,25 +806,57 @@ |
// eax: value |
// edx: receiver, a JSArray |
// ecx: key, a smi. |
- __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); |
- __ CheckMap(edi, FACTORY->fixed_array_map(), &slow, DONT_DO_SMI_CHECK); |
+ // edi: receiver map |
+ __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset)); |
- // Check the key against the length in the array, compute the |
- // address to store into and fall through to fast case. |
+ // Check the key against the length in the array and fall through to the |
+ // common store code. |
__ cmp(ecx, FieldOperand(edx, JSArray::kLengthOffset)); // Compare smis. |
__ j(above_equal, &extra); |
- // Fast case: Do the store. |
- __ bind(&fast); |
+ // Fast case: Do the store, could either Object or double. |
+ __ bind(&fast_object_with_map_check); |
// eax: value |
// ecx: key (a smi) |
// edx: receiver |
- // edi: FixedArray receiver->elements |
- __ mov(CodeGenerator::FixedArrayElementOperand(edi, ecx), eax); |
+ // ebx: FixedArray receiver->elements |
+ // edi: receiver map |
+ __ mov(edi, FieldOperand(ebx, HeapObject::kMapOffset)); |
+ __ cmp(edi, masm->isolate()->factory()->fixed_array_map()); |
+ __ j(not_equal, &fast_double_with_map_check); |
+ __ bind(&fast_object_without_map_check); |
+ // Smi stores don't require further checks. |
+ Label non_smi_value; |
+ __ JumpIfNotSmi(eax, &non_smi_value); |
+ // It's irrelevant whether array is smi-only or not when writing a smi. |
+ __ mov(CodeGenerator::FixedArrayElementOperand(ebx, ecx), eax); |
+ __ ret(0); |
+ |
+ __ bind(&non_smi_value); |
+ if (FLAG_smi_only_arrays) { |
+ // Escape to slow case when writing non-smi into smi-only array. |
+ __ mov(edi, FieldOperand(edx, HeapObject::kMapOffset)); |
+ __ CheckFastObjectElements(edi, &slow, Label::kNear); |
+ } |
+ |
+ // Fast elements array, store the value to the elements backing store. |
+ __ mov(CodeGenerator::FixedArrayElementOperand(ebx, ecx), eax); |
// Update write barrier for the elements array address. |
- __ mov(edx, Operand(eax)); |
- __ RecordWrite(edi, 0, edx, ecx); |
+ __ mov(edx, eax); // Preserve the value which is returned. |
+ __ RecordWriteArray( |
+ ebx, edx, ecx, kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); |
__ ret(0); |
+ |
+ __ bind(&fast_double_with_map_check); |
+ // Check for fast double array case. If this fails, call through to the |
+ // runtime. |
+ __ cmp(edi, masm->isolate()->factory()->fixed_double_array_map()); |
+ __ j(not_equal, &slow); |
+ __ bind(&fast_double_without_map_check); |
+ // If the value is a number, store it as a double in the FastDoubleElements |
+ // array. |
+ __ StoreNumberToDoubleElements(eax, ebx, ecx, edx, xmm0, &slow, false); |
+ __ ret(0); |
} |
@@ -951,22 +993,22 @@ |
// Get the receiver of the function from the stack; 1 ~ return address. |
__ mov(edx, Operand(esp, (argc + 1) * kPointerSize)); |
- // Enter an internal frame. |
- __ EnterInternalFrame(); |
+ { |
+ FrameScope scope(masm, StackFrame::INTERNAL); |
- // Push the receiver and the name of the function. |
- __ push(edx); |
- __ push(ecx); |
+ // Push the receiver and the name of the function. |
+ __ push(edx); |
+ __ push(ecx); |
- // Call the entry. |
- CEntryStub stub(1); |
- __ mov(eax, Immediate(2)); |
- __ mov(ebx, Immediate(ExternalReference(IC_Utility(id), masm->isolate()))); |
- __ CallStub(&stub); |
+ // Call the entry. |
+ CEntryStub stub(1); |
+ __ mov(eax, Immediate(2)); |
+ __ mov(ebx, Immediate(ExternalReference(IC_Utility(id), masm->isolate()))); |
+ __ CallStub(&stub); |
- // Move result to edi and exit the internal frame. |
- __ mov(edi, eax); |
- __ LeaveInternalFrame(); |
+ // Move result to edi and exit the internal frame. |
+ __ mov(edi, eax); |
+ } |
// Check if the receiver is a global object of some sort. |
// This can happen only for regular CallIC but not KeyedCallIC. |
@@ -1111,13 +1153,17 @@ |
// This branch is taken when calling KeyedCallIC_Miss is neither required |
// nor beneficial. |
__ IncrementCounter(counters->keyed_call_generic_slow_load(), 1); |
- __ EnterInternalFrame(); |
- __ push(ecx); // save the key |
- __ push(edx); // pass the receiver |
- __ push(ecx); // pass the key |
- __ CallRuntime(Runtime::kKeyedGetProperty, 2); |
- __ pop(ecx); // restore the key |
- __ LeaveInternalFrame(); |
+ |
+ { |
+ FrameScope scope(masm, StackFrame::INTERNAL); |
+ __ push(ecx); // save the key |
+ __ push(edx); // pass the receiver |
+ __ push(ecx); // pass the key |
+ __ CallRuntime(Runtime::kKeyedGetProperty, 2); |
+ __ pop(ecx); // restore the key |
+ // Leave the internal frame. |
+ } |
+ |
__ mov(edi, eax); |
__ jmp(&do_call); |