Simplify installing concurrently recompiled code.
authoryangguo@chromium.org <yangguo@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 12 Sep 2013 11:30:56 +0000 (11:30 +0000)
committeryangguo@chromium.org <yangguo@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 12 Sep 2013 11:30:56 +0000 (11:30 +0000)
Instead of overwriting the code entry of the function, we trigger
an interrupt to install the code on the main thread.

R=mstarzinger@chromium.org
BUG=

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

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

21 files changed:
src/arm/builtins-arm.cc
src/builtins.h
src/compiler.cc
src/debug.cc
src/execution.cc
src/execution.h
src/ia32/builtins-ia32.cc
src/mips/builtins-mips.cc
src/objects-inl.h
src/objects.cc
src/objects.h
src/optimizing-compiler-thread.cc
src/optimizing-compiler-thread.h
src/runtime-profiler.cc
src/runtime.cc
src/runtime.h
src/x64/builtins-x64.cc
test/mjsunit/fuzz-natives-part1.js
test/mjsunit/fuzz-natives-part2.js
test/mjsunit/fuzz-natives-part3.js
test/mjsunit/fuzz-natives-part4.js

index e0c37e1..f60e1f8 100644 (file)
@@ -291,68 +291,55 @@ void Builtins::Generate_StringConstructCode(MacroAssembler* masm) {
 }
 
 
