| 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 731 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 742 | 742 |
| 743 debug_context_ = Handle<Context>::cast( | 743 debug_context_ = Handle<Context>::cast( |
| 744 isolate_->global_handles()->Create(*context)); | 744 isolate_->global_handles()->Create(*context)); |
| 745 return true; | 745 return true; |
| 746 } | 746 } |
| 747 | 747 |
| 748 | 748 |
| 749 void Debug::Unload() { | 749 void Debug::Unload() { |
| 750 ClearAllBreakPoints(); | 750 ClearAllBreakPoints(); |
| 751 ClearStepping(); | 751 ClearStepping(); |
| 752 ClearSharedFunctionInfoInScript(); |
| 752 | 753 |
| 753 // Return debugger is not loaded. | 754 // Return debugger is not loaded. |
| 754 if (!is_loaded()) return; | 755 if (!is_loaded()) return; |
| 755 | 756 |
| 756 // Clear the script cache. | 757 // Clear the script cache. |
| 757 if (script_cache_ != NULL) { | 758 if (script_cache_ != NULL) { |
| 758 delete script_cache_; | 759 delete script_cache_; |
| 759 script_cache_ = NULL; | 760 script_cache_ = NULL; |
| 760 } | 761 } |
| 761 | 762 |
| (...skipping 1231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1993 RedirectActivationsToRecompiledCodeOnThread(isolate_, | 1994 RedirectActivationsToRecompiledCodeOnThread(isolate_, |
| 1994 isolate_->thread_local_top()); | 1995 isolate_->thread_local_top()); |
| 1995 | 1996 |
| 1996 ActiveFunctionsRedirector active_functions_redirector; | 1997 ActiveFunctionsRedirector active_functions_redirector; |
| 1997 isolate_->thread_manager()->IterateArchivedThreads( | 1998 isolate_->thread_manager()->IterateArchivedThreads( |
| 1998 &active_functions_redirector); | 1999 &active_functions_redirector); |
| 1999 } | 2000 } |
| 2000 } | 2001 } |
| 2001 | 2002 |
| 2002 | 2003 |
| 2004 static int MatchSharedFunctionInfo(Handle<SharedFunctionInfo> shared, |
| 2005 int position, |
| 2006 Handle<SharedFunctionInfo> target, |
| 2007 int target_start_position) { |
| 2008 // If the SharedFunctionInfo found has the requested script data and |
| 2009 // contains the source position it is a candidate. |
| 2010 int start_position = shared->function_token_position(); |
| 2011 if (start_position == RelocInfo::kNoPosition) { |
| 2012 start_position = shared->start_position(); |
| 2013 } |
| 2014 if (start_position <= position && |
| 2015 position <= shared->end_position()) { |
| 2016 // If there is no candidate or this function is within the current |
| 2017 // candidate this is the new candidate. |
| 2018 if (target.is_null()) { |
| 2019 return start_position; |
| 2020 } else { |
| 2021 if (target_start_position == start_position && |
| 2022 shared->end_position() == target->end_position()) { |
| 2023 // If a top-level function contains only one function |
| 2024 // declaration the source for the top-level and the function |
| 2025 // is the same. In that case prefer the non top-level function. |
| 2026 if (!shared->is_toplevel()) { |
| 2027 return start_position; |
| 2028 } |
| 2029 } else if (target_start_position <= start_position && |
| 2030 shared->end_position() <= target->end_position()) { |
| 2031 // This containment check includes equality as a function |
| 2032 // inside a top-level function can share either start or end |
| 2033 // position with the top-level function. |
| 2034 return start_position; |
| 2035 } |
| 2036 } |
| 2037 } |
| 2038 return RelocInfo::kNoPosition; |
| 2039 } |
| 2040 |
| 2041 |
| 2003 Handle<Object> Debug::FindSharedFunctionInfoInScript(Handle<Script> script, | 2042 Handle<Object> Debug::FindSharedFunctionInfoInScript(Handle<Script> script, |
| 2004 int position) { | 2043 int position) { |
| 2005 // Iterate the heap looking for SharedFunctionInfo generated from the | 2044 // Iterate the heap looking for SharedFunctionInfo generated from the |
| 2006 // script. The inner most SharedFunctionInfo containing the source position | 2045 // script. The inner most SharedFunctionInfo containing the source position |
| 2007 // for the requested break point is found. | 2046 // for the requested break point is found. |
| 2008 // NOTE: This might require several heap iterations. If the SharedFunctionInfo | 2047 // NOTE: This might require several heap iterations. If the SharedFunctionInfo |
| 2009 // which is found is not compiled it is compiled and the heap is iterated | 2048 // which is found is not compiled it is compiled and the heap is iterated |
| 2010 // again as the compilation might create inner functions from the newly | 2049 // again as the compilation might create inner functions from the newly |
| 2011 // compiled function and the actual requested break point might be in one of | 2050 // compiled function and the actual requested break point might be in one of |
| 2012 // these functions. | 2051 // these functions. |
| 2013 // NOTE: The below fix-point iteration depends on all functions that cannot be | 2052 // NOTE: The below fix-point iteration depends on all functions that cannot be |
| 2014 // compiled lazily without a context to not be compiled at all. Compilation | 2053 // compiled lazily without a context to not be compiled at all. Compilation |
| 2015 // will be triggered at points where we do not need a context. | 2054 // will be triggered at points where we do not need a context. |
| 2016 bool done = false; | 2055 bool done = false; |
| 2017 // The current candidate for the source position: | 2056 // The current candidate for the source position: |
| 2018 int target_start_position = RelocInfo::kNoPosition; | 2057 int target_start_position = RelocInfo::kNoPosition; |
| 2019 Handle<JSFunction> target_function; | 2058 Handle<JSFunction> target_function; |
| 2020 Handle<SharedFunctionInfo> target; | 2059 Handle<SharedFunctionInfo> target; |
| 2021 Heap* heap = isolate_->heap(); | 2060 Heap* heap = isolate_->heap(); |
| 2061 |
| 2062 if (!shared_info_list_.is_empty()) { |
| 2063 for (Handle<SharedFunctionInfo>* it = shared_info_list_.begin(); |
| 2064 it != shared_info_list_.end(); |
| 2065 it++) { |
| 2066 Handle<SharedFunctionInfo> shared = *it; |
| 2067 DCHECK(shared->script() == *script); |
| 2068 |
| 2069 int start_position = MatchSharedFunctionInfo(shared, |
| 2070 position, |
| 2071 target, |
| 2072 target_start_position); |
| 2073 if (start_position == RelocInfo::kNoPosition) continue; |
| 2074 |
| 2075 target_start_position = start_position; |
| 2076 target = shared; |
| 2077 } |
| 2078 |
| 2079 if (target.is_null()) return isolate_->factory()->undefined_value(); |
| 2080 return target; |
| 2081 } |
| 2082 |
| 2022 while (!done) { | 2083 while (!done) { |
| 2023 { // Extra scope for iterator. | 2084 { // Extra scope for iterator. |
| 2024 // If lazy compilation is off, we won't have duplicate shared function | 2085 // If lazy compilation is off, we won't have duplicate shared function |
| 2025 // infos that need to be filtered. | 2086 // infos that need to be filtered. |
| 2026 HeapIterator iterator(heap, FLAG_lazy ? HeapIterator::kNoFiltering | 2087 HeapIterator iterator(heap, FLAG_lazy ? HeapIterator::kNoFiltering |
| 2027 : HeapIterator::kFilterUnreachable); | 2088 : HeapIterator::kFilterUnreachable); |
| 2089 |
| 2028 for (HeapObject* obj = iterator.next(); | 2090 for (HeapObject* obj = iterator.next(); |
| 2029 obj != NULL; obj = iterator.next()) { | 2091 obj != NULL; obj = iterator.next()) { |
| 2030 bool found_next_candidate = false; | 2092 bool found_next_candidate = false; |
| 2031 Handle<JSFunction> function; | 2093 Handle<JSFunction> function; |
| 2032 Handle<SharedFunctionInfo> shared; | 2094 Handle<SharedFunctionInfo> shared; |
| 2033 if (obj->IsJSFunction()) { | 2095 if (obj->IsJSFunction()) { |
| 2034 function = Handle<JSFunction>(JSFunction::cast(obj)); | 2096 function = Handle<JSFunction>(JSFunction::cast(obj)); |
| 2035 shared = Handle<SharedFunctionInfo>(function->shared()); | 2097 shared = Handle<SharedFunctionInfo>(function->shared()); |
| 2036 DCHECK(shared->allows_lazy_compilation() || shared->is_compiled()); | 2098 DCHECK(shared->allows_lazy_compilation() || shared->is_compiled()); |
| 2037 found_next_candidate = true; | 2099 found_next_candidate = true; |
| 2038 } else if (obj->IsSharedFunctionInfo()) { | 2100 } else if (obj->IsSharedFunctionInfo()) { |
| 2039 shared = Handle<SharedFunctionInfo>(SharedFunctionInfo::cast(obj)); | 2101 shared = Handle<SharedFunctionInfo>(SharedFunctionInfo::cast(obj)); |
| 2040 // Skip functions that we cannot compile lazily without a context, | 2102 // Skip functions that we cannot compile lazily without a context, |
| 2041 // which is not available here, because there is no closure. | 2103 // which is not available here, because there is no closure. |
| 2042 found_next_candidate = shared->is_compiled() || | 2104 found_next_candidate = shared->is_compiled() || |
| 2043 shared->allows_lazy_compilation_without_context(); | 2105 shared->allows_lazy_compilation_without_context(); |
| 2044 } | 2106 } |
| 2045 if (!found_next_candidate) continue; | 2107 if (!found_next_candidate) continue; |
| 2046 if (shared->script() == *script) { | 2108 if (shared->script() != *script) continue; |
| 2047 // If the SharedFunctionInfo found has the requested script data and | 2109 |
| 2048 // contains the source position it is a candidate. | 2110 int start_position = MatchSharedFunctionInfo(shared, |
| 2049 int start_position = shared->function_token_position(); | 2111 position, |
| 2050 if (start_position == RelocInfo::kNoPosition) { | 2112 target, |
| 2051 start_position = shared->start_position(); | 2113 target_start_position); |
| 2052 } | 2114 if (start_position == RelocInfo::kNoPosition) continue; |
| 2053 if (start_position <= position && | 2115 |
| 2054 position <= shared->end_position()) { | 2116 target_start_position = start_position; |
| 2055 // If there is no candidate or this function is within the current | 2117 target_function = function; |
| 2056 // candidate this is the new candidate. | 2118 target = shared; |
| 2057 if (target.is_null()) { | |
| 2058 target_start_position = start_position; | |
| 2059 target_function = function; | |
| 2060 target = shared; | |
| 2061 } else { | |
| 2062 if (target_start_position == start_position && | |
| 2063 shared->end_position() == target->end_position()) { | |
| 2064 // If a top-level function contains only one function | |
| 2065 // declaration the source for the top-level and the function | |
| 2066 // is the same. In that case prefer the non top-level function. | |
| 2067 if (!shared->is_toplevel()) { | |
| 2068 target_start_position = start_position; | |
| 2069 target_function = function; | |
| 2070 target = shared; | |
| 2071 } | |
| 2072 } else if (target_start_position <= start_position && | |
| 2073 shared->end_position() <= target->end_position()) { | |
| 2074 // This containment check includes equality as a function | |
| 2075 // inside a top-level function can share either start or end | |
| 2076 // position with the top-level function. | |
| 2077 target_start_position = start_position; | |
| 2078 target_function = function; | |
| 2079 target = shared; | |
| 2080 } | |
| 2081 } | |
| 2082 } | |
| 2083 } | |
| 2084 } // End for loop. | 2119 } // End for loop. |
| 2085 } // End no-allocation scope. | 2120 } // End no-allocation scope. |
| 2086 | 2121 |
| 2087 if (target.is_null()) return isolate_->factory()->undefined_value(); | 2122 if (target.is_null()) return isolate_->factory()->undefined_value(); |
| 2088 | 2123 |
| 2089 // There will be at least one break point when we are done. | 2124 // There will be at least one break point when we are done. |
| 2090 has_break_points_ = true; | 2125 has_break_points_ = true; |
| 2091 | 2126 |
| 2092 // If the candidate found is compiled we are done. | 2127 // If the candidate found is compiled we are done. |
| 2093 done = target->is_compiled(); | 2128 done = target->is_compiled(); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 2116 shared->start_position_and_type() == | 2151 shared->start_position_and_type() == |
| 2117 target->start_position_and_type()) { | 2152 target->start_position_and_type()) { |
| 2118 function->set_shared(*target); | 2153 function->set_shared(*target); |
| 2119 } | 2154 } |
| 2120 } | 2155 } |
| 2121 | 2156 |
| 2122 return target; | 2157 return target; |
| 2123 } | 2158 } |
| 2124 | 2159 |
| 2125 | 2160 |
| 2161 bool Debug::CollectSharedFunctionInfoInScript(Handle<Script> script) { |
| 2162 bool done = false; |
| 2163 // The current candidate for the source position: |
| 2164 Handle<JSFunction> target_function; |
| 2165 Handle<SharedFunctionInfo> target; |
| 2166 Heap* heap = isolate_->heap(); |
| 2167 GlobalHandles* global_handles = isolate_->global_handles(); |
| 2168 while (!done) { |
| 2169 DCHECK(shared_info_list_.is_empty()); |
| 2170 done = true; |
| 2171 |
| 2172 { // Extra scope for iterator. |
| 2173 // If lazy compilation is off, we won't have duplicate shared function |
| 2174 // infos that need to be filtered. |
| 2175 HeapIterator iterator(heap, FLAG_lazy ? HeapIterator::kNoFiltering |
| 2176 : HeapIterator::kFilterUnreachable); |
| 2177 for (HeapObject* obj = iterator.next(); |
| 2178 obj != NULL; obj = iterator.next()) { |
| 2179 bool found_next_candidate = false; |
| 2180 Handle<JSFunction> function; |
| 2181 Handle<SharedFunctionInfo> shared; |
| 2182 if (obj->IsJSFunction()) { |
| 2183 function = Handle<JSFunction>(JSFunction::cast(obj)); |
| 2184 shared = Handle<SharedFunctionInfo>(function->shared()); |
| 2185 DCHECK(shared->allows_lazy_compilation() || shared->is_compiled()); |
| 2186 found_next_candidate = true; |
| 2187 } else if (obj->IsSharedFunctionInfo()) { |
| 2188 shared = Handle<SharedFunctionInfo>(SharedFunctionInfo::cast(obj)); |
| 2189 // Skip functions that we cannot compile lazily without a context, |
| 2190 // which is not available here, because there is no closure. |
| 2191 found_next_candidate = shared->is_compiled() || |
| 2192 shared->allows_lazy_compilation_without_context(); |
| 2193 } |
| 2194 if (!found_next_candidate) continue; |
| 2195 if (shared->script() != *script) continue; |
| 2196 |
| 2197 if (!shared->is_compiled()) { |
| 2198 target = shared; |
| 2199 target_function = function; |
| 2200 done = false; |
| 2201 break; |
| 2202 } |
| 2203 |
| 2204 shared_info_list_.Add(global_handles->Create(*shared)); |
| 2205 } // End for loop. |
| 2206 } // End no-allocation scope. |
| 2207 |
| 2208 if (done) continue; |
| 2209 |
| 2210 // Cleanup the list, next iteration will re-add all shared infos |
| 2211 ClearSharedFunctionInfoInScript(); |
| 2212 |
| 2213 // If the candidate is not compiled, compile it to reveal any inner |
| 2214 // functions which might contain the requested source position. This |
| 2215 // will compile all inner functions that cannot be compiled without a |
| 2216 // context, because Compiler::BuildFunctionInfo checks whether the |
| 2217 // debugger is active. |
| 2218 MaybeHandle<Code> maybe_result = target_function.is_null() |
| 2219 ? Compiler::GetUnoptimizedCode(target) |
| 2220 : Compiler::GetUnoptimizedCode(target_function); |
| 2221 if (maybe_result.is_null()) return false; |
| 2222 } // End while loop. |
| 2223 |
| 2224 return true; |
| 2225 } |
| 2226 |
| 2227 |
| 2228 void Debug::ClearSharedFunctionInfoInScript() { |
| 2229 while (!shared_info_list_.is_empty()) { |
| 2230 Handle<SharedFunctionInfo> shared = shared_info_list_.RemoveLast(); |
| 2231 Object** location = reinterpret_cast<Object**>(shared.location()); |
| 2232 GlobalHandles::Destroy(location); |
| 2233 } |
| 2234 } |
| 2235 |
| 2236 |
| 2126 // Ensures the debug information is present for shared. | 2237 // Ensures the debug information is present for shared. |
| 2127 bool Debug::EnsureDebugInfo(Handle<SharedFunctionInfo> shared, | 2238 bool Debug::EnsureDebugInfo(Handle<SharedFunctionInfo> shared, |
| 2128 Handle<JSFunction> function) { | 2239 Handle<JSFunction> function) { |
| 2129 Isolate* isolate = shared->GetIsolate(); | 2240 Isolate* isolate = shared->GetIsolate(); |
| 2130 | 2241 |
| 2131 // Return if we already have the debug info for shared. | 2242 // Return if we already have the debug info for shared. |
| 2132 if (HasDebugInfo(shared)) { | 2243 if (HasDebugInfo(shared)) { |
| 2133 DCHECK(shared->is_compiled()); | 2244 DCHECK(shared->is_compiled()); |
| 2134 return true; | 2245 return true; |
| 2135 } | 2246 } |
| (...skipping 524 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2660 return; | 2771 return; |
| 2661 } | 2772 } |
| 2662 DCHECK(update_script_break_points->IsJSFunction()); | 2773 DCHECK(update_script_break_points->IsJSFunction()); |
| 2663 | 2774 |
| 2664 // Wrap the script object in a proper JS object before passing it | 2775 // Wrap the script object in a proper JS object before passing it |
| 2665 // to JavaScript. | 2776 // to JavaScript. |
| 2666 Handle<Object> wrapper = Script::GetWrapper(script); | 2777 Handle<Object> wrapper = Script::GetWrapper(script); |
| 2667 | 2778 |
| 2668 // Call UpdateScriptBreakPoints expect no exceptions. | 2779 // Call UpdateScriptBreakPoints expect no exceptions. |
| 2669 Handle<Object> argv[] = { wrapper }; | 2780 Handle<Object> argv[] = { wrapper }; |
| 2781 ClearSharedFunctionInfoInScript(); |
| 2670 if (Execution::TryCall(Handle<JSFunction>::cast(update_script_break_points), | 2782 if (Execution::TryCall(Handle<JSFunction>::cast(update_script_break_points), |
| 2671 isolate_->js_builtins_object(), | 2783 isolate_->js_builtins_object(), |
| 2672 arraysize(argv), | 2784 arraysize(argv), |
| 2673 argv).is_null()) { | 2785 argv).is_null()) { |
| 2786 ClearSharedFunctionInfoInScript(); |
| 2674 return; | 2787 return; |
| 2675 } | 2788 } |
| 2676 | 2789 |
| 2677 // Create the compile state object. | 2790 // Create the compile state object. |
| 2678 Handle<Object> event_data; | 2791 Handle<Object> event_data; |
| 2679 // Bail out and don't call debugger if exception. | 2792 // Bail out and don't call debugger if exception. |
| 2680 if (!MakeCompileEvent(script, v8::AfterCompile).ToHandle(&event_data)) return; | 2793 if (!MakeCompileEvent(script, v8::AfterCompile).ToHandle(&event_data)) return; |
| 2681 | 2794 |
| 2682 // Process debug event. | 2795 // Process debug event. |
| 2683 ProcessDebugEvent(v8::AfterCompile, Handle<JSObject>::cast(event_data), true); | 2796 ProcessDebugEvent(v8::AfterCompile, Handle<JSObject>::cast(event_data), true); |
| (...skipping 718 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3402 logger_->DebugEvent("Put", message.text()); | 3515 logger_->DebugEvent("Put", message.text()); |
| 3403 } | 3516 } |
| 3404 | 3517 |
| 3405 | 3518 |
| 3406 void LockingCommandMessageQueue::Clear() { | 3519 void LockingCommandMessageQueue::Clear() { |
| 3407 base::LockGuard<base::Mutex> lock_guard(&mutex_); | 3520 base::LockGuard<base::Mutex> lock_guard(&mutex_); |
| 3408 queue_.Clear(); | 3521 queue_.Clear(); |
| 3409 } | 3522 } |
| 3410 | 3523 |
| 3411 } } // namespace v8::internal | 3524 } } // namespace v8::internal |
| OLD | NEW |