Class: YTLJit::VM::Node::MethodSelectNode

Inherits:
BaseNode show all
Includes:
SendNodeCodeGen
Defined in:
lib/ytljit/vm.rb

Overview

Method name

Constant Summary

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

Constants inherited from BaseNode

BaseNode::ESCAPE_LEVEL

Instance Attribute Summary collapse

Attributes inherited from BaseNode

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

Instance Method Summary collapse

Methods included from SendNodeCodeGen

#gen_make_argv

Methods included from CommonCodeGen

#dump_context, #gen_alloca, #gen_call, #gen_save_thepr

Methods inherited from BaseNode

#add_element_node, #add_element_node_backward, #add_element_node_backward_aux, #collect_info, #decide_type, #decide_type_core, #decide_type_once, #gen_type_inference_proc, #get_constant_value, #inference_type, #marge_element_node, #marge_type, #same_type, #search_valid_signature, #set_escape_node, #set_escape_node_backward, #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, name) ⇒ MethodSelectNode

Returns a new instance of MethodSelectNode.



3058
3059
3060
3061
3062
3063
3064
3065
3066
# File 'lib/ytljit/vm.rb', line 3058

def initialize(parent, name)
  super(parent)
  @name = name
  @calling_convention = :unkown
  @reciever = nil
  @send_node = nil
  @ruby_reciever = nil
  @inline_node = nil
end

Instance Attribute Details

#calling_convention(context) ⇒ Object (readonly)

Returns the value of attribute calling_convention.



3082
3083
3084
# File 'lib/ytljit/vm.rb', line 3082

def calling_convention
  @calling_convention
end

#inline_nodeObject (readonly)

Returns the value of attribute inline_node.



3084
3085
3086
# File 'lib/ytljit/vm.rb', line 3084

def inline_node
  @inline_node
end

#nameObject (readonly)

Returns the value of attribute name.



3081
3082
3083
# File 'lib/ytljit/vm.rb', line 3081

def name
  @name
end

#recieverObject

Returns the value of attribute reciever.



3083
3084
3085
# File 'lib/ytljit/vm.rb', line 3083

def reciever
  @reciever
end

Instance Method Details

#collect_candidate_type(context) ⇒ Object



3086
3087
3088
# File 'lib/ytljit/vm.rb', line 3086

def collect_candidate_type(context)
  context
end

#compile(context) ⇒ Object



3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
# File 'lib/ytljit/vm.rb', line 3262

