Revision: 5233
Author: [email protected]
Date: Wed Aug 11 01:12:53 2010
Log: Put direct code pointers into JSFunction objects. This is a first step
in allowing more flexible compilation and to simplify builtins lookup.

This changes a number of places where code objects are assigned to
SharedFunctionInfo objects to also assign this code object to the
JSFunction. In addition, the code flushing is changed slightly to
accomodate this (we need to flush the code from functions pointing to
SharedFunctionInfo objects that has already been flushed).


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

Modified:
 /branches/bleeding_edge/src/accessors.cc
 /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/bootstrapper.cc
 /branches/bleeding_edge/src/factory.cc
 /branches/bleeding_edge/src/handles.cc
 /branches/bleeding_edge/src/heap.cc
 /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/objects-inl.h
 /branches/bleeding_edge/src/objects.h
 /branches/bleeding_edge/src/runtime.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/accessors.cc    Wed Jul 14 04:18:09 2010
+++ /branches/bleeding_edge/src/accessors.cc    Wed Aug 11 01:12:53 2010
@@ -488,7 +488,7 @@
JSFunction* function = FindInPrototypeChain<JSFunction>(object, &found_it);
   if (!found_it) return Smi::FromInt(0);
   // Check if already compiled.
-  if (!function->is_compiled()) {
+  if (!function->shared()->is_compiled()) {
     // If the function isn't compiled yet, the length is not computed
     // correctly yet. Compile it now and return the right length.
     HandleScope scope;
=======================================
--- /branches/bleeding_edge/src/arm/builtins-arm.cc     Mon Jun 14 04:20:36 2010
+++ /branches/bleeding_edge/src/arm/builtins-arm.cc     Wed Aug 11 01:12:53 2010
@@ -1050,7 +1050,7 @@
   __ ldr(r2,
FieldMemOperand(r3, SharedFunctionInfo::kFormalParameterCountOffset));
   __ mov(r2, Operand(r2, ASR, kSmiTagSize));
-  __ ldr(r3, FieldMemOperand(r3, SharedFunctionInfo::kCodeOffset));
+  __ ldr(r3, FieldMemOperand(r1, JSFunction::kCodeOffset));
   __ add(r3, r3, Operand(Code::kHeaderSize - kHeapObjectTag));
   __ cmp(r2, r0);  // Check formal and actual parameter counts.
   __ Jump(Handle<Code>(builtin(ArgumentsAdaptorTrampoline)),
=======================================
--- /branches/bleeding_edge/src/arm/codegen-arm.cc      Tue Aug 10 04:52:18 2010
+++ /branches/bleeding_edge/src/arm/codegen-arm.cc      Wed Aug 11 01:12:53 2010
@@ -1532,9 +1532,8 @@
   __ BranchOnSmi(r0, &build_args);
   __ CompareObjectType(r0, r1, r2, JS_FUNCTION_TYPE);
   __ b(ne, &build_args);
-  __ ldr(r0, FieldMemOperand(r0, JSFunction::kSharedFunctionInfoOffset));
   Handle<Code> apply_code(Builtins::builtin(Builtins::FunctionApply));
-  __ ldr(r1, FieldMemOperand(r0, SharedFunctionInfo::kCodeOffset));
+  __ ldr(r1, FieldMemOperand(r0, JSFunction::kCodeOffset));
   __ cmp(r1, Operand(apply_code));
   __ b(ne, &build_args);

@@ -6858,6 +6857,11 @@
   __ str(cp, FieldMemOperand(r0, JSFunction::kContextOffset));
   __ str(r1, FieldMemOperand(r0, JSFunction::kLiteralsOffset));

+  // 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));
+
   // Return result. The argument function info has been popped already.
   __ Ret();

=======================================
--- /branches/bleeding_edge/src/arm/macro-assembler-arm.cc Fri Aug 6 06:04:27 2010 +++ /branches/bleeding_edge/src/arm/macro-assembler-arm.cc Wed Aug 11 01:12:53 2010
@@ -757,7 +757,7 @@
                       SharedFunctionInfo::kFormalParameterCountOffset));
   mov(expected_reg, Operand(expected_reg, ASR, kSmiTagSize));
   ldr(code_reg,
- MemOperand(code_reg, SharedFunctionInfo::kCodeOffset - kHeapObjectTag));
+      MemOperand(r1, JSFunction::kCodeOffset - kHeapObjectTag));
   add(code_reg, code_reg, Operand(Code::kHeaderSize - kHeapObjectTag));

   ParameterCount expected(expected_reg);
