Revision: 9655
Author:   [email protected]
Date:     Mon Oct 17 03:44:47 2011
Log:      Porting r9605 to x64 (elements kind conversion in generated code).

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

Modified:
 /branches/bleeding_edge/src/code-stubs.cc
 /branches/bleeding_edge/src/ia32/code-stubs-ia32.cc
 /branches/bleeding_edge/src/x64/code-stubs-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/test/mjsunit/elements-transition.js

=======================================
--- /branches/bleeding_edge/src/code-stubs.cc   Thu Oct 13 03:53:31 2011
+++ /branches/bleeding_edge/src/code-stubs.cc   Mon Oct 17 03:44:47 2011
@@ -416,7 +416,7 @@


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

 } }  // namespace v8::internal
=======================================
--- /branches/bleeding_edge/src/ia32/code-stubs-ia32.cc Thu Oct 13 03:53:31 2011 +++ /branches/bleeding_edge/src/ia32/code-stubs-ia32.cc Mon Oct 17 03:44:47 2011
@@ -7061,9 +7061,8 @@
                       OMIT_SMI_CHECK);

   __ mov(edi, FieldOperand(esi, FixedArray::kLengthOffset));
-  // Convert and copy elements
-  // esi: source FixedArray
-  // edi: number of elements to convert/copy
+
+  // Prepare for conversion loop.
   ExternalReference canonical_the_hole_nan_reference =
       ExternalReference::address_of_the_hole_nan();
   XMMRegister the_hole_nan = xmm1;
@@ -7073,6 +7072,18 @@
               Operand::StaticVariable(canonical_the_hole_nan_reference));
   }
   __ jmp(&entry);
+
+  // Call into runtime if GC is required.
+  __ bind(&gc_required);
+  // Restore registers before jumping into runtime.
+  __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
+  __ pop(ebx);
+  __ pop(eax);
+  KeyedStoreIC::GenerateRuntimeSetProperty(masm, strict_mode);
+
+  // Convert and copy elements
+  // esi: source FixedArray
+  // edi: number of elements to convert/copy
   __ bind(&loop);
   __ sub(edi, Immediate(Smi::FromInt(1)));
   __ mov(ebx, FieldOperand(esi, edi, times_2, FixedArray::kHeaderSize));
@@ -7110,7 +7121,6 @@
   __ test(edi, edi);
   __ j(not_zero, &loop);

-  Label done;
   __ pop(ebx);
   __ pop(eax);
   // eax: value
@@ -7126,15 +7136,6 @@
                       OMIT_SMI_CHECK);
   // Restore esi.
   __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
-  __ jmp(&done, Label::kNear);
-
-  __ bind(&gc_required);
-  // Restore registers before jumping into runtime.
-  __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
-  __ pop(ebx);
-  __ pop(eax);
-  KeyedStoreIC::GenerateRuntimeSetProperty(masm, strict_mode);
-  __ bind(&done);
 }


@@ -7167,10 +7168,19 @@
   __ mov(FieldOperand(eax, FixedArray::kLengthOffset), ebx);
   __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));

+  __ jmp(&entry);
+
+  // Call into runtime if GC is required.
+  __ bind(&gc_required);
+  __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
+  __ pop(ebx);
+  __ pop(edx);
+  __ pop(eax);
+  KeyedStoreIC::GenerateRuntimeSetProperty(masm, strict_mode);
+
   // Box doubles into heap numbers.
   // edi: source FixedDoubleArray
   // eax: destination FixedArray
-  __ jmp(&entry);
   __ bind(&loop);
   __ sub(ebx, Immediate(Smi::FromInt(1)));
   // ebx: index of current element (smi-tagged)
@@ -7200,9 +7210,9 @@
                       kDontSaveFPRegs,
                       EMIT_REMEMBERED_SET,
                       OMIT_SMI_CHECK);
-  __ jmp(&entry);
-
-  // Replace the-hole nan with the-hole pointer.
+  __ jmp(&entry, Label::kNear);
+
+  // Replace the-hole NaN with the-hole pointer.
   __ bind(&convert_hole);
   __ mov(FieldOperand(eax, ebx, times_2, FixedArray::kHeaderSize),
          masm->isolate()->factory()->the_hole_value());
@@ -7235,18 +7245,8 @@
                       OMIT_SMI_CHECK);

   // Restore registers.
-  Label done;
   __ pop(eax);
   __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
