compiler.cc 68.7 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.h"
11
#include "src/asmjs/asm-js.h"
12
#include "src/assembler-inl.h"
13 14 15
#include "src/ast/ast-numbering.h"
#include "src/ast/prettyprinter.h"
#include "src/ast/scopes.h"
16
#include "src/base/optional.h"
17 18
#include "src/bootstrapper.h"
#include "src/compilation-cache.h"
19
#include "src/compilation-info.h"
20
#include "src/compiler-dispatcher/compiler-dispatcher.h"
21
#include "src/compiler-dispatcher/optimizing-compile-dispatcher.h"
22
#include "src/compiler/pipeline.h"
23 24
#include "src/debug/debug.h"
#include "src/debug/liveedit.h"
25
#include "src/frames-inl.h"
yangguo's avatar
yangguo committed
26
#include "src/globals.h"
27
#include "src/heap/heap.h"
28
#include "src/interpreter/interpreter.h"
29
#include "src/isolate-inl.h"
30
#include "src/log-inl.h"
31
#include "src/messages.h"
32
#include "src/objects/map.h"
33
#include "src/parsing/parse-info.h"
34
#include "src/parsing/parsing.h"
35 36
#include "src/parsing/rewriter.h"
#include "src/parsing/scanner-character-streams.h"
37
#include "src/runtime-profiler.h"
38
#include "src/snapshot/code-serializer.h"
39
#include "src/vm-state-inl.h"
40

41 42
namespace v8 {
namespace internal {
43

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

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

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

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

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

71
// ----------------------------------------------------------------------------
72
// Implementation of CompilationJob
73

74
CompilationJob::CompilationJob(uintptr_t stack_limit, ParseInfo* parse_info,
75
                               CompilationInfo* compilation_info,
76
                               const char* compiler_name, State initial_state)
77 78
    : parse_info_(parse_info),
      compilation_info_(compilation_info),
79 80
      compiler_name_(compiler_name),
      state_(initial_state),
81
      stack_limit_(stack_limit) {}
82

83 84 85
CompilationJob::Status CompilationJob::PrepareJob(Isolate* isolate) {
  DCHECK(ThreadId::Current().Equals(isolate->thread_id()));
  DisallowJavascriptExecution no_js(isolate);
86

87
  if (FLAG_trace_opt && compilation_info()->IsOptimizing()) {
88
    OFStream os(stdout);
89 90 91
    os << "[compiling method " << Brief(*compilation_info()->closure())
       << " using " << compiler_name_;
    if (compilation_info()->is_osr()) os << " OSR";
92 93 94
    os << "]" << std::endl;
  }

95
  // Delegate to the underlying implementation.
96
  DCHECK_EQ(state(), State::kReadyToPrepare);
97
  ScopedTimer t(&time_taken_to_prepare_);
98
  return UpdateState(PrepareJobImpl(isolate), State::kReadyToExecute);
99 100
}

101
CompilationJob::Status CompilationJob::ExecuteJob() {
102 103 104 105
  DisallowHeapAllocation no_allocation;
  DisallowHandleAllocation no_handles;
  DisallowHandleDereference no_deref;
  DisallowCodeDependencyChange no_dependency_change;
106

107
  // Delegate to the underlying implementation.
108
  DCHECK_EQ(state(), State::kReadyToExecute);
109 110
  ScopedTimer t(&time_taken_to_execute_);
  return UpdateState(ExecuteJobImpl(), State::kReadyToFinalize);
111
}
112

113 114
CompilationJob::Status CompilationJob::FinalizeJob(Isolate* isolate) {
  DCHECK(ThreadId::Current().Equals(isolate->thread_id()));
115
  DisallowCodeDependencyChange no_dependency_change;
116 117 118
  DisallowJavascriptExecution no_js(isolate);
  DCHECK(!compilation_info()->dependencies() ||
         !compilation_info()->dependencies()->HasAborted());
119

120
  // Delegate to the underlying implementation.
121
  DCHECK_EQ(state(), State::kReadyToFinalize);
122
  ScopedTimer t(&time_taken_to_finalize_);
123
  return UpdateState(FinalizeJobImpl(isolate), State::kSucceeded);
124 125
}

126
CompilationJob::Status CompilationJob::RetryOptimization(BailoutReason reason) {
127 128
  DCHECK(compilation_info_->IsOptimizing());
  compilation_info_->RetryOptimization(reason);
129 130 131 132 133
  state_ = State::kFailed;
  return FAILED;
}

CompilationJob::Status CompilationJob::AbortOptimization(BailoutReason reason) {
134 135
  DCHECK(compilation_info_->IsOptimizing());
  compilation_info_->AbortOptimization(reason);
136 137 138 139
  state_ = State::kFailed;
  return FAILED;
}

140
void CompilationJob::RecordUnoptimizedCompilationStats(Isolate* isolate) const {
141
  int code_size;
142 143
  if (compilation_info()->has_bytecode_array()) {
    code_size = compilation_info()->bytecode_array()->SizeIncludingMetadata();
144
  } else {
145
    code_size = compilation_info()->code()->SizeIncludingMetadata();
146 147
  }

148
  Counters* counters = isolate->counters();
149 150 151 152 153 154 155 156
  // TODO(4280): Rename counters from "baseline" to "unoptimized" eventually.
  counters->total_baseline_code_size()->Increment(code_size);
  counters->total_baseline_compile_count()->Increment(1);

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

void CompilationJob::RecordOptimizedCompilationStats() const {
157 158
  DCHECK(compilation_info()->IsOptimizing());
  Handle<JSFunction> function = compilation_info()->closure();
159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
  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);
  }
}

181
void CompilationJob::RecordFunctionCompilation(
182
    CodeEventListener::LogEventsAndTags tag, Isolate* isolate) const {
183 184 185
  // 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.
186 187 188 189
  CompilationInfo* compilation_info = this->compilation_info();
  if (!isolate->logger()->is_logging_code_events() &&
      !isolate->is_profiling() && !FLAG_log_function_events) {
    return;
190
  }
191 192 193 194 195 196 197 198

  Handle<SharedFunctionInfo> shared = compilation_info->shared_info();
  Handle<Script> script = parse_info()->script();
  Handle<AbstractCode> abstract_code =
      compilation_info->has_bytecode_array()
          ? Handle<AbstractCode>::cast(compilation_info->bytecode_array())
          : Handle<AbstractCode>::cast(compilation_info->code());

199
  if (abstract_code.is_identical_to(BUILTIN_CODE(isolate, CompileLazy))) {
200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238
    return;
  }

  int line_num = Script::GetLineNumber(script, shared->start_position()) + 1;
  int column_num =
      Script::GetColumnNumber(script, shared->start_position()) + 1;
  String* script_name = script->name()->IsString()
                            ? String::cast(script->name())
                            : isolate->heap()->empty_string();
  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;

  double ms = time_taken_to_prepare_.InMillisecondsF();
  ms += time_taken_to_execute_.InMillisecondsF();
  ms += time_taken_to_finalize_.InMillisecondsF();

  std::string name = compilation_info->IsOptimizing() ? "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();
  }

  LOG(isolate, FunctionEvent(name.c_str(), nullptr, script->id(), ms,
                             shared->start_position(), shared->end_position(),
239
                             shared->DebugName()));
240 241
}

242 243 244 245 246
// ----------------------------------------------------------------------------
// Local helper methods that make up the compilation pipeline.

