compiler.cc 71.3 KB
Newer Older
1
// Copyright 2012 the V8 project authors. All rights reserved.
2 3
// Use of this source code is governed by a BSD-style license that can be
// 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 13 14
#include "src/ast/ast-numbering.h"
#include "src/ast/prettyprinter.h"
#include "src/ast/scopes.h"
15 16 17
#include "src/bootstrapper.h"
#include "src/codegen.h"
#include "src/compilation-cache.h"
18
#include "src/compiler-dispatcher/compiler-dispatcher.h"
19
#include "src/compiler-dispatcher/optimizing-compile-dispatcher.h"
20
#include "src/compiler/pipeline.h"
21
#include "src/crankshaft/hydrogen.h"
22 23
#include "src/debug/debug.h"
#include "src/debug/liveedit.h"
24
#include "src/frames-inl.h"
25
#include "src/full-codegen/full-codegen.h"
yangguo's avatar
yangguo committed
26
#include "src/globals.h"
27
#include "src/heap/heap.h"
28
#include "src/interpreter/interpreter.h"
29
#include "src/isolate-inl.h"
30
#include "src/log-inl.h"
31
#include "src/messages.h"
32
#include "src/parsing/parsing.h"
33 34
#include "src/parsing/rewriter.h"
#include "src/parsing/scanner-character-streams.h"
35
#include "src/runtime-profiler.h"
36
#include "src/snapshot/code-serializer.h"
37
#include "src/vm-state-inl.h"
38

39 40
namespace v8 {
namespace internal {
41

42 43 44 45 46 47 48 49 50 51 52 53 54
// A wrapper around a ParseInfo that detaches the parser handles from the
// underlying DeferredHandleScope and stores them in info_ on destruction.
class ParseHandleScope final {
 public:
  explicit ParseHandleScope(ParseInfo* info)
      : deferred_(info->isolate()), info_(info) {}
  ~ParseHandleScope() { info_->set_deferred_handles(deferred_.Detach()); }

 private:
  DeferredHandleScope deferred_;
  ParseInfo* info_;
};

55 56 57
// A wrapper around a CompilationInfo that detaches the Handles from
// the underlying DeferredHandleScope and stores them in info_ on
// destruction.
58
class CompilationHandleScope final {
59 60 61 62 63 64 65 66 67
 public:
  explicit CompilationHandleScope(CompilationInfo* info)
      : deferred_(info->isolate()), info_(info) {}
  ~CompilationHandleScope() { info_->set_deferred_handles(deferred_.Detach()); }

 private:
  DeferredHandleScope deferred_;
  CompilationInfo* info_;
};
68

69 70 71 72 73 74 75 76 77 78 79 80 81
// Helper that times a scoped region and records the elapsed time.
struct ScopedTimer {
  explicit ScopedTimer(base::TimeDelta* location) : location_(location) {
    DCHECK(location_ != NULL);
    timer_.Start();
  }

  ~ScopedTimer() { *location_ += timer_.Elapsed(); }

