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.hotspot.replacements; 24 25 import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfig.INJECTED_VMCONFIG; 26 import static org.graalvm.compiler.hotspot.meta.HotSpotForeignCallsProviderImpl.VERIFY_OOP; 27 import static org.graalvm.compiler.hotspot.replacements.UnsafeAccess.UNSAFE; 28 import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayBaseOffset; 29 import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayIndexScale; 30 31 import org.graalvm.compiler.api.replacements.Fold; 32 import org.graalvm.compiler.api.replacements.Fold.InjectedParameter; 33 import org.graalvm.compiler.core.common.LocationIdentity; 34 import org.graalvm.compiler.core.common.SuppressFBWarnings; 35 import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor; 36 import org.graalvm.compiler.core.common.type.ObjectStamp; 37 import org.graalvm.compiler.core.common.type.TypeReference; 38 import org.graalvm.compiler.debug.GraalError; 39 import org.graalvm.compiler.graph.Node.ConstantNodeParameter; 40 import org.graalvm.compiler.graph.Node.NodeIntrinsic; 41 import org.graalvm.compiler.graph.spi.CanonicalizerTool; 42 import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig; 43 import org.graalvm.compiler.hotspot.nodes.CompressionNode; 44 import org.graalvm.compiler.hotspot.nodes.ComputeObjectAddressNode; 45 import org.graalvm.compiler.hotspot.word.KlassPointer; 46 import org.graalvm.compiler.nodes.CanonicalizableLocation; 47 import org.graalvm.compiler.nodes.ConstantNode; 48 import org.graalvm.compiler.nodes.NamedLocationIdentity; 49 import org.graalvm.compiler.nodes.ValueNode; 50 import org.graalvm.compiler.nodes.extended.ForeignCallNode; 51 import org.graalvm.compiler.nodes.extended.LoadHubNode; 52 import org.graalvm.compiler.nodes.extended.StoreHubNode; 53 import org.graalvm.compiler.nodes.extended.RawLoadNode; 54 import org.graalvm.compiler.nodes.memory.Access; 55 import org.graalvm.compiler.nodes.memory.address.AddressNode; 56 import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode; 57 import org.graalvm.compiler.nodes.type.StampTool; 58 import org.graalvm.compiler.replacements.ReplacementsUtil; 59 import org.graalvm.compiler.replacements.nodes.ReadRegisterNode; 60 import org.graalvm.compiler.replacements.nodes.WriteRegisterNode; 61 import org.graalvm.compiler.word.Word; 62 63 import jdk.vm.ci.code.CodeUtil; 64 import jdk.vm.ci.code.Register; 65 import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; 66 import jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider; 67 import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant; 68 import jdk.vm.ci.hotspot.HotSpotResolvedObjectType; 69 import jdk.vm.ci.meta.Assumptions; 70 import jdk.vm.ci.meta.Assumptions.AssumptionResult; 71 import jdk.vm.ci.meta.JavaKind; 72 import jdk.vm.ci.meta.ResolvedJavaType; 73 74 //JaCoCo Exclude 75 76 /** 77 * A collection of methods used in HotSpot snippets, substitutions and stubs. 78 */ 79 public class HotSpotReplacementsUtil { 80 81 abstract static class HotSpotOptimizingLocationIdentity extends NamedLocationIdentity implements CanonicalizableLocation { 82 83 HotSpotOptimizingLocationIdentity(String name) { 84 super(name, true); 85 } 86 87 @Override 88 public abstract ValueNode canonicalizeRead(ValueNode read, AddressNode location, ValueNode object, CanonicalizerTool tool); 89 90 protected ValueNode findReadHub(ValueNode object) { 91 ValueNode base = object; 92 if (base instanceof CompressionNode) { 93 base = ((CompressionNode) base).getValue(); 94 } 95 if (base instanceof Access) { 96 Access access = (Access) base; 97 if (access.getLocationIdentity().equals(HUB_LOCATION) || access.getLocationIdentity().equals(COMPRESSED_HUB_LOCATION)) { 98 AddressNode address = access.getAddress(); 99 if (address instanceof OffsetAddressNode) { 100 OffsetAddressNode offset = (OffsetAddressNode) address; 101 return offset.getBase(); 102 } 103 } 104 } else if (base instanceof LoadHubNode) { 105 LoadHubNode loadhub = (LoadHubNode) base; 106 return loadhub.getValue(); 107 } 108 return null; 109 } 110 111 /** 112 * Fold reads that convert from Class -> Hub -> Class or vice versa. 113 * 114 * @param read 115 * @param object 116 * @param otherLocation 117 * @return an earlier read or the original {@code read} 118 */ 119 protected static ValueNode foldIndirection(ValueNode read, ValueNode object, LocationIdentity otherLocation) { 120 if (object instanceof Access) { 121 Access access = (Access) object; 122 if (access.getLocationIdentity().equals(otherLocation)) { 123 AddressNode address = access.getAddress(); 124 if (address instanceof OffsetAddressNode) { 125 OffsetAddressNode offset = (OffsetAddressNode) address; 126 assert offset.getBase().stamp().isCompatible(read.stamp()); 127 return offset.getBase(); 128 } 129 } 130 } 131 return read; 132 } 133 } 134 135 public static HotSpotJVMCIRuntimeProvider runtime() { 136 return HotSpotJVMCIRuntime.runtime(); 137 } 138 139 @Fold 140 public static GraalHotSpotVMConfig config(@InjectedParameter GraalHotSpotVMConfig config) { 141 assert config != null; 142 return config; 143 } 144 145 @Fold 146 public static boolean useTLAB(@InjectedParameter GraalHotSpotVMConfig config) { 147 return config.useTLAB; 148 } 149 150 @Fold 151 public static boolean verifyOops(@InjectedParameter GraalHotSpotVMConfig config) { 152 return config.verifyOops; 153 } 154 155 public static final LocationIdentity EXCEPTION_OOP_LOCATION = NamedLocationIdentity.mutable("ExceptionOop"); 156 157 /** 158 * @see GraalHotSpotVMConfig#threadExceptionOopOffset 159 */ 160 @Fold 161 public static int threadExceptionOopOffset(@InjectedParameter GraalHotSpotVMConfig config) { 162 return config.threadExceptionOopOffset; 163 } 164 165 public static final LocationIdentity EXCEPTION_PC_LOCATION = NamedLocationIdentity.mutable("ExceptionPc"); 166 167 @Fold 168 public static int threadExceptionPcOffset(@InjectedParameter GraalHotSpotVMConfig config) { 169 return config.threadExceptionPcOffset; 170 } 171 172 public static final LocationIdentity TLAB_TOP_LOCATION = NamedLocationIdentity.mutable("TlabTop"); 173 174 @Fold 175 public static int threadTlabTopOffset(@InjectedParameter GraalHotSpotVMConfig config) { 176 return config.threadTlabTopOffset(); 177 } 178 179 public static final LocationIdentity TLAB_END_LOCATION = NamedLocationIdentity.mutable("TlabEnd"); 180 181 @Fold 182 static int threadTlabEndOffset(@InjectedParameter GraalHotSpotVMConfig config) { 183 return config.threadTlabEndOffset(); 184 } 185 186 public static final LocationIdentity TLAB_START_LOCATION = NamedLocationIdentity.mutable("TlabStart"); 187 188 @Fold 189 static int threadTlabStartOffset(@InjectedParameter GraalHotSpotVMConfig config) { 190 return config.threadTlabStartOffset(); 191 } 192 193 public static final LocationIdentity PENDING_EXCEPTION_LOCATION = NamedLocationIdentity.mutable("PendingException"); 194 195 /** 196 * @see GraalHotSpotVMConfig#pendingExceptionOffset 197 */ 198 @Fold 199 static int threadPendingExceptionOffset(@InjectedParameter GraalHotSpotVMConfig config) { 200 return config.pendingExceptionOffset; 201 } 202 203 public static final LocationIdentity PENDING_DEOPTIMIZATION_LOCATION = NamedLocationIdentity.mutable("PendingDeoptimization"); 204 205 /** 206 * @see GraalHotSpotVMConfig#pendingDeoptimizationOffset 207 */ 208 @Fold 209 static int threadPendingDeoptimizationOffset(@InjectedParameter GraalHotSpotVMConfig config) { 210 return config.pendingDeoptimizationOffset; 211 } 212 213 public static final LocationIdentity OBJECT_RESULT_LOCATION = NamedLocationIdentity.mutable("ObjectResult"); 214 215 @Fold 216 static int objectResultOffset(@InjectedParameter GraalHotSpotVMConfig config) { 217 return config.threadObjectResultOffset; 218 } 219 220 /** 221 * @see GraalHotSpotVMConfig#threadExceptionOopOffset 222 */ 223 public static Object readExceptionOop(Word thread) { 224 return thread.readObject(threadExceptionOopOffset(INJECTED_VMCONFIG), EXCEPTION_OOP_LOCATION); 225 } 226 227 public static Word readExceptionPc(Word thread) { 228 return thread.readWord(threadExceptionPcOffset(INJECTED_VMCONFIG), EXCEPTION_PC_LOCATION); 229 } 230 231 /** 232 * @see GraalHotSpotVMConfig#threadExceptionOopOffset 233 */ 234 public static void writeExceptionOop(Word thread, Object value) { 235 thread.writeObject(threadExceptionOopOffset(INJECTED_VMCONFIG), value, EXCEPTION_OOP_LOCATION); 236 } 237 238 public static void writeExceptionPc(Word thread, Word value) { 239 thread.writeWord(threadExceptionPcOffset(INJECTED_VMCONFIG), value, EXCEPTION_PC_LOCATION); 240 } 241 242 public static Word readTlabTop(Word thread) { 243 return thread.readWord(threadTlabTopOffset(INJECTED_VMCONFIG), TLAB_TOP_LOCATION); 244 } 245 246 public static Word readTlabEnd(Word thread) { 247 return thread.readWord(threadTlabEndOffset(INJECTED_VMCONFIG), TLAB_END_LOCATION); 248 } 249 250 public static Word readTlabStart(Word thread) { 251 return thread.readWord(threadTlabStartOffset(INJECTED_VMCONFIG), TLAB_START_LOCATION); 252 } 253 254 public static void writeTlabTop(Word thread, Word top) { 255 thread.writeWord(threadTlabTopOffset(INJECTED_VMCONFIG), top, TLAB_TOP_LOCATION); 256 } 257 258 @SuppressFBWarnings(value = "NP_NULL_PARAM_DEREF_NONVIRTUAL", justification = "foldable method parameters are injected") 259 public static void initializeTlab(Word thread, Word start, Word end) { 260 thread.writeWord(threadTlabStartOffset(INJECTED_VMCONFIG), start, TLAB_START_LOCATION); 261 thread.writeWord(threadTlabTopOffset(INJECTED_VMCONFIG), start, TLAB_TOP_LOCATION); 262 thread.writeWord(threadTlabEndOffset(INJECTED_VMCONFIG), end, TLAB_END_LOCATION); 263 } 264 265 /** 266 * Clears the pending exception for the given thread. 267 * 268 * @return the pending exception, or null if there was none 269 */ 270 @SuppressFBWarnings(value = "NP_NULL_PARAM_DEREF_NONVIRTUAL", justification = "foldable method parameters are injected") 271 public static Object clearPendingException(Word thread) { 272 Object result = thread.readObject(threadPendingExceptionOffset(INJECTED_VMCONFIG), PENDING_EXCEPTION_LOCATION); 273 thread.writeObject(threadPendingExceptionOffset(INJECTED_VMCONFIG), null, PENDING_EXCEPTION_LOCATION); 274 return result; 275 } 276 277 /** 278 * Reads the pending deoptimization value for the given thread. 279 * 280 * @return {@code true} if there was a pending deoptimization 281 */ 282 public static int readPendingDeoptimization(Word thread) { 283 return thread.readInt(threadPendingDeoptimizationOffset(INJECTED_VMCONFIG), PENDING_DEOPTIMIZATION_LOCATION); 284 } 285 286 /** 287 * Writes the pending deoptimization value for the given thread. 288 */ 289 public static void writePendingDeoptimization(Word thread, int value) { 290 thread.writeInt(threadPendingDeoptimizationOffset(INJECTED_VMCONFIG), value, PENDING_DEOPTIMIZATION_LOCATION); 291 } 292 293 /** 294 * Gets and clears the object result from a runtime call stored in a thread local. 295 * 296 * @return the object that was in the thread local 297 */ 298 public static Object getAndClearObjectResult(Word thread) { 299 Object result = thread.readObject(objectResultOffset(INJECTED_VMCONFIG), OBJECT_RESULT_LOCATION); 300 thread.writeObject(objectResultOffset(INJECTED_VMCONFIG), null, OBJECT_RESULT_LOCATION); 301 return result; 302 } 303 304 public static final LocationIdentity JAVA_THREAD_THREAD_OBJECT_LOCATION = NamedLocationIdentity.mutable("JavaThread::_threadObj"); 305 306 @Fold 307 public static int threadObjectOffset(@InjectedParameter GraalHotSpotVMConfig config) { 308 return config.threadObjectOffset; 309 } 310 311 public static final LocationIdentity JAVA_THREAD_OSTHREAD_LOCATION = NamedLocationIdentity.mutable("JavaThread::_osthread"); 312 313 @Fold 314 public static int osThreadOffset(@InjectedParameter GraalHotSpotVMConfig config) { 315 return config.osThreadOffset; 316 } 317 318 @Fold 319 public static int osThreadInterruptedOffset(@InjectedParameter GraalHotSpotVMConfig config) { 320 return config.osThreadInterruptedOffset; 321 } 322 323 @Fold 324 public static JavaKind getWordKind() { 325 return runtime().getHostJVMCIBackend().getCodeCache().getTarget().wordJavaKind; 326 } 327 328 @Fold 329 public static int wordSize() { 330 return runtime().getHostJVMCIBackend().getCodeCache().getTarget().wordSize; 331 } 332 333 @Fold 334 public static int pageSize() { 335 return UNSAFE.pageSize(); 336 } 337 338 @Fold 339 public static int heapWordSize(@InjectedParameter GraalHotSpotVMConfig config) { 340 return config.heapWordSize; 341 } 342 343 public static final LocationIdentity PROTOTYPE_MARK_WORD_LOCATION = NamedLocationIdentity.mutable("PrototypeMarkWord"); 344 345 @Fold 346 public static int prototypeMarkWordOffset(@InjectedParameter GraalHotSpotVMConfig config) { 347 return config.prototypeMarkWordOffset; 348 } 349 350 @Fold 351 public static long arrayPrototypeMarkWord(@InjectedParameter GraalHotSpotVMConfig config) { 352 return config.arrayPrototypeMarkWord(); 353 } 354 355 public static final LocationIdentity KLASS_ACCESS_FLAGS_LOCATION = NamedLocationIdentity.immutable("Klass::_access_flags"); 356 357 @Fold 358 public static int klassAccessFlagsOffset(@InjectedParameter GraalHotSpotVMConfig config) { 359 return config.klassAccessFlagsOffset; 360 } 361 362 @Fold 363 public static int jvmAccWrittenFlags(@InjectedParameter GraalHotSpotVMConfig config) { 364 return config.jvmAccWrittenFlags; 365 } 366 367 public static final LocationIdentity KLASS_LAYOUT_HELPER_LOCATION = new HotSpotOptimizingLocationIdentity("Klass::_layout_helper") { 368 @Override 369 public ValueNode canonicalizeRead(ValueNode read, AddressNode location, ValueNode object, CanonicalizerTool tool) { 370 ValueNode javaObject = findReadHub(object); 371 if (javaObject != null) { 372 if (javaObject.stamp() instanceof ObjectStamp) { 373 ObjectStamp stamp = (ObjectStamp) javaObject.stamp(); 374 HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) stamp.javaType(tool.getMetaAccess()); 375 if (type.isArray() && !type.getComponentType().isPrimitive()) { 376 int layout = type.layoutHelper(); 377 return ConstantNode.forInt(layout); 378 } 379 } 380 } 381 return read; 382 } 383 }; 384 385 @Fold 386 public static int klassLayoutHelperOffset(@InjectedParameter GraalHotSpotVMConfig config) { 387 return config.klassLayoutHelperOffset; 388 } 389 390 @NodeIntrinsic(value = KlassLayoutHelperNode.class) 391 public static native int readLayoutHelper(KlassPointer object); 392 393 /** 394 * Checks if class {@code klass} is an array. 395 * 396 * See: Klass::layout_helper_is_array 397 * 398 * @param klassNonNull the class to be checked 399 * @return true if klassNonNull is an array, false otherwise 400 */ 401 public static boolean klassIsArray(KlassPointer klassNonNull) { 402 /* 403 * The less-than check only works if both values are ints. We use local variables to make 404 * sure these are still ints and haven't changed. 405 */ 406 final int layoutHelper = readLayoutHelper(klassNonNull); 407 final int layoutHelperNeutralValue = config(INJECTED_VMCONFIG).klassLayoutHelperNeutralValue; 408 return (layoutHelper < layoutHelperNeutralValue); 409 } 410 411 public static final LocationIdentity ARRAY_KLASS_COMPONENT_MIRROR = NamedLocationIdentity.immutable("ArrayKlass::_component_mirror"); 412 413 @Fold 414 public static int arrayKlassComponentMirrorOffset(@InjectedParameter GraalHotSpotVMConfig config) { 415 return config.getFieldOffset("ArrayKlass::_component_mirror", Integer.class, "oop"); 416 } 417 418 public static final LocationIdentity KLASS_SUPER_KLASS_LOCATION = NamedLocationIdentity.immutable("Klass::_super"); 419 420 @Fold 421 public static int klassSuperKlassOffset(@InjectedParameter GraalHotSpotVMConfig config) { 422 return config.klassSuperKlassOffset; 423 } 424 425 public static final LocationIdentity MARK_WORD_LOCATION = NamedLocationIdentity.mutable("MarkWord"); 426 427 @Fold 428 public static int markOffset(@InjectedParameter GraalHotSpotVMConfig config) { 429 return config.markOffset; 430 } 431 432 public static final LocationIdentity HUB_WRITE_LOCATION = NamedLocationIdentity.mutable("Hub:write"); 433 434 public static final LocationIdentity HUB_LOCATION = new HotSpotOptimizingLocationIdentity("Hub") { 435 @Override 436 public ValueNode canonicalizeRead(ValueNode read, AddressNode location, ValueNode object, CanonicalizerTool tool) { 437 TypeReference constantType = StampTool.typeReferenceOrNull(object); 438 if (constantType != null && constantType.isExact()) { 439 return ConstantNode.forConstant(read.stamp(), tool.getConstantReflection().asObjectHub(constantType.getType()), tool.getMetaAccess()); 440 } 441 return read; 442 } 443 }; 444 445 public static final LocationIdentity COMPRESSED_HUB_LOCATION = new HotSpotOptimizingLocationIdentity("CompressedHub") { 446 @Override 447 public ValueNode canonicalizeRead(ValueNode read, AddressNode location, ValueNode object, CanonicalizerTool tool) { 448 TypeReference constantType = StampTool.typeReferenceOrNull(object); 449 if (constantType != null && constantType.isExact()) { 450 return ConstantNode.forConstant(read.stamp(), ((HotSpotMetaspaceConstant) tool.getConstantReflection().asObjectHub(constantType.getType())).compress(), tool.getMetaAccess()); 451 } 452 return read; 453 } 454 }; 455 456 @Fold 457 static int hubOffset(@InjectedParameter GraalHotSpotVMConfig config) { 458 return config.hubOffset; 459 } 460 461 public static void initializeObjectHeader(Word memory, Word markWord, KlassPointer hub) { 462 memory.writeWord(markOffset(INJECTED_VMCONFIG), markWord, MARK_WORD_LOCATION); 463 StoreHubNode.write(memory, hub); 464 } 465 466 @Fold 467 public static int unlockedMask(@InjectedParameter GraalHotSpotVMConfig config) { 468 return config.unlockedMask; 469 } 470 471 @Fold 472 public static int monitorMask(@InjectedParameter GraalHotSpotVMConfig config) { 473 return config.monitorMask; 474 } 475 476 @Fold 477 public static int objectMonitorOwnerOffset(@InjectedParameter GraalHotSpotVMConfig config) { 478 return config.objectMonitorOwner; 479 } 480 481 @Fold 482 public static int objectMonitorRecursionsOffset(@InjectedParameter GraalHotSpotVMConfig config) { 483 return config.objectMonitorRecursions; 484 } 485 486 @Fold 487 public static int objectMonitorCxqOffset(@InjectedParameter GraalHotSpotVMConfig config) { 488 return config.objectMonitorCxq; 489 } 490 491 @Fold 492 public static int objectMonitorEntryListOffset(@InjectedParameter GraalHotSpotVMConfig config) { 493 return config.objectMonitorEntryList; 494 } 495 496 /** 497 * Mask for a biasable, locked or unlocked mark word. 498 * 499 * <pre> 500 * +----------------------------------+-+-+ 501 * | 1|1|1| 502 * +----------------------------------+-+-+ 503 * </pre> 504 * 505 */ 506 @Fold 507 public static int biasedLockMaskInPlace(@InjectedParameter GraalHotSpotVMConfig config) { 508 return config.biasedLockMaskInPlace; 509 } 510 511 @Fold 512 public static int epochMaskInPlace(@InjectedParameter GraalHotSpotVMConfig config) { 513 return config.epochMaskInPlace; 514 } 515 516 /** 517 * Pattern for a biasable, unlocked mark word. 518 * 519 * <pre> 520 * +----------------------------------+-+-+ 521 * | 1|0|1| 522 * +----------------------------------+-+-+ 523 * </pre> 524 * 525 */ 526 @Fold 527 public static int biasedLockPattern(@InjectedParameter GraalHotSpotVMConfig config) { 528 return config.biasedLockPattern; 529 } 530 531 @Fold 532 public static int ageMaskInPlace(@InjectedParameter GraalHotSpotVMConfig config) { 533 return config.ageMaskInPlace; 534 } 535 536 @Fold 537 public static int metaspaceArrayLengthOffset(@InjectedParameter GraalHotSpotVMConfig config) { 538 return config.metaspaceArrayLengthOffset; 539 } 540 541 @Fold 542 public static int metaspaceArrayBaseOffset(@InjectedParameter GraalHotSpotVMConfig config) { 543 return config.metaspaceArrayBaseOffset; 544 } 545 546 @Fold 547 public static int arrayLengthOffset(@InjectedParameter GraalHotSpotVMConfig config) { 548 return config.arrayOopDescLengthOffset(); 549 } 550 551 @Fold 552 public static int arrayBaseOffset(JavaKind elementKind) { 553 return getArrayBaseOffset(elementKind); 554 } 555 556 @Fold 557 public static int arrayIndexScale(JavaKind elementKind) { 558 return getArrayIndexScale(elementKind); 559 } 560 561 public static Word arrayStart(int[] a) { 562 return Word.unsigned(ComputeObjectAddressNode.get(a, getArrayBaseOffset(JavaKind.Int))); 563 } 564 565 @Fold 566 public static int instanceHeaderSize(@InjectedParameter GraalHotSpotVMConfig config) { 567 return config.useCompressedClassPointers ? (2 * wordSize()) - 4 : 2 * wordSize(); 568 } 569 570 @Fold 571 public static byte dirtyCardValue(@InjectedParameter GraalHotSpotVMConfig config) { 572 return config.dirtyCardValue; 573 } 574 575 @Fold 576 public static byte g1YoungCardValue(@InjectedParameter GraalHotSpotVMConfig config) { 577 return config.g1YoungCardValue; 578 } 579 580 @Fold 581 public static int cardTableShift(@InjectedParameter GraalHotSpotVMConfig config) { 582 return config.cardtableShift; 583 } 584 585 @Fold 586 public static long cardTableStart(@InjectedParameter GraalHotSpotVMConfig config) { 587 return config.cardtableStartAddress; 588 } 589 590 @Fold 591 public static int g1CardQueueIndexOffset(@InjectedParameter GraalHotSpotVMConfig config) { 592 return config.g1CardQueueIndexOffset(); 593 } 594 595 @Fold 596 public static int g1CardQueueBufferOffset(@InjectedParameter GraalHotSpotVMConfig config) { 597 return config.g1CardQueueBufferOffset(); 598 } 599 600 @Fold 601 public static int logOfHeapRegionGrainBytes(@InjectedParameter GraalHotSpotVMConfig config) { 602 return config.logOfHRGrainBytes; 603 } 604 605 @Fold 606 public static int g1SATBQueueMarkingOffset(@InjectedParameter GraalHotSpotVMConfig config) { 607 return config.g1SATBQueueMarkingOffset(); 608 } 609 610 @Fold 611 public static int g1SATBQueueIndexOffset(@InjectedParameter GraalHotSpotVMConfig config) { 612 return config.g1SATBQueueIndexOffset(); 613 } 614 615 @Fold 616 public static int g1SATBQueueBufferOffset(@InjectedParameter GraalHotSpotVMConfig config) { 617 return config.g1SATBQueueBufferOffset(); 618 } 619 620 public static final LocationIdentity KLASS_SUPER_CHECK_OFFSET_LOCATION = NamedLocationIdentity.immutable("Klass::_super_check_offset"); 621 622 @Fold 623 public static int superCheckOffsetOffset(@InjectedParameter GraalHotSpotVMConfig config) { 624 return config.superCheckOffsetOffset; 625 } 626 627 public static final LocationIdentity SECONDARY_SUPER_CACHE_LOCATION = NamedLocationIdentity.mutable("SecondarySuperCache"); 628 629 @Fold 630 public static int secondarySuperCacheOffset(@InjectedParameter GraalHotSpotVMConfig config) { 631 return config.secondarySuperCacheOffset; 632 } 633 634 public static final LocationIdentity SECONDARY_SUPERS_LOCATION = NamedLocationIdentity.immutable("SecondarySupers"); 635 636 @Fold 637 public static int secondarySupersOffset(@InjectedParameter GraalHotSpotVMConfig config) { 638 return config.secondarySupersOffset; 639 } 640 641 public static final LocationIdentity DISPLACED_MARK_WORD_LOCATION = NamedLocationIdentity.mutable("DisplacedMarkWord"); 642 643 public static final LocationIdentity OBJECT_MONITOR_OWNER_LOCATION = NamedLocationIdentity.mutable("ObjectMonitor::_owner"); 644 645 public static final LocationIdentity OBJECT_MONITOR_RECURSION_LOCATION = NamedLocationIdentity.mutable("ObjectMonitor::_recursions"); 646 647 public static final LocationIdentity OBJECT_MONITOR_CXQ_LOCATION = NamedLocationIdentity.mutable("ObjectMonitor::_cxq"); 648 649 public static final LocationIdentity OBJECT_MONITOR_ENTRY_LIST_LOCATION = NamedLocationIdentity.mutable("ObjectMonitor::_EntryList"); 650 651 @Fold 652 public static int lockDisplacedMarkOffset(@InjectedParameter GraalHotSpotVMConfig config) { 653 return config.basicLockDisplacedHeaderOffset; 654 } 655 656 @Fold 657 public static boolean useBiasedLocking(@InjectedParameter GraalHotSpotVMConfig config) { 658 return config.useBiasedLocking; 659 } 660 661 @Fold 662 public static boolean useDeferredInitBarriers(@InjectedParameter GraalHotSpotVMConfig config) { 663 return config.useDeferredInitBarriers; 664 } 665 666 @Fold 667 public static boolean useG1GC(@InjectedParameter GraalHotSpotVMConfig config) { 668 return config.useG1GC; 669 } 670 671 @Fold 672 public static boolean useCompressedOops(@InjectedParameter GraalHotSpotVMConfig config) { 673 return config.useCompressedOops; 674 } 675 676 @Fold 677 static int uninitializedIdentityHashCodeValue(@InjectedParameter GraalHotSpotVMConfig config) { 678 return config.uninitializedIdentityHashCodeValue; 679 } 680 681 @Fold 682 static int identityHashCodeShift(@InjectedParameter GraalHotSpotVMConfig config) { 683 return config.identityHashCodeShift; 684 } 685 686 /** 687 * Loads the hub of an object (without null checking it first). 688 */ 689 public static KlassPointer loadHub(Object object) { 690 return loadHubIntrinsic(object); 691 } 692 693 public static Object verifyOop(Object object) { 694 if (verifyOops(INJECTED_VMCONFIG)) { 695 verifyOopStub(VERIFY_OOP, object); 696 } 697 return object; 698 } 699 700 @NodeIntrinsic(ForeignCallNode.class) 701 private static native Object verifyOopStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Object object); 702 703 public static Word loadWordFromObject(Object object, int offset) { 704 ReplacementsUtil.staticAssert(offset != hubOffset(INJECTED_VMCONFIG), "Use loadHubIntrinsic instead of loadWordFromObject"); 705 return loadWordFromObjectIntrinsic(object, offset, getWordKind(), LocationIdentity.any()); 706 } 707 708 public static Word loadWordFromObject(Object object, int offset, LocationIdentity identity) { 709 ReplacementsUtil.staticAssert(offset != hubOffset(INJECTED_VMCONFIG), "Use loadHubIntrinsic instead of loadWordFromObject"); 710 return loadWordFromObjectIntrinsic(object, offset, getWordKind(), identity); 711 } 712 713 public static KlassPointer loadKlassFromObject(Object object, int offset, LocationIdentity identity) { 714 ReplacementsUtil.staticAssert(offset != hubOffset(INJECTED_VMCONFIG), "Use loadHubIntrinsic instead of loadWordFromObject"); 715 return loadKlassFromObjectIntrinsic(object, offset, getWordKind(), identity); 716 } 717 718 /** 719 * Reads the value of a given register. 720 * 721 * @param register a register which must not be available to the register allocator 722 * @return the value of {@code register} as a word 723 */ 724 public static Word registerAsWord(@ConstantNodeParameter Register register) { 725 return registerAsWord(register, true, false); 726 } 727 728 @NodeIntrinsic(value = ReadRegisterNode.class, setStampFromReturnType = true) 729 public static native Word registerAsWord(@ConstantNodeParameter Register register, @ConstantNodeParameter boolean directUse, @ConstantNodeParameter boolean incoming); 730 731 @NodeIntrinsic(value = WriteRegisterNode.class, setStampFromReturnType = true) 732 public static native void writeRegisterAsWord(@ConstantNodeParameter Register register, Word value); 733 734 @NodeIntrinsic(value = RawLoadNode.class, setStampFromReturnType = true) 735 private static native Word loadWordFromObjectIntrinsic(Object object, long offset, @ConstantNodeParameter JavaKind wordKind, @ConstantNodeParameter LocationIdentity locationIdentity); 736 737 @NodeIntrinsic(value = RawLoadNode.class, setStampFromReturnType = true) 738 private static native KlassPointer loadKlassFromObjectIntrinsic(Object object, long offset, @ConstantNodeParameter JavaKind wordKind, @ConstantNodeParameter LocationIdentity locationIdentity); 739 740 @NodeIntrinsic(value = LoadHubNode.class) 741 public static native KlassPointer loadHubIntrinsic(Object object); 742 743 @Fold 744 public static int log2WordSize() { 745 return CodeUtil.log2(wordSize()); 746 } 747 748 public static final LocationIdentity CLASS_STATE_LOCATION = NamedLocationIdentity.mutable("ClassState"); 749 750 @Fold 751 public static int instanceKlassInitStateOffset(@InjectedParameter GraalHotSpotVMConfig config) { 752 return config.instanceKlassInitStateOffset; 753 } 754 755 @Fold 756 public static int instanceKlassStateFullyInitialized(@InjectedParameter GraalHotSpotVMConfig config) { 757 return config.instanceKlassStateFullyInitialized; 758 } 759 760 /** 761 * 762 * @param hub the hub of an InstanceKlass 763 * @return true is the InstanceKlass represented by hub is fully initialized 764 */ 765 public static boolean isInstanceKlassFullyInitialized(KlassPointer hub) { 766 return readInstanceKlassState(hub) == instanceKlassStateFullyInitialized(INJECTED_VMCONFIG); 767 } 768 769 private static byte readInstanceKlassState(KlassPointer hub) { 770 return hub.readByte(instanceKlassInitStateOffset(INJECTED_VMCONFIG), CLASS_STATE_LOCATION); 771 } 772 773 public static final LocationIdentity KLASS_MODIFIER_FLAGS_LOCATION = NamedLocationIdentity.immutable("Klass::_modifier_flags"); 774 775 @Fold 776 public static int klassModifierFlagsOffset(@InjectedParameter GraalHotSpotVMConfig config) { 777 return config.klassModifierFlagsOffset; 778 } 779 780 public static final LocationIdentity CLASS_KLASS_LOCATION = new HotSpotOptimizingLocationIdentity("Class._klass") { 781 @Override 782 public ValueNode canonicalizeRead(ValueNode read, AddressNode location, ValueNode object, CanonicalizerTool tool) { 783 return foldIndirection(read, object, CLASS_MIRROR_LOCATION); 784 } 785 }; 786 787 @Fold 788 public static int klassOffset(@InjectedParameter GraalHotSpotVMConfig config) { 789 return config.klassOffset; 790 } 791 792 public static final LocationIdentity CLASS_ARRAY_KLASS_LOCATION = new HotSpotOptimizingLocationIdentity("Class._array_klass") { 793 @Override 794 public ValueNode canonicalizeRead(ValueNode read, AddressNode location, ValueNode object, CanonicalizerTool tool) { 795 return foldIndirection(read, object, ARRAY_KLASS_COMPONENT_MIRROR); 796 } 797 }; 798 799 @Fold 800 public static int arrayKlassOffset(@InjectedParameter GraalHotSpotVMConfig config) { 801 return config.arrayKlassOffset; 802 } 803 804 public static final LocationIdentity CLASS_MIRROR_LOCATION = NamedLocationIdentity.immutable("Klass::_java_mirror"); 805 806 public static final LocationIdentity HEAP_TOP_LOCATION = NamedLocationIdentity.mutable("HeapTop"); 807 808 @Fold 809 public static long heapTopAddress(@InjectedParameter GraalHotSpotVMConfig config) { 810 return config.heapTopAddress; 811 } 812 813 public static final LocationIdentity HEAP_END_LOCATION = NamedLocationIdentity.mutable("HeapEnd"); 814 815 @Fold 816 public static long heapEndAddress(@InjectedParameter GraalHotSpotVMConfig config) { 817 return config.heapEndAddress; 818 } 819 820 @Fold 821 public static long tlabIntArrayMarkWord(@InjectedParameter GraalHotSpotVMConfig config) { 822 return config.tlabIntArrayMarkWord(); 823 } 824 825 @Fold 826 public static boolean inlineContiguousAllocationSupported(@InjectedParameter GraalHotSpotVMConfig config) { 827 return config.inlineContiguousAllocationSupported; 828 } 829 830 @Fold 831 public static int tlabAlignmentReserveInHeapWords(@InjectedParameter GraalHotSpotVMConfig config) { 832 return config.tlabAlignmentReserve; 833 } 834 835 public static final LocationIdentity TLAB_SIZE_LOCATION = NamedLocationIdentity.mutable("TlabSize"); 836 837 @Fold 838 public static int threadTlabSizeOffset(@InjectedParameter GraalHotSpotVMConfig config) { 839 return config.threadTlabSizeOffset(); 840 } 841 842 public static final LocationIdentity TLAB_THREAD_ALLOCATED_BYTES_LOCATION = NamedLocationIdentity.mutable("TlabThreadAllocatedBytes"); 843 844 @Fold 845 public static int threadAllocatedBytesOffset(@InjectedParameter GraalHotSpotVMConfig config) { 846 return config.threadAllocatedBytesOffset; 847 } 848 849 public static final LocationIdentity TLAB_REFILL_WASTE_LIMIT_LOCATION = NamedLocationIdentity.mutable("RefillWasteLimit"); 850 851 @Fold 852 public static int tlabRefillWasteLimitOffset(@InjectedParameter GraalHotSpotVMConfig config) { 853 return config.tlabRefillWasteLimitOffset(); 854 } 855 856 public static final LocationIdentity TLAB_NOF_REFILLS_LOCATION = NamedLocationIdentity.mutable("TlabNOfRefills"); 857 858 @Fold 859 public static int tlabNumberOfRefillsOffset(@InjectedParameter GraalHotSpotVMConfig config) { 860 return config.tlabNumberOfRefillsOffset(); 861 } 862 863 public static final LocationIdentity TLAB_FAST_REFILL_WASTE_LOCATION = NamedLocationIdentity.mutable("TlabFastRefillWaste"); 864 865 @Fold 866 public static int tlabFastRefillWasteOffset(@InjectedParameter GraalHotSpotVMConfig config) { 867 return config.tlabFastRefillWasteOffset(); 868 } 869 870 public static final LocationIdentity TLAB_SLOW_ALLOCATIONS_LOCATION = NamedLocationIdentity.mutable("TlabSlowAllocations"); 871 872 @Fold 873 public static int tlabSlowAllocationsOffset(@InjectedParameter GraalHotSpotVMConfig config) { 874 return config.tlabSlowAllocationsOffset(); 875 } 876 877 @Fold 878 public static int tlabRefillWasteIncrement(@InjectedParameter GraalHotSpotVMConfig config) { 879 return config.tlabRefillWasteIncrement; 880 } 881 882 @Fold 883 public static boolean tlabStats(@InjectedParameter GraalHotSpotVMConfig config) { 884 return config.tlabStats; 885 } 886 887 @Fold 888 public static int layoutHelperHeaderSizeShift(@InjectedParameter GraalHotSpotVMConfig config) { 889 return config.layoutHelperHeaderSizeShift; 890 } 891 892 @Fold 893 public static int layoutHelperHeaderSizeMask(@InjectedParameter GraalHotSpotVMConfig config) { 894 return config.layoutHelperHeaderSizeMask; 895 } 896 897 @Fold 898 public static int layoutHelperLog2ElementSizeShift(@InjectedParameter GraalHotSpotVMConfig config) { 899 return config.layoutHelperLog2ElementSizeShift; 900 } 901 902 @Fold 903 public static int layoutHelperLog2ElementSizeMask(@InjectedParameter GraalHotSpotVMConfig config) { 904 return config.layoutHelperLog2ElementSizeMask; 905 } 906 907 @Fold 908 public static int layoutHelperElementTypeShift(@InjectedParameter GraalHotSpotVMConfig config) { 909 return config.layoutHelperElementTypeShift; 910 } 911 912 @Fold 913 public static int layoutHelperElementTypeMask(@InjectedParameter GraalHotSpotVMConfig config) { 914 return config.layoutHelperElementTypeMask; 915 } 916 917 @Fold 918 public static int layoutHelperElementTypePrimitiveInPlace(@InjectedParameter GraalHotSpotVMConfig config) { 919 return config.layoutHelperElementTypePrimitiveInPlace(); 920 } 921 922 @NodeIntrinsic(ForeignCallNode.class) 923 public static native int identityHashCode(@ConstantNodeParameter ForeignCallDescriptor descriptor, Object object); 924 925 @Fold 926 public static int verifiedEntryPointOffset(@InjectedParameter GraalHotSpotVMConfig config) { 927 return config.nmethodEntryOffset; 928 } 929 930 @Fold 931 public static long gcTotalCollectionsAddress(@InjectedParameter GraalHotSpotVMConfig config) { 932 return config.gcTotalCollectionsAddress(); 933 } 934 935 @Fold 936 public static long referentOffset() { 937 try { 938 return UNSAFE.objectFieldOffset(java.lang.ref.Reference.class.getDeclaredField("referent")); 939 } catch (Exception e) { 940 throw new GraalError(e); 941 } 942 } 943 944 public static final LocationIdentity OBJ_ARRAY_KLASS_ELEMENT_KLASS_LOCATION = new HotSpotOptimizingLocationIdentity("ObjArrayKlass::_element_klass") { 945 @Override 946 public ValueNode canonicalizeRead(ValueNode read, AddressNode location, ValueNode object, CanonicalizerTool tool) { 947 ValueNode javaObject = findReadHub(object); 948 if (javaObject != null) { 949 ResolvedJavaType type = StampTool.typeOrNull(javaObject); 950 if (type != null && type.isArray()) { 951 ResolvedJavaType element = type.getComponentType(); 952 if (element != null && !element.isPrimitive() && !element.getElementalType().isInterface()) { 953 Assumptions assumptions = object.graph().getAssumptions(); 954 AssumptionResult<ResolvedJavaType> leafType = element.findLeafConcreteSubtype(); 955 if (leafType != null && leafType.canRecordTo(assumptions)) { 956 leafType.recordTo(assumptions); 957 return ConstantNode.forConstant(read.stamp(), tool.getConstantReflection().asObjectHub(leafType.getResult()), tool.getMetaAccess()); 958 } 959 } 960 } 961 } 962 return read; 963 } 964 }; 965 966 @Fold 967 public static int arrayClassElementOffset(@InjectedParameter GraalHotSpotVMConfig config) { 968 return config.arrayClassElementOffset; 969 } 970 971 public static final LocationIdentity PRIMARY_SUPERS_LOCATION = NamedLocationIdentity.immutable("PrimarySupers"); 972 973 public static final LocationIdentity METASPACE_ARRAY_LENGTH_LOCATION = NamedLocationIdentity.immutable("MetaspaceArrayLength"); 974 975 public static final LocationIdentity SECONDARY_SUPERS_ELEMENT_LOCATION = NamedLocationIdentity.immutable("SecondarySupersElement"); 976 }