32
32
import java .lang .reflect .InvocationTargetException ;
33
33
import java .lang .reflect .Method ;
34
34
import java .lang .reflect .Modifier ;
35
- import java .util .Collections ;
36
35
import java .util .Comparator ;
37
36
import java .util .EnumSet ;
38
37
import java .util .HashMap ;
39
- import java .util .HashSet ;
40
38
import java .util .List ;
41
39
import java .util .Map ;
42
40
import java .util .Optional ;
76
74
import com .oracle .svm .core .SubstrateOptions .OptimizationLevel ;
77
75
import com .oracle .svm .core .annotate .InjectAccessors ;
78
76
import com .oracle .svm .core .c .CGlobalData ;
79
- import com .oracle .svm .core .classinitialization .EnsureClassInitializedNode ;
80
77
import com .oracle .svm .core .graal .meta .SubstrateForeignCallLinkage ;
81
78
import com .oracle .svm .core .graal .meta .SubstrateForeignCallsProvider ;
82
79
import com .oracle .svm .core .graal .stackvalue .StackValueNode ;
83
- import com .oracle .svm .core .graal .thread .VMThreadLocalAccess ;
84
80
import com .oracle .svm .core .heap .StoredContinuation ;
85
81
import com .oracle .svm .core .heap .Target_java_lang_ref_Reference ;
86
82
import com .oracle .svm .core .heap .UnknownClass ;
130
126
import jdk .graal .compiler .nodes .StaticDeoptimizingNode ;
131
127
import jdk .graal .compiler .nodes .StructuredGraph ;
132
128
import jdk .graal .compiler .nodes .ValueNode ;
133
- import jdk .graal .compiler .nodes .extended .UnsafeAccessNode ;
134
129
import jdk .graal .compiler .nodes .graphbuilderconf .GraphBuilderConfiguration ;
135
130
import jdk .graal .compiler .nodes .graphbuilderconf .IntrinsicContext ;
136
- import jdk .graal .compiler .nodes .java .AccessFieldNode ;
137
- import jdk .graal .compiler .nodes .java .AccessMonitorNode ;
138
131
import jdk .graal .compiler .options .Option ;
139
132
import jdk .graal .compiler .options .OptionKey ;
140
133
import jdk .graal .compiler .options .OptionValues ;
@@ -170,8 +163,6 @@ public class SVMHost extends HostVM {
170
163
* need to keep the whole graphs alive.
171
164
*/
172
165
private final ConcurrentMap <AnalysisMethod , Boolean > containsStackValueNode = new ConcurrentHashMap <>();
173
- private final ConcurrentMap <AnalysisMethod , Boolean > classInitializerSideEffect = new ConcurrentHashMap <>();
174
- private final ConcurrentMap <AnalysisMethod , Set <AnalysisType >> initializedClasses = new ConcurrentHashMap <>();
175
166
private final ConcurrentMap <AnalysisMethod , Boolean > analysisTrivialMethods = new ConcurrentHashMap <>();
176
167
177
168
private final Set <AnalysisField > finalFieldsInitializedOutsideOfConstructor = ConcurrentHashMap .newKeySet ();
@@ -642,53 +633,6 @@ public void methodBeforeTypeFlowCreationHook(BigBang bb, AnalysisMethod method,
642
633
} else if (n instanceof ReachabilityRegistrationNode node ) {
643
634
bb .postTask (debug -> node .getRegistrationTask ().ensureDone ());
644
635
}
645
- checkClassInitializerSideEffect (method , n );
646
- }
647
- }
648
-
649
- /**
650
- * Classes are only safe for automatic initialization if the class initializer has no side
651
- * effect on other classes and cannot be influenced by other classes. Otherwise there would be
652
- * observable side effects. For example, if a class initializer of class A writes a static field
653
- * B.f in class B, then someone could rely on reading the old value of B.f before triggering
654
- * initialization of A. Similarly, if a class initializer of class A reads a static field B.f,
655
- * then an early automatic initialization of class A could read a non-yet-set value of B.f.
656
- *
657
- * Note that it is not necessary to disallow instance field accesses: Objects allocated by the
658
- * class initializer itself can always be accessed because they are independent from other
659
- * initializers; all other objects must be loaded transitively from a static field.
660
- *
661
- * Currently, we are conservative and mark all methods that access static fields as unsafe for
662
- * automatic class initialization (unless the class initializer itself accesses a static field
663
- * of its own class - the common way of initializing static fields). The check could be relaxed
664
- * by tracking the call chain, i.e., allowing static field accesses when the root method of the
665
- * call chain is the class initializer. But this does not fit well into the current approach
666
- * where each method has a `Safety` flag.
667
- */
668
- private void checkClassInitializerSideEffect (AnalysisMethod method , Node n ) {
669
- if (n instanceof AccessFieldNode ) {
670
- ResolvedJavaField field = ((AccessFieldNode ) n ).field ();
671
- if (field .isStatic () && (!method .isClassInitializer () || !field .getDeclaringClass ().equals (method .getDeclaringClass ()))) {
672
- classInitializerSideEffect .put (method , true );
673
- }
674
- } else if (n instanceof UnsafeAccessNode || n instanceof VMThreadLocalAccess ) {
675
- /*
676
- * Unsafe memory access nodes are rare, so it does not pay off to check what kind of
677
- * field they are accessing.
678
- *
679
- * Methods that access a thread-local value cannot be initialized at image build time
680
- * because such values are not available yet.
681
- */
682
- classInitializerSideEffect .put (method , true );
683
- } else if (n instanceof EnsureClassInitializedNode ) {
684
- ResolvedJavaType type = ((EnsureClassInitializedNode ) n ).constantTypeOrNull (getProviders (method .getMultiMethodKey ()).getConstantReflection ());
685
- if (type != null ) {
686
- initializedClasses .computeIfAbsent (method , k -> new HashSet <>()).add ((AnalysisType ) type );
687
- } else {
688
- classInitializerSideEffect .put (method , true );
689
- }
690
- } else if (n instanceof AccessMonitorNode ) {
691
- classInitializerSideEffect .put (method , true );
692
636
}
693
637
}
694
638
@@ -707,19 +651,6 @@ public boolean containsStackValueNode(AnalysisMethod method) {
707
651
return containsStackValueNode .containsKey (method );
708
652
}
709
653
710
- public boolean hasClassInitializerSideEffect (AnalysisMethod method ) {
711
- return classInitializerSideEffect .containsKey (method );
712
- }
713
-
714
- public Set <AnalysisType > getInitializedClasses (AnalysisMethod method ) {
715
- Set <AnalysisType > result = initializedClasses .get (method );
716
- if (result != null ) {
717
- return result ;
718
- } else {
719
- return Collections .emptySet ();
720
- }
721
- }
722
-
723
654
public boolean isAnalysisTrivialMethod (AnalysisMethod method ) {
724
655
return analysisTrivialMethods .containsKey (method );
725
656
}
0 commit comments