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