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