namespace {

247 248
void EnsureFeedbackMetadata(CompilationInfo* compilation_info,
                            Isolate* isolate) {
249
  DCHECK(compilation_info->has_shared_info());
250 251 252 253 254 255 256

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

  // TODO(mvstanton): reintroduce is_empty() predicate to feedback_metadata().
257 258
  if (compilation_info->shared_info()->feedback_metadata()->length() == 0 ||
      !compilation_info->shared_info()->is_compiled()) {
259
    Handle<FeedbackMetadata> feedback_metadata = FeedbackMetadata::New(
260
        isolate, compilation_info->feedback_vector_spec());
261
    compilation_info->shared_info()->set_feedback_metadata(*feedback_metadata);
262 263 264 265
  }

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

270
bool UseAsmWasm(FunctionLiteral* literal, bool asm_wasm_broken) {
271 272 273 274 275
  // 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.
276
  if (asm_wasm_broken) return false;
277 278 279 280 281

  // 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.
282
  return literal->scope()->IsAsmModule();
283 284
}

285 286
void InstallUnoptimizedCode(CompilationInfo* compilation_info,
                            Isolate* isolate) {
287 288 289
  Handle<SharedFunctionInfo> shared = compilation_info->shared_info();
  DCHECK_EQ(compilation_info->shared_info()->language_mode(),
            compilation_info->literal()->language_mode());
290 291

  // Ensure feedback metadata is installed.
292
  EnsureFeedbackMetadata(compilation_info, isolate);
293

294
  // Update the shared function info with the scope info.
295
  Handle<ScopeInfo> scope_info = compilation_info->scope()->scope_info();
296
  shared->set_scope_info(*scope_info);
297
  Scope* outer_scope = compilation_info->scope()->GetOuterScopeWithContext();
298 299 300
  if (outer_scope) {
    shared->set_outer_scope_info(*outer_scope->scope_info());
  }
301

302
  DCHECK(!compilation_info->code().is_null());
303
  shared->set_code(*compilation_info->code());
304
  if (compilation_info->has_bytecode_array()) {
305
    DCHECK(!shared->HasBytecodeArray());  // Only compiled once.
306 307 308 309
    DCHECK(!compilation_info->has_asm_wasm_data());
    shared->set_bytecode_array(*compilation_info->bytecode_array());
  } else if (compilation_info->has_asm_wasm_data()) {
    shared->set_asm_wasm_data(*compilation_info->asm_wasm_data());
310
  }
311 312

  // Install coverage info on the shared function info.
313
  if (compilation_info->has_coverage_info()) {
314 315 316
    DCHECK(isolate->is_block_code_coverage());
    isolate->debug()->InstallCoverageInfo(compilation_info->shared_info(),
                                          compilation_info->coverage_info());
317
  }
318
}
319

320 321 322 323 324 325 326
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);
327 328
    return;
  }
329 330 331
  Handle<FixedArray> infos(isolate->factory()->NewFixedArray(
      parse_info->max_function_literal_id() + 1));
  parse_info->script()->set_shared_function_infos(*infos);
332 333
}

334 335
void SetSharedFunctionFlagsFromLiteral(FunctionLiteral* literal,
                                       Handle<SharedFunctionInfo> shared_info) {
336 337 338 339
  // Don't overwrite values set by the bootstrapper.
  if (!shared_info->HasLength()) {
    shared_info->set_length(literal->function_length());
  }
340 341
  shared_info->set_has_duplicate_parameters(
      literal->has_duplicate_parameters());
342
  shared_info->SetExpectedNofPropertiesFromEstimate(literal);
343 344 345
  if (literal->dont_optimize_reason() != kNoReason) {
    shared_info->DisableOptimization(literal->dont_optimize_reason());
  }
346 347
}

348 349
CompilationJob::Status FinalizeUnoptimizedCompilationJob(CompilationJob* job,
                                                         Isolate* isolate) {
350 351
  CompilationInfo* compilation_info = job->compilation_info();
  ParseInfo* parse_info = job->parse_info();
352

353 354
  SetSharedFunctionFlagsFromLiteral(compilation_info->literal(),
                                    compilation_info->shared_info());
355

356
  CompilationJob::Status status = job->FinalizeJob(isolate);
357
  if (status == CompilationJob::SUCCEEDED) {
358
    InstallUnoptimizedCode(compilation_info, isolate);
359 360 361 362 363 364 365 366
    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;
    }
367 368
    job->RecordFunctionCompilation(log_tag, isolate);
    job->RecordUnoptimizedCompilationStats(isolate);
369
  }
370
  return status;
371 372
}

373
bool Renumber(ParseInfo* parse_info,
374
              Compiler::EagerInnerFunctionLiterals* eager_literals) {
375 376 377 378 379
  RuntimeCallTimerScope runtimeTimer(
      parse_info->runtime_call_stats(),
      parse_info->on_background_thread()
          ? &RuntimeCallStats::CompileBackgroundRenumber
          : &RuntimeCallStats::CompileRenumber);
380
  return AstNumbering::Renumber(parse_info->stack_limit(), parse_info->zone(),
381
                                parse_info->literal(), eager_literals);
382 383
}

384
std::unique_ptr<CompilationJob> PrepareAndExecuteUnoptimizedCompileJob(
385 386
    ParseInfo* parse_info, FunctionLiteral* literal,
    AccountingAllocator* allocator) {
387
  if (UseAsmWasm(literal, parse_info->is_asm_wasm_broken())) {
388
    std::unique_ptr<CompilationJob> asm_job(
389
        AsmJs::NewCompilationJob(parse_info, literal, allocator));
390
    if (asm_job->ExecuteJob() == CompilationJob::SUCCEEDED) {
391
      return asm_job;
392
    }
393
    // asm.js validation failed, fall through to standard unoptimized compile.
394 395 396 397
    // 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.
398
  }
399
  std::unique_ptr<CompilationJob> job(
400
      interpreter::Interpreter::NewCompilationJob(parse_info, literal,
401
                                                  allocator));
402 403

  if (job->ExecuteJob() == CompilationJob::SUCCEEDED) {
404
    return job;
405
  }
406
  return std::unique_ptr<CompilationJob>();  // Compilation failed, return null.
407 408
}

409
std::unique_ptr<CompilationJob> GenerateUnoptimizedCode(
410
    ParseInfo* parse_info, AccountingAllocator* allocator,
411
    CompilationJobList* inner_function_jobs) {
412 413 414 415
  DisallowHeapAllocation no_allocation;
  DisallowHandleAllocation no_handles;
  DisallowHandleDereference no_deref;
  DCHECK(inner_function_jobs->empty());
416 417

  Compiler::EagerInnerFunctionLiterals inner_literals;
418
  if (!Compiler::Analyze(parse_info, &inner_literals)) {
419
    return std::unique_ptr<CompilationJob>();
420 421
  }

422
  // Prepare and execute compilation of the outer-most function.
423
  std::unique_ptr<CompilationJob> outer_function_job(
424
      PrepareAndExecuteUnoptimizedCompileJob(parse_info, parse_info->literal(),
425
                                             allocator));
426
  if (!outer_function_job) return std::unique_ptr<CompilationJob>();
427 428 429 430 431

  // Prepare and execute compilation jobs for eager inner functions.
  for (auto it : inner_literals) {
    FunctionLiteral* inner_literal = it->value();
    std::unique_ptr<CompilationJob> inner_job(
432
        PrepareAndExecuteUnoptimizedCompileJob(parse_info, inner_literal,
433
                                               allocator));
434 435
    if (!inner_job) return std::unique_ptr<CompilationJob>();
    inner_function_jobs->emplace_front(std::move(inner_job));
436 437
  }

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

441 442 443
  return outer_function_job;
}

444 445 446 447
bool FinalizeUnoptimizedCode(ParseInfo* parse_info, Isolate* isolate,
                             Handle<SharedFunctionInfo> shared_info,
                             CompilationJob* outer_function_job,
                             CompilationJobList* inner_function_jobs) {
448 449
  DCHECK(AllowCompilation::IsAllowed(isolate));

450 451 452 453 454
  // Allocate scope infos for the literal.
  DeclarationScope::AllocateScopeInfos(parse_info, isolate,
                                       AnalyzeMode::kRegular);

  // Finalize the outer-most function's compilation job.
455
  outer_function_job->compilation_info()->set_shared_info(shared_info);
456
  if (FinalizeUnoptimizedCompilationJob(outer_function_job, isolate) !=
457
      CompilationJob::SUCCEEDED) {
458
    return false;
459 460 461
  }

  // Finalize the inner functions' compilation jobs.
462
  for (auto&& inner_job : *inner_function_jobs) {
463 464 465 466 467 468 469 470
    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.
    // TODO(rmcilroy): Fix this and DCHECK !is_compiled() once Full-Codegen dies
    if (inner_shared_info->is_compiled()) continue;
    inner_job->compilation_info()->set_shared_info(inner_shared_info);
471
    if (FinalizeUnoptimizedCompilationJob(inner_job.get(), isolate) !=
472
        CompilationJob::SUCCEEDED) {
473
      return false;
474 475
    }
  }
476 477 478 479 480 481 482

  // 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());
  }

483
  return true;
484 485
}

