compiler.cc 71.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/asmjs/asm-js.h"
11
#include "src/asmjs/asm-typer.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 17 18
#include "src/bootstrapper.h"
#include "src/codegen.h"
#include "src/compilation-cache.h"
19
#include "src/compiler-dispatcher/compiler-dispatcher.h"
20
#include "src/compiler-dispatcher/optimizing-compile-dispatcher.h"
21
#include "src/compiler/pipeline.h"
22
#include "src/crankshaft/hydrogen.h"
23 24
#include "src/debug/debug.h"
#include "src/debug/liveedit.h"
25
#include "src/frames-inl.h"
26
#include "src/full-codegen/full-codegen.h"
yangguo's avatar
yangguo committed
27
#include "src/globals.h"
28
#include "src/heap/heap.h"
29
#include "src/interpreter/interpreter.h"
30
#include "src/isolate-inl.h"
31
#include "src/log-inl.h"
32
#include "src/messages.h"
33
#include "src/parsing/parsing.h"
34 35
#include "src/parsing/rewriter.h"
#include "src/parsing/scanner-character-streams.h"
36
#include "src/runtime-profiler.h"
37
#include "src/snapshot/code-serializer.h"
38
#include "src/vm-state-inl.h"
39

40 41
namespace v8 {
namespace internal {
42

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

 private:
  DeferredHandleScope deferred_;
  ParseInfo* info_;
};

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

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

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

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

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

83
// ----------------------------------------------------------------------------
84
// Implementation of CompilationJob
85

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

214 215 216 217 218 219
namespace {

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

230
}  // namespace
231

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

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

namespace {
276

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

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

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

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

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

330
bool UseTurboFan(Handle<SharedFunctionInfo> shared) {
331
  bool must_use_ignition_turbo = shared->must_use_ignition_turbo();
332 333 334

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

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

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

  return is_turbofanable_asm || is_unsupported_by_crankshaft_but_turbofanable ||
         passes_turbo_filter;
}

348 349
bool ShouldUseIgnition(Handle<SharedFunctionInfo> shared,
                       bool marked_as_debug) {
350 351
  // Code which can't be supported by the old pipeline should use Ignition.
  if (shared->must_use_ignition_turbo()) return true;
352

353 354 355
  // Resumable functions are not supported by {FullCodeGenerator}, suspended
  // activations stored as {JSGeneratorObject} on the heap always assume the
  // underlying code to be based on the bytecode array.
356
  DCHECK(!IsResumableFunction(shared->kind()));
357

358
  // Skip Ignition for asm.js functions.
359 360 361 362
  if (shared->asm_function()) return false;

  // Skip Ignition for asm wasm code.
  if (FLAG_validate_asm && shared->HasAsmWasmData()) {
363 364 365 366
    return false;
  }

  // Code destined for TurboFan should be compiled with Ignition first.
367
  if (UseTurboFan(shared)) return true;
368 369

  // Only use Ignition for any other function if FLAG_ignition is true.
370
  return FLAG_ignition;
371 372
}

373 374 375 376 377
bool ShouldUseIgnition(CompilationInfo* info) {
  DCHECK(info->has_shared_info());
  return ShouldUseIgnition(info->shared_info(), info->is_debug());
}

378 379
bool UseAsmWasm(DeclarationScope* scope, Handle<SharedFunctionInfo> shared_info,
                bool is_debug) {
380 381 382 383 384 385 386 387 388 389 390 391 392 393 394
  // 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.
  if (shared_info->is_asm_wasm_broken()) return false;

  // Compiling for debugging is not supported, fall back.
  if (is_debug) return false;

  // 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.
  return scope->asm_module();
395 396
}

397 398
bool UseCompilerDispatcher(Compiler::ConcurrencyMode inner_function_mode,
                           CompilerDispatcher* dispatcher,
399 400 401
                           DeclarationScope* scope,
                           Handle<SharedFunctionInfo> shared_info,
                           bool is_debug, bool will_serialize) {
402
  return inner_function_mode == Compiler::CONCURRENT &&
403
         dispatcher->IsEnabled() && !is_debug && !will_serialize &&
404 405 406
         !UseAsmWasm(scope, shared_info, is_debug);
}

407
CompilationJob* GetUnoptimizedCompilationJob(CompilationInfo* info) {
408 409 410 411 412 413
  // Function should have been parsed and analyzed before creating a compilation
  // job.
  DCHECK_NOT_NULL(info->literal());
  DCHECK_NOT_NULL(info->scope());

  if (ShouldUseIgnition(info)) {
414
    return interpreter::Interpreter::NewCompilationJob(info);
415
  } else {
416
    return FullCodeGenerator::NewCompilationJob(info);
417 418 419
  }
}

420 421
void InstallSharedScopeInfo(CompilationInfo* info,
                            Handle<SharedFunctionInfo> shared) {
422
  Handle<ScopeInfo> scope_info = info->scope()->scope_info();
423
  shared->set_scope_info(*scope_info);
424 425 426 427
  Scope* outer_scope = info->scope()->GetOuterScopeWithContext();
  if (outer_scope) {
    shared->set_outer_scope_info(*outer_scope->scope_info());
  }
428 429 430 431
}

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

446 447 448 449 450 451 452 453
void InstallUnoptimizedCode(CompilationInfo* info) {
  Handle<SharedFunctionInfo> shared = info->shared_info();

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

  // Install compilation result on the shared function info
  InstallSharedCompilationResult(info, shared);
454
}
455

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

472 473 474
void SetSharedFunctionFlagsFromLiteral(FunctionLiteral* literal,
                                       Handle<SharedFunctionInfo> shared_info) {
  shared_info->set_ast_node_count(literal->ast_node_count());
475 476
  shared_info->set_has_duplicate_parameters(
      literal->has_duplicate_parameters());
477
  shared_info->SetExpectedNofPropertiesFromEstimate(literal);
478 479 480 481 482 483 484 485
  if (literal->dont_optimize_reason() != kNoReason) {
    shared_info->DisableOptimization(literal->dont_optimize_reason());
  }
  if (literal->flags() & AstProperties::kMustUseIgnitionTurbo) {
    shared_info->set_must_use_ignition_turbo(true);
  }
}

486
bool Renumber(ParseInfo* parse_info,
487
              Compiler::EagerInnerFunctionLiterals* eager_literals) {
488
  RuntimeCallTimerScope runtimeTimer(parse_info->runtime_call_stats(),
489
                                     &RuntimeCallStats::CompileRenumber);
490 491 492 493 494 495 496

  // CollectTypeProfile uses its own feedback slots. If we have existing
  // FeedbackMetadata, we can only collect type profile, if the feedback vector
  // has the appropriate slots.
  bool collect_type_profile;
  if (parse_info->shared_info().is_null() ||
      parse_info->shared_info()->feedback_metadata()->length() == 0) {
497 498
    collect_type_profile =
        FLAG_type_profile && parse_info->script()->IsUserJavaScript();
499 500 501 502 503
  } else {
    collect_type_profile =
        parse_info->shared_info()->feedback_metadata()->HasTypeProfileSlot();
  }

504 505 506
  if (!AstNumbering::Renumber(parse_info->stack_limit(), parse_info->zone(),
                              parse_info->literal(), eager_literals,
                              collect_type_profile)) {
507 508
    return false;
  }
509 510 511
  if (!parse_info->shared_info().is_null()) {
    SetSharedFunctionFlagsFromLiteral(parse_info->literal(),
                                      parse_info->shared_info());
512 513 514 515
  }
  return true;
}

516
bool GenerateUnoptimizedCode(CompilationInfo* info) {
517
  if (UseAsmWasm(info->scope(), info->shared_info(), info->is_debug())) {
518 519
    EnsureFeedbackMetadata(info);
    MaybeHandle<FixedArray> wasm_data;
520
    wasm_data = AsmJs::CompileAsmViaWasm(info);
521 522 523 524 525 526 527 528
    if (!wasm_data.is_null()) {
      info->shared_info()->set_asm_wasm_data(*wasm_data.ToHandleChecked());
      info->SetCode(info->isolate()->builtins()->InstantiateAsmJs());
      InstallUnoptimizedCode(info);
      return true;
    }
  }

529
  std::unique_ptr<CompilationJob> job(GetUnoptimizedCompilationJob(info));
530 531 532 533 534 535 536 537 538
  if (job->PrepareJob() != CompilationJob::SUCCEEDED) return false;
  if (job->ExecuteJob() != CompilationJob::SUCCEEDED) return false;
  if (FinalizeUnoptimizedCompilationJob(job.get()) !=
      CompilationJob::SUCCEEDED) {
    return false;
  }
  return true;
}

539
bool CompileUnoptimizedInnerFunctions(
540
    Compiler::EagerInnerFunctionLiterals* literals,
541
    Compiler::ConcurrencyMode inner_function_mode,
542
    std::shared_ptr<Zone> parse_zone, CompilationInfo* outer_info) {
543 544
  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
               "V8.CompileUnoptimizedInnerFunctions");
545 546
  Isolate* isolate = outer_info->isolate();
  Handle<Script> script = outer_info->script();
547 548
  bool is_debug = outer_info->is_debug();
  bool will_serialize = outer_info->will_serialize();
549 550 551 552 553
  RuntimeCallTimerScope runtimeTimer(isolate,
                                     &RuntimeCallStats::CompileInnerFunction);