  base::ElapsedTimer timer_;
  base::TimeDelta* location_;
};

82
// ----------------------------------------------------------------------------
83
// Implementation of CompilationJob
84

85 86 87 88 89 90 91 92 93
CompilationJob::CompilationJob(Isolate* isolate, CompilationInfo* info,
                               const char* compiler_name, State initial_state)
    : info_(info),
      isolate_thread_id_(isolate->thread_id()),
      compiler_name_(compiler_name),
      state_(initial_state),
      stack_limit_(isolate->stack_guard()->real_climit()),
      executed_on_background_thread_(false) {}

94 95
CompilationJob::Status CompilationJob::PrepareJob() {
  DCHECK(ThreadId::Current().Equals(info()->isolate()->thread_id()));
96
  DisallowJavascriptExecution no_js(isolate());
97

98
  if (FLAG_trace_opt && info()->IsOptimizing()) {
99 100 101 102 103 104 105
    OFStream os(stdout);
    os << "[compiling method " << Brief(*info()->closure()) << " using "
       << compiler_name_;
    if (info()->is_osr()) os << " OSR";
    os << "]" << std::endl;
  }

106
  // Delegate to the underlying implementation.
107 108 109
  DCHECK(state() == State::kReadyToPrepare);
  ScopedTimer t(&time_taken_to_prepare_);
  return UpdateState(PrepareJobImpl(), State::kReadyToExecute);
110 111
}

112
CompilationJob::Status CompilationJob::ExecuteJob() {
113 114 115 116 117 118 119 120 121
  std::unique_ptr<DisallowHeapAllocation> no_allocation;
  std::unique_ptr<DisallowHandleAllocation> no_handles;
  std::unique_ptr<DisallowHandleDereference> no_deref;
  std::unique_ptr<DisallowCodeDependencyChange> no_dependency_change;
  if (can_execute_on_background_thread()) {
    no_allocation.reset(new DisallowHeapAllocation());
    no_handles.reset(new DisallowHandleAllocation());
    no_deref.reset(new DisallowHandleDereference());
    no_dependency_change.reset(new DisallowCodeDependencyChange());
122 123
    executed_on_background_thread_ =
        !ThreadId::Current().Equals(isolate_thread_id_);
124
  } else {
125
    DCHECK(ThreadId::Current().Equals(isolate_thread_id_));
126
  }
127

128
  // Delegate to the underlying implementation.
129 130 131
  DCHECK(state() == State::kReadyToExecute);
  ScopedTimer t(&time_taken_to_execute_);
  return UpdateState(ExecuteJobImpl(), State::kReadyToFinalize);
132
}
133

134 135
CompilationJob::Status CompilationJob::FinalizeJob() {
  DCHECK(ThreadId::Current().Equals(info()->isolate()->thread_id()));
136 137 138
  DisallowCodeDependencyChange no_dependency_change;
  DisallowJavascriptExecution no_js(isolate());
  DCHECK(!info()->dependencies()->HasAborted());
139

140
  // Delegate to the underlying implementation.
141 142 143
  DCHECK(state() == State::kReadyToFinalize);
  ScopedTimer t(&time_taken_to_finalize_);
  return UpdateState(FinalizeJobImpl(), State::kSucceeded);
144 145
}

146 147 148 149 150 151 152 153 154 155 156 157 158 159
CompilationJob::Status CompilationJob::RetryOptimization(BailoutReason reason) {
  DCHECK(info_->IsOptimizing());
  info_->RetryOptimization(reason);
  state_ = State::kFailed;
  return FAILED;
}

CompilationJob::Status CompilationJob::AbortOptimization(BailoutReason reason) {
  DCHECK(info_->IsOptimizing());
  info_->AbortOptimization(reason);
  state_ = State::kFailed;
  return FAILED;
}

160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210
void CompilationJob::RecordUnoptimizedCompilationStats() const {
  int code_size;
  if (info()->has_bytecode_array()) {
    code_size = info()->bytecode_array()->SizeIncludingMetadata();
  } else {
    code_size = info()->code()->SizeIncludingMetadata();
  }

  Counters* counters = isolate()->counters();
  // TODO(4280): Rename counters from "baseline" to "unoptimized" eventually.
  counters->total_baseline_code_size()->Increment(code_size);
  counters->total_baseline_compile_count()->Increment(1);

  // TODO(5203): Add timers for each phase of compilation.
}

void CompilationJob::RecordOptimizedCompilationStats() const {
  DCHECK(info()->IsOptimizing());
  Handle<JSFunction> function = info()->closure();
  if (!function->IsOptimized()) {
    // Concurrent recompilation and OSR may race.  Increment only once.
    int opt_count = function->shared()->opt_count();
    function->shared()->set_opt_count(opt_count + 1);
  }
  double ms_creategraph = time_taken_to_prepare_.InMillisecondsF();
  double ms_optimize = time_taken_to_execute_.InMillisecondsF();
  double ms_codegen = time_taken_to_finalize_.InMillisecondsF();
  if (FLAG_trace_opt) {
    PrintF("[optimizing ");
    function->ShortPrint();
    PrintF(" - took %0.3f, %0.3f, %0.3f ms]\n", ms_creategraph, ms_optimize,
           ms_codegen);
  }
  if (FLAG_trace_opt_stats) {
    static double compilation_time = 0.0;
    static int compiled_functions = 0;
    static int code_size = 0;

    compilation_time += (ms_creategraph + ms_optimize + ms_codegen);
    compiled_functions++;
    code_size += function->shared()->SourceSize();
    PrintF("Compiled: %d functions with %d byte source size in %fms.\n",
           compiled_functions, code_size, compilation_time);
  }
  if (FLAG_hydrogen_stats) {
    isolate()->GetHStatistics()->IncrementSubtotals(time_taken_to_prepare_,
                                                    time_taken_to_execute_,
                                                    time_taken_to_finalize_);
  }
}

211 212
Isolate* CompilationJob::isolate() const { return info()->isolate(); }

213 214 215 216 217 218
namespace {

void AddWeakObjectToCodeDependency(Isolate* isolate, Handle<HeapObject> object,
                                   Handle<Code> code) {
  Handle<WeakCell> cell = Code::WeakCellFor(code);
  Heap* heap = isolate->heap();
219 220 221 222 223 224 225 226
  if (heap->InNewSpace(*object)) {
    heap->AddWeakNewSpaceObjectToCodeDependency(object, cell);
  } else {
    Handle<DependentCode> dep(heap->LookupWeakObjectToCodeDependency(object));
    dep =
        DependentCode::InsertWeakCode(dep, DependentCode::kWeakCodeGroup, cell);
    heap->AddWeakObjectToCodeDependency(object, dep);
  }
227 228
}

229
}  // namespace
230

231
void CompilationJob::RegisterWeakObjectsInOptimizedCode(Handle<Code> code) {
232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270
  // TODO(turbofan): Move this to pipeline.cc once Crankshaft dies.
  Isolate* const isolate = code->GetIsolate();
  DCHECK(code->is_optimized_code());
  std::vector<Handle<Map>> maps;
  std::vector<Handle<HeapObject>> objects;
  {
    DisallowHeapAllocation no_gc;
    int const mode_mask = RelocInfo::ModeMask(RelocInfo::EMBEDDED_OBJECT) |
                          RelocInfo::ModeMask(RelocInfo::CELL);
    for (RelocIterator it(*code, mode_mask); !it.done(); it.next()) {
      RelocInfo::Mode mode = it.rinfo()->rmode();
      if (mode == RelocInfo::CELL &&
          code->IsWeakObjectInOptimizedCode(it.rinfo()->target_cell())) {
        objects.push_back(handle(it.rinfo()->target_cell(), isolate));
      } else if (mode == RelocInfo::EMBEDDED_OBJECT &&
                 code->IsWeakObjectInOptimizedCode(
                     it.rinfo()->target_object())) {
        Handle<HeapObject> object(HeapObject::cast(it.rinfo()->target_object()),
                                  isolate);
        if (object->IsMap()) {
          maps.push_back(Handle<Map>::cast(object));
        } else {
          objects.push_back(object);
        }
      }
    }
  }
  for (Handle<Map> map : maps) {
    if (map->dependent_code()->IsEmpty(DependentCode::kWeakCodeGroup)) {
      isolate->heap()->AddRetainedMap(map);
    }
    Map::AddDependentCode(map, DependentCode::kWeakCodeGroup, code);
  }
  for (Handle<HeapObject> object : objects) {
    AddWeakObjectToCodeDependency(isolate, object, code);
  }
  code->set_can_have_weak_objects(true);
}

271 272 273 274
// ----------------------------------------------------------------------------
// Local helper methods that make up the compilation pipeline.

namespace {
275

276
void RecordFunctionCompilation(CodeEventListener::LogEventsAndTags tag,
277
                               CompilationInfo* info) {
278 279 280 281
  // Log the code generation. If source information is available include
  // script name and line number. Check explicitly whether logging is
  // enabled as finding the line number is not free.
  if (info->isolate()->logger()->is_logging_code_events() ||
282
      info->isolate()->is_profiling()) {
283
    Handle<SharedFunctionInfo> shared = info->shared_info();
284
    Handle<Script> script = info->parse_info()->script();
285 286 287 288
    Handle<AbstractCode> abstract_code =
        info->has_bytecode_array()
            ? Handle<AbstractCode>::cast(info->bytecode_array())
            : Handle<AbstractCode>::cast(info->code());
289 290
    if (abstract_code.is_identical_to(
            info->isolate()->builtins()->CompileLazy())) {
291 292 293 294 295 296 297 298
      return;
    }
    int line_num = Script::GetLineNumber(script, shared->start_position()) + 1;
    int column_num =
        Script::GetColumnNumber(script, shared->start_position()) + 1;
    String* script_name = script->name()->IsString()
                              ? String::cast(script->name())
                              : info->isolate()->heap()->empty_string();
299 300
    CodeEventListener::LogEventsAndTags log_tag =
        Logger::ToNativeByScript(tag, *script);
301
    PROFILE(info->isolate(),
302
            CodeCreateEvent(log_tag, *abstract_code, *shared, script_name,
303 304 305 306
                            line_num, column_num));
  }
}

307
void EnsureFeedbackMetadata(CompilationInfo* info) {
308
  DCHECK(info->has_shared_info());
309 310 311 312 313 314 315 316 317

  // If no type feedback metadata exists, create it. At this point the
  // AstNumbering pass has already run. Note the snapshot can contain outdated
  // vectors for a different configuration, hence we also recreate a new vector
  // when the function is not compiled (i.e. no code was serialized).

  // TODO(mvstanton): reintroduce is_empty() predicate to feedback_metadata().
  if (info->shared_info()->feedback_metadata()->length() == 0 ||
      !info->shared_info()->is_compiled()) {
318
    Handle<FeedbackMetadata> feedback_metadata = FeedbackMetadata::New(
319 320 321 322 323 324 325 326
        info->isolate(), info->literal()->feedback_vector_spec());
    info->shared_info()->set_feedback_metadata(*feedback_metadata);
  }

  // It's very important that recompiles do not alter the structure of the type
  // feedback vector. Verify that the structure fits the function literal.
  CHECK(!info->shared_info()->feedback_metadata()->SpecDiffersFrom(
      info->literal()->feedback_vector_spec()));
327 328
}

329
bool UseTurboFan(Handle<SharedFunctionInfo> shared) {
330 331 332 333
  if (shared->optimization_disabled()) {
    return false;
  }

334
  bool must_use_ignition_turbo = shared->must_use_ignition_turbo();
335 336 337

  // Check the enabling conditions for Turbofan.
  // 1. "use asm" code.
338
  bool is_turbofanable_asm = FLAG_turbo_asm && shared->asm_function();
339

340 341
  // 2. Fallback for features unsupported by Crankshaft.
  bool is_unsupported_by_crankshaft_but_turbofanable =
342
      must_use_ignition_turbo && strcmp(FLAG_turbo_filter, "~~") == 0;
343 344 345 346 347 348 349 350 351

  // 3. Explicitly enabled by the command-line filter.
  bool passes_turbo_filter = shared->PassesFilter(FLAG_turbo_filter);

  return is_turbofanable_asm || is_unsupported_by_crankshaft_but_turbofanable ||
         passes_turbo_filter;
}

bool ShouldUseIgnition(CompilationInfo* info) {
352
  DCHECK(info->has_shared_info());
353 354 355 356
  Handle<SharedFunctionInfo> shared = info->shared_info();

  // Code which can't be supported by the old pipeline should use Ignition.
  if (shared->must_use_ignition_turbo()) return true;
357

358 359 360
  // Resumable functions are not supported by {FullCodeGenerator}, suspended
  // activations stored as {JSGeneratorObject} on the heap always assume the
  // underlying code to be based on the bytecode array.
361
  DCHECK(!IsResumableFunction(shared->kind()));
362

363
  // Skip Ignition for asm.js functions.
364 365 366 367
  if (shared->asm_function()) return false;

  // Skip Ignition for asm wasm code.
  if (FLAG_validate_asm && shared->HasAsmWasmData()) {
368 369 370
    return false;
  }

371 372
  // When requesting debug code as a replacement for existing code, we provide
  // the same kind as the existing code (to prevent implicit tier-change).
373 374
  if (info->is_debug() && shared->is_compiled()) {
    return !shared->HasBaselineCode();
375 376
  }

377
  // Code destined for TurboFan should be compiled with Ignition first.
378
  if (UseTurboFan(shared)) return true;
379 380

  // Only use Ignition for any other function if FLAG_ignition is true.
381
  return FLAG_ignition;
382 383
}

384 385 386 387 388 389
bool UseAsmWasm(DeclarationScope* scope, Handle<SharedFunctionInfo> shared_info,
                bool is_debug) {
  return FLAG_validate_asm && scope->asm_module() &&
         !shared_info->is_asm_wasm_broken() && !is_debug;
}

390 391
bool UseCompilerDispatcher(Compiler::ConcurrencyMode inner_function_mode,
                           CompilerDispatcher* dispatcher,
392 393 394
                           DeclarationScope* scope,
                           Handle<SharedFunctionInfo> shared_info,
                           bool is_debug, bool will_serialize) {
395 396 397
  return FLAG_compiler_dispatcher_eager_inner &&
         inner_function_mode == Compiler::CONCURRENT &&
         dispatcher->IsEnabled() && !is_debug && !will_serialize &&
398 399 400
         !UseAsmWasm(scope, shared_info, is_debug);
}

401
CompilationJob* GetUnoptimizedCompilationJob(CompilationInfo* info) {
402 403 404 405 406 407
  // Function should have been parsed and analyzed before creating a compilation
  // job.
  DCHECK_NOT_NULL(info->literal());
  DCHECK_NOT_NULL(info->scope());

  if (ShouldUseIgnition(info)) {
408
    return interpreter::Interpreter::NewCompilationJob(info);
409
  } else {
410
    return FullCodeGenerator::NewCompilationJob(info);
411 412 413
  }
}

414 415
void InstallSharedScopeInfo(CompilationInfo* info,
                            Handle<SharedFunctionInfo> shared) {
416
  Handle<ScopeInfo> scope_info = info->scope()->scope_info();
417
  shared->set_scope_info(*scope_info);
418 419 420 421
  Scope* outer_scope = info->scope()->GetOuterScopeWithContext();
  if (outer_scope) {
    shared->set_outer_scope_info(*outer_scope->scope_info());
  }
422 423 424 425
}

void InstallSharedCompilationResult(CompilationInfo* info,
                                    Handle<SharedFunctionInfo> shared) {
426 427 428 429 430 431
  // TODO(mstarzinger): Compiling for debug code might be used to reveal inner
  // functions via {FindSharedFunctionInfoInScript}, in which case we end up
  // regenerating existing bytecode. Fix this!
  if (info->is_debug() && info->has_bytecode_array()) {
    shared->ClearBytecodeArray();
  }
432 433 434 435 436 437 438
  DCHECK(!info->code().is_null());
  shared->ReplaceCode(*info->code());
  if (info->has_bytecode_array()) {
    DCHECK(!shared->HasBytecodeArray());  // Only compiled once.
    shared->set_bytecode_array(*info->bytecode_array());
  }
}
439

440 441 442 443 444 445 446 447
void InstallUnoptimizedCode(CompilationInfo* info) {
  Handle<SharedFunctionInfo> shared = info->shared_info();

  // Update the shared function info with the scope info.
  InstallSharedScopeInfo(info, shared);

  // Install compilation result on the shared function info
  InstallSharedCompilationResult(info, shared);
448
}
449

450 451 452
CompilationJob::Status FinalizeUnoptimizedCompilationJob(CompilationJob* job) {
  CompilationJob::Status status = job->FinalizeJob();
  if (status == CompilationJob::SUCCEEDED) {
453 454 455 456 457 458 459 460
    CompilationInfo* info = job->info();
    EnsureFeedbackMetadata(info);
    DCHECK(!info->code().is_null());
    if (info->parse_info()->literal()->should_be_used_once_hint()) {
      info->code()->MarkToBeExecutedOnce(info->isolate());
    }
    InstallUnoptimizedCode(info);
    RecordFunctionCompilation(CodeEventListener::FUNCTION_TAG, info);
461 462 463 464 465
    job->RecordUnoptimizedCompilationStats();
  }
  return status;
}

466 467 468 469 470 471 472 473 474 475 476
void SetSharedFunctionFlagsFromLiteral(FunctionLiteral* literal,
                                       Handle<SharedFunctionInfo> shared_info) {
  shared_info->set_ast_node_count(literal->ast_node_count());
  if (literal->dont_optimize_reason() != kNoReason) {
    shared_info->DisableOptimization(literal->dont_optimize_reason());
  }
  if (literal->flags() & AstProperties::kMustUseIgnitionTurbo) {
    shared_info->set_must_use_ignition_turbo(true);
  }
}

477
bool Renumber(ParseInfo* parse_info,
478
              Compiler::EagerInnerFunctionLiterals* eager_literals) {
479
  RuntimeCallTimerScope runtimeTimer(parse_info->isolate(),
480
                                     &RuntimeCallStats::CompileRenumber);
481 482 483
  if (!AstNumbering::Renumber(
          parse_info->isolate()->stack_guard()->real_climit(),
          parse_info->zone(), parse_info->literal(), eager_literals)) {
484 485
    return false;
  }
486 487 488
  if (!parse_info->shared_info().is_null()) {
    SetSharedFunctionFlagsFromLiteral(parse_info->literal(),
                                      parse_info->shared_info());
489 490 491 492
  }
  return true;
}

493
bool GenerateUnoptimizedCode(CompilationInfo* info) {
494
  if (UseAsmWasm(info->scope(), info->shared_info(), info->is_debug())) {
495 496
    EnsureFeedbackMetadata(info);
    MaybeHandle<FixedArray> wasm_data;
497
    wasm_data = AsmJs::CompileAsmViaWasm(info);
498 499 500 501 502 503 504 505
    if (!wasm_data.is_null()) {
      info->shared_info()->set_asm_wasm_data(*wasm_data.ToHandleChecked());
      info->SetCode(info->isolate()->builtins()->InstantiateAsmJs());
      InstallUnoptimizedCode(info);
      return true;
    }
  }

506
  std::unique_ptr<CompilationJob> job(GetUnoptimizedCompilationJob(info));
507 508 509 510 511 512 513 514 515
  if (job->PrepareJob() != CompilationJob::SUCCEEDED) return false;
  if (job->ExecuteJob() != CompilationJob::SUCCEEDED) return false;
  if (FinalizeUnoptimizedCompilationJob(job.get()) !=
      CompilationJob::SUCCEEDED) {
    return false;
  }
  return true;
}

516
bool CompileUnoptimizedInnerFunctions(
517
    Compiler::EagerInnerFunctionLiterals* literals,
518
    Compiler::ConcurrencyMode inner_function_mode,
519
    std::shared_ptr<Zone> parse_zone, CompilationInfo* outer_info) {
520 521
  Isolate* isolate = outer_info->isolate();
  Handle<Script> script = outer_info->script();
522 523
  bool is_debug = outer_info->is_debug();
  bool will_serialize = outer_info->will_serialize();
524 525 526 527 528
  RuntimeCallTimerScope runtimeTimer(isolate,
                                     &RuntimeCallStats::CompileInnerFunction);

  for (auto it : *literals) {
    FunctionLiteral* literal = it->value();
529 530 531
    Handle<SharedFunctionInfo> shared =
        Compiler::GetSharedFunctionInfo(literal, script, outer_info);
    if (shared->is_compiled()) continue;
532

533 534 535
    // The {literal} has already been numbered because AstNumbering decends into
    // eagerly compiled function literals.
    SetSharedFunctionFlagsFromLiteral(literal, shared);
536

537 538
    // Try to enqueue the eager function on the compiler dispatcher.
    CompilerDispatcher* dispatcher = isolate->compiler_dispatcher();
539 540
    if (UseCompilerDispatcher(inner_function_mode, dispatcher, literal->scope(),
                              shared, is_debug, will_serialize) &&
541 542
        dispatcher->EnqueueAndStep(outer_info->script(), shared, literal,
                                   parse_zone,
543 544
                                   outer_info->parse_info()->deferred_handles(),
                                   outer_info->deferred_handles())) {
545 546 547 548 549
      // If we have successfully queued up the function for compilation on the
      // compiler dispatcher then we are done.
      continue;
    } else {
      // Otherwise generate unoptimized code now.
550
      ParseInfo parse_info(script);
551 552
      CompilationInfo info(parse_info.zone(), &parse_info,
                           Handle<JSFunction>::null());
553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568

      parse_info.set_literal(literal);
      parse_info.set_shared_info(shared);
      parse_info.set_function_literal_id(shared->function_literal_id());
      parse_info.set_language_mode(literal->scope()->language_mode());
      parse_info.set_ast_value_factory(
          outer_info->parse_info()->ast_value_factory());
      parse_info.set_ast_value_factory_owned(false);

      if (will_serialize) info.PrepareForSerializing();
      if (is_debug) info.MarkAsDebug();

      if (!GenerateUnoptimizedCode(&info)) {
        if (!isolate->has_pending_exception()) isolate->StackOverflow();
        return false;
      }
569 570 571 572 573
    }
  }
  return true;
}

574 575 576 577 578 579 580 581 582 583 584
bool InnerFunctionIsAsmModule(
    ThreadedList<ThreadedListZoneEntry<FunctionLiteral*>>* literals) {
  for (auto it : *literals) {
    FunctionLiteral* literal = it->value();
    if (literal->scope()->IsAsmModule()) return true;
  }
  return false;
}

bool CompileUnoptimizedCode(CompilationInfo* info,
                            Compiler::ConcurrencyMode inner_function_mode) {
585 586 587 588
  Isolate* isolate = info->isolate();
  DCHECK(AllowCompilation::IsAllowed(isolate));

  Compiler::EagerInnerFunctionLiterals inner_literals;
589 590 591 592 593 594 595 596 597
  {
    std::unique_ptr<CompilationHandleScope> compilation_handle_scope;
    if (inner_function_mode == Compiler::CONCURRENT) {
      compilation_handle_scope.reset(new CompilationHandleScope(info));
    }
    if (!Compiler::Analyze(info->parse_info(), &inner_literals)) {
      if (!isolate->has_pending_exception()) isolate->StackOverflow();
      return false;
    }
598 599 600 601 602 603 604 605 606 607
  }

  // Disable concurrent inner compilation for asm-wasm code.
  // TODO(rmcilroy,bradnelson): Remove this AsmWasm check once the asm-wasm
  // builder doesn't do parsing when visiting function declarations.
  if (info->scope()->IsAsmModule() ||
      InnerFunctionIsAsmModule(&inner_literals)) {
    inner_function_mode = Compiler::NOT_CONCURRENT;
  }

608
  std::shared_ptr<Zone> parse_zone;
609 610 611 612
  if (inner_function_mode == Compiler::CONCURRENT) {
    // Seal the parse zone so that it can be shared by parallel inner function
    // compilation jobs.
    DCHECK_NE(info->parse_info()->zone(), info->zone());
613 614
    parse_zone = info->parse_info()->zone_shared();
    parse_zone->Seal();
615 616 617
  }

  if (!CompileUnoptimizedInnerFunctions(&inner_literals, inner_function_mode,
618
                                        parse_zone, info) ||
619 620 621 622
      !GenerateUnoptimizedCode(info)) {
    if (!isolate->has_pending_exception()) isolate->StackOverflow();
    return false;
  }
623

624
  return true;
625 626
}

627 628 629 630 631 632 633 634 635 636 637 638 639 640
void EnsureSharedFunctionInfosArrayOnScript(ParseInfo* info) {
  DCHECK(info->is_toplevel());
  DCHECK(!info->script().is_null());
  if (info->script()->shared_function_infos()->length() > 0) {
    DCHECK_EQ(info->script()->shared_function_infos()->length(),
              info->max_function_literal_id() + 1);
    return;
  }
  Isolate* isolate = info->isolate();
  Handle<FixedArray> infos(
      isolate->factory()->NewFixedArray(info->max_function_literal_id() + 1));
  info->script()->set_shared_function_infos(*infos);
}

641 642
MUST_USE_RESULT MaybeHandle<Code> GetUnoptimizedCode(
    CompilationInfo* info, Compiler::ConcurrencyMode inner_function_mode) {
643 644
  RuntimeCallTimerScope runtimeTimer(
      info->isolate(), &RuntimeCallStats::CompileGetUnoptimizedCode);
645 646
  VMState<COMPILER> state(info->isolate());
  PostponeInterruptsScope postpone(info->isolate());
647

648 649 650 651 652 653 654 655 656 657 658 659 660 661
  // Parse and update ParseInfo with the results.
  {
    if (!parsing::ParseAny(info->parse_info(),
                           inner_function_mode != Compiler::CONCURRENT)) {
      return MaybeHandle<Code>();
    }

    if (inner_function_mode == Compiler::CONCURRENT) {
      ParseHandleScope parse_handles(info->parse_info());
      info->parse_info()->ReopenHandlesInNewHandleScope();
      info->parse_info()->ast_value_factory()->Internalize(info->isolate());
    }
  }

662 663 664
  if (info->parse_info()->is_toplevel()) {
    EnsureSharedFunctionInfosArrayOnScript(info->parse_info());
  }
665 666
  DCHECK_EQ(info->shared_info()->language_mode(),
            info->literal()->language_mode());
667

668
  // Compile either unoptimized code or bytecode for the interpreter.
669 670 671
  if (!CompileUnoptimizedCode(info, inner_function_mode)) {
    return MaybeHandle<Code>();
  }
672

673 674
  // Record the function compilation event.
  RecordFunctionCompilation(CodeEventListener::LAZY_COMPILE_TAG, info);
675

676 677
  return info->code();
}
678

679
MUST_USE_RESULT MaybeHandle<Code> GetCodeFromOptimizedCodeMap(
680
    Handle<JSFunction> function, BailoutId osr_ast_id) {
681 682 683
  RuntimeCallTimerScope runtimeTimer(
      function->GetIsolate(),
      &RuntimeCallStats::CompileGetFromOptimizedCodeMap);
684 685
  Handle<SharedFunctionInfo> shared(function->shared());
  DisallowHeapAllocation no_gc;
686
  Code* code = shared->SearchOptimizedCodeMap(
687
      function->context()->native_context(), osr_ast_id);
688
  if (code != nullptr) {
689
    // Caching of optimized code enabled and optimized code found.
690
    DCHECK(!code->marked_for_deoptimization());
691
    DCHECK(function->shared()->is_compiled());
692
    return Handle<Code>(code);
693 694 695 696
  }
  return MaybeHandle<Code>();
}

697
void InsertCodeIntoOptimizedCodeMap(CompilationInfo* info) {
698 699 700
  Handle<Code> code = info->code();
  if (code->kind() != Code::OPTIMIZED_FUNCTION) return;  // Nothing to do.

701 702
  // Function context specialization folds-in the function context,
  // so no sharing can occur.
703 704
  if (info->is_function_context_specializing()) return;
  // Frame specialization implies function context specialization.
705
  DCHECK(!info->is_frame_specializing());
706

707 708 709 710
  // TODO(4764): When compiling for OSR from bytecode, BailoutId might derive
  // from bytecode offset and overlap with actual BailoutId. No caching!
  if (info->is_osr() && info->is_optimizing_from_bytecode()) return;

711
  // Cache optimized context-specific code.
712
  Handle<JSFunction> function = info->closure();
713 714 715
  Handle<SharedFunctionInfo> shared(function->shared());
  Handle<Context> native_context(function->context()->native_context());
  SharedFunctionInfo::AddToOptimizedCodeMap(shared, native_context, code,
716
                                            info->osr_ast_id());
717 718
}

719
bool GetOptimizedCodeNow(CompilationJob* job) {
720
  CompilationInfo* info = job->info();
721
  Isolate* isolate = info->isolate();
722 723

  // Parsing is not required when optimizing from existing bytecode.
724
  if (!info->is_optimizing_from_bytecode()) {
725
    if (!Compiler::ParseAndAnalyze(info->parse_info())) return false;
726
    EnsureFeedbackMetadata(info);
727
  }
728

729 730
  JSFunction::EnsureLiterals(info->closure());

731
  TimerEventScope<TimerEventRecompileSynchronous> timer(isolate);
732 733
  RuntimeCallTimerScope runtimeTimer(isolate,
                                     &RuntimeCallStats::RecompileSynchronous);
734 735
  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
               "V8.RecompileSynchronous");
736

737 738 739
  if (job->PrepareJob() != CompilationJob::SUCCEEDED ||
      job->ExecuteJob() != CompilationJob::SUCCEEDED ||
      job->FinalizeJob() != CompilationJob::SUCCEEDED) {
740 741 742 743 744 745 746
    if (FLAG_trace_opt) {
      PrintF("[aborted optimizing ");
      info->closure()->ShortPrint();
      PrintF(" because: %s]\n", GetBailoutReason(info->bailout_reason()));
    }
    return false;
  }
747 748

