Skip to content

Commit

Permalink
Showing 28 changed files with 450 additions and 682 deletions.
55 changes: 30 additions & 25 deletions core/src/main/java/org/jruby/Ruby.java
Original file line number Diff line number Diff line change
@@ -249,7 +249,18 @@ private Ruby(RubyInstanceConfig config) {

constant = OptoFactory.newConstantWrapper(Ruby.class, this);

getJRubyClassLoader(); // force JRubyClassLoader to init if possible
// force JRubyClassLoader to init if possible
if (!Ruby.isSecurityRestricted()) {
if (config.isClassloaderDelegate()){
jrubyClassLoader = new JRubyClassLoader(config.getLoader());
}
else {
jrubyClassLoader = new SelfFirstJRubyClassLoader(config.getLoader());
}
}
else {
jrubyClassLoader = null; // a NullClassLoader object would be better ...
}

this.staticScopeFactory = new StaticScopeFactory(this);
this.beanManager = BeanManagerFactory.create(this, config.isManagementEnabled());
@@ -2515,16 +2526,24 @@ public RubyClass getInvalidByteSequenceError() {
return invalidByteSequenceError;
}

private RubyRandom.RandomType defaultRand;
RubyRandom.RandomType defaultRand;

/**
* @deprecated internal API, to be hidden
*/
public RubyRandom.RandomType getDefaultRand() {
return defaultRand;
}

/**
* @deprecated internal API, to be hidden
*/
public void setDefaultRand(RubyRandom.RandomType defaultRand) {
this.defaultRand = defaultRand;
}

private RubyHash charsetMap;
@Deprecated // no longer used (internal API)
public RubyHash getCharsetMap() {
if (charsetMap == null) charsetMap = new RubyHash(this);
return charsetMap;
@@ -2586,24 +2605,7 @@ public static ClassLoader getClassLoader() {
return loader;
}

/**
* TODO the property {@link #jrubyClassLoader} will only be set in constructor. in the first call of
* {@link #getJRubyClassLoader() getJRubyClassLoader}. So the field {@link #jrubyClassLoader} can be final
* set in the constructor directly and we avoid the synchronized here.
*
* @return
*/
public synchronized JRubyClassLoader getJRubyClassLoader() {
// FIXME: Get rid of laziness and handle restricted access elsewhere
if (!Ruby.isSecurityRestricted() && jrubyClassLoader == null) {
if (config.isClassloaderDelegate()){
jrubyClassLoader = new JRubyClassLoader(config.getLoader());
}
else {
jrubyClassLoader = new SelfFirstJRubyClassLoader(config.getLoader());
}
}

public JRubyClassLoader getJRubyClassLoader() {
return jrubyClassLoader;
}

@@ -3336,9 +3338,9 @@ public void tearDown(boolean systemExit) {
* release the runtime loader but not otherwise - you should do that manually.
*/
public void releaseClassLoader() {
if ( jrubyClassLoader != null ) {
getJRubyClassLoader().close();
jrubyClassLoader = null;
if (jrubyClassLoader != null) {
jrubyClassLoader.close();
//jrubyClassLoader = null;
}
}

@@ -4575,6 +4577,9 @@ public CoverageData getCoverageData() {
return coverageData;
}

/**
* @deprecated internal API, to be removed
*/
public Random getRandom() {
return random;
}
@@ -4954,7 +4959,7 @@ private MRIRecursionGuard oldRecursionGuard() {

// Java support
private JavaSupport javaSupport;
private JRubyClassLoader jrubyClassLoader;
private final JRubyClassLoader jrubyClassLoader;

// Management/monitoring
private BeanManager beanManager;
@@ -5090,7 +5095,7 @@ private MRIRecursionGuard oldRecursionGuard() {
private static ThreadLocal<Ruby> threadLocalRuntime = new ThreadLocal<Ruby>();

/** The runtime-local random number generator. Uses SecureRandom if permissions allow. */
private final Random random;
final Random random;

/** The runtime-local seed for hash randomization */
private final long hashSeedK0;
1 change: 1 addition & 0 deletions core/src/main/java/org/jruby/RubyBasicObject.java
Original file line number Diff line number Diff line change
@@ -260,6 +260,7 @@ protected RubyBasicObject(Ruby runtime, RubyClass metaClass, boolean useObjectSp
runtime.addToObjectSpace(useObjectSpace, this);
}

@Deprecated
protected void taint(Ruby runtime) {
if (!isTaint()) {
testFrozen();
47 changes: 23 additions & 24 deletions core/src/main/java/org/jruby/RubyComplex.java
Original file line number Diff line number Diff line change
@@ -1021,15 +1021,18 @@ public IRubyObject infinite_p(ThreadContext context) {
return sites(context).infinite.call(context, magnitude, magnitude);
}

private static final ByteList SEP = RubyFile.SLASH;
private static final ByteList _eE = new ByteList(new byte[] { '.', 'e', 'E' }, false);

static RubyArray str_to_c_internal(ThreadContext context, IRubyObject recv) {
RubyString s = recv.convertToString();
ByteList bytes = s.getByteList();

Ruby runtime = context.runtime;
if (bytes.getRealSize() == 0) return runtime.newArray(runtime.getNil(), recv);
if (bytes.getRealSize() == 0) return runtime.newArray(context.nil, recv);

IRubyObject sr, si, re;
sr = si = re = runtime.getNil();
sr = si = re = context.nil;
boolean po = false;
IRubyObject m = RubyRegexp.newDummyRegexp(runtime, Numeric.ComplexPatterns.comp_pat0).match_m(context, s, false);

@@ -1059,15 +1062,15 @@ static RubyArray str_to_c_internal(ThreadContext context, IRubyObject recv) {

if (m.isNil()) {
m = RubyRegexp.newDummyRegexp(runtime, Numeric.ComplexPatterns.comp_pat2).match_m(context, s, false);
if (m.isNil()) return runtime.newArray(runtime.getNil(), recv);
if (m.isNil()) return runtime.newArray(context.nil, recv);
RubyMatchData match = (RubyMatchData)m;
sr = match.at(1);
if (match.at(2).isNil()) {
si = runtime.getNil();
si = context.nil;
} else {
si = match.at(3);
IRubyObject t = match.at(4);
if (t.isNil()) t = runtime.newString(RubyFixnum.SINGLE_CHAR_BYTELISTS19['1']);
if (t.isNil()) t = runtime.newString(RubyInteger.singleCharByteList((byte) '1'));
si.convertToString().cat(t.convertToString().getByteList());
}
re = match.post_match(context);
@@ -1077,28 +1080,24 @@ static RubyArray str_to_c_internal(ThreadContext context, IRubyObject recv) {
IRubyObject r = RubyFixnum.zero(runtime);
IRubyObject i = r;

if (!sr.isNil()) {
if (sr.callMethod(context, "include?", runtime.newString(new ByteList(new byte[]{'/'}))).isTrue()) {
r = f_to_r(context, sr);
} else if (f_gt_p(context, sr.callMethod(context, "count", runtime.newString(".eE")), RubyFixnum.zero(runtime)).isTrue()) {
r = f_to_f(context, sr);
} else {
r = f_to_i(context, sr);
}
}
r = convertString(context, sr, r);
i = convertString(context, si, i);

if (!si.isNil()) {
if (si.callMethod(context, "include?", runtime.newString(new ByteList(new byte[]{'/'}))).isTrue()) {
i = f_to_r(context, si);
} else if (f_gt_p(context, si.callMethod(context, "count", runtime.newString(".eE")), RubyFixnum.zero(runtime)).isTrue()) {
i = f_to_f(context, si);
} else {
i = f_to_i(context, si);
}
}
return runtime.newArray(po ? newComplexPolar(context, r, i) : newComplexCanonicalize(context, r, i), re);
}


private static IRubyObject convertString(ThreadContext context, final IRubyObject s, IRubyObject def) {
if (s == context.nil) return def;
final Ruby runtime = context.runtime;
if (s.callMethod(context, "include?", RubyString.newStringShared(runtime, SEP)).isTrue()) {
return f_to_r(context, s);
}
if (f_gt_p(context, s.callMethod(context, "count", RubyString.newStringShared(runtime, _eE)), RubyFixnum.zero(runtime)).isTrue()) {
return f_to_f(context, s);
}
return f_to_i(context, s);
}

private static IRubyObject str_to_c_strict(ThreadContext context, IRubyObject recv) {
RubyArray a = str_to_c_internal(context, recv);
if (a.eltInternal(0).isNil() || a.eltInternal(1).convertToString().getByteList().length() > 0) {
10 changes: 7 additions & 3 deletions core/src/main/java/org/jruby/RubyFile.java
Original file line number Diff line number Diff line change
@@ -92,6 +92,10 @@
**/
@JRubyClass(name="File", parent="IO", include="FileTest")
public class RubyFile extends RubyIO implements EncodingCapable {

static final ByteList SLASH = new ByteList(new byte[] { '/' }, false);
static final ByteList BACKSLASH = new ByteList(new byte[] { '\\' }, false);

public static RubyClass createFileClass(Ruby runtime) {
ThreadContext context = runtime.getCurrentContext();

@@ -107,13 +111,13 @@ public static RubyClass createFileClass(Ruby runtime) {
fileClass.kindOf = new RubyModule.JavaClassKindOf(RubyFile.class);

// file separator constants
RubyString separator = RubyString.newString(runtime, new ByteList(new byte[] { '/' }, false));
RubyString separator = RubyString.newString(runtime, SLASH);
separator.freeze(context);
fileClass.defineConstant("SEPARATOR", separator);
fileClass.defineConstant("Separator", separator);

if (File.separatorChar == '\\') {
RubyString altSeparator = RubyString.newString(runtime, new ByteList(new byte[] { '\\' }, false));
RubyString altSeparator = RubyString.newString(runtime, BACKSLASH);
altSeparator.freeze(context);
fileClass.defineConstant("ALT_SEPARATOR", altSeparator);
} else {
@@ -1153,7 +1157,7 @@ public static IRubyObject utime(ThreadContext context, IRubyObject recv, IRubyOb
long[] atimeval = null;
long[] mtimeval = null;

if (args[0] != runtime.getNil() || args[1] != runtime.getNil()) {
if (args[0] != context.nil || args[1] != context.nil) {
atimeval = extractTimeval(context, args[0]);
mtimeval = extractTimeval(context, args[1]);
}
5 changes: 2 additions & 3 deletions core/src/main/java/org/jruby/RubyFloat.java
Original file line number Diff line number Diff line change
@@ -183,9 +183,8 @@ public RubyFloat convertToFloat() {
return this;
}

protected int compareValue(RubyNumeric other) {
double otherVal = other.getDoubleValue();
return getValue() > otherVal ? 1 : getValue() < otherVal ? -1 : 0;
public int signum() {
return (int) Math.signum(value); // NOTE: (int) NaN ?
}

public static RubyFloat newFloat(Ruby runtime, double value) {
16 changes: 5 additions & 11 deletions core/src/main/java/org/jruby/RubyGenerator.java
Original file line number Diff line number Diff line change
@@ -60,7 +60,7 @@ public RubyGenerator(Ruby runtime, RubyClass klass) {
public IRubyObject initialize(ThreadContext context, IRubyObject[] args, Block block) {
Ruby runtime = context.runtime;

IRubyObject proc;
final IRubyObject proc;

if (args.length == 0) {
proc = RubyProc.newProc(runtime, block, Block.Type.PROC);
@@ -76,7 +76,9 @@ public IRubyObject initialize(ThreadContext context, IRubyObject[] args, Block b
}
}

return init(runtime, proc);
// generator_init
this.proc = proc;
return this;
}

// generator_init_copy
@@ -96,15 +98,7 @@ public IRubyObject initialize_copy(ThreadContext context, IRubyObject other) {
// generator_each
@JRubyMethod(rest = true)
public IRubyObject each(ThreadContext context, IRubyObject[] args, Block block) {
return ((RubyProc) proc).call19(context, ArraySupport.newCopy(RubyYielder.newYielder(context, block), args), Block.NULL_BLOCK);
}


// generator_init
private IRubyObject init(Ruby runtime, IRubyObject proc) {
this.proc = proc;

return this;
return ((RubyProc) proc).call(context, ArraySupport.newCopy(RubyYielder.newYielder(context, block), args), Block.NULL_BLOCK);
}

private IRubyObject proc;
14 changes: 7 additions & 7 deletions core/src/main/java/org/jruby/RubyIO.java
Original file line number Diff line number Diff line change
@@ -1073,7 +1073,7 @@ public IRubyObject internal_encoding(ThreadContext context) {
public IRubyObject set_encoding(ThreadContext context, IRubyObject encodingObj) {
setEncoding(context, encodingObj, context.nil, context.nil);

return context.nil;
return this;
}

@JRubyMethod
@@ -1085,14 +1085,14 @@ public IRubyObject set_encoding(ThreadContext context, IRubyObject encodingStrin
setEncoding(context, encodingString, internalEncoding, context.nil);
}

return context.nil;
return this;
}

@JRubyMethod
public IRubyObject set_encoding(ThreadContext context, IRubyObject encodingString, IRubyObject internalEncoding, IRubyObject options) {
setEncoding(context, encodingString, internalEncoding, options);

return context.nil;
return this;
}

// mri: io_encoding_set
@@ -1642,9 +1642,9 @@ public IRubyObject printf(ThreadContext context, IRubyObject[] args) {
public IRubyObject putc(ThreadContext context, IRubyObject ch) {
IRubyObject str;
if (ch instanceof RubyString) {
str = ((RubyString)ch).substr(context.runtime, 0, 1);
str = ((RubyString) ch).substr(context.runtime, 0, 1);
} else {
str = RubyString.newStringShared(context.runtime, RubyFixnum.SINGLE_CHAR_BYTELISTS19[RubyNumeric.num2chr(ch) & 0xFF]);
str = RubyString.newStringShared(context.runtime, RubyInteger.singleCharByteList(RubyNumeric.num2chr(ch)));
}

sites(context).write.call(context, this, this, str);
@@ -1654,10 +1654,10 @@ public IRubyObject putc(ThreadContext context, IRubyObject ch) {

public static IRubyObject putc(ThreadContext context, IRubyObject maybeIO, IRubyObject object) {
if (maybeIO instanceof RubyIO) {
((RubyIO)maybeIO).putc(context, object);
((RubyIO) maybeIO).putc(context, object);
} else {
byte c = RubyNumeric.num2chr(object);
IRubyObject str = RubyString.newStringShared(context.runtime, RubyFixnum.SINGLE_CHAR_BYTELISTS19[c & 0xFF]);
IRubyObject str = RubyString.newStringShared(context.runtime, RubyInteger.singleCharByteList(c));
sites(context).write.call(context, maybeIO, maybeIO, str);
}

29 changes: 14 additions & 15 deletions core/src/main/java/org/jruby/RubyInteger.java
Original file line number Diff line number Diff line change
@@ -298,20 +298,20 @@ public IRubyObject succ(ThreadContext context) {
}

static final ByteList[] SINGLE_CHAR_BYTELISTS;
@Deprecated
public static final ByteList[] SINGLE_CHAR_BYTELISTS19;
static {
SINGLE_CHAR_BYTELISTS = new ByteList[256];
SINGLE_CHAR_BYTELISTS19 = new ByteList[256];
for (int i = 0; i < 256; i++) {
ByteList usascii = new ByteList(new byte[]{(byte)i}, false);
SINGLE_CHAR_BYTELISTS[i] = usascii;
SINGLE_CHAR_BYTELISTS19[i] = i < 0x80 ?
new ByteList(new byte[]{(byte)i}, USASCIIEncoding.INSTANCE)
:
new ByteList(
new byte[]{(byte)i},
ASCIIEncoding.INSTANCE);
ByteList bytes = new ByteList(new byte[] { (byte) i }, false);
SINGLE_CHAR_BYTELISTS[i] = bytes;
bytes.setEncoding(i < 0x80 ? USASCIIEncoding.INSTANCE : ASCIIEncoding.INSTANCE);
}
SINGLE_CHAR_BYTELISTS19 = SINGLE_CHAR_BYTELISTS;
}

static ByteList singleCharByteList(final byte index) {
return SINGLE_CHAR_BYTELISTS[index & 0xFF];
}

/** int_chr
@@ -320,18 +320,17 @@ public IRubyObject succ(ThreadContext context) {
@JRubyMethod(name = "chr")
public RubyString chr(ThreadContext context) {
Ruby runtime = context.runtime;
int value = (int)getLongValue();
int value = (int) getLongValue();
if (value >= 0 && value <= 0xFF) {
ByteList bytes = SINGLE_CHAR_BYTELISTS19[value];
ByteList bytes = SINGLE_CHAR_BYTELISTS[value];
return RubyString.newStringShared(runtime, bytes, bytes.getEncoding());
} else {
Encoding enc = runtime.getDefaultInternalEncoding();
if (value > 0xFF && (enc == null || enc == ASCIIEncoding.INSTANCE)) {
throw runtime.newRangeError(this.toString() + " out of char range");
} else {
if (enc == null) enc = USASCIIEncoding.INSTANCE;
return RubyString.newStringNoCopy(runtime, fromEncodedBytes(runtime, enc, value), enc, 0);
throw runtime.newRangeError(toString() + " out of char range");
}
if (enc == null) enc = USASCIIEncoding.INSTANCE;
return RubyString.newStringNoCopy(runtime, fromEncodedBytes(runtime, enc, value), enc, 0);
}
}

6 changes: 2 additions & 4 deletions core/src/main/java/org/jruby/RubyKernel.java
Original file line number Diff line number Diff line change
@@ -57,7 +57,6 @@
import org.jruby.runtime.Block;
import org.jruby.runtime.CallType;
import org.jruby.runtime.Helpers;
import org.jruby.runtime.JavaSites;
import org.jruby.runtime.JavaSites.KernelSites;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.Visibility;
@@ -76,7 +75,6 @@
import org.jruby.util.io.PopenExecutor;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
@@ -1521,8 +1519,8 @@ public static IRubyObject rand19(ThreadContext context, IRubyObject recv, IRubyO
}

@JRubyMethod(name = "rand", module = true, optional = 1, visibility = PRIVATE)
public static IRubyObject rand(ThreadContext context, IRubyObject recv, IRubyObject[] arg) {
return RubyRandom.randCommon19(context, recv, arg);
public static IRubyObject rand(ThreadContext context, IRubyObject recv, IRubyObject[] args) {
return RubyRandom.randKernel(context, args);
}

@JRubyMethod(rest = true, module = true, visibility = PRIVATE)
8 changes: 4 additions & 4 deletions core/src/main/java/org/jruby/RubyNumeric.java
Original file line number Diff line number Diff line change
@@ -204,9 +204,9 @@ private static void tooBig(IRubyObject arg, long num) {
*/
public static byte num2chr(IRubyObject arg) {
if (arg instanceof RubyString) {
String value = arg.toString();

if (value != null && value.length() > 0) return (byte) value.charAt(0);
if (((RubyString) arg).size() > 0) {
return (byte) ((RubyString) arg).getByteList().get(0);
}
}

return (byte) num2int(arg);
@@ -332,7 +332,7 @@ public static RubyInteger str2inum(Ruby runtime, RubyString str, int base) {
return str2inum(runtime, str, base, false);
}

public static RubyNumeric int2fix(Ruby runtime, long val) {
public static RubyInteger int2fix(Ruby runtime, long val) {
return RubyFixnum.newFixnum(runtime, val);
}

23 changes: 12 additions & 11 deletions core/src/main/java/org/jruby/RubyProc.java
Original file line number Diff line number Diff line change
@@ -241,14 +241,6 @@ public IRubyObject binding() {
return getRuntime().newBinding(block.getBinding());
}

public IRubyObject call(ThreadContext context, IRubyObject[] args, Block block) {
return call19(context, args, block);
}

public IRubyObject call(ThreadContext context, IRubyObject[] args) {
return call(context, args, null, Block.NULL_BLOCK);
}

/**
* For Type.LAMBDA, ensures that the args have the correct arity.
*
@@ -270,13 +262,17 @@ public static IRubyObject[] prepareArgs(ThreadContext context, Block.Type type,
}

@JRubyMethod(name = {"call", "[]", "yield", "==="}, rest = true, omit = true)
public final IRubyObject call19(ThreadContext context, IRubyObject[] args, Block blockCallArg) {
public final IRubyObject call(ThreadContext context, IRubyObject[] args, Block blockCallArg) {
IRubyObject[] preppedArgs = prepareArgs(context, type, block.getBody(), args);

return call(context, preppedArgs, null, blockCallArg);
}

public IRubyObject call(ThreadContext context, IRubyObject[] args, IRubyObject self, Block passedBlock) {
public final IRubyObject call(ThreadContext context, IRubyObject[] args) {
return call(context, args, null, Block.NULL_BLOCK);
}

public final IRubyObject call(ThreadContext context, IRubyObject[] args, IRubyObject self, Block passedBlock) {
assert args != null;

Block newBlock;
@@ -318,7 +314,7 @@ public IRubyObject source_location(ThreadContext context) {
runtime.newFixnum(binding.getLine() + 1 /*zero-based*/));
}

return runtime.getNil();
return context.nil;
}

@JRubyMethod
@@ -346,4 +342,9 @@ private boolean isThread() {
return type.equals(Block.Type.THREAD);
}

@Deprecated
public final IRubyObject call19(ThreadContext context, IRubyObject[] args, Block block) {
return call(context, args, block);
}

}
158 changes: 82 additions & 76 deletions core/src/main/java/org/jruby/RubyRandom.java
Original file line number Diff line number Diff line change
@@ -44,22 +44,25 @@
@JRubyClass(name = "Random")
public class RubyRandom extends RubyObject {

public static class RandomType {
private final IRubyObject seed;
/**
* Internal API, subject to change.
*/
public static final class RandomType {
private final RubyInteger seed;
private final Random impl;

// RandomType(Ruby runtime) { this(randomSeed(runtime)); }

// c: rand_init
RandomType(IRubyObject vseed) {
this.seed = vseed.convertToInteger();
if (seed instanceof RubyFixnum) {
this.impl = randomFromFixnum((RubyFixnum) seed);
} else if (seed instanceof RubyBignum) {
this.impl = randomFromBignum((RubyBignum) seed);
RandomType(IRubyObject seed) {
this.seed = seed.convertToInteger();
if (this.seed instanceof RubyFixnum) {
this.impl = randomFromFixnum((RubyFixnum) this.seed);
} else if (this.seed instanceof RubyBignum) {
this.impl = randomFromBignum((RubyBignum) this.seed);
} else {
throw vseed.getRuntime().newTypeError(
String.format("failed to convert %s into Integer", vseed.getMetaClass().getName()));
throw seed.getRuntime().newTypeError(
String.format("failed to convert %s into Integer", seed.getMetaClass().getName()));
}
}

@@ -143,7 +146,7 @@ int genrandInt32() {
return impl.genrandReal2();
}

IRubyObject getSeed() {
RubyInteger getSeed() {
return seed;
}

@@ -214,9 +217,10 @@ public static BigInteger randomSeedBigInteger(java.util.Random random) {

// c: random_seed
public static RubyBignum randomSeed(Ruby runtime) {
return RubyBignum.newBignum(runtime, randomSeedBigInteger(runtime.getRandom()));
return RubyBignum.newBignum(runtime, randomSeedBigInteger(runtime.random));
}

@SuppressWarnings("deprecation")
public static RubyClass createRandomClass(Ruby runtime) {
RubyClass randomClass = runtime
.defineClass("Random", runtime.getObject(), RANDOM_ALLOCATOR);
@@ -257,9 +261,9 @@ public IRubyObject seed(ThreadContext context) {
@Override
public IRubyObject initialize_copy(IRubyObject orig) {
if (!(orig instanceof RubyRandom)) {
throw getRuntime().newTypeError(
String.format("wrong argument type %s (expected %s)", orig.getMetaClass()
.getName(), getMetaClass().getName()));
throw getRuntime().newTypeError(String.format(
"wrong argument type %s (expected %s)", orig.getMetaClass().getName(), getMetaClass().getName())
);
}
checkFrozen();
random = new RandomType(((RubyRandom) orig).random);
@@ -269,20 +273,25 @@ public IRubyObject initialize_copy(IRubyObject orig) {
@JRubyMethod(name = "rand", meta = true, optional = 1)
public static IRubyObject rand(ThreadContext context, IRubyObject recv, IRubyObject[] args) {
RandomType random = getDefaultRand(context);
if (args.length == 0) {
return randFloat(context, random);
}
if (args.length == 0) return randFloat(context, random);

return randomRand(context, args[0], random);
}

// c: rb_f_rand for 1.9
@Deprecated // not-used
public static IRubyObject randCommon19(ThreadContext context, IRubyObject recv, IRubyObject[] args) {
return randKernel(context, args);
}

// c: rb_f_rand for 1.9
static IRubyObject randKernel(ThreadContext context, IRubyObject[] args) {
RandomType random = getDefaultRand(context);
if (args.length == 0) {
return randFloat(context, random);
}

IRubyObject arg = args[0];
if (arg.isNil()) {
if (arg == context.nil) {
return randFloat(context, random);
}

@@ -291,18 +300,11 @@ public static IRubyObject randCommon19(ThreadContext context, IRubyObject recv,
}

RubyInteger max = arg.convertToInteger();
return randCommon(context, random, max);
}

private static IRubyObject randCommon(ThreadContext context, RandomType random, RubyInteger max) {
if (max.zero_p(context).isTrue()) {
return randFloat(context, random);
}
IRubyObject r = randInt(context, random, max, false);
if (r.isNil()) {
return randFloat(context, random);
}
return r;
return (r == context.nil) ? randFloat(context, random) : r;
}

@Deprecated
@@ -325,13 +327,9 @@ private static IRubyObject randInt(ThreadContext context, RandomType random, Rub
boolean restrictive) {
if (vmax instanceof RubyFixnum) {
long max = RubyNumeric.fix2long(vmax);
if (max == 0) {
return context.nil;
}
if (max == 0) return context.nil;
if (max < 0) {
if (restrictive) {
return context.nil;
}
if (restrictive) return context.nil;
max = -max;
}
return randLimitedFixnum(context, random, max - 1);
@@ -341,23 +339,29 @@ private static IRubyObject randInt(ThreadContext context, RandomType random, Rub
return context.nil;
}
if (big.signum() < 0) {
if (restrictive) {
return context.nil;
}
if (restrictive) return context.nil;
big = big.abs();
}
big = big.subtract(BigInteger.ONE);
return randLimitedBignum(context, random, RubyBignum.newBignum(context.runtime, big));
return randLimitedBignum(context, random, big);
}
}

public static RubyFloat randFloat(ThreadContext context) {
return randFloat(context, getDefaultRand(context));
}

public static RubyFloat randFloat(ThreadContext context, RandomType random) {
return context.runtime.newFloat(random.genrandReal());
}

public static RubyInteger randLimited(ThreadContext context, long limit) {
return randLimitedFixnum(context, getDefaultRand(context), limit);
}

// c: limited_rand
// limited_rand gets/returns ulong but we do this in signed long only.
private static IRubyObject randLimitedFixnum(ThreadContext context, RandomType random, long limit) {
private static RubyInteger randLimitedFixnum(ThreadContext context, RandomType random, long limit) {
return RubyFixnum.newFixnum(context.runtime, randLimitedFixnumInner(random.impl, limit));
}

@@ -385,9 +389,13 @@ public static long randLimitedFixnumInner(Random random, long limit) {
return val;
}

public static RubyInteger randLimited(ThreadContext context, BigInteger limit) {
return randLimitedBignum(context, getDefaultRand(context), limit);
}

// c: limited_big_rand
private static IRubyObject randLimitedBignum(ThreadContext context, RandomType random, RubyBignum limit) {
byte[] buf = limit.getBigIntegerValue().toByteArray();
private static RubyInteger randLimitedBignum(ThreadContext context, RandomType random, BigInteger limit) {
byte[] buf = limit.toByteArray();
byte[] bytes = new byte[buf.length];
int len = (buf.length + 3) / 4;
// take care before code cleanup; it might break random sequence compatibility
@@ -429,23 +437,24 @@ private static long makeMask(long x) {
}

private static RandomType getDefaultRand(ThreadContext context) {
return context.runtime.getDefaultRand();
return context.runtime.defaultRand;
}

// c: random_rand
private static IRubyObject randomRand(ThreadContext context, IRubyObject vmax, RandomType random) {
IRubyObject v;
RangeLike range = null;
if (vmax.isNil()) {
v = context.nil;
final IRubyObject nil = context.nil;
if (vmax == nil) {
v = nil;
} else if ((v = checkMaxInt(context, vmax)) != null) {
v = randInt(context, random, (RubyInteger) v, true);
} else if (!(v = TypeConverter.checkFloatType(context.runtime, vmax)).isNil()) {
} else if ((v = TypeConverter.checkFloatType(context.runtime, vmax)) != nil) {
double max = ((RubyFloat) v).getDoubleValue();
if (max > 0.0) {
v = context.runtime.newFloat(max * random.genrandReal());
} else {
v = context.nil;
v = nil;
}
} else if ((range = rangeValues(context, vmax)) != null) {
if ((v = checkMaxInt(context, range.range)) != null) {
@@ -457,23 +466,22 @@ private static IRubyObject randomRand(ThreadContext context, IRubyObject vmax, R
if (max >= 0) {
v = randLimitedFixnum(context, random, max);
} else {
v = context.nil;
v = nil;
}
} else if (v instanceof RubyBignum) {
BigInteger big = ((RubyBignum) v).getBigIntegerValue();
if (!big.equals(BigInteger.ZERO) && (big.signum() > 0)) {
if (range.excl) {
big = big.subtract(BigInteger.ONE);
}
v = randLimitedBignum(context, random, RubyBignum.newBignum(
context.runtime, big));
v = randLimitedBignum(context, random, big);
} else {
v = context.nil;
v = nil;
}
} else {
v = context.nil;
v = nil;
}
} else if (!(v = TypeConverter.checkFloatType(context.runtime, range.range)).isNil()) {
} else if ((v = TypeConverter.checkFloatType(context.runtime, range.range)) != nil) {
int scale = 1;
double max = ((RubyFloat) v).getDoubleValue();
double mid = 0.5;
@@ -503,26 +511,23 @@ private static IRubyObject randomRand(ThreadContext context, IRubyObject vmax, R
}
}
} else {
v = context.nil;
v = nil;
RubyNumeric.num2long(vmax); // need check here to raise TypeError
}
if (v.isNil()) {
throw context.runtime.newArgumentError("invalid argument - " + vmax.toString());
if (v == nil) {
throw context.runtime.newArgumentError("invalid argument - " + vmax);
}
if (range == null) {
return v;
}
if ((range.begin instanceof RubyFixnum) && (v instanceof RubyFixnum)) {
if (range == null) return v;
if (range.begin instanceof RubyFixnum && v instanceof RubyFixnum) {
long x = ((RubyFixnum) range.begin).getLongValue() + ((RubyFixnum) v).getLongValue();
return context.runtime.newFixnum(x);
}
if (v instanceof RubyBignum) {
return ((RubyBignum) v).op_plus(context, range.begin);
} else if (v instanceof RubyFloat) {
}
if (v instanceof RubyFloat) {
IRubyObject f = TypeConverter.checkFloatType(context.runtime, range.begin);
if (!f.isNil()) {
return ((RubyFloat) v).op_plus(context, f);
}
if (f != nil) return ((RubyFloat) v).op_plus(context, f);
}
return Helpers.invoke(context, range.begin, "+", v);
}
@@ -550,9 +555,7 @@ private static void checkFloatValue(ThreadContext context, double x) {
private static IRubyObject checkMaxInt(ThreadContext context, IRubyObject vmax) {
if (!(vmax instanceof RubyFloat)) {
IRubyObject v = TypeConverter.checkIntegerType(context, vmax);
if (!v.isNil()) {
return v;
}
if (v != context.nil) return v;
}
return null;
}
@@ -570,15 +573,15 @@ private static RangeLike rangeValues(ThreadContext context, IRubyObject range) {
RubyRange vrange = (RubyRange) range;
like.begin = vrange.first(context);
like.end = vrange.last(context);
like.excl = vrange.exclude_end_p().isTrue();
like.excl = vrange.isExcludeEnd();
} else {
if (!range.respondsTo("begin") || !range.respondsTo("end")
|| !range.respondsTo("exclude_end?")) {
return null;
}
like.begin = Helpers.invoke(context, range, "begin");
like.end = Helpers.invoke(context, range, "end");
like.excl = Helpers.invoke(context, range, "exlucde_end?").isTrue();
like.excl = Helpers.invoke(context, range, "exclude_end?").isTrue();
}
like.range = Helpers.invoke(context, like.end, "-", like.begin);
return like;
@@ -600,22 +603,25 @@ public static IRubyObject srandCommon(ThreadContext context, IRubyObject recv) {
}

// c: rb_f_srand
public static IRubyObject srandCommon(ThreadContext context, IRubyObject recv,
IRubyObject newSeed) {
@SuppressWarnings("deprecation")
public static IRubyObject srandCommon(ThreadContext context, IRubyObject recv, IRubyObject newSeed) {
RandomType defaultRand = getDefaultRand(context);
IRubyObject previousSeed = defaultRand.getSeed();
defaultRand = new RandomType(newSeed);
context.runtime.setDefaultRand(defaultRand);
((RubyRandom) (context.runtime.getRandomClass())
.getConstant("DEFAULT")).setRandomType(defaultRand);
((RubyRandom) (context.runtime.getRandomClass()).getConstant("DEFAULT")).setRandomType(defaultRand);
return previousSeed;
}

// c: random_equal
@Deprecated
public IRubyObject op_equal_19(ThreadContext context, IRubyObject obj) {
return op_equal(context, obj);
}

// c: random_equal
@Override
@JRubyMethod(name = "==", required = 1)
public IRubyObject op_equal_19(ThreadContext context, IRubyObject obj) {
public IRubyObject op_equal(ThreadContext context, IRubyObject obj) {
if (!getType().equals(obj.getType())) {
return context.runtime.getFalse();
}
@@ -650,7 +656,7 @@ public static IRubyObject left(ThreadContext context, IRubyObject recv) {
@JRubyMethod(name = "marshal_dump")
public IRubyObject marshal_dump(ThreadContext context) {
RubyBignum state = random.getState();
RubyInteger left = (RubyInteger) RubyNumeric.int2fix(context.runtime, random.getLeft());
RubyInteger left = RubyNumeric.int2fix(context.runtime, random.getLeft());
RubyArray dump = RubyArray.newArray(context.runtime, state, left, random.getSeed());
if (hasVariables()) {
dump.syncVariables(this);
@@ -751,7 +757,7 @@ public static IRubyObject rawSeed(ThreadContext context, IRubyObject recv, IRuby
if (n == 0) return runtime.newString();

byte[] seed = new byte[n];
runtime.getRandom().nextBytes(seed);
runtime.random.nextBytes(seed);

return RubyString.newString(runtime, seed);
}
26 changes: 20 additions & 6 deletions core/src/main/java/org/jruby/RubyRange.java
Original file line number Diff line number Diff line change
@@ -302,8 +302,8 @@ public RubyFixnum hash(ThreadContext context) {
return context.runtime.newFixnum(hash);
}

private IRubyObject inspectValue(final ThreadContext context, IRubyObject value) {
return context.safeRecurse(INSPECT_RECURSIVE, value, value, "inspect", true);
private static RubyString inspectValue(final ThreadContext context, IRubyObject value) {
return (RubyString) context.safeRecurse(INSPECT_RECURSIVE, value, value, "inspect", true);
}

private static class InspectRecursive implements ThreadContext.RecursiveFunctionEx<IRubyObject> {
@@ -320,20 +320,34 @@ public IRubyObject call(ThreadContext context, IRubyObject state, IRubyObject ob

private static final byte[] DOTDOTDOT = new byte[]{'.', '.', '.'};

@Override
public IRubyObject inspect() {
return inspect(getRuntime().getCurrentContext());
}

@JRubyMethod(name = "inspect")
public IRubyObject inspect(final ThreadContext context) {
RubyString i1 = ((RubyString) inspectValue(context, begin)).strDup(context.runtime);
RubyString i2 = (RubyString) inspectValue(context, end);
public RubyString inspect(final ThreadContext context) {
RubyString i1 = inspectValue(context, begin).strDup(context.runtime);
RubyString i2 = inspectValue(context, end);
i1.cat(DOTDOTDOT, 0, isExclusive ? 3 : 2);
i1.append(i2);
i1.infectBy(i2);
i1.infectBy(this);
return i1;
}

@Override
public IRubyObject to_s() {
return to_s(getRuntime());
}

@JRubyMethod(name = "to_s")
public IRubyObject to_s(final ThreadContext context) {
RubyString i1 = begin.asString().strDup(context.runtime);
return to_s(context.runtime);
}

private RubyString to_s(final Ruby runtime) {
RubyString i1 = begin.asString().strDup(runtime);
RubyString i2 = end.asString();
i1.cat(DOTDOTDOT, 0, isExclusive ? 3 : 2);
i1.append(i2);
26 changes: 16 additions & 10 deletions core/src/main/java/org/jruby/RubyRational.java
Original file line number Diff line number Diff line change
@@ -763,31 +763,32 @@ public IRubyObject idiv(ThreadContext context, IRubyObject other) {
/** nurat_mod
*
*/
public IRubyObject op_mod(ThreadContext context, IRubyObject other) {
return op_mod19(context, other);
}

@JRubyMethod(name = {"modulo", "%"})
public IRubyObject op_mod19(ThreadContext context, IRubyObject other) {
public IRubyObject op_mod(ThreadContext context, IRubyObject other) {
if (num2dbl(other) == 0.0) throw context.runtime.newZeroDivisionError();

return f_sub(context, this, f_mul(context, other, f_floor(context, f_div(context, this, other))));
}

@Deprecated
public IRubyObject op_mod19(ThreadContext context, IRubyObject other) {
return op_mod(context, other);
}

/** nurat_divmod
*
*/
public IRubyObject op_divmod(ThreadContext context, IRubyObject other) {
return op_divmod19(context, other);
}

@JRubyMethod(name = "divmod")
public IRubyObject op_divmod19(ThreadContext context, IRubyObject other) {
public IRubyObject op_divmod(ThreadContext context, IRubyObject other) {
if (num2dbl(other) == 0.0) throw context.runtime.newZeroDivisionError();

IRubyObject val = f_floor(context, f_div(context, this, other));
return context.runtime.newArray(val, f_sub(context, this, f_mul(context, other, val)));
}

@Deprecated
public IRubyObject op_divmod19(ThreadContext context, IRubyObject other) {
return op_divmod(context, other);
}

/** nurat_rem
@@ -1350,6 +1351,11 @@ public IRubyObject op_idiv19(ThreadContext context, IRubyObject other) {
return idiv(context, other);
}

@Deprecated
public IRubyObject op_idiv(ThreadContext context, IRubyObject other) {
return idiv(context, other);
}

private static JavaSites.RationalSites sites(ThreadContext context) {
return context.sites.Rational;
}
20 changes: 12 additions & 8 deletions core/src/main/java/org/jruby/RubyString.java
Original file line number Diff line number Diff line change
@@ -573,8 +573,15 @@ public static RubyString newStringShared(Ruby runtime, RubyClass clazz, ByteList
}

public static RubyString newStringShared(Ruby runtime, RubyClass clazz, ByteList bytes, Encoding encoding) {
RubyString str = new RubyString(runtime, clazz, bytes, encoding);
str.shareLevel = SHARE_LEVEL_BYTELIST;
if (bytes.getEncoding() == encoding) return newStringShared(runtime, clazz, bytes);
RubyString str = new RubyString(runtime, clazz, bytes.makeShared(bytes.getBegin(), bytes.getRealSize()), encoding);
str.shareLevel = SHARE_LEVEL_BUFFER; // since passing an encoding in does bytes.setEncoding(encoding)
return str;
}

private static RubyString newStringShared(Ruby runtime, ByteList bytes, Encoding encoding, int cr) {
RubyString str = newStringShared(runtime, runtime.getString(), bytes, encoding);
str.flags |= cr;
return str;
}

@@ -814,8 +821,7 @@ public final RubyString makeShared(Ruby runtime, RubyClass meta, int index, int
if (len == 0) {
shared = newEmptyString(runtime, meta);
} else if (len == 1) {
shared = newStringShared(runtime, meta,
RubyInteger.SINGLE_CHAR_BYTELISTS[value.getUnsafeBytes()[value.getBegin() + index] & 0xff]);
shared = newStringShared(runtime, meta, RubyInteger.singleCharByteList(value.getUnsafeBytes()[value.getBegin() + index]));
} else {
if (shareLevel == SHARE_LEVEL_NONE) shareLevel = SHARE_LEVEL_BUFFER;
shared = new RubyString(runtime, meta, value.makeShared(index, len));
@@ -3371,10 +3377,8 @@ final IRubyObject uptoCommon(ThreadContext context, IRubyObject arg, boolean exc
byte e = end.value.getUnsafeBytes()[end.value.getBegin()];
if (c > e || (excl && c == e)) return this;
while (true) {
ByteList s = RubyInteger.SINGLE_CHAR_BYTELISTS[c & 0xff];
RubyString str = new RubyString(runtime, runtime.getString(), s, enc, CR_7BIT);
str.shareLevel = SHARE_LEVEL_BYTELIST;
block.yield(context, asSymbol ? runtime.newSymbol(s) : str);
ByteList s = RubyInteger.singleCharByteList(c);
block.yield(context, asSymbol ? runtime.newSymbol(s) : newStringShared(runtime, s, enc, CR_7BIT));

if (!excl && c == e) break;
c++;
2 changes: 1 addition & 1 deletion core/src/main/java/org/jruby/RubyYielder.java
Original file line number Diff line number Diff line change
@@ -99,7 +99,7 @@ public IRubyObject initialize(ThreadContext context, Block block) {
@JRubyMethod(rest = true)
public IRubyObject yield(ThreadContext context, IRubyObject[]args) {
checkInit();
return proc.call19(context, args, Block.NULL_BLOCK);
return proc.call(context, args, Block.NULL_BLOCK);
}

@JRubyMethod(name = "<<", rest = true)
20 changes: 14 additions & 6 deletions core/src/main/java/org/jruby/ext/bigdecimal/RubyBigDecimal.java
Original file line number Diff line number Diff line change
@@ -1549,14 +1549,22 @@ public IRubyObject to_f() {
throw getRuntime().newArgumentError("signum of this rational is invalid: " + value.signum());
}

public final IRubyObject to_int() {
return to_int(getRuntime());
}

@Override
@JRubyMethod(name = {"to_i", "to_int"})
public IRubyObject to_int() {
checkFloatDomain();
public IRubyObject to_int(ThreadContext context) {
return to_int(context.runtime);
}

final RubyInteger to_int(Ruby runtime) {
checkFloatDomain();
try {
return RubyNumeric.int2fix(getRuntime(), value.longValueExact());
} catch (ArithmeticException ae) {
return RubyBignum.bignorm(getRuntime(), value.toBigInteger());
return RubyNumeric.int2fix(runtime, value.longValueExact());
} catch (ArithmeticException ex) {
return RubyBignum.bignorm(runtime, value.toBigInteger());
}
}

@@ -1566,7 +1574,7 @@ public IRubyObject to_r(ThreadContext context) {

int scale = value.scale();
BigInteger numerator = value.scaleByPowerOfTen(scale).toBigInteger();
BigInteger denominator = BigInteger.valueOf((long) Math.pow(10, scale));
BigInteger denominator = BigInteger.TEN.pow(scale);

return RubyRational.newInstance(context, context.runtime.getRational(), RubyBignum.newBignum(context.runtime, numerator), RubyBignum.newBignum(context.runtime, denominator));
}
2 changes: 1 addition & 1 deletion core/src/main/java/org/jruby/ir/IRBuilder.java
Original file line number Diff line number Diff line change
@@ -3026,7 +3026,7 @@ public Operand buildIter(final IterNode iterNode) {
}

public Operand buildLiteral(LiteralNode literalNode) {
return copyAndReturnValue(new StringLiteral(literalNode.getName()));
return new StringLiteral(literalNode.getName());
}

public Operand buildLocalAsgn(LocalAsgnNode localAsgnNode) {
89 changes: 43 additions & 46 deletions core/src/main/java/org/jruby/runtime/Frame.java
Original file line number Diff line number Diff line change
@@ -17,7 +17,7 @@
* Copyright (C) 2004-2007 Thomas E Enebo <enebo@acm.org>
* Copyright (C) 2006 Charles O Nutter <headius@headius.com>
* Copyright (C) 2006 Miguel Covarrubias <mlcovarrubias@gmail.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"),
@@ -57,49 +57,49 @@
* and for some core methods. In general, a frame is required for a method to
* show up in a backtrace, and so some methods only use frame for backtrace
* information (so-called "backtrace frames").
*
*
* @see ThreadContext
*/
public final class Frame {
/** The class against which this call is executing. */
private RubyModule klazz;

/** The 'self' for this frame. */
private IRubyObject self;

/** The name of the method being invoked in this frame. */
private String name;

/**
* The block that was passed in for this frame (as either a block or a &amp;block argument).
* The frame captures the block for super/zsuper, but also for Proc.new (with no arguments)
* and also for block_given?. Both of those methods needs access to the block of the
* and also for block_given?. Both of those methods needs access to the block of the
* previous frame to work.
*/
*/
private Block block = Block.NULL_BLOCK;

/** The current visibility for anything defined under this frame */
private Visibility visibility = Visibility.PUBLIC;

/** backref **/
private IRubyObject backRef;

/** lastline **/
private IRubyObject lastLine;

/** whether this frame has been captured into a binding **/
private boolean captured;

/** A dummy frame **/
public static final Frame DUMMY = new Frame();

/**
* Empty constructor, since Frame objects are pre-allocated and updated
* when needed.
*/
public Frame() {
}

/**
* Copy constructor, since Frame objects are pre-allocated and updated
* when needed.
@@ -119,13 +119,13 @@ private Frame(Frame frame) {
* and method.
*/
public void updateFrame() {
updateFrame(null, null, null, Block.NULL_BLOCK, 0);
updateFrame(null, null, null, Block.NULL_BLOCK);
}

/**
* Update the frame with caller information and method name, so it will
* show up correctly in call stacks.
*
*
* @param name The name of the method being called
*/
public void updateFrame(String name) {
@@ -135,7 +135,7 @@ public void updateFrame(String name) {
/**
* Update the frame based on information from another frame. Used for
* cloning frames (for blocks, usually) and when entering class bodies.
*
*
* @param frame The frame whose data to duplicate in this frame
*/
public void updateFrame(Frame frame) {
@@ -150,15 +150,13 @@ public void updateFrame(Frame frame) {

/**
* Update the frame based on the given values.
*
*
* @param klazz The class against which the method is being called
* @param self The 'self' for the method
* @param name The name under which the method is being invoked
* @param block The block passed to the method
* @param jumpTarget The target for non-local jumps (return in block)
*/
public void updateFrame(RubyModule klazz, IRubyObject self, String name,
Block block, int jumpTarget) {
public void updateFrame(RubyModule klazz, IRubyObject self, String name, Block block) {
assert block != null : "Block uses null object pattern. It should NEVER be null";

this.self = self;
@@ -170,11 +168,10 @@ public void updateFrame(RubyModule klazz, IRubyObject self, String name,

/**
* Update the frame based on the given values.
*
*
* @param self The 'self' for the method
* @param jumpTarget The target for non-local jumps (return in block)
*/
public void updateFrameForEval(IRubyObject self, int jumpTarget) {
public void updateFrameForEval(IRubyObject self) {
this.self = self;
this.name = null;
this.visibility = Visibility.PRIVATE;
@@ -190,13 +187,13 @@ public Frame clear() {
this.block = Block.NULL_BLOCK;
this.backRef = null;
this.lastLine = null;

return this;
}

/**
* Clone this frame.
*
*
* @return A new frame with duplicate information to the target frame
*/
public Frame duplicate() {
@@ -215,9 +212,9 @@ public Frame duplicateForBacktrace() {
return backtraceFrame;
}

/**
/**
* Return class that we are calling against
*
*
* @return The class we are calling against
*/
public RubyModule getKlazz() {
@@ -226,7 +223,7 @@ public RubyModule getKlazz() {

/**
* Set the class we are calling against.
*
*
* @param klazz the new class
*/
public void setKlazz(RubyModule klazz) {
@@ -235,16 +232,16 @@ public void setKlazz(RubyModule klazz) {

/**
* Set the method name associated with this frame
*
*
* @param name the new name
*/
public void setName(String name) {
this.name = name;
}

/**
/**
* Get the method name associated with this frame
*
*
* @return the method name
*/
public String getName() {
@@ -253,76 +250,76 @@ public String getName() {

/**
* Get the self associated with this frame
*
*
* @return The self for the frame
*/
public IRubyObject getSelf() {
return self;
}

/**
/**
* Set the self associated with this frame
*
*
* @param self The new value of self
*/
public void setSelf(IRubyObject self) {
this.self = self;
}

/**
* Get the visibility at the time of this frame
*
*
* @return The visibility
*/
public Visibility getVisibility() {
return visibility;
}

/**
* Change the visibility associated with this frame
*
*
* @param visibility The new visibility
*/
public void setVisibility(Visibility visibility) {
this.visibility = visibility;
}

/**
* Retrieve the block associated with this frame.
*
*
* @return The block of this frame or NULL_BLOCK if no block given
*/
public Block getBlock() {
return block;
}

public IRubyObject getBackRef(IRubyObject nil) {
IRubyObject backRef = this.backRef;
return backRef == null ? nil : backRef;
}

public IRubyObject setBackRef(IRubyObject backRef) {
return this.backRef = backRef;
}

public IRubyObject getLastLine(IRubyObject nil) {
IRubyObject lastLine = this.lastLine;
return lastLine == null ? nil : lastLine;
}

public IRubyObject setLastLine(IRubyObject lastLine) {
return this.lastLine = lastLine;
}

public void setCaptured(boolean captured) {
this.captured = captured;
}

public Frame capture() {
captured = true;
return this;
}

public boolean isCaptured() {
return captured;
}
378 changes: 25 additions & 353 deletions core/src/main/java/org/jruby/runtime/Helpers.java

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion core/src/main/java/org/jruby/runtime/MethodBlockBody.java
Original file line number Diff line number Diff line change
@@ -62,7 +62,7 @@ public IRubyObject call(ThreadContext context, Block block, IRubyObject[] args,

@Override
protected IRubyObject doYield(ThreadContext context, Block block, IRubyObject value) {
IRubyObject[] realArgs = Helpers.restructureBlockArgs19(value, getSignature(), block.type, false, false);
IRubyObject[] realArgs = Helpers.restructureBlockArgs(value, getSignature(), block.type, false);
return method.call(context, receiver, originModule, originName, realArgs, Block.NULL_BLOCK);
}

@@ -90,4 +90,5 @@ public ArgumentDescriptor[] getArgumentDescriptors() {
public void setEvalType(EvalType evalType) {
// nop
}

}
4 changes: 2 additions & 2 deletions core/src/main/java/org/jruby/runtime/ThreadContext.java
Original file line number Diff line number Diff line change
@@ -456,7 +456,7 @@ private void pushCallFrame(RubyModule clazz, String name,
IRubyObject self, Block block) {
int index = ++this.frameIndex;
Frame[] stack = frameStack;
stack[index].updateFrame(clazz, self, name, block, callNumber);
stack[index].updateFrame(clazz, self, name, block);
if (index + 1 == stack.length) {
expandFrameStack();
}
@@ -465,7 +465,7 @@ private void pushCallFrame(RubyModule clazz, String name,
private void pushEvalFrame(IRubyObject self) {
int index = ++this.frameIndex;
Frame[] stack = frameStack;
stack[index].updateFrameForEval(self, callNumber);
stack[index].updateFrameForEval(self);
if (index + 1 == stack.length) {
expandFrameStack();
}
14 changes: 8 additions & 6 deletions core/src/main/java/org/jruby/util/Numeric.java
Original file line number Diff line number Diff line change
@@ -68,7 +68,7 @@ public static IRubyObject f_cmp(ThreadContext context, IRubyObject x, IRubyObjec
*
*/
public static IRubyObject f_div(ThreadContext context, IRubyObject x, IRubyObject y) {
if (y instanceof RubyFixnum && ((RubyFixnum)y).getLongValue() == 1) return x;
if (y instanceof RubyFixnum && ((RubyFixnum) y).getLongValue() == 1) return x;
return sites(context).op_quo.call(context, x, x, y);
}

@@ -343,31 +343,33 @@ public static boolean f_negative_p(ThreadContext context, IRubyObject x) {
*/
public static boolean f_zero_p(ThreadContext context, IRubyObject x) {
if (x instanceof RubyInteger) return ((RubyInteger) x).signum() == 0;
if (x instanceof RubyFloat) return ((RubyFloat) x).signum() == 0;
return sites(context).op_equals.call(context, x, x, RubyFixnum.zero(context.runtime)).isTrue();
}

/** f_one_p
*
*/
public static boolean f_one_p(ThreadContext context, IRubyObject x) {
if (x instanceof RubyFixnum) return ((RubyFixnum)x).getLongValue() == 1;
if (x instanceof RubyFixnum) return ((RubyFixnum) x).getLongValue() == 1;
return sites(context).op_equals.call(context, x, x, RubyFixnum.one(context.runtime)).isTrue();
}

/** f_minus_one_p
*
*/
public static boolean f_minus_one_p(ThreadContext context, IRubyObject x) {
if (x instanceof RubyFixnum) return ((RubyFixnum)x).getLongValue() == -1;
if (x instanceof RubyFixnum) return ((RubyFixnum) x).getLongValue() == -1;
return sites(context).op_equals.call(context, x, x, RubyFixnum.minus_one(context.runtime)).isTrue();
}

/** f_odd_p
*
*/
public static boolean f_odd_p(ThreadContext context, IRubyObject integer) {
Ruby runtime = context.runtime;
return (((RubyFixnum) sites(context).op_mod.call(context, integer, integer, RubyFixnum.two(runtime))).getLongValue() != 0);
public static boolean f_odd_p(ThreadContext context, IRubyObject i) {
if (i instanceof RubyFixnum) return ((RubyFixnum) i).getLongValue() % 2 != 0;
RubyFixnum two = RubyFixnum.two(context.runtime);
return (((RubyFixnum) sites(context).op_mod.call(context, i, i, two)).getLongValue() != 0);
}

/**
80 changes: 43 additions & 37 deletions core/src/main/java/org/jruby/util/RubyDateFormatter.java
Original file line number Diff line number Diff line change
@@ -50,7 +50,7 @@
import org.joda.time.DateTime;
import org.joda.time.chrono.GJChronology;
import org.joda.time.chrono.JulianChronology;
import org.jruby.RubyEncoding;
import org.jruby.Ruby;
import org.jruby.RubyString;
import org.jruby.RubyTime;
import org.jruby.lexer.StrftimeLexer;
@@ -63,8 +63,8 @@ public class RubyDateFormatter {
private static final DateFormatSymbols FORMAT_SYMBOLS = new DateFormatSymbols(Locale.US);
private static final Token[] CONVERSION2TOKEN = new Token[256];

private ThreadContext context;
private StrftimeLexer lexer;
private final Ruby runtime;
private final StrftimeLexer lexer;

static enum Format {
/** encoding to give to output */
@@ -154,7 +154,7 @@ static enum Format {
CONVERSION2TOKEN[alias] = CONVERSION2TOKEN[conversion];
}
}
static final Format INSTANTIATE_ENUM = Format.FORMAT_WEEK_LONG;
//static final Format INSTANTIATE_ENUM = Format.FORMAT_WEEK_LONG;

public static void main(String[] args) {
// composed + special, keys of the switch below
@@ -227,11 +227,11 @@ public String toString() {
*/
public RubyDateFormatter(ThreadContext context) {
super();
this.context = context;
this.runtime = context.runtime;
lexer = new StrftimeLexer((Reader) null);
}

private void addToPattern(List<Token> compiledPattern, String str) {
private static void addToPattern(List<Token> compiledPattern, String str) {
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
if (('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z')) {
@@ -251,14 +251,14 @@ public List<Token> compilePattern(ByteList pattern, boolean dateLibrary) {

Encoding enc = pattern.getEncoding();
if (!enc.isAsciiCompatible()) {
throw context.runtime.newArgumentError("format should have ASCII compatible encoding");
throw runtime.newArgumentError("format should have ASCII compatible encoding");
}
if (enc != ASCIIEncoding.INSTANCE) { // default for ByteList
compiledPattern.add(new Token(Format.FORMAT_ENCODING, enc));
}

ByteArrayInputStream in = new ByteArrayInputStream(pattern.getUnsafeBytes(), pattern.getBegin(), pattern.getRealSize());
Reader reader = new InputStreamReader(in, context.runtime.getEncodingService().charsetForEncoding(pattern.getEncoding()));
Reader reader = new InputStreamReader(in, runtime.getEncodingService().charsetForEncoding(pattern.getEncoding()));
lexer.yyreset(reader);

Token token;
@@ -347,8 +347,8 @@ static enum FieldType {
NUMERIC5('0', 5),
TEXT(' ', 0);

char defaultPadder;
int defaultWidth;
final char defaultPadder;
final int defaultWidth;
FieldType(char padder, int width) {
defaultPadder = padder;
defaultWidth = width;
@@ -359,21 +359,21 @@ static enum FieldType {
public RubyString compileAndFormat(RubyString pattern, boolean dateLibrary, DateTime dt, long nsec, IRubyObject sub_millis) {
RubyString out = format(compilePattern(pattern, dateLibrary), dt, nsec, sub_millis);
if (pattern.isTaint()) {
out.taint(context);
out.setTaint(true);
}
return out;
}

public RubyString format(List<Token> compiledPattern, DateTime dt, long nsec, IRubyObject sub_millis) {
return context.runtime.newString(formatToByteList(compiledPattern, dt, nsec, sub_millis));
return runtime.newString(formatToByteList(compiledPattern, dt, nsec, sub_millis));
}

public ByteList formatToByteList(List<Token> compiledPattern, DateTime dt, long nsec, IRubyObject sub_millis) {
RubyTimeOutputFormatter formatter = RubyTimeOutputFormatter.DEFAULT_FORMATTER;
ByteList toAppendTo = new ByteList();

for (Token token: compiledPattern) {
String output = null;
CharSequence output = null;
long value = 0;
FieldType type = TEXT;
Format format = token.getFormat();
@@ -490,7 +490,7 @@ public ByteList formatToByteList(List<Token> compiledPattern, DateTime dt, long
output = formatZone(colons, (int) value, formatter);
break;
case FORMAT_ZONE_ID:
output = RubyTime.getRubyTimeZoneName(context.runtime, dt);
output = RubyTime.getRubyTimeZoneName(runtime, dt);
break;
case FORMAT_CENTURY:
type = NUMERIC;
@@ -511,24 +511,28 @@ public ByteList formatToByteList(List<Token> compiledPattern, DateTime dt, long

output = RubyTimeOutputFormatter.formatNumber(dt.getMillisOfSecond(), 3, '0');
if (width > 3) {
StringBuilder buff = new StringBuilder(output.length() + 6).append(output);
if (sub_millis == null || sub_millis.isNil()) { // Time
output += RubyTimeOutputFormatter.formatNumber(nsec, 6, '0');
buff.append(RubyTimeOutputFormatter.formatNumber(nsec, 6, '0'));
} else { // Date, DateTime
int prec = width - 3;
IRubyObject power = context.runtime.newFixnum(10).callMethod("**", context.runtime.newFixnum(prec));
final ThreadContext context = runtime.getCurrentContext(); // TODO really need the dynamic nature here?
IRubyObject power = runtime.newFixnum(10).callMethod(context, "**", runtime.newFixnum(prec));
IRubyObject truncated = sub_millis.callMethod(context, "numerator").callMethod(context, "*", power);
truncated = truncated.callMethod(context, "/", sub_millis.callMethod(context, "denominator"));
long decimals = truncated.convertToInteger().getLongValue();
output += RubyTimeOutputFormatter.formatNumber(decimals, prec, '0');
buff.append(RubyTimeOutputFormatter.formatNumber(decimals, prec, '0'));
}
output = buff;
}

if (width < output.length()) {
output = output.substring(0, width);
output = output.subSequence(0, width);
} else {
StringBuilder buff = new StringBuilder(width).append(output);
// Not enough precision, fill with 0
while(output.length() < width)
output += "0";
while (buff.length() < width) buff.append('0');
output = buff;
}
formatter = RubyTimeOutputFormatter.DEFAULT_FORMATTER; // no more formatting
break;
@@ -549,16 +553,17 @@ public ByteList formatToByteList(List<Token> compiledPattern, DateTime dt, long
throw new Error("FORMAT_SPECIAL is a special token only for the lexer.");
}

final String formatted;
try {
output = formatter.format(output, value, type);
formatted = formatter.format(output, value, type);
} catch (IndexOutOfBoundsException ioobe) {
throw context.runtime.newErrnoFromErrno(Errno.ERANGE, "strftime");
throw runtime.newErrnoFromErrno(Errno.ERANGE, "strftime");
}

// reset formatter
formatter = RubyTimeOutputFormatter.DEFAULT_FORMATTER;

toAppendTo.append(output.getBytes(context.runtime.getEncodingService().charsetForEncoding(toAppendTo.getEncoding())));
toAppendTo.append(formatted.getBytes(runtime.getEncodingService().charsetForEncoding(toAppendTo.getEncoding())));
}

return toAppendTo;
@@ -568,7 +573,7 @@ public ByteList formatToByteList(List<Token> compiledPattern, DateTime dt, long
* Ruby always follows Astronomical year numbering,
* that is BC x is -x+1 and there is a year 0 (BC 1)
* but Joda-time returns -x for year x BC in Julian chronology (no year 0) */
private int year(DateTime dt, int year) {
private static int year(DateTime dt, int year) {
Chronology c;
if (year < 0 && (
(c = dt.getChronology()) instanceof JulianChronology ||
@@ -577,7 +582,7 @@ private int year(DateTime dt, int year) {
return year;
}

private int formatWeekYear(DateTime dt, int firstDayOfWeek) {
private static int formatWeekYear(DateTime dt, int firstDayOfWeek) {
java.util.Calendar dtCalendar = dt.toGregorianCalendar();
dtCalendar.setFirstDayOfWeek(firstDayOfWeek);
dtCalendar.setMinimalDaysInFirstWeek(7);
@@ -592,7 +597,7 @@ private int formatWeekYear(DateTime dt, int firstDayOfWeek) {
return value;
}

private String formatZone(int colons, int value, RubyTimeOutputFormatter formatter) {
private static StringBuilder formatZone(int colons, int value, RubyTimeOutputFormatter formatter) {
int seconds = Math.abs(value);
int hours = seconds / 3600;
seconds %= 3600;
@@ -608,7 +613,7 @@ private String formatZone(int colons, int value, RubyTimeOutputFormatter formatt

char padder = formatter.getPadder('0');
int defaultWidth = -1;
String after = null;
CharSequence after = null;

switch (colons) {
case 0: // %z -> +hhmm
@@ -617,17 +622,17 @@ private String formatZone(int colons, int value, RubyTimeOutputFormatter formatt
break;
case 1: // %:z -> +hh:mm
defaultWidth = 6;
after = ":" + mm;
after = new StringBuilder(mm.length() + 1).append(':').append(mm);
break;
case 2: // %::z -> +hh:mm:ss
defaultWidth = 9;
after = ":" + mm + ":" + ss;
after = new StringBuilder(mm.length() + ss.length() + 2).append(':').append(mm).append(':').append(ss);
break;
case 3: // %:::z -> +hh[:mm[:ss]]
StringBuilder sb = new StringBuilder();
if (minutes != 0 || seconds != 0) sb.append(":").append(mm);
if (seconds != 0) sb.append(":").append(ss);
after = sb.toString();
StringBuilder sb = new StringBuilder(mm.length() + ss.length() + 2);
if (minutes != 0 || seconds != 0) sb.append(':').append(mm);
if (seconds != 0) sb.append(':').append(ss);
after = sb;
defaultWidth = after.length() + 3;
break;
}
@@ -638,11 +643,12 @@ private String formatZone(int colons, int value, RubyTimeOutputFormatter formatt
width = minWidth;
}
width -= after.length();
String before = RubyTimeOutputFormatter.formatSignedNumber(hours, width, padder);
CharSequence before = RubyTimeOutputFormatter.formatSignedNumber(hours, width, padder);

if (value < 0 && hours == 0) // the formatter could not handle this case
before = before.replace('+', '-');
return before + after;
if (value < 0 && hours == 0) { // the formatter could not handle this case
before = before.toString().replace('+', '-');
}
return new StringBuilder(before.length() + after.length()).append(before).append(after); // before + after
}

/**
27 changes: 12 additions & 15 deletions core/src/main/java/org/jruby/util/RubyTimeOutputFormatter.java
Original file line number Diff line number Diff line change
@@ -66,7 +66,7 @@ public char getPadder(char defaultPadder) {
return padder;
}

public String format(String sequence, long value, FieldType type) {
public String format(CharSequence sequence, long value, FieldType type) {
int width = getWidth(type.defaultWidth);
char padder = getPadder(type.defaultPadder);

@@ -79,31 +79,30 @@ public String format(String sequence, long value, FieldType type) {
for (int i = 0; i < flags.length(); i++) {
switch (flags.charAt(i)) {
case '^':
sequence = sequence.toUpperCase();
sequence = sequence.toString().toUpperCase();
break;
case '#': // change case
char last = sequence.charAt(sequence.length() - 1);
if (Character.isLowerCase(last)) {
sequence = sequence.toUpperCase();
sequence = sequence.toString().toUpperCase();
} else {
sequence = sequence.toLowerCase();
sequence = sequence.toString().toLowerCase();
}
break;
}
}

return sequence;
return sequence.toString();
}

static String formatNumber(long value, int width, char padder) {
if (value >= 0 || padder != '0') {
return padding(Long.toString(value), width, padder);
} else {
return "-" + padding(Long.toString(-value), width - 1, padder);
return padding(Long.toString(value), width, padder).toString();
}
return "-" + padding(Long.toString(-value), width - 1, padder);
}

static String formatSignedNumber(long value, int width, char padder) {
static CharSequence formatSignedNumber(long value, int width, char padder) {
if (padder == '0') {
if (value >= 0) {
return "+" + padding(Long.toString(value), width - 1, padder);
@@ -112,7 +111,7 @@ static String formatSignedNumber(long value, int width, char padder) {
}
} else {
if (value >= 0) {
return padding("+" + Long.toString(value), width, padder);
return padding('+' + Long.toString(value), width, padder);
} else {
return padding(Long.toString(value), width, padder);
}
@@ -121,10 +120,8 @@ static String formatSignedNumber(long value, int width, char padder) {

private static final int SMALLBUF = 100;

static String padding(String sequence, int width, char padder) {
if (sequence.length() >= width) {
return sequence;
}
private static CharSequence padding(CharSequence sequence, int width, char padder) {
if (sequence.length() >= width) return sequence;

if (width > SMALLBUF) throw new IndexOutOfBoundsException("padding width " + width + " too large");

@@ -133,6 +130,6 @@ static String padding(String sequence, int width, char padder) {
buf.append(padder);
}
buf.append(sequence);
return buf.toString();
return buf;
}
}
16 changes: 16 additions & 0 deletions spec/ruby/library/bigdecimal/to_r_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
require File.expand_path('../../../spec_helper', __FILE__)
require 'bigdecimal'

describe "BigDecimal#to_r" do

it "returns a Rational" do
BigDecimal("3.14159").to_r.should be_kind_of(Rational)
end

it "returns a Rational with bignum values" do
r = BigDecimal.new("3.141592653589793238462643").to_r
r.numerator.should eql(3141592653589793238462643)
r.denominator.should eql(1000000000000000000000000)
end

end
1 change: 0 additions & 1 deletion spec/tags/ruby/core/io/set_encoding_tags.txt

This file was deleted.

52 changes: 46 additions & 6 deletions test/jruby/test_random.rb
Original file line number Diff line number Diff line change
@@ -16,20 +16,46 @@ def test_return_float_for_no_arg
assert(r >= 0.0)
end

def test_Random_return_float_for_no_arg
r = Random.rand
assert(r.kind_of?(Float))
assert(r < 1.0)
assert(r >= 0.0)
end

def test_return_float_for_zero_arg
r = rand(0)
assert(r.kind_of?(Float))
assert(r < 1.0)
assert(r >= 0.0)
end


def test_Random_fail_for_zero_arg
assert_raise(ArgumentError) { Random.rand(0) }
end

def test_one_arg
100.times {
r = rand(1)
assert_equal(0, r)
}
100.times { assert_equal(0, Kernel.rand(1)) }
end


def test_Random_one_arg
100.times { assert_equal(0, Random.rand(1)) }
end

def test_rand_range
r = Kernel.rand 10...20
assert(r.kind_of?(Integer))
assert(r < 20)
assert(r >= 10)
end

def test_Random_rand_range
r = Random.rand 10...20
assert(r.kind_of?(Integer))
assert(r < 20)
assert(r >= 10)
end

def test_rand_int_in_range
do_range_test(2**31 - 1)
end
@@ -69,4 +95,18 @@ def do_abs_value_arg_test(max)
r2 = rand(-max)
assert(r1 == r2)
end

def test_rand_nil
10.times do
r = rand(nil)
assert(r.kind_of?(Float))
assert(r < 1.0)
assert(r >= 0.0)
end
end

def test_Random_nil
assert_raise(ArgumentError) { Random.rand(nil) }
end

end

0 comments on commit 3860d6f

Please sign in to comment.