Skip to content

Commit

Permalink
[GR-12682] Use bulk zeroing when instantiating large arrays.
Browse files Browse the repository at this point in the history
PullRequest: graal/3288
  • Loading branch information
mur47x111 committed Apr 18, 2019
2 parents 085fb0a + eaf9ef8 commit ec79632
Show file tree
Hide file tree
Showing 10 changed files with 320 additions and 36 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3003,6 +3003,18 @@ public final void cdqq() {
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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -1102,6 +1103,12 @@ public Value emitMathPow(Value x, Value y) {
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();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -279,9 +279,13 @@ public final class GraalOptions {
@Option(help = "Enable inlining decision tracing in stubs and snippets.", type = OptionType.Debug)
public static final OptionKey<Boolean> 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<Boolean> 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<Boolean> 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<Integer> MinimalBulkZeroingSize = new OptionKey<>(2048);

}
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -128,4 +128,9 @@ private void lowerUnaryMath(UnaryMathIntrinsicNode math, LoweringTool tool) {
public Integer smallestCompareWidth() {
return 8;
}

@Override
public boolean supportBulkZeroing() {
return true;
}
}

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*
* 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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<AMD64ZeroMemoryOp> TYPE = LIRInstructionClass.create(AMD64ZeroMemoryOp.class);

@Use({COMPOSITE}) protected AMD64AddressValue pointer;
@Use({REG}) protected RegisterValue length;

@Temp protected Value pointerTemp;
@Temp protected Value valueTemp;

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));
}

@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();
}
}
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -132,4 +132,8 @@ default Value emitMathPow(Value x, Value y) {
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");
}
}
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -54,4 +54,11 @@ default Integer smallestCompareWidth() {
// 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;
}
}
Original file line number Diff line number Diff line change
@@ -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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 org.graalvm.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<ZeroMemoryNode> 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);
}
Original file line number Diff line number Diff line change
@@ -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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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];
}
}

0 comments on commit ec79632

Please sign in to comment.