Index: src/arm/builtins-arm.cc |
diff --git a/src/arm/builtins-arm.cc b/src/arm/builtins-arm.cc |
index 50b6bce30b7dddc4caeec098dd1e38464839d610..993addca9ee44263ebe6b1f5bdc246aa9a4d05b9 100644 |
--- a/src/arm/builtins-arm.cc |
+++ b/src/arm/builtins-arm.cc |
@@ -313,7 +313,7 @@ static void ArrayNativeCode(MacroAssembler* masm, |
Label* call_generic_code) { |
Counters* counters = masm->isolate()->counters(); |
Label argc_one_or_more, argc_two_or_more, not_empty_array, empty_array, |
- has_non_smi_element; |
+ has_non_smi_element, finish, cant_transition_map, not_double; |
// Check for array construction with zero arguments or one. |
__ cmp(r0, Operand(0, RelocInfo::NONE)); |
@@ -418,6 +418,8 @@ static void ArrayNativeCode(MacroAssembler* masm, |
__ bind(&entry); |
__ cmp(r4, r5); |
__ b(lt, &loop); |
+ |
+ __ bind(&finish); |
__ mov(sp, r7); |
// Remove caller arguments and receiver from the stack, setup return value and |
@@ -430,8 +432,39 @@ static void ArrayNativeCode(MacroAssembler* masm, |
__ Jump(lr); |
__ bind(&has_non_smi_element); |
+ // Double values are handled by the runtime. |
+ __ CheckMap( |
+ r2, r9, Heap::kHeapNumberMapRootIndex, ¬_double, DONT_DO_SMI_CHECK); |
+ __ bind(&cant_transition_map); |
__ UndoAllocationInNewSpace(r3, r4); |
__ b(call_generic_code); |
+ |
+ __ bind(¬_double); |
+ // Transition FAST_SMI_ONLY_ELEMENTS to FAST_ELEMENTS. |
+ // r3: JSArray |
+ __ ldr(r2, FieldMemOperand(r3, HeapObject::kMapOffset)); |
+ __ LoadTransitionedArrayMapConditional(FAST_SMI_ONLY_ELEMENTS, |
+ FAST_ELEMENTS, |
+ r2, |
+ r9, |
+ &cant_transition_map); |
+ __ str(r2, FieldMemOperand(r3, HeapObject::kMapOffset)); |
+ __ RecordWriteField(r3, |
+ HeapObject::kMapOffset, |
+ r2, |
+ r9, |
+ kLRHasNotBeenSaved, |
+ kDontSaveFPRegs, |
+ EMIT_REMEMBERED_SET, |
+ OMIT_SMI_CHECK); |
+ Label loop2; |
+ __ sub(r7, r7, Operand(kPointerSize)); |
+ __ bind(&loop2); |
+ __ ldr(r2, MemOperand(r7, kPointerSize, PostIndex)); |
+ __ str(r2, MemOperand(r5, -kPointerSize, PreIndex)); |
+ __ cmp(r4, r5); |
+ __ b(lt, &loop2); |
+ __ b(&finish); |
} |