Revision: 3021
Author: [email protected]
Date: Tue Oct  6 06:11:05 2009
Log: Add near calls (32-bit displacement) to Code objects on X64 platform.
Review URL: http://codereview.chromium.org/200095
http://code.google.com/p/v8/source/detail?r=3021

Modified:
  /branches/bleeding_edge/src/arm/assembler-arm-inl.h
  /branches/bleeding_edge/src/assembler.h
  /branches/bleeding_edge/src/ia32/assembler-ia32-inl.h
  /branches/bleeding_edge/src/mark-compact.cc
  /branches/bleeding_edge/src/memory.h
  /branches/bleeding_edge/src/objects.cc
  /branches/bleeding_edge/src/serialize.cc
  /branches/bleeding_edge/src/x64/assembler-x64-inl.h
  /branches/bleeding_edge/src/x64/assembler-x64.cc
  /branches/bleeding_edge/src/x64/assembler-x64.h
  /branches/bleeding_edge/src/x64/macro-assembler-x64.cc

=======================================
--- /branches/bleeding_edge/src/arm/assembler-arm-inl.h Sun Sep 13 23:57:24  
2009
+++ /branches/bleeding_edge/src/arm/assembler-arm-inl.h Tue Oct  6 06:11:05  
2009
@@ -81,7 +81,13 @@

  Object* RelocInfo::target_object() {
    ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
-  return reinterpret_cast<Object*>(Assembler::target_address_at(pc_));
+  return Memory::Object_at(Assembler::target_address_address_at(pc_));
+}
+
+
+Handle<Object> RelocInfo::target_object_handle(Assembler *origin) {
+  ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
+  return  
Memory::Object_Handle_at(Assembler::target_address_address_at(pc_));
  }


=======================================
--- /branches/bleeding_edge/src/assembler.h     Mon Aug 31 05:40:37 2009
+++ /branches/bleeding_edge/src/assembler.h     Tue Oct  6 06:11:05 2009
@@ -191,6 +191,7 @@
    INLINE(Address target_address());
    INLINE(void set_target_address(Address target));
    INLINE(Object* target_object());
+  INLINE(Handle<Object> target_object_handle(Assembler* origin));
    INLINE(Object** target_object_address());
    INLINE(void set_target_object(Object* target));

=======================================
--- /branches/bleeding_edge/src/ia32/assembler-ia32-inl.h       Tue Jun 23  
02:50:51 2009
+++ /branches/bleeding_edge/src/ia32/assembler-ia32-inl.h       Tue Oct  6  
06:11:05 2009
@@ -85,19 +85,25 @@

  Object* RelocInfo::target_object() {
    ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
-  return *reinterpret_cast<Object**>(pc_);
+  return Memory::Object_at(pc_);
+}
+
+
+Handle<Object> RelocInfo::target_object_handle(Assembler *origin) {
+  ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
+  return Memory::Object_Handle_at(pc_);
  }


  Object** RelocInfo::target_object_address() {
    ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
-  return reinterpret_cast<Object**>(pc_);
+  return &Memory::Object_at(pc_);
  }


  void RelocInfo::set_target_object(Object* target) {
    ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
-  *reinterpret_cast<Object**>(pc_) = target;
+  Memory::Object_at(pc_) = target;
  }


=======================================
--- /branches/bleeding_edge/src/mark-compact.cc Mon Sep 21 03:35:47 2009
+++ /branches/bleeding_edge/src/mark-compact.cc Tue Oct  6 06:11:05 2009
@@ -282,8 +282,6 @@
             rinfo->IsCallInstruction());
      HeapObject* code =  
Code::GetCodeFromTargetAddress(rinfo->call_address());
      MarkCompactCollector::MarkObject(code);
-    // When compacting we convert the call to a real object pointer.
-    if (IsCompacting()) rinfo->set_call_object(code);
    }

   private:
@@ -1382,6 +1380,14 @@
      rinfo->set_target_address(
          reinterpret_cast<Code*>(target)->instruction_start());
    }
