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/flags.h" |
12 #include "src/global-handles.h" | 12 #include "src/global-handles.h" |
13 #include "src/isolate.h" | 13 #include "src/isolate.h" |
14 #include "src/objects-inl.h" | 14 #include "src/objects-inl.h" |
15 #include "src/parsing/parse-info.h" | 15 #include "src/parsing/parse-info.h" |
16 #include "src/parsing/parser.h" | 16 #include "src/parsing/parser.h" |
17 #include "src/parsing/scanner-character-streams.h" | 17 #include "src/parsing/scanner-character-streams.h" |
18 #include "src/unicode-cache.h" | 18 #include "src/unicode-cache.h" |
19 #include "src/utils.h" | 19 #include "src/utils.h" |
20 #include "src/zone/zone.h" | 20 #include "src/zone/zone.h" |
21 | 21 |
22 namespace v8 { | 22 namespace v8 { |
23 namespace internal { | 23 namespace internal { |
24 | 24 |
25 namespace { | |
26 | |
27 class OneByteWrapper : public v8::String::ExternalOneByteStringResource { | |
28 public: | |
29 OneByteWrapper(const void* data, int length) : data_(data), length_(length) {} | |
30 ~OneByteWrapper() override = default; | |
31 | |
32 const char* data() const override { | |
33 return reinterpret_cast<const char*>(data_); | |
34 } | |
35 | |
36 size_t length() const override { return static_cast<size_t>(length_); } | |
37 | |
38 private: | |
39 const void* data_; | |
40 int length_; | |
41 | |
42 DISALLOW_COPY_AND_ASSIGN(OneByteWrapper); | |
43 }; | |
44 | |
45 class TwoByteWrapper : public v8::String::ExternalStringResource { | |
46 public: | |
47 TwoByteWrapper(const void* data, int length) : data_(data), length_(length) {} | |
48 ~TwoByteWrapper() override = default; | |
49 | |
50 const uint16_t* data() const override { | |
51 return reinterpret_cast<const uint16_t*>(data_); | |
52 } | |
53 | |
54 size_t length() const override { return static_cast<size_t>(length_); } | |
55 | |
56 private: | |
57 const void* data_; | |
58 int length_; | |
59 | |
60 DISALLOW_COPY_AND_ASSIGN(TwoByteWrapper); | |
61 }; | |
62 | |
63 } // namespace | |
64 | |
25 CompilerDispatcherJob::CompilerDispatcherJob(Isolate* isolate, | 65 CompilerDispatcherJob::CompilerDispatcherJob(Isolate* isolate, |
26 CompilerDispatcherTracer* tracer, | 66 CompilerDispatcherTracer* tracer, |
27 Handle<SharedFunctionInfo> shared, | 67 Handle<SharedFunctionInfo> shared, |
28 size_t max_stack_size) | 68 size_t max_stack_size) |
29 : isolate_(isolate), | 69 : isolate_(isolate), |
30 tracer_(tracer), | 70 tracer_(tracer), |
31 shared_(Handle<SharedFunctionInfo>::cast( | 71 shared_(Handle<SharedFunctionInfo>::cast( |
32 isolate_->global_handles()->Create(*shared))), | 72 isolate_->global_handles()->Create(*shared))), |
33 max_stack_size_(max_stack_size), | 73 max_stack_size_(max_stack_size), |
34 can_compile_on_background_thread_(false), | |
35 trace_compiler_dispatcher_jobs_(FLAG_trace_compiler_dispatcher_jobs) { | 74 trace_compiler_dispatcher_jobs_(FLAG_trace_compiler_dispatcher_jobs) { |
36 HandleScope scope(isolate_); | 75 HandleScope scope(isolate_); |
37 DCHECK(!shared_->outer_scope_info()->IsTheHole(isolate_)); | 76 DCHECK(!shared_->outer_scope_info()->IsTheHole(isolate_)); |
38 Handle<Script> script(Script::cast(shared_->script()), isolate_); | 77 Handle<Script> script(Script::cast(shared_->script()), isolate_); |
39 Handle<String> source(String::cast(script->source()), isolate_); | 78 Handle<String> source(String::cast(script->source()), isolate_); |
40 can_parse_on_background_thread_ = | |
41 source->IsExternalTwoByteString() || source->IsExternalOneByteString(); | |
42 if (trace_compiler_dispatcher_jobs_) { | 79 if (trace_compiler_dispatcher_jobs_) { |
43 PrintF("CompilerDispatcherJob[%p] created for ", static_cast<void*>(this)); | 80 PrintF("CompilerDispatcherJob[%p] created for ", static_cast<void*>(this)); |
44 shared_->ShortPrint(); | 81 shared_->ShortPrint(); |
45 PrintF("\n"); | 82 PrintF("\n"); |
46 } | 83 } |
47 } | 84 } |
48 | 85 |
49 CompilerDispatcherJob::~CompilerDispatcherJob() { | 86 CompilerDispatcherJob::~CompilerDispatcherJob() { |
50 DCHECK(ThreadId::Current().Equals(isolate_->thread_id())); | 87 DCHECK(ThreadId::Current().Equals(isolate_->thread_id())); |
51 DCHECK(status_ == CompileJobStatus::kInitial || | 88 DCHECK(status_ == CompileJobStatus::kInitial || |
(...skipping 18 matching lines...) Expand all Loading... | |
70 unicode_cache_.reset(new UnicodeCache()); | 107 unicode_cache_.reset(new UnicodeCache()); |
71 zone_.reset(new Zone(isolate_->allocator(), ZONE_NAME)); | 108 zone_.reset(new Zone(isolate_->allocator(), ZONE_NAME)); |
72 Handle<Script> script(Script::cast(shared_->script()), isolate_); | 109 Handle<Script> script(Script::cast(shared_->script()), isolate_); |
73 DCHECK(script->type() != Script::TYPE_NATIVE); | 110 DCHECK(script->type() != Script::TYPE_NATIVE); |
74 | 111 |
75 Handle<String> source(String::cast(script->source()), isolate_); | 112 Handle<String> source(String::cast(script->source()), isolate_); |
76 if (source->IsExternalTwoByteString() || source->IsExternalOneByteString()) { | 113 if (source->IsExternalTwoByteString() || source->IsExternalOneByteString()) { |
77 character_stream_.reset(ScannerStream::For( | 114 character_stream_.reset(ScannerStream::For( |
78 source, shared_->start_position(), shared_->end_position())); | 115 source, shared_->start_position(), shared_->end_position())); |
79 } else { | 116 } else { |
80 source = String::Flatten(source); | 117 source = String::Flatten(source); |
vogelheim
2017/01/13 15:20:22
[all below:]
I'm vaguely uncomfortable with this
jochen (gone - plz use gerrit)
2017/01/13 16:14:40
Right. I'm also trying to reduce the impact by jus
| |
81 // Have to globalize the reference here, so it survives between function | 118 const void* data; |
82 // calls. | 119 int offset = 0; |
83 source_ = Handle<String>::cast(isolate_->global_handles()->Create(*source)); | 120 int length = source->length(); |
84 character_stream_.reset(ScannerStream::For( | 121 |
85 source_, shared_->start_position(), shared_->end_position())); | 122 // Objects in lo_space don't move, so we can just read the contents from |
123 // any thread. | |
124 if (isolate_->heap()->lo_space()->Contains(*source)) { | |
jochen (gone - plz use gerrit)
2017/01/13 13:21:39
Hannes, ptal at this if () {} block: here I'm depe
Hannes Payer (out of office)
2017/01/13 14:01:04
Correct, LO don't move.
rmcilroy
2017/01/13 15:56:22
Is it common for the source to be in the LO space?
jochen (gone - plz use gerrit)
2017/01/13 16:14:40
no, I expect most cases to be external strings, or
| |
125 // We need to globalize the handle to the flattened string here, in | |
126 // case it's not referenced from anywhere else. | |
127 source_ = | |
128 Handle<String>::cast(isolate_->global_handles()->Create(*source)); | |
129 DisallowHeapAllocation no_allocation; | |
130 String::FlatContent content = source->GetFlatContent(); | |
131 DCHECK(content.IsFlat()); | |
132 data = | |
133 content.IsOneByte() | |
134 ? reinterpret_cast<const void*>(content.ToOneByteVector().start()) | |
135 : reinterpret_cast<const void*>(content.ToUC16Vector().start()); | |
136 } else { | |
137 // Otherwise, create a copy of the part of the string we'll parse in the | |
138 // zone. | |
139 length = (shared_->end_position() - shared_->start_position()); | |
140 offset = shared_->start_position(); | |
141 | |
142 int byte_len = length * (source->IsOneByteRepresentation() ? 1 : 2); | |
143 data = zone_->New(byte_len); | |
vogelheim
2017/01/13 15:20:22
Who will delete this?
As I see it, it get pointed
jochen (gone - plz use gerrit)
2017/01/13 16:14:40
the zone_ will delete this
| |
144 | |
145 DisallowHeapAllocation no_allocation; | |
146 String::FlatContent content = source->GetFlatContent(); | |
147 DCHECK(content.IsFlat()); | |
148 if (content.IsOneByte()) { | |
149 MemCopy(const_cast<void*>(data), | |
150 &content.ToOneByteVector().at(shared_->start_position()), | |
151 byte_len); | |
152 } else { | |
153 MemCopy(const_cast<void*>(data), | |
154 &content.ToUC16Vector().at(shared_->start_position()), | |
155 byte_len); | |
156 } | |
157 } | |
158 Handle<String> wrapper; | |
159 if (source->IsOneByteRepresentation()) { | |
160 ExternalOneByteString::Resource* resource = | |
161 new OneByteWrapper(data, length); | |
162 source_wrapper_.reset(resource); | |
163 wrapper = isolate_->factory() | |
164 ->NewExternalStringFromOneByte(resource) | |
165 .ToHandleChecked(); | |
166 } else { | |
167 ExternalTwoByteString::Resource* resource = | |
168 new TwoByteWrapper(data, length); | |
169 source_wrapper_.reset(resource); | |
170 wrapper = isolate_->factory() | |
171 ->NewExternalStringFromTwoByte(resource) | |
172 .ToHandleChecked(); | |
173 } | |
174 wrapper_ = | |
175 Handle<String>::cast(isolate_->global_handles()->Create(*wrapper)); | |
176 | |
177 character_stream_.reset( | |
178 ScannerStream::For(wrapper_, shared_->start_position() - offset, | |
179 shared_->end_position() - offset)); | |
86 } | 180 } |
87 parse_info_.reset(new ParseInfo(zone_.get())); | 181 parse_info_.reset(new ParseInfo(zone_.get())); |
88 parse_info_->set_isolate(isolate_); | 182 parse_info_->set_isolate(isolate_); |
89 parse_info_->set_character_stream(character_stream_.get()); | 183 parse_info_->set_character_stream(character_stream_.get()); |
90 parse_info_->set_hash_seed(isolate_->heap()->HashSeed()); | 184 parse_info_->set_hash_seed(isolate_->heap()->HashSeed()); |
91 parse_info_->set_is_named_expression(shared_->is_named_expression()); | 185 parse_info_->set_is_named_expression(shared_->is_named_expression()); |
92 parse_info_->set_compiler_hints(shared_->compiler_hints()); | 186 parse_info_->set_compiler_hints(shared_->compiler_hints()); |
93 parse_info_->set_start_position(shared_->start_position()); | 187 parse_info_->set_start_position(shared_->start_position()); |
94 parse_info_->set_end_position(shared_->end_position()); | 188 parse_info_->set_end_position(shared_->end_position()); |
95 parse_info_->set_unicode_cache(unicode_cache_.get()); | 189 parse_info_->set_unicode_cache(unicode_cache_.get()); |
96 parse_info_->set_language_mode(shared_->language_mode()); | 190 parse_info_->set_language_mode(shared_->language_mode()); |
97 parse_info_->set_function_literal_id(shared_->function_literal_id()); | 191 parse_info_->set_function_literal_id(shared_->function_literal_id()); |
98 | 192 |
99 parser_.reset(new Parser(parse_info_.get())); | 193 parser_.reset(new Parser(parse_info_.get())); |
100 Handle<ScopeInfo> outer_scope_info( | 194 Handle<ScopeInfo> outer_scope_info( |
101 handle(ScopeInfo::cast(shared_->outer_scope_info()))); | 195 handle(ScopeInfo::cast(shared_->outer_scope_info()))); |
102 parser_->DeserializeScopeChain(parse_info_.get(), | 196 parser_->DeserializeScopeChain(parse_info_.get(), |
103 outer_scope_info->length() > 0 | 197 outer_scope_info->length() > 0 |
104 ? MaybeHandle<ScopeInfo>(outer_scope_info) | 198 ? MaybeHandle<ScopeInfo>(outer_scope_info) |
105 : MaybeHandle<ScopeInfo>()); | 199 : MaybeHandle<ScopeInfo>()); |
106 | 200 |
107 Handle<String> name(String::cast(shared_->name())); | 201 Handle<String> name(String::cast(shared_->name())); |
108 parse_info_->set_function_name( | 202 parse_info_->set_function_name( |
109 parse_info_->ast_value_factory()->GetString(name)); | 203 parse_info_->ast_value_factory()->GetString(name)); |
110 status_ = CompileJobStatus::kReadyToParse; | 204 status_ = CompileJobStatus::kReadyToParse; |
111 } | 205 } |
112 | 206 |
113 void CompilerDispatcherJob::Parse() { | 207 void CompilerDispatcherJob::Parse() { |
114 DCHECK(can_parse_on_background_thread_ || | |
115 ThreadId::Current().Equals(isolate_->thread_id())); | |
116 DCHECK(status() == CompileJobStatus::kReadyToParse); | 208 DCHECK(status() == CompileJobStatus::kReadyToParse); |
117 COMPILER_DISPATCHER_TRACE_SCOPE_WITH_NUM( | 209 COMPILER_DISPATCHER_TRACE_SCOPE_WITH_NUM( |
118 tracer_, kParse, | 210 tracer_, kParse, |
119 parse_info_->end_position() - parse_info_->start_position()); | 211 parse_info_->end_position() - parse_info_->start_position()); |
120 if (trace_compiler_dispatcher_jobs_) { | 212 if (trace_compiler_dispatcher_jobs_) { |
121 PrintF("CompilerDispatcherJob[%p]: Parsing\n", static_cast<void*>(this)); | 213 PrintF("CompilerDispatcherJob[%p]: Parsing\n", static_cast<void*>(this)); |
122 } | 214 } |
123 | 215 |
124 DisallowHeapAllocation no_allocation; | 216 DisallowHeapAllocation no_allocation; |
125 DisallowHandleAllocation no_handles; | 217 DisallowHandleAllocation no_handles; |
126 std::unique_ptr<DisallowHandleDereference> no_deref; | 218 DisallowHandleDereference no_deref; |
127 // If we can't parse on a background thread, we need to be able to deref the | |
128 // source string. | |
129 if (can_parse_on_background_thread_) { | |
130 no_deref.reset(new DisallowHandleDereference()); | |
131 } | |
132 | 219 |
133 // Nullify the Isolate temporarily so that the parser doesn't accidentally | 220 // Nullify the Isolate temporarily so that the parser doesn't accidentally |
134 // use it. | 221 // use it. |
135 parse_info_->set_isolate(nullptr); | 222 parse_info_->set_isolate(nullptr); |
136 | 223 |
137 uintptr_t stack_limit = GetCurrentStackPosition() - max_stack_size_ * KB; | 224 uintptr_t stack_limit = GetCurrentStackPosition() - max_stack_size_ * KB; |
138 | 225 |
139 parser_->set_stack_limit(stack_limit); | 226 parser_->set_stack_limit(stack_limit); |
140 parser_->ParseOnBackground(parse_info_.get()); | 227 parser_->ParseOnBackground(parse_info_.get()); |
141 | 228 |
142 parse_info_->set_isolate(isolate_); | 229 parse_info_->set_isolate(isolate_); |
143 | 230 |
144 status_ = CompileJobStatus::kParsed; | 231 status_ = CompileJobStatus::kParsed; |
145 } | 232 } |
146 | 233 |
147 bool CompilerDispatcherJob::FinalizeParsingOnMainThread() { | 234 bool CompilerDispatcherJob::FinalizeParsingOnMainThread() { |
148 DCHECK(ThreadId::Current().Equals(isolate_->thread_id())); | 235 DCHECK(ThreadId::Current().Equals(isolate_->thread_id())); |
149 DCHECK(status() == CompileJobStatus::kParsed); | 236 DCHECK(status() == CompileJobStatus::kParsed); |
150 COMPILER_DISPATCHER_TRACE_SCOPE(tracer_, kFinalizeParsing); | 237 COMPILER_DISPATCHER_TRACE_SCOPE(tracer_, kFinalizeParsing); |
151 if (trace_compiler_dispatcher_jobs_) { | 238 if (trace_compiler_dispatcher_jobs_) { |
152 PrintF("CompilerDispatcherJob[%p]: Finalizing parsing\n", | 239 PrintF("CompilerDispatcherJob[%p]: Finalizing parsing\n", |
153 static_cast<void*>(this)); | 240 static_cast<void*>(this)); |
154 } | 241 } |
155 | 242 |
156 if (!source_.is_null()) { | 243 if (!source_.is_null()) { |
157 i::GlobalHandles::Destroy(Handle<Object>::cast(source_).location()); | 244 i::GlobalHandles::Destroy(Handle<Object>::cast(source_).location()); |
158 source_ = Handle<String>::null(); | 245 source_ = Handle<String>::null(); |
159 } | 246 } |
247 if (!wrapper_.is_null()) { | |
248 i::GlobalHandles::Destroy(Handle<Object>::cast(wrapper_).location()); | |
249 wrapper_ = Handle<String>::null(); | |
250 } | |
160 | 251 |
161 if (parse_info_->literal() == nullptr) { | 252 if (parse_info_->literal() == nullptr) { |
162 status_ = CompileJobStatus::kFailed; | 253 status_ = CompileJobStatus::kFailed; |
163 } else { | 254 } else { |
164 status_ = CompileJobStatus::kReadyToAnalyse; | 255 status_ = CompileJobStatus::kReadyToAnalyse; |
165 } | 256 } |
166 | 257 |
167 DeferredHandleScope scope(isolate_); | 258 DeferredHandleScope scope(isolate_); |
168 { | 259 { |
169 Handle<Script> script(Script::cast(shared_->script()), isolate_); | 260 Handle<Script> script(Script::cast(shared_->script()), isolate_); |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
210 Compiler::PrepareUnoptimizedCompilationJob(compile_info_.get())); | 301 Compiler::PrepareUnoptimizedCompilationJob(compile_info_.get())); |
211 } | 302 } |
212 compile_info_->set_deferred_handles(scope.Detach()); | 303 compile_info_->set_deferred_handles(scope.Detach()); |
213 | 304 |
214 if (!compile_job_.get()) { | 305 if (!compile_job_.get()) { |
215 if (!isolate_->has_pending_exception()) isolate_->StackOverflow(); | 306 if (!isolate_->has_pending_exception()) isolate_->StackOverflow(); |
216 status_ = CompileJobStatus::kFailed; | 307 status_ = CompileJobStatus::kFailed; |
217 return false; | 308 return false; |
218 } | 309 } |
219 | 310 |
220 can_compile_on_background_thread_ = | 311 CHECK(compile_job_->can_execute_on_background_thread()); |
221 compile_job_->can_execute_on_background_thread(); | |
222 status_ = CompileJobStatus::kReadyToCompile; | 312 status_ = CompileJobStatus::kReadyToCompile; |
223 return true; | 313 return true; |
224 } | 314 } |
225 | 315 |
226 void CompilerDispatcherJob::Compile() { | 316 void CompilerDispatcherJob::Compile() { |
227 DCHECK(status() == CompileJobStatus::kReadyToCompile); | 317 DCHECK(status() == CompileJobStatus::kReadyToCompile); |
228 DCHECK(can_compile_on_background_thread_ || | |
229 ThreadId::Current().Equals(isolate_->thread_id())); | |
230 COMPILER_DISPATCHER_TRACE_SCOPE_WITH_NUM( | 318 COMPILER_DISPATCHER_TRACE_SCOPE_WITH_NUM( |
231 tracer_, kCompile, parse_info_->literal()->ast_node_count()); | 319 tracer_, kCompile, parse_info_->literal()->ast_node_count()); |
232 if (trace_compiler_dispatcher_jobs_) { | 320 if (trace_compiler_dispatcher_jobs_) { |
233 PrintF("CompilerDispatcherJob[%p]: Compiling\n", static_cast<void*>(this)); | 321 PrintF("CompilerDispatcherJob[%p]: Compiling\n", static_cast<void*>(this)); |
234 } | 322 } |
235 | 323 |
236 // Disallowing of handle dereference and heap access dealt with in | 324 // Disallowing of handle dereference and heap access dealt with in |
237 // CompilationJob::ExecuteJob. | 325 // CompilationJob::ExecuteJob. |
238 | 326 |
239 uintptr_t stack_limit = GetCurrentStackPosition() - max_stack_size_ * KB; | 327 uintptr_t stack_limit = GetCurrentStackPosition() - max_stack_size_ * KB; |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
286 parse_info_.reset(); | 374 parse_info_.reset(); |
287 handles_from_parsing_.reset(); | 375 handles_from_parsing_.reset(); |
288 compile_info_.reset(); | 376 compile_info_.reset(); |
289 compile_job_.reset(); | 377 compile_job_.reset(); |
290 zone_.reset(); | 378 zone_.reset(); |
291 | 379 |
292 if (!source_.is_null()) { | 380 if (!source_.is_null()) { |
293 i::GlobalHandles::Destroy(Handle<Object>::cast(source_).location()); | 381 i::GlobalHandles::Destroy(Handle<Object>::cast(source_).location()); |
294 source_ = Handle<String>::null(); | 382 source_ = Handle<String>::null(); |
295 } | 383 } |
384 if (!wrapper_.is_null()) { | |
385 i::GlobalHandles::Destroy(Handle<Object>::cast(wrapper_).location()); | |
386 wrapper_ = Handle<String>::null(); | |
387 } | |
296 | 388 |
297 status_ = CompileJobStatus::kInitial; | 389 status_ = CompileJobStatus::kInitial; |
298 } | 390 } |
299 | 391 |
300 double CompilerDispatcherJob::EstimateRuntimeOfNextStepInMs() const { | 392 double CompilerDispatcherJob::EstimateRuntimeOfNextStepInMs() const { |
301 switch (status_) { | 393 switch (status_) { |
302 case CompileJobStatus::kInitial: | 394 case CompileJobStatus::kInitial: |
303 return tracer_->EstimatePrepareToParseInMs(); | 395 return tracer_->EstimatePrepareToParseInMs(); |
304 | 396 |
305 case CompileJobStatus::kReadyToParse: | 397 case CompileJobStatus::kReadyToParse: |
(...skipping 22 matching lines...) Expand all Loading... | |
328 return 0.0; | 420 return 0.0; |
329 } | 421 } |
330 | 422 |
331 void CompilerDispatcherJob::ShortPrint() { | 423 void CompilerDispatcherJob::ShortPrint() { |
332 DCHECK(ThreadId::Current().Equals(isolate_->thread_id())); | 424 DCHECK(ThreadId::Current().Equals(isolate_->thread_id())); |
333 shared_->ShortPrint(); | 425 shared_->ShortPrint(); |
334 } | 426 } |
335 | 427 |
336 } // namespace internal | 428 } // namespace internal |
337 } // namespace v8 | 429 } // namespace v8 |
OLD | NEW |