bitescript 0.0.8 → 0.0.9
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +20 -0
- data/bitescript.gemspec +2 -2
- data/examples/fib.bs +20 -11
- data/examples/hello_world_macro.bs +7 -3
- data/examples/invokedynamic.bs +41 -0
- data/lib/bitescript.rb +3 -1
- data/lib/bitescript/asm.rb +8 -1
- data/lib/bitescript/builder.rb +1 -1
- data/lib/bitescript/bytecode.rb +54 -30
- data/test/test_bitescript.rb +8 -1
- metadata +3 -5
- data/examples/hello_world.class +0 -0
- data/nbproject/private/private.xml +0 -4
- data/nbproject/private/rake-d.txt +0 -2
data/History.txt
CHANGED
@@ -1,3 +1,23 @@
|
|
1
|
+
=== 0.0.9 / 2011-07-11
|
2
|
+
|
3
|
+
62a10d2 Update time format in gemspec
|
4
|
+
0d37ff9 Update hello_world_macro.bs example
|
5
|
+
3b24a1d Fix TypeError in bytecode.rb with --1.9
|
6
|
+
96dfbef Merge pull request #5 from baroquebobcat/fixing_test_method_insns_deltas
|
7
|
+
2b06833 Merge pull request #4 from baroquebobcat/fix_bytecode_version_test
|
8
|
+
501863d Merge pull request #6 from baroquebobcat/continue_to_work_when_asm_4.0_is_unavailable
|
9
|
+
a4b82aa only define mh_* if those opcodes are present
|
10
|
+
a556514 rescue + note around MethodHandle java import
|
11
|
+
11472c7 copy and paste of sig_stack_net had a small bug. This fixes it
|
12
|
+
d5a7e4d default is now dynamic depending on java version used
|
13
|
+
7beeb5a Ask ASM to compute frames too.
|
14
|
+
a9e1c61 Fix ASM package juggling for proper pre-1.6.0.RC2 package.
|
15
|
+
c840664 Get invokedynamic support working.
|
16
|
+
801bea4 Add args length checking to fib script, since it's always confusing to get ArrayIndexOutOfBounds.
|
17
|
+
b537df1 Replace Label#set! calls with forward-referencing symbols.
|
18
|
+
3bf6f98 Replace confusing load_time macro with current_time
|
19
|
+
130bda6 Add .redcar to .gitignore.
|
20
|
+
|
1
21
|
=== 0.0.8 / 2011-03-05
|
2
22
|
|
3
23
|
* Support parsing of generic signatures
|
data/bitescript.gemspec
CHANGED
@@ -2,9 +2,9 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = %q{bitescript}
|
5
|
-
s.version = "0.0.
|
5
|
+
s.version = "0.0.9"
|
6
6
|
s.authors = ["Charles Oliver Nutter", "Ryan Brown"]
|
7
|
-
s.date = Time.now.strftime('
|
7
|
+
s.date = Time.now.strftime('%Y-%m-%d')
|
8
8
|
s.description = %q{BiteScript is a Ruby DSL for generating Java bytecode and classes.}
|
9
9
|
s.email = ["headius@headius.com", "ribrdb@gmail.com"]
|
10
10
|
s.executables = ["bite", "bitec"]
|
data/examples/fib.bs
CHANGED
@@ -7,23 +7,34 @@ macro :lprintln do |i|
|
|
7
7
|
invokevirtual java.io.PrintStream, "println", [void, long]
|
8
8
|
end
|
9
9
|
|
10
|
-
macro :
|
10
|
+
macro :current_time do
|
11
11
|
invokestatic System, "currentTimeMillis", long
|
12
12
|
end
|
13
13
|
|
14
14
|
macro :start_timing do |i|
|
15
|
-
|
15
|
+
current_time
|
16
16
|
lstore i
|
17
17
|
end
|
18
18
|
|
19
19
|
macro :end_timing do |i|
|
20
|
-
|
20
|
+
current_time
|
21
21
|
lload i
|
22
22
|
lsub
|
23
23
|
lstore i
|
24
24
|
end
|
25
25
|
|
26
|
-
macro :
|
26
|
+
macro :load_iters do
|
27
|
+
# check args length
|
28
|
+
aload 0
|
29
|
+
arraylength
|
30
|
+
ifne :ok_iters
|
31
|
+
ldc "Usage: bite fib.bs <iters>"
|
32
|
+
aprintln
|
33
|
+
ldc 1
|
34
|
+
invokestatic System, 'exit', [void, int]
|
35
|
+
|
36
|
+
# args length ok
|
37
|
+
label :ok_iters
|
27
38
|
aload 0
|
28
39
|
ldc 0
|
29
40
|
aaload # number of times
|
@@ -31,7 +42,7 @@ macro :load_times do
|
|
31
42
|
end
|
32
43
|
|
33
44
|
main do
|
34
|
-
|
45
|
+
load_iters
|
35
46
|
istore 1
|
36
47
|
|
37
48
|
ldc "Raw bytecode fib(45) performance:"
|
@@ -39,8 +50,7 @@ main do
|
|
39
50
|
|
40
51
|
label :top
|
41
52
|
iload 1
|
42
|
-
done
|
43
|
-
ifeq done
|
53
|
+
ifeq :done
|
44
54
|
iinc 1, -1
|
45
55
|
|
46
56
|
start_timing 2
|
@@ -54,18 +64,17 @@ main do
|
|
54
64
|
lprintln 2
|
55
65
|
goto :top
|
56
66
|
|
57
|
-
done
|
67
|
+
label :done
|
58
68
|
returnvoid
|
59
69
|
end
|
60
70
|
|
61
71
|
public_static_method "fib", [], int, int do
|
62
72
|
iload 0
|
63
73
|
ldc 2
|
64
|
-
recurse
|
65
|
-
if_icmpge recurse
|
74
|
+
if_icmpge :recurse
|
66
75
|
iload 0
|
67
76
|
ireturn
|
68
|
-
recurse
|
77
|
+
label :recurse
|
69
78
|
iload 0
|
70
79
|
ldc 1
|
71
80
|
isub
|
@@ -4,20 +4,24 @@ import java.io.PrintStream
|
|
4
4
|
macro :aprintln do
|
5
5
|
getstatic System, :out, PrintStream
|
6
6
|
swap
|
7
|
-
invokevirtual PrintStream, println, [
|
7
|
+
invokevirtual PrintStream, "println", [void, object]
|
8
8
|
end
|
9
9
|
|
10
10
|
macro :aprint do
|
11
11
|
getstatic System, :out, PrintStream
|
12
12
|
swap
|
13
|
-
invokevirtual PrintStream, print, [
|
13
|
+
invokevirtual PrintStream, "print", [void, object]
|
14
14
|
end
|
15
15
|
|
16
16
|
main do
|
17
17
|
ldc "Hello, "
|
18
18
|
aprint
|
19
|
+
|
20
|
+
# Get first argument from command line
|
19
21
|
aload 0
|
20
|
-
|
22
|
+
ldc 0
|
23
|
+
aaload
|
24
|
+
|
21
25
|
aprintln
|
22
26
|
returnvoid
|
23
27
|
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
import java.lang.invoke.MethodHandle
|
2
|
+
import java.lang.invoke.MethodType
|
3
|
+
import java.lang.invoke.CallSite
|
4
|
+
import java.lang.invoke.ConstantCallSite
|
5
|
+
import java.lang.invoke.MethodHandles::Lookup
|
6
|
+
JClass = java.lang.Class
|
7
|
+
|
8
|
+
# Our main method, which does one invokedynamic
|
9
|
+
main do
|
10
|
+
# handle for our bootstrap, which binds invokedynamic to a CallSite
|
11
|
+
bootstrap = mh_invokestatic this, 'bootstrap', CallSite, Lookup, string, MethodType
|
12
|
+
|
13
|
+
ldc 'Hello, invokedynamic!'
|
14
|
+
invokedynamic 'print', [void, string], bootstrap
|
15
|
+
returnvoid
|
16
|
+
end
|
17
|
+
|
18
|
+
# The method we want to invoke, prints given string
|
19
|
+
public_static_method :print, [], void, string do
|
20
|
+
aload 0
|
21
|
+
aprintln
|
22
|
+
returnvoid
|
23
|
+
end
|
24
|
+
|
25
|
+
# The bootstrap method, which binds our dynamic call
|
26
|
+
public_static_method :bootstrap, [], CallSite, Lookup, string, MethodType do
|
27
|
+
# Constant since we bind just once directly
|
28
|
+
new ConstantCallSite
|
29
|
+
dup
|
30
|
+
|
31
|
+
# Locate the method indicated by name + type on current class
|
32
|
+
aload 0 # Lookup
|
33
|
+
ldc this # this class
|
34
|
+
aload 1 # String
|
35
|
+
aload 2 # MethodType
|
36
|
+
invokevirtual Lookup, 'findStatic', [MethodHandle, JClass, string, MethodType]
|
37
|
+
|
38
|
+
# finish constructing call site and return
|
39
|
+
invokespecial ConstantCallSite, '<init>', [void, MethodHandle]
|
40
|
+
areturn
|
41
|
+
end
|
data/lib/bitescript.rb
CHANGED
@@ -15,6 +15,8 @@ module BiteScript
|
|
15
15
|
class << self
|
16
16
|
attr_accessor :bytecode_version
|
17
17
|
|
18
|
-
|
18
|
+
# Default to JVM version we're running on
|
19
|
+
spec_version = ENV_JAVA['java.specification.version']
|
20
|
+
BiteScript.bytecode_version = BiteScript.const_get("JAVA#{spec_version.gsub('.', '_')}")
|
19
21
|
end
|
20
22
|
end
|
data/lib/bitescript/asm.rb
CHANGED
@@ -17,7 +17,7 @@ module BiteScript
|
|
17
17
|
# no error, proceed with mangled name
|
18
18
|
asm_package = Java::org.jruby.org.objectweb.asm
|
19
19
|
java_import asm_package.Opcodes
|
20
|
-
rescue
|
20
|
+
rescue Exception
|
21
21
|
# fall back on standard names
|
22
22
|
asm_package = org.objectweb.asm
|
23
23
|
java_import asm_package.Opcodes
|
@@ -35,5 +35,12 @@ module BiteScript
|
|
35
35
|
java_import asm_package.signature.SignatureReader
|
36
36
|
java_import asm_package.signature.SignatureVisitor
|
37
37
|
java_import asm_package.signature.SignatureWriter
|
38
|
+
|
39
|
+
# MethodHandle was introduced in ASM 4.0, and is only available to
|
40
|
+
# JRuby > 1.6.1
|
41
|
+
begin
|
42
|
+
java_import asm_package.MethodHandle
|
43
|
+
rescue
|
44
|
+
end
|
38
45
|
end
|
39
46
|
end
|
data/lib/bitescript/builder.rb
CHANGED
@@ -232,7 +232,7 @@ module BiteScript
|
|
232
232
|
flags = Opcodes::ACC_INTERFACE | Opcodes::ACC_ABSTRACT
|
233
233
|
end
|
234
234
|
|
235
|
-
@class_writer = ClassWriter.new(ClassWriter::COMPUTE_MAXS)
|
235
|
+
@class_writer = ClassWriter.new(ClassWriter::COMPUTE_FRAMES | ClassWriter::COMPUTE_MAXS)
|
236
236
|
|
237
237
|
interface_paths = []
|
238
238
|
(@interfaces).each {|interface| interface_paths << path(interface)}
|
data/lib/bitescript/bytecode.rb
CHANGED
@@ -39,7 +39,7 @@ module BiteScript
|
|
39
39
|
|
40
40
|
OpcodeInstructions = {}
|
41
41
|
|
42
|
-
Opcodes.constants.each do |const_name|
|
42
|
+
Opcodes.constants.map(&:to_s).each do |const_name|
|
43
43
|
const_down = const_name.downcase
|
44
44
|
|
45
45
|
case const_name
|
@@ -78,7 +78,7 @@ module BiteScript
|
|
78
78
|
size = push_int value
|
79
79
|
when Float
|
80
80
|
ldc_double(value)
|
81
|
-
when Module
|
81
|
+
when Module, ClassBuilder
|
82
82
|
ldc_class(value)
|
83
83
|
else
|
84
84
|
method_visitor.visit_ldc_insn(value)
|
@@ -98,40 +98,24 @@ module BiteScript
|
|
98
98
|
", b, __FILE__, line
|
99
99
|
OpcodeInstructions[const_name] = const_down
|
100
100
|
|
101
|
-
when "INVOKESTATIC", "INVOKEVIRTUAL", "INVOKEINTERFACE", "INVOKESPECIAL"
|
101
|
+
when "INVOKESTATIC", "INVOKEVIRTUAL", "INVOKEINTERFACE", "INVOKESPECIAL"
|
102
102
|
# method instructions
|
103
103
|
line = __LINE__; eval "
|
104
104
|
def #{const_down}(type, name, call_sig)
|
105
105
|
method_visitor.visit_method_insn(Opcodes::#{const_name}, path(type), name.to_s, sig(*call_sig))
|
106
106
|
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
this_subtracted = #{const_name == 'INVOKESTATIC' ? 0 : 1}
|
119
|
-
|
120
|
-
args_subtracted = 0
|
121
|
-
[*call_sig][1..-1].each do |param|
|
122
|
-
case param
|
123
|
-
when nil, Java::void, java.lang.Void
|
124
|
-
args_subtracted += 0
|
125
|
-
when Java::boolean, Java::short, Java::char, Java::int, Java::float
|
126
|
-
args_subtracted += 1
|
127
|
-
when Java::long, Java::double
|
128
|
-
args_subtracted += 2
|
129
|
-
else
|
130
|
-
args_subtracted += 1
|
131
|
-
end
|
132
|
-
end
|
107
|
+
sig_stack_net(call_sig, #{const_name == 'INVOKESTATIC' ? 0 : 1})
|
108
|
+
end
|
109
|
+
", b, __FILE__, line
|
110
|
+
OpcodeInstructions[const_name] = const_down
|
111
|
+
|
112
|
+
when "INVOKEDYNAMIC"
|
113
|
+
# invokedynamic instruction
|
114
|
+
line = __LINE__; eval "
|
115
|
+
def #{const_down}(name, call_sig, handle, *args)
|
116
|
+
method_visitor.visit_invoke_dynamic_insn(name.to_s, sig(*call_sig), handle, args.to_java)
|
133
117
|
|
134
|
-
|
118
|
+
sig_stack_net(call_sig, 0)
|
135
119
|
end
|
136
120
|
", b, __FILE__, line
|
137
121
|
OpcodeInstructions[const_name] = const_down
|
@@ -298,6 +282,15 @@ module BiteScript
|
|
298
282
|
end
|
299
283
|
OpcodeInstructions['TABLESWITCH'] = 'tableswitch'
|
300
284
|
|
285
|
+
when "MH_INVOKESPECIAL", "MH_INVOKESTATIC", "MH_PUTSTATIC", "MH_GETSTATIC", "MH_PUTFIELD",
|
286
|
+
"MH_GETFIELD", "MH_INVOKEVIRTUAL", "MH_INVOKEINTERFACE",
|
287
|
+
"MH_NEWINVOKESPECIAL"
|
288
|
+
line = __LINE__; eval "
|
289
|
+
def #{const_down}(cls, name, *call_sig)
|
290
|
+
MethodHandle.new(Opcodes::#{const_name}, path(cls), name, sig(*call_sig))
|
291
|
+
end
|
292
|
+
", b, __FILE__, line
|
293
|
+
OpcodeInstructions[const_name] = const_down
|
301
294
|
when "F_FULL", "ACC_ENUM", "ACC_SYNTHETIC", "ACC_INTERFACE", "ACC_PUBLIC",
|
302
295
|
"ACC_PRIVATE", "ACC_PROTECTED", "ACC_DEPRECATED", "ACC_BRIDGE",
|
303
296
|
"ACC_VARARGS", "ACC_SUPER", "F_CHOP", "F_APPEND", "FLOAT", "F_SAME",
|
@@ -307,6 +300,7 @@ module BiteScript
|
|
307
300
|
"F_SAME1", "ACC_NATIVE", "F_NEW", "T_CHAR", "T_INT", "ACC_VOLATILE",
|
308
301
|
"V1_6", "V1_5", "V1_4", "V1_3", "V1_2", "V1_1", "UNINITIALIZED_THIS",
|
309
302
|
"TOP", "T_SHORT", "INVOKEDYNAMIC_OWNER", "V1_7"
|
303
|
+
|
310
304
|
# non-instructions
|
311
305
|
|
312
306
|
else
|
@@ -429,6 +423,36 @@ module BiteScript
|
|
429
423
|
else
|
430
424
|
ldc_long(num)
|
431
425
|
end
|
426
|
+
end
|
427
|
+
|
428
|
+
def sig_stack_net(call_sig, this_subtracted)
|
429
|
+
case call_sig[0]
|
430
|
+
when nil, Java::void, java.lang.Void
|
431
|
+
added = 0
|
432
|
+
when Java::boolean, Java::short, Java::char, Java::int, Java::float
|
433
|
+
added = 1
|
434
|
+
when Java::long, Java::double
|
435
|
+
added = 2
|
436
|
+
else
|
437
|
+
added = 1
|
438
|
+
end
|
439
|
+
|
440
|
+
args_subtracted = 0
|
441
|
+
[*call_sig][1..-1].each do |param|
|
442
|
+
case param
|
443
|
+
when nil, Java::void, java.lang.Void
|
444
|
+
args_subtracted += 0
|
445
|
+
when Java::boolean, Java::short, Java::char, Java::int, Java::float
|
446
|
+
args_subtracted += 1
|
447
|
+
when Java::long, Java::double
|
448
|
+
args_subtracted += 2
|
449
|
+
else
|
450
|
+
args_subtracted += 1
|
451
|
+
end
|
452
|
+
end
|
453
|
+
|
454
|
+
added - (this_subtracted + args_subtracted)
|
432
455
|
end
|
456
|
+
private :sig_stack_net
|
433
457
|
end
|
434
458
|
end
|
data/test/test_bitescript.rb
CHANGED
@@ -4,8 +4,15 @@ require 'test/unit'
|
|
4
4
|
require 'bitescript'
|
5
5
|
|
6
6
|
class TestBitescript < Test::Unit::TestCase
|
7
|
+
def test_bytecode_defaults_to_current_version
|
8
|
+
spec_version = ENV_JAVA['java.specification.version']
|
9
|
+
expected_version = BiteScript.const_get("JAVA#{spec_version.gsub('.', '_')}")
|
10
|
+
|
11
|
+
assert_equal expected_version, BiteScript.bytecode_version
|
12
|
+
end
|
13
|
+
|
7
14
|
def test_bytecode_version
|
8
|
-
|
15
|
+
|
9
16
|
[BiteScript::JAVA1_4, BiteScript::JAVA1_5, BiteScript::JAVA1_6].each do |ver|
|
10
17
|
BiteScript.bytecode_version = ver
|
11
18
|
assert_equal(ver, BiteScript.bytecode_version)
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: bitescript
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.0.
|
5
|
+
version: 0.0.9
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Charles Oliver Nutter
|
@@ -11,7 +11,7 @@ autorequire:
|
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
13
|
|
14
|
-
date: 2011-
|
14
|
+
date: 2011-07-11 00:00:00 -05:00
|
15
15
|
default_executable:
|
16
16
|
dependencies: []
|
17
17
|
|
@@ -34,10 +34,10 @@ files:
|
|
34
34
|
- bin/bitep
|
35
35
|
- examples/fib.bs
|
36
36
|
- examples/hello_world.bs
|
37
|
-
- examples/hello_world.class
|
38
37
|
- examples/hello_world_macro.bs
|
39
38
|
- examples/indy.bs
|
40
39
|
- examples/instanceof.bs
|
40
|
+
- examples/invokedynamic.bs
|
41
41
|
- examples/mixed_bag.rb
|
42
42
|
- examples/simple_loop.rb
|
43
43
|
- examples/using_ruby.bs
|
@@ -49,8 +49,6 @@ files:
|
|
49
49
|
- lib/bitescript/signature.rb
|
50
50
|
- nbproject/project.properties
|
51
51
|
- nbproject/project.xml
|
52
|
-
- nbproject/private/private.xml
|
53
|
-
- nbproject/private/rake-d.txt
|
54
52
|
- test/test_bitescript.rb
|
55
53
|
- test/test_builder.rb
|
56
54
|
- test/test_bytecode.rb
|
data/examples/hello_world.class
DELETED
Binary file
|