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

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

Issue 2238893002: [debugger] separate break point info from code instrumentation. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: fix Created 4 years, 4 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
« no previous file with comments | « src/debug/debug.h ('k') | src/factory.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 <memory> 7 #include <memory>
8 8
9 #include "src/api.h" 9 #include "src/api.h"
10 #include "src/arguments.h" 10 #include "src/arguments.h"
(...skipping 15 matching lines...) Expand all
26 #include "src/messages.h" 26 #include "src/messages.h"
27 #include "src/snapshot/natives.h" 27 #include "src/snapshot/natives.h"
28 #include "src/wasm/wasm-debug.h" 28 #include "src/wasm/wasm-debug.h"
29 #include "src/wasm/wasm-module.h" 29 #include "src/wasm/wasm-module.h"
30 30
31 #include "include/v8-debug.h" 31 #include "include/v8-debug.h"
32 32
33 namespace v8 { 33 namespace v8 {
34 namespace internal { 34 namespace internal {
35 35
36 namespace {
37
38 inline int CallOffsetFromCodeOffset(int code_offset, bool is_interpreted) {
39 // Code offset points to the instruction after the call. Subtract 1 to
40 // exclude that instruction from the search. For bytecode, the code offset
41 // still points to the call.
42 return is_interpreted ? code_offset : code_offset - 1;
43 }
44
45 } // namespace
46
47 Debug::Debug(Isolate* isolate) 36 Debug::Debug(Isolate* isolate)
48 : debug_context_(Handle<Context>()), 37 : debug_context_(Handle<Context>()),
49 event_listener_(Handle<Object>()), 38 event_listener_(Handle<Object>()),
50 event_listener_data_(Handle<Object>()), 39 event_listener_data_(Handle<Object>()),
51 message_handler_(NULL), 40 message_handler_(NULL),
52 command_received_(0), 41 command_received_(0),
53 command_queue_(isolate->logger(), kQueueInitialSize), 42 command_queue_(isolate->logger(), kQueueInitialSize),
54 is_active_(false), 43 is_active_(false),
55 is_suppressed_(false), 44 is_suppressed_(false),
56 live_edit_enabled_(true), // TODO(yangguo): set to false by default. 45 live_edit_enabled_(true), // TODO(yangguo): set to false by default.
57 break_disabled_(false), 46 break_disabled_(false),
58 break_points_active_(true), 47 break_points_active_(true),
59 in_debug_event_listener_(false), 48 in_debug_event_listener_(false),
60 break_on_exception_(false), 49 break_on_exception_(false),
61 break_on_uncaught_exception_(false), 50 break_on_uncaught_exception_(false),
62 debug_info_list_(NULL), 51 debug_info_list_(NULL),
63 feature_tracker_(isolate), 52 feature_tracker_(isolate),
64 isolate_(isolate) { 53 isolate_(isolate) {
65 ThreadInit(); 54 ThreadInit();
66 } 55 }
67 56
68 57 BreakLocation BreakLocation::FromFrame(Handle<DebugInfo> debug_info,
69 static v8::Local<v8::Context> GetDebugEventContext(Isolate* isolate) { 58 JavaScriptFrame* frame) {
70 Handle<Context> context = isolate->debug()->debugger_entry()->GetContext(); 59 FrameSummary summary = FrameSummary::GetFirst(frame);
71 // Isolate::context() may have been NULL when "script collected" event 60 int offset = summary.code_offset();
72 // occured. 61 Handle<AbstractCode> abstract_code = summary.abstract_code();
73 if (context.is_null()) return v8::Local<v8::Context>(); 62 if (abstract_code->IsCode()) offset = offset - 1;
74 Handle<Context> native_context(context->native_context()); 63 auto it = BreakIterator::GetIterator(debug_info, abstract_code);
75 return v8::Utils::ToLocal(native_context); 64 it->SkipTo(BreakIndexFromCodeOffset(debug_info, abstract_code, offset));
65 return it->GetBreakLocation();
76 } 66 }
77 67
78 BreakLocation::BreakLocation(Handle<DebugInfo> debug_info, DebugBreakType type, 68 void BreakLocation::AllAtCurrentStatement(Handle<DebugInfo> debug_info,
79 int code_offset, int position, 69 JavaScriptFrame* frame,
80 int statement_position) 70 List<BreakLocation>* result_out) {
81 : debug_info_(debug_info), 71 FrameSummary summary = FrameSummary::GetFirst(frame);
82 code_offset_(code_offset), 72 int offset = summary.code_offset();
83 type_(type), 73 Handle<AbstractCode> abstract_code = summary.abstract_code();
84 position_(position), 74 if (abstract_code->IsCode()) offset = offset - 1;
85 statement_position_(statement_position) {} 75 int statement_position;
86 76 {
87 BreakLocation::Iterator* BreakLocation::GetIterator( 77 auto it = BreakIterator::GetIterator(debug_info, abstract_code);
88 Handle<DebugInfo> debug_info, BreakLocatorType type) { 78 it->SkipTo(BreakIndexFromCodeOffset(debug_info, abstract_code, offset));
89 if (debug_info->abstract_code()->IsBytecodeArray()) { 79 statement_position = it->statement_position();
90 return new BytecodeArrayIterator(debug_info, type); 80 }
91 } else { 81 for (auto it = BreakIterator::GetIterator(debug_info, abstract_code);
92 return new CodeIterator(debug_info, type); 82 !it->Done(); it->Next()) {
83 if (it->statement_position() == statement_position) {
84 result_out->Add(it->GetBreakLocation());
85 }
93 } 86 }
94 } 87 }
95 88
96 BreakLocation::Iterator::Iterator(Handle<DebugInfo> debug_info) 89 int BreakLocation::BreakIndexFromCodeOffset(Handle<DebugInfo> debug_info,
97 : debug_info_(debug_info), break_index_(-1) { 90 Handle<AbstractCode> abstract_code,
91 int offset) {
92 // Run through all break points to locate the one closest to the address.
93 int closest_break = 0;
94 int distance = kMaxInt;
95 DCHECK(0 <= offset && offset < abstract_code->Size());
96 for (auto it = BreakIterator::GetIterator(debug_info, abstract_code);
97 !it->Done(); it->Next()) {
98 // Check if this break point is closer that what was previously found.
99 if (it->code_offset() <= offset && offset - it->code_offset() < distance) {
100 closest_break = it->break_index();
101 distance = offset - it->code_offset();
102 // Check whether we can't get any closer.
103 if (distance == 0) break;
104 }
105 }
106 return closest_break;
107 }
108
109 bool BreakLocation::HasBreakPoint(Handle<DebugInfo> debug_info) const {
110 // First check whether there is a break point with the same source position.
111 if (!debug_info->HasBreakPoint(position_)) return false;
112 // Then check whether a break point at that source position would have
113 // the same code offset. Otherwise it's just a break location that we can
114 // step to, but not actually a location where we can put a break point.
115 if (abstract_code_->IsCode()) {
116 DCHECK_EQ(debug_info->DebugCode(), abstract_code_->GetCode());
117 CodeBreakIterator it(debug_info, ALL_BREAK_LOCATIONS);
118 it.SkipToPosition(position_, BREAK_POSITION_ALIGNED);
119 return it.code_offset() == code_offset_;
120 } else {
121 DCHECK(abstract_code_->IsBytecodeArray());
122 BytecodeArrayBreakIterator it(debug_info, ALL_BREAK_LOCATIONS);
123 it.SkipToPosition(position_, BREAK_POSITION_ALIGNED);
124 return it.code_offset() == code_offset_;
125 }
126 }
127
128 std::unique_ptr<BreakIterator> BreakIterator::GetIterator(
129 Handle<DebugInfo> debug_info, Handle<AbstractCode> abstract_code,
130 BreakLocatorType type) {
131 if (abstract_code->IsBytecodeArray()) {
132 DCHECK(debug_info->HasDebugBytecodeArray());
133 return std::unique_ptr<BreakIterator>(
134 new BytecodeArrayBreakIterator(debug_info, type));
135 } else {
136 DCHECK(abstract_code->IsCode());
137 DCHECK(debug_info->HasDebugCode());
138 return std::unique_ptr<BreakIterator>(
139 new CodeBreakIterator(debug_info, type));
140 }
141 }
142
143 BreakIterator::BreakIterator(Handle<DebugInfo> debug_info,
144 BreakLocatorType type)
145 : debug_info_(debug_info), break_index_(-1), break_locator_type_(type) {
98 position_ = debug_info->shared()->start_position(); 146 position_ = debug_info->shared()->start_position();
99 statement_position_ = position_; 147 statement_position_ = position_;
100 } 148 }
101 149
102 BreakLocation::CodeIterator::CodeIterator(Handle<DebugInfo> debug_info, 150 int BreakIterator::BreakIndexFromPosition(int source_position,
103 BreakLocatorType type) 151 BreakPositionAlignment alignment) {
104 : Iterator(debug_info), 152 int distance = kMaxInt;
105 reloc_iterator_(debug_info->abstract_code()->GetCode(), 153 int closest_break = break_index();
106 GetModeMask(type)), 154 while (!Done()) {
155 int next_position;
156 if (alignment == STATEMENT_ALIGNED) {
157 next_position = statement_position();
158 } else {
159 DCHECK(alignment == BREAK_POSITION_ALIGNED);
160 next_position = position();
161 }
162 if (source_position <= next_position &&
163 next_position - source_position < distance) {
164 closest_break = break_index();
165 distance = next_position - source_position;
166 // Check whether we can't get any closer.
167 if (distance == 0) break;
168 }
169 Next();
170 }
171 return closest_break;
172 }
173
174 CodeBreakIterator::CodeBreakIterator(Handle<DebugInfo> debug_info,
175 BreakLocatorType type)
176 : BreakIterator(debug_info, type),
177 reloc_iterator_(debug_info->DebugCode(), GetModeMask(type)),
107 source_position_iterator_( 178 source_position_iterator_(
108 debug_info->abstract_code()->GetCode()->source_position_table()) { 179 debug_info->DebugCode()->source_position_table()) {
109 // There is at least one break location. 180 // There is at least one break location.
110 DCHECK(!Done()); 181 DCHECK(!Done());
111 Next(); 182 Next();
112 } 183 }
113 184
114 int BreakLocation::CodeIterator::GetModeMask(BreakLocatorType type) { 185 int CodeBreakIterator::GetModeMask(BreakLocatorType type) {
115 int mask = 0; 186 int mask = 0;
116 mask |= RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_RETURN); 187 mask |= RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_RETURN);
117 mask |= RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_CALL); 188 mask |= RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_CALL);
118 if (isolate()->is_tail_call_elimination_enabled()) { 189 if (isolate()->is_tail_call_elimination_enabled()) {
119 mask |= RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_TAIL_CALL); 190 mask |= RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_TAIL_CALL);
120 } 191 }
121 if (type == ALL_BREAK_LOCATIONS) { 192 if (type == ALL_BREAK_LOCATIONS) {
122 mask |= RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_POSITION); 193 mask |= RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_POSITION);
123 mask |= RelocInfo::ModeMask(RelocInfo::DEBUGGER_STATEMENT); 194 mask |= RelocInfo::ModeMask(RelocInfo::DEBUGGER_STATEMENT);
124 } 195 }
125 return mask; 196 return mask;
126 } 197 }
127 198
128 void BreakLocation::CodeIterator::Next() { 199 void CodeBreakIterator::Next() {
129 DisallowHeapAllocation no_gc; 200 DisallowHeapAllocation no_gc;
130 DCHECK(!Done()); 201 DCHECK(!Done());
131 202
132 // Iterate through reloc info stopping at each breakable code target. 203 // Iterate through reloc info stopping at each breakable code target.
133 bool first = break_index_ == -1; 204 bool first = break_index_ == -1;
134 205
135 if (!first) reloc_iterator_.next(); 206 if (!first) reloc_iterator_.next();
136 first = false; 207 first = false;
137 if (Done()) return; 208 if (Done()) return;
138 209
139 int offset = code_offset(); 210 int offset = code_offset();
140 while (!source_position_iterator_.done() && 211 while (!source_position_iterator_.done() &&
141 source_position_iterator_.code_offset() <= offset) { 212 source_position_iterator_.code_offset() <= offset) {
142 position_ = source_position_iterator_.source_position(); 213 position_ = source_position_iterator_.source_position();
143 if (source_position_iterator_.is_statement()) { 214 if (source_position_iterator_.is_statement()) {
144 statement_position_ = position_; 215 statement_position_ = position_;
145 } 216 }
146 source_position_iterator_.Advance(); 217 source_position_iterator_.Advance();
147 } 218 }
148 219
149 DCHECK(RelocInfo::IsDebugBreakSlot(rmode()) || 220 DCHECK(RelocInfo::IsDebugBreakSlot(rmode()) ||
150 RelocInfo::IsDebuggerStatement(rmode())); 221 RelocInfo::IsDebuggerStatement(rmode()));
151 break_index_++; 222 break_index_++;
152 } 223 }
153 224
154 BreakLocation BreakLocation::CodeIterator::GetBreakLocation() { 225 DebugBreakType CodeBreakIterator::GetDebugBreakType() {
155 DebugBreakType type;
156 if (RelocInfo::IsDebugBreakSlotAtReturn(rmode())) { 226 if (RelocInfo::IsDebugBreakSlotAtReturn(rmode())) {
157 type = DEBUG_BREAK_SLOT_AT_RETURN; 227 return DEBUG_BREAK_SLOT_AT_RETURN;
158 } else if (RelocInfo::IsDebugBreakSlotAtCall(rmode())) { 228 } else if (RelocInfo::IsDebugBreakSlotAtCall(rmode())) {
159 type = DEBUG_BREAK_SLOT_AT_CALL; 229 return DEBUG_BREAK_SLOT_AT_CALL;
160 } else if (RelocInfo::IsDebugBreakSlotAtTailCall(rmode())) { 230 } else if (RelocInfo::IsDebugBreakSlotAtTailCall(rmode())) {
161 type = isolate()->is_tail_call_elimination_enabled() 231 return isolate()->is_tail_call_elimination_enabled()
162 ? DEBUG_BREAK_SLOT_AT_TAIL_CALL 232 ? DEBUG_BREAK_SLOT_AT_TAIL_CALL
163 : DEBUG_BREAK_SLOT_AT_CALL; 233 : DEBUG_BREAK_SLOT_AT_CALL;
164 } else if (RelocInfo::IsDebuggerStatement(rmode())) { 234 } else if (RelocInfo::IsDebuggerStatement(rmode())) {
165 type = DEBUGGER_STATEMENT; 235 return DEBUGGER_STATEMENT;
166 } else if (RelocInfo::IsDebugBreakSlot(rmode())) { 236 } else if (RelocInfo::IsDebugBreakSlot(rmode())) {
167 type = DEBUG_BREAK_SLOT; 237 return DEBUG_BREAK_SLOT;
168 } else { 238 } else {
169 type = NOT_DEBUG_BREAK; 239 return NOT_DEBUG_BREAK;
170 } 240 }
171 return BreakLocation(debug_info_, type, code_offset(), position(),
172 statement_position());
173 } 241 }
174 242
175 BreakLocation::BytecodeArrayIterator::BytecodeArrayIterator( 243 void CodeBreakIterator::SkipToPosition(int position,
244 BreakPositionAlignment alignment) {
245 CodeBreakIterator it(debug_info_, break_locator_type_);
246 SkipTo(it.BreakIndexFromPosition(position, alignment));
247 }
248
249 void CodeBreakIterator::SetDebugBreak() {
250 DebugBreakType debug_break_type = GetDebugBreakType();
251 if (debug_break_type == DEBUGGER_STATEMENT) return;
252 DCHECK(debug_break_type >= DEBUG_BREAK_SLOT);
253 Builtins* builtins = isolate()->builtins();
254 Handle<Code> target = debug_break_type == DEBUG_BREAK_SLOT_AT_RETURN
255 ? builtins->Return_DebugBreak()
256 : builtins->Slot_DebugBreak();
257 DebugCodegen::PatchDebugBreakSlot(isolate(), rinfo()->pc(), target);
258 }
259
260 void CodeBreakIterator::ClearDebugBreak() {
261 DebugBreakType debug_break_type = GetDebugBreakType();
262 if (debug_break_type == DEBUGGER_STATEMENT) return;
263 DCHECK(debug_break_type >= DEBUG_BREAK_SLOT);
264 DebugCodegen::ClearDebugBreakSlot(isolate(), rinfo()->pc());
265 }
266
267 bool CodeBreakIterator::IsDebugBreak() {
268 DebugBreakType debug_break_type = GetDebugBreakType();
269 if (debug_break_type == DEBUGGER_STATEMENT) return false;
270 DCHECK(debug_break_type >= DEBUG_BREAK_SLOT);
271 return DebugCodegen::DebugBreakSlotIsPatched(rinfo()->pc());
272 }
273
274 BreakLocation CodeBreakIterator::GetBreakLocation() {
275 Handle<AbstractCode> code(AbstractCode::cast(debug_info_->DebugCode()));
276 return BreakLocation(code, GetDebugBreakType(), code_offset(), position_);
277 }
278
279 BytecodeArrayBreakIterator::BytecodeArrayBreakIterator(
176 Handle<DebugInfo> debug_info, BreakLocatorType type) 280 Handle<DebugInfo> debug_info, BreakLocatorType type)
177 : Iterator(debug_info), 281 : BreakIterator(debug_info, type),
178 source_position_iterator_(debug_info->abstract_code() 282 source_position_iterator_(
179 ->GetBytecodeArray() 283 debug_info->DebugBytecodeArray()->source_position_table()) {
180 ->source_position_table()),
181 break_locator_type_(type) {
182 // There is at least one break location. 284 // There is at least one break location.
183 DCHECK(!Done()); 285 DCHECK(!Done());
184 Next(); 286 Next();
185 } 287 }
186 288
187 void BreakLocation::BytecodeArrayIterator::Next() { 289 void BytecodeArrayBreakIterator::Next() {
188 DisallowHeapAllocation no_gc; 290 DisallowHeapAllocation no_gc;
189 DCHECK(!Done()); 291 DCHECK(!Done());
190 bool first = break_index_ == -1; 292 bool first = break_index_ == -1;
191 while (!Done()) { 293 while (!Done()) {
192 if (!first) source_position_iterator_.Advance(); 294 if (!first) source_position_iterator_.Advance();
193 first = false; 295 first = false;
194 if (Done()) return; 296 if (Done()) return;
195 position_ = source_position_iterator_.source_position(); 297 position_ = source_position_iterator_.source_position();
196 if (source_position_iterator_.is_statement()) { 298 if (source_position_iterator_.is_statement()) {
197 statement_position_ = position_; 299 statement_position_ = position_;
198 } 300 }
199 DCHECK(position_ >= 0); 301 DCHECK(position_ >= 0);
200 DCHECK(statement_position_ >= 0); 302 DCHECK(statement_position_ >= 0);
201 303
202 enum DebugBreakType type = GetDebugBreakType(); 304 DebugBreakType type = GetDebugBreakType();
203 if (type == NOT_DEBUG_BREAK) continue; 305 if (type == NOT_DEBUG_BREAK) continue;
204 306
205 if (break_locator_type_ == ALL_BREAK_LOCATIONS) break; 307 if (break_locator_type_ == ALL_BREAK_LOCATIONS) break;
206 308
207 DCHECK_EQ(CALLS_AND_RETURNS, break_locator_type_); 309 DCHECK_EQ(CALLS_AND_RETURNS, break_locator_type_);
208 if (type == DEBUG_BREAK_SLOT_AT_CALL) break; 310 if (type == DEBUG_BREAK_SLOT_AT_CALL) break;
209 if (type == DEBUG_BREAK_SLOT_AT_RETURN) break; 311 if (type == DEBUG_BREAK_SLOT_AT_RETURN) break;
210 } 312 }
211 break_index_++; 313 break_index_++;
212 } 314 }
213 315
214 BreakLocation::DebugBreakType 316 DebugBreakType BytecodeArrayBreakIterator::GetDebugBreakType() {
215 BreakLocation::BytecodeArrayIterator::GetDebugBreakType() { 317 BytecodeArray* bytecode_array = debug_info_->OriginalBytecodeArray();
216 BytecodeArray* bytecode_array = debug_info_->original_bytecode_array();
217 interpreter::Bytecode bytecode = 318 interpreter::Bytecode bytecode =
218 interpreter::Bytecodes::FromByte(bytecode_array->get(code_offset())); 319 interpreter::Bytecodes::FromByte(bytecode_array->get(code_offset()));
219 320
220 if (bytecode == interpreter::Bytecode::kDebugger) { 321 if (bytecode == interpreter::Bytecode::kDebugger) {
221 return DEBUGGER_STATEMENT; 322 return DEBUGGER_STATEMENT;
222 } else if (bytecode == interpreter::Bytecode::kReturn) { 323 } else if (bytecode == interpreter::Bytecode::kReturn) {
223 return DEBUG_BREAK_SLOT_AT_RETURN; 324 return DEBUG_BREAK_SLOT_AT_RETURN;
224 } else if (bytecode == interpreter::Bytecode::kTailCall) { 325 } else if (bytecode == interpreter::Bytecode::kTailCall) {
225 return isolate()->is_tail_call_elimination_enabled() 326 return isolate()->is_tail_call_elimination_enabled()
226 ? DEBUG_BREAK_SLOT_AT_TAIL_CALL 327 ? DEBUG_BREAK_SLOT_AT_TAIL_CALL
227 : DEBUG_BREAK_SLOT_AT_CALL; 328 : DEBUG_BREAK_SLOT_AT_CALL;
228 } else if (interpreter::Bytecodes::IsCallOrNew(bytecode)) { 329 } else if (interpreter::Bytecodes::IsCallOrNew(bytecode)) {
229 return DEBUG_BREAK_SLOT_AT_CALL; 330 return DEBUG_BREAK_SLOT_AT_CALL;
230 } else if (source_position_iterator_.is_statement()) { 331 } else if (source_position_iterator_.is_statement()) {
231 return DEBUG_BREAK_SLOT; 332 return DEBUG_BREAK_SLOT;
232 } else { 333 } else {
233 return NOT_DEBUG_BREAK; 334 return NOT_DEBUG_BREAK;
234 } 335 }
235 } 336 }
236 337
237 BreakLocation BreakLocation::BytecodeArrayIterator::GetBreakLocation() { 338 void BytecodeArrayBreakIterator::SkipToPosition(
238 return BreakLocation(debug_info_, GetDebugBreakType(), code_offset(), 339 int position, BreakPositionAlignment alignment) {
239 position(), statement_position()); 340 BytecodeArrayBreakIterator it(debug_info_, break_locator_type_);
341 SkipTo(it.BreakIndexFromPosition(position, alignment));
240 } 342 }
241 343
242 // Find the break point at the supplied address, or the closest one before 344 void BytecodeArrayBreakIterator::SetDebugBreak() {
243 // the address. 345 DebugBreakType debug_break_type = GetDebugBreakType();
244 BreakLocation BreakLocation::FromCodeOffset(Handle<DebugInfo> debug_info, 346 if (debug_break_type == DEBUGGER_STATEMENT) return;
245 int offset) { 347 DCHECK(debug_break_type >= DEBUG_BREAK_SLOT);
246 std::unique_ptr<Iterator> it(GetIterator(debug_info)); 348 BytecodeArray* bytecode_array = debug_info_->DebugBytecodeArray();
247 it->SkipTo(BreakIndexFromCodeOffset(debug_info, offset)); 349 interpreter::Bytecode bytecode =
248 return it->GetBreakLocation(); 350 interpreter::Bytecodes::FromByte(bytecode_array->get(code_offset()));
351 if (interpreter::Bytecodes::IsDebugBreak(bytecode)) return;
352 interpreter::Bytecode debugbreak =
353 interpreter::Bytecodes::GetDebugBreak(bytecode);
354 bytecode_array->set(code_offset(),
355 interpreter::Bytecodes::ToByte(debugbreak));
249 } 356 }
250 357
251 BreakLocation BreakLocation::FromFrame(Handle<DebugInfo> debug_info, 358 void BytecodeArrayBreakIterator::ClearDebugBreak() {
252 JavaScriptFrame* frame) { 359 DebugBreakType debug_break_type = GetDebugBreakType();
253 int code_offset = FrameSummary::GetFirst(frame).code_offset(); 360 if (debug_break_type == DEBUGGER_STATEMENT) return;
254 int call_offset = 361 DCHECK(debug_break_type >= DEBUG_BREAK_SLOT);
255 CallOffsetFromCodeOffset(code_offset, frame->is_interpreted()); 362 BytecodeArray* bytecode_array = debug_info_->DebugBytecodeArray();
256 return FromCodeOffset(debug_info, call_offset); 363 BytecodeArray* original = debug_info_->OriginalBytecodeArray();
364 bytecode_array->set(code_offset(), original->get(code_offset()));
257 } 365 }
258 366
259 void BreakLocation::AllForStatementPosition(Handle<DebugInfo> debug_info, 367 bool BytecodeArrayBreakIterator::IsDebugBreak() {
260 int statement_position, 368 DebugBreakType debug_break_type = GetDebugBreakType();
261 List<BreakLocation>* result_out) { 369 if (debug_break_type == DEBUGGER_STATEMENT) return false;
262 for (std::unique_ptr<Iterator> it(GetIterator(debug_info)); !it->Done(); 370 DCHECK(debug_break_type >= DEBUG_BREAK_SLOT);
263 it->Next()) { 371 BytecodeArray* bytecode_array = debug_info_->DebugBytecodeArray();
264 if (it->statement_position() == statement_position) { 372 interpreter::Bytecode bytecode =
265 result_out->Add(it->GetBreakLocation()); 373 interpreter::Bytecodes::FromByte(bytecode_array->get(code_offset()));
266 } 374 return interpreter::Bytecodes::IsDebugBreak(bytecode);
267 }
268 } 375 }
269 376
270 int BreakLocation::BreakIndexFromCodeOffset(Handle<DebugInfo> debug_info, 377 BreakLocation BytecodeArrayBreakIterator::GetBreakLocation() {
271 int offset) { 378 Handle<AbstractCode> code(
272 // Run through all break points to locate the one closest to the address. 379 AbstractCode::cast(debug_info_->DebugBytecodeArray()));
273 int closest_break = 0; 380 return BreakLocation(code, GetDebugBreakType(), code_offset(), position_);
274 int distance = kMaxInt;
275 DCHECK(0 <= offset && offset < debug_info->abstract_code()->Size());
276 for (std::unique_ptr<Iterator> it(GetIterator(debug_info)); !it->Done();
277 it->Next()) {
278 // Check if this break point is closer that what was previously found.
279 if (it->code_offset() <= offset && offset - it->code_offset() < distance) {
280 closest_break = it->break_index();
281 distance = offset - it->code_offset();
282 // Check whether we can't get any closer.
283 if (distance == 0) break;
284 }
285 }
286 return closest_break;
287 } 381 }
288 382
289 383
290 BreakLocation BreakLocation::FromPosition(Handle<DebugInfo> debug_info,
291 int position,
292 BreakPositionAlignment alignment) {
293 // Run through all break points to locate the one closest to the source
294 // position.
295 int distance = kMaxInt;
296 std::unique_ptr<Iterator> it(GetIterator(debug_info));
297 BreakLocation closest_break = it->GetBreakLocation();
298 while (!it->Done()) {
299 int next_position;
300 if (alignment == STATEMENT_ALIGNED) {
301 next_position = it->statement_position();
302 } else {
303 DCHECK(alignment == BREAK_POSITION_ALIGNED);
304 next_position = it->position();
305 }
306 if (position <= next_position && next_position - position < distance) {
307 closest_break = it->GetBreakLocation();
308 distance = next_position - position;
309 // Check whether we can't get any closer.
310 if (distance == 0) break;
311 }
312 it->Next();
313 }
314 return closest_break;
315 }
316
317
318 void BreakLocation::SetBreakPoint(Handle<Object> break_point_object) {
319 // If there is not already a real break point here patch code with debug
320 // break.
321 if (!HasBreakPoint()) SetDebugBreak();
322 DCHECK(IsDebugBreak() || IsDebuggerStatement());
323 // Set the break point information.
324 DebugInfo::SetBreakPoint(debug_info_, position_, statement_position_,
325 break_point_object);
326 }
327
328
329 void BreakLocation::ClearBreakPoint(Handle<Object> break_point_object) {
330 // Clear the break point information.
331 DebugInfo::ClearBreakPoint(debug_info_, position_, break_point_object);
332 // If there are no more break points here remove the debug break.
333 if (!HasBreakPoint()) {
334 ClearDebugBreak();
335 DCHECK(!IsDebugBreak());
336 }
337 }
338
339
340 void BreakLocation::SetOneShot() {
341 // Debugger statement always calls debugger. No need to modify it.
342 if (IsDebuggerStatement()) return;
343
344 // Patch code with debug break.
345 SetDebugBreak();
346 }
347
348
349 void BreakLocation::ClearOneShot() {
350 // Debugger statement always calls debugger. No need to modify it.
351 if (IsDebuggerStatement()) return;
352
353 // If there is a real break point here no more to do.
354 if (HasBreakPoint()) {
355 DCHECK(IsDebugBreak());
356 return;
357 }
358
359 // Patch code removing debug break.
360 ClearDebugBreak();
361 DCHECK(!IsDebugBreak());
362 }
363
364
365 void BreakLocation::SetDebugBreak() {
366 // Debugger statement always calls debugger. No need to modify it.
367 if (IsDebuggerStatement()) return;
368
369 // If there is already a break point here just return. This might happen if
370 // the same code is flooded with break points twice. Flooding the same
371 // function twice might happen when stepping in a function with an exception
372 // handler as the handler and the function is the same.
373 if (IsDebugBreak()) return;
374
375 DCHECK(IsDebugBreakSlot());
376 if (abstract_code()->IsCode()) {
377 Code* code = abstract_code()->GetCode();
378 DCHECK(code->kind() == Code::FUNCTION);
379 Builtins* builtins = isolate()->builtins();
380 Handle<Code> target = IsReturn() ? builtins->Return_DebugBreak()
381 : builtins->Slot_DebugBreak();
382 Address pc = code->instruction_start() + code_offset();
383 DebugCodegen::PatchDebugBreakSlot(isolate(), pc, target);
384 } else {
385 BytecodeArray* bytecode_array = abstract_code()->GetBytecodeArray();
386 interpreter::Bytecode bytecode =
387 interpreter::Bytecodes::FromByte(bytecode_array->get(code_offset()));
388 interpreter::Bytecode debugbreak =
389 interpreter::Bytecodes::GetDebugBreak(bytecode);
390 bytecode_array->set(code_offset(),
391 interpreter::Bytecodes::ToByte(debugbreak));
392 }
393 DCHECK(IsDebugBreak());
394 }
395
396
397 void BreakLocation::ClearDebugBreak() {
398 // Debugger statement always calls debugger. No need to modify it.
399 if (IsDebuggerStatement()) return;
400
401 DCHECK(IsDebugBreakSlot());
402 if (abstract_code()->IsCode()) {
403 Code* code = abstract_code()->GetCode();
404 DCHECK(code->kind() == Code::FUNCTION);
405 Address pc = code->instruction_start() + code_offset();
406 DebugCodegen::ClearDebugBreakSlot(isolate(), pc);
407 } else {
408 BytecodeArray* bytecode_array = abstract_code()->GetBytecodeArray();
409 BytecodeArray* original = debug_info_->original_bytecode_array();
410 bytecode_array->set(code_offset(), original->get(code_offset()));
411 }
412 DCHECK(!IsDebugBreak());
413 }
414
415
416 bool BreakLocation::IsDebugBreak() const {
417 if (IsDebuggerStatement()) return false;
418 DCHECK(IsDebugBreakSlot());
419 if (abstract_code()->IsCode()) {
420 Code* code = abstract_code()->GetCode();
421 DCHECK(code->kind() == Code::FUNCTION);
422 Address pc = code->instruction_start() + code_offset();
423 return DebugCodegen::DebugBreakSlotIsPatched(pc);
424 } else {
425 BytecodeArray* bytecode_array = abstract_code()->GetBytecodeArray();
426 interpreter::Bytecode bytecode =
427 interpreter::Bytecodes::FromByte(bytecode_array->get(code_offset()));
428 return interpreter::Bytecodes::IsDebugBreak(bytecode);
429 }
430 }
431
432 Handle<Object> BreakLocation::BreakPointObjects() const {
433 return debug_info_->GetBreakPointObjects(position_);
434 }
435
436 bool BreakLocation::HasBreakPoint() const {
437 // First check whether there is a break point with the same source position.
438 if (!debug_info_->HasBreakPoint(position_)) return false;
439 // Then check whether a break point at that source position would have
440 // the same code offset. Otherwise it's just a break location that we can
441 // step to, but not actually a location where we can put a break point.
442 BreakLocation break_point_location = BreakLocation::FromPosition(
443 debug_info_, position_, BREAK_POSITION_ALIGNED);
444 return break_point_location.code_offset() == code_offset_;
445 }
446
447 void DebugFeatureTracker::Track(DebugFeatureTracker::Feature feature) { 384 void DebugFeatureTracker::Track(DebugFeatureTracker::Feature feature) {
448 uint32_t mask = 1 << feature; 385 uint32_t mask = 1 << feature;
449 // Only count one sample per feature and isolate. 386 // Only count one sample per feature and isolate.
450 if (bitfield_ & mask) return; 387 if (bitfield_ & mask) return;
451 isolate_->counters()->debug_feature_usage()->AddSample(feature); 388 isolate_->counters()->debug_feature_usage()->AddSample(feature);
452 bitfield_ |= mask; 389 bitfield_ |= mask;
453 } 390 }
454 391
455 392
456 // Threading support. 393 // Threading support.
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
575 if (!EnsureDebugInfo(shared, function)) { 512 if (!EnsureDebugInfo(shared, function)) {
576 // Return if we failed to retrieve the debug info. 513 // Return if we failed to retrieve the debug info.
577 return; 514 return;
578 } 515 }
579 Handle<DebugInfo> debug_info(shared->GetDebugInfo(), isolate_); 516 Handle<DebugInfo> debug_info(shared->GetDebugInfo(), isolate_);
580 517
581 // Find the break location where execution has stopped. 518 // Find the break location where execution has stopped.
582 BreakLocation location = BreakLocation::FromFrame(debug_info, frame); 519 BreakLocation location = BreakLocation::FromFrame(debug_info, frame);
583 520
584 // Find actual break points, if any, and trigger debug break event. 521 // Find actual break points, if any, and trigger debug break event.
585 Handle<Object> break_points_hit = CheckBreakPoints(&location); 522 Handle<Object> break_points_hit = CheckBreakPoints(debug_info, &location);
586 if (!break_points_hit->IsUndefined(isolate_)) { 523 if (!break_points_hit->IsUndefined(isolate_)) {
587 // Clear all current stepping setup. 524 // Clear all current stepping setup.
588 ClearStepping(); 525 ClearStepping();
589 // Notify the debug event listeners. 526 // Notify the debug event listeners.
590 OnDebugBreak(break_points_hit, false); 527 OnDebugBreak(break_points_hit, false);
591 return; 528 return;
592 } 529 }
593 530
594 // No break point. Check for stepping. 531 // No break point. Check for stepping.
595 StepAction step_action = last_step_action(); 532 StepAction step_action = last_step_action();
(...skipping 15 matching lines...) Expand all
611 if (current_fp < target_fp) return; 548 if (current_fp < target_fp) return;
612 // For step-next, a tail call is like a return and should break. 549 // For step-next, a tail call is like a return and should break.
613 step_break = location.IsTailCall(); 550 step_break = location.IsTailCall();
614 // Fall through. 551 // Fall through.
615 case StepIn: { 552 case StepIn: {
616 FrameSummary summary = FrameSummary::GetFirst(frame); 553 FrameSummary summary = FrameSummary::GetFirst(frame);
617 int offset = summary.code_offset(); 554 int offset = summary.code_offset();
618 step_break = step_break || location.IsReturn() || 555 step_break = step_break || location.IsReturn() ||
619 (current_fp != last_fp) || 556 (current_fp != last_fp) ||
620 (thread_local_.last_statement_position_ != 557 (thread_local_.last_statement_position_ !=
621 location.abstract_code()->SourceStatementPosition(offset)); 558 summary.abstract_code()->SourceStatementPosition(offset));
622 break; 559 break;
623 } 560 }
624 case StepFrame: 561 case StepFrame:
625 step_break = current_fp != last_fp; 562 step_break = current_fp != last_fp;
626 break; 563 break;
627 } 564 }
628 565
629 // Clear all current stepping setup. 566 // Clear all current stepping setup.
630 ClearStepping(); 567 ClearStepping();
631 568
632 if (step_break) { 569 if (step_break) {
633 // Notify the debug event listeners. 570 // Notify the debug event listeners.
634 OnDebugBreak(isolate_->factory()->undefined_value(), false); 571 OnDebugBreak(isolate_->factory()->undefined_value(), false);
635 } else { 572 } else {
636 // Re-prepare to continue. 573 // Re-prepare to continue.
637 PrepareStep(step_action); 574 PrepareStep(step_action);
638 } 575 }
639 } 576 }
640 577
641 578
642 // Find break point objects for this location, if any, and evaluate them. 579 // Find break point objects for this location, if any, and evaluate them.
643 // Return an array of break point objects that evaluated true. 580 // Return an array of break point objects that evaluated true.
644 Handle<Object> Debug::CheckBreakPoints(BreakLocation* location, 581 Handle<Object> Debug::CheckBreakPoints(Handle<DebugInfo> debug_info,
582 BreakLocation* location,
645 bool* has_break_points) { 583 bool* has_break_points) {
646 Factory* factory = isolate_->factory(); 584 Factory* factory = isolate_->factory();
647 bool has_break_points_to_check = 585 bool has_break_points_to_check =
648 break_points_active_ && location->HasBreakPoint(); 586 break_points_active_ && location->HasBreakPoint(debug_info);
649 if (has_break_points) *has_break_points = has_break_points_to_check; 587 if (has_break_points) *has_break_points = has_break_points_to_check;
650 if (!has_break_points_to_check) return factory->undefined_value(); 588 if (!has_break_points_to_check) return factory->undefined_value();
651 589
652 Handle<Object> break_point_objects = location->BreakPointObjects(); 590 Handle<Object> break_point_objects =
591 debug_info->GetBreakPointObjects(location->position());
653 // Count the number of break points hit. If there are multiple break points 592 // Count the number of break points hit. If there are multiple break points
654 // they are in a FixedArray. 593 // they are in a FixedArray.
655 Handle<FixedArray> break_points_hit; 594 Handle<FixedArray> break_points_hit;
656 int break_points_hit_count = 0; 595 int break_points_hit_count = 0;
657 DCHECK(!break_point_objects->IsUndefined(isolate_)); 596 DCHECK(!break_point_objects->IsUndefined(isolate_));
658 if (break_point_objects->IsFixedArray()) { 597 if (break_point_objects->IsFixedArray()) {
659 Handle<FixedArray> array(FixedArray::cast(*break_point_objects)); 598 Handle<FixedArray> array(FixedArray::cast(*break_point_objects));
660 break_points_hit = factory->NewFixedArray(array->length()); 599 break_points_hit = factory->NewFixedArray(array->length());
661 for (int i = 0; i < array->length(); i++) { 600 for (int i = 0; i < array->length(); i++) {
662 Handle<Object> break_point_object(array->get(i), isolate_); 601 Handle<Object> break_point_object(array->get(i), isolate_);
(...skipping 22 matching lines...) Expand all
685 // an exception event on exception at this location. 624 // an exception event on exception at this location.
686 Object* fun = frame->function(); 625 Object* fun = frame->function();
687 if (!fun->IsJSFunction()) return false; 626 if (!fun->IsJSFunction()) return false;
688 JSFunction* function = JSFunction::cast(fun); 627 JSFunction* function = JSFunction::cast(fun);
689 if (!function->shared()->HasDebugInfo()) return false; 628 if (!function->shared()->HasDebugInfo()) return false;
690 HandleScope scope(isolate_); 629 HandleScope scope(isolate_);
691 Handle<DebugInfo> debug_info(function->shared()->GetDebugInfo()); 630 Handle<DebugInfo> debug_info(function->shared()->GetDebugInfo());
692 // Enter the debugger. 631 // Enter the debugger.
693 DebugScope debug_scope(this); 632 DebugScope debug_scope(this);
694 if (debug_scope.failed()) return false; 633 if (debug_scope.failed()) return false;
695 BreakLocation current_position = BreakLocation::FromFrame(debug_info, frame);
696 List<BreakLocation> break_locations; 634 List<BreakLocation> break_locations;
697 BreakLocation::AllForStatementPosition( 635 BreakLocation::AllAtCurrentStatement(debug_info, frame, &break_locations);
698 debug_info, current_position.statement_position(), &break_locations);
699 bool has_break_points_at_all = false; 636 bool has_break_points_at_all = false;
700 for (int i = 0; i < break_locations.length(); i++) { 637 for (int i = 0; i < break_locations.length(); i++) {
701 bool has_break_points; 638 bool has_break_points;
702 Handle<Object> check_result = 639 Handle<Object> check_result =
703 CheckBreakPoints(&break_locations[i], &has_break_points); 640 CheckBreakPoints(debug_info, &break_locations[i], &has_break_points);
704 has_break_points_at_all |= has_break_points; 641 has_break_points_at_all |= has_break_points;
705 if (has_break_points && !check_result->IsUndefined(isolate_)) return false; 642 if (has_break_points && !check_result->IsUndefined(isolate_)) return false;
706 } 643 }
707 return has_break_points_at_all; 644 return has_break_points_at_all;
708 } 645 }
709 646
710 647
711 MaybeHandle<Object> Debug::CallFunction(const char* name, int argc, 648 MaybeHandle<Object> Debug::CallFunction(const char* name, int argc,
712 Handle<Object> args[]) { 649 Handle<Object> args[]) {
713 PostponeInterruptsScope no_interrupts(isolate_); 650 PostponeInterruptsScope no_interrupts(isolate_);
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
755 if (!EnsureDebugInfo(shared, function)) { 692 if (!EnsureDebugInfo(shared, function)) {
756 // Return if retrieving debug info failed. 693 // Return if retrieving debug info failed.
757 return true; 694 return true;
758 } 695 }
759 696
760 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); 697 Handle<DebugInfo> debug_info(shared->GetDebugInfo());
761 // Source positions starts with zero. 698 // Source positions starts with zero.
762 DCHECK(*source_position >= 0); 699 DCHECK(*source_position >= 0);
763 700
764 // Find the break point and change it. 701 // Find the break point and change it.
765 BreakLocation location = BreakLocation::FromPosition( 702 *source_position =
766 debug_info, *source_position, STATEMENT_ALIGNED); 703 FindBreakablePosition(debug_info, *source_position, STATEMENT_ALIGNED);
767 *source_position = location.statement_position(); 704 DebugInfo::SetBreakPoint(debug_info, *source_position, break_point_object);
768 location.SetBreakPoint(break_point_object); 705 // At least one active break point now.
706 DCHECK(debug_info->GetBreakPointCount() > 0);
707
708 ClearBreakPoints(debug_info);
709 ApplyBreakPoints(debug_info);
769 710
770 feature_tracker()->Track(DebugFeatureTracker::kBreakPoint); 711 feature_tracker()->Track(DebugFeatureTracker::kBreakPoint);
771 712 return true;
772 // At least one active break point now.
773 return debug_info->GetBreakPointCount() > 0;
774 } 713 }
775 714
776 715
777 bool Debug::SetBreakPointForScript(Handle<Script> script, 716 bool Debug::SetBreakPointForScript(Handle<Script> script,
778 Handle<Object> break_point_object, 717 Handle<Object> break_point_object,
779 int* source_position, 718 int* source_position,
780 BreakPositionAlignment alignment) { 719 BreakPositionAlignment alignment) {
781 if (script->type() == Script::TYPE_WASM) { 720 if (script->type() == Script::TYPE_WASM) {
782 // TODO(clemensh): set breakpoint for wasm. 721 // TODO(clemensh): set breakpoint for wasm.
783 return false; 722 return false;
(...skipping 14 matching lines...) Expand all
798 737
799 // Find position within function. The script position might be before the 738 // Find position within function. The script position might be before the
800 // source position of the first function. 739 // source position of the first function.
801 if (shared->start_position() > *source_position) { 740 if (shared->start_position() > *source_position) {
802 *source_position = shared->start_position(); 741 *source_position = shared->start_position();
803 } 742 }
804 743
805 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); 744 Handle<DebugInfo> debug_info(shared->GetDebugInfo());
806 745
807 // Find the break point and change it. 746 // Find the break point and change it.
808 BreakLocation location = 747 *source_position =
809 BreakLocation::FromPosition(debug_info, *source_position, alignment); 748 FindBreakablePosition(debug_info, *source_position, alignment);
810 location.SetBreakPoint(break_point_object); 749 DebugInfo::SetBreakPoint(debug_info, *source_position, break_point_object);
750 // At least one active break point now.
751 DCHECK(debug_info->GetBreakPointCount() > 0);
752
753 ClearBreakPoints(debug_info);
754 ApplyBreakPoints(debug_info);
811 755
812 feature_tracker()->Track(DebugFeatureTracker::kBreakPoint); 756 feature_tracker()->Track(DebugFeatureTracker::kBreakPoint);
813
814 *source_position = (alignment == STATEMENT_ALIGNED)
815 ? location.statement_position()
816 : location.position();
817
818 // At least one active break point now.
819 DCHECK(debug_info->GetBreakPointCount() > 0);
820 return true; 757 return true;
821 } 758 }
822 759
760 int Debug::FindBreakablePosition(Handle<DebugInfo> debug_info,
761 int source_position,
762 BreakPositionAlignment alignment) {
763 int statement_position;
764 int position;
765 if (debug_info->HasDebugCode()) {
766 CodeBreakIterator it(debug_info, ALL_BREAK_LOCATIONS);
767 it.SkipToPosition(source_position, alignment);
768 statement_position = it.statement_position();
769 position = it.position();
770 } else {
771 DCHECK(debug_info->HasDebugBytecodeArray());
772 BytecodeArrayBreakIterator it(debug_info, ALL_BREAK_LOCATIONS);
773 it.SkipToPosition(source_position, alignment);
774 statement_position = it.statement_position();
775 position = it.position();
776 }
777 return alignment == STATEMENT_ALIGNED ? statement_position : position;
778 }
779
780 void Debug::ApplyBreakPoints(Handle<DebugInfo> debug_info) {
781 DisallowHeapAllocation no_gc;
782 if (debug_info->break_points()->IsUndefined(isolate_)) return;
783 FixedArray* break_points = debug_info->break_points();
784 for (int i = 0; i < break_points->length(); i++) {
785 if (break_points->get(i)->IsUndefined(isolate_)) continue;
786 BreakPointInfo* info = BreakPointInfo::cast(break_points->get(i));
787 if (info->GetBreakPointCount() == 0) continue;
788 if (debug_info->HasDebugCode()) {
789 CodeBreakIterator it(debug_info, ALL_BREAK_LOCATIONS);
790 it.SkipToPosition(info->source_position(), BREAK_POSITION_ALIGNED);
791 it.SetDebugBreak();
792 }
793 if (debug_info->HasDebugBytecodeArray()) {
794 BytecodeArrayBreakIterator it(debug_info, ALL_BREAK_LOCATIONS);
795 it.SkipToPosition(info->source_position(), BREAK_POSITION_ALIGNED);
796 it.SetDebugBreak();
797 }
798 }
799 }
800
801 void Debug::ClearBreakPoints(Handle<DebugInfo> debug_info) {
802 DisallowHeapAllocation no_gc;
803 if (debug_info->HasDebugCode()) {
804 for (CodeBreakIterator it(debug_info, ALL_BREAK_LOCATIONS); !it.Done();
805 it.Next()) {
806 it.ClearDebugBreak();
807 }
808 }
809 if (debug_info->HasDebugBytecodeArray()) {
810 for (BytecodeArrayBreakIterator it(debug_info, ALL_BREAK_LOCATIONS);
811 !it.Done(); it.Next()) {
812 it.ClearDebugBreak();
813 }
814 }
815 }
823 816
824 void Debug::ClearBreakPoint(Handle<Object> break_point_object) { 817 void Debug::ClearBreakPoint(Handle<Object> break_point_object) {
825 HandleScope scope(isolate_); 818 HandleScope scope(isolate_);
826 819
827 DebugInfoListNode* node = debug_info_list_; 820 for (DebugInfoListNode* node = debug_info_list_; node != NULL;
828 while (node != NULL) { 821 node = node->next()) {
829 Handle<Object> result = 822 Handle<Object> result =
830 DebugInfo::FindBreakPointInfo(node->debug_info(), break_point_object); 823 DebugInfo::FindBreakPointInfo(node->debug_info(), break_point_object);
831 if (!result->IsUndefined(isolate_)) { 824 if (result->IsUndefined(isolate_)) continue;
832 // Get information in the break point. 825 Handle<DebugInfo> debug_info = node->debug_info();
833 Handle<BreakPointInfo> break_point_info = 826 if (DebugInfo::ClearBreakPoint(debug_info, break_point_object)) {
834 Handle<BreakPointInfo>::cast(result); 827 ClearBreakPoints(debug_info);
835 Handle<DebugInfo> debug_info = node->debug_info();
836
837 BreakLocation location = BreakLocation::FromPosition(
838 debug_info, break_point_info->source_position(),
839 BREAK_POSITION_ALIGNED);
840 location.ClearBreakPoint(break_point_object);
841
842 // If there are no more break points left remove the debug info for this
843 // function.
844 if (debug_info->GetBreakPointCount() == 0) { 828 if (debug_info->GetBreakPointCount() == 0) {
845 RemoveDebugInfoAndClearFromShared(debug_info); 829 RemoveDebugInfoAndClearFromShared(debug_info);
830 } else {
831 ApplyBreakPoints(debug_info);
846 } 832 }
847
848 return; 833 return;
849 } 834 }
850 node = node->next();
851 } 835 }
852 } 836 }
853 837
854
855 // Clear out all the debug break code. This is ONLY supposed to be used when 838 // Clear out all the debug break code. This is ONLY supposed to be used when
856 // shutting down the debugger as it will leave the break point information in 839 // shutting down the debugger as it will leave the break point information in
857 // DebugInfo even though the code is patched back to the non break point state. 840 // DebugInfo even though the code is patched back to the non break point state.
858 void Debug::ClearAllBreakPoints() { 841 void Debug::ClearAllBreakPoints() {
859 for (DebugInfoListNode* node = debug_info_list_; node != NULL; 842 for (DebugInfoListNode* node = debug_info_list_; node != NULL;
860 node = node->next()) { 843 node = node->next()) {
861 for (std::unique_ptr<BreakLocation::Iterator> it( 844 ClearBreakPoints(node->debug_info());
862 BreakLocation::GetIterator(node->debug_info()));
863 !it->Done(); it->Next()) {
864 it->GetBreakLocation().ClearDebugBreak();
865 }
866 } 845 }
867 // Remove all debug info. 846 // Remove all debug info.
868 while (debug_info_list_ != NULL) { 847 while (debug_info_list_ != NULL) {
869 RemoveDebugInfoAndClearFromShared(debug_info_list_->debug_info()); 848 RemoveDebugInfoAndClearFromShared(debug_info_list_->debug_info());
870 } 849 }
871 } 850 }
872 851
873
874 void Debug::FloodWithOneShot(Handle<JSFunction> function, 852 void Debug::FloodWithOneShot(Handle<JSFunction> function,
875 BreakLocatorType type) { 853 BreakLocatorType type) {
876 // Debug utility functions are not subject to debugging. 854 // Debug utility functions are not subject to debugging.
877 if (function->native_context() == *debug_context()) return; 855 if (function->native_context() == *debug_context()) return;
878 856
879 if (!function->shared()->IsSubjectToDebugging()) { 857 if (!function->shared()->IsSubjectToDebugging()) {
880 // Builtin functions are not subject to stepping, but need to be 858 // Builtin functions are not subject to stepping, but need to be
881 // deoptimized, because optimized code does not check for debug 859 // deoptimized, because optimized code does not check for debug
882 // step in at call sites. 860 // step in at call sites.
883 Deoptimizer::DeoptimizeFunction(*function); 861 Deoptimizer::DeoptimizeFunction(*function);
884 return; 862 return;
885 } 863 }
886 // Make sure the function is compiled and has set up the debug info. 864 // Make sure the function is compiled and has set up the debug info.
887 Handle<SharedFunctionInfo> shared(function->shared()); 865 Handle<SharedFunctionInfo> shared(function->shared());
888 if (!EnsureDebugInfo(shared, function)) { 866 if (!EnsureDebugInfo(shared, function)) {
889 // Return if we failed to retrieve the debug info. 867 // Return if we failed to retrieve the debug info.
890 return; 868 return;
891 } 869 }
892 870
893 // Flood the function with break points. 871 // Flood the function with break points.
894 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); 872 Handle<DebugInfo> debug_info(shared->GetDebugInfo());
895 for (std::unique_ptr<BreakLocation::Iterator> it( 873 if (debug_info->HasDebugCode()) {
896 BreakLocation::GetIterator(debug_info, type)); 874 for (CodeBreakIterator it(debug_info, type); !it.Done(); it.Next()) {
897 !it->Done(); it->Next()) { 875 it.SetDebugBreak();
898 it->GetBreakLocation().SetOneShot(); 876 }
877 }
878 if (debug_info->HasDebugBytecodeArray()) {
879 for (BytecodeArrayBreakIterator it(debug_info, type); !it.Done();
880 it.Next()) {
881 it.SetDebugBreak();
882 }
899 } 883 }
900 } 884 }
901 885
902
903 void Debug::ChangeBreakOnException(ExceptionBreakType type, bool enable) { 886 void Debug::ChangeBreakOnException(ExceptionBreakType type, bool enable) {
904 if (type == BreakUncaughtException) { 887 if (type == BreakUncaughtException) {
905 break_on_uncaught_exception_ = enable; 888 break_on_uncaught_exception_ = enable;
906 } else { 889 } else {
907 break_on_exception_ = enable; 890 break_on_exception_ = enable;
908 } 891 }
909 } 892 }
910 893
911 894
912 bool Debug::IsBreakOnException(ExceptionBreakType type) { 895 bool Debug::IsBreakOnException(ExceptionBreakType type) {
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
1007 // Get the debug info (create it if it does not exist). 990 // Get the debug info (create it if it does not exist).
1008 FrameSummary summary = FrameSummary::GetFirst(frame); 991 FrameSummary summary = FrameSummary::GetFirst(frame);
1009 Handle<JSFunction> function(summary.function()); 992 Handle<JSFunction> function(summary.function());
1010 Handle<SharedFunctionInfo> shared(function->shared()); 993 Handle<SharedFunctionInfo> shared(function->shared());
1011 if (!EnsureDebugInfo(shared, function)) { 994 if (!EnsureDebugInfo(shared, function)) {
1012 // Return if ensuring debug info failed. 995 // Return if ensuring debug info failed.
1013 return; 996 return;
1014 } 997 }
1015 998
1016 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); 999 Handle<DebugInfo> debug_info(shared->GetDebugInfo());
1017 // Refresh frame summary if the code has been recompiled for debugging. 1000 BreakLocation location = BreakLocation::FromFrame(debug_info, frame);
1018 if (AbstractCode::cast(shared->code()) != *summary.abstract_code()) {
1019 summary = FrameSummary::GetFirst(frame);
1020 }
1021
1022 int call_offset =
1023 CallOffsetFromCodeOffset(summary.code_offset(), frame->is_interpreted());
1024 BreakLocation location =
1025 BreakLocation::FromCodeOffset(debug_info, call_offset);
1026 1001
1027 // Any step at a return is a step-out. 1002 // Any step at a return is a step-out.
1028 if (location.IsReturn()) step_action = StepOut; 1003 if (location.IsReturn()) step_action = StepOut;
1029 // A step-next at a tail call is a step-out. 1004 // A step-next at a tail call is a step-out.
1030 if (location.IsTailCall() && step_action == StepNext) step_action = StepOut; 1005 if (location.IsTailCall() && step_action == StepNext) step_action = StepOut;
1031 1006
1032 thread_local_.last_statement_position_ = 1007 thread_local_.last_statement_position_ =
1033 debug_info->abstract_code()->SourceStatementPosition( 1008 summary.abstract_code()->SourceStatementPosition(summary.code_offset());
1034 summary.code_offset());
1035 thread_local_.last_fp_ = frame->UnpaddedFP(); 1009 thread_local_.last_fp_ = frame->UnpaddedFP();
1036 // No longer perform the current async step. 1010 // No longer perform the current async step.
1037 clear_suspended_generator(); 1011 clear_suspended_generator();
1038 1012
1039 switch (step_action) { 1013 switch (step_action) {
1040 case StepNone: 1014 case StepNone:
1041 UNREACHABLE(); 1015 UNREACHABLE();
1042 break; 1016 break;
1043 case StepOut: 1017 case StepOut:
1044 // Advance to caller frame. 1018 // Advance to caller frame.
(...skipping 24 matching lines...) Expand all
1069 FloodWithOneShot(function); 1043 FloodWithOneShot(function);
1070 break; 1044 break;
1071 case StepFrame: 1045 case StepFrame:
1072 // No point in setting one-shot breaks at places where we are not about 1046 // No point in setting one-shot breaks at places where we are not about
1073 // to leave the current frame. 1047 // to leave the current frame.
1074 FloodWithOneShot(function, CALLS_AND_RETURNS); 1048 FloodWithOneShot(function, CALLS_AND_RETURNS);
1075 break; 1049 break;
1076 } 1050 }
1077 } 1051 }
1078 1052
1079
1080 // Simple function for returning the source positions for active break points. 1053 // Simple function for returning the source positions for active break points.
1081 Handle<Object> Debug::GetSourceBreakLocations( 1054 Handle<Object> Debug::GetSourceBreakLocations(
1082 Handle<SharedFunctionInfo> shared, 1055 Handle<SharedFunctionInfo> shared,
1083 BreakPositionAlignment position_alignment) { 1056 BreakPositionAlignment position_alignment) {
1084 Isolate* isolate = shared->GetIsolate(); 1057 Isolate* isolate = shared->GetIsolate();
1085 if (!shared->HasDebugInfo()) { 1058 if (!shared->HasDebugInfo()) {
1086 return isolate->factory()->undefined_value(); 1059 return isolate->factory()->undefined_value();
1087 } 1060 }
1088 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); 1061 Handle<DebugInfo> debug_info(shared->GetDebugInfo());
1089 if (debug_info->GetBreakPointCount() == 0) { 1062 if (debug_info->GetBreakPointCount() == 0) {
1090 return isolate->factory()->undefined_value(); 1063 return isolate->factory()->undefined_value();
1091 } 1064 }
1092 Handle<FixedArray> locations = 1065 Handle<FixedArray> locations =
1093 isolate->factory()->NewFixedArray(debug_info->GetBreakPointCount()); 1066 isolate->factory()->NewFixedArray(debug_info->GetBreakPointCount());
1094 int count = 0; 1067 int count = 0;
1095 for (int i = 0; i < debug_info->break_points()->length(); ++i) { 1068 for (int i = 0; i < debug_info->break_points()->length(); ++i) {
1096 if (!debug_info->break_points()->get(i)->IsUndefined(isolate)) { 1069 if (!debug_info->break_points()->get(i)->IsUndefined(isolate)) {
1097 BreakPointInfo* break_point_info = 1070 BreakPointInfo* break_point_info =
1098 BreakPointInfo::cast(debug_info->break_points()->get(i)); 1071 BreakPointInfo::cast(debug_info->break_points()->get(i));
1099 int break_points = break_point_info->GetBreakPointCount(); 1072 int break_points = break_point_info->GetBreakPointCount();
1100 if (break_points == 0) continue; 1073 if (break_points == 0) continue;
1101 Smi* position = NULL; 1074 Smi* position = NULL;
1102 if (position_alignment == STATEMENT_ALIGNED) { 1075 if (position_alignment == STATEMENT_ALIGNED) {
1103 BreakLocation break_point_location = BreakLocation::FromPosition( 1076 if (debug_info->HasDebugCode()) {
1104 debug_info, break_point_info->source_position(), 1077 CodeBreakIterator it(debug_info, ALL_BREAK_LOCATIONS);
1105 BREAK_POSITION_ALIGNED); 1078 it.SkipToPosition(break_point_info->source_position(),
1106 position = Smi::FromInt(break_point_location.statement_position()); 1079 BREAK_POSITION_ALIGNED);
1080 position = Smi::FromInt(it.statement_position());
1081 } else {
1082 DCHECK(debug_info->HasDebugBytecodeArray());
1083 BytecodeArrayBreakIterator it(debug_info, ALL_BREAK_LOCATIONS);
1084 it.SkipToPosition(break_point_info->source_position(),
1085 BREAK_POSITION_ALIGNED);
1086 position = Smi::FromInt(it.statement_position());
1087 }
1107 } else { 1088 } else {
1108 DCHECK_EQ(BREAK_POSITION_ALIGNED, position_alignment); 1089 DCHECK_EQ(BREAK_POSITION_ALIGNED, position_alignment);
1109 position = Smi::FromInt(break_point_info->source_position()); 1090 position = Smi::FromInt(break_point_info->source_position());
1110 } 1091 }
1111 for (int j = 0; j < break_points; ++j) locations->set(count++, position); 1092 for (int j = 0; j < break_points; ++j) locations->set(count++, position);
1112 } 1093 }
1113 } 1094 }
1114 return locations; 1095 return locations;
1115 } 1096 }
1116 1097
1117
1118 void Debug::ClearStepping() { 1098 void Debug::ClearStepping() {
1119 // Clear the various stepping setup. 1099 // Clear the various stepping setup.
1120 ClearOneShot(); 1100 ClearOneShot();
1121 1101
1122 thread_local_.last_step_action_ = StepNone; 1102 thread_local_.last_step_action_ = StepNone;
1123 thread_local_.last_statement_position_ = kNoSourcePosition; 1103 thread_local_.last_statement_position_ = kNoSourcePosition;
1124 thread_local_.last_fp_ = 0; 1104 thread_local_.last_fp_ = 0;
1125 thread_local_.target_fp_ = 0; 1105 thread_local_.target_fp_ = 0;
1126 } 1106 }
1127 1107
1128 1108
1129 // Clears all the one-shot break points that are currently set. Normally this 1109 // Clears all the one-shot break points that are currently set. Normally this
1130 // function is called each time a break point is hit as one shot break points 1110 // function is called each time a break point is hit as one shot break points
1131 // are used to support stepping. 1111 // are used to support stepping.
1132 void Debug::ClearOneShot() { 1112 void Debug::ClearOneShot() {
1133 // The current implementation just runs through all the breakpoints. When the 1113 // The current implementation just runs through all the breakpoints. When the
1134 // last break point for a function is removed that function is automatically 1114 // last break point for a function is removed that function is automatically
1135 // removed from the list. 1115 // removed from the list.
1136 for (DebugInfoListNode* node = debug_info_list_; node != NULL; 1116 for (DebugInfoListNode* node = debug_info_list_; node != NULL;
1137 node = node->next()) { 1117 node = node->next()) {
1138 for (std::unique_ptr<BreakLocation::Iterator> it( 1118 Handle<DebugInfo> debug_info = node->debug_info();
1139 BreakLocation::GetIterator(node->debug_info())); 1119 ClearBreakPoints(debug_info);
1140 !it->Done(); it->Next()) { 1120 ApplyBreakPoints(debug_info);
1141 it->GetBreakLocation().ClearOneShot();
1142 }
1143 } 1121 }
1144 } 1122 }
1145 1123
1146 1124
1147 bool MatchingCodeTargets(Code* target1, Code* target2) { 1125 bool MatchingCodeTargets(Code* target1, Code* target2) {
1148 if (target1 == target2) return true; 1126 if (target1 == target2) return true;
1149 if (target1->kind() != target2->kind()) return false; 1127 if (target1->kind() != target2->kind()) return false;
1150 return target1->is_handler() || target1->is_inline_cache_stub(); 1128 return target1->is_handler() || target1->is_inline_cache_stub();
1151 } 1129 }
1152 1130
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
1236 for (JavaScriptFrameIterator it(isolate, top); !it.done(); it.Advance()) { 1214 for (JavaScriptFrameIterator it(isolate, top); !it.done(); it.Advance()) {
1237 JavaScriptFrame* frame = it.frame(); 1215 JavaScriptFrame* frame = it.frame();
1238 JSFunction* function = frame->function(); 1216 JSFunction* function = frame->function();
1239 if (frame->is_optimized()) continue; 1217 if (frame->is_optimized()) continue;
1240 if (!function->Inlines(shared_)) continue; 1218 if (!function->Inlines(shared_)) continue;
1241 1219
1242 if (frame->is_interpreted()) { 1220 if (frame->is_interpreted()) {
1243 InterpretedFrame* interpreted_frame = 1221 InterpretedFrame* interpreted_frame =
1244 reinterpret_cast<InterpretedFrame*>(frame); 1222 reinterpret_cast<InterpretedFrame*>(frame);
1245 BytecodeArray* debug_copy = 1223 BytecodeArray* debug_copy =
1246 shared_->GetDebugInfo()->abstract_code()->GetBytecodeArray(); 1224 shared_->GetDebugInfo()->DebugBytecodeArray();
1247 interpreted_frame->PatchBytecodeArray(debug_copy); 1225 interpreted_frame->PatchBytecodeArray(debug_copy);
1248 continue; 1226 continue;
1249 } 1227 }
1250 1228
1251 Code* frame_code = frame->LookupCode(); 1229 Code* frame_code = frame->LookupCode();
1252 DCHECK(frame_code->kind() == Code::FUNCTION); 1230 DCHECK(frame_code->kind() == Code::FUNCTION);
1253 if (frame_code->has_debug_break_slots()) continue; 1231 if (frame_code->has_debug_break_slots()) continue;
1254 1232
1255 Code* new_code = function->shared()->code(); 1233 Code* new_code = function->shared()->code();
1256 Address old_pc = frame->pc(); 1234 Address old_pc = frame->pc();
(...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after
1589 bool Debug::IsBreakAtReturn(JavaScriptFrame* frame) { 1567 bool Debug::IsBreakAtReturn(JavaScriptFrame* frame) {
1590 HandleScope scope(isolate_); 1568 HandleScope scope(isolate_);
1591 1569
1592 // Get the executing function in which the debug break occurred. 1570 // Get the executing function in which the debug break occurred.
1593 Handle<SharedFunctionInfo> shared(frame->function()->shared()); 1571 Handle<SharedFunctionInfo> shared(frame->function()->shared());
1594 1572
1595 // With no debug info there are no break points, so we can't be at a return. 1573 // With no debug info there are no break points, so we can't be at a return.
1596 if (!shared->HasDebugInfo()) return false; 1574 if (!shared->HasDebugInfo()) return false;
1597 1575
1598 DCHECK(!frame->is_optimized()); 1576 DCHECK(!frame->is_optimized());
1599 int code_offset = FrameSummary::GetFirst(frame).code_offset();
1600 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); 1577 Handle<DebugInfo> debug_info(shared->GetDebugInfo());
1601 BreakLocation location = 1578 BreakLocation location = BreakLocation::FromFrame(debug_info, frame);
1602 BreakLocation::FromCodeOffset(debug_info, code_offset);
1603 return location.IsReturn() || location.IsTailCall(); 1579 return location.IsReturn() || location.IsTailCall();
1604 } 1580 }
1605 1581
1606 1582
1607 void Debug::FramesHaveBeenDropped(StackFrame::Id new_break_frame_id, 1583 void Debug::FramesHaveBeenDropped(StackFrame::Id new_break_frame_id,
1608 LiveEdit::FrameDropMode mode) { 1584 LiveEdit::FrameDropMode mode) {
1609 if (mode != LiveEdit::CURRENTLY_SET_MODE) { 1585 if (mode != LiveEdit::CURRENTLY_SET_MODE) {
1610 thread_local_.frame_drop_mode_ = mode; 1586 thread_local_.frame_drop_mode_ = mode;
1611 } 1587 }
1612 thread_local_.break_frame_id_ = new_break_frame_id; 1588 thread_local_.break_frame_id_ = new_break_frame_id;
(...skipping 810 matching lines...) Expand 10 before | Expand all | Expand 10 after
2423 Handle<Object> json; 2399 Handle<Object> json;
2424 if (!maybe_json.ToHandle(&json) || !json->IsString()) { 2400 if (!maybe_json.ToHandle(&json) || !json->IsString()) {
2425 return v8::Local<v8::String>(); 2401 return v8::Local<v8::String>();
2426 } 2402 }
2427 return scope.Escape(v8::Utils::ToLocal(Handle<String>::cast(json))); 2403 return scope.Escape(v8::Utils::ToLocal(Handle<String>::cast(json)));
2428 } else { 2404 } else {
2429 return v8::Utils::ToLocal(response_json_); 2405 return v8::Utils::ToLocal(response_json_);
2430 } 2406 }
2431 } 2407 }
2432 2408
2409 namespace {
2410 v8::Local<v8::Context> GetDebugEventContext(Isolate* isolate) {
2411 Handle<Context> context = isolate->debug()->debugger_entry()->GetContext();
2412 // Isolate::context() may have been NULL when "script collected" event
2413 // occured.
2414 if (context.is_null()) return v8::Local<v8::Context>();
2415 Handle<Context> native_context(context->native_context());
2416 return v8::Utils::ToLocal(native_context);
2417 }
2418 } // anonymous namespace
2433 2419
2434 v8::Local<v8::Context> MessageImpl::GetEventContext() const { 2420 v8::Local<v8::Context> MessageImpl::GetEventContext() const {
2435 Isolate* isolate = event_data_->GetIsolate(); 2421 Isolate* isolate = event_data_->GetIsolate();
2436 v8::Local<v8::Context> context = GetDebugEventContext(isolate); 2422 v8::Local<v8::Context> context = GetDebugEventContext(isolate);
2437 // Isolate::context() may be NULL when "script collected" event occurs. 2423 // Isolate::context() may be NULL when "script collected" event occurs.
2438 DCHECK(!context.IsEmpty()); 2424 DCHECK(!context.IsEmpty());
2439 return context; 2425 return context;
2440 } 2426 }
2441 2427
2442 2428
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
2583 } 2569 }
2584 2570
2585 2571
2586 void LockingCommandMessageQueue::Clear() { 2572 void LockingCommandMessageQueue::Clear() {
2587 base::LockGuard<base::Mutex> lock_guard(&mutex_); 2573 base::LockGuard<base::Mutex> lock_guard(&mutex_);
2588 queue_.Clear(); 2574 queue_.Clear();
2589 } 2575 }
2590 2576
2591 } // namespace internal 2577 } // namespace internal
2592 } // namespace v8 2578 } // namespace v8
OLDNEW
« no previous file with comments | « src/debug/debug.h ('k') | src/factory.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698