aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2017-06-01 00:05:33 +0000
committerko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2017-06-01 00:05:33 +0000
commitd4e28e8fd8906ad1051d61cfc01164cb3629dbb5 (patch)
tree3c6d414535225ab0eaba19095da58f0fd26371b5
parent9664b3133048debca63163ebf01f81d916da4a1b (diff)
downloadruby-d4e28e8fd8906ad1051d61cfc01164cb3629dbb5.tar.gz
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
-rw-r--r--compile.c35
-rw-r--r--debug_counter.h5
-rw-r--r--gc.c2
-rw-r--r--iseq.c99
-rw-r--r--iseq.h3
-rw-r--r--proc.c18
-rw-r--r--vm.c19
-rw-r--r--vm_backtrace.c22
-rw-r--r--vm_core.h52
-rw-r--r--vm_dump.c2
-rw-r--r--vm_eval.c19
-rw-r--r--vm_method.c4
-rw-r--r--vm_trace.c2
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 "<L%03d>"
-#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("<compiled>");
- *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("<main>"),
- 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("<compiled>");
- 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("#<ISeq: uninitialized>");
}
else {
- return rb_sprintf("#<ISeq:%s@%s>", RSTRING_PTR(iseq->body->location.label), RSTRING_PTR(iseq->body->location.path));
+ return rb_sprintf("#<ISeq:%s@%s>", 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("<temp>");
@@ -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 {