@@ -1508,8 +1508,7 @@
     // Make sure the code objects in the builtins object and in the
     // builtin function are the same.
     push(r1);
-    ldr(r1, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
-    ldr(r1, FieldMemOperand(r1, SharedFunctionInfo::kCodeOffset));
+    ldr(r1, FieldMemOperand(r1, JSFunction::kCodeOffset));
     cmp(r1, target);
     Assert(eq, "Builtin code object changed");
     pop(r1);
=======================================
--- /branches/bleeding_edge/src/bootstrapper.cc Mon Aug  2 08:08:17 2010
+++ /branches/bleeding_edge/src/bootstrapper.cc Wed Aug 11 01:12:53 2010
@@ -470,6 +470,7 @@
   Handle<Code> code =
       Handle<Code>(Builtins::builtin(Builtins::EmptyFunction));
   empty_function->set_code(*code);
+  empty_function->shared()->set_code(*code);
   Handle<String> source = Factory::NewStringFromAscii(CStrVector("() {}"));
   Handle<Script> script = Factory::NewScript(source);
   script->set_type(Smi::FromInt(Script::TYPE_NATIVE));
@@ -1545,6 +1546,8 @@
     Handle<SharedFunctionInfo> shared
         = Handle<SharedFunctionInfo>(function->shared());
     if (!EnsureCompiled(shared, CLEAR_EXCEPTION)) return false;
+    // Set the code object on the function object.
+    function->set_code(function->shared()->code());
     builtins->set_javascript_builtin_code(id, shared->code());
   }
   return true;
