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.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/parsing/parse-info.h"
34 : #include "src/parsing/parser.h"
35 : #include "src/parsing/parsing.h"
36 : #include "src/parsing/rewriter.h"
37 : #include "src/parsing/scanner-character-streams.h"
38 : #include "src/runtime-profiler.h"
39 : #include "src/snapshot/code-serializer.h"
40 : #include "src/unoptimized-compilation-info.h"
41 : #include "src/vm-state-inl.h"
42 :
43 : namespace v8 {
44 : namespace internal {
45 :
46 : // A wrapper around a OptimizedCompilationInfo that detaches the Handles from
47 : // the underlying DeferredHandleScope and stores them in info_ on
48 : // destruction.
49 : class CompilationHandleScope final {
50 : public:
51 : explicit CompilationHandleScope(Isolate* isolate,
52 : OptimizedCompilationInfo* info)
53 7210 : : deferred_(isolate), info_(info) {}
54 7210 : ~CompilationHandleScope() { info_->set_deferred_handles(deferred_.Detach()); }
55 :
56 : private:
57 : DeferredHandleScope deferred_;
58 : OptimizedCompilationInfo* info_;
59 : };
60 :
61 : // Helper that times a scoped region and records the elapsed time.
62 : struct ScopedTimer {
63 5559565 : explicit ScopedTimer(base::TimeDelta* location) : location_(location) {
64 : DCHECK_NOT_NULL(location_);
65 : timer_.Start();
66 : }
67 :
68 16678371 : ~ScopedTimer() { *location_ += timer_.Elapsed(); }
69 :
70 : base::ElapsedTimer timer_;
71 : base::TimeDelta* location_;
72 : };
73 :
74 : namespace {
75 :
76 2541170 : void LogFunctionCompilation(CodeEventListener::LogEventsAndTags tag,
77 : Handle<SharedFunctionInfo> shared,
78 : Handle<Script> script,
79 : Handle<AbstractCode> abstract_code, bool optimizing,
80 5082020 : double time_taken_ms, Isolate* isolate) {
81 : DCHECK(!abstract_code.is_null());
82 : DCHECK(!abstract_code.is_identical_to(BUILTIN_CODE(isolate, CompileLazy)));
83 :
84 : // Log the code generation. If source information is available include
85 : // script name and line number. Check explicitly whether logging is
86 : // enabled as finding the line number is not free.
87 7623130 : if (!isolate->logger()->is_listening_to_code_events() &&
88 7621974 : !isolate->is_profiling() && !FLAG_log_function_events &&
89 : !isolate->code_event_dispatcher()->IsListeningToCodeEvents()) {
90 2541110 : return;
91 : }
92 :
93 814 : int line_num = Script::GetLineNumber(script, shared->StartPosition()) + 1;
94 814 : int column_num = Script::GetColumnNumber(script, shared->StartPosition()) + 1;
95 1628 : String script_name = script->name()->IsString()
96 870 : ? String::cast(script->name())
97 1628 : : ReadOnlyRoots(isolate).empty_string();
98 : CodeEventListener::LogEventsAndTags log_tag =
99 : Logger::ToNativeByScript(tag, *script);
100 814 : PROFILE(isolate, CodeCreateEvent(log_tag, *abstract_code, *shared,
101 : script_name, line_num, column_num));
102 814 : if (!FLAG_log_function_events) return;
103 :
104 : DisallowHeapAllocation no_gc;
105 :
106 64 : std::string name = optimizing ? "optimize" : "compile";
107 64 : switch (tag) {
108 : case CodeEventListener::EVAL_TAG:
109 : name += "-eval";
110 : break;
111 : case CodeEventListener::SCRIPT_TAG:
112 : break;
113 : case CodeEventListener::LAZY_COMPILE_TAG:
114 : name += "-lazy";
115 : break;
116 : case CodeEventListener::FUNCTION_TAG:
117 : break;
118 : default:
119 0 : UNREACHABLE();
120 : }
121 :
122 320 : LOG(isolate, FunctionEvent(name.c_str(), script->id(), time_taken_ms,
123 : shared->StartPosition(), shared->EndPosition(),
124 : shared->DebugName()));
125 : }
126 :
127 1308868 : ScriptOriginOptions OriginOptionsForEval(Object script) {
128 1308868 : if (!script->IsScript()) return ScriptOriginOptions();
129 :
130 1308868 : const auto outer_origin_options = Script::cast(script)->origin_options();
131 : return ScriptOriginOptions(outer_origin_options.IsSharedCrossOrigin(),
132 1308868 : outer_origin_options.IsOpaque());
133 : }
134 :
135 : } // namespace
136 :
137 : // ----------------------------------------------------------------------------
138 : // Implementation of UnoptimizedCompilationJob
139 :
140 2114309 : CompilationJob::Status UnoptimizedCompilationJob::ExecuteJob() {
141 : DisallowHeapAccess no_heap_access;
142 : // Delegate to the underlying implementation.
143 : DCHECK_EQ(state(), State::kReadyToExecute);
144 2114309 : ScopedTimer t(&time_taken_to_execute_);
145 4228391 : return UpdateState(ExecuteJobImpl(), State::kReadyToFinalize);
146 : }
147 :
148 2089345 : CompilationJob::Status UnoptimizedCompilationJob::FinalizeJob(
149 : Handle<SharedFunctionInfo> shared_info, Isolate* isolate) {
150 : DCHECK(ThreadId::Current().Equals(isolate->thread_id()));
151 : DisallowCodeDependencyChange no_dependency_change;
152 2089345 : DisallowJavascriptExecution no_js(isolate);
153 :
154 : // Delegate to the underlying implementation.
155 : DCHECK_EQ(state(), State::kReadyToFinalize);
156 4178723 : ScopedTimer t(&time_taken_to_finalize_);
157 4178761 : return UpdateState(FinalizeJobImpl(shared_info, isolate), State::kSucceeded);
158 : }
159 :
160 2089363 : void UnoptimizedCompilationJob::RecordCompilationStats(Isolate* isolate) const {
161 : int code_size;
162 2089363 : if (compilation_info()->has_bytecode_array()) {
163 2086378 : code_size = compilation_info()->bytecode_array()->SizeIncludingMetadata();
164 : } else {
165 : DCHECK(compilation_info()->has_asm_wasm_data());
166 2985 : code_size = compilation_info()->asm_wasm_data()->Size();
167 : }
168 :
169 : Counters* counters = isolate->counters();
170 : // TODO(4280): Rename counters from "baseline" to "unoptimized" eventually.
171 2089372 : counters->total_baseline_code_size()->Increment(code_size);
172 2089366 : counters->total_baseline_compile_count()->Increment(1);
173 :
174 : // TODO(5203): Add timers for each phase of compilation.
175 2089367 : }
176 :
177 2089345 : void UnoptimizedCompilationJob::RecordFunctionCompilation(
178 : CodeEventListener::LogEventsAndTags tag, Handle<SharedFunctionInfo> shared,
179 4178709 : Isolate* isolate) const {
180 : Handle<AbstractCode> abstract_code;
181 2089345 : if (compilation_info()->has_bytecode_array()) {
182 : abstract_code =
183 2086360 : Handle<AbstractCode>::cast(compilation_info()->bytecode_array());
184 : } else {
185 : DCHECK(compilation_info()->has_asm_wasm_data());
186 : abstract_code =
187 2985 : Handle<AbstractCode>::cast(BUILTIN_CODE(isolate, InstantiateAsmJs));
188 : }
189 :
190 2089356 : double time_taken_ms = time_taken_to_execute_.InMillisecondsF() +
191 2089355 : time_taken_to_finalize_.InMillisecondsF();
192 :
193 : LogFunctionCompilation(tag, shared, parse_info()->script(), abstract_code,
194 2089364 : false, time_taken_ms, isolate);
195 2089363 : }
196 :
197 : // ----------------------------------------------------------------------------
198 : // Implementation of OptimizedCompilationJob
199 :
200 454553 : CompilationJob::Status OptimizedCompilationJob::PrepareJob(Isolate* isolate) {
201 : DCHECK(ThreadId::Current().Equals(isolate->thread_id()));
202 452033 : DisallowJavascriptExecution no_js(isolate);
203 :
204 452873 : if (FLAG_trace_opt && compilation_info()->IsOptimizing()) {
205 840 : StdoutStream os;
206 1680 : os << "[compiling method " << Brief(*compilation_info()->closure())
207 1680 : << " using " << compiler_name_;
208 840 : if (compilation_info()->is_osr()) os << " OSR";
209 1680 : os << "]" << std::endl;
210 : }
211 :
212 : // Delegate to the underlying implementation.
213 : DCHECK_EQ(state(), State::kReadyToPrepare);
214 904059 : ScopedTimer t(&time_taken_to_prepare_);
215 904064 : return UpdateState(PrepareJobImpl(isolate), State::kReadyToExecute);
216 : }
217 :
218 451990 : CompilationJob::Status OptimizedCompilationJob::ExecuteJob() {
219 : DisallowHeapAccess no_heap_access;
220 : // Delegate to the underlying implementation.
221 : DCHECK_EQ(state(), State::kReadyToExecute);
222 451990 : ScopedTimer t(&time_taken_to_execute_);
223 903961 : return UpdateState(ExecuteJobImpl(), State::kReadyToFinalize);
224 : }
225 :
226 451862 : CompilationJob::Status OptimizedCompilationJob::FinalizeJob(Isolate* isolate) {
227 : DCHECK(ThreadId::Current().Equals(isolate->thread_id()));
228 451862 : DisallowJavascriptExecution no_js(isolate);
229 :
230 : // Delegate to the underlying implementation.
231 : DCHECK_EQ(state(), State::kReadyToFinalize);
232 903748 : ScopedTimer t(&time_taken_to_finalize_);
233 903748 : return UpdateState(FinalizeJobImpl(isolate), State::kSucceeded);
234 : }
235 :
236 55 : CompilationJob::Status OptimizedCompilationJob::RetryOptimization(
237 : BailoutReason reason) {
238 : DCHECK(compilation_info_->IsOptimizing());
239 55 : compilation_info_->RetryOptimization(reason);
240 55 : return UpdateState(FAILED, State::kFailed);
241 : }
242 :
243 14 : CompilationJob::Status OptimizedCompilationJob::AbortOptimization(
244 : BailoutReason reason) {
245 : DCHECK(compilation_info_->IsOptimizing());
246 14 : compilation_info_->AbortOptimization(reason);
247 14 : return UpdateState(FAILED, State::kFailed);
248 : }
249 :
250 451810 : void OptimizedCompilationJob::RecordCompilationStats() const {
251 : DCHECK(compilation_info()->IsOptimizing());
252 : Handle<JSFunction> function = compilation_info()->closure();
253 451810 : double ms_creategraph = time_taken_to_prepare_.InMillisecondsF();
254 451810 : double ms_optimize = time_taken_to_execute_.InMillisecondsF();
255 451810 : double ms_codegen = time_taken_to_finalize_.InMillisecondsF();
256 451810 : if (FLAG_trace_opt) {
257 840 : PrintF("[optimizing ");
258 1680 : function->ShortPrint();
259 : PrintF(" - took %0.3f, %0.3f, %0.3f ms]\n", ms_creategraph, ms_optimize,
260 840 : ms_codegen);
261 : }
262 451810 : if (FLAG_trace_opt_stats) {
263 : static double compilation_time = 0.0;
264 : static int compiled_functions = 0;
265 : static int code_size = 0;
266 :
267 0 : compilation_time += (ms_creategraph + ms_optimize + ms_codegen);
268 0 : compiled_functions++;
269 0 : code_size += function->shared()->SourceSize();
270 : PrintF("Compiled: %d functions with %d byte source size in %fms.\n",
271 0 : compiled_functions, code_size, compilation_time);
272 : }
273 451810 : }
274 :
275 451807 : void OptimizedCompilationJob::RecordFunctionCompilation(
276 1355427 : CodeEventListener::LogEventsAndTags tag, Isolate* isolate) const {
277 : Handle<AbstractCode> abstract_code =
278 451807 : Handle<AbstractCode>::cast(compilation_info()->code());
279 :
280 903618 : double time_taken_ms = time_taken_to_prepare_.InMillisecondsF() +
281 451809 : time_taken_to_execute_.InMillisecondsF() +
282 451809 : time_taken_to_finalize_.InMillisecondsF();
283 :
284 : Handle<Script> script(
285 903620 : Script::cast(compilation_info()->shared_info()->script()), isolate);
286 : LogFunctionCompilation(tag, compilation_info()->shared_info(), script,
287 451810 : abstract_code, true, time_taken_ms, isolate);
288 451810 : }
289 :
290 : // ----------------------------------------------------------------------------
291 : // Local helper methods that make up the compilation pipeline.
292 :
293 : namespace {
294 :
295 4225404 : bool UseAsmWasm(FunctionLiteral* literal, bool asm_wasm_broken) {
296 : // Check whether asm.js validation is enabled.
297 2112802 : if (!FLAG_validate_asm) return false;
298 :
299 : // Modules that have validated successfully, but were subsequently broken by
300 : // invalid module instantiation attempts are off limit forever.
301 2112802 : if (asm_wasm_broken) return false;
302 :
303 : // In stress mode we want to run the validator on everything.
304 2112602 : if (FLAG_stress_validate_asm) return true;
305 :
306 : // In general, we respect the "use asm" directive.
307 2112602 : return literal->scope()->IsAsmModule();
308 : }
309 :
310 2086378 : void InstallBytecodeArray(Handle<BytecodeArray> bytecode_array,
311 : Handle<SharedFunctionInfo> shared_info,
312 : ParseInfo* parse_info, Isolate* isolate) {
313 2086378 : if (!FLAG_interpreted_frames_native_stack) {
314 4172698 : shared_info->set_bytecode_array(*bytecode_array);
315 4172731 : return;
316 : }
317 :
318 : Handle<Code> code = isolate->factory()->CopyCode(Handle<Code>::cast(
319 35 : isolate->factory()->interpreter_entry_trampoline_for_profiling()));
320 :
321 : Handle<InterpreterData> interpreter_data = Handle<InterpreterData>::cast(
322 35 : isolate->factory()->NewStruct(INTERPRETER_DATA_TYPE, TENURED));
323 :
324 35 : interpreter_data->set_bytecode_array(*bytecode_array);
325 35 : interpreter_data->set_interpreter_trampoline(*code);
326 :
327 70 : shared_info->set_interpreter_data(*interpreter_data);
328 :
329 : Handle<Script> script = parse_info->script();
330 35 : Handle<AbstractCode> abstract_code = Handle<AbstractCode>::cast(code);
331 : int line_num =
332 35 : Script::GetLineNumber(script, shared_info->StartPosition()) + 1;
333 : int column_num =
334 35 : Script::GetColumnNumber(script, shared_info->StartPosition()) + 1;
335 70 : String script_name = script->name()->IsString()
336 35 : ? String::cast(script->name())
337 70 : : ReadOnlyRoots(isolate).empty_string();
338 : CodeEventListener::LogEventsAndTags log_tag = Logger::ToNativeByScript(
339 : CodeEventListener::INTERPRETED_FUNCTION_TAG, *script);
340 35 : PROFILE(isolate, CodeCreateEvent(log_tag, *abstract_code, *shared_info,
341 : script_name, line_num, column_num));
342 : }
343 :
344 2089359 : void InstallUnoptimizedCode(UnoptimizedCompilationInfo* compilation_info,
345 : Handle<SharedFunctionInfo> shared_info,
346 1080 : ParseInfo* parse_info, Isolate* isolate) {
347 : DCHECK_EQ(shared_info->language_mode(),
348 : compilation_info->literal()->language_mode());
349 :
350 : // Update the shared function info with the scope info.
351 2089359 : Handle<ScopeInfo> scope_info = compilation_info->scope()->scope_info();
352 2089370 : shared_info->set_scope_info(*scope_info);
353 :
354 2089374 : if (compilation_info->has_bytecode_array()) {
355 : DCHECK(!shared_info->HasBytecodeArray()); // Only compiled once.
356 : DCHECK(!compilation_info->has_asm_wasm_data());
357 : DCHECK(!shared_info->HasFeedbackMetadata());
358 :
359 : InstallBytecodeArray(compilation_info->bytecode_array(), shared_info,
360 2086389 : parse_info, isolate);
361 : if (FLAG_lite_mode) {
362 : // Clear the feedback metadata field. In lite mode we don't need feedback
363 : // metadata since we never allocate feedback vectors.
364 : shared_info->set_raw_outer_scope_info_or_feedback_metadata(
365 : ReadOnlyRoots(isolate).undefined_value());
366 : } else {
367 : Handle<FeedbackMetadata> feedback_metadata = FeedbackMetadata::New(
368 2086377 : isolate, compilation_info->feedback_vector_spec());
369 4172758 : shared_info->set_feedback_metadata(*feedback_metadata);
370 : }
371 : } else {
372 : DCHECK(compilation_info->has_asm_wasm_data());
373 5970 : shared_info->set_asm_wasm_data(*compilation_info->asm_wasm_data());
374 : shared_info->set_feedback_metadata(
375 5970 : ReadOnlyRoots(isolate).empty_feedback_metadata());
376 : }
377 :
378 : // Install coverage info on the shared function info.
379 6268071 : if (compilation_info->has_coverage_info() &&
380 2091517 : !shared_info->HasCoverageInfo()) {
381 : DCHECK(isolate->is_block_code_coverage());
382 : isolate->debug()->InstallCoverageInfo(shared_info,
383 1080 : compilation_info->coverage_info());
384 : }
385 2089357 : }
386 :
387 2013750 : void EnsureSharedFunctionInfosArrayOnScript(ParseInfo* parse_info,
388 : Isolate* isolate) {
389 : DCHECK(parse_info->is_toplevel());
390 : DCHECK(!parse_info->script().is_null());
391 2013750 : if (parse_info->script()->shared_function_infos()->length() > 0) {
392 : DCHECK_EQ(parse_info->script()->shared_function_infos()->length(),
393 : parse_info->max_function_literal_id() + 1);
394 0 : return;
395 : }
396 : Handle<WeakFixedArray> infos(isolate->factory()->NewWeakFixedArray(
397 1006876 : parse_info->max_function_literal_id() + 1));
398 1006871 : parse_info->script()->set_shared_function_infos(*infos);
399 : }
400 :
401 8925658 : void SetSharedFunctionFlagsFromLiteral(FunctionLiteral* literal,
402 : Handle<SharedFunctionInfo> shared_info) {
403 : // Don't overwrite values set by the bootstrapper.
404 2089347 : if (!shared_info->HasLength()) {
405 : shared_info->set_length(literal->function_length());
406 : }
407 : shared_info->set_has_duplicate_parameters(
408 4178699 : literal->has_duplicate_parameters());
409 4178704 : shared_info->set_is_iife(literal->is_iife());
410 2089359 : shared_info->SetExpectedNofPropertiesFromEstimate(literal);
411 2089352 : if (literal->dont_optimize_reason() != BailoutReason::kNoReason) {
412 0 : shared_info->DisableOptimization(literal->dont_optimize_reason());
413 : }
414 2089352 : }
415 :
416 2089345 : CompilationJob::Status FinalizeUnoptimizedCompilationJob(
417 2089345 : UnoptimizedCompilationJob* job, Handle<SharedFunctionInfo> shared_info,
418 : Isolate* isolate) {
419 2089345 : UnoptimizedCompilationInfo* compilation_info = job->compilation_info();
420 : ParseInfo* parse_info = job->parse_info();
421 :
422 2089345 : SetSharedFunctionFlagsFromLiteral(compilation_info->literal(), shared_info);
423 :
424 2089354 : CompilationJob::Status status = job->FinalizeJob(shared_info, isolate);
425 2089378 : if (status == CompilationJob::SUCCEEDED) {
426 2089380 : InstallUnoptimizedCode(compilation_info, shared_info, parse_info, isolate);
427 : CodeEventListener::LogEventsAndTags log_tag;
428 2089361 : if (parse_info->is_toplevel()) {
429 : log_tag = compilation_info->is_eval() ? CodeEventListener::EVAL_TAG
430 1516783 : : CodeEventListener::SCRIPT_TAG;
431 : } else {
432 : log_tag = parse_info->lazy_compile() ? CodeEventListener::LAZY_COMPILE_TAG
433 572578 : : CodeEventListener::FUNCTION_TAG;
434 : }
435 2089361 : job->RecordFunctionCompilation(log_tag, shared_info, isolate);
436 2089364 : job->RecordCompilationStats(isolate);
437 : }
438 2089364 : return status;
439 : }
440 :
441 596174 : std::unique_ptr<UnoptimizedCompilationJob> ExecuteUnoptimizedCompileJobs(
442 : ParseInfo* parse_info, FunctionLiteral* literal,
443 : AccountingAllocator* allocator,
444 : UnoptimizedCompilationJobList* inner_function_jobs) {
445 596174 : if (UseAsmWasm(literal, parse_info->is_asm_wasm_broken())) {
446 : std::unique_ptr<UnoptimizedCompilationJob> asm_job(
447 2249 : AsmJs::NewCompilationJob(parse_info, literal, allocator));
448 2249 : if (asm_job->ExecuteJob() == CompilationJob::SUCCEEDED) {
449 : return asm_job;
450 : }
451 : // asm.js validation failed, fall through to standard unoptimized compile.
452 : // Note: we rely on the fact that AsmJs jobs have done all validation in the
453 : // PrepareJob and ExecuteJob phases and can't fail in FinalizeJob with
454 : // with a validation error or another error that could be solve by falling
455 : // through to standard unoptimized compile.
456 : }
457 : std::vector<FunctionLiteral*> eager_inner_literals;
458 : std::unique_ptr<UnoptimizedCompilationJob> job(
459 : interpreter::Interpreter::NewCompilationJob(
460 594543 : parse_info, literal, allocator, &eager_inner_literals));
461 :
462 594551 : if (job->ExecuteJob() != CompilationJob::SUCCEEDED) {
463 : // Compilation failed, return null.
464 : return std::unique_ptr<UnoptimizedCompilationJob>();
465 : }
466 :
467 : // Recursively compile eager inner literals.
468 1203627 : for (FunctionLiteral* inner_literal : eager_inner_literals) {
469 : std::unique_ptr<UnoptimizedCompilationJob> inner_job(
470 : ExecuteUnoptimizedCompileJobs(parse_info, inner_literal, allocator,
471 14555 : inner_function_jobs));
472 : // Compilation failed, return null.
473 14555 : if (!inner_job) return std::unique_ptr<UnoptimizedCompilationJob>();
474 : inner_function_jobs->emplace_front(std::move(inner_job));
475 : }
476 :
477 : return job;
478 : }
479 :
480 581626 : std::unique_ptr<UnoptimizedCompilationJob> GenerateUnoptimizedCode(
481 581642 : ParseInfo* parse_info, AccountingAllocator* allocator,
482 : UnoptimizedCompilationJobList* inner_function_jobs) {
483 : DisallowHeapAccess no_heap_access;
484 : DCHECK(inner_function_jobs->empty());
485 :
486 581626 : if (!Compiler::Analyze(parse_info)) {
487 : return std::unique_ptr<UnoptimizedCompilationJob>();
488 : }
489 :
490 : // Prepare and execute compilation of the outer-most function.
491 : std::unique_ptr<UnoptimizedCompilationJob> outer_function_job(
492 : ExecuteUnoptimizedCompileJobs(parse_info, parse_info->literal(),
493 581642 : allocator, inner_function_jobs));
494 581629 : if (!outer_function_job) return std::unique_ptr<UnoptimizedCompilationJob>();
495 :
496 : // Character stream shouldn't be used again.
497 581626 : parse_info->ResetCharacterStream();
498 :
499 : return outer_function_job;
500 : }
501 :
502 1006735 : MaybeHandle<SharedFunctionInfo> GenerateUnoptimizedCodeForToplevel(
503 2013440 : Isolate* isolate, ParseInfo* parse_info, AccountingAllocator* allocator,
504 : IsCompiledScope* is_compiled_scope) {
505 1006735 : EnsureSharedFunctionInfosArrayOnScript(parse_info, isolate);
506 1006734 : parse_info->ast_value_factory()->Internalize(isolate);
507 :
508 1006735 : if (!Compiler::Analyze(parse_info)) return MaybeHandle<SharedFunctionInfo>();
509 1006721 : DeclarationScope::AllocateScopeInfos(parse_info, isolate);
510 :
511 : // Prepare and execute compilation of the outer-most function.
512 : // Create the SharedFunctionInfo and add it to the script's list.
513 1006722 : Handle<Script> script = parse_info->script();
514 : Handle<SharedFunctionInfo> top_level =
515 : isolate->factory()->NewSharedFunctionInfoForLiteral(parse_info->literal(),
516 1006722 : script, true);
517 :
518 : std::vector<FunctionLiteral*> functions_to_compile;
519 2013432 : functions_to_compile.push_back(parse_info->literal());
520 :
521 3530075 : while (!functions_to_compile.empty()) {
522 1516635 : FunctionLiteral* literal = functions_to_compile.back();
523 : functions_to_compile.pop_back();
524 : Handle<SharedFunctionInfo> shared_info =
525 1516635 : Compiler::GetSharedFunctionInfo(literal, script, isolate);
526 1516635 : if (shared_info->is_compiled()) continue;
527 1516635 : if (UseAsmWasm(literal, parse_info->is_asm_wasm_broken())) {
528 : std::unique_ptr<UnoptimizedCompilationJob> asm_job(
529 2294 : AsmJs::NewCompilationJob(parse_info, literal, allocator));
530 3667 : if (asm_job->ExecuteJob() == CompilationJob::SUCCEEDED &&
531 : FinalizeUnoptimizedCompilationJob(asm_job.get(), shared_info,
532 1373 : isolate) ==
533 : CompilationJob::SUCCEEDED) {
534 : continue;
535 : }
536 : // asm.js validation failed, fall through to standard unoptimized compile.
537 : // Note: we rely on the fact that AsmJs jobs have done all validation in
538 : // the PrepareJob and ExecuteJob phases and can't fail in FinalizeJob with
539 : // with a validation error or another error that could be solve by falling
540 : // through to standard unoptimized compile.
541 : }
542 :
543 : std::unique_ptr<UnoptimizedCompilationJob> job(
544 : interpreter::Interpreter::NewCompilationJob(
545 1515260 : parse_info, literal, allocator, &functions_to_compile));
546 :
547 3030522 : if (job->ExecuteJob() == CompilationJob::FAILED ||
548 1515256 : FinalizeUnoptimizedCompilationJob(job.get(), shared_info, isolate) ==
549 : CompilationJob::FAILED) {
550 0 : return MaybeHandle<SharedFunctionInfo>();
551 : }
552 :
553 1515262 : if (shared_info.is_identical_to(top_level)) {
554 : // Ensure that the top level function is retained.
555 1006721 : *is_compiled_scope = shared_info->is_compiled_scope();
556 : DCHECK(is_compiled_scope->is_compiled());
557 : }
558 : }
559 :
560 : // Character stream shouldn't be used again.
561 1006726 : parse_info->ResetCharacterStream();
562 :
563 1006720 : return top_level;
564 : }
565 :
566 568713 : bool FinalizeUnoptimizedCode(
567 : ParseInfo* parse_info, Isolate* isolate,
568 : Handle<SharedFunctionInfo> shared_info,
569 : UnoptimizedCompilationJob* outer_function_job,
570 : UnoptimizedCompilationJobList* inner_function_jobs) {
571 : DCHECK(AllowCompilation::IsAllowed(isolate));
572 :
573 : // TODO(rmcilroy): Clear native context in debug once AsmJS generates doesn't
574 : // rely on accessing native context during finalization.
575 :
576 : // Allocate scope infos for the literal.
577 568713 : DeclarationScope::AllocateScopeInfos(parse_info, isolate);
578 :
579 : // Finalize the outer-most function's compilation job.
580 568726 : if (FinalizeUnoptimizedCompilationJob(outer_function_job, shared_info,
581 568724 : isolate) != CompilationJob::SUCCEEDED) {
582 : return false;
583 : }
584 :
585 : // Finalize the inner functions' compilation jobs.
586 1141460 : for (auto&& inner_job : *inner_function_jobs) {
587 : Handle<SharedFunctionInfo> inner_shared_info =
588 : Compiler::GetSharedFunctionInfo(
589 : inner_job->compilation_info()->literal(), parse_info->script(),
590 4010 : isolate);
591 : // The inner function might be compiled already if compiling for debug.
592 4015 : if (inner_shared_info->is_compiled()) continue;
593 4005 : if (FinalizeUnoptimizedCompilationJob(inner_job.get(), inner_shared_info,
594 4005 : isolate) !=
595 : CompilationJob::SUCCEEDED) {
596 0 : return false;
597 : }
598 : }
599 :
600 : // Report any warnings generated during compilation.
601 568725 : if (parse_info->pending_error_handler()->has_pending_warnings()) {
602 : parse_info->pending_error_handler()->ReportWarnings(isolate,
603 554 : parse_info->script());
604 : }
605 :
606 : return true;
607 : }
608 :
609 470368 : V8_WARN_UNUSED_RESULT MaybeHandle<Code> GetCodeFromOptimizedCodeCache(
610 : Handle<JSFunction> function, BailoutId osr_offset) {
611 : RuntimeCallTimerScope runtimeTimer(
612 : function->GetIsolate(),
613 470371 : RuntimeCallCounterId::kCompileGetFromOptimizedCodeMap);
614 940741 : Handle<SharedFunctionInfo> shared(function->shared(), function->GetIsolate());
615 : DisallowHeapAllocation no_gc;
616 470370 : if (osr_offset.IsNone()) {
617 465197 : if (function->has_feedback_vector()) {
618 465197 : FeedbackVector feedback_vector = function->feedback_vector();
619 : feedback_vector->EvictOptimizedCodeMarkedForDeoptimization(
620 465198 : function->shared(), "GetCodeFromOptimizedCodeCache");
621 465192 : Code code = feedback_vector->optimized_code();
622 :
623 465192 : if (!code.is_null()) {
624 : // Caching of optimized code enabled and optimized code found.
625 : DCHECK(!code->marked_for_deoptimization());
626 : DCHECK(function->shared()->is_compiled());
627 0 : return Handle<Code>(code, feedback_vector->GetIsolate());
628 : }
629 : }
630 : }
631 470366 : return MaybeHandle<Code>();
632 : }
633 :
634 428663 : void ClearOptimizedCodeCache(OptimizedCompilationInfo* compilation_info) {
635 : Handle<JSFunction> function = compilation_info->closure();
636 428663 : if (compilation_info->osr_offset().IsNone()) {
637 : Handle<FeedbackVector> vector =
638 847644 : handle(function->feedback_vector(), function->GetIsolate());
639 423822 : vector->ClearOptimizationMarker();
640 : }
641 428661 : }
642 :
643 451810 : void InsertCodeIntoOptimizedCodeCache(
644 : OptimizedCompilationInfo* compilation_info) {
645 : Handle<Code> code = compilation_info->code();
646 451810 : if (code->kind() != Code::OPTIMIZED_FUNCTION) return; // Nothing to do.
647 :
648 : // Function context specialization folds-in the function context,
649 : // so no sharing can occur.
650 451810 : if (compilation_info->is_function_context_specializing()) {
651 : // Native context specialized code is not shared, so make sure the optimized
652 : // code cache is clear.
653 428663 : ClearOptimizedCodeCache(compilation_info);
654 428661 : return;
655 : }
656 :
657 : // Cache optimized context-specific code.
658 : Handle<JSFunction> function = compilation_info->closure();
659 46294 : Handle<SharedFunctionInfo> shared(function->shared(), function->GetIsolate());
660 46294 : Handle<Context> native_context(function->context()->native_context(),
661 46294 : function->GetIsolate());
662 23147 : if (compilation_info->osr_offset().IsNone()) {
663 : Handle<FeedbackVector> vector =
664 46170 : handle(function->feedback_vector(), function->GetIsolate());
665 23085 : FeedbackVector::SetOptimizedCode(vector, code);
666 : }
667 : }
668 :
669 889648 : bool GetOptimizedCodeNow(OptimizedCompilationJob* job, Isolate* isolate) {
670 : TimerEventScope<TimerEventRecompileSynchronous> timer(isolate);
671 : RuntimeCallTimerScope runtimeTimer(
672 444824 : isolate, RuntimeCallCounterId::kRecompileSynchronous);
673 0 : OptimizedCompilationInfo* compilation_info = job->compilation_info();
674 1334472 : TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
675 : "V8.RecompileSynchronous");
676 :
677 1334457 : if (job->PrepareJob(isolate) != CompilationJob::SUCCEEDED ||
678 889637 : job->ExecuteJob() != CompilationJob::SUCCEEDED ||
679 444806 : job->FinalizeJob(isolate) != CompilationJob::SUCCEEDED) {
680 37 : if (FLAG_trace_opt) {
681 0 : PrintF("[aborted optimizing ");
682 0 : compilation_info->closure()->ShortPrint();
683 : PrintF(" because: %s]\n",
684 0 : GetBailoutReason(compilation_info->bailout_reason()));
685 : }
686 : return false;
687 : }
688 :
689 : // Success!
690 444787 : job->RecordCompilationStats();
691 : DCHECK(!isolate->has_pending_exception());
692 444787 : InsertCodeIntoOptimizedCodeCache(compilation_info);
693 444785 : job->RecordFunctionCompilation(CodeEventListener::LAZY_COMPILE_TAG, isolate);
694 444787 : return true;
695 : }
696 :
697 14420 : bool GetOptimizedCodeLater(OptimizedCompilationJob* job, Isolate* isolate) {
698 : OptimizedCompilationInfo* compilation_info = job->compilation_info();
699 7210 : if (!isolate->optimizing_compile_dispatcher()->IsQueueAvailable()) {
700 0 : if (FLAG_trace_concurrent_recompilation) {
701 0 : PrintF(" ** Compilation queue full, will retry optimizing ");
702 0 : compilation_info->closure()->ShortPrint();
703 0 : PrintF(" later.\n");
704 : }
705 : return false;
706 : }
707 :
708 7210 : if (isolate->heap()->HighMemoryPressure()) {
709 0 : if (FLAG_trace_concurrent_recompilation) {
710 0 : PrintF(" ** High memory pressure, will retry optimizing ");
711 0 : compilation_info->closure()->ShortPrint();
712 0 : PrintF(" later.\n");
713 : }
714 : return false;
715 : }
716 :
717 : TimerEventScope<TimerEventRecompileSynchronous> timer(isolate);
718 : RuntimeCallTimerScope runtimeTimer(
719 7210 : isolate, RuntimeCallCounterId::kRecompileSynchronous);
720 21630 : TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
721 : "V8.RecompileSynchronous");
722 :
723 7210 : if (job->PrepareJob(isolate) != CompilationJob::SUCCEEDED) return false;
724 7210 : isolate->optimizing_compile_dispatcher()->QueueForOptimization(job);
725 :
726 7210 : if (FLAG_trace_concurrent_recompilation) {
727 0 : PrintF(" ** Queued ");
728 0 : compilation_info->closure()->ShortPrint();
729 0 : PrintF(" for concurrent optimization.\n");
730 : }
731 : return true;
732 : }
733 :
734 479849 : MaybeHandle<Code> GetOptimizedCode(Handle<JSFunction> function,
735 : ConcurrencyMode mode,
736 : BailoutId osr_offset = BailoutId::None(),
737 : JavaScriptFrame* osr_frame = nullptr) {
738 479852 : Isolate* isolate = function->GetIsolate();
739 1439511 : Handle<SharedFunctionInfo> shared(function->shared(), isolate);
740 :
741 : // Make sure we clear the optimization marker on the function so that we
742 : // don't try to re-optimize.
743 479856 : if (function->HasOptimizationMarker()) {
744 660957 : function->ClearOptimizationMarker();
745 : }
746 :
747 485324 : if (shared->optimization_disabled() &&
748 : shared->disable_optimization_reason() == BailoutReason::kNeverOptimize) {
749 56 : return MaybeHandle<Code>();
750 : }
751 :
752 959602 : if (isolate->debug()->needs_check_on_function_call()) {
753 : // Do not optimize when debugger needs to hook into every call.
754 9431 : return MaybeHandle<Code>();
755 : }
756 :
757 : Handle<Code> cached_code;
758 470367 : if (GetCodeFromOptimizedCodeCache(function, osr_offset)
759 940737 : .ToHandle(&cached_code)) {
760 0 : if (FLAG_trace_opt) {
761 0 : PrintF("[found optimized code for ");
762 0 : function->ShortPrint();
763 0 : if (!osr_offset.IsNone()) {
764 0 : PrintF(" at OSR AST id %d", osr_offset.ToInt());
765 : }
766 0 : PrintF("]\n");
767 : }
768 0 : return cached_code;
769 : }
770 :
771 : // Reset profiler ticks, function is no longer considered hot.
772 : DCHECK(shared->is_compiled());
773 940735 : function->feedback_vector()->set_profiler_ticks(0);
774 :
775 470369 : VMState<COMPILER> state(isolate);
776 : DCHECK(!isolate->has_pending_exception());
777 : PostponeInterruptsScope postpone(isolate);
778 940739 : bool has_script = shared->script()->IsScript();
779 : // BUG(5946): This DCHECK is necessary to make certain that we won't
780 : // tolerate the lack of a script without bytecode.
781 : DCHECK_IMPLIES(!has_script, shared->HasBytecodeArray());
782 : std::unique_ptr<OptimizedCompilationJob> job(
783 470368 : compiler::Pipeline::NewCompilationJob(isolate, function, has_script));
784 470367 : OptimizedCompilationInfo* compilation_info = job->compilation_info();
785 :
786 : compilation_info->SetOptimizingForOsr(osr_offset, osr_frame);
787 :
788 : // Do not use TurboFan if we need to be able to set break points.
789 470368 : if (compilation_info->shared_info()->HasBreakInfo()) {
790 562 : compilation_info->AbortOptimization(BailoutReason::kFunctionBeingDebugged);
791 562 : return MaybeHandle<Code>();
792 : }
793 :
794 : // Do not use TurboFan if optimization is disabled or function doesn't pass
795 : // turbo_filter.
796 921943 : if (!FLAG_opt || !shared->PassesFilter(FLAG_turbo_filter)) {
797 17775 : compilation_info->AbortOptimization(BailoutReason::kOptimizationDisabled);
798 17775 : return MaybeHandle<Code>();
799 : }
800 :
801 452030 : TimerEventScope<TimerEventOptimizeCode> optimize_code_timer(isolate);
802 : RuntimeCallTimerScope runtimeTimer(isolate,
803 452031 : RuntimeCallCounterId::kOptimizeCode);
804 1356078 : TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.OptimizeCode");
805 :
806 : // In case of concurrent recompilation, all handles below this point will be
807 : // allocated in a deferred handle scope that is detached and handed off to
808 : // the background thread when we return.
809 452022 : base::Optional<CompilationHandleScope> compilation;
810 452022 : if (mode == ConcurrencyMode::kConcurrent) {
811 7210 : compilation.emplace(isolate, compilation_info);
812 : }
813 :
814 : // All handles below will be canonicalized.
815 904055 : CanonicalHandleScope canonical(isolate);
816 :
817 : // Reopen handles in the new CompilationHandleScope.
818 452020 : compilation_info->ReopenHandlesInNewHandleScope(isolate);
819 :
820 452034 : if (mode == ConcurrencyMode::kConcurrent) {
821 7210 : if (GetOptimizedCodeLater(job.get(), isolate)) {
822 : job.release(); // The background recompile job owns this now.
823 :
824 : // Set the optimization marker and return a code object which checks it.
825 14420 : function->SetOptimizationMarker(OptimizationMarker::kInOptimizationQueue);
826 : DCHECK(function->IsInterpreted() ||
827 : (!function->is_compiled() && function->shared()->IsInterpreted()));
828 : DCHECK(function->shared()->HasBytecodeArray());
829 7210 : return BUILTIN_CODE(isolate, InterpreterEntryTrampoline);
830 : }
831 : } else {
832 444824 : if (GetOptimizedCodeNow(job.get(), isolate))
833 444786 : return compilation_info->code();
834 : }
835 :
836 37 : if (isolate->has_pending_exception()) isolate->clear_pending_exception();
837 37 : return MaybeHandle<Code>();
838 : }
839 :
840 660 : bool FailWithPendingException(Isolate* isolate, ParseInfo* parse_info,
841 : Compiler::ClearExceptionFlag flag) {
842 660 : if (flag == Compiler::CLEAR_EXCEPTION) {
843 271 : isolate->clear_pending_exception();
844 389 : } else if (!isolate->has_pending_exception()) {
845 31 : if (parse_info->pending_error_handler()->has_pending_error()) {
846 : parse_info->pending_error_handler()->ReportErrors(
847 29 : isolate, parse_info->script(), parse_info->ast_value_factory());
848 : } else {
849 2 : isolate->StackOverflow();
850 : }
851 : }
852 660 : return false;
853 : }
854 :
855 1006850 : void FinalizeScriptCompilation(Isolate* isolate, ParseInfo* parse_info) {
856 : Handle<Script> script = parse_info->script();
857 1006853 : script->set_compilation_state(Script::COMPILATION_STATE_COMPILED);
858 :
859 : // Register any pending parallel tasks with the associated SFI.
860 1006856 : if (parse_info->parallel_tasks()) {
861 15 : CompilerDispatcher* dispatcher = parse_info->parallel_tasks()->dispatcher();
862 85 : for (auto& it : *parse_info->parallel_tasks()) {
863 55 : FunctionLiteral* literal = it.first;
864 55 : CompilerDispatcher::JobId job_id = it.second;
865 : MaybeHandle<SharedFunctionInfo> maybe_shared_for_task =
866 55 : script->FindSharedFunctionInfo(isolate, literal);
867 : Handle<SharedFunctionInfo> shared_for_task;
868 55 : if (maybe_shared_for_task.ToHandle(&shared_for_task)) {
869 50 : dispatcher->RegisterSharedFunctionInfo(job_id, *shared_for_task);
870 : } else {
871 5 : dispatcher->AbortJob(job_id);
872 : }
873 : }
874 : }
875 1006856 : }
876 :
877 138 : MaybeHandle<SharedFunctionInfo> FinalizeTopLevel(
878 138 : ParseInfo* parse_info, Isolate* isolate,
879 : UnoptimizedCompilationJob* outer_function_job,
880 : UnoptimizedCompilationJobList* inner_function_jobs) {
881 : // Internalize ast values onto the heap.
882 138 : parse_info->ast_value_factory()->Internalize(isolate);
883 :
884 : // Create shared function infos for top level and shared function infos array
885 : // for inner functions.
886 138 : EnsureSharedFunctionInfosArrayOnScript(parse_info, isolate);
887 : DCHECK_EQ(kNoSourcePosition,
888 : parse_info->literal()->function_token_position());
889 : Handle<SharedFunctionInfo> shared_info =
890 : isolate->factory()->NewSharedFunctionInfoForLiteral(
891 138 : parse_info->literal(), parse_info->script(), true);
892 :
893 : // Finalize compilation of the unoptimized bytecode or asm-js data.
894 138 : if (!FinalizeUnoptimizedCode(parse_info, isolate, shared_info,
895 138 : outer_function_job, inner_function_jobs)) {
896 : FailWithPendingException(isolate, parse_info,
897 0 : Compiler::ClearExceptionFlag::KEEP_EXCEPTION);
898 0 : return MaybeHandle<SharedFunctionInfo>();
899 : }
900 :
901 138 : FinalizeScriptCompilation(isolate, parse_info);
902 :
903 138 : return shared_info;
904 : }
905 :
906 1112175 : MaybeHandle<SharedFunctionInfo> CompileToplevel(
907 2118921 : ParseInfo* parse_info, Isolate* isolate,
908 : IsCompiledScope* is_compiled_scope) {
909 : TimerEventScope<TimerEventCompileCode> top_level_timer(isolate);
910 3336531 : TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.CompileCode");
911 : DCHECK(ThreadId::Current().Equals(isolate->thread_id()));
912 :
913 : PostponeInterruptsScope postpone(isolate);
914 : DCHECK(!isolate->native_context().is_null());
915 : RuntimeCallTimerScope runtimeTimer(
916 : isolate, parse_info->is_eval() ? RuntimeCallCounterId::kCompileEval
917 1112184 : : RuntimeCallCounterId::kCompileScript);
918 : VMState<BYTECODE_COMPILER> state(isolate);
919 2224357 : if (parse_info->literal() == nullptr &&
920 1112181 : !parsing::ParseProgram(parse_info, isolate)) {
921 105440 : return MaybeHandle<SharedFunctionInfo>();
922 : }
923 : // Measure how long it takes to do the compilation; only take the
924 : // rest of the function into account to avoid overlap with the
925 : // parsing statistics.
926 : HistogramTimer* rate = parse_info->is_eval()
927 : ? isolate->counters()->compile_eval()
928 2013472 : : isolate->counters()->compile();
929 : HistogramTimerScope timer(rate);
930 3020212 : TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
931 : parse_info->is_eval() ? "V8.CompileEval" : "V8.Compile");
932 :
933 : // Generate the unoptimized bytecode or asm-js data.
934 : MaybeHandle<SharedFunctionInfo> shared_info =
935 : GenerateUnoptimizedCodeForToplevel(
936 1006738 : isolate, parse_info, isolate->allocator(), is_compiled_scope);
937 1006732 : if (shared_info.is_null()) {
938 : FailWithPendingException(isolate, parse_info,
939 18 : Compiler::ClearExceptionFlag::KEEP_EXCEPTION);
940 18 : return MaybeHandle<SharedFunctionInfo>();
941 : }
942 :
943 1006714 : FinalizeScriptCompilation(isolate, parse_info);
944 1006718 : return shared_info;
945 : }
946 :
947 13111 : std::unique_ptr<UnoptimizedCompilationJob> CompileOnBackgroundThread(
948 13111 : ParseInfo* parse_info, AccountingAllocator* allocator,
949 : UnoptimizedCompilationJobList* inner_function_jobs) {
950 : DisallowHeapAccess no_heap_access;
951 26222 : TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
952 : "V8.CompileCodeBackground");
953 : RuntimeCallTimerScope runtimeTimer(
954 : parse_info->runtime_call_stats(),
955 : parse_info->is_toplevel()
956 : ? parse_info->is_eval()
957 : ? RuntimeCallCounterId::kCompileBackgroundEval
958 : : RuntimeCallCounterId::kCompileBackgroundScript
959 39263 : : RuntimeCallCounterId::kCompileBackgroundFunction);
960 :
961 : // Generate the unoptimized bytecode or asm-js data.
962 : std::unique_ptr<UnoptimizedCompilationJob> outer_function_job(
963 13111 : GenerateUnoptimizedCode(parse_info, allocator, inner_function_jobs));
964 13111 : return outer_function_job;
965 : }
966 :
967 : } // namespace
968 :
969 13051 : BackgroundCompileTask::BackgroundCompileTask(ScriptStreamingData* streamed_data,
970 26102 : Isolate* isolate)
971 13051 : : info_(new ParseInfo(isolate)),
972 : stack_size_(i::FLAG_stack_size),
973 : worker_thread_runtime_call_stats_(
974 13051 : isolate->counters()->worker_thread_runtime_call_stats()),
975 : allocator_(isolate->allocator()),
976 78306 : timer_(isolate->counters()->compile_script_on_background()) {
977 : VMState<PARSER> state(isolate);
978 :
979 : // Prepare the data for the internalization phase and compilation phase, which
980 : // will happen in the main thread after parsing.
981 13051 : LOG(isolate, ScriptEvent(Logger::ScriptEventType::kStreamingCompile,
982 : info_->script_id()));
983 : info_->set_toplevel();
984 : info_->set_allow_lazy_parsing();
985 13051 : if (V8_UNLIKELY(info_->block_coverage_enabled())) {
986 0 : info_->AllocateSourceRangeMap();
987 : }
988 13051 : LanguageMode language_mode = construct_language_mode(FLAG_use_strict);
989 : info_->set_language_mode(
990 : stricter_language_mode(info_->language_mode(), language_mode));
991 :
992 : std::unique_ptr<Utf16CharacterStream> stream(ScannerStream::For(
993 26102 : streamed_data->source_stream.get(), streamed_data->encoding));
994 26102 : info_->set_character_stream(std::move(stream));
995 13051 : }
996 :
997 80 : BackgroundCompileTask::BackgroundCompileTask(
998 : AccountingAllocator* allocator, const ParseInfo* outer_parse_info,
999 80 : const AstRawString* function_name, const FunctionLiteral* function_literal,
1000 : WorkerThreadRuntimeCallStats* worker_thread_runtime_stats,
1001 : TimedHistogram* timer, int max_stack_size)
1002 : : info_(ParseInfo::FromParent(outer_parse_info, allocator, function_literal,
1003 : function_name)),
1004 : stack_size_(max_stack_size),
1005 : worker_thread_runtime_call_stats_(worker_thread_runtime_stats),
1006 : allocator_(allocator),
1007 160 : timer_(timer) {
1008 : DCHECK(outer_parse_info->is_toplevel());
1009 : DCHECK(!function_literal->is_toplevel());
1010 :
1011 : // Clone the character stream so both can be accessed independently.
1012 : std::unique_ptr<Utf16CharacterStream> character_stream =
1013 80 : outer_parse_info->character_stream()->Clone();
1014 160 : character_stream->Seek(function_literal->start_position());
1015 160 : info_->set_character_stream(std::move(character_stream));
1016 :
1017 : // Get preparsed scope data from the function literal.
1018 80 : if (function_literal->produced_preparse_data()) {
1019 : ZonePreparseData* serialized_data =
1020 20 : function_literal->produced_preparse_data()->Serialize(info_->zone());
1021 : info_->set_consumed_preparse_data(
1022 20 : ConsumedPreparseData::For(info_->zone(), serialized_data));
1023 : }
1024 80 : }
1025 :
1026 : BackgroundCompileTask::~BackgroundCompileTask() = default;
1027 :
1028 : namespace {
1029 :
1030 : // A scope object that ensures a parse info's runtime call stats, stack limit
1031 : // and on_background_thread fields is set correctly during worker-thread
1032 : // compile, and restores it after going out of scope.
1033 : class OffThreadParseInfoScope {
1034 : public:
1035 13122 : OffThreadParseInfoScope(
1036 : ParseInfo* parse_info,
1037 : WorkerThreadRuntimeCallStats* worker_thread_runtime_stats, int stack_size)
1038 : : parse_info_(parse_info),
1039 26244 : original_runtime_call_stats_(parse_info_->runtime_call_stats()),
1040 : original_stack_limit_(parse_info_->stack_limit()),
1041 39366 : worker_thread_scope_(worker_thread_runtime_stats) {
1042 13122 : parse_info_->set_on_background_thread(true);
1043 13122 : parse_info_->set_runtime_call_stats(worker_thread_scope_.Get());
1044 13122 : parse_info_->set_stack_limit(GetCurrentStackPosition() - stack_size * KB);
1045 13122 : }
1046 :
1047 26244 : ~OffThreadParseInfoScope() {
1048 13122 : parse_info_->set_stack_limit(original_stack_limit_);
1049 13122 : parse_info_->set_runtime_call_stats(original_runtime_call_stats_);
1050 13122 : parse_info_->set_on_background_thread(false);
1051 13122 : }
1052 :
1053 : private:
1054 : ParseInfo* parse_info_;
1055 : RuntimeCallStats* original_runtime_call_stats_;
1056 : uintptr_t original_stack_limit_;
1057 : WorkerThreadRuntimeCallStatsScope worker_thread_scope_;
1058 :
1059 : DISALLOW_COPY_AND_ASSIGN(OffThreadParseInfoScope);
1060 : };
1061 :
1062 : } // namespace
1063 :
1064 13122 : void BackgroundCompileTask::Run() {
1065 : DisallowHeapAllocation no_allocation;
1066 : DisallowHandleAllocation no_handles;
1067 : DisallowHeapAccess no_heap_access;
1068 :
1069 13122 : TimedHistogramScope timer(timer_);
1070 : OffThreadParseInfoScope off_thread_scope(
1071 39366 : info_.get(), worker_thread_runtime_call_stats_, stack_size_);
1072 39366 : TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
1073 : "BackgroundCompileTask::Run");
1074 : RuntimeCallTimerScope runtimeTimer(
1075 : info_->runtime_call_stats(),
1076 13122 : RuntimeCallCounterId::kCompileBackgroundCompileTask);
1077 :
1078 : // Update the character stream's runtime call stats.
1079 : info_->character_stream()->set_runtime_call_stats(
1080 13122 : info_->runtime_call_stats());
1081 :
1082 : // Parser needs to stay alive for finalizing the parsing on the main
1083 : // thread.
1084 13122 : parser_.reset(new Parser(info_.get()));
1085 13122 : parser_->InitializeEmptyScopeChain(info_.get());
1086 :
1087 13122 : parser_->ParseOnBackground(info_.get());
1088 13122 : if (info_->literal() != nullptr) {
1089 : // Parsing has succeeded, compile.
1090 26222 : outer_function_job_ = CompileOnBackgroundThread(info_.get(), allocator_,
1091 : &inner_function_jobs_);
1092 : }
1093 13122 : }
1094 :
1095 :
1096 : // ----------------------------------------------------------------------------
1097 : // Implementation of Compiler
1098 :
1099 3241894 : bool Compiler::Analyze(ParseInfo* parse_info) {
1100 : DCHECK_NOT_NULL(parse_info->literal());
1101 : RuntimeCallTimerScope runtimeTimer(
1102 : parse_info->runtime_call_stats(),
1103 : parse_info->on_background_thread()
1104 : ? RuntimeCallCounterId::kCompileBackgroundAnalyse
1105 3241894 : : RuntimeCallCounterId::kCompileAnalyse);
1106 1620955 : if (!Rewriter::Rewrite(parse_info)) return false;
1107 1620941 : if (!DeclarationScope::Analyze(parse_info)) return false;
1108 1620952 : return true;
1109 : }
1110 :
1111 0 : bool Compiler::ParseAndAnalyze(ParseInfo* parse_info,
1112 : Handle<SharedFunctionInfo> shared_info,
1113 : Isolate* isolate) {
1114 0 : if (!parsing::ParseAny(parse_info, shared_info, isolate)) {
1115 : return false;
1116 : }
1117 0 : return Compiler::Analyze(parse_info);
1118 : }
1119 :
1120 569187 : bool Compiler::Compile(Handle<SharedFunctionInfo> shared_info,
1121 : ClearExceptionFlag flag,
1122 : IsCompiledScope* is_compiled_scope) {
1123 : // We should never reach here if the function is already compiled.
1124 : DCHECK(!shared_info->is_compiled());
1125 : DCHECK(!is_compiled_scope->is_compiled());
1126 :
1127 1137715 : Isolate* isolate = shared_info->GetIsolate();
1128 : DCHECK(AllowCompilation::IsAllowed(isolate));
1129 : DCHECK(ThreadId::Current().Equals(isolate->thread_id()));
1130 : DCHECK(!isolate->has_pending_exception());
1131 : DCHECK(!shared_info->HasBytecodeArray());
1132 : VMState<BYTECODE_COMPILER> state(isolate);
1133 : PostponeInterruptsScope postpone(isolate);
1134 : TimerEventScope<TimerEventCompileCode> compile_timer(isolate);
1135 : RuntimeCallTimerScope runtimeTimer(isolate,
1136 569196 : RuntimeCallCounterId::kCompileFunction);
1137 1707591 : TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.CompileCode");
1138 1138398 : AggregatedHistogramTimerScope timer(isolate->counters()->compile_lazy());
1139 :
1140 : // Set up parse info.
1141 1138390 : ParseInfo parse_info(isolate, shared_info);
1142 : parse_info.set_lazy_compile();
1143 :
1144 : // Check if the compiler dispatcher has shared_info enqueued for compile.
1145 : CompilerDispatcher* dispatcher = isolate->compiler_dispatcher();
1146 569200 : if (dispatcher->IsEnqueued(shared_info)) {
1147 43 : if (!dispatcher->FinishNow(shared_info)) {
1148 0 : return FailWithPendingException(isolate, &parse_info, flag);
1149 : }
1150 43 : *is_compiled_scope = shared_info->is_compiled_scope();
1151 : DCHECK(is_compiled_scope->is_compiled());
1152 43 : return true;
1153 : }
1154 :
1155 569157 : if (shared_info->HasUncompiledDataWithPreparseData()) {
1156 : parse_info.set_consumed_preparse_data(ConsumedPreparseData::For(
1157 : isolate,
1158 : handle(
1159 39542 : shared_info->uncompiled_data_with_preparse_data()->preparse_data(),
1160 59313 : isolate)));
1161 : }
1162 :
1163 : // Parse and update ParseInfo with the results.
1164 569158 : if (!parsing::ParseAny(&parse_info, shared_info, isolate)) {
1165 628 : return FailWithPendingException(isolate, &parse_info, flag);
1166 : }
1167 :
1168 : // Generate the unoptimized bytecode or asm-js data.
1169 : UnoptimizedCompilationJobList inner_function_jobs;
1170 : std::unique_ptr<UnoptimizedCompilationJob> outer_function_job(
1171 : GenerateUnoptimizedCode(&parse_info, isolate->allocator(),
1172 568515 : &inner_function_jobs));
1173 568512 : if (!outer_function_job) {
1174 0 : return FailWithPendingException(isolate, &parse_info, flag);
1175 : }
1176 :
1177 : // Internalize ast values onto the heap.
1178 568512 : parse_info.ast_value_factory()->Internalize(isolate);
1179 :
1180 : // Finalize compilation of the unoptimized bytecode or asm-js data.
1181 568521 : if (!FinalizeUnoptimizedCode(&parse_info, isolate, shared_info,
1182 : outer_function_job.get(),
1183 568514 : &inner_function_jobs)) {
1184 0 : return FailWithPendingException(isolate, &parse_info, flag);
1185 : }
1186 :
1187 : DCHECK(!isolate->has_pending_exception());
1188 568525 : *is_compiled_scope = shared_info->is_compiled_scope();
1189 : DCHECK(is_compiled_scope->is_compiled());
1190 568527 : return true;
1191 : }
1192 :
1193 690335 : bool Compiler::Compile(Handle<JSFunction> function, ClearExceptionFlag flag,
1194 690357 : IsCompiledScope* is_compiled_scope) {
1195 : // We should never reach here if the function is already compiled or optimized
1196 : DCHECK(!function->is_compiled());
1197 : DCHECK(!function->IsOptimized());
1198 : DCHECK(!function->HasOptimizationMarker());
1199 : DCHECK(!function->HasOptimizedCode());
1200 :
1201 : // Reset the JSFunction if we are recompiling due to the bytecode having been
1202 : // flushed.
1203 690335 : function->ResetIfBytecodeFlushed();
1204 :
1205 : Isolate* isolate = function->GetIsolate();
1206 1380700 : Handle<SharedFunctionInfo> shared_info = handle(function->shared(), isolate);
1207 :
1208 : // Ensure shared function info is compiled.
1209 690350 : *is_compiled_scope = shared_info->is_compiled_scope();
1210 1256191 : if (!is_compiled_scope->is_compiled() &&
1211 565845 : !Compile(shared_info, flag, is_compiled_scope)) {
1212 : return false;
1213 : }
1214 : DCHECK(is_compiled_scope->is_compiled());
1215 1379457 : Handle<Code> code = handle(shared_info->GetCode(), isolate);
1216 :
1217 : // Allocate FeedbackVector for the JSFunction.
1218 689727 : JSFunction::EnsureFeedbackVector(function);
1219 :
1220 : // Optimize now if --always-opt is enabled.
1221 839212 : if (FLAG_always_opt && !function->shared()->HasAsmWasmData()) {
1222 149073 : if (FLAG_trace_opt) {
1223 0 : PrintF("[optimizing ");
1224 0 : function->ShortPrint();
1225 0 : PrintF(" because --always-opt]\n");
1226 : }
1227 : Handle<Code> opt_code;
1228 149074 : if (GetOptimizedCode(function, ConcurrencyMode::kNotConcurrent)
1229 298147 : .ToHandle(&opt_code)) {
1230 : code = opt_code;
1231 : }
1232 : }
1233 :
1234 : // Install code on closure.
1235 689723 : function->set_code(*code);
1236 :
1237 : // Check postconditions on success.
1238 : DCHECK(!isolate->has_pending_exception());
1239 : DCHECK(function->shared()->is_compiled());
1240 : DCHECK(function->is_compiled());
1241 689729 : return true;
1242 : }
1243 :
1244 67 : bool Compiler::FinalizeBackgroundCompileTask(
1245 : BackgroundCompileTask* task, Handle<SharedFunctionInfo> shared_info,
1246 : Isolate* isolate, ClearExceptionFlag flag) {
1247 134 : TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
1248 : "V8.FinalizeBackgroundCompileTask");
1249 : RuntimeCallTimerScope runtimeTimer(
1250 67 : isolate, RuntimeCallCounterId::kCompileFinalizeBackgroundCompileTask);
1251 : HandleScope scope(isolate);
1252 67 : ParseInfo* parse_info = task->info();
1253 : DCHECK(!parse_info->is_toplevel());
1254 : DCHECK(!shared_info->is_compiled());
1255 :
1256 134 : Handle<Script> script(Script::cast(shared_info->script()), isolate);
1257 67 : parse_info->set_script(script);
1258 :
1259 67 : task->parser()->UpdateStatistics(isolate, script);
1260 67 : task->parser()->HandleSourceURLComments(isolate, script);
1261 :
1262 133 : if (parse_info->literal() == nullptr || !task->outer_function_job()) {
1263 : // Parsing or compile failed on background thread - report error messages.
1264 4 : return FailWithPendingException(isolate, parse_info, flag);
1265 : }
1266 :
1267 : // Parsing has succeeded - finalize compilation.
1268 63 : parse_info->ast_value_factory()->Internalize(isolate);
1269 63 : if (!FinalizeUnoptimizedCode(parse_info, isolate, shared_info,
1270 : task->outer_function_job(),
1271 126 : task->inner_function_jobs())) {
1272 : // Finalization failed - throw an exception.
1273 0 : return FailWithPendingException(isolate, parse_info, flag);
1274 : }
1275 :
1276 : DCHECK(!isolate->has_pending_exception());
1277 : DCHECK(shared_info->is_compiled());
1278 67 : return true;
1279 : }
1280 :
1281 318562 : bool Compiler::CompileOptimized(Handle<JSFunction> function,
1282 : ConcurrencyMode mode) {
1283 318564 : if (function->IsOptimized()) return true;
1284 : Isolate* isolate = function->GetIsolate();
1285 : DCHECK(AllowCompilation::IsAllowed(isolate));
1286 :
1287 : // Start a compilation.
1288 : Handle<Code> code;
1289 637133 : if (!GetOptimizedCode(function, mode).ToHandle(&code)) {
1290 : // Optimization failed, get unoptimized code. Unoptimized code must exist
1291 : // already if we are optimizing.
1292 : DCHECK(!isolate->has_pending_exception());
1293 : DCHECK(function->shared()->is_compiled());
1294 : DCHECK(function->shared()->IsInterpreted());
1295 19930 : code = BUILTIN_CODE(isolate, InterpreterEntryTrampoline);
1296 : }
1297 :
1298 : // Install code on closure.
1299 318567 : function->set_code(*code);
1300 :
1301 : // Check postconditions on success.
1302 : DCHECK(!isolate->has_pending_exception());
1303 : DCHECK(function->shared()->is_compiled());
1304 : DCHECK(function->is_compiled());
1305 : DCHECK_IMPLIES(function->HasOptimizationMarker(),
1306 : function->IsInOptimizationQueue());
1307 : DCHECK_IMPLIES(function->HasOptimizationMarker(),
1308 : function->ChecksOptimizationMarker());
1309 : DCHECK_IMPLIES(function->IsInOptimizationQueue(),
1310 : mode == ConcurrencyMode::kConcurrent);
1311 318567 : return true;
1312 : }
1313 :
1314 761 : MaybeHandle<SharedFunctionInfo> Compiler::CompileForLiveEdit(
1315 : ParseInfo* parse_info, Isolate* isolate) {
1316 : IsCompiledScope is_compiled_scope;
1317 761 : return CompileToplevel(parse_info, isolate, &is_compiled_scope);
1318 : }
1319 :
1320 3550725 : MaybeHandle<JSFunction> Compiler::GetFunctionFromEval(
1321 : Handle<String> source, Handle<SharedFunctionInfo> outer_info,
1322 : Handle<Context> context, LanguageMode language_mode,
1323 : ParseRestriction restriction, int parameters_end_pos,
1324 : int eval_scope_position, int eval_position) {
1325 3550725 : Isolate* isolate = context->GetIsolate();
1326 : int source_length = source->length();
1327 3550725 : isolate->counters()->total_eval_size()->Increment(source_length);
1328 3550725 : isolate->counters()->total_compile_size()->Increment(source_length);
1329 :
1330 : // The cache lookup key needs to be aware of the separation between the
1331 : // parameters and the body to prevent this valid invocation:
1332 : // Function("", "function anonymous(\n/**/) {\n}");
1333 : // from adding an entry that falsely approves this invalid invocation:
1334 : // Function("\n/**/) {\nfunction anonymous(", "}");
1335 : // The actual eval_scope_position for indirect eval and CreateDynamicFunction
1336 : // is unused (just 0), which means it's an available field to use to indicate
1337 : // this separation. But to make sure we're not causing other false hits, we
1338 : // negate the scope position.
1339 7101450 : if (restriction == ONLY_SINGLE_FUNCTION_LITERAL &&
1340 3550725 : parameters_end_pos != kNoSourcePosition) {
1341 : // use the parameters_end_pos as the eval_scope_position in the eval cache.
1342 : DCHECK_EQ(eval_scope_position, 0);
1343 1088867 : eval_scope_position = -parameters_end_pos;
1344 : }
1345 : CompilationCache* compilation_cache = isolate->compilation_cache();
1346 : InfoCellPair eval_result = compilation_cache->LookupEval(
1347 3550725 : source, outer_info, context, language_mode, eval_scope_position);
1348 : Handle<FeedbackCell> feedback_cell;
1349 3550725 : if (eval_result.has_feedback_cell()) {
1350 2229873 : feedback_cell = handle(eval_result.feedback_cell(), isolate);
1351 : }
1352 :
1353 : Handle<SharedFunctionInfo> shared_info;
1354 : Handle<Script> script;
1355 : IsCompiledScope is_compiled_scope;
1356 : bool allow_eval_cache;
1357 3550725 : if (eval_result.has_shared()) {
1358 : shared_info = Handle<SharedFunctionInfo>(eval_result.shared(), isolate);
1359 5193940 : script = Handle<Script>(Script::cast(shared_info->script()), isolate);
1360 2596970 : is_compiled_scope = shared_info->is_compiled_scope();
1361 : allow_eval_cache = true;
1362 : } else {
1363 953755 : ParseInfo parse_info(isolate);
1364 : script = parse_info.CreateScript(
1365 953755 : isolate, source, OriginOptionsForEval(outer_info->script()));
1366 953755 : script->set_compilation_type(Script::COMPILATION_TYPE_EVAL);
1367 1907510 : script->set_eval_from_shared(*outer_info);
1368 953755 : if (eval_position == kNoSourcePosition) {
1369 : // If the position is missing, attempt to get the code offset by
1370 : // walking the stack. Do not translate the code offset into source
1371 : // position, but store it as negative value for lazy translation.
1372 355113 : StackTraceFrameIterator it(isolate);
1373 710226 : if (!it.done() && it.is_javascript()) {
1374 355113 : FrameSummary summary = FrameSummary::GetTop(it.javascript_frame());
1375 : script->set_eval_from_shared(
1376 1065339 : summary.AsJavaScript().function()->shared());
1377 1065339 : script->set_origin_options(OriginOptionsForEval(*summary.script()));
1378 355113 : eval_position = -summary.code_offset();
1379 : } else {
1380 : eval_position = 0;
1381 : }
1382 : }
1383 : script->set_eval_from_position(eval_position);
1384 :
1385 : parse_info.set_eval();
1386 : parse_info.set_language_mode(language_mode);
1387 : parse_info.set_parse_restriction(restriction);
1388 : parse_info.set_parameters_end_pos(parameters_end_pos);
1389 1907510 : if (!context->IsNativeContext()) {
1390 1131746 : parse_info.set_outer_scope_info(handle(context->scope_info(), isolate));
1391 : }
1392 : DCHECK(!parse_info.is_module());
1393 :
1394 953755 : if (!CompileToplevel(&parse_info, isolate, &is_compiled_scope)
1395 1907510 : .ToHandle(&shared_info)) {
1396 103825 : return MaybeHandle<JSFunction>();
1397 : }
1398 849930 : allow_eval_cache = parse_info.allow_eval_cache();
1399 : }
1400 :
1401 : // If caller is strict mode, the result must be in strict mode as well.
1402 : DCHECK(is_sloppy(language_mode) || is_strict(shared_info->language_mode()));
1403 :
1404 : Handle<JSFunction> result;
1405 3446900 : if (eval_result.has_shared()) {
1406 2596970 : if (eval_result.has_feedback_cell()) {
1407 : result = isolate->factory()->NewFunctionFromSharedFunctionInfo(
1408 2229873 : shared_info, context, feedback_cell, NOT_TENURED);
1409 : } else {
1410 : result = isolate->factory()->NewFunctionFromSharedFunctionInfo(
1411 367097 : shared_info, context, NOT_TENURED);
1412 367097 : JSFunction::EnsureFeedbackVector(result);
1413 367097 : if (allow_eval_cache) {
1414 : // Make sure to cache this result.
1415 : Handle<FeedbackCell> new_feedback_cell(result->raw_feedback_cell(),
1416 734194 : isolate);
1417 : compilation_cache->PutEval(source, outer_info, context, shared_info,
1418 367097 : new_feedback_cell, eval_scope_position);
1419 : }
1420 : }
1421 : } else {
1422 : result = isolate->factory()->NewFunctionFromSharedFunctionInfo(
1423 849930 : shared_info, context, NOT_TENURED);
1424 849930 : JSFunction::EnsureFeedbackVector(result);
1425 849930 : if (allow_eval_cache) {
1426 : // Add the SharedFunctionInfo and the LiteralsArray to the eval cache if
1427 : // we didn't retrieve from there.
1428 : Handle<FeedbackCell> new_feedback_cell(result->raw_feedback_cell(),
1429 1698852 : isolate);
1430 : compilation_cache->PutEval(source, outer_info, context, shared_info,
1431 849426 : new_feedback_cell, eval_scope_position);
1432 : }
1433 : }
1434 : DCHECK(is_compiled_scope.is_compiled());
1435 :
1436 3446900 : return result;
1437 : }
1438 :
1439 :
1440 96 : bool Compiler::CodeGenerationFromStringsAllowed(Isolate* isolate,
1441 : Handle<Context> context,
1442 : Handle<String> source) {
1443 : DCHECK(context->allow_code_gen_from_strings()->IsFalse(isolate));
1444 : // Check with callback if set.
1445 : AllowCodeGenerationFromStringsCallback callback =
1446 : isolate->allow_code_gen_callback();
1447 96 : if (callback == nullptr) {
1448 : // No callback set and code generation disallowed.
1449 : return false;
1450 : } else {
1451 : // Callback set. Let it decide if code generation is allowed.
1452 46 : VMState<EXTERNAL> state(isolate);
1453 46 : return callback(v8::Utils::ToLocal(context), v8::Utils::ToLocal(source));
1454 : }
1455 : }
1456 :
1457 1090374 : MaybeHandle<JSFunction> Compiler::GetFunctionFromString(
1458 : Handle<Context> context, Handle<String> source,
1459 : ParseRestriction restriction, int parameters_end_pos) {
1460 : Isolate* const isolate = context->GetIsolate();
1461 2180748 : Handle<Context> native_context(context->native_context(), isolate);
1462 :
1463 : // Check if native context allows code generation from
1464 : // strings. Throw an exception if it doesn't.
1465 2180793 : if (native_context->allow_code_gen_from_strings()->IsFalse(isolate) &&
1466 45 : !CodeGenerationFromStringsAllowed(isolate, native_context, source)) {
1467 : Handle<Object> error_message =
1468 33 : native_context->ErrorMessageForCodeGenerationFromStrings();
1469 33 : THROW_NEW_ERROR(isolate, NewEvalError(MessageTemplate::kCodeGenFromStrings,
1470 : error_message),
1471 : JSFunction);
1472 : }
1473 :
1474 : // Compile source string in the native context.
1475 : int eval_scope_position = 0;
1476 : int eval_position = kNoSourcePosition;
1477 : Handle<SharedFunctionInfo> outer_info(
1478 2180682 : native_context->empty_function()->shared(), isolate);
1479 : return Compiler::GetFunctionFromEval(
1480 : source, outer_info, native_context, LanguageMode::kSloppy, restriction,
1481 1090341 : parameters_end_pos, eval_scope_position, eval_position);
1482 : }
1483 :
1484 : namespace {
1485 :
1486 : struct ScriptCompileTimerScope {
1487 : public:
1488 : // TODO(leszeks): There are too many blink-specific entries in this enum,
1489 : // figure out a way to push produce/hit-isolate-cache/consume/consume-failed
1490 : // back up the API and log them in blink instead.
1491 : enum class CacheBehaviour {
1492 : kProduceCodeCache,
1493 : kHitIsolateCacheWhenNoCache,
1494 : kConsumeCodeCache,
1495 : kConsumeCodeCacheFailed,
1496 : kNoCacheBecauseInlineScript,
1497 : kNoCacheBecauseScriptTooSmall,
1498 : kNoCacheBecauseCacheTooCold,
1499 : kNoCacheNoReason,
1500 : kNoCacheBecauseNoResource,
1501 : kNoCacheBecauseInspector,
1502 : kNoCacheBecauseCachingDisabled,
1503 : kNoCacheBecauseModule,
1504 : kNoCacheBecauseStreamingSource,
1505 : kNoCacheBecauseV8Extension,
1506 : kHitIsolateCacheWhenProduceCodeCache,
1507 : kHitIsolateCacheWhenConsumeCodeCache,
1508 : kNoCacheBecauseExtensionModule,
1509 : kNoCacheBecausePacScript,
1510 : kNoCacheBecauseInDocumentWrite,
1511 : kNoCacheBecauseResourceWithNoCacheHandler,
1512 : kHitIsolateCacheWhenStreamingSource,
1513 : kCount
1514 : };
1515 :
1516 288198 : explicit ScriptCompileTimerScope(
1517 : Isolate* isolate, ScriptCompiler::NoCacheReason no_cache_reason)
1518 : : isolate_(isolate),
1519 : all_scripts_histogram_scope_(isolate->counters()->compile_script(),
1520 : true),
1521 : no_cache_reason_(no_cache_reason),
1522 : hit_isolate_cache_(false),
1523 : producing_code_cache_(false),
1524 : consuming_code_cache_(false),
1525 864605 : consuming_code_cache_failed_(false) {}
1526 :
1527 288196 : ~ScriptCompileTimerScope() {
1528 288196 : CacheBehaviour cache_behaviour = GetCacheBehaviour();
1529 :
1530 : Histogram* cache_behaviour_histogram =
1531 576380 : isolate_->counters()->compile_script_cache_behaviour();
1532 : // Sanity check that the histogram has exactly one bin per enum entry.
1533 : DCHECK_EQ(0, cache_behaviour_histogram->min());
1534 : DCHECK_EQ(static_cast<int>(CacheBehaviour::kCount),
1535 : cache_behaviour_histogram->max() + 1);
1536 : DCHECK_EQ(static_cast<int>(CacheBehaviour::kCount),
1537 : cache_behaviour_histogram->num_buckets());
1538 288190 : cache_behaviour_histogram->AddSample(static_cast<int>(cache_behaviour));
1539 :
1540 : histogram_scope_.set_histogram(
1541 288199 : GetCacheBehaviourTimedHistogram(cache_behaviour));
1542 288200 : }
1543 :
1544 130174 : void set_hit_isolate_cache() { hit_isolate_cache_ = true; }
1545 :
1546 : void set_producing_code_cache() { producing_code_cache_ = true; }
1547 :
1548 488 : void set_consuming_code_cache() { consuming_code_cache_ = true; }
1549 :
1550 : void set_consuming_code_cache_failed() {
1551 30 : consuming_code_cache_failed_ = true;
1552 : }
1553 :
1554 : private:
1555 : Isolate* isolate_;
1556 : LazyTimedHistogramScope histogram_scope_;
1557 : // TODO(leszeks): This timer is the sum of the other times, consider removing
1558 : // it to save space.
1559 : HistogramTimerScope all_scripts_histogram_scope_;
1560 : ScriptCompiler::NoCacheReason no_cache_reason_;
1561 : bool hit_isolate_cache_;
1562 : bool producing_code_cache_;
1563 : bool consuming_code_cache_;
1564 : bool consuming_code_cache_failed_;
1565 :
1566 288187 : CacheBehaviour GetCacheBehaviour() {
1567 288187 : if (producing_code_cache_) {
1568 0 : if (hit_isolate_cache_) {
1569 : return CacheBehaviour::kHitIsolateCacheWhenProduceCodeCache;
1570 : } else {
1571 0 : return CacheBehaviour::kProduceCodeCache;
1572 : }
1573 : }
1574 :
1575 288187 : if (consuming_code_cache_) {
1576 249 : if (hit_isolate_cache_) {
1577 : return CacheBehaviour::kHitIsolateCacheWhenConsumeCodeCache;
1578 244 : } else if (consuming_code_cache_failed_) {
1579 : return CacheBehaviour::kConsumeCodeCacheFailed;
1580 : }
1581 214 : return CacheBehaviour::kConsumeCodeCache;
1582 : }
1583 :
1584 287938 : if (hit_isolate_cache_) {
1585 130169 : if (no_cache_reason_ == ScriptCompiler::kNoCacheBecauseStreamingSource) {
1586 : return CacheBehaviour::kHitIsolateCacheWhenStreamingSource;
1587 : }
1588 117266 : return CacheBehaviour::kHitIsolateCacheWhenNoCache;
1589 : }
1590 :
1591 157769 : switch (no_cache_reason_) {
1592 : case ScriptCompiler::kNoCacheBecauseInlineScript:
1593 : return CacheBehaviour::kNoCacheBecauseInlineScript;
1594 : case ScriptCompiler::kNoCacheBecauseScriptTooSmall:
1595 0 : return CacheBehaviour::kNoCacheBecauseScriptTooSmall;
1596 : case ScriptCompiler::kNoCacheBecauseCacheTooCold:
1597 0 : return CacheBehaviour::kNoCacheBecauseCacheTooCold;
1598 : case ScriptCompiler::kNoCacheNoReason:
1599 154141 : return CacheBehaviour::kNoCacheNoReason;
1600 : case ScriptCompiler::kNoCacheBecauseNoResource:
1601 0 : return CacheBehaviour::kNoCacheBecauseNoResource;
1602 : case ScriptCompiler::kNoCacheBecauseInspector:
1603 261 : return CacheBehaviour::kNoCacheBecauseInspector;
1604 : case ScriptCompiler::kNoCacheBecauseCachingDisabled:
1605 0 : return CacheBehaviour::kNoCacheBecauseCachingDisabled;
1606 : case ScriptCompiler::kNoCacheBecauseModule:
1607 0 : return CacheBehaviour::kNoCacheBecauseModule;
1608 : case ScriptCompiler::kNoCacheBecauseStreamingSource:
1609 148 : return CacheBehaviour::kNoCacheBecauseStreamingSource;
1610 : case ScriptCompiler::kNoCacheBecauseV8Extension:
1611 3220 : return CacheBehaviour::kNoCacheBecauseV8Extension;
1612 : case ScriptCompiler::kNoCacheBecauseExtensionModule:
1613 0 : return CacheBehaviour::kNoCacheBecauseExtensionModule;
1614 : case ScriptCompiler::kNoCacheBecausePacScript:
1615 0 : return CacheBehaviour::kNoCacheBecausePacScript;
1616 : case ScriptCompiler::kNoCacheBecauseInDocumentWrite:
1617 0 : return CacheBehaviour::kNoCacheBecauseInDocumentWrite;
1618 : case ScriptCompiler::kNoCacheBecauseResourceWithNoCacheHandler:
1619 0 : return CacheBehaviour::kNoCacheBecauseResourceWithNoCacheHandler;
1620 : case ScriptCompiler::kNoCacheBecauseDeferredProduceCodeCache: {
1621 0 : if (hit_isolate_cache_) {
1622 : return CacheBehaviour::kHitIsolateCacheWhenProduceCodeCache;
1623 : } else {
1624 0 : return CacheBehaviour::kProduceCodeCache;
1625 : }
1626 : }
1627 : }
1628 0 : UNREACHABLE();
1629 : }
1630 :
1631 288198 : TimedHistogram* GetCacheBehaviourTimedHistogram(
1632 : CacheBehaviour cache_behaviour) {
1633 288198 : switch (cache_behaviour) {
1634 : case CacheBehaviour::kProduceCodeCache:
1635 : // Even if we hit the isolate's compilation cache, we currently recompile
1636 : // when we want to produce the code cache.
1637 : case CacheBehaviour::kHitIsolateCacheWhenProduceCodeCache:
1638 0 : return isolate_->counters()->compile_script_with_produce_cache();
1639 : case CacheBehaviour::kHitIsolateCacheWhenNoCache:
1640 : case CacheBehaviour::kHitIsolateCacheWhenConsumeCodeCache:
1641 : case CacheBehaviour::kHitIsolateCacheWhenStreamingSource:
1642 260348 : return isolate_->counters()->compile_script_with_isolate_cache_hit();
1643 : case CacheBehaviour::kConsumeCodeCacheFailed:
1644 60 : return isolate_->counters()->compile_script_consume_failed();
1645 : case CacheBehaviour::kConsumeCodeCache:
1646 428 : return isolate_->counters()->compile_script_with_consume_cache();
1647 :
1648 : case CacheBehaviour::kNoCacheBecauseInlineScript:
1649 : return isolate_->counters()
1650 0 : ->compile_script_no_cache_because_inline_script();
1651 : case CacheBehaviour::kNoCacheBecauseScriptTooSmall:
1652 : return isolate_->counters()
1653 0 : ->compile_script_no_cache_because_script_too_small();
1654 : case CacheBehaviour::kNoCacheBecauseCacheTooCold:
1655 : return isolate_->counters()
1656 0 : ->compile_script_no_cache_because_cache_too_cold();
1657 :
1658 : // Aggregate all the other "no cache" counters into a single histogram, to
1659 : // save space.
1660 : case CacheBehaviour::kNoCacheNoReason:
1661 : case CacheBehaviour::kNoCacheBecauseNoResource:
1662 : case CacheBehaviour::kNoCacheBecauseInspector:
1663 : case CacheBehaviour::kNoCacheBecauseCachingDisabled:
1664 : // TODO(leszeks): Consider counting separately once modules are more
1665 : // common.
1666 : case CacheBehaviour::kNoCacheBecauseModule:
1667 : // TODO(leszeks): Count separately or remove entirely once we have
1668 : // background compilation.
1669 : case CacheBehaviour::kNoCacheBecauseStreamingSource:
1670 : case CacheBehaviour::kNoCacheBecauseV8Extension:
1671 : case CacheBehaviour::kNoCacheBecauseExtensionModule:
1672 : case CacheBehaviour::kNoCacheBecausePacScript:
1673 : case CacheBehaviour::kNoCacheBecauseInDocumentWrite:
1674 : case CacheBehaviour::kNoCacheBecauseResourceWithNoCacheHandler:
1675 315560 : return isolate_->counters()->compile_script_no_cache_other();
1676 :
1677 : case CacheBehaviour::kCount:
1678 0 : UNREACHABLE();
1679 : }
1680 0 : UNREACHABLE();
1681 : }
1682 : };
1683 :
1684 315618 : Handle<Script> NewScript(Isolate* isolate, ParseInfo* parse_info,
1685 : Handle<String> source,
1686 : Compiler::ScriptDetails script_details,
1687 : ScriptOriginOptions origin_options,
1688 : NativesFlag natives) {
1689 : // Create a script object describing the script to be compiled.
1690 : Handle<Script> script =
1691 157810 : parse_info->CreateScript(isolate, source, origin_options, natives);
1692 : Handle<Object> script_name;
1693 157815 : if (script_details.name_obj.ToHandle(&script_name)) {
1694 90514 : script->set_name(*script_name);
1695 90509 : script->set_line_offset(script_details.line_offset);
1696 90509 : script->set_column_offset(script_details.column_offset);
1697 : }
1698 : Handle<Object> source_map_url;
1699 157808 : if (script_details.source_map_url.ToHandle(&source_map_url)) {
1700 856 : script->set_source_mapping_url(*source_map_url);
1701 : }
1702 : Handle<FixedArray> host_defined_options;
1703 157808 : if (script_details.host_defined_options.ToHandle(&host_defined_options)) {
1704 146004 : script->set_host_defined_options(*host_defined_options);
1705 : }
1706 157862 : LOG(isolate, ScriptDetails(*script));
1707 157808 : return script;
1708 : }
1709 :
1710 : } // namespace
1711 :
1712 275068 : MaybeHandle<SharedFunctionInfo> Compiler::GetSharedFunctionInfoForScript(
1713 275073 : Isolate* isolate, Handle<String> source,
1714 : const Compiler::ScriptDetails& script_details,
1715 : ScriptOriginOptions origin_options, v8::Extension* extension,
1716 : ScriptData* cached_data, ScriptCompiler::CompileOptions compile_options,
1717 : ScriptCompiler::NoCacheReason no_cache_reason, NativesFlag natives) {
1718 275068 : ScriptCompileTimerScope compile_timer(isolate, no_cache_reason);
1719 :
1720 : if (compile_options == ScriptCompiler::kNoCompileOptions ||
1721 : compile_options == ScriptCompiler::kEagerCompile) {
1722 : DCHECK_NULL(cached_data);
1723 : } else {
1724 : DCHECK(compile_options == ScriptCompiler::kConsumeCodeCache);
1725 : DCHECK(cached_data);
1726 : DCHECK_NULL(extension);
1727 : }
1728 : int source_length = source->length();
1729 275072 : isolate->counters()->total_load_size()->Increment(source_length);
1730 275073 : isolate->counters()->total_compile_size()->Increment(source_length);
1731 :
1732 275073 : LanguageMode language_mode = construct_language_mode(FLAG_use_strict);
1733 : CompilationCache* compilation_cache = isolate->compilation_cache();
1734 :
1735 : // Do a lookup in the compilation cache but not for extensions.
1736 : MaybeHandle<SharedFunctionInfo> maybe_result;
1737 : IsCompiledScope is_compiled_scope;
1738 275073 : if (extension == nullptr) {
1739 : bool can_consume_code_cache =
1740 271838 : compile_options == ScriptCompiler::kConsumeCodeCache;
1741 271838 : if (can_consume_code_cache) {
1742 : compile_timer.set_consuming_code_cache();
1743 : }
1744 :
1745 : // First check per-isolate compilation cache.
1746 : maybe_result = compilation_cache->LookupScript(
1747 : source, script_details.name_obj, script_details.line_offset,
1748 : script_details.column_offset, origin_options, isolate->native_context(),
1749 543676 : language_mode);
1750 271838 : if (!maybe_result.is_null()) {
1751 : compile_timer.set_hit_isolate_cache();
1752 154567 : } else if (can_consume_code_cache) {
1753 : compile_timer.set_consuming_code_cache();
1754 : // Then check cached code provided by embedder.
1755 239 : HistogramTimerScope timer(isolate->counters()->compile_deserialize());
1756 : RuntimeCallTimerScope runtimeTimer(
1757 239 : isolate, RuntimeCallCounterId::kCompileDeserialize);
1758 717 : TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
1759 : "V8.CompileDeserialize");
1760 : Handle<SharedFunctionInfo> inner_result;
1761 239 : if (CodeSerializer::Deserialize(isolate, cached_data, source,
1762 : origin_options)
1763 478 : .ToHandle(&inner_result)) {
1764 : // Promote to per-isolate compilation cache.
1765 209 : is_compiled_scope = inner_result->is_compiled_scope();
1766 : DCHECK(is_compiled_scope.is_compiled());
1767 : compilation_cache->PutScript(source, isolate->native_context(),
1768 418 : language_mode, inner_result);
1769 418 : Handle<Script> script(Script::cast(inner_result->script()), isolate);
1770 : maybe_result = inner_result;
1771 : } else {
1772 : // Deserializer failed. Fall through to compile.
1773 : compile_timer.set_consuming_code_cache_failed();
1774 : }
1775 : }
1776 : }
1777 :
1778 275073 : if (maybe_result.is_null()) {
1779 157593 : ParseInfo parse_info(isolate);
1780 : // No cache entry found compile the script.
1781 : NewScript(isolate, &parse_info, source, script_details, origin_options,
1782 157593 : natives);
1783 :
1784 : // Compile the function and add it to the isolate cache.
1785 157585 : if (origin_options.IsModule()) parse_info.set_module();
1786 : parse_info.set_extension(extension);
1787 : parse_info.set_eager(compile_options == ScriptCompiler::kEagerCompile);
1788 :
1789 : parse_info.set_language_mode(
1790 : stricter_language_mode(parse_info.language_mode(), language_mode));
1791 157585 : maybe_result = CompileToplevel(&parse_info, isolate, &is_compiled_scope);
1792 : Handle<SharedFunctionInfo> result;
1793 311937 : if (extension == nullptr && maybe_result.ToHandle(&result)) {
1794 : DCHECK(is_compiled_scope.is_compiled());
1795 : compilation_cache->PutScript(source, isolate->native_context(),
1796 305588 : language_mode, result);
1797 4785 : } else if (maybe_result.is_null() && natives != EXTENSION_CODE &&
1798 : natives != NATIVES_CODE) {
1799 1564 : isolate->ReportPendingMessages();
1800 157579 : }
1801 : }
1802 :
1803 275073 : return maybe_result;
1804 : }
1805 :
1806 79 : MaybeHandle<JSFunction> Compiler::GetWrappedFunction(
1807 : Handle<String> source, Handle<FixedArray> arguments,
1808 : Handle<Context> context, const Compiler::ScriptDetails& script_details,
1809 : ScriptOriginOptions origin_options, ScriptData* cached_data,
1810 : v8::ScriptCompiler::CompileOptions compile_options,
1811 : v8::ScriptCompiler::NoCacheReason no_cache_reason) {
1812 : Isolate* isolate = context->GetIsolate();
1813 79 : ScriptCompileTimerScope compile_timer(isolate, no_cache_reason);
1814 :
1815 : if (compile_options == ScriptCompiler::kNoCompileOptions ||
1816 : compile_options == ScriptCompiler::kEagerCompile) {
1817 : DCHECK_NULL(cached_data);
1818 : } else {
1819 : DCHECK(compile_options == ScriptCompiler::kConsumeCodeCache);
1820 : DCHECK(cached_data);
1821 : }
1822 :
1823 : int source_length = source->length();
1824 79 : isolate->counters()->total_compile_size()->Increment(source_length);
1825 :
1826 79 : LanguageMode language_mode = construct_language_mode(FLAG_use_strict);
1827 :
1828 : MaybeHandle<SharedFunctionInfo> maybe_result;
1829 : bool can_consume_code_cache =
1830 : compile_options == ScriptCompiler::kConsumeCodeCache;
1831 79 : if (can_consume_code_cache) {
1832 : compile_timer.set_consuming_code_cache();
1833 : // Then check cached code provided by embedder.
1834 5 : HistogramTimerScope timer(isolate->counters()->compile_deserialize());
1835 : RuntimeCallTimerScope runtimeTimer(
1836 5 : isolate, RuntimeCallCounterId::kCompileDeserialize);
1837 15 : TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
1838 : "V8.CompileDeserialize");
1839 : maybe_result = CodeSerializer::Deserialize(isolate, cached_data, source,
1840 5 : origin_options);
1841 5 : if (maybe_result.is_null()) {
1842 : // Deserializer failed. Fall through to compile.
1843 : compile_timer.set_consuming_code_cache_failed();
1844 : }
1845 : }
1846 :
1847 : Handle<SharedFunctionInfo> wrapped;
1848 : Handle<Script> script;
1849 : IsCompiledScope is_compiled_scope;
1850 79 : if (!maybe_result.ToHandle(&wrapped)) {
1851 74 : ParseInfo parse_info(isolate);
1852 : script = NewScript(isolate, &parse_info, source, script_details,
1853 74 : origin_options, NOT_NATIVES_CODE);
1854 148 : script->set_wrapped_arguments(*arguments);
1855 :
1856 : parse_info.set_eval(); // Use an eval scope as declaration scope.
1857 : parse_info.set_wrapped_as_function();
1858 : // parse_info.set_eager(compile_options == ScriptCompiler::kEagerCompile);
1859 148 : if (!context->IsNativeContext()) {
1860 38 : parse_info.set_outer_scope_info(handle(context->scope_info(), isolate));
1861 : }
1862 : parse_info.set_language_mode(
1863 : stricter_language_mode(parse_info.language_mode(), language_mode));
1864 :
1865 : Handle<SharedFunctionInfo> top_level;
1866 74 : maybe_result = CompileToplevel(&parse_info, isolate, &is_compiled_scope);
1867 74 : if (maybe_result.is_null()) isolate->ReportPendingMessages();
1868 74 : ASSIGN_RETURN_ON_EXCEPTION(isolate, top_level, maybe_result, JSFunction);
1869 :
1870 64 : SharedFunctionInfo::ScriptIterator infos(isolate, *script);
1871 256 : for (SharedFunctionInfo info = infos.Next(); !info.is_null();
1872 : info = infos.Next()) {
1873 128 : if (info->is_wrapped()) {
1874 : wrapped = Handle<SharedFunctionInfo>(info, isolate);
1875 64 : break;
1876 : }
1877 : }
1878 64 : DCHECK(!wrapped.is_null());
1879 : } else {
1880 5 : is_compiled_scope = wrapped->is_compiled_scope();
1881 10 : script = Handle<Script>(Script::cast(wrapped->script()), isolate);
1882 : }
1883 : DCHECK(is_compiled_scope.is_compiled());
1884 :
1885 : return isolate->factory()->NewFunctionFromSharedFunctionInfo(wrapped, context,
1886 69 : NOT_TENURED);
1887 : }
1888 :
1889 : MaybeHandle<SharedFunctionInfo>
1890 13051 : Compiler::GetSharedFunctionInfoForStreamedScript(
1891 13051 : Isolate* isolate, Handle<String> source,
1892 : const ScriptDetails& script_details, ScriptOriginOptions origin_options,
1893 : ScriptStreamingData* streaming_data) {
1894 : ScriptCompileTimerScope compile_timer(
1895 13051 : isolate, ScriptCompiler::kNoCacheBecauseStreamingSource);
1896 : PostponeInterruptsScope postpone(isolate);
1897 :
1898 : int source_length = source->length();
1899 13051 : isolate->counters()->total_load_size()->Increment(source_length);
1900 13051 : isolate->counters()->total_compile_size()->Increment(source_length);
1901 :
1902 : BackgroundCompileTask* task = streaming_data->task.get();
1903 148 : ParseInfo* parse_info = task->info();
1904 : DCHECK(parse_info->is_toplevel());
1905 : // Check if compile cache already holds the SFI, if so no need to finalize
1906 : // the code compiled on the background thread.
1907 : CompilationCache* compilation_cache = isolate->compilation_cache();
1908 : MaybeHandle<SharedFunctionInfo> maybe_result =
1909 : compilation_cache->LookupScript(
1910 : source, script_details.name_obj, script_details.line_offset,
1911 : script_details.column_offset, origin_options,
1912 26102 : isolate->native_context(), parse_info->language_mode());
1913 13051 : if (!maybe_result.is_null()) {
1914 : compile_timer.set_hit_isolate_cache();
1915 : }
1916 :
1917 13051 : if (maybe_result.is_null()) {
1918 : // No cache entry found, finalize compilation of the script and add it to
1919 : // the isolate cache.
1920 : Handle<Script> script =
1921 : NewScript(isolate, parse_info, source, script_details, origin_options,
1922 148 : NOT_NATIVES_CODE);
1923 148 : task->parser()->UpdateStatistics(isolate, script);
1924 148 : task->parser()->HandleSourceURLComments(isolate, script);
1925 :
1926 286 : if (parse_info->literal() == nullptr || !task->outer_function_job()) {
1927 : // Parsing has failed - report error messages.
1928 : FailWithPendingException(isolate, parse_info,
1929 10 : Compiler::ClearExceptionFlag::KEEP_EXCEPTION);
1930 : } else {
1931 : // Parsing has succeeded - finalize compilation.
1932 : maybe_result =
1933 : FinalizeTopLevel(parse_info, isolate, task->outer_function_job(),
1934 276 : task->inner_function_jobs());
1935 138 : if (maybe_result.is_null()) {
1936 : // Finalization failed - throw an exception.
1937 : FailWithPendingException(isolate, parse_info,
1938 0 : Compiler::ClearExceptionFlag::KEEP_EXCEPTION);
1939 : }
1940 : }
1941 :
1942 : // Add compiled code to the isolate cache.
1943 : Handle<SharedFunctionInfo> result;
1944 148 : if (maybe_result.ToHandle(&result)) {
1945 : compilation_cache->PutScript(source, isolate->native_context(),
1946 276 : parse_info->language_mode(), result);
1947 : }
1948 : }
1949 :
1950 : streaming_data->Release();
1951 26102 : return maybe_result;
1952 : }
1953 :
1954 4078217 : Handle<SharedFunctionInfo> Compiler::GetSharedFunctionInfo(
1955 : FunctionLiteral* literal, Handle<Script> script, Isolate* isolate) {
1956 : // Precondition: code has been parsed and scopes have been analyzed.
1957 : MaybeHandle<SharedFunctionInfo> maybe_existing;
1958 :
1959 : // Find any previously allocated shared function info for the given literal.
1960 4078225 : maybe_existing = script->FindSharedFunctionInfo(isolate, literal);
1961 :
1962 : // If we found an existing shared function info, return it.
1963 : Handle<SharedFunctionInfo> existing;
1964 4078239 : if (maybe_existing.ToHandle(&existing)) return existing;
1965 :
1966 : // Allocate a shared function info object which will be compiled lazily.
1967 : Handle<SharedFunctionInfo> result =
1968 : isolate->factory()->NewSharedFunctionInfoForLiteral(literal, script,
1969 2557479 : false);
1970 2557486 : return result;
1971 : }
1972 :
1973 12215 : MaybeHandle<Code> Compiler::GetOptimizedCodeForOSR(Handle<JSFunction> function,
1974 : BailoutId osr_offset,
1975 : JavaScriptFrame* osr_frame) {
1976 : DCHECK(!osr_offset.IsNone());
1977 : DCHECK_NOT_NULL(osr_frame);
1978 : return GetOptimizedCode(function, ConcurrencyMode::kNotConcurrent, osr_offset,
1979 12215 : osr_frame);
1980 : }
1981 :
1982 14128 : bool Compiler::FinalizeOptimizedCompilationJob(OptimizedCompilationJob* job,
1983 : Isolate* isolate) {
1984 : VMState<COMPILER> state(isolate);
1985 : // Take ownership of compilation job. Deleting job also tears down the zone.
1986 : std::unique_ptr<OptimizedCompilationJob> job_scope(job);
1987 0 : OptimizedCompilationInfo* compilation_info = job->compilation_info();
1988 :
1989 : TimerEventScope<TimerEventRecompileSynchronous> timer(isolate);
1990 : RuntimeCallTimerScope runtimeTimer(
1991 7064 : isolate, RuntimeCallCounterId::kRecompileSynchronous);
1992 21192 : TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
1993 : "V8.RecompileSynchronous");
1994 :
1995 : Handle<SharedFunctionInfo> shared = compilation_info->shared_info();
1996 :
1997 : // Reset profiler ticks, function is no longer considered hot.
1998 14128 : compilation_info->closure()->feedback_vector()->set_profiler_ticks(0);
1999 :
2000 : DCHECK(!shared->HasBreakInfo());
2001 :
2002 : // 1) Optimization on the concurrent thread may have failed.
2003 : // 2) The function may have already been optimized by OSR. Simply continue.
2004 : // Except when OSR already disabled optimization for some reason.
2005 : // 3) The code may have already been invalidated due to dependency change.
2006 : // 4) Code generation may have failed.
2007 7064 : if (job->state() == CompilationJob::State::kReadyToFinalize) {
2008 7064 : if (shared->optimization_disabled()) {
2009 : job->RetryOptimization(BailoutReason::kOptimizationDisabled);
2010 7064 : } else if (job->FinalizeJob(isolate) == CompilationJob::SUCCEEDED) {
2011 7023 : job->RecordCompilationStats();
2012 : job->RecordFunctionCompilation(CodeEventListener::LAZY_COMPILE_TAG,
2013 7023 : isolate);
2014 7023 : InsertCodeIntoOptimizedCodeCache(compilation_info);
2015 7023 : if (FLAG_trace_opt) {
2016 0 : PrintF("[completed optimizing ");
2017 0 : compilation_info->closure()->ShortPrint();
2018 0 : PrintF("]\n");
2019 : }
2020 7023 : compilation_info->closure()->set_code(*compilation_info->code());
2021 7023 : return CompilationJob::SUCCEEDED;
2022 : }
2023 : }
2024 :
2025 : DCHECK_EQ(job->state(), CompilationJob::State::kFailed);
2026 41 : if (FLAG_trace_opt) {
2027 0 : PrintF("[aborted optimizing ");
2028 0 : compilation_info->closure()->ShortPrint();
2029 : PrintF(" because: %s]\n",
2030 0 : GetBailoutReason(compilation_info->bailout_reason()));
2031 : }
2032 82 : compilation_info->closure()->set_code(shared->GetCode());
2033 : // Clear the InOptimizationQueue marker, if it exists.
2034 41 : if (compilation_info->closure()->IsInOptimizationQueue()) {
2035 82 : compilation_info->closure()->ClearOptimizationMarker();
2036 : }
2037 : return CompilationJob::FAILED;
2038 : }
2039 :
2040 13311413 : void Compiler::PostInstantiation(Handle<JSFunction> function,
2041 : PretenureFlag pretenure) {
2042 3734622 : Isolate* isolate = function->GetIsolate();
2043 26622850 : Handle<SharedFunctionInfo> shared(function->shared(), isolate);
2044 13311428 : IsCompiledScope is_compiled_scope(shared->is_compiled_scope());
2045 :
2046 : // If code is compiled to bytecode (i.e., isn't asm.js), then allocate a
2047 : // feedback and check for optimized code.
2048 23418604 : if (is_compiled_scope.is_compiled() && shared->HasBytecodeArray()) {
2049 6263716 : JSFunction::EnsureFeedbackVector(function);
2050 :
2051 12527415 : Code code = function->has_feedback_vector()
2052 12527431 : ? function->feedback_vector()->optimized_code()
2053 12527440 : : Code();
2054 6263711 : if (!code.is_null()) {
2055 : // Caching of optimized code enabled and optimized code found.
2056 : DCHECK(!code->marked_for_deoptimization());
2057 : DCHECK(function->shared()->is_compiled());
2058 457241 : function->set_code(code);
2059 : }
2060 :
2061 7236373 : if (FLAG_always_opt && shared->allows_lazy_compilation() &&
2062 13700016 : !shared->optimization_disabled() && !function->IsOptimized() &&
2063 6464196 : !function->HasOptimizedCode()) {
2064 200484 : function->MarkForOptimization(ConcurrencyMode::kNotConcurrent);
2065 : }
2066 : }
2067 :
2068 22888288 : if (shared->is_toplevel() || shared->is_wrapped()) {
2069 : // If it's a top-level script, report compilation to the debugger.
2070 7469245 : Handle<Script> script(Script::cast(shared->script()), isolate);
2071 3734622 : isolate->debug()->OnAfterCompile(script);
2072 : }
2073 13311414 : }
2074 :
2075 : // ----------------------------------------------------------------------------
2076 : // Implementation of ScriptStreamingData
2077 :
2078 13051 : ScriptStreamingData::ScriptStreamingData(
2079 : ScriptCompiler::ExternalSourceStream* source_stream,
2080 : ScriptCompiler::StreamedSource::Encoding encoding)
2081 13051 : : source_stream(source_stream), encoding(encoding) {}
2082 :
2083 : ScriptStreamingData::~ScriptStreamingData() = default;
2084 :
2085 0 : void ScriptStreamingData::Release() { task.reset(); }
2086 :
2087 : } // namespace internal
2088 183867 : } // namespace v8
|