Revision: 2652
Author: [email protected]
Date: Fri Aug  7 05:52:32 2009
Log: Implement inline constructors for X64.  Fix ia32 inline constructors a  
little.  Fix a bug of a non-constant length between a call and its fixup.
Review URL: http://codereview.chromium.org/164144
http://code.google.com/p/v8/source/detail?r=2652

Modified:
  /branches/bleeding_edge/src/ia32/builtins-ia32.cc
  /branches/bleeding_edge/src/x64/builtins-x64.cc
  /branches/bleeding_edge/src/x64/codegen-x64.cc

=======================================
--- /branches/bleeding_edge/src/ia32/builtins-ia32.cc   Fri Jun 19 00:36:16  
2009
+++ /branches/bleeding_edge/src/ia32/builtins-ia32.cc   Fri Aug  7 05:52:32  
2009
@@ -140,7 +140,7 @@
      ExternalReference new_space_allocation_limit =
          ExternalReference::new_space_allocation_limit_address();
      __ cmp(edi, Operand::StaticVariable(new_space_allocation_limit));
-    __ j(greater_equal, &rt_call);
+    __ j(above_equal, &rt_call);
      // Allocated the JSObject, now initialize the fields.
      // eax: initial map
      // ebx: JSObject
@@ -175,8 +175,8 @@
      __ or_(Operand(ebx), Immediate(kHeapObjectTag));
      __ mov(Operand::StaticVariable(new_space_allocation_top), edi);

-    // Check if a properties array should be setup and allocate one if  
needed.
-    // Otherwise initialize the properties to the empty_fixed_array as  
well.
+    // Check if a non-empty properties array is needed.
+    // Allocate and initialize a FixedArray if it is.
      // eax: initial map
      // ebx: JSObject
      // edi: start of next object
@@ -184,21 +184,19 @@
      __ movzx_b(ecx, FieldOperand(eax, Map::kInObjectPropertiesOffset));
      // Calculate unused properties past the end of the in-object  
properties.
      __ sub(edx, Operand(ecx));
-    __ test(edx, Operand(edx));
      // Done if no extra properties are to be allocated.
      __ j(zero, &allocated);

      // Scale the number of elements by pointer size and add the header for
      // FixedArrays to the start of the next object calculation from above.
-    // eax: initial map
      // ebx: JSObject
      // edi: start of next object (will be start of FixedArray)
      // edx: number of elements in properties array
      ASSERT(Heap::MaxObjectSizeInPagedSpace() >
             (FixedArray::kHeaderSize + 255*kPointerSize));
-    __ lea(ecx, Operand(edi, edx, times_4, FixedArray::kHeaderSize));
+    __ lea(ecx, Operand(edi, edx, times_pointer_size,  
FixedArray::kHeaderSize));
      __ cmp(ecx, Operand::StaticVariable(new_space_allocation_limit));
-    __ j(greater_equal, &undo_allocation);
+    __ j(above_equal, &undo_allocation);
      __ mov(Operand::StaticVariable(new_space_allocation_top), ecx);

      // Initialize the FixedArray.
@@ -223,7 +221,7 @@
        __ add(Operand(eax), Immediate(kPointerSize));
        __ bind(&entry);
        __ cmp(eax, Operand(ecx));
-      __ j(less, &loop);
+      __ j(below, &loop);
      }

      // Store the initialized FixedArray into the properties field of
=======================================
--- /branches/bleeding_edge/src/x64/builtins-x64.cc     Fri Jul 24 04:22:35 2009
+++ /branches/bleeding_edge/src/x64/builtins-x64.cc     Fri Aug  7 05:52:32 2009
@@ -503,13 +503,160 @@
    // Try to allocate the object without transitioning into C code. If any  
of the
    // preconditions is not met, the code bails out to the runtime call.
    Label rt_call, allocated;
