Skip to content

Commit

Permalink
Showing 72 changed files with 1,767 additions and 386 deletions.
4 changes: 0 additions & 4 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -76,10 +76,6 @@ tool/nailgun/ng
!bin/update_rubygems
bin/*

# These files are bin files for default gems
!lib/ruby/gems/shared/gems/rake-10.1.0/bin/rake
!lib/ruby/gems/shared/gems/rdoc-4.0.1/bin/rdoc
!lib/ruby/gems/shared/gems/rdoc-4.0.1/bin/ri
install/updates.xml

# generated ITs
68 changes: 37 additions & 31 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -13,50 +13,56 @@ os:
- osx

env:
# disable cext
global:
- JAVA_OPTS="-XX:+TieredCompilation -XX:TieredStopAtLevel=1 -Djruby.cext.enabled=false"
- JAVA_OPTS="-XX:+TieredCompilation -XX:TieredStopAtLevel=1"
matrix:
- TARGET='-Ptest'
- TARGET='-Pjruby_complete_jar_jruby'
- TARGET='-Prake -Dtask=test:jruby'
- TARGET='-Prake -Dtask=test:mri'
- TARGET='-Prake -Dtask=test:slow_suites'
- TARGET='-Prake -Dtask=test:tracing'
- TARGET='-Prake -Dtask=spec:ji'
- TARGET='-Prake -Dtask=spec:compiler'
- TARGET='-Prake -Dtask=spec:ffi'
- TARGET='-Prake -Dtask=spec:regression'
- TARGET='-Prake -Dtask=spec:ruby:fast'
- TARGET='-Prake -Dtask=spec:jruby'
- TARGET='-Prake -Dtask=spec:jrubyc'
- TARGET='-Prake -Dtask=spec:profiler'
- TARGET='-Ptruffle-specs-language'
- TARGET='-Ptruffle-specs-core'
- PHASE='-Ptest'
- PHASE='-Pjruby_complete_jar_jruby'
- PHASE='-Prake -Dtask=test:jruby'
- PHASE='-Prake -Dtask=test:mri'
- PHASE='-Prake -Dtask=test:slow_suites'
- PHASE='-Prake -Dtask=test:tracing'
- PHASE='-Prake -Dtask=spec:ji'
- PHASE='-Prake -Dtask=spec:compiler'
- PHASE='-Prake -Dtask=spec:ffi'
- PHASE='-Prake -Dtask=spec:regression'
- PHASE='-Prake -Dtask=spec:ruby:fast'
- PHASE='-Prake -Dtask=spec:jruby'
- PHASE='-Prake -Dtask=spec:jrubyc'
- PHASE='-Prake -Dtask=spec:profiler'
- PHASE='-Ptruffle-specs-language'
- PHASE='-Ptruffle-specs-core'

matrix:
include:
# these profile do no need to run for all JDKs
- env: TARGET='-Pdist'
- env: PHASE='-Pdist'
jdk: oraclejdk8
- env: TARGET='-Pjruby-jars'
- env: PHASE='-Pjruby-jars'
jdk: openjdk7
- env: TARGET='-Pmain'
- env: PHASE='-Pmain'
jdk: oraclejdk7
- env: TARGET='-Pcomplete'
- env: PHASE='-Pcomplete'
jdk: oraclejdk8
- env: TARGET='-Posgi'
- env: PHASE='-Posgi'
jdk: openjdk7
- env: TARGET='-Pj2ee'
- env: PHASE='-Pj2ee'
jdk: oraclejdk7
- script: test/check_versions.sh
- env: PHASE='-Pjruby-jars,test -Dinvoker.test=extended'
jdk: oraclejdk7
- env: PHASE='-Pmain,test -Dinvoker.test=extended'
jdk: oraclejdk8
- env: COMMAND=test/check_versions.sh
jdk: oraclejdk8
fast_finish: true
allow_failures:
- env: TARGET='-Pcomplete'
- env: TARGET='-Prake -Dtask=spec:jrubyc'
- env: TARGET='-Pjruby_complete_jar_jruby'
- env: TARGET='-Pj2ee'
- env: TARGET='-Prake -Dtask=spec:profiler'
- env: PHASE='-Pcomplete'
- env: PHASE='-Prake -Dtask=spec:jrubyc'
- env: PHASE='-Pjruby_complete_jar_jruby'
- env: PHASE='-Pj2ee'
- env: PHASE='-Prake -Dtask=spec:profiler'
- env: PHASE='-Pjruby-jars,test -Dinvoker.test=extended'
- env: PHASE='-Pmain,test -Dinvoker.test=extended'

branches:
only:
@@ -67,7 +73,7 @@ branches:
before_install:
- if [[ $TRAVIS_JDK_VERSION = 'oraclejdk8' ]]; then sudo apt-get update; sudo apt-get install oracle-java8-installer; else true; fi

script: travis_retry mvn -q -Pbootstrap clean package ; mvn install $TARGET -Dinvoker.skip=false | egrep -v 'Download|\\[exec\\] [[:digit:]]+/[[:digit:]]+|^[[:space:]]*\\[exec\\][[:space:]]*$' ; [ ${PIPESTATUS[0]} == 0 ]
script: if [[ -v COMMAND ]]; then $COMMAND; else travis_retry mvn -q -Pbootstrap clean package ; mvn install $PHASE -Dinvoker.skip=false | egrep -v 'Download|\\[exec\\] [[:digit:]]+/[[:digit:]]+|^[[:space:]]*\\[exec\\][[:space:]]*$' ; [ ${PIPESTATUS[0]} == 0 ]; fi
install: /bin/true
notifications:
irc:
517 changes: 517 additions & 0 deletions antlib/extra.xml

Large diffs are not rendered by default.

28 changes: 14 additions & 14 deletions core/src/main/java/org/jruby/RubyException.java
Original file line number Diff line number Diff line change
@@ -36,29 +36,26 @@
***** END LICENSE BLOCK *****/
package org.jruby;

import org.jruby.runtime.backtrace.BacktraceData;
import java.io.IOException;
import java.io.PrintStream;
import java.util.List;

import org.jruby.anno.JRubyClass;
import org.jruby.anno.JRubyMethod;
import org.jruby.exceptions.JumpException.FlowControlException;
import org.jruby.java.proxies.ConcreteJavaProxy;
import org.jruby.runtime.Block;
import org.jruby.runtime.ClassIndex;
import org.jruby.runtime.ObjectAllocator;
import org.jruby.runtime.ObjectMarshal;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.*;
import org.jruby.runtime.backtrace.BacktraceData;
import org.jruby.runtime.backtrace.RubyStackTraceElement;
import org.jruby.runtime.backtrace.TraceType;
import static org.jruby.runtime.Visibility.*;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.runtime.builtin.Variable;
import org.jruby.runtime.component.VariableEntry;
import org.jruby.runtime.marshal.MarshalStream;
import org.jruby.runtime.marshal.UnmarshalStream;

import java.io.IOException;
import java.io.PrintStream;
import java.util.List;

import static org.jruby.runtime.Visibility.PRIVATE;

/**
*
* @author jpetersen
@@ -94,11 +91,14 @@ public IRubyObject backtrace() {
public IRubyObject set_backtrace(IRubyObject obj) {
if (obj.isNil()) {
backtrace = null;
} else if (!isArrayOfStrings(obj)) {
throw getRuntime().newTypeError("backtrace must be Array of String");
} else {
} else if (isArrayOfStrings(obj)) {
backtrace = obj;
} else if (obj instanceof RubyString) {
backtrace = RubyArray.newArray(getRuntime(), obj);
} else {
throw getRuntime().newTypeError("backtrace must be Array of String or a single String");
}

return backtrace();
}

4 changes: 1 addition & 3 deletions core/src/main/java/org/jruby/RubyFileTest.java
Original file line number Diff line number Diff line change
@@ -128,9 +128,7 @@ public static RubyBoolean file_p(IRubyObject recv, IRubyObject filename) {

@JRubyMethod(name = "file?", required = 1, module = true)
public static RubyBoolean file_p(ThreadContext context, IRubyObject recv, IRubyObject filename) {
FileStat stat = fileResource(filename).stat();

return context.runtime.newBoolean(stat != null && stat.isFile());
return context.runtime.newBoolean(fileResource(filename).isFile());
}

@JRubyMethod(name = "grpowned?", required = 1, module = true)
13 changes: 12 additions & 1 deletion core/src/main/java/org/jruby/RubyInstanceConfig.java
Original file line number Diff line number Diff line change
@@ -55,6 +55,7 @@
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.math.BigDecimal;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
@@ -316,7 +317,8 @@ private String calculateJRubyHome() {

// RegularFileResource absolutePath will canonicalize resources so that will change c: paths to C:.
// We will cannonicalize on windows so that jruby.home is also C:.
if (Platform.IS_WINDOWS) {
// assume all those uri-like pathnames are already in absolute form
if (Platform.IS_WINDOWS && !newJRubyHome.startsWith("jar:") && !newJRubyHome.startsWith("file:") && !newJRubyHome.startsWith("classpath:") && !newJRubyHome.startsWith("uri:")) {
File file = new File(newJRubyHome);

try {
@@ -1531,6 +1533,15 @@ public boolean shouldPrecompileAll() {
////////////////////////////////////////////////////////////////////////////
// Static configuration fields, used as defaults for new JRuby instances.
////////////////////////////////////////////////////////////////////////////

// NOTE: These BigDecimal fields must be initialized before calls to initGlobalJavaVersion

/** A BigDecimal representing 1.5, for Java spec version matching */
private static final BigDecimal BIGDECIMAL_1_5 = new BigDecimal("1.5");
/** A BigDecimal representing 1.6, for Java spec version matching */
private static final BigDecimal BIGDECIMAL_1_6 = new BigDecimal("1.6");
/** A BigDecimal representing 1.7, for Java spec version matching */
private static final BigDecimal BIGDECIMAL_1_7 = new BigDecimal("1.7");

/**
* The version to use for generated classes. Set to current JVM version by default
23 changes: 23 additions & 0 deletions core/src/main/java/org/jruby/embed/ScriptingContainer.java
Original file line number Diff line number Diff line change
@@ -715,12 +715,35 @@ public ProfilingMode getProfilingMode() {
*
* @since JRuby 1.6.6.
*
* @deprecated Use setProfilingMode instead
*
* @param mode a new profiling mode to be set.
*/
@Deprecated
public void setProfile(ProfilingMode mode) {
provider.getRubyInstanceConfig().setProfilingMode(mode);
}

/**
* Changes a ProfilingMode to a given one. The default value is Profiling.OFF.
* Call this method before you use put/get, runScriptlet, and parse methods so that
* initial configurations will work.
*
* ProfilingMode allows you to change profiling style.
*
* Profiling.OFF - default. profiling off.
* Profiling.API - activates Ruby profiler API. equivalent to --profile.api command line option
* Profiling.FLAT - synonym for --profile command line option equivalent to --profile.flat command line option
* Profiling.GRAPH - runs with instrumented (timed) profiling, graph format. equivalent to --profile.graph command line option.
*
* @since JRuby 1.7.15
*
* @param mode a new profiling mode to be set.
*/
public void setProfilingMode(ProfilingMode mode) {
provider.getRubyInstanceConfig().setProfilingMode(mode);
}

