Class: YTLJit::VM::Node::SendNode

Inherits:
BaseNode show all
Includes:
HaveChildlenMixin, NodeUtil, OptFlagOp, SendUtil, SendNodeCodeGen
Defined in:
lib/ytljit/vm_sendnode.rb

Overview

Send methodes

Constant Summary collapse

@@current_node =
nil
@@special_node_tab =
{}

Constants included from AbsArch

AbsArch::AL, AbsArch::BL, AbsArch::CL, AbsArch::DL, AbsArch::FUNC_ARG, AbsArch::FUNC_ARG_YTL, AbsArch::FUNC_FLOAT_ARG, AbsArch::FUNC_FLOAT_ARG_YTL, AbsArch::INDIRECT_BPR, AbsArch::INDIRECT_RETR, AbsArch::INDIRECT_SPR, AbsArch::INDIRECT_TMPR, AbsArch::INDIRECT_TMPR2, AbsArch::INDIRECT_TMPR3

Constants included from SSE

SSE::XMM0, SSE::XMM1, SSE::XMM2, SSE::XMM3, SSE::XMM4, SSE::XMM5, SSE::XMM6, SSE::XMM7

Instance Attribute Summary collapse

Attributes included from HaveChildlenMixin

#body

Attributes inherited from BaseNode

#code_space, #element_node_list, #id, #parent, #ti_observee, #ti_observer, #type

Class Method Summary collapse

Instance Method Summary collapse

Methods included from SendUtil

#compile_c_fixarg, #compile_c_vararg, #compile_ytl, #gen_eval_self, #signature

Methods included from NodeUtil

#search_class_top, #search_end, #search_frame_info, #search_top

Methods included from SendNodeCodeGen

#dump_context, #gen_call, #gen_make_argv

Methods included from OptFlagOp

#is_args_blockarg, #is_args_splat, #is_fcall, #is_opt_send, #is_super, #is_tailcall, #is_tailrecursion, #is_vcall

Methods inherited from BaseNode

#add_element_node, #decide_type, #decide_type_core, #decide_type_once, #gen_type_inference_proc, #inference_type, #merge_type, #same_type, #ti_add_observer, #ti_changed, #ti_del_link, #ti_reset, #ti_update

Methods included from TypeListWithSignature

#add_type, #set_type_list, #type_list, #type_list_initvar

Methods included from Inspect

#inspect_by_graph

Constructor Details

#initialize(parent, func, arguments, op_flag, seqno) ⇒ SendNode

Returns a new instance of SendNode.



81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/ytljit/vm_sendnode.rb', line 81

def initialize(parent, func, arguments, op_flag, seqno)
  super(parent)
  @func = func
  @arguments = arguments
  @opt_flag = op_flag
  @seq_no = seqno
  @var_return_address = nil
  @next_node = @@current_node
  @@current_node = self

  @class_top = search_class_top
  @frame_info = search_frame_info

  @modified_instance_var = nil
  @modified_local_var = [{}]

  @result_cache = nil
  @method_signature = []
end

Instance Attribute Details

#argumentsObject

Returns the value of attribute arguments.



102
103
104
# File 'lib/ytljit/vm_sendnode.rb', line 102

def arguments
  @arguments
end

#class_topObject (readonly)

Returns the value of attribute class_top.



106
107
108
# File 'lib/ytljit/vm_sendnode.rb', line 106

def class_top
  @class_top
end

#frame_infoObject (readonly)

Returns the value of attribute frame_info.



107
108
109
# File 'lib/ytljit/vm_sendnode.rb', line 107

def frame_info
  @frame_info
end

#funcObject

Returns the value of attribute func.



101
102
103
# File 'lib/ytljit/vm_sendnode.rb', line 101

def func
  @func
end

#modified_instance_varObject (readonly)

Returns the value of attribute modified_instance_var.



109
110
111
# File 'lib/ytljit/vm_sendnode.rb', line 109

def modified_instance_var
  @modified_instance_var
end

#modified_local_varObject (readonly)

