From a760b82cab3f95a36ebc73b5fc865357095e3739 Mon Sep 17 00:00:00 2001 From: "mstarzinger@chromium.org" Date: Tue, 19 Jun 2012 14:29:48 +0000 Subject: [PATCH] Enable lazy compilation for non-trivial outer contexts. This changes the compiler to be more aggressive about lazy compilation of closures with non-trivial outer context. Compilation can only be triggered with a valid outer context now. One exception is the debugger, which can request compilation of arbitrary shared code, but it ensures to trigger compilation only at points where no context is needed. This relands r11782, r11783, r11790 and a minor fix. R=ulan@chromium.org TEST=mjsunit/debug-script-breakpoints-nested Review URL: https://chromiumcodereview.appspot.com/10543141 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@11866 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/ast.cc | 5 + src/ast.h | 1 + src/compiler.cc | 22 ++- src/debug.cc | 125 ++++++++++----- src/debug.h | 14 +- src/full-codegen.cc | 2 +- src/objects-inl.h | 4 + src/objects.cc | 14 +- src/objects.h | 16 +- src/parser.cc | 3 - src/runtime.cc | 189 ++++++++++++----------- src/scopes.cc | 12 +- src/scopes.h | 4 +- test/cctest/test-debug.cc | 5 +- test/cctest/test-heap.cc | 1 + test/mjsunit/debug-script-breakpoints-closure.js | 67 ++++++++ test/mjsunit/debug-script-breakpoints-nested.js | 82 ++++++++++ 17 files changed, 402 insertions(+), 164 deletions(-) create mode 100644 test/mjsunit/debug-script-breakpoints-closure.js create mode 100644 test/mjsunit/debug-script-breakpoints-nested.js diff --git a/src/ast.cc b/src/ast.cc index 0970253..b790e25 100644 --- a/src/ast.cc +++ b/src/ast.cc @@ -156,6 +156,11 @@ bool FunctionLiteral::AllowsLazyCompilation() { } +bool FunctionLiteral::AllowsLazyCompilationWithoutContext() { + return scope()->AllowsLazyCompilationWithoutContext(); +} + + int FunctionLiteral::start_position() const { return scope()->start_position(); } diff --git a/src/ast.h b/src/ast.h index 02ece7f..b495bfe 100644 --- a/src/ast.h +++ b/src/ast.h @@ -2065,6 +2065,7 @@ class FunctionLiteral: public Expression { int parameter_count() { return parameter_count_; } bool AllowsLazyCompilation(); + bool AllowsLazyCompilationWithoutContext(); Handle debug_name() const { if (name_->length() > 0) return name_; diff --git a/src/compiler.cc b/src/compiler.cc index 0dab226..632f3bd 100644 --- a/src/compiler.cc +++ b/src/compiler.cc @@ -118,7 +118,7 @@ bool CompilationInfo::ShouldSelfOptimize() { FLAG_crankshaft && !function()->flags()->Contains(kDontSelfOptimize) && !function()->flags()->Contains(kDontOptimize) && - function()->scope()->AllowsLazyRecompilation() && + function()->scope()->AllowsLazyCompilation() && (shared_info().is_null() || !shared_info()->optimization_disabled()); } @@ -137,9 +137,8 @@ void CompilationInfo::AbortOptimization() { // all. However crankshaft support recompilation of functions, so in this case // the full compiler need not be be used if a debugger is attached, but only if // break points has actually been set. -static bool is_debugging_active() { +static bool IsDebuggerActive(Isolate* isolate) { #ifdef ENABLE_DEBUGGER_SUPPORT - Isolate* isolate = Isolate::Current(); return V8::UseCrankshaft() ? isolate->debug()->has_break_points() : isolate->debugger()->IsDebuggerActive(); @@ -149,8 +148,8 @@ static bool is_debugging_active() { } -static bool AlwaysFullCompiler() { - return FLAG_always_full_compiler || is_debugging_active(); +static bool AlwaysFullCompiler(Isolate* isolate) { + return FLAG_always_full_compiler || IsDebuggerActive(isolate); } @@ -205,7 +204,7 @@ static bool MakeCrankshaftCode(CompilationInfo* info) { // Fall back to using the full code generator if it's not possible // to use the Hydrogen-based optimizing compiler. We already have // generated code for this from the shared function object. - if (AlwaysFullCompiler()) { + if (AlwaysFullCompiler(info->isolate())) { info->SetCode(code); return true; } @@ -758,8 +757,14 @@ Handle Compiler::BuildFunctionInfo(FunctionLiteral* literal, // builtins cannot be handled lazily by the parser, since we have to know // if a function uses the special natives syntax, which is something the // parser records. + // If the debugger requests compilation for break points, we cannot be + // aggressive about lazy compilation, because it might trigger compilation + // of functions without an outer context when setting a breakpoint through + // Runtime::FindSharedFunctionInfoInScript. + bool allow_lazy_without_ctx = literal->AllowsLazyCompilationWithoutContext(); bool allow_lazy = literal->AllowsLazyCompilation() && - !LiveEditFunctionTracker::IsActive(info.isolate()); + !LiveEditFunctionTracker::IsActive(info.isolate()) && + (!info.isolate()->DebuggerHasBreakPoints() || allow_lazy_without_ctx); Handle scope_info(ScopeInfo::Empty()); @@ -784,6 +789,7 @@ Handle Compiler::BuildFunctionInfo(FunctionLiteral* literal, SetFunctionInfo(result, literal, false, script); RecordFunctionCompilation(Logger::FUNCTION_TAG, &info, result); result->set_allows_lazy_compilation(allow_lazy); + result->set_allows_lazy_compilation_without_context(allow_lazy_without_ctx); // Set the expected number of properties for instances and return // the resulting function. @@ -816,6 +822,8 @@ void Compiler::SetFunctionInfo(Handle function_info, lit->has_only_simple_this_property_assignments(), *lit->this_property_assignments()); function_info->set_allows_lazy_compilation(lit->AllowsLazyCompilation()); + function_info->set_allows_lazy_compilation_without_context( + lit->AllowsLazyCompilationWithoutContext()); function_info->set_language_mode(lit->language_mode()); function_info->set_uses_arguments(lit->scope()->arguments() != NULL); function_info->set_has_duplicate_parameters(lit->has_duplicate_parameters()); diff --git a/src/debug.cc b/src/debug.cc index 338f2c0..3ecca28 100644 --- a/src/debug.cc +++ b/src/debug.cc @@ -1170,14 +1170,16 @@ Handle Debug::GetDebugInfo(Handle shared) { } -void Debug::SetBreakPoint(Handle shared, +void Debug::SetBreakPoint(Handle function, Handle break_point_object, int* source_position) { HandleScope scope(isolate_); PrepareForBreakPoints(); - if (!EnsureDebugInfo(shared)) { + // Make sure the function is compiled and has set up the debug info. + Handle shared(function->shared()); + if (!EnsureDebugInfo(shared, function)) { // Return if retrieving debug info failed. return; } @@ -1198,6 +1200,51 @@ void Debug::SetBreakPoint(Handle shared, } +bool Debug::SetBreakPointForScript(Handle