// Copyright 2006-2008 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
//       copyright notice, this list of conditions and the following
//       disclaimer in the documentation and/or other materials provided
//       with the distribution.
//     * Neither the name of Google Inc. nor the names of its
//       contributors may be used to endorse or promote products derived
//       from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include "v8.h"

#include "api.h"
#include "bootstrapper.h"
#include "debug.h"
#include "execution.h"
#include "messages.h"
#include "platform.h"
#include "simulator.h"
#include "string-stream.h"
#include "vm-state-inl.h"

namespace v8 {
namespace internal {

#ifdef ENABLE_LOGGING_AND_PROFILING
Semaphore* Top::runtime_profiler_semaphore_ = NULL;
#endif
ThreadLocalTop Top::thread_local_;
Mutex* Top::break_access_ = OS::CreateMutex();

NoAllocationStringAllocator* preallocated_message_space = NULL;

bool capture_stack_trace_for_uncaught_exceptions = false;
int stack_trace_for_uncaught_exceptions_frame_limit = 0;
StackTrace::StackTraceOptions stack_trace_for_uncaught_exceptions_options =
    StackTrace::kOverview;

Address top_addresses[] = {
#define C(name) reinterpret_cast<Address>(Top::name()),
    TOP_ADDRESS_LIST(C)
    TOP_ADDRESS_LIST_PROF(C)
#undef C
    NULL
};


v8::TryCatch* ThreadLocalTop::TryCatchHandler() {
  return TRY_CATCH_FROM_ADDRESS(try_catch_handler_address());
}


void ThreadLocalTop::Initialize() {
  c_entry_fp_ = 0;
  handler_ = 0;
#ifdef USE_SIMULATOR
#ifdef V8_TARGET_ARCH_ARM
  simulator_ = assembler::arm::Simulator::current();
#elif V8_TARGET_ARCH_MIPS
  simulator_ = assembler::mips::Simulator::current();
#endif
#endif
#ifdef ENABLE_LOGGING_AND_PROFILING
  js_entry_sp_ = NULL;
  external_callback_ = NULL;
#endif
#ifdef ENABLE_VMSTATE_TRACKING
  current_vm_state_ = EXTERNAL;
  runtime_profiler_state_ = Top::PROF_NOT_IN_JS;
#endif
  try_catch_handler_address_ = NULL;
  context_ = NULL;
  int id = ThreadManager::CurrentId();
  thread_id_ = (id == 0) ? ThreadManager::kInvalidId : id;
  external_caught_exception_ = false;
  failed_access_check_callback_ = NULL;
  save_context_ = NULL;
  catcher_ = NULL;
}


Address Top::get_address_from_id(Top::AddressId id) {
  return top_addresses[id];
}


char* Top::Iterate(ObjectVisitor* v, char* thread_storage) {
  ThreadLocalTop* thread = reinterpret_cast<ThreadLocalTop*>(thread_storage);
  Iterate(v, thread);
  return thread_storage + sizeof(ThreadLocalTop);
}


void Top::IterateThread(ThreadVisitor* v) {
  v->VisitThread(&thread_local_);
}


void Top::IterateThread(ThreadVisitor* v, char* t) {
  ThreadLocalTop* thread = reinterpret_cast<ThreadLocalTop*>(t);
  v->VisitThread(thread);
}


void Top::Iterate(ObjectVisitor* v, ThreadLocalTop* thread) {
  // Visit the roots from the top for a given thread.
  Object *pending;
  // The pending exception can sometimes be a failure.  We can't show
  // that to the GC, which only understands objects.
  if (thread->pending_exception_->ToObject(&pending)) {
    v->VisitPointer(&pending);
    thread->pending_exception_ = pending;  // In case GC updated it.
  }
  v->VisitPointer(&(thread->pending_message_obj_));
  v->VisitPointer(BitCast<Object**>(&(thread->pending_message_script_)));
  v->VisitPointer(BitCast<Object**>(&(thread->context_)));
  Object* scheduled;
  if (thread->scheduled_exception_->ToObject(&scheduled)) {
    v->VisitPointer(&scheduled);
    thread->scheduled_exception_ = scheduled;
  }

  for (v8::TryCatch* block = thread->TryCatchHandler();
       block != NULL;
       block = TRY_CATCH_FROM_ADDRESS(block->next_)) {
    v->VisitPointer(BitCast<Object**>(&(block->exception_)));
    v->VisitPointer(BitCast<Object**>(&(block->message_)));
  }

  // Iterate over pointers on native execution stack.
  for (StackFrameIterator it(thread); !it.done(); it.Advance()) {
    it.frame()->Iterate(v);
  }
}


void Top::Iterate(ObjectVisitor* v) {
  ThreadLocalTop* current_t = &thread_local_;
  Iterate(v, current_t);
}


void Top::InitializeThreadLocal() {
  thread_local_.Initialize();
  clear_pending_exception();
  clear_pending_message();
  clear_scheduled_exception();
}


// Create a dummy thread that will wait forever on a semaphore. The only
// purpose for this thread is to have some stack area to save essential data
// into for use by a stacks only core dump (aka minidump).
class PreallocatedMemoryThread: public Thread {
 public:
  PreallocatedMemoryThread()
    : Thread("v8:PreallocMem"),
      keep_running_(true) {
    wait_for_ever_semaphore_ = OS::CreateSemaphore(0);
    data_ready_semaphore_ = OS::CreateSemaphore(0);
  }

