Skip to content
Permalink
Browse files
Merge branch 'master' into truffle-head
  • Loading branch information
chrisseaton committed Jan 30, 2015
2 parents 6ee6976 + 0b8305a commit b35d34d20cddbda3871df1edcbfefcf0651579d1
Showing with 282 additions and 196 deletions.
  1. +11 −6 core/src/main/java/org/jruby/ext/bigdecimal/RubyBigDecimal.java
  2. +88 −3 core/src/main/java/org/jruby/runtime/Signature.java
  3. +36 −8 core/src/main/java/org/jruby/util/io/Sockaddr.java
  4. +1 −1 core/src/main/ruby/jruby/truffle/core.rb
  5. +0 −33 core/src/main/ruby/jruby/truffle/core/rubinius/api/shims/enumerator.rb
  6. +5 −1 core/src/main/ruby/jruby/truffle/core/rubinius/api/shims/rubinius.rb
  7. +2 −0 core/src/main/ruby/jruby/truffle/core/rubinius/kernel/common/array.rb
  8. +35 −0 core/src/main/ruby/jruby/truffle/core/rubinius/kernel/common/exception.rb
  9. +12 −0 spec/regression/GH-2524_bigdecimal_loss_of_precision_with_different_excution_order_spec.rb
  10. +0 −1 spec/truffle/tags/core/enumerable/chunk_tags.txt
  11. +0 −1 spec/truffle/tags/core/enumerable/collect_tags.txt
  12. +0 −2 spec/truffle/tags/core/enumerable/detect_tags.txt
  13. +0 −1 spec/truffle/tags/core/enumerable/drop_tags.txt
  14. +0 −2 spec/truffle/tags/core/enumerable/drop_while_tags.txt
  15. +0 −3 spec/truffle/tags/core/enumerable/each_cons_tags.txt
  16. +0 −2 spec/truffle/tags/core/enumerable/each_entry_tags.txt
  17. +0 −3 spec/truffle/tags/core/enumerable/each_slice_tags.txt
  18. +0 −1 spec/truffle/tags/core/enumerable/each_with_index_tags.txt
  19. +0 −1 spec/truffle/tags/core/enumerable/each_with_object_tags.txt
  20. +0 −2 spec/truffle/tags/core/enumerable/entries_tags.txt
  21. +0 −2 spec/truffle/tags/core/enumerable/find_tags.txt
  22. +0 −5 spec/truffle/tags/core/enumerable/group_by_tags.txt
  23. +0 −1 spec/truffle/tags/core/enumerable/inject_tags.txt
  24. +0 −1 spec/truffle/tags/core/enumerable/lazy_tags.txt
  25. +0 −1 spec/truffle/tags/core/enumerable/map_tags.txt
  26. +0 −1 spec/truffle/tags/core/enumerable/reduce_tags.txt
  27. +0 −1 spec/truffle/tags/core/enumerable/sort_by_tags.txt
  28. +0 −2 spec/truffle/tags/core/enumerable/sort_tags.txt
  29. +0 −2 spec/truffle/tags/core/enumerable/take_while_tags.txt
  30. +0 −2 spec/truffle/tags/core/enumerable/to_a_tags.txt
  31. +0 −4 spec/truffle/tags/core/enumerator/lazy/collect_concat_tags.txt
  32. +0 −3 spec/truffle/tags/core/enumerator/lazy/collect_tags.txt
  33. +0 −3 spec/truffle/tags/core/enumerator/lazy/drop_tags.txt
  34. +0 −4 spec/truffle/tags/core/enumerator/lazy/drop_while_tags.txt
  35. +0 −3 spec/truffle/tags/core/enumerator/lazy/enum_for_tags.txt
  36. +0 −4 spec/truffle/tags/core/enumerator/lazy/find_all_tags.txt
  37. +0 −4 spec/truffle/tags/core/enumerator/lazy/flat_map_tags.txt
  38. +0 −3 spec/truffle/tags/core/enumerator/lazy/grep_tags.txt
  39. +0 −7 spec/truffle/tags/core/enumerator/lazy/initialize_tags.txt
  40. +0 −1 spec/truffle/tags/core/enumerator/lazy/lazy_tags.txt
  41. +0 −3 spec/truffle/tags/core/enumerator/lazy/map_tags.txt
  42. +0 −4 spec/truffle/tags/core/enumerator/lazy/reject_tags.txt
  43. +0 −4 spec/truffle/tags/core/enumerator/lazy/select_tags.txt
  44. +0 −3 spec/truffle/tags/core/enumerator/lazy/take_tags.txt
  45. +0 −4 spec/truffle/tags/core/enumerator/lazy/take_while_tags.txt
  46. +0 −3 spec/truffle/tags/core/enumerator/lazy/to_enum_tags.txt
  47. +0 −5 spec/truffle/tags/core/enumerator/lazy/zip_tags.txt
  48. +14 −1 truffle/src/main/java/org/jruby/truffle/nodes/core/ArrayNodes.java
  49. +1 −1 truffle/src/main/java/org/jruby/truffle/nodes/core/HashNodes.java
  50. +8 −12 truffle/src/main/java/org/jruby/truffle/nodes/core/KernelNodes.java
  51. +9 −9 truffle/src/main/java/org/jruby/truffle/nodes/core/RegexpNodes.java
  52. +11 −0 truffle/src/main/java/org/jruby/truffle/runtime/core/CoreLibrary.java
  53. +6 −7 truffle/src/main/java/org/jruby/truffle/runtime/core/RubyFiber.java
  54. +0 −4 truffle/src/main/java/org/jruby/truffle/runtime/core/RubyRegexp.java
  55. +11 −11 truffle/src/main/java/org/jruby/truffle/runtime/core/RubyThread.java
  56. +32 −0 truffle/src/main/java/org/jruby/truffle/translator/BodyTranslator.java
