ruby closures, how are they possible?
TRANSCRIPT
Ruby closuresHow are they possible?
Carlos Alonso Software Engineer
@calonso
A story about curiosity…
I am curious
def greet str = “hello” lambda do puts str end end f = greet f.call # => hello
def greet str = “hello” lambda do puts str end end f = greet f.call # => hello
def greet str = “hello” lambda do puts str end end f = greet f.call # => hello
This talk!
Some examples…
a = 1 def sum a + 1 end sum
a = 1 def sum a + 1 end sum
NameError: Undefined `a’
def run_block yield end
a = 1 run_block { a + 1 }
def run_block yield end
a = 1 run_block { a + 1 }
2
def run_block a = 1 yield end
run_block { a + 1 }
def run_block a = 1 yield end
run_block { a + 1 }
NameError: Undefined `a’
def run_block a = 100 yield end
a = 1 run_block { a + 1 }
def run_block a = 100 yield end
a = 1 run_block { a + 1 }
2
a = 1 sum = lambda do a + 1 end a = 2 sum.call
a = 1 sum = lambda do a + 1 end a = 2 sum.call
3
What is a closure?
A lambda expression +
an environment to run it
Blocks refer to variables declared in the scope where they were defined,
not where they are executed.
Lexical scope
Ruby uses lexical scope. Let’s see this scopes!!
a = 1 def sum a + 1 end sum
a = 1 def sum a + 1 end sum
top-level a = 1 sum = …
a = 1 def sum a + 1 end sum
top-level a = 1 sum = …
sum a??
a = 1 def sum a + 1 end sum
top-level a = 1 sum = …
sum a??
NameError: Undefined `a’
def run_block(&block) yield end
a = 1 run_block { a + 1 }
def run_block(&block) yield end
a = 1 run_block { a + 1 }
top-level run_block = … a = 1
def run_block(&block) yield end
a = 1 run_block { a + 1 }
top-level run_block = … a = 1 run_block
block
def run_block(&block) yield end
a = 1 run_block { a + 1 }
top-level run_block = … a = 1
in-block a
run_block block
def run_block(&block) yield end
a = 1 run_block { a + 1 }
top-level run_block = … a = 1
in-block a
run_block block
2
def run_block(&block) a = 1 yield end
run_block { a + 1 }
def run_block(&block) a = 1 yield end
run_block { a + 1 }
top-level run_block = …
def run_block(&block) a = 1 yield end
run_block { a + 1 }
top-level run_block = …
run_block a = 1 block
def run_block(&block) a = 1 yield end
run_block { a + 1 }
top-level run_block = …
in-block a??
run_block a = 1 block
def run_block(&block) a = 1 yield end
run_block { a + 1 }
top-level run_block = …
in-block a??
run_block a = 1 block
NameError: Undefined `a’
def run_block(&block) a = 100 yield end
a = 1 run_block { a + 1 }
def run_block(&block) a = 100 yield end
a = 1 run_block { a + 1 }
top-level run_block = … a = 1
def run_block(&block) a = 100 yield end
a = 1 run_block { a + 1 }
top-level run_block = … a = 1 run_block
a = 100 block
def run_block(&block) a = 100 yield end
a = 1 run_block { a + 1 }
top-level run_block = … a = 1
in-block a
run_block a = 100 block
def run_block(&block) a = 100 yield end
a = 1 run_block { a + 1 }
top-level run_block = … a = 1
in-block a
run_block a = 100 block
2
a = 1 sum = lambda do a + 1 end a = 2 sum.call
a = 1 sum = lambda do a + 1 end a = 2 sum.call
top-level a = 2 sum…
a = 1 sum = lambda do a + 1 end a = 2 sum.call
top-level a = 2 sum…
in-lambda a
a = 1 sum = lambda do a + 1 end a = 2 sum.call
top-level a = 2 sum…
in-lambda a
3
Cool!!
The lexical scope explains the examples
Cool!!
The lexical scope explains the examples
But… how exactly??
Ok, let’s start from scratch. How does Ruby executes programs?
0002 putself 0003 putobject 2 0005 putobject 2 0007 opt_plus 0009 opt_send_simple puts 0011 leave
2
rb_control_frame_tpcspselftype
YARV internal stack
[TOP LEVEL]self
2
YARV Control structures stack YARV Instructions
CFP
https://github.com/ruby/ruby/blob/trunk/vm_core.h
== disasm: <RubyVM::InstructionSequence:<compiled>@<compiled>>========== 0000 trace 1 ( 1) 0002 putspecialobject 1 0004 putspecialobject 2 0006 putobject :greet 0008 putiseq greet 0010 opt_send_simple <callinfo!mid:core#define_method, argc:3, ARGS_SKIP> 0012 pop 0013 trace 1 ( 4) 0015 putself 0016 opt_send_simple <callinfo!mid:greet, argc:0, FCALL|VCALL|ARGS_SKIP> 0018 leave == disasm: <RubyVM::InstructionSequence:greet@<compiled>>=============== 0000 trace 8 ( 1) 0002 trace 1 ( 2) 0004 putself 0005 putstring "hello" 0007 opt_send_simple <callinfo!mid:puts, argc:1, FCALL|ARGS_SKIP> 0009 trace 16 ( 3) 0011 leave ( 2)
def greet puts “hello” end greet
0006 putobject :greet 0008 putiseq greet 0010 opt_send_simple define_method 0012 pop 0015 putself 0016 opt_send_simple greet 0018 leave
rb_control_frame_tpcspselftype
[TOP LEVEL]
def greet puts “hello” end greet
0006 putobject :greet 0008 putiseq greet 0010 opt_send_simple define_method 0012 pop 0015 putself 0016 opt_send_simple greet 0018 leave
rb_control_frame_tpcspselftype
[TOP LEVEL]
:greet
def greet puts “hello” end greet
0006 putobject :greet 0008 putiseq greet 0010 opt_send_simple define_method 0012 pop 0015 putself 0016 opt_send_simple greet 0018 leave
rb_control_frame_tpcspselftype
[TOP LEVEL]
:greetgreet
def greet puts “hello” end greet
0006 putobject :greet 0008 putiseq greet 0010 opt_send_simple define_method 0012 pop 0015 putself 0016 opt_send_simple greet 0018 leave
rb_control_frame_tpcspselftype
[TOP LEVEL]
:greetgreet
def greet puts “hello” end greet
0006 putobject :greet 0008 putiseq greet 0010 opt_send_simple define_method 0012 pop 0015 putself 0016 opt_send_simple greet 0018 leave
rb_control_frame_tpcspselftype
[TOP LEVEL]
:greet
def greet puts “hello” end greet
0006 putobject :greet 0008 putiseq greet 0010 opt_send_simple define_method 0012 pop 0015 putself 0016 opt_send_simple greet 0018 leave
rb_control_frame_tpcspselftype
[TOP LEVEL]
:greetself
def greet puts “hello” end greet
0006 putobject :greet 0008 putiseq greet 0010 opt_send_simple define_method 0012 pop 0015 putself 0016 opt_send_simple greet 0018 leave
rb_control_frame_tpcspselftype
[TOP LEVEL]
:greetself
rb_control_frame_tpcspselftype
[METHOD]
0004 putself 0005 putstring "hello" 0007 opt_send_simple puts 0011 leave svar/cref
special
def greet puts “hello” end greet
0006 putobject :greet 0008 putiseq greet 0010 opt_send_simple define_method 0012 pop 0015 putself 0016 opt_send_simple greet 0018 leave
rb_control_frame_tpcspselftype
[TOP LEVEL]
:greetself
self
rb_control_frame_tpcspselftype
[METHOD]
0004 putself 0005 putstring "hello" 0007 opt_send_simple puts 0011 leave svar/cref
special
def greet puts “hello” end greet
0006 putobject :greet 0008 putiseq greet 0010 opt_send_simple define_method 0012 pop 0015 putself 0016 opt_send_simple greet 0018 leave
rb_control_frame_tpcspselftype
[TOP LEVEL]
:greetself
self
rb_control_frame_tpcspselftype
[METHOD]
0004 putself 0005 putstring "hello" 0007 opt_send_simple puts 0011 leave svar/cref
special
“hello”
def greet puts “hello” end greet
0006 putobject :greet 0008 putiseq greet 0010 opt_send_simple define_method 0012 pop 0015 putself 0016 opt_send_simple greet 0018 leave
rb_control_frame_tpcspselftype
[TOP LEVEL]
:greetself
self
rb_control_frame_tpcspselftype
[METHOD]
0004 putself 0005 putstring "hello" 0007 opt_send_simple puts 0011 leave svar/cref
special
$ “hello”def greet puts “hello” end greet
0006 putobject :greet 0008 putiseq greet 0010 opt_send_simple define_method 0012 pop 0015 putself 0016 opt_send_simple greet 0018 leave
rb_control_frame_tpcspselftype
[TOP LEVEL]
:greetself
def greet puts “hello” end greet
Ok cool, what if the method has local variables?
== disasm: <RubyVM::InstructionSequence:<compiled>@<compiled>>========== 0000 trace 1 ( 1) 0002 putspecialobject 1 0004 putspecialobject 2 0006 putobject :greet 0008 putiseq greet 0010 opt_send_simple <callinfo!mid:core#define_method, argc:3, ARGS_SKIP> 0012 pop 0013 trace 1 ( 5) 0015 putself 0016 opt_send_simple <callinfo!mid:greet, argc:0, FCALL|VCALL|ARGS_SKIP> 0018 leave == disasm: <RubyVM::InstructionSequence:greet@<compiled>>=============== local table (size: 2, argc: 0 [opts: 0, rest: -1, post: 0, block: -1, keyword: 0@3] s1) [ 2] str 0000 trace 8 ( 1) 0002 trace 1 ( 2) 0004 putstring "hello" 0006 setlocal_OP__WC__0 2 0008 trace 1 ( 3) 0010 putself 0011 getlocal_OP__WC__0 2 0013 opt_send_simple <callinfo!mid:puts, argc:1, FCALL|ARGS_SKIP> 0015 trace 16 ( 4) 0017 leave( 3)
def greet str = “hello” puts str end greet
local table (size: 2, argc: 0 [opts: 0, rest: -1, post: 0, block: -1, keyword: 0@3] s1) [ 2] str
The local table
0006 putobject :greet 0008 putiseq greet 0010 opt_send_simple define_method 0012 pop 0015 putself 0016 opt_send_simple greet 0018 leave
rb_control_frame_tpcspselftype
[TOP LEVEL]
:greetself
def greet str = “hello” puts str end greet
0006 putobject :greet 0008 putiseq greet 0010 opt_send_simple define_method 0012 pop 0015 putself 0016 opt_send_simple greet 0018 leave
rb_control_frame_tpcspselftype
[TOP LEVEL]
:greetself
special
rb_control_frame_tpcsp
selftype
[METHOD]
0004 putstring "hello" 0006 setlocal 2, 0 0010 putself 0011 getlocal 2, 0 0013 opt_send_simple puts 0017 leave
strsvar/cref
ep
def greet str = “hello” puts str end greet
0006 putobject :greet 0008 putiseq greet 0010 opt_send_simple define_method 0012 pop 0015 putself 0016 opt_send_simple greet 0018 leave
rb_control_frame_tpcspselftype
[TOP LEVEL]
:greetself
special
rb_control_frame_tpcsp
selftype
[METHOD]str
svar/cref
“hello”ep
0004 putstring "hello" 0006 setlocal 2, 0 0010 putself 0011 getlocal 2, 0 0013 opt_send_simple puts 0017 leave
def greet str = “hello” puts str end greet
0006 putobject :greet 0008 putiseq greet 0010 opt_send_simple define_method 0012 pop 0015 putself 0016 opt_send_simple greet 0018 leave
rb_control_frame_tpcspselftype
[TOP LEVEL]
:greetself
special
rb_control_frame_tpcsp
selftype
[METHOD]str
svar/cref
ep
“hello”
0004 putstring "hello" 0006 setlocal 2, 0 0010 putself 0011 getlocal 2, 0 0013 opt_send_simple puts 0017 leave
def greet str = “hello” puts str end greet
0006 putobject :greet 0008 putiseq greet 0010 opt_send_simple define_method 0012 pop 0015 putself 0016 opt_send_simple greet 0018 leave
rb_control_frame_tpcspselftype
[TOP LEVEL]
:greetself
special
rb_control_frame_tpcsp
selftype
[METHOD]str
svar/cref
epself
“hello”
0004 putstring "hello" 0006 setlocal 2, 0 0010 putself 0011 getlocal 2, 0 0013 opt_send_simple puts 0017 leave
def greet str = “hello” puts str end greet
0006 putobject :greet 0008 putiseq greet 0010 opt_send_simple define_method 0012 pop 0015 putself 0016 opt_send_simple greet 0018 leave
rb_control_frame_tpcspselftype
[TOP LEVEL]
:greetself
special
rb_control_frame_tpcsp
selftype
[METHOD]str
svar/cref
epself
“hello”
“hello”
0004 putstring "hello" 0006 setlocal 2, 0 0010 putself 0011 getlocal 2, 0 0013 opt_send_simple puts 0017 leave
def greet str = “hello” puts str end greet
0006 putobject :greet 0008 putiseq greet 0010 opt_send_simple define_method 0012 pop 0015 putself 0016 opt_send_simple greet 0018 leave
rb_control_frame_tpcspselftype
[TOP LEVEL]
:greetself
special
rb_control_frame_tpcsp
selftype
[METHOD]str
svar/cref
ep
“hello”
$ “hello”
0004 putstring "hello" 0006 setlocal 2, 0 0010 putself 0011 getlocal 2, 0 0013 opt_send_simple puts 0017 leave
def greet str = “hello” puts str end greet
0006 putobject :greet 0008 putiseq greet 0010 opt_send_simple define_method 0012 pop 0015 putself 0016 opt_send_simple greet 0018 leave
rb_control_frame_tpcspselftype
[TOP LEVEL]
:greetself
$ “hello”def greet str = “hello” puts str end greet
Got it, but what about blocks accessing variables on lexical
scope?
……… == disasm: <RubyVM::InstructionSequence:greet@<compiled>>=============== == catch table | catch type: break st: 0010 ed: 0014 sp: 0000 cont: 0014 |------------------------------------------------------------------------ local table (size: 2, argc: 0 [opts: 0, rest: -1, post: 0, block: -1, keyword: 0@3] s1) [ 2] str 0000 trace 8 ( 1) 0002 trace 1 ( 2) 0004 putstring "hello" 0006 setlocal_OP__WC__0 2 0008 trace 1 ( 3) 0010 putobject 3 0012 send <callinfo!mid:times, argc:0, block:block in greet> 0014 trace 16 ( 6) 0016 leave ( 3) == disasm: <RubyVM::InstructionSequence:block in greet@<compiled>>====== == catch table | catch type: redo st: 0002 ed: 0009 sp: 0000 cont: 0002 | catch type: next st: 0002 ed: 0009 sp: 0000 cont: 0009 |------------------------------------------------------------------------ 0000 trace 256 ( 3) 0002 trace 1 ( 4) 0004 putself 0005 getlocal_OP__WC__1 2 0007 opt_send_simple <callinfo!mid:puts, argc:1, FCALL|ARGS_SKIP> 0009 trace 512 ( 5) 0011 leave ( 4)
def greet str = “hello” 3.times do puts str end end greet
0006 putobject :greet 0008 putiseq greet 0010 opt_send_simple define_method 0012 pop 0015 putself 0016 opt_send_simple greet 0018 leave
rb_control_frame_tpcspselftype
[TOP LEVEL]
:greetself
def greet str = “hello” 3.times do puts str end end greet
0006 putobject :greet 0008 putiseq greet 0010 opt_send_simple define_method 0012 pop 0015 putself 0016 opt_send_simple greet 0018 leave
rb_control_frame_tpcspselftype
[TOP LEVEL]
:greetself
special
rb_control_frame_tpcsp
selftype
[METHOD]
0004 putstring "hello" 0006 setlocal 2, 0 0010 putobject 3 0012 send times 0016 leave
strsvar/cref
ep
def greet str = “hello” 3.times do puts str end end greet
0006 putobject :greet 0008 putiseq greet 0010 opt_send_simple define_method 0012 pop 0015 putself 0016 opt_send_simple greet 0018 leave
rb_control_frame_tpcspselftype
[TOP LEVEL]
:greetself
special
rb_control_frame_tpcsp
selftype
[METHOD]str
svar/cref
“hello” ep
0004 putstring "hello" 0006 setlocal 2, 0 0010 putobject 3 0012 send times 0016 leave
def greet str = “hello” 3.times do puts str end end greet
0006 putobject :greet 0008 putiseq greet 0010 opt_send_simple define_method 0012 pop 0015 putself 0016 opt_send_simple greet 0018 leave
rb_control_frame_tpcspselftype
[TOP LEVEL]
:greetself
special
rb_control_frame_tpcsp
selftype
[METHOD]str
svar/cref
ep
“hello”
0004 putstring "hello" 0006 setlocal 2, 0 0010 putobject 3 0012 send times 0016 leave
def greet str = “hello” 3.times do puts str end end greet
0006 putobject :greet 0008 putiseq greet 0010 opt_send_simple define_method 0012 pop 0015 putself 0016 opt_send_simple greet 0018 leave
rb_control_frame_tpcspselftype
[TOP LEVEL]
:greetself
special
rb_control_frame_tpcsp
selftype
[METHOD]str
svar/cref
ep3
“hello”
0004 putstring "hello" 0006 setlocal 2, 0 0010 putobject 3 0012 send times 0016 leave
def greet str = “hello” 3.times do puts str end end greet
0006 putobject :greet 0008 putiseq greet 0010 opt_send_simple define_method 0012 pop 0015 putself 0016 opt_send_simple greet 0018 leave
rb_control_frame_tpcsp
[TOP LEVEL]
:greetself
special rb_control_frame_tpcsp
[METHOD]
0004 putstring "hello" 0006 setlocal 2, 0 0010 putobject 3 0012 send times 0016 leave
strsvar/cref
ep
3
“hello”
rb_block_tiseqep…
0004 putself 0005 getlocal 2, 1 0007 opt_send_simple puts 0011 leave
def greet str = “hello” 3.times do puts str end end greet
0006 putobject :greet 0008 putiseq greet 0010 opt_send_simple define_method 0012 pop 0015 putself 0016 opt_send_simple greet 0018 leave
rb_control_frame_tpcsp
[TOP LEVEL]
:greetself
special rb_control_frame_tpcsp
[METHOD]
0004 putstring "hello" 0006 setlocal 2, 0 0010 putobject 3 0012 send times 0016 leave
strsvar/cref
ep
3
“hello”
svar/crefspecial
rb_block_tiseqep…
rb_control_frame_tpcsp
[METHOD]ep
times…
0004 putself 0005 getlocal 2, 1 0007 opt_send_simple puts 0011 leave
def greet str = “hello” 3.times do puts str end end greet
0006 putobject :greet 0008 putiseq greet 0010 opt_send_simple define_method 0012 pop 0015 putself 0016 opt_send_simple greet 0018 leave
rb_control_frame_tpcsp
[TOP LEVEL]
:greetself
special rb_control_frame_tpcsp
[METHOD]
0004 putstring "hello" 0006 setlocal 2, 0 0010 putobject 3 0012 send times 0016 leave
strsvar/cref
ep
3
“hello”
svar/crefspecial
svar/cref
rb_block_tiseqep…
rb_control_frame_tpcsp
[METHOD]ep
times…
rb_con…pcsp
[BLOCK]
ep
special
0004 putself 0005 getlocal 2, 1 0007 opt_send_simple puts 0011 leave
def greet str = “hello” 3.times do puts str end end greet
0006 putobject :greet 0008 putiseq greet 0010 opt_send_simple define_method 0012 pop 0015 putself 0016 opt_send_simple greet 0018 leave
rb_control_frame_tpcsp
[TOP LEVEL]
:greetself
special rb_control_frame_tpcsp
[METHOD]
0004 putstring "hello" 0006 setlocal 2, 0 0010 putobject 3 0012 send times 0016 leave
strsvar/cref
ep
3
“hello”
svar/crefspecial
svar/cref
rb_block_tiseqep…
rb_control_frame_tpcsp
[METHOD]ep
times…
rb_con…pcsp
[BLOCK]
ep
specialself
0004 putself 0005 getlocal 2, 1 0007 opt_send_simple puts 0011 leave
def greet str = “hello” 3.times do puts str end end greet
0006 putobject :greet 0008 putiseq greet 0010 opt_send_simple define_method 0012 pop 0015 putself 0016 opt_send_simple greet 0018 leave
rb_control_frame_tpcsp
[TOP LEVEL]
:greetself
special rb_control_frame_tpcsp
[METHOD]
0004 putstring "hello" 0006 setlocal 2, 0 0010 putobject 3 0012 send times 0016 leave
strsvar/cref
ep
3
“hello”
svar/crefspecial
svar/cref
rb_block_tiseqep…
rb_control_frame_tpcsp
[METHOD]ep
times…
rb_con…pcsp
[BLOCK]
ep
0004 putself 0005 getlocal 2, 1 0007 opt_send_simple puts 0011 leave
specialself
“hello”
def greet str = “hello” 3.times do puts str end end greet
0006 putobject :greet 0008 putiseq greet 0010 opt_send_simple define_method 0012 pop 0015 putself 0016 opt_send_simple greet 0018 leave
rb_control_frame_tpcsp
[TOP LEVEL]
:greetself
special rb_control_frame_tpcsp
[METHOD]
0004 putstring "hello" 0006 setlocal 2, 0 0010 putobject 3 0012 send times 0016 leave
strsvar/cref
ep
3
“hello”
svar/crefspecial
svar/cref
rb_block_tiseqep…
rb_control_frame_tpcsp
[METHOD]ep
times…
rb_con…pcsp
[BLOCK]
ep
0004 putself 0005 getlocal 2, 1 0007 opt_send_simple puts 0011 leave
specialself
$ “hello”def greet str = “hello” 3.times do puts str end end greet
https://github.com/ruby/ruby/blob/trunk/vm_core.h
And what if that scope doesn’t exist anymore?
The heap and rb_proc_t to the
rescue!
\o/
Stack vs Heap
:greetselfstr
“hello”
RString
== disasm: <RubyVM::InstructionSequence:<compiled>@<compiled>>========== local table (size: 2, argc: 0 [opts: 0, rest: -1, post: 0, block: -1, keyword: 0@3] s1) [ 2] f 0002 putspecialobject 1 0004 putspecialobject 2 0006 putobject :greet 0008 putiseq greet 0010 opt_send_simple <callinfo!mid:core#define_method, argc:3, ARGS_SKIP> 0012 pop 0015 putself 0016 opt_send_simple <callinfo!mid:greet, argc:0, FCALL|VCALL|ARGS_SKIP> 0018 setlocal_OP__WC__0 2 0022 getlocal_OP__WC__0 2 0024 opt_send_simple <callinfo!mid:call, argc:0, ARGS_SKIP> 0026 leave == disasm: <RubyVM::InstructionSequence:greet@<compiled>>=============== == catch table | catch type: break st: 0010 ed: 0013 sp: 0000 cont: 0013 |------------------------------------------------------------------------ local table (size: 2, argc: 0 [opts: 0, rest: -1, post: 0, block: -1, keyword: 0@3] s1) [ 2] str 0004 putstring "hello" 0006 setlocal_OP__WC__0 2 0010 putself 0011 send <callinfo!mid:lambda, argc:0, block:block in greet, FCALL> 0015 leave ( 3) == disasm: <RubyVM::InstructionSequence:block in greet@<compiled>>====== == catch table | catch type: redo st: 0002 ed: 0009 sp: 0000 cont: 0002 | catch type: next st: 0002 ed: 0009 sp: 0000 cont: 0009 |------------------------------------------------------------------------ 0004 putself 0005 getlocal_OP__WC__1 2 0007 opt_send_simple <callinfo!mid:puts, argc:1, FCALL|ARGS_SKIP> 0011 leave
def greet str = “hello” lambda do puts str end end f = greet f.call
def greet str = “hello” lambda do puts str end end f = greet f.call
[ 2] f 0006 putobject :greet 0008 putiseq greet 0010 opt_send_simple core#define_method 0012 pop 0015 putself 0016 opt_send_simple greet 0018 setlocal 2, 0 0022 getlocal 2, 0 0024 opt_send_simple call 0026 leave
rb_control_frame_tpcsp
[TOP LEVEL]epf
svar/crefspecial:greet self
[ 2] f 0006 putobject :greet 0008 putiseq greet 0010 opt_send_simple core#define_method 0012 pop 0015 putself 0016 opt_send_simple greet 0018 setlocal 2, 0 0022 getlocal 2, 0 0024 opt_send_simple call 0026 leave
0004 putstring "hello" 0006 setlocal 2, 0 0010 putself 0011 send lambda 0015 leave
def greet str = “hello” lambda do puts str end end f = greet f.call
rb_control_frame_tpcsp
[TOP LEVEL]ep
rb_control_frame_tpcsp
[METHOD]ep
fsvar/crefspecial:greet self str
svar/crefspecial
[ 2] f 0006 putobject :greet 0008 putiseq greet 0010 opt_send_simple core#define_method 0012 pop 0015 putself 0016 opt_send_simple greet 0018 setlocal 2, 0 0022 getlocal 2, 0 0024 opt_send_simple call 0026 leave
0004 putstring "hello" 0006 setlocal 2, 0 0010 putself 0011 send lambda 0015 leave
def greet str = “hello” lambda do puts str end end f = greet f.call
rb_control_frame_tpcsp
[TOP LEVEL]ep
rb_control_frame_tpcsp
[METHOD]ep
fsvar/crefspecial:greet self str
svar/crefspecial“hello”
[ 2] f 0006 putobject :greet 0008 putiseq greet 0010 opt_send_simple core#define_method 0012 pop 0015 putself 0016 opt_send_simple greet 0018 setlocal 2, 0 0022 getlocal 2, 0 0024 opt_send_simple call 0026 leave
0004 putstring "hello" 0006 setlocal 2, 0 0010 putself 0011 send lambda 0015 leave
def greet str = “hello” lambda do puts str end end f = greet f.call
“hello”
rb_control_frame_tpcsp
[TOP LEVEL]ep
rb_control_frame_tpcsp
[METHOD]ep
fsvar/crefspecial:greet self str
svar/crefspecial
[ 2] f 0006 putobject :greet 0008 putiseq greet 0010 opt_send_simple core#define_method 0012 pop 0015 putself 0016 opt_send_simple greet 0018 setlocal 2, 0 0022 getlocal 2, 0 0024 opt_send_simple call 0026 leave
0004 putstring "hello" 0006 setlocal 2, 0 0010 putself 0011 send lambda 0015 leave
def greet str = “hello” lambda do puts str end end f = greet f.call
“hello”
rb_control_frame_tpcsp
[TOP LEVEL]ep
rb_control_frame_tpcsp
[METHOD]ep
fsvar/crefspecial:greet self str
svar/crefspecial
self
rb_control_frame_tpcsp
[TOP LEVEL]epf
svar/crefspecial:greet self str
rb_control_frame_tpcsp
[METHOD]epsvar/cref
specialself
lambda
[ 2] f 0006 putobject :greet 0008 putiseq greet 0010 opt_send_simple core#define_method 0012 pop 0015 putself 0016 opt_send_simple greet 0018 setlocal 2, 0 0022 getlocal 2, 0 0024 opt_send_simple call 0026 leave
0004 putstring "hello" 0006 setlocal 2, 0 0010 putself 0011 send lambda 0015 leave
def greet str = “hello” lambda do puts str end end f = greet f.call
“hello” strsvar/crefspecial
self
“hello”
rb_control_frame_tpcsp
[TOP LEVEL]epf
svar/crefspecial:greet self str
rb_control_frame_tpcsp
[METHOD]epsvar/cref
specialself
lambda
[ 2] f 0006 putobject :greet 0008 putiseq greet 0010 opt_send_simple core#define_method 0012 pop 0015 putself 0016 opt_send_simple greet 0018 setlocal 2, 0 0022 getlocal 2, 0 0024 opt_send_simple call 0026 leave
0004 putstring "hello" 0006 setlocal 2, 0 0010 putself 0011 send lambda 0015 leave
def greet str = “hello” lambda do puts str end end f = greet f.call
“hello”
strsvar/crefspecial
self
“hello”
rb_control_frame_tpcsp
[TOP LEVEL]epf
svar/crefspecial:greet self str
rb_control_frame_tpcsp
[METHOD]epsvar/cref
specialself
lambda
rb_proc_trb_block_t
EP
[ 2] f 0006 putobject :greet 0008 putiseq greet 0010 opt_send_simple core#define_method 0012 pop 0015 putself 0016 opt_send_simple greet 0018 setlocal 2, 0 0022 getlocal 2, 0 0024 opt_send_simple call 0026 leave
0004 putstring "hello" 0006 setlocal 2, 0 0010 putself 0011 send lambda 0015 leave
def greet str = “hello” lambda do puts str end end f = greet f.call
“hello”
strsvar/crefspecial
self
“hello”
rb_control_frame_tpcsp
[TOP LEVEL]epf
svar/crefspecial:greet self str
rb_control_frame_tpcsp
[METHOD]epsvar/cref
specialself
lambda
rb_proc_trb_block_t
EP
[ 2] f 0006 putobject :greet 0008 putiseq greet 0010 opt_send_simple core#define_method 0012 pop 0015 putself 0016 opt_send_simple greet 0018 setlocal 2, 0 0022 getlocal 2, 0 0024 opt_send_simple call 0026 leave
0004 putstring "hello" 0006 setlocal 2, 0 0010 putself 0011 send lambda 0015 leave
def greet str = “hello” lambda do puts str end end f = greet f.call
“hello”
strsvar/crefspecial
self
“hello”
rb_control_frame_tpcsp
[TOP LEVEL]epf
svar/crefspecial:greet self str
rb_control_frame_tpcsp
[METHOD]epsvar/cref
specialself
lambda
rb_proc_trb_block_t
EP
[ 2] f 0006 putobject :greet 0008 putiseq greet 0010 opt_send_simple core#define_method 0012 pop 0015 putself 0016 opt_send_simple greet 0018 setlocal 2, 0 0022 getlocal 2, 0 0024 opt_send_simple call 0026 leave
0004 putstring "hello" 0006 setlocal 2, 0 0010 putself 0011 send lambda 0015 leave
def greet str = “hello” lambda do puts str end end f = greet f.call
“hello”
strsvar/crefspecial
self
“hello”
rb_control_frame_tpcsp
[TOP LEVEL]epf
svar/crefspecial:greet self
lambda
strsvar/crefspecial
selfrb_proc_trb_block_t
EP
[ 2] f 0006 putobject :greet 0008 putiseq greet 0010 opt_send_simple core#define_method 0012 pop 0015 putself 0016 opt_send_simple greet 0018 setlocal 2, 0 0022 getlocal 2, 0 0024 opt_send_simple call 0026 leave
def greet str = “hello” lambda do puts str end end f = greet f.call
“hello”
rb_control_frame_tpcsp
[TOP LEVEL]epf
svar/crefspecial:greet self
strsvar/crefspecial
selfrb_proc_trb_block_t
EP
[ 2] f 0006 putobject :greet 0008 putiseq greet 0010 opt_send_simple core#define_method 0012 pop 0015 putself 0016 opt_send_simple greet 0018 setlocal 2, 0 0022 getlocal 2, 0 0024 opt_send_simple call 0026 leave
def greet str = “hello” lambda do puts str end end f = greet f.call
“hello”
rb_control_frame_tpcsp
[TOP LEVEL]epf
svar/crefspecial:greet self
lambda
strsvar/crefspecial
selfrb_proc_trb_block_t
EP
[ 2] f 0006 putobject :greet 0008 putiseq greet 0010 opt_send_simple core#define_method 0012 pop 0015 putself 0016 opt_send_simple greet 0018 setlocal 2, 0 0022 getlocal 2, 0 0024 opt_send_simple call 0026 leave
def greet str = “hello” lambda do puts str end end f = greet f.call
“hello”
rb_control_frame_tpcsp
[TOP LEVEL]epf
svar/crefspecial:greet self
lambda
strsvar/crefspecial
selfrb_proc_trb_block_t
EP
svar/cref
rb_control_frame_tpcsp
[BLOCK]ep
0004 putself 0005 getlocal 2, 1 0007 opt_send_simple puts 0011 leave
special
[ 2] f 0006 putobject :greet 0008 putiseq greet 0010 opt_send_simple core#define_method 0012 pop 0015 putself 0016 opt_send_simple greet 0018 setlocal 2, 0 0022 getlocal 2, 0 0024 opt_send_simple call 0026 leave
def greet str = “hello” lambda do puts str end end f = greet f.call
“hello”
rb_control_frame_tpcsp
[TOP LEVEL]epf
svar/crefspecial:greet self
lambda
strsvar/crefspecial
selfrb_proc_trb_block_t
EP
svar/cref
rb_control_frame_tpcsp
[BLOCK]ep
specialself
0004 putself 0005 getlocal 2, 1 0007 opt_send_simple puts 0011 leave
[ 2] f 0006 putobject :greet 0008 putiseq greet 0010 opt_send_simple core#define_method 0012 pop 0015 putself 0016 opt_send_simple greet 0018 setlocal 2, 0 0022 getlocal 2, 0 0024 opt_send_simple call 0026 leave
def greet str = “hello” lambda do puts str end end f = greet f.call
“hello”
rb_control_frame_tpcsp
[TOP LEVEL]epf
svar/crefspecial:greet self
lambda
strsvar/crefspecial
selfrb_proc_trb_block_t
EP
svar/cref
rb_control_frame_tpcsp
[BLOCK]ep
specialself
“hello”
0004 putself 0005 getlocal 2, 1 0007 opt_send_simple puts 0011 leave
[ 2] f 0006 putobject :greet 0008 putiseq greet 0010 opt_send_simple core#define_method 0012 pop 0015 putself 0016 opt_send_simple greet 0018 setlocal 2, 0 0022 getlocal 2, 0 0024 opt_send_simple call 0026 leave
def greet str = “hello” lambda do puts str end end f = greet f.call
“hello”
$ “hello”
https://github.com/ruby/ruby/blob/trunk/vm_core.h
Acknowledgements
Pat Shaughnessy
Questions?
Thanks!
Carlos Alonso Software Engineer
@calonso