blob: 6e9401257967cd0f4bcb64385c87213085275bd9 [file] [log] [blame]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001// Copyright 2012 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "src/debug/debug.h"
6
7#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/deoptimizer.h"
15#include "src/execution.h"
16#include "src/frames-inl.h"
17#include "src/full-codegen/full-codegen.h"
18#include "src/global-handles.h"
Ben Murdoch097c5b22016-05-18 11:27:45 +010019#include "src/interpreter/interpreter.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000020#include "src/isolate-inl.h"
21#include "src/list.h"
22#include "src/log.h"
23#include "src/messages.h"
24#include "src/snapshot/natives.h"
25
26#include "include/v8-debug.h"
27
28namespace v8 {
29namespace internal {
30
31Debug::Debug(Isolate* isolate)
32 : debug_context_(Handle<Context>()),
33 event_listener_(Handle<Object>()),
34 event_listener_data_(Handle<Object>()),
35 message_handler_(NULL),
36 command_received_(0),
37 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 break_disabled_(false),
42 break_points_active_(true),
43 in_debug_event_listener_(false),
44 break_on_exception_(false),
45 break_on_uncaught_exception_(false),
46 debug_info_list_(NULL),
47 feature_tracker_(isolate),
48 isolate_(isolate) {
49 ThreadInit();
50}
51
52
53static v8::Local<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>();
58 Handle<Context> native_context(context->native_context());
59 return v8::Utils::ToLocal(native_context);
60}
61
Ben Murdoch097c5b22016-05-18 11:27:45 +010062BreakLocation::BreakLocation(Handle<DebugInfo> debug_info, DebugBreakType type,
63 int code_offset, int position,
64 int statement_position)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000065 : debug_info_(debug_info),
Ben Murdoch097c5b22016-05-18 11:27:45 +010066 code_offset_(code_offset),
67 type_(type),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000068 position_(position),
69 statement_position_(statement_position) {}
70
Ben Murdoch097c5b22016-05-18 11:27:45 +010071BreakLocation::Iterator* BreakLocation::GetIterator(
72 Handle<DebugInfo> debug_info, BreakLocatorType type) {
73 if (debug_info->abstract_code()->IsBytecodeArray()) {
74 return new BytecodeArrayIterator(debug_info, type);
75 } else {
76 return new CodeIterator(debug_info, type);
77 }
78}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000079
Ben Murdoch097c5b22016-05-18 11:27:45 +010080BreakLocation::Iterator::Iterator(Handle<DebugInfo> debug_info)
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000081 : debug_info_(debug_info),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000082 break_index_(-1),
83 position_(1),
Ben Murdoch097c5b22016-05-18 11:27:45 +010084 statement_position_(1) {}
85
Ben Murdochda12d292016-06-02 14:46:10 +010086int BreakLocation::Iterator::ReturnPosition() {
87 if (debug_info_->shared()->HasSourceCode()) {
88 return debug_info_->shared()->end_position() -
89 debug_info_->shared()->start_position() - 1;
90 } else {
91 return 0;
92 }
93}
94
Ben Murdoch097c5b22016-05-18 11:27:45 +010095BreakLocation::CodeIterator::CodeIterator(Handle<DebugInfo> debug_info,
96 BreakLocatorType type)
97 : Iterator(debug_info),
98 reloc_iterator_(debug_info->abstract_code()->GetCode(),
99 GetModeMask(type)) {
Ben Murdochda12d292016-06-02 14:46:10 +0100100 // There is at least one break location.
101 DCHECK(!Done());
102 Next();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000103}
104
Ben Murdoch097c5b22016-05-18 11:27:45 +0100105int BreakLocation::CodeIterator::GetModeMask(BreakLocatorType type) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000106 int mask = 0;
107 mask |= RelocInfo::ModeMask(RelocInfo::POSITION);
108 mask |= RelocInfo::ModeMask(RelocInfo::STATEMENT_POSITION);
109 mask |= RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_RETURN);
110 mask |= RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_CALL);
Ben Murdochda12d292016-06-02 14:46:10 +0100111 if (isolate()->is_tail_call_elimination_enabled()) {
112 mask |= RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_TAIL_CALL);
113 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000114 if (type == ALL_BREAK_LOCATIONS) {
115 mask |= RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_POSITION);
116 mask |= RelocInfo::ModeMask(RelocInfo::DEBUGGER_STATEMENT);
117 }
118 return mask;
119}
120
Ben Murdoch097c5b22016-05-18 11:27:45 +0100121void BreakLocation::CodeIterator::Next() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000122 DisallowHeapAllocation no_gc;
123 DCHECK(!Done());
124
Ben Murdoch097c5b22016-05-18 11:27:45 +0100125 // Iterate through reloc info stopping at each breakable code target.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000126 bool first = break_index_ == -1;
127 while (!Done()) {
128 if (!first) reloc_iterator_.next();
129 first = false;
130 if (Done()) return;
131
132 // Whenever a statement position or (plain) position is passed update the
133 // current value of these.
134 if (RelocInfo::IsPosition(rmode())) {
135 if (RelocInfo::IsStatementPosition(rmode())) {
136 statement_position_ = static_cast<int>(
137 rinfo()->data() - debug_info_->shared()->start_position());
138 }
139 // Always update the position as we don't want that to be before the
140 // statement position.
141 position_ = static_cast<int>(rinfo()->data() -
142 debug_info_->shared()->start_position());
143 DCHECK(position_ >= 0);
144 DCHECK(statement_position_ >= 0);
145 continue;
146 }
147
148 DCHECK(RelocInfo::IsDebugBreakSlot(rmode()) ||
149 RelocInfo::IsDebuggerStatement(rmode()));
150
151 if (RelocInfo::IsDebugBreakSlotAtReturn(rmode())) {
152 // Set the positions to the end of the function.
Ben Murdochda12d292016-06-02 14:46:10 +0100153 statement_position_ = position_ = ReturnPosition();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000154 }
155
156 break;
157 }
158 break_index_++;
159}
160
Ben Murdoch097c5b22016-05-18 11:27:45 +0100161BreakLocation BreakLocation::CodeIterator::GetBreakLocation() {
162 DebugBreakType type;
163 if (RelocInfo::IsDebugBreakSlotAtReturn(rmode())) {
164 type = DEBUG_BREAK_SLOT_AT_RETURN;
165 } else if (RelocInfo::IsDebugBreakSlotAtCall(rmode())) {
166 type = DEBUG_BREAK_SLOT_AT_CALL;
Ben Murdochda12d292016-06-02 14:46:10 +0100167 } else if (RelocInfo::IsDebugBreakSlotAtTailCall(rmode())) {
168 type = isolate()->is_tail_call_elimination_enabled()
169 ? DEBUG_BREAK_SLOT_AT_TAIL_CALL
170 : DEBUG_BREAK_SLOT_AT_CALL;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100171 } else if (RelocInfo::IsDebuggerStatement(rmode())) {
172 type = DEBUGGER_STATEMENT;
173 } else if (RelocInfo::IsDebugBreakSlot(rmode())) {
174 type = DEBUG_BREAK_SLOT;
175 } else {
176 type = NOT_DEBUG_BREAK;
177 }
178 return BreakLocation(debug_info_, type, code_offset(), position(),
179 statement_position());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000180}
181
Ben Murdoch097c5b22016-05-18 11:27:45 +0100182BreakLocation::BytecodeArrayIterator::BytecodeArrayIterator(
183 Handle<DebugInfo> debug_info, BreakLocatorType type)
184 : Iterator(debug_info),
Ben Murdochda12d292016-06-02 14:46:10 +0100185 source_position_iterator_(debug_info->abstract_code()
186 ->GetBytecodeArray()
187 ->source_position_table()),
Ben Murdoch097c5b22016-05-18 11:27:45 +0100188 break_locator_type_(type),
189 start_position_(debug_info->shared()->start_position()) {
Ben Murdochda12d292016-06-02 14:46:10 +0100190 // There is at least one break location.
191 DCHECK(!Done());
192 Next();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100193}
194
195void BreakLocation::BytecodeArrayIterator::Next() {
196 DisallowHeapAllocation no_gc;
197 DCHECK(!Done());
198 bool first = break_index_ == -1;
199 while (!Done()) {
200 if (!first) source_position_iterator_.Advance();
201 first = false;
202 if (Done()) return;
203 position_ = source_position_iterator_.source_position() - start_position_;
204 if (source_position_iterator_.is_statement()) {
205 statement_position_ = position_;
206 }
207 DCHECK(position_ >= 0);
208 DCHECK(statement_position_ >= 0);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100209
210 enum DebugBreakType type = GetDebugBreakType();
211 if (type == NOT_DEBUG_BREAK) continue;
212
213 if (break_locator_type_ == ALL_BREAK_LOCATIONS) break;
214
215 DCHECK_EQ(CALLS_AND_RETURNS, break_locator_type_);
Ben Murdochda12d292016-06-02 14:46:10 +0100216 if (type == DEBUG_BREAK_SLOT_AT_CALL) break;
217 if (type == DEBUG_BREAK_SLOT_AT_RETURN) {
218 DCHECK_EQ(ReturnPosition(), position_);
219 DCHECK_EQ(ReturnPosition(), statement_position_);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100220 break;
221 }
222 }
Ben Murdochda12d292016-06-02 14:46:10 +0100223 break_index_++;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100224}
225
226BreakLocation::DebugBreakType
227BreakLocation::BytecodeArrayIterator::GetDebugBreakType() {
228 BytecodeArray* bytecode_array = debug_info_->original_bytecode_array();
229 interpreter::Bytecode bytecode =
230 interpreter::Bytecodes::FromByte(bytecode_array->get(code_offset()));
231
232 if (bytecode == interpreter::Bytecode::kDebugger) {
233 return DEBUGGER_STATEMENT;
234 } else if (bytecode == interpreter::Bytecode::kReturn) {
235 return DEBUG_BREAK_SLOT_AT_RETURN;
Ben Murdochda12d292016-06-02 14:46:10 +0100236 } else if (bytecode == interpreter::Bytecode::kTailCall) {
237 return isolate()->is_tail_call_elimination_enabled()
238 ? DEBUG_BREAK_SLOT_AT_TAIL_CALL
239 : DEBUG_BREAK_SLOT_AT_CALL;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100240 } else if (interpreter::Bytecodes::IsCallOrNew(bytecode)) {
241 return DEBUG_BREAK_SLOT_AT_CALL;
242 } else if (source_position_iterator_.is_statement()) {
243 return DEBUG_BREAK_SLOT;
244 } else {
245 return NOT_DEBUG_BREAK;
246 }
247}
248
249BreakLocation BreakLocation::BytecodeArrayIterator::GetBreakLocation() {
250 return BreakLocation(debug_info_, GetDebugBreakType(), code_offset(),
251 position(), statement_position());
252}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000253
254// Find the break point at the supplied address, or the closest one before
255// the address.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100256BreakLocation BreakLocation::FromCodeOffset(Handle<DebugInfo> debug_info,
257 int offset) {
258 base::SmartPointer<Iterator> it(GetIterator(debug_info));
259 it->SkipTo(BreakIndexFromCodeOffset(debug_info, offset));
260 return it->GetBreakLocation();
261}
262
263FrameSummary GetFirstFrameSummary(JavaScriptFrame* frame) {
264 List<FrameSummary> frames(FLAG_max_inlining_levels + 1);
265 frame->Summarize(&frames);
266 return frames.first();
267}
268
269int CallOffsetFromCodeOffset(int code_offset, bool is_interpreted) {
270 // Code offset points to the instruction after the call. Subtract 1 to
271 // exclude that instruction from the search. For bytecode, the code offset
272 // still points to the call.
273 return is_interpreted ? code_offset : code_offset - 1;
274}
275
276BreakLocation BreakLocation::FromFrame(Handle<DebugInfo> debug_info,
277 JavaScriptFrame* frame) {
278 FrameSummary summary = GetFirstFrameSummary(frame);
279 int call_offset =
280 CallOffsetFromCodeOffset(summary.code_offset(), frame->is_interpreted());
281 return FromCodeOffset(debug_info, call_offset);
282}
283
Ben Murdoch097c5b22016-05-18 11:27:45 +0100284void BreakLocation::AllForStatementPosition(Handle<DebugInfo> debug_info,
285 int statement_position,
286 List<BreakLocation>* result_out) {
287 for (base::SmartPointer<Iterator> it(GetIterator(debug_info)); !it->Done();
288 it->Next()) {
289 if (it->statement_position() == statement_position) {
290 result_out->Add(it->GetBreakLocation());
291 }
292 }
293}
294
295int BreakLocation::BreakIndexFromCodeOffset(Handle<DebugInfo> debug_info,
296 int offset) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000297 // Run through all break points to locate the one closest to the address.
298 int closest_break = 0;
299 int distance = kMaxInt;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100300 DCHECK(0 <= offset && offset < debug_info->abstract_code()->Size());
301 for (base::SmartPointer<Iterator> it(GetIterator(debug_info)); !it->Done();
302 it->Next()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000303 // Check if this break point is closer that what was previously found.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100304 if (it->code_offset() <= offset && offset - it->code_offset() < distance) {
305 closest_break = it->break_index();
306 distance = offset - it->code_offset();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000307 // Check whether we can't get any closer.
308 if (distance == 0) break;
309 }
310 }
311 return closest_break;
312}
313
314
315BreakLocation BreakLocation::FromPosition(Handle<DebugInfo> debug_info,
316 int position,
317 BreakPositionAlignment alignment) {
318 // Run through all break points to locate the one closest to the source
319 // position.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000320 int distance = kMaxInt;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100321 base::SmartPointer<Iterator> it(GetIterator(debug_info));
322 BreakLocation closest_break = it->GetBreakLocation();
323 while (!it->Done()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000324 int next_position;
325 if (alignment == STATEMENT_ALIGNED) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100326 next_position = it->statement_position();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000327 } else {
328 DCHECK(alignment == BREAK_POSITION_ALIGNED);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100329 next_position = it->position();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000330 }
331 if (position <= next_position && next_position - position < distance) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100332 closest_break = it->GetBreakLocation();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000333 distance = next_position - position;
334 // Check whether we can't get any closer.
335 if (distance == 0) break;
336 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100337 it->Next();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000338 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100339 return closest_break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000340}
341
342
343void BreakLocation::SetBreakPoint(Handle<Object> break_point_object) {
344 // If there is not already a real break point here patch code with debug
345 // break.
346 if (!HasBreakPoint()) SetDebugBreak();
347 DCHECK(IsDebugBreak() || IsDebuggerStatement());
348 // Set the break point information.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100349 DebugInfo::SetBreakPoint(debug_info_, code_offset_, position_,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000350 statement_position_, break_point_object);
351}
352
353
354void BreakLocation::ClearBreakPoint(Handle<Object> break_point_object) {
355 // Clear the break point information.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100356 DebugInfo::ClearBreakPoint(debug_info_, code_offset_, break_point_object);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000357 // If there are no more break points here remove the debug break.
358 if (!HasBreakPoint()) {
359 ClearDebugBreak();
360 DCHECK(!IsDebugBreak());
361 }
362}
363
364
365void BreakLocation::SetOneShot() {
366 // Debugger statement always calls debugger. No need to modify it.
367 if (IsDebuggerStatement()) return;
368
369 // If there is a real break point here no more to do.
370 if (HasBreakPoint()) {
371 DCHECK(IsDebugBreak());
372 return;
373 }
374
375 // Patch code with debug break.
376 SetDebugBreak();
377}
378
379
380void BreakLocation::ClearOneShot() {
381 // Debugger statement always calls debugger. No need to modify it.
382 if (IsDebuggerStatement()) return;
383
384 // If there is a real break point here no more to do.
385 if (HasBreakPoint()) {
386 DCHECK(IsDebugBreak());
387 return;
388 }
389
390 // Patch code removing debug break.
391 ClearDebugBreak();
392 DCHECK(!IsDebugBreak());
393}
394
395
396void BreakLocation::SetDebugBreak() {
397 // Debugger statement always calls debugger. No need to modify it.
398 if (IsDebuggerStatement()) return;
399
400 // If there is already a break point here just return. This might happen if
401 // the same code is flooded with break points twice. Flooding the same
402 // function twice might happen when stepping in a function with an exception
403 // handler as the handler and the function is the same.
404 if (IsDebugBreak()) return;
405
406 DCHECK(IsDebugBreakSlot());
Ben Murdoch097c5b22016-05-18 11:27:45 +0100407 if (abstract_code()->IsCode()) {
408 Code* code = abstract_code()->GetCode();
409 DCHECK(code->kind() == Code::FUNCTION);
410 Builtins* builtins = isolate()->builtins();
411 Handle<Code> target = IsReturn() ? builtins->Return_DebugBreak()
412 : builtins->Slot_DebugBreak();
413 Address pc = code->instruction_start() + code_offset();
414 DebugCodegen::PatchDebugBreakSlot(isolate(), pc, target);
415 } else {
416 BytecodeArray* bytecode_array = abstract_code()->GetBytecodeArray();
417 interpreter::Bytecode bytecode =
418 interpreter::Bytecodes::FromByte(bytecode_array->get(code_offset()));
419 interpreter::Bytecode debugbreak =
420 interpreter::Bytecodes::GetDebugBreak(bytecode);
421 bytecode_array->set(code_offset(),
422 interpreter::Bytecodes::ToByte(debugbreak));
423 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000424 DCHECK(IsDebugBreak());
425}
426
427
428void BreakLocation::ClearDebugBreak() {
429 // Debugger statement always calls debugger. No need to modify it.
430 if (IsDebuggerStatement()) return;
431
432 DCHECK(IsDebugBreakSlot());
Ben Murdoch097c5b22016-05-18 11:27:45 +0100433 if (abstract_code()->IsCode()) {
434 Code* code = abstract_code()->GetCode();
435 DCHECK(code->kind() == Code::FUNCTION);
436 Address pc = code->instruction_start() + code_offset();
437 DebugCodegen::ClearDebugBreakSlot(isolate(), pc);
438 } else {
439 BytecodeArray* bytecode_array = abstract_code()->GetBytecodeArray();
440 BytecodeArray* original = debug_info_->original_bytecode_array();
441 bytecode_array->set(code_offset(), original->get(code_offset()));
442 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000443 DCHECK(!IsDebugBreak());
444}
445
446
447bool BreakLocation::IsDebugBreak() const {
448 if (IsDebuggerStatement()) return false;
449 DCHECK(IsDebugBreakSlot());
Ben Murdoch097c5b22016-05-18 11:27:45 +0100450 if (abstract_code()->IsCode()) {
451 Code* code = abstract_code()->GetCode();
452 DCHECK(code->kind() == Code::FUNCTION);
453 Address pc = code->instruction_start() + code_offset();
454 return DebugCodegen::DebugBreakSlotIsPatched(pc);
455 } else {
456 BytecodeArray* bytecode_array = abstract_code()->GetBytecodeArray();
457 interpreter::Bytecode bytecode =
458 interpreter::Bytecodes::FromByte(bytecode_array->get(code_offset()));
459 return interpreter::Bytecodes::IsDebugBreak(bytecode);
460 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000461}
462
463
464Handle<Object> BreakLocation::BreakPointObjects() const {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100465 return debug_info_->GetBreakPointObjects(code_offset_);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000466}
467
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000468void DebugFeatureTracker::Track(DebugFeatureTracker::Feature feature) {
469 uint32_t mask = 1 << feature;
470 // Only count one sample per feature and isolate.
471 if (bitfield_ & mask) return;
472 isolate_->counters()->debug_feature_usage()->AddSample(feature);
473 bitfield_ |= mask;
474}
475
476
477// Threading support.
478void Debug::ThreadInit() {
479 thread_local_.break_count_ = 0;
480 thread_local_.break_id_ = 0;
481 thread_local_.break_frame_id_ = StackFrame::NO_ID;
482 thread_local_.last_step_action_ = StepNone;
483 thread_local_.last_statement_position_ = RelocInfo::kNoPosition;
484 thread_local_.last_fp_ = 0;
485 thread_local_.target_fp_ = 0;
486 thread_local_.step_in_enabled_ = false;
Ben Murdochda12d292016-06-02 14:46:10 +0100487 thread_local_.return_value_ = Handle<Object>();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000488 // TODO(isolates): frames_are_dropped_?
489 base::NoBarrier_Store(&thread_local_.current_debug_scope_,
490 static_cast<base::AtomicWord>(0));
491}
492
493
494char* Debug::ArchiveDebug(char* storage) {
495 char* to = storage;
496 MemCopy(to, reinterpret_cast<char*>(&thread_local_), sizeof(ThreadLocal));
497 ThreadInit();
498 return storage + ArchiveSpacePerThread();
499}
500
501
502char* Debug::RestoreDebug(char* storage) {
503 char* from = storage;
504 MemCopy(reinterpret_cast<char*>(&thread_local_), from, sizeof(ThreadLocal));
505 return storage + ArchiveSpacePerThread();
506}
507
508
509int Debug::ArchiveSpacePerThread() {
510 return sizeof(ThreadLocal);
511}
512
513
514DebugInfoListNode::DebugInfoListNode(DebugInfo* debug_info): next_(NULL) {
515 // Globalize the request debug info object and make it weak.
516 GlobalHandles* global_handles = debug_info->GetIsolate()->global_handles();
517 debug_info_ =
518 Handle<DebugInfo>::cast(global_handles->Create(debug_info)).location();
519}
520
521
522DebugInfoListNode::~DebugInfoListNode() {
523 if (debug_info_ == nullptr) return;
524 GlobalHandles::Destroy(reinterpret_cast<Object**>(debug_info_));
525 debug_info_ = nullptr;
526}
527
528
529bool Debug::Load() {
530 // Return if debugger is already loaded.
531 if (is_loaded()) return true;
532
533 // Bail out if we're already in the process of compiling the native
534 // JavaScript source code for the debugger.
535 if (is_suppressed_) return false;
536 SuppressDebug while_loading(this);
537
538 // Disable breakpoints and interrupts while compiling and running the
539 // debugger scripts including the context creation code.
540 DisableBreak disable(this, true);
541 PostponeInterruptsScope postpone(isolate_);
542
543 // Create the debugger context.
544 HandleScope scope(isolate_);
545 ExtensionConfiguration no_extensions;
546 Handle<Context> context = isolate_->bootstrapper()->CreateEnvironment(
547 MaybeHandle<JSGlobalProxy>(), v8::Local<ObjectTemplate>(), &no_extensions,
548 DEBUG_CONTEXT);
549
550 // Fail if no context could be created.
551 if (context.is_null()) return false;
552
553 debug_context_ = Handle<Context>::cast(
554 isolate_->global_handles()->Create(*context));
555
556 feature_tracker()->Track(DebugFeatureTracker::kActive);
557
558 return true;
559}
560
561
562void Debug::Unload() {
563 ClearAllBreakPoints();
564 ClearStepping();
565
566 // Return debugger is not loaded.
567 if (!is_loaded()) return;
568
569 // Clear debugger context global handle.
570 GlobalHandles::Destroy(Handle<Object>::cast(debug_context_).location());
571 debug_context_ = Handle<Context>();
572}
573
Ben Murdochda12d292016-06-02 14:46:10 +0100574void Debug::Break(JavaScriptFrame* frame) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000575 HandleScope scope(isolate_);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000576
577 // Initialize LiveEdit.
578 LiveEdit::InitializeThreadLocal(this);
579
580 // Just continue if breaks are disabled or debugger cannot be loaded.
581 if (break_disabled()) return;
582
583 // Enter the debugger.
584 DebugScope debug_scope(this);
585 if (debug_scope.failed()) return;
586
587 // Postpone interrupt during breakpoint processing.
588 PostponeInterruptsScope postpone(isolate_);
589
590 // Get the debug info (create it if it does not exist).
591 Handle<JSFunction> function(frame->function());
592 Handle<SharedFunctionInfo> shared(function->shared());
593 if (!EnsureDebugInfo(shared, function)) {
594 // Return if we failed to retrieve the debug info.
595 return;
596 }
597 Handle<DebugInfo> debug_info(shared->GetDebugInfo());
598
599 // Find the break location where execution has stopped.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100600 BreakLocation location = BreakLocation::FromFrame(debug_info, frame);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000601
602 // Find actual break points, if any, and trigger debug break event.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100603 Handle<Object> break_points_hit = CheckBreakPoints(&location);
604 if (!break_points_hit->IsUndefined()) {
605 // Clear all current stepping setup.
606 ClearStepping();
607 // Notify the debug event listeners.
608 OnDebugBreak(break_points_hit, false);
609 return;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000610 }
611
612 // No break point. Check for stepping.
613 StepAction step_action = last_step_action();
614 Address current_fp = frame->UnpaddedFP();
615 Address target_fp = thread_local_.target_fp_;
616 Address last_fp = thread_local_.last_fp_;
617
Ben Murdochda12d292016-06-02 14:46:10 +0100618 bool step_break = false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000619 switch (step_action) {
620 case StepNone:
621 return;
622 case StepOut:
623 // Step out has not reached the target frame yet.
624 if (current_fp < target_fp) return;
Ben Murdochda12d292016-06-02 14:46:10 +0100625 step_break = true;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000626 break;
627 case StepNext:
628 // Step next should not break in a deeper frame.
629 if (current_fp < target_fp) return;
Ben Murdochda12d292016-06-02 14:46:10 +0100630 // For step-next, a tail call is like a return and should break.
631 step_break = location.IsTailCall();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000632 // Fall through.
Ben Murdoch097c5b22016-05-18 11:27:45 +0100633 case StepIn: {
634 FrameSummary summary = GetFirstFrameSummary(frame);
635 int offset = summary.code_offset();
Ben Murdochda12d292016-06-02 14:46:10 +0100636 step_break = step_break || location.IsReturn() ||
637 (current_fp != last_fp) ||
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000638 (thread_local_.last_statement_position_ !=
Ben Murdoch097c5b22016-05-18 11:27:45 +0100639 location.abstract_code()->SourceStatementPosition(offset));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000640 break;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100641 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000642 case StepFrame:
643 step_break = current_fp != last_fp;
644 break;
645 }
646
647 // Clear all current stepping setup.
648 ClearStepping();
649
650 if (step_break) {
651 // Notify the debug event listeners.
652 OnDebugBreak(isolate_->factory()->undefined_value(), false);
653 } else {
654 // Re-prepare to continue.
655 PrepareStep(step_action);
656 }
657}
658
659
Ben Murdoch097c5b22016-05-18 11:27:45 +0100660// Find break point objects for this location, if any, and evaluate them.
661// Return an array of break point objects that evaluated true.
662Handle<Object> Debug::CheckBreakPoints(BreakLocation* location,
663 bool* has_break_points) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000664 Factory* factory = isolate_->factory();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100665 bool has_break_points_to_check =
666 break_points_active_ && location->HasBreakPoint();
667 if (has_break_points) *has_break_points = has_break_points_to_check;
668 if (!has_break_points_to_check) return factory->undefined_value();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000669
Ben Murdoch097c5b22016-05-18 11:27:45 +0100670 Handle<Object> break_point_objects = location->BreakPointObjects();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000671 // Count the number of break points hit. If there are multiple break points
672 // they are in a FixedArray.
673 Handle<FixedArray> break_points_hit;
674 int break_points_hit_count = 0;
675 DCHECK(!break_point_objects->IsUndefined());
676 if (break_point_objects->IsFixedArray()) {
677 Handle<FixedArray> array(FixedArray::cast(*break_point_objects));
678 break_points_hit = factory->NewFixedArray(array->length());
679 for (int i = 0; i < array->length(); i++) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100680 Handle<Object> break_point_object(array->get(i), isolate_);
681 if (CheckBreakPoint(break_point_object)) {
682 break_points_hit->set(break_points_hit_count++, *break_point_object);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000683 }
684 }
685 } else {
686 break_points_hit = factory->NewFixedArray(1);
687 if (CheckBreakPoint(break_point_objects)) {
688 break_points_hit->set(break_points_hit_count++, *break_point_objects);
689 }
690 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100691 if (break_points_hit_count == 0) return factory->undefined_value();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000692 Handle<JSArray> result = factory->NewJSArrayWithElements(break_points_hit);
693 result->set_length(Smi::FromInt(break_points_hit_count));
694 return result;
695}
696
697
Ben Murdoch097c5b22016-05-18 11:27:45 +0100698bool Debug::IsMutedAtCurrentLocation(JavaScriptFrame* frame) {
699 // A break location is considered muted if break locations on the current
700 // statement have at least one break point, and all of these break points
701 // evaluate to false. Aside from not triggering a debug break event at the
702 // break location, we also do not trigger one for debugger statements, nor
703 // an exception event on exception at this location.
704 Object* fun = frame->function();
705 if (!fun->IsJSFunction()) return false;
706 JSFunction* function = JSFunction::cast(fun);
707 if (!function->shared()->HasDebugInfo()) return false;
708 HandleScope scope(isolate_);
709 Handle<DebugInfo> debug_info(function->shared()->GetDebugInfo());
710 // Enter the debugger.
711 DebugScope debug_scope(this);
712 if (debug_scope.failed()) return false;
713 BreakLocation current_position = BreakLocation::FromFrame(debug_info, frame);
714 List<BreakLocation> break_locations;
715 BreakLocation::AllForStatementPosition(
716 debug_info, current_position.statement_position(), &break_locations);
717 bool has_break_points_at_all = false;
718 for (int i = 0; i < break_locations.length(); i++) {
719 bool has_break_points;
720 Handle<Object> check_result =
721 CheckBreakPoints(&break_locations[i], &has_break_points);
722 has_break_points_at_all |= has_break_points;
723 if (has_break_points && !check_result->IsUndefined()) return false;
724 }
725 return has_break_points_at_all;
726}
727
728
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000729MaybeHandle<Object> Debug::CallFunction(const char* name, int argc,
730 Handle<Object> args[]) {
731 PostponeInterruptsScope no_interrupts(isolate_);
732 AssertDebugContext();
Ben Murdochda12d292016-06-02 14:46:10 +0100733 Handle<JSReceiver> holder =
734 Handle<JSReceiver>::cast(isolate_->natives_utils_object());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000735 Handle<JSFunction> fun = Handle<JSFunction>::cast(
Ben Murdochda12d292016-06-02 14:46:10 +0100736 JSReceiver::GetProperty(isolate_, holder, name).ToHandleChecked());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000737 Handle<Object> undefined = isolate_->factory()->undefined_value();
738 return Execution::TryCall(isolate_, fun, undefined, argc, args);
739}
740
741
742// Check whether a single break point object is triggered.
743bool Debug::CheckBreakPoint(Handle<Object> break_point_object) {
744 Factory* factory = isolate_->factory();
745 HandleScope scope(isolate_);
746
747 // Ignore check if break point object is not a JSObject.
748 if (!break_point_object->IsJSObject()) return true;
749
750 // Get the break id as an object.
751 Handle<Object> break_id = factory->NewNumberFromInt(Debug::break_id());
752
753 // Call IsBreakPointTriggered.
754 Handle<Object> argv[] = { break_id, break_point_object };
755 Handle<Object> result;
756 if (!CallFunction("IsBreakPointTriggered", arraysize(argv), argv)
757 .ToHandle(&result)) {
758 return false;
759 }
760
761 // Return whether the break point is triggered.
762 return result->IsTrue();
763}
764
765
766bool Debug::SetBreakPoint(Handle<JSFunction> function,
767 Handle<Object> break_point_object,
768 int* source_position) {
769 HandleScope scope(isolate_);
770
771 // Make sure the function is compiled and has set up the debug info.
772 Handle<SharedFunctionInfo> shared(function->shared());
773 if (!EnsureDebugInfo(shared, function)) {
774 // Return if retrieving debug info failed.
775 return true;
776 }
777
778 Handle<DebugInfo> debug_info(shared->GetDebugInfo());
779 // Source positions starts with zero.
780 DCHECK(*source_position >= 0);
781
782 // Find the break point and change it.
783 BreakLocation location = BreakLocation::FromPosition(
784 debug_info, *source_position, STATEMENT_ALIGNED);
785 *source_position = location.statement_position();
786 location.SetBreakPoint(break_point_object);
787
788 feature_tracker()->Track(DebugFeatureTracker::kBreakPoint);
789
790 // At least one active break point now.
791 return debug_info->GetBreakPointCount() > 0;
792}
793
794
795bool Debug::SetBreakPointForScript(Handle<Script> script,
796 Handle<Object> break_point_object,
797 int* source_position,
798 BreakPositionAlignment alignment) {
799 HandleScope scope(isolate_);
800
801 // Obtain shared function info for the function.
802 Handle<Object> result =
803 FindSharedFunctionInfoInScript(script, *source_position);
804 if (result->IsUndefined()) return false;
805
806 // Make sure the function has set up the debug info.
807 Handle<SharedFunctionInfo> shared = Handle<SharedFunctionInfo>::cast(result);
808 if (!EnsureDebugInfo(shared, Handle<JSFunction>::null())) {
809 // Return if retrieving debug info failed.
810 return false;
811 }
812
813 // Find position within function. The script position might be before the
814 // source position of the first function.
815 int position;
816 if (shared->start_position() > *source_position) {
817 position = 0;
818 } else {
819 position = *source_position - shared->start_position();
820 }
821
822 Handle<DebugInfo> debug_info(shared->GetDebugInfo());
823 // Source positions starts with zero.
824 DCHECK(position >= 0);
825
826 // Find the break point and change it.
827 BreakLocation location =
828 BreakLocation::FromPosition(debug_info, position, alignment);
829 location.SetBreakPoint(break_point_object);
830
831 feature_tracker()->Track(DebugFeatureTracker::kBreakPoint);
832
833 position = (alignment == STATEMENT_ALIGNED) ? location.statement_position()
834 : location.position();
835
836 *source_position = position + shared->start_position();
837
838 // At least one active break point now.
839 DCHECK(debug_info->GetBreakPointCount() > 0);
840 return true;
841}
842
843
844void Debug::ClearBreakPoint(Handle<Object> break_point_object) {
845 HandleScope scope(isolate_);
846
847 DebugInfoListNode* node = debug_info_list_;
848 while (node != NULL) {
849 Handle<Object> result =
850 DebugInfo::FindBreakPointInfo(node->debug_info(), break_point_object);
851 if (!result->IsUndefined()) {
852 // Get information in the break point.
853 Handle<BreakPointInfo> break_point_info =
854 Handle<BreakPointInfo>::cast(result);
855 Handle<DebugInfo> debug_info = node->debug_info();
856
Ben Murdoch097c5b22016-05-18 11:27:45 +0100857 BreakLocation location = BreakLocation::FromCodeOffset(
858 debug_info, break_point_info->code_offset());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000859 location.ClearBreakPoint(break_point_object);
860
861 // If there are no more break points left remove the debug info for this
862 // function.
863 if (debug_info->GetBreakPointCount() == 0) {
864 RemoveDebugInfoAndClearFromShared(debug_info);
865 }
866
867 return;
868 }
869 node = node->next();
870 }
871}
872
873
874// Clear out all the debug break code. This is ONLY supposed to be used when
875// shutting down the debugger as it will leave the break point information in
876// DebugInfo even though the code is patched back to the non break point state.
877void Debug::ClearAllBreakPoints() {
878 for (DebugInfoListNode* node = debug_info_list_; node != NULL;
879 node = node->next()) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100880 for (base::SmartPointer<BreakLocation::Iterator> it(
881 BreakLocation::GetIterator(node->debug_info()));
882 !it->Done(); it->Next()) {
883 it->GetBreakLocation().ClearDebugBreak();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000884 }
885 }
886 // Remove all debug info.
887 while (debug_info_list_ != NULL) {
888 RemoveDebugInfoAndClearFromShared(debug_info_list_->debug_info());
889 }
890}
891
892
893void Debug::FloodWithOneShot(Handle<JSFunction> function,
894 BreakLocatorType type) {
895 // Debug utility functions are not subject to debugging.
896 if (function->native_context() == *debug_context()) return;
897
898 if (!function->shared()->IsSubjectToDebugging()) {
899 // Builtin functions are not subject to stepping, but need to be
900 // deoptimized, because optimized code does not check for debug
901 // step in at call sites.
902 Deoptimizer::DeoptimizeFunction(*function);
903 return;
904 }
905 // Make sure the function is compiled and has set up the debug info.
906 Handle<SharedFunctionInfo> shared(function->shared());
907 if (!EnsureDebugInfo(shared, function)) {
908 // Return if we failed to retrieve the debug info.
909 return;
910 }
911
912 // Flood the function with break points.
913 Handle<DebugInfo> debug_info(shared->GetDebugInfo());
Ben Murdoch097c5b22016-05-18 11:27:45 +0100914 for (base::SmartPointer<BreakLocation::Iterator> it(
915 BreakLocation::GetIterator(debug_info, type));
916 !it->Done(); it->Next()) {
917 it->GetBreakLocation().SetOneShot();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000918 }
919}
920
921
922void Debug::ChangeBreakOnException(ExceptionBreakType type, bool enable) {
923 if (type == BreakUncaughtException) {
924 break_on_uncaught_exception_ = enable;
925 } else {
926 break_on_exception_ = enable;
927 }
928}
929
930
931bool Debug::IsBreakOnException(ExceptionBreakType type) {
932 if (type == BreakUncaughtException) {
933 return break_on_uncaught_exception_;
934 } else {
935 return break_on_exception_;
936 }
937}
938
939
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000940void Debug::PrepareStepIn(Handle<JSFunction> function) {
941 if (!is_active()) return;
942 if (last_step_action() < StepIn) return;
943 if (in_debug_scope()) return;
944 if (thread_local_.step_in_enabled_) {
945 FloodWithOneShot(function);
946 }
947}
948
949
950void Debug::PrepareStepOnThrow() {
951 if (!is_active()) return;
952 if (last_step_action() == StepNone) return;
953 if (in_debug_scope()) return;
954
955 ClearOneShot();
956
957 // Iterate through the JavaScript stack looking for handlers.
958 JavaScriptFrameIterator it(isolate_);
959 while (!it.done()) {
960 JavaScriptFrame* frame = it.frame();
Ben Murdoch097c5b22016-05-18 11:27:45 +0100961 if (frame->LookupExceptionHandlerInTable(nullptr, nullptr) > 0) break;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000962 it.Advance();
963 }
964
965 // Find the closest Javascript frame we can flood with one-shots.
966 while (!it.done() &&
967 !it.frame()->function()->shared()->IsSubjectToDebugging()) {
968 it.Advance();
969 }
970
971 if (it.done()) return; // No suitable Javascript catch handler.
972
973 FloodWithOneShot(Handle<JSFunction>(it.frame()->function()));
974}
975
976
977void Debug::PrepareStep(StepAction step_action) {
978 HandleScope scope(isolate_);
979
980 DCHECK(in_debug_scope());
981
982 // Get the frame where the execution has stopped and skip the debug frame if
983 // any. The debug frame will only be present if execution was stopped due to
984 // hitting a break point. In other situations (e.g. unhandled exception) the
985 // debug frame is not present.
986 StackFrame::Id frame_id = break_frame_id();
987 // If there is no JavaScript stack don't do anything.
988 if (frame_id == StackFrame::NO_ID) return;
989
990 JavaScriptFrameIterator frames_it(isolate_, frame_id);
991 JavaScriptFrame* frame = frames_it.frame();
992
993 feature_tracker()->Track(DebugFeatureTracker::kStepping);
994
995 // Remember this step action and count.
996 thread_local_.last_step_action_ = step_action;
997 STATIC_ASSERT(StepFrame > StepIn);
998 thread_local_.step_in_enabled_ = (step_action >= StepIn);
999
1000 // If the function on the top frame is unresolved perform step out. This will
1001 // be the case when calling unknown function and having the debugger stopped
1002 // in an unhandled exception.
1003 if (!frame->function()->IsJSFunction()) {
1004 // Step out: Find the calling JavaScript frame and flood it with
1005 // breakpoints.
1006 frames_it.Advance();
1007 // Fill the function to return to with one-shot break points.
1008 JSFunction* function = frames_it.frame()->function();
1009 FloodWithOneShot(Handle<JSFunction>(function));
1010 return;
1011 }
1012
1013 // Get the debug info (create it if it does not exist).
1014 FrameSummary summary = GetFirstFrameSummary(frame);
1015 Handle<JSFunction> function(summary.function());
1016 Handle<SharedFunctionInfo> shared(function->shared());
1017 if (!EnsureDebugInfo(shared, function)) {
1018 // Return if ensuring debug info failed.
1019 return;
1020 }
1021
1022 Handle<DebugInfo> debug_info(shared->GetDebugInfo());
1023 // Refresh frame summary if the code has been recompiled for debugging.
Ben Murdoch097c5b22016-05-18 11:27:45 +01001024 if (AbstractCode::cast(shared->code()) != *summary.abstract_code()) {
1025 summary = GetFirstFrameSummary(frame);
1026 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001027
Ben Murdoch097c5b22016-05-18 11:27:45 +01001028 int call_offset =
1029 CallOffsetFromCodeOffset(summary.code_offset(), frame->is_interpreted());
1030 BreakLocation location =
1031 BreakLocation::FromCodeOffset(debug_info, call_offset);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001032
Ben Murdochda12d292016-06-02 14:46:10 +01001033 // Any step at a return is a step-out.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001034 if (location.IsReturn()) step_action = StepOut;
Ben Murdochda12d292016-06-02 14:46:10 +01001035 // A step-next at a tail call is a step-out.
1036 if (location.IsTailCall() && step_action == StepNext) step_action = StepOut;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001037
1038 thread_local_.last_statement_position_ =
Ben Murdoch097c5b22016-05-18 11:27:45 +01001039 debug_info->abstract_code()->SourceStatementPosition(
1040 summary.code_offset());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001041 thread_local_.last_fp_ = frame->UnpaddedFP();
1042
1043 switch (step_action) {
1044 case StepNone:
1045 UNREACHABLE();
1046 break;
1047 case StepOut:
1048 // Advance to caller frame.
1049 frames_it.Advance();
1050 // Skip native and extension functions on the stack.
1051 while (!frames_it.done() &&
1052 !frames_it.frame()->function()->shared()->IsSubjectToDebugging()) {
1053 // Builtin functions are not subject to stepping, but need to be
1054 // deoptimized to include checks for step-in at call sites.
1055 Deoptimizer::DeoptimizeFunction(frames_it.frame()->function());
1056 frames_it.Advance();
1057 }
1058 if (frames_it.done()) {
1059 // Stepping out to the embedder. Disable step-in to avoid stepping into
1060 // the next (unrelated) call that the embedder makes.
1061 thread_local_.step_in_enabled_ = false;
1062 } else {
1063 // Fill the caller function to return to with one-shot break points.
1064 Handle<JSFunction> caller_function(frames_it.frame()->function());
1065 FloodWithOneShot(caller_function);
1066 thread_local_.target_fp_ = frames_it.frame()->UnpaddedFP();
1067 }
1068 // Clear last position info. For stepping out it does not matter.
1069 thread_local_.last_statement_position_ = RelocInfo::kNoPosition;
1070 thread_local_.last_fp_ = 0;
1071 break;
1072 case StepNext:
1073 thread_local_.target_fp_ = frame->UnpaddedFP();
1074 FloodWithOneShot(function);
1075 break;
1076 case StepIn:
1077 FloodWithOneShot(function);
1078 break;
1079 case StepFrame:
1080 // No point in setting one-shot breaks at places where we are not about
1081 // to leave the current frame.
1082 FloodWithOneShot(function, CALLS_AND_RETURNS);
1083 break;
1084 }
1085}
1086
1087
1088// Simple function for returning the source positions for active break points.
1089Handle<Object> Debug::GetSourceBreakLocations(
1090 Handle<SharedFunctionInfo> shared,
1091 BreakPositionAlignment position_alignment) {
1092 Isolate* isolate = shared->GetIsolate();
1093 Heap* heap = isolate->heap();
1094 if (!shared->HasDebugInfo()) {
1095 return Handle<Object>(heap->undefined_value(), isolate);
1096 }
1097 Handle<DebugInfo> debug_info(shared->GetDebugInfo());
1098 if (debug_info->GetBreakPointCount() == 0) {
1099 return Handle<Object>(heap->undefined_value(), isolate);
1100 }
1101 Handle<FixedArray> locations =
1102 isolate->factory()->NewFixedArray(debug_info->GetBreakPointCount());
1103 int count = 0;
1104 for (int i = 0; i < debug_info->break_points()->length(); ++i) {
1105 if (!debug_info->break_points()->get(i)->IsUndefined()) {
1106 BreakPointInfo* break_point_info =
1107 BreakPointInfo::cast(debug_info->break_points()->get(i));
1108 int break_points = break_point_info->GetBreakPointCount();
1109 if (break_points == 0) continue;
1110 Smi* position = NULL;
1111 switch (position_alignment) {
1112 case STATEMENT_ALIGNED:
1113 position = Smi::FromInt(break_point_info->statement_position());
1114 break;
1115 case BREAK_POSITION_ALIGNED:
1116 position = Smi::FromInt(break_point_info->source_position());
1117 break;
1118 }
1119 for (int j = 0; j < break_points; ++j) locations->set(count++, position);
1120 }
1121 }
1122 return locations;
1123}
1124
1125
1126void Debug::ClearStepping() {
1127 // Clear the various stepping setup.
1128 ClearOneShot();
1129
1130 thread_local_.last_step_action_ = StepNone;
1131 thread_local_.step_in_enabled_ = false;
1132 thread_local_.last_statement_position_ = RelocInfo::kNoPosition;
1133 thread_local_.last_fp_ = 0;
1134 thread_local_.target_fp_ = 0;
1135}
1136
1137
1138// Clears all the one-shot break points that are currently set. Normally this
1139// function is called each time a break point is hit as one shot break points
1140// are used to support stepping.
1141void Debug::ClearOneShot() {
1142 // The current implementation just runs through all the breakpoints. When the
1143 // last break point for a function is removed that function is automatically
1144 // removed from the list.
1145 for (DebugInfoListNode* node = debug_info_list_; node != NULL;
1146 node = node->next()) {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001147 for (base::SmartPointer<BreakLocation::Iterator> it(
1148 BreakLocation::GetIterator(node->debug_info()));
1149 !it->Done(); it->Next()) {
1150 it->GetBreakLocation().ClearOneShot();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001151 }
1152 }
1153}
1154
1155
1156void Debug::EnableStepIn() {
1157 STATIC_ASSERT(StepFrame > StepIn);
1158 thread_local_.step_in_enabled_ = (last_step_action() >= StepIn);
1159}
1160
1161
1162bool MatchingCodeTargets(Code* target1, Code* target2) {
1163 if (target1 == target2) return true;
1164 if (target1->kind() != target2->kind()) return false;
1165 return target1->is_handler() || target1->is_inline_cache_stub();
1166}
1167
1168
1169// Count the number of calls before the current frame PC to find the
1170// corresponding PC in the newly recompiled code.
1171static Address ComputeNewPcForRedirect(Code* new_code, Code* old_code,
1172 Address old_pc) {
1173 DCHECK_EQ(old_code->kind(), Code::FUNCTION);
1174 DCHECK_EQ(new_code->kind(), Code::FUNCTION);
1175 DCHECK(new_code->has_debug_break_slots());
1176 static const int mask = RelocInfo::kCodeTargetMask;
1177
1178 // Find the target of the current call.
1179 Code* target = NULL;
1180 intptr_t delta = 0;
1181 for (RelocIterator it(old_code, mask); !it.done(); it.next()) {
1182 RelocInfo* rinfo = it.rinfo();
1183 Address current_pc = rinfo->pc();
1184 // The frame PC is behind the call instruction by the call instruction size.
1185 if (current_pc > old_pc) break;
1186 delta = old_pc - current_pc;
1187 target = Code::GetCodeFromTargetAddress(rinfo->target_address());
1188 }
1189
1190 // Count the number of calls to the same target before the current call.
1191 int index = 0;
1192 for (RelocIterator it(old_code, mask); !it.done(); it.next()) {
1193 RelocInfo* rinfo = it.rinfo();
1194 Address current_pc = rinfo->pc();
1195 if (current_pc > old_pc) break;
1196 Code* current = Code::GetCodeFromTargetAddress(rinfo->target_address());
1197 if (MatchingCodeTargets(target, current)) index++;
1198 }
1199
1200 DCHECK(index > 0);
1201
1202 // Repeat the count on the new code to find corresponding call.
1203 for (RelocIterator it(new_code, mask); !it.done(); it.next()) {
1204 RelocInfo* rinfo = it.rinfo();
1205 Code* current = Code::GetCodeFromTargetAddress(rinfo->target_address());
1206 if (MatchingCodeTargets(target, current)) index--;
1207 if (index == 0) return rinfo->pc() + delta;
1208 }
1209
1210 UNREACHABLE();
1211 return NULL;
1212}
1213
1214
1215// Count the number of continuations at which the current pc offset is at.
1216static int ComputeContinuationIndexFromPcOffset(Code* code, int pc_offset) {
1217 DCHECK_EQ(code->kind(), Code::FUNCTION);
1218 Address pc = code->instruction_start() + pc_offset;
1219 int mask = RelocInfo::ModeMask(RelocInfo::GENERATOR_CONTINUATION);
1220 int index = 0;
1221 for (RelocIterator it(code, mask); !it.done(); it.next()) {
1222 index++;
1223 RelocInfo* rinfo = it.rinfo();
1224 Address current_pc = rinfo->pc();
1225 if (current_pc == pc) break;
1226 DCHECK(current_pc < pc);
1227 }
1228 return index;
1229}
1230
1231
1232// Find the pc offset for the given continuation index.
1233static int ComputePcOffsetFromContinuationIndex(Code* code, int index) {
1234 DCHECK_EQ(code->kind(), Code::FUNCTION);
1235 DCHECK(code->has_debug_break_slots());
1236 int mask = RelocInfo::ModeMask(RelocInfo::GENERATOR_CONTINUATION);
1237 RelocIterator it(code, mask);
1238 for (int i = 1; i < index; i++) it.next();
1239 return static_cast<int>(it.rinfo()->pc() - code->instruction_start());
1240}
1241
1242
1243class RedirectActiveFunctions : public ThreadVisitor {
1244 public:
1245 explicit RedirectActiveFunctions(SharedFunctionInfo* shared)
1246 : shared_(shared) {
1247 DCHECK(shared->HasDebugCode());
1248 }
1249
1250 void VisitThread(Isolate* isolate, ThreadLocalTop* top) {
1251 for (JavaScriptFrameIterator it(isolate, top); !it.done(); it.Advance()) {
1252 JavaScriptFrame* frame = it.frame();
1253 JSFunction* function = frame->function();
1254 if (frame->is_optimized()) continue;
1255 if (!function->Inlines(shared_)) continue;
1256
Ben Murdoch097c5b22016-05-18 11:27:45 +01001257 if (frame->is_interpreted()) {
1258 InterpretedFrame* interpreted_frame =
1259 reinterpret_cast<InterpretedFrame*>(frame);
1260 BytecodeArray* debug_copy =
1261 shared_->GetDebugInfo()->abstract_code()->GetBytecodeArray();
1262 interpreted_frame->PatchBytecodeArray(debug_copy);
1263 continue;
1264 }
1265
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001266 Code* frame_code = frame->LookupCode();
1267 DCHECK(frame_code->kind() == Code::FUNCTION);
1268 if (frame_code->has_debug_break_slots()) continue;
1269
1270 Code* new_code = function->shared()->code();
1271 Address old_pc = frame->pc();
1272 Address new_pc = ComputeNewPcForRedirect(new_code, frame_code, old_pc);
1273
1274 if (FLAG_trace_deopt) {
1275 PrintF("Replacing pc for debugging: %08" V8PRIxPTR " => %08" V8PRIxPTR
1276 "\n",
1277 reinterpret_cast<intptr_t>(old_pc),
1278 reinterpret_cast<intptr_t>(new_pc));
1279 }
1280
1281 if (FLAG_enable_embedded_constant_pool) {
1282 // Update constant pool pointer for new code.
1283 frame->set_constant_pool(new_code->constant_pool());
1284 }
1285
1286 // Patch the return address to return into the code with
1287 // debug break slots.
1288 frame->set_pc(new_pc);
1289 }
1290 }
1291
1292 private:
1293 SharedFunctionInfo* shared_;
1294 DisallowHeapAllocation no_gc_;
1295};
1296
1297
1298bool Debug::PrepareFunctionForBreakPoints(Handle<SharedFunctionInfo> shared) {
1299 DCHECK(shared->is_compiled());
1300
1301 if (isolate_->concurrent_recompilation_enabled()) {
1302 isolate_->optimizing_compile_dispatcher()->Flush();
1303 }
1304
1305 List<Handle<JSFunction> > functions;
1306 List<Handle<JSGeneratorObject> > suspended_generators;
1307
1308 // Flush all optimized code maps. Note that the below heap iteration does not
1309 // cover this, because the given function might have been inlined into code
1310 // for which no JSFunction exists.
1311 {
1312 SharedFunctionInfo::Iterator iterator(isolate_);
1313 while (SharedFunctionInfo* shared = iterator.Next()) {
1314 if (!shared->OptimizedCodeMapIsCleared()) {
1315 shared->ClearOptimizedCodeMap();
1316 }
1317 }
1318 }
1319
1320 // Make sure we abort incremental marking.
1321 isolate_->heap()->CollectAllGarbage(Heap::kMakeHeapIterableMask,
1322 "prepare for break points");
Ben Murdochda12d292016-06-02 14:46:10 +01001323
Ben Murdoch097c5b22016-05-18 11:27:45 +01001324 bool is_interpreted = shared->HasBytecodeArray();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001325
1326 {
Ben Murdoch097c5b22016-05-18 11:27:45 +01001327 // TODO(yangguo): with bytecode, we still walk the heap to find all
1328 // optimized code for the function to deoptimize. We can probably be
1329 // smarter here and avoid the heap walk.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001330 HeapIterator iterator(isolate_->heap());
1331 HeapObject* obj;
Ben Murdoch097c5b22016-05-18 11:27:45 +01001332 bool include_generators = !is_interpreted && shared->is_generator();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001333
1334 while ((obj = iterator.next())) {
1335 if (obj->IsJSFunction()) {
1336 JSFunction* function = JSFunction::cast(obj);
1337 if (!function->Inlines(*shared)) continue;
1338 if (function->code()->kind() == Code::OPTIMIZED_FUNCTION) {
1339 Deoptimizer::DeoptimizeFunction(function);
1340 }
Ben Murdoch097c5b22016-05-18 11:27:45 +01001341 if (is_interpreted) continue;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001342 if (function->shared() == *shared) functions.Add(handle(function));
1343 } else if (include_generators && obj->IsJSGeneratorObject()) {
1344 JSGeneratorObject* generator_obj = JSGeneratorObject::cast(obj);
1345 if (!generator_obj->is_suspended()) continue;
1346 JSFunction* function = generator_obj->function();
1347 if (!function->Inlines(*shared)) continue;
1348 int pc_offset = generator_obj->continuation();
1349 int index =
1350 ComputeContinuationIndexFromPcOffset(function->code(), pc_offset);
1351 generator_obj->set_continuation(index);
1352 suspended_generators.Add(handle(generator_obj));
1353 }
1354 }
1355 }
1356
Ben Murdoch097c5b22016-05-18 11:27:45 +01001357 // We do not need to replace code to debug bytecode.
1358 DCHECK(!is_interpreted || functions.length() == 0);
1359 DCHECK(!is_interpreted || suspended_generators.length() == 0);
1360
1361 // We do not need to recompile to debug bytecode.
1362 if (!is_interpreted && !shared->HasDebugCode()) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001363 DCHECK(functions.length() > 0);
1364 if (!Compiler::CompileDebugCode(functions.first())) return false;
1365 }
1366
1367 for (Handle<JSFunction> const function : functions) {
1368 function->ReplaceCode(shared->code());
1369 }
1370
1371 for (Handle<JSGeneratorObject> const generator_obj : suspended_generators) {
1372 int index = generator_obj->continuation();
1373 int pc_offset = ComputePcOffsetFromContinuationIndex(shared->code(), index);
1374 generator_obj->set_continuation(pc_offset);
1375 }
1376
1377 // Update PCs on the stack to point to recompiled code.
1378 RedirectActiveFunctions redirect_visitor(*shared);
1379 redirect_visitor.VisitThread(isolate_, isolate_->thread_local_top());
1380 isolate_->thread_manager()->IterateArchivedThreads(&redirect_visitor);
1381
1382 return true;
1383}
1384
1385
1386class SharedFunctionInfoFinder {
1387 public:
1388 explicit SharedFunctionInfoFinder(int target_position)
1389 : current_candidate_(NULL),
1390 current_candidate_closure_(NULL),
1391 current_start_position_(RelocInfo::kNoPosition),
1392 target_position_(target_position) {}
1393
1394 void NewCandidate(SharedFunctionInfo* shared, JSFunction* closure = NULL) {
1395 if (!shared->IsSubjectToDebugging()) return;
1396 int start_position = shared->function_token_position();
1397 if (start_position == RelocInfo::kNoPosition) {
1398 start_position = shared->start_position();
1399 }
1400
1401 if (start_position > target_position_) return;
1402 if (target_position_ > shared->end_position()) return;
1403
1404 if (current_candidate_ != NULL) {
1405 if (current_start_position_ == start_position &&
1406 shared->end_position() == current_candidate_->end_position()) {
1407 // If we already have a matching closure, do not throw it away.
1408 if (current_candidate_closure_ != NULL && closure == NULL) return;
1409 // If a top-level function contains only one function
1410 // declaration the source for the top-level and the function
1411 // is the same. In that case prefer the non top-level function.
1412 if (!current_candidate_->is_toplevel() && shared->is_toplevel()) return;
1413 } else if (start_position < current_start_position_ ||
1414 current_candidate_->end_position() < shared->end_position()) {
1415 return;
1416 }
1417 }
1418
1419 current_start_position_ = start_position;
1420 current_candidate_ = shared;
1421 current_candidate_closure_ = closure;
1422 }
1423
1424 SharedFunctionInfo* Result() { return current_candidate_; }
1425
1426 JSFunction* ResultClosure() { return current_candidate_closure_; }
1427
1428 private:
1429 SharedFunctionInfo* current_candidate_;
1430 JSFunction* current_candidate_closure_;
1431 int current_start_position_;
1432 int target_position_;
1433 DisallowHeapAllocation no_gc_;
1434};
1435
1436
1437// We need to find a SFI for a literal that may not yet have been compiled yet,
1438// and there may not be a JSFunction referencing it. Find the SFI closest to
1439// the given position, compile it to reveal possible inner SFIs and repeat.
1440// While we are at this, also ensure code with debug break slots so that we do
1441// not have to compile a SFI without JSFunction, which is paifu for those that
1442// cannot be compiled without context (need to find outer compilable SFI etc.)
1443Handle<Object> Debug::FindSharedFunctionInfoInScript(Handle<Script> script,
1444 int position) {
1445 for (int iteration = 0;; iteration++) {
1446 // Go through all shared function infos associated with this script to
1447 // find the inner most function containing this position.
1448 // If there is no shared function info for this script at all, there is
1449 // no point in looking for it by walking the heap.
1450 if (!script->shared_function_infos()->IsWeakFixedArray()) break;
1451
1452 SharedFunctionInfo* shared;
1453 {
1454 SharedFunctionInfoFinder finder(position);
1455 WeakFixedArray::Iterator iterator(script->shared_function_infos());
1456 SharedFunctionInfo* candidate;
1457 while ((candidate = iterator.Next<SharedFunctionInfo>())) {
1458 finder.NewCandidate(candidate);
1459 }
1460 shared = finder.Result();
1461 if (shared == NULL) break;
1462 // We found it if it's already compiled and has debug code.
1463 if (shared->HasDebugCode()) {
1464 Handle<SharedFunctionInfo> shared_handle(shared);
1465 // If the iteration count is larger than 1, we had to compile the outer
1466 // function in order to create this shared function info. So there can
1467 // be no JSFunction referencing it. We can anticipate creating a debug
1468 // info while bypassing PrepareFunctionForBreakpoints.
1469 if (iteration > 1) {
1470 AllowHeapAllocation allow_before_return;
1471 CreateDebugInfo(shared_handle);
1472 }
1473 return shared_handle;
1474 }
1475 }
1476 // If not, compile to reveal inner functions, if possible.
1477 if (shared->allows_lazy_compilation_without_context()) {
1478 HandleScope scope(isolate_);
1479 if (!Compiler::CompileDebugCode(handle(shared))) break;
1480 continue;
1481 }
1482
1483 // If not possible, comb the heap for the best suitable compile target.
1484 JSFunction* closure;
1485 {
1486 HeapIterator it(isolate_->heap());
1487 SharedFunctionInfoFinder finder(position);
1488 while (HeapObject* object = it.next()) {
1489 JSFunction* candidate_closure = NULL;
1490 SharedFunctionInfo* candidate = NULL;
1491 if (object->IsJSFunction()) {
1492 candidate_closure = JSFunction::cast(object);
1493 candidate = candidate_closure->shared();
1494 } else if (object->IsSharedFunctionInfo()) {
1495 candidate = SharedFunctionInfo::cast(object);
1496 if (!candidate->allows_lazy_compilation_without_context()) continue;
1497 } else {
1498 continue;
1499 }
1500 if (candidate->script() == *script) {
1501 finder.NewCandidate(candidate, candidate_closure);
1502 }
1503 }
1504 closure = finder.ResultClosure();
1505 shared = finder.Result();
1506 }
1507 if (shared == NULL) break;
1508 HandleScope scope(isolate_);
1509 if (closure == NULL) {
1510 if (!Compiler::CompileDebugCode(handle(shared))) break;
1511 } else {
1512 if (!Compiler::CompileDebugCode(handle(closure))) break;
1513 }
1514 }
1515 return isolate_->factory()->undefined_value();
1516}
1517
1518
1519// Ensures the debug information is present for shared.
1520bool Debug::EnsureDebugInfo(Handle<SharedFunctionInfo> shared,
1521 Handle<JSFunction> function) {
1522 if (!shared->IsSubjectToDebugging()) return false;
1523
1524 // Return if we already have the debug info for shared.
1525 if (shared->HasDebugInfo()) return true;
1526
1527 if (function.is_null()) {
1528 DCHECK(shared->HasDebugCode());
Ben Murdochda12d292016-06-02 14:46:10 +01001529 } else if (!Compiler::Compile(function, Compiler::CLEAR_EXCEPTION)) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001530 return false;
1531 }
1532
Ben Murdoch097c5b22016-05-18 11:27:45 +01001533 if (shared->HasBytecodeArray()) {
1534 // To prepare bytecode for debugging, we already need to have the debug
1535 // info (containing the debug copy) upfront, but since we do not recompile,
1536 // preparing for break points cannot fail.
1537 CreateDebugInfo(shared);
1538 CHECK(PrepareFunctionForBreakPoints(shared));
1539 } else {
1540 if (!PrepareFunctionForBreakPoints(shared)) return false;
1541 CreateDebugInfo(shared);
1542 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001543 return true;
1544}
1545
1546
1547void Debug::CreateDebugInfo(Handle<SharedFunctionInfo> shared) {
1548 // Create the debug info object.
1549 DCHECK(shared->HasDebugCode());
1550 Handle<DebugInfo> debug_info = isolate_->factory()->NewDebugInfo(shared);
1551
1552 // Add debug info to the list.
1553 DebugInfoListNode* node = new DebugInfoListNode(*debug_info);
1554 node->set_next(debug_info_list_);
1555 debug_info_list_ = node;
1556}
1557
1558
1559void Debug::RemoveDebugInfoAndClearFromShared(Handle<DebugInfo> debug_info) {
1560 HandleScope scope(isolate_);
1561 Handle<SharedFunctionInfo> shared(debug_info->shared());
1562
1563 DCHECK_NOT_NULL(debug_info_list_);
1564 // Run through the debug info objects to find this one and remove it.
1565 DebugInfoListNode* prev = NULL;
1566 DebugInfoListNode* current = debug_info_list_;
1567 while (current != NULL) {
1568 if (current->debug_info().is_identical_to(debug_info)) {
1569 // Unlink from list. If prev is NULL we are looking at the first element.
1570 if (prev == NULL) {
1571 debug_info_list_ = current->next();
1572 } else {
1573 prev->set_next(current->next());
1574 }
1575 delete current;
Ben Murdoch097c5b22016-05-18 11:27:45 +01001576 shared->set_debug_info(DebugInfo::uninitialized());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001577 return;
1578 }
1579 // Move to next in list.
1580 prev = current;
1581 current = current->next();
1582 }
1583
1584 UNREACHABLE();
1585}
1586
Ben Murdochda12d292016-06-02 14:46:10 +01001587void Debug::SetAfterBreakTarget(JavaScriptFrame* frame) {
1588 after_break_target_ = NULL;
1589 if (!LiveEdit::SetAfterBreakTarget(this)) {
1590 // Continue just after the slot.
1591 after_break_target_ = frame->pc();
Ben Murdoch097c5b22016-05-18 11:27:45 +01001592 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001593}
1594
1595
1596bool Debug::IsBreakAtReturn(JavaScriptFrame* frame) {
1597 HandleScope scope(isolate_);
1598
1599 // Get the executing function in which the debug break occurred.
1600 Handle<JSFunction> function(JSFunction::cast(frame->function()));
1601 Handle<SharedFunctionInfo> shared(function->shared());
1602
1603 // With no debug info there are no break points, so we can't be at a return.
1604 if (!shared->HasDebugInfo()) return false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001605
Ben Murdoch097c5b22016-05-18 11:27:45 +01001606 DCHECK(!frame->is_optimized());
1607 FrameSummary summary = GetFirstFrameSummary(frame);
1608
1609 Handle<DebugInfo> debug_info(shared->GetDebugInfo());
1610 BreakLocation location =
1611 BreakLocation::FromCodeOffset(debug_info, summary.code_offset());
Ben Murdochda12d292016-06-02 14:46:10 +01001612 return location.IsReturn() || location.IsTailCall();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001613}
1614
1615
1616void Debug::FramesHaveBeenDropped(StackFrame::Id new_break_frame_id,
1617 LiveEdit::FrameDropMode mode) {
1618 if (mode != LiveEdit::CURRENTLY_SET_MODE) {
1619 thread_local_.frame_drop_mode_ = mode;
1620 }
1621 thread_local_.break_frame_id_ = new_break_frame_id;
1622}
1623
1624
1625bool Debug::IsDebugGlobal(JSGlobalObject* global) {
1626 return is_loaded() && global == debug_context()->global_object();
1627}
1628
1629
1630void Debug::ClearMirrorCache() {
1631 PostponeInterruptsScope postpone(isolate_);
1632 HandleScope scope(isolate_);
1633 CallFunction("ClearMirrorCache", 0, NULL);
1634}
1635
1636
1637Handle<FixedArray> Debug::GetLoadedScripts() {
1638 isolate_->heap()->CollectAllGarbage();
1639 Factory* factory = isolate_->factory();
1640 if (!factory->script_list()->IsWeakFixedArray()) {
1641 return factory->empty_fixed_array();
1642 }
1643 Handle<WeakFixedArray> array =
1644 Handle<WeakFixedArray>::cast(factory->script_list());
1645 Handle<FixedArray> results = factory->NewFixedArray(array->Length());
1646 int length = 0;
1647 {
1648 Script::Iterator iterator(isolate_);
1649 Script* script;
1650 while ((script = iterator.Next())) {
1651 if (script->HasValidSource()) results->set(length++, script);
1652 }
1653 }
1654 results->Shrink(length);
1655 return results;
1656}
1657
1658
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001659void Debug::RecordEvalCaller(Handle<Script> script) {
1660 script->set_compilation_type(Script::COMPILATION_TYPE_EVAL);
1661 // For eval scripts add information on the function from which eval was
1662 // called.
1663 StackTraceFrameIterator it(script->GetIsolate());
1664 if (!it.done()) {
1665 script->set_eval_from_shared(it.frame()->function()->shared());
1666 Code* code = it.frame()->LookupCode();
1667 int offset = static_cast<int>(
1668 it.frame()->pc() - code->instruction_start());
1669 script->set_eval_from_instructions_offset(offset);
1670 }
1671}
1672
1673
1674MaybeHandle<Object> Debug::MakeExecutionState() {
1675 // Create the execution state object.
1676 Handle<Object> argv[] = { isolate_->factory()->NewNumberFromInt(break_id()) };
1677 return CallFunction("MakeExecutionState", arraysize(argv), argv);
1678}
1679
1680
1681MaybeHandle<Object> Debug::MakeBreakEvent(Handle<Object> break_points_hit) {
1682 // Create the new break event object.
1683 Handle<Object> argv[] = { isolate_->factory()->NewNumberFromInt(break_id()),
1684 break_points_hit };
1685 return CallFunction("MakeBreakEvent", arraysize(argv), argv);
1686}
1687
1688
1689MaybeHandle<Object> Debug::MakeExceptionEvent(Handle<Object> exception,
1690 bool uncaught,
1691 Handle<Object> promise) {
1692 // Create the new exception event object.
1693 Handle<Object> argv[] = { isolate_->factory()->NewNumberFromInt(break_id()),
1694 exception,
1695 isolate_->factory()->ToBoolean(uncaught),
1696 promise };
1697 return CallFunction("MakeExceptionEvent", arraysize(argv), argv);
1698}
1699
1700
1701MaybeHandle<Object> Debug::MakeCompileEvent(Handle<Script> script,
1702 v8::DebugEvent type) {
1703 // Create the compile event object.
1704 Handle<Object> script_wrapper = Script::GetWrapper(script);
1705 Handle<Object> argv[] = { script_wrapper,
1706 isolate_->factory()->NewNumberFromInt(type) };
1707 return CallFunction("MakeCompileEvent", arraysize(argv), argv);
1708}
1709
1710
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001711MaybeHandle<Object> Debug::MakeAsyncTaskEvent(Handle<JSObject> task_event) {
1712 // Create the async task event object.
1713 Handle<Object> argv[] = { task_event };
1714 return CallFunction("MakeAsyncTaskEvent", arraysize(argv), argv);
1715}
1716
1717
1718void Debug::OnThrow(Handle<Object> exception) {
1719 if (in_debug_scope() || ignore_events()) return;
1720 PrepareStepOnThrow();
1721 // Temporarily clear any scheduled_exception to allow evaluating
1722 // JavaScript from the debug event handler.
1723 HandleScope scope(isolate_);
1724 Handle<Object> scheduled_exception;
1725 if (isolate_->has_scheduled_exception()) {
1726 scheduled_exception = handle(isolate_->scheduled_exception(), isolate_);
1727 isolate_->clear_scheduled_exception();
1728 }
1729 OnException(exception, isolate_->GetPromiseOnStackOnThrow());
1730 if (!scheduled_exception.is_null()) {
1731 isolate_->thread_local_top()->scheduled_exception_ = *scheduled_exception;
1732 }
1733}
1734
1735
1736void Debug::OnPromiseReject(Handle<JSObject> promise, Handle<Object> value) {
1737 if (in_debug_scope() || ignore_events()) return;
1738 HandleScope scope(isolate_);
1739 // Check whether the promise has been marked as having triggered a message.
1740 Handle<Symbol> key = isolate_->factory()->promise_debug_marker_symbol();
1741 if (JSReceiver::GetDataProperty(promise, key)->IsUndefined()) {
1742 OnException(value, promise);
1743 }
1744}
1745
1746
1747MaybeHandle<Object> Debug::PromiseHasUserDefinedRejectHandler(
1748 Handle<JSObject> promise) {
1749 Handle<JSFunction> fun = isolate_->promise_has_user_defined_reject_handler();
1750 return Execution::Call(isolate_, fun, promise, 0, NULL);
1751}
1752
1753
1754void Debug::OnException(Handle<Object> exception, Handle<Object> promise) {
1755 // In our prediction, try-finally is not considered to catch.
1756 Isolate::CatchType catch_type = isolate_->PredictExceptionCatcher();
1757 bool uncaught = (catch_type == Isolate::NOT_CAUGHT);
1758 if (promise->IsJSObject()) {
1759 Handle<JSObject> jspromise = Handle<JSObject>::cast(promise);
1760 // Mark the promise as already having triggered a message.
1761 Handle<Symbol> key = isolate_->factory()->promise_debug_marker_symbol();
1762 JSObject::SetProperty(jspromise, key, key, STRICT).Assert();
1763 // Check whether the promise reject is considered an uncaught exception.
1764 Handle<Object> has_reject_handler;
1765 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
1766 isolate_, has_reject_handler,
1767 PromiseHasUserDefinedRejectHandler(jspromise), /* void */);
1768 uncaught = has_reject_handler->IsFalse();
1769 }
1770 // Bail out if exception breaks are not active
1771 if (uncaught) {
1772 // Uncaught exceptions are reported by either flags.
1773 if (!(break_on_uncaught_exception_ || break_on_exception_)) return;
1774 } else {
1775 // Caught exceptions are reported is activated.
1776 if (!break_on_exception_) return;
1777 }
1778
Ben Murdoch097c5b22016-05-18 11:27:45 +01001779 {
1780 // Check whether the break location is muted.
1781 JavaScriptFrameIterator it(isolate_);
1782 if (!it.done() && IsMutedAtCurrentLocation(it.frame())) return;
1783 }
1784
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001785 DebugScope debug_scope(this);
1786 if (debug_scope.failed()) return;
1787
1788 // Create the event data object.
1789 Handle<Object> event_data;
1790 // Bail out and don't call debugger if exception.
1791 if (!MakeExceptionEvent(
1792 exception, uncaught, promise).ToHandle(&event_data)) {
1793 return;
1794 }
1795
1796 // Process debug event.
1797 ProcessDebugEvent(v8::Exception, Handle<JSObject>::cast(event_data), false);
1798 // Return to continue execution from where the exception was thrown.
1799}
1800
1801
Ben Murdoch097c5b22016-05-18 11:27:45 +01001802void Debug::OnDebugBreak(Handle<Object> break_points_hit, bool auto_continue) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001803 // The caller provided for DebugScope.
1804 AssertDebugContext();
1805 // Bail out if there is no listener for this event
1806 if (ignore_events()) return;
1807
Ben Murdochda12d292016-06-02 14:46:10 +01001808#ifdef DEBUG
1809 PrintBreakLocation();
1810#endif // DEBUG
1811
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001812 HandleScope scope(isolate_);
1813 // Create the event data object.
1814 Handle<Object> event_data;
1815 // Bail out and don't call debugger if exception.
1816 if (!MakeBreakEvent(break_points_hit).ToHandle(&event_data)) return;
1817
1818 // Process debug event.
1819 ProcessDebugEvent(v8::Break,
1820 Handle<JSObject>::cast(event_data),
1821 auto_continue);
1822}
1823
1824
1825void Debug::OnCompileError(Handle<Script> script) {
1826 ProcessCompileEvent(v8::CompileError, script);
1827}
1828
1829
1830void Debug::OnBeforeCompile(Handle<Script> script) {
1831 ProcessCompileEvent(v8::BeforeCompile, script);
1832}
1833
1834
1835// Handle debugger actions when a new script is compiled.
1836void Debug::OnAfterCompile(Handle<Script> script) {
1837 ProcessCompileEvent(v8::AfterCompile, script);
1838}
1839
1840
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001841void Debug::OnAsyncTaskEvent(Handle<JSObject> data) {
1842 if (in_debug_scope() || ignore_events()) return;
1843
1844 HandleScope scope(isolate_);
1845 DebugScope debug_scope(this);
1846 if (debug_scope.failed()) return;
1847
1848 // Create the script collected state object.
1849 Handle<Object> event_data;
1850 // Bail out and don't call debugger if exception.
1851 if (!MakeAsyncTaskEvent(data).ToHandle(&event_data)) return;
1852
1853 // Process debug event.
1854 ProcessDebugEvent(v8::AsyncTaskEvent,
1855 Handle<JSObject>::cast(event_data),
1856 true);
1857}
1858
1859
1860void Debug::ProcessDebugEvent(v8::DebugEvent event,
1861 Handle<JSObject> event_data,
1862 bool auto_continue) {
1863 HandleScope scope(isolate_);
1864
1865 // Create the execution state.
1866 Handle<Object> exec_state;
1867 // Bail out and don't call debugger if exception.
1868 if (!MakeExecutionState().ToHandle(&exec_state)) return;
1869
1870 // First notify the message handler if any.
1871 if (message_handler_ != NULL) {
1872 NotifyMessageHandler(event,
1873 Handle<JSObject>::cast(exec_state),
1874 event_data,
1875 auto_continue);
1876 }
1877 // Notify registered debug event listener. This can be either a C or
1878 // a JavaScript function. Don't call event listener for v8::Break
1879 // here, if it's only a debug command -- they will be processed later.
1880 if ((event != v8::Break || !auto_continue) && !event_listener_.is_null()) {
1881 CallEventCallback(event, exec_state, event_data, NULL);
1882 }
1883}
1884
1885
1886void Debug::CallEventCallback(v8::DebugEvent event,
1887 Handle<Object> exec_state,
1888 Handle<Object> event_data,
1889 v8::Debug::ClientData* client_data) {
1890 // Prevent other interrupts from triggering, for example API callbacks,
1891 // while dispatching event listners.
1892 PostponeInterruptsScope postpone(isolate_);
1893 bool previous = in_debug_event_listener_;
1894 in_debug_event_listener_ = true;
1895 if (event_listener_->IsForeign()) {
1896 // Invoke the C debug event listener.
1897 v8::Debug::EventCallback callback =
1898 FUNCTION_CAST<v8::Debug::EventCallback>(
1899 Handle<Foreign>::cast(event_listener_)->foreign_address());
1900 EventDetailsImpl event_details(event,
1901 Handle<JSObject>::cast(exec_state),
1902 Handle<JSObject>::cast(event_data),
1903 event_listener_data_,
1904 client_data);
1905 callback(event_details);
1906 DCHECK(!isolate_->has_scheduled_exception());
1907 } else {
1908 // Invoke the JavaScript debug event listener.
1909 DCHECK(event_listener_->IsJSFunction());
1910 Handle<Object> argv[] = { Handle<Object>(Smi::FromInt(event), isolate_),
1911 exec_state,
1912 event_data,
1913 event_listener_data_ };
1914 Handle<JSReceiver> global(isolate_->global_proxy());
1915 Execution::TryCall(isolate_, Handle<JSFunction>::cast(event_listener_),
1916 global, arraysize(argv), argv);
1917 }
1918 in_debug_event_listener_ = previous;
1919}
1920
1921
1922void Debug::ProcessCompileEvent(v8::DebugEvent event, Handle<Script> script) {
1923 if (ignore_events()) return;
1924 SuppressDebug while_processing(this);
1925
1926 bool in_nested_debug_scope = in_debug_scope();
1927 HandleScope scope(isolate_);
1928 DebugScope debug_scope(this);
1929 if (debug_scope.failed()) return;
1930
1931 if (event == v8::AfterCompile) {
1932 // If debugging there might be script break points registered for this
1933 // script. Make sure that these break points are set.
1934 Handle<Object> argv[] = {Script::GetWrapper(script)};
1935 if (CallFunction("UpdateScriptBreakPoints", arraysize(argv), argv)
1936 .is_null()) {
1937 return;
1938 }
1939 }
1940
1941 // Create the compile state object.
1942 Handle<Object> event_data;
1943 // Bail out and don't call debugger if exception.
1944 if (!MakeCompileEvent(script, event).ToHandle(&event_data)) return;
1945
1946 // Don't call NotifyMessageHandler if already in debug scope to avoid running
1947 // nested command loop.
1948 if (in_nested_debug_scope) {
1949 if (event_listener_.is_null()) return;
1950 // Create the execution state.
1951 Handle<Object> exec_state;
1952 // Bail out and don't call debugger if exception.
1953 if (!MakeExecutionState().ToHandle(&exec_state)) return;
1954
1955 CallEventCallback(event, exec_state, event_data, NULL);
1956 } else {
1957 // Process debug event.
1958 ProcessDebugEvent(event, Handle<JSObject>::cast(event_data), true);
1959 }
1960}
1961
1962
1963Handle<Context> Debug::GetDebugContext() {
1964 if (!is_loaded()) return Handle<Context>();
1965 DebugScope debug_scope(this);
1966 if (debug_scope.failed()) return Handle<Context>();
1967 // The global handle may be destroyed soon after. Return it reboxed.
1968 return handle(*debug_context(), isolate_);
1969}
1970
1971
1972void Debug::NotifyMessageHandler(v8::DebugEvent event,
1973 Handle<JSObject> exec_state,
1974 Handle<JSObject> event_data,
1975 bool auto_continue) {
1976 // Prevent other interrupts from triggering, for example API callbacks,
1977 // while dispatching message handler callbacks.
1978 PostponeInterruptsScope no_interrupts(isolate_);
1979 DCHECK(is_active_);
1980 HandleScope scope(isolate_);
1981 // Process the individual events.
1982 bool sendEventMessage = false;
1983 switch (event) {
1984 case v8::Break:
1985 sendEventMessage = !auto_continue;
1986 break;
1987 case v8::NewFunction:
1988 case v8::BeforeCompile:
1989 case v8::CompileError:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001990 case v8::AsyncTaskEvent:
1991 break;
1992 case v8::Exception:
1993 case v8::AfterCompile:
1994 sendEventMessage = true;
1995 break;
1996 }
1997
1998 // The debug command interrupt flag might have been set when the command was
1999 // added. It should be enough to clear the flag only once while we are in the
2000 // debugger.
2001 DCHECK(in_debug_scope());
2002 isolate_->stack_guard()->ClearDebugCommand();
2003
2004 // Notify the debugger that a debug event has occurred unless auto continue is
2005 // active in which case no event is send.
2006 if (sendEventMessage) {
2007 MessageImpl message = MessageImpl::NewEvent(
2008 event,
2009 auto_continue,
2010 Handle<JSObject>::cast(exec_state),
2011 Handle<JSObject>::cast(event_data));
2012 InvokeMessageHandler(message);
2013 }
2014
2015 // If auto continue don't make the event cause a break, but process messages
2016 // in the queue if any. For script collected events don't even process
2017 // messages in the queue as the execution state might not be what is expected
2018 // by the client.
2019 if (auto_continue && !has_commands()) return;
2020
2021 // DebugCommandProcessor goes here.
2022 bool running = auto_continue;
2023
Ben Murdochda12d292016-06-02 14:46:10 +01002024 Handle<Object> cmd_processor_ctor =
2025 JSReceiver::GetProperty(isolate_, exec_state, "debugCommandProcessor")
2026 .ToHandleChecked();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002027 Handle<Object> ctor_args[] = { isolate_->factory()->ToBoolean(running) };
Ben Murdochda12d292016-06-02 14:46:10 +01002028 Handle<JSReceiver> cmd_processor = Handle<JSReceiver>::cast(
2029 Execution::Call(isolate_, cmd_processor_ctor, exec_state, 1, ctor_args)
2030 .ToHandleChecked());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002031 Handle<JSFunction> process_debug_request = Handle<JSFunction>::cast(
Ben Murdochda12d292016-06-02 14:46:10 +01002032 JSReceiver::GetProperty(isolate_, cmd_processor, "processDebugRequest")
2033 .ToHandleChecked());
2034 Handle<Object> is_running =
2035 JSReceiver::GetProperty(isolate_, cmd_processor, "isRunning")
2036 .ToHandleChecked();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002037
2038 // Process requests from the debugger.
2039 do {
2040 // Wait for new command in the queue.
2041 command_received_.Wait();
2042
2043 // Get the command from the queue.
2044 CommandMessage command = command_queue_.Get();
2045 isolate_->logger()->DebugTag(
2046 "Got request from command queue, in interactive loop.");
2047 if (!is_active()) {
2048 // Delete command text and user data.
2049 command.Dispose();
2050 return;
2051 }
2052
2053 Vector<const uc16> command_text(
2054 const_cast<const uc16*>(command.text().start()),
2055 command.text().length());
2056 Handle<String> request_text = isolate_->factory()->NewStringFromTwoByte(
2057 command_text).ToHandleChecked();
2058 Handle<Object> request_args[] = { request_text };
2059 Handle<Object> answer_value;
2060 Handle<String> answer;
2061 MaybeHandle<Object> maybe_exception;
2062 MaybeHandle<Object> maybe_result =
2063 Execution::TryCall(isolate_, process_debug_request, cmd_processor, 1,
2064 request_args, &maybe_exception);
2065
2066 if (maybe_result.ToHandle(&answer_value)) {
2067 if (answer_value->IsUndefined()) {
2068 answer = isolate_->factory()->empty_string();
2069 } else {
2070 answer = Handle<String>::cast(answer_value);
2071 }
2072
2073 // Log the JSON request/response.
2074 if (FLAG_trace_debug_json) {
2075 PrintF("%s\n", request_text->ToCString().get());
2076 PrintF("%s\n", answer->ToCString().get());
2077 }
2078
2079 Handle<Object> is_running_args[] = { answer };
2080 maybe_result = Execution::Call(
2081 isolate_, is_running, cmd_processor, 1, is_running_args);
2082 Handle<Object> result;
2083 if (!maybe_result.ToHandle(&result)) break;
2084 running = result->IsTrue();
2085 } else {
2086 Handle<Object> exception;
2087 if (!maybe_exception.ToHandle(&exception)) break;
2088 Handle<Object> result;
2089 if (!Object::ToString(isolate_, exception).ToHandle(&result)) break;
2090 answer = Handle<String>::cast(result);
2091 }
2092
2093 // Return the result.
2094 MessageImpl message = MessageImpl::NewResponse(
2095 event, running, exec_state, event_data, answer, command.client_data());
2096 InvokeMessageHandler(message);
2097 command.Dispose();
2098
2099 // Return from debug event processing if either the VM is put into the
2100 // running state (through a continue command) or auto continue is active
2101 // and there are no more commands queued.
2102 } while (!running || has_commands());
2103 command_queue_.Clear();
2104}
2105
2106
2107void Debug::SetEventListener(Handle<Object> callback,
2108 Handle<Object> data) {
2109 GlobalHandles* global_handles = isolate_->global_handles();
2110
2111 // Remove existing entry.
2112 GlobalHandles::Destroy(event_listener_.location());
2113 event_listener_ = Handle<Object>();
2114 GlobalHandles::Destroy(event_listener_data_.location());
2115 event_listener_data_ = Handle<Object>();
2116
2117 // Set new entry.
2118 if (!callback->IsUndefined() && !callback->IsNull()) {
2119 event_listener_ = global_handles->Create(*callback);
2120 if (data.is_null()) data = isolate_->factory()->undefined_value();
2121 event_listener_data_ = global_handles->Create(*data);
2122 }
2123
2124 UpdateState();
2125}
2126
2127
2128void Debug::SetMessageHandler(v8::Debug::MessageHandler handler) {
2129 message_handler_ = handler;
2130 UpdateState();
2131 if (handler == NULL && in_debug_scope()) {
2132 // Send an empty command to the debugger if in a break to make JavaScript
2133 // run again if the debugger is closed.
2134 EnqueueCommandMessage(Vector<const uint16_t>::empty());
2135 }
2136}
2137
2138
2139
2140void Debug::UpdateState() {
2141 bool is_active = message_handler_ != NULL || !event_listener_.is_null();
2142 if (is_active || in_debug_scope()) {
2143 // Note that the debug context could have already been loaded to
2144 // bootstrap test cases.
2145 isolate_->compilation_cache()->Disable();
2146 is_active = Load();
2147 } else if (is_loaded()) {
2148 isolate_->compilation_cache()->Enable();
2149 Unload();
2150 }
2151 is_active_ = is_active;
2152}
2153
2154
2155// Calls the registered debug message handler. This callback is part of the
2156// public API.
2157void Debug::InvokeMessageHandler(MessageImpl message) {
2158 if (message_handler_ != NULL) message_handler_(message);
2159}
2160
2161
2162// Puts a command coming from the public API on the queue. Creates
2163// a copy of the command string managed by the debugger. Up to this
2164// point, the command data was managed by the API client. Called
2165// by the API client thread.
2166void Debug::EnqueueCommandMessage(Vector<const uint16_t> command,
2167 v8::Debug::ClientData* client_data) {
2168 // Need to cast away const.
2169 CommandMessage message = CommandMessage::New(
2170 Vector<uint16_t>(const_cast<uint16_t*>(command.start()),
2171 command.length()),
2172 client_data);
2173 isolate_->logger()->DebugTag("Put command on command_queue.");
2174 command_queue_.Put(message);
2175 command_received_.Signal();
2176
2177 // Set the debug command break flag to have the command processed.
2178 if (!in_debug_scope()) isolate_->stack_guard()->RequestDebugCommand();
2179}
2180
2181
2182MaybeHandle<Object> Debug::Call(Handle<Object> fun, Handle<Object> data) {
2183 DebugScope debug_scope(this);
2184 if (debug_scope.failed()) return isolate_->factory()->undefined_value();
2185
2186 // Create the execution state.
2187 Handle<Object> exec_state;
2188 if (!MakeExecutionState().ToHandle(&exec_state)) {
2189 return isolate_->factory()->undefined_value();
2190 }
2191
2192 Handle<Object> argv[] = { exec_state, data };
2193 return Execution::Call(
2194 isolate_,
2195 fun,
2196 Handle<Object>(debug_context()->global_proxy(), isolate_),
2197 arraysize(argv),
2198 argv);
2199}
2200
2201
2202void Debug::HandleDebugBreak() {
2203 // Ignore debug break during bootstrapping.
2204 if (isolate_->bootstrapper()->IsActive()) return;
2205 // Just continue if breaks are disabled.
2206 if (break_disabled()) return;
2207 // Ignore debug break if debugger is not active.
2208 if (!is_active()) return;
2209
2210 StackLimitCheck check(isolate_);
2211 if (check.HasOverflowed()) return;
2212
2213 { JavaScriptFrameIterator it(isolate_);
2214 DCHECK(!it.done());
2215 Object* fun = it.frame()->function();
2216 if (fun && fun->IsJSFunction()) {
2217 // Don't stop in builtin functions.
2218 if (!JSFunction::cast(fun)->shared()->IsSubjectToDebugging()) return;
2219 JSGlobalObject* global =
2220 JSFunction::cast(fun)->context()->global_object();
2221 // Don't stop in debugger functions.
2222 if (IsDebugGlobal(global)) return;
Ben Murdoch097c5b22016-05-18 11:27:45 +01002223 // Don't stop if the break location is muted.
2224 if (IsMutedAtCurrentLocation(it.frame())) return;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002225 }
2226 }
2227
2228 // Collect the break state before clearing the flags.
2229 bool debug_command_only = isolate_->stack_guard()->CheckDebugCommand() &&
2230 !isolate_->stack_guard()->CheckDebugBreak();
2231
2232 isolate_->stack_guard()->ClearDebugBreak();
2233
2234 // Clear stepping to avoid duplicate breaks.
2235 ClearStepping();
2236
2237 ProcessDebugMessages(debug_command_only);
2238}
2239
2240
2241void Debug::ProcessDebugMessages(bool debug_command_only) {
2242 isolate_->stack_guard()->ClearDebugCommand();
2243
2244 StackLimitCheck check(isolate_);
2245 if (check.HasOverflowed()) return;
2246
2247 HandleScope scope(isolate_);
2248 DebugScope debug_scope(this);
2249 if (debug_scope.failed()) return;
2250
2251 // Notify the debug event listeners. Indicate auto continue if the break was
2252 // a debug command break.
2253 OnDebugBreak(isolate_->factory()->undefined_value(), debug_command_only);
2254}
2255
Ben Murdochda12d292016-06-02 14:46:10 +01002256#ifdef DEBUG
2257void Debug::PrintBreakLocation() {
2258 if (!FLAG_print_break_location) return;
2259 HandleScope scope(isolate_);
2260 JavaScriptFrameIterator iterator(isolate_);
2261 if (iterator.done()) return;
2262 JavaScriptFrame* frame = iterator.frame();
2263 FrameSummary summary = GetFirstFrameSummary(frame);
2264 int source_position =
2265 summary.abstract_code()->SourcePosition(summary.code_offset());
2266 Handle<Object> script_obj(summary.function()->shared()->script(), isolate_);
2267 PrintF("[debug] break in function '");
2268 summary.function()->PrintName();
2269 PrintF("'.\n");
2270 if (script_obj->IsScript()) {
2271 Handle<Script> script = Handle<Script>::cast(script_obj);
2272 Handle<String> source(String::cast(script->source()));
2273 Script::InitLineEnds(script);
2274 int line = Script::GetLineNumber(script, source_position);
2275 int column = Script::GetColumnNumber(script, source_position);
2276 Handle<FixedArray> line_ends(FixedArray::cast(script->line_ends()));
2277 int line_start =
2278 line == 0 ? 0 : Smi::cast(line_ends->get(line - 1))->value() + 1;
2279 int line_end = Smi::cast(line_ends->get(line))->value();
2280 DisallowHeapAllocation no_gc;
2281 String::FlatContent content = source->GetFlatContent();
2282 if (content.IsOneByte()) {
2283 PrintF("[debug] %.*s\n", line_end - line_start,
2284 content.ToOneByteVector().start() + line_start);
2285 PrintF("[debug] ");
2286 for (int i = 0; i < column; i++) PrintF(" ");
2287 PrintF("^\n");
2288 } else {
2289 PrintF("[debug] at line %d column %d\n", line, column);
2290 }
2291 }
2292}
2293#endif // DEBUG
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002294
2295DebugScope::DebugScope(Debug* debug)
2296 : debug_(debug),
2297 prev_(debug->debugger_entry()),
2298 save_(debug_->isolate_),
2299 no_termination_exceptons_(debug_->isolate_,
2300 StackGuard::TERMINATE_EXECUTION) {
2301 // Link recursive debugger entry.
2302 base::NoBarrier_Store(&debug_->thread_local_.current_debug_scope_,
2303 reinterpret_cast<base::AtomicWord>(this));
2304
Ben Murdochda12d292016-06-02 14:46:10 +01002305 // Store the previous break id, frame id and return value.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002306 break_id_ = debug_->break_id();
2307 break_frame_id_ = debug_->break_frame_id();
Ben Murdochda12d292016-06-02 14:46:10 +01002308 return_value_ = debug_->return_value();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002309
2310 // Create the new break info. If there is no JavaScript frames there is no
2311 // break frame id.
2312 JavaScriptFrameIterator it(isolate());
2313 bool has_js_frames = !it.done();
2314 debug_->thread_local_.break_frame_id_ = has_js_frames ? it.frame()->id()
2315 : StackFrame::NO_ID;
2316 debug_->SetNextBreakId();
2317
2318 debug_->UpdateState();
2319 // Make sure that debugger is loaded and enter the debugger context.
2320 // The previous context is kept in save_.
2321 failed_ = !debug_->is_loaded();
2322 if (!failed_) isolate()->set_context(*debug->debug_context());
2323}
2324
2325
2326DebugScope::~DebugScope() {
2327 if (!failed_ && prev_ == NULL) {
2328 // Clear mirror cache when leaving the debugger. Skip this if there is a
2329 // pending exception as clearing the mirror cache calls back into
2330 // JavaScript. This can happen if the v8::Debug::Call is used in which
2331 // case the exception should end up in the calling code.
2332 if (!isolate()->has_pending_exception()) debug_->ClearMirrorCache();
2333
2334 // If there are commands in the queue when leaving the debugger request
2335 // that these commands are processed.
2336 if (debug_->has_commands()) isolate()->stack_guard()->RequestDebugCommand();
2337 }
2338
2339 // Leaving this debugger entry.
2340 base::NoBarrier_Store(&debug_->thread_local_.current_debug_scope_,
2341 reinterpret_cast<base::AtomicWord>(prev_));
2342
2343 // Restore to the previous break state.
2344 debug_->thread_local_.break_frame_id_ = break_frame_id_;
2345 debug_->thread_local_.break_id_ = break_id_;
Ben Murdochda12d292016-06-02 14:46:10 +01002346 debug_->thread_local_.return_value_ = return_value_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002347
2348 debug_->UpdateState();
2349}
2350
2351
2352MessageImpl MessageImpl::NewEvent(DebugEvent event,
2353 bool running,
2354 Handle<JSObject> exec_state,
2355 Handle<JSObject> event_data) {
2356 MessageImpl message(true, event, running,
2357 exec_state, event_data, Handle<String>(), NULL);
2358 return message;
2359}
2360
2361
2362MessageImpl MessageImpl::NewResponse(DebugEvent event,
2363 bool running,
2364 Handle<JSObject> exec_state,
2365 Handle<JSObject> event_data,
2366 Handle<String> response_json,
2367 v8::Debug::ClientData* client_data) {
2368 MessageImpl message(false, event, running,
2369 exec_state, event_data, response_json, client_data);
2370 return message;
2371}
2372
2373
2374MessageImpl::MessageImpl(bool is_event,
2375 DebugEvent event,
2376 bool running,
2377 Handle<JSObject> exec_state,
2378 Handle<JSObject> event_data,
2379 Handle<String> response_json,
2380 v8::Debug::ClientData* client_data)
2381 : is_event_(is_event),
2382 event_(event),
2383 running_(running),
2384 exec_state_(exec_state),
2385 event_data_(event_data),
2386 response_json_(response_json),
2387 client_data_(client_data) {}
2388
2389
2390bool MessageImpl::IsEvent() const {
2391 return is_event_;
2392}
2393
2394
2395bool MessageImpl::IsResponse() const {
2396 return !is_event_;
2397}
2398
2399
2400DebugEvent MessageImpl::GetEvent() const {
2401 return event_;
2402}
2403
2404
2405bool MessageImpl::WillStartRunning() const {
2406 return running_;
2407}
2408
2409
2410v8::Local<v8::Object> MessageImpl::GetExecutionState() const {
2411 return v8::Utils::ToLocal(exec_state_);
2412}
2413
2414
2415v8::Isolate* MessageImpl::GetIsolate() const {
2416 return reinterpret_cast<v8::Isolate*>(exec_state_->GetIsolate());
2417}
2418
2419
2420v8::Local<v8::Object> MessageImpl::GetEventData() const {
2421 return v8::Utils::ToLocal(event_data_);
2422}
2423
2424
2425v8::Local<v8::String> MessageImpl::GetJSON() const {
2426 Isolate* isolate = event_data_->GetIsolate();
2427 v8::EscapableHandleScope scope(reinterpret_cast<v8::Isolate*>(isolate));
2428
2429 if (IsEvent()) {
2430 // Call toJSONProtocol on the debug event object.
Ben Murdochda12d292016-06-02 14:46:10 +01002431 Handle<Object> fun =
2432 JSReceiver::GetProperty(isolate, event_data_, "toJSONProtocol")
2433 .ToHandleChecked();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00002434 if (!fun->IsJSFunction()) {
2435 return v8::Local<v8::String>();
2436 }
2437
2438 MaybeHandle<Object> maybe_json =
2439 Execution::TryCall(isolate, fun, event_data_, 0, NULL);
2440 Handle<Object> json;
2441 if (!maybe_json.ToHandle(&json) || !json->IsString()) {
2442 return v8::Local<v8::String>();
2443 }
2444 return scope.Escape(v8::Utils::ToLocal(Handle<String>::cast(json)));
2445 } else {
2446 return v8::Utils::ToLocal(response_json_);
2447 }
2448}
2449
2450
2451v8::Local<v8::Context> MessageImpl::GetEventContext() const {
2452 Isolate* isolate = event_data_->GetIsolate();
2453 v8::Local<v8::Context> context = GetDebugEventContext(isolate);
2454 // Isolate::context() may be NULL when "script collected" event occurs.
2455 DCHECK(!context.IsEmpty());
2456 return context;
2457}
2458
2459
2460v8::Debug::ClientData* MessageImpl::GetClientData() const {
2461 return client_data_;
2462}
2463
2464
2465EventDetailsImpl::EventDetailsImpl(DebugEvent event,
2466 Handle<JSObject> exec_state,
2467 Handle<JSObject> event_data,
2468 Handle<Object> callback_data,
2469 v8::Debug::ClientData* client_data)
2470 : event_(event),
2471 exec_state_(exec_state),
2472 event_data_(event_data),
2473 callback_data_(callback_data),
2474 client_data_(client_data) {}
2475
2476
2477DebugEvent EventDetailsImpl::GetEvent() const {
2478 return event_;
2479}
2480
2481
2482v8::Local<v8::Object> EventDetailsImpl::GetExecutionState() const {
2483 return v8::Utils::ToLocal(exec_state_);
2484}
2485
2486
2487v8::Local<v8::Object> EventDetailsImpl::GetEventData() const {
2488 return v8::Utils::ToLocal(event_data_);
2489}
2490
2491
2492v8::Local<v8::Context> EventDetailsImpl::GetEventContext() const {
2493 return GetDebugEventContext(exec_state_->GetIsolate());
2494}
2495
2496
2497v8::Local<v8::Value> EventDetailsImpl::GetCallbackData() const {
2498 return v8::Utils::ToLocal(callback_data_);
2499}
2500
2501
2502v8::Debug::ClientData* EventDetailsImpl::GetClientData() const {
2503 return client_data_;
2504}
2505
2506
2507CommandMessage::CommandMessage() : text_(Vector<uint16_t>::empty()),
2508 client_data_(NULL) {
2509}
2510
2511
2512CommandMessage::CommandMessage(const Vector<uint16_t>& text,
2513 v8::Debug::ClientData* data)
2514 : text_(text),
2515 client_data_(data) {
2516}
2517
2518
2519void CommandMessage::Dispose() {
2520 text_.Dispose();
2521 delete client_data_;
2522 client_data_ = NULL;
2523}
2524
2525
2526CommandMessage CommandMessage::New(const Vector<uint16_t>& command,
2527 v8::Debug::ClientData* data) {
2528 return CommandMessage(command.Clone(), data);
2529}
2530
2531
2532CommandMessageQueue::CommandMessageQueue(int size) : start_(0), end_(0),
2533 size_(size) {
2534 messages_ = NewArray<CommandMessage>(size);
2535}
2536
2537
2538CommandMessageQueue::~CommandMessageQueue() {
2539 while (!IsEmpty()) Get().Dispose();
2540 DeleteArray(messages_);
2541}
2542
2543
2544CommandMessage CommandMessageQueue::Get() {
2545 DCHECK(!IsEmpty());
2546 int result = start_;
2547 start_ = (start_ + 1) % size_;
2548 return messages_[result];
2549}
2550
2551
2552void CommandMessageQueue::Put(const CommandMessage& message) {
2553 if ((end_ + 1) % size_ == start_) {
2554 Expand();
2555 }
2556 messages_[end_] = message;
2557 end_ = (end_ + 1) % size_;
2558}
2559
2560
2561void CommandMessageQueue::Expand() {
2562 CommandMessageQueue new_queue(size_ * 2);
2563 while (!IsEmpty()) {
2564 new_queue.Put(Get());
2565 }
2566 CommandMessage* array_to_free = messages_;
2567 *this = new_queue;
2568 new_queue.messages_ = array_to_free;
2569 // Make the new_queue empty so that it doesn't call Dispose on any messages.
2570 new_queue.start_ = new_queue.end_;
2571 // Automatic destructor called on new_queue, freeing array_to_free.
2572}
2573
2574
2575LockingCommandMessageQueue::LockingCommandMessageQueue(Logger* logger, int size)
2576 : logger_(logger), queue_(size) {}
2577
2578
2579bool LockingCommandMessageQueue::IsEmpty() const {
2580 base::LockGuard<base::Mutex> lock_guard(&mutex_);
2581 return queue_.IsEmpty();
2582}
2583
2584
2585CommandMessage LockingCommandMessageQueue::Get() {
2586 base::LockGuard<base::Mutex> lock_guard(&mutex_);
2587 CommandMessage result = queue_.Get();
2588 logger_->DebugEvent("Get", result.text());
2589 return result;
2590}
2591
2592
2593void LockingCommandMessageQueue::Put(const CommandMessage& message) {
2594 base::LockGuard<base::Mutex> lock_guard(&mutex_);
2595 queue_.Put(message);
2596 logger_->DebugEvent("Put", message.text());
2597}
2598
2599
2600void LockingCommandMessageQueue::Clear() {
2601 base::LockGuard<base::Mutex> lock_guard(&mutex_);
2602 queue_.Clear();
2603}
2604
2605} // namespace internal
2606} // namespace v8