  // Success!
749
  job->RecordOptimizedCompilationStats();
750
  DCHECK(!isolate->has_pending_exception());
751
  InsertCodeIntoOptimizedCodeMap(info);
752
  RecordFunctionCompilation(CodeEventListener::LAZY_COMPILE_TAG, info);
753 754 755
  return true;
}

756
bool GetOptimizedCodeLater(CompilationJob* job) {
757
  CompilationInfo* info = job->info();
758
  Isolate* isolate = info->isolate();
759

760
  if (!isolate->optimizing_compile_dispatcher()->IsQueueAvailable()) {
761 762
    if (FLAG_trace_concurrent_recompilation) {
      PrintF("  ** Compilation queue full, will retry optimizing ");
763
      info->closure()->ShortPrint();
764 765 766 767 768
      PrintF(" later.\n");
    }
    return false;
  }

769 770 771 772 773 774 775 776 777
  if (isolate->heap()->HighMemoryPressure()) {
    if (FLAG_trace_concurrent_recompilation) {
      PrintF("  ** High memory pressure, will retry optimizing ");
      info->closure()->ShortPrint();
      PrintF(" later.\n");
    }
    return false;
  }

778
  // Parsing is not required when optimizing from existing bytecode.
779
  if (!info->is_optimizing_from_bytecode()) {
780
    if (!Compiler::ParseAndAnalyze(info->parse_info())) return false;
781
    EnsureFeedbackMetadata(info);
782
  }
783

784 785
  JSFunction::EnsureLiterals(info->closure());

786
  TimerEventScope<TimerEventRecompileSynchronous> timer(info->isolate());
787 788
  RuntimeCallTimerScope runtimeTimer(info->isolate(),
                                     &RuntimeCallStats::RecompileSynchronous);
789 790
  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
               "V8.RecompileSynchronous");
791

792
  if (job->PrepareJob() != CompilationJob::SUCCEEDED) return false;
793
  isolate->optimizing_compile_dispatcher()->QueueForOptimization(job);
794 795 796