@@ -869,10 +869,16 @@ public IRubyObject op_quo20(ThreadContext context, IRubyObject other) {
}

private IRubyObject op_quo19_20(ThreadContext context, IRubyObject other) {
RubyObject preciseOther = getVpValue19(context, other, true);
RubyBigDecimal preciseOther = getVpValue19(context, other, true);
// regular division with some default precision
// TODO: proper algorithm to set the precision
return op_div(context, preciseOther, getRuntime().newFixnum(200));
// proper algorithm to set the precision
// the precision is multiple of 4
// and the precision is larger than len * 2
int len = value.precision() + preciseOther.value.precision();
int pow = len / 4;
int precision = (pow + 1) * 4 * 2;

return op_div(context, preciseOther, getRuntime().newFixnum(precision));
}

public IRubyObject op_div(ThreadContext context, IRubyObject other) {
@@ -923,10 +929,9 @@ public IRubyObject op_div(ThreadContext context, IRubyObject other, IRubyObject
// MRI behavior: "If digits is 0, the result is the same as the / operator."
if (scale == 0) return op_quo(context, other);

// TODO: better algorithm to set precision needed
int prec = Math.max(200, scale);
MathContext mathContext = new MathContext(scale, getRoundingMode(context.runtime));
return new RubyBigDecimal(context.runtime,
value.divide(val.value, new MathContext(prec, RoundingMode.HALF_UP))).setResult(scale);
value.divide(val.value, mathContext)).setResult(scale);
}

@JRubyMethod(name = "div")
@@ -10,6 +10,7 @@
import org.jruby.ast.PreExeNode;
import org.jruby.ast.StarNode;
import org.jruby.ast.UnnamedRestArgNode;
import org.jruby.ast.RequiredKeywordArgumentValueNode;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.util.TypeConverter;

@@ -35,6 +36,8 @@ public enum Rest { NONE, NORM, ANON, STAR }
private final boolean kwargs;
private final Arity arity;

private boolean requiredKwargs;

