001/* 002 * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. 003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 004 * 005 * This code is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU General Public License version 2 only, as 007 * published by the Free Software Foundation. 008 * 009 * This code is distributed in the hope that it will be useful, but WITHOUT 010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 011 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 012 * version 2 for more details (a copy is included in the LICENSE file that 013 * accompanied this code). 014 * 015 * You should have received a copy of the GNU General Public License version 016 * 2 along with this work; if not, write to the Free Software Foundation, 017 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 018 * 019 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 020 * or visit www.oracle.com if you need additional information or have any 021 * questions. 022 */ 023package com.oracle.graal.hotspot.replacements; 024 025import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; 026import static com.oracle.graal.hotspot.meta.HotSpotForeignCallsProviderImpl.*; 027import static com.oracle.graal.nodes.extended.BranchProbabilityNode.*; 028import static jdk.internal.jvmci.common.UnsafeAccess.*; 029import jdk.internal.jvmci.code.*; 030import jdk.internal.jvmci.common.*; 031import jdk.internal.jvmci.hotspot.*; 032import jdk.internal.jvmci.meta.Assumptions.AssumptionResult; 033import jdk.internal.jvmci.meta.*; 034 035import com.oracle.graal.api.replacements.*; 036import com.oracle.graal.compiler.common.*; 037import com.oracle.graal.compiler.common.spi.*; 038import com.oracle.graal.compiler.common.type.*; 039import com.oracle.graal.graph.Node.ConstantNodeParameter; 040import com.oracle.graal.graph.Node.NodeIntrinsic; 041import com.oracle.graal.graph.spi.*; 042import com.oracle.graal.hotspot.nodes.*; 043import com.oracle.graal.hotspot.word.*; 044import com.oracle.graal.nodes.*; 045import com.oracle.graal.nodes.extended.*; 046import com.oracle.graal.nodes.memory.*; 047import com.oracle.graal.nodes.memory.address.*; 048import com.oracle.graal.nodes.type.*; 049import com.oracle.graal.replacements.*; 050import com.oracle.graal.replacements.nodes.*; 051import com.oracle.graal.word.*; 052 053//JaCoCo Exclude 054 055/** 056 * A collection of methods used in HotSpot snippets, substitutions and stubs. 057 */ 058public class HotSpotReplacementsUtil { 059 060 abstract static class HotSpotOptimizingLocationIdentity extends NamedLocationIdentity implements CanonicalizableLocation { 061 062 HotSpotOptimizingLocationIdentity(String name) { 063 super(name, true); 064 } 065 066 @Override 067 public abstract ValueNode canonicalizeRead(ValueNode read, AddressNode location, ValueNode object, CanonicalizerTool tool); 068 069 protected ValueNode findReadHub(ValueNode object) { 070 ValueNode base = object; 071 if (base instanceof CompressionNode) { 072 base = ((CompressionNode) base).getValue(); 073 } 074 if (base instanceof Access) { 075 Access access = (Access) base; 076 if (access.getLocationIdentity().equals(HUB_LOCATION)) { 077 AddressNode address = access.getAddress(); 078 if (address instanceof OffsetAddressNode) { 079 OffsetAddressNode offset = (OffsetAddressNode) address; 080 return offset.getBase(); 081 } 082 } 083 } else if (base instanceof LoadHubNode) { 084 LoadHubNode loadhub = (LoadHubNode) base; 085 return loadhub.getValue(); 086 } 087 return null; 088 } 089 090 /** 091 * Fold reads that convert from Class -> Hub -> Class or vice versa. 092 * 093 * @param read 094 * @param object 095 * @param otherLocation 096 * @return an earlier read or the original {@code read} 097 */ 098 protected static ValueNode foldIndirection(ValueNode read, ValueNode object, LocationIdentity otherLocation) { 099 if (object instanceof Access) { 100 Access access = (Access) object; 101 if (access.getLocationIdentity().equals(otherLocation)) { 102 AddressNode address = access.getAddress(); 103 if (address instanceof OffsetAddressNode) { 104 OffsetAddressNode offset = (OffsetAddressNode) address; 105 assert offset.getBase().stamp().isCompatible(read.stamp()); 106 return offset.getBase(); 107 } 108 } 109 } 110 return read; 111 } 112 } 113 114 @Fold 115 public static HotSpotVMConfig config() { 116 return runtime().getConfig(); 117 } 118 119 @Fold 120 public static boolean useTLAB() { 121 return config().useTLAB; 122 } 123 124 @Fold 125 public static boolean verifyOops() { 126 return config().verifyOops; 127 } 128 129 public static final LocationIdentity EXCEPTION_OOP_LOCATION = NamedLocationIdentity.mutable("ExceptionOop"); 130 131 /** 132 * @see HotSpotVMConfig#threadExceptionOopOffset 133 */ 134 @Fold 135 public static int threadExceptionOopOffset() { 136 return config().threadExceptionOopOffset; 137 } 138 139 public static final LocationIdentity EXCEPTION_PC_LOCATION = NamedLocationIdentity.mutable("ExceptionPc"); 140 141 @Fold 142 public static int threadExceptionPcOffset() { 143 return config().threadExceptionPcOffset; 144 } 145 146 public static final LocationIdentity LAST_JAVA_PC_LOCATION = NamedLocationIdentity.mutable("LastJavaPc"); 147 148 @Fold 149 public static int threadLastJavaPcOffset() { 150 return config().threadLastJavaPcOffset(); 151 } 152 153 public static final LocationIdentity LAST_JAVA_FP_LOCATION = NamedLocationIdentity.mutable("LastJavaFp"); 154 155 @Fold 156 public static int threadLastJavaFpOffset() { 157 return config().threadLastJavaFpOffset(); 158 } 159 160 public static final LocationIdentity TLAB_TOP_LOCATION = NamedLocationIdentity.mutable("TlabTop"); 161 162 @Fold 163 public static int threadTlabTopOffset() { 164 return config().threadTlabTopOffset(); 165 } 166 167 public static final LocationIdentity TLAB_END_LOCATION = NamedLocationIdentity.mutable("TlabEnd"); 168 169 @Fold 170 private static int threadTlabEndOffset() { 171 return config().threadTlabEndOffset(); 172 } 173 174 public static final LocationIdentity TLAB_START_LOCATION = NamedLocationIdentity.mutable("TlabStart"); 175 176 @Fold 177 private static int threadTlabStartOffset() { 178 return config().threadTlabStartOffset(); 179 } 180 181 public static final LocationIdentity PENDING_EXCEPTION_LOCATION = NamedLocationIdentity.mutable("PendingException"); 182 183 /** 184 * @see HotSpotVMConfig#pendingExceptionOffset 185 */ 186 @Fold 187 private static int threadPendingExceptionOffset() { 188 return config().pendingExceptionOffset; 189 } 190 191 public static final LocationIdentity PENDING_DEOPTIMIZATION_LOCATION = NamedLocationIdentity.mutable("PendingDeoptimization"); 192 193 /** 194 * @see HotSpotVMConfig#pendingDeoptimizationOffset 195 */ 196 @Fold 197 private static int threadPendingDeoptimizationOffset() { 198 return config().pendingDeoptimizationOffset; 199 } 200 201 public static final LocationIdentity OBJECT_RESULT_LOCATION = NamedLocationIdentity.mutable("ObjectResult"); 202 203 @Fold 204 private static int objectResultOffset() { 205 return config().threadObjectResultOffset; 206 } 207 208 /** 209 * @see HotSpotVMConfig#threadExceptionOopOffset 210 */ 211 public static Object readExceptionOop(Word thread) { 212 return thread.readObject(threadExceptionOopOffset(), EXCEPTION_OOP_LOCATION); 213 } 214 215 public static Word readExceptionPc(Word thread) { 216 return thread.readWord(threadExceptionPcOffset(), EXCEPTION_PC_LOCATION); 217 } 218 219 /** 220 * @see HotSpotVMConfig#threadExceptionOopOffset 221 */ 222 public static void writeExceptionOop(Word thread, Object value) { 223 thread.writeObject(threadExceptionOopOffset(), value, EXCEPTION_OOP_LOCATION); 224 } 225 226 public static void writeExceptionPc(Word thread, Word value) { 227 thread.writeWord(threadExceptionPcOffset(), value, EXCEPTION_PC_LOCATION); 228 } 229 230 public static void writeLastJavaPc(Word thread, Word value) { 231 thread.writeWord(threadLastJavaPcOffset(), value, LAST_JAVA_PC_LOCATION); 232 } 233 234 public static void writeLastJavaFp(Word thread, Word value) { 235 thread.writeWord(threadLastJavaFpOffset(), value, LAST_JAVA_FP_LOCATION); 236 } 237 238 public static Word readTlabTop(Word thread) { 239 return thread.readWord(threadTlabTopOffset(), TLAB_TOP_LOCATION); 240 } 241 242 public static Word readTlabEnd(Word thread) { 243 return thread.readWord(threadTlabEndOffset(), TLAB_END_LOCATION); 244 } 245 246 public static Word readTlabStart(Word thread) { 247 return thread.readWord(threadTlabStartOffset(), TLAB_START_LOCATION); 248 } 249 250 public static void writeTlabTop(Word thread, Word top) { 251 thread.writeWord(threadTlabTopOffset(), top, TLAB_TOP_LOCATION); 252 } 253 254 public static void initializeTlab(Word thread, Word start, Word end) { 255 thread.writeWord(threadTlabStartOffset(), start, TLAB_START_LOCATION); 256 thread.writeWord(threadTlabTopOffset(), start, TLAB_TOP_LOCATION); 257 thread.writeWord(threadTlabEndOffset(), end, TLAB_END_LOCATION); 258 } 259 260 /** 261 * Clears the pending exception for the given thread. 262 * 263 * @return {@code true} if there was a pending exception 264 */ 265 public static boolean clearPendingException(Word thread) { 266 boolean result = thread.readObject(threadPendingExceptionOffset(), PENDING_EXCEPTION_LOCATION) != null; 267 thread.writeObject(threadPendingExceptionOffset(), null, PENDING_EXCEPTION_LOCATION); 268 return result; 269 } 270 271 /** 272 * Reads the pending deoptimization value for the given thread. 273 * 274 * @return {@code true} if there was a pending deoptimization 275 */ 276 public static int readPendingDeoptimization(Word thread) { 277 return thread.readInt(threadPendingDeoptimizationOffset(), PENDING_DEOPTIMIZATION_LOCATION); 278 } 279 280 /** 281 * Writes the pending deoptimization value for the given thread. 282 */ 283 public static void writePendingDeoptimization(Word thread, int value) { 284 thread.writeInt(threadPendingDeoptimizationOffset(), value, PENDING_DEOPTIMIZATION_LOCATION); 285 } 286 287 /** 288 * Gets and clears the object result from a runtime call stored in a thread local. 289 * 290 * @return the object that was in the thread local 291 */ 292 public static Object getAndClearObjectResult(Word thread) { 293 Object result = thread.readObject(objectResultOffset(), OBJECT_RESULT_LOCATION); 294 thread.writeObject(objectResultOffset(), null, OBJECT_RESULT_LOCATION); 295 return result; 296 } 297 298 public static final LocationIdentity JAVA_THREAD_THREAD_OBJECT_LOCATION = NamedLocationIdentity.mutable("JavaThread::_threadObj"); 299 300 @Fold 301 public static int threadObjectOffset() { 302 return config().threadObjectOffset; 303 } 304 305 public static final LocationIdentity JAVA_THREAD_OSTHREAD_LOCATION = NamedLocationIdentity.mutable("JavaThread::_osthread"); 306 307 @Fold 308 public static int osThreadOffset() { 309 return config().osThreadOffset; 310 } 311 312 @Fold 313 public static int osThreadInterruptedOffset() { 314 return config().osThreadInterruptedOffset; 315 } 316 317 @Fold 318 public static Kind getWordKind() { 319 return runtime().getTarget().wordKind; 320 } 321 322 @Fold 323 public static int wordSize() { 324 return runtime().getTarget().wordSize; 325 } 326 327 @Fold 328 public static int pageSize() { 329 return unsafe.pageSize(); 330 } 331 332 @Fold 333 public static int heapWordSize() { 334 return config().heapWordSize; 335 } 336 337 public static final LocationIdentity PROTOTYPE_MARK_WORD_LOCATION = NamedLocationIdentity.mutable("PrototypeMarkWord"); 338 339 @Fold 340 public static int prototypeMarkWordOffset() { 341 return config().prototypeMarkWordOffset; 342 } 343 344 @Fold 345 public static long arrayPrototypeMarkWord() { 346 return config().arrayPrototypeMarkWord(); 347 } 348 349 public static final LocationIdentity KLASS_ACCESS_FLAGS_LOCATION = NamedLocationIdentity.immutable("Klass::_access_flags"); 350 351 @Fold 352 public static int klassAccessFlagsOffset() { 353 return config().klassAccessFlagsOffset; 354 } 355 356 @Fold 357 public static int jvmAccWrittenFlags() { 358 return config().jvmAccWrittenFlags; 359 } 360 361 public static final LocationIdentity KLASS_LAYOUT_HELPER_LOCATION = new HotSpotOptimizingLocationIdentity("Klass::_layout_helper") { 362 @Override 363 public ValueNode canonicalizeRead(ValueNode read, AddressNode location, ValueNode object, CanonicalizerTool tool) { 364 ValueNode javaObject = findReadHub(object); 365 if (javaObject != null) { 366 if (javaObject.stamp() instanceof ObjectStamp) { 367 ObjectStamp stamp = (ObjectStamp) javaObject.stamp(); 368 HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) stamp.javaType(tool.getMetaAccess()); 369 if (type.isArray() && !type.getComponentType().isPrimitive()) { 370 int layout = ((HotSpotResolvedObjectTypeImpl) type).layoutHelper(); 371 return ConstantNode.forInt(layout); 372 } 373 } 374 } 375 return read; 376 } 377 }; 378 379 @Fold 380 public static int klassLayoutHelperOffset() { 381 return config().klassLayoutHelperOffset; 382 } 383 384 public static int readLayoutHelper(KlassPointer hub) { 385 // return hub.readInt(klassLayoutHelperOffset(), KLASS_LAYOUT_HELPER_LOCATION); 386 GuardingNode anchorNode = SnippetAnchorNode.anchor(); 387 return loadKlassLayoutHelperIntrinsic(hub, anchorNode); 388 } 389 390 @NodeIntrinsic(value = KlassLayoutHelperNode.class) 391 public static native int loadKlassLayoutHelperIntrinsic(KlassPointer object, GuardingNode anchor); 392 393 @NodeIntrinsic(value = KlassLayoutHelperNode.class) 394 public static native int loadKlassLayoutHelperIntrinsic(KlassPointer object); 395 396 /** 397 * Checks if class {@code klass} is an array. 398 * 399 * See: Klass::layout_helper_is_array 400 * 401 * @param klass the class to be checked 402 * @return true if klass is an array, false otherwise 403 */ 404 public static boolean klassIsArray(KlassPointer klass) { 405 /* 406 * The less-than check only works if both values are ints. We use local variables to make 407 * sure these are still ints and haven't changed. 408 */ 409 final int layoutHelper = readLayoutHelper(klass); 410 final int layoutHelperNeutralValue = config().klassLayoutHelperNeutralValue; 411 return (layoutHelper < layoutHelperNeutralValue); 412 } 413 414 public static final LocationIdentity ARRAY_KLASS_COMPONENT_MIRROR = NamedLocationIdentity.immutable("ArrayKlass::_component_mirror"); 415 416 @Fold 417 public static int arrayKlassComponentMirrorOffset() { 418 return config().arrayKlassComponentMirrorOffset; 419 } 420 421 public static final LocationIdentity KLASS_SUPER_KLASS_LOCATION = NamedLocationIdentity.immutable("Klass::_super"); 422 423 @Fold 424 public static int klassSuperKlassOffset() { 425 return config().klassSuperKlassOffset; 426 } 427 428 public static final LocationIdentity MARK_WORD_LOCATION = NamedLocationIdentity.mutable("MarkWord"); 429 430 @Fold 431 public static int markOffset() { 432 return config().markOffset; 433 } 434 435 public static final LocationIdentity HUB_WRITE_LOCATION = NamedLocationIdentity.mutable("Hub:write"); 436 437 public static final LocationIdentity HUB_LOCATION = new HotSpotOptimizingLocationIdentity("Hub") { 438 @Override 439 public ValueNode canonicalizeRead(ValueNode read, AddressNode location, ValueNode object, CanonicalizerTool tool) { 440 ResolvedJavaType constantType = LoadHubNode.findSynonymType(read.graph(), tool.getMetaAccess(), object); 441 if (constantType != null) { 442 if (config().useCompressedClassPointers) { 443 return ConstantNode.forConstant(read.stamp(), ((HotSpotMetaspaceConstant) constantType.getObjectHub()).compress(config().getKlassEncoding()), tool.getMetaAccess()); 444 } else { 445 return ConstantNode.forConstant(read.stamp(), constantType.getObjectHub(), tool.getMetaAccess()); 446 } 447 } 448 return read; 449 } 450 }; 451 452 @Fold 453 private static int hubOffset() { 454 return config().hubOffset; 455 } 456 457 public static void initializeObjectHeader(Word memory, Word markWord, KlassPointer hub) { 458 memory.writeWord(markOffset(), markWord, MARK_WORD_LOCATION); 459 StoreHubNode.write(memory, hub); 460 } 461 462 @Fold 463 public static int unlockedMask() { 464 return config().unlockedMask; 465 } 466 467 /** 468 * Mask for a biasable, locked or unlocked mark word. 469 * 470 * <pre> 471 * +----------------------------------+-+-+ 472 * | 1|1|1| 473 * +----------------------------------+-+-+ 474 * </pre> 475 * 476 */ 477 @Fold 478 public static int biasedLockMaskInPlace() { 479 return config().biasedLockMaskInPlace; 480 } 481 482 @Fold 483 public static int epochMaskInPlace() { 484 return config().epochMaskInPlace; 485 } 486 487 /** 488 * Pattern for a biasable, unlocked mark word. 489 * 490 * <pre> 491 * +----------------------------------+-+-+ 492 * | 1|0|1| 493 * +----------------------------------+-+-+ 494 * </pre> 495 * 496 */ 497 @Fold 498 public static int biasedLockPattern() { 499 return config().biasedLockPattern; 500 } 501 502 @Fold 503 public static int ageMaskInPlace() { 504 return config().ageMaskInPlace; 505 } 506 507 @Fold 508 public static int metaspaceArrayLengthOffset() { 509 return config().metaspaceArrayLengthOffset; 510 } 511 512 @Fold 513 public static int metaspaceArrayBaseOffset() { 514 return config().metaspaceArrayBaseOffset; 515 } 516 517 @Fold 518 public static int arrayLengthOffset() { 519 return config().arrayLengthOffset; 520 } 521 522 @Fold 523 public static int arrayBaseOffset(Kind elementKind) { 524 return runtime().getJVMCIRuntime().getArrayBaseOffset(elementKind); 525 } 526 527 @Fold 528 public static int arrayIndexScale(Kind elementKind) { 529 return runtime().getJVMCIRuntime().getArrayIndexScale(elementKind); 530 } 531 532 @Fold 533 public static int instanceHeaderSize() { 534 return config().useCompressedClassPointers ? (2 * wordSize()) - 4 : 2 * wordSize(); 535 } 536 537 @Fold 538 public static byte dirtyCardValue() { 539 return config().dirtyCardValue; 540 } 541 542 @Fold 543 public static byte g1YoungCardValue() { 544 return config().g1YoungCardValue; 545 } 546 547 @Fold 548 public static int cardTableShift() { 549 return config().cardtableShift(); 550 } 551 552 @Fold 553 public static long cardTableStart() { 554 return config().cardtableStartAddress(); 555 } 556 557 @Fold 558 public static int g1CardQueueIndexOffset() { 559 return config().g1CardQueueIndexOffset(); 560 } 561 562 @Fold 563 public static int g1CardQueueBufferOffset() { 564 return config().g1CardQueueBufferOffset(); 565 } 566 567 @Fold 568 public static int logOfHeapRegionGrainBytes() { 569 return config().logOfHRGrainBytes; 570 } 571 572 @Fold 573 public static int g1SATBQueueMarkingOffset() { 574 return config().g1SATBQueueMarkingOffset(); 575 } 576 577 @Fold 578 public static int g1SATBQueueIndexOffset() { 579 return config().g1SATBQueueIndexOffset(); 580 } 581 582 @Fold 583 public static int g1SATBQueueBufferOffset() { 584 return config().g1SATBQueueBufferOffset(); 585 } 586 587 public static final LocationIdentity KLASS_SUPER_CHECK_OFFSET_LOCATION = NamedLocationIdentity.immutable("Klass::_super_check_offset"); 588 589 @Fold 590 public static int superCheckOffsetOffset() { 591 return config().superCheckOffsetOffset; 592 } 593 594 public static final LocationIdentity SECONDARY_SUPER_CACHE_LOCATION = NamedLocationIdentity.mutable("SecondarySuperCache"); 595 596 @Fold 597 public static int secondarySuperCacheOffset() { 598 return config().secondarySuperCacheOffset; 599 } 600 601 public static final LocationIdentity SECONDARY_SUPERS_LOCATION = NamedLocationIdentity.immutable("SecondarySupers"); 602 603 @Fold 604 public static int secondarySupersOffset() { 605 return config().secondarySupersOffset; 606 } 607 608 public static final LocationIdentity DISPLACED_MARK_WORD_LOCATION = NamedLocationIdentity.mutable("DisplacedMarkWord"); 609 610 @Fold 611 public static int lockDisplacedMarkOffset() { 612 return config().basicLockDisplacedHeaderOffset; 613 } 614 615 @Fold 616 public static boolean useBiasedLocking() { 617 return config().useBiasedLocking; 618 } 619 620 @Fold 621 public static boolean useDeferredInitBarriers() { 622 return config().useDeferredInitBarriers; 623 } 624 625 @Fold 626 public static boolean useG1GC() { 627 return config().useG1GC; 628 } 629 630 @Fold 631 public static boolean useCompressedOops() { 632 return config().useCompressedOops; 633 } 634 635 @Fold 636 static int uninitializedIdentityHashCodeValue() { 637 return config().uninitializedIdentityHashCodeValue; 638 } 639 640 @Fold 641 static int identityHashCodeShift() { 642 return config().identityHashCodeShift; 643 } 644 645 /** 646 * Loads the hub of an object (without null checking it first). 647 */ 648 public static KlassPointer loadHub(Object object) { 649 return loadHubIntrinsic(object); 650 } 651 652 public static Object verifyOop(Object object) { 653 if (verifyOops()) { 654 verifyOopStub(VERIFY_OOP, object); 655 } 656 return object; 657 } 658 659 @NodeIntrinsic(ForeignCallNode.class) 660 private static native Object verifyOopStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Object object); 661 662 public static Word loadWordFromObject(Object object, int offset) { 663 ReplacementsUtil.staticAssert(offset != hubOffset(), "Use loadHubIntrinsic instead of loadWordFromObject"); 664 return loadWordFromObjectIntrinsic(object, offset, getWordKind(), LocationIdentity.any()); 665 } 666 667 public static Word loadWordFromObject(Object object, int offset, LocationIdentity identity) { 668 ReplacementsUtil.staticAssert(offset != hubOffset(), "Use loadHubIntrinsic instead of loadWordFromObject"); 669 return loadWordFromObjectIntrinsic(object, offset, getWordKind(), identity); 670 } 671 672 public static KlassPointer loadKlassFromObject(Object object, int offset, LocationIdentity identity) { 673 ReplacementsUtil.staticAssert(offset != hubOffset(), "Use loadHubIntrinsic instead of loadWordFromObject"); 674 return loadKlassFromObjectIntrinsic(object, offset, getWordKind(), identity); 675 } 676 677 /** 678 * Reads the value of a given register. 679 * 680 * @param register a register which must not be available to the register allocator 681 * @return the value of {@code register} as a word 682 */ 683 public static Word registerAsWord(@ConstantNodeParameter Register register) { 684 return registerAsWord(register, true, false); 685 } 686 687 @NodeIntrinsic(value = ReadRegisterNode.class, setStampFromReturnType = true) 688 public static native Word registerAsWord(@ConstantNodeParameter Register register, @ConstantNodeParameter boolean directUse, @ConstantNodeParameter boolean incoming); 689 690 @NodeIntrinsic(value = WriteRegisterNode.class, setStampFromReturnType = true) 691 public static native void writeRegisterAsWord(@ConstantNodeParameter Register register, Word value); 692 693 @NodeIntrinsic(value = UnsafeLoadNode.class, setStampFromReturnType = true) 694 private static native Word loadWordFromObjectIntrinsic(Object object, long offset, @ConstantNodeParameter Kind wordKind, @ConstantNodeParameter LocationIdentity locationIdentity); 695 696 @NodeIntrinsic(value = UnsafeLoadNode.class, setStampFromReturnType = true) 697 private static native KlassPointer loadKlassFromObjectIntrinsic(Object object, long offset, @ConstantNodeParameter Kind wordKind, @ConstantNodeParameter LocationIdentity locationIdentity); 698 699 @NodeIntrinsic(value = LoadHubNode.class) 700 public static native KlassPointer loadHubIntrinsic(Object object, GuardingNode anchor); 701 702 @NodeIntrinsic(value = LoadHubNode.class) 703 public static native KlassPointer loadHubIntrinsic(Object object); 704 705 @Fold 706 public static int log2WordSize() { 707 return CodeUtil.log2(wordSize()); 708 } 709 710 public static final LocationIdentity CLASS_STATE_LOCATION = NamedLocationIdentity.mutable("ClassState"); 711 712 @Fold 713 public static int instanceKlassInitStateOffset() { 714 return config().instanceKlassInitStateOffset; 715 } 716 717 @Fold 718 public static int instanceKlassStateFullyInitialized() { 719 return config().instanceKlassStateFullyInitialized; 720 } 721 722 public static final LocationIdentity INSTANCE_KLASS_CONSTANTS = NamedLocationIdentity.immutable("InstanceKlass::_constants"); 723 724 @Fold 725 public static int instanceKlassConstantsOffset() { 726 return config().instanceKlassConstantsOffset; 727 } 728 729 /** 730 * 731 * @param hub the hub of an InstanceKlass 732 * @return true is the InstanceKlass represented by hub is fully initialized 733 */ 734 public static boolean isInstanceKlassFullyInitialized(KlassPointer hub) { 735 return readInstanceKlassState(hub) == instanceKlassStateFullyInitialized(); 736 } 737 738 private static byte readInstanceKlassState(KlassPointer hub) { 739 return hub.readByte(instanceKlassInitStateOffset(), CLASS_STATE_LOCATION); 740 } 741 742 public static final LocationIdentity KLASS_MODIFIER_FLAGS_LOCATION = NamedLocationIdentity.immutable("Klass::_modifier_flags"); 743 744 @Fold 745 public static int klassModifierFlagsOffset() { 746 return config().klassModifierFlagsOffset; 747 } 748 749 public static final LocationIdentity CLASS_KLASS_LOCATION = new HotSpotOptimizingLocationIdentity("Class._klass") { 750 @Override 751 public ValueNode canonicalizeRead(ValueNode read, AddressNode location, ValueNode object, CanonicalizerTool tool) { 752 return foldIndirection(read, object, CLASS_MIRROR_LOCATION); 753 } 754 }; 755 756 @Fold 757 public static int klassOffset() { 758 return config().klassOffset; 759 } 760 761 public static final LocationIdentity CLASS_ARRAY_KLASS_LOCATION = new HotSpotOptimizingLocationIdentity("Class._array_klass") { 762 @Override 763 public ValueNode canonicalizeRead(ValueNode read, AddressNode location, ValueNode object, CanonicalizerTool tool) { 764 return foldIndirection(read, object, ARRAY_KLASS_COMPONENT_MIRROR); 765 } 766 }; 767 768 @Fold 769 public static int arrayKlassOffset() { 770 return config().arrayKlassOffset; 771 } 772 773 public static final LocationIdentity CLASS_MIRROR_LOCATION = NamedLocationIdentity.immutable("Klass::_java_mirror"); 774 775 @Fold 776 public static int classMirrorOffset() { 777 return config().classMirrorOffset; 778 } 779 780 @Fold 781 public static int constantPoolSize() { 782 return config().constantPoolSize; 783 } 784 785 @Fold 786 public static int constantPoolHolderOffset() { 787 return config().constantPoolHolderOffset; 788 } 789 790 @Fold 791 public static int constantPoolLengthOffset() { 792 return config().constantPoolLengthOffset; 793 } 794 795 public static final LocationIdentity HEAP_TOP_LOCATION = NamedLocationIdentity.mutable("HeapTop"); 796 797 @Fold 798 public static long heapTopAddress() { 799 return config().heapTopAddress; 800 } 801 802 public static final LocationIdentity HEAP_END_LOCATION = NamedLocationIdentity.mutable("HeapEnd"); 803 804 @Fold 805 public static long heapEndAddress() { 806 return config().heapEndAddress; 807 } 808 809 @Fold 810 public static long tlabIntArrayMarkWord() { 811 return config().tlabIntArrayMarkWord(); 812 } 813 814 @Fold 815 public static boolean inlineContiguousAllocationSupported() { 816 return config().inlineContiguousAllocationSupported; 817 } 818 819 @Fold 820 public static int tlabAlignmentReserveInHeapWords() { 821 return config().tlabAlignmentReserve; 822 } 823 824 public static final LocationIdentity TLAB_SIZE_LOCATION = NamedLocationIdentity.mutable("TlabSize"); 825 826 @Fold 827 public static int threadTlabSizeOffset() { 828 return config().threadTlabSizeOffset(); 829 } 830 831 public static final LocationIdentity TLAB_THREAD_ALLOCATED_BYTES_LOCATION = NamedLocationIdentity.mutable("TlabThreadAllocatedBytes"); 832 833 @Fold 834 public static int threadAllocatedBytesOffset() { 835 return config().threadAllocatedBytesOffset; 836 } 837 838 public static final LocationIdentity TLAB_REFILL_WASTE_LIMIT_LOCATION = NamedLocationIdentity.mutable("RefillWasteLimit"); 839 840 @Fold 841 public static int tlabRefillWasteLimitOffset() { 842 return config().tlabRefillWasteLimitOffset(); 843 } 844 845 public static final LocationIdentity TLAB_NOF_REFILLS_LOCATION = NamedLocationIdentity.mutable("TlabNOfRefills"); 846 847 @Fold 848 public static int tlabNumberOfRefillsOffset() { 849 return config().tlabNumberOfRefillsOffset(); 850 } 851 852 public static final LocationIdentity TLAB_FAST_REFILL_WASTE_LOCATION = NamedLocationIdentity.mutable("TlabFastRefillWaste"); 853 854 @Fold 855 public static int tlabFastRefillWasteOffset() { 856 return config().tlabFastRefillWasteOffset(); 857 } 858 859 public static final LocationIdentity TLAB_SLOW_ALLOCATIONS_LOCATION = NamedLocationIdentity.mutable("TlabSlowAllocations"); 860 861 @Fold 862 public static int tlabSlowAllocationsOffset() { 863 return config().tlabSlowAllocationsOffset(); 864 } 865 866 @Fold 867 public static int tlabRefillWasteIncrement() { 868 return config().tlabRefillWasteIncrement; 869 } 870 871 @Fold 872 public static boolean tlabStats() { 873 return config().tlabStats; 874 } 875 876 @Fold 877 public static int layoutHelperHeaderSizeShift() { 878 return config().layoutHelperHeaderSizeShift; 879 } 880 881 @Fold 882 public static int layoutHelperHeaderSizeMask() { 883 return config().layoutHelperHeaderSizeMask; 884 } 885 886 @Fold 887 public static int layoutHelperLog2ElementSizeShift() { 888 return config().layoutHelperLog2ElementSizeShift; 889 } 890 891 @Fold 892 public static int layoutHelperLog2ElementSizeMask() { 893 return config().layoutHelperLog2ElementSizeMask; 894 } 895 896 @Fold 897 public static int layoutHelperElementTypeShift() { 898 return config().layoutHelperElementTypeShift; 899 } 900 901 @Fold 902 public static int layoutHelperElementTypeMask() { 903 return config().layoutHelperElementTypeMask; 904 } 905 906 @Fold 907 public static int layoutHelperElementTypePrimitiveInPlace() { 908 return config().layoutHelperElementTypePrimitiveInPlace(); 909 } 910 911 static int computeHashCode(Object x) { 912 Word mark = loadWordFromObject(x, markOffset()); 913 914 // this code is independent from biased locking (although it does not look that way) 915 final Word biasedLock = mark.and(biasedLockMaskInPlace()); 916 if (probability(FAST_PATH_PROBABILITY, biasedLock.equal(Word.unsigned(unlockedMask())))) { 917 int hash = (int) mark.unsignedShiftRight(identityHashCodeShift()).rawValue(); 918 if (probability(FAST_PATH_PROBABILITY, hash != uninitializedIdentityHashCodeValue())) { 919 return hash; 920 } 921 } 922 923 return identityHashCode(IDENTITY_HASHCODE, x); 924 } 925 926 @NodeIntrinsic(ForeignCallNode.class) 927 public static native int identityHashCode(@ConstantNodeParameter ForeignCallDescriptor descriptor, Object object); 928 929 @Fold 930 public static boolean isImmutableCode() { 931 return GraalOptions.ImmutableCode.getValue(); 932 } 933 934 @Fold 935 public static boolean generatePIC() { 936 return GraalOptions.GeneratePIC.getValue(); 937 } 938 939 @Fold 940 public static int verifiedEntryPointOffset() { 941 return config().nmethodEntryOffset; 942 } 943 944 @Fold 945 public static long gcTotalCollectionsAddress() { 946 return config().gcTotalCollectionsAddress(); 947 } 948 949 @Fold 950 public static long referentOffset() { 951 try { 952 return unsafe.objectFieldOffset(java.lang.ref.Reference.class.getDeclaredField("referent")); 953 } catch (Exception e) { 954 throw new JVMCIError(e); 955 } 956 } 957 958 public static final LocationIdentity OBJ_ARRAY_KLASS_ELEMENT_KLASS_LOCATION = new HotSpotOptimizingLocationIdentity("ObjArrayKlass::_element_klass") { 959 @Override 960 public ValueNode canonicalizeRead(ValueNode read, AddressNode location, ValueNode object, CanonicalizerTool tool) { 961 ValueNode javaObject = findReadHub(object); 962 if (javaObject != null) { 963 ResolvedJavaType type = StampTool.typeOrNull(javaObject); 964 if (type != null && type.isArray()) { 965 ResolvedJavaType element = type.getComponentType(); 966 if (element != null && !element.isPrimitive() && !element.getElementalType().isInterface()) { 967 AssumptionResult<ResolvedJavaType> leafType = element.findLeafConcreteSubtype(); 968 if (leafType != null) { 969 object.graph().getAssumptions().record(leafType); 970 return ConstantNode.forConstant(read.stamp(), leafType.getResult().getObjectHub(), tool.getMetaAccess()); 971 } 972 } 973 } 974 } 975 return read; 976 } 977 }; 978 979 @Fold 980 public static int arrayClassElementOffset() { 981 return config().arrayClassElementOffset; 982 } 983 984 public static final LocationIdentity PRIMARY_SUPERS_LOCATION = NamedLocationIdentity.immutable("PrimarySupers"); 985 986 public static final LocationIdentity METASPACE_ARRAY_LENGTH_LOCATION = NamedLocationIdentity.immutable("MetaspaceArrayLength"); 987 988 public static final LocationIdentity SECONDARY_SUPERS_ELEMENT_LOCATION = NamedLocationIdentity.immutable("SecondarySupersElement"); 989}