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 a GC to get rid of all unreferenced scripts. | 597 // Perform two GCs to get rid of all unreferenced scripts. The first GC gets |
| 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"); |
598 heap->CollectAllGarbage(Heap::kMakeHeapIterableMask, "ScriptCache"); | 601 heap->CollectAllGarbage(Heap::kMakeHeapIterableMask, "ScriptCache"); |
599 | 602 |
600 // Scan heap for Script objects. | 603 // Scan heap for Script objects. |
601 HeapIterator iterator(heap); | 604 HeapIterator iterator(heap); |
602 DisallowHeapAllocation no_allocation; | 605 DisallowHeapAllocation no_allocation; |
603 | 606 |
604 for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) { | 607 for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) { |
605 if (obj->IsScript() && Script::cast(obj)->HasValidSource()) { | 608 if (obj->IsScript() && Script::cast(obj)->HasValidSource()) { |
606 Add(Handle<Script>(Script::cast(obj))); | 609 Add(Handle<Script>(Script::cast(obj))); |
607 } | 610 } |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
684 // Clear the weak handle. | 687 // Clear the weak handle. |
685 GlobalHandles::Destroy(location); | 688 GlobalHandles::Destroy(location); |
686 } | 689 } |
687 | 690 |
688 | 691 |
689 void Debug::HandleWeakDebugInfo( | 692 void Debug::HandleWeakDebugInfo( |
690 const v8::WeakCallbackData<v8::Value, void>& data) { | 693 const v8::WeakCallbackData<v8::Value, void>& data) { |
691 Debug* debug = reinterpret_cast<Isolate*>(data.GetIsolate())->debug(); | 694 Debug* debug = reinterpret_cast<Isolate*>(data.GetIsolate())->debug(); |
692 DebugInfoListNode* node = | 695 DebugInfoListNode* node = |
693 reinterpret_cast<DebugInfoListNode*>(data.GetParameter()); | 696 reinterpret_cast<DebugInfoListNode*>(data.GetParameter()); |
694 debug->RemoveDebugInfo(node->debug_info().location()); | 697 // We need to clear all breakpoints associated with the function to restore |
| 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()); |
695 #ifdef DEBUG | 704 #ifdef DEBUG |
696 for (DebugInfoListNode* n = debug->debug_info_list_; | 705 for (DebugInfoListNode* n = debug->debug_info_list_; |
697 n != NULL; | 706 n != NULL; |
698 n = n->next()) { | 707 n = n->next()) { |
699 DCHECK(n != node); | 708 DCHECK(n != node); |
700 } | 709 } |
701 #endif | 710 #endif |
702 } | 711 } |
703 | 712 |
704 | 713 |
705 DebugInfoListNode::DebugInfoListNode(DebugInfo* debug_info): next_(NULL) { | 714 DebugInfoListNode::DebugInfoListNode(DebugInfo* debug_info): next_(NULL) { |
706 // Globalize the request debug info object and make it weak. | 715 // Globalize the request debug info object and make it weak. |
707 GlobalHandles* global_handles = debug_info->GetIsolate()->global_handles(); | 716 GlobalHandles* global_handles = debug_info->GetIsolate()->global_handles(); |
708 debug_info_ = Handle<DebugInfo>::cast(global_handles->Create(debug_info)); | 717 debug_info_ = Handle<DebugInfo>::cast(global_handles->Create(debug_info)); |
709 GlobalHandles::MakeWeak(reinterpret_cast<Object**>(debug_info_.location()), | 718 GlobalHandles::MakeWeak(reinterpret_cast<Object**>(debug_info_.location()), |
710 this, Debug::HandleWeakDebugInfo, | 719 this, |
711 GlobalHandles::Phantom); | 720 Debug::HandleWeakDebugInfo); |
712 } | 721 } |
713 | 722 |
714 | 723 |
715 DebugInfoListNode::~DebugInfoListNode() { | 724 DebugInfoListNode::~DebugInfoListNode() { |
716 GlobalHandles::Destroy(reinterpret_cast<Object**>(debug_info_.location())); | 725 GlobalHandles::Destroy(reinterpret_cast<Object**>(debug_info_.location())); |
717 } | 726 } |
718 | 727 |
719 | 728 |
720 bool Debug::CompileDebuggerScript(Isolate* isolate, int index) { | 729 bool Debug::CompileDebuggerScript(Isolate* isolate, int index) { |
721 Factory* factory = isolate->factory(); | 730 Factory* factory = isolate->factory(); |
(...skipping 434 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1156 | 1165 |
1157 // Find the break point and clear it. | 1166 // Find the break point and clear it. |
1158 BreakLocationIterator it(debug_info, SOURCE_BREAK_LOCATIONS); | 1167 BreakLocationIterator it(debug_info, SOURCE_BREAK_LOCATIONS); |
1159 it.FindBreakLocationFromAddress(debug_info->code()->entry() + | 1168 it.FindBreakLocationFromAddress(debug_info->code()->entry() + |
1160 break_point_info->code_position()->value()); | 1169 break_point_info->code_position()->value()); |
1161 it.ClearBreakPoint(break_point_object); | 1170 it.ClearBreakPoint(break_point_object); |
1162 | 1171 |
1163 // If there are no more break points left remove the debug info for this | 1172 // If there are no more break points left remove the debug info for this |
1164 // function. | 1173 // function. |
1165 if (debug_info->GetBreakPointCount() == 0) { | 1174 if (debug_info->GetBreakPointCount() == 0) { |
1166 RemoveDebugInfoAndClearFromShared(debug_info); | 1175 RemoveDebugInfo(debug_info); |
1167 } | 1176 } |
1168 | 1177 |
1169 return; | 1178 return; |
1170 } | 1179 } |
1171 node = node->next(); | 1180 node = node->next(); |
1172 } | 1181 } |
1173 } | 1182 } |
1174 | 1183 |
1175 | 1184 |
1176 void Debug::ClearAllBreakPoints() { | 1185 void Debug::ClearAllBreakPoints() { |
1177 DebugInfoListNode* node = debug_info_list_; | 1186 DebugInfoListNode* node = debug_info_list_; |
1178 while (node != NULL) { | 1187 while (node != NULL) { |
1179 // Remove all debug break code. | 1188 // Remove all debug break code. |
1180 BreakLocationIterator it(node->debug_info(), ALL_BREAK_LOCATIONS); | 1189 BreakLocationIterator it(node->debug_info(), ALL_BREAK_LOCATIONS); |
1181 it.ClearAllDebugBreak(); | 1190 it.ClearAllDebugBreak(); |
1182 node = node->next(); | 1191 node = node->next(); |
1183 } | 1192 } |
1184 | 1193 |
1185 // Remove all debug info. | 1194 // Remove all debug info. |
1186 while (debug_info_list_ != NULL) { | 1195 while (debug_info_list_ != NULL) { |
1187 RemoveDebugInfoAndClearFromShared(debug_info_list_->debug_info()); | 1196 RemoveDebugInfo(debug_info_list_->debug_info()); |
1188 } | 1197 } |
1189 } | 1198 } |
1190 | 1199 |
1191 | 1200 |
1192 void Debug::FloodWithOneShot(Handle<JSFunction> function) { | 1201 void Debug::FloodWithOneShot(Handle<JSFunction> function) { |
1193 PrepareForBreakPoints(); | 1202 PrepareForBreakPoints(); |
1194 | 1203 |
1195 // Make sure the function is compiled and has set up the debug info. | 1204 // Make sure the function is compiled and has set up the debug info. |
1196 Handle<SharedFunctionInfo> shared(function->shared()); | 1205 Handle<SharedFunctionInfo> shared(function->shared()); |
1197 if (!EnsureDebugInfo(shared, function)) { | 1206 if (!EnsureDebugInfo(shared, function)) { |
(...skipping 981 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2179 | 2188 |
2180 // Add debug info to the list. | 2189 // Add debug info to the list. |
2181 DebugInfoListNode* node = new DebugInfoListNode(*debug_info); | 2190 DebugInfoListNode* node = new DebugInfoListNode(*debug_info); |
2182 node->set_next(debug_info_list_); | 2191 node->set_next(debug_info_list_); |
2183 debug_info_list_ = node; | 2192 debug_info_list_ = node; |
2184 | 2193 |
2185 return true; | 2194 return true; |
2186 } | 2195 } |
2187 | 2196 |
2188 | 2197 |
2189 // This uses the location of a handle to look up the debug info in the debug | 2198 void Debug::RemoveDebugInfo(Handle<DebugInfo> debug_info) { |
2190 // info list, but it doesn't use the actual debug info for anything. Therefore | |
2191 // if the debug info has been collected by the GC, we can be sure that this | |
2192 // method will not attempt to resurrect it. | |
2193 void Debug::RemoveDebugInfo(DebugInfo** debug_info) { | |
2194 DCHECK(debug_info_list_ != NULL); | 2199 DCHECK(debug_info_list_ != NULL); |
2195 // Run through the debug info objects to find this one and remove it. | 2200 // Run through the debug info objects to find this one and remove it. |
2196 DebugInfoListNode* prev = NULL; | 2201 DebugInfoListNode* prev = NULL; |
2197 DebugInfoListNode* current = debug_info_list_; | 2202 DebugInfoListNode* current = debug_info_list_; |
2198 while (current != NULL) { | 2203 while (current != NULL) { |
2199 if (current->debug_info().location() == debug_info) { | 2204 if (*current->debug_info() == *debug_info) { |
2200 // Unlink from list. If prev is NULL we are looking at the first element. | 2205 // Unlink from list. If prev is NULL we are looking at the first element. |
2201 if (prev == NULL) { | 2206 if (prev == NULL) { |
2202 debug_info_list_ = current->next(); | 2207 debug_info_list_ = current->next(); |
2203 } else { | 2208 } else { |
2204 prev->set_next(current->next()); | 2209 prev->set_next(current->next()); |
2205 } | 2210 } |
| 2211 current->debug_info()->shared()->set_debug_info( |
| 2212 isolate_->heap()->undefined_value()); |
2206 delete current; | 2213 delete current; |
2207 | 2214 |
2208 // If there are no more debug info objects there are not more break | 2215 // If there are no more debug info objects there are not more break |
2209 // points. | 2216 // points. |
2210 has_break_points_ = debug_info_list_ != NULL; | 2217 has_break_points_ = debug_info_list_ != NULL; |
2211 | 2218 |
2212 return; | 2219 return; |
2213 } | 2220 } |
2214 // Move to next in list. | 2221 // Move to next in list. |
2215 prev = current; | 2222 prev = current; |
2216 current = current->next(); | 2223 current = current->next(); |
2217 } | 2224 } |
2218 UNREACHABLE(); | 2225 UNREACHABLE(); |
2219 } | 2226 } |
2220 | 2227 |
2221 | 2228 |
2222 void Debug::RemoveDebugInfoAndClearFromShared(Handle<DebugInfo> debug_info) { | |
2223 HandleScope scope(isolate_); | |
2224 Handle<SharedFunctionInfo> shared(debug_info->shared()); | |
2225 | |
2226 RemoveDebugInfo(debug_info.location()); | |
2227 | |
2228 shared->set_debug_info(isolate_->heap()->undefined_value()); | |
2229 } | |
2230 | |
2231 | |
2232 void Debug::SetAfterBreakTarget(JavaScriptFrame* frame) { | 2229 void Debug::SetAfterBreakTarget(JavaScriptFrame* frame) { |
2233 after_break_target_ = NULL; | 2230 after_break_target_ = NULL; |
2234 | 2231 |
2235 if (LiveEdit::SetAfterBreakTarget(this)) return; // LiveEdit did the job. | 2232 if (LiveEdit::SetAfterBreakTarget(this)) return; // LiveEdit did the job. |
2236 | 2233 |
2237 HandleScope scope(isolate_); | 2234 HandleScope scope(isolate_); |
2238 PrepareForBreakPoints(); | 2235 PrepareForBreakPoints(); |
2239 | 2236 |
2240 // Get the executing function in which the debug break occurred. | 2237 // Get the executing function in which the debug break occurred. |
2241 Handle<JSFunction> function(JSFunction::cast(frame->function())); | 2238 Handle<JSFunction> function(JSFunction::cast(frame->function())); |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2316 after_break_target_ = Assembler::target_address_at(addr, *code); | 2313 after_break_target_ = Assembler::target_address_at(addr, *code); |
2317 } | 2314 } |
2318 } | 2315 } |
2319 } | 2316 } |
2320 | 2317 |
2321 | 2318 |
2322 bool Debug::IsBreakAtReturn(JavaScriptFrame* frame) { | 2319 bool Debug::IsBreakAtReturn(JavaScriptFrame* frame) { |
2323 HandleScope scope(isolate_); | 2320 HandleScope scope(isolate_); |
2324 | 2321 |
2325 // If there are no break points this cannot be break at return, as | 2322 // If there are no break points this cannot be break at return, as |
2326 // the debugger statement and stack guard debug break cannot be at | 2323 // the debugger statement and stack guard bebug break cannot be at |
2327 // return. | 2324 // return. |
2328 if (!has_break_points_) { | 2325 if (!has_break_points_) { |
2329 return false; | 2326 return false; |
2330 } | 2327 } |
2331 | 2328 |
2332 PrepareForBreakPoints(); | 2329 PrepareForBreakPoints(); |
2333 | 2330 |
2334 // Get the executing function in which the debug break occurred. | 2331 // Get the executing function in which the debug break occurred. |
2335 Handle<JSFunction> function(JSFunction::cast(frame->function())); | 2332 Handle<JSFunction> function(JSFunction::cast(frame->function())); |
2336 Handle<SharedFunctionInfo> shared(function->shared()); | 2333 Handle<SharedFunctionInfo> shared(function->shared()); |
(...skipping 899 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3236 return scope.Escape(v8::Utils::ToLocal(Handle<String>::cast(json))); | 3233 return scope.Escape(v8::Utils::ToLocal(Handle<String>::cast(json))); |
3237 } else { | 3234 } else { |
3238 return v8::Utils::ToLocal(response_json_); | 3235 return v8::Utils::ToLocal(response_json_); |
3239 } | 3236 } |
3240 } | 3237 } |
3241 | 3238 |
3242 | 3239 |
3243 v8::Handle<v8::Context> MessageImpl::GetEventContext() const { | 3240 v8::Handle<v8::Context> MessageImpl::GetEventContext() const { |
3244 Isolate* isolate = event_data_->GetIsolate(); | 3241 Isolate* isolate = event_data_->GetIsolate(); |
3245 v8::Handle<v8::Context> context = GetDebugEventContext(isolate); | 3242 v8::Handle<v8::Context> context = GetDebugEventContext(isolate); |
3246 // Isolate::context() may be NULL when "script collected" event occurs. | 3243 // Isolate::context() may be NULL when "script collected" event occures. |
3247 DCHECK(!context.IsEmpty()); | 3244 DCHECK(!context.IsEmpty()); |
3248 return context; | 3245 return context; |
3249 } | 3246 } |
3250 | 3247 |
3251 | 3248 |
3252 v8::Debug::ClientData* MessageImpl::GetClientData() const { | 3249 v8::Debug::ClientData* MessageImpl::GetClientData() const { |
3253 return client_data_; | 3250 return client_data_; |
3254 } | 3251 } |
3255 | 3252 |
3256 | 3253 |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3388 logger_->DebugEvent("Put", message.text()); | 3385 logger_->DebugEvent("Put", message.text()); |
3389 } | 3386 } |
3390 | 3387 |
3391 | 3388 |
3392 void LockingCommandMessageQueue::Clear() { | 3389 void LockingCommandMessageQueue::Clear() { |
3393 base::LockGuard<base::Mutex> lock_guard(&mutex_); | 3390 base::LockGuard<base::Mutex> lock_guard(&mutex_); |
3394 queue_.Clear(); | 3391 queue_.Clear(); |
3395 } | 3392 } |
3396 | 3393 |
3397 } } // namespace v8::internal | 3394 } } // namespace v8::internal |
OLD | NEW |