Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Make profiler prototype

  • Loading branch information...
commit a9c0f81ce59a2b0965877abdc3e5f3ad50433dc7 1 parent a664ffe
Miura Hideki miura1729 authored
13 lib/llvmbuilder.rb
View
@@ -13,6 +13,7 @@ def initialize
@module = LLVM::Module.new('yarv2llvm')
@externed_function = {}
@func = nil
+ @global_ptr = nil
ExecutionEngine.get(@module)
end
@@ -89,6 +90,14 @@ def get_or_insert_function(name, type)
def get_or_insert_function_raw(name, type)
@module.get_or_insert_function(name, type)
end
+
+ def define_global_variable(type, init)
+ @global_ptr = @module.global_variable(type, init)
+ end
+
+ def global_variable
+ @global_ptr
+ end
def arguments
@func.arguments
@@ -98,6 +107,10 @@ def create_block
@func.create_block
end
+ def current_function
+ @func
+ end
+
def external_function(name, type)
if rc = @externed_function[name] then
rc
5 lib/llvmutil.rb
View
@@ -98,6 +98,11 @@ def gen_call_var_args_common(fname, rtype, ftype)
context.rc = yield(b, context, func, nele, argarea)
context}]
end
+
+ def add_global_variable(name, type, init)
+ @global_malloc_area_tab[name] = [type, init]
+ @global_malloc_area_tab.size - 1
+ end
end
module SendUtil
28 lib/methoddef.rb
View
@@ -345,7 +345,33 @@ module MethodDefinition
context.rc = b.call(func, nargs.llvm, initarea, recv)
context}]
}
- }
+ },
+
+ :get_interval_cycle => {
+ :inline_proc =>
+ lambda {
+ info = @para[:info]
+ rettype = RubyType.fixnum(info[3], "Return type of gen_interval_cycle")
+ glno = add_global_variable("interval_cycle",
+ Type::Int64Ty,
+ 0.llvm(Type::Int64Ty))
+ @expstack.push [rettype,
+ lambda {|b, context|
+ prevvalp = context.builder.global_variable
+ prevvalp = b.struct_gep(prevvalp, glno)
+ prevval = b.load(prevvalp)
+ ftype = Type.function(Type::Int64Ty, [])
+ fname = 'llvm.readcyclecounter'
+ func = context.builder.external_function(fname, ftype)
+ curval = b.call(func)
+ diffval = b.sub(curval, prevval)
+ rc = b.trunc(diffval, Type::Int32Ty)
+ b.store(curval, prevvalp)
+ context.rc = rc
+ context
+ }]
+ }
+ }
}
# can be maped to C function
146 lib/vmtraverse.rb
View
@@ -164,6 +164,12 @@ def initialize(iseq, bind)
@constant_type_tab = Hash.new {|hash, klass|
hash[klass] = {}
}
+
+ # Information of global variables by malloc
+ @global_malloc_area_tab = {}
+
+ # Number of trace(for profile speed up)
+ @trace_no = 0
end
include IntRuby
@@ -174,6 +180,8 @@ def run
if OPTION[:cache_instance_variable] then
gen_ivar_ptr(@builder)
end
+
+ initfunc = gen_init_ruby(@builder)
@generated_code.each do |fname, gen|
gen.call
@@ -188,6 +196,8 @@ def run
if OPTION[:write_bc] then
@builder.write_bc(OPTION[:write_bc])
end
+
+ LLVM::ExecutionEngine.run_function(initfunc)
end
def visit_block_start(code, ins, local, ln, info)
@@ -692,14 +702,22 @@ def visit_setinstancevariable(code, ins, local, ln, info)
def visit_getconstant(code, ins, local, ln, info)
klass = @expstack.pop
val = nil
- if klass[0].name == "nil" then
- val = eval(ins[1].to_s, @binding)
+ const_path = ins[1].to_s
+ kn = klass[0].name
+ unless kn == "nil" then
+ const_path = "#{kn}::#{const_path}"
+ end
+ if info[0] then
+ const_path = "#{info[0]}::#{const_path}"
end
+ val = eval(const_path, @binding)
+
type = @constant_type_tab[@binding][ins[1]]
if type == nil then
type = RubyType.typeof(val, info[3], ins[1])
@constant_type_tab[@binding][ins[1]] = type
end
+
@expstack.push [type,
lambda {|b, context|
context.rc = val.llvm
@@ -713,8 +731,60 @@ def visit_setconstant(code, ins, local, ln, info)
eval("#{ins[1].to_s} = #{val[0].name}", @binding)
end
- # getglobal
- # setglobal
+ def visit_getglobal(code, ins, local, ln, info)
+ glname = ins[1]
+ type = RubyType.new(nil, info[3], "$#{glname}")
+
+ @expstack.push [type,
+ lambda {|b, context|
+ ftype = Type.function(VALUE, [VALUE])
+ func1 = context.builder.external_function('rb_global_entry', ftype)
+ func2 = context.builder.external_function('rb_gvar_get', ftype)
+ glid = ((glname.object_id << 1) / RVALUE_SIZE)
+ glob = b.call(func1, glid.llvm)
+ val = b.call(func2, glob)
+ context.rc = type.type.from_value(val, b, context)
+ context
+ }]
+ end
+
+ def visit_setglobal(code, ins, local, ln, info)
+ glname = ins[1]
+
+ dsttype = RubyType.new(nil, info[3], "$#{glname}")
+
+ src = @expstack.pop
+ srctype = src[0]
+ srcvalue = src[1]
+
+ srctype.add_same_value(dsttype)
+ dsttype.add_same_value(srctype)
+
+ oldrescode = @rescode
+ @rescode = lambda {|b, context|
+ context = oldrescode.call(b, context)
+ context = srcvalue.call(b, context)
+ srcval = context.rc
+ srcval2 = srctype.type.to_value(srcval, b, context)
+
+ dsttype.type = dsttype.type.dup_type
+ dsttype.type.content = srcval
+
+ ftype1 = Type.function(VALUE, [VALUE])
+ func1 = context.builder.external_function('rb_global_entry', ftype1)
+
+ ftype2 = Type.function(VALUE, [VALUE, VALUE])
+ func2 = context.builder.external_function('rb_gvar_set', ftype2)
+
+ glid = ((glname.object_id << 1) / RVALUE_SIZE)
+
+ gent = b.call(func1, glid.llvm)
+ b.call(func2, gent, srcval2)
+ context.org = dsttype.name
+
+ context
+ }
+ end
def visit_putnil(code, ins, local, ln, info)
# Nil is not support yet.
@@ -918,7 +988,33 @@ def visit_dup(code, ins, local, ln, info)
}]
end
- # dupn
+ def visit_dupn(code, ins, local, ln, info)
+ s = []
+ n = ins[1]
+ n.times do |i|
+ s.push @expstack.pop
+ end
+ s.reverse!
+
+ stacktop_value = []
+ n.times do |i|
+ @expstack.push [s[i][0],
+ lambda {|b, context|
+ context.rc = stacktop_value[i]
+ context
+ }]
+ end
+
+ n.times do |i|
+ @expstack.push [s[i][0],
+ lambda {|b, context|
+ context = s[i][1].call(b, context)
+ stacktop_value[i] = context.rc
+ context
+ }]
+ end
+ end
+
# swap
# reput
# topn
@@ -928,17 +1024,19 @@ def visit_dup(code, ins, local, ln, info)
# defined
def visit_trace(code, ins, local, ln, info)
+ curtrace_no = @trace_no
+ evt = ins[1]
+ TRACE_INFO[curtrace_no] = [evt, info.clone]
+ @trace_no += 1
if info[1] == :trace_func and info[0] == :YARV2LLVM then
return
end
- evt = ins[1]
if minfo = MethodDefinition::RubyMethod[:trace_func][:YARV2LLVM] then
argt = minfo[:argtype]
if argt[0].type == nil then
RubyType.fixnum.add_same_type argt[0]
- RubyType.value.add_same_type argt[1]
- RubyType.value.add_same_type argt[2]
+ RubyType.fixnum.add_same_type argt[1]
RubyType.resolve
end
end
@@ -951,13 +1049,17 @@ def visit_trace(code, ins, local, ln, info)
argt = minfo[:argtype]
if argt[0].type == nil then
RubyType.fixnum.add_same_type argt[0]
- RubyType.value.add_same_type argt[1]
- RubyType.value.add_same_type argt[2]
+ RubyType.fixnum.add_same_type argt[1]
RubyType.resolve
end
- slf = b.load(context.local_vars[2][:area])
+ if info[0] == nil then
+ slf = 4.llvm
+ else
+ slf = b.load(context.local_vars[2][:area])
+ end
func = minfo[:func]
- b.call(func, evt.llvm, lno.immediate, slf)
+ EXPORTED_OBJECT[lno] = true
+ b.call(func, evt.llvm, curtrace_no.llvm, slf)
end
context
}
@@ -1757,6 +1859,26 @@ def store_to_parent(voff, slev, src, acode, ln, info)
context
}
end
+
+ def gen_init_ruby(builder)
+ ftype = Type.function(VALUE, [])
+ b = builder.define_function_raw('init_ruby', ftype)
+ member = []
+ @global_malloc_area_tab.each do |vname, val|
+ member.push val[0]
+ end
+ type = Type.struct(member)
+
+ initarg = []
+ @global_malloc_area_tab.each do |vname, val|
+ initarg.push val[1]
+ end
+ init = Value.get_struct_constant(type, *initarg)
+ gl = builder.define_global_variable(type, init)
+
+ b.return(4.llvm)
+ builder.current_function
+ end
end
def compile_file(fn, opt = {}, bind = TOPLEVEL_BINDING)
7 lib/yarv2llvm.rb
View
@@ -29,6 +29,9 @@ module YARV2LLVM
}
OPTION = {}
+# Protect from GC
+EXPORTED_OBJECT = {}
+
# From gc.c in ruby1.9
# * sizeof(RVALUE) is
# * 20 if 32-bit, double is 4-byte aligned
@@ -36,10 +39,13 @@ module YARV2LLVM
# * 40 if 64-bit
RVALUE_SIZE = 20
RUBY_SYMBOL_FLAG = 0xe
+
+TRACE_INFO = []
end
class Object
def llvm
+ YARV2LLVM::EXPORTED_OBJECT[self] = true
immediate
end
end
@@ -58,6 +64,7 @@ def llvm(b)
class Symbol
def llvm
+ YARV2LLLVM::EXPORTED_OBJECT[self] = true
immediate
end
end
65 sample/profiler_sketch.rb
View
@@ -0,0 +1,65 @@
+require 'yarv2llvm'
+module YARV2LLVM
+ PROFILER_STATICS = []
+ PROFILER_STATICS[0] = 0
+end
+
+YARV2LLVM::compile(<<-EOS, {})
+module YARV2LLVM
+ def trace_func(event, no)
+ if event == 1 then # Line
+ if $fst == 1 then
+ get_interval_cycle
+ $fst = 0
+ end
+ next_curtime = get_interval_cycle
+ PROFILER_STATICS[no] += $curtime
+
+ $curtime = next_curtime
+ # Profile process dont count
+ get_interval_cycle
+ end
+ end
+end
+
+def fib(n)
+ if n < 2 then
+ 1
+ else
+ fib(n - 1) +
+ fib(n - 2)
+ end
+end
+
+EOS
+
+YARV2LLVM::TRACE_INFO.each_with_index do |n, i|
+ YARV2LLVM::PROFILER_STATICS[i] = 0
+end
+$fst = 1
+$curtime = 0
+p fib(10)
+
+src_content = {}
+YARV2LLVM::TRACE_INFO.each do |n|
+ fn, ln = n[1][3].split(/:/)
+ src_content[fn] = File.readlines(fn)
+end
+
+res = {}
+YARV2LLVM::TRACE_INFO.each_with_index do |n, i|
+ fn, ln = n[1][3].split(/:/)
+ res[n[1][3]] = YARV2LLVM::PROFILER_STATICS[i]
+end
+
+src_content.each do |fn, cont|
+ cont.each_with_index do |srcln, ln|
+ re = res[fn + ":" + (ln + 1).to_s].to_i
+ if re != 0 then
+ print "#{re}\t#{ln + 1}: #{srcln}"
+ else
+ print "\t#{ln + 1}: #{srcln}"
+ end
+ end
+end
+
11 test/test_debug.rb
View
@@ -4,13 +4,14 @@
class DebugTests < Test::Unit::TestCase
def test_trace_func
- YARV2LLVM::compile(<<-EOS, {disasm: true})
+ YARV2LLVM::compile(<<-EOS, {dump_yarv: true, disasm: true, optimize: true})
module YARV2LLVM
- def trace_func(event, line)
+ def trace_func(event, no)
p event
- p line
- p "----"
- p self
+ p no
+ p TRACE_INFO[no]
+ get_interval_cycle
+ p get_interval_cycle
end
end
Please sign in to comment.
Something went wrong with that request. Please try again.