8223346: Update Graal

Reviewed-by: kvn
This commit is contained in:
Jesper Wilhelmsson 2019-05-17 00:21:10 +02:00
parent 1e4085b359
commit 993feb95ea
32 changed files with 1047 additions and 126 deletions
src/jdk.internal.vm.compiler/share/classes
org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64
org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64
org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test
org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/spi
org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64
org.graalvm.compiler.hotspot.jdk9.test/src/org/graalvm/compiler/hotspot/jdk9/test
org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test
org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot
org.graalvm.compiler.java/src/org/graalvm/compiler/java
org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64
org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen
org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes
org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64
org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test
org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements
org.graalvm.compiler.serviceprovider/src/org/graalvm/compiler/serviceprovider
org.graalvm.compiler.word/src/org/graalvm/compiler/word

@ -906,7 +906,8 @@ public class AMD64Assembler extends AMD64BaseAssembler {
CPU_XMM(CPUFeature.AVX, null, CPU, null, XMM, null),
AVX1_2_CPU_XMM(CPUFeature.AVX, CPUFeature.AVX2, CPU, null, XMM, null),
BMI1(CPUFeature.BMI1, null, CPU, CPU, CPU, null),
BMI2(CPUFeature.BMI2, null, CPU, CPU, CPU, null);
BMI2(CPUFeature.BMI2, null, CPU, CPU, CPU, null),
FMA(CPUFeature.FMA, null, XMM, XMM, XMM, null);
private final CPUFeature l128feature;
private final CPUFeature l256feature;
@ -1308,6 +1309,8 @@ public class AMD64Assembler extends AMD64BaseAssembler {
public static final VexRVMOp VPCMPGTW = new VexRVMOp("VPCMPGTW", P_66, M_0F, WIG, 0x65, VEXOpAssertion.AVX1_2);
public static final VexRVMOp VPCMPGTD = new VexRVMOp("VPCMPGTD", P_66, M_0F, WIG, 0x66, VEXOpAssertion.AVX1_2);
public static final VexRVMOp VPCMPGTQ = new VexRVMOp("VPCMPGTQ", P_66, M_0F38, WIG, 0x37, VEXOpAssertion.AVX1_2);
public static final VexRVMOp VFMADD231SS = new VexRVMOp("VFMADD231SS", P_66, M_0F38, W0, 0xB9, VEXOpAssertion.FMA);
public static final VexRVMOp VFMADD231SD = new VexRVMOp("VFMADD231SD", P_66, M_0F38, W1, 0xB9, VEXOpAssertion.FMA);
// @formatter:on
private VexRVMOp(String opcode, int pp, int mmmmm, int w, int op) {

@ -57,6 +57,8 @@ import static org.graalvm.compiler.asm.amd64.AMD64Assembler.VexRVMOp.VADDSD;
import static org.graalvm.compiler.asm.amd64.AMD64Assembler.VexRVMOp.VADDSS;
import static org.graalvm.compiler.asm.amd64.AMD64Assembler.VexRVMOp.VDIVSD;
import static org.graalvm.compiler.asm.amd64.AMD64Assembler.VexRVMOp.VDIVSS;
import static org.graalvm.compiler.asm.amd64.AMD64Assembler.VexRVMOp.VFMADD231SD;
import static org.graalvm.compiler.asm.amd64.AMD64Assembler.VexRVMOp.VFMADD231SS;
import static org.graalvm.compiler.asm.amd64.AMD64Assembler.VexRVMOp.VMULSD;
import static org.graalvm.compiler.asm.amd64.AMD64Assembler.VexRVMOp.VMULSS;
import static org.graalvm.compiler.asm.amd64.AMD64Assembler.VexRVMOp.VORPD;
@ -120,6 +122,7 @@ import org.graalvm.compiler.lir.amd64.AMD64Move;
import org.graalvm.compiler.lir.amd64.AMD64MulDivOp;
import org.graalvm.compiler.lir.amd64.AMD64ShiftOp;
import org.graalvm.compiler.lir.amd64.AMD64SignExtendOp;
import org.graalvm.compiler.lir.amd64.AMD64Ternary;
import org.graalvm.compiler.lir.amd64.AMD64Unary;
import org.graalvm.compiler.lir.amd64.AMD64ZeroMemoryOp;
import org.graalvm.compiler.lir.amd64.vector.AMD64VectorBinary;
@ -962,6 +965,22 @@ public class AMD64ArithmeticLIRGenerator extends ArithmeticLIRGenerator implemen
return result;
}
@Override
public Variable emitFusedMultiplyAdd(Value a, Value b, Value c) {
Variable result = getLIRGen().newVariable(LIRKind.combine(a, b, c));
assert ((AMD64Kind) a.getPlatformKind()).isXMM() && ((AMD64Kind) b.getPlatformKind()).isXMM() && ((AMD64Kind) c.getPlatformKind()).isXMM();
assert a.getPlatformKind().equals(b.getPlatformKind());
assert b.getPlatformKind().equals(c.getPlatformKind());
if (a.getPlatformKind() == AMD64Kind.DOUBLE) {
getLIRGen().append(new AMD64Ternary.ThreeOp(VFMADD231SD, AVXSize.XMM, result, asAllocatable(c), asAllocatable(a), asAllocatable(b)));
} else {
assert a.getPlatformKind() == AMD64Kind.SINGLE;
getLIRGen().append(new AMD64Ternary.ThreeOp(VFMADD231SS, AVXSize.XMM, result, asAllocatable(c), asAllocatable(a), asAllocatable(b)));
}
return result;
}
@Override
public Value emitCountLeadingZeros(Value value) {
Variable result = getLIRGen().newVariable(LIRKind.combine(value).changeType(AMD64Kind.DWORD));

@ -0,0 +1,86 @@
/*
* 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.core.test;
import org.junit.Test;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Label;
import jdk.vm.ci.meta.ResolvedJavaMethod;
public class TwoSlotMarkerClearingTest extends CustomizedBytecodePatternTest {
@Test
public void testTwoSlotMarkerClearing() throws ClassNotFoundException {
Class<?> testClass = getClass("Test");
ResolvedJavaMethod t1 = getResolvedJavaMethod(testClass, "t1");
parseForCompile(t1);
ResolvedJavaMethod t2 = getResolvedJavaMethod(testClass, "t2");
parseForCompile(t2);
}
@Override
protected byte[] generateClass(String className) {
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
cw.visit(52, ACC_SUPER | ACC_PUBLIC, className, null, "java/lang/Object", null);
String getDescriptor = "(" + "JII" + ")" + "I";
MethodVisitor t1 = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "t1", getDescriptor, null, null);
t1.visitCode();
t1.visitVarInsn(ILOAD, 2);
t1.visitVarInsn(ISTORE, 0);
t1.visitVarInsn(ILOAD, 0);
Label label = new Label();
t1.visitJumpInsn(IFGE, label);
t1.visitVarInsn(ILOAD, 0);
t1.visitInsn(IRETURN);
t1.visitLabel(label);
t1.visitVarInsn(ILOAD, 3);
t1.visitInsn(IRETURN);
t1.visitMaxs(4, 1);
t1.visitEnd();
getDescriptor = "(" + "IJIJ" + ")" + "J";
MethodVisitor t2 = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "t2", getDescriptor, null, null);
t2.visitCode();
t2.visitVarInsn(LLOAD, 1);
t2.visitVarInsn(LSTORE, 0);
t2.visitVarInsn(ILOAD, 3);
Label label1 = new Label();
t2.visitJumpInsn(IFGE, label1);
t2.visitVarInsn(LLOAD, 0);
t2.visitInsn(LRETURN);
t2.visitLabel(label1);
t2.visitVarInsn(LLOAD, 4);
t2.visitInsn(LRETURN);
t2.visitMaxs(6, 2);
t2.visitEnd();
cw.visitEnd();
return cw.toByteArray();
}
}

@ -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
@ -155,4 +155,49 @@ public interface Canonicalizable {
*/
Node maybeCommuteInputs();
}
/**
* This sub-interface of {@link Canonicalizable} is intended for nodes that have exactly three
* inputs. It has an additional {@link #canonical(CanonicalizerTool, Node, Node, Node)} method
* that looks at the given inputs instead of the current inputs of the node - which can be used
* to ask "what if this input is changed to this node" - questions.
*
* @param <T> the common supertype of all inputs of this node
*/
public interface Ternary<T extends Node> extends Canonicalizable {
/**
* Similar to {@link Canonicalizable#canonical(CanonicalizerTool)}, except that
* implementations should act as if the current input of the node was the given one, i.e.,
* they should never look at the inputs via the this pointer.
*/
Node canonical(CanonicalizerTool tool, T forX, T forY, T forZ);
/**
* Gets the current value of the input, so that calling
* {@link #canonical(CanonicalizerTool, Node, Node, Node)} with the value returned from this
* method should behave exactly like {@link Canonicalizable#canonical(CanonicalizerTool)}.
*/
T getX();
/**
* Gets the current value of the input, so that calling
* {@link #canonical(CanonicalizerTool, Node, Node, Node)} with the value returned from this
* method should behave exactly like {@link Canonicalizable#canonical(CanonicalizerTool)}.
*/
T getY();
/**
* Gets the current value of the input, so that calling
* {@link #canonical(CanonicalizerTool, Node, Node, Node)} with the value returned from this
* method should behave exactly like {@link Canonicalizable#canonical(CanonicalizerTool)}.
*/
T getZ();
@SuppressWarnings("unchecked")
@Override
default T canonical(CanonicalizerTool tool) {
return (T) canonical(tool, getX(), getY(), getZ());
}
}
}

@ -263,14 +263,19 @@ public class AMD64HotSpotBackend extends HotSpotHostBackend implements LIRGenera
if (config.useCompressedClassPointers) {
Register register = r10;
AMD64HotSpotMove.decodeKlassPointer(crb, asm, register, providers.getRegisters().getHeapBaseRegister(), src, config);
Register heapBase = providers.getRegisters().getHeapBaseRegister();
AMD64HotSpotMove.decodeKlassPointer(crb, asm, register, heapBase, src, config);
if (GeneratePIC.getValue(crb.getOptions())) {
asm.movq(providers.getRegisters().getHeapBaseRegister(), asm.getPlaceholder(-1));
asm.movq(heapBase, asm.getPlaceholder(-1));
crb.recordMark(config.MARKID_NARROW_OOP_BASE_ADDRESS);
} else {
if (config.narrowKlassBase != 0) {
// The heap base register was destroyed above, so restore it
asm.movq(providers.getRegisters().getHeapBaseRegister(), config.narrowOopBase);
if (config.narrowOopBase == 0L) {
asm.xorq(heapBase, heapBase);
} else {
asm.movq(heapBase, config.narrowOopBase);
}
}
}
asm.cmpq(inlineCacheKlass, register);

@ -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
@ -161,7 +161,7 @@ public class AMD64HotSpotBackendFactory implements HotSpotBackendFactory {
HotSpotConstantReflectionProvider constantReflection, HotSpotHostForeignCallsProvider foreignCalls, HotSpotMetaAccessProvider metaAccess,
HotSpotSnippetReflectionProvider snippetReflection, HotSpotReplacementsImpl replacements, HotSpotWordTypes wordTypes, OptionValues options) {
Plugins plugins = HotSpotGraphBuilderPlugins.create(compilerConfiguration, config, wordTypes, metaAccess, constantReflection, snippetReflection, foreignCalls, replacements, options);
AMD64GraphBuilderPlugins.register(plugins, replacements.getDefaultReplacementBytecodeProvider(), (AMD64) target.arch, false, JAVA_SPECIFICATION_VERSION >= 9);
AMD64GraphBuilderPlugins.register(plugins, replacements.getDefaultReplacementBytecodeProvider(), (AMD64) target.arch, false, JAVA_SPECIFICATION_VERSION >= 9, config.useFMAIntrinsics);
return plugins;
}

@ -0,0 +1,82 @@
/*
* 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.hotspot.jdk9.test;
import static org.junit.Assume.assumeTrue;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.graalvm.compiler.core.test.GraalCompilerTest;
import org.graalvm.compiler.test.AddExports;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameter;
import org.junit.runners.Parameterized.Parameters;
import jdk.vm.ci.amd64.AMD64;
@AddExports({"java.base/java.lang"})
@RunWith(Parameterized.class)
public final class MathDoubleFMATest extends GraalCompilerTest {
@Before
public void checkAMD64() {
assumeTrue("skipping AMD64 specific test", getTarget().arch instanceof AMD64);
}
@Parameters(name = "{0}, {1}, {2}")
public static Collection<Object[]> data() {
double[] inputs = {0.0d, 1.0d, 4.0d, -0.0d, -1.0d, -4.0d, Double.MIN_VALUE, Double.MAX_VALUE, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY,
Double.NaN, Double.longBitsToDouble(0xfff0000000000001L)};
List<Object[]> tests = new ArrayList<>();
for (double a : inputs) {
for (double b : inputs) {
for (double c : inputs) {
tests.add(new Object[]{a, b, c});
}
}
}
return tests;
}
@Parameter(value = 0) public double input0;
@Parameter(value = 1) public double input1;
@Parameter(value = 2) public double input2;
public static double fma(double a, double b, double c) {
return Math.fma(a, b, c);
}
@Test
public void testFMA() {
test("fma", input0, input1, input2);
}
}

@ -0,0 +1,62 @@
/*
* 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.hotspot.jdk9.test;
import static org.junit.Assume.assumeTrue;
import org.graalvm.compiler.core.test.GraalCompilerTest;
import org.graalvm.compiler.test.AddExports;
import org.junit.Before;
import org.junit.Test;
import jdk.vm.ci.amd64.AMD64;
@AddExports({"java.base/java.lang"})
public final class MathFMAConstantInputTest extends GraalCompilerTest {
@Before
public void checkAMD64() {
assumeTrue("skipping AMD64 specific test", getTarget().arch instanceof AMD64);
}
public static float floatFMA() {
return Math.fma(2.0f, 2.0f, 2.0f);
}
@Test
public void testFloatFMA() {
test("floatFMA");
}
public static double doubleFMA() {
return Math.fma(2.0d, 2.0d, 2.0d);
}
@Test
public void testDoubleFMA() {
test("doubleFMA");
}
}

@ -0,0 +1,82 @@
/*
* 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.hotspot.jdk9.test;
import static org.junit.Assume.assumeTrue;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.graalvm.compiler.core.test.GraalCompilerTest;
import org.graalvm.compiler.test.AddExports;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameter;
import org.junit.runners.Parameterized.Parameters;
import jdk.vm.ci.amd64.AMD64;
@AddExports({"java.base/java.lang"})
@RunWith(Parameterized.class)
public final class MathFloatFMATest extends GraalCompilerTest {
@Before
public void checkAMD64() {
assumeTrue("skipping AMD64 specific test", getTarget().arch instanceof AMD64);
}
@Parameters(name = "{0}, {1}, {2}")
public static Collection<Object[]> data() {
float[] inputs = {0.0f, 1.0f, 4.0f, -0.0f, -1.0f, 4.0f, Float.MIN_VALUE, Float.MAX_VALUE, Float.NEGATIVE_INFINITY, Float.POSITIVE_INFINITY,
Float.NaN, Float.intBitsToFloat(0xff800001)};
List<Object[]> tests = new ArrayList<>();
for (float a : inputs) {
for (float b : inputs) {
for (float c : inputs) {
tests.add(new Object[]{a, b, c});
}
}
}
return tests;
}
@Parameter(value = 0) public float input0;
@Parameter(value = 1) public float input1;
@Parameter(value = 2) public float input2;
public static float fma(float a, float b, float c) {
return Math.fma(a, b, c);
}
@Test
public void testFMA() {
test("fma", input0, input1, input2);
}
}

@ -272,10 +272,6 @@ public class CheckGraalIntrinsics extends GraalTest {
"jdk/jfr/internal/JVM.getClassId(Ljava/lang/Class;)J");
add(toBeInvestigated,
// HotSpot MacroAssembler-based intrinsic
"java/lang/Math.fma(DDD)D",
// HotSpot MacroAssembler-based intrinsic
"java/lang/Math.fma(FFF)F",
// Just check if the argument is a compile time constant
"java/lang/invoke/MethodHandleImpl.isCompileConstant(Ljava/lang/Object;)Z",
// Only used as a marker for vectorization?
@ -371,6 +367,15 @@ public class CheckGraalIntrinsics extends GraalTest {
add(ignore,
"sun/security/provider/DigestBase.implCompressMultiBlock0([BII)I");
}
if (!config.useFMAIntrinsics) {
add(ignore,
"java/lang/Math.fma(DDD)D",
"java/lang/Math.fma(FFF)F");
} else if (!(arch instanceof AMD64)) {
add(toBeInvestigated,
"java/lang/Math.fma(DDD)D",
"java/lang/Math.fma(FFF)F");
}
}
if (isJDK10OrHigher()) {

@ -55,6 +55,8 @@ import org.graalvm.compiler.phases.common.inlining.policy.InlineEverythingPolicy
import org.graalvm.compiler.phases.tiers.HighTierContext;
import org.graalvm.compiler.phases.tiers.MidTierContext;
import org.graalvm.compiler.replacements.NodeIntrinsificationProvider;
import org.graalvm.compiler.word.Word;
import jdk.internal.vm.compiler.word.WordFactory;
import org.junit.Assert;
import org.junit.Test;
@ -255,6 +257,34 @@ public class WriteBarrierAdditionTest extends HotSpotGraalCompilerTest {
test2("testArrayCopy", src, dst, dst.length);
}
public static class WordContainer {
public Word word;
}
public static void testWordFieldSnippet() {
WordContainer wordContainer = new WordContainer();
wordContainer.word = WordFactory.signed(42);
}
@Test
public void testWordField() throws Exception {
testHelper("testWordFieldSnippet", 0);
}
public static Word[] testWordArraySnippet(int length) {
Word fortyTwo = WordFactory.signed(42);
Word[] words = new Word[length];
for (int i = 0; i < length; i++) {
words[i] = fortyTwo;
}
return words;
}
@Test
public void testWordArray() throws Exception {
testHelper("testWordArraySnippet", 0);
}
public static Object testUnsafeLoad(Unsafe theUnsafe, Object a, Object b, Object c) throws Exception {
final int offset = (c == null ? 0 : ((Integer) c).intValue());
final long displacement = (b == null ? 0 : ((Long) b).longValue());
@ -315,9 +345,10 @@ public class WriteBarrierAdditionTest extends HotSpotGraalCompilerTest {
JavaConstant constDisp = ((OffsetAddressNode) read.getAddress()).getOffset().asJavaConstant();
Assert.assertNotNull(constDisp);
Assert.assertEquals(referentOffset(getMetaAccess()), constDisp.asLong());
Assert.assertTrue(config.useG1GC);
Assert.assertEquals(BarrierType.PRECISE, read.getBarrierType());
Assert.assertTrue(read.next() instanceof G1ReferentFieldReadBarrier);
Assert.assertEquals(BarrierType.WEAK_FIELD, read.getBarrierType());
if (config.useG1GC) {
Assert.assertTrue(read.next() instanceof G1ReferentFieldReadBarrier);
}
}
}
} catch (Throwable e) {

@ -56,6 +56,7 @@ import jdk.vm.ci.hotspot.HotSpotInstalledCode;
import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime;
import jdk.vm.ci.hotspot.HotSpotNmethod;
import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
import jdk.vm.ci.meta.ResolvedJavaMethod;
import jdk.vm.ci.runtime.JVMCICompiler;
public class CompilationTask {
@ -169,7 +170,13 @@ public class CompilationTask {
}
stats.finish(method, installedCode);
if (result != null) {
return HotSpotCompilationRequestResult.success(result.getBytecodeSize() - method.getCodeSize());
// For compilation of substitutions the method in the compilation request might be
// different than the actual method parsed. The root of the compilation will always
// be the first method in the methods list, so use that instead.
ResolvedJavaMethod rootMethod = result.getMethods()[0];
int inlinedBytecodes = result.getBytecodeSize() - rootMethod.getCodeSize();
assert inlinedBytecodes >= 0 : rootMethod + " " + method;
return HotSpotCompilationRequestResult.success(inlinedBytecodes);
}
return null;
}

@ -108,6 +108,7 @@ public class GraalHotSpotVMConfig extends GraalHotSpotVMConfigBase {
private final boolean useMulAddIntrinsic = getFlag("UseMulAddIntrinsic", Boolean.class, false);
private final boolean useSquareToLenIntrinsic = getFlag("UseSquareToLenIntrinsic", Boolean.class, false);
public final boolean useVectorizedMismatchIntrinsic = getFlag("UseVectorizedMismatchIntrinsic", Boolean.class, false);
public final boolean useFMAIntrinsics = getFlag("UseFMA", Boolean.class, false);
/*
* These are methods because in some JDKs the flags are visible but the stubs themselves haven't

@ -26,6 +26,7 @@
package org.graalvm.compiler.hotspot.gc.g1;
import org.graalvm.compiler.debug.GraalError;
import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
import org.graalvm.compiler.hotspot.gc.shared.BarrierSet;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.ValueNode;
@ -41,10 +42,13 @@ import org.graalvm.compiler.nodes.type.StampTool;
public class G1BarrierSet extends BarrierSet {
public G1BarrierSet(GraalHotSpotVMConfig vmConfig) {
super(vmConfig);
}
@Override
public void addReadNodeBarriers(ReadNode node, StructuredGraph graph) {
if (node.getBarrierType() != HeapAccess.BarrierType.NONE) {
assert (node.getBarrierType() == HeapAccess.BarrierType.PRECISE);
if (node.getBarrierType() == HeapAccess.BarrierType.WEAK_FIELD) {
G1ReferentFieldReadBarrier barrier = graph.add(new G1ReferentFieldReadBarrier(node.getAddress(), node, false));
graph.addAfterFixed(node, barrier);
}
@ -57,15 +61,19 @@ public class G1BarrierSet extends BarrierSet {
case NONE:
// nothing to do
break;
case IMPRECISE:
case PRECISE:
boolean precise = barrierType == HeapAccess.BarrierType.PRECISE;
if (!node.getLocationIdentity().isInit()) {
// The pre barrier does nothing if the value being read is null, so it can
// be explicitly skipped when this is an initializing store.
addG1PreWriteBarrier(node, node.getAddress(), null, true, node.getNullCheck(), graph);
case FIELD:
case ARRAY:
case UNKNOWN:
boolean init = node.getLocationIdentity().isInit();
if (!init || !getVMConfig().useDeferredInitBarriers) {
if (!init) {
// The pre barrier does nothing if the value being read is null, so it can
// be explicitly skipped when this is an initializing store.
addG1PreWriteBarrier(node, node.getAddress(), null, true, node.getNullCheck(), graph);
}
boolean precise = barrierType != HeapAccess.BarrierType.FIELD;
addG1PostWriteBarrier(node, node.getAddress(), node.value(), precise, graph);
}
addG1PostWriteBarrier(node, node.getAddress(), node.value(), precise, graph);
break;
default:
throw new GraalError("unexpected barrier type: " + barrierType);
@ -79,9 +87,10 @@ public class G1BarrierSet extends BarrierSet {
case NONE:
// nothing to do
break;
case IMPRECISE:
case PRECISE:
boolean precise = barrierType == HeapAccess.BarrierType.PRECISE;
case FIELD:
case ARRAY:
case UNKNOWN:
boolean precise = barrierType != HeapAccess.BarrierType.FIELD;
addG1PreWriteBarrier(node, node.getAddress(), null, true, node.getNullCheck(), graph);
addG1PostWriteBarrier(node, node.getAddress(), node.getNewValue(), precise, graph);
break;
@ -97,9 +106,10 @@ public class G1BarrierSet extends BarrierSet {
case NONE:
// nothing to do
break;
case IMPRECISE:
case PRECISE:
boolean precise = barrierType == HeapAccess.BarrierType.PRECISE;
case FIELD:
case ARRAY:
case UNKNOWN:
boolean precise = barrierType != HeapAccess.BarrierType.FIELD;
addG1PreWriteBarrier(node, node.getAddress(), node.getExpectedValue(), false, false, graph);
addG1PostWriteBarrier(node, node.getAddress(), node.getNewValue(), precise, graph);
break;

@ -25,6 +25,7 @@
package org.graalvm.compiler.hotspot.gc.shared;
import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.extended.ArrayRangeWrite;
import org.graalvm.compiler.nodes.java.AbstractCompareAndSwapNode;
@ -33,6 +34,16 @@ import org.graalvm.compiler.nodes.memory.ReadNode;
import org.graalvm.compiler.nodes.memory.WriteNode;
public abstract class BarrierSet {
private final GraalHotSpotVMConfig vmConfig;
protected BarrierSet(GraalHotSpotVMConfig vmConfig) {
this.vmConfig = vmConfig;
}
public final GraalHotSpotVMConfig getVMConfig() {
return vmConfig;
}
public abstract void addReadNodeBarriers(ReadNode node, StructuredGraph graph);
public abstract void addWriteNodeBarriers(WriteNode node, StructuredGraph graph);

@ -26,6 +26,7 @@
package org.graalvm.compiler.hotspot.gc.shared;
import org.graalvm.compiler.debug.GraalError;
import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.ValueNode;
import org.graalvm.compiler.nodes.extended.ArrayRangeWrite;
@ -40,9 +41,13 @@ import org.graalvm.compiler.nodes.type.StampTool;
public class CardTableBarrierSet extends BarrierSet {
public CardTableBarrierSet(GraalHotSpotVMConfig vmConfig) {
super(vmConfig);
}
@Override
public void addReadNodeBarriers(ReadNode node, StructuredGraph graph) {
assert node.getBarrierType() == HeapAccess.BarrierType.NONE : "Non precise read barrier has been attached to read node.";
// Nothing to do here.
}
@Override
@ -52,10 +57,14 @@ public class CardTableBarrierSet extends BarrierSet {
case NONE:
// nothing to do
break;
case IMPRECISE:
case PRECISE:
boolean precise = barrierType == HeapAccess.BarrierType.PRECISE;
addSerialPostWriteBarrier(node, node.getAddress(), node.value(), precise, graph);
case FIELD:
case ARRAY:
case UNKNOWN:
boolean precise = barrierType != HeapAccess.BarrierType.FIELD;
boolean init = node.getLocationIdentity().isInit();
if (!init || !getVMConfig().useDeferredInitBarriers) {
addSerialPostWriteBarrier(node, node.getAddress(), node.value(), precise, graph);
}
break;
default:
throw new GraalError("unexpected barrier type: " + barrierType);
@ -69,9 +78,10 @@ public class CardTableBarrierSet extends BarrierSet {
case NONE:
// nothing to do
break;
case IMPRECISE:
case PRECISE:
boolean precise = barrierType == HeapAccess.BarrierType.PRECISE;
case FIELD:
case ARRAY:
case UNKNOWN:
boolean precise = barrierType != HeapAccess.BarrierType.FIELD;
addSerialPostWriteBarrier(node, node.getAddress(), node.getNewValue(), precise, graph);
break;
default:
@ -86,9 +96,10 @@ public class CardTableBarrierSet extends BarrierSet {
case NONE:
// nothing to do
break;
case IMPRECISE:
case PRECISE:
boolean precise = barrierType == HeapAccess.BarrierType.PRECISE;
case FIELD:
case ARRAY:
case UNKNOWN:
boolean precise = barrierType != HeapAccess.BarrierType.FIELD;
addSerialPostWriteBarrier(node, node.getAddress(), node.getNewValue(), precise, graph);
break;
default:

@ -583,16 +583,6 @@ public class DefaultHotSpotLoweringProvider extends DefaultJavaLoweringProvider
graph.replaceFixed(storeHub, hub);
}
@Override
public BarrierType fieldInitializationBarrier(JavaKind entryKind) {
return (entryKind == JavaKind.Object && !runtime.getVMConfig().useDeferredInitBarriers) ? BarrierType.IMPRECISE : BarrierType.NONE;
}
@Override
public BarrierType arrayInitializationBarrier(JavaKind entryKind) {
return (entryKind == JavaKind.Object && !runtime.getVMConfig().useDeferredInitBarriers) ? BarrierType.PRECISE : BarrierType.NONE;
}
private void lowerOSRStartNode(OSRStartNode osrStart) {
StructuredGraph graph = osrStart.graph();
if (graph.getGuardsStage() == StructuredGraph.GuardsStage.FIXED_DEOPTS) {
@ -783,12 +773,11 @@ public class DefaultHotSpotLoweringProvider extends DefaultJavaLoweringProvider
@Override
protected BarrierType fieldLoadBarrierType(ResolvedJavaField f) {
HotSpotResolvedJavaField loadField = (HotSpotResolvedJavaField) f;
BarrierType barrierType = BarrierType.NONE;
if (runtime.getVMConfig().useG1GC && loadField.getJavaKind() == JavaKind.Object && metaAccess.lookupJavaType(Reference.class).equals(loadField.getDeclaringClass()) &&
if (loadField.getJavaKind() == JavaKind.Object && metaAccess.lookupJavaType(Reference.class).equals(loadField.getDeclaringClass()) &&
loadField.getName().equals("referent")) {
barrierType = BarrierType.PRECISE;
return BarrierType.WEAK_FIELD;
}
return barrierType;
return super.fieldLoadBarrierType(f);
}
@Override

@ -39,6 +39,7 @@ import org.graalvm.compiler.code.CompilationResult;
import org.graalvm.compiler.code.CompilationResult.CodeAnnotation;
import org.graalvm.compiler.code.DisassemblerProvider;
import org.graalvm.compiler.serviceprovider.ServiceProvider;
import org.graalvm.util.CollectionsUtil;
import jdk.vm.ci.code.CodeCacheProvider;
import jdk.vm.ci.code.CodeUtil;
@ -56,28 +57,31 @@ import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider;
import jdk.vm.ci.services.Services;
/**
* This disassembles the code immediatly with objdump.
* A provider that uses the {@code GNU objdump} utility to disassemble code.
*/
@ServiceProvider(DisassemblerProvider.class)
public class HotSpotObjdumpDisassemblerProvider extends HotSpotDisassemblerProvider {
/**
* Uses objdump to disassemble the compiled code.
*/
private final String objdump = getObjdump();
@Override
public String disassembleCompiledCode(CodeCacheProvider codeCache, CompilationResult compResult) {
if (objdump == null) {
return null;
}
File tmp = null;
try {
tmp = File.createTempFile("compiledBinary", ".bin");
try (FileOutputStream fos = new FileOutputStream(tmp)) {
fos.write(compResult.getTargetCode());
}
String[] cmdline;
String arch = Services.getSavedProperties().get("os.arch");
if (arch.equals("amd64")) {
cmdline = new String[]{"objdump", "-D", "-b", "binary", "-M", "x86-64", "-m", "i386", tmp.getAbsolutePath()};
if (arch.equals("amd64") || arch.equals("x86_64")) {
cmdline = new String[]{objdump, "-D", "-b", "binary", "-M", "x86-64", "-m", "i386", tmp.getAbsolutePath()};
} else if (arch.equals("aarch64")) {
cmdline = new String[]{"objdump", "-D", "-b", "binary", "-m", "aarch64", tmp.getAbsolutePath()};
cmdline = new String[]{objdump, "-D", "-b", "binary", "-m", "aarch64", tmp.getAbsolutePath()};
} else {
return null;
}
@ -116,43 +120,99 @@ public class HotSpotObjdumpDisassemblerProvider extends HotSpotDisassemblerProvi
Process proc = Runtime.getRuntime().exec(cmdline);
InputStream is = proc.getInputStream();
StringBuilder sb = new StringBuilder();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line;
StringBuilder sb = new StringBuilder();
while ((line = br.readLine()) != null) {
Matcher m = p.matcher(line);
if (m.find()) {
int address = Integer.parseInt(m.group(2), 16);
String annotation = annotations.get(address);
if (annotation != null) {
annotation = annotation.replace("\n", "\n; ");
sb.append("; ").append(annotation).append('\n');
try (BufferedReader br = new BufferedReader(isr)) {
String line;
while ((line = br.readLine()) != null) {
Matcher m = p.matcher(line);
if (m.find()) {
int address = Integer.parseInt(m.group(2), 16);
String annotation = annotations.get(address);
if (annotation != null) {
annotation = annotation.replace("\n", "\n; ");
sb.append("; ").append(annotation).append('\n');
}
line = m.replaceAll("0x$1");
}
line = m.replaceAll("0x$1");
sb.append(line).append("\n");
}
sb.append(line).append("\n");
}
BufferedReader ebr = new BufferedReader(new InputStreamReader(proc.getErrorStream()));
while ((line = ebr.readLine()) != null) {
System.err.println(line);
try (BufferedReader ebr = new BufferedReader(new InputStreamReader(proc.getErrorStream()))) {
String errLine = ebr.readLine();
if (errLine != null) {
System.err.println("Error output from executing: " + CollectionsUtil.mapAndJoin(cmdline, e -> quoteShellArg(String.valueOf(e)), " "));
System.err.println(errLine);
while ((errLine = ebr.readLine()) != null) {
System.err.println(errLine);
}
}
}
ebr.close();
return sb.toString();
} catch (IOException e) {
e.printStackTrace();
return null;
} finally {
if (tmp != null) {
tmp.delete();
}
e.printStackTrace();
return null;
}
}
/**
* Pattern for a single shell command argument that does not need to quoted.
*/
private static final Pattern SAFE_SHELL_ARG = Pattern.compile("[A-Za-z0-9@%_\\-\\+=:,\\./]+");
/**
* Reliably quote a string as a single shell command argument.
*/
public static String quoteShellArg(String arg) {
if (arg.isEmpty()) {
return "\"\"";
}
Matcher m = SAFE_SHELL_ARG.matcher(arg);
if (m.matches()) {
return arg;
}
// See http://stackoverflow.com/a/1250279
return "'" + arg.replace("'", "'\"'\"'") + "'";
}
/**
* Searches for a valid GNU objdump executable.
*/
private static String getObjdump() {
// On macOS, `brew install binutils` will provide
// an executable named gobjdump
for (String candidate : new String[]{"objdump", "gobjdump"}) {
try {
String[] cmd = {candidate, "--version"};
Process proc = Runtime.getRuntime().exec(cmd);
InputStream is = proc.getInputStream();
int exitValue = proc.waitFor();
if (exitValue == 0) {
byte[] buf = new byte[is.available()];
int pos = 0;
while (pos < buf.length) {
int read = is.read(buf, pos, buf.length - pos);
pos += read;
}
String output = new String(buf);
if (output.contains("GNU objdump")) {
return candidate;
}
}
} catch (IOException | InterruptedException e) {
}
}
return null;
}
private static void putAnnotation(Map<Integer, String> annotations, int idx, String txt) {
String newAnnoation = annotations.getOrDefault(idx, "") + "\n" + txt;
annotations.put(idx, newAnnoation);
String newAnnotation = annotations.getOrDefault(idx, "") + "\n" + txt;
annotations.put(idx, newAnnotation);
}
@Override

@ -77,17 +77,17 @@ public class WriteBarrierAdditionPhase extends Phase {
private BarrierSet createBarrierSet(GraalHotSpotVMConfig config) {
if (config.useG1GC) {
return createG1BarrierSet();
return createG1BarrierSet(config);
} else {
return createCardTableBarrierSet();
return createCardTableBarrierSet(config);
}
}
protected BarrierSet createCardTableBarrierSet() {
return new CardTableBarrierSet();
protected BarrierSet createCardTableBarrierSet(GraalHotSpotVMConfig config) {
return new CardTableBarrierSet(config);
}
protected BarrierSet createG1BarrierSet() {
return new G1BarrierSet();
protected BarrierSet createG1BarrierSet(GraalHotSpotVMConfig config) {
return new G1BarrierSet(config);
}
}

@ -44,6 +44,7 @@ import org.graalvm.compiler.nodes.ValueNode;
import org.graalvm.compiler.nodes.extended.ArrayRangeWrite;
import org.graalvm.compiler.nodes.java.LoweredAtomicReadAndWriteNode;
import org.graalvm.compiler.nodes.java.LogicCompareAndSwapNode;
import org.graalvm.compiler.nodes.java.ValueCompareAndSwapNode;
import org.graalvm.compiler.nodes.memory.FixedAccessNode;
import org.graalvm.compiler.nodes.memory.HeapAccess;
import org.graalvm.compiler.nodes.memory.HeapAccess.BarrierType;
@ -127,6 +128,9 @@ public class WriteBarrierVerificationPhase extends Phase {
boolean validatePreBarrier = useG1GC() && (isObjectWrite(node) || !((ArrayRangeWrite) node).isInitialization());
if (node instanceof WriteNode) {
WriteNode writeNode = (WriteNode) node;
if (config.useDeferredInitBarriers && writeNode.getLocationIdentity().isInit()) {
return true;
}
if (writeNode.getLocationIdentity().isInit()) {
validatePreBarrier = false;
}
@ -191,7 +195,8 @@ public class WriteBarrierVerificationPhase extends Phase {
}
private static boolean validateBarrier(FixedAccessNode write, ObjectWriteBarrier barrier) {
assert write instanceof WriteNode || write instanceof LogicCompareAndSwapNode || write instanceof LoweredAtomicReadAndWriteNode : "Node must be of type requiring a write barrier " + write;
assert write instanceof WriteNode || write instanceof LogicCompareAndSwapNode || write instanceof ValueCompareAndSwapNode ||
write instanceof LoweredAtomicReadAndWriteNode : "Node must be of type requiring a write barrier " + write;
if (!barrier.usePrecise()) {
if (barrier.getAddress() instanceof OffsetAddressNode && write.getAddress() instanceof OffsetAddressNode) {
return GraphUtil.unproxify(((OffsetAddressNode) barrier.getAddress()).getBase()) == GraphUtil.unproxify(((OffsetAddressNode) write.getAddress()).getBase());

@ -50,7 +50,7 @@ public class UnsafeLoadSnippets implements Snippets {
public static Object lowerUnsafeLoad(Object object, long offset) {
Object fixedObject = FixedValueAnchorNode.getObject(object);
if (object instanceof java.lang.ref.Reference && referentOffset(INJECTED_METAACCESS) == offset) {
return Word.objectToTrackedPointer(fixedObject).readObject((int) offset, BarrierType.PRECISE);
return Word.objectToTrackedPointer(fixedObject).readObject((int) offset, BarrierType.WEAK_FIELD);
} else {
return Word.objectToTrackedPointer(fixedObject).readObject((int) offset, BarrierType.NONE);
}

@ -743,6 +743,13 @@ public final class FrameStateBuilder implements SideEffectsState {
}
locals[i] = x;
if (slotKind.needsTwoSlots()) {
if (i < locals.length - 2 && locals[i + 2] == TWO_SLOT_MARKER) {
/*
* Writing a two-slot marker to an index previously occupied by a two-slot value:
* clear the old marker of the second slot.
*/
locals[i + 2] = null;
}
/* Writing a two-slot value: mark the second slot. */
locals[i + 1] = TWO_SLOT_MARKER;
} else if (i < locals.length - 1 && locals[i + 1] == TWO_SLOT_MARKER) {

@ -0,0 +1,89 @@
/*
* 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 jdk.vm.ci.code.ValueUtil.asRegister;
import static jdk.vm.ci.code.ValueUtil.isRegister;
import static jdk.vm.ci.code.ValueUtil.isStackSlot;
import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.HINT;
import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG;
import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.STACK;
import org.graalvm.compiler.asm.amd64.AMD64Address;
import org.graalvm.compiler.asm.amd64.AMD64Assembler.VexRVMOp;
import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler;
import org.graalvm.compiler.asm.amd64.AVXKind.AVXSize;
import org.graalvm.compiler.lir.LIRInstructionClass;
import org.graalvm.compiler.lir.Opcode;
import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
import jdk.vm.ci.meta.AllocatableValue;
/**
* AMD64 LIR instructions that have three inputs and one output.
*/
public class AMD64Ternary {
/**
* Instruction that has two {@link AllocatableValue} operands.
*/
public static class ThreeOp extends AMD64LIRInstruction {
public static final LIRInstructionClass<ThreeOp> TYPE = LIRInstructionClass.create(ThreeOp.class);
@Opcode private final VexRVMOp opcode;
private final AVXSize size;
@Def({REG, HINT}) protected AllocatableValue result;
@Use({REG}) protected AllocatableValue x;
/**
* This argument must be Alive to ensure that result and y are not assigned to the same
* register, which would break the code generation by destroying y too early.
*/
@Alive({REG}) protected AllocatableValue y;
@Alive({REG, STACK}) protected AllocatableValue z;
public ThreeOp(VexRVMOp opcode, AVXSize size, AllocatableValue result, AllocatableValue x, AllocatableValue y, AllocatableValue z) {
super(TYPE);
this.opcode = opcode;
this.size = size;
this.result = result;
this.x = x;
this.y = y;
this.z = z;
}
@Override
public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
AMD64Move.move(crb, masm, result, x);
if (isRegister(z)) {
opcode.emit(masm, size, asRegister(result), asRegister(y), asRegister(z));
} else {
assert isStackSlot(z);
opcode.emit(masm, size, asRegister(result), asRegister(y), (AMD64Address) crb.asAddress(z));
}
}
}
}

@ -102,6 +102,11 @@ public interface ArithmeticLIRGeneratorTool {
void emitStore(ValueKind<?> kind, Value address, Value input, LIRFrameState state);
@SuppressWarnings("unused")
default Value emitFusedMultiplyAdd(Value a, Value b, Value c) {
throw GraalError.unimplemented("No specialized implementation available");
}
@SuppressWarnings("unused")
default Value emitMathLog(Value input, boolean base10) {
throw GraalError.unimplemented("No specialized implementation available");

@ -0,0 +1,106 @@
/*
* 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.nodes.calc;
import org.graalvm.compiler.core.common.type.Stamp;
import org.graalvm.compiler.graph.NodeClass;
import org.graalvm.compiler.graph.spi.Canonicalizable;
import org.graalvm.compiler.nodeinfo.NodeInfo;
import org.graalvm.compiler.nodes.NodeView;
import org.graalvm.compiler.nodes.ValueNode;
/**
* The {@code TernaryNode} class is the base of arithmetic and logic operations with three inputs.
*/
@NodeInfo
public abstract class TernaryNode extends FloatingNode implements Canonicalizable.Ternary<ValueNode> {
public static final NodeClass<TernaryNode> TYPE = NodeClass.create(TernaryNode.class);
@Input protected ValueNode x;
@Input protected ValueNode y;
@Input protected ValueNode z;
@Override
public ValueNode getX() {
return x;
}
@Override
public ValueNode getY() {
return y;
}
@Override
public ValueNode getZ() {
return z;
}
public void setX(ValueNode x) {
updateUsages(this.x, x);
this.x = x;
}
public void setY(ValueNode y) {
updateUsages(this.y, y);
this.y = y;
}
public void setZ(ValueNode z) {
updateUsages(this.z, z);
this.z = z;
}
/**
* Creates a new TernaryNode instance.
*
* @param stamp the result type of this instruction
* @param x the first input instruction
* @param y the second input instruction
* @param z the second input instruction
*/
protected TernaryNode(NodeClass<? extends TernaryNode> c, Stamp stamp, ValueNode x, ValueNode y, ValueNode z) {
super(c, stamp);
this.x = x;
this.y = y;
this.z = z;
}
@Override
public boolean inferStamp() {
return updateStamp(foldStamp(getX().stamp(NodeView.DEFAULT), getY().stamp(NodeView.DEFAULT), getZ().stamp(NodeView.DEFAULT)));
}
/**
* Compute an improved stamp for this node using the passed in stamps. The stamps must be
* compatible with the current values of {@link #x}, {@link #y} and {@link #z}. This code is
* used to provide the default implementation of {@link #inferStamp()} and may be used by
* external optimizations.
*
* @param stampX
* @param stampY
* @param stampZ
*/
public abstract Stamp foldStamp(Stamp stampX, Stamp stampY, Stamp stampZ);
}

@ -34,17 +34,25 @@ public interface HeapAccess {
*/
enum BarrierType {
/**
* Primitive stores which do not necessitate barriers.
* Primitive access which do not necessitate barriers.
*/
NONE,
/**
* Array object stores which necessitate precise barriers.
* Array object access.
*/
PRECISE,
ARRAY,
/**
* Field object stores which necessitate imprecise barriers.
* Field object access.
*/
IMPRECISE
FIELD,
/**
* Unknown (aka field or array) object access.
*/
UNKNOWN,
/**
* Weak field access (e.g. Hotspot's Reference.referent field).
*/
WEAK_FIELD
}
/**

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 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
@ -59,6 +59,7 @@ import org.graalvm.compiler.replacements.StandardGraphBuilderPlugins.UnsafePutPl
import org.graalvm.compiler.replacements.nodes.BinaryMathIntrinsicNode;
import org.graalvm.compiler.replacements.nodes.BinaryMathIntrinsicNode.BinaryOperation;
import org.graalvm.compiler.replacements.nodes.BitCountNode;
import org.graalvm.compiler.replacements.nodes.FusedMultiplyAddNode;
import org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode;
import org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation;
@ -70,7 +71,8 @@ import sun.misc.Unsafe;
public class AMD64GraphBuilderPlugins {
public static void register(Plugins plugins, BytecodeProvider replacementsBytecodeProvider, AMD64 arch, boolean explicitUnsafeNullChecks, boolean emitJDK9StringSubstitutions) {
public static void register(Plugins plugins, BytecodeProvider replacementsBytecodeProvider, AMD64 arch, boolean explicitUnsafeNullChecks, boolean emitJDK9StringSubstitutions,
boolean useFMAIntrinsics) {
InvocationPlugins invocationPlugins = plugins.getInvocationPlugins();
invocationPlugins.defer(new Runnable() {
@Override
@ -86,7 +88,7 @@ public class AMD64GraphBuilderPlugins {
registerStringLatin1Plugins(invocationPlugins, replacementsBytecodeProvider);
registerStringUTF16Plugins(invocationPlugins, replacementsBytecodeProvider);
}
registerMathPlugins(invocationPlugins, arch, replacementsBytecodeProvider);
registerMathPlugins(invocationPlugins, useFMAIntrinsics, arch, replacementsBytecodeProvider);
registerArraysEqualsPlugins(invocationPlugins, replacementsBytecodeProvider);
}
});
@ -112,7 +114,9 @@ public class AMD64GraphBuilderPlugins {
Class<?> declaringClass = kind.toBoxedJavaClass();
Class<?> type = kind.toJavaClass();
Registration r = new Registration(plugins, declaringClass, bytecodeProvider);
r.registerMethodSubstitution(substituteDeclaringClass, "numberOfLeadingZeros", type);
if (arch.getFeatures().contains(AMD64.CPUFeature.LZCNT) && arch.getFlags().contains(AMD64.Flag.UseCountLeadingZerosInstruction)) {
r.setAllowOverwrite(true);
r.register1("numberOfLeadingZeros", type, new InvocationPlugin() {
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode value) {
@ -125,11 +129,13 @@ public class AMD64GraphBuilderPlugins {
return true;
}
});
} else {
r.registerMethodSubstitution(substituteDeclaringClass, "numberOfLeadingZeros", type);
}
r.registerMethodSubstitution(substituteDeclaringClass, "numberOfTrailingZeros", type);
if (arch.getFeatures().contains(AMD64.CPUFeature.BMI1) && arch.getFlags().contains(AMD64.Flag.UseCountTrailingZerosInstruction)) {
r.setAllowOverwrite(true);
r.register1("numberOfTrailingZeros", type, new InvocationPlugin() {
@Override
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode value) {
ValueNode folded = AMD64CountTrailingZerosNode.tryFold(value);
@ -141,8 +147,6 @@ public class AMD64GraphBuilderPlugins {
return true;
}
});
} else {
r.registerMethodSubstitution(substituteDeclaringClass, "numberOfTrailingZeros", type);
}
if (arch.getFeatures().contains(AMD64.CPUFeature.POPCNT)) {
@ -154,9 +158,10 @@ public class AMD64GraphBuilderPlugins {
}
});
}
}
private static void registerMathPlugins(InvocationPlugins plugins, AMD64 arch, BytecodeProvider bytecodeProvider) {
private static void registerMathPlugins(InvocationPlugins plugins, boolean useFMAIntrinsics, AMD64 arch, BytecodeProvider bytecodeProvider) {
Registration r = new Registration(plugins, Math.class, bytecodeProvider);
registerUnaryMath(r, "log", LOG);
registerUnaryMath(r, "log10", LOG10);
@ -171,6 +176,45 @@ public class AMD64GraphBuilderPlugins {
registerRound(r, "ceil", RoundingMode.UP);
registerRound(r, "floor", RoundingMode.DOWN);
}
if (useFMAIntrinsics && !Java8OrEarlier && arch.getFeatures().contains(CPUFeature.FMA)) {
registerFMA(r);
}
}
private static void registerFMA(Registration r) {
r.register3("fma",
Double.TYPE,
Double.TYPE,
Double.TYPE,
new InvocationPlugin() {
@Override
public boolean apply(GraphBuilderContext b,
ResolvedJavaMethod targetMethod,
Receiver receiver,
ValueNode na,
ValueNode nb,
ValueNode nc) {
b.push(JavaKind.Double, b.append(new FusedMultiplyAddNode(na, nb, nc)));
return true;
}
});
r.register3("fma",
Float.TYPE,
Float.TYPE,
Float.TYPE,
new InvocationPlugin() {
@Override
public boolean apply(GraphBuilderContext b,
ResolvedJavaMethod targetMethod,
Receiver receiver,
ValueNode na,
ValueNode nb,
ValueNode nc) {
b.push(JavaKind.Float, b.append(new FusedMultiplyAddNode(na, nb, nc)));
return true;
}
});
}
private static void registerUnaryMath(Registration r, String name, UnaryOperation operation) {

@ -35,6 +35,7 @@ import org.graalvm.compiler.core.target.Backend;
import org.graalvm.compiler.core.test.GraalCompilerTest;
import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin;
import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins;
import org.graalvm.compiler.nodes.graphbuilderconf.MethodSubstitutionPlugin;
import org.graalvm.compiler.options.OptionValues;
@ -95,7 +96,11 @@ public class RootMethodSubstitutionTest extends GraalCompilerTest {
}
}
if (!original.isNative()) {
ret.add(new Object[]{original});
// Make sure the plugin we found hasn't been overridden.
InvocationPlugin plugin = providers.getReplacements().getGraphBuilderPlugins().getInvocationPlugins().lookupInvocation(original);
if (plugin instanceof MethodSubstitutionPlugin) {
ret.add(new Object[]{original});
}
}
}
}

@ -48,6 +48,7 @@ import org.graalvm.compiler.api.replacements.Snippet;
import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
import org.graalvm.compiler.core.common.LIRKind;
import org.graalvm.compiler.core.common.spi.ForeignCallsProvider;
import org.graalvm.compiler.core.common.type.AbstractObjectStamp;
import org.graalvm.compiler.core.common.type.IntegerStamp;
import org.graalvm.compiler.core.common.type.ObjectStamp;
import org.graalvm.compiler.core.common.type.Stamp;
@ -139,6 +140,7 @@ import org.graalvm.compiler.phases.util.Providers;
import org.graalvm.compiler.replacements.SnippetLowerableMemoryNode.SnippetLowering;
import org.graalvm.compiler.replacements.nodes.BinaryMathIntrinsicNode;
import org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode;
import org.graalvm.compiler.word.WordTypes;
import jdk.internal.vm.compiler.word.LocationIdentity;
import jdk.vm.ci.code.CodeUtil;
@ -164,6 +166,7 @@ public abstract class DefaultJavaLoweringProvider implements LoweringProvider {
protected final TargetDescription target;
private final boolean useCompressedOops;
private final ResolvedJavaType objectArrayType;
private final WordTypes wordTypes;
private BoxingSnippets.Templates boxingSnippets;
private ConstantStringIndexOfSnippets.Templates indexOfSnippets;
@ -174,6 +177,7 @@ public abstract class DefaultJavaLoweringProvider implements LoweringProvider {
this.target = target;
this.useCompressedOops = useCompressedOops;
this.objectArrayType = metaAccess.lookupJavaType(Object[].class);
this.wordTypes = new WordTypes(metaAccess, target.wordJavaKind);
}
public void initialize(OptionValues options, Iterable<DebugHandlersFactory> factories, SnippetCounter.Group.Factory factory, Providers providers, SnippetReflectionProvider snippetReflection) {
@ -513,7 +517,7 @@ public abstract class DefaultJavaLoweringProvider implements LoweringProvider {
AddressNode address = createArrayIndexAddress(graph, array, elementKind, storeIndexed.index(), boundsCheck);
WriteNode memoryWrite = graph.add(new WriteNode(address, NamedLocationIdentity.getArrayLocation(elementKind), implicitStoreConvert(graph, elementKind, value),
arrayStoreBarrierType(storeIndexed.elementKind())));
arrayStoreBarrierType(array, storeIndexed.elementKind())));
memoryWrite.setGuard(boundsCheck);
if (condition != null) {
tool.createGuard(storeIndexed, condition, DeoptimizationReason.ArrayStoreException, DeoptimizationAction.InvalidateReprofile);
@ -788,11 +792,11 @@ public abstract class DefaultJavaLoweringProvider implements LoweringProvider {
long offset = fieldOffset(field);
if (offset >= 0) {
address = createOffsetAddress(graph, newObject, offset);
barrierType = fieldInitializationBarrier(entryKind);
barrierType = fieldInitializationBarrier(field);
}
} else {
address = createOffsetAddress(graph, newObject, metaAccess.getArrayBaseOffset(entryKind) + i * metaAccess.getArrayIndexScale(entryKind));
barrierType = arrayInitializationBarrier(entryKind);
barrierType = arrayInitializationBarrier(newObject, entryKind);
}
if (address != null) {
WriteNode write = new WriteNode(address, LocationIdentity.init(), implicitStoreConvert(graph, entryKind, value), barrierType);
@ -822,10 +826,10 @@ public abstract class DefaultJavaLoweringProvider implements LoweringProvider {
if (virtual instanceof VirtualInstanceNode) {
VirtualInstanceNode virtualInstance = (VirtualInstanceNode) virtual;
address = createFieldAddress(graph, newObject, virtualInstance.field(i));
barrierType = BarrierType.IMPRECISE;
barrierType = fieldStoreBarrierType(virtualInstance.field(i));
} else {
address = createArrayAddress(graph, newObject, virtual.entryKind(i), ConstantNode.forInt(i, graph));
barrierType = BarrierType.PRECISE;
barrierType = arrayStoreBarrierType(newObject, virtual.entryKind(i));
}
if (address != null) {
WriteNode write = new WriteNode(address, LocationIdentity.init(), implicitStoreConvert(graph, JavaKind.Object, allocValue), barrierType);
@ -939,25 +943,50 @@ public abstract class DefaultJavaLoweringProvider implements LoweringProvider {
}
protected BarrierType fieldStoreBarrierType(ResolvedJavaField field) {
if (field.getJavaKind() == JavaKind.Object) {
return BarrierType.IMPRECISE;
JavaKind fieldKind = wordTypes.asKind(field.getType());
if (fieldKind == JavaKind.Object) {
return BarrierType.FIELD;
}
return BarrierType.NONE;
}
protected BarrierType arrayStoreBarrierType(JavaKind elementKind) {
if (elementKind == JavaKind.Object) {
return BarrierType.PRECISE;
/**
* If the given value is indeed an array, and its elements are of a word type, return the
* correct word kind; in all other cases, return the defaultElementKind. This is needed for
* determining the correct write barrier type.
*
* @param array a value that is expected to have an array stamp
* @param defaultElementKind the array's element kind without taking word types into account
* @return the element kind of the array taking word types into account
*/
protected JavaKind maybeWordArrayElementKind(ValueNode array, JavaKind defaultElementKind) {
JavaKind elementKind = defaultElementKind;
Stamp arrayStamp = array.stamp(NodeView.DEFAULT);
if (arrayStamp instanceof AbstractObjectStamp && arrayStamp.hasValues()) {
ResolvedJavaType arrayType = ((AbstractObjectStamp) arrayStamp).type();
if (arrayType != null && arrayType.getComponentType() != null) {
elementKind = wordTypes.asKind(arrayType.getComponentType());
}
}
return elementKind;
}
protected BarrierType arrayStoreBarrierType(ValueNode array, JavaKind elementKind) {
JavaKind kind = maybeWordArrayElementKind(array, elementKind);
if (kind == JavaKind.Object) {
return BarrierType.ARRAY;
}
return BarrierType.NONE;
}
public BarrierType fieldInitializationBarrier(JavaKind entryKind) {
return entryKind == JavaKind.Object ? BarrierType.IMPRECISE : BarrierType.NONE;
public BarrierType fieldInitializationBarrier(ResolvedJavaField field) {
JavaKind fieldKind = wordTypes.asKind(field.getType());
return fieldKind == JavaKind.Object ? BarrierType.FIELD : BarrierType.NONE;
}
public BarrierType arrayInitializationBarrier(JavaKind entryKind) {
return entryKind == JavaKind.Object ? BarrierType.PRECISE : BarrierType.NONE;
public BarrierType arrayInitializationBarrier(ValueNode array, JavaKind entryKind) {
JavaKind kind = maybeWordArrayElementKind(array, entryKind);
return kind == JavaKind.Object ? BarrierType.ARRAY : BarrierType.NONE;
}
private BarrierType unsafeStoreBarrierType(RawStoreNode store) {
@ -972,10 +1001,14 @@ public abstract class DefaultJavaLoweringProvider implements LoweringProvider {
ResolvedJavaType type = StampTool.typeOrNull(object);
// Array types must use a precise barrier, so if the type is unknown or is a supertype
// of Object[] then treat it as an array.
if (type == null || type.isArray() || type.isAssignableFrom(objectArrayType)) {
return BarrierType.PRECISE;
if (type != null && type.isArray()) {
return arrayStoreBarrierType(object, JavaKind.Object);
} else if (type != null && wordTypes.isWord(type)) {
return BarrierType.NONE;
} else if (type == null || type.isAssignableFrom(objectArrayType)) {
return BarrierType.UNKNOWN;
} else {
return BarrierType.IMPRECISE;
return BarrierType.FIELD;
}
}
return BarrierType.NONE;

@ -0,0 +1,92 @@
/*
* 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_2;
import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_1;
import org.graalvm.compiler.core.common.type.FloatStamp;
import org.graalvm.compiler.core.common.type.Stamp;
import org.graalvm.compiler.graph.NodeClass;
import org.graalvm.compiler.graph.spi.CanonicalizerTool;
import org.graalvm.compiler.lir.gen.ArithmeticLIRGeneratorTool;
import org.graalvm.compiler.nodeinfo.NodeInfo;
import org.graalvm.compiler.nodes.ConstantNode;
import org.graalvm.compiler.nodes.NodeView;
import org.graalvm.compiler.nodes.ValueNode;
import org.graalvm.compiler.nodes.calc.TernaryNode;
import org.graalvm.compiler.nodes.spi.ArithmeticLIRLowerable;
import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
import jdk.vm.ci.meta.JavaConstant;
import jdk.vm.ci.meta.JavaKind;
import org.graalvm.compiler.serviceprovider.GraalServices;
@NodeInfo(cycles = CYCLES_2, size = SIZE_1)
public final class FusedMultiplyAddNode extends TernaryNode implements ArithmeticLIRLowerable {
public static final NodeClass<FusedMultiplyAddNode> TYPE = NodeClass.create(FusedMultiplyAddNode.class);
public FusedMultiplyAddNode(ValueNode a, ValueNode b, ValueNode c) {
super(TYPE, computeStamp(a.stamp(NodeView.DEFAULT), b.stamp(NodeView.DEFAULT), c.stamp(NodeView.DEFAULT)), a, b, c);
assert a.getStackKind().isNumericFloat();
assert b.getStackKind().isNumericFloat();
assert c.getStackKind().isNumericFloat();
}
@Override
public Stamp foldStamp(Stamp stampX, Stamp stampY, Stamp stampZ) {
return computeStamp(stampX, stampY, stampZ);
}
private static Stamp computeStamp(Stamp stampX, Stamp stampY, Stamp stampZ) {
Stamp m = FloatStamp.OPS.getMul().foldStamp(stampX, stampY);
return FloatStamp.OPS.getAdd().foldStamp(m, stampZ);
}
@Override
public ValueNode canonical(CanonicalizerTool tool, ValueNode a, ValueNode b, ValueNode c) {
if (a.isConstant() && b.isConstant() && c.isConstant()) {
JavaConstant ca = a.asJavaConstant();
JavaConstant cb = b.asJavaConstant();
JavaConstant cc = c.asJavaConstant();
ValueNode res;
if (a.getStackKind() == JavaKind.Float) {
res = ConstantNode.forFloat(GraalServices.fma(ca.asFloat(), cb.asFloat(), cc.asFloat()));
} else {
assert a.getStackKind() == JavaKind.Double;
res = ConstantNode.forDouble(GraalServices.fma(ca.asDouble(), cb.asDouble(), cc.asDouble()));
}
return res;
}
return this;
}
@Override
public void generate(NodeLIRBuilderTool builder, ArithmeticLIRGeneratorTool gen) {
builder.setResult(this, gen.emitFusedMultiplyAdd(builder.operand(getX()), builder.operand(getY()), builder.operand(getZ())));
}
}

@ -501,4 +501,22 @@ public final class GraalServices {
}
return jmx.getInputArguments();
}
/**
* Returns the fused multiply add of the three arguments; that is, returns the exact product of
* the first two arguments summed with the third argument and then rounded once to the nearest
* {@code float}.
*/
public static float fma(float a, float b, float c) {
return Math.fma(a, b, c);
}
/**
* Returns the fused multiply add of the three arguments; that is, returns the exact product of
* the first two arguments summed with the third argument and then rounded once to the nearest
* {@code double}.
*/
public static double fma(double a, double b, double c) {
return Math.fma(a, b, c);
}
}

@ -447,7 +447,7 @@ public class WordOperationPlugin implements NodePlugin, TypePlugin, InlineInvoke
protected ValueNode readOp(GraphBuilderContext b, JavaKind readKind, AddressNode address, LocationIdentity location, Opcode op) {
assert op == Opcode.READ_POINTER || op == Opcode.READ_OBJECT || op == Opcode.READ_BARRIERED;
final BarrierType barrier = (op == Opcode.READ_BARRIERED ? BarrierType.PRECISE : BarrierType.NONE);
final BarrierType barrier = (op == Opcode.READ_BARRIERED ? BarrierType.UNKNOWN : BarrierType.NONE);
final boolean compressible = (op == Opcode.READ_OBJECT || op == Opcode.READ_BARRIERED);
return readOp(b, readKind, address, location, barrier, compressible);
@ -465,7 +465,7 @@ public class WordOperationPlugin implements NodePlugin, TypePlugin, InlineInvoke
protected void writeOp(GraphBuilderContext b, JavaKind writeKind, AddressNode address, LocationIdentity location, ValueNode value, Opcode op) {
assert op == Opcode.WRITE_POINTER || op == Opcode.WRITE_OBJECT || op == Opcode.WRITE_BARRIERED || op == Opcode.INITIALIZE;
final BarrierType barrier = (op == Opcode.WRITE_BARRIERED ? BarrierType.PRECISE : BarrierType.NONE);
final BarrierType barrier = (op == Opcode.WRITE_BARRIERED ? BarrierType.UNKNOWN : BarrierType.NONE);
final boolean compressible = (op == Opcode.WRITE_OBJECT || op == Opcode.WRITE_BARRIERED);
assert op != Opcode.INITIALIZE || location.isInit() : "must use init location for initializing";
b.add(new JavaWriteNode(writeKind, address, location, value, barrier, compressible));