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