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