Skip to content

Commit

Permalink
Showing 35 changed files with 284 additions and 672 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -76,6 +76,7 @@ tool/nailgun/ng
reference.txt
rubyspec_temp
.polyglot.pom.rb
tool/truffle/jruby_truffle_runner/jruby+truffle_runner-*.gem

# binaries
!bin/gem
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
9.0.1.0-SNAPSHOT
9.0.2.0-SNAPSHOT
2 changes: 1 addition & 1 deletion core/pom.xml
Original file line number Diff line number Diff line change
@@ -12,7 +12,7 @@ DO NOT MODIFIY - GENERATED CODE
<parent>
<groupId>org.jruby</groupId>
<artifactId>jruby-parent</artifactId>
<version>9.0.1.0-SNAPSHOT</version>
<version>9.0.2.0-SNAPSHOT</version>
</parent>
<artifactId>jruby-core</artifactId>
<name>JRuby Core</name>
3 changes: 2 additions & 1 deletion core/src/main/java/org/jruby/util/cli/Options.java
Original file line number Diff line number Diff line change
@@ -228,13 +228,14 @@ public class Options {

public static final Option<Integer> TRUFFLE_DEFAULT_CACHE = integer(TRUFFLE, "truffle.default_cache", 8, "Default size for caches.");

public static final Option<Integer> TRUFFLE_METHOD_LOOKUP_CACHE = integer(TRUFFLE, "truffle.method_lookup.cache", TRUFFLE_DEFAULT_CACHE.load(), "Constant lookup cache size");
public static final Option<Integer> TRUFFLE_METHOD_LOOKUP_CACHE = integer(TRUFFLE, "truffle.method_lookup.cache", TRUFFLE_DEFAULT_CACHE.load(), "Method lookup cache size");
public static final Option<Integer> TRUFFLE_DISPATCH_CACHE = integer(TRUFFLE, "truffle.dispatch.cache", TRUFFLE_DEFAULT_CACHE.load(), "Dispatch (various forms of method call) cache size.");
public static final Option<Integer> TRUFFLE_YIELD_CACHE = integer(TRUFFLE, "truffle.yield.cache", TRUFFLE_DEFAULT_CACHE.load(), "Yield cache size.");
public static final Option<Integer> TRUFFLE_METHOD_TO_PROC_CACHE = integer(TRUFFLE, "truffle.to_proc.cache", TRUFFLE_DEFAULT_CACHE.load(), "Method#to_proc cache size");
public static final Option<Integer> TRUFFLE_IS_A_CACHE = integer(TRUFFLE, "truffle.is_a.cache", TRUFFLE_DEFAULT_CACHE.load(), "Kernel#is_a? and #kind_of? cache size");
public static final Option<Integer> TRUFFLE_BIND_CACHE = integer(TRUFFLE, "truffle.bind.cache", TRUFFLE_DEFAULT_CACHE.load(), "Test for being able to bind a method to a module cache size");
public static final Option<Integer> TRUFFLE_CONSTANT_LOOKUP_CACHE = integer(TRUFFLE, "truffle.constant_lookup.cache", TRUFFLE_DEFAULT_CACHE.load(), "Constant lookup cache size");
public static final Option<Integer> TRUFFLE_FIELD_LOOKUP_CACHE = integer(TRUFFLE, "truffle.field_lookup.cache", TRUFFLE_DEFAULT_CACHE.load(), "Object field lookup cache size");
public static final Option<Integer> TRUFFLE_BINDING_LOCAL_VARIABLE_CACHE = integer(TRUFFLE, "truffle.binding_local_variable.cache", TRUFFLE_DEFAULT_CACHE.load(), "Binding#local_variable_get/set cache size");
public static final Option<Integer> TRUFFLE_SYMBOL_TO_PROC_CACHE = integer(TRUFFLE, "truffle.symbol_to_proc.cache", TRUFFLE_DEFAULT_CACHE.load(), "Symbol#to_proc cache size");
public static final Option<Integer> TRUFFLE_ALLOCATE_CLASS_CACHE = integer(TRUFFLE, "truffle.allocate_class.cache", TRUFFLE_DEFAULT_CACHE.load(), "Allocation size class cache size");
4 changes: 2 additions & 2 deletions lib/pom.xml
Original file line number Diff line number Diff line change
@@ -12,7 +12,7 @@ DO NOT MODIFIY - GENERATED CODE
<parent>
<groupId>org.jruby</groupId>
<artifactId>jruby-parent</artifactId>
<version>9.0.1.0-SNAPSHOT</version>
<version>9.0.2.0-SNAPSHOT</version>
</parent>
<artifactId>jruby-stdlib</artifactId>
<name>JRuby Lib Setup</name>
@@ -28,7 +28,7 @@ DO NOT MODIFIY - GENERATED CODE
<dependency>
<groupId>org.jruby</groupId>
<artifactId>jruby-core</artifactId>
<version>9.0.1.0-SNAPSHOT</version>
<version>9.0.2.0-SNAPSHOT</version>
<scope>test</scope>
</dependency>
<dependency>
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
@@ -16,7 +16,7 @@ DO NOT MODIFIY - GENERATED CODE
</parent>
<groupId>org.jruby</groupId>
<artifactId>jruby-parent</artifactId>
<version>9.0.1.0-SNAPSHOT</version>
<version>9.0.2.0-SNAPSHOT</version>
<packaging>pom</packaging>
<name>JRuby</name>
<description>JRuby is the effort to recreate the Ruby (http://www.ruby-lang.org) interpreter in Java.</description>
2 changes: 1 addition & 1 deletion spec/truffle/specs/truffle/substrate_spec.rb
Original file line number Diff line number Diff line change
@@ -11,7 +11,7 @@
describe "Truffle.substrate?" do

it "returns a Boolean value" do
Truffle.graal?.should be_true_or_false
Truffle.substrate?.should be_true_or_false
end

end
17 changes: 17 additions & 0 deletions tool/jt.rb
Original file line number Diff line number Diff line change
@@ -213,6 +213,7 @@ def help
puts 'jt findbugs run findbugs'
puts 'jt findbugs report run findbugs and generate an HTML report'
puts 'jt install ..../graal/mx/suite.py install a JRuby distribution into an mx suite'
puts 'jt install-tool install the jruby+truffle tool for working with Ruby gems'
puts
puts 'you can also put build or rebuild in front of any command'
puts
@@ -476,6 +477,22 @@ def install(arg)
raise ArgumentError, kind
end
end

def install_tool
Dir.chdir(JRUBY_DIR) do
Dir.chdir('tool/truffle/jruby_truffle_runner') do
raw_sh('gem', 'build', 'jruby+truffle_runner.gemspec')
raw_sh('gem', 'install', 'jruby+truffle_runner-0.0.1.gem')

begin
system('rbenv', 'rehash')
rescue
end
end
end
end

alias_method :"install-tool", :install_tool
end

class JT
51 changes: 36 additions & 15 deletions tool/truffle/jruby_truffle_runner/lib/jruby+truffle_runner.rb
Original file line number Diff line number Diff line change
@@ -10,6 +10,7 @@
require 'pp'
require 'yaml'
require 'fileutils'
require 'shellwords'

# TODO (pitr 01-Sep-2015): add pre stored run options combinations like -S irb, -I test

@@ -246,10 +247,11 @@ def subcommand_setup(rest)

execute_cmd 'gem install bundler' unless bundle_installed

execute_cmd ['bundle install --standalone',
"--path #{bundle_path}",
("--without #{@options[:setup][:without].join(' ')}" unless @options[:setup][:without].empty?)
].join(' ')
execute_cmd ['bundle',
'install',
'--standalone',
'--path', bundle_path,
*(['--without', @options[:setup][:without].join(' ')] unless @options[:setup][:without].empty?)]

link_path = "#{bundle_path}/jruby+truffle"
FileUtils.rm link_path if File.exist? link_path
@@ -277,31 +279,50 @@ def subcommand_run(rest)
('-X+T' unless @options[:run][:test]),
(format(@options[:global][:debug_option], @options[:global][:debug_port]) if @options[:run][:debug]),
('-Xtruffle.exceptions.print_java=true' if @options[:run][:jexception]),
"-r ./#{@options[:global][:truffle_bundle_path]}/bundler/setup.rb",
*@options[:run][:load_path].map { |v| '-I ' + v },
*@options[:run][:require].map { |v| '-r ' + v }
].compact.join(' ')
'-r', "./#{@options[:global][:truffle_bundle_path]}/bundler/setup.rb",
*@options[:run][:load_path].map { |v| ['-I', v] }.flatten,
*@options[:run][:require].map { |v| ['-r', v] }.flatten
].compact

