Revision: 16407
Author:   [email protected]
Date:     Wed Aug 28 16:48:40 2013 UTC
Log: Add OptimizedCodeEntry as a new heap object type. An optimized code entry represents an association between the native context, a function, optimized code, and the literals. Such associations are needed by the deoptimizer and optimized code cache to efficiently find related optimized code and functions for a given context or shared function info.

BUG=
[email protected]

Review URL: https://codereview.chromium.org/23691002
http://code.google.com/p/v8/source/detail?r=16407

Modified:
 /branches/bleeding_edge/include/v8.h
 /branches/bleeding_edge/src/factory.cc
 /branches/bleeding_edge/src/factory.h
 /branches/bleeding_edge/src/heap.cc
 /branches/bleeding_edge/src/heap.h
 /branches/bleeding_edge/src/objects-debug.cc
 /branches/bleeding_edge/src/objects-inl.h
 /branches/bleeding_edge/src/objects-printer.cc
 /branches/bleeding_edge/src/objects-visiting.cc
 /branches/bleeding_edge/src/objects-visiting.h
 /branches/bleeding_edge/src/objects.cc
 /branches/bleeding_edge/src/objects.h

=======================================
--- /branches/bleeding_edge/include/v8.h        Tue Aug 27 14:13:40 2013 UTC
+++ /branches/bleeding_edge/include/v8.h        Wed Aug 28 16:48:40 2013 UTC
@@ -5416,7 +5416,7 @@
   static const int kNullValueRootIndex = 7;
   static const int kTrueValueRootIndex = 8;
   static const int kFalseValueRootIndex = 9;
-  static const int kEmptyStringRootIndex = 133;
+  static const int kEmptyStringRootIndex = 134;

   static const int kNodeClassIdOffset = 1 * kApiPointerSize;
   static const int kNodeFlagsOffset = 1 * kApiPointerSize + 3;
@@ -5427,7 +5427,7 @@
   static const int kNodeIsIndependentShift = 4;
   static const int kNodeIsPartiallyDependentShift = 5;

-  static const int kJSObjectType = 0xb1;
+  static const int kJSObjectType = 0xb2;
   static const int kFirstNonstringType = 0x80;
   static const int kOddballType = 0x83;
   static const int kForeignType = 0x87;
=======================================
--- /branches/bleeding_edge/src/factory.cc      Fri Aug  9 08:22:46 2013 UTC
+++ /branches/bleeding_edge/src/factory.cc      Wed Aug 28 16:48:40 2013 UTC
@@ -1247,6 +1247,21 @@
                      isolate()->heap()->AllocateSharedFunctionInfo(*name),
                      SharedFunctionInfo);
 }
+
+
+Handle<OptimizedCodeEntry> Factory::NewOptimizedCodeEntry(
+      Handle<Context> native_context,
+      Handle<JSFunction> function,
+      Handle<Code> code,
+      Handle<FixedArray> literals) {
+  CALL_HEAP_FUNCTION(isolate(),
+                     isolate()->heap()->AllocateOptimizedCodeEntry(
+                         *native_context,
+                         *function,
+                         *code,
+                         *literals),
+                     OptimizedCodeEntry);
+}


 Handle<String> Factory::NumberToString(Handle<Object> number) {
=======================================
--- /branches/bleeding_edge/src/factory.h       Wed Aug  7 11:24:14 2013 UTC
+++ /branches/bleeding_edge/src/factory.h       Wed Aug 28 16:48:40 2013 UTC
@@ -487,6 +487,12 @@
       Handle<ScopeInfo> scope_info);
   Handle<SharedFunctionInfo> NewSharedFunctionInfo(Handle<String> name);

+  Handle<OptimizedCodeEntry> NewOptimizedCodeEntry(
+      Handle<Context> native_context,
+      Handle<JSFunction> function,
+      Handle<Code> code,
+      Handle<FixedArray> literals);
+
   Handle<JSMessageObject> NewJSMessageObject(
       Handle<String> type,
       Handle<JSArray> arguments,
=======================================
--- /branches/bleeding_edge/src/heap.cc Wed Aug 28 14:26:22 2013 UTC
+++ /branches/bleeding_edge/src/heap.cc Wed Aug 28 16:48:40 2013 UTC
@@ -2824,6 +2824,12 @@
   }
   set_shared_function_info_map(Map::cast(obj));