  if (FLAG_trace_concurrent_recompilation) {
    PrintF("  ** Queued ");
797
    info->closure()->ShortPrint();
798
    PrintF(" for concurrent optimization.\n");
799 800 801 802
  }
  return true;
}

803 804 805 806 807 808 809
MaybeHandle<Code> GetOptimizedCode(Handle<JSFunction> function,
                                   Compiler::ConcurrencyMode mode,
                                   BailoutId osr_ast_id = BailoutId::None(),
                                   JavaScriptFrame* osr_frame = nullptr) {
  Isolate* isolate = function->GetIsolate();
  Handle<SharedFunctionInfo> shared(function->shared(), isolate);

810 811 812 813
  bool ignition_osr = osr_frame && osr_frame->is_interpreted();
  DCHECK_IMPLIES(ignition_osr, !osr_ast_id.IsNone());
  DCHECK_IMPLIES(ignition_osr, FLAG_ignition_osr);

814 815 816
  // Shared function no longer needs to be tiered up
  shared->set_marked_for_tier_up(false);

817
  Handle<Code> cached_code;
818 819 820 821
  // TODO(4764): When compiling for OSR from bytecode, BailoutId might derive
  // from bytecode offset and overlap with actual BailoutId. No lookup!
  if (!ignition_osr &&
      GetCodeFromOptimizedCodeMap(function, osr_ast_id)
822 823 824 825 826 827 828 829 830 831 832 833
          .ToHandle(&cached_code)) {
    if (FLAG_trace_opt) {
      PrintF("[found optimized code for ");
      function->ShortPrint();
      if (!osr_ast_id.IsNone()) {
        PrintF(" at OSR AST id %d", osr_ast_id.ToInt());
      }
      PrintF("]\n");
    }
    return cached_code;
  }

834
  // Reset profiler ticks, function is no longer considered hot.
835
  DCHECK(shared->is_compiled());
836
  if (shared->HasBaselineCode()) {
837
    shared->code()->set_profiler_ticks(0);
838 839
  } else if (shared->HasBytecodeArray()) {
    shared->set_profiler_ticks(0);
840 841 842 843 844
  }

  VMState<COMPILER> state(isolate);
  DCHECK(!isolate->has_pending_exception());
  PostponeInterruptsScope postpone(isolate);
845
  bool use_turbofan = UseTurboFan(shared) || ignition_osr;
846
  std::unique_ptr<CompilationJob> job(
847 848 849
      use_turbofan ? compiler::Pipeline::NewCompilationJob(function)
                   : new HCompilationJob(function));
  CompilationInfo* info = job->info();
850
  ParseInfo* parse_info = info->parse_info();
851

852
  info->SetOptimizingForOsr(osr_ast_id, osr_frame);
853

854 855 856 857 858 859 860 861 862 863
  // Do not use Crankshaft/TurboFan if we need to be able to set break points.
  if (info->shared_info()->HasDebugInfo()) {
    info->AbortOptimization(kFunctionBeingDebugged);
    return MaybeHandle<Code>();
  }

  // Limit the number of times we try to optimize functions.
  const int kMaxOptCount =
      FLAG_deopt_every_n_times == 0 ? FLAG_max_opt_count : 1000;
  if (info->shared_info()->opt_count() > kMaxOptCount) {
864
    info->AbortOptimization(kDeoptimizedTooManyTimes);
865 866 867
    return MaybeHandle<Code>();
  }

868
  TimerEventScope<TimerEventOptimizeCode> optimize_code_timer(isolate);
869
  RuntimeCallTimerScope runtimeTimer(isolate, &RuntimeCallStats::OptimizeCode);
870
  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.OptimizeCode");
871

872
  // TurboFan can optimize directly from existing bytecode.
873
  if (use_turbofan && ShouldUseIgnition(info)) {
874
    if (info->is_osr() && !ignition_osr) return MaybeHandle<Code>();
875
    DCHECK(shared->HasBytecodeArray());
876 877 878
    info->MarkAsOptimizeFromBytecode();
  }

879 880 881 882 883 884 885 886 887 888
  // Verify that OSR compilations are delegated to the correct graph builder.
  // Depending on the underlying frame the semantics of the {BailoutId} differ
  // and the various graph builders hard-code a certain semantic:
  //  - Interpreter : The BailoutId represents a bytecode offset.
  //  - FullCodegen : The BailoutId represents the id of an AST node.
  DCHECK_IMPLIES(info->is_osr() && ignition_osr,
                 info->is_optimizing_from_bytecode());
  DCHECK_IMPLIES(info->is_osr() && !ignition_osr,
                 !info->is_optimizing_from_bytecode());

889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904
  // In case of concurrent recompilation, all handles below this point will be
  // allocated in a deferred handle scope that is detached and handed off to
  // the background thread when we return.
  std::unique_ptr<CompilationHandleScope> compilation;
  if (mode == Compiler::CONCURRENT) {
    compilation.reset(new CompilationHandleScope(info));
  }

  // In case of TurboFan, all handles below will be canonicalized.
  std::unique_ptr<CanonicalHandleScope> canonical;
  if (use_turbofan) canonical.reset(new CanonicalHandleScope(info->isolate()));

  // Reopen handles in the new CompilationHandleScope.
  info->ReopenHandlesInNewHandleScope();
  parse_info->ReopenHandlesInNewHandleScope();

905
  if (mode == Compiler::CONCURRENT) {
906
    if (GetOptimizedCodeLater(job.get())) {
907
      job.release();  // The background recompile job owns this now.
908 909 910
      return isolate->builtins()->InOptimizationQueue();
    }
  } else {
911
    if (GetOptimizedCodeNow(job.get())) return info->code();
912 913 914 915 916 917
  }

  if (isolate->has_pending_exception()) isolate->clear_pending_exception();
  return MaybeHandle<Code>();
}

918 919 920 921 922 923 924
CompilationJob::Status FinalizeOptimizedCompilationJob(CompilationJob* job) {
  CompilationInfo* info = job->info();
  Isolate* isolate = info->isolate();

  TimerEventScope<TimerEventRecompileSynchronous> timer(info->isolate());
  RuntimeCallTimerScope runtimeTimer(isolate,
                                     &RuntimeCallStats::RecompileSynchronous);
925 926
  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
               "V8.RecompileSynchronous");
927 928

  Handle<SharedFunctionInfo> shared = info->shared_info();
929 930 931 932 933 934 935

  // Reset profiler ticks, function is no longer considered hot.
  if (shared->HasBaselineCode()) {
    shared->code()->set_profiler_ticks(0);
  } else if (shared->HasBytecodeArray()) {
    shared->set_profiler_ticks(0);
  }
936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951

  DCHECK(!shared->HasDebugInfo());

  // 1) Optimization on the concurrent thread may have failed.
  // 2) The function may have already been optimized by OSR.  Simply continue.
  //    Except when OSR already disabled optimization for some reason.
  // 3) The code may have already been invalidated due to dependency change.
  // 4) Code generation may have failed.
  if (job->state() == CompilationJob::State::kReadyToFinalize) {
    if (shared->optimization_disabled()) {
      job->RetryOptimization(kOptimizationDisabled);
    } else if (info->dependencies()->HasAborted()) {
      job->RetryOptimization(kBailedOutDueToDependencyChange);
    } else if (job->FinalizeJob() == CompilationJob::SUCCEEDED) {
      job->RecordOptimizedCompilationStats();
      RecordFunctionCompilation(CodeEventListener::LAZY_COMPILE_TAG, info);
952 953
      if (shared->SearchOptimizedCodeMap(info->context()->native_context(),
                                         info->osr_ast_id()) == nullptr) {
954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975
        InsertCodeIntoOptimizedCodeMap(info);
      }
      if (FLAG_trace_opt) {
        PrintF("[completed optimizing ");
        info->closure()->ShortPrint();
        PrintF("]\n");
      }
      info->closure()->ReplaceCode(*info->code());
      return CompilationJob::SUCCEEDED;
    }
  }

