Revision: 5309
Author: [email protected]
Date: Fri Aug 20 00:10:18 2010
Log: Change code pointer in function objects to a pointer to the first
instruction.

By changing the pointer to the code object to a pointer to the first
instruction we can call directly this instruction directly instead of
looking up the address through the code object.

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

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

=======================================
--- /branches/bleeding_edge/src/arm/builtins-arm.cc     Wed Aug 11 06:48:58 2010
+++ /branches/bleeding_edge/src/arm/builtins-arm.cc     Fri Aug 20 00:10:18 2010
@@ -1073,8 +1073,7 @@
   __ ldr(r2,
FieldMemOperand(r3, SharedFunctionInfo::kFormalParameterCountOffset));
   __ mov(r2, Operand(r2, ASR, kSmiTagSize));
-  __ ldr(r3, FieldMemOperand(r1, JSFunction::kCodeOffset));
-  __ add(r3, r3, Operand(Code::kHeaderSize - kHeapObjectTag));
+  __ ldr(r3, FieldMemOperand(r1, JSFunction::kCodeEntryOffset));
   __ cmp(r2, r0);  // Check formal and actual parameter counts.
   __ Jump(Handle<Code>(builtin(ArgumentsAdaptorTrampoline)),
           RelocInfo::CODE_TARGET, ne);
=======================================
--- /branches/bleeding_edge/src/arm/codegen-arm.cc      Mon Aug 16 09:06:46 2010
+++ /branches/bleeding_edge/src/arm/codegen-arm.cc      Fri Aug 20 00:10:18 2010
@@ -1556,7 +1556,8 @@
   __ CompareObjectType(r0, r1, r2, JS_FUNCTION_TYPE);
   __ b(ne, &build_args);
   Handle<Code> apply_code(Builtins::builtin(Builtins::FunctionApply));
-  __ ldr(r1, FieldMemOperand(r0, JSFunction::kCodeOffset));
+  __ ldr(r1, FieldMemOperand(r0, JSFunction::kCodeEntryOffset));
+  __ sub(r1, r1, Operand(Code::kHeaderSize - kHeapObjectTag));
   __ cmp(r1, Operand(apply_code));
   __ b(ne, &build_args);

@@ -7028,7 +7029,8 @@
   // Initialize the code pointer in the function to be the one
   // found in the shared function info object.
   __ ldr(r3, FieldMemOperand(r3, SharedFunctionInfo::kCodeOffset));
-  __ str(r3, FieldMemOperand(r0, JSFunction::kCodeOffset));
+  __ add(r3, r3, Operand(Code::kHeaderSize - kHeapObjectTag));
+  __ str(r3, FieldMemOperand(r0, JSFunction::kCodeEntryOffset));

   // Return result. The argument function info has been popped already.
   __ Ret();
=======================================
--- /branches/bleeding_edge/src/arm/macro-assembler-arm.cc Mon Aug 16 09:06:46 2010 +++ /branches/bleeding_edge/src/arm/macro-assembler-arm.cc Fri Aug 20 00:10:18 2010
@@ -757,8 +757,7 @@
                       SharedFunctionInfo::kFormalParameterCountOffset));
   mov(expected_reg, Operand(expected_reg, ASR, kSmiTagSize));
   ldr(code_reg,
-      MemOperand(r1, JSFunction::kCodeOffset - kHeapObjectTag));
-  add(code_reg, code_reg, Operand(Code::kHeaderSize - kHeapObjectTag));
+      FieldMemOperand(r1, JSFunction::kCodeEntryOffset));

   ParameterCount expected(expected_reg);
   InvokeCode(code_reg, expected, actual, flag);
@@ -1490,30 +1489,22 @@
 }


-void MacroAssembler::GetBuiltinEntry(Register target, Builtins::JavaScript id) {
-  ASSERT(!target.is(r1));
-
+void MacroAssembler::GetBuiltinFunction(Register target,
+                                        Builtins::JavaScript id) {
   // Load the builtins object into target register.
   ldr(target, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX)));
   ldr(target, FieldMemOperand(target, GlobalObject::kBuiltinsOffset));
-
   // Load the JavaScript builtin function from the builtins object.
