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:
mstarzinger@chromium.org 2012-06-13 11:26:34 +00:00
parent 55595839f6
commit 9edaa1536b
16 changed files with 130 additions and 287 deletions

View File

@ -156,11 +156,6 @@ bool FunctionLiteral::AllowsLazyCompilation() {
}
bool FunctionLiteral::AllowsLazyCompilationWithoutContext() {
return scope()->AllowsLazyCompilationWithoutContext();
}
int FunctionLiteral::start_position() const {
return scope()->start_position();
}

View File

@ -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_;

View File

@ -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());

View File

@ -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;
}

View File

@ -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);

View File

@ -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);

View File

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

View File

@ -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();

View File

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

View File

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

View File

@ -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();

View File

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

View File

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

View File

@ -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();

View File

@ -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());

View File

@ -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);