use of org.graalvm.compiler.nodes.java.MonitorEnterNode in project graal by oracle.
the class DefaultJavaLoweringProvider method finishAllocatedObjects.
public void finishAllocatedObjects(LoweringTool tool, CommitAllocationNode commit, ValueNode[] allocations) {
StructuredGraph graph = commit.graph();
for (int objIndex = 0; objIndex < commit.getVirtualObjects().size(); objIndex++) {
FixedValueAnchorNode anchor = graph.add(new FixedValueAnchorNode(allocations[objIndex]));
allocations[objIndex] = anchor;
graph.addBeforeFixed(commit, anchor);
}
/*
* Note that the FrameState that is assigned to these MonitorEnterNodes isn't the correct
* state. It will be the state from before the allocation occurred instead of a valid state
* after the locking is performed. In practice this should be fine since these are newly
* allocated objects. The bytecodes themselves permit allocating an object, doing a
* monitorenter and then dropping all references to the object which would produce the same
* state, though that would normally produce an IllegalMonitorStateException. In HotSpot
* some form of fast path locking should always occur so the FrameState should never
* actually be used.
*/
ArrayList<MonitorEnterNode> enters = null;
for (int objIndex = 0; objIndex < commit.getVirtualObjects().size(); objIndex++) {
List<MonitorIdNode> locks = commit.getLocks(objIndex);
if (locks.size() > 1) {
// Ensure that the lock operations are performed in lock depth order
ArrayList<MonitorIdNode> newList = new ArrayList<>(locks);
newList.sort((a, b) -> Integer.compare(a.getLockDepth(), b.getLockDepth()));
locks = newList;
}
int lastDepth = -1;
for (MonitorIdNode monitorId : locks) {
assert lastDepth < monitorId.getLockDepth();
lastDepth = monitorId.getLockDepth();
MonitorEnterNode enter = graph.add(new MonitorEnterNode(allocations[objIndex], monitorId));
graph.addBeforeFixed(commit, enter);
if (enters == null) {
enters = new ArrayList<>();
}
enters.add(enter);
}
}
for (Node usage : commit.usages().snapshot()) {
if (usage instanceof AllocatedObjectNode) {
AllocatedObjectNode addObject = (AllocatedObjectNode) usage;
int index = commit.getVirtualObjects().indexOf(addObject.getVirtualObject());
addObject.replaceAtUsagesAndDelete(allocations[index]);
} else {
assert enters != null;
commit.replaceAtUsages(InputType.Memory, enters.get(enters.size() - 1));
}
}
if (enters != null) {
for (MonitorEnterNode enter : enters) {
enter.lower(tool);
}
}
assert commit.hasNoUsages();
insertAllocationBarrier(commit, graph);
}
use of org.graalvm.compiler.nodes.java.MonitorEnterNode in project graal by oracle.
the class JNINativeCallWrapperMethod method buildGraph.
@Override
public StructuredGraph buildGraph(DebugContext debug, ResolvedJavaMethod method, HostedProviders providers, Purpose purpose) {
JNIGraphKit kit = new JNIGraphKit(debug, providers, method);
StructuredGraph graph = kit.getGraph();
InvokeWithExceptionNode handleFrame = kit.nativeCallPrologue();
ValueNode callAddress = kit.nativeCallAddress(kit.createObject(linkage));
ValueNode environment = kit.environment();
JavaType javaReturnType = method.getSignature().getReturnType(null);
JavaType[] javaArgumentTypes = method.toParameterTypes();
List<ValueNode> javaArguments = kit.loadArguments(javaArgumentTypes);
List<ValueNode> jniArguments = new ArrayList<>(2 + javaArguments.size());
List<JavaType> jniArgumentTypes = new ArrayList<>(jniArguments.size());
JavaType environmentType = providers.getMetaAccess().lookupJavaType(JNIEnvironment.class);
JavaType objectHandleType = providers.getMetaAccess().lookupJavaType(JNIObjectHandle.class);
jniArguments.add(environment);
jniArgumentTypes.add(environmentType);
if (method.isStatic()) {
JavaConstant clazz = providers.getConstantReflection().asJavaClass(method.getDeclaringClass());
ConstantNode clazzNode = ConstantNode.forConstant(clazz, providers.getMetaAccess(), graph);
ValueNode box = kit.boxObjectInLocalHandle(clazzNode);
jniArguments.add(box);
jniArgumentTypes.add(objectHandleType);
}
for (int i = 0; i < javaArguments.size(); i++) {
ValueNode arg = javaArguments.get(i);
JavaType argType = javaArgumentTypes[i];
if (javaArgumentTypes[i].getJavaKind().isObject()) {
ValueNode obj = javaArguments.get(i);
arg = kit.boxObjectInLocalHandle(obj);
argType = objectHandleType;
}
jniArguments.add(arg);
jniArgumentTypes.add(argType);
}
assert jniArguments.size() == jniArgumentTypes.size();
JavaType jniReturnType = javaReturnType;
if (jniReturnType.getJavaKind().isObject()) {
jniReturnType = objectHandleType;
}
if (getOriginal().isSynchronized()) {
ValueNode monitorObject;
if (method.isStatic()) {
Constant hubConstant = providers.getConstantReflection().asObjectHub(method.getDeclaringClass());
DynamicHub hub = (DynamicHub) SubstrateObjectConstant.asObject(hubConstant);
monitorObject = ConstantNode.forConstant(SubstrateObjectConstant.forObject(hub), providers.getMetaAccess(), graph);
} else {
monitorObject = javaArguments.get(0);
}
MonitorIdNode monitorId = graph.add(new MonitorIdNode(kit.getFrameState().lockDepth(false)));
MonitorEnterNode monitorEnter = kit.append(new MonitorEnterNode(monitorObject, monitorId));
kit.getFrameState().pushLock(monitorEnter.object(), monitorEnter.getMonitorId());
monitorEnter.setStateAfter(kit.getFrameState().create(kit.bci(), monitorEnter));
}
kit.getFrameState().clearLocals();
Signature jniSignature = new JNISignature(jniArgumentTypes, jniReturnType);
ValueNode returnValue = kit.createCFunctionCall(callAddress, method, jniArguments, jniSignature, true, false);
if (getOriginal().isSynchronized()) {
MonitorIdNode monitorId = kit.getFrameState().peekMonitorId();
ValueNode monitorObject = kit.getFrameState().popLock();
MonitorExitNode monitorExit = kit.append(new MonitorExitNode(monitorObject, monitorId, null));
monitorExit.setStateAfter(kit.getFrameState().create(kit.bci(), monitorExit));
}
if (javaReturnType.getJavaKind().isObject()) {
// before destroying handles in epilogue
returnValue = kit.unboxHandle(returnValue);
}
kit.nativeCallEpilogue(handleFrame);
kit.rethrowPendingException();
if (javaReturnType.getJavaKind().isObject()) {
// Just before return to always run the epilogue and never suppress a pending exception
returnValue = castObject(kit, returnValue, (ResolvedJavaType) javaReturnType);
}
kit.createReturn(returnValue, javaReturnType.getJavaKind());
kit.mergeUnwinds();
assert graph.verify();
return graph;
}
use of org.graalvm.compiler.nodes.java.MonitorEnterNode in project graal by oracle.
the class LoopFragment method computeNodes.
protected static void computeNodes(NodeBitMap nodes, Graph graph, Iterable<AbstractBeginNode> blocks, Iterable<AbstractBeginNode> earlyExits) {
for (AbstractBeginNode b : blocks) {
if (b.isDeleted()) {
continue;
}
for (Node n : b.getBlockNodes()) {
if (n instanceof Invoke) {
nodes.mark(((Invoke) n).callTarget());
}
if (n instanceof NodeWithState) {
NodeWithState withState = (NodeWithState) n;
withState.states().forEach(state -> state.applyToVirtual(node -> nodes.mark(node)));
}
if (n instanceof AbstractMergeNode) {
// if a merge is in the loop, all of its phis are also in the loop
for (PhiNode phi : ((AbstractMergeNode) n).phis()) {
nodes.mark(phi);
}
}
nodes.mark(n);
}
}
for (AbstractBeginNode earlyExit : earlyExits) {
if (earlyExit.isDeleted()) {
continue;
}
nodes.mark(earlyExit);
if (earlyExit instanceof LoopExitNode) {
LoopExitNode loopExit = (LoopExitNode) earlyExit;
FrameState stateAfter = loopExit.stateAfter();
if (stateAfter != null) {
stateAfter.applyToVirtual(node -> nodes.mark(node));
}
for (ProxyNode proxy : loopExit.proxies()) {
nodes.mark(proxy);
}
}
}
final NodeBitMap nonLoopNodes = graph.createNodeBitMap();
Deque<WorkListEntry> worklist = new ArrayDeque<>();
for (AbstractBeginNode b : blocks) {
if (b.isDeleted()) {
continue;
}
for (Node n : b.getBlockNodes()) {
if (n instanceof CommitAllocationNode) {
for (VirtualObjectNode obj : ((CommitAllocationNode) n).getVirtualObjects()) {
markFloating(worklist, obj, nodes, nonLoopNodes);
}
}
if (n instanceof MonitorEnterNode) {
markFloating(worklist, ((MonitorEnterNode) n).getMonitorId(), nodes, nonLoopNodes);
}
if (n instanceof AbstractMergeNode) {
/*
* Since we already marked all phi nodes as being in the loop to break cycles,
* we also have to iterate over their usages here.
*/
for (PhiNode phi : ((AbstractMergeNode) n).phis()) {
for (Node usage : phi.usages()) {
markFloating(worklist, usage, nodes, nonLoopNodes);
}
}
}
for (Node usage : n.usages()) {
markFloating(worklist, usage, nodes, nonLoopNodes);
}
}
}
}
use of org.graalvm.compiler.nodes.java.MonitorEnterNode in project graal by oracle.
the class BytecodeParser method genMonitorEnter.
protected void genMonitorEnter(ValueNode x, int bci) {
MonitorIdNode monitorId = graph.add(new MonitorIdNode(frameState.lockDepth(true)));
MonitorEnterNode monitorEnter = append(createMonitorEnterNode(x, monitorId));
frameState.pushLock(x, monitorId);
monitorEnter.setStateAfter(createFrameState(bci, monitorEnter));
}
use of org.graalvm.compiler.nodes.java.MonitorEnterNode in project graal by oracle.
the class LockEliminationPhase method run.
@Override
protected void run(StructuredGraph graph) {
for (MonitorExitNode monitorExitNode : graph.getNodes(MonitorExitNode.TYPE)) {
FixedNode next = monitorExitNode.next();
if ((next instanceof MonitorEnterNode || next instanceof RawMonitorEnterNode)) {
// start
assert !(next instanceof OSRMonitorEnterNode);
AccessMonitorNode monitorEnterNode = (AccessMonitorNode) next;
if (GraphUtil.unproxify(monitorEnterNode.object()) == GraphUtil.unproxify(monitorExitNode.object())) {
/*
* We've coarsened the lock so use the same monitor id for the whole region,
* otherwise the monitor operations appear to be unrelated.
*/
MonitorIdNode enterId = monitorEnterNode.getMonitorId();
MonitorIdNode exitId = monitorExitNode.getMonitorId();
if (enterId != exitId) {
enterId.replaceAndDelete(exitId);
}
GraphUtil.removeFixedWithUnusedInputs(monitorEnterNode);
GraphUtil.removeFixedWithUnusedInputs(monitorExitNode);
}
}
}
}
Aggregations