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.
data/cast_off.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |spec|
2
2
  spec.name = "cast_off"
3
- spec.version = "0.3.1"
3
+ spec.version = "0.3.2"
4
4
  spec.platform = Gem::Platform::RUBY
5
5
  spec.summary = "Performance improvement tool for Ruby1.9.3"
6
6
  spec.description = <<-EOS
@@ -811,9 +811,14 @@ static VALUE cast_off_class_wrapper_each_method_search_target(VALUE self, VALUE
811
811
  rb_yield(module);
812
812
  } else if (TYPE(klass) == T_CLASS) {
813
813
  if (FL_TEST(klass, FL_SINGLETON)) {
814
- rb_bug("cast_off_class_wrapper_each_method_search_target: should not be reached(2)");
814
+ VALUE __klass = rb_iv_get(klass, "__attached__");
815
+ if (rb_class_of(__klass) != klass) {
816
+ rb_bug("cast_off_class_wrapper_each_method_search_target: should not be reached(2)");
817
+ }
818
+ rb_yield(rb_funcall(rb_cCastOffClassWrapper, rb_intern("new"), 2, __klass, Qfalse));
819
+ } else {
820
+ rb_yield(klass);
815
821
  }
816
- rb_yield(klass);
817
822
  } else {
818
823
  rb_bug("cast_off_class_wrapper_each_method_search_target: should not be reached(3)");
819
824
  }
@@ -1239,27 +1244,14 @@ static VALUE caller_info(rb_thread_t *th)
1239
1244
 
1240
1245
  static void cast_off_method_invocation_handler(rb_event_flag_t event, VALUE proc, VALUE self, ID id, VALUE klass)
1241
1246
  {
1242
- VALUE thval = rb_thread_current();
1243
- rb_thread_t *th = DATA_PTR(thval);
1244
- const char *srcfile = rb_sourcefile();
1245
- VALUE filename = srcfile ? rb_str_new2(srcfile) : Qnil;
1247
+ const char *srcfile;
1248
+ VALUE filename, need_binding;
1246
1249
  VALUE argv[6];
1247
- int line = rb_sourceline();
1248
- static VALUE ev = 0;
1249
-
1250
- if (!ev) {
1251
- ev = rb_str_new2("call");
1252
- rb_gc_register_mark_object(ev);
1253
- }
1250
+ int line;
1254
1251
 
1255
1252
  if (klass == 0) {
1256
1253
  rb_frame_method_id_and_class(&id, &klass);
1257
1254
  }
1258
-
1259
- if (id == ID_ALLOCATOR) {
1260
- return;
1261
- }
1262
-
1263
1255
  if (klass) {
1264
1256
  if (TYPE(klass) == T_ICLASS) {
1265
1257
  klass = RBASIC(klass)->klass;
@@ -1267,16 +1259,36 @@ static void cast_off_method_invocation_handler(rb_event_flag_t event, VALUE proc
1267
1259
  klass = rb_iv_get(klass, "__attached__");
1268
1260
  }
1269
1261
  }
1262
+ if (!klass) return;
1270
1263
 
1271
- argv[0] = ev;
1272
- argv[1] = filename;
1273
- argv[2] = INT2FIX(line);
1274
- argv[3] = id ? ID2SYM(id) : Qnil;
1275
- argv[4] = (self && srcfile) ? rb_binding_new() : Qnil;
1276
- argv[5] = klass ? klass : Qnil;
1277
- argv[6] = caller_info(th);
1264
+ if (id == ID_ALLOCATOR) {
1265
+ return;
1266
+ }
1267
+ if (!id) return;
1268
+
1269
+ srcfile = rb_sourcefile();
1270
+ if (!srcfile) return;
1271
+ filename = rb_str_new2(srcfile);
1278
1272
 
1279
- rb_proc_call_with_block(proc, 7, argv, Qnil);
1273
+ line = rb_sourceline();
1274
+ if (line < 0) return;
1275
+
1276
+ argv[0] = filename;
1277
+ argv[1] = INT2FIX(line);
1278
+ argv[2] = ID2SYM(id);
1279
+ argv[3] = Qnil;
1280
+ argv[4] = klass;
1281
+ /* argv[5] = caller_info(th); */
1282
+
1283
+ /* rb_proc_call_with_block(proc, 6, argv, Qnil); */
1284
+ need_binding = rb_proc_call_with_block(proc, 5, argv, Qnil);
1285
+ if (RTEST(need_binding)) {
1286
+ argv[3] = (self && srcfile) ? rb_binding_new() : Qnil;
1287
+ need_binding = rb_proc_call_with_block(proc, 5, argv, Qnil);
1288
+ }
1289
+ if (RTEST(need_binding)) {
1290
+ rb_bug("cast_off_method_invocation_handler: should not be reached");
1291
+ }
1280
1292
 
1281
1293
  return;
1282
1294
  }
@@ -1363,6 +1375,30 @@ VALUE cast_off_singleton_method_added_p(VALUE dummy)
1363
1375
  rb_bug("cast_off_singleton_method_added_p: should not be reached(1)");
1364
1376
  }
