mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 16:14:10 -08:00
Keep location stack in IR when inlining methods
This commit is contained in:
parent
c6f6125622
commit
e762f26a40
|
@ -65,8 +65,7 @@ public final class LocationGraphBuilder {
|
|||
for (int terminal : visitor.nodes) {
|
||||
visitor.terminalNodes.set(terminal);
|
||||
}
|
||||
TextLocation[][] locations = propagate(visitor.locations.toArray(new TextLocation[0]), graph
|
||||
);
|
||||
TextLocation[][] locations = propagate(visitor.locations.toArray(new TextLocation[0]), graph);
|
||||
|
||||
Map<TextLocation, Set<TextLocation>> builder = new LinkedHashMap<>();
|
||||
for (int i = 0; i < graph.size(); ++i) {
|
||||
|
@ -353,7 +352,7 @@ public final class LocationGraphBuilder {
|
|||
}
|
||||
|
||||
private void setLocation(TextLocation location) {
|
||||
if (location == null) {
|
||||
if (location == null || location.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
int node = createNode(location);
|
||||
|
|
|
@ -746,7 +746,7 @@ public class JavaScriptTarget implements TeaVMTarget, TeaVMJavaScriptHost {
|
|||
}
|
||||
|
||||
private static SourceLocation map(TextLocation location) {
|
||||
if (location == null) {
|
||||
if (location == null || location.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return new SourceLocation(location.getFileName(), location.getLine());
|
||||
|
|
|
@ -153,6 +153,9 @@ public class DefaultNamingStrategy implements NamingStrategy {
|
|||
String cls = fieldRef.getClassName();
|
||||
while (cls != null) {
|
||||
ClassReader clsReader = classSource.get(cls);
|
||||
if (clsReader == null) {
|
||||
break;
|
||||
}
|
||||
if (clsReader != null) {
|
||||
FieldReader fieldReader = clsReader.getField(fieldRef.getFieldName());
|
||||
if (fieldReader != null) {
|
||||
|
@ -164,7 +167,7 @@ public class DefaultNamingStrategy implements NamingStrategy {
|
|||
return fieldRef;
|
||||
}
|
||||
|
||||
private final class Key {
|
||||
static final class Key {
|
||||
final MethodReference data;
|
||||
int hash;
|
||||
final byte classifier;
|
||||
|
|
87
core/src/main/java/org/teavm/cache/AstIO.java
vendored
87
core/src/main/java/org/teavm/cache/AstIO.java
vendored
|
@ -71,6 +71,7 @@ import org.teavm.ast.VariableNode;
|
|||
import org.teavm.ast.WhileStatement;
|
||||
import org.teavm.model.ElementModifier;
|
||||
import org.teavm.model.FieldReference;
|
||||
import org.teavm.model.InliningInfo;
|
||||
import org.teavm.model.MethodDescriptor;
|
||||
import org.teavm.model.MethodReference;
|
||||
import org.teavm.model.ReferenceCache;
|
||||
|
@ -89,6 +90,7 @@ public class AstIO {
|
|||
private ReferenceCache referenceCache;
|
||||
private TextLocation lastWrittenLocation;
|
||||
private TextLocation lastReadLocation;
|
||||
private InliningInfo lastReadInlining;
|
||||
|
||||
public AstIO(ReferenceCache referenceCache, SymbolTable symbolTable, SymbolTable fileTable,
|
||||
SymbolTable variableTable) {
|
||||
|
@ -99,7 +101,7 @@ public class AstIO {
|
|||
}
|
||||
|
||||
public void write(VarDataOutput output, ControlFlowEntry[] cfg) throws IOException {
|
||||
lastWrittenLocation = null;
|
||||
lastWrittenLocation = TextLocation.EMPTY;
|
||||
output.writeUnsigned(cfg.length);
|
||||
for (ControlFlowEntry entry : cfg) {
|
||||
writeLocation(output, entry.from);
|
||||
|
@ -130,7 +132,7 @@ public class AstIO {
|
|||
}
|
||||
|
||||
public ControlFlowEntry[] readControlFlow(VarDataInput input) throws IOException {
|
||||
lastReadLocation = null;
|
||||
lastReadLocation = TextLocation.EMPTY;
|
||||
int size = input.readUnsigned();
|
||||
ControlFlowEntry[] result = new ControlFlowEntry[size];
|
||||
for (int i = 0; i < size; ++i) {
|
||||
|
@ -152,7 +154,7 @@ public class AstIO {
|
|||
for (int i = 0; i < varCount; ++i) {
|
||||
node.getVariables().add(readVariable(input));
|
||||
}
|
||||
lastReadLocation = null;
|
||||
lastReadLocation = TextLocation.EMPTY;
|
||||
node.setBody(readStatement(input));
|
||||
return node;
|
||||
}
|
||||
|
@ -211,23 +213,24 @@ public class AstIO {
|
|||
}
|
||||
|
||||
private void writeLocation(VarDataOutput output, TextLocation location) throws IOException {
|
||||
if (location == null || location.getFileName() == null) {
|
||||
if (location == null) {
|
||||
location = TextLocation.EMPTY;
|
||||
}
|
||||
if (location.isEmpty()) {
|
||||
output.writeUnsigned(0);
|
||||
lastWrittenLocation = null;
|
||||
} else if (lastWrittenLocation != null && lastWrittenLocation.getFileName().equals(location.getFileName())) {
|
||||
} else if (!lastWrittenLocation.isEmpty() && lastWrittenLocation.getFileName().equals(location.getFileName())) {
|
||||
output.writeUnsigned(1);
|
||||
output.writeSigned(location.getLine() - lastWrittenLocation.getLine());
|
||||
lastWrittenLocation = location;
|
||||
} else {
|
||||
output.writeUnsigned(fileTable.lookup(location.getFileName()) + 2);
|
||||
output.writeUnsigned(location.getLine());
|
||||
lastWrittenLocation = location;
|
||||
}
|
||||
lastWrittenLocation = location;
|
||||
}
|
||||
|
||||
private class NodeWriter implements ExprVisitor, StatementVisitor {
|
||||
private final VarDataOutput output;
|
||||
private TextLocation lastLocation;
|
||||
private TextLocation lastLocation = TextLocation.EMPTY;
|
||||
|
||||
NodeWriter(VarDataOutput output) {
|
||||
super();
|
||||
|
@ -240,22 +243,52 @@ public class AstIO {
|
|||
}
|
||||
|
||||
private void writeLocation(TextLocation location) throws IOException {
|
||||
if (location == null) {
|
||||
location = TextLocation.EMPTY;
|
||||
}
|
||||
if (Objects.equals(location, lastLocation)) {
|
||||
return;
|
||||
}
|
||||
if (location == null || location.getFileName() == null) {
|
||||
|
||||
InliningInfo lastCommonInlining = null;
|
||||
InliningInfo[] prevPath = lastLocation.getInliningPath();
|
||||
InliningInfo[] newPath = location.getInliningPath();
|
||||
int pathIndex = 0;
|
||||
while (pathIndex < prevPath.length && pathIndex < newPath.length
|
||||
&& prevPath[pathIndex].equals(newPath[pathIndex])) {
|
||||
lastCommonInlining = prevPath[pathIndex++];
|
||||
}
|
||||
|
||||
InliningInfo prevInlining = lastLocation.getInlining();
|
||||
while (prevInlining != lastCommonInlining) {
|
||||
output.writeUnsigned(124);
|
||||
prevInlining = prevInlining.getParent();
|
||||
}
|
||||
|
||||
while (pathIndex < newPath.length) {
|
||||
InliningInfo inlining = newPath[pathIndex++];
|
||||
MethodReference method = inlining.getMethod();
|
||||
output.writeUnsigned(inlining.isEmpty() ? 122 : 123);
|
||||
output.writeUnsigned(symbolTable.lookup(method.getClassName()));
|
||||
output.writeUnsigned(symbolTable.lookup(method.getDescriptor().toString()));
|
||||
if (!inlining.isEmpty()) {
|
||||
output.writeUnsigned(fileTable.lookup(inlining.getFileName()));
|
||||
output.writeUnsigned(inlining.getLine());
|
||||
}
|
||||
}
|
||||
|
||||
if (location.isEmpty()) {
|
||||
output.writeUnsigned(127);
|
||||
lastLocation = null;
|
||||
} else if (lastLocation != null && lastLocation.getFileName().equals(location.getFileName())) {
|
||||
} else if (!lastLocation.isEmpty() && lastLocation.getFileName().equals(location.getFileName())) {
|
||||
output.writeUnsigned(126);
|
||||
output.writeSigned(location.getLine() - lastLocation.getLine());
|
||||
lastLocation = location;
|
||||
} else {
|
||||
output.writeUnsigned(125);
|
||||
output.writeUnsigned(fileTable.lookup(location.getFileName()));
|
||||
output.writeUnsigned(location.getLine());
|
||||
lastLocation = location;
|
||||
}
|
||||
|
||||
lastLocation = location;
|
||||
}
|
||||
|
||||
private void writeSequence(List<Statement> sequence) throws IOException {
|
||||
|
@ -702,10 +735,32 @@ public class AstIO {
|
|||
break;
|
||||
case 126:
|
||||
lastReadLocation = new TextLocation(lastReadLocation.getFileName(),
|
||||
lastReadLocation.getLine() + input.readSigned());
|
||||
lastReadLocation.getLine() + input.readSigned(), lastReadInlining);
|
||||
break;
|
||||
case 125:
|
||||
lastReadLocation = new TextLocation(fileTable.at(input.readUnsigned()), input.readUnsigned());
|
||||
lastReadLocation = new TextLocation(fileTable.at(input.readUnsigned()), input.readUnsigned(),
|
||||
lastReadInlining);
|
||||
break;
|
||||
case 122:
|
||||
case 123: {
|
||||
String className = symbolTable.at(input.readUnsigned());
|
||||
MethodDescriptor methodDescriptor = MethodDescriptor.parse(symbolTable.at(input.readUnsigned()));
|
||||
methodDescriptor = referenceCache.getCached(methodDescriptor);
|
||||
String fileName;
|
||||
int lineNumber;
|
||||
if (type == 122) {
|
||||
fileName = fileTable.at(input.readUnsigned());
|
||||
lineNumber = input.readUnsigned();
|
||||
} else {
|
||||
fileName = null;
|
||||
lineNumber = -1;
|
||||
}
|
||||
lastReadInlining = new InliningInfo(referenceCache.getCached(className, methodDescriptor),
|
||||
fileName, lineNumber, lastReadInlining);
|
||||
break;
|
||||
}
|
||||
case 124:
|
||||
lastReadInlining = lastReadInlining.getParent();
|
||||
break;
|
||||
default:
|
||||
return type;
|
||||
|
|
|
@ -24,6 +24,7 @@ import org.teavm.model.BasicBlockReader;
|
|||
import org.teavm.model.FieldReference;
|
||||
import org.teavm.model.Incoming;
|
||||
import org.teavm.model.IncomingReader;
|
||||
import org.teavm.model.InliningInfo;
|
||||
import org.teavm.model.Instruction;
|
||||
import org.teavm.model.InvokeDynamicInstruction;
|
||||
import org.teavm.model.MethodDescriptor;
|
||||
|
@ -206,6 +207,7 @@ public class ProgramIO {
|
|||
block.getTryCatchBlocks().add(tryCatch);
|
||||
}
|
||||
|
||||
InliningInfo inliningInfo = null;
|
||||
TextLocation location = null;
|
||||
insnLoop: while (true) {
|
||||
int insnType = data.readUnsigned();
|
||||
|
@ -213,19 +215,39 @@ public class ProgramIO {
|
|||
case 0:
|
||||
break insnLoop;
|
||||
case 1:
|
||||
location = null;
|
||||
location = new TextLocation(null, -1, inliningInfo);
|
||||
break;
|
||||
case 2: {
|
||||
String file = fileTable.at(data.readUnsigned());
|
||||
int line = data.readUnsigned();
|
||||
location = new TextLocation(file, line);
|
||||
location = new TextLocation(file, line, inliningInfo);
|
||||
break;
|
||||
}
|
||||
case 127: {
|
||||
int line = location.getLine() + data.readSigned();
|
||||
location = new TextLocation(location.getFileName(), line);
|
||||
location = new TextLocation(location.getFileName(), line, inliningInfo);
|
||||
break;
|
||||
}
|
||||
case 124:
|
||||
case 125: {
|
||||
String className = symbolTable.at(data.readUnsigned());
|
||||
MethodDescriptor methodDescriptor = parseMethodDescriptor(symbolTable.at(data.readUnsigned()));
|
||||
String fileName;
|
||||
int lineNumber;
|
||||
if (insnType == 125) {
|
||||
fileName = fileTable.at(data.readUnsigned());
|
||||
lineNumber = data.readUnsigned();
|
||||
} else {
|
||||
fileName = null;
|
||||
lineNumber = -1;
|
||||
}
|
||||
inliningInfo = new InliningInfo(createMethodReference(className, methodDescriptor),
|
||||
fileName, lineNumber, inliningInfo);
|
||||
break;
|
||||
}
|
||||
case 126:
|
||||
inliningInfo = inliningInfo.getParent();
|
||||
break;
|
||||
default: {
|
||||
Instruction insn = readInstruction(insnType, program, data);
|
||||
insn.setLocation(location);
|
||||
|
@ -241,7 +263,7 @@ public class ProgramIO {
|
|||
|
||||
private class InstructionWriter implements InstructionReader {
|
||||
private VarDataOutput output;
|
||||
TextLocation location;
|
||||
TextLocation location = TextLocation.EMPTY;
|
||||
|
||||
InstructionWriter(VarDataOutput output) {
|
||||
this.output = output;
|
||||
|
@ -250,11 +272,41 @@ public class ProgramIO {
|
|||
@Override
|
||||
public void location(TextLocation newLocation) {
|
||||
try {
|
||||
if (newLocation == null || newLocation.getFileName() == null || newLocation.getLine() < 0) {
|
||||
if (newLocation == null) {
|
||||
newLocation = TextLocation.EMPTY;
|
||||
}
|
||||
|
||||
InliningInfo lastCommonInlining = null;
|
||||
InliningInfo[] prevPath = location.getInliningPath();
|
||||
InliningInfo[] newPath = newLocation.getInliningPath();
|
||||
int pathIndex = 0;
|
||||
while (pathIndex < prevPath.length && pathIndex < newPath.length
|
||||
&& prevPath[pathIndex].equals(newPath[pathIndex])) {
|
||||
lastCommonInlining = prevPath[pathIndex++];
|
||||
}
|
||||
|
||||
InliningInfo prevInlining = location.getInlining();
|
||||
while (prevInlining != lastCommonInlining) {
|
||||
output.writeUnsigned(126);
|
||||
prevInlining = prevInlining.getParent();
|
||||
}
|
||||
|
||||
while (pathIndex < newPath.length) {
|
||||
InliningInfo inlining = newPath[pathIndex++];
|
||||
MethodReference method = inlining.getMethod();
|
||||
output.writeUnsigned(inlining.isEmpty() ? 124 : 125);
|
||||
output.writeUnsigned(symbolTable.lookup(method.getClassName()));
|
||||
output.writeUnsigned(symbolTable.lookup(method.getDescriptor().toString()));
|
||||
if (!inlining.isEmpty()) {
|
||||
output.writeUnsigned(fileTable.lookup(inlining.getFileName()));
|
||||
output.writeUnsigned(inlining.getLine());
|
||||
}
|
||||
}
|
||||
|
||||
if (newLocation.isEmpty()) {
|
||||
output.writeUnsigned(1);
|
||||
location = null;
|
||||
} else {
|
||||
if (location != null && location.getFileName().equals(newLocation.getFileName())) {
|
||||
if (!location.isEmpty() && location.getFileName().equals(newLocation.getFileName())) {
|
||||
output.writeUnsigned(127);
|
||||
output.writeSigned(newLocation.getLine() - location.getLine());
|
||||
} else {
|
||||
|
@ -262,8 +314,8 @@ public class ProgramIO {
|
|||
output.writeUnsigned(fileTable.lookup(newLocation.getFileName()));
|
||||
output.writeUnsigned(newLocation.getLine());
|
||||
}
|
||||
location = newLocation;
|
||||
}
|
||||
location = newLocation;
|
||||
} catch (IOException e) {
|
||||
throw new IOExceptionWrapper(e);
|
||||
}
|
||||
|
|
|
@ -348,7 +348,7 @@ public class DebugInformationBuilder implements DebugInformationEmitter {
|
|||
}
|
||||
|
||||
static class ClassMetadata {
|
||||
int parentIndex;
|
||||
int parentIndex = -1;
|
||||
String jsName;
|
||||
Map<Integer, Integer> fieldMap = new HashMap<>();
|
||||
}
|
||||
|
|
84
core/src/main/java/org/teavm/model/InliningInfo.java
Normal file
84
core/src/main/java/org/teavm/model/InliningInfo.java
Normal file
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* Copyright 2019 Alexey Andreev.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Objects;
|
||||
|
||||
public class InliningInfo implements Serializable {
|
||||
private MethodReference method;
|
||||
private String fileName;
|
||||
private int line;
|
||||
private InliningInfo parent;
|
||||
private transient int hash;
|
||||
|
||||
public InliningInfo(MethodReference method, String fileName, int line, InliningInfo parent) {
|
||||
this.method = method;
|
||||
this.fileName = fileName;
|
||||
this.line = line;
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
public MethodReference getMethod() {
|
||||
return method;
|
||||
}
|
||||
|
||||
public String getFileName() {
|
||||
return fileName;
|
||||
}
|
||||
|
||||
public int getLine() {
|
||||
return line;
|
||||
}
|
||||
|
||||
public InliningInfo getParent() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return fileName == null && line < 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = hash;
|
||||
if (result == 0) {
|
||||
final int prime = 31;
|
||||
result = 1;
|
||||
result = prime * result + method.hashCode();
|
||||
result = prime * result + (fileName == null ? 0 : fileName.hashCode());
|
||||
result = prime * result + line;
|
||||
result = prime * result + (parent != null ? parent.hashCode() : 0);
|
||||
hash = result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (!(obj instanceof InliningInfo)) {
|
||||
return false;
|
||||
}
|
||||
InliningInfo that = (InliningInfo) obj;
|
||||
return Objects.equals(method, that.method)
|
||||
&& Objects.equals(fileName, that.fileName)
|
||||
&& line == that.line
|
||||
&& Objects.equals(parent, that.parent);
|
||||
}
|
||||
}
|
|
@ -19,12 +19,22 @@ import java.io.Serializable;
|
|||
import java.util.Objects;
|
||||
|
||||
public class TextLocation implements Serializable {
|
||||
public static final TextLocation EMPTY = new TextLocation(null, -1);
|
||||
private static final InliningInfo[] EMPTY_ARRAY = new InliningInfo[0];
|
||||
|
||||
private String fileName;
|
||||
private int line = -1;
|
||||
private int line;
|
||||
private InliningInfo inlining;
|
||||
private transient int hash;
|
||||
|
||||
public TextLocation(String fileName, int line) {
|
||||
this(fileName, line, null);
|
||||
}
|
||||
|
||||
public TextLocation(String fileName, int line, InliningInfo inlining) {
|
||||
this.fileName = fileName;
|
||||
this.line = line;
|
||||
this.inlining = inlining;
|
||||
}
|
||||
|
||||
public String getFileName() {
|
||||
|
@ -35,12 +45,47 @@ public class TextLocation implements Serializable {
|
|||
return line;
|
||||
}
|
||||
|
||||
public InliningInfo getInlining() {
|
||||
return inlining;
|
||||
}
|
||||
|
||||
public InliningInfo[] getInliningPath() {
|
||||
if (inlining == null) {
|
||||
return EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
InliningInfo inlining = this.inlining;
|
||||
int sz = 0;
|
||||
while (inlining != null) {
|
||||
sz++;
|
||||
inlining = inlining.getParent();
|
||||
}
|
||||
|
||||
InliningInfo[] result = new InliningInfo[sz];
|
||||
inlining = this.inlining;
|
||||
while (inlining != null) {
|
||||
result[--sz] = inlining;
|
||||
inlining = inlining.getParent();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return fileName == null && line < 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + (fileName == null ? 0 : fileName.hashCode());
|
||||
result = prime * result + line;
|
||||
int result = hash;
|
||||
if (result == 0) {
|
||||
final int prime = 31;
|
||||
result = 1;
|
||||
result = prime * result + (fileName == null ? 0 : fileName.hashCode());
|
||||
result = prime * result + line;
|
||||
result = prime * result + (inlining != null ? inlining.hashCode() : 0);
|
||||
hash = result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -53,11 +98,29 @@ public class TextLocation implements Serializable {
|
|||
return false;
|
||||
}
|
||||
TextLocation other = (TextLocation) obj;
|
||||
return Objects.equals(fileName, other.fileName) && line == other.line;
|
||||
return Objects.equals(fileName, other.fileName) && line == other.line
|
||||
&& Objects.equals(inlining, other.inlining);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return fileName + ":" + line;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(fileName).append(':').append(line);
|
||||
InliningInfo inlining = this.inlining;
|
||||
if (inlining != null) {
|
||||
sb.append('[');
|
||||
boolean first = true;
|
||||
while (inlining != null) {
|
||||
if (!first) {
|
||||
sb.append("->");
|
||||
}
|
||||
first = false;
|
||||
sb.append(inlining.getMethod()).append("@")
|
||||
.append(inlining.getFileName()).append(':').append(inlining.getLine());
|
||||
inlining = inlining.getParent();
|
||||
}
|
||||
sb.append(']');
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@ import org.teavm.model.ClassHierarchy;
|
|||
import org.teavm.model.ClassReader;
|
||||
import org.teavm.model.ElementModifier;
|
||||
import org.teavm.model.Incoming;
|
||||
import org.teavm.model.InliningInfo;
|
||||
import org.teavm.model.Instruction;
|
||||
import org.teavm.model.ListableClassReaderSource;
|
||||
import org.teavm.model.MethodReader;
|
||||
|
@ -44,6 +45,7 @@ import org.teavm.model.MethodReference;
|
|||
import org.teavm.model.Phi;
|
||||
import org.teavm.model.Program;
|
||||
import org.teavm.model.ProgramReader;
|
||||
import org.teavm.model.TextLocation;
|
||||
import org.teavm.model.TryCatchBlock;
|
||||
import org.teavm.model.VariableReader;
|
||||
import org.teavm.model.analysis.ClassInference;
|
||||
|
@ -178,7 +180,7 @@ public class Inlining {
|
|||
if (step == null) {
|
||||
return false;
|
||||
}
|
||||
List<PlanEntry> plan = buildPlan(program, -1, step, method);
|
||||
List<PlanEntry> plan = buildPlan(program, -1, step, method, null);
|
||||
if (plan.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
@ -227,6 +229,8 @@ public class Inlining {
|
|||
jumpToInlinedProgram.setTarget(firstInlineBlock);
|
||||
block.add(jumpToInlinedProgram);
|
||||
|
||||
InliningInfoMerger inliningInfoMerger = new InliningInfoMerger(planEntry.locationInfo);
|
||||
|
||||
for (int i = 0; i < inlineProgram.basicBlockCount(); ++i) {
|
||||
BasicBlock blockToInline = inlineProgram.basicBlockAt(i);
|
||||
BasicBlock inlineBlock = program.basicBlockAt(firstInlineBlock.getIndex() + i);
|
||||
|
@ -244,6 +248,14 @@ public class Inlining {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
TextLocation location = insn.getLocation();
|
||||
if (location == null) {
|
||||
location = TextLocation.EMPTY;
|
||||
}
|
||||
location = new TextLocation(location.getFileName(), location.getLine(),
|
||||
inliningInfoMerger.merge(location.getInlining()));
|
||||
insn.setLocation(location);
|
||||
}
|
||||
|
||||
List<Phi> phis = new ArrayList<>(blockToInline.getPhis());
|
||||
|
@ -324,7 +336,8 @@ public class Inlining {
|
|||
execPlan(program, planEntry.innerPlan, firstInlineBlock.getIndex());
|
||||
}
|
||||
|
||||
private List<PlanEntry> buildPlan(Program program, int depth, InliningStep step, MethodReference method) {
|
||||
private List<PlanEntry> buildPlan(Program program, int depth, InliningStep step, MethodReference method,
|
||||
InliningInfo inliningInfo) {
|
||||
List<PlanEntry> plan = new ArrayList<>();
|
||||
int originalDepth = depth;
|
||||
|
||||
|
@ -373,13 +386,22 @@ public class Inlining {
|
|||
}
|
||||
Program invokedProgram = ProgramUtils.copy(invokedMethod.getProgram());
|
||||
|
||||
TextLocation location = insn.getLocation();
|
||||
InliningInfo innerInliningInfo = new InliningInfo(
|
||||
invoke.getMethod(),
|
||||
location != null ? location.getFileName() : null,
|
||||
location != null ? location.getLine() : -1,
|
||||
inliningInfo);
|
||||
|
||||
PlanEntry entry = new PlanEntry();
|
||||
entry.targetBlock = block.getIndex();
|
||||
entry.targetInstruction = insn;
|
||||
entry.program = invokedProgram;
|
||||
entry.innerPlan.addAll(buildPlan(invokedProgram, depth + 1, innerStep, invokedMethod.getReference()));
|
||||
entry.innerPlan.addAll(buildPlan(invokedProgram, depth + 1, innerStep, invokedMethod.getReference(),
|
||||
inliningInfo));
|
||||
entry.depth = depth;
|
||||
entry.method = invokedMethod.getReference();
|
||||
entry.locationInfo = innerInliningInfo;
|
||||
plan.add(entry);
|
||||
}
|
||||
}
|
||||
|
@ -441,6 +463,7 @@ public class Inlining {
|
|||
Program program;
|
||||
int depth;
|
||||
final List<PlanEntry> innerPlan = new ArrayList<>();
|
||||
InliningInfo locationInfo;
|
||||
}
|
||||
|
||||
static class MethodUsageCounter extends AbstractInstructionReader {
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Copyright 2019 Alexey Andreev.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.teavm.model.optimization;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import org.teavm.model.InliningInfo;
|
||||
|
||||
class InliningInfoMerger {
|
||||
private InliningInfo parent;
|
||||
Map<InliningInfo, InliningInfo> inliningInfoCache = new HashMap<>();
|
||||
|
||||
InliningInfoMerger(InliningInfo parent) {
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
InliningInfo merge(InliningInfo inliningInfo) {
|
||||
if (inliningInfo == null) {
|
||||
return parent;
|
||||
}
|
||||
|
||||
InliningInfo result = inliningInfoCache.get(inliningInfo);
|
||||
if (result == null) {
|
||||
result = new InliningInfo(inliningInfo.getMethod(), inliningInfo.getFileName(), inliningInfo.getLine(),
|
||||
merge(inliningInfo.getParent()));
|
||||
inliningInfoCache.put(inliningInfo, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
|
@ -158,6 +158,11 @@ class InstructionStringifier implements InstructionReader {
|
|||
}
|
||||
|
||||
private InstructionStringifier escapeIdentifierIfNeeded(String s) {
|
||||
escapeIdentifierIfNeeded(sb, s);
|
||||
return this;
|
||||
}
|
||||
|
||||
static void escapeIdentifierIfNeeded(StringBuilder sb, String s) {
|
||||
boolean needsEscaping = false;
|
||||
if (s.isEmpty()) {
|
||||
needsEscaping = true;
|
||||
|
@ -176,8 +181,6 @@ class InstructionStringifier implements InstructionReader {
|
|||
} else {
|
||||
sb.append(s);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -19,6 +19,7 @@ import java.util.List;
|
|||
import java.util.Objects;
|
||||
import org.teavm.model.BasicBlockReader;
|
||||
import org.teavm.model.IncomingReader;
|
||||
import org.teavm.model.InliningInfo;
|
||||
import org.teavm.model.InstructionIterator;
|
||||
import org.teavm.model.PhiReader;
|
||||
import org.teavm.model.ProgramReader;
|
||||
|
@ -76,13 +77,24 @@ public class ListingBuilder {
|
|||
if (!Objects.equals(location, stringifier.getLocation())) {
|
||||
location = stringifier.getLocation();
|
||||
sb.append(prefix).append(" at ");
|
||||
if (location == null) {
|
||||
if (location == null || location.isEmpty()) {
|
||||
sb.append("unknown location");
|
||||
} else {
|
||||
sb.append("'");
|
||||
InstructionStringifier.escapeStringLiteral(location.getFileName(), sb);
|
||||
sb.append("' " + location.getLine());
|
||||
}
|
||||
if (location != null) {
|
||||
InliningInfo inliningInfo = location.getInlining();
|
||||
while (inliningInfo != null) {
|
||||
sb.append(" at ");
|
||||
InstructionStringifier.escapeIdentifierIfNeeded(sb, inliningInfo.getMethod().toString());
|
||||
sb.append(" '");
|
||||
InstructionStringifier.escapeStringLiteral(inliningInfo.getFileName(), sb);
|
||||
sb.append("' " + inliningInfo.getLine());
|
||||
inliningInfo = inliningInfo.getParent();
|
||||
}
|
||||
}
|
||||
sb.append('\n');
|
||||
}
|
||||
sb.append(prefix).append(" ").append(insnSb).append("\n");
|
||||
|
|
|
@ -332,7 +332,7 @@ public class ProgramParser {
|
|||
BasicBlock basicBlock = null;
|
||||
Map<Integer, String> accumulatedDebugNames = new HashMap<>();
|
||||
Integer lastLineNumber = null;
|
||||
TextLocation lastLocation = null;
|
||||
TextLocation lastLocation = TextLocation.EMPTY;
|
||||
for (int i = 0; i < basicBlocks.size(); ++i) {
|
||||
BasicBlock newBasicBlock = basicBlocks.get(i);
|
||||
if (newBasicBlock != null) {
|
||||
|
|
|
@ -37,7 +37,7 @@ interface TeaVMTestConfiguration<T extends TeaVMTarget> {
|
|||
|
||||
@Override
|
||||
public void apply(TeaVM vm) {
|
||||
vm.setOptimizationLevel(TeaVMOptimizationLevel.SIMPLE);
|
||||
vm.setOptimizationLevel(TeaVMOptimizationLevel.FULL);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
Loading…
Reference in New Issue
Block a user