cast_off 0.3.1 → 0.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -87,7 +87,7 @@ static void sampling_variable(VALUE val, VALUE sym)
87
87
  /* :variable => [klass0, klass1, ...] */
88
88
  VALUE klass = rb_class_of(val);
89
89
  VALUE hashval;
90
- VALUE singleton_class_obj_p = Qfalse;
90
+ VALUE singleton_class_or_module_obj_p = Qfalse;
91
91
  st_table *hash;
92
92
 
93
93
  if (!st_lookup(sampling_table, (st_data_t)sym, (st_data_t*)&hashval)) {
@@ -97,16 +97,16 @@ static void sampling_variable(VALUE val, VALUE sym)
97
97
  hash = RHASH_TBL(hashval);
98
98
 
99
99
  if (FL_TEST(klass, FL_SINGLETON)) {
100
- if (rb_obj_class(val) == rb_cClass) {
100
+ if (rb_obj_class(val) == rb_cClass || rb_obj_class(val) == rb_cModule) {
101
101
  klass = val;
102
- singleton_class_obj_p = Qtrue;
102
+ singleton_class_or_module_obj_p = Qtrue;
103
103
  } else {
104
104
  klass = rb_cCastOffSingletonClass;
105
105
  }
106
106
  }
107
107
 
108
108
  if (!st_lookup(hash, (st_data_t)klass, 0)) {
109
- st_insert(hash, (st_data_t)klass, (st_data_t)singleton_class_obj_p);
109
+ st_insert(hash, (st_data_t)klass, (st_data_t)singleton_class_or_module_obj_p);
110
110
  }
111
111
 
112
112
  return;
@@ -116,23 +116,23 @@ static void __sampling_poscall(VALUE val, VALUE method_klass, VALUE method_id)
116
116
  {
117
117
  VALUE klass;
118
118
  VALUE mtblval, method_id_hashval, hashval;
119
- VALUE singleton_class_obj_p = Qfalse;
120
- VALUE class_method_p = Qfalse;
119
+ VALUE singleton_class_or_module_obj_p = Qfalse;
120
+ VALUE class_method_or_module_function_p = Qfalse;
121
121
  st_table *mtbl, *method_id_hash, *hash;
122
122
 
123
123
  if (FL_TEST(method_klass, FL_SINGLETON)) {
124
124
  VALUE recv = rb_ivar_get(method_klass, rb_intern("__attached__"));
125
- if (rb_obj_class(recv) == rb_cClass && rb_class_of(recv) == method_klass) {
125
+ if ((rb_obj_class(recv) == rb_cClass || rb_obj_class(recv) == rb_cModule) && rb_class_of(recv) == method_klass) {
126
126
  method_klass = recv;
127
- class_method_p = Qtrue;
127
+ class_method_or_module_function_p = Qtrue;
128
128
  } else {
129
129
  method_klass = rb_cCastOffSingletonClass;
130
130
  }
131
131
  }
132
132
 
133
- if (!st_lookup(sampling_table, (st_data_t)class_method_p, (st_data_t*)&mtblval)) {
133
+ if (!st_lookup(sampling_table, (st_data_t)class_method_or_module_function_p, (st_data_t*)&mtblval)) {
134
134
  mtblval = rb_hash_new();
135
- st_insert(sampling_table, (st_data_t)class_method_p, (st_data_t)mtblval);
135
+ st_insert(sampling_table, (st_data_t)class_method_or_module_function_p, (st_data_t)mtblval);
136
136
  }
137
137
  mtbl = RHASH_TBL(mtblval);
138
138
 
@@ -149,16 +149,16 @@ static void __sampling_poscall(VALUE val, VALUE method_klass, VALUE method_id)
149
149
 
150
150
  klass = rb_class_of(val);
151
151
  if (FL_TEST(klass, FL_SINGLETON)) {
152
- if (rb_obj_class(val) == rb_cClass) {
152
+ if (rb_obj_class(val) == rb_cClass || rb_obj_class(val) == rb_cModule) {
153
153
  klass = val;
154
- singleton_class_obj_p = Qtrue;
154
+ singleton_class_or_module_obj_p = Qtrue;
155
155
  } else {
156
156
  klass = rb_cCastOffSingletonClass;
157
157
  }
158
158
  }
159
159
 
160
160
  if (!st_lookup(hash, (st_data_t)klass, 0)) {
161
- st_insert(hash, (st_data_t)klass, (st_data_t)singleton_class_obj_p);
161
+ st_insert(hash, (st_data_t)klass, (st_data_t)singleton_class_or_module_obj_p);
162
162
  }
163
163
 
164
164
  return;
@@ -571,6 +571,7 @@ static VALUE <%= this_function_name() %>(VALUE dummy, VALUE self)
571
571
  /* decl variables */
572
572
  VALUE cast_off_argv[<%= @root_iseq.all_argv_size() %>];
573
573
  VALUE cast_off_tmp;
574
+ VALUE sampling_tmp;
574
575
  rb_thread_t *th;
575
576
  %if inline_block?
576
577
  VALUE thval;
@@ -78,34 +78,33 @@ module CastOff
78
78
  class_table = {}
79
79
  bind_table = {}
80
80
  location_table = {}
81
- cinfo_table = {}
81
+ #cinfo_table = {}
82
82
  compiled = []
83
- @@autocompile_proc = lambda {|event, file, line, mid, bind, klass, cinfo|
84
- return unless file
85
- return if line < 0
86
- return if event != 'call'
87
- return if file =~ /\(/
88
-
83
+ #@@autocompile_proc = lambda {|file, line, mid, bind, klass, cinfo|
84
+ @@autocompile_proc = lambda {|file, line, mid, bind, klass|
85
+ # trace method invocation
89
86
  # TODO should handle singleton class
90
87
 
91
- # trace method invocation count
92
- method_table = class_table[klass]
93
- unless method_table
94
- method_table = Hash.new(0)
95
- class_table[klass] = method_table
96
- end
88
+ method_table = (class_table[klass] ||= Hash.new(-1))
97
89
  count = (method_table[mid] += 1)
90
+ if count == 0
91
+ bug() unless bind.nil?
92
+ return true # re-call this proc with binding
93
+ end
98
94
  if count == 1
95
+ #count = @@compilation_threshold if contain_loop?(klass, mid)
96
+ bug() unless bind.instance_of?(Binding) || bind.nil?
99
97
  bind_table[[klass, mid]] = bind
100
- location_table[[klass, mid]] = [File.expand_path(file), line]
101
- end
102
- if cinfo
103
- table = (cinfo_table[[klass, mid]] ||= {})
104
- table[cinfo] = true
98
+ location_table[[klass, mid]] = (file =~ /\(/) ? nil : [File.expand_path(file), line]
105
99
  end
100
+ #if cinfo
101
+ #table = (cinfo_table[[klass, mid]] ||= {})
102
+ #table[cinfo] = true
103
+ #end
106
104
  if count == @@compilation_threshold && @@compile_auto_incremental
107
105
  compiled << __autocompile(klass, mid, bind_table, location_table, compiled.size)
108
106
  end
107
+ false
109
108
  }
110
109
  hook_method_invocation(@@autocompile_proc)
111
110
  at_exit do
@@ -118,7 +117,7 @@ module CastOff
118
117
  targets << [klass, mid, count]
119
118
  end
120
119
  end
121
- targets = sort_targets(targets, cinfo_table)
120
+ #targets = sort_targets(targets, cinfo_table)
122
121
  targets.each_with_index do |(klass, mid, count), index|
123
122
  dlog("#{count}: #{klass} #{mid}")
124
123
  compiled << __autocompile(klass, mid, bind_table, location_table, index)
@@ -168,7 +167,7 @@ module CastOff
168
167
  manager, configuration, suggestion = compile_iseq(iseq, mid, typemap, false, bind)
169
168
  manager.compilation_target_is_a(t, mid, false)
170
169
  set_direct_call(target, mid, target.instance_of?(Class) ? :class : :module, manager, configuration)
171
- load_binary(manager, configuration, suggestion, iseq, bind)
170
+ load_binary(manager, configuration, suggestion, iseq)
172
171
  t = override_target(target, mid)
173
172
  dlog("override target of #{target}##{mid} is #{t}")
174
173
  __send__("register_method_#{manager.signiture}", t)
@@ -190,7 +189,7 @@ module CastOff
190
189
  manager, configuration, suggestion = compile_iseq(iseq, mid, typemap, false, bind)
191
190
  manager.compilation_target_is_a(obj, mid, true)
192
191
  set_direct_call(obj, mid, :singleton, manager, configuration)
193
- load_binary(manager, configuration, suggestion, iseq, bind)
192
+ load_binary(manager, configuration, suggestion, iseq)
194
193
  __send__("register_singleton_method_#{manager.signiture}", obj)
195
194
  @@original_singleton_method_iseq[[obj, mid]] = iseq
196
195
  @@manager_table[manager.signiture] = manager
@@ -207,7 +206,7 @@ module CastOff
207
206
  execute_no_hook() do
208
207
  bind = block.binding
209
208
  manager, configuration, suggestion = compile_iseq(iseq, nil, typemap, false, bind)
210
- load_binary(manager, configuration, suggestion, iseq, bind)
209
+ load_binary(manager, configuration, suggestion, iseq)
211
210
  @@loaded_binary[key] = manager.signiture
212
211
  end
213
212
  end
@@ -321,6 +320,7 @@ Currently, CastOff cannot compile method which source file is not exist.
321
320
  target = compilation_target.target_object
322
321
  mid = compilation_target.method_id
323
322
  singleton = compilation_target.singleton_method?
323
+ return false unless CastOff.use_base_configuration?
324
324
  vlog("re-compile(#{target}#{singleton ? '.' : '#'}#{mid}): update_p = #{update_p}, reciever_result = #{reciever_result}, return_value_result = #{return_value_result}")
325
325
  return false unless update_p
326
326
  ann = manager.load_annotation() || {}
@@ -474,7 +474,57 @@ Currently, CastOff cannot compile method which source file is not exist.
474
474
  end
475
475
  end
476
476
 
477
- def __autocompile(klass, mid, bind_table, location_table, index)
477
+ def contain_loop?(klass, mid)
478
+ case compilation_target_type(klass, mid)
479
+ when :singleton_method
480
+ singleton_p = true
481
+ when :instance_method
482
+ singleton_p = false
483
+ when nil
484
+ return false
485
+ else
486
+ bug()
487
+ end
488
+ begin
489
+ iseq = get_iseq(klass, mid, singleton_p)
490
+ rescue UnsupportedError
491
+ return false
492
+ end
493
+ bug() unless iseq.instance_of?(RubyVM::InstructionSequence)
494
+ a = iseq.to_a
495
+ filepath, line_no = *a.slice(7, 2)
496
+ body = a.last
497
+ pc = 0
498
+ body.each do |insn|
499
+ next unless insn.instance_of?(Array)
500
+ op = insn.first
501
+ case op
502
+ when :jump, :branchif, :branchunless
503
+ dst = insn[1]
504
+ m = (/label_/).match(dst)
505
+ bug() unless m
506
+ dst = m.post_match.to_i
507
+ if dst < pc
508
+ vlog("#{klass}#{singleton_p ? '.' : '#'}#{mid} contains backedge: #{filepath}(#{line_no})")
509
+ return true
510
+ end
511
+ when :send
512
+ case insn[3] # blockiseq
513
+ when NilClass
514
+ # nothing to do
515
+ when Array
516
+ vlog("#{klass}#{singleton_p ? '.' : '#'}#{mid} has block: #{filepath}(#{line_no})")
517
+ return true
518
+ else
519
+ bug()
520
+ end
521
+ end
522
+ pc += insn.size
523
+ end
524
+ false
525
+ end
526
+
527
+ def compilation_target_type(klass, mid)
478
528
  return nil unless klass.instance_of?(Class) || klass.instance_of?(Module) # FIXME
479
529
  return nil if klass.name =~ /CastOff/ # ここで弾いておかないと、__compile の require で __load が走る。
480
530
  # Namespace のほうはあらかじめ require しておくことで回避。
@@ -486,14 +536,29 @@ Currently, CastOff cannot compile method which source file is not exist.
486
536
  return nil unless klass.singleton_methods(false).include?(mid)
487
537
  singleton = true
488
538
  end
539
+ singleton ? :singleton_method : :instance_method
540
+ end
541
+
542
+ def __autocompile(klass, mid, bind_table, location_table, index)
543
+ case compilation_target_type(klass, mid)
544
+ when :singleton_method
545
+ singleton = true
546
+ when :instance_method
547
+ singleton = false
548
+ when nil
549
+ return nil
550
+ else
551
+ bug()
552
+ end
489
553
  begin
554
+ location = location_table[[klass, mid]]
555
+ return nil unless location
490
556
  bind = bind_table[[klass, mid]]
491
557
  if singleton
492
558
  CastOff.compile_singleton_method(klass, mid, bind)
493
559
  else
494
560
  CastOff.compile(klass, mid, bind)
495
561
  end
496
- location = location_table[[klass, mid]]
497
562
  begin
498
563
  Marshal.dump(klass)
499
564
  rescue TypeError => e
@@ -553,11 +618,12 @@ Currently, CastOff cannot compile method which source file is not exist.
553
618
  bug() unless val0.is_a?(Hash)
554
619
  reciever_result[key0] = val0.to_a
555
620
  when TrueClass, FalseClass
556
- mtbl = return_value_result[(key0 ? :singleton_methods : :instance_methods)]
621
+ sym = key0 ? :singleton_methods : :instance_methods
622
+ mtbl = return_value_result[sym]
557
623
  bug() unless mtbl.is_a?(Hash)
558
624
  bug() unless val0.is_a?(Hash)
559
625
  val0.each do |(klass, midtbl)|
560
- bug() unless klass.is_a?(Class)
626
+ bug() unless klass.is_a?(Class) || (klass.is_a?(Module) && sym == :singleton_methods)
561
627
  bug() unless midtbl.is_a?(Hash)
562
628
  newval = {}
563
629
  midtbl.each do |(key1, val1)|
@@ -605,9 +671,10 @@ Currently, CastOff cannot compile method which source file is not exist.
605
671
  __send__("register_sampling_table_#{manager.signiture}", h)
606
672
  suggestion.add_handler do
607
673
  reciever_result, return_value_result = parse_sampling_table(h)
608
- update_base_configuration(manager, reciever_result, return_value_result)
674
+ up = update_base_configuration(manager, reciever_result, return_value_result)
675
+ vlog("update base configuration = #{up}")
609
676
  if reciever_result.size > 0
610
- msg = "These are unresolved local variables sampling results."
677
+ msg = "These are profiling results of unresolved local variables."
611
678
  ary = []
612
679
  reciever_result.each do |key0, val0|
613
680
  bug() unless key0.is_a?(Symbol)
@@ -615,8 +682,14 @@ Currently, CastOff cannot compile method which source file is not exist.
615
682
  val0.each do |(klass, singleton_p)|
616
683
  kstr = klass.to_s
617
684
  if singleton_p
618
- bug() unless klass.is_a?(Class)
619
- kstr = "Class<#{kstr}>"
685
+ case klass # 変数名が klass だとわかりにくいので、変更すること
686
+ when Class
687
+ kstr = "Class<#{kstr}>"
688
+ when Module
689
+ kstr = "Module<#{kstr}>"
690
+ else
691
+ bug()
692
+ end
620
693
  end
621
694
  ary << [key0.to_s, kstr]
622
695
  end
@@ -624,20 +697,26 @@ Currently, CastOff cannot compile method which source file is not exist.
624
697
  suggestion.add_suggestion(msg, ["<Variable>", "<SamplingResultClass>"], ary)
625
698
  end
626
699
  if return_value_result.size > 0
627
- msg = "These are unresolved method return values sampling results."
700
+ msg = "These are profiling results of unresolved method return values."
628
701
  ary = []
629
702
  return_value_result.each do |sym, mtbl|
630
703
  bug() unless sym == :singleton_methods || sym == :instance_methods
631
704
  bug() unless mtbl.is_a?(Hash)
632
705
  mtbl.each do |key0, val0|
633
- bug() unless key0.is_a?(Class)
706
+ bug() unless key0.is_a?(Class) || (key0.is_a?(Module) && sym == :singleton_methods)
634
707
  bug() unless val0.is_a?(Hash)
635
708
  val0.each do |(mid, classes)|
636
709
  classes.each do |(klass, singleton_p)|
637
710
  kstr = klass.to_s
638
711
  if singleton_p
639
- bug() unless klass.is_a?(Class)
640
- kstr = "Class<#{kstr}>"
712
+ case klass # 変数名が klass だとわかりにくいので、変更すること
713
+ when Class
714
+ kstr = "Class<#{kstr}>"
715
+ when Module
716
+ kstr = "Module<#{kstr}>"
717
+ else
718
+ bug()
719
+ end
641
720
  end
642
721
  ary << ["#{key0}#{sym == :singleton_methods ? '.' : '#'}#{mid}", kstr]
643
722
  end
@@ -653,14 +732,15 @@ Currently, CastOff cannot compile method which source file is not exist.
653
732
  s1 = configuration.to_s
654
733
  configuration.compact()
655
734
  s2 = configuration.to_s
735
+ vlog("update configuration = #{update_p}")
656
736
  if update_p
657
- bug() if s0 == s1
737
+ update_p = false if s0 == s1 # ignore configuration が更新されたときにここに来る
658
738
  else
659
739
  bug() if s0 != s1
660
740
  end
661
741
  if update_p
662
- suggestion.add_suggestion("You specify following type map to CastOff", ["Your Annotation"], [[s0]], false)
663
- suggestion.add_suggestion("CastOff suggests you to use following type map", ["CastOff Suggestion"], [[s2]], false)
742
+ suggestion.add_suggestion("You specified following type information to CastOff", ["Your Annotation"], [[s0]], false)
743
+ suggestion.add_suggestion("CastOff suggests you to use following type information", ["CastOff Suggestion"], [[s2]], false)
664
744
  end
665
745
  end
666
746
  end
@@ -680,7 +760,7 @@ Currently, CastOff cannot compile method which source file is not exist.
680
760
  dep.hook(function_pointer_initializer)
681
761
  end
682
762
 
683
- def load_binary(manager, configuration, suggestion, iseq, bind)
763
+ def load_binary(manager, configuration, suggestion, iseq)
684
764
  so = manager.compiled_binary
685
765
  sign = manager.signiture
686
766
  bug("#{so} is not exist") unless File.exist?(so)
@@ -692,7 +772,10 @@ Currently, CastOff cannot compile method which source file is not exist.
692
772
  set_sampling_table(suggestion, manager, configuration)
693
773
  suggestion.dump_at_exit()
694
774
  __send__(function_pointer_initializer)
695
- __send__("prefetch_constants_#{sign}", bind) if bind
775
+ if configuration.prefetch_constant?
776
+ bug() unless configuration.bind.instance_of?(Configuration::BindingWrapper)
777
+ __send__("prefetch_constants_#{sign}", configuration.bind.bind)
778
+ end
696
779
  end
697
780
 
698
781
  def capture_instruction()
data/lib/cast_off/util.rb CHANGED
@@ -43,11 +43,13 @@ module CastOff::Util
43
43
  STDERR.puts("<<< TODO #{message} :#{caller[0]} >>>")
44
44
  bt_and_bye()
45
45
  end
46
+ public(:todo)
46
47
 
47
48
  def bug(message = nil)
48
49
  STDERR.puts("<<< BUG #{message} :#{caller[0]} >>>")
49
50
  bt_and_bye()
50
51
  end
52
+ public(:bug)
51
53
 
52
54
  =begin
53
55
  def method_missing(name, *args, &block)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cast_off
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.3.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-11-18 00:00:00.000000000 Z
12
+ date: 2011-11-22 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description: ! 'CastOff is a performance improvement tool for Ruby1.9.3
15
15