Commit b5a19c10 authored by ager@chromium.org's avatar ager@chromium.org

Rework the way we handle the fact that the ARM simulator uses a

separate JS stack.

In exception handling, we need to be able to compare addresses into
the JavaScript portion of the stack with the address of a C++ handler
on the stack.  Since the stacks are separate on the simulator, we need
a JavaScript stack address corresponding to a C++ try catch handler in
order to perform valid address comparisons.

On the simulator, we now link the C++ try catch handlers indirectly
through the JS stack and use the JS stack indirection address for
comparisons.

      JS                    C++
                           
                           handler
 [C++ address]   <------    next_
                \
                 \
                  \---->   handler
 [C++ address]   <------    next_


On actual hardware the C++ try catch handlers continue to be directly
linked.

BUG=http://code.google.com/p/v8/issues/detail?id=271
Review URL: http://codereview.chromium.org/360004

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3228 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent ec7034e6
...@@ -129,8 +129,9 @@ class Data; ...@@ -129,8 +129,9 @@ class Data;
namespace internal { namespace internal {
class Object;
class Arguments; class Arguments;
class Object;
class Top;
} }
...@@ -2532,15 +2533,16 @@ class V8EXPORT TryCatch { ...@@ -2532,15 +2533,16 @@ class V8EXPORT TryCatch {
*/ */
void SetCaptureMessage(bool value); void SetCaptureMessage(bool value);
public: private:
TryCatch* next_; void* next_;
void* exception_; void* exception_;
void* message_; void* message_;
bool is_verbose_ : 1; bool is_verbose_ : 1;
bool can_continue_ : 1; bool can_continue_ : 1;
bool capture_message_ : 1; bool capture_message_ : 1;
bool rethrow_ : 1; bool rethrow_ : 1;
void* js_handler_;
friend class v8::internal::Top;
}; };
......
...@@ -1191,14 +1191,13 @@ void Script::SetData(v8::Handle<Value> data) { ...@@ -1191,14 +1191,13 @@ void Script::SetData(v8::Handle<Value> data) {
v8::TryCatch::TryCatch() v8::TryCatch::TryCatch()
: next_(i::Top::try_catch_handler()), : next_(i::Top::try_catch_handler_address()),
exception_(i::Heap::the_hole_value()), exception_(i::Heap::the_hole_value()),
message_(i::Smi::FromInt(0)), message_(i::Smi::FromInt(0)),
is_verbose_(false), is_verbose_(false),
can_continue_(true), can_continue_(true),
capture_message_(true), capture_message_(true),
rethrow_(false), rethrow_(false) {
js_handler_(NULL) {
i::Top::RegisterTryCatchHandler(this); i::Top::RegisterTryCatchHandler(this);
} }
......
...@@ -1924,6 +1924,25 @@ int32_t Simulator::Call(byte* entry, int argument_count, ...) { ...@@ -1924,6 +1924,25 @@ int32_t Simulator::Call(byte* entry, int argument_count, ...) {
return result; return result;
} }
uintptr_t Simulator::PushAddress(uintptr_t address) {
int new_sp = get_register(sp) - sizeof(uintptr_t);
uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(new_sp);
*stack_slot = address;
set_register(sp, new_sp);
return new_sp;
}
uintptr_t Simulator::PopAddress() {
int current_sp = get_register(sp);
uintptr_t* stack_slot = reinterpret_cast<uintptr_t*>(current_sp);
uintptr_t address = *stack_slot;
set_register(sp, current_sp + sizeof(uintptr_t));
return address;
}
} } // namespace assembler::arm } } // namespace assembler::arm
#endif // !defined(__arm__) #endif // !defined(__arm__)
...@@ -52,6 +52,12 @@ class SimulatorStack : public v8::internal::AllStatic { ...@@ -52,6 +52,12 @@ class SimulatorStack : public v8::internal::AllStatic {
static inline uintptr_t JsLimitFromCLimit(uintptr_t c_limit) { static inline uintptr_t JsLimitFromCLimit(uintptr_t c_limit) {
return c_limit; return c_limit;
} }
static inline uintptr_t RegisterCTryCatch(uintptr_t try_catch_address) {
return try_catch_address;
}
static inline void UnregisterCTryCatch() { }
}; };
...@@ -60,6 +66,10 @@ class SimulatorStack : public v8::internal::AllStatic { ...@@ -60,6 +66,10 @@ class SimulatorStack : public v8::internal::AllStatic {
#define CALL_GENERATED_REGEXP_CODE(entry, p0, p1, p2, p3, p4, p5, p6) \ #define CALL_GENERATED_REGEXP_CODE(entry, p0, p1, p2, p3, p4, p5, p6) \
entry(p0, p1, p2, p3, p4, p5, p6) entry(p0, p1, p2, p3, p4, p5, p6)
#define TRY_CATCH_FROM_ADDRESS(try_catch_address) \
reinterpret_cast<TryCatch*>(try_catch_address)
#else // defined(__arm__) #else // defined(__arm__)
// When running with the simulator transition into simulated execution at this // When running with the simulator transition into simulated execution at this
...@@ -73,6 +83,11 @@ class SimulatorStack : public v8::internal::AllStatic { ...@@ -73,6 +83,11 @@ class SimulatorStack : public v8::internal::AllStatic {
assembler::arm::Simulator::current()->Call( \ assembler::arm::Simulator::current()->Call( \
FUNCTION_ADDR(entry), 7, p0, p1, p2, p3, p4, p5, p6) FUNCTION_ADDR(entry), 7, p0, p1, p2, p3, p4, p5, p6)
#define TRY_CATCH_FROM_ADDRESS(try_catch_address) \
try_catch_address == NULL ? \
NULL : *(reinterpret_cast<TryCatch**>(try_catch_address))
#include "constants-arm.h" #include "constants-arm.h"
...@@ -124,6 +139,12 @@ class Simulator { ...@@ -124,6 +139,12 @@ class Simulator {
// which sets up the simulator state and grabs the result on return. // which sets up the simulator state and grabs the result on return.
int32_t Call(byte* entry, int argument_count, ...); int32_t Call(byte* entry, int argument_count, ...);
// Push an address onto the JS stack.
uintptr_t PushAddress(uintptr_t address);
// Pop an address from the JS stack.
uintptr_t PopAddress();
private: private:
enum special_values { enum special_values {
// Known bad pc value to ensure that the simulator does not execute // Known bad pc value to ensure that the simulator does not execute
...@@ -198,20 +219,20 @@ class Simulator { ...@@ -198,20 +219,20 @@ class Simulator {
void SetFpResult(const double& result); void SetFpResult(const double& result);
void TrashCallerSaveRegisters(); void TrashCallerSaveRegisters();
// architecture state // Architecture state.
int32_t registers_[16]; int32_t registers_[16];
bool n_flag_; bool n_flag_;
bool z_flag_; bool z_flag_;
bool c_flag_; bool c_flag_;
bool v_flag_; bool v_flag_;
// simulator support // Simulator support.
char* stack_; char* stack_;
bool pc_modified_; bool pc_modified_;
int icount_; int icount_;
static bool initialized_; static bool initialized_;
// registered breakpoints // Registered breakpoints.
Instr* break_pc_; Instr* break_pc_;
instr_t break_instr_; instr_t break_instr_;
}; };
...@@ -229,6 +250,15 @@ class SimulatorStack : public v8::internal::AllStatic { ...@@ -229,6 +250,15 @@ class SimulatorStack : public v8::internal::AllStatic {
static inline uintptr_t JsLimitFromCLimit(uintptr_t c_limit) { static inline uintptr_t JsLimitFromCLimit(uintptr_t c_limit) {
return assembler::arm::Simulator::current()->StackLimit(); return assembler::arm::Simulator::current()->StackLimit();
} }
static inline uintptr_t RegisterCTryCatch(uintptr_t try_catch_address) {
assembler::arm::Simulator* sim = assembler::arm::Simulator::current();
return sim->PushAddress(try_catch_address);
}
static inline void UnregisterCTryCatch() {
assembler::arm::Simulator::current()->PopAddress();
}
}; };
......
...@@ -31,18 +31,8 @@ ...@@ -31,18 +31,8 @@
#include "api.h" #include "api.h"
#include "codegen-inl.h" #include "codegen-inl.h"
#if V8_TARGET_ARCH_IA32
#include "ia32/simulator-ia32.h"
#elif V8_TARGET_ARCH_X64
#include "x64/simulator-x64.h"
#elif V8_TARGET_ARCH_ARM
#include "arm/simulator-arm.h"
#else
#error Unsupported target architecture.
#endif
#include "debug.h" #include "debug.h"
#include "simulator.h"
#include "v8threads.h" #include "v8threads.h"
namespace v8 { namespace v8 {
......
...@@ -43,6 +43,12 @@ class SimulatorStack : public v8::internal::AllStatic { ...@@ -43,6 +43,12 @@ class SimulatorStack : public v8::internal::AllStatic {
static inline uintptr_t JsLimitFromCLimit(uintptr_t c_limit) { static inline uintptr_t JsLimitFromCLimit(uintptr_t c_limit) {
return c_limit; return c_limit;
} }
static inline uintptr_t RegisterCTryCatch(uintptr_t try_catch_address) {
return try_catch_address;
}
static inline void UnregisterCTryCatch() { }
}; };
// Call the generated regexp code directly. The entry function pointer should // Call the generated regexp code directly. The entry function pointer should
...@@ -50,4 +56,7 @@ class SimulatorStack : public v8::internal::AllStatic { ...@@ -50,4 +56,7 @@ class SimulatorStack : public v8::internal::AllStatic {
#define CALL_GENERATED_REGEXP_CODE(entry, p0, p1, p2, p3, p4, p5, p6) \ #define CALL_GENERATED_REGEXP_CODE(entry, p0, p1, p2, p3, p4, p5, p6) \
entry(p0, p1, p2, p3, p4, p5, p6) entry(p0, p1, p2, p3, p4, p5, p6)
#define TRY_CATCH_FROM_ADDRESS(try_catch_address) \
reinterpret_cast<TryCatch*>(try_catch_address)
#endif // V8_IA32_SIMULATOR_IA32_H_ #endif // V8_IA32_SIMULATOR_IA32_H_
...@@ -30,13 +30,7 @@ ...@@ -30,13 +30,7 @@
#include "assembler.h" #include "assembler.h"
#include "regexp-stack.h" #include "regexp-stack.h"
#include "regexp-macro-assembler.h" #include "regexp-macro-assembler.h"
#if V8_TARGET_ARCH_ARM #include "simulator.h"
#include "arm/simulator-arm.h"
#elif V8_TARGET_ARCH_IA32
#include "ia32/simulator-ia32.h"
#elif V8_TARGET_ARCH_X64
#include "x64/simulator-x64.h"
#endif
namespace v8 { namespace v8 {
namespace internal { namespace internal {
......
// Copyright 2009 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.
#ifndef V8_SIMULATOR_H_
#define V8_SIMULATOR_H_
#if V8_TARGET_ARCH_IA32
#include "ia32/simulator-ia32.h"
#elif V8_TARGET_ARCH_X64
#include "x64/simulator-x64.h"
#elif V8_TARGET_ARCH_ARM
#include "arm/simulator-arm.h"
#else
#error Unsupported target architecture.
#endif
#endif // V8_SIMULATOR_H_
...@@ -31,8 +31,9 @@ ...@@ -31,8 +31,9 @@
#include "bootstrapper.h" #include "bootstrapper.h"
#include "debug.h" #include "debug.h"
#include "execution.h" #include "execution.h"
#include "string-stream.h"
#include "platform.h" #include "platform.h"
#include "simulator.h"
#include "string-stream.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
...@@ -50,6 +51,30 @@ Address top_addresses[] = { ...@@ -50,6 +51,30 @@ Address top_addresses[] = {
NULL 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) { Address Top::get_address_from_id(Top::AddressId id) {
return top_addresses[id]; return top_addresses[id];
} }
...@@ -70,9 +95,9 @@ void Top::Iterate(ObjectVisitor* v, ThreadLocalTop* thread) { ...@@ -70,9 +95,9 @@ void Top::Iterate(ObjectVisitor* v, ThreadLocalTop* thread) {
v->VisitPointer(bit_cast<Object**, Context**>(&(thread->context_))); v->VisitPointer(bit_cast<Object**, Context**>(&(thread->context_)));
v->VisitPointer(&(thread->scheduled_exception_)); v->VisitPointer(&(thread->scheduled_exception_));
for (v8::TryCatch* block = thread->try_catch_handler_; for (v8::TryCatch* block = thread->TryCatchHandler();
block != NULL; 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->exception_)));
v->VisitPointer(bit_cast<Object**, void**>(&(block->message_))); v->VisitPointer(bit_cast<Object**, void**>(&(block->message_)));
} }
...@@ -91,23 +116,10 @@ void Top::Iterate(ObjectVisitor* v) { ...@@ -91,23 +116,10 @@ void Top::Iterate(ObjectVisitor* v) {
void Top::InitializeThreadLocal() { void Top::InitializeThreadLocal() {
thread_local_.c_entry_fp_ = 0; thread_local_.Initialize();
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;
clear_pending_exception(); clear_pending_exception();
clear_pending_message(); clear_pending_message();
clear_scheduled_exception(); clear_scheduled_exception();
thread_local_.save_context_ = NULL;
thread_local_.catcher_ = NULL;
} }
...@@ -254,46 +266,24 @@ void Top::TearDown() { ...@@ -254,46 +266,24 @@ void Top::TearDown() {
} }
// 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) { void Top::RegisterTryCatchHandler(v8::TryCatch* that) {
StackHandler* handler = // The ARM simulator has a separate JS stack. We therefore register
reinterpret_cast<StackHandler*>(thread_local_.handler_); // the C++ try catch handler with the simulator and get back an
// address that can be used for comparisons with addresses into the
// Find the top-most try-catch handler. // JS stack. When running without the simulator, the address
while (handler != NULL && !handler->is_try_catch()) { // returned will be the address of the C++ try catch handler itself.
handler = handler->next(); Address address = reinterpret_cast<Address>(
} SimulatorStack::RegisterCTryCatch(reinterpret_cast<uintptr_t>(that)));
thread_local_.set_try_catch_handler_address(address);
that->js_handler_ = handler; // casted to void*
thread_local_.try_catch_handler_ = that;
} }
void Top::UnregisterTryCatchHandler(v8::TryCatch* that) { void Top::UnregisterTryCatchHandler(v8::TryCatch* that) {
ASSERT(thread_local_.try_catch_handler_ == that); ASSERT(thread_local_.TryCatchHandler() == that);
thread_local_.try_catch_handler_ = that->next_; thread_local_.set_try_catch_handler_address(
reinterpret_cast<Address>(that->next_));
thread_local_.catcher_ = NULL; thread_local_.catcher_ = NULL;
SimulatorStack::UnregisterCTryCatch();
} }
...@@ -725,20 +715,18 @@ bool Top::ShouldReturnException(bool* is_caught_externally, ...@@ -725,20 +715,18 @@ bool Top::ShouldReturnException(bool* is_caught_externally,
// Get the address of the external handler so we can compare the address to // 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. // 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 // 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 // an external handler which is on top of the top-most try-catch
// handler. // handler.
// *is_caught_externally = external_handler_address != NULL &&
// See comments in RegisterTryCatchHandler for details. (handler == NULL || handler->address() > external_handler_address ||
*is_caught_externally = try_catch != NULL &&
(handler == NULL || handler == try_catch->js_handler_ ||
!catchable_by_javascript); !catchable_by_javascript);
if (*is_caught_externally) { if (*is_caught_externally) {
// Only report the exception if the external handler is verbose. // 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 { } else {
// Report the exception if it isn't caught by JavaScript code. // Report the exception if it isn't caught by JavaScript code.
return handler == NULL; return handler == NULL;
...@@ -775,7 +763,7 @@ void Top::DoThrow(Object* exception, ...@@ -775,7 +763,7 @@ void Top::DoThrow(Object* exception,
MessageLocation potential_computed_location; MessageLocation potential_computed_location;
bool try_catch_needs_message = bool try_catch_needs_message =
is_caught_externally && is_caught_externally &&
thread_local_.try_catch_handler_->capture_message_; thread_local_.TryCatchHandler()->capture_message_;
if (report_exception || try_catch_needs_message) { if (report_exception || try_catch_needs_message) {
if (location == NULL) { if (location == NULL) {
// If no location was specified we use a computed one instead // If no location was specified we use a computed one instead
...@@ -806,7 +794,7 @@ void Top::DoThrow(Object* exception, ...@@ -806,7 +794,7 @@ void Top::DoThrow(Object* exception,
} }
if (is_caught_externally) { 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 // NOTE: Notifying the debugger or generating the message
...@@ -830,15 +818,15 @@ void Top::ReportPendingMessages() { ...@@ -830,15 +818,15 @@ void Top::ReportPendingMessages() {
} else if (thread_local_.pending_exception_ == } else if (thread_local_.pending_exception_ ==
Heap::termination_exception()) { Heap::termination_exception()) {
if (external_caught) { if (external_caught) {
thread_local_.try_catch_handler_->can_continue_ = false; thread_local_.TryCatchHandler()->can_continue_ = false;
thread_local_.try_catch_handler_->exception_ = Heap::null_value(); thread_local_.TryCatchHandler()->exception_ = Heap::null_value();
} }
} else { } else {
Handle<Object> exception(pending_exception()); Handle<Object> exception(pending_exception());
thread_local_.external_caught_exception_ = false; thread_local_.external_caught_exception_ = false;
if (external_caught) { if (external_caught) {
thread_local_.try_catch_handler_->can_continue_ = true; thread_local_.TryCatchHandler()->can_continue_ = true;
thread_local_.try_catch_handler_->exception_ = thread_local_.TryCatchHandler()->exception_ =
thread_local_.pending_exception_; thread_local_.pending_exception_;
if (!thread_local_.pending_message_obj_->IsTheHole()) { if (!thread_local_.pending_message_obj_->IsTheHole()) {
try_catch_handler()->message_ = thread_local_.pending_message_obj_; try_catch_handler()->message_ = thread_local_.pending_message_obj_;
...@@ -892,9 +880,9 @@ bool Top::OptionalRescheduleException(bool is_bottom_call) { ...@@ -892,9 +880,9 @@ bool Top::OptionalRescheduleException(bool is_bottom_call) {
// If the exception is externally caught, clear it if there are no // If the exception is externally caught, clear it if there are no
// JavaScript frames on the way to the C++ frame that has the // JavaScript frames on the way to the C++ frame that has the
// external handler. // external handler.
ASSERT(thread_local_.try_catch_handler_ != NULL); ASSERT(thread_local_.try_catch_handler_address() != NULL);
Address external_handler_address = Address external_handler_address =
reinterpret_cast<Address>(thread_local_.try_catch_handler_); thread_local_.try_catch_handler_address();
JavaScriptFrameIterator it; JavaScriptFrameIterator it;
if (it.done() || (it.frame()->sp() > external_handler_address)) { if (it.done() || (it.frame()->sp() > external_handler_address)) {
clear_exception = true; clear_exception = true;
......
...@@ -43,6 +43,41 @@ class SaveContext; // Forward declaration. ...@@ -43,6 +43,41 @@ class SaveContext; // Forward declaration.
class ThreadLocalTop BASE_EMBEDDED { class ThreadLocalTop BASE_EMBEDDED {
public: public:
// Initialize the thread data.
void Initialize();
// Get the top C++ try catch handler or NULL if none are registered.
//
// This method is not guarenteed to return an address that can be
// used for comparison with addresses into the JS stack. If such an
// address is needed, use try_catch_handler_address.
v8::TryCatch* TryCatchHandler();
// Get the address of the top C++ try catch handler or NULL if
// none are registered.
//
// This method always returns an address that can be compared to
// pointers into the JavaScript stack. When running on actual
// hardware, try_catch_handler_address and TryCatchHandler return
// the same pointer. When running on a simulator with a separate JS
// stack, try_catch_handler_address returns a JS stack address that
// corresponds to the place on the JS stack where the C++ handler
// would have been if the stack were not separate.
inline Address try_catch_handler_address() {
return try_catch_handler_address_;
}
// Set the address of the top C++ try catch handler.
inline void set_try_catch_handler_address(Address address) {
try_catch_handler_address_ = address;
}
void Free() {
ASSERT(!has_pending_message_);
ASSERT(!external_caught_exception_);
ASSERT(try_catch_handler_address_ == NULL);
}
// The context where the current execution method is created and for variable // The context where the current execution method is created and for variable
// lookups. // lookups.
Context* context_; Context* context_;
...@@ -59,7 +94,6 @@ class ThreadLocalTop BASE_EMBEDDED { ...@@ -59,7 +94,6 @@ class ThreadLocalTop BASE_EMBEDDED {
// unify them later. // unify them later.
Object* scheduled_exception_; Object* scheduled_exception_;
bool external_caught_exception_; bool external_caught_exception_;
v8::TryCatch* try_catch_handler_;
SaveContext* save_context_; SaveContext* save_context_;
v8::TryCatch* catcher_; v8::TryCatch* catcher_;
...@@ -79,11 +113,8 @@ class ThreadLocalTop BASE_EMBEDDED { ...@@ -79,11 +113,8 @@ class ThreadLocalTop BASE_EMBEDDED {
// Call back function to report unsafe JS accesses. // Call back function to report unsafe JS accesses.
v8::FailedAccessCheckCallback failed_access_check_callback_; v8::FailedAccessCheckCallback failed_access_check_callback_;
void Free() { private:
ASSERT(!has_pending_message_); Address try_catch_handler_address_;
ASSERT(!external_caught_exception_);
ASSERT(try_catch_handler_ == NULL);
}
}; };
#define TOP_ADDRESS_LIST(C) \ #define TOP_ADDRESS_LIST(C) \
...@@ -157,7 +188,10 @@ class Top { ...@@ -157,7 +188,10 @@ class Top {
thread_local_.pending_message_script_ = NULL; thread_local_.pending_message_script_ = NULL;
} }
static v8::TryCatch* try_catch_handler() { static v8::TryCatch* try_catch_handler() {
return thread_local_.try_catch_handler_; return thread_local_.TryCatchHandler();
}
static Address try_catch_handler_address() {
return thread_local_.try_catch_handler_address();
} }
// This method is called by the api after operations that may throw // This method is called by the api after operations that may throw
// exceptions. If an exception was thrown and not handled by an external // exceptions. If an exception was thrown and not handled by an external
...@@ -189,7 +223,7 @@ class Top { ...@@ -189,7 +223,7 @@ class Top {
thread_local_.external_caught_exception_ = thread_local_.external_caught_exception_ =
has_pending_exception() && has_pending_exception() &&
(thread_local_.catcher_ != NULL) && (thread_local_.catcher_ != NULL) &&
(thread_local_.try_catch_handler_ == thread_local_.catcher_); (try_catch_handler() == thread_local_.catcher_);
} }
// Tells whether the current context has experienced an out of memory // Tells whether the current context has experienced an out of memory
......
...@@ -30,13 +30,10 @@ ...@@ -30,13 +30,10 @@
#include "bootstrapper.h" #include "bootstrapper.h"
#include "debug.h" #include "debug.h"
#include "serialize.h" #include "serialize.h"
#include "simulator.h"
#include "stub-cache.h" #include "stub-cache.h"
#include "oprofile-agent.h" #include "oprofile-agent.h"
#if V8_TARGET_ARCH_ARM
#include "arm/simulator-arm.h"
#endif
namespace v8 { namespace v8 {
namespace internal { namespace internal {
......
...@@ -44,6 +44,12 @@ class SimulatorStack : public v8::internal::AllStatic { ...@@ -44,6 +44,12 @@ class SimulatorStack : public v8::internal::AllStatic {
static inline uintptr_t JsLimitFromCLimit(uintptr_t c_limit) { static inline uintptr_t JsLimitFromCLimit(uintptr_t c_limit) {
return c_limit; return c_limit;
} }
static inline uintptr_t RegisterCTryCatch(uintptr_t try_catch_address) {
return try_catch_address;
}
static inline void UnregisterCTryCatch() { }
}; };
// Call the generated regexp code directly. The entry function pointer should // Call the generated regexp code directly. The entry function pointer should
...@@ -51,4 +57,7 @@ class SimulatorStack : public v8::internal::AllStatic { ...@@ -51,4 +57,7 @@ class SimulatorStack : public v8::internal::AllStatic {
#define CALL_GENERATED_REGEXP_CODE(entry, p0, p1, p2, p3, p4, p5, p6) \ #define CALL_GENERATED_REGEXP_CODE(entry, p0, p1, p2, p3, p4, p5, p6) \
entry(p0, p1, p2, p3, p4, p5, p6) entry(p0, p1, p2, p3, p4, p5, p6)
#define TRY_CATCH_FROM_ADDRESS(try_catch_address) \
reinterpret_cast<TryCatch*>(try_catch_address)
#endif // V8_X64_SIMULATOR_X64_H_ #endif // V8_X64_SIMULATOR_X64_H_
...@@ -65,11 +65,3 @@ test-api/OutOfMemoryNested: SKIP ...@@ -65,11 +65,3 @@ test-api/OutOfMemoryNested: SKIP
# BUG(355): Test crashes on ARM. # BUG(355): Test crashes on ARM.
test-log/ProfLazyMode: SKIP test-log/ProfLazyMode: SKIP
[ $simulator == arm ]
# BUG(271): During exception propagation, we compare pointers into the
# stack. These tests fail on the ARM simulator because the C++ and
# the JavaScript stacks are separate.
test-api/ExceptionOrder: FAIL
test-api/TryCatchInTryFinally: FAIL
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment