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

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

Overview

Method name

Constant Summary

Constants inherited from BaseNode

BaseNode::ESCAPE_LEVEL

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 inherited from BaseNode

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

Instance Method Summary collapse

Methods inherited from BaseNode

#add_element_node, #add_element_node_backward, #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, #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, val) ⇒ MethodSelectNode

Returns a new instance of MethodSelectNode.



2702
2703
2704
2705
2706
2707
2708
2709
# File 'lib/ytljit/vm.rb', line 2702

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

Instance Attribute Details

#calling_convention(context) ⇒ Object (readonly)

Returns the value of attribute calling_convention.



2725
2726
2727
# File 'lib/ytljit/vm.rb', line 2725

def calling_convention
  @calling_convention
end

#nameObject (readonly)

Returns the value of attribute name.



2724
2725
2726
# File 'lib/ytljit/vm.rb', line 2724

def name
  @name
end

#recieverObject

Returns the value of attribute reciever.



2726
2727
2728
# File 'lib/ytljit/vm.rb', line 2726

def reciever
  @reciever
end

Instance Method Details

#collect_candidate_type(context) ⇒ Object



2728
2729
2730
# File 'lib/ytljit/vm.rb', line 2728

def collect_candidate_type(context)
  context
end

#compile(context) ⇒ Object



2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
# File 'lib/ytljit/vm.rb', line 2839

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, true)
    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)
    if @calling_convention != :ytl then
#              if rnode.is_escape != :global_export then
        context = rtype.gen_boxing(context)
#              end
      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 rtype.is_a?(RubyType::DefaultType0) 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, true)
      context.set_reg_content(TMPR2, true)
      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)
      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(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



2732
2733
2734
2735
2736
2737
2738
# File 'lib/ytljit/vm.rb', line 2732

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



2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
# File 'lib/ytljit/vm.rb', line 2711

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