compiler.cc 59.5 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/assembler-inl.h"
12 13 14
#include "src/ast/ast-numbering.h"
#include "src/ast/prettyprinter.h"
#include "src/ast/scopes.h"
15
#include "src/base/optional.h"
16 17 18
#include "src/bootstrapper.h"
#include "src/codegen.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 49 50 51 52 53 54 55 56
 public:
  explicit CompilationHandleScope(CompilationInfo* info)
      : deferred_(info->isolate()), info_(info) {}
  ~CompilationHandleScope() { info_->set_deferred_handles(deferred_.Detach()); }

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

58 59 60 61 62 63 64 65 66 67 68 69 70
// 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_;
};

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

74 75
CompilationJob::CompilationJob(Isolate* isolate, ParseInfo* parse_info,
                               CompilationInfo* compilation_info,
76
                               const char* compiler_name, State initial_state)
77 78
    : parse_info_(parse_info),
      compilation_info_(compilation_info),
79 80 81 82 83 84
      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) {}

85
CompilationJob::Status CompilationJob::PrepareJob() {
86 87
  DCHECK(
      ThreadId::Current().Equals(compilation_info()->isolate()->thread_id()));
88
  DisallowJavascriptExecution no_js(isolate());
89

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

98
  // Delegate to the underlying implementation.
99 100 101
  DCHECK(state() == State::kReadyToPrepare);
  ScopedTimer t(&time_taken_to_prepare_);
  return UpdateState(PrepareJobImpl(), State::kReadyToExecute);
102 103
}

104
CompilationJob::Status CompilationJob::ExecuteJob() {
105 106 107 108
  base::Optional<DisallowHeapAllocation> no_allocation;
  base::Optional<DisallowHandleAllocation> no_handles;
  base::Optional<DisallowHandleDereference> no_deref;
  base::Optional<DisallowCodeDependencyChange> no_dependency_change;
109
  if (can_execute_on_background_thread()) {
110 111 112 113
    no_allocation.emplace();
    no_handles.emplace();
    no_deref.emplace();
    no_dependency_change.emplace();
114 115
    executed_on_background_thread_ =
        !ThreadId::Current().Equals(isolate_thread_id_);
116
  } else {
117
    DCHECK(ThreadId::Current().Equals(isolate_thread_id_));
118
  }
119

120
  // Delegate to the underlying implementation.
121 122 123
  DCHECK(state() == State::kReadyToExecute);
  ScopedTimer t(&time_taken_to_execute_);
  return UpdateState(ExecuteJobImpl(), State::kReadyToFinalize);
124
}
125

126
CompilationJob::Status CompilationJob::FinalizeJob() {
127 128
  DCHECK(
      ThreadId::Current().Equals(compilation_info()->isolate()->thread_id()));
129 130
  DisallowCodeDependencyChange no_dependency_change;
  DisallowJavascriptExecution no_js(isolate());
131
  DCHECK(!compilation_info()->dependencies()->HasAborted());
132

133
  // Delegate to the underlying implementation.
134 135 136
  DCHECK(state() == State::kReadyToFinalize);
  ScopedTimer t(&time_taken_to_finalize_);
  return UpdateState(FinalizeJobImpl(), State::kSucceeded);
137 138
}

139
CompilationJob::Status CompilationJob::RetryOptimization(BailoutReason reason) {
140 141
  DCHECK(compilation_info_->IsOptimizing());
  compilation_info_->RetryOptimization(reason);
142 143 144 145 146
  state_ = State::kFailed;
  return FAILED;
}

CompilationJob::Status CompilationJob::AbortOptimization(BailoutReason reason) {
147 148
  DCHECK(compilation_info_->IsOptimizing());
  compilation_info_->AbortOptimization(reason);
149 150 151 152
  state_ = State::kFailed;
  return FAILED;
}

153 154
void CompilationJob::RecordUnoptimizedCompilationStats() const {
  int code_size;
155 156
  if (compilation_info()->has_bytecode_array()) {
    code_size = compilation_info()->bytecode_array()->SizeIncludingMetadata();
157
  } else {
158
    code_size = compilation_info()->code()->SizeIncludingMetadata();
159 160 161 162 163 164 165 166 167 168 169
  }

  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 {
170 171
  DCHECK(compilation_info()->IsOptimizing());
  Handle<JSFunction> function = compilation_info()->closure();
172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193
  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);
  }
}

194 195 196
Isolate* CompilationJob::isolate() const {
  return compilation_info()->isolate();
}
197

198 199 200 201
// ----------------------------------------------------------------------------
// Local helper methods that make up the compilation pipeline.