486
MUST_USE_RESULT MaybeHandle<Code> GetCodeFromOptimizedCodeCache(
487
    Handle<JSFunction> function, BailoutId osr_offset) {
488 489 490
  RuntimeCallTimerScope runtimeTimer(
      function->GetIsolate(),
      &RuntimeCallStats::CompileGetFromOptimizedCodeMap);
491 492
  Handle<SharedFunctionInfo> shared(function->shared());
  DisallowHeapAllocation no_gc;
493
  if (osr_offset.IsNone()) {
494 495 496 497
    if (function->feedback_vector_cell()->value()->IsFeedbackVector()) {
      FeedbackVector* feedback_vector = function->feedback_vector();
      feedback_vector->EvictOptimizedCodeMarkedForDeoptimization(
          function->shared(), "GetCodeFromOptimizedCodeCache");
498 499 500 501 502 503 504 505
      Code* code = feedback_vector->optimized_code();

      if (code != nullptr) {
        // Caching of optimized code enabled and optimized code found.
        DCHECK(!code->marked_for_deoptimization());
        DCHECK(function->shared()->is_compiled());
        return Handle<Code>(code);
      }
506
    }
507 508 509 510
  }
  return MaybeHandle<Code>();
}

511 512
void ClearOptimizedCodeCache(CompilationInfo* compilation_info) {
  Handle<JSFunction> function = compilation_info->closure();
513
  if (compilation_info->osr_offset().IsNone()) {
514 515 516 517 518 519
    Handle<FeedbackVector> vector =
        handle(function->feedback_vector(), function->GetIsolate());
    vector->ClearOptimizedCode();
  }
}

520 521
void InsertCodeIntoOptimizedCodeCache(CompilationInfo* compilation_info) {
  Handle<Code> code = compilation_info->code();
522 523
  if (code->kind() != Code::OPTIMIZED_FUNCTION) return;  // Nothing to do.

524 525
  // Function context specialization folds-in the function context,
  // so no sharing can occur.
526
  if (compilation_info->is_function_context_specializing()) {
527 528
    // Native context specialized code is not shared, so make sure the optimized
    // code cache is clear.
529
    ClearOptimizedCodeCache(compilation_info);
530 531
    return;
  }
532

533
  // Cache optimized context-specific code.
534
  Handle<JSFunction> function = compilation_info->closure();
535 536
  Handle<SharedFunctionInfo> shared(function->shared());
  Handle<Context> native_context(function->context()->native_context());
537
  if (compilation_info->osr_offset().IsNone()) {
538 539 540 541
    Handle<FeedbackVector> vector =
        handle(function->feedback_vector(), function->GetIsolate());
    FeedbackVector::SetOptimizedCode(vector, code);
  }
542 543
}

544
bool GetOptimizedCodeNow(CompilationJob* job, Isolate* isolate) {
545
  TimerEventScope<TimerEventRecompileSynchronous> timer(isolate);
546 547
  RuntimeCallTimerScope runtimeTimer(isolate,
                                     &RuntimeCallStats::RecompileSynchronous);
548
  CompilationInfo* compilation_info = job->compilation_info();
549 550
  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
               "V8.RecompileSynchronous");
551

552
  if (job->PrepareJob(isolate) != CompilationJob::SUCCEEDED ||
553
      job->ExecuteJob() != CompilationJob::SUCCEEDED ||
554
      job->FinalizeJob(isolate) != CompilationJob::SUCCEEDED) {
555 556
    if (FLAG_trace_opt) {
      PrintF("[aborted optimizing ");
557 558 559
      compilation_info->closure()->ShortPrint();
      PrintF(" because: %s]\n",
             GetBailoutReason(compilation_info->bailout_reason()));
560 561 562
    }
    return false;
  }
563 564

  // Success!
565
  job->RecordOptimizedCompilationStats();
566
  DCHECK(!isolate->has_pending_exception());
567
  InsertCodeIntoOptimizedCodeCache(compilation_info);
568
  job->RecordFunctionCompilation(CodeEventListener::LAZY_COMPILE_TAG, isolate);
569 570 571
  return true;
}

572
bool GetOptimizedCodeLater(CompilationJob* job, Isolate* isolate) {
573
  CompilationInfo* compilation_info = job->compilation_info();
574
  if (!isolate->optimizing_compile_dispatcher()->IsQueueAvailable()) {
575 576
    if (FLAG_trace_concurrent_recompilation) {
      PrintF("  ** Compilation queue full, will retry optimizing ");
577
      compilation_info->closure()->ShortPrint();
578 579 580 581 582
      PrintF(" later.\n");
    }
    return false;
  }

583 584 585
  if (isolate->heap()->HighMemoryPressure()) {
    if (FLAG_trace_concurrent_recompilation) {
      PrintF("  ** High memory pressure, will retry optimizing ");
586
      compilation_info->closure()->ShortPrint();
587 588 589 590 591
      PrintF(" later.\n");
    }
    return false;
  }

592 593
  TimerEventScope<TimerEventRecompileSynchronous> timer(isolate);
  RuntimeCallTimerScope runtimeTimer(isolate,
594
                                     &RuntimeCallStats::RecompileSynchronous);
595 596
  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
               "V8.RecompileSynchronous");
597

598
  if (job->PrepareJob(isolate) != CompilationJob::SUCCEEDED) return false;
599
  isolate->optimizing_compile_dispatcher()->QueueForOptimization(job);
600 601 602

  if (FLAG_trace_concurrent_recompilation) {
    PrintF("  ** Queued ");
603
    compilation_info->closure()->ShortPrint();
604
    PrintF(" for concurrent optimization.\n");
605 606 607 608
  }
  return true;
}

