compiler.cc 82.8 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/api-inl.h"
11
#include "src/asmjs/asm-js.h"
12
#include "src/assembler-inl.h"
13 14
#include "src/ast/prettyprinter.h"
#include "src/ast/scopes.h"
15
#include "src/base/optional.h"
16 17
#include "src/bootstrapper.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 22
#include "src/debug/debug.h"
#include "src/debug/liveedit.h"
23
#include "src/frames-inl.h"
yangguo's avatar
yangguo committed
24
#include "src/globals.h"
25
#include "src/heap/heap.h"
26
#include "src/interpreter/interpreter.h"
27
#include "src/isolate-inl.h"
28
#include "src/log-inl.h"
29
#include "src/message-template.h"
30
#include "src/objects/feedback-cell-inl.h"
31
#include "src/objects/map.h"
32
#include "src/optimized-compilation-info.h"
33
#include "src/ostreams.h"
34
#include "src/parsing/parse-info.h"
35
#include "src/parsing/parser.h"
36
#include "src/parsing/parsing.h"
37 38
#include "src/parsing/rewriter.h"
#include "src/parsing/scanner-character-streams.h"
39
#include "src/runtime-profiler.h"
40
#include "src/snapshot/code-serializer.h"
41
#include "src/unoptimized-compilation-info.h"
42
#include "src/vm-state-inl.h"
43

44 45
namespace v8 {
namespace internal {
46

47
// A wrapper around a OptimizedCompilationInfo that detaches the Handles from
48 49
// the underlying DeferredHandleScope and stores them in info_ on
// destruction.
50
class CompilationHandleScope final {
51
 public:
52 53
  explicit CompilationHandleScope(Isolate* isolate,
                                  OptimizedCompilationInfo* info)
54
      : deferred_(isolate), info_(info) {}
55 56 57 58
  ~CompilationHandleScope() { info_->set_deferred_handles(deferred_.Detach()); }