-  ldr(r1, FieldMemOperand(target,
+  ldr(target, FieldMemOperand(target,
                           JSBuiltinsObject::OffsetOfFunctionWithId(id)));
-
+}
+
+
+void MacroAssembler::GetBuiltinEntry(Register target, Builtins::JavaScript id) {
+  ASSERT(!target.is(r1));
+  GetBuiltinFunction(r1, id);
   // Load the code entry point from the builtins object.
-  ldr(target, FieldMemOperand(target,
-                              JSBuiltinsObject::OffsetOfCodeWithId(id)));
-  if (FLAG_debug_code) {
-    // Make sure the code objects in the builtins object and in the
-    // builtin function are the same.
-    push(r1);
-    ldr(r1, FieldMemOperand(r1, JSFunction::kCodeOffset));
-    cmp(r1, target);
-    Assert(eq, "Builtin code object changed");
-    pop(r1);
-  }
-  add(target, target, Operand(Code::kHeaderSize - kHeapObjectTag));
+  ldr(target, FieldMemOperand(r1, JSFunction::kCodeEntryOffset));
 }


=======================================
--- /branches/bleeding_edge/src/arm/macro-assembler-arm.h Mon Aug 16 09:06:46 2010 +++ /branches/bleeding_edge/src/arm/macro-assembler-arm.h Fri Aug 20 00:10:18 2010
@@ -576,6 +576,9 @@
   // setup the function in r1.
   void GetBuiltinEntry(Register target, Builtins::JavaScript id);

+  // Store the function for the given builtin in the target register.
+  void GetBuiltinFunction(Register target, Builtins::JavaScript id);
+
   Handle<Object> CodeObject() { return code_object_; }


=======================================
--- /branches/bleeding_edge/src/ia32/builtins-ia32.cc Wed Aug 11 06:48:58 2010 +++ /branches/bleeding_edge/src/ia32/builtins-ia32.cc Fri Aug 20 00:10:18 2010
@@ -567,9 +567,8 @@
   __ mov(edx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
   __ mov(ebx,
FieldOperand(edx, SharedFunctionInfo::kFormalParameterCountOffset));
+  __ mov(edx, FieldOperand(edi, JSFunction::kCodeEntryOffset));
   __ SmiUntag(ebx);
-  __ mov(edx, FieldOperand(edi, JSFunction::kCodeOffset));
-  __ lea(edx, FieldOperand(edx, Code::kHeaderSize));
   __ cmp(eax, Operand(ebx));
   __ j(not_equal, Handle<Code>(builtin(ArgumentsAdaptorTrampoline)));

=======================================
--- /branches/bleeding_edge/src/ia32/codegen-ia32.cc Mon Aug 16 09:06:46 2010 +++ /branches/bleeding_edge/src/ia32/codegen-ia32.cc Fri Aug 20 00:10:18 2010
@@ -3423,8 +3423,10 @@
       __ j(zero, &build_args);
       __ CmpObjectType(eax, JS_FUNCTION_TYPE, ecx);
       __ j(not_equal, &build_args);
+      __ mov(ecx, FieldOperand(eax, JSFunction::kCodeEntryOffset));
+      __ sub(Operand(ecx), Immediate(Code::kHeaderSize - kHeapObjectTag));
       Handle<Code> apply_code(Builtins::builtin(Builtins::FunctionApply));
- __ cmp(FieldOperand(eax, JSFunction::kCodeOffset), Immediate(apply_code));
+      __ cmp(Operand(ecx), Immediate(apply_code));
       __ j(not_equal, &build_args);

       // Check that applicand is a function.
@@ -9815,7 +9817,8 @@
   // Initialize the code pointer in the function to be the one
   // found in the shared function info object.
   __ mov(edx, FieldOperand(edx, SharedFunctionInfo::kCodeOffset));
-  __ mov(FieldOperand(eax, JSFunction::kCodeOffset), edx);
+  __ lea(edx, FieldOperand(edx, Code::kHeaderSize));
+  __ mov(FieldOperand(eax, JSFunction::kCodeEntryOffset), edx);

   // Return and remove the on-stack parameter.
   __ ret(1 * kPointerSize);
=======================================
--- /branches/bleeding_edge/src/ia32/macro-assembler-ia32.cc Mon Aug 16 09:06:46 2010 +++ /branches/bleeding_edge/src/ia32/macro-assembler-ia32.cc Fri Aug 20 00:10:18 2010
@@ -1298,11 +1298,10 @@
   mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
mov(ebx, FieldOperand(edx, SharedFunctionInfo::kFormalParameterCountOffset));
   SmiUntag(ebx);
-  mov(edx, FieldOperand(edi, JSFunction::kCodeOffset));
-  lea(edx, FieldOperand(edx, Code::kHeaderSize));

   ParameterCount expected(ebx);
-  InvokeCode(Operand(edx), expected, actual, flag);
+  InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset),
+             expected, actual, flag);
 }


