- 浏览: 3053260 次
- 性别:
- 来自: 海外
文章分类
- 全部博客 (430)
- Programming Languages (23)
- Compiler (20)
- Virtual Machine (57)
- Garbage Collection (4)
- HotSpot VM (26)
- Mono (2)
- SSCLI Rotor (1)
- Harmony (0)
- DLR (19)
- Ruby (28)
- C# (38)
- F# (3)
- Haskell (0)
- Scheme (1)
- Regular Expression (5)
- Python (4)
- ECMAScript (2)
- JavaScript (18)
- ActionScript (7)
- Squirrel (2)
- C (6)
- C++ (10)
- D (2)
- .NET (13)
- Java (86)
- Scala (1)
- Groovy (3)
- Optimization (6)
- Data Structure and Algorithm (3)
- Books (4)
- WPF (1)
- Game Engines (7)
- 吉里吉里 (12)
- UML (1)
- Reverse Engineering (11)
- NSIS (4)
- Utilities (3)
- Design Patterns (1)
- Visual Studio (9)
- Windows 7 (3)
- x86 Assembler (1)
- Android (2)
- School Assignment / Test (6)
- Anti-virus (1)
- REST (1)
- Profiling (1)
- misc (39)
- NetOA (12)
- rant (6)
- anime (5)
- Links (12)
- CLR (7)
- GC (1)
- OpenJDK (2)
- JVM (4)
- KVM (0)
- Rhino (1)
- LINQ (2)
- JScript (0)
- Nashorn (0)
- Dalvik (1)
- DTrace (0)
- LLVM (0)
- MSIL (0)
最新评论
-
mldxs:
虽然很多还是看不懂,写的很好!
虚拟机随谈(一):解释器,树遍历解释器,基于栈与基于寄存器,大杂烩 -
HanyuKing:
Java的多维数组 -
funnyone:
Java 8的default method与method resolution -
ljs_nogard:
Xamarin workbook - .Net Core 中不 ...
LINQ的恶搞…… -
txm119161336:
allocatestlye1 顺序为 // Fields o ...
最近做的两次Java/JVM分享的概要
AS3, optional type annotation, and strict mode
Boy, this is my first English post on this blog. I wish I had the time to write more English and Japanses posts. Anyway here we go.
Those who have been using ActionScript 3 would have noticed its optional type annotations. So what do we get from being explicit about types? It's obvious that, by stating the programs' invariants through type annotation, type errors can be reported earlier (at compile time) than they would have been otherwise (at runtime). But what else? Does explicit typing yield better runtime performance too?
On the current implementation of Adobe's ActionScript 3 compiler, the answer to that may just be a _no_. Even though Flex SDK and Tamarin are both open source, which means that we can get full sources to the whole compiler+vm suite to get AS3 running, it's still hard to figure things out just by browsing through the code without detailed documentations. So I'm just gonna do some superficial tests to see what's going on in the AS3 compiler.
=======================================================================================================
When compiling AS3 source code, there are two compilation modes: the standard mode and the strict mode. In standard mode, everything's supposed to be compatible to the good old ECMA-262 version 3 spec, so we should be able to safely assume that the type annotations in standard mode doesn't do much. In strict mode, however, some type checks can be done at compile time, so that: we can't assign to a variable not yet declared, neither can we call a function with parameters of imcompatible types.
According to the ES4 wiki, Strict and Standard compilation modes, strict mode is "only meant as a way for programmers to indicate their desire for more extensive and conservative error analysis", and does not imply optimizations, although implementation can take advantage of the type information to produce better code.
So let's take a look at this sample code snippet, to see how type annotations affect type checking and instruction selection in Adobe's AS3 compiler:
test.as:
(compiled with asc.jar from Flex 3 SDK, with the command:
java -jar asc.jar -import builtin.abc -import toplevel.abc -m -strict test.as
builtin.abc and toplevel.abc are from Tamarin, 2007/10/31)
The methods in the code snippet are pretty much the same: they *add up* the two parameters. Foo() is fully type annotated, goo() is totally unannotated, where as the other methods are partially annotated.
Note that there are two AVM2 instructions that does the operation of "add": one is the general "add", the other is "add_i", which adds up two integers.
As stated in ActionScript Virtual Machine 2 Overview, the semantics of add and add_i are:
Both instructions aren't really low-level enough. Whatever parameters passed in, both instructions include the semantics to do a type check/implicit type convertion first, then add the two operands, and finally pushing the result back onto the evaluation stack. Anyway, if it is known that both the operands are ints, I reckon it should be better to choose add_i than add. But that's not the case here, Adobe's AS3 compiler always generated code using add.
Take a closer look at the code generated for foo().
The method's generated signature is:
The return type and parameter types are all int, correct.
The method's body:
So even when fully type annotated as in foo(), the compiler chooses add instead of add_i. Actually the compiler seem to generate the same code for foo()'s method body whatever the compilation mode.
For goo(), we can see that calling goo() with (1, "2") yields a number 3. The string "2" is implicitly converted into int upon calling foo() in goo(), even if that wasn't the programmer's intention.
The compiler doesn't reject methods calls where formal parameters' types and actual parameters' types aren't exactly the same. The types are considered "compatible" if there's a way to implicitly convert from the source type to the target type. So unless we do something like this:
the compiler's gonna be "forgiving" enough not to warn you that implicit conversions have been done. Not to mention, code like this will also compile, whatever the compilation mode:
No errors, no warnings. Not until you run the code will you see the argument error:
I thought strict mode was supposed to be less forgiving than this...well, I'm wrong.
It's easy to see that the compiler doesn't do type inference at all. In ioo(), where I didn't annotate the local variable's type, the compiler adds a coerce instruction after the add:
Again, the code generated for ioo()'s method body is the same whatever the compilation mode. Overall, there's only little difference between code generated in strict mode or standard mode.
Haven't run any benchmarks for differently annotated code, I'd just guess from the code generated that strict mode with annotated types in AS3 doesn't imply better runtime performance. I'm asking Francis Cheng on this, and see if he can give us more detail on optional type annotations and strict mode.
I thought we can take advantage of the declared types and at least reduce some of these redundant type checks/coerces. Adobe's AS3 compiler doesn't do that currently. And there should be a reason behind it, which I don't know. Maybe digging into the source code will give me a better picture...
=======================================================================================================
The only reason I can come up with is, the optimization on reducing dynamic type checking is not done at compile time, and is instead done at runtime, through a tracing-JIT. Tamarin-tracing is the one that
Maybe the JITter knows how to reduce all those redundant type checks on frequently used types, so no matter what compilation mode you're using, you always benefit from the runtime.
=======================================================================================================
The Impact of Optional Type Information on JIt Compilation of Dynammically Typed Languages
Those who have been using ActionScript 3 would have noticed its optional type annotations. So what do we get from being explicit about types? It's obvious that, by stating the programs' invariants through type annotation, type errors can be reported earlier (at compile time) than they would have been otherwise (at runtime). But what else? Does explicit typing yield better runtime performance too?
On the current implementation of Adobe's ActionScript 3 compiler, the answer to that may just be a _no_. Even though Flex SDK and Tamarin are both open source, which means that we can get full sources to the whole compiler+vm suite to get AS3 running, it's still hard to figure things out just by browsing through the code without detailed documentations. So I'm just gonna do some superficial tests to see what's going on in the AS3 compiler.
=======================================================================================================
When compiling AS3 source code, there are two compilation modes: the standard mode and the strict mode. In standard mode, everything's supposed to be compatible to the good old ECMA-262 version 3 spec, so we should be able to safely assume that the type annotations in standard mode doesn't do much. In strict mode, however, some type checks can be done at compile time, so that: we can't assign to a variable not yet declared, neither can we call a function with parameters of imcompatible types.
According to the ES4 wiki, Strict and Standard compilation modes, strict mode is "only meant as a way for programmers to indicate their desire for more extensive and conservative error analysis", and does not imply optimizations, although implementation can take advantage of the type information to produce better code.
So let's take a look at this sample code snippet, to see how type annotations affect type checking and instruction selection in Adobe's AS3 compiler:
test.as:
package { class TestClass { function foo(x : int, y : int) : int { return x + y; } function goo(x, y) { return foo(x, y); } function hoo(x, y : String) { return x + y; } function ioo(x : int, y : int) { var i = x + y; return i; } function joo(x : int, y : int) { var i : int = x + y; return i; } } var c = new TestClass(); var i = c.goo(1, "2"); print(i); // 3 i = c.hoo(1, "2"); print(i); // 12 i = c.ioo(1, "2"); print(i); // 3 }
(compiled with asc.jar from Flex 3 SDK, with the command:
java -jar asc.jar -import builtin.abc -import toplevel.abc -m -strict test.as
builtin.abc and toplevel.abc are from Tamarin, 2007/10/31)
The methods in the code snippet are pretty much the same: they *add up* the two parameters. Foo() is fully type annotated, goo() is totally unannotated, where as the other methods are partially annotated.
Note that there are two AVM2 instructions that does the operation of "add": one is the general "add", the other is "add_i", which adds up two integers.
As stated in ActionScript Virtual Machine 2 Overview, the semantics of add and add_i are:
ActionScript Virtual Machine 2 (AVM2) Overview 写道
add
Operation
Add two values.
Format
add
Forms
add = 160 (0xa0)
Stack
…, value1, value2 => …, value3
Description
Pop value1 and value2 off of the stack and add them together as specified in ECMA-262 section 11.6 and as extended in ECMA-357 section 11.4. The algorithm is briefly described below.
1. If value1 and value2 are both Numbers, then set value3 to the result of adding the two number values. See ECMA-262 section 11.6.3 for a description of adding number values.
2. If value1 or value2 is a String or a Date, convert both values to String using the ToString algorithm described in ECMA-262 section 9.8. Concatenate the string value of value2 to the string value of value1 and set value3 to the new concatenated String.
3. If value1 and value2 are both of type XML or XMLList, construct a new XMLList object, then call [[Append]](value1), and then [[Append]](value2). Set value3 to the new XMLList.
See ECMA-357 section 9.2.1.6 for a description of the [[Append]] method.
4. If none of the above apply, convert value1 and value2 to primitives. This is done by calling ToPrimitive with no hint. This results in value1_primitive and value2_primitive. If value1_primitive or value2_primitive is a String then convert both to Strings using the ToString algorithm (ECMA-262 section 9.8), concatenate the results, and set value3 to the concatenated String. Otherwise convert both to Numbers using the ToNumber algorithm (ECMA-262 section 9.3), add the results, and set value3 to the result of the addition.
Push value3 onto the stack.
Notes
For more information, see ECMA-262 section 11.6 (“Additive Operators”) and ECMA-357 section 11.4.
Operation
Add two values.
Format
add
Forms
add = 160 (0xa0)
Stack
…, value1, value2 => …, value3
Description
Pop value1 and value2 off of the stack and add them together as specified in ECMA-262 section 11.6 and as extended in ECMA-357 section 11.4. The algorithm is briefly described below.
1. If value1 and value2 are both Numbers, then set value3 to the result of adding the two number values. See ECMA-262 section 11.6.3 for a description of adding number values.
2. If value1 or value2 is a String or a Date, convert both values to String using the ToString algorithm described in ECMA-262 section 9.8. Concatenate the string value of value2 to the string value of value1 and set value3 to the new concatenated String.
3. If value1 and value2 are both of type XML or XMLList, construct a new XMLList object, then call [[Append]](value1), and then [[Append]](value2). Set value3 to the new XMLList.
See ECMA-357 section 9.2.1.6 for a description of the [[Append]] method.
4. If none of the above apply, convert value1 and value2 to primitives. This is done by calling ToPrimitive with no hint. This results in value1_primitive and value2_primitive. If value1_primitive or value2_primitive is a String then convert both to Strings using the ToString algorithm (ECMA-262 section 9.8), concatenate the results, and set value3 to the concatenated String. Otherwise convert both to Numbers using the ToNumber algorithm (ECMA-262 section 9.3), add the results, and set value3 to the result of the addition.
Push value3 onto the stack.
Notes
For more information, see ECMA-262 section 11.6 (“Additive Operators”) and ECMA-357 section 11.4.
ActionScript Virtual Machine 2 (AVM2) Overview 写道
add_i
Operation
Add two integer values.
Format
add_i
Forms
add_i = 197 (0xc5)
Stack
…, value1, value2 => …, value3
Description
Pop value1 and value2 off of the stack and convert them to int values using the ToInt32 algorithm (ECMA-262 section 9.5). Add the two int values and push the result onto the stack.
Operation
Add two integer values.
Format
add_i
Forms
add_i = 197 (0xc5)
Stack
…, value1, value2 => …, value3
Description
Pop value1 and value2 off of the stack and convert them to int values using the ToInt32 algorithm (ECMA-262 section 9.5). Add the two int values and push the result onto the stack.
Both instructions aren't really low-level enough. Whatever parameters passed in, both instructions include the semantics to do a type check/implicit type convertion first, then add the two operands, and finally pushing the result back onto the evaluation stack. Anyway, if it is known that both the operands are ints, I reckon it should be better to choose add_i than add. But that's not the case here, Adobe's AS3 compiler always generated code using add.
Take a closer look at the code generated for foo().
The method's generated signature is:
1. MethodInfo param_count=2 return_type=1 param_types={ 1 1 } debug_name_index=2 needs_arguments=false need_rest=false needs_activation=false has_optional=false ignore_rest=false native=false has_param_names =false -> 1
The return type and parameter types are all int, correct.
The method's body:
MethodBody max_stack=2 max_locals=3 scope_depth=4 max_scope=5 code_length=6 traits_count=0 -> 1
// ++StartMethod foo$0 LoadThis 0:Getlocal0 [1] PushScope 1:Pushscope [0] LoadRegister 1, int 2:Getlocal1 [1] LoadRegister 2, int 3:Getlocal2 [2] InvokeBinary BinaryPlusOp 4:Add [1] Return 5:Returnvalue [0] // --FinishMethod foo$0 TestClass/foo
So even when fully type annotated as in foo(), the compiler chooses add instead of add_i. Actually the compiler seem to generate the same code for foo()'s method body whatever the compilation mode.
For goo(), we can see that calling goo() with (1, "2") yields a number 3. The string "2" is implicitly converted into int upon calling foo() in goo(), even if that wasn't the programmer's intention.
The compiler doesn't reject methods calls where formal parameters' types and actual parameters' types aren't exactly the same. The types are considered "compatible" if there's a way to implicitly convert from the source type to the target type. So unless we do something like this:
class A { } class B { } function test(a : A) { print("A"); } test(new B()); // compile time error // [Compiler] Error #1067: Implicit coercion of a value of type B to an unrelated type A.
the compiler's gonna be "forgiving" enough not to warn you that implicit conversions have been done. Not to mention, code like this will also compile, whatever the compilation mode:
c.ioo(1);
No errors, no warnings. Not until you run the code will you see the argument error:
引用
ArgumentError: Error #1063
I thought strict mode was supposed to be less forgiving than this...well, I'm wrong.
It's easy to see that the compiler doesn't do type inference at all. In ioo(), where I didn't annotate the local variable's type, the compiler adds a coerce instruction after the add:
// ++StartMethod ioo$0 LoadThis 0:Getlocal0 [1] PushScope 1:Pushscope [0] LoadRegister 1, int 2:Getlocal1 [1] LoadRegister 2, int 3:Getlocal2 [2] InvokeBinary BinaryPlusOp 4:Add [1] CheckType * 5:Coerce.o [1] // coerce here StoreRegister 3, * 6:Setlocal3 [0] LoadRegister 3, * 7:Getlocal3 [1] Return 8:Returnvalue [0] // --FinishMethod ioo$0 TestClass/ioo
Again, the code generated for ioo()'s method body is the same whatever the compilation mode. Overall, there's only little difference between code generated in strict mode or standard mode.
Haven't run any benchmarks for differently annotated code, I'd just guess from the code generated that strict mode with annotated types in AS3 doesn't imply better runtime performance. I'm asking Francis Cheng on this, and see if he can give us more detail on optional type annotations and strict mode.
I thought we can take advantage of the declared types and at least reduce some of these redundant type checks/coerces. Adobe's AS3 compiler doesn't do that currently. And there should be a reason behind it, which I don't know. Maybe digging into the source code will give me a better picture...
=======================================================================================================
The only reason I can come up with is, the optimization on reducing dynamic type checking is not done at compile time, and is instead done at runtime, through a tracing-JIT. Tamarin-tracing is the one that
引用
traces code executing during hotspots and compiles it so when those hotspots are entered again the compiled code is run instead. It traces each statement executed, including within other function calls, and this entire execution path is compiled.
Maybe the JITter knows how to reduce all those redundant type checks on frequently used types, so no matter what compilation mode you're using, you always benefit from the runtime.
=======================================================================================================
The Impact of Optional Type Information on JIt Compilation of Dynammically Typed Languages
发表评论
-
The Prehistory of Java, HotSpot and Train
2014-06-02 08:18 0http://cs.gmu.edu/cne/itcore/vi ... -
MSJVM and Sun 1.0.x/1.1.x
2014-05-20 18:50 0当年的survey paper: http://www.sym ... -
Sun JDK1.4.2_28有TieredCompilation
2014-05-12 08:48 0原来以前Sun的JDK 1.4.2 update 28就已经有 ... -
IBM JVM notes (2014 ver)
2014-05-11 07:16 0Sovereign JIT http://publib.bou ... -
class data sharing by Apple
2014-03-28 05:17 0class data sharing is implement ... -
HotSpot Server VM与Server Class Machine
2014-02-18 13:21 0HotSpot VM历来有Client VM与Server V ... -
Java 8的lambda表达式在OpenJDK8中的实现
2014-02-04 12:08 0三月份JDK8就要发布首发了,现在JDK8 release c ... -
GC stack map与deopt stack map的异同
2014-01-08 09:56 0两者之间不并存在包含关系。它们有交集,但也各自有特别的地方。 ... -
HotSpot Server Compiler与data-flow analysis
2014-01-07 17:41 0http://en.wikipedia.org/wiki/Da ... -
基于LLVM实现VM的JIT的一些痛点
2014-01-07 17:25 0同事Philip Reames Sanjoy Das http ... -
tailcall notes
2013-12-27 07:42 0http://blogs.msdn.com/b/clrcode ... -
《自制编程语言》的一些笔记
2013-11-24 00:20 0http://kmaebashi.com/programmer ... -
字符串的一般封装方式的内存布局 (1): 元数据与字符串内容,整体还是分离?
2013-11-07 17:44 22410(Disclaimer:未经许可请 ... -
字符串的一般封装方式的内存布局 (0): 拿在手上的是什么
2013-11-04 18:22 21510(Disclaimer:未经许可请 ... -
字符串的一般封装方式的内存布局
2013-11-01 12:55 0(Disclaimer:未经许可请 ... -
关于string,内存布局,C++ std::string,CoW
2013-10-30 20:45 0(Disclaimer:未经许可请 ... -
Java的instanceof是如何实现的
2013-09-22 16:57 0Java语言规范,Java SE 7版 http://docs ... -
也谈类型: 数据, 类型, 标签
2013-08-18 01:59 0numeric tower http://en.wikiped ... -
oop、klass、handle的关系
2013-07-30 17:34 0oopDesc及其子类的实例 oop : oopDesc* ... -
Nashorn各种笔记
2013-07-15 17:03 0http://bits.netbeans.org/netbea ...
相关推荐
如果选择后者,记得取消选中feature linked,并在Create Annotation Feature Class对话框中指定目标数据库,如图1-2和图1-3所示。 然后,进入ArcGlobe来设置和展示3D Annotation图层。首先,打开3DD文件并添加图层...
3. **Arrow Annotation**:创建箭头形状,指示特定的方向或关联。 4. **Box Annotation**:绘制矩形框,可用于突出显示或标记图表区域。 5. **Circle Annotation**:绘制圆形,可以用来标记数据点或其他关键位置。 ...
标题“Hibernate distribution and annotation”涉及到的是Hibernate ORM框架的一个特定版本及其相关的注解功能。Hibernate是一个流行的Java对象关系映射(ORM)工具,它允许开发者使用面向对象的编程模型来操作...
guard let annotation = annotation as? CustomAnnotation else { return nil } let identifier = "CustomAnnotationIdentifier" var annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: ...
3. **Annotation类型**:Annotation类型是一种接口,定义了Annotation的结构和默认值。在Java中,通过`@interface`关键字声明Annotation类型,其中的成员变量是固定的,没有方法参数。当我们通过反射API访问...
这里主要讨论的是如何将这三者结合,并利用注解(Annotation)进行配置,以简化开发过程。 Struts2是MVC(模型-视图-控制器)框架,主要负责处理HTTP请求和控制应用的流程。它通过Action类处理业务逻辑,使用拦截器...
`ElementType`枚举定义了这些元素,如`ANNOTATION_TYPE`表示可以应用于其他Annotation。 9. **处理Annotation**: 处理Annotation通常发生在编译时(通过编译器插件)或运行时(通过反射API)。例如,`@Retention...
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) @...
赠送jar包:jakarta.annotation-api-1.3.5.jar; 赠送原API文档:jakarta.annotation-api-1.3.5-javadoc.jar; 赠送源代码:jakarta.annotation-api-1.3.5-sources.jar; 赠送Maven依赖信息文件:jakarta.annotation...
《Hibernate注解与Hibernate3深度解析》 在Java开发领域,Hibernate作为一种强大的对象关系映射(ORM)框架,极大地简化了数据库操作。本篇将深入探讨Hibernate 3版本中的注解使用,帮助开发者理解如何利用注解进行...
3. 注解(Annotation)在Hibernate中的应用: - @Entity:标记一个Java类为数据库中的一个表,表示该类是实体类。 - @Table:指定实体类对应的数据库表名。 - @Id:标识类中的主键字段,可以配合@GeneratedValue...
赠送jar包:javax.annotation-api-1.2.jar; 赠送原API文档:javax.annotation-api-1.2-javadoc.jar; 赠送源代码:javax.annotation-api-1.2-sources.jar; 赠送Maven依赖信息文件:javax.annotation-api-1.2.pom;...
javax.annotation-3.0.jar javax.annotation-3.0.jar javax.annotation-3.0.jar
@androidx.annotation.NonNull 缺失的兼容、androidx.annotation兼容包
3. **访问Annotation** ##### 1. 定义Annotation 定义Annotation的基本语法如下: ```java public @interface MyAnnotation { String value() default ""; } ``` 这里定义了一个名为`MyAnnotation`的Annotation...
3. **自定义Annotation** 自定义Annotation通过使用`@interface`关键字来创建。 Annotation类型可以包含成员,这些成员通常是没有参数的方法,其返回类型限制为基本类型、字符串、Class、枚举、Annotation或它们的...
赠送jar包:jakarta.annotation-api-1.3.5.jar; 赠送原API文档:jakarta.annotation-api-1.3.5-javadoc.jar; 赠送源代码:jakarta.annotation-api-1.3.5-sources.jar; 赠送Maven依赖信息文件:jakarta.annotation...
hibernate 注解 annotation 教程