Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: jruby/jruby
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: eeabafeb82d3
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: a29b589fd4bd
Choose a head ref
  • 2 commits
  • 8 files changed
  • 1 contributor

Commits on Feb 7, 2016

  1. Copy the full SHA
    2c9a6a3 View commit details
  2. 1
    Copy the full SHA
    a29b589 View commit details
Original file line number Diff line number Diff line change
@@ -19,7 +19,7 @@
import org.jruby.truffle.language.backtrace.Backtrace;
import org.jruby.truffle.language.control.RaiseException;
import org.jruby.truffle.core.Layouts;
import org.jruby.truffle.language.SafepointAction;
import org.jruby.util.func.Function2;

import static org.jruby.RubyThread.*;

@@ -45,9 +45,9 @@ public DynamicObject raise(DynamicObject thread, final DynamicObject exception)
public static void raiseInThread(final RubyContext context, DynamicObject rubyThread, final DynamicObject exception, Node currentNode) {
final Thread javaThread = Layouts.FIBER.getThread((Layouts.THREAD.getFiberManager(rubyThread).getCurrentFiber()));

context.getSafepointManager().pauseThreadAndExecuteLater(javaThread, currentNode, new SafepointAction() {
context.getSafepointManager().pauseThreadAndExecuteLater(javaThread, currentNode, new Function2<Void, DynamicObject, Node>() {
@Override
public void run(DynamicObject currentThread, Node currentNode) {
public Void apply(DynamicObject currentThread, Node currentNode) {
if (Layouts.EXCEPTION.getBacktrace(exception) == null) {
Backtrace backtrace = RubyCallStack.getBacktrace(context, currentNode);
Layouts.EXCEPTION.setBacktrace(exception, backtrace);
Original file line number Diff line number Diff line change
@@ -21,8 +21,8 @@
import org.jruby.truffle.RubyContext;
import org.jruby.truffle.language.backtrace.BacktraceFormatter;
import org.jruby.truffle.language.control.RaiseException;
import org.jruby.truffle.language.SafepointAction;
import org.jruby.truffle.language.SafepointManager;
import org.jruby.util.func.Function2;

import java.util.Collections;
import java.util.Set;
@@ -236,12 +236,13 @@ public Object[] getThreadList() {
private void killOtherThreads() {
while (true) {
try {
context.getSafepointManager().pauseAllThreadsAndExecute(null, false, new SafepointAction() {
context.getSafepointManager().pauseAllThreadsAndExecute(null, false, new Function2<Void, DynamicObject, Node>() {
@Override
public synchronized void run(DynamicObject thread, Node currentNode) {
public synchronized Void apply(DynamicObject thread, Node currentNode) {
if (thread != rootThread && Thread.currentThread() == Layouts.THREAD.getThread(thread)) {
ThreadNodes.shutdown(context, thread, currentNode);
}
return null;
}
});
break; // Successfully executed the safepoint and sent the exceptions.
Original file line number Diff line number Diff line change
@@ -33,7 +33,7 @@
import org.jruby.truffle.language.control.RaiseException;
import org.jruby.truffle.language.control.ReturnException;
import org.jruby.truffle.language.control.ThreadExitException;
import org.jruby.truffle.language.SafepointAction;
import org.jruby.util.func.Function2;

import java.util.ArrayList;
import java.util.concurrent.CountDownLatch;
@@ -181,11 +181,12 @@ public DynamicObject backtrace(DynamicObject rubyThread) {

final DynamicObject[] result = new DynamicObject[1];

getContext().getSafepointManager().pauseThreadAndExecute(thread, this, new SafepointAction() {
getContext().getSafepointManager().pauseThreadAndExecute(thread, this, new Function2<Void, DynamicObject, Node>() {
@Override
public void run(DynamicObject thread, Node currentNode) {
public Void apply(DynamicObject thread, Node currentNode) {
final Backtrace backtrace = RubyCallStack.getBacktrace(getContext(), currentNode);
result[0] = ExceptionNodes.backtraceAsRubyStringArray(getContext(), null, backtrace);
return null;
}
});

@@ -224,10 +225,11 @@ public DynamicObject kill(final DynamicObject rubyThread) {
return rubyThread;
}

getContext().getSafepointManager().pauseThreadAndExecuteLater(toKill, this, new SafepointAction() {
getContext().getSafepointManager().pauseThreadAndExecuteLater(toKill, this, new Function2<Void, DynamicObject, Node>() {
@Override
public void run(DynamicObject currentThread, Node currentNode) {
public Void apply(DynamicObject currentThread, Node currentNode) {
shutdown(getContext(), currentThread, currentNode);
return null;
}
});

This file was deleted.

Original file line number Diff line number Diff line change
@@ -21,6 +21,7 @@
import org.jruby.truffle.core.InterruptMode;
import org.jruby.truffle.RubyContext;
import org.jruby.truffle.core.Layouts;
import org.jruby.util.func.Function2;

import java.util.Collections;
import java.util.Set;
@@ -38,7 +39,7 @@ public class SafepointManager {
private final ReentrantLock lock = new ReentrantLock();

private final Phaser phaser = new Phaser();
private volatile SafepointAction action;
private volatile Function2<Void,DynamicObject,Node> action;
private volatile boolean deferred;

public SafepointManager(RubyContext context) {
@@ -93,16 +94,16 @@ private void assumptionInvalidated(Node currentNode, boolean fromBlockingCall) {
return; // interrupt me later
}

SafepointAction deferredAction = step(currentNode, false);
Function2<Void,DynamicObject,Node> deferredAction = step(currentNode, false);

// We're now running again normally and can run deferred actions
if (deferredAction != null) {
deferredAction.run(thread, currentNode);
deferredAction.apply(thread, currentNode);
}
}

@TruffleBoundary
private SafepointAction step(Node currentNode, boolean isDrivingThread) {
private Function2<Void,DynamicObject,Node> step(Node currentNode, boolean isDrivingThread) {
final DynamicObject thread = context.getThreadManager().getCurrentThread();

// wait other threads to reach their safepoint
@@ -116,11 +117,11 @@ private SafepointAction step(Node currentNode, boolean isDrivingThread) {
phaser.arriveAndAwaitAdvance();

// Read these while in the safepoint.
SafepointAction deferredAction = deferred ? action : null;
Function2<Void,DynamicObject,Node> deferredAction = deferred ? action : null;

try {
if (!deferred && thread != null && Layouts.THREAD.getStatus(thread) != Status.ABORTING) {
action.run(thread, currentNode);
action.apply(thread, currentNode);
}
} finally {
// wait other threads to finish their action
@@ -139,7 +140,7 @@ private void interruptOtherThreads() {
}
}

private void pauseAllThreadsAndExecute(Node currentNode, boolean isRubyThread, SafepointAction action, boolean deferred) {
private void pauseAllThreadsAndExecute(Node currentNode, boolean isRubyThread, Function2<Void,DynamicObject,Node> action, boolean deferred) {
this.action = action;
this.deferred = deferred;

@@ -156,7 +157,7 @@ private void pauseAllThreadsAndExecute(Node currentNode, boolean isRubyThread, S
// Variants for all threads

@TruffleBoundary
public void pauseAllThreadsAndExecute(Node currentNode, boolean deferred, SafepointAction action) {
public void pauseAllThreadsAndExecute(Node currentNode, boolean deferred, Function2<Void,DynamicObject,Node> action) {
if (lock.isHeldByCurrentThread()) {
throw new IllegalStateException("Re-entered SafepointManager");
}
@@ -174,12 +175,12 @@ public void pauseAllThreadsAndExecute(Node currentNode, boolean deferred, Safepo

// Run deferred actions after leaving the SafepointManager lock.
if (deferred) {
action.run(context.getThreadManager().getCurrentThread(), currentNode);
action.apply(context.getThreadManager().getCurrentThread(), currentNode);
}
}

@TruffleBoundary
public void pauseAllThreadsAndExecuteFromNonRubyThread(boolean deferred, SafepointAction action) {
public void pauseAllThreadsAndExecuteFromNonRubyThread(boolean deferred, Function2<Void,DynamicObject,Node> action) {
if (lock.isHeldByCurrentThread()) {
throw new IllegalStateException("Re-entered SafepointManager");
}
@@ -203,49 +204,52 @@ public void pauseAllThreadsAndExecuteFromNonRubyThread(boolean deferred, Safepoi
// Variants for a single thread

@TruffleBoundary
public void pauseThreadAndExecute(final Thread thread, Node currentNode, final SafepointAction action) {
public void pauseThreadAndExecute(final Thread thread, Node currentNode, final Function2<Void,DynamicObject,Node> action) {
if (Thread.currentThread() == thread) {
// fast path if we are already the right thread
DynamicObject rubyThread = context.getThreadManager().getCurrentThread();
action.run(rubyThread, currentNode);
action.apply(rubyThread, currentNode);
} else {
pauseAllThreadsAndExecute(currentNode, false, new SafepointAction() {
pauseAllThreadsAndExecute(currentNode, false, new Function2<Void, DynamicObject, Node>() {
@Override
public void run(DynamicObject rubyThread, Node currentNode) {
public Void apply(DynamicObject rubyThread, Node currentNode) {
if (Thread.currentThread() == thread) {
action.run(rubyThread, currentNode);
action.apply(rubyThread, currentNode);
}
return null;
}
});
}
}

@TruffleBoundary
public void pauseThreadAndExecuteLater(final Thread thread, Node currentNode, final SafepointAction action) {
public void pauseThreadAndExecuteLater(final Thread thread, Node currentNode, final Function2<Void,DynamicObject,Node> action) {
if (Thread.currentThread() == thread) {
// fast path if we are already the right thread
DynamicObject rubyThread = context.getThreadManager().getCurrentThread();
action.run(rubyThread, currentNode);
action.apply(rubyThread, currentNode);
} else {
pauseAllThreadsAndExecute(currentNode, true, new SafepointAction() {
pauseAllThreadsAndExecute(currentNode, true, new Function2<Void, DynamicObject, Node>() {
@Override
public void run(DynamicObject rubyThread, Node currentNode) {
public Void apply(DynamicObject rubyThread, Node currentNode) {
if (Thread.currentThread() == thread) {
action.run(rubyThread, currentNode);
action.apply(rubyThread, currentNode);
}
return null;
}
});
}
}

@TruffleBoundary
public void pauseThreadAndExecuteLaterFromNonRubyThread(final Thread thread, final SafepointAction action) {
pauseAllThreadsAndExecuteFromNonRubyThread(true, new SafepointAction() {
public void pauseThreadAndExecuteLaterFromNonRubyThread(final Thread thread, final Function2<Void,DynamicObject,Node> action) {
pauseAllThreadsAndExecuteFromNonRubyThread(true, new Function2<Void, DynamicObject, Node>() {
@Override
public void run(DynamicObject rubyThread, Node currentNode) {
public Void apply(DynamicObject rubyThread, Node currentNode) {
if (Thread.currentThread() == thread) {
action.run(rubyThread, currentNode);
action.apply(rubyThread, currentNode);
}
return null;
}
});
}
Original file line number Diff line number Diff line change
@@ -21,7 +21,7 @@
import org.jruby.truffle.RubyContext;
import org.jruby.truffle.core.hash.Entry;
import org.jruby.truffle.core.Layouts;
import org.jruby.truffle.language.SafepointAction;
import org.jruby.util.func.Function2;

import java.util.*;

@@ -33,10 +33,10 @@ public static Set<DynamicObject> stopAndGetAllObjects(

final Thread stoppingThread = Thread.currentThread();

context.getSafepointManager().pauseAllThreadsAndExecute(currentNode, false, new SafepointAction() {
context.getSafepointManager().pauseAllThreadsAndExecute(currentNode, false, new Function2<Void, DynamicObject, Node>() {

@Override
public void run(DynamicObject thread, Node currentNode) {
public Void apply(DynamicObject thread, Node currentNode) {
synchronized (visited) {
final Deque<DynamicObject> stack = new ArrayDeque<>();

@@ -66,6 +66,8 @@ public Object visitFrame(FrameInstance frameInstance) {
stack.addAll(ObjectGraph.getAdjacentObjects(object));
}
}

return null;
}
}
});
@@ -78,14 +80,16 @@ public static Set<DynamicObject> stopAndGetRootObjects(Node currentNode, final R

final Thread stoppingThread = Thread.currentThread();

context.getSafepointManager().pauseAllThreadsAndExecute(currentNode, false, new SafepointAction() {
context.getSafepointManager().pauseAllThreadsAndExecute(currentNode, false, new Function2<Void, DynamicObject, Node>() {
@Override
public void run(DynamicObject thread, Node currentNode) {
public Void apply(DynamicObject thread, Node currentNode) {
objects.add(thread);

if (Thread.currentThread() == stoppingThread) {
visitContextRoots(context, objects);
}

return null;
}
});

Original file line number Diff line number Diff line change
@@ -15,7 +15,7 @@
import org.jruby.truffle.core.proc.ProcNodes;
import org.jruby.truffle.RubyContext;
import org.jruby.truffle.core.Layouts;
import org.jruby.truffle.language.SafepointAction;
import org.jruby.util.func.Function2;

public class ProcSignalHandler implements SignalHandler {

@@ -32,10 +32,11 @@ public ProcSignalHandler(RubyContext context, DynamicObject proc) {
@Override
public void handle(Signal signal) {
Thread mainThread = Layouts.FIBER.getThread((Layouts.THREAD.getFiberManager(context.getThreadManager().getRootThread()).getCurrentFiber()));
context.getSafepointManager().pauseThreadAndExecuteLaterFromNonRubyThread(mainThread, new SafepointAction() {
context.getSafepointManager().pauseThreadAndExecuteLaterFromNonRubyThread(mainThread, new Function2<Void, DynamicObject, Node>() {
@Override
public void run(DynamicObject thread, Node currentNode) {
public Void apply(DynamicObject thread, Node currentNode) {
ProcNodes.rootCall(proc);
return null;
}
});
}
Original file line number Diff line number Diff line change
@@ -18,10 +18,10 @@
import com.sun.net.httpserver.HttpServer;
import org.jruby.truffle.language.RubyCallStack;
import org.jruby.truffle.RubyContext;
import org.jruby.truffle.language.SafepointAction;
import org.jruby.truffle.language.backtrace.Backtrace;
import org.jruby.truffle.language.backtrace.BacktraceFormatter;
import org.jruby.truffle.core.Layouts;
import org.jruby.util.func.Function2;

import java.io.IOException;
import java.io.OutputStream;
@@ -62,10 +62,10 @@ public void handle(HttpExchange httpExchange) {
try {
final StringBuilder builder = new StringBuilder();

context.getSafepointManager().pauseAllThreadsAndExecuteFromNonRubyThread(false, new SafepointAction() {
context.getSafepointManager().pauseAllThreadsAndExecuteFromNonRubyThread(false, new Function2<Void, DynamicObject, Node>() {

@Override
public void run(DynamicObject thread, Node currentNode) {
public Void apply(DynamicObject thread, Node currentNode) {
try {
Backtrace backtrace = RubyCallStack.getBacktrace(context, null);

@@ -84,6 +84,8 @@ public void run(DynamicObject thread, Node currentNode) {
} catch (Throwable e) {
e.printStackTrace();
}

return null;
}

});
@@ -112,11 +114,12 @@ public void run(DynamicObject thread, Node currentNode) {
public void handle(HttpExchange httpExchange) {
try {
Thread mainThread = Layouts.FIBER.getThread((Layouts.THREAD.getFiberManager(context.getThreadManager().getRootThread()).getCurrentFiber()));
context.getSafepointManager().pauseThreadAndExecuteLaterFromNonRubyThread(mainThread, new SafepointAction() {
context.getSafepointManager().pauseThreadAndExecuteLaterFromNonRubyThread(mainThread, new Function2<Void, DynamicObject, Node>() {
@Override
public void run(DynamicObject thread, final Node currentNode) {
public Void apply(DynamicObject thread, final Node currentNode) {
new SimpleShell(context).run(Truffle.getRuntime().getCurrentFrame()
.getFrame(FrameInstance.FrameAccess.MATERIALIZE, true).materialize(), currentNode);
return null;
}
});