  DCHECK(job->state() == CompilationJob::State::kFailed);
  if (FLAG_trace_opt) {
    PrintF("[aborted optimizing ");
    info->closure()->ShortPrint();
    PrintF(" because: %s]\n", GetBailoutReason(info->bailout_reason()));
  }
  info->closure()->ReplaceCode(shared->code());
  return CompilationJob::FAILED;
}

976 977 978 979
MaybeHandle<Code> GetBaselineCode(Handle<JSFunction> function) {
  Isolate* isolate = function->GetIsolate();
  VMState<COMPILER> state(isolate);
  PostponeInterruptsScope postpone(isolate);
980
  ParseInfo parse_info(handle(function->shared()));
981
  CompilationInfo info(parse_info.zone(), &parse_info, function);
982

983 984
  DCHECK(function->shared()->is_compiled());

985 986 987
  // Function no longer needs to be tiered up
  function->shared()->set_marked_for_tier_up(false);

988 989 990 991 992
  // Reset profiler ticks, function is no longer considered hot.
  if (function->shared()->HasBytecodeArray()) {
    function->shared()->set_profiler_ticks(0);
  }

993 994 995 996 997
  // Nothing left to do if the function already has baseline code.
  if (function->shared()->code()->kind() == Code::FUNCTION) {
    return Handle<Code>(function->shared()->code());
  }

998 999 1000 1001 1002 1003
  // We do not switch to baseline code when the debugger might have created a
  // copy of the bytecode with break slots to be able to set break points.
  if (function->shared()->HasDebugInfo()) {
    return MaybeHandle<Code>();
  }

1004 1005
  // Don't generate full-codegen code for functions it can't support.
  if (function->shared()->must_use_ignition_turbo()) {
1006 1007
    return MaybeHandle<Code>();
  }
1008
  DCHECK(!IsResumableFunction(function->shared()->kind()));
1009 1010 1011 1012 1013 1014 1015 1016

  if (FLAG_trace_opt) {
    OFStream os(stdout);
    os << "[switching method " << Brief(*function) << " to baseline code]"
       << std::endl;
  }

  // Parse and update CompilationInfo with the results.
1017
  if (!parsing::ParseFunction(info.parse_info())) return MaybeHandle<Code>();
1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034
  Handle<SharedFunctionInfo> shared = info.shared_info();
  DCHECK_EQ(shared->language_mode(), info.literal()->language_mode());

  // Compile baseline code using the full code generator.
  if (!Compiler::Analyze(info.parse_info()) ||
      !FullCodeGenerator::MakeCode(&info)) {
    if (!isolate->has_pending_exception()) isolate->StackOverflow();
    return MaybeHandle<Code>();
  }

  // Update the shared function info with the scope info.
  InstallSharedScopeInfo(&info, shared);

  // Install compilation result on the shared function info
  InstallSharedCompilationResult(&info, shared);

  // Record the function compilation event.
1035
  RecordFunctionCompilation(CodeEventListener::LAZY_COMPILE_TAG, &info);
1036 1037 1038 1039

  return info.code();
}

1040
MaybeHandle<Code> GetLazyCode(Handle<JSFunction> function) {
1041 1042
  Isolate* isolate = function->GetIsolate();
  DCHECK(!isolate->has_pending_exception());
1043
  DCHECK(!function->is_compiled());
1044
  TimerEventScope<TimerEventCompileCode> compile_timer(isolate);
1045 1046
  RuntimeCallTimerScope runtimeTimer(isolate,
                                     &RuntimeCallStats::CompileFunction);
1047
  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.CompileCode");
1048
  AggregatedHistogramTimerScope timer(isolate->counters()->compile_lazy());
1049

1050 1051 1052 1053 1054 1055 1056
  Handle<Code> cached_code;
  if (GetCodeFromOptimizedCodeMap(function, BailoutId::None())
          .ToHandle(&cached_code)) {
    if (FLAG_trace_opt) {
      PrintF("[found optimized code for ");
      function->ShortPrint();
      PrintF(" during unoptimized compile]\n");
1057
    }
1058 1059
    DCHECK(function->shared()->is_compiled());
    return cached_code;
1060 1061
  }

1062 1063
  if (function->shared()->is_compiled() &&
      function->shared()->marked_for_tier_up()) {
1064
    DCHECK(FLAG_mark_shared_functions_for_tier_up);
1065

1066
    function->shared()->set_marked_for_tier_up(false);
1067

1068 1069 1070 1071 1072 1073 1074 1075
    switch (Compiler::NextCompilationTier(*function)) {
      case Compiler::BASELINE: {
        if (FLAG_trace_opt) {
          PrintF("[recompiling function ");
          function->ShortPrint();
          PrintF(
              " to baseline eagerly (shared function marked for tier up)]\n");
        }
1076

1077
        Handle<Code> code;
1078
        if (GetBaselineCode(function).ToHandle(&code)) {
1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091
          return code;
        }
        break;
      }
      case Compiler::OPTIMIZED: {
        if (FLAG_trace_opt) {
          PrintF("[optimizing method ");
          function->ShortPrint();
          PrintF(" eagerly (shared function marked for tier up)]\n");
        }

        Handle<Code> code;
        // TODO(leszeks): Look into performing this compilation concurrently.
1092 1093
        if (GetOptimizedCode(function, Compiler::NOT_CONCURRENT)
                .ToHandle(&code)) {
1094 1095 1096 1097 1098 1099
          return code;
        }
        break;
      }
      default:
        UNREACHABLE();
1100 1101 1102
    }
  }

1103 1104 1105 1106
  if (function->shared()->is_compiled()) {
    return Handle<Code>(function->shared()->code());
  }

1107 1108 1109 1110 1111 1112
  if (function->shared()->HasBytecodeArray()) {
    Handle<Code> entry = isolate->builtins()->InterpreterEntryTrampoline();
    function->shared()->ReplaceCode(*entry);
    return entry;
  }

1113
  ParseInfo parse_info(handle(function->shared()));
1114 1115
  Zone compile_zone(isolate->allocator(), ZONE_NAME);
  CompilationInfo info(&compile_zone, &parse_info, function);
1116
  Handle<Code> result;
1117 1118
  ASSIGN_RETURN_ON_EXCEPTION(
      isolate, result, GetUnoptimizedCode(&info, Compiler::CONCURRENT), Code);
1119

1120
  if (FLAG_always_opt && !info.shared_info()->HasAsmWasmData()) {
1121
    Handle<Code> opt_code;
1122
    if (GetOptimizedCode(function, Compiler::NOT_CONCURRENT)
1123
            .ToHandle(&opt_code)) {
1124 1125
      result = opt_code;
    }
1126
  }
1127

1128 1129
  return result;
}
1130

1131

1132
Handle<SharedFunctionInfo> CompileToplevel(CompilationInfo* info) {
1133
  Isolate* isolate = info->isolate();
1134
  TimerEventScope<TimerEventCompileCode> timer(isolate);
1135
  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.CompileCode");
1136
  PostponeInterruptsScope postpone(isolate);
1137
  DCHECK(!isolate->native_context().is_null());
1138
  ParseInfo* parse_info = info->parse_info();
1139 1140 1141 1142 1143

  RuntimeCallTimerScope runtimeTimer(
      isolate, parse_info->is_eval() ? &RuntimeCallStats::CompileEval
                                     : &RuntimeCallStats::CompileScript);

1144
  Handle<Script> script = parse_info->script();
1145 1146 1147

  // TODO(svenpanne) Obscure place for this, perhaps move to OnBeforeCompile?
  FixedArray* array = isolate->native_context()->embedder_data();
1148
  script->set_context_data(array->get(v8::Context::kDebugIdIndex));
1149 1150 1151 1152

  Handle<SharedFunctionInfo> result;

  { VMState<COMPILER> state(info->isolate());
1153 1154 1155 1156 1157 1158 1159 1160 1161 1162
    if (parse_info->literal() == nullptr) {
      if (!parsing::ParseProgram(parse_info, false)) {
        return Handle<SharedFunctionInfo>::null();
      }

      {
        ParseHandleScope parse_handles(parse_info);
        parse_info->ReopenHandlesInNewHandleScope();
        parse_info->ast_value_factory()->Internalize(info->isolate());
      }
1163 1164
    }

1165 1166
    EnsureSharedFunctionInfosArrayOnScript(parse_info);

1167 1168 1169
    // Measure how long it takes to do the compilation; only take the
    // rest of the function into account to avoid overlap with the
    // parsing statistics.
1170 1171 1172
    HistogramTimer* rate = parse_info->is_eval()
                               ? info->isolate()->counters()->compile_eval()
                               : info->isolate()->counters()->compile();
1173
    HistogramTimerScope timer(rate);
1174 1175
    TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
                 parse_info->is_eval() ? "V8.CompileEval" : "V8.Compile");
1176

1177
    // Allocate a shared function info object.
1178
    FunctionLiteral* lit = parse_info->literal();
yangguo's avatar
yangguo committed
1179
    DCHECK_EQ(kNoSourcePosition, lit->function_token_position());
1180
    result = isolate->factory()->NewSharedFunctionInfoForLiteral(lit, script);
1181
    result->set_is_toplevel(true);
1182
    parse_info->set_shared_info(result);
1183
    parse_info->set_function_literal_id(result->function_literal_id());
1184

1185
    // Compile the code.
1186
    if (!CompileUnoptimizedCode(info, Compiler::CONCURRENT)) {
1187 1188 1189
      return Handle<SharedFunctionInfo>::null();
    }

1190 1191 1192 1193
    Handle<String> script_name =
        script->name()->IsString()
            ? Handle<String>(String::cast(script->name()))
            : isolate->factory()->empty_string();
1194
    CodeEventListener::LogEventsAndTags log_tag =
1195
        parse_info->is_eval()
1196 1197
            ? CodeEventListener::EVAL_TAG
            : Logger::ToNativeByScript(CodeEventListener::SCRIPT_TAG, *script);
1198

1199
    PROFILE(isolate, CodeCreateEvent(log_tag, result->abstract_code(), *result,
1200
                                     *script_name));
1201

1202 1203
    if (!script.is_null())
      script->set_compilation_state(Script::COMPILATION_STATE_COMPILED);
1204 1205 1206 1207 1208
  }

  return result;
}

1209 1210 1211 1212 1213
}  // namespace

// ----------------------------------------------------------------------------
// Implementation of Compiler