@@ -1313,7 +1312,6 @@
   // Get the function and setup the context.
   mov(edi, Immediate(Handle<JSFunction>(function)));
   mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
-
   // Invoke the cached code.
   Handle<Code> code(function->code());
   ParameterCount expected(function->shared()->formal_parameter_count());
@@ -1329,33 +1327,26 @@
   // arguments match the expected number of arguments. Fake a
   // parameter count to avoid emitting code to do the check.
   ParameterCount expected(0);
-  GetBuiltinEntry(edx, id);
-  InvokeCode(Operand(edx), expected, expected, flag);
+  GetBuiltinFunction(edi, id);
+  InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset),
+           expected, expected, flag);
 }

-
-void MacroAssembler::GetBuiltinEntry(Register target, Builtins::JavaScript id) {
-  ASSERT(!target.is(edi));
-
-  // Load the builtins object into target register.
+void MacroAssembler::GetBuiltinFunction(Register target,
+                                        Builtins::JavaScript id) {
+  // Load the JavaScript builtin function from the builtins object.
   mov(target, Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX)));
   mov(target, FieldOperand(target, GlobalObject::kBuiltinsOffset));
-
+  mov(target, FieldOperand(target,
+                           JSBuiltinsObject::OffsetOfFunctionWithId(id)));
+}
+
+void MacroAssembler::GetBuiltinEntry(Register target, Builtins::JavaScript id) {
+  ASSERT(!target.is(edi));
   // Load the JavaScript builtin function from the builtins object.
- mov(edi, FieldOperand(target, JSBuiltinsObject::OffsetOfFunctionWithId(id)));
-
-  // Load the code entry point from the builtins object.
- mov(target, FieldOperand(target, JSBuiltinsObject::OffsetOfCodeWithId(id)));
-  if (FLAG_debug_code) {
-    // Make sure the code objects in the builtins object and in the
-    // builtin function are the same.
-    push(target);
-    mov(target, FieldOperand(edi, JSFunction::kCodeOffset));
-    cmp(target, Operand(esp, 0));
-    Assert(equal, "Builtin code object changed");
-    pop(target);
-  }
-  lea(target, FieldOperand(target, Code::kHeaderSize));
+  GetBuiltinFunction(edi, id);
+  // Load the code entry point from the function into the target register.
+  mov(target, FieldOperand(edi, JSFunction::kCodeEntryOffset));
 }


=======================================
--- /branches/bleeding_edge/src/ia32/macro-assembler-ia32.h Mon Aug 16 09:06:46 2010 +++ /branches/bleeding_edge/src/ia32/macro-assembler-ia32.h Fri Aug 20 00:10:18 2010
@@ -169,6 +169,9 @@
   // the unresolved list if the name does not resolve.
   void InvokeBuiltin(Builtins::JavaScript id, InvokeFlag flag);

+  // Store the function for the given builtin in the target register.
+  void GetBuiltinFunction(Register target, Builtins::JavaScript id);
+
   // Store the code object for the given builtin in the target register.
   void GetBuiltinEntry(Register target, Builtins::JavaScript id);

