Index: src/ia32/stub-cache-ia32.cc |
diff --git a/src/ia32/stub-cache-ia32.cc b/src/ia32/stub-cache-ia32.cc |
index 127d16aab475c3e61bb89b5f14720f3d49d5ba33..28a39946df8978f1adbaf543d0d40f1c3ed655b7 100644 |
--- a/src/ia32/stub-cache-ia32.cc |
+++ b/src/ia32/stub-cache-ia32.cc |
@@ -1523,7 +1523,7 @@ Handle<Code> CallStubCompiler::CompileArrayPushCall( |
Label call_builtin; |
if (argc == 1) { // Otherwise fall through to call builtin. |
- Label attempt_to_grow_elements, with_write_barrier; |
+ Label attempt_to_grow_elements, with_write_barrier, check_double; |
// Get the elements array of the object. |
__ mov(edi, FieldOperand(edx, JSArray::kElementsOffset)); |
@@ -1531,7 +1531,7 @@ Handle<Code> CallStubCompiler::CompileArrayPushCall( |
// Check that the elements are in fast mode and writable. |
__ cmp(FieldOperand(edi, HeapObject::kMapOffset), |
Immediate(factory()->fixed_array_map())); |
- __ j(not_equal, &call_builtin); |
+ __ j(not_equal, &check_double); |
// Get the array's length into eax and calculate new length. |
__ mov(eax, FieldOperand(edx, JSArray::kLengthOffset)); |
@@ -1562,17 +1562,49 @@ Handle<Code> CallStubCompiler::CompileArrayPushCall( |
__ ret((argc + 1) * kPointerSize); |
+ __ bind(&check_double); |
+ |
+ |
+ // Check that the elements are in double mode. |
+ __ cmp(FieldOperand(edi, HeapObject::kMapOffset), |
+ Immediate(factory()->fixed_double_array_map())); |
+ __ j(not_equal, &call_builtin); |
+ |
+ // Get the array's length into eax and calculate new length. |
+ __ mov(eax, FieldOperand(edx, JSArray::kLengthOffset)); |
+ STATIC_ASSERT(kSmiTagSize == 1); |
+ STATIC_ASSERT(kSmiTag == 0); |
+ __ add(eax, Immediate(Smi::FromInt(argc))); |
+ |
+ // Get the elements' length into ecx. |
+ __ mov(ecx, FieldOperand(edi, FixedArray::kLengthOffset)); |
+ |
+ // Check if we could survive without allocation. |
+ __ cmp(eax, ecx); |
+ __ j(greater, &call_builtin); |
+ |
+ __ mov(ecx, Operand(esp, argc * kPointerSize)); |
+ __ StoreNumberToDoubleElements( |
+ ecx, edi, eax, ecx, xmm0, &call_builtin, true, argc * kDoubleSize); |
+ |
+ // Save new length. |
+ __ mov(FieldOperand(edx, JSArray::kLengthOffset), eax); |
+ __ ret((argc + 1) * kPointerSize); |
+ |
__ bind(&with_write_barrier); |
__ mov(ebx, FieldOperand(edx, HeapObject::kMapOffset)); |
- if (FLAG_smi_only_arrays && !FLAG_trace_elements_transitions) { |
+ if (FLAG_smi_only_arrays && !FLAG_trace_elements_transitions) { |
Label fast_object, not_fast_object; |
__ CheckFastObjectElements(ebx, ¬_fast_object, Label::kNear); |
__ jmp(&fast_object); |
// In case of fast smi-only, convert to fast object, otherwise bail out. |
__ bind(¬_fast_object); |
__ CheckFastSmiElements(ebx, &call_builtin); |
+ __ cmp(FieldOperand(ecx, HeapObject::kMapOffset), |
+ Immediate(factory()->heap_number_map())); |
+ __ j(equal, &call_builtin); |
// edi: elements array |
// edx: receiver |
// ebx: map |