  for (auto it : *literals) {
    FunctionLiteral* literal = it->value();
554 555 556
    Handle<SharedFunctionInfo> shared =
        Compiler::GetSharedFunctionInfo(literal, script, outer_info);
    if (shared->is_compiled()) continue;
557

558 559 560
    // The {literal} has already been numbered because AstNumbering decends into
    // eagerly compiled function literals.
    SetSharedFunctionFlagsFromLiteral(literal, shared);
561

562 563
    // Try to enqueue the eager function on the compiler dispatcher.
    CompilerDispatcher* dispatcher = isolate->compiler_dispatcher();
564 565
    if (UseCompilerDispatcher(inner_function_mode, dispatcher, literal->scope(),
                              shared, is_debug, will_serialize) &&
566 567
        dispatcher->EnqueueAndStep(outer_info->script(), shared, literal,
                                   parse_zone,
568 569
                                   outer_info->parse_info()->deferred_handles(),
                                   outer_info->deferred_handles())) {
570 571 572 573 574
      // If we have successfully queued up the function for compilation on the
      // compiler dispatcher then we are done.
      continue;
    } else {
      // Otherwise generate unoptimized code now.
575
      ParseInfo parse_info(script);
576
      CompilationInfo info(parse_info.zone(), &parse_info, isolate,
577
                           Handle<JSFunction>::null());
578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593

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

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

      if (!GenerateUnoptimizedCode(&info)) {
        if (!isolate->has_pending_exception()) isolate->StackOverflow();
        return false;
      }
594 595 596 597 598
    }
  }
  return true;
}

599 600 601 602 603 604 605 606 607 608 609
bool InnerFunctionIsAsmModule(
    ThreadedList<ThreadedListZoneEntry<FunctionLiteral*>>* literals) {
  for (auto it : *literals) {
    FunctionLiteral* literal = it->value();
    if (literal->scope()->IsAsmModule()) return true;
  }
  return false;
}

bool CompileUnoptimizedCode(CompilationInfo* info,
                            Compiler::ConcurrencyMode inner_function_mode) {
610 611 612 613
  Isolate* isolate = info->isolate();
  DCHECK(AllowCompilation::IsAllowed(isolate));

  Compiler::EagerInnerFunctionLiterals inner_literals;
614 615 616 617 618
  {
    std::unique_ptr<CompilationHandleScope> compilation_handle_scope;
    if (inner_function_mode == Compiler::CONCURRENT) {
      compilation_handle_scope.reset(new CompilationHandleScope(info));
    }
619
    if (!Compiler::Analyze(info, &inner_literals)) {
620 621 622
      if (!isolate->has_pending_exception()) isolate->StackOverflow();
      return false;
    }
623 624 625 626 627 628 629 630 631 632
  }

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

633
  std::shared_ptr<Zone> parse_zone;
634 635 636 637
  if (inner_function_mode == Compiler::CONCURRENT) {
    // Seal the parse zone so that it can be shared by parallel inner function
    // compilation jobs.
    DCHECK_NE(info->parse_info()->zone(), info->zone());
638 639
    parse_zone = info->parse_info()->zone_shared();
    parse_zone->Seal();
640 641 642
  }

  if (!CompileUnoptimizedInnerFunctions(&inner_literals, inner_function_mode,
643
                                        parse_zone, info) ||
644 645 646 647
      !GenerateUnoptimizedCode(info)) {
    if (!isolate->has_pending_exception()) isolate->StackOverflow();
    return false;
  }
648

649
  return true;
650 651
}

652
void EnsureSharedFunctionInfosArrayOnScript(ParseInfo* info, Isolate* isolate) {
653 654 655 656 657 658 659 660 661 662 663 664
  DCHECK(info->is_toplevel());
  DCHECK(!info->script().is_null());
  if (info->script()->shared_function_infos()->length() > 0) {
    DCHECK_EQ(info->script()->shared_function_infos()->length(),
              info->max_function_literal_id() + 1);
    return;
  }
  Handle<FixedArray> infos(
      isolate->factory()->NewFixedArray(info->max_function_literal_id() + 1));
  info->script()->set_shared_function_infos(*infos);
}

665 666 667 668 669
void EnsureSharedFunctionInfosArrayOnScript(CompilationInfo* info) {
  return EnsureSharedFunctionInfosArrayOnScript(info->parse_info(),
                                                info->isolate());
}

670 671
MUST_USE_RESULT MaybeHandle<Code> GetUnoptimizedCode(
    CompilationInfo* info, Compiler::ConcurrencyMode inner_function_mode) {
672 673
  RuntimeCallTimerScope runtimeTimer(
      info->isolate(), &RuntimeCallStats::CompileGetUnoptimizedCode);
674 675
  VMState<COMPILER> state(info->isolate());
  PostponeInterruptsScope postpone(info->isolate());
676

677 678
  // Parse and update ParseInfo with the results.
  {
679
    if (!parsing::ParseAny(info->parse_info(), info->isolate(),
680 681 682 683 684
                           inner_function_mode != Compiler::CONCURRENT)) {
      return MaybeHandle<Code>();
    }

    if (inner_function_mode == Compiler::CONCURRENT) {
685
      ParseHandleScope parse_handles(info->parse_info(), info->isolate());
686 687 688 689 690
      info->parse_info()->ReopenHandlesInNewHandleScope();
      info->parse_info()->ast_value_factory()->Internalize(info->isolate());
    }
  }

691
  if (info->parse_info()->is_toplevel()) {
692
    EnsureSharedFunctionInfosArrayOnScript(info);
693
  }
694 695
  DCHECK_EQ(info->shared_info()->language_mode(),
            info->literal()->language_mode());
696

697
  // Compile either unoptimized code or bytecode for the interpreter.
698 699 700
  if (!CompileUnoptimizedCode(info, inner_function_mode)) {
    return MaybeHandle<Code>();
  }
701

702 703
  // Record the function compilation event.
  RecordFunctionCompilation(CodeEventListener::LAZY_COMPILE_TAG, info);
704

705 706
  return info->code();
}
707

708
MUST_USE_RESULT MaybeHandle<Code> GetCodeFromOptimizedCodeMap(
709
    Handle<JSFunction> function, BailoutId osr_ast_id) {
710 711 712
  RuntimeCallTimerScope runtimeTimer(
      function->GetIsolate(),
      &RuntimeCallStats::CompileGetFromOptimizedCodeMap);
713 714
  Handle<SharedFunctionInfo> shared(function->shared());
  DisallowHeapAllocation no_gc;
715
  Code* code = shared->SearchOptimizedCodeMap(
716
      function->context()->native_context(), osr_ast_id);
717
  if (code != nullptr) {
718
    // Caching of optimized code enabled and optimized code found.
719
    DCHECK(!code->marked_for_deoptimization());
720
    DCHECK(function->shared()->is_compiled());
721
    return Handle<Code>(code);
722 723 724 725
  }
  return MaybeHandle<Code>();
}

726
void InsertCodeIntoOptimizedCodeMap(CompilationInfo* info) {
727 728 729
  Handle<Code> code = info->code();
  if (code->kind() != Code::OPTIMIZED_FUNCTION) return;  // Nothing to do.

730 731
  // Function context specialization folds-in the function context,
  // so no sharing can occur.
732 733
  if (info->is_function_context_specializing()) return;
  // Frame specialization implies function context specialization.
734
  DCHECK(!info->is_frame_specializing());
735

736
  // Cache optimized context-specific code.
737
  Handle<JSFunction> function = info->closure();
738 739 740
  Handle<SharedFunctionInfo> shared(function->shared());
  Handle<Context> native_context(function->context()->native_context());
  SharedFunctionInfo::AddToOptimizedCodeMap(shared, native_context, code,
741
                                            info->osr_ast_id());
742 743
}

744
bool GetOptimizedCodeNow(CompilationJob* job) {
745
  CompilationInfo* info = job->info();
746
  Isolate* isolate = info->isolate();
747 748

  // Parsing is not required when optimizing from existing bytecode.
749
  if (!info->is_optimizing_from_bytecode()) {
750
    if (!Compiler::ParseAndAnalyze(info)) return false;
751
    EnsureFeedbackMetadata(info);
752
  }
753

754 755
  JSFunction::EnsureLiterals(info->closure());

756
  TimerEventScope<TimerEventRecompileSynchronous> timer(isolate);
757 758
  RuntimeCallTimerScope runtimeTimer(isolate,
                                     &RuntimeCallStats::RecompileSynchronous);
759 760
  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
               "V8.RecompileSynchronous");
761

762 763 764
  if (job->PrepareJob() != CompilationJob::SUCCEEDED ||
      job->ExecuteJob() != CompilationJob::SUCCEEDED ||
      job->FinalizeJob() != CompilationJob::SUCCEEDED) {
765 766 767 768 769 770 771
    if (FLAG_trace_opt) {
      PrintF("[aborted optimizing ");
      info->closure()->ShortPrint();
      PrintF(" because: %s]\n", GetBailoutReason(info->bailout_reason()));
    }
    return false;
  }
772 773