 private:
  DeferredHandleScope deferred_;
59
  OptimizedCompilationInfo* info_;
60
};
61

62 63 64
// Helper that times a scoped region and records the elapsed time.
struct ScopedTimer {
  explicit ScopedTimer(base::TimeDelta* location) : location_(location) {
65
    DCHECK_NOT_NULL(location_);
66 67 68 69 70 71 72 73 74
    timer_.Start();
  }

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

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

75 76 77 78 79 80 81 82 83 84 85 86 87
namespace {

void LogFunctionCompilation(CodeEventListener::LogEventsAndTags tag,
                            Handle<SharedFunctionInfo> shared,
                            Handle<Script> script,
                            Handle<AbstractCode> abstract_code, bool optimizing,
                            double time_taken_ms, Isolate* isolate) {
  DCHECK(!abstract_code.is_null());
  DCHECK(!abstract_code.is_identical_to(BUILTIN_CODE(isolate, CompileLazy)));

  // 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.
88 89 90
  if (!isolate->logger()->is_listening_to_code_events() &&
      !isolate->is_profiling() && !FLAG_log_function_events &&
      !isolate->code_event_dispatcher()->IsListeningToCodeEvents()) {
91 92 93 94 95
    return;
  }

  int line_num = Script::GetLineNumber(script, shared->StartPosition()) + 1;
  int column_num = Script::GetColumnNumber(script, shared->StartPosition()) + 1;
96 97 98
  String script_name = script->name()->IsString()
                           ? String::cast(script->name())
                           : ReadOnlyRoots(isolate).empty_string();
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
  CodeEventListener::LogEventsAndTags log_tag =
      Logger::ToNativeByScript(tag, *script);
  PROFILE(isolate, CodeCreateEvent(log_tag, *abstract_code, *shared,
                                   script_name, line_num, column_num));
  if (!FLAG_log_function_events) return;

  DisallowHeapAllocation no_gc;

  std::string name = optimizing ? "optimize" : "compile";
  switch (tag) {
    case CodeEventListener::EVAL_TAG:
      name += "-eval";
      break;
    case CodeEventListener::SCRIPT_TAG:
      break;
    case CodeEventListener::LAZY_COMPILE_TAG:
      name += "-lazy";
      break;
    case CodeEventListener::FUNCTION_TAG:
      break;
    default:
      UNREACHABLE();
  }

123
  LOG(isolate, FunctionEvent(name.c_str(), script->id(), time_taken_ms,
124 125 126 127
                             shared->StartPosition(), shared->EndPosition(),
                             shared->DebugName()));
}

128
ScriptOriginOptions OriginOptionsForEval(Object script) {
129 130 131 132 133 134 135
  if (!script->IsScript()) return ScriptOriginOptions();

  const auto outer_origin_options = Script::cast(script)->origin_options();
  return ScriptOriginOptions(outer_origin_options.IsSharedCrossOrigin(),
                             outer_origin_options.IsOpaque());
}

136 137 138 139 140 141
}  // namespace

// ----------------------------------------------------------------------------
// Implementation of UnoptimizedCompilationJob

CompilationJob::Status UnoptimizedCompilationJob::ExecuteJob() {
142
  DisallowHeapAccess no_heap_access;
143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 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
  // Delegate to the underlying implementation.
  DCHECK_EQ(state(), State::kReadyToExecute);
  ScopedTimer t(&time_taken_to_execute_);
  return UpdateState(ExecuteJobImpl(), State::kReadyToFinalize);
}

CompilationJob::Status UnoptimizedCompilationJob::FinalizeJob(
    Handle<SharedFunctionInfo> shared_info, Isolate* isolate) {
  DCHECK(ThreadId::Current().Equals(isolate->thread_id()));
  DisallowCodeDependencyChange no_dependency_change;
  DisallowJavascriptExecution no_js(isolate);

  // Delegate to the underlying implementation.
  DCHECK_EQ(state(), State::kReadyToFinalize);
  ScopedTimer t(&time_taken_to_finalize_);
  return UpdateState(FinalizeJobImpl(shared_info, isolate), State::kSucceeded);
}

void UnoptimizedCompilationJob::RecordCompilationStats(Isolate* isolate) const {
  int code_size;
  if (compilation_info()->has_bytecode_array()) {
    code_size = compilation_info()->bytecode_array()->SizeIncludingMetadata();
  } else {
    DCHECK(compilation_info()->has_asm_wasm_data());
    code_size = compilation_info()->asm_wasm_data()->Size();
  }

  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 UnoptimizedCompilationJob::RecordFunctionCompilation(
    CodeEventListener::LogEventsAndTags tag, Handle<SharedFunctionInfo> shared,
    Isolate* isolate) const {
  Handle<AbstractCode> abstract_code;
  if (compilation_info()->has_bytecode_array()) {
    abstract_code =
        Handle<AbstractCode>::cast(compilation_info()->bytecode_array());
  } else {
    DCHECK(compilation_info()->has_asm_wasm_data());
    abstract_code =
        Handle<AbstractCode>::cast(BUILTIN_CODE(isolate, InstantiateAsmJs));
  }

  double time_taken_ms = time_taken_to_execute_.InMillisecondsF() +
                         time_taken_to_finalize_.InMillisecondsF();

  LogFunctionCompilation(tag, shared, parse_info()->script(), abstract_code,
                         false, time_taken_ms, isolate);
}

198
// ----------------------------------------------------------------------------
199 200 201
// Implementation of OptimizedCompilationJob

CompilationJob::Status OptimizedCompilationJob::PrepareJob(Isolate* isolate) {
202 203
  DCHECK(ThreadId::Current().Equals(isolate->thread_id()));
  DisallowJavascriptExecution no_js(isolate);
204

205
  if (FLAG_trace_opt && compilation_info()->IsOptimizing()) {
206
    StdoutStream os;
207 208 209
    os << "[compiling method " << Brief(*compilation_info()->closure())
       << " using " << compiler_name_;
    if (compilation_info()->is_osr()) os << " OSR";
210 211 212
    os << "]" << std::endl;
  }

213
  // Delegate to the underlying implementation.
214
  DCHECK_EQ(state(), State::kReadyToPrepare);
215
  ScopedTimer t(&time_taken_to_prepare_);
216
  return UpdateState(PrepareJobImpl(isolate), State::kReadyToExecute);
217 218
}

219
CompilationJob::Status OptimizedCompilationJob::ExecuteJob() {
220
  DisallowHeapAccess no_heap_access;
221
  // Delegate to the underlying implementation.
222
  DCHECK_EQ(state(), State::kReadyToExecute);
223 224
  ScopedTimer t(&time_taken_to_execute_);
  return UpdateState(ExecuteJobImpl(), State::kReadyToFinalize);
225
}
226

227
CompilationJob::Status OptimizedCompilationJob::FinalizeJob(Isolate* isolate) {
228 229
  DCHECK(ThreadId::Current().Equals(isolate->thread_id()));
  DisallowJavascriptExecution no_js(isolate);
230

231
  // Delegate to the underlying implementation.
232
  DCHECK_EQ(state(), State::kReadyToFinalize);
233
  ScopedTimer t(&time_taken_to_finalize_);
234
  return UpdateState(FinalizeJobImpl(isolate), State::kSucceeded);
235 236
}

237 238
CompilationJob::Status OptimizedCompilationJob::RetryOptimization(
    BailoutReason reason) {
239 240
  DCHECK(compilation_info_->IsOptimizing());
  compilation_info_->RetryOptimization(reason);
241
  return UpdateState(FAILED, State::kFailed);
242 243
}

244 245
CompilationJob::Status OptimizedCompilationJob::AbortOptimization(
    BailoutReason reason) {
246 247
  DCHECK(compilation_info_->IsOptimizing());
  compilation_info_->AbortOptimization(reason);
248
  return UpdateState(FAILED, State::kFailed);
249 250
}

251
void OptimizedCompilationJob::RecordCompilationStats() const {
252 253
  DCHECK(compilation_info()->IsOptimizing());
  Handle<JSFunction> function = compilation_info()->closure();
254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275
  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);
  }
}

276
void OptimizedCompilationJob::RecordFunctionCompilation(
277
    CodeEventListener::LogEventsAndTags tag, Isolate* isolate) const {
278 279
  Handle<AbstractCode> abstract_code =
      Handle<AbstractCode>::cast(compilation_info()->code());
280

281 282 283
  double time_taken_ms = time_taken_to_prepare_.InMillisecondsF() +
                         time_taken_to_execute_.InMillisecondsF() +
                         time_taken_to_finalize_.InMillisecondsF();
284

285
  Handle<Script> script(
286
      Script::cast(compilation_info()->shared_info()->script()), isolate);
287 288
  LogFunctionCompilation(tag, compilation_info()->shared_info(), script,
                         abstract_code, true, time_taken_ms, isolate);
289 290
}

291 292 293 294 295
// ----------------------------------------------------------------------------
// Local helper methods that make up the compilation pipeline.

namespace {

296
bool UseAsmWasm(FunctionLiteral* literal, bool asm_wasm_broken) {
297 298 299 300 301
  // Check whether asm.js validation is enabled.
  if (!FLAG_validate_asm) return false;

  // Modules that have validated successfully, but were subsequently broken by
  // invalid module instantiation attempts are off limit forever.
302
  if (asm_wasm_broken) return false;
303 304 305 306 307

  // In stress mode we want to run the validator on everything.
  if (FLAG_stress_validate_asm) return true;

  // In general, we respect the "use asm" directive.
308
  return literal->scope()->IsAsmModule();
309 310
}

311 312 313 314 315 316 317 318
void InstallBytecodeArray(Handle<BytecodeArray> bytecode_array,
                          Handle<SharedFunctionInfo> shared_info,
                          ParseInfo* parse_info, Isolate* isolate) {
  if (!FLAG_interpreted_frames_native_stack) {
    shared_info->set_bytecode_array(*bytecode_array);
    return;
  }

319 320
  Handle<Code> code = isolate->factory()->CopyCode(Handle<Code>::cast(
      isolate->factory()->interpreter_entry_trampoline_for_profiling()));
321 322 323 324 325 326 327 328 329 330 331 332 333 334 335

  Handle<InterpreterData> interpreter_data = Handle<InterpreterData>::cast(
      isolate->factory()->NewStruct(INTERPRETER_DATA_TYPE, TENURED));

  interpreter_data->set_bytecode_array(*bytecode_array);
  interpreter_data->set_interpreter_trampoline(*code);

  shared_info->set_interpreter_data(*interpreter_data);

  Handle<Script> script = parse_info->script();
  Handle<AbstractCode> abstract_code = Handle<AbstractCode>::cast(code);
  int line_num =
      Script::GetLineNumber(script, shared_info->StartPosition()) + 1;
  int column_num =
      Script::GetColumnNumber(script, shared_info->StartPosition()) + 1;
336 337 338
  String script_name = script->name()->IsString()
                           ? String::cast(script->name())
                           : ReadOnlyRoots(isolate).empty_string();
339 340 341 342 343 344
  CodeEventListener::LogEventsAndTags log_tag = Logger::ToNativeByScript(
      CodeEventListener::INTERPRETED_FUNCTION_TAG, *script);
  PROFILE(isolate, CodeCreateEvent(log_tag, *abstract_code, *shared_info,
                                   script_name, line_num, column_num));
}

345 346
void InstallUnoptimizedCode(UnoptimizedCompilationInfo* compilation_info,
                            Handle<SharedFunctionInfo> shared_info,
347
                            ParseInfo* parse_info, Isolate* isolate) {
348
  DCHECK_EQ(shared_info->language_mode(),
349
            compilation_info->literal()->language_mode());
350

351
  // Update the shared function info with the scope info.
352
  Handle<ScopeInfo> scope_info = compilation_info->scope()->scope_info();
353
  shared_info->set_scope_info(*scope_info);
354

355
  if (compilation_info->has_bytecode_array()) {
356
    DCHECK(!shared_info->HasBytecodeArray());  // Only compiled once.
357
    DCHECK(!compilation_info->has_asm_wasm_data());
358 359
    DCHECK(!shared_info->HasFeedbackMetadata());

360 361
    InstallBytecodeArray(compilation_info->bytecode_array(), shared_info,
                         parse_info, isolate);
362 363 364 365
    if (FLAG_lite_mode) {
      // Clear the feedback metadata field. In lite mode we don't need feedback
      // metadata since we never allocate feedback vectors.
      shared_info->set_raw_outer_scope_info_or_feedback_metadata(
366
          ReadOnlyRoots(isolate).undefined_value());
367 368 369 370 371
    } else {
      Handle<FeedbackMetadata> feedback_metadata = FeedbackMetadata::New(
          isolate, compilation_info->feedback_vector_spec());
      shared_info->set_feedback_metadata(*feedback_metadata);
    }
372 373
  } else {
    DCHECK(compilation_info->has_asm_wasm_data());
374
    shared_info->set_asm_wasm_data(*compilation_info->asm_wasm_data());
375
    shared_info->set_feedback_metadata(
376
        ReadOnlyRoots(isolate).empty_feedback_metadata());
377
  }
378 379

  // Install coverage info on the shared function info.
380 381
  if (compilation_info->has_coverage_info() &&
      !shared_info->HasCoverageInfo()) {
382
    DCHECK(isolate->is_block_code_coverage());
383
    isolate->debug()->InstallCoverageInfo(shared_info,
384
                                          compilation_info->coverage_info());
385
  }
386
}
387

388 389 390 391 392 393 394
void EnsureSharedFunctionInfosArrayOnScript(ParseInfo* parse_info,
                                            Isolate* isolate) {
  DCHECK(parse_info->is_toplevel());
  DCHECK(!parse_info->script().is_null());
  if (parse_info->script()->shared_function_infos()->length() > 0) {
    DCHECK_EQ(parse_info->script()->shared_function_infos()->length(),
              parse_info->max_function_literal_id() + 1);
395 396
    return;
  }
397
  Handle<WeakFixedArray> infos(isolate->factory()->NewWeakFixedArray(
398 399
      parse_info->max_function_literal_id() + 1));
  parse_info->script()->set_shared_function_infos(*infos);
400 401
}

402 403
void SetSharedFunctionFlagsFromLiteral(FunctionLiteral* literal,
                                       Handle<SharedFunctionInfo> shared_info) {
404 405 406 407
  // Don't overwrite values set by the bootstrapper.
  if (!shared_info->HasLength()) {
    shared_info->set_length(literal->function_length());
  }
408 409
  shared_info->set_has_duplicate_parameters(
      literal->has_duplicate_parameters());
410
  shared_info->set_is_oneshot_iife(literal->is_oneshot_iife());
411
  shared_info->SetExpectedNofPropertiesFromEstimate(literal);
412
  if (literal->dont_optimize_reason() != BailoutReason::kNoReason) {
413 414
    shared_info->DisableOptimization(literal->dont_optimize_reason());
  }
415 416
}

417 418 419 420
CompilationJob::Status FinalizeUnoptimizedCompilationJob(
    UnoptimizedCompilationJob* job, Handle<SharedFunctionInfo> shared_info,
    Isolate* isolate) {
  UnoptimizedCompilationInfo* compilation_info = job->compilation_info();
421
  ParseInfo* parse_info = job->parse_info();
422

423
  SetSharedFunctionFlagsFromLiteral(compilation_info->literal(), shared_info);
424

425
  CompilationJob::Status status = job->FinalizeJob(shared_info, isolate);
426
  if (status == CompilationJob::SUCCEEDED) {
427
    InstallUnoptimizedCode(compilation_info, shared_info, parse_info, isolate);
428 429 430 431 432 433 434 435
    CodeEventListener::LogEventsAndTags log_tag;
    if (parse_info->is_toplevel()) {
      log_tag = compilation_info->is_eval() ? CodeEventListener::EVAL_TAG
                                            : CodeEventListener::SCRIPT_TAG;
    } else {
      log_tag = parse_info->lazy_compile() ? CodeEventListener::LAZY_COMPILE_TAG
                                           : CodeEventListener::FUNCTION_TAG;
    }
436 437
    job->RecordFunctionCompilation(log_tag, shared_info, isolate);
    job->RecordCompilationStats(isolate);
438
  }
439
  return status;
440 441
}

442
std::unique_ptr<UnoptimizedCompilationJob> ExecuteUnoptimizedCompileJobs(
443
    ParseInfo* parse_info, FunctionLiteral* literal,
444 445
    AccountingAllocator* allocator,
    UnoptimizedCompilationJobList* inner_function_jobs) {
446
  if (UseAsmWasm(literal, parse_info->is_asm_wasm_broken())) {
447
    std::unique_ptr<UnoptimizedCompilationJob> asm_job(
448
        AsmJs::NewCompilationJob(parse_info, literal, allocator));
449
    if (asm_job->ExecuteJob() == CompilationJob::SUCCEEDED) {
450
      return asm_job;
451
    }
452
    // asm.js validation failed, fall through to standard unoptimized compile.
453 454 455 456
    // Note: we rely on the fact that AsmJs jobs have done all validation in the
    // PrepareJob and ExecuteJob phases and can't fail in FinalizeJob with
    // with a validation error or another error that could be solve by falling
    // through to standard unoptimized compile.
457
  }
458
  std::vector<FunctionLiteral*> eager_inner_literals;
459
  std::unique_ptr<UnoptimizedCompilationJob> job(
460 461
      interpreter::Interpreter::NewCompilationJob(
          parse_info, literal, allocator, &eager_inner_literals));
462

463 464
  if (job->ExecuteJob() != CompilationJob::SUCCEEDED) {
    // Compilation failed, return null.
465
    return std::unique_ptr<UnoptimizedCompilationJob>();
466 467 468 469
  }

  // Recursively compile eager inner literals.
  for (FunctionLiteral* inner_literal : eager_inner_literals) {
470 471 472
    std::unique_ptr<UnoptimizedCompilationJob> inner_job(
        ExecuteUnoptimizedCompileJobs(parse_info, inner_literal, allocator,
                                      inner_function_jobs));
473
    // Compilation failed, return null.
474
    if (!inner_job) return std::unique_ptr<UnoptimizedCompilationJob>();
475
    inner_function_jobs->emplace_front(std::move(inner_job));
476
  }
477 478

  return job;
479 480
}

481
std::unique_ptr<UnoptimizedCompilationJob> GenerateUnoptimizedCode(
482
    ParseInfo* parse_info, AccountingAllocator* allocator,
483
    UnoptimizedCompilationJobList* inner_function_jobs) {
484
  DisallowHeapAccess no_heap_access;
485
  DCHECK(inner_function_jobs->empty());
486

487
  if (!Compiler::Analyze(parse_info)) {
488
    return std::unique_ptr<UnoptimizedCompilationJob>();
489 490
  }

491
  // Prepare and execute compilation of the outer-most function.
492 493 494 495
  std::unique_ptr<UnoptimizedCompilationJob> outer_function_job(
      ExecuteUnoptimizedCompileJobs(parse_info, parse_info->literal(),
                                    allocator, inner_function_jobs));
  if (!outer_function_job) return std::unique_ptr<UnoptimizedCompilationJob>();
496

497 498 499
  // Character stream shouldn't be used again.
  parse_info->ResetCharacterStream();

500 501 502
  return outer_function_job;
}

503
MaybeHandle<SharedFunctionInfo> GenerateUnoptimizedCodeForToplevel(
504 505
    Isolate* isolate, ParseInfo* parse_info, AccountingAllocator* allocator,
    IsCompiledScope* is_compiled_scope) {
506 507 508 509 510 511 512 513 514 515 516 517 518
  EnsureSharedFunctionInfosArrayOnScript(parse_info, isolate);
  parse_info->ast_value_factory()->Internalize(isolate);

  if (!Compiler::Analyze(parse_info)) return MaybeHandle<SharedFunctionInfo>();
  DeclarationScope::AllocateScopeInfos(parse_info, isolate);

  // Prepare and execute compilation of the outer-most function.
  // Create the SharedFunctionInfo and add it to the script's list.
  Handle<Script> script = parse_info->script();
  Handle<SharedFunctionInfo> top_level =
      isolate->factory()->NewSharedFunctionInfoForLiteral(parse_info->literal(),
                                                          script, true);

519 520
  std::vector<FunctionLiteral*> functions_to_compile;
  functions_to_compile.push_back(parse_info->literal());
521

522 523 524
  while (!functions_to_compile.empty()) {
    FunctionLiteral* literal = functions_to_compile.back();
    functions_to_compile.pop_back();
525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543
    Handle<SharedFunctionInfo> shared_info =
        Compiler::GetSharedFunctionInfo(literal, script, isolate);
    if (shared_info->is_compiled()) continue;
    if (UseAsmWasm(literal, parse_info->is_asm_wasm_broken())) {
      std::unique_ptr<UnoptimizedCompilationJob> asm_job(
          AsmJs::NewCompilationJob(parse_info, literal, allocator));
      if (asm_job->ExecuteJob() == CompilationJob::SUCCEEDED &&
          FinalizeUnoptimizedCompilationJob(asm_job.get(), shared_info,
                                            isolate) ==
              CompilationJob::SUCCEEDED) {
        continue;
      }
      // asm.js validation failed, fall through to standard unoptimized compile.
      // Note: we rely on the fact that AsmJs jobs have done all validation in
      // the PrepareJob and ExecuteJob phases and can't fail in FinalizeJob with
      // with a validation error or another error that could be solve by falling
      // through to standard unoptimized compile.
    }

544 545 546
    std::unique_ptr<UnoptimizedCompilationJob> job(
        interpreter::Interpreter::NewCompilationJob(
            parse_info, literal, allocator, &functions_to_compile));
547

548 549 550 551
    if (job->ExecuteJob() == CompilationJob::FAILED ||
        FinalizeUnoptimizedCompilationJob(job.get(), shared_info, isolate) ==
            CompilationJob::FAILED) {
      return MaybeHandle<SharedFunctionInfo>();
552
    }
553 554 555 556 557 558

    if (shared_info.is_identical_to(top_level)) {
      // Ensure that the top level function is retained.
      *is_compiled_scope = shared_info->is_compiled_scope();
      DCHECK(is_compiled_scope->is_compiled());
    }
559 560 561 562 563 564 565 566
  }

  // Character stream shouldn't be used again.
  parse_info->ResetCharacterStream();

  return top_level;
}

567 568 569 570 571
bool FinalizeUnoptimizedCode(
    ParseInfo* parse_info, Isolate* isolate,
    Handle<SharedFunctionInfo> shared_info,
    UnoptimizedCompilationJob* outer_function_job,
    UnoptimizedCompilationJobList* inner_function_jobs) {
572 573
  DCHECK(AllowCompilation::IsAllowed(isolate));

574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594
  // TODO(rmcilroy): Clear native context in debug once AsmJS generates doesn't
  // rely on accessing native context during finalization.

  // Allocate scope infos for the literal.
  DeclarationScope::AllocateScopeInfos(parse_info, isolate);

  // Finalize the outer-most function's compilation job.
  if (FinalizeUnoptimizedCompilationJob(outer_function_job, shared_info,
                                        isolate) != CompilationJob::SUCCEEDED) {
    return false;
  }

  // Finalize the inner functions' compilation jobs.
  for (auto&& inner_job : *inner_function_jobs) {
    Handle<SharedFunctionInfo> inner_shared_info =
        Compiler::GetSharedFunctionInfo(
            inner_job->compilation_info()->literal(), parse_info->script(),
            isolate);
    // The inner function might be compiled already if compiling for debug.
    if (inner_shared_info->is_compiled()) continue;
    if (FinalizeUnoptimizedCompilationJob(inner_job.get(), inner_shared_info,
595
                                          isolate) !=
596
        CompilationJob::SUCCEEDED) {
597
      return false;
598 599
    }
  }
600 601 602 603 604 605 606

  // Report any warnings generated during compilation.
  if (parse_info->pending_error_handler()->has_pending_warnings()) {
    parse_info->pending_error_handler()->ReportWarnings(isolate,
                                                        parse_info->script());
  }

607
  return true;
608 609
}

610
V8_WARN_UNUSED_RESULT MaybeHandle<Code> GetCodeFromOptimizedCodeCache(
611
    Handle<JSFunction> function, BailoutId osr_offset) {
612 613
  RuntimeCallTimerScope runtimeTimer(
      function->GetIsolate(),
614
      RuntimeCallCounterId::kCompileGetFromOptimizedCodeMap);
615
  Handle<SharedFunctionInfo> shared(function->shared(), function->GetIsolate());
616
  DisallowHeapAllocation no_gc;
617
  if (osr_offset.IsNone()) {
618
    if (function->has_feedback_vector()) {
619
      FeedbackVector feedback_vector = function->feedback_vector();
620 621
      feedback_vector->EvictOptimizedCodeMarkedForDeoptimization(
          function->shared(), "GetCodeFromOptimizedCodeCache");
622
      Code code = feedback_vector->optimized_code();
623

624
      if (!code.is_null()) {
625 626 627
        // Caching of optimized code enabled and optimized code found.
        DCHECK(!code->marked_for_deoptimization());
        DCHECK(function->shared()->is_compiled());
628
        return Handle<Code>(code, feedback_vector->GetIsolate());
629
      }
630
    }
631 632 633 634
  }
  return MaybeHandle<Code>();
}

635
void ClearOptimizedCodeCache(OptimizedCompilationInfo* compilation_info) {
636
  Handle<JSFunction> function = compilation_info->closure();
637
  if (compilation_info->osr_offset().IsNone()) {
638 639
    Handle<FeedbackVector> vector =
        handle(function->feedback_vector(), function->GetIsolate());
640
    vector->ClearOptimizationMarker();
641 642 643
  }
}

644 645
void InsertCodeIntoOptimizedCodeCache(
    OptimizedCompilationInfo* compilation_info) {
646
  Handle<Code> code = compilation_info->code();
647 648
  if (code->kind() != Code::OPTIMIZED_FUNCTION) return;  // Nothing to do.

649 650
  // Function context specialization folds-in the function context,
  // so no sharing can occur.
651
  if (compilation_info->is_function_context_specializing()) {
652 653
    // Native context specialized code is not shared, so make sure the optimized
    // code cache is clear.
654
    ClearOptimizedCodeCache(compilation_info);
655 656
    return;
  }
657

658
  // Cache optimized context-specific code.
659
  Handle<JSFunction> function = compilation_info->closure();
660 661 662
  Handle<SharedFunctionInfo> shared(function->shared(), function->GetIsolate());
  Handle<Context> native_context(function->context()->native_context(),
                                 function->GetIsolate());
663
  if (compilation_info->osr_offset().IsNone()) {
664 665 666 667
    Handle<FeedbackVector> vector =
        handle(function->feedback_vector(), function->GetIsolate());
    FeedbackVector::SetOptimizedCode(vector, code);
  }
668 669
}

670
bool GetOptimizedCodeNow(OptimizedCompilationJob* job, Isolate* isolate) {
671
  TimerEventScope<TimerEventRecompileSynchronous> timer(isolate);
672 673
  RuntimeCallTimerScope runtimeTimer(
      isolate, RuntimeCallCounterId::kRecompileSynchronous);
674
  OptimizedCompilationInfo* compilation_info = job->compilation_info();
675 676
  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
               "V8.RecompileSynchronous");
677

678
  if (job->PrepareJob(isolate) != CompilationJob::SUCCEEDED ||
679
      job->ExecuteJob() != CompilationJob::SUCCEEDED ||
680
      job->FinalizeJob(isolate) != CompilationJob::SUCCEEDED) {
681 682
    if (FLAG_trace_opt) {
      PrintF("[aborted optimizing ");
683 684 685
      compilation_info->closure()->ShortPrint();
      PrintF(" because: %s]\n",
             GetBailoutReason(compilation_info->bailout_reason()));
686 687 688
    }
    return false;
  }
689 690

