Update V8 to r6101 as required by WebKit r74534

Change-Id: I7f84af8dd732f11898fd644b2c2b1538914cb78d
diff --git a/src/frames.cc b/src/frames.cc
index 3cdb015..3af7288 100644
--- a/src/frames.cc
+++ b/src/frames.cc
@@ -27,8 +27,12 @@
 
 #include "v8.h"
 
+#include "ast.h"
+#include "deoptimizer.h"
 #include "frames-inl.h"
+#include "full-codegen.h"
 #include "mark-compact.h"
+#include "safepoint-table.h"
 #include "scopeinfo.h"
 #include "string-stream.h"
 #include "top.h"
@@ -324,11 +328,33 @@
 #endif
 
 
+Code* StackFrame::GetSafepointData(Address pc,
+                                   uint8_t** safepoint_entry,
+                                   unsigned* stack_slots) {
+  PcToCodeCache::PcToCodeCacheEntry* entry = PcToCodeCache::GetCacheEntry(pc);
+  uint8_t* cached_safepoint_entry = entry->safepoint_entry;
+  if (cached_safepoint_entry == NULL) {
+    cached_safepoint_entry = entry->code->GetSafepointEntry(pc);
+    ASSERT(cached_safepoint_entry != NULL);  // No safepoint found.
+    entry->safepoint_entry = cached_safepoint_entry;
+  } else {
+    ASSERT(cached_safepoint_entry == entry->code->GetSafepointEntry(pc));
+  }
+
+  // Fill in the results and return the code.
+  Code* code = entry->code;
+  *safepoint_entry = cached_safepoint_entry;
+  *stack_slots = code->stack_slots();
+  return code;
+}
+
+
 bool StackFrame::HasHandler() const {
   StackHandlerIterator it(this, top_handler());
   return !it.done();
 }
 
+
 void StackFrame::IteratePc(ObjectVisitor* v,
                            Address* pc_address,
                            Code* holder) {
@@ -355,7 +381,16 @@
   // really the function.
   const int offset = StandardFrameConstants::kMarkerOffset;
   Object* marker = Memory::Object_at(state->fp + offset);
-  if (!marker->IsSmi()) return JAVA_SCRIPT;
+  if (!marker->IsSmi()) {
+    // If we're using a "safe" stack iterator, we treat optimized
+    // frames as normal JavaScript frames to avoid having to look
+    // into the heap to determine the state. This is safe as long
+    // as nobody tries to GC...
+    if (SafeStackFrameIterator::is_active()) return JAVA_SCRIPT;
+    Code::Kind kind = GetContainingCode(*(state->pc_address))->kind();
+    ASSERT(kind == Code::FUNCTION || kind == Code::OPTIMIZED_FUNCTION);
+    return (kind == Code::OPTIMIZED_FUNCTION) ? OPTIMIZED : JAVA_SCRIPT;
+  }
   return static_cast<StackFrame::Type>(Smi::cast(marker)->value());
 }
 
@@ -488,6 +523,70 @@
 }
 
 
+void OptimizedFrame::Iterate(ObjectVisitor* v) const {
+#ifdef DEBUG
+  // Make sure that optimized frames do not contain any stack handlers.
+  StackHandlerIterator it(this, top_handler());
+  ASSERT(it.done());
+#endif
+
+  // Make sure that we're not doing "safe" stack frame iteration. We cannot
+  // possibly find pointers in optimized frames in that state.
+  ASSERT(!SafeStackFrameIterator::is_active());
+
+  // Compute the safepoint information.
+  unsigned stack_slots = 0;
+  uint8_t* safepoint_entry = NULL;
+  Code* code = StackFrame::GetSafepointData(
+      pc(), &safepoint_entry, &stack_slots);
+  unsigned slot_space = stack_slots * kPointerSize;
+
+  // Visit the outgoing parameters. This is usually dealt with by the
+  // callee, but while GC'ing we artificially lower the number of
+  // arguments to zero and let the caller deal with it.
+  Object** parameters_base = &Memory::Object_at(sp());
+  Object** parameters_limit = &Memory::Object_at(
+      fp() + JavaScriptFrameConstants::kFunctionOffset - slot_space);
+
+  // Visit the registers that contain pointers if any.
+  if (SafepointTable::HasRegisters(safepoint_entry)) {
+    for (int i = kNumSafepointRegisters - 1; i >=0; i--) {
+      if (SafepointTable::HasRegisterAt(safepoint_entry, i)) {
+        int reg_stack_index = MacroAssembler::SafepointRegisterStackIndex(i);
+        v->VisitPointer(parameters_base + reg_stack_index);
+      }
+    }
+    // Skip the words containing the register values.
+    parameters_base += kNumSafepointRegisters;
+  }
+
+  // We're done dealing with the register bits.
+  safepoint_entry += kNumSafepointRegisters >> kBitsPerByteLog2;
+
+  // Visit the rest of the parameters.
+  v->VisitPointers(parameters_base, parameters_limit);
+
+  // Visit pointer spill slots and locals.
+  for (unsigned index = 0; index < stack_slots; index++) {
+    int byte_index = index >> kBitsPerByteLog2;
+    int bit_index = index & (kBitsPerByte - 1);
+    if ((safepoint_entry[byte_index] & (1U << bit_index)) != 0) {
+      v->VisitPointer(parameters_limit + index);
+    }
+  }
+
+  // Visit the context and the function.
+  Object** fixed_base = &Memory::Object_at(
+      fp() + JavaScriptFrameConstants::kFunctionOffset);
+  Object** fixed_limit = &Memory::Object_at(fp());
+  v->VisitPointers(fixed_base, fixed_limit);
+
+  // Visit the return address in the callee and incoming arguments.
+  IteratePc(v, pc_address(), code);
+  IterateArguments(v);
+}
+
+
 Object* JavaScriptFrame::GetParameter(int index) const {
   ASSERT(index >= 0 && index < ComputeParametersCount());
   const int offset = JavaScriptFrameConstants::kParam0Offset;
@@ -547,6 +646,185 @@
 }
 
 
