Skip to content

Commit 27acfb6

Browse files
author
Ian Graves
committedMar 2, 2024
Assert code modeling
Reviewed-by: psandoz
1 parent 03f40c2 commit 27acfb6

File tree

3 files changed

+170
-0
lines changed

3 files changed

+170
-0
lines changed
 

‎src/java.base/share/classes/java/lang/reflect/code/op/CoreOps.java

+58
Original file line numberDiff line numberDiff line change
@@ -792,6 +792,55 @@ public TypeElement resultType() {
792792
}
793793
}
794794

795+
/**
796+
* The assertion operation. Supporting assertions in statement form.
797+
*/
798+
@OpDeclaration(AssertOp.NAME)
799+
public static final class AssertOp extends OpWithDefinition implements Op.Nested {
800+
public static final String NAME = "assert";
801+
public final List<Body> bodies;
802+
803+
public AssertOp(OpDefinition def) {
804+
super(def);
805+
var bodies = def.bodyDefinitions().stream().map(b -> b.build(this)).toList();
806+
checkBodies(bodies);
807+
this.bodies = bodies;
808+
}
809+
810+
public AssertOp(List<Body.Builder> bodies) {
811+
super(NAME, List.of());
812+
checkBodies(bodies);
813+
this.bodies = bodies.stream().map(b -> b.build(this)).toList();
814+
}
815+
816+
AssertOp(AssertOp that, CopyContext cc, OpTransformer ot) {
817+
818+
super(that, cc);
819+
this.bodies = that.bodies.stream().map(b -> b.transform(cc, ot).build(this)).toList();
820+
}
821+
822+
private void checkBodies(List<?> bodies) {
823+
if (bodies.size() != 1 && bodies.size() != 2) {
824+
throw new IllegalArgumentException("Assert must have one or two bodies.");
825+
}
826+
}
827+
828+
@Override
829+
public Op transform(CopyContext cc, OpTransformer ot) {
830+
return new AssertOp(this, cc, ot);
831+
}
832+
833+
@Override
834+
public TypeElement resultType() {
835+
return JavaType.VOID;
836+
}
837+
838+
@Override
839+
public List<Body> bodies() {
840+
return this.bodies;
841+
}
842+
}
843+
795844
/**
796845
* The terminating unreachable operation.
797846
* <p>
@@ -3106,6 +3155,15 @@ public static YieldOp _yield(Value yieldValue) {
31063155
return new YieldOp(List.of(yieldValue));
31073156
}
31083157

3158+
/**
3159+
* Creates an assert operation.
3160+
* @param bodies the nested bodies
3161+
* @return the assert operation
3162+
*/
3163+
public static AssertOp _assert(List<Body.Builder> bodies) {
3164+
return new AssertOp(bodies);
3165+
}
3166+
31093167
/**
31103168
* Creates an unconditional break operation.
31113169
* @param target the jump target

‎src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ReflectMethods.java

+39
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@
6565
import com.sun.tools.javac.tree.JCTree.JCNewClass;
6666
import com.sun.tools.javac.tree.JCTree.JCReturn;
6767
import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
68+
import com.sun.tools.javac.tree.JCTree.JCAssert;
6869
import com.sun.tools.javac.tree.JCTree.Tag;
6970
import com.sun.tools.javac.tree.TreeInfo;
7071
import com.sun.tools.javac.tree.TreeMaker;
@@ -439,6 +440,7 @@ class BodyScanner extends FilterScanner {
439440
Tag.BLOCK, Tag.IF, Tag.WHILELOOP, Tag.DOLOOP, Tag.FOREACHLOOP, Tag.FORLOOP, Tag.TRY,
440441
Tag.SWITCH_EXPRESSION, Tag.YIELD,
441442
Tag.CONDEXPR,
443+
Tag.ASSERT,
442444
Tag.LABELLED,
443445
Tag.SKIP,
444446
Tag.TYPEARRAY);
@@ -1814,6 +1816,43 @@ private Type adaptBottom(Type type) {
18141816
type;
18151817
}
18161818

1819+
@Override
1820+
public void visitAssert(JCAssert tree) {
1821+
// assert <cond:body1> [detail:body2]
1822+
1823+
List<Body.Builder> bodies = new ArrayList<>();
1824+
JCTree.JCExpression cond = TreeInfo.skipParens(tree.cond);
1825+
1826+
// Push condition
1827+
pushBody(cond,
1828+
FunctionType.functionType(JavaType.BOOLEAN));
1829+
Value condVal = toValue(cond);
1830+
1831+
// Yield the boolean result of the condition
1832+
append(CoreOps._yield(condVal));
1833+
bodies.add(stack.body);
1834+
1835+
// Pop condition
1836+
popBody();
1837+
1838+
if (tree.detail != null) {
1839+
JCTree.JCExpression detail = TreeInfo.skipParens(tree.detail);
1840+
1841+
pushBody(detail,
1842+
FunctionType.functionType(JavaType.J_L_STRING));
1843+
Value detailVal = toValue(detail);
1844+
1845+
append(CoreOps._yield(detailVal));
1846+
bodies.add(stack.body);
1847+
1848+
//Pop detail
1849+
popBody();
1850+
}
1851+
1852+
result = append(CoreOps._assert(bodies));
1853+
1854+
}
1855+
18171856
@Override
18181857
public void visitBlock(JCTree.JCBlock tree) {
18191858
if (stack.tree == tree) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/*
2+
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
24+
import java.lang.runtime.CodeReflection;
25+
26+
/*
27+
* @test
28+
* @summary Smoke test for code reflection with array access.
29+
* @build AssertTest
30+
* @build CodeReflectionTester
31+
* @run main CodeReflectionTester AssertTest
32+
*/
33+
public class AssertTest {
34+
35+
@CodeReflection
36+
@IR("""
37+
func @"assertTest" (%0 : int)void -> {
38+
%1 : Var<int> = var %0 @"i";
39+
assert
40+
()boolean -> {
41+
%2 : int = var.load %1;
42+
%3 : int = constant @"1";
43+
%4 : boolean = eq %2 %3;
44+
yield %4;
45+
}
46+
()java.lang.String -> {
47+
%5 : java.lang.String = constant @"i does not equal 1";
48+
yield %5;
49+
};
50+
return;
51+
};
52+
""")
53+
public static void assertTest(int i) {
54+
assert (i == 1) : "i does not equal 1";
55+
}
56+
57+
@CodeReflection
58+
@IR("""
59+
func @"assertTest2" (%0 : int)void -> {
60+
%1 : Var<int> = var %0 @"i";
61+
assert ()boolean -> {
62+
%2 : int = var.load %1;
63+
%3 : int = constant @"1";
64+
%4 : boolean = eq %2 %3;
65+
yield %4;
66+
};
67+
return;
68+
};
69+
""")
70+
public static void assertTest2(int i) {
71+
assert (i == 1);
72+
}
73+
}

0 commit comments

Comments
 (0)
Please sign in to comment.