More Related Content Similar to Message in a bottle Similar to Message in a bottle (20) Message in a bottle9. Ruby 1.8 is slow because it's interpreted.
Surprise! Ruby 1.9 is interpreted, too.
15. What We'll Look Into
MRI: method dispatch and execution
Rubinius: inline caches and JIT
JRuby: invokedynamic
18. class DeepThought
def ultimate_answer?(value)
value.to_s == '42'
end
end
DeepThought.new.ultimate_answer? 42
19. They Just Love Bytecode
Ruby
value.to_s
MRI
getlocal value
send :to_s, 0, nil, 0, <ic:0>
Rubinius
push_local 0
send_stack :to_s, 0
JRuby
ALOAD 0
LDC "to_suffffNuffffu0000u0000u0001u0000u0000u0000u0000u0000u0000...
INVOKEVIRTUAL org/jruby/ast/executable/AbstractScript.initFromDescriptor (Lj...
...
ALOAD 0
INVOKEVIRTUAL ruby/__dash_e__.getCallSite0 ()Lorg/jruby/runtime/CallSite;
ALOAD 1
ALOAD 2
ALOAD 9
INVOKEVIRTUAL org/jruby/runtime/CallSite.call (Lorg/jruby/runtime/ThreadCont...
24. Speed Up Execution
Reduce operations
Just-in-time compilation
Inlining
Speed up search
27. static inline VALUE
rb_call0(VALUE recv, ID mid, int argc, const VALUE *argv,
call_type scope, VALUE self)
{
rb_method_entry_t *me = rb_search_method_entry(recv, mid);
rb_thread_t *th = GET_THREAD();
int call_status = rb_method_call_status(th, me, scope, self); // <- SEARCH
if (call_status != NOEX_OK) {
return method_missing(recv, mid, argc, argv, call_status);
}
stack_check();
return vm_call0(th, recv, mid, argc, argv, me); // <- EXECUTE
}
29. /*
* rb_call0 searching for a method
* -> rb_method_entry
* -> rb_method_entry_get_without_cache
* -> search_method
*/
static rb_method_entry_t*
search_method(VALUE klass, ID id)
{
st_data_t body;
if (!klass) {
return 0;
}
while (!st_lookup(RCLASS_M_TBL(klass), id, &body)) {
klass = RCLASS_SUPER(klass);
if (!klass) {
return 0;
}
}
return (rb_method_entry_t *)body;
}
31. /*
* rb_call0 executing a method
* -> vm_call0
*/
static inline VALUE
vm_call0(rb_thread_t* th, VALUE recv, VALUE id, int argc, const VALUE *argv,
const rb_method_entry_t *me)
{
const rb_method_definition_t *def = me->def;
VALUE val;
const rb_block_t *blockptr = 0;
// ...
again:
switch (def->type) {
case VM_METHOD_TYPE_ISEQ: {
rb_control_frame_t *reg_cfp;
// ...
vm_setup_method(th, reg_cfp, recv, argc, blockptr, 0 /* flag */, me);
val = vm_exec(th); // <- EXECUTE !!!
break;
}
// ...
}
// ...
}
34. DEFINE_INSN
send
(ID op_id, rb_num_t op_argc, ISEQ blockiseq, rb_num_t op_flag, IC ic)
(...)
(VALUE val)
// inc += - (int)(op_argc + ((op_flag & VM_CALL_ARGS_BLOCKARG_BIT) ? 1 : 0));
{
const rb_method_entry_t *me;
VALUE recv, klass;
rb_block_t *blockptr = 0;
VALUE flag = op_flag;
int num = caller_setup_args(th, GET_CFP(), flag, (int)op_argc,
(rb_iseq_t *)blockiseq, &blockptr);
ID id = op_id;
/* get receiver */
recv = (flag & VM_CALL_FCALL_BIT) ? GET_SELF() : TOPN(num);
klass = CLASS_OF(recv);
me = vm_method_search(id, klass, ic);
CALL_METHOD(num, blockptr, flag, id, me, recv);
}
38. >> cm = DeepThought.method_table
?> .lookup(:ultimate_answer?).method
=> #<Rubinius::CompiledMethod ultimate_answer?>
>> puts cm.decode
0000: push_local 0 # value
0002: send_stack :to_s, 0
0005: push_literal "42"
0007: string_dup
0008: meta_send_op_equal :==
0010: ret
=> nil
>> cm.iseq.opcodes
=> #<Rubinius::Tuple: 20, 0, 49, 0, 0, 7, 1, 64, 83, 2, 11>
>> cm.literals
=> #<Rubinius::Tuple: :to_s, "42", :==>
39. literals: :to_s, "42", :== locals: value (42)
bytes: 20 0 49 0 0 7 1 64 83 2 11
bytes decoded stack
20 0 push_local 0 [ 42 ]
49 0 0 send_stack :to_s, 0 [ "42" ]
7 1 push_literal "42" [ "42", "42" ]
64 string_dup [ "42", "42" ]
83 2 meta_send_op_equal [ true ]
11 ret [ ]
41. instruction send_stack(literal count) [ receiver +count -- value ] => send
Object* recv = stack_back(count);
InlineCache* cache = reinterpret_cast<InlineCache*>(literal);
Arguments args(cache->name, recv, Qnil, count, stack_back_position(count));
Object* ret = cache->execute(state, call_frame, args);
CHECK_AND_PUSH(ret);
end
44. Specialized Methods
cached bytecode
code with breakpoints
specialized for arguments
JITed code
49. INVOKEVIRTUAL
INVOKEVIRTUAL org/jruby/runtime/CallSite.call(
Lorg/jruby/runtime/ThreadContext;
Lorg/jruby/runtime/builtin/IRubyObject;
Lorg/jruby/runtime/builtin/IRubyObject;
)Lorg/jruby/runtime/builtin/IRubyObject;
INVOKEDYNAMIC
INVOKEDYNAMIC call(
Lorg/jruby/runtime/ThreadContext;
Lorg/jruby/runtime/builtin/IRubyObject;
Lorg/jruby/runtime/builtin/IRubyObject;
Ljava/lang/String;
)Lorg/jruby/runtime/builtin/IRubyObject;
[...]
52. The Bootstrap
public static CallSite
invocationBootstrap(Lookup lookup, String name, MethodType type)
throws NoSuchMethodException, IllegalAccessException {
CallSite site;
// ...
if (name.equals("call")) {
site = new JRubyCallSite(lookup, type, CallType.NORMAL, false, false, true);
}
// ...
MethodHandle myFallback = ...
site.setTarget(myFallback);
return site;
}
54. The Fallback
public static IRubyObject invocationFallback(JRubyCallSite site,
ThreadContext context,
IRubyObject caller,
IRubyObject self,
String name) throws Throwable {
RubyClass selfClass = pollAndGetClass(context, self);
CacheEntry entry = selfClass.searchWithCache(name);
if (methodMissing(entry, site.callType(), name, caller)) {
return callMethodMissing(entry, site.callType(), context, self, name);
}
MethodHandle target = getTarget(site, selfClass, name, entry, 0);
target = updateInvocationTarget(target, site, selfClass, name, entry, false, 0);
return (IRubyObject)target.invokeWithArguments(context, caller, self, name);
}
55. images
http://kosmur.deviantart.com/art/assembler-79007314
https://www.facebook.com/headius
https://www.facebook.com/koichi.sasada
https://www.facebook.com/profile.php?id=523826914
http://farm4.static.flickr.com/3207/2522976901_6ff55314cd.jpg
http://www.flickr.com/photos/binkley27/3451700024
http://www.flickr.com/photos/funtik/1175522045
http://en.wikipedia.org/wiki/File:Answer_to_Life.png
http://www.flickr.com/photos/makelessnoise/195088755/
http://www.flickr.com/photos/jeffhenshaw/4833007463/
http://churchmusictoday.wordpress.com/2011/05/13/ten-warning-signs-for-churches-from-thom-ranier/
http://www.freefoto.com/preview/28-06-3/Police-Underwater-Search-Unit
http://blog-blond.blogspot.com/2009/07/how-to-do-blogs-right.html
http://fuckyouverymuch.dk/post/9661487809/we-are-ready-to-leave
http://crunchtools.com/bootstrapping-and-rooting-documentation-part-2/
http://www.softmyhard.com/tag/device-instruction-manual
http://www.flickr.com/photos/quinnanya/4874581964