-
-  // TODO(x64): Implement inlined allocation.
+  if (FLAG_inline_new) {
+    Label undo_allocation;
+    // TODO(X64): Enable debugger support, using debug_step_in_fp.
+
+    // Verified that the constructor is a JSFunction.
+    // Load the initial map and verify that it is in fact a map.
+    // rdi: constructor
+    __ movq(rax, FieldOperand(rdi,  
JSFunction::kPrototypeOrInitialMapOffset));
+    // Will both indicate a NULL and a Smi
+    __ testl(rax, Immediate(kSmiTagMask));
+    __ j(zero, &rt_call);
+    // rdi: constructor
+    // rax: initial map (if proven valid below)
+    __ CmpObjectType(rax, MAP_TYPE, rbx);
+    __ j(not_equal, &rt_call);
+
+    // Check that the constructor is not constructing a JSFunction (see  
comments
+    // in Runtime_NewObject in runtime.cc). In which case the initial map's
+    // instance type would be JS_FUNCTION_TYPE.
+    // rdi: constructor
+    // rax: initial map
+    __ CmpInstanceType(rax, JS_FUNCTION_TYPE);
+    __ j(equal, &rt_call);
+
+    // Now allocate the JSObject on the heap.
+    __ movzxbq(rdi, FieldOperand(rax, Map::kInstanceSizeOffset));
+    __ shl(rdi, Immediate(kPointerSizeLog2));
+    // rdi: size of new object
+    // Make sure that the maximum heap object size will never cause us
+    // problem here, because it is always greater than the maximum
+    // instance size that can be represented in a byte.
+    ASSERT(Heap::MaxObjectSizeInPagedSpace() >= (1 << kBitsPerByte));
+    ExternalReference new_space_allocation_top =
+        ExternalReference::new_space_allocation_top_address();
+    __ movq(kScratchRegister, new_space_allocation_top);
+    __ movq(rbx, Operand(kScratchRegister, 0));
+    __ addq(rdi, rbx);  // Calculate new top
+    ExternalReference new_space_allocation_limit =
+        ExternalReference::new_space_allocation_limit_address();
+    __ movq(kScratchRegister, new_space_allocation_limit);
+    __ cmpq(rdi, Operand(kScratchRegister, 0));
+    __ j(above_equal, &rt_call);
+    // Allocated the JSObject, now initialize the fields.
+    // rax: initial map
+    // rbx: JSObject (not HeapObject tagged - the actual address).
+    // rdi: start of next object
+    __ movq(Operand(rbx, JSObject::kMapOffset), rax);
+    __ Move(rcx, Factory::empty_fixed_array());
+    __ movq(Operand(rbx, JSObject::kPropertiesOffset), rcx);
+    __ movq(Operand(rbx, JSObject::kElementsOffset), rcx);
+    // Set extra fields in the newly allocated object.
+    // rax: initial map
+    // rbx: JSObject
+    // rdi: start of next object
+    { Label loop, entry;
+      __ Move(rdx, Factory::undefined_value());
+      __ lea(rcx, Operand(rbx, JSObject::kHeaderSize));
+      __ jmp(&entry);
+      __ bind(&loop);
+      __ movq(Operand(rcx, 0), rdx);
+      __ addq(rcx, Immediate(kPointerSize));
+      __ bind(&entry);
+      __ cmpq(rcx, rdi);
+      __ j(less, &loop);
+    }
+
+    // Mostly done with the JSObject. Add the heap tag and store the new  
top, so
+    // that we can continue and jump into the continuation code at any  
time from
+    // now on. Any failures need to undo the setting of the new top, so  
that the
+    // heap is in a consistent state and verifiable.
+    // rax: initial map
+    // rbx: JSObject
+    // rdi: start of next object
+    __ or_(rbx, Immediate(kHeapObjectTag));
+    __ movq(kScratchRegister, new_space_allocation_top);
+    __ movq(Operand(kScratchRegister, 0), rdi);
+
+    // Check if a non-empty properties array is needed.
+    // Allocate and initialize a FixedArray if it is.
+    // rax: initial map
+    // rbx: JSObject
+    // rdi: start of next object
+    __ movzxbq(rdx, FieldOperand(rax, Map::kUnusedPropertyFieldsOffset));
+    __ movzxbq(rcx, FieldOperand(rax, Map::kInObjectPropertiesOffset));
+    // Calculate unused properties past the end of the in-object  
properties.
+    __ subq(rdx, rcx);
+    // Done if no extra properties are to be allocated.
+    __ j(zero, &allocated);
+
+    // Scale the number of elements by pointer size and add the header for
+    // FixedArrays to the start of the next object calculation from above.
+    // rbx: JSObject
+    // rdi: start of next object (will be start of FixedArray)
+    // rdx: number of elements in properties array
+    ASSERT(Heap::MaxObjectSizeInPagedSpace() >
+           (FixedArray::kHeaderSize + 255*kPointerSize));
+    __ lea(rax, Operand(rdi, rdx, times_pointer_size,  
FixedArray::kHeaderSize));
+    __ movq(kScratchRegister, new_space_allocation_limit);
+    __ cmpq(rax, Operand(kScratchRegister, 0));
+    __ j(above_equal, &undo_allocation);
+    __ store_rax(new_space_allocation_top);
+
+    // Initialize the FixedArray.
+    // rbx: JSObject
+    // rdi: FixedArray
+    // rdx: number of elements
+    // rax: start of next object
+    __ Move(rcx, Factory::fixed_array_map());
+    __ movq(Operand(rdi, JSObject::kMapOffset), rcx);  // setup the map
+    __ movl(Operand(rdi, FixedArray::kLengthOffset), rdx);  // and length
+
+    // Initialize the fields to undefined.
+    // rbx: JSObject
+    // rdi: FixedArray
+    // rax: start of next object
+    // rdx: number of elements
+    { Label loop, entry;
+      __ Move(rdx, Factory::undefined_value());
+      __ lea(rcx, Operand(rdi, FixedArray::kHeaderSize));
+      __ jmp(&entry);
+      __ bind(&loop);
+      __ movq(Operand(rcx, 0), rdx);
+      __ addq(rcx, Immediate(kPointerSize));
+      __ bind(&entry);
+      __ cmpq(rcx, rax);
+      __ j(below, &loop);
+    }
+
+    // Store the initialized FixedArray into the properties field of
+    // the JSObject
+    // rbx: JSObject
+    // rdi: FixedArray
+    __ or_(rdi, Immediate(kHeapObjectTag));  // add the heap tag
+    __ movq(FieldOperand(rbx, JSObject::kPropertiesOffset), rdi);
+
+
+    // Continue with JSObject being successfully allocated
+    // rbx: JSObject
+    __ jmp(&allocated);
+
+    // Undo the setting of the new top so that the heap is verifiable. For
+    // example, the map's unused properties potentially do not match the
+    // allocated objects unused properties.
+    // rbx: JSObject (previous new top)
+    __ bind(&undo_allocation);
+    __ xor_(rbx, Immediate(kHeapObjectTag));  // clear the heap tag
+    __ movq(kScratchRegister, new_space_allocation_top);
+    __ movq(Operand(kScratchRegister, 0), rbx);
+  }

    // Allocate the new receiver object using the runtime call.
    // rdi: function (constructor)
    __ bind(&rt_call);
