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/v8.h" | 5 #include "src/v8.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 576 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
587 int Debug::ArchiveSpacePerThread() { | 587 int Debug::ArchiveSpacePerThread() { |
588 return sizeof(ThreadLocal); | 588 return sizeof(ThreadLocal); |
589 } | 589 } |
590 | 590 |
591 | 591 |
592 ScriptCache::ScriptCache(Isolate* isolate) : HashMap(HashMap::PointersMatch), | 592 ScriptCache::ScriptCache(Isolate* isolate) : HashMap(HashMap::PointersMatch), |
593 isolate_(isolate) { | 593 isolate_(isolate) { |
594 Heap* heap = isolate_->heap(); | 594 Heap* heap = isolate_->heap(); |
595 HandleScope scope(isolate_); | 595 HandleScope scope(isolate_); |
596 | 596 |
597 // Perform two GCs to get rid of all unreferenced scripts. The first GC gets | 597 // Perform a GC to get rid of all unreferenced scripts. |
598 // rid of all the cached script wrappers and the second gets rid of the | |
599 // scripts which are no longer referenced. | |
600 heap->CollectAllGarbage(Heap::kMakeHeapIterableMask, "ScriptCache"); | |
601 heap->CollectAllGarbage(Heap::kMakeHeapIterableMask, "ScriptCache"); | 598 heap->CollectAllGarbage(Heap::kMakeHeapIterableMask, "ScriptCache"); |
602 | 599 |
603 // Scan heap for Script objects. | 600 // Scan heap for Script objects. |
604 HeapIterator iterator(heap); | 601 HeapIterator iterator(heap); |
605 DisallowHeapAllocation no_allocation; | 602 DisallowHeapAllocation no_allocation; |
606 | 603 |
607 for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) { | 604 for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) { |
608 if (obj->IsScript() && Script::cast(obj)->HasValidSource()) { | 605 if (obj->IsScript() && Script::cast(obj)->HasValidSource()) { |
609 Add(Handle<Script>(Script::cast(obj))); | 606 Add(Handle<Script>(Script::cast(obj))); |
610 } | 607 } |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
687 // Clear the weak handle. | 684 // Clear the weak handle. |
688 GlobalHandles::Destroy(location); | 685 GlobalHandles::Destroy(location); |
689 } | 686 } |
690 | 687 |
691 | 688 |
692 void Debug::HandleWeakDebugInfo( | 689 void Debug::HandleWeakDebugInfo( |
693 const v8::WeakCallbackData<v8::Value, void>& data) { | 690 const v8::WeakCallbackData<v8::Value, void>& data) { |
694 Debug* debug = reinterpret_cast<Isolate*>(data.GetIsolate())->debug(); | 691 Debug* debug = reinterpret_cast<Isolate*>(data.GetIsolate())->debug(); |
695 DebugInfoListNode* node = | 692 DebugInfoListNode* node = |
696 reinterpret_cast<DebugInfoListNode*>(data.GetParameter()); | 693 reinterpret_cast<DebugInfoListNode*>(data.GetParameter()); |
697 // We need to clear all breakpoints associated with the function to restore | 694 debug->RemoveDebugInfo(node->debug_info().location()); |
698 // original code and avoid patching the code twice later because | |
699 // the function will live in the heap until next gc, and can be found by | |
700 // Debug::FindSharedFunctionInfoInScript. | |
701 BreakLocationIterator it(node->debug_info(), ALL_BREAK_LOCATIONS); | |
702 it.ClearAllDebugBreak(); | |
703 debug->RemoveDebugInfo(node->debug_info()); | |
704 #ifdef DEBUG | 695 #ifdef DEBUG |
705 for (DebugInfoListNode* n = debug->debug_info_list_; | 696 for (DebugInfoListNode* n = debug->debug_info_list_; |
706 n != NULL; | 697 n != NULL; |
707 n = n->next()) { | 698 n = n->next()) { |
708 DCHECK(n != node); | 699 DCHECK(n != node); |
709 } | 700 } |
710 #endif | 701 #endif |
711 } | 702 } |
712 | 703 |
713 | 704 |
714 DebugInfoListNode::DebugInfoListNode(DebugInfo* debug_info): next_(NULL) { | 705 DebugInfoListNode::DebugInfoListNode(DebugInfo* debug_info): next_(NULL) { |
715 // Globalize the request debug info object and make it weak. | 706 // Globalize the request debug info object and make it weak. |
716 GlobalHandles* global_handles = debug_info->GetIsolate()->global_handles(); | 707 GlobalHandles* global_handles = debug_info->GetIsolate()->global_handles(); |
717 debug_info_ = Handle<DebugInfo>::cast(global_handles->Create(debug_info)); | 708 debug_info_ = Handle<DebugInfo>::cast(global_handles->Create(debug_info)); |
718 GlobalHandles::MakeWeak(reinterpret_cast<Object**>(debug_info_.location()), | 709 GlobalHandles::MakeWeak(reinterpret_cast<Object**>(debug_info_.location()), |
719 this, | 710 this, Debug::HandleWeakDebugInfo, |
720 Debug::HandleWeakDebugInfo); | 711 GlobalHandles::Phantom); |
721 } | 712 } |
722 | 713 |
723 | 714 |
724 DebugInfoListNode::~DebugInfoListNode() { | 715 DebugInfoListNode::~DebugInfoListNode() { |
725 GlobalHandles::Destroy(reinterpret_cast<Object**>(debug_info_.location())); | 716 GlobalHandles::Destroy(reinterpret_cast<Object**>(debug_info_.location())); |
726 } | 717 } |
727 | 718 |
728 | 719 |
729 bool Debug::CompileDebuggerScript(Isolate* isolate, int index) { | 720 bool Debug::CompileDebuggerScript(Isolate* isolate, int index) { |
730 Factory* factory = isolate->factory(); | 721 Factory* factory = isolate->factory(); |
(...skipping 434 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1165 | 1156 |
1166 // Find the break point and clear it. | 1157 // Find the break point and clear it. |
1167 BreakLocationIterator it(debug_info, SOURCE_BREAK_LOCATIONS); | 1158 BreakLocationIterator it(debug_info, SOURCE_BREAK_LOCATIONS); |
1168 it.FindBreakLocationFromAddress(debug_info->code()->entry() + | 1159 it.FindBreakLocationFromAddress(debug_info->code()->entry() + |
1169 break_point_info->code_position()->value()); | 1160 break_point_info->code_position()->value()); |
1170 it.ClearBreakPoint(break_point_object); | 1161 it.ClearBreakPoint(break_point_object); |
1171 | 1162 |
1172 // If there are no more break points left remove the debug info for this | 1163 // If there are no more break points left remove the debug info for this |
1173 // function. | 1164 // function. |
1174 if (debug_info->GetBreakPointCount() == 0) { | 1165 if (debug_info->GetBreakPointCount() == 0) { |
1175 RemoveDebugInfo(debug_info); | 1166 RemoveDebugInfoAndClearFromShared(debug_info); |
1176 } | 1167 } |
1177 | 1168 |
1178 return; | 1169 return; |
1179 } | 1170 } |
1180 node = node->next(); | 1171 node = node->next(); |
1181 } | 1172 } |
1182 } | 1173 } |
1183 | 1174 |
1184 | 1175 |
1185 void Debug::ClearAllBreakPoints() { | 1176 void Debug::ClearAllBreakPoints() { |
1186 DebugInfoListNode* node = debug_info_list_; | 1177 DebugInfoListNode* node = debug_info_list_; |
1187 while (node != NULL) { | 1178 while (node != NULL) { |
1188 // Remove all debug break code. | 1179 // Remove all debug break code. |
1189 BreakLocationIterator it(node->debug_info(), ALL_BREAK_LOCATIONS); | 1180 BreakLocationIterator it(node->debug_info(), ALL_BREAK_LOCATIONS); |
1190 it.ClearAllDebugBreak(); | 1181 it.ClearAllDebugBreak(); |
1191 node = node->next(); | 1182 node = node->next(); |
1192 } | 1183 } |
1193 | 1184 |
1194 // Remove all debug info. | 1185 // Remove all debug info. |
1195 while (debug_info_list_ != NULL) { | 1186 while (debug_info_list_ != NULL) { |
1196 RemoveDebugInfo(debug_info_list_->debug_info()); | 1187 RemoveDebugInfoAndClearFromShared(debug_info_list_->debug_info()); |
1197 } | 1188 } |
1198 } | 1189 } |
1199 | 1190 |
1200 | 1191 |
1201 void Debug::FloodWithOneShot(Handle<JSFunction> function) { | 1192 void Debug::FloodWithOneShot(Handle<JSFunction> function) { |
1202 PrepareForBreakPoints(); | 1193 PrepareForBreakPoints(); |
1203 | 1194 |
1204 // Make sure the function is compiled and has set up the debug info. | 1195 // Make sure the function is compiled and has set up the debug info. |
1205 Handle<SharedFunctionInfo> shared(function->shared()); | 1196 Handle<SharedFunctionInfo> shared(function->shared()); |
1206 if (!EnsureDebugInfo(shared, function)) { | 1197 if (!EnsureDebugInfo(shared, function)) { |
(...skipping 997 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2204 | 2195 |
2205 // Add debug info to the list. | 2196 // Add debug info to the list. |
2206 DebugInfoListNode* node = new DebugInfoListNode(*debug_info); | 2197 DebugInfoListNode* node = new DebugInfoListNode(*debug_info); |
2207 node->set_next(debug_info_list_); | 2198 node->set_next(debug_info_list_); |
2208 debug_info_list_ = node; | 2199 debug_info_list_ = node; |
2209 | 2200 |
2210 return true; | 2201 return true; |
2211 } | 2202 } |
2212 | 2203 |
2213 | 2204 |
2214 void Debug::RemoveDebugInfo(Handle<DebugInfo> debug_info) { | 2205 // This uses the location of a handle to look up the debug info in the debug |
| 2206 // info list, but it doesn't use the actual debug info for anything. Therefore |
| 2207 // if the debug info has been collected by the GC, we can be sure that this |
| 2208 // method will not attempt to resurrect it. |
| 2209 void Debug::RemoveDebugInfo(DebugInfo** debug_info) { |
2215 DCHECK(debug_info_list_ != NULL); | 2210 DCHECK(debug_info_list_ != NULL); |
2216 // Run through the debug info objects to find this one and remove it. | 2211 // Run through the debug info objects to find this one and remove it. |
2217 DebugInfoListNode* prev = NULL; | 2212 DebugInfoListNode* prev = NULL; |
2218 DebugInfoListNode* current = debug_info_list_; | 2213 DebugInfoListNode* current = debug_info_list_; |
2219 while (current != NULL) { | 2214 while (current != NULL) { |
2220 if (*current->debug_info() == *debug_info) { | 2215 if (current->debug_info().location() == debug_info) { |
2221 // Unlink from list. If prev is NULL we are looking at the first element. | 2216 // Unlink from list. If prev is NULL we are looking at the first element. |
2222 if (prev == NULL) { | 2217 if (prev == NULL) { |
2223 debug_info_list_ = current->next(); | 2218 debug_info_list_ = current->next(); |
2224 } else { | 2219 } else { |
2225 prev->set_next(current->next()); | 2220 prev->set_next(current->next()); |
2226 } | 2221 } |
2227 current->debug_info()->shared()->set_debug_info( | |
2228 isolate_->heap()->undefined_value()); | |
2229 delete current; | 2222 delete current; |
2230 | 2223 |
2231 // If there are no more debug info objects there are not more break | 2224 // If there are no more debug info objects there are not more break |
2232 // points. | 2225 // points. |
2233 has_break_points_ = debug_info_list_ != NULL; | 2226 has_break_points_ = debug_info_list_ != NULL; |
2234 | 2227 |
2235 return; | 2228 return; |
2236 } | 2229 } |
2237 // Move to next in list. | 2230 // Move to next in list. |
2238 prev = current; | 2231 prev = current; |
2239 current = current->next(); | 2232 current = current->next(); |
2240 } | 2233 } |
2241 UNREACHABLE(); | 2234 UNREACHABLE(); |
2242 } | 2235 } |
2243 | 2236 |
2244 | 2237 |
| 2238 void Debug::RemoveDebugInfoAndClearFromShared(Handle<DebugInfo> debug_info) { |
| 2239 HandleScope scope(isolate_); |
| 2240 Handle<SharedFunctionInfo> shared(debug_info->shared()); |
| 2241 |
| 2242 RemoveDebugInfo(debug_info.location()); |
| 2243 |
| 2244 shared->set_debug_info(isolate_->heap()->undefined_value()); |
| 2245 } |
| 2246 |
| 2247 |
2245 void Debug::SetAfterBreakTarget(JavaScriptFrame* frame) { | 2248 void Debug::SetAfterBreakTarget(JavaScriptFrame* frame) { |
2246 after_break_target_ = NULL; | 2249 after_break_target_ = NULL; |
2247 | 2250 |
2248 if (LiveEdit::SetAfterBreakTarget(this)) return; // LiveEdit did the job. | 2251 if (LiveEdit::SetAfterBreakTarget(this)) return; // LiveEdit did the job. |
2249 | 2252 |
2250 HandleScope scope(isolate_); | 2253 HandleScope scope(isolate_); |
2251 PrepareForBreakPoints(); | 2254 PrepareForBreakPoints(); |
2252 | 2255 |
2253 // Get the executing function in which the debug break occurred. | 2256 // Get the executing function in which the debug break occurred. |
2254 Handle<JSFunction> function(JSFunction::cast(frame->function())); | 2257 Handle<JSFunction> function(JSFunction::cast(frame->function())); |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2329 after_break_target_ = Assembler::target_address_at(addr, *code); | 2332 after_break_target_ = Assembler::target_address_at(addr, *code); |
2330 } | 2333 } |
2331 } | 2334 } |
2332 } | 2335 } |
2333 | 2336 |
2334 | 2337 |
2335 bool Debug::IsBreakAtReturn(JavaScriptFrame* frame) { | 2338 bool Debug::IsBreakAtReturn(JavaScriptFrame* frame) { |
2336 HandleScope scope(isolate_); | 2339 HandleScope scope(isolate_); |
2337 | 2340 |
2338 // If there are no break points this cannot be break at return, as | 2341 // If there are no break points this cannot be break at return, as |
2339 // the debugger statement and stack guard bebug break cannot be at | 2342 // the debugger statement and stack guard debug break cannot be at |
2340 // return. | 2343 // return. |
2341 if (!has_break_points_) { | 2344 if (!has_break_points_) { |
2342 return false; | 2345 return false; |
2343 } | 2346 } |
2344 | 2347 |
2345 PrepareForBreakPoints(); | 2348 PrepareForBreakPoints(); |
2346 | 2349 |
2347 // Get the executing function in which the debug break occurred. | 2350 // Get the executing function in which the debug break occurred. |
2348 Handle<JSFunction> function(JSFunction::cast(frame->function())); | 2351 Handle<JSFunction> function(JSFunction::cast(frame->function())); |
2349 Handle<SharedFunctionInfo> shared(function->shared()); | 2352 Handle<SharedFunctionInfo> shared(function->shared()); |
(...skipping 900 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3250 return scope.Escape(v8::Utils::ToLocal(Handle<String>::cast(json))); | 3253 return scope.Escape(v8::Utils::ToLocal(Handle<String>::cast(json))); |
3251 } else { | 3254 } else { |
3252 return v8::Utils::ToLocal(response_json_); | 3255 return v8::Utils::ToLocal(response_json_); |
3253 } | 3256 } |
3254 } | 3257 } |
3255 | 3258 |
3256 | 3259 |
3257 v8::Handle<v8::Context> MessageImpl::GetEventContext() const { | 3260 v8::Handle<v8::Context> MessageImpl::GetEventContext() const { |
3258 Isolate* isolate = event_data_->GetIsolate(); | 3261 Isolate* isolate = event_data_->GetIsolate(); |
3259 v8::Handle<v8::Context> context = GetDebugEventContext(isolate); | 3262 v8::Handle<v8::Context> context = GetDebugEventContext(isolate); |
3260 // Isolate::context() may be NULL when "script collected" event occures. | 3263 // Isolate::context() may be NULL when "script collected" event occurs. |
3261 DCHECK(!context.IsEmpty()); | 3264 DCHECK(!context.IsEmpty()); |
3262 return context; | 3265 return context; |
3263 } | 3266 } |
3264 | 3267 |
3265 | 3268 |
3266 v8::Debug::ClientData* MessageImpl::GetClientData() const { | 3269 v8::Debug::ClientData* MessageImpl::GetClientData() const { |
3267 return client_data_; | 3270 return client_data_; |
3268 } | 3271 } |
3269 | 3272 |
3270 | 3273 |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3402 logger_->DebugEvent("Put", message.text()); | 3405 logger_->DebugEvent("Put", message.text()); |
3403 } | 3406 } |
3404 | 3407 |
3405 | 3408 |
3406 void LockingCommandMessageQueue::Clear() { | 3409 void LockingCommandMessageQueue::Clear() { |
3407 base::LockGuard<base::Mutex> lock_guard(&mutex_); | 3410 base::LockGuard<base::Mutex> lock_guard(&mutex_); |
3408 queue_.Clear(); | 3411 queue_.Clear(); |
3409 } | 3412 } |
3410 | 3413 |
3411 } } // namespace v8::internal | 3414 } } // namespace v8::internal |
OLD | NEW |