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/asmjs/asm-js.h"
11 : #include "src/asmjs/asm-typer.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/bootstrapper.h"
17 : #include "src/codegen.h"
18 : #include "src/compilation-cache.h"
19 : #include "src/compiler-dispatcher/compiler-dispatcher.h"
20 : #include "src/compiler-dispatcher/optimizing-compile-dispatcher.h"
21 : #include "src/compiler/pipeline.h"
22 : #include "src/crankshaft/hydrogen.h"
23 : #include "src/debug/debug.h"
24 : #include "src/debug/liveedit.h"
25 : #include "src/frames-inl.h"
26 : #include "src/full-codegen/full-codegen.h"
27 : #include "src/globals.h"
28 : #include "src/heap/heap.h"
29 : #include "src/interpreter/interpreter.h"
30 : #include "src/isolate-inl.h"
31 : #include "src/log-inl.h"
32 : #include "src/messages.h"
33 : #include "src/parsing/parsing.h"
34 : #include "src/parsing/rewriter.h"
35 : #include "src/parsing/scanner-character-streams.h"
36 : #include "src/runtime-profiler.h"
37 : #include "src/snapshot/code-serializer.h"
38 : #include "src/vm-state-inl.h"
39 :
40 : namespace v8 {
41 : namespace internal {
42 :
43 : // A wrapper around a ParseInfo that detaches the parser handles from the
44 : // underlying DeferredHandleScope and stores them in info_ on destruction.
45 : class ParseHandleScope final {
46 : public:
47 : explicit ParseHandleScope(ParseInfo* info, Isolate* isolate)
48 0 : : deferred_(isolate), info_(info) {}
49 0 : ~ParseHandleScope() { info_->set_deferred_handles(deferred_.Detach()); }
50 :
51 : private:
52 : DeferredHandleScope deferred_;
53 : ParseInfo* info_;
54 : };
55 :
56 : // A wrapper around a CompilationInfo that detaches the Handles from
57 : // the underlying DeferredHandleScope and stores them in info_ on
58 : // destruction.
59 : class CompilationHandleScope final {
60 : public:
61 148169 : explicit CompilationHandleScope(CompilationInfo* info)
62 148169 : : deferred_(info->isolate()), info_(info) {}
63 148169 : ~CompilationHandleScope() { info_->set_deferred_handles(deferred_.Detach()); }
64 :
65 : private:
66 : DeferredHandleScope deferred_;
67 : CompilationInfo* info_;
68 : };
69 :
70 : // Helper that times a scoped region and records the elapsed time.
71 : struct ScopedTimer {
72 10869608 : explicit ScopedTimer(base::TimeDelta* location) : location_(location) {
73 : DCHECK(location_ != NULL);
74 : timer_.Start();
75 : }
76 :
77 32609002 : ~ScopedTimer() { *location_ += timer_.Elapsed(); }
78 :
79 : base::ElapsedTimer timer_;
80 : base::TimeDelta* location_;
81 : };
82 :
83 : // ----------------------------------------------------------------------------
84 : // Implementation of CompilationJob
85 :
86 3415224 : CompilationJob::CompilationJob(Isolate* isolate, CompilationInfo* info,
87 : const char* compiler_name, State initial_state)
88 : : info_(info),
89 : isolate_thread_id_(isolate->thread_id()),
90 : compiler_name_(compiler_name),
91 : state_(initial_state),
92 3794247 : stack_limit_(isolate->stack_guard()->real_climit()),
93 11382741 : executed_on_background_thread_(false) {}
94 :
95 3582808 : CompilationJob::Status CompilationJob::PrepareJob() {
96 : DCHECK(ThreadId::Current().Equals(info()->isolate()->thread_id()));
97 3582808 : DisallowJavascriptExecution no_js(isolate());
98 :
99 3582810 : if (FLAG_trace_opt && info()->IsOptimizing()) {
100 0 : OFStream os(stdout);
101 0 : os << "[compiling method " << Brief(*info()->closure()) << " using "
102 0 : << compiler_name_;
103 0 : if (info()->is_osr()) os << " OSR";
104 0 : os << "]" << std::endl;
105 : }
106 :
107 : // Delegate to the underlying implementation.
108 : DCHECK(state() == State::kReadyToPrepare);
109 7165615 : ScopedTimer t(&time_taken_to_prepare_);
110 7165640 : return UpdateState(PrepareJobImpl(), State::kReadyToExecute);
111 : }
112 :
113 3647507 : CompilationJob::Status CompilationJob::ExecuteJob() {
114 : std::unique_ptr<DisallowHeapAllocation> no_allocation;
115 : std::unique_ptr<DisallowHandleAllocation> no_handles;
116 : std::unique_ptr<DisallowHandleDereference> no_deref;
117 : std::unique_ptr<DisallowCodeDependencyChange> no_dependency_change;
118 3647507 : if (can_execute_on_background_thread()) {
119 2798690 : no_allocation.reset(new DisallowHeapAllocation());
120 2798712 : no_handles.reset(new DisallowHandleAllocation());
121 2798707 : no_deref.reset(new DisallowHandleDereference());
122 2798711 : no_dependency_change.reset(new DisallowCodeDependencyChange());
123 : executed_on_background_thread_ =
124 5597387 : !ThreadId::Current().Equals(isolate_thread_id_);
125 : } else {
126 : DCHECK(ThreadId::Current().Equals(isolate_thread_id_));
127 : }
128 :
129 : // Delegate to the underlying implementation.
130 : DCHECK(state() == State::kReadyToExecute);
131 7294996 : ScopedTimer t(&time_taken_to_execute_);
132 7295081 : return UpdateState(ExecuteJobImpl(), State::kReadyToFinalize);
133 : }
134 :
135 3639310 : CompilationJob::Status CompilationJob::FinalizeJob() {
136 : DCHECK(ThreadId::Current().Equals(info()->isolate()->thread_id()));
137 : DisallowCodeDependencyChange no_dependency_change;
138 3639310 : DisallowJavascriptExecution no_js(isolate());
139 : DCHECK(!info()->dependencies()->HasAborted());
140 :
141 : // Delegate to the underlying implementation.
142 : DCHECK(state() == State::kReadyToFinalize);
143 7278629 : ScopedTimer t(&time_taken_to_finalize_);
144 7278658 : return UpdateState(FinalizeJobImpl(), State::kSucceeded);
145 : }
146 :
147 0 : CompilationJob::Status CompilationJob::RetryOptimization(BailoutReason reason) {
148 : DCHECK(info_->IsOptimizing());
149 90 : info_->RetryOptimization(reason);
150 90 : state_ = State::kFailed;
151 0 : return FAILED;
152 : }
153 :
154 697 : CompilationJob::Status CompilationJob::AbortOptimization(BailoutReason reason) {
155 : DCHECK(info_->IsOptimizing());
156 697 : info_->AbortOptimization(reason);
157 697 : state_ = State::kFailed;
158 697 : return FAILED;
159 : }
160 :
161 2926261 : void CompilationJob::RecordUnoptimizedCompilationStats() const {
162 : int code_size;
163 2926261 : if (info()->has_bytecode_array()) {
164 2077425 : code_size = info()->bytecode_array()->SizeIncludingMetadata();
165 : } else {
166 848836 : code_size = info()->code()->SizeIncludingMetadata();
167 : }
168 :
169 2926260 : Counters* counters = isolate()->counters();
170 : // TODO(4280): Rename counters from "baseline" to "unoptimized" eventually.
171 2926260 : counters->total_baseline_code_size()->Increment(code_size);
172 2926260 : counters->total_baseline_compile_count()->Increment(1);
173 :
174 : // TODO(5203): Add timers for each phase of compilation.
175 2926262 : }
176 :
177 642433 : void CompilationJob::RecordOptimizedCompilationStats() const {
178 : DCHECK(info()->IsOptimizing());
179 : Handle<JSFunction> function = info()->closure();
180 642433 : if (!function->IsOptimized()) {
181 : // Concurrent recompilation and OSR may race. Increment only once.
182 : int opt_count = function->shared()->opt_count();
183 642255 : function->shared()->set_opt_count(opt_count + 1);
184 : }
185 642433 : double ms_creategraph = time_taken_to_prepare_.InMillisecondsF();
186 642436 : double ms_optimize = time_taken_to_execute_.InMillisecondsF();
187 642436 : double ms_codegen = time_taken_to_finalize_.InMillisecondsF();
188 642436 : if (FLAG_trace_opt) {
189 0 : PrintF("[optimizing ");
190 0 : function->ShortPrint();
191 : PrintF(" - took %0.3f, %0.3f, %0.3f ms]\n", ms_creategraph, ms_optimize,
192 0 : ms_codegen);
193 : }
194 642436 : if (FLAG_trace_opt_stats) {
195 : static double compilation_time = 0.0;
196 : static int compiled_functions = 0;
197 : static int code_size = 0;
198 :
199 0 : compilation_time += (ms_creategraph + ms_optimize + ms_codegen);
200 0 : compiled_functions++;
201 0 : code_size += function->shared()->SourceSize();
202 : PrintF("Compiled: %d functions with %d byte source size in %fms.\n",
203 0 : compiled_functions, code_size, compilation_time);
204 : }
205 642436 : if (FLAG_hydrogen_stats) {
206 : isolate()->GetHStatistics()->IncrementSubtotals(time_taken_to_prepare_,
207 : time_taken_to_execute_,
208 0 : time_taken_to_finalize_);
209 : }
210 642436 : }
211 :
212 13408061 : Isolate* CompilationJob::isolate() const { return info()->isolate(); }
213 :
214 : namespace {
215 :
216 1976332 : void AddWeakObjectToCodeDependency(Isolate* isolate, Handle<HeapObject> object,
217 : Handle<Code> code) {
218 1976332 : Handle<WeakCell> cell = Code::WeakCellFor(code);
219 1976333 : Heap* heap = isolate->heap();
220 1976333 : if (heap->InNewSpace(*object)) {
221 926002 : heap->AddWeakNewSpaceObjectToCodeDependency(object, cell);
222 : } else {
223 1050331 : Handle<DependentCode> dep(heap->LookupWeakObjectToCodeDependency(object));
224 : dep =
225 1050332 : DependentCode::InsertWeakCode(dep, DependentCode::kWeakCodeGroup, cell);
226 1050332 : heap->AddWeakObjectToCodeDependency(object, dep);
227 : }
228 1976334 : }
229 :
230 : } // namespace
231 :
232 640383 : void CompilationJob::RegisterWeakObjectsInOptimizedCode(Handle<Code> code) {
233 : // TODO(turbofan): Move this to pipeline.cc once Crankshaft dies.
234 : Isolate* const isolate = code->GetIsolate();
235 : DCHECK(code->is_optimized_code());
236 : std::vector<Handle<Map>> maps;
237 : std::vector<Handle<HeapObject>> objects;
238 : {
239 : DisallowHeapAllocation no_gc;
240 : int const mode_mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
241 : RelocInfo::ModeMask(RelocInfo::CELL);
242 6680808 : for (RelocIterator it(*code, mode_mask); !it.done(); it.next()) {
243 6040424 : RelocInfo::Mode mode = it.rinfo()->rmode();
244 6040424 : if (mode == RelocInfo::CELL &&
245 0 : code->IsWeakObjectInOptimizedCode(it.rinfo()->target_cell())) {
246 0 : objects.push_back(handle(it.rinfo()->target_cell(), isolate));
247 12080848 : } else if (mode == RelocInfo::EMBEDDED_OBJECT &&
248 : code->IsWeakObjectInOptimizedCode(
249 12080848 : it.rinfo()->target_object())) {
250 2180925 : Handle<HeapObject> object(HeapObject::cast(it.rinfo()->target_object()),
251 : isolate);
252 2180926 : if (object->IsMap()) {
253 204592 : maps.push_back(Handle<Map>::cast(object));
254 : } else {
255 1976334 : objects.push_back(object);
256 : }
257 : }
258 : }
259 : }
260 1485356 : for (Handle<Map> map : maps) {
261 204592 : if (map->dependent_code()->IsEmpty(DependentCode::kWeakCodeGroup)) {
262 38141 : isolate->heap()->AddRetainedMap(map);
263 : }
264 204592 : Map::AddDependentCode(map, DependentCode::kWeakCodeGroup, code);
265 : }
266 3257098 : for (Handle<HeapObject> object : objects) {
267 1976333 : AddWeakObjectToCodeDependency(isolate, object, code);
268 : }
269 : code->set_can_have_weak_objects(true);
270 640383 : }
271 :
272 : // ----------------------------------------------------------------------------
273 : // Local helper methods that make up the compilation pipeline.
274 :
275 : namespace {
276 :
277 4686855 : void RecordFunctionCompilation(CodeEventListener::LogEventsAndTags tag,
278 4692948 : CompilationInfo* info) {
279 : // Log the code generation. If source information is available include
280 : // script name and line number. Check explicitly whether logging is
281 : // enabled as finding the line number is not free.
282 14060081 : if (info->isolate()->logger()->is_logging_code_events() ||
283 4686371 : info->isolate()->is_profiling()) {
284 1539 : Handle<SharedFunctionInfo> shared = info->shared_info();
285 : Handle<Script> script = info->parse_info()->script();
286 : Handle<AbstractCode> abstract_code =
287 : info->has_bytecode_array()
288 : ? Handle<AbstractCode>::cast(info->bytecode_array())
289 1539 : : Handle<AbstractCode>::cast(info->code());
290 1539 : if (abstract_code.is_identical_to(
291 3078 : info->isolate()->builtins()->CompileLazy())) {
292 4686855 : return;
293 : }
294 1539 : int line_num = Script::GetLineNumber(script, shared->start_position()) + 1;
295 : int column_num =
296 1539 : Script::GetColumnNumber(script, shared->start_position()) + 1;
297 : String* script_name = script->name()->IsString()
298 : ? String::cast(script->name())
299 3015 : : info->isolate()->heap()->empty_string();
300 : CodeEventListener::LogEventsAndTags log_tag =
301 : Logger::ToNativeByScript(tag, *script);
302 1539 : PROFILE(info->isolate(),
303 : CodeCreateEvent(log_tag, *abstract_code, *shared, script_name,
304 : line_num, column_num));
305 : }
306 : }
307 :
308 7119154 : void EnsureFeedbackMetadata(CompilationInfo* info) {
309 : DCHECK(info->has_shared_info());
310 :
311 : // If no type feedback metadata exists, create it. At this point the
312 : // AstNumbering pass has already run. Note the snapshot can contain outdated
313 : // vectors for a different configuration, hence we also recreate a new vector
314 : // when the function is not compiled (i.e. no code was serialized).
315 :
316 : // TODO(mvstanton): reintroduce is_empty() predicate to feedback_metadata().
317 12093237 : if (info->shared_info()->feedback_metadata()->length() == 0 ||
318 4531529 : !info->shared_info()->is_compiled()) {
319 : Handle<FeedbackMetadata> feedback_metadata = FeedbackMetadata::New(
320 6676606 : info->isolate(), info->literal()->feedback_vector_spec());
321 6676603 : info->shared_info()->set_feedback_metadata(*feedback_metadata);
322 : }
323 :
324 : // It's very important that recompiles do not alter the structure of the type
325 : // feedback vector. Verify that the structure fits the function literal.
326 7561726 : CHECK(!info->shared_info()->feedback_metadata()->SpecDiffersFrom(
327 : info->literal()->feedback_vector_spec()));
328 3780862 : }
329 :
330 3743060 : bool UseTurboFan(Handle<SharedFunctionInfo> shared) {
331 : bool must_use_ignition_turbo = shared->must_use_ignition_turbo();
332 :
333 : // Check the enabling conditions for Turbofan.
334 : // 1. "use asm" code.
335 7486121 : bool is_turbofanable_asm = FLAG_turbo_asm && shared->asm_function();
336 :
337 : // 2. Fallback for features unsupported by Crankshaft.
338 : bool is_unsupported_by_crankshaft_but_turbofanable =
339 3743060 : must_use_ignition_turbo && strcmp(FLAG_turbo_filter, "~~") == 0;
340 :
341 : // 3. Explicitly enabled by the command-line filter.
342 3743060 : bool passes_turbo_filter = shared->PassesFilter(FLAG_turbo_filter);
343 :
344 3743061 : return is_turbofanable_asm || is_unsupported_by_crankshaft_but_turbofanable ||
345 3743061 : passes_turbo_filter;
346 : }
347 :
348 3550504 : bool ShouldUseIgnition(Handle<SharedFunctionInfo> shared,
349 : bool marked_as_debug) {
350 : // Code which can't be supported by the old pipeline should use Ignition.
351 3550504 : if (shared->must_use_ignition_turbo()) return true;
352 :
353 : // Resumable functions are not supported by {FullCodeGenerator}, suspended
354 : // activations stored as {JSGeneratorObject} on the heap always assume the
355 : // underlying code to be based on the bytecode array.
356 : DCHECK(!IsResumableFunction(shared->kind()));
357 :
358 : // Skip Ignition for asm.js functions.
359 2952785 : if (shared->asm_function()) return false;
360 :
361 : // Skip Ignition for asm wasm code.
362 2945716 : if (FLAG_validate_asm && shared->HasAsmWasmData()) {
363 : return false;
364 : }
365 :
366 : // Code destined for TurboFan should be compiled with Ignition first.
367 2945705 : if (UseTurboFan(shared)) return true;
368 :
369 : // Only use Ignition for any other function if FLAG_ignition is true.
370 1083393 : return FLAG_ignition;
371 : }
372 :
373 3550501 : bool ShouldUseIgnition(CompilationInfo* info) {
374 : DCHECK(info->has_shared_info());
375 3550501 : return ShouldUseIgnition(info->shared_info(), info->is_debug());
376 : }
377 :
378 : bool UseAsmWasm(DeclarationScope* scope, Handle<SharedFunctionInfo> shared_info,
379 : bool is_debug) {
380 : // Check whether asm.js validation is enabled.
381 2929887 : if (!FLAG_validate_asm) return false;
382 :
383 : // Modules that have validated successfully, but were subsequently broken by
384 : // invalid module instantiation attempts are off limit forever.
385 381675 : if (shared_info->is_asm_wasm_broken()) return false;
386 :
387 : // Compiling for debugging is not supported, fall back.
388 381168 : if (is_debug) return false;
389 :
390 : // In stress mode we want to run the validator on everything.
391 380169 : if (FLAG_stress_validate_asm) return true;
392 :
393 : // In general, we respect the "use asm" directive.
394 : return scope->asm_module();
395 : }
396 :
397 702138 : bool UseCompilerDispatcher(Compiler::ConcurrencyMode inner_function_mode,
398 : CompilerDispatcher* dispatcher,
399 : DeclarationScope* scope,
400 : Handle<SharedFunctionInfo> shared_info,
401 : bool is_debug, bool will_serialize) {
402 0 : return inner_function_mode == Compiler::CONCURRENT &&
403 702138 : dispatcher->IsEnabled() && !is_debug && !will_serialize &&
404 702138 : !UseAsmWasm(scope, shared_info, is_debug);
405 : }
406 :
407 2926291 : CompilationJob* GetUnoptimizedCompilationJob(CompilationInfo* info) {
408 : // Function should have been parsed and analyzed before creating a compilation
409 : // job.
410 : DCHECK_NOT_NULL(info->literal());
411 : DCHECK_NOT_NULL(info->scope());
412 :
413 2926291 : if (ShouldUseIgnition(info)) {
414 2077460 : return interpreter::Interpreter::NewCompilationJob(info);
415 : } else {
416 848839 : return FullCodeGenerator::NewCompilationJob(info);
417 : }
418 : }
419 :
420 2932913 : void InstallSharedScopeInfo(CompilationInfo* info,
421 : Handle<SharedFunctionInfo> shared) {
422 2932913 : Handle<ScopeInfo> scope_info = info->scope()->scope_info();
423 2932922 : shared->set_scope_info(*scope_info);
424 2932924 : Scope* outer_scope = info->scope()->GetOuterScopeWithContext();
425 2932925 : if (outer_scope) {
426 2647981 : shared->set_outer_scope_info(*outer_scope->scope_info());
427 : }
428 2932925 : }
429 :
430 2929875 : void InstallSharedCompilationResult(CompilationInfo* info,
431 : Handle<SharedFunctionInfo> shared) {
432 : // TODO(mstarzinger): Compiling for debug code might be used to reveal inner
433 : // functions via {FindSharedFunctionInfoInScript}, in which case we end up
434 : // regenerating existing bytecode. Fix this!
435 2940046 : if (info->is_debug() && info->has_bytecode_array()) {
436 : shared->ClearBytecodeArray();
437 : }
438 : DCHECK(!info->code().is_null());
439 2929874 : shared->ReplaceCode(*info->code());
440 2929880 : if (info->has_bytecode_array()) {
441 : DCHECK(!shared->HasBytecodeArray()); // Only compiled once.
442 : shared->set_bytecode_array(*info->bytecode_array());
443 : }
444 2929879 : }
445 :
446 2929868 : void InstallUnoptimizedCode(CompilationInfo* info) {
447 2929868 : Handle<SharedFunctionInfo> shared = info->shared_info();
448 :
449 : // Update the shared function info with the scope info.
450 2929878 : InstallSharedScopeInfo(info, shared);
451 :
452 : // Install compilation result on the shared function info
453 2929874 : InstallSharedCompilationResult(info, shared);
454 2929879 : }
455 :
456 5852513 : CompilationJob::Status FinalizeUnoptimizedCompilationJob(CompilationJob* job) {
457 2926248 : CompilationJob::Status status = job->FinalizeJob();
458 2926265 : if (status == CompilationJob::SUCCEEDED) {
459 2926310 : CompilationInfo* info = job->info();
460 2926265 : EnsureFeedbackMetadata(info);
461 : DCHECK(!info->code().is_null());
462 5852524 : if (info->parse_info()->literal()->should_be_used_once_hint()) {
463 48 : info->code()->MarkToBeExecutedOnce(info->isolate());
464 : }
465 2926262 : InstallUnoptimizedCode(info);
466 2926263 : RecordFunctionCompilation(CodeEventListener::FUNCTION_TAG, info);
467 2926263 : job->RecordUnoptimizedCompilationStats();
468 : }
469 2926263 : return status;
470 : }
471 :
472 10308030 : void SetSharedFunctionFlagsFromLiteral(FunctionLiteral* literal,
473 : Handle<SharedFunctionInfo> shared_info) {
474 : // Don't overwrite values set by the bootstrapper.
475 3341373 : if (!shared_info->HasLength()) {
476 : shared_info->set_length(literal->function_length());
477 : }
478 : shared_info->set_ast_node_count(literal->ast_node_count());
479 : shared_info->set_has_duplicate_parameters(
480 : literal->has_duplicate_parameters());
481 3341373 : shared_info->SetExpectedNofPropertiesFromEstimate(literal);
482 3341377 : if (literal->dont_optimize_reason() != kNoReason) {
483 2674 : shared_info->DisableOptimization(literal->dont_optimize_reason());
484 : }
485 3341378 : if (literal->flags() & AstProperties::kMustUseIgnitionTurbo) {
486 : shared_info->set_must_use_ignition_turbo(true);
487 : }
488 3341378 : }
489 :
490 10680558 : bool Renumber(ParseInfo* parse_info,
491 : Compiler::EagerInnerFunctionLiterals* eager_literals) {
492 : RuntimeCallTimerScope runtimeTimer(parse_info->runtime_call_stats(),
493 2680438 : &RuntimeCallStats::CompileRenumber);
494 :
495 : // CollectTypeProfile uses its own feedback slots. If we have existing
496 : // FeedbackMetadata, we can only collect type profile, if the feedback vector
497 : // has the appropriate slots.
498 : bool collect_type_profile;
499 5319721 : if (parse_info->shared_info().is_null() ||
500 : parse_info->shared_info()->feedback_metadata()->length() == 0) {
501 : collect_type_profile =
502 2292492 : FLAG_type_profile && parse_info->script()->IsUserJavaScript();
503 : } else {
504 : collect_type_profile =
505 388049 : parse_info->shared_info()->feedback_metadata()->HasTypeProfileSlot();
506 : }
507 :
508 2680444 : if (!AstNumbering::Renumber(parse_info->stack_limit(), parse_info->zone(),
509 : parse_info->literal(), eager_literals,
510 5360882 : collect_type_profile)) {
511 : return false;
512 : }
513 2680398 : if (!parse_info->shared_info().is_null()) {
514 : SetSharedFunctionFlagsFromLiteral(parse_info->literal(),
515 2639238 : parse_info->shared_info());
516 : }
517 : return true;
518 : }
519 :
520 2933500 : bool GenerateUnoptimizedCode(CompilationInfo* info) {
521 5859771 : if (UseAsmWasm(info->scope(), info->shared_info(), info->is_debug())) {
522 354696 : EnsureFeedbackMetadata(info);
523 : MaybeHandle<FixedArray> wasm_data;
524 354696 : wasm_data = AsmJs::CompileAsmViaWasm(info);
525 354696 : if (!wasm_data.is_null()) {
526 7232 : info->shared_info()->set_asm_wasm_data(*wasm_data.ToHandleChecked());
527 3616 : info->SetCode(info->isolate()->builtins()->InstantiateAsmJs());
528 3616 : InstallUnoptimizedCode(info);
529 : return true;
530 : }
531 : }
532 :
533 2926271 : std::unique_ptr<CompilationJob> job(GetUnoptimizedCompilationJob(info));
534 2926267 : if (job->PrepareJob() != CompilationJob::SUCCEEDED) return false;
535 2926275 : if (job->ExecuteJob() != CompilationJob::SUCCEEDED) return false;
536 2926233 : if (FinalizeUnoptimizedCompilationJob(job.get()) !=
537 : CompilationJob::SUCCEEDED) {
538 : return false;
539 : }
540 2926241 : return true;
541 : }
542 :
543 2227739 : bool CompileUnoptimizedInnerFunctions(
544 : Compiler::EagerInnerFunctionLiterals* literals,
545 : Compiler::ConcurrencyMode inner_function_mode,
546 2929880 : std::shared_ptr<Zone> parse_zone, CompilationInfo* outer_info) {
547 4455478 : TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
548 : "V8.CompileUnoptimizedInnerFunctions");
549 702141 : Isolate* isolate = outer_info->isolate();
550 2227739 : Handle<Script> script = outer_info->script();
551 2227736 : bool is_debug = outer_info->is_debug();
552 : bool will_serialize = outer_info->will_serialize();
553 : RuntimeCallTimerScope runtimeTimer(isolate,
554 2227749 : &RuntimeCallStats::CompileInnerFunction);
555 :
556 5861701 : for (auto it : *literals) {
557 1404282 : FunctionLiteral* literal = it->value();
558 : Handle<SharedFunctionInfo> shared =
559 703093 : Compiler::GetSharedFunctionInfo(literal, script, outer_info);
560 703108 : if (shared->is_compiled()) continue;
561 :
562 : // The {literal} has already been numbered because AstNumbering decends into
563 : // eagerly compiled function literals.
564 702141 : SetSharedFunctionFlagsFromLiteral(literal, shared);
565 :
566 : // Try to enqueue the eager function on the compiler dispatcher.
567 : CompilerDispatcher* dispatcher = isolate->compiler_dispatcher();
568 1404274 : if (UseCompilerDispatcher(inner_function_mode, dispatcher, literal->scope(),
569 1404282 : shared, is_debug, will_serialize) &&
570 : dispatcher->EnqueueAndStep(outer_info->script(), shared, literal,
571 : parse_zone,
572 : outer_info->parse_info()->deferred_handles(),
573 702137 : outer_info->deferred_handles())) {
574 : // If we have successfully queued up the function for compilation on the
575 : // compiler dispatcher then we are done.
576 : continue;
577 : } else {
578 : // Otherwise generate unoptimized code now.
579 702138 : ParseInfo parse_info(script);
580 : CompilationInfo info(parse_info.zone(), &parse_info, isolate,
581 1404279 : Handle<JSFunction>::null());
582 :
583 : parse_info.set_literal(literal);
584 : parse_info.set_shared_info(shared);
585 : parse_info.set_function_literal_id(shared->function_literal_id());
586 : parse_info.set_language_mode(literal->scope()->language_mode());
587 : parse_info.set_ast_value_factory(
588 702141 : outer_info->parse_info()->ast_value_factory());
589 : parse_info.set_ast_value_factory_owned(false);
590 :
591 702141 : if (will_serialize) info.PrepareForSerializing();
592 702142 : if (is_debug) info.MarkAsDebug();
593 :
594 702142 : if (!GenerateUnoptimizedCode(&info)) {
595 0 : if (!isolate->has_pending_exception()) isolate->StackOverflow();
596 0 : return false;
597 702134 : }
598 : }
599 : }
600 2227764 : return true;
601 : }
602 :
603 2224738 : bool InnerFunctionIsAsmModule(
604 : ThreadedList<ThreadedListZoneEntry<FunctionLiteral*>>* literals) {
605 5852146 : for (auto it : *literals) {
606 702980 : FunctionLiteral* literal = it->value();
607 702980 : if (literal->scope()->IsAsmModule()) return true;
608 : }
609 : return false;
610 : }
611 :
612 2227788 : bool CompileUnoptimizedCode(CompilationInfo* info,
613 : Compiler::ConcurrencyMode inner_function_mode) {
614 : Isolate* isolate = info->isolate();
615 : DCHECK(AllowCompilation::IsAllowed(isolate));
616 :
617 : Compiler::EagerInnerFunctionLiterals inner_literals;
618 : {
619 : std::unique_ptr<CompilationHandleScope> compilation_handle_scope;
620 2227788 : if (inner_function_mode == Compiler::CONCURRENT) {
621 0 : compilation_handle_scope.reset(new CompilationHandleScope(info));
622 : }
623 2227797 : if (!Compiler::Analyze(info, &inner_literals)) {
624 45 : if (!isolate->has_pending_exception()) isolate->StackOverflow();
625 : return false;
626 : }
627 : }
628 :
629 : // Disable concurrent inner compilation for asm-wasm code.
630 : // TODO(rmcilroy,bradnelson): Remove this AsmWasm check once the asm-wasm
631 : // builder doesn't do parsing when visiting function declarations.
632 4452489 : if (info->scope()->IsAsmModule() ||
633 2224736 : InnerFunctionIsAsmModule(&inner_literals)) {
634 : inner_function_mode = Compiler::NOT_CONCURRENT;
635 : }
636 :
637 : std::shared_ptr<Zone> parse_zone;
638 2227750 : if (inner_function_mode == Compiler::CONCURRENT) {
639 : // Seal the parse zone so that it can be shared by parallel inner function
640 : // compilation jobs.
641 : DCHECK_NE(info->parse_info()->zone(), info->zone());
642 : parse_zone = info->parse_info()->zone_shared();
643 : parse_zone->Seal();
644 : }
645 :
646 2227740 : if (!CompileUnoptimizedInnerFunctions(&inner_literals, inner_function_mode,
647 6683237 : parse_zone, info) ||
648 2227747 : !GenerateUnoptimizedCode(info)) {
649 36 : if (!isolate->has_pending_exception()) isolate->StackOverflow();
650 : return false;
651 : }
652 :
653 : return true;
654 : }
655 :
656 2813091 : void EnsureSharedFunctionInfosArrayOnScript(ParseInfo* info, Isolate* isolate) {
657 : DCHECK(info->is_toplevel());
658 : DCHECK(!info->script().is_null());
659 1467534 : if (info->script()->shared_function_infos()->length() > 0) {
660 : DCHECK_EQ(info->script()->shared_function_infos()->length(),
661 : info->max_function_literal_id() + 1);
662 121977 : return;
663 : }
664 : Handle<FixedArray> infos(
665 1345557 : isolate->factory()->NewFixedArray(info->max_function_literal_id() + 1));
666 1345552 : info->script()->set_shared_function_infos(*infos);
667 : }
668 :
669 1341980 : void EnsureSharedFunctionInfosArrayOnScript(CompilationInfo* info) {
670 : return EnsureSharedFunctionInfosArrayOnScript(info->parse_info(),
671 1341980 : info->isolate());
672 : }
673 :
674 889274 : MUST_USE_RESULT MaybeHandle<Code> GetUnoptimizedCode(
675 3554280 : CompilationInfo* info, Compiler::ConcurrencyMode inner_function_mode) {
676 : RuntimeCallTimerScope runtimeTimer(
677 889274 : info->isolate(), &RuntimeCallStats::CompileGetUnoptimizedCode);
678 : VMState<COMPILER> state(info->isolate());
679 : PostponeInterruptsScope postpone(info->isolate());
680 :
681 : // Parse and update ParseInfo with the results.
682 : {
683 889274 : if (!parsing::ParseAny(info->parse_info(), info->isolate(),
684 1778548 : inner_function_mode != Compiler::CONCURRENT)) {
685 : return MaybeHandle<Code>();
686 : }
687 :
688 886458 : if (inner_function_mode == Compiler::CONCURRENT) {
689 : ParseHandleScope parse_handles(info->parse_info(), info->isolate());
690 0 : info->parse_info()->ReopenHandlesInNewHandleScope();
691 0 : info->parse_info()->ast_value_factory()->Internalize(info->isolate());
692 : }
693 : }
694 :
695 886458 : if (info->parse_info()->is_toplevel()) {
696 : EnsureSharedFunctionInfosArrayOnScript(info);
697 : }
698 : DCHECK_EQ(info->shared_info()->language_mode(),
699 : info->literal()->language_mode());
700 :
701 : // Compile either unoptimized code or bytecode for the interpreter.
702 886458 : if (!CompileUnoptimizedCode(info, inner_function_mode)) {
703 : return MaybeHandle<Code>();
704 : }
705 :
706 : // Record the function compilation event.
707 886391 : RecordFunctionCompilation(CodeEventListener::LAZY_COMPILE_TAG, info);
708 :
709 : return info->code();
710 : }
711 :
712 1957921 : MUST_USE_RESULT MaybeHandle<Code> GetCodeFromOptimizedCodeMap(
713 : Handle<JSFunction> function, BailoutId osr_ast_id) {
714 : RuntimeCallTimerScope runtimeTimer(
715 : function->GetIsolate(),
716 1957921 : &RuntimeCallStats::CompileGetFromOptimizedCodeMap);
717 : Handle<SharedFunctionInfo> shared(function->shared());
718 : DisallowHeapAllocation no_gc;
719 : Code* code = shared->SearchOptimizedCodeMap(
720 1957923 : function->context()->native_context(), osr_ast_id);
721 1957923 : if (code != nullptr) {
722 : // Caching of optimized code enabled and optimized code found.
723 : DCHECK(!code->marked_for_deoptimization());
724 : DCHECK(function->shared()->is_compiled());
725 : return Handle<Code>(code);
726 : }
727 : return MaybeHandle<Code>();
728 : }
729 :
730 642413 : void InsertCodeIntoOptimizedCodeMap(CompilationInfo* info) {
731 : Handle<Code> code = info->code();
732 1006615 : if (code->kind() != Code::OPTIMIZED_FUNCTION) return; // Nothing to do.
733 :
734 : // Function context specialization folds-in the function context,
735 : // so no sharing can occur.
736 642413 : if (info->is_function_context_specializing()) return;
737 : // Frame specialization implies function context specialization.
738 : DCHECK(!info->is_frame_specializing());
739 :
740 : // Cache optimized context-specific code.
741 : Handle<JSFunction> function = info->closure();
742 : Handle<SharedFunctionInfo> shared(function->shared());
743 : Handle<Context> native_context(function->context()->native_context());
744 : SharedFunctionInfo::AddToOptimizedCodeMap(shared, native_context, code,
745 278211 : info->osr_ast_id());
746 : }
747 :
748 604781 : bool GetOptimizedCodeNow(CompilationJob* job) {
749 604781 : CompilationInfo* info = job->info();
750 : Isolate* isolate = info->isolate();
751 :
752 : // Parsing is not required when optimizing from existing bytecode.
753 604781 : if (!info->is_optimizing_from_bytecode()) {
754 231950 : if (!Compiler::ParseAndAnalyze(info)) return false;
755 231904 : EnsureFeedbackMetadata(info);
756 : }
757 :
758 604735 : JSFunction::EnsureLiterals(info->closure());
759 :
760 : TimerEventScope<TimerEventRecompileSynchronous> timer(isolate);
761 : RuntimeCallTimerScope runtimeTimer(isolate,
762 604736 : &RuntimeCallStats::RecompileSynchronous);
763 1814207 : TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
764 : "V8.RecompileSynchronous");
765 :
766 1808534 : if (job->PrepareJob() != CompilationJob::SUCCEEDED ||
767 1203749 : job->ExecuteJob() != CompilationJob::SUCCEEDED ||
768 599017 : job->FinalizeJob() != CompilationJob::SUCCEEDED) {
769 5723 : if (FLAG_trace_opt) {
770 0 : PrintF("[aborted optimizing ");
771 0 : info->closure()->ShortPrint();
772 0 : PrintF(" because: %s]\n", GetBailoutReason(info->bailout_reason()));
773 : }
774 : return false;
775 : }
776 :
777 : // Success!
778 599010 : job->RecordOptimizedCompilationStats();
779 : DCHECK(!isolate->has_pending_exception());
780 599012 : InsertCodeIntoOptimizedCodeMap(info);
781 599012 : RecordFunctionCompilation(CodeEventListener::LAZY_COMPILE_TAG, info);
782 599012 : return true;
783 : }
784 :
785 148169 : bool GetOptimizedCodeLater(CompilationJob* job) {
786 251725 : CompilationInfo* info = job->info();
787 103479 : Isolate* isolate = info->isolate();
788 :
789 296338 : if (FLAG_mark_optimizing_shared_functions &&
790 : info->closure()->shared()->has_concurrent_optimization_job()) {
791 96342 : if (FLAG_trace_concurrent_recompilation) {
792 0 : PrintF(" ** Compilation job already running for ");
793 0 : info->shared_info()->ShortPrint();
794 0 : PrintF(".\n");
795 : }
796 : return false;
797 : }
798 :
799 51827 : if (!isolate->optimizing_compile_dispatcher()->IsQueueAvailable()) {
800 0 : if (FLAG_trace_concurrent_recompilation) {
801 0 : PrintF(" ** Compilation queue full, will retry optimizing ");
802 0 : info->closure()->ShortPrint();
803 0 : PrintF(" later.\n");
804 : }
805 : return false;
806 : }
807 :
808 51827 : if (isolate->heap()->HighMemoryPressure()) {
809 0 : if (FLAG_trace_concurrent_recompilation) {
810 0 : PrintF(" ** High memory pressure, will retry optimizing ");
811 0 : info->closure()->ShortPrint();
812 0 : PrintF(" later.\n");
813 : }
814 : return false;
815 : }
816 :
817 : // Parsing is not required when optimizing from existing bytecode.
818 51827 : if (!info->is_optimizing_from_bytecode()) {
819 36275 : if (!Compiler::ParseAndAnalyze(info)) return false;
820 36226 : EnsureFeedbackMetadata(info);
821 : }
822 :
823 51778 : JSFunction::EnsureLiterals(info->closure());
824 :
825 : TimerEventScope<TimerEventRecompileSynchronous> timer(info->isolate());
826 : RuntimeCallTimerScope runtimeTimer(info->isolate(),
827 51778 : &RuntimeCallStats::RecompileSynchronous);
828 155334 : TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
829 : "V8.RecompileSynchronous");
830 :
831 51778 : if (job->PrepareJob() != CompilationJob::SUCCEEDED) return false;
832 51652 : isolate->optimizing_compile_dispatcher()->QueueForOptimization(job);
833 : info->closure()->shared()->set_has_concurrent_optimization_job(true);
834 :
835 51652 : if (FLAG_trace_concurrent_recompilation) {
836 0 : PrintF(" ** Queued ");
837 0 : info->closure()->ShortPrint();
838 0 : PrintF(" for concurrent optimization.\n");
839 : }
840 : return true;
841 : }
842 :
843 800219 : MaybeHandle<Code> GetOptimizedCode(Handle<JSFunction> function,
844 : Compiler::ConcurrencyMode mode,
845 : BailoutId osr_ast_id = BailoutId::None(),
846 : JavaScriptFrame* osr_frame = nullptr) {
847 : Isolate* isolate = function->GetIsolate();
848 : Handle<SharedFunctionInfo> shared(function->shared(), isolate);
849 :
850 808697 : bool ignition_osr = osr_frame && osr_frame->is_interpreted();
851 : DCHECK_IMPLIES(ignition_osr, !osr_ast_id.IsNone());
852 : DCHECK_IMPLIES(ignition_osr, FLAG_ignition_osr);
853 :
854 : Handle<Code> cached_code;
855 800218 : if (GetCodeFromOptimizedCodeMap(function, osr_ast_id)
856 1600438 : .ToHandle(&cached_code)) {
857 2860 : if (FLAG_trace_opt) {
858 0 : PrintF("[found optimized code for ");
859 0 : function->ShortPrint();
860 0 : if (!osr_ast_id.IsNone()) {
861 0 : PrintF(" at OSR AST id %d", osr_ast_id.ToInt());
862 : }
863 0 : PrintF("]\n");
864 : }
865 : return cached_code;
866 : }
867 :
868 : // Reset profiler ticks, function is no longer considered hot.
869 : DCHECK(shared->is_compiled());
870 797358 : if (shared->HasBaselineCode()) {
871 : shared->code()->set_profiler_ticks(0);
872 416539 : } else if (shared->HasBytecodeArray()) {
873 : shared->set_profiler_ticks(0);
874 : }
875 :
876 : VMState<COMPILER> state(isolate);
877 : DCHECK(!isolate->has_pending_exception());
878 : PostponeInterruptsScope postpone(isolate);
879 797360 : bool use_turbofan = UseTurboFan(shared) || ignition_osr;
880 : bool has_script = shared->script()->IsScript();
881 : // BUG(5946): This DCHECK is necessary to make certain that we won't tolerate
882 : // the lack of a script without bytecode.
883 : DCHECK_IMPLIES(!has_script, ShouldUseIgnition(shared, false));
884 : std::unique_ptr<CompilationJob> job(
885 418336 : use_turbofan ? compiler::Pipeline::NewCompilationJob(function, has_script)
886 1215696 : : new HCompilationJob(function));
887 1189381 : CompilationInfo* info = job->info();
888 : ParseInfo* parse_info = info->parse_info();
889 :
890 : info->SetOptimizingForOsr(osr_ast_id, osr_frame);
891 :
892 : // Do not use Crankshaft/TurboFan if we need to be able to set break points.
893 1594718 : if (info->shared_info()->HasDebugInfo()) {
894 : info->AbortOptimization(kFunctionBeingDebugged);
895 : return MaybeHandle<Code>();
896 : }
897 :
898 : // Do not use Crankshaft/TurboFan when %NeverOptimizeFunction was applied.
899 840733 : if (shared->optimization_disabled() &&
900 : shared->disable_optimization_reason() == kOptimizationDisabledForTest) {
901 : info->AbortOptimization(kOptimizationDisabledForTest);
902 : return MaybeHandle<Code>();
903 : }
904 :
905 : // Limit the number of times we try to optimize functions.
906 : const int kMaxDeoptCount =
907 796412 : FLAG_deopt_every_n_times == 0 ? FLAG_max_deopt_count : 1000;
908 1592824 : if (info->shared_info()->deopt_count() > kMaxDeoptCount) {
909 : info->AbortOptimization(kDeoptimizedTooManyTimes);
910 : return MaybeHandle<Code>();
911 : }
912 :
913 : TimerEventScope<TimerEventOptimizeCode> optimize_code_timer(isolate);
914 752950 : RuntimeCallTimerScope runtimeTimer(isolate, &RuntimeCallStats::OptimizeCode);
915 2258847 : TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.OptimizeCode");
916 :
917 : // TurboFan can optimize directly from existing bytecode.
918 752949 : if (use_turbofan && ShouldUseIgnition(info)) {
919 : DCHECK(shared->HasBytecodeArray());
920 : info->MarkAsOptimizeFromBytecode();
921 : }
922 :
923 : // Verify that OSR compilations are delegated to the correct graph builder.
924 : // Depending on the underlying frame the semantics of the {BailoutId} differ
925 : // and the various graph builders hard-code a certain semantic:
926 : // - Interpreter : The BailoutId represents a bytecode offset.
927 : // - FullCodegen : The BailoutId represents the id of an AST node.
928 : DCHECK_IMPLIES(info->is_osr() && ignition_osr,
929 : info->is_optimizing_from_bytecode());
930 : DCHECK_IMPLIES(info->is_osr() && !ignition_osr,
931 : !info->is_optimizing_from_bytecode());
932 :
933 : // In case of concurrent recompilation, all handles below this point will be
934 : // allocated in a deferred handle scope that is detached and handed off to
935 : // the background thread when we return.
936 : std::unique_ptr<CompilationHandleScope> compilation;
937 752950 : if (mode == Compiler::CONCURRENT) {
938 148169 : compilation.reset(new CompilationHandleScope(info));
939 : }
940 :
941 : // In case of TurboFan, all handles below will be canonicalized.
942 : std::unique_ptr<CanonicalHandleScope> canonical;
943 1144971 : if (use_turbofan) canonical.reset(new CanonicalHandleScope(info->isolate()));
944 :
945 : // Reopen handles in the new CompilationHandleScope.
946 752950 : info->ReopenHandlesInNewHandleScope();
947 752951 : parse_info->ReopenHandlesInNewHandleScope();
948 :
949 752951 : if (mode == Compiler::CONCURRENT) {
950 148169 : if (GetOptimizedCodeLater(job.get())) {
951 : job.release(); // The background recompile job owns this now.
952 51652 : return isolate->builtins()->InOptimizationQueue();
953 : }
954 : } else {
955 604782 : if (GetOptimizedCodeNow(job.get())) return info->code();
956 : }
957 :
958 102289 : if (isolate->has_pending_exception()) isolate->clear_pending_exception();
959 : return MaybeHandle<Code>();
960 : }
961 :
962 23670 : MaybeHandle<Code> GetOptimizedCodeMaybeLater(Handle<JSFunction> function) {
963 23670 : Isolate* isolate = function->GetIsolate();
964 : return GetOptimizedCode(function, isolate->concurrent_recompilation_enabled()
965 : ? Compiler::CONCURRENT
966 23670 : : Compiler::NOT_CONCURRENT);
967 : }
968 :
969 87090 : CompilationJob::Status FinalizeOptimizedCompilationJob(CompilationJob* job) {
970 43545 : CompilationInfo* info = job->info();
971 : Isolate* isolate = info->isolate();
972 :
973 : TimerEventScope<TimerEventRecompileSynchronous> timer(info->isolate());
974 : RuntimeCallTimerScope runtimeTimer(isolate,
975 43545 : &RuntimeCallStats::RecompileSynchronous);
976 130635 : TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
977 : "V8.RecompileSynchronous");
978 :
979 43545 : Handle<SharedFunctionInfo> shared = info->shared_info();
980 :
981 : // Reset profiler ticks, function is no longer considered hot.
982 43545 : if (shared->HasBaselineCode()) {
983 : shared->code()->set_profiler_ticks(0);
984 12082 : } else if (shared->HasBytecodeArray()) {
985 : shared->set_profiler_ticks(0);
986 : }
987 :
988 : shared->set_has_concurrent_optimization_job(false);
989 :
990 : // Shared function no longer needs to be tiered up.
991 : shared->set_marked_for_tier_up(false);
992 :
993 : DCHECK(!shared->HasDebugInfo());
994 :
995 : // 1) Optimization on the concurrent thread may have failed.
996 : // 2) The function may have already been optimized by OSR. Simply continue.
997 : // Except when OSR already disabled optimization for some reason.
998 : // 3) The code may have already been invalidated due to dependency change.
999 : // 4) Code generation may have failed.
1000 43545 : if (job->state() == CompilationJob::State::kReadyToFinalize) {
1001 43545 : if (shared->optimization_disabled()) {
1002 : job->RetryOptimization(kOptimizationDisabled);
1003 43545 : } else if (info->dependencies()->HasAborted()) {
1004 : job->RetryOptimization(kBailedOutDueToDependencyChange);
1005 43455 : } else if (job->FinalizeJob() == CompilationJob::SUCCEEDED) {
1006 43423 : job->RecordOptimizedCompilationStats();
1007 43423 : RecordFunctionCompilation(CodeEventListener::LAZY_COMPILE_TAG, info);
1008 43423 : if (shared->SearchOptimizedCodeMap(info->context()->native_context(),
1009 86846 : info->osr_ast_id()) == nullptr) {
1010 43402 : InsertCodeIntoOptimizedCodeMap(info);
1011 : }
1012 43423 : if (FLAG_trace_opt) {
1013 0 : PrintF("[completed optimizing ");
1014 0 : info->closure()->ShortPrint();
1015 0 : PrintF("]\n");
1016 : }
1017 43423 : info->closure()->ReplaceCode(*info->code());
1018 43423 : return CompilationJob::SUCCEEDED;
1019 : }
1020 : }
1021 :
1022 : DCHECK(job->state() == CompilationJob::State::kFailed);
1023 122 : if (FLAG_trace_opt) {
1024 0 : PrintF("[aborted optimizing ");
1025 0 : info->closure()->ShortPrint();
1026 0 : PrintF(" because: %s]\n", GetBailoutReason(info->bailout_reason()));
1027 : }
1028 122 : info->closure()->ReplaceCode(shared->code());
1029 122 : return CompilationJob::FAILED;
1030 : }
1031 :
1032 1157703 : MaybeHandle<Code> GetLazyCode(Handle<JSFunction> function) {
1033 2041187 : Isolate* isolate = function->GetIsolate();
1034 : DCHECK(!isolate->has_pending_exception());
1035 : DCHECK(!function->is_compiled());
1036 : TimerEventScope<TimerEventCompileCode> compile_timer(isolate);
1037 : RuntimeCallTimerScope runtimeTimer(isolate,
1038 1157703 : &RuntimeCallStats::CompileFunction);
1039 3473109 : TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.CompileCode");
1040 2315406 : AggregatedHistogramTimerScope timer(isolate->counters()->compile_lazy());
1041 :
1042 : Handle<Code> cached_code;
1043 1157703 : if (GetCodeFromOptimizedCodeMap(function, BailoutId::None())
1044 2315406 : .ToHandle(&cached_code)) {
1045 5 : if (FLAG_trace_opt) {
1046 0 : PrintF("[found optimized code for ");
1047 0 : function->ShortPrint();
1048 0 : PrintF(" during unoptimized compile]\n");
1049 : }
1050 : DCHECK(function->shared()->is_compiled());
1051 : return cached_code;
1052 : }
1053 :
1054 1431912 : if (function->shared()->is_compiled() &&
1055 : function->shared()->marked_for_tier_up()) {
1056 : DCHECK(FLAG_mark_shared_functions_for_tier_up);
1057 :
1058 : function->shared()->set_marked_for_tier_up(false);
1059 :
1060 23670 : if (FLAG_trace_opt) {
1061 0 : PrintF("[optimizing method ");
1062 0 : function->ShortPrint();
1063 0 : PrintF(" eagerly (shared function marked for tier up)]\n");
1064 : }
1065 :
1066 : Handle<Code> code;
1067 47340 : if (GetOptimizedCodeMaybeLater(function).ToHandle(&code)) {
1068 : return code;
1069 : }
1070 : }
1071 :
1072 1141975 : if (function->shared()->is_compiled()) {
1073 : return Handle<Code>(function->shared()->code());
1074 : }
1075 :
1076 883484 : if (function->shared()->HasBytecodeArray()) {
1077 0 : Handle<Code> entry = isolate->builtins()->InterpreterEntryTrampoline();
1078 0 : function->shared()->ReplaceCode(*entry);
1079 : return entry;
1080 : }
1081 :
1082 1766968 : ParseInfo parse_info(handle(function->shared()));
1083 1766967 : Zone compile_zone(isolate->allocator(), ZONE_NAME);
1084 1766967 : CompilationInfo info(&compile_zone, &parse_info, isolate, function);
1085 883484 : if (FLAG_experimental_preparser_scope_analysis) {
1086 : Handle<SharedFunctionInfo> shared(function->shared());
1087 : Handle<Script> script(Script::cast(function->shared()->script()));
1088 42 : if (script->HasPreparsedScopeData()) {
1089 : parse_info.preparsed_scope_data()->Deserialize(
1090 42 : script->preparsed_scope_data());
1091 : }
1092 : }
1093 : Compiler::ConcurrencyMode inner_function_mode =
1094 : FLAG_compiler_dispatcher_eager_inner ? Compiler::CONCURRENT
1095 883484 : : Compiler::NOT_CONCURRENT;
1096 : Handle<Code> result;
1097 1766967 : ASSIGN_RETURN_ON_EXCEPTION(
1098 : isolate, result, GetUnoptimizedCode(&info, inner_function_mode), Code);
1099 :
1100 977045 : if (FLAG_always_opt && !info.shared_info()->HasAsmWasmData()) {
1101 : Handle<Code> opt_code;
1102 96378 : if (GetOptimizedCode(function, Compiler::NOT_CONCURRENT)
1103 192757 : .ToHandle(&opt_code)) {
1104 : result = opt_code;
1105 : }
1106 : }
1107 :
1108 : return result;
1109 : }
1110 :
1111 :
1112 5852183 : Handle<SharedFunctionInfo> CompileToplevel(CompilationInfo* info) {
1113 : Isolate* isolate = info->isolate();
1114 : TimerEventScope<TimerEventCompileCode> timer(isolate);
1115 4510844 : TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.CompileCode");
1116 : PostponeInterruptsScope postpone(isolate);
1117 : DCHECK(!isolate->native_context().is_null());
1118 2844956 : ParseInfo* parse_info = info->parse_info();
1119 : Compiler::ConcurrencyMode inner_function_mode =
1120 : FLAG_compiler_dispatcher_eager_inner ? Compiler::CONCURRENT
1121 1503615 : : Compiler::NOT_CONCURRENT;
1122 :
1123 : RuntimeCallTimerScope runtimeTimer(
1124 : isolate, parse_info->is_eval() ? &RuntimeCallStats::CompileEval
1125 1503615 : : &RuntimeCallStats::CompileScript);
1126 :
1127 : Handle<Script> script = parse_info->script();
1128 :
1129 : Handle<SharedFunctionInfo> result;
1130 :
1131 : { VMState<COMPILER> state(info->isolate());
1132 1503617 : if (parse_info->literal() == nullptr) {
1133 1503496 : if (!parsing::ParseProgram(parse_info, info->isolate(),
1134 1503502 : inner_function_mode != Compiler::CONCURRENT)) {
1135 : return Handle<SharedFunctionInfo>::null();
1136 : }
1137 :
1138 1341221 : if (inner_function_mode == Compiler::CONCURRENT) {
1139 : ParseHandleScope parse_handles(parse_info, info->isolate());
1140 0 : parse_info->ReopenHandlesInNewHandleScope();
1141 0 : parse_info->ast_value_factory()->Internalize(info->isolate());
1142 : }
1143 : }
1144 :
1145 : EnsureSharedFunctionInfosArrayOnScript(info);
1146 :
1147 : // Measure how long it takes to do the compilation; only take the
1148 : // rest of the function into account to avoid overlap with the
1149 : // parsing statistics.
1150 : HistogramTimer* rate = parse_info->is_eval()
1151 1135581 : ? info->isolate()->counters()->compile_eval()
1152 2682680 : : info->isolate()->counters()->compile();
1153 : HistogramTimerScope timer(rate);
1154 4024004 : TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
1155 : parse_info->is_eval() ? "V8.CompileEval" : "V8.Compile");
1156 :
1157 : // Allocate a shared function info object.
1158 : FunctionLiteral* lit = parse_info->literal();
1159 : DCHECK_EQ(kNoSourcePosition, lit->function_token_position());
1160 1341339 : result = isolate->factory()->NewSharedFunctionInfoForLiteral(lit, script);
1161 : result->set_is_toplevel(true);
1162 : parse_info->set_shared_info(result);
1163 : parse_info->set_function_literal_id(result->function_literal_id());
1164 :
1165 : // Compile the code.
1166 1341339 : if (!CompileUnoptimizedCode(info, inner_function_mode)) {
1167 15 : return Handle<SharedFunctionInfo>::null();
1168 : }
1169 :
1170 : Handle<String> script_name =
1171 : script->name()->IsString()
1172 : ? Handle<String>(String::cast(script->name()))
1173 1341321 : : isolate->factory()->empty_string();
1174 : CodeEventListener::LogEventsAndTags log_tag =
1175 : parse_info->is_eval()
1176 : ? CodeEventListener::EVAL_TAG
1177 1341326 : : Logger::ToNativeByScript(CodeEventListener::SCRIPT_TAG, *script);
1178 :
1179 1341323 : PROFILE(isolate, CodeCreateEvent(log_tag, result->abstract_code(), *result,
1180 : *script_name));
1181 :
1182 1341326 : if (!script.is_null()) {
1183 : script->set_compilation_state(Script::COMPILATION_STATE_COMPILED);
1184 1341326 : if (FLAG_experimental_preparser_scope_analysis) {
1185 : Handle<PodArray<uint32_t>> data =
1186 23 : parse_info->preparsed_scope_data()->Serialize(isolate);
1187 23 : script->set_preparsed_scope_data(*data);
1188 : }
1189 : }
1190 : }
1191 :
1192 1341322 : return result;
1193 : }
1194 :
1195 : } // namespace
1196 :
1197 : // ----------------------------------------------------------------------------
1198 : // Implementation of Compiler
1199 :
1200 2680431 : bool Compiler::Analyze(ParseInfo* info, Isolate* isolate,
1201 : EagerInnerFunctionLiterals* eager_literals) {
1202 : DCHECK_NOT_NULL(info->literal());
1203 : RuntimeCallTimerScope runtimeTimer(isolate,
1204 2680431 : &RuntimeCallStats::CompileAnalyse);
1205 2680439 : if (!Rewriter::Rewrite(info, isolate)) return false;
1206 2680439 : DeclarationScope::Analyze(info, isolate, AnalyzeMode::kRegular);
1207 2680442 : if (!Renumber(info, eager_literals)) {
1208 : return false;
1209 : }
1210 : DCHECK_NOT_NULL(info->scope());
1211 2680392 : return true;
1212 : }
1213 :
1214 2227814 : bool Compiler::Analyze(CompilationInfo* info,
1215 : EagerInnerFunctionLiterals* eager_literals) {
1216 2227814 : return Compiler::Analyze(info->parse_info(), info->isolate(), eager_literals);
1217 : }
1218 :
1219 406700 : bool Compiler::ParseAndAnalyze(ParseInfo* info, Isolate* isolate) {
1220 406700 : if (!parsing::ParseAny(info, isolate)) return false;
1221 406598 : if (info->is_toplevel()) {
1222 125552 : EnsureSharedFunctionInfosArrayOnScript(info, isolate);
1223 : }
1224 406598 : if (!Compiler::Analyze(info, isolate)) return false;
1225 : DCHECK_NOT_NULL(info->literal());
1226 : DCHECK_NOT_NULL(info->scope());
1227 406598 : return true;
1228 : }
1229 :
1230 391217 : bool Compiler::ParseAndAnalyze(CompilationInfo* info) {
1231 391217 : return Compiler::ParseAndAnalyze(info->parse_info(), info->isolate());
1232 : }
1233 :
1234 1169586 : bool Compiler::Compile(Handle<JSFunction> function, ClearExceptionFlag flag) {
1235 1169586 : if (function->is_compiled()) return true;
1236 1157706 : Isolate* isolate = function->GetIsolate();
1237 : DCHECK(AllowCompilation::IsAllowed(isolate));
1238 :
1239 : CompilerDispatcher* dispatcher = isolate->compiler_dispatcher();
1240 : Handle<SharedFunctionInfo> shared(function->shared(), isolate);
1241 : Handle<Code> code;
1242 1157706 : if (dispatcher->IsEnqueued(shared)) {
1243 3 : if (!dispatcher->FinishNow(shared)) {
1244 0 : if (flag == CLEAR_EXCEPTION) {
1245 : isolate->clear_pending_exception();
1246 : }
1247 : return false;
1248 : }
1249 : code = handle(shared->code(), isolate);
1250 : } else {
1251 : // Start a compilation.
1252 2315406 : if (!GetLazyCode(function).ToHandle(&code)) {
1253 2867 : if (flag == CLEAR_EXCEPTION) {
1254 : isolate->clear_pending_exception();
1255 : }
1256 : return false;
1257 : }
1258 : }
1259 :
1260 : // Install code on closure.
1261 1154839 : function->ReplaceCode(*code);
1262 1154839 : JSFunction::EnsureLiterals(function);
1263 :
1264 : // Check postconditions on success.
1265 : DCHECK(!isolate->has_pending_exception());
1266 : DCHECK(function->shared()->is_compiled());
1267 : DCHECK(function->is_compiled());
1268 1154839 : return true;
1269 : }
1270 :
1271 671693 : bool Compiler::CompileOptimized(Handle<JSFunction> function,
1272 : ConcurrencyMode mode) {
1273 671693 : if (function->IsOptimized()) return true;
1274 : Isolate* isolate = function->GetIsolate();
1275 : DCHECK(AllowCompilation::IsAllowed(isolate));
1276 :
1277 : // Start a compilation.
1278 : Handle<Code> code;
1279 1343386 : if (!GetOptimizedCode(function, mode).ToHandle(&code)) {
1280 : // Optimization failed, get unoptimized code. Unoptimized code must exist
1281 : // already if we are optimizing.
1282 : DCHECK(!isolate->has_pending_exception());
1283 : DCHECK(function->shared()->is_compiled());
1284 : code = handle(function->shared()->code(), isolate);
1285 : }
1286 :
1287 : // Install code on closure.
1288 671693 : function->ReplaceCode(*code);
1289 671692 : JSFunction::EnsureLiterals(function);
1290 :
1291 : // Check postconditions on success.
1292 : DCHECK(!isolate->has_pending_exception());
1293 : DCHECK(function->shared()->is_compiled());
1294 : DCHECK(function->is_compiled());
1295 671694 : return true;
1296 : }
1297 :
1298 4461 : bool Compiler::CompileDebugCode(Handle<SharedFunctionInfo> shared) {
1299 : Isolate* isolate = shared->GetIsolate();
1300 : DCHECK(AllowCompilation::IsAllowed(isolate));
1301 :
1302 : // Start a compilation.
1303 4461 : ParseInfo parse_info(shared);
1304 : CompilationInfo info(parse_info.zone(), &parse_info, isolate,
1305 8922 : Handle<JSFunction>::null());
1306 : info.MarkAsDebug();
1307 8922 : if (GetUnoptimizedCode(&info, Compiler::NOT_CONCURRENT).is_null()) {
1308 : isolate->clear_pending_exception();
1309 0 : return false;
1310 : }
1311 :
1312 : // Check postconditions on success.
1313 : DCHECK(!isolate->has_pending_exception());
1314 : DCHECK(shared->is_compiled());
1315 : DCHECK(shared->HasDebugCode());
1316 4461 : return true;
1317 : }
1318 :
1319 1644 : MaybeHandle<JSArray> Compiler::CompileForLiveEdit(Handle<Script> script) {
1320 1644 : Isolate* isolate = script->GetIsolate();
1321 : DCHECK(AllowCompilation::IsAllowed(isolate));
1322 :
1323 : // In order to ensure that live edit function info collection finds the newly
1324 : // generated shared function infos, clear the script's list temporarily
1325 : // and restore it at the end of this method.
1326 : Handle<FixedArray> old_function_infos(script->shared_function_infos(),
1327 : isolate);
1328 3288 : script->set_shared_function_infos(isolate->heap()->empty_fixed_array());
1329 :
1330 : // Start a compilation.
1331 1644 : ParseInfo parse_info(script);
1332 3288 : Zone compile_zone(isolate->allocator(), ZONE_NAME);
1333 : CompilationInfo info(&compile_zone, &parse_info, isolate,
1334 3288 : Handle<JSFunction>::null());
1335 : info.MarkAsDebug();
1336 :
1337 : // TODO(635): support extensions.
1338 3288 : const bool compilation_succeeded = !CompileToplevel(&info).is_null();
1339 : Handle<JSArray> infos;
1340 1644 : if (compilation_succeeded) {
1341 : // Check postconditions on success.
1342 : DCHECK(!isolate->has_pending_exception());
1343 : infos = LiveEditFunctionTracker::Collect(parse_info.literal(), script,
1344 1618 : parse_info.zone(), isolate);
1345 : }
1346 :
1347 : // Restore the original function info list in order to remain side-effect
1348 : // free as much as possible, since some code expects the old shared function
1349 : // infos to stick around.
1350 1644 : script->set_shared_function_infos(*old_function_infos);
1351 :
1352 1644 : return infos;
1353 : }
1354 :
1355 41184 : bool Compiler::EnsureBytecode(CompilationInfo* info) {
1356 79710 : if (!info->shared_info()->is_compiled()) {
1357 1329 : CompilerDispatcher* dispatcher = info->isolate()->compiler_dispatcher();
1358 1329 : if (dispatcher->IsEnqueued(info->shared_info())) {
1359 0 : if (!dispatcher->FinishNow(info->shared_info())) return false;
1360 2658 : } else if (GetUnoptimizedCode(info, Compiler::NOT_CONCURRENT).is_null()) {
1361 : return false;
1362 : }
1363 : }
1364 : DCHECK(info->shared_info()->is_compiled());
1365 :
1366 79680 : if (info->shared_info()->HasAsmWasmData()) return false;
1367 :
1368 : DCHECK_EQ(ShouldUseIgnition(info), info->shared_info()->HasBytecodeArray());
1369 79680 : return info->shared_info()->HasBytecodeArray();
1370 : }
1371 :
1372 : // TODO(turbofan): In the future, unoptimized code with deopt support could
1373 : // be generated lazily once deopt is triggered.
1374 1813819 : bool Compiler::EnsureDeoptimizationSupport(CompilationInfo* info) {
1375 : DCHECK_NOT_NULL(info->literal());
1376 : DCHECK_NOT_NULL(info->scope());
1377 327472 : Handle<SharedFunctionInfo> shared = info->shared_info();
1378 :
1379 327472 : CompilerDispatcher* dispatcher = info->isolate()->compiler_dispatcher();
1380 327472 : if (dispatcher->IsEnqueued(shared)) {
1381 0 : if (!dispatcher->FinishNow(shared)) return false;
1382 : }
1383 :
1384 327472 : if (!shared->has_deoptimization_support()) {
1385 : // Don't generate full-codegen code for functions which should use Ignition.
1386 232605 : if (ShouldUseIgnition(info)) return false;
1387 :
1388 : DCHECK(!shared->must_use_ignition_turbo());
1389 : DCHECK(!IsResumableFunction(shared->kind()));
1390 :
1391 231775 : Zone compile_zone(info->isolate()->allocator(), ZONE_NAME);
1392 : CompilationInfo unoptimized(&compile_zone, info->parse_info(),
1393 463550 : info->isolate(), info->closure());
1394 : unoptimized.EnableDeoptimizationSupport();
1395 :
1396 : // When we call PrepareForSerializing below, we will change the shared
1397 : // ParseInfo. Make sure to reset it.
1398 : bool old_will_serialize_value = info->parse_info()->will_serialize();
1399 :
1400 : // If the current code has reloc info for serialization, also include
1401 : // reloc info for serialization for the new code, so that deopt support
1402 : // can be added without losing IC state.
1403 460480 : if (shared->code()->kind() == Code::FUNCTION &&
1404 : shared->code()->has_reloc_info_for_serialization()) {
1405 41 : unoptimized.PrepareForSerializing();
1406 : }
1407 231775 : EnsureFeedbackMetadata(&unoptimized);
1408 :
1409 231775 : if (!FullCodeGenerator::MakeCode(&unoptimized)) return false;
1410 :
1411 : info->parse_info()->set_will_serialize(old_will_serialize_value);
1412 :
1413 : // The scope info might not have been set if a lazily compiled
1414 : // function is inlined before being called for the first time.
1415 231775 : if (shared->scope_info() == ScopeInfo::Empty(info->isolate())) {
1416 3052 : InstallSharedScopeInfo(info, shared);
1417 : }
1418 :
1419 : // Install compilation result on the shared function info
1420 231775 : shared->EnableDeoptimizationSupport(*unoptimized.code());
1421 :
1422 : // The existing unoptimized code was replaced with the new one.
1423 : RecordFunctionCompilation(CodeEventListener::LAZY_COMPILE_TAG,
1424 463550 : &unoptimized);
1425 : }
1426 : return true;
1427 : }
1428 :
1429 5596538 : MaybeHandle<JSFunction> Compiler::GetFunctionFromEval(
1430 : Handle<String> source, Handle<SharedFunctionInfo> outer_info,
1431 : Handle<Context> context, LanguageMode language_mode,
1432 : ParseRestriction restriction, int parameters_end_pos,
1433 : int eval_scope_position, int eval_position, int line_offset,
1434 : int column_offset, Handle<Object> script_name,
1435 : ScriptOriginOptions options) {
1436 23520376 : Isolate* isolate = source->GetIsolate();
1437 : int source_length = source->length();
1438 5596538 : isolate->counters()->total_eval_size()->Increment(source_length);
1439 5596538 : isolate->counters()->total_compile_size()->Increment(source_length);
1440 :
1441 : // The cache lookup key needs to be aware of the separation between the
1442 : // parameters and the body to prevent this valid invocation:
1443 : // Function("", "function anonymous(\n/**/) {\n}");
1444 : // from adding an entry that falsely approves this invalid invocation:
1445 : // Function("\n/**/) {\nfunction anonymous(", "}");
1446 : // The actual eval_scope_position for indirect eval and CreateDynamicFunction
1447 : // is unused (just 0), which means it's an available field to use to indicate
1448 : // this separation. But to make sure we're not causing other false hits, we
1449 : // negate the scope position.
1450 : int position = eval_scope_position;
1451 5596538 : if (FLAG_harmony_function_tostring &&
1452 16392 : restriction == ONLY_SINGLE_FUNCTION_LITERAL &&
1453 8196 : parameters_end_pos != kNoSourcePosition) {
1454 : // use the parameters_end_pos as the eval_scope_position in the eval cache.
1455 : DCHECK_EQ(eval_scope_position, 0);
1456 3966 : position = -parameters_end_pos;
1457 : }
1458 : CompilationCache* compilation_cache = isolate->compilation_cache();
1459 : InfoVectorPair eval_result = compilation_cache->LookupEval(
1460 5596538 : source, outer_info, context, language_mode, position);
1461 : Handle<Cell> vector;
1462 5596538 : if (eval_result.has_vector()) {
1463 3577590 : vector = Handle<Cell>(eval_result.vector(), isolate);
1464 : }
1465 :
1466 : Handle<SharedFunctionInfo> shared_info;
1467 : Handle<Script> script;
1468 5596538 : if (eval_result.has_shared()) {
1469 : shared_info = Handle<SharedFunctionInfo>(eval_result.shared(), isolate);
1470 : script = Handle<Script>(Script::cast(shared_info->script()), isolate);
1471 : } else {
1472 1294323 : script = isolate->factory()->NewScript(source);
1473 1294323 : if (isolate->NeedsSourcePositionsForProfiling()) {
1474 21013 : Script::InitLineEnds(script);
1475 : }
1476 1294323 : if (!script_name.is_null()) {
1477 21 : script->set_name(*script_name);
1478 : script->set_line_offset(line_offset);
1479 : script->set_column_offset(column_offset);
1480 : }
1481 : script->set_origin_options(options);
1482 : script->set_compilation_type(Script::COMPILATION_TYPE_EVAL);
1483 1294323 : Script::SetEvalOrigin(script, outer_info, eval_position);
1484 :
1485 1294323 : ParseInfo parse_info(script);
1486 2428547 : Zone compile_zone(isolate->allocator(), ZONE_NAME);
1487 : CompilationInfo info(&compile_zone, &parse_info, isolate,
1488 2428547 : Handle<JSFunction>::null());
1489 : parse_info.set_eval();
1490 : parse_info.set_language_mode(language_mode);
1491 : parse_info.set_parse_restriction(restriction);
1492 : parse_info.set_parameters_end_pos(parameters_end_pos);
1493 1294323 : if (!context->IsNativeContext()) {
1494 769342 : parse_info.set_outer_scope_info(handle(context->scope_info()));
1495 : }
1496 :
1497 1294323 : shared_info = CompileToplevel(&info);
1498 1294323 : if (shared_info.is_null()) {
1499 160099 : return MaybeHandle<JSFunction>();
1500 1134224 : }
1501 : }
1502 :
1503 : // If caller is strict mode, the result must be in strict mode as well.
1504 : DCHECK(is_sloppy(language_mode) || is_strict(shared_info->language_mode()));
1505 :
1506 : Handle<JSFunction> result;
1507 5436439 : if (eval_result.has_shared()) {
1508 4302215 : if (eval_result.has_vector()) {
1509 : result = isolate->factory()->NewFunctionFromSharedFunctionInfo(
1510 3577590 : shared_info, context, vector, NOT_TENURED);
1511 : } else {
1512 : result = isolate->factory()->NewFunctionFromSharedFunctionInfo(
1513 724625 : shared_info, context, NOT_TENURED);
1514 724625 : JSFunction::EnsureLiterals(result);
1515 : // Make sure to cache this result.
1516 : Handle<Cell> new_vector(result->feedback_vector_cell(), isolate);
1517 : compilation_cache->PutEval(source, outer_info, context, shared_info,
1518 724625 : new_vector, eval_scope_position);
1519 : }
1520 : } else {
1521 : result = isolate->factory()->NewFunctionFromSharedFunctionInfo(
1522 1134224 : shared_info, context, NOT_TENURED);
1523 1134224 : JSFunction::EnsureLiterals(result);
1524 : // Add the SharedFunctionInfo and the LiteralsArray to the eval cache if
1525 : // we didn't retrieve from there.
1526 : Handle<Cell> vector(result->feedback_vector_cell(), isolate);
1527 : compilation_cache->PutEval(source, outer_info, context, shared_info, vector,
1528 1134224 : eval_scope_position);
1529 : }
1530 :
1531 : // OnAfterCompile has to be called after we create the JSFunction, which we
1532 : // may require to recompile the eval for debugging, if we find a function
1533 : // that contains break points in the eval script.
1534 5436439 : isolate->debug()->OnAfterCompile(script);
1535 :
1536 : return result;
1537 : }
1538 :
1539 : namespace {
1540 :
1541 42 : bool CodeGenerationFromStringsAllowed(Isolate* isolate,
1542 : Handle<Context> context) {
1543 : DCHECK(context->allow_code_gen_from_strings()->IsFalse(isolate));
1544 : // Check with callback if set.
1545 : AllowCodeGenerationFromStringsCallback callback =
1546 : isolate->allow_code_gen_callback();
1547 42 : if (callback == NULL) {
1548 : // No callback set and code generation disallowed.
1549 : return false;
1550 : } else {
1551 : // Callback set. Let it decide if code generation is allowed.
1552 28 : VMState<EXTERNAL> state(isolate);
1553 28 : return callback(v8::Utils::ToLocal(context));
1554 : }
1555 : }
1556 :
1557 404 : bool ContainsAsmModule(Handle<Script> script) {
1558 : DisallowHeapAllocation no_gc;
1559 404 : SharedFunctionInfo::ScriptIterator iter(script);
1560 7755 : while (SharedFunctionInfo* info = iter.Next()) {
1561 7366 : if (info->HasAsmWasmData()) return true;
1562 : }
1563 : return false;
1564 : }
1565 :
1566 : } // namespace
1567 :
1568 1799796 : MaybeHandle<JSFunction> Compiler::GetFunctionFromString(
1569 : Handle<Context> context, Handle<String> source,
1570 : ParseRestriction restriction, int parameters_end_pos) {
1571 : Isolate* const isolate = context->GetIsolate();
1572 : Handle<Context> native_context(context->native_context(), isolate);
1573 :
1574 : // Check if native context allows code generation from
1575 : // strings. Throw an exception if it doesn't.
1576 1799838 : if (native_context->allow_code_gen_from_strings()->IsFalse(isolate) &&
1577 42 : !CodeGenerationFromStringsAllowed(isolate, native_context)) {
1578 : Handle<Object> error_message =
1579 28 : native_context->ErrorMessageForCodeGenerationFromStrings();
1580 56 : THROW_NEW_ERROR(isolate, NewEvalError(MessageTemplate::kCodeGenFromStrings,
1581 : error_message),
1582 : JSFunction);
1583 : }
1584 :
1585 : // Compile source string in the native context.
1586 : int eval_scope_position = 0;
1587 : int eval_position = kNoSourcePosition;
1588 : Handle<SharedFunctionInfo> outer_info(native_context->closure()->shared());
1589 : return Compiler::GetFunctionFromEval(source, outer_info, native_context,
1590 : SLOPPY, restriction, parameters_end_pos,
1591 1799768 : eval_scope_position, eval_position);
1592 : }
1593 :
1594 348960 : Handle<SharedFunctionInfo> Compiler::GetSharedFunctionInfoForScript(
1595 : Handle<String> source, Handle<Object> script_name, int line_offset,
1596 : int column_offset, ScriptOriginOptions resource_options,
1597 : Handle<Object> source_map_url, Handle<Context> context,
1598 : v8::Extension* extension, ScriptData** cached_data,
1599 : ScriptCompiler::CompileOptions compile_options, NativesFlag natives) {
1600 1460996 : Isolate* isolate = source->GetIsolate();
1601 348960 : if (compile_options == ScriptCompiler::kNoCompileOptions) {
1602 : cached_data = NULL;
1603 : } else if (compile_options == ScriptCompiler::kProduceParserCache ||
1604 : compile_options == ScriptCompiler::kProduceCodeCache) {
1605 : DCHECK(cached_data && !*cached_data);
1606 : DCHECK(extension == NULL);
1607 : DCHECK(!isolate->debug()->is_loaded());
1608 : } else {
1609 : DCHECK(compile_options == ScriptCompiler::kConsumeParserCache ||
1610 : compile_options == ScriptCompiler::kConsumeCodeCache);
1611 : DCHECK(cached_data && *cached_data);
1612 : DCHECK(extension == NULL);
1613 : }
1614 : int source_length = source->length();
1615 348960 : isolate->counters()->total_load_size()->Increment(source_length);
1616 348964 : isolate->counters()->total_compile_size()->Increment(source_length);
1617 :
1618 348965 : LanguageMode language_mode = construct_language_mode(FLAG_use_strict);
1619 : CompilationCache* compilation_cache = isolate->compilation_cache();
1620 :
1621 : // Do a lookup in the compilation cache but not for extensions.
1622 : Handle<SharedFunctionInfo> result;
1623 : Handle<Cell> vector;
1624 348965 : if (extension == NULL) {
1625 : // First check per-isolate compilation cache.
1626 : InfoVectorPair pair = compilation_cache->LookupScript(
1627 : source, script_name, line_offset, column_offset, resource_options,
1628 344223 : context, language_mode);
1629 547276 : if (!pair.has_shared() && FLAG_serialize_toplevel &&
1630 344502 : compile_options == ScriptCompiler::kConsumeCodeCache &&
1631 : !isolate->debug()->is_loaded()) {
1632 : // Then check cached code provided by embedder.
1633 279 : HistogramTimerScope timer(isolate->counters()->compile_deserialize());
1634 : RuntimeCallTimerScope runtimeTimer(isolate,
1635 279 : &RuntimeCallStats::CompileDeserialize);
1636 576 : TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
1637 : "V8.CompileDeserialize");
1638 : Handle<SharedFunctionInfo> inner_result;
1639 279 : if (CodeSerializer::Deserialize(isolate, *cached_data, source)
1640 558 : .ToHandle(&inner_result)) {
1641 : // Promote to per-isolate compilation cache.
1642 : DCHECK(inner_result->is_compiled());
1643 : Handle<FeedbackVector> feedback_vector =
1644 261 : FeedbackVector::New(isolate, inner_result);
1645 261 : vector = isolate->factory()->NewCell(feedback_vector);
1646 : compilation_cache->PutScript(source, context, language_mode,
1647 261 : inner_result, vector);
1648 : Handle<Script> script(Script::cast(inner_result->script()), isolate);
1649 261 : isolate->debug()->OnAfterCompile(script);
1650 261 : return inner_result;
1651 : }
1652 : // Deserializer failed. Fall through to compile.
1653 : } else {
1654 343944 : if (pair.has_shared()) {
1655 : result = Handle<SharedFunctionInfo>(pair.shared(), isolate);
1656 : }
1657 343944 : if (pair.has_vector()) {
1658 : vector = Handle<Cell>(pair.vector(), isolate);
1659 : }
1660 : }
1661 : }
1662 :
1663 : base::ElapsedTimer timer;
1664 348704 : if (FLAG_profile_deserialization && FLAG_serialize_toplevel &&
1665 : compile_options == ScriptCompiler::kProduceCodeCache) {
1666 : timer.Start();
1667 : }
1668 :
1669 697408 : if (result.is_null() ||
1670 141169 : (FLAG_serialize_toplevel &&
1671 : compile_options == ScriptCompiler::kProduceCodeCache)) {
1672 : // No cache entry found, or embedder wants a code cache. Compile the script.
1673 :
1674 : // Create a script object describing the script to be compiled.
1675 207535 : Handle<Script> script = isolate->factory()->NewScript(source);
1676 207532 : if (isolate->NeedsSourcePositionsForProfiling()) {
1677 16171 : Script::InitLineEnds(script);
1678 : }
1679 207536 : if (natives == NATIVES_CODE) {
1680 : script->set_type(Script::TYPE_NATIVE);
1681 189621 : } else if (natives == EXTENSION_CODE) {
1682 : script->set_type(Script::TYPE_EXTENSION);
1683 184793 : } else if (natives == INSPECTOR_CODE) {
1684 : script->set_type(Script::TYPE_INSPECTOR);
1685 : }
1686 207536 : if (!script_name.is_null()) {
1687 143268 : script->set_name(*script_name);
1688 : script->set_line_offset(line_offset);
1689 : script->set_column_offset(column_offset);
1690 : }
1691 : script->set_origin_options(resource_options);
1692 207535 : if (!source_map_url.is_null()) {
1693 4816 : script->set_source_mapping_url(*source_map_url);
1694 : }
1695 :
1696 : // Compile the function and add it to the cache.
1697 207535 : ParseInfo parse_info(script);
1698 415068 : Zone compile_zone(isolate->allocator(), ZONE_NAME);
1699 : CompilationInfo info(&compile_zone, &parse_info, isolate,
1700 415069 : Handle<JSFunction>::null());
1701 207535 : if (resource_options.IsModule()) parse_info.set_module();
1702 207535 : if (compile_options != ScriptCompiler::kNoCompileOptions) {
1703 : parse_info.set_cached_data(cached_data);
1704 : }
1705 : parse_info.set_compile_options(compile_options);
1706 : parse_info.set_extension(extension);
1707 207535 : if (!context->IsNativeContext()) {
1708 0 : parse_info.set_outer_scope_info(handle(context->scope_info()));
1709 : }
1710 207535 : if (FLAG_serialize_toplevel &&
1711 : compile_options == ScriptCompiler::kProduceCodeCache) {
1712 404 : info.PrepareForSerializing();
1713 : }
1714 :
1715 : parse_info.set_language_mode(
1716 207534 : static_cast<LanguageMode>(parse_info.language_mode() | language_mode));
1717 207534 : result = CompileToplevel(&info);
1718 207525 : if (extension == NULL && !result.is_null()) {
1719 : // We need a feedback vector.
1720 : DCHECK(result->is_compiled());
1721 : Handle<FeedbackVector> feedback_vector =
1722 200659 : FeedbackVector::New(isolate, result);
1723 200664 : vector = isolate->factory()->NewCell(feedback_vector);
1724 : compilation_cache->PutScript(source, context, language_mode, result,
1725 200663 : vector);
1726 401328 : if (FLAG_serialize_toplevel &&
1727 201068 : compile_options == ScriptCompiler::kProduceCodeCache &&
1728 404 : !ContainsAsmModule(script)) {
1729 : HistogramTimerScope histogram_timer(
1730 389 : isolate->counters()->compile_serialize());
1731 : RuntimeCallTimerScope runtimeTimer(isolate,
1732 389 : &RuntimeCallStats::CompileSerialize);
1733 1167 : TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
1734 : "V8.CompileSerialize");
1735 389 : *cached_data = CodeSerializer::Serialize(isolate, result, source);
1736 389 : if (FLAG_profile_deserialization) {
1737 : PrintF("[Compiling and serializing took %0.3f ms]\n",
1738 0 : timer.Elapsed().InMillisecondsF());
1739 : }
1740 : }
1741 : }
1742 :
1743 207530 : if (result.is_null()) {
1744 2165 : if (natives != EXTENSION_CODE && natives != NATIVES_CODE) {
1745 1509 : isolate->ReportPendingMessages();
1746 : }
1747 : } else {
1748 205365 : isolate->debug()->OnAfterCompile(script);
1749 207533 : }
1750 141169 : } else if (result->ic_age() != isolate->heap()->global_ic_age()) {
1751 573 : result->ResetForNewContext(isolate->heap()->global_ic_age());
1752 : }
1753 348703 : return result;
1754 : }
1755 :
1756 114 : Handle<SharedFunctionInfo> Compiler::GetSharedFunctionInfoForStreamedScript(
1757 : Handle<Script> script, ParseInfo* parse_info, int source_length) {
1758 456 : Isolate* isolate = script->GetIsolate();
1759 : // TODO(titzer): increment the counters in caller.
1760 114 : isolate->counters()->total_load_size()->Increment(source_length);
1761 114 : isolate->counters()->total_compile_size()->Increment(source_length);
1762 :
1763 114 : LanguageMode language_mode = construct_language_mode(FLAG_use_strict);
1764 : parse_info->set_language_mode(
1765 114 : static_cast<LanguageMode>(parse_info->language_mode() | language_mode));
1766 :
1767 114 : Zone compile_zone(isolate->allocator(), ZONE_NAME);
1768 : CompilationInfo compile_info(&compile_zone, parse_info, isolate,
1769 228 : Handle<JSFunction>::null());
1770 :
1771 : // The source was parsed lazily, so compiling for debugging is not possible.
1772 : DCHECK(!compile_info.is_debug());
1773 :
1774 114 : Handle<SharedFunctionInfo> result = CompileToplevel(&compile_info);
1775 228 : if (!result.is_null()) isolate->debug()->OnAfterCompile(script);
1776 228 : return result;
1777 : }
1778 :
1779 5862863 : Handle<SharedFunctionInfo> Compiler::GetSharedFunctionInfo(
1780 4894051 : FunctionLiteral* literal, Handle<Script> script,
1781 5862863 : CompilationInfo* outer_info) {
1782 : // Precondition: code has been parsed and scopes have been analyzed.
1783 : Isolate* isolate = outer_info->isolate();
1784 : MaybeHandle<SharedFunctionInfo> maybe_existing;
1785 :
1786 : // Find any previously allocated shared function info for the given literal.
1787 5862863 : maybe_existing = script->FindSharedFunctionInfo(isolate, literal);
1788 :
1789 : // If we found an existing shared function info, return it.
1790 : Handle<SharedFunctionInfo> existing;
1791 5862880 : if (maybe_existing.ToHandle(&existing)) {
1792 : DCHECK(!existing->is_toplevel());
1793 968830 : return existing;
1794 : }
1795 :
1796 : // Allocate a shared function info object which will be compiled lazily.
1797 : Handle<SharedFunctionInfo> result =
1798 4894050 : isolate->factory()->NewSharedFunctionInfoForLiteral(literal, script);
1799 : result->set_is_toplevel(false);
1800 4894051 : Scope* outer_scope = literal->scope()->GetOuterScopeWithContext();
1801 4894051 : if (outer_scope) {
1802 4432085 : result->set_outer_scope_info(*outer_scope->scope_info());
1803 : }
1804 4894051 : return result;
1805 : }
1806 :
1807 2988 : Handle<SharedFunctionInfo> Compiler::GetSharedFunctionInfoForNative(
1808 : v8::Extension* extension, Handle<String> name) {
1809 : Isolate* isolate = name->GetIsolate();
1810 : v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
1811 :
1812 : // Compute the function template for the native function.
1813 : v8::Local<v8::FunctionTemplate> fun_template =
1814 : extension->GetNativeFunctionTemplate(v8_isolate,
1815 2988 : v8::Utils::ToLocal(name));
1816 : DCHECK(!fun_template.IsEmpty());
1817 :
1818 : // Instantiate the function and create a shared function info from it.
1819 : Handle<JSFunction> fun = Handle<JSFunction>::cast(Utils::OpenHandle(
1820 2988 : *fun_template->GetFunction(v8_isolate->GetCurrentContext())
1821 2988 : .ToLocalChecked()));
1822 : Handle<Code> code = Handle<Code>(fun->shared()->code());
1823 : Handle<Code> construct_stub = Handle<Code>(fun->shared()->construct_stub());
1824 : Handle<SharedFunctionInfo> shared = isolate->factory()->NewSharedFunctionInfo(
1825 : name, FunctionKind::kNormalFunction, code,
1826 2988 : Handle<ScopeInfo>(fun->shared()->scope_info()));
1827 2988 : shared->set_outer_scope_info(fun->shared()->outer_scope_info());
1828 2988 : shared->SetConstructStub(*construct_stub);
1829 2988 : shared->set_feedback_metadata(fun->shared()->feedback_metadata());
1830 :
1831 : // Copy the function data to the shared function info.
1832 2988 : shared->set_function_data(fun->shared()->function_data());
1833 : int parameters = fun->shared()->internal_formal_parameter_count();
1834 : shared->set_internal_formal_parameter_count(parameters);
1835 :
1836 2988 : return shared;
1837 : }
1838 :
1839 8477 : MaybeHandle<Code> Compiler::GetOptimizedCodeForOSR(Handle<JSFunction> function,
1840 : BailoutId osr_ast_id,
1841 : JavaScriptFrame* osr_frame) {
1842 : DCHECK(!osr_ast_id.IsNone());
1843 : DCHECK_NOT_NULL(osr_frame);
1844 8477 : return GetOptimizedCode(function, NOT_CONCURRENT, osr_ast_id, osr_frame);
1845 : }
1846 :
1847 29 : CompilationJob* Compiler::PrepareUnoptimizedCompilationJob(
1848 29 : CompilationInfo* info) {
1849 : VMState<COMPILER> state(info->isolate());
1850 29 : std::unique_ptr<CompilationJob> job(GetUnoptimizedCompilationJob(info));
1851 29 : if (job->PrepareJob() != CompilationJob::SUCCEEDED) {
1852 : return nullptr;
1853 : }
1854 29 : return job.release();
1855 : }
1856 :
1857 43566 : bool Compiler::FinalizeCompilationJob(CompilationJob* raw_job) {
1858 : // Take ownership of compilation job. Deleting job also tears down the zone.
1859 : std::unique_ptr<CompilationJob> job(raw_job);
1860 :
1861 43566 : VMState<COMPILER> state(job->info()->isolate());
1862 43566 : if (job->info()->IsOptimizing()) {
1863 43545 : return FinalizeOptimizedCompilationJob(job.get()) ==
1864 43545 : CompilationJob::SUCCEEDED;
1865 : } else {
1866 21 : return FinalizeUnoptimizedCompilationJob(job.get()) ==
1867 21 : CompilationJob::SUCCEEDED;
1868 : }
1869 : }
1870 :
1871 25956039 : void Compiler::PostInstantiation(Handle<JSFunction> function,
1872 : PretenureFlag pretenure) {
1873 : Handle<SharedFunctionInfo> shared(function->shared());
1874 :
1875 31367104 : if (FLAG_always_opt && shared->allows_lazy_compilation() &&
1876 30758023 : !function->shared()->HasAsmWasmData() &&
1877 : function->shared()->is_compiled()) {
1878 1017032 : function->MarkForOptimization();
1879 : }
1880 :
1881 : Code* code = shared->SearchOptimizedCodeMap(
1882 25956051 : function->context()->native_context(), BailoutId::None());
1883 25956046 : if (code != nullptr) {
1884 : // Caching of optimized code enabled and optimized code found.
1885 : DCHECK(!code->marked_for_deoptimization());
1886 : DCHECK(function->shared()->is_compiled());
1887 835750 : function->ReplaceCode(code);
1888 : }
1889 :
1890 25956052 : if (shared->is_compiled()) {
1891 : // TODO(mvstanton): pass pretenure flag to EnsureLiterals.
1892 14244718 : JSFunction::EnsureLiterals(function);
1893 : }
1894 25956056 : }
1895 :
1896 : } // namespace internal
1897 : } // namespace v8
|