From 1e471aa9c4087d26ab69f0d3b2369d9fe629ac64 Mon Sep 17 00:00:00 2001 From: Alex Tkachman Date: Mon, 19 Dec 2011 10:21:17 +0200 Subject: [PATCH] synchronized method --- .../jet/codegen/ExpressionCodegen.java | 2 +- .../codegen/intrinsics/IntrinsicMethods.java | 2 ++ .../jet/codegen/intrinsics/StupidSync.java | 26 +++++++++++++++ compiler/frontend/src/jet/Library.jet | 2 ++ .../codegen/controlStructures/sync.jet | 33 +++++++++++++++++++ .../jet/codegen/ControlStructuresTest.java | 6 ++++ stdlib/src/jet/runtime/Intrinsics.java | 8 +++++ 7 files changed, 78 insertions(+), 1 deletion(-) create mode 100644 compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/StupidSync.java create mode 100644 compiler/testData/codegen/controlStructures/sync.jet diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index 39101c75e48..da8894292f2 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -1403,7 +1403,7 @@ public class ExpressionCodegen extends JetVisitor { return mask; } - private int pushMethodArguments(JetCallElement expression, List valueParameterTypes) { + public int pushMethodArguments(JetCallElement expression, List valueParameterTypes) { ResolvedCall resolvedCall = bindingContext.get(BindingContext.RESOLVED_CALL, expression.getCalleeExpression()); if(resolvedCall != null) { return pushMethodArguments(resolvedCall, valueParameterTypes); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/IntrinsicMethods.java b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/IntrinsicMethods.java index 79374780086..893d9ce47b3 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/IntrinsicMethods.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/IntrinsicMethods.java @@ -20,6 +20,7 @@ import java.util.*; /** * @author yole + * @author alex.tkachman */ public class IntrinsicMethods { private static final IntrinsicMethod UNARY_MINUS = new UnaryMinus(); @@ -89,6 +90,7 @@ public class IntrinsicMethods { declareOverload(myStdLib.getLibraryScope().getFunctions("plus"), 1, new StringPlus()); declareOverload(myStdLib.getLibraryScope().getFunctions("Array"), 1, new NewArray()); declareOverload(myStdLib.getLibraryScope().getFunctions("sure"), 0, new Sure()); + declareOverload(myStdLib.getLibraryScope().getFunctions("synchronized"), 1, new StupidSync()); declareIntrinsicFunction("ByteIterator", "next", 0, ITERATOR_NEXT); declareIntrinsicFunction("ShortIterator", "next", 0, ITERATOR_NEXT); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/StupidSync.java b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/StupidSync.java new file mode 100644 index 00000000000..1e83272f26e --- /dev/null +++ b/compiler/backend/src/org/jetbrains/jet/codegen/intrinsics/StupidSync.java @@ -0,0 +1,26 @@ +package org.jetbrains.jet.codegen.intrinsics; + +import com.intellij.psi.PsiElement; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.codegen.ExpressionCodegen; +import org.jetbrains.jet.codegen.JetTypeMapper; +import org.jetbrains.jet.codegen.StackValue; +import org.jetbrains.jet.lang.psi.JetCallExpression; +import org.jetbrains.jet.lang.psi.JetExpression; +import org.objectweb.asm.Label; +import org.objectweb.asm.Type; +import org.objectweb.asm.commons.InstructionAdapter; + +import java.util.Arrays; +import java.util.List; + +public class StupidSync implements IntrinsicMethod { + @Override + public StackValue generate(ExpressionCodegen codegen, InstructionAdapter v, Type expectedType, @Nullable PsiElement element, @Nullable List arguments, StackValue receiver) { + receiver.put(receiver.type, v); + codegen.pushMethodArguments((JetCallExpression)element, Arrays.asList(JetTypeMapper.TYPE_FUNCTION0)); + v.invokestatic("jet/runtime/Intrinsics", "stupidSync", "(Ljava/lang/Object;Ljet/Function0;)Ljava/lang/Object;"); + StackValue.onStack(JetTypeMapper.TYPE_OBJECT).put(expectedType, v); + return StackValue.onStack(expectedType); + } +} diff --git a/compiler/frontend/src/jet/Library.jet b/compiler/frontend/src/jet/Library.jet index 6feeeb7d334..c54b0d2c49e 100644 --- a/compiler/frontend/src/jet/Library.jet +++ b/compiler/frontend/src/jet/Library.jet @@ -34,6 +34,8 @@ namespace io { fun readLine() : String? } +fun Any.synchronized(block : fun() : R) : R + fun Any?.identityEquals(other : Any?) : Boolean // = this === other // Can't write a body due to a bootstrapping problem (see JET-74) diff --git a/compiler/testData/codegen/controlStructures/sync.jet b/compiler/testData/codegen/controlStructures/sync.jet new file mode 100644 index 00000000000..408db40ca36 --- /dev/null +++ b/compiler/testData/codegen/controlStructures/sync.jet @@ -0,0 +1,33 @@ +import java.util.concurrent.* +import java.util.concurrent.atomic.* + +fun thread(block: fun():Unit ) { + val thread = object: Thread() { + override fun run() { + block() + } + } + thread.start() +} + +fun box() : String { + val ref = AtomicInteger() + val cdl = CountDownLatch(11) + for(i in 0..10) { + thread { + var current = 0 + do { + current = ref.synchronized { + val v = ref.get() + 1 + if(v < 100) + ref.set(v+1) + v + } + } + while(current < 100) + cdl.countDown() + } + } + cdl.await() + return if(ref.get() == 100) "OK" else ref.get().toString() +} \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/jet/codegen/ControlStructuresTest.java b/compiler/tests/org/jetbrains/jet/codegen/ControlStructuresTest.java index 9c57f5b161c..ec218e38024 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/ControlStructuresTest.java +++ b/compiler/tests/org/jetbrains/jet/codegen/ControlStructuresTest.java @@ -238,6 +238,12 @@ public class ControlStructuresTest extends CodegenTestCase { public void testQuicksort() throws Exception { blackBoxFile("controlStructures/quicksort.jet"); +// System.out.println(generateToText()); + } + + public void testSynchronized() throws Exception { + createEnvironmentWithFullJdk(); + blackBoxFile("controlStructures/sync.jet"); // System.out.println(generateToText()); } } diff --git a/stdlib/src/jet/runtime/Intrinsics.java b/stdlib/src/jet/runtime/Intrinsics.java index 19488b98ba2..d9a8f68ef7b 100644 --- a/stdlib/src/jet/runtime/Intrinsics.java +++ b/stdlib/src/jet/runtime/Intrinsics.java @@ -1,5 +1,7 @@ package jet.runtime; +import jet.Function0; + import java.util.ArrayList; /** @@ -29,6 +31,12 @@ public class Intrinsics { return (thisVal == anotherVal ? 0 : (anotherVal ? 1 : -1)); } + public static R stupidSync(Object lock, Function0 block) { + synchronized (lock) { + return block.invoke(); + } + } + private static Throwable sanitizeStackTrace(Throwable throwable) { StackTraceElement[] stackTrace = throwable.getStackTrace(); ArrayList list = new ArrayList();