Merge remote branch 'origin/master'

This commit is contained in:
Andrey Breslav
2012-01-17 19:04:20 +04:00
27 changed files with 920 additions and 532 deletions
@@ -7,9 +7,8 @@ import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.Function; import com.intellij.util.Function;
import com.intellij.util.Processor; import com.intellij.util.Processor;
import jet.ExtensionFunction0; import jet.modules.AllModules;
import jet.modules.IModuleBuilder; import jet.modules.Module;
import jet.modules.IModuleSetBuilder;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.codegen.ClassFileFactory; import org.jetbrains.jet.codegen.ClassFileFactory;
import org.jetbrains.jet.codegen.GeneratedClassLoader; import org.jetbrains.jet.codegen.GeneratedClassLoader;
@@ -19,7 +18,7 @@ import org.jetbrains.jet.lang.resolve.java.JvmAbi;
import org.jetbrains.jet.plugin.JetMainDetector; import org.jetbrains.jet.plugin.JetMainDetector;
import java.io.*; import java.io.*;
import java.lang.reflect.Field; import java.lang.reflect.Method;
import java.net.URL; import java.net.URL;
import java.net.URLClassLoader; import java.net.URLClassLoader;
import java.util.List; import java.util.List;
@@ -174,13 +173,14 @@ public class CompileEnvironment {
e.printStackTrace(); e.printStackTrace();
} }
final IModuleSetBuilder moduleSetBuilder = loadModuleScript(moduleFile); final List<Module> modules = loadModuleScript(moduleFile);
if (moduleSetBuilder == null) {
return; if (modules == null) {
throw new CompileEnvironmentException("Module script " + moduleFile + " compilation failed");
} }
final String directory = new File(moduleFile).getParent(); final String directory = new File(moduleFile).getParent();
for (IModuleBuilder moduleBuilder : moduleSetBuilder.getModules()) { for (Module moduleBuilder : modules) {
ClassFileFactory moduleFactory = compileModule(moduleBuilder, directory); ClassFileFactory moduleFactory = compileModule(moduleBuilder, directory);
final String path = jarPath != null ? jarPath : new File(directory, moduleBuilder.getModuleName() + ".jar").getPath(); final String path = jarPath != null ? jarPath : new File(directory, moduleBuilder.getModuleName() + ".jar").getPath();
try { try {
@@ -191,7 +191,7 @@ public class CompileEnvironment {
} }
} }
public IModuleSetBuilder loadModuleScript(String moduleFile) { public List<Module> loadModuleScript(String moduleFile) {
CompileSession scriptCompileSession = new CompileSession(myEnvironment); CompileSession scriptCompileSession = new CompileSession(myEnvironment);
scriptCompileSession.addSources(moduleFile); scriptCompileSession.addSources(moduleFile);
scriptCompileSession.addStdLibSources(true); scriptCompileSession.addStdLibSources(true);
@@ -204,34 +204,25 @@ public class CompileEnvironment {
return runDefineModules(moduleFile, factory); return runDefineModules(moduleFile, factory);
} }
private static IModuleSetBuilder runDefineModules(String moduleFile, ClassFileFactory factory) { private static List<Module> runDefineModules(String moduleFile, ClassFileFactory factory) {
GeneratedClassLoader loader = new GeneratedClassLoader(factory); GeneratedClassLoader loader = new GeneratedClassLoader(factory);
try { try {
Class moduleSetBuilderClass = loader.loadClass("kotlin.modules.ModuleSetBuilder");
final IModuleSetBuilder moduleSetBuilder = (IModuleSetBuilder) moduleSetBuilderClass.newInstance();
Class namespaceClass = loader.loadClass(JvmAbi.PACKAGE_CLASS); Class namespaceClass = loader.loadClass(JvmAbi.PACKAGE_CLASS);
final Field[] fields = namespaceClass.getDeclaredFields(); final Method method = namespaceClass.getDeclaredMethod("project");
boolean modulesDefined = false; if (method == null) {
for (Field field : fields) { throw new CompileEnvironmentException("Module script " + moduleFile + " must define project() function");
if (field.getName().equals("modules")) {
field.setAccessible(true);
ExtensionFunction0 defineMudules = (ExtensionFunction0) field.get(null);
defineMudules.invoke(moduleSetBuilder);
modulesDefined = true;
break;
}
} }
if (!modulesDefined) {
throw new CompileEnvironmentException("Module script " + moduleFile + " must define a modules() property"); method.setAccessible(true);
} method.invoke(null);
return moduleSetBuilder;
return AllModules.modules;
} catch (Exception e) { } catch (Exception e) {
throw new CompileEnvironmentException(e); throw new CompileEnvironmentException(e);
} }
} }
public ClassFileFactory compileModule(IModuleBuilder moduleBuilder, String directory) { public ClassFileFactory compileModule(Module moduleBuilder, String directory) {
CompileSession moduleCompileSession = new CompileSession(myEnvironment); CompileSession moduleCompileSession = new CompileSession(myEnvironment);
if (!"stdlib".equals(moduleBuilder.getModuleName())) { if (!"stdlib".equals(moduleBuilder.getModuleName())) {
moduleCompileSession.addStdLibSources(false); moduleCompileSession.addStdLibSources(false);
@@ -19,6 +19,7 @@ public interface JetControlFlowBuilder {
void bindLabel(@NotNull Label label); void bindLabel(@NotNull Label label);
void allowDead(); void allowDead();
void stopAllowDead();
// Jumps // Jumps
void jump(@NotNull Label label); void jump(@NotNull Label label);
@@ -43,6 +43,12 @@ public class JetControlFlowBuilderAdapter implements JetControlFlowBuilder {
builder.allowDead(); builder.allowDead();
} }
@Override
public void stopAllowDead() {
assert builder != null;
builder.stopAllowDead();
}
@Override @Override
public void jump(@NotNull Label label) { public void jump(@NotNull Label label) {
assert builder != null; assert builder != null;
@@ -8,10 +8,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.cfg.pseudocode.*; import org.jetbrains.jet.lang.cfg.pseudocode.*;
import java.util.Collection; import java.util.*;
import java.util.Collections;
import java.util.List;
import java.util.Map;
/** /**
* @author svtk * @author svtk
@@ -140,7 +137,6 @@ public class JetControlFlowGraphTraverser<D> {
Collections.reverse(instructions); Collections.reverse(instructions);
} }
for (Instruction instruction : instructions) { for (Instruction instruction : instructions) {
if (instruction.isDead()) continue;
if (lookInside && instruction instanceof LocalDeclarationInstruction) { if (lookInside && instruction instanceof LocalDeclarationInstruction) {
traverseAndAnalyzeInstructionGraph(((LocalDeclarationInstruction) instruction).getBody(), instructionDataAnalyzeStrategy); traverseAndAnalyzeInstructionGraph(((LocalDeclarationInstruction) instruction).getBody(), instructionDataAnalyzeStrategy);
} }
@@ -153,6 +153,8 @@ public class JetControlFlowProcessor {
@Override @Override
public void visitParenthesizedExpression(JetParenthesizedExpression expression) { public void visitParenthesizedExpression(JetParenthesizedExpression expression) {
builder.read(expression);
JetExpression innerExpression = expression.getExpression(); JetExpression innerExpression = expression.getExpression();
if (innerExpression != null) { if (innerExpression != null) {
value(innerExpression, inCondition); value(innerExpression, inCondition);
@@ -340,6 +342,7 @@ public class JetControlFlowProcessor {
@Override @Override
public void visitTryExpression(JetTryExpression expression) { public void visitTryExpression(JetTryExpression expression) {
builder.read(expression);
final JetFinallySection finallyBlock = expression.getFinallyBlock(); final JetFinallySection finallyBlock = expression.getFinallyBlock();
if (finallyBlock != null) { if (finallyBlock != null) {
builder.enterTryFinally(new GenerationTrigger() { builder.enterTryFinally(new GenerationTrigger() {
@@ -408,10 +411,12 @@ public class JetControlFlowProcessor {
builder.exitTryFinally(); builder.exitTryFinally();
value(finallyBlock.getFinalExpression(), inCondition); value(finallyBlock.getFinalExpression(), inCondition);
} }
builder.stopAllowDead();
} }
@Override @Override
public void visitWhileExpression(JetWhileExpression expression) { public void visitWhileExpression(JetWhileExpression expression) {
builder.read(expression);
LoopInfo loopInfo = builder.enterLoop(expression, null, null); LoopInfo loopInfo = builder.enterLoop(expression, null, null);
builder.bindLabel(loopInfo.getConditionEntryPoint()); builder.bindLabel(loopInfo.getConditionEntryPoint());
@@ -433,6 +438,7 @@ public class JetControlFlowProcessor {
@Override @Override
public void visitDoWhileExpression(JetDoWhileExpression expression) { public void visitDoWhileExpression(JetDoWhileExpression expression) {
builder.read(expression);
LoopInfo loopInfo = builder.enterLoop(expression, null, null); LoopInfo loopInfo = builder.enterLoop(expression, null, null);
builder.bindLabel(loopInfo.getBodyEntryPoint()); builder.bindLabel(loopInfo.getBodyEntryPoint());
@@ -452,6 +458,7 @@ public class JetControlFlowProcessor {
@Override @Override
public void visitForExpression(JetForExpression expression) { public void visitForExpression(JetForExpression expression) {
builder.read(expression);
JetExpression loopRange = expression.getLoopRange(); JetExpression loopRange = expression.getLoopRange();
if (loopRange != null) { if (loopRange != null) {
value(loopRange, false); value(loopRange, false);
@@ -252,7 +252,10 @@ public class JetFlowInformationProvider {
analyzeLocalDeclarations(processLocalDeclaration, pseudocode); analyzeLocalDeclarations(processLocalDeclaration, pseudocode);
} }
private void checkIsInitialized(@NotNull VariableDescriptor variableDescriptor, @NotNull JetElement element, @NotNull VariableInitializers variableInitializers, @NotNull Collection<VariableDescriptor> varWithUninitializedErrorGenerated) { private void checkIsInitialized(@NotNull VariableDescriptor variableDescriptor,
@NotNull JetElement element,
@NotNull VariableInitializers variableInitializers,
@NotNull Collection<VariableDescriptor> varWithUninitializedErrorGenerated) {
if (!(element instanceof JetSimpleNameExpression)) return; if (!(element instanceof JetSimpleNameExpression)) return;
boolean isInitialized = variableInitializers.isInitialized(); boolean isInitialized = variableInitializers.isInitialized();
@@ -272,7 +275,10 @@ public class JetFlowInformationProvider {
} }
} }
private boolean checkValReassignment(@NotNull VariableDescriptor variableDescriptor, @NotNull JetExpression expression, @NotNull VariableInitializers enterInitializers, @NotNull Collection<VariableDescriptor> varWithValReassignErrorGenerated) { private boolean checkValReassignment(@NotNull VariableDescriptor variableDescriptor,
@NotNull JetExpression expression,
@NotNull VariableInitializers enterInitializers,
@NotNull Collection<VariableDescriptor> varWithValReassignErrorGenerated) {
boolean isInitializedNotHere = enterInitializers.isInitialized(); boolean isInitializedNotHere = enterInitializers.isInitialized();
Set<JetElement> possibleLocalInitializers = enterInitializers.getPossibleLocalInitializers(); Set<JetElement> possibleLocalInitializers = enterInitializers.getPossibleLocalInitializers();
if (possibleLocalInitializers.size() == 1) { if (possibleLocalInitializers.size() == 1) {
@@ -20,6 +20,4 @@ public interface Instruction {
Collection<Instruction> getNextInstructions(); Collection<Instruction> getNextInstructions();
void accept(InstructionVisitor visitor); void accept(InstructionVisitor visitor);
boolean isDead();
} }
@@ -190,7 +190,7 @@ public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAd
bindLabel(getExitPoint(subroutine)); bindLabel(getExitPoint(subroutine));
pseudocode.addExitInstruction(new SubroutineExitInstruction(subroutine, "<END>")); pseudocode.addExitInstruction(new SubroutineExitInstruction(subroutine, "<END>"));
bindLabel(error); bindLabel(error);
add(new SubroutineExitInstruction(subroutine, "<ERROR>")); pseudocode.addErrorInstruction(new SubroutineExitInstruction(subroutine, "<ERROR>"));
bindLabel(sink); bindLabel(sink);
pseudocode.addSinkInstruction(new SubroutineSinkInstruction(subroutine, "<SINK>")); pseudocode.addSinkInstruction(new SubroutineSinkInstruction(subroutine, "<SINK>"));
elementToBlockInfo.remove(subroutine); elementToBlockInfo.remove(subroutine);
@@ -266,6 +266,13 @@ public class JetControlFlowInstructionsGenerator extends JetControlFlowBuilderAd
pseudocode.allowDead(allowedDeadLabel); pseudocode.allowDead(allowedDeadLabel);
} }
@Override
public void stopAllowDead() {
Label allowedDeadLabel = createUnboundLabel();
bindLabel(allowedDeadLabel);
pseudocode.stopAllowDead(allowedDeadLabel);
}
@Override @Override
public void nondeterministicJump(Label label) { public void nondeterministicJump(Label label) {
handleJumpInsideTryFinally(label); handleJumpInsideTryFinally(label);
@@ -56,12 +56,16 @@ public class Pseudocode {
private final List<Instruction> mutableInstructionList = new ArrayList<Instruction>(); private final List<Instruction> mutableInstructionList = new ArrayList<Instruction>();
private final List<Instruction> instructions = new ArrayList<Instruction>(); private final List<Instruction> instructions = new ArrayList<Instruction>();
private List<Instruction> deadInstructions;
private final List<PseudocodeLabel> labels = new ArrayList<PseudocodeLabel>(); private final List<PseudocodeLabel> labels = new ArrayList<PseudocodeLabel>();
private final List<PseudocodeLabel> allowedDeadLabels = new ArrayList<PseudocodeLabel>(); private final List<PseudocodeLabel> allowedDeadLabels = new ArrayList<PseudocodeLabel>();
private final List<PseudocodeLabel> stopAllowDeadLabels = new ArrayList<PseudocodeLabel>();
private final JetElement correspondingElement; private final JetElement correspondingElement;
private SubroutineExitInstruction exitInstruction; private SubroutineExitInstruction exitInstruction;
private SubroutineSinkInstruction sinkInstruction; private SubroutineSinkInstruction sinkInstruction;
private SubroutineExitInstruction errorInstruction;
private boolean postPrecessed = false; private boolean postPrecessed = false;
public Pseudocode(JetElement correspondingElement) { public Pseudocode(JetElement correspondingElement) {
@@ -81,6 +85,10 @@ public class Pseudocode {
public void allowDead(Label label) { public void allowDead(Label label) {
allowedDeadLabels.add((PseudocodeLabel) label); allowedDeadLabels.add((PseudocodeLabel) label);
} }
public void stopAllowDead(Label label) {
stopAllowDeadLabels.add((PseudocodeLabel) label);
}
@NotNull @NotNull
public List<Instruction> getInstructions() { public List<Instruction> getInstructions() {
@@ -95,10 +103,17 @@ public class Pseudocode {
@NotNull @NotNull
public List<Instruction> getDeadInstructions() { public List<Instruction> getDeadInstructions() {
List<Instruction> deadInstructions = Lists.newArrayList(); if (deadInstructions != null) {
for (Instruction instruction : instructions) { return deadInstructions;
if (instruction.isDead()) { }
deadInstructions.add(instruction); deadInstructions = Lists.newArrayList();
Collection<Instruction> allowedDeadInstructions = collectAllowedDeadInstructions();
for (Instruction instruction : mutableInstructionList) {
if (((InstructionImpl)instruction).isDead()) {
if (!allowedDeadInstructions.contains(instruction)) {
deadInstructions.add(instruction);
}
} }
} }
return deadInstructions; return deadInstructions;
@@ -122,6 +137,12 @@ public class Pseudocode {
this.sinkInstruction = sinkInstruction; this.sinkInstruction = sinkInstruction;
} }
public void addErrorInstruction(SubroutineExitInstruction errorInstruction) {
addInstruction(errorInstruction);
assert this.errorInstruction == null;
this.errorInstruction = errorInstruction;
}
public void addInstruction(Instruction instruction) { public void addInstruction(Instruction instruction) {
mutableInstructionList.add(instruction); mutableInstructionList.add(instruction);
instruction.setOwner(this); instruction.setOwner(this);
@@ -151,88 +172,107 @@ public class Pseudocode {
if (postPrecessed) return; if (postPrecessed) return;
postPrecessed = true; postPrecessed = true;
for (int i = 0, instructionsSize = mutableInstructionList.size(); i < instructionsSize; i++) { for (int i = 0, instructionsSize = mutableInstructionList.size(); i < instructionsSize; i++) {
Instruction instruction = mutableInstructionList.get(i); processInstruction(mutableInstructionList.get(i), i);
final int currentPosition = i;
instruction.accept(new InstructionVisitor() {
@Override
public void visitInstructionWithNext(InstructionWithNext instruction) {
instruction.setNext(getNextPosition(currentPosition));
}
@Override
public void visitJump(AbstractJumpInstruction instruction) {
instruction.setResolvedTarget(getJumpTarget(instruction.getTargetLabel()));
}
@Override
public void visitNondeterministicJump(NondeterministicJumpInstruction instruction) {
instruction.setNext(getNextPosition(currentPosition));
List<Label> targetLabels = instruction.getTargetLabels();
for (Label targetLabel : targetLabels) {
instruction.setResolvedTarget(targetLabel, getJumpTarget(targetLabel));
}
}
@Override
public void visitConditionalJump(ConditionalJumpInstruction instruction) {
Instruction nextInstruction = getNextPosition(currentPosition);
Instruction jumpTarget = getJumpTarget(instruction.getTargetLabel());
if (instruction.onTrue()) {
instruction.setNextOnFalse(nextInstruction);
instruction.setNextOnTrue(jumpTarget);
}
else {
instruction.setNextOnFalse(jumpTarget);
instruction.setNextOnTrue(nextInstruction);
}
visitJump(instruction);
}
@Override
public void visitLocalDeclarationInstruction(LocalDeclarationInstruction instruction) {
instruction.getBody().postProcess();
instruction.setNext(getSinkInstruction());
}
@Override
public void visitSubroutineExit(SubroutineExitInstruction instruction) {
// Nothing
}
@Override
public void visitSubroutineSink(SubroutineSinkInstruction instruction) {
// Nothing
}
@Override
public void visitInstruction(Instruction instruction) {
throw new UnsupportedOperationException(instruction.toString());
}
});
} }
getExitInstruction().setSink(getSinkInstruction()); getExitInstruction().setSink(getSinkInstruction());
Set<Instruction> allowedDeadStartInstructions = prepareAllowedDeadInstructions(); Set<Instruction> reachableInstructions = collectReachableInstructions();
for (Instruction instruction : mutableInstructionList) {
if (reachableInstructions.contains(instruction)) {
instructions.add(instruction);
}
}
markDeadInstructions(); markDeadInstructions();
Collection<Instruction> allowedDeadInstructions = collectAllowedDeadInstructions(allowedDeadStartInstructions); }
instructions.addAll(mutableInstructionList);
instructions.removeAll(allowedDeadInstructions);
private void processInstruction(Instruction instruction, final int currentPosition) {
instruction.accept(new InstructionVisitor() {
@Override
public void visitInstructionWithNext(InstructionWithNext instruction) {
instruction.setNext(getNextPosition(currentPosition));
}
@Override
public void visitJump(AbstractJumpInstruction instruction) {
instruction.setResolvedTarget(getJumpTarget(instruction.getTargetLabel()));
}
@Override
public void visitNondeterministicJump(NondeterministicJumpInstruction instruction) {
instruction.setNext(getNextPosition(currentPosition));
List<Label> targetLabels = instruction.getTargetLabels();
for (Label targetLabel : targetLabels) {
instruction.setResolvedTarget(targetLabel, getJumpTarget(targetLabel));
}
}
@Override
public void visitConditionalJump(ConditionalJumpInstruction instruction) {
Instruction nextInstruction = getNextPosition(currentPosition);
Instruction jumpTarget = getJumpTarget(instruction.getTargetLabel());
if (instruction.onTrue()) {
instruction.setNextOnFalse(nextInstruction);
instruction.setNextOnTrue(jumpTarget);
}
else {
instruction.setNextOnFalse(jumpTarget);
instruction.setNextOnTrue(nextInstruction);
}
visitJump(instruction);
}
@Override
public void visitLocalDeclarationInstruction(LocalDeclarationInstruction instruction) {
instruction.getBody().postProcess();
instruction.setNext(getSinkInstruction());
}
@Override
public void visitSubroutineExit(SubroutineExitInstruction instruction) {
// Nothing
}
@Override
public void visitSubroutineSink(SubroutineSinkInstruction instruction) {
// Nothing
}
@Override
public void visitInstruction(Instruction instruction) {
throw new UnsupportedOperationException(instruction.toString());
}
});
}
private Set<Instruction> collectReachableInstructions() {
Set<Instruction> visited = Sets.newHashSet();
traverseNextInstructions(getEnterInstruction(), visited);
if (!visited.contains(getExitInstruction())) {
visited.add(getExitInstruction());
}
if (!visited.contains(errorInstruction)) {
visited.add(errorInstruction);
}
if (!visited.contains(getSinkInstruction())) {
visited.add(getSinkInstruction());
}
return visited;
}
private void traverseNextInstructions(Instruction instruction, Set<Instruction> visited) {
if (visited.contains(instruction)) return;
visited.add(instruction);
for (Instruction nextInstruction : instruction.getNextInstructions()) {
traverseNextInstructions(nextInstruction, visited);
}
} }
private void markDeadInstructions() { private void markDeadInstructions() {
boolean hasRemovedInstruction = true; Set<Instruction> instructionSet = Sets.newHashSet(instructions);
Collection<Instruction> processedInstructions = Sets.newHashSet(); for (Instruction instruction : mutableInstructionList) {
while (hasRemovedInstruction) { if (!instructionSet.contains(instruction)) {
hasRemovedInstruction = false; ((InstructionImpl)instruction).die();
for (Instruction instruction : mutableInstructionList) { for (Instruction nextInstruction : instruction.getNextInstructions()) {
if (!(instruction instanceof SubroutineEnterInstruction || instruction instanceof SubroutineExitInstruction || instruction instanceof SubroutineSinkInstruction) && nextInstruction.getPreviousInstructions().remove(instruction);
instruction.getPreviousInstructions().isEmpty() && !processedInstructions.contains(instruction)) {
hasRemovedInstruction = true;
for (Instruction nextInstruction : instruction.getNextInstructions()) {
nextInstruction.getPreviousInstructions().remove(instruction);
}
((InstructionImpl)instruction).die();
processedInstructions.add(instruction);
} }
} }
} }
@@ -243,27 +283,43 @@ public class Pseudocode {
Set<Instruction> allowedDeadStartInstructions = Sets.newHashSet(); Set<Instruction> allowedDeadStartInstructions = Sets.newHashSet();
for (PseudocodeLabel allowedDeadLabel : allowedDeadLabels) { for (PseudocodeLabel allowedDeadLabel : allowedDeadLabels) {
Instruction allowedDeadInstruction = getJumpTarget(allowedDeadLabel); Instruction allowedDeadInstruction = getJumpTarget(allowedDeadLabel);
if (allowedDeadInstruction.getPreviousInstructions().isEmpty()) { if (((InstructionImpl)allowedDeadInstruction).isDead()) {
allowedDeadStartInstructions.add(allowedDeadInstruction); allowedDeadStartInstructions.add(allowedDeadInstruction);
} }
} }
return allowedDeadStartInstructions; return allowedDeadStartInstructions;
} }
@NotNull
private Set<Instruction> prepareStopAllowedDeadInstructions() {
Set<Instruction> stopAllowedDeadInstructions = Sets.newHashSet();
for (PseudocodeLabel stopAllowedDeadLabel : stopAllowDeadLabels) {
Instruction stopAllowDeadInsruction = getJumpTarget(stopAllowedDeadLabel);
if (((InstructionImpl)stopAllowDeadInsruction).isDead()) {
stopAllowedDeadInstructions.add(stopAllowDeadInsruction);
}
}
return stopAllowedDeadInstructions;
}
@NotNull @NotNull
private Collection<Instruction> collectAllowedDeadInstructions(@NotNull Set<Instruction> allowedDeadStartInstructions) { private Collection<Instruction> collectAllowedDeadInstructions() {
Set<Instruction> allowedDeadStartInstructions = prepareAllowedDeadInstructions();
Set<Instruction> stopAllowDeadInstructions = prepareStopAllowedDeadInstructions();
Set<Instruction> allowedDeadInstructions = Sets.newHashSet(); Set<Instruction> allowedDeadInstructions = Sets.newHashSet();
for (Instruction allowedDeadStartInstruction : allowedDeadStartInstructions) { for (Instruction allowedDeadStartInstruction : allowedDeadStartInstructions) {
collectAllowedDeadInstructions(allowedDeadStartInstruction, allowedDeadInstructions); collectAllowedDeadInstructions(allowedDeadStartInstruction, allowedDeadInstructions, stopAllowDeadInstructions);
} }
return allowedDeadInstructions; return allowedDeadInstructions;
} }
private void collectAllowedDeadInstructions(Instruction allowedDeadInstruction, Set<Instruction> instructionSet) { private void collectAllowedDeadInstructions(Instruction allowedDeadInstruction, Set<Instruction> instructionSet, Set<Instruction> stopAllowDeadInstructions) {
if (allowedDeadInstruction.isDead()) { if (stopAllowDeadInstructions.contains(allowedDeadInstruction)) return;
if (((InstructionImpl)allowedDeadInstruction).isDead()) {
instructionSet.add(allowedDeadInstruction); instructionSet.add(allowedDeadInstruction);
for (Instruction instruction : allowedDeadInstruction.getNextInstructions()) { for (Instruction instruction : allowedDeadInstruction.getNextInstructions()) {
collectAllowedDeadInstructions(instruction, instructionSet); collectAllowedDeadInstructions(instruction, instructionSet, stopAllowDeadInstructions);
} }
} }
} }
File diff suppressed because it is too large Load Diff
+19 -16
View File
@@ -6,29 +6,32 @@ fun t1() {
} }
--------------------- ---------------------
l0: l0:
<START> NEXT:[r(1)] PREV:[] <START> NEXT:[r(for (i in 1..2) { doSmth(i..)] PREV:[]
r(1) NEXT:[r(2)] PREV:[<START>] r(for (i in 1..2) {
r(2) NEXT:[r(..)] PREV:[r(1)] doSmth(i)
r(..) NEXT:[r(1..2)] PREV:[r(2)] }) NEXT:[r(1)] PREV:[<START>]
r(1..2) NEXT:[v(i)] PREV:[r(..)] r(1) NEXT:[r(2)] PREV:[r(for (i in 1..2) { doSmth(i..)]
v(i) NEXT:[w(i)] PREV:[r(1..2)] r(2) NEXT:[r(..)] PREV:[r(1)]
w(i) NEXT:[jmp?(l2)] PREV:[v(i)] r(..) NEXT:[r(1..2)] PREV:[r(2)]
r(1..2) NEXT:[v(i)] PREV:[r(..)]
v(i) NEXT:[w(i)] PREV:[r(1..2)]
w(i) NEXT:[jmp?(l2)] PREV:[v(i)]
l3: l3:
jmp?(l2) NEXT:[read (Unit), r(i)] PREV:[w(i)] jmp?(l2) NEXT:[read (Unit), r(i)] PREV:[w(i)]
l4: l4:
l5: l5:
r(i) NEXT:[r(doSmth)] PREV:[jmp?(l2), jmp?(l4)] r(i) NEXT:[r(doSmth)] PREV:[jmp?(l2), jmp?(l4)]
r(doSmth) NEXT:[r(doSmth(i))] PREV:[r(i)] r(doSmth) NEXT:[r(doSmth(i))] PREV:[r(i)]
r(doSmth(i)) NEXT:[jmp?(l4)] PREV:[r(doSmth)] r(doSmth(i)) NEXT:[jmp?(l4)] PREV:[r(doSmth)]
jmp?(l4) NEXT:[r(i), read (Unit)] PREV:[r(doSmth(i))] jmp?(l4) NEXT:[r(i), read (Unit)] PREV:[r(doSmth(i))]
l2: l2:
read (Unit) NEXT:[<END>] PREV:[jmp?(l2), jmp?(l4)] read (Unit) NEXT:[<END>] PREV:[jmp?(l2), jmp?(l4)]
l1: l1:
<END> NEXT:[<SINK>] PREV:[read (Unit)] <END> NEXT:[<SINK>] PREV:[read (Unit)]
error: error:
<ERROR> NEXT:[] PREV:[] <ERROR> NEXT:[] PREV:[]
sink: sink:
<SINK> NEXT:[] PREV:[<END>] <SINK> NEXT:[] PREV:[<END>]
===================== =====================
== doSmth == == doSmth ==
fun doSmth(i: Int) {} fun doSmth(i: Int) {}
+2 -2
View File
@@ -74,7 +74,7 @@ l0:
r(b) NEXT:[jf(l2)] PREV:[w(i)] r(b) NEXT:[jf(l2)] PREV:[w(i)]
jf(l2) NEXT:[read (Unit), ret l1] PREV:[r(b)] jf(l2) NEXT:[read (Unit), ret l1] PREV:[r(b)]
ret l1 NEXT:[<END>] PREV:[jf(l2)] ret l1 NEXT:[<END>] PREV:[jf(l2)]
* jmp(l3) NEXT:[r(i)] PREV:[] - jmp(l3) NEXT:[r(i)] PREV:[]
l2: l2:
read (Unit) NEXT:[r(i)] PREV:[jf(l2)] read (Unit) NEXT:[r(i)] PREV:[jf(l2)]
l3: l3:
@@ -85,7 +85,7 @@ l3:
r(i is Int) NEXT:[jf(l4)] PREV:[r(i)] r(i is Int) NEXT:[jf(l4)] PREV:[r(i)]
jf(l4) NEXT:[read (Unit), ret l1] PREV:[r(i is Int)] jf(l4) NEXT:[read (Unit), ret l1] PREV:[r(i is Int)]
ret l1 NEXT:[<END>] PREV:[jf(l4)] ret l1 NEXT:[<END>] PREV:[jf(l4)]
* jmp(l5) NEXT:[<END>] PREV:[] - jmp(l5) NEXT:[<END>] PREV:[]
l4: l4:
read (Unit) NEXT:[<END>] PREV:[jf(l4)] read (Unit) NEXT:[<END>] PREV:[jf(l4)]
l1: l1:
@@ -6,25 +6,28 @@ fun main() {
} }
--------------------- ---------------------
l0: l0:
<START> NEXT:[r(1)] PREV:[] <START> NEXT:[r(while(1 > 0) { 2 }) ] PREV:[]
r(while(1 > 0) {
2
}) NEXT:[r(1)] PREV:[<START>]
l2: l2:
l5: l5:
r(1) NEXT:[r(0)] PREV:[<START>, jmp(l2)] r(1) NEXT:[r(0)] PREV:[r(while(1 > 0) { 2 }) , jmp(l2)]
r(0) NEXT:[r(>)] PREV:[r(1)] r(0) NEXT:[r(>)] PREV:[r(1)]
r(>) NEXT:[r(1 > 0)] PREV:[r(0)] r(>) NEXT:[r(1 > 0)] PREV:[r(0)]
r(1 > 0) NEXT:[jf(l3)] PREV:[r(>)] r(1 > 0) NEXT:[jf(l3)] PREV:[r(>)]
jf(l3) NEXT:[read (Unit), r(2)] PREV:[r(1 > 0)] jf(l3) NEXT:[read (Unit), r(2)] PREV:[r(1 > 0)]
l4: l4:
r(2) NEXT:[jmp(l2)] PREV:[jf(l3)] r(2) NEXT:[jmp(l2)] PREV:[jf(l3)]
jmp(l2) NEXT:[r(1)] PREV:[r(2)] jmp(l2) NEXT:[r(1)] PREV:[r(2)]
l3: l3:
read (Unit) NEXT:[<END>] PREV:[jf(l3)] read (Unit) NEXT:[<END>] PREV:[jf(l3)]
l1: l1:
<END> NEXT:[<SINK>] PREV:[read (Unit)] <END> NEXT:[<SINK>] PREV:[read (Unit)]
error: error:
<ERROR> NEXT:[] PREV:[] <ERROR> NEXT:[] PREV:[]
sink: sink:
<SINK> NEXT:[] PREV:[<END>] <SINK> NEXT:[] PREV:[<END>]
===================== =====================
== dowhile == == dowhile ==
fun dowhile() { fun dowhile() {
@@ -33,22 +36,24 @@ fun dowhile() {
} }
--------------------- ---------------------
l0: l0:
<START> NEXT:[ret l1] PREV:[] <START> NEXT:[r(do {return} while(1 > 0)) ] PREV:[]
r(do {return}
while(1 > 0)) NEXT:[ret l1] PREV:[<START>]
l2: l2:
l4: l4:
ret l1 NEXT:[<END>] PREV:[<START>] ret l1 NEXT:[<END>] PREV:[r(do {return} while(1 > 0)) ]
l5: l5:
* r(1) NEXT:[r(0)] PREV:[] - r(1) NEXT:[r(0)] PREV:[]
* r(0) NEXT:[r(>)] PREV:[] - r(0) NEXT:[r(>)] PREV:[]
* r(>) NEXT:[r(1 > 0)] PREV:[] - r(>) NEXT:[r(1 > 0)] PREV:[]
* r(1 > 0) NEXT:[jt(l2)] PREV:[] - r(1 > 0) NEXT:[jt(l2)] PREV:[]
* jt(l2) NEXT:[read (Unit), ret l1] PREV:[] - jt(l2) NEXT:[read (Unit), ret l1] PREV:[]
l3: l3:
* read (Unit) NEXT:[<END>] PREV:[] - read (Unit) NEXT:[<END>] PREV:[]
l1: l1:
<END> NEXT:[<SINK>] PREV:[ret l1] <END> NEXT:[<SINK>] PREV:[ret l1]
error: error:
<ERROR> NEXT:[] PREV:[] <ERROR> NEXT:[] PREV:[]
sink: sink:
<SINK> NEXT:[] PREV:[<END>] <SINK> NEXT:[] PREV:[<END>]
===================== =====================
@@ -4,17 +4,18 @@ fun blockAndAndMismatch() : Boolean {
} }
--------------------- ---------------------
l0: l0:
<START> NEXT:[r(false)] PREV:[] <START> NEXT:[r(false)] PREV:[]
r(false) NEXT:[jt(l2)] PREV:[<START>] r(false) NEXT:[jt(l2)] PREV:[<START>]
jt(l2) NEXT:[r(false), r(false || (return false))] PREV:[r(false)] jt(l2) NEXT:[r((return false)), r(false || (return false))] PREV:[r(false)]
r(false) NEXT:[ret(*) l1] PREV:[jt(l2)] r((return false)) NEXT:[r(false)] PREV:[jt(l2)]
ret(*) l1 NEXT:[<END>] PREV:[r(false)] r(false) NEXT:[ret(*) l1] PREV:[r((return false))]
ret(*) l1 NEXT:[<END>] PREV:[r(false)]
l2: l2:
r(false || (return false)) NEXT:[<END>] PREV:[jt(l2)] r(false || (return false)) NEXT:[<END>] PREV:[jt(l2)]
l1: l1:
<END> NEXT:[<SINK>] PREV:[ret(*) l1, r(false || (return false))] <END> NEXT:[<SINK>] PREV:[ret(*) l1, r(false || (return false))]
error: error:
<ERROR> NEXT:[] PREV:[] <ERROR> NEXT:[] PREV:[]
sink: sink:
<SINK> NEXT:[] PREV:[<END>] <SINK> NEXT:[] PREV:[<END>]
===================== =====================
+4 -3
View File
@@ -1,6 +1,7 @@
import kotlin.modules.* import kotlin.modules.*
val modules = module("smoke") { fun project() {
source files "Smoke.kt" module("smoke") {
jar name System.getProperty("java.io.tmpdir") + "/smoke.jar" sources += "Smoke.kt"
}
} }
@@ -0,0 +1,35 @@
//KT-1001 Argument 2 for @NotNull parameter of JetFlowInformationProvider.checkIsInitialized must not be null
package kt1001
//+JDK
fun foo(<!UNUSED_PARAMETER!>c<!>: Array<Int>) {
return
<!UNREACHABLE_CODE!>for (i in c) {}<!>
<!UNREACHABLE_CODE!>for (i in c) {}<!>
}
//more tests
fun t1() : Int {
try {
return 1
}
catch (e : Exception) {
return 2
}
<!UNREACHABLE_CODE!>return 3<!>
}
fun t2() : Int {
try {
return 1
}
finally {
doSmth()
}
<!UNREACHABLE_CODE!>return 2<!>
}
fun doSmth() {}
@@ -0,0 +1,51 @@
//KT-1027 Strange selection of unreachable code
//+JDK
package kt1027
import java.util.List
fun foo(<!UNUSED_PARAMETER!>c<!>: List<Int>) {
var <!UNUSED_VARIABLE!>i<!> = 2
return
<!UNREACHABLE_CODE!>for (j in c) { //strange selection of unreachable code
i += 23
}<!>
}
fun t1() {
return
<!UNREACHABLE_CODE!>while(true) {
doSmth()
}<!>
}
fun t2() {
return
<!UNREACHABLE_CODE!>do {
doSmth()
} while (true)<!>
}
fun t3() {
return
<!UNREACHABLE_CODE!>try {
doSmth()
}
finally {
doSmth()
}<!>
}
fun t4() {
return
<!UNREACHABLE_CODE!>(43)<!>
}
fun doSmth() {}
@@ -0,0 +1,38 @@
//KT-776 Wrong detection of unreachable code
package kt776
fun test5() : Int {
var x = 0
while(true) {
try {
if(x < 10) {
x++
continue
}
else {
break
}
}
finally {
x++
}
}
return x
}
fun test1() : Int {
try {
if (true) {
return 1
}
else {
return 2
}
}
finally {
doSmth() //unreachable
}
}
fun doSmth() {}
@@ -128,7 +128,7 @@ public class JetControlFlowTest extends JetLiteFixture {
//check edges directions //check edges directions
Collection<Instruction> instructions = pseudocode.getMutableInstructionList(); Collection<Instruction> instructions = pseudocode.getMutableInstructionList();
for (Instruction instruction : instructions) { for (Instruction instruction : instructions) {
if (!instruction.isDead()) { if (!((InstructionImpl)instruction).isDead()) {
for (Instruction nextInstruction : instruction.getNextInstructions()) { for (Instruction nextInstruction : instruction.getNextInstructions()) {
assertTrue("instruction '" + instruction + "' has '" + nextInstruction + "' among next instructions list, but not vice versa", assertTrue("instruction '" + instruction + "' has '" + nextInstruction + "' among next instructions list, but not vice versa",
nextInstruction.getPreviousInstructions().contains(instruction)); nextInstruction.getPreviousInstructions().contains(instruction));
@@ -176,7 +176,7 @@ public class JetControlFlowTest extends JetLiteFixture {
private static String formatInstruction(Instruction instruction, int maxLength, Set<Instruction> remainedAfterPostProcessInstructions) { private static String formatInstruction(Instruction instruction, int maxLength, Set<Instruction> remainedAfterPostProcessInstructions) {
String[] parts = instruction.toString().split("\n"); String[] parts = instruction.toString().split("\n");
boolean isRemovedThroughPostProcess = !remainedAfterPostProcessInstructions.contains(instruction); boolean isRemovedThroughPostProcess = !remainedAfterPostProcessInstructions.contains(instruction);
String prefix = isRemovedThroughPostProcess ? "R " : instruction.isDead() ? "* " : " "; String prefix = isRemovedThroughPostProcess ? "- " : ((InstructionImpl)instruction).isDead() ? "* " : " ";
if (parts.length == 1) { if (parts.length == 1) {
return prefix + String.format("%1$-" + maxLength + "s", instruction); return prefix + String.format("%1$-" + maxLength + "s", instruction);
} }
@@ -1,7 +1,6 @@
package org.jetbrains.jet.compiler; package org.jetbrains.jet.compiler;
import jet.modules.IModuleBuilder; import jet.modules.Module;
import jet.modules.IModuleSetBuilder;
import junit.framework.TestCase; import junit.framework.TestCase;
import org.jetbrains.jet.cli.KotlinCompiler; import org.jetbrains.jet.cli.KotlinCompiler;
import org.jetbrains.jet.codegen.ClassFileFactory; import org.jetbrains.jet.codegen.ClassFileFactory;
@@ -37,9 +36,9 @@ public class CompileEnvironmentTest extends TestCase {
environment.setJavaRuntime(activeRtJar); environment.setJavaRuntime(activeRtJar);
environment.initializeKotlinRuntime(); environment.initializeKotlinRuntime();
final String testDataDir = JetParsingTest.getTestDataDir() + "/compiler/smoke/"; final String testDataDir = JetParsingTest.getTestDataDir() + "/compiler/smoke/";
final IModuleSetBuilder setBuilder = environment.loadModuleScript(testDataDir + "Smoke.kts"); final List<Module> modules = environment.loadModuleScript(testDataDir + "Smoke.kts");
assertEquals(1, setBuilder.getModules().size()); assertEquals(1, modules.size());
final IModuleBuilder moduleBuilder = setBuilder.getModules().get(0); final Module moduleBuilder = modules.get(0);
final ClassFileFactory factory = environment.compileModule(moduleBuilder, testDataDir); final ClassFileFactory factory = environment.compileModule(moduleBuilder, testDataDir);
assertNotNull(factory); assertNotNull(factory);
assertNotNull(factory.asBytes("Smoke/namespace.class")); assertNotNull(factory.asBytes("Smoke/namespace.class"));
@@ -51,7 +50,7 @@ public class CompileEnvironmentTest extends TestCase {
assertTrue(entries.contains("Smoke/namespace.class")); assertTrue(entries.contains("Smoke/namespace.class"));
} }
public void _testSmokeWithCompilerJar() throws IOException { public void testSmokeWithCompilerJar() throws IOException {
File tempFile = File.createTempFile("compilerTest", "compilerTest"); File tempFile = File.createTempFile("compilerTest", "compilerTest");
try { try {
KotlinCompiler.main(Arrays.asList("-module", JetParsingTest.getTestDataDir() + "/compiler/smoke/Smoke.kts", "-jar", tempFile.getAbsolutePath()).toArray(new String[0])); KotlinCompiler.main(Arrays.asList("-module", JetParsingTest.getTestDataDir() + "/compiler/smoke/Smoke.kts", "-jar", tempFile.getAbsolutePath()).toArray(new String[0]));
@@ -118,7 +118,8 @@ public class JetKeywordCompletionContributor extends CompletionContributor {
@Override @Override
public boolean isAcceptable(Object element, PsiElement context) { public boolean isAcceptable(Object element, PsiElement context) {
//noinspection unchecked //noinspection unchecked
return PsiTreeUtil.getParentOfType(context, JetClassBody.class, true, JetBlockExpression.class) != null; return PsiTreeUtil.getParentOfType(context, JetClassBody.class, true,
JetBlockExpression.class, JetProperty.class) != null;
} }
@Override @Override
@@ -0,0 +1,7 @@
class MouseMovedEventArgs
{
public val X : int = 0
in<caret>
}
// EXIST: internal
@@ -0,0 +1,6 @@
class MouseMovedEventArgs
{
public val X : int<caret> = 0
}
// ABSENT: internal
+8 -41
View File
@@ -3,57 +3,35 @@ package kotlin.modules
import java.util.* import java.util.*
import jet.modules.* import jet.modules.*
fun moduleSet(description: ModuleSetBuilder.() -> Unit) = description fun module(name: String, callback: ModuleBuilder.() -> Unit) {
val builder = ModuleBuilder(name)
fun module(name: String, description: ModuleBuilder.() -> Unit) = moduleSet { builder.callback()
module(name, description) AllModules.modules?.add(builder)
}
class ModuleSetBuilder(): IModuleSetBuilder {
private val modules = ArrayList<IModuleBuilder?>()
fun module(name: String, callback: ModuleBuilder.() -> Unit) {
val builder = ModuleBuilder(name)
builder.callback()
modules.add(builder)
}
override fun getModules(): List<IModuleBuilder?>? = modules
} }
class SourcesBuilder(val parent: ModuleBuilder) { class SourcesBuilder(val parent: ModuleBuilder) {
fun files(pattern: String) { fun plusAssign(pattern: String) {
parent.addSourceFiles(pattern) parent.addSourceFiles(pattern)
} }
} }
class ClasspathBuilder(val parent: ModuleBuilder) { class ClasspathBuilder(val parent: ModuleBuilder) {
fun entry(name: String) { fun plusAssign(name: String) {
parent.addClasspathEntry(name) parent.addClasspathEntry(name)
} }
} }
class JarBuilder(val parent: ModuleBuilder) { open class ModuleBuilder(val name: String): Module {
fun name(jarName: String) {
parent.setJarName(jarName)
}
}
open class ModuleBuilder(val name: String): IModuleBuilder {
// http://youtrack.jetbrains.net/issue/KT-904 // http://youtrack.jetbrains.net/issue/KT-904
private val sourceFiles0: ArrayList<String?> = ArrayList<String?>() private val sourceFiles0: ArrayList<String?> = ArrayList<String?>()
private val classpathRoots0: ArrayList<String?> = ArrayList<String?>() private val classpathRoots0: ArrayList<String?> = ArrayList<String?>()
var _jarName: String? = null
val source: SourcesBuilder val sources: SourcesBuilder
get() = SourcesBuilder(this) get() = SourcesBuilder(this)
val classpath: ClasspathBuilder val classpath: ClasspathBuilder
get() = ClasspathBuilder(this) get() = ClasspathBuilder(this)
val jar: JarBuilder
get() = JarBuilder(this)
fun addSourceFiles(pattern: String) { fun addSourceFiles(pattern: String) {
sourceFiles0.add(pattern) sourceFiles0.add(pattern)
} }
@@ -62,19 +40,8 @@ open class ModuleBuilder(val name: String): IModuleBuilder {
classpathRoots0.add(name) classpathRoots0.add(name)
} }
fun setJarName(name: String) {
_jarName = name
}
override fun getSourceFiles(): List<String?>? = sourceFiles0 override fun getSourceFiles(): List<String?>? = sourceFiles0
override fun getClasspathRoots(): List<String?>? = classpathRoots0 override fun getClasspathRoots(): List<String?>? = classpathRoots0
override fun getModuleName(): String? = name override fun getModuleName(): String? = name
override fun getJarName(): String? = _jarName
}
class ModuleBuilder2(name: String): ModuleBuilder(name) {
} }
+10
View File
@@ -0,0 +1,10 @@
/*
* @author max
*/
package jet.modules;
import java.util.ArrayList;
public class AllModules {
public static final ArrayList<Module> modules = new ArrayList<Module>();
}
@@ -1,10 +0,0 @@
package jet.modules;
import java.util.List;
/**
* @author yole
*/
public interface IModuleSetBuilder {
List<IModuleBuilder> getModules();
}
@@ -5,9 +5,8 @@ import java.util.List;
/** /**
* @author yole * @author yole
*/ */
public interface IModuleBuilder { public interface Module {
String getModuleName(); String getModuleName();
List<String> getSourceFiles(); List<String> getSourceFiles();
List<String> getClasspathRoots(); List<String> getClasspathRoots();
String getJarName();
} }