Revert r11782, r11783 and r11790 due to Webkit failures.
R=danno@chromium.org Review URL: https://chromiumcodereview.appspot.com/10536142 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@11796 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
55595839f6
commit
9edaa1536b
@ -156,11 +156,6 @@ bool FunctionLiteral::AllowsLazyCompilation() {
|
||||
}
|
||||
|
||||
|
||||
bool FunctionLiteral::AllowsLazyCompilationWithoutContext() {
|
||||
return scope()->AllowsLazyCompilationWithoutContext();
|
||||
}
|
||||
|
||||
|
||||
int FunctionLiteral::start_position() const {
|
||||
return scope()->start_position();
|
||||
}
|
||||
|
@ -2065,7 +2065,6 @@ class FunctionLiteral: public Expression {
|
||||
int parameter_count() { return parameter_count_; }
|
||||
|
||||
bool AllowsLazyCompilation();
|
||||
bool AllowsLazyCompilationWithoutContext();
|
||||
|
||||
Handle<String> debug_name() const {
|
||||
if (name_->length() > 0) return name_;
|
||||
|
@ -118,7 +118,7 @@ bool CompilationInfo::ShouldSelfOptimize() {
|
||||
FLAG_crankshaft &&
|
||||
!function()->flags()->Contains(kDontSelfOptimize) &&
|
||||
!function()->flags()->Contains(kDontOptimize) &&
|
||||
function()->scope()->AllowsLazyCompilation() &&
|
||||
function()->scope()->AllowsLazyRecompilation() &&
|
||||
(shared_info().is_null() || !shared_info()->optimization_disabled());
|
||||
}
|
||||
|
||||
@ -137,8 +137,9 @@ 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 IsDebuggerActive(Isolate* isolate) {
|
||||
static bool is_debugging_active() {
|
||||
#ifdef ENABLE_DEBUGGER_SUPPORT
|
||||
Isolate* isolate = Isolate::Current();
|
||||
return V8::UseCrankshaft() ?
|
||||
isolate->debug()->has_break_points() :
|
||||
isolate->debugger()->IsDebuggerActive();
|
||||
@ -148,8 +149,8 @@ static bool IsDebuggerActive(Isolate* isolate) {
|
||||
}
|
||||
|
||||
|
||||
static bool AlwaysFullCompiler(Isolate* isolate) {
|
||||
return FLAG_always_full_compiler || IsDebuggerActive(isolate);
|
||||
static bool AlwaysFullCompiler() {
|
||||
return FLAG_always_full_compiler || is_debugging_active();
|
||||
}
|
||||
|
||||
|
||||
@ -204,7 +205,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(info->isolate())) {
|
||||
if (AlwaysFullCompiler()) {
|
||||
info->SetCode(code);
|
||||
return true;
|
||||
}
|
||||
@ -718,14 +719,8 @@ Handle<SharedFunctionInfo> 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()) &&
|
||||
(!info.isolate()->DebuggerHasBreakPoints() || allow_lazy_without_ctx);
|
||||
!LiveEditFunctionTracker::IsActive(info.isolate());
|
||||
|
||||
Handle<ScopeInfo> scope_info(ScopeInfo::Empty());
|
||||
|
||||
@ -750,7 +745,6 @@ Handle<SharedFunctionInfo> 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.
|
||||
@ -783,8 +777,6 @@ void Compiler::SetFunctionInfo(Handle<SharedFunctionInfo> 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());
|
||||
|
125
src/debug.cc
125
src/debug.cc
@ -1170,16 +1170,14 @@ Handle<DebugInfo> Debug::GetDebugInfo(Handle<SharedFunctionInfo> shared) {
|
||||
}
|
||||
|
||||
|
||||
void Debug::SetBreakPoint(Handle<JSFunction> function,
|
||||
void Debug::SetBreakPoint(Handle<SharedFunctionInfo> shared,
|
||||
Handle<Object> break_point_object,
|
||||
int* source_position) {
|
||||
HandleScope scope(isolate_);
|
||||
|
||||
PrepareForBreakPoints();
|
||||
|
||||
// Make sure the function is compiled and has set up the debug info.
|
||||
Handle<SharedFunctionInfo> shared(function->shared());
|
||||
if (!EnsureDebugInfo(shared, function)) {
|
||||
if (!EnsureDebugInfo(shared)) {
|
||||
// Return if retrieving debug info failed.
|
||||
return;
|
||||
}
|
||||
@ -1200,51 +1198,6 @@ void Debug::SetBreakPoint(Handle<JSFunction> function,
|
||||
}
|
||||
|
||||
|
||||
bool Debug::SetBreakPointForScript(Handle<Script> script,
|
||||
Handle<Object> break_point_object,
|
||||
int* source_position) {
|
||||
HandleScope scope(isolate_);
|
||||
|
||||
// No need to call PrepareForBreakPoints because it will be called
|
||||
// implicitly by Runtime::FindSharedFunctionInfoInScript.
|
||||
Object* result = Runtime::FindSharedFunctionInfoInScript(isolate_,
|
||||
script,
|
||||
*source_position);
|
||||
if (result->IsUndefined()) return false;
|
||||
|
||||
// Make sure the function has set up the debug info.
|
||||
Handle<SharedFunctionInfo> shared(SharedFunctionInfo::cast(result));
|
||||
if (!EnsureDebugInfo(shared, Handle<JSFunction>::null())) {
|
||||
// Return if retrieving debug info failed.
|
||||
return false;
|
||||
}
|
||||
|
||||
// Find position within function. The script position might be before the
|
||||
// source position of the first function.
|
||||
int position;
|
||||
if (shared->start_position() > *source_position) {
|
||||
position = 0;
|
||||
} else {
|
||||
position = *source_position - shared->start_position();
|
||||
}
|
||||
|
||||
Handle<DebugInfo> debug_info = GetDebugInfo(shared);
|
||||
// Source positions starts with zero.
|
||||
ASSERT(position >= 0);
|
||||
|
||||
// Find the break point and change it.
|
||||
BreakLocationIterator it(debug_info, SOURCE_BREAK_LOCATIONS);
|
||||
it.FindBreakLocationFromPosition(position);
|
||||
it.SetBreakPoint(break_point_object);
|
||||
|
||||
*source_position = it.position() + shared->start_position();
|
||||
|
||||
// At least one active break point now.
|
||||
ASSERT(debug_info->GetBreakPointCount() > 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void Debug::ClearBreakPoint(Handle<Object> break_point_object) {
|
||||
HandleScope scope(isolate_);
|
||||
|
||||
@ -1296,12 +1249,10 @@ void Debug::ClearAllBreakPoints() {
|
||||
}
|
||||
|
||||
|
||||
void Debug::FloodWithOneShot(Handle<JSFunction> function) {
|
||||
void Debug::FloodWithOneShot(Handle<SharedFunctionInfo> shared) {
|
||||
PrepareForBreakPoints();
|
||||
|
||||
// Make sure the function is compiled and has set up the debug info.
|
||||
Handle<SharedFunctionInfo> shared(function->shared());
|
||||
if (!EnsureDebugInfo(shared, function)) {
|
||||
// Make sure the function has set up the debug info.
|
||||
if (!EnsureDebugInfo(shared)) {
|
||||
// Return if we failed to retrieve the debug info.
|
||||
return;
|
||||
}
|
||||
@ -1321,8 +1272,8 @@ void Debug::FloodBoundFunctionWithOneShot(Handle<JSFunction> function) {
|
||||
|
||||
if (!bindee.is_null() && bindee->IsJSFunction() &&
|
||||
!JSFunction::cast(*bindee)->IsBuiltin()) {
|
||||
Handle<JSFunction> bindee_function(JSFunction::cast(*bindee));
|
||||
Debug::FloodWithOneShot(bindee_function);
|
||||
Handle<SharedFunctionInfo> shared_info(JSFunction::cast(*bindee)->shared());
|
||||
Debug::FloodWithOneShot(shared_info);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1337,9 +1288,11 @@ void Debug::FloodHandlerWithOneShot() {
|
||||
for (JavaScriptFrameIterator it(isolate_, id); !it.done(); it.Advance()) {
|
||||
JavaScriptFrame* frame = it.frame();
|
||||
if (frame->HasHandler()) {
|
||||
Handle<SharedFunctionInfo> shared =
|
||||
Handle<SharedFunctionInfo>(
|
||||
JSFunction::cast(frame->function())->shared());
|
||||
// Flood the function with the catch block with break points
|
||||
JSFunction* function = JSFunction::cast(frame->function());
|
||||
FloodWithOneShot(Handle<JSFunction>(function));
|
||||
FloodWithOneShot(shared);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -1406,14 +1359,14 @@ void Debug::PrepareStep(StepAction step_action, int step_count) {
|
||||
frames_it.Advance();
|
||||
// Fill the function to return to with one-shot break points.
|
||||
JSFunction* function = JSFunction::cast(frames_it.frame()->function());
|
||||
FloodWithOneShot(Handle<JSFunction>(function));
|
||||
FloodWithOneShot(Handle<SharedFunctionInfo>(function->shared()));
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the debug info (create it if it does not exist).
|
||||
Handle<JSFunction> function(JSFunction::cast(frame->function()));
|
||||
Handle<SharedFunctionInfo> shared(function->shared());
|
||||
if (!EnsureDebugInfo(shared, function)) {
|
||||
Handle<SharedFunctionInfo> shared =
|
||||
Handle<SharedFunctionInfo>(JSFunction::cast(frame->function())->shared());
|
||||
if (!EnsureDebugInfo(shared)) {
|
||||
// Return if ensuring debug info failed.
|
||||
return;
|
||||
}
|
||||
@ -1483,7 +1436,7 @@ void Debug::PrepareStep(StepAction step_action, int step_count) {
|
||||
if (!frames_it.done()) {
|
||||
// Fill the function to return to with one-shot break points.
|
||||
JSFunction* function = JSFunction::cast(frames_it.frame()->function());
|
||||
FloodWithOneShot(Handle<JSFunction>(function));
|
||||
FloodWithOneShot(Handle<SharedFunctionInfo>(function->shared()));
|
||||
// Set target frame pointer.
|
||||
ActivateStepOut(frames_it.frame());
|
||||
}
|
||||
@ -1493,7 +1446,7 @@ void Debug::PrepareStep(StepAction step_action, int step_count) {
|
||||
// Step next or step min.
|
||||
|
||||
// Fill the current function with one-shot break points.
|
||||
FloodWithOneShot(function);
|
||||
FloodWithOneShot(shared);
|
||||
|
||||
// Remember source position and frame to handle step next.
|
||||
thread_local_.last_statement_position_ =
|
||||
@ -1505,7 +1458,9 @@ void Debug::PrepareStep(StepAction step_action, int step_count) {
|
||||
if (is_at_restarted_function) {
|
||||
Handle<JSFunction> restarted_function(
|
||||
JSFunction::cast(*thread_local_.restarter_frame_function_pointer_));
|
||||
FloodWithOneShot(restarted_function);
|
||||
Handle<SharedFunctionInfo> restarted_shared(
|
||||
restarted_function->shared());
|
||||
FloodWithOneShot(restarted_shared);
|
||||
} else if (!call_function_stub.is_null()) {
|
||||
// If it's CallFunction stub ensure target function is compiled and flood
|
||||
// it with one shot breakpoints.
|
||||
@ -1547,7 +1502,7 @@ void Debug::PrepareStep(StepAction step_action, int step_count) {
|
||||
} else if (!js_function->IsBuiltin()) {
|
||||
// Don't step into builtins.
|
||||
// It will also compile target function if it's not compiled yet.
|
||||
FloodWithOneShot(js_function);
|
||||
FloodWithOneShot(Handle<SharedFunctionInfo>(js_function->shared()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1556,7 +1511,7 @@ void Debug::PrepareStep(StepAction step_action, int step_count) {
|
||||
// a call target as the function called might be a native function for
|
||||
// which step in will not stop. It also prepares for stepping in
|
||||
// getters/setters.
|
||||
FloodWithOneShot(function);
|
||||
FloodWithOneShot(shared);
|
||||
|
||||
if (is_load_or_store) {
|
||||
// Remember source position and frame to handle step in getter/setter. If
|
||||
@ -1756,11 +1711,12 @@ void Debug::HandleStepIn(Handle<JSFunction> function,
|
||||
// function.
|
||||
if (!holder.is_null() && holder->IsJSFunction() &&
|
||||
!JSFunction::cast(*holder)->IsBuiltin()) {
|
||||
Handle<JSFunction> js_function = Handle<JSFunction>::cast(holder);
|
||||
Debug::FloodWithOneShot(js_function);
|
||||
Handle<SharedFunctionInfo> shared_info(
|
||||
JSFunction::cast(*holder)->shared());
|
||||
Debug::FloodWithOneShot(shared_info);
|
||||
}
|
||||
} else {
|
||||
Debug::FloodWithOneShot(function);
|
||||
Debug::FloodWithOneShot(Handle<SharedFunctionInfo>(function->shared()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2000,9 +1956,6 @@ void Debug::PrepareForBreakPoints() {
|
||||
Handle<Code> lazy_compile =
|
||||
Handle<Code>(isolate_->builtins()->builtin(Builtins::kLazyCompile));
|
||||
|
||||
// There will be at least one break point when we are done.
|
||||
has_break_points_ = true;
|
||||
|
||||
// Keep the list of activated functions in a handlified list as it
|
||||
// is used both in GC and non-GC code.
|
||||
List<Handle<JSFunction> > active_functions(100);
|
||||
@ -2110,20 +2063,15 @@ void Debug::PrepareForBreakPoints() {
|
||||
|
||||
|
||||
// Ensures the debug information is present for shared.
|
||||
bool Debug::EnsureDebugInfo(Handle<SharedFunctionInfo> shared,
|
||||
Handle<JSFunction> function) {
|
||||
bool Debug::EnsureDebugInfo(Handle<SharedFunctionInfo> shared) {
|
||||
// Return if we already have the debug info for shared.
|
||||
if (HasDebugInfo(shared)) {
|
||||
ASSERT(shared->is_compiled());
|
||||
return true;
|
||||
}
|
||||
|
||||
// There will be at least one break point when we are done.
|
||||
has_break_points_ = true;
|
||||
|
||||
// Ensure function is compiled. Return false if this failed.
|
||||
if (!function.is_null() &&
|
||||
!JSFunction::EnsureCompiled(function, CLEAR_EXCEPTION)) {
|
||||
// Ensure shared in compiled. Return false if this failed.
|
||||
if (!SharedFunctionInfo::EnsureCompiled(shared, CLEAR_EXCEPTION)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -2135,6 +2083,9 @@ bool Debug::EnsureDebugInfo(Handle<SharedFunctionInfo> shared,
|
||||
node->set_next(debug_info_list_);
|
||||
debug_info_list_ = node;
|
||||
|
||||
// Now there is at least one break point.
|
||||
has_break_points_ = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -2176,9 +2127,9 @@ void Debug::SetAfterBreakTarget(JavaScriptFrame* frame) {
|
||||
PrepareForBreakPoints();
|
||||
|
||||
// Get the executing function in which the debug break occurred.
|
||||
Handle<JSFunction> function(JSFunction::cast(frame->function()));
|
||||
Handle<SharedFunctionInfo> shared(function->shared());
|
||||
if (!EnsureDebugInfo(shared, function)) {
|
||||
Handle<SharedFunctionInfo> shared =
|
||||
Handle<SharedFunctionInfo>(JSFunction::cast(frame->function())->shared());
|
||||
if (!EnsureDebugInfo(shared)) {
|
||||
// Return if we failed to retrieve the debug info.
|
||||
return;
|
||||
}
|
||||
@ -2268,9 +2219,9 @@ bool Debug::IsBreakAtReturn(JavaScriptFrame* frame) {
|
||||
PrepareForBreakPoints();
|
||||
|
||||
// Get the executing function in which the debug break occurred.
|
||||
Handle<JSFunction> function(JSFunction::cast(frame->function()));
|
||||
Handle<SharedFunctionInfo> shared(function->shared());
|
||||
if (!EnsureDebugInfo(shared, function)) {
|
||||
Handle<SharedFunctionInfo> shared =
|
||||
Handle<SharedFunctionInfo>(JSFunction::cast(frame->function())->shared());
|
||||
if (!EnsureDebugInfo(shared)) {
|
||||
// Return if we failed to retrieve the debug info.
|
||||
return false;
|
||||
}
|
||||
|
14
src/debug.h
14
src/debug.h
@ -239,15 +239,12 @@ class Debug {
|
||||
int count,
|
||||
int end));
|
||||
Object* Break(Arguments args);
|
||||
void SetBreakPoint(Handle<JSFunction> function,
|
||||
void SetBreakPoint(Handle<SharedFunctionInfo> shared,
|
||||
Handle<Object> break_point_object,
|
||||
int* source_position);
|
||||
bool SetBreakPointForScript(Handle<Script> script,
|
||||
Handle<Object> break_point_object,
|
||||
int* source_position);
|
||||
void ClearBreakPoint(Handle<Object> break_point_object);
|
||||
void ClearAllBreakPoints();
|
||||
void FloodWithOneShot(Handle<JSFunction> function);
|
||||
void FloodWithOneShot(Handle<SharedFunctionInfo> shared);
|
||||
void FloodBoundFunctionWithOneShot(Handle<JSFunction> function);
|
||||
void FloodHandlerWithOneShot();
|
||||
void ChangeBreakOnException(ExceptionBreakType type, bool enable);
|
||||
@ -263,11 +260,8 @@ class Debug {
|
||||
|
||||
void PrepareForBreakPoints();
|
||||
|
||||
// Returns whether the operation succeeded. Compilation can only be triggered
|
||||
// if a valid closure is passed as the second argument, otherwise the shared
|
||||
// function needs to be compiled already.
|
||||
bool EnsureDebugInfo(Handle<SharedFunctionInfo> shared,
|
||||
Handle<JSFunction> function);
|
||||
// Returns whether the operation succeeded.
|
||||
bool EnsureDebugInfo(Handle<SharedFunctionInfo> shared);
|
||||
|
||||
// Returns true if the current stub call is patched to call the debugger.
|
||||
static bool IsDebugBreak(Address addr);
|
||||
|
@ -315,7 +315,7 @@ bool FullCodeGenerator::MakeCode(CompilationInfo* info) {
|
||||
Handle<Code> code = CodeGenerator::MakeCodeEpilogue(&masm, flags, info);
|
||||
code->set_optimizable(info->IsOptimizable() &&
|
||||
!info->function()->flags()->Contains(kDontOptimize) &&
|
||||
info->function()->scope()->AllowsLazyCompilation());
|
||||
info->function()->scope()->AllowsLazyRecompilation());
|
||||
cgen.PopulateDeoptimizationData(code);
|
||||
cgen.PopulateTypeFeedbackInfo(code);
|
||||
cgen.PopulateTypeFeedbackCells(code);
|
||||
|
@ -3695,10 +3695,6 @@ BOOL_ACCESSORS(SharedFunctionInfo,
|
||||
compiler_hints,
|
||||
allows_lazy_compilation,
|
||||
kAllowLazyCompilation)
|
||||
BOOL_ACCESSORS(SharedFunctionInfo,
|
||||
compiler_hints,
|
||||
allows_lazy_compilation_without_context,
|
||||
kAllowLazyCompilationWithoutContext)
|
||||
BOOL_ACCESSORS(SharedFunctionInfo,
|
||||
compiler_hints,
|
||||
uses_arguments,
|
||||
|
@ -7435,6 +7435,12 @@ void JSFunction::MarkForLazyRecompilation() {
|
||||
}
|
||||
|
||||
|
||||
bool SharedFunctionInfo::EnsureCompiled(Handle<SharedFunctionInfo> shared,
|
||||
ClearExceptionFlag flag) {
|
||||
return shared->is_compiled() || CompileLazy(shared, flag);
|
||||
}
|
||||
|
||||
|
||||
static bool CompileLazyHelper(CompilationInfo* info,
|
||||
ClearExceptionFlag flag) {
|
||||
// Compile the source information to a code object.
|
||||
@ -7451,7 +7457,6 @@ static bool CompileLazyHelper(CompilationInfo* info,
|
||||
|
||||
bool SharedFunctionInfo::CompileLazy(Handle<SharedFunctionInfo> shared,
|
||||
ClearExceptionFlag flag) {
|
||||
ASSERT(shared->allows_lazy_compilation_without_context());
|
||||
CompilationInfo info(shared);
|
||||
return CompileLazyHelper(&info, flag);
|
||||
}
|
||||
@ -7464,7 +7469,6 @@ bool JSFunction::CompileLazy(Handle<JSFunction> function,
|
||||
function->ReplaceCode(function->shared()->code());
|
||||
function->shared()->set_code_age(0);
|
||||
} else {
|
||||
ASSERT(function->shared()->allows_lazy_compilation());
|
||||
CompilationInfo info(function);
|
||||
result = CompileLazyHelper(&info, flag);
|
||||
ASSERT(!result || function->is_compiled());
|
||||
@ -7482,12 +7486,6 @@ bool JSFunction::CompileOptimized(Handle<JSFunction> function,
|
||||
}
|
||||
|
||||
|
||||
bool JSFunction::EnsureCompiled(Handle<JSFunction> function,
|
||||
ClearExceptionFlag flag) {
|
||||
return function->is_compiled() || CompileLazy(function, flag);
|
||||
}
|
||||
|
||||
|
||||
bool JSFunction::IsInlineable() {
|
||||
if (IsBuiltin()) return false;
|
||||
SharedFunctionInfo* shared_info = shared();
|
||||
|
@ -5439,12 +5439,6 @@ class SharedFunctionInfo: public HeapObject {
|
||||
// when doing GC if we expect that the function will no longer be used.
|
||||
DECL_BOOLEAN_ACCESSORS(allows_lazy_compilation)
|
||||
|
||||
// Indicates if this function can be lazy compiled without a context.
|
||||
// This is used to determine if we can force compilation without reaching
|
||||
// the function through program execution but through other means (e.g. heap
|
||||
// iteration by the debugger).
|
||||
DECL_BOOLEAN_ACCESSORS(allows_lazy_compilation_without_context)
|
||||
|
||||
// Indicates how many full GCs this function has survived with assigned
|
||||
// code object. Used to determine when it is relatively safe to flush
|
||||
// this code object and replace it with lazy compilation stub.
|
||||
@ -5591,9 +5585,10 @@ class SharedFunctionInfo: public HeapObject {
|
||||
|
||||
void ResetForNewContext(int new_ic_age);
|
||||
|
||||
// Helper to compile the shared code. Returns true on success, false on
|
||||
// failure (e.g., stack overflow during compilation). This is only used by
|
||||
// the debugger, it is not possible to compile without a context otherwise.
|
||||
// Helpers to compile the shared code. Returns true on success, false on
|
||||
// failure (e.g., stack overflow during compilation).
|
||||
static bool EnsureCompiled(Handle<SharedFunctionInfo> shared,
|
||||
ClearExceptionFlag flag);
|
||||
static bool CompileLazy(Handle<SharedFunctionInfo> shared,
|
||||
ClearExceptionFlag flag);
|
||||
|
||||
@ -5727,7 +5722,6 @@ class SharedFunctionInfo: public HeapObject {
|
||||
enum CompilerHints {
|
||||
kHasOnlySimpleThisPropertyAssignments,
|
||||
kAllowLazyCompilation,
|
||||
kAllowLazyCompilationWithoutContext,
|
||||
kLiveObjectsMayExist,
|
||||
kCodeAgeShift,
|
||||
kOptimizationDisabled = kCodeAgeShift + kCodeAgeSize,
|
||||
@ -5876,8 +5870,6 @@ class JSFunction: public JSObject {
|
||||
|
||||
// Helpers to compile this function. Returns true on success, false on
|
||||
// failure (e.g., stack overflow during compilation).
|
||||
static bool EnsureCompiled(Handle<JSFunction> function,
|
||||
ClearExceptionFlag flag);
|
||||
static bool CompileLazy(Handle<JSFunction> function,
|
||||
ClearExceptionFlag flag);
|
||||
static bool CompileOptimized(Handle<JSFunction> function,
|
||||
|
@ -4521,6 +4521,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> function_name,
|
||||
// The heuristics are:
|
||||
// - It must not have been prohibited by the caller to Parse (some callers
|
||||
// need a full AST).
|
||||
// - The outer scope must be trivial (only global variables in scope).
|
||||
// - The function mustn't be a function expression with an open parenthesis
|
||||
// before; we consider that a hint that the function will be called
|
||||
// immediately, and it would be a waste of time to make it lazily
|
||||
@ -4528,6 +4529,8 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> function_name,
|
||||
// These are all things we can know at this point, without looking at the
|
||||
// function itself.
|
||||
bool is_lazily_compiled = (mode() == PARSE_LAZILY &&
|
||||
top_scope_->outer_scope()->is_global_scope() &&
|
||||
top_scope_->HasTrivialOuterContext() &&
|
||||
!parenthesized_function_);
|
||||
parenthesized_function_ = false; // The bit was set for this function only.
|
||||
|
||||
|
107
src/runtime.cc
107
src/runtime.cc
@ -2183,7 +2183,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_SetCode) {
|
||||
Handle<SharedFunctionInfo> target_shared(target->shared());
|
||||
Handle<SharedFunctionInfo> source_shared(source->shared());
|
||||
|
||||
if (!JSFunction::EnsureCompiled(source, KEEP_EXCEPTION)) {
|
||||
if (!source->is_compiled() &&
|
||||
!JSFunction::CompileLazy(source, KEEP_EXCEPTION)) {
|
||||
return Failure::Exception();
|
||||
}
|
||||
|
||||
@ -4854,13 +4855,14 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugCallbackSupportsStepping) {
|
||||
RUNTIME_FUNCTION(MaybeObject*, Runtime_DebugPrepareStepInIfStepping) {
|
||||
Debug* debug = isolate->debug();
|
||||
if (!debug->IsStepping()) return NULL;
|
||||
CONVERT_ARG_HANDLE_CHECKED(JSFunction, callback, 0);
|
||||
CONVERT_ARG_CHECKED(Object, callback, 0);
|
||||
HandleScope scope(isolate);
|
||||
Handle<SharedFunctionInfo> shared_info(JSFunction::cast(callback)->shared());
|
||||
// When leaving the callback, step out has been activated, but not performed
|
||||
// if we do not leave the builtin. To be able to step into the callback
|
||||
// again, we need to clear the step out at this point.
|
||||
debug->ClearStepOut();
|
||||
debug->FloodWithOneShot(callback);
|
||||
debug->FloodWithOneShot(shared_info);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -8138,8 +8140,12 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_NewObject) {
|
||||
}
|
||||
|
||||
// The function should be compiled for the optimization hints to be
|
||||
// available.
|
||||
JSFunction::EnsureCompiled(function, CLEAR_EXCEPTION);
|
||||
// available. We cannot use EnsureCompiled because that forces a
|
||||
// compilation through the shared function info which makes it
|
||||
// impossible for us to optimize.
|
||||
if (!function->is_compiled()) {
|
||||
JSFunction::CompileLazy(function, CLEAR_EXCEPTION);
|
||||
}
|
||||
|
||||
Handle<SharedFunctionInfo> shared(function->shared(), isolate);
|
||||
if (!function->has_initial_map() &&
|
||||
@ -11149,7 +11155,7 @@ class ScopeIterator {
|
||||
}
|
||||
|
||||
// Get the debug info (create it if it does not exist).
|
||||
if (!isolate->debug()->EnsureDebugInfo(shared_info, function_)) {
|
||||
if (!isolate->debug()->EnsureDebugInfo(shared_info)) {
|
||||
// Return if ensuring debug info failed.
|
||||
return;
|
||||
}
|
||||
@ -11672,14 +11678,30 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetBreakLocations) {
|
||||
}
|
||||
|
||||
|
||||
// Set a break point in a function
|
||||
// args[0]: function
|
||||
// args[1]: number: break source position (within the function source)
|
||||
// args[2]: number: break point object
|
||||
RUNTIME_FUNCTION(MaybeObject*, Runtime_SetFunctionBreakPoint) {
|
||||
HandleScope scope(isolate);
|
||||
ASSERT(args.length() == 3);
|
||||
CONVERT_ARG_HANDLE_CHECKED(JSFunction, fun, 0);
|
||||
Handle<SharedFunctionInfo> shared(fun->shared());
|
||||
CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
|
||||
RUNTIME_ASSERT(source_position >= 0);
|
||||
Handle<Object> break_point_object_arg = args.at<Object>(2);
|
||||
|
||||
// Set break point.
|
||||
isolate->debug()->SetBreakPoint(shared, break_point_object_arg,
|
||||
&source_position);
|
||||
|
||||
return Smi::FromInt(source_position);
|
||||
}
|
||||
|
||||
|
||||
Object* Runtime::FindSharedFunctionInfoInScript(Isolate* isolate,
|
||||
Handle<Script> script,
|
||||
int position) {
|
||||
// The below fix-point iteration depends on all functions that cannot be
|
||||
// compiled lazily without a context to not be compiled at all. Compilation
|
||||
// will be triggered at points where we do not need a context.
|
||||
isolate->debug()->PrepareForBreakPoints();
|
||||
|
||||
// Iterate the heap looking for SharedFunctionInfo generated from the
|
||||
// script. The inner most SharedFunctionInfo containing the source position
|
||||
// for the requested break point is found.
|
||||
@ -11701,12 +11723,6 @@ Object* Runtime::FindSharedFunctionInfoInScript(Isolate* isolate,
|
||||
obj != NULL; obj = iterator.next()) {
|
||||
if (obj->IsSharedFunctionInfo()) {
|
||||
Handle<SharedFunctionInfo> shared(SharedFunctionInfo::cast(obj));
|
||||
if (!shared->allows_lazy_compilation_without_context() &&
|
||||
!shared->is_compiled()) {
|
||||
// Skip functions that we cannot compile lazily without a context,
|
||||
// which is not available here.
|
||||
continue;
|
||||
}
|
||||
if (shared->script() == *script) {
|
||||
// If the SharedFunctionInfo found has the requested script data and
|
||||
// contains the source position it is a candidate.
|
||||
@ -11751,14 +11767,13 @@ Object* Runtime::FindSharedFunctionInfoInScript(Isolate* isolate,
|
||||
return isolate->heap()->undefined_value();
|
||||
}
|
||||
|
||||
// If the candidate found is compiled we are done.
|
||||
// If the candidate found is compiled we are done. NOTE: when lazy
|
||||
// compilation of inner functions is introduced some additional checking
|
||||
// needs to be done here to compile inner functions.
|
||||
done = target->is_compiled();
|
||||
if (!done) {
|
||||
// If the candidate is not compiled, compile it to reveal any inner
|
||||
// functions which might contain the requested source position. This
|
||||
// will compile all inner functions that cannot be compiled without a
|
||||
// context, because Compiler::BuildFunctionInfo checks whether the
|
||||
// debugger is active.
|
||||
// If the candidate is not compiled compile it to reveal any inner
|
||||
// functions which might contain the requested source position.
|
||||
SharedFunctionInfo::CompileLazy(target, KEEP_EXCEPTION);
|
||||
}
|
||||
} // End while loop.
|
||||
@ -11767,26 +11782,6 @@ Object* Runtime::FindSharedFunctionInfoInScript(Isolate* isolate,
|
||||
}
|
||||
|
||||
|
||||
// Set a break point in a function.
|
||||
// args[0]: function
|
||||
// args[1]: number: break source position (within the function source)
|
||||
// args[2]: number: break point object
|
||||
RUNTIME_FUNCTION(MaybeObject*, Runtime_SetFunctionBreakPoint) {
|
||||
HandleScope scope(isolate);
|
||||
ASSERT(args.length() == 3);
|
||||
CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 0);
|
||||
CONVERT_NUMBER_CHECKED(int32_t, source_position, Int32, args[1]);
|
||||
RUNTIME_ASSERT(source_position >= 0);
|
||||
Handle<Object> break_point_object_arg = args.at<Object>(2);
|
||||
|
||||
// Set break point.
|
||||
isolate->debug()->SetBreakPoint(function, break_point_object_arg,
|
||||
&source_position);
|
||||
|
||||
return Smi::FromInt(source_position);
|
||||
}
|
||||
|
||||
|
||||
// Changes the state of a break point in a script and returns source position
|
||||
// where break point was set. NOTE: Regarding performance see the NOTE for
|
||||
// GetScriptFromScriptData.
|
||||
@ -11805,13 +11800,23 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_SetScriptBreakPoint) {
|
||||
RUNTIME_ASSERT(wrapper->value()->IsScript());
|
||||
Handle<Script> script(Script::cast(wrapper->value()));
|
||||
|
||||
// Set break point.
|
||||
if (!isolate->debug()->SetBreakPointForScript(script, break_point_object_arg,
|
||||
&source_position)) {
|
||||
return isolate->heap()->undefined_value();
|
||||
Object* result = Runtime::FindSharedFunctionInfoInScript(
|
||||
isolate, script, source_position);
|
||||
if (!result->IsUndefined()) {
|
||||
Handle<SharedFunctionInfo> shared(SharedFunctionInfo::cast(result));
|
||||
// Find position within function. The script position might be before the
|
||||
// source position of the first function.
|
||||
int position;
|
||||
if (shared->start_position() > source_position) {
|
||||
position = 0;
|
||||
} else {
|
||||
position = source_position - shared->start_position();
|
||||
}
|
||||
isolate->debug()->SetBreakPoint(shared, break_point_object_arg, &position);
|
||||
position += shared->start_position();
|
||||
return Smi::FromInt(position);
|
||||
}
|
||||
|
||||
return Smi::FromInt(source_position);
|
||||
return isolate->heap()->undefined_value();
|
||||
}
|
||||
|
||||
|
||||
@ -12535,7 +12540,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 (!JSFunction::CompileLazy(func, KEEP_EXCEPTION)) {
|
||||
return Failure::Exception();
|
||||
}
|
||||
func->code()->PrintLn();
|
||||
@ -12550,7 +12555,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 (!JSFunction::CompileLazy(func, KEEP_EXCEPTION)) {
|
||||
return Failure::Exception();
|
||||
}
|
||||
func->shared()->construct_stub()->PrintLn();
|
||||
|
@ -637,6 +637,11 @@ bool Scope::AllocateVariables(CompilationInfo* info,
|
||||
}
|
||||
|
||||
|
||||
bool Scope::AllowsLazyCompilation() const {
|
||||
return !force_eager_compilation_ && HasTrivialOuterContext();
|
||||
}
|
||||
|
||||
|
||||
bool Scope::HasTrivialContext() const {
|
||||
// A function scope has a trivial context if it always is the global
|
||||
// context. We iteratively scan out the context chain to see if
|
||||
@ -661,17 +666,12 @@ bool Scope::HasTrivialOuterContext() const {
|
||||
}
|
||||
|
||||
|
||||
bool Scope::AllowsLazyCompilation() const {
|
||||
bool Scope::AllowsLazyRecompilation() const {
|
||||
return !force_eager_compilation_ &&
|
||||
!TrivialDeclarationScopesBeforeWithScope();
|
||||
}
|
||||
|
||||
|
||||
bool Scope::AllowsLazyCompilationWithoutContext() const {
|
||||
return !force_eager_compilation_ && HasTrivialOuterContext();
|
||||
}
|
||||
|
||||
|
||||
bool Scope::TrivialDeclarationScopesBeforeWithScope() const {
|
||||
Scope* outer = outer_scope_;
|
||||
if (outer == NULL) return false;
|
||||
|
@ -374,8 +374,8 @@ class Scope: public ZoneObject {
|
||||
// Determine if we can use lazy compilation for this scope.
|
||||
bool AllowsLazyCompilation() const;
|
||||
|
||||
// Determine if we can use lazy compilation for this scope without a context.
|
||||
bool AllowsLazyCompilationWithoutContext() const;
|
||||
// True if we can lazily recompile functions with this scope.
|
||||
bool AllowsLazyRecompilation() const;
|
||||
|
||||
// True if the outer context of this scope is always the global context.
|
||||
bool HasTrivialOuterContext() const;
|
||||
|
@ -197,9 +197,10 @@ static bool HasDebugInfo(v8::Handle<v8::Function> fun) {
|
||||
// number.
|
||||
static int SetBreakPoint(Handle<v8::internal::JSFunction> fun, int position) {
|
||||
static int break_point = 0;
|
||||
Handle<v8::internal::SharedFunctionInfo> shared(fun->shared());
|
||||
v8::internal::Debug* debug = v8::internal::Isolate::Current()->debug();
|
||||
debug->SetBreakPoint(
|
||||
fun,
|
||||
shared,
|
||||
Handle<Object>(v8::internal::Smi::FromInt(++break_point)),
|
||||
&position);
|
||||
return break_point;
|
||||
@ -514,7 +515,7 @@ void CheckDebugBreakFunction(DebugLocalContext* env,
|
||||
// there
|
||||
ClearBreakPoint(bp);
|
||||
CHECK(!debug->HasDebugInfo(shared));
|
||||
CHECK(debug->EnsureDebugInfo(shared, fun));
|
||||
CHECK(debug->EnsureDebugInfo(shared));
|
||||
TestBreakLocationIterator it2(Debug::GetDebugInfo(shared));
|
||||
it2.FindBreakLocationFromPosition(position);
|
||||
actual_mode = it2.it()->rinfo()->rmode();
|
||||
|
@ -1198,7 +1198,6 @@ TEST(TestSizeOfObjects) {
|
||||
HEAP->CollectAllGarbage(Heap::kNoGCFlags);
|
||||
HEAP->CollectAllGarbage(Heap::kNoGCFlags);
|
||||
HEAP->CollectAllGarbage(Heap::kNoGCFlags);
|
||||
HEAP->CollectAllGarbage(Heap::kNoGCFlags);
|
||||
CHECK(HEAP->old_pointer_space()->IsSweepingComplete());
|
||||
int initial_size = static_cast<int>(HEAP->SizeOfObjects());
|
||||
|
||||
|
@ -1,82 +0,0 @@
|
||||
// Copyright 2012 the V8 project authors. All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following
|
||||
// disclaimer in the documentation and/or other materials provided
|
||||
// with the distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived
|
||||
// from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Flags: --expose-debug-as debug
|
||||
// Get the Debug object exposed from the debug context global object.
|
||||
Debug = debug.Debug
|
||||
|
||||
// Simple debug event handler which just counts the number of break points hit.
|
||||
var break_point_hit_count = 0;
|
||||
|
||||
function listener(event, exec_state, event_data, data) {
|
||||
if (event == Debug.DebugEvent.Break) {
|
||||
break_point_hit_count++;
|
||||
}
|
||||
};
|
||||
|
||||
// Add the debug event listener.
|
||||
Debug.setListener(listener);
|
||||
|
||||
eval(
|
||||
"var inner;\n" +
|
||||
"function outer() {\n" + // Non-trivial outer closure.
|
||||
" var x = 5;\n" +
|
||||
" function a() {\n" +
|
||||
" var foo = 0, y = 7;\n" +
|
||||
" function b() {\n" +
|
||||
" var bar = 0, baz = 0, z = 11;\n" +
|
||||
" function c() {\n" +
|
||||
" return x + y + z;\n" + // Breakpoint line ( #8 )
|
||||
" }\n" +
|
||||
" inner = c;\n" +
|
||||
" return c();\n" +
|
||||
" }\n" +
|
||||
" return b();\n" +
|
||||
" }\n" +
|
||||
" return a();\n" +
|
||||
"}"
|
||||
);
|
||||
|
||||
var script = Debug.findScript(outer);
|
||||
|
||||
// The debugger triggers compilation of inner closures.
|
||||
assertEquals(0, Debug.scriptBreakPoints().length);
|
||||
var sbp = Debug.setScriptBreakPointById(script.id, 8);
|
||||
assertEquals(1, Debug.scriptBreakPoints().length);
|
||||
|
||||
// The compiled outer closure should behave correctly.
|
||||
assertEquals(23, outer());
|
||||
assertEquals(1, break_point_hit_count);
|
||||
|
||||
// The compiled inner closure should behave correctly.
|
||||
assertEquals(23, inner());
|
||||
assertEquals(2, break_point_hit_count);
|
||||
|
||||
// Remove script break point.
|
||||
assertEquals(1, Debug.scriptBreakPoints().length);
|
||||
Debug.clearBreakPoint(sbp);
|
||||
assertEquals(0, Debug.scriptBreakPoints().length);
|
Loading…
Reference in New Issue
Block a user