001/*
002 * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation.
008 *
009 * This code is distributed in the hope that it will be useful, but WITHOUT
010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
011 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
012 * version 2 for more details (a copy is included in the LICENSE file that
013 * accompanied this code).
014 *
015 * You should have received a copy of the GNU General Public License version
016 * 2 along with this work; if not, write to the Free Software Foundation,
017 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
018 *
019 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
020 * or visit www.oracle.com if you need additional information or have any
021 * questions.
022 */
023package com.oracle.graal.word;
024
025import static jdk.internal.jvmci.common.UnsafeAccess.*;
026
027import java.lang.annotation.*;
028
029import jdk.internal.jvmci.code.*;
030import jdk.internal.jvmci.common.*;
031import jdk.internal.jvmci.meta.*;
032
033import com.oracle.graal.compiler.common.calc.*;
034import com.oracle.graal.nodes.*;
035import com.oracle.graal.nodes.calc.*;
036import com.oracle.graal.nodes.memory.HeapAccess.BarrierType;
037import com.oracle.graal.nodes.memory.address.AddressNode.Address;
038
039public abstract class Word implements Signed, Unsigned, Pointer {
040
041    /**
042     * Links a method to a canonical operation represented by an {@link Opcode} val.
043     */
044    @Retention(RetentionPolicy.RUNTIME)
045    @Target(ElementType.METHOD)
046    public @interface Operation {
047
048        Class<? extends ValueNode> node() default ValueNode.class;
049
050        boolean rightOperandIsInt() default false;
051
052        Opcode opcode() default Opcode.NODE_CLASS;
053
054        Condition condition() default Condition.EQ;
055    }
056
057    /**
058     * The canonical {@link Operation} represented by a method in the {@link Word} class.
059     */
060    // @formatter:off
061     public enum Opcode {
062         NODE_CLASS,
063         COMPARISON,
064         NOT,
065         READ_POINTER,
066         READ_OBJECT,
067         READ_BARRIERED,
068         READ_HEAP,
069         WRITE_POINTER,
070         WRITE_OBJECT,
071         WRITE_BARRIERED,
072         INITIALIZE,
073         ZERO,
074         FROM_UNSIGNED,
075         FROM_SIGNED,
076         FROM_OBJECT,
077         FROM_WORDBASE,
078         FROM_ADDRESS,
079         TO_OBJECT,
080         TO_RAW_VALUE,
081    }
082     // @formatter:on
083
084    /*
085     * Outside users should use the different signed() and unsigned() methods to ensure proper
086     * expansion of 32-bit values on 64-bit systems.
087     */
088    private static Word box(long val) {
089        return HostedWord.boxLong(val);
090    }
091
092    protected abstract long unbox();
093
094    private static Word intParam(int val) {
095        return box(val);
096    }
097
098    /**
099     * The constant 0, i.e., the word with no bits set. There is no difference between a signed and
100     * unsigned zero.
101     *
102     * @return the constant 0.
103     */
104    @Operation(opcode = Opcode.ZERO)
105    public static Word zero() {
106        return box(0L);
107    }
108
109    /**
110     * Unsafe conversion from a Java long value to a Word. The parameter is treated as an unsigned
111     * 64-bit value (in contrast to the semantics of a Java long).
112     *
113     * @param val a 64 bit unsigned value
114     * @return the value cast to Word
115     */
116    @Operation(opcode = Opcode.FROM_UNSIGNED)
117    public static Word unsigned(long val) {
118        return box(val);
119    }
120
121    /**
122     * Unsafe conversion from a Java long value to a {@link PointerBase pointer}. The parameter is
123     * treated as an unsigned 64-bit value (in contrast to the semantics of a Java long).
124     *
125     * @param val a 64 bit unsigned value
126     * @return the value cast to PointerBase
127     */
128    @Operation(opcode = Opcode.FROM_UNSIGNED)
129    @SuppressWarnings("unchecked")
130    public static <T extends PointerBase> T pointer(long val) {
131        return (T) box(val);
132    }
133
134    /**
135     * Unsafe conversion from a Java int value to a Word. The parameter is treated as an unsigned
136     * 32-bit value (in contrast to the semantics of a Java int).
137     *
138     * @param val a 32 bit unsigned value
139     * @return the value cast to Word
140     */
141    @Operation(opcode = Opcode.FROM_UNSIGNED)
142    public static Word unsigned(int val) {
143        return box(val & 0xffffffffL);
144    }
145
146    /**
147     * Unsafe conversion from a Java long value to a Word. The parameter is treated as a signed
148     * 64-bit value (unchanged semantics of a Java long).
149     *
150     * @param val a 64 bit signed value
151     * @return the value cast to Word
152     */
153    @Operation(opcode = Opcode.FROM_SIGNED)
154    public static Word signed(long val) {
155        return box(val);
156    }
157
158    /**
159     * Unsafe conversion from a Java int value to a Word. The parameter is treated as a signed
160     * 32-bit value (unchanged semantics of a Java int).
161     *
162     * @param val a 32 bit signed value
163     * @return the value cast to Word
164     */
165    @Operation(opcode = Opcode.FROM_SIGNED)
166    public static Word signed(int val) {
167        return box(val);
168    }
169
170    @Override
171    @Operation(opcode = Opcode.TO_RAW_VALUE)
172    public long rawValue() {
173        return unbox();
174    }
175
176    @Operation(opcode = Opcode.FROM_WORDBASE)
177    public static native Word fromWordBase(WordBase val);
178
179    @Operation(opcode = Opcode.FROM_OBJECT)
180    public static native Pointer fromObject(Object val);
181
182    @Operation(opcode = Opcode.FROM_ADDRESS)
183    public static native Pointer fromAddress(Address address);
184
185    @Override
186    @Operation(opcode = Opcode.TO_OBJECT)
187    public native Object toObject();
188
189    @Override
190    @Operation(node = AddNode.class)
191    public Word add(Signed val) {
192        return add((Word) val);
193    }
194
195    @Override
196    @Operation(node = AddNode.class)
197    public Word add(Unsigned val) {
198        return add((Word) val);
199    }
200
201    @Override
202    @Operation(node = AddNode.class)
203    public Word add(int val) {
204        return add(intParam(val));
205    }
206
207    @Operation(node = AddNode.class)
208    public Word add(Word val) {
209        return box(unbox() + val.unbox());
210    }
211
212    @Override
213    @Operation(node = SubNode.class)
214    public Word subtract(Signed val) {
215        return subtract((Word) val);
216    }
217
218    @Override
219    @Operation(node = SubNode.class)
220    public Word subtract(Unsigned val) {
221        return subtract((Word) val);
222    }
223
224    @Override
225    @Operation(node = SubNode.class)
226    public Word subtract(int val) {
227        return subtract(intParam(val));
228    }
229
230    @Operation(node = SubNode.class)
231    public Word subtract(Word val) {
232        return box(unbox() - val.unbox());
233    }
234
235    @Override
236    @Operation(node = MulNode.class)
237    public Word multiply(Signed val) {
238        return multiply((Word) val);
239    }
240
241    @Override
242    @Operation(node = MulNode.class)
243    public Word multiply(Unsigned val) {
244        return multiply((Word) val);
245    }
246
247    @Override
248    @Operation(node = MulNode.class)
249    public Word multiply(int val) {
250        return multiply(intParam(val));
251    }
252
253    @Operation(node = MulNode.class)
254    public Word multiply(Word val) {
255        return box(unbox() * val.unbox());
256    }
257
258    @Override
259    @Operation(node = IntegerDivNode.class)
260    public Word signedDivide(Signed val) {
261        return signedDivide((Word) val);
262    }
263
264    @Override
265    @Operation(node = IntegerDivNode.class)
266    public Word signedDivide(int val) {
267        return signedDivide(intParam(val));
268    }
269
270    @Operation(node = IntegerDivNode.class)
271    public Word signedDivide(Word val) {
272        return box(unbox() / val.unbox());
273    }
274
275    @Override
276    @Operation(node = UnsignedDivNode.class)
277    public Word unsignedDivide(Unsigned val) {
278        return unsignedDivide((Word) val);
279    }
280
281    @Override
282    @Operation(node = UnsignedDivNode.class)
283    public Word unsignedDivide(int val) {
284        return signedDivide(intParam(val));
285    }
286
287    @Operation(node = UnsignedDivNode.class)
288    public Word unsignedDivide(Word val) {
289        return box(UnsignedMath.divide(unbox(), val.unbox()));
290    }
291
292    @Override
293    @Operation(node = IntegerRemNode.class)
294    public Word signedRemainder(Signed val) {
295        return signedRemainder((Word) val);
296    }
297
298    @Override
299    @Operation(node = IntegerRemNode.class)
300    public Word signedRemainder(int val) {
301        return signedRemainder(intParam(val));
302    }
303
304    @Operation(node = IntegerRemNode.class)
305    public Word signedRemainder(Word val) {
306        return box(unbox() % val.unbox());
307    }
308
309    @Override
310    @Operation(node = UnsignedRemNode.class)
311    public Word unsignedRemainder(Unsigned val) {
312        return unsignedRemainder((Word) val);
313    }
314
315    @Override
316    @Operation(node = UnsignedRemNode.class)
317    public Word unsignedRemainder(int val) {
318        return signedRemainder(intParam(val));
319    }
320
321    @Operation(node = UnsignedRemNode.class)
322    public Word unsignedRemainder(Word val) {
323        return box(UnsignedMath.remainder(unbox(), val.unbox()));
324    }
325
326    @Override
327    @Operation(node = LeftShiftNode.class, rightOperandIsInt = true)
328    public Word shiftLeft(Unsigned val) {
329        return shiftLeft((Word) val);
330    }
331
332    @Override
333    @Operation(node = LeftShiftNode.class, rightOperandIsInt = true)
334    public Word shiftLeft(int val) {
335        return shiftLeft(intParam(val));
336    }
337
338    @Operation(node = LeftShiftNode.class, rightOperandIsInt = true)
339    public Word shiftLeft(Word val) {
340        return box(unbox() << val.unbox());
341    }
342
343    @Override
344    @Operation(node = RightShiftNode.class, rightOperandIsInt = true)
345    public Word signedShiftRight(Unsigned val) {
346        return signedShiftRight((Word) val);
347    }
348
349    @Override
350    @Operation(node = RightShiftNode.class, rightOperandIsInt = true)
351    public Word signedShiftRight(int val) {
352        return signedShiftRight(intParam(val));
353    }
354
355    @Operation(node = RightShiftNode.class, rightOperandIsInt = true)
356    public Word signedShiftRight(Word val) {
357        return box(unbox() >> val.unbox());
358    }
359
360    @Override
361    @Operation(node = UnsignedRightShiftNode.class, rightOperandIsInt = true)
362    public Word unsignedShiftRight(Unsigned val) {
363        return unsignedShiftRight((Word) val);
364    }
365
366    @Override
367    @Operation(node = UnsignedRightShiftNode.class, rightOperandIsInt = true)
368    public Word unsignedShiftRight(int val) {
369        return unsignedShiftRight(intParam(val));
370    }
371
372    @Operation(node = UnsignedRightShiftNode.class, rightOperandIsInt = true)
373    public Word unsignedShiftRight(Word val) {
374        return box(unbox() >>> val.unbox());
375    }
376
377    @Override
378    @Operation(node = AndNode.class)
379    public Word and(Signed val) {
380        return and((Word) val);
381    }
382
383    @Override
384    @Operation(node = AndNode.class)
385    public Word and(Unsigned val) {
386        return and((Word) val);
387    }
388
389    @Override
390    @Operation(node = AndNode.class)
391    public Word and(int val) {
392        return and(intParam(val));
393    }
394
395    @Operation(node = AndNode.class)
396    public Word and(Word val) {
397        return box(unbox() & val.unbox());
398    }
399
400    @Override
401    @Operation(node = OrNode.class)
402    public Word or(Signed val) {
403        return or((Word) val);
404    }
405
406    @Override
407    @Operation(node = OrNode.class)
408    public Word or(Unsigned val) {
409        return or((Word) val);
410    }
411
412    @Override
413    @Operation(node = OrNode.class)
414    public Word or(int val) {
415        return or(intParam(val));
416    }
417
418    @Operation(node = OrNode.class)
419    public Word or(Word val) {
420        return box(unbox() | val.unbox());
421    }
422
423    @Override
424    @Operation(node = XorNode.class)
425    public Word xor(Signed val) {
426        return xor((Word) val);
427    }
428
429    @Override
430    @Operation(node = XorNode.class)
431    public Word xor(Unsigned val) {
432        return xor((Word) val);
433    }
434
435    @Override
436    @Operation(node = XorNode.class)
437    public Word xor(int val) {
438        return xor(intParam(val));
439    }
440
441    @Operation(node = XorNode.class)
442    public Word xor(Word val) {
443        return box(unbox() ^ val.unbox());
444    }
445
446    @Override
447    @Operation(opcode = Opcode.NOT)
448    public Word not() {
449        return box(~unbox());
450    }
451
452    @Override
453    @Operation(opcode = Opcode.COMPARISON, condition = Condition.EQ)
454    public boolean equal(ComparableWord val) {
455        return equal((Word) val);
456    }
457
458    @Override
459    @Operation(opcode = Opcode.COMPARISON, condition = Condition.EQ)
460    public boolean equal(Signed val) {
461        return equal((Word) val);
462    }
463
464    @Override
465    @Operation(opcode = Opcode.COMPARISON, condition = Condition.EQ)
466    public boolean equal(Unsigned val) {
467        return equal((Word) val);
468    }
469
470    @Override
471    @Operation(opcode = Opcode.COMPARISON, condition = Condition.EQ)
472    public boolean equal(int val) {
473        return equal(intParam(val));
474    }
475
476    @Operation(opcode = Opcode.COMPARISON, condition = Condition.EQ)
477    public boolean equal(Word val) {
478        return unbox() == val.unbox();
479    }
480
481    @Override
482    @Operation(opcode = Opcode.COMPARISON, condition = Condition.NE)
483    public boolean notEqual(ComparableWord val) {
484        return notEqual((Word) val);
485    }
486
487    @Override
488    @Operation(opcode = Opcode.COMPARISON, condition = Condition.NE)
489    public boolean notEqual(Signed val) {
490        return notEqual((Word) val);
491    }
492
493    @Override
494    @Operation(opcode = Opcode.COMPARISON, condition = Condition.NE)
495    public boolean notEqual(Unsigned val) {
496        return notEqual((Word) val);
497    }
498
499    @Override
500    @Operation(opcode = Opcode.COMPARISON, condition = Condition.NE)
501    public boolean notEqual(int val) {
502        return notEqual(intParam(val));
503    }
504
505    @Operation(opcode = Opcode.COMPARISON, condition = Condition.NE)
506    public boolean notEqual(Word val) {
507        return unbox() != val.unbox();
508    }
509
510    @Override
511    @Operation(opcode = Opcode.COMPARISON, condition = Condition.LT)
512    public boolean lessThan(Signed val) {
513        return lessThan((Word) val);
514    }
515
516    @Override
517    @Operation(opcode = Opcode.COMPARISON, condition = Condition.LT)
518    public boolean lessThan(int val) {
519        return lessThan(intParam(val));
520    }
521
522    @Operation(opcode = Opcode.COMPARISON, condition = Condition.LT)
523    public boolean lessThan(Word val) {
524        return unbox() < val.unbox();
525    }
526
527    @Override
528    @Operation(opcode = Opcode.COMPARISON, condition = Condition.LE)
529    public boolean lessOrEqual(Signed val) {
530        return lessOrEqual((Word) val);
531    }
532
533    @Override
534    @Operation(opcode = Opcode.COMPARISON, condition = Condition.LE)
535    public boolean lessOrEqual(int val) {
536        return lessOrEqual(intParam(val));
537    }
538
539    @Operation(opcode = Opcode.COMPARISON, condition = Condition.LE)
540    public boolean lessOrEqual(Word val) {
541        return unbox() <= val.unbox();
542    }
543
544    @Override
545    @Operation(opcode = Opcode.COMPARISON, condition = Condition.GT)
546    public boolean greaterThan(Signed val) {
547        return greaterThan((Word) val);
548    }
549
550    @Override
551    @Operation(opcode = Opcode.COMPARISON, condition = Condition.GT)
552    public boolean greaterThan(int val) {
553        return greaterThan(intParam(val));
554    }
555
556    @Operation(opcode = Opcode.COMPARISON, condition = Condition.GT)
557    public boolean greaterThan(Word val) {
558        return unbox() > val.unbox();
559    }
560
561    @Override
562    @Operation(opcode = Opcode.COMPARISON, condition = Condition.GE)
563    public boolean greaterOrEqual(Signed val) {
564        return greaterOrEqual((Word) val);
565    }
566
567    @Override
568    @Operation(opcode = Opcode.COMPARISON, condition = Condition.GE)
569    public boolean greaterOrEqual(int val) {
570        return greaterOrEqual(intParam(val));
571    }
572
573    @Operation(opcode = Opcode.COMPARISON, condition = Condition.GE)
574    public boolean greaterOrEqual(Word val) {
575        return unbox() >= val.unbox();
576    }
577
578    @Override
579    @Operation(opcode = Opcode.COMPARISON, condition = Condition.BT)
580    public boolean belowThan(Unsigned val) {
581        return belowThan((Word) val);
582    }
583
584    @Override
585    @Operation(opcode = Opcode.COMPARISON, condition = Condition.BT)
586    public boolean belowThan(int val) {
587        return belowThan(intParam(val));
588    }
589
590    @Operation(opcode = Opcode.COMPARISON, condition = Condition.BT)
591    public boolean belowThan(Word val) {
592        return UnsignedMath.belowThan(unbox(), val.unbox());
593    }
594
595    @Override
596    @Operation(opcode = Opcode.COMPARISON, condition = Condition.BE)
597    public boolean belowOrEqual(Unsigned val) {
598        return belowOrEqual((Word) val);
599    }
600
601    @Override
602    @Operation(opcode = Opcode.COMPARISON, condition = Condition.BE)
603    public boolean belowOrEqual(int val) {
604        return belowOrEqual(intParam(val));
605    }
606
607    @Operation(opcode = Opcode.COMPARISON, condition = Condition.BE)
608    public boolean belowOrEqual(Word val) {
609        return UnsignedMath.belowOrEqual(unbox(), val.unbox());
610    }
611
612    @Override
613    @Operation(opcode = Opcode.COMPARISON, condition = Condition.AT)
614    public boolean aboveThan(Unsigned val) {
615        return aboveThan((Word) val);
616    }
617
618    @Override
619    @Operation(opcode = Opcode.COMPARISON, condition = Condition.AT)
620    public boolean aboveThan(int val) {
621        return aboveThan(intParam(val));
622    }
623
624    @Operation(opcode = Opcode.COMPARISON, condition = Condition.AT)
625    public boolean aboveThan(Word val) {
626        return UnsignedMath.aboveThan(unbox(), val.unbox());
627    }
628
629    @Override
630    @Operation(opcode = Opcode.COMPARISON, condition = Condition.AE)
631    public boolean aboveOrEqual(Unsigned val) {
632        return aboveOrEqual((Word) val);
633    }
634
635    @Override
636    @Operation(opcode = Opcode.COMPARISON, condition = Condition.AE)
637    public boolean aboveOrEqual(int val) {
638        return aboveOrEqual(intParam(val));
639    }
640
641    @Operation(opcode = Opcode.COMPARISON, condition = Condition.AE)
642    public boolean aboveOrEqual(Word val) {
643        return UnsignedMath.aboveOrEqual(unbox(), val.unbox());
644    }
645
646    @Override
647    @Operation(opcode = Opcode.READ_POINTER)
648    public byte readByte(WordBase offset, LocationIdentity locationIdentity) {
649        return unsafe.getByte(add((Word) offset).unbox());
650    }
651
652    @Override
653    @Operation(opcode = Opcode.READ_POINTER)
654    public char readChar(WordBase offset, LocationIdentity locationIdentity) {
655        return unsafe.getChar(add((Word) offset).unbox());
656    }
657
658    @Override
659    @Operation(opcode = Opcode.READ_POINTER)
660    public short readShort(WordBase offset, LocationIdentity locationIdentity) {
661        return unsafe.getShort(add((Word) offset).unbox());
662    }
663
664    @Override
665    @Operation(opcode = Opcode.READ_POINTER)
666    public int readInt(WordBase offset, LocationIdentity locationIdentity) {
667        return unsafe.getInt(add((Word) offset).unbox());
668    }
669
670    @Override
671    @Operation(opcode = Opcode.READ_POINTER)
672    public long readLong(WordBase offset, LocationIdentity locationIdentity) {
673        return unsafe.getLong(add((Word) offset).unbox());
674    }
675
676    @Override
677    @Operation(opcode = Opcode.READ_POINTER)
678    public float readFloat(WordBase offset, LocationIdentity locationIdentity) {
679        return unsafe.getFloat(add((Word) offset).unbox());
680    }
681
682    @Override
683    @Operation(opcode = Opcode.READ_POINTER)
684    public double readDouble(WordBase offset, LocationIdentity locationIdentity) {
685        return unsafe.getDouble(add((Word) offset).unbox());
686    }
687
688    @Override
689    @Operation(opcode = Opcode.READ_POINTER)
690    public Word readWord(WordBase offset, LocationIdentity locationIdentity) {
691        return box(unsafe.getAddress(add((Word) offset).unbox()));
692    }
693
694    @Override
695    @Operation(opcode = Opcode.READ_POINTER)
696    public native Object readObject(WordBase offset, LocationIdentity locationIdentity);
697
698    @Override
699    @Operation(opcode = Opcode.READ_POINTER)
700    public byte readByte(int offset, LocationIdentity locationIdentity) {
701        return readByte(signed(offset), locationIdentity);
702    }
703
704    @Override
705    @Operation(opcode = Opcode.READ_POINTER)
706    public char readChar(int offset, LocationIdentity locationIdentity) {
707        return readChar(signed(offset), locationIdentity);
708    }
709
710    @Override
711    @Operation(opcode = Opcode.READ_POINTER)
712    public short readShort(int offset, LocationIdentity locationIdentity) {
713        return readShort(signed(offset), locationIdentity);
714    }
715
716    @Override
717    @Operation(opcode = Opcode.READ_POINTER)
718    public int readInt(int offset, LocationIdentity locationIdentity) {
719        return readInt(signed(offset), locationIdentity);
720    }
721
722    @Override
723    @Operation(opcode = Opcode.READ_POINTER)
724    public long readLong(int offset, LocationIdentity locationIdentity) {
725        return readLong(signed(offset), locationIdentity);
726    }
727
728    @Override
729    @Operation(opcode = Opcode.READ_POINTER)
730    public float readFloat(int offset, LocationIdentity locationIdentity) {
731        return readFloat(signed(offset), locationIdentity);
732    }
733
734    @Override
735    @Operation(opcode = Opcode.READ_POINTER)
736    public double readDouble(int offset, LocationIdentity locationIdentity) {
737        return readDouble(signed(offset), locationIdentity);
738    }
739
740    @Override
741    @Operation(opcode = Opcode.READ_POINTER)
742    public Word readWord(int offset, LocationIdentity locationIdentity) {
743        return readWord(signed(offset), locationIdentity);
744    }
745
746    @Override
747    @Operation(opcode = Opcode.READ_POINTER)
748    public Object readObject(int offset, LocationIdentity locationIdentity) {
749        return readObject(signed(offset), locationIdentity);
750    }
751
752    @Override
753    @Operation(opcode = Opcode.WRITE_POINTER)
754    public void writeByte(WordBase offset, byte val, LocationIdentity locationIdentity) {
755        unsafe.putByte(add((Word) offset).unbox(), val);
756    }
757
758    @Override
759    @Operation(opcode = Opcode.WRITE_POINTER)
760    public void writeChar(WordBase offset, char val, LocationIdentity locationIdentity) {
761        unsafe.putChar(add((Word) offset).unbox(), val);
762    }
763
764    @Override
765    @Operation(opcode = Opcode.WRITE_POINTER)
766    public void writeShort(WordBase offset, short val, LocationIdentity locationIdentity) {
767        unsafe.putShort(add((Word) offset).unbox(), val);
768    }
769
770    @Override
771    @Operation(opcode = Opcode.WRITE_POINTER)
772    public void writeInt(WordBase offset, int val, LocationIdentity locationIdentity) {
773        unsafe.putInt(add((Word) offset).unbox(), val);
774    }
775
776    @Override
777    @Operation(opcode = Opcode.WRITE_POINTER)
778    public void writeLong(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 void writeFloat(WordBase offset, float val, LocationIdentity locationIdentity) {
785        unsafe.putFloat(add((Word) offset).unbox(), val);
786    }
787
788    @Override
789    @Operation(opcode = Opcode.WRITE_POINTER)
790    public void writeDouble(WordBase offset, double val, LocationIdentity locationIdentity) {
791        unsafe.putDouble(add((Word) offset).unbox(), val);
792    }
793
794    @Override
795    @Operation(opcode = Opcode.WRITE_POINTER)
796    public void writeWord(WordBase offset, WordBase val, LocationIdentity locationIdentity) {
797        unsafe.putAddress(add((Word) offset).unbox(), ((Word) val).unbox());
798    }
799
800    @Override
801    @Operation(opcode = Opcode.INITIALIZE)
802    public void initializeLong(WordBase offset, long val, LocationIdentity locationIdentity) {
803        unsafe.putLong(add((Word) offset).unbox(), val);
804    }
805
806    @Override
807    @Operation(opcode = Opcode.WRITE_POINTER)
808    public native void writeObject(WordBase offset, Object val, LocationIdentity locationIdentity);
809
810    @Override
811    @Operation(opcode = Opcode.WRITE_POINTER)
812    public void writeByte(int offset, byte val, LocationIdentity locationIdentity) {
813        writeByte(signed(offset), val, locationIdentity);
814    }
815
816    @Override
817    @Operation(opcode = Opcode.WRITE_POINTER)
818    public void writeChar(int offset, char val, LocationIdentity locationIdentity) {
819        writeChar(signed(offset), val, locationIdentity);
820    }
821
822    @Override
823    @Operation(opcode = Opcode.WRITE_POINTER)
824    public void writeShort(int offset, short val, LocationIdentity locationIdentity) {
825        writeShort(signed(offset), val, locationIdentity);
826    }
827
828    @Override
829    @Operation(opcode = Opcode.WRITE_POINTER)
830    public void writeInt(int offset, int val, LocationIdentity locationIdentity) {
831        writeInt(signed(offset), val, locationIdentity);
832    }
833
834    @Override
835    @Operation(opcode = Opcode.WRITE_POINTER)
836    public void writeLong(int offset, long val, LocationIdentity locationIdentity) {
837        writeLong(signed(offset), val, locationIdentity);
838    }
839
840    @Override
841    @Operation(opcode = Opcode.WRITE_POINTER)
842    public void writeFloat(int offset, float val, LocationIdentity locationIdentity) {
843        writeFloat(signed(offset), val, locationIdentity);
844    }
845
846    @Override
847    @Operation(opcode = Opcode.WRITE_POINTER)
848    public void writeDouble(int offset, double val, LocationIdentity locationIdentity) {
849        writeDouble(signed(offset), val, locationIdentity);
850    }
851
852    @Override
853    @Operation(opcode = Opcode.WRITE_POINTER)
854    public void writeWord(int offset, WordBase val, LocationIdentity locationIdentity) {
855        writeWord(signed(offset), val, locationIdentity);
856    }
857
858    @Override
859    @Operation(opcode = Opcode.INITIALIZE)
860    public void initializeLong(int offset, long val, LocationIdentity locationIdentity) {
861        initializeLong(signed(offset), val, locationIdentity);
862    }
863
864    @Override
865    @Operation(opcode = Opcode.WRITE_POINTER)
866    public void writeObject(int offset, Object val, LocationIdentity locationIdentity) {
867        writeObject(signed(offset), val, locationIdentity);
868    }
869
870    @Override
871    @Operation(opcode = Opcode.READ_POINTER)
872    public byte readByte(WordBase offset) {
873        return unsafe.getByte(add((Word) offset).unbox());
874    }
875
876    @Override
877    @Operation(opcode = Opcode.READ_POINTER)
878    public char readChar(WordBase offset) {
879        return unsafe.getChar(add((Word) offset).unbox());
880    }
881
882    @Override
883    @Operation(opcode = Opcode.READ_POINTER)
884    public short readShort(WordBase offset) {
885        return unsafe.getShort(add((Word) offset).unbox());
886    }
887
888    @Override
889    @Operation(opcode = Opcode.READ_POINTER)
890    public int readInt(WordBase offset) {
891        return unsafe.getInt(add((Word) offset).unbox());
892    }
893
894    @Override
895    @Operation(opcode = Opcode.READ_POINTER)
896    public long readLong(WordBase offset) {
897        return unsafe.getLong(add((Word) offset).unbox());
898    }
899
900    @Override
901    @Operation(opcode = Opcode.READ_POINTER)
902    public float readFloat(WordBase offset) {
903        return unsafe.getFloat(add((Word) offset).unbox());
904    }
905
906    @Override
907    @Operation(opcode = Opcode.READ_POINTER)
908    public double readDouble(WordBase offset) {
909        return unsafe.getDouble(add((Word) offset).unbox());
910    }
911
912    @Override
913    @Operation(opcode = Opcode.READ_POINTER)
914    public Word readWord(WordBase offset) {
915        return box(unsafe.getAddress(add((Word) offset).unbox()));
916    }
917
918    @Override
919    @Operation(opcode = Opcode.READ_POINTER)
920    public native Object readObject(WordBase offset);
921
922    @Operation(opcode = Opcode.READ_HEAP)
923    public native Object readObject(WordBase offset, BarrierType barrierType);
924
925    @Override
926    @Operation(opcode = Opcode.READ_POINTER)
927    public byte readByte(int offset) {
928        return readByte(signed(offset));
929    }
930
931    @Override
932    @Operation(opcode = Opcode.READ_POINTER)
933    public char readChar(int offset) {
934        return readChar(signed(offset));
935    }
936
937    @Override
938    @Operation(opcode = Opcode.READ_POINTER)
939    public short readShort(int offset) {
940        return readShort(signed(offset));
941    }
942
943    @Override
944    @Operation(opcode = Opcode.READ_POINTER)
945    public int readInt(int offset) {
946        return readInt(signed(offset));
947    }
948
949    @Override
950    @Operation(opcode = Opcode.READ_POINTER)
951    public long readLong(int offset) {
952        return readLong(signed(offset));
953    }
954
955    @Override
956    @Operation(opcode = Opcode.READ_POINTER)
957    public float readFloat(int offset) {
958        return readFloat(signed(offset));
959    }
960
961    @Override
962    @Operation(opcode = Opcode.READ_POINTER)
963    public double readDouble(int offset) {
964        return readDouble(signed(offset));
965    }
966
967    @Override
968    @Operation(opcode = Opcode.READ_POINTER)
969    public Word readWord(int offset) {
970        return readWord(signed(offset));
971    }
972
973    @Override
974    @Operation(opcode = Opcode.READ_POINTER)
975    public Object readObject(int offset) {
976        return readObject(signed(offset));
977    }
978
979    @Operation(opcode = Opcode.READ_HEAP)
980    public Object readObject(int offset, BarrierType barrierType) {
981        return readObject(signed(offset), barrierType);
982    }
983
984    @Override
985    @Operation(opcode = Opcode.WRITE_POINTER)
986    public void writeByte(WordBase offset, byte val) {
987        unsafe.putByte(add((Word) offset).unbox(), val);
988    }
989
990    @Override
991    @Operation(opcode = Opcode.WRITE_POINTER)
992    public void writeChar(WordBase offset, char val) {
993        unsafe.putChar(add((Word) offset).unbox(), val);
994    }
995
996    @Override
997    @Operation(opcode = Opcode.WRITE_POINTER)
998    public void writeShort(WordBase offset, short val) {
999        unsafe.putShort(add((Word) offset).unbox(), val);
1000    }
1001
1002    @Override
1003    @Operation(opcode = Opcode.WRITE_POINTER)
1004    public void writeInt(WordBase offset, int val) {
1005        unsafe.putInt(add((Word) offset).unbox(), val);
1006    }
1007
1008    @Override
1009    @Operation(opcode = Opcode.WRITE_POINTER)
1010    public void writeLong(WordBase offset, long val) {
1011        unsafe.putLong(add((Word) offset).unbox(), val);
1012    }
1013
1014    @Override
1015    @Operation(opcode = Opcode.WRITE_POINTER)
1016    public void writeFloat(WordBase offset, float val) {
1017        unsafe.putFloat(add((Word) offset).unbox(), val);
1018    }
1019
1020    @Override
1021    @Operation(opcode = Opcode.WRITE_POINTER)
1022    public void writeDouble(WordBase offset, double val) {
1023        unsafe.putDouble(add((Word) offset).unbox(), val);
1024    }
1025
1026    @Override
1027    @Operation(opcode = Opcode.WRITE_POINTER)
1028    public void writeWord(WordBase offset, WordBase val) {
1029        unsafe.putAddress(add((Word) offset).unbox(), ((Word) val).unbox());
1030    }
1031
1032    @Override
1033    @Operation(opcode = Opcode.WRITE_POINTER)
1034    public native void writeObject(WordBase offset, Object val);
1035
1036    @Override
1037    @Operation(opcode = Opcode.WRITE_POINTER)
1038    public void writeByte(int offset, byte val) {
1039        writeByte(signed(offset), val);
1040    }
1041
1042    @Override
1043    @Operation(opcode = Opcode.WRITE_POINTER)
1044    public void writeChar(int offset, char val) {
1045        writeChar(signed(offset), val);
1046    }
1047
1048    @Override
1049    @Operation(opcode = Opcode.WRITE_POINTER)
1050    public void writeShort(int offset, short val) {
1051        writeShort(signed(offset), val);
1052    }
1053
1054    @Override
1055    @Operation(opcode = Opcode.WRITE_POINTER)
1056    public void writeInt(int offset, int val) {
1057        writeInt(signed(offset), val);
1058    }
1059
1060    @Override
1061    @Operation(opcode = Opcode.WRITE_POINTER)
1062    public void writeLong(int offset, long val) {
1063        writeLong(signed(offset), val);
1064    }
1065
1066    @Override
1067    @Operation(opcode = Opcode.WRITE_POINTER)
1068    public void writeFloat(int offset, float val) {
1069        writeFloat(signed(offset), val);
1070    }
1071
1072    @Override
1073    @Operation(opcode = Opcode.WRITE_POINTER)
1074    public void writeDouble(int offset, double val) {
1075        writeDouble(signed(offset), val);
1076    }
1077
1078    @Override
1079    @Operation(opcode = Opcode.WRITE_POINTER)
1080    public void writeWord(int offset, WordBase val) {
1081        writeWord(signed(offset), val);
1082    }
1083
1084    @Override
1085    @Operation(opcode = Opcode.WRITE_POINTER)
1086    public void writeObject(int offset, Object val) {
1087        writeObject(signed(offset), val);
1088    }
1089
1090    @Override
1091    public final boolean equals(Object obj) {
1092        throw JVMCIError.shouldNotReachHere("equals must not be called on words");
1093    }
1094
1095    @Override
1096    public final int hashCode() {
1097        throw JVMCIError.shouldNotReachHere("hashCode must not be called on words");
1098    }
1099
1100    @Override
1101    public String toString() {
1102        throw JVMCIError.shouldNotReachHere("toString must not be called on words");
1103    }
1104}
1105
1106final class HostedWord extends Word {
1107
1108    private static final int SMALL_FROM = -1;
1109    private static final int SMALL_TO = 100;
1110
1111    private static final HostedWord[] smallCache = new HostedWord[SMALL_TO - SMALL_FROM + 1];
1112
1113    static {
1114        for (int i = SMALL_FROM; i <= SMALL_TO; i++) {
1115            smallCache[i - SMALL_FROM] = new HostedWord(i);
1116        }
1117    }
1118
1119    private final long rawValue;
1120
1121    private HostedWord(long rawValue) {
1122        this.rawValue = rawValue;
1123    }
1124
1125    protected static Word boxLong(long val) {
1126        if (val >= SMALL_FROM && val <= SMALL_TO) {
1127            return smallCache[(int) val - SMALL_FROM];
1128        }
1129        return new HostedWord(val);
1130    }
1131
1132    @Override
1133    protected long unbox() {
1134        return rawValue;
1135    }
1136
1137    @Override
1138    public String toString() {
1139        return "Word<" + rawValue + ">";
1140    }
1141}