Merge V8 5.2.361.47  DO NOT MERGE

https://chromium.googlesource.com/v8/v8/+/5.2.361.47

FPIIM-449

Change-Id: Ibec421b85a9b88cb3a432ada642e469fe7e78346
(cherry picked from commit bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8)
diff --git a/src/debug/liveedit.cc b/src/debug/liveedit.cc
index 78ed6f1..50d60a1 100644
--- a/src/debug/liveedit.cc
+++ b/src/debug/liveedit.cc
@@ -13,6 +13,7 @@
 #include "src/deoptimizer.h"
 #include "src/frames-inl.h"
 #include "src/global-handles.h"
+#include "src/interpreter/source-position-table.h"
 #include "src/isolate-inl.h"
 #include "src/messages.h"
 #include "src/parsing/parser.h"
@@ -623,6 +624,8 @@
 
 void FunctionInfoWrapper::SetFunctionCode(Handle<Code> function_code,
                                           Handle<HeapObject> code_scope_info) {
+  // CompileForLiveEdit must deliver full-codegen code.
+  DCHECK(function_code->kind() == Code::FUNCTION);
   Handle<JSValue> code_wrapper = WrapInJSValue(function_code);
   this->SetField(kCodeOffset_, code_wrapper);
 
@@ -688,115 +691,6 @@
 }
 
 
-class FunctionInfoListener {
- public:
-  explicit FunctionInfoListener(Isolate* isolate) {
-    current_parent_index_ = -1;
-    len_ = 0;
-    result_ = isolate->factory()->NewJSArray(10);
-  }
-
-  void FunctionStarted(FunctionLiteral* fun) {
-    HandleScope scope(isolate());
-    FunctionInfoWrapper info = FunctionInfoWrapper::Create(isolate());
-    info.SetInitialProperties(fun->name(), fun->start_position(),
-                              fun->end_position(), fun->parameter_count(),
-                              fun->materialized_literal_count(),
-                              current_parent_index_);
-    current_parent_index_ = len_;
-    SetElementSloppy(result_, len_, info.GetJSArray());
-    len_++;
-  }
-
-  void FunctionDone() {
-    HandleScope scope(isolate());
-    FunctionInfoWrapper info = FunctionInfoWrapper::cast(
-        *JSReceiver::GetElement(isolate(), result_, current_parent_index_)
-             .ToHandleChecked());
-    current_parent_index_ = info.GetParentIndex();
-  }
-
-  // Saves only function code, because for a script function we
-  // may never create a SharedFunctionInfo object.
-  void FunctionCode(Handle<Code> function_code) {
-    FunctionInfoWrapper info = FunctionInfoWrapper::cast(
-        *JSReceiver::GetElement(isolate(), result_, current_parent_index_)
-             .ToHandleChecked());
-    info.SetFunctionCode(function_code,
-                         Handle<HeapObject>(isolate()->heap()->null_value()));
-  }
-
-  // Saves full information about a function: its code, its scope info
-  // and a SharedFunctionInfo object.
-  void FunctionInfo(Handle<SharedFunctionInfo> shared, Scope* scope,
-                    Zone* zone) {
-    if (!shared->IsSharedFunctionInfo()) {
-      return;
-    }
-    FunctionInfoWrapper info = FunctionInfoWrapper::cast(
-        *JSReceiver::GetElement(isolate(), result_, current_parent_index_)
-             .ToHandleChecked());
-    info.SetFunctionCode(Handle<Code>(shared->code()),
-                         Handle<HeapObject>(shared->scope_info()));
-    info.SetSharedFunctionInfo(shared);
-
-    Handle<Object> scope_info_list = SerializeFunctionScope(scope, zone);
-    info.SetFunctionScopeInfo(scope_info_list);
-  }
-
-  Handle<JSArray> GetResult() { return result_; }
-
- private:
-  Isolate* isolate() const { return result_->GetIsolate(); }
-
-  Handle<Object> SerializeFunctionScope(Scope* scope, Zone* zone) {
-    Handle<JSArray> scope_info_list = isolate()->factory()->NewJSArray(10);
-    int scope_info_length = 0;
-
-    // Saves some description of scope. It stores name and indexes of
-    // variables in the whole scope chain. Null-named slots delimit
-    // scopes of this chain.
-    Scope* current_scope = scope;
-    while (current_scope != NULL) {
-      HandleScope handle_scope(isolate());
-      ZoneList<Variable*> stack_list(current_scope->StackLocalCount(), zone);
-      ZoneList<Variable*> context_list(
-          current_scope->ContextLocalCount(), zone);
-      ZoneList<Variable*> globals_list(current_scope->ContextGlobalCount(),
-                                       zone);
-      current_scope->CollectStackAndContextLocals(&stack_list, &context_list,
-                                                  &globals_list);
-      context_list.Sort(&Variable::CompareIndex);
-
-      for (int i = 0; i < context_list.length(); i++) {
-        SetElementSloppy(scope_info_list,
-                         scope_info_length,
-                         context_list[i]->name());
-        scope_info_length++;
-        SetElementSloppy(
-            scope_info_list,
-            scope_info_length,
-            Handle<Smi>(Smi::FromInt(context_list[i]->index()), isolate()));
-        scope_info_length++;
-      }
-      SetElementSloppy(scope_info_list,
-                       scope_info_length,
-                       Handle<Object>(isolate()->heap()->null_value(),
-                                      isolate()));
-      scope_info_length++;
-
-      current_scope = current_scope->outer_scope();
-    }
-
-    return scope_info_list;
-  }
-
-  Handle<JSArray> result_;
-  int len_;
-  int current_parent_index_;
-};
-
-
 void LiveEdit::InitializeThreadLocal(Debug* debug) {
   debug->thread_local_.frame_drop_mode_ = LiveEdit::FRAMES_UNTOUCHED;
 }
