Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(99)

Unified Diff: src/runtime.cc

Issue 110203002: Refactor the compiling pipeline. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: move some code Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: src/runtime.cc
diff --git a/src/runtime.cc b/src/runtime.cc
index e763d435cc985e80a21f0fe43b4e11439c534e6b..f959846c7a34525ea39965f428c9712829d060e3 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -2957,7 +2957,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_SetCode) {
Handle<SharedFunctionInfo> target_shared(target->shared());
Handle<SharedFunctionInfo> source_shared(source->shared());
- if (!JSFunction::EnsureCompiled(source, KEEP_EXCEPTION)) {
+ if (!Compiler::EnsureCompiled(source, KEEP_EXCEPTION)) {
return Failure::Exception();
}
@@ -8265,7 +8265,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_NewObject) {
// The function should be compiled for the optimization hints to be
// available.
- JSFunction::EnsureCompiled(function, CLEAR_EXCEPTION);
+ Compiler::EnsureCompiled(function, CLEAR_EXCEPTION);
Handle<SharedFunctionInfo> shared(function->shared(), isolate);
if (!function->has_initial_map() &&
@@ -8297,7 +8297,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_FinalizeInstanceSize) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_LazyCompile) {
+RUNTIME_FUNCTION(MaybeObject*, Runtime_CompileUnoptimized) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
@@ -8312,27 +8312,35 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_LazyCompile) {
// Compile the target function.
ASSERT(!function->is_compiled());
titzer 2013/12/09 14:49:28 Why?
Yang 2013/12/10 11:22:04 I guess we would guard that this is only called fr
titzer 2013/12/17 15:27:55 In general, I think neither CompileOptimized nor C
Yang 2013/12/17 16:31:33 Added asserts at the end guarding those exit invar
- if (!JSFunction::CompileLazy(function, KEEP_EXCEPTION)) {
- return Failure::Exception();
- }
+ ASSERT(function->shared()->allows_lazy_compilation());
+
+ Handle<Code> code = Compiler::GetUnoptimizedCode(function);
+ RETURN_IF_EMPTY_HANDLE(isolate, code);
+ function->ReplaceCode(*code);
// All done. Return the compiled code.
ASSERT(function->is_compiled());
- return function->code();
+ return *code;
}
-bool AllowOptimization(Isolate* isolate, Handle<JSFunction> function) {
- // If the function is not compiled ignore the lazy
- // recompilation. This can happen if the debugger is activated and
- // the function is returned to the not compiled state.
- if (!function->shared()->is_compiled()) return false;
+RUNTIME_FUNCTION(MaybeObject*, Runtime_CompileOptimized) {
+ HandleScope scope(isolate);
+ ASSERT(args.length() == 2);
+ Handle<JSFunction> function = args.at<JSFunction>(0);
+ CONVERT_BOOLEAN_ARG_CHECKED(concurrent, 1);
- // If the function is not optimizable or debugger is active continue using the
- // code from the full compiler.
- if (!isolate->use_crankshaft() ||
- function->shared()->optimization_disabled() ||
- isolate->DebuggerHasBreakPoints()) {
+ Handle<Code> unoptimized(function->shared()->code());
+ if (!function->shared()->is_compiled()) {
titzer 2013/12/09 14:49:28 I don't think we want this check. IIRC that forces
Yang 2013/12/10 11:22:04 I think that is intentional. I merely inlined Allo
titzer 2013/12/17 15:27:55 Add a TODO. I still think it's an unnecessary rest
Yang 2013/12/17 16:31:33 Done.
+ // If the function is not compiled ignore the lazy
+ // recompilation. This can happen if the debugger is activated and
+ // the function is returned to the not compiled state.
+ function->ReplaceCode(function->shared()->code());
+ } else if (!isolate->use_crankshaft() ||
+ function->shared()->optimization_disabled() ||
+ isolate->DebuggerHasBreakPoints()) {
+ // If the function is not optimizable or debugger is active continue
+ // using the code from the full compiler.
if (FLAG_trace_opt) {
PrintF("[failed to optimize ");
function->PrintName();
@@ -8340,53 +8348,19 @@ bool AllowOptimization(Isolate* isolate, Handle<JSFunction> function) {
function->shared()->optimization_disabled() ? "F" : "T",
isolate->DebuggerHasBreakPoints() ? "T" : "F");
}
- return false;
+ function->ReplaceCode(*unoptimized);
+ } else {
+ Compiler::ConcurrencyMode mode = concurrent ? Compiler::CONCURRENT
+ : Compiler::NOT_CONCURRENT;
+ Handle<Code> code = Compiler::GetOptimizedCode(function, unoptimized, mode);
+ if (code.is_null()) code = isolate->builtins()->InOptimizationQueue();
titzer 2013/12/09 14:49:28 I totally don't understand this. What if the optim
Yang 2013/12/10 11:22:04 You are right. Currently GetOptimizedCode would re
+ function->ReplaceCode(*code);
}
- return true;
-}
-
-RUNTIME_FUNCTION(MaybeObject*, Runtime_LazyRecompile) {
- HandleScope scope(isolate);
- ASSERT(args.length() == 1);
- Handle<JSFunction> function = args.at<JSFunction>(0);
-
- if (!AllowOptimization(isolate, function)) {
- function->ReplaceCode(function->shared()->code());
- return function->code();
- }
- function->shared()->code()->set_profiler_ticks(0);
- if (JSFunction::CompileOptimized(function, CLEAR_EXCEPTION)) {
- return function->code();
- }
- if (FLAG_trace_opt) {
- PrintF("[failed to optimize ");
- function->PrintName();
- PrintF(": optimized compilation failed]\n");
- }
- function->ReplaceCode(function->shared()->code());
return function->code();
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_ConcurrentRecompile) {
- HandleScope handle_scope(isolate);
- ASSERT(args.length() == 1);
- CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
- if (!AllowOptimization(isolate, function)) {
- function->ReplaceCode(function->shared()->code());
- return isolate->heap()->undefined_value();
- }
- Handle<Code> shared_code(function->shared()->code());
- shared_code->set_profiler_ticks(0);
- ASSERT(isolate->concurrent_recompilation_enabled());
- if (!Compiler::RecompileConcurrent(function, shared_code)) {
- function->ReplaceCode(*shared_code);
- }
- return isolate->heap()->undefined_value();
-}
-
-
class ActivationsFinder : public ThreadVisitor {
public:
Code* code_;
@@ -8527,7 +8501,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_OptimizeFunctionOnNextCall) {
CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
if (!function->IsOptimizable()) return isolate->heap()->undefined_value();
- function->MarkForLazyRecompilation();
+ function->MarkForCompileOptimized();
Code* unoptimized = function->shared()->code();
if (args.length() == 2 &&
@@ -8542,7 +8516,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_OptimizeFunctionOnNextCall) {
isolate->runtime_profiler()->AttemptOnStackReplacement(*function);
}
} else if (type->IsOneByteEqualTo(STATIC_ASCII_VECTOR("concurrent"))) {
- function->MarkForConcurrentRecompilation();
+ function->MarkForCompileOptimizedConcurrent();
}
}
@@ -8576,7 +8550,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetOptimizationStatus) {
CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
if (isolate->concurrent_recompilation_enabled() &&
sync_with_compiler_thread) {
- while (function->IsInRecompileQueue()) {
+ while (function->IsInOptimizationQueue()) {
isolate->optimizing_compiler_thread()->InstallOptimizedFunctions();
OS::Sleep(50);
}
@@ -8612,9 +8586,9 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetOptimizationCount) {
static bool IsSuitableForOnStackReplacement(Isolate* isolate,
Handle<JSFunction> function,
- Handle<Code> unoptimized) {
+ Handle<Code> current_code) {
// Keep track of whether we've succeeded in optimizing.
- if (!isolate->use_crankshaft() || !unoptimized->optimizable()) return false;
+ if (!isolate->use_crankshaft() || !current_code->optimizable()) return false;
// If we are trying to do OSR when there are already optimized
// activations of the function, it means (a) the function is directly or
// indirectly recursive and (b) an optimized invocation has been
@@ -8633,79 +8607,75 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_CompileForOnStackReplacement) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
- Handle<Code> unoptimized(function->shared()->code(), isolate);
+ Handle<Code> current_code(function->shared()->code());
titzer 2013/12/09 14:49:28 Let's call this caller_code?
Yang 2013/12/10 11:22:04 Done.
+
+ // We're not prepared to handle a function with arguments object.
+ ASSERT(!function->shared()->uses_arguments());
// Passing the PC in the javascript frame from the caller directly is
// not GC safe, so we walk the stack to get it.
JavaScriptFrameIterator it(isolate);
JavaScriptFrame* frame = it.frame();
- if (!unoptimized->contains(frame->pc())) {
+ if (!current_code->contains(frame->pc())) {
// Code on the stack may not be the code object referenced by the shared
// function info. It may have been replaced to include deoptimization data.
- unoptimized = Handle<Code>(frame->LookupCode());
+ current_code = Handle<Code>(frame->LookupCode());
}
- uint32_t pc_offset = static_cast<uint32_t>(frame->pc() -
- unoptimized->instruction_start());
+ uint32_t pc_offset = static_cast<uint32_t>(
+ frame->pc() - current_code->instruction_start());
#ifdef DEBUG
ASSERT_EQ(frame->function(), *function);
- ASSERT_EQ(frame->LookupCode(), *unoptimized);
- ASSERT(unoptimized->contains(frame->pc()));
+ ASSERT_EQ(frame->LookupCode(), *current_code);
+ ASSERT(current_code->contains(frame->pc()));
#endif // DEBUG
- // We're not prepared to handle a function with arguments object.
- ASSERT(!function->shared()->uses_arguments());
+ BailoutId ast_id = current_code->TranslatePcOffsetToAstId(pc_offset);
+ ASSERT(!ast_id.IsNone());
+
+ Compiler::ConcurrencyMode mode = isolate->concurrent_osr_enabled()
+ ? Compiler::CONCURRENT : Compiler::NOT_CONCURRENT;
Handle<Code> result = Handle<Code>::null();
- BailoutId ast_id = BailoutId::None();
- if (isolate->concurrent_osr_enabled()) {
- if (isolate->optimizing_compiler_thread()->
- IsQueuedForOSR(function, pc_offset)) {
- // Still waiting for the optimizing compiler thread to finish. Carry on.
+ if (mode == Compiler::CONCURRENT) {
+ // Gate the OSR entry with a stack check.
+ BackEdgeTable::AddStackCheck(*current_code, pc_offset);
+ // Poll already queued compilation jobs.
+ OptimizingCompilerThread* thread = isolate->optimizing_compiler_thread();
+ if (thread->IsQueuedForOSR(function, ast_id)) {
if (FLAG_trace_osr) {
- PrintF("[COSR - polling recompile tasks for ");
+ PrintF("[OSR - Still waiting for queued: ");
function->PrintName();
- PrintF("]\n");
+ PrintF(" at AST id %d]\n", ast_id.ToInt());
}
return NULL;
}
- RecompileJob* job = isolate->optimizing_compiler_thread()->
- FindReadyOSRCandidate(function, pc_offset);
-
- if (job == NULL) {
- if (IsSuitableForOnStackReplacement(isolate, function, unoptimized) &&
- Compiler::RecompileConcurrent(function, unoptimized, pc_offset)) {
- if (function->IsMarkedForLazyRecompilation() ||
- function->IsMarkedForConcurrentRecompilation()) {
- // Prevent regular recompilation if we queue this for OSR.
- // TODO(yangguo): remove this as soon as OSR becomes one-shot.
- function->ReplaceCode(function->shared()->code());
- }
- return NULL;
+ RecompileJob* job = thread->FindReadyOSRCandidate(function, ast_id);
+ if (job != NULL) {
+ if (FLAG_trace_osr) {
+ PrintF("[OSR - Found ready: ");
+ function->PrintName();
+ PrintF(" at AST id %d]\n", ast_id.ToInt());
}
- // Fall through to the end in case of failure.
- } else {
- // TODO(titzer): don't install the OSR code into the function.
- ast_id = job->info()->osr_ast_id();
- result = Compiler::InstallOptimizedCode(job);
+ result = Compiler::GetConcurrentlyOptimizedCode(job);
}
- } else if (IsSuitableForOnStackReplacement(isolate, function, unoptimized)) {
- ast_id = unoptimized->TranslatePcOffsetToAstId(pc_offset);
- ASSERT(!ast_id.IsNone());
+ }
+
+ if (result.is_null() &&
+ IsSuitableForOnStackReplacement(isolate, function, current_code)) {
if (FLAG_trace_osr) {
- PrintF("[OSR - replacing at AST id %d in ", ast_id.ToInt());
+ PrintF("[OSR - Compiling: ");
function->PrintName();
- PrintF("]\n");
+ PrintF(" at AST id %d]\n", ast_id.ToInt());
}
- // Attempt OSR compilation.
- result = JSFunction::CompileOsr(function, ast_id, CLEAR_EXCEPTION);
+ result = Compiler::GetOptimizedCode(function, current_code, mode, ast_id);
}
// Revert the patched back edge table, regardless of whether OSR succeeds.
- BackEdgeTable::Revert(isolate, *unoptimized);
+ BackEdgeTable::Revert(isolate, *current_code);
// Check whether we ended up with usable optimized code.
if (!result.is_null() && result->kind() == Code::OPTIMIZED_FUNCTION) {
@@ -8715,26 +8685,27 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_CompileForOnStackReplacement) {
if (data->OsrPcOffset()->value() >= 0) {
ASSERT(BailoutId(data->OsrAstId()->value()) == ast_id);
if (FLAG_trace_osr) {
- PrintF("[OSR - entry at AST id %d, offset %d in optimized code]\n",
+ PrintF("[OSR - Entry at AST id %d, offset %d in optimized code]\n",
ast_id.ToInt(), data->OsrPcOffset()->value());
}
// TODO(titzer): this is a massive hack to make the deopt counts
// match. Fix heuristics for reenabling optimizations!
function->shared()->increment_deopt_count();
+
+ // TODO(titzer): Do not install code into the function.
+ function->ReplaceCode(*result);
return *result;
}
}
+ // Failed.
if (FLAG_trace_osr) {
- PrintF("[OSR - optimization failed for ");
+ PrintF("[OSR - Failed: ");
function->PrintName();
- PrintF("]\n");
+ PrintF(" at AST id %d]\n", ast_id.ToInt());
}
- if (function->IsMarkedForLazyRecompilation() ||
- function->IsMarkedForConcurrentRecompilation()) {
- function->ReplaceCode(function->shared()->code());
- }
+ function->ReplaceCode(function->shared()->code());
return NULL;
}
@@ -9436,7 +9407,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StackGuard) {
}
-RUNTIME_FUNCTION(MaybeObject*, Runtime_TryInstallRecompiledCode) {
+RUNTIME_FUNCTION(MaybeObject*, Runtime_TryInstallOptimizedCode) {
HandleScope scope(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
@@ -9685,13 +9656,9 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_CompileString) {
// Compile source string in the native context.
ParseRestriction restriction = function_literal_only
? ONLY_SINGLE_FUNCTION_LITERAL : NO_PARSE_RESTRICTION;
- Handle<SharedFunctionInfo> shared = Compiler::CompileEval(
- source, context, true, CLASSIC_MODE, restriction, RelocInfo::kNoPosition);
- RETURN_IF_EMPTY_HANDLE(isolate, shared);
- Handle<JSFunction> fun =
- isolate->factory()->NewFunctionFromSharedFunctionInfo(shared,
- context,
- NOT_TENURED);
+ Handle<JSFunction> fun = Compiler::GetFunctionFromEval(
+ source, context, CLASSIC_MODE, restriction, RelocInfo::kNoPosition);
+ RETURN_IF_EMPTY_HANDLE(isolate, fun);
return *fun;
}
@@ -9717,18 +9684,11 @@ static ObjectPair CompileGlobalEval(Isolate* isolate,
// Deal with a normal eval call with a string argument. Compile it
// and return the compiled function bound in the local context.
- Handle<SharedFunctionInfo> shared = Compiler::CompileEval(
- source,
- context,
- context->IsNativeContext(),
- language_mode,
- NO_PARSE_RESTRICTION,
- scope_position);
- RETURN_IF_EMPTY_HANDLE_VALUE(isolate, shared,
+ static const ParseRestriction restriction = NO_PARSE_RESTRICTION;
+ Handle<JSFunction> compiled = Compiler::GetFunctionFromEval(
+ source, context, language_mode, restriction, scope_position);
+ RETURN_IF_EMPTY_HANDLE_VALUE(isolate, compiled,
MakePair(Failure::Exception(), NULL));
- Handle<JSFunction> compiled =
- isolate->factory()->NewFunctionFromSharedFunctionInfo(
- shared, context, NOT_TENURED);
return MakePair(*compiled, *receiver);
}
@@ -12563,7 +12523,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_SetScriptBreakPoint) {
if (!isolate->debug()->SetBreakPointForScript(script, break_point_object_arg,
&source_position,
alignment)) {
- return isolate->heap()->undefined_value();
+ return isolate->heap()->undefined_value();
}
return Smi::FromInt(source_position);
@@ -12723,18 +12683,11 @@ static MaybeObject* DebugEvaluate(Isolate* isolate,
context = isolate->factory()->NewWithContext(closure, context, extension);
}
- Handle<SharedFunctionInfo> shared = Compiler::CompileEval(
- source,
- context,
- context->IsNativeContext(),
- CLASSIC_MODE,
- NO_PARSE_RESTRICTION,
- RelocInfo::kNoPosition);
- RETURN_IF_EMPTY_HANDLE(isolate, shared);
+ static const ParseRestriction restriction = NO_PARSE_RESTRICTION;
titzer 2013/12/09 14:49:28 Why the extra local here?
Yang 2013/12/10 11:22:04 Removed.
+ Handle<JSFunction> eval_fun = Compiler::GetFunctionFromEval(
+ source, context, CLASSIC_MODE, restriction, RelocInfo::kNoPosition);
+ RETURN_IF_EMPTY_HANDLE(isolate, eval_fun);
- Handle<JSFunction> eval_fun =
- isolate->factory()->NewFunctionFromSharedFunctionInfo(
- shared, context, NOT_TENURED);
bool pending_exception;
Handle<Object> result = Execution::Call(
isolate, eval_fun, receiver, 0, NULL, &pending_exception);
@@ -13150,7 +13103,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugDisassembleFunction) {
ASSERT(args.length() == 1);
// Get the function and make sure it is compiled.
CONVERT_ARG_HANDLE_CHECKED(JSFunction, func, 0);
- if (!JSFunction::EnsureCompiled(func, KEEP_EXCEPTION)) {
+ if (!Compiler::EnsureCompiled(func, KEEP_EXCEPTION)) {
return Failure::Exception();
}
func->code()->PrintLn();
@@ -13165,7 +13118,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugDisassembleConstructor) {
ASSERT(args.length() == 1);
// Get the function and make sure it is compiled.
CONVERT_ARG_HANDLE_CHECKED(JSFunction, func, 0);
- if (!JSFunction::EnsureCompiled(func, KEEP_EXCEPTION)) {
+ if (!Compiler::EnsureCompiled(func, KEEP_EXCEPTION)) {
return Failure::Exception();
}
func->shared()->construct_stub()->PrintLn();

Powered by Google App Engine
This is Rietveld 408576698