  // Success!
691
  job->RecordCompilationStats();
692
  DCHECK(!isolate->has_pending_exception());
693
  InsertCodeIntoOptimizedCodeCache(compilation_info);
694
  job->RecordFunctionCompilation(CodeEventListener::LAZY_COMPILE_TAG, isolate);
695 696 697
  return true;
}

698 699
bool GetOptimizedCodeLater(OptimizedCompilationJob* job, Isolate* isolate) {
  OptimizedCompilationInfo* compilation_info = job->compilation_info();
700
  if (!isolate->optimizing_compile_dispatcher()->IsQueueAvailable()) {
701 702
    if (FLAG_trace_concurrent_recompilation) {
      PrintF("  ** Compilation queue full, will retry optimizing ");
703
      compilation_info->closure()->ShortPrint();
704 705 706 707 708
      PrintF(" later.\n");
    }
    return false;
  }

709 710 711
  if (isolate->heap()->HighMemoryPressure()) {
    if (FLAG_trace_concurrent_recompilation) {
      PrintF("  ** High memory pressure, will retry optimizing ");
712
      compilation_info->closure()->ShortPrint();
713 714 715 716 717
      PrintF(" later.\n");
    }
    return false;
  }

718
  TimerEventScope<TimerEventRecompileSynchronous> timer(isolate);
719 720
  RuntimeCallTimerScope runtimeTimer(
      isolate, RuntimeCallCounterId::kRecompileSynchronous);
721 722
  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
               "V8.RecompileSynchronous");
723

724
  if (job->PrepareJob(isolate) != CompilationJob::SUCCEEDED) return false;
725
  isolate->optimizing_compile_dispatcher()->QueueForOptimization(job);
726 727 728