=======================================
--- /branches/bleeding_edge/src/liveedit.cc     Fri Aug 13 06:54:28 2010
+++ /branches/bleeding_edge/src/liveedit.cc     Fri Aug 20 00:10:18 2010
@@ -750,7 +750,7 @@
 class ReferenceCollectorVisitor : public ObjectVisitor {
  public:
   explicit ReferenceCollectorVisitor(Code* original)
-      : original_(original), rvalues_(10), reloc_infos_(10) {
+ : original_(original), rvalues_(10), reloc_infos_(10), code_entries_(10) {
   }

   virtual void VisitPointers(Object** start, Object** end) {
@@ -761,7 +761,13 @@
     }
   }

-  void VisitCodeTarget(RelocInfo* rinfo) {
+  virtual void VisitCodeEntry(Address entry) {
+    if (Code::GetObjectFromEntryAddress(entry) == original_) {
+      code_entries_.Add(entry);
+    }
+  }
+
+  virtual void VisitCodeTarget(RelocInfo* rinfo) {
     if (RelocInfo::IsCodeTarget(rinfo->rmode()) &&
Code::GetCodeFromTargetAddress(rinfo->target_address()) == original_) {
       reloc_infos_.Add(*rinfo);
@@ -778,8 +784,13 @@
     for (int i = 0; i < rvalues_.length(); i++) {
       *(rvalues_[i]) = substitution;
     }
+    Address substitution_entry = substitution->instruction_start();
     for (int i = 0; i < reloc_infos_.length(); i++) {
- reloc_infos_[i].set_target_address(substitution->instruction_start());
+      reloc_infos_[i].set_target_address(substitution_entry);
+    }
+    for (int i = 0; i < code_entries_.length(); i++) {
+      Address entry = code_entries_[i];
+      Memory::Address_at(entry) = substitution_entry;
     }
   }

@@ -787,6 +798,7 @@
   Code* original_;
   ZoneList<Object**> rvalues_;
   ZoneList<RelocInfo> reloc_infos_;
+  ZoneList<Address> code_entries_;
 };


=======================================
--- /branches/bleeding_edge/src/mark-compact.cc Tue Aug 17 05:10:27 2010
+++ /branches/bleeding_edge/src/mark-compact.cc Fri Aug 20 00:10:18 2010
@@ -255,10 +255,9 @@

   static void EnableCodeFlushing(bool enabled) {
     if (enabled) {
-      table_.Register(kVisitJSFunction, &VisitJSFunction);
+      table_.Register(kVisitJSFunction, &VisitJSFunctionAndFlushCode);
     } else {
-      table_.Register(kVisitJSFunction,
- &JSObjectVisitor::VisitSpecialized<JSFunction::kSize>);
+      table_.Register(kVisitJSFunction, &VisitJSFunction);
     }
   }

@@ -299,7 +298,7 @@

     table_.Register(kVisitCode, &VisitCode);

-    table_.Register(kVisitJSFunction, &VisitJSFunction);
+    table_.Register(kVisitJSFunction, &VisitJSFunctionAndFlushCode);

     table_.Register(kVisitPropertyCell,
                     &FixedBodyVisitor<StaticMarkingVisitor,
@@ -534,16 +533,42 @@
   }


-  static void VisitJSFunction(Map* map, HeapObject* object) {
-    JSFunction* jsfunction = reinterpret_cast<JSFunction*>(object);
-
+  static void VisitCodeEntry(Address entry_address) {
+    Object* code = Code::GetObjectFromEntryAddress(entry_address);
+    Object* old_code = code;
+    VisitPointer(&code);
+    if (code != old_code) {
+      Memory::Address_at(entry_address) =
+          reinterpret_cast<Code*>(code)->entry();
+    }
+  }
+
+
+  static void VisitJSFunctionAndFlushCode(Map* map, HeapObject* object) {
+    JSFunction* jsfunction = reinterpret_cast<JSFunction*>(object);
     // The function must have a valid context and not be a builtin.
     if (IsValidNotBuiltinContext(jsfunction->unchecked_context())) {
       FlushCodeForFunction(jsfunction);
     }
-
-    JSObjectVisitor::VisitSpecialized<JSFunction::kSize>(map, object);
-  }
+    VisitJSFunction(map, object);
+  }
+
+
+  static void VisitJSFunction(Map* map, HeapObject* object) {
+#define SLOT_ADDR(obj, offset)   \
+    reinterpret_cast<Object**>((obj)->address() + offset)
+
+    VisitPointers(SLOT_ADDR(object, JSFunction::kPropertiesOffset),
+                  SLOT_ADDR(object, JSFunction::kCodeEntryOffset));
+
+    VisitCodeEntry(object->address() + JSFunction::kCodeEntryOffset);
+
+    VisitPointers(SLOT_ADDR(object,
+                            JSFunction::kCodeEntryOffset + kPointerSize),
+                  SLOT_ADDR(object, JSFunction::kSize));
+#undef SLOT_ADDR
+  }
+

   typedef void (*Callback)(Map* map, HeapObject* object);

=======================================
--- /branches/bleeding_edge/src/objects-inl.h   Wed Aug 18 06:00:38 2010
+++ /branches/bleeding_edge/src/objects-inl.h   Fri Aug 20 00:10:18 2010
@@ -35,9 +35,10 @@
 #ifndef V8_OBJECTS_INL_H_
 #define V8_OBJECTS_INL_H_

-#include "objects.h"
+#include "memory.h"
 #include "contexts.h"
 #include "conversions-inl.h"
+#include "objects.h"
 #include "property.h"

 namespace v8 {
@@ -2408,6 +2409,12 @@
   Code* result = reinterpret_cast<Code*>(code);
   return result;
 }
+
+
+Object* Code::GetObjectFromEntryAddress(Address location_of_address) {
+  return HeapObject::
+ FromAddress(Memory::Address_at(location_of_address) - Code::kHeaderSize);
+}


 Object* Map::prototype() {
@@ -2739,19 +2746,21 @@


 Code* JSFunction::code() {
-  return Code::cast(READ_FIELD(this, kCodeOffset));
+  return Code::cast(unchecked_code());
 }


 Code* JSFunction::unchecked_code() {
-  return reinterpret_cast<Code*>(READ_FIELD(this, kCodeOffset));
+  return reinterpret_cast<Code*>(
+      Code::GetObjectFromEntryAddress(FIELD_ADDR(this, kCodeEntryOffset)));
 }


 void JSFunction::set_code(Code* value) {
   // Skip the write barrier because code is never in new space.
   ASSERT(!Heap::InNewSpace(value));
-  WRITE_FIELD(this, kCodeOffset, value);
+  Address entry = value->entry();
+ WRITE_INTPTR_FIELD(this, kCodeEntryOffset, reinterpret_cast<intptr_t>(entry));
 }


=======================================
--- /branches/bleeding_edge/src/objects.cc      Thu Aug 19 06:28:28 2010
+++ /branches/bleeding_edge/src/objects.cc      Fri Aug 20 00:10:18 2010
@@ -1066,12 +1066,15 @@
     case JS_VALUE_TYPE:
     case JS_ARRAY_TYPE:
     case JS_REGEXP_TYPE:
-    case JS_FUNCTION_TYPE:
     case JS_GLOBAL_PROXY_TYPE:
     case JS_GLOBAL_OBJECT_TYPE:
     case JS_BUILTINS_OBJECT_TYPE:
       JSObject::BodyDescriptor::IterateBody(this, object_size, v);
       break;
+    case JS_FUNCTION_TYPE:
+      reinterpret_cast<JSFunction*>(this)
+          ->JSFunctionIterateBody(object_size, v);
+      break;
     case ODDBALL_TYPE:
       Oddball::BodyDescriptor::IterateBody(this, v);
       break;
@@ -4986,6 +4989,15 @@
     }
   }
 }
