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