src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java
Index
Unified diffs
Context diffs
Sdiffs
Patch
New
Old
Previous File
Next File
*** old/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java Fri Jul 7 09:30:32 2017
--- new/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java Fri Jul 7 09:30:32 2017
*** 25,34 ****
--- 25,36 ----
import static java.lang.String.format;
import static java.lang.reflect.Modifier.STATIC;
import static java.lang.reflect.Modifier.SYNCHRONIZED;
import static jdk.vm.ci.meta.DeoptimizationAction.InvalidateRecompile;
import static jdk.vm.ci.meta.DeoptimizationAction.InvalidateReprofile;
+ import static jdk.vm.ci.meta.DeoptimizationAction.None;
+ import static jdk.vm.ci.meta.DeoptimizationReason.ClassCastException;
import static jdk.vm.ci.meta.DeoptimizationReason.JavaSubroutineMismatch;
import static jdk.vm.ci.meta.DeoptimizationReason.NullCheckException;
import static jdk.vm.ci.meta.DeoptimizationReason.RuntimeConstraint;
import static jdk.vm.ci.meta.DeoptimizationReason.TypeCheckedInliningViolated;
import static jdk.vm.ci.meta.DeoptimizationReason.UnreachedCode;
*** 284,297 ****
--- 286,298 ----
import org.graalvm.compiler.core.common.type.StampFactory;
import org.graalvm.compiler.core.common.type.StampPair;
import org.graalvm.compiler.core.common.type.TypeReference;
import org.graalvm.compiler.core.common.util.Util;
import org.graalvm.compiler.debug.Assertions;
! import org.graalvm.compiler.debug.Debug;
import org.graalvm.compiler.debug.Debug.Scope;
! import org.graalvm.compiler.debug.CounterKey;
import org.graalvm.compiler.debug.DebugCloseable;
! import org.graalvm.compiler.debug.DebugCounter;
! import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.debug.GraalError;
import org.graalvm.compiler.debug.Indent;
import org.graalvm.compiler.debug.TTY;
import org.graalvm.compiler.graph.Graph.Mark;
import org.graalvm.compiler.graph.Node;
*** 450,462 ****
--- 451,463 ----
public static final int TRACELEVEL_STATE = 2;
/**
* Meters the number of actual bytecodes parsed.
*/
! public static final DebugCounter BytecodesParsed = Debug.counter("BytecodesParsed");
! public static final CounterKey BytecodesParsed = DebugContext.counter("BytecodesParsed");
! protected static final DebugCounter EXPLICIT_EXCEPTIONS = Debug.counter("ExplicitExceptions");
! protected static final CounterKey EXPLICIT_EXCEPTIONS = DebugContext.counter("ExplicitExceptions");
/**
* A scoped object for tasks to be performed after parsing an intrinsic such as processing
* {@linkplain BytecodeFrame#isPlaceholderBci(int) placeholder} frames states.
*/
*** 627,636 ****
--- 628,638 ----
}
private final GraphBuilderPhase.Instance graphBuilderInstance;
protected final StructuredGraph graph;
protected final OptionValues options;
+ protected final DebugContext debug;
private BciBlockMapping blockMap;
private LocalLiveness liveness;
protected final int entryBCI;
private final BytecodeParser parent;
*** 661,670 ****
--- 663,673 ----
this.code = bytecodeProvider.getBytecode(method);
this.method = code.getMethod();
this.graphBuilderInstance = graphBuilderInstance;
this.graph = graph;
this.options = graph.getOptions();
+ this.debug = graph.getDebug();
this.graphBuilderConfig = graphBuilderInstance.graphBuilderConfig;
this.optimisticOpts = graphBuilderInstance.optimisticOpts;
this.metaAccess = graphBuilderInstance.metaAccess;
this.stampProvider = graphBuilderInstance.stampProvider;
this.constantReflection = graphBuilderInstance.constantReflection;
*** 714,732 ****
--- 717,735 ----
if (PrintProfilingInformation.getValue(options) && profilingInfo != null) {
TTY.println("Profiling info for " + method.format("%H.%n(%p)"));
TTY.println(Util.indent(profilingInfo.toString(method, CodeUtil.NEW_LINE), " "));
}
! try (Indent indent = Debug.logAndIndent("build graph for %s", method)) {
! try (Indent indent = debug.logAndIndent("build graph for %s", method)) {
if (bytecodeProvider.shouldRecordMethodDependencies()) {
assert getParent() != null || method.equals(graph.method());
// Record method dependency in the graph
graph.recordMethod(method);
}
// compute the block map, setup exception handlers and get the entrypoint(s)
! BciBlockMapping newMapping = BciBlockMapping.create(stream, code, options, graph.getDebug());
this.blockMap = newMapping;
this.firstInstructionArray = new FixedWithNextNode[blockMap.getBlockCount()];
this.entryStateArray = new FrameStateBuilder[blockMap.getBlockCount()];
if (!method.isStatic()) {
originalReceiver = startFrameState.loadLocal(0, JavaKind.Object);
*** 736,750 ****
--- 739,753 ----
* Configure the assertion checking behavior of the FrameStateBuilder. This needs to be
* done only when assertions are enabled, so it is wrapped in an assertion itself.
*/
assert computeKindVerification(startFrameState);
! try (Scope s = Debug.scope("LivenessAnalysis")) {
! try (DebugContext.Scope s = debug.scope("LivenessAnalysis")) {
int maxLocals = method.getMaxLocals();
! liveness = LocalLiveness.compute(debug, stream, blockMap.getBlocks(), maxLocals, blockMap.getLoopCount());
} catch (Throwable e) {
! throw Debug.handle(e);
! throw debug.handle(e);
}
lastInstr = startInstruction;
this.setCurrentFrameState(startFrameState);
stream.setBCI(0);
*** 1003,1013 ****
--- 1006,1016 ----
append(new DeoptimizeNode(InvalidateRecompile, Unresolved));
}
private AbstractBeginNode handleException(ValueNode exceptionObject, int bci) {
assert bci == BytecodeFrame.BEFORE_BCI || bci == bci() : "invalid bci";
! Debug.log("Creating exception dispatch edges at %d, exception object=%s, exception seen=%s", bci, exceptionObject, (profilingInfo == null ? "" : profilingInfo.getExceptionSeen(bci)));
! debug.log("Creating exception dispatch edges at %d, exception object=%s, exception seen=%s", bci, exceptionObject, (profilingInfo == null ? "" : profilingInfo.getExceptionSeen(bci)));
FrameStateBuilder dispatchState = frameState.copy();
dispatchState.clearStack();
AbstractBeginNode dispatchBegin;
*** 1242,1252 ****
--- 1245,1255 ----
append(new IfNode(graph.addOrUniqueWithInputs(IsNullNode.create(receiver)), exception, falseSucc, SLOW_PATH_PROBABILITY));
lastInstr = falseSucc;
exception.setStateAfter(createFrameState(bci(), exception));
exception.setNext(handleException(exception, bci()));
! EXPLICIT_EXCEPTIONS.increment(debug);
return nonNullReceiver;
}
protected void emitExplicitBoundsCheck(ValueNode index, ValueNode length) {
AbstractBeginNode trueSucc = graph.add(new BeginNode());
*** 1450,1459 ****
--- 1453,1466 ----
}
if (invokeKind.hasReceiver()) {
args[0] = emitExplicitExceptions(args[0]);
}
+ if (initialInvokeKind == InvokeKind.Special && !targetMethod.isConstructor()) {
+ emitCheckForInvokeSuperSpecial(args);
+ }
+
InlineInfo inlineInfo = null;
try {
currentInvoke = new CurrentInvoke(args, invokeKind, returnType);
if (tryNodePluginForInvocation(args, targetMethod)) {
if (TraceParserPlugins.getValue(options)) {
*** 1533,1542 ****
--- 1540,1573 ----
invoke.setUseForInlining(false);
}
return invoke;
}
+ /**
+ * Checks that the class of the receiver of an {@link Bytecodes#INVOKESPECIAL} in a method
+ * declared in an interface (i.e., a default method) is assignable to the interface. If not,
+ * then deoptimize so that the interpreter can throw an {@link IllegalAccessError}.
+ *
+ * This is a check not performed by the verifier and so must be performed at runtime.
+ *
+ * @param args arguments to an {@link Bytecodes#INVOKESPECIAL} implementing a direct call to a
+ * method in a super class
+ */
+ protected void emitCheckForInvokeSuperSpecial(ValueNode[] args) {
+ ResolvedJavaType callingClass = method.getDeclaringClass();
+ if (callingClass.getHostClass() != null) {
+ callingClass = callingClass.getHostClass();
+ }
+ if (callingClass.isInterface()) {
+ ValueNode receiver = args[0];
+ TypeReference checkedType = TypeReference.createTrusted(graph.getAssumptions(), callingClass);
+ LogicNode condition = genUnique(createInstanceOf(checkedType, receiver, null));
+ FixedGuardNode fixedGuard = append(new FixedGuardNode(condition, ClassCastException, None, false));
+ args[0] = append(PiNode.create(receiver, StampFactory.object(checkedType, true), fixedGuard));
+ }
+ }
+
protected JavaTypeProfile getProfileForInvoke(InvokeKind invokeKind) {
if (invokeKind.isIndirect() && profilingInfo != null && this.optimisticOpts.useTypeCheckHints(getOptions())) {
return profilingInfo.getTypeProfile(bci());
}
return null;
*** 2093,2105 ****
--- 2124,2133 ----
protected void traceWithContext(String format, Object... args) {
StackTraceElement where = code.asStackTraceElement(bci());
String s = format("%s%s (%s:%d) %s", nSpaces(getDepth()), method.isConstructor() ? method.format("%h.%n") : method.getName(), where.getFileName(), where.getLineNumber(),
format(format, args));
if (s.equals("decrypt (CipherBlockChainingSubstitutions.java:117) inlining call to CipherBlockChainingSubstitutions.decrypt(Object, byte[], int, int, byte[], int)")) {
System.console();
}
TTY.println(s);
}
protected BytecodeParserError asParserError(Throwable e) {
if (e instanceof BytecodeParserError) {
*** 2419,2429 ****
--- 2447,2457 ----
}
if (firstLoopExit == null) {
firstLoopExit = loopExit;
}
lastLoopExit = loopExit;
! Debug.log("Target %s Exits %s, scanning framestates...", targetBlock, loop);
! debug.log("Target %s Exits %s, scanning framestates...", targetBlock, loop);
newState.clearNonLiveLocals(targetBlock, liveness, true);
newState.insertLoopProxies(loopExit, getEntryState(loop));
loopExit.setStateAfter(newState.create(bci, loopExit));
}
*** 2485,2495 ****
--- 2513,2523 ----
FixedNode result = target.fixed;
FrameStateBuilder currentEntryState = target.state == state ? (canReuseState ? state : state.copy()) : target.state;
setEntryState(block, currentEntryState);
currentEntryState.clearNonLiveLocals(block, liveness, true);
! Debug.log("createTarget %s: first visit, result: %s", block, targetNode);
! debug.log("createTarget %s: first visit, result: %s", block, targetNode);
return result;
}
// We already saw this block before, so we have to merge states.
if (!getEntryState(block).isCompatibleWith(state)) {
*** 2506,2516 ****
--- 2534,2544 ----
LoopEndNode loopEnd = graph.add(new LoopEndNode(loopBegin));
Target target = checkLoopExit(loopEnd, block, state);
FixedNode result = target.fixed;
getEntryState(block).merge(loopBegin, target.state);
! Debug.log("createTarget %s: merging backward branch to loop header %s, result: %s", block, loopBegin, result);
! debug.log("createTarget %s: merging backward branch to loop header %s, result: %s", block, loopBegin, result);
return result;
}
assert currentBlock == null || currentBlock.getId() < block.getId() : "must not be backward branch";
assert getFirstInstruction(block).next() == null : "bytecodes already parsed for block";
*** 2547,2557 ****
--- 2575,2585 ----
Target target = checkLoopExit(newEnd, block, state);
FixedNode result = target.fixed;
getEntryState(block).merge(mergeNode, target.state);
mergeNode.addForwardEnd(newEnd);
! Debug.log("createTarget %s: merging state, result: %s", block, result);
! debug.log("createTarget %s: merging state, result: %s", block, result);
return result;
}
/**
* Returns a block begin node with the specified state. If the specified probability is 0, the
*** 2578,2591 ****
--- 2606,2619 ----
@SuppressWarnings("try")
protected void processBlock(BciBlock block) {
// Ignore blocks that have no predecessors by the time their bytecodes are parsed
FixedWithNextNode firstInstruction = getFirstInstruction(block);
if (firstInstruction == null) {
! Debug.log("Ignoring block %s", block);
! debug.log("Ignoring block %s", block);
return;
}
! try (Indent indent = Debug.logAndIndent("Parsing block %s firstInstruction: %s loopHeader: %b", block, firstInstruction, block.isLoopHeader)) {
! try (Indent indent = debug.logAndIndent("Parsing block %s firstInstruction: %s loopHeader: %b", block, firstInstruction, block.isLoopHeader)) {
lastInstr = firstInstruction;
frameState = getEntryState(block);
setCurrentFrameState(frameState);
currentBlock = block;
*** 2727,2754 ****
--- 2755,2782 ----
* We need to preserve the frame state builder of the loop header so that we can merge
* values for phi functions, so make a copy of it.
*/
setEntryState(block, frameState.copy());
! Debug.log(" created loop header %s", loopBegin);
! debug.log(" created loop header %s", loopBegin);
} else if (lastInstr instanceof MergeNode) {
/*
* All inputs of non-loop phi nodes are known by now. We can infer the stamp for the
* phi, so that parsing continues with more precise type information.
*/
frameState.inferPhiStamps((AbstractMergeNode) lastInstr);
}
assert lastInstr.next() == null : "instructions already appended at block " + block;
! Debug.log(" frameState: %s", frameState);
! debug.log(" frameState: %s", frameState);
lastInstr = finishInstruction(lastInstr, frameState);
int endBCI = stream.endBCI();
stream.setBCI(block.startBci);
int bci = block.startBci;
! BytecodesParsed.add(debug, block.endBci - bci);
/* Reset line number for new block */
if (graphBuilderConfig.insertFullInfopoints()) {
previousLineNumber = -1;
}
*** 2805,2815 ****
--- 2833,2843 ----
}
}
}
private DebugCloseable openNodeContext() {
! if ((graphBuilderConfig.trackNodeSourcePosition() || Debug.isDumpEnabledForMethod()) && !parsingIntrinsic()) {
! if ((graphBuilderConfig.trackNodeSourcePosition() || debug.isDumpEnabledForMethod()) && !parsingIntrinsic()) {
return graph.withNodeSourcePosition(createBytecodePosition());
}
return null;
}
*** 2868,2878 ****
--- 2896,2906 ----
append(new FullInfopointNode(reason, createFrameState(bci(), null), escapedReturnValue));
}
}
private boolean traceState() {
! if (Debug.isEnabled() && TraceBytecodeParserLevel.getValue(options) >= TRACELEVEL_STATE && Debug.isLogEnabled()) {
! if (debug.isLogEnabled() && TraceBytecodeParserLevel.getValue(options) >= TRACELEVEL_STATE) {
frameState.traceState();
}
return true;
}
*** 3918,3928 ****
--- 3946,3956 ----
private double[] switchProbability(int numberOfCases, int bci) {
double[] prob = (profilingInfo == null ? null : profilingInfo.getSwitchProbabilities(bci));
if (prob != null) {
assert prob.length == numberOfCases;
} else {
! Debug.log("Missing probability (switch) in %s at bci %d", method, bci);
! debug.log("Missing probability (switch) in %s at bci %d", method, bci);
prob = new double[numberOfCases];
for (int i = 0; i < numberOfCases; i++) {
prob[i] = 1.0d / numberOfCases;
}
}
*** 4004,4014 ****
--- 4032,4042 ----
}
assert assertAtIfBytecode();
double probability = profilingInfo.getBranchTakenProbability(bci());
if (probability < 0) {
assert probability == -1 : "invalid probability";
! Debug.log("missing probability in %s at bci %d", code, bci());
! debug.log("missing probability in %s at bci %d", code, bci());
probability = 0.5;
}
if (!optimisticOpts.removeNeverExecutedCode(getOptions())) {
if (probability == 0) {
*** 4277,4287 ****
--- 4305,4315 ----
public FrameStateBuilder getFrameStateBuilder() {
return frameState;
}
protected boolean traceInstruction(int bci, int opcode, boolean blockStart) {
! if (Debug.isEnabled() && TraceBytecodeParserLevel.getValue(options) >= TRACELEVEL_INSTRUCTIONS && Debug.isLogEnabled()) {
! if (debug.isLogEnabled() && TraceBytecodeParserLevel.getValue(options) >= TRACELEVEL_INSTRUCTIONS) {
traceInstructionHelper(bci, opcode, blockStart);
}
return true;
}
*** 4298,4308 ****
--- 4326,4336 ----
sb.append(' ').append(stream.readUByte(i));
}
if (!currentBlock.getJsrScope().isEmpty()) {
sb.append(' ').append(currentBlock.getJsrScope());
}
! Debug.log("%s", sb);
! debug.log("%s", sb);
}
@Override
public boolean parsingIntrinsic() {
return intrinsicContext != null;
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java
Index
Unified diffs
Context diffs
Sdiffs
Patch
New
Old
Previous File
Next File