LockPerf benchmark and related fixes (try/break/continue interoperability)

This commit is contained in:
Alex Tkachman
2011-12-08 11:18:27 +02:00
parent 0656f1f0e0
commit b89956f1fd
4 changed files with 228 additions and 37 deletions
@@ -43,9 +43,6 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
private static final String CLASS_NO_PATTERN_MATCHED_EXCEPTION = "jet/NoPatternMatchedException"; private static final String CLASS_NO_PATTERN_MATCHED_EXCEPTION = "jet/NoPatternMatchedException";
private static final String CLASS_TYPE_CAST_EXCEPTION = "jet/TypeCastException"; private static final String CLASS_TYPE_CAST_EXCEPTION = "jet/TypeCastException";
private final Stack<Label> myContinueTargets = new Stack<Label>();
private final Stack<Label> myBreakTargets = new Stack<Label>();
private int myLastLineNumber = -1; private int myLastLineNumber = -1;
final InstructionAdapter v; final InstructionAdapter v;
@@ -60,7 +57,29 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
private final CodegenContext context; private final CodegenContext context;
private final IntrinsicMethods intrinsics; private final IntrinsicMethods intrinsics;
private final ArrayList<JetTryExpression> stackOfFinallyBlocks = new ArrayList<JetTryExpression>(); private final Stack<BlockStackElement> blockStackElements = new Stack<BlockStackElement>();
static class BlockStackElement {
}
static class LoopBlockStackElement extends BlockStackElement {
final Label continueLabel;
final Label breakLabel;
LoopBlockStackElement(Label breakLabel, Label continueLabel) {
this.breakLabel = breakLabel;
this.continueLabel = continueLabel;
}
}
static class FinallyBlockStackElement extends BlockStackElement {
final JetTryExpression expression;
FinallyBlockStackElement(JetTryExpression expression) {
this.expression = expression;
}
}
public ExpressionCodegen(MethodVisitor v, public ExpressionCodegen(MethodVisitor v,
FrameMap myMap, FrameMap myMap,
@@ -225,11 +244,10 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
@Override @Override
public StackValue visitWhileExpression(JetWhileExpression expression, StackValue receiver) { public StackValue visitWhileExpression(JetWhileExpression expression, StackValue receiver) {
Label condition = new Label(); Label condition = new Label();
myContinueTargets.push(condition);
v.mark(condition); v.mark(condition);
Label end = continueLabel != null ? continueLabel : new Label(); Label end = continueLabel != null ? continueLabel : new Label();
myBreakTargets.push(end); blockStackElements.push(new LoopBlockStackElement(end, condition));
Label savedContinueLabel = continueLabel; Label savedContinueLabel = continueLabel;
continueLabel = condition; continueLabel = condition;
@@ -243,8 +261,8 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
continueLabel = savedContinueLabel; continueLabel = savedContinueLabel;
if(end != continueLabel) if(end != continueLabel)
v.mark(end); v.mark(end);
myBreakTargets.pop();
myContinueTargets.pop(); blockStackElements.pop();
return StackValue.onStack(Type.VOID_TYPE); return StackValue.onStack(Type.VOID_TYPE);
} }
@@ -253,10 +271,10 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
public StackValue visitDoWhileExpression(JetDoWhileExpression expression, StackValue receiver) { public StackValue visitDoWhileExpression(JetDoWhileExpression expression, StackValue receiver) {
Label condition = new Label(); Label condition = new Label();
v.mark(condition); v.mark(condition);
myContinueTargets.push(condition);
Label end = new Label(); Label end = new Label();
myBreakTargets.push(end);
blockStackElements.push(new LoopBlockStackElement(end, condition));
gen(expression.getBody(), Type.VOID_TYPE); gen(expression.getBody(), Type.VOID_TYPE);
@@ -265,8 +283,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
v.mark(end); v.mark(end);
myBreakTargets.pop(); blockStackElements.pop();
myContinueTargets.pop();
return StackValue.onStack(Type.VOID_TYPE); return StackValue.onStack(Type.VOID_TYPE);
} }
@@ -328,8 +345,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
} }
Label begin = new Label(); Label begin = new Label();
myContinueTargets.push(begin); blockStackElements.push(new LoopBlockStackElement(end, begin));
myBreakTargets.push(end);
v.mark(begin); v.mark(begin);
v.load(iteratorVar, asmIterType); v.load(iteratorVar, asmIterType);
@@ -365,8 +381,8 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
//noinspection ConstantConditions //noinspection ConstantConditions
v.visitLocalVariable(loopParameter.getName(), asmParamType.getDescriptor(), null, begin, end, paramIndex); v.visitLocalVariable(loopParameter.getName(), asmParamType.getDescriptor(), null, begin, end, paramIndex);
myFrameMap.leaveTemp(); myFrameMap.leaveTemp();
myBreakTargets.pop();
myContinueTargets.pop(); blockStackElements.pop();
} }
private OwnerKind contextKind() { private OwnerKind contextKind() {
@@ -398,8 +414,8 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
Label condition = new Label(); Label condition = new Label();
Label increment = new Label(); Label increment = new Label();
v.mark(condition); v.mark(condition);
myContinueTargets.push(increment);
myBreakTargets.push(end); blockStackElements.push(new LoopBlockStackElement(end, increment));
generateCondition(asmParamType, end); generateCondition(asmParamType, end);
@@ -414,8 +430,8 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
final int paramIndex = myFrameMap.leave(parameterDescriptor); final int paramIndex = myFrameMap.leave(parameterDescriptor);
//noinspection ConstantConditions //noinspection ConstantConditions
v.visitLocalVariable(expression.getLoopParameter().getName(), asmParamType.getDescriptor(), null, condition, end, paramIndex); v.visitLocalVariable(expression.getLoopParameter().getName(), asmParamType.getDescriptor(), null, condition, end, paramIndex);
myBreakTargets.pop();
myContinueTargets.pop(); blockStackElements.pop();
} }
protected void generatePrologue() { protected void generatePrologue() {
@@ -536,21 +552,51 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
@Override @Override
public StackValue visitBreakExpression(JetBreakExpression expression, StackValue receiver) { public StackValue visitBreakExpression(JetBreakExpression expression, StackValue receiver) {
JetSimpleNameExpression labelElement = expression.getTargetLabel(); JetSimpleNameExpression labelElement = expression.getTargetLabel();
Label label = labelElement == null ? myBreakTargets.peek() : null; // TODO: for(int i = blockStackElements.size()-1; i >= 0; --i) {
BlockStackElement stackElement = blockStackElements.get(i);
v.goTo(label); if(stackElement instanceof FinallyBlockStackElement) {
return StackValue.none(); FinallyBlockStackElement finallyBlockStackElement = (FinallyBlockStackElement) stackElement;
JetTryExpression jetTryExpression = finallyBlockStackElement.expression;
gen(jetTryExpression.getFinallyBlock().getFinalExpression(), Type.VOID_TYPE);
}
else if(stackElement instanceof LoopBlockStackElement) {
LoopBlockStackElement loopBlockStackElement = (LoopBlockStackElement) stackElement;
Label label = labelElement == null ? loopBlockStackElement.breakLabel : null; // TODO:
v.goTo(label);
return StackValue.none();
}
else {
throw new UnsupportedOperationException();
}
}
throw new UnsupportedOperationException();
} }
@Override @Override
public StackValue visitContinueExpression(JetContinueExpression expression, StackValue receiver) { public StackValue visitContinueExpression(JetContinueExpression expression, StackValue receiver) {
String labelName = expression.getLabelName(); JetSimpleNameExpression labelElement = expression.getTargetLabel();
Label label = labelName == null ? myContinueTargets.peek() : null; // TODO: for(int i = blockStackElements.size()-1; i >= 0; --i) {
BlockStackElement stackElement = blockStackElements.get(i);
if(stackElement instanceof FinallyBlockStackElement) {
FinallyBlockStackElement finallyBlockStackElement = (FinallyBlockStackElement) stackElement;
JetTryExpression jetTryExpression = finallyBlockStackElement.expression;
gen(jetTryExpression.getFinallyBlock().getFinalExpression(), Type.VOID_TYPE);
}
else if(stackElement instanceof LoopBlockStackElement) {
LoopBlockStackElement loopBlockStackElement = (LoopBlockStackElement) stackElement;
Label label = labelElement == null ? loopBlockStackElement.continueLabel : null; // TODO:
v.goTo(label);
return StackValue.none();
}
else {
throw new UnsupportedOperationException();
}
}
v.goTo(label); throw new UnsupportedOperationException();
return StackValue.none();
} }
private StackValue generateSingleBranchIf(StackValue condition, JetExpression expression, boolean inverse) { private StackValue generateSingleBranchIf(StackValue condition, JetExpression expression, boolean inverse) {
@@ -763,12 +809,18 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
} }
private void doFinallyOnReturnOrThrow() { private void doFinallyOnReturnOrThrow() {
if(stackOfFinallyBlocks.size() > 0) { for(int i = blockStackElements.size()-1; i >= 0; --i) {
JetTryExpression jetTryExpression = stackOfFinallyBlocks.remove(stackOfFinallyBlocks.size()-1); BlockStackElement stackElement = blockStackElements.get(i);
//noinspection ConstantConditions if(stackElement instanceof FinallyBlockStackElement) {
gen(jetTryExpression.getFinallyBlock().getFinalExpression(), Type.VOID_TYPE); FinallyBlockStackElement finallyBlockStackElement = (FinallyBlockStackElement) stackElement;
doFinallyOnReturnOrThrow(); JetTryExpression jetTryExpression = finallyBlockStackElement.expression;
stackOfFinallyBlocks.add(jetTryExpression); blockStackElements.pop();
gen(jetTryExpression.getFinallyBlock().getFinalExpression(), Type.VOID_TYPE);
blockStackElements.push(finallyBlockStackElement);
}
else {
break;
}
} }
} }
@@ -2208,9 +2260,12 @@ The "returned" value of try expression with no finally is either the last expres
If finally block is present, its last expression is the value of try expression. If finally block is present, its last expression is the value of try expression.
*/ */
Label savedContinueLabel = continueLabel;
continueLabel = null;
JetFinallySection finallyBlock = expression.getFinallyBlock(); JetFinallySection finallyBlock = expression.getFinallyBlock();
if(finallyBlock != null) { if(finallyBlock != null) {
stackOfFinallyBlocks.add(expression); blockStackElements.push(new FinallyBlockStackElement(expression));
} }
JetType jetType = bindingContext.get(BindingContext.EXPRESSION_TYPE, expression); JetType jetType = bindingContext.get(BindingContext.EXPRESSION_TYPE, expression);
@@ -2267,9 +2322,11 @@ If finally block is present, its last expression is the value of try expression.
v.nop(); v.nop();
if(finallyBlock != null) { if(finallyBlock != null) {
stackOfFinallyBlocks.remove(stackOfFinallyBlocks.size()-1); blockStackElements.pop();
} }
continueLabel = savedContinueLabel;
return StackValue.onStack(expectedAsmType); return StackValue.onStack(expectedAsmType);
} }
@@ -41,12 +41,48 @@ fun test4() : Int {
} }
} }
fun test5() : Int {
var x = 0
System.out?.println("test 5")
while(true) {
System.out?.println(x)
try {
if(x < 10)
x++
else
break
}
finally {
x++
}
}
return x
}
fun test6() : Int {
var x = 0
System.out?.println("test 6")
while(x < 10) {
System.out?.println(x)
try {
x++
continue
}
finally {
x++
}
}
return x
}
fun box() : String { fun box() : String {
if(test1()) return "test1 failed" if(test1()) return "test1 failed"
if(test2()) return "test2 failed" if(test2()) return "test2 failed"
if(test3() != 2) return "test3 failed" if(test3() != 2) return "test3 failed"
System.out?.println(test4()) System.out?.println(test4())
if(test4() != 3) return "test4 failed" if(test4() != 3) return "test4 failed"
if(test5() != 11) return "test5 failed"
if(test6() != 10) return "test6 failed"
return "OK" return "OK"
} }
+43
View File
@@ -0,0 +1,43 @@
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.locks.ReentrantLock;
public class LockPerf {
public static void main(String[] args) {
int processors = Runtime.getRuntime().availableProcessors();
for (int threadNum = 1; threadNum <= 1024; threadNum = threadNum < 2 * processors ? threadNum + 1 : threadNum * 2) {
final AtomicInteger counter = new AtomicInteger();
final CountDownLatch cdl = new CountDownLatch(threadNum);
final ReentrantLock lock = new ReentrantLock();
long start = System.currentTimeMillis();
for (int i = 0; i < threadNum; ++i) {
new Thread(new Runnable() {
public void run() {
for (;;) {
lock.lock();
try {
if (counter.get() == 100000000) {
cdl.countDown();
break;
} else {
counter.incrementAndGet();
}
} finally {
lock.unlock();
}
}
}
}).start();
}
try {
cdl.await();
} catch (InterruptedException e) {//
}
System.out.println(threadNum + " " + (System.currentTimeMillis() - start));
}
}
}
+55
View File
@@ -0,0 +1,55 @@
namespace lockperformance
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.locks.ReentrantLock;
fun thread(f: fun ()) {
val thread = Thread(
object: Runnable {
override fun run() {
f()
}
}
)
thread.start()
}
fun main(args: Array<String>) {
val processors = Runtime.getRuntime().sure().availableProcessors()
var threadNum = 1
while(threadNum <= 1024) {
val counter = AtomicInteger()
val cdl = CountDownLatch(threadNum)
val lock = ReentrantLock()
val start = System.currentTimeMillis()
for(i in 0..threadNum-1) {
thread {
while(true) {
lock.lock()
try {
if (counter.get() == 100000000) {
cdl.countDown();
break;
} else {
counter.incrementAndGet();
}
}
finally {
lock.unlock()
}
}
}
}
cdl.await()
System.out?.println(threadNum.toString() + " " + (System.currentTimeMillis() - start));
if(threadNum < 2 * processors)
threadNum = threadNum + 1
else
threadNum = threadNum * 2
}
}