[9] RFR (S): 8157181: Compilers accept modification of final fields outside initializer methods

Vladimir Ivanov vladimir.x.ivanov at oracle.com
Thu Jun 9 11:28:23 UTC 2016


Zoltan,

> To summarize, webrev.06
> - *detects misbehaving fields in the verifier* for classes with version
> < JAVA_7_VERSION and *disables constant folding for those fields only*;
> - *enforces JVMS-7 conformance* for classes with version >=
> JAVA_7_VERSION and *leaves constant folding as it is* (no performance
> impact).
>
> As I mentioned to David Holmes, we can use JAVA_8_VERSION or
> JAVA_9_VERSION instead of JAVA_7_VERSION.

Agree.

> I'm currently running pre-PIT RBT to see if there are any problems with
> our testbase. Performance runs are also in progress.
>
> Here is the updated webrev:
> http://cr.openjdk.java.net/~zmajo/8157181/webrev.06/

I really like how it shapes out!

Some comments follow:

Unfortunately, it doesn't (and, moreover, can't) cover class 
redefinition: if a new version of a method contains final field update, 
all the generated code which embed previous value should be invalidated.

The only way to handle such case now is to add nmethod dependencies when 
static final field loads are constant folded.

Please, file a separate bug (P4) for that and let's decide how to 
proceed with it later.

---
src/share/vm/classfile/verifier.cpp:

+ void Verifier::detect_invalid_final_field_accesses(instanceKlassHandle 
klass) {

The name is misleading: such accesses are legal according to JVMS-6 (and 
earlier). Maybe something like detect_initialized_final_field_updates?

Same for:
+   bool has_invalid_final_access() const    { return 
access_flags().has_field_invalid_final_access(); }
+   void set_has_invalid_final_access(const bool value) {
+   JVM_ACC_FIELD_INVALID_FINAL_ACCESS  = 0x00000100,


---
Why do you care about _nofast_putfield? The bytecode hasn't been 
rewritten yet.

+   if (klass()->major_version() < 51 && !klass->is_rewritten()) {
...
+         if (opcode == Bytecodes::_putstatic || opcode == 
Bytecodes::_putfield || opcode == Bytecodes::_nofast_putfield) {

---
Also, I don't think in its current shape it is part of verification, but 
instanceKlass linkage phase instead:

bool InstanceKlass::link_class_impl(
     instanceKlassHandle this_k, bool throw_verifyerror, TRAPS) {
...
     if (!this_k->is_linked()) {
       if (!this_k->is_rewritten()) {
         {
           bool verify_ok = verify_code(this_k, throw_verifyerror, THREAD);
           if (!verify_ok) {
             return false;
           }
         }
...
	<< HERE >>
...
         // also sets rewritten
         this_k->rewrite_class(CHECK_false);

---
I don't see much benefit in tracking the problematic updates per-methods 
and not per-class. So, you could do the checks in 
ClassVerifier::verify_field_instructions [1] and mark the whole class 
(ClassVerifier::_klass) as containing problematic instructions.

---
src/share/vm/interpreter/linkResolver.cpp:

         THROW(vmSymbols::java_lang_IllegalAccessError());

+         THROW(vmSymbols::java_lang_IllegalAccessError());

Please, add an error message for diagnostic purposes.

---
src/share/vm/ci/ciField.cpp:

-    if (_known_to_link_with_put == accessing_klass) {
+    if (_known_to_link_with_put_klass == accessing_klass && 
_known_to_link_with_put_method) {

Don't you need to check _known_to_link_with_put_method with 
accessing_method?

Why don't you use accessing_method instead of accessing_klass and 
migrate _known_to_link_with_put/get to ciMethod*?

   bool will_link(ciMethod* accessing_method, Bytecodes::Code bc);

I looked at all will_link usages and accessing_method is always available.


Otherwise, looks good!

Best regards,
Vladimir Ivanov

[1] 
http://hg.openjdk.java.net/jdk9/hs-comp/hotspot/file/84ff58dfd5e0/src/share/vm/classfile/verifier.cpp#l2226


More information about the hotspot-compiler-dev mailing list