def compile(context)
  context = super(context)
  if @send_node.is_fcall or @send_node.is_vcall then
    slfop = @parent.frame_info.offset_arg(2, BPR)
    asm = context.assembler
    asm.with_retry do
      asm.mov(PTMPR, slfop)
    end
    context.set_reg_content(PTMPR, :callee_reciever)
    context.ret_reg2 = PTMPR
    mtop = @reciever.search_method_with_super(@name)[0]
    if mtop then
      sig = @parent.signature(context)
      cs = mtop.find_cs_by_signature(sig)
      if cs then
        context.ret_reg = cs.var_base_address
      else
        # Maybe not reached program
        context.ret_reg = 0
      end
    else
      recobj = @reciever.klass_object
      if recobj.is_a?(ClassClassWrapper) then
        recobj = recobj.value
      end
      if recobj and !recobj.is_a?(Class) then
        # recobj is Module
        recobj = Object
      end
      if recobj then
        addr = lambda {
          a = recobj.method_address_of(@name)
          $symbol_table[a] = @name
          a
        }
        if addr.call then
          context.ret_reg = OpVarMemAddress.new(addr)
          context.code_space.refer_operands.push context.ret_reg 
          context.ret_node = self
        else
          raise "Unkown method - #{@name}"
          context.ret_reg = OpImmidiateAddress.new(0)
          context.ret_node = self
        end
      else
        raise "foo"
      end
    end
  else
    context = @reciever.compile(context)
    rnode = context.ret_node
    rtype = rnode.decide_type_once(context.to_signature)
    do_dyna = rtype.is_a?(RubyType::DefaultType0)
    if @calling_convention != :ytl then
      context = rtype.gen_boxing(context)
      rtype = rtype.to_box
    elsif !rtype.boxed then
      context = rtype.gen_unboxing(context)
    end
    recval = context.ret_reg
    rrtype = rtype.ruby_type_raw
    knode = ClassTopNode.get_class_top_node(rrtype)
    mtop = nil

    if do_dyna then
      # Can't type inference. Dynamic method search
      mnval = @name.address
      addr = lambda {
        a = address_of("rb_obj_class")
        $symbol_table[a] = "rb_obj_class"
        a
      }
      objclass = OpVarMemAddress.new(addr)
      addr = lambda {
        a = address_of("ytl_method_address_of_raw")
        $symbol_table[a] = "ytl_method_address_of_raw"
        a
      }
      addrof = OpVarMemAddress.new(addr)

      context.start_using_reg(TMPR2)
      context.start_arg_reg
      
      asm = context.assembler
      asm.with_retry do
        asm.push(recval)
        asm.mov(FUNC_ARG[0], recval)
        asm.call_with_arg(objclass, 1)
        asm.mov(FUNC_ARG[0], RETR)
        asm.mov(FUNC_ARG[1], mnval)
      end
      context.set_reg_content(FUNC_ARG[0], true)
      context.set_reg_content(FUNC_ARG[1], true)
      context = gen_save_thepr(context)
      asm.with_retry do
        asm.call_with_arg(addrof, 2)
        asm.mov(TMPR2, RETR)
        asm.pop(PTMPR)
      end
      context.set_reg_content(PTMPR, true)
      context.set_reg_content(FUNC_ARG_YTL[0].dst_opecode, true)
      context.set_reg_content(FUNC_ARG_YTL[1].dst_opecode, self)
      context.ret_reg2 = PTMPR
      
      context.end_arg_reg
      
      context.ret_node = self
      context.set_reg_content(RETR, :method_address)
      context.set_reg_content(TMPR2, RETR)
      context.set_reg_content(PTMPR, @reciever)
      context.ret_reg = TMPR2

    elsif knode and
        mtop = knode.search_method_with_super(@name)[0] then
      asm = context.assembler
      if !rtype.boxed and rtype.ruby_type == Float then
        if recval != XMM0 then
          asm.with_retry do
            asm.mov(XMM0, recval)
          end
        end
        context.set_reg_content(XMM0, true)
        context.ret_reg2 = XMM0
      else
        asm.with_retry do
          asm.mov(PTMPR, recval)
        end
        context.set_reg_content(PTMPR, @reciever)
        context.ret_reg2 = PTMPR
      end

      sig = @parent.signature(context)
      cs = mtop.find_cs_by_signature(sig)
      if cs == nil then
        sig[0] = context.to_signature[1]
        cs = mtop.find_cs_by_signature(sig)
      end
      context.ret_reg = cs.var_base_address
    else
      # regident type 

      asm = context.assembler
      if !rtype.boxed and rtype.ruby_type == Float then
        if recval != XMM0 then
          asm.with_retry do
            asm.mov(XMM0, recval)
          end
        end
        context.ret_reg2 = XMM0
      else
        asm.with_retry do
          asm.mov(PTMPR, recval)
        end
        context.set_reg_content(PTMPR, context.ret_node)
        context.set_reg_content(TMPR2, @reciever)
        context.ret_reg2 = PTMPR
      end

      addr = lambda {
        rrec = @ruby_reciever
        if rrec.is_a?(ClassClassWrapper) then
          rrec = rrec.value
        end
        if rrec.class == Module then
          a = rrec.send(:method_address_of, @name)
          $symbol_table[a] = @name
          a
        elsif rrec then
          a = rrec.method_address_of(@name)
          $symbol_table[a] = @name
          a
        else
          4
        end
      }
      if addr.call then
        context.ret_reg = OpVarMemAddress.new(addr)
        context.code_space.refer_operands.push context.ret_reg 
        context.ret_node = self
      else
        raise "Unkown method - #{@ruby_reciever}##{@name}"
        context.ret_reg = OpImmidiateAddress.new(0)
        context.ret_node = self
      end
    end
  end
  context
end

#method_top_node(ctop, slf) ⇒ Object



3090
3091
3092
3093
3094
3095
3096
# File 'lib/ytljit/vm.rb', line 3090

def method_top_node(ctop, slf)
  if slf then
    ctop.search_method_with_super(@name, slf.ruby_type_raw)[0]
  else
    ctop.search_method_with_super(@name)[0]
  end
end

#set_reciever(sendnode) ⇒ Object



3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
# File 'lib/ytljit/vm.rb', line 3068

def set_reciever(sendnode)
  @send_node = sendnode
  if sendnode.is_fcall or sendnode.is_vcall then
    @reciever = @parent.class_top
    if @reciever == @parent.search_top and 
        !@reciever.is_a?(TopTopNode) then
      @reciever = @reciever.make_klassclass_node
    end
  else
    @reciever = sendnode.arguments[2]
  end
end