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: 88c716e6a12a
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 7878a2e20993
Choose a head ref
  • 9 commits
  • 11 files changed
  • 1 contributor

Commits on Sep 14, 2015

  1. Copy the full SHA
    8c3aa43 View commit details
  2. Copy the full SHA
    9991034 View commit details
  3. Copy the full SHA
    85e38aa View commit details
  4. 1
    Copy the full SHA
    de630e0 View commit details
  5. Copy the full SHA
    22fe01d View commit details
  6. Copy the full SHA
    f1d583f View commit details
  7. 1
    Copy the full SHA
    407033b View commit details

Commits on Sep 15, 2015

  1. Copy the full SHA
    f6b4753 View commit details
  2. Copy the full SHA
    7878a2e View commit details
15 changes: 10 additions & 5 deletions lib/ruby/truffle/truffle/objspace.rb
Original file line number Diff line number Diff line change
@@ -65,7 +65,7 @@ def count_objects_size(hash = {})
total = 0
ObjectSpace.each_object(Class) do |klass|
per_klass = memsize_of_all(klass)
hash[klass.name.to_sym] = per_klass
hash[klass.name.to_sym] = per_klass unless klass.name.nil?
total += per_klass
end
hash[:TOTAL] = total
@@ -74,6 +74,11 @@ def count_objects_size(hash = {})
module_function :count_objects_size

def count_tdata_objects(hash = {})
ObjectSpace.each_object do |object|
object_type = Truffle::Primitive.object_type_of(object)
hash[object_type] ||= 0
hash[object_type] += 1
end
hash
end
module_function :count_tdata_objects
@@ -212,7 +217,7 @@ def allocation_class_path(object)
def allocation_generation(object)
allocation = ALLOCATIONS[object]
return nil if allocation.nil?
0
allocation.generation
end
module_function :allocation_generation

@@ -237,12 +242,12 @@ def allocation_sourceline(object)
end
module_function :allocation_sourceline

Allocation = Struct.new(:class_path, :method_id, :sourcefile, :sourceline)
Allocation = Struct.new(:class_path, :method_id, :sourcefile, :sourceline, :generation)

ALLOCATIONS = {}.compare_by_identity

def trace_allocation(object, class_path, method_id, sourcefile, sourceline)
ALLOCATIONS[object] = Allocation.new(class_path, method_id, sourcefile, sourceline)
def trace_allocation(object, class_path, method_id, sourcefile, sourceline, generation)
ALLOCATIONS[object] = Allocation.new(class_path, method_id, sourcefile, sourceline, generation)
end
module_function :trace_allocation

9 changes: 9 additions & 0 deletions test/mri/excludes_truffle/TestObjSpace.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
exclude :test_memsize_of_root_shared_string, "we don't share strings yet"
exclude :test_dump_flags, "we don't expose the same GC information as MRI"
exclude :test_dump_to_default, "object attributes are not the same as MRI"
exclude :test_dump_to_io, "uses a pipe in a way that isn't quite working for us"
exclude :test_dump_uninitialized_file, "needs spawn"
exclude :test_reachable_objects_from, "needs spawn"
exclude :test_reachable_objects_size, "needs spawn"
exclude :test_dump_all, "needs spawn"
exclude :test_argf_memsize, "we store ext as an ivar so it doesn't show up in the object size as they expect"
2 changes: 1 addition & 1 deletion test/mri_truffle.index
Original file line number Diff line number Diff line change
@@ -486,7 +486,7 @@ logger/test_severity.rb
# mkmf/test_signedness.rb
# mkmf/test_sizeof.rb
# net/ftp/test_buffered_socket.rb
# objspace/test_objspace.rb
objspace/test_objspace.rb
# open-uri/test_open-uri.rb
# open-uri/test_ssl.rb
# openssl/test_fips.rb
Original file line number Diff line number Diff line change
@@ -156,7 +156,7 @@ private static RubyRootNode makeGenericMethod(RubyContext context, MethodDetails

final Arity arity = new Arity(required, optional, method.rest());

final SharedMethodInfo sharedMethodInfo = new SharedMethodInfo(sourceSection, LexicalScope.NONE, arity, methodDetails.getIndicativeName(), false, null, context.getOptions().CORE_ALWAYS_CLONE);
final SharedMethodInfo sharedMethodInfo = new SharedMethodInfo(sourceSection, LexicalScope.NONE, arity, method.names()[0], false, null, context.getOptions().CORE_ALWAYS_CLONE);

final List<RubyNode> argumentsNodes = new ArrayList<>();

Original file line number Diff line number Diff line change
@@ -615,4 +615,18 @@ private DynamicObject ast(Node node) {

}

@CoreMethod(names = "object_type_of", onSingleton = true, required = 1)
public abstract static class ObjectTypeOfNode extends CoreMethodArrayArgumentsNode {

public ObjectTypeOfNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
}

@Specialization
public DynamicObject objectTypeOf(DynamicObject value) {
return getSymbol(value.getShape().getObjectType().getClass().getSimpleName());
}

}

}
Original file line number Diff line number Diff line change
@@ -28,10 +28,12 @@
public abstract class ArrayLiteralNode extends RubyNode {

@Children protected final RubyNode[] values;
@Child protected AllocateObjectNode allocateObjectNode;

public ArrayLiteralNode(RubyContext context, SourceSection sourceSection, RubyNode[] values) {
super(context, sourceSection);
this.values = values;
allocateObjectNode = AllocateObjectNodeGen.create(context, sourceSection, false, null, null);
}

protected DynamicObject makeGeneric(VirtualFrame frame, Object[] alreadyExecuted) {
@@ -49,7 +51,7 @@ protected DynamicObject makeGeneric(VirtualFrame frame, Object[] alreadyExecuted
}
}

return Layouts.ARRAY.createArray(getContext().getCoreLibrary().getArrayFactory(), executedValues, executedValues.length);
return allocateObjectNode.allocate(getContext().getCoreLibrary().getArrayClass(), executedValues, executedValues.length);
}