=======================================
--- /branches/bleeding_edge/src/factory.cc      Wed Jul 14 04:18:09 2010
+++ /branches/bleeding_edge/src/factory.cc      Wed Aug 11 01:12:53 2010
@@ -486,6 +486,10 @@
                                         bool force_initial_map) {
   // Allocate the function
   Handle<JSFunction> function = NewFunction(name, the_hole_value());
+
+  // Setup the code pointer in both the shared function info and in
+  // the function itself.
+  function->shared()->set_code(*code);
   function->set_code(*code);

   if (force_initial_map ||
@@ -511,9 +515,12 @@
Handle<JSObject> prototype,
                                                      Handle<Code> code,
bool force_initial_map) {
-  // Allocate the function
+  // Allocate the function.
   Handle<JSFunction> function = NewFunction(name, prototype);

+  // Setup the code pointer in both the shared function info and in
+  // the function itself.
+  function->shared()->set_code(*code);
   function->set_code(*code);

   if (force_initial_map ||
@@ -535,6 +542,7 @@
Handle<JSFunction> Factory::NewFunctionWithoutPrototype(Handle<String> name, Handle<Code> code) {
   Handle<JSFunction> function = NewFunctionWithoutPrototype(name);
+  function->shared()->set_code(*code);
   function->set_code(*code);
   ASSERT(!function->has_initial_map());
   ASSERT(!function->has_prototype());
=======================================
--- /branches/bleeding_edge/src/handles.cc      Mon Jul 19 05:45:21 2010
+++ /branches/bleeding_edge/src/handles.cc      Wed Aug 11 01:12:53 2010
@@ -771,20 +771,30 @@
 bool CompileLazy(Handle<JSFunction> function,
                  Handle<Object> receiver,
                  ClearExceptionFlag flag) {
-  CompilationInfo info(function, 0, receiver);
-  bool result = CompileLazyHelper(&info, flag);
-  PROFILE(FunctionCreateEvent(*function));
-  return result;
+  if (function->shared()->is_compiled()) {
+    function->set_code(function->shared()->code());
+    return true;
+  } else {
+    CompilationInfo info(function, 0, receiver);
+    bool result = CompileLazyHelper(&info, flag);
+    PROFILE(FunctionCreateEvent(*function));
+    return result;
+  }
 }


 bool CompileLazyInLoop(Handle<JSFunction> function,
                        Handle<Object> receiver,
                        ClearExceptionFlag flag) {
-  CompilationInfo info(function, 1, receiver);
-  bool result = CompileLazyHelper(&info, flag);
-  PROFILE(FunctionCreateEvent(*function));
-  return result;
+  if (function->shared()->is_compiled()) {
+    function->set_code(function->shared()->code());
+    return true;
+  } else {
+    CompilationInfo info(function, 1, receiver);
+    bool result = CompileLazyHelper(&info, flag);
+    PROFILE(FunctionCreateEvent(*function));
+    return result;
+  }
 }


=======================================
--- /branches/bleeding_edge/src/heap.cc Thu Aug  5 07:12:50 2010
+++ /branches/bleeding_edge/src/heap.cc Wed Aug 11 01:12:53 2010
@@ -2452,39 +2452,62 @@
 };


-static void FlushCodeForFunction(SharedFunctionInfo* function_info) {
+static bool CodeIsActive(Code* code) {
+  // Make sure we are not referencing the code from the stack.
+  for (StackFrameIterator it; !it.done(); it.Advance()) {
+    if (code->contains(it.frame()->pc())) return true;
+  }
+  // Iterate the archived stacks in all threads to check if
+  // the code is referenced.
+  FlushingStackVisitor threadvisitor(code);
+  ThreadManager::IterateArchivedThreads(&threadvisitor);
+  if (threadvisitor.FoundCode()) return true;
+  return false;
+}
+
+
+static void FlushCodeForFunction(JSFunction* function) {
+  SharedFunctionInfo* shared_info = function->shared();
+
+  // Special handling if the function and shared info objects
+  // have different code objects.
+  if (function->code() != shared_info->code()) {
+    // If the shared function has been flushed but the function has not,
+    // we flush the function if possible.
+    if (!shared_info->is_compiled() && function->is_compiled() &&
+        !CodeIsActive(function->code())) {
+      function->set_code(shared_info->code());
+    }
+    return;
+  }
+
   // The function must be compiled and have the source code available,
   // to be able to recompile it in case we need the function again.
- if (!(function_info->is_compiled() && function_info->HasSourceCode())) return; + if (!(shared_info->is_compiled() && shared_info->HasSourceCode())) return;

   // We never flush code for Api functions.
-  if (function_info->IsApiFunction()) return;
+  if (shared_info->IsApiFunction()) return;

   // Only flush code for functions.
-  if (!function_info->code()->kind() == Code::FUNCTION) return;
+  if (!shared_info->code()->kind() == Code::FUNCTION) return;

   // Function must be lazy compilable.
-  if (!function_info->allows_lazy_compilation()) return;
+  if (!shared_info->allows_lazy_compilation()) return;

// If this is a full script wrapped in a function we do no flush the code.
-  if (function_info->is_toplevel()) return;
+  if (shared_info->is_toplevel()) return;

   // If this function is in the compilation cache we do not flush the code.
-  if (CompilationCache::HasFunction(function_info)) return;
-
-  // Make sure we are not referencing the code from the stack.
-  for (StackFrameIterator it; !it.done(); it.Advance()) {
-    if (function_info->code()->contains(it.frame()->pc())) return;
-  }
-  // Iterate the archived stacks in all threads to check if
-  // the code is referenced.
-  FlushingStackVisitor threadvisitor(function_info->code());
-  ThreadManager::IterateArchivedThreads(&threadvisitor);
-  if (threadvisitor.FoundCode()) return;
+  if (CompilationCache::HasFunction(shared_info)) return;
+
+  // Check stack and archived threads for the code.
+  if (CodeIsActive(shared_info->code())) return;

   // Compute the lazy compilable version of the code.
   HandleScope scope;
-  function_info->set_code(*ComputeLazyCompile(function_info->length()));
+  Code* code = *ComputeLazyCompile(shared_info->length());
+  shared_info->set_code(code);
+  function->set_code(code);
 }


@@ -2496,12 +2519,12 @@
   HeapObjectIterator it(old_pointer_space());
   for (HeapObject* obj = it.next(); obj != NULL; obj = it.next()) {
     if (obj->IsJSFunction()) {
-      JSFunction* jsfunction = JSFunction::cast(obj);
+      JSFunction* function = JSFunction::cast(obj);

       // The function must have a valid context and not be a builtin.
-      if (jsfunction->unchecked_context()->IsContext() &&
-          !jsfunction->IsBuiltin()) {
-        FlushCodeForFunction(jsfunction->shared());
+      if (function->unchecked_context()->IsContext() &&
+          !function->IsBuiltin()) {
+        FlushCodeForFunction(function);
       }
     }
   }
@@ -2651,6 +2674,7 @@
   function->initialize_properties();
   function->initialize_elements();
   function->set_shared(shared);
+  function->set_code(shared->code());
   function->set_prototype_or_initial_map(prototype);
   function->set_context(undefined_value());
   function->set_literals(empty_fixed_array());
=======================================
--- /branches/bleeding_edge/src/ia32/builtins-ia32.cc Fri Jun 4 03:46:04 2010 +++ /branches/bleeding_edge/src/ia32/builtins-ia32.cc Wed Aug 11 01:12:53 2010
@@ -548,7 +548,7 @@
   __ mov(ebx,
FieldOperand(edx, SharedFunctionInfo::kFormalParameterCountOffset));
   __ SmiUntag(ebx);
-  __ mov(edx, FieldOperand(edx, SharedFunctionInfo::kCodeOffset));
+  __ 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 Tue Aug 10 05:30:14 2010 +++ /branches/bleeding_edge/src/ia32/codegen-ia32.cc Wed Aug 11 01:12:53 2010
@@ -3435,10 +3435,8 @@
       __ j(zero, &build_args);
       __ CmpObjectType(eax, JS_FUNCTION_TYPE, ecx);
       __ j(not_equal, &build_args);
- __ mov(ecx, FieldOperand(eax, JSFunction::kSharedFunctionInfoOffset));
       Handle<Code> apply_code(Builtins::builtin(Builtins::FunctionApply));
-      __ cmp(FieldOperand(ecx, SharedFunctionInfo::kCodeOffset),
-             Immediate(apply_code));
+ __ cmp(FieldOperand(eax, JSFunction::kCodeOffset), Immediate(apply_code));
       __ j(not_equal, &build_args);

       // Check that applicand is a function.
@@ -9690,6 +9688,11 @@
   __ mov(FieldOperand(eax, JSFunction::kContextOffset), esi);
   __ mov(FieldOperand(eax, JSFunction::kLiteralsOffset), ebx);

+  // 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);
+
   // Return and remove the on-stack parameter.
   __ ret(1 * kPointerSize);

=======================================
--- /branches/bleeding_edge/src/ia32/macro-assembler-ia32.cc Mon Aug 9 06:12:02 2010 +++ /branches/bleeding_edge/src/ia32/macro-assembler-ia32.cc Wed Aug 11 01:12:53 2010
@@ -1298,7 +1298,7 @@
   mov(esi, FieldOperand(edi, JSFunction::kContextOffset));
mov(ebx, FieldOperand(edx, SharedFunctionInfo::kFormalParameterCountOffset));
   SmiUntag(ebx);
-  mov(edx, FieldOperand(edx, SharedFunctionInfo::kCodeOffset));
+  mov(edx, FieldOperand(edi, JSFunction::kCodeOffset));
   lea(edx, FieldOperand(edx, Code::kHeaderSize));

   ParameterCount expected(ebx);
@@ -1350,8 +1350,7 @@
     // Make sure the code objects in the builtins object and in the
     // builtin function are the same.
     push(target);
-    mov(target, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
-    mov(target, FieldOperand(target, SharedFunctionInfo::kCodeOffset));
+    mov(target, FieldOperand(edi, JSFunction::kCodeOffset));
     cmp(target, Operand(esp, 0));
     Assert(equal, "Builtin code object changed");
     pop(target);
=======================================
--- /branches/bleeding_edge/src/objects-inl.h   Mon Aug  2 08:08:17 2010
+++ /branches/bleeding_edge/src/objects-inl.h   Wed Aug 11 01:12:53 2010
@@ -2694,12 +2694,14 @@


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


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


@@ -2771,7 +2773,7 @@


 bool JSFunction::is_compiled() {
-  return shared()->is_compiled();
+  return code()->kind() != Code::STUB;
 }


=======================================
--- /branches/bleeding_edge/src/objects.h       Fri Aug  6 06:04:27 2010
+++ /branches/bleeding_edge/src/objects.h       Wed Aug 11 01:12:53 2010
@@ -3608,7 +3608,9 @@
   static Context* GlobalContextFromLiterals(FixedArray* literals);

   // Layout descriptors.
-  static const int kPrototypeOrInitialMapOffset = JSObject::kHeaderSize;
+  static const int kCodeOffset = JSObject::kHeaderSize;
+  static const int kPrototypeOrInitialMapOffset =
+      kCodeOffset + kPointerSize;
   static const int kSharedFunctionInfoOffset =
       kPrototypeOrInitialMapOffset + kPointerSize;
static const int kContextOffset = kSharedFunctionInfoOffset + kPointerSize;
=======================================
--- /branches/bleeding_edge/src/runtime.cc      Tue Aug 10 05:44:13 2010
+++ /branches/bleeding_edge/src/runtime.cc      Wed Aug 11 01:12:53 2010
@@ -1627,7 +1627,8 @@
     }
     // Set the code, scope info, formal parameter count,
     // and the length of the target function.
-    target->set_code(fun->code());
+    target->shared()->set_code(shared->code());
+    target->set_code(shared->code());
     target->shared()->set_scope_info(shared->scope_info());
     target->shared()->set_length(shared->length());
     target->shared()->set_formal_parameter_count(
@@ -6870,7 +6871,7 @@

   Handle<JSFunction> function = args.at<JSFunction>(0);
 #ifdef DEBUG
-  if (FLAG_trace_lazy) {
+  if (FLAG_trace_lazy && !function->shared()->is_compiled()) {
     PrintF("[lazy: ");
     function->shared()->name()->Print();
     PrintF("]\n");
=======================================
--- /branches/bleeding_edge/src/serialize.h     Thu May 20 12:58:05 2010
+++ /branches/bleeding_edge/src/serialize.h     Wed Aug 11 01:12:53 2010
@@ -248,7 +248,7 @@
   }

   static int partial_snapshot_cache_length_;
-  static const int kPartialSnapshotCacheCapacity = 1300;
+  static const int kPartialSnapshotCacheCapacity = 1350;
   static Object* partial_snapshot_cache_[];
 };

=======================================
--- /branches/bleeding_edge/src/x64/builtins-x64.cc     Wed Jul 21 23:31:49 2010
+++ /branches/bleeding_edge/src/x64/builtins-x64.cc     Wed Aug 11 01:12:53 2010
@@ -310,7 +310,7 @@
   __ movsxlq(rbx,
              FieldOperand(rdx,
SharedFunctionInfo::kFormalParameterCountOffset));
-  __ movq(rdx, FieldOperand(rdx, SharedFunctionInfo::kCodeOffset));
+  __ movq(rdx, FieldOperand(rdi, JSFunction::kCodeOffset));
   __ lea(rdx, FieldOperand(rdx, Code::kHeaderSize));
   __ cmpq(rax, rbx);
   __ j(not_equal,
=======================================
--- /branches/bleeding_edge/src/x64/codegen-x64.cc      Fri Aug  6 06:04:27 2010
+++ /branches/bleeding_edge/src/x64/codegen-x64.cc      Wed Aug 11 01:12:53 2010
@@ -2630,9 +2630,8 @@
       __ j(is_smi, &build_args);
       __ CmpObjectType(rax, JS_FUNCTION_TYPE, rcx);
       __ j(not_equal, &build_args);
- __ movq(rax, FieldOperand(rax, JSFunction::kSharedFunctionInfoOffset));
       Handle<Code> apply_code(Builtins::builtin(Builtins::FunctionApply));
- __ Cmp(FieldOperand(rax, SharedFunctionInfo::kCodeOffset), apply_code);
+      __ Cmp(FieldOperand(rax, JSFunction::kCodeOffset), apply_code);
       __ j(not_equal, &build_args);

       // Check that applicand is a function.
@@ -8635,6 +8634,12 @@
   __ movq(FieldOperand(rax, JSFunction::kContextOffset), rsi);
   __ movq(FieldOperand(rax, JSFunction::kLiteralsOffset), rbx);

+  // 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);
+
+
   // Return and remove the on-stack parameter.
   __ ret(1 * kPointerSize);

=======================================
--- /branches/bleeding_edge/src/x64/macro-assembler-x64.cc Fri Aug 6 06:04:27 2010 +++ /branches/bleeding_edge/src/x64/macro-assembler-x64.cc Wed Aug 11 01:12:53 2010
@@ -582,8 +582,7 @@
     // Make sure the code objects in the builtins object and in the
     // builtin function are the same.
     push(target);
-    movq(target, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset));
-    movq(target, FieldOperand(target, SharedFunctionInfo::kCodeOffset));
+    movq(target, FieldOperand(rdi, JSFunction::kCodeOffset));
     cmpq(target, Operand(rsp, 0));
     Assert(equal, "Builtin code object changed");
     pop(target);
@@ -2290,7 +2289,7 @@
   movq(rsi, FieldOperand(function, JSFunction::kContextOffset));
   movsxlq(rbx,
FieldOperand(rdx, SharedFunctionInfo::kFormalParameterCountOffset));
-  movq(rdx, FieldOperand(rdx, SharedFunctionInfo::kCodeOffset));
+  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));

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

Reply via email to