-  __ jmp(&done, Label::kNear);
-
-  __ bind(&gc_required);
-  __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset));
-  __ pop(ebx);
-  __ pop(edx);
-  __ pop(eax);
-  KeyedStoreIC::GenerateRuntimeSetProperty(masm, strict_mode);
-  __ bind(&done);
 }

 #undef __
=======================================
--- /branches/bleeding_edge/src/x64/code-stubs-x64.cc Tue Oct 11 02:28:06 2011 +++ /branches/bleeding_edge/src/x64/code-stubs-x64.cc Mon Oct 17 03:44:47 2011
@@ -5665,6 +5665,12 @@
   { rbx, rdx, rcx, EMIT_REMEMBERED_SET},
   // KeyedStoreStubCompiler::GenerateStoreFastElement.
   { rdi, rdx, rcx, EMIT_REMEMBERED_SET},
+  // FastElementsConversionStub::GenerateSmiOnlyToObject
+  // and FastElementsConversionStub::GenerateDoubleToObject
+  { rdx, rbx, rdi, EMIT_REMEMBERED_SET},
+  // FastElementsConversionStub::GenerateDoubleToObject
+  { rax, r11, r15, EMIT_REMEMBERED_SET},
+  { rdx, rax, rdi, EMIT_REMEMBERED_SET},
   // Null termination.
   { no_reg, no_reg, no_reg, EMIT_REMEMBERED_SET}
 };
@@ -5913,6 +5919,181 @@
 }


