JVM language development

开发基于JVM的声明式编程语言

PreRequisites

antlr4
asm-plugin: https://github.com/kamiiel/asm-intellij-plugin/releases
Intellij IDEA Install plugin from disk

排错记录

编译过程没问题,执行时报错:
Exception in thread “main” java.lang.ClassFormatError: Field “out” in class test has illegal signature “Ljava/io/PrintStream”

错误原因:在产生字节码的过程中,调用PrintStream忘记加分号

1
2
methodVisitor.visitFieldInsn(GETSTATIC, "java/lang/System", "out",
"Ljava/io/PrintStream");

应为:

1
2
methodVisitor.visitFieldInsn(GETSTATIC, "java/lang/System", "out",
"Ljava/io/PrintStream;");

JVM结构

1.类加载器
2.运行时数据区
3.执行引擎
4.本地方法库

double和long需要占据2个slot,其余基本类型和引用都是1个slot。
slot可以重复利用

垃圾回收(Garbage Collection)

查看Java进程使用的垃圾回收器:
jps-jinfo.png

查看默认垃圾回收器
default_gc.png

JVM字节码

解析一个接口

接口定义:

1
2
3
4
package edu.ustb.spesc.element;

public interface InterfaceLook {
}

javap -v 结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Classfile /home/wsd/STEM/Experiments/SPESC-Java-Compiler/compiler/target/test-classes/edu/ustb/spesc/element/InterfaceLook.class
Last modified Apr 1, 2021; size 130 bytes
MD5 checksum 849d09ca95f1ed5733cca527dce9ed9c
Compiled from "InterfaceLook.java"
public interface edu.ustb.spesc.element.InterfaceLook
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT
Constant pool:
#1 = Class #5 // edu/ustb/spesc/element/InterfaceLook
#2 = Class #6 // java/lang/Object
#3 = Utf8 SourceFile
#4 = Utf8 InterfaceLook.java
#5 = Utf8 edu/ustb/spesc/element/InterfaceLook
#6 = Utf8 java/lang/Object
{
}
SourceFile: "InterfaceLook.java"

一些操作码助记符:除了比较容易记住的 i=int, l=long, s=short, b=byte, c=char, f=float, d=double,
还有 z=boolean, a=reference

DUP

这是一条直接操作操作数栈的指令,表示复制操作数栈栈顶的值,并插入到栈顶
比如最常见的:

1
2
3
Object create() {
return new Object();
}

编译后字节码如下:

1
2
3
4
5
Method java.lang.Object create()
0 new #1 // Class java.lang.Object
3 dup
4 invokespecial #4 // Method java.lang.Object.<init>()V
7 areturn

第0行通过new创建了一个Object类型的对象,并将其引用压入栈顶
第3行复制栈顶的引用一份
第4行调用invokespecial为Object的构造函数,这里会消耗一个引用
所以第3行需要复制一份,不然调用invokespecial后会导致无法返回实例引用

解析一个类

类定义:

1
2
3
4
package edu.ustb.spesc;

public class bytecodeTest {
}

javap -v 结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
Classfile /home/wsd/STEM/Experiments/SPESC-Java-Compiler/compiler/target/test-classes/edu/ustb/spesc/bytecodeTest.class
Last modified Apr 1, 2021; size 291 bytes
MD5 checksum 58439c875ed1b27cf7a5a68507efbf13
Compiled from "bytecodeTest.java"
public class edu.ustb.spesc.bytecodeTest
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Methodref #3.#13 // java/lang/Object."<init>":()V
#2 = Class #14 // edu/ustb/spesc/bytecodeTest
#3 = Class #15 // java/lang/Object
#4 = Utf8 <init>
#5 = Utf8 ()V
#6 = Utf8 Code
#7 = Utf8 LineNumberTable
#8 = Utf8 LocalVariableTable
#9 = Utf8 this
#10 = Utf8 Ledu/ustb/spesc/bytecodeTest;
#11 = Utf8 SourceFile
#12 = Utf8 bytecodeTest.java
#13 = NameAndType #4:#5 // "<init>":()V
#14 = Utf8 edu/ustb/spesc/bytecodeTest
#15 = Utf8 java/lang/Object
{
public edu.ustb.spesc.bytecodeTest();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
LineNumberTable:
line 3: 0
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this Ledu/ustb/spesc/bytecodeTest;
}
SourceFile: "bytecodeTest.java"