+
+  void VisitDebugTarget(RelocInfo* rinfo) {
+    ASSERT(RelocInfo::IsJSReturn(rinfo->rmode()) &&  
rinfo->IsCallInstruction());
+    Object* target = Code::GetCodeFromTargetAddress(rinfo->call_address());
+    VisitPointer(&target);
+    rinfo->set_call_address(
+        reinterpret_cast<Code*>(target)->instruction_start());
+  }

   private:
    void UpdatePointer(Object** p) {
=======================================
--- /branches/bleeding_edge/src/memory.h        Tue Jun  2 06:40:52 2009
+++ /branches/bleeding_edge/src/memory.h        Tue Oct  6 06:11:05 2009
@@ -63,6 +63,10 @@
    static Object*& Object_at(Address addr)  {
      return *reinterpret_cast<Object**>(addr);
    }
+
+  static Handle<Object>& Object_Handle_at(Address addr)  {
+    return *reinterpret_cast<Handle<Object>*>(addr);
+  }
  };

  } }  // namespace v8::internal
=======================================
--- /branches/bleeding_edge/src/objects.cc      Wed Sep 30 05:25:46 2009
+++ /branches/bleeding_edge/src/objects.cc      Tue Oct  6 06:11:05 2009
@@ -5051,15 +5051,16 @@
    int mode_mask = RelocInfo::kCodeTargetMask |
                    RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
                    RelocInfo::kApplyMask;
