Revision: 9690
Author:   [email protected]
Date:     Wed Oct 19 02:04:35 2011
Log:      Porting r9605 to arm (elements kind conversion in generated code).

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

Modified:
 /branches/bleeding_edge/src/arm/code-stubs-arm.cc
 /branches/bleeding_edge/src/arm/stub-cache-arm.cc
 /branches/bleeding_edge/src/code-stubs.cc
 /branches/bleeding_edge/src/x64/code-stubs-x64.cc
 /branches/bleeding_edge/test/mjsunit/elements-transition.js

=======================================
--- /branches/bleeding_edge/src/arm/code-stubs-arm.cc Mon Oct 17 05:44:16 2011 +++ /branches/bleeding_edge/src/arm/code-stubs-arm.cc Wed Oct 19 02:04:35 2011
@@ -6927,6 +6927,13 @@
   { r3, r1, r2, EMIT_REMEMBERED_SET },
   // KeyedStoreStubCompiler::GenerateStoreFastElement.
   { r4, r2, r3, EMIT_REMEMBERED_SET },
+  // FastElementsConversionStub::GenerateSmiOnlyToObject
+  // and FastElementsConversionStub::GenerateSmiOnlyToDouble
+  // and FastElementsConversionStub::GenerateDoubleToObject
+  { r2, r3, r9, EMIT_REMEMBERED_SET },
+  // FastElementsConversionStub::GenerateDoubleToObject
+  { r6, r0, r3, EMIT_REMEMBERED_SET },
+  { r2, r6, r9, EMIT_REMEMBERED_SET },
   // Null termination.
   { no_reg, no_reg, no_reg, EMIT_REMEMBERED_SET}
 };
@@ -7162,6 +7169,248 @@

   // Fall through when we need to inform the incremental marker.
 }
