ARM: Implement runtime function for array literal transitions.
authordanno@chromium.org <danno@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 11 Nov 2011 14:49:16 +0000 (14:49 +0000)
committerdanno@chromium.org <danno@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 11 Nov 2011 14:49:16 +0000 (14:49 +0000)
Also simplify ia32 and x64 handing of the trace_elements_transition flag.

R=jkummerow@chromium.org
BUG=none
TEST=array-literal-transitions.js

Review URL: http://codereview.chromium.org/8539011

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@9979 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/arm/code-stubs-arm.cc
src/arm/full-codegen-arm.cc
src/builtins.cc
src/ia32/code-stubs-ia32.cc
src/objects-inl.h
src/objects.cc
src/objects.h
src/x64/code-stubs-x64.cc

index bd3d2e6..b37855b 100644 (file)
@@ -6888,6 +6888,8 @@ struct AheadOfTimeWriteBarrierStubList kAheadOfTime[] = {
   // ElementsTransitionGenerator::GenerateDoubleToObject
   { r6, r2, r0, EMIT_REMEMBERED_SET },
   { r2, r6, r9, EMIT_REMEMBERED_SET },
+  // StoreArrayLiteralElementStub::Generate
+  { r5, r0, r6, EMIT_REMEMBERED_SET },
   // Null termination.
   { no_reg, no_reg, no_reg, EMIT_REMEMBERED_SET}
 };
@@ -7124,6 +7126,64 @@ void RecordWriteStub::CheckNeedsToInformIncrementalMarker(
   // Fall through when we need to inform the incremental marker.
 }
 
+
+void StoreArrayLiteralElementStub::Generate(MacroAssembler* masm) {
+  // ----------- S t a t e -------------
+  //  -- r0    : element value to store
+  //  -- r1    : array literal
+  //  -- r2    : map of array literal
+  //  -- r3    : element index as smi
+  //  -- r4    : array literal index in function as smi
+  // -----------------------------------
+
+  Label element_done;
+  Label double_elements;
+  Label smi_element;
+  Label slow_elements;
+  Label fast_elements;
+
+  __ CheckFastElements(r2, r5, &double_elements);
+  // FAST_SMI_ONLY_ELEMENTS or FAST_ELEMENTS
+  __ JumpIfSmi(r0, &smi_element);
+  __ CheckFastSmiOnlyElements(r2, r5, &fast_elements);
+
+  // Store into the array literal requires a elements transition. Call into
+  // the runtime.
+  __ bind(&slow_elements);
+  // call.
+  __ Push(r1, r3, r0);
+  __ ldr(r5, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset));
+  __ ldr(r5, FieldMemOperand(r5, JSFunction::kLiteralsOffset));
+  __ Push(r5, r4);
+  __ TailCallRuntime(Runtime::kStoreArrayLiteralElement, 5, 1);
+
+  // Array literal has ElementsKind of FAST_ELEMENTS and value is an object.
+  __ bind(&fast_elements);
+  __ ldr(r5, FieldMemOperand(r1, JSObject::kElementsOffset));
+  __ add(r6, r5, Operand(r3, LSL, kPointerSizeLog2 - kSmiTagSize));
+  __ add(r6, r6, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
+  __ str(r0, MemOperand(r6, 0));
+  // Update the write barrier for the array store.
+  __ RecordWrite(r5, r6, r0, kLRHasNotBeenSaved, kDontSaveFPRegs,
+                 EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
+  __ Ret();
+
+  // Array literal has ElementsKind of FAST_SMI_ONLY_ELEMENTS or
+  // FAST_ELEMENTS, and value is Smi.
+  __ bind(&smi_element);
+  __ ldr(r5, FieldMemOperand(r1, JSObject::kElementsOffset));
+  __ add(r6, r5, Operand(r3, LSL, kPointerSizeLog2 - kSmiTagSize));
+  __ str(r0, FieldMemOperand(r6, FixedArray::kHeaderSize));
+  __ Ret();
+
+  // Array literal has ElementsKind of FAST_DOUBLE_ELEMENTS.
+  __ bind(&double_elements);
+  __ ldr(r5, FieldMemOperand(r1, JSObject::kElementsOffset));
+  __ StoreNumberToDoubleElements(r0, r3, r1, r5, r6, r7, r9, r10,
+                                 &slow_elements);
+  __ Ret();
+}
+
 #undef __
 
 } }  // namespace v8::internal