1365
1377
 
1378
+ static ID id_include, id_extend;
1379
+ VALUE cast_off_extend_p(VALUE dummy)
1380
+ {
1381
+ VALUE thval = rb_thread_current();
1382
+ rb_thread_t *th = DATA_PTR(thval);
1383
+ rb_control_frame_t *cfp;
1384
+ ID mid;
1385
+
1386
+ cfp = th->cfp; /* this method frame */
1387
+ cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp); /* method_added or singleton_method_added frame */
1388
+ if (!cfp->me) {
1389
+ rb_bug("cast_off_extend_p: should not be reached(0)");
1390
+ }
1391
+ mid = cfp->me->called_id;
1392
+ if (mid == id_include) {
1393
+ return Qfalse;
1394
+ }
1395
+ if (mid == id_extend) {
1396
+ return Qtrue;
1397
+ }
1398
+ /* TODO 別名に対応 */
1399
+ rb_bug("cast_off_extend_p: should not be reached(1)");
1400
+ }
1401
+
1366
1402
  /* for deoptimization */
1367
1403
  rb_iseq_t *cast_off_Fixnum_times_iseq;
1368
1404
  rb_iseq_t *cast_off_Array_each_iseq;
@@ -1470,10 +1506,13 @@ void Init_cast_off(void)
1470
1506
 
1471
1507
  id_method_added = rb_intern("method_added");
1472
1508
  id_singleton_method_added = rb_intern("singleton_method_added");
1509
+ id_include = rb_intern("include");
1510
+ id_extend = rb_intern("extend");
1473
1511
  id_initialize_copy = rb_intern("initialize_copy");
1474
1512
  id_clone = rb_intern("clone");
1475
1513
  rb_define_singleton_method(rb_cCastOffDependency, "ignore_overridden?", cast_off_ignore_overridden_p, 2);
1476
1514
  rb_define_singleton_method(rb_cCastOffDependency, "singleton_method_added?", cast_off_singleton_method_added_p, 0);
1515
+ rb_define_singleton_method(rb_cCastOffDependency, "extend?", cast_off_extend_p, 0);
1477
1516
 
1478
1517
  rb_define_singleton_method(rb_mCastOffCompiler, "destroy_last_finish", cast_off_destroy_last_finish, 0);
1479
1518
  rb_funcall(rb_mCastOffCompiler, rb_intern("module_eval"), 1, rb_str_new2("def self.vm_exec(); destroy_last_finish() end"));
@@ -14,15 +14,52 @@ __END__
14
14
  #else
15
15
  #define CFIX2RFIX(b) LONG2FIX((b))
16
16
  #endif
17
+ static inline VALUE CDOUBLE2RINT(double f)
18
+ {
19
+ if (f > 0.0) f = floor(f);
20
+ if (f < 0.0) f = ceil(f);
21
+ return FIXABLE(f) ? LONG2FIX((double)f) : rb_dbl2big(f);
22
+ }
23
+
17
24
  %# arg size, [type0, type1, ...]
