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 | |
2049 Handle<Object> Debug::FindSharedFunctionInfoInScript(Handle<Script> script, | 1987 Handle<Object> Debug::FindSharedFunctionInfoInScript(Handle<Script> script, |
2050 int position) { | 1988 int position) { |
2051 while (true) { | 1989 // Iterate the heap looking for SharedFunctionInfo generated from the |
2052 // Go through all shared function infos associated with this script to | 1990 // script. The inner most SharedFunctionInfo containing the source position |
2053 // find the inner most function containing this position. | 1991 // for the requested break point is found. |
2054 if (!script->shared_function_infos()->IsWeakFixedArray()) break; | 1992 // NOTE: This might require several heap iterations. If the SharedFunctionInfo |
2055 WeakFixedArray* array = | 1993 // which is found is not compiled it is compiled and the heap is iterated |
2056 WeakFixedArray::cast(script->shared_function_infos()); | 1994 // again as the compilation might create inner functions from the newly |
| 1995 // compiled function and the actual requested break point might be in one of |
| 1996 // these functions. |
| 1997 // NOTE: The below fix-point iteration depends on all functions that cannot be |
| 1998 // compiled lazily without a context to not be compiled at all. Compilation |
| 1999 // will be triggered at points where we do not need a context. |
| 2000 bool done = false; |
| 2001 // The current candidate for the source position: |
| 2002 int target_start_position = RelocInfo::kNoPosition; |
| 2003 Handle<JSFunction> target_function; |
| 2004 Handle<SharedFunctionInfo> target; |
| 2005 Heap* heap = isolate_->heap(); |
| 2006 while (!done) { |
| 2007 { // Extra scope for iterator. |
| 2008 // If lazy compilation is off, we won't have duplicate shared function |
| 2009 // infos that need to be filtered. |
| 2010 HeapIterator iterator(heap, FLAG_lazy ? HeapIterator::kNoFiltering |
| 2011 : HeapIterator::kFilterUnreachable); |
| 2012 for (HeapObject* obj = iterator.next(); |
| 2013 obj != NULL; obj = iterator.next()) { |
| 2014 bool found_next_candidate = false; |
| 2015 Handle<JSFunction> function; |
| 2016 Handle<SharedFunctionInfo> shared; |
| 2017 if (obj->IsJSFunction()) { |
| 2018 function = Handle<JSFunction>(JSFunction::cast(obj)); |
| 2019 shared = Handle<SharedFunctionInfo>(function->shared()); |
| 2020 DCHECK(shared->allows_lazy_compilation() || shared->is_compiled()); |
| 2021 found_next_candidate = true; |
| 2022 } else if (obj->IsSharedFunctionInfo()) { |
| 2023 shared = Handle<SharedFunctionInfo>(SharedFunctionInfo::cast(obj)); |
| 2024 // Skip functions that we cannot compile lazily without a context, |
| 2025 // which is not available here, because there is no closure. |
| 2026 found_next_candidate = shared->is_compiled() || |
| 2027 shared->allows_lazy_compilation_without_context(); |
| 2028 } |
| 2029 if (!found_next_candidate) continue; |
| 2030 if (shared->script() == *script) { |
| 2031 // If the SharedFunctionInfo found has the requested script data and |
| 2032 // contains the source position it is a candidate. |
| 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. |
2057 | 2070 |
2058 SharedFunctionInfo* shared; | 2071 if (target.is_null()) return isolate_->factory()->undefined_value(); |
2059 { | 2072 |
2060 SharedFunctionInfoFinder finder(position); | 2073 // There will be at least one break point when we are done. |
2061 for (int i = 0; i < array->Length(); i++) { | 2074 has_break_points_ = true; |
2062 Object* item = array->Get(i); | 2075 |
2063 if (!item->IsSharedFunctionInfo()) continue; | 2076 // If the candidate found is compiled we are done. |
2064 SharedFunctionInfo* shared = SharedFunctionInfo::cast(item); | 2077 done = target->is_compiled(); |
2065 finder.NewCandidate(shared); | 2078 if (!done) { |
2066 } | 2079 // If the candidate is not compiled, compile it to reveal any inner |
2067 shared = finder.Result(); | 2080 // functions which might contain the requested source position. This |
2068 if (shared == NULL) break; | 2081 // will compile all inner functions that cannot be compiled without a |
2069 // We found it if it's already compiled. | 2082 // context, because Compiler::GetSharedFunctionInfo checks whether the |
2070 if (shared->is_compiled()) return handle(shared); | 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(); |
2071 } | 2088 } |
2072 // If not, compile to reveal inner functions, if possible. | 2089 } // End while loop. |
2073 if (shared->allows_lazy_compilation_without_context()) { | |
2074 if (!CompileToRevealInnerFunctions(shared)) break; | |
2075 continue; | |
2076 } | |
2077 | 2090 |
2078 // If not possible, comb the heap for the best suitable compile target. | 2091 // JSFunctions from the same literal may not have the same shared function |
2079 JSFunction* closure; | 2092 // info. Find those JSFunctions and deduplicate the shared function info. |
2080 { | 2093 HeapIterator iterator(heap, FLAG_lazy ? HeapIterator::kNoFiltering |
2081 HeapIterator it(isolate_->heap(), HeapIterator::kNoFiltering); | 2094 : HeapIterator::kFilterUnreachable); |
2082 SharedFunctionInfoFinder finder(position); | 2095 for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) { |
2083 while (HeapObject* object = it.next()) { | 2096 if (!obj->IsJSFunction()) continue; |
2084 JSFunction* closure = NULL; | 2097 JSFunction* function = JSFunction::cast(obj); |
2085 SharedFunctionInfo* shared = NULL; | 2098 SharedFunctionInfo* shared = function->shared(); |
2086 if (object->IsJSFunction()) { | 2099 if (shared != *target && shared->script() == target->script() && |
2087 closure = JSFunction::cast(object); | 2100 shared->start_position_and_type() == |
2088 shared = closure->shared(); | 2101 target->start_position_and_type()) { |
2089 } else if (object->IsSharedFunctionInfo()) { | 2102 function->set_shared(*target); |
2090 shared = SharedFunctionInfo::cast(object); | |
2091 if (!shared->allows_lazy_compilation_without_context()) continue; | |
2092 } else { | |
2093 continue; | |
2094 } | |
2095 if (shared->script() == *script) finder.NewCandidate(shared, closure); | |
2096 } | |
2097 closure = finder.ResultClosure(); | |
2098 shared = finder.Result(); | |
2099 } | |
2100 if (closure == NULL ? !CompileToRevealInnerFunctions(shared) | |
2101 : !CompileToRevealInnerFunctions(closure)) { | |
2102 break; | |
2103 } | 2103 } |
2104 } | 2104 } |
2105 return isolate_->factory()->undefined_value(); | 2105 |
| 2106 return target; |
2106 } | 2107 } |
2107 | 2108 |
2108 | 2109 |
2109 // Ensures the debug information is present for shared. | 2110 // Ensures the debug information is present for shared. |
2110 bool Debug::EnsureDebugInfo(Handle<SharedFunctionInfo> shared, | 2111 bool Debug::EnsureDebugInfo(Handle<SharedFunctionInfo> shared, |
2111 Handle<JSFunction> function) { | 2112 Handle<JSFunction> function) { |
2112 Isolate* isolate = shared->GetIsolate(); | 2113 Isolate* isolate = shared->GetIsolate(); |
2113 | 2114 |
2114 // Return if we already have the debug info for shared. | 2115 // Return if we already have the debug info for shared. |
2115 if (HasDebugInfo(shared)) { | 2116 if (HasDebugInfo(shared)) { |
(...skipping 1270 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3386 } | 3387 } |
3387 | 3388 |
3388 | 3389 |
3389 void LockingCommandMessageQueue::Clear() { | 3390 void LockingCommandMessageQueue::Clear() { |
3390 base::LockGuard<base::Mutex> lock_guard(&mutex_); | 3391 base::LockGuard<base::Mutex> lock_guard(&mutex_); |
3391 queue_.Clear(); | 3392 queue_.Clear(); |
3392 } | 3393 } |
3393 | 3394 |
3394 } // namespace internal | 3395 } // namespace internal |
3395 } // namespace v8 | 3396 } // namespace v8 |
OLD | NEW |