Revision: 9416
Author:   [email protected]
Date:     Fri Sep 23 07:19:04 2011
Log:      Porting r9392 to x64 (smi-only arrays).

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

Modified:
 /branches/bleeding_edge/src/ia32/stub-cache-ia32.cc
 /branches/bleeding_edge/src/x64/full-codegen-x64.cc
 /branches/bleeding_edge/src/x64/ic-x64.cc
 /branches/bleeding_edge/src/x64/macro-assembler-x64.cc
 /branches/bleeding_edge/src/x64/macro-assembler-x64.h
 /branches/bleeding_edge/src/x64/stub-cache-x64.cc
 /branches/bleeding_edge/test/mjsunit/element-kind.js

=======================================
--- /branches/bleeding_edge/src/ia32/stub-cache-ia32.cc Thu Sep 22 04:30:04 2011 +++ /branches/bleeding_edge/src/ia32/stub-cache-ia32.cc Fri Sep 23 07:19:04 2011
@@ -3936,7 +3936,7 @@

   if (elements_kind == FAST_SMI_ONLY_ELEMENTS) {
     __ JumpIfNotSmi(eax, &miss_force_generic);
-    // ecx is a smi, don't use times_half_pointer_size istead of
+    // ecx is a smi, use times_half_pointer_size instead of
     // times_pointer_size
     __ mov(FieldOperand(edi,
                         ecx,
@@ -3945,7 +3945,7 @@
   } else {
     ASSERT(elements_kind == FAST_ELEMENTS);
     // Do the store and update the write barrier.
-    // ecx is a smi, don't use times_half_pointer_size istead of
+    // ecx is a smi, use times_half_pointer_size instead of
     // times_pointer_size
     __ lea(ecx, FieldOperand(edi,
                              ecx,
=======================================
--- /branches/bleeding_edge/src/x64/full-codegen-x64.cc Wed Sep 21 07:46:54 2011 +++ /branches/bleeding_edge/src/x64/full-codegen-x64.cc Fri Sep 23 07:19:04 2011
@@ -1455,13 +1455,25 @@
     VisitForAccumulatorValue(subexpr);

     // Store the subexpression value in the array's elements.
-    __ movq(rbx, Operand(rsp, 0));  // Copy of array literal.
-    __ movq(rbx, FieldOperand(rbx, JSObject::kElementsOffset));
+    __ movq(r8, Operand(rsp, 0));  // Copy of array literal.
+    __ movq(rbx, FieldOperand(r8, JSObject::kElementsOffset));
     int offset = FixedArray::kHeaderSize + (i * kPointerSize);
     __ movq(FieldOperand(rbx, offset), result_register());

+    Label no_map_change;
+    __ JumpIfSmi(result_register(), &no_map_change);
     // Update the write barrier for the array store.
- __ RecordWriteField(rbx, offset, result_register(), rcx, kDontSaveFPRegs);
+    __ RecordWriteField(rbx, offset, result_register(), rcx,
+                        kDontSaveFPRegs,
+                        EMIT_REMEMBERED_SET,
+                        OMIT_SMI_CHECK);
+    if (FLAG_smi_only_arrays) {
+      __ movq(rdi, FieldOperand(rbx, JSObject::kMapOffset));
+      __ CheckFastSmiOnlyElements(rdi, &no_map_change, Label::kNear);
+      __ push(r8);
+      __ CallRuntime(Runtime::kNonSmiElementStored, 1);
+    }
+    __ bind(&no_map_change);

     PrepareForBailoutForId(expr->GetIdForElement(i), NO_REGISTERS);
   }
=======================================
--- /branches/bleeding_edge/src/x64/ic-x64.cc   Mon Sep 19 11:36:47 2011
+++ /branches/bleeding_edge/src/x64/ic-x64.cc   Fri Sep 23 07:19:04 2011
@@ -692,14 +692,22 @@
   // rax: value
   // rbx: receiver's elements array (a FixedArray)
   // rcx: index
+
   Label non_smi_value;
+  __ JumpIfNotSmi(rax, &non_smi_value);
+  // It's irrelevant whether array is smi-only or not when writing a smi.
__ movq(FieldOperand(rbx, rcx, times_pointer_size, FixedArray::kHeaderSize),
           rax);
-  __ JumpIfNotSmi(rax, &non_smi_value, Label::kNear);
   __ ret(0);
+
   __ bind(&non_smi_value);
-  // Slow case that needs to retain rcx for use by RecordWrite.
-  // Update write barrier for the elements array address.
+  if (FLAG_smi_only_arrays) {
+    // Writing a non-smi, check whether array allows non-smi elements.
+    __ movq(rdi, FieldOperand(rdx, HeapObject::kMapOffset));
+    __ CheckFastObjectElements(rdi, &slow, Label::kNear);
+  }
+ __ movq(FieldOperand(rbx, rcx, times_pointer_size, FixedArray::kHeaderSize),
+          rax);
   __ movq(rdx, rax);
   __ lea(rcx,
FieldOperand(rbx, rcx, times_pointer_size, FixedArray::kHeaderSize));
=======================================
--- /branches/bleeding_edge/src/x64/macro-assembler-x64.cc Thu Sep 22 04:30:04 2011 +++ /branches/bleeding_edge/src/x64/macro-assembler-x64.cc Fri Sep 23 07:19:04 2011
@@ -2654,6 +2654,30 @@
        Immediate(Map::kMaximumBitField2FastElementValue));
   j(above, fail, distance);
 }
+
+
+void MacroAssembler::CheckFastObjectElements(Register map,
+                                             Label* fail,
+                                             Label::Distance distance) {
+  STATIC_ASSERT(FAST_SMI_ONLY_ELEMENTS == 0);
+  STATIC_ASSERT(FAST_ELEMENTS == 1);
+  cmpb(FieldOperand(map, Map::kBitField2Offset),
+       Immediate(Map::kMaximumBitField2FastSmiOnlyElementValue));
+  j(below_equal, fail, distance);
+  cmpb(FieldOperand(map, Map::kBitField2Offset),
+       Immediate(Map::kMaximumBitField2FastElementValue));
+  j(above, fail, distance);
+}
+
+
+void MacroAssembler::CheckFastSmiOnlyElements(Register map,
+                                              Label* fail,
+                                              Label::Distance distance) {
+  STATIC_ASSERT(FAST_SMI_ONLY_ELEMENTS == 0);
+  cmpb(FieldOperand(map, Map::kBitField2Offset),
+       Immediate(Map::kMaximumBitField2FastSmiOnlyElementValue));
+  j(above, fail, distance);
+}


 void MacroAssembler::CheckMap(Register obj,
=======================================
--- /branches/bleeding_edge/src/x64/macro-assembler-x64.h Tue Sep 20 06:32:27 2011 +++ /branches/bleeding_edge/src/x64/macro-assembler-x64.h Fri Sep 23 07:19:04 2011
@@ -847,6 +847,18 @@
                          Label* fail,
                          Label::Distance distance = Label::kFar);

+ // Check if a map for a JSObject indicates that the object can have both smi
+  // and HeapObject elements.  Jump to the specified label if it does not.
+  void CheckFastObjectElements(Register map,
+                               Label* fail,
+                               Label::Distance distance = Label::kFar);
+
+ // Check if a map for a JSObject indicates that the object has fast smi only
+  // elements.  Jump to the specified label if it does not.
+  void CheckFastSmiOnlyElements(Register map,
+                                Label* fail,
+                                Label::Distance distance = Label::kFar);
+
   // Check if the map of an object is equal to a specified map and
   // branch to label if not. Skip the smi check if not required
   // (object is known to be a heap object)
=======================================
--- /branches/bleeding_edge/src/x64/stub-cache-x64.cc Thu Sep 22 04:30:04 2011 +++ /branches/bleeding_edge/src/x64/stub-cache-x64.cc Fri Sep 23 07:19:04 2011
@@ -1442,34 +1442,59 @@
       __ cmpl(rax, rcx);
       __ j(greater, &attempt_to_grow_elements);

+      // Check if value is a smi.
+      __ movq(rcx, Operand(rsp, argc * kPointerSize));
+      __ JumpIfNotSmi(rcx, &with_write_barrier);
+
       // Save new length.
__ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rax);

       // Push the element.
-      __ movq(rcx, Operand(rsp, argc * kPointerSize));
       __ lea(rdx, FieldOperand(rbx,
                                rax, times_pointer_size,
FixedArray::kHeaderSize - argc * kPointerSize));
       __ movq(Operand(rdx, 0), rcx);

-      // Check if value is a smi.
       __ Integer32ToSmi(rax, rax);  // Return new length as smi.
-
-      __ JumpIfNotSmi(rcx, &with_write_barrier);
-
       __ ret((argc + 1) * kPointerSize);

       __ bind(&with_write_barrier);

+      if (FLAG_smi_only_arrays) {
+        __ movq(rdi, FieldOperand(rdx, HeapObject::kMapOffset));
+        __ CheckFastObjectElements(rdi, &call_builtin);
+      }
+
+      // Save new length.
+ __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rax);
+
+      // Push the element.
+      __ lea(rdx, FieldOperand(rbx,
+                               rax, times_pointer_size,
+ FixedArray::kHeaderSize - argc * kPointerSize));
+      __ movq(Operand(rdx, 0), rcx);
+
       __ RecordWrite(
rbx, rdx, rcx, kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);

