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

Unified Diff: src/debug.cc

Issue 942003002: Fix GC-unsafe use of BreakLocationIterator. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 10 months 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.h ('k') | test/mjsunit/mjsunit.status » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/debug.cc
diff --git a/src/debug.cc b/src/debug.cc
index 324d96f333fa21141415041c3640fb8af6957064..46c9e1ebdef10dfb71204d89384a06b7a6eec807 100644
--- a/src/debug.cc
+++ b/src/debug.cc
@@ -387,40 +387,6 @@ bool BreakLocationIterator::IsStepInLocation(Isolate* isolate) {
}
-void BreakLocationIterator::PrepareStepIn(Isolate* isolate) {
-#ifdef DEBUG
- HandleScope scope(isolate);
- // Step in can only be prepared if currently positioned on an IC call,
- // construct call or CallFunction stub call.
- Address target = rinfo()->target_address();
- Handle<Code> target_code(Code::GetCodeFromTargetAddress(target));
- // All the following stuff is needed only for assertion checks so the code
- // is wrapped in ifdef.
- Handle<Code> maybe_call_function_stub = target_code;
- if (IsDebugBreak()) {
- Address original_target = original_rinfo()->target_address();
- maybe_call_function_stub =
- Handle<Code>(Code::GetCodeFromTargetAddress(original_target));
- }
- bool is_call_function_stub =
- (maybe_call_function_stub->kind() == Code::STUB &&
- CodeStub::GetMajorKey(*maybe_call_function_stub) ==
- CodeStub::CallFunction);
-
- // Step in through construct call requires no changes to the running code.
- // Step in through getters/setters should already be prepared as well
- // because caller of this function (Debug::PrepareStep) is expected to
- // flood the top frame's function with one shot breakpoints.
- // Step in through CallFunction stub should also be prepared by caller of
- // this function (Debug::PrepareStep) which should flood target function
- // with breakpoints.
- DCHECK(RelocInfo::IsConstructCall(rmode()) ||
- target_code->is_inline_cache_stub() ||
- is_call_function_stub);
-#endif
-}
-
-
// Check whether the break point is at a position which will exit the function.
bool BreakLocationIterator::IsExit() const {
return (RelocInfo::IsJSReturn(rmode()));
@@ -1371,62 +1337,68 @@ void Debug::PrepareStep(StepAction step_action,
}
Handle<DebugInfo> debug_info = GetDebugInfo(shared);
- // Find the break location where execution has stopped.
- BreakLocationIterator it(debug_info, ALL_BREAK_LOCATIONS);
- // pc points to the instruction after the current one, possibly a break
- // location as well. So the "- 1" to exclude it from the search.
- it.FindBreakLocationFromAddress(frame->pc() - 1);
-
// Compute whether or not the target is a call target.
bool is_load_or_store = false;
bool is_inline_cache_stub = false;
bool is_at_restarted_function = false;
+ bool is_exit = false;
+ bool is_construct_call = false;
Handle<Code> call_function_stub;
- if (thread_local_.restarter_frame_function_pointer_ == NULL) {
- if (RelocInfo::IsCodeTarget(it.rinfo()->rmode())) {
- bool is_call_target = false;
- Address target = it.rinfo()->target_address();
- Code* code = Code::GetCodeFromTargetAddress(target);
- if (code->is_call_stub()) {
- is_call_target = true;
- }
- if (code->is_inline_cache_stub()) {
- is_inline_cache_stub = true;
- is_load_or_store = !is_call_target;
- }
-
- // Check if target code is CallFunction stub.
- Code* maybe_call_function_stub = code;
- // If there is a breakpoint at this line look at the original code to
- // check if it is a CallFunction stub.
- if (it.IsDebugBreak()) {
- Address original_target = it.original_rinfo()->target_address();
- maybe_call_function_stub =
- Code::GetCodeFromTargetAddress(original_target);
- }
- if ((maybe_call_function_stub->kind() == Code::STUB &&
- CodeStub::GetMajorKey(maybe_call_function_stub) ==
- CodeStub::CallFunction) ||
- maybe_call_function_stub->is_call_stub()) {
- // Save reference to the code as we may need it to find out arguments
- // count for 'step in' later.
- call_function_stub = Handle<Code>(maybe_call_function_stub);
+ {
+ // Find the break location where execution has stopped.
+ DisallowHeapAllocation no_gc;
+ BreakLocationIterator it(debug_info, ALL_BREAK_LOCATIONS);
+
+ // pc points to the instruction after the current one, possibly a break
+ // location as well. So the "- 1" to exclude it from the search.
+ it.FindBreakLocationFromAddress(frame->pc() - 1);
+
+ is_exit = it.IsExit();
+
+ if (thread_local_.restarter_frame_function_pointer_ == NULL) {
+ if (RelocInfo::IsCodeTarget(it.rinfo()->rmode())) {
+ bool is_call_target = false;
+ Address target = it.rinfo()->target_address();
+ Code* code = Code::GetCodeFromTargetAddress(target);
+
+ is_call_target = code->is_call_stub();
+ is_construct_call = RelocInfo::IsConstructCall(it.rmode());
+ is_inline_cache_stub = code->is_inline_cache_stub();
+ is_load_or_store = is_inline_cache_stub && !is_call_target;
+
+ // Check if target code is CallFunction stub.
+ Code* maybe_call_function_stub = code;
+ // If there is a breakpoint at this line look at the original code to
+ // check if it is a CallFunction stub.
+ if (it.IsDebugBreak()) {
+ Address original_target = it.original_rinfo()->target_address();
+ maybe_call_function_stub =
+ Code::GetCodeFromTargetAddress(original_target);
+ }
+ if ((maybe_call_function_stub->kind() == Code::STUB &&
+ CodeStub::GetMajorKey(maybe_call_function_stub) ==
+ CodeStub::CallFunction) ||
+ maybe_call_function_stub->is_call_stub()) {
+ // Save reference to the code as we may need it to find out arguments
+ // count for 'step in' later.
+ call_function_stub = Handle<Code>(maybe_call_function_stub);
+ }
}
+ } else {
+ is_at_restarted_function = true;
}
- } else {
- is_at_restarted_function = true;
}
// If this is the last break code target step out is the only possibility.
- if (it.IsExit() || step_action == StepOut) {
+ if (is_exit || step_action == StepOut) {
if (step_action == StepOut) {
// Skip step_count frames starting with the current one.
while (step_count-- > 0 && !frames_it.done()) {
frames_it.Advance();
}
} else {
- DCHECK(it.IsExit());
+ DCHECK(is_exit);
frames_it.Advance();
}
// Skip builtin functions on the stack.
@@ -1443,9 +1415,9 @@ void Debug::PrepareStep(StepAction step_action,
// Set target frame pointer.
ActivateStepOut(frames_it.frame());
}
- } else if (!(is_inline_cache_stub || RelocInfo::IsConstructCall(it.rmode()) ||
- !call_function_stub.is_null() || is_at_restarted_function)
- || step_action == StepNext || step_action == StepMin) {
+ } else if (!(is_inline_cache_stub || is_construct_call ||
+ !call_function_stub.is_null() || is_at_restarted_function) ||
+ step_action == StepNext || step_action == StepMin) {
// Step next or step min.
// Fill the current function with one-shot break points.
@@ -1532,7 +1504,15 @@ void Debug::PrepareStep(StepAction step_action,
}
// Step in or Step in min
- it.PrepareStepIn(isolate_);
+ // Step in through construct call requires no changes to the running code.
+ // Step in through getters/setters should already be prepared as well
+ // because caller of this function (Debug::PrepareStep) is expected to
+ // flood the top frame's function with one shot breakpoints.
+ // Step in through CallFunction stub should also be prepared by caller of
+ // this function (Debug::PrepareStep) which should flood target function
+ // with breakpoints.
+ DCHECK(is_construct_call || is_inline_cache_stub ||
+ !call_function_stub.is_null());
ActivateStepIn(frame);
}
}
« no previous file with comments | « src/debug.h ('k') | test/mjsunit/mjsunit.status » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698