cast_off 0.3.7 → 0.4.0
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/README +81 -513
- data/README.ja +177 -0
- data/bin/cast_off +12 -37
- data/cast_off.gemspec +6 -3
- data/ext/cast_off/cast_off.c.rb +186 -116
- data/ext/cast_off/generated_c_include/inline_api.h +0 -165
- data/ext/cast_off/generated_c_include/unbox_api.h.rb +1 -1
- data/lib/cast_off.rb +1 -0
- data/lib/cast_off/compile.rb +150 -208
- data/lib/cast_off/compile/code_manager.rb +0 -49
- data/lib/cast_off/compile/configuration.rb +8 -8
- data/lib/cast_off/compile/hook_invocation.rb +1 -0
- data/lib/cast_off/compile/ir/call_ir.rb +21 -13
- data/lib/cast_off/compile/translator.rb +6 -7
- data/lib/cast_off/suggestion.rb +1 -1
- metadata +10 -12
- data/README.en +0 -228
@@ -1,126 +1,5 @@
|
|
1
1
|
#define TYPE_ERROR_MESSAGE() "type mismatch"
|
2
2
|
|
3
|
-
static inline VALUE
|
4
|
-
cast_off_inline_fixnum_le(VALUE recv, VALUE obj)
|
5
|
-
{
|
6
|
-
long a, b;
|
7
|
-
|
8
|
-
#if 0
|
9
|
-
#ifdef INJECT_GUARD
|
10
|
-
if (UNLIKELY(!FIXNUM_2_P(recv, obj))) {
|
11
|
-
rb_raise(rb_eCastOffExecutionError, TYPE_ERROR_MESSAGE());
|
12
|
-
}
|
13
|
-
#endif
|
14
|
-
#endif
|
15
|
-
|
16
|
-
a = FIX2LONG(recv);
|
17
|
-
b = FIX2LONG(obj);
|
18
|
-
if (a <= b) {
|
19
|
-
return Qtrue;
|
20
|
-
} else {
|
21
|
-
return Qfalse;
|
22
|
-
}
|
23
|
-
}
|
24
|
-
|
25
|
-
static inline VALUE
|
26
|
-
cast_off_inline_fixnum_lt(VALUE recv, VALUE obj)
|
27
|
-
{
|
28
|
-
long a, b;
|
29
|
-
|
30
|
-
#if 0
|
31
|
-
#ifdef INJECT_GUARD
|
32
|
-
if (UNLIKELY(!FIXNUM_2_P(recv, obj))) {
|
33
|
-
rb_raise(rb_eCastOffExecutionError, TYPE_ERROR_MESSAGE());
|
34
|
-
}
|
35
|
-
#endif
|
36
|
-
#endif
|
37
|
-
|
38
|
-
a = FIX2LONG(recv);
|
39
|
-
b = FIX2LONG(obj);
|
40
|
-
if (a < b) {
|
41
|
-
return Qtrue;
|
42
|
-
} else {
|
43
|
-
return Qfalse;
|
44
|
-
}
|
45
|
-
}
|
46
|
-
|
47
|
-
static inline VALUE
|
48
|
-
cast_off_inline_fixnum_ge(VALUE recv, VALUE obj)
|
49
|
-
{
|
50
|
-
long a, b;
|
51
|
-
|
52
|
-
#if 0
|
53
|
-
#ifdef INJECT_GUARD
|
54
|
-
if (UNLIKELY(!FIXNUM_2_P(recv, obj))) {
|
55
|
-
rb_raise(rb_eCastOffExecutionError, TYPE_ERROR_MESSAGE());
|
56
|
-
}
|
57
|
-
#endif
|
58
|
-
#endif
|
59
|
-
a = FIX2LONG(recv);
|
60
|
-
b = FIX2LONG(obj);
|
61
|
-
if (a >= b) {
|
62
|
-
return Qtrue;
|
63
|
-
} else {
|
64
|
-
return Qfalse;
|
65
|
-
}
|
66
|
-
}
|
67
|
-
|
68
|
-
static inline VALUE
|
69
|
-
cast_off_inline_fixnum_gt(VALUE recv, VALUE obj)
|
70
|
-
{
|
71
|
-
long a, b;
|
72
|
-
|
73
|
-
#if 0
|
74
|
-
#ifdef INJECT_GUARD
|
75
|
-
if (UNLIKELY(!FIXNUM_2_P(recv, obj))) {
|
76
|
-
rb_raise(rb_eCastOffExecutionError, TYPE_ERROR_MESSAGE());
|
77
|
-
}
|
78
|
-
#endif
|
79
|
-
#endif
|
80
|
-
a = FIX2LONG(recv);
|
81
|
-
b = FIX2LONG(obj);
|
82
|
-
if (a > b) {
|
83
|
-
return Qtrue;
|
84
|
-
} else {
|
85
|
-
return Qfalse;
|
86
|
-
}
|
87
|
-
}
|
88
|
-
|
89
|
-
static inline VALUE
|
90
|
-
cast_off_inline_fixnum_eq(VALUE recv, VALUE obj)
|
91
|
-
{
|
92
|
-
#if 0
|
93
|
-
#ifdef INJECT_GUARD
|
94
|
-
if (UNLIKELY(!FIXNUM_2_P(recv, obj))) {
|
95
|
-
rb_raise(rb_eCastOffExecutionError, TYPE_ERROR_MESSAGE());
|
96
|
-
}
|
97
|
-
#endif
|
98
|
-
#endif
|
99
|
-
if (recv == obj) {
|
100
|
-
return Qtrue;
|
101
|
-
} else {
|
102
|
-
return Qfalse;
|
103
|
-
}
|
104
|
-
}
|
105
|
-
#define cast_off_inline_fixnum_eqq(recv, obj) cast_off_inline_fixnum_eq((recv), (obj))
|
106
|
-
|
107
|
-
static inline VALUE
|
108
|
-
cast_off_inline_fixnum_neq(VALUE recv, VALUE obj)
|
109
|
-
{
|
110
|
-
#if 0
|
111
|
-
#ifdef INJECT_GUARD
|
112
|
-
if (UNLIKELY(!FIXNUM_2_P(recv, obj))) {
|
113
|
-
rb_raise(rb_eCastOffExecutionError, TYPE_ERROR_MESSAGE());
|
114
|
-
}
|
115
|
-
#endif
|
116
|
-
#endif
|
117
|
-
if (recv != obj) {
|
118
|
-
return Qtrue;
|
119
|
-
} else {
|
120
|
-
return Qfalse;
|
121
|
-
}
|
122
|
-
}
|
123
|
-
|
124
3
|
static inline VALUE
|
125
4
|
cast_off_inline_fixnum_and(VALUE recv, VALUE obj)
|
126
5
|
{
|
@@ -320,50 +199,6 @@ cast_off_inline_string_empty_p(VALUE str)
|
|
320
199
|
}
|
321
200
|
}
|
322
201
|
|
323
|
-
static inline VALUE
|
324
|
-
cast_off_inline_float_float_plus(VALUE x, VALUE y)
|
325
|
-
{
|
326
|
-
return DBL2NUM(RFLOAT_VALUE(x) + RFLOAT_VALUE(y));
|
327
|
-
}
|
328
|
-
static inline VALUE
|
329
|
-
cast_off_inline_float_fixnum_plus(VALUE x, VALUE y)
|
330
|
-
{
|
331
|
-
return DBL2NUM(RFLOAT_VALUE(x) + (double)FIX2LONG(y));
|
332
|
-
}
|
333
|
-
|
334
|
-
static inline VALUE
|
335
|
-
cast_off_inline_float_float_minus(VALUE x, VALUE y)
|
336
|
-
{
|
337
|
-
return DBL2NUM(RFLOAT_VALUE(x) - RFLOAT_VALUE(y));
|
338
|
-
}
|
339
|
-
static inline VALUE
|
340
|
-
cast_off_inline_float_fixnum_minus(VALUE x, VALUE y)
|
341
|
-
{
|
342
|
-
return DBL2NUM(RFLOAT_VALUE(x) - (double)FIX2LONG(y));
|
343
|
-
}
|
344
|
-
|
345
|
-
static inline VALUE
|
346
|
-
cast_off_inline_float_float_mult(VALUE x, VALUE y)
|
347
|
-
{
|
348
|
-
return DBL2NUM(RFLOAT_VALUE(x) * RFLOAT_VALUE(y));
|
349
|
-
}
|
350
|
-
static inline VALUE
|
351
|
-
cast_off_inline_float_fixnum_mult(VALUE x, VALUE y)
|
352
|
-
{
|
353
|
-
return DBL2NUM(RFLOAT_VALUE(x) * (double)FIX2LONG(y));
|
354
|
-
}
|
355
|
-
|
356
|
-
static inline VALUE
|
357
|
-
cast_off_inline_float_float_div(VALUE x, VALUE y)
|
358
|
-
{
|
359
|
-
return DBL2NUM(RFLOAT_VALUE(x) / RFLOAT_VALUE(y));
|
360
|
-
}
|
361
|
-
static inline VALUE
|
362
|
-
cast_off_inline_float_fixnum_div(VALUE x, VALUE y)
|
363
|
-
{
|
364
|
-
return DBL2NUM(RFLOAT_VALUE(x) / (double)FIX2LONG(y));
|
365
|
-
}
|
366
|
-
|
367
202
|
static inline VALUE
|
368
203
|
cast_off_inline_string_plus(VALUE str1, VALUE str2)
|
369
204
|
{
|
@@ -110,7 +110,7 @@ static inline VALUE MULT(long a, long b)
|
|
110
110
|
% :binary_operator,
|
111
111
|
% {'VALUE' => 'FIX2LONG', 'long' => ''},
|
112
112
|
% {'VALUE' => 'FIX2LONG', 'long' => ''},
|
113
|
-
% {'VALUE' => ''}],
|
113
|
+
% {'VALUE' => 'CBOOL2RBOOL'}],
|
114
114
|
% ['fixnum_float',
|
115
115
|
% {'+' => 'plus', '-' => 'minus', '*' => 'mult'},
|
116
116
|
% 1,
|
data/lib/cast_off.rb
CHANGED
data/lib/cast_off/compile.rb
CHANGED
@@ -22,38 +22,13 @@ module CastOff
|
|
22
22
|
CodeManager.clear()
|
23
23
|
end
|
24
24
|
|
25
|
-
@@
|
26
|
-
]
|
27
|
-
|
28
|
-
@@autoload_proc = nil
|
25
|
+
@@autoload_running_p = false
|
29
26
|
def autoload()
|
30
27
|
return false if autocompile_running?
|
31
|
-
|
32
|
-
@@autoload_proc.call()
|
33
|
-
return true
|
34
|
-
end
|
35
|
-
|
36
|
-
# Marshal.load で定数を参照したときに、クラス定義が走る可能性があるので、
|
37
|
-
# @@autoload_proc を定義する前に、Marshal.load を呼び出しておく。
|
38
|
-
compiled = CodeManager.load_autocompiled()
|
39
|
-
@@autoload_proc = lambda {
|
40
|
-
compiled = CodeManager.load_autocompiled() unless compiled
|
41
|
-
return false unless compiled
|
42
|
-
fin = __load(compiled)
|
43
|
-
hook_class_definition_end(nil) if fin
|
44
|
-
fin
|
45
|
-
}
|
46
|
-
hook_class_definition_end(@@autoload_proc) if RUBY_VERSION == "1.9.3"
|
47
|
-
@@autoload_proc.call()
|
28
|
+
@@autoload_running_p = true
|
48
29
|
true
|
49
30
|
end
|
50
31
|
|
51
|
-
def load()
|
52
|
-
compiled = CodeManager.load_autocompiled()
|
53
|
-
return false unless compiled
|
54
|
-
__load(compiled)
|
55
|
-
end
|
56
|
-
|
57
32
|
@@compilation_threshold = 100
|
58
33
|
def compilation_threshold=(num)
|
59
34
|
raise(ArgumentError.new("first argument should be Integer")) unless num.is_a?(Integer)
|
@@ -62,73 +37,26 @@ module CastOff
|
|
62
37
|
end
|
63
38
|
|
64
39
|
@@autocompile_proc = nil
|
65
|
-
case RUBY_VERSION
|
66
|
-
when "1.9.3"
|
67
|
-
@@compile_auto_incremental = true
|
68
|
-
when "1.9.2"
|
69
|
-
@@compile_auto_incremental = false
|
70
|
-
else
|
71
|
-
bug()
|
72
|
-
end
|
73
|
-
|
74
40
|
def autocompile()
|
75
41
|
return false if autoload_running?
|
76
42
|
return true if autocompile_running?
|
77
43
|
class_table = {}
|
78
|
-
|
79
|
-
|
80
|
-
#cinfo_table = {}
|
81
|
-
compiled = []
|
82
|
-
#@@autocompile_proc = lambda {|file, line, mid, bind, klass, cinfo|
|
83
|
-
@@autocompile_proc = lambda {|file, line, mid, bind, klass|
|
44
|
+
number = 0
|
45
|
+
@@autocompile_proc = lambda {|klass, mid, bind|
|
84
46
|
# trace method invocation
|
85
47
|
# TODO should handle singleton class
|
86
48
|
|
87
|
-
method_table = (class_table[klass] ||= Hash.new(
|
49
|
+
method_table = (class_table[klass] ||= Hash.new(0))
|
88
50
|
count = (method_table[mid] += 1)
|
89
|
-
if count == 0
|
51
|
+
#count = @@compilation_threshold if contain_loop?(klass, mid) if count == 0
|
52
|
+
if count == @@compilation_threshold
|
90
53
|
bug() unless bind.nil?
|
91
54
|
return true # re-call this proc with binding
|
92
55
|
end
|
93
|
-
|
94
|
-
#count = @@compilation_threshold if contain_loop?(klass, mid)
|
95
|
-
bug() unless bind.instance_of?(Binding) || bind.nil?
|
96
|
-
bind_table[[klass, mid]] = bind
|
97
|
-
begin
|
98
|
-
location_table[[klass, mid]] = (file =~ /\(/) ? nil : [File.expand_path(file), line]
|
99
|
-
rescue Errno::ENOENT
|
100
|
-
location_table[[klass, mid]] = nil
|
101
|
-
end
|
102
|
-
end
|
103
|
-
#if cinfo
|
104
|
-
#table = (cinfo_table[[klass, mid]] ||= {})
|
105
|
-
#table[cinfo] = true
|
106
|
-
#end
|
107
|
-
if count == @@compilation_threshold && @@compile_auto_incremental
|
108
|
-
compiled << __autocompile(klass, mid, bind_table, location_table, compiled.size)
|
109
|
-
end
|
56
|
+
__autocompile(klass, mid, bind, (number += 1)) if bind
|
110
57
|
false
|
111
58
|
}
|
112
59
|
hook_method_invocation(@@autocompile_proc)
|
113
|
-
at_exit do
|
114
|
-
hook_method_invocation(nil) # clear trace
|
115
|
-
unless @@compile_auto_incremental
|
116
|
-
targets = []
|
117
|
-
class_table.each do |klass, method_table|
|
118
|
-
method_table.each do |mid, count|
|
119
|
-
next unless count >= @@compilation_threshold
|
120
|
-
targets << [klass, mid, count]
|
121
|
-
end
|
122
|
-
end
|
123
|
-
#targets = sort_targets(targets, cinfo_table)
|
124
|
-
targets.each_with_index do |(klass, mid, count), index|
|
125
|
-
dlog("#{count}: #{klass} #{mid}")
|
126
|
-
compiled << __autocompile(klass, mid, bind_table, location_table, index)
|
127
|
-
end
|
128
|
-
end
|
129
|
-
compiled.compact!
|
130
|
-
CodeManager.dump_auto_compiled(compiled)
|
131
|
-
end
|
132
60
|
true
|
133
61
|
end
|
134
62
|
|
@@ -218,12 +146,134 @@ module CastOff
|
|
218
146
|
__send__(sign, recv)
|
219
147
|
end
|
220
148
|
|
149
|
+
def re_compile_all()
|
150
|
+
all = @@original_singleton_method_iseq.map{|(target, mid), v|
|
151
|
+
[target, mid, true]
|
152
|
+
} + @@original_instance_method_iseq.map{|(target, mid), v|
|
153
|
+
[target, mid, false]
|
154
|
+
}
|
155
|
+
all.each do |(target, mid, singleton)|
|
156
|
+
compilation_method_name = "compile#{singleton ? '_singleton_method' : ''}"
|
157
|
+
separator = singleton ? '.' : '#'
|
158
|
+
begin
|
159
|
+
CastOff.__send__(compilation_method_name, target, mid)
|
160
|
+
rescue ArgumentError, NameError, CompileError => e
|
161
|
+
# ArgumentError: dependency の Marshal.load に失敗
|
162
|
+
# NameError: prefetch constant での定数参照に失敗
|
163
|
+
# CompileError: メソッドが undef されて未定義になってしまった場合
|
164
|
+
vlog("Skip: #{target}#{separator}#{mid}")
|
165
|
+
rescue UnsupportedError => e
|
166
|
+
vlog("Unsupported: #{target}#{separator}#{mid} => #{e}")
|
167
|
+
rescue => e
|
168
|
+
vlog("Catch exception #{e.class}: #{e}\n#{e.backtrace.join("\n")}")
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
def hook_method_definition()
|
174
|
+
Module.class_eval do
|
175
|
+
def method_added(mid)
|
176
|
+
return unless CastOff.autoload_running? && !CastOff.compiler_running? && !CastOff.method_aliasing?
|
177
|
+
CastOff.replace_method_invocation(self, mid, false)
|
178
|
+
end
|
179
|
+
|
180
|
+
def singleton_method_added(mid)
|
181
|
+
return unless CastOff.autoload_running? && !CastOff.compiler_running? && !CastOff.method_aliasing?
|
182
|
+
CastOff.replace_method_invocation(self, mid, true)
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
def do_alias()
|
188
|
+
bug() unless block_given?
|
189
|
+
begin
|
190
|
+
bug() if method_aliasing?
|
191
|
+
method_aliasing(true)
|
192
|
+
yield
|
193
|
+
ensure
|
194
|
+
method_aliasing(false)
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
def restore_method(target, mid, me)
|
199
|
+
do_alias do
|
200
|
+
begin
|
201
|
+
target.__send__(:define_method, mid, me)
|
202
|
+
rescue
|
203
|
+
me = me.clone
|
204
|
+
CastOff.rewrite_rclass_of_unbound_method_object(me, target)
|
205
|
+
begin
|
206
|
+
target.__send__(:define_method, mid, me)
|
207
|
+
rescue => e
|
208
|
+
CastOff.bug("#{target}, #{mid}, #{e}:\n#{e.backtrace}")
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
@@mls = {}
|
215
|
+
def create_method_invocation_callback()
|
216
|
+
proc{|*args, &block|
|
217
|
+
hook_proc = CastOff.current_bmethod_proc()
|
218
|
+
current_method_id = CastOff.current_method_id()
|
219
|
+
target = CastOff.override_target_of_current_method(self)
|
220
|
+
me = @@mls[hook_proc]
|
221
|
+
CastOff.bug() unless me.instance_of?(UnboundMethod)
|
222
|
+
if target && CastOff.singleton_class?(target)
|
223
|
+
compilation_method_id = :compile_singleton_method
|
224
|
+
separator = '.'
|
225
|
+
singleton = true
|
226
|
+
else
|
227
|
+
compilation_method_id = :compile
|
228
|
+
separator = '#'
|
229
|
+
singleton = false
|
230
|
+
unless target
|
231
|
+
# from method object
|
232
|
+
methods = ObjectSpace.each_object(Method).select{|mobj| CastOff.rewrite_method_object(mobj, me, hook_proc)}
|
233
|
+
me = methods.find{|m| m.receiver.__id__ == self.__id__}
|
234
|
+
CastOff.bug() unless me.instance_of?(Method)
|
235
|
+
CastOff.vlog("rewrite method object #{me}")
|
236
|
+
return me.call(*args, &block)
|
237
|
+
end
|
238
|
+
end
|
239
|
+
CastOff.bug() unless CastOff.instance_bmethod_proc(target.instance_method(current_method_id)) == hook_proc
|
240
|
+
CastOff.restore_method(target, current_method_id, me)
|
241
|
+
CastOff.bug() unless CastOff.get_compilable_iseq(target, current_method_id, false)
|
242
|
+
begin
|
243
|
+
CastOff.__send__(compilation_method_id, singleton ? self : target, current_method_id)
|
244
|
+
rescue
|
245
|
+
CastOff.vlog("failed to load #{target}#{separator}#{current_method_id}")
|
246
|
+
end
|
247
|
+
target.instance_method(current_method_id).bind(self).call(*args, &block)
|
248
|
+
}
|
249
|
+
end
|
250
|
+
|
251
|
+
def replace_method_invocation(obj, mid, singleton_p)
|
252
|
+
iseq = get_compilable_iseq(obj, mid, singleton_p)
|
253
|
+
return unless iseq
|
254
|
+
filepath = get_iseq_filepath(iseq)
|
255
|
+
line_no = get_iseq_line(iseq)
|
256
|
+
return unless CodeManager.compiled_method_exist?(filepath, line_no)
|
257
|
+
target = singleton_p ? obj.singleton_class : override_target(obj, mid)
|
258
|
+
begin
|
259
|
+
original_method = target.instance_method(mid)
|
260
|
+
rescue => e
|
261
|
+
CastOff.bug(e)
|
262
|
+
end
|
263
|
+
do_alias do
|
264
|
+
hook_proc = create_method_invocation_callback()
|
265
|
+
target.__send__(:define_method, mid, &hook_proc)
|
266
|
+
CastOff.bug() if @@mls[hook_proc]
|
267
|
+
@@mls[hook_proc] = original_method
|
268
|
+
end
|
269
|
+
end
|
270
|
+
|
221
271
|
def autocompile_running?
|
222
272
|
!!@@autocompile_proc
|
223
273
|
end
|
224
274
|
|
225
275
|
def autoload_running?
|
226
|
-
!!@@
|
276
|
+
!!@@autoload_running_p
|
227
277
|
end
|
228
278
|
|
229
279
|
def compiler_running?
|
@@ -234,6 +284,10 @@ module CastOff
|
|
234
284
|
!!Thread.current[METHOD_REPLACING_KEY]
|
235
285
|
end
|
236
286
|
|
287
|
+
def method_aliasing?
|
288
|
+
!!Thread.current[METHOD_ALIASING_KEY]
|
289
|
+
end
|
290
|
+
|
237
291
|
private
|
238
292
|
|
239
293
|
COMPILER_RUNNING_KEY = :CastOffCompilerRunning
|
@@ -246,6 +300,11 @@ module CastOff
|
|
246
300
|
Thread.current[METHOD_REPLACING_KEY] = bool
|
247
301
|
end
|
248
302
|
|
303
|
+
METHOD_ALIASING_KEY = :CastOffMethodAliasing
|
304
|
+
def method_aliasing(bool)
|
305
|
+
Thread.current[METHOD_ALIASING_KEY] = bool
|
306
|
+
end
|
307
|
+
|
249
308
|
Lock = Mutex.new()
|
250
309
|
def execute_no_hook()
|
251
310
|
bug() unless block_given?
|
@@ -253,7 +312,6 @@ module CastOff
|
|
253
312
|
begin
|
254
313
|
compiler_running(true)
|
255
314
|
hook_m = hook_method_invocation(nil)
|
256
|
-
hook_c = hook_class_definition_end(nil)
|
257
315
|
yield
|
258
316
|
ensure
|
259
317
|
compiler_running(false)
|
@@ -261,10 +319,6 @@ module CastOff
|
|
261
319
|
bug() unless autocompile_running?
|
262
320
|
hook_method_invocation(@@autocompile_proc)
|
263
321
|
end
|
264
|
-
if hook_c
|
265
|
-
bug() unless autoload_running?
|
266
|
-
hook_class_definition_end(@@autoload_proc)
|
267
|
-
end
|
268
322
|
end
|
269
323
|
end
|
270
324
|
end
|
@@ -340,6 +394,7 @@ Currently, CastOff cannot compile method which source file is not exist.
|
|
340
394
|
return false unless update_p
|
341
395
|
ann = manager.load_annotation() || {}
|
342
396
|
bug() unless ann.instance_of?(Hash)
|
397
|
+
warn("re-compile(#{target}#{singleton ? '.' : '#'}#{mid})")
|
343
398
|
begin
|
344
399
|
__send__(singleton ? 'compile_singleton_method' : 'compile', target, mid, ann, nil, true)
|
345
400
|
vlog("re-compilation success: #{target}#{singleton ? '.' : '#'}#{mid}")
|
@@ -376,7 +431,8 @@ Currently, CastOff cannot compile method which source file is not exist.
|
|
376
431
|
conf = Configuration.new(annotation, bind)
|
377
432
|
union_base_configuration(conf, manager)
|
378
433
|
end
|
379
|
-
|
434
|
+
warn("compilng #{mid}...")
|
435
|
+
vlog("use configuration #{conf}, has_binding? = #{!!conf.bind}")
|
380
436
|
|
381
437
|
require 'cast_off/compile/namespace/uuid'
|
382
438
|
require 'cast_off/compile/namespace/namespace'
|
@@ -421,82 +477,6 @@ Currently, CastOff cannot compile method which source file is not exist.
|
|
421
477
|
conf
|
422
478
|
end
|
423
479
|
|
424
|
-
@@skipped = []
|
425
|
-
def __load(compiled)
|
426
|
-
begin
|
427
|
-
(@@skipped + compiled.dup).each do |entry|
|
428
|
-
klass, mid, singleton, file, line, bind = entry
|
429
|
-
if @@blacklist.include?(mid)
|
430
|
-
compiled.delete(entry)
|
431
|
-
next
|
432
|
-
end
|
433
|
-
bind = bind.bind if bind
|
434
|
-
skip = false
|
435
|
-
begin
|
436
|
-
if singleton
|
437
|
-
iseq = @@original_singleton_method_iseq[[klass, mid]] || get_iseq(klass, mid, true)
|
438
|
-
else
|
439
|
-
t = override_target(klass, mid)
|
440
|
-
iseq = @@original_instance_method_iseq[[t, mid]] || get_iseq(klass, mid, false)
|
441
|
-
end
|
442
|
-
rescue CompileError, UnsupportedError
|
443
|
-
@@skipped |= [entry]
|
444
|
-
dlog("skip: entry = #{entry}")
|
445
|
-
skip = true
|
446
|
-
end
|
447
|
-
f, l = *iseq.to_a.slice(7, 2) unless skip
|
448
|
-
if !skip && f == file && l == line
|
449
|
-
begin
|
450
|
-
@@skipped.delete(entry)
|
451
|
-
if singleton
|
452
|
-
CastOff.compile_singleton_method(klass, mid, bind)
|
453
|
-
else
|
454
|
-
CastOff.compile(klass, mid, bind)
|
455
|
-
end
|
456
|
-
vlog("load #{klass}##{mid}")
|
457
|
-
rescue ArgumentError, NameError => e
|
458
|
-
# ArgumentError: dependency の Marshal.load に失敗
|
459
|
-
# NameError: prefetch constant での定数参照に失敗
|
460
|
-
vlog("skip: entry = #{entry[0]}#{entry[2] ? '.' : '#'}#{entry[1]}, #{e}")
|
461
|
-
CodeManager.delete_from_compiled(entry)
|
462
|
-
rescue UnsupportedError => e
|
463
|
-
vlog("unsupported #{klass}##{mid} => #{e}")
|
464
|
-
CodeManager.delete_from_compiled(entry)
|
465
|
-
end
|
466
|
-
else
|
467
|
-
dlog("iseq.filepath = #{f}, file = #{file}\niseq.line = #{l}, line = #{line}")
|
468
|
-
end
|
469
|
-
compiled.delete(entry)
|
470
|
-
end
|
471
|
-
if compiled.empty?
|
472
|
-
vlog("---------- load finish ----------") if @@skipped.empty?
|
473
|
-
true
|
474
|
-
else
|
475
|
-
false
|
476
|
-
end
|
477
|
-
rescue => e
|
478
|
-
vlog("catch exception #{e.class}: #{e}\n#{e.backtrace.join("\n")}")
|
479
|
-
false
|
480
|
-
end
|
481
|
-
end
|
482
|
-
|
483
|
-
s = class << BasicObject
|
484
|
-
self
|
485
|
-
end
|
486
|
-
continue_load = RUBY_VERSION != "1.9.3"
|
487
|
-
s.class_eval do
|
488
|
-
define_method(:method_added) do |mid|
|
489
|
-
return unless CastOff.respond_to?(:autoload_running?)
|
490
|
-
if CastOff.autoload_running? && (!@@skipped.empty? || continue_load) && !CastOff.compiler_running?
|
491
|
-
continue_load &= !@@autoload_proc.call()
|
492
|
-
end
|
493
|
-
end
|
494
|
-
end
|
495
|
-
#Module.class_eval do
|
496
|
-
#define_method(:autoload) do |*args|
|
497
|
-
#raise(ExecutionError.new("Currently, CastOff doesn't support Module#autoload"))
|
498
|
-
#end
|
499
|
-
#end
|
500
480
|
Kernel.module_eval do
|
501
481
|
def set_trace_func(*args, &p)
|
502
482
|
raise(ExecutionError.new("Currently, CastOff doesn't support set_trace_func"))
|
@@ -573,21 +553,18 @@ Currently, CastOff cannot compile method which source file is not exist.
|
|
573
553
|
singleton ? :singleton_method : :instance_method
|
574
554
|
end
|
575
555
|
|
576
|
-
def __autocompile(klass, mid,
|
556
|
+
def __autocompile(klass, mid, bind, index)
|
577
557
|
case compilation_target_type(klass, mid)
|
578
558
|
when :singleton_method
|
579
559
|
singleton = true
|
580
560
|
when :instance_method
|
581
561
|
singleton = false
|
582
562
|
when nil
|
583
|
-
return
|
563
|
+
return false
|
584
564
|
else
|
585
565
|
bug()
|
586
566
|
end
|
587
567
|
begin
|
588
|
-
location = location_table[[klass, mid]]
|
589
|
-
return nil unless location
|
590
|
-
bind = bind_table[[klass, mid]]
|
591
568
|
if singleton
|
592
569
|
CastOff.compile_singleton_method(klass, mid, bind)
|
593
570
|
else
|
@@ -600,47 +577,11 @@ Currently, CastOff cannot compile method which source file is not exist.
|
|
600
577
|
return nil
|
601
578
|
end
|
602
579
|
vlog("#{index}: compile #{klass}#{singleton ? '.' : '#'}#{mid}")
|
603
|
-
|
604
|
-
rescue UnsupportedError, CompileError => e
|
580
|
+
true
|
581
|
+
rescue UnsupportedError, CompileError, ArgumentError => e
|
605
582
|
vlog("#{index}: failed to compile #{klass}#{singleton ? '.' : '#'}#{mid} (#{e.message})")
|
606
|
-
|
607
|
-
end
|
608
|
-
end
|
609
|
-
|
610
|
-
def __sort_targets(entry, targets, cinfo_table)
|
611
|
-
result = []
|
612
|
-
unless cinfo_table[entry]
|
613
|
-
result << entry
|
614
|
-
dlog("<< #{entry}: nil")
|
615
|
-
return result # FIXME
|
616
|
-
end
|
617
|
-
|
618
|
-
targets.each do |te|
|
619
|
-
bug() if entry == te
|
620
|
-
next unless cinfo_table[te]
|
621
|
-
next unless cinfo_table[te].keys.include?(entry) # entry calls te
|
622
|
-
next if cinfo_table[entry].keys.include?(te) # cycle
|
623
|
-
targets.delete(te)
|
624
|
-
result += __sort_targets(te, targets, cinfo_table)
|
625
|
-
end
|
626
|
-
dlog("<< #{entry}: #{cinfo_table[entry].keys}")
|
627
|
-
result << entry
|
628
|
-
result
|
629
|
-
end
|
630
|
-
|
631
|
-
def sort_targets(targets, cinfo_table)
|
632
|
-
result = []
|
633
|
-
counts = {}
|
634
|
-
targets = targets.sort{|v0, v1| v1.last <=> v0.last}
|
635
|
-
targets.each{|klass, mid, count| counts[[klass, mid]] = count}
|
636
|
-
targets = targets.map{|klass, mid, count| [klass, mid]}
|
637
|
-
until targets.empty?
|
638
|
-
entry = targets.shift
|
639
|
-
result += __sort_targets(entry, targets, cinfo_table)
|
583
|
+
false
|
640
584
|
end
|
641
|
-
result.map!{|entry| entry + [counts[entry]]}
|
642
|
-
bug() unless result.size == counts.size
|
643
|
-
result
|
644
585
|
end
|
645
586
|
|
646
587
|
def parse_sampling_table(sampling_table)
|
@@ -691,9 +632,10 @@ Currently, CastOff cannot compile method which source file is not exist.
|
|
691
632
|
last = manager.load_last_configuration()
|
692
633
|
bind = last ? (last.bind ? last.bind.bind : nil) : nil
|
693
634
|
base_configuration = Configuration.new({}, bind)
|
635
|
+
update_p = true
|
694
636
|
end
|
695
637
|
bug() unless base_configuration.instance_of?(Configuration)
|
696
|
-
update_p
|
638
|
+
update_p |= update_configuration(base_configuration, reciever_result, return_value_result)
|
697
639
|
return false unless update_p
|
698
640
|
manager.save_base_configuration(base_configuration)
|
699
641
|
true
|