namespace {
202

203
void RecordFunctionCompilation(CodeEventListener::LogEventsAndTags tag,
204
                               CompilationInfo* compilation_info) {
205 206 207
  // 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.
208 209 210 211
  if (compilation_info->isolate()->logger()->is_logging_code_events() ||
      compilation_info->isolate()->is_profiling()) {
    Handle<SharedFunctionInfo> shared = compilation_info->shared_info();
    Handle<Script> script = compilation_info->script();
212
    Handle<AbstractCode> abstract_code =
213 214 215
        compilation_info->has_bytecode_array()
            ? Handle<AbstractCode>::cast(compilation_info->bytecode_array())
            : Handle<AbstractCode>::cast(compilation_info->code());
216
    if (abstract_code.is_identical_to(
217
            BUILTIN_CODE(compilation_info->isolate(), CompileLazy))) {
218 219 220 221 222
      return;
    }
    int line_num = Script::GetLineNumber(script, shared->start_position()) + 1;
    int column_num =
        Script::GetColumnNumber(script, shared->start_position()) + 1;
223 224 225 226
    String* script_name =
        script->name()->IsString()
            ? String::cast(script->name())
            : compilation_info->isolate()->heap()->empty_string();
227 228
    CodeEventListener::LogEventsAndTags log_tag =
        Logger::ToNativeByScript(tag, *script);
229
    PROFILE(compilation_info->isolate(),
230
            CodeCreateEvent(log_tag, *abstract_code, *shared, script_name,
231 232 233 234
                            line_num, column_num));
  }
}

235 236
void EnsureFeedbackMetadata(CompilationInfo* compilation_info) {
  DCHECK(compilation_info->has_shared_info());
237 238 239 240 241 242 243

  // 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().
244 245
  if (compilation_info->shared_info()->feedback_metadata()->length() == 0 ||
      !compilation_info->shared_info()->is_compiled()) {
246
    Handle<FeedbackMetadata> feedback_metadata = FeedbackMetadata::New(
247 248 249
        compilation_info->isolate(),
        compilation_info->literal()->feedback_vector_spec());
    compilation_info->shared_info()->set_feedback_metadata(*feedback_metadata);
250 251 252 253
  }

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

258
bool UseAsmWasm(FunctionLiteral* literal, bool asm_wasm_broken) {
259 260 261 262 263
  // 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.
264
  if (asm_wasm_broken) return false;
265 266 267 268 269

  // 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.
270
  return literal->scope()->IsAsmModule();
271 272
}

273 274 275 276
void InstallUnoptimizedCode(CompilationInfo* compilation_info) {
  Handle<SharedFunctionInfo> shared = compilation_info->shared_info();
  DCHECK_EQ(compilation_info->shared_info()->language_mode(),
            compilation_info->literal()->language_mode());
277 278

  // Ensure feedback metadata is installed.
279
  EnsureFeedbackMetadata(compilation_info);
280

281
  // Update the shared function info with the scope info.
282
  Handle<ScopeInfo> scope_info = compilation_info->scope()->scope_info();
283
  shared->set_scope_info(*scope_info);
284
  Scope* outer_scope = compilation_info->scope()->GetOuterScopeWithContext();
285 286 287
  if (outer_scope) {
    shared->set_outer_scope_info(*outer_scope->scope_info());
  }
288

289 290 291
  DCHECK(!compilation_info->code().is_null());
  shared->ReplaceCode(*compilation_info->code());
  if (compilation_info->has_bytecode_array()) {
292
    DCHECK(!shared->HasBytecodeArray());  // Only compiled once.
293 294 295 296
    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());
297
  }
298 299

  // Install coverage info on the shared function info.
300
  if (compilation_info->has_coverage_info()) {
301 302
    DCHECK(FLAG_block_coverage &&
           compilation_info->isolate()->is_block_code_coverage());
303 304
    compilation_info->isolate()->debug()->InstallCoverageInfo(
        compilation_info->shared_info(), compilation_info->coverage_info());
305
  }
306
}
307

308 309 310 311 312 313 314
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);
315 316
    return;
  }
317 318 319
  Handle<FixedArray> infos(isolate->factory()->NewFixedArray(
      parse_info->max_function_literal_id() + 1));
  parse_info->script()->set_shared_function_infos(*infos);
320 321
}

322 323
void SetSharedFunctionFlagsFromLiteral(FunctionLiteral* literal,
                                       Handle<SharedFunctionInfo> shared_info) {
324 325 326 327
  // Don't overwrite values set by the bootstrapper.
  if (!shared_info->HasLength()) {
    shared_info->set_length(literal->function_length());
  }
328 329
  shared_info->set_has_duplicate_parameters(
      literal->has_duplicate_parameters());
330
  shared_info->SetExpectedNofPropertiesFromEstimate(literal);
331 332 333
  if (literal->dont_optimize_reason() != kNoReason) {
    shared_info->DisableOptimization(literal->dont_optimize_reason());
  }
334 335 336
}

CompilationJob::Status FinalizeUnoptimizedCompilationJob(CompilationJob* job) {
337 338
  CompilationInfo* compilation_info = job->compilation_info();
  ParseInfo* parse_info = job->parse_info();
339

340 341
  SetSharedFunctionFlagsFromLiteral(compilation_info->literal(),
                                    compilation_info->shared_info());
342 343 344

  CompilationJob::Status status = job->FinalizeJob();
  if (status == CompilationJob::SUCCEEDED) {
345
    InstallUnoptimizedCode(compilation_info);
346 347 348 349 350 351 352 353 354
    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;
    }
    RecordFunctionCompilation(log_tag, compilation_info);
355
    job->RecordUnoptimizedCompilationStats();
356
  }
357
  return status;
358 359
}

360
bool Renumber(ParseInfo* parse_info,
361
              Compiler::EagerInnerFunctionLiterals* eager_literals) {
362
  RuntimeCallTimerScope runtimeTimer(parse_info->runtime_call_stats(),
363
                                     &RuntimeCallStats::CompileRenumber);
364 365 366
  return AstNumbering::Renumber(parse_info->stack_limit(), parse_info->zone(),
                                parse_info->literal(), eager_literals,
                                parse_info->collect_type_profile());
367 368
}

369
std::unique_ptr<CompilationJob> PrepareAndExecuteUnoptimizedCompileJob(
370
    ParseInfo* parse_info, FunctionLiteral* literal, Isolate* isolate) {
371
  if (UseAsmWasm(literal, parse_info->is_asm_wasm_broken())) {
372 373 374 375 376
    std::unique_ptr<CompilationJob> asm_job(
        AsmJs::NewCompilationJob(parse_info, literal, isolate));
    if (asm_job->PrepareJob() == CompilationJob::SUCCEEDED &&
        asm_job->ExecuteJob() == CompilationJob::SUCCEEDED) {
      return asm_job;
377
    }
378
    // asm.js validation failed, fall through to standard unoptimized compile.
379 380 381 382
    // 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.
383
  }
384
  std::unique_ptr<CompilationJob> job(
385 386
      interpreter::Interpreter::NewCompilationJob(parse_info, literal,
                                                  isolate));
387 388 389
  if (job->PrepareJob() == CompilationJob::SUCCEEDED &&
      job->ExecuteJob() == CompilationJob::SUCCEEDED) {
    return job;
390
  }
391
  return std::unique_ptr<CompilationJob>();  // Compilation failed, return null.
392 393
}

394 395 396 397 398 399 400 401
// TODO(rmcilroy): Remove |isolate| once CompilationJob doesn't need it.
std::unique_ptr<CompilationJob> GenerateUnoptimizedCode(
    ParseInfo* parse_info, Isolate* isolate,
    std::forward_list<std::unique_ptr<CompilationJob>>* inner_function_jobs) {
  DisallowHeapAllocation no_allocation;
  DisallowHandleAllocation no_handles;
  DisallowHandleDereference no_deref;
  DCHECK(inner_function_jobs->empty());
402

403 404 405
  DCHECK_IMPLIES(parse_info->consumed_preparsed_scope_data()->HasData(),
                 ThreadId::Current().Equals(isolate->thread_id()));

406
  Compiler::EagerInnerFunctionLiterals inner_literals;
407
  if (!Compiler::Analyze(parse_info, &inner_literals)) {
408
    return std::unique_ptr<CompilationJob>();
409 410
  }

411
  // Prepare and execute compilation of the outer-most function.
412
  std::unique_ptr<CompilationJob> outer_function_job(
413
      PrepareAndExecuteUnoptimizedCompileJob(parse_info, parse_info->literal(),
414 415
                                             isolate));
  if (!outer_function_job) return std::unique_ptr<CompilationJob>();
416 417 418 419 420

  // 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(
421 422 423 424
        PrepareAndExecuteUnoptimizedCompileJob(parse_info, inner_literal,
                                               isolate));
    if (!inner_job) return std::unique_ptr<CompilationJob>();
    inner_function_jobs->emplace_front(std::move(inner_job));
425 426
  }

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

430 431 432 433 434 435 436 437 438
  return outer_function_job;
}

bool FinalizeUnoptimizedCode(
    ParseInfo* parse_info, Isolate* isolate,
    Handle<SharedFunctionInfo> shared_info, CompilationJob* outer_function_job,
    std::forward_list<std::unique_ptr<CompilationJob>>* inner_function_jobs) {
  DCHECK(AllowCompilation::IsAllowed(isolate));

439 440 441 442 443
  // Allocate scope infos for the literal.
  DeclarationScope::AllocateScopeInfos(parse_info, isolate,
                                       AnalyzeMode::kRegular);

  // Finalize the outer-most function's compilation job.
444 445
  outer_function_job->compilation_info()->set_shared_info(shared_info);
  if (FinalizeUnoptimizedCompilationJob(outer_function_job) !=
446
      CompilationJob::SUCCEEDED) {
447
    return false;
448 449 450
  }

  // Finalize the inner functions' compilation jobs.
451
  for (auto&& inner_job : *inner_function_jobs) {
452 453 454 455 456 457 458 459 460 461
    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);
    if (FinalizeUnoptimizedCompilationJob(inner_job.get()) !=
        CompilationJob::SUCCEEDED) {
462
      return false;
463 464
    }
  }
465
  return true;
466 467
}

468
MUST_USE_RESULT MaybeHandle<Code> GetCodeFromOptimizedCodeCache(
469
    Handle<JSFunction> function, BailoutId osr_offset) {
470 471 472
  RuntimeCallTimerScope runtimeTimer(
      function->GetIsolate(),
      &RuntimeCallStats::CompileGetFromOptimizedCodeMap);
473 474
  Handle<SharedFunctionInfo> shared(function->shared());
  DisallowHeapAllocation no_gc;
475
  if (osr_offset.IsNone()) {
476 477 478 479
    if (function->feedback_vector_cell()->value()->IsFeedbackVector()) {
      FeedbackVector* feedback_vector = function->feedback_vector();
      feedback_vector->EvictOptimizedCodeMarkedForDeoptimization(
          function->shared(), "GetCodeFromOptimizedCodeCache");
480 481 482 483 484 485 486 487
      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);
      }
488
    }
489 490 491 492
  }
  return MaybeHandle<Code>();
}

493 494
void ClearOptimizedCodeCache(CompilationInfo* compilation_info) {
  Handle<JSFunction> function = compilation_info->closure();
495
  if (compilation_info->osr_offset().IsNone()) {
496 497 498 499 500 501
    Handle<FeedbackVector> vector =
        handle(function->feedback_vector(), function->GetIsolate());
    vector->ClearOptimizedCode();
  }
}

502 503
void InsertCodeIntoOptimizedCodeCache(CompilationInfo* compilation_info) {
  Handle<Code> code = compilation_info->code();
504 505
  if (code->kind() != Code::OPTIMIZED_FUNCTION) return;  // Nothing to do.

506 507
  // Function context specialization folds-in the function context,
  // so no sharing can occur.
508
  if (compilation_info->is_function_context_specializing()) {
509 510
    // Native context specialized code is not shared, so make sure the optimized
    // code cache is clear.
511
    ClearOptimizedCodeCache(compilation_info);
512 513
    return;
  }
514

515
  // Cache optimized context-specific code.
516
  Handle<JSFunction> function = compilation_info->closure();
517 518
  Handle<SharedFunctionInfo> shared(function->shared());
  Handle<Context> native_context(function->context()->native_context());
519
  if (compilation_info->osr_offset().IsNone()) {
520 521 522 523
    Handle<FeedbackVector> vector =
        handle(function->feedback_vector(), function->GetIsolate());
    FeedbackVector::SetOptimizedCode(vector, code);
  }
524 525
}

526
bool GetOptimizedCodeNow(CompilationJob* job) {
527 528
  CompilationInfo* compilation_info = job->compilation_info();
  Isolate* isolate = compilation_info->isolate();
529
  TimerEventScope<TimerEventRecompileSynchronous> timer(isolate);
530 531
  RuntimeCallTimerScope runtimeTimer(isolate,
                                     &RuntimeCallStats::RecompileSynchronous);
532 533
  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
               "V8.RecompileSynchronous");
534

535 536 537
  if (job->PrepareJob() != CompilationJob::SUCCEEDED ||
      job->ExecuteJob() != CompilationJob::SUCCEEDED ||
      job->FinalizeJob() != CompilationJob::SUCCEEDED) {
538 539
    if (FLAG_trace_opt) {
      PrintF("[aborted optimizing ");
540 541 542
      compilation_info->closure()->ShortPrint();
      PrintF(" because: %s]\n",
             GetBailoutReason(compilation_info->bailout_reason()));
543 544 545
    }
    return false;
  }
546 547

  // Success!
548
  job->RecordOptimizedCompilationStats();
549
  DCHECK(!isolate->has_pending_exception());
550 551 552
  InsertCodeIntoOptimizedCodeCache(compilation_info);
  RecordFunctionCompilation(CodeEventListener::LAZY_COMPILE_TAG,
                            compilation_info);
553 554 555
  return true;
}

