OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 680 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
691 } | 691 } |
692 } | 692 } |
693 | 693 |
694 | 694 |
695 void Debug::HandleWeakDebugInfo(v8::Persistent<v8::Value> obj, void* data) { | 695 void Debug::HandleWeakDebugInfo(v8::Persistent<v8::Value> obj, void* data) { |
696 Debug* debug = Isolate::Current()->debug(); | 696 Debug* debug = Isolate::Current()->debug(); |
697 DebugInfoListNode* node = reinterpret_cast<DebugInfoListNode*>(data); | 697 DebugInfoListNode* node = reinterpret_cast<DebugInfoListNode*>(data); |
698 // We need to clear all breakpoints associated with the function to restore | 698 // We need to clear all breakpoints associated with the function to restore |
699 // original code and avoid patching the code twice later because | 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 | 700 // the function will live in the heap until next gc, and can be found by |
701 // Runtime::FindSharedFunctionInfoInScript. | 701 // Debug::FindSharedFunctionInfoInScript. |
702 BreakLocationIterator it(node->debug_info(), ALL_BREAK_LOCATIONS); | 702 BreakLocationIterator it(node->debug_info(), ALL_BREAK_LOCATIONS); |
703 it.ClearAllDebugBreak(); | 703 it.ClearAllDebugBreak(); |
704 debug->RemoveDebugInfo(node->debug_info()); | 704 debug->RemoveDebugInfo(node->debug_info()); |
705 #ifdef DEBUG | 705 #ifdef DEBUG |
706 node = debug->debug_info_list_; | 706 node = debug->debug_info_list_; |
707 while (node != NULL) { | 707 while (node != NULL) { |
708 ASSERT(node != reinterpret_cast<DebugInfoListNode*>(data)); | 708 ASSERT(node != reinterpret_cast<DebugInfoListNode*>(data)); |
709 node = node->next(); | 709 node = node->next(); |
710 } | 710 } |
711 #endif | 711 #endif |
(...skipping 453 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1165 // At least one active break point now. | 1165 // At least one active break point now. |
1166 ASSERT(debug_info->GetBreakPointCount() > 0); | 1166 ASSERT(debug_info->GetBreakPointCount() > 0); |
1167 } | 1167 } |
1168 | 1168 |
1169 | 1169 |
1170 bool Debug::SetBreakPointForScript(Handle<Script> script, | 1170 bool Debug::SetBreakPointForScript(Handle<Script> script, |
1171 Handle<Object> break_point_object, | 1171 Handle<Object> break_point_object, |
1172 int* source_position) { | 1172 int* source_position) { |
1173 HandleScope scope(isolate_); | 1173 HandleScope scope(isolate_); |
1174 | 1174 |
1175 // No need to call PrepareForBreakPoints because it will be called | 1175 PrepareForBreakPoints(); |
1176 // implicitly by Runtime::FindSharedFunctionInfoInScript. | 1176 |
1177 Object* result = Runtime::FindSharedFunctionInfoInScript(isolate_, | 1177 // Obtain shared function info for the function. |
1178 script, | 1178 Object* result = FindSharedFunctionInfoInScript(script, *source_position); |
1179 *source_position); | |
1180 if (result->IsUndefined()) return false; | 1179 if (result->IsUndefined()) return false; |
1181 | 1180 |
1182 // Make sure the function has set up the debug info. | 1181 // Make sure the function has set up the debug info. |
1183 Handle<SharedFunctionInfo> shared(SharedFunctionInfo::cast(result)); | 1182 Handle<SharedFunctionInfo> shared(SharedFunctionInfo::cast(result)); |
1184 if (!EnsureDebugInfo(shared, Handle<JSFunction>::null())) { | 1183 if (!EnsureDebugInfo(shared, Handle<JSFunction>::null())) { |
1185 // Return if retrieving debug info failed. | 1184 // Return if retrieving debug info failed. |
1186 return false; | 1185 return false; |
1187 } | 1186 } |
1188 | 1187 |
1189 // Find position within function. The script position might be before the | 1188 // Find position within function. The script position might be before the |
(...skipping 895 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2085 RedirectActivationsToRecompiledCodeOnThread(isolate_, | 2084 RedirectActivationsToRecompiledCodeOnThread(isolate_, |
2086 isolate_->thread_local_top()); | 2085 isolate_->thread_local_top()); |
2087 | 2086 |
2088 ActiveFunctionsRedirector active_functions_redirector; | 2087 ActiveFunctionsRedirector active_functions_redirector; |
2089 isolate_->thread_manager()->IterateArchivedThreads( | 2088 isolate_->thread_manager()->IterateArchivedThreads( |
2090 &active_functions_redirector); | 2089 &active_functions_redirector); |
2091 } | 2090 } |
2092 } | 2091 } |
2093 | 2092 |
2094 | 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()) { |
| 2192 SharedFunctionInfo::CompileLazy(target, KEEP_EXCEPTION); |
| 2193 } else { |
| 2194 JSFunction::CompileLazy(target_function, KEEP_EXCEPTION); |
| 2195 } |
| 2196 } |
| 2197 } // End while loop. |
| 2198 |
| 2199 return *target; |
| 2200 } |
| 2201 |
| 2202 |
2095 // Ensures the debug information is present for shared. | 2203 // Ensures the debug information is present for shared. |
2096 bool Debug::EnsureDebugInfo(Handle<SharedFunctionInfo> shared, | 2204 bool Debug::EnsureDebugInfo(Handle<SharedFunctionInfo> shared, |
2097 Handle<JSFunction> function) { | 2205 Handle<JSFunction> function) { |
2098 // Return if we already have the debug info for shared. | 2206 // Return if we already have the debug info for shared. |
2099 if (HasDebugInfo(shared)) { | 2207 if (HasDebugInfo(shared)) { |
2100 ASSERT(shared->is_compiled()); | 2208 ASSERT(shared->is_compiled()); |
2101 return true; | 2209 return true; |
2102 } | 2210 } |
2103 | 2211 |
2104 // There will be at least one break point when we are done. | 2212 // There will be at least one break point when we are done. |
(...skipping 1552 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3657 { | 3765 { |
3658 Locker locker; | 3766 Locker locker; |
3659 Isolate::Current()->debugger()->CallMessageDispatchHandler(); | 3767 Isolate::Current()->debugger()->CallMessageDispatchHandler(); |
3660 } | 3768 } |
3661 } | 3769 } |
3662 } | 3770 } |
3663 | 3771 |
3664 #endif // ENABLE_DEBUGGER_SUPPORT | 3772 #endif // ENABLE_DEBUGGER_SUPPORT |
3665 | 3773 |
3666 } } // namespace v8::internal | 3774 } } // namespace v8::internal |
OLD | NEW |