v8  3.14.5(node0.10.28)
V8 is Google's open source JavaScript engine
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
debug.cc
Go to the documentation of this file.
1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 
28 #include "v8.h"
29 
30 #include "api.h"
31 #include "arguments.h"
32 #include "bootstrapper.h"
33 #include "code-stubs.h"
34 #include "codegen.h"
35 #include "compilation-cache.h"
36 #include "compiler.h"
37 #include "debug.h"
38 #include "deoptimizer.h"
39 #include "execution.h"
40 #include "full-codegen.h"
41 #include "global-handles.h"
42 #include "ic.h"
43 #include "ic-inl.h"
44 #include "isolate-inl.h"
45 #include "list.h"
46 #include "messages.h"
47 #include "natives.h"
48 #include "stub-cache.h"
49 #include "log.h"
50 
51 #include "../include/v8-debug.h"
52 
53 namespace v8 {
54 namespace internal {
55 
56 #ifdef ENABLE_DEBUGGER_SUPPORT
57 
58 
59 Debug::Debug(Isolate* isolate)
60  : has_break_points_(false),
61  script_cache_(NULL),
62  debug_info_list_(NULL),
63  disable_break_(false),
64  break_on_exception_(false),
65  break_on_uncaught_exception_(false),
66  debug_break_return_(NULL),
67  debug_break_slot_(NULL),
68  isolate_(isolate) {
69  memset(registers_, 0, sizeof(JSCallerSavedBuffer));
70 }
71 
72 
73 Debug::~Debug() {
74 }
75 
76 
77 static void PrintLn(v8::Local<v8::Value> value) {
78  v8::Local<v8::String> s = value->ToString();
79  ScopedVector<char> data(s->Length() + 1);
80  if (data.start() == NULL) {
81  V8::FatalProcessOutOfMemory("PrintLn");
82  return;
83  }
84  s->WriteAscii(data.start());
85  PrintF("%s\n", data.start());
86 }
87 
88 
89 static Handle<Code> ComputeCallDebugPrepareStepIn(int argc, Code::Kind kind) {
90  Isolate* isolate = Isolate::Current();
91  return isolate->stub_cache()->ComputeCallDebugPrepareStepIn(argc, kind);
92 }
93 
94 
95 static v8::Handle<v8::Context> GetDebugEventContext(Isolate* isolate) {
96  Handle<Context> context = isolate->debug()->debugger_entry()->GetContext();
97  // Isolate::context() may have been NULL when "script collected" event
98  // occured.
99  if (context.is_null()) return v8::Local<v8::Context>();
100  Handle<Context> native_context(context->native_context());
101  return v8::Utils::ToLocal(native_context);
102 }
103 
104 
105 BreakLocationIterator::BreakLocationIterator(Handle<DebugInfo> debug_info,
106  BreakLocatorType type) {
107  debug_info_ = debug_info;
108  type_ = type;
109  reloc_iterator_ = NULL;
110  reloc_iterator_original_ = NULL;
111  Reset(); // Initialize the rest of the member variables.
112 }
113 
114 
115 BreakLocationIterator::~BreakLocationIterator() {
116  ASSERT(reloc_iterator_ != NULL);
117  ASSERT(reloc_iterator_original_ != NULL);
118  delete reloc_iterator_;
119  delete reloc_iterator_original_;
120 }
121 
122 
123 void BreakLocationIterator::Next() {
124  AssertNoAllocation nogc;
125  ASSERT(!RinfoDone());
126 
127  // Iterate through reloc info for code and original code stopping at each
128  // breakable code target.
129  bool first = break_point_ == -1;
130  while (!RinfoDone()) {
131  if (!first) RinfoNext();
132  first = false;
133  if (RinfoDone()) return;
134 
135  // Whenever a statement position or (plain) position is passed update the
136  // current value of these.
137  if (RelocInfo::IsPosition(rmode())) {
138  if (RelocInfo::IsStatementPosition(rmode())) {
139  statement_position_ = static_cast<int>(
140  rinfo()->data() - debug_info_->shared()->start_position());
141  }
142  // Always update the position as we don't want that to be before the
143  // statement position.
144  position_ = static_cast<int>(
145  rinfo()->data() - debug_info_->shared()->start_position());
146  ASSERT(position_ >= 0);
147  ASSERT(statement_position_ >= 0);
148  }
149 
150  if (IsDebugBreakSlot()) {
151  // There is always a possible break point at a debug break slot.
152  break_point_++;
153  return;
154  } else if (RelocInfo::IsCodeTarget(rmode())) {
155  // Check for breakable code target. Look in the original code as setting
156  // break points can cause the code targets in the running (debugged) code
157  // to be of a different kind than in the original code.
158  Address target = original_rinfo()->target_address();
159  Code* code = Code::GetCodeFromTargetAddress(target);
160  if ((code->is_inline_cache_stub() &&
161  !code->is_binary_op_stub() &&
162  !code->is_unary_op_stub() &&
163  !code->is_compare_ic_stub() &&
164  !code->is_to_boolean_ic_stub()) ||
165  RelocInfo::IsConstructCall(rmode())) {
166  break_point_++;
167  return;
168  }
169  if (code->kind() == Code::STUB) {
170  if (IsDebuggerStatement()) {
171  break_point_++;
172  return;
173  }
174  if (type_ == ALL_BREAK_LOCATIONS) {
175  if (Debug::IsBreakStub(code)) {
176  break_point_++;
177  return;
178  }
179  } else {
180  ASSERT(type_ == SOURCE_BREAK_LOCATIONS);
181  if (Debug::IsSourceBreakStub(code)) {
182  break_point_++;
183  return;
184  }
185  }
186  }
187  }
188 
189  // Check for break at return.
190  if (RelocInfo::IsJSReturn(rmode())) {
191  // Set the positions to the end of the function.
192  if (debug_info_->shared()->HasSourceCode()) {
193  position_ = debug_info_->shared()->end_position() -
194  debug_info_->shared()->start_position() - 1;
195  } else {
196  position_ = 0;
197  }
198  statement_position_ = position_;
199  break_point_++;
200  return;
201  }
202  }
203 }
204 
205 
206 void BreakLocationIterator::Next(int count) {
207  while (count > 0) {
208  Next();
209  count--;
210  }
211 }
212 
213 
214 // Find the break point closest to the supplied address.
215 void BreakLocationIterator::FindBreakLocationFromAddress(Address pc) {
216  // Run through all break points to locate the one closest to the address.
217  int closest_break_point = 0;
218  int distance = kMaxInt;
219  while (!Done()) {
220  // Check if this break point is closer that what was previously found.
221  if (this->pc() < pc && pc - this->pc() < distance) {
222  closest_break_point = break_point();
223  distance = static_cast<int>(pc - this->pc());
224  // Check whether we can't get any closer.
225  if (distance == 0) break;
226  }
227  Next();
228  }
229 
230  // Move to the break point found.
231  Reset();
232  Next(closest_break_point);
233 }
234 
235 
236 // Find the break point closest to the supplied source position.
237 void BreakLocationIterator::FindBreakLocationFromPosition(int position) {
238  // Run through all break points to locate the one closest to the source
239  // position.
240  int closest_break_point = 0;
241  int distance = kMaxInt;
242  while (!Done()) {
243  // Check if this break point is closer that what was previously found.
244  if (position <= statement_position() &&
245  statement_position() - position < distance) {
246  closest_break_point = break_point();
247  distance = statement_position() - position;
248  // Check whether we can't get any closer.
249  if (distance == 0) break;
250  }
251  Next();
252  }
253 
254  // Move to the break point found.
255  Reset();
256  Next(closest_break_point);
257 }
258 
259 
260 void BreakLocationIterator::Reset() {
261  // Create relocation iterators for the two code objects.
262  if (reloc_iterator_ != NULL) delete reloc_iterator_;
263  if (reloc_iterator_original_ != NULL) delete reloc_iterator_original_;
264  reloc_iterator_ = new RelocIterator(debug_info_->code());
265  reloc_iterator_original_ = new RelocIterator(debug_info_->original_code());
266 
267  // Position at the first break point.
268  break_point_ = -1;
269  position_ = 1;
270  statement_position_ = 1;
271  Next();
272 }
273 
274 
275 bool BreakLocationIterator::Done() const {
276  return RinfoDone();
277 }
278 
279 
280 void BreakLocationIterator::SetBreakPoint(Handle<Object> break_point_object) {
281  // If there is not already a real break point here patch code with debug
282  // break.
283  if (!HasBreakPoint()) {
284  SetDebugBreak();
285  }
286  ASSERT(IsDebugBreak() || IsDebuggerStatement());
287  // Set the break point information.
288  DebugInfo::SetBreakPoint(debug_info_, code_position(),
289  position(), statement_position(),
290  break_point_object);
291 }
292 
293 
294 void BreakLocationIterator::ClearBreakPoint(Handle<Object> break_point_object) {
295  // Clear the break point information.
296  DebugInfo::ClearBreakPoint(debug_info_, code_position(), break_point_object);
297  // If there are no more break points here remove the debug break.
298  if (!HasBreakPoint()) {
299  ClearDebugBreak();
300  ASSERT(!IsDebugBreak());
301  }
302 }
303 
304 
305 void BreakLocationIterator::SetOneShot() {
306  // Debugger statement always calls debugger. No need to modify it.
307  if (IsDebuggerStatement()) {
308  return;
309  }
310 
311  // If there is a real break point here no more to do.
312  if (HasBreakPoint()) {
313  ASSERT(IsDebugBreak());
314  return;
315  }
316 
317  // Patch code with debug break.
318  SetDebugBreak();
319 }
320 
321 
322 void BreakLocationIterator::ClearOneShot() {
323  // Debugger statement always calls debugger. No need to modify it.
324  if (IsDebuggerStatement()) {
325  return;
326  }
327 
328  // If there is a real break point here no more to do.
329  if (HasBreakPoint()) {
330  ASSERT(IsDebugBreak());
331  return;
332  }
333 
334  // Patch code removing debug break.
335  ClearDebugBreak();
336  ASSERT(!IsDebugBreak());
337 }
338 
339 
340 void BreakLocationIterator::SetDebugBreak() {
341  // Debugger statement always calls debugger. No need to modify it.
342  if (IsDebuggerStatement()) {
343  return;
344  }
345 
346  // If there is already a break point here just return. This might happen if
347  // the same code is flooded with break points twice. Flooding the same
348  // function twice might happen when stepping in a function with an exception
349  // handler as the handler and the function is the same.
350  if (IsDebugBreak()) {
351  return;
352  }
353 
354  if (RelocInfo::IsJSReturn(rmode())) {
355  // Patch the frame exit code with a break point.
356  SetDebugBreakAtReturn();
357  } else if (IsDebugBreakSlot()) {
358  // Patch the code in the break slot.
359  SetDebugBreakAtSlot();
360  } else {
361  // Patch the IC call.
362  SetDebugBreakAtIC();
363  }
364  ASSERT(IsDebugBreak());
365 }
366 
367 
368 void BreakLocationIterator::ClearDebugBreak() {
369  // Debugger statement always calls debugger. No need to modify it.
370  if (IsDebuggerStatement()) {
371  return;
372  }
373 
374  if (RelocInfo::IsJSReturn(rmode())) {
375  // Restore the frame exit code.
376  ClearDebugBreakAtReturn();
377  } else if (IsDebugBreakSlot()) {
378  // Restore the code in the break slot.
379  ClearDebugBreakAtSlot();
380  } else {
381  // Patch the IC call.
382  ClearDebugBreakAtIC();
383  }
384  ASSERT(!IsDebugBreak());
385 }
386 
387 
388 void BreakLocationIterator::PrepareStepIn() {
389  HandleScope scope;
390 
391  // Step in can only be prepared if currently positioned on an IC call,
392  // construct call or CallFunction stub call.
393  Address target = rinfo()->target_address();
394  Handle<Code> target_code(Code::GetCodeFromTargetAddress(target));
395  if (target_code->is_call_stub() || target_code->is_keyed_call_stub()) {
396  // Step in through IC call is handled by the runtime system. Therefore make
397  // sure that the any current IC is cleared and the runtime system is
398  // called. If the executing code has a debug break at the location change
399  // the call in the original code as it is the code there that will be
400  // executed in place of the debug break call.
401  Handle<Code> stub = ComputeCallDebugPrepareStepIn(
402  target_code->arguments_count(), target_code->kind());
403  if (IsDebugBreak()) {
404  original_rinfo()->set_target_address(stub->entry());
405  } else {
406  rinfo()->set_target_address(stub->entry());
407  }
408  } else {
409 #ifdef DEBUG
410  // All the following stuff is needed only for assertion checks so the code
411  // is wrapped in ifdef.
412  Handle<Code> maybe_call_function_stub = target_code;
413  if (IsDebugBreak()) {
414  Address original_target = original_rinfo()->target_address();
415  maybe_call_function_stub =
416  Handle<Code>(Code::GetCodeFromTargetAddress(original_target));
417  }
418  bool is_call_function_stub =
419  (maybe_call_function_stub->kind() == Code::STUB &&
420  maybe_call_function_stub->major_key() == CodeStub::CallFunction);
421 
422  // Step in through construct call requires no changes to the running code.
423  // Step in through getters/setters should already be prepared as well
424  // because caller of this function (Debug::PrepareStep) is expected to
425  // flood the top frame's function with one shot breakpoints.
426  // Step in through CallFunction stub should also be prepared by caller of
427  // this function (Debug::PrepareStep) which should flood target function
428  // with breakpoints.
429  ASSERT(RelocInfo::IsConstructCall(rmode()) ||
430  target_code->is_inline_cache_stub() ||
431  is_call_function_stub);
432 #endif
433  }
434 }
435 
436 
437 // Check whether the break point is at a position which will exit the function.
438 bool BreakLocationIterator::IsExit() const {
439  return (RelocInfo::IsJSReturn(rmode()));
440 }
441 
442 
443 bool BreakLocationIterator::HasBreakPoint() {
444  return debug_info_->HasBreakPoint(code_position());
445 }
446 
447 
448 // Check whether there is a debug break at the current position.
449 bool BreakLocationIterator::IsDebugBreak() {
450  if (RelocInfo::IsJSReturn(rmode())) {
451  return IsDebugBreakAtReturn();
452  } else if (IsDebugBreakSlot()) {
453  return IsDebugBreakAtSlot();
454  } else {
455  return Debug::IsDebugBreak(rinfo()->target_address());
456  }
457 }
458 
459 
460 void BreakLocationIterator::SetDebugBreakAtIC() {
461  // Patch the original code with the current address as the current address
462  // might have changed by the inline caching since the code was copied.
463  original_rinfo()->set_target_address(rinfo()->target_address());
464 
465  RelocInfo::Mode mode = rmode();
466  if (RelocInfo::IsCodeTarget(mode)) {
467  Address target = rinfo()->target_address();
468  Handle<Code> target_code(Code::GetCodeFromTargetAddress(target));
469 
470  // Patch the code to invoke the builtin debug break function matching the
471  // calling convention used by the call site.
472  Handle<Code> dbgbrk_code(Debug::FindDebugBreak(target_code, mode));
473  rinfo()->set_target_address(dbgbrk_code->entry());
474  }
475 }
476 
477 
478 void BreakLocationIterator::ClearDebugBreakAtIC() {
479  // Patch the code to the original invoke.
480  rinfo()->set_target_address(original_rinfo()->target_address());
481 }
482 
483 
484 bool BreakLocationIterator::IsDebuggerStatement() {
485  return RelocInfo::DEBUG_BREAK == rmode();
486 }
487 
488 
489 bool BreakLocationIterator::IsDebugBreakSlot() {
490  return RelocInfo::DEBUG_BREAK_SLOT == rmode();
491 }
492 
493 
494 Object* BreakLocationIterator::BreakPointObjects() {
495  return debug_info_->GetBreakPointObjects(code_position());
496 }
497 
498 
499 // Clear out all the debug break code. This is ONLY supposed to be used when
500 // shutting down the debugger as it will leave the break point information in
501 // DebugInfo even though the code is patched back to the non break point state.
502 void BreakLocationIterator::ClearAllDebugBreak() {
503  while (!Done()) {
504  ClearDebugBreak();
505  Next();
506  }
507 }
508 
509 
510 bool BreakLocationIterator::RinfoDone() const {
511  ASSERT(reloc_iterator_->done() == reloc_iterator_original_->done());
512  return reloc_iterator_->done();
513 }
514 
515 
516 void BreakLocationIterator::RinfoNext() {
517  reloc_iterator_->next();
518  reloc_iterator_original_->next();
519 #ifdef DEBUG
520  ASSERT(reloc_iterator_->done() == reloc_iterator_original_->done());
521  if (!reloc_iterator_->done()) {
522  ASSERT(rmode() == original_rmode());
523  }
524 #endif
525 }
526 
527 
528 // Threading support.
529 void Debug::ThreadInit() {
530  thread_local_.break_count_ = 0;
531  thread_local_.break_id_ = 0;
532  thread_local_.break_frame_id_ = StackFrame::NO_ID;
533  thread_local_.last_step_action_ = StepNone;
534  thread_local_.last_statement_position_ = RelocInfo::kNoPosition;
535  thread_local_.step_count_ = 0;
536  thread_local_.last_fp_ = 0;
537  thread_local_.queued_step_count_ = 0;
538  thread_local_.step_into_fp_ = 0;
539  thread_local_.step_out_fp_ = 0;
540  thread_local_.after_break_target_ = 0;
541  // TODO(isolates): frames_are_dropped_?
542  thread_local_.debugger_entry_ = NULL;
543  thread_local_.pending_interrupts_ = 0;
544  thread_local_.restarter_frame_function_pointer_ = NULL;
545 }
546 
547 
548 char* Debug::ArchiveDebug(char* storage) {
549  char* to = storage;
550  memcpy(to, reinterpret_cast<char*>(&thread_local_), sizeof(ThreadLocal));
551  to += sizeof(ThreadLocal);
552  memcpy(to, reinterpret_cast<char*>(&registers_), sizeof(registers_));
553  ThreadInit();
554  ASSERT(to <= storage + ArchiveSpacePerThread());
555  return storage + ArchiveSpacePerThread();
556 }
557 
558 
559 char* Debug::RestoreDebug(char* storage) {
560  char* from = storage;
561  memcpy(reinterpret_cast<char*>(&thread_local_), from, sizeof(ThreadLocal));
562  from += sizeof(ThreadLocal);
563  memcpy(reinterpret_cast<char*>(&registers_), from, sizeof(registers_));
564  ASSERT(from <= storage + ArchiveSpacePerThread());
565  return storage + ArchiveSpacePerThread();
566 }
567 
568 
569 int Debug::ArchiveSpacePerThread() {
570  return sizeof(ThreadLocal) + sizeof(JSCallerSavedBuffer);
571 }
572 
573 
574 // Frame structure (conforms InternalFrame structure):
575 // -- code
576 // -- SMI maker
577 // -- function (slot is called "context")
578 // -- frame base
579 Object** Debug::SetUpFrameDropperFrame(StackFrame* bottom_js_frame,
580  Handle<Code> code) {
581  ASSERT(bottom_js_frame->is_java_script());
582 
583  Address fp = bottom_js_frame->fp();
584 
585  // Move function pointer into "context" slot.
588 
592 
593  return reinterpret_cast<Object**>(&Memory::Object_at(
595 }
596 
597 const int Debug::kFrameDropperFrameSize = 4;
598 
599 
600 void ScriptCache::Add(Handle<Script> script) {
601  GlobalHandles* global_handles = Isolate::Current()->global_handles();
602  // Create an entry in the hash map for the script.
603  int id = Smi::cast(script->id())->value();
604  HashMap::Entry* entry =
605  HashMap::Lookup(reinterpret_cast<void*>(id), Hash(id), true);
606  if (entry->value != NULL) {
607  ASSERT(*script == *reinterpret_cast<Script**>(entry->value));
608  return;
609  }
610 
611  // Globalize the script object, make it weak and use the location of the
612  // global handle as the value in the hash map.
613  Handle<Script> script_ =
615  (global_handles->Create(*script)));
616  global_handles->MakeWeak(
617  reinterpret_cast<Object**>(script_.location()),
618  this,
619  ScriptCache::HandleWeakScript);
620  entry->value = script_.location();
621 }
622 
623 
624 Handle<FixedArray> ScriptCache::GetScripts() {
625  Handle<FixedArray> instances = FACTORY->NewFixedArray(occupancy());
626  int count = 0;
627  for (HashMap::Entry* entry = Start(); entry != NULL; entry = Next(entry)) {
628  ASSERT(entry->value != NULL);
629  if (entry->value != NULL) {
630  instances->set(count, *reinterpret_cast<Script**>(entry->value));
631  count++;
632  }
633  }
634  return instances;
635 }
636 
637 
638 void ScriptCache::ProcessCollectedScripts() {
639  Debugger* debugger = Isolate::Current()->debugger();
640  for (int i = 0; i < collected_scripts_.length(); i++) {
641  debugger->OnScriptCollected(collected_scripts_[i]);
642  }
643  collected_scripts_.Clear();
644 }
645 
646 
647 void ScriptCache::Clear() {
648  GlobalHandles* global_handles = Isolate::Current()->global_handles();
649  // Iterate the script cache to get rid of all the weak handles.
650  for (HashMap::Entry* entry = Start(); entry != NULL; entry = Next(entry)) {
651  ASSERT(entry != NULL);
652  Object** location = reinterpret_cast<Object**>(entry->value);
653  ASSERT((*location)->IsScript());
654  global_handles->ClearWeakness(location);
655  global_handles->Destroy(location);
656  }
657  // Clear the content of the hash map.
658  HashMap::Clear();
659 }
660 
661 
662 void ScriptCache::HandleWeakScript(v8::Persistent<v8::Value> obj, void* data) {
663  ScriptCache* script_cache = reinterpret_cast<ScriptCache*>(data);
664  // Find the location of the global handle.
665  Script** location =
666  reinterpret_cast<Script**>(Utils::OpenHandle(*obj).location());
667  ASSERT((*location)->IsScript());
668 
669  // Remove the entry from the cache.
670  int id = Smi::cast((*location)->id())->value();
671  script_cache->Remove(reinterpret_cast<void*>(id), Hash(id));
672  script_cache->collected_scripts_.Add(id);
673 
674  // Clear the weak handle.
675  obj.Dispose();
676  obj.Clear();
677 }
678 
679 
680 void Debug::SetUp(bool create_heap_objects) {
681  ThreadInit();
682  if (create_heap_objects) {
683  // Get code to handle debug break on return.
684  debug_break_return_ =
685  isolate_->builtins()->builtin(Builtins::kReturn_DebugBreak);
686  ASSERT(debug_break_return_->IsCode());
687  // Get code to handle debug break in debug break slots.
688  debug_break_slot_ =
689  isolate_->builtins()->builtin(Builtins::kSlot_DebugBreak);
690  ASSERT(debug_break_slot_->IsCode());
691  }
692 }
693 
694 
695 void Debug::HandleWeakDebugInfo(v8::Persistent<v8::Value> obj, void* data) {
696  Debug* debug = Isolate::Current()->debug();
697  DebugInfoListNode* node = reinterpret_cast<DebugInfoListNode*>(data);
698  // We need to clear all breakpoints associated with the function to restore
699  // original code and avoid patching the code twice later because
700  // the function will live in the heap until next gc, and can be found by
701  // Debug::FindSharedFunctionInfoInScript.
702  BreakLocationIterator it(node->debug_info(), ALL_BREAK_LOCATIONS);
703  it.ClearAllDebugBreak();
704  debug->RemoveDebugInfo(node->debug_info());
705 #ifdef DEBUG
706  node = debug->debug_info_list_;
707  while (node != NULL) {
708  ASSERT(node != reinterpret_cast<DebugInfoListNode*>(data));
709  node = node->next();
710  }
711 #endif
712 }
713 
714 
715 DebugInfoListNode::DebugInfoListNode(DebugInfo* debug_info): next_(NULL) {
716  GlobalHandles* global_handles = Isolate::Current()->global_handles();
717  // Globalize the request debug info object and make it weak.
718  debug_info_ = Handle<DebugInfo>::cast(
719  (global_handles->Create(debug_info)));
720  global_handles->MakeWeak(
721  reinterpret_cast<Object**>(debug_info_.location()),
722  this,
723  Debug::HandleWeakDebugInfo);
724 }
725 
726 
727 DebugInfoListNode::~DebugInfoListNode() {
728  Isolate::Current()->global_handles()->Destroy(
729  reinterpret_cast<Object**>(debug_info_.location()));
730 }
731 
732 
733 bool Debug::CompileDebuggerScript(int index) {
734  Isolate* isolate = Isolate::Current();
735  Factory* factory = isolate->factory();
736  HandleScope scope(isolate);
737 
738  // Bail out if the index is invalid.
739  if (index == -1) {
740  return false;
741  }
742 
743  // Find source and name for the requested script.
744  Handle<String> source_code =
745  isolate->bootstrapper()->NativesSourceLookup(index);
746  Vector<const char> name = Natives::GetScriptName(index);
747  Handle<String> script_name = factory->NewStringFromAscii(name);
748  Handle<Context> context = isolate->native_context();
749 
750  // Compile the script.
751  Handle<SharedFunctionInfo> function_info;
752  function_info = Compiler::Compile(source_code,
753  script_name,
754  0, 0,
755  context,
756  NULL, NULL,
758  NATIVES_CODE);
759 
760  // Silently ignore stack overflows during compilation.
761  if (function_info.is_null()) {
762  ASSERT(isolate->has_pending_exception());
763  isolate->clear_pending_exception();
764  return false;
765  }
766 
767  // Execute the shared function in the debugger context.
768  bool caught_exception;
769  Handle<JSFunction> function =
770  factory->NewFunctionFromSharedFunctionInfo(function_info, context);
771 
772  Handle<Object> exception =
773  Execution::TryCall(function, Handle<Object>(context->global_object()),
774  0, NULL, &caught_exception);
775 
776  // Check for caught exceptions.
777  if (caught_exception) {
778  ASSERT(!isolate->has_pending_exception());
779  MessageLocation computed_location;
780  isolate->ComputeLocation(&computed_location);
782  "error_loading_debugger", &computed_location,
783  Vector<Handle<Object> >::empty(), Handle<String>(), Handle<JSArray>());
784  ASSERT(!isolate->has_pending_exception());
785  isolate->set_pending_exception(*exception);
786  MessageHandler::ReportMessage(Isolate::Current(), NULL, message);
787  isolate->clear_pending_exception();
788  return false;
789  }
790 
791  // Mark this script as native and return successfully.
792  Handle<Script> script(Script::cast(function->shared()->script()));
793  script->set_type(Smi::FromInt(Script::TYPE_NATIVE));
794  return true;
795 }
796 
797 
798 bool Debug::Load() {
799  // Return if debugger is already loaded.
800  if (IsLoaded()) return true;
801 
802  Debugger* debugger = isolate_->debugger();
803 
804  // Bail out if we're already in the process of compiling the native
805  // JavaScript source code for the debugger.
806  if (debugger->compiling_natives() ||
807  debugger->is_loading_debugger())
808  return false;
809  debugger->set_loading_debugger(true);
810 
811  // Disable breakpoints and interrupts while compiling and running the
812  // debugger scripts including the context creation code.
813  DisableBreak disable(true);
814  PostponeInterruptsScope postpone(isolate_);
815 
816  // Create the debugger context.
817  HandleScope scope(isolate_);
818  Handle<Context> context =
819  isolate_->bootstrapper()->CreateEnvironment(
820  isolate_,
823  NULL);
824 
825  // Fail if no context could be created.
826  if (context.is_null()) return false;
827 
828  // Use the debugger context.
829  SaveContext save(isolate_);
830  isolate_->set_context(*context);
831 
832  // Expose the builtins object in the debugger context.
833  Handle<String> key = isolate_->factory()->LookupAsciiSymbol("builtins");
834  Handle<GlobalObject> global = Handle<GlobalObject>(context->global_object());
836  isolate_,
837  JSReceiver::SetProperty(global, key, Handle<Object>(global->builtins()),
839  false);
840 
841  // Compile the JavaScript for the debugger in the debugger context.
842  debugger->set_compiling_natives(true);
843  bool caught_exception =
844  !CompileDebuggerScript(Natives::GetIndex("mirror")) ||
845  !CompileDebuggerScript(Natives::GetIndex("debug"));
846 
847  if (FLAG_enable_liveedit) {
848  caught_exception = caught_exception ||
849  !CompileDebuggerScript(Natives::GetIndex("liveedit"));
850  }
851 
852  debugger->set_compiling_natives(false);
853 
854  // Make sure we mark the debugger as not loading before we might
855  // return.
856  debugger->set_loading_debugger(false);
857 
858  // Check for caught exceptions.
859  if (caught_exception) return false;
860 
861  // Debugger loaded.
862  debug_context_ = context;
863 
864  return true;
865 }
866 
867 
868 void Debug::Unload() {
869  // Return debugger is not loaded.
870  if (!IsLoaded()) {
871  return;
872  }
873 
874  // Clear the script cache.
875  DestroyScriptCache();
876 
877  // Clear debugger context global handle.
878  Isolate::Current()->global_handles()->Destroy(
879  reinterpret_cast<Object**>(debug_context_.location()));
880  debug_context_ = Handle<Context>();
881 }
882 
883 
884 // Set the flag indicating that preemption happened during debugging.
885 void Debug::PreemptionWhileInDebugger() {
886  ASSERT(InDebugger());
887  Debug::set_interrupts_pending(PREEMPT);
888 }
889 
890 
891 void Debug::Iterate(ObjectVisitor* v) {
892  v->VisitPointer(BitCast<Object**>(&(debug_break_return_)));
893  v->VisitPointer(BitCast<Object**>(&(debug_break_slot_)));
894 }
895 
896 
897 Object* Debug::Break(Arguments args) {
898  Heap* heap = isolate_->heap();
899  HandleScope scope(isolate_);
900  ASSERT(args.length() == 0);
901 
902  thread_local_.frame_drop_mode_ = FRAMES_UNTOUCHED;
903 
904  // Get the top-most JavaScript frame.
905  JavaScriptFrameIterator it(isolate_);
906  JavaScriptFrame* frame = it.frame();
907 
908  // Just continue if breaks are disabled or debugger cannot be loaded.
909  if (disable_break() || !Load()) {
910  SetAfterBreakTarget(frame);
911  return heap->undefined_value();
912  }
913 
914  // Enter the debugger.
915  EnterDebugger debugger;
916  if (debugger.FailedToEnter()) {
917  return heap->undefined_value();
918  }
919 
920  // Postpone interrupt during breakpoint processing.
921  PostponeInterruptsScope postpone(isolate_);
922 
923  // Get the debug info (create it if it does not exist).
924  Handle<SharedFunctionInfo> shared =
925  Handle<SharedFunctionInfo>(JSFunction::cast(frame->function())->shared());
926  Handle<DebugInfo> debug_info = GetDebugInfo(shared);
927 
928  // Find the break point where execution has stopped.
929  BreakLocationIterator break_location_iterator(debug_info,
930  ALL_BREAK_LOCATIONS);
931  break_location_iterator.FindBreakLocationFromAddress(frame->pc());
932 
933  // Check whether step next reached a new statement.
934  if (!StepNextContinue(&break_location_iterator, frame)) {
935  // Decrease steps left if performing multiple steps.
936  if (thread_local_.step_count_ > 0) {
937  thread_local_.step_count_--;
938  }
939  }
940 
941  // If there is one or more real break points check whether any of these are
942  // triggered.
943  Handle<Object> break_points_hit(heap->undefined_value());
944  if (break_location_iterator.HasBreakPoint()) {
945  Handle<Object> break_point_objects =
946  Handle<Object>(break_location_iterator.BreakPointObjects());
947  break_points_hit = CheckBreakPoints(break_point_objects);
948  }
949 
950  // If step out is active skip everything until the frame where we need to step
951  // out to is reached, unless real breakpoint is hit.
952  if (StepOutActive() && frame->fp() != step_out_fp() &&
953  break_points_hit->IsUndefined() ) {
954  // Step count should always be 0 for StepOut.
955  ASSERT(thread_local_.step_count_ == 0);
956  } else if (!break_points_hit->IsUndefined() ||
957  (thread_local_.last_step_action_ != StepNone &&
958  thread_local_.step_count_ == 0)) {
959  // Notify debugger if a real break point is triggered or if performing
960  // single stepping with no more steps to perform. Otherwise do another step.
961 
962  // Clear all current stepping setup.
963  ClearStepping();
964 
965  if (thread_local_.queued_step_count_ > 0) {
966  // Perform queued steps
967  int step_count = thread_local_.queued_step_count_;
968 
969  // Clear queue
970  thread_local_.queued_step_count_ = 0;
971 
972  PrepareStep(StepNext, step_count);
973  } else {
974  // Notify the debug event listeners.
975  isolate_->debugger()->OnDebugBreak(break_points_hit, false);
976  }
977  } else if (thread_local_.last_step_action_ != StepNone) {
978  // Hold on to last step action as it is cleared by the call to
979  // ClearStepping.
980  StepAction step_action = thread_local_.last_step_action_;
981  int step_count = thread_local_.step_count_;
982 
983  // If StepNext goes deeper in code, StepOut until original frame
984  // and keep step count queued up in the meantime.
985  if (step_action == StepNext && frame->fp() < thread_local_.last_fp_) {
986  // Count frames until target frame
987  int count = 0;
988  JavaScriptFrameIterator it(isolate_);
989  while (!it.done() && it.frame()->fp() < thread_local_.last_fp_) {
990  count++;
991  it.Advance();
992  }
993 
994  // Check that we indeed found the frame we are looking for.
995  CHECK(!it.done() && (it.frame()->fp() == thread_local_.last_fp_));
996  if (step_count > 1) {
997  // Save old count and action to continue stepping after StepOut.
998  thread_local_.queued_step_count_ = step_count - 1;
999  }
1000 
1001  // Set up for StepOut to reach target frame.
1002  step_action = StepOut;
1003  step_count = count;
1004  }
1005 
1006  // Clear all current stepping setup.
1007  ClearStepping();
1008 
1009  // Set up for the remaining steps.
1010  PrepareStep(step_action, step_count);
1011  }
1012 
1013  if (thread_local_.frame_drop_mode_ == FRAMES_UNTOUCHED) {
1014  SetAfterBreakTarget(frame);
1015  } else if (thread_local_.frame_drop_mode_ ==
1016  FRAME_DROPPED_IN_IC_CALL) {
1017  // We must have been calling IC stub. Do not go there anymore.
1018  Code* plain_return = isolate_->builtins()->builtin(
1019  Builtins::kPlainReturn_LiveEdit);
1020  thread_local_.after_break_target_ = plain_return->entry();
1021  } else if (thread_local_.frame_drop_mode_ ==
1022  FRAME_DROPPED_IN_DEBUG_SLOT_CALL) {
1023  // Debug break slot stub does not return normally, instead it manually
1024  // cleans the stack and jumps. We should patch the jump address.
1025  Code* plain_return = isolate_->builtins()->builtin(
1026  Builtins::kFrameDropper_LiveEdit);
1027  thread_local_.after_break_target_ = plain_return->entry();
1028  } else if (thread_local_.frame_drop_mode_ ==
1029  FRAME_DROPPED_IN_DIRECT_CALL) {
1030  // Nothing to do, after_break_target is not used here.
1031  } else if (thread_local_.frame_drop_mode_ ==
1032  FRAME_DROPPED_IN_RETURN_CALL) {
1033  Code* plain_return = isolate_->builtins()->builtin(
1034  Builtins::kFrameDropper_LiveEdit);
1035  thread_local_.after_break_target_ = plain_return->entry();
1036  } else {
1037  UNREACHABLE();
1038  }
1039 
1040  return heap->undefined_value();
1041 }
1042 
1043 
1044 RUNTIME_FUNCTION(Object*, Debug_Break) {
1045  return isolate->debug()->Break(args);
1046 }
1047 
1048 
1049 // Check the break point objects for whether one or more are actually
1050 // triggered. This function returns a JSArray with the break point objects
1051 // which is triggered.
1052 Handle<Object> Debug::CheckBreakPoints(Handle<Object> break_point_objects) {
1053  Factory* factory = isolate_->factory();
1054 
1055  // Count the number of break points hit. If there are multiple break points
1056  // they are in a FixedArray.
1057  Handle<FixedArray> break_points_hit;
1058  int break_points_hit_count = 0;
1059  ASSERT(!break_point_objects->IsUndefined());
1060  if (break_point_objects->IsFixedArray()) {
1061  Handle<FixedArray> array(FixedArray::cast(*break_point_objects));
1062  break_points_hit = factory->NewFixedArray(array->length());
1063  for (int i = 0; i < array->length(); i++) {
1064  Handle<Object> o(array->get(i));
1065  if (CheckBreakPoint(o)) {
1066  break_points_hit->set(break_points_hit_count++, *o);
1067  }
1068  }
1069  } else {
1070  break_points_hit = factory->NewFixedArray(1);
1071  if (CheckBreakPoint(break_point_objects)) {
1072  break_points_hit->set(break_points_hit_count++, *break_point_objects);
1073  }
1074  }
1075 
1076  // Return undefined if no break points were triggered.
1077  if (break_points_hit_count == 0) {
1078  return factory->undefined_value();
1079  }
1080  // Return break points hit as a JSArray.
1081  Handle<JSArray> result = factory->NewJSArrayWithElements(break_points_hit);
1082  result->set_length(Smi::FromInt(break_points_hit_count));
1083  return result;
1084 }
1085 
1086 
1087 // Check whether a single break point object is triggered.
1088 bool Debug::CheckBreakPoint(Handle<Object> break_point_object) {
1089  Factory* factory = isolate_->factory();
1090  HandleScope scope(isolate_);
1091 
1092  // Ignore check if break point object is not a JSObject.
1093  if (!break_point_object->IsJSObject()) return true;
1094 
1095  // Get the function IsBreakPointTriggered (defined in debug-debugger.js).
1096  Handle<String> is_break_point_triggered_symbol =
1097  factory->LookupAsciiSymbol("IsBreakPointTriggered");
1098  Handle<JSFunction> check_break_point =
1099  Handle<JSFunction>(JSFunction::cast(
1100  debug_context()->global_object()->GetPropertyNoExceptionThrown(
1101  *is_break_point_triggered_symbol)));
1102 
1103  // Get the break id as an object.
1104  Handle<Object> break_id = factory->NewNumberFromInt(Debug::break_id());
1105 
1106  // Call HandleBreakPointx.
1107  bool caught_exception;
1108  Handle<Object> argv[] = { break_id, break_point_object };
1109  Handle<Object> result = Execution::TryCall(check_break_point,
1110  isolate_->js_builtins_object(),
1111  ARRAY_SIZE(argv),
1112  argv,
1113  &caught_exception);
1114 
1115  // If exception or non boolean result handle as not triggered
1116  if (caught_exception || !result->IsBoolean()) {
1117  return false;
1118  }
1119 
1120  // Return whether the break point is triggered.
1121  ASSERT(!result.is_null());
1122  return (*result)->IsTrue();
1123 }
1124 
1125 
1126 // Check whether the function has debug information.
1127 bool Debug::HasDebugInfo(Handle<SharedFunctionInfo> shared) {
1128  return !shared->debug_info()->IsUndefined();
1129 }
1130 
1131 
1132 // Return the debug info for this function. EnsureDebugInfo must be called
1133 // prior to ensure the debug info has been generated for shared.
1134 Handle<DebugInfo> Debug::GetDebugInfo(Handle<SharedFunctionInfo> shared) {
1135  ASSERT(HasDebugInfo(shared));
1136  return Handle<DebugInfo>(DebugInfo::cast(shared->debug_info()));
1137 }
1138 
1139 
1140 void Debug::SetBreakPoint(Handle<JSFunction> function,
1141  Handle<Object> break_point_object,
1142  int* source_position) {
1143  HandleScope scope(isolate_);
1144 
1145  PrepareForBreakPoints();
1146 
1147  // Make sure the function is compiled and has set up the debug info.
1148  Handle<SharedFunctionInfo> shared(function->shared());
1149  if (!EnsureDebugInfo(shared, function)) {
1150  // Return if retrieving debug info failed.
1151  return;
1152  }
1153 
1154  Handle<DebugInfo> debug_info = GetDebugInfo(shared);
1155  // Source positions starts with zero.
1156  ASSERT(*source_position >= 0);
1157 
1158  // Find the break point and change it.
1159  BreakLocationIterator it(debug_info, SOURCE_BREAK_LOCATIONS);
1160  it.FindBreakLocationFromPosition(*source_position);
1161  it.SetBreakPoint(break_point_object);
1162 
1163  *source_position = it.position();
1164 
1165  // At least one active break point now.
1166  ASSERT(debug_info->GetBreakPointCount() > 0);
1167 }
1168 
1169 
1170 bool Debug::SetBreakPointForScript(Handle<Script> script,
1171  Handle<Object> break_point_object,
1172  int* source_position) {
1173  HandleScope scope(isolate_);
1174 
1175  PrepareForBreakPoints();
1176 
1177  // Obtain shared function info for the function.
1178  Object* result = FindSharedFunctionInfoInScript(script, *source_position);
1179  if (result->IsUndefined()) return false;
1180 
1181  // Make sure the function has set up the debug info.
1182  Handle<SharedFunctionInfo> shared(SharedFunctionInfo::cast(result));
1183  if (!EnsureDebugInfo(shared, Handle<JSFunction>::null())) {
1184  // Return if retrieving debug info failed.
1185  return false;
1186  }
1187 
1188  // Find position within function. The script position might be before the
1189  // source position of the first function.
1190  int position;
1191  if (shared->start_position() > *source_position) {
1192  position = 0;
1193  } else {
1194  position = *source_position - shared->start_position();
1195  }
1196 
1197  Handle<DebugInfo> debug_info = GetDebugInfo(shared);
1198  // Source positions starts with zero.
1199  ASSERT(position >= 0);
1200 
1201  // Find the break point and change it.
1202  BreakLocationIterator it(debug_info, SOURCE_BREAK_LOCATIONS);
1203  it.FindBreakLocationFromPosition(position);
1204  it.SetBreakPoint(break_point_object);
1205 
1206  *source_position = it.position() + shared->start_position();
1207 
1208  // At least one active break point now.
1209  ASSERT(debug_info->GetBreakPointCount() > 0);
1210  return true;
1211 }
1212 
1213 
1214 void Debug::ClearBreakPoint(Handle<Object> break_point_object) {
1215  HandleScope scope(isolate_);
1216 
1217  DebugInfoListNode* node = debug_info_list_;
1218  while (node != NULL) {
1219  Object* result = DebugInfo::FindBreakPointInfo(node->debug_info(),
1220  break_point_object);
1221  if (!result->IsUndefined()) {
1222  // Get information in the break point.
1223  BreakPointInfo* break_point_info = BreakPointInfo::cast(result);
1224  Handle<DebugInfo> debug_info = node->debug_info();
1225  Handle<SharedFunctionInfo> shared(debug_info->shared());
1226  int source_position = break_point_info->statement_position()->value();
1227 
1228  // Source positions starts with zero.
1229  ASSERT(source_position >= 0);
1230 
1231  // Find the break point and clear it.
1232  BreakLocationIterator it(debug_info, SOURCE_BREAK_LOCATIONS);
1233  it.FindBreakLocationFromPosition(source_position);
1234  it.ClearBreakPoint(break_point_object);
1235 
1236  // If there are no more break points left remove the debug info for this
1237  // function.
1238  if (debug_info->GetBreakPointCount() == 0) {
1239  RemoveDebugInfo(debug_info);
1240  }
1241 
1242  return;
1243  }
1244  node = node->next();
1245  }
1246 }
1247 
1248 
1249 void Debug::ClearAllBreakPoints() {
1250  DebugInfoListNode* node = debug_info_list_;
1251  while (node != NULL) {
1252  // Remove all debug break code.
1253  BreakLocationIterator it(node->debug_info(), ALL_BREAK_LOCATIONS);
1254  it.ClearAllDebugBreak();
1255  node = node->next();
1256  }
1257 
1258  // Remove all debug info.
1259  while (debug_info_list_ != NULL) {
1260  RemoveDebugInfo(debug_info_list_->debug_info());
1261  }
1262 }
1263 
1264 
1265 void Debug::FloodWithOneShot(Handle<JSFunction> function) {
1266  PrepareForBreakPoints();
1267 
1268  // Make sure the function is compiled and has set up the debug info.
1269  Handle<SharedFunctionInfo> shared(function->shared());
1270  if (!EnsureDebugInfo(shared, function)) {
1271  // Return if we failed to retrieve the debug info.
1272  return;
1273  }
1274 
1275  // Flood the function with break points.
1276  BreakLocationIterator it(GetDebugInfo(shared), ALL_BREAK_LOCATIONS);
1277  while (!it.Done()) {
1278  it.SetOneShot();
1279  it.Next();
1280  }
1281 }
1282 
1283 
1284 void Debug::FloodBoundFunctionWithOneShot(Handle<JSFunction> function) {
1285  Handle<FixedArray> new_bindings(function->function_bindings());
1286  Handle<Object> bindee(new_bindings->get(JSFunction::kBoundFunctionIndex));
1287 
1288  if (!bindee.is_null() && bindee->IsJSFunction() &&
1289  !JSFunction::cast(*bindee)->IsBuiltin()) {
1290  Handle<JSFunction> bindee_function(JSFunction::cast(*bindee));
1291  Debug::FloodWithOneShot(bindee_function);
1292  }
1293 }
1294 
1295 
1296 void Debug::FloodHandlerWithOneShot() {
1297  // Iterate through the JavaScript stack looking for handlers.
1298  StackFrame::Id id = break_frame_id();
1299  if (id == StackFrame::NO_ID) {
1300  // If there is no JavaScript stack don't do anything.
1301  return;
1302  }
1303  for (JavaScriptFrameIterator it(isolate_, id); !it.done(); it.Advance()) {
1304  JavaScriptFrame* frame = it.frame();
1305  if (frame->HasHandler()) {
1306  // Flood the function with the catch block with break points
1307  JSFunction* function = JSFunction::cast(frame->function());
1308  FloodWithOneShot(Handle<JSFunction>(function));
1309  return;
1310  }
1311  }
1312 }
1313 
1314 
1315 void Debug::ChangeBreakOnException(ExceptionBreakType type, bool enable) {
1316  if (type == BreakUncaughtException) {
1317  break_on_uncaught_exception_ = enable;
1318  } else {
1319  break_on_exception_ = enable;
1320  }
1321 }
1322 
1323 
1324 bool Debug::IsBreakOnException(ExceptionBreakType type) {
1325  if (type == BreakUncaughtException) {
1326  return break_on_uncaught_exception_;
1327  } else {
1328  return break_on_exception_;
1329  }
1330 }
1331 
1332 
1333 void Debug::PrepareStep(StepAction step_action, int step_count) {
1334  HandleScope scope(isolate_);
1335 
1336  PrepareForBreakPoints();
1337 
1338  ASSERT(Debug::InDebugger());
1339 
1340  // Remember this step action and count.
1341  thread_local_.last_step_action_ = step_action;
1342  if (step_action == StepOut) {
1343  // For step out target frame will be found on the stack so there is no need
1344  // to set step counter for it. It's expected to always be 0 for StepOut.
1345  thread_local_.step_count_ = 0;
1346  } else {
1347  thread_local_.step_count_ = step_count;
1348  }
1349 
1350  // Get the frame where the execution has stopped and skip the debug frame if
1351  // any. The debug frame will only be present if execution was stopped due to
1352  // hitting a break point. In other situations (e.g. unhandled exception) the
1353  // debug frame is not present.
1354  StackFrame::Id id = break_frame_id();
1355  if (id == StackFrame::NO_ID) {
1356  // If there is no JavaScript stack don't do anything.
1357  return;
1358  }
1359  JavaScriptFrameIterator frames_it(isolate_, id);
1360  JavaScriptFrame* frame = frames_it.frame();
1361 
1362  // First of all ensure there is one-shot break points in the top handler
1363  // if any.
1364  FloodHandlerWithOneShot();
1365 
1366  // If the function on the top frame is unresolved perform step out. This will
1367  // be the case when calling unknown functions and having the debugger stopped
1368  // in an unhandled exception.
1369  if (!frame->function()->IsJSFunction()) {
1370  // Step out: Find the calling JavaScript frame and flood it with
1371  // breakpoints.
1372  frames_it.Advance();
1373  // Fill the function to return to with one-shot break points.
1374  JSFunction* function = JSFunction::cast(frames_it.frame()->function());
1375  FloodWithOneShot(Handle<JSFunction>(function));
1376  return;
1377  }
1378 
1379  // Get the debug info (create it if it does not exist).
1380  Handle<JSFunction> function(JSFunction::cast(frame->function()));
1381  Handle<SharedFunctionInfo> shared(function->shared());
1382  if (!EnsureDebugInfo(shared, function)) {
1383  // Return if ensuring debug info failed.
1384  return;
1385  }
1386  Handle<DebugInfo> debug_info = GetDebugInfo(shared);
1387 
1388  // Find the break location where execution has stopped.
1389  BreakLocationIterator it(debug_info, ALL_BREAK_LOCATIONS);
1390  it.FindBreakLocationFromAddress(frame->pc());
1391 
1392  // Compute whether or not the target is a call target.
1393  bool is_load_or_store = false;
1394  bool is_inline_cache_stub = false;
1395  bool is_at_restarted_function = false;
1396  Handle<Code> call_function_stub;
1397 
1398  if (thread_local_.restarter_frame_function_pointer_ == NULL) {
1399  if (RelocInfo::IsCodeTarget(it.rinfo()->rmode())) {
1400  bool is_call_target = false;
1401  Address target = it.rinfo()->target_address();
1402  Code* code = Code::GetCodeFromTargetAddress(target);
1403  if (code->is_call_stub() || code->is_keyed_call_stub()) {
1404  is_call_target = true;
1405  }
1406  if (code->is_inline_cache_stub()) {
1407  is_inline_cache_stub = true;
1408  is_load_or_store = !is_call_target;
1409  }
1410 
1411  // Check if target code is CallFunction stub.
1412  Code* maybe_call_function_stub = code;
1413  // If there is a breakpoint at this line look at the original code to
1414  // check if it is a CallFunction stub.
1415  if (it.IsDebugBreak()) {
1416  Address original_target = it.original_rinfo()->target_address();
1417  maybe_call_function_stub =
1418  Code::GetCodeFromTargetAddress(original_target);
1419  }
1420  if (maybe_call_function_stub->kind() == Code::STUB &&
1421  maybe_call_function_stub->major_key() == CodeStub::CallFunction) {
1422  // Save reference to the code as we may need it to find out arguments
1423  // count for 'step in' later.
1424  call_function_stub = Handle<Code>(maybe_call_function_stub);
1425  }
1426  }
1427  } else {
1428  is_at_restarted_function = true;
1429  }
1430 
1431  // If this is the last break code target step out is the only possibility.
1432  if (it.IsExit() || step_action == StepOut) {
1433  if (step_action == StepOut) {
1434  // Skip step_count frames starting with the current one.
1435  while (step_count-- > 0 && !frames_it.done()) {
1436  frames_it.Advance();
1437  }
1438  } else {
1439  ASSERT(it.IsExit());
1440  frames_it.Advance();
1441  }
1442  // Skip builtin functions on the stack.
1443  while (!frames_it.done() &&
1444  JSFunction::cast(frames_it.frame()->function())->IsBuiltin()) {
1445  frames_it.Advance();
1446  }
1447  // Step out: If there is a JavaScript caller frame, we need to
1448  // flood it with breakpoints.
1449  if (!frames_it.done()) {
1450  // Fill the function to return to with one-shot break points.
1451  JSFunction* function = JSFunction::cast(frames_it.frame()->function());
1452  FloodWithOneShot(Handle<JSFunction>(function));
1453  // Set target frame pointer.
1454  ActivateStepOut(frames_it.frame());
1455  }
1456  } else if (!(is_inline_cache_stub || RelocInfo::IsConstructCall(it.rmode()) ||
1457  !call_function_stub.is_null() || is_at_restarted_function)
1458  || step_action == StepNext || step_action == StepMin) {
1459  // Step next or step min.
1460 
1461  // Fill the current function with one-shot break points.
1462  FloodWithOneShot(function);
1463 
1464  // Remember source position and frame to handle step next.
1465  thread_local_.last_statement_position_ =
1466  debug_info->code()->SourceStatementPosition(frame->pc());
1467  thread_local_.last_fp_ = frame->UnpaddedFP();
1468  } else {
1469  // If there's restarter frame on top of the stack, just get the pointer
1470  // to function which is going to be restarted.
1471  if (is_at_restarted_function) {
1472  Handle<JSFunction> restarted_function(
1473  JSFunction::cast(*thread_local_.restarter_frame_function_pointer_));
1474  FloodWithOneShot(restarted_function);
1475  } else if (!call_function_stub.is_null()) {
1476  // If it's CallFunction stub ensure target function is compiled and flood
1477  // it with one shot breakpoints.
1478 
1479  // Find out number of arguments from the stub minor key.
1480  // Reverse lookup required as the minor key cannot be retrieved
1481  // from the code object.
1482  Handle<Object> obj(
1483  isolate_->heap()->code_stubs()->SlowReverseLookup(
1484  *call_function_stub));
1485  ASSERT(!obj.is_null());
1486  ASSERT(!(*obj)->IsUndefined());
1487  ASSERT(obj->IsSmi());
1488  // Get the STUB key and extract major and minor key.
1489  uint32_t key = Smi::cast(*obj)->value();
1490  // Argc in the stub is the number of arguments passed - not the
1491  // expected arguments of the called function.
1492  int call_function_arg_count =
1494  CodeStub::MinorKeyFromKey(key));
1495  ASSERT(call_function_stub->major_key() ==
1496  CodeStub::MajorKeyFromKey(key));
1497 
1498  // Find target function on the expression stack.
1499  // Expression stack looks like this (top to bottom):
1500  // argN
1501  // ...
1502  // arg0
1503  // Receiver
1504  // Function to call
1505  int expressions_count = frame->ComputeExpressionsCount();
1506  ASSERT(expressions_count - 2 - call_function_arg_count >= 0);
1507  Object* fun = frame->GetExpression(
1508  expressions_count - 2 - call_function_arg_count);
1509  if (fun->IsJSFunction()) {
1510  Handle<JSFunction> js_function(JSFunction::cast(fun));
1511  if (js_function->shared()->bound()) {
1512  Debug::FloodBoundFunctionWithOneShot(js_function);
1513  } else if (!js_function->IsBuiltin()) {
1514  // Don't step into builtins.
1515  // It will also compile target function if it's not compiled yet.
1516  FloodWithOneShot(js_function);
1517  }
1518  }
1519  }
1520 
1521  // Fill the current function with one-shot break points even for step in on
1522  // a call target as the function called might be a native function for
1523  // which step in will not stop. It also prepares for stepping in
1524  // getters/setters.
1525  FloodWithOneShot(function);
1526 
1527  if (is_load_or_store) {
1528  // Remember source position and frame to handle step in getter/setter. If
1529  // there is a custom getter/setter it will be handled in
1530  // Object::Get/SetPropertyWithCallback, otherwise the step action will be
1531  // propagated on the next Debug::Break.
1532  thread_local_.last_statement_position_ =
1533  debug_info->code()->SourceStatementPosition(frame->pc());
1534  thread_local_.last_fp_ = frame->UnpaddedFP();
1535  }
1536 
1537  // Step in or Step in min
1538  it.PrepareStepIn();
1539  ActivateStepIn(frame);
1540  }
1541 }
1542 
1543 
1544 // Check whether the current debug break should be reported to the debugger. It
1545 // is used to have step next and step in only report break back to the debugger
1546 // if on a different frame or in a different statement. In some situations
1547 // there will be several break points in the same statement when the code is
1548 // flooded with one-shot break points. This function helps to perform several
1549 // steps before reporting break back to the debugger.
1550 bool Debug::StepNextContinue(BreakLocationIterator* break_location_iterator,
1551  JavaScriptFrame* frame) {
1552  // StepNext and StepOut shouldn't bring us deeper in code, so last frame
1553  // shouldn't be a parent of current frame.
1554  if (thread_local_.last_step_action_ == StepNext ||
1555  thread_local_.last_step_action_ == StepOut) {
1556  if (frame->fp() < thread_local_.last_fp_) return true;
1557  }
1558 
1559  // If the step last action was step next or step in make sure that a new
1560  // statement is hit.
1561  if (thread_local_.last_step_action_ == StepNext ||
1562  thread_local_.last_step_action_ == StepIn) {
1563  // Never continue if returning from function.
1564  if (break_location_iterator->IsExit()) return false;
1565 
1566  // Continue if we are still on the same frame and in the same statement.
1567  int current_statement_position =
1568  break_location_iterator->code()->SourceStatementPosition(frame->pc());
1569  return thread_local_.last_fp_ == frame->UnpaddedFP() &&
1570  thread_local_.last_statement_position_ == current_statement_position;
1571  }
1572 
1573  // No step next action - don't continue.
1574  return false;
1575 }
1576 
1577 
1578 // Check whether the code object at the specified address is a debug break code
1579 // object.
1580 bool Debug::IsDebugBreak(Address addr) {
1581  Code* code = Code::GetCodeFromTargetAddress(addr);
1582  return code->ic_state() == DEBUG_BREAK;
1583 }
1584 
1585 
1586 // Check whether a code stub with the specified major key is a possible break
1587 // point location when looking for source break locations.
1588 bool Debug::IsSourceBreakStub(Code* code) {
1589  CodeStub::Major major_key = CodeStub::GetMajorKey(code);
1590  return major_key == CodeStub::CallFunction;
1591 }
1592 
1593 
1594 // Check whether a code stub with the specified major key is a possible break
1595 // location.
1596 bool Debug::IsBreakStub(Code* code) {
1597  CodeStub::Major major_key = CodeStub::GetMajorKey(code);
1598  return major_key == CodeStub::CallFunction;
1599 }
1600 
1601 
1602 // Find the builtin to use for invoking the debug break
1603 Handle<Code> Debug::FindDebugBreak(Handle<Code> code, RelocInfo::Mode mode) {
1604  Isolate* isolate = Isolate::Current();
1605 
1606  // Find the builtin debug break function matching the calling convention
1607  // used by the call site.
1608  if (code->is_inline_cache_stub()) {
1609  switch (code->kind()) {
1610  case Code::CALL_IC:
1611  case Code::KEYED_CALL_IC:
1612  return isolate->stub_cache()->ComputeCallDebugBreak(
1613  code->arguments_count(), code->kind());
1614 
1615  case Code::LOAD_IC:
1616  return isolate->builtins()->LoadIC_DebugBreak();
1617 
1618  case Code::STORE_IC:
1619  return isolate->builtins()->StoreIC_DebugBreak();
1620 
1621  case Code::KEYED_LOAD_IC:
1622  return isolate->builtins()->KeyedLoadIC_DebugBreak();
1623 
1624  case Code::KEYED_STORE_IC:
1625  return isolate->builtins()->KeyedStoreIC_DebugBreak();
1626 
1627  default:
1628  UNREACHABLE();
1629  }
1630  }
1631  if (RelocInfo::IsConstructCall(mode)) {
1632  if (code->has_function_cache()) {
1633  return isolate->builtins()->CallConstructStub_Recording_DebugBreak();
1634  } else {
1635  return isolate->builtins()->CallConstructStub_DebugBreak();
1636  }
1637  }
1638  if (code->kind() == Code::STUB) {
1639  ASSERT(code->major_key() == CodeStub::CallFunction);
1640  if (code->has_function_cache()) {
1641  return isolate->builtins()->CallFunctionStub_Recording_DebugBreak();
1642  } else {
1643  return isolate->builtins()->CallFunctionStub_DebugBreak();
1644  }
1645  }
1646 
1647  UNREACHABLE();
1648  return Handle<Code>::null();
1649 }
1650 
1651 
1652 // Simple function for returning the source positions for active break points.
1653 Handle<Object> Debug::GetSourceBreakLocations(
1654  Handle<SharedFunctionInfo> shared) {
1655  Isolate* isolate = Isolate::Current();
1656  Heap* heap = isolate->heap();
1657  if (!HasDebugInfo(shared)) return Handle<Object>(heap->undefined_value());
1658  Handle<DebugInfo> debug_info = GetDebugInfo(shared);
1659  if (debug_info->GetBreakPointCount() == 0) {
1660  return Handle<Object>(heap->undefined_value());
1661  }
1662  Handle<FixedArray> locations =
1663  isolate->factory()->NewFixedArray(debug_info->GetBreakPointCount());
1664  int count = 0;
1665  for (int i = 0; i < debug_info->break_points()->length(); i++) {
1666  if (!debug_info->break_points()->get(i)->IsUndefined()) {
1667  BreakPointInfo* break_point_info =
1668  BreakPointInfo::cast(debug_info->break_points()->get(i));
1669  if (break_point_info->GetBreakPointCount() > 0) {
1670  locations->set(count++, break_point_info->statement_position());
1671  }
1672  }
1673  }
1674  return locations;
1675 }
1676 
1677 
1678 void Debug::NewBreak(StackFrame::Id break_frame_id) {
1679  thread_local_.break_frame_id_ = break_frame_id;
1680  thread_local_.break_id_ = ++thread_local_.break_count_;
1681 }
1682 
1683 
1684 void Debug::SetBreak(StackFrame::Id break_frame_id, int break_id) {
1685  thread_local_.break_frame_id_ = break_frame_id;
1686  thread_local_.break_id_ = break_id;
1687 }
1688 
1689 
1690 // Handle stepping into a function.
1691 void Debug::HandleStepIn(Handle<JSFunction> function,
1692  Handle<Object> holder,
1693  Address fp,
1694  bool is_constructor) {
1695  // If the frame pointer is not supplied by the caller find it.
1696  if (fp == 0) {
1697  StackFrameIterator it;
1698  it.Advance();
1699  // For constructor functions skip another frame.
1700  if (is_constructor) {
1701  ASSERT(it.frame()->is_construct());
1702  it.Advance();
1703  }
1704  fp = it.frame()->fp();
1705  }
1706 
1707  // Flood the function with one-shot break points if it is called from where
1708  // step into was requested.
1709  if (fp == step_in_fp()) {
1710  if (function->shared()->bound()) {
1711  // Handle Function.prototype.bind
1712  Debug::FloodBoundFunctionWithOneShot(function);
1713  } else if (!function->IsBuiltin()) {
1714  // Don't allow step into functions in the native context.
1715  if (function->shared()->code() ==
1716  Isolate::Current()->builtins()->builtin(Builtins::kFunctionApply) ||
1717  function->shared()->code() ==
1718  Isolate::Current()->builtins()->builtin(Builtins::kFunctionCall)) {
1719  // Handle function.apply and function.call separately to flood the
1720  // function to be called and not the code for Builtins::FunctionApply or
1721  // Builtins::FunctionCall. The receiver of call/apply is the target
1722  // function.
1723  if (!holder.is_null() && holder->IsJSFunction() &&
1724  !JSFunction::cast(*holder)->IsBuiltin()) {
1725  Handle<JSFunction> js_function = Handle<JSFunction>::cast(holder);
1726  Debug::FloodWithOneShot(js_function);
1727  }
1728  } else {
1729  Debug::FloodWithOneShot(function);
1730  }
1731  }
1732  }
1733 }
1734 
1735 
1736 void Debug::ClearStepping() {
1737  // Clear the various stepping setup.
1738  ClearOneShot();
1739  ClearStepIn();
1740  ClearStepOut();
1741  ClearStepNext();
1742 
1743  // Clear multiple step counter.
1744  thread_local_.step_count_ = 0;
1745 }
1746 
1747 // Clears all the one-shot break points that are currently set. Normally this
1748 // function is called each time a break point is hit as one shot break points
1749 // are used to support stepping.
1750 void Debug::ClearOneShot() {
1751  // The current implementation just runs through all the breakpoints. When the
1752  // last break point for a function is removed that function is automatically
1753  // removed from the list.
1754 
1755  DebugInfoListNode* node = debug_info_list_;
1756  while (node != NULL) {
1757  BreakLocationIterator it(node->debug_info(), ALL_BREAK_LOCATIONS);
1758  while (!it.Done()) {
1759  it.ClearOneShot();
1760  it.Next();
1761  }
1762  node = node->next();
1763  }
1764 }
1765 
1766 
1767 void Debug::ActivateStepIn(StackFrame* frame) {
1768  ASSERT(!StepOutActive());
1769  thread_local_.step_into_fp_ = frame->UnpaddedFP();
1770 }
1771 
1772 
1773 void Debug::ClearStepIn() {
1774  thread_local_.step_into_fp_ = 0;
1775 }
1776 
1777 
1778 void Debug::ActivateStepOut(StackFrame* frame) {
1779  ASSERT(!StepInActive());
1780  thread_local_.step_out_fp_ = frame->UnpaddedFP();
1781 }
1782 
1783 
1784 void Debug::ClearStepOut() {
1785  thread_local_.step_out_fp_ = 0;
1786 }
1787 
1788 
1789 void Debug::ClearStepNext() {
1790  thread_local_.last_step_action_ = StepNone;
1791  thread_local_.last_statement_position_ = RelocInfo::kNoPosition;
1792  thread_local_.last_fp_ = 0;
1793 }
1794 
1795 
1796 // Helper function to compile full code for debugging. This code will
1797 // have debug break slots and deoptimization information. Deoptimization
1798 // information is required in case that an optimized version of this
1799 // function is still activated on the stack. It will also make sure that
1800 // the full code is compiled with the same flags as the previous version,
1801 // that is flags which can change the code generated. The current method
1802 // of mapping from already compiled full code without debug break slots
1803 // to full code with debug break slots depends on the generated code is
1804 // otherwise exactly the same.
1805 static bool CompileFullCodeForDebugging(Handle<JSFunction> function,
1806  Handle<Code> current_code) {
1807  ASSERT(!current_code->has_debug_break_slots());
1808 
1809  CompilationInfoWithZone info(function);
1810  info.MarkCompilingForDebugging(current_code);
1811  ASSERT(!info.shared_info()->is_compiled());
1812  ASSERT(!info.isolate()->has_pending_exception());
1813 
1814  // Use compile lazy which will end up compiling the full code in the
1815  // configuration configured above.
1816  bool result = Compiler::CompileLazy(&info);
1817  ASSERT(result != Isolate::Current()->has_pending_exception());
1818  info.isolate()->clear_pending_exception();
1819 #if DEBUG
1820  if (result) {
1821  Handle<Code> new_code(function->shared()->code());
1822  ASSERT(new_code->has_debug_break_slots());
1823  ASSERT(current_code->is_compiled_optimizable() ==
1824  new_code->is_compiled_optimizable());
1825  }
1826 #endif
1827  return result;
1828 }
1829 
1830 
1831 static void CollectActiveFunctionsFromThread(
1832  Isolate* isolate,
1833  ThreadLocalTop* top,
1834  List<Handle<JSFunction> >* active_functions,
1835  Object* active_code_marker) {
1836  // Find all non-optimized code functions with activation frames
1837  // on the stack. This includes functions which have optimized
1838  // activations (including inlined functions) on the stack as the
1839  // non-optimized code is needed for the lazy deoptimization.
1840  for (JavaScriptFrameIterator it(isolate, top); !it.done(); it.Advance()) {
1841  JavaScriptFrame* frame = it.frame();
1842  if (frame->is_optimized()) {
1843  List<JSFunction*> functions(Compiler::kMaxInliningLevels + 1);
1844  frame->GetFunctions(&functions);
1845  for (int i = 0; i < functions.length(); i++) {
1846  JSFunction* function = functions[i];
1847  active_functions->Add(Handle<JSFunction>(function));
1848  function->shared()->code()->set_gc_metadata(active_code_marker);
1849  }
1850  } else if (frame->function()->IsJSFunction()) {
1851  JSFunction* function = JSFunction::cast(frame->function());
1852  ASSERT(frame->LookupCode()->kind() == Code::FUNCTION);
1853  active_functions->Add(Handle<JSFunction>(function));
1854  function->shared()->code()->set_gc_metadata(active_code_marker);
1855  }
1856  }
1857 }
1858 
1859 
1860 static void RedirectActivationsToRecompiledCodeOnThread(
1861  Isolate* isolate,
1862  ThreadLocalTop* top) {
1863  for (JavaScriptFrameIterator it(isolate, top); !it.done(); it.Advance()) {
1864  JavaScriptFrame* frame = it.frame();
1865 
1866  if (frame->is_optimized() || !frame->function()->IsJSFunction()) continue;
1867 
1868  JSFunction* function = JSFunction::cast(frame->function());
1869 
1870  ASSERT(frame->LookupCode()->kind() == Code::FUNCTION);
1871 
1872  Handle<Code> frame_code(frame->LookupCode());
1873  if (frame_code->has_debug_break_slots()) continue;
1874 
1875  Handle<Code> new_code(function->shared()->code());
1876  if (new_code->kind() != Code::FUNCTION ||
1877  !new_code->has_debug_break_slots()) {
1878  continue;
1879  }
1880 
1881  // Iterate over the RelocInfo in the original code to compute the sum of the
1882  // constant pools sizes. (See Assembler::CheckConstPool())
1883  // Note that this is only useful for architectures using constant pools.
1884  int constpool_mask = RelocInfo::ModeMask(RelocInfo::CONST_POOL);
1885  int frame_const_pool_size = 0;
1886  for (RelocIterator it(*frame_code, constpool_mask); !it.done(); it.next()) {
1887  RelocInfo* info = it.rinfo();
1888  if (info->pc() >= frame->pc()) break;
1889  frame_const_pool_size += static_cast<int>(info->data());
1890  }
1891  intptr_t frame_offset =
1892  frame->pc() - frame_code->instruction_start() - frame_const_pool_size;
1893 
1894  // Iterate over the RelocInfo for new code to find the number of bytes
1895  // generated for debug slots and constant pools.
1896  int debug_break_slot_bytes = 0;
1897  int new_code_const_pool_size = 0;
1898  int mask = RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT) |
1899  RelocInfo::ModeMask(RelocInfo::CONST_POOL);
1900  for (RelocIterator it(*new_code, mask); !it.done(); it.next()) {
1901  // Check if the pc in the new code with debug break
1902  // slots is before this slot.
1903  RelocInfo* info = it.rinfo();
1904  intptr_t new_offset = info->pc() - new_code->instruction_start() -
1905  new_code_const_pool_size - debug_break_slot_bytes;
1906  if (new_offset >= frame_offset) {
1907  break;
1908  }
1909 
1910  if (RelocInfo::IsDebugBreakSlot(info->rmode())) {
1911  debug_break_slot_bytes += Assembler::kDebugBreakSlotLength;
1912  } else {
1913  ASSERT(RelocInfo::IsConstPool(info->rmode()));
1914  // The size of the constant pool is encoded in the data.
1915  new_code_const_pool_size += static_cast<int>(info->data());
1916  }
1917  }
1918 
1919  // Compute the equivalent pc in the new code.
1920  byte* new_pc = new_code->instruction_start() + frame_offset +
1921  debug_break_slot_bytes + new_code_const_pool_size;
1922 
1923  if (FLAG_trace_deopt) {
1924  PrintF("Replacing code %08" V8PRIxPTR " - %08" V8PRIxPTR " (%d) "
1925  "with %08" V8PRIxPTR " - %08" V8PRIxPTR " (%d) "
1926  "for debugging, "
1927  "changing pc from %08" V8PRIxPTR " to %08" V8PRIxPTR "\n",
1928  reinterpret_cast<intptr_t>(
1929  frame_code->instruction_start()),
1930  reinterpret_cast<intptr_t>(
1931  frame_code->instruction_start()) +
1932  frame_code->instruction_size(),
1933  frame_code->instruction_size(),
1934  reinterpret_cast<intptr_t>(new_code->instruction_start()),
1935  reinterpret_cast<intptr_t>(new_code->instruction_start()) +
1936  new_code->instruction_size(),
1937  new_code->instruction_size(),
1938  reinterpret_cast<intptr_t>(frame->pc()),
1939  reinterpret_cast<intptr_t>(new_pc));
1940  }
1941 
1942  // Patch the return address to return into the code with
1943  // debug break slots.
1944  frame->set_pc(new_pc);
1945  }
1946 }
1947 
1948 
1949 class ActiveFunctionsCollector : public ThreadVisitor {
1950  public:
1951  explicit ActiveFunctionsCollector(List<Handle<JSFunction> >* active_functions,
1952  Object* active_code_marker)
1953  : active_functions_(active_functions),
1954  active_code_marker_(active_code_marker) { }
1955 
1956  void VisitThread(Isolate* isolate, ThreadLocalTop* top) {
1957  CollectActiveFunctionsFromThread(isolate,
1958  top,
1959  active_functions_,
1960  active_code_marker_);
1961  }
1962 
1963  private:
1964  List<Handle<JSFunction> >* active_functions_;
1965  Object* active_code_marker_;
1966 };
1967 
1968 
1969 class ActiveFunctionsRedirector : public ThreadVisitor {
1970  public:
1971  void VisitThread(Isolate* isolate, ThreadLocalTop* top) {
1972  RedirectActivationsToRecompiledCodeOnThread(isolate, top);
1973  }
1974 };
1975 
1976 
1977 void Debug::PrepareForBreakPoints() {
1978  // If preparing for the first break point make sure to deoptimize all
1979  // functions as debugging does not work with optimized code.
1980  if (!has_break_points_) {
1982 
1983  Handle<Code> lazy_compile =
1984  Handle<Code>(isolate_->builtins()->builtin(Builtins::kLazyCompile));
1985 
1986  // There will be at least one break point when we are done.
1987  has_break_points_ = true;
1988 
1989  // Keep the list of activated functions in a handlified list as it
1990  // is used both in GC and non-GC code.
1991  List<Handle<JSFunction> > active_functions(100);
1992 
1993  {
1994  // We are going to iterate heap to find all functions without
1995  // debug break slots.
1996  isolate_->heap()->CollectAllGarbage(Heap::kMakeHeapIterableMask,
1997  "preparing for breakpoints");
1998 
1999  // Ensure no GC in this scope as we are going to use gc_metadata
2000  // field in the Code object to mark active functions.
2001  AssertNoAllocation no_allocation;
2002 
2003  Object* active_code_marker = isolate_->heap()->the_hole_value();
2004 
2005  CollectActiveFunctionsFromThread(isolate_,
2006  isolate_->thread_local_top(),
2007  &active_functions,
2008  active_code_marker);
2009  ActiveFunctionsCollector active_functions_collector(&active_functions,
2010  active_code_marker);
2011  isolate_->thread_manager()->IterateArchivedThreads(
2012  &active_functions_collector);
2013 
2014  // Scan the heap for all non-optimized functions which have no
2015  // debug break slots and are not active or inlined into an active
2016  // function and mark them for lazy compilation.
2017  HeapIterator iterator;
2018  HeapObject* obj = NULL;
2019  while (((obj = iterator.next()) != NULL)) {
2020  if (obj->IsJSFunction()) {
2021  JSFunction* function = JSFunction::cast(obj);
2022  SharedFunctionInfo* shared = function->shared();
2023  if (shared->allows_lazy_compilation() &&
2024  shared->script()->IsScript() &&
2025  function->code()->kind() == Code::FUNCTION &&
2026  !function->code()->has_debug_break_slots() &&
2027  shared->code()->gc_metadata() != active_code_marker) {
2028  function->set_code(*lazy_compile);
2029  function->shared()->set_code(*lazy_compile);
2030  }
2031  }
2032  }
2033 
2034  // Clear gc_metadata field.
2035  for (int i = 0; i < active_functions.length(); i++) {
2036  Handle<JSFunction> function = active_functions[i];
2037  function->shared()->code()->set_gc_metadata(Smi::FromInt(0));
2038  }
2039  }
2040 
2041  // Now recompile all functions with activation frames and and
2042  // patch the return address to run in the new compiled code.
2043  for (int i = 0; i < active_functions.length(); i++) {
2044  Handle<JSFunction> function = active_functions[i];
2045  Handle<SharedFunctionInfo> shared(function->shared());
2046 
2047  if (function->code()->kind() == Code::FUNCTION &&
2048  function->code()->has_debug_break_slots()) {
2049  // Nothing to do. Function code already had debug break slots.
2050  continue;
2051  }
2052 
2053  // If recompilation is not possible just skip it.
2054  if (shared->is_toplevel() ||
2055  !shared->allows_lazy_compilation() ||
2056  shared->code()->kind() == Code::BUILTIN) {
2057  continue;
2058  }
2059 
2060  // Make sure that the shared full code is compiled with debug
2061  // break slots.
2062  if (!shared->code()->has_debug_break_slots()) {
2063  // Try to compile the full code with debug break slots. If it
2064  // fails just keep the current code.
2065  Handle<Code> current_code(function->shared()->code());
2066  shared->set_code(*lazy_compile);
2067  bool prev_force_debugger_active =
2068  isolate_->debugger()->force_debugger_active();
2069  isolate_->debugger()->set_force_debugger_active(true);
2070  ASSERT(current_code->kind() == Code::FUNCTION);
2071  CompileFullCodeForDebugging(function, current_code);
2072  isolate_->debugger()->set_force_debugger_active(
2073  prev_force_debugger_active);
2074  if (!shared->is_compiled()) {
2075  shared->set_code(*current_code);
2076  continue;
2077  }
2078  }
2079 
2080  // Keep function code in sync with shared function info.
2081  function->set_code(shared->code());
2082  }
2083 
2084  RedirectActivationsToRecompiledCodeOnThread(isolate_,
2085  isolate_->thread_local_top());
2086 
2087  ActiveFunctionsRedirector active_functions_redirector;
2088  isolate_->thread_manager()->IterateArchivedThreads(
2089  &active_functions_redirector);
2090  }
2091 }
2092 
2093 
2094 Object* Debug::FindSharedFunctionInfoInScript(Handle<Script> script,
2095  int position) {
2096  // Iterate the heap looking for SharedFunctionInfo generated from the
2097  // script. The inner most SharedFunctionInfo containing the source position
2098  // for the requested break point is found.
2099  // NOTE: This might require several heap iterations. If the SharedFunctionInfo
2100  // which is found is not compiled it is compiled and the heap is iterated
2101  // again as the compilation might create inner functions from the newly
2102  // compiled function and the actual requested break point might be in one of
2103  // these functions.
2104  // NOTE: The below fix-point iteration depends on all functions that cannot be
2105  // compiled lazily without a context to not be compiled at all. Compilation
2106  // will be triggered at points where we do not need a context.
2107  bool done = false;
2108  // The current candidate for the source position:
2109  int target_start_position = RelocInfo::kNoPosition;
2110  Handle<JSFunction> target_function;
2111  Handle<SharedFunctionInfo> target;
2112  while (!done) {
2113  { // Extra scope for iterator and no-allocation.
2114  isolate_->heap()->EnsureHeapIsIterable();
2115  AssertNoAllocation no_alloc_during_heap_iteration;
2116  HeapIterator iterator;
2117  for (HeapObject* obj = iterator.next();
2118  obj != NULL; obj = iterator.next()) {
2119  bool found_next_candidate = false;
2120  Handle<JSFunction> function;
2121  Handle<SharedFunctionInfo> shared;
2122  if (obj->IsJSFunction()) {
2123  function = Handle<JSFunction>(JSFunction::cast(obj));
2124  shared = Handle<SharedFunctionInfo>(function->shared());
2125  ASSERT(shared->allows_lazy_compilation() || shared->is_compiled());
2126  found_next_candidate = true;
2127  } else if (obj->IsSharedFunctionInfo()) {
2128  shared = Handle<SharedFunctionInfo>(SharedFunctionInfo::cast(obj));
2129  // Skip functions that we cannot compile lazily without a context,
2130  // which is not available here, because there is no closure.
2131  found_next_candidate = shared->is_compiled() ||
2132  shared->allows_lazy_compilation_without_context();
2133  }
2134  if (!found_next_candidate) continue;
2135  if (shared->script() == *script) {
2136  // If the SharedFunctionInfo found has the requested script data and
2137  // contains the source position it is a candidate.
2138  int start_position = shared->function_token_position();
2139  if (start_position == RelocInfo::kNoPosition) {
2140  start_position = shared->start_position();
2141  }
2142  if (start_position <= position &&
2143  position <= shared->end_position()) {
2144  // If there is no candidate or this function is within the current
2145  // candidate this is the new candidate.
2146  if (target.is_null()) {
2147  target_start_position = start_position;
2148  target_function = function;
2149  target = shared;
2150  } else {
2151  if (target_start_position == start_position &&
2152  shared->end_position() == target->end_position()) {
2153  // If a top-level function contains only one function
2154  // declaration the source for the top-level and the function
2155  // is the same. In that case prefer the non top-level function.
2156  if (!shared->is_toplevel()) {
2157  target_start_position = start_position;
2158  target_function = function;
2159  target = shared;
2160  }
2161  } else if (target_start_position <= start_position &&
2162  shared->end_position() <= target->end_position()) {
2163  // This containment check includes equality as a function
2164  // inside a top-level function can share either start or end
2165  // position with the top-level function.
2166  target_start_position = start_position;
2167  target_function = function;
2168  target = shared;
2169  }
2170  }
2171  }
2172  }
2173  } // End for loop.
2174  } // End no-allocation scope.
2175 
2176  if (target.is_null()) {
2177  return isolate_->heap()->undefined_value();
2178  }
2179 
2180  // There will be at least one break point when we are done.
2181  has_break_points_ = true;
2182 
2183  // If the candidate found is compiled we are done.
2184  done = target->is_compiled();
2185  if (!done) {
2186  // If the candidate is not compiled, compile it to reveal any inner
2187  // functions which might contain the requested source position. This
2188  // will compile all inner functions that cannot be compiled without a
2189  // context, because Compiler::BuildFunctionInfo checks whether the
2190  // debugger is active.
2191  if (target_function.is_null()) {
2193  } else {
2194  JSFunction::CompileLazy(target_function, KEEP_EXCEPTION);
2195  }
2196  }
2197  } // End while loop.
2198 
2199  return *target;
2200 }
2201 
2202 
2203 // Ensures the debug information is present for shared.
2204 bool Debug::EnsureDebugInfo(Handle<SharedFunctionInfo> shared,
2205  Handle<JSFunction> function) {
2206  // Return if we already have the debug info for shared.
2207  if (HasDebugInfo(shared)) {
2208  ASSERT(shared->is_compiled());
2209  return true;
2210  }
2211 
2212  // There will be at least one break point when we are done.
2213  has_break_points_ = true;
2214 
2215  // Ensure function is compiled. Return false if this failed.
2216  if (!function.is_null() &&
2218  return false;
2219  }
2220 
2221  // Create the debug info object.
2222  Handle<DebugInfo> debug_info = FACTORY->NewDebugInfo(shared);
2223 
2224  // Add debug info to the list.
2225  DebugInfoListNode* node = new DebugInfoListNode(*debug_info);
2226  node->set_next(debug_info_list_);
2227  debug_info_list_ = node;
2228 
2229  return true;
2230 }
2231 
2232 
2233 void Debug::RemoveDebugInfo(Handle<DebugInfo> debug_info) {
2234  ASSERT(debug_info_list_ != NULL);
2235  // Run through the debug info objects to find this one and remove it.
2236  DebugInfoListNode* prev = NULL;
2237  DebugInfoListNode* current = debug_info_list_;
2238  while (current != NULL) {
2239  if (*current->debug_info() == *debug_info) {
2240  // Unlink from list. If prev is NULL we are looking at the first element.
2241  if (prev == NULL) {
2242  debug_info_list_ = current->next();
2243  } else {
2244  prev->set_next(current->next());
2245  }
2246  current->debug_info()->shared()->set_debug_info(
2247  isolate_->heap()->undefined_value());
2248  delete current;
2249 
2250  // If there are no more debug info objects there are not more break
2251  // points.
2252  has_break_points_ = debug_info_list_ != NULL;
2253 
2254  return;
2255  }
2256  // Move to next in list.
2257  prev = current;
2258  current = current->next();
2259  }
2260  UNREACHABLE();
2261 }
2262 
2263 
2264 void Debug::SetAfterBreakTarget(JavaScriptFrame* frame) {
2265  HandleScope scope(isolate_);
2266 
2267  PrepareForBreakPoints();
2268 
2269  // Get the executing function in which the debug break occurred.
2270  Handle<JSFunction> function(JSFunction::cast(frame->function()));
2271  Handle<SharedFunctionInfo> shared(function->shared());
2272  if (!EnsureDebugInfo(shared, function)) {
2273  // Return if we failed to retrieve the debug info.
2274  return;
2275  }
2276  Handle<DebugInfo> debug_info = GetDebugInfo(shared);
2277  Handle<Code> code(debug_info->code());
2278  Handle<Code> original_code(debug_info->original_code());
2279 #ifdef DEBUG
2280  // Get the code which is actually executing.
2281  Handle<Code> frame_code(frame->LookupCode());
2282  ASSERT(frame_code.is_identical_to(code));
2283 #endif
2284 
2285  // Find the call address in the running code. This address holds the call to
2286  // either a DebugBreakXXX or to the debug break return entry code if the
2287  // break point is still active after processing the break point.
2289 
2290  // Check if the location is at JS exit or debug break slot.
2291  bool at_js_return = false;
2292  bool break_at_js_return_active = false;
2293  bool at_debug_break_slot = false;
2294  RelocIterator it(debug_info->code());
2295  while (!it.done() && !at_js_return && !at_debug_break_slot) {
2296  if (RelocInfo::IsJSReturn(it.rinfo()->rmode())) {
2297  at_js_return = (it.rinfo()->pc() ==
2299  break_at_js_return_active = it.rinfo()->IsPatchedReturnSequence();
2300  }
2301  if (RelocInfo::IsDebugBreakSlot(it.rinfo()->rmode())) {
2302  at_debug_break_slot = (it.rinfo()->pc() ==
2304  }
2305  it.next();
2306  }
2307 
2308  // Handle the jump to continue execution after break point depending on the
2309  // break location.
2310  if (at_js_return) {
2311  // If the break point as return is still active jump to the corresponding
2312  // place in the original code. If not the break point was removed during
2313  // break point processing.
2314  if (break_at_js_return_active) {
2315  addr += original_code->instruction_start() - code->instruction_start();
2316  }
2317 
2318  // Move back to where the call instruction sequence started.
2319  thread_local_.after_break_target_ =
2321  } else if (at_debug_break_slot) {
2322  // Address of where the debug break slot starts.
2324 
2325  // Continue just after the slot.
2326  thread_local_.after_break_target_ = addr + Assembler::kDebugBreakSlotLength;
2327  } else if (IsDebugBreak(Assembler::target_address_at(addr))) {
2328  // We now know that there is still a debug break call at the target address,
2329  // so the break point is still there and the original code will hold the
2330  // address to jump to in order to complete the call which is replaced by a
2331  // call to DebugBreakXXX.
2332 
2333  // Find the corresponding address in the original code.
2334  addr += original_code->instruction_start() - code->instruction_start();
2335 
2336  // Install jump to the call address in the original code. This will be the
2337  // call which was overwritten by the call to DebugBreakXXX.
2338  thread_local_.after_break_target_ = Assembler::target_address_at(addr);
2339  } else {
2340  // There is no longer a break point present. Don't try to look in the
2341  // original code as the running code will have the right address. This takes
2342  // care of the case where the last break point is removed from the function
2343  // and therefore no "original code" is available.
2344  thread_local_.after_break_target_ = Assembler::target_address_at(addr);
2345  }
2346 }
2347 
2348 
2349 bool Debug::IsBreakAtReturn(JavaScriptFrame* frame) {
2350  HandleScope scope(isolate_);
2351 
2352  // If there are no break points this cannot be break at return, as
2353  // the debugger statement and stack guard bebug break cannot be at
2354  // return.
2355  if (!has_break_points_) {
2356  return false;
2357  }
2358 
2359  PrepareForBreakPoints();
2360 
2361  // Get the executing function in which the debug break occurred.
2362  Handle<JSFunction> function(JSFunction::cast(frame->function()));
2363  Handle<SharedFunctionInfo> shared(function->shared());
2364  if (!EnsureDebugInfo(shared, function)) {
2365  // Return if we failed to retrieve the debug info.
2366  return false;
2367  }
2368  Handle<DebugInfo> debug_info = GetDebugInfo(shared);
2369  Handle<Code> code(debug_info->code());
2370 #ifdef DEBUG
2371  // Get the code which is actually executing.
2372  Handle<Code> frame_code(frame->LookupCode());
2373  ASSERT(frame_code.is_identical_to(code));
2374 #endif
2375 
2376  // Find the call address in the running code.
2378 
2379  // Check if the location is at JS return.
2380  RelocIterator it(debug_info->code());
2381  while (!it.done()) {
2382  if (RelocInfo::IsJSReturn(it.rinfo()->rmode())) {
2383  return (it.rinfo()->pc() ==
2385  }
2386  it.next();
2387  }
2388  return false;
2389 }
2390 
2391 
2392 void Debug::FramesHaveBeenDropped(StackFrame::Id new_break_frame_id,
2393  FrameDropMode mode,
2394  Object** restarter_frame_function_pointer) {
2395  if (mode != CURRENTLY_SET_MODE) {
2396  thread_local_.frame_drop_mode_ = mode;
2397  }
2398  thread_local_.break_frame_id_ = new_break_frame_id;
2399  thread_local_.restarter_frame_function_pointer_ =
2400  restarter_frame_function_pointer;
2401 }
2402 
2403 
2404 const int Debug::FramePaddingLayout::kInitialSize = 1;
2405 
2406 
2407 // Any even value bigger than kInitialSize as needed for stack scanning.
2408 const int Debug::FramePaddingLayout::kPaddingValue = kInitialSize + 1;
2409 
2410 
2411 bool Debug::IsDebugGlobal(GlobalObject* global) {
2412  return IsLoaded() && global == debug_context()->global_object();
2413 }
2414 
2415 
2416 void Debug::ClearMirrorCache() {
2417  PostponeInterruptsScope postpone(isolate_);
2418  HandleScope scope(isolate_);
2419  ASSERT(isolate_->context() == *Debug::debug_context());
2420 
2421  // Clear the mirror cache.
2422  Handle<String> function_name =
2423  isolate_->factory()->LookupSymbol(CStrVector("ClearMirrorCache"));
2424  Handle<Object> fun(
2425  Isolate::Current()->global_object()->GetPropertyNoExceptionThrown(
2426  *function_name));
2427  ASSERT(fun->IsJSFunction());
2428  bool caught_exception;
2429  Execution::TryCall(Handle<JSFunction>::cast(fun),
2430  Handle<JSObject>(Debug::debug_context()->global_object()),
2431  0, NULL, &caught_exception);
2432 }
2433 
2434 
2435 void Debug::CreateScriptCache() {
2436  Heap* heap = isolate_->heap();
2437  HandleScope scope(isolate_);
2438 
2439  // Perform two GCs to get rid of all unreferenced scripts. The first GC gets
2440  // rid of all the cached script wrappers and the second gets rid of the
2441  // scripts which are no longer referenced. The second also sweeps precisely,
2442  // which saves us doing yet another GC to make the heap iterable.
2443  heap->CollectAllGarbage(Heap::kNoGCFlags, "Debug::CreateScriptCache");
2444  heap->CollectAllGarbage(Heap::kMakeHeapIterableMask,
2445  "Debug::CreateScriptCache");
2446 
2447  ASSERT(script_cache_ == NULL);
2448  script_cache_ = new ScriptCache();
2449 
2450  // Scan heap for Script objects.
2451  int count = 0;
2452  HeapIterator iterator;
2453  AssertNoAllocation no_allocation;
2454 
2455  for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
2456  if (obj->IsScript() && Script::cast(obj)->HasValidSource()) {
2457  script_cache_->Add(Handle<Script>(Script::cast(obj)));
2458  count++;
2459  }
2460  }
2461 }
2462 
2463 
2464 void Debug::DestroyScriptCache() {
2465  // Get rid of the script cache if it was created.
2466  if (script_cache_ != NULL) {
2467  delete script_cache_;
2468  script_cache_ = NULL;
2469  }
2470 }
2471 
2472 
2473 void Debug::AddScriptToScriptCache(Handle<Script> script) {
2474  if (script_cache_ != NULL) {
2475  script_cache_->Add(script);
2476  }
2477 }
2478 
2479 
2480 Handle<FixedArray> Debug::GetLoadedScripts() {
2481  // Create and fill the script cache when the loaded scripts is requested for
2482  // the first time.
2483  if (script_cache_ == NULL) {
2484  CreateScriptCache();
2485  }
2486 
2487  // If the script cache is not active just return an empty array.
2488  ASSERT(script_cache_ != NULL);
2489  if (script_cache_ == NULL) {
2490  isolate_->factory()->NewFixedArray(0);
2491  }
2492 
2493  // Perform GC to get unreferenced scripts evicted from the cache before
2494  // returning the content.
2495  isolate_->heap()->CollectAllGarbage(Heap::kNoGCFlags,
2496  "Debug::GetLoadedScripts");
2497 
2498  // Get the scripts from the cache.
2499  return script_cache_->GetScripts();
2500 }
2501 
2502 
2503 void Debug::AfterGarbageCollection() {
2504  // Generate events for collected scripts.
2505  if (script_cache_ != NULL) {
2506  script_cache_->ProcessCollectedScripts();
2507  }
2508 }
2509 
2510 
2511 Debugger::Debugger(Isolate* isolate)
2512  : debugger_access_(isolate->debugger_access()),
2513  event_listener_(Handle<Object>()),
2514  event_listener_data_(Handle<Object>()),
2515  compiling_natives_(false),
2516  is_loading_debugger_(false),
2517  live_edit_enabled_(true),
2518  never_unload_debugger_(false),
2519  force_debugger_active_(false),
2520  message_handler_(NULL),
2521  debugger_unload_pending_(false),
2522  host_dispatch_handler_(NULL),
2523  dispatch_handler_access_(OS::CreateMutex()),
2524  debug_message_dispatch_handler_(NULL),
2525  message_dispatch_helper_thread_(NULL),
2526  host_dispatch_micros_(100 * 1000),
2527  agent_(NULL),
2528  command_queue_(isolate->logger(), kQueueInitialSize),
2529  command_received_(OS::CreateSemaphore(0)),
2530  event_command_queue_(isolate->logger(), kQueueInitialSize),
2531  isolate_(isolate) {
2532 }
2533 
2534 
2535 Debugger::~Debugger() {
2536  delete dispatch_handler_access_;
2537  dispatch_handler_access_ = 0;
2538  delete command_received_;
2539  command_received_ = 0;
2540 }
2541 
2542 
2543 Handle<Object> Debugger::MakeJSObject(Vector<const char> constructor_name,
2544  int argc,
2545  Handle<Object> argv[],
2546  bool* caught_exception) {
2547  ASSERT(isolate_->context() == *isolate_->debug()->debug_context());
2548 
2549  // Create the execution state object.
2550  Handle<String> constructor_str =
2551  isolate_->factory()->LookupSymbol(constructor_name);
2552  Handle<Object> constructor(
2553  isolate_->global_object()->GetPropertyNoExceptionThrown(
2554  *constructor_str));
2555  ASSERT(constructor->IsJSFunction());
2556  if (!constructor->IsJSFunction()) {
2557  *caught_exception = true;
2558  return isolate_->factory()->undefined_value();
2559  }
2560  Handle<Object> js_object = Execution::TryCall(
2561  Handle<JSFunction>::cast(constructor),
2562  Handle<JSObject>(isolate_->debug()->debug_context()->global_object()),
2563  argc,
2564  argv,
2565  caught_exception);
2566  return js_object;
2567 }
2568 
2569 
2570 Handle<Object> Debugger::MakeExecutionState(bool* caught_exception) {
2571  // Create the execution state object.
2572  Handle<Object> break_id = isolate_->factory()->NewNumberFromInt(
2573  isolate_->debug()->break_id());
2574  Handle<Object> argv[] = { break_id };
2575  return MakeJSObject(CStrVector("MakeExecutionState"),
2576  ARRAY_SIZE(argv),
2577  argv,
2578  caught_exception);
2579 }
2580 
2581 
2582 Handle<Object> Debugger::MakeBreakEvent(Handle<Object> exec_state,
2583  Handle<Object> break_points_hit,
2584  bool* caught_exception) {
2585  // Create the new break event object.
2586  Handle<Object> argv[] = { exec_state, break_points_hit };
2587  return MakeJSObject(CStrVector("MakeBreakEvent"),
2588  ARRAY_SIZE(argv),
2589  argv,
2590  caught_exception);
2591 }
2592 
2593 
2594 Handle<Object> Debugger::MakeExceptionEvent(Handle<Object> exec_state,
2595  Handle<Object> exception,
2596  bool uncaught,
2597  bool* caught_exception) {
2598  Factory* factory = isolate_->factory();
2599  // Create the new exception event object.
2600  Handle<Object> argv[] = { exec_state,
2601  exception,
2602  factory->ToBoolean(uncaught) };
2603  return MakeJSObject(CStrVector("MakeExceptionEvent"),
2604  ARRAY_SIZE(argv),
2605  argv,
2606  caught_exception);
2607 }
2608 
2609 
2610 Handle<Object> Debugger::MakeNewFunctionEvent(Handle<Object> function,
2611  bool* caught_exception) {
2612  // Create the new function event object.
2613  Handle<Object> argv[] = { function };
2614  return MakeJSObject(CStrVector("MakeNewFunctionEvent"),
2615  ARRAY_SIZE(argv),
2616  argv,
2617  caught_exception);
2618 }
2619 
2620 
2621 Handle<Object> Debugger::MakeCompileEvent(Handle<Script> script,
2622  bool before,
2623  bool* caught_exception) {
2624  Factory* factory = isolate_->factory();
2625  // Create the compile event object.
2626  Handle<Object> exec_state = MakeExecutionState(caught_exception);
2627  Handle<Object> script_wrapper = GetScriptWrapper(script);
2628  Handle<Object> argv[] = { exec_state,
2629  script_wrapper,
2630  factory->ToBoolean(before) };
2631  return MakeJSObject(CStrVector("MakeCompileEvent"),
2632  ARRAY_SIZE(argv),
2633  argv,
2634  caught_exception);
2635 }
2636 
2637 
2638 Handle<Object> Debugger::MakeScriptCollectedEvent(int id,
2639  bool* caught_exception) {
2640  // Create the script collected event object.
2641  Handle<Object> exec_state = MakeExecutionState(caught_exception);
2642  Handle<Object> id_object = Handle<Smi>(Smi::FromInt(id));
2643  Handle<Object> argv[] = { exec_state, id_object };
2644 
2645  return MakeJSObject(CStrVector("MakeScriptCollectedEvent"),
2646  ARRAY_SIZE(argv),
2647  argv,
2648  caught_exception);
2649 }
2650 
2651 
2652 void Debugger::OnException(Handle<Object> exception, bool uncaught) {
2653  HandleScope scope(isolate_);
2654  Debug* debug = isolate_->debug();
2655 
2656  // Bail out based on state or if there is no listener for this event
2657  if (debug->InDebugger()) return;
2658  if (!Debugger::EventActive(v8::Exception)) return;
2659 
2660  // Bail out if exception breaks are not active
2661  if (uncaught) {
2662  // Uncaught exceptions are reported by either flags.
2663  if (!(debug->break_on_uncaught_exception() ||
2664  debug->break_on_exception())) return;
2665  } else {
2666  // Caught exceptions are reported is activated.
2667  if (!debug->break_on_exception()) return;
2668  }
2669 
2670  // Enter the debugger.
2671  EnterDebugger debugger;
2672  if (debugger.FailedToEnter()) return;
2673 
2674  // Clear all current stepping setup.
2675  debug->ClearStepping();
2676  // Create the event data object.
2677  bool caught_exception = false;
2678  Handle<Object> exec_state = MakeExecutionState(&caught_exception);
2679  Handle<Object> event_data;
2680  if (!caught_exception) {
2681  event_data = MakeExceptionEvent(exec_state, exception, uncaught,
2682  &caught_exception);
2683  }
2684  // Bail out and don't call debugger if exception.
2685  if (caught_exception) {
2686  return;
2687  }
2688 
2689  // Process debug event.
2690  ProcessDebugEvent(v8::Exception, Handle<JSObject>::cast(event_data), false);
2691  // Return to continue execution from where the exception was thrown.
2692 }
2693 
2694 
2695 void Debugger::OnDebugBreak(Handle<Object> break_points_hit,
2696  bool auto_continue) {
2697  HandleScope scope(isolate_);
2698 
2699  // Debugger has already been entered by caller.
2700  ASSERT(isolate_->context() == *isolate_->debug()->debug_context());
2701 
2702  // Bail out if there is no listener for this event
2703  if (!Debugger::EventActive(v8::Break)) return;
2704 
2705  // Debugger must be entered in advance.
2706  ASSERT(isolate_->context() == *isolate_->debug()->debug_context());
2707 
2708  // Create the event data object.
2709  bool caught_exception = false;
2710  Handle<Object> exec_state = MakeExecutionState(&caught_exception);
2711  Handle<Object> event_data;
2712  if (!caught_exception) {
2713  event_data = MakeBreakEvent(exec_state, break_points_hit,
2714  &caught_exception);
2715  }
2716  // Bail out and don't call debugger if exception.
2717  if (caught_exception) {
2718  return;
2719  }
2720 
2721  // Process debug event.
2722  ProcessDebugEvent(v8::Break,
2723  Handle<JSObject>::cast(event_data),
2724  auto_continue);
2725 }
2726 
2727 
2728 void Debugger::OnBeforeCompile(Handle<Script> script) {
2729  HandleScope scope(isolate_);
2730 
2731  // Bail out based on state or if there is no listener for this event
2732  if (isolate_->debug()->InDebugger()) return;
2733  if (compiling_natives()) return;
2734  if (!EventActive(v8::BeforeCompile)) return;
2735 
2736  // Enter the debugger.
2737  EnterDebugger debugger;
2738  if (debugger.FailedToEnter()) return;
2739 
2740  // Create the event data object.
2741  bool caught_exception = false;
2742  Handle<Object> event_data = MakeCompileEvent(script, true, &caught_exception);
2743  // Bail out and don't call debugger if exception.
2744  if (caught_exception) {
2745  return;
2746  }
2747 
2748  // Process debug event.
2749  ProcessDebugEvent(v8::BeforeCompile,
2750  Handle<JSObject>::cast(event_data),
2751  true);
2752 }
2753 
2754 
2755 // Handle debugger actions when a new script is compiled.
2756 void Debugger::OnAfterCompile(Handle<Script> script,
2757  AfterCompileFlags after_compile_flags) {
2758  HandleScope scope(isolate_);
2759  Debug* debug = isolate_->debug();
2760 
2761  // Add the newly compiled script to the script cache.
2762  debug->AddScriptToScriptCache(script);
2763 
2764  // No more to do if not debugging.
2765  if (!IsDebuggerActive()) return;
2766 
2767  // No compile events while compiling natives.
2768  if (compiling_natives()) return;
2769 
2770  // Store whether in debugger before entering debugger.
2771  bool in_debugger = debug->InDebugger();
2772 
2773  // Enter the debugger.
2774  EnterDebugger debugger;
2775  if (debugger.FailedToEnter()) return;
2776 
2777  // If debugging there might be script break points registered for this
2778  // script. Make sure that these break points are set.
2779 
2780  // Get the function UpdateScriptBreakPoints (defined in debug-debugger.js).
2781  Handle<String> update_script_break_points_symbol =
2782  isolate_->factory()->LookupAsciiSymbol("UpdateScriptBreakPoints");
2783  Handle<Object> update_script_break_points =
2784  Handle<Object>(debug->debug_context()->global_object()->
2785  GetPropertyNoExceptionThrown(*update_script_break_points_symbol));
2786  if (!update_script_break_points->IsJSFunction()) {
2787  return;
2788  }
2789  ASSERT(update_script_break_points->IsJSFunction());
2790 
2791  // Wrap the script object in a proper JS object before passing it
2792  // to JavaScript.
2793  Handle<JSValue> wrapper = GetScriptWrapper(script);
2794 
2795  // Call UpdateScriptBreakPoints expect no exceptions.
2796  bool caught_exception;
2797  Handle<Object> argv[] = { wrapper };
2798  Execution::TryCall(Handle<JSFunction>::cast(update_script_break_points),
2799  Isolate::Current()->js_builtins_object(),
2800  ARRAY_SIZE(argv),
2801  argv,
2802  &caught_exception);
2803  if (caught_exception) {
2804  return;
2805  }
2806  // Bail out based on state or if there is no listener for this event
2807  if (in_debugger && (after_compile_flags & SEND_WHEN_DEBUGGING) == 0) return;
2808  if (!Debugger::EventActive(v8::AfterCompile)) return;
2809 
2810  // Create the compile state object.
2811  Handle<Object> event_data = MakeCompileEvent(script,
2812  false,
2813  &caught_exception);
2814  // Bail out and don't call debugger if exception.
2815  if (caught_exception) {
2816  return;
2817  }
2818  // Process debug event.
2819  ProcessDebugEvent(v8::AfterCompile,
2820  Handle<JSObject>::cast(event_data),
2821  true);
2822 }
2823 
2824 
2825 void Debugger::OnScriptCollected(int id) {
2826  HandleScope scope(isolate_);
2827 
2828  // No more to do if not debugging.
2829  if (isolate_->debug()->InDebugger()) return;
2830  if (!IsDebuggerActive()) return;
2831  if (!Debugger::EventActive(v8::ScriptCollected)) return;
2832 
2833  // Enter the debugger.
2834  EnterDebugger debugger;
2835  if (debugger.FailedToEnter()) return;
2836 
2837  // Create the script collected state object.
2838  bool caught_exception = false;
2839  Handle<Object> event_data = MakeScriptCollectedEvent(id,
2840  &caught_exception);
2841  // Bail out and don't call debugger if exception.
2842  if (caught_exception) {
2843  return;
2844  }
2845 
2846  // Process debug event.
2847  ProcessDebugEvent(v8::ScriptCollected,
2848  Handle<JSObject>::cast(event_data),
2849  true);
2850 }
2851 
2852 
2853 void Debugger::ProcessDebugEvent(v8::DebugEvent event,
2854  Handle<JSObject> event_data,
2855  bool auto_continue) {
2856  HandleScope scope(isolate_);
2857 
2858  // Clear any pending debug break if this is a real break.
2859  if (!auto_continue) {
2860  isolate_->debug()->clear_interrupt_pending(DEBUGBREAK);
2861  }
2862 
2863  // Create the execution state.
2864  bool caught_exception = false;
2865  Handle<Object> exec_state = MakeExecutionState(&caught_exception);
2866  if (caught_exception) {
2867  return;
2868  }
2869  // First notify the message handler if any.
2870  if (message_handler_ != NULL) {
2871  NotifyMessageHandler(event,
2872  Handle<JSObject>::cast(exec_state),
2873  event_data,
2874  auto_continue);
2875  }
2876  // Notify registered debug event listener. This can be either a C or
2877  // a JavaScript function. Don't call event listener for v8::Break
2878  // here, if it's only a debug command -- they will be processed later.
2879  if ((event != v8::Break || !auto_continue) && !event_listener_.is_null()) {
2880  CallEventCallback(event, exec_state, event_data, NULL);
2881  }
2882  // Process pending debug commands.
2883  if (event == v8::Break) {
2884  while (!event_command_queue_.IsEmpty()) {
2885  CommandMessage command = event_command_queue_.Get();
2886  if (!event_listener_.is_null()) {
2887  CallEventCallback(v8::BreakForCommand,
2888  exec_state,
2889  event_data,
2890  command.client_data());
2891  }
2892  command.Dispose();
2893  }
2894  }
2895 }
2896 
2897 
2898 void Debugger::CallEventCallback(v8::DebugEvent event,
2899  Handle<Object> exec_state,
2900  Handle<Object> event_data,
2901  v8::Debug::ClientData* client_data) {
2902  if (event_listener_->IsForeign()) {
2903  CallCEventCallback(event, exec_state, event_data, client_data);
2904  } else {
2905  CallJSEventCallback(event, exec_state, event_data);
2906  }
2907 }
2908 
2909 
2910 void Debugger::CallCEventCallback(v8::DebugEvent event,
2911  Handle<Object> exec_state,
2912  Handle<Object> event_data,
2913  v8::Debug::ClientData* client_data) {
2914  Handle<Foreign> callback_obj(Handle<Foreign>::cast(event_listener_));
2915  v8::Debug::EventCallback2 callback =
2916  FUNCTION_CAST<v8::Debug::EventCallback2>(
2917  callback_obj->foreign_address());
2918  EventDetailsImpl event_details(
2919  event,
2920  Handle<JSObject>::cast(exec_state),
2921  Handle<JSObject>::cast(event_data),
2922  event_listener_data_,
2923  client_data);
2924  callback(event_details);
2925 }
2926 
2927 
2928 void Debugger::CallJSEventCallback(v8::DebugEvent event,
2929  Handle<Object> exec_state,
2930  Handle<Object> event_data) {
2931  ASSERT(event_listener_->IsJSFunction());
2932  Handle<JSFunction> fun(Handle<JSFunction>::cast(event_listener_));
2933 
2934  // Invoke the JavaScript debug event listener.
2935  Handle<Object> argv[] = { Handle<Object>(Smi::FromInt(event)),
2936  exec_state,
2937  event_data,
2938  event_listener_data_ };
2939  bool caught_exception;
2940  Execution::TryCall(fun,
2941  isolate_->global_object(),
2942  ARRAY_SIZE(argv),
2943  argv,
2944  &caught_exception);
2945  // Silently ignore exceptions from debug event listeners.
2946 }
2947 
2948 
2949 Handle<Context> Debugger::GetDebugContext() {
2950  never_unload_debugger_ = true;
2951  EnterDebugger debugger;
2952  return isolate_->debug()->debug_context();
2953 }
2954 
2955 
2956 void Debugger::UnloadDebugger() {
2957  Debug* debug = isolate_->debug();
2958 
2959  // Make sure that there are no breakpoints left.
2960  debug->ClearAllBreakPoints();
2961 
2962  // Unload the debugger if feasible.
2963  if (!never_unload_debugger_) {
2964  debug->Unload();
2965  }
2966 
2967  // Clear the flag indicating that the debugger should be unloaded.
2968  debugger_unload_pending_ = false;
2969 }
2970 
2971 
2972 void Debugger::NotifyMessageHandler(v8::DebugEvent event,
2973  Handle<JSObject> exec_state,
2974  Handle<JSObject> event_data,
2975  bool auto_continue) {
2976  HandleScope scope(isolate_);
2977 
2978  if (!isolate_->debug()->Load()) return;
2979 
2980  // Process the individual events.
2981  bool sendEventMessage = false;
2982  switch (event) {
2983  case v8::Break:
2984  case v8::BreakForCommand:
2985  sendEventMessage = !auto_continue;
2986  break;
2987  case v8::Exception:
2988  sendEventMessage = true;
2989  break;
2990  case v8::BeforeCompile:
2991  break;
2992  case v8::AfterCompile:
2993  sendEventMessage = true;
2994  break;
2995  case v8::ScriptCollected:
2996  sendEventMessage = true;
2997  break;
2998  case v8::NewFunction:
2999  break;
3000  default:
3001  UNREACHABLE();
3002  }
3003 
3004  // The debug command interrupt flag might have been set when the command was
3005  // added. It should be enough to clear the flag only once while we are in the
3006  // debugger.
3007  ASSERT(isolate_->debug()->InDebugger());
3008  isolate_->stack_guard()->Continue(DEBUGCOMMAND);
3009 
3010  // Notify the debugger that a debug event has occurred unless auto continue is
3011  // active in which case no event is send.
3012  if (sendEventMessage) {
3013  MessageImpl message = MessageImpl::NewEvent(
3014  event,
3015  auto_continue,
3016  Handle<JSObject>::cast(exec_state),
3017  Handle<JSObject>::cast(event_data));
3018  InvokeMessageHandler(message);
3019  }
3020 
3021  // If auto continue don't make the event cause a break, but process messages
3022  // in the queue if any. For script collected events don't even process
3023  // messages in the queue as the execution state might not be what is expected
3024  // by the client.
3025  if ((auto_continue && !HasCommands()) || event == v8::ScriptCollected) {
3026  return;
3027  }
3028 
3029  v8::TryCatch try_catch;
3030 
3031  // DebugCommandProcessor goes here.
3032  v8::Local<v8::Object> cmd_processor;
3033  {
3034  v8::Local<v8::Object> api_exec_state =
3035  v8::Utils::ToLocal(Handle<JSObject>::cast(exec_state));
3036  v8::Local<v8::String> fun_name =
3037  v8::String::New("debugCommandProcessor");
3039  v8::Function::Cast(*api_exec_state->Get(fun_name));
3040 
3041  v8::Handle<v8::Boolean> running =
3042  auto_continue ? v8::True() : v8::False();
3043  static const int kArgc = 1;
3044  v8::Handle<Value> argv[kArgc] = { running };
3045  cmd_processor = v8::Object::Cast(*fun->Call(api_exec_state, kArgc, argv));
3046  if (try_catch.HasCaught()) {
3047  PrintLn(try_catch.Exception());
3048  return;
3049  }
3050  }
3051 
3052  bool running = auto_continue;
3053 
3054  // Process requests from the debugger.
3055  while (true) {
3056  // Wait for new command in the queue.
3057  if (Debugger::host_dispatch_handler_) {
3058  // In case there is a host dispatch - do periodic dispatches.
3059  if (!command_received_->Wait(host_dispatch_micros_)) {
3060  // Timout expired, do the dispatch.
3061  Debugger::host_dispatch_handler_();
3062  continue;
3063  }
3064  } else {
3065  // In case there is no host dispatch - just wait.
3066  command_received_->Wait();
3067  }
3068 
3069  // Get the command from the queue.
3070  CommandMessage command = command_queue_.Get();
3071  isolate_->logger()->DebugTag(
3072  "Got request from command queue, in interactive loop.");
3073  if (!Debugger::IsDebuggerActive()) {
3074  // Delete command text and user data.
3075  command.Dispose();
3076  return;
3077  }
3078 
3079  // Invoke JavaScript to process the debug request.
3080  v8::Local<v8::String> fun_name;
3082  v8::Local<v8::Value> request;
3083  v8::TryCatch try_catch;
3084  fun_name = v8::String::New("processDebugRequest");
3085  fun = v8::Function::Cast(*cmd_processor->Get(fun_name));
3086 
3087  request = v8::String::New(command.text().start(),
3088  command.text().length());
3089  static const int kArgc = 1;
3090  v8::Handle<Value> argv[kArgc] = { request };
3091  v8::Local<v8::Value> response_val = fun->Call(cmd_processor, kArgc, argv);
3092 
3093  // Get the response.
3094  v8::Local<v8::String> response;
3095  if (!try_catch.HasCaught()) {
3096  // Get response string.
3097  if (!response_val->IsUndefined()) {
3098  response = v8::String::Cast(*response_val);
3099  } else {
3100  response = v8::String::New("");
3101  }
3102 
3103  // Log the JSON request/response.
3104  if (FLAG_trace_debug_json) {
3105  PrintLn(request);
3106  PrintLn(response);
3107  }
3108 
3109  // Get the running state.
3110  fun_name = v8::String::New("isRunning");
3111  fun = v8::Function::Cast(*cmd_processor->Get(fun_name));
3112  static const int kArgc = 1;
3113  v8::Handle<Value> argv[kArgc] = { response };
3114  v8::Local<v8::Value> running_val = fun->Call(cmd_processor, kArgc, argv);
3115  if (!try_catch.HasCaught()) {
3116  running = running_val->ToBoolean()->Value();
3117  }
3118  } else {
3119  // In case of failure the result text is the exception text.
3120  response = try_catch.Exception()->ToString();
3121  }
3122 
3123  // Return the result.
3124  MessageImpl message = MessageImpl::NewResponse(
3125  event,
3126  running,
3127  Handle<JSObject>::cast(exec_state),
3128  Handle<JSObject>::cast(event_data),
3129  Handle<String>(Utils::OpenHandle(*response)),
3130  command.client_data());
3131  InvokeMessageHandler(message);
3132  command.Dispose();
3133 
3134  // Return from debug event processing if either the VM is put into the
3135  // running state (through a continue command) or auto continue is active
3136  // and there are no more commands queued.
3137  if (running && !HasCommands()) {
3138  return;
3139  }
3140  }
3141 }
3142 
3143 
3144 void Debugger::SetEventListener(Handle<Object> callback,
3145  Handle<Object> data) {
3146  HandleScope scope(isolate_);
3147  GlobalHandles* global_handles = isolate_->global_handles();
3148 
3149  // Clear the global handles for the event listener and the event listener data
3150  // object.
3151  if (!event_listener_.is_null()) {
3152  global_handles->Destroy(
3153  reinterpret_cast<Object**>(event_listener_.location()));
3154  event_listener_ = Handle<Object>();
3155  }
3156  if (!event_listener_data_.is_null()) {
3157  global_handles->Destroy(
3158  reinterpret_cast<Object**>(event_listener_data_.location()));
3159  event_listener_data_ = Handle<Object>();
3160  }
3161 
3162  // If there is a new debug event listener register it together with its data
3163  // object.
3164  if (!callback->IsUndefined() && !callback->IsNull()) {
3165  event_listener_ = Handle<Object>::cast(
3166  global_handles->Create(*callback));
3167  if (data.is_null()) {
3168  data = isolate_->factory()->undefined_value();
3169  }
3170  event_listener_data_ = Handle<Object>::cast(
3171  global_handles->Create(*data));
3172  }
3173 
3174  ListenersChanged();
3175 }
3176 
3177 
3178 void Debugger::SetMessageHandler(v8::Debug::MessageHandler2 handler) {
3179  ScopedLock with(debugger_access_);
3180 
3181  message_handler_ = handler;
3182  ListenersChanged();
3183  if (handler == NULL) {
3184  // Send an empty command to the debugger if in a break to make JavaScript
3185  // run again if the debugger is closed.
3186  if (isolate_->debug()->InDebugger()) {
3187  ProcessCommand(Vector<const uint16_t>::empty());
3188  }
3189  }
3190 }
3191 
3192 
3193 void Debugger::ListenersChanged() {
3194  if (IsDebuggerActive()) {
3195  // Disable the compilation cache when the debugger is active.
3196  isolate_->compilation_cache()->Disable();
3197  debugger_unload_pending_ = false;
3198  } else {
3199  isolate_->compilation_cache()->Enable();
3200  // Unload the debugger if event listener and message handler cleared.
3201  // Schedule this for later, because we may be in non-V8 thread.
3202  debugger_unload_pending_ = true;
3203  }
3204 }
3205 
3206 
3207 void Debugger::SetHostDispatchHandler(v8::Debug::HostDispatchHandler handler,
3208  int period) {
3209  host_dispatch_handler_ = handler;
3210  host_dispatch_micros_ = period * 1000;
3211 }
3212 
3213 
3214 void Debugger::SetDebugMessageDispatchHandler(
3215  v8::Debug::DebugMessageDispatchHandler handler, bool provide_locker) {
3216  ScopedLock with(dispatch_handler_access_);
3217  debug_message_dispatch_handler_ = handler;
3218 
3219  if (provide_locker && message_dispatch_helper_thread_ == NULL) {
3220  message_dispatch_helper_thread_ = new MessageDispatchHelperThread(isolate_);
3221  message_dispatch_helper_thread_->Start();
3222  }
3223 }
3224 
3225 
3226 // Calls the registered debug message handler. This callback is part of the
3227 // public API.
3228 void Debugger::InvokeMessageHandler(MessageImpl message) {
3229  ScopedLock with(debugger_access_);
3230 
3231  if (message_handler_ != NULL) {
3232  message_handler_(message);
3233  }
3234 }
3235 
3236 
3237 // Puts a command coming from the public API on the queue. Creates
3238 // a copy of the command string managed by the debugger. Up to this
3239 // point, the command data was managed by the API client. Called
3240 // by the API client thread.
3241 void Debugger::ProcessCommand(Vector<const uint16_t> command,
3242  v8::Debug::ClientData* client_data) {
3243  // Need to cast away const.
3244  CommandMessage message = CommandMessage::New(
3245  Vector<uint16_t>(const_cast<uint16_t*>(command.start()),
3246  command.length()),
3247  client_data);
3248  isolate_->logger()->DebugTag("Put command on command_queue.");
3249  command_queue_.Put(message);
3250  command_received_->Signal();
3251 
3252  // Set the debug command break flag to have the command processed.
3253  if (!isolate_->debug()->InDebugger()) {
3254  isolate_->stack_guard()->DebugCommand();
3255  }
3256 
3257  MessageDispatchHelperThread* dispatch_thread;
3258  {
3259  ScopedLock with(dispatch_handler_access_);
3260  dispatch_thread = message_dispatch_helper_thread_;
3261  }
3262 
3263  if (dispatch_thread == NULL) {
3264  CallMessageDispatchHandler();
3265  } else {
3266  dispatch_thread->Schedule();
3267  }
3268 }
3269 
3270 
3271 bool Debugger::HasCommands() {
3272  return !command_queue_.IsEmpty();
3273 }
3274 
3275 
3276 void Debugger::EnqueueDebugCommand(v8::Debug::ClientData* client_data) {
3277  CommandMessage message = CommandMessage::New(Vector<uint16_t>(), client_data);
3278  event_command_queue_.Put(message);
3279 
3280  // Set the debug command break flag to have the command processed.
3281  if (!isolate_->debug()->InDebugger()) {
3282  isolate_->stack_guard()->DebugCommand();
3283  }
3284 }
3285 
3286 
3287 bool Debugger::IsDebuggerActive() {
3288  ScopedLock with(debugger_access_);
3289 
3290  return message_handler_ != NULL ||
3291  !event_listener_.is_null() ||
3292  force_debugger_active_;
3293 }
3294 
3295 
3296 Handle<Object> Debugger::Call(Handle<JSFunction> fun,
3297  Handle<Object> data,
3298  bool* pending_exception) {
3299  // When calling functions in the debugger prevent it from beeing unloaded.
3300  Debugger::never_unload_debugger_ = true;
3301 
3302  // Enter the debugger.
3303  EnterDebugger debugger;
3304  if (debugger.FailedToEnter()) {
3305  return isolate_->factory()->undefined_value();
3306  }
3307 
3308  // Create the execution state.
3309  bool caught_exception = false;
3310  Handle<Object> exec_state = MakeExecutionState(&caught_exception);
3311  if (caught_exception) {
3312  return isolate_->factory()->undefined_value();
3313  }
3314 
3315  Handle<Object> argv[] = { exec_state, data };
3316  Handle<Object> result = Execution::Call(
3317  fun,
3318  Handle<Object>(isolate_->debug()->debug_context_->global_proxy()),
3319  ARRAY_SIZE(argv),
3320  argv,
3321  pending_exception);
3322  return result;
3323 }
3324 
3325 
3326 static void StubMessageHandler2(const v8::Debug::Message& message) {
3327  // Simply ignore message.
3328 }
3329 
3330 
3331 bool Debugger::StartAgent(const char* name, int port,
3332  bool wait_for_connection) {
3333  ASSERT(Isolate::Current() == isolate_);
3334  if (wait_for_connection) {
3335  // Suspend V8 if it is already running or set V8 to suspend whenever
3336  // it starts.
3337  // Provide stub message handler; V8 auto-continues each suspend
3338  // when there is no message handler; we doesn't need it.
3339  // Once become suspended, V8 will stay so indefinitely long, until remote
3340  // debugger connects and issues "continue" command.
3341  Debugger::message_handler_ = StubMessageHandler2;
3343  }
3344 
3345  if (Socket::SetUp()) {
3346  if (agent_ == NULL) {
3347  agent_ = new DebuggerAgent(name, port);
3348  agent_->Start();
3349  }
3350  return true;
3351  }
3352 
3353  return false;
3354 }
3355 
3356 
3357 void Debugger::StopAgent() {
3358  ASSERT(Isolate::Current() == isolate_);
3359  if (agent_ != NULL) {
3360  agent_->Shutdown();
3361  agent_->Join();
3362  delete agent_;
3363  agent_ = NULL;
3364  }
3365 }
3366 
3367 
3368 void Debugger::WaitForAgent() {
3369  ASSERT(Isolate::Current() == isolate_);
3370  if (agent_ != NULL)
3371  agent_->WaitUntilListening();
3372 }
3373 
3374 
3375 void Debugger::CallMessageDispatchHandler() {
3377  {
3378  ScopedLock with(dispatch_handler_access_);
3379  handler = Debugger::debug_message_dispatch_handler_;
3380  }
3381  if (handler != NULL) {
3382  handler();
3383  }
3384 }
3385 
3386 
3387 EnterDebugger::EnterDebugger()
3388  : isolate_(Isolate::Current()),
3389  prev_(isolate_->debug()->debugger_entry()),
3390  it_(isolate_),
3391  has_js_frames_(!it_.done()),
3392  save_(isolate_) {
3393  Debug* debug = isolate_->debug();
3394  ASSERT(prev_ != NULL || !debug->is_interrupt_pending(PREEMPT));
3395  ASSERT(prev_ != NULL || !debug->is_interrupt_pending(DEBUGBREAK));
3396 
3397  // Link recursive debugger entry.
3398  debug->set_debugger_entry(this);
3399 
3400  // Store the previous break id and frame id.
3401  break_id_ = debug->break_id();
3402  break_frame_id_ = debug->break_frame_id();
3403 
3404  // Create the new break info. If there is no JavaScript frames there is no
3405  // break frame id.
3406  if (has_js_frames_) {
3407  debug->NewBreak(it_.frame()->id());
3408  } else {
3409  debug->NewBreak(StackFrame::NO_ID);
3410  }
3411 
3412  // Make sure that debugger is loaded and enter the debugger context.
3413  load_failed_ = !debug->Load();
3414  if (!load_failed_) {
3415  // NOTE the member variable save which saves the previous context before
3416  // this change.
3417  isolate_->set_context(*debug->debug_context());
3418  }
3419 }
3420 
3421 
3422 EnterDebugger::~EnterDebugger() {
3423  ASSERT(Isolate::Current() == isolate_);
3424  Debug* debug = isolate_->debug();
3425 
3426  // Restore to the previous break state.
3427  debug->SetBreak(break_frame_id_, break_id_);
3428 
3429  // Check for leaving the debugger.
3430  if (!load_failed_ && prev_ == NULL) {
3431  // Clear mirror cache when leaving the debugger. Skip this if there is a
3432  // pending exception as clearing the mirror cache calls back into
3433  // JavaScript. This can happen if the v8::Debug::Call is used in which
3434  // case the exception should end up in the calling code.
3435  if (!isolate_->has_pending_exception()) {
3436  // Try to avoid any pending debug break breaking in the clear mirror
3437  // cache JavaScript code.
3438  if (isolate_->stack_guard()->IsDebugBreak()) {
3439  debug->set_interrupts_pending(DEBUGBREAK);
3440  isolate_->stack_guard()->Continue(DEBUGBREAK);
3441  }
3442  debug->ClearMirrorCache();
3443  }
3444 
3445  // Request preemption and debug break when leaving the last debugger entry
3446  // if any of these where recorded while debugging.
3447  if (debug->is_interrupt_pending(PREEMPT)) {
3448  // This re-scheduling of preemption is to avoid starvation in some
3449  // debugging scenarios.
3450  debug->clear_interrupt_pending(PREEMPT);
3451  isolate_->stack_guard()->Preempt();
3452  }
3453  if (debug->is_interrupt_pending(DEBUGBREAK)) {
3454  debug->clear_interrupt_pending(DEBUGBREAK);
3455  isolate_->stack_guard()->DebugBreak();
3456  }
3457 
3458  // If there are commands in the queue when leaving the debugger request
3459  // that these commands are processed.
3460  if (isolate_->debugger()->HasCommands()) {
3461  isolate_->stack_guard()->DebugCommand();
3462  }
3463 
3464  // If leaving the debugger with the debugger no longer active unload it.
3465  if (!isolate_->debugger()->IsDebuggerActive()) {
3466  isolate_->debugger()->UnloadDebugger();
3467  }
3468  }
3469 
3470  // Leaving this debugger entry.
3471  debug->set_debugger_entry(prev_);
3472 }
3473 
3474 
3475 MessageImpl MessageImpl::NewEvent(DebugEvent event,
3476  bool running,
3477  Handle<JSObject> exec_state,
3478  Handle<JSObject> event_data) {
3479  MessageImpl message(true, event, running,
3480  exec_state, event_data, Handle<String>(), NULL);
3481  return message;
3482 }
3483 
3484 
3485 MessageImpl MessageImpl::NewResponse(DebugEvent event,
3486  bool running,
3487  Handle<JSObject> exec_state,
3488  Handle<JSObject> event_data,
3489  Handle<String> response_json,
3490  v8::Debug::ClientData* client_data) {
3491  MessageImpl message(false, event, running,
3492  exec_state, event_data, response_json, client_data);
3493  return message;
3494 }
3495 
3496 
3497 MessageImpl::MessageImpl(bool is_event,
3498  DebugEvent event,
3499  bool running,
3500  Handle<JSObject> exec_state,
3501  Handle<JSObject> event_data,
3502  Handle<String> response_json,
3503  v8::Debug::ClientData* client_data)
3504  : is_event_(is_event),
3505  event_(event),
3506  running_(running),
3507  exec_state_(exec_state),
3508  event_data_(event_data),
3509  response_json_(response_json),
3510  client_data_(client_data) {}
3511 
3512 
3513 bool MessageImpl::IsEvent() const {
3514  return is_event_;
3515 }
3516 
3517 
3518 bool MessageImpl::IsResponse() const {
3519  return !is_event_;
3520 }
3521 
3522 
3523 DebugEvent MessageImpl::GetEvent() const {
3524  return event_;
3525 }
3526 
3527 
3528 bool MessageImpl::WillStartRunning() const {
3529  return running_;
3530 }
3531 
3532 
3533 v8::Handle<v8::Object> MessageImpl::GetExecutionState() const {
3534  return v8::Utils::ToLocal(exec_state_);
3535 }
3536 
3537 
3538 v8::Handle<v8::Object> MessageImpl::GetEventData() const {
3539  return v8::Utils::ToLocal(event_data_);
3540 }
3541 
3542 
3543 v8::Handle<v8::String> MessageImpl::GetJSON() const {
3544  v8::HandleScope scope;
3545 
3546  if (IsEvent()) {
3547  // Call toJSONProtocol on the debug event object.
3548  Handle<Object> fun = GetProperty(event_data_, "toJSONProtocol");
3549  if (!fun->IsJSFunction()) {
3550  return v8::Handle<v8::String>();
3551  }
3552  bool caught_exception;
3553  Handle<Object> json = Execution::TryCall(Handle<JSFunction>::cast(fun),
3554  event_data_,
3555  0, NULL, &caught_exception);
3556  if (caught_exception || !json->IsString()) {
3557  return v8::Handle<v8::String>();
3558  }
3559  return scope.Close(v8::Utils::ToLocal(Handle<String>::cast(json)));
3560  } else {
3561  return v8::Utils::ToLocal(response_json_);
3562  }
3563 }
3564 
3565 
3566 v8::Handle<v8::Context> MessageImpl::GetEventContext() const {
3567  Isolate* isolate = Isolate::Current();
3568  v8::Handle<v8::Context> context = GetDebugEventContext(isolate);
3569  // Isolate::context() may be NULL when "script collected" event occures.
3570  ASSERT(!context.IsEmpty() || event_ == v8::ScriptCollected);
3571  return context;
3572 }
3573 
3574 
3575 v8::Debug::ClientData* MessageImpl::GetClientData() const {
3576  return client_data_;
3577 }
3578 
3579 
3580 EventDetailsImpl::EventDetailsImpl(DebugEvent event,
3581  Handle<JSObject> exec_state,
3582  Handle<JSObject> event_data,
3583  Handle<Object> callback_data,
3584  v8::Debug::ClientData* client_data)
3585  : event_(event),
3586  exec_state_(exec_state),
3587  event_data_(event_data),
3588  callback_data_(callback_data),
3589  client_data_(client_data) {}
3590 
3591 
3592 DebugEvent EventDetailsImpl::GetEvent() const {
3593  return event_;
3594 }
3595 
3596 
3597 v8::Handle<v8::Object> EventDetailsImpl::GetExecutionState() const {
3598  return v8::Utils::ToLocal(exec_state_);
3599 }
3600 
3601 
3602 v8::Handle<v8::Object> EventDetailsImpl::GetEventData() const {
3603  return v8::Utils::ToLocal(event_data_);
3604 }
3605 
3606 
3607 v8::Handle<v8::Context> EventDetailsImpl::GetEventContext() const {
3608  return GetDebugEventContext(Isolate::Current());
3609 }
3610 
3611 
3612 v8::Handle<v8::Value> EventDetailsImpl::GetCallbackData() const {
3613  return v8::Utils::ToLocal(callback_data_);
3614 }
3615 
3616 
3617 v8::Debug::ClientData* EventDetailsImpl::GetClientData() const {
3618  return client_data_;
3619 }
3620 
3621 
3622 CommandMessage::CommandMessage() : text_(Vector<uint16_t>::empty()),
3623  client_data_(NULL) {
3624 }
3625 
3626 
3627 CommandMessage::CommandMessage(const Vector<uint16_t>& text,
3628  v8::Debug::ClientData* data)
3629  : text_(text),
3630  client_data_(data) {
3631 }
3632 
3633 
3634 CommandMessage::~CommandMessage() {
3635 }
3636 
3637 
3638 void CommandMessage::Dispose() {
3639  text_.Dispose();
3640  delete client_data_;
3641  client_data_ = NULL;
3642 }
3643 
3644 
3645 CommandMessage CommandMessage::New(const Vector<uint16_t>& command,
3646  v8::Debug::ClientData* data) {
3647  return CommandMessage(command.Clone(), data);
3648 }
3649 
3650 
3651 CommandMessageQueue::CommandMessageQueue(int size) : start_(0), end_(0),
3652  size_(size) {
3653  messages_ = NewArray<CommandMessage>(size);
3654 }
3655 
3656 
3657 CommandMessageQueue::~CommandMessageQueue() {
3658  while (!IsEmpty()) {
3659  CommandMessage m = Get();
3660  m.Dispose();
3661  }
3662  DeleteArray(messages_);
3663 }
3664 
3665 
3666 CommandMessage CommandMessageQueue::Get() {
3667  ASSERT(!IsEmpty());
3668  int result = start_;
3669  start_ = (start_ + 1) % size_;
3670  return messages_[result];
3671 }
3672 
3673 
3674 void CommandMessageQueue::Put(const CommandMessage& message) {
3675  if ((end_ + 1) % size_ == start_) {
3676  Expand();
3677  }
3678  messages_[end_] = message;
3679  end_ = (end_ + 1) % size_;
3680 }
3681 
3682 
3683 void CommandMessageQueue::Expand() {
3684  CommandMessageQueue new_queue(size_ * 2);
3685  while (!IsEmpty()) {
3686  new_queue.Put(Get());
3687  }
3688  CommandMessage* array_to_free = messages_;
3689  *this = new_queue;
3690  new_queue.messages_ = array_to_free;
3691  // Make the new_queue empty so that it doesn't call Dispose on any messages.
3692  new_queue.start_ = new_queue.end_;
3693  // Automatic destructor called on new_queue, freeing array_to_free.
3694 }
3695 
3696 
3697 LockingCommandMessageQueue::LockingCommandMessageQueue(Logger* logger, int size)
3698  : logger_(logger), queue_(size) {
3699  lock_ = OS::CreateMutex();
3700 }
3701 
3702 
3703 LockingCommandMessageQueue::~LockingCommandMessageQueue() {
3704  delete lock_;
3705 }
3706 
3707 
3708 bool LockingCommandMessageQueue::IsEmpty() const {
3709  ScopedLock sl(lock_);
3710  return queue_.IsEmpty();
3711 }
3712 
3713 
3714 CommandMessage LockingCommandMessageQueue::Get() {
3715  ScopedLock sl(lock_);
3716  CommandMessage result = queue_.Get();
3717  logger_->DebugEvent("Get", result.text());
3718  return result;
3719 }
3720 
3721 
3722 void LockingCommandMessageQueue::Put(const CommandMessage& message) {
3723  ScopedLock sl(lock_);
3724  queue_.Put(message);
3725  logger_->DebugEvent("Put", message.text());
3726 }
3727 
3728 
3729 void LockingCommandMessageQueue::Clear() {
3730  ScopedLock sl(lock_);
3731  queue_.Clear();
3732 }
3733 
3734 
3735 MessageDispatchHelperThread::MessageDispatchHelperThread(Isolate* isolate)
3736  : Thread("v8:MsgDispHelpr"),
3737  sem_(OS::CreateSemaphore(0)), mutex_(OS::CreateMutex()),
3738  already_signalled_(false) {
3739 }
3740 
3741 
3742 MessageDispatchHelperThread::~MessageDispatchHelperThread() {
3743  delete mutex_;
3744  delete sem_;
3745 }
3746 
3747 
3748 void MessageDispatchHelperThread::Schedule() {
3749  {
3750  ScopedLock lock(mutex_);
3751  if (already_signalled_) {
3752  return;
3753  }
3754  already_signalled_ = true;
3755  }
3756  sem_->Signal();
3757 }
3758 
3759 
3760 void MessageDispatchHelperThread::Run() {
3761  while (true) {
3762  sem_->Wait();
3763  {
3764  ScopedLock lock(mutex_);
3765  already_signalled_ = false;
3766  }
3767  {
3768  Locker locker;
3769  Isolate::Current()->debugger()->CallMessageDispatchHandler();
3770  }
3771  }
3772 }
3773 
3774 #endif // ENABLE_DEBUGGER_SUPPORT
3775 
3776 } } // namespace v8::internal
byte * Address
Definition: globals.h:157
V8EXPORT int Length() const
Definition: api.cc:3741
static Handle< Object > SetProperty(Handle< JSReceiver > object, Handle< String > key, Handle< Object > value, PropertyAttributes attributes, StrictModeFlag strict_mode)
Definition: objects.cc:1893
static Object * Cast(Value *obj)
Definition: v8.h:4581
static bool CompileLazy(Handle< JSFunction > function, ClearExceptionFlag flag)
Definition: objects.cc:7643
static Object *& Object_at(Address addr)
Definition: v8memory.h:75
#define V8PRIxPTR
Definition: globals.h:189
static Handle< Object > TryCall(Handle< JSFunction > func, Handle< Object > receiver, int argc, Handle< Object > argv[], bool *caught_exception)
Definition: execution.cc:192
Handle< Boolean > V8EXPORT True()
Definition: api.cc:569
void Dispose()
Definition: v8.h:4235
void PrintF(const char *format,...)
Definition: v8utils.cc:40
Local< Value > Exception() const
Definition: api.cc:1720
static Handle< JSMessageObject > MakeMessageObject(const char *type, MessageLocation *loc, Vector< Handle< Object > > args, Handle< String > stack_trace, Handle< JSArray > stack_frames)
Definition: messages.cc:58
V8EXPORT Local< Value > Get(Handle< Value > key)
Definition: api.cc:2853
static Smi * FromInt(int value)
Definition: objects-inl.h:981
static int GetIndex(const char *name)
bool HasCaught() const
Definition: api.cc:1703
static int ExtractArgcFromMinorKey(int minor_key)
Definition: code-stubs.h:758
static Handle< T > cast(Handle< S > that)
Definition: handles.h:81
static const int kPatchDebugBreakSlotReturnOffset
static Vector< const char > GetScriptName(int index)
static V8EXPORT Local< String > New(const char *data, int length=-1)
Definition: api.cc:4779
DebugEvent
Definition: v8-debug.h:73
const int kMaxInt
Definition: globals.h:210
void(* DebugMessageDispatchHandler)()
Definition: v8-debug.h:245
V8EXPORT Local< Value > Call(Handle< Object > recv, int argc, Handle< Value > argv[])
Definition: api.cc:3652
#define ASSERT(condition)
Definition: checks.h:270
static const int kPatchReturnSequenceAddressOffset
void Clear()
Definition: v8.h:214
static Script * cast(Object *obj)
void(* MessageHandler2)(const Message &message)
Definition: v8-debug.h:235
unsigned short uint16_t
Definition: unicode.cc:46
static void DeoptimizeAll()
Definition: deoptimizer.cc:250
static SharedFunctionInfo * cast(Object *obj)
V8EXPORT Local< String > ToString() const
Definition: api.cc:2313
#define CHECK(condition)
Definition: checks.h:56
Handle< Object > GetProperty(Handle< JSReceiver > obj, const char *name)
Definition: handles.cc:282
static Function * Cast(Value *obj)
Definition: v8.h:4597
#define RETURN_IF_EMPTY_HANDLE_VALUE(isolate, call, value)
Definition: isolate.h:120
static Smi * cast(Object *object)
uint8_t byte
Definition: globals.h:156
HANDLE HANDLE LPSTACKFRAME64 StackFrame
#define UNREACHABLE()
Definition: checks.h:50
static const int kNoGCFlags
Definition: heap.h:1081
Handle< JSValue > GetScriptWrapper(Handle< Script > script)
Definition: handles.cc:366
Entry * Lookup(void *key, uint32_t hash, bool insert, FreeStoreAllocationPolicyallocator=FreeStoreAllocationPolicy())
const Register pc
static Mutex * CreateMutex()
static Code * GetCodeFromTargetAddress(Address address)
Definition: objects-inl.h:3559
static const int kMakeHeapIterableMask
Definition: heap.h:1088
static String * Cast(v8::Value *obj)
Definition: v8.h:4417
bool IsUndefined() const
Definition: v8.h:4472
Handle< Boolean > V8EXPORT False()
Definition: api.cc:579
activate correct semantics for inheriting readonliness false
Definition: flags.cc:141
static Handle< Object > Call(Handle< Object > callable, Handle< Object > receiver, int argc, Handle< Object > argv[], bool *pending_exception, bool convert_receiver=false)
Definition: execution.cc:150
Vector< const char > CStrVector(const char *data)
Definition: utils.h:526
static const int kDebugBreakSlotLength
static Local< Context > ToLocal(v8::internal::Handle< v8::internal::Context > obj)
void(* EventCallback2)(const EventDetails &event_details)
Definition: v8-debug.h:210
static Address target_address_at(Address pc)
void(* HostDispatchHandler)()
Definition: v8-debug.h:240
static Handle< SharedFunctionInfo > Compile(Handle< String > source, Handle< Object > script_name, int line_offset, int column_offset, Handle< Context > context, v8::Extension *extension, ScriptDataImpl *pre_data, Handle< Object > script_data, NativesFlag is_natives_code)
Definition: compiler.cc:542
JavaScriptFrameIteratorTemp< StackFrameIterator > JavaScriptFrameIterator
Definition: frames.h:775
static bool EnsureCompiled(Handle< JSFunction > function, ClearExceptionFlag flag)
Definition: objects.cc:7668
Object * JSCallerSavedBuffer[kNumJSCallerSaved]
Definition: frames-arm.h:55
v8::Handle< v8::Value > Load(const v8::Arguments &args)
Definition: shell.cc:159
static Handle< String > null()
Definition: handles.h:86
static bool CompileLazy(Handle< SharedFunctionInfo > shared, ClearExceptionFlag flag)
Definition: objects.cc:7570
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination use dead code elimination trace on stack replacement optimize closures cache optimized code for closures functions with arguments object loop weight for representation inference allow uint32 values on optimize frames if they are used only in safe operations track parallel recompilation enable all profiler experiments number of stack frames inspected by the profiler call recompile stub directly when self optimizing trigger profiler ticks based on counting instead of timing weight back edges by jump distance for interrupt triggering percentage of ICs that must have type info to allow optimization watch_ic_patching retry_self_opt interrupt_at_exit extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of SAHF instruction if enable use of VFP3 instructions if available this implies enabling ARMv7 and VFP2 enable use of VFP2 instructions if available enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of MIPS FPU instructions if expose natives in global object expose gc extension number of stack frames to capture disable builtin natives files print a stack trace if an assertion failure occurs use random jit cookie to mask large constants trace lazy optimization use adaptive optimizations prepare for turning on always opt minimum length for automatic enable preparsing maximum number of optimization attempts before giving up cache prototype transitions automatically set the debug break flag when debugger commands are in the queue always cause a debug break before aborting maximum length of function source code printed in a stack trace max size of the new max size of the old max size of executable always perform global GCs print one trace line following each garbage collection do not print trace line after scavenger collection print more details following each garbage collection print amount of external allocated memory after each time it is adjusted flush code that we expect not to use again before full gc do incremental marking steps track object counts and memory usage use caching Perform compaction on every full GC Never perform compaction on full GC testing only Compact code space on full incremental collections Default seed for initializing random allows verbose printing trace parsing and preparsing Check icache flushes in ARM and MIPS simulator Stack alingment in bytes in print stack trace when throwing exceptions randomize hashes to avoid predictable hash Fixed seed to use to hash property activate a timer that switches between V8 threads testing_bool_flag float flag Seed used for threading test randomness A filename with extra code to be included in the Print usage message
Definition: flags.cc:495
Local< T > Close(Handle< T > value)
Definition: v8.h:4324
static FixedArray * cast(Object *obj)
bool end_
V8EXPORT int WriteAscii(char *buffer, int start=0, int length=-1, int options=NO_OPTIONS) const
Definition: api.cc:3984
static bool CompileLazy(CompilationInfo *info)
Definition: compiler.cc:786
static const int kBoundFunctionIndex
Definition: objects.h:6198
bool IsEmpty() const
Definition: v8.h:209
#define FACTORY
Definition: isolate.h:1434
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination use dead code elimination trace on stack replacement optimize closures cache optimized code for closures functions with arguments object loop weight for representation inference allow uint32 values on optimize frames if they are used only in safe operations track parallel recompilation enable all profiler experiments number of stack frames inspected by the profiler call recompile stub directly when self optimizing trigger profiler ticks based on counting instead of timing weight back edges by jump distance for interrupt triggering percentage of ICs that must have type info to allow optimization watch_ic_patching retry_self_opt interrupt_at_exit extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of SAHF instruction if enable use of VFP3 instructions if available this implies enabling ARMv7 and VFP2 enable use of VFP2 instructions if available enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of MIPS FPU instructions if NULL
Definition: flags.cc:301
#define BUILTIN(name)
Definition: builtins.cc:142
static const int kMaxInliningLevels
Definition: compiler.h:419
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination use dead code elimination trace on stack replacement optimize closures cache optimized code for closures functions with arguments object loop weight for representation inference allow uint32 values on optimize frames if they are used only in safe operations track parallel recompilation enable all profiler experiments number of stack frames inspected by the profiler call recompile stub directly when self optimizing trigger profiler ticks based on counting instead of timing weight back edges by jump distance for interrupt triggering percentage of ICs that must have type info to allow optimization watch_ic_patching retry_self_opt interrupt_at_exit extra verbose compilation tracing generate extra code(assertions) for debugging") DEFINE_bool(code_comments
V8EXPORT Local< Boolean > ToBoolean() const
Definition: api.cc:2373
static void DebugBreak(Isolate *isolate=NULL)
const Register fp
static void ReportMessage(Isolate *isolate, MessageLocation *loc, Handle< Object > message)
Definition: messages.cc:103
void DeleteArray(T *array)
Definition: allocation.h:91
static const int kPatchDebugBreakSlotAddressOffset
static void FatalProcessOutOfMemory(const char *location, bool take_snapshot=false)
#define ARRAY_SIZE(a)
Definition: globals.h:281
Definition: v8.h:106
static JSFunction * cast(Object *obj)