-  // Must restore edi (constructor) before calling runtime.
+  // Must restore rdi (constructor) before calling runtime.
    __ movq(rdi, Operand(rsp, 0));
    __ push(rdi);
    __ CallRuntime(Runtime::kNewObject, 1);
=======================================
--- /branches/bleeding_edge/src/x64/codegen-x64.cc      Fri Aug  7 04:16:26 2009
+++ /branches/bleeding_edge/src/x64/codegen-x64.cc      Fri Aug  7 05:52:32 2009
@@ -5605,9 +5605,20 @@
          Comment cmnt(masm, "[ Inlined named property load");
          Result receiver = cgen_->frame()->Pop();
          receiver.ToRegister();
-
          Result value = cgen_->allocator()->Allocate();
          ASSERT(value.is_valid());
+        // Cannot use r12 for receiver, because that changes
+        // the distance between a call and a fixup location,
+        // due to a special encoding of r12 as r/m in a ModR/M byte.
+        if (receiver.reg().is(r12)) {
+          // Swap receiver and value.
+          __ movq(value.reg(), receiver.reg());
+          Result temp = receiver;
+          receiver = value;
+          value = temp;
+          cgen_->frame()->Spill(value.reg());  // r12 may have been shared.
+        }
+
          DeferredReferenceGetNamedValue* deferred =
              new DeferredReferenceGetNamedValue(value.reg(),
                                                 receiver.reg(),

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

Reply via email to