+
+
+void FastElementsConversionStub::GenerateSmiOnlyToObject(MacroAssembler* masm) {
+  // ----------- S t a t e -------------
+  //  -- r0    : value
+  //  -- r1    : key
+  //  -- r2    : receiver
+  //  -- lr    : return address
+  //  -- r3    : target map, scratch for subsequent call
+  //  -- r4    : scratch (elements)
+  // -----------------------------------
+  // Set transitioned map.
+  __ str(r3, FieldMemOperand(r2, HeapObject::kMapOffset));
+  __ RecordWriteField(r2,
+                      HeapObject::kMapOffset,
+                      r3,
+                      r9,
+                      kLRHasNotBeenSaved,
+                      kDontSaveFPRegs,
+                      EMIT_REMEMBERED_SET,
+                      OMIT_SMI_CHECK);
+}
+
+
+void FastElementsConversionStub::GenerateSmiOnlyToDouble(
+    MacroAssembler* masm, StrictModeFlag strict_mode) {
+  // ----------- S t a t e -------------
+  //  -- r0    : value
+  //  -- r1    : key
+  //  -- r2    : receiver
+  //  -- lr    : return address
+  //  -- r3    : target map, scratch for subsequent call
+  //  -- r4    : scratch (elements)
+  // -----------------------------------
+  Label loop, entry, convert_hole, gc_required, fail;
+  bool vfp3_supported = CpuFeatures::IsSupported(VFP3);
+
+  __ ldr(r4, FieldMemOperand(r2, JSObject::kElementsOffset));
+  __ ldr(r5, FieldMemOperand(r4, FixedArray::kLengthOffset));
+  // r4: source FixedArray
+  // r5: number of elements (smi-tagged)
+
+  // Allocate new FixedDoubleArray.
+  __ mov(ip, Operand(FixedDoubleArray::kHeaderSize));
+  __ add(ip, ip, Operand(r5, LSL, 2));
+  __ AllocateInNewSpace(ip, r6, r7, r9, &gc_required, NO_ALLOCATION_FLAGS);
+  // r6: destination FixedDoubleArray, not tagged as heap object
+  __ LoadRoot(r9, Heap::kFixedDoubleArrayMapRootIndex);
+  __ str(r9, MemOperand(r6, HeapObject::kMapOffset));
+  // Set destination FixedDoubleArray's length.
+  __ str(r5, MemOperand(r6, FixedDoubleArray::kLengthOffset));
+  // Update receiver's map.
+  __ push(lr);
+  __ str(r3, FieldMemOperand(r2, HeapObject::kMapOffset));
+  __ RecordWriteField(r2,
+                      HeapObject::kMapOffset,
+                      r3,
+                      r9,
+                      kLRHasBeenSaved,
+                      kDontSaveFPRegs,
+                      EMIT_REMEMBERED_SET,
+                      OMIT_SMI_CHECK);
+  // Replace receiver's backing store with newly created FixedDoubleArray.
+  __ add(r3, r6, Operand(kHeapObjectTag));
+  __ str(r3, FieldMemOperand(r2, JSObject::kElementsOffset));
+  __ RecordWriteField(r2,
+                      JSObject::kElementsOffset,
+                      r3,
+                      r9,
+                      kLRHasBeenSaved,
+                      kDontSaveFPRegs,
+                      EMIT_REMEMBERED_SET,
+                      OMIT_SMI_CHECK);
+  __ pop(lr);
+
+  // Prepare for conversion loop.
+  __ add(r3, r4, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
+  __ add(r6, r6, Operand(FixedDoubleArray::kHeaderSize));
+  __ add(r4, r6, Operand(r5, LSL, 2));
+  __ mov(r5, Operand(kHoleNanLower32));
+  __ mov(r7, Operand(kHoleNanUpper32));
+  // r3: begin of source FixedArray element fields, not tagged
+  // r4: end of destination FixedDoubleArray, not tagged
+  // r6: begin of FixedDoubleArray element fields, not tagged
+  // r5: kHoleNanLower32
+  // r7: kHoleNanUpper32
+  if (vfp3_supported) __ Push(r0, r1);
+
+  __ b(&entry);
+
+  // Call into runtime if GC is required.
+  __ bind(&gc_required);
+  KeyedStoreIC::GenerateRuntimeSetProperty(masm, strict_mode);
+
+  // Convert and copy elements.
+  __ bind(&loop);
+  __ ldr(r9, MemOperand(r3, 4, PostIndex));
+  // r9: current element
+  __ JumpIfNotSmi(r9, &convert_hole);
+
+  // Normal smi, convert to double and store.
+  __ SmiUntag(r9);
+  if (vfp3_supported) {
+    CpuFeatures::Scope scope(VFP3);
+    __ vmov(s0, r9);
+    __ vcvt_f64_s32(d0, s0);
+    __ vstr(d0, r6, 0);
+    __ add(r6, r6, Operand(8));
+  } else {
+    FloatingPointHelper::ConvertIntToDouble(masm,
+                                            r9,
+ FloatingPointHelper::kCoreRegisters,
+                                            d0,
+                                            r0,
+                                            r1,
+                                            ip,
+                                            s0);
+    __ str(r0, MemOperand(r6, 4, PostIndex));  // mantissa
+    __ str(r1, MemOperand(r6, 4, PostIndex));  // exponent
+  }
+  __ b(&entry);
+
+  // Hole found, store the-hole NaN.
+  __ bind(&convert_hole);
+  __ str(r5, MemOperand(r6, 4, PostIndex));  // mantissa
+  __ str(r7, MemOperand(r6, 4, PostIndex));  // exponent
+
+  __ bind(&entry);
+  __ cmp(r6, r4);
+  __ b(lt, &loop);
+
+  if (vfp3_supported) __ Pop(r0, r1);
+}
+
+
+void FastElementsConversionStub::GenerateDoubleToObject(
+    MacroAssembler* masm, StrictModeFlag strict_mode) {
+  // ----------- S t a t e -------------
+  //  -- r0    : value
+  //  -- r1    : key
+  //  -- r2    : receiver
+  //  -- lr    : return address
+  //  -- r3    : target map, scratch for subsequent call
+  //  -- r4    : scratch (elements)
+  // -----------------------------------
+  Label entry, loop, convert_hole, gc_required;
+
+  __ push(lr);
+  __ Push(r0, r1, r2, r3);
+
+  __ ldr(r4, FieldMemOperand(r2, JSObject::kElementsOffset));
+  __ ldr(r5, FieldMemOperand(r4, FixedArray::kLengthOffset));
+  // r4: source FixedDoubleArray
+  // r5: number of elements (smi-tagged)
+
+  // Allocate new FixedArray.
+  __ mov(r0, Operand(FixedDoubleArray::kHeaderSize));
+  __ add(r0, r0, Operand(r5, LSL, 1));
+  __ AllocateInNewSpace(r0, r6, r7, r9, &gc_required, NO_ALLOCATION_FLAGS);
+  // r6: destination FixedArray, not tagged as heap object
+  __ LoadRoot(r9, Heap::kFixedArrayMapRootIndex);
+  __ str(r9, MemOperand(r6, HeapObject::kMapOffset));
+  // Set destination FixedDoubleArray's length.
+  __ str(r5, MemOperand(r6, FixedDoubleArray::kLengthOffset));
+
+  // Prepare for conversion loop.
+ __ add(r4, r4, Operand(FixedDoubleArray::kHeaderSize - kHeapObjectTag + 4));
+  __ add(r3, r6, Operand(FixedArray::kHeaderSize - 4));
+  __ add(r6, r6, Operand(kHeapObjectTag));
+  __ add(r5, r3, Operand(r5, LSL, 1));
+  __ LoadRoot(r7, Heap::kTheHoleValueRootIndex);
+  __ LoadRoot(r9, Heap::kHeapNumberMapRootIndex);
+  // Using offsetted addresses to fully take advantage of pre/post-indexing
+  // r3: begin of destination FixedArray element fields, not tagged, -4
+  // r4: begin of source FixedDoubleArray element fields, not tagged, +4
+  // r5: end of destination FixedArray, not tagged, -4
+  // r6: destination FixedArray
+  // r7: the-hole pointer
+  // r9: heap number map
+  __ b(&entry);
+
+  // Call into runtime if GC is required.
+  __ bind(&gc_required);
+  __ Pop(r2, r3);
+  __ Pop(r0, r1);
+  __ pop(lr);
+  KeyedStoreIC::GenerateRuntimeSetProperty(masm, strict_mode);
+
+  __ bind(&loop);
+  __ ldr(lr, MemOperand(r4, 8, PostIndex));
+  // lr: current element's upper 32 bit
+  // r4: address of next element's upper 32 bit
+  __ cmp(lr, Operand(kHoleNanUpper32));
+  __ b(eq, &convert_hole);
+
+  // Non-hole double, copy value into a heap number.
+  __ AllocateHeapNumber(r0, r1, r2, r9, &gc_required);
+  __ str(lr, FieldMemOperand(r0, HeapNumber::kExponentOffset));
+  __ ldr(lr, MemOperand(r4, 12, NegOffset));
+  __ str(lr, FieldMemOperand(r0, HeapNumber::kMantissaOffset));
+  __ str(r0, MemOperand(r3, 4, PreIndex));
+  __ RecordWrite(r6,
+                 r3,
+                 r0,
+                 kLRHasBeenSaved,
+                 kDontSaveFPRegs,
+                 EMIT_REMEMBERED_SET,
+                 OMIT_SMI_CHECK);
+  __ b(&entry);
+
+  // Replace the-hole NaN with the-hole pointer.
+  __ bind(&convert_hole);
+  __ str(r7, MemOperand(r3, 4, PreIndex));
+
+  __ bind(&entry);
+  __ cmp(r3, r5);
+  __ b(lt, &loop);
+
+  __ Pop(r2, r3);
+  __ Pop(r0, r1);
+  // Update receiver's map.
+  __ str(r3, FieldMemOperand(r2, HeapObject::kMapOffset));
+  __ RecordWriteField(r2,
+                      HeapObject::kMapOffset,
+                      r3,
+                      r9,
+                      kLRHasBeenSaved,
+                      kDontSaveFPRegs,
+                      EMIT_REMEMBERED_SET,
+                      OMIT_SMI_CHECK);
+ // Replace receiver's backing store with newly created and filled FixedArray.
+  __ str(r6, FieldMemOperand(r2, JSObject::kElementsOffset));
+  __ RecordWriteField(r2,
+                      JSObject::kElementsOffset,
+                      r6,
+                      r9,
+                      kLRHasBeenSaved,
+                      kDontSaveFPRegs,
+                      EMIT_REMEMBERED_SET,
+                      OMIT_SMI_CHECK);
+  __ pop(lr);
+}


 #undef __
=======================================
--- /branches/bleeding_edge/src/arm/stub-cache-arm.cc Tue Oct 18 04:18:55 2011 +++ /branches/bleeding_edge/src/arm/stub-cache-arm.cc Wed Oct 19 02:04:35 2011
@@ -3299,8 +3299,8 @@
       __ Jump(code, RelocInfo::CODE_TARGET, eq);
     } else {
       Label next_map;
-      __ b(eq, &next_map);
-      __ mov(r4, Operand(Handle<Map>(transitioned_maps->at(i))));
+      __ b(ne, &next_map);
+      __ mov(r3, Operand(Handle<Map>(transitioned_maps->at(i))));
       __ Jump(code, RelocInfo::CODE_TARGET, al);
       __ bind(&next_map);
     }
