cast_off 0.2.3 → 0.3.1
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 +22 -47
- data/README.en +14 -36
- data/bin/{CastOff → cast_off} +53 -22
- data/cast_off.gemspec +2 -2
- data/lib/cast_off/compile/basicblock.rb +12 -0
- data/lib/cast_off/compile/cfg.rb +1 -1
- data/lib/cast_off/compile/code_manager.rb +3 -2
- data/lib/cast_off/compile/configuration.rb +43 -29
- data/lib/cast_off/compile/information.rb +363 -229
- data/lib/cast_off/compile/ir/guard_ir.rb +29 -9
- data/lib/cast_off/compile/ir/simple_ir.rb +2 -2
- data/lib/cast_off/compile/translator.rb +48 -10
- data/lib/cast_off/compile.rb +42 -17
- metadata +4 -4
data/README
CHANGED
@@ -22,8 +22,8 @@ $gem install cast_off
|
|
22
22
|
CastOff は Ruby 処理系に一切手をくわえることなく、Ruby 処理系の拡張ライブラリとして実装しています。
|
23
23
|
このため、gem コマンド経由で容易にインストールすることができます。
|
24
24
|
ただし、脱最適化などの処理が処理系の実装依存になっているため、Ruby 1.9.3 のみの対応となっています。
|
25
|
-
一応 Ruby 1.9.2
|
26
|
-
Ruby1.9.2 と Ruby1.9.3 以外のバージョンの Ruby
|
25
|
+
一応 Ruby 1.9.2 でも動作しますが、Ruby 1.9.3 よりも不安定かもしれません。
|
26
|
+
Ruby1.9.2 と Ruby1.9.3 以外のバージョンの Ruby 処理系では動作しないため、ご注意ください。
|
27
27
|
|
28
28
|
|
29
29
|
|
@@ -133,13 +133,13 @@ CastOff の利用方法には、コマンドラインからの利用とスクリ
|
|
133
133
|
** コマンドラインからの利用
|
134
134
|
|
135
135
|
*** コマンドラインからの利用の流れ
|
136
|
-
|
137
|
-
|
136
|
+
CastOff が提供するコマンドラインツール cast_off では、
|
137
|
+
引数に高速化したいプログラムを指定することで、容易にコンパイルを行うことができます。
|
138
138
|
詳しくは下で解説しますが、コマンドラインからの CastOff の利用は、
|
139
139
|
次のようなコマンドを繰り返し実行することで行います。
|
140
140
|
|
141
141
|
-----------------------------------------------------
|
142
|
-
$
|
142
|
+
$cast_off コンパイル対象のスクリプト コンパイル対象に与える引数の例
|
143
143
|
-----------------------------------------------------
|
144
144
|
|
145
145
|
例えば、次のようなスクリプトの実行を高速化したい場合、
|
@@ -149,35 +149,19 @@ $ruby foo.rb bar
|
|
149
149
|
次のように実行することで、foo.rb と、使用するライブラリをコンパイルすることができます。
|
150
150
|
(この例での bar は、foo.rb に対する引数です)
|
151
151
|
|
152
|
-
$
|
152
|
+
$cast_off foo.rb bar
|
153
153
|
|
154
|
-
|
154
|
+
コマンドラインからのコンパイルは、次の2つの手順で行います。
|
155
155
|
1:コンパイル対象のメソッドを決定
|
156
156
|
2:コンパイル対象のプロファイル情報を収集し、コンパイル
|
157
157
|
この2つのステップそれぞれで対象プログラムを実行します。
|
158
158
|
このため、上の例の場合、foo.rb を、コンパイルのために2度実行します。
|
159
159
|
実行の回数は、今後、1-2の手順をまとめることで、削減する予定です。
|
160
160
|
|
161
|
-
|
162
|
-
|
163
|
-
上の例の場合、次のようなソースコードを貼り付けることで、
|
164
|
-
foo.rb の実行の際にコンパイル済みコードを使用することができます。
|
165
|
-
コマンドラインからのコンパイルが済んだ後は、コンパイルにかかる時間を気にする必要はありません。
|
166
|
-
-----------------------------------------------------
|
167
|
-
require 'cast_off'
|
168
|
-
CastOff.program_name = "foo.rb"
|
169
|
-
CastOff.skip_configuration_check(true)
|
170
|
-
CastOff.deoptimize(false)
|
171
|
-
CastOff.use_default_configuration()
|
172
|
-
CastOff.autoload()
|
173
|
-
-----------------------------------------------------
|
174
|
-
|
175
|
-
CastOff.autoload は、Ruby 処理系が提供するトレース API を用いて動作します。
|
176
|
-
この API は実行時のオーバヘッドが大きいため、CastOff.autoload を呼び出してから、
|
177
|
-
コンパイル済みコードの読み込みが終了するまで、対象プログラムの実行速度が大きく低下します。
|
161
|
+
コンパイルした後は、--run オプションを用いることで、コンパイルしたコードを読み込んで動作させることができます。
|
162
|
+
上の例の場合、次のようなコマンドを実行することで、コンパイル済みコードを用いて foo.rb を実行することができます。
|
178
163
|
|
179
|
-
|
180
|
-
このため、CastOff.autoload の呼び出しは、require 文などを一通り呼び終えた後に行うのが、もっとも効率が良いです。
|
164
|
+
$cast_off --run foo.rb bar
|
181
165
|
|
182
166
|
また、コマンドラインからの利用で注意する必要があるのは、コンパイル時とは異なる引数を用いて実行する場合の挙動です。
|
183
167
|
上の例では、コンパイル時に bar という引数を与えています。
|
@@ -200,7 +184,7 @@ when 'baz'
|
|
200
184
|
end
|
201
185
|
-----------------------------------------------------
|
202
186
|
|
203
|
-
ここで、
|
187
|
+
ここで、cast_off foo.rb bar として foo.rb をコンパイルすると、CastOff は、プロファイル情報から、
|
204
188
|
sample メソッドに渡されるオブジェクトは String オブジェクトのみであるという判断を下します。
|
205
189
|
そして、sample メソッドに渡されるオブジェクトが String オブジェクトであるという前提に基づいたコードを生成します。
|
206
190
|
このため、foo.rb に baz という引数を渡した場合、sample メソッドに対し、想定していなかった Symbol オブジェクトが
|
@@ -210,24 +194,24 @@ CastOff は、コンパイルの前提条件が崩れたことを検出したと
|
|
210
194
|
|
211
195
|
このような場合には、
|
212
196
|
|
213
|
-
$
|
197
|
+
$cast_off foo.rb bar
|
214
198
|
|
215
199
|
とした次に、
|
216
200
|
|
217
|
-
$
|
201
|
+
$cast_off foo.rb baz
|
218
202
|
|
219
203
|
としてください。
|
220
204
|
このようにすることで、引数を bar とした場合、引数を baz とした場合の両方のプロファイル情報を用いてコンパイルを行うことができます。
|
221
|
-
プロファイル情報やコンパイル結果を削除したい場合は、--clear
|
205
|
+
プロファイル情報やコンパイル結果を削除したい場合は、--clear という引数を与えて実行してください。
|
222
206
|
|
223
207
|
|
224
208
|
***コマンドライン引数
|
225
|
-
|
209
|
+
cast_off [options] [programfile] [arguments]
|
226
210
|
|
227
211
|
|
228
212
|
***オプション一覧
|
229
|
-
--
|
230
|
-
|
213
|
+
--run
|
214
|
+
コンパイル済みコードを用いて、対象プログラム[programfile]を実行します。
|
231
215
|
|
232
216
|
--deoptimize
|
233
217
|
脱最適化を有効にします。
|
@@ -235,7 +219,7 @@ CastOff [options] [programfile] [arguments]
|
|
235
219
|
--clear
|
236
220
|
プロファイル結果やコンパイル結果を削除します。
|
237
221
|
name オプションによって foo と名づけたコンパイル結果を削除する場合、次のコマンドを使用してください。
|
238
|
-
$
|
222
|
+
$cast_off --clear --name=foo
|
239
223
|
|
240
224
|
--threshold=COUNT
|
241
225
|
COUNT 回以上実行されたメソッドをコンパイルするよう、閾値を設定します。
|
@@ -248,24 +232,15 @@ COUNT のデフォルト値は100です。
|
|
248
232
|
に変更が無かった場合、CastOff はコンパイル済みコードを再利用します。
|
249
233
|
name オプションを使用しなかった場合、CastOff は File.basename([programfile]) の結果を名前として使用します。
|
250
234
|
|
235
|
+
--verbose
|
236
|
+
コンパイルの進捗とコンパイル結果に関する内部情報を表示します。
|
237
|
+
|
251
238
|
-h, --help
|
252
|
-
|
239
|
+
ヘルプメッセージを表示します。
|
253
240
|
|
254
241
|
--version
|
255
242
|
CastOff のバージョンを表示します。
|
256
243
|
|
257
|
-
--step-1
|
258
|
-
コンパイルの最初のステップを実行します。
|
259
|
-
このステップでは、コンパイル対象のメソッドを決定します。
|
260
|
-
|
261
|
-
--step-2
|
262
|
-
コンパイルの2番目のステップを実行します。
|
263
|
-
このステップでは、コンパイル対象のプロファイル情報を収集します。
|
264
|
-
そして、コンパイル対象のメソッドをコンパイルします。
|
265
|
-
|
266
|
-
--run
|
267
|
-
コンパイル済みコードを用いて、対象プログラム[programfile]を実行します。
|
268
|
-
|
269
244
|
|
270
245
|
|
271
246
|
** スクリプトからの利用
|
data/README.en
CHANGED
@@ -89,19 +89,19 @@ end
|
|
89
89
|
* Usage
|
90
90
|
|
91
91
|
** Use CastOff from command line
|
92
|
-
By use of command line tool
|
92
|
+
By use of command line tool cast_off, you can improve performance of your Ruby program easily.
|
93
93
|
If you want to improve performance of your Ruby program, you should execute following command repeatedly.
|
94
94
|
|
95
95
|
-----------------------------------------------------
|
96
|
-
$
|
96
|
+
$cast_off PathOfTargetProgram ArgumentsOfTargetProgram
|
97
97
|
-----------------------------------------------------
|
98
98
|
|
99
99
|
For example, when you want to improve performance of Ruby program "foo.rb"
|
100
100
|
(in this example, "foo.rb" recieves one argument "bar" or "baz"), you should execute following commands.
|
101
101
|
|
102
102
|
-----------------------------------------------------
|
103
|
-
$
|
104
|
-
$
|
103
|
+
$cast_off foo.rb bar
|
104
|
+
$cast_off foo.rb baz
|
105
105
|
-----------------------------------------------------
|
106
106
|
|
107
107
|
When you execute these commands, CastOff does followings to compile foo.rb and related libraries.
|
@@ -111,34 +111,20 @@ When you execute these commands, CastOff does followings to compile foo.rb and r
|
|
111
111
|
3: Executes "foo.rb" with argument "baz" to get and update profile information.
|
112
112
|
4: Compiles "foo.rb" and related libraries.
|
113
113
|
|
114
|
-
|
115
|
-
|
116
|
-
In above example, CastOff outputs following codes.
|
114
|
+
After CastOff finishes compilation, you can run target program with --run option.
|
115
|
+
In above example, you can run target program with compiled codes by use of following command.
|
117
116
|
|
118
|
-
|
119
|
-
require 'cast_off'
|
120
|
-
CastOff.program_name = "foo.rb"
|
121
|
-
CastOff.skip_configuration_check(true)
|
122
|
-
CastOff.deoptimize(false)
|
123
|
-
CastOff.use_default_configuration()
|
124
|
-
CastOff.autoload()
|
125
|
-
-----------------------------------------------------
|
126
|
-
|
127
|
-
"CastOff.autoload" uses trace api provided from Ruby runtime.
|
128
|
-
But this api slows down Ruby program execution significantly.
|
129
|
-
If you want to avoid this overhead, call "CastOff.autoload" after all method definitions.
|
130
|
-
CastOff uses trace api to check method definition,
|
131
|
-
so if you call "CastOff.autoload" after all method definitions, CastOff can cancel tracing immediately.
|
117
|
+
$cast_off --run foo.rb bar
|
132
118
|
|
133
119
|
|
134
120
|
*** Command line arguments
|
135
121
|
|
136
|
-
|
122
|
+
cast_off [options] PathOfTargetProgram ArgumentsOfTargetProgram
|
137
123
|
|
138
124
|
|
139
125
|
*** Command line options
|
140
|
-
--
|
141
|
-
|
126
|
+
--run
|
127
|
+
Execute target program with compiled methods.
|
142
128
|
|
143
129
|
--deoptimize
|
144
130
|
Enable deoptimization.
|
@@ -147,7 +133,7 @@ Enable deoptimization.
|
|
147
133
|
Clear profile information and delete compiled methods.
|
148
134
|
If you want to clear profile information and compiled methods of target name "foo",
|
149
135
|
you should execute following command.
|
150
|
-
$
|
136
|
+
$cast_off --clear --name=foo
|
151
137
|
|
152
138
|
--threshold=COUNT
|
153
139
|
Compile method which is executed more than COUNT.
|
@@ -158,23 +144,15 @@ Name compiled methods NAME.
|
|
158
144
|
This name is used for search of compiled methods.
|
159
145
|
If you don't use this option, CastOff uses File.basename([programfile]) as name.
|
160
146
|
|
147
|
+
--verbose
|
148
|
+
Show compilation progress and internal information.
|
149
|
+
|
161
150
|
-h, --help
|
162
151
|
Show help.
|
163
152
|
|
164
153
|
--version
|
165
154
|
Show version number of CastOff.
|
166
155
|
|
167
|
-
--step-1
|
168
|
-
Execute first step of compilation.
|
169
|
-
On this step, CastOff decides compilation target methods.
|
170
|
-
|
171
|
-
--step-2
|
172
|
-
Execute second step of compilation.
|
173
|
-
On this step, CastOff collects profile information and compiles methods.
|
174
|
-
|
175
|
-
--run
|
176
|
-
Execute target program with compiled methods.
|
177
|
-
|
178
156
|
|
179
157
|
|
180
158
|
** Use CastOff from script
|
data/bin/{CastOff → cast_off}
RENAMED
@@ -16,11 +16,11 @@ opt = OptionParser.new(<<-EOS, 32, ' ')
|
|
16
16
|
CastOff is a performance improvement tool for Ruby1.9.3.
|
17
17
|
|
18
18
|
Usage:
|
19
|
-
|
19
|
+
cast_off [options] [programfile] [arguments]
|
20
20
|
EOS
|
21
21
|
opt.separator("\n Options:")
|
22
|
-
opt.on('--
|
23
|
-
|
22
|
+
opt.on('--run', <<-EOS.strip) {|v| step = 'run' }
|
23
|
+
Execute [programfile] with compiled codes.
|
24
24
|
EOS
|
25
25
|
opt.on('--deoptimize', <<-EOS.strip) {|v| deoptimize = true }
|
26
26
|
Enable deoptimization.
|
@@ -30,29 +30,43 @@ opt.on('--threshold=COUNT', <<-EOS.strip, Integer) {|v| threshold = v }
|
|
30
30
|
Default value is 100.
|
31
31
|
EOS
|
32
32
|
opt.on('--name=NAME', <<-EOS.strip, String) {|v| name = v }
|
33
|
-
Name compiled
|
34
|
-
This name is used for search of compiled
|
33
|
+
Name compiled codes NAME.
|
34
|
+
This name is used for search of compiled codes.
|
35
35
|
If you don't use this option, CastOff uses File.basename([programfile]) as name.
|
36
36
|
EOS
|
37
37
|
opt.on('--clear', <<-EOS.strip) {|v| clear = true }
|
38
|
-
Clear profile information and delete compiled
|
39
|
-
If you want to clear profile information and compiled
|
38
|
+
Clear profile information and delete compiled codes.
|
39
|
+
If you want to clear profile information and compiled codes of target name "foo",
|
40
40
|
you should execute following command.
|
41
|
-
$
|
42
|
-
EOS
|
43
|
-
opt.on('--run', <<-EOS.strip) {|v| step = 'run' }
|
44
|
-
Execute [programfile] with compiled methods.
|
41
|
+
$cast_off --clear --name=foo
|
45
42
|
EOS
|
46
|
-
opt.on('--step-1'
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
opt.on('--step-2', <<-EOS.strip) {|v| step = '2' }
|
51
|
-
Second step of compilation.
|
52
|
-
On this step, CastOff collects profile information and compiles methods.
|
43
|
+
opt.on('--step-1') {|v| step = '1' }
|
44
|
+
opt.on('--step-2') {|v| step = '2' }
|
45
|
+
opt.on('--verbose', <<-EOS.strip) {|v| verbose = true }
|
46
|
+
Show compilation progress and internal information.
|
53
47
|
EOS
|
54
48
|
opt.on_tail('-h', "--help", "Show this help.") do
|
55
|
-
|
49
|
+
message = opt.to_s.gsub(/\n[ ]*--step-[0-9]+[ ]*/, '')
|
50
|
+
message.concat(<<-EOS)
|
51
|
+
|
52
|
+
Example:
|
53
|
+
------------------------------------------
|
54
|
+
# fib.rb
|
55
|
+
def fib n
|
56
|
+
(n < 3) ? 1 : (fib(n-1) + fib(n-2))
|
57
|
+
end
|
58
|
+
fib(ARGV.shift.to_i)
|
59
|
+
------------------------------------------
|
60
|
+
|
61
|
+
1 Profile and compile fib.rb:
|
62
|
+
$cast_off fib.rb 30 # 30 is a argument of fib.rb
|
63
|
+
|
64
|
+
2 Run fib.rb with compiled codes:
|
65
|
+
$cast_off --run fib.rb 30 # 30 is a argument of fib.rb
|
66
|
+
|
67
|
+
Report bugs to <http://github.com/soba1104/CastOff/issues>.
|
68
|
+
EOS
|
69
|
+
puts message
|
56
70
|
exit
|
57
71
|
end
|
58
72
|
opt.on_tail("--version", "Show version number.") do
|
@@ -70,9 +84,9 @@ if clear
|
|
70
84
|
if name.empty?
|
71
85
|
STDERR.puts(<<-EOS)
|
72
86
|
Invalid arguments. You should pass target name to CastOff.
|
73
|
-
If you want to clear profile information and compiled
|
87
|
+
If you want to clear profile information and compiled codes of target name "foo",
|
74
88
|
you should execute following command.
|
75
|
-
$
|
89
|
+
$cast_off --clear --name=foo
|
76
90
|
EOS
|
77
91
|
exit(1)
|
78
92
|
end
|
@@ -104,7 +118,13 @@ CastOff.verbose(verbose)
|
|
104
118
|
case step
|
105
119
|
when nil
|
106
120
|
STDERR.puts("-------------------------------- compilation start: threshold = #{threshold}, name = #{name}, profiling = ruby #{args} --------------------------------")
|
107
|
-
2.times
|
121
|
+
2.times do |i|
|
122
|
+
system("#{this} --step-#{i + 1} --threshold=#{threshold} --name=#{name} #{deoptimize ? '--deoptimize' : ''} #{verbose ? '--verbose' : ''} #{args}")
|
123
|
+
unless $? == 0
|
124
|
+
STDERR.puts("Failed to execute 'ruby #{args}'")
|
125
|
+
exit
|
126
|
+
end
|
127
|
+
end
|
108
128
|
when '1'
|
109
129
|
STDERR.puts("-------------------------------- step 1 --------------------------------") if verbose
|
110
130
|
CastOff.development(true)
|
@@ -123,6 +143,7 @@ when '2'
|
|
123
143
|
}
|
124
144
|
fin = Object.new
|
125
145
|
ObjectSpace.define_finalizer(fin){
|
146
|
+
=begin
|
126
147
|
msg = <<-EOS
|
127
148
|
|
128
149
|
----------------------------------------------------------------------------------------
|
@@ -132,6 +153,15 @@ Please add following lines to top of #{script}.
|
|
132
153
|
require 'cast_off'
|
133
154
|
#{configuration.chomp}
|
134
155
|
CastOff.autoload()
|
156
|
+
----------------------------------------------------------------------------------------
|
157
|
+
EOS
|
158
|
+
=end
|
159
|
+
msg = <<-EOS
|
160
|
+
----------------------------------------------------------------------------------------
|
161
|
+
Compilation finished successfully.
|
162
|
+
You can execute #{script} with compiled codes by use of following command.
|
163
|
+
|
164
|
+
$cast_off --run --name=#{name}#{deoptimize ? ' --deoptimize ' : ' '}#{args}
|
135
165
|
----------------------------------------------------------------------------------------
|
136
166
|
EOS
|
137
167
|
STDERR.puts(msg)
|
@@ -142,5 +172,6 @@ else
|
|
142
172
|
raise("should not be reached")
|
143
173
|
end
|
144
174
|
|
175
|
+
$0 = script
|
145
176
|
load script if step
|
146
177
|
|
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
|
+
spec.version = "0.3.1"
|
4
4
|
spec.platform = Gem::Platform::RUBY
|
5
5
|
spec.summary = "Performance improvement tool for Ruby1.9.3"
|
6
6
|
spec.description = <<-EOS
|
@@ -10,7 +10,7 @@ CastOff is a performance improvement tool for Ruby1.9.3
|
|
10
10
|
cast_off.gemspec
|
11
11
|
]
|
12
12
|
spec.bindir = 'bin'
|
13
|
-
spec.executables << '
|
13
|
+
spec.executables << 'cast_off'
|
14
14
|
spec.require_path = 'lib'
|
15
15
|
spec.extensions = 'ext/cast_off/extconf.rb'
|
16
16
|
spec.has_rdoc = false
|
@@ -23,6 +23,18 @@ module CastOff::Compiler
|
|
23
23
|
bug() if @insns.find{|i| i.iseq != @iseq}
|
24
24
|
end
|
25
25
|
|
26
|
+
def source
|
27
|
+
return '' unless @irs
|
28
|
+
line = nil
|
29
|
+
@irs.inject(''){|src, ir|
|
30
|
+
insn = ir.insn
|
31
|
+
next src if insn.line == line
|
32
|
+
next src if insn.source.empty?
|
33
|
+
line = insn.line
|
34
|
+
src.concat(insn.source).concat("\n")
|
35
|
+
}.chomp
|
36
|
+
end
|
37
|
+
|
26
38
|
def entry_point?
|
27
39
|
@entry_point
|
28
40
|
end
|
data/lib/cast_off/compile/cfg.rb
CHANGED
@@ -302,7 +302,7 @@ module CastOff::Compiler
|
|
302
302
|
bug() unless ir.src.unboxed? == ir.dst.unboxed?
|
303
303
|
end
|
304
304
|
ir.variables_without_result.each do |v|
|
305
|
-
ds = defs.
|
305
|
+
ds = defs.definition.select {|d| v == d.result_variable }
|
306
306
|
if v.unboxed?
|
307
307
|
bug() if ds.find{|d| not d.result_variable.unboxed? }
|
308
308
|
elsif v.boxed?
|
@@ -252,6 +252,7 @@ module CastOff
|
|
252
252
|
def load_base_configuration()
|
253
253
|
return nil unless File.exist?(@base_configuration_path)
|
254
254
|
conf_str = File.open(@base_configuration_path, 'rb:us-ascii').read()
|
255
|
+
conf_str.untaint # FIXME
|
255
256
|
Configuration.load(conf_str)
|
256
257
|
end
|
257
258
|
|
@@ -260,7 +261,7 @@ module CastOff
|
|
260
261
|
exist_conf_str = File.open("#{@dstdir}/#{@conffile}", 'rb:us-ascii').read()
|
261
262
|
# exist_conf_str が tainted であるため、Marshal.load で読み込んだ class も tainted になってしまう
|
262
263
|
# RDoc だと、それのせいで Insecure: can't modify array となる
|
263
|
-
|
264
|
+
exist_conf_str.untaint # FIXME
|
264
265
|
Configuration.load(exist_conf_str)
|
265
266
|
end
|
266
267
|
|
@@ -274,7 +275,7 @@ module CastOff
|
|
274
275
|
def load_annotation()
|
275
276
|
return nil unless File.exist?(@annotation_path)
|
276
277
|
ann_str = File.open(@annotation_path, 'rb:us-ascii').read()
|
277
|
-
ann_str.untaint
|
278
|
+
ann_str.untaint # FIXME
|
278
279
|
Marshal.load(ann_str)
|
279
280
|
end
|
280
281
|
|
@@ -244,8 +244,7 @@ o = Object
|
|
244
244
|
dst = (@variable_configuration[sym] ||= [])
|
245
245
|
(src + dst).each do |cw|
|
246
246
|
bug() unless cw.instance_of?(ClassWrapper)
|
247
|
-
bug() if cw.singleton?
|
248
|
-
bug() if cw.contain_class == SingletonClass
|
247
|
+
bug() if !cw.singleton? && cw.contain_class == SingletonClass
|
249
248
|
end
|
250
249
|
@variable_configuration[sym] = (dst | src)
|
251
250
|
end
|
@@ -253,16 +252,14 @@ o = Object
|
|
253
252
|
conf.return_value_configuration.each do |(cw0, src0)|
|
254
253
|
bug() unless src0.instance_of?(Hash)
|
255
254
|
bug() unless cw0.instance_of?(ClassWrapper)
|
256
|
-
bug() if cw0.singleton?
|
257
|
-
bug() if cw0.contain_class == SingletonClass
|
255
|
+
bug() if !cw0.singleton? && cw0.contain_class == SingletonClass
|
258
256
|
dst0 = (@return_value_configuration[cw0] ||= {})
|
259
257
|
src0.each do |(sym, src1)|
|
260
258
|
bug() unless src1.instance_of?(Array)
|
261
259
|
dst1 = (dst0[sym] ||= [])
|
262
260
|
(src1 + dst1).each do |cw1|
|
263
261
|
bug() unless cw1.instance_of?(ClassWrapper)
|
264
|
-
bug() if cw1.singleton?
|
265
|
-
bug() if cw1.contain_class == SingletonClass
|
262
|
+
bug() if !cw1.singleton? && cw1.contain_class == SingletonClass
|
266
263
|
end
|
267
264
|
dst0[sym] = (dst1 | src1)
|
268
265
|
end
|
@@ -278,13 +275,19 @@ o = Object
|
|
278
275
|
update_hash.each do |(k, v)|
|
279
276
|
bug() unless k.instance_of?(Symbol)
|
280
277
|
bug() unless v.instance_of?(Array)
|
281
|
-
next if v.include?(SingletonClass)
|
278
|
+
next if v.map{|a| a.first }.include?(SingletonClass)
|
282
279
|
# variable annotation
|
283
280
|
a0 = v
|
284
|
-
a0 = a0.map{|c|
|
281
|
+
a0 = a0.map{|(c, singleton_p)|
|
285
282
|
bug(c) unless c.is_a?(Class)
|
286
283
|
bug() unless c != SingletonClass
|
287
|
-
|
284
|
+
if singleton_p
|
285
|
+
wrapper = ClassWrapper.new(c, false)
|
286
|
+
bug() unless wrapper.singleton?
|
287
|
+
else
|
288
|
+
wrapper = ClassWrapper.new(c, true)
|
289
|
+
end
|
290
|
+
wrapper
|
288
291
|
}
|
289
292
|
a1 = @variable_configuration[k] || []
|
290
293
|
update_p = true unless (a0 - a1).empty?
|
@@ -296,27 +299,38 @@ o = Object
|
|
296
299
|
|
297
300
|
def update_return_value_configuration(update_hash)
|
298
301
|
update_p = false
|
299
|
-
update_hash.
|
300
|
-
|
301
|
-
bug() unless
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
302
|
+
bug() unless update_hash.size == 2
|
303
|
+
update_hash.each do |(sym, mtbl)|
|
304
|
+
bug() unless sym == :singleton_methods || sym == :instance_methods
|
305
|
+
bug() unless mtbl.is_a?(Hash)
|
306
|
+
mtbl.each do |(k, v)|
|
307
|
+
bug() unless k.instance_of?(Class)
|
308
|
+
bug() unless v.instance_of?(Hash)
|
309
|
+
next if k == SingletonClass
|
310
|
+
# return value annotation
|
311
|
+
h0 = v
|
312
|
+
k = ClassWrapper.new(k, sym == :instance_methods)
|
313
|
+
h1 = @return_value_configuration[k] || {}
|
314
|
+
h0.each do |(mid, klasses0)|
|
315
|
+
next if klasses0.include?(SingletonClass)
|
316
|
+
klasses0 = klasses0.map{|(c, singleton_p)|
|
317
|
+
bug(c) unless c.is_a?(Class)
|
318
|
+
bug() unless c != SingletonClass
|
319
|
+
if singleton_p
|
320
|
+
wrapper = ClassWrapper.new(c, false)
|
321
|
+
bug() unless wrapper.singleton?
|
322
|
+
else
|
323
|
+
wrapper = ClassWrapper.new(c, true)
|
324
|
+
end
|
325
|
+
wrapper
|
326
|
+
}
|
327
|
+
klasses1 = h1[mid] || []
|
328
|
+
update_p = true unless (klasses0 - klasses1).empty?
|
329
|
+
klasses1 |= klasses0
|
330
|
+
h1[mid] = klasses1
|
331
|
+
end
|
332
|
+
@return_value_configuration[k] = h1
|
318
333
|
end
|
319
|
-
@return_value_configuration[k] = h1
|
320
334
|
end
|
321
335
|
update_p
|
322
336
|
end
|