Returns the value of attribute modified_local_var.



108
109
110
# File 'lib/ytljit/vm_sendnode.rb', line 108

def modified_local_var
  @modified_local_var
end

#next_nodeObject (readonly)

Returns the value of attribute next_node.



105
106
107
# File 'lib/ytljit/vm_sendnode.rb', line 105

def next_node
  @next_node
end

#opt_flagObject (readonly)

Returns the value of attribute opt_flag.



103
104
105
# File 'lib/ytljit/vm_sendnode.rb', line 103

def opt_flag
  @opt_flag
end

#result_cacheObject

Returns the value of attribute result_cache.



110
111
112
# File 'lib/ytljit/vm_sendnode.rb', line 110

def result_cache
  @result_cache
end

#seq_noObject (readonly)

Returns the value of attribute seq_no.



111
112
113
# File 'lib/ytljit/vm_sendnode.rb', line 111

def seq_no
  @seq_no
end

#var_return_addressObject (readonly)

Returns the value of attribute var_return_address.



104
105
106
# File 'lib/ytljit/vm_sendnode.rb', line 104

def var_return_address
  @var_return_address
end

Class Method Details

.add_special_send_node(name) ⇒ Object



55
56
57
58
59
60
61
62
63
# File 'lib/ytljit/vm_sendnode.rb', line 55

def self.add_special_send_node(name)
  oldcls = @@special_node_tab[name]
  if oldcls == nil or self < oldcls then
    @@special_node_tab[name] = self

  else
    raise "Illigal SendNode #{self} #{name}"
  end
end

.make_send_node(parent, func, arguments, op_flag, seqno) ⇒ Object



65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/ytljit/vm_sendnode.rb', line 65

def self.make_send_node(parent, func, arguments, op_flag, seqno)
  spcl = @@special_node_tab[func.name]
  newobj = nil
  if spcl then
    newobj = spcl.new(parent, func, arguments, op_flag, seqno)
  else
    newobj = self.new(parent, func, arguments, op_flag, seqno)
  end
  func.parent = newobj
  arguments.each do |ele|
    ele.parent = newobj
  end

  newobj
end

.nodeObject



51
52
53
# File 'lib/ytljit/vm_sendnode.rb', line 51

def self.node
  @@current_node
end

Instance Method Details

#check_signature_changed(context, signat, metsigent, cursig) ⇒ Object



187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
# File 'lib/ytljit/vm_sendnode.rb', line 187

def check_signature_changed(context, signat, metsigent, cursig)
  if metsigent then
    if metsigent[1][1] != signat[1] then
      if metsigent[1][1].ruby_type < signat[1].ruby_type then
        signat[1] = metsigent[1][1]
        false
      else
        type_list(cursig)[1] = []
        ti_reset
        ti_del_link
        context.convergent = false
        metsigent[1] = signat
        true
      end
    else
      false
    end
  else
    # Why not push, because it excepted type inference about
    # this signature after. So reduce search loop.
    @method_signature.unshift [cursig, signat]
    false
  end
end

#collect_candidate_type(context) ⇒ Object



212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
# File 'lib/ytljit/vm_sendnode.rb', line 212

def collect_candidate_type(context)
  cursig = context.to_signature

  # get saved original signature
  metsigent = search_signature(cursig)
  oldsignat = nil
  if metsigent then
    oldsignat = metsigent[1]
  end

  # prev env
  context = @arguments[0].collect_candidate_type(context)

  # block is after detect method
  blknode = @arguments[1]

  # other
  @arguments[2.. -1].each do |arg|
    context = arg.collect_candidate_type(context)
  end

  # function select
  context = @func.collect_candidate_type(context)

  signat = signature(context)
  check_signature_changed(context, signat, metsigent, cursig)

  mt, slf = get_send_method_node(cursig)
  if mt then
    same_type(self, mt, cursig, signat, context)
    same_type(mt, self, signat, cursig, context)

    context = mt.collect_candidate_type(context, @arguments, signat)

    context.push_signature(@arguments, mt)
    if blknode.is_a?(TopNode) then
      # Have block
      mt.yield_node.map do |ynode|
        yargs = ynode.arguments
        ysignat = ynode.signature(context)

        same_type(ynode, blknode, signat, ysignat, context)
        context = blknode.collect_candidate_type(context, 
                                                 yargs, ysignat)

      end
    else
      context = blknode.collect_candidate_type(context)
    end
    context.pop_signature
    
  else
    context = collect_candidate_type_regident(context, slf)
  end

  @body.collect_candidate_type(context)
