| 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
|
|
|