+void FastElementsConversionStub::GenerateSmiOnlyToObject(MacroAssembler* masm) {
+  // ----------- S t a t e -------------
+  //  -- rax    : value
+  //  -- rbx    : target map
+  //  -- rcx    : key
+  //  -- rdx    : receiver
+  //  -- rsp[0] : return address
+  // -----------------------------------
+  // Set transitioned map.
+  __ movq(FieldOperand(rdx, HeapObject::kMapOffset), rbx);
+  __ RecordWriteField(rdx,
+                      HeapObject::kMapOffset,
+                      rbx,
+                      rdi,
+                      kDontSaveFPRegs,
+                      EMIT_REMEMBERED_SET,
+                      OMIT_SMI_CHECK);
+}
+
+
+void FastElementsConversionStub::GenerateSmiOnlyToDouble(
+    MacroAssembler* masm, StrictModeFlag strict_mode) {
+  // ----------- S t a t e -------------
+  //  -- rax    : value
+  //  -- rbx    : target map
+  //  -- rcx    : key
+  //  -- rdx    : receiver
+  //  -- rsp[0] : return address
+  // -----------------------------------
+  // Set transitioned map.
+  __ movq(FieldOperand(rdx, HeapObject::kMapOffset), rbx);
+  __ RecordWriteField(rdx,
+                      HeapObject::kMapOffset,
+                      rbx,
+                      rdi,
+                      kDontSaveFPRegs,
+                      EMIT_REMEMBERED_SET,
+                      OMIT_SMI_CHECK);
+  // Set backing store's map
+  __ movq(r8, FieldOperand(rdx, JSObject::kElementsOffset));
+  __ LoadRoot(rdi, Heap::kFixedDoubleArrayMapRootIndex);
+  __ movq(FieldOperand(r8, HeapObject::kMapOffset), rdi);
+
+  // Convert smis to doubles and holes to hole NaNs.  Since FixedArray and
+ // FixedDoubleArray do not differ in size, we do not allocate a new array. + STATIC_ASSERT(FixedDoubleArray::kLengthOffset == FixedArray::kLengthOffset);
+  STATIC_ASSERT(FixedDoubleArray::kHeaderSize == FixedArray::kHeaderSize);
+  __ SmiToInteger32(r9, FieldOperand(r8, FixedDoubleArray::kLengthOffset));
+  // r8 : elements array
+  // r9 : elements array length
+  Label loop, entry, convert_hole;
+  __ movq(r15, BitCast<int64_t, uint64_t>(kHoleNanInt64), RelocInfo::NONE);
+  // r15: the-hole NaN
+  __ jmp(&entry);
+  __ bind(&loop);
+  __ decq(r9);
+  __ movq(rbx,
+          FieldOperand(r8, r9, times_8, FixedArray::kHeaderSize));
+  // r9 : current element's index
+  // rbx: current element (smi-tagged)
+  __ JumpIfNotSmi(rbx, &convert_hole);
+  __ SmiToInteger32(rbx, rbx);
+  __ cvtlsi2sd(xmm0, rbx);
+  __ movsd(FieldOperand(r8, r9, times_8, FixedDoubleArray::kHeaderSize),
+           xmm0);
+  __ jmp(&entry);
+  __ bind(&convert_hole);
+ __ movq(FieldOperand(r8, r9, times_8, FixedDoubleArray::kHeaderSize), r15);
+  __ bind(&entry);
+  __ testq(r9, r9);
+  __ j(not_zero, &loop);
+}
+
+
+void FastElementsConversionStub::GenerateDoubleToObject(
+    MacroAssembler* masm, StrictModeFlag strict_mode) {
+  // ----------- S t a t e -------------
+  //  -- rax    : value
+  //  -- rbx    : target map
+  //  -- rcx    : key
+  //  -- rdx    : receiver
+  //  -- rsp[0] : return address
+  // -----------------------------------
+  Label loop, entry, convert_hole, gc_required;
+  __ push(rax);
+
+  __ movq(r8, FieldOperand(rdx, JSObject::kElementsOffset));
+  __ SmiToInteger32(r9, FieldOperand(r8, FixedDoubleArray::kLengthOffset));
+  // r8 : source FixedDoubleArray
+  // r9 : number of elements
+  __ lea(rdi, Operand(r9, times_pointer_size, FixedArray::kHeaderSize));
+  __ AllocateInNewSpace(rdi, rax, r14, r15, &gc_required, TAG_OBJECT);
+  // rax: destination FixedArray
+  __ LoadRoot(rdi, Heap::kFixedArrayMapRootIndex);
+  __ movq(FieldOperand(rax, HeapObject::kMapOffset), rdi);
+  __ Integer32ToSmi(r14, r9);
+  __ movq(FieldOperand(rax, FixedArray::kLengthOffset), r14);
+
+  // Prepare for conversion loop.
+  __ movq(rsi, BitCast<int64_t, uint64_t>(kHoleNanInt64), RelocInfo::NONE);
+  __ Move(rdi, masm->isolate()->factory()->the_hole_value());
+  // rsi: the-hole NaN
+  // rdi: pointer to the-hole
+  __ jmp(&entry);
+
+  // Call into runtime if GC is required.
+  __ bind(&gc_required);
+  __ pop(rax);
+  __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
+  KeyedStoreIC::GenerateRuntimeSetProperty(masm, strict_mode);
+
+  // Box doubles into heap numbers.
+  __ bind(&loop);
+  __ decq(r9);
+  __ movq(r14, FieldOperand(r8,
+                            r9,
+                            times_pointer_size,
+                            FixedDoubleArray::kHeaderSize));
+  // r9 : current element's index
+  // r14: current element
+  __ cmpq(r14, rsi);
+  __ j(equal, &convert_hole);
+
+  // Non-hole double, copy value into a heap number.
+  __ AllocateHeapNumber(r11, r15, &gc_required);
+  // r11: new heap number
+  __ movq(FieldOperand(r11, HeapNumber::kValueOffset), r14);
+  __ movq(FieldOperand(rax,
+                       r9,
+                       times_pointer_size,
+                       FixedArray::kHeaderSize),
+          r11);
+  __ movq(r15, r9);
+  __ RecordWriteArray(rax,
+                      r11,
+                      r15,
+                      kDontSaveFPRegs,
+                      EMIT_REMEMBERED_SET,
+                      OMIT_SMI_CHECK);
+  __ jmp(&entry, Label::kNear);
+
+  // Replace the-hole NaN with the-hole pointer.
+  __ bind(&convert_hole);
+  __ movq(FieldOperand(rax,
+                       r9,
+                       times_pointer_size,
+                       FixedArray::kHeaderSize),
+          rdi);
+
+  __ bind(&entry);
+  __ testq(r9, r9);
+  __ j(not_zero, &loop);
+
+  // Set transitioned map.
+  __ movq(FieldOperand(rdx, HeapObject::kMapOffset), rbx);
+  __ RecordWriteField(rdx,
+                      HeapObject::kMapOffset,
+                      rbx,
+                      rdi,
+                      kDontSaveFPRegs,
+                      EMIT_REMEMBERED_SET,
+                      OMIT_SMI_CHECK);
+ // Replace receiver's backing store with newly created and filled FixedArray.
+  __ movq(FieldOperand(rdx, JSObject::kElementsOffset), rax);
+  __ RecordWriteField(rdx,
+                      JSObject::kElementsOffset,
+                      rax,
+                      rdi,
+                      kDontSaveFPRegs,
+                      EMIT_REMEMBERED_SET,
+                      OMIT_SMI_CHECK);
+  __ pop(rax);
+  __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
+}
+
 #undef __

 } }  // namespace v8::internal
