diff options
| author | take_cheeze <[email protected]> | 2014-02-25 18:47:28 +0900 |
|---|---|---|
| committer | take_cheeze <[email protected]> | 2014-03-01 20:05:29 +0900 |
| commit | 78915f96017a12e8c3c40a4a2714543c10d0d070 (patch) | |
| tree | 9db022c63ebd09aec5d1164141a0bdb85cc93d3f /src | |
| parent | 5ff9c1d2861609fc98f03ec2d768e0b4f1559a09 (diff) | |
| download | mruby-78915f96017a12e8c3c40a4a2714543c10d0d070.tar.gz mruby-78915f96017a12e8c3c40a4a2714543c10d0d070.zip | |
support c++ exception
Diffstat (limited to 'src')
| -rw-r--r-- | src/codegen.c | 13 | ||||
| -rw-r--r-- | src/debug.c | 13 | ||||
| -rw-r--r-- | src/error.c | 7 | ||||
| -rw-r--r-- | src/load.c | 11 | ||||
| -rw-r--r-- | src/mrb_throw.h | 41 | ||||
| -rw-r--r-- | src/mruby_core.rake | 53 | ||||
| -rw-r--r-- | src/parse.y | 24 | ||||
| -rw-r--r-- | src/vm.c | 48 |
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); } @@ -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); -} |