end

#collect_candidate_type_regident(context, slf) ⇒ Object



140
141
142
# File 'lib/ytljit/vm_sendnode.rb', line 140

def collect_candidate_type_regident(context, slf)
  context
end

#collect_info(context) ⇒ Object



151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
# File 'lib/ytljit/vm_sendnode.rb', line 151

def collect_info(context)
  @arguments.each do |arg|
    context = arg.collect_info(context)
  end
  context = @func.collect_info(context)
  if is_fcall or is_vcall then
    # Call method of same class
    mt = @class_top.get_method_tab[@func.name]
    if mt then
      miv = mt.modified_instance_var
      if miv then
        miv.each do |vname, vall|
          context.modified_instance_var[vname] = vall
        end
      end
    end
  end

  @modified_local_var    = context.modified_local_var.last.dup
  @modified_instance_var = context.modified_instance_var.dup

  context = fill_result_cache(context)

  @body.collect_info(context)
end

#compile(context) ⇒ Object



270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
# File 'lib/ytljit/vm_sendnode.rb', line 270

def compile(context)
  context = super(context)

  context.start_using_reg(TMPR2)
  context.start_using_reg(TMPR3)
  callconv = @func.calling_convention(context)
  
  case callconv
  when :c_vararg
    context = compile_c_vararg(context)
    
  when :c_fixarg
    context = compile_c_fixarg(context)

  when :ytl
    context = compile_ytl(context)
  end
  
  decide_type_once(context.to_signature)
  if @type.is_a?(RubyType::RubyTypeUnboxed) and 
      @type.ruby_type == Float then
    context.ret_reg = XMM0
  else
    context.ret_reg = RETR
  end
  context.ret_node = self
  context.end_using_reg(TMPR3)
  context.end_using_reg(TMPR2)
  
  context = @body.compile(context)
  context
end

#fill_result_cache(context) ⇒ Object

This is for reduce method call whose all arguments is constant. But all methods can’t apply because the method may have side effect.



147
148
149
# File 'lib/ytljit/vm_sendnode.rb', line 147

def fill_result_cache(context)
  context
end

#get_constant_valueObject



303
304
305
306
307
308
309
# File 'lib/ytljit/vm_sendnode.rb', line 303

def get_constant_value
  if @result_cache then
    [@result_cache]
  else
    nil
  end
end

#get_send_method_node(cursig) ⇒ Object



121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/ytljit/vm_sendnode.rb', line 121

def get_send_method_node(cursig)
  mt = nil
  @arguments[2].decide_type_once(cursig)
  slf = @arguments[2].type
  if slf.instance_of?(RubyType::DefaultType0) then
    # Chaos
  end

  if is_fcall or is_vcall then
    mt = @func.method_top_node(@class_top, nil)

  else

    mt = @func.method_top_node(@class_top, slf)
  end

  [mt, slf]
end

#search_signature(cursig) ⇒ Object



177
178
179
180
181
182
183
184
185
# File 'lib/ytljit/vm_sendnode.rb', line 177

def search_signature(cursig)
  metsigent = nil
  @method_signature.each do |tabent|
    if cursig == tabent[0] then
      metsigent = tabent
    end
  end
  metsigent
end

#traverse_childlen {|@func| ... } ⇒ Object

Yields:



113
114
115
116
117
118
119
# File 'lib/ytljit/vm_sendnode.rb', line 113

def traverse_childlen
  @arguments.each do |arg|
    yield arg
  end
  yield @func
  yield @body
end