| Index: src/top.cc
|
| ===================================================================
|
| --- src/top.cc (revision 3208)
|
| +++ src/top.cc (working copy)
|
| @@ -31,8 +31,9 @@
|
| #include "bootstrapper.h"
|
| #include "debug.h"
|
| #include "execution.h"
|
| -#include "string-stream.h"
|
| #include "platform.h"
|
| +#include "simulator.h"
|
| +#include "string-stream.h"
|
|
|
| namespace v8 {
|
| namespace internal {
|
| @@ -50,6 +51,30 @@
|
| NULL
|
| };
|
|
|
| +
|
| +v8::TryCatch* ThreadLocalTop::TryCatchHandler() {
|
| + return TRY_CATCH_FROM_ADDRESS(try_catch_handler_address());
|
| +}
|
| +
|
| +
|
| +void ThreadLocalTop::Initialize() {
|
| + c_entry_fp_ = 0;
|
| + handler_ = 0;
|
| +#ifdef ENABLE_LOGGING_AND_PROFILING
|
| + js_entry_sp_ = 0;
|
| +#endif
|
| + stack_is_cooked_ = false;
|
| + 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];
|
| }
|
| @@ -70,9 +95,9 @@
|
| v->VisitPointer(bit_cast<Object**, Context**>(&(thread->context_)));
|
| v->VisitPointer(&(thread->scheduled_exception_));
|
|
|
| - for (v8::TryCatch* block = thread->try_catch_handler_;
|
| + for (v8::TryCatch* block = thread->TryCatchHandler();
|
| block != NULL;
|
| - block = block->next_) {
|
| + block = TRY_CATCH_FROM_ADDRESS(block->next_)) {
|
| v->VisitPointer(bit_cast<Object**, void**>(&(block->exception_)));
|
| v->VisitPointer(bit_cast<Object**, void**>(&(block->message_)));
|
| }
|
| @@ -91,23 +116,10 @@
|
|
|
|
|
| void Top::InitializeThreadLocal() {
|
| - thread_local_.c_entry_fp_ = 0;
|
| - thread_local_.handler_ = 0;
|
| -#ifdef ENABLE_LOGGING_AND_PROFILING
|
| - thread_local_.js_entry_sp_ = 0;
|
| -#endif
|
| - thread_local_.stack_is_cooked_ = false;
|
| - thread_local_.try_catch_handler_ = NULL;
|
| - thread_local_.context_ = NULL;
|
| - int id = ThreadManager::CurrentId();
|
| - thread_local_.thread_id_ = (id == 0) ? ThreadManager::kInvalidId : id;
|
| - thread_local_.external_caught_exception_ = false;
|
| - thread_local_.failed_access_check_callback_ = NULL;
|
| + thread_local_.Initialize();
|
| clear_pending_exception();
|
| clear_pending_message();
|
| clear_scheduled_exception();
|
| - thread_local_.save_context_ = NULL;
|
| - thread_local_.catcher_ = NULL;
|
| }
|
|
|
|
|
| @@ -254,46 +266,24 @@
|
| }
|
|
|
|
|
| -// There are cases where the C stack is separated from JS stack (ARM simulator).
|
| -// To figure out the order of top-most JS try-catch handler and the top-most C
|
| -// try-catch handler, the C try-catch handler keeps a reference to the top-most
|
| -// JS try_catch handler when it was created.
|
| -//
|
| -// Here is a picture to explain the idea:
|
| -// Top::thread_local_.handler_ Top::thread_local_.try_catch_handler_
|
| -//
|
| -// | |
|
| -// v v
|
| -//
|
| -// | JS handler | | C try_catch handler |
|
| -// | next |--+ +-------- | js_handler_ |
|
| -// | | | next_ |--+
|
| -// | | |
|
| -// | JS handler |--+ <---------+ |
|
| -// | next |
|
| -//
|
| -// If the top-most JS try-catch handler is not equal to
|
| -// Top::thread_local_.try_catch_handler_.js_handler_, it means the JS handler
|
| -// is on the top. Otherwise, it means the C try-catch handler is on the top.
|
| -//
|
| void Top::RegisterTryCatchHandler(v8::TryCatch* that) {
|
| - StackHandler* handler =
|
| - reinterpret_cast<StackHandler*>(thread_local_.handler_);
|
| -
|
| - // Find the top-most try-catch handler.
|
| - while (handler != NULL && !handler->is_try_catch()) {
|
| - handler = handler->next();
|
| - }
|
| -
|
| - that->js_handler_ = handler; // casted to void*
|
| - thread_local_.try_catch_handler_ = 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_.try_catch_handler_ == that);
|
| - thread_local_.try_catch_handler_ = that->next_;
|
| + ASSERT(thread_local_.TryCatchHandler() == that);
|
| + thread_local_.set_try_catch_handler_address(
|
| + reinterpret_cast<Address>(that->next_));
|
| thread_local_.catcher_ = NULL;
|
| + SimulatorStack::UnregisterCTryCatch();
|
| }
|
|
|
|
|
| @@ -725,20 +715,18 @@
|
|
|
| // 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.
|
| - v8::TryCatch* try_catch = thread_local_.try_catch_handler_;
|
| + 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.
|
| - //
|
| - // See comments in RegisterTryCatchHandler for details.
|
| - *is_caught_externally = try_catch != NULL &&
|
| - (handler == NULL || handler == try_catch->js_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_.try_catch_handler_->is_verbose_;
|
| + return thread_local_.TryCatchHandler()->is_verbose_;
|
| } else {
|
| // Report the exception if it isn't caught by JavaScript code.
|
| return handler == NULL;
|
| @@ -775,7 +763,7 @@
|
| MessageLocation potential_computed_location;
|
| bool try_catch_needs_message =
|
| is_caught_externally &&
|
| - thread_local_.try_catch_handler_->capture_message_;
|
| + 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
|
| @@ -806,7 +794,7 @@
|
| }
|
|
|
| if (is_caught_externally) {
|
| - thread_local_.catcher_ = thread_local_.try_catch_handler_;
|
| + thread_local_.catcher_ = thread_local_.TryCatchHandler();
|
| }
|
|
|
| // NOTE: Notifying the debugger or generating the message
|
| @@ -830,15 +818,15 @@
|
| } else if (thread_local_.pending_exception_ ==
|
| Heap::termination_exception()) {
|
| if (external_caught) {
|
| - thread_local_.try_catch_handler_->can_continue_ = false;
|
| - thread_local_.try_catch_handler_->exception_ = Heap::null_value();
|
| + thread_local_.TryCatchHandler()->can_continue_ = false;
|
| + thread_local_.TryCatchHandler()->exception_ = Heap::null_value();
|
| }
|
| } else {
|
| Handle<Object> exception(pending_exception());
|
| thread_local_.external_caught_exception_ = false;
|
| if (external_caught) {
|
| - thread_local_.try_catch_handler_->can_continue_ = true;
|
| - thread_local_.try_catch_handler_->exception_ =
|
| + 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_;
|
| @@ -892,9 +880,9 @@
|
| // 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_ != NULL);
|
| + ASSERT(thread_local_.try_catch_handler_address() != NULL);
|
| Address external_handler_address =
|
| - reinterpret_cast<Address>(thread_local_.try_catch_handler_);
|
| + thread_local_.try_catch_handler_address();
|
| JavaScriptFrameIterator it;
|
| if (it.done() || (it.frame()->sp() > external_handler_address)) {
|
| clear_exception = true;
|
|
|