556
bool GetOptimizedCodeLater(CompilationJob* job) {
557 558
  CompilationInfo* compilation_info = job->compilation_info();
  Isolate* isolate = compilation_info->isolate();
559

560
  if (!isolate->optimizing_compile_dispatcher()->IsQueueAvailable()) {
561 562
    if (FLAG_trace_concurrent_recompilation) {
      PrintF("  ** Compilation queue full, will retry optimizing ");
563
      compilation_info->closure()->ShortPrint();
564 565 566 567 568
      PrintF(" later.\n");
    }
    return false;
  }

569 570 571
  if (isolate->heap()->HighMemoryPressure()) {
    if (FLAG_trace_concurrent_recompilation) {
      PrintF("  ** High memory pressure, will retry optimizing ");
572
      compilation_info->closure()->ShortPrint();
573 574 575 576 577
      PrintF(" later.\n");
    }
    return false;
  }

578 579
  TimerEventScope<TimerEventRecompileSynchronous> timer(isolate);
  RuntimeCallTimerScope runtimeTimer(isolate,
580
                                     &RuntimeCallStats::RecompileSynchronous);
581 582
  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
               "V8.RecompileSynchronous");
583

584
  if (job->PrepareJob() != CompilationJob::SUCCEEDED) return false;
585
  isolate->optimizing_compile_dispatcher()->QueueForOptimization(job);
586 587 588

  if (FLAG_trace_concurrent_recompilation) {
    PrintF("  ** Queued ");
589
    compilation_info->closure()->ShortPrint();
590
    PrintF(" for concurrent optimization.\n");
591 592 593 594
  }
  return true;
}

595
MaybeHandle<Code> GetOptimizedCode(Handle<JSFunction> function,
596
                                   ConcurrencyMode mode,
597
                                   BailoutId osr_offset = BailoutId::None(),
598 599 600 601
                                   JavaScriptFrame* osr_frame = nullptr) {
  Isolate* isolate = function->GetIsolate();
  Handle<SharedFunctionInfo> shared(function->shared(), isolate);

602 603 604 605 606 607
  // Make sure we clear the optimization marker on the function so that we
  // don't try to re-optimize.
  if (function->HasOptimizationMarker()) {
    function->ClearOptimizationMarker();
  }

608
  Handle<Code> cached_code;
609
  if (GetCodeFromOptimizedCodeCache(function, osr_offset)
610 611 612 613
          .ToHandle(&cached_code)) {
    if (FLAG_trace_opt) {
      PrintF("[found optimized code for ");
      function->ShortPrint();
614 615
      if (!osr_offset.IsNone()) {
        PrintF(" at OSR AST id %d", osr_offset.ToInt());
616 617 618 619 620 621
      }
      PrintF("]\n");
    }
    return cached_code;
  }

622
  // Reset profiler ticks, function is no longer considered hot.
623
  DCHECK(shared->is_compiled());
624
  function->feedback_vector()->set_profiler_ticks(0);
625 626 627 628

  VMState<COMPILER> state(isolate);
  DCHECK(!isolate->has_pending_exception());
  PostponeInterruptsScope postpone(isolate);
629
  bool has_script = shared->script()->IsScript();
630 631 632
  // 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());
633
  std::unique_ptr<CompilationJob> job(
634
      compiler::Pipeline::NewCompilationJob(function, has_script));
635 636
  CompilationInfo* compilation_info = job->compilation_info();
  ParseInfo* parse_info = job->parse_info();
637

638
  compilation_info->SetOptimizingForOsr(osr_offset, osr_frame);
639

640
  // Do not use TurboFan if we need to be able to set break points.
641 642
  if (compilation_info->shared_info()->HasBreakInfo()) {
    compilation_info->AbortOptimization(kFunctionBeingDebugged);
643 644 645
    return MaybeHandle<Code>();
  }

646
  // Do not use TurboFan when %NeverOptimizeFunction was applied.
647 648
  if (shared->optimization_disabled() &&
      shared->disable_optimization_reason() == kOptimizationDisabledForTest) {
649
    compilation_info->AbortOptimization(kOptimizationDisabledForTest);
650 651 652
    return MaybeHandle<Code>();
  }

653 654 655
  // Do not use TurboFan if optimization is disabled or function doesn't pass
  // turbo_filter.
  if (!FLAG_opt || !shared->PassesFilter(FLAG_turbo_filter)) {
656
    compilation_info->AbortOptimization(kOptimizationDisabled);
657 658 659
    return MaybeHandle<Code>();
  }

660
  TimerEventScope<TimerEventOptimizeCode> optimize_code_timer(isolate);
661
  RuntimeCallTimerScope runtimeTimer(isolate, &RuntimeCallStats::OptimizeCode);
662
  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.OptimizeCode");
663

664 665 666
  // 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.
667
  base::Optional<CompilationHandleScope> compilation;
668
  if (mode == ConcurrencyMode::kConcurrent) {
669
    compilation.emplace(compilation_info);
670 671
  }

672
  // All handles below will be canonicalized.
673
  CanonicalHandleScope canonical(isolate);
674 675

  // Reopen handles in the new CompilationHandleScope.
676
  compilation_info->ReopenHandlesInNewHandleScope();
677 678
  parse_info->ReopenHandlesInNewHandleScope();

679
  if (mode == ConcurrencyMode::kConcurrent) {
680
    if (GetOptimizedCodeLater(job.get())) {
681
      job.release();  // The background recompile job owns this now.
682 683 684 685

      // Set the optimization marker and return a code object which checks it.
      function->SetOptimizationMarker(OptimizationMarker::kInOptimizationQueue);
      if (function->IsInterpreted()) {
686
        return BUILTIN_CODE(isolate, InterpreterEntryTrampoline);
687
      } else {
688
        return BUILTIN_CODE(isolate, CheckOptimizationMarker);
689
      }
690 691
    }
  } else {
692
    if (GetOptimizedCodeNow(job.get())) return compilation_info->code();
693 694 695 696 697 698
  }

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

699
CompilationJob::Status FinalizeOptimizedCompilationJob(CompilationJob* job) {
700 701
  CompilationInfo* compilation_info = job->compilation_info();
  Isolate* isolate = compilation_info->isolate();
702

703
  TimerEventScope<TimerEventRecompileSynchronous> timer(isolate);
704 705
  RuntimeCallTimerScope runtimeTimer(isolate,
                                     &RuntimeCallStats::RecompileSynchronous);
706 707
  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
               "V8.RecompileSynchronous");
708

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

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

714
  DCHECK(!shared->HasBreakInfo());
715 716 717 718 719 720 721 722 723

  // 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);
724
    } else if (compilation_info->dependencies()->HasAborted()) {
725 726 727
      job->RetryOptimization(kBailedOutDueToDependencyChange);
    } else if (job->FinalizeJob() == CompilationJob::SUCCEEDED) {
      job->RecordOptimizedCompilationStats();
728 729 730
      RecordFunctionCompilation(CodeEventListener::LAZY_COMPILE_TAG,
                                compilation_info);
      InsertCodeIntoOptimizedCodeCache(compilation_info);
731 732
      if (FLAG_trace_opt) {
        PrintF("[completed optimizing ");
733
        compilation_info->closure()->ShortPrint();
734 735
        PrintF("]\n");
      }
736
      compilation_info->closure()->ReplaceCode(*compilation_info->code());
737 738 739 740 741 742 743
      return CompilationJob::SUCCEEDED;
    }
  }

  DCHECK(job->state() == CompilationJob::State::kFailed);
  if (FLAG_trace_opt) {
    PrintF("[aborted optimizing ");
744 745 746
    compilation_info->closure()->ShortPrint();
    PrintF(" because: %s]\n",
           GetBailoutReason(compilation_info->bailout_reason()));
747
  }