由于JVM解析Java文件是按照行来解析的,一行Java代码可能对应多行字节码,所以设置 LineNumberTable 这个属性就是表示java文件的某行与字节码某行的对应关系。
比如上面的显示 line 3: 0 就表示bytecodeTest.java的第3行对应解析到jvm字节码的第0行即 aload_0
Slot是字节码中的存储单位,1个Slot大小为32bit(4 bytes)

使用ASM操作字节码

methodVisitor.visitMethodInsn五个参数

  1. INVOKE
  2. 调用函数的内部全类名
  3. 函数名
  4. 返回类型
  5. 是否接口调用

一些与标准文档的出入之处

3.1 .用作结构体访问的操作符,用做结束符会冲突
6.3 当事人描述中的 field 不止属于当事人,还可以作为合约的全局变量
另外,在filed定义中 attribute : (constant | type)
实际匹配过程应该是先匹配type,再匹配constant。否则如果出现类似 name : String 会将其匹配到constant
所以程序中使用 name : (type | value) 的方式匹配
name : IDENTIFIER
type : BOOLEAN (‘[‘ ‘]’)
| INTEGER (‘[‘ ‘]’)
;
value : NUMBER | STRING ;
其中,(‘[‘ ‘]’)*用于匹配数组

6.8 有关系符号,但缺少关系表达式
关系表达式属于谓词,可返回Yes,No,Unknown
关系表达式中可再分所属关系和比较关系,所属关系的关键词是belongsTo,比较关系的关键词有 > >= < <= == !=
所以在规则中添加了relationalExpression

实验探究 invokespecial 和 invokevirtual 的区别

1
2
3
4
5
public class LibSayHello {
public void sayHello() {
System.out.println("Hello");
}
}

bytecode如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
public sayHello()V
L0
LINENUMBER 5 L0
GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
LDC "Hello"
INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V
L1
LINENUMBER 6 L1
RETURN
L2
LOCALVARIABLE this Ledu/ustb/spesc/LibSayHello; L0 L2 0
MAXSTACK = 2
MAXLOCALS = 1
1
2
3
4
5
6
public class MainTest {
public static void main(String[] args) {
LibSayHello testObj = new LibSayHello();
testObj.sayHello();
}
}

