[macruby-changes] [3372] MacRuby/trunk
source_changes at macosforge.org
source_changes at macosforge.org
Fri Jan 29 17:31:56 PST 2010
Revision: 3372
http://trac.macosforge.org/projects/ruby/changeset/3372
Author: lsansonetti at apple.com
Date: 2010-01-29 17:31:55 -0800 (Fri, 29 Jan 2010)
Log Message:
-----------
now properly popping exceptions from the VM stack when we unwind from a handler, added blocks symbolication
Modified Paths:
--------------
MacRuby/trunk/compiler.cpp
MacRuby/trunk/compiler.h
MacRuby/trunk/vm.cpp
MacRuby/trunk/vm.h
Modified: MacRuby/trunk/compiler.cpp
===================================================================
--- MacRuby/trunk/compiler.cpp 2010-01-30 01:26:55 UTC (rev 3371)
+++ MacRuby/trunk/compiler.cpp 2010-01-30 01:31:55 UTC (rev 3372)
@@ -1951,15 +1951,17 @@
}
void
-RoxorCompiler::compile_pop_exception(void)
+RoxorCompiler::compile_pop_exception(int pos)
{
if (popExceptionFunc == NULL) {
- // void rb_vm_pop_exception(void);
+ // void rb_vm_pop_exception(int pos);
popExceptionFunc = cast<Function>(
module->getOrInsertFunction("rb_vm_pop_exception",
- VoidTy, NULL));
+ VoidTy, Int32Ty, NULL));
}
- CallInst::Create(popExceptionFunc, "", bb);
+ std::vector<Value *> params;
+ params.push_back(ConstantInt::get(Int32Ty, pos));
+ CallInst::Create(popExceptionFunc, params.begin(), params.end(), "", bb);
}
void
@@ -4886,13 +4888,28 @@
bb = handler_bb;
assert(n->nd_body != NULL);
+
+ // Compile the rescue handler within another exception
+ // handler.
+ BasicBlock *old_rescue_invoke_bb = rescue_invoke_bb;
+ BasicBlock *new_rescue_invoke_bb =
+ BasicBlock::Create(context, "rescue", f);
+ rescue_invoke_bb = new_rescue_invoke_bb;
+
Value *header_val = compile_node(n->nd_body);
handler_bb = bb;
BranchInst::Create(merge_bb, bb);
-
handlers.push_back(std::pair<Value *, BasicBlock *>
(header_val, handler_bb));
+ // If the handler raised an exception, pop the previous
+ // one from the VM stack and rethrow.
+ bb = new_rescue_invoke_bb;
+ compile_landing_pad_header();
+ compile_pop_exception(1);
+ compile_rethrow_exception();
+ rescue_invoke_bb = old_rescue_invoke_bb;
+
bb = handler_bb = next_handler_bb;
n = n->nd_head;
@@ -5050,7 +5067,8 @@
current_loop_begin_bb = loopBB;
current_loop_body_bb = bodyBB;
current_loop_end_bb = afterBB;
- current_loop_exit_val = PHINode::Create(RubyObjTy, "loop_exit", afterBB);
+ current_loop_exit_val = PHINode::Create(RubyObjTy,
+ "loop_exit", afterBB);
current_loop_exit_val->addIncoming(nilVal, exitBB);
bb = bodyBB;
Modified: MacRuby/trunk/compiler.h
===================================================================
--- MacRuby/trunk/compiler.h 2010-01-30 01:26:55 UTC (rev 3371)
+++ MacRuby/trunk/compiler.h 2010-01-30 01:31:55 UTC (rev 3372)
@@ -321,7 +321,7 @@
void compile_landing_pad_footer(bool pop_exception=true);
Value *compile_current_exception(void);
void compile_rethrow_exception(void);
- void compile_pop_exception(void);
+ void compile_pop_exception(int pos=0);
Value *compile_lvar_slot(ID name);
bool compile_lvars(ID *tbl);
Value *compile_new_struct(Value *klass, std::vector<Value *> &fields);
Modified: MacRuby/trunk/vm.cpp
===================================================================
--- MacRuby/trunk/vm.cpp 2010-01-30 01:26:55 UTC (rev 3371)
+++ MacRuby/trunk/vm.cpp 2010-01-30 01:31:55 UTC (rev 3372)
@@ -271,6 +271,7 @@
extern "C" void *__cxa_allocate_exception(size_t);
extern "C" void __cxa_throw(void *, void *, void (*)(void *));
extern "C" void __cxa_rethrow(void);
+extern "C" std::type_info *__cxa_current_exception_type(void);
RoxorCore::RoxorCore(void)
{
@@ -553,6 +554,25 @@
#endif
}
+// Dummy function to be used for debugging (in gdb).
+extern "C"
+void
+rb_symbolicate(void *addr)
+{
+ void *start = NULL;
+ char path[1000];
+ char name[100];
+ unsigned long ln = 0;
+ if (GET_CORE()->symbolize_call_address(addr, &start, path, sizeof path,
+ &ln, name, sizeof name)) {
+ printf("addr %p start %p selector %s location %s:%ld\n",
+ addr, start, name, path, ln);
+ }
+ else {
+ printf("addr %p unknown\n", addr);
+ }
+}
+
bool
RoxorCore::symbolize_call_address(void *addr, void **startp, char *path,
size_t path_len, unsigned long *ln, char *name, size_t name_len)
@@ -577,37 +597,40 @@
*startp = start;
}
- if (name != NULL || path != NULL || ln != NULL) {
- std::map<IMP, rb_vm_method_node_t *>::iterator iter =
- ruby_imps.find((IMP)start);
- if (iter == ruby_imps.end()) {
- // TODO symbolize objc selectors
- return false;
- }
-
- rb_vm_method_node_t *node = iter->second;
+ if (f != NULL) {
if (ln != NULL) {
*ln = 0;
- if (f != NULL) {
- for (std::vector<RoxorFunction::Line>::iterator iter =
- f->lines.begin(); iter != f->lines.end(); ++iter) {
- *ln = (*iter).line;
- if ((*iter).address <= (uintptr_t)addr) {
- break;
- }
+ for (std::vector<RoxorFunction::Line>::iterator iter =
+ f->lines.begin(); iter != f->lines.end(); ++iter) {
+ *ln = (*iter).line;
+ if ((*iter).address <= (uintptr_t)addr) {
+ break;
}
}
}
if (path != NULL) {
- if (f != NULL && f->path.size() > 0) {
- strncpy(path, f->path.c_str(), path_len);
+ strncpy(path, f->path.c_str(), path_len);
+ }
+ if (name != NULL) {
+ std::map<IMP, rb_vm_method_node_t *>::iterator iter =
+ ruby_imps.find((IMP)start);
+ if (iter == ruby_imps.end()) {
+ strncpy(name, "block", name_len);
}
else {
- strncpy(path, "core", path_len);
+ strncpy(name, sel_getName(iter->second->sel), name_len);
}
}
+ }
+ else {
+ if (ln != NULL) {
+ *ln = 0;
+ }
+ if (path != NULL) {
+ strncpy(path, "core", path_len);
+ }
if (name != NULL) {
- strncpy(name, sel_getName(node->sel), name_len);
+ name[0] = '\0';
}
}
@@ -3426,6 +3449,61 @@
#endif
}
+void
+RoxorVM::push_current_exception(VALUE exc)
+{
+ assert(!NIL_P(exc));
+ rb_objc_retain((void *)exc);
+ current_exceptions.push_back(exc);
+//printf("PUSH %p %s\n", (void *)exc, RSTRING_PTR(rb_inspect(exc)));
+}
+
+class RoxorThreadRaiseException {
+};
+
+static inline bool
+current_exception_is_return_from_block(void)
+{
+ const std::type_info *exc_type = __cxa_current_exception_type();
+ return exc_type != NULL
+ && *exc_type == typeid(RoxorReturnFromBlockException *);
+}
+
+static inline bool
+current_exception_is_catch_throw(void)
+{
+ const std::type_info *exc_type = __cxa_current_exception_type();
+ return exc_type != NULL
+ && *exc_type == typeid(RoxorCatchThrowException *);
+}
+
+static inline bool
+current_exception_is_thread_raise(void)
+{
+ const std::type_info *exc_type = __cxa_current_exception_type();
+ return exc_type != NULL
+ && *exc_type == typeid(RoxorThreadRaiseException *);
+}
+
+void
+RoxorVM::pop_current_exception(int pos)
+{
+ if (current_exception_is_return_from_block()
+ || current_exception_is_catch_throw()
+ || current_exception_is_thread_raise()) {
+ return;
+ }
+
+ assert((size_t)pos < current_exceptions.size());
+
+ std::vector<VALUE>::iterator iter = current_exceptions.end() - (pos + 1);
+ VALUE exc = *iter;
+ current_exceptions.erase(iter);
+
+ rb_objc_release((void *)exc);
+//printf("POP (%d) %p %s\n", pos, (void *)exc, RSTRING_PTR(rb_inspect(exc)));
+}
+
#if !__LP64__
extern "C"
void
@@ -3465,13 +3543,14 @@
extern "C"
VALUE
rb_rescue2(VALUE (*b_proc) (ANYARGS), VALUE data1,
- VALUE (*r_proc) (ANYARGS), VALUE data2, ...)
+ VALUE (*r_proc) (ANYARGS), VALUE data2, ...)
{
try {
return (*b_proc)(data1);
}
catch (...) {
- VALUE exc = rb_vm_current_exception();
+ RoxorVM *vm = GET_VM();
+ VALUE exc = vm->current_exception();
if (exc != Qnil) {
va_list ar;
VALUE eclass;
@@ -3487,8 +3566,9 @@
va_end(ar);
if (handled) {
+ vm->pop_current_exception();
if (r_proc != NULL) {
- return (*r_proc)(data2);
+ return (*r_proc)(data2, exc);
}
return Qnil;
}
@@ -3604,16 +3684,6 @@
return vm->pop_broken_with();
}
-extern "C" std::type_info *__cxa_current_exception_type(void);
-
-static inline bool
-current_exception_is_return_from_block(void)
-{
- const std::type_info *exc_type = __cxa_current_exception_type();
- return exc_type != NULL
- && *exc_type == typeid(RoxorReturnFromBlockException *);
-}
-
extern "C"
VALUE
rb_vm_check_return_from_block_exc(RoxorReturnFromBlockException **pexc, int id)
@@ -3652,8 +3722,11 @@
char name[100];
unsigned long ln = 0;
+ path[0] = name[0] = '\0';
+
if (GET_CORE()->symbolize_call_address(callstack[i], NULL,
- path, sizeof path, &ln, name, sizeof name)) {
+ path, sizeof path, &ln, name, sizeof name)
+ && name[0] != '\0') {
char entry[PATH_MAX];
if (ln == 0) {
snprintf(entry, sizeof entry, "%s:in `%s'",
@@ -3709,7 +3782,7 @@
extern "C"
void
-rb_vm_pop_exception(void)
+rb_vm_pop_exception(int pos)
{
GET_VM()->pop_current_exception();
}
@@ -4435,7 +4508,7 @@
// Killing a thread is implemented using a non-catchable (from Ruby)
// exception, which allows us to call the ensure blocks before dying,
// which is unfortunately covered in the Ruby specifications.
- rb_vm_rethrow();
+ throw new RoxorThreadRaiseException();
}
static void
Modified: MacRuby/trunk/vm.h
===================================================================
--- MacRuby/trunk/vm.h 2010-01-30 01:26:55 UTC (rev 3371)
+++ MacRuby/trunk/vm.h 2010-01-30 01:31:55 UTC (rev 3372)
@@ -847,13 +847,20 @@
METHOD_MISSING_SUPER
} rb_vm_method_missing_reason_t;
-// Custome C++ exception for catch/throw blocks
+// Custom C++ exception class for catch/throw blocks.
class RoxorCatchThrowException {
- public:
- VALUE throw_symbol;
- VALUE throw_value;
+ public:
+ VALUE throw_symbol;
+ VALUE throw_value;
};
+// Custom C++ exception class used to implement "return-from-block".
+class RoxorReturnFromBlockException {
+ public:
+ VALUE val;
+ int id;
+};
+
// The VM class is instantiated per thread. There is always at least one
// instance. The VM class is purely thread-safe and concurrent, it does not
// acquire any lock, except when it calls the Core.
@@ -1011,20 +1018,9 @@
? Qnil : current_exceptions.back();
}
- void push_current_exception(VALUE exc) {
- assert(!NIL_P(exc));
- rb_objc_retain((void *)exc);
- current_exceptions.push_back(exc);
- }
+ void push_current_exception(VALUE exc);
+ void pop_current_exception(int pos=0);
- VALUE pop_current_exception(void) {
- assert(!current_exceptions.empty());
- VALUE exc = current_exceptions.back();
- rb_objc_release((void *)exc);
- current_exceptions.pop_back();
- return exc;
- }
-
VALUE *get_binding_lvar(ID name, bool create);
VALUE ruby_catch(VALUE tag);
@@ -1048,13 +1044,6 @@
#define GET_VM() (RoxorVM::current())
#define GET_THREAD() (GetThreadPtr(GET_VM()->get_thread()))
-// Custom C++ exception class used to implement "return-from-block".
-class RoxorReturnFromBlockException {
- public:
- VALUE val;
- int id;
-};
-
#endif /* __cplusplus */
#endif /* __VM_H_ */
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20100129/2b2e6885/attachment-0001.html>
More information about the macruby-changes
mailing list