748
  compilation_info->closure()->ReplaceCode(shared->code());
749
  // Clear the InOptimizationQueue marker, if it exists.
750 751
  if (compilation_info->closure()->IsInOptimizationQueue()) {
    compilation_info->closure()->ClearOptimizationMarker();
752
  }
753 754 755
  return CompilationJob::FAILED;
}

756 757 758
MaybeHandle<SharedFunctionInfo> CompileToplevel(ParseInfo* parse_info,
                                                Isolate* isolate) {
  TimerEventScope<TimerEventCompileCode> top_level_timer(isolate);
759
  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"), "V8.CompileCode");
760
  PostponeInterruptsScope postpone(isolate);
761
  DCHECK(!isolate->native_context().is_null());
762 763 764 765
  RuntimeCallTimerScope runtimeTimer(
      isolate, parse_info->is_eval() ? &RuntimeCallStats::CompileEval
                                     : &RuntimeCallStats::CompileScript);

766
  Handle<Script> script = parse_info->script();
767
  Handle<SharedFunctionInfo> result;
768 769 770 771 772 773 774 775 776 777 778 779 780 781
  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");
782

783 784 785 786 787 788 789 790
  // Generate the unoptimized bytecode or asm-js data.
  std::forward_list<std::unique_ptr<CompilationJob>> inner_function_jobs;
  std::unique_ptr<CompilationJob> outer_function_job(
      GenerateUnoptimizedCode(parse_info, isolate, &inner_function_jobs));
  if (!outer_function_job) {
    if (!isolate->has_pending_exception()) isolate->StackOverflow();
    return MaybeHandle<SharedFunctionInfo>();
  }
791

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

795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810
  // 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.get(),
                               &inner_function_jobs)) {
    if (!isolate->has_pending_exception()) isolate->StackOverflow();
    return MaybeHandle<SharedFunctionInfo>();
811 812
  }

813 814 815 816 817 818 819 820 821 822 823 824 825 826 827
  if (!script.is_null()) {
    script->set_compilation_state(Script::COMPILATION_STATE_COMPILED);
  }

  return shared_info;
}

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;
828 829
}

830 831 832 833 834
}  // namespace

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

835
bool Compiler::Analyze(ParseInfo* parse_info,
836
                       EagerInnerFunctionLiterals* eager_literals) {
837
  DCHECK_NOT_NULL(parse_info->literal());
838
  RuntimeCallTimerScope runtimeTimer(parse_info->runtime_call_stats(),
839
                                     &RuntimeCallStats::CompileAnalyse);
840
  if (!Rewriter::Rewrite(parse_info)) return false;
841
  DeclarationScope::Analyze(parse_info);
842
  if (!Renumber(parse_info, eager_literals)) return false;
843 844 845
  return true;
}

846
bool Compiler::ParseAndAnalyze(ParseInfo* parse_info,
847 848
                               Handle<SharedFunctionInfo> shared_info,
                               Isolate* isolate) {
849
  if (!parsing::ParseAny(parse_info, shared_info, isolate)) {
850 851
    return false;
  }
852
  return Compiler::Analyze(parse_info);
853 854
}

855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 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 916 917 918 919 920
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();
  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.
      shared_info->set_preparsed_scope_data(isolate->heap()->null_value());
    }
  }

  // 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.
  std::forward_list<std::unique_ptr<CompilationJob>> inner_function_jobs;
  std::unique_ptr<CompilationJob> outer_function_job(
      GenerateUnoptimizedCode(&parse_info, isolate, &inner_function_jobs));
  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;
}

921
bool Compiler::Compile(Handle<JSFunction> function, ClearExceptionFlag flag) {
922 923 924
  // We should never reach here if the function is already compiled or optimized
  DCHECK(!function->is_compiled());
  DCHECK(!function->IsOptimized());
925 926
  DCHECK(!function->HasOptimizationMarker());
  DCHECK(!function->HasOptimizedCode());
927

928
  Isolate* isolate = function->GetIsolate();
929
  Handle<SharedFunctionInfo> shared_info = handle(function->shared());
930
  DCHECK(AllowCompilation::IsAllowed(isolate));
931

932 933 934 935 936 937 938 939 940 941 942 943 944
  // 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");
945
    }
946 947 948 949
    Handle<Code> opt_code;
    if (GetOptimizedCode(function, ConcurrencyMode::kNotConcurrent)
            .ToHandle(&opt_code)) {
      code = opt_code;
950 951
    }
  }
952

953
  // Install code on closure.
954
  function->ReplaceCode(*code);
955 956 957 958

  // Check postconditions on success.
  DCHECK(!isolate->has_pending_exception());
  DCHECK(function->shared()->is_compiled());
959 960 961 962 963 964
  DCHECK(function->is_compiled());
  return true;
}