+
+
+void JSFunction::JSFunctionIterateBody(int object_size, ObjectVisitor* v) {
+  // Iterate over all fields in the body but take care in dealing with
+  // the code entry.
+  IteratePointers(v, kPropertiesOffset, kCodeEntryOffset);
+  v->VisitCodeEntry(this->address() + kCodeEntryOffset);
+  IteratePointers(v, kCodeEntryOffset + kPointerSize, object_size);
+}


 Object* JSFunction::SetInstancePrototype(Object* value) {
@@ -5002,7 +5014,6 @@
   Heap::ClearInstanceofCache();
   return value;
 }
-


 Object* JSFunction::SetPrototype(Object* value) {
@@ -5230,6 +5241,16 @@
   VisitPointer(&target);
CHECK_EQ(target, old_target); // VisitPointer doesn't change Code* *target.
 }
+
+
+void ObjectVisitor::VisitCodeEntry(Address entry_address) {
+  Object* code = Code::GetObjectFromEntryAddress(entry_address);
+  Object* old_code = code;
+  VisitPointer(&code);
+  if (code != old_code) {
+ Memory::Address_at(entry_address) = reinterpret_cast<Code*>(code)->entry();
+  }
+}


 void ObjectVisitor::VisitDebugTarget(RelocInfo* rinfo) {
=======================================
--- /branches/bleeding_edge/src/objects.h       Thu Aug 19 06:28:28 2010
+++ /branches/bleeding_edge/src/objects.h       Fri Aug 20 00:10:18 2010
@@ -2883,6 +2883,9 @@
   // Convert a target address into a code object.
   static inline Code* GetCodeFromTargetAddress(Address address);

+  // Convert an entry address into an object.
+ static inline Object* GetObjectFromEntryAddress(Address location_of_address);
+
   // Returns the address of the first instruction.
   inline byte* instruction_start();

@@ -3705,6 +3708,10 @@
   // Casting.
   static inline JSFunction* cast(Object* obj);

+  // Iterates the objects, including code objects indirectly referenced
+  // through pointers to the first instruction in the code object.
+  void JSFunctionIterateBody(int object_size, ObjectVisitor* v);
+
   // Dispatched behavior.
 #ifdef DEBUG
   void JSFunctionPrint();
@@ -3718,9 +3725,9 @@
   static Context* GlobalContextFromLiterals(FixedArray* literals);

   // Layout descriptors.
-  static const int kCodeOffset = JSObject::kHeaderSize;
+  static const int kCodeEntryOffset = JSObject::kHeaderSize;
   static const int kPrototypeOrInitialMapOffset =
-      kCodeOffset + kPointerSize;
+      kCodeEntryOffset + kPointerSize;
   static const int kSharedFunctionInfoOffset =
       kPrototypeOrInitialMapOffset + kPointerSize;
static const int kContextOffset = kSharedFunctionInfoOffset + kPointerSize;
@@ -5435,6 +5442,9 @@
   // Visits a code target in the instruction stream.
   virtual void VisitCodeTarget(RelocInfo* rinfo);

+  // Visits a code entry in a JS function.
+  virtual void VisitCodeEntry(Address entry_address);
+
   // Visits a runtime entry in the instruction stream.
   virtual void VisitRuntimeEntry(RelocInfo* rinfo) {}

=======================================
--- /branches/bleeding_edge/src/serialize.cc    Wed Aug 11 07:30:14 2010
+++ /branches/bleeding_edge/src/serialize.cc    Fri Aug 20 00:10:18 2010
@@ -831,6 +831,12 @@
CASE_STATEMENT(where, how, within, kLargeFixedArray) \
   CASE_BODY(where, how, within, kAnyOldSpace, kUnknownOffsetFromStart)

+#define ONE_PER_CODE_SPACE(where, how, within) \ + CASE_STATEMENT(where, how, within, CODE_SPACE) \ + CASE_BODY(where, how, within, CODE_SPACE, kUnknownOffsetFromStart) \ + CASE_STATEMENT(where, how, within, kLargeCode) \
+  CASE_BODY(where, how, within, LO_SPACE, kUnknownOffsetFromStart)
+
#define EMIT_COMMON_REFERENCE_PATTERNS(pseudo_space_number, \ space_number, \ offset_from_start) \
@@ -862,6 +868,8 @@
       // Deserialize a new object and write a pointer to it to the current
       // object.
       ONE_PER_SPACE(kNewObject, kPlain, kStartOfObject)
+      // Support for direct instruction pointers in functions
+      ONE_PER_CODE_SPACE(kNewObject, kPlain, kFirstInstruction)
       // Deserialize a new code object and write a pointer to its first
       // instruction to the current code object.
       ONE_PER_SPACE(kNewObject, kFromCode, kFirstInstruction)
@@ -870,11 +878,14 @@
       ALL_SPACES(kBackref, kPlain, kStartOfObject)
       // Find a recently deserialized code object using its offset from the
// current allocation point and write a pointer to its first instruction
-      // to the current code object.
+ // to the current code object or the instruction pointer in a function
+      // object.
       ALL_SPACES(kBackref, kFromCode, kFirstInstruction)
+      ALL_SPACES(kBackref, kPlain, kFirstInstruction)
// Find an already deserialized object using its offset from the start
       // and write a pointer to it to the current object.
       ALL_SPACES(kFromStart, kPlain, kStartOfObject)
+      ALL_SPACES(kFromStart, kPlain, kFirstInstruction)
       // Find an already deserialized code object using its offset from the
// start and write a pointer to its first instruction to the current code
       // object.
@@ -893,6 +904,14 @@
                 kPlain,
                 kStartOfObject,
                 0,
+                kUnknownOffsetFromStart)
+      // Find an code entry in the partial snapshots cache and
+      // write a pointer to it to the current object.
+      CASE_STATEMENT(kPartialSnapshotCache, kPlain, kFirstInstruction, 0)
+      CASE_BODY(kPartialSnapshotCache,
+                kPlain,
+                kFirstInstruction,
+                0,
                 kUnknownOffsetFromStart)
