Generate C struct from `irep` instead of binary dump.

parent 7deb41b0
......@@ -106,11 +106,17 @@ end
mkdir_p "#{MRUBY_ROOT}/build"
cfiles = (Dir.glob("#{MRUBY_ROOT}/src/*.c")+
Dir.glob("#{MRUBY_ROOT}/mrbgems/*/{core,src}/*.c")+
Dir.glob("#{MRUBY_ROOT}/build/*/mrbgems/**/{src,core}/*.c")).uniq
rbfiles = (Dir.glob("#{MRUBY_ROOT}/mrblib/*.rb")+
Dir.glob("#{MRUBY_ROOT}/mrbgems/*/mrblib/*.rb")+
Dir.glob("#{MRUBY_ROOT}/build/*/mrbgems/**/mrblib/*.rb")).uniq
Dir.glob("#{MRUBY_ROOT}/mrbgems/**/*.c")+
Dir.glob("#{MRUBY_ROOT}/build/*/mrbgems/**/{src,test,core}/*.c")).uniq
rbfiles = (Dir.glob("#{MRUBY_ROOT}/{mrblib,test,test/t}/*.rb")+
Dir.glob("#{MRUBY_ROOT}/mrbgems/*/{mrblib,test}/*.rb")+
Dir.glob("#{MRUBY_ROOT}/build/*/mrbgems/**/{mrblib,test}/*.rb")).uniq
psfiles = Dir.glob("#{MRUBY_ROOT}/{mrblib,mrbgems,test}/**/presym")
symbols = []
psfiles.each do |file|
symbols += File.readlines(file).grep_v(/^# /)
end
symbols.each{|x| x.chomp!}
presym_file="#{MRUBY_ROOT}/build/presym"
op_table = {
"!" => "not",
......@@ -145,30 +151,42 @@ op_table = {
"~" => "neg",
}
file presym_file => cfiles+rbfiles+[__FILE__] do
file presym_file => cfiles+rbfiles+psfiles+[__FILE__] do
csymbols = cfiles.map do |f|
src = File.read(f)
[src.scan(/intern_lit\([^\n"]*"([^\n "]*)"/),
src.scan(/mrb_define_method\([^\n"]*"([^\n"]*)"/),
src.scan(/mrb_define_class_method\([^\n"]*"([^\n"]*)"/),
src.scan(/mrb_define_class\([^\n"]*"([^\n"]*)"/),
src.scan(/mrb_define_module\([^\n"]*"([^\n"]*)"/),
src.scan(/mrb_define_module_function\([^\n"]*"([^\n"]*)"/),
src.scan(/mrb_define_const\([^\n"]*"([^\n"]*)"/),
src.scan(/mrb_define_global_const\([^\n"]*"([^\n"]*)"/),
src.scan(/MRB_SYM\((\w+)\)/),
src.scan(/MRB_QSYM\((\w+)\)/).map{|x,|
x.sub!(/_p$/, "?") || x.sub!(/_b$/, "!") || x.sub!(/_e$/, "=") || x.sub!(/^a_/, "@") || x.sub!(/^d_/, "$")
x.sub!(/_p$/, "?") || x.sub!(/_b$/, "!") || x.sub!(/_e$/, "=") || x.sub!(/^0_/, "@") || x.sub!(/^00_/, "@@")
}.compact]
end
rbsymbols = rbfiles.map do |f|
src = File.read(f)
src.force_encoding(Encoding::BINARY)
[src.scan(/\bclass +([A-Z]\w*)/),
src.scan(/\bmodule +([A-Z]\w*)/),
src.scan(/\bdef +(\w+[!?]?)/),
src.scan(/\bdef +(\w+[!?=]?)/),
src.scan(/\balias +(\w+[!?]?)/),
src.scan(/\b([A-Z]\w+) *=/),
src.scan(/(@\w+)/),
src.scan(/:(\w+)/)]
src.scan(/\b([A-Z]\w*) *=[^=]/),
src.scan(/(\$[a-zA-Z_]\w*)/),
src.scan(/(\$[$!?]\w*)/),
src.scan(/(@@?[a-zA-Z_]\w*)/),
src.scan(/[^.]\.([a-zA-Z_]\w*[!?]?)/),
src.scan(/\.([a-zA-Z_]\w* *=)/).map{|x|x.map{|s|s.gsub(' ', '')}},
src.scan(/\b([a-zA-Z_]\w*):/),
src.scan(/:([a-zA-Z_]\w*[!?=]?)/),
src.scan(/[\(\[\{ ]:"([^"]+)"/).map{|x|x.map{|s|s.gsub('\#', '#')}},
src.scan(/[ \(\[\{]:'([^']+)'/)
]
end
symbols = (csymbols+rbsymbols+op_table.keys).flatten.compact.uniq.sort
symbols = (symbols+csymbols+rbsymbols+op_table.keys).flatten.compact.uniq.sort.map{|x| x.gsub("\n", '\n')}
presyms = File.readlines(presym_file) rescue []
presyms.each{|x| x.chomp!}
if presyms != symbols
......@@ -182,10 +200,12 @@ file presym_inc => presym_file do
presyms.each{|x| x.chomp!}
File.open(presym_inc, "w") do |f|
f.print "/* MRB_PRESYM_CSYM(sym, num) - symbol which is valid C id name */\n"
f.print "/* MRB_PRESYM_QSYM(sym, name, num) - symbol with alias name */\n"
f.print "/* MRB_PRESYM_SYM(sym, num) - symbol which is not valid C id */\n\n"
f.print "/* MRB_PRESYM_QSYM(name, sym, num) - symbol with alias name */\n"
f.print "/* MRB_PRESYM_SYM(name, num) - symbol which is not valid C id */\n"
presyms.each.with_index do |sym,i|
if /\A\w+\Z/ =~ sym
if sym.bytes.detect{|x|x>0x80} || /\A\$/ =~ sym
f.print "MRB_PRESYM_SYM(\"#{sym}\", #{i+1})\n"
elsif /\A\w+\Z/ =~ sym
f.print "MRB_PRESYM_CSYM(#{sym}, #{i+1})\n"
elsif op_table.key?(sym)
f.print "MRB_PRESYM_QSYM(\"#{sym}\", #{op_table[sym]}, #{i+1})\n"
......@@ -198,11 +218,11 @@ file presym_inc => presym_file do
elsif /\=\Z/ =~ sym
s = sym.dup; s[-1] = "_e"
f.print "MRB_PRESYM_QSYM(\"#{sym}\", #{s}, #{i+1})\n"
elsif /\A@/ =~ sym
s = sym.dup; s[0] = "a_"
elsif /\A@@/ =~ sym
s = sym.dup; s[0,2] = "00_"
f.print "MRB_PRESYM_QSYM(\"#{sym}\", #{s}, #{i+1})\n"
elsif /\A$/ =~ sym
s = sym.dup; s[0] = "d_"
elsif /\A@/ =~ sym
s = sym.dup; s[0] = "0_"
f.print "MRB_PRESYM_QSYM(\"#{sym}\", #{s}, #{i+1})\n"
else
f.print "MRB_PRESYM_SYM(\"#{sym}\", #{i+1})\n"
......
......@@ -147,7 +147,7 @@ typedef void* (*mrb_allocf) (struct mrb_state *mrb, void*, size_t, void *ud);
typedef struct {
mrb_sym mid;
struct RProc *proc;
const struct RProc *proc;
mrb_value *stackent;
uint16_t ridx;
uint16_t epos;
......@@ -1202,9 +1202,9 @@ MRB_API void mrb_close(mrb_state *mrb);
MRB_API void* mrb_default_allocf(mrb_state*, void*, size_t, void*);
MRB_API mrb_value mrb_top_self(mrb_state *mrb);
MRB_API mrb_value mrb_top_run(mrb_state *mrb, struct RProc *proc, mrb_value self, unsigned int stack_keep);
MRB_API mrb_value mrb_vm_run(mrb_state *mrb, struct RProc *proc, mrb_value self, unsigned int stack_keep);
MRB_API mrb_value mrb_vm_exec(mrb_state *mrb, struct RProc *proc, const mrb_code *iseq);
MRB_API mrb_value mrb_top_run(mrb_state *mrb, const struct RProc *proc, mrb_value self, unsigned int stack_keep);
MRB_API mrb_value mrb_vm_run(mrb_state *mrb, const struct RProc *proc, mrb_value self, unsigned int stack_keep);
MRB_API mrb_value mrb_vm_exec(mrb_state *mrb, const struct RProc *proc, const mrb_code *iseq);
/* compatibility macros */
#define mrb_toplevel_run_keep(m,p,k) mrb_top_run((m),(p),mrb_top_self(m),(k))
#define mrb_toplevel_run(m,p) mrb_toplevel_run_keep((m),(p),0)
......
......@@ -33,7 +33,7 @@ typedef struct mrbc_context {
mrb_bool no_exec:1;
mrb_bool keep_lv:1;
mrb_bool no_optimize:1;
struct RProc *upper;
const struct RProc *upper;
size_t parser_nerr;
} mrbc_context;
......@@ -153,7 +153,7 @@ struct mrb_parser_state {
mrb_bool no_optimize:1;
mrb_bool capture_errors:1;
struct RProc *upper;
const struct RProc *upper;
struct mrb_parser_message error_buffer[10];
struct mrb_parser_message warn_buffer[10];
......
......@@ -35,7 +35,7 @@ MRB_API mrb_value mrb_f_raise(mrb_state*, mrb_value);
#if defined(MRB_64BIT) || defined(MRB_USE_FLOAT) || defined(MRB_NAN_BOXING) || defined(MRB_WORD_BOXING)
struct RBreak {
MRB_OBJECT_HEADER;
struct RProc *proc;
const struct RProc *proc;
mrb_value val;
};
#define mrb_break_value_get(brk) ((brk)->val)
......@@ -43,7 +43,7 @@ struct RBreak {
#else
struct RBreak {
MRB_OBJECT_HEADER;
struct RProc *proc;
const struct RProc *proc;
union mrb_value_union value;
};
#define RBREAK_VALUE_TT_MASK ((1 << 8) - 1)
......
......@@ -44,7 +44,7 @@ struct RProc {
const mrb_irep *irep;
mrb_func_t func;
} body;
struct RProc *upper;
const struct RProc *upper;
union {
struct RClass *target_class;
struct REnv *env;
......@@ -93,9 +93,6 @@ MRB_API struct RProc *mrb_closure_new_cfunc(mrb_state *mrb, mrb_func_t func, int
void mrb_proc_copy(struct RProc *a, struct RProc *b);
mrb_int mrb_proc_arity(const struct RProc *p);
/* implementation of #send method */
mrb_value mrb_f_send(mrb_state *mrb, mrb_value self);
/* following functions are defined in mruby-proc-ext so please include it when using */
MRB_API struct RProc *mrb_proc_new_cfunc_with_env(mrb_state *mrb, mrb_func_t func, mrb_int argc, const mrb_value *argv);
MRB_API mrb_value mrb_proc_cfunc_env_get(mrb_state *mrb, mrb_int idx);
......@@ -137,6 +134,8 @@ MRB_API mrb_value mrb_proc_cfunc_env_get(mrb_state *mrb, mrb_int idx);
#include <mruby/khash.h>
KHASH_DECLARE(mt, mrb_sym, mrb_method_t, TRUE)
MRB_API mrb_value mrb_load_proc(mrb_state *mrb, const struct RProc *proc);
MRB_END_DECL
#endif /* MRUBY_PROC_H */
......@@ -310,7 +310,7 @@ module MRuby
def initialize(build)
super
@command = nil
@compile_options = "-B%{funcname} -o-"
@compile_options = "-S -B%{funcname} -o-"
end
def run(out, infiles, funcname)
......
......@@ -174,7 +174,7 @@ module MRuby
def generate_gem_init(fname)
open(fname, 'w') do |f|
print_gem_init_header f
build.mrbc.run f, rbfiles, "gem_mrblib_irep_#{funcname}" unless rbfiles.empty?
build.mrbc.run f, rbfiles, "gem_mrblib_#{funcname}_proc" unless rbfiles.empty?
f.puts %Q[void mrb_#{funcname}_gem_init(mrb_state *mrb);]
f.puts %Q[void mrb_#{funcname}_gem_final(mrb_state *mrb);]
f.puts %Q[]
......@@ -183,7 +183,7 @@ module MRuby
f.puts %Q[ struct REnv *e;] unless rbfiles.empty?
f.puts %Q[ mrb_#{funcname}_gem_init(mrb);] if objs != [objfile("#{build_dir}/gem_init")]
unless rbfiles.empty?
f.puts %Q[ mrb_load_irep(mrb, gem_mrblib_irep_#{funcname});]
f.puts %Q[ mrb_load_proc(mrb, gem_mrblib_#{funcname}_proc);]
f.puts %Q[ if (mrb->exc) {]
f.puts %Q[ mrb_print_error(mrb);]
f.puts %Q[ mrb_close(mrb);]
......@@ -215,10 +215,13 @@ module MRuby
def print_gem_init_header(f)
print_gem_comment(f)
f.puts %Q[#include <stdlib.h>] unless rbfiles.empty?
f.puts %Q[#include <mruby.h>]
f.puts %Q[#include <mruby/irep.h>] unless rbfiles.empty?
f.puts %Q[#include <mruby/proc.h>] unless rbfiles.empty?
unless rbfiles.empty?
f.puts %Q[#include <stdlib.h>]
f.puts %Q[#include <mruby.h>]
f.puts %Q[#include <mruby/proc.h>]
else
f.puts %Q[#include <mruby.h>]
end
end
def print_gem_test_header(f)
......@@ -226,7 +229,7 @@ module MRuby
f.puts %Q[#include <stdio.h>]
f.puts %Q[#include <stdlib.h>]
f.puts %Q[#include <mruby.h>]
f.puts %Q[#include <mruby/irep.h>]
f.puts %Q[#include <mruby/proc.h>]
f.puts %Q[#include <mruby/variable.h>]
f.puts %Q[#include <mruby/hash.h>] unless test_args.empty?
end
......
......@@ -706,7 +706,7 @@ lv_idx(codegen_scope *s, mrb_sym id)
static int
search_upvar(codegen_scope *s, mrb_sym id, int *idx)
{
struct RProc *u;
const struct RProc *u;
int lv = 0;
codegen_scope *up = s->prev;
......
......@@ -265,7 +265,7 @@ local_unnest(parser_state *p)
static mrb_bool
local_var_p(parser_state *p, mrb_sym sym)
{
struct RProc *u;
const struct RProc *u;
node *l = p->locals;
while (l) {
......@@ -282,7 +282,7 @@ local_var_p(parser_state *p, mrb_sym sym)
const struct mrb_irep *ir = u->body.irep;
uint_fast16_t n = ir->nlocals;
const struct mrb_lvinfo *v = ir->lv;
for (; n > 1; n --, v ++) {
for (; v && n > 1; n--, v++) {
if (v->name == sym) return TRUE;
}
if (MRB_PROC_SCOPE_P(u)) break;
......
......@@ -328,7 +328,7 @@ local_unnest(parser_state *p)
static mrb_bool
local_var_p(parser_state *p, mrb_sym sym)
{
struct RProc *u;
const struct RProc *u;
node *l = p->locals;
while (l) {
......@@ -345,7 +345,7 @@ local_var_p(parser_state *p, mrb_sym sym)
const struct mrb_irep *ir = u->body.irep;
uint_fast16_t n = ir->nlocals;
const struct mrb_lvinfo *v = ir->lv;
for (; n > 1; n --, v ++) {
for (; v && n > 1; n--, v++) {
if (v->name == sym) return TRUE;
}
if (MRB_PROC_SCOPE_P(u)) break;
......
......@@ -130,6 +130,7 @@ class Enumerator
@feedvalue = nil
@stop_exc = false
end
attr_accessor :obj, :meth, :args
attr_reader :fib
......
......@@ -132,7 +132,7 @@ mrb_obj_ivar_set(mrb_state *mrb, mrb_value self)
static mrb_value
mrb_local_variables(mrb_state *mrb, mrb_value self)
{
struct RProc *proc;
const struct RProc *proc;
const mrb_irep *irep;
mrb_value vars;
size_t i;
......@@ -664,7 +664,7 @@ mrb_mod_s_constants(mrb_state *mrb, mrb_value mod)
static mrb_value
mrb_mod_s_nesting(mrb_state *mrb, mrb_value mod)
{
struct RProc *proc;
const struct RProc *proc;
mrb_value ary;
struct RClass *c = NULL;
......@@ -684,6 +684,9 @@ mrb_mod_s_nesting(mrb_state *mrb, mrb_value mod)
return ary;
}
/* implementation of #send method */
mrb_value mrb_f_send(mrb_state *mrb, mrb_value self);
void
mrb_mruby_metaprog_gem_init(mrb_state* mrb)
{
......
......@@ -200,7 +200,7 @@ mrb_addrinfo_getnameinfo(mrb_state *mrb, mrb_value self)
host = mrb_str_buf_new(mrb, NI_MAXHOST);
serv = mrb_str_buf_new(mrb, NI_MAXSERV);
sastr = mrb_iv_get(mrb, self, MRB_QSYM(a_sockaddr));
sastr = mrb_iv_get(mrb, self, MRB_QSYM(0_sockaddr));
if (!mrb_string_p(sastr)) {
mrb_raise(mrb, E_SOCKET_ERROR, "invalid sockaddr");
}
......@@ -222,7 +222,7 @@ mrb_addrinfo_unix_path(mrb_state *mrb, mrb_value self)
{
mrb_value sastr;
sastr = mrb_iv_get(mrb, self, MRB_QSYM(a_sockaddr));
sastr = mrb_iv_get(mrb, self, MRB_QSYM(0_sockaddr));
if (((struct sockaddr *)RSTRING_PTR(sastr))->sa_family != AF_UNIX)
mrb_raise(mrb, E_SOCKET_ERROR, "need AF_UNIX address");
if (RSTRING_LEN(sastr) < (mrb_int)offsetof(struct sockaddr_un, sun_path) + 1) {
......
......@@ -13,13 +13,13 @@ end
%w[size length].each do |n|
assert("Symbol##{n}") do
assert_equal 5, :hello.__send__(n)
assert_equal 4, :"aA\0b".__send__(n)
assert_equal 4, :"aA b".__send__(n)
if __ENCODING__ == "UTF-8"
assert_equal 8, :"こんにちは世界!".__send__(n)
assert_equal 4, :"aあ\0b".__send__(n)
assert_equal 4, :"aあ b".__send__(n)
else
assert_equal 22, :"こんにちは世界!".__send__(n)
assert_equal 6, :"aあ\0b".__send__(n)
assert_equal 6, :"aあ b".__send__(n)
end
end
end
......
......@@ -18,7 +18,7 @@
#include <mruby/variable.h>
#include <mruby/array.h>
extern const uint8_t mrbtest_assert_irep[];
extern const struct RProc mrbtest_assert_proc[];
void mrbgemtest_init(mrb_state* mrb);
void mrb_init_test_vformat(mrb_state* mrb);
......@@ -300,7 +300,7 @@ main(int argc, char **argv)
}
mrb_init_test_driver(mrb, verbose);
mrb_load_irep(mrb, mrbtest_assert_irep);
mrb_load_proc(mrb, mrbtest_assert_proc);
mrbgemtest_init(mrb);
ret = eval_test(mrb);
mrb_close(mrb);
......
......@@ -28,7 +28,7 @@ MRuby::Gem::Specification.new('mruby-test') do |spec|
file assert_c => [assert_rb, build.mrbcfile] do |t|
mkdir_p File.dirname(t.name)
open(t.name, 'w') do |f|
mrbc.run f, assert_rb, 'mrbtest_assert_irep'
mrbc.run f, assert_rb, 'mrbtest_assert_proc'
end
end
......@@ -56,12 +56,12 @@ MRuby::Gem::Specification.new('mruby-test') do |spec|
f.puts %Q[ * All manual changes will get lost.]
f.puts %Q[ */]
if test_preload.nil?
f.puts %Q[extern const uint8_t mrbtest_assert_irep[];]
f.puts %Q[extern const struct RProc mrbtest_assert_proc[];]
else
g.build.mrbc.run f, test_preload, "gem_test_irep_#{g.funcname}_preload"
g.build.mrbc.run f, test_preload, "gem_test_#{g.funcname}_preload"
end
g.test_rbfiles.flatten.each_with_index do |rbfile, i|
g.build.mrbc.run f, rbfile, "gem_test_irep_#{g.funcname}_#{i}"
g.build.mrbc.run f, rbfile, "gem_test_#{g.funcname}_#{i}_proc"
end
f.puts %Q[void mrb_#{g.funcname}_gem_test(mrb_state *mrb);] unless g.test_objs.empty?
dep_list.each do |d|
......@@ -90,9 +90,9 @@ MRuby::Gem::Specification.new('mruby-test') do |spec|
end
f.puts %Q[ mrb_init_test_driver(mrb2, mrb_test(mrb_gv_get(mrb, mrb_intern_lit(mrb, "$mrbtest_verbose"))));]
if test_preload.nil?
f.puts %Q[ mrb_load_irep(mrb2, mrbtest_assert_irep);]
f.puts %Q[ mrb_load_proc(mrb2, mrbtest_assert_proc);]
else
f.puts %Q[ mrb_load_irep(mrb2, gem_test_irep_#{g.funcname}_preload);]
f.puts %Q[ mrb_load_proc(mrb2, gem_test_#{g.funcname}_preload);]
end
f.puts %Q[ if (mrb2->exc) {]
f.puts %Q[ mrb_print_error(mrb2);]
......@@ -113,7 +113,7 @@ MRuby::Gem::Specification.new('mruby-test') do |spec|
f.puts %Q[ mrb_#{g.funcname}_gem_test(mrb2);] if g.custom_test_init?
f.puts %Q[ mrb_load_irep(mrb2, gem_test_irep_#{g.funcname}_#{i});]
f.puts %Q[ mrb_load_proc(mrb2, gem_test_#{g.funcname}_#{i}_proc);]
f.puts %Q[ ]
f.puts %Q[ mrb_t_pass_result(mrb, mrb2);]
......
#include <mruby.h>
#include <mruby/irep.h>
extern const uint8_t mrblib_irep[];
void
mrb_init_mrblib(mrb_state *mrb)
{
mrb_load_irep(mrb, mrblib_irep);
}
......@@ -11,8 +11,21 @@ MRuby.each_target do
mkdir_p File.dirname(t.name)
open(t.name, 'w') do |f|
_pp "GEN", "*.rb", "#{t.name.relative_path}"
f.puts File.read("#{current_dir}/init_mrblib.c")
mrbc.run f, rbfiles, 'mrblib_irep'
f.puts %Q[/*]
f.puts %Q[ * This file is loading the mrblib]
f.puts %Q[ *]
f.puts %Q[ * IMPORTANT:]
f.puts %Q[ * This file was generated!]
f.puts %Q[ * All manual changes will get lost.]
f.puts %Q[ */]
mrbc.run f, rbfiles, 'mrblib_proc'
f.puts <<INIT_END
void
mrb_init_mrblib(mrb_state *mrb)
{
mrb_load_proc(mrb, mrblib_proc);
}
INIT_END
end
end
end
......@@ -2334,6 +2334,9 @@ init_class_new(mrb_state *mrb, struct RClass *cls)
mrb_define_method_raw(mrb, cls, MRB_SYM(new), m);
}
/* implementation of #send method */
mrb_value mrb_f_send(mrb_state *mrb, mrb_value self);
void
mrb_init_class(mrb_state *mrb)
{
......
......@@ -942,7 +942,12 @@ dump_pool(mrb_state *mrb, const mrb_pool_value *p, FILE *fp)
fprintf(fp, "{IREP_TT_INT64, {.i64=%"PRId64"}},\n", p->u.i64);
break;
case IREP_TT_FLOAT:
fprintf(fp, "{IREP_TT_FLOAT, {.f="MRB_FLOAT_FMT"}},\n", p->u.f);
if (p->u.f == 0) {
fprintf(fp, "{IREP_TT_FLOAT, {.f=%#.1f}},\n", p->u.f);
}
else {
fprintf(fp, "{IREP_TT_FLOAT, {.f="MRB_FLOAT_FMT"}},\n", p->u.f);
}
break;
}
}
......@@ -951,83 +956,28 @@ dump_pool(mrb_state *mrb, const mrb_pool_value *p, FILE *fp)
const char *s = p->u.str;
fprintf(fp, "{IREP_TT_STR|(%d<<2), {.str=\"", len);
for (i=0; i<len; i++) {
fprintf(fp, "\\%03o", (int)s[i]);
fprintf(fp, "\\x%02x", (int)s[i]&0xff);
}
fputs("\"}},\n", fp);
}
return MRB_DUMP_OK;
}
static struct {
const char *op;
const char *name;
} op_table[] = {
{"!", "not"},
{"!=", "neq"},
{"!~", "nmatch"},
{"%", "mod"},
{"&", "and"},
{"&&", "andand"},
{"*", "mul"},
{"**", "pow"},
{"+", "add"},
{"+@", "plus"},
{"-", "sub"},
{"-@", "minus"},
{"/", "div"},
{"<", "lt"},
{"<=", "le"},
{"<<", "lshift"},
{"<=>", "cmp"},
{"==", "eq"},
{"===", "eqq"},
{"=~", "match"},
{">", "gt"},
{">=", "ge"},
{">>", "rshift"},
{"[]", "aref"},
{"[]=", "aset"},
{"^", "xor"},
{"`", "tick"},
{"|", "or"},
{"||", "oror"},
{"~", "neg"},
{0},
};
mrb_bool mrb_sym_static_p(mrb_state *mrb, mrb_sym sym);
static int
dump_sym(mrb_state *mrb, mrb_sym sym, FILE *fp)
{
mrb_int len;
const char *name = mrb_sym_name_len(mrb, sym, &len);
int i;
if (len == 0 || len != strlen(name))
return MRB_DUMP_INVALID_ARGUMENT;
for (i=0; op_table[i].op; i++) {
if (strcmp(name, op_table[i].op) == 0) {
fprintf(fp, "MRB_QSYM(%s),", op_table[i].name);
return MRB_DUMP_OK;
}
}
if (name[0] == '@') {
fprintf(fp, "MRB_QSYM(a_%s),", name+1);
}
else if (name[0] == '$') {
fprintf(fp, "MRB_QSYM(d_%s),", name+1);
}
else if (name[len-1] == '!') {
fprintf(fp, "MRB_QSYM(%.*s_b),", (int)len-1, name);
}
else if (name[len-1] == '?') {
fprintf(fp, "MRB_QSYM(%.*s_p),", (int)len-1, name);
}
else if (name[len-1] == '=') {
fprintf(fp, "MRB_QSYM(%.*s_e),", (int)len-1, name);
const char *name;
if (sym == 0) return MRB_DUMP_INVALID_ARGUMENT;
name = mrb_sym_name(mrb, sym);
if (!name) {
fprintf(stderr, "undefined symbol (%d) - define presym\n", sym);
}
else {
fprintf(fp, "MRB_SYM(%s),", name);
if (!mrb_sym_static_p(mrb, sym)) {
fprintf(stderr, "no static symbol (%s) - define presym\n", name);
}
fprintf(fp, "%d /* %s */,", sym, name);
return MRB_DUMP_OK;
}
......@@ -1065,8 +1015,7 @@ dump_irep_struct(mrb_state *mrb, const mrb_irep *irep, uint8_t flags, FILE *fp,
len=irep->slen;
fprintf(fp, "static const mrb_sym %s_syms_%d[%d] = {", name, n, len);
for (i=0; i<len; i++) {
if (dump_sym(mrb, irep->syms[i], fp) != MRB_DUMP_OK)
return MRB_DUMP_INVALID_ARGUMENT;
dump_sym(mrb, irep->syms[i], fp);
}
fputs("};\n", fp);
}
......@@ -1078,13 +1027,17 @@ dump_irep_struct(mrb_state *mrb, const mrb_irep *irep, uint8_t flags, FILE *fp,
fprintf(fp, "0x%02x,", irep->iseq[i]);
}
fputs("};\n", fp);
/* dump irep */
if (n == 0) { /* topleve irep */
fprintf(fp, "static const mrb_irep %s = {\n", name);
}
else {
fprintf(fp, "static const mrb_irep %s_irep_%d = {\n", name, n);
/* dump lv */
if (irep->lv) {
len=irep->nlocals;
fprintf(fp, "static const struct mrb_lvinfo %s_lv_%d[%d] = {", name, n, len);
for (i=0; i+1<len; i++) {
fprintf(fp, "{%d,%d},\n", irep->lv[i].name, irep->lv[i].r);
}
fputs("};\n", fp);
}
/* dump irep */
fprintf(fp, "static const mrb_irep %s_irep_%d = {\n", name, n);
fprintf(fp, " %d,%d,\n", irep->nlocals, irep->nregs);
fprintf(fp, " MRB_IREP_STATIC,%s_iseq_%d,\n", name, n);
if (irep->pool) {
......@@ -1105,9 +1058,14 @@ dump_irep_struct(mrb_state *mrb, const mrb_irep *irep, uint8_t flags, FILE *fp,
else {
fputs( "NULL,\n", fp);
}
fputs( " NULL,\t\t\t\t\t/* lv */\n", fp);
if (irep->lv) {
fprintf(fp, "%s_lv_%d,\n", name, n);
}
else {
fputs( " NULL,\t\t\t\t\t/* lv */\n", fp);
}
fputs( " NULL,\t\t\t\t\t/* debug_info */\n", fp);
fprintf(fp, " %d,%d,%d,%d,0\n};", irep->ilen, irep->plen, irep->slen, irep->rlen);
fprintf(fp, " %d,%d,%d,%d,0\n};\n", irep->ilen, irep->plen, irep->slen, irep->rlen);
return MRB_DUMP_OK;
}
......@@ -1116,13 +1074,20 @@ int
mrb_dump_irep_cstruct(mrb_state *mrb, const mrb_irep *irep, uint8_t flags, FILE *fp, const char *initname)
{
int max = 1;
int n;
if (fp == NULL || initname == NULL || initname[0] == '\0') {
return MRB_DUMP_INVALID_ARGUMENT;
}
if (fprintf(fp, "#include <mruby.h>\n" "#include <mruby/irep.h>\n\n") < 0) {
if (fprintf(fp, "#include <mruby.h>\n" "#include <mruby/proc.h>\n\n") < 0) {
return MRB_DUMP_WRITE_FAULT;
}
return dump_irep_struct(mrb, irep, flags, fp, initname, 0, &max);
n = dump_irep_struct(mrb, irep, flags, fp, initname, 0, &max);
if (n != MRB_DUMP_OK) return n;
fprintf(fp, "#ifdef __cplusplus\nextern struct RProc %s[];\n#endif\n", initname);
fprintf(fp, "struct RProc %s[] = {{\n", initname);
fprintf(fp, "NULL,NULL,MRB_TT_PROC,7,0,{&%s_irep_0},NULL,{NULL},\n}};\n", initname);
return MRB_DUMP_OK;
}
#endif /* MRB_DISABLE_STDIO */
......@@ -35,6 +35,11 @@
* Gray - Marked, But the child objects are unmarked.
* Black - Marked, the child objects are also marked.
Extra color
* Red - Static (ROM object) no need to be collected.
- All child objects should be Red as well.
== Two White Types
There're two white color types in a flip-flop fashion: White-A and White-B,
......@@ -185,6 +190,7 @@ gettimeofday_time(void)
#define GC_WHITE_A 1
#define GC_WHITE_B (1 << 1)
#define GC_BLACK (1 << 2)
#define GC_RED 7
#define GC_WHITES (GC_WHITE_A | GC_WHITE_B)
#define GC_COLOR_MASK 7
......@@ -194,7 +200,8 @@ gettimeofday_time(void)
#define paint_partial_white(s, o) ((o)->color = (s)->current_white_part)
#define is_gray(o) ((o)->color == GC_GRAY)
#define is_white(o) ((o)->color & GC_WHITES)
#define is_black(o) ((o)->color & GC_BLACK)
#define is_black(o) ((o)->color == GC_BLACK)
#define is_red(o) ((o)->color == GC_RED)
#define flip_white_part(s) ((s)->current_white_part = other_white_part(s))
#define other_white_part(s) ((s)->current_white_part ^ GC_WHITES)
#define is_dead(s, o) (((o)->color & other_white_part(s) & GC_WHITES) || (o)->tt == MRB_TT_FREE)
......@@ -584,7 +591,7 @@ add_gray_list(mrb_state *mrb, mrb_gc *gc, struct RBasic *obj)
static int
ci_nregs(mrb_callinfo *ci)
{
struct RProc *p = ci->proc;
const struct RProc *p = ci->proc;
int n = 0;
if (!p) {
......
......@@ -19,7 +19,7 @@ mrb_func_basic_p(mrb_state *mrb, mrb_value obj, mrb_sym mid, mrb_func_t func)
{
struct RClass *c = mrb_class(mrb, obj);
mrb_method_t m = mrb_method_search_vm(mrb, &c, mid);
struct RProc *p;
const struct RProc *p;
if (MRB_METHOD_UNDEF_P(m)) return FALSE;
if (MRB_METHOD_FUNC_P(m))
......@@ -143,7 +143,7 @@ mrb_f_block_given_p_m(mrb_state *mrb, mrb_value self)
mrb_value *bp;
int bidx;
struct REnv *e = NULL;
struct RProc *p;
const struct RProc *p;
if (ci <= cibase) {
/* toplevel does not have block */
......
......@@ -676,6 +676,12 @@ mrb_load_irep_buf(mrb_state *mrb, const void *buf, size_t bufsize)
return mrb_load_irep_buf_cxt(mrb, buf, bufsize, NULL);
}
MRB_API mrb_value
mrb_load_proc(mrb_state *mrb, const struct RProc *proc)
{
return mrb_vm_run(mrb, proc, mrb_top_self(mrb), 0);
}
#ifndef MRB_DISABLE_STDIO
mrb_irep*
......
......@@ -80,7 +80,7 @@ static void
closure_setup(mrb_state *mrb, struct RProc *p)
{
mrb_callinfo *ci = mrb->c->ci;
struct RProc *up = p->upper;
const struct RProc *up = p->upper;
struct REnv *e = NULL;
if (ci && ci->env) {
......@@ -170,7 +170,7 @@ mrb_closure_new_cfunc(mrb_state *mrb, mrb_func_t func, int nlocals)
MRB_API mrb_value
mrb_proc_cfunc_env_get(mrb_state *mrb, mrb_int idx)
{
struct RProc *p = mrb->c->ci->proc;
const struct RProc *p = mrb->c->ci->proc;
struct REnv *e;
if (!p || !MRB_PROC_CFUNC_P(p)) {
......
......@@ -330,6 +330,15 @@ mrb_sym_name_len(mrb_state *mrb, mrb_sym sym, mrb_int *lenp)
return sym2name_len(mrb, sym, mrb->symbuf, lenp);
}
mrb_bool
mrb_sym_static_p(mrb_state *mrb, mrb_sym sym)
{
if (SYMBOL_INLINE_P(sym)) return TRUE;
sym >>= SYMBOL_NORMAL_SHIFT;
if (sym > MRB_PRESYM_MAX) return FALSE;
return TRUE;
}
void
mrb_free_symtbl(mrb_state *mrb)
{
......
......@@ -741,11 +741,11 @@ mrb_vm_cv_get(mrb_state *mrb, mrb_sym sym)
{
struct RClass *c;
struct RProc *p = mrb->c->ci->proc;
const struct RProc *p = mrb->c->ci->proc;
for (;;) {
c = MRB_PROC_TARGET_CLASS(p);
if (c->tt != MRB_TT_SCLASS) break;
if (c && c->tt != MRB_TT_SCLASS) break;
p = p->upper;
}
return mrb_mod_cv_get(mrb, c, sym);
......@@ -755,11 +755,11 @@ void
mrb_vm_cv_set(mrb_state *mrb, mrb_sym sym, mrb_value v)
{
struct RClass *c;
struct RProc *p = mrb->c->ci->proc;
const struct RProc *p = mrb->c->ci->proc;
for (;;) {
c = MRB_PROC_TARGET_CLASS(p);
if (c->tt != MRB_TT_SCLASS) break;
if (c && c->tt != MRB_TT_SCLASS) break;
p = p->upper;
}
mrb_mod_cv_set(mrb, c, sym, v);
......@@ -817,9 +817,10 @@ mrb_vm_const_get(mrb_state *mrb, mrb_sym sym)
struct RClass *c;
struct RClass *c2;
mrb_value v;
struct RProc *proc;
const struct RProc *proc;
c = MRB_PROC_TARGET_CLASS(mrb->c->ci->proc);
if (!c) c = mrb->object_class;
if (iv_get(mrb, c->iv, sym, &v)) {
return v;
}
......@@ -862,6 +863,7 @@ mrb_vm_const_set(mrb_state *mrb, mrb_sym sym, mrb_value v)
struct RClass *c;
c = MRB_PROC_TARGET_CLASS(mrb->c->ci->proc);
if (!c) c = mrb->object_class;
mrb_obj_iv_set(mrb, (struct RObject*)c, sym, v);
}
......
......@@ -224,7 +224,7 @@ mrb_stack_extend(mrb_state *mrb, mrb_int room)
static inline struct REnv*
uvenv(mrb_state *mrb, int up)
{
struct RProc *proc = mrb->c->ci->proc;
const struct RProc *proc = mrb->c->ci->proc;
struct REnv *e;
while (up--) {
......@@ -247,8 +247,8 @@ uvenv(mrb_state *mrb, int up)
return NULL;
}
static inline struct RProc*
top_proc(mrb_state *mrb, struct RProc *proc)
static inline const struct RProc*
top_proc(mrb_state *mrb, const struct RProc *proc)
{
while (proc->upper) {
if (MRB_PROC_SCOPE_P(proc) || MRB_PROC_STRICT_P(proc))
......@@ -327,7 +327,7 @@ cipop(mrb_state *mrb)
}
void mrb_exc_set(mrb_state *mrb, mrb_value exc);
static mrb_value mrb_run(mrb_state *mrb, struct RProc* proc, mrb_value self);
static mrb_value mrb_run(mrb_state *mrb, const struct RProc* proc, mrb_value self);
static void
ecall(mrb_state *mrb)
......@@ -423,7 +423,7 @@ mrb_funcall_id(mrb_state *mrb, mrb_value self, mrb_sym mid, mrb_int argc, ...)
static int
ci_nregs(mrb_callinfo *ci)
{
struct RProc *p;
const struct RProc *p;
int n = 0;
if (!ci) return 3;
......@@ -821,7 +821,7 @@ mrb_yield_cont(mrb_state *mrb, mrb_value b, mrb_value self, mrb_int argc, const
}
static struct RBreak*
break_new(mrb_state *mrb, struct RProc *p, mrb_value val)
break_new(mrb_state *mrb, const struct RProc *p, mrb_value val)
{
struct RBreak *brk;
......@@ -918,7 +918,7 @@ argnum_error(mrb_state *mrb, mrb_int num)
#endif
MRB_API mrb_value
mrb_vm_run(mrb_state *mrb, struct RProc *proc, mrb_value self, unsigned int stack_keep)
mrb_vm_run(mrb_state *mrb, const struct RProc *proc, mrb_value self, unsigned int stack_keep)
{
const mrb_irep *irep = proc->body.irep;
mrb_value result;
......@@ -961,7 +961,7 @@ check_target_class(mrb_state *mrb)
void mrb_hash_check_kdict(mrb_state *mrb, mrb_value self);
MRB_API mrb_value
mrb_vm_exec(mrb_state *mrb, struct RProc *proc, const mrb_code *pc)
mrb_vm_exec(mrb_state *mrb, const struct RProc *proc, const mrb_code *pc)
{
/* mrb_assert(MRB_PROC_CFUNC_P(proc)) */
const mrb_code *pc0 = pc;
......@@ -1534,7 +1534,7 @@ RETRY_TRY_BLOCK:
struct RClass *cls;
mrb_callinfo *ci = mrb->c->ci;
mrb_value recv, blk;
struct RProc *p = ci->proc;
const struct RProc *p = ci->proc;
mrb_sym mid = ci->mid;
struct RClass* target_class = MRB_PROC_TARGET_CLASS(p);
......@@ -1975,7 +1975,7 @@ RETRY_TRY_BLOCK:
else {
int acc;
mrb_value v;
struct RProc *dst;
const struct RProc *dst;
ci = mrb->c->ci;
v = regs[a];
......@@ -2612,6 +2612,7 @@ RETRY_TRY_BLOCK:
super = regs[a+1];
if (mrb_nil_p(base)) {
baseclass = MRB_PROC_TARGET_CLASS(mrb->c->ci->proc);
if (!baseclass) baseclass = mrb->object_class;
base = mrb_obj_value(baseclass);
}
c = mrb_vm_define_class(mrb, base, super, id);
......@@ -2628,6 +2629,7 @@ RETRY_TRY_BLOCK:
base = regs[a];
if (mrb_nil_p(base)) {
baseclass = MRB_PROC_TARGET_CLASS(mrb->c->ci->proc);
if (!baseclass) baseclass = mrb->object_class;
base = mrb_obj_value(baseclass);
}
cls = mrb_vm_define_module(mrb, base, id);
......@@ -2782,7 +2784,7 @@ RETRY_TRY_BLOCK:
}
static mrb_value
mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
mrb_run(mrb_state *mrb, const struct RProc *proc, mrb_value self)
{
if (mrb->c->ci->argc < 0) {
return mrb_vm_run(mrb, proc, self, 3); /* receiver, args and block) */
......@@ -2793,7 +2795,7 @@ mrb_run(mrb_state *mrb, struct RProc *proc, mrb_value self)
}
MRB_API mrb_value
mrb_top_run(mrb_state *mrb, struct RProc *proc, mrb_value self, unsigned int stack_keep)
mrb_top_run(mrb_state *mrb, const struct RProc *proc, mrb_value self, unsigned int stack_keep)
{
mrb_value v;
......
# List of symbols that cannot be detected by Rakefile
# Those symbols are not defined (to cause exceptions)
doesNotExistAsAMethodNameForVerySure
UnknownConstant
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