@@ -1595,6 +1595,14 @@ protected GuardingNode maybeEmitExplicitStoreCheck(ValueNode array, JavaKind ele
15951595 return emitBytecodeExceptionCheck (condition , true , BytecodeExceptionKind .ARRAY_STORE , value );
15961596 }
15971597
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+
15981606 @ Override
15991607 public AbstractBeginNode emitBytecodeExceptionCheck (LogicNode condition , boolean passingOnTrue , BytecodeExceptionKind exceptionKind , ValueNode ... arguments ) {
16001608 AbstractBeginNode result = GraphBuilderContext .super .emitBytecodeExceptionCheck (condition , passingOnTrue , exceptionKind , arguments );
@@ -1664,7 +1672,7 @@ void genInvokeStatic(JavaMethod target) {
16641672 }
16651673
16661674 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 );
16681676 if (invoke != null && classInit [0 ] != null ) {
16691677 invoke .setClassInit (classInit [0 ]);
16701678 }
@@ -1689,7 +1697,7 @@ protected void genInvokeInterface(int cpi, int opcode) {
16891697 protected void genInvokeInterface (JavaType referencedType , JavaMethod target ) {
16901698 if (callTargetIsResolved (target ) && (referencedType == null || referencedType instanceof ResolvedJavaType )) {
16911699 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 );
16931701 if (invoke != null ) {
16941702 invoke .callTarget ().setReferencedType ((ResolvedJavaType ) referencedType );
16951703 }
@@ -1732,7 +1740,7 @@ protected void genInvokeVirtual(ResolvedJavaMethod resolvedTarget) {
17321740 }
17331741
17341742 ValueNode [] args = frameState .popArguments (resolvedTarget .getSignature ().getParameterCount (true ));
1735- appendInvoke (InvokeKind .Virtual , resolvedTarget , args );
1743+ appendInvoke (InvokeKind .Virtual , resolvedTarget , args , null );
17361744 }
17371745
17381746 private boolean genDynamicInvokeHelper (ResolvedJavaMethod target , int cpi , int opcode ) {
@@ -1751,9 +1759,9 @@ private boolean genDynamicInvokeHelper(ResolvedJavaMethod target, int cpi, int o
17511759 boolean hasReceiver = (opcode == INVOKEDYNAMIC ) ? false : !target .isStatic ();
17521760 ValueNode [] args = frameState .popArguments (target .getSignature ().getParameterCount (hasReceiver ));
17531761 if (hasReceiver ) {
1754- appendInvoke (InvokeKind .Virtual , target , args );
1762+ appendInvoke (InvokeKind .Virtual , target , args , null );
17551763 } else {
1756- appendInvoke (InvokeKind .Static , target , args );
1764+ appendInvoke (InvokeKind .Static , target , args , null );
17571765 }
17581766
17591767 return true ;
@@ -1769,7 +1777,7 @@ void genInvokeSpecial(JavaMethod target) {
17691777 assert target != null ;
17701778 assert target .getSignature () != null ;
17711779 ValueNode [] args = frameState .popArguments (target .getSignature ().getParameterCount (true ));
1772- appendInvoke (InvokeKind .Special , (ResolvedJavaMethod ) target , args );
1780+ appendInvoke (InvokeKind .Special , (ResolvedJavaMethod ) target , args , null );
17731781 } else {
17741782 handleUnresolvedInvoke (target , InvokeKind .Special );
17751783 }
@@ -1816,11 +1824,16 @@ public JavaType getInvokeReturnType() {
18161824
18171825 @ Override
18181826 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 ) {
18191832 boolean previous = forceInliningEverything ;
18201833 forceInliningEverything = previous || inlineEverything ;
18211834 try {
18221835 setBciCanBeDuplicated (true );
1823- return appendInvoke (invokeKind , targetMethod , args );
1836+ return appendInvoke (invokeKind , targetMethod , args , referencedType );
18241837 } finally {
18251838 setBciCanBeDuplicated (false );
18261839 forceInliningEverything = previous ;
@@ -1834,7 +1847,20 @@ public void handleReplacedInvoke(CallTargetNode callTarget, JavaKind resultType)
18341847 createNonInlinedInvoke (exceptionEdgeAction , bci (), callTarget , resultType );
18351848 }
18361849
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+
18381864 ResolvedJavaMethod targetMethod = initialTargetMethod ;
18391865 InvokeKind invokeKind = initialInvokeKind ;
18401866 if (initialInvokeKind .isIndirect ()) {
@@ -1847,16 +1873,7 @@ protected Invoke appendInvoke(InvokeKind initialInvokeKind, ResolvedJavaMethod i
18471873 }
18481874
18491875 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-
18561876 JavaType returnType = maybeEagerlyResolve (targetMethod .getSignature ().getReturnType (method .getDeclaringClass ()), targetMethod .getDeclaringClass ());
1857- if (invokeKind .hasReceiver ()) {
1858- args [0 ] = maybeEmitExplicitNullCheck (args [0 ]);
1859- }
18601877
18611878 if (initialInvokeKind == InvokeKind .Special && !targetMethod .isConstructor ()) {
18621879 emitCheckForInvokeSuperSpecial (args );
@@ -1956,11 +1973,7 @@ protected Invoke appendInvoke(InvokeKind initialInvokeKind, ResolvedJavaMethod i
19561973 * declared in a interface
19571974 */
19581975 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 );
19641977 }
19651978
19661979 /**
@@ -1977,14 +1990,22 @@ protected void emitCheckForInvokeSuperSpecial(ValueNode[] args) {
19771990 ResolvedJavaType callingClass = method .getDeclaringClass ();
19781991 callingClass = getHostClass (callingClass );
19791992 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 );
19851994 }
19861995 }
19871996
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+
19882009 @ SuppressWarnings ("deprecation" )
19892010 private static ResolvedJavaType getHostClass (ResolvedJavaType type ) {
19902011 ResolvedJavaType hostClass = type .getHostClass ();
@@ -4723,6 +4744,10 @@ protected boolean needsExplicitStoreCheckException(ValueNode array, ValueNode va
47234744 return needsExplicitException ();
47244745 }
47254746
4747+ protected boolean needsIncompatibleClassChangeErrorCheck () {
4748+ return false ;
4749+ }
4750+
47264751 @ Override
47274752 public boolean needsExplicitException () {
47284753 BytecodeExceptionMode exceptionMode = graphBuilderConfig .getBytecodeExceptionMode ();
0 commit comments