// Find an external reference and write a pointer to it to the current
       // object.
@@ -1334,6 +1353,14 @@
   serializer_->SerializeObject(target, kFromCode, kFirstInstruction);
   bytes_processed_so_far_ += rinfo->target_address_size();
 }
+
+
+void Serializer::ObjectSerializer::VisitCodeEntry(Address entry_address) {
+ Code* target = Code::cast(Code::GetObjectFromEntryAddress(entry_address));
+  OutputRawData(entry_address);
+  serializer_->SerializeObject(target, kPlain, kFirstInstruction);
+  bytes_processed_so_far_ += kPointerSize;
+}


 void Serializer::ObjectSerializer::VisitExternalAsciiString(
=======================================
--- /branches/bleeding_edge/src/serialize.h     Mon Aug 16 09:06:46 2010
+++ /branches/bleeding_edge/src/serialize.h     Fri Aug 20 00:10:18 2010
@@ -448,6 +448,7 @@
     void VisitPointers(Object** start, Object** end);
     void VisitExternalReferences(Address* start, Address* end);
     void VisitCodeTarget(RelocInfo* target);
+    void VisitCodeEntry(Address entry_address);
     void VisitRuntimeEntry(RelocInfo* reloc);
// Used for seralizing the external strings that hold the natives source.
     void VisitExternalAsciiString(
=======================================
--- /branches/bleeding_edge/src/x64/builtins-x64.cc     Wed Aug 11 06:48:58 2010
+++ /branches/bleeding_edge/src/x64/builtins-x64.cc     Fri Aug 20 00:10:18 2010
@@ -310,8 +310,7 @@
   __ movsxlq(rbx,
              FieldOperand(rdx,
SharedFunctionInfo::kFormalParameterCountOffset));
-  __ movq(rdx, FieldOperand(rdi, JSFunction::kCodeOffset));
-  __ lea(rdx, FieldOperand(rdx, Code::kHeaderSize));
+  __ movq(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset));
   __ cmpq(rax, rbx);
   __ j(not_equal,
        Handle<Code>(builtin(ArgumentsAdaptorTrampoline)),
=======================================
--- /branches/bleeding_edge/src/x64/codegen-x64.cc      Mon Aug 16 09:06:46 2010
+++ /branches/bleeding_edge/src/x64/codegen-x64.cc      Fri Aug 20 00:10:18 2010
@@ -2616,8 +2616,10 @@
       __ j(is_smi, &build_args);
       __ CmpObjectType(rax, JS_FUNCTION_TYPE, rcx);
       __ j(not_equal, &build_args);
+      __ movq(rcx, FieldOperand(rax, JSFunction::kCodeEntryOffset));
+      __ subq(rcx, Immediate(Code::kHeaderSize - kHeapObjectTag));
       Handle<Code> apply_code(Builtins::builtin(Builtins::FunctionApply));
-      __ Cmp(FieldOperand(rax, JSFunction::kCodeOffset), apply_code);
+ __ Cmp(FieldOperand(rcx, SharedFunctionInfo::kCodeOffset), apply_code);
       __ j(not_equal, &build_args);

       // Check that applicand is a function.
@@ -8758,7 +8760,8 @@
   // Initialize the code pointer in the function to be the one
   // found in the shared function info object.
   __ movq(rdx, FieldOperand(rdx, SharedFunctionInfo::kCodeOffset));
-  __ movq(FieldOperand(rax, JSFunction::kCodeOffset), rdx);
+  __ lea(rdx, FieldOperand(rdx, Code::kHeaderSize));
+  __ movq(FieldOperand(rax, JSFunction::kCodeEntryOffset), rdx);


   // Return and remove the on-stack parameter.
=======================================
--- /branches/bleeding_edge/src/x64/macro-assembler-x64.cc Mon Aug 16 09:06:46 2010 +++ /branches/bleeding_edge/src/x64/macro-assembler-x64.cc Fri Aug 20 00:10:18 2010
@@ -581,28 +581,21 @@
 }


-void MacroAssembler::GetBuiltinEntry(Register target, Builtins::JavaScript id) {
-  ASSERT(!target.is(rdi));
-
+void MacroAssembler::GetBuiltinFunction(Register target,
+                                        Builtins::JavaScript id) {
   // Load the builtins object into target register.
   movq(target, Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX)));
   movq(target, FieldOperand(target, GlobalObject::kBuiltinsOffset));
-
-  // Load the JavaScript builtin function from the builtins object.
- movq(rdi, FieldOperand(target, JSBuiltinsObject::OffsetOfFunctionWithId(id)));
-
-  // Load the code entry point from the builtins object.
- movq(target, FieldOperand(target, JSBuiltinsObject::OffsetOfCodeWithId(id)));
-  if (FLAG_debug_code) {
-    // Make sure the code objects in the builtins object and in the
-    // builtin function are the same.
-    push(target);
-    movq(target, FieldOperand(rdi, JSFunction::kCodeOffset));
-    cmpq(target, Operand(rsp, 0));
-    Assert(equal, "Builtin code object changed");
-    pop(target);
-  }
-  lea(target, FieldOperand(target, Code::kHeaderSize));
+  movq(target, FieldOperand(target,
+                            JSBuiltinsObject::OffsetOfFunctionWithId(id)));
+}
+
+
+void MacroAssembler::GetBuiltinEntry(Register target, Builtins::JavaScript id) {
+  ASSERT(!target.is(rdi));
+  // Load the JavaScript builtin function from the builtins object.
+  GetBuiltinFunction(rdi, id);
+  movq(target, FieldOperand(rdi, JSFunction::kCodeEntryOffset));
 }