  // When the thread starts running it will allocate a fixed number of bytes
  // on the stack and publish the location of this memory for others to use.
  void Run() {
    EmbeddedVector<char, 15 * 1024> local_buffer;

    // Initialize the buffer with a known good value.
    OS::StrNCpy(local_buffer, "Trace data was not generated.\n",
                local_buffer.length());

    // Publish the local buffer and signal its availability.
    data_ = local_buffer.start();
    length_ = local_buffer.length();
    data_ready_semaphore_->Signal();

    while (keep_running_) {
      // This thread will wait here until the end of time.
      wait_for_ever_semaphore_->Wait();
    }

    // Make sure we access the buffer after the wait to remove all possibility
    // of it being optimized away.
    OS::StrNCpy(local_buffer, "PreallocatedMemoryThread shutting down.\n",
                local_buffer.length());
  }

  static char* data() {
    if (data_ready_semaphore_ != NULL) {
      // Initial access is guarded until the data has been published.
      data_ready_semaphore_->Wait();
      delete data_ready_semaphore_;
      data_ready_semaphore_ = NULL;
    }
    return data_;
  }

  static unsigned length() {
    if (data_ready_semaphore_ != NULL) {
      // Initial access is guarded until the data has been published.
      data_ready_semaphore_->Wait();
      delete data_ready_semaphore_;
      data_ready_semaphore_ = NULL;
    }
    return length_;
  }

  static void StartThread() {
    if (the_thread_ != NULL) return;

    the_thread_ = new PreallocatedMemoryThread();
    the_thread_->Start();
  }

  // Stop the PreallocatedMemoryThread and release its resources.
  static void StopThread() {
    if (the_thread_ == NULL) return;

    the_thread_->keep_running_ = false;
    wait_for_ever_semaphore_->Signal();

    // Wait for the thread to terminate.
    the_thread_->Join();

    if (data_ready_semaphore_ != NULL) {
      delete data_ready_semaphore_;
      data_ready_semaphore_ = NULL;
    }

    delete wait_for_ever_semaphore_;
    wait_for_ever_semaphore_ = NULL;

    // Done with the thread entirely.
    delete the_thread_;
    the_thread_ = NULL;
  }

 private:
  // Used to make sure that the thread keeps looping even for spurious wakeups.
  bool keep_running_;

  // The preallocated memory thread singleton.
  static PreallocatedMemoryThread* the_thread_;
  // This semaphore is used by the PreallocatedMemoryThread to wait for ever.
  static Semaphore* wait_for_ever_semaphore_;
  // Semaphore to signal that the data has been initialized.
  static Semaphore* data_ready_semaphore_;

  // Location and size of the preallocated memory block.
  static char* data_;
  static unsigned length_;