18
- %[['float_float',
25
+ %[['float',
26
+ % {'-' => 'uminus'},
27
+ % 0,
28
+ % {'VALUE' => 'RFLOAT_VALUE', 'double' => ''},
29
+ % {},
30
+ % {'VALUE' => 'DBL2NUM', 'double' => ''}],
31
+ % ['float',
32
+ % {'' => 'to_f'},
33
+ % 0,
34
+ % {'VALUE' => ''},
35
+ % {},
36
+ % {'VALUE' => '', 'double' => 'RFLOAT_VALUE'}],
37
+ % ['float',
38
+ % {'' => 'to_i'},
39
+ % 0,
40
+ % {'VALUE' => 'RFLOAT_VALUE', 'double' => ''},
41
+ % {},
42
+ % {'VALUE' => 'CDOUBLE2RINT'}],
43
+ % ['fixnum',
44
+ % {'-' => 'uminus'},
45
+ % 0,
46
+ % {'VALUE' => 'FIX2LONG', 'long' => ''},
47
+ % {},
48
+ % {'VALUE' => 'CFIX2RFIX', 'long' => ''}],
49
+ % ['fixnum',
50
+ % {'(double)' => 'to_f'},
51
+ % 0,
52
+ % {'VALUE' => 'FIX2LONG', 'long' => ''},
53
+ % {},
54
+ % {'VALUE' => 'DBL2NUM', 'double' => ''}],
55
+ % ['float_float',
19
56
  % {'+' => 'plus', '-' => 'minus', '*' => 'mult', '/' => 'div'},
20
57
  % 1,
21
58
  % {'VALUE' => 'RFLOAT_VALUE', 'double' => ''},
22
59
  % {'VALUE' => 'RFLOAT_VALUE', 'double' => ''},
23
60
  % {'VALUE' => 'DBL2NUM', 'double' => ''}],
24
61
  % ['float_float',
25
- % {'>' => 'gt', '>=' => 'ge', '<' => 'lt', '<=' => 'le'},
62
+ % {'>' => 'gt', '>=' => 'ge', '<' => 'lt', '<=' => 'le', '==' => 'eq', '==' => 'eqq'},
26
63
  % 1,
27
64
  % {'VALUE' => 'RFLOAT_VALUE', 'double' => ''},
28
65
  % {'VALUE' => 'RFLOAT_VALUE', 'double' => ''},
@@ -39,12 +76,24 @@ __END__
39
76
  % {'VALUE' => '(double)FIX2LONG', 'long' => ''},
40
77
  % {'VALUE' => 'RFLOAT_VALUE', 'double' => ''},
41
78
  % {'VALUE' => 'DBL2NUM', 'double' => ''}],
79
+ % ['fixnum_float',
80
+ % {'>' => 'gt', '>=' => 'ge', '<' => 'lt', '<=' => 'le', '==' => 'eq', '==' => 'eqq'},
81
+ % 1,
82
+ % {'VALUE' => '(double)FIX2LONG', 'long' => ''},
83
+ % {'VALUE' => 'RFLOAT_VALUE', 'double' => ''},
84
+ % {'VALUE' => 'CBOOL2RBOOL'}],
42
85
  % ['float_fixnum',
43
86
  % {'+' => 'plus', '-' => 'minus', '*' => 'mult', '/' => 'div'},
44
87
  % 1,
45
88
  % {'VALUE' => 'RFLOAT_VALUE', 'double' => ''},
46
89
  % {'VALUE' => '(double)FIX2LONG', 'long' => ''},
47
- % {'VALUE' => 'DBL2NUM', 'double' => ''}]].each do |(function_name, h, argc, reciever_converter, arguments_converter, return_value_converter)|
90
+ % {'VALUE' => 'DBL2NUM', 'double' => ''}],
91
+ % ['float_fixnum',
92
+ % {'>' => 'gt', '>=' => 'ge', '<' => 'lt', '<=' => 'le', '==' => 'eq', '==' => 'eqq'},
93
+ % 1,
94
+ % {'VALUE' => 'RFLOAT_VALUE', 'double' => ''},
95
+ % {'VALUE' => '(double)FIX2LONG', 'long' => ''},
96
+ % {'VALUE' => 'CBOOL2RBOOL'}]].each do |(function_name, h, argc, reciever_converter, arguments_converter, return_value_converter)|
48
97
  % arguments_decls = arguments_converter.keys