  if (FLAG_trace_concurrent_recompilation) {
    PrintF("  ** Queued ");
729
    compilation_info->closure()->ShortPrint();
730
    PrintF(" for concurrent optimization.\n");
731 732 733 734
  }
  return true;
}

735
MaybeHandle<Code> GetOptimizedCode(Handle<JSFunction> function,
736
                                   ConcurrencyMode mode,
737
                                   BailoutId osr_offset = BailoutId::None(),
738 739 740 741
                                   JavaScriptFrame* osr_frame = nullptr) {
  Isolate* isolate = function->GetIsolate();
  Handle<SharedFunctionInfo> shared(function->shared(), isolate);

742 743 744 745 746 747
  // Make sure we clear the optimization marker on the function so that we
  // don't try to re-optimize.
  if (function->HasOptimizationMarker()) {
    function->ClearOptimizationMarker();
  }

748 749 750 751 752
  if (shared->optimization_disabled() &&
      shared->disable_optimization_reason() == BailoutReason::kNeverOptimize) {
    return MaybeHandle<Code>();
  }

753 754 755 756 757
  if (isolate->debug()->needs_check_on_function_call()) {
    // Do not optimize when debugger needs to hook into every call.
    return MaybeHandle<Code>();
  }

758
  Handle<Code> cached_code;
759
  if (GetCodeFromOptimizedCodeCache(function, osr_offset)
760 761 762 763
          .ToHandle(&cached_code)) {
    if (FLAG_trace_opt) {
      PrintF("[found optimized code for ");
      function->ShortPrint();
764 765
      if (!osr_offset.IsNone()) {
        PrintF(" at OSR AST id %d", osr_offset.ToInt());
766 767 768 769 770 771
      }
      PrintF("]\n");
    }
    return cached_code;
  }

772
  // Reset profiler ticks, function is no longer considered hot.
773
  DCHECK(shared->is_compiled());
774
  function->feedback_vector()->set_profiler_ticks(0);
775 776 777 778

  VMState<COMPILER> state(isolate);
  DCHECK(!isolate->has_pending_exception());
  PostponeInterruptsScope postpone(isolate);
779
  bool has_script = shared->script()->IsScript();
780 781 782
  // BUG(5946): This DCHECK is necessary to make certain that we won't
  // tolerate the lack of a script without bytecode.
  DCHECK_IMPLIES(!has_script, shared->HasBytecodeArray());
783
  std::unique_ptr<OptimizedCompilationJob> job(
784
      compiler::Pipeline::NewCompilationJob(isolate, function, has_script));
785
  OptimizedCompilationInfo* compilation_info = job->compilation_info();
786

787
  compilation_info->SetOptimizingForOsr(osr_offset, osr_frame);
788

789
  // Do not use TurboFan if we need to be able to set break points.
790
  if (compilation_info->shared_info()->HasBreakInfo()) {
791
    compilation_info->AbortOptimization(BailoutReason::kFunctionBeingDebugged);
792 793 794
    return MaybeHandle<Code>();
  }

795 796 797
  // Do not use TurboFan if optimization is disabled or function doesn't pass
  // turbo_filter.
  if (!FLAG_opt || !shared->PassesFilter(FLAG_turbo_filter)) {
798
    compilation_info->AbortOptimization(BailoutReason::kOptimizationDisabled);
799 800 801
    return MaybeHandle<Code>();
  }

802
  TimerEventScope<TimerEventOptimizeCode> optimize_code_timer(isolate);
803 804
  RuntimeCallTimerScope runtimeTimer(isolate,
                                     RuntimeCallCounterId::kOptimizeCode);
805
  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.OptimizeCode");
806

807 808 809
  // 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.
810
  base::Optional<CompilationHandleScope> compilation;
811
  if (mode == ConcurrencyMode::kConcurrent) {
812
    compilation.emplace(isolate, compilation_info);
813 814
  }

815
  // All handles below will be canonicalized.
816
  CanonicalHandleScope canonical(isolate);
817 818

  // Reopen handles in the new CompilationHandleScope.
819
  compilation_info->ReopenHandlesInNewHandleScope(isolate);
820

821
  if (mode == ConcurrencyMode::kConcurrent) {
822
    if (GetOptimizedCodeLater(job.get(), isolate)) {
823
      job.release();  // The background recompile job owns this now.
824 825 826

      // Set the optimization marker and return a code object which checks it.
      function->SetOptimizationMarker(OptimizationMarker::kInOptimizationQueue);
827 828 829 830
      DCHECK(function->IsInterpreted() ||
             (!function->is_compiled() && function->shared()->IsInterpreted()));
      DCHECK(function->shared()->HasBytecodeArray());
      return BUILTIN_CODE(isolate, InterpreterEntryTrampoline);
831 832
    }
  } else {
833 834
    if (GetOptimizedCodeNow(job.get(), isolate))
      return compilation_info->code();
835 836 837 838 839 840
  }

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

841 842 843 844 845 846 847 848 849 850 851 852 853 854 855
bool FailWithPendingException(Isolate* isolate, ParseInfo* parse_info,
                              Compiler::ClearExceptionFlag flag) {
  if (flag == Compiler::CLEAR_EXCEPTION) {
    isolate->clear_pending_exception();
  } else if (!isolate->has_pending_exception()) {
    if (parse_info->pending_error_handler()->has_pending_error()) {
      parse_info->pending_error_handler()->ReportErrors(
          isolate, parse_info->script(), parse_info->ast_value_factory());
    } else {
      isolate->StackOverflow();
    }
  }
  return false;
}

856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877
void FinalizeScriptCompilation(Isolate* isolate, ParseInfo* parse_info) {
  Handle<Script> script = parse_info->script();
  script->set_compilation_state(Script::COMPILATION_STATE_COMPILED);

  // Register any pending parallel tasks with the associated SFI.
  if (parse_info->parallel_tasks()) {
    CompilerDispatcher* dispatcher = parse_info->parallel_tasks()->dispatcher();
    for (auto& it : *parse_info->parallel_tasks()) {
      FunctionLiteral* literal = it.first;
      CompilerDispatcher::JobId job_id = it.second;
      MaybeHandle<SharedFunctionInfo> maybe_shared_for_task =
          script->FindSharedFunctionInfo(isolate, literal);
      Handle<SharedFunctionInfo> shared_for_task;
      if (maybe_shared_for_task.ToHandle(&shared_for_task)) {
        dispatcher->RegisterSharedFunctionInfo(job_id, *shared_for_task);
      } else {
        dispatcher->AbortJob(job_id);
      }
    }
  }
}

878
MaybeHandle<SharedFunctionInfo> FinalizeTopLevel(
879 880 881
    ParseInfo* parse_info, Isolate* isolate,
    UnoptimizedCompilationJob* outer_function_job,
    UnoptimizedCompilationJobList* inner_function_jobs) {
882
  // Internalize ast values onto the heap.
883
  parse_info->ast_value_factory()->Internalize(isolate);
884 885 886 887 888 889 890

  // Create shared function infos for top level and shared function infos array
  // for inner functions.
  EnsureSharedFunctionInfosArrayOnScript(parse_info, isolate);
  DCHECK_EQ(kNoSourcePosition,
            parse_info->literal()->function_token_position());
  Handle<SharedFunctionInfo> shared_info =
891 892
      isolate->factory()->NewSharedFunctionInfoForLiteral(
          parse_info->literal(), parse_info->script(), true);
893 894 895 896

  // Finalize compilation of the unoptimized bytecode or asm-js data.
  if (!FinalizeUnoptimizedCode(parse_info, isolate, shared_info,
                               outer_function_job, inner_function_jobs)) {
897 898
    FailWithPendingException(isolate, parse_info,
                             Compiler::ClearExceptionFlag::KEEP_EXCEPTION);
899 900 901
    return MaybeHandle<SharedFunctionInfo>();
  }

902
  FinalizeScriptCompilation(isolate, parse_info);
903

904 905 906
  return shared_info;
}

907 908 909
MaybeHandle<SharedFunctionInfo> CompileToplevel(
    ParseInfo* parse_info, Isolate* isolate,
    IsCompiledScope* is_compiled_scope) {
910
  TimerEventScope<TimerEventCompileCode> top_level_timer(isolate);
911
  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.CompileCode");
912 913
  DCHECK(ThreadId::Current().Equals(isolate->thread_id()));

914
  PostponeInterruptsScope postpone(isolate);
915
  DCHECK(!isolate->native_context().is_null());
916
  RuntimeCallTimerScope runtimeTimer(
917 918
      isolate, parse_info->is_eval() ? RuntimeCallCounterId::kCompileEval
                                     : RuntimeCallCounterId::kCompileScript);
919 920 921 922 923 924 925 926 927 928 929 930 931 932
  VMState<BYTECODE_COMPILER> state(isolate);
  if (parse_info->literal() == nullptr &&
      !parsing::ParseProgram(parse_info, isolate)) {
    return MaybeHandle<SharedFunctionInfo>();
  }
  // 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.
  HistogramTimer* rate = parse_info->is_eval()
                             ? isolate->counters()->compile_eval()
                             : isolate->counters()->compile();
  HistogramTimerScope timer(rate);
  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
               parse_info->is_eval() ? "V8.CompileEval" : "V8.Compile");
933

934
  // Generate the unoptimized bytecode or asm-js data.
935
  MaybeHandle<SharedFunctionInfo> shared_info =
936 937
      GenerateUnoptimizedCodeForToplevel(
          isolate, parse_info, isolate->allocator(), is_compiled_scope);
938
  if (shared_info.is_null()) {
939 940
    FailWithPendingException(isolate, parse_info,
                             Compiler::ClearExceptionFlag::KEEP_EXCEPTION);
941 942
    return MaybeHandle<SharedFunctionInfo>();
  }
943

944 945
  FinalizeScriptCompilation(isolate, parse_info);
  return shared_info;
946 947
}

948
std::unique_ptr<UnoptimizedCompilationJob> CompileOnBackgroundThread(
949
    ParseInfo* parse_info, AccountingAllocator* allocator,
950
    UnoptimizedCompilationJobList* inner_function_jobs) {
951
  DisallowHeapAccess no_heap_access;
952 953 954 955
  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
               "V8.CompileCodeBackground");
  RuntimeCallTimerScope runtimeTimer(
      parse_info->runtime_call_stats(),
956 957 958 959 960
      parse_info->is_toplevel()
          ? parse_info->is_eval()
                ? RuntimeCallCounterId::kCompileBackgroundEval
                : RuntimeCallCounterId::kCompileBackgroundScript
          : RuntimeCallCounterId::kCompileBackgroundFunction);
961 962

  // Generate the unoptimized bytecode or asm-js data.
963
  std::unique_ptr<UnoptimizedCompilationJob> outer_function_job(
964 965 966 967
      GenerateUnoptimizedCode(parse_info, allocator, inner_function_jobs));
  return outer_function_job;
}

968
}  // namespace
969

970
BackgroundCompileTask::BackgroundCompileTask(ScriptStreamingData* streamed_data,
971
                                             Isolate* isolate)
972
    : info_(new ParseInfo(isolate)),
973
      stack_size_(i::FLAG_stack_size),
974 975
      worker_thread_runtime_call_stats_(
          isolate->counters()->worker_thread_runtime_call_stats()),
976
      allocator_(isolate->allocator()),
977 978 979 980 981
      timer_(isolate->counters()->compile_script_on_background()) {
  VMState<PARSER> state(isolate);

  // Prepare the data for the internalization phase and compilation phase, which
  // will happen in the main thread after parsing.
982
  LOG(isolate, ScriptEvent(Logger::ScriptEventType::kStreamingCompile,
983 984 985 986 987
                           info_->script_id()));
  info_->set_toplevel();
  info_->set_allow_lazy_parsing();
  if (V8_UNLIKELY(info_->block_coverage_enabled())) {
    info_->AllocateSourceRangeMap();
988 989
  }
  LanguageMode language_mode = construct_language_mode(FLAG_use_strict);
990 991
  info_->set_language_mode(
      stricter_language_mode(info_->language_mode(), language_mode));
992

993 994 995
  std::unique_ptr<Utf16CharacterStream> stream(ScannerStream::For(
      streamed_data->source_stream.get(), streamed_data->encoding));
  info_->set_character_stream(std::move(stream));
996 997
}

998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018
BackgroundCompileTask::BackgroundCompileTask(
    AccountingAllocator* allocator, const ParseInfo* outer_parse_info,
    const AstRawString* function_name, const FunctionLiteral* function_literal,
    WorkerThreadRuntimeCallStats* worker_thread_runtime_stats,
    TimedHistogram* timer, int max_stack_size)
    : info_(ParseInfo::FromParent(outer_parse_info, allocator, function_literal,
                                  function_name)),
      stack_size_(max_stack_size),
      worker_thread_runtime_call_stats_(worker_thread_runtime_stats),
      allocator_(allocator),
      timer_(timer) {
  DCHECK(outer_parse_info->is_toplevel());
  DCHECK(!function_literal->is_toplevel());

  // Clone the character stream so both can be accessed independently.
  std::unique_ptr<Utf16CharacterStream> character_stream =
      outer_parse_info->character_stream()->Clone();
  character_stream->Seek(function_literal->start_position());
  info_->set_character_stream(std::move(character_stream));

  // Get preparsed scope data from the function literal.
1019 1020 1021 1022 1023
  if (function_literal->produced_preparse_data()) {
    ZonePreparseData* serialized_data =
        function_literal->produced_preparse_data()->Serialize(info_->zone());
    info_->set_consumed_preparse_data(
        ConsumedPreparseData::For(info_->zone(), serialized_data));
1024 1025 1026
  }
}

1027 1028
BackgroundCompileTask::~BackgroundCompileTask() = default;

1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064
namespace {

// A scope object that ensures a parse info's runtime call stats, stack limit
// and on_background_thread fields is set correctly during worker-thread
// compile, and restores it after going out of scope.
class OffThreadParseInfoScope {
 public:
  OffThreadParseInfoScope(
      ParseInfo* parse_info,
      WorkerThreadRuntimeCallStats* worker_thread_runtime_stats, int stack_size)
      : parse_info_(parse_info),
        original_runtime_call_stats_(parse_info_->runtime_call_stats()),
        original_stack_limit_(parse_info_->stack_limit()),
        worker_thread_scope_(worker_thread_runtime_stats) {
    parse_info_->set_on_background_thread(true);
    parse_info_->set_runtime_call_stats(worker_thread_scope_.Get());
    parse_info_->set_stack_limit(GetCurrentStackPosition() - stack_size * KB);
  }

  ~OffThreadParseInfoScope() {
    parse_info_->set_stack_limit(original_stack_limit_);
    parse_info_->set_runtime_call_stats(original_runtime_call_stats_);
    parse_info_->set_on_background_thread(false);
  }

 private:
  ParseInfo* parse_info_;
  RuntimeCallStats* original_runtime_call_stats_;
  uintptr_t original_stack_limit_;
  WorkerThreadRuntimeCallStatsScope worker_thread_scope_;

  DISALLOW_COPY_AND_ASSIGN(OffThreadParseInfoScope);
};

}  // namespace

1065
void BackgroundCompileTask::Run() {
1066 1067
  DisallowHeapAllocation no_allocation;
  DisallowHandleAllocation no_handles;
1068
  DisallowHeapAccess no_heap_access;
1069

1070 1071 1072 1073 1074 1075 1076 1077
  TimedHistogramScope timer(timer_);
  OffThreadParseInfoScope off_thread_scope(
      info_.get(), worker_thread_runtime_call_stats_, stack_size_);
  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
               "BackgroundCompileTask::Run");
  RuntimeCallTimerScope runtimeTimer(
      info_->runtime_call_stats(),
      RuntimeCallCounterId::kCompileBackgroundCompileTask);
