@@ -1595,6 +1595,14 @@ protected GuardingNode maybeEmitExplicitStoreCheck(ValueNode array, JavaKind ele
1595
1595
return emitBytecodeExceptionCheck (condition , true , BytecodeExceptionKind .ARRAY_STORE , value );
1596
1596
}
1597
1597
1598
+ protected ValueNode maybeEmitIncompatibleClassChangeErrorCheck (ValueNode receiver , InvokeKind invokeKind , ResolvedJavaType referencedType ) {
1599
+ if (invokeKind != InvokeKind .Interface || receiver .getStackKind () != JavaKind .Object || !needsIncompatibleClassChangeErrorCheck ()) {
1600
+ return receiver ;
1601
+ }
1602
+ GraalError .guarantee (referencedType != null , "Interface calls must have a referenceType" );
1603
+ return emitIncompatibleClassChangeCheck (receiver , referencedType );
1604
+ }
1605
+
1598
1606
@ Override
1599
1607
public AbstractBeginNode emitBytecodeExceptionCheck (LogicNode condition , boolean passingOnTrue , BytecodeExceptionKind exceptionKind , ValueNode ... arguments ) {
1600
1608
AbstractBeginNode result = GraphBuilderContext .super .emitBytecodeExceptionCheck (condition , passingOnTrue , exceptionKind , arguments );
@@ -1664,7 +1672,7 @@ void genInvokeStatic(JavaMethod target) {
1664
1672
}
1665
1673
1666
1674
ValueNode [] args = frameState .popArguments (resolvedTarget .getSignature ().getParameterCount (false ));
1667
- Invoke invoke = appendInvoke (InvokeKind .Static , resolvedTarget , args );
1675
+ Invoke invoke = appendInvoke (InvokeKind .Static , resolvedTarget , args , null );
1668
1676
if (invoke != null && classInit [0 ] != null ) {
1669
1677
invoke .setClassInit (classInit [0 ]);
1670
1678
}
@@ -1689,7 +1697,7 @@ protected void genInvokeInterface(int cpi, int opcode) {
1689
1697
protected void genInvokeInterface (JavaType referencedType , JavaMethod target ) {
1690
1698
if (callTargetIsResolved (target ) && (referencedType == null || referencedType instanceof ResolvedJavaType )) {
1691
1699
ValueNode [] args = frameState .popArguments (target .getSignature ().getParameterCount (true ));
1692
- Invoke invoke = appendInvoke (InvokeKind .Interface , (ResolvedJavaMethod ) target , args );
1700
+ Invoke invoke = appendInvoke (InvokeKind .Interface , (ResolvedJavaMethod ) target , args , ( ResolvedJavaType ) referencedType );
1693
1701
if (invoke != null ) {
1694
1702
invoke .callTarget ().setReferencedType ((ResolvedJavaType ) referencedType );
1695
1703
}
@@ -1732,7 +1740,7 @@ protected void genInvokeVirtual(ResolvedJavaMethod resolvedTarget) {
1732
1740
}
1733
1741
1734
1742
ValueNode [] args = frameState .popArguments (resolvedTarget .getSignature ().getParameterCount (true ));
1735
- appendInvoke (InvokeKind .Virtual , resolvedTarget , args );
1743
+ appendInvoke (InvokeKind .Virtual , resolvedTarget , args , null );
1736
1744
}
1737
1745
1738
1746
private boolean genDynamicInvokeHelper (ResolvedJavaMethod target , int cpi , int opcode ) {
@@ -1751,9 +1759,9 @@ private boolean genDynamicInvokeHelper(ResolvedJavaMethod target, int cpi, int o
1751
1759
boolean hasReceiver = (opcode == INVOKEDYNAMIC ) ? false : !target .isStatic ();
1752
1760
ValueNode [] args = frameState .popArguments (target .getSignature ().getParameterCount (hasReceiver ));
1753
1761
if (hasReceiver ) {
1754
- appendInvoke (InvokeKind .Virtual , target , args );
1762
+ appendInvoke (InvokeKind .Virtual , target , args , null );
1755
1763
} else {
1756
- appendInvoke (InvokeKind .Static , target , args );
1764
+ appendInvoke (InvokeKind .Static , target , args , null );
1757
1765
}
1758
1766
1759
1767
return true ;
@@ -1769,7 +1777,7 @@ void genInvokeSpecial(JavaMethod target) {
1769
1777
assert target != null ;
1770
1778
assert target .getSignature () != null ;
1771
1779
ValueNode [] args = frameState .popArguments (target .getSignature ().getParameterCount (true ));
1772
- appendInvoke (InvokeKind .Special , (ResolvedJavaMethod ) target , args );
1780
+ appendInvoke (InvokeKind .Special , (ResolvedJavaMethod ) target , args , null );
1773
1781
} else {
1774
1782
handleUnresolvedInvoke (target , InvokeKind .Special );
1775
1783
}
@@ -1816,11 +1824,16 @@ public JavaType getInvokeReturnType() {
1816
1824
1817
1825
@ Override
1818
1826
public Invoke handleReplacedInvoke (InvokeKind invokeKind , ResolvedJavaMethod targetMethod , ValueNode [] args , boolean inlineEverything ) {
1827
+ GraalError .guarantee (invokeKind != InvokeKind .Interface , "Interface invoke needs a referencedType" );
1828
+ return handleReplacedInvoke (invokeKind , targetMethod , args , inlineEverything , null );
1829
+ }
1830
+
1831
+ public Invoke handleReplacedInvoke (InvokeKind invokeKind , ResolvedJavaMethod targetMethod , ValueNode [] args , boolean inlineEverything , ResolvedJavaType referencedType ) {
1819
1832
boolean previous = forceInliningEverything ;
1820
1833
forceInliningEverything = previous || inlineEverything ;
1821
1834
try {
1822
1835
setBciCanBeDuplicated (true );
1823
- return appendInvoke (invokeKind , targetMethod , args );
1836
+ return appendInvoke (invokeKind , targetMethod , args , referencedType );
1824
1837
} finally {
1825
1838
setBciCanBeDuplicated (false );
1826
1839
forceInliningEverything = previous ;
@@ -1834,7 +1847,20 @@ public void handleReplacedInvoke(CallTargetNode callTarget, JavaKind resultType)
1834
1847
createNonInlinedInvoke (exceptionEdgeAction , bci (), callTarget , resultType );
1835
1848
}
1836
1849
1837
- protected Invoke appendInvoke (InvokeKind initialInvokeKind , ResolvedJavaMethod initialTargetMethod , ValueNode [] args ) {
1850
+ protected Invoke appendInvoke (InvokeKind initialInvokeKind , ResolvedJavaMethod initialTargetMethod , ValueNode [] args , ResolvedJavaType referencedType ) {
1851
+ if (!parsingIntrinsic () && DeoptALot .getValue (options )) {
1852
+ append (new DeoptimizeNode (DeoptimizationAction .None , RuntimeConstraint ));
1853
+ JavaKind resultType = initialTargetMethod .getSignature ().getReturnKind ();
1854
+ frameState .pushReturn (resultType , ConstantNode .defaultForKind (resultType , graph ));
1855
+ return null ;
1856
+ }
1857
+
1858
+ if (initialInvokeKind .hasReceiver ()) {
1859
+ args [0 ] = maybeEmitExplicitNullCheck (args [0 ]);
1860
+ /* This check must be done before any de-virtualization of the invoke. */
1861
+ args [0 ] = maybeEmitIncompatibleClassChangeErrorCheck (args [0 ], initialInvokeKind , referencedType );
1862
+ }
1863
+
1838
1864
ResolvedJavaMethod targetMethod = initialTargetMethod ;
1839
1865
InvokeKind invokeKind = initialInvokeKind ;
1840
1866
if (initialInvokeKind .isIndirect ()) {
@@ -1847,16 +1873,7 @@ protected Invoke appendInvoke(InvokeKind initialInvokeKind, ResolvedJavaMethod i
1847
1873
}
1848
1874
1849
1875
JavaKind resultType = targetMethod .getSignature ().getReturnKind ();
1850
- if (!parsingIntrinsic () && DeoptALot .getValue (options )) {
1851
- append (new DeoptimizeNode (DeoptimizationAction .None , RuntimeConstraint ));
1852
- frameState .pushReturn (resultType , ConstantNode .defaultForKind (resultType , graph ));
1853
- return null ;
1854
- }
1855
-
1856
1876
JavaType returnType = maybeEagerlyResolve (targetMethod .getSignature ().getReturnType (method .getDeclaringClass ()), targetMethod .getDeclaringClass ());
1857
- if (invokeKind .hasReceiver ()) {
1858
- args [0 ] = maybeEmitExplicitNullCheck (args [0 ]);
1859
- }
1860
1877
1861
1878
if (initialInvokeKind == InvokeKind .Special && !targetMethod .isConstructor ()) {
1862
1879
emitCheckForInvokeSuperSpecial (args );
@@ -1956,11 +1973,7 @@ protected Invoke appendInvoke(InvokeKind initialInvokeKind, ResolvedJavaMethod i
1956
1973
* declared in a interface
1957
1974
*/
1958
1975
private void emitCheckForDeclaringClassChange (ResolvedJavaType declaringClass , ValueNode [] args ) {
1959
- ValueNode receiver = args [0 ];
1960
- TypeReference checkedType = TypeReference .createTrusted (graph .getAssumptions (), declaringClass );
1961
- LogicNode condition = genUnique (createInstanceOf (checkedType , receiver , null ));
1962
- FixedGuardNode fixedGuard = append (new FixedGuardNode (condition , ClassCastException , None , false ));
1963
- args [0 ] = append (PiNode .create (receiver , StampFactory .object (checkedType , true ), fixedGuard ));
1976
+ args [0 ] = emitIncompatibleClassChangeCheck (args [0 ], declaringClass );
1964
1977
}
1965
1978
1966
1979
/**
@@ -1977,14 +1990,22 @@ protected void emitCheckForInvokeSuperSpecial(ValueNode[] args) {
1977
1990
ResolvedJavaType callingClass = method .getDeclaringClass ();
1978
1991
callingClass = getHostClass (callingClass );
1979
1992
if (callingClass .isInterface ()) {
1980
- ValueNode receiver = args [0 ];
1981
- TypeReference checkedType = TypeReference .createTrusted (graph .getAssumptions (), callingClass );
1982
- LogicNode condition = genUnique (createInstanceOf (checkedType , receiver , null ));
1983
- FixedGuardNode fixedGuard = append (new FixedGuardNode (condition , ClassCastException , None , false ));
1984
- args [0 ] = append (PiNode .create (receiver , StampFactory .object (checkedType , true ), fixedGuard ));
1993
+ args [0 ] = emitIncompatibleClassChangeCheck (args [0 ], callingClass );
1985
1994
}
1986
1995
}
1987
1996
1997
+ protected ValueNode emitIncompatibleClassChangeCheck (ValueNode object , ResolvedJavaType checkedType ) {
1998
+ TypeReference checkedTypeRef = TypeReference .createTrusted (graph .getAssumptions (), checkedType );
1999
+ LogicNode condition = genUnique (InstanceOfNode .create (checkedTypeRef , object ));
2000
+ ValueNode guardingNode ;
2001
+ if (needsExplicitException ()) {
2002
+ guardingNode = emitBytecodeExceptionCheck (condition , true , BytecodeExceptionKind .INCOMPATIBLE_CLASS_CHANGE );
2003
+ } else {
2004
+ guardingNode = append (new FixedGuardNode (condition , ClassCastException , None , false ));
2005
+ }
2006
+ return append (PiNode .create (object , StampFactory .object (checkedTypeRef , true ), guardingNode ));
2007
+ }
2008
+
1988
2009
@ SuppressWarnings ("deprecation" )
1989
2010
private static ResolvedJavaType getHostClass (ResolvedJavaType type ) {
1990
2011
ResolvedJavaType hostClass = type .getHostClass ();
@@ -4723,6 +4744,10 @@ protected boolean needsExplicitStoreCheckException(ValueNode array, ValueNode va
4723
4744
return needsExplicitException ();
4724
4745
}
4725
4746
4747
+ protected boolean needsIncompatibleClassChangeErrorCheck () {
4748
+ return false ;
4749
+ }
4750
+
4726
4751
@ Override
4727
4752
public boolean needsExplicitException () {
4728
4753
BytecodeExceptionMode exceptionMode = graphBuilderConfig .getBytecodeExceptionMode ();
0 commit comments