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