=======================================
--- /branches/bleeding_edge/src/code-stubs.cc   Mon Oct 17 03:44:47 2011
+++ /branches/bleeding_edge/src/code-stubs.cc   Wed Oct 19 02:04:35 2011
@@ -416,7 +416,6 @@


 void FastElementsConversionStub::Generate(MacroAssembler* masm) {
-#if defined(V8_TARGET_ARCH_IA32) || defined(V8_TARGET_ARCH_X64)
   if (to_ == FAST_ELEMENTS) {
     if (from_ == FAST_SMI_ONLY_ELEMENTS) {
       GenerateSmiOnlyToObject(masm);
@@ -434,9 +433,6 @@
   } else {
     UNREACHABLE();
   }
-#else
-  KeyedStoreIC::GenerateRuntimeSetProperty(masm, strict_mode_);
-#endif  // V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_X64
 }

 } }  // namespace v8::internal
=======================================
--- /branches/bleeding_edge/src/x64/code-stubs-x64.cc Mon Oct 17 05:44:16 2011 +++ /branches/bleeding_edge/src/x64/code-stubs-x64.cc Wed Oct 19 02:04:35 2011
@@ -6019,7 +6019,7 @@

   // Prepare for conversion loop.
   __ movq(rsi, BitCast<int64_t, uint64_t>(kHoleNanInt64), RelocInfo::NONE);
