Update V8 to r5388 as required by WebKit r66666

Change-Id: Ib3c42e9b7226d22c65c7077c543fe31afe62a318
diff --git a/src/frames.cc b/src/frames.cc
index 9f815c3..76a441b 100644
--- a/src/frames.cc
+++ b/src/frames.cc
@@ -36,6 +36,11 @@
 namespace v8 {
 namespace internal {
 
+PcToCodeCache::PcToCodeCacheEntry
+    PcToCodeCache::cache_[PcToCodeCache::kPcToCodeCacheSize];
+
+int SafeStackFrameIterator::active_count_ = 0;
+
 // Iterator that supports traversing the stack handlers of a
 // particular frame. Needs to know the top of the handler chain.
 class StackHandlerIterator BASE_EMBEDDED {
@@ -88,7 +93,6 @@
   if (use_top || fp != NULL) {
     Reset();
   }
-  JavaScriptFrame_.DisableHeapAccess();
 }
 
 #undef INITIALIZE_SINGLETON
@@ -201,7 +205,7 @@
 
 SafeStackFrameIterator::SafeStackFrameIterator(
     Address fp, Address sp, Address low_bound, Address high_bound) :
-    low_bound_(low_bound), high_bound_(high_bound),
+    maintainer_(), low_bound_(low_bound), high_bound_(high_bound),
     is_valid_top_(
         IsWithinBounds(low_bound, high_bound,
                        Top::c_entry_fp(Top::GetCurrentThread())) &&
@@ -302,69 +306,42 @@
 #endif
 
 
-// -------------------------------------------------------------------------
-
-
-void StackHandler::Cook(Code* code) {
-  ASSERT(code->contains(pc()));
-  set_pc(AddressFrom<Address>(pc() - code->instruction_start()));
-}
-
-
-void StackHandler::Uncook(Code* code) {
-  set_pc(code->instruction_start() + OffsetFrom(pc()));
-  ASSERT(code->contains(pc()));
-}
-
-
-// -------------------------------------------------------------------------
-
-
 bool StackFrame::HasHandler() const {
   StackHandlerIterator it(this, top_handler());
   return !it.done();
 }
 
-
-void StackFrame::CookFramesForThread(ThreadLocalTop* thread) {
-  ASSERT(!thread->stack_is_cooked());
-  for (StackFrameIterator it(thread); !it.done(); it.Advance()) {
-    it.frame()->Cook();
+void StackFrame::IteratePc(ObjectVisitor* v,
+                           Address* pc_address,
+                           Code* holder) {
+  Address pc = *pc_address;
+  ASSERT(holder->contains(pc));
+  unsigned pc_offset = static_cast<unsigned>(pc - holder->instruction_start());
+  Object* code = holder;
+  v->VisitPointer(&code);
+  if (code != holder) {
+    holder = reinterpret_cast<Code*>(code);
+    pc = holder->instruction_start() + pc_offset;
+    *pc_address = pc;
   }
-  thread->set_stack_is_cooked(true);
 }
 
 
-void StackFrame::UncookFramesForThread(ThreadLocalTop* thread) {
-  ASSERT(thread->stack_is_cooked());
-  for (StackFrameIterator it(thread); !it.done(); it.Advance()) {
-    it.frame()->Uncook();
+StackFrame::Type StackFrame::ComputeType(State* state) {
+  ASSERT(state->fp != NULL);
+  if (StandardFrame::IsArgumentsAdaptorFrame(state->fp)) {
+    return ARGUMENTS_ADAPTOR;
   }
-  thread->set_stack_is_cooked(false);
+  // The marker and function offsets overlap. If the marker isn't a
+  // smi then the frame is a JavaScript frame -- and the marker is
+  // really the function.
+  const int offset = StandardFrameConstants::kMarkerOffset;
+  Object* marker = Memory::Object_at(state->fp + offset);
+  if (!marker->IsSmi()) return JAVA_SCRIPT;
+  return static_cast<StackFrame::Type>(Smi::cast(marker)->value());
 }
 
 
-void StackFrame::Cook() {
-  Code* code = this->code();
-  ASSERT(code->IsCode());
-  for (StackHandlerIterator it(this, top_handler()); !it.done(); it.Advance()) {
-    it.handler()->Cook(code);
-  }
-  ASSERT(code->contains(pc()));
-  set_pc(AddressFrom<Address>(pc() - code->instruction_start()));
-}
-
-
-void StackFrame::Uncook() {
-  Code* code = this->code();
-  ASSERT(code->IsCode());
-  for (StackHandlerIterator it(this, top_handler()); !it.done(); it.Advance()) {
-    it.handler()->Uncook(code);
-  }
-  set_pc(code->instruction_start() + OffsetFrom(pc()));
-  ASSERT(code->contains(pc()));
-}
-
 
 StackFrame::Type StackFrame::GetCallerState(State* state) const {
   ComputeCallerState(state);
@@ -425,6 +402,14 @@
 }
 
 
+void ExitFrame::Iterate(ObjectVisitor* v) const {
+  // The arguments are traversed as part of the expression stack of
+  // the calling frame.
+  IteratePc(v, pc_address(), code());
+  v->VisitPointer(&code_slot());
+}
+
+
 Address ExitFrame::GetCallerStackPointer() const {
   return fp() + ExitFrameConstants::kCallerSPDisplacement;
 }
@@ -499,6 +484,49 @@
 }
 
 
+int JavaScriptFrame::GetProvidedParametersCount() const {
+  return ComputeParametersCount();
+}
+
+
+Address JavaScriptFrame::GetCallerStackPointer() const {
+  int arguments;
+  if (Heap::gc_state() != Heap::NOT_IN_GC ||
+      SafeStackFrameIterator::is_active()) {
+    // If the we are currently iterating the safe stack the
+    // arguments for frames are traversed as if they were
+    // expression stack elements of the calling frame. The reason for
+    // this rather strange decision is that we cannot access the
+    // function during mark-compact GCs when objects may have been marked.
+    // In fact accessing heap objects (like function->shared() below)
+    // at all during GC is problematic.
+    arguments = 0;
+  } else {
+    // Compute the number of arguments by getting the number of formal
+    // parameters of the function. We must remember to take the
+    // receiver into account (+1).
+    JSFunction* function = JSFunction::cast(this->function());
+    arguments = function->shared()->formal_parameter_count() + 1;
+  }
+  const int offset = StandardFrameConstants::kCallerSPOffset;
+  return fp() + offset + (arguments * kPointerSize);
+}
+
+
+Address ArgumentsAdaptorFrame::GetCallerStackPointer() const {
+  const int arguments = Smi::cast(GetExpression(0))->value();
+  const int offset = StandardFrameConstants::kCallerSPOffset;
+  return fp() + offset + (arguments + 1) * kPointerSize;
+}
+
+
+Address InternalFrame::GetCallerStackPointer() const {
+  // Internal frames have no arguments. The stack pointer of the
+  // caller is at a fixed offset from the frame pointer.
+  return fp() + StandardFrameConstants::kCallerSPOffset;
+}
+
+
 Code* ArgumentsAdaptorFrame::unchecked_code() const {
   return Builtins::builtin(Builtins::ArgumentsAdaptorTrampoline);
 }
@@ -694,13 +722,14 @@
   ASSERT(!it.done());
   StackHandler* handler = it.handler();
   ASSERT(handler->is_entry());
-  handler->Iterate(v);
-  // Make sure that there's the entry frame does not contain more than
-  // one stack handler.
+  handler->Iterate(v, code());
 #ifdef DEBUG
+  // Make sure that the entry frame does not contain more than one
+  // stack handler.
   it.Advance();
   ASSERT(it.done());
 #endif
+  IteratePc(v, pc_address(), code());
 }
 
 
@@ -717,7 +746,7 @@
     v->VisitPointers(base, reinterpret_cast<Object**>(address));
     base = reinterpret_cast<Object**>(address + StackHandlerConstants::kSize);
     // Traverse the pointers in the handler itself.
-    handler->Iterate(v);
+    handler->Iterate(v, code());
   }
   v->VisitPointers(base, limit);
 }
@@ -725,6 +754,7 @@
 
 void JavaScriptFrame::Iterate(ObjectVisitor* v) const {
   IterateExpressions(v);
+  IteratePc(v, pc_address(), code());
 
   // Traverse callee-saved registers, receiver, and parameters.
   const int kBaseOffset = JavaScriptFrameConstants::kSavedRegistersOffset;
@@ -739,6 +769,7 @@
   // Internal frames only have object pointers on the expression stack
   // as they never have any arguments.
   IterateExpressions(v);
+  IteratePc(v, pc_address(), code());
 }
 
 
@@ -760,6 +791,56 @@
 // -------------------------------------------------------------------------
 
 
+Code* PcToCodeCache::GcSafeCastToCode(HeapObject* object, Address pc) {
+  Code* code = reinterpret_cast<Code*>(object);
+  ASSERT(code != NULL && code->contains(pc));
+  return code;
+}
+
+
+Code* PcToCodeCache::GcSafeFindCodeForPc(Address pc) {
+  // Check if the pc points into a large object chunk.
+  LargeObjectChunk* chunk = Heap::lo_space()->FindChunkContainingPc(pc);
+  if (chunk != NULL) return GcSafeCastToCode(chunk->GetObject(), pc);
+
+  // Iterate through the 8K page until we reach the end or find an
+  // object starting after the pc.
+  Page* page = Page::FromAddress(pc);
+  HeapObjectIterator iterator(page, Heap::GcSafeSizeOfOldObjectFunction());
+  HeapObject* previous = NULL;
+  while (true) {
+    HeapObject* next = iterator.next();
+    if (next == NULL || next->address() >= pc) {
+      return GcSafeCastToCode(previous, pc);
+    }
+    previous = next;
+  }
+}
+
+PcToCodeCache::PcToCodeCacheEntry* PcToCodeCache::GetCacheEntry(Address pc) {
+  Counters::pc_to_code.Increment();
+  ASSERT(IsPowerOf2(kPcToCodeCacheSize));
+  uint32_t hash = ComputeIntegerHash(
+      static_cast<uint32_t>(reinterpret_cast<uintptr_t>(pc)));
+  uint32_t index = hash & (kPcToCodeCacheSize - 1);
+  PcToCodeCacheEntry* entry = cache(index);
+  if (entry->pc == pc) {
+    Counters::pc_to_code_cached.Increment();
+    ASSERT(entry->code == GcSafeFindCodeForPc(pc));
+  } else {
+    // Because this code may be interrupted by a profiling signal that
+    // also queries the cache, we cannot update pc before the code has
+    // been set. Otherwise, we risk trying to use a cache entry before
+    // the code has been computed.
+    entry->code = GcSafeFindCodeForPc(pc);
+    entry->pc = pc;
+  }
+  return entry;
+}
+
+
+// -------------------------------------------------------------------------
+
 int NumRegs(RegList reglist) {
   int n = 0;
   while (reglist != 0) {