bytecode如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public static main([Ljava/lang/String;)V
L0
LINENUMBER 5 L0
NEW edu/ustb/spesc/LibSayHello
DUP
INVOKESPECIAL edu/ustb/spesc/LibSayHello.<init> ()V
ASTORE 1
L1
LINENUMBER 6 L1
ALOAD 1
INVOKEVIRTUAL edu/ustb/spesc/LibSayHello.sayHello ()V
L2
LINENUMBER 7 L2
RETURN
L3
LOCALVARIABLE args [Ljava/lang/String; L0 L3 0
LOCALVARIABLE testObj Ledu/ustb/spesc/LibSayHello; L1 L3 1
MAXSTACK = 2
MAXLOCALS = 2

可以看到,init构造函数使用的是INVOKESPECIAL,普通方法sayHello使用的是INVOKEVIRTUAL

再来进行一层抽象,将LibHello写成接口的形式,类LibHelloImpl用于实现,此时测试main函数的bytecode变为如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public static main([Ljava/lang/String;)V
L0
LINENUMBER 5 L0
NEW edu/ustb/spesc/LibHelloImpl
DUP
INVOKESPECIAL edu/ustb/spesc/LibHelloImpl.<init> ()V
ASTORE 1
L1
LINENUMBER 6 L1
ALOAD 1
INVOKEINTERFACE edu/ustb/spesc/LibHello.sayHello ()V (itf)
L2
LINENUMBER 7 L2
RETURN
L3
LOCALVARIABLE args [Ljava/lang/String; L0 L3 0
LOCALVARIABLE testObj Ledu/ustb/spesc/LibHello; L1 L3 1
MAXSTACK = 2
MAXLOCALS = 2

可以看到对sayHello的调用由原来的invokespecial变成了invokeinterface

假如LibHello是abstract类呢?
实验后可以发现,不管LibHelloImpl是否重写hello方法,对sayHello的调用都变回了invokevirtual
并且只要LibHello不变,即使改变了LibHelloImpl,也不会触发对于MainTest的字节码重新编译

FunctionalInterface底层实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
       ││  [Verified Entry Point]
1.54% ↘│ 0x00007f6db5299a80: mov %eax,-0x14000(%rsp)
2.23% │ 0x00007f6db5299a87: push %rbp
0.80% │ 0x00007f6db5299a88: sub $0x30,%rsp ;*aload_1
│ ; - cn.wsd.benchmark.functionalinterface.TestMain::lambda$dynamicMethodCall$0@0 (line 30)
2.00% ││ 0x00007f6db5299a8c: mov 0xc(%rdx),%eax ;*arraylength
││ ; - cn.wsd.benchmark.functionalinterface.TestMain::lambda$dynamicMethodCall$0@1 (line 30)
││ ; implicit exception: dispatches to 0x00007f6db5299aa0
0.94% ││ 0x00007f6db5299a8f: mov 0xc(%rsi),%esi ;*getfield offset
││ ; - cn.wsd.benchmark.functionalinterface.TestMain::lambda$dynamicMethodCall$0@3 (line 30)
0.78% ││ 0x00007f6db5299a92: add %esi,%eax
0.85% ││ 0x00007f6db5299a94: add $0x30,%rsp
1.21% ││ 0x00007f6db5299a98: pop %rbp
0.95% ││ 0x00007f6db5299a99: test %eax,0x177c7661(%rip) # 0x00007f6dcca61100
││ ; {poll_return}
0.74% ││╭ 0x00007f6db5299a9f: retq
│││ 0x00007f6db5299aa0: callq 0x00007f6db5100a80 ; OopMap{rsi=Oop off=69}
│││ ;*arraylength
│││ ; - cn.wsd.benchmark.functionalinterface.TestMain::lambda$dynamicMethodCall$0@1 (line 30)
│││ ; {runtime_call}
│ │ 0x00007f6db5299aa5: nop
│ │ 0x00007f6db5299aa6: nop

先看下总得分:

1
2
3
4
5
Benchmark                                       Mode  Cnt  Score   Error  Units
FunctionalInterfaceTest.dynamicMethodCall avgt 5 7.902 ± 0.807 ns/op
FunctionalInterfaceTest.dynamicMethodCall:·asm avgt NaN ---
FunctionalInterfaceTest.normalMethodCall avgt 5 4.139 ± 0.081 ns/op
FunctionalInterfaceTest.normalMethodCall:·asm avgt NaN ---

函数式调用方式较差,但没有数量级上的差距。这比较符合预期。

normalMethod的汇编实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
c2, level 4, cn.wsd.benchmark.functionalinterface.CounterImpl::work, version 2, compile id 6875 

# parm0: rdx:rdx = &apos;[B&apos;
# [sp+0x20] (sp of caller)
0x00007fef9c3c9320: mov 0x8(%rsi),%r10d
0x00007fef9c3c9324: movabs $0x800000000,%r12
0x00007fef9c3c932e: add %r12,%r10
0x00007fef9c3c9331: xor %r12,%r12
0x00007fef9c3c9334: cmp %r10,%rax
0x00007fef9c3c9337: jne 0x00007fef9464b080 ; {runtime_call ic_miss_stub}
0x00007fef9c3c933d: data16 xchg %ax,%ax
[Verified Entry Point]
1.51% 0x00007fef9c3c9340: mov %eax,-0x14000(%rsp)
5.94% 0x00007fef9c3c9347: push %rbp
0.04% 0x00007fef9c3c9348: sub $0x10,%rsp ;*synchronization entry
; - cn.wsd.benchmark.functionalinterface.CounterImpl::work@-1 (line 17)
1.49% ╭ 0x00007fef9c3c934c: mov 0xc(%rdx),%eax ; implicit exception: dispatches to 0x00007fef9c3c9362
5.46% │ 0x00007fef9c3c934f: add 0xc(%rsi),%eax ;*iadd {reexecute=0 rethrow=0 return_oop=0}
│ ; - cn.wsd.benchmark.functionalinterface.CounterImpl::work@6 (line 17)
0.30% │ 0x00007fef9c3c9352: add $0x10,%rsp
1.39% │ 0x00007fef9c3c9356: pop %rbp
0.15% │ 0x00007fef9c3c9357: mov 0x108(%r15),%r10
5.24% │ 0x00007fef9c3c935e: test %eax,(%r10) ; {poll_return}
0.28% │ 0x00007fef9c3c9361: retq
↘ 0x00007fef9c3c9362: mov $0xfffffff6,%esi
0x00007fef9c3c9367: callq 0x00007fef94649e00 ; ImmutableOopMap{}
;*arraylength {reexecute=0 rethrow=0 return_oop=0}
; - cn.wsd.benchmark.functionalinterface.CounterImpl::work@1 (line 17)
; {runtime_call UncommonTrapBlob}
0x00007fef9c3c936c: hlt

调用它的地方:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
c2, level 4, cn.wsd.benchmark.functionalinterface.jmh_generated.FunctionalInterfaceTest_normalMethodCall_jmhTest::normalMethodCall_avgt_jmhStub, version 4, compile id 6989 

0x00007fef9c3d41e4: mov 0x40(%rsp),%r10
0x00007fef9c3d41e9: movzbl 0x94(%r10),%r11d ;*getfield isDone {reexecute=0 rethrow=0 return_oop=0}
; - cn.wsd.benchmark.functionalinterface.jmh_generated.FunctionalInterfaceTest_normalMethodCall_jmhTest::normalMethodCall_avgt_jmhStub@30 (line 192)
; implicit exception: dispatches to 0x00007fef9c3d4318
0x00007fef9c3d41f1: mov $0x1,%ebp
0x00007fef9c3d41f6: test %r11d,%r11d
╭ 0x00007fef9c3d41f9: jne 0x00007fef9c3d4258 ;*ifeq {reexecute=0 rethrow=0 return_oop=0}
│ ; - cn.wsd.benchmark.functionalinterface.jmh_generated.FunctionalInterfaceTest_normalMethodCall_jmhTest::normalMethodCall_avgt_jmhStub@33 (line 192)
│ 0x00007fef9c3d41fb: nopl 0x0(%rax,%rax,1) ;*aload_1 {reexecute=0 rethrow=0 return_oop=0}
│ ; - cn.wsd.benchmark.functionalinterface.jmh_generated.FunctionalInterfaceTest_normalMethodCall_jmhTest::normalMethodCall_avgt_jmhStub@36 (line 193)
0.31% │↗ 0x00007fef9c3d4200: mov 0x50(%rsp),%r10
1.44% ││ 0x00007fef9c3d4205: mov 0x14(%r10),%r11d ;*getfield coder {reexecute=0 rethrow=0 return_oop=0}
││ ; - cn.wsd.benchmark.functionalinterface.FunctionalInterfaceTest::normalMethodCall@1 (line 29)
││ ; - cn.wsd.benchmark.functionalinterface.jmh_generated.FunctionalInterfaceTest_normalMethodCall_jmhTest::normalMethodCall_avgt_jmhStub@17 (line 190)
0.17% ││ 0x00007fef9c3d4209: mov 0x10(%r10),%r10d ;*getfield inBytes {reexecute=0 rethrow=0 return_oop=0}
││ ; - cn.wsd.benchmark.functionalinterface.FunctionalInterfaceTest::normalMethodCall@5 (line 29)
││ ; - cn.wsd.benchmark.functionalinterface.jmh_generated.FunctionalInterfaceTest_normalMethodCall_jmhTest::normalMethodCall_avgt_jmhStub@17 (line 190)
5.39% ││ 0x00007fef9c3d420d: mov 0x8(%r12,%r11,8),%r9d ; implicit exception: dispatches to 0x00007fef9c3d42d4
7.70% ││ 0x00007fef9c3d4212: cmp $0xfa768,%r9d ; {metadata(&apos;cn/wsd/benchmark/functionalinterface/CounterImpl&apos;)}
││ 0x00007fef9c3d4219: jne 0x00007fef9c3d4291
5.56% ││ 0x00007fef9c3d421b: lea (%r12,%r11,8),%rsi ;*invokeinterface work {reexecute=0 rethrow=0 return_oop=0}
││ ; - cn.wsd.benchmark.functionalinterface.FunctionalInterfaceTest::normalMethodCall@8 (line 29)
││ ; - cn.wsd.benchmark.functionalinterface.jmh_generated.FunctionalInterfaceTest_normalMethodCall_jmhTest::normalMethodCall_avgt_jmhStub@17 (line 190)
0.05% ││ 0x00007fef9c3d421f: mov %r10,%rdx
1.49% ││ 0x00007fef9c3d4222: shl $0x3,%rdx ;*getfield inBytes {reexecute=0 rethrow=0 return_oop=0}
││ ; - cn.wsd.benchmark.functionalinterface.FunctionalInterfaceTest::normalMethodCall@5 (line 29)
││ ; - cn.wsd.benchmark.functionalinterface.jmh_generated.FunctionalInterfaceTest_normalMethodCall_jmhTest::normalMethodCall_avgt_jmhStub@17 (line 190)
0.11% ││ 0x00007fef9c3d4226: nop
5.45% ││ 0x00007fef9c3d4227: callq 0x00007fef9464ad80 ; ImmutableOopMap{[64]=Oop [72]=Oop [80]=Oop [8]=Oop }
││ ;*invokeinterface work {reexecute=0 rethrow=0 return_oop=0}
││ ; - cn.wsd.benchmark.functionalinterface.FunctionalInterfaceTest::normalMethodCall@8 (line 29)
││ ; - cn.wsd.benchmark.functionalinterface.jmh_generated.FunctionalInterfaceTest_normalMethodCall_jmhTest::normalMethodCall_avgt_jmhStub@17 (line 190)
││ ; {optimized virtual_call}
1.63% ││ 0x00007fef9c3d422c: mov 0x8(%rsp),%rsi
5.43% ││ 0x00007fef9c3d4231: mov %eax,%edx
0.28% ││ 0x00007fef9c3d4233: callq 0x00007fef9464ad80 ; ImmutableOopMap{[64]=Oop [72]=Oop [80]=Oop [8]=Oop }
││ ;*invokespecial consumeFull {reexecute=0 rethrow=0 return_oop=0}
││ ; - org.openjdk.jmh.infra.Blackhole::consume@15 (line 382)
││ ; - cn.wsd.benchmark.functionalinterface.jmh_generated.FunctionalInterfaceTest_normalMethodCall_jmhTest::normalMethodCall_avgt_jmhStub@20 (line 190)
││ ; {optimized virtual_call}
1.67% ││ 0x00007fef9c3d4238: mov 0x40(%rsp),%r10
5.12% ││ 0x00007fef9c3d423d: movzbl 0x94(%r10),%r11d ;*ifeq {reexecute=0 rethrow=0 return_oop=0}
││ ; - cn.wsd.benchmark.functionalinterface.jmh_generated.FunctionalInterfaceTest_normalMethodCall_jmhTest::normalMethodCall_avgt_jmhStub@33 (line 192)
0.30% ││ 0x00007fef9c3d4245: mov 0x108(%r15),%r10
1.49% ││ 0x00007fef9c3d424c: add $0x1,%rbp ; ImmutableOopMap{[64]=Oop [72]=Oop [80]=Oop [8]=Oop }
││ ;*ifeq {reexecute=1 rethrow=0 return_oop=0}
││ ; - cn.wsd.benchmark.functionalinterface.jmh_generated.FunctionalInterfaceTest_normalMethodCall_jmhTest::normalMethodCall_avgt_jmhStub@33 (line 192)
0.16% ││ 0x00007fef9c3d4250: test %eax,(%r10) ; {poll}
5.16% ││ 0x00007fef9c3d4253: test %r11d,%r11d
│╰ 0x00007fef9c3d4256: je 0x00007fef9c3d4200 ;*aload_1 {reexecute=0 rethrow=0 return_oop=0}
│ ; - cn.wsd.benchmark.functionalinterface.jmh_generated.FunctionalInterfaceTest_normalMethodCall_jmhTest::normalMethodCall_avgt_jmhStub@36 (line 193)
↘ 0x00007fef9c3d4258: movabs $0x7fefb409bc20,%r10
0x00007fef9c3d4262: callq *%r10 ;*invokestatic nanoTime {reexecute=0 rethrow=0 return_oop=0}
; - cn.wsd.benchmark.functionalinterface.jmh_generated.FunctionalInterfaceTest_normalMethodCall_jmhTest::normalMethodCall_avgt_jmhStub@37 (line 193)
0x00007fef9c3d4265: mov 0x48(%rsp),%r10
0x00007fef9c3d426a: mov %rax,0x30(%r10) ;*putfield stopTime {reexecute=0 rethrow=0 return_oop=0}
; - cn.wsd.benchmark.functionalinterface.jmh_generated.FunctionalInterfaceTest_normalMethodCall_jmhTest::normalMethodCall_avgt_jmhStub@40 (line 193)
0x00007fef9c3d426e: movq $0x0,0x20(%r10) ;*putfield realTime {reexecute=0 rethrow=0 return_oop=0}
; - cn.wsd.benchmark.functionalinterface.jmh_generated.FunctionalInterfaceTest_normalMethodCall_jmhTest::normalMethodCall_avgt_jmhStub@46 (line 194)

lambda函数的汇编实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
c2, level 4, cn.wsd.benchmark.functionalinterface.FunctionalInterfaceTest$$Lambda$49.0x00000008000d3840::work, version 2, compile id 6885 

dependencies [0x00007ff0e03ca928,0x00007ff0e03ca930] = 8
handler table [0x00007ff0e03ca930,0x00007ff0e03ca948] = 24
----------------------------------------------------------------------
cn/wsd/benchmark/functionalinterface/FunctionalInterfaceTest$$Lambda$49.work([B)I [0x00007ff0e03ca7c0, 0x00007ff0e03ca868] 168 bytes
[Entry Point]
[Constants]
# {method} {0x00007ff08fcf8ba0} &apos;work&apos; &apos;([B)I&apos; in &apos;cn/wsd/benchmark/functionalinterface/FunctionalInterfaceTest$$Lambda$49&apos;
# this: rsi:rsi = &apos;cn/wsd/benchmark/functionalinterface/FunctionalInterfaceTest$$Lambda$49&apos;
# parm0: rdx:rdx = &apos;[B&apos;
# [sp+0x20] (sp of caller)
0.05% 0x00007ff0e03ca7c0: mov 0x8(%rsi),%r10d
3.30% 0x00007ff0e03ca7c4: movabs $0x800000000,%r12
0.07% 0x00007ff0e03ca7ce: add %r12,%r10
0.05% 0x00007ff0e03ca7d1: xor %r12,%r12
0.03% 0x00007ff0e03ca7d4: cmp %r10,%rax
0x00007ff0e03ca7d7: jne 0x00007ff0d864b080 ; {runtime_call ic_miss_stub}
3.08% 0x00007ff0e03ca7dd: data16 xchg %ax,%ax
[Verified Entry Point]
0.05% 0x00007ff0e03ca7e0: mov %eax,-0x14000(%rsp)
0.10% 0x00007ff0e03ca7e7: push %rbp
3.07% 0x00007ff0e03ca7e8: sub $0x10,%rsp ;*synchronization entry
; - cn.wsd.benchmark.functionalinterface.FunctionalInterfaceTest$$Lambda$49/0x00000008000d3840::work@-1
0.06% 0x00007ff0e03ca7ec: mov 0xc(%rsi),%r10d ;*getfield arg$1 {reexecute=0 rethrow=0 return_oop=0}
; - cn.wsd.benchmark.functionalinterface.FunctionalInterfaceTest$$Lambda$49/0x00000008000d3840::work@1
0.07% 0x00007ff0e03ca7f0: test %r10d,%r10d
╭ 0x00007ff0e03ca7f3: je 0x00007ff0e03ca810 ;*invokespecial lambda$dynamicMethodCall$0 {reexecute=0 rethrow=0 return_oop=0}
│ ; - cn.wsd.benchmark.functionalinterface.FunctionalInterfaceTest$$Lambda$49/0x00000008000d3840::work@5
3.11% │ 0x00007ff0e03ca7f5: lea (%r12,%r10,8),%rsi ;*getfield arg$1 {reexecute=0 rethrow=0 return_oop=0}
│ ; - cn.wsd.benchmark.functionalinterface.FunctionalInterfaceTest$$Lambda$49/0x00000008000d3840::work@1
0.05% │ 0x00007ff0e03ca7f9: xchg %ax,%ax
0.02% │ 0x00007ff0e03ca7fb: callq 0x00007ff0d864ad80 ; ImmutableOopMap{}
│ ;*invokespecial lambda$dynamicMethodCall$0 {reexecute=0 rethrow=0 return_oop=0}
│ ; - cn.wsd.benchmark.functionalinterface.FunctionalInterfaceTest$$Lambda$49/0x00000008000d3840::work@5
│ ; {optimized virtual_call}
6.98% │ 0x00007ff0e03ca800: add $0x10,%rsp
0.04% │ 0x00007ff0e03ca804: pop %rbp
0.06% │ 0x00007ff0e03ca805: mov 0x108(%r15),%r10
3.10% │ 0x00007ff0e03ca80c: test %eax,(%r10) ; {poll_return}
0.04% │ 0x00007ff0e03ca80f: retq
↘ 0x00007ff0e03ca810: mov $0xfffffff6,%esi
0x00007ff0e03ca815: mov %rdx,%rbp
0x00007ff0e03ca818: data16 xchg %ax,%ax
0x00007ff0e03ca81b: callq 0x00007ff0d8649e00 ; ImmutableOopMap{rbp=Oop }
;*invokespecial lambda$dynamicMethodCall$0 {reexecute=0 rethrow=0 return_oop=0}
; - cn.wsd.benchmark.functionalinterface.FunctionalInterfaceTest$$Lambda$49/0x00000008000d3840::work@5
; {runtime_call UncommonTrapBlob}
0x00007ff0e03ca820: mov %rax,%rsi
0x00007ff0e03ca823: add $0x10,%rsp
0x00007ff0e03ca827: pop %rbp

调用它的地方:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
c2, level 4, cn.wsd.benchmark.functionalinterface.FunctionalInterfaceTest::bynamicMethod, version 2, compile id 6881 

# parm1: rcx:rcx = &apos;[B&apos;
# [sp+0x20] (sp of caller)
0x00007ff0e03c99a0: mov 0x8(%rsi),%r10d
0x00007ff0e03c99a4: movabs $0x800000000,%r12
0x00007ff0e03c99ae: add %r12,%r10
0x00007ff0e03c99b1: xor %r12,%r12
0x00007ff0e03c99b4: cmp %r10,%rax
0x00007ff0e03c99b7: jne 0x00007ff0d864b080 ; {runtime_call ic_miss_stub}
0x00007ff0e03c99bd: data16 xchg %ax,%ax
[Verified Entry Point]
3.14% 0x00007ff0e03c99c0: mov %eax,-0x14000(%rsp)
0.08% 0x00007ff0e03c99c7: push %rbp
0.04% 0x00007ff0e03c99c8: sub $0x10,%rsp ;*synchronization entry
; - cn.wsd.benchmark.functionalinterface.FunctionalInterfaceTest::bynamicMethod@-1 (line 19)
3.19% 0x00007ff0e03c99cc: mov %rdx,%rsi
0.03% 0x00007ff0e03c99cf: mov %rcx,%rdx
0.05% 0x00007ff0e03c99d2: data16 xchg %ax,%ax
3.35% 0x00007ff0e03c99d5: movabs $0xffffffffffffffff,%rax
0.06% 0x00007ff0e03c99df: callq 0x00007ff0d864aa80 ; ImmutableOopMap{}
;*invokeinterface work {reexecute=0 rethrow=0 return_oop=0}
; - cn.wsd.benchmark.functionalinterface.FunctionalInterfaceTest::bynamicMethod@2 (line 19)
; {virtual_call}
0.06% 0x00007ff0e03c99e4: add $0x10,%rsp
2.95% 0x00007ff0e03c99e8: pop %rbp
0.06% 0x00007ff0e03c99e9: mov 0x108(%r15),%r10
0.05% 0x00007ff0e03c99f0: test %eax,(%r10) ; {poll_return}
0.06% 0x00007ff0e03c99f3: retq ;*invokeinterface work {reexecute=0 rethrow=0 return_oop=0}
; - cn.wsd.benchmark.functionalinterface.FunctionalInterfaceTest::bynamicMethod@2 (line 19)
0x00007ff0e03c99f4: mov %rax,%rsi
0x00007ff0e03c99f7: add $0x10,%rsp
0x00007ff0e03c99fb: pop %rbp
0x00007ff0e03c99fc: jmpq 0x00007ff0d86f9900 ; {runtime_call _rethrow_Java}

reexperiment

0x00007f95a864ad80

一些思考

条款对应实现的Java数据结构是怎样的?一个函数、多个函数还是一个类

一个函数表达不出条款的意思
多个函数方案可以将when,while,where分别对应到一个函数,不过难以统一判断条款的参与方party,需要每个函数前面都加一个判断。
一个类的方案目前还没遇到问题。

条款中的动作参数是形参还是实参

使用形参parametersList。因为条款里的动作相当于AOP中的PointCut,定义为ActionSignature
与此区分,test函数里的action调用定义为 functionCall,使用实参argumentList

关于不支持函数重载

一般说来,虽然Action中支持定义参数,但是我们一般不使用同名不同参来进行函数重载(即不支持函数重载)
原因是我们使用的是方法名作为唯一标示去查找和判定的。为什么不用Method?
因为 Method 不支持 Berkeley DB持久化存储。

ContractEngine 的设计

根据Action是由自主触发还是AOP外部触发将工作模式分为自实现和AOP两种。

自实现 AOP
handleAction触发,内部调用method.invoke执行动作 Spring Bean中方法执行动作,@Pointcut拦截触发

两种模式对于duty的处理:

Duty 自实现 AOP
can 通过调用handleAction触发 拦截外部调用后检查termObj, termObj.when 通过后执行
must runMustActions 中触发调用must动作 和can对待是一样的。所以需要另写breach term处理must动作如果一直不触发的情况
cannot handleAction中检查出来,则不发生动作执行 termObj.when 通过后,则不执行pjp.proceed

两种模式对于条件的处理:

Condition 自实现 AOP
when termObj.when 和自实现一样
while termObj.while,和method.invoke 并列执行 termObj.while,和 pjp.proceed 并列执行
where termObj.where 和自实现一样
设计模式 之 访问者模式 Spring cloud 总线实验

Comments

You forgot to set the shortname for Disqus. Please set it in _config.yml.
Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×