Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(268)

Side by Side Diff: src/debug.cc

Issue 1100183002: debug: cache SharedFunctionInfo for multi-bp set Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/debug.h ('k') | src/debug-debugger.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/debug.h ('k') | src/debug-debugger.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698