27 import java.lang.annotation.ElementType; |
27 import java.lang.annotation.ElementType; |
28 import java.lang.annotation.Retention; |
28 import java.lang.annotation.Retention; |
29 import java.lang.annotation.RetentionPolicy; |
29 import java.lang.annotation.RetentionPolicy; |
30 import java.lang.annotation.Target; |
30 import java.lang.annotation.Target; |
31 |
31 |
32 import org.graalvm.compiler.core.common.LocationIdentity; |
32 import org.graalvm.api.word.ComparableWord; |
|
33 import org.graalvm.api.word.LocationIdentity; |
|
34 import org.graalvm.api.word.Pointer; |
|
35 import org.graalvm.api.word.Signed; |
|
36 import org.graalvm.api.word.Unsigned; |
|
37 import org.graalvm.api.word.WordBase; |
|
38 import org.graalvm.api.word.WordFactory; |
33 import org.graalvm.compiler.core.common.calc.Condition; |
39 import org.graalvm.compiler.core.common.calc.Condition; |
34 import org.graalvm.compiler.core.common.calc.UnsignedMath; |
40 import org.graalvm.compiler.core.common.calc.UnsignedMath; |
35 import org.graalvm.compiler.debug.GraalError; |
41 import org.graalvm.compiler.debug.GraalError; |
36 import org.graalvm.compiler.nodes.ValueNode; |
42 import org.graalvm.compiler.nodes.ValueNode; |
37 import org.graalvm.compiler.nodes.calc.AddNode; |
43 import org.graalvm.compiler.nodes.calc.AddNode; |
48 import org.graalvm.compiler.nodes.calc.UnsignedRightShiftNode; |
54 import org.graalvm.compiler.nodes.calc.UnsignedRightShiftNode; |
49 import org.graalvm.compiler.nodes.calc.XorNode; |
55 import org.graalvm.compiler.nodes.calc.XorNode; |
50 import org.graalvm.compiler.nodes.memory.HeapAccess.BarrierType; |
56 import org.graalvm.compiler.nodes.memory.HeapAccess.BarrierType; |
51 import org.graalvm.compiler.nodes.memory.address.AddressNode.Address; |
57 import org.graalvm.compiler.nodes.memory.address.AddressNode.Address; |
52 |
58 |
53 public abstract class Word implements Signed, Unsigned, Pointer { |
59 public abstract class Word extends WordFactory implements Signed, Unsigned, Pointer { |
54 |
60 |
55 /** |
61 /** |
56 * Links a method to a canonical operation represented by an {@link Opcode} val. |
62 * Links a method to a canonical operation represented by an {@link Opcode} val. |
57 */ |
63 */ |
58 @Retention(RetentionPolicy.RUNTIME) |
64 @Retention(RetentionPolicy.RUNTIME) |
69 } |
75 } |
70 |
76 |
71 /** |
77 /** |
72 * The canonical {@link Operation} represented by a method in the {@link Word} class. |
78 * The canonical {@link Operation} represented by a method in the {@link Word} class. |
73 */ |
79 */ |
74 // @formatter:off |
80 public enum Opcode { |
75 public enum Opcode { |
81 NODE_CLASS, |
76 NODE_CLASS, |
82 COMPARISON, |
77 COMPARISON, |
83 NOT, |
78 NOT, |
84 READ_POINTER, |
79 READ_POINTER, |
85 READ_OBJECT, |
80 READ_OBJECT, |
86 READ_BARRIERED, |
81 READ_BARRIERED, |
87 READ_HEAP, |
82 READ_HEAP, |
88 WRITE_POINTER, |
83 WRITE_POINTER, |
89 WRITE_OBJECT, |
84 WRITE_OBJECT, |
90 WRITE_BARRIERED, |
85 WRITE_BARRIERED, |
91 CAS_POINTER, |
86 CAS_POINTER, |
92 INITIALIZE, |
87 INITIALIZE, |
93 FROM_ADDRESS, |
88 ZERO, |
94 OBJECT_TO_TRACKED, |
89 FROM_UNSIGNED, |
95 OBJECT_TO_UNTRACKED, |
90 FROM_SIGNED, |
96 TO_OBJECT, |
91 FROM_ADDRESS, |
97 TO_OBJECT_NON_NULL, |
92 OBJECT_TO_TRACKED, |
98 TO_RAW_VALUE, |
93 OBJECT_TO_UNTRACKED, |
99 } |
94 TO_OBJECT, |
100 |
95 TO_OBJECT_NON_NULL, |
101 public static class BoxFactoryImpl implements BoxFactory { |
96 TO_RAW_VALUE, |
102 @SuppressWarnings("unchecked") |
97 } |
103 @Override |
98 // @formatter:on |
104 public <T extends WordBase> T box(long val) { |
|
105 return (T) HostedWord.boxLong(val); |
|
106 } |
|
107 } |
99 |
108 |
100 /* |
109 /* |
101 * Outside users should use the different signed() and unsigned() methods to ensure proper |
110 * Outside users must use the different signed() and unsigned() methods to ensure proper |
102 * expansion of 32-bit values on 64-bit systems. |
111 * expansion of 32-bit values on 64-bit systems. |
103 */ |
112 */ |
104 private static Word box(long val) { |
113 @SuppressWarnings("unchecked") |
105 return HostedWord.boxLong(val); |
114 private static <T extends WordBase> T box(long val) { |
|
115 return (T) HostedWord.boxLong(val); |
106 } |
116 } |
107 |
117 |
108 protected abstract long unbox(); |
118 protected abstract long unbox(); |
109 |
119 |
110 private static Word intParam(int val) { |
120 private static Word intParam(int val) { |
111 return box(val); |
|
112 } |
|
113 |
|
114 /** |
|
115 * The constant 0, i.e., the word with no bits set. There is no difference between a signed and |
|
116 * unsigned zero. |
|
117 * |
|
118 * @return the constant 0. |
|
119 */ |
|
120 @Operation(opcode = Opcode.ZERO) |
|
121 public static Word zero() { |
|
122 return box(0L); |
|
123 } |
|
124 |
|
125 /** |
|
126 * Unsafe conversion from a Java long value to a Word. The parameter is treated as an unsigned |
|
127 * 64-bit value (in contrast to the semantics of a Java long). |
|
128 * |
|
129 * @param val a 64 bit unsigned value |
|
130 * @return the value cast to Word |
|
131 */ |
|
132 @Operation(opcode = Opcode.FROM_UNSIGNED) |
|
133 public static Word unsigned(long val) { |
|
134 return box(val); |
|
135 } |
|
136 |
|
137 /** |
|
138 * Unsafe conversion from a Java long value to a {@link PointerBase pointer}. The parameter is |
|
139 * treated as an unsigned 64-bit value (in contrast to the semantics of a Java long). |
|
140 * |
|
141 * @param val a 64 bit unsigned value |
|
142 * @return the value cast to PointerBase |
|
143 */ |
|
144 @Operation(opcode = Opcode.FROM_UNSIGNED) |
|
145 @SuppressWarnings("unchecked") |
|
146 public static <T extends PointerBase> T pointer(long val) { |
|
147 return (T) box(val); |
|
148 } |
|
149 |
|
150 /** |
|
151 * Unsafe conversion from a Java int value to a Word. The parameter is treated as an unsigned |
|
152 * 32-bit value (in contrast to the semantics of a Java int). |
|
153 * |
|
154 * @param val a 32 bit unsigned value |
|
155 * @return the value cast to Word |
|
156 */ |
|
157 @Operation(opcode = Opcode.FROM_UNSIGNED) |
|
158 public static Word unsigned(int val) { |
|
159 return box(val & 0xffffffffL); |
|
160 } |
|
161 |
|
162 /** |
|
163 * Unsafe conversion from a Java long value to a Word. The parameter is treated as a signed |
|
164 * 64-bit value (unchanged semantics of a Java long). |
|
165 * |
|
166 * @param val a 64 bit signed value |
|
167 * @return the value cast to Word |
|
168 */ |
|
169 @Operation(opcode = Opcode.FROM_SIGNED) |
|
170 public static Word signed(long val) { |
|
171 return box(val); |
|
172 } |
|
173 |
|
174 /** |
|
175 * Unsafe conversion from a Java int value to a Word. The parameter is treated as a signed |
|
176 * 32-bit value (unchanged semantics of a Java int). |
|
177 * |
|
178 * @param val a 32 bit signed value |
|
179 * @return the value cast to Word |
|
180 */ |
|
181 @Operation(opcode = Opcode.FROM_SIGNED) |
|
182 public static Word signed(int val) { |
|
183 return box(val); |
121 return box(val); |
184 } |
122 } |
185 |
123 |
186 @Override |
124 @Override |
187 @Operation(opcode = Opcode.TO_RAW_VALUE) |
125 @Operation(opcode = Opcode.TO_RAW_VALUE) |
194 * returned pointer or any value derived from it is alive across a safepoint, it will be |
132 * returned pointer or any value derived from it is alive across a safepoint, it will be |
195 * tracked. Depending on the arithmetic on the pointer and the capabilities of the backend to |
133 * tracked. Depending on the arithmetic on the pointer and the capabilities of the backend to |
196 * deal with derived references, this may work correctly, or result in a compiler error. |
134 * deal with derived references, this may work correctly, or result in a compiler error. |
197 */ |
135 */ |
198 @Operation(opcode = Opcode.OBJECT_TO_TRACKED) |
136 @Operation(opcode = Opcode.OBJECT_TO_TRACKED) |
199 public static native Pointer objectToTrackedPointer(Object val); |
137 public static native Word objectToTrackedPointer(Object val); |
200 |
138 |
201 /** |
139 /** |
202 * Convert an {@link Object} to a {@link Pointer}, dropping the reference information. If the |
140 * Convert an {@link Object} to a {@link Pointer}, dropping the reference information. If the |
203 * returned pointer or any value derived from it is alive across a safepoint, it will be treated |
141 * returned pointer or any value derived from it is alive across a safepoint, it will be treated |
204 * as a simple integer and not tracked by the garbage collector. |
142 * as a simple integer and not tracked by the garbage collector. |
209 * <p> |
147 * <p> |
210 * If the result value should not be alive across a safepoint, it's better to use |
148 * If the result value should not be alive across a safepoint, it's better to use |
211 * {@link #objectToTrackedPointer(Object)} instead. |
149 * {@link #objectToTrackedPointer(Object)} instead. |
212 */ |
150 */ |
213 @Operation(opcode = Opcode.OBJECT_TO_UNTRACKED) |
151 @Operation(opcode = Opcode.OBJECT_TO_UNTRACKED) |
214 public static native Pointer objectToUntrackedPointer(Object val); |
152 public static native Word objectToUntrackedPointer(Object val); |
215 |
153 |
216 @Operation(opcode = Opcode.FROM_ADDRESS) |
154 @Operation(opcode = Opcode.FROM_ADDRESS) |
217 public static native Pointer fromAddress(Address address); |
155 public static native Word fromAddress(Address address); |
218 |
156 |
219 @Override |
157 @Override |
220 @Operation(opcode = Opcode.TO_OBJECT) |
158 @Operation(opcode = Opcode.TO_OBJECT) |
221 public native Object toObject(); |
159 public native Object toObject(); |
222 |
160 |
775 return readDouble(signed(offset), locationIdentity); |
713 return readDouble(signed(offset), locationIdentity); |
776 } |
714 } |
777 |
715 |
778 @Override |
716 @Override |
779 @Operation(opcode = Opcode.READ_POINTER) |
717 @Operation(opcode = Opcode.READ_POINTER) |
780 public Word readWord(int offset, LocationIdentity locationIdentity) { |
718 public <T extends WordBase> T readWord(int offset, LocationIdentity locationIdentity) { |
781 return readWord(signed(offset), locationIdentity); |
719 return readWord(signed(offset), locationIdentity); |
782 } |
720 } |
783 |
721 |
784 @Override |
722 @Override |
785 @Operation(opcode = Opcode.READ_POINTER) |
723 @Operation(opcode = Opcode.READ_POINTER) |
947 return UNSAFE.getDouble(add((Word) offset).unbox()); |
885 return UNSAFE.getDouble(add((Word) offset).unbox()); |
948 } |
886 } |
949 |
887 |
950 @Override |
888 @Override |
951 @Operation(opcode = Opcode.READ_POINTER) |
889 @Operation(opcode = Opcode.READ_POINTER) |
952 public Word readWord(WordBase offset) { |
890 public <T extends WordBase> T readWord(WordBase offset) { |
953 return box(UNSAFE.getAddress(add((Word) offset).unbox())); |
891 return box(UNSAFE.getAddress(add((Word) offset).unbox())); |
954 } |
892 } |
955 |
893 |
956 @Override |
894 @Override |
957 @Operation(opcode = Opcode.READ_POINTER) |
895 @Operation(opcode = Opcode.READ_POINTER) |
958 public native Object readObject(WordBase offset); |
896 public native Object readObject(WordBase offset); |
959 |
897 |
960 @Override |
|
961 @Operation(opcode = Opcode.READ_HEAP) |
898 @Operation(opcode = Opcode.READ_HEAP) |
962 public native Object readObject(WordBase offset, BarrierType barrierType); |
899 public native Object readObject(WordBase offset, BarrierType barrierType); |
963 |
900 |
964 @Override |
901 @Override |
965 @Operation(opcode = Opcode.READ_POINTER) |
902 @Operation(opcode = Opcode.READ_POINTER) |
1003 return readDouble(signed(offset)); |
940 return readDouble(signed(offset)); |
1004 } |
941 } |
1005 |
942 |
1006 @Override |
943 @Override |
1007 @Operation(opcode = Opcode.READ_POINTER) |
944 @Operation(opcode = Opcode.READ_POINTER) |
1008 public Word readWord(int offset) { |
945 public <T extends WordBase> T readWord(int offset) { |
1009 return readWord(signed(offset)); |
946 return readWord(signed(offset)); |
1010 } |
947 } |
1011 |
948 |
1012 @Override |
949 @Override |
1013 @Operation(opcode = Opcode.READ_POINTER) |
950 @Operation(opcode = Opcode.READ_POINTER) |
1014 public Object readObject(int offset) { |
951 public Object readObject(int offset) { |
1015 return readObject(signed(offset)); |
952 return readObject(signed(offset)); |
1016 } |
953 } |
1017 |
954 |
1018 @Override |
|
1019 @Operation(opcode = Opcode.READ_HEAP) |
955 @Operation(opcode = Opcode.READ_HEAP) |
1020 public Object readObject(int offset, BarrierType barrierType) { |
956 public Object readObject(int offset, BarrierType barrierType) { |
1021 return readObject(signed(offset), barrierType); |
957 return readObject(signed(offset), barrierType); |
1022 } |
958 } |
1023 |
959 |
1071 @Operation(opcode = Opcode.CAS_POINTER) |
1007 @Operation(opcode = Opcode.CAS_POINTER) |
1072 public native long compareAndSwapLong(WordBase offset, long expectedValue, long newValue, LocationIdentity locationIdentity); |
1008 public native long compareAndSwapLong(WordBase offset, long expectedValue, long newValue, LocationIdentity locationIdentity); |
1073 |
1009 |
1074 @Override |
1010 @Override |
1075 @Operation(opcode = Opcode.CAS_POINTER) |
1011 @Operation(opcode = Opcode.CAS_POINTER) |
1076 public native Word compareAndSwapWord(WordBase offset, WordBase expectedValue, WordBase newValue, LocationIdentity locationIdentity); |
1012 public native <T extends WordBase> T compareAndSwapWord(WordBase offset, T expectedValue, T newValue, LocationIdentity locationIdentity); |
1077 |
1013 |
1078 @Override |
1014 @Override |
1079 @Operation(opcode = Opcode.CAS_POINTER) |
1015 @Operation(opcode = Opcode.CAS_POINTER) |
1080 public native Object compareAndSwapObject(WordBase offset, Object expectedValue, Object newValue, LocationIdentity locationIdentity); |
1016 public native Object compareAndSwapObject(WordBase offset, Object expectedValue, Object newValue, LocationIdentity locationIdentity); |
1081 |
1017 |
1177 return compareAndSwapLong(signed(offset), expectedValue, newValue, locationIdentity); |
1113 return compareAndSwapLong(signed(offset), expectedValue, newValue, locationIdentity); |
1178 } |
1114 } |
1179 |
1115 |
1180 @Override |
1116 @Override |
1181 @Operation(opcode = Opcode.CAS_POINTER) |
1117 @Operation(opcode = Opcode.CAS_POINTER) |
1182 public Word compareAndSwapWord(int offset, WordBase expectedValue, WordBase newValue, LocationIdentity locationIdentity) { |
1118 public <T extends WordBase> T compareAndSwapWord(int offset, T expectedValue, T newValue, LocationIdentity locationIdentity) { |
1183 return compareAndSwapWord(signed(offset), expectedValue, newValue, locationIdentity); |
1119 return compareAndSwapWord(signed(offset), expectedValue, newValue, locationIdentity); |
1184 } |
1120 } |
1185 |
1121 |
1186 @Override |
1122 @Override |
1187 @Operation(opcode = Opcode.CAS_POINTER) |
1123 @Operation(opcode = Opcode.CAS_POINTER) |
1211 @Operation(opcode = Opcode.CAS_POINTER) |
1147 @Operation(opcode = Opcode.CAS_POINTER) |
1212 public boolean logicCompareAndSwapObject(int offset, Object expectedValue, Object newValue, LocationIdentity locationIdentity) { |
1148 public boolean logicCompareAndSwapObject(int offset, Object expectedValue, Object newValue, LocationIdentity locationIdentity) { |
1213 return logicCompareAndSwapObject(signed(offset), expectedValue, newValue, locationIdentity); |
1149 return logicCompareAndSwapObject(signed(offset), expectedValue, newValue, locationIdentity); |
1214 } |
1150 } |
1215 |
1151 |
|
1152 /** |
|
1153 * This is deprecated because of the easy to mistype name collision between {@link #equals} and |
|
1154 * the other equals routines like {@link #equal(Word)}. In general you should never be |
|
1155 * statically calling this method for Word types. |
|
1156 */ |
|
1157 @SuppressWarnings("deprecation") |
|
1158 @Deprecated |
1216 @Override |
1159 @Override |
1217 public final boolean equals(Object obj) { |
1160 public final boolean equals(Object obj) { |
1218 throw GraalError.shouldNotReachHere("equals must not be called on words"); |
1161 throw GraalError.shouldNotReachHere("equals must not be called on words"); |
1219 } |
1162 } |
1220 |
1163 |