| Index: src/compiler.cc | 
| diff --git a/src/compiler.cc b/src/compiler.cc | 
| index 7977bd04d3da23c6ef018fd343906bd241a27e86..8e9095bc1b1ae918c5e77866a2318838de0519f3 100644 | 
| --- a/src/compiler.cc | 
| +++ b/src/compiler.cc | 
| @@ -15,13 +15,10 @@ | 
| #include "src/compilation-cache.h" | 
| #include "src/compiler/pipeline.h" | 
| #include "src/crankshaft/hydrogen.h" | 
| -#include "src/crankshaft/lithium.h" | 
| -#include "src/crankshaft/typing.h" | 
| #include "src/debug/debug.h" | 
| #include "src/debug/liveedit.h" | 
| #include "src/deoptimizer.h" | 
| #include "src/full-codegen/full-codegen.h" | 
| -#include "src/gdb-jit.h" | 
| #include "src/interpreter/interpreter.h" | 
| #include "src/isolate-inl.h" | 
| #include "src/log-inl.h" | 
| @@ -102,6 +99,19 @@ class CompilationInfoWithZone : public CompilationInfo { | 
| Zone zone_; | 
| }; | 
|  | 
| +// 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_; | 
| +}; | 
| + | 
| // ---------------------------------------------------------------------------- | 
| // Implementation of CompilationInfo | 
|  | 
| @@ -306,51 +316,6 @@ void CompilationInfo::PrintAstForTesting() { | 
| // ---------------------------------------------------------------------------- | 
| // Implementation of OptimizedCompileJob | 
|  | 
| -class HOptimizedGraphBuilderWithPositions: public HOptimizedGraphBuilder { | 
| - public: | 
| -  explicit HOptimizedGraphBuilderWithPositions(CompilationInfo* info) | 
| -      : HOptimizedGraphBuilder(info) { | 
| -  } | 
| - | 
| -#define DEF_VISIT(type)                                      \ | 
| -  void Visit##type(type* node) override {                    \ | 
| -    SourcePosition old_position = SourcePosition::Unknown(); \ | 
| -    if (node->position() != RelocInfo::kNoPosition) {        \ | 
| -      old_position = source_position();                      \ | 
| -      SetSourcePosition(node->position());                   \ | 
| -    }                                                        \ | 
| -    HOptimizedGraphBuilder::Visit##type(node);               \ | 
| -    if (!old_position.IsUnknown()) {                         \ | 
| -      set_source_position(old_position);                     \ | 
| -    }                                                        \ | 
| -  } | 
| -  EXPRESSION_NODE_LIST(DEF_VISIT) | 
| -#undef DEF_VISIT | 
| - | 
| -#define DEF_VISIT(type)                                      \ | 
| -  void Visit##type(type* node) override {                    \ | 
| -    SourcePosition old_position = SourcePosition::Unknown(); \ | 
| -    if (node->position() != RelocInfo::kNoPosition) {        \ | 
| -      old_position = source_position();                      \ | 
| -      SetSourcePosition(node->position());                   \ | 
| -    }                                                        \ | 
| -    HOptimizedGraphBuilder::Visit##type(node);               \ | 
| -    if (!old_position.IsUnknown()) {                         \ | 
| -      set_source_position(old_position);                     \ | 
| -    }                                                        \ | 
| -  } | 
| -  STATEMENT_NODE_LIST(DEF_VISIT) | 
| -#undef DEF_VISIT | 
| - | 
| -#define DEF_VISIT(type)                        \ | 
| -  void Visit##type(type* node) override {      \ | 
| -    HOptimizedGraphBuilder::Visit##type(node); \ | 
| -  } | 
| -  DECLARATION_NODE_LIST(DEF_VISIT) | 
| -#undef DEF_VISIT | 
| -}; | 
| - | 
| - | 
| OptimizedCompileJob::Status OptimizedCompileJob::CreateGraph() { | 
| DCHECK(info()->IsOptimizing()); | 
|  | 
| @@ -393,126 +358,10 @@ OptimizedCompileJob::Status OptimizedCompileJob::CreateGraph() { | 
| DCHECK(info()->shared_info()->has_deoptimization_support()); | 
| DCHECK(!info()->is_first_compile()); | 
|  | 
| -  bool optimization_disabled = info()->shared_info()->optimization_disabled(); | 
| -  bool dont_crankshaft = info()->shared_info()->dont_crankshaft(); | 
| - | 
| -  // Check the enabling conditions for Turbofan. | 
| -  // 1. "use asm" code. | 
| -  bool is_turbofanable_asm = FLAG_turbo_asm && | 
| -                             info()->shared_info()->asm_function() && | 
| -                             !optimization_disabled; | 
| - | 
| -  // 2. Fallback for features unsupported by Crankshaft. | 
| -  bool is_unsupported_by_crankshaft_but_turbofanable = | 
| -      dont_crankshaft && strcmp(FLAG_turbo_filter, "~~") == 0 && | 
| -      !optimization_disabled; | 
| - | 
| -  // 3. Explicitly enabled by the command-line filter. | 
| -  bool passes_turbo_filter = | 
| -      info()->shared_info()->PassesFilter(FLAG_turbo_filter); | 
| - | 
| -  // If this is OSR request, OSR must be enabled by Turbofan. | 
| -  bool passes_osr_test = FLAG_turbo_osr || !info()->is_osr(); | 
| - | 
| -  if ((is_turbofanable_asm || is_unsupported_by_crankshaft_but_turbofanable || | 
| -       passes_turbo_filter) && | 
| -      passes_osr_test) { | 
| -    // Use TurboFan for the compilation. | 
| -    if (FLAG_trace_opt) { | 
| -      OFStream os(stdout); | 
| -      os << "[compiling method " << Brief(*info()->closure()) | 
| -         << " using TurboFan"; | 
| -      if (info()->is_osr()) os << " OSR"; | 
| -      os << "]" << std::endl; | 
| -    } | 
| - | 
| -    if (info()->shared_info()->asm_function()) { | 
| -      if (info()->osr_frame()) info()->MarkAsFrameSpecializing(); | 
| -      info()->MarkAsFunctionContextSpecializing(); | 
| -    } else { | 
| -      if (!FLAG_always_opt) { | 
| -        info()->MarkAsBailoutOnUninitialized(); | 
| -      } | 
| -      if (FLAG_native_context_specialization) { | 
| -        info()->MarkAsNativeContextSpecializing(); | 
| -        info()->MarkAsTypingEnabled(); | 
| -      } | 
| -    } | 
| -    if (!info()->shared_info()->asm_function() || | 
| -        FLAG_turbo_asm_deoptimization) { | 
| -      info()->MarkAsDeoptimizationEnabled(); | 
| -    } | 
| - | 
| -    Timer t(this, &time_taken_to_create_graph_); | 
| -    compiler::Pipeline pipeline(info()); | 
| -    pipeline.GenerateCode(); | 
| -    if (!info()->code().is_null()) { | 
| -      return SetLastStatus(SUCCEEDED); | 
| -    } | 
| -  } | 
| - | 
| -  if (!isolate()->use_crankshaft() || dont_crankshaft) { | 
| -    // Crankshaft is entirely disabled. | 
| -    return SetLastStatus(FAILED); | 
| -  } | 
| - | 
| -  Scope* scope = info()->scope(); | 
| -  if (LUnallocated::TooManyParameters(scope->num_parameters())) { | 
| -    // Crankshaft would require too many Lithium operands. | 
| -    return AbortOptimization(kTooManyParameters); | 
| -  } | 
| - | 
| -  if (info()->is_osr() && | 
| -      LUnallocated::TooManyParametersOrStackSlots(scope->num_parameters(), | 
| -                                                  scope->num_stack_slots())) { | 
| -    // Crankshaft would require too many Lithium operands. | 
| -    return AbortOptimization(kTooManyParametersLocals); | 
| -  } | 
| - | 
| -  if (FLAG_trace_opt) { | 
| -    OFStream os(stdout); | 
| -    os << "[compiling method " << Brief(*info()->closure()) | 
| -       << " using Crankshaft"; | 
| -    if (info()->is_osr()) os << " OSR"; | 
| -    os << "]" << std::endl; | 
| -  } | 
| - | 
| -  if (FLAG_trace_hydrogen) { | 
| -    isolate()->GetHTracer()->TraceCompilation(info()); | 
| -  } | 
| - | 
| -  // Type-check the function. | 
| -  AstTyper(info()->isolate(), info()->zone(), info()->closure(), | 
| -           info()->scope(), info()->osr_ast_id(), info()->literal()) | 
| -      .Run(); | 
| - | 
| -  // Optimization could have been disabled by the parser. Note that this check | 
| -  // is only needed because the Hydrogen graph builder is missing some bailouts. | 
| -  if (info()->shared_info()->optimization_disabled()) { | 
| -    return AbortOptimization( | 
| -        info()->shared_info()->disable_optimization_reason()); | 
| -  } | 
| - | 
| -  HOptimizedGraphBuilder* graph_builder = | 
| -      (info()->is_tracking_positions() || FLAG_trace_ic) | 
| -          ? new (info()->zone()) HOptimizedGraphBuilderWithPositions(info()) | 
| -          : new (info()->zone()) HOptimizedGraphBuilder(info()); | 
| - | 
| -  Timer t(this, &time_taken_to_create_graph_); | 
| -  graph_ = graph_builder->CreateGraph(); | 
| - | 
| -  if (isolate()->has_pending_exception()) { | 
| -    return SetLastStatus(FAILED); | 
| -  } | 
| - | 
| -  if (graph_ == NULL) return SetLastStatus(BAILED_OUT); | 
| - | 
| -  if (info()->dependencies()->HasAborted()) { | 
| -    // Dependency has changed during graph creation. Let's try again later. | 
| -    return RetryOptimization(kBailedOutDueToDependencyChange); | 
| -  } | 
| - | 
| -  return SetLastStatus(SUCCEEDED); | 
| +  // Delegate to the underlying implementation. | 
| +  DCHECK_EQ(SUCCEEDED, last_status()); | 
| +  ScopedTimer t(&time_taken_to_create_graph_); | 
| +  return SetLastStatus(CreateGraphImpl()); | 
| } | 
|  | 
|  | 
| @@ -522,24 +371,21 @@ OptimizedCompileJob::Status OptimizedCompileJob::OptimizeGraph() { | 
| DisallowHandleDereference no_deref; | 
| DisallowCodeDependencyChange no_dependency_change; | 
|  | 
| -  DCHECK(last_status() == SUCCEEDED); | 
| -  // TODO(turbofan): Currently everything is done in the first phase. | 
| -  if (!info()->code().is_null()) { | 
| -    return last_status(); | 
| -  } | 
| - | 
| -  Timer t(this, &time_taken_to_optimize_); | 
| -  DCHECK(graph_ != NULL); | 
| -  BailoutReason bailout_reason = kNoReason; | 
| +  // Delegate to the underlying implementation. | 
| +  DCHECK_EQ(SUCCEEDED, last_status()); | 
| +  ScopedTimer t(&time_taken_to_optimize_); | 
| +  return SetLastStatus(OptimizeGraphImpl()); | 
| +} | 
|  | 
| -  if (graph_->Optimize(&bailout_reason)) { | 
| -    chunk_ = LChunk::NewChunk(graph_); | 
| -    if (chunk_ != NULL) return SetLastStatus(SUCCEEDED); | 
| -  } else if (bailout_reason != kNoReason) { | 
| -    info_->AbortOptimization(bailout_reason); | 
| -  } | 
| +OptimizedCompileJob::Status OptimizedCompileJob::GenerateCode() { | 
| +  DisallowCodeDependencyChange no_dependency_change; | 
| +  DisallowJavascriptExecution no_js(isolate()); | 
| +  DCHECK(!info()->dependencies()->HasAborted()); | 
|  | 
| -  return SetLastStatus(BAILED_OUT); | 
| +  // Delegate to the underlying implementation. | 
| +  DCHECK_EQ(SUCCEEDED, last_status()); | 
| +  ScopedTimer t(&time_taken_to_codegen_); | 
| +  return SetLastStatus(GenerateCodeImpl()); | 
| } | 
|  | 
|  | 
| @@ -554,8 +400,10 @@ void AddWeakObjectToCodeDependency(Isolate* isolate, Handle<HeapObject> object, | 
| heap->AddWeakObjectToCodeDependency(object, dep); | 
| } | 
|  | 
| +}  // namespace | 
|  | 
| -void RegisterWeakObjectsInOptimizedCode(Handle<Code> code) { | 
| +void OptimizedCompileJob::RegisterWeakObjectsInOptimizedCode( | 
| +    Handle<Code> code) { | 
| // TODO(turbofan): Move this to pipeline.cc once Crankshaft dies. | 
| Isolate* const isolate = code->GetIsolate(); | 
| DCHECK(code->is_optimized_code()); | 
| @@ -595,51 +443,6 @@ void RegisterWeakObjectsInOptimizedCode(Handle<Code> code) { | 
| code->set_can_have_weak_objects(true); | 
| } | 
|  | 
| -}  // namespace | 
| - | 
| - | 
| -OptimizedCompileJob::Status OptimizedCompileJob::GenerateCode() { | 
| -  DCHECK(last_status() == SUCCEEDED); | 
| -  // TODO(turbofan): Currently everything is done in the first phase. | 
| -  if (!info()->code().is_null()) { | 
| -    info()->dependencies()->Commit(info()->code()); | 
| -    if (info()->is_deoptimization_enabled()) { | 
| -      info()->parse_info()->context()->native_context()->AddOptimizedCode( | 
| -          *info()->code()); | 
| -      RegisterWeakObjectsInOptimizedCode(info()->code()); | 
| -    } | 
| -    RecordOptimizationStats(); | 
| -    return last_status(); | 
| -  } | 
| - | 
| -  DCHECK(!info()->dependencies()->HasAborted()); | 
| -  DisallowCodeDependencyChange no_dependency_change; | 
| -  DisallowJavascriptExecution no_js(isolate()); | 
| -  {  // Scope for timer. | 
| -    Timer timer(this, &time_taken_to_codegen_); | 
| -    DCHECK(chunk_ != NULL); | 
| -    DCHECK(graph_ != NULL); | 
| -    // Deferred handles reference objects that were accessible during | 
| -    // graph creation.  To make sure that we don't encounter inconsistencies | 
| -    // between graph creation and code generation, we disallow accessing | 
| -    // objects through deferred handles during the latter, with exceptions. | 
| -    DisallowDeferredHandleDereference no_deferred_handle_deref; | 
| -    Handle<Code> optimized_code = chunk_->Codegen(); | 
| -    if (optimized_code.is_null()) { | 
| -      if (info()->bailout_reason() == kNoReason) { | 
| -        return AbortOptimization(kCodeGenerationFailed); | 
| -      } | 
| -      return SetLastStatus(BAILED_OUT); | 
| -    } | 
| -    RegisterWeakObjectsInOptimizedCode(optimized_code); | 
| -    info()->SetCode(optimized_code); | 
| -  } | 
| -  RecordOptimizationStats(); | 
| -  // Add to the weak list of optimized code objects. | 
| -  info()->context()->native_context()->AddOptimizedCode(*info()->code()); | 
| -  return SetLastStatus(SUCCEEDED); | 
| -} | 
| - | 
|  | 
| void OptimizedCompileJob::RecordOptimizationStats() { | 
| Handle<JSFunction> function = info()->closure(); | 
| @@ -937,6 +740,34 @@ bool Renumber(ParseInfo* parse_info) { | 
| return true; | 
| } | 
|  | 
| +bool UseTurboFan(CompilationInfo* info) { | 
| +  bool optimization_disabled = info->shared_info()->optimization_disabled(); | 
| +  bool dont_crankshaft = info->shared_info()->dont_crankshaft(); | 
| + | 
| +  // Check the enabling conditions for Turbofan. | 
| +  // 1. "use asm" code. | 
| +  bool is_turbofanable_asm = FLAG_turbo_asm && | 
| +                             info->shared_info()->asm_function() && | 
| +                             !optimization_disabled; | 
| + | 
| +  // 2. Fallback for features unsupported by Crankshaft. | 
| +  bool is_unsupported_by_crankshaft_but_turbofanable = | 
| +      dont_crankshaft && strcmp(FLAG_turbo_filter, "~~") == 0 && | 
| +      !optimization_disabled; | 
| + | 
| +  // 3. Explicitly enabled by the command-line filter. | 
| +  bool passes_turbo_filter = | 
| +      info->shared_info()->PassesFilter(FLAG_turbo_filter); | 
| + | 
| +  // If this is OSR request, OSR must be enabled by Turbofan. | 
| +  bool passes_osr_test = FLAG_turbo_osr || !info->is_osr(); | 
| + | 
| +  return (is_turbofanable_asm || | 
| +          is_unsupported_by_crankshaft_but_turbofanable || | 
| +          passes_turbo_filter) && | 
| +         passes_osr_test; | 
| +} | 
| + | 
| bool GetOptimizedCodeNow(CompilationInfo* info) { | 
| Isolate* isolate = info->isolate(); | 
| CanonicalHandleScope canonical(isolate); | 
| @@ -948,10 +779,12 @@ bool GetOptimizedCodeNow(CompilationInfo* info) { | 
| TimerEventScope<TimerEventRecompileSynchronous> timer(isolate); | 
| TRACE_EVENT0("v8", "V8.RecompileSynchronous"); | 
|  | 
| -  OptimizedCompileJob job(info); | 
| -  if (job.CreateGraph() != OptimizedCompileJob::SUCCEEDED || | 
| -      job.OptimizeGraph() != OptimizedCompileJob::SUCCEEDED || | 
| -      job.GenerateCode() != OptimizedCompileJob::SUCCEEDED) { | 
| +  OptimizedCompileJob* job = UseTurboFan(info) | 
| +                                 ? compiler::Pipeline::NewCompilationJob(info) | 
| +                                 : new (info->zone()) HCompilationJob(info); | 
| +  if (job->CreateGraph() != OptimizedCompileJob::SUCCEEDED || | 
| +      job->OptimizeGraph() != OptimizedCompileJob::SUCCEEDED || | 
| +      job->GenerateCode() != OptimizedCompileJob::SUCCEEDED) { | 
| if (FLAG_trace_opt) { | 
| PrintF("[aborted optimizing "); | 
| info->closure()->ShortPrint(); | 
| @@ -961,6 +794,7 @@ bool GetOptimizedCodeNow(CompilationInfo* info) { | 
| } | 
|  | 
| // Success! | 
| +  job->RecordOptimizationStats(); | 
| DCHECK(!isolate->has_pending_exception()); | 
| InsertCodeIntoOptimizedCodeMap(info); | 
| RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, info, | 
| @@ -993,7 +827,9 @@ bool GetOptimizedCodeLater(CompilationInfo* info) { | 
| TimerEventScope<TimerEventRecompileSynchronous> timer(info->isolate()); | 
| TRACE_EVENT0("v8", "V8.RecompileSynchronous"); | 
|  | 
| -  OptimizedCompileJob* job = new (info->zone()) OptimizedCompileJob(info); | 
| +  OptimizedCompileJob* job = UseTurboFan(info) | 
| +                                 ? compiler::Pipeline::NewCompilationJob(info) | 
| +                                 : new (info->zone()) HCompilationJob(info); | 
| OptimizedCompileJob::Status status = job->CreateGraph(); | 
| if (status != OptimizedCompileJob::SUCCEEDED) return false; | 
| isolate->optimizing_compile_dispatcher()->QueueForOptimization(job); | 
| @@ -1843,6 +1679,7 @@ void Compiler::FinalizeOptimizedCompileJob(OptimizedCompileJob* job) { | 
| } else if (info->dependencies()->HasAborted()) { | 
| job->RetryOptimization(kBailedOutDueToDependencyChange); | 
| } else if (job->GenerateCode() == OptimizedCompileJob::SUCCEEDED) { | 
| +      job->RecordOptimizationStats(); | 
| RecordFunctionCompilation(Logger::LAZY_COMPILE_TAG, info.get(), shared); | 
| if (shared->SearchOptimizedCodeMap(info->context()->native_context(), | 
| info->osr_ast_id()).code == nullptr) { | 
|  |