  // Success!
774
  job->RecordOptimizedCompilationStats();
775
  DCHECK(!isolate->has_pending_exception());
776
  InsertCodeIntoOptimizedCodeMap(info);
777
  RecordFunctionCompilation(CodeEventListener::LAZY_COMPILE_TAG, info);
778 779 780
  return true;
}

781
bool GetOptimizedCodeLater(CompilationJob* job) {
782
  CompilationInfo* info = job->info();
783
  Isolate* isolate = info->isolate();
784

785 786 787 788 789 790 791 792 793 794
  if (FLAG_mark_optimizing_shared_functions &&
      info->closure()->shared()->has_concurrent_optimization_job()) {
    if (FLAG_trace_concurrent_recompilation) {
      PrintF("  ** Compilation job already running for ");
      info->shared_info()->ShortPrint();
      PrintF(".\n");
    }
    return false;
  }

795
  if (!isolate->optimizing_compile_dispatcher()->IsQueueAvailable()) {
796 797
    if (FLAG_trace_concurrent_recompilation) {
      PrintF("  ** Compilation queue full, will retry optimizing ");
798
      info->closure()->ShortPrint();
799 800 801 802 803
      PrintF(" later.\n");
    }
    return false;
  }

804 805 806 807 808 809 810 811 812
  if (isolate->heap()->HighMemoryPressure()) {
    if (FLAG_trace_concurrent_recompilation) {
      PrintF("  ** High memory pressure, will retry optimizing ");
      info->closure()->ShortPrint();
      PrintF(" later.\n");
    }
    return false;
  }

813
  // Parsing is not required when optimizing from existing bytecode.
814
  if (!info->is_optimizing_from_bytecode()) {
815
    if (!Compiler::ParseAndAnalyze(info)) return false;
816
    EnsureFeedbackMetadata(info);
817
  }
818

819 820
  JSFunction::EnsureLiterals(info->closure());

821
  TimerEventScope<TimerEventRecompileSynchronous> timer(info->isolate());
822 823
  RuntimeCallTimerScope runtimeTimer(info->isolate(),
                                     &RuntimeCallStats::RecompileSynchronous);
824 825
  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
               "V8.RecompileSynchronous");
826

827
  if (job->PrepareJob() != CompilationJob::SUCCEEDED) return false;
828
  isolate->optimizing_compile_dispatcher()->QueueForOptimization(job);
829
  info->closure()->shared()->set_has_concurrent_optimization_job(true);
830 831 832

  if (FLAG_trace_concurrent_recompilation) {
    PrintF("  ** Queued ");
833
    info->closure()->ShortPrint();
834
    PrintF(" for concurrent optimization.\n");
835 836 837 838
  }
  return true;
}

