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: 2d909947683d
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: afabf344ba62
Choose a head ref
  • 3 commits
  • 7 files changed
  • 1 contributor

Commits on Aug 20, 2015

  1. Copy the full SHA
    a6f8357 View commit details
  2. Copy the full SHA
    555f300 View commit details
  3. [Truffle] Save the right CallTarget for a Proc in a field for faster …

    …access.
    
    * Proc can only migrate from proc-semantics to lambda-semantics,
      so we can discard the proc-semantics CallTarget when creating a lambda.
    eregon committed Aug 20, 2015
    Copy the full SHA
    afabf34 View commit details
Original file line number Diff line number Diff line change
@@ -67,7 +67,7 @@ public void trace(VirtualFrame frame) {
traceFunc = context.getTraceManager().getTraceFunc();

if (traceFunc != null) {
callNode = insert(Truffle.getRuntime().createDirectCallNode(ProcNodes.getCallTargetForType(traceFunc)));
callNode = insert(Truffle.getRuntime().createDirectCallNode(Layouts.PROC.getCallTargetForType(traceFunc)));
} else {
callNode = null;
}
Original file line number Diff line number Diff line change
@@ -1382,7 +1382,7 @@ public DynamicObject procSpecial(DynamicObject block) {
getContext().getCoreLibrary().getProcClass(),
Layouts.PROC.getType(block),
Layouts.PROC.getSharedMethodInfo(block),
Layouts.PROC.getCallTargetForProcs(block),
Layouts.PROC.getCallTargetForType(block),
Layouts.PROC.getCallTargetForLambdas(block),
Layouts.PROC.getDeclarationFrame(block),
Layouts.PROC.getMethod(block),
17 changes: 3 additions & 14 deletions truffle/src/main/java/org/jruby/truffle/nodes/core/ProcNodes.java
Original file line number Diff line number Diff line change
@@ -40,21 +40,10 @@
@CoreClass(name = "Proc")
public abstract class ProcNodes {

public static CallTarget getCallTargetForType(DynamicObject proc) {
switch (Layouts.PROC.getType(proc)) {
case PROC:
return Layouts.PROC.getCallTargetForProcs(proc);
case LAMBDA:
return Layouts.PROC.getCallTargetForLambdas(proc);
}

throw new UnsupportedOperationException(Layouts.PROC.getType(proc).toString());
}

public static Object rootCall(DynamicObject proc, Object... args) {
assert RubyGuards.isRubyProc(proc);

return getCallTargetForType(proc).call(RubyArguments.pack(
return Layouts.PROC.getCallTargetForType(proc).call(RubyArguments.pack(
Layouts.PROC.getMethod(proc),
Layouts.PROC.getDeclarationFrame(proc),
Layouts.PROC.getSelf(proc),
@@ -68,7 +57,7 @@ public static void initialize(DynamicObject proc, SharedMethodInfo sharedMethodI
assert RubyGuards.isRubyProc(proc);

Layouts.PROC.setSharedMethodInfo(proc, sharedMethodInfo);
Layouts.PROC.setCallTargetForProcs(proc, callTargetForProcs);
Layouts.PROC.setCallTargetForType(proc, Layouts.PROC.getType(proc) == Type.PROC ? callTargetForProcs : callTargetForLambdas);
Layouts.PROC.setCallTargetForLambdas(proc, callTargetForLambdas);
Layouts.PROC.setDeclarationFrame(proc, declarationFrame);
Layouts.PROC.setMethod(proc, method);
@@ -165,7 +154,7 @@ public InitializeNode(RubyContext context, SourceSection sourceSection) {

@Specialization(guards = "isRubyProc(block)")
public DynamicObject initialize(DynamicObject proc, DynamicObject block) {
ProcNodes.initialize(proc, Layouts.PROC.getSharedMethodInfo(block), Layouts.PROC.getCallTargetForProcs(block),
ProcNodes.initialize(proc, Layouts.PROC.getSharedMethodInfo(block), Layouts.PROC.getCallTargetForType(block),
Layouts.PROC.getCallTargetForLambdas(block), Layouts.PROC.getDeclarationFrame(block), Layouts.PROC.getMethod(block),
Layouts.PROC.getSelf(block), Layouts.PROC.getBlock(block));

Original file line number Diff line number Diff line change
@@ -37,7 +37,7 @@ public CachedYieldDispatchNode(RubyContext context, DynamicObject block, YieldDi

assert RubyGuards.isRubyProc(block);

callNode = Truffle.getRuntime().createDirectCallNode(ProcNodes.getCallTargetForType(block));
callNode = Truffle.getRuntime().createDirectCallNode(Layouts.PROC.getCallTargetForType(block));
insert(callNode);

if (INLINER_ALWAYS_CLONE_YIELD && callNode.isCallTargetCloningAllowed()) {
@@ -53,7 +53,7 @@ public CachedYieldDispatchNode(RubyContext context, DynamicObject block, YieldDi

@Override
protected boolean guard(DynamicObject block) {
return ProcNodes.getCallTargetForType(block) == callNode.getCallTarget();
return Layouts.PROC.getCallTargetForType(block) == callNode.getCallTarget();
}

@Override
Original file line number Diff line number Diff line change
@@ -38,7 +38,7 @@ protected boolean guard(DynamicObject block) {

@Override
public Object dispatchWithSelfAndBlock(VirtualFrame frame, DynamicObject block, Object self, DynamicObject modifiedBlock, Object... argumentsObjects) {
return callNode.call(frame, ProcNodes.getCallTargetForType(block),
return callNode.call(frame, Layouts.PROC.getCallTargetForType(block),
RubyArguments.pack(Layouts.PROC.getMethod(block), Layouts.PROC.getDeclarationFrame(block), self, modifiedBlock, argumentsObjects));
}

Original file line number Diff line number Diff line change
@@ -19,6 +19,13 @@
import org.jruby.truffle.runtime.methods.InternalMethod;
import org.jruby.truffle.runtime.methods.SharedMethodInfo;

// A instance of Proc behaves either as a proc or lambda (its type).
// Kernel#lambda is the only primitive which can produce a lambda-semantics Proc from a proc-semantics one.
// (possibly Module#define_method as well, but it does not need to be).
// The literal lambda -> *args { body } defines the Proc as lambda directly.
// callTargetForType caches the current CallTarget according to the type for faster access.
// See the documentation of Proc#lambda?, it is a good reference.

@Layout
public interface ProcLayout extends BasicObjectLayout {

@@ -29,7 +36,7 @@ DynamicObject createProc(
DynamicObjectFactory factory,
@Nullable ProcNodes.Type type,
@Nullable SharedMethodInfo sharedMethodInfo,
@Nullable CallTarget callTargetForProcs,
@Nullable CallTarget callTargetForType,
@Nullable CallTarget callTargetForLambdas,
@Nullable MaterializedFrame declarationFrame,
@Nullable InternalMethod method,
@@ -44,8 +51,8 @@ DynamicObject createProc(
SharedMethodInfo getSharedMethodInfo(DynamicObject object);
void setSharedMethodInfo(DynamicObject object, SharedMethodInfo value);

CallTarget getCallTargetForProcs(DynamicObject object);
void setCallTargetForProcs(DynamicObject object, CallTarget value);
CallTarget getCallTargetForType(DynamicObject object);
void setCallTargetForType(DynamicObject object, CallTarget value);

CallTarget getCallTargetForLambdas(DynamicObject object);
void setCallTargetForLambdas(DynamicObject object, CallTarget value);
Original file line number Diff line number Diff line change
@@ -63,47 +63,44 @@ public boolean visit(DynamicObject object) throws StopVisitingObjectsException {
}

private void visitRoots(final ObjectGraphVisitor visitor) {
final Memo<Boolean> keepVisiting = new Memo<>(true);

context.getSafepointManager().pauseAllThreadsAndExecute(null, false, new SafepointAction() {

boolean keepVisiting = true;

@Override
public void run(DynamicObject thread, Node currentNode) {
if (keepVisiting.get()) {
synchronized (this) {
try {
// We only visit the main object from the root thread

if (thread == context.getThreadManager().getRootThread()) {
visitObject(context.getCoreLibrary().getGlobalVariablesObject(), visitor);
}

// All threads visit the thread object
synchronized (this) {
if (!keepVisiting) {
return;
}

visitObject(thread, visitor);
try {
// We only visit the global variables from the root thread
visitObject(context.getCoreLibrary().getGlobalVariablesObject(), visitor);

// All threads visit the call stack
// All threads visit the thread object
visitObject(thread, visitor);

if (Truffle.getRuntime().getCurrentFrame() != null) {
visitFrameInstance(Truffle.getRuntime().getCurrentFrame(), visitor);
}
// All threads visit their call stack
if (Truffle.getRuntime().getCurrentFrame() != null) {
visitFrameInstance(Truffle.getRuntime().getCurrentFrame(), visitor);
}

Truffle.getRuntime().iterateFrames(new FrameInstanceVisitor<Object>() {
Truffle.getRuntime().iterateFrames(new FrameInstanceVisitor<Object>() {

@Override
public Object visitFrame(FrameInstance frameInstance) {
try {
visitFrameInstance(frameInstance, visitor);
} catch (StopVisitingObjectsException e) {
return new Object();
}
return null;
@Override
public Object visitFrame(FrameInstance frameInstance) {
try {
visitFrameInstance(frameInstance, visitor);
} catch (StopVisitingObjectsException e) {
return new Object();
}
return null;
}

});
} catch (StopVisitingObjectsException e) {
keepVisiting.set(true);
}
});
} catch (StopVisitingObjectsException e) {
keepVisiting = false;
}
}
}