+  Assembler* origin = desc.origin;  // Needed to find target_object on X64.
    for (RelocIterator it(this, mode_mask); !it.done(); it.next()) {
      RelocInfo::Mode mode = it.rinfo()->rmode();
      if (mode == RelocInfo::EMBEDDED_OBJECT) {
-      Object** p = reinterpret_cast<Object**>(it.rinfo()->target_object());
+      Handle<Object> p = it.rinfo()->target_object_handle(origin);
        it.rinfo()->set_target_object(*p);
      } else if (RelocInfo::IsCodeTarget(mode)) {
        // rewrite code handles in inline cache targets to direct
        // pointers to the first instruction in the code object
-      Object** p = reinterpret_cast<Object**>(it.rinfo()->target_object());
+      Handle<Object> p = it.rinfo()->target_object_handle(origin);
        Code* code = Code::cast(*p);
        it.rinfo()->set_target_address(code->instruction_start());
      } else {
=======================================
--- /branches/bleeding_edge/src/serialize.cc    Mon Sep 28 05:25:21 2009
+++ /branches/bleeding_edge/src/serialize.cc    Tue Oct  6 06:11:05 2009
@@ -922,7 +922,9 @@
        serializer_(serializer),
        reference_encoder_(serializer->reference_encoder_),
        offsets_(8),
-      addresses_(8) {
+      addresses_(8),
+      offsets_32_bit_(0),
+      data_32_bit_(0) {
    }

    virtual void VisitPointers(Object** start, Object** end) {
@@ -939,9 +941,13 @@
      ASSERT(RelocInfo::IsCodeTarget(rinfo->rmode()));
      Code* target = Code::GetCodeFromTargetAddress(rinfo->target_address());
      Address encoded_target = serializer_->GetSavedAddress(target);
-    offsets_.Add(rinfo->target_address_address() - obj_address_);
-    addresses_.Add(encoded_target);
-  }
+    // All calls and jumps are to code objects that encode into 32 bits.
+    offsets_32_bit_.Add(rinfo->target_address_address() - obj_address_);
+    uint32_t small_target =
+        static_cast<uint32_t>(reinterpret_cast<uintptr_t>(encoded_target));
+    ASSERT(reinterpret_cast<uintptr_t>(encoded_target) == small_target);
+    data_32_bit_.Add(small_target);
+ }


    virtual void VisitExternalReferences(Address* start, Address* end) {
@@ -965,6 +971,10 @@
      for (int i = 0; i < offsets_.length(); i++) {
        memcpy(start_address + offsets_[i], &addresses_[i], sizeof(Address));
      }
+    for (int i = 0; i < offsets_32_bit_.length(); i++) {
+      memcpy(start_address + offsets_32_bit_[i], &data_32_bit_[i],
+             sizeof(uint32_t));
+    }
    }

   private:
@@ -973,6 +983,10 @@
    ExternalReferenceEncoder* reference_encoder_;
    List<int> offsets_;
    List<Address> addresses_;
+  // Some updates are 32-bit even on a 64-bit platform.
+  // We keep a separate list of them on 64-bit platforms.
+  List<int> offsets_32_bit_;
+  List<uint32_t> data_32_bit_;
  };


@@ -1432,7 +1446,9 @@

  void Deserializer::VisitCodeTarget(RelocInfo* rinfo) {
    ASSERT(RelocInfo::IsCodeTarget(rinfo->rmode()));
-  Address encoded_address =  
reinterpret_cast<Address>(rinfo->target_object());
+  // On all platforms, the encoded code object address is only 32 bits.
+  Address encoded_address = reinterpret_cast<Address>(Memory::uint32_at(
+      reinterpret_cast<Address>(rinfo->target_object_address())));
    Code* target_object = reinterpret_cast<Code*>(Resolve(encoded_address));
    rinfo->set_target_address(target_object->instruction_start());
  }
@@ -1663,7 +1679,6 @@

    // Encoded addresses of HeapObjects always have 'HeapObject' tags.
    ASSERT(o->IsHeapObject());
-
    switch (GetSpace(encoded)) {
      // For Map space and Old space, we cache the known Pages in map_pages,
      // old_pointer_pages and old_data_pages. Even though MapSpace keeps a  
list
=======================================
--- /branches/bleeding_edge/src/x64/assembler-x64-inl.h Thu Aug 27 23:18:36  
2009
+++ /branches/bleeding_edge/src/x64/assembler-x64-inl.h Tue Oct  6 06:11:05  
2009
@@ -68,6 +68,20 @@
    Memory::uint16_at(pc_) = x;
    pc_ += sizeof(uint16_t);
  }
+
+
+void Assembler::emit_code_target(Handle<Code> target, RelocInfo::Mode  
rmode) {
+  ASSERT(RelocInfo::IsCodeTarget(rmode));
+  RecordRelocInfo(rmode);
+  int current = code_targets_.length();
+  if (current > 0 && code_targets_.last().is_identical_to(target)) {
+    // Optimization if we keep jumping to the same code target.
+    emitl(current - 1);
+  } else {
+    code_targets_.Add(target);
+    emitl(current);
+  }
+}


  void Assembler::emit_rex_64(Register reg, Register rm_reg) {
@@ -162,15 +176,18 @@


  Address Assembler::target_address_at(Address pc) {
-  return Memory::Address_at(pc);
+  return Memory::int32_at(pc) + pc + 4;
  }


  void Assembler::set_target_address_at(Address pc, Address target) {
-  Memory::Address_at(pc) = target;
-  CPU::FlushICache(pc, sizeof(intptr_t));
+  Memory::int32_at(pc) = target - pc - 4;
+  CPU::FlushICache(pc, sizeof(int32_t));
  }

+Handle<Object> Assembler::code_target_object_handle_at(Address pc) {
+  return code_targets_[Memory::int32_at(pc)];
+}

  //  
-----------------------------------------------------------------------------
  // Implementation of RelocInfo
@@ -179,15 +196,24 @@
  void RelocInfo::apply(intptr_t delta) {
    if (IsInternalReference(rmode_)) {
      // absolute code pointer inside code object moves with the code object.
-    intptr_t* p = reinterpret_cast<intptr_t*>(pc_);
-    *p += delta;  // relocate entry
+    Memory::Address_at(pc_) += delta;
+  } else if (IsCodeTarget(rmode_)) {
+    Memory::int32_at(pc_) -= delta;
+  } else if (rmode_ == JS_RETURN && IsCallInstruction()) {
+    // Special handling of js_return when a break point is set (call
+    // instruction has been inserted).
+    Memory::int32_at(pc_ + 1) -= delta;  // relocate entry
    }
  }


  Address RelocInfo::target_address() {
    ASSERT(IsCodeTarget(rmode_) || rmode_ == RUNTIME_ENTRY);
-  return Assembler::target_address_at(pc_);
+  if (IsCodeTarget(rmode_)) {
+    return Assembler::target_address_at(pc_);
+  } else {
+    return Memory::Address_at(pc_);
+  }
  }


@@ -199,13 +225,27 @@

  void RelocInfo::set_target_address(Address target) {
    ASSERT(IsCodeTarget(rmode_) || rmode_ == RUNTIME_ENTRY);
-  Assembler::set_target_address_at(pc_, target);
+  if (IsCodeTarget(rmode_)) {
+    Assembler::set_target_address_at(pc_, target);
+  } else {
+    Memory::Address_at(pc_) = target;
+  }
  }


  Object* RelocInfo::target_object() {
    ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
-  return *reinterpret_cast<Object**>(pc_);
+  return Memory::Object_at(pc_);
+}
+
+
+Handle<Object> RelocInfo::target_object_handle(Assembler *origin) {
+  ASSERT(IsCodeTarget(rmode_) || rmode_ == EMBEDDED_OBJECT);
+  if (rmode_ == EMBEDDED_OBJECT) {
+    return Memory::Object_Handle_at(pc_);
+  } else {
+    return origin->code_target_object_handle_at(pc_);
+  }
  }


@@ -240,16 +280,15 @@

  Address RelocInfo::call_address() {
    ASSERT(IsCallInstruction());
-  return Assembler::target_address_at(
-      pc_ + Assembler::kPatchReturnSequenceAddressOffset);
+  return Memory::Address_at(
+      pc_ + Assembler::kRealPatchReturnSequenceAddressOffset);
  }


  void RelocInfo::set_call_address(Address target) {
    ASSERT(IsCallInstruction());
-  Assembler::set_target_address_at(
-      pc_ + Assembler::kPatchReturnSequenceAddressOffset,
-      target);
+  Memory::Address_at(pc_ +  
Assembler::kRealPatchReturnSequenceAddressOffset) =
+      target;
  }


=======================================
--- /branches/bleeding_edge/src/x64/assembler-x64.cc    Thu Sep 10 05:59:01  
2009
+++ /branches/bleeding_edge/src/x64/assembler-x64.cc    Tue Oct  6 06:11:05  
2009
@@ -264,7 +264,8 @@

  byte* Assembler::spare_buffer_ = NULL;

-Assembler::Assembler(void* buffer, int buffer_size) {
+Assembler::Assembler(void* buffer, int buffer_size)
+    : code_targets_(100) {
    if (buffer == NULL) {
      // do our own buffer management
      if (buffer_size <= kMinimalBufferSize) {
@@ -760,6 +761,15 @@
      L->link_to(current);
    }
  }
+
+
+void Assembler::call(Handle<Code> target, RelocInfo::Mode rmode) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  // 1110 1000 #32-bit disp
+  emit(0xE8);
+  emit_code_target(target, rmode);
+}


  void Assembler::call(Register adr) {
@@ -1060,6 +1070,19 @@
      L->link_to(current);
    }
  }
+
+
+void Assembler::j(Condition cc,
+                  Handle<Code> target,
+                  RelocInfo::Mode rmode) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  ASSERT(is_uint4(cc));
+  // 0000 1111 1000 tttn #32-bit disp
+  emit(0x0F);
+  emit(0x80 | cc);
+  emit_code_target(target, rmode);
+}


  void Assembler::jmp(Label* L) {
@@ -1091,6 +1114,15 @@
      L->link_to(current);
    }
  }
