SlideShare a Scribd company logo
Ruby closures
How are they possible?
Carlos Alonso
Software Engineer
@calonso
A story about curiosity…
I am curious
Ruby closures, how are they possible?
Ruby closures, how are they possible?
Ruby closures, how are they possible?
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
Ruby closures, how are they possible?
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?
Ruby closures, how are they possible?
0002 putself
0003 putobject 2
0005 putobject 2
0007 opt_plus
0009 opt_send_simple puts
0011 leave
2
rb_control_frame_t
pc
sp
self
type
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_t
pc
sp
self
type
[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_t
pc
sp
self
type
[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_t
pc
sp
self
type
[TOP LEVEL]
:greet
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_t
pc
sp
self
type
[TOP LEVEL]
:greet
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_t
pc
sp
self
type
[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_t
pc
sp
self
type
[TOP LEVEL]
:greet
self
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_t
pc
sp
self
type
[TOP LEVEL]
:greet
self
rb_control_frame_t
pc
sp
self
type
[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_t
pc
sp
self
type
[TOP LEVEL]
:greet
self
self
rb_control_frame_t
pc
sp
self
type
[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_t
pc
sp
self
type
[TOP LEVEL]
:greet
self
self
rb_control_frame_t
pc
sp
self
type
[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_t
pc
sp
self
type
[TOP LEVEL]
:greet
self
self
rb_control_frame_t
pc
sp
self
type
[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_t
pc
sp
self
type
[TOP LEVEL]
:greet
self
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_t
pc
sp
self
type
[TOP LEVEL]
:greet
self
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_t
pc
sp
self
type
[TOP LEVEL]
:greet
self
special
rb_control_frame_t
pc
sp
self
type
[METHOD]
0004 putstring "hello"
0006 setlocal 2, 0
0010 putself
0011 getlocal 2, 0
0013 opt_send_simple puts
0017 leave
str
svar/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_t
pc
sp
self
type
[TOP LEVEL]
:greet
self
special
rb_control_frame_t
pc
sp
self
type
[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_t
pc
sp
self
type
[TOP LEVEL]
:greet
self
special
rb_control_frame_t
pc
sp
self
type
[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_t
pc
sp
self
type
[TOP LEVEL]
:greet
self
special
rb_control_frame_t
pc
sp
self
type
[METHOD]
str
svar/cref
ep
self
“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_t
pc
sp
self
type
[TOP LEVEL]
:greet
self
special
rb_control_frame_t
pc
sp
self
type
[METHOD]
str
svar/cref
ep
self
“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_t
pc
sp
self
type
[TOP LEVEL]
:greet
self
special
rb_control_frame_t
pc
sp
self
type
[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_t
pc
sp
self
type
[TOP LEVEL]
:greet
self
$ “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_t
pc
sp
self
type
[TOP LEVEL]
:greet
self
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_t
pc
sp
self
type
[TOP LEVEL]
:greet
self
special
rb_control_frame_t
pc
sp
self
type
[METHOD]
0004 putstring "hello"
0006 setlocal 2, 0
0010 putobject 3
0012 send times
0016 leave
str
svar/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_t
pc
sp
self
type
[TOP LEVEL]
:greet
self
special
rb_control_frame_t
pc
sp
self
type
[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_t
pc
sp
self
type
[TOP LEVEL]
:greet
self
special
rb_control_frame_t
pc
sp
self
type
[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_t
pc
sp
self
type
[TOP LEVEL]
:greet
self
special
rb_control_frame_t
pc
sp
self
type
[METHOD]
str
svar/cref
ep
3
“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_t
pc
sp
[TOP LEVEL]
:greet
self
special
rb_control_frame_t
pc
sp
[METHOD]
0004 putstring "hello"
0006 setlocal 2, 0
0010 putobject 3
0012 send times
0016 leave
str
svar/cref
ep
3
“hello”
rb_block_t
iseq
ep
…
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_t
pc
sp
[TOP LEVEL]
:greet
self
special
rb_control_frame_t
pc
sp
[METHOD]
0004 putstring "hello"
0006 setlocal 2, 0
0010 putobject 3
0012 send times
0016 leave
str
svar/cref
ep
3
“hello”
svar/cref
special
rb_block_t
iseq
ep
…
rb_control_frame_t
pc
sp
[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_t
pc
sp
[TOP LEVEL]
:greet
self
special
rb_control_frame_t
pc
sp
[METHOD]
0004 putstring "hello"
0006 setlocal 2, 0
0010 putobject 3
0012 send times
0016 leave
str
svar/cref
ep
3
“hello”
svar/cref
special
svar/cref
rb_block_t
iseq
ep
…
rb_control_frame_t
pc
sp
[METHOD]
ep
times…
rb_con…
pc
sp
[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_t
pc
sp
[TOP LEVEL]
:greet
self
special
rb_control_frame_t
pc
sp
[METHOD]
0004 putstring "hello"
0006 setlocal 2, 0
0010 putobject 3
0012 send times
0016 leave
str
svar/cref
ep
3
“hello”
svar/cref
special
svar/cref
rb_block_t
iseq
ep
…
rb_control_frame_t
pc
sp
[METHOD]
ep
times…
rb_con…
pc
sp
[BLOCK]
ep
special
self
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_t
pc
sp
[TOP LEVEL]
:greet
self
special
rb_control_frame_t
pc
sp
[METHOD]
0004 putstring "hello"
0006 setlocal 2, 0
0010 putobject 3
0012 send times
0016 leave
str
svar/cref
ep
3
“hello”
svar/cref
special
svar/cref
rb_block_t
iseq
ep
…
rb_control_frame_t
pc
sp
[METHOD]
ep
times…
rb_con…
pc
sp
[BLOCK]
ep
0004 putself
0005 getlocal 2, 1
0007 opt_send_simple puts
0011 leave
special
self
“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_t
pc
sp
[TOP LEVEL]
:greet
self
special
rb_control_frame_t
pc
sp
[METHOD]
0004 putstring "hello"
0006 setlocal 2, 0
0010 putobject 3
0012 send times
0016 leave
str
svar/cref
ep
3
“hello”
svar/cref
special
svar/cref
rb_block_t
iseq
ep
…
rb_control_frame_t
pc
sp
[METHOD]
ep
times…
rb_con…
pc
sp
[BLOCK]
ep
0004 putself
0005 getlocal 2, 1
0007 opt_send_simple puts
0011 leave
special
self
$ “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
:greet
self
str
“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_t
pc
sp
[TOP LEVEL]
epf
svar/cref
special
: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_t
pc
sp
[TOP LEVEL]
ep
rb_control_frame_t
pc
sp
[METHOD]
ep
f
svar/cref
special
:greet
self
str
svar/cref
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
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_t
pc
sp
[TOP LEVEL]
ep
rb_control_frame_t
pc
sp
[METHOD]
ep
f
svar/cref
special
:greet
self
str
svar/cref
special
“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_t
pc
sp
[TOP LEVEL]
ep
rb_control_frame_t
pc
sp
[METHOD]
ep
f
svar/cref
special
:greet
self
str
svar/cref
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
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_t
pc
sp
[TOP LEVEL]
ep
rb_control_frame_t
pc
sp
[METHOD]
ep
f
svar/cref
special
:greet
self
str
svar/cref
special
self
rb_control_frame_t
pc
sp
[TOP LEVEL]
epf
svar/cref
special
:greet
self
str
rb_control_frame_t
pc
sp
[METHOD]
epsvar/cref
special
self
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” str
svar/cref
special
self
“hello”
rb_control_frame_t
pc
sp
[TOP LEVEL]
epf
svar/cref
special
:greet
self
str
rb_control_frame_t
pc
sp
[METHOD]
epsvar/cref
special
self
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”
str
svar/cref
special
self
“hello”
rb_control_frame_t
pc
sp
[TOP LEVEL]
epf
svar/cref
special
:greet
self
str
rb_control_frame_t
pc
sp
[METHOD]
epsvar/cref
special
self
lambda
rb_proc_t
rb_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”
str
svar/cref
special
self
“hello”
rb_control_frame_t
pc
sp
[TOP LEVEL]
epf
svar/cref
special
:greet
self
str
rb_control_frame_t
pc
sp
[METHOD]
epsvar/cref
special
self
lambda
rb_proc_t
rb_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”
str
svar/cref
special
self
“hello”
rb_control_frame_t
pc
sp
[TOP LEVEL]
epf
svar/cref
special
:greet
self
str
rb_control_frame_t
pc
sp
[METHOD]
epsvar/cref
special
self
lambda
rb_proc_t
rb_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”
str
svar/cref
special
self
“hello”
rb_control_frame_t
pc
sp
[TOP LEVEL]
epf
svar/cref
special
:greet
self
lambda
str
svar/cref
special
selfrb_proc_t
rb_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_t
pc
sp
[TOP LEVEL]
epf
svar/cref
special
:greet
self
str
svar/cref
special
selfrb_proc_t
rb_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_t
pc
sp
[TOP LEVEL]
epf
svar/cref
special
:greet
self
lambda
str
svar/cref
special
selfrb_proc_t
rb_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_t
pc
sp
[TOP LEVEL]
epf
svar/cref
special
:greet
self
lambda
str
svar/cref
special
selfrb_proc_t
rb_block_t
EP
svar/cref
rb_control_frame_t
pc
sp
[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_t
pc
sp
[TOP LEVEL]
epf
svar/cref
special
:greet
self
lambda
str
svar/cref
special
selfrb_proc_t
rb_block_t
EP
svar/cref
rb_control_frame_t
pc
sp
[BLOCK]
ep
special
self
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_t
pc
sp
[TOP LEVEL]
epf
svar/cref
special
:greet
self
lambda
str
svar/cref
special
selfrb_proc_t
rb_block_t
EP
svar/cref
rb_control_frame_t
pc
sp
[BLOCK]
ep
special
self
“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

More Related Content

PDF
Essentials and Impactful Features of ES6
PDF
async/await Revisited
PDF
Parse Everything With Elixir
PDF
The Magic Of Elixir
PDF
ClojurianからみたElixir
PDF
Top 10 php classic traps DPC 2020
PDF
Top 10 php classic traps confoo
KEY
循環参照のはなし
Essentials and Impactful Features of ES6
async/await Revisited
Parse Everything With Elixir
The Magic Of Elixir
ClojurianからみたElixir
Top 10 php classic traps DPC 2020
Top 10 php classic traps confoo
循環参照のはなし

What's hot (20)

KEY
Building Better Applications with Data::Manager
PDF
I, For One, Welcome Our New Perl6 Overlords
PDF
Perl 6 by example
PDF
R57shell
KEY
Good Evils In Perl (Yapc Asia)
KEY
KEY
10 Catalyst Tips
DOCX
Tugas praktikukm pemrograman c++
PDF
Investigating Python Wats
PDF
Gabriele Lana - The Magic of Elixir
PDF
Melhorando sua API com DSLs
PDF
The Ring programming language version 1.8 book - Part 96 of 202
PDF
[KOSSA] C++ Programming - 17th Study - STL #3
PDF
Aprenda Elixir em um final de semana
PDF
[PL] Jak nie zostać "programistą" PHP?
PPT
PDF
PofEAA and SQLAlchemy
DOC
Useful c programs
PDF
Mdp plus 2.1
Building Better Applications with Data::Manager
I, For One, Welcome Our New Perl6 Overlords
Perl 6 by example
R57shell
Good Evils In Perl (Yapc Asia)
10 Catalyst Tips
Tugas praktikukm pemrograman c++
Investigating Python Wats
Gabriele Lana - The Magic of Elixir
Melhorando sua API com DSLs
The Ring programming language version 1.8 book - Part 96 of 202
[KOSSA] C++ Programming - 17th Study - STL #3
Aprenda Elixir em um final de semana
[PL] Jak nie zostać "programistą" PHP?
PofEAA and SQLAlchemy
Useful c programs
Mdp plus 2.1
Ad

Viewers also liked (16)

PDF
Enumerados Server
PDF
Aplicaciones móviles - HTML5
PDF
Construyendo y publicando nuestra primera app multi plataforma (II)
PDF
Construyendo y publicando nuestra primera app multiplataforma
PPTX
Swift and the BigData
PDF
Javascript - 2014
PDF
iOS Notifications
PDF
PDF
Cassandra for impatients
PDF
Scalable data modelling by example - Cassandra Summit '16
PDF
Case Study: Troubleshooting Cassandra performance issues as a developer
PDF
Programacion web
PDF
Cassandra Workshop - Cassandra from scratch in one day
PDF
Sensors (Accelerometer, Magnetometer, Gyroscope, Proximity and Luminosity)
Enumerados Server
Aplicaciones móviles - HTML5
Construyendo y publicando nuestra primera app multi plataforma (II)
Construyendo y publicando nuestra primera app multiplataforma
Swift and the BigData
Javascript - 2014
iOS Notifications
Cassandra for impatients
Scalable data modelling by example - Cassandra Summit '16
Case Study: Troubleshooting Cassandra performance issues as a developer
Programacion web
Cassandra Workshop - Cassandra from scratch in one day
Sensors (Accelerometer, Magnetometer, Gyroscope, Proximity and Luminosity)
Ad

Similar to Ruby closures, how are they possible? (20)

KEY
Learn Ruby 2011 - Session 5 - Looking for a Rescue
PDF
Message in a bottle
PPT
Advanced Ruby
KEY
PDF
Hijacking Ruby Syntax in Ruby (RubyConf 2018)
PDF
A limited guide to intermediate and advanced Ruby
PDF
Hijacking Ruby Syntax in Ruby
PDF
Blocks and loops.pptx
PDF
Callable and runnable objects in ruby
PDF
Ruby19 osdc-090418222718-phpapp02
PDF
JRuby 9000 - Optimizing Above the JVM
PPTX
Grow and Shrink - Dynamically Extending the Ruby VM Stack
PPTX
7 Methods and Functional Programming
PDF
block
ODP
Ruby Basics by Rafiq
ODP
What I Love About Ruby
PPTX
Ruby from zero to hero
PDF
Ruby : Block, Proc and, lambda
PDF
Ruby_Basic
PDF
Ruby Intro {spection}
Learn Ruby 2011 - Session 5 - Looking for a Rescue
Message in a bottle
Advanced Ruby
Hijacking Ruby Syntax in Ruby (RubyConf 2018)
A limited guide to intermediate and advanced Ruby
Hijacking Ruby Syntax in Ruby
Blocks and loops.pptx
Callable and runnable objects in ruby
Ruby19 osdc-090418222718-phpapp02
JRuby 9000 - Optimizing Above the JVM
Grow and Shrink - Dynamically Extending the Ruby VM Stack
7 Methods and Functional Programming
block
Ruby Basics by Rafiq
What I Love About Ruby
Ruby from zero to hero
Ruby : Block, Proc and, lambda
Ruby_Basic
Ruby Intro {spection}

Recently uploaded (20)

PDF
Well-logging-methods_new................
PDF
Mohammad Mahdi Farshadian CV - Prospective PhD Student 2026
PDF
Mitigating Risks through Effective Management for Enhancing Organizational Pe...
PDF
keyrequirementskkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk
PPTX
Infosys Presentation by1.Riyan Bagwan 2.Samadhan Naiknavare 3.Gaurav Shinde 4...
PPTX
CYBER-CRIMES AND SECURITY A guide to understanding
PDF
R24 SURVEYING LAB MANUAL for civil enggi
PPTX
UNIT-1 - COAL BASED THERMAL POWER PLANTS
PDF
The CXO Playbook 2025 – Future-Ready Strategies for C-Suite Leaders Cerebrai...
PPTX
IOT PPTs Week 10 Lecture Material.pptx of NPTEL Smart Cities contd
PDF
Model Code of Practice - Construction Work - 21102022 .pdf
PPTX
additive manufacturing of ss316l using mig welding
PPTX
Sustainable Sites - Green Building Construction
PPTX
Foundation to blockchain - A guide to Blockchain Tech
PPTX
CARTOGRAPHY AND GEOINFORMATION VISUALIZATION chapter1 NPTE (2).pptx
PPT
Project quality management in manufacturing
PDF
PPT on Performance Review to get promotions
PDF
Embodied AI: Ushering in the Next Era of Intelligent Systems
PDF
Automation-in-Manufacturing-Chapter-Introduction.pdf
PPTX
Engineering Ethics, Safety and Environment [Autosaved] (1).pptx
Well-logging-methods_new................
Mohammad Mahdi Farshadian CV - Prospective PhD Student 2026
Mitigating Risks through Effective Management for Enhancing Organizational Pe...
keyrequirementskkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk
Infosys Presentation by1.Riyan Bagwan 2.Samadhan Naiknavare 3.Gaurav Shinde 4...
CYBER-CRIMES AND SECURITY A guide to understanding
R24 SURVEYING LAB MANUAL for civil enggi
UNIT-1 - COAL BASED THERMAL POWER PLANTS
The CXO Playbook 2025 – Future-Ready Strategies for C-Suite Leaders Cerebrai...
IOT PPTs Week 10 Lecture Material.pptx of NPTEL Smart Cities contd
Model Code of Practice - Construction Work - 21102022 .pdf
additive manufacturing of ss316l using mig welding
Sustainable Sites - Green Building Construction
Foundation to blockchain - A guide to Blockchain Tech
CARTOGRAPHY AND GEOINFORMATION VISUALIZATION chapter1 NPTE (2).pptx
Project quality management in manufacturing
PPT on Performance Review to get promotions
Embodied AI: Ushering in the Next Era of Intelligent Systems
Automation-in-Manufacturing-Chapter-Introduction.pdf
Engineering Ethics, Safety and Environment [Autosaved] (1).pptx

Ruby closures, how are they possible?

  • 1. Ruby closures How are they possible? Carlos Alonso Software Engineer @calonso
  • 2. A story about curiosity…
  • 7. def greet str = “hello” lambda do puts str end end f = greet f.call # => hello
  • 8. def greet str = “hello” lambda do puts str end end f = greet f.call # => hello
  • 9. def greet str = “hello” lambda do puts str end end f = greet f.call # => hello This talk!
  • 11. a = 1 def sum a + 1 end sum
  • 12. a = 1 def sum a + 1 end sum NameError: Undefined `a’
  • 13. def run_block yield end a = 1 run_block { a + 1 }
  • 14. def run_block yield end a = 1 run_block { a + 1 } 2
  • 15. def run_block a = 1 yield end run_block { a + 1 }
  • 16. def run_block a = 1 yield end run_block { a + 1 } NameError: Undefined `a’
  • 17. def run_block a = 100 yield end a = 1 run_block { a + 1 }
  • 18. def run_block a = 100 yield end a = 1 run_block { a + 1 } 2
  • 19. a = 1 sum = lambda do a + 1 end a = 2 sum.call
  • 20. a = 1 sum = lambda do a + 1 end a = 2 sum.call 3
  • 22. What is a closure? A lambda expression + an environment to run it
  • 23. Blocks refer to variables declared in the scope where they were defined, not where they are executed. Lexical scope
  • 24. Ruby uses lexical scope. Let’s see this scopes!!
  • 25. a = 1 def sum a + 1 end sum
  • 26. a = 1 def sum a + 1 end sum top-level a = 1 sum = …
  • 27. a = 1 def sum a + 1 end sum top-level a = 1 sum = … sum a??
  • 28. a = 1 def sum a + 1 end sum top-level a = 1 sum = … sum a?? NameError: Undefined `a’
  • 29. def run_block(&block) yield end a = 1 run_block { a + 1 }
  • 30. def run_block(&block) yield end a = 1 run_block { a + 1 } top-level run_block = … a = 1
  • 31. def run_block(&block) yield end a = 1 run_block { a + 1 } top-level run_block = … a = 1 run_block block
  • 32. def run_block(&block) yield end a = 1 run_block { a + 1 } top-level run_block = … a = 1 in-block a run_block block
  • 33. 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
  • 34. def run_block(&block) a = 1 yield end run_block { a + 1 }
  • 35. def run_block(&block) a = 1 yield end run_block { a + 1 } top-level run_block = …
  • 36. def run_block(&block) a = 1 yield end run_block { a + 1 } top-level run_block = … run_block a = 1 block
  • 37. def run_block(&block) a = 1 yield end run_block { a + 1 } top-level run_block = … in-block a?? run_block a = 1 block
  • 38. 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’
  • 39. def run_block(&block) a = 100 yield end a = 1 run_block { a + 1 }
  • 40. def run_block(&block) a = 100 yield end a = 1 run_block { a + 1 } top-level run_block = … a = 1
  • 41. 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
  • 42. 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
  • 43. 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
  • 44. a = 1 sum = lambda do a + 1 end a = 2 sum.call
  • 45. a = 1 sum = lambda do a + 1 end a = 2 sum.call top-level a = 2 sum…
  • 46. a = 1 sum = lambda do a + 1 end a = 2 sum.call top-level a = 2 sum… in-lambda a
  • 47. a = 1 sum = lambda do a + 1 end a = 2 sum.call top-level a = 2 sum… in-lambda a 3
  • 48. Cool!! The lexical scope explains the examples
  • 49. Cool!! The lexical scope explains the examples But… how exactly??
  • 50. Ok, let’s start from scratch. How does Ruby executes programs?
  • 52. 0002 putself 0003 putobject 2 0005 putobject 2 0007 opt_plus 0009 opt_send_simple puts 0011 leave 2 rb_control_frame_t pc sp self type YARV internal stack [TOP LEVEL] self 2 YARV Control structures stack YARV Instructions CFP
  • 54. == 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
  • 55. 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_t pc sp self type [TOP LEVEL] def greet puts “hello” end greet
  • 56. 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_t pc sp self type [TOP LEVEL] :greet def greet puts “hello” end greet
  • 57. 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_t pc sp self type [TOP LEVEL] :greet greet def greet puts “hello” end greet
  • 58. 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_t pc sp self type [TOP LEVEL] :greet greet def greet puts “hello” end greet
  • 59. 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_t pc sp self type [TOP LEVEL] :greet def greet puts “hello” end greet
  • 60. 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_t pc sp self type [TOP LEVEL] :greet self def greet puts “hello” end greet
  • 61. 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_t pc sp self type [TOP LEVEL] :greet self rb_control_frame_t pc sp self type [METHOD] 0004 putself 0005 putstring "hello" 0007 opt_send_simple puts 0011 leave svar/cref special def greet puts “hello” end greet
  • 62. 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_t pc sp self type [TOP LEVEL] :greet self self rb_control_frame_t pc sp self type [METHOD] 0004 putself 0005 putstring "hello" 0007 opt_send_simple puts 0011 leave svar/cref special def greet puts “hello” end greet
  • 63. 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_t pc sp self type [TOP LEVEL] :greet self self rb_control_frame_t pc sp self type [METHOD] 0004 putself 0005 putstring "hello" 0007 opt_send_simple puts 0011 leave svar/cref special “hello” def greet puts “hello” end greet
  • 64. 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_t pc sp self type [TOP LEVEL] :greet self self rb_control_frame_t pc sp self type [METHOD] 0004 putself 0005 putstring "hello" 0007 opt_send_simple puts 0011 leave svar/cref special $ “hello” def greet puts “hello” end greet
  • 65. 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_t pc sp self type [TOP LEVEL] :greet self def greet puts “hello” end greet
  • 66. Ok cool, what if the method has local variables?
  • 67. == 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
  • 68. local table (size: 2, argc: 0 [opts: 0, rest: -1, post: 0, block: -1, keyword: 0@3] s1) [ 2] str The local table
  • 69. 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_t pc sp self type [TOP LEVEL] :greet self def greet str = “hello” puts str end greet
  • 70. 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_t pc sp self type [TOP LEVEL] :greet self special rb_control_frame_t pc sp self type [METHOD] 0004 putstring "hello" 0006 setlocal 2, 0 0010 putself 0011 getlocal 2, 0 0013 opt_send_simple puts 0017 leave str svar/cref ep def greet str = “hello” puts str end greet
  • 71. 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_t pc sp self type [TOP LEVEL] :greet self special rb_control_frame_t pc sp self type [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
  • 72. 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_t pc sp self type [TOP LEVEL] :greet self special rb_control_frame_t pc sp self type [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
  • 73. 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_t pc sp self type [TOP LEVEL] :greet self special rb_control_frame_t pc sp self type [METHOD] str svar/cref ep self “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
  • 74. 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_t pc sp self type [TOP LEVEL] :greet self special rb_control_frame_t pc sp self type [METHOD] str svar/cref ep self “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
  • 75. 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_t pc sp self type [TOP LEVEL] :greet self special rb_control_frame_t pc sp self type [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
  • 76. 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_t pc sp self type [TOP LEVEL] :greet self $ “hello” def greet str = “hello” puts str end greet
  • 77. Got it, but what about blocks accessing variables on lexical scope?
  • 78. ……… == 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
  • 79. 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_t pc sp self type [TOP LEVEL] :greet self def greet str = “hello” 3.times do puts str end end greet
  • 80. 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_t pc sp self type [TOP LEVEL] :greet self special rb_control_frame_t pc sp self type [METHOD] 0004 putstring "hello" 0006 setlocal 2, 0 0010 putobject 3 0012 send times 0016 leave str svar/cref ep def greet str = “hello” 3.times do puts str end end greet
  • 81. 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_t pc sp self type [TOP LEVEL] :greet self special rb_control_frame_t pc sp self type [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
  • 82. 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_t pc sp self type [TOP LEVEL] :greet self special rb_control_frame_t pc sp self type [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
  • 83. 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_t pc sp self type [TOP LEVEL] :greet self special rb_control_frame_t pc sp self type [METHOD] str svar/cref ep 3 “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
  • 84. 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_t pc sp [TOP LEVEL] :greet self special rb_control_frame_t pc sp [METHOD] 0004 putstring "hello" 0006 setlocal 2, 0 0010 putobject 3 0012 send times 0016 leave str svar/cref ep 3 “hello” rb_block_t iseq ep … 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
  • 85. 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_t pc sp [TOP LEVEL] :greet self special rb_control_frame_t pc sp [METHOD] 0004 putstring "hello" 0006 setlocal 2, 0 0010 putobject 3 0012 send times 0016 leave str svar/cref ep 3 “hello” svar/cref special rb_block_t iseq ep … rb_control_frame_t pc sp [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
  • 86. 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_t pc sp [TOP LEVEL] :greet self special rb_control_frame_t pc sp [METHOD] 0004 putstring "hello" 0006 setlocal 2, 0 0010 putobject 3 0012 send times 0016 leave str svar/cref ep 3 “hello” svar/cref special svar/cref rb_block_t iseq ep … rb_control_frame_t pc sp [METHOD] ep times… rb_con… pc sp [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
  • 87. 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_t pc sp [TOP LEVEL] :greet self special rb_control_frame_t pc sp [METHOD] 0004 putstring "hello" 0006 setlocal 2, 0 0010 putobject 3 0012 send times 0016 leave str svar/cref ep 3 “hello” svar/cref special svar/cref rb_block_t iseq ep … rb_control_frame_t pc sp [METHOD] ep times… rb_con… pc sp [BLOCK] ep special self 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
  • 88. 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_t pc sp [TOP LEVEL] :greet self special rb_control_frame_t pc sp [METHOD] 0004 putstring "hello" 0006 setlocal 2, 0 0010 putobject 3 0012 send times 0016 leave str svar/cref ep 3 “hello” svar/cref special svar/cref rb_block_t iseq ep … rb_control_frame_t pc sp [METHOD] ep times… rb_con… pc sp [BLOCK] ep 0004 putself 0005 getlocal 2, 1 0007 opt_send_simple puts 0011 leave special self “hello” def greet str = “hello” 3.times do puts str end end greet
  • 89. 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_t pc sp [TOP LEVEL] :greet self special rb_control_frame_t pc sp [METHOD] 0004 putstring "hello" 0006 setlocal 2, 0 0010 putobject 3 0012 send times 0016 leave str svar/cref ep 3 “hello” svar/cref special svar/cref rb_block_t iseq ep … rb_control_frame_t pc sp [METHOD] ep times… rb_con… pc sp [BLOCK] ep 0004 putself 0005 getlocal 2, 1 0007 opt_send_simple puts 0011 leave special self $ “hello” def greet str = “hello” 3.times do puts str end end greet
  • 91. And what if that scope doesn’t exist anymore?
  • 92. The heap and rb_proc_t to the rescue! o/
  • 94. == 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
  • 95. 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_t pc sp [TOP LEVEL] epf svar/cref special :greet self
  • 96. [ 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_t pc sp [TOP LEVEL] ep rb_control_frame_t pc sp [METHOD] ep f svar/cref special :greet self str svar/cref special
  • 97. [ 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_t pc sp [TOP LEVEL] ep rb_control_frame_t pc sp [METHOD] ep f svar/cref special :greet self str svar/cref special “hello”
  • 98. [ 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_t pc sp [TOP LEVEL] ep rb_control_frame_t pc sp [METHOD] ep f svar/cref special :greet self str svar/cref special
  • 99. [ 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_t pc sp [TOP LEVEL] ep rb_control_frame_t pc sp [METHOD] ep f svar/cref special :greet self str svar/cref special self
  • 100. rb_control_frame_t pc sp [TOP LEVEL] epf svar/cref special :greet self str rb_control_frame_t pc sp [METHOD] epsvar/cref special self 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” str svar/cref special self “hello”
  • 101. rb_control_frame_t pc sp [TOP LEVEL] epf svar/cref special :greet self str rb_control_frame_t pc sp [METHOD] epsvar/cref special self 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” str svar/cref special self “hello”
  • 102. rb_control_frame_t pc sp [TOP LEVEL] epf svar/cref special :greet self str rb_control_frame_t pc sp [METHOD] epsvar/cref special self lambda rb_proc_t rb_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” str svar/cref special self “hello”
  • 103. rb_control_frame_t pc sp [TOP LEVEL] epf svar/cref special :greet self str rb_control_frame_t pc sp [METHOD] epsvar/cref special self lambda rb_proc_t rb_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” str svar/cref special self “hello”
  • 104. rb_control_frame_t pc sp [TOP LEVEL] epf svar/cref special :greet self str rb_control_frame_t pc sp [METHOD] epsvar/cref special self lambda rb_proc_t rb_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” str svar/cref special self “hello”
  • 105. rb_control_frame_t pc sp [TOP LEVEL] epf svar/cref special :greet self lambda str svar/cref special selfrb_proc_t rb_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”
  • 106. rb_control_frame_t pc sp [TOP LEVEL] epf svar/cref special :greet self str svar/cref special selfrb_proc_t rb_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”
  • 107. rb_control_frame_t pc sp [TOP LEVEL] epf svar/cref special :greet self lambda str svar/cref special selfrb_proc_t rb_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”
  • 108. rb_control_frame_t pc sp [TOP LEVEL] epf svar/cref special :greet self lambda str svar/cref special selfrb_proc_t rb_block_t EP svar/cref rb_control_frame_t pc sp [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”
  • 109. rb_control_frame_t pc sp [TOP LEVEL] epf svar/cref special :greet self lambda str svar/cref special selfrb_proc_t rb_block_t EP svar/cref rb_control_frame_t pc sp [BLOCK] ep special self 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”
  • 110. rb_control_frame_t pc sp [TOP LEVEL] epf svar/cref special :greet self lambda str svar/cref special selfrb_proc_t rb_block_t EP svar/cref rb_control_frame_t pc sp [BLOCK] ep special self “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”