Skip to content

Commit

Permalink
Showing 42 changed files with 3,900 additions and 3,285 deletions.
1 change: 1 addition & 0 deletions bin/jruby-cext-c
Original file line number Diff line number Diff line change
@@ -46,6 +46,7 @@ LL = []
SRC.each do |src|
ll = File.join(File.dirname(src), File.basename(src, '.*') + '.ll')
mx 'su-clang', "-I#{SULONG_DIR}/include", '-Ilib/ruby/truffle/cext', '-S', '-emit-llvm', src, '-o', ll
mx 'su-opt', '-S', '-mem2reg', ll, '-o', ll
LL.push ll
end

38 changes: 38 additions & 0 deletions ci.hocon
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
java7: {name: oraclejdk, version: "8u66", platformspecific: true}

common: {
packages: {
git : ">=1.8.3"
maven : ">=3.3.9"
ruby : ">=2.1.0"
}

downloads: {
JAVA_HOME: ${java7}
}

environment: {
PATH: "$JAVA_HOME/bin:$PATH"
}

setup: [
[ruby, "tool/jt.rb", build]
]

timelimit: "30:00"
}

gate_caps: {
capabilities: [linux, amd64, gate]
}

jt: [ruby, "tool/jt.rb"]

builds = [
{name: "ruby-test-fast"} ${common} ${gate_caps} {run: [${jt} [test, fast]]},
{name: "ruby-test-specs-command-line"} ${common} ${gate_caps} {run: [${jt} [test, specs, ":command_line"]]},
{name: "ruby-test-specs-language"} ${common} ${gate_caps} {run: [${jt} [test, specs, ":language"]]},
{name: "ruby-test-specs-core"} ${common} ${gate_caps} {run: [${jt} [test, specs, ":core"]]},
{name: "ruby-test-specs-library"} ${common} ${gate_caps} {run: [${jt} [test, specs, ":library"]]},
{name: "ruby-test-specs-truffle"} ${common} ${gate_caps} {run: [${jt} [test, specs, ":truffle"]]}
]
2 changes: 1 addition & 1 deletion lib/ruby/truffle/cext/ruby.h
Original file line number Diff line number Diff line change
@@ -106,7 +106,7 @@ VALUE rb_define_module_under(VALUE module, const char *name);

void rb_define_method(VALUE module, const char *name, void *function, int args);
void rb_define_private_method(VALUE module, const char *name, void *function, int args);
int rb_define_module_function(VALUE module, const char *name, void *function, int args);
void rb_define_module_function(VALUE module, const char *name, void *function, int args);

#if defined(__cplusplus)
}
Binary file modified lib/ruby/truffle/cext/ruby.su
Binary file not shown.
4 changes: 2 additions & 2 deletions lib/ruby/truffle/jruby+truffle/bin/jruby+truffle
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/usr/bin/env ruby

require_relative '../lib/runner.rb'
require_relative '../lib/truffle/runner.rb'

runner = JRubyTruffleRunner.new ARGV
runner = Truffle::Runner.new ARGV
exit runner.run
23 changes: 2 additions & 21 deletions lib/ruby/truffle/jruby+truffle/gem_configurations/activemodel.yaml
Original file line number Diff line number Diff line change
@@ -136,27 +136,7 @@
:test_validates_presence_of_finds_global_default_key_translation_when_blank],
NumericalityValidationTest: [:test_validates_numericality_with_equal_to] }
undefine = if ENV['CI']
failures
else
{}
end
undefine.each do |mod_name, tests|
unless Object.const_defined? mod_name
warn "#{mod_name} not found"
next
end
mod = Object.const_get mod_name
Array(tests).each do |test|
begin
puts "Undefining: #{mod}##{test}"
mod.send :undef_method, test
rescue NoMethodError => e
p e
end
end
end
Truffle.exclude_rspec_examples failures
# do not let bundler to install db gem group
:without:
@@ -166,5 +146,6 @@
- rubygems
- shims
- openssl-stubs
- truffle/exclude_rspec_examples
:environment:
N: 1
Original file line number Diff line number Diff line change
@@ -60,27 +60,7 @@
TimeZoneTest: :test_map_srednekolymsk_to_tzinfo }
undefine = if ENV['CI']
failures
else
{}
end
undefine.each do |mod_name, tests|
unless Object.const_defined? mod_name
warn "#{mod_name} not found"
next
end
mod = Object.const_get mod_name
Array(tests).each do |test|
begin
puts "Undefining: #{mod}##{test}"
mod.send :undef_method, test
rescue NoMethodError => e
p e
end
end
end
Truffle.exclude_rspec_examples failures
# do not let bundler to install db gem group
:without:
@@ -93,5 +73,6 @@
- bigdecimal
- pathname
- openssl-stubs
- truffle/exclude_rspec_examples
:environment:
N: 1
716 changes: 0 additions & 716 deletions lib/ruby/truffle/jruby+truffle/lib/runner.rb

This file was deleted.

720 changes: 720 additions & 0 deletions lib/ruby/truffle/jruby+truffle/lib/truffle/runner.rb

Large diffs are not rendered by default.

10 changes: 8 additions & 2 deletions test/truffle/integration/rails-app.sh
Original file line number Diff line number Diff line change
@@ -14,6 +14,12 @@ then

else

if [ -f tmp/pids/server.pid ]
then
kill $(cat tmp/pids/server.pid) || true
rm tmp/pids/server.pid
fi

$JRUBY $JRUBY_BIN/gem install bundler

$JTR setup
@@ -23,8 +29,8 @@ else

while ! curl -s "$url/people.json";
do
echo -n .
sleep 1
echo -n .
sleep 1
done

echo Server is up
29 changes: 11 additions & 18 deletions tool/jt.rb
Original file line number Diff line number Diff line change
@@ -61,14 +61,9 @@ def self.find_graal
end

def self.find_sulong_graal(dir)
jvmci = File.join(dir, '..', 'jvmci')
Dir.entries(jvmci).each do |entry|
child = File.join(jvmci, entry)
if File.directory?(child) && entry.start_with?('jdk')
return File.join(child, 'product', 'bin', 'java')
end
end
raise "couldn't find the Java build in the Sulong repository - you need to check it out and build it"
jvmci = File.expand_path("../jvmci", dir)
Dir["#{jvmci}/jdk*/product/bin/java"].first or
raise "couldn't find the Java build in the Sulong repository - you need to check it out and build it"
end

def self.find_graal_js
@@ -406,12 +401,10 @@ def run(*args)
if args.delete('--sulong')
dir = Utilities.find_sulong_dir
env_vars["JAVACMD"] = Utilities.find_sulong_graal(dir)
jruby_args << '-J-classpath'
jruby_args << File.join(dir, 'lib', '*')
jruby_args << '-J-classpath'
jruby_args << File.join(dir, 'build', 'sulong.jar')
jruby_args << '-J-classpath'
jruby_args << File.join(dir, '..', 'graal-core', 'mxbuild', 'graal', 'com.oracle.nfi', 'bin')
jruby_args << '-J-classpath' << "#{dir}/lib/*"
jruby_args << '-J-classpath' << "#{dir}/build/sulong.jar"
nfi_classes = File.expand_path('../graal-core/mxbuild/graal/com.oracle.nfi/bin', dir)
jruby_args << '-J-classpath' << nfi_classes
jruby_args << '-J-XX:-UseJVMCIClassLoader'
end

@@ -472,7 +465,7 @@ def test(*args)
test_tck
test_specs('run')
# test_mri # TODO (pitr-ch 29-Mar-2016): temporarily disabled
test_integration({'CI' => 'true', 'HAS_REDIS' => 'true'}, 'all')
test_integration({'HAS_REDIS' => 'true'}, 'all')
test_compiler
test_cexts if ENV['SULONG_DIR']
when 'compiler' then test_compiler(*rest)
@@ -538,8 +531,8 @@ def test_cexts(*args)
Dir["#{JRUBY_DIR}/test/truffle/cexts/*"].each do |dir|
sh Utilities.find_jruby, "#{JRUBY_DIR}/bin/jruby-cext-c", dir
name = File.basename(dir)
run '--sulong', '-I', File.join(dir, 'lib'), File.join(dir, 'bin', name), :out => output_file
unless File.read(output_file) == File.read(File.join(dir, 'expected.txt'))
run '--sulong', '-I', "#{dir}/lib", "#{dir}/bin/#{name}", :out => output_file
unless File.read(output_file) == File.read("#{dir}/expected.txt")
abort "c extension #{dir} didn't work as expected"
end
end
@@ -570,7 +563,7 @@ def test_integration(env, *args)

env_vars["PATH"] = "#{Utilities.find_jruby_bin_dir}:#{ENV["PATH"]}"
integration_path = "#{JRUBY_DIR}/test/truffle/integration"
long_tests = File.read(File.join(integration_path, 'long-tests.txt')).lines.map(&:chomp)
long_tests = File.read("#{integration_path}/long-tests.txt").lines.map(&:chomp)
single_test = !args.empty?
test_names = single_test ? '{' + args.join(',') + '}' : '*'