609
MaybeHandle<Code> GetOptimizedCode(Handle<JSFunction> function,
610
                                   ConcurrencyMode mode,
611
                                   BailoutId osr_offset = BailoutId::None(),
612 613 614 615
                                   JavaScriptFrame* osr_frame = nullptr) {
  Isolate* isolate = function->GetIsolate();
  Handle<SharedFunctionInfo> shared(function->shared(), isolate);

616 617 618 619 620 621
  // Make sure we clear the optimization marker on the function so that we
  // don't try to re-optimize.
  if (function->HasOptimizationMarker()) {
    function->ClearOptimizationMarker();
  }

622
  Handle<Code> cached_code;
623
  if (GetCodeFromOptimizedCodeCache(function, osr_offset)
624 625 626 627
          .ToHandle(&cached_code)) {
    if (FLAG_trace_opt) {
      PrintF("[found optimized code for ");
      function->ShortPrint();
628 629
      if (!osr_offset.IsNone()) {
        PrintF(" at OSR AST id %d", osr_offset.ToInt());
630 631 632 633 634 635
      }
      PrintF("]\n");
    }
    return cached_code;
  }

636
  // Reset profiler ticks, function is no longer considered hot.
637
  DCHECK(shared->is_compiled());
638
  function->feedback_vector()->set_profiler_ticks(0);
639 640 641 642

  VMState<COMPILER> state(isolate);
  DCHECK(!isolate->has_pending_exception());
  PostponeInterruptsScope postpone(isolate);
643
  bool has_script = shared->script()->IsScript();
644 645 646
  // 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());
647
  std::unique_ptr<CompilationJob> job(
648
      compiler::Pipeline::NewCompilationJob(function, has_script));
649 650
  CompilationInfo* compilation_info = job->compilation_info();
  ParseInfo* parse_info = job->parse_info();
651

652
  compilation_info->SetOptimizingForOsr(osr_offset, osr_frame);
653

654
  // Do not use TurboFan if we need to be able to set break points.
655 656
  if (compilation_info->shared_info()->HasBreakInfo()) {
    compilation_info->AbortOptimization(kFunctionBeingDebugged);
657 658 659
    return MaybeHandle<Code>();
  }

660
  // Do not use TurboFan when %NeverOptimizeFunction was applied.
661 662
  if (shared->optimization_disabled() &&
      shared->disable_optimization_reason() == kOptimizationDisabledForTest) {
663
    compilation_info->AbortOptimization(kOptimizationDisabledForTest);
664 665 666
    return MaybeHandle<Code>();
  }

667 668 669
  // Do not use TurboFan if optimization is disabled or function doesn't pass
  // turbo_filter.
  if (!FLAG_opt || !shared->PassesFilter(FLAG_turbo_filter)) {
670
    compilation_info->AbortOptimization(kOptimizationDisabled);
671 672 673
    return MaybeHandle<Code>();
  }

674
  TimerEventScope<TimerEventOptimizeCode> optimize_code_timer(isolate);
675
  RuntimeCallTimerScope runtimeTimer(isolate, &RuntimeCallStats::OptimizeCode);
676
  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.OptimizeCode");
677

678 679 680
  // 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.
681
  base::Optional<CompilationHandleScope> compilation;
682
  if (mode == ConcurrencyMode::kConcurrent) {
683
    compilation.emplace(isolate, compilation_info);
684 685
  }

686
  // All handles below will be canonicalized.
687
  CanonicalHandleScope canonical(isolate);
688 689

  // Reopen handles in the new CompilationHandleScope.
690
  compilation_info->ReopenHandlesInNewHandleScope();
691 692
  parse_info->ReopenHandlesInNewHandleScope();

693
  if (mode == ConcurrencyMode::kConcurrent) {
694
    if (GetOptimizedCodeLater(job.get(), isolate)) {
695
      job.release();  // The background recompile job owns this now.
696 697 698 699

      // Set the optimization marker and return a code object which checks it.
      function->SetOptimizationMarker(OptimizationMarker::kInOptimizationQueue);
      if (function->IsInterpreted()) {
700
        return BUILTIN_CODE(isolate, InterpreterEntryTrampoline);
701
      } else {
702
        return BUILTIN_CODE(isolate, CheckOptimizationMarker);
703
      }
704 705
    }
  } else {
706 707
    if (GetOptimizedCodeNow(job.get(), isolate))
      return compilation_info->code();
708 709 710 711 712 713
  }

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

714 715
CompilationJob::Status FinalizeOptimizedCompilationJob(CompilationJob* job,
                                                       Isolate* isolate) {
716
  CompilationInfo* compilation_info = job->compilation_info();
717

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

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

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

729
  DCHECK(!shared->HasBreakInfo());
730 731 732 733 734 735 736 737 738

  // 1) Optimization on the concurrent thread may have failed.
  // 2) The function may have already been optimized by OSR.  Simply continue.
  //    Except when OSR already disabled optimization for some reason.
  // 3) The code may have already been invalidated due to dependency change.
  // 4) Code generation may have failed.
  if (job->state() == CompilationJob::State::kReadyToFinalize) {
    if (shared->optimization_disabled()) {
      job->RetryOptimization(kOptimizationDisabled);
739
    } else if (compilation_info->dependencies()->HasAborted()) {
740
      job->RetryOptimization(kBailedOutDueToDependencyChange);
741
    } else if (job->FinalizeJob(isolate) == CompilationJob::SUCCEEDED) {
742
      job->RecordOptimizedCompilationStats();
743 744
      job->RecordFunctionCompilation(CodeEventListener::LAZY_COMPILE_TAG,
                                     isolate);
745
      InsertCodeIntoOptimizedCodeCache(compilation_info);
746 747
      if (FLAG_trace_opt) {
        PrintF("[completed optimizing ");
748
        compilation_info->closure()->ShortPrint();
749 750
        PrintF("]\n");
      }
751
      compilation_info->closure()->set_code(*compilation_info->code());
752 753 754 755
      return CompilationJob::SUCCEEDED;
    }
  }

756
  DCHECK_EQ(job->state(), CompilationJob::State::kFailed);
757 758
  if (FLAG_trace_opt) {
    PrintF("[aborted optimizing ");
759 760 761
    compilation_info->closure()->ShortPrint();
    PrintF(" because: %s]\n",
           GetBailoutReason(compilation_info->bailout_reason()));
762
  }
763
  compilation_info->closure()->set_code(shared->code());
764
  // Clear the InOptimizationQueue marker, if it exists.
765 766
  if (compilation_info->closure()->IsInOptimizationQueue()) {
    compilation_info->closure()->ClearOptimizationMarker();
767
  }
768 769 770
  return CompilationJob::FAILED;
}

771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802
MaybeHandle<SharedFunctionInfo> FinalizeTopLevel(
    ParseInfo* parse_info, Isolate* isolate, CompilationJob* outer_function_job,
    CompilationJobList* inner_function_jobs) {
  Handle<Script> script = parse_info->script();

  // Internalize ast values onto the heap.
  parse_info->ast_value_factory()->Internalize(isolate);

  // 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 =
      isolate->factory()->NewSharedFunctionInfoForLiteral(parse_info->literal(),
                                                          parse_info->script());
  shared_info->set_is_toplevel(true);

  // Finalize compilation of the unoptimized bytecode or asm-js data.
  if (!FinalizeUnoptimizedCode(parse_info, isolate, shared_info,
                               outer_function_job, inner_function_jobs)) {
    if (!isolate->has_pending_exception()) isolate->StackOverflow();
    return MaybeHandle<SharedFunctionInfo>();
  }

  if (!script.is_null()) {
    script->set_compilation_state(Script::COMPILATION_STATE_COMPILED);
  }

  return shared_info;
}

803 804 805
MaybeHandle<SharedFunctionInfo> CompileToplevel(ParseInfo* parse_info,
                                                Isolate* isolate) {
  TimerEventScope<TimerEventCompileCode> top_level_timer(isolate);
806
  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.CompileCode");
807 808
  DCHECK(ThreadId::Current().Equals(isolate->thread_id()));

809
  PostponeInterruptsScope postpone(isolate);
810
  DCHECK(!isolate->native_context().is_null());
811 812 813
  RuntimeCallTimerScope runtimeTimer(
      isolate, parse_info->is_eval() ? &RuntimeCallStats::CompileEval
                                     : &RuntimeCallStats::CompileScript);
814 815 816 817 818 819 820 821 822 823 824 825 826 827
  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");
828

829
  // Generate the unoptimized bytecode or asm-js data.
830
  CompilationJobList inner_function_jobs;
831 832
  std::unique_ptr<CompilationJob> outer_function_job(GenerateUnoptimizedCode(
      parse_info, isolate->allocator(), &inner_function_jobs));
833 834 835 836
  if (!outer_function_job) {
    if (!isolate->has_pending_exception()) isolate->StackOverflow();
    return MaybeHandle<SharedFunctionInfo>();
  }
837

838 839
  return FinalizeTopLevel(parse_info, isolate, outer_function_job.get(),
                          &inner_function_jobs);
840 841 842 843 844 845 846 847 848 849
}

bool FailWithPendingException(Isolate* isolate,
                              Compiler::ClearExceptionFlag flag) {
  if (flag == Compiler::CLEAR_EXCEPTION) {
    isolate->clear_pending_exception();
  } else if (!isolate->has_pending_exception()) {
    isolate->StackOverflow();
  }
  return false;
850 851
}

852 853 854 855 856
}  // namespace

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

857
bool Compiler::Analyze(ParseInfo* parse_info,
858
                       EagerInnerFunctionLiterals* eager_literals) {
859
  DCHECK_NOT_NULL(parse_info->literal());
860 861 862 863 864
  RuntimeCallTimerScope runtimeTimer(
      parse_info->runtime_call_stats(),
      parse_info->on_background_thread()
          ? &RuntimeCallStats::CompileBackgroundAnalyse
          : &RuntimeCallStats::CompileAnalyse);
865
  if (!Rewriter::Rewrite(parse_info)) return false;
866
  DeclarationScope::Analyze(parse_info);
867
  if (!Renumber(parse_info, eager_literals)) return false;
868 869 870
  return true;
}

871
bool Compiler::ParseAndAnalyze(ParseInfo* parse_info,
872 873
                               Handle<SharedFunctionInfo> shared_info,
                               Isolate* isolate) {
874
  if (!parsing::ParseAny(parse_info, shared_info, isolate)) {
875 876
    return false;
  }
877
  return Compiler::Analyze(parse_info);
878 879
}