839 840 841 842 843 844 845
MaybeHandle<Code> GetOptimizedCode(Handle<JSFunction> function,
                                   Compiler::ConcurrencyMode mode,
                                   BailoutId osr_ast_id = BailoutId::None(),
                                   JavaScriptFrame* osr_frame = nullptr) {
  Isolate* isolate = function->GetIsolate();
  Handle<SharedFunctionInfo> shared(function->shared(), isolate);

846 847 848 849
  bool ignition_osr = osr_frame && osr_frame->is_interpreted();
  DCHECK_IMPLIES(ignition_osr, !osr_ast_id.IsNone());
  DCHECK_IMPLIES(ignition_osr, FLAG_ignition_osr);

850
  Handle<Code> cached_code;
851
  if (GetCodeFromOptimizedCodeMap(function, osr_ast_id)
852 853 854 855 856 857 858 859 860 861 862 863
          .ToHandle(&cached_code)) {
    if (FLAG_trace_opt) {
      PrintF("[found optimized code for ");
      function->ShortPrint();
      if (!osr_ast_id.IsNone()) {
        PrintF(" at OSR AST id %d", osr_ast_id.ToInt());
      }
      PrintF("]\n");
    }
    return cached_code;
  }

864
  // Reset profiler ticks, function is no longer considered hot.
865
  DCHECK(shared->is_compiled());
866
  if (shared->HasBaselineCode()) {
867
    shared->code()->set_profiler_ticks(0);
868 869
  } else if (shared->HasBytecodeArray()) {
    shared->set_profiler_ticks(0);
870 871 872 873 874
  }

  VMState<COMPILER> state(isolate);
  DCHECK(!isolate->has_pending_exception());
  PostponeInterruptsScope postpone(isolate);
875
  bool use_turbofan = UseTurboFan(shared) || ignition_osr;
876 877 878 879
  bool has_script = shared->script()->IsScript();
  // 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, ShouldUseIgnition(shared, false));
880
  std::unique_ptr<CompilationJob> job(
881
      use_turbofan ? compiler::Pipeline::NewCompilationJob(function, has_script)
882 883
                   : new HCompilationJob(function));
  CompilationInfo* info = job->info();
884
  ParseInfo* parse_info = info->parse_info();
885

886
  info->SetOptimizingForOsr(osr_ast_id, osr_frame);
887

888 889 890 891 892 893
  // Do not use Crankshaft/TurboFan if we need to be able to set break points.
  if (info->shared_info()->HasDebugInfo()) {
    info->AbortOptimization(kFunctionBeingDebugged);
    return MaybeHandle<Code>();
  }

894 895 896 897 898 899 900
  // Do not use Crankshaft/TurboFan when %NeverOptimizeFunction was applied.
  if (shared->optimization_disabled() &&
      shared->disable_optimization_reason() == kOptimizationDisabledForTest) {
    info->AbortOptimization(kOptimizationDisabledForTest);
    return MaybeHandle<Code>();
  }

901
  // Limit the number of times we try to optimize functions.
902 903 904
  const int kMaxDeoptCount =
      FLAG_deopt_every_n_times == 0 ? FLAG_max_deopt_count : 1000;
  if (info->shared_info()->deopt_count() > kMaxDeoptCount) {
905
    info->AbortOptimization(kDeoptimizedTooManyTimes);
906 907 908
    return MaybeHandle<Code>();
  }

909
  TimerEventScope<TimerEventOptimizeCode> optimize_code_timer(isolate);
910
  RuntimeCallTimerScope runtimeTimer(isolate, &RuntimeCallStats::OptimizeCode);
911
  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.OptimizeCode");
912

913
  // TurboFan can optimize directly from existing bytecode.
914
  if (use_turbofan && ShouldUseIgnition(info)) {
915
    DCHECK(shared->HasBytecodeArray());
916 917 918
    info->MarkAsOptimizeFromBytecode();
  }

919 920 921 922 923 924 925 926 927 928
  // Verify that OSR compilations are delegated to the correct graph builder.
  // Depending on the underlying frame the semantics of the {BailoutId} differ
  // and the various graph builders hard-code a certain semantic:
  //  - Interpreter : The BailoutId represents a bytecode offset.
  //  - FullCodegen : The BailoutId represents the id of an AST node.
  DCHECK_IMPLIES(info->is_osr() && ignition_osr,
                 info->is_optimizing_from_bytecode());
  DCHECK_IMPLIES(info->is_osr() && !ignition_osr,
                 !info->is_optimizing_from_bytecode());

929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944
  // In case of concurrent recompilation, all handles below this point will be
  // allocated in a deferred handle scope that is detached and handed off to
  // the background thread when we return.
  std::unique_ptr<CompilationHandleScope> compilation;
  if (mode == Compiler::CONCURRENT) {
    compilation.reset(new CompilationHandleScope(info));
  }

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

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

945
  if (mode == Compiler::CONCURRENT) {
946
    if (GetOptimizedCodeLater(job.get())) {
947
      job.release();  // The background recompile job owns this now.
948 949 950
      return isolate->builtins()->InOptimizationQueue();
    }
  } else {
951
    if (GetOptimizedCodeNow(job.get())) return info->code();
952 953 954 955 956 957
  }

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

958 959 960 961 962 963 964
MaybeHandle<Code> GetOptimizedCodeMaybeLater(Handle<JSFunction> function) {
  Isolate* isolate = function->GetIsolate();
  return GetOptimizedCode(function, isolate->concurrent_recompilation_enabled()
                                        ? Compiler::CONCURRENT
                                        : Compiler::NOT_CONCURRENT);
}

965 966 967 968 969 970 971
CompilationJob::Status FinalizeOptimizedCompilationJob(CompilationJob* job) {
  CompilationInfo* info = job->info();
  Isolate* isolate = info->isolate();

  TimerEventScope<TimerEventRecompileSynchronous> timer(info->isolate());
  RuntimeCallTimerScope runtimeTimer(isolate,
                                     &RuntimeCallStats::RecompileSynchronous);
972 973
  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
               "V8.RecompileSynchronous");
974 975

  Handle<SharedFunctionInfo> shared = info->shared_info();
976 977 978 979 980 981 982

  // Reset profiler ticks, function is no longer considered hot.
  if (shared->HasBaselineCode()) {
    shared->code()->set_profiler_ticks(0);
  } else if (shared->HasBytecodeArray()) {
    shared->set_profiler_ticks(0);
  }
983

984 985 986 987 988
  shared->set_has_concurrent_optimization_job(false);

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

989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003
  DCHECK(!shared->HasDebugInfo());

  // 1) Optimization on the concurrent thread may have failed.
  // 2) The function may have already been optimized by OSR.  Simply continue.
  //    Except when OSR already disabled optimization for some reason.
  // 3) The code may have already been invalidated due to dependency change.
  // 4) Code generation may have failed.
  if (job->state() == CompilationJob::State::kReadyToFinalize) {
    if (shared->optimization_disabled()) {
      job->RetryOptimization(kOptimizationDisabled);
    } else if (info->dependencies()->HasAborted()) {
      job->RetryOptimization(kBailedOutDueToDependencyChange);
    } else if (job->FinalizeJob() == CompilationJob::SUCCEEDED) {
      job->RecordOptimizedCompilationStats();
      RecordFunctionCompilation(CodeEventListener::LAZY_COMPILE_TAG, info);
1004 1005
      if (shared->SearchOptimizedCodeMap(info->context()->native_context(),
                                         info->osr_ast_id()) == nullptr) {
1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027
        InsertCodeIntoOptimizedCodeMap(info);
      }
      if (FLAG_trace_opt) {
        PrintF("[completed optimizing ");
        info->closure()->ShortPrint();
        PrintF("]\n");
      }
      info->closure()->ReplaceCode(*info->code());
      return CompilationJob::SUCCEEDED;
    }
  }

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

1028
MaybeHandle<Code> GetLazyCode(Handle<JSFunction> function) {
1029 1030
  Isolate* isolate = function->GetIsolate();
  DCHECK(!isolate->has_pending_exception());
1031
  DCHECK(!function->is_compiled());
1032
  TimerEventScope<TimerEventCompileCode> compile_timer(isolate);
1033 1034
  RuntimeCallTimerScope runtimeTimer(isolate,
                                     &RuntimeCallStats::CompileFunction);
1035
  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.CompileCode");
1036
  AggregatedHistogramTimerScope timer(isolate->counters()->compile_lazy());
1037

1038 1039 1040 1041 1042 1043 1044
  Handle<Code> cached_code;
  if (GetCodeFromOptimizedCodeMap(function, BailoutId::None())
          .ToHandle(&cached_code)) {
    if (FLAG_trace_opt) {
      PrintF("[found optimized code for ");
      function->ShortPrint();
      PrintF(" during unoptimized compile]\n");
1045
    }
1046 1047
    DCHECK(function->shared()->is_compiled());
    return cached_code;
1048 1049
  }

1050 1051
  if (function->shared()->is_compiled() &&
      function->shared()->marked_for_tier_up()) {
1052
    DCHECK(FLAG_mark_shared_functions_for_tier_up);
1053

1054
    function->shared()->set_marked_for_tier_up(false);
1055

1056 1057 1058 1059 1060
    if (FLAG_trace_opt) {
      PrintF("[optimizing method ");
      function->ShortPrint();
      PrintF(" eagerly (shared function marked for tier up)]\n");
    }
1061

1062 1063 1064
    Handle<Code> code;
    if (GetOptimizedCodeMaybeLater(function).ToHandle(&code)) {
      return code;
1065 1066 1067
    }
  }

1068 1069 1070 1071
  if (function->shared()->is_compiled()) {
    return Handle<Code>(function->shared()->code());
  }

1072 1073 1074 1075 1076 1077
  if (function->shared()->HasBytecodeArray()) {
    Handle<Code> entry = isolate->builtins()->InterpreterEntryTrampoline();
    function->shared()->ReplaceCode(*entry);
    return entry;
  }

1078
  ParseInfo parse_info(handle(function->shared()));
1079
  Zone compile_zone(isolate->allocator(), ZONE_NAME);
1080
  CompilationInfo info(&compile_zone, &parse_info, isolate, function);
1081 1082 1083 1084 1085 1086 1087 1088
  if (FLAG_preparser_scope_analysis) {
    Handle<SharedFunctionInfo> shared(function->shared());
    Handle<Script> script(Script::cast(function->shared()->script()));
    if (script->HasPreparsedScopeData()) {
      parse_info.preparsed_scope_data()->Deserialize(
          script->GetPreparsedScopeData());
    }
  }
1089 1090 1091
  Compiler::ConcurrencyMode inner_function_mode =
      FLAG_compiler_dispatcher_eager_inner ? Compiler::CONCURRENT
                                           : Compiler::NOT_CONCURRENT;
1092
  Handle<Code> result;
1093
  ASSIGN_RETURN_ON_EXCEPTION(
1094
      isolate, result, GetUnoptimizedCode(&info, inner_function_mode), Code);
1095

1096
  if (FLAG_always_opt && !info.shared_info()->HasAsmWasmData()) {
1097
    Handle<Code> opt_code;
1098
    if (GetOptimizedCode(function, Compiler::NOT_CONCURRENT)
1099
            .ToHandle(&opt_code)) {
1100 1101
      result = opt_code;
    }
1102
  }
1103

1104 1105
  return result;
}
1106

1107

1108
Handle<SharedFunctionInfo> CompileToplevel(CompilationInfo* info) {
1109
  Isolate* isolate = info->isolate();
1110
  TimerEventScope<TimerEventCompileCode> timer(isolate);
1111
  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.CompileCode");
1112
  PostponeInterruptsScope postpone(isolate);
1113
  DCHECK(!isolate->native_context().is_null());
1114
  ParseInfo* parse_info = info->parse_info();
1115 1116 1117
  Compiler::ConcurrencyMode inner_function_mode =
      FLAG_compiler_dispatcher_eager_inner ? Compiler::CONCURRENT
                                           : Compiler::NOT_CONCURRENT;
1118 1119 1120 1121 1122

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

1123
  Handle<Script> script = parse_info->script();
1124 1125 1126 1127

  Handle<SharedFunctionInfo> result;

  { VMState<COMPILER> state(info->isolate());
1128
    if (parse_info->literal() == nullptr) {
1129 1130
      if (!parsing::ParseProgram(parse_info, info->isolate(),
                                 inner_function_mode != Compiler::CONCURRENT)) {
1131 1132 1133
        return Handle<SharedFunctionInfo>::null();
      }

1134
      if (inner_function_mode == Compiler::CONCURRENT) {
1135
        ParseHandleScope parse_handles(parse_info, info->isolate());
1136 1137 1138
        parse_info->ReopenHandlesInNewHandleScope();
        parse_info->ast_value_factory()->Internalize(info->isolate());
      }
1139 1140
    }

1141
    EnsureSharedFunctionInfosArrayOnScript(info);
1142

1143 1144 1145
    // 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.
1146 1147 1148
    HistogramTimer* rate = parse_info->is_eval()
                               ? info->isolate()->counters()->compile_eval()
                               : info->isolate()->counters()->compile();
1149
    HistogramTimerScope timer(rate);
1150 1151
    TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
                 parse_info->is_eval() ? "V8.CompileEval" : "V8.Compile");
1152

1153
    // Allocate a shared function info object.
1154
    FunctionLiteral* lit = parse_info->literal();
yangguo's avatar
yangguo committed
1155
    DCHECK_EQ(kNoSourcePosition, lit->function_token_position());
1156
    result = isolate->factory()->NewSharedFunctionInfoForLiteral(lit, script);
1157
    result->set_is_toplevel(true);
1158
    parse_info->set_shared_info(result);
1159
    parse_info->set_function_literal_id(result->function_literal_id());
1160

1161
    // Compile the code.
1162
    if (!CompileUnoptimizedCode(info, inner_function_mode)) {
1163 1164 1165
      return Handle<SharedFunctionInfo>::null();
    }

1166 1167 1168 1169
    Handle<String> script_name =
        script->name()->IsString()
            ? Handle<String>(String::cast(script->name()))
            : isolate->factory()->empty_string();
1170
    CodeEventListener::LogEventsAndTags log_tag =
1171
        parse_info->is_eval()
1172 1173
            ? CodeEventListener::EVAL_TAG
            : Logger::ToNativeByScript(CodeEventListener::SCRIPT_TAG, *script);
1174

1175
    PROFILE(isolate, CodeCreateEvent(log_tag, result->abstract_code(), *result,
1176
                                     *script_name));
1177

1178
    if (!script.is_null()) {
1179
      script->set_compilation_state(Script::COMPILATION_STATE_COMPILED);
1180 1181 1182 1183 1184 1185
      if (FLAG_preparser_scope_analysis) {
        Handle<FixedUint32Array> data(
            parse_info->preparsed_scope_data()->Serialize(isolate));
        script->set_preparsed_scope_data(*data);
      }
    }
1186 1187 1188 1189 1190
  }

  return result;
}