cmd = [("JAVACMD=#{@options[:global][:graal_path]}" if @options[:run][:graal]),
env = {}
env['JAVACMD'] = @options[:global][:graal_path] if @options[:run][:graal]

cmd = [(env unless env.empty?),
@options[:global][:jruby_truffle_path],
cmd_options,
*cmd_options,
*rest
].compact.join(' ')
].compact

exit execute_cmd(cmd, fail: false, print_always: true)
execute_cmd(cmd, fail: false, print_always: true)
exit $?.exitstatus
end

def subcommand_clean(rest)
FileUtils.rm_rf @options[:global][:truffle_bundle_path]
end

def print_cmd(cmd, print_always)
puts '$ ' + cmd if verbose? || print_always
cmd
unless verbose? || print_always
return cmd
end

print = if String === cmd
cmd
else
cmd.map do |v|
if Hash === v
v.map { |k, v| "#{k}=#{v}" }.join(' ')
else
Shellwords.escape v
end
end.join(' ')
end
puts '$ ' + print
return cmd
end

def execute_cmd(cmd, fail: true, print_always: false)
result = system(print_cmd(cmd, print_always))
result = system(*print_cmd(cmd, print_always))
ensure
raise 'command failed' if fail && !result
end
8 changes: 3 additions & 5 deletions truffle/README.md
Original file line number Diff line number Diff line change
@@ -42,10 +42,8 @@ You can then run JRuby with GraalVM
JAVACMD=path/to/graal/java bin/jruby -X+T ...