1214 1215
bool Compiler::Analyze(ParseInfo* info,
                       EagerInnerFunctionLiterals* eager_literals) {
1216
  DCHECK_NOT_NULL(info->literal());
1217 1218
  RuntimeCallTimerScope runtimeTimer(info->isolate(),
                                     &RuntimeCallStats::CompileAnalyse);
1219
  if (!Rewriter::Rewrite(info)) return false;
1220
  DeclarationScope::Analyze(info, AnalyzeMode::kRegular);
1221 1222 1223
  if (!Renumber(info, eager_literals)) {
    return false;
  }
1224 1225 1226 1227 1228
  DCHECK_NOT_NULL(info->scope());
  return true;
}

bool Compiler::ParseAndAnalyze(ParseInfo* info) {
1229
  if (!parsing::ParseAny(info)) return false;
1230
  if (info->is_toplevel()) EnsureSharedFunctionInfosArrayOnScript(info);
1231 1232 1233 1234
  if (!Compiler::Analyze(info)) return false;
  DCHECK_NOT_NULL(info->literal());
  DCHECK_NOT_NULL(info->scope());
  return true;
1235 1236 1237 1238
}

bool Compiler::Compile(Handle<JSFunction> function, ClearExceptionFlag flag) {
  if (function->is_compiled()) return true;
1239 1240
  Isolate* isolate = function->GetIsolate();
  DCHECK(AllowCompilation::IsAllowed(isolate));
1241

1242 1243
  CompilerDispatcher* dispatcher = isolate->compiler_dispatcher();
  Handle<SharedFunctionInfo> shared(function->shared(), isolate);
1244
  Handle<Code> code;
1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259
  if (dispatcher->IsEnqueued(shared)) {
    if (!dispatcher->FinishNow(shared)) {
      if (flag == CLEAR_EXCEPTION) {
        isolate->clear_pending_exception();
      }
      return false;
    }
    code = handle(shared->code(), isolate);
  } else {
    // Start a compilation.
    if (!GetLazyCode(function).ToHandle(&code)) {
      if (flag == CLEAR_EXCEPTION) {
        isolate->clear_pending_exception();
      }
      return false;
1260 1261
    }
  }
1262

1263
  // Install code on closure.
1264
  function->ReplaceCode(*code);
1265
  JSFunction::EnsureLiterals(function);
1266 1267 1268 1269

  // Check postconditions on success.
  DCHECK(!isolate->has_pending_exception());
  DCHECK(function->shared()->is_compiled());
1270 1271 1272 1273
  DCHECK(function->is_compiled());
  return true;
}

1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288
bool Compiler::CompileBaseline(Handle<JSFunction> function) {
  Isolate* isolate = function->GetIsolate();
  DCHECK(AllowCompilation::IsAllowed(isolate));

  // Start a compilation.
  Handle<Code> code;
  if (!GetBaselineCode(function).ToHandle(&code)) {
    // Baseline generation failed, get unoptimized code.
    DCHECK(function->shared()->is_compiled());
    code = handle(function->shared()->code());
    isolate->clear_pending_exception();
  }

  // Install code on closure.
  function->ReplaceCode(*code);
1289
  JSFunction::EnsureLiterals(function);
1290 1291 1292 1293 1294 1295 1296 1297

  // Check postconditions on success.
  DCHECK(!isolate->has_pending_exception());
  DCHECK(function->shared()->is_compiled());
  DCHECK(function->is_compiled());
  return true;
}

1298 1299
bool Compiler::CompileOptimized(Handle<JSFunction> function,
                                ConcurrencyMode mode) {
1300 1301 1302 1303 1304
  if (function->IsOptimized()) return true;
  Isolate* isolate = function->GetIsolate();
  DCHECK(AllowCompilation::IsAllowed(isolate));

  // Start a compilation.
1305
  Handle<Code> code;
1306
  if (!GetOptimizedCode(function, mode).ToHandle(&code)) {
1307 1308
    // Optimization failed, get unoptimized code. Unoptimized code must exist
    // already if we are optimizing.
1309
    DCHECK(!isolate->has_pending_exception());
1310 1311
    DCHECK(function->shared()->is_compiled());
    code = handle(function->shared()->code(), isolate);
1312 1313
  }

1314 1315
  // Install code on closure.
  function->ReplaceCode(*code);
1316
  JSFunction::EnsureLiterals(function);
1317 1318 1319 1320 1321

  // Check postconditions on success.
  DCHECK(!isolate->has_pending_exception());
  DCHECK(function->shared()->is_compiled());
  DCHECK(function->is_compiled());
1322 1323 1324 1325
  return true;
}

bool Compiler::CompileDebugCode(Handle<SharedFunctionInfo> shared) {
1326 1327 1328 1329
  Isolate* isolate = shared->GetIsolate();
  DCHECK(AllowCompilation::IsAllowed(isolate));

  // Start a compilation.
1330
  ParseInfo parse_info(shared);
1331 1332
  CompilationInfo info(parse_info.zone(), &parse_info,
                       Handle<JSFunction>::null());
1333
  info.MarkAsDebug();
1334
  if (GetUnoptimizedCode(&info, Compiler::NOT_CONCURRENT).is_null()) {
1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345
    isolate->clear_pending_exception();
    return false;
  }

  // Check postconditions on success.
  DCHECK(!isolate->has_pending_exception());
  DCHECK(shared->is_compiled());
  DCHECK(shared->HasDebugCode());
  return true;
}

1346
MaybeHandle<JSArray> Compiler::CompileForLiveEdit(Handle<Script> script) {
1347 1348 1349
  Isolate* isolate = script->GetIsolate();
  DCHECK(AllowCompilation::IsAllowed(isolate));

1350 1351 1352
  // In order to ensure that live edit function info collection finds the newly
  // generated shared function infos, clear the script's list temporarily
  // and restore it at the end of this method.
1353 1354 1355
  Handle<FixedArray> old_function_infos(script->shared_function_infos(),
                                        isolate);
  script->set_shared_function_infos(isolate->heap()->empty_fixed_array());
1356

1357
  // Start a compilation.
1358
  ParseInfo parse_info(script);
1359 1360
  Zone compile_zone(isolate->allocator(), ZONE_NAME);
  CompilationInfo info(&compile_zone, &parse_info, Handle<JSFunction>::null());
1361
  info.MarkAsDebug();
1362

1363
  // TODO(635): support extensions.
1364
  const bool compilation_succeeded = !CompileToplevel(&info).is_null();
1365 1366 1367 1368 1369
  Handle<JSArray> infos;
  if (compilation_succeeded) {
    // Check postconditions on success.
    DCHECK(!isolate->has_pending_exception());
    infos = LiveEditFunctionTracker::Collect(parse_info.literal(), script,
1370
                                             parse_info.zone(), isolate);
1371
  }
1372 1373 1374 1375 1376 1377

  // Restore the original function info list in order to remain side-effect
  // free as much as possible, since some code expects the old shared function
  // infos to stick around.
  script->set_shared_function_infos(*old_function_infos);

1378
  return infos;
1379 1380
}

1381
bool Compiler::EnsureBytecode(CompilationInfo* info) {
1382
  if (!info->shared_info()->is_compiled()) {
1383 1384 1385 1386
    CompilerDispatcher* dispatcher = info->isolate()->compiler_dispatcher();
    if (dispatcher->IsEnqueued(info->shared_info())) {
      if (!dispatcher->FinishNow(info->shared_info())) return false;
    } else if (GetUnoptimizedCode(info, Compiler::NOT_CONCURRENT).is_null()) {
1387 1388
      return false;
    }
1389
  }
1390
  DCHECK(info->shared_info()->is_compiled());
1391 1392 1393

  if (info->shared_info()->HasAsmWasmData()) return false;

1394 1395
  DCHECK_EQ(ShouldUseIgnition(info), info->shared_info()->HasBytecodeArray());
  return info->shared_info()->HasBytecodeArray();
1396 1397
}

1398 1399 1400 1401
// TODO(turbofan): In the future, unoptimized code with deopt support could
// be generated lazily once deopt is triggered.
bool Compiler::EnsureDeoptimizationSupport(CompilationInfo* info) {
  DCHECK_NOT_NULL(info->literal());
1402
  DCHECK_NOT_NULL(info->scope());
1403
  Handle<SharedFunctionInfo> shared = info->shared_info();
1404 1405 1406 1407 1408 1409

  CompilerDispatcher* dispatcher = info->isolate()->compiler_dispatcher();
  if (dispatcher->IsEnqueued(shared)) {
    if (!dispatcher->FinishNow(shared)) return false;
  }

1410
  if (!shared->has_deoptimization_support()) {
1411 1412 1413
    Zone compile_zone(info->isolate()->allocator(), ZONE_NAME);
    CompilationInfo unoptimized(&compile_zone, info->parse_info(),
                                info->closure());
1414
    unoptimized.EnableDeoptimizationSupport();
1415

1416 1417 1418
    // Don't generate full-codegen code for functions it can't support.
    if (shared->must_use_ignition_turbo()) return false;
    DCHECK(!IsResumableFunction(shared->kind()));
1419

1420 1421 1422 1423
    // When we call PrepareForSerializing below, we will change the shared
    // ParseInfo. Make sure to reset it.
    bool old_will_serialize_value = info->parse_info()->will_serialize();

1424 1425 1426 1427 1428 1429 1430
    // If the current code has reloc info for serialization, also include
    // reloc info for serialization for the new code, so that deopt support
    // can be added without losing IC state.
    if (shared->code()->kind() == Code::FUNCTION &&
        shared->code()->has_reloc_info_for_serialization()) {
      unoptimized.PrepareForSerializing();
    }
1431
    EnsureFeedbackMetadata(&unoptimized);
1432 1433 1434 1435 1436 1437 1438 1439

    // Ensure we generate and install bytecode first if the function should use
    // Ignition to avoid implicit tier-down.
    if (!shared->is_compiled() && ShouldUseIgnition(info) &&
        !GenerateUnoptimizedCode(info)) {
      return false;
    }

1440 1441
    if (!FullCodeGenerator::MakeCode(&unoptimized)) return false;

1442 1443
    info->parse_info()->set_will_serialize(old_will_serialize_value);

1444 1445 1446
    // The scope info might not have been set if a lazily compiled
    // function is inlined before being called for the first time.
    if (shared->scope_info() == ScopeInfo::Empty(info->isolate())) {
1447
      InstallSharedScopeInfo(info, shared);
1448 1449
    }

1450 1451 1452
    // Install compilation result on the shared function info
    shared->EnableDeoptimizationSupport(*unoptimized.code());

1453
    // The existing unoptimized code was replaced with the new one.
1454 1455
    RecordFunctionCompilation(CodeEventListener::LAZY_COMPILE_TAG,
                              &unoptimized);
1456 1457 1458 1459
  }
  return true;
}

1460 1461 1462
// static
Compiler::CompilationTier Compiler::NextCompilationTier(JSFunction* function) {
  Handle<SharedFunctionInfo> shared(function->shared(), function->GetIsolate());
1463
  if (shared->IsInterpreted()) {
1464
    if (UseTurboFan(shared)) {
1465 1466 1467 1468 1469 1470 1471 1472 1473
      return OPTIMIZED;
    } else {
      return BASELINE;
    }
  } else {
    return OPTIMIZED;
  }
}

