| Index: src/debug.cc | 
| diff --git a/src/debug.cc b/src/debug.cc | 
| index 1d90c2999a2bd0efb19080b1fac1ccca6beffaa7..a71315ad6976ce6003482c5af31d9e00af997b6d 100644 | 
| --- a/src/debug.cc | 
| +++ b/src/debug.cc | 
| @@ -36,7 +36,6 @@ Debug::Debug(Isolate* isolate) | 
| is_active_(false), | 
| is_suppressed_(false), | 
| live_edit_enabled_(true),  // TODO(yangguo): set to false by default. | 
| -      has_break_points_(false), | 
| break_disabled_(false), | 
| in_debug_event_listener_(false), | 
| break_on_exception_(false), | 
| @@ -146,7 +145,6 @@ void BreakLocation::Iterator::Next() { | 
| // the address. | 
| BreakLocation BreakLocation::FromAddress(Handle<DebugInfo> debug_info, | 
| BreakLocatorType type, Address pc) { | 
| -  DCHECK(debug_info->code()->has_debug_break_slots()); | 
| Iterator it(debug_info, type); | 
| it.SkipTo(BreakIndexFromAddress(debug_info, type, pc)); | 
| return it.GetBreakLocation(); | 
| @@ -158,7 +156,6 @@ BreakLocation BreakLocation::FromAddress(Handle<DebugInfo> debug_info, | 
| void BreakLocation::FromAddressSameStatement(Handle<DebugInfo> debug_info, | 
| BreakLocatorType type, Address pc, | 
| List<BreakLocation>* result_out) { | 
| -  DCHECK(debug_info->code()->has_debug_break_slots()); | 
| int break_index = BreakIndexFromAddress(debug_info, type, pc); | 
| Iterator it(debug_info, type); | 
| it.SkipTo(break_index); | 
| @@ -191,7 +188,6 @@ int BreakLocation::BreakIndexFromAddress(Handle<DebugInfo> debug_info, | 
| BreakLocation BreakLocation::FromPosition(Handle<DebugInfo> debug_info, | 
| BreakLocatorType type, int position, | 
| BreakPositionAlignment alignment) { | 
| -  DCHECK(debug_info->code()->has_debug_break_slots()); | 
| // Run through all break points to locate the one closest to the source | 
| // position. | 
| int closest_break = 0; | 
| @@ -222,7 +218,6 @@ BreakLocation BreakLocation::FromPosition(Handle<DebugInfo> debug_info, | 
| void BreakLocation::SetBreakPoint(Handle<Object> break_point_object) { | 
| // If there is not already a real break point here patch code with debug | 
| // break. | 
| -  DCHECK(code()->has_debug_break_slots()); | 
| if (!HasBreakPoint()) SetDebugBreak(); | 
| DCHECK(IsDebugBreak() || IsDebuggerStatement()); | 
| // Set the break point information. | 
| @@ -607,7 +602,7 @@ void Debug::Break(Arguments args, JavaScriptFrame* frame) { | 
| // Get the debug info (create it if it does not exist). | 
| Handle<SharedFunctionInfo> shared = | 
| Handle<SharedFunctionInfo>(frame->function()->shared()); | 
| -  Handle<DebugInfo> debug_info = GetDebugInfo(shared); | 
| +  Handle<DebugInfo> debug_info(shared->GetDebugInfo()); | 
|  | 
| // Find the break point where execution has stopped. | 
| // PC points to the instruction after the current one, possibly a break | 
| @@ -780,27 +775,11 @@ bool Debug::CheckBreakPoint(Handle<Object> break_point_object) { | 
| } | 
|  | 
|  | 
| -// Check whether the function has debug information. | 
| -bool Debug::HasDebugInfo(Handle<SharedFunctionInfo> shared) { | 
| -  return !shared->debug_info()->IsUndefined(); | 
| -} | 
| - | 
| - | 
| -// Return the debug info for this function. EnsureDebugInfo must be called | 
| -// prior to ensure the debug info has been generated for shared. | 
| -Handle<DebugInfo> Debug::GetDebugInfo(Handle<SharedFunctionInfo> shared) { | 
| -  DCHECK(HasDebugInfo(shared)); | 
| -  return Handle<DebugInfo>(DebugInfo::cast(shared->debug_info())); | 
| -} | 
| - | 
| - | 
| bool Debug::SetBreakPoint(Handle<JSFunction> function, | 
| Handle<Object> break_point_object, | 
| int* source_position) { | 
| HandleScope scope(isolate_); | 
|  | 
| -  PrepareForBreakPoints(); | 
| - | 
| // Make sure the function is compiled and has set up the debug info. | 
| Handle<SharedFunctionInfo> shared(function->shared()); | 
| if (!EnsureDebugInfo(shared, function)) { | 
| @@ -808,7 +787,7 @@ bool Debug::SetBreakPoint(Handle<JSFunction> function, | 
| return true; | 
| } | 
|  | 
| -  Handle<DebugInfo> debug_info = GetDebugInfo(shared); | 
| +  Handle<DebugInfo> debug_info(shared->GetDebugInfo()); | 
| // Source positions starts with zero. | 
| DCHECK(*source_position >= 0); | 
|  | 
| @@ -829,8 +808,6 @@ bool Debug::SetBreakPointForScript(Handle<Script> script, | 
| BreakPositionAlignment alignment) { | 
| HandleScope scope(isolate_); | 
|  | 
| -  PrepareForBreakPoints(); | 
| - | 
| // Obtain shared function info for the function. | 
| Handle<Object> result = | 
| FindSharedFunctionInfoInScript(script, *source_position); | 
| @@ -852,7 +829,7 @@ bool Debug::SetBreakPointForScript(Handle<Script> script, | 
| position = *source_position - shared->start_position(); | 
| } | 
|  | 
| -  Handle<DebugInfo> debug_info = GetDebugInfo(shared); | 
| +  Handle<DebugInfo> debug_info(shared->GetDebugInfo()); | 
| // Source positions starts with zero. | 
| DCHECK(position >= 0); | 
|  | 
| @@ -926,8 +903,6 @@ void Debug::ClearAllBreakPoints() { | 
|  | 
| void Debug::FloodWithOneShot(Handle<JSFunction> function, | 
| BreakLocatorType type) { | 
| -  PrepareForBreakPoints(); | 
| - | 
| // Make sure the function is compiled and has set up the debug info. | 
| Handle<SharedFunctionInfo> shared(function->shared()); | 
| if (!EnsureDebugInfo(shared, function)) { | 
| @@ -936,8 +911,8 @@ void Debug::FloodWithOneShot(Handle<JSFunction> function, | 
| } | 
|  | 
| // Flood the function with break points. | 
| -  for (BreakLocation::Iterator it(GetDebugInfo(shared), type); !it.Done(); | 
| -       it.Next()) { | 
| +  Handle<DebugInfo> debug_info(shared->GetDebugInfo()); | 
| +  for (BreakLocation::Iterator it(debug_info, type); !it.Done(); it.Next()) { | 
| it.GetBreakLocation().SetOneShot(); | 
| } | 
| } | 
| @@ -1033,13 +1008,18 @@ bool Debug::IsBreakOnException(ExceptionBreakType type) { | 
| } | 
|  | 
|  | 
| +FrameSummary GetFirstFrameSummary(JavaScriptFrame* frame) { | 
| +  List<FrameSummary> frames(FLAG_max_inlining_levels + 1); | 
| +  frame->Summarize(&frames); | 
| +  return frames.first(); | 
| +} | 
| + | 
| + | 
| void Debug::PrepareStep(StepAction step_action, | 
| int step_count, | 
| StackFrame::Id frame_id) { | 
| HandleScope scope(isolate_); | 
|  | 
| -  PrepareForBreakPoints(); | 
| - | 
| DCHECK(in_debug_scope()); | 
|  | 
| // Remember this step action and count. | 
| @@ -1084,22 +1064,18 @@ void Debug::PrepareStep(StepAction step_action, | 
| return; | 
| } | 
|  | 
| -  List<FrameSummary> frames(FLAG_max_inlining_levels + 1); | 
| -  frames_it.frame()->Summarize(&frames); | 
| -  FrameSummary summary = frames.first(); | 
| - | 
| // Get the debug info (create it if it does not exist). | 
| +  FrameSummary summary = GetFirstFrameSummary(frame); | 
| Handle<JSFunction> function(summary.function()); | 
| Handle<SharedFunctionInfo> shared(function->shared()); | 
| if (!EnsureDebugInfo(shared, function)) { | 
| // Return if ensuring debug info failed. | 
| return; | 
| } | 
| -  Handle<DebugInfo> debug_info = GetDebugInfo(shared); | 
|  | 
| -  // Compute whether or not the target is a call target. | 
| -  bool is_at_restarted_function = false; | 
| -  Handle<Code> call_function_stub; | 
| +  Handle<DebugInfo> debug_info(shared->GetDebugInfo()); | 
| +  // Refresh frame summary if the code has been recompiled for debugging. | 
| +  if (shared->code() != *summary.code()) summary = GetFirstFrameSummary(frame); | 
|  | 
| // PC points to the instruction after the current one, possibly a break | 
| // location as well. So the "- 1" to exclude it from the search. | 
| @@ -1107,10 +1083,6 @@ void Debug::PrepareStep(StepAction step_action, | 
| BreakLocation location = | 
| BreakLocation::FromAddress(debug_info, ALL_BREAK_LOCATIONS, call_pc); | 
|  | 
| -  if (thread_local_.restarter_frame_function_pointer_ != NULL) { | 
| -    is_at_restarted_function = true; | 
| -  } | 
| - | 
| // If this is the last break code target step out is the only possibility. | 
| if (location.IsReturn() || step_action == StepOut) { | 
| if (step_action == StepOut) { | 
| @@ -1142,7 +1114,7 @@ void Debug::PrepareStep(StepAction step_action, | 
| if (step_action != StepNext && step_action != StepMin) { | 
| // If there's restarter frame on top of the stack, just get the pointer | 
| // to function which is going to be restarted. | 
| -    if (is_at_restarted_function) { | 
| +    if (thread_local_.restarter_frame_function_pointer_ != NULL) { | 
| Handle<JSFunction> restarted_function( | 
| JSFunction::cast(*thread_local_.restarter_frame_function_pointer_)); | 
| FloodWithOneShot(restarted_function); | 
| @@ -1253,10 +1225,10 @@ Handle<Object> Debug::GetSourceBreakLocations( | 
| BreakPositionAlignment position_alignment) { | 
| Isolate* isolate = shared->GetIsolate(); | 
| Heap* heap = isolate->heap(); | 
| -  if (!HasDebugInfo(shared)) { | 
| +  if (!shared->HasDebugInfo()) { | 
| return Handle<Object>(heap->undefined_value(), isolate); | 
| } | 
| -  Handle<DebugInfo> debug_info = GetDebugInfo(shared); | 
| +  Handle<DebugInfo> debug_info(shared->GetDebugInfo()); | 
| if (debug_info->GetBreakPointCount() == 0) { | 
| return Handle<Object>(heap->undefined_value(), isolate); | 
| } | 
| @@ -1369,42 +1341,12 @@ void Debug::ClearStepNext() { | 
| } | 
|  | 
|  | 
| -static void CollectActiveFunctionsFromThread( | 
| -    Isolate* isolate, | 
| -    ThreadLocalTop* top, | 
| -    List<Handle<JSFunction> >* active_functions, | 
| -    Object* active_code_marker) { | 
| -  // Find all non-optimized code functions with activation frames | 
| -  // on the stack. This includes functions which have optimized | 
| -  // activations (including inlined functions) on the stack as the | 
| -  // non-optimized code is needed for the lazy deoptimization. | 
| -  for (JavaScriptFrameIterator it(isolate, top); !it.done(); it.Advance()) { | 
| -    JavaScriptFrame* frame = it.frame(); | 
| -    if (frame->is_optimized()) { | 
| -      List<JSFunction*> functions(FLAG_max_inlining_levels + 1); | 
| -      frame->GetFunctions(&functions); | 
| -      for (int i = 0; i < functions.length(); i++) { | 
| -        JSFunction* function = functions[i]; | 
| -        active_functions->Add(Handle<JSFunction>(function)); | 
| -        function->shared()->code()->set_gc_metadata(active_code_marker); | 
| -      } | 
| -    } else if (frame->function()->IsJSFunction()) { | 
| -      JSFunction* function = frame->function(); | 
| -      DCHECK(frame->LookupCode()->kind() == Code::FUNCTION); | 
| -      active_functions->Add(Handle<JSFunction>(function)); | 
| -      function->shared()->code()->set_gc_metadata(active_code_marker); | 
| -    } | 
| -  } | 
| -} | 
| - | 
| - | 
| // Count the number of calls before the current frame PC to find the | 
| // corresponding PC in the newly recompiled code. | 
| static Address ComputeNewPcForRedirect(Code* new_code, Code* old_code, | 
| Address old_pc) { | 
| DCHECK_EQ(old_code->kind(), Code::FUNCTION); | 
| DCHECK_EQ(new_code->kind(), Code::FUNCTION); | 
| -  DCHECK(!old_code->has_debug_break_slots()); | 
| DCHECK(new_code->has_debug_break_slots()); | 
| int mask = RelocInfo::kCodeTargetMask; | 
| int index = 0; | 
| @@ -1427,7 +1369,6 @@ static Address ComputeNewPcForRedirect(Code* new_code, Code* old_code, | 
| // Count the number of continuations at which the current pc offset is at. | 
| static int ComputeContinuationIndexFromPcOffset(Code* code, int pc_offset) { | 
| DCHECK_EQ(code->kind(), Code::FUNCTION); | 
| -  DCHECK(!code->has_debug_break_slots()); | 
| Address pc = code->instruction_start() + pc_offset; | 
| int mask = RelocInfo::ModeMask(RelocInfo::GENERATOR_CONTINUATION); | 
| int index = 0; | 
| @@ -1453,301 +1394,120 @@ static int ComputePcOffsetFromContinuationIndex(Code* code, int index) { | 
| } | 
|  | 
|  | 
| -static void RedirectActivationsToRecompiledCodeOnThread( | 
| -    Isolate* isolate, | 
| -    ThreadLocalTop* top) { | 
| -  for (JavaScriptFrameIterator it(isolate, top); !it.done(); it.Advance()) { | 
| -    JavaScriptFrame* frame = it.frame(); | 
| - | 
| -    if (frame->is_optimized() || !frame->function()->IsJSFunction()) continue; | 
| - | 
| -    JSFunction* function = frame->function(); | 
| - | 
| -    DCHECK(frame->LookupCode()->kind() == Code::FUNCTION); | 
| - | 
| -    Handle<Code> frame_code(frame->LookupCode()); | 
| -    if (frame_code->has_debug_break_slots()) continue; | 
| - | 
| -    Handle<Code> new_code(function->shared()->code()); | 
| -    if (new_code->kind() != Code::FUNCTION || | 
| -        !new_code->has_debug_break_slots()) { | 
| -      continue; | 
| -    } | 
| - | 
| -    Address new_pc = | 
| -        ComputeNewPcForRedirect(*new_code, *frame_code, frame->pc()); | 
| - | 
| -    if (FLAG_trace_deopt) { | 
| -      PrintF("Replacing code %08" V8PRIxPTR " - %08" V8PRIxPTR " (%d) " | 
| -             "with %08" V8PRIxPTR " - %08" V8PRIxPTR " (%d) " | 
| -             "for debugging, " | 
| -             "changing pc from %08" V8PRIxPTR " to %08" V8PRIxPTR "\n", | 
| -             reinterpret_cast<intptr_t>( | 
| -                 frame_code->instruction_start()), | 
| -             reinterpret_cast<intptr_t>( | 
| -                 frame_code->instruction_start()) + | 
| -             frame_code->instruction_size(), | 
| -             frame_code->instruction_size(), | 
| -             reinterpret_cast<intptr_t>(new_code->instruction_start()), | 
| -             reinterpret_cast<intptr_t>(new_code->instruction_start()) + | 
| -             new_code->instruction_size(), | 
| -             new_code->instruction_size(), | 
| -             reinterpret_cast<intptr_t>(frame->pc()), | 
| -             reinterpret_cast<intptr_t>(new_pc)); | 
| -    } | 
| - | 
| -    if (FLAG_enable_embedded_constant_pool) { | 
| -      // Update constant pool pointer for new code. | 
| -      frame->set_constant_pool(new_code->constant_pool()); | 
| -    } | 
| - | 
| -    // Patch the return address to return into the code with | 
| -    // debug break slots. | 
| -    frame->set_pc(new_pc); | 
| +class RedirectActiveFunctions : public ThreadVisitor { | 
| + public: | 
| +  explicit RedirectActiveFunctions(SharedFunctionInfo* shared) | 
| +      : shared_(shared) { | 
| +    DCHECK(shared->HasDebugCode()); | 
| } | 
| -} | 
|  | 
| +  void VisitThread(Isolate* isolate, ThreadLocalTop* top) { | 
| +    for (JavaScriptFrameIterator it(isolate, top); !it.done(); it.Advance()) { | 
| +      JavaScriptFrame* frame = it.frame(); | 
| +      JSFunction* function = frame->function(); | 
| +      if (frame->is_optimized()) continue; | 
| +      if (!function->Inlines(shared_)) continue; | 
| + | 
| +      Code* frame_code = frame->LookupCode(); | 
| +      DCHECK(frame_code->kind() == Code::FUNCTION); | 
| +      if (frame_code->has_debug_break_slots()) continue; | 
| + | 
| +      Code* new_code = function->shared()->code(); | 
| +      Address old_pc = frame->pc(); | 
| +      Address new_pc = ComputeNewPcForRedirect(new_code, frame_code, old_pc); | 
| + | 
| +      if (FLAG_trace_deopt) { | 
| +        PrintF("Replacing pc for debugging: %08" V8PRIxPTR " => %08" V8PRIxPTR | 
| +               "\n", | 
| +               reinterpret_cast<intptr_t>(old_pc), | 
| +               reinterpret_cast<intptr_t>(new_pc)); | 
| +      } | 
|  | 
| -class ActiveFunctionsCollector : public ThreadVisitor { | 
| - public: | 
| -  explicit ActiveFunctionsCollector(List<Handle<JSFunction> >* active_functions, | 
| -                                    Object* active_code_marker) | 
| -      : active_functions_(active_functions), | 
| -        active_code_marker_(active_code_marker) { } | 
| +      if (FLAG_enable_embedded_constant_pool) { | 
| +        // Update constant pool pointer for new code. | 
| +        frame->set_constant_pool(new_code->constant_pool()); | 
| +      } | 
|  | 
| -  void VisitThread(Isolate* isolate, ThreadLocalTop* top) { | 
| -    CollectActiveFunctionsFromThread(isolate, | 
| -                                     top, | 
| -                                     active_functions_, | 
| -                                     active_code_marker_); | 
| +      // Patch the return address to return into the code with | 
| +      // debug break slots. | 
| +      frame->set_pc(new_pc); | 
| +    } | 
| } | 
|  | 
| private: | 
| -  List<Handle<JSFunction> >* active_functions_; | 
| -  Object* active_code_marker_; | 
| +  SharedFunctionInfo* shared_; | 
| +  DisallowHeapAllocation no_gc_; | 
| }; | 
|  | 
|  | 
| -class ActiveFunctionsRedirector : public ThreadVisitor { | 
| - public: | 
| -  void VisitThread(Isolate* isolate, ThreadLocalTop* top) { | 
| -    RedirectActivationsToRecompiledCodeOnThread(isolate, top); | 
| -  } | 
| -}; | 
| - | 
| +bool Debug::PrepareFunctionForBreakPoints(Handle<SharedFunctionInfo> shared) { | 
| +  DCHECK(shared->is_compiled()); | 
|  | 
| -static void EnsureFunctionHasDebugBreakSlots(Handle<JSFunction> function) { | 
| -  if (function->code()->kind() == Code::FUNCTION && | 
| -      function->code()->has_debug_break_slots()) { | 
| -    // Nothing to do. Function code already had debug break slots. | 
| -    return; | 
| +  if (isolate_->concurrent_recompilation_enabled()) { | 
| +    isolate_->optimizing_compile_dispatcher()->Flush(); | 
| } | 
| -  // Make sure that the shared full code is compiled with debug | 
| -  // break slots. | 
| -  if (!function->shared()->code()->has_debug_break_slots()) { | 
| -    MaybeHandle<Code> code = Compiler::GetDebugCode(function); | 
| -    // Recompilation can fail.  In that case leave the code as it was. | 
| -    if (!code.is_null()) function->ReplaceCode(*code.ToHandleChecked()); | 
| -  } else { | 
| -    // Simply use shared code if it has debug break slots. | 
| -    function->ReplaceCode(function->shared()->code()); | 
| -  } | 
| -} | 
| - | 
|  | 
| -static void RecompileAndRelocateSuspendedGenerators( | 
| -    const List<Handle<JSGeneratorObject> > &generators) { | 
| -  for (int i = 0; i < generators.length(); i++) { | 
| -    Handle<JSFunction> fun(generators[i]->function()); | 
| +  List<Handle<JSFunction> > functions; | 
| +  List<Handle<JSGeneratorObject> > suspended_generators; | 
|  | 
| -    EnsureFunctionHasDebugBreakSlots(fun); | 
| - | 
| -    int index = generators[i]->continuation(); | 
| -    int pc_offset = ComputePcOffsetFromContinuationIndex(fun->code(), index); | 
| -    generators[i]->set_continuation(pc_offset); | 
| +  if (!shared->optimized_code_map()->IsSmi()) { | 
| +    shared->ClearOptimizedCodeMap(); | 
| } | 
| -} | 
| - | 
| - | 
| -static bool SkipSharedFunctionInfo(SharedFunctionInfo* shared, | 
| -                                   Object* active_code_marker) { | 
| -  if (!shared->allows_lazy_compilation()) return true; | 
| -  Object* script = shared->script(); | 
| -  if (!script->IsScript()) return true; | 
| -  if (Script::cast(script)->type()->value() == Script::TYPE_NATIVE) return true; | 
| -  Code* shared_code = shared->code(); | 
| -  return shared_code->gc_metadata() == active_code_marker; | 
| -} | 
| - | 
| - | 
| -static inline bool HasDebugBreakSlots(Code* code) { | 
| -  return code->kind() == Code::FUNCTION && code->has_debug_break_slots(); | 
| -} | 
| - | 
| - | 
| -void Debug::PrepareForBreakPoints() { | 
| -  // If preparing for the first break point make sure to deoptimize all | 
| -  // functions as debugging does not work with optimized code. | 
| -  if (!has_break_points_) { | 
| -    if (isolate_->concurrent_recompilation_enabled()) { | 
| -      isolate_->optimizing_compile_dispatcher()->Flush(); | 
| -    } | 
| - | 
| -    Deoptimizer::DeoptimizeAll(isolate_); | 
| - | 
| -    Handle<Code> lazy_compile = isolate_->builtins()->CompileLazy(); | 
| - | 
| -    // There will be at least one break point when we are done. | 
| -    has_break_points_ = true; | 
| - | 
| -    // Keep the list of activated functions in a handlified list as it | 
| -    // is used both in GC and non-GC code. | 
| -    List<Handle<JSFunction> > active_functions(100); | 
| - | 
| -    // A list of all suspended generators. | 
| -    List<Handle<JSGeneratorObject> > suspended_generators; | 
|  | 
| -    // A list of all generator functions.  We need to recompile all functions, | 
| -    // but we don't know until after visiting the whole heap which generator | 
| -    // functions have suspended activations and which do not.  As in the case of | 
| -    // functions with activations on the stack, we need to be careful with | 
| -    // generator functions with suspended activations because although they | 
| -    // should be recompiled, recompilation can fail, and we need to avoid | 
| -    // leaving the heap in an inconsistent state. | 
| -    // | 
| -    // We could perhaps avoid this list and instead re-use the GC metadata | 
| -    // links. | 
| -    List<Handle<JSFunction> > generator_functions; | 
| +  // Make sure we abort incremental marking. | 
| +  isolate_->heap()->CollectAllGarbage(Heap::kMakeHeapIterableMask, | 
| +                                      "prepare for break points"); | 
|  | 
| -    { | 
| -      // We are going to iterate heap to find all functions without | 
| -      // debug break slots. | 
| -      Heap* heap = isolate_->heap(); | 
| -      heap->CollectAllGarbage(Heap::kMakeHeapIterableMask, | 
| -                              "preparing for breakpoints"); | 
| -      HeapIterator iterator(heap); | 
| - | 
| -      // Ensure no GC in this scope as we are going to use gc_metadata | 
| -      // field in the Code object to mark active functions. | 
| -      DisallowHeapAllocation no_allocation; | 
| - | 
| -      Object* active_code_marker = heap->the_hole_value(); | 
| - | 
| -      CollectActiveFunctionsFromThread(isolate_, | 
| -                                       isolate_->thread_local_top(), | 
| -                                       &active_functions, | 
| -                                       active_code_marker); | 
| -      ActiveFunctionsCollector active_functions_collector(&active_functions, | 
| -                                                          active_code_marker); | 
| -      isolate_->thread_manager()->IterateArchivedThreads( | 
| -          &active_functions_collector); | 
| - | 
| -      // Scan the heap for all non-optimized functions which have no | 
| -      // debug break slots and are not active or inlined into an active | 
| -      // function and mark them for lazy compilation. | 
| -      HeapObject* obj = NULL; | 
| -      while (((obj = iterator.next()) != NULL)) { | 
| -        if (obj->IsJSFunction()) { | 
| -          JSFunction* function = JSFunction::cast(obj); | 
| -          SharedFunctionInfo* shared = function->shared(); | 
| -          if (SkipSharedFunctionInfo(shared, active_code_marker)) continue; | 
| -          if (shared->is_generator()) { | 
| -            generator_functions.Add(Handle<JSFunction>(function, isolate_)); | 
| -            continue; | 
| -          } | 
| -          if (HasDebugBreakSlots(function->code())) continue; | 
| -          Code* fallback = HasDebugBreakSlots(shared->code()) ? shared->code() | 
| -                                                              : *lazy_compile; | 
| -          Code::Kind kind = function->code()->kind(); | 
| -          if (kind == Code::FUNCTION || | 
| -              (kind == Code::BUILTIN &&  // Abort in-flight compilation. | 
| -               (function->IsInOptimizationQueue() || | 
| -                function->IsMarkedForOptimization() || | 
| -                function->IsMarkedForConcurrentOptimization()))) { | 
| -            function->ReplaceCode(fallback); | 
| -          } | 
| -          if (kind == Code::OPTIMIZED_FUNCTION) { | 
| -            // Optimized code can only get here if DeoptimizeAll did not | 
| -            // deoptimize turbo fan code. | 
| -            DCHECK(!FLAG_turbo_asm_deoptimization); | 
| -            DCHECK(function->shared()->asm_function()); | 
| -            DCHECK(function->code()->is_turbofanned()); | 
| -            function->ReplaceCode(fallback); | 
| -          } | 
| -        } else if (obj->IsJSGeneratorObject()) { | 
| -          JSGeneratorObject* gen = JSGeneratorObject::cast(obj); | 
| -          if (!gen->is_suspended()) continue; | 
| - | 
| -          JSFunction* fun = gen->function(); | 
| -          DCHECK_EQ(fun->code()->kind(), Code::FUNCTION); | 
| -          if (fun->code()->has_debug_break_slots()) continue; | 
| - | 
| -          int pc_offset = gen->continuation(); | 
| -          DCHECK_LT(0, pc_offset); | 
| - | 
| -          int index = | 
| -              ComputeContinuationIndexFromPcOffset(fun->code(), pc_offset); | 
| - | 
| -          // This will be fixed after we recompile the functions. | 
| -          gen->set_continuation(index); | 
| - | 
| -          suspended_generators.Add(Handle<JSGeneratorObject>(gen, isolate_)); | 
| -        } else if (obj->IsSharedFunctionInfo()) { | 
| -          SharedFunctionInfo* shared = SharedFunctionInfo::cast(obj); | 
| -          if (SkipSharedFunctionInfo(shared, active_code_marker)) continue; | 
| -          if (shared->is_generator()) continue; | 
| -          if (HasDebugBreakSlots(shared->code())) continue; | 
| -          shared->ReplaceCode(*lazy_compile); | 
| +  { | 
| +    HeapIterator iterator(isolate_->heap()); | 
| +    HeapObject* obj; | 
| +    bool include_generators = shared->is_generator(); | 
| + | 
| +    while ((obj = iterator.next())) { | 
| +      if (obj->IsJSFunction()) { | 
| +        JSFunction* function = JSFunction::cast(obj); | 
| +        if (!function->Inlines(*shared)) continue; | 
| +        if (function->code()->kind() == Code::OPTIMIZED_FUNCTION) { | 
| +          Deoptimizer::DeoptimizeFunction(function); | 
| } | 
| -      } | 
| - | 
| -      // Clear gc_metadata field. | 
| -      for (int i = 0; i < active_functions.length(); i++) { | 
| -        Handle<JSFunction> function = active_functions[i]; | 
| -        function->shared()->code()->set_gc_metadata(Smi::FromInt(0)); | 
| +        functions.Add(handle(function)); | 
| +      } else if (include_generators && obj->IsJSGeneratorObject()) { | 
| +        JSGeneratorObject* generator_obj = JSGeneratorObject::cast(obj); | 
| +        if (!generator_obj->is_suspended()) continue; | 
| +        JSFunction* function = generator_obj->function(); | 
| +        if (!function->Inlines(*shared)) continue; | 
| +        int pc_offset = generator_obj->continuation(); | 
| +        int index = | 
| +            ComputeContinuationIndexFromPcOffset(function->code(), pc_offset); | 
| +        generator_obj->set_continuation(index); | 
| +        suspended_generators.Add(handle(generator_obj)); | 
| } | 
| } | 
| +  } | 
|  | 
| -    // Recompile generator functions that have suspended activations, and | 
| -    // relocate those activations. | 
| -    RecompileAndRelocateSuspendedGenerators(suspended_generators); | 
| - | 
| -    // Mark generator functions that didn't have suspended activations for lazy | 
| -    // recompilation.  Note that this set does not include any active functions. | 
| -    for (int i = 0; i < generator_functions.length(); i++) { | 
| -      Handle<JSFunction> &function = generator_functions[i]; | 
| -      if (function->code()->kind() != Code::FUNCTION) continue; | 
| -      if (function->code()->has_debug_break_slots()) continue; | 
| -      function->ReplaceCode(*lazy_compile); | 
| -      function->shared()->ReplaceCode(*lazy_compile); | 
| +  if (!shared->HasDebugCode()) { | 
| +    DCHECK(functions.length() > 0); | 
| +    if (Compiler::GetDebugCode(functions.first()).is_null()) { | 
| +      return false; | 
| } | 
| +  } | 
|  | 
| -    // Now recompile all functions with activation frames and and | 
| -    // patch the return address to run in the new compiled code.  It could be | 
| -    // that some active functions were recompiled already by the suspended | 
| -    // generator recompilation pass above; a generator with suspended | 
| -    // activations could also have active activations.  That's fine. | 
| -    for (int i = 0; i < active_functions.length(); i++) { | 
| -      Handle<JSFunction> function = active_functions[i]; | 
| -      Handle<SharedFunctionInfo> shared(function->shared()); | 
| -      if (!shared->allows_lazy_compilation()) { | 
| -        // Ignore functions that cannot be recompiled. Fortunately, those are | 
| -        // only ones that are not subject to debugging in the first place. | 
| -        DCHECK(!function->IsSubjectToDebugging()); | 
| -        continue; | 
| -      } | 
| -      if (shared->code()->kind() == Code::BUILTIN) continue; | 
| +  for (Handle<JSFunction> const function : functions) { | 
| +    function->ReplaceCode(shared->code()); | 
| +  } | 
|  | 
| -      EnsureFunctionHasDebugBreakSlots(function); | 
| -    } | 
| +  for (Handle<JSGeneratorObject> const generator_obj : suspended_generators) { | 
| +    int index = generator_obj->continuation(); | 
| +    int pc_offset = ComputePcOffsetFromContinuationIndex(shared->code(), index); | 
| +    generator_obj->set_continuation(pc_offset); | 
| +  } | 
|  | 
| -    RedirectActivationsToRecompiledCodeOnThread(isolate_, | 
| -                                                isolate_->thread_local_top()); | 
| +  // Update PCs on the stack to point to recompiled code. | 
| +  RedirectActiveFunctions redirect_visitor(*shared); | 
| +  redirect_visitor.VisitThread(isolate_, isolate_->thread_local_top()); | 
| +  isolate_->thread_manager()->IterateArchivedThreads(&redirect_visitor); | 
|  | 
| -    ActiveFunctionsRedirector active_functions_redirector; | 
| -    isolate_->thread_manager()->IterateArchivedThreads( | 
| -          &active_functions_redirector); | 
| -  } | 
| +  return true; | 
| } | 
|  | 
|  | 
| @@ -1799,20 +1559,12 @@ class SharedFunctionInfoFinder { | 
| }; | 
|  | 
|  | 
| -template <typename C> | 
| -bool Debug::CompileToRevealInnerFunctions(C* compilable) { | 
| -  HandleScope scope(isolate_); | 
| -  // Force compiling inner functions that require context. | 
| -  // TODO(yangguo): remove this hack. | 
| -  bool has_break_points = has_break_points_; | 
| -  has_break_points_ = true; | 
| -  Handle<C> compilable_handle(compilable); | 
| -  bool result = !Compiler::GetUnoptimizedCode(compilable_handle).is_null(); | 
| -  has_break_points_ = has_break_points; | 
| -  return result; | 
| -} | 
| - | 
| - | 
| +// We need to find a SFI for a literal that may not yet have been compiled yet, | 
| +// and there may not be a JSFunction referencing it. Find the SFI closest to | 
| +// the given position, compile it to reveal possible inner SFIs and repeat. | 
| +// While we are at this, also ensure code with debug break slots so that we do | 
| +// not have to compile a SFI without JSFunction, which is paifu for those that | 
| +// cannot be compiled without context (need to find outer compilable SFI etc.) | 
| Handle<Object> Debug::FindSharedFunctionInfoInScript(Handle<Script> script, | 
| int position) { | 
| while (true) { | 
| @@ -1832,19 +1584,20 @@ Handle<Object> Debug::FindSharedFunctionInfoInScript(Handle<Script> script, | 
| } | 
| shared = finder.Result(); | 
| if (shared == NULL) break; | 
| -      // We found it if it's already compiled. | 
| -      if (shared->is_compiled()) return handle(shared); | 
| +      // We found it if it's already compiled and has debug code. | 
| +      if (shared->HasDebugCode()) return handle(shared); | 
| } | 
| // If not, compile to reveal inner functions, if possible. | 
| if (shared->allows_lazy_compilation_without_context()) { | 
| -      if (!CompileToRevealInnerFunctions(shared)) break; | 
| +      HandleScope scope(isolate_); | 
| +      if (Compiler::GetDebugCode(handle(shared)).is_null()) break; | 
| continue; | 
| } | 
|  | 
| // If not possible, comb the heap for the best suitable compile target. | 
| JSFunction* closure; | 
| { | 
| -      HeapIterator it(isolate_->heap(), HeapIterator::kNoFiltering); | 
| +      HeapIterator it(isolate_->heap()); | 
| SharedFunctionInfoFinder finder(position); | 
| while (HeapObject* object = it.next()) { | 
| JSFunction* candidate_closure = NULL; | 
| @@ -1865,9 +1618,11 @@ Handle<Object> Debug::FindSharedFunctionInfoInScript(Handle<Script> script, | 
| closure = finder.ResultClosure(); | 
| shared = finder.Result(); | 
| } | 
| -    if (closure == NULL ? !CompileToRevealInnerFunctions(shared) | 
| -                        : !CompileToRevealInnerFunctions(closure)) { | 
| -      break; | 
| +    HandleScope scope(isolate_); | 
| +    if (closure == NULL) { | 
| +      if (Compiler::GetDebugCode(handle(shared)).is_null()) break; | 
| +    } else { | 
| +      if (Compiler::GetDebugCode(handle(closure)).is_null()) break; | 
| } | 
| } | 
| return isolate_->factory()->undefined_value(); | 
| @@ -1880,30 +1635,23 @@ bool Debug::EnsureDebugInfo(Handle<SharedFunctionInfo> shared, | 
| if (!shared->IsSubjectToDebugging()) return false; | 
|  | 
| // Return if we already have the debug info for shared. | 
| -  if (HasDebugInfo(shared)) { | 
| -    DCHECK(shared->is_compiled()); | 
| -    DCHECK(shared->code()->has_debug_break_slots()); | 
| -    return true; | 
| -  } | 
| - | 
| -  // There will be at least one break point when we are done. | 
| -  has_break_points_ = true; | 
| +  if (shared->HasDebugInfo()) return true; | 
|  | 
| if (function.is_null()) { | 
| -    DCHECK(shared->is_compiled()); | 
| -    DCHECK(shared->code()->has_debug_break_slots()); | 
| +    DCHECK(shared->HasDebugCode()); | 
| } else if (!Compiler::EnsureCompiled(function, CLEAR_EXCEPTION)) { | 
| return false; | 
| } | 
|  | 
| +  if (!PrepareFunctionForBreakPoints(shared)) return false; | 
| + | 
| // Make sure IC state is clean. This is so that we correctly flood | 
| // accessor pairs when stepping in. | 
| shared->code()->ClearInlineCaches(); | 
| shared->feedback_vector()->ClearICSlots(*shared); | 
|  | 
| // Create the debug info object. | 
| -  DCHECK(shared->is_compiled()); | 
| -  DCHECK(shared->code()->has_debug_break_slots()); | 
| +  DCHECK(shared->HasDebugCode()); | 
| Handle<DebugInfo> debug_info = isolate_->factory()->NewDebugInfo(shared); | 
|  | 
| // Add debug info to the list. | 
| @@ -1923,10 +1671,6 @@ void Debug::RemoveDebugInfo(DebugInfoListNode* prev, DebugInfoListNode* node) { | 
| prev->set_next(node->next()); | 
| } | 
| delete node; | 
| - | 
| -  // If there are no more debug info objects there are not more break | 
| -  // points. | 
| -  has_break_points_ = debug_info_list_ != NULL; | 
| } | 
|  | 
|  | 
| @@ -1989,21 +1733,13 @@ void Debug::SetAfterBreakTarget(JavaScriptFrame* frame) { | 
| bool Debug::IsBreakAtReturn(JavaScriptFrame* frame) { | 
| HandleScope scope(isolate_); | 
|  | 
| -  // If there are no break points this cannot be break at return, as | 
| -  // the debugger statement and stack guard debug break cannot be at | 
| -  // return. | 
| -  if (!has_break_points_) return false; | 
| - | 
| -  PrepareForBreakPoints(); | 
| - | 
| // Get the executing function in which the debug break occurred. | 
| Handle<JSFunction> function(JSFunction::cast(frame->function())); | 
| Handle<SharedFunctionInfo> shared(function->shared()); | 
| -  if (!EnsureDebugInfo(shared, function)) { | 
| -    // Return if we failed to retrieve the debug info. | 
| -    return false; | 
| -  } | 
| -  Handle<DebugInfo> debug_info = GetDebugInfo(shared); | 
| + | 
| +  // With no debug info there are no break points, so we can't be at a return. | 
| +  if (!shared->HasDebugInfo()) return false; | 
| +  Handle<DebugInfo> debug_info(shared->GetDebugInfo()); | 
| Handle<Code> code(debug_info->code()); | 
| #ifdef DEBUG | 
| // Get the code which is actually executing. | 
| @@ -2014,7 +1750,7 @@ bool Debug::IsBreakAtReturn(JavaScriptFrame* frame) { | 
| // Find the reloc info matching the start of the debug break slot. | 
| Address slot_pc = frame->pc() - Assembler::kDebugBreakSlotLength; | 
| int mask = RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_RETURN); | 
| -  for (RelocIterator it(debug_info->code(), mask); !it.done(); it.next()) { | 
| +  for (RelocIterator it(*code, mask); !it.done(); it.next()) { | 
| if (it.rinfo()->pc() == slot_pc) return true; | 
| } | 
| return false; | 
| @@ -2068,6 +1804,44 @@ Handle<FixedArray> Debug::GetLoadedScripts() { | 
| } | 
|  | 
|  | 
| +void Debug::GetStepinPositions(JavaScriptFrame* frame, StackFrame::Id frame_id, | 
| +                               List<int>* results_out) { | 
| +  FrameSummary summary = GetFirstFrameSummary(frame); | 
| + | 
| +  Handle<JSFunction> fun = Handle<JSFunction>(summary.function()); | 
| +  Handle<SharedFunctionInfo> shared = Handle<SharedFunctionInfo>(fun->shared()); | 
| + | 
| +  if (!EnsureDebugInfo(shared, fun)) return; | 
| + | 
| +  Handle<DebugInfo> debug_info(shared->GetDebugInfo()); | 
| +  // Refresh frame summary if the code has been recompiled for debugging. | 
| +  if (shared->code() != *summary.code()) summary = GetFirstFrameSummary(frame); | 
| + | 
| +  // Find range of break points starting from the break point where execution | 
| +  // has stopped. | 
| +  Address call_pc = summary.pc() - 1; | 
| +  List<BreakLocation> locations; | 
| +  BreakLocation::FromAddressSameStatement(debug_info, ALL_BREAK_LOCATIONS, | 
| +                                          call_pc, &locations); | 
| + | 
| +  for (BreakLocation location : locations) { | 
| +    if (location.pc() <= summary.pc()) { | 
| +      // The break point is near our pc. Could be a step-in possibility, | 
| +      // that is currently taken by active debugger call. | 
| +      if (break_frame_id() == StackFrame::NO_ID) { | 
| +        continue;  // We are not stepping. | 
| +      } else { | 
| +        JavaScriptFrameIterator frame_it(isolate_, break_frame_id()); | 
| +        // If our frame is a top frame and we are stepping, we can do step-in | 
| +        // at this place. | 
| +        if (frame_it.frame()->id() != frame_id) continue; | 
| +      } | 
| +    } | 
| +    if (location.IsStepInLocation()) results_out->Add(location.position()); | 
| +  } | 
| +} | 
| + | 
| + | 
| void Debug::RecordEvalCaller(Handle<Script> script) { | 
| script->set_compilation_type(Script::COMPILATION_TYPE_EVAL); | 
| // For eval scripts add information on the function from which eval was | 
|  |