+void JavaScriptFrame::GetFunctions(List<JSFunction*>* functions) {
+  ASSERT(functions->length() == 0);
+  functions->Add(JSFunction::cast(function()));
+}
+
+
+void JavaScriptFrame::Summarize(List<FrameSummary>* functions) {
+  ASSERT(functions->length() == 0);
+  Code* code_pointer = code();
+  int offset = static_cast<int>(pc() - code_pointer->address());
+  FrameSummary summary(receiver(),
+                       JSFunction::cast(function()),
+                       code_pointer,
+                       offset,
+                       IsConstructor());
+  functions->Add(summary);
+}
+
+
+void FrameSummary::Print() {
+  PrintF("receiver: ");
+  receiver_->ShortPrint();
+  PrintF("\nfunction: ");
+  function_->shared()->DebugName()->ShortPrint();
+  PrintF("\ncode: ");
+  code_->ShortPrint();
+  if (code_->kind() == Code::FUNCTION) PrintF(" NON-OPT");
+  if (code_->kind() == Code::OPTIMIZED_FUNCTION) PrintF(" OPT");
+  PrintF("\npc: %d\n", offset_);
+}
+
+
+void OptimizedFrame::Summarize(List<FrameSummary>* frames) {
+  ASSERT(frames->length() == 0);
+  ASSERT(is_optimized());
+
+  int deopt_index = AstNode::kNoNumber;
+  DeoptimizationInputData* data = GetDeoptimizationData(&deopt_index);
+
+  // BUG(3243555): Since we don't have a lazy-deopt registered at
+  // throw-statements, we can't use the translation at the call-site of
+  // throw. An entry with no deoptimization index indicates a call-site
+  // without a lazy-deopt. As a consequence we are not allowed to inline
+  // functions containing throw.
+  if (deopt_index == Safepoint::kNoDeoptimizationIndex) {
+    JavaScriptFrame::Summarize(frames);
+    return;
+  }
+
+  TranslationIterator it(data->TranslationByteArray(),
+                         data->TranslationIndex(deopt_index)->value());
+  Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next());
+  ASSERT(opcode == Translation::BEGIN);
+  int frame_count = it.Next();
+
+  // We create the summary in reverse order because the frames
+  // in the deoptimization translation are ordered bottom-to-top.
+  int i = frame_count;
+  while (i > 0) {
+    opcode = static_cast<Translation::Opcode>(it.Next());
+    if (opcode == Translation::FRAME) {
+      // We don't inline constructor calls, so only the first, outermost
+      // frame can be a constructor frame in case of inlining.
+      bool is_constructor = (i == frame_count) && IsConstructor();
+
+      i--;
+      int ast_id = it.Next();
+      int function_id = it.Next();
+      it.Next();  // Skip height.
+      JSFunction* function =
+          JSFunction::cast(data->LiteralArray()->get(function_id));
+
+      // The translation commands are ordered and the receiver is always
+      // at the first position. Since we are always at a call when we need
+      // to construct a stack trace, the receiver is always in a stack slot.
+      opcode = static_cast<Translation::Opcode>(it.Next());
+      ASSERT(opcode == Translation::STACK_SLOT);
+      int input_slot_index = it.Next();
+
+      // Get the correct receiver in the optimized frame.
+      Object* receiver = NULL;
+      // Positive index means the value is spilled to the locals area. Negative
+      // means it is stored in the incoming parameter area.
+      if (input_slot_index >= 0) {
+        receiver = GetExpression(input_slot_index);
+      } else {
+        // Index -1 overlaps with last parameter, -n with the first parameter,
+        // (-n - 1) with the receiver with n being the number of parameters
+        // of the outermost, optimized frame.
+        int parameter_count = ComputeParametersCount();
+        int parameter_index = input_slot_index + parameter_count;
+        receiver = (parameter_index == -1)
+            ? this->receiver()
+            : this->GetParameter(parameter_index);
+      }
+
+      Code* code = function->shared()->code();
+      DeoptimizationOutputData* output_data =
+          DeoptimizationOutputData::cast(code->deoptimization_data());
+      unsigned entry = Deoptimizer::GetOutputInfo(output_data,
+                                                  ast_id,
+                                                  function->shared());
+      unsigned pc_offset =
+          FullCodeGenerator::PcField::decode(entry) + Code::kHeaderSize;
+      ASSERT(pc_offset > 0);
+
+      FrameSummary summary(receiver, function, code, pc_offset, is_constructor);
+      frames->Add(summary);
+    } else {
+      // Skip over operands to advance to the next opcode.
+      it.Skip(Translation::NumberOfOperandsFor(opcode));
+    }
+  }
+}
+
+
+DeoptimizationInputData* OptimizedFrame::GetDeoptimizationData(
+    int* deopt_index) {
+  ASSERT(is_optimized());
+
+  JSFunction* opt_function = JSFunction::cast(function());
+  Code* code = opt_function->code();
+
+  // The code object may have been replaced by lazy deoptimization. Fall
+  // back to a slow search in this case to find the original optimized
+  // code object.
+  if (!code->contains(pc())) {
+    code = PcToCodeCache::GcSafeFindCodeForPc(pc());
+  }
+  ASSERT(code != NULL);
+  ASSERT(code->kind() == Code::OPTIMIZED_FUNCTION);
+
+  SafepointTable table(code);
+  unsigned pc_offset = static_cast<unsigned>(pc() - code->instruction_start());
+  for (unsigned i = 0; i < table.length(); i++) {
+    if (table.GetPcOffset(i) == pc_offset) {
+      *deopt_index = table.GetDeoptimizationIndex(i);
+      break;
+    }
+  }
+  ASSERT(*deopt_index != AstNode::kNoNumber);
+
+  return DeoptimizationInputData::cast(code->deoptimization_data());
+}
+
+
+void OptimizedFrame::GetFunctions(List<JSFunction*>* functions) {
+  ASSERT(functions->length() == 0);
+  ASSERT(is_optimized());
+
+  int deopt_index = AstNode::kNoNumber;
+  DeoptimizationInputData* data = GetDeoptimizationData(&deopt_index);
+
+  TranslationIterator it(data->TranslationByteArray(),
+                         data->TranslationIndex(deopt_index)->value());
+  Translation::Opcode opcode = static_cast<Translation::Opcode>(it.Next());
+  ASSERT(opcode == Translation::BEGIN);
+  int frame_count = it.Next();
+
+  // We insert the frames in reverse order because the frames
+  // in the deoptimization translation are ordered bottom-to-top.
+  while (frame_count > 0) {
+    opcode = static_cast<Translation::Opcode>(it.Next());
+    if (opcode == Translation::FRAME) {
+      frame_count--;
+      it.Next();  // Skip ast id.
+      int function_id = it.Next();
+      it.Next();  // Skip height.
+      JSFunction* function =
+          JSFunction::cast(data->LiteralArray()->get(function_id));
+      functions->Add(function);
+    } else {
+      // Skip over operands to advance to the next opcode.
+      it.Skip(Translation::NumberOfOperandsFor(opcode));
+    }
+  }
+}
+
+
 Address ArgumentsAdaptorFrame::GetCallerStackPointer() const {
   const int arguments = Smi::cast(GetExpression(0))->value();
   const int offset = StandardFrameConstants::kCallerSPOffset;
@@ -789,7 +1067,11 @@
 void JavaScriptFrame::Iterate(ObjectVisitor* v) const {
   IterateExpressions(v);
   IteratePc(v, pc_address(), code());
+  IterateArguments(v);
+}
 
+
+void JavaScriptFrame::IterateArguments(ObjectVisitor* v) const {
   // Traverse callee-saved registers, receiver, and parameters.
   const int kBaseOffset = JavaScriptFrameConstants::kSavedRegistersOffset;
   const int kLimitOffset = JavaScriptFrameConstants::kReceiverOffset;
@@ -851,6 +1133,7 @@
   }
 }
 
+
 PcToCodeCache::PcToCodeCacheEntry* PcToCodeCache::GetCacheEntry(Address pc) {
   Counters::pc_to_code.Increment();
   ASSERT(IsPowerOf2(kPcToCodeCacheSize));
@@ -867,6 +1150,7 @@
     // been set. Otherwise, we risk trying to use a cache entry before
     // the code has been computed.
     entry->code = GcSafeFindCodeForPc(pc);
+    entry->safepoint_entry = NULL;
     entry->pc = pc;
   }
   return entry;