1191 1192 1193 1194 1195
}  // namespace

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

1196
bool Compiler::Analyze(ParseInfo* info, Isolate* isolate,
1197
                       EagerInnerFunctionLiterals* eager_literals) {
1198
  DCHECK_NOT_NULL(info->literal());
1199
  RuntimeCallTimerScope runtimeTimer(isolate,
1200
                                     &RuntimeCallStats::CompileAnalyse);
1201
  if (!Rewriter::Rewrite(info, isolate)) return false;
1202
  DeclarationScope::Analyze(info, isolate, AnalyzeMode::kRegular);
1203 1204 1205
  if (!Renumber(info, eager_literals)) {
    return false;
  }
1206 1207 1208 1209
  DCHECK_NOT_NULL(info->scope());
  return true;
}

1210 1211 1212 1213 1214 1215
bool Compiler::Analyze(CompilationInfo* info,
                       EagerInnerFunctionLiterals* eager_literals) {
  return Compiler::Analyze(info->parse_info(), info->isolate(), eager_literals);
}

bool Compiler::ParseAndAnalyze(ParseInfo* info, Isolate* isolate) {
1216
  if (!parsing::ParseAny(info, isolate)) return false;
1217 1218 1219 1220
  if (info->is_toplevel()) {
    EnsureSharedFunctionInfosArrayOnScript(info, isolate);
  }
  if (!Compiler::Analyze(info, isolate)) return false;
1221 1222 1223
  DCHECK_NOT_NULL(info->literal());
  DCHECK_NOT_NULL(info->scope());
  return true;
1224 1225
}

1226 1227 1228 1229
bool Compiler::ParseAndAnalyze(CompilationInfo* info) {
  return Compiler::ParseAndAnalyze(info->parse_info(), info->isolate());
}

1230 1231
bool Compiler::Compile(Handle<JSFunction> function, ClearExceptionFlag flag) {
  if (function->is_compiled()) return true;
1232 1233
  Isolate* isolate = function->GetIsolate();
  DCHECK(AllowCompilation::IsAllowed(isolate));
1234

1235 1236
  CompilerDispatcher* dispatcher = isolate->compiler_dispatcher();
  Handle<SharedFunctionInfo> shared(function->shared(), isolate);
1237
  Handle<Code> code;
1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252
  if (dispatcher->IsEnqueued(shared)) {
    if (!dispatcher->FinishNow(shared)) {
      if (flag == CLEAR_EXCEPTION) {
        isolate->clear_pending_exception();
      }
      return false;
    }
    code = handle(shared->code(), isolate);
  } else {
    // Start a compilation.
    if (!GetLazyCode(function).ToHandle(&code)) {
      if (flag == CLEAR_EXCEPTION) {
        isolate->clear_pending_exception();
      }
      return false;
1253 1254
    }
  }
1255

1256
  // Install code on closure.
1257
  function->ReplaceCode(*code);
1258
  JSFunction::EnsureLiterals(function);
1259 1260 1261 1262

  // Check postconditions on success.
  DCHECK(!isolate->has_pending_exception());
  DCHECK(function->shared()->is_compiled());
1263 1264 1265 1266 1267 1268
  DCHECK(function->is_compiled());
  return true;
}