880 881 882 883 884 885
bool Compiler::Compile(Handle<SharedFunctionInfo> shared_info,
                       ClearExceptionFlag flag) {
  // We should never reach here if the function is already compiled.
  DCHECK(!shared_info->is_compiled());

  Isolate* isolate = shared_info->GetIsolate();
886
  DCHECK(ThreadId::Current().Equals(isolate->thread_id()));
887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915
  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,
                                     &RuntimeCallStats::CompileFunction);
  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.CompileCode");
  AggregatedHistogramTimerScope timer(isolate->counters()->compile_lazy());

  // 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)) {
      return FailWithPendingException(isolate, flag);
    }
    return true;
  }

  // Set up parse info.
  ParseInfo parse_info(shared_info);
  parse_info.set_lazy_compile();
  if (FLAG_preparser_scope_analysis) {
    if (shared_info->HasPreParsedScopeData()) {
      Handle<PreParsedScopeData> data(
          PreParsedScopeData::cast(shared_info->preparsed_scope_data()));
      parse_info.consumed_preparsed_scope_data()->SetData(data);
      // After we've compiled the function, we don't need data about its
      // skippable functions any more.
916
      shared_info->ClearPreParsedScopeData();
917 918 919 920 921 922 923 924 925
    }
  }

  // Parse and update ParseInfo with the results.
  if (!parsing::ParseFunction(&parse_info, shared_info, isolate)) {
    return FailWithPendingException(isolate, flag);
  }

  // Generate the unoptimized bytecode or asm-js data.
926
  CompilationJobList inner_function_jobs;
927 928
  std::unique_ptr<CompilationJob> outer_function_job(GenerateUnoptimizedCode(
      &parse_info, isolate->allocator(), &inner_function_jobs));
929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946
  if (!outer_function_job) {
    return FailWithPendingException(isolate, flag);
  }

  // Internalize ast values onto the heap.
  parse_info.ast_value_factory()->Internalize(isolate);

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

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

947
bool Compiler::Compile(Handle<JSFunction> function, ClearExceptionFlag flag) {
948 949 950
  // We should never reach here if the function is already compiled or optimized
  DCHECK(!function->is_compiled());
  DCHECK(!function->IsOptimized());
951 952
  DCHECK(!function->HasOptimizationMarker());
  DCHECK(!function->HasOptimizedCode());
953

954
  Isolate* isolate = function->GetIsolate();
955
  Handle<SharedFunctionInfo> shared_info = handle(function->shared());
956
  DCHECK(AllowCompilation::IsAllowed(isolate));
957

958 959 960 961 962 963 964 965 966 967 968 969 970
  // Ensure shared function info is compiled.
  if (!shared_info->is_compiled() && !Compile(shared_info, flag)) return false;
  Handle<Code> code = handle(shared_info->code(), isolate);

  // Allocate literals for the JSFunction.
  JSFunction::EnsureLiterals(function);

  // 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");
971
    }
972 973 974 975
    Handle<Code> opt_code;
    if (GetOptimizedCode(function, ConcurrencyMode::kNotConcurrent)
            .ToHandle(&opt_code)) {
      code = opt_code;
976 977
    }
  }
978

979
  // Install code on closure.
980
  function->set_code(*code);
981 982 983 984

  // Check postconditions on success.
  DCHECK(!isolate->has_pending_exception());
  DCHECK(function->shared()->is_compiled());
985 986 987 988 989 990
  DCHECK(function->is_compiled());
  return true;
}

bool Compiler::CompileOptimized(Handle<JSFunction> function,
                                ConcurrencyMode mode) {
991 992 993 994 995
  if (function->IsOptimized()) return true;
  Isolate* isolate = function->GetIsolate();
  DCHECK(AllowCompilation::IsAllowed(isolate));

  // Start a compilation.
996
  Handle<Code> code;
997
  if (!GetOptimizedCode(function, mode).ToHandle(&code)) {
998 999
    // Optimization failed, get unoptimized code. Unoptimized code must exist
    // already if we are optimizing.
1000
    DCHECK(!isolate->has_pending_exception());
1001 1002
    DCHECK(function->shared()->is_compiled());
    code = handle(function->shared()->code(), isolate);
1003 1004
  }

1005
  // Install code on closure.
1006
  function->set_code(*code);
1007 1008 1009 1010 1011

  // Check postconditions on success.
  DCHECK(!isolate->has_pending_exception());
  DCHECK(function->shared()->is_compiled());
  DCHECK(function->is_compiled());
1012 1013 1014 1015 1016 1017
  DCHECK_IMPLIES(function->HasOptimizationMarker(),
                 function->IsInOptimizationQueue());
  DCHECK_IMPLIES(function->HasOptimizationMarker(),
                 function->ChecksOptimizationMarker());
  DCHECK_IMPLIES(function->IsInOptimizationQueue(),
                 mode == ConcurrencyMode::kConcurrent);
1018 1019 1020
  return true;
}

1021
MaybeHandle<JSArray> Compiler::CompileForLiveEdit(Handle<Script> script) {
1022 1023 1024
  Isolate* isolate = script->GetIsolate();
  DCHECK(AllowCompilation::IsAllowed(isolate));

1025 1026 1027
  // In order to ensure that live edit function info collection finds the newly
  // generated shared function infos, clear the script's list temporarily
  // and restore it at the end of this method.
1028 1029 1030
  Handle<FixedArray> old_function_infos(script->shared_function_infos(),
                                        isolate);
  script->set_shared_function_infos(isolate->heap()->empty_fixed_array());
1031

1032
  // Start a compilation.
1033
  ParseInfo parse_info(script);
1034
  parse_info.set_eager();
1035

1036
  // TODO(635): support extensions.
1037
  Handle<JSArray> infos;
1038 1039
  Handle<SharedFunctionInfo> shared_info;
  if (CompileToplevel(&parse_info, isolate).ToHandle(&shared_info)) {
1040 1041 1042
    // Check postconditions on success.
    DCHECK(!isolate->has_pending_exception());
    infos = LiveEditFunctionTracker::Collect(parse_info.literal(), script,
1043
                                             parse_info.zone(), isolate);
1044
  }
1045 1046 1047 1048 1049 1050

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

1051
  return infos;
1052 1053
}

1054
MaybeHandle<JSFunction> Compiler::GetFunctionFromEval(
1055
    Handle<String> source, Handle<SharedFunctionInfo> outer_info,
1056
    Handle<Context> context, LanguageMode language_mode,
1057 1058 1059
    ParseRestriction restriction, int parameters_end_pos,
    int eval_scope_position, int eval_position, int line_offset,
    int column_offset, Handle<Object> script_name,
1060
    ScriptOriginOptions options) {
1061 1062 1063 1064 1065
  Isolate* isolate = source->GetIsolate();
  int source_length = source->length();
  isolate->counters()->total_eval_size()->Increment(source_length);
  isolate->counters()->total_compile_size()->Increment(source_length);

1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082
  // 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.
  int position = eval_scope_position;
  if (FLAG_harmony_function_tostring &&
      restriction == ONLY_SINGLE_FUNCTION_LITERAL &&
      parameters_end_pos != kNoSourcePosition) {
    // use the parameters_end_pos as the eval_scope_position in the eval cache.
    DCHECK_EQ(eval_scope_position, 0);
    position = -parameters_end_pos;
  }
1083
  CompilationCache* compilation_cache = isolate->compilation_cache();
1084
  InfoVectorPair eval_result = compilation_cache->LookupEval(
1085
      source, outer_info, context, language_mode, position);
1086 1087 1088 1089
  Handle<Cell> vector;
  if (eval_result.has_vector()) {
    vector = Handle<Cell>(eval_result.vector(), isolate);
  }
1090

1091
  Handle<SharedFunctionInfo> shared_info;
1092
  Handle<Script> script;
1093 1094 1095 1096
  if (eval_result.has_shared()) {
    shared_info = Handle<SharedFunctionInfo>(eval_result.shared(), isolate);
    script = Handle<Script>(Script::cast(shared_info->script()), isolate);
  } else {
1097
    script = isolate->factory()->NewScript(source);
1098 1099 1100
    if (isolate->NeedsSourcePositionsForProfiling()) {
      Script::InitLineEnds(script);
    }
1101 1102
    if (!script_name.is_null()) {
      script->set_name(*script_name);
1103 1104
      script->set_line_offset(line_offset);
      script->set_column_offset(column_offset);
1105 1106
    }
    script->set_origin_options(options);
1107
    script->set_compilation_type(Script::COMPILATION_TYPE_EVAL);
1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124

    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.
      StackTraceFrameIterator it(script->GetIsolate());
      if (!it.done() && it.is_javascript()) {
        FrameSummary summary = FrameSummary::GetTop(it.javascript_frame());
        script->set_eval_from_shared(
            summary.AsJavaScript().function()->shared());
        eval_position = -summary.code_offset();
      } else {
        eval_position = 0;
      }
    }
    script->set_eval_from_position(eval_position);
1125

1126
    ParseInfo parse_info(script);
1127 1128 1129
    parse_info.set_eval();
    parse_info.set_language_mode(language_mode);
    parse_info.set_parse_restriction(restriction);
1130
    parse_info.set_parameters_end_pos(parameters_end_pos);
1131 1132 1133
    if (!context->IsNativeContext()) {
      parse_info.set_outer_scope_info(handle(context->scope_info()));
    }
1134
    DCHECK(!parse_info.is_module());
1135

1136
    if (!CompileToplevel(&parse_info, isolate).ToHandle(&shared_info)) {
1137
      return MaybeHandle<JSFunction>();
1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148
    }
  }

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

  Handle<JSFunction> result;
  if (eval_result.has_shared()) {
    if (eval_result.has_vector()) {
      result = isolate->factory()->NewFunctionFromSharedFunctionInfo(
          shared_info, context, vector, NOT_TENURED);
1149
    } else {
1150
      result = isolate->factory()->NewFunctionFromSharedFunctionInfo(
1151
          shared_info, context, NOT_TENURED);
1152 1153 1154
      JSFunction::EnsureLiterals(result);
      // Make sure to cache this result.
      Handle<Cell> new_vector(result->feedback_vector_cell(), isolate);
1155
      compilation_cache->PutEval(source, outer_info, context, shared_info,
1156
                                 new_vector, eval_scope_position);
1157
    }
1158 1159 1160 1161 1162 1163 1164 1165 1166
  } else {
    result = isolate->factory()->NewFunctionFromSharedFunctionInfo(
        shared_info, context, NOT_TENURED);
    JSFunction::EnsureLiterals(result);
    // Add the SharedFunctionInfo and the LiteralsArray to the eval cache if
    // we didn't retrieve from there.
    Handle<Cell> vector(result->feedback_vector_cell(), isolate);
    compilation_cache->PutEval(source, outer_info, context, shared_info, vector,
                               eval_scope_position);
1167 1168
  }