+      __ Integer32ToSmi(rax, rax);  // Return new length as smi.
       __ ret((argc + 1) * kPointerSize);

       __ bind(&attempt_to_grow_elements);
       if (!FLAG_inline_new) {
         __ jmp(&call_builtin);
       }
+
+      __ movq(rdi, Operand(rsp, argc * kPointerSize));
+      if (FLAG_smi_only_arrays) {
+ // Growing elements that are SMI-only requires special handling in case
+        // the new element is non-Smi. For now, delegate to the builtin.
+        Label no_fast_elements_check;
+        __ JumpIfSmi(rdi, &no_fast_elements_check);
+        __ movq(rsi, FieldOperand(rdx, HeapObject::kMapOffset));
+        __ CheckFastObjectElements(rsi, &call_builtin, Label::kFar);
+        __ bind(&no_fast_elements_check);
+      }

       ExternalReference new_space_allocation_top =
           ExternalReference::new_space_allocation_top_address(isolate());
@@ -1494,10 +1519,9 @@

       // We fit and could grow elements.
       __ Store(new_space_allocation_top, rcx);
-      __ movq(rcx, Operand(rsp, argc * kPointerSize));

       // Push the argument...
-      __ movq(Operand(rdx, 0), rcx);
+      __ movq(Operand(rdx, 0), rdi);
       // ... and fill the rest with holes.
       __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex);
       for (int i = 1; i < kAllocationDelta; i++) {
@@ -1509,7 +1533,7 @@
// tell the incremental marker to rescan the object that we just grew. We // don't need to worry about the holes because they are in old space and
       // already marked black.
-      __ RecordWrite(rbx, rdx, rcx, kDontSaveFPRegs, OMIT_REMEMBERED_SET);
+      __ RecordWrite(rbx, rdx, rdi, kDontSaveFPRegs, OMIT_REMEMBERED_SET);

       // Restore receiver to rdx as finish sequence assumes it's here.
       __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
@@ -3699,13 +3723,19 @@

   // Do the store and update the write barrier.
   __ SmiToInteger32(rcx, rcx);
-  __ lea(rcx,
- FieldOperand(rdi, rcx, times_pointer_size, FixedArray::kHeaderSize));
-  __ movq(Operand(rcx, 0), rax);
-  // Make sure to preserve the value in register rax.
-  __ movq(rdx, rax);
-  ASSERT(elements_kind == FAST_ELEMENTS);
-  __ RecordWrite(rdi, rcx, rdx, kDontSaveFPRegs);
+  if (elements_kind == FAST_SMI_ONLY_ELEMENTS) {
+    __ JumpIfNotSmi(rax, &miss_force_generic);
+ __ movq(FieldOperand(rdi, rcx, times_pointer_size, FixedArray::kHeaderSize),
+            rax);
+  } else {
+    ASSERT(elements_kind == FAST_ELEMENTS);
+    __ lea(rcx,
+ FieldOperand(rdi, rcx, times_pointer_size, FixedArray::kHeaderSize));
+    __ movq(Operand(rcx, 0), rax);
+    // Make sure to preserve the value in register rax.
+    __ movq(rdx, rax);
+    __ RecordWrite(rdi, rcx, rdx, kDontSaveFPRegs);
+  }

   // Done.
   __ ret(0);
=======================================
--- /branches/bleeding_edge/test/mjsunit/element-kind.js Thu Sep 22 04:30:04 2011 +++ /branches/bleeding_edge/test/mjsunit/element-kind.js Fri Sep 23 07:19:04 2011
@@ -47,7 +47,7 @@
 }

 // We expect an object to only be of one element kind.
