blob: cdcb0a759f0e4309ddebe829628e28f3e1b02e20 [file] [log] [blame]
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001// Copyright 2012 the V8 project authors. All rights reserved.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
Steve Blocka7e24c12009-10-30 11:49:00 +00004
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005#include "src/v8.h"
Steve Blocka7e24c12009-10-30 11:49:00 +00006
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007#include "src/api.h"
8#include "src/arguments.h"
9#include "src/bootstrapper.h"
10#include "src/code-stubs.h"
11#include "src/codegen.h"
12#include "src/compilation-cache.h"
13#include "src/compiler.h"
14#include "src/debug.h"
15#include "src/deoptimizer.h"
16#include "src/execution.h"
17#include "src/full-codegen.h"
18#include "src/global-handles.h"
19#include "src/isolate-inl.h"
20#include "src/list.h"
21#include "src/log.h"
22#include "src/messages.h"
23#include "src/natives.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000024
Ben Murdochb8a8cc12014-11-26 15:28:44 +000025#include "include/v8-debug.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000026
27namespace v8 {
28namespace internal {
29
Steve Block44f0eee2011-05-26 01:26:41 +010030Debug::Debug(Isolate* isolate)
Ben Murdochb8a8cc12014-11-26 15:28:44 +000031 : debug_context_(Handle<Context>()),
32 event_listener_(Handle<Object>()),
33 event_listener_data_(Handle<Object>()),
34 message_handler_(NULL),
35 command_received_(0),
36 command_queue_(isolate->logger(), kQueueInitialSize),
37 event_command_queue_(isolate->logger(), kQueueInitialSize),
38 is_active_(false),
39 is_suppressed_(false),
40 live_edit_enabled_(true), // TODO(yangguo): set to false by default.
41 has_break_points_(false),
42 break_disabled_(false),
Emily Bernierd0a1eb72015-03-24 16:35:39 -040043 in_debug_event_listener_(false),
Steve Block44f0eee2011-05-26 01:26:41 +010044 break_on_exception_(false),
45 break_on_uncaught_exception_(false),
Ben Murdochb8a8cc12014-11-26 15:28:44 +000046 script_cache_(NULL),
47 debug_info_list_(NULL),
Steve Block44f0eee2011-05-26 01:26:41 +010048 isolate_(isolate) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000049 ThreadInit();
Steve Block44f0eee2011-05-26 01:26:41 +010050}
51
52
53static v8::Handle<v8::Context> GetDebugEventContext(Isolate* isolate) {
54 Handle<Context> context = isolate->debug()->debugger_entry()->GetContext();
55 // Isolate::context() may have been NULL when "script collected" event
56 // occured.
57 if (context.is_null()) return v8::Local<v8::Context>();
Ben Murdochb8a8cc12014-11-26 15:28:44 +000058 Handle<Context> native_context(context->native_context());
59 return v8::Utils::ToLocal(native_context);
Leon Clarkef7060e22010-06-03 12:02:55 +010060}
61
62
Steve Blocka7e24c12009-10-30 11:49:00 +000063BreakLocationIterator::BreakLocationIterator(Handle<DebugInfo> debug_info,
64 BreakLocatorType type) {
65 debug_info_ = debug_info;
66 type_ = type;
Steve Blocka7e24c12009-10-30 11:49:00 +000067 reloc_iterator_ = NULL;
68 reloc_iterator_original_ = NULL;
69 Reset(); // Initialize the rest of the member variables.
70}
71
72
73BreakLocationIterator::~BreakLocationIterator() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000074 DCHECK(reloc_iterator_ != NULL);
75 DCHECK(reloc_iterator_original_ != NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +000076 delete reloc_iterator_;
77 delete reloc_iterator_original_;
78}
79
80
Ben Murdochb8a8cc12014-11-26 15:28:44 +000081// Check whether a code stub with the specified major key is a possible break
82// point location when looking for source break locations.
83static bool IsSourceBreakStub(Code* code) {
84 CodeStub::Major major_key = CodeStub::GetMajorKey(code);
85 return major_key == CodeStub::CallFunction;
86}
87
88
89// Check whether a code stub with the specified major key is a possible break
90// location.
91static bool IsBreakStub(Code* code) {
92 CodeStub::Major major_key = CodeStub::GetMajorKey(code);
93 return major_key == CodeStub::CallFunction;
94}
95
96
Steve Blocka7e24c12009-10-30 11:49:00 +000097void BreakLocationIterator::Next() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000098 DisallowHeapAllocation no_gc;
99 DCHECK(!RinfoDone());
Steve Blocka7e24c12009-10-30 11:49:00 +0000100
101 // Iterate through reloc info for code and original code stopping at each
102 // breakable code target.
103 bool first = break_point_ == -1;
104 while (!RinfoDone()) {
105 if (!first) RinfoNext();
106 first = false;
107 if (RinfoDone()) return;
108
109 // Whenever a statement position or (plain) position is passed update the
110 // current value of these.
111 if (RelocInfo::IsPosition(rmode())) {
112 if (RelocInfo::IsStatementPosition(rmode())) {
Steve Blockd0582a62009-12-15 09:54:21 +0000113 statement_position_ = static_cast<int>(
114 rinfo()->data() - debug_info_->shared()->start_position());
Steve Blocka7e24c12009-10-30 11:49:00 +0000115 }
116 // Always update the position as we don't want that to be before the
117 // statement position.
Steve Blockd0582a62009-12-15 09:54:21 +0000118 position_ = static_cast<int>(
119 rinfo()->data() - debug_info_->shared()->start_position());
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000120 DCHECK(position_ >= 0);
121 DCHECK(statement_position_ >= 0);
Steve Blocka7e24c12009-10-30 11:49:00 +0000122 }
123
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400124 // Check for break at return.
125 if (RelocInfo::IsJSReturn(rmode())) {
126 // Set the positions to the end of the function.
127 if (debug_info_->shared()->HasSourceCode()) {
128 position_ = debug_info_->shared()->end_position() -
129 debug_info_->shared()->start_position() - 1;
130 } else {
131 position_ = 0;
132 }
133 statement_position_ = position_;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100134 break_point_++;
135 return;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400136 }
137
138 if (RelocInfo::IsCodeTarget(rmode())) {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100139 // Check for breakable code target. Look in the original code as setting
140 // break points can cause the code targets in the running (debugged) code
141 // to be of a different kind than in the original code.
Steve Blocka7e24c12009-10-30 11:49:00 +0000142 Address target = original_rinfo()->target_address();
143 Code* code = Code::GetCodeFromTargetAddress(target);
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400144
145 if (RelocInfo::IsConstructCall(rmode()) || code->is_call_stub()) {
146 break_point_++;
147 return;
148 }
149
150 // Skip below if we only want locations for calls and returns.
151 if (type_ == CALLS_AND_RETURNS) continue;
152
153 if ((code->is_inline_cache_stub() && !code->is_binary_op_stub() &&
154 !code->is_compare_ic_stub() && !code->is_to_boolean_ic_stub())) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000155 break_point_++;
156 return;
157 }
158 if (code->kind() == Code::STUB) {
159 if (IsDebuggerStatement()) {
160 break_point_++;
161 return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000162 } else if (type_ == ALL_BREAK_LOCATIONS) {
163 if (IsBreakStub(code)) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000164 break_point_++;
165 return;
166 }
167 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000168 DCHECK(type_ == SOURCE_BREAK_LOCATIONS);
169 if (IsSourceBreakStub(code)) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000170 break_point_++;
171 return;
172 }
173 }
174 }
175 }
176
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400177 if (IsDebugBreakSlot() && type_ != CALLS_AND_RETURNS) {
178 // There is always a possible break point at a debug break slot.
Steve Blocka7e24c12009-10-30 11:49:00 +0000179 break_point_++;
180 return;
181 }
182 }
183}
184
185
186void BreakLocationIterator::Next(int count) {
187 while (count > 0) {
188 Next();
189 count--;
190 }
191}
192
193
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000194// Find the break point at the supplied address, or the closest one before
195// the address.
Steve Blocka7e24c12009-10-30 11:49:00 +0000196void BreakLocationIterator::FindBreakLocationFromAddress(Address pc) {
197 // Run through all break points to locate the one closest to the address.
198 int closest_break_point = 0;
199 int distance = kMaxInt;
200 while (!Done()) {
201 // Check if this break point is closer that what was previously found.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000202 if (this->pc() <= pc && pc - this->pc() < distance) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000203 closest_break_point = break_point();
Steve Blockd0582a62009-12-15 09:54:21 +0000204 distance = static_cast<int>(pc - this->pc());
Steve Blocka7e24c12009-10-30 11:49:00 +0000205 // Check whether we can't get any closer.
206 if (distance == 0) break;
207 }
208 Next();
209 }
210
211 // Move to the break point found.
212 Reset();
213 Next(closest_break_point);
214}
215
216
217// Find the break point closest to the supplied source position.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000218void BreakLocationIterator::FindBreakLocationFromPosition(int position,
219 BreakPositionAlignment alignment) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000220 // Run through all break points to locate the one closest to the source
221 // position.
222 int closest_break_point = 0;
223 int distance = kMaxInt;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000224
Steve Blocka7e24c12009-10-30 11:49:00 +0000225 while (!Done()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000226 int next_position;
227 switch (alignment) {
228 case STATEMENT_ALIGNED:
229 next_position = this->statement_position();
230 break;
231 case BREAK_POSITION_ALIGNED:
232 next_position = this->position();
233 break;
234 default:
235 UNREACHABLE();
236 next_position = this->statement_position();
237 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000238 // Check if this break point is closer that what was previously found.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000239 if (position <= next_position && next_position - position < distance) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000240 closest_break_point = break_point();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000241 distance = next_position - position;
Steve Blocka7e24c12009-10-30 11:49:00 +0000242 // Check whether we can't get any closer.
243 if (distance == 0) break;
244 }
245 Next();
246 }
247
248 // Move to the break point found.
249 Reset();
250 Next(closest_break_point);
251}
252
253
254void BreakLocationIterator::Reset() {
255 // Create relocation iterators for the two code objects.
256 if (reloc_iterator_ != NULL) delete reloc_iterator_;
257 if (reloc_iterator_original_ != NULL) delete reloc_iterator_original_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000258 reloc_iterator_ = new RelocIterator(
259 debug_info_->code(),
260 ~RelocInfo::ModeMask(RelocInfo::CODE_AGE_SEQUENCE));
261 reloc_iterator_original_ = new RelocIterator(
262 debug_info_->original_code(),
263 ~RelocInfo::ModeMask(RelocInfo::CODE_AGE_SEQUENCE));
Steve Blocka7e24c12009-10-30 11:49:00 +0000264
265 // Position at the first break point.
266 break_point_ = -1;
267 position_ = 1;
268 statement_position_ = 1;
269 Next();
270}
271
272
273bool BreakLocationIterator::Done() const {
274 return RinfoDone();
275}
276
277
278void BreakLocationIterator::SetBreakPoint(Handle<Object> break_point_object) {
279 // If there is not already a real break point here patch code with debug
280 // break.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000281 if (!HasBreakPoint()) SetDebugBreak();
282 DCHECK(IsDebugBreak() || IsDebuggerStatement());
Steve Blocka7e24c12009-10-30 11:49:00 +0000283 // Set the break point information.
284 DebugInfo::SetBreakPoint(debug_info_, code_position(),
285 position(), statement_position(),
286 break_point_object);
287}
288
289
290void BreakLocationIterator::ClearBreakPoint(Handle<Object> break_point_object) {
291 // Clear the break point information.
292 DebugInfo::ClearBreakPoint(debug_info_, code_position(), break_point_object);
293 // If there are no more break points here remove the debug break.
294 if (!HasBreakPoint()) {
295 ClearDebugBreak();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000296 DCHECK(!IsDebugBreak());
Steve Blocka7e24c12009-10-30 11:49:00 +0000297 }
298}
299
300
301void BreakLocationIterator::SetOneShot() {
302 // Debugger statement always calls debugger. No need to modify it.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000303 if (IsDebuggerStatement()) return;
Steve Blocka7e24c12009-10-30 11:49:00 +0000304
305 // If there is a real break point here no more to do.
306 if (HasBreakPoint()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000307 DCHECK(IsDebugBreak());
Steve Blocka7e24c12009-10-30 11:49:00 +0000308 return;
309 }
310
311 // Patch code with debug break.
312 SetDebugBreak();
313}
314
315
316void BreakLocationIterator::ClearOneShot() {
317 // Debugger statement always calls debugger. No need to modify it.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000318 if (IsDebuggerStatement()) return;
Steve Blocka7e24c12009-10-30 11:49:00 +0000319
320 // If there is a real break point here no more to do.
321 if (HasBreakPoint()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000322 DCHECK(IsDebugBreak());
Steve Blocka7e24c12009-10-30 11:49:00 +0000323 return;
324 }
325
326 // Patch code removing debug break.
327 ClearDebugBreak();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000328 DCHECK(!IsDebugBreak());
Steve Blocka7e24c12009-10-30 11:49:00 +0000329}
330
331
332void BreakLocationIterator::SetDebugBreak() {
333 // Debugger statement always calls debugger. No need to modify it.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000334 if (IsDebuggerStatement()) return;
Steve Blocka7e24c12009-10-30 11:49:00 +0000335
336 // If there is already a break point here just return. This might happen if
337 // the same code is flooded with break points twice. Flooding the same
338 // function twice might happen when stepping in a function with an exception
339 // handler as the handler and the function is the same.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000340 if (IsDebugBreak()) return;
Steve Blocka7e24c12009-10-30 11:49:00 +0000341
342 if (RelocInfo::IsJSReturn(rmode())) {
343 // Patch the frame exit code with a break point.
344 SetDebugBreakAtReturn();
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100345 } else if (IsDebugBreakSlot()) {
346 // Patch the code in the break slot.
347 SetDebugBreakAtSlot();
Steve Blocka7e24c12009-10-30 11:49:00 +0000348 } else {
349 // Patch the IC call.
350 SetDebugBreakAtIC();
351 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000352 DCHECK(IsDebugBreak());
Steve Blocka7e24c12009-10-30 11:49:00 +0000353}
354
355
356void BreakLocationIterator::ClearDebugBreak() {
357 // Debugger statement always calls debugger. No need to modify it.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000358 if (IsDebuggerStatement()) return;
Steve Blocka7e24c12009-10-30 11:49:00 +0000359
360 if (RelocInfo::IsJSReturn(rmode())) {
361 // Restore the frame exit code.
362 ClearDebugBreakAtReturn();
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100363 } else if (IsDebugBreakSlot()) {
364 // Restore the code in the break slot.
365 ClearDebugBreakAtSlot();
Steve Blocka7e24c12009-10-30 11:49:00 +0000366 } else {
367 // Patch the IC call.
368 ClearDebugBreakAtIC();
369 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000370 DCHECK(!IsDebugBreak());
Steve Blocka7e24c12009-10-30 11:49:00 +0000371}
372
373
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000374bool BreakLocationIterator::IsStepInLocation(Isolate* isolate) {
375 if (RelocInfo::IsConstructCall(original_rmode())) {
376 return true;
377 } else if (RelocInfo::IsCodeTarget(rmode())) {
378 HandleScope scope(debug_info_->GetIsolate());
379 Address target = original_rinfo()->target_address();
380 Handle<Code> target_code(Code::GetCodeFromTargetAddress(target));
381 if (target_code->kind() == Code::STUB) {
382 return CodeStub::GetMajorKey(*target_code) == CodeStub::CallFunction;
383 }
384 return target_code->is_call_stub();
385 }
386 return false;
387}
Steve Blocka7e24c12009-10-30 11:49:00 +0000388
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000389
390void BreakLocationIterator::PrepareStepIn(Isolate* isolate) {
391#ifdef DEBUG
392 HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +0000393 // Step in can only be prepared if currently positioned on an IC call,
394 // construct call or CallFunction stub call.
395 Address target = rinfo()->target_address();
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100396 Handle<Code> target_code(Code::GetCodeFromTargetAddress(target));
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000397 // All the following stuff is needed only for assertion checks so the code
398 // is wrapped in ifdef.
399 Handle<Code> maybe_call_function_stub = target_code;
400 if (IsDebugBreak()) {
401 Address original_target = original_rinfo()->target_address();
402 maybe_call_function_stub =
403 Handle<Code>(Code::GetCodeFromTargetAddress(original_target));
Steve Blocka7e24c12009-10-30 11:49:00 +0000404 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000405 bool is_call_function_stub =
406 (maybe_call_function_stub->kind() == Code::STUB &&
407 CodeStub::GetMajorKey(*maybe_call_function_stub) ==
408 CodeStub::CallFunction);
409
410 // Step in through construct call requires no changes to the running code.
411 // Step in through getters/setters should already be prepared as well
412 // because caller of this function (Debug::PrepareStep) is expected to
413 // flood the top frame's function with one shot breakpoints.
414 // Step in through CallFunction stub should also be prepared by caller of
415 // this function (Debug::PrepareStep) which should flood target function
416 // with breakpoints.
417 DCHECK(RelocInfo::IsConstructCall(rmode()) ||
418 target_code->is_inline_cache_stub() ||
419 is_call_function_stub);
420#endif
Steve Blocka7e24c12009-10-30 11:49:00 +0000421}
422
423
424// Check whether the break point is at a position which will exit the function.
425bool BreakLocationIterator::IsExit() const {
426 return (RelocInfo::IsJSReturn(rmode()));
427}
428
429
430bool BreakLocationIterator::HasBreakPoint() {
431 return debug_info_->HasBreakPoint(code_position());
432}
433
434
435// Check whether there is a debug break at the current position.
436bool BreakLocationIterator::IsDebugBreak() {
437 if (RelocInfo::IsJSReturn(rmode())) {
438 return IsDebugBreakAtReturn();
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100439 } else if (IsDebugBreakSlot()) {
440 return IsDebugBreakAtSlot();
Steve Blocka7e24c12009-10-30 11:49:00 +0000441 } else {
442 return Debug::IsDebugBreak(rinfo()->target_address());
443 }
444}
445
446
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000447// Find the builtin to use for invoking the debug break
448static Handle<Code> DebugBreakForIC(Handle<Code> code, RelocInfo::Mode mode) {
449 Isolate* isolate = code->GetIsolate();
450
451 // Find the builtin debug break function matching the calling convention
452 // used by the call site.
453 if (code->is_inline_cache_stub()) {
454 switch (code->kind()) {
455 case Code::CALL_IC:
456 return isolate->builtins()->CallICStub_DebugBreak();
457
458 case Code::LOAD_IC:
459 return isolate->builtins()->LoadIC_DebugBreak();
460
461 case Code::STORE_IC:
462 return isolate->builtins()->StoreIC_DebugBreak();
463
464 case Code::KEYED_LOAD_IC:
465 return isolate->builtins()->KeyedLoadIC_DebugBreak();
466
467 case Code::KEYED_STORE_IC:
468 return isolate->builtins()->KeyedStoreIC_DebugBreak();
469
470 case Code::COMPARE_NIL_IC:
471 return isolate->builtins()->CompareNilIC_DebugBreak();
472
473 default:
474 UNREACHABLE();
475 }
476 }
477 if (RelocInfo::IsConstructCall(mode)) {
478 if (code->has_function_cache()) {
479 return isolate->builtins()->CallConstructStub_Recording_DebugBreak();
480 } else {
481 return isolate->builtins()->CallConstructStub_DebugBreak();
482 }
483 }
484 if (code->kind() == Code::STUB) {
485 DCHECK(CodeStub::GetMajorKey(*code) == CodeStub::CallFunction);
486 return isolate->builtins()->CallFunctionStub_DebugBreak();
487 }
488
489 UNREACHABLE();
490 return Handle<Code>::null();
491}
492
493
Steve Blocka7e24c12009-10-30 11:49:00 +0000494void BreakLocationIterator::SetDebugBreakAtIC() {
495 // Patch the original code with the current address as the current address
496 // might have changed by the inline caching since the code was copied.
497 original_rinfo()->set_target_address(rinfo()->target_address());
498
499 RelocInfo::Mode mode = rmode();
500 if (RelocInfo::IsCodeTarget(mode)) {
501 Address target = rinfo()->target_address();
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100502 Handle<Code> target_code(Code::GetCodeFromTargetAddress(target));
Steve Blocka7e24c12009-10-30 11:49:00 +0000503
504 // Patch the code to invoke the builtin debug break function matching the
505 // calling convention used by the call site.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000506 Handle<Code> dbgbrk_code = DebugBreakForIC(target_code, mode);
Steve Blocka7e24c12009-10-30 11:49:00 +0000507 rinfo()->set_target_address(dbgbrk_code->entry());
Steve Blocka7e24c12009-10-30 11:49:00 +0000508 }
509}
510
511
512void BreakLocationIterator::ClearDebugBreakAtIC() {
513 // Patch the code to the original invoke.
514 rinfo()->set_target_address(original_rinfo()->target_address());
Steve Blocka7e24c12009-10-30 11:49:00 +0000515}
516
517
518bool BreakLocationIterator::IsDebuggerStatement() {
Andrei Popescu402d9372010-02-26 13:31:12 +0000519 return RelocInfo::DEBUG_BREAK == rmode();
Steve Blocka7e24c12009-10-30 11:49:00 +0000520}
521
522
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +0100523bool BreakLocationIterator::IsDebugBreakSlot() {
524 return RelocInfo::DEBUG_BREAK_SLOT == rmode();
525}
526
527
Steve Blocka7e24c12009-10-30 11:49:00 +0000528Object* BreakLocationIterator::BreakPointObjects() {
529 return debug_info_->GetBreakPointObjects(code_position());
530}
531
532
533// Clear out all the debug break code. This is ONLY supposed to be used when
534// shutting down the debugger as it will leave the break point information in
535// DebugInfo even though the code is patched back to the non break point state.
536void BreakLocationIterator::ClearAllDebugBreak() {
537 while (!Done()) {
538 ClearDebugBreak();
539 Next();
540 }
541}
542
543
544bool BreakLocationIterator::RinfoDone() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000545 DCHECK(reloc_iterator_->done() == reloc_iterator_original_->done());
Steve Blocka7e24c12009-10-30 11:49:00 +0000546 return reloc_iterator_->done();
547}
548
549
550void BreakLocationIterator::RinfoNext() {
551 reloc_iterator_->next();
552 reloc_iterator_original_->next();
553#ifdef DEBUG
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000554 DCHECK(reloc_iterator_->done() == reloc_iterator_original_->done());
Steve Blocka7e24c12009-10-30 11:49:00 +0000555 if (!reloc_iterator_->done()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000556 DCHECK(rmode() == original_rmode());
Steve Blocka7e24c12009-10-30 11:49:00 +0000557 }
558#endif
559}
560
561
Steve Blocka7e24c12009-10-30 11:49:00 +0000562// Threading support.
563void Debug::ThreadInit() {
564 thread_local_.break_count_ = 0;
565 thread_local_.break_id_ = 0;
566 thread_local_.break_frame_id_ = StackFrame::NO_ID;
567 thread_local_.last_step_action_ = StepNone;
568 thread_local_.last_statement_position_ = RelocInfo::kNoPosition;
569 thread_local_.step_count_ = 0;
570 thread_local_.last_fp_ = 0;
Ben Murdoch589d6972011-11-30 16:04:58 +0000571 thread_local_.queued_step_count_ = 0;
Steve Blocka7e24c12009-10-30 11:49:00 +0000572 thread_local_.step_into_fp_ = 0;
573 thread_local_.step_out_fp_ = 0;
Steve Block44f0eee2011-05-26 01:26:41 +0100574 // TODO(isolates): frames_are_dropped_?
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400575 base::NoBarrier_Store(&thread_local_.current_debug_scope_,
576 static_cast<base::AtomicWord>(0));
Iain Merrick75681382010-08-19 15:07:18 +0100577 thread_local_.restarter_frame_function_pointer_ = NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +0000578}
579
580
Steve Blocka7e24c12009-10-30 11:49:00 +0000581char* Debug::ArchiveDebug(char* storage) {
582 char* to = storage;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000583 MemCopy(to, reinterpret_cast<char*>(&thread_local_), sizeof(ThreadLocal));
Steve Blocka7e24c12009-10-30 11:49:00 +0000584 ThreadInit();
Steve Blocka7e24c12009-10-30 11:49:00 +0000585 return storage + ArchiveSpacePerThread();
586}
587
588
589char* Debug::RestoreDebug(char* storage) {
590 char* from = storage;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000591 MemCopy(reinterpret_cast<char*>(&thread_local_), from, sizeof(ThreadLocal));
Steve Blocka7e24c12009-10-30 11:49:00 +0000592 return storage + ArchiveSpacePerThread();
593}
594
595
596int Debug::ArchiveSpacePerThread() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000597 return sizeof(ThreadLocal);
Steve Blocka7e24c12009-10-30 11:49:00 +0000598}
599
600
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000601ScriptCache::ScriptCache(Isolate* isolate) : HashMap(HashMap::PointersMatch),
602 isolate_(isolate) {
603 Heap* heap = isolate_->heap();
604 HandleScope scope(isolate_);
Iain Merrick75681382010-08-19 15:07:18 +0100605
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400606 // Perform a GC to get rid of all unreferenced scripts.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000607 heap->CollectAllGarbage(Heap::kMakeHeapIterableMask, "ScriptCache");
Iain Merrick75681382010-08-19 15:07:18 +0100608
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000609 // Scan heap for Script objects.
610 HeapIterator iterator(heap);
611 DisallowHeapAllocation no_allocation;
Iain Merrick75681382010-08-19 15:07:18 +0100612
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000613 for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
614 if (obj->IsScript() && Script::cast(obj)->HasValidSource()) {
615 Add(Handle<Script>(Script::cast(obj)));
616 }
617 }
Iain Merrick75681382010-08-19 15:07:18 +0100618}
619
Iain Merrick75681382010-08-19 15:07:18 +0100620
Steve Blocka7e24c12009-10-30 11:49:00 +0000621void ScriptCache::Add(Handle<Script> script) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000622 GlobalHandles* global_handles = isolate_->global_handles();
Steve Blocka7e24c12009-10-30 11:49:00 +0000623 // Create an entry in the hash map for the script.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000624 int id = script->id()->value();
Steve Blocka7e24c12009-10-30 11:49:00 +0000625 HashMap::Entry* entry =
626 HashMap::Lookup(reinterpret_cast<void*>(id), Hash(id), true);
627 if (entry->value != NULL) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000628#ifdef DEBUG
629 // The code deserializer may introduce duplicate Script objects.
630 // Assert that the Script objects with the same id have the same name.
631 Handle<Script> found(reinterpret_cast<Script**>(entry->value));
632 DCHECK(script->id() == found->id());
633 DCHECK(!script->name()->IsString() ||
634 String::cast(script->name())->Equals(String::cast(found->name())));
635#endif
Steve Blocka7e24c12009-10-30 11:49:00 +0000636 return;
637 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000638 // Globalize the script object, make it weak and use the location of the
639 // global handle as the value in the hash map.
640 Handle<Script> script_ =
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000641 Handle<Script>::cast(global_handles->Create(*script));
642 GlobalHandles::MakeWeak(reinterpret_cast<Object**>(script_.location()),
643 this,
644 ScriptCache::HandleWeakScript);
Steve Blocka7e24c12009-10-30 11:49:00 +0000645 entry->value = script_.location();
646}
647
648
649Handle<FixedArray> ScriptCache::GetScripts() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000650 Factory* factory = isolate_->factory();
651 Handle<FixedArray> instances = factory->NewFixedArray(occupancy());
Steve Blocka7e24c12009-10-30 11:49:00 +0000652 int count = 0;
653 for (HashMap::Entry* entry = Start(); entry != NULL; entry = Next(entry)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000654 DCHECK(entry->value != NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +0000655 if (entry->value != NULL) {
656 instances->set(count, *reinterpret_cast<Script**>(entry->value));
657 count++;
658 }
659 }
660 return instances;
661}
662
663
Steve Blocka7e24c12009-10-30 11:49:00 +0000664void ScriptCache::Clear() {
665 // Iterate the script cache to get rid of all the weak handles.
666 for (HashMap::Entry* entry = Start(); entry != NULL; entry = Next(entry)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000667 DCHECK(entry != NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +0000668 Object** location = reinterpret_cast<Object**>(entry->value);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000669 DCHECK((*location)->IsScript());
670 GlobalHandles::ClearWeakness(location);
671 GlobalHandles::Destroy(location);
Steve Blocka7e24c12009-10-30 11:49:00 +0000672 }
673 // Clear the content of the hash map.
674 HashMap::Clear();
675}
676
677
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000678void ScriptCache::HandleWeakScript(
679 const v8::WeakCallbackData<v8::Value, void>& data) {
680 // Retrieve the script identifier.
681 Handle<Object> object = Utils::OpenHandle(*data.GetValue());
682 int id = Handle<Script>::cast(object)->id()->value();
683 void* key = reinterpret_cast<void*>(id);
684 uint32_t hash = Hash(id);
Steve Blocka7e24c12009-10-30 11:49:00 +0000685
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000686 // Remove the corresponding entry from the cache.
687 ScriptCache* script_cache =
688 reinterpret_cast<ScriptCache*>(data.GetParameter());
689 HashMap::Entry* entry = script_cache->Lookup(key, hash, false);
690 Object** location = reinterpret_cast<Object**>(entry->value);
691 script_cache->Remove(key, hash);
Steve Blocka7e24c12009-10-30 11:49:00 +0000692
693 // Clear the weak handle.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000694 GlobalHandles::Destroy(location);
Steve Blocka7e24c12009-10-30 11:49:00 +0000695}
696
697
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400698void Debug::HandlePhantomDebugInfo(
699 const v8::PhantomCallbackData<DebugInfoListNode>& data) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000700 Debug* debug = reinterpret_cast<Isolate*>(data.GetIsolate())->debug();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400701 DebugInfoListNode* node = data.GetParameter();
702 debug->RemoveDebugInfo(node);
Steve Blocka7e24c12009-10-30 11:49:00 +0000703#ifdef DEBUG
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000704 for (DebugInfoListNode* n = debug->debug_info_list_;
705 n != NULL;
706 n = n->next()) {
707 DCHECK(n != node);
Steve Blocka7e24c12009-10-30 11:49:00 +0000708 }
709#endif
710}
711
712
713DebugInfoListNode::DebugInfoListNode(DebugInfo* debug_info): next_(NULL) {
714 // Globalize the request debug info object and make it weak.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000715 GlobalHandles* global_handles = debug_info->GetIsolate()->global_handles();
716 debug_info_ = Handle<DebugInfo>::cast(global_handles->Create(debug_info));
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400717 typedef PhantomCallbackData<void>::Callback Callback;
718 GlobalHandles::MakePhantom(
719 reinterpret_cast<Object**>(debug_info_.location()), this,
720 reinterpret_cast<Callback>(Debug::HandlePhantomDebugInfo));
Steve Blocka7e24c12009-10-30 11:49:00 +0000721}
722
723
724DebugInfoListNode::~DebugInfoListNode() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000725 GlobalHandles::Destroy(reinterpret_cast<Object**>(debug_info_.location()));
Steve Blocka7e24c12009-10-30 11:49:00 +0000726}
727
728
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000729bool Debug::CompileDebuggerScript(Isolate* isolate, int index) {
Steve Block44f0eee2011-05-26 01:26:41 +0100730 Factory* factory = isolate->factory();
731 HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +0000732
733 // Bail out if the index is invalid.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000734 if (index == -1) return false;
Steve Blocka7e24c12009-10-30 11:49:00 +0000735
736 // Find source and name for the requested script.
Steve Block44f0eee2011-05-26 01:26:41 +0100737 Handle<String> source_code =
738 isolate->bootstrapper()->NativesSourceLookup(index);
Steve Blocka7e24c12009-10-30 11:49:00 +0000739 Vector<const char> name = Natives::GetScriptName(index);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000740 Handle<String> script_name =
741 factory->NewStringFromAscii(name).ToHandleChecked();
742 Handle<Context> context = isolate->native_context();
Steve Blocka7e24c12009-10-30 11:49:00 +0000743
744 // Compile the script.
Steve Block6ded16b2010-05-10 14:33:55 +0100745 Handle<SharedFunctionInfo> function_info;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000746 function_info = Compiler::CompileScript(
747 source_code, script_name, 0, 0, false, context, NULL, NULL,
748 ScriptCompiler::kNoCompileOptions, NATIVES_CODE);
Steve Blocka7e24c12009-10-30 11:49:00 +0000749
750 // Silently ignore stack overflows during compilation.
Steve Block6ded16b2010-05-10 14:33:55 +0100751 if (function_info.is_null()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000752 DCHECK(isolate->has_pending_exception());
Steve Block44f0eee2011-05-26 01:26:41 +0100753 isolate->clear_pending_exception();
Steve Blocka7e24c12009-10-30 11:49:00 +0000754 return false;
755 }
756
Steve Block6ded16b2010-05-10 14:33:55 +0100757 // Execute the shared function in the debugger context.
Steve Blocka7e24c12009-10-30 11:49:00 +0000758 Handle<JSFunction> function =
Steve Block44f0eee2011-05-26 01:26:41 +0100759 factory->NewFunctionFromSharedFunctionInfo(function_info, context);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +0000760
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000761 MaybeHandle<Object> maybe_exception;
762 MaybeHandle<Object> result = Execution::TryCall(
763 function, handle(context->global_proxy()), 0, NULL, &maybe_exception);
Steve Blocka7e24c12009-10-30 11:49:00 +0000764
765 // Check for caught exceptions.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000766 if (result.is_null()) {
767 DCHECK(!isolate->has_pending_exception());
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100768 MessageLocation computed_location;
769 isolate->ComputeLocation(&computed_location);
Steve Blocka7e24c12009-10-30 11:49:00 +0000770 Handle<Object> message = MessageHandler::MakeMessageObject(
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000771 isolate, "error_loading_debugger", &computed_location,
772 Vector<Handle<Object> >::empty(), Handle<JSArray>());
773 DCHECK(!isolate->has_pending_exception());
774 Handle<Object> exception;
775 if (maybe_exception.ToHandle(&exception)) {
776 isolate->set_pending_exception(*exception);
777 MessageHandler::ReportMessage(isolate, NULL, message);
778 isolate->clear_pending_exception();
779 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000780 return false;
781 }
782
783 // Mark this script as native and return successfully.
784 Handle<Script> script(Script::cast(function->shared()->script()));
Steve Block6ded16b2010-05-10 14:33:55 +0100785 script->set_type(Smi::FromInt(Script::TYPE_NATIVE));
Steve Blocka7e24c12009-10-30 11:49:00 +0000786 return true;
787}
788
789
790bool Debug::Load() {
791 // Return if debugger is already loaded.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000792 if (is_loaded()) return true;
Steve Block44f0eee2011-05-26 01:26:41 +0100793
Steve Blocka7e24c12009-10-30 11:49:00 +0000794 // Bail out if we're already in the process of compiling the native
795 // JavaScript source code for the debugger.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000796 if (is_suppressed_) return false;
797 SuppressDebug while_loading(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000798
799 // Disable breakpoints and interrupts while compiling and running the
800 // debugger scripts including the context creation code.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000801 DisableBreak disable(this, true);
Steve Block44f0eee2011-05-26 01:26:41 +0100802 PostponeInterruptsScope postpone(isolate_);
Steve Blocka7e24c12009-10-30 11:49:00 +0000803
804 // Create the debugger context.
Steve Block44f0eee2011-05-26 01:26:41 +0100805 HandleScope scope(isolate_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000806 ExtensionConfiguration no_extensions;
Steve Blocka7e24c12009-10-30 11:49:00 +0000807 Handle<Context> context =
Steve Block44f0eee2011-05-26 01:26:41 +0100808 isolate_->bootstrapper()->CreateEnvironment(
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000809 MaybeHandle<JSGlobalProxy>(),
Steve Block44f0eee2011-05-26 01:26:41 +0100810 v8::Handle<ObjectTemplate>(),
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000811 &no_extensions);
Steve Blocka7e24c12009-10-30 11:49:00 +0000812
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100813 // Fail if no context could be created.
814 if (context.is_null()) return false;
815
Steve Blocka7e24c12009-10-30 11:49:00 +0000816 // Use the debugger context.
Steve Block44f0eee2011-05-26 01:26:41 +0100817 SaveContext save(isolate_);
818 isolate_->set_context(*context);
Steve Blocka7e24c12009-10-30 11:49:00 +0000819
820 // Expose the builtins object in the debugger context.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000821 Handle<String> key = isolate_->factory()->InternalizeOneByteString(
822 STATIC_CHAR_VECTOR("builtins"));
823 Handle<GlobalObject> global =
824 Handle<GlobalObject>(context->global_object(), isolate_);
825 Handle<JSBuiltinsObject> builtin =
826 Handle<JSBuiltinsObject>(global->builtins(), isolate_);
827 RETURN_ON_EXCEPTION_VALUE(
828 isolate_, Object::SetProperty(global, key, builtin, SLOPPY), false);
Steve Blocka7e24c12009-10-30 11:49:00 +0000829
830 // Compile the JavaScript for the debugger in the debugger context.
Steve Blocka7e24c12009-10-30 11:49:00 +0000831 bool caught_exception =
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000832 !CompileDebuggerScript(isolate_, Natives::GetIndex("mirror")) ||
833 !CompileDebuggerScript(isolate_, Natives::GetIndex("debug"));
Steve Block6ded16b2010-05-10 14:33:55 +0100834
835 if (FLAG_enable_liveedit) {
836 caught_exception = caught_exception ||
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000837 !CompileDebuggerScript(isolate_, Natives::GetIndex("liveedit"));
Steve Block6ded16b2010-05-10 14:33:55 +0100838 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000839 // Check for caught exceptions.
840 if (caught_exception) return false;
841
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000842 debug_context_ = Handle<Context>::cast(
843 isolate_->global_handles()->Create(*context));
Steve Blocka7e24c12009-10-30 11:49:00 +0000844 return true;
845}
846
847
848void Debug::Unload() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000849 ClearAllBreakPoints();
850 ClearStepping();
851
Steve Blocka7e24c12009-10-30 11:49:00 +0000852 // Return debugger is not loaded.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000853 if (!is_loaded()) return;
Steve Blocka7e24c12009-10-30 11:49:00 +0000854
855 // Clear the script cache.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000856 if (script_cache_ != NULL) {
857 delete script_cache_;
858 script_cache_ = NULL;
859 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000860
861 // Clear debugger context global handle.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000862 GlobalHandles::Destroy(Handle<Object>::cast(debug_context_).location());
Steve Blocka7e24c12009-10-30 11:49:00 +0000863 debug_context_ = Handle<Context>();
864}
865
866
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000867void Debug::Break(Arguments args, JavaScriptFrame* frame) {
Ben Murdoch8b112d22011-06-08 16:22:53 +0100868 Heap* heap = isolate_->heap();
869 HandleScope scope(isolate_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000870 DCHECK(args.length() == 0);
Steve Blocka7e24c12009-10-30 11:49:00 +0000871
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000872 // Initialize LiveEdit.
873 LiveEdit::InitializeThreadLocal(this);
Steve Blocka7e24c12009-10-30 11:49:00 +0000874
875 // Just continue if breaks are disabled or debugger cannot be loaded.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400876 if (break_disabled()) return;
Steve Blocka7e24c12009-10-30 11:49:00 +0000877
878 // Enter the debugger.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000879 DebugScope debug_scope(this);
880 if (debug_scope.failed()) return;
Steve Blocka7e24c12009-10-30 11:49:00 +0000881
882 // Postpone interrupt during breakpoint processing.
Ben Murdoch8b112d22011-06-08 16:22:53 +0100883 PostponeInterruptsScope postpone(isolate_);
Steve Blocka7e24c12009-10-30 11:49:00 +0000884
885 // Get the debug info (create it if it does not exist).
886 Handle<SharedFunctionInfo> shared =
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000887 Handle<SharedFunctionInfo>(frame->function()->shared());
Steve Blocka7e24c12009-10-30 11:49:00 +0000888 Handle<DebugInfo> debug_info = GetDebugInfo(shared);
889
890 // Find the break point where execution has stopped.
891 BreakLocationIterator break_location_iterator(debug_info,
892 ALL_BREAK_LOCATIONS);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000893 // pc points to the instruction after the current one, possibly a break
894 // location as well. So the "- 1" to exclude it from the search.
895 break_location_iterator.FindBreakLocationFromAddress(frame->pc() - 1);
Steve Blocka7e24c12009-10-30 11:49:00 +0000896
897 // Check whether step next reached a new statement.
Ben Murdoch8b112d22011-06-08 16:22:53 +0100898 if (!StepNextContinue(&break_location_iterator, frame)) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000899 // Decrease steps left if performing multiple steps.
Ben Murdoch8b112d22011-06-08 16:22:53 +0100900 if (thread_local_.step_count_ > 0) {
901 thread_local_.step_count_--;
Steve Blocka7e24c12009-10-30 11:49:00 +0000902 }
903 }
904
905 // If there is one or more real break points check whether any of these are
906 // triggered.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000907 Handle<Object> break_points_hit(heap->undefined_value(), isolate_);
Steve Blocka7e24c12009-10-30 11:49:00 +0000908 if (break_location_iterator.HasBreakPoint()) {
909 Handle<Object> break_point_objects =
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000910 Handle<Object>(break_location_iterator.BreakPointObjects(), isolate_);
Ben Murdoch8b112d22011-06-08 16:22:53 +0100911 break_points_hit = CheckBreakPoints(break_point_objects);
Steve Blocka7e24c12009-10-30 11:49:00 +0000912 }
913
914 // If step out is active skip everything until the frame where we need to step
915 // out to is reached, unless real breakpoint is hit.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000916 if (StepOutActive() &&
917 frame->fp() != thread_local_.step_out_fp_ &&
Steve Blocka7e24c12009-10-30 11:49:00 +0000918 break_points_hit->IsUndefined() ) {
919 // Step count should always be 0 for StepOut.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000920 DCHECK(thread_local_.step_count_ == 0);
Steve Blocka7e24c12009-10-30 11:49:00 +0000921 } else if (!break_points_hit->IsUndefined() ||
Ben Murdoch8b112d22011-06-08 16:22:53 +0100922 (thread_local_.last_step_action_ != StepNone &&
923 thread_local_.step_count_ == 0)) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000924 // Notify debugger if a real break point is triggered or if performing
925 // single stepping with no more steps to perform. Otherwise do another step.
926
927 // Clear all current stepping setup.
Ben Murdoch8b112d22011-06-08 16:22:53 +0100928 ClearStepping();
Steve Blocka7e24c12009-10-30 11:49:00 +0000929
Ben Murdoch589d6972011-11-30 16:04:58 +0000930 if (thread_local_.queued_step_count_ > 0) {
931 // Perform queued steps
932 int step_count = thread_local_.queued_step_count_;
933
934 // Clear queue
935 thread_local_.queued_step_count_ = 0;
936
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000937 PrepareStep(StepNext, step_count, StackFrame::NO_ID);
Ben Murdoch589d6972011-11-30 16:04:58 +0000938 } else {
939 // Notify the debug event listeners.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000940 OnDebugBreak(break_points_hit, false);
Ben Murdoch589d6972011-11-30 16:04:58 +0000941 }
Ben Murdoch8b112d22011-06-08 16:22:53 +0100942 } else if (thread_local_.last_step_action_ != StepNone) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000943 // Hold on to last step action as it is cleared by the call to
944 // ClearStepping.
Ben Murdoch8b112d22011-06-08 16:22:53 +0100945 StepAction step_action = thread_local_.last_step_action_;
946 int step_count = thread_local_.step_count_;
Steve Blocka7e24c12009-10-30 11:49:00 +0000947
Ben Murdoch589d6972011-11-30 16:04:58 +0000948 // If StepNext goes deeper in code, StepOut until original frame
949 // and keep step count queued up in the meantime.
950 if (step_action == StepNext && frame->fp() < thread_local_.last_fp_) {
951 // Count frames until target frame
952 int count = 0;
953 JavaScriptFrameIterator it(isolate_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000954 while (!it.done() && it.frame()->fp() < thread_local_.last_fp_) {
Ben Murdoch589d6972011-11-30 16:04:58 +0000955 count++;
956 it.Advance();
957 }
958
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000959 // Check that we indeed found the frame we are looking for.
960 CHECK(!it.done() && (it.frame()->fp() == thread_local_.last_fp_));
961 if (step_count > 1) {
962 // Save old count and action to continue stepping after StepOut.
963 thread_local_.queued_step_count_ = step_count - 1;
Ben Murdoch589d6972011-11-30 16:04:58 +0000964 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000965
966 // Set up for StepOut to reach target frame.
967 step_action = StepOut;
968 step_count = count;
Ben Murdoch589d6972011-11-30 16:04:58 +0000969 }
970
Steve Blocka7e24c12009-10-30 11:49:00 +0000971 // Clear all current stepping setup.
Ben Murdoch8b112d22011-06-08 16:22:53 +0100972 ClearStepping();
Steve Blocka7e24c12009-10-30 11:49:00 +0000973
974 // Set up for the remaining steps.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000975 PrepareStep(step_action, step_count, StackFrame::NO_ID);
Steve Blocka7e24c12009-10-30 11:49:00 +0000976 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000977}
978
979
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000980RUNTIME_FUNCTION(Debug_Break) {
981 // Get the top-most JavaScript frame.
982 JavaScriptFrameIterator it(isolate);
983 isolate->debug()->Break(args, it.frame());
984 isolate->debug()->SetAfterBreakTarget(it.frame());
985 return isolate->heap()->undefined_value();
Ben Murdoch8b112d22011-06-08 16:22:53 +0100986}
987
988
Steve Blocka7e24c12009-10-30 11:49:00 +0000989// Check the break point objects for whether one or more are actually
990// triggered. This function returns a JSArray with the break point objects
991// which is triggered.
992Handle<Object> Debug::CheckBreakPoints(Handle<Object> break_point_objects) {
Steve Block44f0eee2011-05-26 01:26:41 +0100993 Factory* factory = isolate_->factory();
Steve Blocka7e24c12009-10-30 11:49:00 +0000994
Steve Block44f0eee2011-05-26 01:26:41 +0100995 // Count the number of break points hit. If there are multiple break points
996 // they are in a FixedArray.
997 Handle<FixedArray> break_points_hit;
998 int break_points_hit_count = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000999 DCHECK(!break_point_objects->IsUndefined());
Steve Blocka7e24c12009-10-30 11:49:00 +00001000 if (break_point_objects->IsFixedArray()) {
1001 Handle<FixedArray> array(FixedArray::cast(*break_point_objects));
Steve Block44f0eee2011-05-26 01:26:41 +01001002 break_points_hit = factory->NewFixedArray(array->length());
Steve Blocka7e24c12009-10-30 11:49:00 +00001003 for (int i = 0; i < array->length(); i++) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001004 Handle<Object> o(array->get(i), isolate_);
Steve Blocka7e24c12009-10-30 11:49:00 +00001005 if (CheckBreakPoint(o)) {
Steve Block44f0eee2011-05-26 01:26:41 +01001006 break_points_hit->set(break_points_hit_count++, *o);
Steve Blocka7e24c12009-10-30 11:49:00 +00001007 }
1008 }
1009 } else {
Steve Block44f0eee2011-05-26 01:26:41 +01001010 break_points_hit = factory->NewFixedArray(1);
Steve Blocka7e24c12009-10-30 11:49:00 +00001011 if (CheckBreakPoint(break_point_objects)) {
Steve Block44f0eee2011-05-26 01:26:41 +01001012 break_points_hit->set(break_points_hit_count++, *break_point_objects);
Steve Blocka7e24c12009-10-30 11:49:00 +00001013 }
1014 }
1015
Kristian Monsen80d68ea2010-09-08 11:05:35 +01001016 // Return undefined if no break points were triggered.
Steve Blocka7e24c12009-10-30 11:49:00 +00001017 if (break_points_hit_count == 0) {
Steve Block44f0eee2011-05-26 01:26:41 +01001018 return factory->undefined_value();
Steve Blocka7e24c12009-10-30 11:49:00 +00001019 }
Steve Block44f0eee2011-05-26 01:26:41 +01001020 // Return break points hit as a JSArray.
1021 Handle<JSArray> result = factory->NewJSArrayWithElements(break_points_hit);
1022 result->set_length(Smi::FromInt(break_points_hit_count));
1023 return result;
Steve Blocka7e24c12009-10-30 11:49:00 +00001024}
1025
1026
1027// Check whether a single break point object is triggered.
1028bool Debug::CheckBreakPoint(Handle<Object> break_point_object) {
Steve Block44f0eee2011-05-26 01:26:41 +01001029 Factory* factory = isolate_->factory();
1030 HandleScope scope(isolate_);
Steve Blocka7e24c12009-10-30 11:49:00 +00001031
1032 // Ignore check if break point object is not a JSObject.
1033 if (!break_point_object->IsJSObject()) return true;
1034
Steve Block44f0eee2011-05-26 01:26:41 +01001035 // Get the function IsBreakPointTriggered (defined in debug-debugger.js).
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001036 Handle<String> is_break_point_triggered_string =
1037 factory->InternalizeOneByteString(
1038 STATIC_CHAR_VECTOR("IsBreakPointTriggered"));
1039 Handle<GlobalObject> debug_global(debug_context()->global_object());
Steve Blocka7e24c12009-10-30 11:49:00 +00001040 Handle<JSFunction> check_break_point =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001041 Handle<JSFunction>::cast(Object::GetProperty(
1042 debug_global, is_break_point_triggered_string).ToHandleChecked());
Steve Blocka7e24c12009-10-30 11:49:00 +00001043
1044 // Get the break id as an object.
Steve Block44f0eee2011-05-26 01:26:41 +01001045 Handle<Object> break_id = factory->NewNumberFromInt(Debug::break_id());
Steve Blocka7e24c12009-10-30 11:49:00 +00001046
1047 // Call HandleBreakPointx.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001048 Handle<Object> argv[] = { break_id, break_point_object };
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001049 Handle<Object> result;
1050 if (!Execution::TryCall(check_break_point,
1051 isolate_->js_builtins_object(),
1052 arraysize(argv),
1053 argv).ToHandle(&result)) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001054 return false;
1055 }
1056
1057 // Return whether the break point is triggered.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001058 return result->IsTrue();
Steve Blocka7e24c12009-10-30 11:49:00 +00001059}
1060
1061
1062// Check whether the function has debug information.
1063bool Debug::HasDebugInfo(Handle<SharedFunctionInfo> shared) {
1064 return !shared->debug_info()->IsUndefined();
1065}
1066
1067
1068// Return the debug info for this function. EnsureDebugInfo must be called
1069// prior to ensure the debug info has been generated for shared.
1070Handle<DebugInfo> Debug::GetDebugInfo(Handle<SharedFunctionInfo> shared) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001071 DCHECK(HasDebugInfo(shared));
Steve Blocka7e24c12009-10-30 11:49:00 +00001072 return Handle<DebugInfo>(DebugInfo::cast(shared->debug_info()));
1073}
1074
1075
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001076bool Debug::SetBreakPoint(Handle<JSFunction> function,
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01001077 Handle<Object> break_point_object,
1078 int* source_position) {
Steve Block44f0eee2011-05-26 01:26:41 +01001079 HandleScope scope(isolate_);
Steve Blocka7e24c12009-10-30 11:49:00 +00001080
Ben Murdoch589d6972011-11-30 16:04:58 +00001081 PrepareForBreakPoints();
1082
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001083 // Make sure the function is compiled and has set up the debug info.
1084 Handle<SharedFunctionInfo> shared(function->shared());
1085 if (!EnsureDebugInfo(shared, function)) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001086 // Return if retrieving debug info failed.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001087 return true;
Steve Blocka7e24c12009-10-30 11:49:00 +00001088 }
1089
1090 Handle<DebugInfo> debug_info = GetDebugInfo(shared);
1091 // Source positions starts with zero.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001092 DCHECK(*source_position >= 0);
Steve Blocka7e24c12009-10-30 11:49:00 +00001093
1094 // Find the break point and change it.
1095 BreakLocationIterator it(debug_info, SOURCE_BREAK_LOCATIONS);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001096 it.FindBreakLocationFromPosition(*source_position, STATEMENT_ALIGNED);
Steve Blocka7e24c12009-10-30 11:49:00 +00001097 it.SetBreakPoint(break_point_object);
1098
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001099 *source_position = it.statement_position();
Kristian Monsen9dcf7e22010-06-28 14:14:28 +01001100
Steve Blocka7e24c12009-10-30 11:49:00 +00001101 // At least one active break point now.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001102 return debug_info->GetBreakPointCount() > 0;
1103}
1104
1105
1106bool Debug::SetBreakPointForScript(Handle<Script> script,
1107 Handle<Object> break_point_object,
1108 int* source_position,
1109 BreakPositionAlignment alignment) {
1110 HandleScope scope(isolate_);
1111
1112 PrepareForBreakPoints();
1113
1114 // Obtain shared function info for the function.
1115 Object* result = FindSharedFunctionInfoInScript(script, *source_position);
1116 if (result->IsUndefined()) return false;
1117
1118 // Make sure the function has set up the debug info.
1119 Handle<SharedFunctionInfo> shared(SharedFunctionInfo::cast(result));
1120 if (!EnsureDebugInfo(shared, Handle<JSFunction>::null())) {
1121 // Return if retrieving debug info failed.
1122 return false;
1123 }
1124
1125 // Find position within function. The script position might be before the
1126 // source position of the first function.
1127 int position;
1128 if (shared->start_position() > *source_position) {
1129 position = 0;
1130 } else {
1131 position = *source_position - shared->start_position();
1132 }
1133
1134 Handle<DebugInfo> debug_info = GetDebugInfo(shared);
1135 // Source positions starts with zero.
1136 DCHECK(position >= 0);
1137
1138 // Find the break point and change it.
1139 BreakLocationIterator it(debug_info, SOURCE_BREAK_LOCATIONS);
1140 it.FindBreakLocationFromPosition(position, alignment);
1141 it.SetBreakPoint(break_point_object);
1142
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001143 position = (alignment == STATEMENT_ALIGNED) ? it.statement_position()
1144 : it.position();
1145
1146 *source_position = position + shared->start_position();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001147
1148 // At least one active break point now.
1149 DCHECK(debug_info->GetBreakPointCount() > 0);
1150 return true;
Steve Blocka7e24c12009-10-30 11:49:00 +00001151}
1152
1153
1154void Debug::ClearBreakPoint(Handle<Object> break_point_object) {
Steve Block44f0eee2011-05-26 01:26:41 +01001155 HandleScope scope(isolate_);
Steve Blocka7e24c12009-10-30 11:49:00 +00001156
1157 DebugInfoListNode* node = debug_info_list_;
1158 while (node != NULL) {
1159 Object* result = DebugInfo::FindBreakPointInfo(node->debug_info(),
1160 break_point_object);
1161 if (!result->IsUndefined()) {
1162 // Get information in the break point.
1163 BreakPointInfo* break_point_info = BreakPointInfo::cast(result);
1164 Handle<DebugInfo> debug_info = node->debug_info();
Steve Blocka7e24c12009-10-30 11:49:00 +00001165
1166 // Find the break point and clear it.
1167 BreakLocationIterator it(debug_info, SOURCE_BREAK_LOCATIONS);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001168 it.FindBreakLocationFromAddress(debug_info->code()->entry() +
1169 break_point_info->code_position()->value());
Steve Blocka7e24c12009-10-30 11:49:00 +00001170 it.ClearBreakPoint(break_point_object);
1171
1172 // If there are no more break points left remove the debug info for this
1173 // function.
1174 if (debug_info->GetBreakPointCount() == 0) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001175 RemoveDebugInfoAndClearFromShared(debug_info);
Steve Blocka7e24c12009-10-30 11:49:00 +00001176 }
1177
1178 return;
1179 }
1180 node = node->next();
1181 }
1182}
1183
1184
1185void Debug::ClearAllBreakPoints() {
1186 DebugInfoListNode* node = debug_info_list_;
1187 while (node != NULL) {
1188 // Remove all debug break code.
1189 BreakLocationIterator it(node->debug_info(), ALL_BREAK_LOCATIONS);
1190 it.ClearAllDebugBreak();
1191 node = node->next();
1192 }
1193
1194 // Remove all debug info.
1195 while (debug_info_list_ != NULL) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001196 RemoveDebugInfoAndClearFromShared(debug_info_list_->debug_info());
Steve Blocka7e24c12009-10-30 11:49:00 +00001197 }
1198}
1199
1200
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001201void Debug::FloodWithOneShot(Handle<JSFunction> function,
1202 BreakLocatorType type) {
1203 // Do not ever break in native functions.
1204 if (function->IsFromNativeScript()) return;
1205
Ben Murdoch589d6972011-11-30 16:04:58 +00001206 PrepareForBreakPoints();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001207
1208 // Make sure the function is compiled and has set up the debug info.
1209 Handle<SharedFunctionInfo> shared(function->shared());
1210 if (!EnsureDebugInfo(shared, function)) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001211 // Return if we failed to retrieve the debug info.
1212 return;
1213 }
1214
1215 // Flood the function with break points.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001216 BreakLocationIterator it(GetDebugInfo(shared), type);
Steve Blocka7e24c12009-10-30 11:49:00 +00001217 while (!it.Done()) {
1218 it.SetOneShot();
1219 it.Next();
1220 }
1221}
1222
1223
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001224void Debug::FloodBoundFunctionWithOneShot(Handle<JSFunction> function) {
1225 Handle<FixedArray> new_bindings(function->function_bindings());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001226 Handle<Object> bindee(new_bindings->get(JSFunction::kBoundFunctionIndex),
1227 isolate_);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001228
1229 if (!bindee.is_null() && bindee->IsJSFunction() &&
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001230 !JSFunction::cast(*bindee)->IsFromNativeScript()) {
1231 Handle<JSFunction> bindee_function(JSFunction::cast(*bindee));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001232 FloodWithOneShotGeneric(bindee_function);
1233 }
1234}
1235
1236
1237void Debug::FloodDefaultConstructorWithOneShot(Handle<JSFunction> function) {
1238 DCHECK(function->shared()->is_default_constructor());
1239 // Instead of stepping into the function we directly step into the super class
1240 // constructor.
1241 Isolate* isolate = function->GetIsolate();
1242 PrototypeIterator iter(isolate, function);
1243 Handle<Object> proto = PrototypeIterator::GetCurrent(iter);
1244 if (!proto->IsJSFunction()) return; // Object.prototype
1245 Handle<JSFunction> function_proto = Handle<JSFunction>::cast(proto);
1246 FloodWithOneShotGeneric(function_proto);
1247}
1248
1249
1250void Debug::FloodWithOneShotGeneric(Handle<JSFunction> function,
1251 Handle<Object> holder) {
1252 if (function->shared()->bound()) {
1253 FloodBoundFunctionWithOneShot(function);
1254 } else if (function->shared()->is_default_constructor()) {
1255 FloodDefaultConstructorWithOneShot(function);
1256 } else {
1257 Isolate* isolate = function->GetIsolate();
1258 // Don't allow step into functions in the native context.
1259 if (function->shared()->code() ==
1260 isolate->builtins()->builtin(Builtins::kFunctionApply) ||
1261 function->shared()->code() ==
1262 isolate->builtins()->builtin(Builtins::kFunctionCall)) {
1263 // Handle function.apply and function.call separately to flood the
1264 // function to be called and not the code for Builtins::FunctionApply or
1265 // Builtins::FunctionCall. The receiver of call/apply is the target
1266 // function.
1267 if (!holder.is_null() && holder->IsJSFunction()) {
1268 Handle<JSFunction> js_function = Handle<JSFunction>::cast(holder);
1269 FloodWithOneShotGeneric(js_function);
1270 }
1271 } else {
1272 FloodWithOneShot(function);
1273 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001274 }
1275}
1276
1277
Steve Blocka7e24c12009-10-30 11:49:00 +00001278void Debug::FloodHandlerWithOneShot() {
1279 // Iterate through the JavaScript stack looking for handlers.
1280 StackFrame::Id id = break_frame_id();
1281 if (id == StackFrame::NO_ID) {
1282 // If there is no JavaScript stack don't do anything.
1283 return;
1284 }
Ben Murdoch8b112d22011-06-08 16:22:53 +01001285 for (JavaScriptFrameIterator it(isolate_, id); !it.done(); it.Advance()) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001286 JavaScriptFrame* frame = it.frame();
1287 if (frame->HasHandler()) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001288 // Flood the function with the catch block with break points
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001289 FloodWithOneShot(Handle<JSFunction>(frame->function()));
Steve Blocka7e24c12009-10-30 11:49:00 +00001290 return;
1291 }
1292 }
1293}
1294
1295
1296void Debug::ChangeBreakOnException(ExceptionBreakType type, bool enable) {
1297 if (type == BreakUncaughtException) {
1298 break_on_uncaught_exception_ = enable;
1299 } else {
1300 break_on_exception_ = enable;
1301 }
1302}
1303
1304
Kristian Monsen0d5e1162010-09-30 15:31:59 +01001305bool Debug::IsBreakOnException(ExceptionBreakType type) {
1306 if (type == BreakUncaughtException) {
1307 return break_on_uncaught_exception_;
1308 } else {
1309 return break_on_exception_;
1310 }
1311}
1312
1313
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001314void Debug::PrepareStep(StepAction step_action,
1315 int step_count,
1316 StackFrame::Id frame_id) {
Steve Block44f0eee2011-05-26 01:26:41 +01001317 HandleScope scope(isolate_);
Ben Murdoch589d6972011-11-30 16:04:58 +00001318
1319 PrepareForBreakPoints();
1320
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001321 DCHECK(in_debug_scope());
Steve Blocka7e24c12009-10-30 11:49:00 +00001322
1323 // Remember this step action and count.
1324 thread_local_.last_step_action_ = step_action;
1325 if (step_action == StepOut) {
1326 // For step out target frame will be found on the stack so there is no need
1327 // to set step counter for it. It's expected to always be 0 for StepOut.
1328 thread_local_.step_count_ = 0;
1329 } else {
1330 thread_local_.step_count_ = step_count;
1331 }
1332
1333 // Get the frame where the execution has stopped and skip the debug frame if
1334 // any. The debug frame will only be present if execution was stopped due to
1335 // hitting a break point. In other situations (e.g. unhandled exception) the
1336 // debug frame is not present.
1337 StackFrame::Id id = break_frame_id();
1338 if (id == StackFrame::NO_ID) {
1339 // If there is no JavaScript stack don't do anything.
1340 return;
1341 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001342 if (frame_id != StackFrame::NO_ID) {
1343 id = frame_id;
1344 }
Ben Murdoch8b112d22011-06-08 16:22:53 +01001345 JavaScriptFrameIterator frames_it(isolate_, id);
Steve Blocka7e24c12009-10-30 11:49:00 +00001346 JavaScriptFrame* frame = frames_it.frame();
1347
1348 // First of all ensure there is one-shot break points in the top handler
1349 // if any.
1350 FloodHandlerWithOneShot();
1351
1352 // If the function on the top frame is unresolved perform step out. This will
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001353 // be the case when calling unknown function and having the debugger stopped
Steve Blocka7e24c12009-10-30 11:49:00 +00001354 // in an unhandled exception.
1355 if (!frame->function()->IsJSFunction()) {
1356 // Step out: Find the calling JavaScript frame and flood it with
1357 // breakpoints.
1358 frames_it.Advance();
1359 // Fill the function to return to with one-shot break points.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001360 JSFunction* function = frames_it.frame()->function();
1361 FloodWithOneShot(Handle<JSFunction>(function));
Steve Blocka7e24c12009-10-30 11:49:00 +00001362 return;
1363 }
1364
1365 // Get the debug info (create it if it does not exist).
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001366 Handle<JSFunction> function(frame->function());
1367 Handle<SharedFunctionInfo> shared(function->shared());
1368 if (!EnsureDebugInfo(shared, function)) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001369 // Return if ensuring debug info failed.
1370 return;
1371 }
1372 Handle<DebugInfo> debug_info = GetDebugInfo(shared);
1373
1374 // Find the break location where execution has stopped.
1375 BreakLocationIterator it(debug_info, ALL_BREAK_LOCATIONS);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001376 // pc points to the instruction after the current one, possibly a break
1377 // location as well. So the "- 1" to exclude it from the search.
1378 it.FindBreakLocationFromAddress(frame->pc() - 1);
Steve Blocka7e24c12009-10-30 11:49:00 +00001379
1380 // Compute whether or not the target is a call target.
Steve Blocka7e24c12009-10-30 11:49:00 +00001381 bool is_load_or_store = false;
1382 bool is_inline_cache_stub = false;
Ben Murdochbb769b22010-08-11 14:56:33 +01001383 bool is_at_restarted_function = false;
Steve Blocka7e24c12009-10-30 11:49:00 +00001384 Handle<Code> call_function_stub;
Steve Blocka7e24c12009-10-30 11:49:00 +00001385
Ben Murdochbb769b22010-08-11 14:56:33 +01001386 if (thread_local_.restarter_frame_function_pointer_ == NULL) {
1387 if (RelocInfo::IsCodeTarget(it.rinfo()->rmode())) {
1388 bool is_call_target = false;
1389 Address target = it.rinfo()->target_address();
1390 Code* code = Code::GetCodeFromTargetAddress(target);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001391 if (code->is_call_stub()) {
Ben Murdochbb769b22010-08-11 14:56:33 +01001392 is_call_target = true;
1393 }
1394 if (code->is_inline_cache_stub()) {
1395 is_inline_cache_stub = true;
1396 is_load_or_store = !is_call_target;
1397 }
1398
1399 // Check if target code is CallFunction stub.
1400 Code* maybe_call_function_stub = code;
1401 // If there is a breakpoint at this line look at the original code to
1402 // check if it is a CallFunction stub.
1403 if (it.IsDebugBreak()) {
1404 Address original_target = it.original_rinfo()->target_address();
1405 maybe_call_function_stub =
1406 Code::GetCodeFromTargetAddress(original_target);
1407 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001408 if ((maybe_call_function_stub->kind() == Code::STUB &&
1409 CodeStub::GetMajorKey(maybe_call_function_stub) ==
1410 CodeStub::CallFunction) ||
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001411 maybe_call_function_stub->is_call_stub()) {
Ben Murdochbb769b22010-08-11 14:56:33 +01001412 // Save reference to the code as we may need it to find out arguments
1413 // count for 'step in' later.
1414 call_function_stub = Handle<Code>(maybe_call_function_stub);
1415 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001416 }
Ben Murdochbb769b22010-08-11 14:56:33 +01001417 } else {
1418 is_at_restarted_function = true;
Steve Blocka7e24c12009-10-30 11:49:00 +00001419 }
1420
1421 // If this is the last break code target step out is the only possibility.
1422 if (it.IsExit() || step_action == StepOut) {
1423 if (step_action == StepOut) {
1424 // Skip step_count frames starting with the current one.
1425 while (step_count-- > 0 && !frames_it.done()) {
1426 frames_it.Advance();
1427 }
1428 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001429 DCHECK(it.IsExit());
Steve Blocka7e24c12009-10-30 11:49:00 +00001430 frames_it.Advance();
1431 }
1432 // Skip builtin functions on the stack.
1433 while (!frames_it.done() &&
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001434 frames_it.frame()->function()->IsFromNativeScript()) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001435 frames_it.Advance();
1436 }
1437 // Step out: If there is a JavaScript caller frame, we need to
1438 // flood it with breakpoints.
1439 if (!frames_it.done()) {
1440 // Fill the function to return to with one-shot break points.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001441 JSFunction* function = frames_it.frame()->function();
1442 FloodWithOneShot(Handle<JSFunction>(function));
Steve Blocka7e24c12009-10-30 11:49:00 +00001443 // Set target frame pointer.
1444 ActivateStepOut(frames_it.frame());
1445 }
1446 } else if (!(is_inline_cache_stub || RelocInfo::IsConstructCall(it.rmode()) ||
Ben Murdochbb769b22010-08-11 14:56:33 +01001447 !call_function_stub.is_null() || is_at_restarted_function)
Steve Blocka7e24c12009-10-30 11:49:00 +00001448 || step_action == StepNext || step_action == StepMin) {
1449 // Step next or step min.
1450
1451 // Fill the current function with one-shot break points.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001452 // If we are stepping into another frame, only fill calls and returns.
1453 FloodWithOneShot(function, step_action == StepFrame ? CALLS_AND_RETURNS
1454 : ALL_BREAK_LOCATIONS);
Steve Blocka7e24c12009-10-30 11:49:00 +00001455
1456 // Remember source position and frame to handle step next.
1457 thread_local_.last_statement_position_ =
1458 debug_info->code()->SourceStatementPosition(frame->pc());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001459 thread_local_.last_fp_ = frame->UnpaddedFP();
Steve Blocka7e24c12009-10-30 11:49:00 +00001460 } else {
Ben Murdochbb769b22010-08-11 14:56:33 +01001461 // If there's restarter frame on top of the stack, just get the pointer
1462 // to function which is going to be restarted.
1463 if (is_at_restarted_function) {
1464 Handle<JSFunction> restarted_function(
1465 JSFunction::cast(*thread_local_.restarter_frame_function_pointer_));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001466 FloodWithOneShot(restarted_function);
Ben Murdochbb769b22010-08-11 14:56:33 +01001467 } else if (!call_function_stub.is_null()) {
1468 // If it's CallFunction stub ensure target function is compiled and flood
1469 // it with one shot breakpoints.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001470 bool is_call_ic = call_function_stub->kind() == Code::CALL_IC;
Ben Murdochbb769b22010-08-11 14:56:33 +01001471
Steve Blocka7e24c12009-10-30 11:49:00 +00001472 // Find out number of arguments from the stub minor key.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001473 uint32_t key = call_function_stub->stub_key();
Steve Blocka7e24c12009-10-30 11:49:00 +00001474 // Argc in the stub is the number of arguments passed - not the
1475 // expected arguments of the called function.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001476 int call_function_arg_count = is_call_ic
1477 ? CallICStub::ExtractArgcFromMinorKey(CodeStub::MinorKeyFromKey(key))
1478 : CallFunctionStub::ExtractArgcFromMinorKey(
Leon Clarkee46be812010-01-19 14:06:41 +00001479 CodeStub::MinorKeyFromKey(key));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001480
1481 DCHECK(is_call_ic ||
1482 CodeStub::GetMajorKey(*call_function_stub) ==
1483 CodeStub::MajorKeyFromKey(key));
Steve Blocka7e24c12009-10-30 11:49:00 +00001484
1485 // Find target function on the expression stack.
Leon Clarkee46be812010-01-19 14:06:41 +00001486 // Expression stack looks like this (top to bottom):
Steve Blocka7e24c12009-10-30 11:49:00 +00001487 // argN
1488 // ...
1489 // arg0
1490 // Receiver
1491 // Function to call
1492 int expressions_count = frame->ComputeExpressionsCount();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001493 DCHECK(expressions_count - 2 - call_function_arg_count >= 0);
Steve Blocka7e24c12009-10-30 11:49:00 +00001494 Object* fun = frame->GetExpression(
1495 expressions_count - 2 - call_function_arg_count);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001496
1497 // Flood the actual target of call/apply.
1498 if (fun->IsJSFunction()) {
1499 Isolate* isolate = JSFunction::cast(fun)->GetIsolate();
1500 Code* apply = isolate->builtins()->builtin(Builtins::kFunctionApply);
1501 Code* call = isolate->builtins()->builtin(Builtins::kFunctionCall);
1502 while (fun->IsJSFunction()) {
1503 Code* code = JSFunction::cast(fun)->shared()->code();
1504 if (code != apply && code != call) break;
1505 fun = frame->GetExpression(
1506 expressions_count - 1 - call_function_arg_count);
1507 }
1508 }
1509
Steve Blocka7e24c12009-10-30 11:49:00 +00001510 if (fun->IsJSFunction()) {
1511 Handle<JSFunction> js_function(JSFunction::cast(fun));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001512 FloodWithOneShotGeneric(js_function);
Steve Blocka7e24c12009-10-30 11:49:00 +00001513 }
1514 }
1515
1516 // Fill the current function with one-shot break points even for step in on
1517 // a call target as the function called might be a native function for
1518 // which step in will not stop. It also prepares for stepping in
1519 // getters/setters.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001520 // If we are stepping into another frame, only fill calls and returns.
1521 FloodWithOneShot(function, step_action == StepFrame ? CALLS_AND_RETURNS
1522 : ALL_BREAK_LOCATIONS);
Steve Blocka7e24c12009-10-30 11:49:00 +00001523
1524 if (is_load_or_store) {
1525 // Remember source position and frame to handle step in getter/setter. If
1526 // there is a custom getter/setter it will be handled in
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001527 // Object::Get/SetPropertyWithAccessor, otherwise the step action will be
Steve Blocka7e24c12009-10-30 11:49:00 +00001528 // propagated on the next Debug::Break.
1529 thread_local_.last_statement_position_ =
1530 debug_info->code()->SourceStatementPosition(frame->pc());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001531 thread_local_.last_fp_ = frame->UnpaddedFP();
Steve Blocka7e24c12009-10-30 11:49:00 +00001532 }
1533
1534 // Step in or Step in min
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001535 it.PrepareStepIn(isolate_);
Steve Blocka7e24c12009-10-30 11:49:00 +00001536 ActivateStepIn(frame);
1537 }
1538}
1539
1540
1541// Check whether the current debug break should be reported to the debugger. It
1542// is used to have step next and step in only report break back to the debugger
1543// if on a different frame or in a different statement. In some situations
1544// there will be several break points in the same statement when the code is
1545// flooded with one-shot break points. This function helps to perform several
1546// steps before reporting break back to the debugger.
1547bool Debug::StepNextContinue(BreakLocationIterator* break_location_iterator,
1548 JavaScriptFrame* frame) {
Ben Murdoch589d6972011-11-30 16:04:58 +00001549 // StepNext and StepOut shouldn't bring us deeper in code, so last frame
1550 // shouldn't be a parent of current frame.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001551 StepAction step_action = thread_local_.last_step_action_;
1552
1553 if (step_action == StepNext || step_action == StepOut) {
Ben Murdoch589d6972011-11-30 16:04:58 +00001554 if (frame->fp() < thread_local_.last_fp_) return true;
1555 }
1556
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001557 // We stepped into a new frame if the frame pointer changed.
1558 if (step_action == StepFrame) {
1559 return frame->UnpaddedFP() == thread_local_.last_fp_;
1560 }
1561
Steve Blocka7e24c12009-10-30 11:49:00 +00001562 // If the step last action was step next or step in make sure that a new
1563 // statement is hit.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001564 if (step_action == StepNext || step_action == StepIn) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001565 // Never continue if returning from function.
1566 if (break_location_iterator->IsExit()) return false;
1567
1568 // Continue if we are still on the same frame and in the same statement.
1569 int current_statement_position =
1570 break_location_iterator->code()->SourceStatementPosition(frame->pc());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001571 return thread_local_.last_fp_ == frame->UnpaddedFP() &&
Steve Blocka7e24c12009-10-30 11:49:00 +00001572 thread_local_.last_statement_position_ == current_statement_position;
1573 }
1574
1575 // No step next action - don't continue.
1576 return false;
1577}
1578
1579
1580// Check whether the code object at the specified address is a debug break code
1581// object.
1582bool Debug::IsDebugBreak(Address addr) {
1583 Code* code = Code::GetCodeFromTargetAddress(addr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001584 return code->is_debug_stub() && code->extra_ic_state() == DEBUG_BREAK;
Steve Blocka7e24c12009-10-30 11:49:00 +00001585}
1586
1587
Steve Blocka7e24c12009-10-30 11:49:00 +00001588
1589
Steve Blocka7e24c12009-10-30 11:49:00 +00001590
1591// Simple function for returning the source positions for active break points.
1592Handle<Object> Debug::GetSourceBreakLocations(
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001593 Handle<SharedFunctionInfo> shared,
1594 BreakPositionAlignment position_alignment) {
1595 Isolate* isolate = shared->GetIsolate();
Steve Block44f0eee2011-05-26 01:26:41 +01001596 Heap* heap = isolate->heap();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001597 if (!HasDebugInfo(shared)) {
1598 return Handle<Object>(heap->undefined_value(), isolate);
1599 }
Steve Blocka7e24c12009-10-30 11:49:00 +00001600 Handle<DebugInfo> debug_info = GetDebugInfo(shared);
1601 if (debug_info->GetBreakPointCount() == 0) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001602 return Handle<Object>(heap->undefined_value(), isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00001603 }
1604 Handle<FixedArray> locations =
Steve Block44f0eee2011-05-26 01:26:41 +01001605 isolate->factory()->NewFixedArray(debug_info->GetBreakPointCount());
Steve Blocka7e24c12009-10-30 11:49:00 +00001606 int count = 0;
1607 for (int i = 0; i < debug_info->break_points()->length(); i++) {
1608 if (!debug_info->break_points()->get(i)->IsUndefined()) {
1609 BreakPointInfo* break_point_info =
1610 BreakPointInfo::cast(debug_info->break_points()->get(i));
1611 if (break_point_info->GetBreakPointCount() > 0) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001612 Smi* position = NULL;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001613 switch (position_alignment) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001614 case STATEMENT_ALIGNED:
1615 position = break_point_info->statement_position();
1616 break;
1617 case BREAK_POSITION_ALIGNED:
1618 position = break_point_info->source_position();
1619 break;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001620 }
1621
1622 locations->set(count++, position);
Steve Blocka7e24c12009-10-30 11:49:00 +00001623 }
1624 }
1625 }
1626 return locations;
1627}
1628
1629
Steve Blocka7e24c12009-10-30 11:49:00 +00001630// Handle stepping into a function.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001631void Debug::HandleStepIn(Handle<Object> function_obj, Handle<Object> holder,
1632 Address fp, bool is_constructor) {
1633 // Flood getter/setter if we either step in or step to another frame.
1634 bool step_frame = thread_local_.last_step_action_ == StepFrame;
1635 if (!StepInActive() && !step_frame) return;
1636 if (!function_obj->IsJSFunction()) return;
1637 Handle<JSFunction> function = Handle<JSFunction>::cast(function_obj);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001638 Isolate* isolate = function->GetIsolate();
Steve Blocka7e24c12009-10-30 11:49:00 +00001639 // If the frame pointer is not supplied by the caller find it.
1640 if (fp == 0) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001641 StackFrameIterator it(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00001642 it.Advance();
1643 // For constructor functions skip another frame.
1644 if (is_constructor) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001645 DCHECK(it.frame()->is_construct());
Steve Blocka7e24c12009-10-30 11:49:00 +00001646 it.Advance();
1647 }
1648 fp = it.frame()->fp();
1649 }
1650
1651 // Flood the function with one-shot break points if it is called from where
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001652 // step into was requested, or when stepping into a new frame.
1653 if (fp == thread_local_.step_into_fp_ || step_frame) {
1654 FloodWithOneShotGeneric(function, holder);
Steve Blocka7e24c12009-10-30 11:49:00 +00001655 }
1656}
1657
1658
1659void Debug::ClearStepping() {
1660 // Clear the various stepping setup.
1661 ClearOneShot();
1662 ClearStepIn();
1663 ClearStepOut();
1664 ClearStepNext();
1665
1666 // Clear multiple step counter.
1667 thread_local_.step_count_ = 0;
1668}
1669
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001670
Steve Blocka7e24c12009-10-30 11:49:00 +00001671// Clears all the one-shot break points that are currently set. Normally this
1672// function is called each time a break point is hit as one shot break points
1673// are used to support stepping.
1674void Debug::ClearOneShot() {
1675 // The current implementation just runs through all the breakpoints. When the
1676 // last break point for a function is removed that function is automatically
1677 // removed from the list.
1678
1679 DebugInfoListNode* node = debug_info_list_;
1680 while (node != NULL) {
1681 BreakLocationIterator it(node->debug_info(), ALL_BREAK_LOCATIONS);
1682 while (!it.Done()) {
1683 it.ClearOneShot();
1684 it.Next();
1685 }
1686 node = node->next();
1687 }
1688}
1689
1690
1691void Debug::ActivateStepIn(StackFrame* frame) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001692 DCHECK(!StepOutActive());
1693 thread_local_.step_into_fp_ = frame->UnpaddedFP();
Steve Blocka7e24c12009-10-30 11:49:00 +00001694}
1695
1696
1697void Debug::ClearStepIn() {
1698 thread_local_.step_into_fp_ = 0;
1699}
1700
1701
1702void Debug::ActivateStepOut(StackFrame* frame) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001703 DCHECK(!StepInActive());
1704 thread_local_.step_out_fp_ = frame->UnpaddedFP();
Steve Blocka7e24c12009-10-30 11:49:00 +00001705}
1706
1707
1708void Debug::ClearStepOut() {
1709 thread_local_.step_out_fp_ = 0;
1710}
1711
1712
1713void Debug::ClearStepNext() {
1714 thread_local_.last_step_action_ = StepNone;
1715 thread_local_.last_statement_position_ = RelocInfo::kNoPosition;
1716 thread_local_.last_fp_ = 0;
1717}
1718
1719
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001720static void CollectActiveFunctionsFromThread(
1721 Isolate* isolate,
1722 ThreadLocalTop* top,
1723 List<Handle<JSFunction> >* active_functions,
1724 Object* active_code_marker) {
1725 // Find all non-optimized code functions with activation frames
1726 // on the stack. This includes functions which have optimized
1727 // activations (including inlined functions) on the stack as the
1728 // non-optimized code is needed for the lazy deoptimization.
1729 for (JavaScriptFrameIterator it(isolate, top); !it.done(); it.Advance()) {
1730 JavaScriptFrame* frame = it.frame();
1731 if (frame->is_optimized()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001732 List<JSFunction*> functions(FLAG_max_inlining_levels + 1);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001733 frame->GetFunctions(&functions);
1734 for (int i = 0; i < functions.length(); i++) {
1735 JSFunction* function = functions[i];
1736 active_functions->Add(Handle<JSFunction>(function));
1737 function->shared()->code()->set_gc_metadata(active_code_marker);
1738 }
1739 } else if (frame->function()->IsJSFunction()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001740 JSFunction* function = frame->function();
1741 DCHECK(frame->LookupCode()->kind() == Code::FUNCTION);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001742 active_functions->Add(Handle<JSFunction>(function));
1743 function->shared()->code()->set_gc_metadata(active_code_marker);
1744 }
1745 }
1746}
1747
1748
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001749// Figure out how many bytes of "pc_offset" correspond to actual code by
1750// subtracting off the bytes that correspond to constant/veneer pools. See
1751// Assembler::CheckConstPool() and Assembler::CheckVeneerPool(). Note that this
1752// is only useful for architectures using constant pools or veneer pools.
1753static int ComputeCodeOffsetFromPcOffset(Code *code, int pc_offset) {
1754 DCHECK_EQ(code->kind(), Code::FUNCTION);
1755 DCHECK(!code->has_debug_break_slots());
1756 DCHECK_LE(0, pc_offset);
1757 DCHECK_LT(pc_offset, code->instruction_end() - code->instruction_start());
1758
1759 int mask = RelocInfo::ModeMask(RelocInfo::CONST_POOL) |
1760 RelocInfo::ModeMask(RelocInfo::VENEER_POOL);
1761 byte *pc = code->instruction_start() + pc_offset;
1762 int code_offset = pc_offset;
1763 for (RelocIterator it(code, mask); !it.done(); it.next()) {
1764 RelocInfo* info = it.rinfo();
1765 if (info->pc() >= pc) break;
1766 DCHECK(RelocInfo::IsConstPool(info->rmode()));
1767 code_offset -= static_cast<int>(info->data());
1768 DCHECK_LE(0, code_offset);
1769 }
1770
1771 return code_offset;
1772}
1773
1774
1775// The inverse of ComputeCodeOffsetFromPcOffset.
1776static int ComputePcOffsetFromCodeOffset(Code *code, int code_offset) {
1777 DCHECK_EQ(code->kind(), Code::FUNCTION);
1778
1779 int mask = RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT) |
1780 RelocInfo::ModeMask(RelocInfo::CONST_POOL) |
1781 RelocInfo::ModeMask(RelocInfo::VENEER_POOL);
1782 int reloc = 0;
1783 for (RelocIterator it(code, mask); !it.done(); it.next()) {
1784 RelocInfo* info = it.rinfo();
1785 if (info->pc() - code->instruction_start() - reloc >= code_offset) break;
1786 if (RelocInfo::IsDebugBreakSlot(info->rmode())) {
1787 reloc += Assembler::kDebugBreakSlotLength;
1788 } else {
1789 DCHECK(RelocInfo::IsConstPool(info->rmode()));
1790 reloc += static_cast<int>(info->data());
1791 }
1792 }
1793
1794 int pc_offset = code_offset + reloc;
1795
1796 DCHECK_LT(code->instruction_start() + pc_offset, code->instruction_end());
1797
1798 return pc_offset;
1799}
1800
1801
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001802static void RedirectActivationsToRecompiledCodeOnThread(
1803 Isolate* isolate,
1804 ThreadLocalTop* top) {
1805 for (JavaScriptFrameIterator it(isolate, top); !it.done(); it.Advance()) {
1806 JavaScriptFrame* frame = it.frame();
1807
1808 if (frame->is_optimized() || !frame->function()->IsJSFunction()) continue;
1809
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001810 JSFunction* function = frame->function();
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001811
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001812 DCHECK(frame->LookupCode()->kind() == Code::FUNCTION);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001813
1814 Handle<Code> frame_code(frame->LookupCode());
1815 if (frame_code->has_debug_break_slots()) continue;
1816
1817 Handle<Code> new_code(function->shared()->code());
1818 if (new_code->kind() != Code::FUNCTION ||
1819 !new_code->has_debug_break_slots()) {
1820 continue;
1821 }
1822
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001823 int old_pc_offset =
1824 static_cast<int>(frame->pc() - frame_code->instruction_start());
1825 int code_offset = ComputeCodeOffsetFromPcOffset(*frame_code, old_pc_offset);
1826 int new_pc_offset = ComputePcOffsetFromCodeOffset(*new_code, code_offset);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001827
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001828 // Compute the equivalent pc in the new code.
1829 byte* new_pc = new_code->instruction_start() + new_pc_offset;
1830
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001831 if (FLAG_trace_deopt) {
1832 PrintF("Replacing code %08" V8PRIxPTR " - %08" V8PRIxPTR " (%d) "
1833 "with %08" V8PRIxPTR " - %08" V8PRIxPTR " (%d) "
1834 "for debugging, "
1835 "changing pc from %08" V8PRIxPTR " to %08" V8PRIxPTR "\n",
1836 reinterpret_cast<intptr_t>(
1837 frame_code->instruction_start()),
1838 reinterpret_cast<intptr_t>(
1839 frame_code->instruction_start()) +
1840 frame_code->instruction_size(),
1841 frame_code->instruction_size(),
1842 reinterpret_cast<intptr_t>(new_code->instruction_start()),
1843 reinterpret_cast<intptr_t>(new_code->instruction_start()) +
1844 new_code->instruction_size(),
1845 new_code->instruction_size(),
1846 reinterpret_cast<intptr_t>(frame->pc()),
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001847 reinterpret_cast<intptr_t>(new_pc));
1848 }
1849
1850 if (FLAG_enable_ool_constant_pool) {
1851 // Update constant pool pointer for new code.
1852 frame->set_constant_pool(new_code->constant_pool());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001853 }
1854
1855 // Patch the return address to return into the code with
1856 // debug break slots.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001857 frame->set_pc(new_pc);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001858 }
1859}
1860
1861
1862class ActiveFunctionsCollector : public ThreadVisitor {
1863 public:
1864 explicit ActiveFunctionsCollector(List<Handle<JSFunction> >* active_functions,
1865 Object* active_code_marker)
1866 : active_functions_(active_functions),
1867 active_code_marker_(active_code_marker) { }
1868
1869 void VisitThread(Isolate* isolate, ThreadLocalTop* top) {
1870 CollectActiveFunctionsFromThread(isolate,
1871 top,
1872 active_functions_,
1873 active_code_marker_);
1874 }
1875
1876 private:
1877 List<Handle<JSFunction> >* active_functions_;
1878 Object* active_code_marker_;
1879};
1880
1881
1882class ActiveFunctionsRedirector : public ThreadVisitor {
1883 public:
1884 void VisitThread(Isolate* isolate, ThreadLocalTop* top) {
1885 RedirectActivationsToRecompiledCodeOnThread(isolate, top);
1886 }
1887};
1888
1889
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001890static void EnsureFunctionHasDebugBreakSlots(Handle<JSFunction> function) {
1891 if (function->code()->kind() == Code::FUNCTION &&
1892 function->code()->has_debug_break_slots()) {
1893 // Nothing to do. Function code already had debug break slots.
1894 return;
1895 }
1896 // Make sure that the shared full code is compiled with debug
1897 // break slots.
1898 if (!function->shared()->code()->has_debug_break_slots()) {
1899 MaybeHandle<Code> code = Compiler::GetDebugCode(function);
1900 // Recompilation can fail. In that case leave the code as it was.
1901 if (!code.is_null()) function->ReplaceCode(*code.ToHandleChecked());
1902 } else {
1903 // Simply use shared code if it has debug break slots.
1904 function->ReplaceCode(function->shared()->code());
1905 }
1906}
1907
1908
1909static void RecompileAndRelocateSuspendedGenerators(
1910 const List<Handle<JSGeneratorObject> > &generators) {
1911 for (int i = 0; i < generators.length(); i++) {
1912 Handle<JSFunction> fun(generators[i]->function());
1913
1914 EnsureFunctionHasDebugBreakSlots(fun);
1915
1916 int code_offset = generators[i]->continuation();
1917 int pc_offset = ComputePcOffsetFromCodeOffset(fun->code(), code_offset);
1918 generators[i]->set_continuation(pc_offset);
1919 }
1920}
1921
1922
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001923static bool SkipSharedFunctionInfo(SharedFunctionInfo* shared,
1924 Object* active_code_marker) {
1925 if (!shared->allows_lazy_compilation()) return true;
1926 if (!shared->script()->IsScript()) return true;
1927 Object* script = shared->script();
1928 if (!script->IsScript()) return true;
1929 if (Script::cast(script)->type()->value() == Script::TYPE_NATIVE) return true;
1930 Code* shared_code = shared->code();
1931 return shared_code->gc_metadata() == active_code_marker;
1932}
1933
1934
1935static inline bool HasDebugBreakSlots(Code* code) {
1936 return code->kind() == Code::FUNCTION && code->has_debug_break_slots();
1937}
1938
1939
Ben Murdoch589d6972011-11-30 16:04:58 +00001940void Debug::PrepareForBreakPoints() {
Ben Murdochb0fe1622011-05-05 13:52:32 +01001941 // If preparing for the first break point make sure to deoptimize all
1942 // functions as debugging does not work with optimized code.
1943 if (!has_break_points_) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001944 if (isolate_->concurrent_recompilation_enabled()) {
1945 isolate_->optimizing_compiler_thread()->Flush();
1946 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001947
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001948 Deoptimizer::DeoptimizeAll(isolate_);
1949
1950 Handle<Code> lazy_compile = isolate_->builtins()->CompileLazy();
1951
1952 // There will be at least one break point when we are done.
1953 has_break_points_ = true;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001954
1955 // Keep the list of activated functions in a handlified list as it
1956 // is used both in GC and non-GC code.
1957 List<Handle<JSFunction> > active_functions(100);
1958
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001959 // A list of all suspended generators.
1960 List<Handle<JSGeneratorObject> > suspended_generators;
1961
1962 // A list of all generator functions. We need to recompile all functions,
1963 // but we don't know until after visiting the whole heap which generator
1964 // functions have suspended activations and which do not. As in the case of
1965 // functions with activations on the stack, we need to be careful with
1966 // generator functions with suspended activations because although they
1967 // should be recompiled, recompilation can fail, and we need to avoid
1968 // leaving the heap in an inconsistent state.
1969 //
1970 // We could perhaps avoid this list and instead re-use the GC metadata
1971 // links.
1972 List<Handle<JSFunction> > generator_functions;
1973
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001974 {
1975 // We are going to iterate heap to find all functions without
1976 // debug break slots.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001977 Heap* heap = isolate_->heap();
1978 heap->CollectAllGarbage(Heap::kMakeHeapIterableMask,
1979 "preparing for breakpoints");
1980 HeapIterator iterator(heap);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001981
1982 // Ensure no GC in this scope as we are going to use gc_metadata
1983 // field in the Code object to mark active functions.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001984 DisallowHeapAllocation no_allocation;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001985
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001986 Object* active_code_marker = heap->the_hole_value();
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001987
1988 CollectActiveFunctionsFromThread(isolate_,
1989 isolate_->thread_local_top(),
1990 &active_functions,
1991 active_code_marker);
1992 ActiveFunctionsCollector active_functions_collector(&active_functions,
1993 active_code_marker);
1994 isolate_->thread_manager()->IterateArchivedThreads(
1995 &active_functions_collector);
1996
1997 // Scan the heap for all non-optimized functions which have no
1998 // debug break slots and are not active or inlined into an active
1999 // function and mark them for lazy compilation.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002000 HeapObject* obj = NULL;
2001 while (((obj = iterator.next()) != NULL)) {
2002 if (obj->IsJSFunction()) {
2003 JSFunction* function = JSFunction::cast(obj);
2004 SharedFunctionInfo* shared = function->shared();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002005 if (SkipSharedFunctionInfo(shared, active_code_marker)) continue;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002006 if (shared->is_generator()) {
2007 generator_functions.Add(Handle<JSFunction>(function, isolate_));
2008 continue;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002009 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002010 if (HasDebugBreakSlots(function->code())) continue;
2011 Code* fallback = HasDebugBreakSlots(shared->code()) ? shared->code()
2012 : *lazy_compile;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002013 Code::Kind kind = function->code()->kind();
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002014 if (kind == Code::FUNCTION ||
2015 (kind == Code::BUILTIN && // Abort in-flight compilation.
2016 (function->IsInOptimizationQueue() ||
2017 function->IsMarkedForOptimization() ||
2018 function->IsMarkedForConcurrentOptimization()))) {
2019 function->ReplaceCode(fallback);
2020 }
2021 if (kind == Code::OPTIMIZED_FUNCTION) {
2022 // Optimized code can only get here if DeoptimizeAll did not
2023 // deoptimize turbo fan code.
2024 DCHECK(!FLAG_turbo_deoptimization);
2025 DCHECK(function->code()->is_turbofanned());
2026 function->ReplaceCode(fallback);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002027 }
2028 } else if (obj->IsJSGeneratorObject()) {
2029 JSGeneratorObject* gen = JSGeneratorObject::cast(obj);
2030 if (!gen->is_suspended()) continue;
2031
2032 JSFunction* fun = gen->function();
2033 DCHECK_EQ(fun->code()->kind(), Code::FUNCTION);
2034 if (fun->code()->has_debug_break_slots()) continue;
2035
2036 int pc_offset = gen->continuation();
2037 DCHECK_LT(0, pc_offset);
2038
2039 int code_offset =
2040 ComputeCodeOffsetFromPcOffset(fun->code(), pc_offset);
2041
2042 // This will be fixed after we recompile the functions.
2043 gen->set_continuation(code_offset);
2044
2045 suspended_generators.Add(Handle<JSGeneratorObject>(gen, isolate_));
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002046 } else if (obj->IsSharedFunctionInfo()) {
2047 SharedFunctionInfo* shared = SharedFunctionInfo::cast(obj);
2048 if (SkipSharedFunctionInfo(shared, active_code_marker)) continue;
2049 if (shared->is_generator()) continue;
2050 if (HasDebugBreakSlots(shared->code())) continue;
2051 shared->ReplaceCode(*lazy_compile);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002052 }
2053 }
2054
2055 // Clear gc_metadata field.
2056 for (int i = 0; i < active_functions.length(); i++) {
2057 Handle<JSFunction> function = active_functions[i];
2058 function->shared()->code()->set_gc_metadata(Smi::FromInt(0));
2059 }
2060 }
2061
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002062 // Recompile generator functions that have suspended activations, and
2063 // relocate those activations.
2064 RecompileAndRelocateSuspendedGenerators(suspended_generators);
2065
2066 // Mark generator functions that didn't have suspended activations for lazy
2067 // recompilation. Note that this set does not include any active functions.
2068 for (int i = 0; i < generator_functions.length(); i++) {
2069 Handle<JSFunction> &function = generator_functions[i];
2070 if (function->code()->kind() != Code::FUNCTION) continue;
2071 if (function->code()->has_debug_break_slots()) continue;
2072 function->ReplaceCode(*lazy_compile);
2073 function->shared()->ReplaceCode(*lazy_compile);
2074 }
2075
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002076 // Now recompile all functions with activation frames and and
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002077 // patch the return address to run in the new compiled code. It could be
2078 // that some active functions were recompiled already by the suspended
2079 // generator recompilation pass above; a generator with suspended
2080 // activations could also have active activations. That's fine.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002081 for (int i = 0; i < active_functions.length(); i++) {
2082 Handle<JSFunction> function = active_functions[i];
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002083 Handle<SharedFunctionInfo> shared(function->shared());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002084
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002085 // If recompilation is not possible just skip it.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002086 if (shared->is_toplevel()) continue;
2087 if (!shared->allows_lazy_compilation()) continue;
2088 if (shared->code()->kind() == Code::BUILTIN) continue;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002089
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002090 EnsureFunctionHasDebugBreakSlots(function);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002091 }
2092
2093 RedirectActivationsToRecompiledCodeOnThread(isolate_,
2094 isolate_->thread_local_top());
2095
2096 ActiveFunctionsRedirector active_functions_redirector;
2097 isolate_->thread_manager()->IterateArchivedThreads(
2098 &active_functions_redirector);
Ben Murdochb0fe1622011-05-05 13:52:32 +01002099 }
Ben Murdoch589d6972011-11-30 16:04:58 +00002100}
2101
2102
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002103Object* Debug::FindSharedFunctionInfoInScript(Handle<Script> script,
2104 int position) {
2105 // Iterate the heap looking for SharedFunctionInfo generated from the
2106 // script. The inner most SharedFunctionInfo containing the source position
2107 // for the requested break point is found.
2108 // NOTE: This might require several heap iterations. If the SharedFunctionInfo
2109 // which is found is not compiled it is compiled and the heap is iterated
2110 // again as the compilation might create inner functions from the newly
2111 // compiled function and the actual requested break point might be in one of
2112 // these functions.
2113 // NOTE: The below fix-point iteration depends on all functions that cannot be
2114 // compiled lazily without a context to not be compiled at all. Compilation
2115 // will be triggered at points where we do not need a context.
2116 bool done = false;
2117 // The current candidate for the source position:
2118 int target_start_position = RelocInfo::kNoPosition;
2119 Handle<JSFunction> target_function;
2120 Handle<SharedFunctionInfo> target;
2121 Heap* heap = isolate_->heap();
2122 while (!done) {
2123 { // Extra scope for iterator.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002124 // If lazy compilation is off, we won't have duplicate shared function
2125 // infos that need to be filtered.
2126 HeapIterator iterator(heap, FLAG_lazy ? HeapIterator::kNoFiltering
2127 : HeapIterator::kFilterUnreachable);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002128 for (HeapObject* obj = iterator.next();
2129 obj != NULL; obj = iterator.next()) {
2130 bool found_next_candidate = false;
2131 Handle<JSFunction> function;
2132 Handle<SharedFunctionInfo> shared;
2133 if (obj->IsJSFunction()) {
2134 function = Handle<JSFunction>(JSFunction::cast(obj));
2135 shared = Handle<SharedFunctionInfo>(function->shared());
2136 DCHECK(shared->allows_lazy_compilation() || shared->is_compiled());
2137 found_next_candidate = true;
2138 } else if (obj->IsSharedFunctionInfo()) {
2139 shared = Handle<SharedFunctionInfo>(SharedFunctionInfo::cast(obj));
2140 // Skip functions that we cannot compile lazily without a context,
2141 // which is not available here, because there is no closure.
2142 found_next_candidate = shared->is_compiled() ||
2143 shared->allows_lazy_compilation_without_context();
2144 }
2145 if (!found_next_candidate) continue;
2146 if (shared->script() == *script) {
2147 // If the SharedFunctionInfo found has the requested script data and
2148 // contains the source position it is a candidate.
2149 int start_position = shared->function_token_position();
2150 if (start_position == RelocInfo::kNoPosition) {
2151 start_position = shared->start_position();
2152 }
2153 if (start_position <= position &&
2154 position <= shared->end_position()) {
2155 // If there is no candidate or this function is within the current
2156 // candidate this is the new candidate.
2157 if (target.is_null()) {
2158 target_start_position = start_position;
2159 target_function = function;
2160 target = shared;
2161 } else {
2162 if (target_start_position == start_position &&
2163 shared->end_position() == target->end_position()) {
2164 // If a top-level function contains only one function
2165 // declaration the source for the top-level and the function
2166 // is the same. In that case prefer the non top-level function.
2167 if (!shared->is_toplevel()) {
2168 target_start_position = start_position;
2169 target_function = function;
2170 target = shared;
2171 }
2172 } else if (target_start_position <= start_position &&
2173 shared->end_position() <= target->end_position()) {
2174 // This containment check includes equality as a function
2175 // inside a top-level function can share either start or end
2176 // position with the top-level function.
2177 target_start_position = start_position;
2178 target_function = function;
2179 target = shared;
2180 }
2181 }
2182 }
2183 }
2184 } // End for loop.
2185 } // End no-allocation scope.
2186
2187 if (target.is_null()) return heap->undefined_value();
2188
2189 // There will be at least one break point when we are done.
2190 has_break_points_ = true;
2191
2192 // If the candidate found is compiled we are done.
2193 done = target->is_compiled();
2194 if (!done) {
2195 // If the candidate is not compiled, compile it to reveal any inner
2196 // functions which might contain the requested source position. This
2197 // will compile all inner functions that cannot be compiled without a
2198 // context, because Compiler::BuildFunctionInfo checks whether the
2199 // debugger is active.
2200 MaybeHandle<Code> maybe_result = target_function.is_null()
2201 ? Compiler::GetUnoptimizedCode(target)
2202 : Compiler::GetUnoptimizedCode(target_function);
2203 if (maybe_result.is_null()) return isolate_->heap()->undefined_value();
2204 }
2205 } // End while loop.
2206
2207 return *target;
2208}
2209
2210
Ben Murdoch589d6972011-11-30 16:04:58 +00002211// Ensures the debug information is present for shared.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002212bool Debug::EnsureDebugInfo(Handle<SharedFunctionInfo> shared,
2213 Handle<JSFunction> function) {
2214 Isolate* isolate = shared->GetIsolate();
2215
Ben Murdoch589d6972011-11-30 16:04:58 +00002216 // Return if we already have the debug info for shared.
2217 if (HasDebugInfo(shared)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002218 DCHECK(shared->is_compiled());
Ben Murdoch589d6972011-11-30 16:04:58 +00002219 return true;
2220 }
2221
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002222 // There will be at least one break point when we are done.
2223 has_break_points_ = true;
2224
2225 // Ensure function is compiled. Return false if this failed.
2226 if (!function.is_null() &&
2227 !Compiler::EnsureCompiled(function, CLEAR_EXCEPTION)) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002228 return false;
2229 }
Ben Murdochb0fe1622011-05-05 13:52:32 +01002230
Steve Blocka7e24c12009-10-30 11:49:00 +00002231 // Create the debug info object.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002232 Handle<DebugInfo> debug_info = isolate->factory()->NewDebugInfo(shared);
Steve Blocka7e24c12009-10-30 11:49:00 +00002233
2234 // Add debug info to the list.
2235 DebugInfoListNode* node = new DebugInfoListNode(*debug_info);
2236 node->set_next(debug_info_list_);
2237 debug_info_list_ = node;
2238
Steve Blocka7e24c12009-10-30 11:49:00 +00002239 return true;
2240}
2241
2242
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002243void Debug::RemoveDebugInfo(DebugInfoListNode* prev, DebugInfoListNode* node) {
2244 // Unlink from list. If prev is NULL we are looking at the first element.
2245 if (prev == NULL) {
2246 debug_info_list_ = node->next();
2247 } else {
2248 prev->set_next(node->next());
2249 }
2250 delete node;
2251
2252 // If there are no more debug info objects there are not more break
2253 // points.
2254 has_break_points_ = debug_info_list_ != NULL;
2255}
2256
2257
2258void Debug::RemoveDebugInfo(DebugInfo** debug_info) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002259 DCHECK(debug_info_list_ != NULL);
Steve Blocka7e24c12009-10-30 11:49:00 +00002260 // Run through the debug info objects to find this one and remove it.
2261 DebugInfoListNode* prev = NULL;
2262 DebugInfoListNode* current = debug_info_list_;
2263 while (current != NULL) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002264 if (current->debug_info().location() == debug_info) {
2265 RemoveDebugInfo(prev, current);
Steve Blocka7e24c12009-10-30 11:49:00 +00002266 return;
2267 }
2268 // Move to next in list.
2269 prev = current;
2270 current = current->next();
2271 }
2272 UNREACHABLE();
2273}
2274
2275
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002276void Debug::RemoveDebugInfo(DebugInfoListNode* node) {
2277 DCHECK(debug_info_list_ != NULL);
2278 // Run through the debug info objects to find this one and remove it.
2279 DebugInfoListNode* prev = NULL;
2280 DebugInfoListNode* current = debug_info_list_;
2281 while (current != NULL) {
2282 if (current == node) {
2283 RemoveDebugInfo(prev, node);
2284 return;
2285 }
2286 // Move to next in list.
2287 prev = current;
2288 current = current->next();
2289 }
2290 UNREACHABLE();
2291}
2292
2293
2294void Debug::RemoveDebugInfoAndClearFromShared(Handle<DebugInfo> debug_info) {
2295 HandleScope scope(isolate_);
2296 Handle<SharedFunctionInfo> shared(debug_info->shared());
2297
2298 RemoveDebugInfo(debug_info.location());
2299
2300 shared->set_debug_info(isolate_->heap()->undefined_value());
2301}
2302
2303
Steve Blocka7e24c12009-10-30 11:49:00 +00002304void Debug::SetAfterBreakTarget(JavaScriptFrame* frame) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002305 after_break_target_ = NULL;
Steve Blocka7e24c12009-10-30 11:49:00 +00002306
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002307 if (LiveEdit::SetAfterBreakTarget(this)) return; // LiveEdit did the job.
2308
2309 HandleScope scope(isolate_);
Ben Murdoch589d6972011-11-30 16:04:58 +00002310 PrepareForBreakPoints();
2311
Steve Blocka7e24c12009-10-30 11:49:00 +00002312 // Get the executing function in which the debug break occurred.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002313 Handle<JSFunction> function(JSFunction::cast(frame->function()));
2314 Handle<SharedFunctionInfo> shared(function->shared());
2315 if (!EnsureDebugInfo(shared, function)) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002316 // Return if we failed to retrieve the debug info.
2317 return;
2318 }
2319 Handle<DebugInfo> debug_info = GetDebugInfo(shared);
2320 Handle<Code> code(debug_info->code());
2321 Handle<Code> original_code(debug_info->original_code());
2322#ifdef DEBUG
2323 // Get the code which is actually executing.
Ben Murdoch8b112d22011-06-08 16:22:53 +01002324 Handle<Code> frame_code(frame->LookupCode());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002325 DCHECK(frame_code.is_identical_to(code));
Steve Blocka7e24c12009-10-30 11:49:00 +00002326#endif
2327
2328 // Find the call address in the running code. This address holds the call to
2329 // either a DebugBreakXXX or to the debug break return entry code if the
2330 // break point is still active after processing the break point.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002331 Address addr = Assembler::break_address_from_return_address(frame->pc());
Steve Blocka7e24c12009-10-30 11:49:00 +00002332
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002333 // Check if the location is at JS exit or debug break slot.
Steve Blocka7e24c12009-10-30 11:49:00 +00002334 bool at_js_return = false;
2335 bool break_at_js_return_active = false;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002336 bool at_debug_break_slot = false;
Steve Blocka7e24c12009-10-30 11:49:00 +00002337 RelocIterator it(debug_info->code());
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002338 while (!it.done() && !at_js_return && !at_debug_break_slot) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002339 if (RelocInfo::IsJSReturn(it.rinfo()->rmode())) {
2340 at_js_return = (it.rinfo()->pc() ==
2341 addr - Assembler::kPatchReturnSequenceAddressOffset);
Steve Block3ce2e202009-11-05 08:53:23 +00002342 break_at_js_return_active = it.rinfo()->IsPatchedReturnSequence();
Steve Blocka7e24c12009-10-30 11:49:00 +00002343 }
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002344 if (RelocInfo::IsDebugBreakSlot(it.rinfo()->rmode())) {
2345 at_debug_break_slot = (it.rinfo()->pc() ==
2346 addr - Assembler::kPatchDebugBreakSlotAddressOffset);
2347 }
Steve Blocka7e24c12009-10-30 11:49:00 +00002348 it.next();
2349 }
2350
2351 // Handle the jump to continue execution after break point depending on the
2352 // break location.
2353 if (at_js_return) {
2354 // If the break point as return is still active jump to the corresponding
2355 // place in the original code. If not the break point was removed during
2356 // break point processing.
2357 if (break_at_js_return_active) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002358 addr += original_code->instruction_start() - code->instruction_start();
Steve Blocka7e24c12009-10-30 11:49:00 +00002359 }
2360
2361 // Move back to where the call instruction sequence started.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002362 after_break_target_ = addr - Assembler::kPatchReturnSequenceAddressOffset;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002363 } else if (at_debug_break_slot) {
2364 // Address of where the debug break slot starts.
2365 addr = addr - Assembler::kPatchDebugBreakSlotAddressOffset;
Steve Blocka7e24c12009-10-30 11:49:00 +00002366
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002367 // Continue just after the slot.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002368 after_break_target_ = addr + Assembler::kDebugBreakSlotLength;
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002369 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002370 addr = Assembler::target_address_from_return_address(frame->pc());
2371 if (IsDebugBreak(Assembler::target_address_at(addr, *code))) {
2372 // We now know that there is still a debug break call at the target
2373 // address, so the break point is still there and the original code will
2374 // hold the address to jump to in order to complete the call which is
2375 // replaced by a call to DebugBreakXXX.
2376
2377 // Find the corresponding address in the original code.
2378 addr += original_code->instruction_start() - code->instruction_start();
2379
2380 // Install jump to the call address in the original code. This will be the
2381 // call which was overwritten by the call to DebugBreakXXX.
2382 after_break_target_ = Assembler::target_address_at(addr, *original_code);
2383 } else {
2384 // There is no longer a break point present. Don't try to look in the
2385 // original code as the running code will have the right address. This
2386 // takes care of the case where the last break point is removed from the
2387 // function and therefore no "original code" is available.
2388 after_break_target_ = Assembler::target_address_at(addr, *code);
2389 }
Steve Blocka7e24c12009-10-30 11:49:00 +00002390 }
2391}
2392
2393
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002394bool Debug::IsBreakAtReturn(JavaScriptFrame* frame) {
Steve Block44f0eee2011-05-26 01:26:41 +01002395 HandleScope scope(isolate_);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002396
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002397 // If there are no break points this cannot be break at return, as
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002398 // the debugger statement and stack guard debug break cannot be at
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002399 // return.
2400 if (!has_break_points_) {
2401 return false;
2402 }
2403
Ben Murdoch589d6972011-11-30 16:04:58 +00002404 PrepareForBreakPoints();
2405
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002406 // Get the executing function in which the debug break occurred.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002407 Handle<JSFunction> function(JSFunction::cast(frame->function()));
2408 Handle<SharedFunctionInfo> shared(function->shared());
2409 if (!EnsureDebugInfo(shared, function)) {
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002410 // Return if we failed to retrieve the debug info.
2411 return false;
2412 }
2413 Handle<DebugInfo> debug_info = GetDebugInfo(shared);
2414 Handle<Code> code(debug_info->code());
2415#ifdef DEBUG
2416 // Get the code which is actually executing.
Ben Murdoch8b112d22011-06-08 16:22:53 +01002417 Handle<Code> frame_code(frame->LookupCode());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002418 DCHECK(frame_code.is_identical_to(code));
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002419#endif
2420
2421 // Find the call address in the running code.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002422 Address addr = Assembler::break_address_from_return_address(frame->pc());
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01002423
2424 // Check if the location is at JS return.
2425 RelocIterator it(debug_info->code());
2426 while (!it.done()) {
2427 if (RelocInfo::IsJSReturn(it.rinfo()->rmode())) {
2428 return (it.rinfo()->pc() ==
2429 addr - Assembler::kPatchReturnSequenceAddressOffset);
2430 }
2431 it.next();
2432 }
2433 return false;
2434}
2435
2436
Steve Block8defd9f2010-07-08 12:39:36 +01002437void Debug::FramesHaveBeenDropped(StackFrame::Id new_break_frame_id,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002438 LiveEdit::FrameDropMode mode,
Ben Murdochbb769b22010-08-11 14:56:33 +01002439 Object** restarter_frame_function_pointer) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002440 if (mode != LiveEdit::CURRENTLY_SET_MODE) {
2441 thread_local_.frame_drop_mode_ = mode;
2442 }
Steve Block6ded16b2010-05-10 14:33:55 +01002443 thread_local_.break_frame_id_ = new_break_frame_id;
Ben Murdochbb769b22010-08-11 14:56:33 +01002444 thread_local_.restarter_frame_function_pointer_ =
2445 restarter_frame_function_pointer;
Steve Block6ded16b2010-05-10 14:33:55 +01002446}
2447
2448
Steve Blocka7e24c12009-10-30 11:49:00 +00002449bool Debug::IsDebugGlobal(GlobalObject* global) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002450 return is_loaded() && global == debug_context()->global_object();
Steve Blocka7e24c12009-10-30 11:49:00 +00002451}
2452
2453
2454void Debug::ClearMirrorCache() {
Steve Block44f0eee2011-05-26 01:26:41 +01002455 PostponeInterruptsScope postpone(isolate_);
2456 HandleScope scope(isolate_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002457 AssertDebugContext();
2458 Factory* factory = isolate_->factory();
2459 Handle<GlobalObject> global(isolate_->global_object());
2460 JSObject::SetProperty(global,
2461 factory->NewStringFromAsciiChecked("next_handle_"),
2462 handle(Smi::FromInt(0), isolate_), SLOPPY).Check();
2463 JSObject::SetProperty(global,
2464 factory->NewStringFromAsciiChecked("mirror_cache_"),
2465 factory->NewJSArray(0, FAST_ELEMENTS), SLOPPY).Check();
Steve Blocka7e24c12009-10-30 11:49:00 +00002466}
2467
2468
2469Handle<FixedArray> Debug::GetLoadedScripts() {
2470 // Create and fill the script cache when the loaded scripts is requested for
2471 // the first time.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002472 if (script_cache_ == NULL) script_cache_ = new ScriptCache(isolate_);
Steve Blocka7e24c12009-10-30 11:49:00 +00002473
2474 // Perform GC to get unreferenced scripts evicted from the cache before
2475 // returning the content.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002476 isolate_->heap()->CollectAllGarbage(Heap::kNoGCFlags,
2477 "Debug::GetLoadedScripts");
Steve Blocka7e24c12009-10-30 11:49:00 +00002478
2479 // Get the scripts from the cache.
2480 return script_cache_->GetScripts();
2481}
2482
2483
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002484void Debug::RecordEvalCaller(Handle<Script> script) {
2485 script->set_compilation_type(Script::COMPILATION_TYPE_EVAL);
2486 // For eval scripts add information on the function from which eval was
2487 // called.
2488 StackTraceFrameIterator it(script->GetIsolate());
2489 if (!it.done()) {
2490 script->set_eval_from_shared(it.frame()->function()->shared());
2491 Code* code = it.frame()->LookupCode();
2492 int offset = static_cast<int>(
2493 it.frame()->pc() - code->instruction_start());
2494 script->set_eval_from_instructions_offset(Smi::FromInt(offset));
Steve Blocka7e24c12009-10-30 11:49:00 +00002495 }
2496}
2497
2498
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002499MaybeHandle<Object> Debug::MakeJSObject(const char* constructor_name,
2500 int argc,
2501 Handle<Object> argv[]) {
2502 AssertDebugContext();
Steve Blocka7e24c12009-10-30 11:49:00 +00002503 // Create the execution state object.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002504 Handle<GlobalObject> global(isolate_->global_object());
2505 Handle<Object> constructor = Object::GetProperty(
2506 isolate_, global, constructor_name).ToHandleChecked();
2507 DCHECK(constructor->IsJSFunction());
2508 if (!constructor->IsJSFunction()) return MaybeHandle<Object>();
2509 // We do not handle interrupts here. In particular, termination interrupts.
2510 PostponeInterruptsScope no_interrupts(isolate_);
2511 return Execution::TryCall(Handle<JSFunction>::cast(constructor),
2512 handle(debug_context()->global_proxy()),
2513 argc,
2514 argv);
Steve Blocka7e24c12009-10-30 11:49:00 +00002515}
2516
2517
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002518MaybeHandle<Object> Debug::MakeExecutionState() {
Steve Blocka7e24c12009-10-30 11:49:00 +00002519 // Create the execution state object.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002520 Handle<Object> argv[] = { isolate_->factory()->NewNumberFromInt(break_id()) };
2521 return MakeJSObject("MakeExecutionState", arraysize(argv), argv);
Steve Blocka7e24c12009-10-30 11:49:00 +00002522}
2523
2524
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002525MaybeHandle<Object> Debug::MakeBreakEvent(Handle<Object> break_points_hit) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002526 // Create the new break event object.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002527 Handle<Object> argv[] = { isolate_->factory()->NewNumberFromInt(break_id()),
2528 break_points_hit };
2529 return MakeJSObject("MakeBreakEvent", arraysize(argv), argv);
Steve Blocka7e24c12009-10-30 11:49:00 +00002530}
2531
2532
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002533MaybeHandle<Object> Debug::MakeExceptionEvent(Handle<Object> exception,
2534 bool uncaught,
2535 Handle<Object> promise) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002536 // Create the new exception event object.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002537 Handle<Object> argv[] = { isolate_->factory()->NewNumberFromInt(break_id()),
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002538 exception,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002539 isolate_->factory()->ToBoolean(uncaught),
2540 promise };
2541 return MakeJSObject("MakeExceptionEvent", arraysize(argv), argv);
Steve Blocka7e24c12009-10-30 11:49:00 +00002542}
2543
2544
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002545MaybeHandle<Object> Debug::MakeCompileEvent(Handle<Script> script,
2546 v8::DebugEvent type) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002547 // Create the compile event object.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002548 Handle<Object> script_wrapper = Script::GetWrapper(script);
2549 Handle<Object> argv[] = { script_wrapper,
2550 isolate_->factory()->NewNumberFromInt(type) };
2551 return MakeJSObject("MakeCompileEvent", arraysize(argv), argv);
Steve Blocka7e24c12009-10-30 11:49:00 +00002552}
2553
2554
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002555MaybeHandle<Object> Debug::MakePromiseEvent(Handle<JSObject> event_data) {
2556 // Create the promise event object.
2557 Handle<Object> argv[] = { event_data };
2558 return MakeJSObject("MakePromiseEvent", arraysize(argv), argv);
Steve Blocka7e24c12009-10-30 11:49:00 +00002559}
2560
2561
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002562MaybeHandle<Object> Debug::MakeAsyncTaskEvent(Handle<JSObject> task_event) {
2563 // Create the async task event object.
2564 Handle<Object> argv[] = { task_event };
2565 return MakeJSObject("MakeAsyncTaskEvent", arraysize(argv), argv);
2566}
2567
2568
2569void Debug::OnThrow(Handle<Object> exception, bool uncaught) {
2570 if (in_debug_scope() || ignore_events()) return;
2571 // Temporarily clear any scheduled_exception to allow evaluating
2572 // JavaScript from the debug event handler.
Steve Block44f0eee2011-05-26 01:26:41 +01002573 HandleScope scope(isolate_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002574 Handle<Object> scheduled_exception;
2575 if (isolate_->has_scheduled_exception()) {
2576 scheduled_exception = handle(isolate_->scheduled_exception(), isolate_);
2577 isolate_->clear_scheduled_exception();
2578 }
2579 OnException(exception, uncaught, isolate_->GetPromiseOnStackOnThrow());
2580 if (!scheduled_exception.is_null()) {
2581 isolate_->thread_local_top()->scheduled_exception_ = *scheduled_exception;
2582 }
2583}
Steve Blocka7e24c12009-10-30 11:49:00 +00002584
Steve Blocka7e24c12009-10-30 11:49:00 +00002585
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002586void Debug::OnPromiseReject(Handle<JSObject> promise, Handle<Object> value) {
2587 if (in_debug_scope() || ignore_events()) return;
2588 HandleScope scope(isolate_);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002589 // Check whether the promise has been marked as having triggered a message.
2590 Handle<Symbol> key = isolate_->factory()->promise_debug_marker_symbol();
2591 if (JSObject::GetDataProperty(promise, key)->IsUndefined()) {
2592 OnException(value, false, promise);
2593 }
2594}
2595
2596
2597MaybeHandle<Object> Debug::PromiseHasUserDefinedRejectHandler(
2598 Handle<JSObject> promise) {
2599 Handle<JSFunction> fun = Handle<JSFunction>::cast(
2600 JSObject::GetDataProperty(isolate_->js_builtins_object(),
2601 isolate_->factory()->NewStringFromStaticChars(
2602 "PromiseHasUserDefinedRejectHandler")));
2603 return Execution::Call(isolate_, fun, promise, 0, NULL);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002604}
2605
2606
2607void Debug::OnException(Handle<Object> exception, bool uncaught,
2608 Handle<Object> promise) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002609 if (!uncaught && promise->IsJSObject()) {
2610 Handle<JSObject> jspromise = Handle<JSObject>::cast(promise);
2611 // Mark the promise as already having triggered a message.
2612 Handle<Symbol> key = isolate_->factory()->promise_debug_marker_symbol();
2613 JSObject::SetProperty(jspromise, key, key, STRICT).Assert();
2614 // Check whether the promise reject is considered an uncaught exception.
2615 Handle<Object> has_reject_handler;
2616 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
2617 isolate_, has_reject_handler,
2618 PromiseHasUserDefinedRejectHandler(jspromise), /* void */);
2619 uncaught = has_reject_handler->IsFalse();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002620 }
Steve Blocka7e24c12009-10-30 11:49:00 +00002621 // Bail out if exception breaks are not active
2622 if (uncaught) {
2623 // Uncaught exceptions are reported by either flags.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002624 if (!(break_on_uncaught_exception_ || break_on_exception_)) return;
Steve Blocka7e24c12009-10-30 11:49:00 +00002625 } else {
2626 // Caught exceptions are reported is activated.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002627 if (!break_on_exception_) return;
Steve Blocka7e24c12009-10-30 11:49:00 +00002628 }
2629
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002630 DebugScope debug_scope(this);
2631 if (debug_scope.failed()) return;
Steve Blocka7e24c12009-10-30 11:49:00 +00002632
2633 // Clear all current stepping setup.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002634 ClearStepping();
2635
Steve Blocka7e24c12009-10-30 11:49:00 +00002636 // Create the event data object.
Steve Blocka7e24c12009-10-30 11:49:00 +00002637 Handle<Object> event_data;
Steve Blocka7e24c12009-10-30 11:49:00 +00002638 // Bail out and don't call debugger if exception.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002639 if (!MakeExceptionEvent(
2640 exception, uncaught, promise).ToHandle(&event_data)) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002641 return;
2642 }
2643
2644 // Process debug event.
2645 ProcessDebugEvent(v8::Exception, Handle<JSObject>::cast(event_data), false);
2646 // Return to continue execution from where the exception was thrown.
2647}
2648
2649
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002650void Debug::OnCompileError(Handle<Script> script) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002651 if (ignore_events()) return;
2652
2653 if (in_debug_scope()) {
2654 ProcessCompileEventInDebugScope(v8::CompileError, script);
2655 return;
2656 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002657
Steve Block44f0eee2011-05-26 01:26:41 +01002658 HandleScope scope(isolate_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002659 DebugScope debug_scope(this);
2660 if (debug_scope.failed()) return;
Steve Blocka7e24c12009-10-30 11:49:00 +00002661
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002662 // Create the compile state object.
Steve Blocka7e24c12009-10-30 11:49:00 +00002663 Handle<Object> event_data;
Steve Blocka7e24c12009-10-30 11:49:00 +00002664 // Bail out and don't call debugger if exception.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002665 if (!MakeCompileEvent(script, v8::CompileError).ToHandle(&event_data)) return;
2666
2667 // Process debug event.
2668 ProcessDebugEvent(v8::CompileError, Handle<JSObject>::cast(event_data), true);
2669}
2670
2671
2672void Debug::OnDebugBreak(Handle<Object> break_points_hit,
2673 bool auto_continue) {
2674 // The caller provided for DebugScope.
2675 AssertDebugContext();
2676 // Bail out if there is no listener for this event
2677 if (ignore_events()) return;
2678
2679 HandleScope scope(isolate_);
2680 // Create the event data object.
2681 Handle<Object> event_data;
2682 // Bail out and don't call debugger if exception.
2683 if (!MakeBreakEvent(break_points_hit).ToHandle(&event_data)) return;
Steve Blocka7e24c12009-10-30 11:49:00 +00002684
2685 // Process debug event.
2686 ProcessDebugEvent(v8::Break,
2687 Handle<JSObject>::cast(event_data),
2688 auto_continue);
2689}
2690
2691
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002692void Debug::OnBeforeCompile(Handle<Script> script) {
2693 if (in_debug_scope() || ignore_events()) return;
2694
Steve Block44f0eee2011-05-26 01:26:41 +01002695 HandleScope scope(isolate_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002696 DebugScope debug_scope(this);
2697 if (debug_scope.failed()) return;
Steve Blocka7e24c12009-10-30 11:49:00 +00002698
2699 // Create the event data object.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002700 Handle<Object> event_data;
Steve Blocka7e24c12009-10-30 11:49:00 +00002701 // Bail out and don't call debugger if exception.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002702 if (!MakeCompileEvent(script, v8::BeforeCompile).ToHandle(&event_data))
Steve Blocka7e24c12009-10-30 11:49:00 +00002703 return;
Steve Blocka7e24c12009-10-30 11:49:00 +00002704
2705 // Process debug event.
2706 ProcessDebugEvent(v8::BeforeCompile,
2707 Handle<JSObject>::cast(event_data),
2708 true);
2709}
2710
2711
2712// Handle debugger actions when a new script is compiled.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002713void Debug::OnAfterCompile(Handle<Script> script) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002714 // Add the newly compiled script to the script cache.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002715 if (script_cache_ != NULL) script_cache_->Add(script);
Steve Blocka7e24c12009-10-30 11:49:00 +00002716
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002717 if (ignore_events()) return;
2718
2719 if (in_debug_scope()) {
2720 ProcessCompileEventInDebugScope(v8::AfterCompile, script);
2721 return;
2722 }
Steve Blocka7e24c12009-10-30 11:49:00 +00002723
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002724 HandleScope scope(isolate_);
2725 DebugScope debug_scope(this);
2726 if (debug_scope.failed()) return;
Steve Blocka7e24c12009-10-30 11:49:00 +00002727
2728 // If debugging there might be script break points registered for this
2729 // script. Make sure that these break points are set.
2730
Andrei Popescu31002712010-02-23 13:46:05 +00002731 // Get the function UpdateScriptBreakPoints (defined in debug-debugger.js).
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002732 Handle<String> update_script_break_points_string =
2733 isolate_->factory()->InternalizeOneByteString(
2734 STATIC_CHAR_VECTOR("UpdateScriptBreakPoints"));
2735 Handle<GlobalObject> debug_global(debug_context()->global_object());
Steve Blocka7e24c12009-10-30 11:49:00 +00002736 Handle<Object> update_script_break_points =
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002737 Object::GetProperty(
2738 debug_global, update_script_break_points_string).ToHandleChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00002739 if (!update_script_break_points->IsJSFunction()) {
2740 return;
2741 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002742 DCHECK(update_script_break_points->IsJSFunction());
Steve Blocka7e24c12009-10-30 11:49:00 +00002743
2744 // Wrap the script object in a proper JS object before passing it
2745 // to JavaScript.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002746 Handle<Object> wrapper = Script::GetWrapper(script);
Steve Blocka7e24c12009-10-30 11:49:00 +00002747
2748 // Call UpdateScriptBreakPoints expect no exceptions.
Ben Murdoch3ef787d2012-04-12 10:51:47 +01002749 Handle<Object> argv[] = { wrapper };
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002750 if (Execution::TryCall(Handle<JSFunction>::cast(update_script_break_points),
2751 isolate_->js_builtins_object(),
2752 arraysize(argv),
2753 argv).is_null()) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002754 return;
2755 }
Steve Blocka7e24c12009-10-30 11:49:00 +00002756
2757 // Create the compile state object.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002758 Handle<Object> event_data;
Steve Blocka7e24c12009-10-30 11:49:00 +00002759 // Bail out and don't call debugger if exception.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002760 if (!MakeCompileEvent(script, v8::AfterCompile).ToHandle(&event_data)) return;
2761
Steve Blocka7e24c12009-10-30 11:49:00 +00002762 // Process debug event.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002763 ProcessDebugEvent(v8::AfterCompile, Handle<JSObject>::cast(event_data), true);
Steve Blocka7e24c12009-10-30 11:49:00 +00002764}
2765
2766
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002767void Debug::OnPromiseEvent(Handle<JSObject> data) {
2768 if (in_debug_scope() || ignore_events()) return;
2769
Steve Block44f0eee2011-05-26 01:26:41 +01002770 HandleScope scope(isolate_);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002771 DebugScope debug_scope(this);
2772 if (debug_scope.failed()) return;
Steve Blocka7e24c12009-10-30 11:49:00 +00002773
2774 // Create the script collected state object.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002775 Handle<Object> event_data;
Steve Blocka7e24c12009-10-30 11:49:00 +00002776 // Bail out and don't call debugger if exception.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002777 if (!MakePromiseEvent(data).ToHandle(&event_data)) return;
Steve Blocka7e24c12009-10-30 11:49:00 +00002778
2779 // Process debug event.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002780 ProcessDebugEvent(v8::PromiseEvent,
Steve Blocka7e24c12009-10-30 11:49:00 +00002781 Handle<JSObject>::cast(event_data),
2782 true);
2783}
2784
2785
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002786void Debug::OnAsyncTaskEvent(Handle<JSObject> data) {
2787 if (in_debug_scope() || ignore_events()) return;
2788
2789 HandleScope scope(isolate_);
2790 DebugScope debug_scope(this);
2791 if (debug_scope.failed()) return;
2792
2793 // Create the script collected state object.
2794 Handle<Object> event_data;
2795 // Bail out and don't call debugger if exception.
2796 if (!MakeAsyncTaskEvent(data).ToHandle(&event_data)) return;
2797
2798 // Process debug event.
2799 ProcessDebugEvent(v8::AsyncTaskEvent,
2800 Handle<JSObject>::cast(event_data),
2801 true);
2802}
2803
2804
2805void Debug::ProcessDebugEvent(v8::DebugEvent event,
2806 Handle<JSObject> event_data,
2807 bool auto_continue) {
Steve Block44f0eee2011-05-26 01:26:41 +01002808 HandleScope scope(isolate_);
Steve Blocka7e24c12009-10-30 11:49:00 +00002809
Steve Blocka7e24c12009-10-30 11:49:00 +00002810 // Create the execution state.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002811 Handle<Object> exec_state;
2812 // Bail out and don't call debugger if exception.
2813 if (!MakeExecutionState().ToHandle(&exec_state)) return;
2814
Steve Blocka7e24c12009-10-30 11:49:00 +00002815 // First notify the message handler if any.
2816 if (message_handler_ != NULL) {
2817 NotifyMessageHandler(event,
2818 Handle<JSObject>::cast(exec_state),
2819 event_data,
2820 auto_continue);
2821 }
Ben Murdoch3bec4d22010-07-22 14:51:16 +01002822 // Notify registered debug event listener. This can be either a C or
2823 // a JavaScript function. Don't call event listener for v8::Break
2824 // here, if it's only a debug command -- they will be processed later.
2825 if ((event != v8::Break || !auto_continue) && !event_listener_.is_null()) {
2826 CallEventCallback(event, exec_state, event_data, NULL);
2827 }
2828 // Process pending debug commands.
2829 if (event == v8::Break) {
2830 while (!event_command_queue_.IsEmpty()) {
2831 CommandMessage command = event_command_queue_.Get();
2832 if (!event_listener_.is_null()) {
2833 CallEventCallback(v8::BreakForCommand,
2834 exec_state,
2835 event_data,
2836 command.client_data());
2837 }
2838 command.Dispose();
Steve Blocka7e24c12009-10-30 11:49:00 +00002839 }
2840 }
2841}
2842
2843
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002844void Debug::CallEventCallback(v8::DebugEvent event,
2845 Handle<Object> exec_state,
2846 Handle<Object> event_data,
2847 v8::Debug::ClientData* client_data) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002848 bool previous = in_debug_event_listener_;
2849 in_debug_event_listener_ = true;
Ben Murdoch257744e2011-11-30 15:57:28 +00002850 if (event_listener_->IsForeign()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002851 // Invoke the C debug event listener.
2852 v8::Debug::EventCallback callback =
2853 FUNCTION_CAST<v8::Debug::EventCallback>(
2854 Handle<Foreign>::cast(event_listener_)->foreign_address());
2855 EventDetailsImpl event_details(event,
2856 Handle<JSObject>::cast(exec_state),
2857 Handle<JSObject>::cast(event_data),
2858 event_listener_data_,
2859 client_data);
2860 callback(event_details);
2861 DCHECK(!isolate_->has_scheduled_exception());
Ben Murdoch3bec4d22010-07-22 14:51:16 +01002862 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002863 // Invoke the JavaScript debug event listener.
2864 DCHECK(event_listener_->IsJSFunction());
2865 Handle<Object> argv[] = { Handle<Object>(Smi::FromInt(event), isolate_),
2866 exec_state,
2867 event_data,
2868 event_listener_data_ };
2869 Handle<JSReceiver> global(isolate_->global_proxy());
2870 Execution::TryCall(Handle<JSFunction>::cast(event_listener_),
2871 global, arraysize(argv), argv);
Ben Murdoch3bec4d22010-07-22 14:51:16 +01002872 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -04002873 in_debug_event_listener_ = previous;
2874}
2875
2876
2877void Debug::ProcessCompileEventInDebugScope(v8::DebugEvent event,
2878 Handle<Script> script) {
2879 if (event_listener_.is_null()) return;
2880
2881 SuppressDebug while_processing(this);
2882 DebugScope debug_scope(this);
2883 if (debug_scope.failed()) return;
2884
2885 Handle<Object> event_data;
2886 // Bail out and don't call debugger if exception.
2887 if (!MakeCompileEvent(script, event).ToHandle(&event_data)) return;
2888
2889 // Create the execution state.
2890 Handle<Object> exec_state;
2891 // Bail out and don't call debugger if exception.
2892 if (!MakeExecutionState().ToHandle(&exec_state)) return;
2893
2894 CallEventCallback(event, exec_state, event_data, NULL);
Ben Murdoch3bec4d22010-07-22 14:51:16 +01002895}
2896
2897
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002898Handle<Context> Debug::GetDebugContext() {
2899 DebugScope debug_scope(this);
2900 // The global handle may be destroyed soon after. Return it reboxed.
2901 return handle(*debug_context(), isolate_);
Ben Murdoch3bec4d22010-07-22 14:51:16 +01002902}
2903
2904
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002905void Debug::NotifyMessageHandler(v8::DebugEvent event,
2906 Handle<JSObject> exec_state,
2907 Handle<JSObject> event_data,
2908 bool auto_continue) {
2909 // Prevent other interrupts from triggering, for example API callbacks,
2910 // while dispatching message handler callbacks.
2911 PostponeInterruptsScope no_interrupts(isolate_);
2912 DCHECK(is_active_);
Steve Block44f0eee2011-05-26 01:26:41 +01002913 HandleScope scope(isolate_);
Steve Blocka7e24c12009-10-30 11:49:00 +00002914 // Process the individual events.
2915 bool sendEventMessage = false;
2916 switch (event) {
2917 case v8::Break:
Ben Murdoch3bec4d22010-07-22 14:51:16 +01002918 case v8::BreakForCommand:
Steve Blocka7e24c12009-10-30 11:49:00 +00002919 sendEventMessage = !auto_continue;
2920 break;
2921 case v8::Exception:
2922 sendEventMessage = true;
2923 break;
2924 case v8::BeforeCompile:
2925 break;
2926 case v8::AfterCompile:
2927 sendEventMessage = true;
2928 break;
Steve Blocka7e24c12009-10-30 11:49:00 +00002929 case v8::NewFunction:
2930 break;
2931 default:
2932 UNREACHABLE();
2933 }
2934
2935 // The debug command interrupt flag might have been set when the command was
2936 // added. It should be enough to clear the flag only once while we are in the
2937 // debugger.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002938 DCHECK(in_debug_scope());
2939 isolate_->stack_guard()->ClearDebugCommand();
Steve Blocka7e24c12009-10-30 11:49:00 +00002940
2941 // Notify the debugger that a debug event has occurred unless auto continue is
2942 // active in which case no event is send.
2943 if (sendEventMessage) {
2944 MessageImpl message = MessageImpl::NewEvent(
2945 event,
2946 auto_continue,
2947 Handle<JSObject>::cast(exec_state),
2948 Handle<JSObject>::cast(event_data));
2949 InvokeMessageHandler(message);
2950 }
2951
2952 // If auto continue don't make the event cause a break, but process messages
2953 // in the queue if any. For script collected events don't even process
2954 // messages in the queue as the execution state might not be what is expected
2955 // by the client.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002956 if (auto_continue && !has_commands()) return;
Steve Block3ce2e202009-11-05 08:53:23 +00002957
2958 // DebugCommandProcessor goes here.
Steve Block3ce2e202009-11-05 08:53:23 +00002959 bool running = auto_continue;
2960
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002961 Handle<Object> cmd_processor_ctor = Object::GetProperty(
2962 isolate_, exec_state, "debugCommandProcessor").ToHandleChecked();
2963 Handle<Object> ctor_args[] = { isolate_->factory()->ToBoolean(running) };
2964 Handle<Object> cmd_processor = Execution::Call(
2965 isolate_, cmd_processor_ctor, exec_state, 1, ctor_args).ToHandleChecked();
2966 Handle<JSFunction> process_debug_request = Handle<JSFunction>::cast(
2967 Object::GetProperty(
2968 isolate_, cmd_processor, "processDebugRequest").ToHandleChecked());
2969 Handle<Object> is_running = Object::GetProperty(
2970 isolate_, cmd_processor, "isRunning").ToHandleChecked();
2971
Steve Blocka7e24c12009-10-30 11:49:00 +00002972 // Process requests from the debugger.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002973 do {
Steve Blocka7e24c12009-10-30 11:49:00 +00002974 // Wait for new command in the queue.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002975 command_received_.Wait();
Steve Blocka7e24c12009-10-30 11:49:00 +00002976
2977 // Get the command from the queue.
2978 CommandMessage command = command_queue_.Get();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00002979 isolate_->logger()->DebugTag(
2980 "Got request from command queue, in interactive loop.");
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002981 if (!is_active()) {
Steve Blocka7e24c12009-10-30 11:49:00 +00002982 // Delete command text and user data.
2983 command.Dispose();
2984 return;
2985 }
2986
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002987 Vector<const uc16> command_text(
2988 const_cast<const uc16*>(command.text().start()),
2989 command.text().length());
2990 Handle<String> request_text = isolate_->factory()->NewStringFromTwoByte(
2991 command_text).ToHandleChecked();
2992 Handle<Object> request_args[] = { request_text };
2993 Handle<Object> answer_value;
2994 Handle<String> answer;
2995 MaybeHandle<Object> maybe_exception;
2996 MaybeHandle<Object> maybe_result =
2997 Execution::TryCall(process_debug_request, cmd_processor, 1,
2998 request_args, &maybe_exception);
Steve Blocka7e24c12009-10-30 11:49:00 +00002999
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003000 if (maybe_result.ToHandle(&answer_value)) {
3001 if (answer_value->IsUndefined()) {
3002 answer = isolate_->factory()->empty_string();
Steve Blocka7e24c12009-10-30 11:49:00 +00003003 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003004 answer = Handle<String>::cast(answer_value);
Steve Blocka7e24c12009-10-30 11:49:00 +00003005 }
3006
3007 // Log the JSON request/response.
3008 if (FLAG_trace_debug_json) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003009 PrintF("%s\n", request_text->ToCString().get());
3010 PrintF("%s\n", answer->ToCString().get());
Steve Blocka7e24c12009-10-30 11:49:00 +00003011 }
3012
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003013 Handle<Object> is_running_args[] = { answer };
3014 maybe_result = Execution::Call(
3015 isolate_, is_running, cmd_processor, 1, is_running_args);
3016 Handle<Object> result;
3017 if (!maybe_result.ToHandle(&result)) break;
3018 running = result->IsTrue();
Steve Blocka7e24c12009-10-30 11:49:00 +00003019 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003020 Handle<Object> exception;
3021 if (!maybe_exception.ToHandle(&exception)) break;
3022 Handle<Object> result;
3023 if (!Execution::ToString(isolate_, exception).ToHandle(&result)) break;
3024 answer = Handle<String>::cast(result);
Steve Blocka7e24c12009-10-30 11:49:00 +00003025 }
3026
3027 // Return the result.
3028 MessageImpl message = MessageImpl::NewResponse(
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003029 event, running, exec_state, event_data, answer, command.client_data());
Steve Blocka7e24c12009-10-30 11:49:00 +00003030 InvokeMessageHandler(message);
3031 command.Dispose();
3032
3033 // Return from debug event processing if either the VM is put into the
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003034 // running state (through a continue command) or auto continue is active
Steve Blocka7e24c12009-10-30 11:49:00 +00003035 // and there are no more commands queued.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003036 } while (!running || has_commands());
3037 command_queue_.Clear();
Steve Blocka7e24c12009-10-30 11:49:00 +00003038}
3039
3040
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003041void Debug::SetEventListener(Handle<Object> callback,
3042 Handle<Object> data) {
Steve Block44f0eee2011-05-26 01:26:41 +01003043 GlobalHandles* global_handles = isolate_->global_handles();
Steve Blocka7e24c12009-10-30 11:49:00 +00003044
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003045 // Remove existing entry.
3046 GlobalHandles::Destroy(event_listener_.location());
3047 event_listener_ = Handle<Object>();
3048 GlobalHandles::Destroy(event_listener_data_.location());
3049 event_listener_data_ = Handle<Object>();
Steve Blocka7e24c12009-10-30 11:49:00 +00003050
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003051 // Set new entry.
Steve Blocka7e24c12009-10-30 11:49:00 +00003052 if (!callback->IsUndefined() && !callback->IsNull()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003053 event_listener_ = global_handles->Create(*callback);
3054 if (data.is_null()) data = isolate_->factory()->undefined_value();
3055 event_listener_data_ = global_handles->Create(*data);
Steve Blocka7e24c12009-10-30 11:49:00 +00003056 }
3057
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003058 UpdateState();
Steve Blocka7e24c12009-10-30 11:49:00 +00003059}
3060
3061
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003062void Debug::SetMessageHandler(v8::Debug::MessageHandler handler) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003063 message_handler_ = handler;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003064 UpdateState();
3065 if (handler == NULL && in_debug_scope()) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003066 // Send an empty command to the debugger if in a break to make JavaScript
3067 // run again if the debugger is closed.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003068 EnqueueCommandMessage(Vector<const uint16_t>::empty());
Steve Blocka7e24c12009-10-30 11:49:00 +00003069 }
3070}
3071
3072
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003073
3074void Debug::UpdateState() {
3075 is_active_ = message_handler_ != NULL || !event_listener_.is_null();
3076 if (is_active_ || in_debug_scope()) {
3077 // Note that the debug context could have already been loaded to
3078 // bootstrap test cases.
Steve Block44f0eee2011-05-26 01:26:41 +01003079 isolate_->compilation_cache()->Disable();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003080 is_active_ = Load();
3081 } else if (is_loaded()) {
Steve Block44f0eee2011-05-26 01:26:41 +01003082 isolate_->compilation_cache()->Enable();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003083 Unload();
Leon Clarkee46be812010-01-19 14:06:41 +00003084 }
Steve Blockd0582a62009-12-15 09:54:21 +00003085}
3086
3087
Steve Blocka7e24c12009-10-30 11:49:00 +00003088// Calls the registered debug message handler. This callback is part of the
3089// public API.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003090void Debug::InvokeMessageHandler(MessageImpl message) {
3091 if (message_handler_ != NULL) message_handler_(message);
Steve Blocka7e24c12009-10-30 11:49:00 +00003092}
3093
3094
3095// Puts a command coming from the public API on the queue. Creates
3096// a copy of the command string managed by the debugger. Up to this
3097// point, the command data was managed by the API client. Called
3098// by the API client thread.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003099void Debug::EnqueueCommandMessage(Vector<const uint16_t> command,
3100 v8::Debug::ClientData* client_data) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003101 // Need to cast away const.
3102 CommandMessage message = CommandMessage::New(
3103 Vector<uint16_t>(const_cast<uint16_t*>(command.start()),
3104 command.length()),
3105 client_data);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003106 isolate_->logger()->DebugTag("Put command on command_queue.");
Steve Blocka7e24c12009-10-30 11:49:00 +00003107 command_queue_.Put(message);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003108 command_received_.Signal();
Steve Blocka7e24c12009-10-30 11:49:00 +00003109
3110 // Set the debug command break flag to have the command processed.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003111 if (!in_debug_scope()) isolate_->stack_guard()->RequestDebugCommand();
Steve Blocka7e24c12009-10-30 11:49:00 +00003112}
3113
3114
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003115void Debug::EnqueueDebugCommand(v8::Debug::ClientData* client_data) {
Ben Murdoch3bec4d22010-07-22 14:51:16 +01003116 CommandMessage message = CommandMessage::New(Vector<uint16_t>(), client_data);
3117 event_command_queue_.Put(message);
3118
3119 // Set the debug command break flag to have the command processed.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003120 if (!in_debug_scope()) isolate_->stack_guard()->RequestDebugCommand();
Ben Murdoch3bec4d22010-07-22 14:51:16 +01003121}
3122
3123
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003124MaybeHandle<Object> Debug::Call(Handle<JSFunction> fun, Handle<Object> data) {
3125 DebugScope debug_scope(this);
3126 if (debug_scope.failed()) return isolate_->factory()->undefined_value();
Steve Blocka7e24c12009-10-30 11:49:00 +00003127
3128 // Create the execution state.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003129 Handle<Object> exec_state;
3130 if (!MakeExecutionState().ToHandle(&exec_state)) {
Steve Block44f0eee2011-05-26 01:26:41 +01003131 return isolate_->factory()->undefined_value();
Steve Blocka7e24c12009-10-30 11:49:00 +00003132 }
3133
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003134 Handle<Object> argv[] = { exec_state, data };
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003135 return Execution::Call(
3136 isolate_,
Steve Block6ded16b2010-05-10 14:33:55 +01003137 fun,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003138 Handle<Object>(debug_context()->global_proxy(), isolate_),
3139 arraysize(argv),
3140 argv);
Steve Blocka7e24c12009-10-30 11:49:00 +00003141}
3142
3143
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003144void Debug::HandleDebugBreak() {
3145 // Ignore debug break during bootstrapping.
3146 if (isolate_->bootstrapper()->IsActive()) return;
3147 // Just continue if breaks are disabled.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003148 if (break_disabled()) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003149 // Ignore debug break if debugger is not active.
3150 if (!is_active()) return;
Leon Clarkee46be812010-01-19 14:06:41 +00003151
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003152 StackLimitCheck check(isolate_);
3153 if (check.HasOverflowed()) return;
Leon Clarkee46be812010-01-19 14:06:41 +00003154
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003155 { JavaScriptFrameIterator it(isolate_);
3156 DCHECK(!it.done());
3157 Object* fun = it.frame()->function();
3158 if (fun && fun->IsJSFunction()) {
3159 // Don't stop in builtin functions.
3160 if (JSFunction::cast(fun)->IsBuiltin()) return;
3161 GlobalObject* global = JSFunction::cast(fun)->context()->global_object();
3162 // Don't stop in debugger functions.
3163 if (IsDebugGlobal(global)) return;
Ben Murdoch086aeea2011-05-13 15:57:08 +01003164 }
Steve Blocka7e24c12009-10-30 11:49:00 +00003165 }
3166
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003167 // Collect the break state before clearing the flags.
3168 bool debug_command_only = isolate_->stack_guard()->CheckDebugCommand() &&
3169 !isolate_->stack_guard()->CheckDebugBreak();
3170
3171 isolate_->stack_guard()->ClearDebugBreak();
3172
3173 ProcessDebugMessages(debug_command_only);
Steve Blocka7e24c12009-10-30 11:49:00 +00003174}
3175
3176
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003177void Debug::ProcessDebugMessages(bool debug_command_only) {
3178 isolate_->stack_guard()->ClearDebugCommand();
3179
3180 StackLimitCheck check(isolate_);
3181 if (check.HasOverflowed()) return;
3182
3183 HandleScope scope(isolate_);
3184 DebugScope debug_scope(this);
3185 if (debug_scope.failed()) return;
3186
3187 // Notify the debug event listeners. Indicate auto continue if the break was
3188 // a debug command break.
3189 OnDebugBreak(isolate_->factory()->undefined_value(), debug_command_only);
Steve Blocka7e24c12009-10-30 11:49:00 +00003190}
3191
3192
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003193DebugScope::DebugScope(Debug* debug)
3194 : debug_(debug),
3195 prev_(debug->debugger_entry()),
3196 save_(debug_->isolate_),
3197 no_termination_exceptons_(debug_->isolate_,
3198 StackGuard::TERMINATE_EXECUTION) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003199 // Link recursive debugger entry.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003200 base::NoBarrier_Store(&debug_->thread_local_.current_debug_scope_,
3201 reinterpret_cast<base::AtomicWord>(this));
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003202
3203 // Store the previous break id and frame id.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003204 break_id_ = debug_->break_id();
3205 break_frame_id_ = debug_->break_frame_id();
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003206
3207 // Create the new break info. If there is no JavaScript frames there is no
3208 // break frame id.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003209 JavaScriptFrameIterator it(isolate());
3210 bool has_js_frames = !it.done();
3211 debug_->thread_local_.break_frame_id_ = has_js_frames ? it.frame()->id()
3212 : StackFrame::NO_ID;
3213 debug_->SetNextBreakId();
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003214
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003215 debug_->UpdateState();
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003216 // Make sure that debugger is loaded and enter the debugger context.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003217 // The previous context is kept in save_.
3218 failed_ = !debug_->is_loaded();
3219 if (!failed_) isolate()->set_context(*debug->debug_context());
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003220}
3221
3222
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003223
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003224DebugScope::~DebugScope() {
3225 if (!failed_ && prev_ == NULL) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003226 // Clear mirror cache when leaving the debugger. Skip this if there is a
3227 // pending exception as clearing the mirror cache calls back into
3228 // JavaScript. This can happen if the v8::Debug::Call is used in which
3229 // case the exception should end up in the calling code.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003230 if (!isolate()->has_pending_exception()) debug_->ClearMirrorCache();
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003231
3232 // If there are commands in the queue when leaving the debugger request
3233 // that these commands are processed.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003234 if (debug_->has_commands()) isolate()->stack_guard()->RequestDebugCommand();
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003235 }
3236
3237 // Leaving this debugger entry.
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003238 base::NoBarrier_Store(&debug_->thread_local_.current_debug_scope_,
3239 reinterpret_cast<base::AtomicWord>(prev_));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003240
3241 // Restore to the previous break state.
3242 debug_->thread_local_.break_frame_id_ = break_frame_id_;
3243 debug_->thread_local_.break_id_ = break_id_;
3244
3245 debug_->UpdateState();
Ben Murdoch3ef787d2012-04-12 10:51:47 +01003246}
3247
3248
Steve Blocka7e24c12009-10-30 11:49:00 +00003249MessageImpl MessageImpl::NewEvent(DebugEvent event,
3250 bool running,
3251 Handle<JSObject> exec_state,
3252 Handle<JSObject> event_data) {
3253 MessageImpl message(true, event, running,
3254 exec_state, event_data, Handle<String>(), NULL);
3255 return message;
3256}
3257
3258
3259MessageImpl MessageImpl::NewResponse(DebugEvent event,
3260 bool running,
3261 Handle<JSObject> exec_state,
3262 Handle<JSObject> event_data,
3263 Handle<String> response_json,
3264 v8::Debug::ClientData* client_data) {
3265 MessageImpl message(false, event, running,
3266 exec_state, event_data, response_json, client_data);
3267 return message;
3268}
3269
3270
3271MessageImpl::MessageImpl(bool is_event,
3272 DebugEvent event,
3273 bool running,
3274 Handle<JSObject> exec_state,
3275 Handle<JSObject> event_data,
3276 Handle<String> response_json,
3277 v8::Debug::ClientData* client_data)
3278 : is_event_(is_event),
3279 event_(event),
3280 running_(running),
3281 exec_state_(exec_state),
3282 event_data_(event_data),
3283 response_json_(response_json),
3284 client_data_(client_data) {}
3285
3286
3287bool MessageImpl::IsEvent() const {
3288 return is_event_;
3289}
3290
3291
3292bool MessageImpl::IsResponse() const {
3293 return !is_event_;
3294}
3295
3296
3297DebugEvent MessageImpl::GetEvent() const {
3298 return event_;
3299}
3300
3301
3302bool MessageImpl::WillStartRunning() const {
3303 return running_;
3304}
3305
3306
3307v8::Handle<v8::Object> MessageImpl::GetExecutionState() const {
3308 return v8::Utils::ToLocal(exec_state_);
3309}
3310
3311
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003312v8::Isolate* MessageImpl::GetIsolate() const {
3313 return reinterpret_cast<v8::Isolate*>(exec_state_->GetIsolate());
3314}
3315
3316
Steve Blocka7e24c12009-10-30 11:49:00 +00003317v8::Handle<v8::Object> MessageImpl::GetEventData() const {
3318 return v8::Utils::ToLocal(event_data_);
3319}
3320
3321
3322v8::Handle<v8::String> MessageImpl::GetJSON() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003323 Isolate* isolate = event_data_->GetIsolate();
3324 v8::EscapableHandleScope scope(reinterpret_cast<v8::Isolate*>(isolate));
Steve Blocka7e24c12009-10-30 11:49:00 +00003325
3326 if (IsEvent()) {
3327 // Call toJSONProtocol on the debug event object.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003328 Handle<Object> fun = Object::GetProperty(
3329 isolate, event_data_, "toJSONProtocol").ToHandleChecked();
Steve Blocka7e24c12009-10-30 11:49:00 +00003330 if (!fun->IsJSFunction()) {
3331 return v8::Handle<v8::String>();
3332 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003333
3334 MaybeHandle<Object> maybe_json =
3335 Execution::TryCall(Handle<JSFunction>::cast(fun), event_data_, 0, NULL);
3336 Handle<Object> json;
3337 if (!maybe_json.ToHandle(&json) || !json->IsString()) {
Steve Blocka7e24c12009-10-30 11:49:00 +00003338 return v8::Handle<v8::String>();
3339 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003340 return scope.Escape(v8::Utils::ToLocal(Handle<String>::cast(json)));
Steve Blocka7e24c12009-10-30 11:49:00 +00003341 } else {
3342 return v8::Utils::ToLocal(response_json_);
3343 }
3344}
3345
3346
3347v8::Handle<v8::Context> MessageImpl::GetEventContext() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003348 Isolate* isolate = event_data_->GetIsolate();
Steve Block44f0eee2011-05-26 01:26:41 +01003349 v8::Handle<v8::Context> context = GetDebugEventContext(isolate);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04003350 // Isolate::context() may be NULL when "script collected" event occurs.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003351 DCHECK(!context.IsEmpty());
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003352 return context;
Steve Blocka7e24c12009-10-30 11:49:00 +00003353}
3354
3355
3356v8::Debug::ClientData* MessageImpl::GetClientData() const {
3357 return client_data_;
3358}
3359
3360
Leon Clarkef7060e22010-06-03 12:02:55 +01003361EventDetailsImpl::EventDetailsImpl(DebugEvent event,
3362 Handle<JSObject> exec_state,
3363 Handle<JSObject> event_data,
Ben Murdoch3bec4d22010-07-22 14:51:16 +01003364 Handle<Object> callback_data,
3365 v8::Debug::ClientData* client_data)
Leon Clarkef7060e22010-06-03 12:02:55 +01003366 : event_(event),
3367 exec_state_(exec_state),
3368 event_data_(event_data),
Ben Murdoch3bec4d22010-07-22 14:51:16 +01003369 callback_data_(callback_data),
3370 client_data_(client_data) {}
Leon Clarkef7060e22010-06-03 12:02:55 +01003371
3372
3373DebugEvent EventDetailsImpl::GetEvent() const {
3374 return event_;
3375}
3376
3377
3378v8::Handle<v8::Object> EventDetailsImpl::GetExecutionState() const {
3379 return v8::Utils::ToLocal(exec_state_);
3380}
3381
3382
3383v8::Handle<v8::Object> EventDetailsImpl::GetEventData() const {
3384 return v8::Utils::ToLocal(event_data_);
3385}
3386
3387
3388v8::Handle<v8::Context> EventDetailsImpl::GetEventContext() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003389 return GetDebugEventContext(exec_state_->GetIsolate());
Leon Clarkef7060e22010-06-03 12:02:55 +01003390}
3391
3392
3393v8::Handle<v8::Value> EventDetailsImpl::GetCallbackData() const {
3394 return v8::Utils::ToLocal(callback_data_);
3395}
3396
3397
Ben Murdoch3bec4d22010-07-22 14:51:16 +01003398v8::Debug::ClientData* EventDetailsImpl::GetClientData() const {
3399 return client_data_;
3400}
3401
3402
Steve Blocka7e24c12009-10-30 11:49:00 +00003403CommandMessage::CommandMessage() : text_(Vector<uint16_t>::empty()),
3404 client_data_(NULL) {
3405}
3406
3407
3408CommandMessage::CommandMessage(const Vector<uint16_t>& text,
3409 v8::Debug::ClientData* data)
3410 : text_(text),
3411 client_data_(data) {
3412}
3413
3414
Steve Blocka7e24c12009-10-30 11:49:00 +00003415void CommandMessage::Dispose() {
3416 text_.Dispose();
3417 delete client_data_;
3418 client_data_ = NULL;
3419}
3420
3421
3422CommandMessage CommandMessage::New(const Vector<uint16_t>& command,
3423 v8::Debug::ClientData* data) {
3424 return CommandMessage(command.Clone(), data);
3425}
3426
3427
3428CommandMessageQueue::CommandMessageQueue(int size) : start_(0), end_(0),
3429 size_(size) {
3430 messages_ = NewArray<CommandMessage>(size);
3431}
3432
3433
3434CommandMessageQueue::~CommandMessageQueue() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003435 while (!IsEmpty()) Get().Dispose();
Steve Blocka7e24c12009-10-30 11:49:00 +00003436 DeleteArray(messages_);
3437}
3438
3439
3440CommandMessage CommandMessageQueue::Get() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003441 DCHECK(!IsEmpty());
Steve Blocka7e24c12009-10-30 11:49:00 +00003442 int result = start_;
3443 start_ = (start_ + 1) % size_;
3444 return messages_[result];
3445}
3446
3447
3448void CommandMessageQueue::Put(const CommandMessage& message) {
3449 if ((end_ + 1) % size_ == start_) {
3450 Expand();
3451 }
3452 messages_[end_] = message;
3453 end_ = (end_ + 1) % size_;
3454}
3455
3456
3457void CommandMessageQueue::Expand() {
3458 CommandMessageQueue new_queue(size_ * 2);
3459 while (!IsEmpty()) {
3460 new_queue.Put(Get());
3461 }
3462 CommandMessage* array_to_free = messages_;
3463 *this = new_queue;
3464 new_queue.messages_ = array_to_free;
3465 // Make the new_queue empty so that it doesn't call Dispose on any messages.
3466 new_queue.start_ = new_queue.end_;
3467 // Automatic destructor called on new_queue, freeing array_to_free.
3468}
3469
3470
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003471LockingCommandMessageQueue::LockingCommandMessageQueue(Logger* logger, int size)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003472 : logger_(logger), queue_(size) {}
Steve Blocka7e24c12009-10-30 11:49:00 +00003473
3474
3475bool LockingCommandMessageQueue::IsEmpty() const {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003476 base::LockGuard<base::Mutex> lock_guard(&mutex_);
Steve Blocka7e24c12009-10-30 11:49:00 +00003477 return queue_.IsEmpty();
3478}
3479
3480
3481CommandMessage LockingCommandMessageQueue::Get() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003482 base::LockGuard<base::Mutex> lock_guard(&mutex_);
Steve Blocka7e24c12009-10-30 11:49:00 +00003483 CommandMessage result = queue_.Get();
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003484 logger_->DebugEvent("Get", result.text());
Steve Blocka7e24c12009-10-30 11:49:00 +00003485 return result;
3486}
3487
3488
3489void LockingCommandMessageQueue::Put(const CommandMessage& message) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003490 base::LockGuard<base::Mutex> lock_guard(&mutex_);
Steve Blocka7e24c12009-10-30 11:49:00 +00003491 queue_.Put(message);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00003492 logger_->DebugEvent("Put", message.text());
Steve Blocka7e24c12009-10-30 11:49:00 +00003493}
3494
3495
3496void LockingCommandMessageQueue::Clear() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00003497 base::LockGuard<base::Mutex> lock_guard(&mutex_);
Steve Blocka7e24c12009-10-30 11:49:00 +00003498 queue_.Clear();
3499}
3500
Steve Blocka7e24c12009-10-30 11:49:00 +00003501} } // namespace v8::internal