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