Skip to content

Commit

Permalink
Showing 12 changed files with 539 additions and 187 deletions.
2 changes: 1 addition & 1 deletion truffle/src/main/java/org/jruby/truffle/RubyLanguage.java
Original file line number Diff line number Diff line change
@@ -17,11 +17,11 @@
import com.oracle.truffle.api.instrumentation.StandardTags;
import com.oracle.truffle.api.nodes.Node;
import com.oracle.truffle.api.source.Source;
import org.jruby.runtime.Constants;
import org.jruby.truffle.core.kernel.TraceManager;
import org.jruby.truffle.language.LazyRubyRootNode;
import org.jruby.truffle.language.RubyGuards;
import org.jruby.truffle.stdlib.CoverageManager;
import org.jruby.truffle.util.Constants;

import java.io.IOException;

Original file line number Diff line number Diff line change
@@ -46,17 +46,10 @@
import org.joni.Syntax;
import org.joni.WarnCallback;
import org.joni.exception.JOniException;
import org.jruby.Ruby;
import org.jruby.anno.JRubyMethod;
import org.jruby.exceptions.RaiseException;
import org.jruby.parser.ReOptions;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.encoding.EncodingCapable;
import org.jruby.runtime.encoding.MarshalEncoding;
import org.jruby.truffle.RubyContext;
import org.jruby.truffle.core.string.StringSupport;
import org.jruby.truffle.parser.ReOptions;
import org.jruby.util.ByteList;
import org.jruby.util.RegexpSupport;
import org.jruby.util.collections.WeakValuedMap;
import org.jruby.util.io.EncodingUtils;

@@ -67,7 +60,7 @@
import static org.jruby.util.StringSupport.EMPTY_STRING_ARRAY;
import static org.jruby.util.StringSupport.codeRangeScan;