bool Compiler::CompileOptimized(Handle<JSFunction> function,
                                ConcurrencyMode mode) {
1269 1270 1271 1272 1273
  if (function->IsOptimized()) return true;
  Isolate* isolate = function->GetIsolate();
  DCHECK(AllowCompilation::IsAllowed(isolate));

  // Start a compilation.
1274
  Handle<Code> code;
1275
  if (!GetOptimizedCode(function, mode).ToHandle(&code)) {
1276 1277
    // Optimization failed, get unoptimized code. Unoptimized code must exist
    // already if we are optimizing.
1278
    DCHECK(!isolate->has_pending_exception());
1279 1280
    DCHECK(function->shared()->is_compiled());
    code = handle(function->shared()->code(), isolate);
1281 1282
  }

1283 1284
  // Install code on closure.
  function->ReplaceCode(*code);
1285
  JSFunction::EnsureLiterals(function);
1286 1287 1288 1289 1290

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

bool Compiler::CompileDebugCode(Handle<SharedFunctionInfo> shared) {
1295 1296 1297 1298
  Isolate* isolate = shared->GetIsolate();
  DCHECK(AllowCompilation::IsAllowed(isolate));

  // Start a compilation.
1299
  ParseInfo parse_info(shared);
1300
  CompilationInfo info(parse_info.zone(), &parse_info, isolate,
1301
                       Handle<JSFunction>::null());
1302
  info.MarkAsDebug();
1303
  if (GetUnoptimizedCode(&info, Compiler::NOT_CONCURRENT).is_null()) {
1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314
    isolate->clear_pending_exception();
    return false;
  }

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

1315
MaybeHandle<JSArray> Compiler::CompileForLiveEdit(Handle<Script> script) {
1316 1317 1318
  Isolate* isolate = script->GetIsolate();
  DCHECK(AllowCompilation::IsAllowed(isolate));

1319 1320 1321
  // 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.
1322 1323 1324
  Handle<FixedArray> old_function_infos(script->shared_function_infos(),
                                        isolate);
  script->set_shared_function_infos(isolate->heap()->empty_fixed_array());
1325

1326
  // Start a compilation.
1327
  ParseInfo parse_info(script);
1328
  Zone compile_zone(isolate->allocator(), ZONE_NAME);
1329 1330
  CompilationInfo info(&compile_zone, &parse_info, isolate,
                       Handle<JSFunction>::null());
1331
  info.MarkAsDebug();
1332

1333
  // TODO(635): support extensions.
1334
  const bool compilation_succeeded = !CompileToplevel(&info).is_null();
1335 1336 1337 1338 1339
  Handle<JSArray> infos;
  if (compilation_succeeded) {
    // Check postconditions on success.
    DCHECK(!isolate->has_pending_exception());
    infos = LiveEditFunctionTracker::Collect(parse_info.literal(), script,
1340
                                             parse_info.zone(), isolate);
1341
  }
1342 1343 1344 1345 1346 1347

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

1348
  return infos;
1349 1350
}

1351
bool Compiler::EnsureBytecode(CompilationInfo* info) {
1352
  if (!info->shared_info()->is_compiled()) {
1353 1354 1355 1356
    CompilerDispatcher* dispatcher = info->isolate()->compiler_dispatcher();
    if (dispatcher->IsEnqueued(info->shared_info())) {
      if (!dispatcher->FinishNow(info->shared_info())) return false;
    } else if (GetUnoptimizedCode(info, Compiler::NOT_CONCURRENT).is_null()) {
1357 1358
      return false;
    }
1359
  }
1360
  DCHECK(info->shared_info()->is_compiled());
1361 1362 1363

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

1364 1365
  DCHECK_EQ(ShouldUseIgnition(info), info->shared_info()->HasBytecodeArray());
  return info->shared_info()->HasBytecodeArray();
1366 1367
}

1368 1369 1370 1371
// TODO(turbofan): In the future, unoptimized code with deopt support could
// be generated lazily once deopt is triggered.
bool Compiler::EnsureDeoptimizationSupport(CompilationInfo* info) {
  DCHECK_NOT_NULL(info->literal());
1372
  DCHECK_NOT_NULL(info->scope());
1373
  Handle<SharedFunctionInfo> shared = info->shared_info();
1374 1375 1376 1377 1378 1379

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

1380
  if (!shared->has_deoptimization_support()) {
1381 1382 1383 1384 1385 1386
    // Don't generate full-codegen code for functions which should use Ignition.
    if (ShouldUseIgnition(info)) return false;

    DCHECK(!shared->must_use_ignition_turbo());
    DCHECK(!IsResumableFunction(shared->kind()));

1387 1388
    Zone compile_zone(info->isolate()->allocator(), ZONE_NAME);
    CompilationInfo unoptimized(&compile_zone, info->parse_info(),
1389
                                info->isolate(), info->closure());
1390
    unoptimized.EnableDeoptimizationSupport();
1391

1392 1393 1394 1395
    // When we call PrepareForSerializing below, we will change the shared
    // ParseInfo. Make sure to reset it.
    bool old_will_serialize_value = info->parse_info()->will_serialize();

1396 1397 1398 1399 1400 1401 1402
    // If the current code has reloc info for serialization, also include
    // reloc info for serialization for the new code, so that deopt support
    // can be added without losing IC state.
    if (shared->code()->kind() == Code::FUNCTION &&
        shared->code()->has_reloc_info_for_serialization()) {
      unoptimized.PrepareForSerializing();
    }
1403
    EnsureFeedbackMetadata(&unoptimized);
1404

1405 1406
    if (!FullCodeGenerator::MakeCode(&unoptimized)) return false;

1407 1408
    info->parse_info()->set_will_serialize(old_will_serialize_value);

1409 1410 1411
    // The scope info might not have been set if a lazily compiled
    // function is inlined before being called for the first time.
    if (shared->scope_info() == ScopeInfo::Empty(info->isolate())) {
1412
      InstallSharedScopeInfo(info, shared);
1413 1414
    }

1415 1416 1417
    // Install compilation result on the shared function info
    shared->EnableDeoptimizationSupport(*unoptimized.code());

1418
    // The existing unoptimized code was replaced with the new one.
1419 1420
    RecordFunctionCompilation(CodeEventListener::LAZY_COMPILE_TAG,
                              &unoptimized);
1421 1422 1423 1424
  }
  return true;
}

1425
MaybeHandle<JSFunction> Compiler::GetFunctionFromEval(
1426
    Handle<String> source, Handle<SharedFunctionInfo> outer_info,
1427
    Handle<Context> context, LanguageMode language_mode,
1428 1429 1430
    ParseRestriction restriction, int parameters_end_pos,
    int eval_scope_position, int eval_position, int line_offset,
    int column_offset, Handle<Object> script_name,
1431
    ScriptOriginOptions options) {
1432 1433 1434 1435 1436
  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);

1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453
  // 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;
  }
1454
  CompilationCache* compilation_cache = isolate->compilation_cache();
1455
  InfoVectorPair eval_result = compilation_cache->LookupEval(
1456
      source, outer_info, context, language_mode, position);
1457 1458 1459 1460
  Handle<Cell> vector;
  if (eval_result.has_vector()) {
    vector = Handle<Cell>(eval_result.vector(), isolate);
  }
1461

1462
  Handle<SharedFunctionInfo> shared_info;
1463
  Handle<Script> script;
1464 1465 1466 1467
  if (eval_result.has_shared()) {
    shared_info = Handle<SharedFunctionInfo>(eval_result.shared(), isolate);
    script = Handle<Script>(Script::cast(shared_info->script()), isolate);
  } else {
1468
    script = isolate->factory()->NewScript(source);
1469 1470 1471
    if (isolate->NeedsSourcePositionsForProfiling()) {
      Script::InitLineEnds(script);
    }
1472 1473
    if (!script_name.is_null()) {
      script->set_name(*script_name);
1474 1475
      script->set_line_offset(line_offset);
      script->set_column_offset(column_offset);
1476 1477
    }
    script->set_origin_options(options);
1478
    script->set_compilation_type(Script::COMPILATION_TYPE_EVAL);
1479
    Script::SetEvalOrigin(script, outer_info, eval_position);
1480

1481
    ParseInfo parse_info(script);
1482
    Zone compile_zone(isolate->allocator(), ZONE_NAME);
1483
    CompilationInfo info(&compile_zone, &parse_info, isolate,
1484
                         Handle<JSFunction>::null());
1485 1486 1487
    parse_info.set_eval();
    parse_info.set_language_mode(language_mode);
    parse_info.set_parse_restriction(restriction);
1488
    parse_info.set_parameters_end_pos(parameters_end_pos);
1489 1490 1491
    if (!context->IsNativeContext()) {
      parse_info.set_outer_scope_info(handle(context->scope_info()));
    }
1492 1493 1494

    shared_info = CompileToplevel(&info);
    if (shared_info.is_null()) {
1495
      return MaybeHandle<JSFunction>();
1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506
    }
  }

  // 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);
1507
    } else {
1508
      result = isolate->factory()->NewFunctionFromSharedFunctionInfo(
1509
          shared_info, context, NOT_TENURED);
1510 1511 1512
      JSFunction::EnsureLiterals(result);
      // Make sure to cache this result.
      Handle<Cell> new_vector(result->feedback_vector_cell(), isolate);
1513
      compilation_cache->PutEval(source, outer_info, context, shared_info,
1514
                                 new_vector, eval_scope_position);
1515
    }