If you want to develop against the latest version of Graal, you should use the
`truffle-head` branch of JRuby. Follow the
[instructions](https://wiki.openjdk.java.net/display/Graal/Instructions) on the
Graal wiki, then additionally execute `./mx.sh maven-install-truffle`, before
you build JRuby.
`truffle-head` branch of JRuby and you will need to
[build Graal for yourself](https://wiki.openjdk.java.net/display/Graal/Instructions).

### What to expect

@@ -55,7 +53,7 @@ run they are unlikely to run fast yet due to requiring new functionality to be
tuned. We are at least a year away from being able to run significant programs
without needing new methods to be implemented.

Windows support is more limited than Mac and Linux support.
Windows is currently not supported.

### How we benchmark

2 changes: 1 addition & 1 deletion truffle/pom.xml
Original file line number Diff line number Diff line change
@@ -12,7 +12,7 @@ DO NOT MODIFIY - GENERATED CODE
<parent>
<groupId>org.jruby</groupId>
<artifactId>jruby-parent</artifactId>
<version>9.0.1.0-SNAPSHOT</version>
<version>9.0.2.0-SNAPSHOT</version>
</parent>
<artifactId>jruby-truffle</artifactId>
<name>JRuby Truffle</name>
6 changes: 5 additions & 1 deletion truffle/src/main/java/org/jruby/truffle/nodes/RubyNode.java
Original file line number Diff line number Diff line change
@@ -219,9 +219,13 @@ protected Object ruby(VirtualFrame frame, String expression, Object... arguments

protected Object rubyWithSelf(VirtualFrame frame, Object self, String expression, Object... arguments) {
final MaterializedFrame evalFrame = setupFrame(RubyArguments.getSelf(frame.getArguments()), arguments);

final DynamicObject binding = Layouts.BINDING.createBinding(getContext().getCoreLibrary().getBindingFactory(), self, evalFrame);
return getContext().eval(expression, binding, true, "inline-ruby", this);
}

protected Object rubyWithSelf(Object self, String expression, Object... arguments) {
final MaterializedFrame evalFrame = setupFrame(self, arguments);
final DynamicObject binding = Layouts.BINDING.createBinding(getContext().getCoreLibrary().getBindingFactory(), self, evalFrame);
return getContext().eval(expression, binding, true, "inline-ruby", this);
}

Original file line number Diff line number Diff line change
@@ -51,7 +51,7 @@ public TaintResultNode(RubyContext context, SourceSection sourceSection) {
}

public Object maybeTaint(DynamicObject source, DynamicObject result) {
if (taintProfile.profile(isTaintedNode.isTainted(source))) {
if (taintProfile.profile(isTaintedNode.executeIsTainted(source))) {
if (taintNode == null) {
CompilerDirectives.transferToInterpreter();
taintNode = insert(TaintNodeGen.create(getContext(), getSourceSection(), null));
Original file line number Diff line number Diff line change
@@ -18,6 +18,7 @@
import org.jruby.RubyString;
import org.jruby.truffle.nodes.RubyGuards;
import org.jruby.truffle.nodes.objectstorage.ReadHeadObjectFieldNode;
import org.jruby.truffle.nodes.objectstorage.ReadHeadObjectFieldNodeGen;
import org.jruby.truffle.runtime.NotProvided;
import org.jruby.truffle.runtime.RubyCallStack;
import org.jruby.truffle.runtime.RubyContext;
@@ -91,13 +92,14 @@ public abstract static class BacktraceNode extends CoreMethodArrayArgumentsNode

public BacktraceNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
readCustomBacktrace = new ReadHeadObjectFieldNode("@custom_backtrace");
readCustomBacktrace = ReadHeadObjectFieldNodeGen.create(context, sourceSection, "@custom_backtrace", null, null);
}

@Specialization
public Object backtrace(DynamicObject exception) {
if (readCustomBacktrace.isSet(exception)) {
return readCustomBacktrace.execute(exception);
final Object customBacktrace = readCustomBacktrace.execute(exception);
if (customBacktrace != null) {
return customBacktrace;
} else if (Layouts.EXCEPTION.getBacktrace(exception) != null) {
return asRubyStringArray(exception);
} else {
Original file line number Diff line number Diff line change
@@ -1013,7 +1013,7 @@ public Object instanceVariableGetSymbol(DynamicObject object, DynamicObject name
}

private Object instanceVariableGet(DynamicObject object, String name) {
return object.get(RubyContext.checkInstanceVariableName(getContext(), name, this), Layouts.MODULE.getFields(Layouts.BASIC_OBJECT.getLogicalClass(object)).getContext().getCoreLibrary().getNilObject());
return object.get(RubyContext.checkInstanceVariableName(getContext(), name, this), nil());
}

}
Original file line number Diff line number Diff line change
@@ -12,6 +12,7 @@
import org.jruby.truffle.nodes.RubyGuards;
import org.jruby.truffle.nodes.dispatch.RespondToNode;
import org.jruby.truffle.nodes.objectstorage.ReadHeadObjectFieldNode;
import org.jruby.truffle.nodes.objectstorage.ReadHeadObjectFieldNodeGen;
import org.jruby.truffle.runtime.ModuleOperations;
import org.jruby.truffle.runtime.NotProvided;
import org.jruby.truffle.runtime.RubyContext;
@@ -29,6 +30,7 @@
import com.oracle.truffle.api.dsl.ImportStatic;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.nodes.UnexpectedResultException;
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.api.source.SourceSection;

@@ -73,8 +75,14 @@ public Object id2Ref(final VirtualFrame frame, final long id,
new ObjectGraph(getContext()).visitObjects(new ObjectGraphVisitor() {
@Override
public boolean visit(DynamicObject object) throws StopVisitingObjectsException {
final Object objectID = readObjectIdNode.execute(object);
if (objectID != nil() && (long) objectID == id) {
final long objectID;
try {
objectID = readObjectIdNode.executeLong(object);
} catch (UnexpectedResultException e) {
throw new UnsupportedOperationException(e);
}

if (objectID == id) {
result.set(object);
throw new StopVisitingObjectsException();
}
@@ -96,7 +104,7 @@ public double id2RefFloat(DynamicObject id) {
}

protected ReadHeadObjectFieldNode createReadObjectIDNode() {
return new ReadHeadObjectFieldNode(Layouts.OBJECT_ID_IDENTIFIER);
return ReadHeadObjectFieldNodeGen.create(getContext(), getSourceSection(), Layouts.OBJECT_ID_IDENTIFIER, 0L, null);
}

protected boolean isLargeFixnumID(DynamicObject id) {
Original file line number Diff line number Diff line change
@@ -10,22 +10,22 @@

package org.jruby.truffle.nodes.objects;

import com.oracle.truffle.api.CompilerDirectives;
import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.nodes.objectstorage.ReadHeadObjectFieldNode;
import org.jruby.truffle.nodes.objectstorage.ReadHeadObjectFieldNodeGen;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.layouts.Layouts;

import com.oracle.truffle.api.dsl.Cached;
import com.oracle.truffle.api.dsl.NodeChild;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.nodes.UnexpectedResultException;
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.objectstorage.ReadHeadObjectFieldNode;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.layouts.Layouts;

@NodeChild(value = "child")
public abstract class IsFrozenNode extends RubyNode {

@Child private ReadHeadObjectFieldNode readFrozenNode;

public IsFrozenNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
}
@@ -68,16 +68,16 @@ public boolean isFrozenSymbol(DynamicObject symbol) {
}

@Specialization(guards = { "!isNil(object)", "!isRubyBignum(object)", "!isRubySymbol(object)" })
public boolean isFrozen(DynamicObject object) {
if (readFrozenNode == null) {
CompilerDirectives.transferToInterpreter();
readFrozenNode = insert(new ReadHeadObjectFieldNode(Layouts.FROZEN_IDENTIFIER));
}

protected boolean isFrozen(DynamicObject object,
@Cached("createReadFrozenNode()") ReadHeadObjectFieldNode readFrozenNode) {
try {
return readFrozenNode.isSet(object) && readFrozenNode.executeBoolean(object);
return readFrozenNode.executeBoolean(object);
} catch (UnexpectedResultException e) {
throw new UnsupportedOperationException(readFrozenNode.execute(object).toString());
throw new UnsupportedOperationException(e);
}
}

protected ReadHeadObjectFieldNode createReadFrozenNode() {
return ReadHeadObjectFieldNodeGen.create(getContext(), getSourceSection(), Layouts.FROZEN_IDENTIFIER, false, null);
}
}
Original file line number Diff line number Diff line change
@@ -9,16 +9,18 @@
*/
package org.jruby.truffle.nodes.objects;

import com.oracle.truffle.api.CompilerDirectives;
import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.nodes.objectstorage.ReadHeadObjectFieldNode;
import org.jruby.truffle.nodes.objectstorage.ReadHeadObjectFieldNodeGen;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.layouts.Layouts;

import com.oracle.truffle.api.dsl.Cached;
import com.oracle.truffle.api.dsl.NodeChild;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.nodes.UnexpectedResultException;
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.objectstorage.ReadHeadObjectFieldNode;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.layouts.Layouts;

@NodeChild(value = "child", type = RubyNode.class)
public abstract class IsTaintedNode extends RubyNode {
@@ -52,17 +54,17 @@ public boolean isTainted(double object) {
}

@Specialization
public boolean isTainted(DynamicObject object) {
if (readTaintNode == null) {
CompilerDirectives.transferToInterpreter();
readTaintNode = insert(new ReadHeadObjectFieldNode(Layouts.TAINTED_IDENTIFIER));
}

protected boolean isTainted(DynamicObject object,
@Cached("createReadTaintedNode()") ReadHeadObjectFieldNode readTaintedNode) {
try {
return readTaintNode.isSet(object) && readTaintNode.executeBoolean(object);
return readTaintedNode.executeBoolean(object);
} catch (UnexpectedResultException e) {
throw new UnsupportedOperationException(readTaintNode.execute(object).toString());
throw new UnsupportedOperationException(e);
}
}

protected ReadHeadObjectFieldNode createReadTaintedNode() {
return ReadHeadObjectFieldNodeGen.create(getContext(), getSourceSection(), Layouts.TAINTED_IDENTIFIER, false, null);
}

}
Original file line number Diff line number Diff line change
@@ -17,10 +17,12 @@
import com.oracle.truffle.api.object.Shape;
import com.oracle.truffle.api.source.SourceSection;
import com.oracle.truffle.api.utilities.BranchProfile;

import org.jcodings.specific.UTF8Encoding;
import org.jruby.RubyString;
import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.nodes.objectstorage.ReadHeadObjectFieldNode;
import org.jruby.truffle.nodes.objectstorage.ReadHeadObjectFieldNodeGen;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.layouts.Layouts;
import org.jruby.truffle.translator.ReadNode;
@@ -37,7 +39,7 @@ public class ReadInstanceVariableNode extends RubyNode implements ReadNode {
public ReadInstanceVariableNode(RubyContext context, SourceSection sourceSection, String name, RubyNode receiver, boolean isGlobal) {
super(context, sourceSection);
this.receiver = receiver;
readNode = new ReadHeadObjectFieldNode(name);
readNode = ReadHeadObjectFieldNodeGen.create(context, sourceSection, name, nil(), null);
this.isGlobal = isGlobal;
}

@@ -102,14 +104,8 @@ public Object isDefined(VirtualFrame frame) {
if (isGlobal) {
final DynamicObject receiverValue = (DynamicObject) receiver.execute(frame);

if (readNode.getName().equals("$~") || readNode.getName().equals("$!")) {
if (readNode.getName().equals("$~") || readNode.getName().equals("$!") || readNode.execute(receiverValue) != nil()) {
return Layouts.STRING.createString(getContext().getCoreLibrary().getStringFactory(), RubyString.encodeBytelist("global-variable", UTF8Encoding.INSTANCE), StringSupport.CR_7BIT, null);
} else if (readNode.isSet(receiverValue)) {
if (readNode.execute(receiverValue) == nil()) {
return nil();
} else {
return Layouts.STRING.createString(getContext().getCoreLibrary().getStringFactory(), RubyString.encodeBytelist("global-variable", UTF8Encoding.INSTANCE), StringSupport.CR_7BIT, null);
}
} else {
return nil();
}

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -9,46 +9,146 @@
*/
package org.jruby.truffle.nodes.objectstorage;

import com.oracle.truffle.api.nodes.Node;
import org.jruby.truffle.nodes.RubyNode;
import org.jruby.truffle.runtime.RubyContext;

import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.api.dsl.Cached;
import com.oracle.truffle.api.dsl.NodeChild;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.nodes.UnexpectedResultException;
import com.oracle.truffle.api.object.BooleanLocation;
import com.oracle.truffle.api.object.DoubleLocation;
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.api.object.IntLocation;
import com.oracle.truffle.api.object.LongLocation;
import com.oracle.truffle.api.object.Property;
import com.oracle.truffle.api.object.Shape;
import com.oracle.truffle.api.source.SourceSection;

public class ReadHeadObjectFieldNode extends Node {

private final Object name;
@Child private ReadObjectFieldNode first;
@NodeChild("receiver")
public abstract class ReadHeadObjectFieldNode extends RubyNode {
private final Object defaultValue;
protected final Object name;

public ReadHeadObjectFieldNode(Object name) {
public ReadHeadObjectFieldNode(RubyContext context, SourceSection sourceSection, Object name, Object defaultValue) {
super(context, sourceSection);
this.name = name;
first = new UninitializedReadObjectFieldNode(name);
this.defaultValue = defaultValue;
}

public boolean executeBoolean(DynamicObject object) throws UnexpectedResultException {
return first.executeBoolean(object);
public Object getName() {
return name;
}

public int executeInteger(DynamicObject object) throws UnexpectedResultException {
return first.executeInteger(object);
public abstract boolean executeBoolean(DynamicObject object) throws UnexpectedResultException;
public abstract int executeInteger(DynamicObject object) throws UnexpectedResultException;
public abstract long executeLong(DynamicObject object) throws UnexpectedResultException;
public abstract double executeDouble(DynamicObject object) throws UnexpectedResultException;

public abstract Object execute(DynamicObject object);

@Specialization(
guards = { "location != null", "receiver.getShape() == cachedShape" },
assumptions = "cachedShape.getValidAssumption()",
limit = "getCacheLimit()")
protected boolean readBooleanObjectFieldCached(DynamicObject receiver,
@Cached("receiver.getShape()") Shape cachedShape,
@Cached("getBooleanLocation(cachedShape)") BooleanLocation location) {
return location.getBoolean(receiver, cachedShape);
}

public long executeLong(DynamicObject object) throws UnexpectedResultException {
return first.executeLong(object);
@Specialization(
guards = { "location != null", "receiver.getShape() == cachedShape" },
assumptions = "cachedShape.getValidAssumption()",
limit = "getCacheLimit()")
protected int readIntObjectFieldCached(DynamicObject receiver,
@Cached("receiver.getShape()") Shape cachedShape,
@Cached("getIntLocation(cachedShape)") IntLocation location) {
return location.getInt(receiver, cachedShape);
}

public double executeDouble(DynamicObject object) throws UnexpectedResultException {
return first.executeDouble(object);
@Specialization(
guards = { "location != null", "receiver.getShape() == cachedShape" },
assumptions = "cachedShape.getValidAssumption()",
limit = "getCacheLimit()")
protected long readLongObjectFieldCached(DynamicObject receiver,
@Cached("receiver.getShape()") Shape cachedShape,
@Cached("getLongLocation(cachedShape)") LongLocation location) {
return location.getLong(receiver, cachedShape);
}

public Object execute(DynamicObject object) {
return first.execute(object);
@Specialization(
guards = { "location != null", "receiver.getShape() == cachedShape" },
assumptions = "cachedShape.getValidAssumption()",
limit = "getCacheLimit()")
protected double readDoubleObjectFieldCached(DynamicObject receiver,
@Cached("receiver.getShape()") Shape cachedShape,
@Cached("getDoubleLocation(cachedShape)") DoubleLocation location) {
return location.getDouble(receiver, cachedShape);
}

public Object getName() {
return name;
@Specialization(
guards = "receiver.getShape() == cachedShape",
assumptions = "cachedShape.getValidAssumption()",
limit = "getCacheLimit()",
contains = { "readBooleanObjectFieldCached", "readIntObjectFieldCached", "readLongObjectFieldCached", "readDoubleObjectFieldCached" })
protected Object readObjectFieldCached(DynamicObject receiver,
@Cached("receiver.getShape()") Shape cachedShape,
@Cached("cachedShape.getProperty(name)") Property property) {
if (property != null) {
return property.get(receiver, cachedShape);
} else {
return defaultValue;
}
}

@TruffleBoundary
@Specialization
protected Object readObjectFieldUncached(DynamicObject receiver) {
final Shape shape = receiver.getShape();
final Property property = shape.getProperty(name);
if (property != null) {
return property.get(receiver, shape);
} else {
return defaultValue;
}
}

protected BooleanLocation getBooleanLocation(Shape shape) {
final Property property = shape.getProperty(name);
if (property != null && property.getLocation() instanceof BooleanLocation) {
return (BooleanLocation) property.getLocation();
}
return null;
}

protected IntLocation getIntLocation(Shape shape) {
final Property property = shape.getProperty(name);
if (property != null && property.getLocation() instanceof IntLocation) {
return (IntLocation) property.getLocation();
}
return null;
}

protected LongLocation getLongLocation(Shape shape) {
final Property property = shape.getProperty(name);
if (property != null && property.getLocation() instanceof LongLocation) {
return (LongLocation) property.getLocation();
}
return null;
}

protected DoubleLocation getDoubleLocation(Shape shape) {
final Property property = shape.getProperty(name);
if (property != null && property.getLocation() instanceof DoubleLocation) {
return (DoubleLocation) property.getLocation();
}
return null;
}

public boolean isSet(DynamicObject object) {
return first.isSet(object);
protected int getCacheLimit() {
return getContext().getOptions().FIELD_LOOKUP_CACHE;
}

}

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -262,23 +262,26 @@ public Object readIfAvailable(DynamicObject file, int numberOfBytes) {
// Taken from Rubinius's IO::read_if_available.

if (numberOfBytes == 0) {
return Layouts.STRING.createString(getContext().getCoreLibrary().getStringFactory(), new ByteList(), StringSupport.CR_UNKNOWN, null);
return Layouts.STRING.createString(getContext().getCoreLibrary().getStringFactory(),
new ByteList(), StringSupport.CR_UNKNOWN, null);
}

final int fd = Layouts.IO.getDescriptor(file);

final FDSet fdSet = fdSetFactory.create();
fdSet.set(fd);

final Pointer timeout = jnr.ffi.Runtime.getSystemRuntime().getMemoryManager().allocateDirect(8 * 2); // Needs to be two longs.
// TODO CS 2-Sep-15 why are longs 8 bytes? Is that always the case?
final Pointer timeout = getContext().getMemoryManager().allocateDirect(8 * 2); // Needs to be two longs.
timeout.putLong(0, 0);
timeout.putLong(8, 0);

final int res = nativeSockets().select(fd + 1, fdSet.getPointer(), PointerNodes.NULL_POINTER, PointerNodes.NULL_POINTER, timeout);
final int res = nativeSockets().select(fd + 1, fdSet.getPointer(),
PointerNodes.NULL_POINTER, PointerNodes.NULL_POINTER, timeout);

if (res == 0) {
CompilerDirectives.transferToInterpreter();
throw new RaiseException(getContext().getCoreLibrary().errnoError(Errno.EAGAIN.intValue(), this));
rubyWithSelf(file, "IO::EAGAINWaitReadable.new");
}

if (res < 0) {
@@ -295,10 +298,12 @@ public Object readIfAvailable(DynamicObject file, int numberOfBytes) {
}

if (bytesRead == 0) {
return Layouts.STRING.createString(getContext().getCoreLibrary().getStringFactory(), new ByteList(), StringSupport.CR_UNKNOWN, null);
return Layouts.STRING.createString(getContext().getCoreLibrary().getStringFactory(),
new ByteList(), StringSupport.CR_UNKNOWN, null);
}

return Layouts.STRING.createString(getContext().getCoreLibrary().getStringFactory(), new ByteList(bytes), StringSupport.CR_UNKNOWN, null);
return Layouts.STRING.createString(getContext().getCoreLibrary().getStringFactory(),
new ByteList(bytes), StringSupport.CR_UNKNOWN, null);
}

}
Original file line number Diff line number Diff line change
@@ -13,14 +13,17 @@
import com.oracle.truffle.api.dsl.Cached;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.nodes.UnexpectedResultException;
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.api.source.SourceSection;
import com.oracle.truffle.api.utilities.ConditionProfile;

import org.jruby.truffle.nodes.objects.IsTaintedNode;
import org.jruby.truffle.nodes.objects.IsTaintedNodeGen;
import org.jruby.truffle.nodes.objects.TaintNode;
import org.jruby.truffle.nodes.objects.TaintNodeGen;
import org.jruby.truffle.nodes.objectstorage.ReadHeadObjectFieldNode;
import org.jruby.truffle.nodes.objectstorage.ReadHeadObjectFieldNodeGen;
import org.jruby.truffle.nodes.objectstorage.WriteHeadObjectFieldNode;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.layouts.Layouts;
@@ -41,17 +44,17 @@ public ObjectIDPrimitiveNode(RubyContext context, SourceSection sourceSection) {
public abstract Object executeObjectID(VirtualFrame frame, Object value);

@Specialization(guards = "isNil(nil)")
public int objectID(Object nil) {
public long objectID(Object nil) {
return ObjectIDOperations.NIL;
}

@Specialization(guards = "value")
public int objectIDTrue(boolean value) {
public long objectIDTrue(boolean value) {
return ObjectIDOperations.TRUE;
}

@Specialization(guards = "!value")
public int objectIDFalse(boolean value) {
public long objectIDFalse(boolean value) {
return ObjectIDOperations.FALSE;
}

@@ -84,9 +87,14 @@ public Object objectID(double value) {
public long objectID(DynamicObject object,
@Cached("createReadObjectIDNode()") ReadHeadObjectFieldNode readObjectIdNode,
@Cached("createWriteObjectIDNode()") WriteHeadObjectFieldNode writeObjectIdNode) {
final Object id = readObjectIdNode.execute(object);
final long id;
try {
id = readObjectIdNode.executeLong(object);
} catch (UnexpectedResultException e) {
throw new UnsupportedOperationException(e);
}

if (id == nil()) {
if (id == 0) {
final long newId = getContext().getNextObjectID();
writeObjectIdNode.execute(object, newId);
return newId;
@@ -96,7 +104,7 @@ public long objectID(DynamicObject object,
}

protected ReadHeadObjectFieldNode createReadObjectIDNode() {
return new ReadHeadObjectFieldNode(Layouts.OBJECT_ID_IDENTIFIER);
return ReadHeadObjectFieldNodeGen.create(getContext(), getSourceSection(), Layouts.OBJECT_ID_IDENTIFIER, 0L, null);
}

protected WriteHeadObjectFieldNode createWriteObjectIDNode() {
Original file line number Diff line number Diff line change
@@ -15,9 +15,12 @@
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.api.object.HiddenKey;
import com.oracle.truffle.api.source.SourceSection;

import jnr.posix.FileStat;

import org.jruby.RubyEncoding;
import org.jruby.truffle.nodes.objectstorage.ReadHeadObjectFieldNode;
import org.jruby.truffle.nodes.objectstorage.ReadHeadObjectFieldNodeGen;
import org.jruby.truffle.nodes.objectstorage.WriteHeadObjectFieldNode;
import org.jruby.truffle.runtime.RubyContext;
import org.jruby.truffle.runtime.layouts.Layouts;
@@ -249,7 +252,7 @@ public static abstract class StatReadPrimitiveNode extends RubiniusPrimitiveNode

public StatReadPrimitiveNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
readStatNode = new ReadHeadObjectFieldNode(STAT_IDENTIFIER);
readStatNode = ReadHeadObjectFieldNodeGen.create(getContext(), getSourceSection(), STAT_IDENTIFIER, null, null);
}

public FileStat getStat(DynamicObject rubyStat) {
Original file line number Diff line number Diff line change
@@ -35,6 +35,7 @@ public class Options {
public final int IS_A_CACHE = org.jruby.util.cli.Options.TRUFFLE_IS_A_CACHE.load();
public final int BIND_CACHE = org.jruby.util.cli.Options.TRUFFLE_BIND_CACHE.load();
public final int CONSTANT_LOOKUP_CACHE = org.jruby.util.cli.Options.TRUFFLE_CONSTANT_LOOKUP_CACHE.load();
public final int FIELD_LOOKUP_CACHE = org.jruby.util.cli.Options.TRUFFLE_FIELD_LOOKUP_CACHE.load();
public final int BINDING_LOCAL_VARIABLE_CACHE = org.jruby.util.cli.Options.TRUFFLE_BINDING_LOCAL_VARIABLE_CACHE.load();
public final int SYMBOL_TO_PROC_CACHE = org.jruby.util.cli.Options.TRUFFLE_SYMBOL_TO_PROC_CACHE.load();
public final int ALLOCATE_CLASS_CACHE = org.jruby.util.cli.Options.TRUFFLE_ALLOCATE_CLASS_CACHE.load();
Original file line number Diff line number Diff line change
@@ -21,6 +21,7 @@
import com.oracle.truffle.api.source.SourceSection;
import com.oracle.truffle.tools.CoverageTracker;
import jnr.ffi.LibraryLoader;
import jnr.ffi.provider.MemoryManager;
import jnr.posix.POSIX;
import jnr.posix.POSIXFactory;
import org.jcodings.Encoding;
@@ -72,6 +73,7 @@
import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.atomic.AtomicLong;
import jnr.ffi.Runtime;

/**
* The global state of a running Ruby system.
@@ -86,6 +88,7 @@ public class RubyContext extends ExecutionContext implements TruffleContextInter

private final POSIX posix;
private final NativeSockets nativeSockets;
private final MemoryManager memoryManager = Runtime.getSystemRuntime().getMemoryManager();

private final CoreLibrary coreLibrary;
private final FeatureLoader featureLoader;
@@ -695,4 +698,7 @@ public Options getOptions() {
return options;
}

public MemoryManager getMemoryManager() {
return memoryManager;
}
}
Original file line number Diff line number Diff line change
@@ -40,10 +40,10 @@
*/
public abstract class ObjectIDOperations {

public static final int FALSE = 0;
public static final int TRUE = 2;
public static final int NIL = 4;
public static final int FIRST_OBJECT_ID = 6;
public static final long FALSE = 0;
public static final long TRUE = 2;
public static final long NIL = 4;
public static final long FIRST_OBJECT_ID = 6;

private static final BigInteger LARGE_FIXNUM_FLAG = BigInteger.ONE.shiftLeft(64);
private static final BigInteger FLOAT_FLAG = BigInteger.ONE.shiftLeft(65);

0 comments on commit 59bfc0b

Please sign in to comment.