use of jdk.vm.ci.meta.JavaKind in project graal by oracle.
the class PEReadEliminationClosure method processLoadIndexed.
private boolean processLoadIndexed(LoadIndexedNode load, PEReadEliminationBlockState state, GraphEffectList effects) {
if (load.index().isConstant()) {
int index = ((JavaConstant) load.index().asConstant()).asInt();
// BALOAD (with elementKind being Byte) can be used to retrieve values from boolean
// arrays.
JavaKind elementKind = load.elementKind();
if (elementKind == JavaKind.Byte) {
elementKind = getElementKindFromStamp(load.array());
if (elementKind == JavaKind.Illegal) {
return false;
}
}
LocationIdentity arrayLocation = NamedLocationIdentity.getArrayLocation(elementKind);
return processLoad(load, load.array(), arrayLocation, index, elementKind, state, effects);
}
return false;
}
use of jdk.vm.ci.meta.JavaKind in project graal by oracle.
the class VirtualizerToolImpl method setVirtualEntry.
@Override
public boolean setVirtualEntry(VirtualObjectNode virtual, int index, ValueNode value, JavaKind theAccessKind, long offset) {
ObjectState obj = state.getObjectState(virtual);
assert obj.isVirtual() : "not virtual: " + obj;
ValueNode newValue;
JavaKind entryKind = virtual.entryKind(index);
JavaKind accessKind = theAccessKind != null ? theAccessKind : entryKind;
if (value == null) {
newValue = null;
} else {
newValue = closure.getAliasAndResolve(state, value);
}
getDebug().log(DebugContext.DETAILED_LEVEL, "Setting entry %d in virtual object %s %s results in %s", index, virtual.getObjectId(), virtual, state.getObjectState(virtual.getObjectId()));
ValueNode oldValue = getEntry(virtual, index);
boolean canVirtualize = entryKind == accessKind || (entryKind == accessKind.getStackKind() && virtual instanceof VirtualInstanceNode);
if (!canVirtualize) {
if (entryKind == JavaKind.Long && oldValue.getStackKind() == newValue.getStackKind() && oldValue.getStackKind().isPrimitive()) {
/*
* Special case: If the entryKind is long, allow arbitrary kinds as long as a value
* of the same kind is already there. This can only happen if some other node
* initialized the entry with a value of a different kind. One example where this
* happens is the Truffle NewFrameNode.
*/
getDebug().log(DebugContext.DETAILED_LEVEL, "virtualizing %s with primitive of kind %s in long entry ", current, oldValue.getStackKind());
canVirtualize = true;
} else if (entryKind == JavaKind.Int && (accessKind == JavaKind.Long || accessKind == JavaKind.Double) && offset % 8 == 0) {
/*
* Special case: Allow storing a single long or double value into two consecutive
* int slots.
*/
int nextIndex = virtual.entryIndexForOffset(getArrayOffsetProvider(), offset + 4, JavaKind.Int);
if (nextIndex != -1) {
canVirtualize = true;
assert nextIndex == index + 1 : "expected to be sequential";
getDebug().log(DebugContext.DETAILED_LEVEL, "virtualizing %s for double word stored in two ints", current);
}
}
}
if (canVirtualize) {
getDebug().log(DebugContext.DETAILED_LEVEL, "virtualizing %s for entryKind %s and access kind %s", current, entryKind, accessKind);
state.setEntry(virtual.getObjectId(), index, newValue);
if (entryKind == JavaKind.Int) {
if (accessKind.needsTwoSlots()) {
// Storing double word value two int slots
assert virtual.entryKind(index + 1) == JavaKind.Int;
state.setEntry(virtual.getObjectId(), index + 1, getIllegalConstant());
} else if (oldValue.getStackKind() == JavaKind.Double || oldValue.getStackKind() == JavaKind.Long) {
// Splitting double word constant by storing over it with an int
getDebug().log(DebugContext.DETAILED_LEVEL, "virtualizing %s producing second half of double word value %s", current, oldValue);
ValueNode secondHalf = UnpackEndianHalfNode.create(oldValue, false, NodeView.DEFAULT);
addNode(secondHalf);
state.setEntry(virtual.getObjectId(), index + 1, secondHalf);
}
}
if (oldValue.isConstant() && oldValue.asConstant().equals(JavaConstant.forIllegal())) {
// Storing into second half of double, so replace previous value
ValueNode previous = getEntry(virtual, index - 1);
getDebug().log(DebugContext.DETAILED_LEVEL, "virtualizing %s producing first half of double word value %s", current, previous);
ValueNode firstHalf = UnpackEndianHalfNode.create(previous, true, NodeView.DEFAULT);
addNode(firstHalf);
state.setEntry(virtual.getObjectId(), index - 1, firstHalf);
}
return true;
}
// Should only occur if there are mismatches between the entry and access kind
assert entryKind != accessKind;
return false;
}
use of jdk.vm.ci.meta.JavaKind in project graal by oracle.
the class JNIJavaCallWrapperMethod method loadAndUnboxArguments.
private List<Pair<ValueNode, ResolvedJavaType>> loadAndUnboxArguments(JNIGraphKit kit, HostedProviders providers, ResolvedJavaMethod invokeMethod, Signature invokeSignature) {
MetaAccessProvider metaAccess = providers.getMetaAccess();
List<Pair<ValueNode, ResolvedJavaType>> args = new ArrayList<>();
int javaIndex = 0;
javaIndex += metaAccess.lookupJavaType(JNIEnvironment.class).getJavaKind().getSlotCount();
if (!invokeMethod.isStatic()) {
JavaKind kind = metaAccess.lookupJavaType(JNIObjectHandle.class).getJavaKind();
ValueNode handle = kit.loadLocal(javaIndex, kind);
ValueNode unboxed = kit.unboxHandle(handle);
ValueNode receiver;
ResolvedJavaType receiverClass = invokeMethod.getDeclaringClass();
if (invokeMethod.isConstructor()) {
/*
* Our target method is a constructor and we might be called via `NewObject`, in
* which case we need to allocate the object before calling the constructor. We can
* detect when this is the case because unlike with `Call<Type>Method`, we are
* passed the object hub of our target class in place of the receiver object.
*/
Constant hub = providers.getConstantReflection().asObjectHub(receiverClass);
ConstantNode hubNode = kit.createConstant(hub, JavaKind.Object);
kit.startIf(kit.unique(new ObjectEqualsNode(unboxed, hubNode)), BranchProbabilityNode.FAST_PATH_PROBABILITY);
kit.thenPart();
ValueNode created = kit.append(new NewInstanceNode(receiverClass, true));
AbstractMergeNode merge = kit.endIf();
receiver = kit.unique(new ValuePhiNode(StampFactory.object(), merge, new ValueNode[] { created, unboxed }));
} else {
receiver = unboxed;
}
args.add(Pair.create(receiver, receiverClass));
}
javaIndex += metaAccess.lookupJavaType(JNIObjectHandle.class).getJavaKind().getSlotCount();
if (nonVirtual) {
javaIndex += metaAccess.lookupJavaType(JNIObjectHandle.class).getJavaKind().getSlotCount();
}
javaIndex += metaAccess.lookupJavaType(JNIMethodId.class).getJavaKind().getSlotCount();
int count = invokeSignature.getParameterCount(false);
if (callVariant == CallVariant.VARARGS) {
for (int i = 0; i < count; i++) {
ResolvedJavaType type = (ResolvedJavaType) invokeSignature.getParameterType(i, null);
JavaKind kind = type.getJavaKind();
JavaKind loadKind = kind;
if (loadKind == JavaKind.Float) {
// C varargs promote float to double
loadKind = JavaKind.Double;
}
ValueNode value = kit.loadLocal(javaIndex, loadKind);
if (kind == JavaKind.Float) {
value = kit.unique(new FloatConvertNode(FloatConvert.D2F, value));
} else if (kind.isObject()) {
value = kit.unboxHandle(value);
}
args.add(Pair.create(value, type));
javaIndex += loadKind.getSlotCount();
}
} else if (callVariant == CallVariant.ARRAY) {
ResolvedJavaType elementType = metaAccess.lookupJavaType(JNIValue.class);
int elementSize = SizeOf.get(JNIValue.class);
ValueNode array = kit.loadLocal(javaIndex, elementType.getJavaKind());
for (int i = 0; i < count; i++) {
ResolvedJavaType type = (ResolvedJavaType) invokeSignature.getParameterType(i, null);
JavaKind readKind = type.getJavaKind();
StructFieldInfo fieldInfo = getJNIValueOffsetOf(elementType, readKind);
int offset = i * elementSize + fieldInfo.getOffsetInfo().getProperty();
ConstantNode offsetConstant = kit.createConstant(JavaConstant.forInt(offset), providers.getWordTypes().getWordKind());
OffsetAddressNode address = kit.unique(new OffsetAddressNode(array, offsetConstant));
LocationIdentity locationIdentity = fieldInfo.getLocationIdentity();
if (locationIdentity == null) {
locationIdentity = LocationIdentity.any();
}
Stamp readStamp = getNarrowStamp(providers, readKind);
ValueNode value = kit.append(new CInterfaceReadNode(address, locationIdentity, readStamp, BarrierType.NONE, "args[" + i + "]"));
JavaKind stackKind = readKind.getStackKind();
if (readKind != stackKind) {
assert stackKind.getBitCount() > readKind.getBitCount() : "read kind must be narrower than stack kind";
if (readKind.isUnsigned()) {
// needed or another op may illegally sign-extend
value = kit.unique(new ZeroExtendNode(value, stackKind.getBitCount()));
} else {
value = kit.unique(new SignExtendNode(value, stackKind.getBitCount()));
}
} else if (readKind.isObject()) {
value = kit.unboxHandle(value);
}
args.add(Pair.create(value, type));
}
} else if (callVariant == CallVariant.VA_LIST) {
ValueNode valist = kit.loadLocal(javaIndex, metaAccess.lookupJavaType(WordBase.class).getJavaKind());
for (int i = 0; i < count; i++) {
ResolvedJavaType type = (ResolvedJavaType) invokeSignature.getParameterType(i, null);
JavaKind loadKind = type.getJavaKind();
if (loadKind.isObject()) {
loadKind = providers.getWordTypes().getWordKind();
}
ValueNode value = kit.append(new VaListNextArgNode(loadKind, valist));
if (type.getJavaKind().isObject()) {
value = kit.unboxHandle(value);
}
args.add(Pair.create(value, type));
}
} else {
throw VMError.unsupportedFeature("Call variant: " + callVariant);
}
return args;
}
use of jdk.vm.ci.meta.JavaKind in project graal by oracle.
the class JNIJavaCallWrapperMethod method createSignature.
private JNISignature createSignature(MetaAccessProvider metaAccess) {
ResolvedJavaType objectHandle = metaAccess.lookupJavaType(JNIObjectHandle.class);
List<JavaType> args = new ArrayList<>();
args.add(metaAccess.lookupJavaType(JNIEnvironment.class));
// this (instance method) or class (static method)
args.add(objectHandle);
if (nonVirtual) {
// class of implementation to invoke
args.add(objectHandle);
}
args.add(metaAccess.lookupJavaType(JNIMethodId.class));
Signature targetSignature = targetMethod.getSignature();
if (callVariant == CallVariant.VARARGS) {
for (JavaType targetArg : targetSignature.toParameterTypes(null)) {
JavaKind kind = targetArg.getJavaKind();
if (kind.isObject()) {
args.add(objectHandle);
} else if (kind == JavaKind.Float) {
// C varargs promote float to double
args.add(metaAccess.lookupJavaType(JavaKind.Double.toJavaClass()));
} else {
args.add(targetArg);
}
}
} else if (callVariant == CallVariant.ARRAY) {
// const jvalue *
args.add(metaAccess.lookupJavaType(JNIValue.class));
} else if (callVariant == CallVariant.VA_LIST) {
// va_list (a pointer of some kind)
args.add(metaAccess.lookupJavaType(WordBase.class));
} else {
throw VMError.shouldNotReachHere();
}
JavaType returnType = targetSignature.getReturnType(null);
if (returnType.getJavaKind().isObject() || targetMethod.isConstructor()) {
// Constructor: returns `this` to implement NewObject
returnType = objectHandle;
}
return new JNISignature(args, returnType);
}
use of jdk.vm.ci.meta.JavaKind in project graal by oracle.
the class JNIJavaCallWrapperMethod method buildGraph.
@Override
public StructuredGraph buildGraph(DebugContext debug, ResolvedJavaMethod method, HostedProviders providers, Purpose purpose) {
UniverseMetaAccess metaAccess = (UniverseMetaAccess) providers.getMetaAccess();
JNIGraphKit kit = new JNIGraphKit(debug, providers, method);
StructuredGraph graph = kit.getGraph();
FrameStateBuilder state = new FrameStateBuilder(null, method, graph);
state.initializeForMethodStart(null, true, providers.getGraphBuilderPlugins());
JavaKind vmThreadKind = metaAccess.lookupJavaType(JNIEnvironment.class).getJavaKind();
ValueNode vmThread = kit.loadLocal(0, vmThreadKind);
kit.append(new CEntryPointEnterNode(EnterAction.Enter, vmThread));
ResolvedJavaMethod invokeMethod = providers.getMetaAccess().lookupJavaMethod(reflectMethod);
Signature invokeSignature = invokeMethod.getSignature();
List<Pair<ValueNode, ResolvedJavaType>> argsWithTypes = loadAndUnboxArguments(kit, providers, invokeMethod, invokeSignature);
JavaKind returnKind = invokeSignature.getReturnKind();
if (invokeMethod.isConstructor()) {
// return `this` to implement NewObject
assert returnKind == JavaKind.Void;
returnKind = JavaKind.Object;
}
IfNode ifNode = kit.startIf(null, BranchProbabilityNode.FAST_PATH_PROBABILITY);
kit.thenPart();
LogicNode typeChecks = LogicConstantNode.tautology(kit.getGraph());
ValueNode[] args = new ValueNode[argsWithTypes.size()];
for (int i = 0; i < argsWithTypes.size(); i++) {
ValueNode value = argsWithTypes.get(i).getLeft();
ResolvedJavaType type = argsWithTypes.get(i).getRight();
if (!type.isPrimitive() && !type.isJavaLangObject()) {
TypeReference typeRef = TypeReference.createTrusted(kit.getAssumptions(), type);
LogicNode instanceOf = kit.unique(InstanceOfNode.createAllowNull(typeRef, value, null, null));
typeChecks = LogicNode.and(typeChecks, instanceOf, BranchProbabilityNode.FAST_PATH_PROBABILITY);
FixedGuardNode guard = kit.append(new FixedGuardNode(instanceOf, DeoptimizationReason.ClassCastException, DeoptimizationAction.None, false));
value = kit.append(PiNode.create(value, StampFactory.object(typeRef), guard));
}
args[i] = value;
}
// safe because logic nodes are floating
ifNode.setCondition(typeChecks);
InvokeKind kind = //
invokeMethod.isStatic() ? //
InvokeKind.Static : ((nonVirtual || invokeMethod.isConstructor()) ? InvokeKind.Special : InvokeKind.Virtual);
ValueNode invokeResult = createInvoke(kit, invokeMethod, kind, state, kit.bci(), args);
if (invokeMethod.isConstructor()) {
// return `this` to implement NewObject
invokeResult = args[0];
}
// illegal parameter types
kit.elsePart();
ConstantNode exceptionObject = kit.createObject(cachedArgumentClassCastException);
kit.retainPendingException(exceptionObject);
ValueNode typeMismatchValue = null;
if (returnKind != JavaKind.Void) {
typeMismatchValue = kit.unique(ConstantNode.defaultForKind(returnKind.getStackKind()));
}
AbstractMergeNode merge = kit.endIf();
ValueNode returnValue = null;
if (returnKind != JavaKind.Void) {
ValueNode[] inputs = { invokeResult, typeMismatchValue };
returnValue = kit.getGraph().addWithoutUnique(new ValuePhiNode(invokeResult.stamp(NodeView.DEFAULT), merge, inputs));
state.push(returnKind, returnValue);
}
merge.setStateAfter(state.create(kit.bci(), merge));
if (returnKind != JavaKind.Void) {
state.pop(returnKind);
if (returnKind.isObject()) {
returnValue = kit.boxObjectInLocalHandle(returnValue);
}
}
kit.append(new CEntryPointLeaveNode(LeaveAction.Leave));
kit.createReturn(returnValue, returnKind);
assert graph.verify();
return graph;
}
Aggregations