+  { MaybeObject* maybe_obj = AllocateMap(OPTIMIZED_CODE_ENTRY_TYPE,
+                                         OptimizedCodeEntry::kAlignedSize);
+    if (!maybe_obj->ToObject(&obj)) return false;
+  }
+  set_optimized_code_entry_map(Map::cast(obj));
+
   { MaybeObject* maybe_obj = AllocateMap(JS_MESSAGE_OBJECT_TYPE,
                                          JSMessageObject::kSize);
     if (!maybe_obj->ToObject(&obj)) return false;
@@ -3649,6 +3655,30 @@

   return share;
 }
+
+
+MaybeObject* Heap::AllocateOptimizedCodeEntry(
+      Context* native_context,
+      JSFunction* function,
+      Code* code,
+      FixedArray* literals) {
+  OptimizedCodeEntry* entry;
+ MaybeObject* maybe = Allocate(optimized_code_entry_map(), OLD_POINTER_SPACE);
+  if (!maybe->To<OptimizedCodeEntry>(&entry)) return maybe;
+
+  // Set pointer fields.
+  entry->set_native_context(native_context);
+  entry->set_function(function);
+  entry->set_code(code);
+  entry->set_literals(literals);
+
+  // NULL-out link fields.
+  entry->set_next_by_shared_info(NULL, SKIP_WRITE_BARRIER);
+  entry->set_next_by_native_context(NULL, SKIP_WRITE_BARRIER);
+  entry->set_cacheable(false);
+
+  return entry;
+}


 MaybeObject* Heap::AllocateJSMessageObject(String* type,
=======================================
--- /branches/bleeding_edge/src/heap.h  Thu Aug 22 16:14:37 2013 UTC
+++ /branches/bleeding_edge/src/heap.h  Wed Aug 28 16:48:40 2013 UTC
@@ -63,6 +63,7 @@
V(Map, cell_map, CellMap) \ V(Map, global_property_cell_map, GlobalPropertyCellMap) \ V(Map, shared_function_info_map, SharedFunctionInfoMap) \ + V(Map, optimized_code_entry_map, OptimizedCodeEntryMap) \ V(Map, meta_map, MetaMap) \ V(Map, heap_number_map, HeapNumberMap) \ V(Map, native_context_map, NativeContextMap) \
@@ -78,9 +79,9 @@
V(DescriptorArray, empty_descriptor_array, EmptyDescriptorArray) \ V(Smi, stack_limit, StackLimit) \ V(Oddball, arguments_marker, ArgumentsMarker) \ - /* The first 32 roots above this line should be boring from a GC point of */ \ - /* view. This means they are never in new space and never on a page that */ \ - /* is being compacted. */ \ + /* The roots above this line should be boring from a GC point of view. */ \ + /* This means they are never in new space and never on a page that is */ \ + /* being compacted. */ \ V(FixedArray, number_string_cache, NumberStringCache) \ V(Object, instanceof_cache_function, InstanceofCacheFunction) \ V(Object, instanceof_cache_map, InstanceofCacheMap) \
@@ -1097,6 +1098,16 @@
   // Please note this does not perform a garbage collection.
   MUST_USE_RESULT MaybeObject* AllocateSharedFunctionInfo(Object* name);

+  // Allocates a new OptimizedCodeEntry object.
+ // Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
+  // failed.
+  // Please note this does not perform a garbage collection.
+  MUST_USE_RESULT MaybeObject* AllocateOptimizedCodeEntry(
+      Context* native_context,
+      JSFunction* function,
+      Code* code,
+      FixedArray* literals);
+
   // Allocates a new JSMessageObject object.
// Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
   // failed.
=======================================
--- /branches/bleeding_edge/src/objects-debug.cc Mon Aug 26 11:59:14 2013 UTC +++ /branches/bleeding_edge/src/objects-debug.cc Wed Aug 28 16:48:40 2013 UTC
@@ -201,6 +201,9 @@
     case SHARED_FUNCTION_INFO_TYPE:
       SharedFunctionInfo::cast(this)->SharedFunctionInfoVerify();
       break;
+    case OPTIMIZED_CODE_ENTRY_TYPE:
+      OptimizedCodeEntry::cast(this)->OptimizedCodeEntryVerify();
+      break;
     case JS_MESSAGE_OBJECT_TYPE:
       JSMessageObject::cast(this)->JSMessageObjectVerify();
       break;
@@ -575,6 +578,17 @@
   VerifyObjectField(kScriptOffset);
   VerifyObjectField(kDebugInfoOffset);
 }
