Reviewers: Toon Verwaest,

Description:
Use optimized code map to cache OSR code.

[email protected]

Please review this at https://codereview.chromium.org/100613004/

SVN Base: https://v8.googlecode.com/svn/branches/bleeding_edge

Affected files (+73, -22 lines):
  M src/code-stubs-hydrogen.cc
  M src/compiler.cc
  M src/factory.cc
  M src/hydrogen-instructions.h
  M src/mark-compact.cc
  M src/objects.h
  M src/objects.cc
  M src/runtime.cc


Index: src/code-stubs-hydrogen.cc
diff --git a/src/code-stubs-hydrogen.cc b/src/code-stubs-hydrogen.cc
index e52ec65c4b7632ac81cb082bfcd5d727cce3a574..b04403ff80778ee0e70ddff4aa76e40efdc5467c 100644
--- a/src/code-stubs-hydrogen.cc
+++ b/src/code-stubs-hydrogen.cc
@@ -1189,6 +1189,10 @@ void CodeStubGraphBuilderBase::BuildInstallFromOptimizedCodeMap(
     // optimized_map points to fixed array of 3-element entries
     // (native context, optimized code, literals).
     // Map must never be empty, so check the first elements.
+ // Matching code that we find may have been compiled for OSR as opposed to
+    // regular optimized code.  That is probably because we never had the
+ // chance to compile regular optimized code before OSR engaged. In that + // case, it's probably a good idea to just reuse that OSR code right now.
     Label install_optimized;
     HValue* first_context_slot = Add<HLoadNamedField>(optimized_map,
         HObjectAccess::ForFirstContextSlot());
Index: src/compiler.cc
diff --git a/src/compiler.cc b/src/compiler.cc
index 83f9ab2daffb78830e80a50e4aefe2aa171af624..d4a48b4c745fab92d66736614e4b8a37f6976177 100644
--- a/src/compiler.cc
+++ b/src/compiler.cc
@@ -964,14 +964,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());
   }
 }

