OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/debug/debug.h" | 5 #include "src/debug/debug.h" |
6 | 6 |
7 #include "src/api.h" | 7 #include "src/api.h" |
8 #include "src/arguments.h" | 8 #include "src/arguments.h" |
9 #include "src/bootstrapper.h" | 9 #include "src/bootstrapper.h" |
10 #include "src/code-stubs.h" | 10 #include "src/code-stubs.h" |
(...skipping 22 matching lines...) Expand all Loading... |
33 message_handler_(NULL), | 33 message_handler_(NULL), |
34 command_received_(0), | 34 command_received_(0), |
35 command_queue_(isolate->logger(), kQueueInitialSize), | 35 command_queue_(isolate->logger(), kQueueInitialSize), |
36 is_active_(false), | 36 is_active_(false), |
37 is_suppressed_(false), | 37 is_suppressed_(false), |
38 live_edit_enabled_(true), // TODO(yangguo): set to false by default. | 38 live_edit_enabled_(true), // TODO(yangguo): set to false by default. |
39 break_disabled_(false), | 39 break_disabled_(false), |
40 in_debug_event_listener_(false), | 40 in_debug_event_listener_(false), |
41 break_on_exception_(false), | 41 break_on_exception_(false), |
42 break_on_uncaught_exception_(false), | 42 break_on_uncaught_exception_(false), |
43 script_cache_(NULL), | |
44 debug_info_list_(NULL), | 43 debug_info_list_(NULL), |
45 isolate_(isolate) { | 44 isolate_(isolate) { |
46 ThreadInit(); | 45 ThreadInit(); |
47 } | 46 } |
48 | 47 |
49 | 48 |
50 static v8::Local<v8::Context> GetDebugEventContext(Isolate* isolate) { | 49 static v8::Local<v8::Context> GetDebugEventContext(Isolate* isolate) { |
51 Handle<Context> context = isolate->debug()->debugger_entry()->GetContext(); | 50 Handle<Context> context = isolate->debug()->debugger_entry()->GetContext(); |
52 // Isolate::context() may have been NULL when "script collected" event | 51 // Isolate::context() may have been NULL when "script collected" event |
53 // occured. | 52 // occured. |
(...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
347 MemCopy(reinterpret_cast<char*>(&thread_local_), from, sizeof(ThreadLocal)); | 346 MemCopy(reinterpret_cast<char*>(&thread_local_), from, sizeof(ThreadLocal)); |
348 return storage + ArchiveSpacePerThread(); | 347 return storage + ArchiveSpacePerThread(); |
349 } | 348 } |
350 | 349 |
351 | 350 |
352 int Debug::ArchiveSpacePerThread() { | 351 int Debug::ArchiveSpacePerThread() { |
353 return sizeof(ThreadLocal); | 352 return sizeof(ThreadLocal); |
354 } | 353 } |
355 | 354 |
356 | 355 |
357 ScriptCache::ScriptCache(Isolate* isolate) : isolate_(isolate) { | |
358 Heap* heap = isolate_->heap(); | |
359 HandleScope scope(isolate_); | |
360 | |
361 DCHECK(isolate_->debug()->is_active()); | |
362 | |
363 // Perform a GC to get rid of all unreferenced scripts. | |
364 heap->CollectAllGarbage(Heap::kMakeHeapIterableMask, "ScriptCache"); | |
365 | |
366 // Scan heap for Script objects. | |
367 List<Handle<Script> > scripts; | |
368 { | |
369 HeapIterator iterator(heap, HeapIterator::kFilterUnreachable); | |
370 DisallowHeapAllocation no_allocation; | |
371 for (HeapObject* obj = iterator.next(); obj != NULL; | |
372 obj = iterator.next()) { | |
373 if (obj->IsScript() && Script::cast(obj)->HasValidSource()) { | |
374 scripts.Add(Handle<Script>(Script::cast(obj))); | |
375 } | |
376 } | |
377 } | |
378 | |
379 GlobalHandles* global_handles = isolate_->global_handles(); | |
380 table_ = Handle<WeakValueHashTable>::cast(global_handles->Create( | |
381 Object::cast(*WeakValueHashTable::New(isolate_, scripts.length())))); | |
382 for (int i = 0; i < scripts.length(); i++) Add(scripts[i]); | |
383 } | |
384 | |
385 | |
386 void ScriptCache::Add(Handle<Script> script) { | |
387 HandleScope scope(isolate_); | |
388 Handle<Smi> id(script->id(), isolate_); | |
389 | |
390 #ifdef DEBUG | |
391 Handle<Object> lookup(table_->LookupWeak(id), isolate_); | |
392 if (!lookup->IsTheHole()) { | |
393 Handle<Script> found = Handle<Script>::cast(lookup); | |
394 DCHECK(script->id() == found->id()); | |
395 DCHECK(!script->name()->IsString() || | |
396 String::cast(script->name())->Equals(String::cast(found->name()))); | |
397 } | |
398 #endif | |
399 | |
400 Handle<WeakValueHashTable> new_table = | |
401 WeakValueHashTable::PutWeak(table_, id, script); | |
402 | |
403 if (new_table.is_identical_to(table_)) return; | |
404 GlobalHandles* global_handles = isolate_->global_handles(); | |
405 global_handles->Destroy(Handle<Object>::cast(table_).location()); | |
406 table_ = Handle<WeakValueHashTable>::cast( | |
407 global_handles->Create(Object::cast(*new_table))); | |
408 } | |
409 | |
410 | |
411 ScriptCache::~ScriptCache() { | |
412 isolate_->global_handles()->Destroy(Handle<Object>::cast(table_).location()); | |
413 table_ = Handle<WeakValueHashTable>(); | |
414 } | |
415 | |
416 | |
417 DebugInfoListNode::DebugInfoListNode(DebugInfo* debug_info): next_(NULL) { | 356 DebugInfoListNode::DebugInfoListNode(DebugInfo* debug_info): next_(NULL) { |
418 // Globalize the request debug info object and make it weak. | 357 // Globalize the request debug info object and make it weak. |
419 GlobalHandles* global_handles = debug_info->GetIsolate()->global_handles(); | 358 GlobalHandles* global_handles = debug_info->GetIsolate()->global_handles(); |
420 debug_info_ = | 359 debug_info_ = |
421 Handle<DebugInfo>::cast(global_handles->Create(debug_info)).location(); | 360 Handle<DebugInfo>::cast(global_handles->Create(debug_info)).location(); |
422 } | 361 } |
423 | 362 |
424 | 363 |
425 DebugInfoListNode::~DebugInfoListNode() { | 364 DebugInfoListNode::~DebugInfoListNode() { |
426 if (debug_info_ == nullptr) return; | 365 if (debug_info_ == nullptr) return; |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
459 } | 398 } |
460 | 399 |
461 | 400 |
462 void Debug::Unload() { | 401 void Debug::Unload() { |
463 ClearAllBreakPoints(); | 402 ClearAllBreakPoints(); |
464 ClearStepping(); | 403 ClearStepping(); |
465 | 404 |
466 // Return debugger is not loaded. | 405 // Return debugger is not loaded. |
467 if (!is_loaded()) return; | 406 if (!is_loaded()) return; |
468 | 407 |
469 // Clear the script cache. | |
470 if (script_cache_ != NULL) { | |
471 delete script_cache_; | |
472 script_cache_ = NULL; | |
473 } | |
474 | |
475 // Clear debugger context global handle. | 408 // Clear debugger context global handle. |
476 GlobalHandles::Destroy(Handle<Object>::cast(debug_context_).location()); | 409 GlobalHandles::Destroy(Handle<Object>::cast(debug_context_).location()); |
477 debug_context_ = Handle<Context>(); | 410 debug_context_ = Handle<Context>(); |
478 } | 411 } |
479 | 412 |
480 | 413 |
481 void Debug::Break(Arguments args, JavaScriptFrame* frame) { | 414 void Debug::Break(Arguments args, JavaScriptFrame* frame) { |
482 Heap* heap = isolate_->heap(); | 415 Heap* heap = isolate_->heap(); |
483 HandleScope scope(isolate_); | 416 HandleScope scope(isolate_); |
484 DCHECK(args.length() == 0); | 417 DCHECK(args.length() == 0); |
(...skipping 1183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1668 | 1601 |
1669 | 1602 |
1670 void Debug::ClearMirrorCache() { | 1603 void Debug::ClearMirrorCache() { |
1671 PostponeInterruptsScope postpone(isolate_); | 1604 PostponeInterruptsScope postpone(isolate_); |
1672 HandleScope scope(isolate_); | 1605 HandleScope scope(isolate_); |
1673 CallFunction("ClearMirrorCache", 0, NULL); | 1606 CallFunction("ClearMirrorCache", 0, NULL); |
1674 } | 1607 } |
1675 | 1608 |
1676 | 1609 |
1677 Handle<FixedArray> Debug::GetLoadedScripts() { | 1610 Handle<FixedArray> Debug::GetLoadedScripts() { |
1678 // Create and fill the script cache when the loaded scripts is requested for | |
1679 // the first time. | |
1680 if (script_cache_ == NULL) script_cache_ = new ScriptCache(isolate_); | |
1681 | |
1682 // Perform GC to get unreferenced scripts evicted from the cache before | |
1683 // returning the content. | |
1684 isolate_->heap()->CollectAllGarbage(Heap::kNoGCFlags, | 1611 isolate_->heap()->CollectAllGarbage(Heap::kNoGCFlags, |
1685 "Debug::GetLoadedScripts"); | 1612 "Debug::GetLoadedScripts"); |
1686 | 1613 Factory* factory = isolate_->factory(); |
1687 // Get the scripts from the cache. | 1614 if (!factory->script_list()->IsWeakFixedArray()) { |
1688 return script_cache_->GetScripts(); | 1615 return factory->empty_fixed_array(); |
| 1616 } |
| 1617 Handle<WeakFixedArray> array = |
| 1618 Handle<WeakFixedArray>::cast(factory->script_list()); |
| 1619 Handle<FixedArray> results = factory->NewFixedArray(array->Length()); |
| 1620 int length = 0; |
| 1621 for (int i = 0; i < array->Length(); ++i) { |
| 1622 Object* item = array->Get(i); |
| 1623 if (item->IsScript() && Script::cast(item)->HasValidSource()) { |
| 1624 results->set(length++, item); |
| 1625 } |
| 1626 } |
| 1627 results->Shrink(length); |
| 1628 return results; |
1689 } | 1629 } |
1690 | 1630 |
1691 | 1631 |
1692 void Debug::GetStepinPositions(JavaScriptFrame* frame, StackFrame::Id frame_id, | 1632 void Debug::GetStepinPositions(JavaScriptFrame* frame, StackFrame::Id frame_id, |
1693 List<int>* results_out) { | 1633 List<int>* results_out) { |
1694 FrameSummary summary = GetFirstFrameSummary(frame); | 1634 FrameSummary summary = GetFirstFrameSummary(frame); |
1695 | 1635 |
1696 Handle<JSFunction> fun = Handle<JSFunction>(summary.function()); | 1636 Handle<JSFunction> fun = Handle<JSFunction>(summary.function()); |
1697 Handle<SharedFunctionInfo> shared = Handle<SharedFunctionInfo>(fun->shared()); | 1637 Handle<SharedFunctionInfo> shared = Handle<SharedFunctionInfo>(fun->shared()); |
1698 | 1638 |
(...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1930 | 1870 |
1931 // Process debug event. | 1871 // Process debug event. |
1932 ProcessDebugEvent(v8::BeforeCompile, | 1872 ProcessDebugEvent(v8::BeforeCompile, |
1933 Handle<JSObject>::cast(event_data), | 1873 Handle<JSObject>::cast(event_data), |
1934 true); | 1874 true); |
1935 } | 1875 } |
1936 | 1876 |
1937 | 1877 |
1938 // Handle debugger actions when a new script is compiled. | 1878 // Handle debugger actions when a new script is compiled. |
1939 void Debug::OnAfterCompile(Handle<Script> script) { | 1879 void Debug::OnAfterCompile(Handle<Script> script) { |
1940 // Add the newly compiled script to the script cache. | |
1941 if (script_cache_ != NULL) script_cache_->Add(script); | |
1942 | |
1943 if (ignore_events()) return; | 1880 if (ignore_events()) return; |
1944 | 1881 |
1945 if (in_debug_scope()) { | 1882 if (in_debug_scope()) { |
1946 ProcessCompileEventInDebugScope(v8::AfterCompile, script); | 1883 ProcessCompileEventInDebugScope(v8::AfterCompile, script); |
1947 return; | 1884 return; |
1948 } | 1885 } |
1949 | 1886 |
1950 HandleScope scope(isolate_); | 1887 HandleScope scope(isolate_); |
1951 DebugScope debug_scope(this); | 1888 DebugScope debug_scope(this); |
1952 if (debug_scope.failed()) return; | 1889 if (debug_scope.failed()) return; |
(...skipping 723 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2676 } | 2613 } |
2677 | 2614 |
2678 | 2615 |
2679 void LockingCommandMessageQueue::Clear() { | 2616 void LockingCommandMessageQueue::Clear() { |
2680 base::LockGuard<base::Mutex> lock_guard(&mutex_); | 2617 base::LockGuard<base::Mutex> lock_guard(&mutex_); |
2681 queue_.Clear(); | 2618 queue_.Clear(); |
2682 } | 2619 } |
2683 | 2620 |
2684 } // namespace internal | 2621 } // namespace internal |
2685 } // namespace v8 | 2622 } // namespace v8 |
OLD | NEW |