OLD | NEW |
1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 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/compiler-dispatcher/compiler-dispatcher-job.h" | 5 #include "src/compiler-dispatcher/compiler-dispatcher-job.h" |
6 | 6 |
7 #include "src/assert-scope.h" | 7 #include "src/assert-scope.h" |
8 #include "src/compilation-info.h" | 8 #include "src/compilation-info.h" |
9 #include "src/compiler-dispatcher/compiler-dispatcher-tracer.h" | 9 #include "src/compiler-dispatcher/compiler-dispatcher-tracer.h" |
10 #include "src/compiler.h" | 10 #include "src/compiler.h" |
| 11 #include "src/flags.h" |
11 #include "src/global-handles.h" | 12 #include "src/global-handles.h" |
12 #include "src/isolate.h" | 13 #include "src/isolate.h" |
13 #include "src/objects-inl.h" | 14 #include "src/objects-inl.h" |
14 #include "src/parsing/parse-info.h" | 15 #include "src/parsing/parse-info.h" |
15 #include "src/parsing/parser.h" | 16 #include "src/parsing/parser.h" |
16 #include "src/parsing/scanner-character-streams.h" | 17 #include "src/parsing/scanner-character-streams.h" |
17 #include "src/unicode-cache.h" | 18 #include "src/unicode-cache.h" |
| 19 #include "src/utils.h" |
18 #include "src/zone/zone.h" | 20 #include "src/zone/zone.h" |
19 | 21 |
20 namespace v8 { | 22 namespace v8 { |
21 namespace internal { | 23 namespace internal { |
22 | 24 |
23 CompilerDispatcherJob::CompilerDispatcherJob(Isolate* isolate, | 25 CompilerDispatcherJob::CompilerDispatcherJob(Isolate* isolate, |
24 CompilerDispatcherTracer* tracer, | 26 CompilerDispatcherTracer* tracer, |
25 Handle<SharedFunctionInfo> shared, | 27 Handle<SharedFunctionInfo> shared, |
26 size_t max_stack_size) | 28 size_t max_stack_size) |
27 : isolate_(isolate), | 29 : isolate_(isolate), |
28 tracer_(tracer), | 30 tracer_(tracer), |
29 shared_(Handle<SharedFunctionInfo>::cast( | 31 shared_(Handle<SharedFunctionInfo>::cast( |
30 isolate_->global_handles()->Create(*shared))), | 32 isolate_->global_handles()->Create(*shared))), |
31 max_stack_size_(max_stack_size), | 33 max_stack_size_(max_stack_size), |
32 can_compile_on_background_thread_(false) { | 34 can_compile_on_background_thread_(false), |
| 35 trace_compiler_dispatcher_jobs_(FLAG_trace_compiler_dispatcher_jobs) { |
33 HandleScope scope(isolate_); | 36 HandleScope scope(isolate_); |
34 DCHECK(!shared_->outer_scope_info()->IsTheHole(isolate_)); | 37 DCHECK(!shared_->outer_scope_info()->IsTheHole(isolate_)); |
35 Handle<Script> script(Script::cast(shared_->script()), isolate_); | 38 Handle<Script> script(Script::cast(shared_->script()), isolate_); |
36 Handle<String> source(String::cast(script->source()), isolate_); | 39 Handle<String> source(String::cast(script->source()), isolate_); |
37 can_parse_on_background_thread_ = | 40 can_parse_on_background_thread_ = |
38 source->IsExternalTwoByteString() || source->IsExternalOneByteString(); | 41 source->IsExternalTwoByteString() || source->IsExternalOneByteString(); |
| 42 if (trace_compiler_dispatcher_jobs_) { |
| 43 PrintF("CompilerDispatcherJob[%p] created for ", static_cast<void*>(this)); |
| 44 shared_->ShortPrint(); |
| 45 PrintF("\n"); |
| 46 } |
39 } | 47 } |
40 | 48 |
41 CompilerDispatcherJob::~CompilerDispatcherJob() { | 49 CompilerDispatcherJob::~CompilerDispatcherJob() { |
42 DCHECK(ThreadId::Current().Equals(isolate_->thread_id())); | 50 DCHECK(ThreadId::Current().Equals(isolate_->thread_id())); |
43 DCHECK(status_ == CompileJobStatus::kInitial || | 51 DCHECK(status_ == CompileJobStatus::kInitial || |
44 status_ == CompileJobStatus::kDone); | 52 status_ == CompileJobStatus::kDone); |
45 i::GlobalHandles::Destroy(Handle<Object>::cast(shared_).location()); | 53 i::GlobalHandles::Destroy(Handle<Object>::cast(shared_).location()); |
46 } | 54 } |
47 | 55 |
48 bool CompilerDispatcherJob::IsAssociatedWith( | 56 bool CompilerDispatcherJob::IsAssociatedWith( |
49 Handle<SharedFunctionInfo> shared) const { | 57 Handle<SharedFunctionInfo> shared) const { |
50 return *shared_ == *shared; | 58 return *shared_ == *shared; |
51 } | 59 } |
52 | 60 |
53 void CompilerDispatcherJob::PrepareToParseOnMainThread() { | 61 void CompilerDispatcherJob::PrepareToParseOnMainThread() { |
54 DCHECK(ThreadId::Current().Equals(isolate_->thread_id())); | 62 DCHECK(ThreadId::Current().Equals(isolate_->thread_id())); |
55 DCHECK(status() == CompileJobStatus::kInitial); | 63 DCHECK(status() == CompileJobStatus::kInitial); |
56 COMPILER_DISPATCHER_TRACE_SCOPE(tracer_, kPrepareToParse); | 64 COMPILER_DISPATCHER_TRACE_SCOPE(tracer_, kPrepareToParse); |
| 65 if (trace_compiler_dispatcher_jobs_) { |
| 66 PrintF("CompilerDispatcherJob[%p]: Preparing to parse\n", |
| 67 static_cast<void*>(this)); |
| 68 } |
57 HandleScope scope(isolate_); | 69 HandleScope scope(isolate_); |
58 unicode_cache_.reset(new UnicodeCache()); | 70 unicode_cache_.reset(new UnicodeCache()); |
59 zone_.reset(new Zone(isolate_->allocator(), ZONE_NAME)); | 71 zone_.reset(new Zone(isolate_->allocator(), ZONE_NAME)); |
60 Handle<Script> script(Script::cast(shared_->script()), isolate_); | 72 Handle<Script> script(Script::cast(shared_->script()), isolate_); |
61 DCHECK(script->type() != Script::TYPE_NATIVE); | 73 DCHECK(script->type() != Script::TYPE_NATIVE); |
62 | 74 |
63 Handle<String> source(String::cast(script->source()), isolate_); | 75 Handle<String> source(String::cast(script->source()), isolate_); |
64 if (source->IsExternalTwoByteString() || source->IsExternalOneByteString()) { | 76 if (source->IsExternalTwoByteString() || source->IsExternalOneByteString()) { |
65 character_stream_.reset(ScannerStream::For( | 77 character_stream_.reset(ScannerStream::For( |
66 source, shared_->start_position(), shared_->end_position())); | 78 source, shared_->start_position(), shared_->end_position())); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
98 status_ = CompileJobStatus::kReadyToParse; | 110 status_ = CompileJobStatus::kReadyToParse; |
99 } | 111 } |
100 | 112 |
101 void CompilerDispatcherJob::Parse() { | 113 void CompilerDispatcherJob::Parse() { |
102 DCHECK(can_parse_on_background_thread_ || | 114 DCHECK(can_parse_on_background_thread_ || |
103 ThreadId::Current().Equals(isolate_->thread_id())); | 115 ThreadId::Current().Equals(isolate_->thread_id())); |
104 DCHECK(status() == CompileJobStatus::kReadyToParse); | 116 DCHECK(status() == CompileJobStatus::kReadyToParse); |
105 COMPILER_DISPATCHER_TRACE_SCOPE_WITH_NUM( | 117 COMPILER_DISPATCHER_TRACE_SCOPE_WITH_NUM( |
106 tracer_, kParse, | 118 tracer_, kParse, |
107 parse_info_->end_position() - parse_info_->start_position()); | 119 parse_info_->end_position() - parse_info_->start_position()); |
| 120 if (trace_compiler_dispatcher_jobs_) { |
| 121 PrintF("CompilerDispatcherJob[%p]: Parsing\n", static_cast<void*>(this)); |
| 122 } |
108 | 123 |
109 DisallowHeapAllocation no_allocation; | 124 DisallowHeapAllocation no_allocation; |
110 DisallowHandleAllocation no_handles; | 125 DisallowHandleAllocation no_handles; |
111 std::unique_ptr<DisallowHandleDereference> no_deref; | 126 std::unique_ptr<DisallowHandleDereference> no_deref; |
112 // If we can't parse on a background thread, we need to be able to deref the | 127 // If we can't parse on a background thread, we need to be able to deref the |
113 // source string. | 128 // source string. |
114 if (can_parse_on_background_thread_) { | 129 if (can_parse_on_background_thread_) { |
115 no_deref.reset(new DisallowHandleDereference()); | 130 no_deref.reset(new DisallowHandleDereference()); |
116 } | 131 } |
117 | 132 |
118 // Nullify the Isolate temporarily so that the parser doesn't accidentally | 133 // Nullify the Isolate temporarily so that the parser doesn't accidentally |
119 // use it. | 134 // use it. |
120 parse_info_->set_isolate(nullptr); | 135 parse_info_->set_isolate(nullptr); |
121 | 136 |
122 uintptr_t stack_limit = GetCurrentStackPosition() - max_stack_size_ * KB; | 137 uintptr_t stack_limit = GetCurrentStackPosition() - max_stack_size_ * KB; |
123 | 138 |
124 parser_->set_stack_limit(stack_limit); | 139 parser_->set_stack_limit(stack_limit); |
125 parser_->ParseOnBackground(parse_info_.get()); | 140 parser_->ParseOnBackground(parse_info_.get()); |
126 | 141 |
127 parse_info_->set_isolate(isolate_); | 142 parse_info_->set_isolate(isolate_); |
128 | 143 |
129 status_ = CompileJobStatus::kParsed; | 144 status_ = CompileJobStatus::kParsed; |
130 } | 145 } |
131 | 146 |
132 bool CompilerDispatcherJob::FinalizeParsingOnMainThread() { | 147 bool CompilerDispatcherJob::FinalizeParsingOnMainThread() { |
133 DCHECK(ThreadId::Current().Equals(isolate_->thread_id())); | 148 DCHECK(ThreadId::Current().Equals(isolate_->thread_id())); |
134 DCHECK(status() == CompileJobStatus::kParsed); | 149 DCHECK(status() == CompileJobStatus::kParsed); |
135 COMPILER_DISPATCHER_TRACE_SCOPE(tracer_, kFinalizeParsing); | 150 COMPILER_DISPATCHER_TRACE_SCOPE(tracer_, kFinalizeParsing); |
| 151 if (trace_compiler_dispatcher_jobs_) { |
| 152 PrintF("CompilerDispatcherJob[%p]: Finalizing parsing\n", |
| 153 static_cast<void*>(this)); |
| 154 } |
136 | 155 |
137 if (!source_.is_null()) { | 156 if (!source_.is_null()) { |
138 i::GlobalHandles::Destroy(Handle<Object>::cast(source_).location()); | 157 i::GlobalHandles::Destroy(Handle<Object>::cast(source_).location()); |
139 source_ = Handle<String>::null(); | 158 source_ = Handle<String>::null(); |
140 } | 159 } |
141 | 160 |
142 if (parse_info_->literal() == nullptr) { | 161 if (parse_info_->literal() == nullptr) { |
143 status_ = CompileJobStatus::kFailed; | 162 status_ = CompileJobStatus::kFailed; |
144 } else { | 163 } else { |
145 status_ = CompileJobStatus::kReadyToAnalyse; | 164 status_ = CompileJobStatus::kReadyToAnalyse; |
(...skipping 24 matching lines...) Expand all Loading... |
170 } | 189 } |
171 handles_from_parsing_.reset(scope.Detach()); | 190 handles_from_parsing_.reset(scope.Detach()); |
172 | 191 |
173 return status_ != CompileJobStatus::kFailed; | 192 return status_ != CompileJobStatus::kFailed; |
174 } | 193 } |
175 | 194 |
176 bool CompilerDispatcherJob::PrepareToCompileOnMainThread() { | 195 bool CompilerDispatcherJob::PrepareToCompileOnMainThread() { |
177 DCHECK(ThreadId::Current().Equals(isolate_->thread_id())); | 196 DCHECK(ThreadId::Current().Equals(isolate_->thread_id())); |
178 DCHECK(status() == CompileJobStatus::kReadyToAnalyse); | 197 DCHECK(status() == CompileJobStatus::kReadyToAnalyse); |
179 COMPILER_DISPATCHER_TRACE_SCOPE(tracer_, kPrepareToCompile); | 198 COMPILER_DISPATCHER_TRACE_SCOPE(tracer_, kPrepareToCompile); |
| 199 if (trace_compiler_dispatcher_jobs_) { |
| 200 PrintF("CompilerDispatcherJob[%p]: Preparing to compile\n", |
| 201 static_cast<void*>(this)); |
| 202 } |
180 | 203 |
181 compile_info_.reset( | 204 compile_info_.reset( |
182 new CompilationInfo(parse_info_.get(), Handle<JSFunction>::null())); | 205 new CompilationInfo(parse_info_.get(), Handle<JSFunction>::null())); |
183 | 206 |
184 DeferredHandleScope scope(isolate_); | 207 DeferredHandleScope scope(isolate_); |
185 if (Compiler::Analyze(parse_info_.get())) { | 208 if (Compiler::Analyze(parse_info_.get())) { |
186 compile_job_.reset(Compiler::PrepareUnoptimizedCompilationJob( | 209 compile_job_.reset(Compiler::PrepareUnoptimizedCompilationJob( |
187 compile_info_.get(), LazyCompilationMode::kAlways)); | 210 compile_info_.get(), LazyCompilationMode::kAlways)); |
188 } | 211 } |
189 compile_info_->set_deferred_handles(scope.Detach()); | 212 compile_info_->set_deferred_handles(scope.Detach()); |
190 | 213 |
191 if (!compile_job_.get()) { | 214 if (!compile_job_.get()) { |
192 if (!isolate_->has_pending_exception()) isolate_->StackOverflow(); | 215 if (!isolate_->has_pending_exception()) isolate_->StackOverflow(); |
193 status_ = CompileJobStatus::kFailed; | 216 status_ = CompileJobStatus::kFailed; |
194 return false; | 217 return false; |
195 } | 218 } |
196 | 219 |
197 can_compile_on_background_thread_ = | 220 can_compile_on_background_thread_ = |
198 compile_job_->can_execute_on_background_thread(); | 221 compile_job_->can_execute_on_background_thread(); |
199 status_ = CompileJobStatus::kReadyToCompile; | 222 status_ = CompileJobStatus::kReadyToCompile; |
200 return true; | 223 return true; |
201 } | 224 } |
202 | 225 |
203 void CompilerDispatcherJob::Compile() { | 226 void CompilerDispatcherJob::Compile() { |
204 DCHECK(status() == CompileJobStatus::kReadyToCompile); | 227 DCHECK(status() == CompileJobStatus::kReadyToCompile); |
205 DCHECK(can_compile_on_background_thread_ || | 228 DCHECK(can_compile_on_background_thread_ || |
206 ThreadId::Current().Equals(isolate_->thread_id())); | 229 ThreadId::Current().Equals(isolate_->thread_id())); |
207 COMPILER_DISPATCHER_TRACE_SCOPE_WITH_NUM( | 230 COMPILER_DISPATCHER_TRACE_SCOPE_WITH_NUM( |
208 tracer_, kCompile, parse_info_->literal()->ast_node_count()); | 231 tracer_, kCompile, parse_info_->literal()->ast_node_count()); |
| 232 if (trace_compiler_dispatcher_jobs_) { |
| 233 PrintF("CompilerDispatcherJob[%p]: Compiling\n", static_cast<void*>(this)); |
| 234 } |
209 | 235 |
210 // Disallowing of handle dereference and heap access dealt with in | 236 // Disallowing of handle dereference and heap access dealt with in |
211 // CompilationJob::ExecuteJob. | 237 // CompilationJob::ExecuteJob. |
212 | 238 |
213 uintptr_t stack_limit = GetCurrentStackPosition() - max_stack_size_ * KB; | 239 uintptr_t stack_limit = GetCurrentStackPosition() - max_stack_size_ * KB; |
214 compile_job_->set_stack_limit(stack_limit); | 240 compile_job_->set_stack_limit(stack_limit); |
215 | 241 |
216 CompilationJob::Status status = compile_job_->ExecuteJob(); | 242 CompilationJob::Status status = compile_job_->ExecuteJob(); |
217 USE(status); | 243 USE(status); |
218 | 244 |
219 // Always transition to kCompiled - errors will be reported by | 245 // Always transition to kCompiled - errors will be reported by |
220 // FinalizeCompilingOnMainThread. | 246 // FinalizeCompilingOnMainThread. |
221 status_ = CompileJobStatus::kCompiled; | 247 status_ = CompileJobStatus::kCompiled; |
222 } | 248 } |
223 | 249 |
224 bool CompilerDispatcherJob::FinalizeCompilingOnMainThread() { | 250 bool CompilerDispatcherJob::FinalizeCompilingOnMainThread() { |
225 DCHECK(ThreadId::Current().Equals(isolate_->thread_id())); | 251 DCHECK(ThreadId::Current().Equals(isolate_->thread_id())); |
226 DCHECK(status() == CompileJobStatus::kCompiled); | 252 DCHECK(status() == CompileJobStatus::kCompiled); |
227 COMPILER_DISPATCHER_TRACE_SCOPE(tracer_, kFinalizeCompiling); | 253 COMPILER_DISPATCHER_TRACE_SCOPE(tracer_, kFinalizeCompiling); |
| 254 if (trace_compiler_dispatcher_jobs_) { |
| 255 PrintF("CompilerDispatcherJob[%p]: Finalizing compiling\n", |
| 256 static_cast<void*>(this)); |
| 257 } |
228 | 258 |
229 if (compile_job_->state() == CompilationJob::State::kFailed || | 259 if (compile_job_->state() == CompilationJob::State::kFailed || |
230 !Compiler::FinalizeCompilationJob(compile_job_.release())) { | 260 !Compiler::FinalizeCompilationJob(compile_job_.release())) { |
231 if (!isolate_->has_pending_exception()) isolate_->StackOverflow(); | 261 if (!isolate_->has_pending_exception()) isolate_->StackOverflow(); |
232 status_ = CompileJobStatus::kFailed; | 262 status_ = CompileJobStatus::kFailed; |
233 return false; | 263 return false; |
234 } | 264 } |
235 | 265 |
236 zone_.reset(); | 266 zone_.reset(); |
237 parse_info_.reset(); | 267 parse_info_.reset(); |
238 compile_info_.reset(); | 268 compile_info_.reset(); |
239 compile_job_.reset(); | 269 compile_job_.reset(); |
240 handles_from_parsing_.reset(); | 270 handles_from_parsing_.reset(); |
241 | 271 |
242 status_ = CompileJobStatus::kDone; | 272 status_ = CompileJobStatus::kDone; |
243 return true; | 273 return true; |
244 } | 274 } |
245 | 275 |
246 void CompilerDispatcherJob::ResetOnMainThread() { | 276 void CompilerDispatcherJob::ResetOnMainThread() { |
247 DCHECK(ThreadId::Current().Equals(isolate_->thread_id())); | 277 DCHECK(ThreadId::Current().Equals(isolate_->thread_id())); |
248 | 278 |
| 279 if (trace_compiler_dispatcher_jobs_) { |
| 280 PrintF("CompilerDispatcherJob[%p]: Resetting\n", static_cast<void*>(this)); |
| 281 } |
| 282 |
249 parser_.reset(); | 283 parser_.reset(); |
250 unicode_cache_.reset(); | 284 unicode_cache_.reset(); |
251 character_stream_.reset(); | 285 character_stream_.reset(); |
252 parse_info_.reset(); | 286 parse_info_.reset(); |
253 zone_.reset(); | 287 zone_.reset(); |
254 handles_from_parsing_.reset(); | 288 handles_from_parsing_.reset(); |
255 compile_info_.reset(); | 289 compile_info_.reset(); |
256 compile_job_.reset(); | 290 compile_job_.reset(); |
257 | 291 |
258 if (!source_.is_null()) { | 292 if (!source_.is_null()) { |
(...skipping 28 matching lines...) Expand all Loading... |
287 | 321 |
288 case CompileJobStatus::kFailed: | 322 case CompileJobStatus::kFailed: |
289 case CompileJobStatus::kDone: | 323 case CompileJobStatus::kDone: |
290 return 0.0; | 324 return 0.0; |
291 } | 325 } |
292 | 326 |
293 UNREACHABLE(); | 327 UNREACHABLE(); |
294 return 0.0; | 328 return 0.0; |
295 } | 329 } |
296 | 330 |
| 331 void CompilerDispatcherJob::ShortPrint() { |
| 332 DCHECK(ThreadId::Current().Equals(isolate_->thread_id())); |
| 333 shared_->ShortPrint(); |
| 334 } |
| 335 |
297 } // namespace internal | 336 } // namespace internal |
298 } // namespace v8 | 337 } // namespace v8 |
OLD | NEW |