@@ -832,11 +726,10 @@
                                                  Handle<String> source) {
   Isolate* isolate = script->GetIsolate();
 
-  FunctionInfoListener listener(isolate);
+  MaybeHandle<JSArray> infos;
   Handle<Object> original_source =
       Handle<Object>(script->source(), isolate);
   script->set_source(*source);
-  isolate->set_active_function_info_listener(&listener);
 
   {
     // Creating verbose TryCatch from public API is currently the only way to
@@ -845,7 +738,7 @@
     try_catch.SetVerbose(true);
 
     // A logical 'try' section.
-    Compiler::CompileForLiveEdit(script);
+    infos = Compiler::CompileForLiveEdit(script);
   }
 
   // A logical 'catch' section.
@@ -883,11 +776,10 @@
   }
 
   // A logical 'finally' section.
-  isolate->set_active_function_info_listener(NULL);
   script->set_source(*original_source);
 
   if (rethrow_exception.is_null()) {
-    return listener.GetResult();
+    return infos.ToHandleChecked();
   } else {
     return isolate->Throw<JSArray>(rethrow_exception);
   }
@@ -1116,9 +1008,23 @@
 
   Handle<SharedFunctionInfo> shared_info = shared_info_wrapper.GetInfo();
 
-  if (shared_info->code()->kind() == Code::FUNCTION) {
-    Handle<Code> code = compile_info_wrapper.GetFunctionCode();
-    ReplaceCodeObject(Handle<Code>(shared_info->code()), code);
+  if (shared_info->is_compiled()) {
+    Handle<Code> new_code = compile_info_wrapper.GetFunctionCode();
+    Handle<Code> old_code(shared_info->code());
+    if (shared_info->HasBytecodeArray()) {
+      // The old code is interpreted. If we clear the bytecode array, the
+      // interpreter entry trampoline will self-heal and go to compiled code.
+      shared_info->ClearBytecodeArray();
+      shared_info->ReplaceCode(*new_code);
+    } else {
+      DCHECK(old_code->kind() == Code::FUNCTION);
+      ReplaceCodeObject(old_code, new_code);
+    }
+    if (shared_info->HasDebugInfo()) {
+      // Existing break points will be re-applied. Reset the debug info here.
+      isolate->debug()->RemoveDebugInfoAndClearFromShared(
+          handle(shared_info->GetDebugInfo()));
+    }
     Handle<Object> code_scope_info = compile_info_wrapper.GetCodeScopeInfo();
     if (code_scope_info->IsFixedArray()) {
       shared_info->set_scope_info(ScopeInfo::cast(*code_scope_info));
@@ -1282,12 +1188,11 @@
   static const int kMaximalBufferSize = 512*MB;
 };
 
-
+namespace {
 // Patch positions in code (changes relocation info section) and possibly
 // returns new instance of code.
-static Handle<Code> PatchPositionsInCode(
-    Handle<Code> code,
-    Handle<JSArray> position_change_array) {
+Handle<Code> PatchPositionsInCode(Handle<Code> code,
+                                  Handle<JSArray> position_change_array) {
   Isolate* isolate = code->GetIsolate();
 
   RelocInfoBuffer buffer_writer(code->relocation_size(),
@@ -1328,6 +1233,24 @@
   }
 }
 
+void PatchPositionsInBytecodeArray(Handle<BytecodeArray> bytecode,
+                                   Handle<JSArray> position_change_array) {
+  Isolate* isolate = bytecode->GetIsolate();
+  Zone zone(isolate->allocator());
+  interpreter::SourcePositionTableBuilder builder(isolate, &zone);
+
+  for (interpreter::SourcePositionTableIterator iterator(
+           bytecode->source_position_table());
+       !iterator.done(); iterator.Advance()) {
+    int position = iterator.source_position();
+    int new_position = TranslatePosition(position, position_change_array);
+    builder.AddPosition(iterator.bytecode_offset(), new_position,
+                        iterator.is_statement());
+  }
+
+  bytecode->set_source_position_table(*builder.ToSourcePositionTable());
+}
+}  // namespace
 
 void LiveEdit::PatchFunctionPositions(Handle<JSArray> shared_info_array,
                                       Handle<JSArray> position_change_array) {
@@ -1358,6 +1281,9 @@
       // untouched).
       ReplaceCodeObject(Handle<Code>(info->code()), patched_code);
     }
+  } else if (info->HasBytecodeArray()) {
+    PatchPositionsInBytecodeArray(Handle<BytecodeArray>(info->bytecode_array()),
+                                  position_change_array);
   }
 }
 
@@ -1374,8 +1300,7 @@
   copy->set_type(original->type());
   copy->set_context_data(original->context_data());
   copy->set_eval_from_shared(original->eval_from_shared());
-  copy->set_eval_from_instructions_offset(
-      original->eval_from_instructions_offset());
+  copy->set_eval_from_position(original->eval_from_position());
 
   // Copy all the flags, but clear compilation state.
   copy->set_flags(original->flags());
@@ -1555,6 +1480,13 @@
     top_frame = frames[top_frame_index - 2];
     *mode = LiveEdit::CURRENTLY_SET_MODE;
     frame_has_padding = false;
+  } else if (pre_top_frame_code->kind() == Code::BYTECODE_HANDLER) {
+    // Interpreted bytecode takes up two stack frames, one for the bytecode
+    // handler and one for the interpreter entry trampoline. Therefore we shift
+    // up by one frame.
+    *mode = LiveEdit::FRAME_DROPPED_IN_DIRECT_CALL;
+    pre_top_frame = frames[top_frame_index - 2];
+    top_frame = frames[top_frame_index - 1];
   } else {
     return "Unknown structure of stack above changing function";
   }