@@ -979,21 +979,26 @@ static void InsertCodeIntoOptimizedCodeMap(CompilationInfo* info) {
 static bool InstallCodeFromOptimizedCodeMap(CompilationInfo* info) {
   if (!info->IsOptimizing()) return false;  // Nothing to look up.

-  // Lookup non-OSR optimized code.
-  if (FLAG_cache_optimized_code && !info->is_osr()) {
+  // Lookup optimized code.
+  if (FLAG_cache_optimized_code) {
     Handle<SharedFunctionInfo> shared = info->shared_info();
     Handle<JSFunction> function = info->closure();
     ASSERT(!function.is_null());
     Handle<Context> native_context(function->context()->native_context());
-    int index = shared->SearchOptimizedCodeMap(*native_context);
+    int index = shared->SearchOptimizedCodeMap(*native_context,
+                                               info->osr_ast_id());
     if (index > 0) {
       if (FLAG_trace_opt) {
         PrintF("[found optimized code for ");
         function->ShortPrint();
+        if (info->is_osr()) {
+          PrintF(" with osr ast id %d ", info->osr_ast_id().ToInt());
+        }
         PrintF("]\n");
       }
       // Caching of optimized code enabled and optimized code found.
       shared->InstallFromOptimizedCodeMap(*function, index);
+      info->SetCode(Handle<Code>(function->code()));
       return true;
     }
   }
@@ -1102,7 +1107,7 @@ bool Compiler::RecompileConcurrent(Handle<JSFunction> closure,
   {
     CompilationHandleScope handle_scope(*info);

-    if (!compiling_for_osr && InstallCodeFromOptimizedCodeMap(*info)) {
+    if (InstallCodeFromOptimizedCodeMap(*info)) {
       return true;
     }

@@ -1178,7 +1183,8 @@ Handle<Code> Compiler::InstallOptimizedCode(RecompileJob* job) {
     ASSERT(info->shared_info()->scope_info() != ScopeInfo::Empty(isolate));
     info->closure()->ReplaceCode(*code);
     if (info->shared_info()->SearchOptimizedCodeMap(
-            info->closure()->context()->native_context()) == -1) {
+            info->closure()->context()->native_context(),
+            info->osr_ast_id()) == -1) {
       InsertCodeIntoOptimizedCodeMap(*info);
     }
     if (FLAG_trace_concurrent_recompilation) {
Index: src/factory.cc
diff --git a/src/factory.cc b/src/factory.cc
index 483e6a632a3e6f975a9f8bee259869d5e318251a..bf3ee0ef811e014634e12ec819a85d36097ff6cd 100644
--- a/src/factory.cc
+++ b/src/factory.cc
@@ -732,7 +732,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: src/hydrogen-instructions.h
diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h
index d4beb6e1de2180b9fb903116a2d66b4dc7f21428..5a3b91775d7b1318b37e81117da7c1b5bb0074cb 100644
--- a/src/hydrogen-instructions.h
+++ b/src/hydrogen-instructions.h
@@ -6018,6 +6018,12 @@ class HObjectAccess V8_FINAL {
     return HObjectAccess(kInobject, SharedFunctionInfo::kFirstContextSlot);
   }

+  static HObjectAccess ForFirstOsrAstIdSlot() {
+    return HObjectAccess(kInobject,
+                         SharedFunctionInfo::kFirstOsrAstIdSlot,
+                         Representation::Smi());
+  }
+
   static HObjectAccess ForOptimizedCodeMap() {
     return HObjectAccess(kInobject,
                          SharedFunctionInfo::kOptimizedCodeMapOffset);
Index: src/mark-compact.cc
diff --git a/src/mark-compact.cc b/src/mark-compact.cc
index 0e6b9804e09fe6776b0b61d97362d1d3ecf223ab..bc14bb495a307acf75079b88bc93a535a3e8e2cd 100644
--- a/src/mark-compact.cc
+++ b/src/mark-compact.cc
@@ -1068,7 +1068,8 @@ void CodeFlusher::ProcessOptimizedCodeMaps() {
   static const int kContextOffset = 0;
   static const int kCodeOffset = 1;
   static const int kLiteralsOffset = 2;
-  STATIC_ASSERT(kEntryLength == 3);
+  static const int kOsrAstIdOffset = 3;
+  STATIC_ASSERT(kEntryLength == 4);

   SharedFunctionInfo* holder = optimized_code_map_holder_head_;
   SharedFunctionInfo* next_holder;
@@ -1112,6 +1113,10 @@ void CodeFlusher::ProcessOptimizedCodeMaps() {
           Marking::MarkBitFrom(HeapObject::cast(*literals_slot))));
       isolate_->heap()->mark_compact_collector()->
           RecordSlot(literals_slot, literals_slot, *literals_slot);
+
+      // Update and record the osr ast id slot in the optimized code map.
+      code_map->set(new_length++, code_map->get(i + kOsrAstIdOffset));
+      ASSERT(code_map->get(i + kOsrAstIdOffset)->IsSmi());
     }

     // Trim the optimized code map if entries have been removed.
Index: src/objects.cc
diff --git a/src/objects.cc b/src/objects.cc
index f96fd83849cff3090814484757f26b352932bc87..d0ed208b4d89d7cbd75cd4bf2e51c4ba0c4f5853 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -9543,22 +9543,26 @@ 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_smi = Smi::FromInt(osr_ast_id.ToInt());
   if (value->IsSmi()) {
     // No optimized code map.
     ASSERT_EQ(0, Smi::cast(value)->value());
@@ -9568,10 +9572,11 @@ MaybeObject* SharedFunctionInfo::AddToOptimizedCodeMap(Context* native_context,
     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 + 3, osr_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);
@@ -9579,6 +9584,7 @@ MaybeObject* SharedFunctionInfo::AddToOptimizedCodeMap(Context* native_context,
     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 + 3, osr_smi);
     // Zap the old map for the sake of the heap verifier.
     if (Heap::ShouldZapGarbage()) {
       Object** data = old_code_map->data_start();
@@ -9592,6 +9598,7 @@ MaybeObject* SharedFunctionInfo::AddToOptimizedCodeMap(Context* native_context,
     ASSERT(Code::cast(new_code_map->get(i + 1))->kind() ==
            Code::OPTIMIZED_FUNCTION);
     ASSERT(new_code_map->get(i + 2)->IsFixedArray());
+    ASSERT(new_code_map->get(i + 3)->IsSmi());
   }
 #endif
   set_optimized_code_map(new_code_map);
@@ -9653,6 +9660,7 @@ void SharedFunctionInfo::EvictFromOptimizedCodeMap(Code* optimized_code,
     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 + 3, code_map->get(i + 3 + kEntryLength));
     i += kEntryLength;
   }
   if (removed_entry) {
@@ -10258,15 +10266,18 @@ 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();
+  Smi* osr_smi = Smi::FromInt(osr_ast_id.ToInt());
   if (!value->IsSmi()) {
     FixedArray* optimized_code_map = FixedArray::cast(value);
     int length = optimized_code_map->length();
     for (int i = kEntriesStart; i < length; i += kEntryLength) {
-      if (optimized_code_map->get(i) == native_context) {
+      if (optimized_code_map->get(i) == native_context &&
+          optimized_code_map->get(i + 3) == osr_smi) {
         return i + 1;
       }
     }
Index: src/objects.h
diff --git a/src/objects.h b/src/objects.h
index bbdefc14a5942122092dd2f82345b4b4d73a2bb6..5256fc556d696b994bdbfde9ea923bded280f649 100644
--- a/src/objects.h
+++ b/src/objects.h
@@ -6537,7 +6537,7 @@ class SharedFunctionInfo: public HeapObject {
   // 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);
+ 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.
@@ -6555,18 +6555,22 @@ 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 kEntryLength = 4;
static const int kFirstContextSlot = FixedArray::kHeaderSize + kPointerSize; static const int kFirstCodeSlot = FixedArray::kHeaderSize + 2 * kPointerSize;
+  static const int kFirstOsrAstIdSlot =
+      FixedArray::kHeaderSize + 4 * kPointerSize;
   static const int kSecondEntryIndex = kEntryLength + kEntriesStart;
   static const int kInitialLength = kEntriesStart + kEntryLength;

Index: src/runtime.cc
diff --git a/src/runtime.cc b/src/runtime.cc
index 7dc96f201970eec90466b79f20fa2823271fe737..13f16bc3b02d38addc90dba89834902cfa9ecace 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -8705,8 +8705,22 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_CompileForOnStackReplacement) {
           // Prevent regular recompilation if we queue this for OSR.
           // TODO(yangguo): remove this as soon as OSR becomes one-shot.
           function->ReplaceCode(*unoptimized);
+        } else if (function->IsOptimized() &&
+                   !isolate->optimizing_compiler_thread()->
+                       IsQueuedForOSR(function, pc_offset)) {
+ // Function has already been optimized and no OSR job has been queued.
+          // This means that we have found cached code.
+          result = Handle<Code>(function->code());
+          DeoptimizationInputData* data =
+              DeoptimizationInputData::cast(result->deoptimization_data());
+          ASSERT_LE(0, data->OsrPcOffset()->value());
+          ast_id = BailoutId(data->OsrAstId()->value());
+          ASSERT_EQ(ast_id.ToInt(),
+ unoptimized->TranslatePcOffsetToAstId(pc_offset).ToInt());
+          // Fall through to the part where we use the OSR code.
+        } else {
+          return NULL;
         }
-        return NULL;
       }
       // Fall through to the end in case of failure.
     } else {


--
--
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