=======================================
--- /branches/bleeding_edge/src/x64/ic-x64.cc   Mon Oct 17 00:43:40 2011
+++ /branches/bleeding_edge/src/x64/ic-x64.cc   Mon Oct 17 03:44:47 2011
@@ -712,12 +712,11 @@
   // Writing a non-smi, check whether array allows non-smi elements.
   // r9: receiver's map
   __ CheckFastObjectElements(r9, &slow, Label::kNear);
-  __ lea(rcx,
- FieldOperand(rbx, rcx, times_pointer_size, FixedArray::kHeaderSize));
-  __ movq(Operand(rcx, 0), rax);
-  __ movq(rdx, rax);
-  __ RecordWrite(
-      rbx, rcx, rdx, kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
+ __ movq(FieldOperand(rbx, rcx, times_pointer_size, FixedArray::kHeaderSize),
+          rax);
+  __ movq(rdx, rax);  // Preserve the value which is returned.
+  __ RecordWriteArray(
+      rbx, rax, rcx, kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
   __ ret(0);

   __ bind(&fast_double_with_map_check);
=======================================
--- /branches/bleeding_edge/src/x64/macro-assembler-x64.cc Thu Sep 29 07:08:21 2011 +++ /branches/bleeding_edge/src/x64/macro-assembler-x64.cc Mon Oct 17 03:44:47 2011
@@ -324,6 +324,40 @@
     movq(dst, BitCast<int64_t>(kZapValue), RelocInfo::NONE);
   }
 }
+
+
+void MacroAssembler::RecordWriteArray(Register object,
+                                      Register value,
+                                      Register index,
+                                      SaveFPRegsMode save_fp,
+ RememberedSetAction remembered_set_action,
+                                      SmiCheck smi_check) {
+  // First, check if a write barrier is even needed. The tests below
+  // catch stores of Smis.
+  Label done;
+
+  // Skip barrier if writing a smi.
+  if (smi_check == INLINE_SMI_CHECK) {
+    JumpIfSmi(value, &done);
+  }
+
+  // Array access: calculate the destination address. Index is not a smi.
+  Register dst = index;
+  lea(dst, Operand(object, index, times_pointer_size,
+                   FixedArray::kHeaderSize - kHeapObjectTag));
+
+  RecordWrite(
+      object, dst, value, save_fp, remembered_set_action, OMIT_SMI_CHECK);
+
+  bind(&done);
+
+ // Clobber clobbered input registers when running with the debug-code flag
+  // turned on to provoke errors.
+  if (emit_debug_code()) {
+    movq(value, Immediate(BitCast<int64_t>(kZapValue)));
+    movq(index, Immediate(BitCast<int64_t>(kZapValue)));
+  }
+}


 void MacroAssembler::RecordWrite(Register object,
=======================================
--- /branches/bleeding_edge/src/x64/macro-assembler-x64.h Thu Sep 29 07:08:21 2011 +++ /branches/bleeding_edge/src/x64/macro-assembler-x64.h Mon Oct 17 03:44:47 2011
@@ -256,8 +256,8 @@

// Notify the garbage collector that we wrote a pointer into a fixed array.
   // |array| is the array being stored into, |value| is the
-  // object being stored.  |index| is the array index represented as a
-  // Smi. All registers are clobbered by the operation RecordWriteArray
+ // object being stored. |index| is the array index represented as a non-smi.
+  // All registers are clobbered by the operation RecordWriteArray
   // filters out smis so it does not update the write barrier if the
   // value is a smi.
   void RecordWriteArray(
=======================================
--- /branches/bleeding_edge/test/mjsunit/elements-transition.js Thu Oct 13 03:53:31 2011 +++ /branches/bleeding_edge/test/mjsunit/elements-transition.js Mon Oct 17 03:44:47 2011
@@ -69,6 +69,9 @@
         assertEquals(2*i+1, array_2[i]);
       }
     }
+
+    assertEquals(length, array_1.length);
+    assertEquals(length, array_2.length);
   }

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

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

Reply via email to