mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
iseq.c: struct accessors
* iseq.c (rb_method_for_self_aref, rb_method_for_self_aset): call accessor functions directly, not to be affected by [] and []= methods. [ruby-core:66846] [Bug #10601] * struct.c (define_aref_method, define_aset_method): ditto. * vm_insnhelper.c (rb_vm_opt_struct_aref, rb_vm_opt_struct_aset): direct accessors of Struct. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@48864 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
97628bff12
commit
e4717eaa4c
5 changed files with 84 additions and 32 deletions
11
ChangeLog
11
ChangeLog
|
@ -1,3 +1,14 @@
|
||||||
|
Tue Dec 16 15:18:23 2014 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||||
|
|
||||||
|
* iseq.c (rb_method_for_self_aref, rb_method_for_self_aset): call
|
||||||
|
accessor functions directly, not to be affected by [] and []=
|
||||||
|
methods. [ruby-core:66846] [Bug #10601]
|
||||||
|
|
||||||
|
* struct.c (define_aref_method, define_aset_method): ditto.
|
||||||
|
|
||||||
|
* vm_insnhelper.c (rb_vm_opt_struct_aref, rb_vm_opt_struct_aset):
|
||||||
|
direct accessors of Struct.
|
||||||
|
|
||||||
Tue Dec 16 12:01:29 2014 Koichi Sasada <ko1@atdot.net>
|
Tue Dec 16 12:01:29 2014 Koichi Sasada <ko1@atdot.net>
|
||||||
|
|
||||||
* test/ruby/test_process.rb (test_deadlock_by_signal_at_forking):
|
* test/ruby/test_process.rb (test_deadlock_by_signal_at_forking):
|
||||||
|
|
49
iseq.c
49
iseq.c
|
@ -569,14 +569,14 @@ caller_location(VALUE *path)
|
||||||
}
|
}
|
||||||
|
|
||||||
VALUE
|
VALUE
|
||||||
rb_method_for_self_aref(VALUE name, VALUE arg)
|
rb_method_for_self_aref(VALUE name, VALUE arg, rb_insn_func_t func)
|
||||||
{
|
{
|
||||||
|
rb_control_frame_t *FUNC_FASTCALL(rb_vm_struct_aref_c)(rb_thread_t *, rb_control_frame_t *);
|
||||||
VALUE iseqval = iseq_alloc(rb_cISeq);
|
VALUE iseqval = iseq_alloc(rb_cISeq);
|
||||||
rb_iseq_t *iseq;
|
rb_iseq_t *iseq;
|
||||||
VALUE path, lineno = caller_location(&path);
|
VALUE path, lineno = caller_location(&path);
|
||||||
VALUE parent = 0;
|
VALUE parent = 0;
|
||||||
VALUE misc, locals, params, exception, body, send_arg;
|
VALUE misc, locals, params, exception, body, send_arg;
|
||||||
int flag = VM_CALL_FCALL | VM_CALL_ARGS_SIMPLE;
|
|
||||||
|
|
||||||
GetISeqPtr(iseqval, iseq);
|
GetISeqPtr(iseqval, iseq);
|
||||||
iseq->self = iseqval;
|
iseq->self = iseqval;
|
||||||
|
@ -593,18 +593,15 @@ rb_method_for_self_aref(VALUE name, VALUE arg)
|
||||||
#define ADD(a) rb_ary_push(body, rb_obj_hide(a))
|
#define ADD(a) rb_ary_push(body, rb_obj_hide(a))
|
||||||
/* def name; self[arg]; end */
|
/* def name; self[arg]; end */
|
||||||
ADD(lineno);
|
ADD(lineno);
|
||||||
ADD(rb_ary_new3(1, S(putself)));
|
|
||||||
ADD(rb_ary_new3(2, S(putobject), arg));
|
ADD(rb_ary_new3(2, S(putobject), arg));
|
||||||
|
|
||||||
/* {:mid=>:[], :flag=>264, :blockptr=>nil, :orig_argc=>1} */
|
#if SIZEOF_VALUE <= SIZEOF_LONG
|
||||||
send_arg = rb_hash_new();
|
send_arg = LONG2NUM((SIGNED_VALUE)func);
|
||||||
rb_hash_aset(send_arg, S(mid), ID2SYM(idAREF));
|
#else
|
||||||
rb_hash_aset(send_arg, S(flag), INT2FIX(flag));
|
send_arg = LL2NUM((SIGNED_VALUE)func);
|
||||||
rb_hash_aset(send_arg, S(blockptr), Qnil);
|
#endif
|
||||||
rb_hash_aset(send_arg, S(orig_argc), INT2FIX(1));
|
send_arg = rb_ary_new3(2, S(opt_call_c_function), send_arg);
|
||||||
|
ADD(send_arg);
|
||||||
/* we do not want opt_aref for struct */
|
|
||||||
ADD(rb_ary_new3(2, S(opt_send_without_block), send_arg));
|
|
||||||
ADD(rb_ary_new3(1, S(leave)));
|
ADD(rb_ary_new3(1, S(leave)));
|
||||||
#undef S
|
#undef S
|
||||||
#undef ADD
|
#undef ADD
|
||||||
|
@ -613,19 +610,19 @@ rb_method_for_self_aref(VALUE name, VALUE arg)
|
||||||
cleanup_iseq_build(iseq);
|
cleanup_iseq_build(iseq);
|
||||||
|
|
||||||
rb_ary_clear(body);
|
rb_ary_clear(body);
|
||||||
|
rb_ary_clear(send_arg);
|
||||||
|
|
||||||
return iseqval;
|
return iseqval;
|
||||||
}
|
}
|
||||||
|
|
||||||
VALUE
|
VALUE
|
||||||
rb_method_for_self_aset(VALUE name, VALUE arg)
|
rb_method_for_self_aset(VALUE name, VALUE arg, rb_insn_func_t func)
|
||||||
{
|
{
|
||||||
VALUE iseqval = iseq_alloc(rb_cISeq);
|
VALUE iseqval = iseq_alloc(rb_cISeq);
|
||||||
rb_iseq_t *iseq;
|
rb_iseq_t *iseq;
|
||||||
VALUE path, lineno = caller_location(&path);
|
VALUE path, lineno = caller_location(&path);
|
||||||
VALUE parent = 0;
|
VALUE parent = 0;
|
||||||
VALUE misc, locals, params, exception, body, send_arg;
|
VALUE misc, locals, params, exception, body, send_arg;
|
||||||
int flag = VM_CALL_FCALL | VM_CALL_ARGS_SIMPLE;
|
|
||||||
|
|
||||||
GetISeqPtr(iseqval, iseq);
|
GetISeqPtr(iseqval, iseq);
|
||||||
iseq->self = iseqval;
|
iseq->self = iseqval;
|
||||||
|
@ -641,26 +638,21 @@ rb_method_for_self_aset(VALUE name, VALUE arg)
|
||||||
locals = rb_obj_hide(rb_ary_new3(1, S(val)));
|
locals = rb_obj_hide(rb_ary_new3(1, S(val)));
|
||||||
params = rb_hash_new();
|
params = rb_hash_new();
|
||||||
exception = rb_ary_tmp_new(0); /* empty */
|
exception = rb_ary_tmp_new(0); /* empty */
|
||||||
body = rb_ary_tmp_new(9);
|
body = rb_ary_tmp_new(6);
|
||||||
|
|
||||||
rb_hash_aset(params, S(lead_num), INT2FIX(1));
|
rb_hash_aset(params, S(lead_num), INT2FIX(1));
|
||||||
|
|
||||||
ADD(lineno);
|
ADD(lineno);
|
||||||
ADD(rb_ary_new3(1, S(putnil)));
|
|
||||||
ADD(rb_ary_new3(1, S(putself)));
|
|
||||||
ADD(rb_ary_new3(2, S(putobject), arg));
|
|
||||||
ADD(rb_ary_new3(3, S(getlocal), INT2FIX(2), INT2FIX(0)));
|
ADD(rb_ary_new3(3, S(getlocal), INT2FIX(2), INT2FIX(0)));
|
||||||
ADD(rb_ary_new3(2, S(setn), INT2FIX(3)));
|
ADD(rb_ary_new3(2, S(putobject), arg));
|
||||||
|
|
||||||
/* {:mid=>:[]=, :flag=>264, :blockptr=>nil, :orig_argc=>2} */
|
#if SIZEOF_VALUE <= SIZEOF_LONG
|
||||||
send_arg = rb_hash_new();
|
send_arg = LONG2NUM((SIGNED_VALUE)func);
|
||||||
rb_hash_aset(send_arg, S(mid), ID2SYM(idASET));
|
#else
|
||||||
rb_hash_aset(send_arg, S(flag), INT2FIX(flag));
|
send_arg = LL2NUM((SIGNED_VALUE)func);
|
||||||
rb_hash_aset(send_arg, S(blockptr), Qnil);
|
#endif
|
||||||
rb_hash_aset(send_arg, S(orig_argc), INT2FIX(2));
|
send_arg = rb_ary_new3(2, S(opt_call_c_function), send_arg);
|
||||||
|
ADD(send_arg);
|
||||||
/* we do not want opt_aset for struct */
|
|
||||||
ADD(rb_ary_new3(2, S(opt_send_without_block), send_arg));
|
|
||||||
|
|
||||||
ADD(rb_ary_new3(1, S(pop)));
|
ADD(rb_ary_new3(1, S(pop)));
|
||||||
ADD(rb_ary_new3(1, S(leave)));
|
ADD(rb_ary_new3(1, S(leave)));
|
||||||
|
@ -671,6 +663,7 @@ rb_method_for_self_aset(VALUE name, VALUE arg)
|
||||||
cleanup_iseq_build(iseq);
|
cleanup_iseq_build(iseq);
|
||||||
|
|
||||||
rb_ary_clear(body);
|
rb_ary_clear(body);
|
||||||
|
rb_ary_clear(send_arg);
|
||||||
|
|
||||||
return iseqval;
|
return iseqval;
|
||||||
}
|
}
|
||||||
|
|
10
struct.c
10
struct.c
|
@ -13,8 +13,8 @@
|
||||||
#include "vm_core.h"
|
#include "vm_core.h"
|
||||||
#include "method.h"
|
#include "method.h"
|
||||||
|
|
||||||
VALUE rb_method_for_self_aref(VALUE name, VALUE arg);
|
VALUE rb_method_for_self_aref(VALUE name, VALUE arg, rb_insn_func_t func);
|
||||||
VALUE rb_method_for_self_aset(VALUE name, VALUE arg);
|
VALUE rb_method_for_self_aset(VALUE name, VALUE arg, rb_insn_func_t func);
|
||||||
|
|
||||||
VALUE rb_cStruct;
|
VALUE rb_cStruct;
|
||||||
static ID id_members;
|
static ID id_members;
|
||||||
|
@ -175,7 +175,8 @@ new_struct(VALUE name, VALUE super)
|
||||||
static void
|
static void
|
||||||
define_aref_method(VALUE nstr, VALUE name, VALUE off)
|
define_aref_method(VALUE nstr, VALUE name, VALUE off)
|
||||||
{
|
{
|
||||||
VALUE iseqval = rb_method_for_self_aref(name, off);
|
rb_control_frame_t *FUNC_FASTCALL(rb_vm_opt_struct_aref)(rb_thread_t *, rb_control_frame_t *);
|
||||||
|
VALUE iseqval = rb_method_for_self_aref(name, off, rb_vm_opt_struct_aref);
|
||||||
rb_iseq_t *iseq = DATA_PTR(iseqval);
|
rb_iseq_t *iseq = DATA_PTR(iseqval);
|
||||||
|
|
||||||
rb_add_method(nstr, SYM2ID(name), VM_METHOD_TYPE_ISEQ, iseq, NOEX_PUBLIC);
|
rb_add_method(nstr, SYM2ID(name), VM_METHOD_TYPE_ISEQ, iseq, NOEX_PUBLIC);
|
||||||
|
@ -185,7 +186,8 @@ define_aref_method(VALUE nstr, VALUE name, VALUE off)
|
||||||
static void
|
static void
|
||||||
define_aset_method(VALUE nstr, VALUE name, VALUE off)
|
define_aset_method(VALUE nstr, VALUE name, VALUE off)
|
||||||
{
|
{
|
||||||
VALUE iseqval = rb_method_for_self_aset(name, off);
|
rb_control_frame_t *FUNC_FASTCALL(rb_vm_opt_struct_aset)(rb_thread_t *, rb_control_frame_t *);
|
||||||
|
VALUE iseqval = rb_method_for_self_aset(name, off, rb_vm_opt_struct_aset);
|
||||||
rb_iseq_t *iseq = DATA_PTR(iseqval);
|
rb_iseq_t *iseq = DATA_PTR(iseqval);
|
||||||
|
|
||||||
rb_add_method(nstr, SYM2ID(name), VM_METHOD_TYPE_ISEQ, iseq, NOEX_PUBLIC);
|
rb_add_method(nstr, SYM2ID(name), VM_METHOD_TYPE_ISEQ, iseq, NOEX_PUBLIC);
|
||||||
|
|
|
@ -195,6 +195,39 @@ module TestStruct
|
||||||
assert_equal(:foo, o[25])
|
assert_equal(:foo, o[25])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_overridden_aset
|
||||||
|
bug10601 = '[ruby-core:66846] [Bug #10601]: should not be affected by []= method'
|
||||||
|
|
||||||
|
struct = Class.new(Struct.new(*(:a..:z), :result)) do
|
||||||
|
def []=(*args)
|
||||||
|
raise args.inspect
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
obj = struct.new
|
||||||
|
assert_nothing_raised(RuntimeError, bug10601) do
|
||||||
|
obj.result = 42
|
||||||
|
end
|
||||||
|
assert_equal(42, obj.result, bug10601)
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_overridden_aref
|
||||||
|
bug10601 = '[ruby-core:66846] [Bug #10601]: should not be affected by [] method'
|
||||||
|
|
||||||
|
struct = Class.new(Struct.new(*(:a..:z), :result)) do
|
||||||
|
def [](*args)
|
||||||
|
raise args.inspect
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
obj = struct.new
|
||||||
|
obj.result = 42
|
||||||
|
result = assert_nothing_raised(RuntimeError, bug10601) do
|
||||||
|
break obj.result
|
||||||
|
end
|
||||||
|
assert_equal(42, result, bug10601)
|
||||||
|
end
|
||||||
|
|
||||||
def test_equal
|
def test_equal
|
||||||
klass1 = @Struct.new(:a)
|
klass1 = @Struct.new(:a)
|
||||||
klass2 = @Struct.new(:a, :b)
|
klass2 = @Struct.new(:a, :b)
|
||||||
|
|
|
@ -2107,3 +2107,16 @@ vm_once_clear(VALUE data)
|
||||||
return Qnil;
|
return Qnil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rb_control_frame_t *
|
||||||
|
FUNC_FASTCALL(rb_vm_opt_struct_aref)(rb_thread_t *th, rb_control_frame_t *reg_cfp)
|
||||||
|
{
|
||||||
|
TOPN(0) = rb_struct_aref(GET_SELF(), TOPN(0));
|
||||||
|
return reg_cfp;
|
||||||
|
}
|
||||||
|
|
||||||
|
rb_control_frame_t *
|
||||||
|
FUNC_FASTCALL(rb_vm_opt_struct_aset)(rb_thread_t *th, rb_control_frame_t *reg_cfp)
|
||||||
|
{
|
||||||
|
rb_struct_aset(GET_SELF(), TOPN(0), TOPN(1));
|
||||||
|
return reg_cfp;
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue