Skip to content

Commit

Permalink
Showing 70 changed files with 936 additions and 465 deletions.
2 changes: 1 addition & 1 deletion bin/jruby.bash
Original file line number Diff line number Diff line change
@@ -247,11 +247,11 @@ do
# Pass -X... and -X? search options through
-X*\.\.\.|-X*\?)
ruby_args=("${ruby_args[@]}" "$1") ;;
# Match -Xa.b.c=d to translate to -Da.b.c=d as a java option
-X+T)
JRUBY_CP="$JRUBY_CP$CP_DELIMITER$JRUBY_HOME/lib/jruby-truffle.jar"
ruby_args=("${ruby_args[@]}" "-X+T")
;;
# Match -Xa.b.c=d to translate to -Da.b.c=d as a java option
-X*)
val=${1:2}
if expr "$val" : '.*[.]' > /dev/null; then
2 changes: 1 addition & 1 deletion bin/jruby.sh
Original file line number Diff line number Diff line change
@@ -196,11 +196,11 @@ do
# Pass -X... and -X? search options through
-X*\.\.\.|-X*\?)
ruby_args="${ruby_args} $1" ;;
# Match -Xa.b.c=d to translate to -Da.b.c=d as a java option
-X+T)
JRUBY_CP="$JRUBY_CP$CP_DELIMITER$JRUBY_HOME/lib/jruby-truffle.jar"
ruby_args="${ruby_args} -X+T"
;;
# Match -Xa.b.c=d to translate to -Da.b.c=d as a java option
-X*)
val=${1:2}
if expr "$val" : '.*[.]' > /dev/null; then
2 changes: 1 addition & 1 deletion core/pom.rb
Original file line number Diff line number Diff line change
@@ -46,7 +46,7 @@
jar 'com.github.jnr:jnr-x86asm:1.0.2', :exclusions => ['com.github.jnr:jnr-ffi']
jar 'com.github.jnr:jnr-unixsocket:0.12', :exclusions => ['com.github.jnr:jnr-ffi']
jar 'com.github.jnr:jnr-posix:3.0.29', :exclusions => ['com.github.jnr:jnr-ffi']
jar 'com.github.jnr:jnr-constants:0.9.1', :exclusions => ['com.github.jnr:jnr-ffi']
jar 'com.github.jnr:jnr-constants:0.9.2-SNAPSHOT', :exclusions => ['com.github.jnr:jnr-ffi']
jar 'com.github.jnr:jnr-ffi:2.0.9'
jar 'com.github.jnr:jffi:${jffi.version}'
jar 'com.github.jnr:jffi:${jffi.version}:native'
2 changes: 1 addition & 1 deletion core/pom.xml
Original file line number Diff line number Diff line change
@@ -147,7 +147,7 @@ DO NOT MODIFIY - GENERATED CODE
<dependency>
<groupId>com.github.jnr</groupId>
<artifactId>jnr-constants</artifactId>
<version>0.9.1</version>
<version>0.9.2-SNAPSHOT</version>
<exclusions>
<exclusion>
<artifactId>jnr-ffi</artifactId>
2 changes: 1 addition & 1 deletion core/src/main/java/org/jruby/Main.java
Original file line number Diff line number Diff line change
@@ -399,7 +399,7 @@ private String getRuntimeFlagValue(String prefix) {

private Status handleMainExit(MainExitException mee) {
if (!mee.isAborted()) {
config.getOutput().println(mee.getMessage());
config.getError().println(mee.getMessage());
if (mee.isUsageError()) {
doPrintUsage(true);
}
8 changes: 8 additions & 0 deletions core/src/main/java/org/jruby/Ruby.java
Original file line number Diff line number Diff line change
@@ -40,6 +40,7 @@
package org.jruby;

import org.jcodings.specific.UTF8Encoding;
import org.jruby.anno.TypePopulator;
import org.jruby.ast.ArrayNode;
import org.jruby.ast.BlockNode;
import org.jruby.ast.CallNode;
@@ -5290,4 +5291,11 @@ public void addToObjectSpace(boolean useObjectSpace, IRubyObject object) {
* The nullToNil filter for this runtime.
*/
private MethodHandle nullToNil;

public final ClassValue<TypePopulator> POPULATORS = new ClassValue<TypePopulator>() {
@Override
protected TypePopulator computeValue(Class<?> type) {
return RubyModule.loadPopulatorFor(type);
}
};
}
14 changes: 12 additions & 2 deletions core/src/main/java/org/jruby/RubyClass.java
Original file line number Diff line number Diff line change
@@ -1968,12 +1968,22 @@ private CS_NAMES(String id) {
this.id = id;
}

private static final CS_NAMES[] VALUES = values();
public static final int length = VALUES.length;

public static CS_NAMES fromOrdinal(int ordinal) {
if (ordinal < 0 || ordinal >= VALUES.length) {
throw new RuntimeException("invalid rest: " + ordinal);
}
return VALUES[ordinal];
}

public final String id;
};
private final CallSite[] baseCallSites = new CallSite[CS_NAMES.values().length];
private final CallSite[] baseCallSites = new CallSite[CS_NAMES.length];
{
for(int i = 0; i < baseCallSites.length; i++) {
baseCallSites[i] = MethodIndex.getFunctionalCallSite(CS_NAMES.values()[i].id);
baseCallSites[i] = MethodIndex.getFunctionalCallSite(CS_NAMES.fromOrdinal(i).id);
}
}

6 changes: 5 additions & 1 deletion core/src/main/java/org/jruby/RubyHash.java
Original file line number Diff line number Diff line change
@@ -1664,7 +1664,11 @@ public void visit(IRubyObject key, IRubyObject value) {
*
*/

private static class Mismatch extends RuntimeException {}
private static class Mismatch extends RuntimeException {
public Throwable fillInStackTrace() {
return this;
}
}
private static final Mismatch MISMATCH = new Mismatch();

/** rb_hash_shift
28 changes: 13 additions & 15 deletions core/src/main/java/org/jruby/RubyIO.java
Original file line number Diff line number Diff line change
@@ -1952,7 +1952,6 @@ public IRubyObject close() {
if (isClosed()) {
return runtime.getNil();
}
openFile.checkClosed();
return rbIoClose(runtime);
}

@@ -3734,7 +3733,6 @@ private void setupPopen(ModeFlags modes, POpenProcess process) throws RaiseExcep
ChannelFD main = new ChannelFD(inChannel, runtime.getPosix(), runtime.getFilenoUtil());

openFile.setFD(main);
openFile.setMode(OpenFile.READABLE);
}

if (openFile.isWritable() && process.hasOutput()) {
@@ -3748,11 +3746,16 @@ private void setupPopen(ModeFlags modes, POpenProcess process) throws RaiseExcep

ChannelFD pipe = new ChannelFD(outChannel, runtime.getPosix(), runtime.getFilenoUtil());

RubyIO writeIO = new RubyIO(runtime, runtime.getIO());
writeIO.initializeCommon(runtime.getCurrentContext(), pipe, runtime.newFixnum(OpenFlags.O_WRONLY), runtime.getNil());
// if also readable, attach as tied IO; otherwise, primary IO
if (openFile.isReadable()) {
RubyIO writeIO = new RubyIO(runtime, runtime.getIO());
writeIO.initializeCommon(runtime.getCurrentContext(), pipe, runtime.newFixnum(OpenFlags.O_WRONLY), runtime.getNil());

openFile.tiedIOForWriting = writeIO;
setInstanceVariable("@tied_io_for_writing", writeIO);
openFile.tiedIOForWriting = writeIO;
setInstanceVariable("@tied_io_for_writing", writeIO);
} else {
openFile.setFD(pipe);
}
}
}

@@ -3884,15 +3887,10 @@ public static IRubyObject popen(ThreadContext context, IRubyObject recv, IRubyOb
io.setupPopen(modes, process);

if (block.isGiven()) {
try {
return block.yield(context, io);
} finally {
if (io.openFile.isOpen()) {
io.close();
}
// RubyStatus uses real native status now, so we unshift Java's shifted exit status
context.setLastExitStatus(RubyProcess.RubyStatus.newProcessStatus(runtime, process.waitFor() << 8, ShellLauncher.getPidFromProcess(process)));
}
ensureYieldClose(context, io, block);

// RubyStatus uses real native status now, so we unshift Java's shifted exit status
context.setLastExitStatus(RubyProcess.RubyStatus.newProcessStatus(runtime, process.waitFor() << 8, ShellLauncher.getPidFromProcess(process)));
}
return io;
} catch (IOException e) {
31 changes: 19 additions & 12 deletions core/src/main/java/org/jruby/RubyModule.java
Original file line number Diff line number Diff line change
@@ -82,6 +82,7 @@
import org.jruby.internal.runtime.methods.WrapperMethod;
import org.jruby.ir.IRClosure;
import org.jruby.ir.IRMethod;
import org.jruby.javasupport.binding.Initializer;
import org.jruby.parser.StaticScope;
import org.jruby.runtime.Arity;
import org.jruby.runtime.Block;
@@ -936,7 +937,7 @@ public static class MethodClumper {
Map<String, List<JavaMethodDescriptor>> allAnnotatedMethods = new HashMap<String, List<JavaMethodDescriptor>>();

public void clump(Class cls) {
Method[] declaredMethods = cls.getDeclaredMethods();
Method[] declaredMethods = Initializer.DECLARED_METHODS.get(cls);
for (Method method: declaredMethods) {
JRubyMethod anno = method.getAnnotation(JRubyMethod.class);

@@ -1005,28 +1006,34 @@ public Map<String, List<JavaMethodDescriptor>> getStaticAnnotatedMethods() {
}
}

public void defineAnnotatedMethodsIndividually(Class clazz) {
TypePopulator populator;

if (Options.DEBUG_FULLTRACE.load() || Options.REFLECTED_HANDLES.load() || Options.INVOKEDYNAMIC_HANDLES.load()) {
public static TypePopulator loadPopulatorFor(Class<?> type) {
if (Options.DEBUG_FULLTRACE.load() || Options.REFLECTED_HANDLES.load()) {
// we want non-generated invokers or need full traces, use default (slow) populator
if (DEBUG) LOG.info("trace mode, using default populator");
populator = TypePopulator.DEFAULT;
} else {
try {
String qualifiedName = "org.jruby.gen." + clazz.getCanonicalName().replace('.', '$');
String qualifiedName = "org.jruby.gen." + type.getCanonicalName().replace('.', '$');
String fullName = qualifiedName + AnnotationBinder.POPULATOR_SUFFIX;
String fullPath = fullName.replace('.', '/') + ".class";

if (DEBUG) LOG.info("looking for " + qualifiedName + AnnotationBinder.POPULATOR_SUFFIX);
if (DEBUG) LOG.info("looking for " + fullName);

Class populatorClass = Class.forName(qualifiedName + AnnotationBinder.POPULATOR_SUFFIX);
populator = (TypePopulator)populatorClass.newInstance();
if (Ruby.getClassLoader().getResource(fullPath) == null) {
if (DEBUG) LOG.info("Could not find it, using default populator");
} else {
Class populatorClass = Class.forName(qualifiedName + AnnotationBinder.POPULATOR_SUFFIX);
return (TypePopulator) populatorClass.newInstance();
}
} catch (Throwable t) {
if (DEBUG) LOG.info("Could not find it, using default populator");
populator = TypePopulator.DEFAULT;
}
}

populator.populate(this, clazz);
return new TypePopulator.ReflectiveTypePopulator(type);
}

public void defineAnnotatedMethodsIndividually(Class clazz) {
getRuntime().POPULATORS.get(clazz).populate(this, clazz);
}

public boolean defineAnnotatedMethod(String name, List<JavaMethodDescriptor> methods, MethodFactory methodFactory) {
141 changes: 115 additions & 26 deletions core/src/main/java/org/jruby/RubyRegexp.java
Original file line number Diff line number Diff line change
@@ -486,43 +486,132 @@ public static RubyString preprocessDRegexp(Ruby runtime, RubyString[] strings, i
public static RubyString preprocessDRegexp(Ruby runtime, IRubyObject[] strings, RegexpOptions options) {
RubyString string = null;
Encoding regexpEnc = null;
Encoding[] fixedEnc = new Encoding[1];

for (int i = 0; i < strings.length; i++) {
RubyString str = strings[i].convertToString();
Encoding strEnc = str.getEncoding();
regexpEnc = processDRegexpElement(runtime, options, regexpEnc, runtime.getCurrentContext().encodingHolder(), str);
string = string == null ? string = (RubyString)str.dup() : string.append19(str);
}

if (options.isEncodingNone() && strEnc != ASCIIEncoding.INSTANCE) {
if (str.scanForCodeRange() != StringSupport.CR_7BIT) {
throw runtime.newRegexpError("/.../n has a non escaped non ASCII character in non ASCII-8BIT script");
}
strEnc = ASCIIEncoding.INSTANCE;
}
if (regexpEnc != null) string.setEncoding(regexpEnc);

// This used to call preprocess, but the resulting bytelist was not
// used. Since the preprocessing error-checking can be done without
// creating a new bytelist, I added a "light" path.
RubyRegexp.preprocessLight(runtime, str.getByteList(), strEnc, fixedEnc, RegexpSupport.ErrorMode.PREPROCESS);
return string;
}

if (fixedEnc[0] != null) {
if (regexpEnc != null && regexpEnc != fixedEnc[0]) {
throw runtime.newRegexpError("encoding mismatch in dynamic regexp: " + new String(regexpEnc.getName()) + " and " + new String(fixedEnc[0].getName()));
}
regexpEnc = fixedEnc[0];
}
public static RubyString preprocessDRegexp(Ruby runtime, IRubyObject arg0, RegexpOptions options) {
return processElementIntoResult(runtime, null, arg0, options, null, runtime.getCurrentContext().encodingHolder());
}

public static RubyString preprocessDRegexp(Ruby runtime, IRubyObject arg0, IRubyObject arg1, RegexpOptions options) {
return processElementIntoResult(runtime, null, arg0, arg1, options, null, runtime.getCurrentContext().encodingHolder());
}

public static RubyString preprocessDRegexp(Ruby runtime, IRubyObject arg0, IRubyObject arg1, IRubyObject arg2, RegexpOptions options) {
return processElementIntoResult(runtime, null, arg0, arg1, arg2, options, null, runtime.getCurrentContext().encodingHolder());
}

public static RubyString preprocessDRegexp(Ruby runtime, IRubyObject arg0, IRubyObject arg1, IRubyObject arg2, IRubyObject arg3, RegexpOptions options) {
return processElementIntoResult(runtime, null, arg0, arg1, arg2, arg3, options, null, runtime.getCurrentContext().encodingHolder());
}

public static RubyString preprocessDRegexp(Ruby runtime, IRubyObject arg0, IRubyObject arg1, IRubyObject arg2, IRubyObject arg3, IRubyObject arg4, RegexpOptions options) {
return processElementIntoResult(runtime, null, arg0, arg1, arg2, arg3, arg4, options, null, runtime.getCurrentContext().encodingHolder());
}

private static RubyString processElementIntoResult(
Ruby runtime,
RubyString result,
IRubyObject arg0,
IRubyObject arg1,
IRubyObject arg2,
IRubyObject arg3,
IRubyObject arg4,
RegexpOptions options,
Encoding regexpEnc,
Encoding[] fixedEnc) {
RubyString str = arg0.convertToString();
regexpEnc = processDRegexpElement(runtime, options, regexpEnc, fixedEnc, str);
return processElementIntoResult(runtime, result == null ? str.strDup(runtime) : result.append19(str), arg1, arg2, arg3, arg4, options, regexpEnc, fixedEnc);
}

private static RubyString processElementIntoResult(
Ruby runtime,
RubyString result,
IRubyObject arg0,
IRubyObject arg1,
IRubyObject arg2,
IRubyObject arg3,
RegexpOptions options,
Encoding regexpEnc,
Encoding[] fixedEnc) {
RubyString str = arg0.convertToString();
regexpEnc = processDRegexpElement(runtime, options, regexpEnc, fixedEnc, str);
return processElementIntoResult(runtime, result == null ? str.strDup(runtime) : result.append19(str), arg1, arg2, arg3, options, regexpEnc, fixedEnc);
}

private static RubyString processElementIntoResult(
Ruby runtime,
RubyString result,
IRubyObject arg0,
IRubyObject arg1,
IRubyObject arg2,
RegexpOptions options,
Encoding regexpEnc,
Encoding[] fixedEnc) {
RubyString str = arg0.convertToString();
regexpEnc = processDRegexpElement(runtime, options, regexpEnc, fixedEnc, str);
return processElementIntoResult(runtime, result == null ? str.strDup(runtime) : result.append19(str), arg1, arg2, options, regexpEnc, fixedEnc);
}

private static RubyString processElementIntoResult(
Ruby runtime,
RubyString result,
IRubyObject arg0,
IRubyObject arg1,
RegexpOptions options,
Encoding regexpEnc,
Encoding[] fixedEnc) {
RubyString str = arg0.convertToString();
regexpEnc = processDRegexpElement(runtime, options, regexpEnc, fixedEnc, str);
return processElementIntoResult(runtime, result == null ? str.strDup(runtime) : result.append19(str), arg1, options, regexpEnc, fixedEnc);
}

private static RubyString processElementIntoResult(
Ruby runtime,
RubyString result,
IRubyObject arg0,
RegexpOptions options,
Encoding regexpEnc,
Encoding[] fixedEnc) {
RubyString str = arg0.convertToString();
regexpEnc = processDRegexpElement(runtime, options, regexpEnc, fixedEnc, str);
result = result == null ? str.strDup(runtime) : result.append19(str);
if (regexpEnc != null) result.setEncoding(regexpEnc);
return result;
}

if (string == null) {
string = (RubyString)str.dup();
} else {
string.append19(str);
private static Encoding processDRegexpElement(Ruby runtime, RegexpOptions options, Encoding regexpEnc, Encoding[] fixedEnc, RubyString str) {
Encoding strEnc = str.getEncoding();

if (options.isEncodingNone() && strEnc != ASCIIEncoding.INSTANCE) {
if (str.scanForCodeRange() != StringSupport.CR_7BIT) {
throw runtime.newRegexpError("/.../n has a non escaped non ASCII character in non ASCII-8BIT script");
}
strEnc = ASCIIEncoding.INSTANCE;
}

if (regexpEnc != null) {
string.setEncoding(regexpEnc);
}
// This used to call preprocess, but the resulting bytelist was not
// used. Since the preprocessing error-checking can be done without
// creating a new bytelist, I added a "light" path.
RubyRegexp.preprocessLight(runtime, str.getByteList(), strEnc, fixedEnc, RegexpSupport.ErrorMode.PREPROCESS);

return string;
if (fixedEnc[0] != null) {
if (regexpEnc != null && regexpEnc != fixedEnc[0]) {
throw runtime.newRegexpError("encoding mismatch in dynamic regexp: " + new String(regexpEnc.getName()) + " and " + new String(fixedEnc[0].getName()));
}
regexpEnc = fixedEnc[0];
}
return regexpEnc;
}

private void check() {
Loading

0 comments on commit 797aea4

Please sign in to comment.