-function assertKind(expected, obj){
+function assertKind(expected, obj) {
   if (support_smi_only_arrays) {
     assertEquals(expected == element_kind.fast_smi_only_elements,
                  %HasFastSmiOnlyElements(obj));
@@ -100,7 +100,7 @@
// Make sure the element kind transitions from smionly when a non-smi is stored.
 var you = new Array();
 assertKind(element_kind.fast_smi_only_elements, you);
-for(i = 0; i < 1337; i++) {
+for (var i = 0; i < 1337; i++) {
   var val = i;
   if (i == 1336) {
     assertKind(element_kind.fast_smi_only_elements, you);
@@ -110,10 +110,11 @@
 }
 assertKind(element_kind.fast_elements, you);

-assertKind(element_kind.dictionary_elements, new Array(0xC0C0A));
-
-// fast_double_elements not yet available
-
+assertKind(element_kind.dictionary_elements, new Array(0xDECAF));
+
+var fast_double_array = new Array(0xDECAF);
+for (var i = 0; i < 0xDECAF; i++) fast_double_array[i] = i / 2;
+assertKind(element_kind.fast_double_elements, fast_double_array);

assertKind(element_kind.external_byte_elements, new Int8Array(9001)); assertKind(element_kind.external_unsigned_byte_elements, new Uint8Array(007));

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

Reply via email to