1474
MaybeHandle<JSFunction> Compiler::GetFunctionFromEval(
1475
    Handle<String> source, Handle<SharedFunctionInfo> outer_info,
1476
    Handle<Context> context, LanguageMode language_mode,
1477 1478 1479
    ParseRestriction restriction, int eval_scope_position, int eval_position,
    int line_offset, int column_offset, Handle<Object> script_name,
    ScriptOriginOptions options) {
1480 1481 1482 1483 1484 1485
  Isolate* isolate = source->GetIsolate();
  int source_length = source->length();
  isolate->counters()->total_eval_size()->Increment(source_length);
  isolate->counters()->total_compile_size()->Increment(source_length);

  CompilationCache* compilation_cache = isolate->compilation_cache();
1486 1487
  InfoVectorPair eval_result = compilation_cache->LookupEval(
      source, outer_info, context, language_mode, eval_scope_position);
1488
  Handle<SharedFunctionInfo> shared_info;
1489 1490 1491 1492 1493 1494 1495
  if (eval_result.has_shared()) {
    shared_info = Handle<SharedFunctionInfo>(eval_result.shared(), isolate);
  }
  Handle<Cell> vector;
  if (eval_result.has_vector()) {
    vector = Handle<Cell>(eval_result.vector(), isolate);
  }
1496

1497
  Handle<Script> script;
1498
  if (!eval_result.has_shared()) {
1499
    script = isolate->factory()->NewScript(source);
1500 1501 1502
    if (isolate->NeedsSourcePositionsForProfiling()) {
      Script::InitLineEnds(script);
    }
1503 1504
    if (!script_name.is_null()) {
      script->set_name(*script_name);
1505 1506
      script->set_line_offset(line_offset);
      script->set_column_offset(column_offset);
1507 1508
    }
    script->set_origin_options(options);
1509
    script->set_compilation_type(Script::COMPILATION_TYPE_EVAL);
1510
    Script::SetEvalOrigin(script, outer_info, eval_position);
1511

1512
    ParseInfo parse_info(script);
1513 1514 1515
    Zone compile_zone(isolate->allocator(), ZONE_NAME);
    CompilationInfo info(&compile_zone, &parse_info,
                         Handle<JSFunction>::null());
1516 1517 1518
    parse_info.set_eval();
    parse_info.set_language_mode(language_mode);
    parse_info.set_parse_restriction(restriction);
1519 1520 1521
    if (!context->IsNativeContext()) {
      parse_info.set_outer_scope_info(handle(context->scope_info()));
    }
1522 1523 1524

    shared_info = CompileToplevel(&info);
    if (shared_info.is_null()) {
1525
      return MaybeHandle<JSFunction>();
1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536
    }
  }

  // If caller is strict mode, the result must be in strict mode as well.
  DCHECK(is_sloppy(language_mode) || is_strict(shared_info->language_mode()));

  Handle<JSFunction> result;
  if (eval_result.has_shared()) {
    if (eval_result.has_vector()) {
      result = isolate->factory()->NewFunctionFromSharedFunctionInfo(
          shared_info, context, vector, NOT_TENURED);
1537
    } else {
1538
      result = isolate->factory()->NewFunctionFromSharedFunctionInfo(
1539
          shared_info, context, NOT_TENURED);
1540 1541 1542
      JSFunction::EnsureLiterals(result);
      // Make sure to cache this result.
      Handle<Cell> new_vector(result->feedback_vector_cell(), isolate);
1543
      compilation_cache->PutEval(source, outer_info, context, shared_info,
1544
                                 new_vector, eval_scope_position);
1545
    }
1546 1547 1548 1549 1550 1551 1552 1553 1554
  } else {
    result = isolate->factory()->NewFunctionFromSharedFunctionInfo(
        shared_info, context, NOT_TENURED);
    JSFunction::EnsureLiterals(result);
    // Add the SharedFunctionInfo and the LiteralsArray to the eval cache if
    // we didn't retrieve from there.
    Handle<Cell> vector(result->feedback_vector_cell(), isolate);
    compilation_cache->PutEval(source, outer_info, context, shared_info, vector,
                               eval_scope_position);
1555 1556
  }

1557 1558 1559 1560 1561 1562
  // OnAfterCompile has to be called after we create the JSFunction, which we
  // may require to recompile the eval for debugging, if we find a function
  // that contains break points in the eval script.
  isolate->debug()->OnAfterCompile(script);

  return result;
1563 1564
}

1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582
namespace {

bool CodeGenerationFromStringsAllowed(Isolate* isolate,
                                      Handle<Context> context) {
  DCHECK(context->allow_code_gen_from_strings()->IsFalse(isolate));
  // Check with callback if set.
  AllowCodeGenerationFromStringsCallback callback =
      isolate->allow_code_gen_callback();
  if (callback == NULL) {
    // No callback set and code generation disallowed.
    return false;
  } else {
    // Callback set. Let it decide if code generation is allowed.
    VMState<EXTERNAL> state(isolate);
    return callback(v8::Utils::ToLocal(context));
  }
}

1583 1584 1585 1586 1587
bool ContainsAsmModule(Handle<Script> script) {
  DisallowHeapAllocation no_gc;
  SharedFunctionInfo::ScriptIterator iter(script);
  while (SharedFunctionInfo* info = iter.Next()) {
    if (info->HasAsmWasmData()) return true;
1588 1589 1590 1591
  }
  return false;
}

1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619
}  // namespace

MaybeHandle<JSFunction> Compiler::GetFunctionFromString(
    Handle<Context> context, Handle<String> source,
    ParseRestriction restriction) {
  Isolate* const isolate = context->GetIsolate();
  Handle<Context> native_context(context->native_context(), isolate);

  // Check if native context allows code generation from
  // strings. Throw an exception if it doesn't.
  if (native_context->allow_code_gen_from_strings()->IsFalse(isolate) &&
      !CodeGenerationFromStringsAllowed(isolate, native_context)) {
    Handle<Object> error_message =
        native_context->ErrorMessageForCodeGenerationFromStrings();
    THROW_NEW_ERROR(isolate, NewEvalError(MessageTemplate::kCodeGenFromStrings,
                                          error_message),
                    JSFunction);
  }

  // Compile source string in the native context.
  int eval_scope_position = 0;
  int eval_position = kNoSourcePosition;
  Handle<SharedFunctionInfo> outer_info(native_context->closure()->shared());
  return Compiler::GetFunctionFromEval(source, outer_info, native_context,
                                       SLOPPY, restriction, eval_scope_position,
                                       eval_position);
}

1620
Handle<SharedFunctionInfo> Compiler::GetSharedFunctionInfoForScript(
1621
    Handle<String> source, Handle<Object> script_name, int line_offset,
1622 1623 1624
    int column_offset, ScriptOriginOptions resource_options,
    Handle<Object> source_map_url, Handle<Context> context,
    v8::Extension* extension, ScriptData** cached_data,
1625
    ScriptCompiler::CompileOptions compile_options, NativesFlag natives) {
1626
  Isolate* isolate = source->GetIsolate();
1627
  if (compile_options == ScriptCompiler::kNoCompileOptions) {
1628
    cached_data = NULL;
1629 1630
  } else if (compile_options == ScriptCompiler::kProduceParserCache ||
             compile_options == ScriptCompiler::kProduceCodeCache) {
1631 1632
    DCHECK(cached_data && !*cached_data);
    DCHECK(extension == NULL);
1633
    DCHECK(!isolate->debug()->is_loaded());
1634
  } else {
1635
    DCHECK(compile_options == ScriptCompiler::kConsumeParserCache ||
1636
           compile_options == ScriptCompiler::kConsumeCodeCache);
1637 1638
    DCHECK(cached_data && *cached_data);
    DCHECK(extension == NULL);
1639
  }
1640 1641 1642 1643
  int source_length = source->length();
  isolate->counters()->total_load_size()->Increment(source_length);
  isolate->counters()->total_compile_size()->Increment(source_length);

1644
  LanguageMode language_mode = construct_language_mode(FLAG_use_strict);
1645 1646 1647
  CompilationCache* compilation_cache = isolate->compilation_cache();

  // Do a lookup in the compilation cache but not for extensions.
1648
  Handle<SharedFunctionInfo> result;
1649
  Handle<Cell> vector;
1650
  if (extension == NULL) {
1651
    // First check per-isolate compilation cache.
1652
    InfoVectorPair pair = compilation_cache->LookupScript(
1653 1654
        source, script_name, line_offset, column_offset, resource_options,
        context, language_mode);
1655
    if (!pair.has_shared() && FLAG_serialize_toplevel &&
1656 1657
        compile_options == ScriptCompiler::kConsumeCodeCache &&
        !isolate->debug()->is_loaded()) {
1658
      // Then check cached code provided by embedder.
1659
      HistogramTimerScope timer(isolate->counters()->compile_deserialize());
1660 1661
      RuntimeCallTimerScope runtimeTimer(isolate,
                                         &RuntimeCallStats::CompileDeserialize);
1662 1663
      TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
                   "V8.CompileDeserialize");
1664
      Handle<SharedFunctionInfo> inner_result;
1665
      if (CodeSerializer::Deserialize(isolate, *cached_data, source)
1666
              .ToHandle(&inner_result)) {
1667
        // Promote to per-isolate compilation cache.
1668 1669
        // TODO(mvstanton): create a feedback vector array here.
        DCHECK(inner_result->is_compiled());
1670 1671
        Handle<FeedbackVector> feedback_vector =
            FeedbackVector::New(isolate, inner_result);
1672 1673 1674 1675
        vector = isolate->factory()->NewCell(feedback_vector);
        compilation_cache->PutScript(source, context, language_mode,
                                     inner_result, vector);
        return inner_result;
1676 1677
      }
      // Deserializer failed. Fall through to compile.
1678 1679 1680 1681 1682 1683 1684
    } else {
      if (pair.has_shared()) {
        result = Handle<SharedFunctionInfo>(pair.shared(), isolate);
      }
      if (pair.has_vector()) {
        vector = Handle<Cell>(pair.vector(), isolate);
      }
1685
    }
1686 1687
  }

1688 1689 1690 1691 1692 1693
  base::ElapsedTimer timer;
  if (FLAG_profile_deserialization && FLAG_serialize_toplevel &&
      compile_options == ScriptCompiler::kProduceCodeCache) {
    timer.Start();
  }