@Override
@@ -88,7 +90,7 @@ public EmptyArrayLiteralNode(RubyContext context, SourceSection sourceSection, R

@Override
public Object execute(VirtualFrame frame) {
return Layouts.ARRAY.createArray(getContext().getCoreLibrary().getArrayFactory(), null, 0);
return allocateObjectNode.allocate(getContext().getCoreLibrary().getArrayClass(), null, 0);
}

}
@@ -112,7 +114,7 @@ public Object execute(VirtualFrame frame) {
}
}

return Layouts.ARRAY.createArray(getContext().getCoreLibrary().getArrayFactory(), executedValues, values.length);
return allocateObjectNode.allocate(getContext().getCoreLibrary().getArrayClass(), executedValues, values.length);
}

private DynamicObject makeGeneric(VirtualFrame frame,
@@ -147,7 +149,7 @@ public Object execute(VirtualFrame frame) {
}
}

return Layouts.ARRAY.createArray(getContext().getCoreLibrary().getArrayFactory(), executedValues, values.length);
return allocateObjectNode.allocate(getContext().getCoreLibrary().getArrayClass(), executedValues, values.length);
}

private DynamicObject makeGeneric(VirtualFrame frame,
@@ -182,7 +184,7 @@ public Object execute(VirtualFrame frame) {
}
}

return Layouts.ARRAY.createArray(getContext().getCoreLibrary().getArrayFactory(), executedValues, values.length);
return allocateObjectNode.allocate(getContext().getCoreLibrary().getArrayClass(), executedValues, values.length);
}

private DynamicObject makeGeneric(VirtualFrame frame,
@@ -213,7 +215,7 @@ public Object execute(VirtualFrame frame) {
executedValues[n] = values[n].execute(frame);
}

return Layouts.ARRAY.createArray(getContext().getCoreLibrary().getArrayFactory(), executedValues, values.length);
return allocateObjectNode.allocate(getContext().getCoreLibrary().getArrayClass(), executedValues, values.length);
}

}
@@ -235,7 +237,7 @@ public Object execute(VirtualFrame frame) {
executedValues[n] = values[n].execute(frame);
}

final DynamicObject array = Layouts.ARRAY.createArray(getContext().getCoreLibrary().getArrayFactory(), storeSpecialisedFromObjects(executedValues), executedValues.length);
final DynamicObject array = allocateObjectNode.allocate(getContext().getCoreLibrary().getArrayClass(), storeSpecialisedFromObjects(executedValues), executedValues.length);
final Object store = Layouts.ARRAY.getStore(array);

if (store == null) {
Original file line number Diff line number Diff line change
@@ -32,6 +32,11 @@ public MemsizeOfNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
}

