--- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64Assembler.java 2019-05-04 02:43:32.632050382 +0200 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64Assembler.java 2019-05-04 02:43:32.272048276 +0200 @@ -3003,6 +3003,18 @@ emitByte(0x99); } + public final void repStosb() { + emitByte(0xf3); + rexw(); + emitByte(0xaa); + } + + public final void repStosq() { + emitByte(0xf3); + rexw(); + emitByte(0xab); + } + public final void cmovq(ConditionFlag cc, Register dst, Register src) { prefixq(dst, src); emitByte(0x0F); --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64ArithmeticLIRGenerator.java 2019-05-04 02:43:33.100053121 +0200 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64ArithmeticLIRGenerator.java 2019-05-04 02:43:32.740051014 +0200 @@ -121,6 +121,7 @@ import org.graalvm.compiler.lir.amd64.AMD64ShiftOp; import org.graalvm.compiler.lir.amd64.AMD64SignExtendOp; import org.graalvm.compiler.lir.amd64.AMD64Unary; +import org.graalvm.compiler.lir.amd64.AMD64ZeroMemoryOp; import org.graalvm.compiler.lir.amd64.vector.AMD64VectorBinary; import org.graalvm.compiler.lir.amd64.vector.AMD64VectorBinary.AVXBinaryOp; import org.graalvm.compiler.lir.amd64.vector.AMD64VectorUnary; @@ -1102,6 +1103,12 @@ return new AMD64MathPowOp().emitLIRWrapper(getLIRGen(), x, y); } + @Override + public void emitZeroMemory(Value address, Value length) { + RegisterValue lengthReg = moveToReg(AMD64.rcx, length); + getLIRGen().append(new AMD64ZeroMemoryOp(getAMD64LIRGen().asAddressValue(address), lengthReg)); + } + protected AMD64LIRGenerator getAMD64LIRGen() { return (AMD64LIRGenerator) getLIRGen(); } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/GraalOptions.java 2019-05-04 02:43:33.548055743 +0200 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/GraalOptions.java 2019-05-04 02:43:33.180053589 +0200 @@ -279,9 +279,13 @@ @Option(help = "Enable inlining decision tracing in stubs and snippets.", type = OptionType.Debug) public static final OptionKey TraceInliningForStubsAndSnippets = new OptionKey<>(false); - @Option(help = "Use Graal-generated stubs for complicated LIR operations instead of embedding all the emitted code.") + @Option(help = "Use Graal-generated stubs for complicated LIR operations instead of embedding all the emitted code.", type = OptionType.Expert) public static final OptionKey UseGraalStubs = new OptionKey<>(true); @Option(help = "Encode and decode snippets and substitutions before parsing to test libgraal code path. This option is ignored in the context of libgraal.") public static final OptionKey UseEncodedGraphs = new OptionKey<>(false); + + @Option(help = "If applicable, use bulk zeroing instructions when the zeroing size in bytes exceeds this threshold.", type = OptionType.Expert) + public static final OptionKey MinimalBulkZeroingSize = new OptionKey<>(2048); + } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLoweringProvider.java 2019-05-04 02:43:33.984058296 +0200 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLoweringProvider.java 2019-05-04 02:43:33.620056164 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,6 @@ package org.graalvm.compiler.hotspot.amd64; -import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; import static org.graalvm.compiler.hotspot.HotSpotBackend.Options.GraalArithmeticStubs; import org.graalvm.compiler.api.replacements.Snippet; @@ -67,7 +66,7 @@ @Override public void initialize(OptionValues options, Iterable factories, HotSpotProviders providers, GraalHotSpotVMConfig config) { convertSnippets = new AMD64ConvertSnippets.Templates(options, factories, providers, providers.getSnippetReflection(), providers.getCodeCache().getTarget()); - profileSnippets = ProfileNode.Options.ProbabilisticProfiling.getValue(options) && !JavaVersionUtil.Java8OrEarlier && GeneratePIC.getValue(options) + profileSnippets = ProfileNode.Options.ProbabilisticProfiling.getValue(options) && !JavaVersionUtil.Java8OrEarlier ? new ProbabilisticProfileSnippets.Templates(options, factories, providers, providers.getCodeCache().getTarget()) : null; mathSnippets = new AMD64X87MathSnippets.Templates(options, factories, providers, providers.getSnippetReflection(), providers.getCodeCache().getTarget()); @@ -129,4 +128,9 @@ public Integer smallestCompareWidth() { return 8; } + + @Override + public boolean supportBulkZeroing() { + return true; + } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfig.java 2019-05-04 02:43:34.420060846 +0200 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfig.java 2019-05-04 02:43:34.060058739 +0200 @@ -460,6 +460,7 @@ public final int objectMonitorRecursions = getFieldOffset("ObjectMonitor::_recursions", Integer.class, "intptr_t", -1); public final int objectMonitorCxq = getFieldOffset("ObjectMonitor::_cxq", Integer.class, "ObjectWaiter*", -1); public final int objectMonitorEntryList = getFieldOffset("ObjectMonitor::_EntryList", Integer.class, "ObjectWaiter*", -1); + public final int objectMonitorSucc = getFieldOffset("ObjectMonitor::_succ", Integer.class, "Thread*", -1); public final int markWordNoHashInPlace = getConstant("markOopDesc::no_hash_in_place", Integer.class); public final int markWordNoLockInPlace = getConstant("markOopDesc::no_lock_in_place", Integer.class); --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/IsGraalPredicate.java 2019-05-04 02:43:34.888063587 +0200 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/IsGraalPredicate.java 2019-05-04 02:43:34.532061502 +0200 @@ -24,10 +24,6 @@ package org.graalvm.compiler.hotspot; -import static jdk.vm.ci.hotspot.HotSpotJVMCICompilerFactory.CompilationLevelAdjustment.None; - -import org.graalvm.compiler.debug.GraalError; - import jdk.vm.ci.hotspot.HotSpotJVMCICompilerFactory; import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; @@ -60,17 +56,17 @@ @Override void onCompilerConfigurationFactorySelection(HotSpotJVMCIRuntime runtime, CompilerConfigurationFactory factory) { compilerConfigurationModule = factory.getClass().getModule(); - runtime.excludeFromJVMCICompilation(jvmciModule, graalModule, compilerConfigurationModule); } @Override boolean apply(Class declaringClass) { - throw GraalError.shouldNotReachHere(); + Module module = declaringClass.getModule(); + return jvmciModule == module || graalModule == module || compilerConfigurationModule == module; } @Override HotSpotJVMCICompilerFactory.CompilationLevelAdjustment getCompilationLevelAdjustment() { - return None; + return HotSpotJVMCICompilerFactory.CompilationLevelAdjustment.ByHolder; } - } + --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/SymbolicSnippetEncoder.java 2019-05-04 02:43:35.360066349 +0200 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/SymbolicSnippetEncoder.java 2019-05-04 02:43:35.012064312 +0200 @@ -571,7 +571,7 @@ try { replacement = ((SymbolicJVMCIReference) o).resolve(type); break; - } catch (NoClassDefFoundError | AssertionError e) { + } catch (NoClassDefFoundError e) { } } } else if (o instanceof UnresolvedJavaType) { @@ -579,7 +579,7 @@ try { replacement = ((UnresolvedJavaType) o).resolve(type); break; - } catch (NoClassDefFoundError | AssertionError e) { + } catch (NoClassDefFoundError e) { } } } else if (o instanceof UnresolvedJavaMethod) { @@ -589,7 +589,7 @@ try { replacement = ((UnresolvedJavaField) o).resolve(type); break; - } catch (NoClassDefFoundError | AssertionError e) { + } catch (NoClassDefFoundError e) { } } } else if (o instanceof GraalCapability) { --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java 2019-05-04 02:43:35.836069137 +0200 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java 2019-05-04 02:43:35.484067076 +0200 @@ -26,7 +26,6 @@ import static jdk.vm.ci.services.Services.IS_IN_NATIVE_IMAGE; import static org.graalvm.compiler.core.common.GraalOptions.AlwaysInlineVTableStubs; -import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; import static org.graalvm.compiler.core.common.GraalOptions.InlineVTableStubs; import static org.graalvm.compiler.core.common.GraalOptions.OmitHotExceptionStacktrace; import static org.graalvm.compiler.hotspot.meta.HotSpotForeignCallsProviderImpl.OSR_MIGRATION_END; @@ -228,7 +227,7 @@ stringToBytesSnippets = new StringToBytesSnippets.Templates(options, factories, providers, target); hashCodeSnippets = new HashCodeSnippets.Templates(options, factories, providers, target); resolveConstantSnippets = new ResolveConstantSnippets.Templates(options, factories, providers, target); - if (!JavaVersionUtil.Java8OrEarlier && GeneratePIC.getValue(options)) { + if (!JavaVersionUtil.Java8OrEarlier) { profileSnippets = new ProfileSnippets.Templates(options, factories, providers, target); } objectCloneSnippets = new ObjectCloneSnippets.Templates(options, factories, providers, target); --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotReplacementsUtil.java 2019-05-04 02:43:36.372072275 +0200 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotReplacementsUtil.java 2019-05-04 02:43:35.968069909 +0200 @@ -516,6 +516,11 @@ return config.objectMonitorEntryList; } + @Fold + public static int objectMonitorSuccOffset(@InjectedParameter GraalHotSpotVMConfig config) { + return config.objectMonitorSucc; + } + /** * Mask for a biasable, locked or unlocked mark word. * @@ -685,6 +690,8 @@ public static final LocationIdentity OBJECT_MONITOR_ENTRY_LIST_LOCATION = NamedLocationIdentity.mutable("ObjectMonitor::_EntryList"); + public static final LocationIdentity OBJECT_MONITOR_SUCC_LOCATION = NamedLocationIdentity.mutable("ObjectMonitor::_succ"); + @Fold public static int lockDisplacedMarkOffset(@InjectedParameter GraalHotSpotVMConfig config) { return config.basicLockDisplacedHeaderOffset; --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/MonitorSnippets.java 2019-05-04 02:43:36.904075389 +0200 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/MonitorSnippets.java 2019-05-04 02:43:36.508073070 +0200 @@ -25,6 +25,7 @@ package org.graalvm.compiler.hotspot.replacements; import static jdk.vm.ci.code.MemoryBarriers.LOAD_STORE; +import static jdk.vm.ci.code.MemoryBarriers.STORE_LOAD; import static jdk.vm.ci.code.MemoryBarriers.STORE_STORE; import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfig.INJECTED_OPTIONVALUES; import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfig.INJECTED_VMCONFIG; @@ -38,6 +39,7 @@ import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.OBJECT_MONITOR_ENTRY_LIST_LOCATION; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.OBJECT_MONITOR_OWNER_LOCATION; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.OBJECT_MONITOR_RECURSION_LOCATION; +import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.OBJECT_MONITOR_SUCC_LOCATION; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.PROTOTYPE_MARK_WORD_LOCATION; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.ageMaskInPlace; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.biasedLockMaskInPlace; @@ -51,6 +53,7 @@ import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.objectMonitorEntryListOffset; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.objectMonitorOwnerOffset; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.objectMonitorRecursionsOffset; +import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.objectMonitorSuccOffset; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.pageSize; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.prototypeMarkWordOffset; import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.registerAsWord; @@ -574,6 +577,32 @@ traceObject(trace, "-lock{inflated:simple}", object, false); counters.unlockInflatedSimple.inc(); return true; + } else { + int succOffset = objectMonitorSuccOffset(INJECTED_VMCONFIG); + Word succ = monitor.readWord(succOffset, OBJECT_MONITOR_SUCC_LOCATION); + if (probability(FREQUENT_PROBABILITY, succ.isNonNull())) { + // There may be a thread spinning on this monitor. Temporarily setting + // the monitor owner to null, and hope that the other thread will grab it. + monitor.writeWord(ownerOffset, zero()); + memoryBarrier(STORE_STORE | STORE_LOAD); + succ = monitor.readWord(succOffset, OBJECT_MONITOR_SUCC_LOCATION); + if (probability(NOT_FREQUENT_PROBABILITY, succ.isNonNull())) { + // We manage to release the monitor before the other running thread even + // notices. + traceObject(trace, "-lock{inflated:transfer}", object, false); + counters.unlockInflatedTransfer.inc(); + return true; + } else { + // Either the monitor is grabbed by a spinning thread, or the spinning + // thread parks. Now we attempt to reset the owner of the monitor. + if (probability(FREQUENT_PROBABILITY, !monitor.logicCompareAndSwapWord(ownerOffset, zero(), thread, OBJECT_MONITOR_OWNER_LOCATION))) { + // The monitor is stolen. + traceObject(trace, "-lock{inflated:transfer}", object, false); + counters.unlockInflatedTransfer.inc(); + return true; + } + } + } } } counters.unlockStubInflated.inc(); @@ -692,6 +721,7 @@ public final SnippetCounter unlockStub; public final SnippetCounter unlockStubInflated; public final SnippetCounter unlockInflatedSimple; + public final SnippetCounter unlockInflatedTransfer; public Counters(SnippetCounter.Group.Factory factory) { SnippetCounter.Group enter = factory.createSnippetCounterGroup("MonitorEnters"); @@ -716,6 +746,7 @@ unlockStub = new SnippetCounter(exit, "unlock{stub}", "stub-unlocked an object"); unlockStubInflated = new SnippetCounter(exit, "unlock{stub:inflated}", "stub-unlocked an object with inflated monitor"); unlockInflatedSimple = new SnippetCounter(exit, "unlock{inflated}", "unlocked an object monitor"); + unlockInflatedTransfer = new SnippetCounter(exit, "unlock{inflated:transfer}", "unlocked an object monitor in the presence of ObjectMonitor::_succ"); } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/NewObjectSnippets.java 2019-05-04 02:43:37.440078528 +0200 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/NewObjectSnippets.java 2019-05-04 02:43:37.040076185 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,6 +27,7 @@ import static jdk.vm.ci.meta.DeoptimizationAction.None; import static jdk.vm.ci.meta.DeoptimizationReason.RuntimeConstraint; import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC; +import static org.graalvm.compiler.core.common.GraalOptions.MinimalBulkZeroingSize; import static org.graalvm.compiler.core.common.calc.UnsignedMath.belowThan; import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfigBase.INJECTED_OPTIONVALUES; import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfigBase.INJECTED_VMCONFIG; @@ -130,6 +131,7 @@ import org.graalvm.compiler.replacements.SnippetTemplate.SnippetInfo; import org.graalvm.compiler.replacements.Snippets; import org.graalvm.compiler.replacements.nodes.ExplodeLoopNode; +import org.graalvm.compiler.replacements.nodes.ZeroMemoryNode; import org.graalvm.compiler.word.Word; import jdk.internal.vm.compiler.word.LocationIdentity; import jdk.internal.vm.compiler.word.WordFactory; @@ -311,21 +313,39 @@ public static final int MAX_ARRAY_FAST_PATH_ALLOCATION_LENGTH = 0x00FFFFFF; @Snippet - public static Object allocatePrimitiveArrayPIC(KlassPointer hub, int length, Word prototypeMarkWord, @ConstantParameter int headerSize, @ConstantParameter int log2ElementSize, - @ConstantParameter boolean fillContents, @ConstantParameter Register threadRegister, @ConstantParameter boolean maybeUnroll, @ConstantParameter String typeContext, + public static Object allocatePrimitiveArrayPIC(KlassPointer hub, + int length, + Word prototypeMarkWord, + @ConstantParameter int headerSize, + @ConstantParameter int log2ElementSize, + @ConstantParameter boolean fillContents, + @ConstantParameter Register threadRegister, + @ConstantParameter boolean maybeUnroll, + @ConstantParameter String typeContext, + @ConstantParameter boolean useBulkZeroing, @ConstantParameter Counters counters) { // Primitive array types are eagerly pre-resolved. We can use a floating load. KlassPointer picHub = LoadConstantIndirectlyNode.loadKlass(hub); - return allocateArrayImpl(picHub, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents, threadRegister, maybeUnroll, typeContext, counters); + return allocateArrayImpl(picHub, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents, + threadRegister, maybeUnroll, typeContext, useBulkZeroing, counters); } @Snippet - public static Object allocateArrayPIC(KlassPointer hub, int length, Word prototypeMarkWord, @ConstantParameter int headerSize, @ConstantParameter int log2ElementSize, - @ConstantParameter boolean fillContents, @ConstantParameter Register threadRegister, @ConstantParameter boolean maybeUnroll, @ConstantParameter String typeContext, + public static Object allocateArrayPIC(KlassPointer hub, + int length, + Word prototypeMarkWord, + @ConstantParameter int headerSize, + @ConstantParameter int log2ElementSize, + @ConstantParameter boolean fillContents, + @ConstantParameter Register threadRegister, + @ConstantParameter boolean maybeUnroll, + @ConstantParameter String typeContext, + @ConstantParameter boolean useBulkZeroing, @ConstantParameter Counters counters) { // Array type would be resolved by dominating resolution. KlassPointer picHub = LoadConstantIndirectlyFixedNode.loadKlass(hub); - return allocateArrayImpl(picHub, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents, threadRegister, maybeUnroll, typeContext, counters); + return allocateArrayImpl(picHub, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents, + threadRegister, maybeUnroll, typeContext, useBulkZeroing, counters); } @Snippet @@ -338,6 +358,7 @@ @ConstantParameter Register threadRegister, @ConstantParameter boolean maybeUnroll, @ConstantParameter String typeContext, + @ConstantParameter boolean useBulkZeroing, @ConstantParameter Counters counters) { Object result = allocateArrayImpl(hub, length, @@ -348,7 +369,7 @@ threadRegister, maybeUnroll, typeContext, - + useBulkZeroing, counters); return piArrayCastToSnippetReplaceeStamp(verifyOop(result), length); } @@ -363,7 +384,7 @@ } private static Object allocateArrayImpl(KlassPointer hub, int length, Word prototypeMarkWord, int headerSize, int log2ElementSize, boolean fillContents, Register threadRegister, - boolean maybeUnroll, String typeContext, Counters counters) { + boolean maybeUnroll, String typeContext, boolean useBulkZeroing, Counters counters) { Object result; long allocationSize = arrayAllocationSize(length, headerSize, log2ElementSize); Word thread = registerAsWord(threadRegister); @@ -378,7 +399,7 @@ if (theCounters != null && theCounters.arrayLoopInit != null) { theCounters.arrayLoopInit.inc(); } - result = formatArray(hub, allocationSize, length, headerSize, top, prototypeMarkWord, fillContents, maybeUnroll, counters); + result = formatArray(hub, allocationSize, length, headerSize, top, prototypeMarkWord, fillContents, maybeUnroll, useBulkZeroing, counters); } else { result = newArrayStub(hub, length); } @@ -435,15 +456,23 @@ public static native Object dynamicNewInstanceOrNull(@ConstantNodeParameter ForeignCallDescriptor descriptor, Class elementType); @Snippet - public static Object allocateArrayDynamic(Class elementType, Class voidClass, int length, @ConstantParameter boolean fillContents, @ConstantParameter Register threadRegister, - @ConstantParameter JavaKind knownElementKind, @ConstantParameter int knownLayoutHelper, Word prototypeMarkWord, + public static Object allocateArrayDynamic(Class elementType, + Class voidClass, + int length, + @ConstantParameter boolean fillContents, + @ConstantParameter Register threadRegister, + @ConstantParameter JavaKind knownElementKind, + @ConstantParameter int knownLayoutHelper, + @ConstantParameter boolean useBulkZeroing, + Word prototypeMarkWord, @ConstantParameter Counters counters) { - Object result = allocateArrayDynamicImpl(elementType, voidClass, length, fillContents, threadRegister, knownElementKind, knownLayoutHelper, prototypeMarkWord, counters); + Object result = allocateArrayDynamicImpl(elementType, voidClass, length, fillContents, threadRegister, knownElementKind, + knownLayoutHelper, useBulkZeroing, prototypeMarkWord, counters); return result; } private static Object allocateArrayDynamicImpl(Class elementType, Class voidClass, int length, boolean fillContents, Register threadRegister, JavaKind knownElementKind, - int knownLayoutHelper, Word prototypeMarkWord, Counters counters) { + int knownLayoutHelper, boolean useBulkZeroing, Word prototypeMarkWord, Counters counters) { /* * We only need the dynamic check for void when we have no static information from * knownElementKind. @@ -485,7 +514,8 @@ int headerSize = (layoutHelper >> layoutHelperHeaderSizeShift(INJECTED_VMCONFIG)) & layoutHelperHeaderSizeMask(INJECTED_VMCONFIG); int log2ElementSize = (layoutHelper >> layoutHelperLog2ElementSizeShift(INJECTED_VMCONFIG)) & layoutHelperLog2ElementSizeMask(INJECTED_VMCONFIG); - Object result = allocateArrayImpl(nonNullKlass, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents, threadRegister, false, "dynamic type", counters); + Object result = allocateArrayImpl(nonNullKlass, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents, + threadRegister, false, "dynamic type", useBulkZeroing, counters); return piArrayCastToSnippetReplaceeStamp(verifyOop(result), length); } @@ -538,12 +568,15 @@ * @param constantSize is {@code size} known to be constant in the snippet * @param startOffset offset to begin zeroing. May not be word aligned. * @param manualUnroll maximally unroll zeroing + * @param useBulkZeroing apply bulk zeroing */ - private static void zeroMemory(long size, Word memory, boolean constantSize, int startOffset, boolean manualUnroll, Counters counters) { - fillMemory(0, size, memory, constantSize, startOffset, manualUnroll, counters); + private static void zeroMemory(long size, Word memory, boolean constantSize, int startOffset, boolean manualUnroll, + boolean useBulkZeroing, Counters counters) { + fillMemory(0, size, memory, constantSize, startOffset, manualUnroll, useBulkZeroing, counters); } - private static void fillMemory(long value, long size, Word memory, boolean constantSize, int startOffset, boolean manualUnroll, Counters counters) { + private static void fillMemory(long value, long size, Word memory, boolean constantSize, int startOffset, boolean manualUnroll, + boolean useBulkZeroing, Counters counters) { ReplacementsUtil.runtimeAssert((size & 0x7) == 0, "unaligned object size"); int offset = startOffset; if ((offset & 0x7) != 0) { @@ -571,22 +604,35 @@ } else { // Use Word instead of int to avoid extension to long in generated code Word off = WordFactory.signed(offset); - if (constantSize && ((size - offset) / 8) <= MAX_UNROLLED_OBJECT_ZEROING_STORES) { - if (theCounters != null && theCounters.instanceSeqInit != null) { - theCounters.instanceSeqInit.inc(); + if (useBulkZeroing && probability(SLOW_PATH_PROBABILITY, size >= getMinimalBulkZeroingSize(INJECTED_OPTIONVALUES))) { + if (theCounters != null && theCounters.instanceBulkInit != null) { + theCounters.instanceBulkInit.inc(); } - explodeLoop(); + ZeroMemoryNode.zero(memory.add(off), size - offset, LocationIdentity.init()); } else { - if (theCounters != null && theCounters.instanceLoopInit != null) { - theCounters.instanceLoopInit.inc(); + if (constantSize && ((size - offset) / 8) <= MAX_UNROLLED_OBJECT_ZEROING_STORES) { + if (theCounters != null && theCounters.instanceSeqInit != null) { + theCounters.instanceSeqInit.inc(); + } + explodeLoop(); + } else { + if (theCounters != null && theCounters.instanceLoopInit != null) { + theCounters.instanceLoopInit.inc(); + } } - } - for (; off.rawValue() < size; off = off.add(8)) { - memory.initializeLong(off, value, LocationIdentity.init()); + for (; off.rawValue() < size; off = off.add(8)) { + memory.initializeLong(off, value, LocationIdentity.init()); + } + } } } + @Fold + static int getMinimalBulkZeroingSize(@InjectedParameter OptionValues optionValues) { + return MinimalBulkZeroingSize.getValue(optionValues); + } + /** * Fill uninitialized memory with garbage value in a newly allocated object, unrolling as * necessary and ensuring that stores are aligned. @@ -598,7 +644,7 @@ * @param manualUnroll maximally unroll zeroing */ private static void fillWithGarbage(long size, Word memory, boolean constantSize, int startOffset, boolean manualUnroll, Counters counters) { - fillMemory(0xfefefefefefefefeL, size, memory, constantSize, startOffset, manualUnroll, counters); + fillMemory(0xfefefefefefefefeL, size, memory, constantSize, startOffset, manualUnroll, false, counters); } /** @@ -608,7 +654,7 @@ Word prototypeMarkWord = useBiasedLocking(INJECTED_VMCONFIG) ? hub.readWord(prototypeMarkWordOffset(INJECTED_VMCONFIG), PROTOTYPE_MARK_WORD_LOCATION) : compileTimePrototypeMarkWord; initializeObjectHeader(memory, prototypeMarkWord, hub); if (fillContents) { - zeroMemory(size, memory, constantSize, instanceHeaderSize(INJECTED_VMCONFIG), false, counters); + zeroMemory(size, memory, constantSize, instanceHeaderSize(INJECTED_VMCONFIG), false, false, counters); } else if (REPLACEMENTS_ASSERTIONS_ENABLED) { fillWithGarbage(size, memory, constantSize, instanceHeaderSize(INJECTED_VMCONFIG), false, counters); } @@ -632,7 +678,7 @@ * Formats some allocated memory with an object header and zeroes out the rest. */ private static Object formatArray(KlassPointer hub, long allocationSize, int length, int headerSize, Word memory, Word prototypeMarkWord, boolean fillContents, boolean maybeUnroll, - Counters counters) { + boolean useBulkZeroing, Counters counters) { memory.writeInt(arrayLengthOffset(INJECTED_VMCONFIG), length, LocationIdentity.init()); /* * store hub last as the concurrent garbage collectors assume length is valid if hub field @@ -640,7 +686,7 @@ */ initializeObjectHeader(memory, prototypeMarkWord, hub); if (fillContents) { - zeroMemory(allocationSize, memory, false, headerSize, maybeUnroll, counters); + zeroMemory(allocationSize, memory, false, headerSize, maybeUnroll, useBulkZeroing, counters); } else if (REPLACEMENTS_ASSERTIONS_ENABLED) { fillWithGarbage(allocationSize, memory, false, headerSize, maybeUnroll, counters); } @@ -654,12 +700,14 @@ Group newArray = factory.createSnippetCounterGroup("NewArray"); instanceSeqInit = new SnippetCounter(newInstance, "tlabSeqInit", "TLAB alloc with unrolled zeroing"); instanceLoopInit = new SnippetCounter(newInstance, "tlabLoopInit", "TLAB alloc with zeroing in a loop"); + instanceBulkInit = new SnippetCounter(newArray, "tlabBulkInit", "TLAB alloc with bulk zeroing"); arrayLoopInit = new SnippetCounter(newArray, "tlabLoopInit", "TLAB alloc with zeroing in a loop"); stub = new SnippetCounter(newInstance, "stub", "alloc and zeroing via stub"); } final SnippetCounter instanceSeqInit; final SnippetCounter instanceLoopInit; + final SnippetCounter instanceBulkInit; final SnippetCounter arrayLoopInit; final SnippetCounter stub; } @@ -753,6 +801,7 @@ args.addConst("threadRegister", registers.getThreadRegister()); args.addConst("maybeUnroll", length.isConstant()); args.addConst("typeContext", ProfileAllocations.getValue(localOptions) ? arrayType.toJavaName(false) : ""); + args.addConst("useBulkZeroing", tool.getLowerer().supportBulkZeroing()); args.addConst("counters", counters); SnippetTemplate template = template(newArrayNode, args); graph.getDebug().log("Lowering allocateArray in %s: node=%s, template=%s, arguments=%s", graph, newArrayNode, template, args); @@ -775,7 +824,7 @@ public void lower(DynamicNewArrayNode newArrayNode, HotSpotRegistersProvider registers, LoweringTool tool) { StructuredGraph graph = newArrayNode.graph(); - Arguments args = new Arguments(allocateArrayDynamic, newArrayNode.graph().getGuardsStage(), tool.getLoweringStage()); + Arguments args = new Arguments(allocateArrayDynamic, graph.getGuardsStage(), tool.getLoweringStage()); args.add("elementType", newArrayNode.getElementType()); ValueNode voidClass = newArrayNode.getVoidClass(); assert voidClass != null; @@ -794,6 +843,7 @@ } else { args.addConst("knownLayoutHelper", 0); } + args.addConst("useBulkZeroing", tool.getLowerer().supportBulkZeroing()); args.add("prototypeMarkWord", lookupArrayClass(tool, JavaKind.Object).prototypeMarkWord()); args.addConst("counters", counters); SnippetTemplate template = template(newArrayNode, args); --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/ArithmeticLIRGeneratorTool.java 2019-05-04 02:43:37.972081644 +0200 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/ArithmeticLIRGeneratorTool.java 2019-05-04 02:43:37.572079301 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -132,4 +132,8 @@ throw GraalError.unimplemented("No specialized implementation available"); } + @SuppressWarnings("unused") + default void emitZeroMemory(Value address, Value length) { + throw GraalError.unimplemented("Bulk zeroing is not supported on this platform"); + } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/NewInstanceNode.java 2019-05-04 02:43:38.488084666 +0200 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/NewInstanceNode.java 2019-05-04 02:43:38.088082324 +0200 @@ -60,7 +60,7 @@ protected NewInstanceNode(NodeClass c, ResolvedJavaType type, boolean fillContents, FrameState stateBefore) { super(c, StampFactory.objectNonNull(TypeReference.createExactTrusted(type)), fillContents, stateBefore); - assert !type.isArray() && !type.isInterface() && !type.isPrimitive() && !type.isAbstract(); + assert !type.isArray() && !type.isInterface() && !type.isPrimitive() && !type.isAbstract() : type; this.instanceClass = type; } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/LoweringProvider.java 2019-05-04 02:43:39.020087783 +0200 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/LoweringProvider.java 2019-05-04 02:43:38.620085439 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -54,4 +54,11 @@ // most platforms only support 32 and 64 bit compares return 32; } + + /** + * Indicates whether the target platform supports bulk zeroing instruction. + */ + default boolean supportBulkZeroing() { + return false; + } } --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/BinaryGraphPrinter.java 2019-05-04 02:43:39.528090759 +0200 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/BinaryGraphPrinter.java 2019-05-04 02:43:39.132088438 +0200 @@ -91,7 +91,7 @@ public BinaryGraphPrinter(DebugContext ctx, SnippetReflectionProvider snippetReflection) throws IOException { // @formatter:off this.output = ctx.buildOutput(GraphOutput.newBuilder(this). - protocolVersion(6, 0). + protocolVersion(6, 1). blocks(this). elementsAndLocations(this, this). types(this) --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.serviceprovider/src/org/graalvm/compiler/serviceprovider/GraalServices.java 2019-05-04 02:43:40.044093782 +0200 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.serviceprovider/src/org/graalvm/compiler/serviceprovider/GraalServices.java 2019-05-04 02:43:39.644091439 +0200 @@ -29,38 +29,22 @@ import java.io.IOException; import java.io.InputStream; import java.util.Arrays; -import java.util.ArrayList; -import java.util.HashMap; import java.util.Iterator; import java.util.List; -import java.util.Map; import java.util.ServiceConfigurationError; import java.util.ServiceLoader; import java.util.concurrent.atomic.AtomicLong; -import java.util.function.Supplier; -import org.graalvm.compiler.serviceprovider.SpeculationReasonGroup.SpeculationContextObject; - -import jdk.vm.ci.code.BytecodePosition; -import jdk.vm.ci.meta.ResolvedJavaField; -import jdk.vm.ci.meta.ResolvedJavaMethod; -import jdk.vm.ci.meta.ResolvedJavaType; import jdk.vm.ci.meta.SpeculationLog.SpeculationReason; -import jdk.vm.ci.meta.SpeculationLog.SpeculationReasonEncoding; import jdk.vm.ci.runtime.JVMCI; import jdk.vm.ci.services.JVMCIPermission; import jdk.vm.ci.services.Services; -import static jdk.vm.ci.services.Services.IS_IN_NATIVE_IMAGE; -import static jdk.vm.ci.services.Services.IS_BUILDING_NATIVE_IMAGE; - /** - * JDK 13+ version of {@link GraalServices}. + * JDK 9+ version of {@link GraalServices}. */ public final class GraalServices { - private static final Map, List> servicesCache = IS_BUILDING_NATIVE_IMAGE ? new HashMap<>() : null; - private GraalServices() { } @@ -70,37 +54,8 @@ * @throws SecurityException if on JDK8 and a security manager is present and it denies * {@link JVMCIPermission} */ - @SuppressWarnings("unchecked") public static Iterable load(Class service) { - if (IS_IN_NATIVE_IMAGE || IS_BUILDING_NATIVE_IMAGE) { - List list = servicesCache.get(service); - if (list != null) { - return (Iterable) list; - } - if (IS_IN_NATIVE_IMAGE) { - throw new InternalError(String.format("No %s providers found when building native image", service.getName())); - } - } - - Iterable providers = load0(service); - - if (IS_BUILDING_NATIVE_IMAGE) { - synchronized (servicesCache) { - ArrayList providersList = new ArrayList<>(); - for (S provider : providers) { - providersList.add(provider); - } - providers = providersList; - servicesCache.put(service, providersList); - return providers; - } - } - - return providers; - } - - protected static Iterable load0(Class service) { - Iterable iterable = ServiceLoader.load(service, GraalServices.class.getClassLoader()); + Iterable iterable = ServiceLoader.load(service); return new Iterable<>() { @Override public Iterator iterator() { @@ -135,8 +90,6 @@ * @param other all JVMCI packages will be opened to the module defining this class */ static void openJVMCITo(Class other) { - if (IS_IN_NATIVE_IMAGE) return; - Module jvmciModule = JVMCI_MODULE; Module otherModule = other.getModule(); if (jvmciModule != otherModule) { @@ -145,7 +98,7 @@ // JVMCI initialization opens all JVMCI packages // to Graal which is a prerequisite for Graal to // open JVMCI packages to other modules. - JVMCI.getRuntime(); + JVMCI.initialize(); jvmciModule.addOpens(pkg, otherModule); } @@ -226,7 +179,6 @@ final int groupId; final String groupName; final Object[] context; - private SpeculationReasonEncoding encoding; DirectSpeculationReason(int groupId, String groupName, Object[] context) { this.groupId = groupId; @@ -252,123 +204,6 @@ public String toString() { return String.format("%s@%d%s", groupName, groupId, Arrays.toString(context)); } - - @Override - public SpeculationReasonEncoding encode(Supplier encodingSupplier) { - if (encoding == null) { - encoding = encodingSupplier.get(); - encoding.addInt(groupId); - for (Object o : context) { - if (o == null) { - encoding.addInt(0); - } else { - addNonNullObject(encoding, o); - } - } - } - return encoding; - } - - static void addNonNullObject(SpeculationReasonEncoding encoding, Object o) { - Class c = o.getClass(); - if (c == String.class) { - encoding.addString((String) o); - } else if (c == Byte.class) { - encoding.addByte((Byte) o); - } else if (c == Short.class) { - encoding.addShort((Short) o); - } else if (c == Character.class) { - encoding.addShort((Character) o); - } else if (c == Integer.class) { - encoding.addInt((Integer) o); - } else if (c == Long.class) { - encoding.addLong((Long) o); - } else if (c == Float.class) { - encoding.addInt(Float.floatToRawIntBits((Float) o)); - } else if (c == Double.class) { - encoding.addLong(Double.doubleToRawLongBits((Double) o)); - } else if (o instanceof Enum) { - encoding.addInt(((Enum) o).ordinal()); - } else if (o instanceof ResolvedJavaMethod) { - encoding.addMethod((ResolvedJavaMethod) o); - } else if (o instanceof ResolvedJavaType) { - encoding.addType((ResolvedJavaType) o); - } else if (o instanceof ResolvedJavaField) { - encoding.addField((ResolvedJavaField) o); - } else if (o instanceof SpeculationContextObject) { - SpeculationContextObject sco = (SpeculationContextObject) o; - // These are compiler objects which all have the same class - // loader so the class name uniquely identifies the class. - encoding.addString(o.getClass().getName()); - sco.accept(new EncodingAdapter(encoding)); - } else if (o.getClass() == BytecodePosition.class) { - BytecodePosition p = (BytecodePosition) o; - while (p != null) { - encoding.addInt(p.getBCI()); - encoding.addMethod(p.getMethod()); - p = p.getCaller(); - } - } else { - throw new IllegalArgumentException("Unsupported type for encoding: " + c.getName()); - } - } - } - - static class EncodingAdapter implements SpeculationContextObject.Visitor { - private final SpeculationReasonEncoding encoding; - - EncodingAdapter(SpeculationReasonEncoding encoding) { - this.encoding = encoding; - } - - @Override - public void visitBoolean(boolean v) { - encoding.addByte(v ? 1 : 0); - } - - @Override - public void visitByte(byte v) { - encoding.addByte(v); - } - - @Override - public void visitChar(char v) { - encoding.addShort(v); - } - - @Override - public void visitShort(short v) { - encoding.addInt(v); - } - - @Override - public void visitInt(int v) { - encoding.addInt(v); - } - - @Override - public void visitLong(long v) { - encoding.addLong(v); - } - - @Override - public void visitFloat(float v) { - encoding.addInt(Float.floatToRawIntBits(v)); - } - - @Override - public void visitDouble(double v) { - encoding.addLong(Double.doubleToRawLongBits(v)); - } - - @Override - public void visitObject(Object v) { - if (v == null) { - encoding.addInt(0); - } else { - DirectSpeculationReason.addNonNullObject(encoding, v); - } - } } static SpeculationReason createSpeculationReason(int groupId, String groupName, Object... context) { @@ -502,3 +337,4 @@ return jmx.getInputArguments(); } } + --- old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.graphio/src/org/graalvm/graphio/GraphProtocol.java 2019-05-04 02:43:40.580096923 +0200 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.graphio/src/org/graalvm/graphio/GraphProtocol.java 2019-05-04 02:43:40.176094556 +0200 @@ -75,6 +75,9 @@ private static final byte[] MAGIC_BYTES = {'B', 'I', 'G', 'V'}; + private static final int MAJOR_VERSION = 6; + private static final int MINOR_VERSION = 1; + private final ConstantPool constantPool; private final ByteBuffer buffer; private final WritableByteChannel channel; @@ -84,7 +87,7 @@ private boolean printing; GraphProtocol(WritableByteChannel channel, int major, int minor, boolean embedded) throws IOException { - if (major > 6 || (major == 6 && minor > 0)) { + if (major > MAJOR_VERSION || (major == MAJOR_VERSION && minor > MINOR_VERSION)) { throw new IllegalArgumentException("Unrecognized version " + major + "." + minor); } this.versionMajor = major; --- /dev/null 2017-11-16 08:17:56.803999947 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ZeroMemoryOp.java 2019-05-04 02:43:40.708097673 +0200 @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +package org.graalvm.compiler.lir.amd64; + +import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.COMPOSITE; +import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG; + +import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler; +import org.graalvm.compiler.core.common.LIRKind; +import org.graalvm.compiler.lir.LIRInstructionClass; +import org.graalvm.compiler.lir.Opcode; +import org.graalvm.compiler.lir.asm.CompilationResultBuilder; + +import jdk.vm.ci.amd64.AMD64; +import jdk.vm.ci.amd64.AMD64Kind; +import jdk.vm.ci.code.RegisterValue; +import jdk.vm.ci.meta.Value; + +/** + * Zeros a chunk of memory using rep stosb. + */ +@Opcode("ZERO_MEMORY") +public final class AMD64ZeroMemoryOp extends AMD64LIRInstruction { + + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AMD64ZeroMemoryOp.class); + + @Use({COMPOSITE}) protected AMD64AddressValue pointer; + @Use({REG}) protected RegisterValue length; + + @Temp protected Value pointerTemp; + @Temp protected Value valueTemp; + @Temp protected Value lengthTemp; + + public AMD64ZeroMemoryOp(AMD64AddressValue pointer, RegisterValue length) { + super(TYPE); + this.pointer = pointer; + this.length = length; + + this.pointerTemp = AMD64.rdi.asValue(LIRKind.value(AMD64Kind.QWORD)); + this.valueTemp = AMD64.rax.asValue(LIRKind.value(AMD64Kind.QWORD)); + this.lengthTemp = AMD64.rcx.asValue(LIRKind.value(AMD64Kind.QWORD)); + } + + @Override + public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { + assert AMD64.rcx.equals(length.getRegister()); + masm.leaq(AMD64.rdi, pointer.toAddress()); + masm.xorq(AMD64.rax, AMD64.rax); + masm.repStosb(); + } +} --- /dev/null 2017-11-16 08:17:56.803999947 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/ZeroMemoryNode.java 2019-05-04 02:43:41.236100767 +0200 @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +package org.graalvm.compiler.replacements.nodes; + +import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_8; +import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_8; + +import org.graalvm.compiler.core.common.type.StampFactory; +import org.graalvm.compiler.graph.NodeClass; +import org.graalvm.compiler.nodeinfo.InputType; +import org.graalvm.compiler.nodeinfo.NodeInfo; +import org.graalvm.compiler.nodes.ValueNode; +import org.graalvm.compiler.nodes.memory.FixedAccessNode; +import org.graalvm.compiler.nodes.memory.address.AddressNode; +import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode; +import org.graalvm.compiler.nodes.spi.LIRLowerable; +import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; +import org.graalvm.compiler.word.Word; +import jdk.internal.vm.compiler.word.LocationIdentity; + +/** + * Zeros a chunk of memory. + */ +@NodeInfo(nameTemplate = "ZeroMemory#{p#location/s}", allowedUsageTypes = {InputType.Memory}, cycles = CYCLES_8, size = SIZE_8) +public class ZeroMemoryNode extends FixedAccessNode implements LIRLowerable { + public static final NodeClass TYPE = NodeClass.create(ZeroMemoryNode.class); + + @Input ValueNode length; + + public ZeroMemoryNode(ValueNode address, ValueNode length, LocationIdentity locationIdentity) { + this(OffsetAddressNode.create(address), length, locationIdentity, BarrierType.NONE); + } + + public ZeroMemoryNode(AddressNode address, ValueNode length, LocationIdentity locationIdentity, BarrierType type) { + super(TYPE, address, locationIdentity, StampFactory.forVoid(), type); + this.length = length; + } + + @Override + public void generate(NodeLIRBuilderTool gen) { + gen.getLIRGeneratorTool().getArithmetic().emitZeroMemory(gen.operand(getAddress()), gen.operand(length)); + } + + @Override + public boolean canNullCheck() { + return false; + } + + @NodeIntrinsic + public static native void zero(Word address, long length, @ConstantNodeParameter LocationIdentity locationIdentity); +} --- /dev/null 2017-11-16 08:17:56.803999947 +0100 +++ new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.micro.benchmarks/src/micro/benchmarks/ArrayAllocationBenchmark.java 2019-05-04 02:43:41.764103860 +0200 @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +package micro.benchmarks; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Threads; +import org.openjdk.jmh.annotations.Warmup; + +/** + * Benchmarks cost of ArrayList. + */ +public class ArrayAllocationBenchmark extends BenchmarkBase { + + @State(Scope.Benchmark) + public static class ThreadState { + @Param({"128", "256", "512", "1024", "2048", "4096", "8192", "16384", "32768", "65536", "131072"}) int size; + byte[] result; + } + + @Benchmark + @Threads(8) + @Warmup(iterations = 10) + public void arrayAllocate(ThreadState state) { + state.result = new byte[state.size]; + } +}