index 8decb19..e8a2cb0 100644 (file)
@@ -1580,56 +1580,12 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
     }
     VisitForAccumulatorValue(subexpr);
 
-    __ ldr(r6, MemOperand(sp));  // Copy of array literal.
-    __ ldr(r1, FieldMemOperand(r6, JSObject::kElementsOffset));
-    __ ldr(r2, FieldMemOperand(r6, JSObject::kMapOffset));
-    int offset = FixedArray::kHeaderSize + (i * kPointerSize);
-
-    Label element_done;
-    Label double_elements;
-    Label smi_element;
-    Label slow_elements;
-    Label fast_elements;
-    __ CheckFastElements(r2, r3, &double_elements);
-
-    // FAST_SMI_ONLY_ELEMENTS or FAST_ELEMENTS
-    __ JumpIfSmi(result_register(), &smi_element);
-    __ CheckFastSmiOnlyElements(r2, r3, &fast_elements);
-
-    // Store into the array literal requires a elements transition. Call into
-    // the runtime.
-    __ bind(&slow_elements);
-    __ push(r6);  // Copy of array literal.
-    __ mov(r1, Operand(Smi::FromInt(i)));
-    __ mov(r2, Operand(Smi::FromInt(NONE)));  // PropertyAttributes
-    __ mov(r3, Operand(Smi::FromInt(strict_mode_flag())));  // Strict mode.
-    __ Push(r1, result_register(), r2, r3);
-    __ CallRuntime(Runtime::kSetProperty, 5);
-    __ b(&element_done);
-
-      // Array literal has ElementsKind of FAST_DOUBLE_ELEMENTS.
-    __ bind(&double_elements);
+    __ ldr(r1, MemOperand(sp));  // Copy of array literal.
+    __ ldr(r2, FieldMemOperand(r1, JSObject::kMapOffset));
     __ mov(r3, Operand(Smi::FromInt(i)));
-    __ StoreNumberToDoubleElements(result_register(), r3, r6, r1, r4, r5, r9,
-                                   r7, &slow_elements);
-    __ b(&element_done);
-
-    // Array literal has ElementsKind of FAST_ELEMENTS and value is an object.
-    __ bind(&fast_elements);
-    __ str(result_register(), FieldMemOperand(r1, offset));
-    // Update the write barrier for the array store.
-    __ RecordWriteField(
-        r1, offset, result_register(), r2, kLRHasBeenSaved, kDontSaveFPRegs,
-        EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
-    __ b(&element_done);
-
-    // Array literal has ElementsKind of FAST_SMI_ONLY_ELEMENTS or
-    // FAST_ELEMENTS, and value is Smi.
-    __ bind(&smi_element);
-    __ str(result_register(), FieldMemOperand(r1, offset));
-    // Fall through
-
-    __ bind(&element_done);
+    __ mov(r4, Operand(Smi::FromInt(expr->literal_index())));
+    StoreArrayLiteralElementStub stub;
+    __ CallStub(&stub);
 
     PrepareForBailoutForId(expr->GetIdForElement(i), NO_REGISTERS);
   }
