Line data Source code
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
3 : // found in the LICENSE file.
4 :
5 : #include "src/compiler.h"
6 :
7 : #include <algorithm>
8 : #include <memory>
9 :
10 : #include "src/api-inl.h"
11 : #include "src/asmjs/asm-js.h"
12 : #include "src/assembler-inl.h"
13 : #include "src/ast/prettyprinter.h"
14 : #include "src/ast/scopes.h"
15 : #include "src/base/optional.h"
16 : #include "src/bootstrapper.h"
17 : #include "src/compilation-cache.h"
18 : #include "src/compiler-dispatcher/compiler-dispatcher.h"
19 : #include "src/compiler-dispatcher/optimizing-compile-dispatcher.h"
20 : #include "src/compiler/pipeline.h"
21 : #include "src/debug/debug.h"
22 : #include "src/debug/liveedit.h"
23 : #include "src/frames-inl.h"
24 : #include "src/globals.h"
25 : #include "src/heap/heap-inl.h"
26 : #include "src/interpreter/interpreter.h"
27 : #include "src/isolate-inl.h"
28 : #include "src/log-inl.h"
29 : #include "src/message-template.h"
30 : #include "src/objects/feedback-cell-inl.h"
31 : #include "src/objects/map.h"
32 : #include "src/optimized-compilation-info.h"
33 : #include "src/ostreams.h"
34 : #include "src/parsing/parse-info.h"
35 : #include "src/parsing/parser.h"
36 : #include "src/parsing/parsing.h"
37 : #include "src/parsing/rewriter.h"
38 : #include "src/parsing/scanner-character-streams.h"
39 : #include "src/runtime-profiler.h"
40 : #include "src/snapshot/code-serializer.h"
41 : #include "src/unoptimized-compilation-info.h"
42 : #include "src/vm-state-inl.h"
43 : #include "src/zone/zone-list-inl.h" // crbug.com/v8/8816
44 :
45 : namespace v8 {
46 : namespace internal {
47 :
48 : // A wrapper around a OptimizedCompilationInfo that detaches the Handles from
49 : // the underlying DeferredHandleScope and stores them in info_ on
50 : // destruction.
51 : class CompilationHandleScope final {
52 : public:
53 : explicit CompilationHandleScope(Isolate* isolate,
54 : OptimizedCompilationInfo* info)
55 6885 : : deferred_(isolate), info_(info) {}
56 6885 : ~CompilationHandleScope() { info_->set_deferred_handles(deferred_.Detach()); }
57 :
58 : private:
59 : DeferredHandleScope deferred_;
60 : OptimizedCompilationInfo* info_;
61 : };
62 :
63 : // Helper that times a scoped region and records the elapsed time.
64 : struct ScopedTimer {
65 : explicit ScopedTimer(base::TimeDelta* location) : location_(location) {
66 : DCHECK_NOT_NULL(location_);
67 : timer_.Start();
68 : }
69 :
70 : ~ScopedTimer() { *location_ += timer_.Elapsed(); }
71 :
72 : base::ElapsedTimer timer_;
73 : base::TimeDelta* location_;
74 : };
75 :
76 : namespace {
77 :
78 2555711 : void LogFunctionCompilation(CodeEventListener::LogEventsAndTags tag,
79 : Handle<SharedFunctionInfo> shared,
80 : Handle<Script> script,
81 : Handle<AbstractCode> abstract_code, bool optimizing,
82 : double time_taken_ms, Isolate* isolate) {
83 : DCHECK(!abstract_code.is_null());
84 : DCHECK(!abstract_code.is_identical_to(BUILTIN_CODE(isolate, CompileLazy)));
85 :
86 : // Log the code generation. If source information is available include
87 : // script name and line number. Check explicitly whether logging is
88 : // enabled as finding the line number is not free.
89 7666766 : if (!isolate->logger()->is_listening_to_code_events() &&
90 7665215 : !isolate->is_profiling() && !FLAG_log_function_events &&
91 : !isolate->code_event_dispatcher()->IsListeningToCodeEvents()) {
92 2555663 : return;
93 : }
94 :
95 1007 : int line_num = Script::GetLineNumber(script, shared->StartPosition()) + 1;
96 1007 : int column_num = Script::GetColumnNumber(script, shared->StartPosition()) + 1;
97 : String script_name = script->name()->IsString()
98 : ? String::cast(script->name())
99 2014 : : ReadOnlyRoots(isolate).empty_string();
100 : CodeEventListener::LogEventsAndTags log_tag =
101 : Logger::ToNativeByScript(tag, *script);
102 1007 : PROFILE(isolate, CodeCreateEvent(log_tag, *abstract_code, *shared,
103 : script_name, line_num, column_num));
104 1007 : if (!FLAG_log_function_events) return;
105 :
106 : DisallowHeapAllocation no_gc;
107 :
108 54 : std::string name = optimizing ? "optimize" : "compile";
109 54 : switch (tag) {
110 : case CodeEventListener::EVAL_TAG:
111 : name += "-eval";
112 : break;
113 : case CodeEventListener::SCRIPT_TAG:
114 : break;
115 : case CodeEventListener::LAZY_COMPILE_TAG:
116 : name += "-lazy";
117 : break;
118 : case CodeEventListener::FUNCTION_TAG:
119 : break;
120 : default:
121 0 : UNREACHABLE();
122 : }
123 :
124 270 : LOG(isolate, FunctionEvent(name.c_str(), script->id(), time_taken_ms,
125 : shared->StartPosition(), shared->EndPosition(),
126 : shared->DebugName()));
127 : }
128 :
129 1313374 : ScriptOriginOptions OriginOptionsForEval(Object script) {
130 1313374 : if (!script->IsScript()) return ScriptOriginOptions();
131 :
132 : const auto outer_origin_options = Script::cast(script)->origin_options();
133 : return ScriptOriginOptions(outer_origin_options.IsSharedCrossOrigin(),
134 1313374 : outer_origin_options.IsOpaque());
135 : }
136 :
137 : } // namespace
138 :
139 : // ----------------------------------------------------------------------------
140 : // Implementation of UnoptimizedCompilationJob
141 :
142 2120712 : CompilationJob::Status UnoptimizedCompilationJob::ExecuteJob() {
143 : DisallowHeapAccess no_heap_access;
144 : // Delegate to the underlying implementation.
145 : DCHECK_EQ(state(), State::kReadyToExecute);
146 2120712 : ScopedTimer t(&time_taken_to_execute_);
147 2120755 : return UpdateState(ExecuteJobImpl(), State::kReadyToFinalize);
148 : }
149 :
150 2095180 : CompilationJob::Status UnoptimizedCompilationJob::FinalizeJob(
151 : Handle<SharedFunctionInfo> shared_info, Isolate* isolate) {
152 : DCHECK_EQ(ThreadId::Current(), isolate->thread_id());
153 : DisallowCodeDependencyChange no_dependency_change;
154 4190373 : DisallowJavascriptExecution no_js(isolate);
155 :
156 : // Delegate to the underlying implementation.
157 : DCHECK_EQ(state(), State::kReadyToFinalize);
158 2095179 : ScopedTimer t(&time_taken_to_finalize_);
159 4190389 : return UpdateState(FinalizeJobImpl(shared_info, isolate), State::kSucceeded);
160 : }
161 :
162 2095169 : void UnoptimizedCompilationJob::RecordCompilationStats(Isolate* isolate) const {
163 : int code_size;
164 2095169 : if (compilation_info()->has_bytecode_array()) {
165 2092700 : code_size = compilation_info()->bytecode_array()->SizeIncludingMetadata();
166 : } else {
167 : DCHECK(compilation_info()->has_asm_wasm_data());
168 2469 : code_size = compilation_info()->asm_wasm_data()->Size();
169 : }
170 :
171 : Counters* counters = isolate->counters();
172 : // TODO(4280): Rename counters from "baseline" to "unoptimized" eventually.
173 2095176 : counters->total_baseline_code_size()->Increment(code_size);
174 2095172 : counters->total_baseline_compile_count()->Increment(1);
175 :
176 : // TODO(5203): Add timers for each phase of compilation.
177 : // Also add total time (there's now already timer_ on the base class).
178 2095174 : }
179 :
180 2095158 : void UnoptimizedCompilationJob::RecordFunctionCompilation(
181 : CodeEventListener::LogEventsAndTags tag, Handle<SharedFunctionInfo> shared,
182 : Isolate* isolate) const {
183 : Handle<AbstractCode> abstract_code;
184 2095158 : if (compilation_info()->has_bytecode_array()) {
185 : abstract_code =
186 2092689 : Handle<AbstractCode>::cast(compilation_info()->bytecode_array());
187 : } else {
188 : DCHECK(compilation_info()->has_asm_wasm_data());
189 : abstract_code =
190 2469 : Handle<AbstractCode>::cast(BUILTIN_CODE(isolate, InstantiateAsmJs));
191 : }
192 :
193 2095158 : double time_taken_ms = time_taken_to_execute_.InMillisecondsF() +
194 2095157 : time_taken_to_finalize_.InMillisecondsF();
195 :
196 : LogFunctionCompilation(tag, shared, parse_info()->script(), abstract_code,
197 2095167 : false, time_taken_ms, isolate);
198 2095171 : }
199 :
200 : // ----------------------------------------------------------------------------
201 : // Implementation of OptimizedCompilationJob
202 :
203 460854 : CompilationJob::Status OptimizedCompilationJob::PrepareJob(Isolate* isolate) {
204 : DCHECK_EQ(ThreadId::Current(), isolate->thread_id());
205 921708 : DisallowJavascriptExecution no_js(isolate);
206 :
207 460853 : if (FLAG_trace_opt && compilation_info()->IsOptimizing()) {
208 1344 : StdoutStream os;
209 2016 : os << "[compiling method " << Brief(*compilation_info()->closure())
210 1344 : << " using " << compiler_name_;
211 672 : if (compilation_info()->is_osr()) os << " OSR";
212 : os << "]" << std::endl;
213 : }
214 :
215 : // Delegate to the underlying implementation.
216 : DCHECK_EQ(state(), State::kReadyToPrepare);
217 460853 : ScopedTimer t(&time_taken_to_prepare_);
218 921704 : return UpdateState(PrepareJobImpl(isolate), State::kReadyToExecute);
219 : }
220 :
221 460787 : CompilationJob::Status OptimizedCompilationJob::ExecuteJob() {
222 : DisallowHeapAccess no_heap_access;
223 : // Delegate to the underlying implementation.
224 : DCHECK_EQ(state(), State::kReadyToExecute);
225 460787 : ScopedTimer t(&time_taken_to_execute_);
226 921574 : return UpdateState(ExecuteJobImpl(), State::kReadyToFinalize);
227 : }
228 :
229 460614 : CompilationJob::Status OptimizedCompilationJob::FinalizeJob(Isolate* isolate) {
230 : DCHECK_EQ(ThreadId::Current(), isolate->thread_id());
231 921231 : DisallowJavascriptExecution no_js(isolate);
232 :
233 : // Delegate to the underlying implementation.
234 : DCHECK_EQ(state(), State::kReadyToFinalize);
235 460613 : ScopedTimer t(&time_taken_to_finalize_);
236 921227 : return UpdateState(FinalizeJobImpl(isolate), State::kSucceeded);
237 : }
238 :
239 66 : CompilationJob::Status OptimizedCompilationJob::RetryOptimization(
240 : BailoutReason reason) {
241 : DCHECK(compilation_info_->IsOptimizing());
242 66 : compilation_info_->RetryOptimization(reason);
243 66 : return UpdateState(FAILED, State::kFailed);
244 : }
245 :
246 30 : CompilationJob::Status OptimizedCompilationJob::AbortOptimization(
247 : BailoutReason reason) {
248 : DCHECK(compilation_info_->IsOptimizing());
249 30 : compilation_info_->AbortOptimization(reason);
250 30 : return UpdateState(FAILED, State::kFailed);
251 : }
252 :
253 460551 : void OptimizedCompilationJob::RecordCompilationStats(CompilationMode mode,
254 : Isolate* isolate) const {
255 : DCHECK(compilation_info()->IsOptimizing());
256 : Handle<JSFunction> function = compilation_info()->closure();
257 460551 : double ms_creategraph = time_taken_to_prepare_.InMillisecondsF();
258 460551 : double ms_optimize = time_taken_to_execute_.InMillisecondsF();
259 460551 : double ms_codegen = time_taken_to_finalize_.InMillisecondsF();
260 460551 : if (FLAG_trace_opt) {
261 672 : PrintF("[optimizing ");
262 1344 : function->ShortPrint();
263 : PrintF(" - took %0.3f, %0.3f, %0.3f ms]\n", ms_creategraph, ms_optimize,
264 672 : ms_codegen);
265 : }
266 460550 : if (FLAG_trace_opt_stats) {
267 : static double compilation_time = 0.0;
268 : static int compiled_functions = 0;
269 : static int code_size = 0;
270 :
271 0 : compilation_time += (ms_creategraph + ms_optimize + ms_codegen);
272 0 : compiled_functions++;
273 0 : code_size += function->shared()->SourceSize();
274 : PrintF("Compiled: %d functions with %d byte source size in %fms.\n",
275 0 : compiled_functions, code_size, compilation_time);
276 : }
277 : // Don't record samples from machines without high-resolution timers,
278 : // as that can cause serious reporting issues. See the thread at
279 : // http://g/chrome-metrics-team/NwwJEyL8odU/discussion for more details.
280 460550 : if (base::TimeTicks::IsHighResolution()) {
281 : Counters* const counters = isolate->counters();
282 460548 : if (compilation_info()->is_osr()) {
283 4642 : counters->turbofan_osr_prepare()->AddSample(
284 9284 : static_cast<int>(time_taken_to_prepare_.InMicroseconds()));
285 4642 : counters->turbofan_osr_execute()->AddSample(
286 9284 : static_cast<int>(time_taken_to_execute_.InMicroseconds()));
287 4642 : counters->turbofan_osr_finalize()->AddSample(
288 9284 : static_cast<int>(time_taken_to_finalize_.InMicroseconds()));
289 4642 : counters->turbofan_osr_total_time()->AddSample(
290 9284 : static_cast<int>(ElapsedTime().InMicroseconds()));
291 : } else {
292 455907 : counters->turbofan_optimize_prepare()->AddSample(
293 911813 : static_cast<int>(time_taken_to_prepare_.InMicroseconds()));
294 455909 : counters->turbofan_optimize_execute()->AddSample(
295 911818 : static_cast<int>(time_taken_to_execute_.InMicroseconds()));
296 455909 : counters->turbofan_optimize_finalize()->AddSample(
297 911818 : static_cast<int>(time_taken_to_finalize_.InMicroseconds()));
298 455909 : counters->turbofan_optimize_total_time()->AddSample(
299 911818 : static_cast<int>(ElapsedTime().InMicroseconds()));
300 :
301 : // Compute foreground / background time.
302 455909 : base::TimeDelta time_background;
303 : base::TimeDelta time_foreground =
304 455909 : time_taken_to_prepare_ + time_taken_to_finalize_;
305 455909 : switch (mode) {
306 : case OptimizedCompilationJob::kConcurrent:
307 : time_background += time_taken_to_execute_;
308 : break;
309 : case OptimizedCompilationJob::kSynchronous:
310 : time_foreground += time_taken_to_execute_;
311 : break;
312 : }
313 455908 : counters->turbofan_optimize_total_background()->AddSample(
314 911817 : static_cast<int>(time_background.InMicroseconds()));
315 455908 : counters->turbofan_optimize_total_foreground()->AddSample(
316 911816 : static_cast<int>(time_foreground.InMicroseconds()));
317 : }
318 : }
319 460551 : }
320 :
321 460551 : void OptimizedCompilationJob::RecordFunctionCompilation(
322 : CodeEventListener::LogEventsAndTags tag, Isolate* isolate) const {
323 : Handle<AbstractCode> abstract_code =
324 460551 : Handle<AbstractCode>::cast(compilation_info()->code());
325 :
326 921102 : double time_taken_ms = time_taken_to_prepare_.InMillisecondsF() +
327 460551 : time_taken_to_execute_.InMillisecondsF() +
328 460551 : time_taken_to_finalize_.InMillisecondsF();
329 :
330 : Handle<Script> script(
331 921101 : Script::cast(compilation_info()->shared_info()->script()), isolate);
332 : LogFunctionCompilation(tag, compilation_info()->shared_info(), script,
333 460550 : abstract_code, true, time_taken_ms, isolate);
334 460551 : }
335 :
336 : // ----------------------------------------------------------------------------
337 : // Local helper methods that make up the compilation pipeline.
338 :
339 : namespace {
340 :
341 2119462 : bool UseAsmWasm(FunctionLiteral* literal, bool asm_wasm_broken) {
342 : // Check whether asm.js validation is enabled.
343 2119462 : if (!FLAG_validate_asm) return false;
344 :
345 : // Modules that have validated successfully, but were subsequently broken by
346 : // invalid module instantiation attempts are off limit forever.
347 1807289 : if (asm_wasm_broken) return false;
348 :
349 : // In stress mode we want to run the validator on everything.
350 1807121 : if (FLAG_stress_validate_asm) return true;
351 :
352 : // In general, we respect the "use asm" directive.
353 1807124 : return literal->scope()->IsAsmModule();
354 : }
355 :
356 2092688 : void InstallBytecodeArray(Handle<BytecodeArray> bytecode_array,
357 : Handle<SharedFunctionInfo> shared_info,
358 : ParseInfo* parse_info, Isolate* isolate) {
359 2092688 : if (!FLAG_interpreted_frames_native_stack) {
360 4185324 : shared_info->set_bytecode_array(*bytecode_array);
361 2092665 : return;
362 : }
363 :
364 : Handle<Code> code = isolate->factory()->CopyCode(Handle<Code>::cast(
365 29 : isolate->factory()->interpreter_entry_trampoline_for_profiling()));
366 :
367 : Handle<InterpreterData> interpreter_data =
368 : Handle<InterpreterData>::cast(isolate->factory()->NewStruct(
369 29 : INTERPRETER_DATA_TYPE, AllocationType::kOld));
370 :
371 29 : interpreter_data->set_bytecode_array(*bytecode_array);
372 29 : interpreter_data->set_interpreter_trampoline(*code);
373 :
374 58 : shared_info->set_interpreter_data(*interpreter_data);
375 :
376 : Handle<Script> script = parse_info->script();
377 : Handle<AbstractCode> abstract_code = Handle<AbstractCode>::cast(code);
378 : int line_num =
379 29 : Script::GetLineNumber(script, shared_info->StartPosition()) + 1;
380 : int column_num =
381 29 : Script::GetColumnNumber(script, shared_info->StartPosition()) + 1;
382 : String script_name = script->name()->IsString()
383 : ? String::cast(script->name())
384 58 : : ReadOnlyRoots(isolate).empty_string();
385 : CodeEventListener::LogEventsAndTags log_tag = Logger::ToNativeByScript(
386 : CodeEventListener::INTERPRETED_FUNCTION_TAG, *script);
387 29 : PROFILE(isolate, CodeCreateEvent(log_tag, *abstract_code, *shared_info,
388 : script_name, line_num, column_num));
389 : }
390 :
391 2095154 : void InstallUnoptimizedCode(UnoptimizedCompilationInfo* compilation_info,
392 : Handle<SharedFunctionInfo> shared_info,
393 : ParseInfo* parse_info, Isolate* isolate) {
394 : DCHECK_EQ(shared_info->language_mode(),
395 : compilation_info->literal()->language_mode());
396 :
397 : // Update the shared function info with the scope info.
398 2095154 : Handle<ScopeInfo> scope_info = compilation_info->scope()->scope_info();
399 2095152 : shared_info->set_scope_info(*scope_info);
400 :
401 2095156 : if (compilation_info->has_bytecode_array()) {
402 : DCHECK(!shared_info->HasBytecodeArray()); // Only compiled once.
403 : DCHECK(!compilation_info->has_asm_wasm_data());
404 : DCHECK(!shared_info->HasFeedbackMetadata());
405 :
406 : InstallBytecodeArray(compilation_info->bytecode_array(), shared_info,
407 2092687 : parse_info, isolate);
408 :
409 : Handle<FeedbackMetadata> feedback_metadata = FeedbackMetadata::New(
410 2092692 : isolate, compilation_info->feedback_vector_spec());
411 4185405 : shared_info->set_feedback_metadata(*feedback_metadata);
412 : } else {
413 : DCHECK(compilation_info->has_asm_wasm_data());
414 4938 : shared_info->set_asm_wasm_data(*compilation_info->asm_wasm_data());
415 4938 : shared_info->set_feedback_metadata(
416 : ReadOnlyRoots(isolate).empty_feedback_metadata());
417 : }
418 :
419 : // Install coverage info on the shared function info.
420 6285519 : if (compilation_info->has_coverage_info() &&
421 2096957 : !shared_info->HasCoverageInfo()) {
422 : DCHECK(isolate->is_block_code_coverage());
423 : isolate->debug()->InstallCoverageInfo(shared_info,
424 880 : compilation_info->coverage_info());
425 : }
426 2095173 : }
427 :
428 1008718 : void EnsureSharedFunctionInfosArrayOnScript(ParseInfo* parse_info,
429 : Isolate* isolate) {
430 : DCHECK(parse_info->is_toplevel());
431 : DCHECK(!parse_info->script().is_null());
432 1008718 : if (parse_info->script()->shared_function_infos()->length() > 0) {
433 : DCHECK_EQ(parse_info->script()->shared_function_infos()->length(),
434 : parse_info->max_function_literal_id() + 1);
435 0 : return;
436 : }
437 : Handle<WeakFixedArray> infos(isolate->factory()->NewWeakFixedArray(
438 1008718 : parse_info->max_function_literal_id() + 1));
439 1008711 : parse_info->script()->set_shared_function_infos(*infos);
440 : }
441 :
442 2095149 : void SetSharedFunctionFlagsFromLiteral(FunctionLiteral* literal,
443 : Handle<SharedFunctionInfo> shared_info) {
444 6285445 : shared_info->set_has_duplicate_parameters(
445 2095149 : literal->has_duplicate_parameters());
446 4190294 : shared_info->set_is_oneshot_iife(literal->is_oneshot_iife());
447 2095164 : shared_info->UpdateAndFinalizeExpectedNofPropertiesFromEstimate(literal);
448 2095166 : if (literal->dont_optimize_reason() != BailoutReason::kNoReason) {
449 0 : shared_info->DisableOptimization(literal->dont_optimize_reason());
450 : }
451 6285499 : shared_info->set_is_safe_to_skip_arguments_adaptor(
452 4190333 : literal->SafeToSkipArgumentsAdaptor());
453 2095165 : }
454 :
455 2095151 : CompilationJob::Status FinalizeUnoptimizedCompilationJob(
456 : UnoptimizedCompilationJob* job, Handle<SharedFunctionInfo> shared_info,
457 : Isolate* isolate) {
458 : UnoptimizedCompilationInfo* compilation_info = job->compilation_info();
459 : ParseInfo* parse_info = job->parse_info();
460 :
461 2095151 : SetSharedFunctionFlagsFromLiteral(compilation_info->literal(), shared_info);
462 :
463 2095165 : CompilationJob::Status status = job->FinalizeJob(shared_info, isolate);
464 2095174 : if (status == CompilationJob::SUCCEEDED) {
465 2095175 : InstallUnoptimizedCode(compilation_info, shared_info, parse_info, isolate);
466 : CodeEventListener::LogEventsAndTags log_tag;
467 2095169 : if (parse_info->is_toplevel()) {
468 : log_tag = compilation_info->is_eval() ? CodeEventListener::EVAL_TAG
469 1516460 : : CodeEventListener::SCRIPT_TAG;
470 : } else {
471 : log_tag = parse_info->lazy_compile() ? CodeEventListener::LAZY_COMPILE_TAG
472 578709 : : CodeEventListener::FUNCTION_TAG;
473 : }
474 2095169 : job->RecordFunctionCompilation(log_tag, shared_info, isolate);
475 2095170 : job->RecordCompilationStats(isolate);
476 : }
477 2095174 : return status;
478 : }
479 :
480 603185 : std::unique_ptr<UnoptimizedCompilationJob> ExecuteUnoptimizedCompileJobs(
481 : ParseInfo* parse_info, FunctionLiteral* literal,
482 : AccountingAllocator* allocator,
483 : UnoptimizedCompilationJobList* inner_function_jobs) {
484 603185 : if (UseAsmWasm(literal, parse_info->is_asm_wasm_broken())) {
485 : std::unique_ptr<UnoptimizedCompilationJob> asm_job(
486 1861 : AsmJs::NewCompilationJob(parse_info, literal, allocator));
487 1861 : if (asm_job->ExecuteJob() == CompilationJob::SUCCEEDED) {
488 : return asm_job;
489 : }
490 : // asm.js validation failed, fall through to standard unoptimized compile.
491 : // Note: we rely on the fact that AsmJs jobs have done all validation in the
492 : // PrepareJob and ExecuteJob phases and can't fail in FinalizeJob with
493 : // with a validation error or another error that could be solve by falling
494 : // through to standard unoptimized compile.
495 : }
496 : std::vector<FunctionLiteral*> eager_inner_literals;
497 : std::unique_ptr<UnoptimizedCompilationJob> job(
498 : interpreter::Interpreter::NewCompilationJob(
499 601832 : parse_info, literal, allocator, &eager_inner_literals));
500 :
501 601824 : if (job->ExecuteJob() != CompilationJob::SUCCEEDED) {
502 : // Compilation failed, return null.
503 : return std::unique_ptr<UnoptimizedCompilationJob>();
504 : }
505 :
506 : // Recursively compile eager inner literals.
507 617031 : for (FunctionLiteral* inner_literal : eager_inner_literals) {
508 : std::unique_ptr<UnoptimizedCompilationJob> inner_job(
509 : ExecuteUnoptimizedCompileJobs(parse_info, inner_literal, allocator,
510 15208 : inner_function_jobs));
511 : // Compilation failed, return null.
512 15208 : if (!inner_job) return std::unique_ptr<UnoptimizedCompilationJob>();
513 : inner_function_jobs->emplace_front(std::move(inner_job));
514 : }
515 :
516 : return job;
517 : }
518 :
519 587974 : std::unique_ptr<UnoptimizedCompilationJob> GenerateUnoptimizedCode(
520 : ParseInfo* parse_info, AccountingAllocator* allocator,
521 : UnoptimizedCompilationJobList* inner_function_jobs) {
522 : DisallowHeapAccess no_heap_access;
523 : DCHECK(inner_function_jobs->empty());
524 :
525 587974 : if (!Compiler::Analyze(parse_info)) {
526 : return std::unique_ptr<UnoptimizedCompilationJob>();
527 : }
528 :
529 : // Prepare and execute compilation of the outer-most function.
530 : std::unique_ptr<UnoptimizedCompilationJob> outer_function_job(
531 : ExecuteUnoptimizedCompileJobs(parse_info, parse_info->literal(),
532 587981 : allocator, inner_function_jobs));
533 587980 : if (!outer_function_job) return std::unique_ptr<UnoptimizedCompilationJob>();
534 :
535 : // Character stream shouldn't be used again.
536 587977 : parse_info->ResetCharacterStream();
537 :
538 : return outer_function_job;
539 : }
540 :
541 1008577 : MaybeHandle<SharedFunctionInfo> GenerateUnoptimizedCodeForToplevel(
542 : Isolate* isolate, ParseInfo* parse_info, AccountingAllocator* allocator,
543 : IsCompiledScope* is_compiled_scope) {
544 1008577 : EnsureSharedFunctionInfosArrayOnScript(parse_info, isolate);
545 1008565 : parse_info->ast_value_factory()->Internalize(isolate);
546 :
547 1008587 : if (!Compiler::Analyze(parse_info)) return MaybeHandle<SharedFunctionInfo>();
548 1008563 : DeclarationScope::AllocateScopeInfos(parse_info, isolate);
549 :
550 : // Prepare and execute compilation of the outer-most function.
551 : // Create the SharedFunctionInfo and add it to the script's list.
552 1008564 : Handle<Script> script = parse_info->script();
553 : Handle<SharedFunctionInfo> top_level =
554 : isolate->factory()->NewSharedFunctionInfoForLiteral(parse_info->literal(),
555 1008564 : script, true);
556 :
557 : std::vector<FunctionLiteral*> functions_to_compile;
558 2017124 : functions_to_compile.push_back(parse_info->literal());
559 :
560 2524872 : while (!functions_to_compile.empty()) {
561 1516302 : FunctionLiteral* literal = functions_to_compile.back();
562 : functions_to_compile.pop_back();
563 : Handle<SharedFunctionInfo> shared_info =
564 1516302 : Compiler::GetSharedFunctionInfo(literal, script, isolate);
565 1516284 : if (shared_info->is_compiled()) continue;
566 1516283 : if (UseAsmWasm(literal, parse_info->is_asm_wasm_broken())) {
567 : std::unique_ptr<UnoptimizedCompilationJob> asm_job(
568 1898 : AsmJs::NewCompilationJob(parse_info, literal, allocator));
569 3038 : if (asm_job->ExecuteJob() == CompilationJob::SUCCEEDED &&
570 1140 : FinalizeUnoptimizedCompilationJob(asm_job.get(), shared_info,
571 : isolate) ==
572 : CompilationJob::SUCCEEDED) {
573 : continue;
574 : }
575 : // asm.js validation failed, fall through to standard unoptimized compile.
576 : // Note: we rely on the fact that AsmJs jobs have done all validation in
577 : // the PrepareJob and ExecuteJob phases and can't fail in FinalizeJob with
578 : // with a validation error or another error that could be solve by falling
579 : // through to standard unoptimized compile.
580 : }
581 :
582 : std::unique_ptr<UnoptimizedCompilationJob> job(
583 : interpreter::Interpreter::NewCompilationJob(
584 1515143 : parse_info, literal, allocator, &functions_to_compile));
585 :
586 3030308 : if (job->ExecuteJob() == CompilationJob::FAILED ||
587 1515157 : FinalizeUnoptimizedCompilationJob(job.get(), shared_info, isolate) ==
588 : CompilationJob::FAILED) {
589 0 : return MaybeHandle<SharedFunctionInfo>();
590 : }
591 :
592 1515160 : if (shared_info.is_identical_to(top_level)) {
593 : // Ensure that the top level function is retained.
594 1008570 : *is_compiled_scope = shared_info->is_compiled_scope();
595 : DCHECK(is_compiled_scope->is_compiled());
596 : }
597 : }
598 :
599 : // Character stream shouldn't be used again.
600 1008570 : parse_info->ResetCharacterStream();
601 :
602 1008562 : return top_level;
603 : }
604 :
605 574793 : bool FinalizeUnoptimizedCode(
606 : ParseInfo* parse_info, Isolate* isolate,
607 : Handle<SharedFunctionInfo> shared_info,
608 : UnoptimizedCompilationJob* outer_function_job,
609 : UnoptimizedCompilationJobList* inner_function_jobs) {
610 : DCHECK(AllowCompilation::IsAllowed(isolate));
611 :
612 : // TODO(rmcilroy): Clear native context in debug once AsmJS generates doesn't
613 : // rely on accessing native context during finalization.
614 :
615 : // Allocate scope infos for the literal.
616 574793 : DeclarationScope::AllocateScopeInfos(parse_info, isolate);
617 :
618 : // Finalize the outer-most function's compilation job.
619 574809 : if (FinalizeUnoptimizedCompilationJob(outer_function_job, shared_info,
620 : isolate) != CompilationJob::SUCCEEDED) {
621 : return false;
622 : }
623 :
624 : // Finalize the inner functions' compilation jobs.
625 578881 : for (auto&& inner_job : *inner_function_jobs) {
626 : Handle<SharedFunctionInfo> inner_shared_info =
627 : Compiler::GetSharedFunctionInfo(
628 : inner_job->compilation_info()->literal(), parse_info->script(),
629 4070 : isolate);
630 : // The inner function might be compiled already if compiling for debug.
631 4075 : if (inner_shared_info->is_compiled()) continue;
632 4065 : if (FinalizeUnoptimizedCompilationJob(inner_job.get(), inner_shared_info,
633 : isolate) !=
634 : CompilationJob::SUCCEEDED) {
635 0 : return false;
636 : }
637 : }
638 :
639 : // Report any warnings generated during compilation.
640 574811 : if (parse_info->pending_error_handler()->has_pending_warnings()) {
641 : parse_info->pending_error_handler()->ReportWarnings(isolate,
642 449 : parse_info->script());
643 : }
644 :
645 : return true;
646 : }
647 :
648 479916 : V8_WARN_UNUSED_RESULT MaybeHandle<Code> GetCodeFromOptimizedCodeCache(
649 : Handle<JSFunction> function, BailoutId osr_offset) {
650 : RuntimeCallTimerScope runtimeTimer(
651 : function->GetIsolate(),
652 479916 : RuntimeCallCounterId::kCompileGetFromOptimizedCodeMap);
653 : Handle<SharedFunctionInfo> shared(function->shared(), function->GetIsolate());
654 : DisallowHeapAllocation no_gc;
655 479914 : if (osr_offset.IsNone()) {
656 475001 : if (function->has_feedback_vector()) {
657 475003 : FeedbackVector feedback_vector = function->feedback_vector();
658 : feedback_vector->EvictOptimizedCodeMarkedForDeoptimization(
659 475003 : function->shared(), "GetCodeFromOptimizedCodeCache");
660 : Code code = feedback_vector->optimized_code();
661 :
662 475002 : if (!code.is_null()) {
663 : // Caching of optimized code enabled and optimized code found.
664 : DCHECK(!code->marked_for_deoptimization());
665 : DCHECK(function->shared()->is_compiled());
666 0 : return Handle<Code>(code, feedback_vector->GetIsolate());
667 : }
668 : }
669 : }
670 479915 : return MaybeHandle<Code>();
671 : }
672 :
673 437419 : void ClearOptimizedCodeCache(OptimizedCompilationInfo* compilation_info) {
674 : Handle<JSFunction> function = compilation_info->closure();
675 437419 : if (compilation_info->osr_offset().IsNone()) {
676 : Handle<FeedbackVector> vector =
677 : handle(function->feedback_vector(), function->GetIsolate());
678 432835 : vector->ClearOptimizationMarker();
679 : }
680 437419 : }
681 :
682 460550 : void InsertCodeIntoOptimizedCodeCache(
683 : OptimizedCompilationInfo* compilation_info) {
684 : Handle<Code> code = compilation_info->code();
685 460550 : if (code->kind() != Code::OPTIMIZED_FUNCTION) return; // Nothing to do.
686 :
687 : // Function context specialization folds-in the function context,
688 : // so no sharing can occur.
689 460550 : if (compilation_info->is_function_context_specializing()) {
690 : // Native context specialized code is not shared, so make sure the optimized
691 : // code cache is clear.
692 437419 : ClearOptimizedCodeCache(compilation_info);
693 437420 : return;
694 : }
695 :
696 : // Cache optimized context-specific code.
697 : Handle<JSFunction> function = compilation_info->closure();
698 : Handle<SharedFunctionInfo> shared(function->shared(), function->GetIsolate());
699 : Handle<Context> native_context(function->context()->native_context(),
700 : function->GetIsolate());
701 23131 : if (compilation_info->osr_offset().IsNone()) {
702 : Handle<FeedbackVector> vector =
703 23074 : handle(function->feedback_vector(), function->GetIsolate());
704 23074 : FeedbackVector::SetOptimizedCode(vector, code);
705 : }
706 : }
707 :
708 453995 : bool GetOptimizedCodeNow(OptimizedCompilationJob* job, Isolate* isolate) {
709 : TimerEventScope<TimerEventRecompileSynchronous> timer(isolate);
710 : RuntimeCallTimerScope runtimeTimer(
711 453995 : isolate, RuntimeCallCounterId::kRecompileSynchronous);
712 : OptimizedCompilationInfo* compilation_info = job->compilation_info();
713 1361985 : TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
714 : "V8.RecompileSynchronous");
715 :
716 1361950 : if (job->PrepareJob(isolate) != CompilationJob::SUCCEEDED ||
717 907952 : job->ExecuteJob() != CompilationJob::SUCCEEDED ||
718 453954 : job->FinalizeJob(isolate) != CompilationJob::SUCCEEDED) {
719 53 : if (FLAG_trace_opt) {
720 0 : PrintF("[aborted optimizing ");
721 0 : compilation_info->closure()->ShortPrint();
722 0 : PrintF(" because: %s]\n",
723 0 : GetBailoutReason(compilation_info->bailout_reason()));
724 : }
725 : return false;
726 : }
727 :
728 : // Success!
729 453942 : job->RecordCompilationStats(OptimizedCompilationJob::kSynchronous, isolate);
730 : DCHECK(!isolate->has_pending_exception());
731 453941 : InsertCodeIntoOptimizedCodeCache(compilation_info);
732 453942 : job->RecordFunctionCompilation(CodeEventListener::LAZY_COMPILE_TAG, isolate);
733 453942 : return true;
734 : }
735 :
736 6885 : bool GetOptimizedCodeLater(OptimizedCompilationJob* job, Isolate* isolate) {
737 : OptimizedCompilationInfo* compilation_info = job->compilation_info();
738 6885 : if (!isolate->optimizing_compile_dispatcher()->IsQueueAvailable()) {
739 26 : if (FLAG_trace_concurrent_recompilation) {
740 0 : PrintF(" ** Compilation queue full, will retry optimizing ");
741 0 : compilation_info->closure()->ShortPrint();
742 0 : PrintF(" later.\n");
743 : }
744 : return false;
745 : }
746 :
747 6859 : if (isolate->heap()->HighMemoryPressure()) {
748 0 : if (FLAG_trace_concurrent_recompilation) {
749 0 : PrintF(" ** High memory pressure, will retry optimizing ");
750 0 : compilation_info->closure()->ShortPrint();
751 0 : PrintF(" later.\n");
752 : }
753 : return false;
754 : }
755 :
756 : TimerEventScope<TimerEventRecompileSynchronous> timer(isolate);
757 : RuntimeCallTimerScope runtimeTimer(
758 6859 : isolate, RuntimeCallCounterId::kRecompileSynchronous);
759 20577 : TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
760 : "V8.RecompileSynchronous");
761 :
762 6859 : if (job->PrepareJob(isolate) != CompilationJob::SUCCEEDED) return false;
763 6859 : isolate->optimizing_compile_dispatcher()->QueueForOptimization(job);
764 :
765 6859 : if (FLAG_trace_concurrent_recompilation) {
766 0 : PrintF(" ** Queued ");
767 0 : compilation_info->closure()->ShortPrint();
768 0 : PrintF(" for concurrent optimization.\n");
769 : }
770 : return true;
771 : }
772 :
773 489390 : MaybeHandle<Code> GetOptimizedCode(Handle<JSFunction> function,
774 : ConcurrencyMode mode,
775 : BailoutId osr_offset = BailoutId::None(),
776 : JavaScriptFrame* osr_frame = nullptr) {
777 489390 : Isolate* isolate = function->GetIsolate();
778 : Handle<SharedFunctionInfo> shared(function->shared(), isolate);
779 :
780 : // Make sure we clear the optimization marker on the function so that we
781 : // don't try to re-optimize.
782 489390 : if (function->HasOptimizationMarker()) {
783 : function->ClearOptimizationMarker();
784 : }
785 :
786 494946 : if (shared->optimization_disabled() &&
787 : shared->disable_optimization_reason() == BailoutReason::kNeverOptimize) {
788 66 : return MaybeHandle<Code>();
789 : }
790 :
791 489325 : if (isolate->debug()->needs_check_on_function_call()) {
792 : // Do not optimize when debugger needs to hook into every call.
793 9409 : return MaybeHandle<Code>();
794 : }
795 :
796 : // If code was pending optimization for testing, delete remove the strong root
797 : // that was preventing the bytecode from being flushed between marking and
798 : // optimization.
799 479916 : if (!isolate->heap()->pending_optimize_for_test_bytecode()->IsUndefined()) {
800 : Handle<ObjectHashTable> table =
801 : handle(ObjectHashTable::cast(
802 : isolate->heap()->pending_optimize_for_test_bytecode()),
803 : isolate);
804 : bool was_present;
805 : table = table->Remove(isolate, table, handle(function->shared(), isolate),
806 89044 : &was_present);
807 44522 : isolate->heap()->SetPendingOptimizeForTestBytecode(*table);
808 : }
809 :
810 : Handle<Code> cached_code;
811 959830 : if (GetCodeFromOptimizedCodeCache(function, osr_offset)
812 : .ToHandle(&cached_code)) {
813 0 : if (FLAG_trace_opt) {
814 0 : PrintF("[found optimized code for ");
815 0 : function->ShortPrint();
816 0 : if (!osr_offset.IsNone()) {
817 0 : PrintF(" at OSR AST id %d", osr_offset.ToInt());
818 : }
819 0 : PrintF("]\n");
820 : }
821 0 : return cached_code;
822 : }
823 :
824 : // Reset profiler ticks, function is no longer considered hot.
825 : DCHECK(shared->is_compiled());
826 : function->feedback_vector()->set_profiler_ticks(0);
827 :
828 479914 : VMState<COMPILER> state(isolate);
829 : TimerEventScope<TimerEventOptimizeCode> optimize_code_timer(isolate);
830 : RuntimeCallTimerScope runtimeTimer(isolate,
831 479914 : RuntimeCallCounterId::kOptimizeCode);
832 1439746 : TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.OptimizeCode");
833 :
834 : DCHECK(!isolate->has_pending_exception());
835 479915 : PostponeInterruptsScope postpone(isolate);
836 959830 : bool has_script = shared->script()->IsScript();
837 : // BUG(5946): This DCHECK is necessary to make certain that we won't
838 : // tolerate the lack of a script without bytecode.
839 : DCHECK_IMPLIES(!has_script, shared->HasBytecodeArray());
840 : std::unique_ptr<OptimizedCompilationJob> job(
841 479915 : compiler::Pipeline::NewCompilationJob(isolate, function, has_script));
842 479910 : OptimizedCompilationInfo* compilation_info = job->compilation_info();
843 :
844 : compilation_info->SetOptimizingForOsr(osr_offset, osr_frame);
845 :
846 : // Do not use TurboFan if we need to be able to set break points.
847 479910 : if (compilation_info->shared_info()->HasBreakInfo()) {
848 567 : compilation_info->AbortOptimization(BailoutReason::kFunctionBeingDebugged);
849 567 : return MaybeHandle<Code>();
850 : }
851 :
852 : // Do not use TurboFan if optimization is disabled or function doesn't pass
853 : // turbo_filter.
854 940331 : if (!FLAG_opt || !shared->PassesFilter(FLAG_turbo_filter)) {
855 18469 : compilation_info->AbortOptimization(BailoutReason::kOptimizationDisabled);
856 18469 : return MaybeHandle<Code>();
857 : }
858 :
859 : // In case of concurrent recompilation, all handles below this point will be
860 : // allocated in a deferred handle scope that is detached and handed off to
861 : // the background thread when we return.
862 460879 : base::Optional<CompilationHandleScope> compilation;
863 460879 : if (mode == ConcurrencyMode::kConcurrent) {
864 6885 : compilation.emplace(isolate, compilation_info);
865 : }
866 :
867 : // All handles below will be canonicalized.
868 921759 : CanonicalHandleScope canonical(isolate);
869 :
870 : // Reopen handles in the new CompilationHandleScope.
871 460879 : compilation_info->ReopenHandlesInNewHandleScope(isolate);
872 :
873 460880 : if (mode == ConcurrencyMode::kConcurrent) {
874 6885 : if (GetOptimizedCodeLater(job.get(), isolate)) {
875 : job.release(); // The background recompile job owns this now.
876 :
877 : // Set the optimization marker and return a code object which checks it.
878 : function->SetOptimizationMarker(OptimizationMarker::kInOptimizationQueue);
879 : DCHECK(function->IsInterpreted() ||
880 : (!function->is_compiled() && function->shared()->IsInterpreted()));
881 : DCHECK(function->shared()->HasBytecodeArray());
882 13718 : return BUILTIN_CODE(isolate, InterpreterEntryTrampoline);
883 : }
884 : } else {
885 453995 : if (GetOptimizedCodeNow(job.get(), isolate))
886 453942 : return compilation_info->code();
887 : }
888 :
889 158 : if (isolate->has_pending_exception()) isolate->clear_pending_exception();
890 79 : return MaybeHandle<Code>();
891 : }
892 :
893 402 : bool FailWithPendingException(Isolate* isolate, ParseInfo* parse_info,
894 : Compiler::ClearExceptionFlag flag) {
895 402 : if (flag == Compiler::CLEAR_EXCEPTION) {
896 : isolate->clear_pending_exception();
897 153 : } else if (!isolate->has_pending_exception()) {
898 130 : if (parse_info->pending_error_handler()->has_pending_error()) {
899 : parse_info->pending_error_handler()->ReportErrors(
900 128 : isolate, parse_info->script(), parse_info->ast_value_factory());
901 : } else {
902 2 : isolate->StackOverflow();
903 : }
904 : }
905 402 : return false;
906 : }
907 :
908 1008695 : void FinalizeScriptCompilation(Isolate* isolate, ParseInfo* parse_info) {
909 : Handle<Script> script = parse_info->script();
910 : script->set_compilation_state(Script::COMPILATION_STATE_COMPILED);
911 :
912 : // Register any pending parallel tasks with the associated SFI.
913 1008695 : if (parse_info->parallel_tasks()) {
914 : CompilerDispatcher* dispatcher = parse_info->parallel_tasks()->dispatcher();
915 70 : for (auto& it : *parse_info->parallel_tasks()) {
916 55 : FunctionLiteral* literal = it.first;
917 55 : CompilerDispatcher::JobId job_id = it.second;
918 : MaybeHandle<SharedFunctionInfo> maybe_shared_for_task =
919 55 : script->FindSharedFunctionInfo(isolate, literal);
920 : Handle<SharedFunctionInfo> shared_for_task;
921 55 : if (maybe_shared_for_task.ToHandle(&shared_for_task)) {
922 50 : dispatcher->RegisterSharedFunctionInfo(job_id, *shared_for_task);
923 : } else {
924 5 : dispatcher->AbortJob(job_id);
925 : }
926 : }
927 : }
928 1008695 : }
929 :
930 138 : MaybeHandle<SharedFunctionInfo> FinalizeTopLevel(
931 : ParseInfo* parse_info, Isolate* isolate,
932 : UnoptimizedCompilationJob* outer_function_job,
933 : UnoptimizedCompilationJobList* inner_function_jobs) {
934 : // Internalize ast values onto the heap.
935 138 : parse_info->ast_value_factory()->Internalize(isolate);
936 :
937 : // Create shared function infos for top level and shared function infos array
938 : // for inner functions.
939 138 : EnsureSharedFunctionInfosArrayOnScript(parse_info, isolate);
940 : DCHECK_EQ(kNoSourcePosition,
941 : parse_info->literal()->function_token_position());
942 : Handle<SharedFunctionInfo> shared_info =
943 : isolate->factory()->NewSharedFunctionInfoForLiteral(
944 138 : parse_info->literal(), parse_info->script(), true);
945 :
946 : // Finalize compilation of the unoptimized bytecode or asm-js data.
947 138 : if (!FinalizeUnoptimizedCode(parse_info, isolate, shared_info,
948 : outer_function_job, inner_function_jobs)) {
949 : FailWithPendingException(isolate, parse_info,
950 0 : Compiler::ClearExceptionFlag::KEEP_EXCEPTION);
951 0 : return MaybeHandle<SharedFunctionInfo>();
952 : }
953 :
954 138 : FinalizeScriptCompilation(isolate, parse_info);
955 :
956 138 : return shared_info;
957 : }
958 :
959 1118007 : MaybeHandle<SharedFunctionInfo> CompileToplevel(
960 : ParseInfo* parse_info, Isolate* isolate,
961 : IsCompiledScope* is_compiled_scope) {
962 : TimerEventScope<TimerEventCompileCode> top_level_timer(isolate);
963 3354023 : TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.CompileCode");
964 : DCHECK_EQ(ThreadId::Current(), isolate->thread_id());
965 :
966 : PostponeInterruptsScope postpone(isolate);
967 : DCHECK(!isolate->native_context().is_null());
968 : RuntimeCallTimerScope runtimeTimer(
969 : isolate, parse_info->is_eval() ? RuntimeCallCounterId::kCompileEval
970 1118012 : : RuntimeCallCounterId::kCompileScript);
971 : VMState<BYTECODE_COMPILER> state(isolate);
972 2236013 : if (parse_info->literal() == nullptr &&
973 1118009 : !parsing::ParseProgram(parse_info, isolate)) {
974 109428 : return MaybeHandle<SharedFunctionInfo>();
975 : }
976 : // Measure how long it takes to do the compilation; only take the
977 : // rest of the function into account to avoid overlap with the
978 : // parsing statistics.
979 : HistogramTimer* rate = parse_info->is_eval()
980 : ? isolate->counters()->compile_eval()
981 1008576 : : isolate->counters()->compile();
982 : HistogramTimerScope timer(rate);
983 3025738 : TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
984 : parse_info->is_eval() ? "V8.CompileEval" : "V8.Compile");
985 :
986 : // Generate the unoptimized bytecode or asm-js data.
987 : MaybeHandle<SharedFunctionInfo> shared_info =
988 : GenerateUnoptimizedCodeForToplevel(
989 1008579 : isolate, parse_info, isolate->allocator(), is_compiled_scope);
990 1008582 : if (shared_info.is_null()) {
991 : FailWithPendingException(isolate, parse_info,
992 18 : Compiler::ClearExceptionFlag::KEEP_EXCEPTION);
993 18 : return MaybeHandle<SharedFunctionInfo>();
994 : }
995 :
996 1008564 : FinalizeScriptCompilation(isolate, parse_info);
997 1008560 : return shared_info;
998 : }
999 :
1000 13364 : std::unique_ptr<UnoptimizedCompilationJob> CompileOnBackgroundThread(
1001 : ParseInfo* parse_info, AccountingAllocator* allocator,
1002 : UnoptimizedCompilationJobList* inner_function_jobs) {
1003 : DisallowHeapAccess no_heap_access;
1004 40092 : TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
1005 : "V8.CompileCodeBackground");
1006 : RuntimeCallTimerScope runtimeTimer(
1007 : parse_info->runtime_call_stats(),
1008 : parse_info->is_toplevel()
1009 : ? parse_info->is_eval()
1010 : ? RuntimeCallCounterId::kCompileBackgroundEval
1011 : : RuntimeCallCounterId::kCompileBackgroundScript
1012 26653 : : RuntimeCallCounterId::kCompileBackgroundFunction);
1013 :
1014 : // Generate the unoptimized bytecode or asm-js data.
1015 : std::unique_ptr<UnoptimizedCompilationJob> outer_function_job(
1016 13364 : GenerateUnoptimizedCode(parse_info, allocator, inner_function_jobs));
1017 13364 : return outer_function_job;
1018 : }
1019 :
1020 : } // namespace
1021 :
1022 13398 : BackgroundCompileTask::BackgroundCompileTask(ScriptStreamingData* streamed_data,
1023 : Isolate* isolate)
1024 13398 : : info_(new ParseInfo(isolate)),
1025 : stack_size_(i::FLAG_stack_size),
1026 : worker_thread_runtime_call_stats_(
1027 : isolate->counters()->worker_thread_runtime_call_stats()),
1028 : allocator_(isolate->allocator()),
1029 53592 : timer_(isolate->counters()->compile_script_on_background()) {
1030 : VMState<PARSER> state(isolate);
1031 :
1032 : // Prepare the data for the internalization phase and compilation phase, which
1033 : // will happen in the main thread after parsing.
1034 13398 : LOG(isolate, ScriptEvent(Logger::ScriptEventType::kStreamingCompile,
1035 : info_->script_id()));
1036 : info_->set_toplevel();
1037 : info_->set_allow_lazy_parsing();
1038 13398 : if (V8_UNLIKELY(info_->block_coverage_enabled())) {
1039 0 : info_->AllocateSourceRangeMap();
1040 : }
1041 13398 : LanguageMode language_mode = construct_language_mode(FLAG_use_strict);
1042 : info_->set_language_mode(
1043 : stricter_language_mode(info_->language_mode(), language_mode));
1044 :
1045 : std::unique_ptr<Utf16CharacterStream> stream(ScannerStream::For(
1046 26796 : streamed_data->source_stream.get(), streamed_data->encoding));
1047 26795 : info_->set_character_stream(std::move(stream));
1048 13398 : }
1049 :
1050 80 : BackgroundCompileTask::BackgroundCompileTask(
1051 : AccountingAllocator* allocator, const ParseInfo* outer_parse_info,
1052 : const AstRawString* function_name, const FunctionLiteral* function_literal,
1053 : WorkerThreadRuntimeCallStats* worker_thread_runtime_stats,
1054 : TimedHistogram* timer, int max_stack_size)
1055 : : info_(ParseInfo::FromParent(outer_parse_info, allocator, function_literal,
1056 : function_name)),
1057 : stack_size_(max_stack_size),
1058 : worker_thread_runtime_call_stats_(worker_thread_runtime_stats),
1059 : allocator_(allocator),
1060 160 : timer_(timer) {
1061 : DCHECK(outer_parse_info->is_toplevel());
1062 : DCHECK(!function_literal->is_toplevel());
1063 :
1064 : // Clone the character stream so both can be accessed independently.
1065 : std::unique_ptr<Utf16CharacterStream> character_stream =
1066 80 : outer_parse_info->character_stream()->Clone();
1067 160 : character_stream->Seek(function_literal->start_position());
1068 160 : info_->set_character_stream(std::move(character_stream));
1069 :
1070 : // Get preparsed scope data from the function literal.
1071 80 : if (function_literal->produced_preparse_data()) {
1072 : ZonePreparseData* serialized_data =
1073 20 : function_literal->produced_preparse_data()->Serialize(info_->zone());
1074 : info_->set_consumed_preparse_data(
1075 20 : ConsumedPreparseData::For(info_->zone(), serialized_data));
1076 : }
1077 80 : }
1078 :
1079 : BackgroundCompileTask::~BackgroundCompileTask() = default;
1080 :
1081 : namespace {
1082 :
1083 : // A scope object that ensures a parse info's runtime call stats, stack limit
1084 : // and on_background_thread fields is set correctly during worker-thread
1085 : // compile, and restores it after going out of scope.
1086 : class OffThreadParseInfoScope {
1087 : public:
1088 13474 : OffThreadParseInfoScope(
1089 : ParseInfo* parse_info,
1090 : WorkerThreadRuntimeCallStats* worker_thread_runtime_stats, int stack_size)
1091 : : parse_info_(parse_info),
1092 : original_runtime_call_stats_(parse_info_->runtime_call_stats()),
1093 : original_stack_limit_(parse_info_->stack_limit()),
1094 13474 : worker_thread_scope_(worker_thread_runtime_stats) {
1095 13474 : parse_info_->set_on_background_thread(true);
1096 13474 : parse_info_->set_runtime_call_stats(worker_thread_scope_.Get());
1097 13474 : parse_info_->set_stack_limit(GetCurrentStackPosition() - stack_size * KB);
1098 13474 : }
1099 :
1100 26948 : ~OffThreadParseInfoScope() {
1101 13474 : parse_info_->set_stack_limit(original_stack_limit_);
1102 13474 : parse_info_->set_runtime_call_stats(original_runtime_call_stats_);
1103 13474 : parse_info_->set_on_background_thread(false);
1104 13474 : }
1105 :
1106 : private:
1107 : ParseInfo* parse_info_;
1108 : RuntimeCallStats* original_runtime_call_stats_;
1109 : uintptr_t original_stack_limit_;
1110 : WorkerThreadRuntimeCallStatsScope worker_thread_scope_;
1111 :
1112 : DISALLOW_COPY_AND_ASSIGN(OffThreadParseInfoScope);
1113 : };
1114 :
1115 : } // namespace
1116 :
1117 13474 : void BackgroundCompileTask::Run() {
1118 : DisallowHeapAllocation no_allocation;
1119 : DisallowHandleAllocation no_handles;
1120 : DisallowHeapAccess no_heap_access;
1121 :
1122 13474 : TimedHistogramScope timer(timer_);
1123 : OffThreadParseInfoScope off_thread_scope(
1124 40422 : info_.get(), worker_thread_runtime_call_stats_, stack_size_);
1125 40422 : TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
1126 : "BackgroundCompileTask::Run");
1127 : RuntimeCallTimerScope runtimeTimer(
1128 : info_->runtime_call_stats(),
1129 13474 : RuntimeCallCounterId::kCompileBackgroundCompileTask);
1130 :
1131 : // Update the character stream's runtime call stats.
1132 : info_->character_stream()->set_runtime_call_stats(
1133 : info_->runtime_call_stats());
1134 :
1135 : // Parser needs to stay alive for finalizing the parsing on the main
1136 : // thread.
1137 13474 : parser_.reset(new Parser(info_.get()));
1138 13474 : parser_->InitializeEmptyScopeChain(info_.get());
1139 :
1140 13474 : parser_->ParseOnBackground(info_.get());
1141 13474 : if (info_->literal() != nullptr) {
1142 : // Parsing has succeeded, compile.
1143 26728 : outer_function_job_ = CompileOnBackgroundThread(info_.get(), allocator_,
1144 : &inner_function_jobs_);
1145 : }
1146 13474 : }
1147 :
1148 :
1149 : // ----------------------------------------------------------------------------
1150 : // Implementation of Compiler
1151 :
1152 1629154 : bool Compiler::Analyze(ParseInfo* parse_info) {
1153 : DCHECK_NOT_NULL(parse_info->literal());
1154 : RuntimeCallTimerScope runtimeTimer(
1155 : parse_info->runtime_call_stats(),
1156 : parse_info->on_background_thread()
1157 : ? RuntimeCallCounterId::kCompileBackgroundAnalyse
1158 1629154 : : RuntimeCallCounterId::kCompileAnalyse);
1159 1629152 : if (!Rewriter::Rewrite(parse_info)) return false;
1160 1629143 : if (!DeclarationScope::Analyze(parse_info)) return false;
1161 1629142 : return true;
1162 : }
1163 :
1164 0 : bool Compiler::ParseAndAnalyze(ParseInfo* parse_info,
1165 : Handle<SharedFunctionInfo> shared_info,
1166 : Isolate* isolate) {
1167 0 : if (!parsing::ParseAny(parse_info, shared_info, isolate)) {
1168 : return false;
1169 : }
1170 0 : return Compiler::Analyze(parse_info);
1171 : }
1172 :
1173 : // static
1174 25 : bool Compiler::CollectSourcePositions(Isolate* isolate,
1175 : Handle<SharedFunctionInfo> shared_info) {
1176 : DCHECK(shared_info->is_compiled());
1177 : DCHECK(shared_info->HasBytecodeArray());
1178 : DCHECK(!shared_info->GetBytecodeArray()->HasSourcePositionTable());
1179 :
1180 : // Collecting source positions requires allocating a new source position
1181 : // table.
1182 : DCHECK(AllowHeapAllocation::IsAllowed());
1183 :
1184 : Handle<BytecodeArray> bytecode =
1185 50 : handle(shared_info->GetBytecodeArray(), isolate);
1186 :
1187 : // TODO(v8:8510): Push the CLEAR_EXCEPTION flag or something like it down into
1188 : // the parser so it aborts without setting a pending exception, which then
1189 : // gets thrown. This would avoid the situation where potentially we'd reparse
1190 : // several times (running out of stack each time) before hitting this limit.
1191 25 : if (GetCurrentStackPosition() < isolate->stack_guard()->real_climit()) {
1192 : // Stack is already exhausted.
1193 5 : bytecode->SetSourcePositionsFailedToCollect();
1194 5 : return false;
1195 : }
1196 :
1197 : DCHECK(AllowCompilation::IsAllowed(isolate));
1198 : DCHECK_EQ(ThreadId::Current(), isolate->thread_id());
1199 : DCHECK(!isolate->has_pending_exception());
1200 : VMState<BYTECODE_COMPILER> state(isolate);
1201 : PostponeInterruptsScope postpone(isolate);
1202 : RuntimeCallTimerScope runtimeTimer(
1203 20 : isolate, RuntimeCallCounterId::kCompileCollectSourcePositions);
1204 60 : TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
1205 : "V8.CollectSourcePositions");
1206 : HistogramTimerScope timer(isolate->counters()->collect_source_positions());
1207 :
1208 : // Set up parse info.
1209 40 : ParseInfo parse_info(isolate, shared_info);
1210 : parse_info.set_lazy_compile();
1211 : parse_info.set_collect_source_positions();
1212 20 : if (FLAG_allow_natives_syntax) parse_info.set_allow_natives_syntax();
1213 :
1214 : // Parse and update ParseInfo with the results.
1215 20 : if (!parsing::ParseAny(&parse_info, shared_info, isolate)) {
1216 : // Parsing failed probably as a result of stack exhaustion.
1217 0 : bytecode->SetSourcePositionsFailedToCollect();
1218 : return FailWithPendingException(
1219 0 : isolate, &parse_info, Compiler::ClearExceptionFlag::CLEAR_EXCEPTION);
1220 : }
1221 :
1222 : // Generate the unoptimized bytecode.
1223 : // TODO(v8:8510): Consider forcing preparsing of inner functions to avoid
1224 : // wasting time fully parsing them when they won't ever be used.
1225 : UnoptimizedCompilationJobList inner_function_jobs;
1226 : std::unique_ptr<UnoptimizedCompilationJob> outer_function_job(
1227 : GenerateUnoptimizedCode(&parse_info, isolate->allocator(),
1228 20 : &inner_function_jobs));
1229 20 : if (!outer_function_job) {
1230 : // Recompiling failed probably as a result of stack exhaustion.
1231 0 : bytecode->SetSourcePositionsFailedToCollect();
1232 : return FailWithPendingException(
1233 0 : isolate, &parse_info, Compiler::ClearExceptionFlag::CLEAR_EXCEPTION);
1234 : }
1235 :
1236 : DCHECK(outer_function_job->compilation_info()->collect_source_positions());
1237 :
1238 : // TODO(v8:8510) Avoid re-allocating bytecode array/constant pool and
1239 : // re-internalizeing the ast values. Maybe we could use the
1240 : // unoptimized_compilation_flag to signal that all we need is the source
1241 : // position table (and we could do the DCHECK that the bytecode array is the
1242 : // same in the bytecode-generator, by comparing the real bytecode array on the
1243 : // SFI with the off-heap bytecode array).
1244 :
1245 : // Internalize ast values onto the heap.
1246 20 : parse_info.ast_value_factory()->Internalize(isolate);
1247 :
1248 : {
1249 : // Allocate scope infos for the literal.
1250 20 : DeclarationScope::AllocateScopeInfos(&parse_info, isolate);
1251 20 : CHECK_EQ(outer_function_job->FinalizeJob(shared_info, isolate),
1252 : CompilationJob::SUCCEEDED);
1253 : }
1254 :
1255 : // Update the source position table on the original bytecode.
1256 : DCHECK(bytecode->IsBytecodeEqual(
1257 : *outer_function_job->compilation_info()->bytecode_array()));
1258 : DCHECK(outer_function_job->compilation_info()->has_bytecode_array());
1259 : ByteArray source_position_table = outer_function_job->compilation_info()
1260 : ->bytecode_array()
1261 20 : ->SourcePositionTable();
1262 20 : bytecode->set_source_position_table(source_position_table);
1263 : // If debugging, make sure that instrumented bytecode has the source position
1264 : // table set on it as well.
1265 40 : if (shared_info->HasDebugInfo() &&
1266 20 : shared_info->GetDebugInfo()->HasInstrumentedBytecodeArray()) {
1267 0 : shared_info->GetDebugBytecodeArray()->set_source_position_table(
1268 0 : source_position_table);
1269 : }
1270 :
1271 : DCHECK(!isolate->has_pending_exception());
1272 : DCHECK(shared_info->is_compiled_scope().is_compiled());
1273 : return true;
1274 : }
1275 :
1276 574909 : bool Compiler::Compile(Handle<SharedFunctionInfo> shared_info,
1277 : ClearExceptionFlag flag,
1278 : IsCompiledScope* is_compiled_scope) {
1279 : // We should never reach here if the function is already compiled.
1280 : DCHECK(!shared_info->is_compiled());
1281 : DCHECK(!is_compiled_scope->is_compiled());
1282 :
1283 : Isolate* isolate = shared_info->GetIsolate();
1284 : DCHECK(AllowCompilation::IsAllowed(isolate));
1285 : DCHECK_EQ(ThreadId::Current(), isolate->thread_id());
1286 : DCHECK(!isolate->has_pending_exception());
1287 : DCHECK(!shared_info->HasBytecodeArray());
1288 : VMState<BYTECODE_COMPILER> state(isolate);
1289 : PostponeInterruptsScope postpone(isolate);
1290 : TimerEventScope<TimerEventCompileCode> compile_timer(isolate);
1291 : RuntimeCallTimerScope runtimeTimer(isolate,
1292 574916 : RuntimeCallCounterId::kCompileFunction);
1293 1724736 : TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.CompileCode");
1294 : AggregatedHistogramTimerScope timer(isolate->counters()->compile_lazy());
1295 :
1296 : // Set up parse info.
1297 1149825 : ParseInfo parse_info(isolate, shared_info);
1298 : parse_info.set_lazy_compile();
1299 :
1300 : // Check if the compiler dispatcher has shared_info enqueued for compile.
1301 : CompilerDispatcher* dispatcher = isolate->compiler_dispatcher();
1302 574917 : if (dispatcher->IsEnqueued(shared_info)) {
1303 43 : if (!dispatcher->FinishNow(shared_info)) {
1304 0 : return FailWithPendingException(isolate, &parse_info, flag);
1305 : }
1306 43 : *is_compiled_scope = shared_info->is_compiled_scope();
1307 : DCHECK(is_compiled_scope->is_compiled());
1308 43 : return true;
1309 : }
1310 :
1311 574873 : if (shared_info->HasUncompiledDataWithPreparseData()) {
1312 38848 : parse_info.set_consumed_preparse_data(ConsumedPreparseData::For(
1313 : isolate,
1314 : handle(
1315 : shared_info->uncompiled_data_with_preparse_data()->preparse_data(),
1316 : isolate)));
1317 : }
1318 :
1319 : // Parse and update ParseInfo with the results.
1320 574876 : if (!parsing::ParseAny(&parse_info, shared_info, isolate)) {
1321 271 : return FailWithPendingException(isolate, &parse_info, flag);
1322 : }
1323 :
1324 : // Generate the unoptimized bytecode or asm-js data.
1325 : UnoptimizedCompilationJobList inner_function_jobs;
1326 : std::unique_ptr<UnoptimizedCompilationJob> outer_function_job(
1327 : GenerateUnoptimizedCode(&parse_info, isolate->allocator(),
1328 574593 : &inner_function_jobs));
1329 574591 : if (!outer_function_job) {
1330 0 : return FailWithPendingException(isolate, &parse_info, flag);
1331 : }
1332 :
1333 : // Internalize ast values onto the heap.
1334 574591 : parse_info.ast_value_factory()->Internalize(isolate);
1335 :
1336 : // Finalize compilation of the unoptimized bytecode or asm-js data.
1337 574589 : if (!FinalizeUnoptimizedCode(&parse_info, isolate, shared_info,
1338 : outer_function_job.get(),
1339 : &inner_function_jobs)) {
1340 0 : return FailWithPendingException(isolate, &parse_info, flag);
1341 : }
1342 :
1343 : DCHECK(!isolate->has_pending_exception());
1344 574606 : *is_compiled_scope = shared_info->is_compiled_scope();
1345 : DCHECK(is_compiled_scope->is_compiled());
1346 574602 : return true;
1347 : }
1348 :
1349 698948 : bool Compiler::Compile(Handle<JSFunction> function, ClearExceptionFlag flag,
1350 : IsCompiledScope* is_compiled_scope) {
1351 : // We should never reach here if the function is already compiled or optimized
1352 : DCHECK(!function->is_compiled());
1353 : DCHECK(!function->IsOptimized());
1354 : DCHECK(!function->HasOptimizationMarker());
1355 : DCHECK(!function->HasOptimizedCode());
1356 :
1357 : // Reset the JSFunction if we are recompiling due to the bytecode having been
1358 : // flushed.
1359 698948 : function->ResetIfBytecodeFlushed();
1360 :
1361 : Isolate* isolate = function->GetIsolate();
1362 : Handle<SharedFunctionInfo> shared_info = handle(function->shared(), isolate);
1363 :
1364 : // Ensure shared function info is compiled.
1365 698957 : *is_compiled_scope = shared_info->is_compiled_scope();
1366 1270337 : if (!is_compiled_scope->is_compiled() &&
1367 571387 : !Compile(shared_info, flag, is_compiled_scope)) {
1368 : return false;
1369 : }
1370 : DCHECK(is_compiled_scope->is_compiled());
1371 1397372 : Handle<Code> code = handle(shared_info->GetCode(), isolate);
1372 :
1373 : // Initialize the feedback cell for this JSFunction.
1374 698684 : JSFunction::InitializeFeedbackCell(function);
1375 :
1376 : // Optimize now if --always-opt is enabled.
1377 852080 : if (FLAG_always_opt && !function->shared()->HasAsmWasmData()) {
1378 152981 : if (FLAG_trace_opt) {
1379 0 : PrintF("[optimizing ");
1380 0 : function->ShortPrint();
1381 0 : PrintF(" because --always-opt]\n");
1382 : }
1383 : Handle<Code> opt_code;
1384 305962 : if (GetOptimizedCode(function, ConcurrencyMode::kNotConcurrent)
1385 : .ToHandle(&opt_code)) {
1386 : code = opt_code;
1387 : }
1388 : }
1389 :
1390 : // Install code on closure.
1391 698692 : function->set_code(*code);
1392 :
1393 : // Check postconditions on success.
1394 : DCHECK(!isolate->has_pending_exception());
1395 : DCHECK(function->shared()->is_compiled());
1396 : DCHECK(function->is_compiled());
1397 698689 : return true;
1398 : }
1399 :
1400 71 : bool Compiler::FinalizeBackgroundCompileTask(
1401 : BackgroundCompileTask* task, Handle<SharedFunctionInfo> shared_info,
1402 : Isolate* isolate, ClearExceptionFlag flag) {
1403 213 : TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
1404 : "V8.FinalizeBackgroundCompileTask");
1405 : RuntimeCallTimerScope runtimeTimer(
1406 71 : isolate, RuntimeCallCounterId::kCompileFinalizeBackgroundCompileTask);
1407 : HandleScope scope(isolate);
1408 : ParseInfo* parse_info = task->info();
1409 : DCHECK(!parse_info->is_toplevel());
1410 : DCHECK(!shared_info->is_compiled());
1411 :
1412 142 : Handle<Script> script(Script::cast(shared_info->script()), isolate);
1413 71 : parse_info->set_script(script);
1414 :
1415 71 : task->parser()->UpdateStatistics(isolate, script);
1416 71 : task->parser()->HandleSourceURLComments(isolate, script);
1417 :
1418 141 : if (parse_info->literal() == nullptr || !task->outer_function_job()) {
1419 : // Parsing or compile failed on background thread - report error messages.
1420 4 : return FailWithPendingException(isolate, parse_info, flag);
1421 : }
1422 :
1423 : // Parsing has succeeded - finalize compilation.
1424 67 : parse_info->ast_value_factory()->Internalize(isolate);
1425 67 : if (!FinalizeUnoptimizedCode(parse_info, isolate, shared_info,
1426 : task->outer_function_job(),
1427 : task->inner_function_jobs())) {
1428 : // Finalization failed - throw an exception.
1429 0 : return FailWithPendingException(isolate, parse_info, flag);
1430 : }
1431 :
1432 : DCHECK(!isolate->has_pending_exception());
1433 : DCHECK(shared_info->is_compiled());
1434 : return true;
1435 : }
1436 :
1437 324485 : bool Compiler::CompileOptimized(Handle<JSFunction> function,
1438 : ConcurrencyMode mode) {
1439 324485 : if (function->IsOptimized()) return true;
1440 : Isolate* isolate = function->GetIsolate();
1441 : DCHECK(AllowCompilation::IsAllowed(isolate));
1442 :
1443 : // Start a compilation.
1444 : Handle<Code> code;
1445 648970 : if (!GetOptimizedCode(function, mode).ToHandle(&code)) {
1446 : // Optimization failed, get unoptimized code. Unoptimized code must exist
1447 : // already if we are optimizing.
1448 : DCHECK(!isolate->has_pending_exception());
1449 : DCHECK(function->shared()->is_compiled());
1450 : DCHECK(function->shared()->IsInterpreted());
1451 20649 : code = BUILTIN_CODE(isolate, InterpreterEntryTrampoline);
1452 : }
1453 :
1454 : // Install code on closure.
1455 324485 : function->set_code(*code);
1456 :
1457 : // Check postconditions on success.
1458 : DCHECK(!isolate->has_pending_exception());
1459 : DCHECK(function->shared()->is_compiled());
1460 : DCHECK(function->is_compiled());
1461 : DCHECK_IMPLIES(function->HasOptimizationMarker(),
1462 : function->IsInOptimizationQueue());
1463 : DCHECK_IMPLIES(function->HasOptimizationMarker(),
1464 : function->ChecksOptimizationMarker());
1465 : DCHECK_IMPLIES(function->IsInOptimizationQueue(),
1466 : mode == ConcurrencyMode::kConcurrent);
1467 324485 : return true;
1468 : }
1469 :
1470 761 : MaybeHandle<SharedFunctionInfo> Compiler::CompileForLiveEdit(
1471 : ParseInfo* parse_info, Isolate* isolate) {
1472 : IsCompiledScope is_compiled_scope;
1473 761 : return CompileToplevel(parse_info, isolate, &is_compiled_scope);
1474 : }
1475 :
1476 3556335 : MaybeHandle<JSFunction> Compiler::GetFunctionFromEval(
1477 : Handle<String> source, Handle<SharedFunctionInfo> outer_info,
1478 : Handle<Context> context, LanguageMode language_mode,
1479 : ParseRestriction restriction, int parameters_end_pos,
1480 : int eval_scope_position, int eval_position) {
1481 : Isolate* isolate = context->GetIsolate();
1482 : int source_length = source->length();
1483 3556335 : isolate->counters()->total_eval_size()->Increment(source_length);
1484 3556335 : isolate->counters()->total_compile_size()->Increment(source_length);
1485 :
1486 : // The cache lookup key needs to be aware of the separation between the
1487 : // parameters and the body to prevent this valid invocation:
1488 : // Function("", "function anonymous(\n/**/) {\n}");
1489 : // from adding an entry that falsely approves this invalid invocation:
1490 : // Function("\n/**/) {\nfunction anonymous(", "}");
1491 : // The actual eval_scope_position for indirect eval and CreateDynamicFunction
1492 : // is unused (just 0), which means it's an available field to use to indicate
1493 : // this separation. But to make sure we're not causing other false hits, we
1494 : // negate the scope position.
1495 7112670 : if (restriction == ONLY_SINGLE_FUNCTION_LITERAL &&
1496 3556335 : parameters_end_pos != kNoSourcePosition) {
1497 : // use the parameters_end_pos as the eval_scope_position in the eval cache.
1498 : DCHECK_EQ(eval_scope_position, 0);
1499 1088875 : eval_scope_position = -parameters_end_pos;
1500 : }
1501 : CompilationCache* compilation_cache = isolate->compilation_cache();
1502 : InfoCellPair eval_result = compilation_cache->LookupEval(
1503 3556335 : source, outer_info, context, language_mode, eval_scope_position);
1504 : Handle<FeedbackCell> feedback_cell;
1505 3556335 : if (eval_result.has_feedback_cell()) {
1506 2232032 : feedback_cell = handle(eval_result.feedback_cell(), isolate);
1507 : }
1508 :
1509 : Handle<SharedFunctionInfo> shared_info;
1510 : Handle<Script> script;
1511 : IsCompiledScope is_compiled_scope;
1512 : bool allow_eval_cache;
1513 3556335 : if (eval_result.has_shared()) {
1514 : shared_info = Handle<SharedFunctionInfo>(eval_result.shared(), isolate);
1515 5192570 : script = Handle<Script>(Script::cast(shared_info->script()), isolate);
1516 2596285 : is_compiled_scope = shared_info->is_compiled_scope();
1517 : allow_eval_cache = true;
1518 : } else {
1519 1812892 : ParseInfo parse_info(isolate);
1520 : script = parse_info.CreateScript(
1521 960050 : isolate, source, OriginOptionsForEval(outer_info->script()));
1522 : script->set_compilation_type(Script::COMPILATION_TYPE_EVAL);
1523 1920100 : script->set_eval_from_shared(*outer_info);
1524 960050 : if (eval_position == kNoSourcePosition) {
1525 : // If the position is missing, attempt to get the code offset by
1526 : // walking the stack. Do not translate the code offset into source
1527 : // position, but store it as negative value for lazy translation.
1528 353324 : StackTraceFrameIterator it(isolate);
1529 706648 : if (!it.done() && it.is_javascript()) {
1530 706648 : FrameSummary summary = FrameSummary::GetTop(it.javascript_frame());
1531 706648 : script->set_eval_from_shared(
1532 : summary.AsJavaScript().function()->shared());
1533 1059972 : script->set_origin_options(OriginOptionsForEval(*summary.script()));
1534 353324 : eval_position = -summary.code_offset();
1535 : } else {
1536 : eval_position = 0;
1537 : }
1538 : }
1539 : script->set_eval_from_position(eval_position);
1540 1920100 : TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(
1541 : TRACE_DISABLED_BY_DEFAULT("v8.compile"), "Script",
1542 : TRACE_ID_WITH_SCOPE(Script::kTraceScope, script->id()),
1543 : script->ToTracedValue());
1544 :
1545 : parse_info.set_eval();
1546 : parse_info.set_language_mode(language_mode);
1547 : parse_info.set_parse_restriction(restriction);
1548 : parse_info.set_parameters_end_pos(parameters_end_pos);
1549 960050 : if (!context->IsNativeContext()) {
1550 1148050 : parse_info.set_outer_scope_info(handle(context->scope_info(), isolate));
1551 : }
1552 : DCHECK(!parse_info.is_module());
1553 :
1554 1920100 : if (!CompileToplevel(&parse_info, isolate, &is_compiled_scope)
1555 : .ToHandle(&shared_info)) {
1556 107208 : return MaybeHandle<JSFunction>();
1557 : }
1558 : allow_eval_cache = parse_info.allow_eval_cache();
1559 : }
1560 :
1561 : // If caller is strict mode, the result must be in strict mode as well.
1562 : DCHECK(is_sloppy(language_mode) || is_strict(shared_info->language_mode()));
1563 :
1564 : Handle<JSFunction> result;
1565 3449127 : if (eval_result.has_shared()) {
1566 2596285 : if (eval_result.has_feedback_cell()) {
1567 : result = isolate->factory()->NewFunctionFromSharedFunctionInfo(
1568 2232032 : shared_info, context, feedback_cell, AllocationType::kYoung);
1569 : } else {
1570 : result = isolate->factory()->NewFunctionFromSharedFunctionInfo(
1571 364253 : shared_info, context, AllocationType::kYoung);
1572 364253 : JSFunction::InitializeFeedbackCell(result);
1573 364253 : if (allow_eval_cache) {
1574 : // Make sure to cache this result.
1575 : Handle<FeedbackCell> new_feedback_cell(result->raw_feedback_cell(),
1576 : isolate);
1577 : compilation_cache->PutEval(source, outer_info, context, shared_info,
1578 364253 : new_feedback_cell, eval_scope_position);
1579 : }
1580 : }
1581 : } else {
1582 : result = isolate->factory()->NewFunctionFromSharedFunctionInfo(
1583 852842 : shared_info, context, AllocationType::kYoung);
1584 852842 : JSFunction::InitializeFeedbackCell(result);
1585 852842 : if (allow_eval_cache) {
1586 : // Add the SharedFunctionInfo and the LiteralsArray to the eval cache if
1587 : // we didn't retrieve from there.
1588 : Handle<FeedbackCell> new_feedback_cell(result->raw_feedback_cell(),
1589 : isolate);
1590 : compilation_cache->PutEval(source, outer_info, context, shared_info,
1591 852393 : new_feedback_cell, eval_scope_position);
1592 : }
1593 : }
1594 : DCHECK(is_compiled_scope.is_compiled());
1595 :
1596 3449127 : return result;
1597 : }
1598 :
1599 :
1600 96 : bool Compiler::CodeGenerationFromStringsAllowed(Isolate* isolate,
1601 : Handle<Context> context,
1602 : Handle<String> source) {
1603 : DCHECK(context->allow_code_gen_from_strings()->IsFalse(isolate));
1604 : // Check with callback if set.
1605 : AllowCodeGenerationFromStringsCallback callback =
1606 : isolate->allow_code_gen_callback();
1607 96 : if (callback == nullptr) {
1608 : // No callback set and code generation disallowed.
1609 : return false;
1610 : } else {
1611 : // Callback set. Let it decide if code generation is allowed.
1612 92 : VMState<EXTERNAL> state(isolate);
1613 46 : return callback(v8::Utils::ToLocal(context), v8::Utils::ToLocal(source));
1614 : }
1615 : }
1616 :
1617 1090382 : MaybeHandle<JSFunction> Compiler::GetFunctionFromString(
1618 : Handle<Context> context, Handle<String> source,
1619 : ParseRestriction restriction, int parameters_end_pos) {
1620 : Isolate* const isolate = context->GetIsolate();
1621 : Handle<Context> native_context(context->native_context(), isolate);
1622 :
1623 : // Check if native context allows code generation from
1624 : // strings. Throw an exception if it doesn't.
1625 2180809 : if (native_context->allow_code_gen_from_strings()->IsFalse(isolate) &&
1626 45 : !CodeGenerationFromStringsAllowed(isolate, native_context, source)) {
1627 : Handle<Object> error_message =
1628 33 : native_context->ErrorMessageForCodeGenerationFromStrings();
1629 66 : THROW_NEW_ERROR(isolate, NewEvalError(MessageTemplate::kCodeGenFromStrings,
1630 : error_message),
1631 : JSFunction);
1632 : }
1633 :
1634 : // Compile source string in the native context.
1635 : int eval_scope_position = 0;
1636 : int eval_position = kNoSourcePosition;
1637 : Handle<SharedFunctionInfo> outer_info(
1638 2180698 : native_context->empty_function()->shared(), isolate);
1639 : return Compiler::GetFunctionFromEval(
1640 : source, outer_info, native_context, LanguageMode::kSloppy, restriction,
1641 1090349 : parameters_end_pos, eval_scope_position, eval_position);
1642 : }
1643 :
1644 : namespace {
1645 :
1646 : struct ScriptCompileTimerScope {
1647 : public:
1648 : // TODO(leszeks): There are too many blink-specific entries in this enum,
1649 : // figure out a way to push produce/hit-isolate-cache/consume/consume-failed
1650 : // back up the API and log them in blink instead.
1651 : enum class CacheBehaviour {
1652 : kProduceCodeCache,
1653 : kHitIsolateCacheWhenNoCache,
1654 : kConsumeCodeCache,
1655 : kConsumeCodeCacheFailed,
1656 : kNoCacheBecauseInlineScript,
1657 : kNoCacheBecauseScriptTooSmall,
1658 : kNoCacheBecauseCacheTooCold,
1659 : kNoCacheNoReason,
1660 : kNoCacheBecauseNoResource,
1661 : kNoCacheBecauseInspector,
1662 : kNoCacheBecauseCachingDisabled,
1663 : kNoCacheBecauseModule,
1664 : kNoCacheBecauseStreamingSource,
1665 : kNoCacheBecauseV8Extension,
1666 : kHitIsolateCacheWhenProduceCodeCache,
1667 : kHitIsolateCacheWhenConsumeCodeCache,
1668 : kNoCacheBecauseExtensionModule,
1669 : kNoCacheBecausePacScript,
1670 : kNoCacheBecauseInDocumentWrite,
1671 : kNoCacheBecauseResourceWithNoCacheHandler,
1672 : kHitIsolateCacheWhenStreamingSource,
1673 : kCount
1674 : };
1675 :
1676 288599 : explicit ScriptCompileTimerScope(
1677 : Isolate* isolate, ScriptCompiler::NoCacheReason no_cache_reason)
1678 : : isolate_(isolate),
1679 : all_scripts_histogram_scope_(isolate->counters()->compile_script(),
1680 : true),
1681 : no_cache_reason_(no_cache_reason),
1682 : hit_isolate_cache_(false),
1683 : producing_code_cache_(false),
1684 : consuming_code_cache_(false),
1685 577203 : consuming_code_cache_failed_(false) {}
1686 :
1687 577209 : ~ScriptCompileTimerScope() {
1688 288603 : CacheBehaviour cache_behaviour = GetCacheBehaviour();
1689 :
1690 : Histogram* cache_behaviour_histogram =
1691 288601 : isolate_->counters()->compile_script_cache_behaviour();
1692 : // Sanity check that the histogram has exactly one bin per enum entry.
1693 : DCHECK_EQ(0, cache_behaviour_histogram->min());
1694 : DCHECK_EQ(static_cast<int>(CacheBehaviour::kCount),
1695 : cache_behaviour_histogram->max() + 1);
1696 : DCHECK_EQ(static_cast<int>(CacheBehaviour::kCount),
1697 : cache_behaviour_histogram->num_buckets());
1698 288601 : cache_behaviour_histogram->AddSample(static_cast<int>(cache_behaviour));
1699 :
1700 288604 : histogram_scope_.set_histogram(
1701 : GetCacheBehaviourTimedHistogram(cache_behaviour));
1702 288606 : }
1703 :
1704 130949 : void set_hit_isolate_cache() { hit_isolate_cache_ = true; }
1705 :
1706 : void set_producing_code_cache() { producing_code_cache_ = true; }
1707 :
1708 478 : void set_consuming_code_cache() { consuming_code_cache_ = true; }
1709 :
1710 : void set_consuming_code_cache_failed() {
1711 30 : consuming_code_cache_failed_ = true;
1712 : }
1713 :
1714 : private:
1715 : Isolate* isolate_;
1716 : LazyTimedHistogramScope histogram_scope_;
1717 : // TODO(leszeks): This timer is the sum of the other times, consider removing
1718 : // it to save space.
1719 : HistogramTimerScope all_scripts_histogram_scope_;
1720 : ScriptCompiler::NoCacheReason no_cache_reason_;
1721 : bool hit_isolate_cache_;
1722 : bool producing_code_cache_;
1723 : bool consuming_code_cache_;
1724 : bool consuming_code_cache_failed_;
1725 :
1726 288601 : CacheBehaviour GetCacheBehaviour() {
1727 288601 : if (producing_code_cache_) {
1728 0 : if (hit_isolate_cache_) {
1729 : return CacheBehaviour::kHitIsolateCacheWhenProduceCodeCache;
1730 : } else {
1731 0 : return CacheBehaviour::kProduceCodeCache;
1732 : }
1733 : }
1734 :
1735 288601 : if (consuming_code_cache_) {
1736 244 : if (hit_isolate_cache_) {
1737 : return CacheBehaviour::kHitIsolateCacheWhenConsumeCodeCache;
1738 239 : } else if (consuming_code_cache_failed_) {
1739 : return CacheBehaviour::kConsumeCodeCacheFailed;
1740 : }
1741 209 : return CacheBehaviour::kConsumeCodeCache;
1742 : }
1743 :
1744 288357 : if (hit_isolate_cache_) {
1745 130944 : if (no_cache_reason_ == ScriptCompiler::kNoCacheBecauseStreamingSource) {
1746 : return CacheBehaviour::kHitIsolateCacheWhenStreamingSource;
1747 : }
1748 117793 : return CacheBehaviour::kHitIsolateCacheWhenNoCache;
1749 : }
1750 :
1751 157413 : switch (no_cache_reason_) {
1752 : case ScriptCompiler::kNoCacheBecauseInlineScript:
1753 : return CacheBehaviour::kNoCacheBecauseInlineScript;
1754 : case ScriptCompiler::kNoCacheBecauseScriptTooSmall:
1755 0 : return CacheBehaviour::kNoCacheBecauseScriptTooSmall;
1756 : case ScriptCompiler::kNoCacheBecauseCacheTooCold:
1757 0 : return CacheBehaviour::kNoCacheBecauseCacheTooCold;
1758 : case ScriptCompiler::kNoCacheNoReason:
1759 153594 : return CacheBehaviour::kNoCacheNoReason;
1760 : case ScriptCompiler::kNoCacheBecauseNoResource:
1761 0 : return CacheBehaviour::kNoCacheBecauseNoResource;
1762 : case ScriptCompiler::kNoCacheBecauseInspector:
1763 301 : return CacheBehaviour::kNoCacheBecauseInspector;
1764 : case ScriptCompiler::kNoCacheBecauseCachingDisabled:
1765 0 : return CacheBehaviour::kNoCacheBecauseCachingDisabled;
1766 : case ScriptCompiler::kNoCacheBecauseModule:
1767 0 : return CacheBehaviour::kNoCacheBecauseModule;
1768 : case ScriptCompiler::kNoCacheBecauseStreamingSource:
1769 247 : return CacheBehaviour::kNoCacheBecauseStreamingSource;
1770 : case ScriptCompiler::kNoCacheBecauseV8Extension:
1771 3270 : return CacheBehaviour::kNoCacheBecauseV8Extension;
1772 : case ScriptCompiler::kNoCacheBecauseExtensionModule:
1773 0 : return CacheBehaviour::kNoCacheBecauseExtensionModule;
1774 : case ScriptCompiler::kNoCacheBecausePacScript:
1775 0 : return CacheBehaviour::kNoCacheBecausePacScript;
1776 : case ScriptCompiler::kNoCacheBecauseInDocumentWrite:
1777 0 : return CacheBehaviour::kNoCacheBecauseInDocumentWrite;
1778 : case ScriptCompiler::kNoCacheBecauseResourceWithNoCacheHandler:
1779 0 : return CacheBehaviour::kNoCacheBecauseResourceWithNoCacheHandler;
1780 : case ScriptCompiler::kNoCacheBecauseDeferredProduceCodeCache: {
1781 0 : if (hit_isolate_cache_) {
1782 : return CacheBehaviour::kHitIsolateCacheWhenProduceCodeCache;
1783 : } else {
1784 0 : return CacheBehaviour::kProduceCodeCache;
1785 : }
1786 : }
1787 : }
1788 0 : UNREACHABLE();
1789 : }
1790 :
1791 288604 : TimedHistogram* GetCacheBehaviourTimedHistogram(
1792 : CacheBehaviour cache_behaviour) {
1793 288604 : switch (cache_behaviour) {
1794 : case CacheBehaviour::kProduceCodeCache:
1795 : // Even if we hit the isolate's compilation cache, we currently recompile
1796 : // when we want to produce the code cache.
1797 : case CacheBehaviour::kHitIsolateCacheWhenProduceCodeCache:
1798 0 : return isolate_->counters()->compile_script_with_produce_cache();
1799 : case CacheBehaviour::kHitIsolateCacheWhenNoCache:
1800 : case CacheBehaviour::kHitIsolateCacheWhenConsumeCodeCache:
1801 : case CacheBehaviour::kHitIsolateCacheWhenStreamingSource:
1802 130949 : return isolate_->counters()->compile_script_with_isolate_cache_hit();
1803 : case CacheBehaviour::kConsumeCodeCacheFailed:
1804 30 : return isolate_->counters()->compile_script_consume_failed();
1805 : case CacheBehaviour::kConsumeCodeCache:
1806 209 : return isolate_->counters()->compile_script_with_consume_cache();
1807 :
1808 : case CacheBehaviour::kNoCacheBecauseInlineScript:
1809 0 : return isolate_->counters()
1810 : ->compile_script_no_cache_because_inline_script();
1811 : case CacheBehaviour::kNoCacheBecauseScriptTooSmall:
1812 0 : return isolate_->counters()
1813 : ->compile_script_no_cache_because_script_too_small();
1814 : case CacheBehaviour::kNoCacheBecauseCacheTooCold:
1815 0 : return isolate_->counters()
1816 : ->compile_script_no_cache_because_cache_too_cold();
1817 :
1818 : // Aggregate all the other "no cache" counters into a single histogram, to
1819 : // save space.
1820 : case CacheBehaviour::kNoCacheNoReason:
1821 : case CacheBehaviour::kNoCacheBecauseNoResource:
1822 : case CacheBehaviour::kNoCacheBecauseInspector:
1823 : case CacheBehaviour::kNoCacheBecauseCachingDisabled:
1824 : // TODO(leszeks): Consider counting separately once modules are more
1825 : // common.
1826 : case CacheBehaviour::kNoCacheBecauseModule:
1827 : // TODO(leszeks): Count separately or remove entirely once we have
1828 : // background compilation.
1829 : case CacheBehaviour::kNoCacheBecauseStreamingSource:
1830 : case CacheBehaviour::kNoCacheBecauseV8Extension:
1831 : case CacheBehaviour::kNoCacheBecauseExtensionModule:
1832 : case CacheBehaviour::kNoCacheBecausePacScript:
1833 : case CacheBehaviour::kNoCacheBecauseInDocumentWrite:
1834 : case CacheBehaviour::kNoCacheBecauseResourceWithNoCacheHandler:
1835 157416 : return isolate_->counters()->compile_script_no_cache_other();
1836 :
1837 : case CacheBehaviour::kCount:
1838 0 : UNREACHABLE();
1839 : }
1840 0 : UNREACHABLE();
1841 : }
1842 : };
1843 :
1844 157448 : Handle<Script> NewScript(Isolate* isolate, ParseInfo* parse_info,
1845 : Handle<String> source,
1846 : Compiler::ScriptDetails script_details,
1847 : ScriptOriginOptions origin_options,
1848 : NativesFlag natives) {
1849 : // Create a script object describing the script to be compiled.
1850 : Handle<Script> script =
1851 157448 : parse_info->CreateScript(isolate, source, origin_options, natives);
1852 : Handle<Object> script_name;
1853 157447 : if (script_details.name_obj.ToHandle(&script_name)) {
1854 91174 : script->set_name(*script_name);
1855 91170 : script->set_line_offset(script_details.line_offset);
1856 91170 : script->set_column_offset(script_details.column_offset);
1857 : }
1858 : Handle<Object> source_map_url;
1859 157443 : if (script_details.source_map_url.ToHandle(&source_map_url)) {
1860 774 : script->set_source_mapping_url(*source_map_url);
1861 : }
1862 : Handle<FixedArray> host_defined_options;
1863 157443 : if (script_details.host_defined_options.ToHandle(&host_defined_options)) {
1864 145374 : script->set_host_defined_options(*host_defined_options);
1865 : }
1866 157495 : LOG(isolate, ScriptDetails(*script));
1867 314886 : TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(
1868 : TRACE_DISABLED_BY_DEFAULT("v8.compile"), "Script",
1869 : TRACE_ID_WITH_SCOPE(Script::kTraceScope, script->id()),
1870 : script->ToTracedValue());
1871 157443 : return script;
1872 : }
1873 :
1874 : } // namespace
1875 :
1876 275122 : MaybeHandle<SharedFunctionInfo> Compiler::GetSharedFunctionInfoForScript(
1877 : Isolate* isolate, Handle<String> source,
1878 : const Compiler::ScriptDetails& script_details,
1879 : ScriptOriginOptions origin_options, v8::Extension* extension,
1880 : ScriptData* cached_data, ScriptCompiler::CompileOptions compile_options,
1881 : ScriptCompiler::NoCacheReason no_cache_reason, NativesFlag natives) {
1882 550257 : ScriptCompileTimerScope compile_timer(isolate, no_cache_reason);
1883 :
1884 : if (compile_options == ScriptCompiler::kNoCompileOptions ||
1885 : compile_options == ScriptCompiler::kEagerCompile) {
1886 : DCHECK_NULL(cached_data);
1887 : } else {
1888 : DCHECK(compile_options == ScriptCompiler::kConsumeCodeCache);
1889 : DCHECK(cached_data);
1890 : DCHECK_NULL(extension);
1891 : }
1892 : int source_length = source->length();
1893 275127 : isolate->counters()->total_load_size()->Increment(source_length);
1894 275127 : isolate->counters()->total_compile_size()->Increment(source_length);
1895 :
1896 275128 : LanguageMode language_mode = construct_language_mode(FLAG_use_strict);
1897 : CompilationCache* compilation_cache = isolate->compilation_cache();
1898 :
1899 : // Do a lookup in the compilation cache but not for extensions.
1900 : MaybeHandle<SharedFunctionInfo> maybe_result;
1901 : IsCompiledScope is_compiled_scope;
1902 275128 : if (extension == nullptr) {
1903 : bool can_consume_code_cache =
1904 : compile_options == ScriptCompiler::kConsumeCodeCache;
1905 271852 : if (can_consume_code_cache) {
1906 : compile_timer.set_consuming_code_cache();
1907 : }
1908 :
1909 : // First check per-isolate compilation cache.
1910 : maybe_result = compilation_cache->LookupScript(
1911 271852 : source, script_details.name_obj, script_details.line_offset,
1912 271852 : script_details.column_offset, origin_options, isolate->native_context(),
1913 543704 : language_mode);
1914 271853 : if (!maybe_result.is_null()) {
1915 : compile_timer.set_hit_isolate_cache();
1916 154055 : } else if (can_consume_code_cache) {
1917 : compile_timer.set_consuming_code_cache();
1918 : // Then check cached code provided by embedder.
1919 : HistogramTimerScope timer(isolate->counters()->compile_deserialize());
1920 : RuntimeCallTimerScope runtimeTimer(
1921 234 : isolate, RuntimeCallCounterId::kCompileDeserialize);
1922 702 : TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
1923 : "V8.CompileDeserialize");
1924 : Handle<SharedFunctionInfo> inner_result;
1925 468 : if (CodeSerializer::Deserialize(isolate, cached_data, source,
1926 : origin_options)
1927 438 : .ToHandle(&inner_result) &&
1928 438 : inner_result->is_compiled()) {
1929 : // Promote to per-isolate compilation cache.
1930 204 : is_compiled_scope = inner_result->is_compiled_scope();
1931 : DCHECK(is_compiled_scope.is_compiled());
1932 408 : compilation_cache->PutScript(source, isolate->native_context(),
1933 204 : language_mode, inner_result);
1934 408 : Handle<Script> script(Script::cast(inner_result->script()), isolate);
1935 : maybe_result = inner_result;
1936 : } else {
1937 : // Deserializer failed. Fall through to compile.
1938 : compile_timer.set_consuming_code_cache_failed();
1939 : }
1940 : }
1941 : }
1942 :
1943 275129 : if (maybe_result.is_null()) {
1944 314246 : ParseInfo parse_info(isolate);
1945 : // No cache entry found compile the script.
1946 : NewScript(isolate, &parse_info, source, script_details, origin_options,
1947 157130 : natives);
1948 :
1949 : // Compile the function and add it to the isolate cache.
1950 157124 : if (origin_options.IsModule()) parse_info.set_module();
1951 : parse_info.set_extension(extension);
1952 : parse_info.set_eager(compile_options == ScriptCompiler::kEagerCompile);
1953 :
1954 : parse_info.set_language_mode(
1955 : stricter_language_mode(parse_info.language_mode(), language_mode));
1956 157124 : maybe_result = CompileToplevel(&parse_info, isolate, &is_compiled_scope);
1957 : Handle<SharedFunctionInfo> result;
1958 310971 : if (extension == nullptr && maybe_result.ToHandle(&result)) {
1959 : DCHECK(is_compiled_scope.is_compiled());
1960 303364 : compilation_cache->PutScript(source, isolate->native_context(),
1961 151682 : language_mode, result);
1962 5438 : } else if (maybe_result.is_null() && natives != EXTENSION_CODE) {
1963 2169 : isolate->ReportPendingMessages();
1964 : }
1965 : }
1966 :
1967 550264 : return maybe_result;
1968 : }
1969 :
1970 79 : MaybeHandle<JSFunction> Compiler::GetWrappedFunction(
1971 : Handle<String> source, Handle<FixedArray> arguments,
1972 : Handle<Context> context, const Compiler::ScriptDetails& script_details,
1973 : ScriptOriginOptions origin_options, ScriptData* cached_data,
1974 : v8::ScriptCompiler::CompileOptions compile_options,
1975 : v8::ScriptCompiler::NoCacheReason no_cache_reason) {
1976 : Isolate* isolate = context->GetIsolate();
1977 158 : ScriptCompileTimerScope compile_timer(isolate, no_cache_reason);
1978 :
1979 : if (compile_options == ScriptCompiler::kNoCompileOptions ||
1980 : compile_options == ScriptCompiler::kEagerCompile) {
1981 : DCHECK_NULL(cached_data);
1982 : } else {
1983 : DCHECK(compile_options == ScriptCompiler::kConsumeCodeCache);
1984 : DCHECK(cached_data);
1985 : }
1986 :
1987 : int source_length = source->length();
1988 79 : isolate->counters()->total_compile_size()->Increment(source_length);
1989 :
1990 79 : LanguageMode language_mode = construct_language_mode(FLAG_use_strict);
1991 :
1992 : MaybeHandle<SharedFunctionInfo> maybe_result;
1993 : bool can_consume_code_cache =
1994 : compile_options == ScriptCompiler::kConsumeCodeCache;
1995 79 : if (can_consume_code_cache) {
1996 : compile_timer.set_consuming_code_cache();
1997 : // Then check cached code provided by embedder.
1998 : HistogramTimerScope timer(isolate->counters()->compile_deserialize());
1999 : RuntimeCallTimerScope runtimeTimer(
2000 5 : isolate, RuntimeCallCounterId::kCompileDeserialize);
2001 15 : TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
2002 : "V8.CompileDeserialize");
2003 : maybe_result = CodeSerializer::Deserialize(isolate, cached_data, source,
2004 5 : origin_options);
2005 5 : if (maybe_result.is_null()) {
2006 : // Deserializer failed. Fall through to compile.
2007 : compile_timer.set_consuming_code_cache_failed();
2008 : }
2009 : }
2010 :
2011 : Handle<SharedFunctionInfo> wrapped;
2012 : Handle<Script> script;
2013 : IsCompiledScope is_compiled_scope;
2014 79 : if (!maybe_result.ToHandle(&wrapped)) {
2015 138 : ParseInfo parse_info(isolate);
2016 : script = NewScript(isolate, &parse_info, source, script_details,
2017 74 : origin_options, NOT_NATIVES_CODE);
2018 148 : script->set_wrapped_arguments(*arguments);
2019 :
2020 : parse_info.set_eval(); // Use an eval scope as declaration scope.
2021 : parse_info.set_wrapped_as_function();
2022 : // parse_info.set_eager(compile_options == ScriptCompiler::kEagerCompile);
2023 74 : if (!context->IsNativeContext()) {
2024 38 : parse_info.set_outer_scope_info(handle(context->scope_info(), isolate));
2025 : }
2026 : parse_info.set_language_mode(
2027 : stricter_language_mode(parse_info.language_mode(), language_mode));
2028 :
2029 : Handle<SharedFunctionInfo> top_level;
2030 74 : maybe_result = CompileToplevel(&parse_info, isolate, &is_compiled_scope);
2031 74 : if (maybe_result.is_null()) isolate->ReportPendingMessages();
2032 74 : ASSIGN_RETURN_ON_EXCEPTION(isolate, top_level, maybe_result, JSFunction);
2033 :
2034 64 : SharedFunctionInfo::ScriptIterator infos(isolate, *script);
2035 128 : for (SharedFunctionInfo info = infos.Next(); !info.is_null();
2036 : info = infos.Next()) {
2037 128 : if (info->is_wrapped()) {
2038 : wrapped = Handle<SharedFunctionInfo>(info, isolate);
2039 : break;
2040 : }
2041 : }
2042 : DCHECK(!wrapped.is_null());
2043 : } else {
2044 5 : is_compiled_scope = wrapped->is_compiled_scope();
2045 10 : script = Handle<Script>(Script::cast(wrapped->script()), isolate);
2046 : }
2047 : DCHECK(is_compiled_scope.is_compiled());
2048 :
2049 : return isolate->factory()->NewFunctionFromSharedFunctionInfo(
2050 69 : wrapped, context, AllocationType::kYoung);
2051 : }
2052 :
2053 : MaybeHandle<SharedFunctionInfo>
2054 13398 : Compiler::GetSharedFunctionInfoForStreamedScript(
2055 : Isolate* isolate, Handle<String> source,
2056 : const ScriptDetails& script_details, ScriptOriginOptions origin_options,
2057 : ScriptStreamingData* streaming_data) {
2058 : ScriptCompileTimerScope compile_timer(
2059 26796 : isolate, ScriptCompiler::kNoCacheBecauseStreamingSource);
2060 : PostponeInterruptsScope postpone(isolate);
2061 :
2062 : int source_length = source->length();
2063 13398 : isolate->counters()->total_load_size()->Increment(source_length);
2064 13398 : isolate->counters()->total_compile_size()->Increment(source_length);
2065 :
2066 : BackgroundCompileTask* task = streaming_data->task.get();
2067 : ParseInfo* parse_info = task->info();
2068 : DCHECK(parse_info->is_toplevel());
2069 : // Check if compile cache already holds the SFI, if so no need to finalize
2070 : // the code compiled on the background thread.
2071 : CompilationCache* compilation_cache = isolate->compilation_cache();
2072 : MaybeHandle<SharedFunctionInfo> maybe_result =
2073 : compilation_cache->LookupScript(
2074 13398 : source, script_details.name_obj, script_details.line_offset,
2075 13398 : script_details.column_offset, origin_options,
2076 26796 : isolate->native_context(), parse_info->language_mode());
2077 13398 : if (!maybe_result.is_null()) {
2078 : compile_timer.set_hit_isolate_cache();
2079 : }
2080 :
2081 13398 : if (maybe_result.is_null()) {
2082 : // No cache entry found, finalize compilation of the script and add it to
2083 : // the isolate cache.
2084 : Handle<Script> script =
2085 : NewScript(isolate, parse_info, source, script_details, origin_options,
2086 247 : NOT_NATIVES_CODE);
2087 247 : task->parser()->UpdateStatistics(isolate, script);
2088 247 : task->parser()->HandleSourceURLComments(isolate, script);
2089 :
2090 385 : if (parse_info->literal() == nullptr || !task->outer_function_job()) {
2091 : // Parsing has failed - report error messages.
2092 : FailWithPendingException(isolate, parse_info,
2093 109 : Compiler::ClearExceptionFlag::KEEP_EXCEPTION);
2094 : } else {
2095 : // Parsing has succeeded - finalize compilation.
2096 : maybe_result =
2097 : FinalizeTopLevel(parse_info, isolate, task->outer_function_job(),
2098 138 : task->inner_function_jobs());
2099 138 : if (maybe_result.is_null()) {
2100 : // Finalization failed - throw an exception.
2101 : FailWithPendingException(isolate, parse_info,
2102 0 : Compiler::ClearExceptionFlag::KEEP_EXCEPTION);
2103 : }
2104 : }
2105 :
2106 : // Add compiled code to the isolate cache.
2107 : Handle<SharedFunctionInfo> result;
2108 247 : if (maybe_result.ToHandle(&result)) {
2109 276 : compilation_cache->PutScript(source, isolate->native_context(),
2110 138 : parse_info->language_mode(), result);
2111 : }
2112 : }
2113 :
2114 : streaming_data->Release();
2115 26796 : return maybe_result;
2116 : }
2117 :
2118 4152797 : Handle<SharedFunctionInfo> Compiler::GetSharedFunctionInfo(
2119 : FunctionLiteral* literal, Handle<Script> script, Isolate* isolate) {
2120 : // Precondition: code has been parsed and scopes have been analyzed.
2121 : MaybeHandle<SharedFunctionInfo> maybe_existing;
2122 :
2123 : // Find any previously allocated shared function info for the given literal.
2124 4152797 : maybe_existing = script->FindSharedFunctionInfo(isolate, literal);
2125 :
2126 : // If we found an existing shared function info, return it.
2127 : Handle<SharedFunctionInfo> existing;
2128 4152799 : if (maybe_existing.ToHandle(&existing)) return existing;
2129 :
2130 : // Allocate a shared function info object which will be compiled lazily.
2131 : Handle<SharedFunctionInfo> result =
2132 : isolate->factory()->NewSharedFunctionInfoForLiteral(literal, script,
2133 2630779 : false);
2134 2630781 : return result;
2135 : }
2136 :
2137 11925 : MaybeHandle<Code> Compiler::GetOptimizedCodeForOSR(Handle<JSFunction> function,
2138 : BailoutId osr_offset,
2139 : JavaScriptFrame* osr_frame) {
2140 : DCHECK(!osr_offset.IsNone());
2141 : DCHECK_NOT_NULL(osr_frame);
2142 : return GetOptimizedCode(function, ConcurrencyMode::kNotConcurrent, osr_offset,
2143 11925 : osr_frame);
2144 : }
2145 :
2146 6661 : bool Compiler::FinalizeOptimizedCompilationJob(OptimizedCompilationJob* job,
2147 : Isolate* isolate) {
2148 : VMState<COMPILER> state(isolate);
2149 : // Take ownership of compilation job. Deleting job also tears down the zone.
2150 : std::unique_ptr<OptimizedCompilationJob> job_scope(job);
2151 : OptimizedCompilationInfo* compilation_info = job->compilation_info();
2152 :
2153 : TimerEventScope<TimerEventRecompileSynchronous> timer(isolate);
2154 : RuntimeCallTimerScope runtimeTimer(
2155 6661 : isolate, RuntimeCallCounterId::kRecompileSynchronous);
2156 19983 : TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
2157 : "V8.RecompileSynchronous");
2158 :
2159 : Handle<SharedFunctionInfo> shared = compilation_info->shared_info();
2160 :
2161 : // Reset profiler ticks, function is no longer considered hot.
2162 : compilation_info->closure()->feedback_vector()->set_profiler_ticks(0);
2163 :
2164 : DCHECK(!shared->HasBreakInfo());
2165 :
2166 : // 1) Optimization on the concurrent thread may have failed.
2167 : // 2) The function may have already been optimized by OSR. Simply continue.
2168 : // Except when OSR already disabled optimization for some reason.
2169 : // 3) The code may have already been invalidated due to dependency change.
2170 : // 4) Code generation may have failed.
2171 6661 : if (job->state() == CompilationJob::State::kReadyToFinalize) {
2172 6661 : if (shared->optimization_disabled()) {
2173 : job->RetryOptimization(BailoutReason::kOptimizationDisabled);
2174 6661 : } else if (job->FinalizeJob(isolate) == CompilationJob::SUCCEEDED) {
2175 : job->RecordCompilationStats(OptimizedCompilationJob::kConcurrent,
2176 6609 : isolate);
2177 : job->RecordFunctionCompilation(CodeEventListener::LAZY_COMPILE_TAG,
2178 6609 : isolate);
2179 6609 : InsertCodeIntoOptimizedCodeCache(compilation_info);
2180 6609 : if (FLAG_trace_opt) {
2181 0 : PrintF("[completed optimizing ");
2182 0 : compilation_info->closure()->ShortPrint();
2183 0 : PrintF("]\n");
2184 : }
2185 6609 : compilation_info->closure()->set_code(*compilation_info->code());
2186 6609 : return CompilationJob::SUCCEEDED;
2187 : }
2188 : }
2189 :
2190 : DCHECK_EQ(job->state(), CompilationJob::State::kFailed);
2191 52 : if (FLAG_trace_opt) {
2192 0 : PrintF("[aborted optimizing ");
2193 0 : compilation_info->closure()->ShortPrint();
2194 0 : PrintF(" because: %s]\n",
2195 0 : GetBailoutReason(compilation_info->bailout_reason()));
2196 : }
2197 104 : compilation_info->closure()->set_code(shared->GetCode());
2198 : // Clear the InOptimizationQueue marker, if it exists.
2199 52 : if (compilation_info->closure()->IsInOptimizationQueue()) {
2200 : compilation_info->closure()->ClearOptimizationMarker();
2201 : }
2202 : return CompilationJob::FAILED;
2203 : }
2204 :
2205 13384989 : void Compiler::PostInstantiation(Handle<JSFunction> function,
2206 : AllocationType allocation) {
2207 : Isolate* isolate = function->GetIsolate();
2208 : Handle<SharedFunctionInfo> shared(function->shared(), isolate);
2209 13384996 : IsCompiledScope is_compiled_scope(shared->is_compiled_scope());
2210 :
2211 : // If code is compiled to bytecode (i.e., isn't asm.js), then allocate a
2212 : // feedback and check for optimized code.
2213 23481483 : if (is_compiled_scope.is_compiled() && shared->HasBytecodeArray()) {
2214 6281343 : JSFunction::InitializeFeedbackCell(function);
2215 :
2216 12562702 : Code code = function->has_feedback_vector()
2217 : ? function->feedback_vector()->optimized_code()
2218 6281353 : : Code();
2219 6281353 : if (!code.is_null()) {
2220 : // Caching of optimized code enabled and optimized code found.
2221 : DCHECK(!code->marked_for_deoptimization());
2222 : DCHECK(function->shared()->is_compiled());
2223 440032 : function->set_code(code);
2224 : }
2225 :
2226 7228723 : if (FLAG_always_opt && shared->allows_lazy_compilation() &&
2227 13236855 : !shared->optimization_disabled() && !function->IsOptimized() &&
2228 6482241 : !function->HasOptimizedCode()) {
2229 200888 : JSFunction::EnsureFeedbackVector(function);
2230 200888 : function->MarkForOptimization(ConcurrencyMode::kNotConcurrent);
2231 : }
2232 : }
2233 :
2234 23033510 : if (shared->is_toplevel() || shared->is_wrapped()) {
2235 : // If it's a top-level script, report compilation to the debugger.
2236 7473188 : Handle<Script> script(Script::cast(shared->script()), isolate);
2237 3736593 : isolate->debug()->OnAfterCompile(script);
2238 : }
2239 13385021 : }
2240 :
2241 : // ----------------------------------------------------------------------------
2242 : // Implementation of ScriptStreamingData
2243 :
2244 13397 : ScriptStreamingData::ScriptStreamingData(
2245 : std::unique_ptr<ScriptCompiler::ExternalSourceStream> source_stream,
2246 : ScriptCompiler::StreamedSource::Encoding encoding)
2247 26794 : : source_stream(std::move(source_stream)), encoding(encoding) {}
2248 :
2249 : ScriptStreamingData::~ScriptStreamingData() = default;
2250 :
2251 13398 : void ScriptStreamingData::Release() { task.reset(); }
2252 :
2253 : } // namespace internal
2254 122004 : } // namespace v8
|