1078

1079
  // Update the character stream's runtime call stats.
1080
  info_->character_stream()->set_runtime_call_stats(
1081
      info_->runtime_call_stats());
1082 1083 1084

  // Parser needs to stay alive for finalizing the parsing on the main
  // thread.
1085 1086
  parser_.reset(new Parser(info_.get()));
  parser_->InitializeEmptyScopeChain(info_.get());
1087

1088 1089
  parser_->ParseOnBackground(info_.get());
  if (info_->literal() != nullptr) {
1090
    // Parsing has succeeded, compile.
1091 1092
    outer_function_job_ = CompileOnBackgroundThread(info_.get(), allocator_,
                                                    &inner_function_jobs_);
1093 1094 1095
  }
}

1096 1097 1098 1099

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

1100
bool Compiler::Analyze(ParseInfo* parse_info) {
1101
  DCHECK_NOT_NULL(parse_info->literal());
1102 1103 1104
  RuntimeCallTimerScope runtimeTimer(
      parse_info->runtime_call_stats(),
      parse_info->on_background_thread()
1105 1106
          ? RuntimeCallCounterId::kCompileBackgroundAnalyse
          : RuntimeCallCounterId::kCompileAnalyse);
1107
  if (!Rewriter::Rewrite(parse_info)) return false;
1108
  if (!DeclarationScope::Analyze(parse_info)) return false;
1109 1110 1111
  return true;
}

1112
bool Compiler::ParseAndAnalyze(ParseInfo* parse_info,
1113 1114
                               Handle<SharedFunctionInfo> shared_info,
                               Isolate* isolate) {
1115
  if (!parsing::ParseAny(parse_info, shared_info, isolate)) {
1116 1117
    return false;
  }
1118
  return Compiler::Analyze(parse_info);
1119 1120
}

1121
bool Compiler::Compile(Handle<SharedFunctionInfo> shared_info,
1122 1123
                       ClearExceptionFlag flag,
                       IsCompiledScope* is_compiled_scope) {
1124 1125
  // We should never reach here if the function is already compiled.
  DCHECK(!shared_info->is_compiled());
1126
  DCHECK(!is_compiled_scope->is_compiled());
1127 1128

  Isolate* isolate = shared_info->GetIsolate();
1129
  DCHECK(AllowCompilation::IsAllowed(isolate));
1130
  DCHECK(ThreadId::Current().Equals(isolate->thread_id()));
1131 1132 1133 1134 1135 1136
  DCHECK(!isolate->has_pending_exception());
  DCHECK(!shared_info->HasBytecodeArray());
  VMState<BYTECODE_COMPILER> state(isolate);
  PostponeInterruptsScope postpone(isolate);
  TimerEventScope<TimerEventCompileCode> compile_timer(isolate);
  RuntimeCallTimerScope runtimeTimer(isolate,
1137
                                     RuntimeCallCounterId::kCompileFunction);
1138 1139 1140
  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.CompileCode");
  AggregatedHistogramTimerScope timer(isolate->counters()->compile_lazy());

1141
  // Set up parse info.
1142
  ParseInfo parse_info(isolate, shared_info);
1143 1144
  parse_info.set_lazy_compile();

1145 1146 1147 1148
  // Check if the compiler dispatcher has shared_info enqueued for compile.
  CompilerDispatcher* dispatcher = isolate->compiler_dispatcher();
  if (dispatcher->IsEnqueued(shared_info)) {
    if (!dispatcher->FinishNow(shared_info)) {
1149
      return FailWithPendingException(isolate, &parse_info, flag);
1150
    }
1151 1152
    *is_compiled_scope = shared_info->is_compiled_scope();
    DCHECK(is_compiled_scope->is_compiled());
1153 1154 1155
    return true;
  }

1156 1157 1158 1159 1160 1161
  if (shared_info->HasUncompiledDataWithPreparseData()) {
    parse_info.set_consumed_preparse_data(ConsumedPreparseData::For(
        isolate,
        handle(
            shared_info->uncompiled_data_with_preparse_data()->preparse_data(),
            isolate)));
1162 1163 1164
  }

  // Parse and update ParseInfo with the results.
1165
  if (!parsing::ParseAny(&parse_info, shared_info, isolate)) {
1166
    return FailWithPendingException(isolate, &parse_info, flag);
1167 1168 1169
  }

  // Generate the unoptimized bytecode or asm-js data.
1170 1171 1172 1173
  UnoptimizedCompilationJobList inner_function_jobs;
  std::unique_ptr<UnoptimizedCompilationJob> outer_function_job(
      GenerateUnoptimizedCode(&parse_info, isolate->allocator(),
                              &inner_function_jobs));
1174
  if (!outer_function_job) {
1175
    return FailWithPendingException(isolate, &parse_info, flag);
1176 1177 1178
  }

  // Internalize ast values onto the heap.
1179
  parse_info.ast_value_factory()->Internalize(isolate);
1180 1181 1182 1183 1184

  // Finalize compilation of the unoptimized bytecode or asm-js data.
  if (!FinalizeUnoptimizedCode(&parse_info, isolate, shared_info,
                               outer_function_job.get(),
                               &inner_function_jobs)) {
1185
    return FailWithPendingException(isolate, &parse_info, flag);
1186 1187 1188
  }

  DCHECK(!isolate->has_pending_exception());
1189 1190
  *is_compiled_scope = shared_info->is_compiled_scope();
  DCHECK(is_compiled_scope->is_compiled());
1191 1192 1193
  return true;
}

1194 1195
bool Compiler::Compile(Handle<JSFunction> function, ClearExceptionFlag flag,
                       IsCompiledScope* is_compiled_scope) {
1196 1197 1198
  // We should never reach here if the function is already compiled or optimized
  DCHECK(!function->is_compiled());
  DCHECK(!function->IsOptimized());
1199 1200
  DCHECK(!function->HasOptimizationMarker());
  DCHECK(!function->HasOptimizedCode());
1201

1202 1203 1204 1205
  // Reset the JSFunction if we are recompiling due to the bytecode having been
  // flushed.
  function->ResetIfBytecodeFlushed();

1206
  Isolate* isolate = function->GetIsolate();
1207
  Handle<SharedFunctionInfo> shared_info = handle(function->shared(), isolate);
1208

1209
  // Ensure shared function info is compiled.
1210 1211 1212 1213 1214 1215
  *is_compiled_scope = shared_info->is_compiled_scope();
  if (!is_compiled_scope->is_compiled() &&
      !Compile(shared_info, flag, is_compiled_scope)) {
    return false;
  }
  DCHECK(is_compiled_scope->is_compiled());
1216
  Handle<Code> code = handle(shared_info->GetCode(), isolate);
1217

1218 1219
  // Allocate FeedbackVector for the JSFunction.
  JSFunction::EnsureFeedbackVector(function);
1220 1221 1222 1223 1224 1225 1226

  // Optimize now if --always-opt is enabled.
  if (FLAG_always_opt && !function->shared()->HasAsmWasmData()) {
    if (FLAG_trace_opt) {
      PrintF("[optimizing ");
      function->ShortPrint();
      PrintF(" because --always-opt]\n");
1227
    }
1228 1229 1230 1231
    Handle<Code> opt_code;
    if (GetOptimizedCode(function, ConcurrencyMode::kNotConcurrent)
            .ToHandle(&opt_code)) {
      code = opt_code;
1232 1233
    }
  }
1234

1235
  // Install code on closure.
1236
  function->set_code(*code);
1237 1238 1239 1240

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

1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281
bool Compiler::FinalizeBackgroundCompileTask(
    BackgroundCompileTask* task, Handle<SharedFunctionInfo> shared_info,
    Isolate* isolate, ClearExceptionFlag flag) {
  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
               "V8.FinalizeBackgroundCompileTask");
  RuntimeCallTimerScope runtimeTimer(
      isolate, RuntimeCallCounterId::kCompileFinalizeBackgroundCompileTask);
  HandleScope scope(isolate);
  ParseInfo* parse_info = task->info();
  DCHECK(!parse_info->is_toplevel());
  DCHECK(!shared_info->is_compiled());

  Handle<Script> script(Script::cast(shared_info->script()), isolate);
  parse_info->set_script(script);

  task->parser()->UpdateStatistics(isolate, script);
  task->parser()->HandleSourceURLComments(isolate, script);

  if (parse_info->literal() == nullptr || !task->outer_function_job()) {
    // Parsing or compile failed on background thread - report error messages.
    return FailWithPendingException(isolate, parse_info, flag);
  }

  // Parsing has succeeded - finalize compilation.
  parse_info->ast_value_factory()->Internalize(isolate);
  if (!FinalizeUnoptimizedCode(parse_info, isolate, shared_info,
                               task->outer_function_job(),
                               task->inner_function_jobs())) {
    // Finalization failed - throw an exception.
    return FailWithPendingException(isolate, parse_info, flag);
  }

  DCHECK(!isolate->has_pending_exception());
  DCHECK(shared_info->is_compiled());
  return true;
}

1282 1283
bool Compiler::CompileOptimized(Handle<JSFunction> function,
                                ConcurrencyMode mode) {
1284 1285 1286 1287 1288
  if (function->IsOptimized()) return true;
  Isolate* isolate = function->GetIsolate();
  DCHECK(AllowCompilation::IsAllowed(isolate));

  // Start a compilation.
1289
  Handle<Code> code;
1290
  if (!GetOptimizedCode(function, mode).ToHandle(&code)) {
1291 1292
    // Optimization failed, get unoptimized code. Unoptimized code must exist
    // already if we are optimizing.
1293
    DCHECK(!isolate->has_pending_exception());
1294
    DCHECK(function->shared()->is_compiled());
1295 1296
    DCHECK(function->shared()->IsInterpreted());
    code = BUILTIN_CODE(isolate, InterpreterEntryTrampoline);
1297 1298
  }

1299
  // Install code on closure.
1300
  function->set_code(*code);
1301 1302 1303 1304 1305

  // Check postconditions on success.
  DCHECK(!isolate->has_pending_exception());
  DCHECK(function->shared()->is_compiled());
  DCHECK(function->is_compiled());
1306 1307 1308 1309 1310 1311
  DCHECK_IMPLIES(function->HasOptimizationMarker(),
                 function->IsInOptimizationQueue());
  DCHECK_IMPLIES(function->HasOptimizationMarker(),
                 function->ChecksOptimizationMarker());
  DCHECK_IMPLIES(function->IsInOptimizationQueue(),
                 mode == ConcurrencyMode::kConcurrent);
1312 1313 1314
  return true;
}

1315 1316
MaybeHandle<SharedFunctionInfo> Compiler::CompileForLiveEdit(
    ParseInfo* parse_info, Isolate* isolate) {
1317 1318
  IsCompiledScope is_compiled_scope;
  return CompileToplevel(parse_info, isolate, &is_compiled_scope);
1319 1320
}

