thread ring benchmark and related bug fixes (non null array creation and wrong signature of enclosing class)
This commit is contained in:
@@ -10,7 +10,6 @@ import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.JetDeclarationWithBody;
|
||||
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||
import org.jetbrains.jet.lang.psi.JetFunctionLiteral;
|
||||
import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||
@@ -100,7 +99,7 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
|
||||
generateBridge(name, funDescriptor, fun, cv);
|
||||
captureThis = generateBody(funDescriptor, cv, fun.getFunctionLiteral());
|
||||
ClassDescriptor thisDescriptor = context.getThisDescriptor();
|
||||
final Type enclosingType = thisDescriptor == null ? null : Type.getObjectType(thisDescriptor.getName());
|
||||
final Type enclosingType = thisDescriptor == null ? null : state.getTypeMapper().mapType(thisDescriptor.getDefaultType());
|
||||
if (enclosingType == null)
|
||||
captureThis = false;
|
||||
|
||||
@@ -164,7 +163,7 @@ public class ClosureCodegen extends ObjectOrClosureCodegen {
|
||||
Collections.<TypeParameterDescriptor>emptyList(),
|
||||
Collections.singleton((funDescriptor.getReceiverParameter().exists() ? JetStandardClasses.getReceiverFunction(arity) : JetStandardClasses.getFunction(arity)).getDefaultType()), JetScope.EMPTY, Collections.<ConstructorDescriptor>emptySet(), null);
|
||||
|
||||
final CodegenContext.ClosureContext closureContext = context.intoClosure(funDescriptor, function, name, this);
|
||||
final CodegenContext.ClosureContext closureContext = context.intoClosure(funDescriptor, function, name, this, state.getTypeMapper());
|
||||
FunctionCodegen fc = new FunctionCodegen(closureContext, cv, state);
|
||||
fc.generateMethod(body, invokeSignature(funDescriptor), funDescriptor);
|
||||
return closureContext.outerWasUsed;
|
||||
|
||||
@@ -104,24 +104,24 @@ public abstract class CodegenContext {
|
||||
return new ClassContext(descriptor, kind, this, typeMapper);
|
||||
}
|
||||
|
||||
public CodegenContext intoAnonymousClass(@NotNull ObjectOrClosureCodegen closure, ClassDescriptor descriptor, OwnerKind kind) {
|
||||
return new AnonymousClassContext(descriptor, kind, this, closure);
|
||||
public CodegenContext intoAnonymousClass(@NotNull ObjectOrClosureCodegen closure, ClassDescriptor descriptor, OwnerKind kind, JetTypeMapper typeMapper) {
|
||||
return new AnonymousClassContext(descriptor, kind, this, closure, typeMapper);
|
||||
}
|
||||
|
||||
public MethodContext intoFunction(FunctionDescriptor descriptor) {
|
||||
return new MethodContext(descriptor, getContextKind(), this);
|
||||
}
|
||||
|
||||
public ConstructorContext intoConstructor(ConstructorDescriptor descriptor) {
|
||||
public ConstructorContext intoConstructor(ConstructorDescriptor descriptor, JetTypeMapper typeMapper) {
|
||||
if(descriptor == null) {
|
||||
descriptor = new ConstructorDescriptorImpl(getThisDescriptor(), Collections.<AnnotationDescriptor>emptyList(), true)
|
||||
.initialize(Collections.<TypeParameterDescriptor>emptyList(), Collections.<ValueParameterDescriptor>emptyList(), Modality.OPEN, Visibility.PUBLIC);
|
||||
}
|
||||
return new ConstructorContext(descriptor, getContextKind(), this);
|
||||
return new ConstructorContext(descriptor, getContextKind(), this, typeMapper);
|
||||
}
|
||||
|
||||
public ClosureContext intoClosure(FunctionDescriptor funDescriptor, ClassDescriptor classDescriptor, String internalClassName, ClosureCodegen closureCodegen) {
|
||||
return new ClosureContext(funDescriptor, classDescriptor, this, closureCodegen, internalClassName);
|
||||
public ClosureContext intoClosure(FunctionDescriptor funDescriptor, ClassDescriptor classDescriptor, String internalClassName, ClosureCodegen closureCodegen, JetTypeMapper typeMapper) {
|
||||
return new ClosureContext(funDescriptor, classDescriptor, this, closureCodegen, internalClassName, typeMapper);
|
||||
}
|
||||
|
||||
public FrameMap prepareFrame(JetTypeMapper mapper) {
|
||||
@@ -170,12 +170,12 @@ public abstract class CodegenContext {
|
||||
return parentContext != null ? parentContext.lookupInContext(d, v, result) : null;
|
||||
}
|
||||
|
||||
public Type enclosingClassType() {
|
||||
public Type enclosingClassType(JetTypeMapper typeMapper) {
|
||||
CodegenContext cur = getParentContext();
|
||||
while(cur != null && !(cur.getContextDescriptor() instanceof ClassDescriptor))
|
||||
cur = cur.getParentContext();
|
||||
|
||||
return cur == null ? null : Type.getObjectType(cur.getContextDescriptor().getName());
|
||||
return cur == null ? null : typeMapper.mapType(((ClassDescriptor)cur.getContextDescriptor()).getDefaultType());
|
||||
}
|
||||
|
||||
public int getTypeInfoConstantIndex(JetType type) {
|
||||
@@ -290,8 +290,8 @@ public abstract class CodegenContext {
|
||||
return getParentContext().lookupInContext(d, v, result);
|
||||
}
|
||||
|
||||
public Type enclosingClassType() {
|
||||
return getParentContext().enclosingClassType();
|
||||
public Type enclosingClassType(JetTypeMapper typeMapper) {
|
||||
return getParentContext().enclosingClassType(typeMapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -305,10 +305,10 @@ public abstract class CodegenContext {
|
||||
}
|
||||
|
||||
public static class ConstructorContext extends MethodContext {
|
||||
public ConstructorContext(ConstructorDescriptor contextType, OwnerKind kind, CodegenContext parent) {
|
||||
public ConstructorContext(ConstructorDescriptor contextType, OwnerKind kind, CodegenContext parent, JetTypeMapper typeMapper) {
|
||||
super(contextType, kind, parent);
|
||||
|
||||
final Type type = enclosingClassType();
|
||||
final Type type = enclosingClassType(typeMapper);
|
||||
outerExpression = type != null
|
||||
? local1
|
||||
: null;
|
||||
@@ -323,7 +323,7 @@ public abstract class CodegenContext {
|
||||
public ClassContext(ClassDescriptor contextType, OwnerKind contextKind, CodegenContext parentContext, JetTypeMapper typeMapper) {
|
||||
super(contextType, contextKind, parentContext, null);
|
||||
|
||||
final Type type = enclosingClassType();
|
||||
final Type type = enclosingClassType(typeMapper);
|
||||
outerExpression = type != null
|
||||
? StackValue.field(type, typeMapper.getFQName(contextType), "this$0", false)
|
||||
: null;
|
||||
@@ -341,10 +341,10 @@ public abstract class CodegenContext {
|
||||
}
|
||||
|
||||
public static class AnonymousClassContext extends CodegenContext {
|
||||
public AnonymousClassContext(ClassDescriptor contextType, OwnerKind contextKind, CodegenContext parentContext, @NotNull ObjectOrClosureCodegen closure) {
|
||||
public AnonymousClassContext(ClassDescriptor contextType, OwnerKind contextKind, CodegenContext parentContext, @NotNull ObjectOrClosureCodegen closure, JetTypeMapper typeMapper) {
|
||||
super(contextType, contextKind, parentContext, closure);
|
||||
|
||||
final Type type = enclosingClassType();
|
||||
final Type type = enclosingClassType(typeMapper);
|
||||
outerExpression = type != null
|
||||
? StackValue.field(type, closure.state.getTypeMapper().mapType(contextType.getDefaultType(), OwnerKind.IMPLEMENTATION).getInternalName(), "this$0", false)
|
||||
: null;
|
||||
@@ -364,11 +364,11 @@ public abstract class CodegenContext {
|
||||
public static class ClosureContext extends ReceiverContext {
|
||||
private ClassDescriptor classDescriptor;
|
||||
|
||||
public ClosureContext(FunctionDescriptor contextType, ClassDescriptor classDescriptor, CodegenContext parentContext, @NotNull ObjectOrClosureCodegen closureCodegen, String internalClassName) {
|
||||
public ClosureContext(FunctionDescriptor contextType, ClassDescriptor classDescriptor, CodegenContext parentContext, @NotNull ObjectOrClosureCodegen closureCodegen, String internalClassName, JetTypeMapper typeMapper) {
|
||||
super(contextType, OwnerKind.IMPLEMENTATION, parentContext, closureCodegen);
|
||||
this.classDescriptor = classDescriptor;
|
||||
|
||||
final Type type = enclosingClassType();
|
||||
final Type type = enclosingClassType(typeMapper);
|
||||
outerExpression = type != null
|
||||
? StackValue.field(type, internalClassName, "this$0", false)
|
||||
: null;
|
||||
|
||||
@@ -1958,26 +1958,13 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
} else {
|
||||
ClassDescriptor classDecl = (ClassDescriptor) constructorDescriptor.getContainingDeclaration();
|
||||
|
||||
receiver.put(receiver.type, v);
|
||||
v.anew(type);
|
||||
v.dup();
|
||||
|
||||
// TODO typechecker must verify that we're the outer class of the instance being created
|
||||
//noinspection ConstantConditions
|
||||
if (classDecl.getContainingDeclaration() instanceof ClassDescriptor) {
|
||||
if(!receiver.type.equals(Type.VOID_TYPE)) {
|
||||
// class object is in receiver
|
||||
v.dupX1();
|
||||
v.swap();
|
||||
}
|
||||
else {
|
||||
// this$0 need to be put on stack
|
||||
v.dup();
|
||||
v.load(0, typeMapper.mapType(classDecl.getDefaultType(), OwnerKind.IMPLEMENTATION));
|
||||
}
|
||||
}
|
||||
else {
|
||||
// regular case
|
||||
v.dup();
|
||||
if(!receiver.type.equals(Type.VOID_TYPE)) {
|
||||
receiver.put(receiver.type, v);
|
||||
}
|
||||
|
||||
CallableMethod method = typeMapper.mapToCallableMethod((ConstructorDescriptor) constructorDescriptor, OwnerKind.IMPLEMENTATION);
|
||||
|
||||
@@ -140,7 +140,7 @@ public class GenerationState {
|
||||
|
||||
closure.cv = nameAndVisitor.getSecond();
|
||||
closure.name = nameAndVisitor.getFirst();
|
||||
final CodegenContext objectContext = closure.context.intoAnonymousClass(closure, getBindingContext().get(BindingContext.CLASS, objectDeclaration), OwnerKind.IMPLEMENTATION);
|
||||
final CodegenContext objectContext = closure.context.intoAnonymousClass(closure, getBindingContext().get(BindingContext.CLASS, objectDeclaration), OwnerKind.IMPLEMENTATION, typeMapper);
|
||||
|
||||
new ImplementationBodyCodegen(objectDeclaration, objectContext, nameAndVisitor.getSecond(), this).generate(null);
|
||||
|
||||
|
||||
@@ -267,7 +267,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
|
||||
ConstructorDescriptor constructorDescriptor = bindingContext.get(BindingContext.CONSTRUCTOR, myClass);
|
||||
|
||||
CodegenContext.ConstructorContext constructorContext = context.intoConstructor(constructorDescriptor);
|
||||
CodegenContext.ConstructorContext constructorContext = context.intoConstructor(constructorDescriptor, typeMapper);
|
||||
|
||||
Method constructorMethod;
|
||||
CallableMethod callableMethod;
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
class A() {
|
||||
class B(val i: Int) {
|
||||
}
|
||||
|
||||
fun test() = Array<B> (10, { B(it) })
|
||||
}
|
||||
|
||||
fun box() = if(A().test()[5].i == 5) "OK" else "fail"
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace org2
|
||||
|
||||
enum class Test {
|
||||
A
|
||||
B
|
||||
C
|
||||
}
|
||||
|
||||
fun box() = Test.A.toString()
|
||||
@@ -286,4 +286,9 @@ public class ArrayGenTest extends CodegenTestCase {
|
||||
// System.out.println(generateToText());
|
||||
blackBox();
|
||||
}
|
||||
|
||||
public void testNonNullArray() throws Exception {
|
||||
blackBoxFile("classes/nonnullarray.jet");
|
||||
System.out.println(generateToText());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package org.jetbrains.jet.codegen;
|
||||
|
||||
import org.jetbrains.jet.lang.psi.JetNamespace;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
@@ -216,6 +218,10 @@ public class ClassGenTest extends CodegenTestCase {
|
||||
blackBoxFile("regressions/kt500.jet");
|
||||
}
|
||||
|
||||
public void testKt694 () throws Exception {
|
||||
blackBoxFile("regressions/kt694.jet");
|
||||
}
|
||||
|
||||
public void testKt285 () throws Exception {
|
||||
// blackBoxFile("regressions/kt285.jet");
|
||||
}
|
||||
|
||||
@@ -0,0 +1,137 @@
|
||||
/**
|
||||
* The Computer Language Benchmarks Game
|
||||
* http://shootout.alioth.debian.org/
|
||||
*
|
||||
* contributed by Fabien Le Floc'h
|
||||
*
|
||||
* Java implementation of thread-ring benchmark. Best performance is achieved with
|
||||
* MAX_THREAD=1 as the thread-ring test is bested with only 1 os thread.
|
||||
* This implementation shows using a simple thread pool solves the thread context
|
||||
* switch issue.
|
||||
*/
|
||||
|
||||
import java.util.concurrent.*;
|
||||
|
||||
public class ThreadRing {
|
||||
private static final int MAX_NODES = 503;
|
||||
private static final int MAX_THREADS = 503;
|
||||
|
||||
private ExecutorService executor;
|
||||
private final int N;
|
||||
|
||||
static final CountDownLatch cdl = new CountDownLatch(1);
|
||||
|
||||
public static void main(String[] args) throws InterruptedException {
|
||||
long start = System.currentTimeMillis();
|
||||
int n = 5000000;
|
||||
try {
|
||||
n = Integer.parseInt(args[0]);
|
||||
} catch (Exception e) {}
|
||||
ThreadRing ring = new ThreadRing(n);
|
||||
Node node = ring.start(MAX_NODES);
|
||||
node.sendMessage(new TokenMessage(1,0));
|
||||
cdl.await();
|
||||
|
||||
long total = System.currentTimeMillis() - start;
|
||||
System.out.println("[ThreadRing-" + System.getProperty("project.name")+ " Benchmark Result: " + total + "]");
|
||||
}
|
||||
|
||||
public ThreadRing(int n) {
|
||||
N = n;
|
||||
}
|
||||
|
||||
public Node start(int n) {
|
||||
Node[] nodes = spawnNodes(n);
|
||||
connectNodes(n, nodes);
|
||||
return nodes[0];
|
||||
}
|
||||
|
||||
private Node[] spawnNodes(int n) {
|
||||
executor = Executors.newFixedThreadPool(MAX_THREADS);
|
||||
Node[] nodes = new Node[n+1];
|
||||
for (int i = 0; i < n ; i++) {
|
||||
nodes[i] = new Node(i+1, null);
|
||||
}
|
||||
return nodes;
|
||||
}
|
||||
|
||||
public void connectNodes(int n, Node[] nodes) {
|
||||
nodes[n] = nodes[0];
|
||||
for (int i=0; i<n; i++) {
|
||||
nodes[i].connect(nodes[i+1]);
|
||||
}
|
||||
}
|
||||
|
||||
private static class TokenMessage {
|
||||
private int nodeId;
|
||||
private volatile int value;
|
||||
private boolean isStop;
|
||||
|
||||
public TokenMessage(int nodeId, int value) {
|
||||
this.nodeId = nodeId;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public TokenMessage(int nodeId, int value, boolean isStop) {
|
||||
this.nodeId = nodeId;
|
||||
this.value = value;
|
||||
this.isStop = isStop;
|
||||
}
|
||||
}
|
||||
|
||||
private class Node implements Runnable {
|
||||
private int nodeId;
|
||||
private Node nextNode;
|
||||
private BlockingQueue<TokenMessage> queue = new LinkedBlockingQueue<TokenMessage>();
|
||||
private boolean isActive = false;
|
||||
private int counter;
|
||||
|
||||
public Node(int id, Node nextNode) {
|
||||
this.nodeId = id;
|
||||
this.nextNode = nextNode;
|
||||
this.counter = 0;
|
||||
}
|
||||
|
||||
public void connect(Node node) {
|
||||
this.nextNode = node;
|
||||
isActive = true;
|
||||
}
|
||||
|
||||
public void sendMessage(TokenMessage m) {
|
||||
queue.add(m);
|
||||
executor.execute(this);
|
||||
}
|
||||
|
||||
|
||||
public void run() {
|
||||
if (isActive) {
|
||||
try {
|
||||
TokenMessage m = queue.take();
|
||||
if (m.isStop) {
|
||||
int nextValue = m.value+1;
|
||||
if (nextValue == MAX_NODES) {
|
||||
// System.out.println("last one");
|
||||
executor.shutdown();
|
||||
cdl.countDown();
|
||||
} else {
|
||||
m.value = nextValue;
|
||||
nextNode.sendMessage(m);
|
||||
}
|
||||
isActive = false;
|
||||
// System.out.println("ending node "+nodeId);
|
||||
} else {
|
||||
if (m.value == N) {
|
||||
System.out.println(nodeId);
|
||||
nextNode.sendMessage(new TokenMessage(nodeId, 0, true));
|
||||
} else {
|
||||
m.value = m.value + 1;
|
||||
nextNode.sendMessage(m);
|
||||
}
|
||||
}
|
||||
} catch (InterruptedException ie) {
|
||||
ie.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
namespace threadring
|
||||
|
||||
import java.util.concurrent.*;
|
||||
import java.util.concurrent.atomic.*;
|
||||
|
||||
val MAX_NODES = 503
|
||||
val MAX_THREADS = 503
|
||||
|
||||
val cdl = CountDownLatch(1)
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
val start = System.currentTimeMillis()
|
||||
var n = 5000000;
|
||||
try {
|
||||
n = Integer.parseInt(args[0]);
|
||||
} catch (e: Throwable) {
|
||||
}
|
||||
|
||||
val ring = ThreadRing(n)
|
||||
ring.sendMessage(TokenMessage(1,0,false))
|
||||
cdl.await();
|
||||
|
||||
val total = System.currentTimeMillis() - start
|
||||
System.out?.println("[ThreadRing-" + System.getProperty("project.name")+ " Benchmark Result: " + total + "]")
|
||||
}
|
||||
|
||||
class TokenMessage(val nodeId : Int, value: Int, val isStop: Boolean) : AtomicInteger(value){
|
||||
}
|
||||
|
||||
class ThreadRing(val N: Int) {
|
||||
val executor = Executors.newFixedThreadPool(MAX_THREADS).sure()
|
||||
|
||||
val nodes : Array<Node> = Array<Node>(MAX_NODES+1, { Node(it+1) })
|
||||
|
||||
{
|
||||
connectNodes()
|
||||
}
|
||||
|
||||
fun connectNodes() {
|
||||
nodes[nodes.size-1] = nodes[0]
|
||||
for (i in 0..nodes.size-2) {
|
||||
nodes[i].connect(nodes[i+1]);
|
||||
}
|
||||
}
|
||||
|
||||
fun sendMessage(m : TokenMessage) {
|
||||
nodes[0].sendMessage(m)
|
||||
}
|
||||
class Node(val nodeId : Int) : Runnable {
|
||||
val queue = LinkedBlockingQueue<TokenMessage>()
|
||||
var isActive = false
|
||||
var nextNode : Node? = null
|
||||
|
||||
fun sendMessage(m: TokenMessage) {
|
||||
queue.add(m)
|
||||
executor.execute(this)
|
||||
}
|
||||
|
||||
fun connect(next: Node) {
|
||||
nextNode = next
|
||||
isActive = true
|
||||
}
|
||||
|
||||
override fun run() {
|
||||
if(isActive) {
|
||||
try {
|
||||
val m = queue.take()
|
||||
if(m.isStop) {
|
||||
val nextValue = m.get()+1
|
||||
if (nextValue == MAX_NODES) {
|
||||
executor.shutdown()
|
||||
cdl.countDown()
|
||||
} else {
|
||||
m.set(nextValue)
|
||||
nextNode.sure().sendMessage(m)
|
||||
}
|
||||
isActive = false
|
||||
}
|
||||
else {
|
||||
if (m.get() == N) {
|
||||
System.out?.println(nodeId);
|
||||
nextNode.sure().sendMessage(TokenMessage(nodeId, 0, true));
|
||||
} else {
|
||||
m.incrementAndGet()
|
||||
nextNode.sure().sendMessage(m);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(e: InterruptedException) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user