use of jdk.vm.ci.meta.JavaConstant in project graal by oracle.
the class InfoTreeBuilder method createEnumConstantInfo.
private void createEnumConstantInfo(EnumInfo enumInfo, ResolvedJavaField field) {
JavaConstant enumValue = nativeLibs.getConstantReflection().readFieldValue(field, null);
assert enumValue.isNonNull() && nativeLibs.getMetaAccess().lookupJavaType(enumValue).equals(enumInfo.getAnnotatedElement());
CEnumConstant fieldAnnotation = field.getAnnotation(CEnumConstant.class);
String name = "";
boolean includeInLookup = true;
if (fieldAnnotation != null) {
name = fieldAnnotation.value();
includeInLookup = fieldAnnotation.includeInLookup();
}
if (name.length() == 0) {
name = field.getName();
}
EnumConstantInfo constantInfo = new EnumConstantInfo(name, field, includeInLookup, nativeLibs.getSnippetReflection().asObject(Enum.class, enumValue));
enumInfo.adoptChild(constantInfo);
}
use of jdk.vm.ci.meta.JavaConstant in project graal by oracle.
the class BytecodeParser method getJsrConstant.
private ConstantNode getJsrConstant(long bci) {
JavaConstant nextBciConstant = new RawConstant(bci);
Stamp nextBciStamp = StampFactory.forConstant(nextBciConstant);
ConstantNode nextBciNode = new ConstantNode(nextBciConstant, nextBciStamp);
return graph.unique(nextBciNode);
}
use of jdk.vm.ci.meta.JavaConstant in project graal by oracle.
the class AArch64Compare method gpCompare.
/**
* Compares integer values x and y.
*
* @param x integer value to compare. May not be null.
* @param y integer value to compare. May not be null.
*/
public static void gpCompare(AArch64MacroAssembler masm, Value x, Value y) {
final int size = x.getPlatformKind().getSizeInBytes() * Byte.SIZE;
if (isRegister(y)) {
masm.cmp(size, asRegister(x), asRegister(y));
} else {
JavaConstant constant = asJavaConstant(y);
if (constant.isDefaultForKind()) {
masm.cmp(size, asRegister(x), 0);
} else {
final long longValue = constant.asLong();
assert NumUtil.isInt(longValue);
int maskedValue;
switch(constant.getJavaKind()) {
case Boolean:
case Byte:
maskedValue = (int) (longValue & 0xFF);
break;
case Char:
case Short:
maskedValue = (int) (longValue & 0xFFFF);
break;
case Int:
case Long:
maskedValue = (int) longValue;
break;
default:
throw GraalError.shouldNotReachHere();
}
masm.cmp(size, asRegister(x), maskedValue);
}
}
}
use of jdk.vm.ci.meta.JavaConstant in project graal by oracle.
the class ObjectEqualsNode method virtualizeNonVirtualComparison.
private void virtualizeNonVirtualComparison(VirtualObjectNode virtual, ValueNode other, VirtualizerTool tool) {
if (virtual instanceof VirtualBoxingNode && other.isConstant()) {
VirtualBoxingNode virtualBoxingNode = (VirtualBoxingNode) virtual;
if (virtualBoxingNode.getBoxingKind() == JavaKind.Boolean) {
JavaConstant otherUnboxed = tool.getConstantReflectionProvider().unboxPrimitive(other.asJavaConstant());
if (otherUnboxed != null && otherUnboxed.getJavaKind() == JavaKind.Boolean) {
int expectedValue = otherUnboxed.asBoolean() ? 1 : 0;
IntegerEqualsNode equals = new IntegerEqualsNode(virtualBoxingNode.getBoxedValue(tool), ConstantNode.forInt(expectedValue, graph()));
tool.addNode(equals);
tool.replaceWithValue(equals);
} else {
tool.replaceWithValue(LogicConstantNode.contradiction(graph()));
}
}
}
if (virtual.hasIdentity()) {
// one of them is virtual: they can never be the same objects
tool.replaceWithValue(LogicConstantNode.contradiction(graph()));
}
}
use of jdk.vm.ci.meta.JavaConstant in project graal by oracle.
the class IntegerSwitchNode method tryOptimizeEnumSwitch.
/**
* For switch statements on enum values, the Java compiler has to generate complicated code:
* because {@link Enum#ordinal()} can change when recompiling an enum, it cannot be used
* directly as the value that is switched on. An intermediate int[] array, which is initialized
* once at run time based on the actual {@link Enum#ordinal()} values, is used.
*
* The {@link ConstantFieldProvider} of Graal already detects the int[] arrays and marks them as
* {@link ConstantNode#isDefaultStable() stable}, i.e., the array elements are constant. The
* code in this method detects array loads from such a stable array and re-wires the switch to
* use the keys from the array elements, so that the array load is unnecessary.
*/
private boolean tryOptimizeEnumSwitch(SimplifierTool tool) {
if (!(value() instanceof LoadIndexedNode)) {
/* Not the switch pattern we are looking for. */
return false;
}
LoadIndexedNode loadIndexed = (LoadIndexedNode) value();
if (loadIndexed.usages().count() > 1) {
/*
* The array load is necessary for other reasons too, so there is no benefit optimizing
* the switch.
*/
return false;
}
assert loadIndexed.usages().first() == this;
ValueNode newValue = loadIndexed.index();
JavaConstant arrayConstant = loadIndexed.array().asJavaConstant();
if (arrayConstant == null || ((ConstantNode) loadIndexed.array()).getStableDimension() != 1 || !((ConstantNode) loadIndexed.array()).isDefaultStable()) {
/*
* The array is a constant that we can optimize. We require the array elements to be
* constant too, since we put them as literal constants into the switch keys.
*/
return false;
}
Integer optionalArrayLength = tool.getConstantReflection().readArrayLength(arrayConstant);
if (optionalArrayLength == null) {
/* Loading a constant value can be denied by the VM. */
return false;
}
int arrayLength = optionalArrayLength;
Map<Integer, List<Integer>> reverseArrayMapping = new HashMap<>();
for (int i = 0; i < arrayLength; i++) {
JavaConstant elementConstant = tool.getConstantReflection().readArrayElement(arrayConstant, i);
if (elementConstant == null || elementConstant.getJavaKind() != JavaKind.Int) {
/* Loading a constant value can be denied by the VM. */
return false;
}
int element = elementConstant.asInt();
/*
* The value loaded from the array is the old switch key, the index into the array is
* the new switch key. We build a mapping from the old switch key to new keys.
*/
reverseArrayMapping.computeIfAbsent(element, e -> new ArrayList<>()).add(i);
}
/* Build high-level representation of new switch keys. */
List<KeyData> newKeyDatas = new ArrayList<>(arrayLength);
ArrayList<AbstractBeginNode> newSuccessors = new ArrayList<>(blockSuccessorCount());
for (int i = 0; i < keys.length; i++) {
List<Integer> newKeys = reverseArrayMapping.get(keys[i]);
if (newKeys == null || newKeys.size() == 0) {
/* The switch case is unreachable, we can ignore it. */
continue;
}
/*
* We do not have detailed profiling information about the individual new keys, so we
* have to assume they split the probability of the old key.
*/
double newKeyProbability = keyProbabilities[i] / newKeys.size();
int newKeySuccessor = addNewSuccessor(keySuccessor(i), newSuccessors);
for (int newKey : newKeys) {
newKeyDatas.add(new KeyData(newKey, newKeyProbability, newKeySuccessor));
}
}
int newDefaultSuccessor = addNewSuccessor(defaultSuccessor(), newSuccessors);
double newDefaultProbability = keyProbabilities[keyProbabilities.length - 1];
/*
* We remove the array load, but we still need to preserve exception semantics by keeping
* the bounds check. Fortunately the array length is a constant.
*/
LogicNode boundsCheck = graph().unique(new IntegerBelowNode(newValue, ConstantNode.forInt(arrayLength, graph())));
graph().addBeforeFixed(this, graph().add(new FixedGuardNode(boundsCheck, DeoptimizationReason.BoundsCheckException, DeoptimizationAction.InvalidateReprofile)));
/*
* Build the low-level representation of the new switch keys and replace ourself with a new
* node.
*/
doReplace(newValue, newKeyDatas, newSuccessors, newDefaultSuccessor, newDefaultProbability);
/* The array load is now unnecessary. */
assert loadIndexed.hasNoUsages();
GraphUtil.removeFixedWithUnusedInputs(loadIndexed);
return true;
}
Aggregations