+
+
+void Assembler::jmp(Handle<Code> target, RelocInfo::Mode rmode) {
+  EnsureSpace ensure_space(this);
+  last_pc_ = pc_;
+  // 1110 1001 #32-bit disp
+  emit(0xE9);
+  emit_code_target(target, rmode);
+}


  void Assembler::jmp(Register target) {
@@ -2387,7 +2419,8 @@
  }


-const int RelocInfo::kApplyMask = 1 << RelocInfo::INTERNAL_REFERENCE;
-
+const int RelocInfo::kApplyMask = RelocInfo::kCodeTargetMask |
+                                  1 << RelocInfo::INTERNAL_REFERENCE |
+                                  1 << RelocInfo::JS_RETURN;

  } }  // namespace v8::internal
=======================================
--- /branches/bleeding_edge/src/x64/assembler-x64.h     Wed Sep 23 06:04:07 2009
+++ /branches/bleeding_edge/src/x64/assembler-x64.h     Tue Oct  6 06:11:05 2009
@@ -440,18 +440,26 @@
    // Assembler functions are invoked in between GetCode() calls.
    void GetCode(CodeDesc* desc);

-  // Read/Modify the code target in the branch/call instruction at pc.
-  // On the x64 architecture, the address is absolute, not relative.
+  // Read/Modify the code target in the relative branch/call instruction  
at pc.
+  // On the x64 architecture, we use relative jumps with a 32-bit  
displacement
+  // to jump to other Code objects in the Code space in the heap.
+  // Jumps to C functions are done indirectly through a 64-bit register  
holding
+  // the absolute address of the target.
+  // These functions convert between absolute Addresses of Code objects and
+  // the relative displacements stored in the code.
    static inline Address target_address_at(Address pc);
    static inline void set_target_address_at(Address pc, Address target);