49
98
  % reciever_decls = reciever_converter.keys
50
99
  % return_value_decls = return_value_converter.keys
@@ -68,7 +117,12 @@ __END__
68
117
  static inline <%= return_value %>
69
118
  cast_off_inline_<%= function_name %>_<%= name %>_<%= suffix %>(<%= parameter.join(', ') %>)
70
119
  {
120
+ % if argc > 0
71
121
  return <%= return_value_converter[return_value] %>(<%= statement.join(" #{operator} ") %>);
122
+ % else
123
+ % raise unless statement.size == 1
124
+ return <%= return_value_converter[return_value] %>(<%= operator %>(<%= statement.first %>));
125
+ % end
72
126
  }
73
127
  % end
74
128
  % end
@@ -101,7 +101,7 @@ module CastOff::Compiler
101
101
  end
102
102
 
103
103
  def all_pointer()
104
- ptrs = all_pointer_definition().map{|ir| ir.result_variable}.uniq()
104
+ ptrs = all_ir.map{|ir| ir.variables}.flatten.select{|v| v.is_a?(Pointer)}.uniq()
105
105
  bug() if ptrs.find{|p| not p.is_a?(Pointer)}
106
106
  ptrs.freeze()
107
107
  end
@@ -131,6 +131,9 @@ module CastOff::Compiler
131
131
  aliveblock.pre.reject!{|b| deadblocks.include?(b)}
132
132
  bug() if aliveblock.next.find{|b| deadblocks.include?(b)}
133
133
  end
134
+ deadblocks.each do |b|
135
+ b.iseq.delete_labels(b.labels)
136
+ end
134
137
  @blocks = achieved
135
138
  @blocks.sort! {|a, b| a.number <=> b.number}
136
139
  bug() if @blocks.find{|b| b.pre.empty? && !b.entry_point?}
@@ -239,60 +242,23 @@ module CastOff::Compiler
239
242
 
240
243
  ### unboxing begin ###
241
244
  def unboxing()
242
- # 1: mark value which can not unbox
243
- # 1: mark value which can unbox
244
245
  irs = all_ir()
245
246
  irs.each{|ir| ir.unboxing_prelude()}
246
- bug() if irs.map{|ir| ir.values }.flatten.find{|v| v.box_unbox_undefined? }
247
-
248
- # 2: propergate value which can not unbox
249
- change = true
250
- while change
251
- change = false
252
- @blocks.each do |b|
253
- defs = b.information.dup
254
- b.irs.each do |ir|
255
- change |= ir.propergate_value_which_can_not_unbox(defs)
256
- defs.step(ir)
257
- end
258
- end
259
- end
260
- bug() if irs.find{|ir| ir.instance_of?(SubIR) && ir.dst.can_not_unbox? != ir.src.can_not_unbox?}
261
-
262
- # 3: propergate value which can unbox
263
- change = true
264
- while change
265
- change = false
266
- @blocks.each do |b|
267
- defs = b.information.dup
268
- b.irs.each do |ir|
269
- change |= ir.propergate_unbox_value(defs)
270
- defs.step(ir)
271
- end
272
- end
273
- end
274
-
275
- bug() if irs.map{|ir| ir.values }.flatten.find{|v| v.unboxed? && (v.dynamic? || v.types.size != 1)}
276
- irs.each do |ir|
277
- ir.values.each do |v|
278
- next unless v.unboxed?
279
- end
280
- end
281
247
 
282
- irs.map{|ir| ir.values}.flatten.each{|v| v.box() unless v.unboxed?}
283
- irs.map{|ir| ir.values}.flatten.each{|v| bug() if !v.boxed? && !v.unboxed?}
284
248
  change = true