-  __ Move(rdi, masm->isolate()->factory()->the_hole_value());
+  __ LoadRoot(rdi, Heap::kTheHoleValueRootIndex);
   // rsi: the-hole NaN
   // rdi: pointer to the-hole
   __ jmp(&entry);
=======================================
--- /branches/bleeding_edge/test/mjsunit/elements-transition.js Mon Oct 17 03:44:47 2011 +++ /branches/bleeding_edge/test/mjsunit/elements-transition.js Wed Oct 19 02:04:35 2011
@@ -41,32 +41,38 @@
     assertTrue(%HasFastSmiOnlyElements(array_1));
     assertTrue(%HasFastSmiOnlyElements(array_2));
     for (var i = 0; i < length; i++) {
-      if (i == length - 8 && test_double) {
+      if (i == length - 5 && test_double) {
+        // Trigger conversion to fast double elements at length-5.
         set(array_1, i, 0.5);
         set(array_2, i, 0.5);
         assertTrue(%HasFastDoubleElements(array_1));
         assertTrue(%HasFastDoubleElements(array_2));
-      } else if (i == length - 5 && test_object) {
+      } else if (i == length - 3 && test_object) {
+        // Trigger conversion to fast object elements at length-3.
         set(array_1, i, 'object');
         set(array_2, i, 'object');
         assertTrue(%HasFastElements(array_1));
         assertTrue(%HasFastElements(array_2));
-      } else {
+      } else if (i != length - 7) {
+        // Set the element to an integer but leave a hole at length-7.
         set(array_1, i, 2*i+1);
         set(array_2, i, 2*i+1);
       }
     }

     for (var i = 0; i < length; i++) {
-      if (i == length - 8 && test_double) {
+      if (i == length - 5 && test_double) {
         assertEquals(0.5, array_1[i]);
         assertEquals(0.5, array_2[i]);
-      } else if (i == length - 5 && test_object) {
+      } else if (i == length - 3 && test_object) {
         assertEquals('object', array_1[i]);
         assertEquals('object', array_2[i]);
-      } else {
+      } else if (i != length - 7) {
         assertEquals(2*i+1, array_1[i]);
         assertEquals(2*i+1, array_2[i]);
+      } else {
+        assertEquals(undefined, array_1[i]);
+        assertEquals(undefined, array_2[i]);
       }
     }

@@ -74,10 +80,10 @@
     assertEquals(length, array_2.length);
   }

-  test(false, false, function(a,i,v){ a[i] = v; }, 100);
-  test(true,  false, function(a,i,v){ a[i] = v; }, 100);
-  test(false, true,  function(a,i,v){ a[i] = v; }, 100);
-  test(true,  true,  function(a,i,v){ a[i] = v; }, 100);
+  test(false, false, function(a,i,v){ a[i] = v; }, 20);
+  test(true,  false, function(a,i,v){ a[i] = v; }, 20);
+  test(false, true,  function(a,i,v){ a[i] = v; }, 20);
+  test(true,  true,  function(a,i,v){ a[i] = v; }, 10);

   test(false, false, function(a,i,v){ a[i] = v; }, 10000);
   test(true,  false, function(a,i,v){ a[i] = v; }, 10000);

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

Reply via email to