1694
  if (result.is_null() ||
1695 1696 1697
      (FLAG_serialize_toplevel &&
       compile_options == ScriptCompiler::kProduceCodeCache)) {
    // No cache entry found, or embedder wants a code cache. Compile the script.
1698 1699

    // Create a script object describing the script to be compiled.
1700
    Handle<Script> script = isolate->factory()->NewScript(source);
1701 1702 1703
    if (isolate->NeedsSourcePositionsForProfiling()) {
      Script::InitLineEnds(script);
    }
1704
    if (natives == NATIVES_CODE) {
1705
      script->set_type(Script::TYPE_NATIVE);
1706 1707
    } else if (natives == EXTENSION_CODE) {
      script->set_type(Script::TYPE_EXTENSION);
1708 1709
    } else if (natives == INSPECTOR_CODE) {
      script->set_type(Script::TYPE_INSPECTOR);
1710
    }
1711 1712
    if (!script_name.is_null()) {
      script->set_name(*script_name);
1713 1714
      script->set_line_offset(line_offset);
      script->set_column_offset(column_offset);
1715
    }
1716
    script->set_origin_options(resource_options);
1717 1718 1719
    if (!source_map_url.is_null()) {
      script->set_source_mapping_url(*source_map_url);
    }
1720 1721

    // Compile the function and add it to the cache.
1722
    ParseInfo parse_info(script);
1723 1724 1725
    Zone compile_zone(isolate->allocator(), ZONE_NAME);
    CompilationInfo info(&compile_zone, &parse_info,
                         Handle<JSFunction>::null());
1726
    if (resource_options.IsModule()) parse_info.set_module();
1727
    if (compile_options != ScriptCompiler::kNoCompileOptions) {
1728
      parse_info.set_cached_data(cached_data);
1729
    }
1730 1731
    parse_info.set_compile_options(compile_options);
    parse_info.set_extension(extension);
1732 1733 1734
    if (!context->IsNativeContext()) {
      parse_info.set_outer_scope_info(handle(context->scope_info()));
    }
1735 1736
    if (FLAG_serialize_toplevel &&
        compile_options == ScriptCompiler::kProduceCodeCache) {
1737 1738
      info.PrepareForSerializing();
    }
1739

1740
    parse_info.set_language_mode(
1741
        static_cast<LanguageMode>(parse_info.language_mode() | language_mode));
1742
    result = CompileToplevel(&info);
1743
    if (extension == NULL && !result.is_null()) {
1744 1745
      // We need a feedback vector.
      DCHECK(result->is_compiled());
1746
      Handle<FeedbackVector> feedback_vector =
1747
          FeedbackVector::New(isolate, result);
1748 1749 1750
      vector = isolate->factory()->NewCell(feedback_vector);
      compilation_cache->PutScript(source, context, language_mode, result,
                                   vector);
1751
      if (FLAG_serialize_toplevel &&
1752
          compile_options == ScriptCompiler::kProduceCodeCache &&
1753
          !ContainsAsmModule(script)) {
1754 1755
        HistogramTimerScope histogram_timer(
            isolate->counters()->compile_serialize());
1756 1757
        RuntimeCallTimerScope runtimeTimer(isolate,
                                           &RuntimeCallStats::CompileSerialize);
1758 1759
        TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
                     "V8.CompileSerialize");
1760
        *cached_data = CodeSerializer::Serialize(isolate, result, source);
1761
        if (FLAG_profile_deserialization) {
1762 1763
          PrintF("[Compiling and serializing took %0.3f ms]\n",
                 timer.Elapsed().InMillisecondsF());
1764
        }
1765
      }
1766
    }
1767

1768
    if (result.is_null()) {
1769 1770 1771
      if (natives != EXTENSION_CODE && natives != NATIVES_CODE) {
        isolate->ReportPendingMessages();
      }
1772 1773 1774
    } else {
      isolate->debug()->OnAfterCompile(script);
    }
1775
  } else if (result->ic_age() != isolate->heap()->global_ic_age()) {
1776
    result->ResetForNewContext(isolate->heap()->global_ic_age());
1777 1778 1779 1780
  }
  return result;
}

1781
Handle<SharedFunctionInfo> Compiler::GetSharedFunctionInfoForStreamedScript(
1782 1783 1784
    Handle<Script> script, ParseInfo* parse_info, int source_length) {
  Isolate* isolate = script->GetIsolate();
  // TODO(titzer): increment the counters in caller.
1785 1786 1787
  isolate->counters()->total_load_size()->Increment(source_length);
  isolate->counters()->total_compile_size()->Increment(source_length);

1788
  LanguageMode language_mode = construct_language_mode(FLAG_use_strict);
1789 1790
  parse_info->set_language_mode(
      static_cast<LanguageMode>(parse_info->language_mode() | language_mode));
1791

1792 1793 1794
  Zone compile_zone(isolate->allocator(), ZONE_NAME);
  CompilationInfo compile_info(&compile_zone, parse_info,
                               Handle<JSFunction>::null());
1795

1796 1797
  // The source was parsed lazily, so compiling for debugging is not possible.
  DCHECK(!compile_info.is_debug());
1798

1799 1800 1801
  Handle<SharedFunctionInfo> result = CompileToplevel(&compile_info);
  if (!result.is_null()) isolate->debug()->OnAfterCompile(script);
  return result;
1802 1803
}

1804
Handle<SharedFunctionInfo> Compiler::GetSharedFunctionInfo(
1805
    FunctionLiteral* literal, Handle<Script> script,
1806
    CompilationInfo* outer_info) {
1807
  // Precondition: code has been parsed and scopes have been analyzed.
1808
  Isolate* isolate = outer_info->isolate();
1809
  MaybeHandle<SharedFunctionInfo> maybe_existing;
1810 1811

  // Find any previously allocated shared function info for the given literal.
1812
  maybe_existing = script->FindSharedFunctionInfo(isolate, literal);
1813

1814
  // If we found an existing shared function info, return it.
1815
  Handle<SharedFunctionInfo> existing;
1816
  if (maybe_existing.ToHandle(&existing)) {
1817
    DCHECK(!existing->is_toplevel());
1818
    return existing;
1819 1820
  }

1821 1822 1823 1824 1825 1826 1827
  // Allocate a shared function info object which will be compiled lazily.
  Handle<SharedFunctionInfo> result =
      isolate->factory()->NewSharedFunctionInfoForLiteral(literal, script);
  result->set_is_toplevel(false);
  Scope* outer_scope = literal->scope()->GetOuterScopeWithContext();
  if (outer_scope) {
    result->set_outer_scope_info(*outer_scope->scope_info());
1828 1829
  }
  return result;
1830 1831
}

1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849
Handle<SharedFunctionInfo> Compiler::GetSharedFunctionInfoForNative(
    v8::Extension* extension, Handle<String> name) {
  Isolate* isolate = name->GetIsolate();
  v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);

  // Compute the function template for the native function.
  v8::Local<v8::FunctionTemplate> fun_template =
      extension->GetNativeFunctionTemplate(v8_isolate,
                                           v8::Utils::ToLocal(name));
  DCHECK(!fun_template.IsEmpty());

  // Instantiate the function and create a shared function info from it.
  Handle<JSFunction> fun = Handle<JSFunction>::cast(Utils::OpenHandle(
      *fun_template->GetFunction(v8_isolate->GetCurrentContext())
           .ToLocalChecked()));
  Handle<Code> code = Handle<Code>(fun->shared()->code());
  Handle<Code> construct_stub = Handle<Code>(fun->shared()->construct_stub());
  Handle<SharedFunctionInfo> shared = isolate->factory()->NewSharedFunctionInfo(
1850
      name, fun->shared()->num_literals(), FunctionKind::kNormalFunction, code,
1851
      Handle<ScopeInfo>(fun->shared()->scope_info()));
1852
  shared->set_outer_scope_info(fun->shared()->outer_scope_info());
1853
  shared->SetConstructStub(*construct_stub);
1854
  shared->set_feedback_metadata(fun->shared()->feedback_metadata());
1855 1856 1857 1858 1859 1860 1861 1862

  // Copy the function data to the shared function info.
  shared->set_function_data(fun->shared()->function_data());
  int parameters = fun->shared()->internal_formal_parameter_count();
  shared->set_internal_formal_parameter_count(parameters);

  return shared;
}
1863

1864 1865 1866
MaybeHandle<Code> Compiler::GetOptimizedCodeForOSR(Handle<JSFunction> function,
                                                   BailoutId osr_ast_id,
                                                   JavaScriptFrame* osr_frame) {
1867
  DCHECK(!osr_ast_id.IsNone());
1868 1869
  DCHECK_NOT_NULL(osr_frame);
  return GetOptimizedCode(function, NOT_CONCURRENT, osr_ast_id, osr_frame);
1870 1871
}

1872
CompilationJob* Compiler::PrepareUnoptimizedCompilationJob(
1873
    CompilationInfo* info) {
1874
  VMState<COMPILER> state(info->isolate());
1875
  std::unique_ptr<CompilationJob> job(GetUnoptimizedCompilationJob(info));
1876 1877 1878 1879 1880 1881 1882
  if (job->PrepareJob() != CompilationJob::SUCCEEDED) {
    return nullptr;
  }
  return job.release();
}

bool Compiler::FinalizeCompilationJob(CompilationJob* raw_job) {
1883
  // Take ownership of compilation job.  Deleting job also tears down the zone.
1884
  std::unique_ptr<CompilationJob> job(raw_job);
1885

1886 1887 1888 1889 1890
  VMState<COMPILER> state(job->info()->isolate());
  if (job->info()->IsOptimizing()) {
    return FinalizeOptimizedCompilationJob(job.get()) ==
           CompilationJob::SUCCEEDED;
  } else {
1891 1892
    return FinalizeUnoptimizedCompilationJob(job.get()) ==
           CompilationJob::SUCCEEDED;
1893
  }
1894 1895
}

1896 1897 1898 1899
void Compiler::PostInstantiation(Handle<JSFunction> function,
                                 PretenureFlag pretenure) {
  Handle<SharedFunctionInfo> shared(function->shared());

1900
  if (FLAG_always_opt && shared->allows_lazy_compilation() &&
1901
      !function->shared()->HasAsmWasmData() &&
1902
      function->shared()->is_compiled()) {
1903 1904 1905
    function->MarkForOptimization();
  }

1906
  Code* code = shared->SearchOptimizedCodeMap(
1907
      function->context()->native_context(), BailoutId::None());
1908
  if (code != nullptr) {
1909
    // Caching of optimized code enabled and optimized code found.
1910
    DCHECK(!code->marked_for_deoptimization());
1911
    DCHECK(function->shared()->is_compiled());
1912
    function->ReplaceCode(code);
1913 1914
  }

1915
  if (shared->is_compiled()) {
1916 1917
    // TODO(mvstanton): pass pretenure flag to EnsureLiterals.
    JSFunction::EnsureLiterals(function);
1918 1919
  }
}
1920

1921 1922
}  // namespace internal
}  // namespace v8