1321
MaybeHandle<JSFunction> Compiler::GetFunctionFromEval(
1322
    Handle<String> source, Handle<SharedFunctionInfo> outer_info,
1323
    Handle<Context> context, LanguageMode language_mode,
1324
    ParseRestriction restriction, int parameters_end_pos,
1325
    int eval_scope_position, int eval_position) {
1326
  Isolate* isolate = context->GetIsolate();
1327 1328 1329 1330
  int source_length = source->length();
  isolate->counters()->total_eval_size()->Increment(source_length);
  isolate->counters()->total_compile_size()->Increment(source_length);

1331 1332 1333 1334 1335 1336 1337 1338 1339
  // The cache lookup key needs to be aware of the separation between the
  // parameters and the body to prevent this valid invocation:
  //   Function("", "function anonymous(\n/**/) {\n}");
  // from adding an entry that falsely approves this invalid invocation:
  //   Function("\n/**/) {\nfunction anonymous(", "}");
  // The actual eval_scope_position for indirect eval and CreateDynamicFunction
  // is unused (just 0), which means it's an available field to use to indicate
  // this separation. But to make sure we're not causing other false hits, we
  // negate the scope position.
1340
  if (restriction == ONLY_SINGLE_FUNCTION_LITERAL &&
1341 1342 1343
      parameters_end_pos != kNoSourcePosition) {
    // use the parameters_end_pos as the eval_scope_position in the eval cache.
    DCHECK_EQ(eval_scope_position, 0);
1344
    eval_scope_position = -parameters_end_pos;
1345
  }
1346
  CompilationCache* compilation_cache = isolate->compilation_cache();
1347
  InfoCellPair eval_result = compilation_cache->LookupEval(
1348
      source, outer_info, context, language_mode, eval_scope_position);
1349 1350 1351
  Handle<FeedbackCell> feedback_cell;
  if (eval_result.has_feedback_cell()) {
    feedback_cell = handle(eval_result.feedback_cell(), isolate);
1352
  }
1353

1354
  Handle<SharedFunctionInfo> shared_info;
1355
  Handle<Script> script;
1356
  IsCompiledScope is_compiled_scope;
1357
  bool allow_eval_cache;
1358 1359 1360
  if (eval_result.has_shared()) {
    shared_info = Handle<SharedFunctionInfo>(eval_result.shared(), isolate);
    script = Handle<Script>(Script::cast(shared_info->script()), isolate);
1361
    is_compiled_scope = shared_info->is_compiled_scope();
1362
    allow_eval_cache = true;
1363
  } else {
1364
    ParseInfo parse_info(isolate);
1365 1366
    script = parse_info.CreateScript(
        isolate, source, OriginOptionsForEval(outer_info->script()));
1367
    script->set_compilation_type(Script::COMPILATION_TYPE_EVAL);
1368 1369 1370 1371 1372
    script->set_eval_from_shared(*outer_info);
    if (eval_position == kNoSourcePosition) {
      // If the position is missing, attempt to get the code offset by
      // walking the stack. Do not translate the code offset into source
      // position, but store it as negative value for lazy translation.
1373
      StackTraceFrameIterator it(isolate);
1374 1375 1376 1377
      if (!it.done() && it.is_javascript()) {
        FrameSummary summary = FrameSummary::GetTop(it.javascript_frame());
        script->set_eval_from_shared(
            summary.AsJavaScript().function()->shared());
1378
        script->set_origin_options(OriginOptionsForEval(*summary.script()));
1379 1380 1381 1382 1383 1384
        eval_position = -summary.code_offset();
      } else {
        eval_position = 0;
      }
    }
    script->set_eval_from_position(eval_position);
1385

1386 1387 1388
    parse_info.set_eval();
    parse_info.set_language_mode(language_mode);
    parse_info.set_parse_restriction(restriction);
1389
    parse_info.set_parameters_end_pos(parameters_end_pos);
1390
    if (!context->IsNativeContext()) {
1391
      parse_info.set_outer_scope_info(handle(context->scope_info(), isolate));
1392
    }
1393
    DCHECK(!parse_info.is_module());
1394

1395 1396
    if (!CompileToplevel(&parse_info, isolate, &is_compiled_scope)
             .ToHandle(&shared_info)) {
1397
      return MaybeHandle<JSFunction>();
1398
    }
1399
    allow_eval_cache = parse_info.allow_eval_cache();
1400 1401 1402 1403 1404 1405 1406
  }

  // 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()) {
1407
    if (eval_result.has_feedback_cell()) {
1408
      result = isolate->factory()->NewFunctionFromSharedFunctionInfo(
1409
          shared_info, context, feedback_cell, NOT_TENURED);
1410
    } else {
1411
      result = isolate->factory()->NewFunctionFromSharedFunctionInfo(
1412
          shared_info, context, NOT_TENURED);
1413
      JSFunction::EnsureFeedbackVector(result);
1414 1415
      if (allow_eval_cache) {
        // Make sure to cache this result.
1416
        Handle<FeedbackCell> new_feedback_cell(result->raw_feedback_cell(),
1417
                                               isolate);
1418
        compilation_cache->PutEval(source, outer_info, context, shared_info,
1419
                                   new_feedback_cell, eval_scope_position);
1420
      }
1421
    }
1422 1423 1424
  } else {
    result = isolate->factory()->NewFunctionFromSharedFunctionInfo(
        shared_info, context, NOT_TENURED);
1425
    JSFunction::EnsureFeedbackVector(result);
1426 1427 1428
    if (allow_eval_cache) {
      // Add the SharedFunctionInfo and the LiteralsArray to the eval cache if
      // we didn't retrieve from there.
1429 1430
      Handle<FeedbackCell> new_feedback_cell(result->raw_feedback_cell(),
                                             isolate);
1431
      compilation_cache->PutEval(source, outer_info, context, shared_info,
1432
                                 new_feedback_cell, eval_scope_position);
1433
    }
1434
  }
1435
  DCHECK(is_compiled_scope.is_compiled());
1436

1437
  return result;
1438 1439
}

1440

1441 1442 1443
bool Compiler::CodeGenerationFromStringsAllowed(Isolate* isolate,
                                                Handle<Context> context,
                                                Handle<String> source) {
1444 1445 1446 1447
  DCHECK(context->allow_code_gen_from_strings()->IsFalse(isolate));
  // Check with callback if set.
  AllowCodeGenerationFromStringsCallback callback =
      isolate->allow_code_gen_callback();
1448
  if (callback == nullptr) {
1449 1450 1451 1452 1453
    // No callback set and code generation disallowed.
    return false;
  } else {
    // Callback set. Let it decide if code generation is allowed.
    VMState<EXTERNAL> state(isolate);
1454
    return callback(v8::Utils::ToLocal(context), v8::Utils::ToLocal(source));
1455 1456 1457 1458 1459
  }
}

MaybeHandle<JSFunction> Compiler::GetFunctionFromString(
    Handle<Context> context, Handle<String> source,
1460
    ParseRestriction restriction, int parameters_end_pos) {
1461 1462 1463 1464 1465 1466
  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) &&
1467
      !CodeGenerationFromStringsAllowed(isolate, native_context, source)) {
1468 1469 1470 1471 1472 1473 1474 1475 1476 1477
    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;
1478
  Handle<SharedFunctionInfo> outer_info(
1479
      native_context->empty_function()->shared(), isolate);
1480 1481 1482
  return Compiler::GetFunctionFromEval(
      source, outer_info, native_context, LanguageMode::kSloppy, restriction,
      parameters_end_pos, eval_scope_position, eval_position);
1483 1484
}

1485 1486 1487 1488
namespace {

struct ScriptCompileTimerScope {
 public:
1489 1490 1491
  // TODO(leszeks): There are too many blink-specific entries in this enum,
  // figure out a way to push produce/hit-isolate-cache/consume/consume-failed
  // back up the API and log them in blink instead.
1492 1493
  enum class CacheBehaviour {
    kProduceCodeCache,
1494
    kHitIsolateCacheWhenNoCache,
1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505
    kConsumeCodeCache,
    kConsumeCodeCacheFailed,
    kNoCacheBecauseInlineScript,
    kNoCacheBecauseScriptTooSmall,
    kNoCacheBecauseCacheTooCold,
    kNoCacheNoReason,
    kNoCacheBecauseNoResource,
    kNoCacheBecauseInspector,
    kNoCacheBecauseCachingDisabled,
    kNoCacheBecauseModule,
    kNoCacheBecauseStreamingSource,
1506
    kNoCacheBecauseV8Extension,
1507 1508
    kHitIsolateCacheWhenProduceCodeCache,
    kHitIsolateCacheWhenConsumeCodeCache,
1509 1510 1511
    kNoCacheBecauseExtensionModule,
    kNoCacheBecausePacScript,
    kNoCacheBecauseInDocumentWrite,
1512
    kNoCacheBecauseResourceWithNoCacheHandler,
1513
    kHitIsolateCacheWhenStreamingSource,
1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568
    kCount
  };

  explicit ScriptCompileTimerScope(
      Isolate* isolate, ScriptCompiler::NoCacheReason no_cache_reason)
      : isolate_(isolate),
        all_scripts_histogram_scope_(isolate->counters()->compile_script(),
                                     true),
        no_cache_reason_(no_cache_reason),
        hit_isolate_cache_(false),
        producing_code_cache_(false),
        consuming_code_cache_(false),
        consuming_code_cache_failed_(false) {}

  ~ScriptCompileTimerScope() {
    CacheBehaviour cache_behaviour = GetCacheBehaviour();

    Histogram* cache_behaviour_histogram =
        isolate_->counters()->compile_script_cache_behaviour();
    // Sanity check that the histogram has exactly one bin per enum entry.
    DCHECK_EQ(0, cache_behaviour_histogram->min());
    DCHECK_EQ(static_cast<int>(CacheBehaviour::kCount),
              cache_behaviour_histogram->max() + 1);
    DCHECK_EQ(static_cast<int>(CacheBehaviour::kCount),
              cache_behaviour_histogram->num_buckets());
    cache_behaviour_histogram->AddSample(static_cast<int>(cache_behaviour));

    histogram_scope_.set_histogram(
        GetCacheBehaviourTimedHistogram(cache_behaviour));
  }

  void set_hit_isolate_cache() { hit_isolate_cache_ = true; }

  void set_producing_code_cache() { producing_code_cache_ = true; }

  void set_consuming_code_cache() { consuming_code_cache_ = true; }

  void set_consuming_code_cache_failed() {
    consuming_code_cache_failed_ = true;
  }

 private:
  Isolate* isolate_;
  LazyTimedHistogramScope histogram_scope_;
  // TODO(leszeks): This timer is the sum of the other times, consider removing
  // it to save space.
  HistogramTimerScope all_scripts_histogram_scope_;
  ScriptCompiler::NoCacheReason no_cache_reason_;
  bool hit_isolate_cache_;
  bool producing_code_cache_;
  bool consuming_code_cache_;
  bool consuming_code_cache_failed_;