@@ -2311,10 +2304,9 @@
   movq(rsi, FieldOperand(function, JSFunction::kContextOffset));
   movsxlq(rbx,
FieldOperand(rdx, SharedFunctionInfo::kFormalParameterCountOffset));
-  movq(rdx, FieldOperand(rdi, JSFunction::kCodeOffset));
   // Advances rdx to the end of the Code object header, to the start of
   // the executable code.
-  lea(rdx, FieldOperand(rdx, Code::kHeaderSize));
+  movq(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset));

   ParameterCount expected(rbx);
   InvokeCode(rdx, expected, actual, flag);
=======================================
--- /branches/bleeding_edge/src/x64/macro-assembler-x64.h Mon Aug 16 09:06:46 2010 +++ /branches/bleeding_edge/src/x64/macro-assembler-x64.h Fri Aug 20 00:10:18 2010
@@ -203,6 +203,9 @@
   // the unresolved list if the name does not resolve.
   void InvokeBuiltin(Builtins::JavaScript id, InvokeFlag flag);

+  // Store the function for the given builtin in the target register.
+  void GetBuiltinFunction(Register target, Builtins::JavaScript id);
+
   // Store the code object for the given builtin in the target register.
   void GetBuiltinEntry(Register target, Builtins::JavaScript id);

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

Reply via email to