index 49053db..e542e4d 100644 (file)
@@ -775,7 +775,8 @@ BUILTIN(ArraySlice) {
 
   // Set the ElementsKind.
   ElementsKind elements_kind = JSObject::cast(receiver)->GetElementsKind();
-  if (result_array->GetElementsKind() != elements_kind) {
+  if (IsMoreGeneralElementsKindTransition(result_array->GetElementsKind(),
+                                          elements_kind)) {
     MaybeObject* maybe = result_array->TransitionElementsKind(elements_kind);
     if (maybe->IsFailure()) return maybe;
   }
@@ -875,7 +876,8 @@ BUILTIN(ArraySplice) {
 
     // Set the ElementsKind.
     ElementsKind elements_kind = array->GetElementsKind();
-    if (result_array->GetElementsKind() != elements_kind) {
+    if (IsMoreGeneralElementsKindTransition(result_array->GetElementsKind(),
+                                            elements_kind)) {
       MaybeObject* maybe = result_array->TransitionElementsKind(elements_kind);
       if (maybe->IsFailure()) return maybe;
     }
index 4d69bf8..23bea4f 100644 (file)
@@ -7046,16 +7046,14 @@ void StoreArrayLiteralElementStub::Generate(MacroAssembler* masm) {
   Label slow_elements_from_double;
   Label fast_elements;
 
-  if (!FLAG_trace_elements_transitions) {
-    __ CheckFastElements(edi, &double_elements);
+  __ CheckFastElements(edi, &double_elements);
 
-    // FAST_SMI_ONLY_ELEMENTS or FAST_ELEMENTS
-    __ JumpIfSmi(eax, &smi_element);
-    __ CheckFastSmiOnlyElements(edi, &fast_elements, Label::kNear);
+  // FAST_SMI_ONLY_ELEMENTS or FAST_ELEMENTS
+  __ JumpIfSmi(eax, &smi_element);
+  __ CheckFastSmiOnlyElements(edi, &fast_elements, Label::kNear);
 
-    // Store into the array literal requires a elements transition. Call into
-    // the runtime.
-  }
+  // Store into the array literal requires a elements transition. Call into
+  // the runtime.
 
   __ bind(&slow_elements);
   __ pop(edi);  // Pop return address and remember to put back later for tail
@@ -7070,49 +7068,45 @@ void StoreArrayLiteralElementStub::Generate(MacroAssembler* masm) {
                  // place.
   __ TailCallRuntime(Runtime::kStoreArrayLiteralElement, 5, 1);
 
-  if (!FLAG_trace_elements_transitions) {
-    // Array literal has ElementsKind of FAST_DOUBLE_ELEMENTS.
-    __ bind(&double_elements);
+  __ bind(&slow_elements_from_double);
+  __ pop(edx);
+  __ jmp(&slow_elements);
+
+  // Array literal has ElementsKind of FAST_ELEMENTS and value is an object.
+  __ bind(&fast_elements);
+  __ mov(ebx, FieldOperand(ebx, JSObject::kElementsOffset));
+  __ lea(ecx, FieldOperand(ebx, ecx, times_half_pointer_size,
+                           FixedArrayBase::kHeaderSize));
+  __ mov(Operand(ecx, 0), eax);
+  // Update the write barrier for the array store.
+  __ RecordWrite(ebx, ecx, eax,
+                 kDontSaveFPRegs,
+                 EMIT_REMEMBERED_SET,
+                 OMIT_SMI_CHECK);
+  __ ret(0);
 
-    __ push(edx);
-    __ mov(edx, FieldOperand(ebx, JSObject::kElementsOffset));
-    __ StoreNumberToDoubleElements(eax,
-                                   edx,
-                                   ecx,
-                                   edi,
-                                   xmm0,
-                                   &slow_elements_from_double,
-                                   false);
-    __ pop(edx);
-    __ jmp(&element_done);
+  // Array literal has ElementsKind of FAST_SMI_ONLY_ELEMENTS or
+  // FAST_ELEMENTS, and value is Smi.
+  __ bind(&smi_element);
+  __ mov(ebx, FieldOperand(ebx, JSObject::kElementsOffset));
+  __ mov(FieldOperand(ebx, ecx, times_half_pointer_size,
+                      FixedArrayBase::kHeaderSize), eax);
+  __ ret(0);
 
-    __ bind(&slow_elements_from_double);
-    __ pop(edx);
-    __ jmp(&slow_elements);
-
-    // Array literal has ElementsKind of FAST_ELEMENTS and value is an object.
-    __ bind(&fast_elements);
-    __ mov(ebx, FieldOperand(ebx, JSObject::kElementsOffset));
-    __ lea(ecx, FieldOperand(ebx, ecx, times_half_pointer_size,
-                             FixedArrayBase::kHeaderSize));
-    __ mov(Operand(ecx, 0), eax);
-    // Update the write barrier for the array store.
-    __ RecordWrite(ebx, ecx, eax,
-                   kDontSaveFPRegs,
-                   EMIT_REMEMBERED_SET,
-                   OMIT_SMI_CHECK);
-    __ jmp(&element_done);
-
-    // Array literal has ElementsKind of FAST_SMI_ONLY_ELEMENTS or
-    // FAST_ELEMENTS, and value is Smi.
-    __ bind(&smi_element);
-    __ mov(ebx, FieldOperand(ebx, JSObject::kElementsOffset));
-    __ mov(FieldOperand(ebx, ecx, times_half_pointer_size,
-                        FixedArrayBase::kHeaderSize), eax);
-    // Fall through
-    __ bind(&element_done);
-    __ ret(0);
-  }
+  // Array literal has ElementsKind of FAST_DOUBLE_ELEMENTS.
+  __ bind(&double_elements);
+
+  __ push(edx);
+  __ mov(edx, FieldOperand(ebx, JSObject::kElementsOffset));
+  __ StoreNumberToDoubleElements(eax,
+                                 edx,
+                                 ecx,
+                                 edi,
+                                 xmm0,
+                                 &slow_elements_from_double,
+                                 false);
+  __ pop(edx);
+  __ ret(0);
 }
 
 #undef __
index 1e5a4da..24501c8 100644 (file)
@@ -119,6 +119,18 @@ PropertyDetails PropertyDetails::AsDeleted() {
   }
 
 
+bool IsMoreGeneralElementsKindTransition(ElementsKind from_kind,
+                                         ElementsKind to_kind) {
+  if (to_kind == FAST_ELEMENTS) {
+    return from_kind == FAST_SMI_ONLY_ELEMENTS ||
+        from_kind == FAST_DOUBLE_ELEMENTS;
+  } else {
+    return to_kind == FAST_DOUBLE_ELEMENTS &&
+        from_kind == FAST_SMI_ONLY_ELEMENTS;
+  }
+}
+
+
 bool Object::IsFixedArrayBase() {
   return IsFixedArray() || IsFixedDoubleArray();
 }
index 238fe1e..9a2319a 100644 (file)
@@ -9501,6 +9501,9 @@ MUST_USE_RESULT MaybeObject* JSObject::TransitionElementsKind(
       MaybeObject* maybe_new_map = GetElementsTransitionMap(FAST_ELEMENTS);
       Map* new_map;
       if (!maybe_new_map->To(&new_map)) return maybe_new_map;
+      if (FLAG_trace_elements_transitions) {
+        PrintElementsTransition(stdout, from_kind, elms, FAST_ELEMENTS, elms);
+      }
       set_map(new_map);
       return this;
     }
index b521231..fbaee6b 100644 (file)
@@ -167,6 +167,8 @@ static const int kElementsKindCount =
 
 void PrintElementsKind(FILE* out, ElementsKind kind);
 
+inline bool IsMoreGeneralElementsKindTransition(ElementsKind from_kind,
+                                                ElementsKind to_kind);
 
 // Setter that skips the write barrier if mode is SKIP_WRITE_BARRIER.
 enum WriteBarrierMode { SKIP_WRITE_BARRIER, UPDATE_WRITE_BARRIER };
index e608a53..bf50869 100644 (file)
@@ -5971,16 +5971,14 @@ void StoreArrayLiteralElementStub::Generate(MacroAssembler* masm) {
   Label slow_elements;
   Label fast_elements;
 
-  if (!FLAG_trace_elements_transitions) {
-    __ CheckFastElements(rdi, &double_elements);
+  __ CheckFastElements(rdi, &double_elements);
 
-    // FAST_SMI_ONLY_ELEMENTS or FAST_ELEMENTS
-    __ JumpIfSmi(rax, &smi_element);
-    __ CheckFastSmiOnlyElements(rdi, &fast_elements);
+  // FAST_SMI_ONLY_ELEMENTS or FAST_ELEMENTS
+  __ JumpIfSmi(rax, &smi_element);
+  __ CheckFastSmiOnlyElements(rdi, &fast_elements);
 
-    // Store into the array literal requires a elements transition. Call into
-    // the runtime.
-  }
+  // Store into the array literal requires a elements transition. Call into
+  // the runtime.
 
   __ bind(&slow_elements);
   __ pop(rdi);  // Pop return address and remember to put back later for tail
@@ -5995,44 +5993,40 @@ void StoreArrayLiteralElementStub::Generate(MacroAssembler* masm) {
                  // place.
   __ TailCallRuntime(Runtime::kStoreArrayLiteralElement, 5, 1);
 
-  if (!FLAG_trace_elements_transitions) {
-    // Array literal has ElementsKind of FAST_DOUBLE_ELEMENTS.
-    __ bind(&double_elements);
-
-    __ movq(r9, FieldOperand(rbx, JSObject::kElementsOffset));
-    __ SmiToInteger32(r11, rcx);
-    __ StoreNumberToDoubleElements(rax,
-                                   r9,
-                                   r11,
-                                   xmm0,
-                                   &slow_elements);
-    __ jmp(&element_done);
-
-    // Array literal has ElementsKind of FAST_ELEMENTS and value is an object.
-    __ bind(&fast_elements);
-    __ SmiToInteger32(kScratchRegister, rcx);
-    __ movq(rbx, FieldOperand(rbx, JSObject::kElementsOffset));
-    __ lea(rcx, FieldOperand(rbx, kScratchRegister, times_pointer_size,
-                             FixedArrayBase::kHeaderSize));
-    __ movq(Operand(rcx, 0), rax);
-    // Update the write barrier for the array store.
-    __ RecordWrite(rbx, rcx, rax,
-                   kDontSaveFPRegs,
-                   EMIT_REMEMBERED_SET,
-                   OMIT_SMI_CHECK);
-    __ jmp(&element_done);
-
-    // Array literal has ElementsKind of FAST_SMI_ONLY_ELEMENTS or
-    // FAST_ELEMENTS, and value is Smi.
-    __ bind(&smi_element);
-    __ SmiToInteger32(kScratchRegister, rcx);
-    __ movq(rbx, FieldOperand(rbx, JSObject::kElementsOffset));
-    __ movq(FieldOperand(rbx, kScratchRegister, times_pointer_size,
-                        FixedArrayBase::kHeaderSize), rax);
-    // Fall through
-    __ bind(&element_done);
-    __ ret(0);
-  }
+  // Array literal has ElementsKind of FAST_ELEMENTS and value is an object.
+  __ bind(&fast_elements);
+  __ SmiToInteger32(kScratchRegister, rcx);
+  __ movq(rbx, FieldOperand(rbx, JSObject::kElementsOffset));
+  __ lea(rcx, FieldOperand(rbx, kScratchRegister, times_pointer_size,
+                           FixedArrayBase::kHeaderSize));
+  __ movq(Operand(rcx, 0), rax);
+  // Update the write barrier for the array store.
+  __ RecordWrite(rbx, rcx, rax,
+                 kDontSaveFPRegs,
+                 EMIT_REMEMBERED_SET,
+                 OMIT_SMI_CHECK);
+  __ ret(0);
+
+  // Array literal has ElementsKind of FAST_SMI_ONLY_ELEMENTS or
+  // FAST_ELEMENTS, and value is Smi.
+  __ bind(&smi_element);
+  __ SmiToInteger32(kScratchRegister, rcx);
+  __ movq(rbx, FieldOperand(rbx, JSObject::kElementsOffset));
+  __ movq(FieldOperand(rbx, kScratchRegister, times_pointer_size,
+                       FixedArrayBase::kHeaderSize), rax);
+  __ ret(0);
+
+  // Array literal has ElementsKind of FAST_DOUBLE_ELEMENTS.
+  __ bind(&double_elements);
+
+  __ movq(r9, FieldOperand(rbx, JSObject::kElementsOffset));
+  __ SmiToInteger32(r11, rcx);
+  __ StoreNumberToDoubleElements(rax,
+                                 r9,
+                                 r11,
+                                 xmm0,
+                                 &slow_elements);
+  __ ret(0);
 }
 
 #undef __