Discussion:
[jruby-dev] IR: push/pop binding and variable load/stores
Charles Oliver Nutter
2014-01-31 11:56:48 UTC
Permalink
Ok, so I got frame push/pop working and wanted to move on to binding.
I was under the impression that push/pop binding was basically for
pushing/popping a DynamicScope, but it seems like it's more than that.

For the following code: def foo; a = 1; eval 'p a'; end

We get these linearized instructions:

Linearized instructions for JIT:

0 push_frame
1 push_binding(INSTANCE_METHOD foo[-e:0])
2 check_arity(0, 0, -1)
3 %t_%block_1 = recv_closure
4 thread_poll
5 line_num(0)
6 %t_a_2 = Fixnum:1
7 store_lvar(%t_a_2, foo, a(0:1))
8 store_lvar(%t_%block_1, foo, %block(0:0))
9 %v_0 = call_1o(FUNCTIONAL, 'eval', %self, ["p a"]){1O}
10 pop_binding
11 pop_frame
12 return(%v_0)
13 %v_3 = recv_jruby_exc
14 pop_binding
15 pop_frame
16 throw(%v_3)

Note that there's a store_lvar for the temporary "a" variable into the
heap "a" variable, but there's also a store for the temporary "%block"
variable. If I represent binding as DynamicScope, this isn't
supportable; the scope entries only support IRubyObject.

In the current runtime, the binding's block lives on the frame, not on
the scope.

I think this is a problem with the explicit heap load/store
instructions. The block will already have been saved to the frame in
pushFrame, and eval will great a binding on demand using frame +
scope. So if push/pop binding just manipulate scope and block is not
part of the explicit stores, I think this will work.

Looking into it now, but I welcome comments.

- Charlie

---------------------------------------------------------------------
To unsubscribe from this list, please visit:

http://xircles.codehaus.org/manage_email
Subramanya Sastry
2014-01-31 15:48:46 UTC
Permalink
On Fri, Jan 31, 2014 at 5:56 AM, Charles Oliver Nutter
Post by Charles Oliver Nutter
Ok, so I got frame push/pop working and wanted to move on to binding.
I was under the impression that push/pop binding was basically for
pushing/popping a DynamicScope, but it seems like it's more than that.
For the following code: def foo; a = 1; eval 'p a'; end
0 push_frame
1 push_binding(INSTANCE_METHOD foo[-e:0])
2 check_arity(0, 0, -1)
3 %t_%block_1 = recv_closure
This is only used to receive "&blk" arg which is a Proc and hence an
IRubyObject.

I was baffled for a bit as well how the Interpreter works on this and
realized what was going on when I looked at how this instr. is interpreted.
I think the name of the instruction is confusing. Maybe we should change it
to receive_proc or something else to indicate this?

However, I forget the reasoning why I always add it to the arg-receive
protocol. I'll have to dig into IRBuilder or look into it later.

Subbu.
Post by Charles Oliver Nutter
4 thread_poll
5 line_num(0)
6 %t_a_2 = Fixnum:1
7 store_lvar(%t_a_2, foo, a(0:1))
8 store_lvar(%t_%block_1, foo, %block(0:0))
9 %v_0 = call_1o(FUNCTIONAL, 'eval', %self, ["p a"]){1O}
10 pop_binding
11 pop_frame
12 return(%v_0)
13 %v_3 = recv_jruby_exc
14 pop_binding
15 pop_frame
16 throw(%v_3)
Note that there's a store_lvar for the temporary "a" variable into the
heap "a" variable, but there's also a store for the temporary "%block"
variable. If I represent binding as DynamicScope, this isn't
supportable; the scope entries only support IRubyObject.
In the current runtime, the binding's block lives on the frame, not on
the scope.
I think this is a problem with the explicit heap load/store
instructions. The block will already have been saved to the frame in
pushFrame, and eval will great a binding on demand using frame +
scope. So if push/pop binding just manipulate scope and block is not
part of the explicit stores, I think this will work.
Looking into it now, but I welcome comments.
- Charlie
---------------------------------------------------------------------
http://xircles.codehaus.org/manage_email
Subramanya Sastry
2014-01-31 15:55:57 UTC
Permalink
Post by Charles Oliver Nutter
3 %t_%block_1 = recv_closure
This is only used to receive "&blk" arg which is a Proc and hence an
IRubyObject.
I was baffled for a bit as well how the Interpreter works on this and
realized what was going on when I looked at how this instr. is interpreted.
result = (block == Block.NULL_BLOCK) ? context.nil :
context.runtime.newProc(Block.Type.PROC, block);

Subbu.
Thomas E Enebo
2014-01-31 22:44:26 UTC
Permalink
I will convert %block and %self to be temporary variables this weekend. It
is arguable whether we need these to be variables at all but making them
temp vars will eliminate any issues with binding var stuff.

-Tom
Post by Charles Oliver Nutter
3 %t_%block_1 = recv_closure
Post by Subramanya Sastry
This is only used to receive "&blk" arg which is a Proc and hence an
IRubyObject.
I was baffled for a bit as well how the Interpreter works on this and
realized what was going on when I looked at how this instr. is interpreted.
context.runtime.newProc(Block.Type.PROC, block);
Subbu.
--
blog: http://blog.enebo.com twitter: tom_enebo
mail: tom.enebo-***@public.gmane.org
Loading...