public Signature(int pre, int opt, int post, Rest rest, boolean kwargs) {
this.pre = pre;
this.opt = opt;
@@ -47,12 +50,36 @@ public Signature(int pre, int opt, int post, Rest rest, boolean kwargs) {
// permit more than required args to be passed to a lambda, so we do not consider
// it a "true" rest arg for arity-checking purposes below in checkArity.
if (rest != Rest.NONE || opt != 0) {
arity = Arity.createArity(-(pre + post + 1));
arity = Arity.createArity(-(required() + 1));
} else {
arity = Arity.fixed(pre + post);
arity = Arity.fixed(required() + getRequiredKeywordCount());
}
}

public Signature(int pre, int opt, int post, Rest rest, boolean kwargs, boolean requiredKwargs) {
this.pre = pre;
this.opt = opt;
this.post = post;
this.rest = rest;
this.kwargs = kwargs;
this.requiredKwargs = requiredKwargs;

// NOTE: Some logic to *assign* variables still uses Arity, which treats Rest.ANON (the
// |a,| form) as a rest arg for destructuring purposes. However ANON does *not*
// permit more than required args to be passed to a lambda, so we do not consider
// it a "true" rest arg for arity-checking purposes below in checkArity.
if (rest != Rest.NONE || opt != 0) {
arity = Arity.createArity(-(required() + 1));
} else {
arity = Arity.fixed(required() + getRequiredKeywordCount());
}
}

private int getRequiredKeywordCount() {
if (requiredKwargs) return 1;
return 0;
}

public int pre() { return pre; }
public int opt() { return opt; }
public Rest rest() { return rest; }
@@ -102,6 +129,46 @@ public static Signature from(int pre, int opt, int post, Rest rest, boolean kwar
return new Signature(pre, opt, post, rest, kwargs);
}

public static Signature from(int pre, int opt, int post, Rest rest, boolean kwargs, boolean requiredKwargs) {
if (opt == 0 && post == 0 && !kwargs) {
switch (pre) {
case 0:
switch (rest) {
case NONE:
return Signature.NO_ARGUMENTS;
case NORM:
return Signature.OPTIONAL;
}
break;
case 1:
switch (rest) {
case NONE:
return Signature.ONE_ARGUMENT;
case NORM:
return Signature.ONE_REQUIRED;
}
break;
case 2:
switch (rest) {
case NONE:
return Signature.TWO_ARGUMENTS;
case NORM:
return Signature.TWO_REQUIRED;
}
break;
case 3:
switch (rest) {
case NONE:
return Signature.THREE_ARGUMENTS;
case NORM:
return Signature.THREE_REQUIRED;
}
break;
}
}
return new Signature(pre, opt, post, rest, kwargs, requiredKwargs);
}

public static Signature from(IterNode iter) {
if (iter instanceof ForNode) return from((ForNode)iter);
if (iter instanceof PreExeNode) return from((PreExeNode)iter);
@@ -118,7 +185,25 @@ public static Signature from(IterNode iter) {
rest = restFromArg(restArg);
}

return Signature.from(args.getPreCount(), args.getOptionalArgsCount(), args.getPostCount(), rest, args.hasKwargs());
return Signature.from(args.getPreCount(), args.getOptionalArgsCount(), args.getPostCount(), rest, args.hasKwargs(), hasRequiredKeywordArg(args));
}

private static boolean hasRequiredKeywordArg(ArgsNode args) {
if (args.getKeywords() == null) return false;

for (Node keyWordNode : args.getKeywords().childNodes()) {
for (Node asgnNode : keyWordNode.childNodes()) {
if (isRequiredKeywordArgumentValueNode(asgnNode)) {
return true;
}
}
}
return false;
}


private static boolean isRequiredKeywordArgumentValueNode(Node asgnNode) {
return asgnNode.childNodes().get(0) instanceof RequiredKeywordArgumentValueNode;
}

private static Rest restFromArg(Node restArg) {
@@ -88,14 +88,27 @@ public static IRubyObject unpack_sockaddr_in(ThreadContext context, IRubyObject

int port = ((val.get(2)&0xff) << 8) + (val.get(3)&0xff);

StringBuilder sb = new StringBuilder()
.append(val.get(4)&0xff)
AddressFamily af = getAddressFamilyFromSockaddr(runtime, val);

StringBuilder sb = new StringBuilder();

if (af == AddressFamily.AF_INET) {
sb.append(val.get(4) & 0xff)
.append(".")
.append(val.get(5)&0xff)
.append(val.get(5) & 0xff)
.append(".")
.append(val.get(6)&0xff)
.append(val.get(6) & 0xff)
.append(".")
.append(val.get(7)&0xff);
.append(val.get(7) & 0xff);

} else { // if af == AddressFamily.AF_INET6
for (int i = 4; i <= 19; i++) {
if (i != 4 && i % 2 == 0) {
sb.append(":");
}
sb.append(Integer.toHexString(val.get(i) & 0xff | 0x100).substring(1));
}
}

IRubyObject[] result = new IRubyObject[]{
runtime.newFixnum(port),
@@ -117,15 +130,23 @@ public static IRubyObject pack_sockaddr_in(ThreadContext context, int iport, Str
try {
DataOutputStream ds = new DataOutputStream(bufS);

writeSockaddrHeader(AddressFamily.AF_INET, ds);
writeSockaddrPort(ds, iport);

try {
if(host != null && "".equals(host)) {
writeSockaddrHeader(AddressFamily.AF_INET, ds);
writeSockaddrPort(ds, iport);
ds.writeInt(0);
} else {
InetAddress[] addrs = InetAddress.getAllByName(host);
byte[] addr = addrs[0].getAddress();

if (addr.length == 4) {
writeSockaddrHeader(AddressFamily.AF_INET, ds);
} else {
writeSockaddrHeader(AddressFamily.AF_INET6, ds);
}

writeSockaddrPort(ds, iport);

ds.write(addr, 0, addr.length);
}
} catch (UnknownHostException e) {
@@ -207,6 +228,13 @@ public static void validateSockaddr(Ruby runtime, ByteList val) {
}
}

public static AddressFamily getAddressFamilyFromSockaddr(Ruby runtime, ByteList val) {
int high = val.get(0) & 0xff;
int low = val.get(1) & 0xff;

return AddressFamily.valueOf((high << 8) + low);
}

private static RuntimeException sockerr(Ruby runtime, String msg) {
return new RaiseException(runtime, runtime.getClass("SocketError"), msg, true);
}
@@ -15,7 +15,6 @@
require_relative 'core/rubinius/api/shims/rubinius'
require_relative 'core/rubinius/api/shims/lookuptable'
require_relative 'core/rubinius/api/shims/thread'
require_relative 'core/rubinius/api/shims/enumerator'
require_relative 'core/rubinius/api/shims/undefined'
require_relative 'core/rubinius/api/shims/metrics'

@@ -34,6 +33,7 @@
# Load common (ordered according to Rubinius' load_order.txt)
require_relative 'core/rubinius/kernel/common/enumerator'
require_relative 'core/rubinius/kernel/common/enumerable'
require_relative 'core/rubinius/kernel/common/exception'
require_relative 'core/rubinius/kernel/common/undefined'
require_relative 'core/rubinius/kernel/common/type'
require_relative 'core/rubinius/kernel/common/array'

This file was deleted.

@@ -12,10 +12,14 @@ def self.mathn_loaded?
false
end

module Fiber
class Fiber < ::Fiber

ENABLED = true

def initialize(size, &block)
super &block
end

end

end
@@ -24,6 +24,8 @@
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

# Only part of Rubinius' array.rb

class Array

def values_at(*args)
@@ -0,0 +1,35 @@
# Copyright (c) 2007-2014, Evan Phoenix and contributors
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice, this
# list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright notice
# this list of conditions and the following disclaimer in the documentation
# and/or other materials provided with the distribution.
# * Neither the name of Rubinius nor the names of its contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

# Only part of Rubinius' exception.rb

class StopIteration < IndexError
end

class StopIteration
attr_accessor :result
private :result=
end
@@ -0,0 +1,12 @@
require 'bigdecimal'

# https://github.com/jruby/jruby/issues/2524
describe 'BigDecimal precision test with different execution order' do
it 'returns same precision ' do
fraction = BigDecimal.new("0.0095") / 365 * BigDecimal.new(50_000)
r1 = fraction * BigDecimal.new(50_000) / BigDecimal.new(100_000)
r2 = fraction * (BigDecimal.new(50_000) / BigDecimal.new(100_000))
expect(r1).to eq(r2)
end
end

@@ -1,4 +1,3 @@
fails:Enumerable#chunk returns an Enumerator if given a block
fails:Enumerable#chunk yields the current element and the current chunk to the block
fails:Enumerable#chunk returns elements of the Enumerable in an Array of Arrays, [v, ary], where 'ary' contains the consecutive elements for which the block returned the value 'v'
fails:Enumerable#chunk returns elements for which the block returns :_alone in separate Arrays
@@ -1,2 +1 @@
fails:Enumerable#collect passes through the values yielded by #each_with_index
fails:Enumerable#collect returns an enumerator when no block given
@@ -1,3 +1 @@
fails:Enumerable#detect passes through the values yielded by #each_with_index
fails:Enumerable#detect returns an enumerator when no block given
fails:Enumerable#detect passes the ifnone proc to the enumerator
@@ -1,3 +1,2 @@
fails:Enumerable#drop passed a number n as an argument tries to convert n to an Integer using #to_int
fails:Enumerable#drop passed a number n as an argument returns [] for empty enumerables
fails:Enumerable#drop passed a number n as an argument returns [] if dropping all
@@ -1,3 +1 @@
fails:Enumerable#drop_while returns no/all elements for {true/false} block
fails:Enumerable#drop_while accepts returns other than true/false
fails:Enumerable#drop_while will only go through what's needed
@@ -1,5 +1,2 @@
fails:Enumerable#each_cons tries to convert n to an Integer using #to_int
fails:Enumerable#each_cons works when n is >= full length
fails:Enumerable#each_cons yields only as much as needed
fails:Enumerable#each_cons returns an enumerator if no block
fails:Enumerable#each_cons gathers whole arrays as elements when each yields multiple
@@ -1,3 +1 @@
fails:Enumerable#each_entry returns an enumerator if no block
fails:Enumerable#each_entry passes through the values yielded by #each_with_index
fails:Enumerable#each_entry passes extra arguments to #each

This file was deleted.

This file was deleted.

This file was deleted.

0 comments on commit b35d34d

Please sign in to comment.