285
249
  while change
286
250
  change = false
287
251
  @blocks.each do |b|
288
252
  defs = b.information.dup
289
253
  b.irs.each do |ir|
290
- change |= ir.propergate_box_value(defs)
254
+ change |= ir.propergate_boxed_value(defs)
291
255
  defs.step(ir)
292
256
  end
293
257
  end
294
258
  end
259
+ bug() if irs.map{|ir| ir.values }.flatten.find{|v| v.unboxed? && !v.can_unbox?}
295
260
 
261
+ # validation
296
262
  @blocks.each do |b|
297
263
  defs = b.information.dup
298
264
  b.irs.each do |ir|
@@ -16,7 +16,9 @@ module Compiler
16
16
  class InvalidConfigurationError < StandardError; end
17
17
 
18
18
  attr_reader :return_value_configuration
19
+ attr_reader :ignore_configuration_of_return_values
19
20
  attr_reader :variable_configuration
21
+ attr_reader :ignore_configuration_of_variables
20
22
  attr_reader :method_information_usage
21
23
  attr_reader :option_table_configuration
22
24
  attr_reader :bind
@@ -194,13 +196,16 @@ o = Object
194
196
  ary.each{|t| bug(t) unless t.is_a?(ClassWrapper)}
195
197
  end
196
198
  end
199
+ @ignore_configuration_of_return_values = {}
197
200
  @variable_configuration.values.each do |ary|
198
201
  ary.each{|t| bug(t) unless t.is_a?(ClassWrapper)}
199
202
  end
203
+ @ignore_configuration_of_variables = {}
200
204
  @method_information_usage = []
201
205
  @option_table_configuration = {}
202
206
  @use_method_frame = false
203
207
  OPTION_TABLE.each{|(cvar, val)| @option_table_configuration[cvar] = self.class.class_variable_get(cvar)}
208
+ prefetch_constant(false) unless @bind
204
209
  end
205
210
 
206
211
  def use_method_frame(bool)
@@ -248,6 +253,12 @@ o = Object
248
253
  end
249
254
  @variable_configuration[sym] = (dst | src)
250
255
  end
256
+ conf.ignore_configuration_of_variables.each do |(k, v)|
257
+ bug() unless k.instance_of?(Symbol)
258
+ bug() unless v == true
259
+ @ignore_configuration_of_variables[k] = true
260
+ end
261
+ __ignore_configuration_of_variables(:union)
251
262
 
252
263
  conf.return_value_configuration.each do |(cw0, src0)|
253
264
  bug() unless src0.instance_of?(Hash)
@@ -264,6 +275,13 @@ o = Object
264
275
  dst0[sym] = (dst1 | src1)
265
276
  end
266
277
  end
278
+ conf.ignore_configuration_of_return_values.each do |(k, mids)|
279
+ bug() if mids.find{|m| !m.instance_of?(Symbol)}
280
+ @ignore_configuration_of_return_values[k] ||= []
281
+ @ignore_configuration_of_return_values[k] |= mids
282
+ end
283
+ __ignore_configuration_of_return_values(:union)
284
+
267
285
  return if @bind
268
286
  return unless conf.bind
269
287
  bug() unless conf.bind.instance_of?(BindingWrapper)
@@ -272,14 +290,20 @@ o = Object
272
290
 
273
291
  def update_variable_configuration(update_hash)
274
292
  update_p = false
293
+ updates = []
294
+ starts = @variable_configuration.keys
275
295
  update_hash.each do |(k, v)|
276
296
  bug() unless k.instance_of?(Symbol)
277
297
  bug() unless v.instance_of?(Array)
278
- next if v.map{|a| a.first }.include?(SingletonClass)
279
- # variable annotation
298
+ if v.map{|a| a.first }.include?(SingletonClass)
299
+ update_p = true unless @ignore_configuration_of_variables[k]
300
+ @ignore_configuration_of_variables[k] = true
301
+ end
302
+ next if @ignore_configuration_of_variables[k]
303
+ # annotation of variables
280
304
  a0 = v
