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

Unified Diff: src/debug/debug.cc

Issue 1474293002: [debugger] Remove code to predict step-in target. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: fix mips Created 5 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
« no previous file with comments | « src/debug/debug.h ('k') | src/ia32/macro-assembler-ia32.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/debug/debug.cc
diff --git a/src/debug/debug.cc b/src/debug/debug.cc
index d6e4637d9876a40487cac04b638acf6669de69c3..adba75ebd3fb86a6887d766f88ad8f6d94750aee 100644
--- a/src/debug/debug.cc
+++ b/src/debug/debug.cc
@@ -336,8 +336,8 @@ void Debug::ThreadInit() {
thread_local_.step_count_ = 0;
thread_local_.last_fp_ = 0;
thread_local_.queued_step_count_ = 0;
- thread_local_.step_into_fp_ = 0;
thread_local_.step_out_fp_ = 0;
+ thread_local_.step_in_enabled_ = false;
// TODO(isolates): frames_are_dropped_?
base::NoBarrier_Store(&thread_local_.current_debug_scope_,
static_cast<base::AtomicWord>(0));
@@ -748,6 +748,9 @@ void Debug::ClearAllBreakPoints() {
void Debug::FloodWithOneShot(Handle<JSFunction> function,
BreakLocatorType type) {
+ // Debug utility functions are not subject to debugging.
+ if (function->native_context() == *debug_context()) return;
+
if (!function->shared()->IsSubjectToDebugging()) {
// Builtin functions are not subject to stepping, but need to be
// deoptimized, because optimized code does not check for debug
@@ -770,66 +773,11 @@ void Debug::FloodWithOneShot(Handle<JSFunction> function,
}
-void Debug::FloodBoundFunctionWithOneShot(Handle<JSFunction> function) {
- Handle<BindingsArray> new_bindings(function->function_bindings());
- Handle<Object> bindee(new_bindings->bound_function(), isolate_);
-
- if (!bindee.is_null() && bindee->IsJSFunction()) {
- Handle<JSFunction> bindee_function(JSFunction::cast(*bindee));
- FloodWithOneShotGeneric(bindee_function);
- }
-}
-
-
-void Debug::FloodDefaultConstructorWithOneShot(Handle<JSFunction> function) {
- DCHECK(function->shared()->is_default_constructor());
- // Instead of stepping into the function we directly step into the super class
- // constructor.
- Isolate* isolate = function->GetIsolate();
- PrototypeIterator iter(isolate, function);
- Handle<Object> proto = PrototypeIterator::GetCurrent(iter);
- if (!proto->IsJSFunction()) return; // Object.prototype
- Handle<JSFunction> function_proto = Handle<JSFunction>::cast(proto);
- FloodWithOneShotGeneric(function_proto);
-}
-
-
-void Debug::FloodWithOneShotGeneric(Handle<JSFunction> function,
- Handle<Object> holder) {
- if (function->shared()->bound()) {
- FloodBoundFunctionWithOneShot(function);
- } else if (function->shared()->is_default_constructor()) {
- FloodDefaultConstructorWithOneShot(function);
- } else {
- Isolate* isolate = function->GetIsolate();
- // Don't allow step into functions in the native context.
- if (function->shared()->code() ==
- isolate->builtins()->builtin(Builtins::kFunctionApply) ||
- function->shared()->code() ==
- isolate->builtins()->builtin(Builtins::kFunctionCall)) {
- // Handle function.apply and function.call separately to flood the
- // function to be called and not the code for Builtins::FunctionApply or
- // Builtins::FunctionCall. The receiver of call/apply is the target
- // function.
- if (!holder.is_null() && holder->IsJSFunction()) {
- Handle<JSFunction> js_function = Handle<JSFunction>::cast(holder);
- FloodWithOneShotGeneric(js_function);
- }
- } else {
- FloodWithOneShot(function);
- }
- }
-}
-
-
void Debug::FloodHandlerWithOneShot() {
// Iterate through the JavaScript stack looking for handlers.
- StackFrame::Id id = break_frame_id();
- if (id == StackFrame::NO_ID) {
- // If there is no JavaScript stack don't do anything.
- return;
- }
- for (JavaScriptFrameIterator it(isolate_, id); !it.done(); it.Advance()) {
+ DCHECK_NE(StackFrame::NO_ID, break_frame_id());
+ for (JavaScriptFrameIterator it(isolate_, break_frame_id()); !it.done();
+ it.Advance()) {
JavaScriptFrame* frame = it.frame();
int stack_slots = 0; // The computed stack slot count is not used.
if (frame->LookupExceptionHandlerInTable(&stack_slots, NULL) > 0) {
@@ -866,6 +814,18 @@ FrameSummary GetFirstFrameSummary(JavaScriptFrame* frame) {
}
+void Debug::PrepareStepIn(Handle<JSFunction> function) {
+ if (!is_active()) return;
+ if (!IsStepping()) return;
+ if (last_step_action() < StepIn) return;
+ if (in_debug_scope()) return;
+ if (thread_local_.step_in_enabled_) {
+ ClearStepOut();
+ FloodWithOneShot(function);
+ }
+}
+
+
void Debug::PrepareStep(StepAction step_action,
int step_count,
StackFrame::Id frame_id) {
@@ -875,6 +835,8 @@ void Debug::PrepareStep(StepAction step_action,
// Remember this step action and count.
thread_local_.last_step_action_ = step_action;
+ STATIC_ASSERT(StepFrame > StepIn);
+ thread_local_.step_in_enabled_ = (step_action >= StepIn);
if (step_action == StepOut) {
// For step out target frame will be found on the stack so there is no need
// to set step counter for it. It's expected to always be 0 for StepOut.
@@ -950,6 +912,12 @@ void Debug::PrepareStep(StepAction step_action,
// Skip native and extension functions on the stack.
while (!frames_it.done() &&
!frames_it.frame()->function()->shared()->IsSubjectToDebugging()) {
+ if (step_action >= StepIn) {
+ // Builtin functions are not subject to stepping, but need to be
+ // deoptimized, because optimized code does not check for debug
+ // step in at call sites.
+ Deoptimizer::DeoptimizeFunction(frames_it.frame()->function());
+ }
frames_it.Advance();
}
// Step out: If there is a JavaScript caller frame, we need to
@@ -960,55 +928,23 @@ void Debug::PrepareStep(StepAction step_action,
FloodWithOneShot(Handle<JSFunction>(function));
// Set target frame pointer.
ActivateStepOut(frames_it.frame());
+ } else {
+ // Stepping out to the embedder. Disable step-in to avoid stepping into
+ // the next (unrelated) call that the embedder makes.
+ thread_local_.step_in_enabled_ = false;
}
return;
}
- if (step_action != StepNext) {
+ STATIC_ASSERT(StepFrame > StepIn);
+ if (step_action >= StepIn) {
// If there's restarter frame on top of the stack, just get the pointer
// to function which is going to be restarted.
if (thread_local_.restarter_frame_function_pointer_ != NULL) {
Handle<JSFunction> restarted_function(
JSFunction::cast(*thread_local_.restarter_frame_function_pointer_));
FloodWithOneShot(restarted_function);
- } else if (location.IsStepInLocation()) {
- // Find target function on the expression stack.
- // Expression stack looks like this (top to bottom):
- // argN
- // ...
- // arg0
- // Receiver (only present for calls, not for construct).
- // Function to call
- int base = location.IsCall() ? 2 : 1;
- int num_expressions_without_args =
- frame->ComputeExpressionsCount() - location.CallArgumentsCount();
- DCHECK(num_expressions_without_args >= base);
- Object* fun = frame->GetExpression(num_expressions_without_args - base);
-
- // Flood the actual target of call/apply.
- if (location.IsCall() && fun->IsJSFunction()) {
- Isolate* isolate = JSFunction::cast(fun)->GetIsolate();
- Code* apply = isolate->builtins()->builtin(Builtins::kFunctionApply);
- Code* call = isolate->builtins()->builtin(Builtins::kFunctionCall);
- // Find target function on the expression stack for expression like
- // Function.call.call...apply(...)
- int i = 1;
- while (fun->IsJSFunction()) {
- Code* code = JSFunction::cast(fun)->shared()->code();
- if (code != apply && code != call) break;
- DCHECK(num_expressions_without_args >= i);
- fun = frame->GetExpression(num_expressions_without_args - i);
- i--;
- }
- }
-
- if (fun->IsJSFunction()) {
- Handle<JSFunction> js_function(JSFunction::cast(fun));
- FloodWithOneShotGeneric(js_function);
- }
}
-
- ActivateStepIn(frame);
}
// Fill the current function with one-shot break points even for step in on
@@ -1111,36 +1047,15 @@ Handle<Object> Debug::GetSourceBreakLocations(
}
-// Handle stepping into a function.
-void Debug::HandleStepIn(Handle<Object> function_obj) {
- // Flood getter/setter if we either step in or step to another frame.
- bool step_frame = thread_local_.last_step_action_ == StepFrame;
- if (!StepInActive() && !step_frame) return;
- if (!function_obj->IsJSFunction()) return;
- Handle<JSFunction> function = Handle<JSFunction>::cast(function_obj);
- Isolate* isolate = function->GetIsolate();
-
- StackFrameIterator it(isolate);
- it.Advance();
- Address fp = it.frame()->fp();
-
- // Flood the function with one-shot break points if it is called from where
- // step into was requested, or when stepping into a new frame.
- if (fp == thread_local_.step_into_fp_ || step_frame) {
- FloodWithOneShotGeneric(function, Handle<Object>());
- }
-}
-
-
void Debug::ClearStepping() {
// Clear the various stepping setup.
ClearOneShot();
- ClearStepIn();
ClearStepOut();
- ClearStepNext();
- // Clear multiple step counter.
thread_local_.step_count_ = 0;
+ thread_local_.last_step_action_ = StepNone;
+ thread_local_.last_statement_position_ = RelocInfo::kNoPosition;
+ thread_local_.last_fp_ = 0;
}
@@ -1161,33 +1076,18 @@ void Debug::ClearOneShot() {
}
-void Debug::ActivateStepIn(StackFrame* frame) {
- DCHECK(!StepOutActive());
- thread_local_.step_into_fp_ = frame->UnpaddedFP();
-}
-
-
-void Debug::ClearStepIn() {
- thread_local_.step_into_fp_ = 0;
-}
-
-
void Debug::ActivateStepOut(StackFrame* frame) {
- DCHECK(!StepInActive());
thread_local_.step_out_fp_ = frame->UnpaddedFP();
}
-void Debug::ClearStepOut() {
- thread_local_.step_out_fp_ = 0;
+void Debug::EnableStepIn() {
+ STATIC_ASSERT(StepFrame > StepIn);
+ thread_local_.step_in_enabled_ = (last_step_action() >= StepIn);
}
-void Debug::ClearStepNext() {
- thread_local_.last_step_action_ = StepNone;
- thread_local_.last_statement_position_ = RelocInfo::kNoPosition;
- thread_local_.last_fp_ = 0;
-}
+void Debug::ClearStepOut() { thread_local_.step_out_fp_ = 0; }
bool MatchingCodeTargets(Code* target1, Code* target2) {
@@ -1542,11 +1442,6 @@ bool Debug::EnsureDebugInfo(Handle<SharedFunctionInfo> shared,
if (!PrepareFunctionForBreakPoints(shared)) return false;
- // Make sure IC state is clean. This is so that we correctly flood
- // accessor pairs when stepping in.
- shared->code()->ClearInlineCaches();
- shared->ClearTypeFeedbackInfo();
-
CreateDebugInfo(shared);
return true;
@@ -2358,7 +2253,6 @@ DebugScope::DebugScope(Debug* debug)
}
-
DebugScope::~DebugScope() {
if (!failed_ && prev_ == NULL) {
// Clear mirror cache when leaving the debugger. Skip this if there is a
« no previous file with comments | « src/debug/debug.h ('k') | src/ia32/macro-assembler-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698