@Specialization(guards = "isNil(nil)")
public int memsizeOf(Object nil) {
return 0;
}

@Specialization
public int memsizeOf(boolean object) {
return 0;
@@ -67,7 +72,13 @@ public int memsizeOfString(DynamicObject object) {
return 1 + object.getShape().getPropertyListInternal(false).size() + Layouts.STRING.getByteList(object).getRealSize();
}

@Specialization(guards = {"!isRubyArray(object)", "!isRubyHash(object)", "!isRubyString(object)"})
@Specialization(guards = "isRubyMatchData(object)")
public int memsizeOfMatchData(DynamicObject object) {
return 1 + object.getShape().getPropertyListInternal(false).size() + Layouts.MATCH_DATA.getValues(object).length;
}

@Specialization(guards = {"!isNil(object)", "!isRubyArray(object)", "!isRubyHash(object)",
"!isRubyString(object)", "!isRubyMatchData(object)"})
public int memsizeOfObject(DynamicObject object) {
return 1 + object.getShape().getPropertyListInternal(false).size();
}
Original file line number Diff line number Diff line change
@@ -13,6 +13,8 @@
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.api.source.SourceSection;
import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.nodes.objects.AllocateObjectNode;
import org.jruby.truffle.nodes.objects.AllocateObjectNodeGen;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.layouts.Layouts;
import org.jruby.util.ByteList;
@@ -23,17 +25,19 @@ public class StringLiteralNode extends RubyNode {
private final ByteList bytes;
private final int codeRange;

@Child private AllocateObjectNode allocateObjectNode;

public StringLiteralNode(RubyContext context, SourceSection sourceSection, ByteList bytes, int codeRange) {
super(context, sourceSection);
assert bytes != null;
this.bytes = bytes;
this.codeRange = codeRange;
allocateObjectNode = AllocateObjectNodeGen.create(context, sourceSection, false, null, null);
}

@Override
public DynamicObject execute(VirtualFrame frame) {
final DynamicObject string = Layouts.STRING.createString(getContext().getCoreLibrary().getStringFactory(), bytes.dup(), codeRange, null);
return string;
return allocateObjectNode.allocate(getContext().getCoreLibrary().getStringClass(), bytes.dup(), codeRange, null);
}

}
Original file line number Diff line number Diff line change
@@ -16,6 +16,9 @@
import com.oracle.truffle.api.dsl.NodeChild;
import com.oracle.truffle.api.dsl.NodeChildren;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.frame.Frame;
import com.oracle.truffle.api.frame.FrameInstance;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.nodes.Node;
import com.oracle.truffle.api.nodes.RootNode;
import com.oracle.truffle.api.object.DynamicObject;
@@ -25,6 +28,7 @@
import org.jruby.RubyString;
import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.nodes.RubyRootNode;
import org.jruby.truffle.runtime.RubyArguments;
import org.jruby.truffle.runtime.RubyCallStack;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.control.RaiseException;
@@ -37,8 +41,15 @@
})
public abstract class AllocateObjectNode extends RubyNode {

private final boolean useCallerFrame;

public AllocateObjectNode(RubyContext context, SourceSection sourceSection) {
this(context, sourceSection, true);
}

public AllocateObjectNode(RubyContext context, SourceSection sourceSection, boolean useCallerFrame) {
super(context, sourceSection);
this.useCallerFrame = useCallerFrame;
}

public DynamicObject allocate(DynamicObject classToAllocate, Object... values) {
@@ -49,7 +60,8 @@ public DynamicObject allocate(DynamicObject classToAllocate, Object... values) {

@Specialization(guards = {
"cachedClassToAllocate == classToAllocate",
"!cachedIsSingleton"
"!cachedIsSingleton",
"!isTracing()"
}, assumptions = "getTracingAssumption()", limit = "getCacheLimit()")
public DynamicObject allocateCached(
DynamicObject classToAllocate,
@@ -63,34 +75,41 @@ public DynamicObject allocateCached(
@CompilerDirectives.TruffleBoundary
@Specialization(
contains = "allocateCached",
guards = "!isSingleton(classToAllocate)",
guards = {"!isSingleton(classToAllocate)", "!isTracing()"},
assumptions = "getTracingAssumption()")
public DynamicObject allocateUncached(DynamicObject classToAllocate, Object[] values) {
return getInstanceFactory(classToAllocate).newInstance(values);
}

@CompilerDirectives.TruffleBoundary
@Specialization(guards = {"!isSingleton(classToAllocate)", "isTracing()"})
@Specialization(guards = {"!isSingleton(classToAllocate)", "isTracing()"},
assumptions = "getTracingAssumption()")
public DynamicObject allocateTracing(DynamicObject classToAllocate, Object[] values) {
final DynamicObject object = getInstanceFactory(classToAllocate).newInstance(values);

final Node caller = RubyCallStack.getTopMostUserCallNode();
final SourceSection callerSource = caller.getEncapsulatingSourceSection();
final FrameInstance allocatingFrameInstance;
final Node allocatingNode;

final String callerMethod;

if (caller.getRootNode() instanceof RubyRootNode) {
callerMethod = ((RubyRootNode) caller.getRootNode()).getSharedMethodInfo().getName();
if (useCallerFrame) {
allocatingFrameInstance = RubyCallStack.getCallerFrame(getContext());
allocatingNode = RubyCallStack.getTopMostUserCallNode();
} else {
callerMethod = "(unknown)";
allocatingFrameInstance = Truffle.getRuntime().getCurrentFrame();
allocatingNode = this;
}

final Frame allocatingFrame = allocatingFrameInstance.getFrame(FrameInstance.FrameAccess.READ_ONLY, true);

final Object allocatingSelf = RubyArguments.getSelf(allocatingFrame.getArguments());
final String allocatingMethod = RubyArguments.getMethod(allocatingFrame.getArguments()).getName();
final SourceSection allocatingSourceSection = allocatingNode.getEncapsulatingSourceSection();

getContext().getObjectSpaceManager().traceAllocation(
object,
string(Layouts.CLASS.getFields(classToAllocate).getName()),
string(callerMethod),
string(callerSource.getSource().getShortName()),
callerSource.getStartLine());
string(Layouts.CLASS.getFields(getContext().getCoreLibrary().getLogicalClass(allocatingSelf)).getName()),
getSymbol(allocatingMethod),
string(allocatingSourceSection.getSource().getName()),
allocatingSourceSection.getStartLine());

return object;
}
@@ -114,7 +133,7 @@ protected Assumption getTracingAssumption() {
}

protected boolean isTracing() {
return !getContext().getObjectSpaceManager().getTracingAssumption().isValid();
return getContext().getObjectSpaceManager().isTracing();
}

protected boolean isSingleton(DynamicObject classToAllocate) {
Original file line number Diff line number Diff line change
@@ -12,7 +12,9 @@
import com.oracle.truffle.api.Assumption;
import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.api.utilities.AssumedValue;
import com.oracle.truffle.api.utilities.CyclicAssumption;
import org.jruby.RubyGC;
import org.jruby.truffle.nodes.core.ThreadNodes;
import org.jruby.truffle.nodes.dispatch.CallDispatchHeadNode;
import org.jruby.truffle.runtime.RubyContext;
@@ -59,6 +61,7 @@ public void clearFinalizers() {
private DynamicObject finalizerThread;

private final CyclicAssumption tracingAssumption = new CyclicAssumption("objspace-tracing");
@CompilerDirectives.CompilationFinal private boolean isTracing = false;
private int tracingAssumptionActivations = 0;
private boolean tracingPaused = false;

@@ -146,14 +149,16 @@ public void traceAllocationsStart() {
tracingAssumptionActivations++;

if (tracingAssumptionActivations == 1) {
tracingAssumption.getAssumption().invalidate();
isTracing = true;
tracingAssumption.invalidate();
}
}

public void traceAllocationsStop() {
tracingAssumptionActivations--;

if (tracingAssumptionActivations == 0) {
isTracing = false;
tracingAssumption.invalidate();
}
}
@@ -166,7 +171,7 @@ public void traceAllocation(DynamicObject object, DynamicObject classPath, Dynam
tracingPaused = true;

try {
context.send(context.getCoreLibrary().getObjectSpaceModule(), "trace_allocation", null, object, classPath, methodId, sourcefile, sourceline);
context.send(context.getCoreLibrary().getObjectSpaceModule(), "trace_allocation", null, object, classPath, methodId, sourcefile, sourceline, RubyGC.getCollectionCount());
} finally {
tracingPaused = false;
}
@@ -176,4 +181,8 @@ public Assumption getTracingAssumption() {
return tracingAssumption.getAssumption();
}

public boolean isTracing() {
return isTracing;
}

}
Loading