Word.java revision 12651:6ef01bd40ce2
1/*
2 * Copyright (c) 2012, 2016, 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 */
23package org.graalvm.compiler.word;
24
25import static org.graalvm.compiler.word.UnsafeAccess.UNSAFE;
26
27import java.lang.annotation.ElementType;
28import java.lang.annotation.Retention;
29import java.lang.annotation.RetentionPolicy;
30import java.lang.annotation.Target;
31
32import org.graalvm.compiler.core.common.LocationIdentity;
33import org.graalvm.compiler.core.common.calc.Condition;
34import org.graalvm.compiler.core.common.calc.UnsignedMath;
35import org.graalvm.compiler.debug.GraalError;
36import org.graalvm.compiler.nodes.ValueNode;
37import org.graalvm.compiler.nodes.calc.AddNode;
38import org.graalvm.compiler.nodes.calc.AndNode;
39import org.graalvm.compiler.nodes.calc.LeftShiftNode;
40import org.graalvm.compiler.nodes.calc.MulNode;
41import org.graalvm.compiler.nodes.calc.OrNode;
42import org.graalvm.compiler.nodes.calc.RightShiftNode;
43import org.graalvm.compiler.nodes.calc.SignedDivNode;
44import org.graalvm.compiler.nodes.calc.SignedRemNode;
45import org.graalvm.compiler.nodes.calc.SubNode;
46import org.graalvm.compiler.nodes.calc.UnsignedDivNode;
47import org.graalvm.compiler.nodes.calc.UnsignedRemNode;
48import org.graalvm.compiler.nodes.calc.UnsignedRightShiftNode;
49import org.graalvm.compiler.nodes.calc.XorNode;
50import org.graalvm.compiler.nodes.memory.HeapAccess.BarrierType;
51import org.graalvm.compiler.nodes.memory.address.AddressNode.Address;
52
53public abstract class Word implements Signed, Unsigned, Pointer {
54
55    /**
56     * Links a method to a canonical operation represented by an {@link Opcode} val.
57     */
58    @Retention(RetentionPolicy.RUNTIME)
59    @Target(ElementType.METHOD)
60    public @interface Operation {
61
62        Class<? extends ValueNode> node() default ValueNode.class;
63
64        boolean rightOperandIsInt() default false;
65
66        Opcode opcode() default Opcode.NODE_CLASS;
67
68        Condition condition() default Condition.EQ;
69    }
70
71    /**
72     * The canonical {@link Operation} represented by a method in the {@link Word} class.
73     */
74    // @formatter:off
75     public enum Opcode {
76         NODE_CLASS,
77         COMPARISON,
78         NOT,
79         READ_POINTER,
80         READ_OBJECT,
81         READ_BARRIERED,
82         READ_HEAP,
83         WRITE_POINTER,
84         WRITE_OBJECT,
85         WRITE_BARRIERED,
86         INITIALIZE,
87         ZERO,
88         FROM_UNSIGNED,
89         FROM_SIGNED,
90         FROM_ADDRESS,
91         OBJECT_TO_TRACKED,
92         OBJECT_TO_UNTRACKED,
93         TO_OBJECT,
94         TO_RAW_VALUE,
95    }
96     // @formatter:on
97
98    /*
99     * Outside users should use the different signed() and unsigned() methods to ensure proper
100     * expansion of 32-bit values on 64-bit systems.
101     */
102    private static Word box(long val) {
103        return HostedWord.boxLong(val);
104    }
105
106    protected abstract long unbox();
107
108    private static Word intParam(int val) {
109        return box(val);
110    }
111
112    /**
113     * The constant 0, i.e., the word with no bits set. There is no difference between a signed and
114     * unsigned zero.
115     *
116     * @return the constant 0.
117     */
118    @Operation(opcode = Opcode.ZERO)
119    public static Word zero() {
120        return box(0L);
121    }
122
123    /**
124     * Unsafe conversion from a Java long value to a Word. The parameter is treated as an unsigned
125     * 64-bit value (in contrast to the semantics of a Java long).
126     *
127     * @param val a 64 bit unsigned value
128     * @return the value cast to Word
129     */
130    @Operation(opcode = Opcode.FROM_UNSIGNED)
131    public static Word unsigned(long val) {
132        return box(val);
133    }
134
135    /**
136     * Unsafe conversion from a Java long value to a {@link PointerBase pointer}. The parameter is
137     * treated as an unsigned 64-bit value (in contrast to the semantics of a Java long).
138     *
139     * @param val a 64 bit unsigned value
140     * @return the value cast to PointerBase
141     */
142    @Operation(opcode = Opcode.FROM_UNSIGNED)
143    @SuppressWarnings("unchecked")
144    public static <T extends PointerBase> T pointer(long val) {
145        return (T) box(val);
146    }
147
148    /**
149     * Unsafe conversion from a Java int value to a Word. The parameter is treated as an unsigned
150     * 32-bit value (in contrast to the semantics of a Java int).
151     *
152     * @param val a 32 bit unsigned value
153     * @return the value cast to Word
154     */
155    @Operation(opcode = Opcode.FROM_UNSIGNED)
156    public static Word unsigned(int val) {
157        return box(val & 0xffffffffL);
158    }
159
160    /**
161     * Unsafe conversion from a Java long value to a Word. The parameter is treated as a signed
162     * 64-bit value (unchanged semantics of a Java long).
163     *
164     * @param val a 64 bit signed value
165     * @return the value cast to Word
166     */
167    @Operation(opcode = Opcode.FROM_SIGNED)
168    public static Word signed(long val) {
169        return box(val);
170    }
171
172    /**
173     * Unsafe conversion from a Java int value to a Word. The parameter is treated as a signed
174     * 32-bit value (unchanged semantics of a Java int).
175     *
176     * @param val a 32 bit signed value
177     * @return the value cast to Word
178     */
179    @Operation(opcode = Opcode.FROM_SIGNED)
180    public static Word signed(int val) {
181        return box(val);
182    }
183
184    @Override
185    @Operation(opcode = Opcode.TO_RAW_VALUE)
186    public long rawValue() {
187        return unbox();
188    }
189
190    /**
191     * Convert an {@link Object} to a {@link Pointer}, keeping the reference information. If the
192     * returned pointer or any value derived from it is alive across a safepoint, it will be
193     * tracked. Depending on the arithmetic on the pointer and the capabilities of the backend to
194     * deal with derived references, this may work correctly, or result in a compiler error.
195     */
196    @Operation(opcode = Opcode.OBJECT_TO_TRACKED)
197    public static native Pointer objectToTrackedPointer(Object val);
198
199    /**
200     * Convert an {@link Object} to a {@link Pointer}, dropping the reference information. If the
201     * returned pointer or any value derived from it is alive across a safepoint, it will be treated
202     * as a simple integer and not tracked by the garbage collector.
203     * <p>
204     * This is a dangerous operation, the GC could move the object without updating the pointer! Use
205     * only in combination with some mechanism to prevent the GC from moving or freeing the object
206     * as long as the pointer is in use.
207     * <p>
208     * If the result value should not be alive across a safepoint, it's better to use
209     * {@link #objectToTrackedPointer(Object)} instead.
210     */
211    @Operation(opcode = Opcode.OBJECT_TO_UNTRACKED)
212    public static native Pointer objectToUntrackedPointer(Object val);
213
214    @Operation(opcode = Opcode.FROM_ADDRESS)
215    public static native Pointer fromAddress(Address address);
216
217    @Override
218    @Operation(opcode = Opcode.TO_OBJECT)
219    public native Object toObject();
220
221    @Override
222    @Operation(node = AddNode.class)
223    public Word add(Signed val) {
224        return add((Word) val);
225    }
226
227    @Override
228    @Operation(node = AddNode.class)
229    public Word add(Unsigned val) {
230        return add((Word) val);
231    }
232
233    @Override
234    @Operation(node = AddNode.class)
235    public Word add(int val) {
236        return add(intParam(val));
237    }
238
239    @Operation(node = AddNode.class)
240    public Word add(Word val) {
241        return box(unbox() + val.unbox());
242    }
243
244    @Override
245    @Operation(node = SubNode.class)
246    public Word subtract(Signed val) {
247        return subtract((Word) val);
248    }
249
250    @Override
251    @Operation(node = SubNode.class)
252    public Word subtract(Unsigned val) {
253        return subtract((Word) val);
254    }
255
256    @Override
257    @Operation(node = SubNode.class)
258    public Word subtract(int val) {
259        return subtract(intParam(val));
260    }
261
262    @Operation(node = SubNode.class)
263    public Word subtract(Word val) {
264        return box(unbox() - val.unbox());
265    }
266
267    @Override
268    @Operation(node = MulNode.class)
269    public Word multiply(Signed val) {
270        return multiply((Word) val);
271    }
272
273    @Override
274    @Operation(node = MulNode.class)
275    public Word multiply(Unsigned val) {
276        return multiply((Word) val);
277    }
278
279    @Override
280    @Operation(node = MulNode.class)
281    public Word multiply(int val) {
282        return multiply(intParam(val));
283    }
284
285    @Operation(node = MulNode.class)
286    public Word multiply(Word val) {
287        return box(unbox() * val.unbox());
288    }
289
290    @Override
291    @Operation(node = SignedDivNode.class)
292    public Word signedDivide(Signed val) {
293        return signedDivide((Word) val);
294    }
295
296    @Override
297    @Operation(node = SignedDivNode.class)
298    public Word signedDivide(int val) {
299        return signedDivide(intParam(val));
300    }
301
302    @Operation(node = SignedDivNode.class)
303    public Word signedDivide(Word val) {
304        return box(unbox() / val.unbox());
305    }
306
307    @Override
308    @Operation(node = UnsignedDivNode.class)
309    public Word unsignedDivide(Unsigned val) {
310        return unsignedDivide((Word) val);
311    }
312
313    @Override
314    @Operation(node = UnsignedDivNode.class)
315    public Word unsignedDivide(int val) {
316        return signedDivide(intParam(val));
317    }
318
319    @Operation(node = UnsignedDivNode.class)
320    public Word unsignedDivide(Word val) {
321        return box(Long.divideUnsigned(unbox(), val.unbox()));
322    }
323
324    @Override
325    @Operation(node = SignedRemNode.class)
326    public Word signedRemainder(Signed val) {
327        return signedRemainder((Word) val);
328    }
329
330    @Override
331    @Operation(node = SignedRemNode.class)
332    public Word signedRemainder(int val) {
333        return signedRemainder(intParam(val));
334    }
335
336    @Operation(node = SignedRemNode.class)
337    public Word signedRemainder(Word val) {
338        return box(unbox() % val.unbox());
339    }
340
341    @Override
342    @Operation(node = UnsignedRemNode.class)
343    public Word unsignedRemainder(Unsigned val) {
344        return unsignedRemainder((Word) val);
345    }
346
347    @Override
348    @Operation(node = UnsignedRemNode.class)
349    public Word unsignedRemainder(int val) {
350        return signedRemainder(intParam(val));
351    }
352
353    @Operation(node = UnsignedRemNode.class)
354    public Word unsignedRemainder(Word val) {
355        return box(Long.remainderUnsigned(unbox(), val.unbox()));
356    }
357
358    @Override
359    @Operation(node = LeftShiftNode.class, rightOperandIsInt = true)
360    public Word shiftLeft(Unsigned val) {
361        return shiftLeft((Word) val);
362    }
363
364    @Override
365    @Operation(node = LeftShiftNode.class, rightOperandIsInt = true)
366    public Word shiftLeft(int val) {
367        return shiftLeft(intParam(val));
368    }
369
370    @Operation(node = LeftShiftNode.class, rightOperandIsInt = true)
371    public Word shiftLeft(Word val) {
372        return box(unbox() << val.unbox());
373    }
374
375    @Override
376    @Operation(node = RightShiftNode.class, rightOperandIsInt = true)
377    public Word signedShiftRight(Unsigned val) {
378        return signedShiftRight((Word) val);
379    }
380
381    @Override
382    @Operation(node = RightShiftNode.class, rightOperandIsInt = true)
383    public Word signedShiftRight(int val) {
384        return signedShiftRight(intParam(val));
385    }
386
387    @Operation(node = RightShiftNode.class, rightOperandIsInt = true)
388    public Word signedShiftRight(Word val) {
389        return box(unbox() >> val.unbox());
390    }
391
392    @Override
393    @Operation(node = UnsignedRightShiftNode.class, rightOperandIsInt = true)
394    public Word unsignedShiftRight(Unsigned val) {
395        return unsignedShiftRight((Word) val);
396    }
397
398    @Override
399    @Operation(node = UnsignedRightShiftNode.class, rightOperandIsInt = true)
400    public Word unsignedShiftRight(int val) {
401        return unsignedShiftRight(intParam(val));
402    }
403
404    @Operation(node = UnsignedRightShiftNode.class, rightOperandIsInt = true)
405    public Word unsignedShiftRight(Word val) {
406        return box(unbox() >>> val.unbox());
407    }
408
409    @Override
410    @Operation(node = AndNode.class)
411    public Word and(Signed val) {
412        return and((Word) val);
413    }
414
415    @Override
416    @Operation(node = AndNode.class)
417    public Word and(Unsigned val) {
418        return and((Word) val);
419    }
420
421    @Override
422    @Operation(node = AndNode.class)
423    public Word and(int val) {
424        return and(intParam(val));
425    }
426
427    @Operation(node = AndNode.class)
428    public Word and(Word val) {
429        return box(unbox() & val.unbox());
430    }
431
432    @Override
433    @Operation(node = OrNode.class)
434    public Word or(Signed val) {
435        return or((Word) val);
436    }
437
438    @Override
439    @Operation(node = OrNode.class)
440    public Word or(Unsigned val) {
441        return or((Word) val);
442    }
443
444    @Override
445    @Operation(node = OrNode.class)
446    public Word or(int val) {
447        return or(intParam(val));
448    }
449
450    @Operation(node = OrNode.class)
451    public Word or(Word val) {
452        return box(unbox() | val.unbox());
453    }
454
455    @Override
456    @Operation(node = XorNode.class)
457    public Word xor(Signed val) {
458        return xor((Word) val);
459    }
460
461    @Override
462    @Operation(node = XorNode.class)
463    public Word xor(Unsigned val) {
464        return xor((Word) val);
465    }
466
467    @Override
468    @Operation(node = XorNode.class)
469    public Word xor(int val) {
470        return xor(intParam(val));
471    }
472
473    @Operation(node = XorNode.class)
474    public Word xor(Word val) {
475        return box(unbox() ^ val.unbox());
476    }
477
478    @Override
479    @Operation(opcode = Opcode.NOT)
480    public Word not() {
481        return box(~unbox());
482    }
483
484    @Override
485    @Operation(opcode = Opcode.COMPARISON, condition = Condition.EQ)
486    public boolean equal(ComparableWord val) {
487        return equal((Word) val);
488    }
489
490    @Override
491    @Operation(opcode = Opcode.COMPARISON, condition = Condition.EQ)
492    public boolean equal(Signed val) {
493        return equal((Word) val);
494    }
495
496    @Override
497    @Operation(opcode = Opcode.COMPARISON, condition = Condition.EQ)
498    public boolean equal(Unsigned val) {
499        return equal((Word) val);
500    }
501
502    @Override
503    @Operation(opcode = Opcode.COMPARISON, condition = Condition.EQ)
504    public boolean equal(int val) {
505        return equal(intParam(val));
506    }
507
508    @Operation(opcode = Opcode.COMPARISON, condition = Condition.EQ)
509    public boolean equal(Word val) {
510        return unbox() == val.unbox();
511    }
512
513    @Override
514    @Operation(opcode = Opcode.COMPARISON, condition = Condition.NE)
515    public boolean notEqual(ComparableWord val) {
516        return notEqual((Word) val);
517    }
518
519    @Override
520    @Operation(opcode = Opcode.COMPARISON, condition = Condition.NE)
521    public boolean notEqual(Signed val) {
522        return notEqual((Word) val);
523    }
524
525    @Override
526    @Operation(opcode = Opcode.COMPARISON, condition = Condition.NE)
527    public boolean notEqual(Unsigned val) {
528        return notEqual((Word) val);
529    }
530
531    @Override
532    @Operation(opcode = Opcode.COMPARISON, condition = Condition.NE)
533    public boolean notEqual(int val) {
534        return notEqual(intParam(val));
535    }
536
537    @Operation(opcode = Opcode.COMPARISON, condition = Condition.NE)
538    public boolean notEqual(Word val) {
539        return unbox() != val.unbox();
540    }
541
542    @Override
543    @Operation(opcode = Opcode.COMPARISON, condition = Condition.LT)
544    public boolean lessThan(Signed val) {
545        return lessThan((Word) val);
546    }
547
548    @Override
549    @Operation(opcode = Opcode.COMPARISON, condition = Condition.LT)
550    public boolean lessThan(int val) {
551        return lessThan(intParam(val));
552    }
553
554    @Operation(opcode = Opcode.COMPARISON, condition = Condition.LT)
555    public boolean lessThan(Word val) {
556        return unbox() < val.unbox();
557    }
558
559    @Override
560    @Operation(opcode = Opcode.COMPARISON, condition = Condition.LE)
561    public boolean lessOrEqual(Signed val) {
562        return lessOrEqual((Word) val);
563    }
564
565    @Override
566    @Operation(opcode = Opcode.COMPARISON, condition = Condition.LE)
567    public boolean lessOrEqual(int val) {
568        return lessOrEqual(intParam(val));
569    }
570
571    @Operation(opcode = Opcode.COMPARISON, condition = Condition.LE)
572    public boolean lessOrEqual(Word val) {
573        return unbox() <= val.unbox();
574    }
575
576    @Override
577    @Operation(opcode = Opcode.COMPARISON, condition = Condition.GT)
578    public boolean greaterThan(Signed val) {
579        return greaterThan((Word) val);
580    }
581
582    @Override
583    @Operation(opcode = Opcode.COMPARISON, condition = Condition.GT)
584    public boolean greaterThan(int val) {
585        return greaterThan(intParam(val));
586    }
587
588    @Operation(opcode = Opcode.COMPARISON, condition = Condition.GT)
589    public boolean greaterThan(Word val) {
590        return unbox() > val.unbox();
591    }
592
593    @Override
594    @Operation(opcode = Opcode.COMPARISON, condition = Condition.GE)
595    public boolean greaterOrEqual(Signed val) {
596        return greaterOrEqual((Word) val);
597    }
598
599    @Override
600    @Operation(opcode = Opcode.COMPARISON, condition = Condition.GE)
601    public boolean greaterOrEqual(int val) {
602        return greaterOrEqual(intParam(val));
603    }
604
605    @Operation(opcode = Opcode.COMPARISON, condition = Condition.GE)
606    public boolean greaterOrEqual(Word val) {
607        return unbox() >= val.unbox();
608    }
609
610    @Override
611    @Operation(opcode = Opcode.COMPARISON, condition = Condition.BT)
612    public boolean belowThan(Unsigned val) {
613        return belowThan((Word) val);
614    }
615
616    @Override
617    @Operation(opcode = Opcode.COMPARISON, condition = Condition.BT)
618    public boolean belowThan(int val) {
619        return belowThan(intParam(val));
620    }
621
622    @Operation(opcode = Opcode.COMPARISON, condition = Condition.BT)
623    public boolean belowThan(Word val) {
624        return UnsignedMath.belowThan(unbox(), val.unbox());
625    }
626
627    @Override
628    @Operation(opcode = Opcode.COMPARISON, condition = Condition.BE)
629    public boolean belowOrEqual(Unsigned val) {
630        return belowOrEqual((Word) val);
631    }
632
633    @Override
634    @Operation(opcode = Opcode.COMPARISON, condition = Condition.BE)
635    public boolean belowOrEqual(int val) {
636        return belowOrEqual(intParam(val));
637    }
638
639    @Operation(opcode = Opcode.COMPARISON, condition = Condition.BE)
640    public boolean belowOrEqual(Word val) {
641        return UnsignedMath.belowOrEqual(unbox(), val.unbox());
642    }
643
644    @Override
645    @Operation(opcode = Opcode.COMPARISON, condition = Condition.AT)
646    public boolean aboveThan(Unsigned val) {
647        return aboveThan((Word) val);
648    }
649
650    @Override
651    @Operation(opcode = Opcode.COMPARISON, condition = Condition.AT)
652    public boolean aboveThan(int val) {
653        return aboveThan(intParam(val));
654    }
655
656    @Operation(opcode = Opcode.COMPARISON, condition = Condition.AT)
657    public boolean aboveThan(Word val) {
658        return UnsignedMath.aboveThan(unbox(), val.unbox());
659    }
660
661    @Override
662    @Operation(opcode = Opcode.COMPARISON, condition = Condition.AE)
663    public boolean aboveOrEqual(Unsigned val) {
664        return aboveOrEqual((Word) val);
665    }
666
667    @Override
668    @Operation(opcode = Opcode.COMPARISON, condition = Condition.AE)
669    public boolean aboveOrEqual(int val) {
670        return aboveOrEqual(intParam(val));
671    }
672
673    @Operation(opcode = Opcode.COMPARISON, condition = Condition.AE)
674    public boolean aboveOrEqual(Word val) {
675        return UnsignedMath.aboveOrEqual(unbox(), val.unbox());
676    }
677
678    @Override
679    @Operation(opcode = Opcode.READ_POINTER)
680    public byte readByte(WordBase offset, LocationIdentity locationIdentity) {
681        return UNSAFE.getByte(add((Word) offset).unbox());
682    }
683
684    @Override
685    @Operation(opcode = Opcode.READ_POINTER)
686    public char readChar(WordBase offset, LocationIdentity locationIdentity) {
687        return UNSAFE.getChar(add((Word) offset).unbox());
688    }
689
690    @Override
691    @Operation(opcode = Opcode.READ_POINTER)
692    public short readShort(WordBase offset, LocationIdentity locationIdentity) {
693        return UNSAFE.getShort(add((Word) offset).unbox());
694    }
695
696    @Override
697    @Operation(opcode = Opcode.READ_POINTER)
698    public int readInt(WordBase offset, LocationIdentity locationIdentity) {
699        return UNSAFE.getInt(add((Word) offset).unbox());
700    }
701
702    @Override
703    @Operation(opcode = Opcode.READ_POINTER)
704    public long readLong(WordBase offset, LocationIdentity locationIdentity) {
705        return UNSAFE.getLong(add((Word) offset).unbox());
706    }
707
708    @Override
709    @Operation(opcode = Opcode.READ_POINTER)
710    public float readFloat(WordBase offset, LocationIdentity locationIdentity) {
711        return UNSAFE.getFloat(add((Word) offset).unbox());
712    }
713
714    @Override
715    @Operation(opcode = Opcode.READ_POINTER)
716    public double readDouble(WordBase offset, LocationIdentity locationIdentity) {
717        return UNSAFE.getDouble(add((Word) offset).unbox());
718    }
719
720    @Override
721    @Operation(opcode = Opcode.READ_POINTER)
722    public Word readWord(WordBase offset, LocationIdentity locationIdentity) {
723        return box(UNSAFE.getAddress(add((Word) offset).unbox()));
724    }
725
726    @Override
727    @Operation(opcode = Opcode.READ_POINTER)
728    public native Object readObject(WordBase offset, LocationIdentity locationIdentity);
729
730    @Override
731    @Operation(opcode = Opcode.READ_POINTER)
732    public byte readByte(int offset, LocationIdentity locationIdentity) {
733        return readByte(signed(offset), locationIdentity);
734    }
735
736    @Override
737    @Operation(opcode = Opcode.READ_POINTER)
738    public char readChar(int offset, LocationIdentity locationIdentity) {
739        return readChar(signed(offset), locationIdentity);
740    }
741
742    @Override
743    @Operation(opcode = Opcode.READ_POINTER)
744    public short readShort(int offset, LocationIdentity locationIdentity) {
745        return readShort(signed(offset), locationIdentity);
746    }
747
748    @Override
749    @Operation(opcode = Opcode.READ_POINTER)
750    public int readInt(int offset, LocationIdentity locationIdentity) {
751        return readInt(signed(offset), locationIdentity);
752    }
753
754    @Override
755    @Operation(opcode = Opcode.READ_POINTER)
756    public long readLong(int offset, LocationIdentity locationIdentity) {
757        return readLong(signed(offset), locationIdentity);
758    }
759
760    @Override
761    @Operation(opcode = Opcode.READ_POINTER)
762    public float readFloat(int offset, LocationIdentity locationIdentity) {
763        return readFloat(signed(offset), locationIdentity);
764    }
765
766    @Override
767    @Operation(opcode = Opcode.READ_POINTER)
768    public double readDouble(int offset, LocationIdentity locationIdentity) {
769        return readDouble(signed(offset), locationIdentity);
770    }
771
772    @Override
773    @Operation(opcode = Opcode.READ_POINTER)
774    public Word readWord(int offset, LocationIdentity locationIdentity) {
775        return readWord(signed(offset), locationIdentity);
776    }
777
778    @Override
779    @Operation(opcode = Opcode.READ_POINTER)
780    public Object readObject(int offset, LocationIdentity locationIdentity) {
781        return readObject(signed(offset), locationIdentity);
782    }
783
784    @Override
785    @Operation(opcode = Opcode.WRITE_POINTER)
786    public void writeByte(WordBase offset, byte val, LocationIdentity locationIdentity) {
787        UNSAFE.putByte(add((Word) offset).unbox(), val);
788    }
789
790    @Override
791    @Operation(opcode = Opcode.WRITE_POINTER)
792    public void writeChar(WordBase offset, char val, LocationIdentity locationIdentity) {
793        UNSAFE.putChar(add((Word) offset).unbox(), val);
794    }
795
796    @Override
797    @Operation(opcode = Opcode.WRITE_POINTER)
798    public void writeShort(WordBase offset, short val, LocationIdentity locationIdentity) {
799        UNSAFE.putShort(add((Word) offset).unbox(), val);
800    }
801
802    @Override
803    @Operation(opcode = Opcode.WRITE_POINTER)
804    public void writeInt(WordBase offset, int val, LocationIdentity locationIdentity) {
805        UNSAFE.putInt(add((Word) offset).unbox(), val);
806    }
807
808    @Override
809    @Operation(opcode = Opcode.WRITE_POINTER)
810    public void writeLong(WordBase offset, long val, LocationIdentity locationIdentity) {
811        UNSAFE.putLong(add((Word) offset).unbox(), val);
812    }
813
814    @Override
815    @Operation(opcode = Opcode.WRITE_POINTER)
816    public void writeFloat(WordBase offset, float val, LocationIdentity locationIdentity) {
817        UNSAFE.putFloat(add((Word) offset).unbox(), val);
818    }
819
820    @Override
821    @Operation(opcode = Opcode.WRITE_POINTER)
822    public void writeDouble(WordBase offset, double val, LocationIdentity locationIdentity) {
823        UNSAFE.putDouble(add((Word) offset).unbox(), val);
824    }
825
826    @Override
827    @Operation(opcode = Opcode.WRITE_POINTER)
828    public void writeWord(WordBase offset, WordBase val, LocationIdentity locationIdentity) {
829        UNSAFE.putAddress(add((Word) offset).unbox(), ((Word) val).unbox());
830    }
831
832    @Override
833    @Operation(opcode = Opcode.INITIALIZE)
834    public void initializeLong(WordBase offset, long val, LocationIdentity locationIdentity) {
835        UNSAFE.putLong(add((Word) offset).unbox(), val);
836    }
837
838    @Override
839    @Operation(opcode = Opcode.WRITE_POINTER)
840    public native void writeObject(WordBase offset, Object val, LocationIdentity locationIdentity);
841
842    @Override
843    @Operation(opcode = Opcode.WRITE_POINTER)
844    public void writeByte(int offset, byte val, LocationIdentity locationIdentity) {
845        writeByte(signed(offset), val, locationIdentity);
846    }
847
848    @Override
849    @Operation(opcode = Opcode.WRITE_POINTER)
850    public void writeChar(int offset, char val, LocationIdentity locationIdentity) {
851        writeChar(signed(offset), val, locationIdentity);
852    }
853
854    @Override
855    @Operation(opcode = Opcode.WRITE_POINTER)
856    public void writeShort(int offset, short val, LocationIdentity locationIdentity) {
857        writeShort(signed(offset), val, locationIdentity);
858    }
859
860    @Override
861    @Operation(opcode = Opcode.WRITE_POINTER)
862    public void writeInt(int offset, int val, LocationIdentity locationIdentity) {
863        writeInt(signed(offset), val, locationIdentity);
864    }
865
866    @Override
867    @Operation(opcode = Opcode.WRITE_POINTER)
868    public void writeLong(int offset, long val, LocationIdentity locationIdentity) {
869        writeLong(signed(offset), val, locationIdentity);
870    }
871
872    @Override
873    @Operation(opcode = Opcode.WRITE_POINTER)
874    public void writeFloat(int offset, float val, LocationIdentity locationIdentity) {
875        writeFloat(signed(offset), val, locationIdentity);
876    }
877
878    @Override
879    @Operation(opcode = Opcode.WRITE_POINTER)
880    public void writeDouble(int offset, double val, LocationIdentity locationIdentity) {
881        writeDouble(signed(offset), val, locationIdentity);
882    }
883
884    @Override
885    @Operation(opcode = Opcode.WRITE_POINTER)
886    public void writeWord(int offset, WordBase val, LocationIdentity locationIdentity) {
887        writeWord(signed(offset), val, locationIdentity);
888    }
889
890    @Override
891    @Operation(opcode = Opcode.INITIALIZE)
892    public void initializeLong(int offset, long val, LocationIdentity locationIdentity) {
893        initializeLong(signed(offset), val, locationIdentity);
894    }
895
896    @Override
897    @Operation(opcode = Opcode.WRITE_POINTER)
898    public void writeObject(int offset, Object val, LocationIdentity locationIdentity) {
899        writeObject(signed(offset), val, locationIdentity);
900    }
901
902    @Override
903    @Operation(opcode = Opcode.READ_POINTER)
904    public byte readByte(WordBase offset) {
905        return UNSAFE.getByte(add((Word) offset).unbox());
906    }
907
908    @Override
909    @Operation(opcode = Opcode.READ_POINTER)
910    public char readChar(WordBase offset) {
911        return UNSAFE.getChar(add((Word) offset).unbox());
912    }
913
914    @Override
915    @Operation(opcode = Opcode.READ_POINTER)
916    public short readShort(WordBase offset) {
917        return UNSAFE.getShort(add((Word) offset).unbox());
918    }
919
920    @Override
921    @Operation(opcode = Opcode.READ_POINTER)
922    public int readInt(WordBase offset) {
923        return UNSAFE.getInt(add((Word) offset).unbox());
924    }
925
926    @Override
927    @Operation(opcode = Opcode.READ_POINTER)
928    public long readLong(WordBase offset) {
929        return UNSAFE.getLong(add((Word) offset).unbox());
930    }
931
932    @Override
933    @Operation(opcode = Opcode.READ_POINTER)
934    public float readFloat(WordBase offset) {
935        return UNSAFE.getFloat(add((Word) offset).unbox());
936    }
937
938    @Override
939    @Operation(opcode = Opcode.READ_POINTER)
940    public double readDouble(WordBase offset) {
941        return UNSAFE.getDouble(add((Word) offset).unbox());
942    }
943
944    @Override
945    @Operation(opcode = Opcode.READ_POINTER)
946    public Word readWord(WordBase offset) {
947        return box(UNSAFE.getAddress(add((Word) offset).unbox()));
948    }
949
950    @Override
951    @Operation(opcode = Opcode.READ_POINTER)
952    public native Object readObject(WordBase offset);
953
954    @Override
955    @Operation(opcode = Opcode.READ_HEAP)
956    public native Object readObject(WordBase offset, BarrierType barrierType);
957
958    @Override
959    @Operation(opcode = Opcode.READ_POINTER)
960    public byte readByte(int offset) {
961        return readByte(signed(offset));
962    }
963
964    @Override
965    @Operation(opcode = Opcode.READ_POINTER)
966    public char readChar(int offset) {
967        return readChar(signed(offset));
968    }
969
970    @Override
971    @Operation(opcode = Opcode.READ_POINTER)
972    public short readShort(int offset) {
973        return readShort(signed(offset));
974    }
975
976    @Override
977    @Operation(opcode = Opcode.READ_POINTER)
978    public int readInt(int offset) {
979        return readInt(signed(offset));
980    }
981
982    @Override
983    @Operation(opcode = Opcode.READ_POINTER)
984    public long readLong(int offset) {
985        return readLong(signed(offset));
986    }
987
988    @Override
989    @Operation(opcode = Opcode.READ_POINTER)
990    public float readFloat(int offset) {
991        return readFloat(signed(offset));
992    }
993
994    @Override
995    @Operation(opcode = Opcode.READ_POINTER)
996    public double readDouble(int offset) {
997        return readDouble(signed(offset));
998    }
999
1000    @Override
1001    @Operation(opcode = Opcode.READ_POINTER)
1002    public Word readWord(int offset) {
1003        return readWord(signed(offset));
1004    }
1005
1006    @Override
1007    @Operation(opcode = Opcode.READ_POINTER)
1008    public Object readObject(int offset) {
1009        return readObject(signed(offset));
1010    }
1011
1012    @Override
1013    @Operation(opcode = Opcode.READ_HEAP)
1014    public Object readObject(int offset, BarrierType barrierType) {
1015        return readObject(signed(offset), barrierType);
1016    }
1017
1018    @Override
1019    @Operation(opcode = Opcode.WRITE_POINTER)
1020    public void writeByte(WordBase offset, byte val) {
1021        UNSAFE.putByte(add((Word) offset).unbox(), val);
1022    }
1023
1024    @Override
1025    @Operation(opcode = Opcode.WRITE_POINTER)
1026    public void writeChar(WordBase offset, char val) {
1027        UNSAFE.putChar(add((Word) offset).unbox(), val);
1028    }
1029
1030    @Override
1031    @Operation(opcode = Opcode.WRITE_POINTER)
1032    public void writeShort(WordBase offset, short val) {
1033        UNSAFE.putShort(add((Word) offset).unbox(), val);
1034    }
1035
1036    @Override
1037    @Operation(opcode = Opcode.WRITE_POINTER)
1038    public void writeInt(WordBase offset, int val) {
1039        UNSAFE.putInt(add((Word) offset).unbox(), val);
1040    }
1041
1042    @Override
1043    @Operation(opcode = Opcode.WRITE_POINTER)
1044    public void writeLong(WordBase offset, long val) {
1045        UNSAFE.putLong(add((Word) offset).unbox(), val);
1046    }
1047
1048    @Override
1049    @Operation(opcode = Opcode.WRITE_POINTER)
1050    public void writeFloat(WordBase offset, float val) {
1051        UNSAFE.putFloat(add((Word) offset).unbox(), val);
1052    }
1053
1054    @Override
1055    @Operation(opcode = Opcode.WRITE_POINTER)
1056    public void writeDouble(WordBase offset, double val) {
1057        UNSAFE.putDouble(add((Word) offset).unbox(), val);
1058    }
1059
1060    @Override
1061    @Operation(opcode = Opcode.WRITE_POINTER)
1062    public void writeWord(WordBase offset, WordBase val) {
1063        UNSAFE.putAddress(add((Word) offset).unbox(), ((Word) val).unbox());
1064    }
1065
1066    @Override
1067    @Operation(opcode = Opcode.WRITE_POINTER)
1068    public native void writeObject(WordBase offset, Object val);
1069
1070    @Override
1071    @Operation(opcode = Opcode.WRITE_POINTER)
1072    public void writeByte(int offset, byte val) {
1073        writeByte(signed(offset), val);
1074    }
1075
1076    @Override
1077    @Operation(opcode = Opcode.WRITE_POINTER)
1078    public void writeChar(int offset, char val) {
1079        writeChar(signed(offset), val);
1080    }
1081
1082    @Override
1083    @Operation(opcode = Opcode.WRITE_POINTER)
1084    public void writeShort(int offset, short val) {
1085        writeShort(signed(offset), val);
1086    }
1087
1088    @Override
1089    @Operation(opcode = Opcode.WRITE_POINTER)
1090    public void writeInt(int offset, int val) {
1091        writeInt(signed(offset), val);
1092    }
1093
1094    @Override
1095    @Operation(opcode = Opcode.WRITE_POINTER)
1096    public void writeLong(int offset, long val) {
1097        writeLong(signed(offset), val);
1098    }
1099
1100    @Override
1101    @Operation(opcode = Opcode.WRITE_POINTER)
1102    public void writeFloat(int offset, float val) {
1103        writeFloat(signed(offset), val);
1104    }
1105
1106    @Override
1107    @Operation(opcode = Opcode.WRITE_POINTER)
1108    public void writeDouble(int offset, double val) {
1109        writeDouble(signed(offset), val);
1110    }
1111
1112    @Override
1113    @Operation(opcode = Opcode.WRITE_POINTER)
1114    public void writeWord(int offset, WordBase val) {
1115        writeWord(signed(offset), val);
1116    }
1117
1118    @Override
1119    @Operation(opcode = Opcode.WRITE_POINTER)
1120    public void writeObject(int offset, Object val) {
1121        writeObject(signed(offset), val);
1122    }
1123
1124    @Override
1125    public final boolean equals(Object obj) {
1126        throw GraalError.shouldNotReachHere("equals must not be called on words");
1127    }
1128
1129    @Override
1130    public final int hashCode() {
1131        throw GraalError.shouldNotReachHere("hashCode must not be called on words");
1132    }
1133
1134    @Override
1135    public String toString() {
1136        throw GraalError.shouldNotReachHere("toString must not be called on words");
1137    }
1138}
1139
1140final class HostedWord extends Word {
1141
1142    private static final int SMALL_FROM = -1;
1143    private static final int SMALL_TO = 100;
1144
1145    private static final HostedWord[] smallCache = new HostedWord[SMALL_TO - SMALL_FROM + 1];
1146
1147    static {
1148        for (int i = SMALL_FROM; i <= SMALL_TO; i++) {
1149            smallCache[i - SMALL_FROM] = new HostedWord(i);
1150        }
1151    }
1152
1153    private final long rawValue;
1154
1155    private HostedWord(long rawValue) {
1156        this.rawValue = rawValue;
1157    }
1158
1159    protected static Word boxLong(long val) {
1160        if (val >= SMALL_FROM && val <= SMALL_TO) {
1161            return smallCache[(int) val - SMALL_FROM];
1162        }
1163        return new HostedWord(val);
1164    }
1165
1166    @Override
1167    protected long unbox() {
1168        return rawValue;
1169    }
1170
1171    @Override
1172    public String toString() {
1173        return "Word<" + rawValue + ">";
1174    }
1175}
1176