1169 1170 1171 1172 1173 1174
  // OnAfterCompile has to be called after we create the JSFunction, which we
  // may require to recompile the eval for debugging, if we find a function
  // that contains break points in the eval script.
  isolate->debug()->OnAfterCompile(script);

  return result;
1175 1176
}

1177 1178
namespace {

1179 1180 1181 1182 1183 1184 1185 1186 1187
bool ContainsAsmModule(Handle<Script> script) {
  DisallowHeapAllocation no_gc;
  SharedFunctionInfo::ScriptIterator iter(script);
  while (SharedFunctionInfo* info = iter.Next()) {
    if (info->HasAsmWasmData()) return true;
  }
  return false;
}

1188 1189 1190 1191 1192
bool ShouldProduceCodeCache(ScriptCompiler::CompileOptions options) {
  return options == ScriptCompiler::kProduceCodeCache ||
         options == ScriptCompiler::kProduceFullCodeCache;
}

1193 1194 1195 1196 1197
}  // namespace

bool Compiler::CodeGenerationFromStringsAllowed(Isolate* isolate,
                                                Handle<Context> context,
                                                Handle<String> source) {
1198 1199 1200 1201
  DCHECK(context->allow_code_gen_from_strings()->IsFalse(isolate));
  // Check with callback if set.
  AllowCodeGenerationFromStringsCallback callback =
      isolate->allow_code_gen_callback();
1202
  if (callback == nullptr) {
1203 1204 1205 1206 1207
    // No callback set and code generation disallowed.
    return false;
  } else {
    // Callback set. Let it decide if code generation is allowed.
    VMState<EXTERNAL> state(isolate);
1208
    return callback(v8::Utils::ToLocal(context), v8::Utils::ToLocal(source));
1209 1210 1211 1212 1213
  }
}

MaybeHandle<JSFunction> Compiler::GetFunctionFromString(
    Handle<Context> context, Handle<String> source,
1214
    ParseRestriction restriction, int parameters_end_pos) {
1215 1216 1217 1218 1219 1220
  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) &&
1221
      !CodeGenerationFromStringsAllowed(isolate, native_context, source)) {
1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232
    Handle<Object> error_message =
        native_context->ErrorMessageForCodeGenerationFromStrings();
    THROW_NEW_ERROR(isolate, NewEvalError(MessageTemplate::kCodeGenFromStrings,
                                          error_message),
                    JSFunction);
  }

  // Compile source string in the native context.
  int eval_scope_position = 0;
  int eval_position = kNoSourcePosition;
  Handle<SharedFunctionInfo> outer_info(native_context->closure()->shared());
1233 1234 1235
  return Compiler::GetFunctionFromEval(
      source, outer_info, native_context, LanguageMode::kSloppy, restriction,
      parameters_end_pos, eval_scope_position, eval_position);
1236 1237
}

1238 1239 1240 1241
namespace {

struct ScriptCompileTimerScope {
 public:
1242 1243 1244
  // 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.
1245 1246
  enum class CacheBehaviour {
    kProduceCodeCache,
1247
    kHitIsolateCacheWhenNoCache,
1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258
    kConsumeCodeCache,
    kConsumeCodeCacheFailed,
    kNoCacheBecauseInlineScript,
    kNoCacheBecauseScriptTooSmall,
    kNoCacheBecauseCacheTooCold,
    kNoCacheNoReason,
    kNoCacheBecauseNoResource,
    kNoCacheBecauseInspector,
    kNoCacheBecauseCachingDisabled,
    kNoCacheBecauseModule,
    kNoCacheBecauseStreamingSource,
1259
    kNoCacheBecauseV8Extension,
1260 1261
    kHitIsolateCacheWhenProduceCodeCache,
    kHitIsolateCacheWhenConsumeCodeCache,
1262 1263 1264
    kNoCacheBecauseExtensionModule,
    kNoCacheBecausePacScript,
    kNoCacheBecauseInDocumentWrite,
1265
    kNoCacheBecauseResourceWithNoCacheHandler,
1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320
    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_) {
1321 1322 1323 1324 1325
      if (hit_isolate_cache_) {
        return CacheBehaviour::kHitIsolateCacheWhenProduceCodeCache;
      } else {
        return CacheBehaviour::kProduceCodeCache;
      }
1326 1327 1328
    }

