From 478003f6df40dc79d33c6ec86919f2dde07284be Mon Sep 17 00:00:00 2001 From: ko1 Date: Thu, 1 Jun 2017 00:05:33 +0000 Subject: [PATCH] rename absolute_path to realpath internally and introduce pathobj. * vm_core.h: rename absolute_path to realpath because it is expected name. external APIs (#absolute_path methods) are remained. * vm_core.h: remove rb_iseq_location_struct::path and rb_iseq_location_struct::absolute_path and introduce pathobj. if given path equals to given absolute_path (and most of case it is true), pathobj is simply given path String. If it is not same, pathobj is Array and pathobj[0] is path and pathobj[1] is realpath. This size optimization reduce 8 bytes and sizeof(struct rb_iseq_constant_body) is 200 bytes -> 192 bytes on 64bit CPU. To support this change, the following functions are introduced: * pathobj_path() (defined in vm_core.h) * pathobj_realpath() (ditto) * rb_iseq_path() (decl. in vm_core.h) * rb_iseq_realpath() (ditto) * rb_iseq_pathobj_new() (ditto) * rb_iseq_pathobj_set() (ditto) * vm_core.h (rb_binding_t): use pathobj instead of path. If binding is given at eval methods, realpath (absolute_path) was caller's realpath. However, they should use binding's realpath. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@58979 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- compile.c | 35 ++++++++--------- debug_counter.h | 5 +++ gc.c | 2 +- iseq.c | 99 ++++++++++++++++++++++++++++++------------------- iseq.h | 3 +- proc.c | 18 ++++----- vm.c | 19 ++++++---- vm_backtrace.c | 22 +++++------ vm_core.h | 52 +++++++++++++++++++++----- vm_dump.c | 2 +- vm_eval.c | 19 ++++------ vm_method.c | 4 +- vm_trace.c | 2 +- 13 files changed, 165 insertions(+), 117 deletions(-) diff --git a/compile.c b/compile.c index a448b2120b..db3c7f7e4f 100644 --- a/compile.c +++ b/compile.c @@ -175,9 +175,6 @@ struct iseq_compile_data_ensure_node_stack { #define NEW_LABEL(l) new_label_body(iseq, (l)) #define LABEL_FORMAT "" -#define iseq_path(iseq) ((iseq)->body->location.path) -#define iseq_absolute_path(iseq) ((iseq)->body->location.absolute_path) - #define NEW_ISEQ(node, name, type, line_no) \ new_child_iseq(iseq, (node), rb_fstring(name), 0, (type), (line_no)) @@ -328,7 +325,7 @@ static void append_compile_error(rb_iseq_t *iseq, int line, const char *fmt, ...) { VALUE err_info = ISEQ_COMPILE_DATA(iseq)->err_info; - VALUE file = iseq->body->location.path; + VALUE file = rb_iseq_path(iseq); VALUE err = err_info == Qtrue ? Qfalse : err_info; va_list args; @@ -349,7 +346,7 @@ compile_bug(rb_iseq_t *iseq, int line, const char *fmt, ...) { va_list args; va_start(args, fmt); - rb_report_bug_valist(iseq->body->location.path, line, fmt, args); + rb_report_bug_valist(rb_iseq_path(iseq), line, fmt, args); va_end(args); abort(); } @@ -532,7 +529,7 @@ iseq_add_mark_object(const rb_iseq_t *iseq, VALUE v) return COMPILE_OK; } -#define ruby_sourcefile RSTRING_PTR(iseq->body->location.path) +#define ruby_sourcefile RSTRING_PTR(rb_iseq_path(iseq)) static int iseq_add_mark_object_compile_time(const rb_iseq_t *iseq, VALUE v) @@ -1116,7 +1113,7 @@ new_child_iseq(rb_iseq_t *iseq, NODE *node, debugs("[new_child_iseq]> ---------------------------------------\n"); ret_iseq = rb_iseq_new_with_opt(node, name, - iseq_path(iseq), iseq_absolute_path(iseq), + rb_iseq_path(iseq), rb_iseq_realpath(iseq), INT2FIX(line_no), parent, type, ISEQ_COMPILE_DATA(iseq)->option); debugs("[new_child_iseq]< ---------------------------------------\n"); iseq_add_mark_object(iseq, (VALUE)ret_iseq); @@ -5809,7 +5806,7 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int popp } else { if (ISEQ_COMPILE_DATA(iseq)->option->debug_frozen_string_literal || RTEST(ruby_debug)) { - VALUE debug_info = rb_ary_new_from_args(2, iseq->body->location.path, INT2FIX(line)); + VALUE debug_info = rb_ary_new_from_args(2, rb_iseq_path(iseq), INT2FIX(line)); VALUE str = rb_str_dup(node->nd_lit); rb_ivar_set(str, id_debug_created_info, rb_obj_freeze(debug_info)); ADD_INSN1(ret, line, putobject, rb_obj_freeze(str)); @@ -5832,7 +5829,7 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, NODE *node, int popp if (ISEQ_COMPILE_DATA(iseq)->option->frozen_string_literal) { VALUE debug_info = Qnil; if (ISEQ_COMPILE_DATA(iseq)->option->debug_frozen_string_literal || RTEST(ruby_debug)) { - debug_info = rb_ary_new_from_args(2, iseq->body->location.path, INT2FIX(line)); + debug_info = rb_ary_new_from_args(2, rb_iseq_path(iseq), INT2FIX(line)); iseq_add_mark_object_compile_time(iseq, rb_obj_freeze(debug_info)); } ADD_INSN1(ret, line, freezestring, debug_info); @@ -7148,7 +7145,7 @@ rb_local_defined(ID id, const struct rb_block *base_block) } static int -caller_location(VALUE *path, VALUE *absolute_path) +caller_location(VALUE *path, VALUE *realpath) { const rb_thread_t *const th = GET_THREAD(); const rb_control_frame_t *const cfp = @@ -7156,13 +7153,13 @@ caller_location(VALUE *path, VALUE *absolute_path) if (cfp) { int line = rb_vm_get_sourceline(cfp); - *path = cfp->iseq->body->location.path; - *absolute_path = cfp->iseq->body->location.absolute_path; + *path = rb_iseq_path(cfp->iseq); + *realpath = rb_iseq_realpath(cfp->iseq); return line; } else { *path = rb_fstring_cstr(""); - *absolute_path = *path; + *realpath = *path; return 1; } } @@ -7177,14 +7174,14 @@ static const rb_iseq_t * method_for_self(VALUE name, VALUE arg, rb_insn_func_t func, VALUE (*build)(rb_iseq_t *, LINK_ANCHOR *const, VALUE)) { - VALUE path, absolute_path; + VALUE path, realpath; accessor_args acc; acc.arg = arg; acc.func = func; - acc.line = caller_location(&path, &absolute_path); + acc.line = caller_location(&path, &realpath); return rb_iseq_new_with_opt((NODE *)IFUNC_NEW(build, (VALUE)&acc, 0), - rb_sym2str(name), path, absolute_path, + rb_sym2str(name), path, realpath, INT2FIX(acc.line), 0, ISEQ_TYPE_METHOD, 0); } @@ -7797,8 +7794,7 @@ ibf_dump_iseq_each(struct ibf_dump *dump, const rb_iseq_t *iseq) struct rb_iseq_constant_body dump_body; dump_body = *iseq->body; - dump_body.location.path = ibf_dump_object(dump, dump_body.location.path); - dump_body.location.absolute_path = ibf_dump_object(dump, dump_body.location.absolute_path); + dump_body.location.pathobj = ibf_dump_object(dump, dump_body.location.pathobj); /* TODO: freeze */ dump_body.location.base_label = ibf_dump_object(dump, dump_body.location.base_label); dump_body.location.label = ibf_dump_object(dump, dump_body.location.label); @@ -7847,8 +7843,7 @@ ibf_load_iseq_each(const struct ibf_load *load, rb_iseq_t *iseq, ibf_offset_t of RB_OBJ_WRITE(iseq, &load_body->mark_ary, iseq_mark_ary_create((int)body->mark_ary)); - RB_OBJ_WRITE(iseq, &load_body->location.path, ibf_load_location_str(load, body->location.path)); - RB_OBJ_WRITE(iseq, &load_body->location.absolute_path, ibf_load_location_str(load, body->location.absolute_path)); + RB_OBJ_WRITE(iseq, &load_body->location.pathobj, ibf_load_location_str(load, body->location.pathobj)); RB_OBJ_WRITE(iseq, &load_body->location.base_label, ibf_load_location_str(load, body->location.base_label)); RB_OBJ_WRITE(iseq, &load_body->location.label, ibf_load_location_str(load, body->location.label)); load_body->location.first_lineno = body->location.first_lineno; diff --git a/debug_counter.h b/debug_counter.h index 724dc3a257..f0f4e5ed0b 100644 --- a/debug_counter.h +++ b/debug_counter.h @@ -61,6 +61,11 @@ RB_DEBUG_COUNTER(obj_ary_embed) RB_DEBUG_COUNTER(obj_obj_ptr) RB_DEBUG_COUNTER(obj_obj_embed) + +/* load */ +RB_DEBUG_COUNTER(load_files) +RB_DEBUG_COUNTER(load_path_is_not_realpath) + #endif #ifndef RUBY_DEBUG_COUNTER_H diff --git a/gc.c b/gc.c index 77d84a7f91..9ff2da545c 100644 --- a/gc.c +++ b/gc.c @@ -9210,7 +9210,7 @@ rb_raw_iseq_info(char *buff, const int buff_size, const rb_iseq_t *iseq) if (iseq->body->location.label) { snprintf(buff, buff_size, "%s %s@%s:%d", buff, RSTRING_PTR(iseq->body->location.label), - RSTRING_PTR(iseq->body->location.path), + RSTRING_PTR(rb_iseq_path(iseq)), FIX2INT(iseq->body->location.first_lineno)); } } diff --git a/iseq.c b/iseq.c index bfdbeadfa9..0d66f5a603 100644 --- a/iseq.c +++ b/iseq.c @@ -107,16 +107,13 @@ rb_iseq_mark(const rb_iseq_t *iseq) { RUBY_MARK_ENTER("iseq"); - RUBY_GC_INFO("%s @ %s\n", RSTRING_PTR(iseq->body->location.label), RSTRING_PTR(iseq->body->location.path)); - if (iseq->body) { const struct rb_iseq_constant_body *body = iseq->body; RUBY_MARK_UNLESS_NULL(body->mark_ary); rb_gc_mark(body->location.label); rb_gc_mark(body->location.base_label); - rb_gc_mark(body->location.path); - RUBY_MARK_UNLESS_NULL(body->location.absolute_path); + rb_gc_mark(body->location.pathobj); RUBY_MARK_UNLESS_NULL((VALUE)body->parent_iseq); } @@ -216,17 +213,38 @@ iseq_alloc(void) return iseq; } -static rb_iseq_location_t * -iseq_location_setup(rb_iseq_t *iseq, VALUE path, VALUE absolute_path, VALUE name, VALUE first_lineno) +VALUE +rb_iseq_pathobj_new(VALUE path, VALUE realpath) { - rb_iseq_location_t *loc = &iseq->body->location; - RB_OBJ_WRITE(iseq, &loc->path, path); - if (RTEST(absolute_path) && rb_str_cmp(path, absolute_path) == 0) { - RB_OBJ_WRITE(iseq, &loc->absolute_path, path); + VALUE pathobj; + VM_ASSERT(RB_TYPE_P(path, T_STRING)); + VM_ASSERT(realpath == Qnil || RB_TYPE_P(realpath, T_STRING)); + + if (path == realpath || + (!NIL_P(realpath) && rb_str_cmp(path, realpath) == 0)) { + pathobj = rb_fstring(path); } else { - RB_OBJ_WRITE(iseq, &loc->absolute_path, absolute_path); + if (!NIL_P(realpath)) realpath = rb_fstring(realpath); + pathobj = rb_ary_new_from_args(2, rb_fstring(path), realpath); + rb_obj_freeze(pathobj); } + return pathobj; +} + +void +rb_iseq_pathobj_set(const rb_iseq_t *iseq, VALUE path, VALUE realpath) +{ + RB_OBJ_WRITE(iseq, &iseq->body->location.pathobj, + rb_iseq_pathobj_new(path, realpath)); +} + +static rb_iseq_location_t * +iseq_location_setup(rb_iseq_t *iseq, VALUE name, VALUE path, VALUE realpath, VALUE first_lineno) +{ + rb_iseq_location_t *loc = &iseq->body->location; + + rb_iseq_pathobj_set(iseq, path, realpath); RB_OBJ_WRITE(iseq, &loc->label, name); RB_OBJ_WRITE(iseq, &loc->base_label, name); loc->first_lineno = first_lineno; @@ -267,7 +285,7 @@ rb_iseq_add_mark_object(const rb_iseq_t *iseq, VALUE obj) static VALUE prepare_iseq_build(rb_iseq_t *iseq, - VALUE name, VALUE path, VALUE absolute_path, VALUE first_lineno, + VALUE name, VALUE path, VALUE realpath, VALUE first_lineno, const rb_iseq_t *parent, enum iseq_type type, const rb_compile_option_t *option) { @@ -281,9 +299,7 @@ prepare_iseq_build(rb_iseq_t *iseq, set_relation(iseq, parent); name = rb_fstring(name); - path = rb_fstring(path); - if (RTEST(absolute_path)) absolute_path = rb_fstring(absolute_path); - iseq_location_setup(iseq, path, absolute_path, name, first_lineno); + iseq_location_setup(iseq, name, path, realpath, first_lineno); if (iseq != iseq->body->local_iseq) { RB_OBJ_WRITE(iseq, &iseq->body->location.base_label, iseq->body->local_iseq->body->location.label); } @@ -311,7 +327,7 @@ prepare_iseq_build(rb_iseq_t *iseq, if (option->coverage_enabled) { VALUE coverages = rb_get_coverages(); if (RTEST(coverages)) { - coverage = rb_hash_lookup(coverages, path); + coverage = rb_hash_lookup(coverages, rb_iseq_path(iseq)); if (NIL_P(coverage)) coverage = Qfalse; } } @@ -329,8 +345,9 @@ cleanup_iseq_build(rb_iseq_t *iseq) compile_data_free(data); if (RTEST(err)) { + VALUE path = pathobj_path(iseq->body->location.pathobj); if (err == Qtrue) err = rb_exc_new_cstr(rb_eSyntaxError, "compile error"); - rb_funcallv(err, rb_intern("set_backtrace"), 1, &iseq->body->location.path); + rb_funcallv(err, rb_intern("set_backtrace"), 1, &path); rb_exc_raise(err); } return Qtrue; @@ -438,25 +455,25 @@ make_compile_option_value(rb_compile_option_t *option) } rb_iseq_t * -rb_iseq_new(NODE *node, VALUE name, VALUE path, VALUE absolute_path, +rb_iseq_new(NODE *node, VALUE name, VALUE path, VALUE realpath, const rb_iseq_t *parent, enum iseq_type type) { - return rb_iseq_new_with_opt(node, name, path, absolute_path, INT2FIX(0), parent, type, + return rb_iseq_new_with_opt(node, name, path, realpath, INT2FIX(0), parent, type, &COMPILE_OPTION_DEFAULT); } rb_iseq_t * -rb_iseq_new_top(NODE *node, VALUE name, VALUE path, VALUE absolute_path, const rb_iseq_t *parent) +rb_iseq_new_top(NODE *node, VALUE name, VALUE path, VALUE realpath, const rb_iseq_t *parent) { - return rb_iseq_new_with_opt(node, name, path, absolute_path, INT2FIX(0), parent, ISEQ_TYPE_TOP, + return rb_iseq_new_with_opt(node, name, path, realpath, INT2FIX(0), parent, ISEQ_TYPE_TOP, &COMPILE_OPTION_DEFAULT); } rb_iseq_t * -rb_iseq_new_main(NODE *node, VALUE path, VALUE absolute_path, const rb_iseq_t *parent) +rb_iseq_new_main(NODE *node, VALUE path, VALUE realpath, const rb_iseq_t *parent) { return rb_iseq_new_with_opt(node, rb_fstring_cstr("
"), - path, absolute_path, INT2FIX(0), + path, realpath, INT2FIX(0), parent, ISEQ_TYPE_MAIN, &COMPILE_OPTION_DEFAULT); } @@ -475,7 +492,7 @@ iseq_translate(rb_iseq_t *iseq) } rb_iseq_t * -rb_iseq_new_with_opt(NODE *node, VALUE name, VALUE path, VALUE absolute_path, +rb_iseq_new_with_opt(NODE *node, VALUE name, VALUE path, VALUE realpath, VALUE first_lineno, const rb_iseq_t *parent, enum iseq_type type, const rb_compile_option_t *option) { @@ -483,7 +500,7 @@ rb_iseq_new_with_opt(NODE *node, VALUE name, VALUE path, VALUE absolute_path, rb_iseq_t *iseq = iseq_alloc(); if (!option) option = &COMPILE_OPTION_DEFAULT; - prepare_iseq_build(iseq, name, path, absolute_path, first_lineno, parent, type, option); + prepare_iseq_build(iseq, name, path, realpath, first_lineno, parent, type, option); rb_iseq_compile_node(iseq, node); cleanup_iseq_build(iseq); @@ -542,7 +559,7 @@ iseq_load(VALUE data, const rb_iseq_t *parent, VALUE opt) rb_iseq_t *iseq = iseq_alloc(); VALUE magic, version1, version2, format_type, misc; - VALUE name, path, absolute_path, first_lineno; + VALUE name, path, realpath, first_lineno; VALUE type, body, locals, params, exception; st_data_t iseq_type; @@ -565,8 +582,8 @@ iseq_load(VALUE data, const rb_iseq_t *parent, VALUE opt) name = CHECK_STRING(rb_ary_entry(data, i++)); path = CHECK_STRING(rb_ary_entry(data, i++)); - absolute_path = rb_ary_entry(data, i++); - absolute_path = NIL_P(absolute_path) ? Qnil : CHECK_STRING(absolute_path); + realpath = rb_ary_entry(data, i++); + realpath = NIL_P(realpath) ? Qnil : CHECK_STRING(realpath); first_lineno = CHECK_INTEGER(rb_ary_entry(data, i++)); type = CHECK_SYMBOL(rb_ary_entry(data, i++)); @@ -584,7 +601,7 @@ iseq_load(VALUE data, const rb_iseq_t *parent, VALUE opt) make_compile_option(&option, opt); option.peephole_optimization = FALSE; /* because peephole optimization can modify original iseq */ - prepare_iseq_build(iseq, name, path, absolute_path, first_lineno, + prepare_iseq_build(iseq, name, path, realpath, first_lineno, parent, (enum iseq_type)iseq_type, &option); rb_iseq_build_from_ary(iseq, misc, locals, params, exception, body); @@ -612,7 +629,7 @@ rb_iseq_load(VALUE data, VALUE parent, VALUE opt) } rb_iseq_t * -rb_iseq_compile_with_option(VALUE src, VALUE file, VALUE absolute_path, VALUE line, const struct rb_block *base_block, VALUE opt) +rb_iseq_compile_with_option(VALUE src, VALUE file, VALUE realpath, VALUE line, const struct rb_block *base_block, VALUE opt) { rb_thread_t *th = GET_THREAD(); rb_iseq_t *iseq = NULL; @@ -652,7 +669,7 @@ rb_iseq_compile_with_option(VALUE src, VALUE file, VALUE absolute_path, VALUE li INITIALIZED VALUE label = parent ? parent->body->location.label : rb_fstring_cstr(""); - iseq = rb_iseq_new_with_opt(node, label, file, absolute_path, line, + iseq = rb_iseq_new_with_opt(node, label, file, realpath, line, parent, type, &option); } @@ -674,13 +691,19 @@ rb_iseq_compile_on_base(VALUE src, VALUE file, VALUE line, const struct rb_block VALUE rb_iseq_path(const rb_iseq_t *iseq) { - return iseq->body->location.path; + return pathobj_path(iseq->body->location.pathobj); +} + +VALUE +rb_iseq_realpath(const rb_iseq_t *iseq) +{ + return pathobj_realpath(iseq->body->location.pathobj); } VALUE rb_iseq_absolute_path(const rb_iseq_t *iseq) { - return iseq->body->location.absolute_path; + return rb_iseq_realpath(iseq); } VALUE @@ -967,7 +990,7 @@ iseqw_inspect(VALUE self) else { return rb_sprintf("<%s:%s@%s>", rb_obj_classname(self), - RSTRING_PTR(iseq->body->location.label), RSTRING_PTR(iseq->body->location.path)); + RSTRING_PTR(iseq->body->location.label), RSTRING_PTR(rb_iseq_path(iseq))); } } @@ -1019,7 +1042,7 @@ iseqw_path(VALUE self) static VALUE iseqw_absolute_path(VALUE self) { - return rb_iseq_absolute_path(iseqw_check(self)); + return rb_iseq_realpath(iseqw_check(self)); } /* Returns the label of this instruction sequence. @@ -1484,7 +1507,7 @@ iseq_inspect(const rb_iseq_t *iseq) return rb_sprintf("#"); } else { - return rb_sprintf("#", RSTRING_PTR(iseq->body->location.label), RSTRING_PTR(iseq->body->location.path)); + return rb_sprintf("#", RSTRING_PTR(iseq->body->location.label), RSTRING_PTR(rb_iseq_path(iseq))); } } @@ -2087,8 +2110,8 @@ iseq_data_to_ary(const rb_iseq_t *iseq) rb_ary_push(val, INT2FIX(1)); rb_ary_push(val, misc); rb_ary_push(val, iseq->body->location.label); - rb_ary_push(val, iseq->body->location.path); - rb_ary_push(val, iseq->body->location.absolute_path); + rb_ary_push(val, rb_iseq_path(iseq)); + rb_ary_push(val, rb_iseq_realpath(iseq)); rb_ary_push(val, iseq->body->location.first_lineno); rb_ary_push(val, type); rb_ary_push(val, locals); diff --git a/iseq.h b/iseq.h index 6a5cb8bdad..3f3ed8a195 100644 --- a/iseq.h +++ b/iseq.h @@ -112,8 +112,7 @@ VALUE rb_iseqw_line_trace_specify(VALUE iseqval, VALUE pos, VALUE set); VALUE rb_iseqw_new(const rb_iseq_t *iseq); const rb_iseq_t *rb_iseqw_to_iseq(VALUE iseqw); -VALUE rb_iseq_path(const rb_iseq_t *iseq); -VALUE rb_iseq_absolute_path(const rb_iseq_t *iseq); +VALUE rb_iseq_absolute_path(const rb_iseq_t *iseq); /* obsolete */ VALUE rb_iseq_label(const rb_iseq_t *iseq); VALUE rb_iseq_base_label(const rb_iseq_t *iseq); VALUE rb_iseq_first_lineno(const rb_iseq_t *iseq); diff --git a/proc.c b/proc.c index ba67e3ef6d..8ad703cbd3 100644 --- a/proc.c +++ b/proc.c @@ -276,13 +276,9 @@ static void binding_mark(void *ptr) { rb_binding_t *bind = ptr; - RUBY_MARK_ENTER("binding"); - block_mark(&bind->block); - - RUBY_MARK_UNLESS_NULL(bind->path); - + rb_gc_mark(bind->pathobj); RUBY_MARK_LEAVE("binding"); } @@ -320,7 +316,7 @@ binding_dup(VALUE self) GetBindingPtr(self, src); GetBindingPtr(bindval, dst); dst->block = src->block; - dst->path = src->path; + dst->pathobj = src->pathobj; dst->first_lineno = src->first_lineno; return bindval; } @@ -1073,7 +1069,7 @@ iseq_location(const rb_iseq_t *iseq) if (!iseq) return Qnil; rb_iseq_check(iseq); - loc[0] = iseq->body->location.path; + loc[0] = rb_iseq_path(iseq); loc[1] = iseq->body->location.first_lineno; return rb_ary_new4(2, loc); @@ -1225,7 +1221,7 @@ proc_to_s_(VALUE self, const rb_proc_t *proc) { const rb_iseq_t *iseq = rb_iseq_check(block->as.captured.code.iseq); rb_str_catf(str, "%p@%"PRIsVALUE":%d", (void *)self, - iseq->body->location.path, + rb_iseq_path(iseq), FIX2INT(iseq->body->location.first_lineno)); } break; @@ -2777,12 +2773,12 @@ proc_binding(VALUE self) if (iseq) { rb_iseq_check(iseq); - bind->path = iseq->body->location.path; + bind->pathobj = iseq->body->location.pathobj; bind->first_lineno = FIX2INT(rb_iseq_first_lineno(iseq)); } else { - bind->path = Qnil; - bind->first_lineno = 0; + bind->pathobj = rb_iseq_pathobj_new(rb_fstring_cstr("(binding)"), Qnil); + bind->first_lineno = 1; } return bindval; diff --git a/vm.c b/vm.c index d90cb2f472..3b9fd5ec95 100644 --- a/vm.c +++ b/vm.c @@ -902,7 +902,7 @@ rb_vm_make_binding(rb_thread_t *th, const rb_control_frame_t *src_cfp) vm_bind_update_env(bind, envval); bind->block.as.captured.self = cfp->self; bind->block.as.captured.code.iseq = cfp->iseq; - bind->path = ruby_level_cfp->iseq->body->location.path; + bind->pathobj = ruby_level_cfp->iseq->body->location.pathobj; bind->first_lineno = rb_vm_get_sourceline(ruby_level_cfp); return bindval; @@ -911,7 +911,9 @@ rb_vm_make_binding(rb_thread_t *th, const rb_control_frame_t *src_cfp) const VALUE * rb_binding_add_dynavars(rb_binding_t *bind, int dyncount, const ID *dynvars) { - VALUE envval, path = bind->path; + VALUE envval, pathobj = bind->pathobj; + VALUE path = pathobj_path(pathobj); + VALUE realpath = pathobj_realpath(pathobj); const struct rb_block *base_block; const rb_env_t *env; rb_thread_t *th = GET_THREAD(); @@ -932,7 +934,7 @@ rb_binding_add_dynavars(rb_binding_t *bind, int dyncount, const ID *dynvars) node = NEW_NODE(NODE_SCOPE, dyns, 0, 0); if (base_iseq) { - iseq = rb_iseq_new(node, base_iseq->body->location.label, path, path, base_iseq, ISEQ_TYPE_EVAL); + iseq = rb_iseq_new(node, base_iseq->body->location.label, path, realpath, base_iseq, ISEQ_TYPE_EVAL); } else { VALUE tempstr = rb_fstring_cstr(""); @@ -1234,7 +1236,7 @@ rb_sourcefilename(void) rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(th, th->ec.cfp); if (cfp) { - return cfp->iseq->body->location.path; + return rb_iseq_path(cfp->iseq); } else { return Qnil; @@ -1248,7 +1250,7 @@ rb_sourcefile(void) rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(th, th->ec.cfp); if (cfp) { - return RSTRING_PTR(cfp->iseq->body->location.path); + return RSTRING_PTR(rb_iseq_path(cfp->iseq)); } else { return 0; @@ -1277,7 +1279,7 @@ rb_source_location(int *pline) if (cfp) { if (pline) *pline = rb_vm_get_sourceline(cfp); - return cfp->iseq->body->location.path; + return rb_iseq_path(cfp->iseq); } else { if (pline) *pline = 0; @@ -2060,7 +2062,7 @@ rb_thread_current_status(const rb_thread_t *th) const rb_iseq_t *iseq = cfp->iseq; int line_no = rb_vm_get_sourceline(cfp); str = rb_sprintf("%"PRIsVALUE":%d:in `%"PRIsVALUE"'", - iseq->body->location.path, line_no, iseq->body->location.label); + rb_iseq_path(iseq), line_no, iseq->body->location.label); } } else if ((me = rb_vm_frame_method_entry(cfp)) && me->def->original_id) { @@ -3085,7 +3087,8 @@ rb_vm_set_progname(VALUE filename) rb_thread_t *th = GET_VM()->main_thread; rb_control_frame_t *cfp = (void *)(th->ec.stack + th->ec.stack_size); --cfp; - RB_OBJ_WRITE(cfp->iseq, &cfp->iseq->body->location.path, filename); + + rb_iseq_pathobj_set(cfp->iseq, rb_str_dup(filename), rb_iseq_realpath(cfp->iseq)); } extern const struct st_hash_type rb_fstring_hash_type; diff --git a/vm_backtrace.c b/vm_backtrace.c index 5c1cca5aef..ac9a59e4ba 100644 --- a/vm_backtrace.c +++ b/vm_backtrace.c @@ -232,7 +232,7 @@ location_path(rb_backtrace_location_t *loc) switch (loc->type) { case LOCATION_TYPE_ISEQ: case LOCATION_TYPE_ISEQ_CALCED: - return loc->body.iseq.iseq->body->location.path; + return rb_iseq_path(loc->body.iseq.iseq); case LOCATION_TYPE_CFUNC: if (loc->body.cfunc.prev_loc) { return location_path(loc->body.cfunc.prev_loc); @@ -260,20 +260,20 @@ location_path_m(VALUE self) } static VALUE -location_absolute_path(rb_backtrace_location_t *loc) +location_realpath(rb_backtrace_location_t *loc) { switch (loc->type) { case LOCATION_TYPE_ISEQ: case LOCATION_TYPE_ISEQ_CALCED: - return loc->body.iseq.iseq->body->location.absolute_path; + return rb_iseq_realpath(loc->body.iseq.iseq); case LOCATION_TYPE_CFUNC: if (loc->body.cfunc.prev_loc) { - return location_absolute_path(loc->body.cfunc.prev_loc); + return location_realpath(loc->body.cfunc.prev_loc); } return Qnil; case LOCATION_TYPE_IFUNC: default: - rb_bug("location_absolute_path: unreachable"); + rb_bug("location_realpath: unreachable"); UNREACHABLE; } } @@ -286,7 +286,7 @@ location_absolute_path(rb_backtrace_location_t *loc) static VALUE location_absolute_path_m(VALUE self) { - return location_absolute_path(location_ptr(self)); + return location_realpath(location_ptr(self)); } static VALUE @@ -314,20 +314,20 @@ location_to_str(rb_backtrace_location_t *loc) switch (loc->type) { case LOCATION_TYPE_ISEQ: - file = loc->body.iseq.iseq->body->location.path; + file = rb_iseq_path(loc->body.iseq.iseq); name = loc->body.iseq.iseq->body->location.label; lineno = loc->body.iseq.lineno.lineno = calc_lineno(loc->body.iseq.iseq, loc->body.iseq.lineno.pc); loc->type = LOCATION_TYPE_ISEQ_CALCED; break; case LOCATION_TYPE_ISEQ_CALCED: - file = loc->body.iseq.iseq->body->location.path; + file = rb_iseq_path(loc->body.iseq.iseq); lineno = loc->body.iseq.lineno.lineno; name = loc->body.iseq.iseq->body->location.label; break; case LOCATION_TYPE_CFUNC: if (loc->body.cfunc.prev_loc) { - file = loc->body.cfunc.prev_loc->body.iseq.iseq->body->location.path; + file = rb_iseq_path(loc->body.cfunc.prev_loc->body.iseq.iseq); lineno = location_lineno(loc->body.cfunc.prev_loc); } else { @@ -686,7 +686,7 @@ oldbt_iter_iseq(void *ptr, const rb_control_frame_t *cfp) const rb_iseq_t *iseq = cfp->iseq; const VALUE *pc = cfp->pc; struct oldbt_arg *arg = (struct oldbt_arg *)ptr; - VALUE file = arg->filename = iseq->body->location.path; + VALUE file = arg->filename = rb_iseq_path(iseq); VALUE name = iseq->body->location.label; int lineno = arg->lineno = calc_lineno(iseq, pc); @@ -1314,7 +1314,7 @@ VALUE rb_profile_frame_absolute_path(VALUE frame) { const rb_iseq_t *iseq = frame2iseq(frame); - return iseq ? rb_iseq_absolute_path(iseq) : Qnil; + return iseq ? rb_iseq_realpath(iseq) : Qnil; } VALUE diff --git a/vm_core.h b/vm_core.h index 21136a8874..6a5f10d0bd 100644 --- a/vm_core.h +++ b/vm_core.h @@ -261,13 +261,39 @@ struct rb_call_cache { #define GetCoreDataFromValue(obj, type, ptr) ((ptr) = CoreDataFromValue((obj), type)) typedef struct rb_iseq_location_struct { - VALUE path; - VALUE absolute_path; - VALUE base_label; - VALUE label; + VALUE pathobj; /* String (path) or Array [path, realpath]. Frozen. */ + VALUE base_label; /* String */ + VALUE label; /* String */ VALUE first_lineno; /* TODO: may be unsigned short */ } rb_iseq_location_t; +#define PATHOBJ_PATH 0 +#define PATHOBJ_REALPATH 1 + +static inline VALUE +pathobj_path(VALUE pathobj) +{ + if (RB_TYPE_P(pathobj, T_STRING)) { + return pathobj; + } + else { + VM_ASSERT(RB_TYPE_P(pathobj, T_ARRAY)); + return RARRAY_AREF(pathobj, PATHOBJ_PATH); + } +} + +static inline VALUE +pathobj_realpath(VALUE pathobj) +{ + if (RB_TYPE_P(pathobj, T_STRING)) { + return pathobj; + } + else { + VM_ASSERT(RB_TYPE_P(pathobj, T_ARRAY)); + return RARRAY_AREF(pathobj, PATHOBJ_REALPATH); + } +} + struct rb_iseq_constant_body { enum iseq_type { ISEQ_TYPE_TOP, @@ -842,16 +868,16 @@ typedef enum { RUBY_SYMBOL_EXPORT_BEGIN /* node -> iseq */ -rb_iseq_t *rb_iseq_new (NODE *node, VALUE name, VALUE path, VALUE absolute_path, const rb_iseq_t *parent, enum iseq_type); -rb_iseq_t *rb_iseq_new_top (NODE *node, VALUE name, VALUE path, VALUE absolute_path, const rb_iseq_t *parent); -rb_iseq_t *rb_iseq_new_main (NODE *node, VALUE path, VALUE absolute_path, const rb_iseq_t *parent); -rb_iseq_t *rb_iseq_new_with_opt(NODE* node, VALUE name, VALUE path, VALUE absolute_path, VALUE first_lineno, +rb_iseq_t *rb_iseq_new (NODE *node, VALUE name, VALUE path, VALUE realpath, const rb_iseq_t *parent, enum iseq_type); +rb_iseq_t *rb_iseq_new_top (NODE *node, VALUE name, VALUE path, VALUE realpath, const rb_iseq_t *parent); +rb_iseq_t *rb_iseq_new_main (NODE *node, VALUE path, VALUE realpath, const rb_iseq_t *parent); +rb_iseq_t *rb_iseq_new_with_opt(NODE* node, VALUE name, VALUE path, VALUE realpath, VALUE first_lineno, const rb_iseq_t *parent, enum iseq_type, const rb_compile_option_t*); /* src -> iseq */ rb_iseq_t *rb_iseq_compile(VALUE src, VALUE file, VALUE line); rb_iseq_t *rb_iseq_compile_on_base(VALUE src, VALUE file, VALUE line, const struct rb_block *base_block); -rb_iseq_t *rb_iseq_compile_with_option(VALUE src, VALUE file, VALUE absolute_path, VALUE line, const struct rb_block *base_block, VALUE opt); +rb_iseq_t *rb_iseq_compile_with_option(VALUE src, VALUE file, VALUE realpath, VALUE line, const struct rb_block *base_block, VALUE opt); VALUE rb_iseq_disasm(const rb_iseq_t *iseq); int rb_iseq_disasm_insn(VALUE str, const VALUE *iseqval, size_t pos, const rb_iseq_t *iseq, VALUE child); @@ -889,7 +915,7 @@ extern const rb_data_type_t ruby_binding_data_type; typedef struct { struct rb_block block; - VALUE path; + VALUE pathobj; unsigned short first_lineno; } rb_binding_t; @@ -1417,7 +1443,13 @@ NORETURN(void rb_bug_context(const void *, const char *fmt, ...)); RUBY_SYMBOL_EXPORT_BEGIN VALUE rb_iseq_eval(const rb_iseq_t *iseq); VALUE rb_iseq_eval_main(const rb_iseq_t *iseq); +VALUE rb_iseq_path(const rb_iseq_t *iseq); +VALUE rb_iseq_realpath(const rb_iseq_t *iseq); RUBY_SYMBOL_EXPORT_END + +VALUE rb_iseq_pathobj_new(VALUE path, VALUE realpath); +void rb_iseq_pathobj_set(const rb_iseq_t *iseq, VALUE path, VALUE realpath); + int rb_thread_method_id_and_class(rb_thread_t *th, ID *idp, ID *called_idp, VALUE *klassp); VALUE rb_vm_invoke_proc(rb_thread_t *th, rb_proc_t *proc, int argc, const VALUE *argv, VALUE block_handler); diff --git a/vm_dump.c b/vm_dump.c index f249b7efec..8d34631931 100644 --- a/vm_dump.c +++ b/vm_dump.c @@ -107,7 +107,7 @@ control_frame_dump(rb_thread_t *th, rb_control_frame_t *cfp) iseq_name = RSTRING_PTR(cfp->iseq->body->location.label); line = rb_vm_get_sourceline(cfp); if (line) { - snprintf(posbuf, MAX_POSBUF, "%s:%d", RSTRING_PTR(cfp->iseq->body->location.path), line); + snprintf(posbuf, MAX_POSBUF, "%s:%d", RSTRING_PTR(rb_iseq_path(cfp->iseq)), line); } } } diff --git a/vm_eval.c b/vm_eval.c index 345eba753a..86541cc845 100644 --- a/vm_eval.c +++ b/vm_eval.c @@ -1296,20 +1296,20 @@ eval_string_with_cref(VALUE self, VALUE src, VALUE scope, rb_cref_t *const cref_ rb_cref_t *cref = cref_arg; rb_binding_t *bind = 0; const rb_iseq_t *iseq; - VALUE absolute_path = Qnil; + VALUE realpath = Qnil; VALUE fname; if (file != Qundef) { - absolute_path = file; + realpath = file; } if (!NIL_P(scope)) { bind = Check_TypedStruct(scope, &ruby_binding_data_type); - if (NIL_P(absolute_path) && !NIL_P(bind->path)) { - file = bind->path; + if (NIL_P(realpath)) { + file = pathobj_path(bind->pathobj); + realpath = pathobj_realpath(bind->pathobj); line = bind->first_lineno; - absolute_path = rb_current_realfilepath(); } base_block = &bind->block; } @@ -1332,13 +1332,8 @@ eval_string_with_cref(VALUE self, VALUE src, VALUE scope, rb_cref_t *const cref_ fname = rb_usascii_str_new_cstr("(eval)"); } - if (RTEST(fname)) - fname = rb_fstring(fname); - if (RTEST(absolute_path)) - absolute_path = rb_fstring(absolute_path); - /* make eval iseq */ - iseq = rb_iseq_compile_with_option(src, fname, absolute_path, INT2FIX(line), base_block, Qnil); + iseq = rb_iseq_compile_with_option(src, fname, realpath, INT2FIX(line), base_block, Qnil); if (!iseq) { rb_exc_raise(adjust_backtrace_in_eval(th, th->errinfo)); @@ -2180,7 +2175,7 @@ rb_current_realfilepath(void) rb_thread_t *th = GET_THREAD(); rb_control_frame_t *cfp = th->ec.cfp; cfp = vm_get_ruby_level_caller_cfp(th, RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp)); - if (cfp != 0) return cfp->iseq->body->location.absolute_path; + if (cfp != 0) return rb_iseq_realpath(cfp->iseq); return Qnil; } diff --git a/vm_method.c b/vm_method.c index 16c9a277e3..3be7213678 100644 --- a/vm_method.c +++ b/vm_method.c @@ -267,7 +267,7 @@ method_definition_set(const rb_method_entry_t *me, rb_method_definition_t *def, cfp = rb_vm_get_ruby_level_next_cfp(th, th->ec.cfp); if (cfp && (line = rb_vm_get_sourceline(cfp))) { - VALUE location = rb_ary_new3(2, cfp->iseq->body->location.path, INT2FIX(line)); + VALUE location = rb_ary_new3(2, rb_iseq_path(cfp->iseq), INT2FIX(line)); RB_OBJ_WRITE(me, &def->body.attr.location, rb_ary_freeze(location)); } else { @@ -558,7 +558,7 @@ rb_method_entry_make(VALUE klass, ID mid, VALUE defined_class, rb_method_visibil break; } if (iseq) { - rb_compile_warning(RSTRING_PTR(iseq->body->location.path), + rb_compile_warning(RSTRING_PTR(rb_iseq_path(iseq)), FIX2INT(iseq->body->location.first_lineno), "previous definition of %"PRIsVALUE" was here", rb_id2str(old_def->original_id)); diff --git a/vm_trace.c b/vm_trace.c index 2f78284805..b047b73e22 100644 --- a/vm_trace.c +++ b/vm_trace.c @@ -753,7 +753,7 @@ fill_path_and_lineno(rb_trace_arg_t *trace_arg) rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(trace_arg->th, trace_arg->cfp); if (cfp) { - trace_arg->path = cfp->iseq->body->location.path; + trace_arg->path = rb_iseq_path(cfp->iseq); trace_arg->lineno = rb_vm_get_sourceline(cfp); } else {