+
+
+void OptimizedCodeEntry::OptimizedCodeEntryVerify() {
+  CHECK(IsOptimizedCodeEntry());
+  VerifyObjectField(kNativeContextOffset);
+  VerifyObjectField(kFunctionOffset);
+  VerifyObjectField(kCodeOffset);
+  VerifyObjectField(kLiteralsOffset);
+  VerifyObjectField(kNextBySharedInfoOffset);
+  VerifyObjectField(kNextByNativeContextOffset);
+}


 void JSGlobalProxy::JSGlobalProxyVerify() {
=======================================
--- /branches/bleeding_edge/src/objects-inl.h   Wed Aug 28 14:26:22 2013 UTC
+++ /branches/bleeding_edge/src/objects-inl.h   Wed Aug 28 16:48:40 2013 UTC
@@ -675,6 +675,7 @@
 TYPE_CHECKER(Cell, CELL_TYPE)
 TYPE_CHECKER(PropertyCell, PROPERTY_CELL_TYPE)
 TYPE_CHECKER(SharedFunctionInfo, SHARED_FUNCTION_INFO_TYPE)
+TYPE_CHECKER(OptimizedCodeEntry, OPTIMIZED_CODE_ENTRY_TYPE)
 TYPE_CHECKER(JSGeneratorObject, JS_GENERATOR_OBJECT_TYPE)
 TYPE_CHECKER(JSModule, JS_MODULE_TYPE)
 TYPE_CHECKER(JSValue, JS_VALUE_TYPE)
@@ -2572,6 +2573,7 @@
 CAST_ACCESSOR(Cell)
 CAST_ACCESSOR(PropertyCell)
 CAST_ACCESSOR(SharedFunctionInfo)
+CAST_ACCESSOR(OptimizedCodeEntry)
 CAST_ACCESSOR(Map)
 CAST_ACCESSOR(JSFunction)
 CAST_ACCESSOR(GlobalObject)
@@ -4922,6 +4924,52 @@
     code()->set_optimizable(true);
   }
 }
+
+
+ACCESSORS(OptimizedCodeEntry, native_context, Context, kNativeContextOffset)
+ACCESSORS(OptimizedCodeEntry, function, JSFunction, kFunctionOffset)
+ACCESSORS(OptimizedCodeEntry, code, Code, kCodeOffset)
+ACCESSORS(OptimizedCodeEntry, literals, FixedArray, kLiteralsOffset)
+
+
+OptimizedCodeEntry* OptimizedCodeEntry::next_by_shared_info() {
+  Object* object = READ_FIELD(this, kNextBySharedInfoOffset);
+  if (object == NULL) return NULL;
+  return OptimizedCodeEntry::cast(object);
+}
+
+
+OptimizedCodeEntry* OptimizedCodeEntry::next_by_native_context() {
+  Object* object = READ_FIELD(this, kNextByNativeContextOffset);
+  if (object == NULL) return NULL;
+  return OptimizedCodeEntry::cast(object);
+}
+
+
+void OptimizedCodeEntry::set_next_by_shared_info(OptimizedCodeEntry* value,
+    WriteBarrierMode mode) {
+  WRITE_FIELD(this, kNextBySharedInfoOffset, value);
+  CONDITIONAL_WRITE_BARRIER(
+      GetHeap(), this, kNextBySharedInfoOffset, value, mode);
+}
+
+
+void OptimizedCodeEntry::set_next_by_native_context(OptimizedCodeEntry* value,
+    WriteBarrierMode mode) {
+  WRITE_FIELD(this, kNextByNativeContextOffset, value);
+  CONDITIONAL_WRITE_BARRIER(
+      GetHeap(), this, kNextByNativeContextOffset, value, mode);
+}
+
+
+bool OptimizedCodeEntry::cacheable() {
+  return static_cast<bool>(READ_BYTE_FIELD(this, kCacheableOffset));
+}
+
+
+void OptimizedCodeEntry::set_cacheable(bool val) {
+  WRITE_BYTE_FIELD(this, kCacheableOffset, static_cast<byte>(val));
+}


 bool JSFunction::IsBuiltin() {
=======================================
--- /branches/bleeding_edge/src/objects-printer.cc Mon Aug 26 11:59:14 2013 UTC +++ /branches/bleeding_edge/src/objects-printer.cc Wed Aug 28 16:48:40 2013 UTC
@@ -195,6 +195,9 @@
     case SHARED_FUNCTION_INFO_TYPE:
       SharedFunctionInfo::cast(this)->SharedFunctionInfoPrint(out);
       break;
+    case OPTIMIZED_CODE_ENTRY_TYPE:
+      OptimizedCodeEntry::cast(this)->OptimizedCodeEntryPrint(out);
+      break;
     case JS_MESSAGE_OBJECT_TYPE:
       JSMessageObject::cast(this)->JSMessageObjectPrint(out);
       break;
@@ -888,6 +891,25 @@
   optimized_code_map()->ShortPrint(out);
   PrintF(out, "\n");
 }
