Alien-LibJIT
view release on metacpan or search on metacpan
libjit/jitruby/ext/method_data.c.rpp view on Meta::CPAN
/* Okay to not pop this temporary frame, since it will be popped by the
* caller
*/
#define FIX_FRAME() \
struct FRAME _frame = *ruby_frame; \
_frame.last_class = RCLASS(ruby_frame->last_class)->super; \
_frame.prev = ruby_frame; \
ruby_frame = &_frame; \
static NODE * data_memo_node()
{
return (NODE *)(RBASIC(ruby_frame->prev->last_class)->klass);
}
#endif
typedef VALUE (*Method_Func)(ANYARGS);
static Method_Func actual_cfunc()
{
return data_memo_node()->nd_cfnc;
}
static VALUE data_wrapper_m1(int argc, VALUE * argv, VALUE self)
{
VALUE result;
FIX_FRAME();
result = (*actual_cfunc())(argc, argv, self);
return result;
}
static VALUE data_wrapper_0(VALUE self)
{
VALUE result;
FIX_FRAME();
result = (*actual_cfunc())(self);
return result;
}
#ruby <<END
(1..MAX_ARGS).each do |i|
params = (1..i).map { |j| "VALUE arg#{j}" }.join(', ')
args = (1..i).map { |j| "arg#{j}" }.join(', ')
puts <<-END
static VALUE data_wrapper_#{i}(VALUE self, #{params})
{
VALUE result;
FIX_FRAME();
result = (*actual_cfunc())(self, #{args});
return result;
}
END
end
nil
END
/* Define a method and attach data to it.
*
* The method looks to ruby like a normal aliased CFUNC, with a modified
* origin class:
*
* NODE_FBODY
* |- (u1) orig - origin class
* | |- basic
* | | |- flags - origin class flags + FL_SINGLETON
* | | +- klass - NODE_MEMO
* | | |- (u1) cfnc - actual C function to call
* | | |- (u2) rval - stored data
* | | +- (u3) 0
* | |- iv_tbl - 0
* | |- m_tbl - 0
* | +- super - actual origin class
* |- (u2) mid - name of the method
* +- (u3) head - NODE_CFUNC
* |- (u1) cfnc - wrapper function to call
* +- (u2) argc - function arity
*
* Or, on YARV:
*
* NODE_FBODY
* |- (u1) oid - name of the method
* +- (u2) body - NODE_METHOD
* |- (u1) clss - origin class
* | |- basic
* | | |- flags - origin class flags + FL_SINGLETON
* | | +- klass - NODE_MEMO
* | | |- (u1) cfnc - actual C function to call
* | | |- (u2) rval - stored data
* | | +- (u3) 0
* | |- ptr - rb_classext_t
* | | |- super - actual origin class
* | | +- iv_tbl - 0
* | |- m_tbl - 0
* | +- iv_index_tbl - 0?
* |- (u2) body - NODE_CFUNC
* | |- (u1) cfnc - wrapper function to call
* | |- (u2) argc - function arity
* +- (u3) noex - NOEX_PUBLIC
*
* When the wrapper function is called, last_class is set to the origin
* class found in the FBODY node. So that the method data will be
* accessible, and so last_class will point to klass and not to our MEMO
* node, it is necessary to "fix" the current frame.
*
* Pre-YARV, this means we duplicate the current frame and set last_class:
*
* ruby_frame
* |- last_class - klass
* |- prev
* | |- last_class - NODE_MEMO
* | | |- (u1) cfnc - actual C function to call
* | | |- (u2) rval - stored data
* | | +- (u3) 0
* | |- prev - the real previous frame
* | +- ...
* +- ...
*
* The method data is then accessible via
* ruby_frame->prev->last_class->rval.
( run in 1.949 second using v1.01-cache-2.11-cpan-8f98c5d2c55 )