281
305
  a0 = a0.map{|(c, singleton_p)|
282
- bug(c) unless c.is_a?(Class)
306
+ bug(c) unless c.is_a?(Class) || (c.is_a?(Module) && singleton_p)
283
307
  bug() unless c != SingletonClass
284
308
  if singleton_p
285
309
  wrapper = ClassWrapper.new(c, false)
@@ -290,31 +314,70 @@ o = Object
290
314
  wrapper
291
315
  }
292
316
  a1 = @variable_configuration[k] || []
293
- update_p = true unless (a0 - a1).empty?
317
+ updates << k unless (a0 - a1).empty?
294
318
  a1 |= a0
295
319
  @variable_configuration[k] = a1
296
320
  end
297
- update_p
321
+ deletes = __ignore_configuration_of_variables(:update)
322
+ inc_p = !(updates - deletes).empty?
323
+ dec_p = !(starts & deletes).empty?
324
+ inc_p | dec_p | update_p
298
325
  end
299
326
 
300
327
  def update_return_value_configuration(update_hash)
301
328
  update_p = false
329
+ updates = []
330
+ starts = []
331
+ @return_value_configuration.each do |klass, hash|
332
+ bug() unless klass.instance_of?(ClassWrapper)
333
+ bug() unless hash.instance_of?(Hash)
334
+ hash.keys.each do |mid|
335
+ bug() unless mid.instance_of?(Symbol)
336
+ starts << [klass, mid]
337
+ end
338
+ end
302
339
  bug() unless update_hash.size == 2
303
340
  update_hash.each do |(sym, mtbl)|
304
341
  bug() unless sym == :singleton_methods || sym == :instance_methods
305
342
  bug() unless mtbl.is_a?(Hash)
306
343
  mtbl.each do |(k, v)|
307
- bug() unless k.instance_of?(Class)
344
+ bug() unless k.instance_of?(Class) || (k.instance_of?(Module) && sym == :singleton_methods)
308
345
  bug() unless v.instance_of?(Hash)
309
- next if k == SingletonClass
310
- # return value annotation
346
+ if k == SingletonClass
347
+ bug() if sym == :singleton_methods
348
+ ignore_targets = v.keys
349
+ bug() if ignore_targets.find{|m| !m.instance_of?(Symbol)}
350
+ @ignore_configuration_of_return_values[SingletonClass] ||= []
351
+ update_p = true unless (ignore_targets - @ignore_configuration_of_return_values[SingletonClass]).empty?
352
+ @ignore_configuration_of_return_values[SingletonClass] |= ignore_targets
353
+ next
354
+ end
355
+ # annotation of return values
311
356
  h0 = v
312
357
  k = ClassWrapper.new(k, sym == :instance_methods)
313
358
  h1 = @return_value_configuration[k] || {}
314
359
  h0.each do |(mid, klasses0)|
315
- next if klasses0.include?(SingletonClass)
360
+ ignore_p = false
361
+ bug() unless klasses0.is_a?(Array)
362
+ klasses0.each do |(c, singleton_p)|
363
+ if c == SingletonClass
364
+ bug() if singleton_p
365
+ ignore_p = true
366
+ break
367
+ end
368
+ end
369
+ if ignore_p
370
+ bug() unless k.instance_of?(ClassWrapper)
371
+ ignore_targets = (@ignore_configuration_of_return_values[k] ||= [])
372
+ unless ignore_targets.include?(mid)
373
+ ignore_targets.push(mid)
374
+ update_p = true
375
+ end
376
+ next
377
+ end
378
+ next if @ignore_configuration_of_return_values[k] && @ignore_configuration_of_return_values[k].include?(mid)
316
379
  klasses0 = klasses0.map{|(c, singleton_p)|
317
- bug(c) unless c.is_a?(Class)
380
+ bug(c) unless c.is_a?(Class) || (c.is_a?(Module) && singleton_p)
318
381
  bug() unless c != SingletonClass
319
382
  if singleton_p
320
383
  wrapper = ClassWrapper.new(c, false)
@@ -325,14 +388,20 @@ o = Object
325
388
  wrapper
326
389
  }
