Pastie now auto-senses if line-wrap is a bad or good idea. Feedback?
## mark a section (Learn more)
diff --git a/vm/builtin/nativemethod.cpp b/vm/builtin/nativemethod.cpp index b989390..0a1f6df 100644 --- a/vm/builtin/nativemethod.cpp +++ b/vm/builtin/nativemethod.cpp @@ -2,6 +2,9 @@ #include "vm.hpp" +#include "exception.hpp" +#include "exception_point.hpp" +#include "message.hpp" #include "native_libraries.hpp" #include "primitives.hpp" @@ -11,8 +14,6 @@ #include "builtin/string.hpp" #include "builtin/tuple.hpp" -#include "message.hpp" - namespace rubinius { typedef TypedRoot<Object*> RootHandle; @@ -91,7 +92,6 @@ namespace rubinius { return create<GenericFunctor>(state); } - Object* NativeMethod::executor_implementation(STATE, CallFrame* call_frame, Message& msg) { NativeMethodEnvironment* env = native_method_environment.get(); NativeMethodFrame nmf(env->current_native_frame()); @@ -101,9 +101,20 @@ namespace rubinius { env->set_state(state); NativeMethod* nm = as<NativeMethod>(msg.method); - Object* ret = nm->call(state, env, msg); + + Object* ret; + ExceptionPoint ep(env); + + PLACE_EXCEPTION_POINT(ep); + + if(unlikely(ep.jumped_to())) { + ret = NULL; + } else { + ret = nm->call(state, env, msg); + } env->set_current_native_frame(nmf.previous()); + ep.pop(env); return ret; } @@ -256,6 +267,4 @@ namespace rubinius { } } - - } diff --git a/vm/builtin/nativemethod.hpp b/vm/builtin/nativemethod.hpp index 028329b..c57728a 100644 --- a/vm/builtin/nativemethod.hpp +++ b/vm/builtin/nativemethod.hpp @@ -20,6 +20,7 @@ namespace rubinius { /* Forwards */ + class ExceptionPoint; class Message; class NativeMethodFrame; @@ -99,6 +100,14 @@ namespace rubinius { current_native_frame_ = frame; } + ExceptionPoint* current_ep() { + return current_ep_; + } + + void set_current_ep(ExceptionPoint* ep) { + current_ep_ = ep; + } + /** Set of Handles available in current Frame (convenience.) */ Handles& handles(); @@ -113,6 +122,7 @@ namespace rubinius { NativeMethodFrame* current_native_frame_; /** Global object handles. */ Handles global_handles_; + ExceptionPoint* current_ep_; }; diff --git a/vm/exception_point.cpp b/vm/exception_point.cpp new file mode 100644 index 0000000..8cddf16 --- /dev/null +++ b/vm/exception_point.cpp @@ -0,0 +1,22 @@ +#include "exception_point.hpp" +#include "builtin/nativemethod.hpp" + +namespace rubinius { + ExceptionPoint::ExceptionPoint(NativeMethodEnvironment* env) + : jumped_to_(false) + , previous_(env->current_ep()) + { + env->set_current_ep(this); + } + + void ExceptionPoint::return_to(NativeMethodEnvironment* env) { + jumped_to_ = true; + env->set_current_ep(this); + _longjmp(__jump_buffer, 1); + abort(); // HUH! + } + + void ExceptionPoint::pop(NativeMethodEnvironment* env) { + env->set_current_ep(previous_); + } +} diff --git a/vm/exception_point.hpp b/vm/exception_point.hpp index 5571c26..075bd84 100644 --- a/vm/exception_point.hpp +++ b/vm/exception_point.hpp @@ -3,6 +3,8 @@ #include <setjmp.h> namespace rubinius { + class NativeMethodEnvironment; + class ExceptionPoint { bool jumped_to_; ExceptionPoint* previous_; @@ -11,12 +13,7 @@ namespace rubinius { jmp_buf __jump_buffer; public: - ExceptionPoint(Task* task) - : jumped_to_(false) - , previous_(task->current_ep) - { - task->current_ep = this; - } + ExceptionPoint(NativeMethodEnvironment* env); bool jumped_to() { return jumped_to_; @@ -26,23 +23,16 @@ namespace rubinius { jumped_to_ = false; } - void return_to(Task* task) { - jumped_to_ = true; - task->current_ep = this; - _longjmp(__jump_buffer, 1); - abort(); // HUH! - } - - void unwind_to_previous(Task* task) { - previous_->return_to(task); - } + void return_to(NativeMethodEnvironment* env); - void pop(Task* task) { - task->current_ep = previous_; + void unwind_to_previous(NativeMethodEnvironment* env) { + previous_->return_to(env); } + void pop(NativeMethodEnvironment* env); }; } -#define PLACE_EXCEPTIONPOINT(ep) _setjmp(ep.__jump_buffer) + +#define PLACE_EXCEPTION_POINT(ep) _setjmp(ep.__jump_buffer) #endif diff --git a/vm/subtend/ruby.cpp b/vm/subtend/ruby.cpp index b7e3345..3a56ecb 100644 --- a/vm/subtend/ruby.cpp +++ b/vm/subtend/ruby.cpp @@ -20,6 +20,8 @@ #include "builtin/string.hpp" #include "builtin/symbol.hpp" +#include "vm/exception.hpp" +#include "vm/exception_point.hpp" #include "vm/global_cache.hpp" #include "vm/message.hpp" #include "vm/object_utils.hpp" @@ -38,6 +40,7 @@ using rubinius::ByteArray; using rubinius::Class; using rubinius::ClassType; using rubinius::Data; +using rubinius::Exception; using rubinius::Fixnum; using rubinius::Integer; using rubinius::Message; @@ -936,8 +939,22 @@ extern "C" { return value; } +#define RB_RAISE_BUFSIZE 256 + void rb_raise(VALUE error_handle, const char* format_string, ...) { - throw std::runtime_error(std::string("rb_raise: ") + format_string); /* Yeah, not 'exactly' correct. */ + va_list args; + char reason[RB_RAISE_BUFSIZE]; + + va_start(args, format_string); + vsnprintf(reason, RB_RAISE_BUFSIZE, format_string, args); + va_end(args); + + NativeMethodEnvironment* env = NativeMethodEnvironment::get(); + Exception* exc = Exception::make_exception( + env->state(), as<Class>(env->get_object(error_handle)), reason); + env->state()->thread_state()->raise_exception(exc); + + env->current_ep()->return_to(env); } VALUE rb_require(const char* name) {
This paste will be private.
From the Design Piracy series on my blog: