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: 3d81301011a8
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 8d27349f466b
Choose a head ref
  • 4 commits
  • 3 files changed
  • 1 contributor

Commits on Jan 27, 2016

  1. Copy the full SHA
    fb8d0c3 View commit details
  2. Copy the full SHA
    45118e3 View commit details
  3. Copy the full SHA
    4b04b6d View commit details
  4. semi-port MRI's rb_check_funcall_default which is the new rb_check_fu…

    …ncall
    
    ... and does an additional respond_to_missing? check
    kares committed Jan 27, 2016
    Copy the full SHA
    8d27349 View commit details
Showing with 42 additions and 30 deletions.
  1. +6 −5 core/src/main/java/org/jruby/RubyArray.java
  2. +1 −2 core/src/main/java/org/jruby/RubyBasicObject.java
  3. +35 −23 core/src/main/java/org/jruby/RubyClass.java
11 changes: 6 additions & 5 deletions core/src/main/java/org/jruby/RubyArray.java
Original file line number Diff line number Diff line change
@@ -2805,8 +2805,9 @@ public IRubyObject rassoc(ThreadContext context, IRubyObject value) {
return runtime.getNil();
}

private boolean flatten(ThreadContext context, int level, RubyArray result) {
Ruby runtime = context.runtime;
// MRI array.c flatten
private boolean flatten(ThreadContext context, final int level, final RubyArray result) {
final Ruby runtime = context.runtime;
RubyArray stack = new RubyArray(runtime, ARRAY_DEFAULT_SIZE, false);
IdentityHashMap<Object, Object> memo = new IdentityHashMap<Object, Object>();
RubyArray ary = this;
@@ -2840,10 +2841,10 @@ private boolean flatten(ThreadContext context, int level, RubyArray result) {
if (stack.realLength == 0) break;
memo.remove(ary);
tmp = stack.pop(context);
i = (int)((RubyFixnum)tmp).getLongValue();
ary = (RubyArray)stack.pop(context);
i = (int) ((RubyFixnum) tmp).getLongValue();
ary = (RubyArray) stack.pop(context);
}
} catch (ArrayIndexOutOfBoundsException aioob) {
} catch (ArrayIndexOutOfBoundsException ex) {
concurrentModification();
}
return modified;
3 changes: 1 addition & 2 deletions core/src/main/java/org/jruby/RubyBasicObject.java
Original file line number Diff line number Diff line change
@@ -595,11 +595,10 @@ public final boolean respondsTo(String name) {
final Ruby runtime = getRuntime();

final DynamicMethod respondTo = getMetaClass().searchMethod("respond_to?");
final DynamicMethod respondToMissing = getMetaClass().searchMethod("respond_to_missing?");

// fastest path; builtin respond_to? and respond_to_missing? so we just check isMethodBound
if ( respondTo.equals(runtime.getRespondToMethod()) &&
respondToMissing.equals(runtime.getRespondToMissingMethod()) ) {
getMetaClass().searchMethod("respond_to_missing?").equals(runtime.getRespondToMissingMethod()) ) {
return getMetaClass().isMethodBound(name, false);
}

58 changes: 35 additions & 23 deletions core/src/main/java/org/jruby/RubyClass.java
Original file line number Diff line number Diff line change
@@ -621,22 +621,25 @@ public IRubyObject finvoke(ThreadContext context, IRubyObject self, String name)
*
* MRI: rb_check_funcall
*/
public IRubyObject finvokeChecked(ThreadContext context, IRubyObject self, String name) {
return finvokeChecked(context, self, name, IRubyObject.NULL_ARRAY);
public final IRubyObject finvokeChecked(ThreadContext context, IRubyObject self, String name) {
return checkFuncallDefault(context, self, name, IRubyObject.NULL_ARRAY);
}

/**
* Safely attempt to invoke the given method name on self, using respond_to? and method_missing as appropriate.
*
* MRI: rb_check_funcall
*/
public IRubyObject finvokeChecked(ThreadContext context, IRubyObject self, String name, IRubyObject... args) {
RubyClass klass = self.getMetaClass();
DynamicMethod me;
if (!checkFuncallRespondTo(context, self.getMetaClass(), self, name))
return null;
public final IRubyObject finvokeChecked(ThreadContext context, IRubyObject self, String name, IRubyObject... args) {
return checkFuncallDefault(context, self, name, args);
}

// MRI: rb_check_funcall_default
private IRubyObject checkFuncallDefault(ThreadContext context, IRubyObject self, String name, IRubyObject[] args) {
final RubyClass klass = self.getMetaClass();
if (!checkFuncallRespondTo(context, klass, self, name)) return null; // return def;

me = searchMethod(name);
DynamicMethod me = searchMethod(name);
if (!checkFuncallCallable(context, me, CallType.FUNCTIONAL, self)) {
return checkFuncallMissing(context, klass, self, name, args);
}
@@ -665,7 +668,7 @@ private static IRubyObject checkFuncallFailed(ThreadContext context, IRubyObject
* MRI: check_funcall_respond_to
*/
private static boolean checkFuncallRespondTo(ThreadContext context, RubyClass klass, IRubyObject recv, String mid) {
Ruby runtime = context.runtime;
final Ruby runtime = context.runtime;
DynamicMethod me = klass.searchMethod("respond_to?");

// NOTE: isBuiltin here would be NOEX_BASIC in MRI, a flag only added to respond_to?, method_missing, and
@@ -681,8 +684,7 @@ private static boolean checkFuncallRespondTo(ThreadContext context, RubyClass kl
} else {
result = me.call(context, recv, klass, "respond_to?", runtime.newSymbol(mid), runtime.getTrue());
}

if (!result.isTrue()) return false;
return result.isTrue();
}
return true;
}
@@ -700,19 +702,29 @@ public static boolean rbMethodCallStatus(ThreadContext context, DynamicMethod me

// MRI: check_funcall_missing
private static IRubyObject checkFuncallMissing(ThreadContext context, RubyClass klass, IRubyObject self, String method, IRubyObject... args) {
Ruby runtime = context.runtime;
if (klass.isMethodBuiltin("method_missing")) {
return null;
}
else {
final IRubyObject $ex = context.getErrorInfo();
try {
return checkFuncallExec(context, self, method, args);
}
catch (RaiseException e) {
context.setErrorInfo($ex); // restore $!
return checkFuncallFailed(context, self, method, runtime.getNoMethodError(), args);
final Ruby runtime = context.runtime;

DynamicMethod me = klass.searchMethod("respond_to_missing?");
// MRI: basic_obj_respond_to_missing ...
if ( me != null && ! me.isUndefined() ) {
IRubyObject ret;
if (me.getArity().getValue() == 1) {
ret = me.call(context, self, klass, "respond_to_missing?", runtime.newSymbol(method));
} else {
ret = me.call(context, self, klass, "respond_to_missing?", runtime.newSymbol(method), runtime.getTrue());
}
if ( ! ret.isTrue() ) return null;
}

if ( klass.isMethodBuiltin("method_missing") ) return null;

final IRubyObject $ex = context.getErrorInfo();
try {
return checkFuncallExec(context, self, method, args);
}
catch (RaiseException e) {
context.setErrorInfo($ex); // restore $!
return checkFuncallFailed(context, self, method, runtime.getNoMethodError(), args);
}
}