Skip to content

Commit

Permalink
[Truffle] Revert recent changes for a stable preview master branch.
Browse files Browse the repository at this point in the history
  • Loading branch information
eregon committed Jan 19, 2015
1 parent 295fdb5 commit 72353c0
Show file tree
Hide file tree
Showing 8 changed files with 95 additions and 121 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ public long objectID(int value) {
}

@Specialization(rewriteOn = ArithmeticException.class)
public long objectIDSmallFixnumOverflow(long value) throws ArithmeticException {
public long objectIDSmallFixnumOverflow(long value) {
return ObjectIDOperations.smallFixnumToIDOverflow(value);
}

Expand Down
84 changes: 53 additions & 31 deletions core/src/main/java/org/jruby/truffle/nodes/core/KernelNodes.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
import com.oracle.truffle.api.frame.*;
import com.oracle.truffle.api.nodes.UnexpectedResultException;
import com.oracle.truffle.api.source.SourceSection;

import org.jruby.common.IRubyWarnings;
import org.jruby.runtime.Visibility;
import org.jruby.truffle.nodes.RubyNode;
Expand All @@ -41,7 +40,6 @@
import org.jruby.truffle.runtime.hash.HashOperations;
import org.jruby.truffle.runtime.hash.KeyValue;
import org.jruby.truffle.runtime.methods.InternalMethod;
import org.jruby.truffle.runtime.subsystems.ThreadManager.BlockingActionWithoutGlobalLock;
import org.jruby.util.ByteList;
import org.jruby.util.cli.Options;

Expand Down Expand Up @@ -678,7 +676,7 @@ private static void exec(RubyContext context, String[] commandLine) {
builder.environment().put(keyValue.getKey().toString(), keyValue.getValue().toString());
}

final Process process;
Process process;

try {
process = builder.start();
Expand All @@ -687,12 +685,16 @@ private static void exec(RubyContext context, String[] commandLine) {
throw new RuntimeException(e);
}

int exitCode = context.getThreadManager().runUntilResult(new BlockingActionWithoutGlobalLock<Integer>() {
@Override
public Integer block() throws InterruptedException {
return process.waitFor();
int exitCode;

while (true) {
try {
exitCode = process.waitFor();
break;
} catch (InterruptedException e) {
continue;
}
});
}

System.exit(exitCode);
}
Expand All @@ -712,7 +714,11 @@ public ExitNode(ExitNode prev) {

@Specialization
public Object exit(UndefinedPlaceholder exitCode) {
return exit(0);
notDesignedForCompilation();

getContext().shutdown();
System.exit(0);
return null;
}

@Specialization
Expand Down Expand Up @@ -851,23 +857,25 @@ public GetsNode(GetsNode prev) {
public RubyString gets(VirtualFrame frame) {
notDesignedForCompilation();

// TODO(CS): having some trouble interacting with JRuby stdin - so using this hack
final InputStream in = getContext().getRuntime().getInstanceConfig().getInput();
final RubyContext context = getContext();

final BufferedReader reader = new BufferedReader(new InputStreamReader(in));
final Frame caller = Truffle.getRuntime().getCallerFrame().getFrame(FrameInstance.FrameAccess.READ_WRITE, false);

final String line = getContext().getThreadManager().runOnce(new BlockingActionWithoutGlobalLock<String>() {
@Override
public String block() throws InterruptedException {
return gets(reader);
}
});
final String line;

final RubyString rubyLine = getContext().makeString(line);
final RubyThread runningThread = getContext().getThreadManager().leaveGlobalLock();

// Set the local variable $_ in the caller
try {
line = gets(context);
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
getContext().getThreadManager().enterGlobalLock(runningThread);
}

final Frame caller = Truffle.getRuntime().getCallerFrame().getFrame(FrameInstance.FrameAccess.READ_WRITE, false);
final RubyString rubyLine = context.makeString(line);

// Set the local variable $_ in the caller

final FrameSlot slot = caller.getFrameDescriptor().findFrameSlot("$_");

Expand All @@ -879,12 +887,22 @@ public String block() throws InterruptedException {
}

@TruffleBoundary
private static String gets(BufferedReader reader) throws InterruptedException {
try {
return reader.readLine();
} catch (IOException e) {
throw new RuntimeException(e);
private static String gets(RubyContext context) throws IOException {
// TODO(CS): having some trouble interacting with JRuby stdin - so using this hack

final StringBuilder builder = new StringBuilder();

while (true) {
final int c = context.getRuntime().getInstanceConfig().getInput().read();

if (c == -1 || c == '\r' || c == '\n') {
break;
}

builder.append((char) c);
}

return builder.toString();
}

}
Expand Down Expand Up @@ -1952,13 +1970,17 @@ public double sleep(double duration) {
private double doSleep(final double duration) {
final long start = System.nanoTime();

getContext().getThreadManager().runOnce(new BlockingActionWithoutGlobalLock<Boolean>() {
@Override
public Boolean block() throws InterruptedException {
final RubyThread runningThread = getContext().getThreadManager().leaveGlobalLock();

try {
try {
Thread.sleep((long) (duration * 1000));
return SUCCESS;
} finally {
getContext().getThreadManager().enterGlobalLock(runningThread);
}
});
} catch (InterruptedException e) {
getContext().getSafepointManager().poll();
}

final long end = System.nanoTime();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public static boolean isSmallFixnum(long fixnum) {
return SMALL_FIXNUM_MIN <= fixnum && fixnum <= SMALL_FIXNUM_MAX;
}

public static long smallFixnumToIDOverflow(long fixnum) throws ArithmeticException {
public static long smallFixnumToIDOverflow(long fixnum) throws ArithmeticException{
return ExactMath.addExact(ExactMath.multiplyExact(fixnum, 2), 1);
}

Expand Down
18 changes: 10 additions & 8 deletions core/src/main/java/org/jruby/truffle/runtime/core/RubyFiber.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,11 @@
package org.jruby.truffle.runtime.core;

import com.oracle.truffle.api.nodes.ControlFlowException;

import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.nodes.objects.Allocator;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.subsystems.FiberManager;
import org.jruby.truffle.runtime.subsystems.ThreadManager;
import org.jruby.truffle.runtime.subsystems.ThreadManager.BlockingActionWithoutGlobalLock;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
Expand Down Expand Up @@ -110,18 +108,22 @@ public void run() {
}

/**
* Send the Java thread that represents this fiber to sleep until it receives a resume or exit
* Send the Java thread that represents this fiber to sleep until it recieves a resume or exit
* message. On entry, assumes that the GIL is not held. On exit, holding the GIL.
*/
public Object waitForResume() {
RubyNode.notDesignedForCompilation();

FiberMessage message = getContext().getThreadManager().runUntilResult(new BlockingActionWithoutGlobalLock<FiberMessage>() {
@Override
public FiberMessage block() throws InterruptedException {
return messageQueue.poll(1, TimeUnit.SECONDS);
FiberMessage message = null;

do {
try {
// TODO(cs) what is a suitable timeout?
message = messageQueue.poll(1, TimeUnit.SECONDS);
} catch (InterruptedException e) {
// Poll again
}
});
} while (message == null);

if (message instanceof FiberExitMessage) {
throw new FiberExitException();
Expand Down
20 changes: 13 additions & 7 deletions core/src/main/java/org/jruby/truffle/runtime/core/RubyThread.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
import org.jruby.truffle.runtime.control.ReturnException;
import org.jruby.truffle.runtime.control.ThreadExitException;
import org.jruby.truffle.runtime.subsystems.ThreadManager;
import org.jruby.truffle.runtime.subsystems.ThreadManager.BlockingActionWithoutGlobalLock;

import java.util.concurrent.CountDownLatch;

Expand Down Expand Up @@ -109,13 +108,20 @@ public void setRootThread(Thread thread) {
}

public void join() {
getContext().getThreadManager().runUntilResult(new BlockingActionWithoutGlobalLock<Boolean>() {
@Override
public Boolean block() throws InterruptedException {
finished.await();
return SUCCESS;
final RubyThread runningThread = getContext().getThreadManager().leaveGlobalLock();

try {
while (true) {
try {
finished.await();
break;
} catch (InterruptedException e) {
// Await again
}
}
});
} finally {
getContext().getThreadManager().enterGlobalLock(runningThread);
}

if (exception != null) {
throw new RaiseException(exception);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,12 @@
import com.oracle.truffle.api.frame.FrameInstance;
import com.oracle.truffle.api.frame.FrameInstanceVisitor;
import com.oracle.truffle.api.frame.FrameSlot;

import org.jruby.runtime.Visibility;
import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.core.RubyBasicObject;
import org.jruby.truffle.runtime.core.RubyProc;
import org.jruby.truffle.runtime.core.RubyThread;
import org.jruby.truffle.runtime.subsystems.ThreadManager.BlockingActionWithoutGlobalLock;
import org.jruby.truffle.runtime.util.Consumer;

import java.lang.ref.ReferenceQueue;
Expand Down Expand Up @@ -134,18 +132,18 @@ private void runFinalizers() {

// Leave the global lock and wait on the finalizer queue

final RubyThread runningThread = context.getThreadManager().leaveGlobalLock();
finalizerJavaThread = Thread.currentThread();

finalizerReference = context.getThreadManager().runOnce(new BlockingActionWithoutGlobalLock<FinalizerReference>() {
@Override
public FinalizerReference block() throws InterruptedException {
return (FinalizerReference) finalizerQueue.remove();
}
});

if (finalizerReference != null) {
runFinalizers(finalizerReference);
try {
finalizerReference = (FinalizerReference) finalizerQueue.remove();
} catch (InterruptedException e) {
continue;
} finally {
context.getThreadManager().enterGlobalLock(runningThread);
}

runFinalizers(finalizerReference);
}

finished.countDown();
Expand All @@ -164,7 +162,6 @@ private static void runFinalizers(FinalizerReference finalizerReference) {
public void shutdown() {
RubyNode.notDesignedForCompilation();

// TODO (eregon): refactor this without explicit interrupt
context.getThreadManager().enterGlobalLock(finalizerThread);

try {
Expand All @@ -177,13 +174,14 @@ public void shutdown() {
finalizerJavaThread.interrupt();
}

context.getThreadManager().runOnce(new BlockingActionWithoutGlobalLock<Boolean>() {
@Override
public Boolean block() throws InterruptedException {
finished.await();
return SUCCESS;
}
});
context.getThreadManager().leaveGlobalLock();

try {
finished.await();
} catch (InterruptedException e) {
} finally {
context.getThreadManager().enterGlobalLock(finalizerThread);
}
}

// Run any finalizers for objects that are still live
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.Truffle;
import com.oracle.truffle.api.nodes.InvalidAssumptionException;

import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.core.RubyThread;
import org.jruby.truffle.runtime.util.Consumer;
Expand Down Expand Up @@ -136,7 +135,6 @@ private void waitOnBarrierNoGlobalLock() {
} catch (BrokenBarrierException e) {
throw new RuntimeException(e);
} catch (InterruptedException e) {
throw new RuntimeException("Should not be interrupted while waiting on the safepoint barrier", e);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,58 +71,6 @@ public RubyThread leaveGlobalLock() {
return result;
}

public static interface BlockingActionWithoutGlobalLock<T> {
public static boolean SUCCESS = true;

T block() throws InterruptedException;
}

/**
* Runs {@code action} until it returns a non-null value.
* The action might be {@link Thread#interrupted()}, for instance by
* the {@link SafepointManager}, in which case it will be run again.
*
* @param action must not touch any Ruby state
* @return the first non-null return value from {@code action}
*/
@CompilerDirectives.TruffleBoundary
public <T> T runUntilResult(BlockingActionWithoutGlobalLock<T> action) {
T result = null;

do {
result = runOnce(action);
} while (result == null);

return result;
}

/**
* Runs {@code action} once.
* The action might be {@link Thread#interrupted()}, for instance by
* the {@link SafepointManager}, in which case null will be returned.
*
* @param action must not touch any Ruby state
* @return the return value from {@code action} or null if interrupted
*/
@CompilerDirectives.TruffleBoundary
public <T> T runOnce(BlockingActionWithoutGlobalLock<T> action) {
T result = null;
final RubyThread runningThread = leaveGlobalLock();

try {
try {
result = action.block();
} finally {
// We need to enter the global lock before anything else!
enterGlobalLock(runningThread);
}
} catch (InterruptedException e) {
// We were interrupted, possibly by the SafepointManager.
runningThread.getContext().getSafepointManager().poll();
}
return result;
}

public RubyThread getCurrentThread() {
return currentThread;
}
Expand Down

0 comments on commit 72353c0

Please sign in to comment.