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