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_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;
final InstructionAdapter v;
@@ -60,7 +57,29 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
private final CodegenContext context;
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,
FrameMap myMap,
@@ -225,11 +244,10 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
@Override
public StackValue visitWhileExpression(JetWhileExpression expression, StackValue receiver) {
Label condition = new Label();
myContinueTargets.push(condition);
v.mark(condition);
Label end = continueLabel != null ? continueLabel : new Label();
myBreakTargets.push(end);
blockStackElements.push(new LoopBlockStackElement(end, condition));
Label savedContinueLabel = continueLabel;
continueLabel = condition;
@@ -243,8 +261,8 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
continueLabel = savedContinueLabel;
if(end != continueLabel)
v.mark(end);
myBreakTargets.pop();
myContinueTargets.pop();
blockStackElements.pop();
return StackValue.onStack(Type.VOID_TYPE);
}
@@ -253,10 +271,10 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
public StackValue visitDoWhileExpression(JetDoWhileExpression expression, StackValue receiver) {
Label condition = new Label();
v.mark(condition);
myContinueTargets.push(condition);
Label end = new Label();
myBreakTargets.push(end);
blockStackElements.push(new LoopBlockStackElement(end, condition));
gen(expression.getBody(), Type.VOID_TYPE);
@@ -265,8 +283,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
v.mark(end);
myBreakTargets.pop();
myContinueTargets.pop();
blockStackElements.pop();
return StackValue.onStack(Type.VOID_TYPE);
}
@@ -328,8 +345,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
}
Label begin = new Label();
myContinueTargets.push(begin);
myBreakTargets.push(end);
blockStackElements.push(new LoopBlockStackElement(end, begin));
v.mark(begin);
v.load(iteratorVar, asmIterType);
@@ -365,8 +381,8 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
//noinspection ConstantConditions
v.visitLocalVariable(loopParameter.getName(), asmParamType.getDescriptor(), null, begin, end, paramIndex);
myFrameMap.leaveTemp();
myBreakTargets.pop();
myContinueTargets.pop();
blockStackElements.pop();
}
private OwnerKind contextKind() {
@@ -398,8 +414,8 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
Label condition = new Label();
Label increment = new Label();
v.mark(condition);
myContinueTargets.push(increment);
myBreakTargets.push(end);
blockStackElements.push(new LoopBlockStackElement(end, increment));
generateCondition(asmParamType, end);
@@ -414,8 +430,8 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
final int paramIndex = myFrameMap.leave(parameterDescriptor);
//noinspection ConstantConditions
v.visitLocalVariable(expression.getLoopParameter().getName(), asmParamType.getDescriptor(), null, condition, end, paramIndex);
myBreakTargets.pop();
myContinueTargets.pop();
blockStackElements.pop();
}
protected void generatePrologue() {
@@ -536,21 +552,51 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
@Override
public StackValue visitBreakExpression(JetBreakExpression expression, StackValue receiver) {
JetSimpleNameExpression labelElement = expression.getTargetLabel();
Label label = labelElement == null ? myBreakTargets.peek() : null; // TODO:
v.goTo(label);
return StackValue.none();
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.breakLabel : null; // TODO:
v.goTo(label);
return StackValue.none();
}
else {
throw new UnsupportedOperationException();
}
}
throw new UnsupportedOperationException();
}
@Override
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);
return StackValue.none();
throw new UnsupportedOperationException();
}
private StackValue generateSingleBranchIf(StackValue condition, JetExpression expression, boolean inverse) {
@@ -763,12 +809,18 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
}
private void doFinallyOnReturnOrThrow() {
if(stackOfFinallyBlocks.size() > 0) {
JetTryExpression jetTryExpression = stackOfFinallyBlocks.remove(stackOfFinallyBlocks.size()-1);
//noinspection ConstantConditions
gen(jetTryExpression.getFinallyBlock().getFinalExpression(), Type.VOID_TYPE);
doFinallyOnReturnOrThrow();
stackOfFinallyBlocks.add(jetTryExpression);
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;
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.
*/
Label savedContinueLabel = continueLabel;
continueLabel = null;
JetFinallySection finallyBlock = expression.getFinallyBlock();
if(finallyBlock != null) {
stackOfFinallyBlocks.add(expression);
blockStackElements.push(new FinallyBlockStackElement(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();
if(finallyBlock != null) {
stackOfFinallyBlocks.remove(stackOfFinallyBlocks.size()-1);
blockStackElements.pop();
}
continueLabel = savedContinueLabel;
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 {
if(test1()) return "test1 failed"
if(test2()) return "test2 failed"
if(test3() != 2) return "test3 failed"
System.out?.println(test4())
if(test4() != 3) return "test4 failed"
if(test5() != 11) return "test5 failed"
if(test6() != 10) return "test6 failed"
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
}
}