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