+
+
+void OptimizedCodeEntry::OptimizedCodeEntryPrint(FILE* out) {
+  HeapObject::PrintHeader(out, "OptimizedCodeEntry");
+  PrintF(out, "\n - native_context = ");
+  native_context()->ShortPrint(out);
+  PrintF(out, "\n - function = ");
+  function()->ShortPrint(out);
+  PrintF(out, "\n - code = ");
+  code()->ShortPrint(out);
+  PrintF(out, "\n - literals = ");
+  literals()->ShortPrint(out);
+  PrintF(out, "\n - next_by_shared_info = ");
+  next_by_shared_info()->ShortPrint(out);
+  PrintF(out, "\n - next_by_native_context = ");
+  next_by_native_context()->ShortPrint(out);
+  PrintF(out, "\n - cacheable = %s", cacheable() ? "true" : "false");
+  PrintF(out, "\n");
+}


 void JSGlobalProxy::JSGlobalProxyPrint(FILE* out) {
=======================================
--- /branches/bleeding_edge/src/objects-visiting.cc Mon Jul 22 08:32:24 2013 UTC +++ /branches/bleeding_edge/src/objects-visiting.cc Wed Aug 28 16:48:40 2013 UTC
@@ -119,6 +119,9 @@
     case SHARED_FUNCTION_INFO_TYPE:
       return kVisitSharedFunctionInfo;

+    case OPTIMIZED_CODE_ENTRY_TYPE:
+      return kVisitOptimizedCodeEntry;
+
     case JS_PROXY_TYPE:
       return GetVisitorIdForSize(kVisitStruct,
                                  kVisitStructGeneric,
=======================================
--- /branches/bleeding_edge/src/objects-visiting.h Mon Aug 5 12:52:53 2013 UTC +++ /branches/bleeding_edge/src/objects-visiting.h Wed Aug 28 16:48:40 2013 UTC
@@ -92,6 +92,7 @@
   V(Cell)                     \
   V(PropertyCell)             \
   V(SharedFunctionInfo)       \
+  V(OptimizedCodeEntry)       \
   V(JSFunction)               \
   V(JSWeakMap)                \
   V(JSWeakSet)                \
=======================================
--- /branches/bleeding_edge/src/objects.cc      Wed Aug 28 13:01:53 2013 UTC
+++ /branches/bleeding_edge/src/objects.cc      Wed Aug 28 16:48:40 2013 UTC
@@ -1786,6 +1786,10 @@
       SharedFunctionInfo::BodyDescriptor::IterateBody(this, v);
       break;
     }
+    case OPTIMIZED_CODE_ENTRY_TYPE: {
+      OptimizedCodeEntry::BodyDescriptor::IterateBody(this, v);
+      break;
+    }

 #define MAKE_STRUCT_CASE(NAME, Name, name) \
         case NAME##_TYPE:
@@ -9428,6 +9432,15 @@
     ClearOptimizedCodeMap();
   }
 }
