summaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authortake_cheeze <[email protected]>2014-02-25 18:47:28 +0900
committertake_cheeze <[email protected]>2014-03-01 20:05:29 +0900
commit78915f96017a12e8c3c40a4a2714543c10d0d070 (patch)
tree9db022c63ebd09aec5d1164141a0bdb85cc93d3f /src
parent5ff9c1d2861609fc98f03ec2d768e0b4f1559a09 (diff)
downloadmruby-78915f96017a12e8c3c40a4a2714543c10d0d070.tar.gz
mruby-78915f96017a12e8c3c40a4a2714543c10d0d070.zip
support c++ exception
Diffstat (limited to 'src')
-rw-r--r--src/codegen.c13
-rw-r--r--src/debug.c13
-rw-r--r--src/error.c7
-rw-r--r--src/load.c11
-rw-r--r--src/mrb_throw.h41
-rw-r--r--src/mruby_core.rake53
-rw-r--r--src/parse.y24
-rw-r--r--src/vm.c48
8 files changed, 157 insertions, 53 deletions
diff --git a/src/codegen.c b/src/codegen.c
index 29890f3b3..77bc5e34e 100644
--- a/src/codegen.c
+++ b/src/codegen.c
@@ -16,6 +16,7 @@
#include "node.h"
#include "opcode.h"
#include "re.h"
+#include "mrb_throw.h"
typedef mrb_ast_node node;
typedef struct mrb_parser_state parser_state;
@@ -38,7 +39,7 @@ struct loopinfo {
typedef struct scope {
mrb_state *mrb;
mrb_pool *mpool;
- jmp_buf jmp;
+ struct mrb_jmpbuf jmp;
struct scope *prev;
@@ -101,7 +102,7 @@ codegen_error(codegen_scope *s, const char *message)
fprintf(stderr, "codegen error: %s\n", message);
}
#endif
- longjmp(s->jmp, 1);
+ MRB_THROW(&s->jmp);
}
static void*
@@ -2487,7 +2488,7 @@ scope_finish(codegen_scope *s)
mrb_debug_info_append_file(mrb, s->irep, s->debug_start_pos, s->pc);
fname_len = strlen(s->filename);
- fname = codegen_malloc(s, fname_len + 1);
+ fname = (char*)codegen_malloc(s, fname_len + 1);
memcpy(fname, s->filename, fname_len);
fname[fname_len] = '\0';
irep->filename = fname;
@@ -2920,7 +2921,8 @@ mrb_generate_code(mrb_state *mrb, parser_state *p)
scope->parser = p;
scope->filename = p->filename;
scope->filename_index = p->current_filename_index;
- if (setjmp(scope->jmp) == 0) {
+
+ MRB_TRY(&scope->jmp) {
/* prepare irep */
codegen(scope, p->tree, NOVAL);
proc = mrb_proc_new(mrb, scope->irep);
@@ -2928,7 +2930,7 @@ mrb_generate_code(mrb_state *mrb, parser_state *p)
mrb_pool_close(scope->mpool);
return proc;
}
- else {
+ MRB_CATCH(&scope->jmp) {
if (scope->filename == scope->irep->filename) {
scope->irep->filename = NULL;
}
@@ -2936,4 +2938,5 @@ mrb_generate_code(mrb_state *mrb, parser_state *p)
mrb_pool_close(scope->mpool);
return NULL;
}
+ MRB_END_EXC(&scope->jmp);
}
diff --git a/src/debug.c b/src/debug.c
index 27c1c6f78..cdb0aa9e8 100644
--- a/src/debug.c
+++ b/src/debug.c
@@ -143,9 +143,10 @@ mrb_debug_info_append_file(mrb_state *mrb, mrb_irep *irep,
ret = (mrb_irep_debug_info_file *)mrb_malloc(mrb, sizeof(*ret));
info->files =
- (mrb_irep_debug_info_file*)info->files
- ? mrb_realloc(mrb, info->files, sizeof(mrb_irep_debug_info_file*) * (info->flen + 1))
- : mrb_malloc(mrb, sizeof(mrb_irep_debug_info_file*));
+ (mrb_irep_debug_info_file**)(
+ info->files
+ ? mrb_realloc(mrb, info->files, sizeof(mrb_irep_debug_info_file*) * (info->flen + 1))
+ : mrb_malloc(mrb, sizeof(mrb_irep_debug_info_file*)));
info->files[info->flen++] = ret;
file_pc_count = end_pos - start_pos;
@@ -164,7 +165,7 @@ mrb_debug_info_append_file(mrb_state *mrb, mrb_irep *irep,
switch(ret->line_type) {
case mrb_debug_line_ary:
ret->line_entry_count = file_pc_count;
- ret->line_ary = mrb_malloc(mrb, sizeof(uint16_t) * file_pc_count);
+ ret->line_ary = (uint16_t*)mrb_malloc(mrb, sizeof(uint16_t) * file_pc_count);
for(i = 0; i < file_pc_count; ++i) {
ret->line_ary[i] = irep->lines[start_pos + i];
}
@@ -173,12 +174,12 @@ mrb_debug_info_append_file(mrb_state *mrb, mrb_irep *irep,
case mrb_debug_line_flat_map: {
uint16_t prev_line = 0;
mrb_irep_debug_info_line m;
- ret->line_flat_map = mrb_malloc(mrb, sizeof(mrb_irep_debug_info_line) * 1);
+ ret->line_flat_map = (mrb_irep_debug_info_line*)mrb_malloc(mrb, sizeof(mrb_irep_debug_info_line) * 1);
ret->line_entry_count = 0;
for(i = 0; i < file_pc_count; ++i) {
if(irep->lines[start_pos + i] == prev_line) { continue; }
- ret->line_flat_map = mrb_realloc(
+ ret->line_flat_map = (mrb_irep_debug_info_line*)mrb_realloc(
mrb, ret->line_flat_map,
sizeof(mrb_irep_debug_info_line) * (ret->line_entry_count + 1));
m.start_pos = start_pos + i;
diff --git a/src/error.c b/src/error.c
index db516d766..f7e5995e6 100644
--- a/src/error.c
+++ b/src/error.c
@@ -15,6 +15,7 @@
#include "mruby/variable.h"
#include "mruby/debug.h"
#include "mruby/error.h"
+#include "mrb_throw.h"
mrb_value
mrb_exc_new(mrb_state *mrb, struct RClass *c, const char *ptr, long len)
@@ -221,7 +222,7 @@ mrb_exc_raise(mrb_state *mrb, mrb_value exc)
mrb_p(mrb, exc);
abort();
}
- mrb_longjmp(mrb);
+ MRB_THROW(mrb->jmp);
}
void
@@ -431,6 +432,10 @@ mrb_sys_fail(mrb_state *mrb, const char *mesg)
}
}
+#ifdef MRB_ENABLE_CXX_EXCEPTION
+mrb_int mrb_jmpbuf::jmpbuf_id = 0;
+#endif
+
void
mrb_init_exception(mrb_state *mrb)
{
diff --git a/src/load.c b/src/load.c
index e4b2c9987..857dd7740 100644
--- a/src/load.c
+++ b/src/load.c
@@ -305,7 +305,7 @@ read_debug_record(mrb_state *mrb, const uint8_t *start, mrb_irep* irep, uint32_t
file->filename = mrb_sym2name_len(mrb, file->filename_sym, &len);
file->line_entry_count = bin_to_uint32(bin); bin += sizeof(uint32_t);
- file->line_type = bin_to_uint8(bin); bin += sizeof(uint8_t);
+ file->line_type = (mrb_debug_line_type)bin_to_uint8(bin); bin += sizeof(uint8_t);
switch(file->line_type) {
case mrb_debug_line_ary: {
size_t l;
@@ -319,7 +319,8 @@ read_debug_record(mrb_state *mrb, const uint8_t *start, mrb_irep* irep, uint32_t
case mrb_debug_line_flat_map: {
size_t l;
- file->line_flat_map = mrb_malloc(mrb, sizeof(mrb_irep_debug_info_line) * file->line_entry_count);
+ file->line_flat_map = (mrb_irep_debug_info_line*)mrb_malloc(
+ mrb, sizeof(mrb_irep_debug_info_line) * file->line_entry_count);
for(l = 0; l < file->line_entry_count; ++l) {
file->line_flat_map[l].start_pos = bin_to_uint32(bin); bin += sizeof(uint32_t);
file->line_flat_map[l].line = bin_to_uint16(bin); bin += sizeof(uint16_t);
@@ -613,7 +614,7 @@ mrb_read_irep_file(mrb_state *mrb, FILE* fp)
}
/* You don't need use SIZE_ERROR as buf_size is enough small. */
- buf = mrb_malloc(mrb, buf_size);
+ buf = (uint8_t*)mrb_malloc(mrb, buf_size);
if (!buf) {
return NULL;
}
@@ -631,7 +632,7 @@ mrb_read_irep_file(mrb_state *mrb, FILE* fp)
fpos = ftell(fp);
/* You don't need use SIZE_ERROR as block_size is enough small. */
for (i = 0; i < block_fallback_count; i++,block_size >>= 1){
- buf = mrb_malloc_simple(mrb, block_size);
+ buf = (uint8_t*)mrb_malloc_simple(mrb, block_size);
if (buf) break;
}
if (!buf) {
@@ -672,7 +673,7 @@ mrb_read_irep_file(mrb_state *mrb, FILE* fp)
else if (memcmp(section_header.section_identify, RITE_SECTION_DEBUG_IDENTIFIER, sizeof(section_header.section_identify)) == 0) {
if (!irep) return NULL; /* corrupted data */
else {
- uint8_t* const bin = mrb_malloc(mrb, section_size);
+ uint8_t* const bin = (uint8_t*)mrb_malloc(mrb, section_size);
fseek(fp, fpos, SEEK_SET);
if(fread((char*)bin, section_size, 1, fp) != 1) {
diff --git a/src/mrb_throw.h b/src/mrb_throw.h
new file mode 100644
index 000000000..b0c455e25
--- /dev/null
+++ b/src/mrb_throw.h
@@ -0,0 +1,41 @@
+/*
+** mrb_throw.h - mruby exception throwing handler
+**
+** See Copyright Notice in mruby.h
+*/
+
+#ifndef MRB_THROW_H
+#define MRB_THROW_H
+
+#ifdef MRB_ENABLE_CXX_EXCEPTION
+
+#define MRB_TRY(buf) try {
+#define MRB_CATCH(buf) } catch(mrb_jmpbuf_impl e) { if (e != (buf)->impl) { throw e; }
+#define MRB_END_EXC(buf) }
+
+#define MRB_THROW(buf) throw((buf)->impl)
+typedef mrb_int mrb_jmpbuf_impl;
+
+#else
+
+#include <setjmp.h>
+
+#define MRB_TRY(buf) do { if (setjmp((buf)->impl) == 0) {
+#define MRB_CATCH(buf) } else {
+#define MRB_END_EXC(buf) } } while(0)
+
+#define MRB_THROW(buf) longjmp((buf)->impl, 1);
+#define mrb_jmpbuf_impl jmp_buf
+
+#endif
+
+struct mrb_jmpbuf {
+ mrb_jmpbuf_impl impl;
+
+#ifdef MRB_ENABLE_CXX_EXCEPTION
+ static mrb_int jmpbuf_id;
+ mrb_jmpbuf() : impl(jmpbuf_id++) {}
+#endif
+};
+
+#endif
diff --git a/src/mruby_core.rake b/src/mruby_core.rake
index db335223d..28ce74e64 100644
--- a/src/mruby_core.rake
+++ b/src/mruby_core.rake
@@ -4,8 +4,53 @@ MRuby.each_target do
current_build_dir = "#{build_dir}/#{relative_from_root}"
lex_def = "#{current_dir}/lex.def"
- objs = Dir.glob("#{current_dir}/*.c").map { |f| objfile(f.pathmap("#{current_build_dir}/%n")) }
- objs += [objfile("#{current_build_dir}/y.tab")]
+ objs = Dir.glob("#{current_dir}/*.c").map { |f|
+ next nil if cxx_abi_enabled? and f =~ /(codegen|error|vm).c$/
+ objfile(f.pathmap("#{current_build_dir}/%n"))
+ }.compact
+
+ if cxx_abi_enabled?
+ cxx_abi_dependency = %w(codegen error vm)
+ cxx_abi_objs = cxx_abi_dependency.map { |v|
+ src = "#{current_build_dir}/#{v}.cxx"
+ file src => "#{current_dir}/#{v}.c" do |t|
+ File.open(t.name, 'w') do |f|
+ f.write <<EOS
+extern "C" {
+#include "#{MRUBY_ROOT}/#{t.prerequisites.first}"
+}
+EOS
+ end
+ end
+
+ file objfile(src) => src do |t|
+ cxx.run t.name, t.prerequisites.first, [], [current_dir]
+ end
+
+ objfile src
+ }
+ cxx_abi_objs << objfile("#{current_build_dir}/y.tab")
+
+ file "#{current_build_dir}/y.tab.cxx" => "#{current_build_dir}/y.tab.c" do |t|
+ File.open(t.name, 'w') do |f|
+ f.write <<EOS
+extern "C" {
+#include "#{t.prerequisites.first}"
+}
+EOS
+ end
+ end
+ file objfile("#{current_build_dir}/y.tab") => ["#{current_build_dir}/y.tab.cxx", lex_def] do |t|
+ cxx.run t.name, t.prerequisites.first, [], [current_dir]
+ end
+
+ objs += cxx_abi_objs
+ else
+ objs += [objfile("#{current_build_dir}/y.tab")]
+ file objfile("#{current_build_dir}/y.tab") => ["#{current_build_dir}/y.tab.c", lex_def] do |t|
+ cc.run t.name, t.prerequisites.first, [], [current_dir]
+ end
+ end
self.libmruby << objs
file libfile("#{build_dir}/lib/libmruby_core") => objs do |t|
@@ -17,10 +62,6 @@ MRuby.each_target do
yacc.run t.name, t.prerequisites.first
end
- file objfile("#{current_build_dir}/y.tab") => ["#{current_build_dir}/y.tab.c", lex_def] do |t|
- cc.run t.name, t.prerequisites.first, [], [current_dir]
- end
-
# Lexical analyzer
file lex_def => "#{current_dir}/keywords" do |t|
gperf.run t.name, t.prerequisites.first
diff --git a/src/parse.y b/src/parse.y
index 43dfc57fc..53b271496 100644
--- a/src/parse.y
+++ b/src/parse.y
@@ -25,6 +25,7 @@
#include "mruby/compile.h"
#include "mruby/proc.h"
#include "node.h"
+#include "mrb_throw.h"
#define YYLEX_PARAM p
@@ -103,7 +104,7 @@ parser_palloc(parser_state *p, size_t size)
void *m = mrb_pool_alloc(p->pool, size);
if (!m) {
- longjmp(p->jmp, 1);
+ MRB_THROW(p->jmp);
}
return m;
}
@@ -5189,12 +5190,10 @@ void mrb_parser_dump(mrb_state *mrb, node *tree, int offset);
void
mrb_parser_parse(parser_state *p, mrbc_context *c)
{
- if (setjmp(p->jmp) != 0) {
- yyerror(p, "memory allocation error");
- p->nerr++;
- p->tree = 0;
- return;
- }
+ struct mrb_jmpbuf buf;
+ p->jmp = &buf;
+
+ MRB_TRY(p->jmp) {
p->cmd_start = TRUE;
p->in_def = p->in_single = 0;
@@ -5210,6 +5209,15 @@ mrb_parser_parse(parser_state *p, mrbc_context *c)
if (c && c->dump_result) {
mrb_parser_dump(p->mrb, p->tree, 0);
}
+
+ }
+ MRB_CATCH(p->jmp) {
+ yyerror(p, "memory allocation error");
+ p->nerr++;
+ p->tree = 0;
+ return;
+ }
+ MRB_END_EXC(p->jmp);
}
parser_state*
@@ -5316,7 +5324,7 @@ mrb_parser_set_filename(struct mrb_parser_state *p, const char *f)
p->current_filename_index = p->filename_table_length++;
- new_table = parser_palloc(p, sizeof(mrb_sym) * p->filename_table_length);
+ new_table = (mrb_sym*)parser_palloc(p, sizeof(mrb_sym) * p->filename_table_length);
if (p->filename_table) {
memcpy(new_table, p->filename_table, sizeof(mrb_sym) * p->filename_table_length);
}
diff --git a/src/vm.c b/src/vm.c
index 62ac86c90..7aec31909 100644
--- a/src/vm.c
+++ b/src/vm.c
@@ -4,7 +4,6 @@
** See Copyright Notice in mruby.h
*/
-#include <setjmp.h>
#include <stddef.h>
#include <stdarg.h>
#include <math.h>
@@ -20,6 +19,7 @@
#include "mruby/error.h"
#include "opcode.h"
#include "value_array.h"
+#include "mrb_throw.h"
#ifndef ENABLE_STDIO
#if defined(__cplusplus)
@@ -328,10 +328,16 @@ mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, int argc, mr
mrb_value val;
if (!mrb->jmp) {
- jmp_buf c_jmp;
+ struct mrb_jmpbuf c_jmp;
mrb_callinfo *old_ci = mrb->c->ci;
- if (setjmp(c_jmp) != 0) { /* error */
+ MRB_TRY(&c_jmp) {
+ mrb->jmp = &c_jmp;
+ /* recursive call */
+ val = mrb_funcall_with_block(mrb, self, mid, argc, argv, blk);
+ mrb->jmp = 0;
+ }
+ MRB_CATCH(&c_jmp) { /* error */
while (old_ci != mrb->c->ci) {
mrb->c->stack = mrb->c->ci->stackent;
cipop(mrb);
@@ -339,12 +345,7 @@ mrb_funcall_with_block(mrb_state *mrb, mrb_value self, mrb_sym mid, int argc, mr
mrb->jmp = 0;
val = mrb_obj_value(mrb->exc);
}
- else {
- mrb->jmp = &c_jmp;
- /* recursive call */
- val = mrb_funcall_with_block(mrb, self, mid, argc, argv, blk);
- mrb->jmp = 0;
- }
+ MRB_END_EXC(&c_jmp);
}
else {
struct RProc *p;
@@ -629,8 +630,8 @@ mrb_context_run(mrb_state *mrb, struct RProc *proc, mrb_value self, unsigned int
mrb_value *regs = NULL;
mrb_code i;
int ai = mrb_gc_arena_save(mrb);
- jmp_buf *prev_jmp = (jmp_buf *)mrb->jmp;
- jmp_buf c_jmp;
+ struct mrb_jmpbuf *prev_jmp = mrb->jmp;
+ struct mrb_jmpbuf c_jmp;
#ifdef DIRECT_THREADED
static void *optable[] = {
@@ -657,13 +658,15 @@ mrb_context_run(mrb_state *mrb, struct RProc *proc, mrb_value self, unsigned int
};
#endif
+ mrb_bool exc_catched = FALSE;
+RETRY_TRY_BLOCK:
- if (setjmp(c_jmp) == 0) {
- mrb->jmp = &c_jmp;
- }
- else {
+ MRB_TRY(&c_jmp) {
+
+ if (exc_catched) {
goto L_RAISE;
}
+ mrb->jmp = &c_jmp;
if (!mrb->c->stack) {
stack_init(mrb);
}
@@ -1353,7 +1356,7 @@ mrb_context_run(mrb_state *mrb, struct RProc *proc, mrb_value self, unsigned int
mrb->c->stack = ci[1].stackent;
if (ci[1].acc == CI_ACC_SKIP && prev_jmp) {
mrb->jmp = prev_jmp;
- mrb_longjmp(mrb);
+ MRB_THROW(prev_jmp);
}
if (ci > mrb->c->cibase) {
while (eidx > ci[-1].eidx) {
@@ -2247,6 +2250,13 @@ mrb_context_run(mrb_state *mrb, struct RProc *proc, mrb_value self, unsigned int
}
}
END_DISPATCH;
+
+ }
+ MRB_CATCH(&c_jmp) {
+ exc_catched = TRUE;
+ goto RETRY_TRY_BLOCK;
+ }
+ MRB_END_EXC(&c_jmp);
}
mrb_value
@@ -2254,9 +2264,3 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
{
return mrb_context_run(mrb, proc, self, mrb->c->ci->argc + 2); /* argc + 2 (receiver and block) */
}
-
-void
-mrb_longjmp(mrb_state *mrb)
-{
- longjmp(*(jmp_buf*)mrb->jmp, 1);
-}