-
+  inline Handle<Object> code_target_object_handle_at(Address pc);
    // Distance between the address of the code target in the call  
instruction
-  // and the return address.  Checked in the debug build.
-  static const int kCallTargetAddressOffset = 3 + kPointerSize;
-  // Distance between start of patched return sequence and the emitted  
address
-  // to jump to (movq = REX.W 0xB8+r.).
-  static const int kPatchReturnSequenceAddressOffset = 2;
-
+  // and the return address pushed on the stack.
+  static const int kCallTargetAddressOffset = 4;  // Use 32-bit  
displacement.
+  // Distance between the start of the JS return sequence and where the
+  // 32-bit displacement of a near call would be, relative to the pushed
+  // return address.  TODO: Use return sequence length instead.
+  // Should equal Debug::kX64JSReturnSequenceLength -  
kCallTargetAddressOffset;
+  static const int kPatchReturnSequenceAddressOffset = 13 - 4;
+  // TODO(X64): Rename this, removing the "Real", after changing the above.
+  static const int kRealPatchReturnSequenceAddressOffset = 2;
    //  
---------------------------------------------------------------------------
    // Code generation
    //
@@ -923,6 +931,7 @@
    // Calls
    // Call near relative 32-bit displacement, relative to next instruction.
    void call(Label* L);
+  void call(Handle<Code> target, RelocInfo::Mode rmode);

    // Call near absolute indirect, address in register
    void call(Register adr);
@@ -932,7 +941,9 @@

    // Jumps
    // Jump short or near relative.
+  // Use a 32-bit signed displacement.
    void jmp(Label* L);  // unconditional jump to L
+  void jmp(Handle<Code> target, RelocInfo::Mode rmode);

    // Jump near absolute indirect (r64)
    void jmp(Register adr);
@@ -942,6 +953,7 @@

    // Conditional jumps
    void j(Condition cc, Label* L);
+  void j(Condition cc, Handle<Code> target, RelocInfo::Mode rmode);

    // Floating-point operations
    void fld(int i);
@@ -1047,14 +1059,6 @@
    void RecordStatementPosition(int pos);
    void WriteRecordedPositions();

-  // Writes a doubleword of data in the code stream.
-  // Used for inline tables, e.g., jump-tables.
-  // void dd(uint32_t data);
-
-  // Writes a quadword of data in the code stream.
-  // Used for inline tables, e.g., jump-tables.
-  // void dd(uint64_t data, RelocInfo::Mode reloc_info);
-
    int pc_offset() const  { return pc_ - buffer_; }
    int current_statement_position() const { return  
current_statement_position_; }
    int current_position() const  { return current_position_; }
@@ -1096,9 +1100,9 @@

    void emit(byte x) { *pc_++ = x; }
    inline void emitl(uint32_t x);
-  inline void emit(Handle<Object> handle);
    inline void emitq(uint64_t x, RelocInfo::Mode rmode);
    inline void emitw(uint16_t x);
+  inline void emit_code_target(Handle<Code> target, RelocInfo::Mode rmode);
    void emit(Immediate x) { emitl(x.value_); }

    // Emits a REX prefix that encodes a 64-bit operand size and
@@ -1276,6 +1280,7 @@
    byte* pc_;  // the program counter; moves forward
    RelocInfoWriter reloc_info_writer;

+  List< Handle<Code> > code_targets_;
    // push-pop elimination
    byte* last_pc_;

=======================================
--- /branches/bleeding_edge/src/x64/macro-assembler-x64.cc      Wed Sep 30  
13:18:40 2009
+++ /branches/bleeding_edge/src/x64/macro-assembler-x64.cc      Tue Oct  6  
06:11:05 2009
@@ -348,8 +348,7 @@
    // Set the entry point and jump to the C entry runtime stub.
    movq(rbx, ext);
    CEntryStub ces(result_size);
-  movq(kScratchRegister, ces.GetCode(), RelocInfo::CODE_TARGET);
-  jmp(kScratchRegister);
+  jmp(ces.GetCode(), RelocInfo::CODE_TARGET);
  }


@@ -1270,17 +1269,8 @@


  void MacroAssembler::Jump(Handle<Code> code_object, RelocInfo::Mode rmode)  
{
-  ASSERT(RelocInfo::IsCodeTarget(rmode));
-  movq(kScratchRegister, code_object, rmode);
-#ifdef DEBUG
-  Label target;
-  bind(&target);
-#endif
-  jmp(kScratchRegister);
-#ifdef DEBUG
-  ASSERT_EQ(kCallTargetAddressOffset,
-            SizeOfCodeGeneratedSince(&target) + kPointerSize);
-#endif
+  // TODO(X64): Inline this
+  jmp(code_object, rmode);
  }


@@ -1299,17 +1289,7 @@
  void MacroAssembler::Call(Handle<Code> code_object, RelocInfo::Mode rmode)  
{
    ASSERT(RelocInfo::IsCodeTarget(rmode));
    WriteRecordedPositions();
-  movq(kScratchRegister, code_object, rmode);
-#ifdef DEBUG
-  // Patch target is kPointer size bytes *before* target label.
-  Label target;
-  bind(&target);
-#endif
-  call(kScratchRegister);
-#ifdef DEBUG
-  ASSERT_EQ(kCallTargetAddressOffset,
-            SizeOfCodeGeneratedSince(&target) + kPointerSize);
-#endif
+  call(code_object, rmode);
  }


@@ -1576,7 +1556,7 @@
    if (!resolved) {
      uint32_t flags =
          Bootstrapper::FixupFlagsArgumentsCount::encode(argc) |
-        Bootstrapper::FixupFlagsIsPCRelative::encode(false) |
+        Bootstrapper::FixupFlagsIsPCRelative::encode(true) |
          Bootstrapper::FixupFlagsUseCodeObject::encode(false);
      Unresolved entry =
          { pc_offset() - kCallTargetAddressOffset, flags, name };

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

Reply via email to