+static void CallRuntimePassFunction(MacroAssembler* masm,
+                                    Runtime::FunctionId function_id) {
+  FrameScope scope(masm, StackFrame::INTERNAL);
+  // Push a copy of the function onto the stack.
+  __ push(r1);
+  // Push call kind information.
+  __ push(r5);
+  // Function is also the parameter to the runtime call.
+  __ push(r1);
+
+  __ CallRuntime(function_id, 1);
+  // Restore call kind information.
+  __ pop(r5);
+  // Restore receiver.
+  __ pop(r1);
+}
+
+
 static void GenerateTailCallToSharedCode(MacroAssembler* masm) {
   __ ldr(r2, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
   __ ldr(r2, FieldMemOperand(r2, SharedFunctionInfo::kCodeOffset));
   __ add(r2, r2, Operand(Code::kHeaderSize - kHeapObjectTag));
-  __ mov(pc, r2);
+  __ Jump(r2);
 }
 
 
 void Builtins::Generate_InRecompileQueue(MacroAssembler* masm) {
+  // Checking whether the queued function is ready for install is optional,
+  // since we come across interrupts and stack checks elsewhere.  However,
+  // not checking may delay installing ready functions, and always checking
+  // would be quite expensive.  A good compromise is to first check against
+  // stack limit as a cue for an interrupt signal.
+  Label ok;
+  __ LoadRoot(ip, Heap::kStackLimitRootIndex);
+  __ cmp(sp, Operand(ip));
+  __ b(hs, &ok);
+
+  CallRuntimePassFunction(masm, Runtime::kTryInstallRecompiledCode);
+  // Tail call to returned code.
+  __ add(r0, r0, Operand(Code::kHeaderSize - kHeapObjectTag));
+  __ Jump(r0);
+
+  __ bind(&ok);
   GenerateTailCallToSharedCode(masm);
 }
 
 
-void Builtins::Generate_InstallRecompiledCode(MacroAssembler* masm) {
-  // Enter an internal frame.
-  {
-    FrameScope scope(masm, StackFrame::INTERNAL);
-
-    // Preserve the function.
-    __ push(r1);
-    // Push call kind information.
-    __ push(r5);
-
-    // Push the function on the stack as the argument to the runtime function.
-    __ push(r1);
-    __ CallRuntime(Runtime::kInstallRecompiledCode, 1);
-    // Calculate the entry point.
-    __ add(r2, r0, Operand(Code::kHeaderSize - kHeapObjectTag));
-
-    // Restore call kind information.
-    __ pop(r5);
-    // Restore saved function.
-    __ pop(r1);
-
-    // Tear down internal frame.
-  }
-
-  // Do a tail-call of the compiled function.
-  __ Jump(r2);
-}
-
-
 void Builtins::Generate_ConcurrentRecompile(MacroAssembler* masm) {
-  {
-    FrameScope scope(masm, StackFrame::INTERNAL);
-
-    // Push a copy of the function onto the stack.
-    __ push(r1);
-    // Push call kind information.
-    __ push(r5);
-
-    __ push(r1);  // Function is also the parameter to the runtime call.
-    __ CallRuntime(Runtime::kConcurrentRecompile, 1);
-
-    // Restore call kind information.
-    __ pop(r5);
-    // Restore receiver.
-    __ pop(r1);
-
-    // Tear down internal frame.
-  }
-
+  CallRuntimePassFunction(masm, Runtime::kConcurrentRecompile);
   GenerateTailCallToSharedCode(masm);
 }
 
@@ -795,59 +782,17 @@ void Builtins::Generate_JSConstructEntryTrampoline(MacroAssembler* masm) {
 
 
 void Builtins::Generate_LazyCompile(MacroAssembler* masm) {
-  // Enter an internal frame.
-  {
-    FrameScope scope(masm, StackFrame::INTERNAL);
-
-    // Preserve the function.
-    __ push(r1);
-    // Push call kind information.
-    __ push(r5);
-
-    // Push the function on the stack as the argument to the runtime function.
-    __ push(r1);
-    __ CallRuntime(Runtime::kLazyCompile, 1);
-    // Calculate the entry point.
-    __ add(r2, r0, Operand(Code::kHeaderSize - kHeapObjectTag));
-
-    // Restore call kind information.
-    __ pop(r5);
-    // Restore saved function.
-    __ pop(r1);
-
-    // Tear down internal frame.
-  }
-
+  CallRuntimePassFunction(masm, Runtime::kLazyCompile);
   // Do a tail-call of the compiled function.
+  __ add(r2, r0, Operand(Code::kHeaderSize - kHeapObjectTag));
   __ Jump(r2);
 }
 
 
 void Builtins::Generate_LazyRecompile(MacroAssembler* masm) {
-  // Enter an internal frame.
-  {
-    FrameScope scope(masm, StackFrame::INTERNAL);
-
-    // Preserve the function.
-    __ push(r1);
-    // Push call kind information.
-    __ push(r5);
-
-    // Push the function on the stack as the argument to the runtime function.
-    __ push(r1);
-    __ CallRuntime(Runtime::kLazyRecompile, 1);
-    // Calculate the entry point.
-    __ add(r2, r0, Operand(Code::kHeaderSize - kHeapObjectTag));
-
-    // Restore call kind information.
-    __ pop(r5);
-    // Restore saved function.
-    __ pop(r1);
-
-    // Tear down internal frame.
-  }
-
+  CallRuntimePassFunction(masm, Runtime::kLazyRecompile);
   // Do a tail-call of the compiled function.
+  __ add(r2, r0, Operand(Code::kHeaderSize - kHeapObjectTag));
   __ Jump(r2);
 }
 
index cbfa1d7..fc97cd3 100644 (file)
@@ -87,8 +87,6 @@ enum BuiltinExtraArguments {
                                     Code::kNoExtraICState)              \
   V(InRecompileQueue,               BUILTIN, UNINITIALIZED,             \
                                     Code::kNoExtraICState)              \
-  V(InstallRecompiledCode,          BUILTIN, UNINITIALIZED,             \
-                                    Code::kNoExtraICState)              \
   V(JSConstructStubCountdown,       BUILTIN, UNINITIALIZED,             \
                                     Code::kNoExtraICState)              \
   V(JSConstructStubGeneric,         BUILTIN, UNINITIALIZED,             \
@@ -382,7 +380,6 @@ class Builtins {
                                CFunctionId id,
                                BuiltinExtraArguments extra_args);
   static void Generate_InRecompileQueue(MacroAssembler* masm);
-  static void Generate_InstallRecompiledCode(MacroAssembler* masm);
   static void Generate_ConcurrentRecompile(MacroAssembler* masm);
   static void Generate_JSConstructStubCountdown(MacroAssembler* masm);
   static void Generate_JSConstructStubGeneric(MacroAssembler* masm);
index 50db8e0..47634ec 100644 (file)
@@ -1067,7 +1067,7 @@ Handle<Code> Compiler::InstallOptimizedCode(
       info->closure()->PrintName();
       PrintF(" as it has been disabled.\n");
     }
-    ASSERT(!info->closure()->IsMarkedForInstallingRecompiledCode());
+    ASSERT(!info->closure()->IsInRecompileQueue());
     return Handle<Code>::null();
   }
 
@@ -1114,7 +1114,7 @@ Handle<Code> Compiler::InstallOptimizedCode(
   // Optimized code is finally replacing unoptimized code.  Reset the latter's
   // profiler ticks to prevent too soon re-opt after a deopt.
   info->shared_info()->code()->set_profiler_ticks(0);
-  ASSERT(!info->closure()->IsMarkedForInstallingRecompiledCode());
+  ASSERT(!info->closure()->IsInRecompileQueue());
   return (status == OptimizingCompiler::SUCCEEDED) ? info->code()
                                                    : Handle<Code>::null();
 }
index 3f2739e..0496b8c 100644 (file)
@@ -2110,8 +2110,7 @@ void Debug::PrepareForBreakPoints() {
             function->set_code(*lazy_compile);
             function->shared()->set_code(*lazy_compile);
           } else if (kind == Code::BUILTIN &&
-              (function->IsMarkedForInstallingRecompiledCode() ||
-               function->IsInRecompileQueue() ||
+              (function->IsInRecompileQueue() ||
                function->IsMarkedForLazyRecompilation() ||
                function->IsMarkedForConcurrentRecompilation())) {
             // Abort in-flight compilation.
index c59a737..979641a 100644 (file)
@@ -459,6 +459,22 @@ void StackGuard::RequestGC() {
 }
 
 
+bool StackGuard::IsInstallCodeRequest() {
+  ExecutionAccess access(isolate_);
+  return (thread_local_.interrupt_flags_ & INSTALL_CODE) != 0;
+}
+
+
+void StackGuard::RequestInstallCode() {
+  ExecutionAccess access(isolate_);
+  thread_local_.interrupt_flags_ |= INSTALL_CODE;
+  if (thread_local_.postpone_interrupts_nesting_ == 0) {
+    thread_local_.jslimit_ = thread_local_.climit_ = kInterruptLimit;
+    isolate_->heap()->SetStackLimits();
+  }
+}
+
+
 bool StackGuard::IsFullDeopt() {
   ExecutionAccess access(isolate_);
   return (thread_local_.interrupt_flags_ & FULL_DEOPT) != 0;
@@ -916,7 +932,6 @@ MaybeObject* Execution::HandleStackGuardInterrupt(Isolate* isolate) {
 
   isolate->counters()->stack_interrupts()->Increment();
   isolate->counters()->runtime_profiler_ticks()->Increment();
-  isolate->runtime_profiler()->OptimizeNow();
 #ifdef ENABLE_DEBUGGER_SUPPORT
   if (stack_guard->IsDebugBreak() || stack_guard->IsDebugCommand()) {
     DebugBreakHelper(isolate);
@@ -935,6 +950,12 @@ MaybeObject* Execution::HandleStackGuardInterrupt(Isolate* isolate) {
     stack_guard->Continue(FULL_DEOPT);
     Deoptimizer::DeoptimizeAll(isolate);
   }
+  if (stack_guard->IsInstallCodeRequest()) {
+    ASSERT(FLAG_concurrent_recompilation);
+    stack_guard->Continue(INSTALL_CODE);
+    isolate->optimizing_compiler_thread()->InstallOptimizedFunctions();
+  }
+  isolate->runtime_profiler()->OptimizeNow();
   return isolate->heap()->undefined_value();
 }
 
index 0c1bf94..371ea30 100644 (file)
@@ -42,7 +42,8 @@ enum InterruptFlag {
   PREEMPT = 1 << 3,
   TERMINATE = 1 << 4,
   GC_REQUEST = 1 << 5,
-  FULL_DEOPT = 1 << 6
+  FULL_DEOPT = 1 << 6,
+  INSTALL_CODE = 1 << 7
 };
 
 
@@ -213,6 +214,8 @@ class StackGuard {
 #endif
   bool IsGCRequest();
   void RequestGC();
+  bool IsInstallCodeRequest();
+  void RequestInstallCode();
   bool IsFullDeopt();
   void FullDeopt();
   void Continue(InterruptFlag after_what);
index 5f5d397..a159748 100644 (file)
@@ -74,6 +74,24 @@ void Builtins::Generate_Adaptor(MacroAssembler* masm,
 }
 
 
+static void CallRuntimePassFunction(MacroAssembler* masm,
+                                    Runtime::FunctionId function_id) {
+  FrameScope scope(masm, StackFrame::INTERNAL);
+  // Push a copy of the function.
+  __ push(edi);
+  // Push call kind information.
+  __ push(ecx);
+  // Function is also the parameter to the runtime call.
+  __ push(edi);
+
+  __ CallRuntime(function_id, 1);
+  // Restore call kind information.
+  __ pop(ecx);
+  // Restore receiver.
+  __ pop(edi);
+}
+
+
 static void GenerateTailCallToSharedCode(MacroAssembler* masm) {
   __ mov(eax, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
   __ mov(eax, FieldOperand(eax, SharedFunctionInfo::kCodeOffset));
@@ -83,56 +101,29 @@ static void GenerateTailCallToSharedCode(MacroAssembler* masm) {
 
 
 void Builtins::Generate_InRecompileQueue(MacroAssembler* masm) {
-  GenerateTailCallToSharedCode(masm);
-}
-
-
-void Builtins::Generate_InstallRecompiledCode(MacroAssembler* masm) {
-  {
-    FrameScope scope(masm, StackFrame::INTERNAL);
-
-    // Push a copy of the function.
-    __ push(edi);
-    // Push call kind information.
-    __ push(ecx);
-
-    __ push(edi);  // Function is also the parameter to the runtime call.
-    __ CallRuntime(Runtime::kInstallRecompiledCode, 1);
-
-    // Restore call kind information.
-    __ pop(ecx);
-    // Restore receiver.
-    __ pop(edi);
-
-    // Tear down internal frame.
-  }
-
-  // Do a tail-call of the compiled function.
+  // Checking whether the queued function is ready for install is optional,
+  // since we come across interrupts and stack checks elsewhere.  However,
+  // not checking may delay installing ready functions, and always checking
+  // would be quite expensive.  A good compromise is to first check against
+  // stack limit as a cue for an interrupt signal.
+  Label ok;
+  ExternalReference stack_limit =
+      ExternalReference::address_of_stack_limit(masm->isolate());
+  __ cmp(esp, Operand::StaticVariable(stack_limit));
+  __ j(above_equal, &ok, Label::kNear);
+
+  CallRuntimePassFunction(masm, Runtime::kTryInstallRecompiledCode);
+  // Tail call to returned code.
   __ lea(eax, FieldOperand(eax, Code::kHeaderSize));
   __ jmp(eax);
+
+  __ bind(&ok);
+  GenerateTailCallToSharedCode(masm);
 }
 
 
 void Builtins::Generate_ConcurrentRecompile(MacroAssembler* masm) {
-  {
-    FrameScope scope(masm, StackFrame::INTERNAL);
-
-    // Push a copy of the function onto the stack.
-    __ push(edi);
-    // Push call kind information.
-    __ push(ecx);
-
-    __ push(edi);  // Function is also the parameter to the runtime call.
-    __ CallRuntime(Runtime::kConcurrentRecompile, 1);
-
-    // Restore call kind information.
-    __ pop(ecx);
-    // Restore receiver.
-    __ pop(edi);
-
-    // Tear down internal frame.
-  }
-
+  CallRuntimePassFunction(masm, Runtime::kConcurrentRecompile);
   GenerateTailCallToSharedCode(masm);
 }
 
@@ -519,25 +510,7 @@ void Builtins::Generate_JSConstructEntryTrampoline(MacroAssembler* masm) {
 
 
 void Builtins::Generate_LazyCompile(MacroAssembler* masm) {
-  {
-    FrameScope scope(masm, StackFrame::INTERNAL);
-
-    // Push a copy of the function.
-    __ push(edi);
-    // Push call kind information.
-    __ push(ecx);
-
-    __ push(edi);  // Function is also the parameter to the runtime call.
-    __ CallRuntime(Runtime::kLazyCompile, 1);
-
-    // Restore call kind information.
-    __ pop(ecx);
-    // Restore receiver.
-    __ pop(edi);
-
-    // Tear down internal frame.
-  }
-
+  CallRuntimePassFunction(masm, Runtime::kLazyCompile);
   // Do a tail-call of the compiled function.
   __ lea(eax, FieldOperand(eax, Code::kHeaderSize));
   __ jmp(eax);
@@ -545,25 +518,7 @@ void Builtins::Generate_LazyCompile(MacroAssembler* masm) {
 
 
 void Builtins::Generate_LazyRecompile(MacroAssembler* masm) {
-  {
-    FrameScope scope(masm, StackFrame::INTERNAL);
-
-    // Push a copy of the function onto the stack.
-    __ push(edi);
-    // Push call kind information.
-    __ push(ecx);
-
-    __ push(edi);  // Function is also the parameter to the runtime call.
-    __ CallRuntime(Runtime::kLazyRecompile, 1);
-
-    // Restore call kind information.
-    __ pop(ecx);
-    // Restore receiver.
-    __ pop(edi);
-
-    // Tear down internal frame.
-  }
-
+  CallRuntimePassFunction(masm, Runtime::kLazyRecompile);
   // Do a tail-call of the compiled function.
   __ lea(eax, FieldOperand(eax, Code::kHeaderSize));
   __ jmp(eax);
index f27ded7..2996693 100644 (file)
@@ -299,6 +299,24 @@ void Builtins::Generate_StringConstructCode(MacroAssembler* masm) {
 }
 
 
+static void CallRuntimePassFunction(MacroAssembler* masm,
+                                    Runtime::FunctionId function_id) {
+  FrameScope scope(masm, StackFrame::INTERNAL);
+  // Push a copy of the function onto the stack.
+  __ push(a1);
+  // Push call kind information.
+  __ push(t1);
+  // Function is also the parameter to the runtime call.
+  __ push(a1);
+
+  __ CallRuntime(function_id, 1);
+  // Restore call kind information.
+  __ pop(t1);
+  // Restore receiver.
+  __ pop(a1);
+}
+
+
 static void GenerateTailCallToSharedCode(MacroAssembler* masm) {
   __ lw(a2, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
   __ lw(a2, FieldMemOperand(a2, SharedFunctionInfo::kCodeOffset));
@@ -308,59 +326,27 @@ static void GenerateTailCallToSharedCode(MacroAssembler* masm) {
 
 
 void Builtins::Generate_InRecompileQueue(MacroAssembler* masm) {
-  GenerateTailCallToSharedCode(masm);
-}
-
-
-void Builtins::Generate_InstallRecompiledCode(MacroAssembler* masm) {
-  // Enter an internal frame.
-  {
-    FrameScope scope(masm, StackFrame::INTERNAL);
-
-    // Preserve the function.
-    __ push(a1);
-    // Push call kind information.
-    __ push(t1);
-
-    // Push the function on the stack as the argument to the runtime function.
-    __ push(a1);
-    __ CallRuntime(Runtime::kInstallRecompiledCode, 1);
-    // Calculate the entry point.
-    __ Addu(t9, v0, Operand(Code::kHeaderSize - kHeapObjectTag));
-
-    // Restore call kind information.
-    __ pop(t1);
-    // Restore saved function.
-    __ pop(a1);
-
-    // Tear down temporary frame.
-  }
+  // Checking whether the queued function is ready for install is optional,
+  // since we come across interrupts and stack checks elsewhere.  However,
+  // not checking may delay installing ready functions, and always checking
+  // would be quite expensive.  A good compromise is to first check against
+  // stack limit as a cue for an interrupt signal.
+  Label ok;
+  __ LoadRoot(t0, Heap::kStackLimitRootIndex);
+  __ Branch(&ok, hs, sp, Operand(t0));
+
+  CallRuntimePassFunction(masm, Runtime::kTryInstallRecompiledCode);
+  // Tail call to returned code.
+  __ Addu(at, a2, Operand(Code::kHeaderSize - kHeapObjectTag));
+  __ Jump(at);
 
-  // Do a tail-call of the compiled function.
-  __ Jump(t9);
+  __ bind(&ok);
+  GenerateTailCallToSharedCode(masm);
 }
 
 
 void Builtins::Generate_ConcurrentRecompile(MacroAssembler* masm) {
-  {
-    FrameScope scope(masm, StackFrame::INTERNAL);
-
-    // Push a copy of the function onto the stack.
-    __ push(a1);
-    // Push call kind information.
-    __ push(t1);
-
-    __ push(a1);  // Function is also the parameter to the runtime call.
-    __ CallRuntime(Runtime::kConcurrentRecompile, 1);
-
-    // Restore call kind information.
-    __ pop(t1);
-    // Restore receiver.
-    __ pop(a1);
-
-    // Tear down internal frame.
-  }
-
+  CallRuntimePassFunction(masm, Runtime::kConcurrentRecompile);
   GenerateTailCallToSharedCode(masm);
 }
 
@@ -815,60 +801,17 @@ void Builtins::Generate_JSConstructEntryTrampoline(MacroAssembler* masm) {
 
 
 void Builtins::Generate_LazyCompile(MacroAssembler* masm) {
-  // Enter an internal frame.
-  {
-    FrameScope scope(masm, StackFrame::INTERNAL);
-
-    // Preserve the function.
-    __ push(a1);
-    // Push call kind information.
-    __ push(t1);
-
-    // Push the function on the stack as the argument to the runtime function.
-    __ push(a1);
-    // Call the runtime function.
-    __ CallRuntime(Runtime::kLazyCompile, 1);
-    // Calculate the entry point.
-    __ addiu(t9, v0, Code::kHeaderSize - kHeapObjectTag);
-
-    // Restore call kind information.
-    __ pop(t1);
-    // Restore saved function.
-    __ pop(a1);
-
-    // Tear down temporary frame.
-  }
-
+  CallRuntimePassFunction(masm, Runtime::kLazyCompile);
   // Do a tail-call of the compiled function.
+  __ Addu(t9, v0, Operand(Code::kHeaderSize - kHeapObjectTag));
   __ Jump(t9);
 }
 
 
 void Builtins::Generate_LazyRecompile(MacroAssembler* masm) {
-  // Enter an internal frame.
-  {
-    FrameScope scope(masm, StackFrame::INTERNAL);
-
-    // Preserve the function.
-    __ push(a1);
-    // Push call kind information.
-    __ push(t1);
-
-    // Push the function on the stack as the argument to the runtime function.
-    __ push(a1);
-    __ CallRuntime(Runtime::kLazyRecompile, 1);
-    // Calculate the entry point.
-    __ Addu(t9, v0, Operand(Code::kHeaderSize - kHeapObjectTag));
-
-    // Restore call kind information.
-    __ pop(t1);
-    // Restore saved function.
-    __ pop(a1);
-
-    // Tear down temporary frame.
-  }
-
+  CallRuntimePassFunction(masm, Runtime::kLazyRecompile);
   // Do a tail-call of the compiled function.
+  __ Addu(t9, v0, Operand(Code::kHeaderSize - kHeapObjectTag));
   __ Jump(t9);
 }
 
index c2dc750..89abe50 100644 (file)
@@ -4970,12 +4970,6 @@ bool JSFunction::IsMarkedForLazyRecompilation() {
 }
 
 
-bool JSFunction::IsMarkedForInstallingRecompiledCode() {
-  return code() == GetIsolate()->builtins()->builtin(
-      Builtins::kInstallRecompiledCode);
-}
-
-
 bool JSFunction::IsMarkedForConcurrentRecompilation() {
   return code() == GetIsolate()->builtins()->builtin(
       Builtins::kConcurrentRecompile);
index 362b363..068d347 100644 (file)
@@ -9321,18 +9321,6 @@ void JSFunction::MarkForConcurrentRecompilation() {
 }
 
 
-void JSFunction::MarkForInstallingRecompiledCode() {
-  // The debugger could have switched the builtin to lazy compile.
-  // In that case, simply carry on.  It will be dealt with later.
-  ASSERT(!IsOptimized());
-  ASSERT(shared()->allows_lazy_compilation() || code()->optimizable());
-  ASSERT(FLAG_concurrent_recompilation);
-  set_code_no_write_barrier(
-      GetIsolate()->builtins()->builtin(Builtins::kInstallRecompiledCode));
-  // No write barrier required, since the builtin is part of the root set.
-}
-
-
 void JSFunction::MarkInRecompileQueue() {
   // We can only arrive here via the concurrent-recompilation builtin.  If
   // break points were set, the code would point to the lazy-compile builtin.
index fff2717..0b8a9b9 100644 (file)
@@ -6989,7 +6989,6 @@ class JSFunction: public JSObject {
   // recompiled the next time it is executed.
   void MarkForLazyRecompilation();
   void MarkForConcurrentRecompilation();
-  void MarkForInstallingRecompiledCode();
   void MarkInRecompileQueue();
 
   // Helpers to compile this function.  Returns true on success, false on
@@ -7008,7 +7007,6 @@ class JSFunction: public JSObject {
   // recompilation.
   inline bool IsMarkedForLazyRecompilation();
   inline bool IsMarkedForConcurrentRecompilation();
-  inline bool IsMarkedForInstallingRecompiledCode();
 
   // Tells whether or not the function is on the concurrent recompilation queue.
   inline bool IsInRecompileQueue();
index a040453..085143d 100644 (file)
@@ -114,11 +114,8 @@ void OptimizingCompilerThread::CompileNext() {
     osr_candidates_.RemoveElement(optimizing_compiler);
     ready_for_osr_.Add(optimizing_compiler);
   } else {
-    LockGuard<Mutex> mark_and_queue(&install_mutex_);
-    Heap::RelocationLock relocation_lock(isolate_->heap());
-    AllowHandleDereference ahd;
-    optimizing_compiler->info()->closure()->MarkForInstallingRecompiledCode();
     output_queue_.Enqueue(optimizing_compiler);
+    isolate_->stack_guard()->RequestInstallCode();
   }
 }
 
@@ -201,10 +198,7 @@ void OptimizingCompilerThread::InstallOptimizedFunctions() {
   HandleScope handle_scope(isolate_);
   OptimizingCompiler* compiler;
   while (true) {
-    { // Memory barrier to ensure marked functions are queued.
-      LockGuard<Mutex> marked_and_queued(&install_mutex_);
-      if (!output_queue_.Dequeue(&compiler)) return;
-    }
+    if (!output_queue_.Dequeue(&compiler)) return;
     Compiler::InstallOptimizedCode(compiler);
   }
 
index f45665b..d1ed6a2 100644 (file)
@@ -120,7 +120,6 @@ class OptimizingCompilerThread : public Thread {
   // List of recompilation tasks ready for OSR.
   List<OptimizingCompiler*> ready_for_osr_;
 
-  Mutex install_mutex_;
   volatile AtomicWord stop_thread_;
   volatile Atomic32 queue_length_;
   TimeDelta time_spent_compiling_;
index 8676d81..95dcc4f 100644 (file)
@@ -149,7 +149,6 @@ void RuntimeProfiler::Optimize(JSFunction* function, const char* reason) {
       // recompilation race.  This goes away as soon as OSR becomes one-shot.
       return;
     }
-    ASSERT(!function->IsMarkedForInstallingRecompiledCode());
     ASSERT(!function->IsInRecompileQueue());
     function->MarkForConcurrentRecompilation();
   } else {
@@ -227,12 +226,6 @@ void RuntimeProfiler::OptimizeNow() {
 
   if (isolate_->DebuggerHasBreakPoints()) return;
 
-  if (FLAG_concurrent_recompilation) {
-    // Take this as opportunity to process the optimizing compiler thread's
-    // output queue so that it does not unnecessarily keep objects alive.
-    isolate_->optimizing_compiler_thread()->InstallOptimizedFunctions();
-  }
-
   DisallowHeapAllocation no_gc;
 
   // Run through the JavaScript frames and collect them. If we already
index 00efa51..912cfce 100644 (file)
@@ -8346,16 +8346,6 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_ConcurrentRecompile) {
 }
 
 
-RUNTIME_FUNCTION(MaybeObject*, Runtime_InstallRecompiledCode) {
-  HandleScope handle_scope(isolate);
-  ASSERT(args.length() == 1);
-  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
-  ASSERT(isolate->use_crankshaft() && FLAG_concurrent_recompilation);
-  isolate->optimizing_compiler_thread()->InstallOptimizedFunctions();
-  return function->code();
-}
-
-
 class ActivationsFinder : public ThreadVisitor {
  public:
   Code* code_;
@@ -8553,8 +8543,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetOptimizationStatus) {
   }
   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
   if (FLAG_concurrent_recompilation && sync_with_compiler_thread) {
-    while (function->IsInRecompileQueue() ||
-           function->IsMarkedForInstallingRecompiledCode()) {
+    while (function->IsInRecompileQueue()) {
       isolate->optimizing_compiler_thread()->InstallOptimizedFunctions();
       OS::Sleep(50);
     }
@@ -9382,7 +9371,6 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StackGuard) {
 
   // First check if this is a real stack overflow.
   if (isolate->stack_guard()->IsStackOverflow()) {
-    SealHandleScope shs(isolate);
     return isolate->StackOverflow();
   }
 
@@ -9390,6 +9378,23 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StackGuard) {
 }
 
 
+RUNTIME_FUNCTION(MaybeObject*, Runtime_TryInstallRecompiledCode) {
+  HandleScope scope(isolate);
+  ASSERT(args.length() == 1);
+  CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
+
+  // First check if this is a real stack overflow.
+  if (isolate->stack_guard()->IsStackOverflow()) {
+    SealHandleScope shs(isolate);
+    return isolate->StackOverflow();
+  }
+
+  isolate->optimizing_compiler_thread()->InstallOptimizedFunctions();
+  return (function->IsOptimized()) ? function->code()
+                                   : function->shared()->code();
+}
+
+
 RUNTIME_FUNCTION(MaybeObject*, Runtime_Interrupt) {
   SealHandleScope shs(isolate);
   ASSERT(args.length() == 0);
index bce09a4..60c6677 100644 (file)
@@ -88,7 +88,7 @@ namespace internal {
   F(LazyCompile, 1, 1) \
   F(LazyRecompile, 1, 1) \
   F(ConcurrentRecompile, 1, 1) \
-  F(InstallRecompiledCode, 1, 1) \
+  F(TryInstallRecompiledCode, 1, 1) \
   F(NotifyDeoptimized, 1, 1) \
   F(NotifyStubFailure, 0, 1) \
   F(NotifyOSR, 0, 1) \
index 1960c3c..81721c2 100644 (file)
@@ -73,6 +73,24 @@ void Builtins::Generate_Adaptor(MacroAssembler* masm,
 }
 
 
+static void CallRuntimePassFunction(MacroAssembler* masm,
+                                    Runtime::FunctionId function_id) {
+  FrameScope scope(masm, StackFrame::INTERNAL);
+  // Push a copy of the function onto the stack.
+  __ push(rdi);
+  // Push call kind information.
+  __ push(rcx);
+  // Function is also the parameter to the runtime call.
+  __ push(rdi);
+
+  __ CallRuntime(function_id, 1);
+  // Restore call kind information.
+  __ pop(rcx);
+  // Restore receiver.
+  __ pop(rdi);
+}
+
+
 static void GenerateTailCallToSharedCode(MacroAssembler* masm) {
   __ movq(kScratchRegister,
           FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset));
@@ -84,57 +102,27 @@ static void GenerateTailCallToSharedCode(MacroAssembler* masm) {
 
 
 void Builtins::Generate_InRecompileQueue(MacroAssembler* masm) {
-  GenerateTailCallToSharedCode(masm);
-}
-
-
-void Builtins::Generate_InstallRecompiledCode(MacroAssembler* masm) {
-  // Enter an internal frame.
-  {
-    FrameScope scope(masm, StackFrame::INTERNAL);
-
-    // Push a copy of the function onto the stack.
-    __ push(rdi);
-    // Push call kind information.
-    __ push(rcx);
-
-    __ push(rdi);  // Function is also the parameter to the runtime call.
-    __ CallRuntime(Runtime::kInstallRecompiledCode, 1);
-
-    // Restore call kind information.
-    __ pop(rcx);
-    // Restore function.
-    __ pop(rdi);
-
-    // Tear down internal frame.
-  }
-
-  // Do a tail-call of the compiled function.
+  // Checking whether the queued function is ready for install is optional,
+  // since we come across interrupts and stack checks elsewhere.  However,
+  // not checking may delay installing ready functions, and always checking
+  // would be quite expensive.  A good compromise is to first check against
+  // stack limit as a cue for an interrupt signal.
+  Label ok;
+  __ CompareRoot(rsp, Heap::kStackLimitRootIndex);
+  __ j(above_equal, &ok);
+
+  CallRuntimePassFunction(masm, Runtime::kTryInstallRecompiledCode);
+  // Tail call to returned code.
   __ lea(rax, FieldOperand(rax, Code::kHeaderSize));
   __ jmp(rax);
+
+  __ bind(&ok);
+  GenerateTailCallToSharedCode(masm);
 }
 
 
 void Builtins::Generate_ConcurrentRecompile(MacroAssembler* masm) {
-  {
-    FrameScope scope(masm, StackFrame::INTERNAL);
-
-    // Push a copy of the function onto the stack.
-    __ push(rdi);
-    // Push call kind information.
-    __ push(rcx);
-
-    __ push(rdi);  // Function is also the parameter to the runtime call.
-    __ CallRuntime(Runtime::kConcurrentRecompile, 1);
-
-    // Restore call kind information.
-    __ pop(rcx);
-    // Restore receiver.
-    __ pop(rdi);
-
-    // Tear down internal frame.
-  }
-
+  CallRuntimePassFunction(masm, Runtime::kConcurrentRecompile);
   GenerateTailCallToSharedCode(masm);
 }
 
@@ -586,26 +574,7 @@ void Builtins::Generate_JSConstructEntryTrampoline(MacroAssembler* masm) {
 
 
 void Builtins::Generate_LazyCompile(MacroAssembler* masm) {
-  // Enter an internal frame.
-  {
-    FrameScope scope(masm, StackFrame::INTERNAL);
-
-    // Push a copy of the function onto the stack.
-    __ push(rdi);
-    // Push call kind information.
-    __ push(rcx);
-
-    __ push(rdi);  // Function is also the parameter to the runtime call.
-    __ CallRuntime(Runtime::kLazyCompile, 1);
-
-    // Restore call kind information.
-    __ pop(rcx);
-    // Restore receiver.
-    __ pop(rdi);
-
-    // Tear down internal frame.
-  }
-
+  CallRuntimePassFunction(masm, Runtime::kLazyCompile);
   // Do a tail-call of the compiled function.
   __ lea(rax, FieldOperand(rax, Code::kHeaderSize));
   __ jmp(rax);
@@ -613,26 +582,7 @@ void Builtins::Generate_LazyCompile(MacroAssembler* masm) {
 
 
 void Builtins::Generate_LazyRecompile(MacroAssembler* masm) {
-  // Enter an internal frame.
-  {
-    FrameScope scope(masm, StackFrame::INTERNAL);
-
-    // Push a copy of the function onto the stack.
-    __ push(rdi);
-    // Push call kind information.
-    __ push(rcx);
-
-    __ push(rdi);  // Function is also the parameter to the runtime call.
-    __ CallRuntime(Runtime::kLazyRecompile, 1);
-
-    // Restore call kind information.
-    __ pop(rcx);
-    // Restore function.
-    __ pop(rdi);
-
-    // Tear down internal frame.
-  }
-
+  CallRuntimePassFunction(masm, Runtime::kLazyRecompile);
   // Do a tail-call of the compiled function.
   __ lea(rax, FieldOperand(rax, Code::kHeaderSize));
   __ jmp(rax);
index 08b7258..e76b9be 100644 (file)
@@ -151,7 +151,6 @@ var knownProblems = {
   "LazyCompile": true,
   "LazyRecompile": true,
   "ConcurrentRecompile": true,
-  "InstallRecompiledCode": true,
   "NotifyDeoptimized": true,
   "NotifyStubFailure": true,
   "NotifyOSR": true,
index 1cebf41..0797deb 100644 (file)
@@ -151,7 +151,6 @@ var knownProblems = {
   "LazyCompile": true,
   "LazyRecompile": true,
   "ConcurrentRecompile": true,
-  "InstallRecompiledCode": true,
   "NotifyDeoptimized": true,
   "NotifyStubFailure": true,
   "NotifyOSR": true,
index f2efee4..9a3a883 100644 (file)
@@ -151,7 +151,6 @@ var knownProblems = {
   "LazyCompile": true,
   "LazyRecompile": true,
   "ConcurrentRecompile": true,
-  "InstallRecompiledCode": true,
   "NotifyDeoptimized": true,
   "NotifyStubFailure": true,
   "NotifyOSR": true,
index fa53480..83e00d2 100644 (file)
@@ -151,7 +151,6 @@ var knownProblems = {
   "LazyCompile": true,
   "LazyRecompile": true,
   "ConcurrentRecompile": true,
-  "InstallRecompiledCode": true,
   "NotifyDeoptimized": true,
   "NotifyStubFailure": true,
   "NotifyOSR": true,