Skip to content

Commit

Permalink
[Truffle] Fix ObjectSpaceManager.collectLiveObjects().
Browse files Browse the repository at this point in the history
* Modules should visit their ancestors.
* Class variables should be visited as well.
* The Thread should care to visit it call stack.
* No need to visit main or Object, main will be in one of the top frames
  and in TOPLEVEL_BINDING. Its class is Object, which anyway has
  so many roots pointing to it like Thread's superclass.
  • Loading branch information
eregon committed Feb 20, 2015
1 parent 33d537b commit 11bace0
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 24 deletions.
Expand Up @@ -490,11 +490,21 @@ public void visitObjectGraphChildren(ObjectSpaceManager.ObjectGraphVisitor visit
}
}

for (Object classVariable : classVariables.values()) {
if (classVariable instanceof RubyBasicObject) {
((RubyBasicObject) classVariable).visitObjectGraph(visitor);
}
}

for (InternalMethod method : methods.values()) {
if (method.getDeclarationFrame() != null) {
getContext().getObjectSpaceManager().visitFrame(method.getDeclarationFrame(), visitor);
}
}

for (RubyModule ancestor : ancestors()) {
ancestor.visitObjectGraph(visitor);
}
}

public ModuleChain getParentModule() {
Expand Down
Expand Up @@ -17,8 +17,14 @@
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.ObjectSpaceManager.ObjectGraphVisitor;
import org.jruby.truffle.runtime.subsystems.ThreadManager.BlockingActionWithoutGlobalLock;

import com.oracle.truffle.api.Truffle;
import com.oracle.truffle.api.frame.Frame;
import com.oracle.truffle.api.frame.FrameInstance;
import com.oracle.truffle.api.frame.FrameInstanceVisitor;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
Expand Down Expand Up @@ -173,6 +179,31 @@ public String getName() {
return name;
}

@Override
public void visitObjectGraphChildren(ObjectGraphVisitor visitor) {
visitCallStack(visitor);
}

private void visitCallStack(final ObjectGraphVisitor visitor) {
FrameInstance currentFrame = Truffle.getRuntime().getCurrentFrame();
if (currentFrame != null) {
visitFrameInstance(currentFrame, visitor);
}

Truffle.getRuntime().iterateFrames(new FrameInstanceVisitor<Object>() {
@Override
public Void visitFrame(FrameInstance frameInstance) {
visitFrameInstance(frameInstance, visitor);
return null;
}
});
}

private void visitFrameInstance(FrameInstance frameInstance, ObjectGraphVisitor visitor) {
Frame frame = frameInstance.getFrame(FrameInstance.FrameAccess.READ_ONLY, true);
getContext().getObjectSpaceManager().visitFrame(frame, visitor);
}

public static class ThreadAllocator implements Allocator {

@Override
Expand Down
Expand Up @@ -160,16 +160,14 @@ public boolean visit(RubyBasicObject object) {

};

context.getCoreLibrary().getGlobalVariablesObject().visitObjectGraph(visitor);

context.getSafepointManager().pauseAllThreadsAndExecute(new Consumer<RubyThread>() {

@Override
public void accept(RubyThread currentThread) {
synchronized (liveObjects) {
visitor.visit(currentThread);
context.getCoreLibrary().getGlobalVariablesObject().visitObjectGraph(visitor);
context.getCoreLibrary().getMainObject().visitObjectGraph(visitor);
context.getCoreLibrary().getObjectClass().visitObjectGraph(visitor);
visitCallStack(visitor);
currentThread.visitObjectGraph(visitor);
}
}

Expand All @@ -178,25 +176,6 @@ public void accept(RubyThread currentThread) {
return Collections.unmodifiableMap(liveObjects);
}

public void visitCallStack(final ObjectGraphVisitor visitor) {
FrameInstance currentFrame = Truffle.getRuntime().getCurrentFrame();
if (currentFrame != null) {
visitFrameInstance(currentFrame, visitor);
}

Truffle.getRuntime().iterateFrames(new FrameInstanceVisitor<Object>() {
@Override
public Void visitFrame(FrameInstance frameInstance) {
visitFrameInstance(frameInstance, visitor);
return null;
}
});
}

public void visitFrameInstance(FrameInstance frameInstance, ObjectGraphVisitor visitor) {
visitFrame(frameInstance.getFrame(FrameInstance.FrameAccess.READ_ONLY, true), visitor);
}

public void visitFrame(Frame frame, ObjectGraphVisitor visitor) {
if (frame == null) {
return;
Expand Down

0 comments on commit 11bace0

Please sign in to comment.