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 +1 -1
- data/ext/cast_off/cast_off.c.rb +65 -26
- data/ext/cast_off/generated_c_include/unbox_api.h.rb +57 -3
- data/lib/cast_off/compile/cfg.rb +7 -41
- data/lib/cast_off/compile/configuration.rb +124 -13
- data/lib/cast_off/compile/dependency.rb +66 -18
- data/lib/cast_off/compile/information.rb +19 -75
- data/lib/cast_off/compile/ir/call_ir.rb +55 -57
- data/lib/cast_off/compile/ir/guard_ir.rb +96 -80
- data/lib/cast_off/compile/ir/jump_ir.rb +3 -15
- data/lib/cast_off/compile/ir/operand.rb +33 -47
- data/lib/cast_off/compile/ir/param_ir.rb +3 -24
- data/lib/cast_off/compile/ir/return_ir.rb +3 -13
- data/lib/cast_off/compile/ir/simple_ir.rb +16 -6
- data/lib/cast_off/compile/ir/sub_ir.rb +8 -66
- data/lib/cast_off/compile/iseq.rb +11 -0
- data/lib/cast_off/compile/translator.rb +14 -13
- data/lib/cast_off/compile.rb +122 -39
- data/lib/cast_off/util.rb +2 -0
- metadata +2 -2
data/cast_off.gemspec
CHANGED
data/ext/cast_off/cast_off.c.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
1243
|
-
|
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
|
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
|
-
|
1272
|
-
|
1273
|
-
|
1274
|
-
|
1275
|
-
|
1276
|
-
|
1277
|
-
|
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
|
-
|
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
|
-
%[['
|
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' => ''}]
|
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
|
data/lib/cast_off/compile/cfg.rb
CHANGED
@@ -101,7 +101,7 @@ module CastOff::Compiler
|
|
101
101
|
end
|
102
102
|
|
103
103
|
def all_pointer()
|
104
|
-
ptrs =
|
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.
|
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
|
-
|
279
|
-
|
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
|
-
|
317
|
+
updates << k unless (a0 - a1).empty?
|
294
318
|
a1 |= a0
|
295
319
|
@variable_configuration[k] = a1
|
296
320
|
end
|
297
|
-
|
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
|
-
|
310
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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,
|
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
|