Revision: 9979
Author:   [email protected]
Date:     Fri Nov 11 06:49:16 2011
Log:      ARM: Implement runtime function for array literal transitions.

Also simplify ia32 and x64 handing of the trace_elements_transition flag.

[email protected]
BUG=none
TEST=array-literal-transitions.js

Review URL: http://codereview.chromium.org/8539011
http://code.google.com/p/v8/source/detail?r=9979

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

=======================================
--- /branches/bleeding_edge/src/arm/code-stubs-arm.cc Fri Nov 11 05:48:14 2011 +++ /branches/bleeding_edge/src/arm/code-stubs-arm.cc Fri Nov 11 06:49:16 2011
@@ -6888,6 +6888,8 @@
   // 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}
 };
@@ -7123,6 +7125,64 @@

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

=======================================
--- /branches/bleeding_edge/src/arm/full-codegen-arm.cc Fri Nov 11 05:48:14 2011 +++ /branches/bleeding_edge/src/arm/full-codegen-arm.cc Fri Nov 11 06:49:16 2011
@@ -1580,56 +1580,12 @@
     }
     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);
   }
=======================================
--- /branches/bleeding_edge/src/builtins.cc     Tue Nov  8 06:39:37 2011
+++ /branches/bleeding_edge/src/builtins.cc     Fri Nov 11 06:49:16 2011
@@ -775,7 +775,8 @@

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

     // 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;
     }
=======================================
--- /branches/bleeding_edge/src/ia32/code-stubs-ia32.cc Fri Nov 11 05:48:14 2011 +++ /branches/bleeding_edge/src/ia32/code-stubs-ia32.cc Fri Nov 11 06:49:16 2011
@@ -7046,16 +7046,14 @@
   Label slow_elements_from_double;
   Label fast_elements;

-  if (!FLAG_trace_elements_transitions) {
-    __ CheckFastElements(edi, &double_elements);
-
-    // 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.
-  }
+  __ CheckFastElements(edi, &double_elements);
+
+  // 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.

   __ bind(&slow_elements);
__ pop(edi); // Pop return address and remember to put back later for tail
@@ -7070,49 +7068,45 @@
                  // place.
   __ TailCallRuntime(Runtime::kStoreArrayLiteralElement, 5, 1);

-  if (!FLAG_trace_elements_transitions) {
-    // 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);
-    __ jmp(&element_done);
-
-    __ 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);
-  }
+  __ 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);
+
+  // 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);
+
+  // 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 __
=======================================
--- /branches/bleeding_edge/src/objects-inl.h   Fri Nov 11 05:48:14 2011
+++ /branches/bleeding_edge/src/objects-inl.h   Fri Nov 11 06:49:16 2011
@@ -117,6 +117,18 @@
   void holder::set_##name(bool value) {                    \
     set_##field(BooleanBit::set(field(), offset, value));  \
   }
+
+
+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() {
=======================================
--- /branches/bleeding_edge/src/objects.cc      Fri Nov 11 04:28:42 2011
+++ /branches/bleeding_edge/src/objects.cc      Fri Nov 11 06:49:16 2011
@@ -9501,6 +9501,9 @@
       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;
     }
=======================================
--- /branches/bleeding_edge/src/objects.h       Fri Nov 11 05:48:14 2011
+++ /branches/bleeding_edge/src/objects.h       Fri Nov 11 06:49:16 2011
@@ -167,6 +167,8 @@

 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 };
=======================================
--- /branches/bleeding_edge/src/x64/code-stubs-x64.cc Fri Nov 11 05:48:14 2011 +++ /branches/bleeding_edge/src/x64/code-stubs-x64.cc Fri Nov 11 06:49:16 2011
@@ -5971,16 +5971,14 @@
   Label slow_elements;
   Label fast_elements;

-  if (!FLAG_trace_elements_transitions) {
-    __ CheckFastElements(rdi, &double_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.
-  }
+  __ CheckFastElements(rdi, &double_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.

   __ bind(&slow_elements);
__ pop(rdi); // Pop return address and remember to put back later for tail
@@ -5995,44 +5993,40 @@
                  // 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 __

--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

Reply via email to