  CacheBehaviour GetCacheBehaviour() {
    if (producing_code_cache_) {
1569 1570 1571 1572 1573
      if (hit_isolate_cache_) {
        return CacheBehaviour::kHitIsolateCacheWhenProduceCodeCache;
      } else {
        return CacheBehaviour::kProduceCodeCache;
      }
1574 1575 1576
    }

    if (consuming_code_cache_) {
1577 1578 1579
      if (hit_isolate_cache_) {
        return CacheBehaviour::kHitIsolateCacheWhenConsumeCodeCache;
      } else if (consuming_code_cache_failed_) {
1580 1581 1582 1583 1584
        return CacheBehaviour::kConsumeCodeCacheFailed;
      }
      return CacheBehaviour::kConsumeCodeCache;
    }

1585
    if (hit_isolate_cache_) {
1586 1587 1588
      if (no_cache_reason_ == ScriptCompiler::kNoCacheBecauseStreamingSource) {
        return CacheBehaviour::kHitIsolateCacheWhenStreamingSource;
      }
1589 1590 1591
      return CacheBehaviour::kHitIsolateCacheWhenNoCache;
    }

1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610
    switch (no_cache_reason_) {
      case ScriptCompiler::kNoCacheBecauseInlineScript:
        return CacheBehaviour::kNoCacheBecauseInlineScript;
      case ScriptCompiler::kNoCacheBecauseScriptTooSmall:
        return CacheBehaviour::kNoCacheBecauseScriptTooSmall;
      case ScriptCompiler::kNoCacheBecauseCacheTooCold:
        return CacheBehaviour::kNoCacheBecauseCacheTooCold;
      case ScriptCompiler::kNoCacheNoReason:
        return CacheBehaviour::kNoCacheNoReason;
      case ScriptCompiler::kNoCacheBecauseNoResource:
        return CacheBehaviour::kNoCacheBecauseNoResource;
      case ScriptCompiler::kNoCacheBecauseInspector:
        return CacheBehaviour::kNoCacheBecauseInspector;
      case ScriptCompiler::kNoCacheBecauseCachingDisabled:
        return CacheBehaviour::kNoCacheBecauseCachingDisabled;
      case ScriptCompiler::kNoCacheBecauseModule:
        return CacheBehaviour::kNoCacheBecauseModule;
      case ScriptCompiler::kNoCacheBecauseStreamingSource:
        return CacheBehaviour::kNoCacheBecauseStreamingSource;
1611 1612 1613 1614 1615 1616 1617 1618
      case ScriptCompiler::kNoCacheBecauseV8Extension:
        return CacheBehaviour::kNoCacheBecauseV8Extension;
      case ScriptCompiler::kNoCacheBecauseExtensionModule:
        return CacheBehaviour::kNoCacheBecauseExtensionModule;
      case ScriptCompiler::kNoCacheBecausePacScript:
        return CacheBehaviour::kNoCacheBecausePacScript;
      case ScriptCompiler::kNoCacheBecauseInDocumentWrite:
        return CacheBehaviour::kNoCacheBecauseInDocumentWrite;
1619 1620
      case ScriptCompiler::kNoCacheBecauseResourceWithNoCacheHandler:
        return CacheBehaviour::kNoCacheBecauseResourceWithNoCacheHandler;
1621 1622 1623 1624 1625 1626 1627
      case ScriptCompiler::kNoCacheBecauseDeferredProduceCodeCache: {
        if (hit_isolate_cache_) {
          return CacheBehaviour::kHitIsolateCacheWhenProduceCodeCache;
        } else {
          return CacheBehaviour::kProduceCodeCache;
        }
      }
1628 1629 1630 1631 1632 1633 1634 1635
    }
    UNREACHABLE();
  }

  TimedHistogram* GetCacheBehaviourTimedHistogram(
      CacheBehaviour cache_behaviour) {
    switch (cache_behaviour) {
      case CacheBehaviour::kProduceCodeCache:
1636 1637 1638
      // Even if we hit the isolate's compilation cache, we currently recompile
      // when we want to produce the code cache.
      case CacheBehaviour::kHitIsolateCacheWhenProduceCodeCache:
1639
        return isolate_->counters()->compile_script_with_produce_cache();
1640 1641
      case CacheBehaviour::kHitIsolateCacheWhenNoCache:
      case CacheBehaviour::kHitIsolateCacheWhenConsumeCodeCache:
1642
      case CacheBehaviour::kHitIsolateCacheWhenStreamingSource:
1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670
        return isolate_->counters()->compile_script_with_isolate_cache_hit();
      case CacheBehaviour::kConsumeCodeCacheFailed:
        return isolate_->counters()->compile_script_consume_failed();
      case CacheBehaviour::kConsumeCodeCache:
        return isolate_->counters()->compile_script_with_consume_cache();

      case CacheBehaviour::kNoCacheBecauseInlineScript:
        return isolate_->counters()
            ->compile_script_no_cache_because_inline_script();
      case CacheBehaviour::kNoCacheBecauseScriptTooSmall:
        return isolate_->counters()
            ->compile_script_no_cache_because_script_too_small();
      case CacheBehaviour::kNoCacheBecauseCacheTooCold:
        return isolate_->counters()
            ->compile_script_no_cache_because_cache_too_cold();

      // Aggregate all the other "no cache" counters into a single histogram, to
      // save space.
      case CacheBehaviour::kNoCacheNoReason:
      case CacheBehaviour::kNoCacheBecauseNoResource:
      case CacheBehaviour::kNoCacheBecauseInspector:
      case CacheBehaviour::kNoCacheBecauseCachingDisabled:
      // TODO(leszeks): Consider counting separately once modules are more
      // common.
      case CacheBehaviour::kNoCacheBecauseModule:
      // TODO(leszeks): Count separately or remove entirely once we have
      // background compilation.
      case CacheBehaviour::kNoCacheBecauseStreamingSource:
1671 1672 1673 1674
      case CacheBehaviour::kNoCacheBecauseV8Extension:
      case CacheBehaviour::kNoCacheBecauseExtensionModule:
      case CacheBehaviour::kNoCacheBecausePacScript:
      case CacheBehaviour::kNoCacheBecauseInDocumentWrite:
1675
      case CacheBehaviour::kNoCacheBecauseResourceWithNoCacheHandler:
1676 1677 1678 1679 1680 1681 1682 1683 1684
        return isolate_->counters()->compile_script_no_cache_other();

      case CacheBehaviour::kCount:
        UNREACHABLE();
    }
    UNREACHABLE();
  }
};

1685 1686
Handle<Script> NewScript(Isolate* isolate, ParseInfo* parse_info,
                         Handle<String> source,
1687 1688 1689 1690
                         Compiler::ScriptDetails script_details,
                         ScriptOriginOptions origin_options,
                         NativesFlag natives) {
  // Create a script object describing the script to be compiled.
1691 1692
  Handle<Script> script =
      parse_info->CreateScript(isolate, source, origin_options, natives);
1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706
  Handle<Object> script_name;
  if (script_details.name_obj.ToHandle(&script_name)) {
    script->set_name(*script_name);
    script->set_line_offset(script_details.line_offset);
    script->set_column_offset(script_details.column_offset);
  }
  Handle<Object> source_map_url;
  if (script_details.source_map_url.ToHandle(&source_map_url)) {
    script->set_source_mapping_url(*source_map_url);
  }
  Handle<FixedArray> host_defined_options;
  if (script_details.host_defined_options.ToHandle(&host_defined_options)) {
    script->set_host_defined_options(*host_defined_options);
  }
1707
  LOG(isolate, ScriptDetails(*script));
1708 1709 1710
  return script;
}

1711 1712
}  // namespace

1713
MaybeHandle<SharedFunctionInfo> Compiler::GetSharedFunctionInfoForScript(
1714 1715
    Isolate* isolate, Handle<String> source,
    const Compiler::ScriptDetails& script_details,
1716
    ScriptOriginOptions origin_options, v8::Extension* extension,
1717
    ScriptData* cached_data, ScriptCompiler::CompileOptions compile_options,
1718
    ScriptCompiler::NoCacheReason no_cache_reason, NativesFlag natives) {
1719 1720
  ScriptCompileTimerScope compile_timer(isolate, no_cache_reason);

1721 1722
  if (compile_options == ScriptCompiler::kNoCompileOptions ||
      compile_options == ScriptCompiler::kEagerCompile) {
1723
    DCHECK_NULL(cached_data);
1724
  } else {
1725
    DCHECK(compile_options == ScriptCompiler::kConsumeCodeCache);
1726
    DCHECK(cached_data);
1727
    DCHECK_NULL(extension);
1728
  }
1729 1730 1731 1732
  int source_length = source->length();
  isolate->counters()->total_load_size()->Increment(source_length);
  isolate->counters()->total_compile_size()->Increment(source_length);

1733
  LanguageMode language_mode = construct_language_mode(FLAG_use_strict);
1734 1735 1736
  CompilationCache* compilation_cache = isolate->compilation_cache();

  // Do a lookup in the compilation cache but not for extensions.
1737
  MaybeHandle<SharedFunctionInfo> maybe_result;
1738
  IsCompiledScope is_compiled_scope;
1739
  if (extension == nullptr) {
1740
    bool can_consume_code_cache =
1741
        compile_options == ScriptCompiler::kConsumeCodeCache;
1742 1743 1744 1745
    if (can_consume_code_cache) {
      compile_timer.set_consuming_code_cache();
    }

1746
    // First check per-isolate compilation cache.
1747
    maybe_result = compilation_cache->LookupScript(
1748 1749 1750
        source, script_details.name_obj, script_details.line_offset,
        script_details.column_offset, origin_options, isolate->native_context(),
        language_mode);
1751 1752 1753
    if (!maybe_result.is_null()) {
      compile_timer.set_hit_isolate_cache();
    } else if (can_consume_code_cache) {
1754
      compile_timer.set_consuming_code_cache();
1755
      // Then check cached code provided by embedder.
1756
      HistogramTimerScope timer(isolate->counters()->compile_deserialize());
1757 1758
      RuntimeCallTimerScope runtimeTimer(
          isolate, RuntimeCallCounterId::kCompileDeserialize);
1759 1760
      TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
                   "V8.CompileDeserialize");
1761
      Handle<SharedFunctionInfo> inner_result;
1762 1763
      if (CodeSerializer::Deserialize(isolate, cached_data, source,
                                      origin_options)
1764
              .ToHandle(&inner_result)) {
1765
        // Promote to per-isolate compilation cache.
1766 1767
        is_compiled_scope = inner_result->is_compiled_scope();
        DCHECK(is_compiled_scope.is_compiled());
1768
        compilation_cache->PutScript(source, isolate->native_context(),
1769
                                     language_mode, inner_result);
1770
        Handle<Script> script(Script::cast(inner_result->script()), isolate);
1771 1772 1773 1774
        maybe_result = inner_result;
      } else {
        // Deserializer failed. Fall through to compile.
        compile_timer.set_consuming_code_cache_failed();
1775
      }
1776
    }
1777 1778
  }

1779
  if (maybe_result.is_null()) {
1780
    ParseInfo parse_info(isolate);
1781
    // No cache entry found compile the script.
1782 1783
    NewScript(isolate, &parse_info, source, script_details, origin_options,
              natives);
1784

1785
    // Compile the function and add it to the isolate cache.
1786
    if (origin_options.IsModule()) parse_info.set_module();
1787
    parse_info.set_extension(extension);
1788
    parse_info.set_eager(compile_options == ScriptCompiler::kEagerCompile);
1789

1790
    parse_info.set_language_mode(
1791
        stricter_language_mode(parse_info.language_mode(), language_mode));
1792
    maybe_result = CompileToplevel(&parse_info, isolate, &is_compiled_scope);
1793
    Handle<SharedFunctionInfo> result;
1794
    if (extension == nullptr && maybe_result.ToHandle(&result)) {
1795
      DCHECK(is_compiled_scope.is_compiled());
1796
      compilation_cache->PutScript(source, isolate->native_context(),
1797
                                   language_mode, result);
1798 1799 1800
    } else if (maybe_result.is_null() && natives != EXTENSION_CODE &&
               natives != NATIVES_CODE) {
      isolate->ReportPendingMessages();
1801
    }
1802
  }
1803

1804
  return maybe_result;
1805 1806
}

1807 1808 1809 1810 1811 1812
MaybeHandle<JSFunction> Compiler::GetWrappedFunction(
    Handle<String> source, Handle<FixedArray> arguments,
    Handle<Context> context, const Compiler::ScriptDetails& script_details,
    ScriptOriginOptions origin_options, ScriptData* cached_data,
    v8::ScriptCompiler::CompileOptions compile_options,
    v8::ScriptCompiler::NoCacheReason no_cache_reason) {
1813
  Isolate* isolate = context->GetIsolate();
1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830
  ScriptCompileTimerScope compile_timer(isolate, no_cache_reason);

  if (compile_options == ScriptCompiler::kNoCompileOptions ||
      compile_options == ScriptCompiler::kEagerCompile) {
    DCHECK_NULL(cached_data);
  } else {
    DCHECK(compile_options == ScriptCompiler::kConsumeCodeCache);
    DCHECK(cached_data);
  }

  int source_length = source->length();
  isolate->counters()->total_compile_size()->Increment(source_length);

  LanguageMode language_mode = construct_language_mode(FLAG_use_strict);

  MaybeHandle<SharedFunctionInfo> maybe_result;
  bool can_consume_code_cache =
1831
      compile_options == ScriptCompiler::kConsumeCodeCache;
1832 1833 1834 1835 1836 1837 1838 1839
  if (can_consume_code_cache) {
    compile_timer.set_consuming_code_cache();
    // Then check cached code provided by embedder.
    HistogramTimerScope timer(isolate->counters()->compile_deserialize());
    RuntimeCallTimerScope runtimeTimer(
        isolate, RuntimeCallCounterId::kCompileDeserialize);
    TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
                 "V8.CompileDeserialize");
1840 1841
    maybe_result = CodeSerializer::Deserialize(isolate, cached_data, source,
                                               origin_options);
1842 1843 1844 1845 1846 1847 1848 1849
    if (maybe_result.is_null()) {
      // Deserializer failed. Fall through to compile.
      compile_timer.set_consuming_code_cache_failed();
    }
  }

  Handle<SharedFunctionInfo> wrapped;
  Handle<Script> script;
