Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: jruby/jruby
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 889bfbffef78
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 1ec7e208acb1
Choose a head ref
  • 5 commits
  • 5 files changed
  • 1 contributor

Commits on Jun 3, 2016

  1. Copy the full SHA
    88fad80 View commit details
  2. Copy the full SHA
    98b95ce View commit details
  3. Copy the full SHA
    7a2fc20 View commit details
  4. minor JavaClass house-keeping

    kares committed Jun 3, 2016
    Copy the full SHA
    89cedd5 View commit details
  5. make sure ObjectSpace.each_object(&block) always returns the count

    ... wasn't the case with <class instance>.singleton_class
    kares committed Jun 3, 2016
    Copy the full SHA
    1ec7e20 View commit details
63 changes: 30 additions & 33 deletions core/src/main/java/org/jruby/RubyObjectSpace.java
Original file line number Diff line number Diff line change
@@ -32,7 +32,6 @@
package org.jruby;

import java.util.ArrayList;
import java.util.Collection;
import static org.jruby.RubyEnumerator.enumeratorize;

import java.util.Iterator;
@@ -67,7 +66,7 @@ public static RubyModule createObjectSpaceModule(Ruby runtime) {
@JRubyMethod(required = 1, optional = 1, module = true, visibility = PRIVATE)
public static IRubyObject define_finalizer(IRubyObject recv, IRubyObject[] args, Block block) {
Ruby runtime = recv.getRuntime();
IRubyObject finalizer = null;
IRubyObject finalizer;
if (args.length == 2) {
finalizer = args[1];
if (!finalizer.respondsTo("call")) {
@@ -90,7 +89,7 @@ public static IRubyObject undefine_finalizer(IRubyObject recv, IRubyObject arg1,

@JRubyMethod(name = "_id2ref", required = 1, module = true, visibility = PRIVATE)
public static IRubyObject id2ref(IRubyObject recv, IRubyObject id) {
Ruby runtime = id.getRuntime();
final Ruby runtime = id.getRuntime();
if (!(id instanceof RubyFixnum)) {
throw recv.getRuntime().newTypeError(id, recv.getRuntime().getFixnum());
}
@@ -120,63 +119,61 @@ public static IRubyObject id2ref(IRubyObject recv, IRubyObject id) {
}

public static IRubyObject each_objectInternal(final ThreadContext context, IRubyObject recv, IRubyObject[] args, final Block block) {
RubyModule tmpClass;
final Ruby runtime = context.runtime;
final RubyModule rubyClass;
if (args.length == 0) {
tmpClass = recv.getRuntime().getObject();
rubyClass = runtime.getObject();
} else {
if (!(args[0] instanceof RubyModule)) throw recv.getRuntime().newTypeError("class or module required");
tmpClass = (RubyModule) args[0];
if (!(args[0] instanceof RubyModule)) throw runtime.newTypeError("class or module required");
rubyClass = (RubyModule) args[0];
}
final RubyModule rubyClass = tmpClass;
Ruby runtime = recv.getRuntime();
final int[] count = {0};
if (rubyClass == runtime.getClassClass() ||
rubyClass == runtime.getModule()) {
final Collection<IRubyObject> modules = new ArrayList<IRubyObject>();
if (rubyClass == runtime.getClassClass() || rubyClass == runtime.getModule()) {

final ArrayList<IRubyObject> modules = new ArrayList<>(96);
runtime.eachModule(new Function1<Object, IRubyObject>() {
public Object apply(IRubyObject arg1) {
if (rubyClass.isInstance(arg1)) {
if (arg1 instanceof IncludedModule) {
// do nothing for included wrappers or singleton classes
} else {
count[0]++;
modules.add(arg1); // store the module to avoid concurrent modification exceptions
}
}
return null;
}
});

for (IRubyObject arg : modules) {
block.yield(context, arg);
final int count = modules.size();
for (int i = 0; i<count; i++) {
block.yield(context, modules.get(i));
}
} else if (args[0].getClass() == MetaClass.class) {
return runtime.newFixnum(count);
}
if (args[0].getClass() == MetaClass.class) {
// each_object(Cls.singleton_class) is basically a walk of Cls and all descendants of Cls.
// In other words, this is walking all instances of Cls's singleton class and its subclasses.
IRubyObject attached = ((MetaClass)args[0]).getAttached();
block.yield(context, attached);
IRubyObject attached = ((MetaClass) args[0]).getAttached();
block.yield(context, attached); int count = 1;
if (attached instanceof RubyClass) {
for (RubyClass child : ((RubyClass)attached).subclasses(true)) {
for (RubyClass child : ((RubyClass) attached).subclasses(true)) {
if (child instanceof IncludedModule) {
// do nothing for included wrappers or singleton classes
} else {
block.yield(context, child);
count++; block.yield(context, child);
}
}
}
} else {
if (!runtime.isObjectSpaceEnabled()) {
throw runtime.newRuntimeError("ObjectSpace is disabled; each_object will only work with Class, pass -X+O to enable");
}
Iterator iter = recv.getRuntime().getObjectSpace().iterator(rubyClass);

IRubyObject obj = null;
while ((obj = (IRubyObject)iter.next()) != null) {
count[0]++;
block.yield(context, obj);
}
return runtime.newFixnum(count);
}
if ( ! runtime.isObjectSpaceEnabled() ) {
throw runtime.newRuntimeError("ObjectSpace is disabled; each_object will only work with Class, pass -X+O to enable");
}
final Iterator iter = runtime.getObjectSpace().iterator(rubyClass);
IRubyObject obj; int count = 0;
while ((obj = (IRubyObject) iter.next()) != null) {
count++; block.yield(context, obj);
}
return recv.getRuntime().newFixnum(count[0]);
return runtime.newFixnum(count);
}

@JRubyMethod(name = "each_object", optional = 1, module = true, visibility = PRIVATE)
6 changes: 3 additions & 3 deletions core/src/main/java/org/jruby/RubyThread.java
Original file line number Diff line number Diff line change
@@ -850,7 +850,7 @@ public static IRubyObject pass(IRubyObject recv) {
ts.setCritical(critical);
}

return recv.getRuntime().getNil();
return runtime.getNil();
}

@JRubyMethod(meta = true)
@@ -937,7 +937,7 @@ public synchronized IRubyObject thread_variable_get(ThreadContext context, IRuby
if ((value = getThreadLocals().get(getSymbolKey(key))) != null) {
return value;
}
return context.runtime.getNil();
return context.nil;
}

@JRubyMethod(name = "thread_variable_set", required = 2)
@@ -1150,7 +1150,7 @@ public static IRubyObject stop(ThreadContext context, IRubyObject receiver) {
}
}

return receiver.getRuntime().getNil();
return context.nil;
}

@JRubyMethod(required = 1, meta = true)
54 changes: 24 additions & 30 deletions core/src/main/java/org/jruby/javasupport/JavaClass.java
Original file line number Diff line number Diff line change
@@ -68,7 +68,7 @@

import static org.jruby.RubyModule.undefinedMethodMessage;

@JRubyClass(name="Java::JavaClass", parent="Java::JavaObject")
@JRubyClass(name="Java::JavaClass", parent="Java::JavaObject", include = "Comparable")
public class JavaClass extends JavaObject {

public static final Class[] EMPTY_CLASS_ARRAY = new Class[0];
@@ -100,26 +100,18 @@ public final RubyClass getProxyClass() {
return (RubyClass) Java.getProxyClass(getRuntime(), javaClass());
}

public void addProxyExtender(final IRubyObject extender) {
Ruby runtime = getRuntime();

if (!extender.respondsTo("extend_proxy")) {
throw runtime.newTypeError("proxy extender must have an extend_proxy method");
private IRubyObject addProxyExtender(final ThreadContext context, final IRubyObject extender) {
if ( ! extender.respondsTo("extend_proxy") ) {
throw context.runtime.newTypeError("proxy extender must have an extend_proxy method");
}

ThreadContext context = runtime.getCurrentContext();
RubyModule proxy = Java.getProxyClass(runtime, javaClass());
extendProxy(context, extender, proxy);
}

private void extendProxy(final ThreadContext context, final IRubyObject extender, final RubyModule proxy) {
extender.callMethod(context, "extend_proxy", proxy);
RubyModule proxy = Java.getProxyClass(context.runtime, javaClass());
return extender.callMethod(context, "extend_proxy", proxy);
}

@JRubyMethod(required = 1)
public IRubyObject extend_proxy(final ThreadContext context, IRubyObject extender) {
addProxyExtender(extender);
return getRuntime().getNil();
addProxyExtender(context, extender);
return context.nil;
}

public static JavaClass get(final Ruby runtime, final Class<?> klass) {
@@ -144,10 +136,9 @@ public static RubyClass createJavaClassClass(final Ruby runtime, final RubyModul
}

static RubyClass createJavaClassClass(final Ruby runtime, final RubyModule Java, final RubyClass JavaObject) {
// FIXME: Determine if a real allocator is needed here. Do people want to extend
// JavaClass? Do we want them to do that? Can you Class.new(JavaClass)? Should
// you be able to?
// TODO: NOT_ALLOCATABLE_ALLOCATOR is probably ok here, since we don't intend for people to monkey with
// TODO: Determine if a real allocator is needed here. Do people want to extend
// JavaClass? Do we want them to do that? Can you Class.new(JavaClass)? Should you be able to?
// NOTE: NOT_ALLOCATABLE_ALLOCATOR is probably OK here, since we don't intend for people to monkey with
// this type and it can't be marshalled. Confirm. JRUBY-415
RubyClass JavaCLass = Java.defineClassUnder("JavaClass", JavaObject, ObjectAllocator.NOT_ALLOCATABLE_ALLOCATOR);

@@ -187,22 +178,25 @@ static boolean isPrimitiveName(final String name) {
return JavaUtil.PRIMITIVE_CLASSES.containsKey(name);
}

public static synchronized JavaClass forNameVerbose(Ruby runtime, String className) {
Class <?> klass = null;
if (className.indexOf('.') == -1 && Character.isLowerCase(className.charAt(0))) {
public static JavaClass forNameVerbose(Ruby runtime, String className) {
Class<?> klass = null; // "boolean".length() == 7
if (className.length() < 8 && Character.isLowerCase(className.charAt(0))) {
// one word type name that starts lower-case...it may be a primitive type
klass = JavaUtil.PRIMITIVE_CLASSES.get(className);
}

if (klass == null) {
klass = runtime.getJavaSupport().loadJavaClassVerbose(className);
synchronized (JavaClass.class) {
if (klass == null) {
klass = runtime.getJavaSupport().loadJavaClassVerbose(className);
}
return JavaClass.get(runtime, klass);
}
return JavaClass.get(runtime, klass);
}

public static synchronized JavaClass forNameQuiet(Ruby runtime, String className) {
Class klass = runtime.getJavaSupport().loadJavaClassQuiet(className);
return JavaClass.get(runtime, klass);
public static JavaClass forNameQuiet(Ruby runtime, String className) {
synchronized (JavaClass.class) {
Class<?> klass = runtime.getJavaSupport().loadJavaClassQuiet(className);
return JavaClass.get(runtime, klass);
}
}

@JRubyMethod(name = "for_name", required = 1, meta = true)
7 changes: 3 additions & 4 deletions core/src/main/java/org/jruby/javasupport/JavaObject.java
Original file line number Diff line number Diff line change
@@ -75,12 +75,12 @@ protected JavaObject(Ruby runtime, RubyClass rubyClass, Object value) {
}

@Override
public Object dataGetStruct() {
public final Object dataGetStruct() {
return objectAccessor.get(this);
}

@Override
public void dataWrapStruct(Object object) {
public final void dataWrapStruct(Object object) {
objectAccessor.set(this, object);
}

@@ -155,8 +155,7 @@ public boolean equals(final Object other) {
@Override
public int hashCode() {
final Object value = dataGetStruct();
if ( value == null ) return 0;
return value.hashCode();
return value == null ? 0 : value.hashCode();
}

@JRubyMethod
15 changes: 8 additions & 7 deletions core/src/main/java/org/jruby/runtime/Arity.java
Original file line number Diff line number Diff line change
@@ -42,7 +42,7 @@
*/
public final class Arity implements Serializable {
private static final long serialVersionUID = 1L;
private static final Map<Integer, Arity> arities = new HashMap<Integer, Arity>();
private static final Map<Integer, Arity> arities = new HashMap<>();
private final int value;

public final static Arity NO_ARGUMENTS = newArity(0);
@@ -112,12 +112,13 @@ public static Arity fromAnnotation(JRubyMethod anno, Class[] parameterTypes, boo
}

private static Arity newArity(int value) {
Arity result;
synchronized (arities) {
result = arities.get(value);
if (result == null) {
result = new Arity(value);
arities.put(value, result);
Arity result = arities.get(value);
if (result == null) {
synchronized (arities) {
result = arities.get(value);
if (result == null) {
arities.put(value, result = new Arity(value));
}
}
}
return result;