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 package runtime.valhalla.valuetypes;
25
26 import jdk.test.lib.Asserts;
27
28 /*
29 * @test VWithFieldTest
30 * @summary vwithfield bytecode test
31 * @library /testlibrary /
32 * @run main/othervm -noverify -Xint runtime.valhalla.valuetypes.VWithFieldTest
33 */
34
35 public class VWithFieldTest {
36
37 static __ByValue final class Point {
38 final private int x;
39 final private int y;
40
41 __ValueFactory static Point make(int x, int y) {
42 Point p = __MakeDefault Point();
43 Asserts.assertEquals(p.x, 0, "invalid x default value");
44 Asserts.assertEquals(p.y, 0, "invalid y default value");
45 p.x = x;
46 Asserts.assertEquals(p.x, x, "invalid x value");
59 public int getX() {
60 return x;
61 }
62
63 __ValueFactory static Point setX(Point p, int x) {
64 p.x = x;
65 return p;
66 }
67
68 public int getY() {
69 return y;
70 }
71
72 __ValueFactory static Point setY(Point p, int y) {
73 p.y = y;
74 return p;
75 }
76 }
77
78 public static void main(String[] args) {
79 creationTest();
80 creationTest();
81 witherTest();
82 witherTest();
83 }
84
85 static void creationTest() {
86 Point p = Point.make(10,20);
87 Asserts.assertEquals(p.x, 10, "invalid x value");
88 Asserts.assertEquals(p.y, 20, "invalid y value");
89 }
90
91 static void witherTest() {
92 Point p1 = Point.make(2,12);
93 Asserts.assertEquals(p1.x, 2, "invalid x value");
94 Asserts.assertEquals(p1.y, 12, "invalid y value");
95 Point p2 = Point.setX(p1,3);
96 Asserts.assertEquals(p2.x, 3, "invalid x value");
97 Asserts.assertEquals(p2.y, 12, "invalid y value");
98 Point p3 = Point.setY(p2, 14);
99 Asserts.assertEquals(p3.x, 3, "invalid x value");
100 Asserts.assertEquals(p3.y, 14, "invalid y value");
101 }
102
103 }
|
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 package runtime.valhalla.valuetypes;
25
26 import java.lang.invoke.*;
27 import jdk.experimental.value.*;
28 import jdk.test.lib.*;
29 import static jdk.test.lib.Asserts.*;
30
31 /*
32 * @test VWithFieldTest
33 * @summary vwithfield bytecode test
34 * @library /testlibrary /
35 * @run main/othervm -noverify -Xint runtime.valhalla.valuetypes.VWithFieldTest
36 */
37
38 public class VWithFieldTest {
39
40 static __ByValue final class Point {
41 final private int x;
42 final private int y;
43
44 __ValueFactory static Point make(int x, int y) {
45 Point p = __MakeDefault Point();
46 Asserts.assertEquals(p.x, 0, "invalid x default value");
47 Asserts.assertEquals(p.y, 0, "invalid y default value");
48 p.x = x;
49 Asserts.assertEquals(p.x, x, "invalid x value");
62 public int getX() {
63 return x;
64 }
65
66 __ValueFactory static Point setX(Point p, int x) {
67 p.x = x;
68 return p;
69 }
70
71 public int getY() {
72 return y;
73 }
74
75 __ValueFactory static Point setY(Point p, int y) {
76 p.y = y;
77 return p;
78 }
79 }
80
81 public static void main(String[] args) {
82 witherViaVvt();
83 witherViaAnonymousClass();
84 witherViaMvt();
85 }
86
87 static void witherViaVvt() {
88 creationTest();
89 witherTest();
90 }
91
92 static void creationTest() {
93 Point p = Point.make(10,20);
94 Asserts.assertEquals(p.x, 10, "invalid x value");
95 Asserts.assertEquals(p.y, 20, "invalid y value");
96 }
97
98 static void witherTest() {
99 Point p1 = Point.make(2,12);
100 Asserts.assertEquals(p1.x, 2, "invalid x value");
101 Asserts.assertEquals(p1.y, 12, "invalid y value");
102 Point p2 = Point.setX(p1,3);
103 Asserts.assertEquals(p2.x, 3, "invalid x value");
104 Asserts.assertEquals(p2.y, 12, "invalid y value");
105 Point p3 = Point.setY(p2, 14);
106 Asserts.assertEquals(p3.x, 3, "invalid x value");
107 Asserts.assertEquals(p3.y, 14, "invalid y value");
108 }
109
110
111 @jvm.internal.value.DeriveValueType
112 static final class PointVcc {
113 // "package-private" access: Test access from anonymous class
114 // "final": Test vwithfield opcode issued from outside the (DVT) class
115 final int x;
116 final int y;
117
118 private PointVcc(int x, int y) {
119 this.x = x;
120 this.y = y;
121 }
122
123 /**
124 * MVT fields are final by definition, want to maintain full control of field values
125 * ACC_FINAL states only the code that owns the fields may do this.
126 *
127 * MVT needs a small hole, whereby the lookup klass->host_class == VCC, may modify
128 * DVT klass->derive_value_type_klass(). See: LinkResolver::resolve_field().
129 *
130 * But we are still left with this ugly code pattern, i.e. the method handle lookup
131 * must be VCC..."ugly" but enforces the semantics of ACC_FINAL.
132 *
133 * ValueType.findWither() risks breaking code wishing to maintain value invariants,
134 * by exposing the wither method handle to arbitrary code.
135 *
136 * - There appears to be a discrepancy between the ValueType.findWither() API and
137 * "Shady Values" document. Missing "Class<?> refc" (see MethodHandles.Lookup.findSetter()).
138 * It could be argued that this dependency on hiding "refc" is too weak/dangerous.
139 */
140 public static MethodHandle dvtCreator() {
141 Class<?> dvtClass = (Class<?>) ValueType.forClass(PointVcc.class).valueClass();
142 return MethodHandleBuilder.
143 loadCode(MethodHandles.lookup(),
144 "vdefaultWithXWithY",
145 MethodType.methodType(dvtClass, Integer.TYPE, Integer.TYPE),
146 CODE-> {
147 CODE
148 .vdefault(dvtClass)
149 .iload(0)
150 .vwithfield(dvtClass, "x", "I")
151 .iload(1)
152 .vwithfield(dvtClass, "y", "I")
153 .vreturn();
154 });
155 }
156
157 public String toString() {
158 return "x=" + x + " y=" + y;
159 }
160 }
161
162 static void witherViaAnonymousClass() {
163 try {
164 Class<?> vccClass = (Class<?>) PointVcc.class;
165 ValueType<?> vt = ValueType.forClass(vccClass);
166 Class<?> dvtClass = vt.valueClass();
167
168 int x = 7;
169 int y = 4711;
170
171 MethodHandle boxMh = MethodHandleBuilder.
172 loadCode(MethodHandles.lookup(),
173 "boxPointVcc",
174 MethodType.methodType(vccClass, dvtClass),
175 CODE-> { CODE.vload(0).vbox(vccClass).areturn(); });
176 PointVcc point = (PointVcc) MethodHandles.filterReturnValue(PointVcc.dvtCreator(),
177 boxMh).invoke(x, y);
178 assertTrue(point.x == x);
179 assertTrue(point.y == y);
180
181 try { // Try to modify final fields from another class, should fail...
182 PointVcc apoint = (PointVcc) MethodHandleBuilder.
183 loadCode(MethodHandles.lookup(),
184 "vdefaultWithXWithY",
185 MethodType.methodType(vccClass, Integer.TYPE, Integer.TYPE),
186 CODE-> {
187 CODE
188 .vdefault(dvtClass)
189 .iload(0)
190 .vwithfield(dvtClass, "x", "I")
191 .iload(1)
192 .vwithfield(dvtClass, "y", "I")
193 .vbox(vccClass)
194 .areturn();
195 }).invoke(x, y);
196 throw new RuntimeException("Expected IllegalAccessError");
197 }
198 catch (IllegalAccessError illAccErr) {}
199 }
200 catch (Throwable t) {
201 throw new RuntimeException("witherViaAnonymousClass", t);
202 }
203 }
204
205 static void witherViaMvt() {
206 try {
207 Class<?> vccClass = (Class<?>) PointVcc.class;
208 ValueType<?> vt = ValueType.forClass(vccClass);
209 Class<?> dvtClass = vt.valueClass();
210
211 int x = 4711;
212 int y = 13;
213
214 MethodHandle defValue = vt.defaultValueConstant();
215 MethodHandle setX = vt.findWither("x", Integer.TYPE);
216 MethodHandle setY = vt.findWither("y", Integer.TYPE);
217 MethodHandle boxValue = vt.box();
218
219 // Chain these VT methods up to be "VT.defaultValueConstant().setX(x).setY(y).box()"...
220 MethodHandle createX = MethodHandles.collectArguments(setX, 0, defValue);
221 MethodHandle updateY = MethodHandles.collectArguments(setY, 0, createX);
222 MethodHandle boxed = MethodHandles.filterReturnValue(updateY, boxValue);
223
224 PointVcc point = (PointVcc) boxed.invoke(x, y);
225 assertTrue(point.x == x);
226 assertTrue(point.y == y);
227 }
228 catch (Throwable t) {
229 throw new RuntimeException("witherViaMvt", t);
230 }
231 }
232 }
|