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