1516 1517 1518 1519 1520 1521 1522 1523 1524
  } 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);
1525 1526
  }

1527 1528 1529 1530 1531 1532
  // 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;
1533 1534
}

1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552
namespace {

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

1553 1554 1555 1556 1557
bool ContainsAsmModule(Handle<Script> script) {
  DisallowHeapAllocation no_gc;
  SharedFunctionInfo::ScriptIterator iter(script);
  while (SharedFunctionInfo* info = iter.Next()) {
    if (info->HasAsmWasmData()) return true;
1558 1559 1560 1561
  }
  return false;
}

1562 1563 1564 1565
}  // namespace

MaybeHandle<JSFunction> Compiler::GetFunctionFromString(
    Handle<Context> context, Handle<String> source,
1566
    ParseRestriction restriction, int parameters_end_pos) {
1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585
  Isolate* const isolate = context->GetIsolate();
  Handle<Context> native_context(context->native_context(), isolate);

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

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

1590
Handle<SharedFunctionInfo> Compiler::GetSharedFunctionInfoForScript(
1591
    Handle<String> source, Handle<Object> script_name, int line_offset,
1592 1593 1594
    int column_offset, ScriptOriginOptions resource_options,
    Handle<Object> source_map_url, Handle<Context> context,
    v8::Extension* extension, ScriptData** cached_data,
1595
    ScriptCompiler::CompileOptions compile_options, NativesFlag natives) {
1596
  Isolate* isolate = source->GetIsolate();
1597
  if (compile_options == ScriptCompiler::kNoCompileOptions) {
1598
    cached_data = NULL;
1599 1600
  } else if (compile_options == ScriptCompiler::kProduceParserCache ||
             compile_options == ScriptCompiler::kProduceCodeCache) {
1601 1602
    DCHECK(cached_data && !*cached_data);
    DCHECK(extension == NULL);
1603
    DCHECK(!isolate->debug()->is_loaded());
1604
  } else {
1605
    DCHECK(compile_options == ScriptCompiler::kConsumeParserCache ||
1606
           compile_options == ScriptCompiler::kConsumeCodeCache);
1607 1608
    DCHECK(cached_data && *cached_data);
    DCHECK(extension == NULL);
1609
  }
1610 1611 1612 1613
  int source_length = source->length();
  isolate->counters()->total_load_size()->Increment(source_length);
  isolate->counters()->total_compile_size()->Increment(source_length);

1614
  LanguageMode language_mode = construct_language_mode(FLAG_use_strict);
1615 1616 1617
  CompilationCache* compilation_cache = isolate->compilation_cache();

  // Do a lookup in the compilation cache but not for extensions.
1618
  Handle<SharedFunctionInfo> result;
1619
  Handle<Cell> vector;
1620
  if (extension == NULL) {
1621
    // First check per-isolate compilation cache.
1622
    InfoVectorPair pair = compilation_cache->LookupScript(
1623 1624
        source, script_name, line_offset, column_offset, resource_options,
        context, language_mode);
1625
    if (!pair.has_shared() && FLAG_serialize_toplevel &&
1626 1627
        compile_options == ScriptCompiler::kConsumeCodeCache &&
        !isolate->debug()->is_loaded()) {
1628
      // Then check cached code provided by embedder.
1629
      HistogramTimerScope timer(isolate->counters()->compile_deserialize());
1630 1631
      RuntimeCallTimerScope runtimeTimer(isolate,
                                         &RuntimeCallStats::CompileDeserialize);
1632 1633
      TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
                   "V8.CompileDeserialize");
1634
      Handle<SharedFunctionInfo> inner_result;
1635
      if (CodeSerializer::Deserialize(isolate, *cached_data, source)
1636
              .ToHandle(&inner_result)) {
1637
        // Promote to per-isolate compilation cache.
1638
        DCHECK(inner_result->is_compiled());
1639 1640
        Handle<FeedbackVector> feedback_vector =
            FeedbackVector::New(isolate, inner_result);
1641 1642 1643
        vector = isolate->factory()->NewCell(feedback_vector);
        compilation_cache->PutScript(source, context, language_mode,
                                     inner_result, vector);
1644 1645
        Handle<Script> script(Script::cast(inner_result->script()), isolate);
        isolate->debug()->OnAfterCompile(script);
1646
        return inner_result;
1647 1648
      }
      // Deserializer failed. Fall through to compile.
1649 1650 1651 1652 1653 1654 1655
    } else {
      if (pair.has_shared()) {
        result = Handle<SharedFunctionInfo>(pair.shared(), isolate);
      }
      if (pair.has_vector()) {
        vector = Handle<Cell>(pair.vector(), isolate);
      }
1656
    }
1657 1658
  }

1659 1660 1661 1662 1663 1664
  base::ElapsedTimer timer;
  if (FLAG_profile_deserialization && FLAG_serialize_toplevel &&
      compile_options == ScriptCompiler::kProduceCodeCache) {
    timer.Start();
  }

1665
  if (result.is_null() ||
1666 1667 1668
      (FLAG_serialize_toplevel &&
       compile_options == ScriptCompiler::kProduceCodeCache)) {
    // No cache entry found, or embedder wants a code cache. Compile the script.
1669 1670

    // Create a script object describing the script to be compiled.
1671
    Handle<Script> script = isolate->factory()->NewScript(source);
1672 1673 1674
    if (isolate->NeedsSourcePositionsForProfiling()) {
      Script::InitLineEnds(script);
    }
1675
    if (natives == NATIVES_CODE) {
1676
      script->set_type(Script::TYPE_NATIVE);
1677 1678
    } else if (natives == EXTENSION_CODE) {
      script->set_type(Script::TYPE_EXTENSION);
1679 1680
    } else if (natives == INSPECTOR_CODE) {
      script->set_type(Script::TYPE_INSPECTOR);
1681
    }
1682 1683
    if (!script_name.is_null()) {
      script->set_name(*script_name);
1684 1685
      script->set_line_offset(line_offset);
      script->set_column_offset(column_offset);
1686
    }
1687
    script->set_origin_options(resource_options);
1688 1689 1690
    if (!source_map_url.is_null()) {
      script->set_source_mapping_url(*source_map_url);
    }
1691 1692

    // Compile the function and add it to the cache.
1693
    ParseInfo parse_info(script);
1694
    Zone compile_zone(isolate->allocator(), ZONE_NAME);
1695
    CompilationInfo info(&compile_zone, &parse_info, isolate,
1696
                         Handle<JSFunction>::null());
1697
    if (resource_options.IsModule()) parse_info.set_module();
1698
    if (compile_options != ScriptCompiler::kNoCompileOptions) {
1699
      parse_info.set_cached_data(cached_data);
1700
    }
1701 1702
    parse_info.set_compile_options(compile_options);
    parse_info.set_extension(extension);
1703 1704 1705
    if (!context->IsNativeContext()) {
      parse_info.set_outer_scope_info(handle(context->scope_info()));
    }
1706 1707
    if (FLAG_serialize_toplevel &&
        compile_options == ScriptCompiler::kProduceCodeCache) {
1708 1709
      info.PrepareForSerializing();
    }
1710

1711
    parse_info.set_language_mode(
1712
        static_cast<LanguageMode>(parse_info.language_mode() | language_mode));
1713
    result = CompileToplevel(&info);
1714
    if (extension == NULL && !result.is_null()) {
1715 1716
      // We need a feedback vector.
      DCHECK(result->is_compiled());
1717
      Handle<FeedbackVector> feedback_vector =
1718
          FeedbackVector::New(isolate, result);
1719 1720 1721
      vector = isolate->factory()->NewCell(feedback_vector);
      compilation_cache->PutScript(source, context, language_mode, result,
                                   vector);
1722
      if (FLAG_serialize_toplevel &&
1723
          compile_options == ScriptCompiler::kProduceCodeCache &&
1724
          !ContainsAsmModule(script)) {
1725 1726
        HistogramTimerScope histogram_timer(
            isolate->counters()->compile_serialize());
1727 1728
        RuntimeCallTimerScope runtimeTimer(isolate,
                                           &RuntimeCallStats::CompileSerialize);
1729 1730
        TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
                     "V8.CompileSerialize");
1731
        *cached_data = CodeSerializer::Serialize(isolate, result, source);
1732
        if (FLAG_profile_deserialization) {
1733 1734
          PrintF("[Compiling and serializing took %0.3f ms]\n",
                 timer.Elapsed().InMillisecondsF());
1735
        }
1736
      }
1737
    }
1738

1739
    if (result.is_null()) {
1740 1741 1742
      if (natives != EXTENSION_CODE && natives != NATIVES_CODE) {
        isolate->ReportPendingMessages();
      }
1743 1744 1745
    } else {
      isolate->debug()->OnAfterCompile(script);
    }
1746
  } else if (result->ic_age() != isolate->heap()->global_ic_age()) {
1747
    result->ResetForNewContext(isolate->heap()->global_ic_age());
1748 1749 1750 1751
  }
  return result;
}