327
390
  klasses1 = h1[mid] || []
328
- update_p = true unless (klasses0 - klasses1).empty?
391
+ updates |= [[k, mid]] unless (klasses0 - klasses1).empty?
329
392
  klasses1 |= klasses0
330
393
  h1[mid] = klasses1
331
394
  end
332
395
  @return_value_configuration[k] = h1
333
396
  end
334
397
  end
335
- update_p
398
+ deletes = __ignore_configuration_of_return_values(:update)
399
+ inc_p = !(updates - deletes).empty?
400
+ dec_p = !(starts & deletes).empty?
401
+ bug() if updates.find{|(k, v)| !(k.instance_of?(ClassWrapper) && v.instance_of?(Symbol))}
402
+ bug() if deletes.find{|(k, v)| !(k.instance_of?(ClassWrapper) && v.instance_of?(Symbol))}
403
+ bug() if starts.find{|(k, v)| !(k.instance_of?(ClassWrapper) && v.instance_of?(Symbol))}
404
+ inc_p | dec_p | update_p
336
405
  end
337
406
 
338
407
  def compact()
@@ -2259,7 +2328,7 @@ Currently, CastOff doesn't support object, which cannot marshal dump (e.g. STDIN
2259
2328
  :@@reuse_compiled_code => [true, false, true],
2260
2329
  :@@allow_builtin_variable_incompatibility => [false, true, false],
2261
2330
  :@@prefetch_constant => [true, true, false],
2262
- :@@deoptimize => [false, true, false],
2331
+ :@@deoptimize => [false, true, true],
2263
2332
  :@@development => [false, true, true],
2264
2333
  :@@alert_override => [true, true, false],
2265
2334
  :@@skip_configuration_check => [false, false, true],
@@ -2378,6 +2447,48 @@ Currently, CastOff doesn't support object, which cannot marshal dump (e.g. STDIN
2378
2447
 
2379
2448
  private
2380
2449
 
2450
+ def __ignore_configuration_of_variables(sign)
2451
+ deletes = []
2452
+ @ignore_configuration_of_variables.each do |(k, v)|
2453
+ bug() unless k.instance_of?(Symbol)
2454
+ bug() unless v == true
2455
+ next unless @variable_configuration[k]
2456
+ bug() if @variable_configuration[k].empty?
2457
+ vlog("(#{sign}): ignore #{k} => #{@variable_configuration[k]}")
2458
+ @variable_configuration.delete(k)
2459
+ deletes |= [k]
2460
+ end
2461
+ deletes
2462
+ end
2463
+
2464
+ def __ignore_configuration_of_return_values(sign)
2465
+ deletes = []
2466
+ @ignore_configuration_of_return_values.each do |(k, mids)|
2467
+ bug() if mids.find{|m| !m.instance_of?(Symbol)}
2468
+ if k.instance_of?(ClassWrapper)
2469
+ h = @return_value_configuration[k]
2470
+ next unless h
2471
+ bug() unless h.instance_of?(Hash)
2472
+ kh = {k => h}
2473
+ else
2474
+ bug() unless k == SingletonClass
2475
+ kh = @return_value_configuration.dup
2476
+ end
2477
+ kh.each do |(k, h)|
2478
+ h.keys.each do |m|
2479
+ bug() unless m.instance_of?(Symbol)
2480
+ if mids.include?(m)
2481
+ vlog("(#{sign}): ignore #{k}#{k.singleton? ? '.' : '#'}#{m} => #{h[m]}")
2482
+ h.delete(m)
2483
+ @return_value_configuration.delete(k) if h.empty?
2484
+ deletes |= [[k, m]]
2485
+ end
2486
+ end
2487
+ end
2488
+ end
2489
+ deletes
2490
+ end
2491
+
2381
2492
  def invalid_configuration(message = "Invalid configuration")
2382
2493
  raise(InvalidConfigurationError, message)
2383
2494
  end