4 changes: 2 additions & 2 deletions truffle/src/main/c/cext/ruby.c
Original file line number Diff line number Diff line change
@@ -217,6 +217,6 @@ void rb_define_private_method(VALUE module, const char *name, void *function, in
truffle_invoke(RUBY_CEXT, "rb_define_private_method", module, truffle_read_string(name), function, args);
}

int rb_define_module_function(VALUE module, const char *name, void *function, int args) {
return truffle_invoke_i(RUBY_CEXT, "rb_define_module_function", module, truffle_read_string(name), function, args);
void rb_define_module_function(VALUE module, const char *name, void *function, int args) {
truffle_invoke(RUBY_CEXT, "rb_define_module_function", module, truffle_read_string(name), truffle_address_to_function(function), args);
}
14 changes: 7 additions & 7 deletions truffle/src/main/java/org/jruby/truffle/core/CoreLibrary.java
Original file line number Diff line number Diff line change
@@ -100,14 +100,14 @@
import org.jruby.truffle.language.parser.ParserContext;
import org.jruby.truffle.platform.RubiniusTypes;
import org.jruby.truffle.platform.signal.SignalManager;
import org.jruby.truffle.stdlib.BigDecimalNodesFactory;
import org.jruby.truffle.stdlib.bigdecimal.BigDecimalNodesFactory;
import org.jruby.truffle.stdlib.CoverageNodesFactory;
import org.jruby.truffle.stdlib.digest.DigestNodesFactory;
import org.jruby.truffle.stdlib.EtcNodesFactory;
import org.jruby.truffle.stdlib.ObjSpaceNodesFactory;
import org.jruby.truffle.stdlib.digest.DigestNodesFactory;
import org.jruby.truffle.stdlib.psych.PsychEmitterNodesFactory;
import org.jruby.truffle.stdlib.psych.PsychParserNodes;
import org.jruby.truffle.stdlib.psych.PsychParserNodesFactory;
import org.jruby.truffle.stdlib.psych.YAMLEncoding;
import org.jruby.util.cli.OutputStrings;

import java.io.File;
@@ -823,10 +823,10 @@ private void initializeConstants() {
Layouts.MODULE.getFields(encodingConverterClass).setConstant(context, node, "XML_ATTR_CONTENT_DECORATOR", EConvFlags.XML_ATTR_CONTENT_DECORATOR);
Layouts.MODULE.getFields(encodingConverterClass).setConstant(context, node, "XML_ATTR_QUOTE_DECORATOR", EConvFlags.XML_ATTR_QUOTE_DECORATOR);

Layouts.MODULE.getFields(psychParserClass).setConstant(context, node, "ANY", PsychParserNodes.YAMLEncoding.YAML_ANY_ENCODING.ordinal());
Layouts.MODULE.getFields(psychParserClass).setConstant(context, node, "UTF8", PsychParserNodes.YAMLEncoding.YAML_UTF8_ENCODING.ordinal());
Layouts.MODULE.getFields(psychParserClass).setConstant(context, node, "UTF16LE", PsychParserNodes.YAMLEncoding.YAML_UTF16LE_ENCODING.ordinal());
Layouts.MODULE.getFields(psychParserClass).setConstant(context, node, "UTF16BE", PsychParserNodes.YAMLEncoding.YAML_UTF16BE_ENCODING.ordinal());
Layouts.MODULE.getFields(psychParserClass).setConstant(context, node, "ANY", YAMLEncoding.YAML_ANY_ENCODING.ordinal());
Layouts.MODULE.getFields(psychParserClass).setConstant(context, node, "UTF8", YAMLEncoding.YAML_UTF8_ENCODING.ordinal());
Layouts.MODULE.getFields(psychParserClass).setConstant(context, node, "UTF16LE", YAMLEncoding.YAML_UTF16LE_ENCODING.ordinal());
Layouts.MODULE.getFields(psychParserClass).setConstant(context, node, "UTF16BE", YAMLEncoding.YAML_UTF16BE_ENCODING.ordinal());

// Java interop
final DynamicObject javaModule = defineModule(truffleModule, "Java");
4 changes: 2 additions & 2 deletions truffle/src/main/java/org/jruby/truffle/core/Layouts.java
Original file line number Diff line number Diff line change
@@ -82,8 +82,8 @@
import org.jruby.truffle.core.time.TimeLayoutImpl;
import org.jruby.truffle.core.tracepoint.TracePointLayout;
import org.jruby.truffle.core.tracepoint.TracePointLayoutImpl;
import org.jruby.truffle.stdlib.BigDecimalLayout;
import org.jruby.truffle.stdlib.BigDecimalLayoutImpl;
import org.jruby.truffle.stdlib.bigdecimal.BigDecimalLayout;
import org.jruby.truffle.stdlib.bigdecimal.BigDecimalLayoutImpl;
import org.jruby.truffle.stdlib.digest.DigestLayout;
import org.jruby.truffle.stdlib.digest.DigestLayoutImpl;
import org.jruby.truffle.stdlib.psych.EmitterLayout;
Original file line number Diff line number Diff line change
@@ -520,6 +520,22 @@ public DynamicObject floatDomainError(String value, Node currentNode) {
context.getCallStack().getBacktrace(currentNode));
}

public DynamicObject floatDomainErrorResultsToNaN(Node currentNode) {
return floatDomainError("Computation results to 'NaN'(Not a Number)", currentNode);
}

public DynamicObject floatDomainErrorResultsToInfinity(Node currentNode) {
return floatDomainError("Computation results to 'Infinity'", currentNode);
}

public DynamicObject floatDomainErrorResultsToNegInfinity(Node currentNode) {
return floatDomainError("Computation results to '-Infinity'", currentNode);
}

public DynamicObject floatDomainErrorSqrtNegative(Node currentNode) {
return floatDomainError("(VpSqrt) SQRT(negative value)", currentNode);
}

// IOError

@TruffleBoundary
Original file line number Diff line number Diff line change
@@ -28,6 +28,10 @@ public static FixnumOrBignumNode create(RubyContext context, SourceSection sourc
return new FixnumOrBignumNode(context, sourceSection);
}

public FixnumOrBignumNode() {
this(null, null);
}

public FixnumOrBignumNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
}
60 changes: 58 additions & 2 deletions truffle/src/main/java/org/jruby/truffle/debug/DebugHelpers.java
Original file line number Diff line number Diff line change
@@ -12,20 +12,76 @@
import com.oracle.truffle.api.CompilerAsserts;
import com.oracle.truffle.api.Truffle;
import com.oracle.truffle.api.frame.Frame;
import com.oracle.truffle.api.frame.FrameDescriptor;
import com.oracle.truffle.api.frame.FrameInstance;
import com.oracle.truffle.api.frame.MaterializedFrame;
import com.oracle.truffle.api.source.Source;
import org.jcodings.specific.UTF8Encoding;
import org.jruby.truffle.RubyContext;
import org.jruby.truffle.core.string.StringOperations;
import org.jruby.truffle.language.RubyRootNode;
import org.jruby.truffle.language.arguments.RubyArguments;
import org.jruby.truffle.language.loader.CodeLoader;
import org.jruby.truffle.language.methods.DeclarationContext;
import org.jruby.truffle.language.parser.ParserContext;

@SuppressWarnings("deprecation")
@Deprecated
public abstract class DebugHelpers {

@Deprecated
public static Object eval(String code, Object... arguments) {
return eval(RubyContext.getLatestInstance(), code, arguments);
}

@Deprecated
public static Object eval(RubyContext context, String code, Object... arguments) {
CompilerAsserts.neverPartOfCompilation();
final FrameInstance currentFrameInstance = Truffle.getRuntime().getCurrentFrame();

final Frame currentFrame = currentFrameInstance.getFrame(FrameInstance.FrameAccess.MATERIALIZE, true);
return context.getCodeLoader().inline(null, currentFrame, code, arguments);

final Object[] packedArguments = RubyArguments.pack(
null,
null,
RubyArguments.getMethod(currentFrame),
DeclarationContext.INSTANCE_EVAL,
null,
RubyArguments.getSelf(currentFrame),
null,
new Object[]{});

final FrameDescriptor frameDescriptor = new FrameDescriptor(currentFrame.getFrameDescriptor().getDefaultValue());

final MaterializedFrame evalFrame = Truffle.getRuntime().createMaterializedFrame(
packedArguments,
frameDescriptor);

if (arguments.length % 2 == 1) {
throw new UnsupportedOperationException("odd number of name-value pairs for arguments");
}

for (int n = 0; n < arguments.length; n += 2) {
evalFrame.setObject(evalFrame.getFrameDescriptor().findOrAddFrameSlot(arguments[n]), arguments[n + 1]);
}

final Source source = Source.fromText(StringOperations.createByteList(code), "debug-eval");

final RubyRootNode rootNode = context.getCodeLoader().parse(
source,
UTF8Encoding.INSTANCE,
ParserContext.INLINE,
evalFrame,
true,
null);

final CodeLoader.DeferredCall deferredCall = context.getCodeLoader().prepareExecute(
ParserContext.INLINE,
DeclarationContext.INSTANCE_EVAL,
rootNode,
evalFrame,
RubyArguments.getSelf(evalFrame));

return deferredCall.callWithoutCallNode();
}

}
24 changes: 11 additions & 13 deletions truffle/src/main/java/org/jruby/truffle/interop/CExtNodes.java
Original file line number Diff line number Diff line change
@@ -10,16 +10,14 @@
package org.jruby.truffle.interop;