    if (consuming_code_cache_) {
1329 1330 1331
      if (hit_isolate_cache_) {
        return CacheBehaviour::kHitIsolateCacheWhenConsumeCodeCache;
      } else if (consuming_code_cache_failed_) {
1332 1333 1334 1335 1336
        return CacheBehaviour::kConsumeCodeCacheFailed;
      }
      return CacheBehaviour::kConsumeCodeCache;
    }

1337 1338 1339 1340 1341 1342
    if (hit_isolate_cache_) {
      // There's probably no need to distinguish the different isolate cache
      // hits.
      return CacheBehaviour::kHitIsolateCacheWhenNoCache;
    }

1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361
    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;
1362 1363 1364 1365 1366 1367 1368 1369
      case ScriptCompiler::kNoCacheBecauseV8Extension:
        return CacheBehaviour::kNoCacheBecauseV8Extension;
      case ScriptCompiler::kNoCacheBecauseExtensionModule:
        return CacheBehaviour::kNoCacheBecauseExtensionModule;
      case ScriptCompiler::kNoCacheBecausePacScript:
        return CacheBehaviour::kNoCacheBecausePacScript;
      case ScriptCompiler::kNoCacheBecauseInDocumentWrite:
        return CacheBehaviour::kNoCacheBecauseInDocumentWrite;
1370 1371
      case ScriptCompiler::kNoCacheBecauseResourceWithNoCacheHandler:
        return CacheBehaviour::kNoCacheBecauseResourceWithNoCacheHandler;
1372 1373 1374 1375 1376 1377 1378 1379
    }
    UNREACHABLE();
  }

  TimedHistogram* GetCacheBehaviourTimedHistogram(
      CacheBehaviour cache_behaviour) {
    switch (cache_behaviour) {
      case CacheBehaviour::kProduceCodeCache:
1380 1381 1382
      // Even if we hit the isolate's compilation cache, we currently recompile
      // when we want to produce the code cache.
      case CacheBehaviour::kHitIsolateCacheWhenProduceCodeCache:
1383
        return isolate_->counters()->compile_script_with_produce_cache();
1384 1385
      case CacheBehaviour::kHitIsolateCacheWhenNoCache:
      case CacheBehaviour::kHitIsolateCacheWhenConsumeCodeCache:
1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413
        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:
1414 1415 1416 1417
      case CacheBehaviour::kNoCacheBecauseV8Extension:
      case CacheBehaviour::kNoCacheBecauseExtensionModule:
      case CacheBehaviour::kNoCacheBecausePacScript:
      case CacheBehaviour::kNoCacheBecauseInDocumentWrite:
1418
      case CacheBehaviour::kNoCacheBecauseResourceWithNoCacheHandler:
1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429
        return isolate_->counters()->compile_script_no_cache_other();

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

}  // namespace

1430 1431 1432 1433
MaybeHandle<SharedFunctionInfo> Compiler::GetSharedFunctionInfoForScript(
    Handle<String> source, MaybeHandle<Object> maybe_script_name,
    int line_offset, int column_offset, ScriptOriginOptions resource_options,
    MaybeHandle<Object> maybe_source_map_url, Handle<Context> context,
1434
    v8::Extension* extension, ScriptData** cached_data,
1435 1436
    ScriptCompiler::CompileOptions compile_options,
    ScriptCompiler::NoCacheReason no_cache_reason, NativesFlag natives,
1437
    MaybeHandle<FixedArray> maybe_host_defined_options) {
1438
  Isolate* isolate = source->GetIsolate();
1439 1440
  ScriptCompileTimerScope compile_timer(isolate, no_cache_reason);

1441
  if (compile_options == ScriptCompiler::kNoCompileOptions) {
1442
    cached_data = nullptr;
1443
  } else if (compile_options == ScriptCompiler::kProduceParserCache ||
1444
             ShouldProduceCodeCache(compile_options)) {
1445
    DCHECK(cached_data && !*cached_data);
1446
    DCHECK_NULL(extension);
1447
    DCHECK(!isolate->debug()->is_loaded());
1448
  } else {
1449
    DCHECK(compile_options == ScriptCompiler::kConsumeParserCache ||
1450
           compile_options == ScriptCompiler::kConsumeCodeCache);
1451
    DCHECK(cached_data && *cached_data);
1452
    DCHECK_NULL(extension);
1453
  }
1454 1455 1456 1457
  int source_length = source->length();
  isolate->counters()->total_load_size()->Increment(source_length);
  isolate->counters()->total_compile_size()->Increment(source_length);

1458
  LanguageMode language_mode = construct_language_mode(FLAG_use_strict);
1459 1460 1461
  CompilationCache* compilation_cache = isolate->compilation_cache();

  // Do a lookup in the compilation cache but not for extensions.
1462
  MaybeHandle<SharedFunctionInfo> maybe_result;
1463
  Handle<Cell> vector;
1464
  if (extension == nullptr) {
1465 1466 1467 1468 1469 1470 1471
    bool can_consume_code_cache =
        compile_options == ScriptCompiler::kConsumeCodeCache &&
        !isolate->debug()->is_loaded();
    if (can_consume_code_cache) {
      compile_timer.set_consuming_code_cache();
    }

1472
    // First check per-isolate compilation cache.
1473
    InfoVectorPair pair = compilation_cache->LookupScript(
1474
        source, maybe_script_name, line_offset, column_offset, resource_options,
1475
        context, language_mode);
1476
    if (can_consume_code_cache && !pair.has_shared()) {
1477
      compile_timer.set_consuming_code_cache();
1478
      // Then check cached code provided by embedder.
1479
      HistogramTimerScope timer(isolate->counters()->compile_deserialize());
1480 1481
      RuntimeCallTimerScope runtimeTimer(isolate,
                                         &RuntimeCallStats::CompileDeserialize);
1482 1483
      TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
                   "V8.CompileDeserialize");
1484
      Handle<SharedFunctionInfo> inner_result;
1485
      if (CodeSerializer::Deserialize(isolate, *cached_data, source)
1486
              .ToHandle(&inner_result)) {
1487
        // Promote to per-isolate compilation cache.
1488
        DCHECK(inner_result->is_compiled());
1489 1490
        Handle<FeedbackVector> feedback_vector =
            FeedbackVector::New(isolate, inner_result);
1491 1492 1493
        vector = isolate->factory()->NewCell(feedback_vector);
        compilation_cache->PutScript(source, context, language_mode,
                                     inner_result, vector);
1494 1495
        Handle<Script> script(Script::cast(inner_result->script()), isolate);
        isolate->debug()->OnAfterCompile(script);
1496
        return inner_result;
1497 1498
      }
      // Deserializer failed. Fall through to compile.
1499
      compile_timer.set_consuming_code_cache_failed();
1500 1501
    } else {
      if (pair.has_shared()) {
1502
        maybe_result = MaybeHandle<SharedFunctionInfo>(pair.shared(), isolate);
1503
        compile_timer.set_hit_isolate_cache();
1504 1505 1506 1507
      }
      if (pair.has_vector()) {
        vector = Handle<Cell>(pair.vector(), isolate);
      }
1508
    }
1509 1510
  }

1511
  base::ElapsedTimer timer;
1512
  if (FLAG_profile_deserialization && ShouldProduceCodeCache(compile_options)) {
1513 1514 1515
    timer.Start();
  }

1516
  if (maybe_result.is_null() || ShouldProduceCodeCache(compile_options)) {
1517
    // No cache entry found, or embedder wants a code cache. Compile the script.
1518 1519

    // Create a script object describing the script to be compiled.
1520
    Handle<Script> script = isolate->factory()->NewScript(source);
1521 1522 1523
    if (isolate->NeedsSourcePositionsForProfiling()) {
      Script::InitLineEnds(script);
    }
1524
    if (natives == NATIVES_CODE) {
1525
      script->set_type(Script::TYPE_NATIVE);
1526 1527
    } else if (natives == EXTENSION_CODE) {
      script->set_type(Script::TYPE_EXTENSION);
1528 1529
    } else if (natives == INSPECTOR_CODE) {
      script->set_type(Script::TYPE_INSPECTOR);
1530
    }
1531 1532
    Handle<Object> script_name;
    if (maybe_script_name.ToHandle(&script_name)) {
1533
      script->set_name(*script_name);
1534 1535
      script->set_line_offset(line_offset);
      script->set_column_offset(column_offset);
1536
    }
1537
    script->set_origin_options(resource_options);
1538 1539
    Handle<Object> source_map_url;
    if (maybe_source_map_url.ToHandle(&source_map_url)) {
1540 1541
      script->set_source_mapping_url(*source_map_url);
    }
1542 1543
    Handle<FixedArray> host_defined_options;
    if (maybe_host_defined_options.ToHandle(&host_defined_options)) {
1544 1545
      script->set_host_defined_options(*host_defined_options);
    }
1546 1547

    // Compile the function and add it to the cache.
1548
    ParseInfo parse_info(script);
1549
    Zone compile_zone(isolate->allocator(), ZONE_NAME);
1550
    if (resource_options.IsModule()) parse_info.set_module();
1551
    if (compile_options != ScriptCompiler::kNoCompileOptions) {
1552
      parse_info.set_cached_data(cached_data);
1553
    }
1554 1555
    parse_info.set_compile_options(compile_options);
    parse_info.set_extension(extension);
1556 1557 1558
    if (!context->IsNativeContext()) {
      parse_info.set_outer_scope_info(handle(context->scope_info()));
    }
1559 1560
    parse_info.set_eager(compile_options ==
                         ScriptCompiler::kProduceFullCodeCache);
1561

1562
    parse_info.set_language_mode(
1563
        stricter_language_mode(parse_info.language_mode(), language_mode));
1564 1565
    maybe_result = CompileToplevel(&parse_info, isolate);
    Handle<SharedFunctionInfo> result;
1566
    if (extension == nullptr && maybe_result.ToHandle(&result)) {
1567 1568
      // We need a feedback vector.
      DCHECK(result->is_compiled());
1569
      Handle<FeedbackVector> feedback_vector =
1570
          FeedbackVector::New(isolate, result);
1571 1572 1573
      vector = isolate->factory()->NewCell(feedback_vector);
      compilation_cache->PutScript(source, context, language_mode, result,
                                   vector);
1574
      if (ShouldProduceCodeCache(compile_options) &&
1575
          !ContainsAsmModule(script)) {
1576 1577
        compile_timer.set_producing_code_cache();

1578 1579
        HistogramTimerScope histogram_timer(
            isolate->counters()->compile_serialize());
1580 1581
        RuntimeCallTimerScope runtimeTimer(isolate,
                                           &RuntimeCallStats::CompileSerialize);
1582 1583
        TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
                     "V8.CompileSerialize");
1584
        *cached_data = CodeSerializer::Serialize(isolate, result, source);
1585
        if (FLAG_profile_deserialization) {
1586 1587
          PrintF("[Compiling and serializing took %0.3f ms]\n",
                 timer.Elapsed().InMillisecondsF());
1588
        }
1589
      }
1590
    }
1591

1592
    if (maybe_result.is_null()) {
1593 1594 1595
      if (natives != EXTENSION_CODE && natives != NATIVES_CODE) {
        isolate->ReportPendingMessages();
      }
1596 1597 1598
    } else {
      isolate->debug()->OnAfterCompile(script);
    }
1599
  }
1600
  return maybe_result;
1601 1602
}

1603
std::unique_ptr<CompilationJob> Compiler::CompileTopLevelOnBackgroundThread(
1604
    ParseInfo* parse_info, AccountingAllocator* allocator,
1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619
    CompilationJobList* inner_function_jobs) {
  DisallowHeapAllocation no_allocation;
  DisallowHandleAllocation no_handles;
  DisallowHandleDereference no_deref;
  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
               "V8.CompileCodeBackground");
  RuntimeCallTimerScope runtimeTimer(
      parse_info->runtime_call_stats(),
      parse_info->is_eval() ? &RuntimeCallStats::CompileBackgroundEval
                            : &RuntimeCallStats::CompileBackgroundScript);

  LanguageMode language_mode = construct_language_mode(FLAG_use_strict);
  parse_info->set_language_mode(
      stricter_language_mode(parse_info->language_mode(), language_mode));

1620 1621 1622
  // Can't access scope info data off-main-thread.
  DCHECK(!parse_info->consumed_preparsed_scope_data()->HasData());

1623 1624
  // Generate the unoptimized bytecode or asm-js data.
  std::unique_ptr<CompilationJob> outer_function_job(
1625
      GenerateUnoptimizedCode(parse_info, allocator, inner_function_jobs));
1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654
  return outer_function_job;
}

Handle<SharedFunctionInfo> Compiler::GetSharedFunctionInfoForBackgroundCompile(
    Handle<Script> script, ParseInfo* parse_info, int source_length,
    CompilationJob* outer_function_job,
    CompilationJobList* inner_function_jobs) {
  Isolate* isolate = script->GetIsolate();
  PostponeInterruptsScope postpone(isolate);

  // TODO(titzer): increment the counters in caller.
  isolate->counters()->total_load_size()->Increment(source_length);
  isolate->counters()->total_compile_size()->Increment(source_length);

  if (outer_function_job == nullptr) {
    // Compilation failed on background thread - throw an exception.
    if (!isolate->has_pending_exception()) isolate->StackOverflow();
    return Handle<SharedFunctionInfo>();
  }

  Handle<SharedFunctionInfo> result;
  if (FinalizeTopLevel(parse_info, isolate, outer_function_job,
                       inner_function_jobs)
          .ToHandle(&result)) {
    isolate->debug()->OnAfterCompile(script);
  }
  return result;
}

1655
Handle<SharedFunctionInfo> Compiler::GetSharedFunctionInfoForStreamedScript(
1656 1657 1658
    Handle<Script> script, ParseInfo* parse_info, int source_length) {
  Isolate* isolate = script->GetIsolate();
  // TODO(titzer): increment the counters in caller.
1659 1660 1661
  isolate->counters()->total_load_size()->Increment(source_length);
  isolate->counters()->total_compile_size()->Increment(source_length);

1662
  LanguageMode language_mode = construct_language_mode(FLAG_use_strict);
1663
  parse_info->set_language_mode(
1664
      stricter_language_mode(parse_info->language_mode(), language_mode));
1665

1666 1667 1668 1669
  Handle<SharedFunctionInfo> result;
  if (CompileToplevel(parse_info, isolate).ToHandle(&result)) {
    isolate->debug()->OnAfterCompile(script);
  }
1670
  return result;
1671 1672
}

1673
Handle<SharedFunctionInfo> Compiler::GetSharedFunctionInfo(
1674
    FunctionLiteral* literal, Handle<Script> script, Isolate* isolate) {
1675
  // Precondition: code has been parsed and scopes have been analyzed.
1676
  MaybeHandle<SharedFunctionInfo> maybe_existing;
1677 1678

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

1681
  // If we found an existing shared function info, return it.
1682
  Handle<SharedFunctionInfo> existing;
1683
  if (maybe_existing.ToHandle(&existing)) {
1684
    DCHECK(!existing->is_toplevel());
1685
    return existing;
1686 1687
  }

1688 1689 1690 1691 1692 1693 1694
  // Allocate a shared function info object which will be compiled lazily.
  Handle<SharedFunctionInfo> result =
      isolate->factory()->NewSharedFunctionInfoForLiteral(literal, script);
  result->set_is_toplevel(false);
  Scope* outer_scope = literal->scope()->GetOuterScopeWithContext();
  if (outer_scope) {
    result->set_outer_scope_info(*outer_scope->scope_info());
1695 1696
  }
  return result;
1697 1698
}

1699
MaybeHandle<Code> Compiler::GetOptimizedCodeForOSR(Handle<JSFunction> function,
1700
                                                   BailoutId osr_offset,
1701
                                                   JavaScriptFrame* osr_frame) {
1702
  DCHECK(!osr_offset.IsNone());
1703
  DCHECK_NOT_NULL(osr_frame);
1704
  return GetOptimizedCode(function, ConcurrencyMode::kNotConcurrent, osr_offset,
1705
                          osr_frame);
1706 1707
}

1708 1709
bool Compiler::FinalizeCompilationJob(CompilationJob* raw_job,
                                      Isolate* isolate) {
1710
  // Take ownership of compilation job.  Deleting job also tears down the zone.
1711
  std::unique_ptr<CompilationJob> job(raw_job);
1712

1713
  if (job->compilation_info()->IsOptimizing()) {
1714 1715
    VMState<COMPILER> state(isolate);
    return FinalizeOptimizedCompilationJob(job.get(), isolate) ==
1716 1717
           CompilationJob::SUCCEEDED;
  } else {
1718 1719
    VMState<BYTECODE_COMPILER> state(isolate);
    return FinalizeUnoptimizedCompilationJob(job.get(), isolate) ==
1720
           CompilationJob::SUCCEEDED;
1721
  }
1722 1723
}

1724 1725 1726 1727
void Compiler::PostInstantiation(Handle<JSFunction> function,
                                 PretenureFlag pretenure) {
  Handle<SharedFunctionInfo> shared(function->shared());

1728
  if (FLAG_always_opt && shared->allows_lazy_compilation() &&
1729 1730
      !shared->optimization_disabled() && !shared->HasAsmWasmData() &&
      shared->is_compiled()) {
1731 1732 1733 1734 1735 1736 1737 1738 1739
    // TODO(mvstanton): pass pretenure flag to EnsureLiterals.
    JSFunction::EnsureLiterals(function);

    if (!function->IsOptimized()) {
      // Only mark for optimization if we don't already have optimized code.
      if (!function->HasOptimizedCode()) {
        function->MarkForOptimization(ConcurrencyMode::kNotConcurrent);
      }
    }
1740 1741
  }

1742
  if (shared->is_compiled() && !shared->HasAsmWasmData()) {
1743 1744
    // TODO(mvstanton): pass pretenure flag to EnsureLiterals.
    JSFunction::EnsureLiterals(function);
1745 1746 1747 1748 1749 1750

    Code* code = function->feedback_vector()->optimized_code();
    if (code != nullptr) {
      // Caching of optimized code enabled and optimized code found.
      DCHECK(!code->marked_for_deoptimization());
      DCHECK(function->shared()->is_compiled());
1751
      function->set_code(code);
1752
    }
1753 1754
  }
}
1755

1756 1757
}  // namespace internal
}  // namespace v8