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.h"
11 : #include "src/asmjs/asm-js.h"
12 : #include "src/assembler-inl.h"
13 : #include "src/ast/ast-numbering.h"
14 : #include "src/ast/prettyprinter.h"
15 : #include "src/ast/scopes.h"
16 : #include "src/base/optional.h"
17 : #include "src/bootstrapper.h"
18 : #include "src/compilation-cache.h"
19 : #include "src/compilation-info.h"
20 : #include "src/compiler-dispatcher/compiler-dispatcher.h"
21 : #include "src/compiler-dispatcher/optimizing-compile-dispatcher.h"
22 : #include "src/compiler/pipeline.h"
23 : #include "src/debug/debug.h"
24 : #include "src/debug/liveedit.h"
25 : #include "src/frames-inl.h"
26 : #include "src/globals.h"
27 : #include "src/heap/heap.h"
28 : #include "src/interpreter/interpreter.h"
29 : #include "src/isolate-inl.h"
30 : #include "src/log-inl.h"
31 : #include "src/messages.h"
32 : #include "src/objects/map.h"
33 : #include "src/parsing/parse-info.h"
34 : #include "src/parsing/parsing.h"
35 : #include "src/parsing/rewriter.h"
36 : #include "src/parsing/scanner-character-streams.h"
37 : #include "src/runtime-profiler.h"
38 : #include "src/snapshot/code-serializer.h"
39 : #include "src/vm-state-inl.h"
40 :
41 : namespace v8 {
42 : namespace internal {
43 :
44 : // A wrapper around a CompilationInfo that detaches the Handles from
45 : // the underlying DeferredHandleScope and stores them in info_ on
46 : // destruction.
47 : class CompilationHandleScope final {
48 : public:
49 8605 : explicit CompilationHandleScope(CompilationInfo* info)
50 8605 : : deferred_(info->isolate()), info_(info) {}
51 8605 : ~CompilationHandleScope() { info_->set_deferred_handles(deferred_.Detach()); }
52 :
53 : private:
54 : DeferredHandleScope deferred_;
55 : CompilationInfo* info_;
56 : };
57 :
58 : // Helper that times a scoped region and records the elapsed time.
59 : struct ScopedTimer {
60 8861606 : explicit ScopedTimer(base::TimeDelta* location) : location_(location) {
61 : DCHECK_NOT_NULL(location_);
62 : timer_.Start();
63 : }
64 :
65 26584950 : ~ScopedTimer() { *location_ += timer_.Elapsed(); }
66 :
67 : base::ElapsedTimer timer_;
68 : base::TimeDelta* location_;
69 : };
70 :
71 : // ----------------------------------------------------------------------------
72 : // Implementation of CompilationJob
73 :
74 3162360 : CompilationJob::CompilationJob(Isolate* isolate, ParseInfo* parse_info,
75 : CompilationInfo* compilation_info,
76 : const char* compiler_name, State initial_state)
77 : : parse_info_(parse_info),
78 : compilation_info_(compilation_info),
79 : isolate_thread_id_(isolate->thread_id()),
80 : compiler_name_(compiler_name),
81 : state_(initial_state),
82 3162360 : stack_limit_(isolate->stack_guard()->real_climit()),
83 9487080 : executed_on_background_thread_(false) {}
84 :
85 2916448 : CompilationJob::Status CompilationJob::PrepareJob() {
86 : DCHECK(
87 : ThreadId::Current().Equals(compilation_info()->isolate()->thread_id()));
88 2916448 : DisallowJavascriptExecution no_js(isolate());
89 :
90 2916450 : if (FLAG_trace_opt && compilation_info()->IsOptimizing()) {
91 0 : OFStream os(stdout);
92 0 : os << "[compiling method " << Brief(*compilation_info()->closure())
93 0 : << " using " << compiler_name_;
94 0 : if (compilation_info()->is_osr()) os << " OSR";
95 0 : os << "]" << std::endl;
96 : }
97 :
98 : // Delegate to the underlying implementation.
99 : DCHECK_EQ(state(), State::kReadyToPrepare);
100 5832894 : ScopedTimer t(&time_taken_to_prepare_);
101 5832902 : return UpdateState(PrepareJobImpl(), State::kReadyToExecute);
102 : }
103 :
104 3144326 : CompilationJob::Status CompilationJob::ExecuteJob() {
105 : base::Optional<DisallowHeapAllocation> no_allocation;
106 : base::Optional<DisallowHandleAllocation> no_handles;
107 : base::Optional<DisallowHandleDereference> no_deref;
108 : base::Optional<DisallowCodeDependencyChange> no_dependency_change;
109 3144326 : if (can_execute_on_background_thread()) {
110 : no_allocation.emplace();
111 : no_handles.emplace();
112 : no_deref.emplace();
113 : no_dependency_change.emplace();
114 : executed_on_background_thread_ =
115 6288657 : !ThreadId::Current().Equals(isolate_thread_id_);
116 : } else {
117 : DCHECK(ThreadId::Current().Equals(isolate_thread_id_));
118 : }
119 :
120 : // Delegate to the underlying implementation.
121 : DCHECK_EQ(state(), State::kReadyToExecute);
122 3144328 : ScopedTimer t(&time_taken_to_execute_);
123 6288753 : return UpdateState(ExecuteJobImpl(), State::kReadyToFinalize);
124 : }
125 :
126 2800827 : CompilationJob::Status CompilationJob::FinalizeJob() {
127 : DCHECK(
128 : ThreadId::Current().Equals(compilation_info()->isolate()->thread_id()));
129 : DisallowCodeDependencyChange no_dependency_change;
130 2800827 : DisallowJavascriptExecution no_js(isolate());
131 : DCHECK(!compilation_info()->dependencies()->HasAborted());
132 :
133 : // Delegate to the underlying implementation.
134 : DCHECK_EQ(state(), State::kReadyToFinalize);
135 5601653 : ScopedTimer t(&time_taken_to_finalize_);
136 5601658 : return UpdateState(FinalizeJobImpl(), State::kSucceeded);
137 : }
138 :
139 0 : CompilationJob::Status CompilationJob::RetryOptimization(BailoutReason reason) {
140 : DCHECK(compilation_info_->IsOptimizing());
141 41 : compilation_info_->RetryOptimization(reason);
142 41 : state_ = State::kFailed;
143 0 : return FAILED;
144 : }
145 :
146 0 : CompilationJob::Status CompilationJob::AbortOptimization(BailoutReason reason) {
147 : DCHECK(compilation_info_->IsOptimizing());
148 0 : compilation_info_->AbortOptimization(reason);
149 0 : state_ = State::kFailed;
150 0 : return FAILED;
151 : }
152 :
153 2134855 : void CompilationJob::RecordUnoptimizedCompilationStats() const {
154 : int code_size;
155 2134855 : if (compilation_info()->has_bytecode_array()) {
156 2131308 : code_size = compilation_info()->bytecode_array()->SizeIncludingMetadata();
157 : } else {
158 3547 : code_size = compilation_info()->code()->SizeIncludingMetadata();
159 : }
160 :
161 : Counters* counters = isolate()->counters();
162 : // TODO(4280): Rename counters from "baseline" to "unoptimized" eventually.
163 2134855 : counters->total_baseline_code_size()->Increment(code_size);
164 2134855 : counters->total_baseline_compile_count()->Increment(1);
165 :
166 : // TODO(5203): Add timers for each phase of compilation.
167 2134855 : }
168 :
169 438219 : void CompilationJob::RecordOptimizedCompilationStats() const {
170 : DCHECK(compilation_info()->IsOptimizing());
171 : Handle<JSFunction> function = compilation_info()->closure();
172 438219 : double ms_creategraph = time_taken_to_prepare_.InMillisecondsF();
173 438219 : double ms_optimize = time_taken_to_execute_.InMillisecondsF();
174 438219 : double ms_codegen = time_taken_to_finalize_.InMillisecondsF();
175 438219 : if (FLAG_trace_opt) {
176 0 : PrintF("[optimizing ");
177 0 : function->ShortPrint();
178 : PrintF(" - took %0.3f, %0.3f, %0.3f ms]\n", ms_creategraph, ms_optimize,
179 0 : ms_codegen);
180 : }
181 438219 : if (FLAG_trace_opt_stats) {
182 : static double compilation_time = 0.0;
183 : static int compiled_functions = 0;
184 : static int code_size = 0;
185 :
186 0 : compilation_time += (ms_creategraph + ms_optimize + ms_codegen);
187 0 : compiled_functions++;
188 0 : code_size += function->shared()->SourceSize();
189 : PrintF("Compiled: %d functions with %d byte source size in %fms.\n",
190 0 : compiled_functions, code_size, compilation_time);
191 : }
192 438219 : }
193 :
194 12718363 : Isolate* CompilationJob::isolate() const {
195 12718363 : return compilation_info()->isolate();
196 : }
197 :
198 : // ----------------------------------------------------------------------------
199 : // Local helper methods that make up the compilation pipeline.
200 :
201 : namespace {
202 :
203 2573073 : void RecordFunctionCompilation(CodeEventListener::LogEventsAndTags tag,
204 : Handle<Script> script,
205 2574671 : CompilationInfo* compilation_info) {
206 : // Log the code generation. If source information is available include
207 : // script name and line number. Check explicitly whether logging is
208 : // enabled as finding the line number is not free.
209 7718859 : if (compilation_info->isolate()->logger()->is_logging_code_events() ||
210 2572713 : compilation_info->isolate()->is_profiling()) {
211 : Handle<SharedFunctionInfo> shared = compilation_info->shared_info();
212 : Handle<AbstractCode> abstract_code =
213 : compilation_info->has_bytecode_array()
214 : ? Handle<AbstractCode>::cast(compilation_info->bytecode_array())
215 869 : : Handle<AbstractCode>::cast(compilation_info->code());
216 869 : if (abstract_code.is_identical_to(
217 1738 : BUILTIN_CODE(compilation_info->isolate(), CompileLazy))) {
218 2573073 : return;
219 : }
220 869 : int line_num = Script::GetLineNumber(script, shared->start_position()) + 1;
221 : int column_num =
222 869 : Script::GetColumnNumber(script, shared->start_position()) + 1;
223 : String* script_name =
224 : script->name()->IsString()
225 : ? String::cast(script->name())
226 1598 : : compilation_info->isolate()->heap()->empty_string();
227 : CodeEventListener::LogEventsAndTags log_tag =
228 : Logger::ToNativeByScript(tag, *script);
229 869 : PROFILE(compilation_info->isolate(),
230 : CodeCreateEvent(log_tag, *abstract_code, *shared, script_name,
231 : line_num, column_num));
232 : }
233 : }
234 :
235 4269710 : void EnsureFeedbackMetadata(CompilationInfo* compilation_info) {
236 : DCHECK(compilation_info->has_shared_info());
237 :
238 : // If no type feedback metadata exists, create it. At this point the
239 : // AstNumbering pass has already run. Note the snapshot can contain outdated
240 : // vectors for a different configuration, hence we also recreate a new vector
241 : // when the function is not compiled (i.e. no code was serialized).
242 :
243 : // TODO(mvstanton): reintroduce is_empty() predicate to feedback_metadata().
244 2147558 : if (compilation_info->shared_info()->feedback_metadata()->length() == 0 ||
245 : !compilation_info->shared_info()->is_compiled()) {
246 : Handle<FeedbackMetadata> feedback_metadata = FeedbackMetadata::New(
247 4269710 : compilation_info->isolate(), compilation_info->feedback_vector_spec());
248 2134854 : compilation_info->shared_info()->set_feedback_metadata(*feedback_metadata);
249 : }
250 :
251 : // It's very important that recompiles do not alter the structure of the type
252 : // feedback vector. Verify that the structure fits the function literal.
253 4269710 : CHECK(!compilation_info->shared_info()->feedback_metadata()->SpecDiffersFrom(
254 : compilation_info->feedback_vector_spec()));
255 2134854 : }
256 :
257 3927896 : bool UseAsmWasm(FunctionLiteral* literal, bool asm_wasm_broken) {
258 : // Check whether asm.js validation is enabled.
259 2134847 : if (!FLAG_validate_asm) return false;
260 :
261 : // Modules that have validated successfully, but were subsequently broken by
262 : // invalid module instantiation attempts are off limit forever.
263 2134838 : if (asm_wasm_broken) return false;
264 :
265 : // In stress mode we want to run the validator on everything.
266 2134658 : if (FLAG_stress_validate_asm) return true;
267 :
268 : // In general, we respect the "use asm" directive.
269 1793049 : return literal->scope()->IsAsmModule();
270 : }
271 :
272 2135636 : void InstallUnoptimizedCode(CompilationInfo* compilation_info) {
273 : Handle<SharedFunctionInfo> shared = compilation_info->shared_info();
274 : DCHECK_EQ(compilation_info->shared_info()->language_mode(),
275 : compilation_info->literal()->language_mode());
276 :
277 : // Ensure feedback metadata is installed.
278 2134855 : EnsureFeedbackMetadata(compilation_info);
279 :
280 : // Update the shared function info with the scope info.
281 2134855 : Handle<ScopeInfo> scope_info = compilation_info->scope()->scope_info();
282 2134855 : shared->set_scope_info(*scope_info);
283 2134855 : Scope* outer_scope = compilation_info->scope()->GetOuterScopeWithContext();
284 2134855 : if (outer_scope) {
285 1927124 : shared->set_outer_scope_info(*outer_scope->scope_info());
286 : }
287 :
288 : DCHECK(!compilation_info->code().is_null());
289 2134855 : shared->set_code(*compilation_info->code());
290 2134855 : if (compilation_info->has_bytecode_array()) {
291 : DCHECK(!shared->HasBytecodeArray()); // Only compiled once.
292 : DCHECK(!compilation_info->has_asm_wasm_data());
293 : shared->set_bytecode_array(*compilation_info->bytecode_array());
294 3547 : } else if (compilation_info->has_asm_wasm_data()) {
295 : shared->set_asm_wasm_data(*compilation_info->asm_wasm_data());
296 : }
297 :
298 : // Install coverage info on the shared function info.
299 2134855 : if (compilation_info->has_coverage_info()) {
300 : DCHECK(compilation_info->isolate()->is_block_code_coverage());
301 : compilation_info->isolate()->debug()->InstallCoverageInfo(
302 781 : compilation_info->shared_info(), compilation_info->coverage_info());
303 : }
304 2134855 : }
305 :
306 2022462 : void EnsureSharedFunctionInfosArrayOnScript(ParseInfo* parse_info,
307 : Isolate* isolate) {
308 : DCHECK(parse_info->is_toplevel());
309 : DCHECK(!parse_info->script().is_null());
310 1011231 : if (parse_info->script()->shared_function_infos()->length() > 0) {
311 : DCHECK_EQ(parse_info->script()->shared_function_infos()->length(),
312 : parse_info->max_function_literal_id() + 1);
313 0 : return;
314 : }
315 : Handle<FixedArray> infos(isolate->factory()->NewFixedArray(
316 1011231 : parse_info->max_function_literal_id() + 1));
317 1011231 : parse_info->script()->set_shared_function_infos(*infos);
318 : }
319 :
320 6759599 : void SetSharedFunctionFlagsFromLiteral(FunctionLiteral* literal,
321 : Handle<SharedFunctionInfo> shared_info) {
322 : // Don't overwrite values set by the bootstrapper.
323 2134855 : if (!shared_info->HasLength()) {
324 : shared_info->set_length(literal->function_length());
325 : }
326 : shared_info->set_has_duplicate_parameters(
327 : literal->has_duplicate_parameters());
328 2134855 : shared_info->SetExpectedNofPropertiesFromEstimate(literal);
329 2134855 : if (literal->dont_optimize_reason() != kNoReason) {
330 1413 : shared_info->DisableOptimization(literal->dont_optimize_reason());
331 : }
332 2134855 : }
333 :
334 2134855 : CompilationJob::Status FinalizeUnoptimizedCompilationJob(CompilationJob* job) {
335 2134855 : CompilationInfo* compilation_info = job->compilation_info();
336 : ParseInfo* parse_info = job->parse_info();
337 :
338 : SetSharedFunctionFlagsFromLiteral(compilation_info->literal(),
339 2134855 : compilation_info->shared_info());
340 :
341 2134855 : CompilationJob::Status status = job->FinalizeJob();
342 2134855 : if (status == CompilationJob::SUCCEEDED) {
343 2134855 : InstallUnoptimizedCode(compilation_info);
344 : CodeEventListener::LogEventsAndTags log_tag;
345 2134855 : if (parse_info->is_toplevel()) {
346 : log_tag = compilation_info->is_eval() ? CodeEventListener::EVAL_TAG
347 1554885 : : CodeEventListener::SCRIPT_TAG;
348 : } else {
349 : log_tag = parse_info->lazy_compile() ? CodeEventListener::LAZY_COMPILE_TAG
350 579970 : : CodeEventListener::FUNCTION_TAG;
351 : }
352 2134855 : RecordFunctionCompilation(log_tag, parse_info->script(), compilation_info);
353 2134855 : job->RecordUnoptimizedCompilationStats();
354 : }
355 2134855 : return status;
356 : }
357 :
358 4889792 : bool Renumber(ParseInfo* parse_info,
359 : Compiler::EagerInnerFunctionLiterals* eager_literals) {
360 : RuntimeCallTimerScope runtimeTimer(parse_info->runtime_call_stats(),
361 1629930 : &RuntimeCallStats::CompileRenumber);
362 : return AstNumbering::Renumber(parse_info->stack_limit(), parse_info->zone(),
363 3259862 : parse_info->literal(), eager_literals);
364 : }
365 :
366 2134847 : std::unique_ptr<CompilationJob> PrepareAndExecuteUnoptimizedCompileJob(
367 : ParseInfo* parse_info, FunctionLiteral* literal, Isolate* isolate) {
368 2134847 : if (UseAsmWasm(literal, parse_info->is_asm_wasm_broken())) {
369 : std::unique_ptr<CompilationJob> asm_job(
370 346048 : AsmJs::NewCompilationJob(parse_info, literal, isolate));
371 692095 : if (asm_job->PrepareJob() == CompilationJob::SUCCEEDED &&
372 346048 : asm_job->ExecuteJob() == CompilationJob::SUCCEEDED) {
373 : return asm_job;
374 : }
375 : // asm.js validation failed, fall through to standard unoptimized compile.
376 : // Note: we rely on the fact that AsmJs jobs have done all validation in the
377 : // PrepareJob and ExecuteJob phases and can't fail in FinalizeJob with
378 : // with a validation error or another error that could be solve by falling
379 : // through to standard unoptimized compile.
380 : }
381 : std::unique_ptr<CompilationJob> job(
382 : interpreter::Interpreter::NewCompilationJob(parse_info, literal,
383 2131304 : isolate));
384 4262606 : if (job->PrepareJob() == CompilationJob::SUCCEEDED &&
385 2131304 : job->ExecuteJob() == CompilationJob::SUCCEEDED) {
386 : return job;
387 : }
388 : return std::unique_ptr<CompilationJob>(); // Compilation failed, return null.
389 : }
390 :
391 : // TODO(rmcilroy): Remove |isolate| once CompilationJob doesn't need it.
392 1587388 : std::unique_ptr<CompilationJob> GenerateUnoptimizedCode(
393 1587359 : ParseInfo* parse_info, Isolate* isolate,
394 : std::forward_list<std::unique_ptr<CompilationJob>>* inner_function_jobs) {
395 : DisallowHeapAllocation no_allocation;
396 : DisallowHandleAllocation no_handles;
397 : DisallowHandleDereference no_deref;
398 : DCHECK(inner_function_jobs->empty());
399 :
400 : DCHECK_IMPLIES(parse_info->consumed_preparsed_scope_data()->HasData(),
401 : ThreadId::Current().Equals(isolate->thread_id()));
402 :
403 : Compiler::EagerInnerFunctionLiterals inner_literals;
404 1587388 : if (!Compiler::Analyze(parse_info, &inner_literals)) {
405 : return std::unique_ptr<CompilationJob>();
406 : }
407 :
408 : // Prepare and execute compilation of the outer-most function.
409 : std::unique_ptr<CompilationJob> outer_function_job(
410 : PrepareAndExecuteUnoptimizedCompileJob(parse_info, parse_info->literal(),
411 1587359 : isolate));
412 1587357 : if (!outer_function_job) return std::unique_ptr<CompilationJob>();
413 :
414 : // Prepare and execute compilation jobs for eager inner functions.
415 4269674 : for (auto it : inner_literals) {
416 : FunctionLiteral* inner_literal = it->value();
417 : std::unique_ptr<CompilationJob> inner_job(
418 : PrepareAndExecuteUnoptimizedCompileJob(parse_info, inner_literal,
419 547489 : isolate));
420 547490 : if (!inner_job) return std::unique_ptr<CompilationJob>();
421 : inner_function_jobs->emplace_front(std::move(inner_job));
422 : }
423 :
424 : // Character stream shouldn't be used again.
425 1587349 : parse_info->ResetCharacterStream();
426 :
427 : return outer_function_job;
428 : }
429 :
430 1587350 : bool FinalizeUnoptimizedCode(
431 : ParseInfo* parse_info, Isolate* isolate,
432 1587350 : Handle<SharedFunctionInfo> shared_info, CompilationJob* outer_function_job,
433 : std::forward_list<std::unique_ptr<CompilationJob>>* inner_function_jobs) {
434 : DCHECK(AllowCompilation::IsAllowed(isolate));
435 :
436 : // Allocate scope infos for the literal.
437 : DeclarationScope::AllocateScopeInfos(parse_info, isolate,
438 1587350 : AnalyzeMode::kRegular);
439 :
440 : // Finalize the outer-most function's compilation job.
441 : outer_function_job->compilation_info()->set_shared_info(shared_info);
442 1587350 : if (FinalizeUnoptimizedCompilationJob(outer_function_job) !=
443 : CompilationJob::SUCCEEDED) {
444 : return false;
445 : }
446 :
447 : // Finalize the inner functions' compilation jobs.
448 3722191 : for (auto&& inner_job : *inner_function_jobs) {
449 : Handle<SharedFunctionInfo> inner_shared_info =
450 : Compiler::GetSharedFunctionInfo(
451 : inner_job->compilation_info()->literal(), parse_info->script(),
452 547491 : isolate);
453 : // The inner function might be compiled already if compiling for debug.
454 : // TODO(rmcilroy): Fix this and DCHECK !is_compiled() once Full-Codegen dies
455 547496 : if (inner_shared_info->is_compiled()) continue;
456 547486 : inner_job->compilation_info()->set_shared_info(inner_shared_info);
457 547486 : if (FinalizeUnoptimizedCompilationJob(inner_job.get()) !=
458 : CompilationJob::SUCCEEDED) {
459 0 : return false;
460 : }
461 : }
462 : return true;
463 : }
464 :
465 457031 : MUST_USE_RESULT MaybeHandle<Code> GetCodeFromOptimizedCodeCache(
466 : Handle<JSFunction> function, BailoutId osr_offset) {
467 : RuntimeCallTimerScope runtimeTimer(
468 : function->GetIsolate(),
469 457031 : &RuntimeCallStats::CompileGetFromOptimizedCodeMap);
470 : Handle<SharedFunctionInfo> shared(function->shared());
471 : DisallowHeapAllocation no_gc;
472 457030 : if (osr_offset.IsNone()) {
473 450995 : if (function->feedback_vector_cell()->value()->IsFeedbackVector()) {
474 : FeedbackVector* feedback_vector = function->feedback_vector();
475 : feedback_vector->EvictOptimizedCodeMarkedForDeoptimization(
476 450995 : function->shared(), "GetCodeFromOptimizedCodeCache");
477 : Code* code = feedback_vector->optimized_code();
478 :
479 450995 : if (code != nullptr) {
480 : // Caching of optimized code enabled and optimized code found.
481 : DCHECK(!code->marked_for_deoptimization());
482 : DCHECK(function->shared()->is_compiled());
483 0 : return Handle<Code>(code);
484 : }
485 : }
486 : }
487 457030 : return MaybeHandle<Code>();
488 : }
489 :
490 419612 : void ClearOptimizedCodeCache(CompilationInfo* compilation_info) {
491 : Handle<JSFunction> function = compilation_info->closure();
492 419612 : if (compilation_info->osr_offset().IsNone()) {
493 : Handle<FeedbackVector> vector =
494 : handle(function->feedback_vector(), function->GetIsolate());
495 413853 : vector->ClearOptimizedCode();
496 : }
497 419613 : }
498 :
499 438218 : void InsertCodeIntoOptimizedCodeCache(CompilationInfo* compilation_info) {
500 : Handle<Code> code = compilation_info->code();
501 438218 : if (code->kind() != Code::OPTIMIZED_FUNCTION) return; // Nothing to do.
502 :
503 : // Function context specialization folds-in the function context,
504 : // so no sharing can occur.
505 438218 : if (compilation_info->is_function_context_specializing()) {
506 : // Native context specialized code is not shared, so make sure the optimized
507 : // code cache is clear.
508 419612 : ClearOptimizedCodeCache(compilation_info);
509 419613 : return;
510 : }
511 :
512 : // Cache optimized context-specific code.
513 : Handle<JSFunction> function = compilation_info->closure();
514 : Handle<SharedFunctionInfo> shared(function->shared());
515 : Handle<Context> native_context(function->context()->native_context());
516 18606 : if (compilation_info->osr_offset().IsNone()) {
517 : Handle<FeedbackVector> vector =
518 18557 : handle(function->feedback_vector(), function->GetIsolate());
519 18557 : FeedbackVector::SetOptimizedCode(vector, code);
520 : }
521 : }
522 :
523 860927 : bool GetOptimizedCodeNow(CompilationJob* job) {
524 430469 : CompilationInfo* compilation_info = job->compilation_info();
525 : Isolate* isolate = compilation_info->isolate();
526 : TimerEventScope<TimerEventRecompileSynchronous> timer(isolate);
527 : RuntimeCallTimerScope runtimeTimer(isolate,
528 430469 : &RuntimeCallStats::RecompileSynchronous);
529 1291406 : TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
530 : "V8.RecompileSynchronous");
531 :
532 1291405 : if (job->PrepareJob() != CompilationJob::SUCCEEDED ||
533 860927 : job->ExecuteJob() != CompilationJob::SUCCEEDED ||
534 430459 : job->FinalizeJob() != CompilationJob::SUCCEEDED) {
535 10 : if (FLAG_trace_opt) {
536 0 : PrintF("[aborted optimizing ");
537 0 : compilation_info->closure()->ShortPrint();
538 : PrintF(" because: %s]\n",
539 0 : GetBailoutReason(compilation_info->bailout_reason()));
540 : }
541 : return false;
542 : }
543 :
544 : // Success!
545 430459 : job->RecordOptimizedCompilationStats();
546 : DCHECK(!isolate->has_pending_exception());
547 430458 : InsertCodeIntoOptimizedCodeCache(compilation_info);
548 : RecordFunctionCompilation(CodeEventListener::LAZY_COMPILE_TAG,
549 430458 : job->parse_info()->script(), compilation_info);
550 430458 : return true;
551 : }
552 :
553 8605 : bool GetOptimizedCodeLater(CompilationJob* job) {
554 8605 : CompilationInfo* compilation_info = job->compilation_info();
555 17210 : Isolate* isolate = compilation_info->isolate();
556 :
557 8605 : if (!isolate->optimizing_compile_dispatcher()->IsQueueAvailable()) {
558 0 : if (FLAG_trace_concurrent_recompilation) {
559 0 : PrintF(" ** Compilation queue full, will retry optimizing ");
560 0 : compilation_info->closure()->ShortPrint();
561 0 : PrintF(" later.\n");
562 : }
563 : return false;
564 : }
565 :
566 8605 : if (isolate->heap()->HighMemoryPressure()) {
567 0 : if (FLAG_trace_concurrent_recompilation) {
568 0 : PrintF(" ** High memory pressure, will retry optimizing ");
569 0 : compilation_info->closure()->ShortPrint();
570 0 : PrintF(" later.\n");
571 : }
572 : return false;
573 : }
574 :
575 : TimerEventScope<TimerEventRecompileSynchronous> timer(isolate);
576 : RuntimeCallTimerScope runtimeTimer(isolate,
577 8605 : &RuntimeCallStats::RecompileSynchronous);
578 25815 : TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
579 : "V8.RecompileSynchronous");
580 :
581 8605 : if (job->PrepareJob() != CompilationJob::SUCCEEDED) return false;
582 8605 : isolate->optimizing_compile_dispatcher()->QueueForOptimization(job);
583 :
584 8605 : if (FLAG_trace_concurrent_recompilation) {
585 0 : PrintF(" ** Queued ");
586 0 : compilation_info->closure()->ShortPrint();
587 0 : PrintF(" for concurrent optimization.\n");
588 : }
589 : return true;
590 : }
591 :
592 457031 : MaybeHandle<Code> GetOptimizedCode(Handle<JSFunction> function,
593 : ConcurrencyMode mode,
594 : BailoutId osr_offset = BailoutId::None(),
595 : JavaScriptFrame* osr_frame = nullptr) {
596 : Isolate* isolate = function->GetIsolate();
597 : Handle<SharedFunctionInfo> shared(function->shared(), isolate);
598 :
599 : // Make sure we clear the optimization marker on the function so that we
600 : // don't try to re-optimize.
601 457031 : if (function->HasOptimizationMarker()) {
602 : function->ClearOptimizationMarker();
603 : }
604 :
605 : Handle<Code> cached_code;
606 457031 : if (GetCodeFromOptimizedCodeCache(function, osr_offset)
607 914062 : .ToHandle(&cached_code)) {
608 0 : if (FLAG_trace_opt) {
609 0 : PrintF("[found optimized code for ");
610 0 : function->ShortPrint();
611 0 : if (!osr_offset.IsNone()) {
612 0 : PrintF(" at OSR AST id %d", osr_offset.ToInt());
613 : }
614 0 : PrintF("]\n");
615 : }
616 0 : return cached_code;
617 : }
618 :
619 : // Reset profiler ticks, function is no longer considered hot.
620 : DCHECK(shared->is_compiled());
621 : function->feedback_vector()->set_profiler_ticks(0);
622 :
623 : VMState<COMPILER> state(isolate);
624 : DCHECK(!isolate->has_pending_exception());
625 : PostponeInterruptsScope postpone(isolate);
626 : bool has_script = shared->script()->IsScript();
627 : // BUG(5946): This DCHECK is necessary to make certain that we won't
628 : // tolerate the lack of a script without bytecode.
629 : DCHECK_IMPLIES(!has_script, shared->HasBytecodeArray());
630 : std::unique_ptr<CompilationJob> job(
631 457030 : compiler::Pipeline::NewCompilationJob(function, has_script));
632 457030 : CompilationInfo* compilation_info = job->compilation_info();
633 457030 : ParseInfo* parse_info = job->parse_info();
634 :
635 : compilation_info->SetOptimizingForOsr(osr_offset, osr_frame);
636 :
637 : // Do not use TurboFan if we need to be able to set break points.
638 457030 : if (compilation_info->shared_info()->HasBreakInfo()) {
639 674 : compilation_info->AbortOptimization(kFunctionBeingDebugged);
640 674 : return MaybeHandle<Code>();
641 : }
642 :
643 : // Do not use TurboFan when %NeverOptimizeFunction was applied.
644 456356 : if (shared->optimization_disabled() &&
645 : shared->disable_optimization_reason() == kOptimizationDisabledForTest) {
646 82 : compilation_info->AbortOptimization(kOptimizationDisabledForTest);
647 82 : return MaybeHandle<Code>();
648 : }
649 :
650 : // Do not use TurboFan if optimization is disabled or function doesn't pass
651 : // turbo_filter.
652 456274 : if (!FLAG_opt || !shared->PassesFilter(FLAG_turbo_filter)) {
653 17201 : compilation_info->AbortOptimization(kOptimizationDisabled);
654 17201 : return MaybeHandle<Code>();
655 : }
656 :
657 : TimerEventScope<TimerEventOptimizeCode> optimize_code_timer(isolate);
658 439073 : RuntimeCallTimerScope runtimeTimer(isolate, &RuntimeCallStats::OptimizeCode);
659 1317217 : TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.OptimizeCode");
660 :
661 : // In case of concurrent recompilation, all handles below this point will be
662 : // allocated in a deferred handle scope that is detached and handed off to
663 : // the background thread when we return.
664 439072 : base::Optional<CompilationHandleScope> compilation;
665 439072 : if (mode == ConcurrencyMode::kConcurrent) {
666 8605 : compilation.emplace(compilation_info);
667 : }
668 :
669 : // All handles below will be canonicalized.
670 878145 : CanonicalHandleScope canonical(isolate);
671 :
672 : // Reopen handles in the new CompilationHandleScope.
673 439073 : compilation_info->ReopenHandlesInNewHandleScope();
674 439074 : parse_info->ReopenHandlesInNewHandleScope();
675 :
676 439074 : if (mode == ConcurrencyMode::kConcurrent) {
677 8605 : if (GetOptimizedCodeLater(job.get())) {
678 : job.release(); // The background recompile job owns this now.
679 :
680 : // Set the optimization marker and return a code object which checks it.
681 : function->SetOptimizationMarker(OptimizationMarker::kInOptimizationQueue);
682 8605 : if (function->IsInterpreted()) {
683 8465 : return BUILTIN_CODE(isolate, InterpreterEntryTrampoline);
684 : } else {
685 140 : return BUILTIN_CODE(isolate, CheckOptimizationMarker);
686 : }
687 : }
688 : } else {
689 430469 : if (GetOptimizedCodeNow(job.get())) return compilation_info->code();
690 : }
691 :
692 9 : if (isolate->has_pending_exception()) isolate->clear_pending_exception();
693 10 : return MaybeHandle<Code>();
694 : }
695 :
696 23365 : CompilationJob::Status FinalizeOptimizedCompilationJob(CompilationJob* job) {
697 7802 : CompilationInfo* compilation_info = job->compilation_info();
698 : Isolate* isolate = compilation_info->isolate();
699 :
700 : TimerEventScope<TimerEventRecompileSynchronous> timer(isolate);
701 : RuntimeCallTimerScope runtimeTimer(isolate,
702 7802 : &RuntimeCallStats::RecompileSynchronous);
703 23406 : TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
704 : "V8.RecompileSynchronous");
705 :
706 : Handle<SharedFunctionInfo> shared = compilation_info->shared_info();
707 :
708 : // Reset profiler ticks, function is no longer considered hot.
709 : compilation_info->closure()->feedback_vector()->set_profiler_ticks(0);
710 :
711 : DCHECK(!shared->HasBreakInfo());
712 :
713 : // 1) Optimization on the concurrent thread may have failed.
714 : // 2) The function may have already been optimized by OSR. Simply continue.
715 : // Except when OSR already disabled optimization for some reason.
716 : // 3) The code may have already been invalidated due to dependency change.
717 : // 4) Code generation may have failed.
718 7802 : if (job->state() == CompilationJob::State::kReadyToFinalize) {
719 7802 : if (shared->optimization_disabled()) {
720 : job->RetryOptimization(kOptimizationDisabled);
721 7802 : } else if (compilation_info->dependencies()->HasAborted()) {
722 : job->RetryOptimization(kBailedOutDueToDependencyChange);
723 7761 : } else if (job->FinalizeJob() == CompilationJob::SUCCEEDED) {
724 7761 : job->RecordOptimizedCompilationStats();
725 : RecordFunctionCompilation(CodeEventListener::LAZY_COMPILE_TAG,
726 7761 : job->parse_info()->script(), compilation_info);
727 7761 : InsertCodeIntoOptimizedCodeCache(compilation_info);
728 7761 : if (FLAG_trace_opt) {
729 0 : PrintF("[completed optimizing ");
730 0 : compilation_info->closure()->ShortPrint();
731 0 : PrintF("]\n");
732 : }
733 7761 : compilation_info->closure()->set_code(*compilation_info->code());
734 7761 : return CompilationJob::SUCCEEDED;
735 : }
736 : }
737 :
738 : DCHECK_EQ(job->state(), CompilationJob::State::kFailed);
739 41 : if (FLAG_trace_opt) {
740 0 : PrintF("[aborted optimizing ");
741 0 : compilation_info->closure()->ShortPrint();
742 : PrintF(" because: %s]\n",
743 0 : GetBailoutReason(compilation_info->bailout_reason()));
744 : }
745 41 : compilation_info->closure()->set_code(shared->code());
746 : // Clear the InOptimizationQueue marker, if it exists.
747 41 : if (compilation_info->closure()->IsInOptimizationQueue()) {
748 : compilation_info->closure()->ClearOptimizationMarker();
749 : }
750 : return CompilationJob::FAILED;
751 : }
752 :
753 3247302 : MaybeHandle<SharedFunctionInfo> CompileToplevel(ParseInfo* parse_info,
754 : Isolate* isolate) {
755 : TimerEventScope<TimerEventCompileCode> top_level_timer(isolate);
756 3354109 : TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.CompileCode");
757 : PostponeInterruptsScope postpone(isolate);
758 : DCHECK(!isolate->native_context().is_null());
759 : RuntimeCallTimerScope runtimeTimer(
760 : isolate, parse_info->is_eval() ? &RuntimeCallStats::CompileEval
761 1118037 : : &RuntimeCallStats::CompileScript);
762 :
763 : Handle<Script> script = parse_info->script();
764 : Handle<SharedFunctionInfo> result;
765 : VMState<BYTECODE_COMPILER> state(isolate);
766 2235976 : if (parse_info->literal() == nullptr &&
767 1117941 : !parsing::ParseProgram(parse_info, isolate)) {
768 106796 : return MaybeHandle<SharedFunctionInfo>();
769 : }
770 : // Measure how long it takes to do the compilation; only take the
771 : // rest of the function into account to avoid overlap with the
772 : // parsing statistics.
773 : HistogramTimer* rate = parse_info->is_eval()
774 : ? isolate->counters()->compile_eval()
775 2022478 : : isolate->counters()->compile();
776 : HistogramTimerScope timer(rate);
777 3033723 : TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
778 : parse_info->is_eval() ? "V8.CompileEval" : "V8.Compile");
779 :
780 : // Generate the unoptimized bytecode or asm-js data.
781 : std::forward_list<std::unique_ptr<CompilationJob>> inner_function_jobs;
782 : std::unique_ptr<CompilationJob> outer_function_job(
783 1011241 : GenerateUnoptimizedCode(parse_info, isolate, &inner_function_jobs));
784 1011238 : if (!outer_function_job) {
785 10 : if (!isolate->has_pending_exception()) isolate->StackOverflow();
786 10 : return MaybeHandle<SharedFunctionInfo>();
787 : }
788 :
789 : // Internalize ast values onto the heap.
790 1011228 : parse_info->ast_value_factory()->Internalize(isolate);
791 :
792 : // Create shared function infos for top level and shared function infos array
793 : // for inner functions.
794 1011229 : EnsureSharedFunctionInfosArrayOnScript(parse_info, isolate);
795 : DCHECK_EQ(kNoSourcePosition,
796 : parse_info->literal()->function_token_position());
797 : Handle<SharedFunctionInfo> shared_info =
798 : isolate->factory()->NewSharedFunctionInfoForLiteral(parse_info->literal(),
799 1011231 : parse_info->script());
800 : shared_info->set_is_toplevel(true);
801 :
802 : // Finalize compilation of the unoptimized bytecode or asm-js data.
803 1011231 : if (!FinalizeUnoptimizedCode(parse_info, isolate, shared_info,
804 : outer_function_job.get(),
805 1011231 : &inner_function_jobs)) {
806 0 : if (!isolate->has_pending_exception()) isolate->StackOverflow();
807 0 : return MaybeHandle<SharedFunctionInfo>();
808 : }
809 :
810 1011231 : if (!script.is_null()) {
811 1011231 : script->set_compilation_state(Script::COMPILATION_STATE_COMPILED);
812 : }
813 :
814 1011231 : return shared_info;
815 : }
816 :
817 485 : bool FailWithPendingException(Isolate* isolate,
818 : Compiler::ClearExceptionFlag flag) {
819 485 : if (flag == Compiler::CLEAR_EXCEPTION) {
820 : isolate->clear_pending_exception();
821 470 : } else if (!isolate->has_pending_exception()) {
822 30 : isolate->StackOverflow();
823 : }
824 485 : return false;
825 : }
826 :
827 : } // namespace
828 :
829 : // ----------------------------------------------------------------------------
830 : // Implementation of Compiler
831 :
832 1629929 : bool Compiler::Analyze(ParseInfo* parse_info,
833 : EagerInnerFunctionLiterals* eager_literals) {
834 : DCHECK_NOT_NULL(parse_info->literal());
835 : RuntimeCallTimerScope runtimeTimer(parse_info->runtime_call_stats(),
836 1629929 : &RuntimeCallStats::CompileAnalyse);
837 1629929 : if (!Rewriter::Rewrite(parse_info)) return false;
838 1629931 : DeclarationScope::Analyze(parse_info);
839 1629930 : if (!Renumber(parse_info, eager_literals)) return false;
840 1629900 : return true;
841 : }
842 :
843 0 : bool Compiler::ParseAndAnalyze(ParseInfo* parse_info,
844 : Handle<SharedFunctionInfo> shared_info,
845 : Isolate* isolate) {
846 0 : if (!parsing::ParseAny(parse_info, shared_info, isolate)) {
847 : return false;
848 : }
849 0 : return Compiler::Analyze(parse_info);
850 : }
851 :
852 576607 : bool Compiler::Compile(Handle<SharedFunctionInfo> shared_info,
853 : ClearExceptionFlag flag) {
854 : // We should never reach here if the function is already compiled.
855 : DCHECK(!shared_info->is_compiled());
856 :
857 576607 : Isolate* isolate = shared_info->GetIsolate();
858 : DCHECK(!isolate->has_pending_exception());
859 : DCHECK(!shared_info->HasBytecodeArray());
860 : VMState<BYTECODE_COMPILER> state(isolate);
861 : PostponeInterruptsScope postpone(isolate);
862 : TimerEventScope<TimerEventCompileCode> compile_timer(isolate);
863 : RuntimeCallTimerScope runtimeTimer(isolate,
864 576607 : &RuntimeCallStats::CompileFunction);
865 1729821 : TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.CompileCode");
866 1153214 : AggregatedHistogramTimerScope timer(isolate->counters()->compile_lazy());
867 :
868 : // Check if the compiler dispatcher has shared_info enqueued for compile.
869 : CompilerDispatcher* dispatcher = isolate->compiler_dispatcher();
870 576607 : if (dispatcher->IsEnqueued(shared_info)) {
871 3 : if (!dispatcher->FinishNow(shared_info)) {
872 0 : return FailWithPendingException(isolate, flag);
873 : }
874 : return true;
875 : }
876 :
877 : // Set up parse info.
878 1153208 : ParseInfo parse_info(shared_info);
879 : parse_info.set_lazy_compile();
880 576604 : if (FLAG_preparser_scope_analysis) {
881 576604 : if (shared_info->HasPreParsedScopeData()) {
882 : Handle<PreParsedScopeData> data(
883 : PreParsedScopeData::cast(shared_info->preparsed_scope_data()));
884 19142 : parse_info.consumed_preparsed_scope_data()->SetData(data);
885 : // After we've compiled the function, we don't need data about its
886 : // skippable functions any more.
887 38284 : shared_info->set_preparsed_scope_data(isolate->heap()->null_value());
888 : }
889 : }
890 :
891 : // Parse and update ParseInfo with the results.
892 576604 : if (!parsing::ParseFunction(&parse_info, shared_info, isolate)) {
893 455 : return FailWithPendingException(isolate, flag);
894 : }
895 :
896 : // Generate the unoptimized bytecode or asm-js data.
897 : std::forward_list<std::unique_ptr<CompilationJob>> inner_function_jobs;
898 : std::unique_ptr<CompilationJob> outer_function_job(
899 576147 : GenerateUnoptimizedCode(&parse_info, isolate, &inner_function_jobs));
900 576148 : if (!outer_function_job) {
901 30 : return FailWithPendingException(isolate, flag);
902 : }
903 :
904 : // Internalize ast values onto the heap.
905 576118 : parse_info.ast_value_factory()->Internalize(isolate);
906 :
907 : // Finalize compilation of the unoptimized bytecode or asm-js data.
908 576119 : if (!FinalizeUnoptimizedCode(&parse_info, isolate, shared_info,
909 : outer_function_job.get(),
910 576119 : &inner_function_jobs)) {
911 0 : return FailWithPendingException(isolate, flag);
912 : }
913 :
914 : DCHECK(!isolate->has_pending_exception());
915 : return true;
916 : }
917 :
918 717628 : bool Compiler::Compile(Handle<JSFunction> function, ClearExceptionFlag flag) {
919 : // We should never reach here if the function is already compiled or optimized
920 : DCHECK(!function->is_compiled());
921 : DCHECK(!function->IsOptimized());
922 : DCHECK(!function->HasOptimizationMarker());
923 : DCHECK(!function->HasOptimizedCode());
924 :
925 : Isolate* isolate = function->GetIsolate();
926 : Handle<SharedFunctionInfo> shared_info = handle(function->shared());
927 : DCHECK(AllowCompilation::IsAllowed(isolate));
928 :
929 : // Ensure shared function info is compiled.
930 717628 : if (!shared_info->is_compiled() && !Compile(shared_info, flag)) return false;
931 : Handle<Code> code = handle(shared_info->code(), isolate);
932 :
933 : // Allocate literals for the JSFunction.
934 717148 : JSFunction::EnsureLiterals(function);
935 :
936 : // Optimize now if --always-opt is enabled.
937 867304 : if (FLAG_always_opt && !function->shared()->HasAsmWasmData()) {
938 149741 : if (FLAG_trace_opt) {
939 0 : PrintF("[optimizing ");
940 0 : function->ShortPrint();
941 0 : PrintF(" because --always-opt]\n");
942 : }
943 : Handle<Code> opt_code;
944 149740 : if (GetOptimizedCode(function, ConcurrencyMode::kNotConcurrent)
945 299481 : .ToHandle(&opt_code)) {
946 : code = opt_code;
947 : }
948 : }
949 :
950 : // Install code on closure.
951 717147 : function->set_code(*code);
952 :
953 : // Check postconditions on success.
954 : DCHECK(!isolate->has_pending_exception());
955 : DCHECK(function->shared()->is_compiled());
956 : DCHECK(function->is_compiled());
957 717148 : return true;
958 : }
959 :
960 301254 : bool Compiler::CompileOptimized(Handle<JSFunction> function,
961 : ConcurrencyMode mode) {
962 301254 : if (function->IsOptimized()) return true;
963 : Isolate* isolate = function->GetIsolate();
964 : DCHECK(AllowCompilation::IsAllowed(isolate));
965 :
966 : // Start a compilation.
967 : Handle<Code> code;
968 602507 : if (!GetOptimizedCode(function, mode).ToHandle(&code)) {
969 : // Optimization failed, get unoptimized code. Unoptimized code must exist
970 : // already if we are optimizing.
971 : DCHECK(!isolate->has_pending_exception());
972 : DCHECK(function->shared()->is_compiled());
973 : code = handle(function->shared()->code(), isolate);
974 : }
975 :
976 : // Install code on closure.
977 301253 : function->set_code(*code);
978 :
979 : // Check postconditions on success.
980 : DCHECK(!isolate->has_pending_exception());
981 : DCHECK(function->shared()->is_compiled());
982 : DCHECK(function->is_compiled());
983 : DCHECK_IMPLIES(function->HasOptimizationMarker(),
984 : function->IsInOptimizationQueue());
985 : DCHECK_IMPLIES(function->HasOptimizationMarker(),
986 : function->ChecksOptimizationMarker());
987 : DCHECK_IMPLIES(function->IsInOptimizationQueue(),
988 : mode == ConcurrencyMode::kConcurrent);
989 301254 : return true;
990 : }
991 :
992 1156 : MaybeHandle<JSArray> Compiler::CompileForLiveEdit(Handle<Script> script) {
993 : Isolate* isolate = script->GetIsolate();
994 : DCHECK(AllowCompilation::IsAllowed(isolate));
995 :
996 : // In order to ensure that live edit function info collection finds the newly
997 : // generated shared function infos, clear the script's list temporarily
998 : // and restore it at the end of this method.
999 : Handle<FixedArray> old_function_infos(script->shared_function_infos(),
1000 : isolate);
1001 2312 : script->set_shared_function_infos(isolate->heap()->empty_fixed_array());
1002 :
1003 : // Start a compilation.
1004 1156 : ParseInfo parse_info(script);
1005 : parse_info.set_eager();
1006 :
1007 : // TODO(635): support extensions.
1008 : Handle<JSArray> infos;
1009 : Handle<SharedFunctionInfo> shared_info;
1010 2312 : if (CompileToplevel(&parse_info, isolate).ToHandle(&shared_info)) {
1011 : // Check postconditions on success.
1012 : DCHECK(!isolate->has_pending_exception());
1013 : infos = LiveEditFunctionTracker::Collect(parse_info.literal(), script,
1014 1137 : parse_info.zone(), isolate);
1015 : }
1016 :
1017 : // Restore the original function info list in order to remain side-effect
1018 : // free as much as possible, since some code expects the old shared function
1019 : // infos to stick around.
1020 1156 : script->set_shared_function_infos(*old_function_infos);
1021 :
1022 1156 : return infos;
1023 : }
1024 :
1025 3647841 : MaybeHandle<JSFunction> Compiler::GetFunctionFromEval(
1026 : Handle<String> source, Handle<SharedFunctionInfo> outer_info,
1027 : Handle<Context> context, LanguageMode language_mode,
1028 : ParseRestriction restriction, int parameters_end_pos,
1029 : int eval_scope_position, int eval_position, int line_offset,
1030 : int column_offset, Handle<Object> script_name,
1031 : ScriptOriginOptions options) {
1032 7190419 : Isolate* isolate = source->GetIsolate();
1033 : int source_length = source->length();
1034 3647841 : isolate->counters()->total_eval_size()->Increment(source_length);
1035 3647841 : isolate->counters()->total_compile_size()->Increment(source_length);
1036 :
1037 : // The cache lookup key needs to be aware of the separation between the
1038 : // parameters and the body to prevent this valid invocation:
1039 : // Function("", "function anonymous(\n/**/) {\n}");
1040 : // from adding an entry that falsely approves this invalid invocation:
1041 : // Function("\n/**/) {\nfunction anonymous(", "}");
1042 : // The actual eval_scope_position for indirect eval and CreateDynamicFunction
1043 : // is unused (just 0), which means it's an available field to use to indicate
1044 : // this separation. But to make sure we're not causing other false hits, we
1045 : // negate the scope position.
1046 : int position = eval_scope_position;
1047 3647841 : if (FLAG_harmony_function_tostring &&
1048 16454 : restriction == ONLY_SINGLE_FUNCTION_LITERAL &&
1049 8227 : parameters_end_pos != kNoSourcePosition) {
1050 : // use the parameters_end_pos as the eval_scope_position in the eval cache.
1051 : DCHECK_EQ(eval_scope_position, 0);
1052 5495 : position = -parameters_end_pos;
1053 : }
1054 : CompilationCache* compilation_cache = isolate->compilation_cache();
1055 : InfoVectorPair eval_result = compilation_cache->LookupEval(
1056 3647841 : source, outer_info, context, language_mode, position);
1057 : Handle<Cell> vector;
1058 3647841 : if (eval_result.has_vector()) {
1059 2313581 : vector = Handle<Cell>(eval_result.vector(), isolate);
1060 : }
1061 :
1062 : Handle<SharedFunctionInfo> shared_info;
1063 : Handle<Script> script;
1064 3647841 : if (eval_result.has_shared()) {
1065 : shared_info = Handle<SharedFunctionInfo>(eval_result.shared(), isolate);
1066 : script = Handle<Script>(Script::cast(shared_info->script()), isolate);
1067 : } else {
1068 971748 : script = isolate->factory()->NewScript(source);
1069 971748 : if (isolate->NeedsSourcePositionsForProfiling()) {
1070 14009 : Script::InitLineEnds(script);
1071 : }
1072 971748 : if (!script_name.is_null()) {
1073 18 : script->set_name(*script_name);
1074 : script->set_line_offset(line_offset);
1075 : script->set_column_offset(column_offset);
1076 : }
1077 971748 : script->set_origin_options(options);
1078 971748 : script->set_compilation_type(Script::COMPILATION_TYPE_EVAL);
1079 :
1080 971748 : script->set_eval_from_shared(*outer_info);
1081 971748 : if (eval_position == kNoSourcePosition) {
1082 : // If the position is missing, attempt to get the code offset by
1083 : // walking the stack. Do not translate the code offset into source
1084 : // position, but store it as negative value for lazy translation.
1085 373277 : StackTraceFrameIterator it(script->GetIsolate());
1086 746488 : if (!it.done() && it.is_javascript()) {
1087 373211 : FrameSummary summary = FrameSummary::GetTop(it.javascript_frame());
1088 : script->set_eval_from_shared(
1089 373211 : summary.AsJavaScript().function()->shared());
1090 373211 : eval_position = -summary.code_offset();
1091 : } else {
1092 : eval_position = 0;
1093 : }
1094 : }
1095 : script->set_eval_from_position(eval_position);
1096 :
1097 971748 : ParseInfo parse_info(script);
1098 : parse_info.set_eval();
1099 : parse_info.set_language_mode(language_mode);
1100 : parse_info.set_parse_restriction(restriction);
1101 : parse_info.set_parameters_end_pos(parameters_end_pos);
1102 971748 : if (!context->IsNativeContext()) {
1103 563575 : parse_info.set_outer_scope_info(handle(context->scope_info()));
1104 : }
1105 :
1106 1943496 : if (!CompileToplevel(&parse_info, isolate).ToHandle(&shared_info)) {
1107 105263 : return MaybeHandle<JSFunction>();
1108 866485 : }
1109 : }
1110 :
1111 : // If caller is strict mode, the result must be in strict mode as well.
1112 : DCHECK(is_sloppy(language_mode) || is_strict(shared_info->language_mode()));
1113 :
1114 : Handle<JSFunction> result;
1115 3542578 : if (eval_result.has_shared()) {
1116 2676093 : if (eval_result.has_vector()) {
1117 : result = isolate->factory()->NewFunctionFromSharedFunctionInfo(
1118 2313581 : shared_info, context, vector, NOT_TENURED);
1119 : } else {
1120 : result = isolate->factory()->NewFunctionFromSharedFunctionInfo(
1121 362512 : shared_info, context, NOT_TENURED);
1122 362512 : JSFunction::EnsureLiterals(result);
1123 : // Make sure to cache this result.
1124 : Handle<Cell> new_vector(result->feedback_vector_cell(), isolate);
1125 : compilation_cache->PutEval(source, outer_info, context, shared_info,
1126 362512 : new_vector, eval_scope_position);
1127 : }
1128 : } else {
1129 : result = isolate->factory()->NewFunctionFromSharedFunctionInfo(
1130 866485 : shared_info, context, NOT_TENURED);
1131 866485 : JSFunction::EnsureLiterals(result);
1132 : // Add the SharedFunctionInfo and the LiteralsArray to the eval cache if
1133 : // we didn't retrieve from there.
1134 : Handle<Cell> vector(result->feedback_vector_cell(), isolate);
1135 : compilation_cache->PutEval(source, outer_info, context, shared_info, vector,
1136 866485 : eval_scope_position);
1137 : }
1138 :
1139 : // OnAfterCompile has to be called after we create the JSFunction, which we
1140 : // may require to recompile the eval for debugging, if we find a function
1141 : // that contains break points in the eval script.
1142 3542578 : isolate->debug()->OnAfterCompile(script);
1143 :
1144 3542578 : return result;
1145 : }
1146 :
1147 : namespace {
1148 :
1149 310 : bool ContainsAsmModule(Handle<Script> script) {
1150 : DisallowHeapAllocation no_gc;
1151 310 : SharedFunctionInfo::ScriptIterator iter(script);
1152 7113 : while (SharedFunctionInfo* info = iter.Next()) {
1153 6813 : if (info->HasAsmWasmData()) return true;
1154 : }
1155 : return false;
1156 : }
1157 :
1158 : bool ShouldProduceCodeCache(ScriptCompiler::CompileOptions options) {
1159 237196 : return options == ScriptCompiler::kProduceCodeCache ||
1160 : options == ScriptCompiler::kProduceFullCodeCache;
1161 : }
1162 :
1163 : } // namespace
1164 :
1165 64 : bool Compiler::CodeGenerationFromStringsAllowed(Isolate* isolate,
1166 : Handle<Context> context,
1167 : Handle<String> source) {
1168 : DCHECK(context->allow_code_gen_from_strings()->IsFalse(isolate));
1169 : // Check with callback if set.
1170 : AllowCodeGenerationFromStringsCallback callback =
1171 : isolate->allow_code_gen_callback();
1172 64 : if (callback == nullptr) {
1173 : // No callback set and code generation disallowed.
1174 : return false;
1175 : } else {
1176 : // Callback set. Let it decide if code generation is allowed.
1177 46 : VMState<EXTERNAL> state(isolate);
1178 46 : return callback(v8::Utils::ToLocal(context), v8::Utils::ToLocal(source));
1179 : }
1180 : }
1181 :
1182 1198425 : MaybeHandle<JSFunction> Compiler::GetFunctionFromString(
1183 : Handle<Context> context, Handle<String> source,
1184 : ParseRestriction restriction, int parameters_end_pos) {
1185 : Isolate* const isolate = context->GetIsolate();
1186 : Handle<Context> native_context(context->native_context(), isolate);
1187 :
1188 : // Check if native context allows code generation from
1189 : // strings. Throw an exception if it doesn't.
1190 1198461 : if (native_context->allow_code_gen_from_strings()->IsFalse(isolate) &&
1191 36 : !CodeGenerationFromStringsAllowed(isolate, native_context, source)) {
1192 : Handle<Object> error_message =
1193 24 : native_context->ErrorMessageForCodeGenerationFromStrings();
1194 48 : THROW_NEW_ERROR(isolate, NewEvalError(MessageTemplate::kCodeGenFromStrings,
1195 : error_message),
1196 : JSFunction);
1197 : }
1198 :
1199 : // Compile source string in the native context.
1200 : int eval_scope_position = 0;
1201 : int eval_position = kNoSourcePosition;
1202 : Handle<SharedFunctionInfo> outer_info(native_context->closure()->shared());
1203 : return Compiler::GetFunctionFromEval(
1204 : source, outer_info, native_context, LanguageMode::kSloppy, restriction,
1205 1198401 : parameters_end_pos, eval_scope_position, eval_position);
1206 : }
1207 :
1208 236715 : MaybeHandle<SharedFunctionInfo> Compiler::GetSharedFunctionInfoForScript(
1209 : Handle<String> source, MaybeHandle<Object> maybe_script_name,
1210 : int line_offset, int column_offset, ScriptOriginOptions resource_options,
1211 : MaybeHandle<Object> maybe_source_map_url, Handle<Context> context,
1212 : v8::Extension* extension, ScriptData** cached_data,
1213 : ScriptCompiler::CompileOptions compile_options, NativesFlag natives,
1214 : MaybeHandle<FixedArray> maybe_host_defined_options) {
1215 525722 : Isolate* isolate = source->GetIsolate();
1216 236715 : if (compile_options == ScriptCompiler::kNoCompileOptions) {
1217 : cached_data = nullptr;
1218 785 : } else if (compile_options == ScriptCompiler::kProduceParserCache ||
1219 : ShouldProduceCodeCache(compile_options)) {
1220 : DCHECK(cached_data && !*cached_data);
1221 : DCHECK_NULL(extension);
1222 : DCHECK(!isolate->debug()->is_loaded());
1223 : } else {
1224 : DCHECK(compile_options == ScriptCompiler::kConsumeParserCache ||
1225 : compile_options == ScriptCompiler::kConsumeCodeCache);
1226 : DCHECK(cached_data && *cached_data);
1227 : DCHECK_NULL(extension);
1228 : }
1229 : int source_length = source->length();
1230 236715 : isolate->counters()->total_load_size()->Increment(source_length);
1231 236716 : isolate->counters()->total_compile_size()->Increment(source_length);
1232 :
1233 236716 : LanguageMode language_mode = construct_language_mode(FLAG_use_strict);
1234 : CompilationCache* compilation_cache = isolate->compilation_cache();
1235 :
1236 : // Do a lookup in the compilation cache but not for extensions.
1237 : MaybeHandle<SharedFunctionInfo> maybe_result;
1238 : Handle<Cell> vector;
1239 236716 : if (extension == nullptr) {
1240 : // First check per-isolate compilation cache.
1241 : InfoVectorPair pair = compilation_cache->LookupScript(
1242 : source, maybe_script_name, line_offset, column_offset, resource_options,
1243 233578 : context, language_mode);
1244 375698 : if (!pair.has_shared() &&
1245 233813 : compile_options == ScriptCompiler::kConsumeCodeCache &&
1246 : !isolate->debug()->is_loaded()) {
1247 : // Then check cached code provided by embedder.
1248 235 : HistogramTimerScope timer(isolate->counters()->compile_deserialize());
1249 : RuntimeCallTimerScope runtimeTimer(isolate,
1250 235 : &RuntimeCallStats::CompileDeserialize);
1251 485 : TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
1252 : "V8.CompileDeserialize");
1253 : Handle<SharedFunctionInfo> inner_result;
1254 470 : if (CodeSerializer::Deserialize(isolate, *cached_data, source)
1255 470 : .ToHandle(&inner_result)) {
1256 : // Promote to per-isolate compilation cache.
1257 : DCHECK(inner_result->is_compiled());
1258 : Handle<FeedbackVector> feedback_vector =
1259 220 : FeedbackVector::New(isolate, inner_result);
1260 220 : vector = isolate->factory()->NewCell(feedback_vector);
1261 : compilation_cache->PutScript(source, context, language_mode,
1262 220 : inner_result, vector);
1263 : Handle<Script> script(Script::cast(inner_result->script()), isolate);
1264 220 : isolate->debug()->OnAfterCompile(script);
1265 220 : return inner_result;
1266 : }
1267 : // Deserializer failed. Fall through to compile.
1268 : } else {
1269 233343 : if (pair.has_shared()) {
1270 : maybe_result = MaybeHandle<SharedFunctionInfo>(pair.shared(), isolate);
1271 : }
1272 233343 : if (pair.has_vector()) {
1273 : vector = Handle<Cell>(pair.vector(), isolate);
1274 : }
1275 : }
1276 : }
1277 :
1278 : base::ElapsedTimer timer;
1279 236496 : if (FLAG_profile_deserialization && ShouldProduceCodeCache(compile_options)) {
1280 : timer.Start();
1281 : }
1282 :
1283 327954 : if (maybe_result.is_null() || ShouldProduceCodeCache(compile_options)) {
1284 : // No cache entry found, or embedder wants a code cache. Compile the script.
1285 :
1286 : // Create a script object describing the script to be compiled.
1287 145038 : Handle<Script> script = isolate->factory()->NewScript(source);
1288 145038 : if (isolate->NeedsSourcePositionsForProfiling()) {
1289 10229 : Script::InitLineEnds(script);
1290 : }
1291 145038 : if (natives == NATIVES_CODE) {
1292 : script->set_type(Script::TYPE_NATIVE);
1293 132711 : } else if (natives == EXTENSION_CODE) {
1294 : script->set_type(Script::TYPE_EXTENSION);
1295 129507 : } else if (natives == INSPECTOR_CODE) {
1296 : script->set_type(Script::TYPE_INSPECTOR);
1297 : }
1298 : Handle<Object> script_name;
1299 145038 : if (maybe_script_name.ToHandle(&script_name)) {
1300 93675 : script->set_name(*script_name);
1301 : script->set_line_offset(line_offset);
1302 : script->set_column_offset(column_offset);
1303 : }
1304 145038 : script->set_origin_options(resource_options);
1305 : Handle<Object> source_map_url;
1306 145038 : if (maybe_source_map_url.ToHandle(&source_map_url)) {
1307 5591 : script->set_source_mapping_url(*source_map_url);
1308 : }
1309 : Handle<FixedArray> host_defined_options;
1310 145038 : if (maybe_host_defined_options.ToHandle(&host_defined_options)) {
1311 126256 : script->set_host_defined_options(*host_defined_options);
1312 : }
1313 :
1314 : // Compile the function and add it to the cache.
1315 145038 : ParseInfo parse_info(script);
1316 290075 : Zone compile_zone(isolate->allocator(), ZONE_NAME);
1317 145038 : if (resource_options.IsModule()) parse_info.set_module();
1318 145038 : if (compile_options != ScriptCompiler::kNoCompileOptions) {
1319 : parse_info.set_cached_data(cached_data);
1320 : }
1321 : parse_info.set_compile_options(compile_options);
1322 : parse_info.set_extension(extension);
1323 145038 : if (!context->IsNativeContext()) {
1324 0 : parse_info.set_outer_scope_info(handle(context->scope_info()));
1325 : }
1326 145038 : if (ShouldProduceCodeCache(compile_options)) {
1327 : parse_info.set_will_serialize();
1328 : parse_info.set_eager(compile_options ==
1329 : ScriptCompiler::kProduceFullCodeCache);
1330 : }
1331 :
1332 : parse_info.set_language_mode(
1333 : stricter_language_mode(parse_info.language_mode(), language_mode));
1334 145038 : maybe_result = CompileToplevel(&parse_info, isolate);
1335 : Handle<SharedFunctionInfo> result;
1336 286938 : if (extension == nullptr && maybe_result.ToHandle(&result)) {
1337 : // We need a feedback vector.
1338 : DCHECK(result->is_compiled());
1339 : Handle<FeedbackVector> feedback_vector =
1340 140406 : FeedbackVector::New(isolate, result);
1341 140406 : vector = isolate->factory()->NewCell(feedback_vector);
1342 : compilation_cache->PutScript(source, context, language_mode, result,
1343 140406 : vector);
1344 140716 : if (ShouldProduceCodeCache(compile_options) &&
1345 310 : !ContainsAsmModule(script)) {
1346 : HistogramTimerScope histogram_timer(
1347 300 : isolate->counters()->compile_serialize());
1348 : RuntimeCallTimerScope runtimeTimer(isolate,
1349 300 : &RuntimeCallStats::CompileSerialize);
1350 900 : TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
1351 : "V8.CompileSerialize");
1352 300 : *cached_data = CodeSerializer::Serialize(isolate, result, source);
1353 300 : if (FLAG_profile_deserialization) {
1354 : PrintF("[Compiling and serializing took %0.3f ms]\n",
1355 0 : timer.Elapsed().InMillisecondsF());
1356 : }
1357 : }
1358 : }
1359 :
1360 145038 : if (maybe_result.is_null()) {
1361 1524 : if (natives != EXTENSION_CODE && natives != NATIVES_CODE) {
1362 1494 : isolate->ReportPendingMessages();
1363 : }
1364 : } else {
1365 143514 : isolate->debug()->OnAfterCompile(script);
1366 145038 : }
1367 : }
1368 236496 : return maybe_result;
1369 : }
1370 :
1371 95 : Handle<SharedFunctionInfo> Compiler::GetSharedFunctionInfoForStreamedScript(
1372 : Handle<Script> script, ParseInfo* parse_info, int source_length) {
1373 95 : Isolate* isolate = script->GetIsolate();
1374 : // TODO(titzer): increment the counters in caller.
1375 95 : isolate->counters()->total_load_size()->Increment(source_length);
1376 95 : isolate->counters()->total_compile_size()->Increment(source_length);
1377 :
1378 95 : LanguageMode language_mode = construct_language_mode(FLAG_use_strict);
1379 : parse_info->set_language_mode(
1380 : stricter_language_mode(parse_info->language_mode(), language_mode));
1381 :
1382 : Handle<SharedFunctionInfo> result;
1383 190 : if (CompileToplevel(parse_info, isolate).ToHandle(&result)) {
1384 95 : isolate->debug()->OnAfterCompile(script);
1385 : }
1386 95 : return result;
1387 : }
1388 :
1389 4704561 : Handle<SharedFunctionInfo> Compiler::GetSharedFunctionInfo(
1390 4155760 : FunctionLiteral* literal, Handle<Script> script, Isolate* isolate) {
1391 : // Precondition: code has been parsed and scopes have been analyzed.
1392 : MaybeHandle<SharedFunctionInfo> maybe_existing;
1393 :
1394 : // Find any previously allocated shared function info for the given literal.
1395 4704561 : maybe_existing = script->FindSharedFunctionInfo(isolate, literal);
1396 :
1397 : // If we found an existing shared function info, return it.
1398 : Handle<SharedFunctionInfo> existing;
1399 4704561 : if (maybe_existing.ToHandle(&existing)) {
1400 : DCHECK(!existing->is_toplevel());
1401 548801 : return existing;
1402 : }
1403 :
1404 : // Allocate a shared function info object which will be compiled lazily.
1405 : Handle<SharedFunctionInfo> result =
1406 4155760 : isolate->factory()->NewSharedFunctionInfoForLiteral(literal, script);
1407 : result->set_is_toplevel(false);
1408 4155760 : Scope* outer_scope = literal->scope()->GetOuterScopeWithContext();
1409 4155760 : if (outer_scope) {
1410 3754634 : result->set_outer_scope_info(*outer_scope->scope_info());
1411 : }
1412 4155760 : return result;
1413 : }
1414 :
1415 1678 : Handle<SharedFunctionInfo> Compiler::GetSharedFunctionInfoForNative(
1416 : v8::Extension* extension, Handle<String> name) {
1417 : Isolate* isolate = name->GetIsolate();
1418 : v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
1419 :
1420 : // Compute the function template for the native function.
1421 : v8::Local<v8::FunctionTemplate> fun_template =
1422 : extension->GetNativeFunctionTemplate(v8_isolate,
1423 1678 : v8::Utils::ToLocal(name));
1424 : DCHECK(!fun_template.IsEmpty());
1425 :
1426 : // Instantiate the function and create a shared function info from it.
1427 : Handle<JSFunction> fun = Handle<JSFunction>::cast(Utils::OpenHandle(
1428 1678 : *fun_template->GetFunction(v8_isolate->GetCurrentContext())
1429 1678 : .ToLocalChecked()));
1430 : Handle<Code> code = Handle<Code>(fun->shared()->code());
1431 : Handle<Code> construct_stub = Handle<Code>(fun->shared()->construct_stub());
1432 : Handle<SharedFunctionInfo> shared = isolate->factory()->NewSharedFunctionInfo(
1433 : name, FunctionKind::kNormalFunction, code,
1434 1678 : Handle<ScopeInfo>(fun->shared()->scope_info()));
1435 1678 : shared->set_outer_scope_info(fun->shared()->outer_scope_info());
1436 1678 : shared->SetConstructStub(*construct_stub);
1437 1678 : shared->set_feedback_metadata(fun->shared()->feedback_metadata());
1438 :
1439 : // Copy the function data to the shared function info.
1440 1678 : shared->set_function_data(fun->shared()->function_data());
1441 : int parameters = fun->shared()->internal_formal_parameter_count();
1442 : shared->set_internal_formal_parameter_count(parameters);
1443 :
1444 1678 : return shared;
1445 : }
1446 :
1447 6036 : MaybeHandle<Code> Compiler::GetOptimizedCodeForOSR(Handle<JSFunction> function,
1448 : BailoutId osr_offset,
1449 : JavaScriptFrame* osr_frame) {
1450 : DCHECK(!osr_offset.IsNone());
1451 : DCHECK_NOT_NULL(osr_frame);
1452 : return GetOptimizedCode(function, ConcurrencyMode::kNotConcurrent, osr_offset,
1453 6036 : osr_frame);
1454 : }
1455 :
1456 25 : CompilationJob* Compiler::PrepareUnoptimizedCompilationJob(
1457 25 : ParseInfo* parse_info, Isolate* isolate) {
1458 : VMState<BYTECODE_COMPILER> state(isolate);
1459 : std::unique_ptr<CompilationJob> job(
1460 : interpreter::Interpreter::NewCompilationJob(
1461 25 : parse_info, parse_info->literal(), isolate));
1462 25 : if (job->PrepareJob() != CompilationJob::SUCCEEDED) {
1463 : return nullptr;
1464 : }
1465 25 : return job.release();
1466 : }
1467 :
1468 7821 : bool Compiler::FinalizeCompilationJob(CompilationJob* raw_job) {
1469 : // Take ownership of compilation job. Deleting job also tears down the zone.
1470 : std::unique_ptr<CompilationJob> job(raw_job);
1471 :
1472 7821 : if (job->compilation_info()->IsOptimizing()) {
1473 7802 : VMState<COMPILER> state(job->compilation_info()->isolate());
1474 7802 : return FinalizeOptimizedCompilationJob(job.get()) ==
1475 7802 : CompilationJob::SUCCEEDED;
1476 : } else {
1477 19 : VMState<BYTECODE_COMPILER> state(job->compilation_info()->isolate());
1478 19 : return FinalizeUnoptimizedCompilationJob(job.get()) ==
1479 19 : CompilationJob::SUCCEEDED;
1480 : }
1481 : }
1482 :
1483 14429117 : void Compiler::PostInstantiation(Handle<JSFunction> function,
1484 : PretenureFlag pretenure) {
1485 : Handle<SharedFunctionInfo> shared(function->shared());
1486 :
1487 16712126 : if (FLAG_always_opt && shared->allows_lazy_compilation() &&
1488 16354149 : !shared->optimization_disabled() && !shared->HasAsmWasmData() &&
1489 : shared->is_compiled()) {
1490 : // TODO(mvstanton): pass pretenure flag to EnsureLiterals.
1491 466900 : JSFunction::EnsureLiterals(function);
1492 :
1493 466900 : if (!function->IsOptimized()) {
1494 : // Only mark for optimization if we don't already have optimized code.
1495 466900 : if (!function->HasOptimizedCode()) {
1496 188821 : function->MarkForOptimization(ConcurrencyMode::kNotConcurrent);
1497 : }
1498 : }
1499 : }
1500 :
1501 14429117 : if (shared->is_compiled() && !shared->HasAsmWasmData()) {
1502 : // TODO(mvstanton): pass pretenure flag to EnsureLiterals.
1503 9524740 : JSFunction::EnsureLiterals(function);
1504 :
1505 : Code* code = function->feedback_vector()->optimized_code();
1506 9524741 : if (code != nullptr) {
1507 : // Caching of optimized code enabled and optimized code found.
1508 : DCHECK(!code->marked_for_deoptimization());
1509 : DCHECK(function->shared()->is_compiled());
1510 494189 : function->set_code(code);
1511 : }
1512 : }
1513 14429119 : }
1514 :
1515 : } // namespace internal
1516 : } // namespace v8
|