@@ -1792,7 +1724,8 @@
   // Adjust break_frame after some frames has been dropped.
   StackFrame::Id new_id = StackFrame::NO_ID;
   for (int i = bottom_js_frame_index + 1; i < frames.length(); i++) {
-    if (frames[i]->type() == StackFrame::JAVA_SCRIPT) {
+    if (frames[i]->type() == StackFrame::JAVA_SCRIPT ||
+        frames[i]->type() == StackFrame::INTERPRETED) {
       new_id = frames[i]->id();
       break;
     }
@@ -2004,40 +1937,107 @@
   return NULL;
 }
 
+Handle<JSArray> LiveEditFunctionTracker::Collect(FunctionLiteral* node,
+                                                 Handle<Script> script,
+                                                 Zone* zone, Isolate* isolate) {
+  LiveEditFunctionTracker visitor(script, zone, isolate);
+  visitor.VisitFunctionLiteral(node);
+  return visitor.result_;
+}
 
-LiveEditFunctionTracker::LiveEditFunctionTracker(Isolate* isolate,
-                                                 FunctionLiteral* fun)
-    : isolate_(isolate) {
-  if (isolate_->active_function_info_listener() != NULL) {
-    isolate_->active_function_info_listener()->FunctionStarted(fun);
+LiveEditFunctionTracker::LiveEditFunctionTracker(Handle<Script> script,
+                                                 Zone* zone, Isolate* isolate)
+    : AstTraversalVisitor(isolate) {
+  current_parent_index_ = -1;
+  isolate_ = isolate;
+  len_ = 0;
+  result_ = isolate->factory()->NewJSArray(10);
+  script_ = script;
+  zone_ = zone;
+}
+
+void LiveEditFunctionTracker::VisitFunctionLiteral(FunctionLiteral* node) {
+  Scope* scope = node->scope();
+
+  // FunctionStarted is called in pre-order.
+  FunctionStarted(node);
+
+  VisitDeclarations(scope->declarations());
+  VisitStatements(node->body());
+
+  // FunctionDone are called in post-order.
+  // TODO(jgruber): If required, replace the (linear cost)
+  // FindSharedFunctionInfo call with a more efficient implementation.
+  Handle<SharedFunctionInfo> info =
+      script_->FindSharedFunctionInfo(node).ToHandleChecked();
+  FunctionDone(info, scope);
+}
+
+void LiveEditFunctionTracker::FunctionStarted(FunctionLiteral* fun) {
+  HandleScope handle_scope(isolate_);
+  FunctionInfoWrapper info = FunctionInfoWrapper::Create(isolate_);
+  info.SetInitialProperties(fun->name(), fun->start_position(),
+                            fun->end_position(), fun->parameter_count(),
+                            fun->materialized_literal_count(),
+                            current_parent_index_);
+  current_parent_index_ = len_;
+  SetElementSloppy(result_, len_, info.GetJSArray());
+  len_++;
+}
+
+// Saves full information about a function: its code, its scope info
+// and a SharedFunctionInfo object.
+void LiveEditFunctionTracker::FunctionDone(Handle<SharedFunctionInfo> shared,
+                                           Scope* scope) {
+  HandleScope handle_scope(isolate_);
+  FunctionInfoWrapper info = FunctionInfoWrapper::cast(
+      *JSReceiver::GetElement(isolate_, result_, current_parent_index_)
+           .ToHandleChecked());
+  info.SetFunctionCode(Handle<Code>(shared->code()),
+                       Handle<HeapObject>(shared->scope_info()));
+  info.SetSharedFunctionInfo(shared);
+
+  Handle<Object> scope_info_list = SerializeFunctionScope(scope);
+  info.SetFunctionScopeInfo(scope_info_list);
+
+  current_parent_index_ = info.GetParentIndex();
+}
+
+Handle<Object> LiveEditFunctionTracker::SerializeFunctionScope(Scope* scope) {
+  Handle<JSArray> scope_info_list = isolate_->factory()->NewJSArray(10);
+  int scope_info_length = 0;
+
+  // Saves some description of scope. It stores name and indexes of
+  // variables in the whole scope chain. Null-named slots delimit
+  // scopes of this chain.
+  Scope* current_scope = scope;
+  while (current_scope != NULL) {
+    HandleScope handle_scope(isolate_);
+    ZoneList<Variable*> stack_list(current_scope->StackLocalCount(), zone_);
+    ZoneList<Variable*> context_list(current_scope->ContextLocalCount(), zone_);
+    ZoneList<Variable*> globals_list(current_scope->ContextGlobalCount(),
+                                     zone_);
+    current_scope->CollectStackAndContextLocals(&stack_list, &context_list,
+                                                &globals_list);
+    context_list.Sort(&Variable::CompareIndex);
+
+    for (int i = 0; i < context_list.length(); i++) {
+      SetElementSloppy(scope_info_list, scope_info_length,
+                       context_list[i]->name());
+      scope_info_length++;
+      SetElementSloppy(
+          scope_info_list, scope_info_length,
+          Handle<Smi>(Smi::FromInt(context_list[i]->index()), isolate_));
+      scope_info_length++;
+    }
+    SetElementSloppy(scope_info_list, scope_info_length,
+                     Handle<Object>(isolate_->heap()->null_value(), isolate_));
+    scope_info_length++;
+
+    current_scope = current_scope->outer_scope();
   }
-}
 
-
-LiveEditFunctionTracker::~LiveEditFunctionTracker() {
-  if (isolate_->active_function_info_listener() != NULL) {
-    isolate_->active_function_info_listener()->FunctionDone();
-  }
-}
-
-
-void LiveEditFunctionTracker::RecordFunctionInfo(
-    Handle<SharedFunctionInfo> info, FunctionLiteral* lit,
-    Zone* zone) {
-  if (isolate_->active_function_info_listener() != NULL) {
-    isolate_->active_function_info_listener()->FunctionInfo(info, lit->scope(),
-                                                            zone);
-  }
-}
-
-
-void LiveEditFunctionTracker::RecordRootFunctionInfo(Handle<Code> code) {
-  isolate_->active_function_info_listener()->FunctionCode(code);
-}
-
-
-bool LiveEditFunctionTracker::IsActive(Isolate* isolate) {
-  return isolate->active_function_info_listener() != NULL;
+  return scope_info_list;
 }
 
 }  // namespace internal