bool Compiler::CompileOptimized(Handle<JSFunction> function,
                                ConcurrencyMode mode) {
965 966 967 968 969
  if (function->IsOptimized()) return true;
  Isolate* isolate = function->GetIsolate();
  DCHECK(AllowCompilation::IsAllowed(isolate));

  // Start a compilation.
970
  Handle<Code> code;
971
  if (!GetOptimizedCode(function, mode).ToHandle(&code)) {
972 973
    // Optimization failed, get unoptimized code. Unoptimized code must exist
    // already if we are optimizing.
974
    DCHECK(!isolate->has_pending_exception());
975 976
    DCHECK(function->shared()->is_compiled());
    code = handle(function->shared()->code(), isolate);
977 978
  }

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

  // Check postconditions on success.
  DCHECK(!isolate->has_pending_exception());
  DCHECK(function->shared()->is_compiled());
  DCHECK(function->is_compiled());
986 987 988 989 990 991
  DCHECK_IMPLIES(function->HasOptimizationMarker(),
                 function->IsInOptimizationQueue());
  DCHECK_IMPLIES(function->HasOptimizationMarker(),
                 function->ChecksOptimizationMarker());
  DCHECK_IMPLIES(function->IsInOptimizationQueue(),
                 mode == ConcurrencyMode::kConcurrent);
992 993 994
  return true;
}

995
MaybeHandle<JSArray> Compiler::CompileForLiveEdit(Handle<Script> script) {
996 997 998
  Isolate* isolate = script->GetIsolate();
  DCHECK(AllowCompilation::IsAllowed(isolate));

999 1000 1001
  // 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.
1002 1003 1004
  Handle<FixedArray> old_function_infos(script->shared_function_infos(),
                                        isolate);
  script->set_shared_function_infos(isolate->heap()->empty_fixed_array());
1005

1006
  // Start a compilation.
1007
  ParseInfo parse_info(script);
1008
  parse_info.set_is_debug();
1009

1010
  // TODO(635): support extensions.
1011
  Handle<JSArray> infos;
1012 1013
  Handle<SharedFunctionInfo> shared_info;
  if (CompileToplevel(&parse_info, isolate).ToHandle(&shared_info)) {
1014 1015 1016
    // Check postconditions on success.
    DCHECK(!isolate->has_pending_exception());
    infos = LiveEditFunctionTracker::Collect(parse_info.literal(), script,
1017
                                             parse_info.zone(), isolate);
1018
  }
1019 1020 1021 1022 1023 1024

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

1025
  return infos;
1026 1027
}

1028
MaybeHandle<JSFunction> Compiler::GetFunctionFromEval(
1029
    Handle<String> source, Handle<SharedFunctionInfo> outer_info,
1030
    Handle<Context> context, LanguageMode language_mode,
1031 1032 1033
    ParseRestriction restriction, int parameters_end_pos,
    int eval_scope_position, int eval_position, int line_offset,
    int column_offset, Handle<Object> script_name,
1034
    ScriptOriginOptions options) {
1035 1036 1037 1038 1039
  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);

1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056
  // 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;
  }
1057
  CompilationCache* compilation_cache = isolate->compilation_cache();
1058
  InfoVectorPair eval_result = compilation_cache->LookupEval(
1059
      source, outer_info, context, language_mode, position);
1060 1061 1062 1063
  Handle<Cell> vector;
  if (eval_result.has_vector()) {
    vector = Handle<Cell>(eval_result.vector(), isolate);
  }
1064

1065
  Handle<SharedFunctionInfo> shared_info;
1066
  Handle<Script> script;
1067 1068 1069 1070
  if (eval_result.has_shared()) {
    shared_info = Handle<SharedFunctionInfo>(eval_result.shared(), isolate);
    script = Handle<Script>(Script::cast(shared_info->script()), isolate);
  } else {
1071
    script = isolate->factory()->NewScript(source);
1072 1073 1074
    if (isolate->NeedsSourcePositionsForProfiling()) {
      Script::InitLineEnds(script);
    }
1075 1076
    if (!script_name.is_null()) {
      script->set_name(*script_name);
1077 1078
      script->set_line_offset(line_offset);
      script->set_column_offset(column_offset);
1079 1080
    }
    script->set_origin_options(options);
1081
    script->set_compilation_type(Script::COMPILATION_TYPE_EVAL);
1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098

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

1100
    ParseInfo parse_info(script);
1101 1102 1103
    parse_info.set_eval();
    parse_info.set_language_mode(language_mode);
    parse_info.set_parse_restriction(restriction);
1104
    parse_info.set_parameters_end_pos(parameters_end_pos);
1105 1106 1107
    if (!context->IsNativeContext()) {
      parse_info.set_outer_scope_info(handle(context->scope_info()));
    }
1108

1109
    if (!CompileToplevel(&parse_info, isolate).ToHandle(&shared_info)) {
1110
      return MaybeHandle<JSFunction>();
1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121
    }
  }

  // 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);
1122
    } else {
1123
      result = isolate->factory()->NewFunctionFromSharedFunctionInfo(
1124
          shared_info, context, NOT_TENURED);
1125 1126 1127
      JSFunction::EnsureLiterals(result);
      // Make sure to cache this result.
      Handle<Cell> new_vector(result->feedback_vector_cell(), isolate);
1128
      compilation_cache->PutEval(source, outer_info, context, shared_info,
1129
                                 new_vector, eval_scope_position);
1130
    }
1131 1132 1133 1134 1135 1136 1137 1138 1139
  } 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);
1140 1141
  }

1142 1143 1144 1145 1146 1147
  // 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;
1148 1149
}

1150 1151
namespace {

1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165
bool ContainsAsmModule(Handle<Script> script) {
  DisallowHeapAllocation no_gc;
  SharedFunctionInfo::ScriptIterator iter(script);
  while (SharedFunctionInfo* info = iter.Next()) {
    if (info->HasAsmWasmData()) return true;
  }
  return false;
}

}  // namespace

bool Compiler::CodeGenerationFromStringsAllowed(Isolate* isolate,
                                                Handle<Context> context,
                                                Handle<String> source) {
1166 1167 1168 1169 1170 1171 1172 1173 1174 1175
  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);
1176
    return callback(v8::Utils::ToLocal(context), v8::Utils::ToLocal(source));
1177 1178 1179 1180 1181
  }
}

MaybeHandle<JSFunction> Compiler::GetFunctionFromString(
    Handle<Context> context, Handle<String> source,
1182
    ParseRestriction restriction, int parameters_end_pos) {
1183 1184 1185 1186 1187 1188
  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) &&
1189
      !CodeGenerationFromStringsAllowed(isolate, native_context, source)) {
1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201
    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,
1202 1203
                                       SLOPPY, restriction, parameters_end_pos,
                                       eval_scope_position, eval_position);
1204 1205
}