import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.source.SourceSection;
import org.jruby.truffle.RubyContext;
import org.jruby.truffle.core.CoreClass;
import org.jruby.truffle.core.CoreMethod;
import org.jruby.truffle.core.CoreMethodArrayArgumentsNode;

@CoreClass(name = "Truffle::CExt")
public class CExtNodes {

@CoreMethod(names = "NUM2INT", isModuleFunction = true, needsSelf = false)
@CoreMethod(names = "NUM2INT", isModuleFunction = true, needsSelf = false, required = 1)
public abstract static class NUM2INTNode extends CoreMethodArrayArgumentsNode {

@Specialization
@@ -29,7 +27,7 @@ public int num2int(int num) {

}

@CoreMethod(names = "NUM2UINT", isModuleFunction = true, needsSelf = false)
@CoreMethod(names = "NUM2UINT", isModuleFunction = true, needsSelf = false, required = 1)
public abstract static class NUM2UINTNode extends CoreMethodArrayArgumentsNode {

@Specialization
@@ -40,7 +38,7 @@ public int num2uint(int num) {

}

@CoreMethod(names = "NUM2LONG", isModuleFunction = true, needsSelf = false)
@CoreMethod(names = "NUM2LONG", isModuleFunction = true, needsSelf = false, required = 1)
public abstract static class NUM2LONGNode extends CoreMethodArrayArgumentsNode {

@Specialization
@@ -50,7 +48,7 @@ public long num2long(int num) {

}

@CoreMethod(names = "FIX2INT", isModuleFunction = true, needsSelf = false)
@CoreMethod(names = "FIX2INT", isModuleFunction = true, needsSelf = false, required = 1)
public abstract static class FIX2INTNode extends CoreMethodArrayArgumentsNode {

@Specialization
@@ -60,7 +58,7 @@ public int fix2int(int num) {

}

@CoreMethod(names = "FIX2UINT", isModuleFunction = true, needsSelf = false)
@CoreMethod(names = "FIX2UINT", isModuleFunction = true, needsSelf = false, required = 1)
public abstract static class FIX2UINTNode extends CoreMethodArrayArgumentsNode {

@Specialization
@@ -71,7 +69,7 @@ public int fix2uint(int num) {

}

@CoreMethod(names = "FIX2LONG", isModuleFunction = true, needsSelf = false)
@CoreMethod(names = "FIX2LONG", isModuleFunction = true, needsSelf = false, required = 1)
public abstract static class FIX2LONGNode extends CoreMethodArrayArgumentsNode {

@Specialization
@@ -81,7 +79,7 @@ public long fix2long(int num) {

}

@CoreMethod(names = "INT2NUM", isModuleFunction = true, needsSelf = false)
@CoreMethod(names = "INT2NUM", isModuleFunction = true, needsSelf = false, required = 1)
public abstract static class INT2NUMNode extends CoreMethodArrayArgumentsNode {

@Specialization
@@ -91,7 +89,7 @@ public int int2num(int num) {

}

@CoreMethod(names = "INT2FIX", isModuleFunction = true, needsSelf = false)
@CoreMethod(names = "INT2FIX", isModuleFunction = true, needsSelf = false, required = 1)
public abstract static class INT2FIXNode extends CoreMethodArrayArgumentsNode {

@Specialization
@@ -101,7 +99,7 @@ public int int2fix(int num) {

}

@CoreMethod(names = "UINT2NUM", isModuleFunction = true, needsSelf = false)
@CoreMethod(names = "UINT2NUM", isModuleFunction = true, needsSelf = false, required = 1)
public abstract static class UINT2NUMNode extends CoreMethodArrayArgumentsNode {

@Specialization
@@ -112,7 +110,7 @@ public int uint2num(int num) {

}

@CoreMethod(names = "LONG2NUM", isModuleFunction = true, needsSelf = false)
@CoreMethod(names = "LONG2NUM", isModuleFunction = true, needsSelf = false, required = 1)
public abstract static class LONG2NUMNode extends CoreMethodArrayArgumentsNode {

@Specialization
@@ -122,7 +120,7 @@ public int long2num(int num) {

}

@CoreMethod(names = "LONG2FIX", isModuleFunction = true, needsSelf = false)
@CoreMethod(names = "LONG2FIX", isModuleFunction = true, needsSelf = false, required = 1)
public abstract static class LONG2FIXNode extends CoreMethodArrayArgumentsNode {

@Specialization
Original file line number Diff line number Diff line change
@@ -28,6 +28,7 @@
import org.jruby.truffle.core.numeric.BignumOperations;
import org.jruby.truffle.core.rope.CodeRange;
import org.jruby.truffle.core.rope.Rope;
import org.jruby.truffle.core.rope.RopeOperations;
import org.jruby.truffle.core.string.CoreStrings;
import org.jruby.truffle.core.string.StringOperations;
import org.jruby.truffle.extra.AttachmentsManager;
@@ -89,6 +90,10 @@ protected DynamicObject createString(ByteList bytes) {
return StringOperations.createString(getContext(), bytes);
}

protected DynamicObject createString(byte[] bytes, Encoding encoding) {
return StringOperations.createString(getContext(), RopeOperations.create(bytes, encoding, CodeRange.CR_7BIT));
}

protected DynamicObject create7BitString(CharSequence value, Encoding encoding) {
return StringOperations.createString(getContext(), StringOperations.encodeRope(value, encoding, CodeRange.CR_7BIT));
}
Original file line number Diff line number Diff line change
@@ -19,6 +19,7 @@
import org.jruby.truffle.core.array.ArrayUtils;
import org.jruby.truffle.language.RubyGuards;
import org.jruby.truffle.language.RubyNode;
import org.jruby.truffle.language.SnippetNode;

public class ReadRestArgumentNode extends RubyNode {

@@ -30,6 +31,7 @@ public class ReadRestArgumentNode extends RubyNode {
private final BranchProfile subsetOfArgumentsProfile = BranchProfile.create();

@Child private ReadUserKeywordsHashNode readUserKeywordsHashNode;
@Child private SnippetNode snippetNode = new SnippetNode();

public ReadRestArgumentNode(RubyContext context, SourceSection sourceSection, int startIndex, int indexFromCount,
boolean keywordArguments, int minimumForKWargs) {
@@ -89,7 +91,7 @@ public Object execute(VirtualFrame frame) {
kwargsHash = nil();
}

getContext().getCodeLoader().inline(this,
snippetNode.execute(frame,
"Truffle.add_rejected_kwargs_to_rest(rest, kwargs)",
"rest", rest,
"kwargs", kwargsHash);
Original file line number Diff line number Diff line change
@@ -14,6 +14,10 @@

public class DoesRespondDispatchHeadNode extends DispatchHeadNode {

public static DoesRespondDispatchHeadNode create() {
return new DoesRespondDispatchHeadNode(null, false);
}

public DoesRespondDispatchHeadNode(RubyContext context, boolean ignoreVisibility) {
super(context, ignoreVisibility, MissingBehavior.RETURN_MISSING, DispatchAction.RESPOND_TO_METHOD);
}
Original file line number Diff line number Diff line change
@@ -100,57 +100,6 @@ public DeferredCall prepareExecute(ParserContext parserContext,
new Object[]{}));
}

@TruffleBoundary
public Object inline(Node currentNode, String expression, Object... arguments) {
final Frame frame = Truffle.getRuntime().getCurrentFrame().getFrame(FrameInstance.FrameAccess.MATERIALIZE, true);
return inline(currentNode, frame, expression, arguments);
}

public Object inline(Node currentNode, Frame frame, String expression, Object... arguments) {
final Object[] packedArguments = RubyArguments.pack(
null,
null,
RubyArguments.getMethod(frame),
DeclarationContext.INSTANCE_EVAL,
null,
RubyArguments.getSelf(frame),
null,
new Object[]{});

final FrameDescriptor frameDescriptor = new FrameDescriptor(frame.getFrameDescriptor().getDefaultValue());

final MaterializedFrame evalFrame = Truffle.getRuntime().createMaterializedFrame(
packedArguments,
frameDescriptor);

if (arguments.length % 2 == 1) {
throw new UnsupportedOperationException("odd number of name-value pairs for arguments");
}

for (int n = 0; n < arguments.length; n += 2) {
evalFrame.setObject(evalFrame.getFrameDescriptor().findOrAddFrameSlot(arguments[n]), arguments[n + 1]);
}

final Source source = Source.fromText(StringOperations.createByteList(expression), "inline-ruby");

final RubyRootNode rootNode = context.getCodeLoader().parse(
source,
UTF8Encoding.INSTANCE,
ParserContext.INLINE,
evalFrame,
true,
currentNode);

final DeferredCall deferredCall = context.getCodeLoader().prepareExecute(
ParserContext.INLINE,
DeclarationContext.INSTANCE_EVAL,
rootNode,
evalFrame,
RubyArguments.getSelf(evalFrame));

return deferredCall.callWithoutCallNode();
}

public static class DeferredCall {

private final CallTarget callTarget;
2,145 changes: 0 additions & 2,145 deletions truffle/src/main/java/org/jruby/truffle/stdlib/BigDecimalNodes.java

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* Copyright (c) 2013, 2016 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.stdlib.bigdecimal;

import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.object.DynamicObject;
import org.jruby.truffle.core.Layouts;

import java.math.BigDecimal;
import java.math.MathContext;

public abstract class AbstractAddNode extends BigDecimalOpNode {

@CompilerDirectives.TruffleBoundary
private BigDecimal addBigDecimal(DynamicObject a, DynamicObject b, MathContext mathContext) {
return Layouts.BIG_DECIMAL.getValue(a).add(Layouts.BIG_DECIMAL.getValue(b), mathContext);
}

protected Object add(VirtualFrame frame, DynamicObject a, DynamicObject b, int precision) {
return createBigDecimal(frame, addBigDecimal(a, b, new MathContext(precision, getRoundMode(frame))));
}

protected Object addSpecial(VirtualFrame frame, DynamicObject a, DynamicObject b, int precision) {
final BigDecimalType aType = Layouts.BIG_DECIMAL.getType(a);
final BigDecimalType bType = Layouts.BIG_DECIMAL.getType(b);

if (aType == BigDecimalType.NAN || bType == BigDecimalType.NAN ||
(aType == BigDecimalType.POSITIVE_INFINITY && bType == BigDecimalType.NEGATIVE_INFINITY) ||
(aType == BigDecimalType.NEGATIVE_INFINITY && bType == BigDecimalType.POSITIVE_INFINITY)) {
return createBigDecimal(frame, BigDecimalType.NAN);
}

if (aType == BigDecimalType.POSITIVE_INFINITY || bType == BigDecimalType.POSITIVE_INFINITY) {
return createBigDecimal(frame, BigDecimalType.POSITIVE_INFINITY);
}

if (aType == BigDecimalType.NEGATIVE_INFINITY || bType == BigDecimalType.NEGATIVE_INFINITY) {
return createBigDecimal(frame, BigDecimalType.NEGATIVE_INFINITY);
}

// one is NEGATIVE_ZERO and second is NORMAL
if (isNormal(a)) {
return a;
} else {
return b;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
/*
* Copyright (c) 2013, 2016 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.stdlib.bigdecimal;

import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.api.profiles.ConditionProfile;
import org.jruby.truffle.core.Layouts;

import java.math.BigDecimal;
import java.math.MathContext;

public abstract class AbstractDivNode extends BigDecimalOpNode {

private final ConditionProfile normalZero = ConditionProfile.createBinaryProfile();

private Object divBigDecimalWithProfile(DynamicObject a, DynamicObject b, MathContext mathContext) {
final BigDecimal aBigDecimal = Layouts.BIG_DECIMAL.getValue(a);
final BigDecimal bBigDecimal = Layouts.BIG_DECIMAL.getValue(b);
if (normalZero.profile(bBigDecimal.signum() == 0)) {
switch (aBigDecimal.signum()) {
case 1:
return BigDecimalType.POSITIVE_INFINITY;
case 0:
return BigDecimalType.NAN;
case -1:
return BigDecimalType.NEGATIVE_INFINITY;
default:
throw new UnsupportedOperationException("unreachable code branch for value: " + aBigDecimal.signum());
}
} else {
return divBigDecimal(aBigDecimal, bBigDecimal, mathContext);
}
}

@CompilerDirectives.TruffleBoundary
private BigDecimal divBigDecimal(BigDecimal a, BigDecimal b, MathContext mathContext) {
return a.divide(b, mathContext);
}

protected Object div(VirtualFrame frame, DynamicObject a, DynamicObject b, int precision) {
return createBigDecimal(frame, divBigDecimalWithProfile(a, b, new MathContext(precision, getRoundMode(frame))));
}

protected Object divNormalSpecial(VirtualFrame frame, DynamicObject a, DynamicObject b, int precision) {
switch (Layouts.BIG_DECIMAL.getType(b)) {
case NAN:
return createBigDecimal(frame, BigDecimalType.NAN);
case NEGATIVE_ZERO:
switch (Layouts.BIG_DECIMAL.getValue(a).signum()) {
case 1:
return createBigDecimal(frame, BigDecimalType.NEGATIVE_INFINITY);
case 0:
return createBigDecimal(frame, BigDecimalType.NAN);
case -1:
return createBigDecimal(frame, BigDecimalType.POSITIVE_INFINITY);
}
case POSITIVE_INFINITY:
switch (Layouts.BIG_DECIMAL.getValue(a).signum()) {
case 1:
case 0:
return createBigDecimal(frame, BigDecimal.ZERO);
case -1:
return createBigDecimal(frame, BigDecimalType.NEGATIVE_ZERO);
}
case NEGATIVE_INFINITY:
switch (Layouts.BIG_DECIMAL.getValue(b).signum()) {
case 1:
return createBigDecimal(frame, BigDecimalType.NEGATIVE_ZERO);
case 0:
case -1:
return createBigDecimal(frame, BigDecimal.ZERO);
}
default:
throw new UnsupportedOperationException("unreachable code branch for value: " + Layouts.BIG_DECIMAL.getType(b));
}
}

protected Object divSpecialNormal(VirtualFrame frame, DynamicObject a, DynamicObject b, int precision) {
switch (Layouts.BIG_DECIMAL.getType(a)) {
case NAN:
return createBigDecimal(frame, BigDecimalType.NAN);
case NEGATIVE_ZERO:
switch (Layouts.BIG_DECIMAL.getValue(b).signum()) {
case 1:
return createBigDecimal(frame, BigDecimalType.NEGATIVE_ZERO);
case 0:
return createBigDecimal(frame, BigDecimalType.NAN);
case -1:
return createBigDecimal(frame, BigDecimal.ZERO);
}
case POSITIVE_INFINITY:
switch (Layouts.BIG_DECIMAL.getValue(b).signum()) {
case 1:
case 0:
return createBigDecimal(frame, BigDecimalType.POSITIVE_INFINITY);
case -1:
return createBigDecimal(frame, BigDecimalType.NEGATIVE_INFINITY);
}
case NEGATIVE_INFINITY:
switch (Layouts.BIG_DECIMAL.getValue(b).signum()) {
case 1:
case 0:
return createBigDecimal(frame, BigDecimalType.NEGATIVE_INFINITY);
case -1:
return createBigDecimal(frame, BigDecimalType.POSITIVE_INFINITY);
}
default:
throw new UnsupportedOperationException("unreachable code branch for value: " + Layouts.BIG_DECIMAL.getType(a));
}
}

protected Object divSpecialSpecial(VirtualFrame frame, DynamicObject a, DynamicObject b, int precision) {
final BigDecimalType aType = Layouts.BIG_DECIMAL.getType(a);
final BigDecimalType bType = Layouts.BIG_DECIMAL.getType(b);

if (aType == BigDecimalType.NAN || bType == BigDecimalType.NAN ||
(aType == BigDecimalType.NEGATIVE_ZERO && bType == BigDecimalType.NEGATIVE_ZERO)) {
return createBigDecimal(frame, BigDecimalType.NAN);
}

if (aType == BigDecimalType.NEGATIVE_ZERO) {
if (bType == BigDecimalType.POSITIVE_INFINITY) {
return createBigDecimal(frame, BigDecimalType.NEGATIVE_ZERO);
} else {
return createBigDecimal(frame, BigDecimalType.POSITIVE_INFINITY);
}
}

if (bType == BigDecimalType.NEGATIVE_ZERO) {
if (aType == BigDecimalType.POSITIVE_INFINITY) {
return createBigDecimal(frame, BigDecimalType.NEGATIVE_INFINITY);
} else {
return createBigDecimal(frame, BigDecimalType.POSITIVE_INFINITY);
}
}

// a and b are only +-Infinity
return createBigDecimal(frame, BigDecimalType.NAN);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
/*
* Copyright (c) 2013, 2016 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.stdlib.bigdecimal;

import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.api.profiles.ConditionProfile;
import org.jruby.truffle.core.Layouts;

import java.math.BigDecimal;
import java.math.MathContext;

public abstract class AbstractMultNode extends BigDecimalOpNode {

private final ConditionProfile zeroNormal = ConditionProfile.createBinaryProfile();

private Object multBigDecimalWithProfile(DynamicObject a, DynamicObject b, MathContext mathContext) {
final BigDecimal bBigDecimal = Layouts.BIG_DECIMAL.getValue(b);

if (zeroNormal.profile(isNormalZero(a) && bBigDecimal.signum() == -1)) {
return BigDecimalType.NEGATIVE_ZERO;
}

return multBigDecimal(Layouts.BIG_DECIMAL.getValue(a), bBigDecimal, mathContext);
}

@CompilerDirectives.TruffleBoundary
private Object multBigDecimal(BigDecimal a, BigDecimal b, MathContext mathContext) {
return a.multiply(b, mathContext);
}

protected Object mult(VirtualFrame frame, DynamicObject a, DynamicObject b, int precision) {
return createBigDecimal(frame, multBigDecimalWithProfile(a, b, new MathContext(precision, getRoundMode(frame))));
}

protected Object multNormalSpecial(VirtualFrame frame, DynamicObject a, DynamicObject b, int precision) {
return multSpecialNormal(frame, b, a, precision);
}

protected Object multSpecialNormal(VirtualFrame frame, DynamicObject a, DynamicObject b, int precision) {
switch (Layouts.BIG_DECIMAL.getType(a)) {
case NAN:
return createBigDecimal(frame, BigDecimalType.NAN);
case NEGATIVE_ZERO:
switch (Layouts.BIG_DECIMAL.getValue(b).signum()) {
case 1:
case 0:
return createBigDecimal(frame, BigDecimalType.NEGATIVE_ZERO);
case -1:
return createBigDecimal(frame, BigDecimal.ZERO);
}
case POSITIVE_INFINITY:
switch (Layouts.BIG_DECIMAL.getValue(b).signum()) {
case 1:
return createBigDecimal(frame, BigDecimalType.POSITIVE_INFINITY);
case 0:
return createBigDecimal(frame, BigDecimalType.NAN);
case -1:
return createBigDecimal(frame, BigDecimalType.NEGATIVE_INFINITY);
}
case NEGATIVE_INFINITY:
switch (Layouts.BIG_DECIMAL.getValue(b).signum()) {
case 1:
return createBigDecimal(frame, BigDecimalType.NEGATIVE_INFINITY);
case 0:
return createBigDecimal(frame, BigDecimalType.NAN);
case -1:
return createBigDecimal(frame, BigDecimalType.POSITIVE_INFINITY);
}
default:
throw new UnsupportedOperationException("unreachable code branch");
}
}

protected Object multSpecial(VirtualFrame frame, DynamicObject a, DynamicObject b, int precision) {
final BigDecimalType aType = Layouts.BIG_DECIMAL.getType(a);
final BigDecimalType bType = Layouts.BIG_DECIMAL.getType(b);

if (aType == BigDecimalType.NAN || bType == BigDecimalType.NAN) {
return createBigDecimal(frame, BigDecimalType.NAN);
}
if (aType == BigDecimalType.NEGATIVE_ZERO && bType == BigDecimalType.NEGATIVE_ZERO) {
return createBigDecimal(frame, BigDecimal.ZERO);
}
if (aType == BigDecimalType.NEGATIVE_ZERO || bType == BigDecimalType.NEGATIVE_ZERO) {
return createBigDecimal(frame, BigDecimalType.NAN);
}

// a and b are only +-Infinity

if (aType == BigDecimalType.POSITIVE_INFINITY) {
return bType == BigDecimalType.POSITIVE_INFINITY ? a : createBigDecimal(frame, BigDecimalType.NEGATIVE_INFINITY);
}
if (aType == BigDecimalType.NEGATIVE_INFINITY) {
return bType == BigDecimalType.POSITIVE_INFINITY ? a : createBigDecimal(frame, (BigDecimalType.POSITIVE_INFINITY));
}

throw new UnsupportedOperationException("unreachable code branch");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* Copyright (c) 2013, 2016 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.stdlib.bigdecimal;

import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.object.DynamicObject;
import org.jruby.truffle.core.Layouts;

import java.math.BigDecimal;
import java.math.MathContext;

public abstract class AbstractSubNode extends BigDecimalOpNode {

@CompilerDirectives.TruffleBoundary
private BigDecimal subBigDecimal(DynamicObject a, DynamicObject b, MathContext mathContext) {
return Layouts.BIG_DECIMAL.getValue(a).subtract(Layouts.BIG_DECIMAL.getValue(b), mathContext);
}

protected Object subNormal(VirtualFrame frame, DynamicObject a, DynamicObject b, int precision) {
return createBigDecimal(frame, subBigDecimal(a, b, new MathContext(precision, getRoundMode(frame))));
}

protected Object subSpecial(VirtualFrame frame, DynamicObject a, DynamicObject b, int precision) {
final BigDecimalType aType = Layouts.BIG_DECIMAL.getType(a);
final BigDecimalType bType = Layouts.BIG_DECIMAL.getType(b);

if (aType == BigDecimalType.NAN || bType == BigDecimalType.NAN ||
(aType == BigDecimalType.POSITIVE_INFINITY && bType == BigDecimalType.POSITIVE_INFINITY) ||
(aType == BigDecimalType.NEGATIVE_INFINITY && bType == BigDecimalType.NEGATIVE_INFINITY)) {
return createBigDecimal(frame, BigDecimalType.NAN);
}

if (aType == BigDecimalType.POSITIVE_INFINITY || bType == BigDecimalType.NEGATIVE_INFINITY) {
return createBigDecimal(frame, BigDecimalType.POSITIVE_INFINITY);
}

if (aType == BigDecimalType.NEGATIVE_INFINITY || bType == BigDecimalType.POSITIVE_INFINITY) {
return createBigDecimal(frame, BigDecimalType.NEGATIVE_INFINITY);
}

// one is NEGATIVE_ZERO and second is NORMAL
if (isNormal(a)) {
return a;
} else {
return createBigDecimal(frame, Layouts.BIG_DECIMAL.getValue(b).negate());
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
/*
* Copyright (c) 2013, 2016 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.stdlib.bigdecimal;

import com.oracle.truffle.api.dsl.Cached;
import com.oracle.truffle.api.dsl.Fallback;
import com.oracle.truffle.api.dsl.ImportStatic;
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.VirtualFrame;
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.api.source.SourceSection;
import org.jruby.RubyBignum;
import org.jruby.RubyFixnum;
import org.jruby.RubyRational;
import org.jruby.ext.bigdecimal.RubyBigDecimal;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.truffle.RubyContext;
import org.jruby.truffle.core.Layouts;
import org.jruby.truffle.language.RubyGuards;
import org.jruby.truffle.language.RubyNode;
import org.jruby.truffle.language.SnippetNode;
import org.jruby.truffle.language.dispatch.CallDispatchHeadNode;

import java.math.BigDecimal;
import java.math.RoundingMode;

@NodeChildren({
@NodeChild(value = "value", type = RubyNode.class),
@NodeChild(value = "roundingMode", type = RubyNode.class)
})
@ImportStatic(BigDecimalCoreMethodNode.class)
public abstract class BigDecimalCastNode extends RubyNode {
public BigDecimalCastNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
}

public abstract BigDecimal executeBigDecimal(VirtualFrame frame, Object value, RoundingMode roundingMode);

public abstract Object executeObject(VirtualFrame frame, Object value, RoundingMode roundingMode);

@Specialization
public BigDecimal doInt(long value, Object roundingMode) {
return BigDecimal.valueOf(value);
}

@Specialization
public BigDecimal doDouble(double value, Object roundingMode) {
return BigDecimal.valueOf(value);
}

@Specialization(guards = "isRubyBignum(value)")
public BigDecimal doBignum(DynamicObject value, Object roundingMode) {
return new BigDecimal(Layouts.BIGNUM.getValue(value));
}

@Specialization(guards = "isNormalRubyBigDecimal(value)")
public BigDecimal doBigDecimal(DynamicObject value, Object roundingMode) {
return Layouts.BIG_DECIMAL.getValue(value);
}

@Specialization(guards = {"!isRubyBignum(value)", "!isRubyBigDecimal(value)"})
public Object doOther(
VirtualFrame frame,
DynamicObject value,
Object roundingMode,
@Cached("new()") SnippetNode isRationalSnippet,
@Cached("createMethodCall()") CallDispatchHeadNode numeratorCallNode,
@Cached("createMethodCall()") CallDispatchHeadNode denominatorCallNode,
@Cached("createMethodCall()") CallDispatchHeadNode toFCallNode) {
if (roundingMode instanceof RoundingMode && (boolean) isRationalSnippet.execute(frame, "value.is_a?(Rational)", "value", value)) {

final Object numerator = numeratorCallNode.call(frame, value, "numerator", null);

final IRubyObject numeratorValue;

if (numerator instanceof Integer) {
numeratorValue = RubyFixnum.newFixnum(getContext().getJRubyRuntime(), (int) numerator);
} else if (numerator instanceof Long) {
numeratorValue = RubyFixnum.newFixnum(getContext().getJRubyRuntime(), (long) numerator);
} else if (RubyGuards.isRubyBignum(numerator)) {
numeratorValue = RubyBignum.newBignum(getContext().getJRubyRuntime(), Layouts.BIGNUM.getValue((DynamicObject) numerator));
} else {
throw new UnsupportedOperationException(numerator.toString());
}

final Object denominator = denominatorCallNode.call(frame, value, "denominator", null);

final IRubyObject denominatorValue;

if (denominator instanceof Integer) {
denominatorValue = RubyFixnum.newFixnum(getContext().getJRubyRuntime(), (int) denominator);
} else if (denominator instanceof Long) {
denominatorValue = RubyFixnum.newFixnum(getContext().getJRubyRuntime(), (long) denominator);
} else if (RubyGuards.isRubyBignum(denominator)) {
denominatorValue = RubyBignum.newBignum(getContext().getJRubyRuntime(), Layouts.BIGNUM.getValue((DynamicObject) denominator));
} else {
throw new UnsupportedOperationException(denominator.toString());
}

final RubyRational rubyRationalValue = RubyRational.newRationalRaw(getContext().getJRubyRuntime(), numeratorValue, denominatorValue);

final RubyBigDecimal rubyBigDecimalValue;

try {
rubyBigDecimalValue = RubyBigDecimal.getVpRubyObjectWithPrec19Inner(getContext().getJRubyRuntime().getCurrentContext(), rubyRationalValue, (RoundingMode) roundingMode);
} catch (Exception e) {
e.printStackTrace();
throw e;
}

return rubyBigDecimalValue.getBigDecimalValue();
} else {
final Object result = toFCallNode.call(frame, value, "to_f", null);
if (result != nil()) {
return new BigDecimal((double) result);
} else {
return result;
}
}
}

@Fallback
public Object doBigDecimalFallback(Object value, Object roundingMode) {
return nil();
}
// TODO (pitr 22-Jun-2015): How to better communicate failure without throwing
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*
* Copyright (c) 2013, 2016 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.stdlib.bigdecimal;

import com.oracle.truffle.api.CompilerDirectives;
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.VirtualFrame;
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.api.source.SourceSection;
import org.jruby.truffle.RubyContext;
import org.jruby.truffle.language.RubyNode;

import java.math.BigDecimal;
import java.math.RoundingMode;

@NodeChildren({
@NodeChild(value = "value", type = RubyNode.class),
@NodeChild(value = "roundingMode", type = RoundModeNode.class),
@NodeChild(value = "cast", type = BigDecimalCastNode.class, executeWith = {"value", "roundingMode"})

})
public abstract class BigDecimalCoerceNode extends RubyNode {
@Child private CreateBigDecimalNode createBigDecimal;

public static BigDecimalCoerceNode create(RubyContext context, SourceSection sourceSection, RubyNode value) {
return BigDecimalCoerceNodeGen.create(value,
RoundModeNodeFactory.create(),
BigDecimalCastNodeGen.create(context, sourceSection, null, null));
}

private void setupCreateBigDecimal() {
if (createBigDecimal == null) {
CompilerDirectives.transferToInterpreter();
createBigDecimal = insert(CreateBigDecimalNodeFactory.create(getContext(), getSourceSection(), null, null, null));
}
}

protected DynamicObject createBigDecimal(VirtualFrame frame, Object value) {
setupCreateBigDecimal();
return createBigDecimal.executeCreate(frame, value);
}

public abstract DynamicObject executeBigDecimal(VirtualFrame frame, RoundingMode roundingMode, Object value);

@Specialization
public DynamicObject doBigDecimal(VirtualFrame frame, Object value, RoundingMode roundingMode, BigDecimal cast) {
return createBigDecimal(frame, cast);
}

@Specialization(guards = { "isRubyBigDecimal(value)", "isNil(cast)" })
public Object doBigDecimal(DynamicObject value, RoundingMode roundingMode, DynamicObject cast) {
return value;
}

// TODO (pitr 22-Jun-2015): deal with not-coerce-able values

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* Copyright (c) 2013, 2016 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.stdlib.bigdecimal;

import com.oracle.truffle.api.dsl.NodeChild;
import com.oracle.truffle.api.source.SourceSection;
import org.jruby.truffle.RubyContext;
import org.jruby.truffle.language.RubyNode;

@NodeChild(value = "arguments", type = RubyNode[].class)
public abstract class BigDecimalCoreMethodArrayArgumentsNode extends BigDecimalCoreMethodNode {

public BigDecimalCoreMethodArrayArgumentsNode() {
}

public BigDecimalCoreMethodArrayArgumentsNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
package org.jruby.truffle.stdlib.bigdecimal;

/*
* Copyright (c) 2013, 2016 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
*/
import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.api.source.SourceSection;
import org.jruby.truffle.RubyContext;
import org.jruby.truffle.core.CoreMethodNode;
import org.jruby.truffle.core.Layouts;
import org.jruby.truffle.core.cast.IntegerCastNode;
import org.jruby.truffle.core.cast.IntegerCastNodeGen;
import org.jruby.truffle.language.RubyGuards;
import org.jruby.truffle.language.dispatch.CallDispatchHeadNode;
import org.jruby.truffle.language.dispatch.DispatchHeadNodeFactory;

import java.math.BigDecimal;
import java.math.RoundingMode;

public abstract class BigDecimalCoreMethodNode extends CoreMethodNode {

@Child
private CreateBigDecimalNode createBigDecimal;
@Child
private CallDispatchHeadNode limitCall;
@Child
private IntegerCastNode limitIntegerCast;
@Child
private CallDispatchHeadNode roundModeCall;
@Child
private IntegerCastNode roundModeIntegerCast;

public BigDecimalCoreMethodNode() {
}

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

public static boolean isNormal(DynamicObject value) {
return Layouts.BIG_DECIMAL.getType(value) == BigDecimalType.NORMAL;
}

public static boolean isNormalRubyBigDecimal(DynamicObject value) {
return RubyGuards.isRubyBigDecimal(value) && Layouts.BIG_DECIMAL.getType(value) == BigDecimalType.NORMAL;
}

public static boolean isSpecialRubyBigDecimal(DynamicObject value) {
return RubyGuards.isRubyBigDecimal(value) && Layouts.BIG_DECIMAL.getType(value) != BigDecimalType.NORMAL;
}

public static boolean isNormalZero(DynamicObject value) {
return Layouts.BIG_DECIMAL.getValue(value).compareTo(BigDecimal.ZERO) == 0;
}

public static boolean isNan(DynamicObject value) {
return Layouts.BIG_DECIMAL.getType(value) == BigDecimalType.NAN;
}

private void setupCreateBigDecimal() {
if (createBigDecimal == null) {
CompilerDirectives.transferToInterpreter();
createBigDecimal = insert(CreateBigDecimalNodeFactory.create(getContext(), getSourceSection(), null, null, null));
}
}

protected DynamicObject createBigDecimal(VirtualFrame frame, Object value) {
setupCreateBigDecimal();
return createBigDecimal.executeCreate(frame, value);
}

protected DynamicObject initializeBigDecimal(VirtualFrame frame, Object value, DynamicObject self, Object digits) {
setupCreateBigDecimal();
return createBigDecimal.executeInitialize(frame, value, self, digits);
}

private void setupLimitCall() {
if (limitCall == null) {
CompilerDirectives.transferToInterpreter();
limitCall = insert(DispatchHeadNodeFactory.createMethodCall(getContext()));
}
}

private void setupLimitIntegerCast() {
if (limitIntegerCast == null) {
CompilerDirectives.transferToInterpreter();
limitIntegerCast = insert(IntegerCastNodeGen.create(getContext(), getSourceSection(), null));
}
}

protected int getLimit(VirtualFrame frame) {
setupLimitCall();
setupLimitIntegerCast();

return limitIntegerCast.executeCastInt(limitCall.call(frame, getBigDecimalClass(), "limit", null));
}

private void setupRoundModeCall() {
if (roundModeCall == null) {
CompilerDirectives.transferToInterpreter();
roundModeCall = insert(DispatchHeadNodeFactory.createMethodCall(getContext()));
}
}

private void setupRoundModeIntegerCast() {
if (roundModeIntegerCast == null) {
CompilerDirectives.transferToInterpreter();
roundModeIntegerCast = insert(IntegerCastNodeGen.create(getContext(), getSourceSection(), null));
}
}

protected RoundingMode getRoundMode(VirtualFrame frame) {
setupRoundModeCall();
setupRoundModeIntegerCast();

return toRoundingMode(roundModeIntegerCast.executeCastInt(
// TODO (pitr 21-Jun-2015): read the actual constant
roundModeCall.call(frame, getBigDecimalClass(), "mode", null, 256)));
}

protected DynamicObject getBigDecimalClass() {
return coreLibrary().getBigDecimalClass();
}

protected static RoundingMode toRoundingMode(int constValue) {
switch (constValue) {
case 1:
return RoundingMode.UP;
case 2:
return RoundingMode.DOWN;
case 3:
return RoundingMode.HALF_UP;
case 4:
return RoundingMode.HALF_DOWN;
case 5:
return RoundingMode.CEILING;
case 6:
return RoundingMode.FLOOR;
case 7:
return RoundingMode.HALF_EVEN;
default:
throw new UnsupportedOperationException("unknown value: " + constValue);
}
}

protected static int nearestBiggerMultipleOf4(int value) {
return ((value / 4) + 1) * 4;
}

protected static int defaultDivisionPrecision(int precisionA, int precisionB, int limit) {
final int combination = nearestBiggerMultipleOf4(precisionA + precisionB) * 4;
return (limit > 0 && limit < combination) ? limit : combination;
}

protected static int defaultDivisionPrecision(BigDecimal a, BigDecimal b, int limit) {
return defaultDivisionPrecision(a.precision(), b.precision(), limit);
}

}
Original file line number Diff line number Diff line change
@@ -7,7 +7,7 @@
* GNU General Public License version 2
* GNU Lesser General Public License version 2.1
*/
package org.jruby.truffle.stdlib;
package org.jruby.truffle.stdlib.bigdecimal;

import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.api.object.DynamicObjectFactory;
@@ -26,14 +26,14 @@ DynamicObjectFactory createBigDecimalShape(
DynamicObject createBigDecimal(
DynamicObjectFactory factory,
BigDecimal value,
BigDecimalNodes.Type type);
BigDecimalType type);

boolean isBigDecimal(DynamicObject object);

BigDecimal getValue(DynamicObject object);
void setValue(DynamicObject object, BigDecimal value);

BigDecimalNodes.Type getType(DynamicObject object);
void setType(DynamicObject object, BigDecimalNodes.Type value);
BigDecimalType getType(DynamicObject object);
void setType(DynamicObject object, BigDecimalType value);

}
1,396 changes: 1,396 additions & 0 deletions truffle/src/main/java/org/jruby/truffle/stdlib/bigdecimal/BigDecimalNodes.java

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* Copyright (c) 2013, 2016 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.stdlib.bigdecimal;

import com.oracle.truffle.api.dsl.CreateCast;
import com.oracle.truffle.api.dsl.NodeChild;
import com.oracle.truffle.api.dsl.NodeChildren;
import org.jruby.truffle.language.RubyNode;

@NodeChildren({
@NodeChild(value = "a", type = RubyNode.class),
@NodeChild(value = "b", type = RubyNode.class),
})
public abstract class BigDecimalOpNode extends BigDecimalCoreMethodNode {

@CreateCast("b")
protected RubyNode castB(RubyNode b) {
return BigDecimalCoerceNodeGen.create(null, null, b);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* Copyright (c) 2013, 2016 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.stdlib.bigdecimal;

public enum BigDecimalType {
NEGATIVE_INFINITY("-Infinity"),
POSITIVE_INFINITY("Infinity"),
NAN("NaN"),
NEGATIVE_ZERO("-0"),
NORMAL(null);

private final String representation;

BigDecimalType(String representation) {
this.representation = representation;
}

public String getRepresentation() {
assert representation != null;
return representation;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,285 @@
/*
* Copyright (c) 2013, 2016 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.stdlib.bigdecimal;

import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.dsl.ImportStatic;
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.VirtualFrame;
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.api.source.SourceSection;
import org.jruby.truffle.RubyContext;
import org.jruby.truffle.core.Layouts;
import org.jruby.truffle.core.cast.BooleanCastNode;
import org.jruby.truffle.core.cast.BooleanCastNodeGen;
import org.jruby.truffle.language.NotProvided;
import org.jruby.truffle.language.RubyNode;
import org.jruby.truffle.language.control.RaiseException;
import org.jruby.truffle.language.dispatch.CallDispatchHeadNode;
import org.jruby.truffle.language.dispatch.DispatchHeadNodeFactory;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.MathContext;
import java.util.regex.MatchResult;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@NodeChildren({
@NodeChild(value = "value", type = RubyNode.class),
@NodeChild(value = "self", type = RubyNode.class),
@NodeChild(value = "digits", type = RubyNode.class)
})
@ImportStatic(BigDecimalType.class)
public abstract class CreateBigDecimalNode extends BigDecimalCoreMethodNode {

private final static Pattern NUMBER_PATTERN;
private final static Pattern ZERO_PATTERN;

static {
final String exponent = "([eE][+-]?)?(\\d*)";
NUMBER_PATTERN = Pattern.compile("^([+-]?\\d*\\.?\\d*" + exponent + ").*");
ZERO_PATTERN = Pattern.compile("^[+-]?0*\\.?0*" + exponent);
}

@Child
private BigDecimalCastNode bigDecimalCast;
@Child
private CallDispatchHeadNode modeCall;
@Child
private GetIntegerConstantNode getIntegerConstant;
@Child
private BooleanCastNode booleanCast;
@Child
private CallDispatchHeadNode allocateNode;

public CreateBigDecimalNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
bigDecimalCast = BigDecimalCastNodeGen.create(context, sourceSection, null, null);
}

private void setBigDecimalValue(DynamicObject bigdecimal, BigDecimal value) {
Layouts.BIG_DECIMAL.setValue(bigdecimal, value);
}

private void setBigDecimalValue(DynamicObject bigdecimal, BigDecimalType type) {
Layouts.BIG_DECIMAL.setType(bigdecimal, type);
}

public abstract DynamicObject executeInitialize(VirtualFrame frame, Object value, DynamicObject alreadyAllocatedSelf, Object digits);

public final DynamicObject executeCreate(VirtualFrame frame, Object value) {
if (allocateNode == null) {
CompilerDirectives.transferToInterpreter();
allocateNode = insert(DispatchHeadNodeFactory.createMethodCall(getContext(), true));
}

DynamicObject rubyClass = (getBigDecimalClass());
return executeInitialize(frame, value, (DynamicObject) allocateNode.call(frame, rubyClass, "allocate", null), NotProvided.INSTANCE);
}

@Specialization
public DynamicObject create(VirtualFrame frame, long value, DynamicObject self, NotProvided digits) {
return create(frame, value, self, 0);
}

@Specialization
public DynamicObject create(VirtualFrame frame, long value, DynamicObject self, int digits) {
setBigDecimalValue(self,
bigDecimalCast.executeBigDecimal(frame, value, getRoundMode(frame)).round(new MathContext(digits, getRoundMode(frame))));
return self;
}

@Specialization
public DynamicObject create(VirtualFrame frame, double value, DynamicObject self, NotProvided digits) {
CompilerDirectives.transferToInterpreter();
throw new RaiseException(coreExceptions().argumentError("can't omit precision for a Float.", this));
}

@Specialization
public DynamicObject create(VirtualFrame frame, double value, DynamicObject self, int digits) {
setBigDecimalValue(self,
bigDecimalCast.executeBigDecimal(frame, value, getRoundMode(frame)).round(new MathContext(digits, getRoundMode(frame))));
return self;
}

@Specialization(guards = "value == NEGATIVE_INFINITY || value == POSITIVE_INFINITY")
public DynamicObject createInfinity(VirtualFrame frame, BigDecimalType value, DynamicObject self, Object digits) {
return createWithMode(frame, value, self, "EXCEPTION_INFINITY", "Computation results to 'Infinity'");
}

@Specialization(guards = "value == NAN")
public DynamicObject createNaN(VirtualFrame frame, BigDecimalType value, DynamicObject self, Object digits) {
return createWithMode(frame, value, self, "EXCEPTION_NaN", "Computation results to 'NaN'(Not a Number)");
}

@Specialization(guards = "value == NEGATIVE_ZERO")
public DynamicObject createNegativeZero(VirtualFrame frame, BigDecimalType value, DynamicObject self, Object digits) {
setBigDecimalValue(self, value);
return self;
}

@Specialization
public DynamicObject create(VirtualFrame frame, BigDecimal value, DynamicObject self, NotProvided digits) {
return create(frame, value, self, 0);
}

@Specialization
public DynamicObject create(VirtualFrame frame, BigDecimal value, DynamicObject self, int digits) {
setBigDecimalValue(self, value.round(new MathContext(digits, getRoundMode(frame))));
return self;
}

@Specialization(guards = "isRubyBignum(value)")
public DynamicObject createBignum(VirtualFrame frame, DynamicObject value, DynamicObject self, NotProvided digits) {
return createBignum(frame, value, self, 0);
}

@Specialization(guards = "isRubyBignum(value)")
public DynamicObject createBignum(VirtualFrame frame, DynamicObject value, DynamicObject self, int digits) {
setBigDecimalValue(self,
new BigDecimal(Layouts.BIGNUM.getValue(value)).round(new MathContext(digits, getRoundMode(frame))));
return self;
}

@Specialization(guards = "isRubyBigDecimal(value)")
public DynamicObject createBigDecimal(VirtualFrame frame, DynamicObject value, DynamicObject self, NotProvided digits) {
return createBigDecimal(frame, value, self, 0);
}

@Specialization(guards = "isRubyBigDecimal(value)")
public DynamicObject createBigDecimal(VirtualFrame frame, DynamicObject value, DynamicObject self, int digits) {
setBigDecimalValue(self,
Layouts.BIG_DECIMAL.getValue(value).round(new MathContext(digits, getRoundMode(frame))));
return self;
}

@Specialization(guards = "isRubyString(value)")
public DynamicObject createString(VirtualFrame frame, DynamicObject value, DynamicObject self, NotProvided digits) {
return createString(frame, value, self, 0);
}

@Specialization(guards = "isRubyString(value)")
public DynamicObject createString(VirtualFrame frame, DynamicObject value, DynamicObject self, int digits) {
return executeInitialize(frame, getValueFromString(value.toString(), digits), self, digits);
}

@Specialization(guards = {"!isRubyBignum(value)", "!isRubyBigDecimal(value)", "!isRubyString(value)"})
public DynamicObject create(VirtualFrame frame, DynamicObject value, DynamicObject self, int digits) {
final Object castedValue = bigDecimalCast.executeObject(frame, value, getRoundMode(frame));
if (castedValue == nil()) {
throw new RaiseException(coreExceptions().typeError("could not be casted to BigDecimal", this));
}

setBigDecimalValue(
self,
((BigDecimal) castedValue).round(new MathContext(digits, getRoundMode(frame))));

return self;
}

// TODO (pitr 21-Jun-2015): raise on underflow

private DynamicObject createWithMode(VirtualFrame frame, BigDecimalType value, DynamicObject self,
String constantName, String errorMessage) {
setupModeCall();
setupGetIntegerConstant();
setupBooleanCast();

final int exceptionConstant = getIntegerConstant.executeGetIntegerConstant(frame, getBigDecimalClass(), constantName);
final boolean raise = booleanCast.executeBoolean(frame,
modeCall.call(frame, getBigDecimalClass(), "boolean_mode", null, exceptionConstant));
if (raise) {
CompilerDirectives.transferToInterpreter();
throw new RaiseException(coreExceptions().floatDomainError(errorMessage, this));
}

setBigDecimalValue(self, value);
return self;
}

private void setupBooleanCast() {
if (booleanCast == null) {
CompilerDirectives.transferToInterpreter();
booleanCast = insert(BooleanCastNodeGen.create(getContext(), getSourceSection(), null));
}
}

private void setupGetIntegerConstant() {
if (getIntegerConstant == null) {
CompilerDirectives.transferToInterpreter();
getIntegerConstant = insert(GetIntegerConstantNodeGen.create(getContext(), getSourceSection(), null, null));
}
}

private void setupModeCall() {
if (modeCall == null) {
CompilerDirectives.transferToInterpreter();
modeCall = insert(DispatchHeadNodeFactory.createMethodCall(getContext(), true));
}
}

@CompilerDirectives.TruffleBoundary
private Object getValueFromString(String string, int digits) {
String strValue = string.trim();

// TODO (pitr 26-May-2015): create specialization without trims and other cleanups, use rewriteOn

switch (strValue) {
case "NaN":
return BigDecimalType.NAN;
case "Infinity":
case "+Infinity":
return BigDecimalType.POSITIVE_INFINITY;
case "-Infinity":
return BigDecimalType.NEGATIVE_INFINITY;
case "-0":
return BigDecimalType.NEGATIVE_ZERO;
}

// Convert String to Java understandable format (for BigDecimal).
strValue = strValue.replaceFirst("[dD]", "E"); // 1. MRI allows d and D as exponent separators
strValue = strValue.replaceAll("_", ""); // 2. MRI allows underscores anywhere

final MatchResult result;
{
final Matcher matcher = NUMBER_PATTERN.matcher(strValue);
strValue = matcher.replaceFirst("$1"); // 3. MRI ignores the trailing junk
result = matcher.toMatchResult();
}

try {
final BigDecimal value = new BigDecimal(strValue, new MathContext(digits));
if (value.compareTo(BigDecimal.ZERO) == 0 && strValue.startsWith("-")) {
return BigDecimalType.NEGATIVE_ZERO;
} else {
return value;
}

} catch (NumberFormatException e) {
if (ZERO_PATTERN.matcher(strValue).matches()) {
return BigDecimal.ZERO;
}

final BigInteger exponent = new BigInteger(result.group(3));
if (exponent.signum() == 1) {
return BigDecimalType.POSITIVE_INFINITY;
}
// TODO (pitr 21-Jun-2015): raise on underflow
if (exponent.signum() == -1) {
return BigDecimal.ZERO;
}

throw e;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* Copyright (c) 2013, 2016 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.stdlib.bigdecimal;

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.VirtualFrame;
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.api.source.SourceSection;
import org.jruby.truffle.RubyContext;
import org.jruby.truffle.core.cast.IntegerCastNode;
import org.jruby.truffle.core.cast.IntegerCastNodeGen;
import org.jruby.truffle.core.cast.ToIntNode;
import org.jruby.truffle.language.RubyNode;
import org.jruby.truffle.language.constants.ReadConstantNode;

@NodeChildren({@NodeChild("module"), @NodeChild("name")})
public abstract class GetIntegerConstantNode extends RubyNode {

@Child
ReadConstantNode readConstantNode;
@Child
ToIntNode toIntNode;
@Child
IntegerCastNode integerCastNode;

public GetIntegerConstantNode(RubyContext context, SourceSection sourceSection) {
super(context, sourceSection);
readConstantNode = new ReadConstantNode(context, sourceSection, false, false, null, null);
toIntNode = ToIntNode.create();
integerCastNode = IntegerCastNodeGen.create(context, sourceSection, null);
}

public abstract int executeGetIntegerConstant(VirtualFrame frame, DynamicObject module, String name);

@Specialization(guards = "isRubyModule(module)")
public int doInteger(VirtualFrame frame, DynamicObject module, String name) {
final Object value = readConstantNode.readConstant(frame, module, name);
return integerCastNode.executeCastInt(toIntNode.executeIntOrLong(frame, value));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* Copyright (c) 2013, 2016 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.stdlib.bigdecimal;

import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.frame.VirtualFrame;

import java.math.RoundingMode;

public abstract class RoundModeNode extends BigDecimalCoreMethodNode {

@Specialization
public RoundingMode doGetRoundMode(VirtualFrame frame) {
return getRoundMode(frame);
}

}

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* Copyright (c) 2015, 2016 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
*
* This code is modified from the Psych JRuby extension module
* implementation with the following header:
*
* Version: EPL 1.0/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Eclipse Public
* License Version 1.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.eclipse.org/legal/epl-v10.html
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* Copyright (C) 2010 Charles O Nutter <headius@headius.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the EPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the EPL, the GPL or the LGPL.
*/
package org.jruby.truffle.stdlib.psych;

import org.jcodings.Encoding;
import org.jcodings.specific.UTF16BEEncoding;
import org.jcodings.specific.UTF16LEEncoding;
import org.jcodings.specific.UTF8Encoding;

public enum YAMLEncoding {
YAML_ANY_ENCODING(UTF8Encoding.INSTANCE),
YAML_UTF8_ENCODING(UTF8Encoding.INSTANCE),
YAML_UTF16LE_ENCODING(UTF16LEEncoding.INSTANCE),
YAML_UTF16BE_ENCODING(UTF16BEEncoding.INSTANCE);

YAMLEncoding(Encoding encoding) {
this.encoding = encoding;
}

private final Encoding encoding;

public Encoding getEncoding() {
return encoding;
}

}
10 changes: 7 additions & 3 deletions truffle/src/main/ruby/core/truffle/cext.rb
Original file line number Diff line number Diff line change
@@ -111,15 +111,19 @@ def rb_define_module_under(mod, name)
end

def rb_define_method(mod, name, function, args)
raise 'not implemented'
mod.send(:define_method, name) do |*args|
function.call(self, *args)
end
end

def rb_define_private_method(mod, name, function, args)
raise 'not implemented'
rb_define_method mod, name, function, args
mod.send :private, name
end

def rb_define_module_function(mod, name, function, args)
raise 'not implemented'
rb_define_method mod, name, function, args
mod.send :module_function, name
end

end

0 comments on commit 7424d6c

Please sign in to comment.