Class: FastRuby::Method

Inherits:
Object show all
Defined in:
lib/fastruby/builder.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(method_name, owner) ⇒ Method

Returns a new instance of Method.



34
35
36
37
# File 'lib/fastruby/builder.rb', line 34

def initialize(method_name, owner)
  @method_name = method_name
  @owner = owner
end

Instance Attribute Details

#localsObject

Returns the value of attribute locals.



30
31
32
# File 'lib/fastruby/builder.rb', line 30

def locals
  @locals
end

#optionsObject

Returns the value of attribute options.



31
32
33
# File 'lib/fastruby/builder.rb', line 31

def options
  @options
end

#snippet_hashObject

Returns the value of attribute snippet_hash.



32
33
34
# File 'lib/fastruby/builder.rb', line 32

def snippet_hash
  @snippet_hash
end

Instance Method Details

#build(signature, noreturn = false) ⇒ Object



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
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
176
177
# File 'lib/fastruby/builder.rb', line 39

def build(signature, noreturn = false)
  return nil unless tree
  
  no_cache = false

  mname = FastRuby.make_str_signature(@method_name, signature)

  if @owner.respond_to? :method_hash
    method_hash = @owner.method_hash(@method_name.to_sym) || {}
    if (@owner.has_fastruby_function(method_hash,mname.to_s))
      FastRuby.logger.info "NOT Building #{@owner}::#{@method_name} for signature #{signature.inspect}, it's already done"
      return nil
    end
  end

  FastRuby.logger.info "Building #{@owner}::#{@method_name} for signature #{signature.inspect}"

  
  require "fastruby/translator/translator"
  require "rubygems"
  require "inline"
  require "fastruby/inline_extension"

  context = FastRuby::Context.new
  context.locals = locals
  context.options = options

  args_tree = if tree[0] == :defn
     tree[2]
  elsif tree[0] == :defs
     tree[3]
  else
    raise ArgumentError, "unknown type of method definition #{tree[0]}"
  end

  # create random method name
  context.snippet_hash = snippet_hash
  context.alt_method_name = "_" + @method_name.to_s + "_" + rand(10000000000).to_s

  (1..signature.size-1).each do |i|
    arg = args_tree[i]
    
    if arg.instance_of? Symbol
      
      if arg
        if arg.to_s.match(/\*/)
          context.infer_lvar_map[arg.to_s.gsub("*","").to_sym] = Array
        else
          context.infer_lvar_map[arg.to_sym] = signature[i]
        end
      end
    end
  end

  context.infer_self = signature[0]
  c_code = context.to_c_method(tree,signature)

  unless options[:main]
     context.define_method_at_init(@owner,@method_name, args_tree.size+1, signature)
  end

  so_name = nil

  old_class_self = $class_self
  $class_self = @owner
  $last_obj_proc = nil

  begin

    unless $inline_extra_flags
      $inline_extra_flags = true
      
      ['CFLAGS','CXXFLAGS','OPTFLAGS','cflags','cxxflags','optflags'].each do |name|
        RbConfig::CONFIG[name].gsub!(/\-O\d/,"-O1") if RbConfig::CONFIG[name]
      end
      
      if RUBY_VERSION =~ /^1\.8/
        RbConfig::CONFIG['CFLAGS'] << " -DRUBY_1_8 -Wno-clobbered"
      elsif RUBY_VERSION =~ /^1\.9/
        RbConfig::CONFIG['CFLAGS'] << " -DRUBY_1_9 -Wno-clobbered"
      end
    end
    
    @owner.class_eval do
      inline :C  do |builder|
        builder.inc << context.extra_code
        builder.init_extra = context.init_extra

          def builder.generate_ext
            ext = []

            @inc.unshift "#include \"ruby.h\""

            ext << @inc
            ext << nil
            ext << @src.join("\n\n")
            ext << nil
            ext << nil
            ext << "#ifdef __cplusplus"
            ext << "extern \"C\" {"
            ext << "#endif"
            ext << "  void Init_#{module_name}() {"

            ext << @init_extra.join("\n") unless @init_extra.empty?

            ext << nil
            ext << "  }"
            ext << "#ifdef __cplusplus"
            ext << "}"
            ext << "#endif"
            ext << nil

            ext.join "\n"
          end

        builder.c c_code
        so_name = builder.so_name
      end
    end

    if $last_obj_proc
      unless options[:no_cache]
        FastRuby.cache.register_proc(so_name, $last_obj_proc)
      end
      $last_obj_proc.call($class_self)
    end

  ensure
    $class_self = old_class_self
  end

  unless no_cache
    no_cache = context.no_cache
  end

  unless options[:no_cache]
    FastRuby.cache.insert(snippet_hash, so_name) unless no_cache
  end
end