1206
Handle<SharedFunctionInfo> Compiler::GetSharedFunctionInfoForScript(
1207
    Handle<String> source, Handle<Object> script_name, int line_offset,
1208 1209 1210
    int column_offset, ScriptOriginOptions resource_options,
    Handle<Object> source_map_url, Handle<Context> context,
    v8::Extension* extension, ScriptData** cached_data,
1211 1212
    ScriptCompiler::CompileOptions compile_options, NativesFlag natives,
    Handle<FixedArray> host_defined_options) {
1213
  Isolate* isolate = source->GetIsolate();
1214
  if (compile_options == ScriptCompiler::kNoCompileOptions) {
1215
    cached_data = NULL;
1216 1217
  } else if (compile_options == ScriptCompiler::kProduceParserCache ||
             compile_options == ScriptCompiler::kProduceCodeCache) {
1218 1219
    DCHECK(cached_data && !*cached_data);
    DCHECK(extension == NULL);
1220
    DCHECK(!isolate->debug()->is_loaded());
1221
  } else {
1222
    DCHECK(compile_options == ScriptCompiler::kConsumeParserCache ||
1223
           compile_options == ScriptCompiler::kConsumeCodeCache);
1224 1225
    DCHECK(cached_data && *cached_data);
    DCHECK(extension == NULL);
1226
  }
1227 1228 1229 1230
  int source_length = source->length();
  isolate->counters()->total_load_size()->Increment(source_length);
  isolate->counters()->total_compile_size()->Increment(source_length);

1231
  LanguageMode language_mode = construct_language_mode(FLAG_use_strict);
1232 1233 1234
  CompilationCache* compilation_cache = isolate->compilation_cache();

  // Do a lookup in the compilation cache but not for extensions.
1235
  Handle<SharedFunctionInfo> result;
1236
  Handle<Cell> vector;
1237
  if (extension == NULL) {
1238
    // First check per-isolate compilation cache.
1239
    InfoVectorPair pair = compilation_cache->LookupScript(
1240 1241
        source, script_name, line_offset, column_offset, resource_options,
        context, language_mode);
1242
    if (!pair.has_shared() && FLAG_serialize_toplevel &&
1243 1244
        compile_options == ScriptCompiler::kConsumeCodeCache &&
        !isolate->debug()->is_loaded()) {
1245
      // Then check cached code provided by embedder.
1246
      HistogramTimerScope timer(isolate->counters()->compile_deserialize());
1247 1248
      RuntimeCallTimerScope runtimeTimer(isolate,
                                         &RuntimeCallStats::CompileDeserialize);
1249 1250
      TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
                   "V8.CompileDeserialize");
1251
      Handle<SharedFunctionInfo> inner_result;
1252
      if (CodeSerializer::Deserialize(isolate, *cached_data, source)
1253
              .ToHandle(&inner_result)) {
1254
        // Promote to per-isolate compilation cache.
1255
        DCHECK(inner_result->is_compiled());
1256 1257
        Handle<FeedbackVector> feedback_vector =
            FeedbackVector::New(isolate, inner_result);
1258 1259 1260
        vector = isolate->factory()->NewCell(feedback_vector);
        compilation_cache->PutScript(source, context, language_mode,
                                     inner_result, vector);
1261 1262
        Handle<Script> script(Script::cast(inner_result->script()), isolate);
        isolate->debug()->OnAfterCompile(script);
1263
        return inner_result;
1264 1265
      }
      // Deserializer failed. Fall through to compile.
1266 1267 1268 1269 1270 1271 1272
    } else {
      if (pair.has_shared()) {
        result = Handle<SharedFunctionInfo>(pair.shared(), isolate);
      }
      if (pair.has_vector()) {
        vector = Handle<Cell>(pair.vector(), isolate);
      }
1273
    }
1274 1275
  }

1276 1277 1278 1279 1280 1281
  base::ElapsedTimer timer;
  if (FLAG_profile_deserialization && FLAG_serialize_toplevel &&
      compile_options == ScriptCompiler::kProduceCodeCache) {
    timer.Start();
  }

1282
  if (result.is_null() ||
1283 1284 1285
      (FLAG_serialize_toplevel &&
       compile_options == ScriptCompiler::kProduceCodeCache)) {
    // No cache entry found, or embedder wants a code cache. Compile the script.
1286 1287

    // Create a script object describing the script to be compiled.
1288
    Handle<Script> script = isolate->factory()->NewScript(source);
1289 1290 1291
    if (isolate->NeedsSourcePositionsForProfiling()) {
      Script::InitLineEnds(script);
    }
1292
    if (natives == NATIVES_CODE) {
1293
      script->set_type(Script::TYPE_NATIVE);
1294 1295
    } else if (natives == EXTENSION_CODE) {
      script->set_type(Script::TYPE_EXTENSION);
1296 1297
    } else if (natives == INSPECTOR_CODE) {
      script->set_type(Script::TYPE_INSPECTOR);
1298
    }
1299 1300
    if (!script_name.is_null()) {
      script->set_name(*script_name);
1301 1302
      script->set_line_offset(line_offset);
      script->set_column_offset(column_offset);
1303
    }
1304
    script->set_origin_options(resource_options);
1305 1306 1307
    if (!source_map_url.is_null()) {
      script->set_source_mapping_url(*source_map_url);
    }
1308 1309 1310
    if (!host_defined_options.is_null()) {
      script->set_host_defined_options(*host_defined_options);
    }
1311 1312

    // Compile the function and add it to the cache.
1313
    ParseInfo parse_info(script);
1314
    Zone compile_zone(isolate->allocator(), ZONE_NAME);
1315
    if (resource_options.IsModule()) parse_info.set_module();
1316
    if (compile_options != ScriptCompiler::kNoCompileOptions) {
1317
      parse_info.set_cached_data(cached_data);
1318
    }
1319 1320
    parse_info.set_compile_options(compile_options);
    parse_info.set_extension(extension);
1321 1322 1323
    if (!context->IsNativeContext()) {
      parse_info.set_outer_scope_info(handle(context->scope_info()));
    }
1324 1325
    if (FLAG_serialize_toplevel &&
        compile_options == ScriptCompiler::kProduceCodeCache) {
1326
      parse_info.set_will_serialize();
1327
    }
1328

1329
    parse_info.set_language_mode(
1330
        static_cast<LanguageMode>(parse_info.language_mode() | language_mode));
1331
    CompileToplevel(&parse_info, isolate).ToHandle(&result);
1332
    if (extension == NULL && !result.is_null()) {
1333 1334
      // We need a feedback vector.
      DCHECK(result->is_compiled());
1335
      Handle<FeedbackVector> feedback_vector =
1336
          FeedbackVector::New(isolate, result);
1337 1338 1339
      vector = isolate->factory()->NewCell(feedback_vector);
      compilation_cache->PutScript(source, context, language_mode, result,
                                   vector);
1340
      if (FLAG_serialize_toplevel &&
1341
          compile_options == ScriptCompiler::kProduceCodeCache &&
1342
          !ContainsAsmModule(script)) {
1343 1344
        HistogramTimerScope histogram_timer(
            isolate->counters()->compile_serialize());
1345 1346
        RuntimeCallTimerScope runtimeTimer(isolate,
                                           &RuntimeCallStats::CompileSerialize);
1347 1348
        TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.compile"),
                     "V8.CompileSerialize");
1349
        *cached_data = CodeSerializer::Serialize(isolate, result, source);
1350
        if (FLAG_profile_deserialization) {
1351 1352
          PrintF("[Compiling and serializing took %0.3f ms]\n",
                 timer.Elapsed().InMillisecondsF());
1353
        }
1354
      }
1355
    }
