use of org.graalvm.compiler.java.BciBlockMapping.BciBlock in project graal by oracle.
the class BytecodeParser method genRet.
protected void genRet(int localIndex) {
BciBlock successor = currentBlock.getRetSuccessor();
ValueNode local = frameState.loadLocal(localIndex, JavaKind.Object);
JsrScope scope = currentBlock.getJsrScope();
int retAddress = scope.nextReturnAddress();
ConstantNode returnBciNode = getJsrConstant(retAddress);
LogicNode guard = IntegerEqualsNode.create(constantReflection, metaAccess, options, null, local, returnBciNode, NodeView.DEFAULT);
guard = graph.addOrUniqueWithInputs(guard);
append(new FixedGuardNode(guard, JavaSubroutineMismatch, InvalidateReprofile));
if (!successor.getJsrScope().equals(scope.pop())) {
throw new JsrNotSupportedBailout("unstructured control flow (ret leaves more than one scope)");
}
appendGoto(successor);
}
use of org.graalvm.compiler.java.BciBlockMapping.BciBlock in project graal by oracle.
the class BytecodeParser method genSwitch.
private void genSwitch(BytecodeSwitch bs) {
int bci = bci();
ValueNode value = frameState.pop(JavaKind.Int);
int nofCases = bs.numberOfCases();
int nofCasesPlusDefault = nofCases + 1;
double[] keyProbabilities = switchProbability(nofCasesPlusDefault, bci);
EconomicMap<Integer, SuccessorInfo> bciToBlockSuccessorIndex = EconomicMap.create(Equivalence.DEFAULT);
for (int i = 0; i < currentBlock.getSuccessorCount(); i++) {
assert !bciToBlockSuccessorIndex.containsKey(currentBlock.getSuccessor(i).startBci);
bciToBlockSuccessorIndex.put(currentBlock.getSuccessor(i).startBci, new SuccessorInfo(i));
}
ArrayList<BciBlock> actualSuccessors = new ArrayList<>();
int[] keys = new int[nofCases];
int[] keySuccessors = new int[nofCasesPlusDefault];
int deoptSuccessorIndex = -1;
int nextSuccessorIndex = 0;
boolean constantValue = value.isConstant();
for (int i = 0; i < nofCasesPlusDefault; i++) {
if (i < nofCases) {
keys[i] = bs.keyAt(i);
}
if (!constantValue && isNeverExecutedCode(keyProbabilities[i])) {
if (deoptSuccessorIndex < 0) {
deoptSuccessorIndex = nextSuccessorIndex++;
actualSuccessors.add(null);
}
keySuccessors[i] = deoptSuccessorIndex;
} else {
int targetBci = i < nofCases ? bs.targetAt(i) : bs.defaultTarget();
SuccessorInfo info = bciToBlockSuccessorIndex.get(targetBci);
if (info.actualIndex < 0) {
info.actualIndex = nextSuccessorIndex++;
actualSuccessors.add(currentBlock.getSuccessor(info.blockIndex));
}
keySuccessors[i] = info.actualIndex;
}
}
/*
* When the profile indicates a case is never taken, the above code will cause the case to
* deopt should it be subsequently encountered. However, the case may share code with
* another case that is taken according to the profile.
*
* For example:
* // @formatter:off
* switch (opcode) {
* case GOTO:
* case GOTO_W: {
* // emit goto code
* break;
* }
* }
* // @formatter:on
*
* The profile may indicate the GOTO_W case is never taken, and thus a deoptimization stub
* will be emitted. There might be optimization opportunity if additional branching based
* on opcode is within the case block. Specially, if there is only single case that
* reaches a target, we have better chance cutting out unused branches. Otherwise,
* it might be beneficial routing to the same code instead of deopting.
*
* The following code rewires deoptimization stub to existing resolved branch target if
* the target is connected by more than 1 cases.
*/
if (deoptSuccessorIndex >= 0) {
int[] connectedCases = new int[nextSuccessorIndex];
for (int i = 0; i < nofCasesPlusDefault; i++) {
connectedCases[keySuccessors[i]]++;
}
for (int i = 0; i < nofCasesPlusDefault; i++) {
if (keySuccessors[i] == deoptSuccessorIndex) {
int targetBci = i < nofCases ? bs.targetAt(i) : bs.defaultTarget();
SuccessorInfo info = bciToBlockSuccessorIndex.get(targetBci);
int rewiredIndex = info.actualIndex;
if (rewiredIndex >= 0 && connectedCases[rewiredIndex] > 1) {
keySuccessors[i] = info.actualIndex;
}
}
}
}
genIntegerSwitch(value, actualSuccessors, keys, keyProbabilities, keySuccessors);
}
use of org.graalvm.compiler.java.BciBlockMapping.BciBlock in project graal by oracle.
the class BytecodeParser method createHandleExceptionTarget.
protected void createHandleExceptionTarget(FixedWithNextNode finishedDispatch, int bci, FrameStateBuilder dispatchState) {
BciBlock dispatchBlock = currentBlock.exceptionDispatchBlock();
/*
* The exception dispatch block is always for the last bytecode of a block, so if we are not
* at the endBci yet, there is no exception handler for this bci and we can unwind
* immediately.
*/
if (bci != currentBlock.endBci || dispatchBlock == null) {
dispatchBlock = blockMap.getUnwindBlock();
}
FixedNode target = createTarget(dispatchBlock, dispatchState);
finishedDispatch.setNext(target);
}
use of org.graalvm.compiler.java.BciBlockMapping.BciBlock in project graal by oracle.
the class BytecodeParser method createExceptionDispatch.
private void createExceptionDispatch(ExceptionDispatchBlock block) {
lastInstr = finishInstruction(lastInstr, frameState);
assert frameState.stackSize() == 1 : frameState;
if (block.handler.isCatchAll()) {
assert block.getSuccessorCount() == 1;
appendGoto(block.getSuccessor(0));
return;
}
JavaType catchType = block.handler.getCatchType();
if (graphBuilderConfig.eagerResolving()) {
catchType = lookupType(block.handler.catchTypeCPI(), INSTANCEOF);
}
if (catchType instanceof ResolvedJavaType) {
TypeReference checkedCatchType = TypeReference.createTrusted(graph.getAssumptions(), (ResolvedJavaType) catchType);
if (graphBuilderConfig.getSkippedExceptionTypes() != null) {
for (ResolvedJavaType skippedType : graphBuilderConfig.getSkippedExceptionTypes()) {
if (skippedType.isAssignableFrom(checkedCatchType.getType())) {
BciBlock nextBlock = block.getSuccessorCount() == 1 ? blockMap.getUnwindBlock() : block.getSuccessor(1);
ValueNode exception = frameState.stack[0];
FixedNode trueSuccessor = graph.add(new DeoptimizeNode(InvalidateReprofile, UnreachedCode));
FixedNode nextDispatch = createTarget(nextBlock, frameState);
append(new IfNode(graph.addOrUniqueWithInputs(createInstanceOf(checkedCatchType, exception)), trueSuccessor, nextDispatch, 0));
return;
}
}
}
BciBlock nextBlock = block.getSuccessorCount() == 1 ? blockMap.getUnwindBlock() : block.getSuccessor(1);
ValueNode exception = frameState.stack[0];
/* Anchor for the piNode, which must be before any LoopExit inserted by createTarget. */
BeginNode piNodeAnchor = graph.add(new BeginNode());
ObjectStamp checkedStamp = StampFactory.objectNonNull(checkedCatchType);
PiNode piNode = graph.addWithoutUnique(new PiNode(exception, checkedStamp));
frameState.pop(JavaKind.Object);
frameState.push(JavaKind.Object, piNode);
FixedNode catchSuccessor = createTarget(block.getSuccessor(0), frameState);
frameState.pop(JavaKind.Object);
frameState.push(JavaKind.Object, exception);
FixedNode nextDispatch = createTarget(nextBlock, frameState);
piNodeAnchor.setNext(catchSuccessor);
IfNode ifNode = append(new IfNode(graph.unique(createInstanceOf(checkedCatchType, exception)), piNodeAnchor, nextDispatch, 0.5));
assert ifNode.trueSuccessor() == piNodeAnchor;
piNode.setGuard(ifNode.trueSuccessor());
} else {
handleUnresolvedExceptionType(catchType);
}
}
use of org.graalvm.compiler.java.BciBlockMapping.BciBlock in project graal by oracle.
the class LargeLocalLiveness method storeOne.
@Override
protected void storeOne(int blockID, int local) {
if (!localsLiveGen[blockID].get(local)) {
localsLiveKill[blockID].set(local);
}
BciBlock block = blocks[blockID];
long tmp = block.loops;
int pos = 0;
while (tmp != 0) {
if ((tmp & 1L) == 1L) {
this.localsChangedInLoop[pos].set(local);
}
tmp >>>= 1;
++pos;
}
}
Aggregations