/**
* Returns a LoadServiceCreator currently used.
*
10 changes: 6 additions & 4 deletions core/src/main/java/org/jruby/ext/ffi/Enums.java
Original file line number Diff line number Diff line change
@@ -51,8 +51,9 @@
* Represents a C enum
*/
@JRubyClass(name="FFI::Enums", parent="Object")
public final class Enums extends RubyHash {
public final class Enums extends RubyObject {
private final RubyArray allEnums;
private final RubyHash symbolMap;
private final RubyHash taggedEnums;

public static RubyClass createEnumsClass(Ruby runtime, RubyModule ffiModule) {
@@ -77,6 +78,7 @@ private Enums(Ruby runtime, RubyClass klass) {
super(runtime, klass);
allEnums = RubyArray.newArray(runtime);
taggedEnums = RubyHash.newHash(runtime);
symbolMap = RubyHash.newHash(runtime);
}

@JRubyMethod(name = "initialize", visibility = Visibility.PRIVATE)
@@ -93,12 +95,12 @@ public IRubyObject append(final ThreadContext context, IRubyObject item){
if (!(item == null || item == context.nil)){
taggedEnums.fastASet(((Enum)item).tag(context), item);
}
merge_bang(context, ((Enum)item).symbol_map(context), Block.NULL_BLOCK);
symbolMap.merge_bang(context, ((Enum)item).symbol_map(context), Block.NULL_BLOCK);
return item;
}

public boolean isEmpty(){
return (super.isEmpty() && allEnums.isEmpty() && taggedEnums.isEmpty());
return ( allEnums.isEmpty() && symbolMap.isEmpty() && taggedEnums.isEmpty());
}

@JRubyMethod(name = "empty?")
@@ -122,6 +124,6 @@ public IRubyObject find(final ThreadContext context, IRubyObject query){

@JRubyMethod(name = "__map_symbol")
public IRubyObject mapSymbol(final ThreadContext context, IRubyObject symbol){
return op_aref(context, symbol);
return symbolMap.op_aref(context, symbol);
}
}
51 changes: 33 additions & 18 deletions core/src/main/java/org/jruby/ext/ffi/TypeResolver.java
Original file line number Diff line number Diff line change
@@ -2,6 +2,7 @@

import org.jruby.Ruby;
import org.jruby.RubySymbol;
import org.jruby.RubyHash;
import org.jruby.runtime.builtin.IRubyObject;

import java.util.Collections;
@@ -17,32 +18,41 @@ public final class TypeResolver {
}

public final Type findType(Ruby runtime, IRubyObject name) {
return findType(runtime, name, null);
}

public final Type findType(Ruby runtime, IRubyObject name, IRubyObject typeMap) {

if (name instanceof Type) {
return (Type) name;

} else if (name instanceof RubySymbol) {
return findType(runtime, (RubySymbol) name);
Object obj = ((RubySymbol)name).getFFIHandle();
if (obj instanceof Type) {
return ((Type) obj);
}

if (typeMap != null && typeMap instanceof RubyHash) {
Type type = (Type)((RubyHash)typeMap).get(name);
if (type != null && !type.isNil()) {
return type;
}
}

Type type = symbolTypeCache.get(name);
if (type != null) {
return type;
}

return lookupAndCacheType(runtime, (RubySymbol)name, (RubyHash)typeMap);

} else {
return lookupType(runtime, name);
return lookupType(runtime, name, typeMap);
}
}
public final Type findType(Ruby runtime, RubySymbol name) {
Object obj = name.getFFIHandle();
if (obj instanceof Type) {
return ((Type) obj);
}

Type type = symbolTypeCache.get(name);
if (type != null) {
return type;
}

return lookupAndCacheType(runtime, name);
}

private synchronized Type lookupAndCacheType(Ruby runtime, RubySymbol name) {
Type type = lookupType(runtime, name);
private synchronized Type lookupAndCacheType(Ruby runtime, RubySymbol name, RubyHash typeMap) {
Type type = lookupType(runtime, name, typeMap);

Map<RubySymbol, Type> map = new IdentityHashMap<RubySymbol, Type>(symbolTypeCache);
map.put(name, type);
@@ -53,12 +63,17 @@ private synchronized Type lookupAndCacheType(Ruby runtime, RubySymbol name) {
}

private Type lookupType(Ruby runtime, IRubyObject name) {
return lookupType(runtime, name, null);
}

private Type lookupType(Ruby runtime, IRubyObject name, IRubyObject typeMap) {
IRubyObject type = ffi.typedefs.fastARef(name);
if (type instanceof Type) {
return (Type) type;
}

if ((type = ffi.ffiModule.callMethod(runtime.getCurrentContext(), "find_type", name)) instanceof Type) {
IRubyObject args[] = new IRubyObject[]{name, typeMap};
if ((type = ffi.ffiModule.callMethod(runtime.getCurrentContext(), "find_type", args)) instanceof Type) {
return (Type) type;
}

4 changes: 4 additions & 0 deletions core/src/main/java/org/jruby/ext/ffi/Util.java
Original file line number Diff line number Diff line change
@@ -174,6 +174,10 @@ public static Type findType(ThreadContext context, IRubyObject name) {
return context.runtime.getFFI().getTypeResolver().findType(context.runtime, name);
}

public static Type findType(ThreadContext context, IRubyObject name, IRubyObject typeMap) {
return context.runtime.getFFI().getTypeResolver().findType(context.runtime, name, typeMap);
}

public static ByteOrder parseByteOrder(Ruby runtime, IRubyObject byte_order) {
if (byte_order instanceof RubySymbol || byte_order instanceof RubyString) {
String orderName = byte_order.asJavaString();
55 changes: 46 additions & 9 deletions core/src/main/java/org/jruby/ext/ffi/jffi/DataConverters.java
Original file line number Diff line number Diff line change
@@ -19,8 +19,9 @@
*/
public class DataConverters {
@SuppressWarnings("unchecked")
private static final Map<RubyHash, NativeDataConverter> enumConverters = Collections.synchronizedMap(new WeakIdentityHashMap());
private static final Map<IRubyObject, NativeDataConverter> enumConverters = Collections.synchronizedMap(new WeakIdentityHashMap());

@Deprecated
static boolean isEnumConversionRequired(Type type, RubyHash enums) {
if (type instanceof Type.Builtin && enums != null && !enums.isEmpty()) {
switch (type.getNativeType()) {
@@ -42,7 +43,28 @@ static boolean isEnumConversionRequired(Type type, RubyHash enums) {
}
return false;
}


static boolean isEnumConversionRequired(Type type, Enums enums) {
if (type instanceof Type.Builtin && enums != null && !enums.isEmpty()) {
switch (type.getNativeType()) {
case CHAR:
case UCHAR:
case SHORT:
case USHORT:
case INT:
case UINT:
case LONG:
case ULONG:
case LONG_LONG:
case ULONG_LONG:
return true;

default:
return false;
}
}
return false;
}

static NativeDataConverter getResultConverter(Type type) {
if (type instanceof Type.Builtin) {
@@ -70,6 +92,7 @@ static NativeDataConverter getParameterConverter(Type type) {
return null;
}

@Deprecated
static NativeDataConverter getParameterConverter(Type type, RubyHash enums) {
if (isEnumConversionRequired(type, enums)) {
NativeDataConverter converter = enumConverters.get(enums);
@@ -84,12 +107,26 @@ static NativeDataConverter getParameterConverter(Type type, RubyHash enums) {
}
}

static NativeDataConverter getParameterConverter(Type type, Enums enums) {
if (isEnumConversionRequired(type, enums)) {
NativeDataConverter converter = enumConverters.get(enums);
if (converter != null) {
return converter;
}
enumConverters.put(enums, converter = new IntOrEnumConverter(NativeType.INT, enums));
return converter;

} else {
return getParameterConverter(type);
}
}

public static final class IntOrEnumConverter extends NativeDataConverter {
private final NativeType nativeType;
private final RubyHash enums;
private final IRubyObject enums;
private volatile IdentityHashMap<RubySymbol, RubyInteger> symbolToValue = new IdentityHashMap<RubySymbol, RubyInteger>();

public IntOrEnumConverter(NativeType nativeType, RubyHash enums) {
public IntOrEnumConverter(NativeType nativeType, IRubyObject enums) {
this.nativeType = nativeType;
this.enums = enums;
}
@@ -111,25 +148,25 @@ public IRubyObject toNative(ThreadContext context, IRubyObject obj) {
return obj;
}

return lookupOrConvert(obj);
return lookupOrConvert(context, obj);
}

IRubyObject lookupOrConvert(IRubyObject obj) {
IRubyObject lookupOrConvert(ThreadContext context, IRubyObject obj) {
if (obj instanceof RubySymbol) {
IRubyObject value;
if ((value = symbolToValue.get(obj)) != null) {
return value;
}

return lookupAndCacheValue(obj);
return lookupAndCacheValue(context, obj);

} else {
return obj.convertToInteger();
}
}

private synchronized IRubyObject lookupAndCacheValue(IRubyObject obj) {
IRubyObject value = enums.fastARef(obj);
private synchronized IRubyObject lookupAndCacheValue(ThreadContext context, IRubyObject obj) {
IRubyObject value = enums instanceof Enums ? ((Enums)enums).mapSymbol(context, obj) : ((RubyHash)enums).fastARef(obj);
if (value.isNil() || !(value instanceof RubyInteger)) {
throw obj.getRuntime().newArgumentError("invalid enum value, " + obj.inspect());
}
Original file line number Diff line number Diff line change
@@ -142,22 +142,31 @@ static FunctionInvoker getFunctionInvoker(NativeType returnType) {
* @return A new <tt>Marshaller</tt>
*/
static ParameterMarshaller getMarshaller(Type type, CallingConvention convention, IRubyObject enums) {
if (enums != null && !enums.isNil() && !(enums instanceof RubyHash || enums instanceof Enums)) {
throw type.getRuntime().newArgumentError("wrong argument type "
+ enums.getMetaClass().getName() + " (expected Hash or Enums)");
}

if (type instanceof Type.Builtin) {
return enums != null && !enums.isNil() ? getEnumMarshaller(type, convention, enums) : getMarshaller(type.getNativeType());

} else if (type instanceof org.jruby.ext.ffi.CallbackInfo) {
return new ConvertingMarshaller(getMarshaller(type.getNativeType()),
DataConverters.getParameterConverter(type, null));
DataConverters.getParameterConverter(type, (Enums)null));

} else if (type instanceof org.jruby.ext.ffi.StructByValue) {
return new StructByValueMarshaller((org.jruby.ext.ffi.StructByValue) type);

} else if (type instanceof org.jruby.ext.ffi.MappedType) {
MappedType ctype = (MappedType) type;
return new ConvertingMarshaller(
getMarshaller(ctype.getRealType(), convention, enums),
DataConverters.getParameterConverter(type,
enums instanceof RubyHash ? (RubyHash) enums : null));
if (enums == null || enums instanceof Enums)
return new ConvertingMarshaller(
getMarshaller(ctype.getRealType(), convention, (Enums)enums),
DataConverters.getParameterConverter(type, (Enums)enums));
else
return new ConvertingMarshaller(
getMarshaller(ctype.getRealType(), convention, enums.isNil() ? null : (RubyHash)enums),
DataConverters.getParameterConverter(type, enums.isNil() ? null : (RubyHash)enums));

} else {
return null;
@@ -172,11 +181,11 @@ static ParameterMarshaller getMarshaller(Type type, CallingConvention convention
* @return A new <tt>ParameterMarshaller</tt>
*/
static ParameterMarshaller getEnumMarshaller(Type type, CallingConvention convention, IRubyObject enums) {
if (!(enums instanceof RubyHash)) {
if (enums != null && !enums.isNil() && !(enums instanceof RubyHash || enums instanceof Enums)) {
throw type.getRuntime().newArgumentError("wrong argument type "
+ enums.getMetaClass().getName() + " (expected Hash or Enums)");
}
NativeDataConverter converter = DataConverters.getParameterConverter(type, (RubyHash) enums);
NativeDataConverter converter = DataConverters.getParameterConverter(type, (Enums)enums);
ParameterMarshaller marshaller = getMarshaller(type.getNativeType());
return converter != null ? new ConvertingMarshaller(marshaller, converter) : marshaller;
}
2 changes: 1 addition & 1 deletion core/src/main/java/org/jruby/ext/ffi/jffi/Function.java
Original file line number Diff line number Diff line change
@@ -119,7 +119,7 @@ public static IRubyObject newInstance(ThreadContext context, IRubyObject recv, I
}

enums = options.fastARef(context.runtime.newSymbol("enums"));
if (enums != null && !enums.isNil() && !(enums instanceof RubyHash)) {
if (enums != null && !enums.isNil() && !(enums instanceof RubyHash || enums instanceof Enums)) {
throw context.runtime.newTypeError("wrong type for options[:enum] "
+ enums.getMetaClass().getName() + " (expected Hash or Enums)");

2 changes: 1 addition & 1 deletion core/src/main/java/org/jruby/ext/ffi/jffi/JFFIInvoker.java
Original file line number Diff line number Diff line change
@@ -91,7 +91,7 @@ public static IRubyObject newInstance(ThreadContext context, IRubyObject recv, I
RubyHash options = (RubyHash) args[3];
convention = options.fastARef(context.runtime.newSymbol("convention")).asJavaString();
enums = options.fastARef(context.runtime.newSymbol("enums"));
if (enums != null && !enums.isNil() && !(enums instanceof RubyHash)) {
if (enums != null && !enums.isNil() && !(enums instanceof RubyHash || enums instanceof Enums)) {
throw context.runtime.newTypeError("wrong type for options[:enum] "
+ enums.getMetaClass().getName() + " (expected Hash or Enums)");

102 changes: 77 additions & 25 deletions core/src/main/java/org/jruby/ext/ffi/jffi/VariadicInvoker.java
Original file line number Diff line number Diff line change
@@ -6,25 +6,32 @@
import com.kenai.jffi.HeapInvocationBuffer;
import org.jruby.Ruby;
import org.jruby.RubyArray;
import org.jruby.RubyHash;
import org.jruby.RubyClass;
import org.jruby.RubyModule;
import org.jruby.RubyObject;
import org.jruby.anno.JRubyClass;
import org.jruby.anno.JRubyMethod;
import org.jruby.ext.ffi.Enums;
import org.jruby.ext.ffi.NativeType;
import org.jruby.ext.ffi.Pointer;
import org.jruby.ext.ffi.Type;
import org.jruby.runtime.Arity;
import org.jruby.runtime.ObjectAllocator;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.util.TypeConverter;

@JRubyClass(name = "FFI::VariadicInvoker", parent = "Object")
public class VariadicInvoker extends RubyObject {
private final CallingConvention convention;
private final Pointer address;
private final FunctionInvoker functionInvoker;
private final com.kenai.jffi.Type returnType;
private final IRubyObject enums;
private final boolean saveError;
private static final java.util.Locale LOCALE = java.util.Locale.ENGLISH;


public static RubyClass createVariadicInvokerClass(Ruby runtime, RubyModule module) {
RubyClass result = module.defineClassUnder("VariadicInvoker",
@@ -35,20 +42,19 @@ public static RubyClass createVariadicInvokerClass(Ruby runtime, RubyModule modu

return result;
}
/**
* Creates a new <tt>Invoker</tt> instance.
* @param arity
*/

private VariadicInvoker(Ruby runtime, IRubyObject klazz, Pointer address,
FunctionInvoker functionInvoker, com.kenai.jffi.Type returnType,
CallingConvention convention) {
CallingConvention convention, IRubyObject enums, boolean saveError) {
super(runtime, (RubyClass) klazz);
this.address = address;
this.functionInvoker = functionInvoker;
this.returnType = returnType;
this.convention = convention;
this.enums = enums;
this.saveError = saveError;
}

/**
* Returns the {@link org.jruby.runtime.Arity} of this function.
*
@@ -58,26 +64,71 @@ public final Arity getArity() {
return Arity.OPTIONAL;
}

@JRubyMethod(name = { "__new" }, meta = true, required = 3, optional = 1)
public static VariadicInvoker newInvoker(ThreadContext context, IRubyObject klass, IRubyObject[] args) {
@JRubyMethod(name = { "new" }, meta = true, required = 3, optional = 1)
public static VariadicInvoker newInstance(ThreadContext context, IRubyObject klass, IRubyObject[] args) {
// Get the convention from the options hash
String convention = "default";
IRubyObject enums = null;
boolean saveError = true;
IRubyObject typeMap = null;

if (args.length == 4) {
RubyHash options = (RubyHash) args[3];
IRubyObject rbConvention = options.fastARef(context.runtime.newSymbol("convention"));
if (rbConvention != null && !rbConvention.isNil()) {
convention = rbConvention.asJavaString();
}

IRubyObject rbSaveErrno = options.fastARef(context.runtime.newSymbol("save_errno"));
if (rbSaveErrno != null && !rbSaveErrno.isNil()) {
saveError = rbSaveErrno.isTrue();
}

enums = options.fastARef(context.runtime.newSymbol("enums"));
if (enums != null && !enums.isNil() && !(enums instanceof RubyHash || enums instanceof Enums)) {
throw context.runtime.newTypeError("wrong type for options[:enum] "
+ enums.getMetaClass().getName() + " (expected Hash or Enums)");

}
typeMap = options.fastARef(context.runtime.newSymbol("type_map"));
if (typeMap != null && !typeMap.isNil() && !(typeMap instanceof RubyHash)) {
throw context.runtime.newTypeError("wrong type for options[:type_map] "
+ typeMap.getMetaClass().getName() + " (expected Hash)");

}
}

final Type returnType = org.jruby.ext.ffi.Util.findType(context, args[0], typeMap);

if (!(args[0] instanceof Pointer)) {
throw context.runtime.newTypeError(args[0], context.runtime.getFFI().pointerClass);
if (!(args[1] instanceof RubyArray)) {
throw context.runtime.newTypeError("Invalid parameter array "
+ args[1].getMetaClass().getName() + " (expected Array)");
}

final Pointer address = (Pointer) args[0];

if (!(args[1] instanceof Type)) {
throw context.runtime.newTypeError("invalid return type");
if (!(args[2] instanceof Pointer)) {
throw context.runtime.newTypeError(args[2], context.runtime.getFFI().pointerClass);
}
final Pointer address = (Pointer) args[2];

CallingConvention callConvention = "stdcall".equals(convention)
? CallingConvention.STDCALL : CallingConvention.DEFAULT;

RubyArray paramTypes = (RubyArray) args[1];
RubyArray fixed = RubyArray.newArray(context.runtime);
for (int i = 0; i < paramTypes.getLength(); ++i) {
Type type = (Type)paramTypes.entry(i);
if (type.getNativeType() != org.jruby.ext.ffi.NativeType.VARARGS)
fixed.append(type);
}

final Type returnType = (Type) args[1];
final CallingConvention conv = "stdcall".equals(args[2].toString())
? CallingConvention.STDCALL : CallingConvention.DEFAULT;

FunctionInvoker functionInvoker = DefaultMethodFactory.getFunctionInvoker(returnType);
return new VariadicInvoker(context.runtime, klass, address,
functionInvoker, FFIUtil.getFFIType(returnType), conv);

VariadicInvoker varInvoker = new VariadicInvoker(context.runtime, klass, address, functionInvoker, FFIUtil.getFFIType(returnType), callConvention, enums, saveError);

varInvoker.setInstanceVariable("@fixed", fixed);
varInvoker.setInstanceVariable("@type_map", typeMap);

return varInvoker;
}

@JRubyMethod(name = { "invoke" })
@@ -86,6 +137,7 @@ public IRubyObject invoke(ThreadContext context, IRubyObject typesArg, IRubyObje
IRubyObject[] params = ((RubyArray) paramsArg).toJavaArrayMaybeUnsafe();
com.kenai.jffi.Type[] ffiParamTypes = new com.kenai.jffi.Type[types.length];
ParameterMarshaller[] marshallers = new ParameterMarshaller[types.length];
RubyClass builtinClass = Type.getTypeClass(context.getRuntime()).getClass("Builtin");

for (int i = 0; i < types.length; ++i) {
Type type = (Type) types[i];
@@ -94,28 +146,28 @@ public IRubyObject invoke(ThreadContext context, IRubyObject typesArg, IRubyObje
case SHORT:
case INT:
ffiParamTypes[i] = com.kenai.jffi.Type.SINT32;
marshallers[i] = DefaultMethodFactory.getMarshaller(NativeType.INT);
marshallers[i] = DefaultMethodFactory.getMarshaller((Type)builtinClass.getConstant(NativeType.INT.name().toUpperCase(LOCALE)), convention, enums);
break;
case UCHAR:
case USHORT:
case UINT:
ffiParamTypes[i] = com.kenai.jffi.Type.UINT32;
marshallers[i] = DefaultMethodFactory.getMarshaller(NativeType.UINT);
marshallers[i] = DefaultMethodFactory.getMarshaller((Type)builtinClass.getConstant(NativeType.UINT.name().toUpperCase(LOCALE)), convention, enums);
break;
case FLOAT:
case DOUBLE:
ffiParamTypes[i] = com.kenai.jffi.Type.DOUBLE;
marshallers[i] = DefaultMethodFactory.getMarshaller(NativeType.DOUBLE);
marshallers[i] = DefaultMethodFactory.getMarshaller((Type)builtinClass.getConstant(NativeType.DOUBLE.name().toUpperCase(LOCALE)), convention, enums);
break;
default:
ffiParamTypes[i] = FFIUtil.getFFIType(type);
marshallers[i] = DefaultMethodFactory.getMarshaller((Type) types[i], CallingConvention.DEFAULT, null);
marshallers[i] = DefaultMethodFactory.getMarshaller((Type) types[i], convention, enums);
break;
}
}

Invocation invocation = new Invocation(context);
Function function = new Function(address.getAddress(), returnType, ffiParamTypes, convention);
Function function = new Function(address.getAddress(), returnType, ffiParamTypes, convention, saveError);
try {
HeapInvocationBuffer args = new HeapInvocationBuffer(function);
for (int i = 0; i < marshallers.length; ++i) {
114 changes: 0 additions & 114 deletions core/src/main/java/org/jruby/runtime/load/CExtension.java

This file was deleted.

10 changes: 9 additions & 1 deletion core/src/main/java/org/jruby/runtime/load/LibrarySearcher.java
Original file line number Diff line number Diff line change
@@ -60,10 +60,18 @@ public FoundLibrary findBySearchState(LoadService.SearchState state) {
}

public FoundLibrary findLibrary(String baseName, SuffixType suffixType) {
boolean searchedForServiceLibrary = false;

for (String suffix : suffixType.getSuffixes()) {
FoundLibrary library = findBuiltinLibrary(baseName, suffix);
if (library == null) library = findResourceLibrary(baseName, suffix);
if (library == null) library = findServiceLibrary(baseName, suffix);

// Since searching for a service library doesn't take the suffix into account, there's no need
// to perform it more than once.
if ((library == null) && (searchedForServiceLibrary == false)) {
library = findServiceLibrary(baseName, suffix);
searchedForServiceLibrary = true;
}

if (library != null) {
return library;
Original file line number Diff line number Diff line change
@@ -170,15 +170,15 @@ private static void methodData1(final IntHashMap<MethodData> methods, Invocation
}
}

private static final String PROFILER_START_METHOD = "JRuby::ProfilingService.start";
private static final String PROFILER_STOP_METHOD = "JRuby::ProfilingService.stop";
private static final String PROFILER_START_METHOD = "JRuby::Profiler.start";
private static final String PROFILER_STOP_METHOD = "JRuby::Profiler.stop";

/*
* Here to keep these in one place if the hash format gets updated
* @see ProfileData#computeResults()
*/
static final String PROFILER_PROFILE_METHOD = "JRuby::ProfilingService.profile";
static final String PROFILER_PROFILED_CODE_METHOD = "JRuby::ProfilingService.profiled_code";
static final String PROFILER_PROFILE_METHOD = "JRuby::Profiler.profile";
static final String PROFILER_PROFILED_CODE_METHOD = "JRuby::Profiler.profiled_code";

private static String moduleHashMethod(RubyModule module, String name) {
if (module instanceof MetaClass) {
44 changes: 44 additions & 0 deletions core/src/main/java/org/jruby/truffle/nodes/core/EncodingNodes.java
Original file line number Diff line number Diff line change
@@ -79,6 +79,50 @@ public RubyEncoding defaultInternal() {

}

@CoreMethod(names = "default_external=", onSingleton = true, required = 1)
public abstract static class SetDefaultExternalNode extends CoreMethodNode {

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

public SetDefaultExternalNode(SetDefaultExternalNode prev) {
super(prev);
}

@Specialization
public RubyEncoding defaultExternal(RubyEncoding encoding) {
notDesignedForCompilation();

getContext().getRuntime().setDefaultExternalEncoding(encoding.getEncoding());

return encoding;
}

}

@CoreMethod(names = "default_internal=", onSingleton = true, required = 1)
public abstract static class SetDefaultInternalNode extends CoreMethodNode {

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

public SetDefaultInternalNode(SetDefaultInternalNode prev) {
super(prev);
}

@Specialization
public RubyEncoding defaultExternal(RubyEncoding encoding) {
notDesignedForCompilation();

getContext().getRuntime().setDefaultInternalEncoding(encoding.getEncoding());

return encoding;
}

}

@CoreMethod(names = "find", onSingleton = true, required = 1)
public abstract static class FindNode extends CoreMethodNode {

Original file line number Diff line number Diff line change
@@ -17,6 +17,59 @@
@CoreClass(name = "FalseClass")
public abstract class FalseClassNodes {

@CoreMethod(names = "&", needsSelf = false, required = 1)
public abstract static class AndNode extends CoreMethodNode {

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

public AndNode(AndNode prev) {
super(prev);
}

@Specialization
public boolean and(boolean other) {
return false;
}

@Specialization
public boolean and(RubyObject other) {
return false;
}
}

@CoreMethod(names = "|", needsSelf = false, required = 1)
public abstract static class OrNode extends CoreMethodNode {

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

public OrNode(OrNode prev) {
super(prev);
}

@Specialization
public boolean or(boolean other) {
return other;
}

@Specialization
public boolean or(RubyNilClass other) {
return false;
}

@Specialization(guards = "isNotNil")
public boolean or(RubyObject other) {
return true;
}

static boolean isNotNil(RubyObject o) {
return ! (o instanceof RubyNilClass);
}
}

@CoreMethod(names = "^", needsSelf = false, required = 1)
public abstract static class XorNode extends CoreMethodNode {

@@ -33,6 +86,20 @@ public boolean xor(boolean other) {
return false ^ other;
}

@Specialization
public boolean xor(RubyNilClass other) {
return false;
}

@Specialization(guards = "isNotNil")
public boolean xor(RubyObject other) {
return true;
}

static boolean isNotNil(RubyObject o) {
return ! (o instanceof RubyNilClass);
}

}

@CoreMethod(names = {"to_s", "inspect"}, needsSelf = false)
Original file line number Diff line number Diff line change
@@ -17,6 +17,59 @@
@CoreClass(name = "TrueClass")
public abstract class TrueClassNodes {

@CoreMethod(names = "&", needsSelf = false, required = 1)
public abstract static class AndNode extends CoreMethodNode {

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

public AndNode(AndNode prev) {
super(prev);
}

@Specialization
public boolean and(boolean other) {
return other;
}

@Specialization
public boolean and(RubyNilClass other) {
return false;
}

@Specialization(guards = "isNotNil")
public boolean and(RubyObject other) {
return true;
}

static boolean isNotNil(RubyObject o) {
return ! (o instanceof RubyNilClass);
}
}

@CoreMethod(names = "|", needsSelf = false, required = 1)
public abstract static class OrNode extends CoreMethodNode {

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

public OrNode(OrNode prev) {
super(prev);
}

@Specialization
public boolean or(boolean other) {
return true;
}

@Specialization
public boolean or(RubyObject other) {
return true;
}
}

@CoreMethod(names = "^", needsSelf = false, required = 1)
public abstract static class XorNode extends CoreMethodNode {

Original file line number Diff line number Diff line change
@@ -202,6 +202,7 @@ public void initialize() {
// Includes

objectClass.include(null, kernelModule);
numericClass.include(null, comparableModule);

// Set constants

@@ -290,8 +291,8 @@ public void initializeAfterMethodsAdded() {
globalVariablesObject.setInstanceVariable("$stdout", stdout);

objectClass.setConstant(null, "STDIN", new RubyBasicObject(objectClass));
objectClass.setConstant(null, "STDOUT", globalVariablesObject.getInstanceVariable("$stdout"));
objectClass.setConstant(null, "STDERR", globalVariablesObject.getInstanceVariable("$stdout"));
objectClass.setConstant(null, "STDOUT", stdout);
objectClass.setConstant(null, "STDERR", stdout);
objectClass.setConstant(null, "RUBY_RELEASE_DATE", context.makeString(Constants.COMPILE_DATE));
objectClass.setConstant(null, "RUBY_DESCRIPTION", context.makeString(OutputStrings.getVersionString()));

@@ -327,6 +328,7 @@ public void initializeEncodingConstants() {
encodingClass.setConstant(null, "EUC_JP", RubyEncoding.getEncoding(context, EUCJPEncoding.INSTANCE));
encodingClass.setConstant(null, "Windows_31J", RubyEncoding.getEncoding(context, SJISEncoding.INSTANCE));
encodingClass.setConstant(null, "Big5", RubyEncoding.getEncoding(context, BIG5Encoding.INSTANCE));
encodingClass.setConstant(null, "IBM437", RubyEncoding.getEncoding(context, USASCIIEncoding.INSTANCE));

}

2 changes: 2 additions & 0 deletions core/src/main/java/org/jruby/util/JarResource.java
Original file line number Diff line number Diff line change
@@ -31,6 +31,8 @@ public static JarResource create(String pathname) {
int bang = sanitized.indexOf('!');
String jarPath = sanitized.substring(0, bang);
String entryPath = sanitized.substring(bang + 1);
// normalize path -- issue #2017
if (entryPath.startsWith("//")) entryPath = entryPath.substring(1);

// TODO: Do we really need to support both test.jar!foo/bar.rb and test.jar!/foo/bar.rb cases?
JarResource resource = createJarResource(jarPath, entryPath, false);
20 changes: 14 additions & 6 deletions core/src/main/java/org/jruby/util/ShellLauncher.java
Original file line number Diff line number Diff line change
@@ -1198,12 +1198,20 @@ public void verifyExecutableForShell() {
}

public void verifyExecutableForDirect() {
verifyExecutable();
execArgs = args;
try {
execArgs[0] = executableFile.getCanonicalPath();
} catch (IOException ioe) {
// can't get the canonical path, will use as-is
if (isCmdBuiltin(args[0].trim())) {
execArgs = new String[args.length + 2];
execArgs[0] = shell;
execArgs[1] = "/c";
execArgs[2] = args[0].trim();
System.arraycopy(args, 1, execArgs, 3, args.length - 1);
} else {
verifyExecutable();
execArgs = args;
try {
execArgs[0] = executableFile.getCanonicalPath();
} catch (IOException ioe) {
// can't get the canonical path, will use as-is
}
}
}

110 changes: 65 additions & 45 deletions core/src/main/java/org/jruby/util/SipHashInline.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
package org.jruby.util;

import java.nio.ByteOrder;

import org.jruby.util.unsafe.UnsafeHolder;

import sun.misc.Unsafe;

/**
* SipHash implementation with hand inlining the SIPROUND.
*
@@ -23,17 +29,16 @@ public static long hash24(long k0, long k1, byte[] src, int offset, int length)
int last = offset + length / 8 * 8;
int i = offset;

if (offset < 0) {
throw new ArrayIndexOutOfBoundsException(offset);
} else if (offset + length > src.length) {
throw new ArrayIndexOutOfBoundsException(src.length);
}

// processing 8 bytes blocks in data
while (i < last) {
// pack a block to long, as LE 8 bytes
m = (long) src[i++] |
(long) src[i++] << 8 |
(long) src[i++] << 16 |
(long) src[i++] << 24 |
(long) src[i++] << 32 |
(long) src[i++] << 40 |
(long) src[i++] << 48 |
(long) src[i++] << 56 ;
m = LongReader.INSTANCE.getLong(src, i);
i += 8;
// MSGROUND {
v3 ^= m;

@@ -110,6 +115,7 @@ public static long hash24(long k0, long k1, byte[] src, int offset, int length)
m |= (long) length << 56;
// MSGROUND {
v3 ^= m;
for (int j = 0; j < 2; j++) {
// SIPROUND {
v0 += v1; v2 += v3;
v1 = (v1 << 13) | v1 >>> 51; v3 = (v3 << 16) | v3 >>> 48;
@@ -119,20 +125,13 @@ public static long hash24(long k0, long k1, byte[] src, int offset, int length)
v3 = (v3 << 21) | v3 >>> 43; v1 ^= v2;
v3 ^= v0; v2 = (v2 << 32) | v2 >>> 32;
// }
// SIPROUND {
v0 += v1; v2 += v3;
v1 = (v1 << 13) | v1 >>> 51; v3 = (v3 << 16) | v3 >>> 48;
v1 ^= v0; v3 ^= v2;
v0 = (v0 << 32) | v0 >>> 32; v2 += v1;
v0 += v3; v1 = (v1 << 17) | v1 >>> 47;
v3 = (v3 << 21) | v3 >>> 43; v1 ^= v2;
v3 ^= v0; v2 = (v2 << 32) | v2 >>> 32;
// }
}
v0 ^= m;
// }

// finishing...
v2 ^= 0xff;
for (int j = 0; j < 4; j++) {
// SIPROUND {
v0 += v1; v2 += v3;
v1 = (v1 << 13) | v1 >>> 51; v3 = (v3 << 16) | v3 >>> 48;
@@ -142,33 +141,54 @@ public static long hash24(long k0, long k1, byte[] src, int offset, int length)
v3 = (v3 << 21) | v3 >>> 43; v1 ^= v2;
v3 ^= v0; v2 = (v2 << 32) | v2 >>> 32;
// }
// SIPROUND {
v0 += v1; v2 += v3;
v1 = (v1 << 13) | v1 >>> 51; v3 = (v3 << 16) | v3 >>> 48;
v1 ^= v0; v3 ^= v2;
v0 = (v0 << 32) | v0 >>> 32; v2 += v1;
v0 += v3; v1 = (v1 << 17) | v1 >>> 47;
v3 = (v3 << 21) | v3 >>> 43; v1 ^= v2;
v3 ^= v0; v2 = (v2 << 32) | v2 >>> 32;
// }
// SIPROUND {
v0 += v1; v2 += v3;
v1 = (v1 << 13) | v1 >>> 51; v3 = (v3 << 16) | v3 >>> 48;
v1 ^= v0; v3 ^= v2;
v0 = (v0 << 32) | v0 >>> 32; v2 += v1;
v0 += v3; v1 = (v1 << 17) | v1 >>> 47;
v3 = (v3 << 21) | v3 >>> 43; v1 ^= v2;
v3 ^= v0; v2 = (v2 << 32) | v2 >>> 32;
// }
// SIPROUND {
v0 += v1; v2 += v3;
v1 = (v1 << 13) | v1 >>> 51; v3 = (v3 << 16) | v3 >>> 48;
v1 ^= v0; v3 ^= v2;
v0 = (v0 << 32) | v0 >>> 32; v2 += v1;
v0 += v3; v1 = (v1 << 17) | v1 >>> 47;
v3 = (v3 << 21) | v3 >>> 43; v1 ^= v2;
v3 ^= v0; v2 = (v2 << 32) | v2 >>> 32;
// }
}
return v0 ^ v1 ^ v2 ^ v3;
}

private static abstract class LongReader {
public abstract long getLong(byte[] src, int offset);

public static final LongReader INSTANCE = createBestLongReader();

private static LongReader createBestLongReader() {
try {
if (UnsafeHolder.U != null) {
if (ByteOrder.nativeOrder() == ByteOrder.LITTLE_ENDIAN) {
return new UnsafeLongReader(UnsafeHolder.U);
}
}
} catch (Exception e) {
}
return new FallbackLongReader();
}

private static final class FallbackLongReader extends LongReader {
@Override
public long getLong(byte[] src, int offset) {
return (long) src[offset++] |
(long) src[offset++] << 8 |
(long) src[offset++] << 16 |
(long) src[offset++] << 24 |
(long) src[offset++] << 32 |
(long) src[offset++] << 40 |
(long) src[offset++] << 48 |
(long) src[offset++] << 56 ;
}
}

private static final class UnsafeLongReader extends LongReader {
final Unsafe unsafe;
final int byteArrayBaseOffset;

public UnsafeLongReader(Unsafe unsafe) {
this.unsafe = unsafe;
this.byteArrayBaseOffset = unsafe.arrayBaseOffset(byte[].class);
}

@Override
public final long getLong(byte[] src, int offset) {
return unsafe.getLong(src, byteArrayBaseOffset + (long)offset);
}
}
}
}
2 changes: 0 additions & 2 deletions core/src/main/java/org/jruby/util/cli/Options.java
Original file line number Diff line number Diff line change
@@ -252,8 +252,6 @@ public static String dump() {

// After PROPERTIES so it doesn't show up in --properties
@Deprecated
public static final Option<Boolean> CEXT_ENABLED = bool(NATIVE, "cext.enabled", false, "Enable or disable C extension support.");
@Deprecated
public static final Option<Boolean> JIT_CACHE = bool(JIT, "jit.cache", !COMPILE_INVOKEDYNAMIC.load(), "(DEPRECATED) Cache jitted method in-memory bodies across runtimes and loads.");

private static Option<String> string(Category category, String name, String[] options, String defval, String description) {
1 change: 1 addition & 0 deletions core/src/main/ruby/jruby/java/core_ext/object.rb
Original file line number Diff line number Diff line change
@@ -31,6 +31,7 @@ def java_import(*import_classes)
raise ArgumentError.new "not a valid Java identifier: #{import_class}"
end
# pull in the class
raise ArgumentError.new "must use jvm-style name: #{import_class}" if import_class.include? "::"
import_class = JavaUtilities.get_proxy_class(import_class)
when Module
if import_class.respond_to? "java_class"
4 changes: 4 additions & 0 deletions core/src/main/ruby/jruby/truffle/core/kernel.rb
Original file line number Diff line number Diff line change
@@ -35,6 +35,10 @@ def puts(*args)

end

def STDOUT.internal_encoding
nil # FIXME
end

# Here temporarily while we adapt to the newly imported specs

class Channel
59 changes: 59 additions & 0 deletions core/src/test/java/org/jruby/lexer/yacc/StringTermTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package org.jruby.lexer.yacc;

import org.jruby.CompatVersion;
import org.jruby.Ruby;
import org.jruby.RubyInstanceConfig;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.util.KCode;

import junit.framework.TestCase;

public class StringTermTest extends TestCase {

/**
* @see https://github.com/jruby/jruby/issues/1069
*/
public void testGH1069() {
final String testScriptUsingSingleQuote = "# encoding: utf-8\n'\\’'";
final String testScriptUsingDoubleQuote = "# encoding: utf-8\n\"\\’\"";

CompatVersion[] versions = new CompatVersion[] { CompatVersion.RUBY1_8,
CompatVersion.RUBY1_9, CompatVersion.RUBY2_0 };

for (CompatVersion v : versions) {
RubyInstanceConfig config = new RubyInstanceConfig();
config.setCompatVersion(v);
Ruby runtime = Ruby.newInstance(config);

IRubyObject eval1 = runtime.evalScriptlet(testScriptUsingSingleQuote);
assertEquals("\\’", eval1.toJava(String.class));

IRubyObject eval2 = runtime.evalScriptlet(testScriptUsingDoubleQuote);
assertEquals("’", eval2.toJava(String.class));
}
}

/**
* @see https://github.com/jruby/jruby/issues/1390
*/
public void testGH1390() {
final String testScriptUsingSingleQuote = "# encoding: utf-8\n'\\\\あ'";
final String testScriptUsingDoubleQuote = "# encoding: utf-8\n\"\\\\\"";

CompatVersion[] versions = new CompatVersion[] { CompatVersion.RUBY1_8,
CompatVersion.RUBY1_9, CompatVersion.RUBY2_0 };

for (CompatVersion v : versions) {
RubyInstanceConfig config = new RubyInstanceConfig();
config.setCompatVersion(v);
Ruby runtime = Ruby.newInstance(config);

IRubyObject eval1 = runtime.evalScriptlet(testScriptUsingSingleQuote);
assertEquals("\\あ", eval1.toJava(String.class));

IRubyObject eval2 = runtime.evalScriptlet(testScriptUsingDoubleQuote);
assertEquals("\\あ", eval2.toJava(String.class));
}
}

}
34 changes: 21 additions & 13 deletions core/src/test/java/org/jruby/test/TestRubyException.java
Original file line number Diff line number Diff line change
@@ -27,18 +27,17 @@
***** END LICENSE BLOCK *****/
package org.jruby.test;

import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.List;

import junit.framework.TestCase;

import org.jruby.Ruby;
import org.jruby.RubyArray;
import org.jruby.RubyException;
import org.jruby.RubyString;

import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.List;

public class TestRubyException extends TestCase {

private Ruby interpreter;
@@ -53,29 +52,38 @@ public void testPrintBacktrace() throws Exception {
setBackTrace(18);

String[] lines = printError();
assertEquals(expectedTraceLine(1), lines[0]);
assertEquals(expectedTraceLine(RubyException.TRACE_HEAD + 1), lines[RubyException.TRACE_HEAD]);

assertEquals(expectedTraceLine(0), lines[0]);
assertEquals(expectedTraceLine(RubyException.TRACE_HEAD), lines[RubyException.TRACE_HEAD]);
}

public void testPrintNilBacktrace() throws Exception {
exception.set_backtrace(interpreter.getNil());
exception.set_backtrace(interpreter.getNil());

String[] lines = printError();

assertEquals(0, lines.length);
}

public void testPrintBackTraceWithString() throws Exception {
exception.set_backtrace(RubyArray.newArray(interpreter, RubyString.newString(interpreter, testLine(0))));

String[] lines = printError();

assertEquals(1, lines.length);
assertEquals(expectedTraceLine(0), lines[0]);
}

private String[] printError() {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(2048);
PrintStream stream = new PrintStream(byteArrayOutputStream);
exception.printBacktrace(stream, 1);
exception.printBacktrace(stream);
String output = new String(byteArrayOutputStream.toByteArray());
if (output.trim().length() == 0) {
return new String[0];
} else {
} else {
return output.split("\n");
}
}
}

private void setBackTrace(int lineCount) {
2 changes: 1 addition & 1 deletion lib/ruby/stdlib/ffi/library.rb
Original file line number Diff line number Diff line change
@@ -228,7 +228,7 @@ def attach_function(name, func, args, returns = nil, options = nil)
raise LoadError unless function

invokers << if arg_types.length > 0 && arg_types[arg_types.length - 1] == FFI::NativeType::VARARGS
FFI::VariadicInvoker.new(arg_types, find_type(ret_type), function, options)
FFI::VariadicInvoker.new(find_type(ret_type), arg_types, function, options)
else
FFI::Function.new(find_type(ret_type), arg_types, function, options)
end
16 changes: 5 additions & 11 deletions lib/ruby/stdlib/ffi/variadic.rb
Original file line number Diff line number Diff line change
@@ -28,17 +28,11 @@

module FFI
class VariadicInvoker
def VariadicInvoker.new(arg_types, ret_type, function, options)
invoker = self.__new(function, ret_type, options[:convention].to_s)
invoker.init(arg_types, options[:type_map])
invoker
end

def init(arg_types, type_map)
@fixed = Array.new
@type_map = type_map
arg_types.each_with_index do |type, i|
@fixed << FFI.find_type(type, @type_map) unless type == FFI::NativeType::VARARGS
@fixed << type unless type == FFI::NativeType::VARARGS
end
end

@@ -57,10 +51,10 @@ def call(*args, &block)
invoke(param_types, param_values, &block)
end

#
# Attach the invoker to module +mod+ as +mname+
#
def attach(mod, mname)
#
# Attach the invoker to this module as 'mname'.
#
invoker = self
params = "*args"
call = "call"
@@ -76,4 +70,4 @@ def #{mname}(#{params})
invoker
end
end
end
end
12 changes: 12 additions & 0 deletions lib/ruby/stdlib/rexml/rexml.rb
Original file line number Diff line number Diff line change
@@ -28,4 +28,16 @@ module REXML

Copyright = COPYRIGHT
Version = VERSION

@@entity_expansion_text_limit = 10_240

# Set the entity expansion limit. By default the limit is set to 10240.
def self.entity_expansion_text_limit=( val )
@@entity_expansion_text_limit = val
end

# Get the entity expansion limit. By default the limit is set to 10240.
def self.entity_expansion_text_limit
return @@entity_expansion_text_limit
end
end
7 changes: 6 additions & 1 deletion maven/jruby-complete/pom.rb
Original file line number Diff line number Diff line change
@@ -19,7 +19,12 @@
end

scope :provided do
jar 'org.jruby:jruby-core:${project.version}'
jar( 'org.jruby:jruby-core:${project.version}:noasm',
:exclusions => [ 'com.github.jnr:jnr-ffi',
'org.ow2.asm:asm',
'org.ow2.asm:asm-commons',
'org.ow2.asm:asm-analysis',
'org.ow2.asm:asm-util' ] )
jar 'org.jruby:jruby-stdlib:${project.version}'
end

23 changes: 23 additions & 0 deletions maven/jruby-complete/pom.xml
Original file line number Diff line number Diff line change
@@ -22,7 +22,30 @@
<groupId>org.jruby</groupId>
<artifactId>jruby-core</artifactId>
<version>${project.version}</version>
<classifier>noasm</classifier>
<scope>provided</scope>
<exclusions>
<exclusion>
<artifactId>jnr-ffi</artifactId>
<groupId>com.github.jnr</groupId>
</exclusion>
<exclusion>
<artifactId>asm</artifactId>
<groupId>org.ow2.asm</groupId>
</exclusion>
<exclusion>
<artifactId>asm-commons</artifactId>
<groupId>org.ow2.asm</groupId>
</exclusion>
<exclusion>
<artifactId>asm-analysis</artifactId>
<groupId>org.ow2.asm</groupId>
</exclusion>
<exclusion>
<artifactId>asm-util</artifactId>
<groupId>org.ow2.asm</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.jruby</groupId>
2 changes: 1 addition & 1 deletion maven/jruby-dist/src/it/integrity/verify.bsh
Original file line number Diff line number Diff line change
@@ -37,4 +37,4 @@ expected = "ffi,jar-dependencies,jruby-openssl,krypt,krypt-core,krypt-provider-j
if ( !log.contains( expected ) )
{
throw new RuntimeException( "log file does not contain '" + expected + "'" );
}
}
3 changes: 3 additions & 0 deletions maven/jruby-jars/src/it/extended/invoker.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
invoker.goals = install
invoker.mavenOpts = -client

10 changes: 10 additions & 0 deletions maven/jruby-jars/src/it/extended/pom.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# jruby scripting container
jar 'org.jruby:jruby-core', '@project.version@'
jar 'org.jruby:jruby-stdlib', '@project.version@'

# unit tests
jar 'junit:junit', '4.8.2', :scope => :test

properties 'tesla.dump.pom' => 'pom.xml', 'tesla.dump.readOnly' => true

plugin :surefire, '2.15', :additionalClasspathElements => [ '${basedir}/../../../../../core/target/test-classes', '${basedir}/../../../../../test/target/test-classes' ]
45 changes: 45 additions & 0 deletions maven/jruby-jars/src/it/extended/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<groupId>no_group_id_given</groupId>
<artifactId>extended</artifactId>
<version>0.0.0</version>
<name>extended</name>
<properties>
<tesla.dump.readOnly>true</tesla.dump.readOnly>
<tesla.dump.pom>pom.xml</tesla.dump.pom>
</properties>
<dependencies>
<dependency>
<groupId>org.jruby</groupId>
<artifactId>jruby-core</artifactId>
<version>@project.version@</version>
</dependency>
<dependency>
<groupId>org.jruby</groupId>
<artifactId>jruby-stdlib</artifactId>
<version>@project.version@</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.8.2</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.15</version>
<configuration>
<additionalClasspathElements>
<additionalClasspathElement>${basedir}/../../../../../core/target/test-classes</additionalClasspathElement>
<additionalClasspathElement>${basedir}/../../../../../test/target/test-classes</additionalClasspathElement>
</additionalClasspathElements>
</configuration>
</plugin>
</plugins>
</build>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
package org.example;

import static org.junit.Assert.assertEquals;

import java.util.Arrays;
import java.io.File;
import java.io.StringWriter;

import org.jruby.embed.LocalContextScope;
import org.jruby.embed.ScriptingContainer;

import org.junit.Before;
import org.junit.Test;

public class SimpleTest {

private final String basedir = new File( "../../../../../" ).getAbsolutePath();

private ScriptingContainer newScriptingContainer() {
ScriptingContainer container = new ScriptingContainer(LocalContextScope.SINGLETHREAD);
container.setCurrentDirectory(basedir);
container.getProvider().getRubyInstanceConfig().setJRubyHome("uri:classloader://META-INF/jruby.home");
container.getProvider().getRubyInstanceConfig().setLoadPaths(Arrays.asList(".", "test", "test/mri", "test/mri/ruby"));
container.runScriptlet("ENV['GEM_PATH']='lib/ruby/gems/shared'");
return container;
}

private void runTests(ScriptingContainer container) throws Exception {
container.getProvider().getRuntime().tearDown(true);
container.terminate();
}

private void collectTests(ScriptingContainer container, String index) throws Exception {
container.runScriptlet("File.open(File.join('test', '" + index + ".index')) do |f|\n" +
" f.each_line.each do |line|\n" +
" next if line =~ /^#/ or line.strip.empty?\n" +
" filename = \"test/mri/#{line.chomp}\"\n" +
" filename = \"test/jruby/#{line.chomp}.rb\" unless File.exist? filename\n" +
" filename = \"test/#{line.chomp}.rb\" unless File.exist? filename\n" +
" next unless File.file? filename\n" +
" next if filename =~ /mri\\/net\\/http\\//\n" +
" next if filename =~ /mri\\/ruby\\/test_class/\n" +
" next if filename =~ /mri\\/ruby\\/test_io/\n" +
" next if filename =~ /mri\\/ruby\\/test_econv/\n" +
" next if filename =~ /nru\\/test_open3/\n" +
// TODO file an issue or so
" next if filename =~ /test_load_compiled_ruby.rb/\n" +
// TODO remove the following after fix of #2215
" next if filename =~ /test_jar_on_load_path.rb/\n" +
" next if filename =~ /test_file.rb/\n" +
" filename.sub!( /.*\\/test\\//, 'test/' )\n" +
" puts filename\n" +
" require filename\n" +
" end\n" +
" end");
}

private void runIt(String index) throws Exception {
runIt(index, null);
}

private void runIt(String index, String script) throws Exception {
ClassLoader cl = Thread.currentThread().getContextClassLoader();
try {
//Thread.currentThread().setContextClassLoader();
System.err.println("\n\nrunning --------- " + index + "\n");
ScriptingContainer container = newScriptingContainer();
if (script != null) container.runScriptlet( script );
if (index != null) collectTests(container, index);
runTests(container);
}
finally {
Thread.currentThread().setContextClassLoader(cl);
}
}

@Test
public void testObjectspace() throws Exception {
runIt("objectspace");
}

@Test
public void testSlow() throws Exception {
runIt("slow");
}

@Test
public void testMRI() throws Exception {
runIt("mri", "ENV['EXCLUDE_DIR']='test/mri/excludes';");
}

@Test
public void testJRuby() throws Exception {
runIt("jruby");
}

// @Test
// public void test() throws Exception {
// runIt(null, "require 'test/test_load_compiled_ruby.rb'");
// }

}
2 changes: 1 addition & 1 deletion maven/jruby-jars/src/it/integrity/verify.bsh
Original file line number Diff line number Diff line change
@@ -37,4 +37,4 @@ expected = "ffi,jar-dependencies,jruby-openssl,krypt,krypt-core,krypt-provider-j
if ( !log.contains( expected ) )
{
throw new RuntimeException( "log file does not contain '" + expected + "'" );
}
}
2 changes: 1 addition & 1 deletion maven/jruby-noasm/src/it/integrity/verify.bsh
Original file line number Diff line number Diff line change
@@ -37,4 +37,4 @@ expected = "ffi,jar-dependencies,jruby-openssl,krypt,krypt-core,krypt-provider-j
if ( !log.contains( expected ) )
{
throw new RuntimeException( "log file does not contain '" + expected + "'" );
}
}
8 changes: 1 addition & 7 deletions maven/jruby/pom.rb
Original file line number Diff line number Diff line change
@@ -54,13 +54,7 @@
activation do
jdk '1.8'
end
plugin :invoker, :pomExcludes => ['osgi_all_inclusive_felix-3.2/pom.xml', '${its.j2ee}', '${its.osgi}']
end
profile :id => :jdk6 do
activation do
jdk '1.6'
end
plugin :invoker, :pomExcludes => [ '${its.j2ee}', '${its.osgi}' ]
plugin :invoker, :pomExcludes => ['extended/pom.xml', 'osgi_all_inclusive_felix-3.2/pom.xml', '${its.j2ee}', '${its.osgi}']
end

profile :id => :wlp do
20 changes: 1 addition & 19 deletions maven/jruby/pom.xml
Original file line number Diff line number Diff line change
@@ -104,6 +104,7 @@
<artifactId>maven-invoker-plugin</artifactId>
<configuration>
<pomExcludes>
<pomExclude>extended/pom.xml</pomExclude>
<pomExclude>osgi_all_inclusive_felix-3.2/pom.xml</pomExclude>
<pomExclude>${its.j2ee}</pomExclude>
<pomExclude>${its.osgi}</pomExclude>
@@ -113,25 +114,6 @@
</plugins>
</build>
</profile>
<profile>
<id>jdk6</id>
<activation>
<jdk>1.6</jdk>
</activation>
<build>
<plugins>
<plugin>
<artifactId>maven-invoker-plugin</artifactId>
<configuration>
<pomExcludes>
<pomExclude>${its.j2ee}</pomExclude>
<pomExclude>${its.osgi}</pomExclude>
</pomExcludes>
</configuration>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>wlp</id>
<activation>
3 changes: 3 additions & 0 deletions maven/jruby/src/it/extended/invoker.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
invoker.goals = install
invoker.mavenOpts = -client

9 changes: 9 additions & 0 deletions maven/jruby/src/it/extended/pom.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# jruby scripting container
pom 'org.jruby:jruby', '@project.version@'

# unit tests
jar 'junit:junit', '4.8.2', :scope => :test

properties 'tesla.dump.pom' => 'pom.xml', 'tesla.dump.readOnly' => true

plugin :surefire, '2.15', :additionalClasspathElements => [ '${basedir}/../../../../../core/target/test-classes', '${basedir}/../../../../../test/target/test-classes' ]
41 changes: 41 additions & 0 deletions maven/jruby/src/it/extended/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<groupId>no_group_id_given</groupId>
<artifactId>extended</artifactId>
<version>0.0.0</version>
<name>extended</name>
<properties>
<tesla.dump.readOnly>true</tesla.dump.readOnly>
<tesla.dump.pom>pom.xml</tesla.dump.pom>
</properties>
<dependencies>
<dependency>
<groupId>org.jruby</groupId>
<artifactId>jruby</artifactId>
<version>@project.version@</version>
<type>pom</type>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.8.2</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.15</version>
<configuration>
<additionalClasspathElements>
<additionalClasspathElement>${basedir}/../../../../../core/target/test-classes</additionalClasspathElement>
<additionalClasspathElement>${basedir}/../../../../../test/target/test-classes</additionalClasspathElement>
</additionalClasspathElements>
</configuration>
</plugin>
</plugins>
</build>
</project>
102 changes: 102 additions & 0 deletions maven/jruby/src/it/extended/src/test/java/org/example/SimpleTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
package org.example;

import static org.junit.Assert.assertEquals;

import java.util.Arrays;
import java.io.File;
import java.io.StringWriter;

import org.jruby.embed.LocalContextScope;
import org.jruby.embed.ScriptingContainer;

import org.junit.Before;
import org.junit.Test;

public class SimpleTest {

private final String basedir = new File( "../../../../../" ).getAbsolutePath();

private ScriptingContainer newScriptingContainer() {
ScriptingContainer container = new ScriptingContainer(LocalContextScope.SINGLETHREAD);
container.setCurrentDirectory(basedir);
container.getProvider().getRubyInstanceConfig().setJRubyHome("uri:classloader://META-INF/jruby.home");
container.getProvider().getRubyInstanceConfig().setLoadPaths(Arrays.asList(".", "test", "test/mri", "test/mri/ruby"));
container.runScriptlet("ENV['GEM_PATH']='lib/ruby/gems/shared'");
return container;
}

private void runTests(ScriptingContainer container) throws Exception {
container.getProvider().getRuntime().tearDown(true);
container.terminate();
}

private void collectTests(ScriptingContainer container, String index) throws Exception {
container.runScriptlet("File.open(File.join('test', '" + index + ".index')) do |f|\n" +
" f.each_line.each do |line|\n" +
" next if line =~ /^#/ or line.strip.empty?\n" +
" filename = \"test/mri/#{line.chomp}\"\n" +
" filename = \"test/jruby/#{line.chomp}.rb\" unless File.exist? filename\n" +
" filename = \"test/#{line.chomp}.rb\" unless File.exist? filename\n" +
" next unless File.file? filename\n" +
" next if filename =~ /mri\\/net\\/http\\//\n" +
" next if filename =~ /mri\\/ruby\\/test_class/\n" +
" next if filename =~ /mri\\/ruby\\/test_io/\n" +
" next if filename =~ /mri\\/ruby\\/test_econv/\n" +
" next if filename =~ /nru\\/test_open3/\n" +
// TODO file an issue or so
" next if filename =~ /test_load_compiled_ruby.rb/\n" +
// TODO remove the following after fix of #2215
" next if filename =~ /test_jar_on_load_path.rb/\n" +
" next if filename =~ /test_file.rb/\n" +
" filename.sub!( /.*\\/test\\//, 'test/' )\n" +
" puts filename\n" +
" require filename\n" +
" end\n" +
" end");
}

private void runIt(String index) throws Exception {
runIt(index, null);
}

private void runIt(String index, String script) throws Exception {
ClassLoader cl = Thread.currentThread().getContextClassLoader();
try {
//Thread.currentThread().setContextClassLoader();
System.err.println("\n\nrunning --------- " + index + "\n");
ScriptingContainer container = newScriptingContainer();
if (script != null) container.runScriptlet( script );
if (index != null) collectTests(container, index);
runTests(container);
}
finally {
Thread.currentThread().setContextClassLoader(cl);
}
}

@Test
public void testObjectspace() throws Exception {
runIt("objectspace");
}

@Test
public void testSlow() throws Exception {
runIt("slow");
}

@Test
public void testMRI() throws Exception {
runIt("mri", "ENV['EXCLUDE_DIR']='test/mri/excludes';");
}

@Test
public void testJRuby() throws Exception {
runIt("jruby");
}

// @Test
// public void test() throws Exception {
// runIt(null, "require 'test/test_load_compiled_ruby.rb'");
// }

}
14 changes: 11 additions & 3 deletions pom.rb
Original file line number Diff line number Diff line change
@@ -67,7 +67,7 @@
'jffi.version' => '1.2.7',
'rake.version' => '10.1.0',
'project.build.sourceEncoding' => 'utf-8',
'jruby-launcher.version' => '1.0.19',
'jruby-launcher.version' => '1.1.1',
'asm.version' => '5.0.3',
'rspec-expectations.version' => '2.14.0',
'base.javac.version' => '1.7',
@@ -85,7 +85,7 @@
'bouncy-castle.version' => '1.47',
'github.global.server' => 'github',
'main.basedir' => '${project.basedir}',
'joda.time.version' => '2.3',
'joda.time.version' => '2.5',
'test-unit.version' => '3.0.3',
'power_assert.version' => '0.1.4' )

@@ -137,7 +137,7 @@
'localRepositoryPath' => '${project.build.directory}/local-repo',
'properties' => { 'project.version' => '${project.version}' },
'pomIncludes' => [ '*/pom.xml' ],
'pomExcludes' => [ '${its.j2ee}', '${its.osgi}' ],
'pomExcludes' => [ 'extended/pom.xml', '${its.j2ee}', '${its.osgi}' ],
'projectsDirectory' => 'src/it',
'cloneProjectsTo' => '${project.build.directory}/it',
'preBuildHookScript' => 'setup.bsh',
@@ -184,6 +184,11 @@
end
end

profile 'test' do
properties 'invoker.skip' => false
modules [ 'test' ]
end

[ 'rake', 'exec', 'truffle-specs-language', 'truffle-specs-core', 'truffle-test-pe' ].each do |name|
profile name do

@@ -211,6 +216,9 @@

build do
default_goal 'install'
plugin_management do
plugin :surefire, '2.15', :skipTests => true
end
end
end
end
58 changes: 56 additions & 2 deletions pom.xml
Original file line number Diff line number Diff line change
@@ -119,7 +119,7 @@
<jffi.version>1.2.7</jffi.version>
<rake.version>10.1.0</rake.version>
<project.build.sourceEncoding>utf-8</project.build.sourceEncoding>
<jruby-launcher.version>1.0.19</jruby-launcher.version>
<jruby-launcher.version>1.1.1</jruby-launcher.version>
<rspec-expectations.version>2.14.0</rspec-expectations.version>
<asm.version>5.0.3</asm.version>
<its.osgi>osgi*/pom.xml</its.osgi>
@@ -140,7 +140,7 @@
<bouncy-castle.version>1.47</bouncy-castle.version>
<main.basedir>${project.basedir}</main.basedir>
<github.global.server>github</github.global.server>
<joda.time.version>2.3</joda.time.version>
<joda.time.version>2.5</joda.time.version>
</properties>
<dependencyManagement>
<dependencies>
@@ -315,6 +315,7 @@
<pomInclude>*/pom.xml</pomInclude>
</pomIncludes>
<pomExcludes>
<pomExclude>extended/pom.xml</pomExclude>
<pomExclude>${its.j2ee}</pomExclude>
<pomExclude>${its.osgi}</pomExclude>
</pomExcludes>
@@ -533,6 +534,15 @@
<module>ext</module>
</modules>
</profile>
<profile>
<id>test</id>
<modules>
<module>test</module>
</modules>
<properties>
<invoker.skip>false</invoker.skip>
</properties>
</profile>
<profile>
<id>rake</id>
<build>
@@ -594,6 +604,17 @@
<id>jruby-jars</id>
<build>
<defaultGoal>install</defaultGoal>
<pluginManagement>
<plugins>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.15</version>
<configuration>
<skipTests>true</skipTests>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
<modules>
<module>maven</module>
@@ -603,6 +624,17 @@
<id>main</id>
<build>
<defaultGoal>install</defaultGoal>
<pluginManagement>
<plugins>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.15</version>
<configuration>
<skipTests>true</skipTests>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
<modules>
<module>maven</module>
@@ -612,6 +644,17 @@
<id>complete</id>
<build>
<defaultGoal>install</defaultGoal>
<pluginManagement>
<plugins>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.15</version>
<configuration>
<skipTests>true</skipTests>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
<modules>
<module>maven</module>
@@ -621,6 +664,17 @@
<id>dist</id>
<build>
<defaultGoal>install</defaultGoal>
<pluginManagement>
<plugins>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.15</version>
<configuration>
<skipTests>true</skipTests>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
<modules>
<module>maven</module>
37 changes: 37 additions & 0 deletions spec/ffi/fixtures/VariadicTest.c
Original file line number Diff line number Diff line change
@@ -60,3 +60,40 @@ void pack_varargs(s64* buf, const char* fmt, ...)
va_end(ap);
}

int pack_varargs2(s64* buf, int retval, const char* fmt, ...)
{
va_list ap;
int c;
double d;
va_start(ap, fmt);
while ((c = *fmt++)) {
switch (c) {
case 'c':
case 's':
case 'i':
*buf++ = va_arg(ap, s32);
break;
case 'l':
*buf++ = va_arg(ap, long);
break;
case 'j':
*buf++ = va_arg(ap, s64);
break;
case 'f':
case 'd':
d = va_arg(ap, double);
memcpy(buf++, &d, sizeof(d));
break;
case 'C':
case 'S':
case 'I':
*buf++ = va_arg(ap, u32);
break;
case 'L':
*buf++ = va_arg(ap, unsigned long);
break;
}
}
va_end(ap);
return retval + 1;
}
4 changes: 2 additions & 2 deletions spec/ffi/spec_helper.rb
Original file line number Diff line number Diff line change
@@ -53,9 +53,9 @@ def compile_library(path, lib)
dir = File.expand_path(path, File.dirname(__FILE__))
lib = "#{dir}/#{lib}"
if !File.exists?(lib)
ldshared = RbConfig::CONFIG["LDSHARED"]
ldshared = RbConfig::CONFIG["LDSHARED"] || "clang -dynamic -bundle"
libs = RbConfig::CONFIG["LIBS"]
dldflags = RbConfig::CONFIG["DLDFLAGS"]
dldflags = RbConfig::CONFIG["DLDFLAGS"] || "-Wl,-undefined,dynamic_lookup -Wl,-multiply_defined,suppress"

puts Dir.pwd, dir, File.dirname(__FILE__)

Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
require 'rational'
require 'bigdecimal'

# https://github.com/jruby/jruby/issues/1695
describe 'BigDecimal#*' do
it 'returns correct value' do
(BigDecimal.new('100') * Rational(1, 100)).to_i.should == 1
(BigDecimal.new('100') * Rational(49, 100)).to_i.should == 49
(BigDecimal.new('100') * Rational(50, 100)).to_i.should == 50
end
end

1 change: 0 additions & 1 deletion spec/truffle/tags/core/false/and_tags.txt

This file was deleted.

1 change: 0 additions & 1 deletion spec/truffle/tags/core/false/inspect_tags.txt

This file was deleted.

1 change: 0 additions & 1 deletion spec/truffle/tags/core/false/or_tags.txt

This file was deleted.

1 change: 0 additions & 1 deletion spec/truffle/tags/core/false/to_s_tags.txt

This file was deleted.

1 change: 0 additions & 1 deletion spec/truffle/tags/core/false/xor_tags.txt

This file was deleted.

1 change: 0 additions & 1 deletion spec/truffle/tags/core/true/and_tags.txt

This file was deleted.

1 change: 0 additions & 1 deletion spec/truffle/tags/core/true/or_tags.txt

This file was deleted.

4 changes: 0 additions & 4 deletions spec/truffle/tags/language/predefined_tags.txt
Original file line number Diff line number Diff line change
@@ -38,11 +38,7 @@ fails:The predefined global constants includes TOPLEVEL_BINDING
fails:The predefined global constant STDERR has nil for the external encoding despite Encoding.default_external being changed
fails:The predefined global constant STDERR has the encodings set by #set_encoding
fails:The predefined global constant ARGV contains Strings encoded in locale Encoding
fails:The predefined global constant STDERR has nil for the internal encoding despite Encoding.default_internal being changed
fails:The predefined global constant STDERR has nil for the internal encoding
fails:The predefined global constant STDERR has nil for the external encoding
fails:The predefined global constant STDOUT has nil for the internal encoding despite Encoding.default_internal being changed
fails:The predefined global constant STDOUT has nil for the internal encoding
fails:The predefined global constant STDOUT has the encodings set by #set_encoding
fails:The predefined global constant STDOUT has nil for the external encoding despite Encoding.default_external being changed
fails:The predefined global constant STDOUT has nil for the external encoding
3 changes: 3 additions & 0 deletions test/compiler/test_jrubyc.rb
Original file line number Diff line number Diff line change
@@ -87,6 +87,9 @@ def test_require
end

def test_signature_with_arg_named_result
if RbConfig::CONFIG['bindir'].match( /!\//) || RbConfig::CONFIG['bindir'].match( /:\//)
skip( 'only filesystem installations of jruby can compile ruby to java' )
end
$compile_test = false
File.open("test_file2.rb", "w") {|file| file.write(<<-RUBY
class C
4 changes: 3 additions & 1 deletion test/jruby/test_cache_map_leak.rb
Original file line number Diff line number Diff line change
@@ -5,7 +5,7 @@ class TestMe; end

class TestCacheMapLeak < Test::Unit::TestCase

def setup
def setup_test
@num = 100
@num.times { class << TestMe.new; def foo; end; end }

@@ -14,6 +14,8 @@ def setup
end

def test_objects_are_released_by_cache_map
return unless JRuby.runtime.object_space_enabled?
setup_test
assert(@num != ObjectSpace.each_object(TestMe){}, "Objects not being release by CacheMap" )
end

20 changes: 10 additions & 10 deletions test/jruby/test_dir.rb
Original file line number Diff line number Diff line change
@@ -1,16 +1,12 @@
# coding: utf-8
require 'test/unit'
require 'test/jruby/test_helper'
require 'rbconfig'

class TestDir < Test::Unit::TestCase
include TestHelper
WINDOWS = RbConfig::CONFIG['host_os'] =~ /Windows|mswin/

def jruby
exe = File.join RbConfig::CONFIG['bindir'], RbConfig::CONFIG['RUBY_INSTALL_NAME']
exe += RbConfig::CONFIG['EXEEXT'] if RbConfig::CONFIG['EXEEXT']
exe
end

def setup
@save_dir = Dir.pwd
1.upto(5) do |i|
@@ -124,13 +120,17 @@ def test_chdir_and_pwd
java_test_classes = java_test_classes + ":" + File.expand_path(File.dirname(__FILE__) + '/../core/target/test-classes')
Dir.mkdir("testDir_4")
Dir.chdir("testDir_4") do
pwd = `#{jruby} -e "puts Dir.pwd"`
pwd = `#{RUBY} -e "puts Dir.pwd"`
pwd.gsub! '\\', '/'
assert_equal("testDir_4", pwd.split("/")[-1].strip)

pwd = `#{ENV_JAVA['jruby.home']}/bin/jruby -e "puts Dir.pwd"`
pwd.gsub! '\\', '/'
assert_equal("testDir_4", pwd.split("/")[-1].strip)
if (ENV_JAVA['jruby.home'] and not
ENV_JAVA['jruby.home'].match( /!\// ) and not
ENV_JAVA['jruby.home'].match( /:\// ))
pwd = `#{ENV_JAVA['jruby.home']}/bin/jruby -e "puts Dir.pwd"`
pwd.gsub! '\\', '/'
assert_equal("testDir_4", pwd.split("/")[-1].strip)
end

# FIXME: does not pass in 2.0 mode
# pwd = `java -cp "#{java_test_classes}" org.jruby.util.Pwd`
20 changes: 20 additions & 0 deletions test/jruby/test_file.rb
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
# -*- coding: utf-8 -*-
require 'test/unit'
require 'test/jruby/test_helper'
require 'rbconfig'
require 'fileutils'
require 'tempfile'
require 'pathname'
require 'jruby'

class TestFile < Test::Unit::TestCase
include TestHelper
WINDOWS = RbConfig::CONFIG['host_os'] =~ /Windows|mswin/

def setup
@@ -461,13 +463,31 @@ def test_mkdir
end
end

def test_directory_query # - directory?
begin
Dir.mkdir("dir_tmp")
assert(File.directory?("dir_tmp"))
assert(! File.directory?("test/test_file.rb"))
assert(! File.directory?("dir_not_tmp"))
result = jruby("-e 'print File.directory?(\"dir_not_tmp\");print File.directory?(\"dir_tmp\");print File.directory?(\"test/test_file.rb\")'", 'jruby.native.enabled' => 'false')
assert(result == 'falsetruefalse')
ensure
Dir.rmdir("dir_tmp")
end
end

def test_file_query # - file?
assert(File.file?('test/jruby/test_file.rb'))
assert(! File.file?('test'))
assert(! File.file?('test_not'))
result = jruby("-e 'print File.file?(\"test_not\");print File.file?(\"test\");print File.file?(\"test/test_file.rb\")'", 'jruby.native.enabled' => 'false' )
assert(result == 'falsefalsetrue')
end

def test_file_exist_query
assert(File.exist?('test'))
assert(! File.exist?('test_not'))
assert(jruby("-e 'print File.exists?(\"test_not\");print File.exists?(\"test\")'", 'jruby.native.enabled' => 'false' ) == 'falsetrue')
end

def test_file_exist_in_jar_file
36 changes: 34 additions & 2 deletions test/jruby/test_helper.rb
Original file line number Diff line number Diff line change
@@ -6,7 +6,23 @@ module TestHelper
# TODO: Consider how this should work if we have --windows or similiar
WINDOWS = RbConfig::CONFIG['host_os'] =~ /Windows|mswin/
SEPARATOR = WINDOWS ? '\\' : '/'
RUBY = '"' + File.join([RbConfig::CONFIG['bindir'], RbConfig::CONFIG['ruby_install_name']]) << RbConfig::CONFIG['EXEEXT'] + '"'
IS_JAR_EXECUTION = RbConfig::CONFIG['bindir'].match( /!\//) || RbConfig::CONFIG['bindir'].match( /:\//)
RUBY = if IS_JAR_EXECUTION
exe = 'java'
exe += RbConfig::CONFIG['EXEEXT'] if RbConfig::CONFIG['EXEEXT']
# assume the parent CL of jruby-classloader has a getUrls method
urls = JRuby.runtime.getJRubyClassLoader.parent.get_ur_ls.collect do |u|
u.path
end
urls.unshift '.'
exe += " -cp #{urls.join(File::PATH_SEPARATOR)} org.jruby.Main"
exe
else
exe = '"' + File.join(RbConfig::CONFIG['bindir'], RbConfig::CONFIG['RUBY_INSTALL_NAME'])
exe += RbConfig::CONFIG['EXEEXT'] if RbConfig::CONFIG['EXEEXT']
exe += '"'
exe
end

if (WINDOWS)
RUBY.gsub!('/', '\\')
@@ -26,8 +42,23 @@ def q
WINDOWS ? '"' : '\''
end

def interpreter( options = {} )
options = options.collect { |k,v| "-D#{k}=\"#{v}\"" }
if RUBY =~ /-cp /
RUBY.sub(/-cp [.]/, "-cp #{ENV["CLASSPATH"]}").sub(/-cp /, options.join(' ') + ' -cp ')
else
RUBY
end
end

def jruby(*args)
with_jruby_shell_spawning { `#{RUBY} #{args.join(' ')}` }
options = []
if args.last.is_a? Hash
options = args.last
args = args[0..-2]
end
options.each { |k,v| args.unshift "-J-D#{k}=\"#{v}\"" } unless RUBY =~ /-cp /
with_jruby_shell_spawning { `#{interpreter(options)} #{args.join(' ')}` }
end

def jruby_with_pipe(pipe, *args)
@@ -66,6 +97,7 @@ def quiet(&block)

def run_in_sub_runtime(script)
container = org.jruby.embed.ScriptingContainer.new(org.jruby.embed.LocalContextScope::SINGLETHREAD)
container.setLoadPaths(['.'])
container.runScriptlet("require 'java'")
container.runScriptlet(script)
end
6 changes: 5 additions & 1 deletion test/jruby/test_higher_javasupport.rb
Original file line number Diff line number Diff line change
@@ -691,7 +691,11 @@ def test_top_level_package_load_doesnt_set_error

# JRUBY-2169
def test_java_class_resource_methods
$CLASSPATH << 'test/org/jruby/javasupport/test/'
path = 'test/org/jruby/javasupport/test/'
# workaround for https://github.com/jruby/jruby/issues/2216
path = File.expand_path(path) if ENV_JAVA['user.dir'] != Dir.pwd
$CLASSPATH << path

file = 'test_java_class_resource_methods.properties'

jc = JRuby.runtime.jruby_class_loader
5 changes: 4 additions & 1 deletion test/jruby/test_io.rb
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
# -*- coding: utf-8 -*-
require 'test/unit'
require 'test/jruby/test_helper'
require 'rbconfig'
require 'stringio'
require 'java'
require 'jruby'

class TestIO < Test::Unit::TestCase
include TestHelper

WINDOWS = RbConfig::CONFIG['host_os'] =~ /Windows|mswin/
SOLARIS = RbConfig::CONFIG['host_os'] =~ /solaris/

@@ -389,7 +392,7 @@ def test_file_constants_included
#JRUBY-3012
def test_io_reopen
quiet_script = File.dirname(__FILE__) + '/quiet.rb'
result = `#{ENV_JAVA['jruby.home']}/bin/jruby #{quiet_script}`.chomp
result = `#{RUBY} #{quiet_script}`.chomp
assert_equal("foo", result)
end

15 changes: 14 additions & 1 deletion test/jruby/test_jarred_gems_with_spaces_in_directory.rb
Original file line number Diff line number Diff line change
@@ -7,5 +7,18 @@ class TestJarredGemsWithSpacesInDirectory < Test::Unit::TestCase
def test_list_gem_from_jar_with_spaces_in_directory
out = jruby(%q{-r"test/jruby/dir with spaces/testgem.jar" -S jgem list})
assert(out =~ /testgem/)

cp = ENV['CLASSPATH']
begin
if RUBY.match( /.jar/) # uses jruby-complete.jar
ENV['CLASSPATH'] = cp.to_s + File::PATH_SEPARATOR + '"test/dir with spaces/testgem.jar"'
out = jruby(%q{-e "p require 'testgem'"})
else
out = jruby(%q{-J-cp "test/dir with spaces/testgem.jar" -e "p require 'testgem'"})
end
ensure
ENV['CLASSPATH'] = cp if cp
end
assert(out =~ /true/)
end
end
end
8 changes: 5 additions & 3 deletions test/jruby/test_launching_by_shell_script.rb
Original file line number Diff line number Diff line change
@@ -79,7 +79,7 @@ def test_system_call_with_stdin_data_doesnt_hang
if (!WINDOWS)
# JRUBY-2295
def test_java_props_with_spaces
res = jruby(%q{-J-Dfoo='a b c' -e "require 'java'; puts java.lang.System.getProperty('foo')"}).chomp
res = jruby(%q{-e "require 'java'; puts java.lang.System.getProperty('foo')"}, 'foo' => 'a b c').chomp
assert_equal("a b c", res)
end

@@ -180,7 +180,9 @@ def test_run_script_from_jar
end

def test_launch_inproc_ignores_dash_J_with_warning
output = `#{ENV_JAVA['jruby.home']}/bin/jruby -J-Xmx256m -e "puts true"`
assert_equal "true\n", output
unless IS_JAR_EXECUTION
output = `#{ENV_JAVA['jruby.home']}/bin/jruby -J-Xmx256m -e "puts true"`
assert_equal "true\n", output
end
end
end
4 changes: 2 additions & 2 deletions test/jruby/test_missing_jruby_home.rb
Original file line number Diff line number Diff line change
@@ -12,7 +12,7 @@ def test_missing_jruby_home
runtime.eval_scriptlet('require "rbconfig"')
end
ensure
java.lang.System.set_property('jruby.home', old)
java.lang.System.set_property('jruby.home', old) if old
end
end
end
end
47 changes: 47 additions & 0 deletions test/test_include_order.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#GH-1938
require "test/unit"

class TestIncludeOrder < Test::Unit::TestCase
module X
end

class Q
def foo arg = []
arg << :Q
end
end

class Y < Q
include X
end

module A
def foo arg = []
arg << :A
super
end
end

module X
include A
end

module Z
def foo arg = []
arg << :Z
super
end
end

class Y
include Z
end

class Y
include X
end

def test_include_order
assert_equal Y.new.foo, [:Z, :A, :Q]
end
end

0 comments on commit 1b1c259

Please sign in to comment.