1356

1357
    if (result.is_null()) {
1358 1359 1360
      if (natives != EXTENSION_CODE && natives != NATIVES_CODE) {
        isolate->ReportPendingMessages();
      }
1361 1362 1363
    } else {
      isolate->debug()->OnAfterCompile(script);
    }
1364 1365 1366 1367
  }
  return result;
}

1368
Handle<SharedFunctionInfo> Compiler::GetSharedFunctionInfoForStreamedScript(
1369 1370 1371
    Handle<Script> script, ParseInfo* parse_info, int source_length) {
  Isolate* isolate = script->GetIsolate();
  // TODO(titzer): increment the counters in caller.
1372 1373 1374
  isolate->counters()->total_load_size()->Increment(source_length);
  isolate->counters()->total_compile_size()->Increment(source_length);

1375
  LanguageMode language_mode = construct_language_mode(FLAG_use_strict);
1376 1377
  parse_info->set_language_mode(
      static_cast<LanguageMode>(parse_info->language_mode() | language_mode));
1378

1379 1380 1381 1382
  Handle<SharedFunctionInfo> result;
  if (CompileToplevel(parse_info, isolate).ToHandle(&result)) {
    isolate->debug()->OnAfterCompile(script);
  }
1383
  return result;
1384 1385
}

1386
Handle<SharedFunctionInfo> Compiler::GetSharedFunctionInfo(
1387
    FunctionLiteral* literal, Handle<Script> script, Isolate* isolate) {
1388
  // Precondition: code has been parsed and scopes have been analyzed.
1389
  MaybeHandle<SharedFunctionInfo> maybe_existing;
1390 1391

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

1394
  // If we found an existing shared function info, return it.
1395
  Handle<SharedFunctionInfo> existing;
1396
  if (maybe_existing.ToHandle(&existing)) {
1397
    DCHECK(!existing->is_toplevel());
1398
    return existing;
1399 1400
  }

1401 1402 1403 1404 1405 1406 1407
  // 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());
1408 1409
  }
  return result;
1410 1411
}

1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429
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(
1430
      name, FunctionKind::kNormalFunction, code,
1431
      Handle<ScopeInfo>(fun->shared()->scope_info()));
1432
  shared->set_outer_scope_info(fun->shared()->outer_scope_info());
1433
  shared->SetConstructStub(*construct_stub);
1434
  shared->set_feedback_metadata(fun->shared()->feedback_metadata());
1435 1436 1437 1438 1439 1440 1441 1442

  // 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;
}
1443

1444
MaybeHandle<Code> Compiler::GetOptimizedCodeForOSR(Handle<JSFunction> function,
1445
                                                   BailoutId osr_offset,
1446
                                                   JavaScriptFrame* osr_frame) {
1447
  DCHECK(!osr_offset.IsNone());
1448
  DCHECK_NOT_NULL(osr_frame);
1449
  return GetOptimizedCode(function, ConcurrencyMode::kNotConcurrent, osr_offset,
1450
                          osr_frame);
1451 1452
}

1453
CompilationJob* Compiler::PrepareUnoptimizedCompilationJob(
1454
    ParseInfo* parse_info, Isolate* isolate) {
1455
  VMState<BYTECODE_COMPILER> state(isolate);
1456
  std::unique_ptr<CompilationJob> job(
1457 1458
      interpreter::Interpreter::NewCompilationJob(
          parse_info, parse_info->literal(), isolate));
1459 1460 1461 1462 1463 1464 1465
  if (job->PrepareJob() != CompilationJob::SUCCEEDED) {
    return nullptr;
  }
  return job.release();
}

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

1469
  if (job->compilation_info()->IsOptimizing()) {
1470
    VMState<COMPILER> state(job->compilation_info()->isolate());
1471 1472 1473
    return FinalizeOptimizedCompilationJob(job.get()) ==
           CompilationJob::SUCCEEDED;
  } else {
1474
    VMState<BYTECODE_COMPILER> state(job->compilation_info()->isolate());
1475 1476
    return FinalizeUnoptimizedCompilationJob(job.get()) ==
           CompilationJob::SUCCEEDED;
1477
  }
1478 1479
}

1480 1481 1482 1483
void Compiler::PostInstantiation(Handle<JSFunction> function,
                                 PretenureFlag pretenure) {
  Handle<SharedFunctionInfo> shared(function->shared());

1484
  if (FLAG_always_opt && shared->allows_lazy_compilation() &&
1485 1486
      !shared->optimization_disabled() && !shared->HasAsmWasmData() &&
      shared->is_compiled()) {
1487 1488 1489 1490 1491 1492 1493 1494 1495
    // 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);
      }
    }
1496 1497
  }

1498
  if (shared->is_compiled()) {
1499 1500
    // TODO(mvstanton): pass pretenure flag to EnsureLiterals.
    JSFunction::EnsureLiterals(function);
1501 1502 1503 1504 1505 1506 1507 1508

    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());
      function->ReplaceCode(code);
    }
1509 1510
  }
}
1511

1512 1513
}  // namespace internal
}  // namespace v8