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