1752
Handle<SharedFunctionInfo> Compiler::GetSharedFunctionInfoForStreamedScript(
1753 1754 1755
    Handle<Script> script, ParseInfo* parse_info, int source_length) {
  Isolate* isolate = script->GetIsolate();
  // TODO(titzer): increment the counters in caller.
1756 1757 1758
  isolate->counters()->total_load_size()->Increment(source_length);
  isolate->counters()->total_compile_size()->Increment(source_length);

1759
  LanguageMode language_mode = construct_language_mode(FLAG_use_strict);
1760 1761
  parse_info->set_language_mode(
      static_cast<LanguageMode>(parse_info->language_mode() | language_mode));
1762

1763
  Zone compile_zone(isolate->allocator(), ZONE_NAME);
1764
  CompilationInfo compile_info(&compile_zone, parse_info, isolate,
1765
                               Handle<JSFunction>::null());
1766

1767 1768
  // The source was parsed lazily, so compiling for debugging is not possible.
  DCHECK(!compile_info.is_debug());
1769

1770 1771 1772
  Handle<SharedFunctionInfo> result = CompileToplevel(&compile_info);
  if (!result.is_null()) isolate->debug()->OnAfterCompile(script);
  return result;
1773 1774
}

1775
Handle<SharedFunctionInfo> Compiler::GetSharedFunctionInfo(
1776
    FunctionLiteral* literal, Handle<Script> script,
1777
    CompilationInfo* outer_info) {
1778
  // Precondition: code has been parsed and scopes have been analyzed.
1779
  Isolate* isolate = outer_info->isolate();
1780
  MaybeHandle<SharedFunctionInfo> maybe_existing;
1781 1782

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

1785
  // If we found an existing shared function info, return it.
1786
  Handle<SharedFunctionInfo> existing;
1787
  if (maybe_existing.ToHandle(&existing)) {
1788
    DCHECK(!existing->is_toplevel());
1789
    return existing;
1790 1791
  }

1792 1793 1794 1795 1796 1797 1798
  // 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());
1799 1800
  }
  return result;
1801 1802
}

1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820
Handle<SharedFunctionInfo> Compiler::GetSharedFunctionInfoForNative(
    v8::Extension* extension, Handle<String> name) {
  Isolate* isolate = name->GetIsolate();
  v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);

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

  // Instantiate the function and create a shared function info from it.
  Handle<JSFunction> fun = Handle<JSFunction>::cast(Utils::OpenHandle(
      *fun_template->GetFunction(v8_isolate->GetCurrentContext())
           .ToLocalChecked()));
  Handle<Code> code = Handle<Code>(fun->shared()->code());
  Handle<Code> construct_stub = Handle<Code>(fun->shared()->construct_stub());
  Handle<SharedFunctionInfo> shared = isolate->factory()->NewSharedFunctionInfo(
1821
      name, FunctionKind::kNormalFunction, code,
1822
      Handle<ScopeInfo>(fun->shared()->scope_info()));
1823
  shared->set_outer_scope_info(fun->shared()->outer_scope_info());
1824
  shared->SetConstructStub(*construct_stub);
1825
  shared->set_feedback_metadata(fun->shared()->feedback_metadata());
1826 1827 1828 1829 1830 1831 1832 1833

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

  return shared;
}
1834

1835 1836 1837
MaybeHandle<Code> Compiler::GetOptimizedCodeForOSR(Handle<JSFunction> function,
                                                   BailoutId osr_ast_id,
                                                   JavaScriptFrame* osr_frame) {
1838
  DCHECK(!osr_ast_id.IsNone());
1839 1840
  DCHECK_NOT_NULL(osr_frame);
  return GetOptimizedCode(function, NOT_CONCURRENT, osr_ast_id, osr_frame);
1841 1842
}

1843
CompilationJob* Compiler::PrepareUnoptimizedCompilationJob(
1844
    CompilationInfo* info) {
1845
  VMState<COMPILER> state(info->isolate());
1846
  std::unique_ptr<CompilationJob> job(GetUnoptimizedCompilationJob(info));
1847 1848 1849 1850 1851 1852 1853
  if (job->PrepareJob() != CompilationJob::SUCCEEDED) {
    return nullptr;
  }
  return job.release();
}

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

1857 1858 1859 1860 1861
  VMState<COMPILER> state(job->info()->isolate());
  if (job->info()->IsOptimizing()) {
    return FinalizeOptimizedCompilationJob(job.get()) ==
           CompilationJob::SUCCEEDED;
  } else {
1862 1863
    return FinalizeUnoptimizedCompilationJob(job.get()) ==
           CompilationJob::SUCCEEDED;
1864
  }
1865 1866
}

1867 1868 1869 1870
void Compiler::PostInstantiation(Handle<JSFunction> function,
                                 PretenureFlag pretenure) {
  Handle<SharedFunctionInfo> shared(function->shared());

1871
  if (FLAG_always_opt && shared->allows_lazy_compilation() &&
1872
      !function->shared()->HasAsmWasmData() &&
1873
      function->shared()->is_compiled()) {
1874 1875 1876
    function->MarkForOptimization();
  }

1877
  Code* code = shared->SearchOptimizedCodeMap(
1878
      function->context()->native_context(), BailoutId::None());
1879
  if (code != nullptr) {
1880
    // Caching of optimized code enabled and optimized code found.
1881
    DCHECK(!code->marked_for_deoptimization());
1882
    DCHECK(function->shared()->is_compiled());
1883
    function->ReplaceCode(code);
1884 1885
  }

1886
  if (shared->is_compiled()) {
1887 1888
    // TODO(mvstanton): pass pretenure flag to EnsureLiterals.
    JSFunction::EnsureLiterals(function);
1889 1890
  }
}
1891

1892 1893
}  // namespace internal
}  // namespace v8