1850
  IsCompiledScope is_compiled_scope;
1851
  if (!maybe_result.ToHandle(&wrapped)) {
1852 1853 1854
    ParseInfo parse_info(isolate);
    script = NewScript(isolate, &parse_info, source, script_details,
                       origin_options, NOT_NATIVES_CODE);
1855 1856 1857 1858 1859 1860
    script->set_wrapped_arguments(*arguments);

    parse_info.set_eval();  // Use an eval scope as declaration scope.
    parse_info.set_wrapped_as_function();
    // parse_info.set_eager(compile_options == ScriptCompiler::kEagerCompile);
    if (!context->IsNativeContext()) {
1861
      parse_info.set_outer_scope_info(handle(context->scope_info(), isolate));
1862 1863 1864 1865 1866
    }
    parse_info.set_language_mode(
        stricter_language_mode(parse_info.language_mode(), language_mode));

    Handle<SharedFunctionInfo> top_level;
1867
    maybe_result = CompileToplevel(&parse_info, isolate, &is_compiled_scope);
1868 1869 1870
    if (maybe_result.is_null()) isolate->ReportPendingMessages();
    ASSIGN_RETURN_ON_EXCEPTION(isolate, top_level, maybe_result, JSFunction);

1871
    SharedFunctionInfo::ScriptIterator infos(isolate, *script);
1872 1873
    for (SharedFunctionInfo info = infos.Next(); !info.is_null();
         info = infos.Next()) {
1874 1875 1876 1877 1878 1879 1880
      if (info->is_wrapped()) {
        wrapped = Handle<SharedFunctionInfo>(info, isolate);
        break;
      }
    }
    DCHECK(!wrapped.is_null());
  } else {
1881
    is_compiled_scope = wrapped->is_compiled_scope();
1882 1883
    script = Handle<Script>(Script::cast(wrapped->script()), isolate);
  }
1884
  DCHECK(is_compiled_scope.is_compiled());
1885

1886
  return isolate->factory()->NewFunctionFromSharedFunctionInfo(wrapped, context,
1887
                                                               NOT_TENURED);
1888 1889
}

1890 1891
MaybeHandle<SharedFunctionInfo>
Compiler::GetSharedFunctionInfoForStreamedScript(
1892 1893 1894
    Isolate* isolate, Handle<String> source,
    const ScriptDetails& script_details, ScriptOriginOptions origin_options,
    ScriptStreamingData* streaming_data) {
1895 1896
  ScriptCompileTimerScope compile_timer(
      isolate, ScriptCompiler::kNoCacheBecauseStreamingSource);
1897 1898
  PostponeInterruptsScope postpone(isolate);

1899
  int source_length = source->length();
1900 1901 1902
  isolate->counters()->total_load_size()->Increment(source_length);
  isolate->counters()->total_compile_size()->Increment(source_length);

1903 1904 1905
  BackgroundCompileTask* task = streaming_data->task.get();
  ParseInfo* parse_info = task->info();
  DCHECK(parse_info->is_toplevel());
1906 1907 1908 1909 1910 1911 1912 1913 1914 1915
  // Check if compile cache already holds the SFI, if so no need to finalize
  // the code compiled on the background thread.
  CompilationCache* compilation_cache = isolate->compilation_cache();
  MaybeHandle<SharedFunctionInfo> maybe_result =
      compilation_cache->LookupScript(
          source, script_details.name_obj, script_details.line_offset,
          script_details.column_offset, origin_options,
          isolate->native_context(), parse_info->language_mode());
  if (!maybe_result.is_null()) {
    compile_timer.set_hit_isolate_cache();
1916
  }
1917

1918 1919 1920
  if (maybe_result.is_null()) {
    // No cache entry found, finalize compilation of the script and add it to
    // the isolate cache.
1921 1922 1923
    Handle<Script> script =
        NewScript(isolate, parse_info, source, script_details, origin_options,
                  NOT_NATIVES_CODE);
1924 1925
    task->parser()->UpdateStatistics(isolate, script);
    task->parser()->HandleSourceURLComments(isolate, script);
1926

1927
    if (parse_info->literal() == nullptr || !task->outer_function_job()) {
1928
      // Parsing has failed - report error messages.
1929 1930
      FailWithPendingException(isolate, parse_info,
                               Compiler::ClearExceptionFlag::KEEP_EXCEPTION);
1931
    } else {
1932
      // Parsing has succeeded - finalize compilation.
1933 1934 1935 1936 1937
      maybe_result =
          FinalizeTopLevel(parse_info, isolate, task->outer_function_job(),
                           task->inner_function_jobs());
      if (maybe_result.is_null()) {
        // Finalization failed - throw an exception.
1938 1939
        FailWithPendingException(isolate, parse_info,
                                 Compiler::ClearExceptionFlag::KEEP_EXCEPTION);
1940 1941 1942 1943 1944 1945 1946 1947
      }
    }

    // Add compiled code to the isolate cache.
    Handle<SharedFunctionInfo> result;
    if (maybe_result.ToHandle(&result)) {
      compilation_cache->PutScript(source, isolate->native_context(),
                                   parse_info->language_mode(), result);
1948
    }
1949
  }
1950

1951
  streaming_data->Release();
1952
  return maybe_result;
1953 1954
}

1955
Handle<SharedFunctionInfo> Compiler::GetSharedFunctionInfo(
1956
    FunctionLiteral* literal, Handle<Script> script, Isolate* isolate) {
1957
  // Precondition: code has been parsed and scopes have been analyzed.
1958
  MaybeHandle<SharedFunctionInfo> maybe_existing;
1959 1960

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

1963
  // If we found an existing shared function info, return it.
1964
  Handle<SharedFunctionInfo> existing;
1965
  if (maybe_existing.ToHandle(&existing)) return existing;
1966

1967 1968
  // Allocate a shared function info object which will be compiled lazily.
  Handle<SharedFunctionInfo> result =
1969 1970
      isolate->factory()->NewSharedFunctionInfoForLiteral(literal, script,
                                                          false);
1971
  return result;
1972 1973
}

1974
MaybeHandle<Code> Compiler::GetOptimizedCodeForOSR(Handle<JSFunction> function,
1975
                                                   BailoutId osr_offset,
1976
                                                   JavaScriptFrame* osr_frame) {
1977
  DCHECK(!osr_offset.IsNone());
1978
  DCHECK_NOT_NULL(osr_frame);
1979
  return GetOptimizedCode(function, ConcurrencyMode::kNotConcurrent, osr_offset,
1980
                          osr_frame);
1981 1982
}

1983 1984
bool Compiler::FinalizeOptimizedCompilationJob(OptimizedCompilationJob* job,
                                               Isolate* isolate) {
1985
  VMState<COMPILER> state(isolate);
1986
  // Take ownership of compilation job.  Deleting job also tears down the zone.
1987 1988
  std::unique_ptr<OptimizedCompilationJob> job_scope(job);
  OptimizedCompilationInfo* compilation_info = job->compilation_info();
1989

1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038
  TimerEventScope<TimerEventRecompileSynchronous> timer(isolate);
  RuntimeCallTimerScope runtimeTimer(
      isolate, RuntimeCallCounterId::kRecompileSynchronous);
  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
               "V8.RecompileSynchronous");

  Handle<SharedFunctionInfo> shared = compilation_info->shared_info();

  // Reset profiler ticks, function is no longer considered hot.
  compilation_info->closure()->feedback_vector()->set_profiler_ticks(0);

  DCHECK(!shared->HasBreakInfo());

  // 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(BailoutReason::kOptimizationDisabled);
    } else if (job->FinalizeJob(isolate) == CompilationJob::SUCCEEDED) {
      job->RecordCompilationStats();
      job->RecordFunctionCompilation(CodeEventListener::LAZY_COMPILE_TAG,
                                     isolate);
      InsertCodeIntoOptimizedCodeCache(compilation_info);
      if (FLAG_trace_opt) {
        PrintF("[completed optimizing ");
        compilation_info->closure()->ShortPrint();
        PrintF("]\n");
      }
      compilation_info->closure()->set_code(*compilation_info->code());
      return CompilationJob::SUCCEEDED;
    }
  }

  DCHECK_EQ(job->state(), CompilationJob::State::kFailed);
  if (FLAG_trace_opt) {
    PrintF("[aborted optimizing ");
    compilation_info->closure()->ShortPrint();
    PrintF(" because: %s]\n",
           GetBailoutReason(compilation_info->bailout_reason()));
  }
  compilation_info->closure()->set_code(shared->GetCode());
  // Clear the InOptimizationQueue marker, if it exists.
  if (compilation_info->closure()->IsInOptimizationQueue()) {
    compilation_info->closure()->ClearOptimizationMarker();
  }
  return CompilationJob::FAILED;
2039 2040
}

2041 2042
void Compiler::PostInstantiation(Handle<JSFunction> function,
                                 PretenureFlag pretenure) {
2043 2044 2045
  Isolate* isolate = function->GetIsolate();
  Handle<SharedFunctionInfo> shared(function->shared(), isolate);
  IsCompiledScope is_compiled_scope(shared->is_compiled_scope());
2046

2047 2048 2049
  // If code is compiled to bytecode (i.e., isn't asm.js), then allocate a
  // feedback and check for optimized code.
  if (is_compiled_scope.is_compiled() && shared->HasBytecodeArray()) {
2050
    JSFunction::EnsureFeedbackVector(function);
2051

2052 2053 2054
    Code code = function->has_feedback_vector()
                    ? function->feedback_vector()->optimized_code()
                    : Code();
2055
    if (!code.is_null()) {
2056 2057 2058
      // Caching of optimized code enabled and optimized code found.
      DCHECK(!code->marked_for_deoptimization());
      DCHECK(function->shared()->is_compiled());
2059
      function->set_code(code);
2060
    }
2061 2062 2063 2064 2065 2066

    if (FLAG_always_opt && shared->allows_lazy_compilation() &&
        !shared->optimization_disabled() && !function->IsOptimized() &&
        !function->HasOptimizedCode()) {
      function->MarkForOptimization(ConcurrencyMode::kNotConcurrent);
    }
2067
  }
2068 2069 2070

  if (shared->is_toplevel() || shared->is_wrapped()) {
    // If it's a top-level script, report compilation to the debugger.
2071 2072
    Handle<Script> script(Script::cast(shared->script()), isolate);
    isolate->debug()->OnAfterCompile(script);
2073
  }
2074
}
2075

2076 2077 2078 2079 2080 2081 2082 2083
// ----------------------------------------------------------------------------
// Implementation of ScriptStreamingData

ScriptStreamingData::ScriptStreamingData(
    ScriptCompiler::ExternalSourceStream* source_stream,
    ScriptCompiler::StreamedSource::Encoding encoding)
    : source_stream(source_stream), encoding(encoding) {}

2084
ScriptStreamingData::~ScriptStreamingData() = default;
2085

2086
void ScriptStreamingData::Release() { task.reset(); }
2087

2088 2089
}  // namespace internal
}  // namespace v8