[讨论] 请教一个share/vm/oops下的代码做fast subtype check的问题
hellhell
2011-07-27
刚开始这个问题我是直接去私信问R大的,R大受了我不少私信轰炸,估计不胜其扰,所以还没有回我,我也考虑过OpenJDK的邮件组,但是稍为翻了下邮件存档,觉得这种新手问题大概会石沉大海,于是先发到这里,希望各位高手给点提示。
不熟悉或者忘记fast subtype check的兄弟们请看这里http://www.everbox.com/f/jkOyJVAg6Lp6TuUockIu3ccswh 我不大理解paper上的算法,作者给出checking secondary types方法的时候 s.is_subtype_of(T) := { if (S.cache == T) return true; if (S == T) return true; if ( S.scan_s_s_array(T) ) { S.cache = T return true; } } 然后给出Combining the Checks的时候,就把这个对cache内容的检查去掉了,换成if (off != &cache) return false;一句,我理解这句是off != &cache的话,T根本不是一个secondary type,下面就没有必要查了,但是如果在线性扫描secondary type array前做一个对cache内容的检查,不会效率更高么? S.is_subtype_of(T) := { int off = T.offset; if (T == S[off]) return true; if (off != &cache) return false; if (S == T) return true; if ( S.scan_s_s_array(T) ) { S.cache = T return true; } return false; } 我在实际的HotSpot代码中也找了,从1.5.0到最新的,没有的确没有任何地方去读这个cache的值(不是offset!!!!),希望各位高手可以解惑,谢谢。 |
|
RednaxelaFX
2011-07-27
sorry…难怪我觉得还有啥漏了的事情。
在以前做分享用的PPT里我写过,JDK 6的HotSpot里是这样做的(跟论文不完全一样): S.is_subtype_of(T) := { int off = T.offset; if (S == T) return true; if (T == S[off]) return true; if (off != &cache) return false; if ( S.scan_secondary_subtype_array(T) ) { S.cache = T; return true; } return false; } 注意,&cache是指cache的地址,不是cache的内容。 那么看看实际是怎么实现的。用x86版的解释器代码来看,代码在src/cpu/x86/vm/assembler_x86.cpp。 在解释器里,instanceof指令会使用下面的程序生成的代码: void MacroAssembler::check_klass_subtype(Register sub_klass, Register super_klass, Register temp_reg, Label& L_success) { Label L_failure; check_klass_subtype_fast_path(sub_klass, super_klass, temp_reg, &L_success, &L_failure, NULL); check_klass_subtype_slow_path(sub_klass, super_klass, temp_reg, noreg, &L_success, NULL); bind(L_failure); } 这里可以看到,整个检查是分为fast path和slow path两边的。 在fast path里,这段: // This check has worked decisively for primary supers. // Secondary supers are sought in the super_cache ('super_cache_addr'). // (Secondary supers are interfaces and very deeply nested subtypes.) // This works in the same check above because of a tricky aliasing // between the super_cache and the primary super display elements. // (The 'super_check_addr' can address either, as the case requires.) // Note that the cache is updated below if it does not help us find // what we need immediately. // So if it was a primary super, we can just fail immediately. // Otherwise, it's the slow path for us (no success at this point). if (super_check_offset.is_register()) { local_jcc(Assembler::equal, *L_success); // 这是if (T == S[off])后面要跳到return true的地方 cmpl(super_check_offset.as_register(), sc_offset); // 这是off 跟 &cache在比较 if (L_failure == &L_fallthrough) { local_jcc(Assembler::equal, *L_slow_path); // 特殊情况直接跳去slow path继续 } else { local_jcc(Assembler::notEqual, *L_failure); // 这个是if (off != &cache)后面要跳到return false的地方 final_jmp(*L_slow_path); } } 于是…就这样。那个cache的地址的作用被重载了。这种用法在论文里有写的,仔细读读应该能懂。 |
|
hellhell
2011-07-27
这里的确是paper上算法的实现,不过我觉得对cache地址的检查,只可以说明这个T是一个secondary type,所以对&cache检查结果为false了就立即返回失败。但是这里具体是什么type,就不能断定。比如一个对象,实现了多个interface,在check subtype时如果传入的T是interface,还是要去slow path线性扫描。
我的疑问是为什么不在进入slow path前先check下cache的内容?而且如果不用读cache的内容,那么把这个S.cache = T 移除不好么?(这个我还没有尝试过) |
|
RednaxelaFX
2011-07-27
hellhell 写道 我的疑问是为什么不在进入slow path前先check下cache的内容?而且如果不用读cache的内容,那么把这个S.cache = T 移除不好么?(这个我还没有尝试过)
因为: 4.3 Combining the Checks 写道 But, as shown in Figure 2 below, if T is a restricted secondary type, its offset field holds the offset of cache, and so S[T.offset] is the same as S.cache.
S.cache的内容在fast path里还是check过的。只是跟S[off]合体了而已。 论文读仔细哦~ |
|
hellhell
2011-07-28
so S[T.offset] is the same as S.cache.
不好意思,我居然看漏了这一句,现在明白了,第一个检查就相当于对cache的检查。 感谢R大的帮助,打扰你这么多,不好意思。 |
相关讨论
相关资源推荐
- openjdk源码阅读导航
- System.arraycopy 本地方法 源代码分析
- Java instanceof 关键字是如何实现的?
- HotSpot Oop/Klass 模型
- JVM源码实战 - OOP-Klass模型
- /proc详解--linux man page
- 编译内核 make modules_install报错make[1]: *** [arch/x86/crypto/aegis128-aesni.ko] Error 1 Makefile:1281: r
- HotSpot的类模型(2)
- Java Interview Questions/Java面试题 .
- Java Interview Questions/Java面试题