3535import  org .graalvm .compiler .core .common .type .StampFactory ;
3636import  org .graalvm .compiler .core .common .type .TypeReference ;
3737import  org .graalvm .compiler .debug .DebugContext ;
38+ import  org .graalvm .compiler .debug .GraalError ;
3839import  org .graalvm .compiler .graph .Node ;
3940import  org .graalvm .compiler .graph .NodeBitMap ;
4041import  org .graalvm .compiler .graph .NodeInputList ;
8384import  com .oracle .graal .pointsto .flow .MethodFlowsGraph ;
8485import  com .oracle .graal .pointsto .flow .MethodTypeFlow ;
8586import  com .oracle .graal .pointsto .flow .TypeFlow ;
87+ import  com .oracle .graal .pointsto .heap .ImageHeapConstant ;
8688import  com .oracle .graal .pointsto .infrastructure .Universe ;
8789import  com .oracle .graal .pointsto .meta .AnalysisField ;
8890import  com .oracle .graal .pointsto .meta .AnalysisMethod ;
9193import  com .oracle .graal .pointsto .typestate .TypeState ;
9294import  com .oracle .svm .util .ImageBuildStatistics ;
9395
96+ import  jdk .vm .ci .meta .JavaConstant ;
9497import  jdk .vm .ci .meta .JavaKind ;
9598import  jdk .vm .ci .meta .JavaMethodProfile ;
9699import  jdk .vm .ci .meta .JavaTypeProfile ;
100+ import  jdk .vm .ci .meta .MetaAccessProvider ;
97101import  jdk .vm .ci .meta .ResolvedJavaType ;
98102
99103/** 
@@ -142,6 +146,11 @@ public StaticAnalysisResults makeOrApplyResults(AnalysisMethod m) {
142146                debug .handle (ex );
143147            }
144148
149+             for  (Node  node  : graph .getNodes ()) {
150+                 if  (node  instanceof  ValueNode  && ((ValueNode ) node ).stamp (NodeView .DEFAULT ) instanceof  ConstantObjectStamp ) {
151+                     throw  GraalError .shouldNotReachHere ("ConstantObjectStamp must not be visible outside of this class" );
152+                 }
153+             }
145154            method .setAnalyzedGraph (GraphEncoder .encodeSingleGraph (graph , AnalysisParsedGraph .HOST_ARCHITECTURE ));
146155        }
147156
@@ -259,7 +268,13 @@ public void simplify(Node n, SimplifierTool tool) {
259268                 * context-sensitive analysis, we will need to change this. But for now, we are 
260269                 * fine. 
261270                 */ 
262-                 updateStampInPlace (node , newStamp , tool );
271+                 if  (newStamp  instanceof  ConstantObjectStamp ) {
272+                     ConstantNode  replacement  = ConstantNode .forConstant (((ConstantObjectStamp ) newStamp ).constant , bb .getMetaAccess (), graph );
273+                     graph .replaceFixedWithFloating (node , replacement );
274+                     tool .addToWorkList (replacement );
275+                 } else  {
276+                     updateStampInPlace (node , newStamp , tool );
277+                 }
263278
264279            } else  if  (n  instanceof  Invoke ) {
265280                Invoke  invoke  = (Invoke ) n ;
@@ -390,8 +405,8 @@ private void handleInvoke(Invoke invoke, SimplifierTool tool) {
390405                    /* Parameter stamp was empty, so invoke is unreachable. */ 
391406                    return ;
392407                } else  if  (newStamp  != null ) {
393-                     PiNode  pi  = insertPi (argument , newStamp , beforeInvoke );
394-                     if  (pi  != null ) {
408+                     ValueNode  pi  = insertPi (argument , newStamp , beforeInvoke );
409+                     if  (pi  != null  &&  pi  !=  argument ) {
395410                        callTarget .replaceAllInputs (argument , pi );
396411                    }
397412                }
@@ -521,17 +536,20 @@ private void updateStampInPlace(ValueNode node, Stamp newStamp, SimplifierTool t
521536
522537        private  void  updateStampUsingPiNode (ValueNode  node , Stamp  newStamp , FixedWithNextNode  anchorPoint , SimplifierTool  tool ) {
523538            if  (newStamp  != null  && node .hasUsages () && !createdPiNodes .isMarked (node )) {
524-                 PiNode  pi  = insertPi (node , newStamp , anchorPoint );
539+                 ValueNode  pi  = insertPi (node , newStamp , anchorPoint );
525540                if  (pi  != null ) {
526541                    /* 
527542                     * The Canonicalizer that drives all of our node processing is iterative. We 
528543                     * only want to insert the PiNode the first time we handle a node. 
529544                     */ 
530545                    createdPiNodes .mark (node );
531546
532-                     FrameState  anchorState  = node  instanceof  StateSplit  ? ((StateSplit ) node ).stateAfter () : graph .start ().stateAfter ();
533-                     node .replaceAtUsages (pi , usage  -> usage  != pi  && usage  != anchorState );
534- 
547+                     if  (pi .isConstant ()) {
548+                         node .replaceAtUsages (pi );
549+                     } else  {
550+                         FrameState  anchorState  = node  instanceof  StateSplit  ? ((StateSplit ) node ).stateAfter () : graph .start ().stateAfter ();
551+                         node .replaceAtUsages (pi , usage  -> usage  != pi  && usage  != anchorState );
552+                     }
535553                    tool .addToWorkList (pi .usages ());
536554                }
537555            }
@@ -540,7 +558,16 @@ private void updateStampUsingPiNode(ValueNode node, Stamp newStamp, FixedWithNex
540558        /* 
541559         * See comment on {@link StrengthenGraphs} on why anchoring is necessary. 
542560         */ 
543-         private  PiNode  insertPi (ValueNode  input , Stamp  piStamp , FixedWithNextNode  anchorPoint ) {
561+         private  ValueNode  insertPi (ValueNode  input , Stamp  piStamp , FixedWithNextNode  anchorPoint ) {
562+             if  (piStamp  instanceof  ConstantObjectStamp ) {
563+                 JavaConstant  constant  = ((ConstantObjectStamp ) piStamp ).constant ;
564+                 if  (input .isConstant ()) {
565+                     assert  input .asConstant ().equals (constant );
566+                     return  null ;
567+                 }
568+                 return  ConstantNode .forConstant (constant , bb .getMetaAccess (), graph );
569+             }
570+ 
544571            Stamp  oldStamp  = input .stamp (NodeView .DEFAULT );
545572            Stamp  computedStamp  = oldStamp .improveWith (piStamp );
546573            if  (oldStamp .equals (computedStamp )) {
@@ -571,6 +598,23 @@ private Stamp strengthenStampFromTypeFlow(ValueNode node, TypeFlow<?> nodeFlow,
571598            }
572599
573600            TypeState  nodeTypeState  = methodFlow .foldTypeFlow (pta , nodeFlow );
601+ 
602+             if  (!nodeTypeState .canBeNull ()) {
603+                 JavaConstant  constantValue  = nodeTypeState .asConstant ();
604+                 if  (constantValue  instanceof  ImageHeapConstant ) {
605+                     /* 
606+                      * Temporary: until the AOT compilation can properly constant fold also 
607+                      * ImageHeapConstant, we unwrap the ImageHeapConstant to the hosted object. This 
608+                      * also means we do not constant fold yet when the constant does not wrap a 
609+                      * hosted object. 
610+                      */ 
611+                     constantValue  = ((ImageHeapConstant ) constantValue ).getHostedObject ();
612+                 }
613+                 if  (constantValue  != null ) {
614+                     return  ConstantObjectStamp .forConstant (constantValue , bb .getMetaAccess ());
615+                 }
616+             }
617+ 
574618            node .inferStamp ();
575619            ObjectStamp  oldStamp  = (ObjectStamp ) node .stamp (NodeView .DEFAULT );
576620            AnalysisType  oldType  = (AnalysisType ) oldStamp .type ();
@@ -732,3 +776,23 @@ private Stamp strengthenStamp(Stamp s) {
732776        }
733777    }
734778}
779+ 
780+ /** 
781+  * {@link ObjectStamp} cannot represent a real "constant" stamp, so we use this class as a temporary 
782+  * holder for a constant. Such a stamp is never stored as the stamp of a node, instead the node is 
783+  * replaces with a {@link ConstantNode}. 
784+  */ 
785+ final  class  ConstantObjectStamp  extends  ObjectStamp  {
786+ 
787+     final  JavaConstant  constant ;
788+ 
789+     static  Stamp  forConstant (JavaConstant  constant , MetaAccessProvider  metaAccess ) {
790+         ResolvedJavaType  type  = constant .isNull () ? null  : metaAccess .lookupJavaType (constant );
791+         return  new  ConstantObjectStamp (constant , type , constant .isNonNull (), constant .isNonNull (), constant .isNull (), false );
792+     }
793+ 
794+     private  ConstantObjectStamp (JavaConstant  constant , ResolvedJavaType  type , boolean  exactType , boolean  nonNull , boolean  alwaysNull , boolean  alwaysArray ) {
795+         super (type , exactType , nonNull , alwaysNull , alwaysArray );
796+         this .constant  = constant ;
797+     }
798+ }
0 commit comments