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