-
-
Notifications
You must be signed in to change notification settings - Fork 925
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #3321 from jruby/truffle-objspace
[Truffle] Implement objspace.
- 9.4.12.0
- 9.4.11.0
- 9.4.10.0
- 9.4.9.0
- 9.4.8.0
- 9.4.7.0
- 9.4.6.0
- 9.4.5.0
- 9.4.4.0
- 9.4.3.0
- 9.4.2.0
- 9.4.1.0
- 9.4.0.0
- 9.3.15.0
- 9.3.14.0
- 9.3.13.0
- 9.3.12.0
- 9.3.11.0
- 9.3.10.0
- 9.3.9.0
- 9.3.8.0
- 9.3.7.0
- 9.3.6.0
- 9.3.5.0
- 9.3.4.0
- 9.3.3.0
- 9.3.2.0
- 9.3.1.0
- 9.3.0.0
- 9.2.21.0
- 9.2.20.1
- 9.2.20.0
- 9.2.19.0
- 9.2.18.0
- 9.2.17.0
- 9.2.16.0
- 9.2.15.0
- 9.2.14.0
- 9.2.13.0
- 9.2.12.0
- 9.2.11.1
- 9.2.11.0
- 9.2.10.0
- 9.2.9.0
- 9.2.8.0
- 9.2.7.0
- 9.2.6.0
- 9.2.5.0
- 9.2.4.1
- 9.2.4.0
- 9.2.3.0
- 9.2.2.0
- 9.2.1.0
- 9.2.0.0
- 9.1.17.0
- 9.1.16.0
- 9.1.15.0
- 9.1.14.0
- 9.1.13.0
- 9.1.12.0
- 9.1.11.0
- 9.1.10.0
- 9.1.9.0
- 9.1.8.0
- 9.1.7.0
- 9.1.6.0
- 9.1.5.0
- 9.1.4.0
- 9.1.3.0
- 9.1.2.0
- 9.1.1.0
- 9.1.0.0
- 9.0.5.0
- 9.0.4.0
- 9.0.3.0
Showing
19 changed files
with
827 additions
and
193 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,253 @@ | ||
# Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved. This | ||
# code is released under a tri EPL/GPL/LGPL license. You can use it, | ||
# redistribute it and/or modify it under the terms of the: | ||
# | ||
# Eclipse Public License version 1.0 | ||
# GNU General Public License version 2 | ||
# GNU Lesser General Public License version 2.1 | ||
|
||
require 'json' | ||
require 'tempfile' | ||
require 'weakref' | ||
|
||
module ObjectSpace | ||
|
||
def count_nodes(nodes = {}) | ||
ObjectSpace.each_object(Module) do |mod| | ||
mod.methods(false).each do |name| | ||
count_nodes_method mod.method(name), nodes | ||
end | ||
|
||
mod.private_methods(false).each do |name| | ||
count_nodes_method mod.method(name), nodes | ||
end | ||
end | ||
|
||
ObjectSpace.each_object(Proc) do |proc| | ||
count_nodes_method proc, nodes | ||
end | ||
|
||
ObjectSpace.each_object(Method) do |method| | ||
count_nodes_method method, nodes | ||
end | ||
|
||
ObjectSpace.each_object(UnboundMethod) do |umethod| | ||
count_nodes_method umethod, nodes | ||
end | ||
|
||
nodes | ||
end | ||
|
||
module_function :count_nodes | ||
|
||
class << self | ||
|
||
def count_nodes_method(method, nodes) | ||
node_stack = [Truffle::Primitive.ast(method)] | ||
|
||
until node_stack.empty? | ||
node = node_stack.pop | ||
next if node.nil? | ||
|
||
name = node.first | ||
children = node.drop(1) | ||
nodes[name] ||= 0 | ||
nodes[name] += 1 | ||
node_stack.push(*children) | ||
end | ||
end | ||
private :count_nodes_method | ||
|
||
end | ||
|
||
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 unless klass.name.nil? | ||
total += per_klass | ||
end | ||
hash[:TOTAL] = total | ||
hash | ||
end | ||
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 | ||
|
||
def dump(object, output: :string) | ||
case output | ||
when :string | ||
json = { | ||
address: "0x" + object.object_id.to_s(16), | ||
class: "0x" + object.class.object_id.to_s(16), | ||
memsize: memsize_of(object), | ||
flags: { } | ||
} | ||
case object | ||
when String | ||
json.merge!({ | ||
type: "STRING", | ||
bytesize: object.bytesize, | ||
value: object, | ||
encoding: object.encoding.name | ||
}) | ||
when Array | ||
json.merge!({ | ||
type: "ARRAY", | ||
length: object.size | ||
}) | ||
when Hash | ||
json.merge!({ | ||
type: "HASH", | ||
size: object.size | ||
}) | ||
else | ||
json.merge!({ | ||
type: "OBJECT", | ||
length: object.instance_variables.size | ||
}) | ||
end | ||
JSON.generate(json) | ||
when :file | ||
f = Tempfile.new(['rubyobj', '.json']) | ||
f.write dump(object, output: :string) | ||
f.close | ||
f.path | ||
when :stdout | ||
puts dump(object, output: :string) | ||
nil | ||
end | ||
end | ||
module_function :dump | ||
|
||
def dump_all(output: :file) | ||
case output | ||
when :string | ||
objects = [] | ||
ObjectSpace.each_object do |object| | ||
objects.push dump(object) | ||
end | ||
objects.join("\n") | ||
when :file | ||
f = Tempfile.new(['ruby', '.json']) | ||
f.write dump_all(output: :string) | ||
f.close | ||
f.path | ||
when :stdout | ||
puts dump_all(output: :string) | ||
nil | ||
when IO | ||
output.write dump_all(output: :string) | ||
nil | ||
end | ||
end | ||
module_function :dump_all | ||
|
||
def memsize_of(object) | ||
Truffle::ObjSpace.memsize_of(object) | ||
end | ||
module_function :memsize_of | ||
|
||
def memsize_of_all(klass = BasicObject) | ||
total = 0 | ||
ObjectSpace.each_object(klass) do |object| | ||
total += ObjectSpace.memsize_of(object) | ||
end | ||
total | ||
end | ||
module_function :memsize_of_all | ||
|
||
def reachable_objects_from(object) | ||
Truffle::ObjSpace.adjacent_objects(object) | ||
end | ||
module_function :reachable_objects_from | ||
|
||
def reachable_objects_from_root | ||
{"roots" => Truffle::ObjSpace.root_objects} | ||
end | ||
module_function :reachable_objects_from_root | ||
|
||
def trace_object_allocations | ||
trace_object_allocations_start | ||
|
||
begin | ||
yield | ||
ensure | ||
trace_object_allocations_stop | ||
end | ||
end | ||
module_function :trace_object_allocations | ||
|
||
def trace_object_allocations_clear | ||
ALLOCATIONS.clear | ||
end | ||
module_function :trace_object_allocations_clear | ||
|
||
def trace_object_allocations_debug_start | ||
trace_object_allocations_start | ||
end | ||
module_function :trace_object_allocations_debug_start | ||
|
||
def trace_object_allocations_start | ||
Truffle::ObjSpace.trace_allocations_start | ||
end | ||
module_function :trace_object_allocations_start | ||
|
||
def trace_object_allocations_stop | ||
Truffle::ObjSpace.trace_allocations_stop | ||
end | ||
module_function :trace_object_allocations_stop | ||
|
||
def allocation_class_path(object) | ||
allocation = ALLOCATIONS[object] | ||
return nil if allocation.nil? | ||
allocation.class_path | ||
end | ||
module_function :allocation_class_path | ||
|
||
def allocation_generation(object) | ||
allocation = ALLOCATIONS[object] | ||
return nil if allocation.nil? | ||
allocation.generation | ||
end | ||
module_function :allocation_generation | ||
|
||
def allocation_method_id(object) | ||
allocation = ALLOCATIONS[object] | ||
return nil if allocation.nil? | ||
allocation.method_id | ||
end | ||
module_function :allocation_method_id | ||
|
||
def allocation_sourcefile(object) | ||
allocation = ALLOCATIONS[object] | ||
return nil if allocation.nil? | ||
allocation.sourcefile | ||
end | ||
module_function :allocation_sourcefile | ||
|
||
def allocation_sourceline(object) | ||
allocation = ALLOCATIONS[object] | ||
return nil if allocation.nil? | ||
allocation.sourceline | ||
end | ||
module_function :allocation_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, generation) | ||
ALLOCATIONS[object] = Allocation.new(class_path, method_id, sourcefile, sourceline, generation) | ||
end | ||
module_function :trace_allocation | ||
|
||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
152 changes: 152 additions & 0 deletions
152
truffle/src/main/java/org/jruby/truffle/nodes/ext/ObjSpaceNodes.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,152 @@ | ||
/* | ||
* Copyright (c) 2015 Oracle and/or its affiliates. All rights reserved. This | ||
* code is released under a tri EPL/GPL/LGPL license. You can use it, | ||
* redistribute it and/or modify it under the terms of the: | ||
* | ||
* Eclipse Public License version 1.0 | ||
* GNU General Public License version 2 | ||
* GNU Lesser General Public License version 2.1 | ||
*/ | ||
package org.jruby.truffle.nodes.ext; | ||
|
||
import com.oracle.truffle.api.CompilerDirectives; | ||
import com.oracle.truffle.api.dsl.Specialization; | ||
import com.oracle.truffle.api.object.DynamicObject; | ||
import com.oracle.truffle.api.source.SourceSection; | ||
import org.jruby.truffle.nodes.core.CoreClass; | ||
import org.jruby.truffle.nodes.core.CoreMethod; | ||
import org.jruby.truffle.nodes.core.CoreMethodArrayArgumentsNode; | ||
import org.jruby.truffle.runtime.RubyContext; | ||
import org.jruby.truffle.runtime.layouts.Layouts; | ||
import org.jruby.truffle.runtime.object.ObjectGraph; | ||
|
||
import java.util.Set; | ||
|
||
@CoreClass(name = "Truffle::ObjSpace") | ||
public abstract class ObjSpaceNodes { | ||
|
||
@CoreMethod(names = "memsize_of", isModuleFunction = true, required = 1) | ||
public abstract static class MemsizeOfNode extends CoreMethodArrayArgumentsNode { | ||
|
||
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; | ||
} | ||
|
||
@Specialization | ||
public int memsizeOf(int object) { | ||
return 0; | ||
} | ||
|
||
@Specialization | ||
public int memsizeOf(long object) { | ||
return 0; | ||
} | ||
|
||
@Specialization | ||
public int memsizeOf(double object) { | ||
return 0; | ||
} | ||
|
||
@Specialization(guards = "isRubyArray(object)") | ||
public int memsizeOfArray(DynamicObject object) { | ||
return 1 + object.getShape().getPropertyListInternal(false).size() + Layouts.ARRAY.getSize(object); | ||
} | ||
|
||
@Specialization(guards = "isRubyHash(object)") | ||
public int memsizeOfHash(DynamicObject object) { | ||
return 1 + object.getShape().getPropertyListInternal(false).size() + Layouts.HASH.getSize(object); | ||
} | ||
|
||
@Specialization(guards = "isRubyString(object)") | ||
public int memsizeOfString(DynamicObject object) { | ||
return 1 + object.getShape().getPropertyListInternal(false).size() + Layouts.STRING.getByteList(object).getRealSize(); | ||
} | ||
|
||
@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(); | ||
} | ||
|
||
} | ||
|
||
@CoreMethod(names = "adjacent_objects", isModuleFunction = true, required = 1) | ||
public abstract static class AdjacentObjectsNode extends CoreMethodArrayArgumentsNode { | ||
|
||
public AdjacentObjectsNode(RubyContext context, SourceSection sourceSection) { | ||
super(context, sourceSection); | ||
} | ||
|
||
@CompilerDirectives.TruffleBoundary | ||
@Specialization | ||
public DynamicObject adjacentObjects(DynamicObject object) { | ||
final Set<DynamicObject> objects = ObjectGraph.getAdjacentObjects(object); | ||
return Layouts.ARRAY.createArray(getContext().getCoreLibrary().getArrayFactory(), objects.toArray(), objects.size()); | ||
} | ||
|
||
} | ||
|
||
@CoreMethod(names = "root_objects", isModuleFunction = true) | ||
public abstract static class RootObjectsNode extends CoreMethodArrayArgumentsNode { | ||
|
||
public RootObjectsNode(RubyContext context, SourceSection sourceSection) { | ||
super(context, sourceSection); | ||
} | ||
|
||
@CompilerDirectives.TruffleBoundary | ||
@Specialization | ||
public DynamicObject rootObjects() { | ||
final Set<DynamicObject> objects = ObjectGraph.stopAndGetRootObjects(this, getContext()); | ||
return Layouts.ARRAY.createArray(getContext().getCoreLibrary().getArrayFactory(), objects.toArray(), objects.size()); | ||
} | ||
|
||
} | ||
|
||
@CoreMethod(names = "trace_allocations_start", isModuleFunction = true) | ||
public abstract static class TraceAllocationsStartNode extends CoreMethodArrayArgumentsNode { | ||
|
||
public TraceAllocationsStartNode(RubyContext context, SourceSection sourceSection) { | ||
super(context, sourceSection); | ||
} | ||
|
||
@CompilerDirectives.TruffleBoundary | ||
@Specialization | ||
public DynamicObject traceAllocationsStart() { | ||
getContext().getObjectSpaceManager().traceAllocationsStart(); | ||
return nil(); | ||
} | ||
|
||
} | ||
|
||
@CoreMethod(names = "trace_allocations_stop", isModuleFunction = true) | ||
public abstract static class TraceAllocationsStopNode extends CoreMethodArrayArgumentsNode { | ||
|
||
public TraceAllocationsStopNode(RubyContext context, SourceSection sourceSection) { | ||
super(context, sourceSection); | ||
} | ||
|
||
@CompilerDirectives.TruffleBoundary | ||
@Specialization | ||
public DynamicObject traceAllocationsStop() { | ||
getContext().getObjectSpaceManager().traceAllocationsStop(); | ||
return nil(); | ||
} | ||
|
||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
15 changes: 0 additions & 15 deletions
15
truffle/src/main/java/org/jruby/truffle/runtime/object/StopVisitingObjectsException.java
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters