src/share/vm/interpreter/rewriter.cpp
Index
Unified diffs
Context diffs
Sdiffs
Patch
New
Old
Previous File
Next File
8161987 Cdiff src/share/vm/interpreter/rewriter.cpp
src/share/vm/interpreter/rewriter.cpp
Print this page
rev 8156 : 8157181: Compilers accept modification of final fields outside initializer methods
Summary: Track initialized final field updates; disable constant folding if an update is detected.
Reviewed-by: vlivanov, dnsimon, forax, never, kvn, coleenp
*** 394,407 ****
case Bytecodes::_invokespecial : {
rewrite_invokespecial(bcp, prefix_length+1, reverse, invokespecial_error);
break;
}
case Bytecodes::_getstatic : // fall through
- case Bytecodes::_putstatic : // fall through
case Bytecodes::_getfield : // fall through
- case Bytecodes::_putfield : // fall through
case Bytecodes::_invokevirtual : // fall through
case Bytecodes::_invokestatic :
case Bytecodes::_invokeinterface:
case Bytecodes::_invokehandle : // if reverse=true
rewrite_member_reference(bcp, prefix_length+1, reverse);
--- 394,442 ----
case Bytecodes::_invokespecial : {
rewrite_invokespecial(bcp, prefix_length+1, reverse, invokespecial_error);
break;
}
+ case Bytecodes::_putstatic :
+ case Bytecodes::_putfield : {
+ if (!reverse) {
+ // Check if any final field of the class given as parameter is modified
+ // outside of initializer methods of the class. Fields that are modified
+ // are marked with a flag. For marked fields, the compilers do not perform
+ // constant folding (as the field can be changed after initialization).
+ //
+ // The check is performed after verification and only if verification has
+ // succeeded. Therefore, the class is guaranteed to be well-formed.
+ InstanceKlass* klass = method->method_holder();
+ u2 bc_index = Bytes::get_Java_u2(bcp + prefix_length + 1);
+ constantPoolHandle cp(method->constants());
+ Symbol* field_name = cp->name_ref_at(bc_index);
+ Symbol* field_sig = cp->signature_ref_at(bc_index);
+ Symbol* ref_class_name = cp->klass_name_at(cp->klass_ref_index_at(bc_index));
+
+ if (klass->name() == ref_class_name) {
+ fieldDescriptor fd;
+ klass->find_field(field_name, field_sig, &fd);
+ if (fd.access_flags().is_final()) {
+ if (fd.access_flags().is_static()) {
+ assert(c == Bytecodes::_putstatic, "must be putstatic");
+ if (!method->is_static_initializer()) {
+ fd.set_has_initialized_final_update(true);
+ }
+ } else {
+ assert(c == Bytecodes::_putfield, "must be putfield");
+ if (!method->is_object_initializer()) {
+ fd.set_has_initialized_final_update(true);
+ }
+ }
+ }
+ }
+ }
+ }
+ // fall through
case Bytecodes::_getstatic : // fall through
case Bytecodes::_getfield : // fall through
case Bytecodes::_invokevirtual : // fall through
case Bytecodes::_invokestatic :
case Bytecodes::_invokeinterface:
case Bytecodes::_invokehandle : // if reverse=true
rewrite_member_reference(bcp, prefix_length+1, reverse);
src/share/vm/interpreter/rewriter.cpp
Index
Unified diffs
Context diffs
Sdiffs
Patch
New
Old
Previous File
Next File