Cache optimized code for OSR.
authoryangguo@chromium.org <yangguo@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 23 Dec 2013 14:42:42 +0000 (14:42 +0000)
committeryangguo@chromium.org <yangguo@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 23 Dec 2013 14:42:42 +0000 (14:42 +0000)
BUG=v8:2637
LOG=N
R=titzer@chromium.org, verwaest@chromium.org

Review URL: https://codereview.chromium.org/101853003

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@18410 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/code-stubs-hydrogen.cc
src/compiler.cc
src/factory.cc
src/hydrogen-instructions.h
src/mark-compact.cc
src/objects-inl.h
src/objects-visiting-inl.h
src/objects.cc
src/objects.h
src/transitions-inl.h

index dc1f1859850efe5b556a484c23f788f3003d9607..f66a9e3a27a37834927eb3322f82789c63265e61 100644 (file)
@@ -1194,9 +1194,14 @@ void CodeStubGraphBuilderBase::BuildInstallFromOptimizedCodeMap(
     Label install_optimized;
     HValue* first_context_slot = Add<HLoadNamedField>(optimized_map,
         HObjectAccess::ForFirstContextSlot());
+    HValue* first_osr_ast_slot = Add<HLoadNamedField>(optimized_map,
+        HObjectAccess::ForFirstOsrAstIdSlot());
+    HValue* osr_ast_id_none = Add<HConstant>(BailoutId::None().ToInt());
     IfBuilder already_in(this);
     already_in.If<HCompareObjectEqAndBranch>(native_context,
                                              first_context_slot);
+    already_in.AndIf<HCompareObjectEqAndBranch>(first_osr_ast_slot,
+                                                osr_ast_id_none);
     already_in.Then();
     {
       HValue* code_object = Add<HLoadNamedField>(optimized_map,
@@ -1213,7 +1218,7 @@ void CodeStubGraphBuilderBase::BuildInstallFromOptimizedCodeMap(
                                shared_function_entry_length);
       HValue* array_length = Add<HLoadNamedField>(optimized_map,
           HObjectAccess::ForFixedArrayLength());
-      HValue* key = loop_builder.BeginBody(array_length,
+      HValue* slot_iterator = loop_builder.BeginBody(array_length,
                                            graph()->GetConstant0(),
                                            Token::GT);
       {
@@ -1222,8 +1227,8 @@ void CodeStubGraphBuilderBase::BuildInstallFromOptimizedCodeMap(
         HValue* second_entry_index =
             Add<HConstant>(SharedFunctionInfo::kSecondEntryIndex);
         IfBuilder restore_check(this);
-        restore_check.If<HCompareNumericAndBranch>(key, second_entry_index,
-                                                   Token::EQ);
+        restore_check.If<HCompareNumericAndBranch>(
+            slot_iterator, second_entry_index, Token::EQ);
         restore_check.Then();
         {
           // Store the unoptimized code
@@ -1232,20 +1237,29 @@ void CodeStubGraphBuilderBase::BuildInstallFromOptimizedCodeMap(
         }
         restore_check.Else();
         {
-          HValue* keyed_minus = AddUncasted<HSub>(
-              key, shared_function_entry_length);
-          HInstruction* keyed_lookup = Add<HLoadKeyed>(optimized_map,
-              keyed_minus, static_cast<HValue*>(NULL), FAST_ELEMENTS);
+          STATIC_ASSERT(SharedFunctionInfo::kContextOffset == 0);
+          STATIC_ASSERT(SharedFunctionInfo::kEntryLength -
+                            SharedFunctionInfo::kOsrAstIdOffset == 1);
+          HValue* native_context_slot = AddUncasted<HSub>(
+              slot_iterator, shared_function_entry_length);
+          HValue* osr_ast_id_slot = AddUncasted<HSub>(
+              slot_iterator, graph()->GetConstant1());
+          HInstruction* native_context_entry = Add<HLoadKeyed>(optimized_map,
+              native_context_slot, static_cast<HValue*>(NULL), FAST_ELEMENTS);
+          HInstruction* osr_ast_id_entry = Add<HLoadKeyed>(optimized_map,
+              osr_ast_id_slot, static_cast<HValue*>(NULL), FAST_ELEMENTS);
           IfBuilder done_check(this);
           done_check.If<HCompareObjectEqAndBranch>(native_context,
-                                                   keyed_lookup);
+                                                   native_context_entry);
+          done_check.AndIf<HCompareObjectEqAndBranch>(osr_ast_id_entry,
+                                                      osr_ast_id_none);
           done_check.Then();
           {
             // Hit: fetch the optimized code.
-            HValue* keyed_plus = AddUncasted<HAdd>(
-                keyed_minus, graph()->GetConstant1());
+            HValue* code_slot = AddUncasted<HAdd>(
+                native_context_slot, graph()->GetConstant1());
             HValue* code_object = Add<HLoadKeyed>(optimized_map,
-                keyed_plus, static_cast<HValue*>(NULL), FAST_ELEMENTS);
+                code_slot, static_cast<HValue*>(NULL), FAST_ELEMENTS);
             BuildInstallOptimizedCode(js_function, native_context, code_object);
 
             // Fall out of the loop
index 82bec65d856bdcf2a8dc9a09fc00e71f3b5ab541..65bccf2122126eaa0bb46ca4d798daa1068f7ebd 100644 (file)
@@ -1028,16 +1028,20 @@ Handle<SharedFunctionInfo> Compiler::BuildFunctionInfo(FunctionLiteral* literal,
 }
 
 
-static Handle<Code> GetCodeFromOptimizedCodeMap(Handle<JSFunction> function) {
+static Handle<Code> GetCodeFromOptimizedCodeMap(Handle<JSFunction> function,
+                                                BailoutId osr_ast_id) {
   if (FLAG_cache_optimized_code) {
     Handle<SharedFunctionInfo> shared(function->shared());
     DisallowHeapAllocation no_gc;
     int index = shared->SearchOptimizedCodeMap(
-        function->context()->native_context());
+        function->context()->native_context(), osr_ast_id);
     if (index > 0) {
       if (FLAG_trace_opt) {
         PrintF("[found optimized code for ");
         function->ShortPrint();
+        if (!osr_ast_id.IsNone()) {
+          PrintF(" at OSR AST id %d", osr_ast_id.ToInt());
+        }
         PrintF("]\n");
       }
       FixedArray* literals = shared->GetLiteralsFromOptimizedCodeMap(index);
@@ -1053,14 +1057,14 @@ static void InsertCodeIntoOptimizedCodeMap(CompilationInfo* info) {
   Handle<Code> code = info->code();
   if (code->kind() != Code::OPTIMIZED_FUNCTION) return;  // Nothing to do.
 
-  // Cache non-OSR optimized code.
-  if (FLAG_cache_optimized_code && !info->is_osr()) {
+  // Cache optimized code.
+  if (FLAG_cache_optimized_code) {
     Handle<JSFunction> function = info->closure();
     Handle<SharedFunctionInfo> shared(function->shared());
     Handle<FixedArray> literals(function->literals());
     Handle<Context> native_context(function->context()->native_context());
     SharedFunctionInfo::AddToOptimizedCodeMap(
-        shared, native_context, code, literals);
+        shared, native_context, code, literals, info->osr_ast_id());
   }
 }
 
@@ -1137,10 +1141,8 @@ Handle<Code> Compiler::GetOptimizedCode(Handle<JSFunction> function,
                                         Handle<Code> current_code,
                                         ConcurrencyMode mode,
                                         BailoutId osr_ast_id) {
-  if (osr_ast_id.IsNone()) {  // No cache for OSR.
-    Handle<Code> cached_code = GetCodeFromOptimizedCodeMap(function);
-    if (!cached_code.is_null()) return cached_code;
-  }
+  Handle<Code> cached_code = GetCodeFromOptimizedCodeMap(function, osr_ast_id);
+  if (!cached_code.is_null()) return cached_code;
 
   SmartPointer<CompilationInfo> info(new CompilationInfoWithZone(function));
   Isolate* isolate = info->isolate();
@@ -1210,7 +1212,7 @@ Handle<Code> Compiler::GetConcurrentlyOptimizedCode(OptimizedCompileJob* job) {
   Compiler::RecordFunctionCompilation(
       Logger::LAZY_COMPILE_TAG, info.get(), shared);
   if (info->shared_info()->SearchOptimizedCodeMap(
-          info->context()->native_context()) == -1) {
+          info->context()->native_context(), info->osr_ast_id()) == -1) {
     InsertCodeIntoOptimizedCodeMap(info.get());
   }
 
index 1a70f6c601240b569596f68af52f2487b7db6a89..9f1f085fc7701362d68d00fed153486fc826467b 100644 (file)
@@ -924,7 +924,8 @@ Handle<JSFunction> Factory::NewFunctionFromSharedFunctionInfo(
 
   result->set_context(*context);
 
-  int index = function_info->SearchOptimizedCodeMap(context->native_context());
+  int index = function_info->SearchOptimizedCodeMap(context->native_context(),
+                                                    BailoutId::None());
   if (!function_info->bound() && index < 0) {
     int number_of_literals = function_info->num_literals();
     Handle<FixedArray> literals = NewFixedArray(number_of_literals, pretenure);
index 1e270ab2c5c963c662dc20e194dc7a9158863789..25ac2df12152fcfd25a32d5e064386afde483fe5 100644 (file)
@@ -6028,6 +6028,10 @@ class HObjectAccess V8_FINAL {
     return HObjectAccess(kInobject, SharedFunctionInfo::kFirstContextSlot);
   }
 
+  static HObjectAccess ForFirstOsrAstIdSlot() {
+    return HObjectAccess(kInobject, SharedFunctionInfo::kFirstOsrAstIdSlot);
+  }
+
   static HObjectAccess ForOptimizedCodeMap() {
     return HObjectAccess(kInobject,
                          SharedFunctionInfo::kOptimizedCodeMapOffset);
index 0a6793503b2c4fc57db1f84bd29c3b1e296f6a3a..0594c0792af1a8c8651310bd6499c8fc75427c27 100644 (file)
@@ -1065,55 +1065,40 @@ void CodeFlusher::ProcessSharedFunctionInfoCandidates() {
 
 
 void CodeFlusher::ProcessOptimizedCodeMaps() {
-  static const int kEntriesStart = SharedFunctionInfo::kEntriesStart;
-  static const int kEntryLength = SharedFunctionInfo::kEntryLength;
-  static const int kContextOffset = 0;
-  static const int kCodeOffset = 1;
-  static const int kLiteralsOffset = 2;
-  STATIC_ASSERT(kEntryLength == 3);
+  STATIC_ASSERT(SharedFunctionInfo::kEntryLength == 4);
 
   SharedFunctionInfo* holder = optimized_code_map_holder_head_;
   SharedFunctionInfo* next_holder;
+
   while (holder != NULL) {
     next_holder = GetNextCodeMap(holder);
     ClearNextCodeMap(holder);
 
     FixedArray* code_map = FixedArray::cast(holder->optimized_code_map());
-    int new_length = kEntriesStart;
+    int new_length = SharedFunctionInfo::kEntriesStart;
     int old_length = code_map->length();
-    for (int i = kEntriesStart; i < old_length; i += kEntryLength) {
-      Code* code = Code::cast(code_map->get(i + kCodeOffset));
-      MarkBit code_mark = Marking::MarkBitFrom(code);
-      if (!code_mark.Get()) {
-        continue;
+    for (int i = SharedFunctionInfo::kEntriesStart;
+         i < old_length;
+         i += SharedFunctionInfo::kEntryLength) {
+      Code* code =
+          Code::cast(code_map->get(i + SharedFunctionInfo::kCachedCodeOffset));
+      if (!Marking::MarkBitFrom(code).Get()) continue;
+
+      // Move every slot in the entry.
+      for (int j = 0; j < SharedFunctionInfo::kEntryLength; j++) {
+        int dst_index = new_length++;
+        Object** slot = code_map->RawFieldOfElementAt(dst_index);
+        Object* object = code_map->get(i + j);
+        code_map->set(dst_index, object);
+        if (j == SharedFunctionInfo::kOsrAstIdOffset) {
+          ASSERT(object->IsSmi());
+        } else {
+          ASSERT(Marking::IsBlack(
+              Marking::MarkBitFrom(HeapObject::cast(*slot))));
+          isolate_->heap()->mark_compact_collector()->
+              RecordSlot(slot, slot, *slot);
+        }
       }
-
-      // Update and record the context slot in the optimized code map.
-      Object** context_slot = HeapObject::RawField(code_map,
-          FixedArray::OffsetOfElementAt(new_length));
-      code_map->set(new_length++, code_map->get(i + kContextOffset));
-      ASSERT(Marking::IsBlack(
-          Marking::MarkBitFrom(HeapObject::cast(*context_slot))));
-      isolate_->heap()->mark_compact_collector()->
-          RecordSlot(context_slot, context_slot, *context_slot);
-
-      // Update and record the code slot in the optimized code map.
-      Object** code_slot = HeapObject::RawField(code_map,
-          FixedArray::OffsetOfElementAt(new_length));
-      code_map->set(new_length++, code_map->get(i + kCodeOffset));
-      ASSERT(Marking::IsBlack(
-          Marking::MarkBitFrom(HeapObject::cast(*code_slot))));
-      isolate_->heap()->mark_compact_collector()->
-          RecordSlot(code_slot, code_slot, *code_slot);
-
-      // Update and record the literals slot in the optimized code map.
-      Object** literals_slot = HeapObject::RawField(code_map,
-          FixedArray::OffsetOfElementAt(new_length));
-      code_map->set(new_length++, code_map->get(i + kLiteralsOffset));
-      ASSERT(Marking::IsBlack(
-          Marking::MarkBitFrom(HeapObject::cast(*literals_slot))));
-      isolate_->heap()->mark_compact_collector()->
-          RecordSlot(literals_slot, literals_slot, *literals_slot);
     }
 
     // Trim the optimized code map if entries have been removed.
@@ -2608,9 +2593,7 @@ void MarkCompactCollector::ClearNonLivePrototypeTransitions(Map* map) {
             cached_map,
             SKIP_WRITE_BARRIER);
       }
-      Object** slot =
-          HeapObject::RawField(prototype_transitions,
-                               FixedArray::OffsetOfElementAt(proto_index));
+      Object** slot = prototype_transitions->RawFieldOfElementAt(proto_index);
       RecordSlot(slot, slot, prototype);
       new_number_of_transitions++;
     }
@@ -2715,12 +2698,10 @@ void MarkCompactCollector::ProcessWeakCollections() {
     for (int i = 0; i < table->Capacity(); i++) {
       if (MarkCompactCollector::IsMarked(HeapObject::cast(table->KeyAt(i)))) {
         Object** key_slot =
-            HeapObject::RawField(table, FixedArray::OffsetOfElementAt(
-                ObjectHashTable::EntryToIndex(i)));
+            table->RawFieldOfElementAt(ObjectHashTable::EntryToIndex(i));
         RecordSlot(anchor, key_slot, *key_slot);
         Object** value_slot =
-            HeapObject::RawField(table, FixedArray::OffsetOfElementAt(
-                ObjectHashTable::EntryToValueIndex(i)));
+            table->RawFieldOfElementAt(ObjectHashTable::EntryToValueIndex(i));
         MarkCompactMarkingVisitor::MarkObjectByPointer(
             this, anchor, value_slot);
       }
index 185f9d0803eb80301d7026f0ee525a9b81680f8e..5ad0453a1892e990222e97bfcf2b9175726b7eee 100644 (file)
@@ -2364,9 +2364,7 @@ void Map::LookupTransition(JSObject* holder,
 
 Object** DescriptorArray::GetKeySlot(int descriptor_number) {
   ASSERT(descriptor_number < number_of_descriptors());
-  return HeapObject::RawField(
-      reinterpret_cast<HeapObject*>(this),
-      OffsetOfElementAt(ToKeyIndex(descriptor_number)));
+  return RawFieldOfElementAt(ToKeyIndex(descriptor_number));
 }
 
 
@@ -2421,9 +2419,7 @@ void DescriptorArray::InitializeRepresentations(Representation representation) {
 
 Object** DescriptorArray::GetValueSlot(int descriptor_number) {
   ASSERT(descriptor_number < number_of_descriptors());
-  return HeapObject::RawField(
-      reinterpret_cast<HeapObject*>(this),
-      OffsetOfElementAt(ToValueIndex(descriptor_number)));
+  return RawFieldOfElementAt(ToValueIndex(descriptor_number));
 }
 
 
@@ -3224,7 +3220,7 @@ void JSFunctionResultCache::MakeZeroSize() {
 
 void JSFunctionResultCache::Clear() {
   int cache_size = size();
-  Object** entries_start = RawField(this, OffsetOfElementAt(kEntriesIndex));
+  Object** entries_start = RawFieldOfElementAt(kEntriesIndex);
   MemsetPointer(entries_start,
                 GetHeap()->the_hole_value(),
                 cache_size - kEntriesIndex);
@@ -3830,8 +3826,7 @@ Object* DependentCode::object_at(int i) {
 
 
 Object** DependentCode::slot_at(int i) {
-  return HeapObject::RawField(
-      this, FixedArray::OffsetOfElementAt(kCodesStartIndex + i));
+  return RawFieldOfElementAt(kCodesStartIndex + i);
 }
 
 
index 1a68344b26a6782f83c9e4661b6a8f4e9831d402..a7fc84f24dc9fe113d6eda7618d42693500b0416 100644 (file)
@@ -331,8 +331,7 @@ void StaticMarkingVisitor<StaticVisitor>::VisitNativeContext(
   for (int idx = Context::FIRST_WEAK_SLOT;
        idx < Context::NATIVE_CONTEXT_SLOTS;
        ++idx) {
-    Object** slot =
-        HeapObject::RawField(object, FixedArray::OffsetOfElementAt(idx));
+    Object** slot = Context::cast(object)->RawFieldOfElementAt(idx);
     collector->RecordSlot(slot, slot, *slot);
   }
 }
index b9dcaca3b8a7c24d8d3c197ff70b58376390bc1d..0e2f4c1cbe7fcca45b3f8b23a4841a759b984119 100644 (file)
@@ -9526,42 +9526,48 @@ void SharedFunctionInfo::AddToOptimizedCodeMap(
     Handle<SharedFunctionInfo> shared,
     Handle<Context> native_context,
     Handle<Code> code,
-    Handle<FixedArray> literals) {
+    Handle<FixedArray> literals,
+    BailoutId osr_ast_id) {
   CALL_HEAP_FUNCTION_VOID(
       shared->GetIsolate(),
-      shared->AddToOptimizedCodeMap(*native_context, *code, *literals));
+      shared->AddToOptimizedCodeMap(
+          *native_context, *code, *literals, osr_ast_id));
 }
 
 
 MaybeObject* SharedFunctionInfo::AddToOptimizedCodeMap(Context* native_context,
                                                        Code* code,
-                                                       FixedArray* literals) {
+                                                       FixedArray* literals,
+                                                       BailoutId osr_ast_id) {
   ASSERT(code->kind() == Code::OPTIMIZED_FUNCTION);
   ASSERT(native_context->IsNativeContext());
-  STATIC_ASSERT(kEntryLength == 3);
+  STATIC_ASSERT(kEntryLength == 4);
   Heap* heap = GetHeap();
   FixedArray* new_code_map;
   Object* value = optimized_code_map();
+  Smi* osr_ast_id_smi = Smi::FromInt(osr_ast_id.ToInt());
   if (value->IsSmi()) {
     // No optimized code map.
     ASSERT_EQ(0, Smi::cast(value)->value());
     // Create 3 entries per context {context, code, literals}.
     MaybeObject* maybe = heap->AllocateFixedArray(kInitialLength);
     if (!maybe->To(&new_code_map)) return maybe;
-    new_code_map->set(kEntriesStart + 0, native_context);
-    new_code_map->set(kEntriesStart + 1, code);
-    new_code_map->set(kEntriesStart + 2, literals);
+    new_code_map->set(kEntriesStart + kContextOffset, native_context);
+    new_code_map->set(kEntriesStart + kCachedCodeOffset, code);
+    new_code_map->set(kEntriesStart + kLiteralsOffset, literals);
+    new_code_map->set(kEntriesStart + kOsrAstIdOffset, osr_ast_id_smi);
   } else {
     // Copy old map and append one new entry.
     FixedArray* old_code_map = FixedArray::cast(value);
-    ASSERT_EQ(-1, SearchOptimizedCodeMap(native_context));
+    ASSERT_EQ(-1, SearchOptimizedCodeMap(native_context, osr_ast_id));
     int old_length = old_code_map->length();
     int new_length = old_length + kEntryLength;
     MaybeObject* maybe = old_code_map->CopySize(new_length);
     if (!maybe->To(&new_code_map)) return maybe;
-    new_code_map->set(old_length + 0, native_context);
-    new_code_map->set(old_length + 1, code);
-    new_code_map->set(old_length + 2, literals);
+    new_code_map->set(old_length + kContextOffset, native_context);
+    new_code_map->set(old_length + kCachedCodeOffset, code);
+    new_code_map->set(old_length + kLiteralsOffset, literals);
+    new_code_map->set(old_length + kOsrAstIdOffset, osr_ast_id_smi);
     // Zap the old map for the sake of the heap verifier.
     if (Heap::ShouldZapGarbage()) {
       Object** data = old_code_map->data_start();
@@ -9570,11 +9576,12 @@ MaybeObject* SharedFunctionInfo::AddToOptimizedCodeMap(Context* native_context,
   }
 #ifdef DEBUG
   for (int i = kEntriesStart; i < new_code_map->length(); i += kEntryLength) {
-    ASSERT(new_code_map->get(i)->IsNativeContext());
-    ASSERT(new_code_map->get(i + 1)->IsCode());
-    ASSERT(Code::cast(new_code_map->get(i + 1))->kind() ==
+    ASSERT(new_code_map->get(i + kContextOffset)->IsNativeContext());
+    ASSERT(new_code_map->get(i + kCachedCodeOffset)->IsCode());
+    ASSERT(Code::cast(new_code_map->get(i + kCachedCodeOffset))->kind() ==
            Code::OPTIMIZED_FUNCTION);
-    ASSERT(new_code_map->get(i + 2)->IsFixedArray());
+    ASSERT(new_code_map->get(i + kLiteralsOffset)->IsFixedArray());
+    ASSERT(new_code_map->get(i + kOsrAstIdOffset)->IsSmi());
   }
 #endif
   set_optimized_code_map(new_code_map);
@@ -9594,7 +9601,6 @@ FixedArray* SharedFunctionInfo::GetLiteralsFromOptimizedCodeMap(int index) {
 }
 
 
-
 Code* SharedFunctionInfo::GetCodeFromOptimizedCodeMap(int index) {
   ASSERT(index > kEntriesStart);
   FixedArray* code_map = FixedArray::cast(optimized_code_map());
@@ -9639,9 +9645,14 @@ void SharedFunctionInfo::EvictFromOptimizedCodeMap(Code* optimized_code,
     }
   }
   while (i < (code_map->length() - kEntryLength)) {
-    code_map->set(i, code_map->get(i + kEntryLength));
-    code_map->set(i + 1, code_map->get(i + 1 + kEntryLength));
-    code_map->set(i + 2, code_map->get(i + 2 + kEntryLength));
+    code_map->set(i + kContextOffset,
+                  code_map->get(i + kContextOffset + kEntryLength));
+    code_map->set(i + kCachedCodeOffset,
+                  code_map->get(i + kCachedCodeOffset + kEntryLength));
+    code_map->set(i + kLiteralsOffset,
+                  code_map->get(i + kLiteralsOffset + kEntryLength));
+    code_map->set(i + kOsrAstIdOffset,
+                  code_map->get(i + kOsrAstIdOffset + kEntryLength));
     i += kEntryLength;
   }
   if (removed_entry) {
@@ -10203,16 +10214,19 @@ void SharedFunctionInfo::CompleteInobjectSlackTracking() {
 }
 
 
-int SharedFunctionInfo::SearchOptimizedCodeMap(Context* native_context) {
+int SharedFunctionInfo::SearchOptimizedCodeMap(Context* native_context,
+                                               BailoutId osr_ast_id) {
   ASSERT(native_context->IsNativeContext());
   if (!FLAG_cache_optimized_code) return -1;
   Object* value = optimized_code_map();
   if (!value->IsSmi()) {
     FixedArray* optimized_code_map = FixedArray::cast(value);
     int length = optimized_code_map->length();
+    Smi* osr_ast_id_smi = Smi::FromInt(osr_ast_id.ToInt());
     for (int i = kEntriesStart; i < length; i += kEntryLength) {
-      if (optimized_code_map->get(i) == native_context) {
-        return i + 1;
+      if (optimized_code_map->get(i + kContextOffset) == native_context &&
+          optimized_code_map->get(i + kOsrAstIdOffset) == osr_ast_id_smi) {
+        return i + kCachedCodeOffset;
       }
     }
     if (FLAG_trace_opt) {
index a24f30ec6932d690c775010d657847302b35107d..7a557e910b72949fb60473ecf7121beb3788e872 100644 (file)
@@ -2957,6 +2957,11 @@ class FixedArray: public FixedArrayBase {
   // Code Generation support.
   static int OffsetOfElementAt(int index) { return SizeFor(index); }
 
+  // Garbage collection support.
+  Object** RawFieldOfElementAt(int index) {
+    return HeapObject::RawField(this, OffsetOfElementAt(index));
+  }
+
   // Casting.
   static inline FixedArray* cast(Object* obj);
 
@@ -6536,10 +6541,10 @@ class SharedFunctionInfo: public HeapObject {
   // and a shared literals array or Smi(0) if none.
   DECL_ACCESSORS(optimized_code_map, Object)
 
-  // Returns index i of the entry with the specified context. At position
-  // i - 1 is the context, position i the code, and i + 1 the literals array.
-  // Returns -1 when no matching entry is found.
-  int SearchOptimizedCodeMap(Context* native_context);
+  // Returns index i of the entry with the specified context and OSR entry.
+  // At position i - 1 is the context, position i the code, and i + 1 the
+  // literals array.  Returns -1 when no matching entry is found.
+  int SearchOptimizedCodeMap(Context* native_context, BailoutId osr_ast_id);
 
   // Installs optimized code from the code map on the given closure. The
   // index has to be consistent with a search result as defined above.
@@ -6559,18 +6564,28 @@ class SharedFunctionInfo: public HeapObject {
   // Add a new entry to the optimized code map.
   MUST_USE_RESULT MaybeObject* AddToOptimizedCodeMap(Context* native_context,
                                                      Code* code,
-                                                     FixedArray* literals);
+                                                     FixedArray* literals,
+                                                     BailoutId osr_ast_id);
   static void AddToOptimizedCodeMap(Handle<SharedFunctionInfo> shared,
                                     Handle<Context> native_context,
                                     Handle<Code> code,
-                                    Handle<FixedArray> literals);
+                                    Handle<FixedArray> literals,
+                                    BailoutId osr_ast_id);
 
   // Layout description of the optimized code map.
   static const int kNextMapIndex = 0;
   static const int kEntriesStart = 1;
-  static const int kEntryLength = 3;
-  static const int kFirstContextSlot = FixedArray::kHeaderSize + kPointerSize;
-  static const int kFirstCodeSlot = FixedArray::kHeaderSize + 2 * kPointerSize;
+  static const int kContextOffset = 0;
+  static const int kCachedCodeOffset = 1;
+  static const int kLiteralsOffset = 2;
+  static const int kOsrAstIdOffset = 3;
+  static const int kEntryLength = 4;
+  static const int kFirstContextSlot = FixedArray::kHeaderSize +
+      (kEntriesStart + kContextOffset) * kPointerSize;
+  static const int kFirstCodeSlot = FixedArray::kHeaderSize +
+      (kEntriesStart + kCachedCodeOffset) * kPointerSize;
+  static const int kFirstOsrAstIdSlot = FixedArray::kHeaderSize +
+      (kEntriesStart + kOsrAstIdOffset) * kPointerSize;
   static const int kSecondEntryIndex = kEntryLength + kEntriesStart;
   static const int kInitialLength = kEntriesStart + kEntryLength;
 
index c4825fcf734a590dc6dbe114355fa3fc08fede2a..7d8608b050aed7dc7dadca3751465f9a573924c6 100644 (file)
@@ -115,9 +115,7 @@ Object** TransitionArray::GetPrototypeTransitionsSlot() {
 Object** TransitionArray::GetKeySlot(int transition_number) {
   ASSERT(!IsSimpleTransition());
   ASSERT(transition_number < number_of_transitions());
-  return HeapObject::RawField(
-      reinterpret_cast<HeapObject*>(this),
-      OffsetOfElementAt(ToKeyIndex(transition_number)));
+  return RawFieldOfElementAt(ToKeyIndex(transition_number));
 }