  DISALLOW_COPY_AND_ASSIGN(PreallocatedMemoryThread);
};

PreallocatedMemoryThread* PreallocatedMemoryThread::the_thread_ = NULL;
Semaphore* PreallocatedMemoryThread::wait_for_ever_semaphore_ = NULL;
Semaphore* PreallocatedMemoryThread::data_ready_semaphore_ = NULL;
char* PreallocatedMemoryThread::data_ = NULL;
unsigned PreallocatedMemoryThread::length_ = 0;

static bool initialized = false;

void Top::Initialize() {
  CHECK(!initialized);

#ifdef ENABLE_LOGGING_AND_PROFILING
  ASSERT(runtime_profiler_semaphore_ == NULL);
  runtime_profiler_semaphore_ = OS::CreateSemaphore(0);
#endif

  InitializeThreadLocal();

  // Only preallocate on the first initialization.
  if (FLAG_preallocate_message_memory && (preallocated_message_space == NULL)) {
    // Start the thread which will set aside some memory.
    PreallocatedMemoryThread::StartThread();
    preallocated_message_space =
        new NoAllocationStringAllocator(PreallocatedMemoryThread::data(),
                                        PreallocatedMemoryThread::length());
    PreallocatedStorage::Init(PreallocatedMemoryThread::length() / 4);
  }
  initialized = true;
}


void Top::TearDown() {
  if (initialized) {
#ifdef ENABLE_LOGGING_AND_PROFILING
    delete runtime_profiler_semaphore_;
    runtime_profiler_semaphore_ = NULL;
#endif

    // Remove the external reference to the preallocated stack memory.
    if (preallocated_message_space != NULL) {
      delete preallocated_message_space;
      preallocated_message_space = NULL;
    }

    PreallocatedMemoryThread::StopThread();
    initialized = false;
  }
}


void Top::RegisterTryCatchHandler(v8::TryCatch* that) {
  // The ARM simulator has a separate JS stack.  We therefore register
  // the C++ try catch handler with the simulator and get back an
  // address that can be used for comparisons with addresses into the
  // JS stack.  When running without the simulator, the address
  // returned will be the address of the C++ try catch handler itself.
  Address address = reinterpret_cast<Address>(
      SimulatorStack::RegisterCTryCatch(reinterpret_cast<uintptr_t>(that)));
  thread_local_.set_try_catch_handler_address(address);
}


void Top::UnregisterTryCatchHandler(v8::TryCatch* that) {
  ASSERT(thread_local_.TryCatchHandler() == that);
  thread_local_.set_try_catch_handler_address(
      reinterpret_cast<Address>(that->next_));
  thread_local_.catcher_ = NULL;
  SimulatorStack::UnregisterCTryCatch();
}



static int stack_trace_nesting_level = 0;
static StringStream* incomplete_message = NULL;


Handle<String> Top::StackTraceString() {
  if (stack_trace_nesting_level == 0) {
    stack_trace_nesting_level++;
    HeapStringAllocator allocator;
    StringStream::ClearMentionedObjectCache();
    StringStream accumulator(&allocator);
    incomplete_message = &accumulator;
    PrintStack(&accumulator);
    Handle<String> stack_trace = accumulator.ToString();
    incomplete_message = NULL;
    stack_trace_nesting_level = 0;
    return stack_trace;
  } else if (stack_trace_nesting_level == 1) {
    stack_trace_nesting_level++;
    OS::PrintError(
      "\n\nAttempt to print stack while printing stack (double fault)\n");
    OS::PrintError(
      "If you are lucky you may find a partial stack dump on stdout.\n\n");
    incomplete_message->OutputToStdOut();
    return Factory::empty_symbol();
  } else {
    OS::Abort();
    // Unreachable
    return Factory::empty_symbol();
  }
}


Handle<JSArray> Top::CaptureCurrentStackTrace(
    int frame_limit, StackTrace::StackTraceOptions options) {
  // Ensure no negative values.
  int limit = Max(frame_limit, 0);
  Handle<JSArray> stack_trace = Factory::NewJSArray(frame_limit);

  Handle<String> column_key =  Factory::LookupAsciiSymbol("column");
  Handle<String> line_key =  Factory::LookupAsciiSymbol("lineNumber");
  Handle<String> script_key =  Factory::LookupAsciiSymbol("scriptName");
  Handle<String> name_or_source_url_key =
      Factory::LookupAsciiSymbol("nameOrSourceURL");
  Handle<String> script_name_or_source_url_key =
      Factory::LookupAsciiSymbol("scriptNameOrSourceURL");
  Handle<String> function_key =  Factory::LookupAsciiSymbol("functionName");
  Handle<String> eval_key =  Factory::LookupAsciiSymbol("isEval");
  Handle<String> constructor_key =  Factory::LookupAsciiSymbol("isConstructor");

  StackTraceFrameIterator it;
  int frames_seen = 0;
  while (!it.done() && (frames_seen < limit)) {
    JavaScriptFrame* frame = it.frame();

    List<FrameSummary> frames(3);  // Max 2 levels of inlining.
    frame->Summarize(&frames);
    for (int i = frames.length() - 1; i >= 0 && frames_seen < limit; i--) {
      // Create a JSObject to hold the information for the StackFrame.
      Handle<JSObject> stackFrame = Factory::NewJSObject(object_function());

      Handle<JSFunction> fun = frames[i].function();
      Handle<Script> script(Script::cast(fun->shared()->script()));

      if (options & StackTrace::kLineNumber) {
        int script_line_offset = script->line_offset()->value();
        int position = frames[i].code()->SourcePosition(frames[i].pc());
        int line_number = GetScriptLineNumber(script, position);
        // line_number is already shifted by the script_line_offset.
        int relative_line_number = line_number - script_line_offset;
        if (options & StackTrace::kColumnOffset && relative_line_number >= 0) {
          Handle<FixedArray> line_ends(FixedArray::cast(script->line_ends()));
          int start = (relative_line_number == 0) ? 0 :
              Smi::cast(line_ends->get(relative_line_number - 1))->value() + 1;
          int column_offset = position - start;
          if (relative_line_number == 0) {
            // For the case where the code is on the same line as the script
            // tag.
            column_offset += script->column_offset()->value();
          }
          SetProperty(stackFrame, column_key,
                      Handle<Smi>(Smi::FromInt(column_offset + 1)), NONE);
        }
        SetProperty(stackFrame, line_key,
                    Handle<Smi>(Smi::FromInt(line_number + 1)), NONE);
      }

      if (options & StackTrace::kScriptName) {
        Handle<Object> script_name(script->name());
        SetProperty(stackFrame, script_key, script_name, NONE);
      }

      if (options & StackTrace::kScriptNameOrSourceURL) {
        Handle<Object> script_name(script->name());
        Handle<JSValue> script_wrapper = GetScriptWrapper(script);
        Handle<Object> property = GetProperty(script_wrapper,
                                              name_or_source_url_key);
        ASSERT(property->IsJSFunction());
        Handle<JSFunction> method = Handle<JSFunction>::cast(property);
        bool caught_exception;
        Handle<Object> result = Execution::TryCall(method, script_wrapper, 0,
                                                   NULL, &caught_exception);
        if (caught_exception) {
          result = Factory::undefined_value();
        }
        SetProperty(stackFrame, script_name_or_source_url_key, result, NONE);
      }

      if (options & StackTrace::kFunctionName) {
        Handle<Object> fun_name(fun->shared()->name());
        if (fun_name->ToBoolean()->IsFalse()) {
          fun_name = Handle<Object>(fun->shared()->inferred_name());
        }
        SetProperty(stackFrame, function_key, fun_name, NONE);
      }

      if (options & StackTrace::kIsEval) {
        int type = Smi::cast(script->compilation_type())->value();
        Handle<Object> is_eval = (type == Script::COMPILATION_TYPE_EVAL) ?
            Factory::true_value() : Factory::false_value();
        SetProperty(stackFrame, eval_key, is_eval, NONE);
      }

      if (options & StackTrace::kIsConstructor) {
        Handle<Object> is_constructor = (frames[i].is_constructor()) ?
            Factory::true_value() : Factory::false_value();
        SetProperty(stackFrame, constructor_key, is_constructor, NONE);
      }

      FixedArray::cast(stack_trace->elements())->set(frames_seen, *stackFrame);
      frames_seen++;
    }
    it.Advance();
  }

  stack_trace->set_length(Smi::FromInt(frames_seen));
  return stack_trace;
}


void Top::PrintStack() {
  if (stack_trace_nesting_level == 0) {
    stack_trace_nesting_level++;

    StringAllocator* allocator;
    if (preallocated_message_space == NULL) {
      allocator = new HeapStringAllocator();
    } else {
      allocator = preallocated_message_space;
    }

    NativeAllocationChecker allocation_checker(
      !FLAG_preallocate_message_memory ?
      NativeAllocationChecker::ALLOW :
      NativeAllocationChecker::DISALLOW);

    StringStream::ClearMentionedObjectCache();
    StringStream accumulator(allocator);
    incomplete_message = &accumulator;
    PrintStack(&accumulator);
    accumulator.OutputToStdOut();
    accumulator.Log();
    incomplete_message = NULL;
    stack_trace_nesting_level = 0;
    if (preallocated_message_space == NULL) {
      // Remove the HeapStringAllocator created above.
      delete allocator;
    }
  } else if (stack_trace_nesting_level == 1) {
    stack_trace_nesting_level++;
    OS::PrintError(
      "\n\nAttempt to print stack while printing stack (double fault)\n");
    OS::PrintError(
      "If you are lucky you may find a partial stack dump on stdout.\n\n");
    incomplete_message->OutputToStdOut();
  }
}


static void PrintFrames(StringStream* accumulator,
                        StackFrame::PrintMode mode) {
  StackFrameIterator it;
  for (int i = 0; !it.done(); it.Advance()) {
    it.frame()->Print(accumulator, mode, i++);
  }
}


void Top::PrintStack(StringStream* accumulator) {
  // The MentionedObjectCache is not GC-proof at the moment.
  AssertNoAllocation nogc;
  ASSERT(StringStream::IsMentionedObjectCacheClear());

  // Avoid printing anything if there are no frames.
  if (c_entry_fp(GetCurrentThread()) == 0) return;

  accumulator->Add(
      "\n==== Stack trace ============================================\n\n");
  PrintFrames(accumulator, StackFrame::OVERVIEW);

  accumulator->Add(
      "\n==== Details ================================================\n\n");
  PrintFrames(accumulator, StackFrame::DETAILS);

  accumulator->PrintMentionedObjectCache();
  accumulator->Add("=====================\n\n");
}


void Top::SetFailedAccessCheckCallback(v8::FailedAccessCheckCallback callback) {
  thread_local_.failed_access_check_callback_ = callback;
}


void Top::ReportFailedAccessCheck(JSObject* receiver, v8::AccessType type) {
  if (!thread_local_.failed_access_check_callback_) return;

  ASSERT(receiver->IsAccessCheckNeeded());
  ASSERT(Top::context());

  // Get the data object from access check info.
  JSFunction* constructor = JSFunction::cast(receiver->map()->constructor());
  if (!constructor->shared()->IsApiFunction()) return;
  Object* data_obj =
      constructor->shared()->get_api_func_data()->access_check_info();
  if (data_obj == Heap::undefined_value()) return;

  HandleScope scope;
  Handle<JSObject> receiver_handle(receiver);
  Handle<Object> data(AccessCheckInfo::cast(data_obj)->data());
  thread_local_.failed_access_check_callback_(
    v8::Utils::ToLocal(receiver_handle),
    type,
    v8::Utils::ToLocal(data));
}


enum MayAccessDecision {
  YES, NO, UNKNOWN
};


static MayAccessDecision MayAccessPreCheck(JSObject* receiver,
                                           v8::AccessType type) {
  // During bootstrapping, callback functions are not enabled yet.
  if (Bootstrapper::IsActive()) return YES;

  if (receiver->IsJSGlobalProxy()) {
    Object* receiver_context = JSGlobalProxy::cast(receiver)->context();
    if (!receiver_context->IsContext()) return NO;

    // Get the global context of current top context.
    // avoid using Top::global_context() because it uses Handle.
    Context* global_context = Top::context()->global()->global_context();
    if (receiver_context == global_context) return YES;

    if (Context::cast(receiver_context)->security_token() ==
        global_context->security_token())
      return YES;
  }

  return UNKNOWN;
}


bool Top::MayNamedAccess(JSObject* receiver, Object* key, v8::AccessType type) {
  ASSERT(receiver->IsAccessCheckNeeded());

  // The callers of this method are not expecting a GC.
  AssertNoAllocation no_gc;

  // Skip checks for hidden properties access.  Note, we do not
  // require existence of a context in this case.
  if (key == Heap::hidden_symbol()) return true;

  // Check for compatibility between the security tokens in the
  // current lexical context and the accessed object.
  ASSERT(Top::context());

  MayAccessDecision decision = MayAccessPreCheck(receiver, type);
  if (decision != UNKNOWN) return decision == YES;

  // Get named access check callback
  JSFunction* constructor = JSFunction::cast(receiver->map()->constructor());
  if (!constructor->shared()->IsApiFunction()) return false;

  Object* data_obj =
     constructor->shared()->get_api_func_data()->access_check_info();
  if (data_obj == Heap::undefined_value()) return false;

  Object* fun_obj = AccessCheckInfo::cast(data_obj)->named_callback();
  v8::NamedSecurityCallback callback =
      v8::ToCData<v8::NamedSecurityCallback>(fun_obj);

  if (!callback) return false;

  HandleScope scope;
  Handle<JSObject> receiver_handle(receiver);
  Handle<Object> key_handle(key);
  Handle<Object> data(AccessCheckInfo::cast(data_obj)->data());
  LOG(ApiNamedSecurityCheck(key));
  bool result = false;
  {
    // Leaving JavaScript.
    VMState state(EXTERNAL);
    result = callback(v8::Utils::ToLocal(receiver_handle),
                      v8::Utils::ToLocal(key_handle),
                      type,
                      v8::Utils::ToLocal(data));
  }
  return result;
}


bool Top::MayIndexedAccess(JSObject* receiver,
                           uint32_t index,
                           v8::AccessType type) {
  ASSERT(receiver->IsAccessCheckNeeded());
  // Check for compatibility between the security tokens in the
  // current lexical context and the accessed object.
  ASSERT(Top::context());
  // The callers of this method are not expecting a GC.
  AssertNoAllocation no_gc;

  MayAccessDecision decision = MayAccessPreCheck(receiver, type);
  if (decision != UNKNOWN) return decision == YES;

  // Get indexed access check callback
  JSFunction* constructor = JSFunction::cast(receiver->map()->constructor());
  if (!constructor->shared()->IsApiFunction()) return false;

  Object* data_obj =
      constructor->shared()->get_api_func_data()->access_check_info();
  if (data_obj == Heap::undefined_value()) return false;

  Object* fun_obj = AccessCheckInfo::cast(data_obj)->indexed_callback();
  v8::IndexedSecurityCallback callback =
      v8::ToCData<v8::IndexedSecurityCallback>(fun_obj);

  if (!callback) return false;

  HandleScope scope;
  Handle<JSObject> receiver_handle(receiver);
  Handle<Object> data(AccessCheckInfo::cast(data_obj)->data());
  LOG(ApiIndexedSecurityCheck(index));
  bool result = false;
  {
    // Leaving JavaScript.
    VMState state(EXTERNAL);
    result = callback(v8::Utils::ToLocal(receiver_handle),
                      index,
                      type,
                      v8::Utils::ToLocal(data));
  }
  return result;
}


const char* Top::kStackOverflowMessage =
  "Uncaught RangeError: Maximum call stack size exceeded";


Failure* Top::StackOverflow() {
  HandleScope scope;
  Handle<String> key = Factory::stack_overflow_symbol();
  Handle<JSObject> boilerplate =
      Handle<JSObject>::cast(GetProperty(Top::builtins(), key));
  Handle<Object> exception = Copy(boilerplate);
  // TODO(1240995): To avoid having to call JavaScript code to compute
  // the message for stack overflow exceptions which is very likely to
  // double fault with another stack overflow exception, we use a
  // precomputed message.
  DoThrow(*exception, NULL, kStackOverflowMessage);
  return Failure::Exception();
}


Failure* Top::TerminateExecution() {
  DoThrow(Heap::termination_exception(), NULL, NULL);
  return Failure::Exception();
}


Failure* Top::Throw(Object* exception, MessageLocation* location) {
  DoThrow(exception, location, NULL);
  return Failure::Exception();
}


Failure* Top::ReThrow(MaybeObject* exception, MessageLocation* location) {
  // Set the exception being re-thrown.
  set_pending_exception(exception);
  return Failure::Exception();
}


Failure* Top::ThrowIllegalOperation() {
  return Throw(Heap::illegal_access_symbol());
}


void Top::ScheduleThrow(Object* exception) {
  // When scheduling a throw we first throw the exception to get the
  // error reporting if it is uncaught before rescheduling it.
  Throw(exception);
  thread_local_.scheduled_exception_ = pending_exception();
  thread_local_.external_caught_exception_ = false;
  clear_pending_exception();
}


Failure* Top::PromoteScheduledException() {
  MaybeObject* thrown = scheduled_exception();
  clear_scheduled_exception();
  // Re-throw the exception to avoid getting repeated error reporting.
  return ReThrow(thrown);
}


void Top::PrintCurrentStackTrace(FILE* out) {
  StackTraceFrameIterator it;
  while (!it.done()) {
    HandleScope scope;
    // Find code position if recorded in relocation info.
    JavaScriptFrame* frame = it.frame();
    int pos = frame->code()->SourcePosition(frame->pc());
    Handle<Object> pos_obj(Smi::FromInt(pos));
    // Fetch function and receiver.
    Handle<JSFunction> fun(JSFunction::cast(frame->function()));
    Handle<Object> recv(frame->receiver());
    // Advance to the next JavaScript frame and determine if the
    // current frame is the top-level frame.
    it.Advance();
    Handle<Object> is_top_level = it.done()
        ? Factory::true_value()
        : Factory::false_value();
    // Generate and print stack trace line.
    Handle<String> line =
        Execution::GetStackTraceLine(recv, fun, pos_obj, is_top_level);
    if (line->length() > 0) {
      line->PrintOn(out);
      fprintf(out, "\n");
    }
  }
}


void Top::ComputeLocation(MessageLocation* target) {
  *target = MessageLocation(Handle<Script>(Heap::empty_script()), -1, -1);
  StackTraceFrameIterator it;
  if (!it.done()) {
    JavaScriptFrame* frame = it.frame();
    JSFunction* fun = JSFunction::cast(frame->function());
    Object* script = fun->shared()->script();
    if (script->IsScript() &&
        !(Script::cast(script)->source()->IsUndefined())) {
      int pos = frame->code()->SourcePosition(frame->pc());
      // Compute the location from the function and the reloc info.
      Handle<Script> casted_script(Script::cast(script));
      *target = MessageLocation(casted_script, pos, pos + 1);
    }
  }
}


bool Top::ShouldReturnException(bool* is_caught_externally,
                                bool catchable_by_javascript) {
  // Find the top-most try-catch handler.
  StackHandler* handler =
      StackHandler::FromAddress(Top::handler(Top::GetCurrentThread()));
  while (handler != NULL && !handler->is_try_catch()) {
    handler = handler->next();
  }

  // Get the address of the external handler so we can compare the address to
  // determine which one is closer to the top of the stack.
  Address external_handler_address = thread_local_.try_catch_handler_address();

  // The exception has been externally caught if and only if there is
  // an external handler which is on top of the top-most try-catch
  // handler.
  *is_caught_externally = external_handler_address != NULL &&
      (handler == NULL || handler->address() > external_handler_address ||
       !catchable_by_javascript);

  if (*is_caught_externally) {
    // Only report the exception if the external handler is verbose.
    return thread_local_.TryCatchHandler()->is_verbose_;
  } else {
    // Report the exception if it isn't caught by JavaScript code.
    return handler == NULL;
  }
}


void Top::DoThrow(MaybeObject* exception,
                  MessageLocation* location,
                  const char* message) {
  ASSERT(!has_pending_exception());

  HandleScope scope;
  Object* exception_object = Smi::FromInt(0);
  bool is_object = exception->ToObject(&exception_object);
  Handle<Object> exception_handle(exception_object);

  // Determine reporting and whether the exception is caught externally.
  bool is_caught_externally = false;
  bool is_out_of_memory = exception == Failure::OutOfMemoryException();
  bool is_termination_exception = exception == Heap::termination_exception();
  bool catchable_by_javascript = !is_termination_exception && !is_out_of_memory;
  // Only real objects can be caught by JS.
  ASSERT(!catchable_by_javascript || is_object);
  bool should_return_exception =
      ShouldReturnException(&is_caught_externally, catchable_by_javascript);
  bool report_exception = catchable_by_javascript && should_return_exception;

#ifdef ENABLE_DEBUGGER_SUPPORT
  // Notify debugger of exception.
  if (catchable_by_javascript) {
    Debugger::OnException(exception_handle, report_exception);
  }
#endif

  // Generate the message.
  Handle<Object> message_obj;
  MessageLocation potential_computed_location;
  bool try_catch_needs_message =
      is_caught_externally &&
      thread_local_.TryCatchHandler()->capture_message_;
  if (report_exception || try_catch_needs_message) {
    if (location == NULL) {
      // If no location was specified we use a computed one instead
      ComputeLocation(&potential_computed_location);
      location = &potential_computed_location;
    }
    if (!Bootstrapper::IsActive()) {
      // It's not safe to try to make message objects or collect stack
      // traces while the bootstrapper is active since the infrastructure
      // may not have been properly initialized.
      Handle<String> stack_trace;
      if (FLAG_trace_exception) stack_trace = StackTraceString();
      Handle<JSArray> stack_trace_object;
      if (report_exception && capture_stack_trace_for_uncaught_exceptions) {
          stack_trace_object = Top::CaptureCurrentStackTrace(
              stack_trace_for_uncaught_exceptions_frame_limit,
              stack_trace_for_uncaught_exceptions_options);
      }
      ASSERT(is_object);  // Can't use the handle unless there's a real object.
      message_obj = MessageHandler::MakeMessageObject("uncaught_exception",
          location, HandleVector<Object>(&exception_handle, 1), stack_trace,
          stack_trace_object);
    }
  }

  // Save the message for reporting if the the exception remains uncaught.
  thread_local_.has_pending_message_ = report_exception;
  thread_local_.pending_message_ = message;
  if (!message_obj.is_null()) {
    thread_local_.pending_message_obj_ = *message_obj;
    if (location != NULL) {
      thread_local_.pending_message_script_ = *location->script();
      thread_local_.pending_message_start_pos_ = location->start_pos();
      thread_local_.pending_message_end_pos_ = location->end_pos();
    }
  }

  if (is_caught_externally) {
    thread_local_.catcher_ = thread_local_.TryCatchHandler();
  }

  // NOTE: Notifying the debugger or generating the message
  // may have caused new exceptions. For now, we just ignore
  // that and set the pending exception to the original one.
  if (is_object) {
    set_pending_exception(*exception_handle);
  } else {
    // Failures are not on the heap so they neither need nor work with handles.
    ASSERT(exception_handle->IsFailure());
    set_pending_exception(exception);
  }
}


void Top::ReportPendingMessages() {
  ASSERT(has_pending_exception());
  setup_external_caught();
  // If the pending exception is OutOfMemoryException set out_of_memory in
  // the global context.  Note: We have to mark the global context here
  // since the GenerateThrowOutOfMemory stub cannot make a RuntimeCall to
  // set it.
  bool external_caught = thread_local_.external_caught_exception_;
  HandleScope scope;
  if (thread_local_.pending_exception_ == Failure::OutOfMemoryException()) {
    context()->mark_out_of_memory();
  } else if (thread_local_.pending_exception_ ==
             Heap::termination_exception()) {
    if (external_caught) {
      thread_local_.TryCatchHandler()->can_continue_ = false;
      thread_local_.TryCatchHandler()->exception_ = Heap::null_value();
    }
  } else {
    // At this point all non-object (failure) exceptions have
    // been dealt with so this shouldn't fail.
    Object* pending_exception_object = pending_exception()->ToObjectUnchecked();
    Handle<Object> exception(pending_exception_object);
    thread_local_.external_caught_exception_ = false;
    if (external_caught) {
      thread_local_.TryCatchHandler()->can_continue_ = true;
      thread_local_.TryCatchHandler()->exception_ =
        thread_local_.pending_exception_;
      if (!thread_local_.pending_message_obj_->IsTheHole()) {
        try_catch_handler()->message_ = thread_local_.pending_message_obj_;
      }
    }
    if (thread_local_.has_pending_message_) {
      thread_local_.has_pending_message_ = false;
      if (thread_local_.pending_message_ != NULL) {
        MessageHandler::ReportMessage(thread_local_.pending_message_);
      } else if (!thread_local_.pending_message_obj_->IsTheHole()) {
        Handle<Object> message_obj(thread_local_.pending_message_obj_);
        if (thread_local_.pending_message_script_ != NULL) {
          Handle<Script> script(thread_local_.pending_message_script_);
          int start_pos = thread_local_.pending_message_start_pos_;
          int end_pos = thread_local_.pending_message_end_pos_;
          MessageLocation location(script, start_pos, end_pos);
          MessageHandler::ReportMessage(&location, message_obj);
        } else {
          MessageHandler::ReportMessage(NULL, message_obj);
        }
      }
    }
    thread_local_.external_caught_exception_ = external_caught;
    set_pending_exception(*exception);
  }
  clear_pending_message();
}


void Top::TraceException(bool flag) {
  FLAG_trace_exception = flag;
}


bool Top::OptionalRescheduleException(bool is_bottom_call) {
  // Allways reschedule out of memory exceptions.
  if (!is_out_of_memory()) {
    bool is_termination_exception =
        pending_exception() == Heap::termination_exception();

    // Do not reschedule the exception if this is the bottom call.
    bool clear_exception = is_bottom_call;

    if (is_termination_exception) {
      if (is_bottom_call) {
        thread_local_.external_caught_exception_ = false;
        clear_pending_exception();
        return false;
      }
    } else if (thread_local_.external_caught_exception_) {
      // If the exception is externally caught, clear it if there are no
      // JavaScript frames on the way to the C++ frame that has the
      // external handler.
      ASSERT(thread_local_.try_catch_handler_address() != NULL);
      Address external_handler_address =
          thread_local_.try_catch_handler_address();
      JavaScriptFrameIterator it;
      if (it.done() || (it.frame()->sp() > external_handler_address)) {
        clear_exception = true;
      }
    }

    // Clear the exception if needed.
    if (clear_exception) {
      thread_local_.external_caught_exception_ = false;
      clear_pending_exception();
      return false;
    }
  }

  // Reschedule the exception.
  thread_local_.scheduled_exception_ = pending_exception();
  clear_pending_exception();
  return true;
}


void Top::SetCaptureStackTraceForUncaughtExceptions(
      bool capture,
      int frame_limit,
      StackTrace::StackTraceOptions options) {
  capture_stack_trace_for_uncaught_exceptions = capture;
  stack_trace_for_uncaught_exceptions_frame_limit = frame_limit;
  stack_trace_for_uncaught_exceptions_options = options;
}


bool Top::is_out_of_memory() {
  if (has_pending_exception()) {
    MaybeObject* e = pending_exception();
    if (e->IsFailure() && Failure::cast(e)->IsOutOfMemoryException()) {
      return true;
    }
  }
  if (has_scheduled_exception()) {
    MaybeObject* e = scheduled_exception();
    if (e->IsFailure() && Failure::cast(e)->IsOutOfMemoryException()) {
      return true;
    }
  }
  return false;
}


Handle<Context> Top::global_context() {
  GlobalObject* global = thread_local_.context_->global();
  return Handle<Context>(global->global_context());
}


Handle<Context> Top::GetCallingGlobalContext() {
  JavaScriptFrameIterator it;
#ifdef ENABLE_DEBUGGER_SUPPORT
  if (Debug::InDebugger()) {
    while (!it.done()) {
      JavaScriptFrame* frame = it.frame();
      Context* context = Context::cast(frame->context());
      if (context->global_context() == *Debug::debug_context()) {
        it.Advance();
      } else {
        break;
      }
    }
  }
#endif  // ENABLE_DEBUGGER_SUPPORT
  if (it.done()) return Handle<Context>::null();
  JavaScriptFrame* frame = it.frame();
  Context* context = Context::cast(frame->context());
  return Handle<Context>(context->global_context());
}


char* Top::ArchiveThread(char* to) {
  memcpy(to, reinterpret_cast<char*>(&thread_local_), sizeof(thread_local_));
  InitializeThreadLocal();
  return to + sizeof(thread_local_);
}


char* Top::RestoreThread(char* from) {
  memcpy(reinterpret_cast<char*>(&thread_local_), from, sizeof(thread_local_));
  // This might be just paranoia, but it seems to be needed in case a
  // thread_local_ is restored on a separate OS thread.
#ifdef USE_SIMULATOR
#ifdef V8_TARGET_ARCH_ARM
  thread_local_.simulator_ = assembler::arm::Simulator::current();
#elif V8_TARGET_ARCH_MIPS
  thread_local_.simulator_ = assembler::mips::Simulator::current();
#endif
#endif
  return from + sizeof(thread_local_);
}

} }  // namespace v8::internal
