Class: CastOff::Compiler::Iseq
- Inherits:
-
Object
- Object
- CastOff::Compiler::Iseq
show all
- Includes:
- Util
- Defined in:
- lib/cast_off/compile/iseq.rb
Defined Under Namespace
Classes: Args
Constant Summary
collapse
- IfuncNodeGeneratorTemplate =
ERB.new("static void <%= ifunc_node_generator() %>()\n{\n%# NEW_IFUNC \u306E\u7B2C\u4E8C\u5F15\u6570\u306F Proc \u306B\u5BFE\u3057\u3066\u6E21\u305B\u308B\u597D\u304D\u306A\u5024\n%#<%= @ifunc_node_name %> = NEW_IFUNC(<%= @ifunc_name %>, <%= self %>->self); \n <%= @ifunc_node_name %> = NEW_IFUNC(<%= @ifunc_name %>, Qnil); \n%# nd_aid = 0 \u3060\u3068 rb_frame_this_func \u3067 <ifunc> \u3068\u306A\u308B\u3002\n <%= @ifunc_node_name %>->nd_aid = 0;\n rb_gc_register_mark_object((VALUE)<%= @ifunc_node_name %>);\n}\n", 0, '%-', 'io')
- BlockGeneratorTemplate =
ERB.new("<%= declare_block_generator() %>\n{\n VALUE thval = rb_thread_current();\n rb_thread_t * th = DATA_PTR(thval);\n rb_control_frame_t *cfp = th->cfp;\n rb_block_t *blockptr = (rb_block_t *)(&(cfp)->self);\n /* cfp \u306E self \u4EE5\u4E0B\u304C block \u69CB\u9020\u4F53\u306E\u30E1\u30F3\u30D0\u3068\u306A\u308B */\n\n blockptr->iseq = (void *)<%= @ifunc_node_name %>;\n blockptr->proc = 0;\n blockptr->self = self; /* for CastOff.execute */\n\n return blockptr;\n}\n", 0, '%-', 'io')
- IfuncTemplate =
ERB.new("<%= declare_ifunc() %>\n{\n /* decl variables */\n rb_thread_t *th = current_thread();\n VALUE cast_off_argv[<%= own_argv_size() %>];\n VALUE cast_off_tmp;\n VALUE sampling_tmp;\n VALUE self = get_self(th);\n int lambda_p = cast_off_lambda_p(arg, argc, argv);\n int i, num;\n<%= declare_dfp %>\n<%= (own_local_variable_declarations).map{|v| \" \#{v};\"}.join(\"\\n\") %>\n\n% bug() if root?\n expand_dframe(th, <%= @lvars.size %>, <%= self %>, 0);\n<%= update_dfp %>\n\n%inits = own_initializations_for_guards\n%bug() if inits.uniq!\n%inits.join(\"\\n\")\n\n /* setup arguments */\n if (lambda_p) {\n% bug() if @args.simple? && @args.arg_size != @args.argc\n num = cast_off_prepare_iter_api_lambda_args(<%= @args.arg_size %>, cast_off_argv, argc, argv, <%= @args.simple? ? 1 : 0 %>, <%= @args.argc %>, <%= @args.opt_len %>, <%= @args.post_len %>, <%= @args.post_start %>, <%= @args.rest_index %>);\n } else {\n num = cast_off_prepare_iter_api_block_args(<%= @args.arg_size %>, cast_off_argv, argc, argv, <%= @args.splat? ? 1 : 0 %>, <%= @args.argc %>, <%= @args.opt_len %>, <%= @args.post_len %>, <%= @args.post_start %>, <%= @args.rest_index %>);\n }\n%if @args.block?\n cast_off_argv[<%= @args.block_index %>] = blockarg;\n%end\n\n<%= enclose_begin %>\n\n%#if reference_constant?\n%# check_cref(th);\n%#end\n\n /* body */\n<%= own_c_function_body() %>\n\n%iterate_own_guards do |code, insns|\n{\n long pc;\n <%= enclose_end_deoptimize %>\n%code_label = \"deoptimize_\#{code.hash.to_s.gsub(/-/, \"_\")}\"\n% insns.uniq.each do |insn|\n<%= insn.guard_label %>:\n pc = <%= insn.pc %>;\n goto <%= code_label %>;\n% end\n<%= code_label %>:\n<%= code %>\n}\n%end\n\n<%= enclose_end %>\n}\n", 0, '%-', 'io')
- ExceptionHandlerTemplate =
ERB.new(" {\n int state;\n rb_control_frame_t *volatile cfp;\n\n th = current_thread();\n cfp = th->cfp;\n\n TH_PUSH_TAG(th);\n if ((state = EXEC_TAG()) != 0) {\nVALUE excval;\n\nth = current_thread();\nwhile (th->cfp != cfp) {\n th->cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(th->cfp);\n}\n\n%@excs.each do |(exc, entries)|\nswitch(state) {\n% case exc\n% when :break\ncase TAG_BREAK:\n excval = catch_break(th);\n if (excval != Qundef) {\n switch((int)(cfp->pc - cfp->iseq->iseq_encoded)) {\n% entries.each do |(pc, label, stack)|\n case <%= pc %>:\n<%= update_dfp(12) %>\n tmp<%= stack - 1 %> = excval; /* FIXME */\n goto <%= label %>;\n% end\n default:\n rb_bug(\"failed to found break target\");\n }\n }\n% when :return\ncase TAG_RETURN:\n excval = catch_return(th);\n if (excval != Qundef) {\n /* vm_pop_frame is called at the vm_call_method() */\n TH_POP_TAG2();\n return excval;\n }\n% else\n% bug()\n% end\n}\nTH_POP_TAG2();\nTH_JUMP_TAG(th, state);\n%end\n }\n", 0, '%-', 'io')
Instance Attribute Summary collapse
Instance Method Summary
collapse
Methods included from Util
#bug, #dlog, #todo, #vlog
Constructor Details
#initialize(iseq, parent, depth, ppc) ⇒ Iseq
Returns a new instance of Iseq.
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
|
# File 'lib/cast_off/compile/iseq.rb', line 69
def initialize(iseq, parent, depth, ppc)
bug() unless iseq.is_a?(RubyVM::InstructionSequence)
@iseq = iseq
ary = iseq.to_a
@name = ary[5]
@source_file = ary[7]
@source_line = ary[8]
@itype = ary[9]
args = ary[11]
@args = Args.new(args, self)
if @source_file && File.exist?(@source_file)
@source = File.readlines(@source_file)
else
@source = nil
end
@parent = parent
@children = {}
bug() unless depth.is_a?(Fixnum)
@depth = depth
@parent_pc = ppc
@generation = 0
p = @parent
while p
p = p.parent
@generation += 1
end
bug() if !root? && @generation < 1
@argv_size = 1
@initialize_for_guards = []
@guard_codes = {}
@local_variable_declarations = []
@c_function_body = ""
@c_name = "iseq_#{@iseq.hash.to_s.gsub(/-/, "_")}"
@ifunc_name = "ifunc_#{@c_name}"
@ifunc_node_name = "ifunc_node_#{@c_name}"
@excs = {}
@reference_constant_p = false
@loopkey = nil
end
|
Instance Attribute Details
#args ⇒ Object
Returns the value of attribute args.
8
9
10
|
# File 'lib/cast_off/compile/iseq.rb', line 8
def args
@args
end
|
#children ⇒ Object
Returns the value of attribute children.
8
9
10
|
# File 'lib/cast_off/compile/iseq.rb', line 8
def children
@children
end
|
#depth ⇒ Object
Returns the value of attribute depth.
8
9
10
|
# File 'lib/cast_off/compile/iseq.rb', line 8
def depth
@depth
end
|
#generation ⇒ Object
Returns the value of attribute generation.
8
9
10
|
# File 'lib/cast_off/compile/iseq.rb', line 8
def generation
@generation
end
|
#iseq ⇒ Object
Returns the value of attribute iseq.
8
9
10
|
# File 'lib/cast_off/compile/iseq.rb', line 8
def iseq
@iseq
end
|
#itype ⇒ Object
Returns the value of attribute itype.
8
9
10
|
# File 'lib/cast_off/compile/iseq.rb', line 8
def itype
@itype
end
|
#loopkey ⇒ Object
Returns the value of attribute loopkey.
8
9
10
|
# File 'lib/cast_off/compile/iseq.rb', line 8
def loopkey
@loopkey
end
|
#lvars ⇒ Object
Returns the value of attribute lvars.
8
9
10
|
# File 'lib/cast_off/compile/iseq.rb', line 8
def lvars
@lvars
end
|
#name ⇒ Object
Returns the value of attribute name.
8
9
10
|
# File 'lib/cast_off/compile/iseq.rb', line 8
def name
@name
end
|
#parent ⇒ Object
Returns the value of attribute parent.
8
9
10
|
# File 'lib/cast_off/compile/iseq.rb', line 8
def parent
@parent
end
|
#parent_pc ⇒ Object
Returns the value of attribute parent_pc.
8
9
10
|
# File 'lib/cast_off/compile/iseq.rb', line 8
def parent_pc
@parent_pc
end
|
#source ⇒ Object
Returns the value of attribute source.
8
9
10
|
# File 'lib/cast_off/compile/iseq.rb', line 8
def source
@source
end
|
#source_file ⇒ Object
Returns the value of attribute source_file.
8
9
10
|
# File 'lib/cast_off/compile/iseq.rb', line 8
def source_file
@source_file
end
|
#source_line ⇒ Object
Returns the value of attribute source_line.
8
9
10
|
# File 'lib/cast_off/compile/iseq.rb', line 8
def source_line
@source_line
end
|
Instance Method Details
#add(child, pc) ⇒ Object
121
122
123
124
125
126
|
# File 'lib/cast_off/compile/iseq.rb', line 121
def add(child, pc)
bug() unless child.is_a?(Iseq)
bug() unless pc.is_a?(Fixnum)
bug() if @children[pc]
@children[pc] = child
end
|
#all_argv_size ⇒ Object
169
170
171
172
173
|
# File 'lib/cast_off/compile/iseq.rb', line 169
def all_argv_size()
o = own_argv_size()
c = @children.values.map{|i| i.all_argv_size()}
[o, c].flatten.max()
end
|
#all_c_function_body ⇒ Object
154
155
156
157
158
|
# File 'lib/cast_off/compile/iseq.rb', line 154
def all_c_function_body()
o = own_c_function_body()
c = @children.values.map{|i| i.all_c_function_body() }.join("\n")
[o, c].join("\n")
end
|
#all_initializations_for_guards ⇒ Object
197
198
199
200
201
202
203
204
|
# File 'lib/cast_off/compile/iseq.rb', line 197
def all_initializations_for_guards()
ret = []
ret += own_initializations_for_guards()
@children.values.each{|c| ret += c.all_initializations_for_guards() }
ret.uniq()
end
|
#all_local_variable_declarations ⇒ Object
183
184
185
186
187
|
# File 'lib/cast_off/compile/iseq.rb', line 183
def all_local_variable_declarations()
o = own_local_variable_declarations()
c = @children.values.map{|i| i.all_local_variable_declarations() }
[o, c].flatten.uniq()
end
|
#ancestors ⇒ Object
132
133
134
135
136
137
138
139
140
|
# File 'lib/cast_off/compile/iseq.rb', line 132
def ancestors
a = []
s = self.parent
while s
a << s
s = s.parent
end
a
end
|
#append_c_function_body(code) ⇒ Object
150
151
152
|
# File 'lib/cast_off/compile/iseq.rb', line 150
def append_c_function_body(code)
@c_function_body = [@c_function_body, code].join("\n")
end
|
#block_generator ⇒ Object
282
283
284
|
# File 'lib/cast_off/compile/iseq.rb', line 282
def block_generator()
"cast_off_create_block_#{@c_name}"
end
|
#catch_exception(exc, pc, label, stack) ⇒ Object
439
440
441
442
443
|
# File 'lib/cast_off/compile/iseq.rb', line 439
def catch_exception(exc, pc, label, stack)
@excs[exc] ||= []
entry = [pc, label, stack]
@excs[exc] << entry unless @excs[exc].include?(entry)
end
|
#catch_exception? ⇒ Boolean
435
436
437
|
# File 'lib/cast_off/compile/iseq.rb', line 435
def catch_exception?
not @excs.empty?
end
|
#declare_block_generator ⇒ Object
274
275
276
|
# File 'lib/cast_off/compile/iseq.rb', line 274
def declare_block_generator()
"rb_block_t *#{block_generator()}(VALUE self)"
end
|
#declare_dfp(indent = 2) ⇒ Object
286
287
288
289
|
# File 'lib/cast_off/compile/iseq.rb', line 286
def declare_dfp(indent = 2)
indent = ' ' * indent
(0..@generation).map{|i| "#{indent}VALUE *dfp#{i};"}.join("\n")
end
|
#declare_ifunc ⇒ Object
357
358
359
|
# File 'lib/cast_off/compile/iseq.rb', line 357
def declare_ifunc()
"static VALUE #{@ifunc_name}(VALUE arg, VALUE dummy, int argc, VALUE *argv, VALUE blockarg)"
end
|
#declare_ifunc_node ⇒ Object
233
234
235
|
# File 'lib/cast_off/compile/iseq.rb', line 233
def declare_ifunc_node()
"static NODE *#{@ifunc_node_name}"
end
|
#declare_local_variable(v) ⇒ Object
179
180
181
|
# File 'lib/cast_off/compile/iseq.rb', line 179
def declare_local_variable(v)
@local_variable_declarations << v
end
|
#define_block_generator ⇒ Object
278
279
280
|
# File 'lib/cast_off/compile/iseq.rb', line 278
def define_block_generator()
BlockGeneratorTemplate.trigger(binding)
end
|
#define_ifunc ⇒ Object
361
362
363
|
# File 'lib/cast_off/compile/iseq.rb', line 361
def define_ifunc()
IfuncTemplate.trigger(binding)
end
|
#define_ifunc_node_generator ⇒ Object
249
250
251
|
# File 'lib/cast_off/compile/iseq.rb', line 249
def define_ifunc_node_generator()
IfuncNodeGeneratorTemplate.trigger(binding)
end
|
#delete_labels(ls) ⇒ Object
445
446
447
448
449
450
451
452
453
|
# File 'lib/cast_off/compile/iseq.rb', line 445
def delete_labels(ls)
entries = @excs[:break]
return unless entries
entries.delete_if do |(pc, label, stack)|
del_p = ls.include?(label)
dlog("#{self}: delete break label #{label}") if del_p
del_p
end
end
|
#enclose_begin ⇒ Object
418
419
420
421
|
# File 'lib/cast_off/compile/iseq.rb', line 418
def enclose_begin()
return '' if @excs.empty?
ExceptionHandlerTemplate.trigger(binding)
end
|
#enclose_end ⇒ Object
423
424
425
426
427
428
429
|
# File 'lib/cast_off/compile/iseq.rb', line 423
def enclose_end()
@excs.empty? ? '' : " TH_POP_TAG();\n rb_bug(\"enclose_end: should not be reached\");\n }\n EOS\nend\n"
|
#enclose_end_deoptimize ⇒ Object
431
432
433
|
# File 'lib/cast_off/compile/iseq.rb', line 431
def enclose_end_deoptimize()
@excs.empty? ? '' : 'TH_POP_TAG2();'
end
|
#ifunc_node_generator ⇒ Object
253
254
255
|
# File 'lib/cast_off/compile/iseq.rb', line 253
def ifunc_node_generator()
"generate_ifunc_node_#{@c_name}"
end
|
#initialize_for_guards(var) ⇒ Object
193
194
195
|
# File 'lib/cast_off/compile/iseq.rb', line 193
def initialize_for_guards(var)
@initialize_for_guards << var
end
|
#inject_guard(insn, code) ⇒ Object
210
211
212
213
214
215
216
217
|
# File 'lib/cast_off/compile/iseq.rb', line 210
def inject_guard(insn, code)
bug() unless insn.iseq == self
if @guard_codes[code]
@guard_codes[code] << insn
else
@guard_codes[code] = [insn]
end
end
|
#iterate_all_guards(&b) ⇒ Object
219
220
221
222
|
# File 'lib/cast_off/compile/iseq.rb', line 219
def iterate_all_guards(&b)
iterate_own_guards(&b)
@children.values.each{|c| c.iterate_all_guards(&b)}
end
|
#iterate_all_iseq {|_self| ... } ⇒ Object
228
229
230
231
|
# File 'lib/cast_off/compile/iseq.rb', line 228
def iterate_all_iseq(&b)
yield(self)
@children.values.each{|c| c.iterate_all_iseq(&b)}
end
|
#iterate_own_guards ⇒ Object
224
225
226
|
# File 'lib/cast_off/compile/iseq.rb', line 224
def iterate_own_guards()
@guard_codes.each{|(code, insns)| yield(code, insns)}
end
|
#own_argv_size ⇒ Object
175
176
177
|
# File 'lib/cast_off/compile/iseq.rb', line 175
def own_argv_size()
@argv_size
end
|
#own_c_function_body ⇒ Object
160
161
162
|
# File 'lib/cast_off/compile/iseq.rb', line 160
def own_c_function_body()
@c_function_body
end
|
#own_initializations_for_guards ⇒ Object
206
207
208
|
# File 'lib/cast_off/compile/iseq.rb', line 206
def own_initializations_for_guards()
@initialize_for_guards.map{|v| " #{v} = Qnil;"}.uniq()
end
|
#own_local_variable_declarations ⇒ Object
189
190
191
|
# File 'lib/cast_off/compile/iseq.rb', line 189
def own_local_variable_declarations()
@local_variable_declarations.uniq()
end
|
#reference_constant ⇒ Object
142
143
144
|
# File 'lib/cast_off/compile/iseq.rb', line 142
def reference_constant
@reference_constant_p = true
end
|
#reference_constant? ⇒ Boolean
146
147
148
|
# File 'lib/cast_off/compile/iseq.rb', line 146
def reference_constant?
@reference_constant_p
end
|
#root? ⇒ Boolean
128
129
130
|
# File 'lib/cast_off/compile/iseq.rb', line 128
def root?
!@parent
end
|
#set_local_variables(lvars) ⇒ Object
112
113
114
|
# File 'lib/cast_off/compile/iseq.rb', line 112
def set_local_variables(lvars)
@lvars = lvars
end
|
#set_loopkey(k) ⇒ Object
116
117
118
119
|
# File 'lib/cast_off/compile/iseq.rb', line 116
def set_loopkey(k)
bug() if root?
@loopkey = k
end
|
#to_name ⇒ Object
455
456
457
|
# File 'lib/cast_off/compile/iseq.rb', line 455
def to_name
"#{@name}: #{@source_file} #{@source_line}"
end
|
#to_s ⇒ Object
459
460
461
|
# File 'lib/cast_off/compile/iseq.rb', line 459
def to_s
@c_name
end
|
#update_dfp(indent = 2) ⇒ Object
291
292
293
294
|
# File 'lib/cast_off/compile/iseq.rb', line 291
def update_dfp(indent = 2)
indent = ' ' * indent
(0..@generation).map{|i| "#{indent}dfp#{i} = fetch_dfp(th, #{@generation - i});"}.join("\n")
end
|
#use_temporary_c_ary(size) ⇒ Object
164
165
166
167
|
# File 'lib/cast_off/compile/iseq.rb', line 164
def use_temporary_c_ary(size)
@argv_size = size if size > @argv_size
"cast_off_argv"
end
|