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