+
+
+void OptimizedCodeEntry::Kill() {
+  set_function(NULL, SKIP_WRITE_BARRIER);
+  set_code(NULL, SKIP_WRITE_BARRIER);
+  set_native_context(NULL, SKIP_WRITE_BARRIER);
+  set_literals(NULL, SKIP_WRITE_BARRIER);
+  set_cacheable(false);
+}


 bool JSFunction::CompileLazy(Handle<JSFunction> function,
=======================================
--- /branches/bleeding_edge/src/objects.h       Wed Aug 28 14:26:22 2013 UTC
+++ /branches/bleeding_edge/src/objects.h       Wed Aug 28 16:48:40 2013 UTC
@@ -131,6 +131,7 @@
 //       - Oddball
 //       - Foreign
 //       - SharedFunctionInfo
+//       - OptimizedCodeEntry
 //       - Struct
 //         - Box
 //         - DeclaredAccessorDescriptor
@@ -406,6 +407,7 @@
V(FIXED_ARRAY_TYPE) \ V(FIXED_DOUBLE_ARRAY_TYPE) \ V(SHARED_FUNCTION_INFO_TYPE) \ + V(OPTIMIZED_CODE_ENTRY_TYPE) \ \ V(JS_MESSAGE_OBJECT_TYPE) \ \
@@ -756,6 +758,7 @@

   FIXED_ARRAY_TYPE,
   SHARED_FUNCTION_INFO_TYPE,
+  OPTIMIZED_CODE_ENTRY_TYPE,

   JS_MESSAGE_OBJECT_TYPE,

@@ -1017,6 +1020,7 @@
   V(Code)                                      \
   V(Oddball)                                   \
   V(SharedFunctionInfo)                        \
+  V(OptimizedCodeEntry)                        \
   V(JSValue)                                   \
   V(JSDate)                                    \
   V(JSMessageObject)                           \
@@ -6837,6 +6841,76 @@
 };


+// An optimized code entry represents an association between the native
+// context, a function, optimized code, and the literals. The entries
+// are linked into two lists for efficient lookup: by native context
+// (linked through next_by_native_context), or by shared function
+// info (linked through next_by_shared_info).
+// The references to the native context, function, and code are weak,
+// in order not to leak native contexts or functions through
+// SharedFunctionInfo. This means an entry can become "dead" through GC.
+// Entries are removed lazily as each list is traversed.
+class OptimizedCodeEntry: public HeapObject {
+ public:
+  // [native_context]: The native context of this entry. (WEAK)
+  DECL_ACCESSORS(native_context, Context)
+
+  // [function]: The JSFunction of this entry. (WEAK)
+  DECL_ACCESSORS(function, JSFunction)
+
+  // [code]: The optimized code of this entry. (WEAK)
+  DECL_ACCESSORS(code, Code)
+
+  // [literals]: Array of literals for this entry.
+  DECL_ACCESSORS(literals, FixedArray)
+
+  // [next_by_shared_info]: The next link in the list, when traversing
+  // starting with a SharedFunctionInfo. (NULL if none).
+  DECL_ACCESSORS(next_by_shared_info, OptimizedCodeEntry)
+
+  // [next_by_native_context]: The next link in the list, when traversing
+  // starting with a native context. (NULL if none)
+  DECL_ACCESSORS(next_by_native_context, OptimizedCodeEntry)
+
+  // Casting.
+  static inline OptimizedCodeEntry* cast(Object* obj);
+
+  DECLARE_PRINTER(OptimizedCodeEntry)
+  DECLARE_VERIFIER(OptimizedCodeEntry)
+
+  // Layout description.
+  static const int kNativeContextOffset = JSObject::kHeaderSize;
+  static const int kFunctionOffset = kNativeContextOffset + kPointerSize;
+  static const int kCodeOffset = kFunctionOffset + kPointerSize;
+  static const int kLiteralsOffset = kCodeOffset + kPointerSize;
+  static const int kNextBySharedInfoOffset =
+      kLiteralsOffset + kPointerSize;
+  static const int kNextByNativeContextOffset =
+      kNextBySharedInfoOffset + kPointerSize;
+ static const int kCacheableOffset = kNextByNativeContextOffset + kPointerSize;
+  static const int kSize = kCacheableOffset + kIntSize;
+  static const int kAlignedSize = OBJECT_POINTER_ALIGN(kSize);
+
+  typedef FixedBodyDescriptor<kLiteralsOffset,
+                              kNextByNativeContextOffset + kPointerSize,
+                              kSize> BodyDescriptor;
+
+ // Kills an entry, nulling out its references to native context, function,
+  // code, and literals.
+  void Kill();
+  inline bool cacheable();
+  inline void set_cacheable(bool val);
+
+ private:
+  // Used internally during traversal to skip dead entries.
+  inline bool IsDead() {
+    return function() == NULL || code() == NULL;
+  }
+
+  DISALLOW_IMPLICIT_CONSTRUCTORS(OptimizedCodeEntry);
+};
+
+
 class JSGeneratorObject: public JSObject {
  public:
   // [function]: The function corresponding to this generator object.

--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.

Reply via email to