8210478: Update Graal
Reviewed-by: kvn
This commit is contained in:
parent
07392d976a
commit
acb7acc64f
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2017, 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,6 +24,7 @@
|
||||
|
||||
package org.graalvm.compiler.hotspot.management;
|
||||
|
||||
import org.graalvm.compiler.phases.common.jmx.HotSpotMBeanOperationProvider;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
@ -49,6 +50,7 @@ import org.graalvm.compiler.hotspot.HotSpotGraalRuntime;
|
||||
import org.graalvm.compiler.options.OptionDescriptor;
|
||||
import org.graalvm.compiler.options.OptionDescriptors;
|
||||
import org.graalvm.compiler.options.OptionsParser;
|
||||
import org.graalvm.compiler.serviceprovider.GraalServices;
|
||||
|
||||
/**
|
||||
* MBean used to access properties and operations of a {@link HotSpotGraalRuntime} instance.
|
||||
@ -170,11 +172,32 @@ final class HotSpotGraalRuntimeMBean implements DynamicMBean {
|
||||
if (DEBUG) {
|
||||
System.out.printf("invoke: %s%s%n", actionName, Arrays.asList(params));
|
||||
}
|
||||
Object retvalue = runtime.invokeManagementAction(actionName, params);
|
||||
Object retvalue = null;
|
||||
if ("dumpMethod".equals(actionName)) {
|
||||
retvalue = runtime.invokeManagementAction(actionName, params);
|
||||
} else {
|
||||
boolean found = false;
|
||||
for (HotSpotMBeanOperationProvider p : GraalServices.load(HotSpotMBeanOperationProvider.class)) {
|
||||
List<MBeanOperationInfo> info = new ArrayList<>();
|
||||
p.registerOperations(MBeanOperationInfo.class, info);
|
||||
for (MBeanOperationInfo op : info) {
|
||||
if (actionName.equals(op.getName())) {
|
||||
retvalue = p.invoke(actionName, params, signature);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
throw new MBeanException(new IllegalStateException("Cannot find operation " + actionName));
|
||||
}
|
||||
}
|
||||
if (DEBUG) {
|
||||
System.out.printf("invoke: %s%s = %s%n", actionName, Arrays.asList(params), retvalue);
|
||||
}
|
||||
return retvalue;
|
||||
} catch (MBeanException ex) {
|
||||
throw ex;
|
||||
} catch (Exception ex) {
|
||||
throw new ReflectionException(ex);
|
||||
}
|
||||
@ -198,30 +221,35 @@ final class HotSpotGraalRuntimeMBean implements DynamicMBean {
|
||||
return o1.getName().compareTo(o2.getName());
|
||||
}
|
||||
});
|
||||
MBeanOperationInfo[] ops = {
|
||||
new MBeanOperationInfo("dumpMethod", "Enable IGV dumps for provided method", new MBeanParameterInfo[]{
|
||||
new MBeanParameterInfo("className", "java.lang.String", "Class to observe"),
|
||||
new MBeanParameterInfo("methodName", "java.lang.String", "Method to observe"),
|
||||
}, "void", MBeanOperationInfo.ACTION),
|
||||
new MBeanOperationInfo("dumpMethod", "Enable IGV dumps for provided method", new MBeanParameterInfo[]{
|
||||
new MBeanParameterInfo("className", "java.lang.String", "Class to observe"),
|
||||
new MBeanParameterInfo("methodName", "java.lang.String", "Method to observe"),
|
||||
new MBeanParameterInfo("filter", "java.lang.String", "The parameter for Dump option"),
|
||||
}, "void", MBeanOperationInfo.ACTION),
|
||||
new MBeanOperationInfo("dumpMethod", "Enable IGV dumps for provided method", new MBeanParameterInfo[]{
|
||||
new MBeanParameterInfo("className", "java.lang.String", "Class to observe"),
|
||||
new MBeanParameterInfo("methodName", "java.lang.String", "Method to observe"),
|
||||
new MBeanParameterInfo("filter", "java.lang.String", "The parameter for Dump option"),
|
||||
new MBeanParameterInfo("host", "java.lang.String", "The host where the IGV tool is running at"),
|
||||
new MBeanParameterInfo("port", "int", "The port where the IGV tool is listening at"),
|
||||
}, "void", MBeanOperationInfo.ACTION)
|
||||
};
|
||||
List<MBeanOperationInfo> opts = new ArrayList<>();
|
||||
opts.add(new MBeanOperationInfo("dumpMethod", "Enable IGV dumps for provided method", new MBeanParameterInfo[]{
|
||||
new MBeanParameterInfo("className", "java.lang.String", "Class to observe"),
|
||||
new MBeanParameterInfo("methodName", "java.lang.String", "Method to observe"),
|
||||
}, "void", MBeanOperationInfo.ACTION));
|
||||
opts.add(new MBeanOperationInfo("dumpMethod", "Enable IGV dumps for provided method", new MBeanParameterInfo[]{
|
||||
new MBeanParameterInfo("className", "java.lang.String", "Class to observe"),
|
||||
new MBeanParameterInfo("methodName", "java.lang.String", "Method to observe"),
|
||||
new MBeanParameterInfo("filter", "java.lang.String", "The parameter for Dump option"),
|
||||
}, "void", MBeanOperationInfo.ACTION));
|
||||
opts.add(new MBeanOperationInfo("dumpMethod", "Enable IGV dumps for provided method", new MBeanParameterInfo[]{
|
||||
new MBeanParameterInfo("className", "java.lang.String", "Class to observe"),
|
||||
new MBeanParameterInfo("methodName", "java.lang.String", "Method to observe"),
|
||||
new MBeanParameterInfo("filter", "java.lang.String", "The parameter for Dump option"),
|
||||
new MBeanParameterInfo("host", "java.lang.String", "The host where the IGV tool is running at"),
|
||||
new MBeanParameterInfo("port", "int", "The port where the IGV tool is listening at"),
|
||||
}, "void", MBeanOperationInfo.ACTION));
|
||||
|
||||
for (HotSpotMBeanOperationProvider p : GraalServices.load(HotSpotMBeanOperationProvider.class)) {
|
||||
p.registerOperations(MBeanOperationInfo.class, opts);
|
||||
}
|
||||
|
||||
return new MBeanInfo(
|
||||
HotSpotGraalRuntimeMBean.class.getName(),
|
||||
"Graal",
|
||||
attrs.toArray(new MBeanAttributeInfo[attrs.size()]),
|
||||
null, ops, null);
|
||||
null,
|
||||
opts.toArray(new MBeanOperationInfo[opts.size()]),
|
||||
null);
|
||||
}
|
||||
|
||||
private static EconomicMap<String, OptionDescriptor> getOptionDescriptors() {
|
||||
|
@ -74,6 +74,7 @@ module jdk.internal.vm.compiler {
|
||||
jdk.aot,
|
||||
jdk.internal.vm.compiler.management;
|
||||
exports org.graalvm.compiler.phases to jdk.aot;
|
||||
exports org.graalvm.compiler.phases.common.jmx to jdk.internal.vm.compiler.management;
|
||||
exports org.graalvm.compiler.phases.tiers to jdk.aot;
|
||||
exports org.graalvm.compiler.printer to jdk.aot;
|
||||
exports org.graalvm.compiler.runtime to jdk.aot;
|
||||
|
@ -52,6 +52,8 @@ import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.OperandSize.SD;
|
||||
import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.OperandSize.SS;
|
||||
import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.OperandSize.WORD;
|
||||
import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.VEXPrefixConfig.L128;
|
||||
import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.VEXPrefixConfig.L256;
|
||||
import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.VEXPrefixConfig.LZ;
|
||||
import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.VEXPrefixConfig.M_0F;
|
||||
import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.VEXPrefixConfig.M_0F38;
|
||||
import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.VEXPrefixConfig.M_0F3A;
|
||||
@ -78,7 +80,6 @@ import org.graalvm.compiler.debug.GraalError;
|
||||
|
||||
import jdk.vm.ci.amd64.AMD64;
|
||||
import jdk.vm.ci.amd64.AMD64.CPUFeature;
|
||||
import jdk.vm.ci.amd64.AMD64Kind;
|
||||
import jdk.vm.ci.code.Register;
|
||||
import jdk.vm.ci.code.Register.RegisterCategory;
|
||||
import jdk.vm.ci.code.TargetDescription;
|
||||
@ -893,7 +894,7 @@ public class AMD64Assembler extends AMD64BaseAssembler {
|
||||
}
|
||||
}
|
||||
|
||||
private enum AVXOpAssertion {
|
||||
private enum VEXOpAssertion {
|
||||
AVX1(CPUFeature.AVX, CPUFeature.AVX),
|
||||
AVX1_2(CPUFeature.AVX, CPUFeature.AVX2),
|
||||
AVX2(CPUFeature.AVX2, CPUFeature.AVX2),
|
||||
@ -903,23 +904,25 @@ public class AMD64Assembler extends AMD64BaseAssembler {
|
||||
XMM_CPU(CPUFeature.AVX, null, XMM, null, CPU, null),
|
||||
XMM_XMM_CPU(CPUFeature.AVX, null, XMM, XMM, CPU, null),
|
||||
CPU_XMM(CPUFeature.AVX, null, CPU, null, XMM, null),
|
||||
AVX1_2_CPU_XMM(CPUFeature.AVX, CPUFeature.AVX2, 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);
|
||||
|
||||
private final CPUFeature avx128feature;
|
||||
private final CPUFeature avx256feature;
|
||||
private final CPUFeature l128feature;
|
||||
private final CPUFeature l256feature;
|
||||
|
||||
private final RegisterCategory rCategory;
|
||||
private final RegisterCategory vCategory;
|
||||
private final RegisterCategory mCategory;
|
||||
private final RegisterCategory imm8Category;
|
||||
|
||||
AVXOpAssertion(CPUFeature avx128feature, CPUFeature avx256feature) {
|
||||
this(avx128feature, avx256feature, XMM, XMM, XMM, XMM);
|
||||
VEXOpAssertion(CPUFeature l128feature, CPUFeature l256feature) {
|
||||
this(l128feature, l256feature, XMM, XMM, XMM, XMM);
|
||||
}
|
||||
|
||||
AVXOpAssertion(CPUFeature avx128feature, CPUFeature avx256feature, RegisterCategory rCategory, RegisterCategory vCategory, RegisterCategory mCategory, RegisterCategory imm8Category) {
|
||||
this.avx128feature = avx128feature;
|
||||
this.avx256feature = avx256feature;
|
||||
VEXOpAssertion(CPUFeature l128feature, CPUFeature l256feature, RegisterCategory rCategory, RegisterCategory vCategory, RegisterCategory mCategory, RegisterCategory imm8Category) {
|
||||
this.l128feature = l128feature;
|
||||
this.l256feature = l256feature;
|
||||
this.rCategory = rCategory;
|
||||
this.vCategory = vCategory;
|
||||
this.mCategory = mCategory;
|
||||
@ -927,16 +930,20 @@ public class AMD64Assembler extends AMD64BaseAssembler {
|
||||
}
|
||||
|
||||
public boolean check(AMD64 arch, AVXSize size, Register r, Register v, Register m) {
|
||||
return check(arch, size, r, v, m, null);
|
||||
return check(arch, getLFlag(size), r, v, m, null);
|
||||
}
|
||||
|
||||
public boolean check(AMD64 arch, AVXSize size, Register r, Register v, Register m, Register imm8) {
|
||||
switch (size) {
|
||||
case XMM:
|
||||
assert avx128feature != null && arch.getFeatures().contains(avx128feature) : "emitting illegal 128 bit instruction";
|
||||
return check(arch, getLFlag(size), r, v, m, imm8);
|
||||
}
|
||||
|
||||
public boolean check(AMD64 arch, int l, Register r, Register v, Register m, Register imm8) {
|
||||
switch (l) {
|
||||
case L128:
|
||||
assert l128feature != null && arch.getFeatures().contains(l128feature) : "emitting illegal 128 bit instruction";
|
||||
break;
|
||||
case YMM:
|
||||
assert avx256feature != null && arch.getFeatures().contains(avx256feature) : "emitting illegal 256 bit instruction";
|
||||
case L256:
|
||||
assert l256feature != null && arch.getFeatures().contains(l256feature) : "emitting illegal 256 bit instruction";
|
||||
break;
|
||||
}
|
||||
if (r != null) {
|
||||
@ -957,9 +964,9 @@ public class AMD64Assembler extends AMD64BaseAssembler {
|
||||
public boolean supports(EnumSet<CPUFeature> features, AVXSize avxSize) {
|
||||
switch (avxSize) {
|
||||
case XMM:
|
||||
return avx128feature != null && features.contains(avx128feature);
|
||||
return l128feature != null && features.contains(l128feature);
|
||||
case YMM:
|
||||
return avx256feature != null && features.contains(avx256feature);
|
||||
return l256feature != null && features.contains(l256feature);
|
||||
default:
|
||||
throw GraalError.shouldNotReachHere();
|
||||
}
|
||||
@ -976,9 +983,9 @@ public class AMD64Assembler extends AMD64BaseAssembler {
|
||||
protected final int op;
|
||||
|
||||
private final String opcode;
|
||||
protected final AVXOpAssertion assertion;
|
||||
protected final VEXOpAssertion assertion;
|
||||
|
||||
protected VexOp(String opcode, int pp, int mmmmm, int w, int op, AVXOpAssertion assertion) {
|
||||
protected VexOp(String opcode, int pp, int mmmmm, int w, int op, VEXOpAssertion assertion) {
|
||||
this.pp = pp;
|
||||
this.mmmmm = mmmmm;
|
||||
this.w = w;
|
||||
@ -987,10 +994,6 @@ public class AMD64Assembler extends AMD64BaseAssembler {
|
||||
this.assertion = assertion;
|
||||
}
|
||||
|
||||
public boolean isSupported(AMD64Assembler vasm, AMD64Kind kind) {
|
||||
return assertion.supports(((AMD64) vasm.target.arch).getFeatures(), AVXKind.getRegisterSize(kind));
|
||||
}
|
||||
|
||||
public final boolean isSupported(AMD64Assembler vasm, AVXSize size) {
|
||||
return assertion.supports(((AMD64) vasm.target.arch).getFeatures(), size);
|
||||
}
|
||||
@ -1006,14 +1009,14 @@ public class AMD64Assembler extends AMD64BaseAssembler {
|
||||
*/
|
||||
public static class VexRROp extends VexOp {
|
||||
// @formatter:off
|
||||
public static final VexRROp VMASKMOVDQU = new VexRROp("VMASKMOVDQU", P_66, M_0F, WIG, 0xF7, AVXOpAssertion.AVX1_128ONLY);
|
||||
public static final VexRROp VMASKMOVDQU = new VexRROp("VMASKMOVDQU", P_66, M_0F, WIG, 0xF7, VEXOpAssertion.AVX1_128ONLY);
|
||||
// @formatter:on
|
||||
|
||||
protected VexRROp(String opcode, int pp, int mmmmm, int w, int op) {
|
||||
this(opcode, pp, mmmmm, w, op, AVXOpAssertion.AVX1);
|
||||
this(opcode, pp, mmmmm, w, op, VEXOpAssertion.AVX1);
|
||||
}
|
||||
|
||||
protected VexRROp(String opcode, int pp, int mmmmm, int w, int op, AVXOpAssertion assertion) {
|
||||
protected VexRROp(String opcode, int pp, int mmmmm, int w, int op, VEXOpAssertion assertion) {
|
||||
super(opcode, pp, mmmmm, w, op, assertion);
|
||||
}
|
||||
|
||||
@ -1031,10 +1034,10 @@ public class AMD64Assembler extends AMD64BaseAssembler {
|
||||
*/
|
||||
public static class VexRMOp extends VexRROp {
|
||||
// @formatter:off
|
||||
public static final VexRMOp VCVTTSS2SI = new VexRMOp("VCVTTSS2SI", P_F3, M_0F, W0, 0x2C, AVXOpAssertion.CPU_XMM);
|
||||
public static final VexRMOp VCVTTSS2SQ = new VexRMOp("VCVTTSS2SQ", P_F3, M_0F, W1, 0x2C, AVXOpAssertion.CPU_XMM);
|
||||
public static final VexRMOp VCVTTSD2SI = new VexRMOp("VCVTTSD2SI", P_F2, M_0F, W0, 0x2C, AVXOpAssertion.CPU_XMM);
|
||||
public static final VexRMOp VCVTTSD2SQ = new VexRMOp("VCVTTSD2SQ", P_F2, M_0F, W1, 0x2C, AVXOpAssertion.CPU_XMM);
|
||||
public static final VexRMOp VCVTTSS2SI = new VexRMOp("VCVTTSS2SI", P_F3, M_0F, W0, 0x2C, VEXOpAssertion.CPU_XMM);
|
||||
public static final VexRMOp VCVTTSS2SQ = new VexRMOp("VCVTTSS2SQ", P_F3, M_0F, W1, 0x2C, VEXOpAssertion.CPU_XMM);
|
||||
public static final VexRMOp VCVTTSD2SI = new VexRMOp("VCVTTSD2SI", P_F2, M_0F, W0, 0x2C, VEXOpAssertion.CPU_XMM);
|
||||
public static final VexRMOp VCVTTSD2SQ = new VexRMOp("VCVTTSD2SQ", P_F2, M_0F, W1, 0x2C, VEXOpAssertion.CPU_XMM);
|
||||
public static final VexRMOp VCVTPS2PD = new VexRMOp("VCVTPS2PD", P_, M_0F, WIG, 0x5A);
|
||||
public static final VexRMOp VCVTPD2PS = new VexRMOp("VCVTPD2PS", P_66, M_0F, WIG, 0x5A);
|
||||
public static final VexRMOp VCVTDQ2PS = new VexRMOp("VCVTDQ2PS", P_, M_0F, WIG, 0x5B);
|
||||
@ -1042,14 +1045,14 @@ public class AMD64Assembler extends AMD64BaseAssembler {
|
||||
public static final VexRMOp VCVTTPD2DQ = new VexRMOp("VCVTTPD2DQ", P_66, M_0F, WIG, 0xE6);
|
||||
public static final VexRMOp VCVTDQ2PD = new VexRMOp("VCVTDQ2PD", P_F3, M_0F, WIG, 0xE6);
|
||||
public static final VexRMOp VBROADCASTSS = new VexRMOp("VBROADCASTSS", P_66, M_0F38, W0, 0x18);
|
||||
public static final VexRMOp VBROADCASTSD = new VexRMOp("VBROADCASTSD", P_66, M_0F38, W0, 0x19, AVXOpAssertion.AVX1_256ONLY);
|
||||
public static final VexRMOp VBROADCASTF128 = new VexRMOp("VBROADCASTF128", P_66, M_0F38, W0, 0x1A, AVXOpAssertion.AVX1_256ONLY);
|
||||
public static final VexRMOp VPBROADCASTI128 = new VexRMOp("VPBROADCASTI128", P_66, M_0F38, W0, 0x5A, AVXOpAssertion.AVX2_256ONLY);
|
||||
public static final VexRMOp VPBROADCASTB = new VexRMOp("VPBROADCASTB", P_66, M_0F38, W0, 0x78, AVXOpAssertion.AVX2);
|
||||
public static final VexRMOp VPBROADCASTW = new VexRMOp("VPBROADCASTW", P_66, M_0F38, W0, 0x79, AVXOpAssertion.AVX2);
|
||||
public static final VexRMOp VPBROADCASTD = new VexRMOp("VPBROADCASTD", P_66, M_0F38, W0, 0x58, AVXOpAssertion.AVX2);
|
||||
public static final VexRMOp VPBROADCASTQ = new VexRMOp("VPBROADCASTQ", P_66, M_0F38, W0, 0x59, AVXOpAssertion.AVX2);
|
||||
public static final VexRMOp VPMOVMSKB = new VexRMOp("VPMOVMSKB", P_66, M_0F, WIG, 0xD7, AVXOpAssertion.AVX1_2_CPU_XMM);
|
||||
public static final VexRMOp VBROADCASTSD = new VexRMOp("VBROADCASTSD", P_66, M_0F38, W0, 0x19, VEXOpAssertion.AVX1_256ONLY);
|
||||
public static final VexRMOp VBROADCASTF128 = new VexRMOp("VBROADCASTF128", P_66, M_0F38, W0, 0x1A, VEXOpAssertion.AVX1_256ONLY);
|
||||
public static final VexRMOp VPBROADCASTI128 = new VexRMOp("VPBROADCASTI128", P_66, M_0F38, W0, 0x5A, VEXOpAssertion.AVX2_256ONLY);
|
||||
public static final VexRMOp VPBROADCASTB = new VexRMOp("VPBROADCASTB", P_66, M_0F38, W0, 0x78, VEXOpAssertion.AVX2);
|
||||
public static final VexRMOp VPBROADCASTW = new VexRMOp("VPBROADCASTW", P_66, M_0F38, W0, 0x79, VEXOpAssertion.AVX2);
|
||||
public static final VexRMOp VPBROADCASTD = new VexRMOp("VPBROADCASTD", P_66, M_0F38, W0, 0x58, VEXOpAssertion.AVX2);
|
||||
public static final VexRMOp VPBROADCASTQ = new VexRMOp("VPBROADCASTQ", P_66, M_0F38, W0, 0x59, VEXOpAssertion.AVX2);
|
||||
public static final VexRMOp VPMOVMSKB = new VexRMOp("VPMOVMSKB", P_66, M_0F, WIG, 0xD7, VEXOpAssertion.AVX1_2_CPU_XMM);
|
||||
public static final VexRMOp VPMOVSXBW = new VexRMOp("VPMOVSXBW", P_66, M_0F38, WIG, 0x20);
|
||||
public static final VexRMOp VPMOVSXBD = new VexRMOp("VPMOVSXBD", P_66, M_0F38, WIG, 0x21);
|
||||
public static final VexRMOp VPMOVSXBQ = new VexRMOp("VPMOVSXBQ", P_66, M_0F38, WIG, 0x22);
|
||||
@ -1072,10 +1075,10 @@ public class AMD64Assembler extends AMD64BaseAssembler {
|
||||
// @formatter:on
|
||||
|
||||
protected VexRMOp(String opcode, int pp, int mmmmm, int w, int op) {
|
||||
this(opcode, pp, mmmmm, w, op, AVXOpAssertion.AVX1);
|
||||
this(opcode, pp, mmmmm, w, op, VEXOpAssertion.AVX1);
|
||||
}
|
||||
|
||||
protected VexRMOp(String opcode, int pp, int mmmmm, int w, int op, AVXOpAssertion assertion) {
|
||||
protected VexRMOp(String opcode, int pp, int mmmmm, int w, int op, VEXOpAssertion assertion) {
|
||||
super(opcode, pp, mmmmm, w, op, assertion);
|
||||
}
|
||||
|
||||
@ -1103,17 +1106,17 @@ public class AMD64Assembler extends AMD64BaseAssembler {
|
||||
public static final VexMoveOp VMOVUPD = new VexMoveOp("VMOVUPD", P_66, M_0F, WIG, 0x10, 0x11);
|
||||
public static final VexMoveOp VMOVSS = new VexMoveOp("VMOVSS", P_F3, M_0F, WIG, 0x10, 0x11);
|
||||
public static final VexMoveOp VMOVSD = new VexMoveOp("VMOVSD", P_F2, M_0F, WIG, 0x10, 0x11);
|
||||
public static final VexMoveOp VMOVD = new VexMoveOp("VMOVD", P_66, M_0F, W0, 0x6E, 0x7E, AVXOpAssertion.XMM_CPU);
|
||||
public static final VexMoveOp VMOVQ = new VexMoveOp("VMOVQ", P_66, M_0F, W1, 0x6E, 0x7E, AVXOpAssertion.XMM_CPU);
|
||||
public static final VexMoveOp VMOVD = new VexMoveOp("VMOVD", P_66, M_0F, W0, 0x6E, 0x7E, VEXOpAssertion.XMM_CPU);
|
||||
public static final VexMoveOp VMOVQ = new VexMoveOp("VMOVQ", P_66, M_0F, W1, 0x6E, 0x7E, VEXOpAssertion.XMM_CPU);
|
||||
// @formatter:on
|
||||
|
||||
private final int opReverse;
|
||||
|
||||
private VexMoveOp(String opcode, int pp, int mmmmm, int w, int op, int opReverse) {
|
||||
this(opcode, pp, mmmmm, w, op, opReverse, AVXOpAssertion.AVX1);
|
||||
this(opcode, pp, mmmmm, w, op, opReverse, VEXOpAssertion.AVX1);
|
||||
}
|
||||
|
||||
private VexMoveOp(String opcode, int pp, int mmmmm, int w, int op, int opReverse, AVXOpAssertion assertion) {
|
||||
private VexMoveOp(String opcode, int pp, int mmmmm, int w, int op, int opReverse, VEXOpAssertion assertion) {
|
||||
super(opcode, pp, mmmmm, w, op, assertion);
|
||||
this.opReverse = opReverse;
|
||||
}
|
||||
@ -1142,13 +1145,13 @@ public class AMD64Assembler extends AMD64BaseAssembler {
|
||||
*/
|
||||
public static final class VexRMIOp extends VexOp implements VexRRIOp {
|
||||
// @formatter:off
|
||||
public static final VexRMIOp VPERMQ = new VexRMIOp("VPERMQ", P_66, M_0F3A, W1, 0x00, AVXOpAssertion.AVX2_256ONLY);
|
||||
public static final VexRMIOp VPSHUFLW = new VexRMIOp("VPSHUFLW", P_F2, M_0F, WIG, 0x70, AVXOpAssertion.AVX1_2);
|
||||
public static final VexRMIOp VPSHUFHW = new VexRMIOp("VPSHUFHW", P_F3, M_0F, WIG, 0x70, AVXOpAssertion.AVX1_2);
|
||||
public static final VexRMIOp VPSHUFD = new VexRMIOp("VPSHUFD", P_66, M_0F, WIG, 0x70, AVXOpAssertion.AVX1_2);
|
||||
public static final VexRMIOp VPERMQ = new VexRMIOp("VPERMQ", P_66, M_0F3A, W1, 0x00, VEXOpAssertion.AVX2_256ONLY);
|
||||
public static final VexRMIOp VPSHUFLW = new VexRMIOp("VPSHUFLW", P_F2, M_0F, WIG, 0x70, VEXOpAssertion.AVX1_2);
|
||||
public static final VexRMIOp VPSHUFHW = new VexRMIOp("VPSHUFHW", P_F3, M_0F, WIG, 0x70, VEXOpAssertion.AVX1_2);
|
||||
public static final VexRMIOp VPSHUFD = new VexRMIOp("VPSHUFD", P_66, M_0F, WIG, 0x70, VEXOpAssertion.AVX1_2);
|
||||
// @formatter:on
|
||||
|
||||
private VexRMIOp(String opcode, int pp, int mmmmm, int w, int op, AVXOpAssertion assertion) {
|
||||
private VexRMIOp(String opcode, int pp, int mmmmm, int w, int op, VEXOpAssertion assertion) {
|
||||
super(opcode, pp, mmmmm, w, op, assertion);
|
||||
}
|
||||
|
||||
@ -1175,15 +1178,15 @@ public class AMD64Assembler extends AMD64BaseAssembler {
|
||||
*/
|
||||
public static final class VexMRIOp extends VexOp implements VexRRIOp {
|
||||
// @formatter:off
|
||||
public static final VexMRIOp VEXTRACTF128 = new VexMRIOp("VEXTRACTF128", P_66, M_0F3A, W0, 0x19, AVXOpAssertion.AVX1_256ONLY);
|
||||
public static final VexMRIOp VEXTRACTI128 = new VexMRIOp("VEXTRACTI128", P_66, M_0F3A, W0, 0x39, AVXOpAssertion.AVX2_256ONLY);
|
||||
public static final VexMRIOp VPEXTRB = new VexMRIOp("VPEXTRB", P_66, M_0F3A, W0, 0x14, AVXOpAssertion.XMM_CPU);
|
||||
public static final VexMRIOp VPEXTRW = new VexMRIOp("VPEXTRW", P_66, M_0F3A, W0, 0x15, AVXOpAssertion.XMM_CPU);
|
||||
public static final VexMRIOp VPEXTRD = new VexMRIOp("VPEXTRD", P_66, M_0F3A, W0, 0x16, AVXOpAssertion.XMM_CPU);
|
||||
public static final VexMRIOp VPEXTRQ = new VexMRIOp("VPEXTRQ", P_66, M_0F3A, W1, 0x16, AVXOpAssertion.XMM_CPU);
|
||||
public static final VexMRIOp VEXTRACTF128 = new VexMRIOp("VEXTRACTF128", P_66, M_0F3A, W0, 0x19, VEXOpAssertion.AVX1_256ONLY);
|
||||
public static final VexMRIOp VEXTRACTI128 = new VexMRIOp("VEXTRACTI128", P_66, M_0F3A, W0, 0x39, VEXOpAssertion.AVX2_256ONLY);
|
||||
public static final VexMRIOp VPEXTRB = new VexMRIOp("VPEXTRB", P_66, M_0F3A, W0, 0x14, VEXOpAssertion.XMM_CPU);
|
||||
public static final VexMRIOp VPEXTRW = new VexMRIOp("VPEXTRW", P_66, M_0F3A, W0, 0x15, VEXOpAssertion.XMM_CPU);
|
||||
public static final VexMRIOp VPEXTRD = new VexMRIOp("VPEXTRD", P_66, M_0F3A, W0, 0x16, VEXOpAssertion.XMM_CPU);
|
||||
public static final VexMRIOp VPEXTRQ = new VexMRIOp("VPEXTRQ", P_66, M_0F3A, W1, 0x16, VEXOpAssertion.XMM_CPU);
|
||||
// @formatter:on
|
||||
|
||||
private VexMRIOp(String opcode, int pp, int mmmmm, int w, int op, AVXOpAssertion assertion) {
|
||||
private VexMRIOp(String opcode, int pp, int mmmmm, int w, int op, VEXOpAssertion assertion) {
|
||||
super(opcode, pp, mmmmm, w, op, assertion);
|
||||
}
|
||||
|
||||
@ -1210,12 +1213,12 @@ public class AMD64Assembler extends AMD64BaseAssembler {
|
||||
*/
|
||||
public static class VexRVMROp extends VexOp {
|
||||
// @formatter:off
|
||||
public static final VexRVMROp VPBLENDVB = new VexRVMROp("VPBLENDVB", P_66, M_0F3A, W0, 0x4C, AVXOpAssertion.AVX1_2);
|
||||
public static final VexRVMROp VPBLENDVPS = new VexRVMROp("VPBLENDVPS", P_66, M_0F3A, W0, 0x4A, AVXOpAssertion.AVX1);
|
||||
public static final VexRVMROp VPBLENDVPD = new VexRVMROp("VPBLENDVPD", P_66, M_0F3A, W0, 0x4B, AVXOpAssertion.AVX1);
|
||||
public static final VexRVMROp VPBLENDVB = new VexRVMROp("VPBLENDVB", P_66, M_0F3A, W0, 0x4C, VEXOpAssertion.AVX1_2);
|
||||
public static final VexRVMROp VPBLENDVPS = new VexRVMROp("VPBLENDVPS", P_66, M_0F3A, W0, 0x4A, VEXOpAssertion.AVX1);
|
||||
public static final VexRVMROp VPBLENDVPD = new VexRVMROp("VPBLENDVPD", P_66, M_0F3A, W0, 0x4B, VEXOpAssertion.AVX1);
|
||||
// @formatter:on
|
||||
|
||||
protected VexRVMROp(String opcode, int pp, int mmmmm, int w, int op, AVXOpAssertion assertion) {
|
||||
protected VexRVMROp(String opcode, int pp, int mmmmm, int w, int op, VEXOpAssertion assertion) {
|
||||
super(opcode, pp, mmmmm, w, op, assertion);
|
||||
}
|
||||
|
||||
@ -1275,43 +1278,43 @@ public class AMD64Assembler extends AMD64BaseAssembler {
|
||||
public static final VexRVMOp VMAXSD = new VexRVMOp("VMAXSD", P_F2, M_0F, WIG, 0x5F);
|
||||
public static final VexRVMOp VADDSUBPS = new VexRVMOp("VADDSUBPS", P_F2, M_0F, WIG, 0xD0);
|
||||
public static final VexRVMOp VADDSUBPD = new VexRVMOp("VADDSUBPD", P_66, M_0F, WIG, 0xD0);
|
||||
public static final VexRVMOp VPAND = new VexRVMOp("VPAND", P_66, M_0F, WIG, 0xDB, AVXOpAssertion.AVX1_2);
|
||||
public static final VexRVMOp VPOR = new VexRVMOp("VPOR", P_66, M_0F, WIG, 0xEB, AVXOpAssertion.AVX1_2);
|
||||
public static final VexRVMOp VPXOR = new VexRVMOp("VPXOR", P_66, M_0F, WIG, 0xEF, AVXOpAssertion.AVX1_2);
|
||||
public static final VexRVMOp VPADDB = new VexRVMOp("VPADDB", P_66, M_0F, WIG, 0xFC, AVXOpAssertion.AVX1_2);
|
||||
public static final VexRVMOp VPADDW = new VexRVMOp("VPADDW", P_66, M_0F, WIG, 0xFD, AVXOpAssertion.AVX1_2);
|
||||
public static final VexRVMOp VPADDD = new VexRVMOp("VPADDD", P_66, M_0F, WIG, 0xFE, AVXOpAssertion.AVX1_2);
|
||||
public static final VexRVMOp VPADDQ = new VexRVMOp("VPADDQ", P_66, M_0F, WIG, 0xD4, AVXOpAssertion.AVX1_2);
|
||||
public static final VexRVMOp VPMULHUW = new VexRVMOp("VPMULHUW", P_66, M_0F, WIG, 0xE4, AVXOpAssertion.AVX1_2);
|
||||
public static final VexRVMOp VPMULHW = new VexRVMOp("VPMULHW", P_66, M_0F, WIG, 0xE5, AVXOpAssertion.AVX1_2);
|
||||
public static final VexRVMOp VPMULLW = new VexRVMOp("VPMULLW", P_66, M_0F, WIG, 0xD5, AVXOpAssertion.AVX1_2);
|
||||
public static final VexRVMOp VPMULLD = new VexRVMOp("VPMULLD", P_66, M_0F38, WIG, 0x40, AVXOpAssertion.AVX1_2);
|
||||
public static final VexRVMOp VPSUBB = new VexRVMOp("VPSUBB", P_66, M_0F, WIG, 0xF8, AVXOpAssertion.AVX1_2);
|
||||
public static final VexRVMOp VPSUBW = new VexRVMOp("VPSUBW", P_66, M_0F, WIG, 0xF9, AVXOpAssertion.AVX1_2);
|
||||
public static final VexRVMOp VPSUBD = new VexRVMOp("VPSUBD", P_66, M_0F, WIG, 0xFA, AVXOpAssertion.AVX1_2);
|
||||
public static final VexRVMOp VPSUBQ = new VexRVMOp("VPSUBQ", P_66, M_0F, WIG, 0xFB, AVXOpAssertion.AVX1_2);
|
||||
public static final VexRVMOp VPSHUFB = new VexRVMOp("VPSHUFB", P_66, M_0F38, WIG, 0x00, AVXOpAssertion.AVX1_2);
|
||||
public static final VexRVMOp VPAND = new VexRVMOp("VPAND", P_66, M_0F, WIG, 0xDB, VEXOpAssertion.AVX1_2);
|
||||
public static final VexRVMOp VPOR = new VexRVMOp("VPOR", P_66, M_0F, WIG, 0xEB, VEXOpAssertion.AVX1_2);
|
||||
public static final VexRVMOp VPXOR = new VexRVMOp("VPXOR", P_66, M_0F, WIG, 0xEF, VEXOpAssertion.AVX1_2);
|
||||
public static final VexRVMOp VPADDB = new VexRVMOp("VPADDB", P_66, M_0F, WIG, 0xFC, VEXOpAssertion.AVX1_2);
|
||||
public static final VexRVMOp VPADDW = new VexRVMOp("VPADDW", P_66, M_0F, WIG, 0xFD, VEXOpAssertion.AVX1_2);
|
||||
public static final VexRVMOp VPADDD = new VexRVMOp("VPADDD", P_66, M_0F, WIG, 0xFE, VEXOpAssertion.AVX1_2);
|
||||
public static final VexRVMOp VPADDQ = new VexRVMOp("VPADDQ", P_66, M_0F, WIG, 0xD4, VEXOpAssertion.AVX1_2);
|
||||
public static final VexRVMOp VPMULHUW = new VexRVMOp("VPMULHUW", P_66, M_0F, WIG, 0xE4, VEXOpAssertion.AVX1_2);
|
||||
public static final VexRVMOp VPMULHW = new VexRVMOp("VPMULHW", P_66, M_0F, WIG, 0xE5, VEXOpAssertion.AVX1_2);
|
||||
public static final VexRVMOp VPMULLW = new VexRVMOp("VPMULLW", P_66, M_0F, WIG, 0xD5, VEXOpAssertion.AVX1_2);
|
||||
public static final VexRVMOp VPMULLD = new VexRVMOp("VPMULLD", P_66, M_0F38, WIG, 0x40, VEXOpAssertion.AVX1_2);
|
||||
public static final VexRVMOp VPSUBB = new VexRVMOp("VPSUBB", P_66, M_0F, WIG, 0xF8, VEXOpAssertion.AVX1_2);
|
||||
public static final VexRVMOp VPSUBW = new VexRVMOp("VPSUBW", P_66, M_0F, WIG, 0xF9, VEXOpAssertion.AVX1_2);
|
||||
public static final VexRVMOp VPSUBD = new VexRVMOp("VPSUBD", P_66, M_0F, WIG, 0xFA, VEXOpAssertion.AVX1_2);
|
||||
public static final VexRVMOp VPSUBQ = new VexRVMOp("VPSUBQ", P_66, M_0F, WIG, 0xFB, VEXOpAssertion.AVX1_2);
|
||||
public static final VexRVMOp VPSHUFB = new VexRVMOp("VPSHUFB", P_66, M_0F38, WIG, 0x00, VEXOpAssertion.AVX1_2);
|
||||
public static final VexRVMOp VCVTSD2SS = new VexRVMOp("VCVTSD2SS", P_F2, M_0F, WIG, 0x5A);
|
||||
public static final VexRVMOp VCVTSS2SD = new VexRVMOp("VCVTSS2SD", P_F3, M_0F, WIG, 0x5A);
|
||||
public static final VexRVMOp VCVTSI2SD = new VexRVMOp("VCVTSI2SD", P_F2, M_0F, W0, 0x2A, AVXOpAssertion.XMM_XMM_CPU);
|
||||
public static final VexRVMOp VCVTSQ2SD = new VexRVMOp("VCVTSQ2SD", P_F2, M_0F, W1, 0x2A, AVXOpAssertion.XMM_XMM_CPU);
|
||||
public static final VexRVMOp VCVTSI2SS = new VexRVMOp("VCVTSI2SS", P_F3, M_0F, W0, 0x2A, AVXOpAssertion.XMM_XMM_CPU);
|
||||
public static final VexRVMOp VCVTSQ2SS = new VexRVMOp("VCVTSQ2SS", P_F3, M_0F, W1, 0x2A, AVXOpAssertion.XMM_XMM_CPU);
|
||||
public static final VexRVMOp VPCMPEQB = new VexRVMOp("VPCMPEQB", P_66, M_0F, WIG, 0x74, AVXOpAssertion.AVX1_2);
|
||||
public static final VexRVMOp VPCMPEQW = new VexRVMOp("VPCMPEQW", P_66, M_0F, WIG, 0x75, AVXOpAssertion.AVX1_2);
|
||||
public static final VexRVMOp VPCMPEQD = new VexRVMOp("VPCMPEQD", P_66, M_0F, WIG, 0x76, AVXOpAssertion.AVX1_2);
|
||||
public static final VexRVMOp VPCMPEQQ = new VexRVMOp("VPCMPEQQ", P_66, M_0F38, WIG, 0x29, AVXOpAssertion.AVX1_2);
|
||||
public static final VexRVMOp VPCMPGTB = new VexRVMOp("VPCMPGTB", P_66, M_0F, WIG, 0x64, AVXOpAssertion.AVX1_2);
|
||||
public static final VexRVMOp VPCMPGTW = new VexRVMOp("VPCMPGTW", P_66, M_0F, WIG, 0x65, AVXOpAssertion.AVX1_2);
|
||||
public static final VexRVMOp VPCMPGTD = new VexRVMOp("VPCMPGTD", P_66, M_0F, WIG, 0x66, AVXOpAssertion.AVX1_2);
|
||||
public static final VexRVMOp VPCMPGTQ = new VexRVMOp("VPCMPGTQ", P_66, M_0F38, WIG, 0x37, AVXOpAssertion.AVX1_2);
|
||||
public static final VexRVMOp VCVTSI2SD = new VexRVMOp("VCVTSI2SD", P_F2, M_0F, W0, 0x2A, VEXOpAssertion.XMM_XMM_CPU);
|
||||
public static final VexRVMOp VCVTSQ2SD = new VexRVMOp("VCVTSQ2SD", P_F2, M_0F, W1, 0x2A, VEXOpAssertion.XMM_XMM_CPU);
|
||||
public static final VexRVMOp VCVTSI2SS = new VexRVMOp("VCVTSI2SS", P_F3, M_0F, W0, 0x2A, VEXOpAssertion.XMM_XMM_CPU);
|
||||
public static final VexRVMOp VCVTSQ2SS = new VexRVMOp("VCVTSQ2SS", P_F3, M_0F, W1, 0x2A, VEXOpAssertion.XMM_XMM_CPU);
|
||||
public static final VexRVMOp VPCMPEQB = new VexRVMOp("VPCMPEQB", P_66, M_0F, WIG, 0x74, VEXOpAssertion.AVX1_2);
|
||||
public static final VexRVMOp VPCMPEQW = new VexRVMOp("VPCMPEQW", P_66, M_0F, WIG, 0x75, VEXOpAssertion.AVX1_2);
|
||||
public static final VexRVMOp VPCMPEQD = new VexRVMOp("VPCMPEQD", P_66, M_0F, WIG, 0x76, VEXOpAssertion.AVX1_2);
|
||||
public static final VexRVMOp VPCMPEQQ = new VexRVMOp("VPCMPEQQ", P_66, M_0F38, WIG, 0x29, VEXOpAssertion.AVX1_2);
|
||||
public static final VexRVMOp VPCMPGTB = new VexRVMOp("VPCMPGTB", P_66, M_0F, WIG, 0x64, VEXOpAssertion.AVX1_2);
|
||||
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);
|
||||
// @formatter:on
|
||||
|
||||
private VexRVMOp(String opcode, int pp, int mmmmm, int w, int op) {
|
||||
this(opcode, pp, mmmmm, w, op, AVXOpAssertion.AVX1);
|
||||
this(opcode, pp, mmmmm, w, op, VEXOpAssertion.AVX1);
|
||||
}
|
||||
|
||||
protected VexRVMOp(String opcode, int pp, int mmmmm, int w, int op, AVXOpAssertion assertion) {
|
||||
protected VexRVMOp(String opcode, int pp, int mmmmm, int w, int op, VEXOpAssertion assertion) {
|
||||
super(opcode, pp, mmmmm, w, op, assertion);
|
||||
}
|
||||
|
||||
@ -1330,6 +1333,65 @@ public class AMD64Assembler extends AMD64BaseAssembler {
|
||||
}
|
||||
}
|
||||
|
||||
public static final class VexGeneralPurposeRVMOp extends VexOp {
|
||||
// @formatter:off
|
||||
public static final VexGeneralPurposeRVMOp ANDN = new VexGeneralPurposeRVMOp("ANDN", P_, M_0F38, WIG, 0xF2, VEXOpAssertion.BMI1);
|
||||
public static final VexGeneralPurposeRVMOp MULX = new VexGeneralPurposeRVMOp("MULX", P_F2, M_0F38, WIG, 0xF6, VEXOpAssertion.BMI2);
|
||||
public static final VexGeneralPurposeRVMOp PDEP = new VexGeneralPurposeRVMOp("PDEP", P_F2, M_0F38, WIG, 0xF5, VEXOpAssertion.BMI2);
|
||||
public static final VexGeneralPurposeRVMOp PEXT = new VexGeneralPurposeRVMOp("PEXT", P_F3, M_0F38, WIG, 0xF5, VEXOpAssertion.BMI2);
|
||||
// @formatter:on
|
||||
|
||||
private VexGeneralPurposeRVMOp(String opcode, int pp, int mmmmm, int w, int op, VEXOpAssertion assertion) {
|
||||
super(opcode, pp, mmmmm, w, op, assertion);
|
||||
}
|
||||
|
||||
public void emit(AMD64Assembler asm, AVXSize size, Register dst, Register src1, Register src2) {
|
||||
assert assertion.check((AMD64) asm.target.arch, LZ, dst, src1, src2, null);
|
||||
assert size == AVXSize.DWORD || size == AVXSize.QWORD;
|
||||
asm.vexPrefix(dst, src1, src2, size, pp, mmmmm, size == AVXSize.DWORD ? W0 : W1);
|
||||
asm.emitByte(op);
|
||||
asm.emitModRM(dst, src2);
|
||||
}
|
||||
|
||||
public void emit(AMD64Assembler asm, AVXSize size, Register dst, Register src1, AMD64Address src2) {
|
||||
assert assertion.check((AMD64) asm.target.arch, LZ, dst, src1, null, null);
|
||||
assert size == AVXSize.DWORD || size == AVXSize.QWORD;
|
||||
asm.vexPrefix(dst, src1, src2, size, pp, mmmmm, size == AVXSize.DWORD ? W0 : W1);
|
||||
asm.emitByte(op);
|
||||
asm.emitOperandHelper(dst, src2, 0);
|
||||
}
|
||||
}
|
||||
|
||||
public static final class VexGeneralPurposeRMVOp extends VexOp {
|
||||
// @formatter:off
|
||||
public static final VexGeneralPurposeRMVOp BEXTR = new VexGeneralPurposeRMVOp("BEXTR", P_, M_0F38, WIG, 0xF7, VEXOpAssertion.BMI1);
|
||||
public static final VexGeneralPurposeRMVOp BZHI = new VexGeneralPurposeRMVOp("BZHI", P_, M_0F38, WIG, 0xF5, VEXOpAssertion.BMI2);
|
||||
public static final VexGeneralPurposeRMVOp SARX = new VexGeneralPurposeRMVOp("SARX", P_F3, M_0F38, WIG, 0xF7, VEXOpAssertion.BMI2);
|
||||
public static final VexGeneralPurposeRMVOp SHRX = new VexGeneralPurposeRMVOp("SHRX", P_F2, M_0F38, WIG, 0xF7, VEXOpAssertion.BMI2);
|
||||
public static final VexGeneralPurposeRMVOp SHLX = new VexGeneralPurposeRMVOp("SHLX", P_66, M_0F38, WIG, 0xF7, VEXOpAssertion.BMI2);
|
||||
// @formatter:on
|
||||
|
||||
private VexGeneralPurposeRMVOp(String opcode, int pp, int mmmmm, int w, int op, VEXOpAssertion assertion) {
|
||||
super(opcode, pp, mmmmm, w, op, assertion);
|
||||
}
|
||||
|
||||
public void emit(AMD64Assembler asm, AVXSize size, Register dst, Register src1, Register src2) {
|
||||
assert assertion.check((AMD64) asm.target.arch, LZ, dst, src2, src1, null);
|
||||
assert size == AVXSize.DWORD || size == AVXSize.QWORD;
|
||||
asm.vexPrefix(dst, src2, src1, size, pp, mmmmm, size == AVXSize.DWORD ? W0 : W1);
|
||||
asm.emitByte(op);
|
||||
asm.emitModRM(dst, src1);
|
||||
}
|
||||
|
||||
public void emit(AMD64Assembler asm, AVXSize size, Register dst, AMD64Address src1, Register src2) {
|
||||
assert assertion.check((AMD64) asm.target.arch, LZ, dst, src2, null, null);
|
||||
assert size == AVXSize.DWORD || size == AVXSize.QWORD;
|
||||
asm.vexPrefix(dst, src2, src1, size, pp, mmmmm, size == AVXSize.DWORD ? W0 : W1);
|
||||
asm.emitByte(op);
|
||||
asm.emitOperandHelper(dst, src1, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* VEX-encoded shift instructions with an operand order of either RVM or VMI.
|
||||
*/
|
||||
@ -1349,7 +1411,7 @@ public class AMD64Assembler extends AMD64BaseAssembler {
|
||||
private final int r;
|
||||
|
||||
private VexShiftOp(String opcode, int pp, int mmmmm, int w, int op, int immOp, int r) {
|
||||
super(opcode, pp, mmmmm, w, op, AVXOpAssertion.AVX1_2);
|
||||
super(opcode, pp, mmmmm, w, op, VEXOpAssertion.AVX1_2);
|
||||
this.immOp = immOp;
|
||||
this.r = r;
|
||||
}
|
||||
@ -1368,17 +1430,17 @@ public class AMD64Assembler extends AMD64BaseAssembler {
|
||||
// @formatter:off
|
||||
public static final VexMaskMoveOp VMASKMOVPS = new VexMaskMoveOp("VMASKMOVPS", P_66, M_0F38, W0, 0x2C, 0x2E);
|
||||
public static final VexMaskMoveOp VMASKMOVPD = new VexMaskMoveOp("VMASKMOVPD", P_66, M_0F38, W0, 0x2D, 0x2F);
|
||||
public static final VexMaskMoveOp VPMASKMOVD = new VexMaskMoveOp("VPMASKMOVD", P_66, M_0F38, W0, 0x8C, 0x8E, AVXOpAssertion.AVX2);
|
||||
public static final VexMaskMoveOp VPMASKMOVQ = new VexMaskMoveOp("VPMASKMOVQ", P_66, M_0F38, W1, 0x8C, 0x8E, AVXOpAssertion.AVX2);
|
||||
public static final VexMaskMoveOp VPMASKMOVD = new VexMaskMoveOp("VPMASKMOVD", P_66, M_0F38, W0, 0x8C, 0x8E, VEXOpAssertion.AVX2);
|
||||
public static final VexMaskMoveOp VPMASKMOVQ = new VexMaskMoveOp("VPMASKMOVQ", P_66, M_0F38, W1, 0x8C, 0x8E, VEXOpAssertion.AVX2);
|
||||
// @formatter:on
|
||||
|
||||
private final int opReverse;
|
||||
|
||||
private VexMaskMoveOp(String opcode, int pp, int mmmmm, int w, int op, int opReverse) {
|
||||
this(opcode, pp, mmmmm, w, op, opReverse, AVXOpAssertion.AVX1);
|
||||
this(opcode, pp, mmmmm, w, op, opReverse, VEXOpAssertion.AVX1);
|
||||
}
|
||||
|
||||
private VexMaskMoveOp(String opcode, int pp, int mmmmm, int w, int op, int opReverse, AVXOpAssertion assertion) {
|
||||
private VexMaskMoveOp(String opcode, int pp, int mmmmm, int w, int op, int opReverse, VEXOpAssertion assertion) {
|
||||
super(opcode, pp, mmmmm, w, op, assertion);
|
||||
this.opReverse = opReverse;
|
||||
}
|
||||
@ -1405,15 +1467,15 @@ public class AMD64Assembler extends AMD64BaseAssembler {
|
||||
// @formatter:off
|
||||
public static final VexRVMIOp VSHUFPS = new VexRVMIOp("VSHUFPS", P_, M_0F, WIG, 0xC6);
|
||||
public static final VexRVMIOp VSHUFPD = new VexRVMIOp("VSHUFPD", P_66, M_0F, WIG, 0xC6);
|
||||
public static final VexRVMIOp VINSERTF128 = new VexRVMIOp("VINSERTF128", P_66, M_0F3A, W0, 0x18, AVXOpAssertion.AVX1_256ONLY);
|
||||
public static final VexRVMIOp VINSERTI128 = new VexRVMIOp("VINSERTI128", P_66, M_0F3A, W0, 0x38, AVXOpAssertion.AVX2_256ONLY);
|
||||
public static final VexRVMIOp VINSERTF128 = new VexRVMIOp("VINSERTF128", P_66, M_0F3A, W0, 0x18, VEXOpAssertion.AVX1_256ONLY);
|
||||
public static final VexRVMIOp VINSERTI128 = new VexRVMIOp("VINSERTI128", P_66, M_0F3A, W0, 0x38, VEXOpAssertion.AVX2_256ONLY);
|
||||
// @formatter:on
|
||||
|
||||
private VexRVMIOp(String opcode, int pp, int mmmmm, int w, int op) {
|
||||
this(opcode, pp, mmmmm, w, op, AVXOpAssertion.AVX1);
|
||||
this(opcode, pp, mmmmm, w, op, VEXOpAssertion.AVX1);
|
||||
}
|
||||
|
||||
private VexRVMIOp(String opcode, int pp, int mmmmm, int w, int op, AVXOpAssertion assertion) {
|
||||
private VexRVMIOp(String opcode, int pp, int mmmmm, int w, int op, VEXOpAssertion assertion) {
|
||||
super(opcode, pp, mmmmm, w, op, assertion);
|
||||
}
|
||||
|
||||
@ -1528,7 +1590,7 @@ public class AMD64Assembler extends AMD64BaseAssembler {
|
||||
}
|
||||
|
||||
private VexFloatCompareOp(String opcode, int pp, int mmmmm, int w, int op) {
|
||||
super(opcode, pp, mmmmm, w, op, AVXOpAssertion.AVX1);
|
||||
super(opcode, pp, mmmmm, w, op, VEXOpAssertion.AVX1);
|
||||
}
|
||||
|
||||
public void emit(AMD64Assembler asm, AVXSize size, Register dst, Register src1, Register src2, Predicate p) {
|
||||
|
@ -37,7 +37,7 @@ import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.EVEXPrefixConfig
|
||||
import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.EVEXPrefixConfig.Z1;
|
||||
import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.VEXPrefixConfig.L128;
|
||||
import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.VEXPrefixConfig.L256;
|
||||
import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.VEXPrefixConfig.LIG;
|
||||
import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.VEXPrefixConfig.LZ;
|
||||
import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.VEXPrefixConfig.M_0F;
|
||||
import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.VEXPrefixConfig.M_0F38;
|
||||
import static org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.VEXPrefixConfig.M_0F3A;
|
||||
@ -748,7 +748,7 @@ public abstract class AMD64BaseAssembler extends Assembler {
|
||||
public static final class VEXPrefixConfig {
|
||||
public static final int L128 = 0;
|
||||
public static final int L256 = 1;
|
||||
public static final int LIG = 0;
|
||||
public static final int LZ = 0;
|
||||
|
||||
public static final int W0 = 0;
|
||||
public static final int W1 = 1;
|
||||
@ -849,10 +849,10 @@ public abstract class AMD64BaseAssembler extends Assembler {
|
||||
protected final void emitVEX(int l, int pp, int mmmmm, int w, int rxb, int vvvv) {
|
||||
assert ((AMD64) target.arch).getFeatures().contains(CPUFeature.AVX) : "emitting VEX prefix on a CPU without AVX support";
|
||||
|
||||
assert l == L128 || l == L256 || l == LIG : "invalid value for VEX.L";
|
||||
assert l == L128 || l == L256 : "invalid value for VEX.L";
|
||||
assert pp == P_ || pp == P_66 || pp == P_F3 || pp == P_F2 : "invalid value for VEX.pp";
|
||||
assert mmmmm == M_0F || mmmmm == M_0F38 || mmmmm == M_0F3A : "invalid value for VEX.m-mmmm";
|
||||
assert w == W0 || w == W1 || w == WIG : "invalid value for VEX.W";
|
||||
assert w == W0 || w == W1 : "invalid value for VEX.W";
|
||||
|
||||
assert (rxb & 0x07) == rxb : "invalid value for VEX.RXB";
|
||||
assert (vvvv & 0x0F) == vvvv : "invalid value for VEX.vvvv";
|
||||
@ -887,7 +887,7 @@ public abstract class AMD64BaseAssembler extends Assembler {
|
||||
}
|
||||
}
|
||||
|
||||
private static int getLFlag(AVXSize size) {
|
||||
public static int getLFlag(AVXSize size) {
|
||||
switch (size) {
|
||||
case XMM:
|
||||
return L128;
|
||||
@ -896,7 +896,7 @@ public abstract class AMD64BaseAssembler extends Assembler {
|
||||
case ZMM:
|
||||
return L512;
|
||||
default:
|
||||
return LIG;
|
||||
return LZ;
|
||||
}
|
||||
}
|
||||
|
||||
@ -910,6 +910,7 @@ public abstract class AMD64BaseAssembler extends Assembler {
|
||||
|
||||
protected static final class EVEXPrefixConfig {
|
||||
public static final int L512 = 2;
|
||||
public static final int LIG = 0;
|
||||
|
||||
public static final int Z0 = 0x0;
|
||||
public static final int Z1 = 0x1;
|
||||
@ -1013,10 +1014,10 @@ public abstract class AMD64BaseAssembler extends Assembler {
|
||||
private void emitEVEX(int l, int pp, int mm, int w, int rxb, int reg, int vvvvv, int z, int b, int aaa) {
|
||||
assert ((AMD64) target.arch).getFeatures().contains(CPUFeature.AVX512F) : "emitting EVEX prefix on a CPU without AVX512 support";
|
||||
|
||||
assert l == L128 || l == L256 || l == L512 || l == LIG : "invalid value for EVEX.L'L";
|
||||
assert l == L128 || l == L256 || l == L512 : "invalid value for EVEX.L'L";
|
||||
assert pp == P_ || pp == P_66 || pp == P_F3 || pp == P_F2 : "invalid value for EVEX.pp";
|
||||
assert mm == M_0F || mm == M_0F38 || mm == M_0F3A : "invalid value for EVEX.mm";
|
||||
assert w == W0 || w == W1 || w == WIG : "invalid value for EVEX.W";
|
||||
assert w == W0 || w == W1 : "invalid value for EVEX.W";
|
||||
|
||||
assert (rxb & 0x07) == rxb : "invalid value for EVEX.RXB";
|
||||
assert (reg & 0x1F) == reg : "invalid value for EVEX.R'";
|
||||
|
@ -41,6 +41,7 @@ import java.util.concurrent.TimeUnit;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
import org.graalvm.compiler.api.replacements.MethodSubstitution;
|
||||
import org.graalvm.compiler.api.replacements.Snippet;
|
||||
import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter;
|
||||
import org.graalvm.compiler.api.replacements.Snippet.NonNullParameter;
|
||||
@ -279,7 +280,8 @@ public class CheckGraalInvariants extends GraalCompilerTest {
|
||||
executor.execute(() -> {
|
||||
try (DebugContext debug = DebugContext.create(options, DebugHandlersFactory.LOADER)) {
|
||||
ResolvedJavaMethod method = metaAccess.lookupJavaMethod(m);
|
||||
StructuredGraph graph = new StructuredGraph.Builder(options, debug).method(method).build();
|
||||
boolean isSubstitution = method.getAnnotation(Snippet.class) != null || method.getAnnotation(MethodSubstitution.class) != null;
|
||||
StructuredGraph graph = new StructuredGraph.Builder(options, debug).method(method).setIsSubstitution(isSubstitution).build();
|
||||
try (DebugCloseable s = debug.disableIntercept(); DebugContext.Scope ds = debug.scope("CheckingGraph", graph, method)) {
|
||||
checkMethod(method);
|
||||
graphBuilderSuite.apply(graph, context);
|
||||
|
@ -0,0 +1,164 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 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 java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.lang.reflect.Constructor;
|
||||
|
||||
import org.graalvm.compiler.java.GraphBuilderPhase;
|
||||
import org.graalvm.compiler.nodes.DeoptimizeNode;
|
||||
import org.graalvm.compiler.nodes.StructuredGraph;
|
||||
import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
|
||||
import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
|
||||
import org.graalvm.compiler.nodes.java.NewInstanceNode;
|
||||
import org.graalvm.compiler.options.OptionValues;
|
||||
import org.graalvm.compiler.phases.OptimisticOptimizations;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import jdk.vm.ci.meta.ResolvedJavaMethod;
|
||||
|
||||
public class NewInstanceTest extends GraalCompilerTest {
|
||||
public static class Template {
|
||||
public Object o = new CCCC();
|
||||
}
|
||||
|
||||
/**
|
||||
* 1. Concrete class, should produce normal {@link NewInstanceNode}
|
||||
*/
|
||||
public static class CCCC {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 2. The test will replace references to {@link CCCC} in the {@link Template} to {@link AAAA}
|
||||
*/
|
||||
public abstract static class AAAA {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 3. The test will replace references to {@link CCCC} in the {@link Template} to {@link IIII}
|
||||
*/
|
||||
public interface IIII {
|
||||
|
||||
}
|
||||
|
||||
private StructuredGraph parseAndProcess(Class<?> cl) {
|
||||
Constructor<?>[] constructors = cl.getConstructors();
|
||||
Assert.assertTrue(constructors.length == 1);
|
||||
final ResolvedJavaMethod javaMethod = getMetaAccess().lookupJavaMethod(constructors[0]);
|
||||
OptionValues options = getInitialOptions();
|
||||
StructuredGraph graph = new StructuredGraph.Builder(options, getDebugContext(options, null, javaMethod), AllowAssumptions.YES).method(javaMethod).build();
|
||||
|
||||
GraphBuilderConfiguration conf = GraphBuilderConfiguration.getSnippetDefault(getDefaultGraphBuilderPlugins()).withUnresolvedIsError(false);
|
||||
new GraphBuilderPhase.Instance(getMetaAccess(), getProviders().getStampProvider(), getProviders().getConstantReflection(), getProviders().getConstantFieldProvider(), conf,
|
||||
OptimisticOptimizations.ALL, null).apply(graph);
|
||||
return graph;
|
||||
}
|
||||
|
||||
private void checkGraph(Class<?> cl, int newInstanceNodeCount, int deoptimizeNodeCount) {
|
||||
StructuredGraph graph = parseAndProcess(cl);
|
||||
Assert.assertEquals(newInstanceNodeCount, graph.getNodes().filter(NewInstanceNode.class).count());
|
||||
Assert.assertEquals(deoptimizeNodeCount, graph.getNodes().filter(DeoptimizeNode.class).count());
|
||||
}
|
||||
|
||||
/**
|
||||
* Use a custom class loader to generate classes, substitute class names at the allocation site.
|
||||
*/
|
||||
@Test
|
||||
public void test1() throws ClassNotFoundException {
|
||||
checkGraph(Template.class, 1, 0);
|
||||
ClassTemplateLoader loader1 = new ClassTemplateLoader("CCCC", "AAAA");
|
||||
checkGraph(loader1.findClass("Template"), 0, 1);
|
||||
ClassTemplateLoader loader2 = new ClassTemplateLoader("CCCC", "IIII");
|
||||
checkGraph(loader2.findClass("Template"), 0, 1);
|
||||
}
|
||||
|
||||
private static class ClassTemplateLoader extends ClassLoader {
|
||||
private final String find;
|
||||
private final String replace;
|
||||
|
||||
ClassTemplateLoader(String find, String replace) {
|
||||
assert find.length() == replace.length();
|
||||
this.find = find;
|
||||
this.replace = replace;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?> findClass(final String name) throws ClassNotFoundException {
|
||||
// copy classfile to byte array
|
||||
byte[] classData = null;
|
||||
try {
|
||||
InputStream is = NewInstanceTest.class.getResourceAsStream("NewInstanceTest$" + name + ".class");
|
||||
assert is != null;
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
|
||||
byte[] buf = new byte[1024];
|
||||
int size;
|
||||
while ((size = is.read(buf, 0, buf.length)) != -1) {
|
||||
baos.write(buf, 0, size);
|
||||
}
|
||||
baos.flush();
|
||||
classData = baos.toByteArray();
|
||||
} catch (IOException e) {
|
||||
Assert.fail("can't access class: " + name);
|
||||
}
|
||||
|
||||
// replace all occurrences of the template in classfile
|
||||
int index = -1;
|
||||
while ((index = indexOfTemplate(classData, index + 1, find)) != -1) {
|
||||
replaceTemplate(classData, index, replace);
|
||||
}
|
||||
|
||||
Class<?> c = defineClass(null, classData, 0, classData.length);
|
||||
return c;
|
||||
}
|
||||
|
||||
private static int indexOfTemplate(byte[] b, int index, String find) {
|
||||
for (int i = index; i < b.length; i++) {
|
||||
boolean match = true;
|
||||
for (int j = i; j < i + find.length(); j++) {
|
||||
if (b[j] != (byte) find.charAt(j - i)) {
|
||||
match = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (match) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
private static void replaceTemplate(byte[] b, int index, String replace) {
|
||||
for (int i = index; i < index + replace.length(); i++) {
|
||||
b[i] = (byte) replace.charAt(i - index);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -27,6 +27,7 @@ package org.graalvm.compiler.core.test.ea;
|
||||
import java.util.List;
|
||||
|
||||
import org.graalvm.compiler.graph.Node;
|
||||
import org.graalvm.compiler.graph.iterators.NodeIterable;
|
||||
import org.graalvm.compiler.loop.DefaultLoopPolicies;
|
||||
import org.graalvm.compiler.loop.phases.LoopFullUnrollPhase;
|
||||
import org.graalvm.compiler.loop.phases.LoopPeelingPhase;
|
||||
@ -492,4 +493,21 @@ public class EscapeAnalysisTest extends EATestBase {
|
||||
public void testDeoptMonitor() {
|
||||
test("testDeoptMonitorSnippet", new Object(), 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInterfaceArrayAssignment() {
|
||||
prepareGraph("testInterfaceArrayAssignmentSnippet", false);
|
||||
NodeIterable<ReturnNode> returns = graph.getNodes().filter(ReturnNode.class);
|
||||
assertTrue(returns.count() == 1);
|
||||
assertFalse(returns.first().result().isConstant());
|
||||
}
|
||||
|
||||
private interface TestInterface {
|
||||
}
|
||||
|
||||
public static boolean testInterfaceArrayAssignmentSnippet() {
|
||||
Object[] array = new TestInterface[1];
|
||||
array[0] = new Object();
|
||||
return array[0] == null;
|
||||
}
|
||||
}
|
||||
|
@ -41,6 +41,7 @@ import java.io.IOException;
|
||||
import java.io.PrintStream;
|
||||
import java.util.Map;
|
||||
|
||||
import org.graalvm.compiler.debug.DebugCloseable;
|
||||
import org.graalvm.compiler.debug.DebugContext;
|
||||
import org.graalvm.compiler.debug.DiagnosticsOutputDirectory;
|
||||
import org.graalvm.compiler.debug.PathUtilities;
|
||||
@ -181,15 +182,64 @@ public abstract class CompilationWrapper<T> {
|
||||
actionKey = CompilationFailureAction;
|
||||
causeType = "failure";
|
||||
}
|
||||
ExceptionAction action = lookupAction(initialOptions, actionKey, cause);
|
||||
synchronized (CompilationFailureAction) {
|
||||
// Serialize all compilation failure handling.
|
||||
// This prevents retry compilation storms and interleaving
|
||||
// of compilation exception messages.
|
||||
// It also allows for reliable testing of CompilationWrapper
|
||||
// by avoiding a race whereby retry compilation output from a
|
||||
// forced crash (i.e., use of GraalCompilerOptions.CrashAt)
|
||||
// is truncated.
|
||||
|
||||
action = adjustAction(initialOptions, actionKey, action);
|
||||
ExceptionAction action = lookupAction(initialOptions, actionKey, cause);
|
||||
|
||||
if (action == ExceptionAction.Silent) {
|
||||
return handleException(cause);
|
||||
}
|
||||
action = adjustAction(initialOptions, actionKey, action);
|
||||
|
||||
if (action == ExceptionAction.Print) {
|
||||
if (action == ExceptionAction.Silent) {
|
||||
return handleException(cause);
|
||||
}
|
||||
|
||||
if (action == ExceptionAction.Print) {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
try (PrintStream ps = new PrintStream(baos)) {
|
||||
ps.printf("%s: Compilation of %s failed: ", Thread.currentThread(), this);
|
||||
cause.printStackTrace(ps);
|
||||
ps.printf("To disable compilation %s notifications, set %s to %s (e.g., -Dgraal.%s=%s).%n",
|
||||
causeType,
|
||||
actionKey.getName(), ExceptionAction.Silent,
|
||||
actionKey.getName(), ExceptionAction.Silent);
|
||||
ps.printf("To capture more information for diagnosing or reporting a compilation %s, " +
|
||||
"set %s to %s or %s (e.g., -Dgraal.%s=%s).%n",
|
||||
causeType,
|
||||
actionKey.getName(), ExceptionAction.Diagnose,
|
||||
ExceptionAction.ExitVM,
|
||||
actionKey.getName(), ExceptionAction.Diagnose);
|
||||
}
|
||||
TTY.print(baos.toString());
|
||||
return handleException(cause);
|
||||
}
|
||||
|
||||
// action is Diagnose or ExitVM
|
||||
|
||||
if (Dump.hasBeenSet(initialOptions)) {
|
||||
// If dumping is explicitly enabled, Graal is being debugged
|
||||
// so don't interfere with what the user is expecting to see.
|
||||
return handleException(cause);
|
||||
}
|
||||
|
||||
String dir = this.outputDirectory.getPath();
|
||||
if (dir == null) {
|
||||
return handleException(cause);
|
||||
}
|
||||
String dumpName = PathUtilities.sanitizeFileName(toString());
|
||||
File dumpPath = new File(dir, dumpName);
|
||||
dumpPath.mkdirs();
|
||||
if (!dumpPath.exists()) {
|
||||
TTY.println("Warning: could not create diagnostics directory " + dumpPath);
|
||||
return handleException(cause);
|
||||
}
|
||||
|
||||
String message;
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
try (PrintStream ps = new PrintStream(baos)) {
|
||||
ps.printf("%s: Compilation of %s failed: ", Thread.currentThread(), this);
|
||||
@ -198,63 +248,16 @@ public abstract class CompilationWrapper<T> {
|
||||
causeType,
|
||||
actionKey.getName(), ExceptionAction.Silent,
|
||||
actionKey.getName(), ExceptionAction.Silent);
|
||||
ps.printf("To capture more information for diagnosing or reporting a compilation %s, " +
|
||||
"set %s to %s or %s (e.g., -Dgraal.%s=%s).%n",
|
||||
ps.printf("To print a message for a compilation %s without retrying the compilation, " +
|
||||
"set %s to %s (e.g., -Dgraal.%s=%s).%n",
|
||||
causeType,
|
||||
actionKey.getName(), ExceptionAction.Diagnose,
|
||||
ExceptionAction.ExitVM,
|
||||
actionKey.getName(), ExceptionAction.Diagnose);
|
||||
actionKey.getName(), ExceptionAction.Print,
|
||||
actionKey.getName(), ExceptionAction.Print);
|
||||
ps.println("Retrying compilation of " + this);
|
||||
message = baos.toString();
|
||||
}
|
||||
synchronized (CompilationFailureAction) {
|
||||
// Synchronize to prevent compilation exception
|
||||
// messages from interleaving.
|
||||
TTY.println(baos.toString());
|
||||
}
|
||||
return handleException(cause);
|
||||
}
|
||||
|
||||
// action is Diagnose or ExitVM
|
||||
|
||||
if (Dump.hasBeenSet(initialOptions)) {
|
||||
// If dumping is explicitly enabled, Graal is being debugged
|
||||
// so don't interfere with what the user is expecting to see.
|
||||
return handleException(cause);
|
||||
}
|
||||
|
||||
String dir = this.outputDirectory.getPath();
|
||||
if (dir == null) {
|
||||
return handleException(cause);
|
||||
}
|
||||
String dumpName = PathUtilities.sanitizeFileName(toString());
|
||||
File dumpPath = new File(dir, dumpName);
|
||||
dumpPath.mkdirs();
|
||||
if (!dumpPath.exists()) {
|
||||
TTY.println("Warning: could not create diagnostics directory " + dumpPath);
|
||||
return handleException(cause);
|
||||
}
|
||||
|
||||
String message;
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
try (PrintStream ps = new PrintStream(baos)) {
|
||||
ps.printf("%s: Compilation of %s failed: ", Thread.currentThread(), this);
|
||||
cause.printStackTrace(ps);
|
||||
ps.printf("To disable compilation %s notifications, set %s to %s (e.g., -Dgraal.%s=%s).%n",
|
||||
causeType,
|
||||
actionKey.getName(), ExceptionAction.Silent,
|
||||
actionKey.getName(), ExceptionAction.Silent);
|
||||
ps.printf("To print a message for a compilation %s without retrying the compilation, " +
|
||||
"set %s to %s (e.g., -Dgraal.%s=%s).%n",
|
||||
causeType,
|
||||
actionKey.getName(), ExceptionAction.Print,
|
||||
actionKey.getName(), ExceptionAction.Print);
|
||||
ps.println("Retrying compilation of " + this);
|
||||
message = baos.toString();
|
||||
}
|
||||
|
||||
synchronized (CompilationFailureAction) {
|
||||
// Synchronize here to serialize retry compilations. This
|
||||
// mitigates retry compilation storms.
|
||||
TTY.println(message);
|
||||
TTY.print(message);
|
||||
File retryLogFile = new File(dumpPath, "retry.log");
|
||||
try (PrintStream ps = new PrintStream(new FileOutputStream(retryLogFile))) {
|
||||
ps.print(message);
|
||||
@ -267,7 +270,7 @@ public abstract class CompilationWrapper<T> {
|
||||
MethodFilter, null,
|
||||
DumpPath, dumpPath.getPath());
|
||||
|
||||
try (DebugContext retryDebug = createRetryDebugContext(retryOptions)) {
|
||||
try (DebugContext retryDebug = createRetryDebugContext(retryOptions); DebugCloseable s = retryDebug.disableIntercept()) {
|
||||
T res = performCompilation(retryDebug);
|
||||
maybeExitVM(action);
|
||||
return res;
|
||||
@ -283,16 +286,8 @@ public abstract class CompilationWrapper<T> {
|
||||
|
||||
private void maybeExitVM(ExceptionAction action) {
|
||||
if (action == ExitVM) {
|
||||
synchronized (ExceptionAction.class) {
|
||||
try {
|
||||
// Give other compiler threads a chance to flush
|
||||
// error handling output.
|
||||
ExceptionAction.class.wait(2000);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
TTY.println("Exiting VM after retry compilation of " + this);
|
||||
System.exit(-1);
|
||||
}
|
||||
TTY.println("Exiting VM after retry compilation of " + this);
|
||||
System.exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
@ -303,22 +298,24 @@ public abstract class CompilationWrapper<T> {
|
||||
private ExceptionAction adjustAction(OptionValues initialOptions, EnumOptionKey<ExceptionAction> actionKey, ExceptionAction initialAction) {
|
||||
ExceptionAction action = initialAction;
|
||||
int maxProblems = MaxCompilationProblemsPerAction.getValue(initialOptions);
|
||||
synchronized (problemsHandledPerAction) {
|
||||
while (action != ExceptionAction.Silent) {
|
||||
int problems = problemsHandledPerAction.getOrDefault(action, 0);
|
||||
if (problems >= maxProblems) {
|
||||
if (problems == maxProblems) {
|
||||
TTY.printf("Warning: adjusting %s from %s to %s after %s (%d) failed compilations%n", actionKey, action, action.quieter(),
|
||||
MaxCompilationProblemsPerAction, maxProblems);
|
||||
// Ensure that the message above is only printed once
|
||||
problemsHandledPerAction.put(action, problems + 1);
|
||||
if (action != ExceptionAction.ExitVM) {
|
||||
synchronized (problemsHandledPerAction) {
|
||||
while (action != ExceptionAction.Silent) {
|
||||
int problems = problemsHandledPerAction.getOrDefault(action, 0);
|
||||
if (problems >= maxProblems) {
|
||||
if (problems == maxProblems) {
|
||||
TTY.printf("Warning: adjusting %s from %s to %s after %s (%d) failed compilations%n", actionKey, action, action.quieter(),
|
||||
MaxCompilationProblemsPerAction, maxProblems);
|
||||
// Ensure that the message above is only printed once
|
||||
problemsHandledPerAction.put(action, problems + 1);
|
||||
}
|
||||
action = action.quieter();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
action = action.quieter();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
problemsHandledPerAction.put(action, problemsHandledPerAction.getOrDefault(action, 0) + 1);
|
||||
}
|
||||
problemsHandledPerAction.put(action, problemsHandledPerAction.getOrDefault(action, 0) + 1);
|
||||
}
|
||||
return action;
|
||||
}
|
||||
|
@ -50,7 +50,8 @@ public class GraalCompilerOptions {
|
||||
"The accepted values are the same as for CompilationBailoutAction.", type = OptionType.User)
|
||||
public static final EnumOptionKey<ExceptionAction> CompilationFailureAction = new EnumOptionKey<>(ExceptionAction.Diagnose);
|
||||
@Option(help = "The maximum number of compilation failures or bailouts to handle with the action specified " +
|
||||
"by CompilationFailureAction or CompilationBailoutAction before changing to a less verbose action.", type = OptionType.User)
|
||||
"by CompilationFailureAction or CompilationBailoutAction before changing to a less verbose action. " +
|
||||
"This does not apply to the ExitVM action.", type = OptionType.User)
|
||||
public static final OptionKey<Integer> MaxCompilationProblemsPerAction = new OptionKey<>(2);
|
||||
@Option(help = "Alias for CompilationFailureAction=ExitVM.", type = OptionType.User)
|
||||
public static final OptionKey<Boolean> ExitVMOnException = new OptionKey<>(false);
|
||||
|
@ -27,14 +27,16 @@ package org.graalvm.compiler.debug.test;
|
||||
import static org.graalvm.compiler.debug.DebugContext.NO_DESCRIPTION;
|
||||
import static org.graalvm.compiler.debug.DebugContext.NO_GLOBAL_METRIC_VALUES;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.PrintStream;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Formatter;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import jdk.internal.vm.compiler.collections.EconomicMap;
|
||||
import org.graalvm.compiler.debug.Assertions;
|
||||
@ -158,14 +160,13 @@ public class DebugContextTest {
|
||||
}
|
||||
}
|
||||
}
|
||||
DataInputStream in = new DataInputStream(getClass().getResourceAsStream(getClass().getSimpleName() + ".testLogging.input"));
|
||||
byte[] buf = new byte[in.available()];
|
||||
in.readFully(buf);
|
||||
String threadLabel = "[thread:" + Thread.currentThread().getId() + "]";
|
||||
String expect = new String(buf).replace("[thread:1]", threadLabel);
|
||||
|
||||
String log = setup.logOutput.toString();
|
||||
Assert.assertEquals(expect, log);
|
||||
String expected;
|
||||
try (BufferedReader input = new BufferedReader(new InputStreamReader(getClass().getResourceAsStream(getClass().getSimpleName() + ".testLogging.input")))) {
|
||||
String threadLabel = "[thread:" + Thread.currentThread().getId() + "]";
|
||||
expected = input.lines().collect(Collectors.joining(System.lineSeparator(), "", System.lineSeparator())).replace("[thread:1]", threadLabel);
|
||||
}
|
||||
String logged = setup.logOutput.toString();
|
||||
Assert.assertEquals(expected, logged);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -84,7 +84,10 @@ public class DiagnosticsOutputDirectory {
|
||||
}
|
||||
}
|
||||
}
|
||||
return CLOSED.equals(path) ? null : path;
|
||||
if (CLOSED.equals(path)) {
|
||||
TTY.println("Warning: Graal diagnostic directory already closed");
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -24,8 +24,11 @@
|
||||
|
||||
package org.graalvm.compiler.debug;
|
||||
|
||||
import static java.nio.file.LinkOption.NOFOLLOW_LINKS;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.AccessDeniedException;
|
||||
import java.nio.file.FileAlreadyExistsException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.InvalidPathException;
|
||||
@ -118,7 +121,15 @@ public class PathUtilities {
|
||||
if (createDirectory) {
|
||||
return Files.createDirectory(result);
|
||||
} else {
|
||||
return Files.createFile(result);
|
||||
try {
|
||||
return Files.createFile(result);
|
||||
} catch (AccessDeniedException e) {
|
||||
/*
|
||||
* Thrown on Windows if a directory with the same name already exists, so
|
||||
* convert it to FileAlreadyExistsException if that's the case.
|
||||
*/
|
||||
throw Files.isDirectory(result, NOFOLLOW_LINKS) ? new FileAlreadyExistsException(e.getFile()) : e;
|
||||
}
|
||||
}
|
||||
} catch (FileAlreadyExistsException e) {
|
||||
uniqueTag = "_" + dumpCounter++;
|
||||
|
@ -54,11 +54,13 @@ public class CompilationWrapperTest extends GraalCompilerTest {
|
||||
*/
|
||||
@Test
|
||||
public void testVMCompilation1() throws IOException, InterruptedException {
|
||||
testHelper(Collections.emptyList(), Arrays.asList("-XX:+BootstrapJVMCI",
|
||||
testHelper(Collections.emptyList(), Arrays.asList("-XX:-TieredCompilation",
|
||||
"-XX:+UseJVMCICompiler",
|
||||
"-Dgraal.CompilationFailureAction=ExitVM",
|
||||
"-Dgraal.CrashAt=Object.*,String.*",
|
||||
"-version"));
|
||||
"-Dgraal.CrashAt=TestProgram.*",
|
||||
"-Xcomp",
|
||||
"-XX:CompileCommand=compileonly,*/TestProgram.print*",
|
||||
TestProgram.class.getName()));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -67,11 +69,13 @@ public class CompilationWrapperTest extends GraalCompilerTest {
|
||||
*/
|
||||
@Test
|
||||
public void testVMCompilation2() throws IOException, InterruptedException {
|
||||
testHelper(Collections.emptyList(), Arrays.asList("-XX:+BootstrapJVMCI",
|
||||
testHelper(Collections.emptyList(), Arrays.asList("-XX:-TieredCompilation",
|
||||
"-XX:+UseJVMCICompiler",
|
||||
"-Dgraal.ExitVMOnException=true",
|
||||
"-Dgraal.CrashAt=Object.*,String.*",
|
||||
"-version"));
|
||||
"-Dgraal.CrashAt=TestProgram.*",
|
||||
"-Xcomp",
|
||||
"-XX:CompileCommand=compileonly,*/TestProgram.print*",
|
||||
TestProgram.class.getName()));
|
||||
}
|
||||
|
||||
static class Probe {
|
||||
@ -105,23 +109,36 @@ public class CompilationWrapperTest extends GraalCompilerTest {
|
||||
*/
|
||||
@Test
|
||||
public void testVMCompilation3() throws IOException, InterruptedException {
|
||||
final int maxProblems = 4;
|
||||
Probe[] probes = {
|
||||
new Probe("Retrying compilation of", maxProblems) {
|
||||
@Override
|
||||
String test() {
|
||||
return actualOccurrences > 0 && actualOccurrences <= maxProblems ? null : String.format("expected occurrences to be in [1 .. %d]", maxProblems);
|
||||
}
|
||||
},
|
||||
new Probe("adjusting CompilationFailureAction from Diagnose to Print", 1),
|
||||
new Probe("adjusting CompilationFailureAction from Print to Silent", 1),
|
||||
final int maxProblems = 2;
|
||||
Probe retryingProbe = new Probe("Retrying compilation of", maxProblems) {
|
||||
@Override
|
||||
String test() {
|
||||
return actualOccurrences > 0 && actualOccurrences <= maxProblems ? null : String.format("expected occurrences to be in [1 .. %d]", maxProblems);
|
||||
}
|
||||
};
|
||||
testHelper(Arrays.asList(probes), Arrays.asList("-XX:+BootstrapJVMCI",
|
||||
Probe adjustmentProbe = new Probe("adjusting CompilationFailureAction from Diagnose to Print", 1) {
|
||||
@Override
|
||||
String test() {
|
||||
if (retryingProbe.actualOccurrences >= maxProblems) {
|
||||
if (actualOccurrences == 0) {
|
||||
return "expected at least one occurrence";
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
};
|
||||
Probe[] probes = {
|
||||
retryingProbe,
|
||||
adjustmentProbe
|
||||
};
|
||||
testHelper(Arrays.asList(probes), Arrays.asList("-XX:-TieredCompilation",
|
||||
"-XX:+UseJVMCICompiler",
|
||||
"-Dgraal.CompilationFailureAction=Diagnose",
|
||||
"-Dgraal.MaxCompilationProblemsPerAction=" + maxProblems,
|
||||
"-Dgraal.CrashAt=Object.*,String.*",
|
||||
"-version"));
|
||||
"-Dgraal.CrashAt=TestProgram.*",
|
||||
"-Xcomp",
|
||||
"-XX:CompileCommand=compileonly,*/TestProgram.print*",
|
||||
TestProgram.class.getName()));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -246,3 +263,38 @@ public class CompilationWrapperTest extends GraalCompilerTest {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class TestProgram {
|
||||
public static void main(String[] args) {
|
||||
printHello1();
|
||||
printWorld1();
|
||||
printHello2();
|
||||
printWorld2();
|
||||
printHello3();
|
||||
printWorld3();
|
||||
}
|
||||
|
||||
private static void printHello1() {
|
||||
System.out.println("Hello1");
|
||||
}
|
||||
|
||||
private static void printWorld1() {
|
||||
System.out.println("World1");
|
||||
}
|
||||
|
||||
private static void printHello2() {
|
||||
System.out.println("Hello2");
|
||||
}
|
||||
|
||||
private static void printWorld2() {
|
||||
System.out.println("World2");
|
||||
}
|
||||
|
||||
private static void printHello3() {
|
||||
System.out.println("Hello3");
|
||||
}
|
||||
|
||||
private static void printWorld3() {
|
||||
System.out.println("World3");
|
||||
}
|
||||
}
|
||||
|
@ -28,9 +28,6 @@ import org.graalvm.compiler.api.directives.GraalDirectives;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import jdk.vm.ci.meta.ProfilingInfo;
|
||||
import jdk.vm.ci.meta.ResolvedJavaMethod;
|
||||
|
||||
/**
|
||||
* Test on-stack-replacement with Graal. The test manually triggers a Graal OSR-compilation which is
|
||||
* later invoked when hitting the backedge counter overflow.
|
||||
@ -103,58 +100,4 @@ public class GraalOSRTest extends GraalOSRTestBase {
|
||||
GraalDirectives.controlFlowAnchor();
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOSR04() {
|
||||
testFunnyOSR("testDoWhile", GraalOSRTest::testDoWhile);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOSR05() {
|
||||
testFunnyOSR("testDoWhileLocked", GraalOSRTest::testDoWhileLocked);
|
||||
}
|
||||
|
||||
/**
|
||||
* Because of a bug in C1 profile collection HotSpot can sometimes request an OSR compilation
|
||||
* for a backedge which isn't ever taken. This test synthetically creates that situation.
|
||||
*/
|
||||
private void testFunnyOSR(String name, Runnable warmup) {
|
||||
ResolvedJavaMethod method = getResolvedJavaMethod(name);
|
||||
int iterations = 0;
|
||||
while (true) {
|
||||
ProfilingInfo profilingInfo = method.getProfilingInfo();
|
||||
if (profilingInfo.isMature()) {
|
||||
break;
|
||||
}
|
||||
|
||||
warmup.run();
|
||||
if (iterations++ % 1000 == 0) {
|
||||
System.err.print('.');
|
||||
}
|
||||
if (iterations > 200000) {
|
||||
throw new AssertionError("no profile");
|
||||
}
|
||||
}
|
||||
compileOSR(getInitialOptions(), method);
|
||||
Result result = executeExpected(method, null);
|
||||
checkResult(result);
|
||||
}
|
||||
|
||||
private static boolean repeatLoop;
|
||||
|
||||
public static ReturnValue testDoWhile() {
|
||||
do {
|
||||
sideEffect++;
|
||||
} while (repeatLoop);
|
||||
return ReturnValue.SUCCESS;
|
||||
}
|
||||
|
||||
public static synchronized ReturnValue testDoWhileLocked() {
|
||||
// synchronized (GraalOSRTest.class) {
|
||||
do {
|
||||
sideEffect++;
|
||||
} while (repeatLoop);
|
||||
// }
|
||||
return ReturnValue.SUCCESS;
|
||||
}
|
||||
}
|
||||
|
@ -358,14 +358,17 @@ public class HotSpotGraalManagementTest {
|
||||
assertNotNull("Info is found", info);
|
||||
|
||||
final MBeanOperationInfo[] arr = info.getOperations();
|
||||
assertEquals("Currently three overloads", 3, arr.length);
|
||||
MBeanOperationInfo dumpOp = null;
|
||||
int dumpMethodCount = 0;
|
||||
for (int i = 0; i < arr.length; i++) {
|
||||
assertEquals("dumpMethod", arr[i].getName());
|
||||
if (arr[i].getSignature().length == 3) {
|
||||
dumpOp = arr[i];
|
||||
if ("dumpMethod".equals(arr[i].getName())) {
|
||||
if (arr[i].getSignature().length == 3) {
|
||||
dumpOp = arr[i];
|
||||
}
|
||||
dumpMethodCount++;
|
||||
}
|
||||
}
|
||||
assertEquals("Currently three overloads", 3, dumpMethodCount);
|
||||
assertNotNull("three args variant (as used by VisualVM) found", dumpOp);
|
||||
|
||||
MBeanAttributeInfo dumpPath = findAttributeInfo("DumpPath", info);
|
||||
|
@ -26,6 +26,10 @@ package org.graalvm.compiler.hotspot;
|
||||
|
||||
import java.util.EnumSet;
|
||||
|
||||
import jdk.internal.vm.compiler.collections.EconomicMap;
|
||||
import jdk.internal.vm.compiler.collections.EconomicSet;
|
||||
import jdk.internal.vm.compiler.collections.Equivalence;
|
||||
import jdk.internal.vm.compiler.collections.MapCursor;
|
||||
import org.graalvm.compiler.code.CompilationResult;
|
||||
import org.graalvm.compiler.core.common.CompilationIdentifier;
|
||||
import org.graalvm.compiler.core.common.cfg.AbstractBlockBase;
|
||||
@ -66,10 +70,6 @@ import org.graalvm.compiler.options.OptionType;
|
||||
import org.graalvm.compiler.options.OptionValues;
|
||||
import org.graalvm.compiler.phases.tiers.SuitesProvider;
|
||||
import org.graalvm.compiler.word.Word;
|
||||
import jdk.internal.vm.compiler.collections.EconomicMap;
|
||||
import jdk.internal.vm.compiler.collections.EconomicSet;
|
||||
import jdk.internal.vm.compiler.collections.Equivalence;
|
||||
import jdk.internal.vm.compiler.collections.MapCursor;
|
||||
import jdk.internal.vm.compiler.word.Pointer;
|
||||
|
||||
import jdk.vm.ci.code.CompilationRequest;
|
||||
@ -286,7 +286,7 @@ public abstract class HotSpotBackend extends Backend implements FrameMap.Referen
|
||||
/**
|
||||
* New array stub.
|
||||
*/
|
||||
public static final ForeignCallDescriptor NEW_ARRAY = new ForeignCallDescriptor("new_array", Object.class, KlassPointer.class, int.class, boolean.class);
|
||||
public static final ForeignCallDescriptor NEW_ARRAY = new ForeignCallDescriptor("new_array", Object.class, KlassPointer.class, int.class);
|
||||
|
||||
/**
|
||||
* New instance stub.
|
||||
|
@ -227,6 +227,7 @@ public class HotSpotGraalCompiler implements GraalJVMCICompiler {
|
||||
method(substMethod).
|
||||
compilationId(compilationId).
|
||||
recordInlinedMethods(bytecodeProvider.shouldRecordMethodDependencies()).
|
||||
setIsSubstitution(true).
|
||||
build();
|
||||
// @formatter:on
|
||||
try (DebugContext.Scope scope = debug.scope("GetIntrinsicGraph", graph)) {
|
||||
|
@ -93,7 +93,8 @@ public interface HotSpotGraalRuntimeProvider extends GraalRuntime, RuntimeProvid
|
||||
DiagnosticsOutputDirectory getOutputDirectory();
|
||||
|
||||
/**
|
||||
* Gets the map used to count compilation problems at each {@link ExceptionAction} level.
|
||||
* Gets the map used to count compilation problems at each {@link ExceptionAction} level. All
|
||||
* updates and queries to the map should be synchronized.
|
||||
*/
|
||||
Map<ExceptionAction, Integer> getCompilationProblemsPerAction();
|
||||
|
||||
|
@ -131,7 +131,7 @@ class JVMCIVersionCheck {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// Graal is compatible with all JDK versions as of 9 GA.
|
||||
// Graal is compatible with all JDK versions as of 11 GA.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -85,8 +85,6 @@ import static org.graalvm.compiler.hotspot.replacements.WriteBarrierSnippets.G1W
|
||||
import static org.graalvm.compiler.hotspot.replacements.WriteBarrierSnippets.G1WBPRECALL;
|
||||
import static org.graalvm.compiler.hotspot.replacements.WriteBarrierSnippets.VALIDATE_OBJECT;
|
||||
import static org.graalvm.compiler.hotspot.stubs.ExceptionHandlerStub.EXCEPTION_HANDLER_FOR_PC;
|
||||
import static org.graalvm.compiler.hotspot.stubs.NewArrayStub.NEW_ARRAY_C;
|
||||
import static org.graalvm.compiler.hotspot.stubs.NewInstanceStub.NEW_INSTANCE_C;
|
||||
import static org.graalvm.compiler.hotspot.stubs.StubUtil.VM_MESSAGE_C;
|
||||
import static org.graalvm.compiler.hotspot.stubs.UnwindExceptionToCallerStub.EXCEPTION_HANDLER_FOR_RETURN_ADDRESS;
|
||||
import static org.graalvm.compiler.nodes.java.ForeignCallDescriptors.REGISTER_FINALIZER;
|
||||
@ -119,8 +117,6 @@ import org.graalvm.compiler.hotspot.stubs.DivisionByZeroExceptionStub;
|
||||
import org.graalvm.compiler.hotspot.stubs.ExceptionHandlerStub;
|
||||
import org.graalvm.compiler.hotspot.stubs.IntegerExactOverflowExceptionStub;
|
||||
import org.graalvm.compiler.hotspot.stubs.LongExactOverflowExceptionStub;
|
||||
import org.graalvm.compiler.hotspot.stubs.NewArrayStub;
|
||||
import org.graalvm.compiler.hotspot.stubs.NewInstanceStub;
|
||||
import org.graalvm.compiler.hotspot.stubs.NullPointerExceptionStub;
|
||||
import org.graalvm.compiler.hotspot.stubs.OutOfBoundsExceptionStub;
|
||||
import org.graalvm.compiler.hotspot.stubs.Stub;
|
||||
@ -280,8 +276,6 @@ public abstract class HotSpotHostForeignCallsProvider extends HotSpotForeignCall
|
||||
|
||||
registerForeignCall(EXCEPTION_HANDLER_FOR_PC, c.exceptionHandlerForPcAddress, NativeCall, DESTROYS_REGISTERS, SAFEPOINT, REEXECUTABLE, any());
|
||||
registerForeignCall(EXCEPTION_HANDLER_FOR_RETURN_ADDRESS, c.exceptionHandlerForReturnAddressAddress, NativeCall, DESTROYS_REGISTERS, SAFEPOINT, REEXECUTABLE, any());
|
||||
registerForeignCall(NEW_ARRAY_C, c.newArrayAddress, NativeCall, DESTROYS_REGISTERS, SAFEPOINT, REEXECUTABLE, any());
|
||||
registerForeignCall(NEW_INSTANCE_C, c.newInstanceAddress, NativeCall, DESTROYS_REGISTERS, SAFEPOINT, REEXECUTABLE, any());
|
||||
|
||||
CreateExceptionStub.registerForeignCalls(c, this);
|
||||
|
||||
@ -292,8 +286,8 @@ public abstract class HotSpotHostForeignCallsProvider extends HotSpotForeignCall
|
||||
registerForeignCall(VM_MESSAGE_C, c.vmMessageAddress, NativeCall, DESTROYS_REGISTERS, SAFEPOINT, REEXECUTABLE, NO_LOCATIONS);
|
||||
registerForeignCall(ASSERTION_VM_MESSAGE_C, c.vmMessageAddress, NativeCall, PRESERVES_REGISTERS, LEAF, REEXECUTABLE, NO_LOCATIONS);
|
||||
|
||||
link(new NewInstanceStub(options, providers, registerStubCall(NEW_INSTANCE, SAFEPOINT, REEXECUTABLE, TLAB_TOP_LOCATION, TLAB_END_LOCATION)));
|
||||
link(new NewArrayStub(options, providers, registerStubCall(NEW_ARRAY, SAFEPOINT, REEXECUTABLE, TLAB_TOP_LOCATION, TLAB_END_LOCATION)));
|
||||
linkForeignCall(options, providers, NEW_INSTANCE, c.newInstanceAddress, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE, TLAB_TOP_LOCATION, TLAB_END_LOCATION);
|
||||
linkForeignCall(options, providers, NEW_ARRAY, c.newArrayAddress, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE, TLAB_TOP_LOCATION, TLAB_END_LOCATION);
|
||||
link(new ExceptionHandlerStub(options, providers, foreignCalls.get(EXCEPTION_HANDLER)));
|
||||
link(new UnwindExceptionToCallerStub(options, providers, registerStubCall(UNWIND_EXCEPTION_TO_CALLER, SAFEPOINT, REEXECUTABLE_ONLY_AFTER_EXCEPTION, any())));
|
||||
link(new VerifyOopStub(options, providers, registerStubCall(VERIFY_OOP, LEAF_NOFP, REEXECUTABLE, NO_LOCATIONS)));
|
||||
|
@ -331,14 +331,14 @@ public class NewObjectSnippets implements Snippets {
|
||||
}
|
||||
result = formatArray(hub, allocationSize, length, headerSize, top, prototypeMarkWord, fillContents, maybeUnroll, counters);
|
||||
} else {
|
||||
result = newArray(HotSpotBackend.NEW_ARRAY, hub, length, fillContents);
|
||||
result = newArray(HotSpotBackend.NEW_ARRAY, hub, length);
|
||||
}
|
||||
profileAllocation("array", allocationSize, typeContext, options);
|
||||
return result;
|
||||
}
|
||||
|
||||
@NodeIntrinsic(value = ForeignCallNode.class, injectedStampIsNonNull = true)
|
||||
public static native Object newArray(@ConstantNodeParameter ForeignCallDescriptor descriptor, KlassPointer hub, int length, boolean fillContents);
|
||||
public static native Object newArray(@ConstantNodeParameter ForeignCallDescriptor descriptor, KlassPointer hub, int length);
|
||||
|
||||
public static final ForeignCallDescriptor DYNAMIC_NEW_ARRAY = new ForeignCallDescriptor("dynamic_new_array", Object.class, Class.class, int.class);
|
||||
public static final ForeignCallDescriptor DYNAMIC_NEW_INSTANCE = new ForeignCallDescriptor("dynamic_new_instance", Object.class, Class.class);
|
||||
|
@ -1,122 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2015, 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.stubs;
|
||||
|
||||
import static org.graalvm.compiler.hotspot.GraalHotSpotVMConfig.INJECTED_VMCONFIG;
|
||||
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.arrayAllocationSize;
|
||||
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.getAndClearObjectResult;
|
||||
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.layoutHelperElementTypeMask;
|
||||
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.layoutHelperElementTypeShift;
|
||||
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.layoutHelperHeaderSizeMask;
|
||||
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.layoutHelperHeaderSizeShift;
|
||||
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.layoutHelperLog2ElementSizeMask;
|
||||
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.layoutHelperLog2ElementSizeShift;
|
||||
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.readLayoutHelper;
|
||||
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.registerAsWord;
|
||||
import static org.graalvm.compiler.hotspot.stubs.StubUtil.handlePendingException;
|
||||
import static org.graalvm.compiler.hotspot.stubs.StubUtil.newDescriptor;
|
||||
import static org.graalvm.compiler.hotspot.stubs.StubUtil.printf;
|
||||
import static org.graalvm.compiler.hotspot.stubs.StubUtil.verifyObject;
|
||||
|
||||
import org.graalvm.compiler.api.replacements.Fold;
|
||||
import org.graalvm.compiler.api.replacements.Snippet;
|
||||
import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter;
|
||||
import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
|
||||
import org.graalvm.compiler.graph.Node.ConstantNodeParameter;
|
||||
import org.graalvm.compiler.graph.Node.NodeIntrinsic;
|
||||
import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage;
|
||||
import org.graalvm.compiler.hotspot.meta.HotSpotProviders;
|
||||
import org.graalvm.compiler.hotspot.nodes.StubForeignCallNode;
|
||||
import org.graalvm.compiler.hotspot.replacements.NewObjectSnippets;
|
||||
import org.graalvm.compiler.hotspot.word.KlassPointer;
|
||||
import org.graalvm.compiler.options.OptionValues;
|
||||
import org.graalvm.compiler.word.Word;
|
||||
|
||||
import jdk.vm.ci.code.Register;
|
||||
|
||||
/**
|
||||
* Stub implementing the fast path for TLAB refill during instance class allocation. This stub is
|
||||
* called from the {@linkplain NewObjectSnippets inline} allocation code when TLAB allocation fails.
|
||||
* If this stub fails to refill the TLAB or allocate the object, it calls out to the HotSpot C++
|
||||
* runtime to complete the allocation.
|
||||
*/
|
||||
public class NewArrayStub extends SnippetStub {
|
||||
|
||||
public NewArrayStub(OptionValues options, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) {
|
||||
super("newArray", options, providers, linkage);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object[] makeConstArgs() {
|
||||
int count = method.getSignature().getParameterCount(false);
|
||||
Object[] args = new Object[count];
|
||||
assert checkConstArg(2, "threadRegister");
|
||||
assert checkConstArg(3, "options");
|
||||
args[2] = providers.getRegisters().getThreadRegister();
|
||||
args[3] = options;
|
||||
return args;
|
||||
}
|
||||
|
||||
@Fold
|
||||
static boolean logging(OptionValues options) {
|
||||
return StubOptions.TraceNewArrayStub.getValue(options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-attempts allocation after an initial TLAB allocation failed or was skipped (e.g., due to
|
||||
* -XX:-UseTLAB).
|
||||
*
|
||||
* @param hub the hub of the object to be allocated
|
||||
* @param length the length of the array
|
||||
*/
|
||||
@Snippet
|
||||
private static Object newArray(KlassPointer hub, int length, @ConstantParameter Register threadRegister, @ConstantParameter OptionValues options) {
|
||||
int layoutHelper = readLayoutHelper(hub);
|
||||
int log2ElementSize = (layoutHelper >> layoutHelperLog2ElementSizeShift(INJECTED_VMCONFIG)) & layoutHelperLog2ElementSizeMask(INJECTED_VMCONFIG);
|
||||
int headerSize = (layoutHelper >> layoutHelperHeaderSizeShift(INJECTED_VMCONFIG)) & layoutHelperHeaderSizeMask(INJECTED_VMCONFIG);
|
||||
int elementKind = (layoutHelper >> layoutHelperElementTypeShift(INJECTED_VMCONFIG)) & layoutHelperElementTypeMask(INJECTED_VMCONFIG);
|
||||
int sizeInBytes = arrayAllocationSize(length, headerSize, log2ElementSize);
|
||||
if (logging(options)) {
|
||||
printf("newArray: element kind %d\n", elementKind);
|
||||
printf("newArray: array length %d\n", length);
|
||||
printf("newArray: array size %d\n", sizeInBytes);
|
||||
printf("newArray: hub=%p\n", hub.asWord().rawValue());
|
||||
}
|
||||
|
||||
Word thread = registerAsWord(threadRegister);
|
||||
if (logging(options)) {
|
||||
printf("newArray: calling new_array_c\n");
|
||||
}
|
||||
|
||||
newArrayC(NEW_ARRAY_C, thread, hub, length);
|
||||
handlePendingException(thread, true, true);
|
||||
return verifyObject(getAndClearObjectResult(thread));
|
||||
}
|
||||
|
||||
public static final ForeignCallDescriptor NEW_ARRAY_C = newDescriptor(NewArrayStub.class, "newArrayC", void.class, Word.class, KlassPointer.class, int.class);
|
||||
|
||||
@NodeIntrinsic(StubForeignCallNode.class)
|
||||
public static native void newArrayC(@ConstantNodeParameter ForeignCallDescriptor newArrayC, Word thread, KlassPointer hub, int length);
|
||||
}
|
@ -1,109 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2015, 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.stubs;
|
||||
|
||||
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.getAndClearObjectResult;
|
||||
import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.registerAsWord;
|
||||
import static org.graalvm.compiler.hotspot.stubs.StubUtil.handlePendingException;
|
||||
import static org.graalvm.compiler.hotspot.stubs.StubUtil.newDescriptor;
|
||||
import static org.graalvm.compiler.hotspot.stubs.StubUtil.printf;
|
||||
import static org.graalvm.compiler.hotspot.stubs.StubUtil.verifyObject;
|
||||
|
||||
import org.graalvm.compiler.api.replacements.Fold;
|
||||
import org.graalvm.compiler.api.replacements.Snippet;
|
||||
import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter;
|
||||
import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
|
||||
import org.graalvm.compiler.graph.Node.ConstantNodeParameter;
|
||||
import org.graalvm.compiler.graph.Node.NodeIntrinsic;
|
||||
import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage;
|
||||
import org.graalvm.compiler.hotspot.meta.HotSpotProviders;
|
||||
import org.graalvm.compiler.hotspot.nodes.StubForeignCallNode;
|
||||
import org.graalvm.compiler.hotspot.replacements.NewObjectSnippets;
|
||||
import org.graalvm.compiler.hotspot.word.KlassPointer;
|
||||
import org.graalvm.compiler.options.OptionValues;
|
||||
import org.graalvm.compiler.word.Word;
|
||||
|
||||
import jdk.vm.ci.code.Register;
|
||||
|
||||
/**
|
||||
* Stub implementing the fast path for TLAB refill during instance class allocation. This stub is
|
||||
* called from the {@linkplain NewObjectSnippets inline} allocation code when TLAB allocation fails.
|
||||
* If this stub fails to refill the TLAB or allocate the object, it calls out to the HotSpot C++
|
||||
* runtime for to complete the allocation.
|
||||
*/
|
||||
public class NewInstanceStub extends SnippetStub {
|
||||
|
||||
public NewInstanceStub(OptionValues options, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) {
|
||||
super("newInstance", options, providers, linkage);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object[] makeConstArgs() {
|
||||
int count = method.getSignature().getParameterCount(false);
|
||||
Object[] args = new Object[count];
|
||||
assert checkConstArg(1, "threadRegister");
|
||||
assert checkConstArg(2, "options");
|
||||
args[1] = providers.getRegisters().getThreadRegister();
|
||||
args[2] = options;
|
||||
return args;
|
||||
}
|
||||
|
||||
@Fold
|
||||
static boolean logging(OptionValues options) {
|
||||
return StubOptions.TraceNewInstanceStub.getValue(options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-attempts allocation after an initial TLAB allocation failed or was skipped (e.g., due to
|
||||
* -XX:-UseTLAB).
|
||||
*
|
||||
* @param hub the hub of the object to be allocated
|
||||
*/
|
||||
@Snippet
|
||||
private static Object newInstance(KlassPointer hub, @ConstantParameter Register threadRegister, @ConstantParameter OptionValues options) {
|
||||
/*
|
||||
* The type is known to be an instance so Klass::_layout_helper is the instance size as a
|
||||
* raw number
|
||||
*/
|
||||
Word thread = registerAsWord(threadRegister);
|
||||
if (logging(options)) {
|
||||
printf("newInstance: calling new_instance_c\n");
|
||||
}
|
||||
|
||||
newInstanceC(NEW_INSTANCE_C, thread, hub);
|
||||
handlePendingException(thread, true, true);
|
||||
return verifyObject(getAndClearObjectResult(thread));
|
||||
}
|
||||
|
||||
@Fold
|
||||
static boolean forceSlowPath(OptionValues options) {
|
||||
return StubOptions.ForceUseOfNewInstanceStub.getValue(options);
|
||||
}
|
||||
|
||||
public static final ForeignCallDescriptor NEW_INSTANCE_C = newDescriptor(NewInstanceStub.class, "newInstanceC", void.class, Word.class, KlassPointer.class);
|
||||
|
||||
@NodeIntrinsic(StubForeignCallNode.class)
|
||||
public static native void newInstanceC(@ConstantNodeParameter ForeignCallDescriptor newInstanceC, Word thread, KlassPointer hub);
|
||||
}
|
@ -107,9 +107,15 @@ public abstract class SnippetStub extends Stub implements Snippets {
|
||||
plugins.prependParameterPlugin(new ConstantBindingParameterPlugin(makeConstArgs(), metaAccess, snippetReflection));
|
||||
GraphBuilderConfiguration config = GraphBuilderConfiguration.getSnippetDefault(plugins);
|
||||
|
||||
// @formatter:off
|
||||
// Stubs cannot have optimistic assumptions since they have
|
||||
// to be valid for the entire run of the VM.
|
||||
final StructuredGraph graph = new StructuredGraph.Builder(options, debug).method(method).compilationId(compilationId).build();
|
||||
final StructuredGraph graph = new StructuredGraph.Builder(options, debug).
|
||||
method(method).
|
||||
compilationId(compilationId).
|
||||
setIsSubstitution(true).
|
||||
build();
|
||||
// @formatter:on
|
||||
try (DebugContext.Scope outer = debug.scope("SnippetStub", graph)) {
|
||||
graph.disableUnsafeAccessTracking();
|
||||
|
||||
|
@ -25,8 +25,8 @@
|
||||
package org.graalvm.compiler.hotspot.stubs;
|
||||
|
||||
import org.graalvm.compiler.options.Option;
|
||||
import org.graalvm.compiler.options.OptionType;
|
||||
import org.graalvm.compiler.options.OptionKey;
|
||||
import org.graalvm.compiler.options.OptionType;
|
||||
|
||||
//JaCoCo Exclude
|
||||
|
||||
@ -43,14 +43,5 @@ public class StubOptions {
|
||||
|
||||
@Option(help = "Trace execution of the stub that routes an exception to a handler in the calling frame.", type = OptionType.Debug)
|
||||
static final OptionKey<Boolean> TraceUnwindStub = new OptionKey<>(false);
|
||||
|
||||
@Option(help = "Trace execution of slow path stub for array allocation.", type = OptionType.Debug)
|
||||
static final OptionKey<Boolean> TraceNewArrayStub = new OptionKey<>(false);
|
||||
|
||||
@Option(help = "Trace execution of slow path stub for non-array object allocation.", type = OptionType.Debug)
|
||||
static final OptionKey<Boolean> TraceNewInstanceStub = new OptionKey<>(false);
|
||||
|
||||
@Option(help = "Force non-array object allocation to always use the slow path.", type = OptionType.Debug)
|
||||
static final OptionKey<Boolean> ForceUseOfNewInstanceStub = new OptionKey<>(false);
|
||||
//@formatter:on
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ package org.graalvm.compiler.java;
|
||||
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.AALOAD;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.AASTORE;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.ANEWARRAY;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.ARETURN;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.ARRAYLENGTH;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.ATHROW;
|
||||
@ -78,6 +79,8 @@ import static org.graalvm.compiler.bytecode.Bytecodes.LDIV;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.LOOKUPSWITCH;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.LREM;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.LRETURN;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.MULTIANEWARRAY;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.NEW;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.PUTFIELD;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.PUTSTATIC;
|
||||
import static org.graalvm.compiler.bytecode.Bytecodes.RET;
|
||||
@ -679,10 +682,19 @@ public final class BciBlockMapping {
|
||||
case SALOAD:
|
||||
case ARRAYLENGTH:
|
||||
case CHECKCAST:
|
||||
case NEW:
|
||||
case ANEWARRAY:
|
||||
case MULTIANEWARRAY:
|
||||
case PUTSTATIC:
|
||||
case GETSTATIC:
|
||||
case PUTFIELD:
|
||||
case GETFIELD: {
|
||||
/*
|
||||
* All bytecodes that can trigger lazy class initialization via a
|
||||
* ClassInitializationPlugin (allocations, static field access) must be listed
|
||||
* because the class initializer is allowed to throw an exception, which
|
||||
* requires proper exception handling.
|
||||
*/
|
||||
ExceptionDispatchBlock handler = handleExceptions(blockMap, bci);
|
||||
if (handler != null) {
|
||||
current = null;
|
||||
|
@ -3369,29 +3369,25 @@ public class BytecodeParser implements GraphBuilderContext {
|
||||
|
||||
NodeSourcePosition currentPosition = graph.currentNodeSourcePosition();
|
||||
if (isNeverExecutedCode(probability)) {
|
||||
if (!graph.isOSR() || getParent() != null || graph.getEntryBCI() != trueBlock.startBci) {
|
||||
NodeSourcePosition survivingSuccessorPosition = graph.trackNodeSourcePosition()
|
||||
? new NodeSourcePosition(currentPosition.getCaller(), currentPosition.getMethod(), falseBlock.startBci)
|
||||
: null;
|
||||
append(new FixedGuardNode(condition, UnreachedCode, InvalidateReprofile, true, survivingSuccessorPosition));
|
||||
if (profilingPlugin != null && profilingPlugin.shouldProfile(this, method)) {
|
||||
profilingPlugin.profileGoto(this, method, bci(), falseBlock.startBci, stateBefore);
|
||||
}
|
||||
appendGoto(falseBlock);
|
||||
return;
|
||||
NodeSourcePosition survivingSuccessorPosition = graph.trackNodeSourcePosition()
|
||||
? new NodeSourcePosition(currentPosition.getCaller(), currentPosition.getMethod(), falseBlock.startBci)
|
||||
: null;
|
||||
append(new FixedGuardNode(condition, UnreachedCode, InvalidateReprofile, true, survivingSuccessorPosition));
|
||||
if (profilingPlugin != null && profilingPlugin.shouldProfile(this, method)) {
|
||||
profilingPlugin.profileGoto(this, method, bci(), falseBlock.startBci, stateBefore);
|
||||
}
|
||||
appendGoto(falseBlock);
|
||||
return;
|
||||
} else if (isNeverExecutedCode(1 - probability)) {
|
||||
if (!graph.isOSR() || getParent() != null || graph.getEntryBCI() != falseBlock.startBci) {
|
||||
NodeSourcePosition survivingSuccessorPosition = graph.trackNodeSourcePosition()
|
||||
? new NodeSourcePosition(currentPosition.getCaller(), currentPosition.getMethod(), trueBlock.startBci)
|
||||
: null;
|
||||
append(new FixedGuardNode(condition, UnreachedCode, InvalidateReprofile, false, survivingSuccessorPosition));
|
||||
if (profilingPlugin != null && profilingPlugin.shouldProfile(this, method)) {
|
||||
profilingPlugin.profileGoto(this, method, bci(), trueBlock.startBci, stateBefore);
|
||||
}
|
||||
appendGoto(trueBlock);
|
||||
return;
|
||||
NodeSourcePosition survivingSuccessorPosition = graph.trackNodeSourcePosition()
|
||||
? new NodeSourcePosition(currentPosition.getCaller(), currentPosition.getMethod(), trueBlock.startBci)
|
||||
: null;
|
||||
append(new FixedGuardNode(condition, UnreachedCode, InvalidateReprofile, false, survivingSuccessorPosition));
|
||||
if (profilingPlugin != null && profilingPlugin.shouldProfile(this, method)) {
|
||||
profilingPlugin.profileGoto(this, method, bci(), trueBlock.startBci, stateBefore);
|
||||
}
|
||||
appendGoto(trueBlock);
|
||||
return;
|
||||
}
|
||||
|
||||
if (profilingPlugin != null && profilingPlugin.shouldProfile(this, method)) {
|
||||
@ -4116,6 +4112,11 @@ public class BytecodeParser implements GraphBuilderContext {
|
||||
return;
|
||||
}
|
||||
ResolvedJavaType resolvedType = (ResolvedJavaType) type;
|
||||
if (resolvedType.isAbstract() || resolvedType.isInterface()) {
|
||||
handleUnresolvedNewInstance(type);
|
||||
return;
|
||||
}
|
||||
|
||||
ClassInitializationPlugin classInitializationPlugin = graphBuilderConfig.getPlugins().getClassInitializationPlugin();
|
||||
if (!resolvedType.isInitialized() && classInitializationPlugin == null) {
|
||||
handleUnresolvedNewInstance(type);
|
||||
|
@ -436,7 +436,12 @@ public class GraphEncoder {
|
||||
@SuppressWarnings("try")
|
||||
public static boolean verifyEncoding(StructuredGraph originalGraph, EncodedGraph encodedGraph, Architecture architecture) {
|
||||
DebugContext debug = originalGraph.getDebug();
|
||||
StructuredGraph decodedGraph = new StructuredGraph.Builder(originalGraph.getOptions(), debug, AllowAssumptions.YES).method(originalGraph.method()).build();
|
||||
// @formatter:off
|
||||
StructuredGraph decodedGraph = new StructuredGraph.Builder(originalGraph.getOptions(), debug, AllowAssumptions.YES).
|
||||
method(originalGraph.method()).
|
||||
setIsSubstitution(originalGraph.isSubstitution()).
|
||||
build();
|
||||
// @formatter:off
|
||||
if (originalGraph.trackNodeSourcePosition()) {
|
||||
decodedGraph.setTrackNodeSourcePosition();
|
||||
}
|
||||
|
@ -40,6 +40,8 @@ import jdk.internal.vm.compiler.collections.EconomicMap;
|
||||
import jdk.internal.vm.compiler.collections.EconomicSet;
|
||||
import jdk.internal.vm.compiler.collections.Equivalence;
|
||||
import jdk.internal.vm.compiler.collections.UnmodifiableEconomicMap;
|
||||
import org.graalvm.compiler.api.replacements.MethodSubstitution;
|
||||
import org.graalvm.compiler.api.replacements.Snippet;
|
||||
import org.graalvm.compiler.core.common.CancellationBailoutException;
|
||||
import org.graalvm.compiler.core.common.CompilationIdentifier;
|
||||
import org.graalvm.compiler.core.common.GraalOptions;
|
||||
@ -187,6 +189,7 @@ public final class StructuredGraph extends Graph implements JavaMethodContext {
|
||||
private Cancellable cancellable = null;
|
||||
private final DebugContext debug;
|
||||
private NodeSourcePosition callerContext;
|
||||
private boolean isSubstitution;
|
||||
|
||||
/**
|
||||
* Creates a builder for a graph.
|
||||
@ -217,6 +220,14 @@ public final class StructuredGraph extends Graph implements JavaMethodContext {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see StructuredGraph#isSubstitution
|
||||
*/
|
||||
public Builder setIsSubstitution(boolean flag) {
|
||||
this.isSubstitution = flag;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ResolvedJavaMethod getMethod() {
|
||||
return rootMethod;
|
||||
}
|
||||
@ -303,8 +314,22 @@ public final class StructuredGraph extends Graph implements JavaMethodContext {
|
||||
|
||||
public StructuredGraph build() {
|
||||
List<ResolvedJavaMethod> inlinedMethods = recordInlinedMethods ? new ArrayList<>() : null;
|
||||
return new StructuredGraph(name, rootMethod, entryBCI, assumptions, speculationLog, useProfilingInfo, inlinedMethods,
|
||||
trackNodeSourcePosition, compilationId, options, debug, cancellable, callerContext);
|
||||
// @formatter:off
|
||||
return new StructuredGraph(name,
|
||||
rootMethod,
|
||||
entryBCI,
|
||||
assumptions,
|
||||
speculationLog,
|
||||
useProfilingInfo,
|
||||
isSubstitution,
|
||||
inlinedMethods,
|
||||
trackNodeSourcePosition,
|
||||
compilationId,
|
||||
options,
|
||||
debug,
|
||||
cancellable,
|
||||
callerContext);
|
||||
// @formatter:on
|
||||
}
|
||||
}
|
||||
|
||||
@ -323,6 +348,8 @@ public final class StructuredGraph extends Graph implements JavaMethodContext {
|
||||
private boolean isAfterExpandLogic = false;
|
||||
private final boolean useProfilingInfo;
|
||||
private final Cancellable cancellable;
|
||||
private final boolean isSubstitution;
|
||||
|
||||
/**
|
||||
* The assumptions made while constructing and transforming this graph.
|
||||
*/
|
||||
@ -369,6 +396,7 @@ public final class StructuredGraph extends Graph implements JavaMethodContext {
|
||||
Assumptions assumptions,
|
||||
SpeculationLog speculationLog,
|
||||
boolean useProfilingInfo,
|
||||
boolean isSubstitution,
|
||||
List<ResolvedJavaMethod> methods,
|
||||
SourcePositionTracking trackNodeSourcePosition,
|
||||
CompilationIdentifier compilationId,
|
||||
@ -386,6 +414,8 @@ public final class StructuredGraph extends Graph implements JavaMethodContext {
|
||||
this.methods = methods;
|
||||
this.speculationLog = speculationLog;
|
||||
this.useProfilingInfo = useProfilingInfo;
|
||||
this.isSubstitution = isSubstitution;
|
||||
assert checkIsSubstitutionInvariants(method, isSubstitution);
|
||||
this.trackNodeSourcePosition = trackNodeSourcePosition;
|
||||
assert trackNodeSourcePosition != null;
|
||||
this.cancellable = cancellable;
|
||||
@ -393,6 +423,18 @@ public final class StructuredGraph extends Graph implements JavaMethodContext {
|
||||
this.callerContext = context;
|
||||
}
|
||||
|
||||
private static boolean checkIsSubstitutionInvariants(ResolvedJavaMethod method, boolean isSubstitution) {
|
||||
if (method != null) {
|
||||
if (method.getAnnotation(Snippet.class) != null || method.getAnnotation(MethodSubstitution.class) != null) {
|
||||
assert isSubstitution : "Graph for method " + method.format("%H.%n(%p)") +
|
||||
" annotated by " + Snippet.class.getName() + " or " +
|
||||
MethodSubstitution.class.getName() +
|
||||
" must have its `isSubstitution` field set to true";
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setLastSchedule(ScheduleResult result) {
|
||||
lastSchedule = result;
|
||||
}
|
||||
@ -535,6 +577,7 @@ public final class StructuredGraph extends Graph implements JavaMethodContext {
|
||||
assumptions == null ? null : new Assumptions(),
|
||||
speculationLog,
|
||||
useProfilingInfo,
|
||||
isSubstitution,
|
||||
methods != null ? new ArrayList<>(methods) : null,
|
||||
trackNodeSourcePosition,
|
||||
newCompilationId,
|
||||
@ -858,6 +901,15 @@ public final class StructuredGraph extends Graph implements JavaMethodContext {
|
||||
return useProfilingInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this graph is built without parsing the {@linkplain #method() root method} or
|
||||
* if the root method is annotated by {@link Snippet} or {@link MethodSubstitution}. This is
|
||||
* preferred over querying annotations directly as querying annotations can cause class loading.
|
||||
*/
|
||||
public boolean isSubstitution() {
|
||||
return isSubstitution;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the profiling info for the {@linkplain #method() root method} of this graph.
|
||||
*/
|
||||
|
@ -61,7 +61,7 @@ import jdk.vm.ci.meta.TriState;
|
||||
public class InstanceOfNode extends UnaryOpLogicNode implements Lowerable, Virtualizable {
|
||||
public static final NodeClass<InstanceOfNode> TYPE = NodeClass.create(InstanceOfNode.class);
|
||||
|
||||
private ObjectStamp checkedStamp;
|
||||
private final ObjectStamp checkedStamp;
|
||||
|
||||
private JavaTypeProfile profile;
|
||||
@OptionalInput(Anchor) protected AnchoringNode anchor;
|
||||
@ -77,6 +77,7 @@ public class InstanceOfNode extends UnaryOpLogicNode implements Lowerable, Virtu
|
||||
this.anchor = anchor;
|
||||
assert (profile == null) || (anchor != null) : "profiles must be anchored";
|
||||
assert checkedStamp != null;
|
||||
assert type() != null;
|
||||
}
|
||||
|
||||
public static LogicNode createAllowNull(TypeReference type, ValueNode object, JavaTypeProfile profile, AnchoringNode anchor) {
|
||||
@ -217,11 +218,6 @@ public class InstanceOfNode extends UnaryOpLogicNode implements Lowerable, Virtu
|
||||
return checkedStamp;
|
||||
}
|
||||
|
||||
public void strengthenCheckedStamp(ObjectStamp newCheckedStamp) {
|
||||
assert this.checkedStamp.join(newCheckedStamp).equals(newCheckedStamp) : "stamp can only improve";
|
||||
this.checkedStamp = newCheckedStamp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TriState implies(boolean thisNegated, LogicNode other) {
|
||||
if (other instanceof InstanceOfNode) {
|
||||
|
@ -60,7 +60,7 @@ public class NewInstanceNode extends AbstractNewObjectNode implements Virtualiza
|
||||
|
||||
protected NewInstanceNode(NodeClass<? extends NewInstanceNode> c, ResolvedJavaType type, boolean fillContents, FrameState stateBefore) {
|
||||
super(c, StampFactory.objectNonNull(TypeReference.createExactTrusted(type)), fillContents, stateBefore);
|
||||
assert !type.isArray() && !type.isInterface() && !type.isPrimitive();
|
||||
assert !type.isArray() && !type.isInterface() && !type.isPrimitive() && !type.isAbstract();
|
||||
this.instanceClass = type;
|
||||
}
|
||||
|
||||
|
@ -98,7 +98,7 @@ public final class StoreIndexedNode extends AccessIndexedNode implements StateSp
|
||||
VirtualArrayNode virtual = (VirtualArrayNode) alias;
|
||||
if (idx >= 0 && idx < virtual.entryCount()) {
|
||||
ResolvedJavaType componentType = virtual.type().getComponentType();
|
||||
if (componentType.isPrimitive() || StampTool.isPointerAlwaysNull(value) || componentType.getSuperclass() == null ||
|
||||
if (componentType.isPrimitive() || StampTool.isPointerAlwaysNull(value) || componentType.isJavaLangObject() ||
|
||||
(StampTool.typeReferenceOrNull(value) != null && componentType.isAssignableFrom(StampTool.typeOrNull(value)))) {
|
||||
tool.setVirtualEntry(virtual, idx, value());
|
||||
tool.delete();
|
||||
|
@ -32,7 +32,6 @@ import java.util.ServiceLoader;
|
||||
|
||||
import jdk.internal.vm.compiler.collections.EconomicMap;
|
||||
import jdk.internal.vm.compiler.collections.MapCursor;
|
||||
import org.graalvm.util.CollectionsUtil;
|
||||
|
||||
/**
|
||||
* This class contains methods for parsing Graal options and matching them against a set of
|
||||
@ -45,20 +44,21 @@ public class OptionsParser {
|
||||
* {@link OptionDescriptors} providers.
|
||||
*/
|
||||
public static Iterable<OptionDescriptors> getOptionsLoader() {
|
||||
ServiceLoader<OptionDescriptors> graalLoader = ServiceLoader.load(OptionDescriptors.class, OptionDescriptors.class.getClassLoader());
|
||||
boolean java8OrEarlier = System.getProperty("java.specification.version").compareTo("1.9") < 0;
|
||||
ClassLoader loader;
|
||||
if (java8OrEarlier) {
|
||||
return graalLoader;
|
||||
// On JDK 8, Graal and its extensions are loaded by same class loader.
|
||||
loader = OptionDescriptors.class.getClassLoader();
|
||||
} else {
|
||||
/*
|
||||
* The Graal module (i.e., jdk.internal.vm.compiler) is loaded by the platform class
|
||||
* loader on JDK 9. Other modules that extend Graal or are Graal dependencies (such as
|
||||
* Truffle) are supplied via --module-path which means they are loaded by the app class
|
||||
* loader. As such, we need to search the app class loader path as well.
|
||||
* loader as of JDK 9. Modules that depend on and extend Graal are loaded by the app
|
||||
* class loader. As such, we need to start the provider search at the app class loader
|
||||
* instead of the platform class loader.
|
||||
*/
|
||||
ServiceLoader<OptionDescriptors> truffleLoader = ServiceLoader.load(OptionDescriptors.class, ClassLoader.getSystemClassLoader());
|
||||
return CollectionsUtil.concat(graalLoader, truffleLoader);
|
||||
loader = ClassLoader.getSystemClassLoader();
|
||||
}
|
||||
return ServiceLoader.load(OptionDescriptors.class, loader);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -56,7 +56,6 @@ import org.graalvm.compiler.nodes.AbstractBeginNode;
|
||||
import org.graalvm.compiler.nodes.AbstractMergeNode;
|
||||
import org.graalvm.compiler.nodes.BinaryOpLogicNode;
|
||||
import org.graalvm.compiler.nodes.ConditionAnchorNode;
|
||||
import org.graalvm.compiler.nodes.DeoptimizeNode;
|
||||
import org.graalvm.compiler.nodes.DeoptimizingGuard;
|
||||
import org.graalvm.compiler.nodes.EndNode;
|
||||
import org.graalvm.compiler.nodes.FixedGuardNode;
|
||||
@ -64,6 +63,7 @@ import org.graalvm.compiler.nodes.FixedNode;
|
||||
import org.graalvm.compiler.nodes.FixedWithNextNode;
|
||||
import org.graalvm.compiler.nodes.GuardNode;
|
||||
import org.graalvm.compiler.nodes.IfNode;
|
||||
import org.graalvm.compiler.nodes.LogicConstantNode;
|
||||
import org.graalvm.compiler.nodes.LogicNode;
|
||||
import org.graalvm.compiler.nodes.LoopExitNode;
|
||||
import org.graalvm.compiler.nodes.MergeNode;
|
||||
@ -335,11 +335,18 @@ public class ConditionalEliminationPhase extends BasePhase<PhaseContext> {
|
||||
if (result != node.isNegated()) {
|
||||
node.replaceAndDelete(guard.asNode());
|
||||
} else {
|
||||
DeoptimizeNode deopt = node.graph().add(new DeoptimizeNode(node.getAction(), node.getReason(), node.getSpeculation()));
|
||||
/*
|
||||
* Don't kill this branch immediately because `killCFG` can have complex
|
||||
* implications in the presence of loops: it might replace or delete nodes in
|
||||
* other branches or even above the kill point. Instead of killing immediately,
|
||||
* just leave the graph in a state that is easy to simplify by a subsequent
|
||||
* canonicalizer phase.
|
||||
*/
|
||||
FixedGuardNode deopt = new FixedGuardNode(LogicConstantNode.forBoolean(result, node.graph()), node.getReason(), node.getAction(), node.getSpeculation(), node.isNegated(),
|
||||
node.getNodeSourcePosition());
|
||||
AbstractBeginNode beginNode = (AbstractBeginNode) node.getAnchor();
|
||||
FixedNode next = beginNode.next();
|
||||
beginNode.setNext(deopt);
|
||||
GraphUtil.killCFG(next);
|
||||
graph.addAfterFixed(beginNode, node.graph().add(deopt));
|
||||
|
||||
}
|
||||
return true;
|
||||
})) {
|
||||
@ -354,10 +361,8 @@ public class ConditionalEliminationPhase extends BasePhase<PhaseContext> {
|
||||
GraphUtil.unlinkFixedNode(node);
|
||||
GraphUtil.killWithUnusedFloatingInputs(node);
|
||||
} else {
|
||||
DeoptimizeNode deopt = node.graph().add(new DeoptimizeNode(node.getAction(), node.getReason(), node.getSpeculation()));
|
||||
deopt.setStateBefore(node.stateBefore());
|
||||
node.replaceAtPredecessor(deopt);
|
||||
GraphUtil.killCFG(node);
|
||||
node.setCondition(LogicConstantNode.forBoolean(result, node.graph()), node.isNegated());
|
||||
// Don't kill this branch immediately, see `processGuard`.
|
||||
}
|
||||
debug.log("Kill fixed guard guard");
|
||||
return true;
|
||||
@ -368,11 +373,10 @@ public class ConditionalEliminationPhase extends BasePhase<PhaseContext> {
|
||||
|
||||
protected void processIf(IfNode node) {
|
||||
tryProveCondition(node.condition(), (guard, result, guardedValueStamp, newInput) -> {
|
||||
node.setCondition(LogicConstantNode.forBoolean(result, node.graph()));
|
||||
AbstractBeginNode survivingSuccessor = node.getSuccessor(result);
|
||||
survivingSuccessor.replaceAtUsages(InputType.Guard, guard.asNode());
|
||||
survivingSuccessor.replaceAtPredecessor(null);
|
||||
node.replaceAtPredecessor(survivingSuccessor);
|
||||
GraphUtil.killCFG(node);
|
||||
// Don't kill the other branch immediately, see `processGuard`.
|
||||
counterIfsKilled.increment(debug);
|
||||
return true;
|
||||
});
|
||||
@ -524,8 +528,7 @@ public class ConditionalEliminationPhase extends BasePhase<PhaseContext> {
|
||||
if (input == null) {
|
||||
input = valueAt;
|
||||
}
|
||||
ValueNode valueNode = graph.maybeAddOrUnique(PiNode.create(input, curBestStamp, (ValueNode) infoElement.guard));
|
||||
valueAt = valueNode;
|
||||
valueAt = graph.maybeAddOrUnique(PiNode.create(input, curBestStamp, (ValueNode) infoElement.guard));
|
||||
}
|
||||
newPhi.addInput(valueAt);
|
||||
}
|
||||
|
@ -41,7 +41,6 @@ import jdk.internal.vm.compiler.collections.Equivalence;
|
||||
import jdk.internal.vm.compiler.collections.UnmodifiableEconomicMap;
|
||||
import jdk.internal.vm.compiler.collections.UnmodifiableMapCursor;
|
||||
import org.graalvm.compiler.api.replacements.MethodSubstitution;
|
||||
import org.graalvm.compiler.api.replacements.Snippet;
|
||||
import org.graalvm.compiler.core.common.GraalOptions;
|
||||
import org.graalvm.compiler.core.common.type.Stamp;
|
||||
import org.graalvm.compiler.core.common.type.StampFactory;
|
||||
@ -674,12 +673,12 @@ public class InliningUtil extends ValueMergeUtil {
|
||||
@SuppressWarnings("try")
|
||||
private static void updateSourcePositions(Invoke invoke, StructuredGraph inlineGraph, UnmodifiableEconomicMap<Node, Node> duplicates, boolean isSub, Mark mark) {
|
||||
FixedNode invokeNode = invoke.asNode();
|
||||
boolean isSubstitution = isSub || inlineGraph.method().getAnnotation(MethodSubstitution.class) != null || inlineGraph.method().getAnnotation(Snippet.class) != null;
|
||||
StructuredGraph invokeGraph = invokeNode.graph();
|
||||
assert !invokeGraph.trackNodeSourcePosition() || inlineGraph.trackNodeSourcePosition() ||
|
||||
isSubstitution : String.format("trackNodeSourcePosition mismatch %s %s != %s %s", invokeGraph, invokeGraph.trackNodeSourcePosition(), inlineGraph,
|
||||
inlineGraph.trackNodeSourcePosition());
|
||||
if (invokeGraph.trackNodeSourcePosition() && invoke.stateAfter() != null) {
|
||||
boolean isSubstitution = isSub || inlineGraph.isSubstitution();
|
||||
assert !invokeGraph.trackNodeSourcePosition() || inlineGraph.trackNodeSourcePosition() ||
|
||||
isSubstitution : String.format("trackNodeSourcePosition mismatch %s %s != %s %s", invokeGraph, invokeGraph.trackNodeSourcePosition(), inlineGraph,
|
||||
inlineGraph.trackNodeSourcePosition());
|
||||
final NodeSourcePosition invokePos = invoke.asNode().getNodeSourcePosition();
|
||||
updateSourcePosition(invokeGraph, duplicates, mark, invokePos, isSubstitution);
|
||||
}
|
||||
|
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 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.phases.common.jmx;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public interface HotSpotMBeanOperationProvider {
|
||||
<T> void registerOperations(Class<T> clazz, Collection<? super T> ops);
|
||||
|
||||
Object invoke(String actionName, Object[] params, String[] signature);
|
||||
}
|
@ -32,6 +32,7 @@ import org.graalvm.compiler.phases.util.Providers;
|
||||
|
||||
import jdk.vm.ci.meta.ConstantReflectionProvider;
|
||||
import jdk.vm.ci.meta.MetaAccessProvider;
|
||||
import org.graalvm.compiler.core.common.spi.ForeignCallsProvider;
|
||||
|
||||
public class PhaseContext {
|
||||
|
||||
@ -41,19 +42,22 @@ public class PhaseContext {
|
||||
private final LoweringProvider lowerer;
|
||||
private final Replacements replacements;
|
||||
private final StampProvider stampProvider;
|
||||
private final ForeignCallsProvider foreignCalls;
|
||||
|
||||
public PhaseContext(MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, ConstantFieldProvider constantFieldProvider, LoweringProvider lowerer, Replacements replacements,
|
||||
StampProvider stampProvider) {
|
||||
StampProvider stampProvider, ForeignCallsProvider foreignCalls) {
|
||||
this.metaAccess = metaAccess;
|
||||
this.constantReflection = constantReflection;
|
||||
this.constantFieldProvider = constantFieldProvider;
|
||||
this.lowerer = lowerer;
|
||||
this.replacements = replacements;
|
||||
this.stampProvider = stampProvider;
|
||||
this.foreignCalls = foreignCalls;
|
||||
}
|
||||
|
||||
public PhaseContext(Providers providers) {
|
||||
this(providers.getMetaAccess(), providers.getConstantReflection(), providers.getConstantFieldProvider(), providers.getLowerer(), providers.getReplacements(), providers.getStampProvider());
|
||||
this(providers.getMetaAccess(), providers.getConstantReflection(), providers.getConstantFieldProvider(), providers.getLowerer(), providers.getReplacements(), providers.getStampProvider(),
|
||||
providers.getForeignCalls());
|
||||
}
|
||||
|
||||
public MetaAccessProvider getMetaAccess() {
|
||||
@ -80,4 +84,7 @@ public class PhaseContext {
|
||||
return stampProvider;
|
||||
}
|
||||
|
||||
public ForeignCallsProvider getForeignCalls() {
|
||||
return foreignCalls;
|
||||
}
|
||||
}
|
||||
|
@ -140,7 +140,7 @@ public class PEGraphDecoderTest extends GraalCompilerTest {
|
||||
CachingPEGraphDecoder decoder = new CachingPEGraphDecoder(getTarget().arch, targetGraph, getProviders(), graphBuilderConfig, OptimisticOptimizations.NONE, AllowAssumptions.YES,
|
||||
null, null, new InlineInvokePlugin[]{new InlineAll()}, null, null, null, null);
|
||||
|
||||
decoder.decode(testMethod, false);
|
||||
decoder.decode(testMethod, false, false);
|
||||
debug.dump(DebugContext.BASIC_LEVEL, targetGraph, "Target Graph");
|
||||
targetGraph.verify();
|
||||
|
||||
|
@ -83,9 +83,15 @@ public class CachingPEGraphDecoder extends PEGraphDecoder {
|
||||
}
|
||||
|
||||
@SuppressWarnings("try")
|
||||
private EncodedGraph createGraph(ResolvedJavaMethod method, ResolvedJavaMethod originalMethod, BytecodeProvider intrinsicBytecodeProvider) {
|
||||
StructuredGraph graphToEncode = new StructuredGraph.Builder(options, debug, allowAssumptions).useProfilingInfo(false).trackNodeSourcePosition(
|
||||
graphBuilderConfig.trackNodeSourcePosition()).method(method).build();
|
||||
private EncodedGraph createGraph(ResolvedJavaMethod method, ResolvedJavaMethod originalMethod, BytecodeProvider intrinsicBytecodeProvider, boolean isSubstitution) {
|
||||
// @formatter:off
|
||||
StructuredGraph graphToEncode = new StructuredGraph.Builder(options, debug, allowAssumptions).
|
||||
useProfilingInfo(false).
|
||||
trackNodeSourcePosition(graphBuilderConfig.trackNodeSourcePosition()).
|
||||
method(method).
|
||||
setIsSubstitution(isSubstitution).
|
||||
build();
|
||||
// @formatter:on
|
||||
try (DebugContext.Scope scope = debug.scope("createGraph", graphToEncode)) {
|
||||
IntrinsicContext initialIntrinsicContext = intrinsicBytecodeProvider != null ? new IntrinsicContext(originalMethod, method, intrinsicBytecodeProvider, INLINE_AFTER_PARSING) : null;
|
||||
GraphBuilderPhase.Instance graphBuilderPhaseInstance = createGraphBuilderPhaseInstance(initialIntrinsicContext);
|
||||
@ -110,10 +116,11 @@ public class CachingPEGraphDecoder extends PEGraphDecoder {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected EncodedGraph lookupEncodedGraph(ResolvedJavaMethod method, ResolvedJavaMethod originalMethod, BytecodeProvider intrinsicBytecodeProvider, boolean trackNodeSourcePosition) {
|
||||
protected EncodedGraph lookupEncodedGraph(ResolvedJavaMethod method, ResolvedJavaMethod originalMethod, BytecodeProvider intrinsicBytecodeProvider, boolean isSubstitution,
|
||||
boolean trackNodeSourcePosition) {
|
||||
EncodedGraph result = graphCache.get(method);
|
||||
if (result == null && method.hasBytecodes()) {
|
||||
result = createGraph(method, originalMethod, intrinsicBytecodeProvider);
|
||||
result = createGraph(method, originalMethod, intrinsicBytecodeProvider, isSubstitution);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -94,7 +94,7 @@ public class IntrinsicGraphBuilder implements GraphBuilderContext, Receiver {
|
||||
this.stampProvider = stampProvider;
|
||||
this.code = code;
|
||||
this.method = code.getMethod();
|
||||
this.graph = new StructuredGraph.Builder(options, debug, allowAssumptions).method(method).build();
|
||||
this.graph = new StructuredGraph.Builder(options, debug, allowAssumptions).method(method).setIsSubstitution(true).build();
|
||||
this.graph.setTrackNodeSourcePosition();
|
||||
this.invokeBci = invokeBci;
|
||||
this.lastInstr = graph.start();
|
||||
|
@ -551,8 +551,8 @@ public abstract class PEGraphDecoder extends SimplifyingGraphDecoder {
|
||||
}
|
||||
}
|
||||
|
||||
public void decode(ResolvedJavaMethod method, boolean trackNodeSourcePosition) {
|
||||
PEMethodScope methodScope = new PEMethodScope(graph, null, null, lookupEncodedGraph(method, null, null, trackNodeSourcePosition), method, null, 0, loopExplosionPlugin, null);
|
||||
public void decode(ResolvedJavaMethod method, boolean isSubstitution, boolean trackNodeSourcePosition) {
|
||||
PEMethodScope methodScope = new PEMethodScope(graph, null, null, lookupEncodedGraph(method, null, null, isSubstitution, trackNodeSourcePosition), method, null, 0, loopExplosionPlugin, null);
|
||||
decode(createInitialLoopScope(methodScope, null));
|
||||
cleanupGraph(methodScope);
|
||||
|
||||
@ -783,7 +783,9 @@ public abstract class PEGraphDecoder extends SimplifyingGraphDecoder {
|
||||
return null;
|
||||
}
|
||||
ResolvedJavaMethod inlineMethod = inlineInfo.getMethodToInline();
|
||||
EncodedGraph graphToInline = lookupEncodedGraph(inlineMethod, inlineInfo.getOriginalMethod(), inlineInfo.getIntrinsicBytecodeProvider(), graph.trackNodeSourcePosition());
|
||||
ResolvedJavaMethod originalMethod = inlineInfo.getOriginalMethod();
|
||||
boolean isSubstitution = originalMethod != null && !originalMethod.equals(inlineMethod);
|
||||
EncodedGraph graphToInline = lookupEncodedGraph(inlineMethod, originalMethod, inlineInfo.getIntrinsicBytecodeProvider(), isSubstitution, graph.trackNodeSourcePosition());
|
||||
if (graphToInline == null) {
|
||||
return null;
|
||||
}
|
||||
@ -1052,7 +1054,8 @@ public abstract class PEGraphDecoder extends SimplifyingGraphDecoder {
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract EncodedGraph lookupEncodedGraph(ResolvedJavaMethod method, ResolvedJavaMethod originalMethod, BytecodeProvider intrinsicBytecodeProvider, boolean trackNodeSourcePosition);
|
||||
protected abstract EncodedGraph lookupEncodedGraph(ResolvedJavaMethod method, ResolvedJavaMethod originalMethod, BytecodeProvider intrinsicBytecodeProvider, boolean isSubstitution,
|
||||
boolean trackNodeSourcePosition);
|
||||
|
||||
@Override
|
||||
protected void handleFixedNode(MethodScope s, LoopScope loopScope, int nodeOrderId, FixedNode node) {
|
||||
|
@ -429,10 +429,16 @@ public class ReplacementsImpl implements Replacements, InlineInvokePlugin {
|
||||
@SuppressWarnings("try")
|
||||
protected StructuredGraph buildInitialGraph(DebugContext debug, BytecodeProvider bytecodeProvider, final ResolvedJavaMethod methodToParse, Object[] args, boolean trackNodeSourcePosition,
|
||||
NodeSourcePosition replaceePosition) {
|
||||
// @formatter:off
|
||||
// Replacements cannot have optimistic assumptions since they have
|
||||
// to be valid for the entire run of the VM.
|
||||
final StructuredGraph graph = new StructuredGraph.Builder(replacements.options, debug).method(methodToParse).trackNodeSourcePosition(trackNodeSourcePosition).callerContext(
|
||||
replaceePosition).build();
|
||||
final StructuredGraph graph = new StructuredGraph.Builder(replacements.options, debug).
|
||||
method(methodToParse).
|
||||
trackNodeSourcePosition(trackNodeSourcePosition).
|
||||
callerContext(replaceePosition).
|
||||
setIsSubstitution(true).
|
||||
build();
|
||||
// @formatter:on
|
||||
|
||||
// Replacements are not user code so they do not participate in unsafe access
|
||||
// tracking
|
||||
|
@ -723,7 +723,7 @@ public class SnippetTemplate {
|
||||
|
||||
// Copy snippet graph, replacing constant parameters with given arguments
|
||||
final StructuredGraph snippetCopy = new StructuredGraph.Builder(options, debug).name(snippetGraph.name).method(snippetGraph.method()).trackNodeSourcePosition(
|
||||
snippetGraph.trackNodeSourcePosition()).build();
|
||||
snippetGraph.trackNodeSourcePosition()).setIsSubstitution(true).build();
|
||||
assert !GraalOptions.TrackNodeSourcePosition.getValue(options) || snippetCopy.trackNodeSourcePosition();
|
||||
if (providers.getCodeCache() != null && providers.getCodeCache().shouldDebugNonSafepoints()) {
|
||||
snippetCopy.setTrackNodeSourcePosition();
|
||||
|
@ -155,7 +155,7 @@ public abstract class MacroNode extends FixedWithNextNode implements Lowerable,
|
||||
@SuppressWarnings("try")
|
||||
protected StructuredGraph lowerReplacement(final StructuredGraph replacementGraph, LoweringTool tool) {
|
||||
final PhaseContext c = new PhaseContext(tool.getMetaAccess(), tool.getConstantReflection(), tool.getConstantFieldProvider(), tool.getLowerer(), tool.getReplacements(),
|
||||
tool.getStampProvider());
|
||||
tool.getStampProvider(), null);
|
||||
if (!graph().hasValueProxies()) {
|
||||
new RemoveValueProxyPhase().apply(replacementGraph);
|
||||
}
|
||||
|
@ -211,9 +211,9 @@ public final class GraphOutput<G, M> implements Closeable {
|
||||
* <p>
|
||||
* Both GraphOutput (the {@code parent} and the returned one) has to be used in
|
||||
* synchronization - e.g. only one
|
||||
* {@link #beginGroup(java.lang.Object, java.lang.String, java.lang.String, java.lang.Object, int, java.util.Map)
|
||||
* begin}, {@link #endGroup() end} of group or
|
||||
* {@link #print(java.lang.Object, java.util.Map, int, java.lang.String, java.lang.Object...)
|
||||
* {@link GraphOutput#beginGroup(java.lang.Object, java.lang.String, java.lang.String, java.lang.Object, int, java.util.Map)
|
||||
* begin}, {@link GraphOutput#endGroup() end} of group or
|
||||
* {@link GraphOutput#print(java.lang.Object, java.util.Map, int, java.lang.String, java.lang.Object...)
|
||||
* printing} can be on at a given moment.
|
||||
*
|
||||
* @param parent the output to inherit {@code channel} and protocol version from
|
||||
|
Loading…
x
Reference in New Issue
Block a user