--- a/src/hotspot/share/opto/compile.cpp Thu May 30 09:24:13 2019 -0400
+++ b/src/hotspot/share/opto/compile.cpp Thu May 30 19:12:11 2019 +0300
@@ -3846,9 +3846,42 @@
}
}
-bool Compile::is_compiling_clinit_for(ciKlass* k) {
- ciMethod* root = method(); // the root method of compilation
- return root->is_static_initializer() && root->holder() == k; // access in the context of clinit
+bool Compile::needs_clinit_barrier(ciMethod* method, ciMethod* accessing_method) {
+ return method->is_static() && needs_clinit_barrier(method->holder(), accessing_method);
+}
+
+bool Compile::needs_clinit_barrier(ciField* field, ciMethod* accessing_method) {
+ return field->is_static() && needs_clinit_barrier(field->holder(), accessing_method);
+}
+
+bool Compile::needs_clinit_barrier(ciInstanceKlass* holder, ciMethod* accessing_method) {
+ if (holder->is_initialized()) {
+ return false;
+ }
+ if (holder->is_being_initialized()) {
+ if (accessing_method->holder() == holder) {
+ // Access inside a class. The barrier can be elided when access happens in <clinit>,
+ // <init>, or a static method. In all those cases, there was an initialization
+ // barrier on the holder klass passed.
+ if (accessing_method->is_static_initializer() ||
+ accessing_method->is_object_initializer() ||
+ accessing_method->is_static()) {
+ return false;
+ }
+ } else if (accessing_method->holder()->is_subclass_of(holder)) {
+ // Access from a subclass. The barrier can be elided only when access happens in <clinit>.
+ // In case of <init> or a static method, the barrier is on the subclass is not enough:
+ // child class can become fully initialized while its parent class is still being initialized.
+ if (accessing_method->is_static_initializer()) {
+ return false;
+ }
+ }
+ ciMethod* root = method(); // the root method of compilation
+ if (root != accessing_method) {
+ return needs_clinit_barrier(holder, root); // check access in the context of compilation root
+ }
+ }
+ return true;
}
#ifndef PRODUCT