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 1966 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1977 RedirectActivationsToRecompiledCodeOnThread(isolate_, | 1977 RedirectActivationsToRecompiledCodeOnThread(isolate_, |
1978 isolate_->thread_local_top()); | 1978 isolate_->thread_local_top()); |
1979 | 1979 |
1980 ActiveFunctionsRedirector active_functions_redirector; | 1980 ActiveFunctionsRedirector active_functions_redirector; |
1981 isolate_->thread_manager()->IterateArchivedThreads( | 1981 isolate_->thread_manager()->IterateArchivedThreads( |
1982 &active_functions_redirector); | 1982 &active_functions_redirector); |
1983 } | 1983 } |
1984 } | 1984 } |
1985 | 1985 |
1986 | 1986 |
1987 class SharedFunctionInfoFinder { | |
1988 public: | |
1989 explicit SharedFunctionInfoFinder(int target_position) | |
1990 : current_candidate_(NULL), | |
1991 current_candidate_closure_(NULL), | |
1992 current_start_position_(RelocInfo::kNoPosition), | |
1993 target_position_(target_position) {} | |
1994 | |
1995 void NewCandidate(SharedFunctionInfo* shared, JSFunction* closure = NULL) { | |
1996 int start_position = shared->function_token_position(); | |
1997 if (start_position == RelocInfo::kNoPosition) { | |
1998 start_position = shared->start_position(); | |
1999 } | |
2000 | |
2001 if (start_position > target_position_) return; | |
2002 if (target_position_ > shared->end_position()) return; | |
2003 | |
2004 if (current_candidate_ != NULL) { | |
2005 if (current_start_position_ == start_position && | |
2006 shared->end_position() == current_candidate_->end_position()) { | |
2007 // If a top-level function contains only one function | |
2008 // declaration the source for the top-level and the function | |
2009 // is the same. In that case prefer the non top-level function. | |
2010 if (shared->is_toplevel()) return; | |
2011 } else if (start_position < current_start_position_ || | |
2012 current_candidate_->end_position() < shared->end_position()) { | |
2013 return; | |
2014 } | |
2015 } | |
2016 | |
2017 current_start_position_ = start_position; | |
2018 current_candidate_ = shared; | |
2019 current_candidate_closure_ = closure; | |
2020 } | |
2021 | |
2022 SharedFunctionInfo* Result() { return current_candidate_; } | |
2023 | |
2024 JSFunction* ResultClosure() { return current_candidate_closure_; } | |
2025 | |
2026 private: | |
2027 SharedFunctionInfo* current_candidate_; | |
2028 JSFunction* current_candidate_closure_; | |
2029 int current_start_position_; | |
2030 int target_position_; | |
2031 DisallowHeapAllocation no_gc_; | |
2032 }; | |
2033 | |
2034 | |
2035 template <typename C> | |
2036 bool Debug::CompileToRevealInnerFunctions(C* compilable) { | |
2037 HandleScope scope(isolate_); | |
2038 // Force compiling inner functions that require context. | |
2039 // TODO(yangguo): remove this hack. | |
2040 bool has_break_points = has_break_points_; | |
2041 has_break_points_ = true; | |
2042 Handle<C> compilable_handle(compilable); | |
2043 bool result = !Compiler::GetUnoptimizedCode(compilable_handle).is_null(); | |
2044 has_break_points_ = has_break_points; | |
2045 return result; | |
2046 } | |
2047 | |
2048 | |
1987 Handle<Object> Debug::FindSharedFunctionInfoInScript(Handle<Script> script, | 2049 Handle<Object> Debug::FindSharedFunctionInfoInScript(Handle<Script> script, |
1988 int position) { | 2050 int position) { |
1989 // Iterate the heap looking for SharedFunctionInfo generated from the | 2051 while (true) { |
1990 // script. The inner most SharedFunctionInfo containing the source position | 2052 // Go through all shared function infos associated with this script to |
1991 // for the requested break point is found. | 2053 // find the inner most function containing this position. |
1992 // NOTE: This might require several heap iterations. If the SharedFunctionInfo | 2054 if (!script->shared_function_infos()->IsWeakFixedArray()) break; |
1993 // which is found is not compiled it is compiled and the heap is iterated | 2055 WeakFixedArray* array = |
1994 // again as the compilation might create inner functions from the newly | 2056 WeakFixedArray::cast(script->shared_function_infos()); |
1995 // compiled function and the actual requested break point might be in one of | 2057 |
1996 // these functions. | 2058 SharedFunctionInfo* shared; |
1997 // NOTE: The below fix-point iteration depends on all functions that cannot be | 2059 { |
1998 // compiled lazily without a context to not be compiled at all. Compilation | 2060 SharedFunctionInfoFinder finder(position); |
1999 // will be triggered at points where we do not need a context. | 2061 for (int i = 0; i < array->Length(); i++) { |
2000 bool done = false; | 2062 Object* item = array->Get(i); |
2001 // The current candidate for the source position: | 2063 if (!item->IsSharedFunctionInfo()) continue; |
2002 int target_start_position = RelocInfo::kNoPosition; | 2064 SharedFunctionInfo* shared = SharedFunctionInfo::cast(item); |
brucedawson
2015/06/29 17:08:53
Is it intentional that this shadows the outer-scop
| |
2003 Handle<JSFunction> target_function; | 2065 finder.NewCandidate(shared); |
2004 Handle<SharedFunctionInfo> target; | 2066 } |
2005 Heap* heap = isolate_->heap(); | 2067 shared = finder.Result(); |
2006 while (!done) { | 2068 if (shared == NULL) break; |
2007 { // Extra scope for iterator. | 2069 // We found it if it's already compiled. |
2008 // If lazy compilation is off, we won't have duplicate shared function | 2070 if (shared->is_compiled()) return handle(shared); |
2009 // infos that need to be filtered. | 2071 } |
2010 HeapIterator iterator(heap, FLAG_lazy ? HeapIterator::kNoFiltering | 2072 // If not, compile to reveal inner functions, if possible. |
2011 : HeapIterator::kFilterUnreachable); | 2073 if (shared->allows_lazy_compilation_without_context()) { |
2012 for (HeapObject* obj = iterator.next(); | 2074 if (!CompileToRevealInnerFunctions(shared)) break; |
2013 obj != NULL; obj = iterator.next()) { | 2075 continue; |
2014 bool found_next_candidate = false; | 2076 } |
2015 Handle<JSFunction> function; | 2077 |
2016 Handle<SharedFunctionInfo> shared; | 2078 // If not possible, comb the heap for the best suitable compile target. |
2017 if (obj->IsJSFunction()) { | 2079 JSFunction* closure; |
2018 function = Handle<JSFunction>(JSFunction::cast(obj)); | 2080 { |
2019 shared = Handle<SharedFunctionInfo>(function->shared()); | 2081 HeapIterator it(isolate_->heap(), HeapIterator::kNoFiltering); |
2020 DCHECK(shared->allows_lazy_compilation() || shared->is_compiled()); | 2082 SharedFunctionInfoFinder finder(position); |
2021 found_next_candidate = true; | 2083 while (HeapObject* object = it.next()) { |
2022 } else if (obj->IsSharedFunctionInfo()) { | 2084 JSFunction* closure = NULL; |
brucedawson
2015/06/29 17:08:53
Is it intentional that this shadows the outer-scop
| |
2023 shared = Handle<SharedFunctionInfo>(SharedFunctionInfo::cast(obj)); | 2085 SharedFunctionInfo* shared = NULL; |
brucedawson
2015/06/29 17:08:53
Is it intentional that this shadows the outer-scop
| |
2024 // Skip functions that we cannot compile lazily without a context, | 2086 if (object->IsJSFunction()) { |
2025 // which is not available here, because there is no closure. | 2087 closure = JSFunction::cast(object); |
2026 found_next_candidate = shared->is_compiled() || | 2088 shared = closure->shared(); |
2027 shared->allows_lazy_compilation_without_context(); | 2089 } else if (object->IsSharedFunctionInfo()) { |
2090 shared = SharedFunctionInfo::cast(object); | |
2091 if (!shared->allows_lazy_compilation_without_context()) continue; | |
2092 } else { | |
2093 continue; | |
2028 } | 2094 } |
2029 if (!found_next_candidate) continue; | 2095 if (shared->script() == *script) finder.NewCandidate(shared, closure); |
2030 if (shared->script() == *script) { | 2096 } |
2031 // If the SharedFunctionInfo found has the requested script data and | 2097 closure = finder.ResultClosure(); |
2032 // contains the source position it is a candidate. | 2098 shared = finder.Result(); |
2033 int start_position = shared->function_token_position(); | |
2034 if (start_position == RelocInfo::kNoPosition) { | |
2035 start_position = shared->start_position(); | |
2036 } | |
2037 if (start_position <= position && | |
2038 position <= shared->end_position()) { | |
2039 // If there is no candidate or this function is within the current | |
2040 // candidate this is the new candidate. | |
2041 if (target.is_null()) { | |
2042 target_start_position = start_position; | |
2043 target_function = function; | |
2044 target = shared; | |
2045 } else { | |
2046 if (target_start_position == start_position && | |
2047 shared->end_position() == target->end_position()) { | |
2048 // If a top-level function contains only one function | |
2049 // declaration the source for the top-level and the function | |
2050 // is the same. In that case prefer the non top-level function. | |
2051 if (!shared->is_toplevel()) { | |
2052 target_start_position = start_position; | |
2053 target_function = function; | |
2054 target = shared; | |
2055 } | |
2056 } else if (target_start_position <= start_position && | |
2057 shared->end_position() <= target->end_position()) { | |
2058 // This containment check includes equality as a function | |
2059 // inside a top-level function can share either start or end | |
2060 // position with the top-level function. | |
2061 target_start_position = start_position; | |
2062 target_function = function; | |
2063 target = shared; | |
2064 } | |
2065 } | |
2066 } | |
2067 } | |
2068 } // End for loop. | |
2069 } // End no-allocation scope. | |
2070 | |
2071 if (target.is_null()) return isolate_->factory()->undefined_value(); | |
2072 | |
2073 // There will be at least one break point when we are done. | |
2074 has_break_points_ = true; | |
2075 | |
2076 // If the candidate found is compiled we are done. | |
2077 done = target->is_compiled(); | |
2078 if (!done) { | |
2079 // If the candidate is not compiled, compile it to reveal any inner | |
2080 // functions which might contain the requested source position. This | |
2081 // will compile all inner functions that cannot be compiled without a | |
2082 // context, because Compiler::GetSharedFunctionInfo checks whether the | |
2083 // debugger is active. | |
2084 MaybeHandle<Code> maybe_result = target_function.is_null() | |
2085 ? Compiler::GetUnoptimizedCode(target) | |
2086 : Compiler::GetUnoptimizedCode(target_function); | |
2087 if (maybe_result.is_null()) return isolate_->factory()->undefined_value(); | |
2088 } | 2099 } |
2089 } // End while loop. | 2100 if (closure == NULL ? !CompileToRevealInnerFunctions(shared) |
2090 | 2101 : !CompileToRevealInnerFunctions(closure)) { |
2091 // JSFunctions from the same literal may not have the same shared function | 2102 break; |
2092 // info. Find those JSFunctions and deduplicate the shared function info. | |
2093 HeapIterator iterator(heap, FLAG_lazy ? HeapIterator::kNoFiltering | |
2094 : HeapIterator::kFilterUnreachable); | |
2095 for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) { | |
2096 if (!obj->IsJSFunction()) continue; | |
2097 JSFunction* function = JSFunction::cast(obj); | |
2098 SharedFunctionInfo* shared = function->shared(); | |
2099 if (shared != *target && shared->script() == target->script() && | |
2100 shared->start_position_and_type() == | |
2101 target->start_position_and_type()) { | |
2102 function->set_shared(*target); | |
2103 } | 2103 } |
2104 } | 2104 } |
2105 | 2105 return isolate_->factory()->undefined_value(); |
2106 return target; | |
2107 } | 2106 } |
2108 | 2107 |
2109 | 2108 |
2110 // Ensures the debug information is present for shared. | 2109 // Ensures the debug information is present for shared. |
2111 bool Debug::EnsureDebugInfo(Handle<SharedFunctionInfo> shared, | 2110 bool Debug::EnsureDebugInfo(Handle<SharedFunctionInfo> shared, |
2112 Handle<JSFunction> function) { | 2111 Handle<JSFunction> function) { |
2113 Isolate* isolate = shared->GetIsolate(); | 2112 Isolate* isolate = shared->GetIsolate(); |
2114 | 2113 |
2115 // Return if we already have the debug info for shared. | 2114 // Return if we already have the debug info for shared. |
2116 if (HasDebugInfo(shared)) { | 2115 if (HasDebugInfo(shared)) { |
(...skipping 1270 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3387 } | 3386 } |
3388 | 3387 |
3389 | 3388 |
3390 void LockingCommandMessageQueue::Clear() { | 3389 void LockingCommandMessageQueue::Clear() { |
3391 base::LockGuard<base::Mutex> lock_guard(&mutex_); | 3390 base::LockGuard<base::Mutex> lock_guard(&mutex_); |
3392 queue_.Clear(); | 3391 queue_.Clear(); |
3393 } | 3392 } |
3394 | 3393 |
3395 } // namespace internal | 3394 } // namespace internal |
3396 } // namespace v8 | 3395 } // namespace v8 |
OLD | NEW |