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

Side by Side Diff: src/debug/debug.cc

Issue 1682853004: [interpreter, debugger] implement bytecode break location iterator. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: small fix Created 4 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 unified diff | Download patch
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/debug/debug.h" 5 #include "src/debug/debug.h"
6 6
7 #include "src/api.h" 7 #include "src/api.h"
8 #include "src/arguments.h" 8 #include "src/arguments.h"
9 #include "src/bootstrapper.h" 9 #include "src/bootstrapper.h"
10 #include "src/code-stubs.h" 10 #include "src/code-stubs.h"
11 #include "src/codegen.h" 11 #include "src/codegen.h"
12 #include "src/compilation-cache.h" 12 #include "src/compilation-cache.h"
13 #include "src/compiler.h" 13 #include "src/compiler.h"
14 #include "src/deoptimizer.h" 14 #include "src/deoptimizer.h"
15 #include "src/execution.h" 15 #include "src/execution.h"
16 #include "src/frames-inl.h" 16 #include "src/frames-inl.h"
17 #include "src/full-codegen/full-codegen.h" 17 #include "src/full-codegen/full-codegen.h"
18 #include "src/global-handles.h" 18 #include "src/global-handles.h"
19 #include "src/interpreter/bytecodes.h"
19 #include "src/isolate-inl.h" 20 #include "src/isolate-inl.h"
20 #include "src/list.h" 21 #include "src/list.h"
21 #include "src/log.h" 22 #include "src/log.h"
22 #include "src/messages.h" 23 #include "src/messages.h"
23 #include "src/snapshot/natives.h" 24 #include "src/snapshot/natives.h"
24 25
25 #include "include/v8-debug.h" 26 #include "include/v8-debug.h"
26 27
27 namespace v8 { 28 namespace v8 {
28 namespace internal { 29 namespace internal {
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
62 int code_offset, int position, 63 int code_offset, int position,
63 int statement_position) 64 int statement_position)
64 : debug_info_(debug_info), 65 : debug_info_(debug_info),
65 code_offset_(code_offset), 66 code_offset_(code_offset),
66 type_(type), 67 type_(type),
67 position_(position), 68 position_(position),
68 statement_position_(statement_position) {} 69 statement_position_(statement_position) {}
69 70
70 BreakLocation::Iterator* BreakLocation::GetIterator( 71 BreakLocation::Iterator* BreakLocation::GetIterator(
71 Handle<DebugInfo> debug_info, BreakLocatorType type) { 72 Handle<DebugInfo> debug_info, BreakLocatorType type) {
72 if (debug_info->shared()->HasBytecodeArray()) { 73 if (debug_info->abstract_code()->IsBytecodeArray()) {
73 UNIMPLEMENTED(); 74 return new BytecodeArrayIterator(debug_info, type);
74 return nullptr;
75 } 75 }
rmcilroy 2016/02/11 12:32:03 nit - make this an else? Seems lopsided to me to m
Yang 2016/02/11 14:16:55 Done.
76 return new CodeIterator(debug_info, type); 76 return new CodeIterator(debug_info, type);
77 } 77 }
78 78
79 BreakLocation::Iterator::Iterator(Handle<DebugInfo> debug_info, 79 BreakLocation::Iterator::Iterator(Handle<DebugInfo> debug_info)
80 BreakLocatorType type)
81 : debug_info_(debug_info), 80 : debug_info_(debug_info),
82 break_index_(-1), 81 break_index_(-1),
83 position_(1), 82 position_(1),
84 statement_position_(1) { 83 statement_position_(1) {}
85 }
86 84
87 BreakLocation::CodeIterator::CodeIterator(Handle<DebugInfo> debug_info, 85 BreakLocation::CodeIterator::CodeIterator(Handle<DebugInfo> debug_info,
88 BreakLocatorType type) 86 BreakLocatorType type)
89 : Iterator(debug_info, type), 87 : Iterator(debug_info),
90 reloc_iterator_(debug_info->abstract_code()->GetCode(), 88 reloc_iterator_(debug_info->abstract_code()->GetCode(),
91 GetModeMask(type)) { 89 GetModeMask(type)) {
92 if (!Done()) Next(); 90 if (!Done()) Next();
93 } 91 }
94 92
95 int BreakLocation::CodeIterator::GetModeMask(BreakLocatorType type) { 93 int BreakLocation::CodeIterator::GetModeMask(BreakLocatorType type) {
96 int mask = 0; 94 int mask = 0;
97 mask |= RelocInfo::ModeMask(RelocInfo::POSITION); 95 mask |= RelocInfo::ModeMask(RelocInfo::POSITION);
98 mask |= RelocInfo::ModeMask(RelocInfo::STATEMENT_POSITION); 96 mask |= RelocInfo::ModeMask(RelocInfo::STATEMENT_POSITION);
99 mask |= RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_RETURN); 97 mask |= RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_RETURN);
100 mask |= RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_CALL); 98 mask |= RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_CALL);
101 if (type == ALL_BREAK_LOCATIONS) { 99 if (type == ALL_BREAK_LOCATIONS) {
102 mask |= RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_POSITION); 100 mask |= RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_POSITION);
103 mask |= RelocInfo::ModeMask(RelocInfo::DEBUGGER_STATEMENT); 101 mask |= RelocInfo::ModeMask(RelocInfo::DEBUGGER_STATEMENT);
104 } 102 }
105 return mask; 103 return mask;
106 } 104 }
107 105
108 void BreakLocation::CodeIterator::Next() { 106 void BreakLocation::CodeIterator::Next() {
109 DisallowHeapAllocation no_gc; 107 DisallowHeapAllocation no_gc;
110 DCHECK(!Done()); 108 DCHECK(!Done());
111 109
112 // Iterate through reloc info for code and original code stopping at each 110 // Iterate through reloc info stopping at each breakable code target.
113 // breakable code target.
114 bool first = break_index_ == -1; 111 bool first = break_index_ == -1;
115 while (!Done()) { 112 while (!Done()) {
116 if (!first) reloc_iterator_.next(); 113 if (!first) reloc_iterator_.next();
117 first = false; 114 first = false;
118 if (Done()) return; 115 if (Done()) return;
119 116
120 // Whenever a statement position or (plain) position is passed update the 117 // Whenever a statement position or (plain) position is passed update the
121 // current value of these. 118 // current value of these.
122 if (RelocInfo::IsPosition(rmode())) { 119 if (RelocInfo::IsPosition(rmode())) {
123 if (RelocInfo::IsStatementPosition(rmode())) { 120 if (RelocInfo::IsStatementPosition(rmode())) {
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
162 type = DEBUGGER_STATEMENT; 159 type = DEBUGGER_STATEMENT;
163 } else if (RelocInfo::IsDebugBreakSlot(rmode())) { 160 } else if (RelocInfo::IsDebugBreakSlot(rmode())) {
164 type = DEBUG_BREAK_SLOT; 161 type = DEBUG_BREAK_SLOT;
165 } else { 162 } else {
166 type = NOT_DEBUG_BREAK; 163 type = NOT_DEBUG_BREAK;
167 } 164 }
168 return BreakLocation(debug_info_, type, code_offset(), position(), 165 return BreakLocation(debug_info_, type, code_offset(), position(),
169 statement_position()); 166 statement_position());
170 } 167 }
171 168
169 BreakLocation::BytecodeArrayIterator::BytecodeArrayIterator(
170 Handle<DebugInfo> debug_info, BreakLocatorType type)
171 : Iterator(debug_info),
172 iterator_(debug_info->abstract_code()->GetBytecodeArray()),
173 break_locator_type_(type),
174 start_position_(debug_info->shared()->start_position()) {
175 if (!Done()) Next();
176 }
177
178 void BreakLocation::BytecodeArrayIterator::Next() {
179 DisallowHeapAllocation no_gc;
180 DCHECK(!Done());
181 bool first = break_index_ == -1;
182 while (!Done()) {
183 if (!first) iterator_.Advance();
184 first = false;
185 if (Done()) return;
186 position_ = iterator_.source_position() - start_position_;
187 if (iterator_.is_statement()) statement_position_ = position_;
188 DCHECK(position_ >= 0);
189 DCHECK(statement_position_ >= 0);
190 break_index_++;
191
192 if (break_locator_type_ == ALL_BREAK_LOCATIONS) break;
193 DCHECK_EQ(CALLS_AND_RETURNS, break_locator_type_);
rmcilroy 2016/02/11 12:32:03 nit - new line above
Yang 2016/02/11 14:16:55 Done.
194 enum DebugBreakType type = DebugBreakType();
195 if (type == DEBUG_BREAK_SLOT_AT_CALL ||
196 type == DEBUG_BREAK_SLOT_AT_RETURN) {
197 break;
198 }
199 }
200 }
201
202 BreakLocation::DebugBreakType
203 BreakLocation::BytecodeArrayIterator::DebugBreakType() {
204 BytecodeArray* bytecode_array =
205 debug_info_->abstract_code()->GetBytecodeArray();
206 interpreter::Bytecode bytecode =
207 static_cast<interpreter::Bytecode>(bytecode_array->get(code_offset()));
208
209 switch (bytecode) {
210 case interpreter::Bytecode::kDebugger:
211 return DEBUGGER_STATEMENT;
212 case interpreter::Bytecode::kCall:
rmcilroy 2016/02/11 12:32:03 You need to list KCallWide and kNewWide as well (a
Yang 2016/02/11 14:16:55 Done.
213 case interpreter::Bytecode::kNew:
214 return DEBUG_BREAK_SLOT_AT_CALL;
215 case interpreter::Bytecode::kReturn:
216 return DEBUG_BREAK_SLOT_AT_RETURN;
217 default:
218 break;
219 }
220 return iterator_.is_statement() ? DEBUG_BREAK_SLOT : NOT_DEBUG_BREAK;
221 }
222
223 BreakLocation BreakLocation::BytecodeArrayIterator::GetBreakLocation() {
224 return BreakLocation(debug_info_, DebugBreakType(), code_offset(), position(),
225 statement_position());
226 }
227
172 // Find the break point at the supplied address, or the closest one before 228 // Find the break point at the supplied address, or the closest one before
173 // the address. 229 // the address.
174 BreakLocation BreakLocation::FromCodeOffset(Handle<DebugInfo> debug_info, 230 BreakLocation BreakLocation::FromCodeOffset(Handle<DebugInfo> debug_info,
175 int offset) { 231 int offset) {
176 base::SmartPointer<Iterator> it(GetIterator(debug_info)); 232 base::SmartPointer<Iterator> it(GetIterator(debug_info));
177 it->SkipTo(BreakIndexFromCodeOffset(debug_info, offset)); 233 it->SkipTo(BreakIndexFromCodeOffset(debug_info, offset));
178 return it->GetBreakLocation(); 234 return it->GetBreakLocation();
179 } 235 }
180 236
181 // Move GetFirstFrameSummary Definition to here as FromFrame use it. 237 // Move GetFirstFrameSummary Definition to here as FromFrame use it.
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after
335 if (abstract_code()->IsCode()) { 391 if (abstract_code()->IsCode()) {
336 Code* code = abstract_code()->GetCode(); 392 Code* code = abstract_code()->GetCode();
337 DCHECK(code->kind() == Code::FUNCTION); 393 DCHECK(code->kind() == Code::FUNCTION);
338 Builtins* builtins = isolate()->builtins(); 394 Builtins* builtins = isolate()->builtins();
339 Handle<Code> target = IsReturn() ? builtins->Return_DebugBreak() 395 Handle<Code> target = IsReturn() ? builtins->Return_DebugBreak()
340 : builtins->Slot_DebugBreak(); 396 : builtins->Slot_DebugBreak();
341 Address pc = code->instruction_start() + code_offset(); 397 Address pc = code->instruction_start() + code_offset();
342 DebugCodegen::PatchDebugBreakSlot(isolate(), pc, target); 398 DebugCodegen::PatchDebugBreakSlot(isolate(), pc, target);
343 DCHECK(IsDebugBreak()); 399 DCHECK(IsDebugBreak());
344 } else { 400 } else {
345 UNIMPLEMENTED(); 401 // TODO(yangguo): implement this once we have a way to record break points.
346 } 402 }
347 } 403 }
348 404
349 405
350 void BreakLocation::ClearDebugBreak() { 406 void BreakLocation::ClearDebugBreak() {
351 // Debugger statement always calls debugger. No need to modify it. 407 // Debugger statement always calls debugger. No need to modify it.
352 if (IsDebuggerStatement()) return; 408 if (IsDebuggerStatement()) return;
353 409
354 DCHECK(IsDebugBreakSlot()); 410 DCHECK(IsDebugBreakSlot());
355 if (abstract_code()->IsCode()) { 411 if (abstract_code()->IsCode()) {
356 Code* code = abstract_code()->GetCode(); 412 Code* code = abstract_code()->GetCode();
357 DCHECK(code->kind() == Code::FUNCTION); 413 DCHECK(code->kind() == Code::FUNCTION);
358 Address pc = code->instruction_start() + code_offset(); 414 Address pc = code->instruction_start() + code_offset();
359 DebugCodegen::ClearDebugBreakSlot(isolate(), pc); 415 DebugCodegen::ClearDebugBreakSlot(isolate(), pc);
360 DCHECK(!IsDebugBreak()); 416 DCHECK(!IsDebugBreak());
361 } else { 417 } else {
362 UNIMPLEMENTED(); 418 // TODO(yangguo): implement this once we have a way to record break points.
363 } 419 }
364 } 420 }
365 421
366 422
367 bool BreakLocation::IsDebugBreak() const { 423 bool BreakLocation::IsDebugBreak() const {
368 if (IsDebuggerStatement()) return false; 424 if (IsDebuggerStatement()) return false;
369 DCHECK(IsDebugBreakSlot()); 425 DCHECK(IsDebugBreakSlot());
370 if (abstract_code()->IsCode()) { 426 if (abstract_code()->IsCode()) {
371 Code* code = abstract_code()->GetCode(); 427 Code* code = abstract_code()->GetCode();
372 DCHECK(code->kind() == Code::FUNCTION); 428 DCHECK(code->kind() == Code::FUNCTION);
373 Address pc = code->instruction_start() + code_offset(); 429 Address pc = code->instruction_start() + code_offset();
374 return DebugCodegen::DebugBreakSlotIsPatched(pc); 430 return DebugCodegen::DebugBreakSlotIsPatched(pc);
375 } else { 431 } else {
376 UNIMPLEMENTED(); 432 // TODO(yangguo): implement this once we have a way to record break points.
377 return false; 433 return false;
378 } 434 }
379 } 435 }
380 436
381 437
382 Handle<Object> BreakLocation::BreakPointObjects() const { 438 Handle<Object> BreakLocation::BreakPointObjects() const {
383 return debug_info_->GetBreakPointObjects(code_offset_); 439 return debug_info_->GetBreakPointObjects(code_offset_);
384 } 440 }
385 441
386 void DebugFeatureTracker::Track(DebugFeatureTracker::Feature feature) { 442 void DebugFeatureTracker::Track(DebugFeatureTracker::Feature feature) {
(...skipping 769 matching lines...) Expand 10 before | Expand all | Expand 10 after
1156 public: 1212 public:
1157 explicit RedirectActiveFunctions(SharedFunctionInfo* shared) 1213 explicit RedirectActiveFunctions(SharedFunctionInfo* shared)
1158 : shared_(shared) { 1214 : shared_(shared) {
1159 DCHECK(shared->HasDebugCode()); 1215 DCHECK(shared->HasDebugCode());
1160 } 1216 }
1161 1217
1162 void VisitThread(Isolate* isolate, ThreadLocalTop* top) { 1218 void VisitThread(Isolate* isolate, ThreadLocalTop* top) {
1163 for (JavaScriptFrameIterator it(isolate, top); !it.done(); it.Advance()) { 1219 for (JavaScriptFrameIterator it(isolate, top); !it.done(); it.Advance()) {
1164 JavaScriptFrame* frame = it.frame(); 1220 JavaScriptFrame* frame = it.frame();
1165 JSFunction* function = frame->function(); 1221 JSFunction* function = frame->function();
1222 if (frame->is_interpreted()) {
1223 // TODO(yangguo): replace dispatch table for activated frames.
1224 continue;
1225 }
1166 if (frame->is_optimized()) continue; 1226 if (frame->is_optimized()) continue;
1167 if (!function->Inlines(shared_)) continue; 1227 if (!function->Inlines(shared_)) continue;
1168 1228
1169 Code* frame_code = frame->LookupCode(); 1229 Code* frame_code = frame->LookupCode();
1170 DCHECK(frame_code->kind() == Code::FUNCTION); 1230 DCHECK(frame_code->kind() == Code::FUNCTION);
1171 if (frame_code->has_debug_break_slots()) continue; 1231 if (frame_code->has_debug_break_slots()) continue;
1172 1232
1173 Code* new_code = function->shared()->code(); 1233 Code* new_code = function->shared()->code();
1174 Address old_pc = frame->pc(); 1234 Address old_pc = frame->pc();
1175 Address new_pc = ComputeNewPcForRedirect(new_code, frame_code, old_pc); 1235 Address new_pc = ComputeNewPcForRedirect(new_code, frame_code, old_pc);
(...skipping 1329 matching lines...) Expand 10 before | Expand all | Expand 10 after
2505 } 2565 }
2506 2566
2507 2567
2508 void LockingCommandMessageQueue::Clear() { 2568 void LockingCommandMessageQueue::Clear() {
2509 base::LockGuard<base::Mutex> lock_guard(&mutex_); 2569 base::LockGuard<base::Mutex> lock_guard(&mutex_);
2510 queue_.Clear(); 2570 queue_.Clear();
2511 } 2571 }
2512 2572
2513 } // namespace internal 2573 } // namespace internal
2514 } // namespace v8 2574 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698