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