public class ClassicRegexp implements ReOptions, EncodingCapable, MarshalEncoding {
public class ClassicRegexp implements ReOptions {
private final RubyContext context;
private Regex pattern;
private ByteList str = ByteList.EMPTY_BYTELIST;
@@ -85,27 +78,15 @@ public void setEncodingNone() {
options.setEncodingNone(true);
}

@Override
public Encoding getEncoding() {
return pattern.getEncoding();
}

@Override
public void setEncoding(Encoding encoding) {
// FIXME: Which encoding should be changed here?
// FIXME: transcode?
}

@Override
public boolean shouldMarshalEncoding() {
return getEncoding() != ASCIIEncoding.INSTANCE;
}

@Override
public Encoding getMarshalEncoding() {
return getEncoding();
}
// FIXME: Maybe these should not be static?
static final WeakValuedMap<ByteList, Regex> patternCache = new WeakValuedMap<>();

private static Regex makeRegexp(RubyContext runtime, ByteList bytes, RegexpOptions options, Encoding enc) {
@@ -154,7 +135,7 @@ private static class SearchMatchTask {
this.match = match;
}

public Integer run(ThreadContext context, Matcher matcher) throws InterruptedException {
public Integer run(Object context, Matcher matcher) throws InterruptedException {
return match ?
matcher.matchInterruptible(start, range, option) :
matcher.searchInterruptible(start, range, option);
@@ -182,11 +163,11 @@ public static ClassicRegexp newRegexp(RubyContext runtime, ByteList pattern, int

// used only by the compiler/interpreter (will set the literal flag)
public static ClassicRegexp newRegexp(RubyContext runtime, ByteList pattern, RegexpOptions options) {
try {
//try {
return new ClassicRegexp(runtime, pattern, (RegexpOptions)options.clone());
} catch (RaiseException re) {
throw new org.jruby.truffle.language.control.RaiseException(runtime.getCoreExceptions().syntaxError(re.getMessage(), null));
}
//} catch (RaiseException re) {
// throw new org.jruby.truffle.language.control.RaiseException(runtime.getCoreExceptions().syntaxError(re.getMessage(), null));
//}
}

/**
@@ -198,18 +179,6 @@ public static ClassicRegexp newRegexpParser(RubyContext runtime, ByteList patter
return new ClassicRegexp(runtime, pattern, (RegexpOptions)options.clone());
}

/** rb_reg_options
*/
public RegexpOptions getOptions() {
check();
return options;
}

public final Regex getPattern() {
check();
return pattern;
}

private static void preprocessLight(RubyContext context, ByteList str, Encoding enc, Encoding[]fixedEnc, RegexpSupport.ErrorMode mode) {
if (enc.isAsciiCompatible()) {
fixedEnc[0] = null;
@@ -592,10 +561,6 @@ private static int scanForCodeRange(ByteList str) {
return cr;
}

private void check() {
if (pattern == null) throw getRuntime().newTypeError("uninitialized Regexp");
}

/** rb_reg_quote
*
*/
@@ -740,20 +705,13 @@ public ClassicRegexp regexpInitialize(ByteList bytes, Encoding enc, RegexpOption
return this;
}

@JRubyMethod
public Object options() {
return getRuntime().newFixnum(getOptions().toOptions());
}

public static void appendOptions(ByteList to, RegexpOptions options) {
if (options.isMultiline()) to.append((byte)'m');
if (options.isIgnorecase()) to.append((byte)'i');
if (options.isExtended()) to.append((byte)'x');
}

public ByteList toByteList() {
check();

RegexpOptions newOptions = (RegexpOptions)options.clone();
int p = str.getBegin();
int len = str.getRealSize();
@@ -925,14 +883,4 @@ public String[] getNames() {
return names;
}

@JRubyMethod
public Object encoding(ThreadContext context) {
Encoding enc = (pattern == null) ? str.getEncoding() : pattern.getEncoding();
return context.runtime.getEncodingService().getEncoding(enc);
}

public Ruby getRuntime() {
throw new UnsupportedOperationException();
}

}
Original file line number Diff line number Diff line change
@@ -75,8 +75,6 @@
import org.jruby.truffle.language.threadlocal.ThreadLocalObject;
import org.jruby.truffle.util.StringUtils;
import org.jruby.util.ByteList;
import org.jruby.util.RegexpSupport;
import org.jruby.util.RegexpSupport.ErrorMode;

import java.nio.charset.StandardCharsets;
import java.util.Arrays;
@@ -94,7 +92,7 @@ public static Matcher createMatcher(RubyContext context, DynamicObject regexp, D
if (regex.getEncoding() != enc) {
final Encoding[] fixedEnc = new Encoding[] { null };
final ByteList sourceByteList = RopeOperations.getByteListReadOnly(Layouts.REGEXP.getSource(regexp));
final ByteList preprocessed = ClassicRegexp.preprocess(context, sourceByteList, enc, fixedEnc, ErrorMode.RAISE);
final ByteList preprocessed = ClassicRegexp.preprocess(context, sourceByteList, enc, fixedEnc, RegexpSupport.ErrorMode.RAISE);
final RegexpOptions options = Layouts.REGEXP.getOptions(regexp);
final Encoding newEnc = checkEncoding(regexp, stringRope, true);
regex = new Regex(preprocessed.getUnsafeBytes(), preprocessed.getBegin(), preprocessed.getBegin() + preprocessed.getRealSize(),
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/***** BEGIN LICENSE BLOCK *****
* 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.
*
* 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.
***** END LICENSE BLOCK *****/

package org.jruby.truffle.core.regexp;

public class RegexpSupport {

public enum ErrorMode {RAISE, PREPROCESS, DESC}

}
Original file line number Diff line number Diff line change
@@ -13,7 +13,7 @@
import com.oracle.truffle.api.object.DynamicObjectFactory;
import com.oracle.truffle.api.object.dsl.Layout;
import org.jruby.truffle.core.basicobject.BasicObjectLayout;
import org.jruby.util.Random;
import org.jruby.truffle.util.Random;

@Layout
public interface RandomizerLayout extends BasicObjectLayout {
Original file line number Diff line number Diff line change
@@ -13,7 +13,6 @@
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.object.DynamicObject;
import org.jcodings.specific.ASCIIEncoding;
import org.jruby.RubyRandom;
import org.jruby.truffle.Layouts;
import org.jruby.truffle.builtins.Primitive;
import org.jruby.truffle.builtins.PrimitiveArrayArgumentsNode;
@@ -31,7 +30,7 @@ public static abstract class RandomizerAllocatePrimitiveNode extends PrimitiveAr

@Specialization
public DynamicObject randomizerAllocate() {
return Layouts.RANDOMIZER.createRandomizer(coreLibrary().getRandomizerFactory(), new org.jruby.util.Random());
return Layouts.RANDOMIZER.createRandomizer(coreLibrary().getRandomizerFactory(), new org.jruby.truffle.util.Random());
}

}
@@ -52,13 +51,55 @@ public DynamicObject randomizerSeed(DynamicObject randomizer, long seed) {
}

@TruffleBoundary
protected static org.jruby.util.Random randomFromBigInteger(BigInteger seed) {
return RubyRandom.RandomType.randomFromBigInteger(seed);
protected static org.jruby.truffle.util.Random randomFromLong(long seed) {
return org.jruby.truffle.util.Random.RandomType.randomFromLong(seed);
}

public static int N = 624;

@TruffleBoundary
protected static org.jruby.util.Random randomFromLong(long seed) {
return RubyRandom.RandomType.randomFromLong(seed);
public static org.jruby.truffle.util.Random randomFromBigInteger(BigInteger big) {
if (big.signum() < 0) {
big = big.abs();
}
byte[] buf = big.toByteArray();
int buflen = buf.length;
if (buf[0] == 0) {
buflen -= 1;
}
int len = Math.min((buflen + 3) / 4, N);
int[] ints = bigEndianToInts(buf, len);
if (len <= 1) {
return new org.jruby.truffle.util.Random(ints[0]);
} else {
return new org.jruby.truffle.util.Random(ints);
}
}

private static int[] bigEndianToInts(byte[] buf, int initKeyLen) {
int[] initKey = new int[initKeyLen];
for (int idx = 0; idx < initKey.length; ++idx) {
initKey[idx] = getIntBigIntegerBuffer(buf, idx);
}
return initKey;
}

static int getIntBigIntegerBuffer(byte[] src, int loc) {
int v = 0;
int idx = src.length - loc * 4 - 1;
if (idx >= 0) {
v |= (src[idx--] & 0xff);
if (idx >= 0) {
v |= (src[idx--] & 0xff) << 8;
if (idx >= 0) {
v |= (src[idx--] & 0xff) << 16;
if (idx >= 0) {
v |= (src[idx--] & 0xff) << 24;
}
}
}
}
return v;
}

}
@@ -69,7 +110,7 @@ public static abstract class RandomizerRandFloatPrimitiveNode extends PrimitiveA
@Specialization
public double randomizerRandFloat(DynamicObject randomizer) {
// Logic copied from org.jruby.util.Random
final org.jruby.util.Random r = Layouts.RANDOMIZER.getRandom(randomizer);
final org.jruby.truffle.util.Random r = Layouts.RANDOMIZER.getRandom(randomizer);
final int a = randomInt(r) >>> 5;
final int b = randomInt(r) >>> 6;
return (a * 67108864.0 + b) * (1.0 / 9007199254740992.0);
@@ -82,19 +123,53 @@ public static abstract class RandomizerRandIntPrimitiveNode extends PrimitiveArr

@Specialization
public int randomizerRandInt(DynamicObject randomizer, int limit) {
final org.jruby.util.Random r = Layouts.RANDOMIZER.getRandom(randomizer);
final org.jruby.truffle.util.Random r = Layouts.RANDOMIZER.getRandom(randomizer);
return (int) randInt(r, (long) limit);
}

@Specialization
public long randomizerRandInt(DynamicObject randomizer, long limit) {
final org.jruby.util.Random r = Layouts.RANDOMIZER.getRandom(randomizer);
final org.jruby.truffle.util.Random r = Layouts.RANDOMIZER.getRandom(randomizer);
return randInt(r, limit);
}

@TruffleBoundary
protected static long randInt(org.jruby.util.Random r, long limit) {
return RubyRandom.randLimitedFixnumInner(r, limit);
protected static long randInt(org.jruby.truffle.util.Random r, long limit) {
return randLimitedFixnumInner(r, limit);
}

public static long randLimitedFixnumInner(org.jruby.truffle.util.Random random, long limit) {
long val;
if (limit == 0) {
val = 0;
} else {
long mask = makeMask(limit);
// take care before code cleanup; it might break random sequence compatibility
retry: while (true) {
val = 0;
for (int i = 1; 0 <= i; --i) {
if (((mask >>> (i * 32)) & 0xffffffffL) != 0) {
val |= (random.genrandInt32() & 0xffffffffL) << (i * 32);
val &= mask;
}
if (limit < val) {
continue retry;
}
}
break;
}
}
return val;
}

private static long makeMask(long x) {
x = x | x >>> 1;
x = x | x >>> 2;
x = x | x >>> 4;
x = x | x >>> 8;
x = x | x >>> 16;
x = x | x >>> 32;
return x;
}

}
@@ -108,10 +183,18 @@ public static abstract class RandomizerGenSeedPrimitiveNode extends PrimitiveArr
@TruffleBoundary
@Specialization
public DynamicObject randomizerGenSeed(DynamicObject randomizerClass) {
final BigInteger seed = RubyRandom.randomSeedBigInteger(RANDOM);
final BigInteger seed = randomSeedBigInteger(RANDOM);
return createBignum(seed);
}

private static final int DEFAULT_SEED_CNT = 4;

public static BigInteger randomSeedBigInteger(java.util.Random random) {
byte[] seed = new byte[DEFAULT_SEED_CNT * 4];
random.nextBytes(seed);
return new BigInteger(seed).abs();
}

}

@Primitive(name = "randomizer_bytes", lowerFixnum = 1)
@@ -120,7 +203,7 @@ public static abstract class RandomizerBytesPrimitiveNode extends PrimitiveArray
@TruffleBoundary
@Specialization
public DynamicObject genRandBytes(DynamicObject randomizer, int length) {
final org.jruby.util.Random random = Layouts.RANDOMIZER.getRandom(randomizer);
final org.jruby.truffle.util.Random random = Layouts.RANDOMIZER.getRandom(randomizer);
final byte[] bytes = new byte[length];
int idx = 0;
for (; length >= 4; length -= 4) {
@@ -142,7 +225,7 @@ public DynamicObject genRandBytes(DynamicObject randomizer, int length) {
}

@TruffleBoundary
private static int randomInt(org.jruby.util.Random random) {
private static int randomInt(org.jruby.truffle.util.Random random) {
return random.genrandInt32();
}

Original file line number Diff line number Diff line change
@@ -18,7 +18,6 @@
import com.oracle.truffle.api.source.SourceSection;
import org.jcodings.specific.USASCIIEncoding;
import org.jcodings.specific.UTF8Encoding;
import org.jruby.runtime.Helpers;
import org.jruby.truffle.Layouts;
import org.jruby.truffle.RubyContext;
import org.jruby.truffle.builtins.CoreClass;
@@ -36,6 +35,7 @@
import org.jruby.truffle.language.Visibility;
import org.jruby.truffle.language.control.RaiseException;
import org.jruby.truffle.language.objects.AllocateObjectNode;
import org.jruby.truffle.parser.Helpers;
import org.jruby.truffle.util.StringUtils;

import java.time.DateTimeException;
Original file line number Diff line number Diff line change
@@ -32,7 +32,6 @@

import org.jcodings.Encoding;
import org.jcodings.specific.UTF8Encoding;
import org.jruby.RubyInstanceConfig;
import org.jruby.truffle.RubyContext;
import org.jruby.truffle.parser.scope.DynamicScope;
import org.jruby.truffle.parser.scope.ManyVarsDynamicScope;
@@ -72,19 +71,6 @@ public ParserConfiguration(RubyContext context, int lineNumber, boolean inlineSo
staticScopeFactory = new StaticScopeFactory();
}

public ParserConfiguration(RubyContext context, int lineNumber,
boolean inlineSource, boolean isFileParse, RubyInstanceConfig config) {
this(context, lineNumber, inlineSource, isFileParse, false, config);
}

public ParserConfiguration(RubyContext context, int lineNumber,
boolean inlineSource, boolean isFileParse, boolean saveData, RubyInstanceConfig config) {
this(context, lineNumber, inlineSource, isFileParse, saveData);

this.isDebug = config.isParserDebug();
this.frozenStringLiteral = config.isFrozenStringLiteral();
}

public void setFrozenStringLiteral(boolean frozenStringLiteral) {
this.frozenStringLiteral = frozenStringLiteral;
}
38 changes: 0 additions & 38 deletions truffle/src/main/java/org/jruby/truffle/util/Constants.java
Original file line number Diff line number Diff line change
@@ -30,14 +30,6 @@
***** END LICENSE BLOCK *****/
package org.jruby.truffle.util;

import org.jruby.FlagRegistry;
import org.jruby.RubyBasicObject;
import org.jruby.RubyHash;
import org.jruby.RubyMatchData;
import org.jruby.RubyModule;
import org.jruby.RubyString;
import org.jruby.ext.stringio.StringIO;

public final class Constants {
public static final String PLATFORM = "java";

@@ -79,36 +71,6 @@ public final class Constants {
* The JIT threshold to the specified method invocation count.
*/
public static final int JIT_THRESHOLD = 50;

private static final FlagRegistry registry = new FlagRegistry();

// These flags must be registered from top of hierarchy down to maintain order.
// TODO: Replace these during the build with their calculated values.
public static final int FALSE_F = registry.newFlag(RubyBasicObject.class);
public static final int NIL_F = registry.newFlag(RubyBasicObject.class);
public static final int FROZEN_F = registry.newFlag(RubyBasicObject.class);
public static final int TAINTED_F = registry.newFlag(RubyBasicObject.class);

public static final int CACHEPROXY_F = registry.newFlag(RubyModule.class);
public static final int NEEDSIMPL_F = registry.newFlag(RubyModule.class);
public static final int REFINED_MODULE_F = registry.newFlag(RubyModule.class);
public static final int IS_OVERLAID_F = registry.newFlag(RubyModule.class);

public static final int CR_7BIT_F = registry.newFlag(RubyString.class);
public static final int CR_VALID_F = registry.newFlag(RubyString.class);

public static final int STRIO_READABLE = registry.newFlag(StringIO.class);
public static final int STRIO_WRITABLE = registry.newFlag(StringIO.class);

public static final int MATCH_BUSY = registry.newFlag(RubyMatchData.class);

public static final int COMPARE_BY_IDENTITY_F = registry.newFlag(RubyHash.class);
public static final int PROCDEFAULT_HASH_F = registry.newFlag(RubyHash.class);

private static final boolean DEBUG = false;
static {
if (DEBUG) registry.printFlags();
}

private static String jruby_revision = "046edbf";

56 changes: 0 additions & 56 deletions truffle/src/main/java/org/jruby/truffle/util/Platform.java
Original file line number Diff line number Diff line change
@@ -27,13 +27,6 @@
***** END LICENSE BLOCK *****/
package org.jruby.truffle.util;

import org.jruby.Ruby;
import org.jruby.RubyModule;
import org.jruby.anno.JRubyMethod;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.util.SafePropertyAccessor;

import java.nio.ByteOrder;
import java.util.regex.Pattern;

@@ -45,7 +38,6 @@ public class Platform {
public static final CPU_TYPE CPU = determineCPU();
public static final OS_TYPE OS = determineOS();

public static final String NAME = CPU + "-" + OS;
public static final String LIBPREFIX = OS == OS.WINDOWS ? "" : "lib";
public static final String LIBSUFFIX = determineLibExt();
public static final String LIBC = determineLibC();
@@ -289,54 +281,6 @@ public final boolean isSupported() {
&& (addressSize == 32 || addressSize == 64)
&& javaVersionMajor >= 5;
}
public static void createPlatformModule(Ruby runtime, RubyModule ffi) {
RubyModule module = ffi.defineModuleUnder("Platform");
Platform platform = Platform.getPlatform();
OS_TYPE os = platform.getOS();
module.defineConstant("ADDRESS_SIZE", runtime.newFixnum(platform.addressSize));
module.defineConstant("LONG_SIZE", runtime.newFixnum(platform.longSize));
module.defineConstant("OS", runtime.newString(OS.toString()));
module.defineConstant("ARCH", runtime.newString(platform.getCPU().toString()));
module.defineConstant("NAME", runtime.newString(platform.getName()));
module.defineConstant("IS_WINDOWS", runtime.newBoolean(os == OS.WINDOWS));
module.defineConstant("IS_BSD", runtime.newBoolean(platform.isBSD()));
module.defineConstant("IS_FREEBSD", runtime.newBoolean(os == OS.FREEBSD));
module.defineConstant("IS_OPENBSD", runtime.newBoolean(os == OS.OPENBSD));
module.defineConstant("IS_SOLARIS", runtime.newBoolean(os == OS.SOLARIS));
module.defineConstant("IS_LINUX", runtime.newBoolean(os == OS.LINUX));
module.defineConstant("IS_MAC", runtime.newBoolean(os == OS.DARWIN));
module.defineConstant("LIBC", runtime.newString(LIBC));
module.defineConstant("LIBPREFIX", runtime.newString(LIBPREFIX));
module.defineConstant("LIBSUFFIX", runtime.newString(LIBSUFFIX));
module.defineConstant("BYTE_ORDER", runtime.newFixnum(BYTE_ORDER));
module.defineConstant("BIG_ENDIAN", runtime.newFixnum(BIG_ENDIAN));
module.defineConstant("LITTLE_ENDIAN", runtime.newFixnum(LITTLE_ENDIAN));
module.defineAnnotatedMethods(Platform.class);
}
@JRubyMethod(name = "windows?", module=true)
public static IRubyObject windows_p(ThreadContext context, IRubyObject recv) {
return context.runtime.newBoolean(OS == OS.WINDOWS);
}
@JRubyMethod(name = "mac?", module=true)
public static IRubyObject mac_p(ThreadContext context, IRubyObject recv) {
return context.runtime.newBoolean(OS == OS.DARWIN);
}
@JRubyMethod(name = "unix?", module=true)
public static IRubyObject unix_p(ThreadContext context, IRubyObject recv) {
return context.runtime.newBoolean(Platform.getPlatform().isUnix());
}
@JRubyMethod(name = "bsd?", module=true)
public static IRubyObject bsd_p(ThreadContext context, IRubyObject recv) {
return context.runtime.newBoolean(Platform.getPlatform().isBSD());
}
@JRubyMethod(name = "linux?", module=true)
public static IRubyObject linux_p(ThreadContext context, IRubyObject recv) {
return context.runtime.newBoolean(OS == OS.LINUX);
}
@JRubyMethod(name = "solaris?", module=true)
public static IRubyObject solaris_p(ThreadContext context, IRubyObject recv) {
return context.runtime.newBoolean(OS == OS.SOLARIS);
}
/**
* An extension over <code>System.getProperty</code> method.
* Handles security restrictions, and returns the default
212 changes: 212 additions & 0 deletions truffle/src/main/java/org/jruby/truffle/util/Random.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
/***** BEGIN LICENSE BLOCK *****
* 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.
*
* 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.
***** END LICENSE BLOCK *****/
package org.jruby.truffle.util;

import java.math.BigInteger;
import java.util.Arrays;

public class Random {
public static int N = 624;
private static int M = 397;
private static int MATRIX_A = 0x9908b0df; /* constant vector a */
private static int UMASK = 0x80000000; /* most significant w-r bits */
private static int LMASK = 0x7fffffff; /* least significant r bits */

private static int MIXBITS(int u, int v) {
return (u & UMASK) | (v & LMASK);
}

private static int TWIST(int u, int v) {
return (MIXBITS(u, v) >>> 1) ^ (((v & 1) != 0) ? MATRIX_A : 0);
}

private final int[] state = new int[N];
private int left = 1;

public Random() {
}

public Random(int s) {
initGenrand(s);
}

public Random(int[] initKey) {
initByArray(initKey);
}

public Random(Random orig) {
System.arraycopy(orig.state, 0, this.state, 0, this.state.length);
this.left = orig.left;
}

public Random(int[] state, int left) {
if (state.length != this.state.length) {
throw new IllegalStateException("wrong state length: " + state.length);
}
System.arraycopy(state, 0, this.state, 0, this.state.length);
this.left = left;
}

@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
} else if (!(obj instanceof Random)) {
return false;
}
Random rhs = (Random) obj;
return (left == rhs.left) && Arrays.equals(state, rhs.state);
}

@Override
public int hashCode() {
// Using 17 as the initializer, 37 as the multiplier.
return (629 + left) * 37 + Arrays.hashCode(state);
}

private void initGenrand(int s) {
state[0] = s;
for (int j = 1; j < N; j++) {
state[j] = (1812433253 * (state[j - 1] ^ (state[j - 1] >>> 30)) + j);
}
left = 1;
}

private void initByArray(int[] initKey) {
initGenrand(19650218);
int len = initKey.length;
int i = 1;
int j = 0;
int k = N > len ? N : len;
for (; k > 0; k--) {
state[i] = (state[i] ^ ((state[i - 1] ^ (state[i - 1] >>> 30)) * 1664525)) + initKey[j]
+ j;
i++;
j++;
if (i >= N) {
state[0] = state[N - 1];
i = 1;
}
if (j >= len) {
j = 0;
}
}
for (k = N - 1; k > 0; k--) {
state[i] = (state[i] ^ ((state[i - 1] ^ (state[i - 1] >>> 30)) * 1566083941)) - i;
i++;
if (i >= N) {
state[0] = state[N - 1];
i = 1;
}
}
state[0] = 0x80000000;
}

private void nextState() {
int p = 0;

left = N;

for (int j = N - M + 1; --j > 0; p++) {
state[p] = state[p + M] ^ TWIST(state[p + 0], state[p + 1]);
}

for (int j = M; --j > 0; p++) {
state[p] = state[p + M - N] ^ TWIST(state[p + 0], state[p + 1]);
}

state[p] = state[p + M - N] ^ TWIST(state[p + 0], state[0]);
}

public int genrandInt32() {
int y;

synchronized (this) {
if (--left <= 0)
nextState();

y = state[N - left];
}

/* Tempering */
y ^= (y >>> 11);
y ^= (y << 7) & 0x9d2c5680L;
y ^= (y << 15) & 0xefc60000L;
y ^= (y >>> 18);

return y;
}

public double genrandReal() {
int a = genrandInt32() >>> 5;
int b = genrandInt32() >>> 6;
return (a * 67108864.0 + b) * (1.0 / 9007199254740992.0);
}

public double genrandReal2() {
int a = genrandInt32();
int b = genrandInt32();
return intPairToRealInclusive(a, b);
}

private static final BigInteger INTPAIR_CONST = BigInteger.valueOf((1L << 53) + 1);
private static final double LDEXP_CONST = Math.pow(2.0, -53);

// c: ldexp((a<< 32)|b) * ((1<<53)+1) >> 64, -53)
// TODO: not enough prec...
private double intPairToRealInclusive(int a, int b) {
BigInteger c = BigInteger.valueOf(a & 0xffffffffL);
BigInteger d = BigInteger.valueOf(b & 0xffffffffL);
return c.shiftLeft(32).or(d).multiply(INTPAIR_CONST).shiftRight(64).doubleValue()
* LDEXP_CONST;
}

public int[] getState() {
return state;
}

public int getLeft() {
return left;
}


public static class RandomType {

public static Random randomFromLong(long seed) {
long v = Math.abs(seed);
if (v == (v & 0xffffffffL)) {
return new Random((int) v);
} else {
int[] ints = new int[2];
ints[0] = (int) v;
ints[1] = (int) (v >> 32);
return new Random(ints);
}
}

}

}
186 changes: 186 additions & 0 deletions truffle/src/main/java/org/jruby/truffle/util/SafePropertyAccessor.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
/***** BEGIN LICENSE BLOCK *****
* 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) 2007 Vladimir Sizikov <vsizikov@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"),
* 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.
***** END LICENSE BLOCK *****/

package org.jruby.truffle.util;

import java.util.Map;

/**
* Utility class to safely access system properties in security-sensitive
* environments.
*/
public class SafePropertyAccessor {

/**
* An extension over <code>Boolean.getBoolean</code> method.
* Returns true if and only if the system property
* named by the argument exists and is equal to the string "true".
* If there is no property with the specified name, or if the specified
* name is empty or null, or if the access to the property is
* restricted, then false is returned.
* @param property The system property name.
* @return The boolean value of the system property.
*/
public static boolean getBoolean(String property) {
try {
return Boolean.getBoolean(property);
} catch (SecurityException se) {
return false;
}
}

/**
* An extension over <code>Boolean.getBoolean</code> method.
* Handles security restrictions, and provides default value
* in case when access to the property is restricted,
* of when the property does not exist.
* @param property The system property name.
* @param defValue The default value.
* @return The boolean value of the system property,
* or the default value.
*/
public static boolean getBoolean(String property, boolean defValue) {
try {
if (System.getProperty(property) != null) {
return Boolean.getBoolean(property);
} else {
return defValue;
}
} catch (SecurityException se) {
return defValue;
}
}

/**
* An extension over <code>System.getProperty</code> method.
* Handles security restrictions, and returns <code>null</code>
* if the access to the property is restricted.
* @param property The system property name.
* @return The value of the system property,
* or the default value.
*/
public static String getProperty(String property) {
return getProperty(property, null);
}

/**
* An extension over <code>System.getProperty</code> method.
* Handles security restrictions, and returns the default
* value if the access to the property is restricted.
* @param property The system property name.
* @param defValue The default value.
* @return The value of the system property,
* or the default value.
*/
public static String getProperty(String property, String defValue) {
try {
return System.getProperty(property, defValue);
} catch (SecurityException se) {
return defValue;
}
}

/**
* An extension over <code>System.getProperty</code> method
* that additionally produces an int value.
* Handles security restrictions, and returns <code>0</code>
* if the access to the property is restricted.
* @param property The system property name.
* @return The value of the system property,
* or the default value.
*/
public static int getInt(String property) {
return getInt(property, 0);
}

/**
* An extension over <code>System.getProperty</code> method
* that additionally produces an int value.
* Handles security restrictions, and returns the default
* value if the access to the property is restricted.
* @param property The system property name.
* @param defValue The default value.
* @return The value of the system property,
* or the default value.
*/
public static int getInt(String property, int defValue) {
try {
return Integer.parseInt(System.getProperty(property, String.valueOf(defValue)));
} catch (SecurityException se) {
return defValue;
}
}

/**
* Returns <code>true</code> if the access to the system property
* is restricted (i.e., when System.getProperty()
* throws SecurityException).
* @param property The system property name.
* @return <code>true</code> if the access is restricted,
* <code>false</code> otherwise.
*/
public static boolean isSecurityProtected(String property) {
try {
System.getProperty(property);
return false;
} catch (SecurityException se) {
return true;
}
}

/**
* An extension over <code>System.getenv</code> method.
* Handles security restrictions, and returns <code>null</code>
* if the access to the environment variable is restricted.
* @param name The environment variable name.
* @return The value of the environment variable,
* or null.
*/
public static String getenv(String name) {
try {
return System.getenv(name);
} catch (SecurityException se) {
return null;
}
}

/**
* An extension over <code>System.getenv</code> method.
* Handles security restrictions, and returns <code>null</code>
* if the access to the environment map is restricted.
* @return The map of the environment variables,
* or null.
*/
public static Map<String,String> getenv() {
try {
return System.getenv();
} catch (SecurityException se) {
return null;
}
}
}

0 comments on commit 540ce66

Please sign in to comment.