Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merge branch 'master' into JRUBY-6785

  • Loading branch information...
commit bce5609649e59b21bb07171ddc6188924660aba8 2 parents 3118cd9 + 846be19
@donv donv authored
View
7 src/jruby/kernel19/proc.rb
@@ -20,10 +20,11 @@ def curry(curried_arity = nil)
m = lambda? ? :lambda : :proc
f = send(m) {|*x|
- args += x
- if args.length >= arity
- self[*args]
+ call_args = args + x
+ if call_args.length >= arity
+ self[*call_args]
else
+ args = call_args
f
end
}
View
2  src/org/jruby/BasicObjectStub.java
@@ -124,7 +124,7 @@ public static RubyClass getType(IRubyObject self) {
}
public static boolean respondsTo(IRubyObject self, String name) {
- if(getMetaClass(self).searchMethod("respond_to?") == getRuntime(self).getRespondToMethod()) {
+ if(getMetaClass(self).searchMethod("respond_to?").equals(getRuntime(self).getRespondToMethod())) {
return getMetaClass(self).isMethodBound(name, false);
} else {
return callMethod(self, getRuntime(self).getCurrentContext(), "respond_to?", getRuntime(self).newSymbol(name)).isTrue();
View
42 src/org/jruby/Ruby.java
@@ -1185,7 +1185,13 @@ private void init() {
initRubyKernel();
if(config.isProfiling()) {
+ // additional twiddling for profiled mode
getLoadService().require("jruby/profiler/shutdown_hook");
+
+ // recache core methods, since they'll have profiling wrappers now
+ kernelModule.invalidateCacheDescendants(); // to avoid already-cached methods
+ RubyKernel.recacheBuiltinMethods(this);
+ RubyBasicObject.recacheBuiltinMethods(this);
}
if (config.getLoadGemfile()) {
@@ -1646,14 +1652,6 @@ private void addBuiltinIfAllowed(String name, Library lib) {
loadService.addBuiltinLibrary(name,lib);
}
}
-
- public Object getRespondToMethod() {
- return respondToMethod;
- }
-
- public void setRespondToMethod(Object rtm) {
- this.respondToMethod = rtm;
- }
public IRManager getIRManager() {
return irManager;
@@ -1729,42 +1727,66 @@ void setKernel(RubyModule kernelModule) {
this.kernelModule = kernelModule;
}
+ ///////////////////////////////////////////////////////////////////////////
+ // Cached DynamicMethod objects, used for direct dispatch or for short
+ // circuiting dynamic invocation logic.
+ ///////////////////////////////////////////////////////////////////////////
+
public DynamicMethod getPrivateMethodMissing() {
return privateMethodMissing;
}
+
public void setPrivateMethodMissing(DynamicMethod method) {
privateMethodMissing = method;
}
+
public DynamicMethod getProtectedMethodMissing() {
return protectedMethodMissing;
}
+
public void setProtectedMethodMissing(DynamicMethod method) {
protectedMethodMissing = method;
}
+
public DynamicMethod getVariableMethodMissing() {
return variableMethodMissing;
}
+
public void setVariableMethodMissing(DynamicMethod method) {
variableMethodMissing = method;
}
+
public DynamicMethod getSuperMethodMissing() {
return superMethodMissing;
}
+
public void setSuperMethodMissing(DynamicMethod method) {
superMethodMissing = method;
}
+
public DynamicMethod getNormalMethodMissing() {
return normalMethodMissing;
}
+
public void setNormalMethodMissing(DynamicMethod method) {
normalMethodMissing = method;
}
+
public DynamicMethod getDefaultMethodMissing() {
return defaultMethodMissing;
}
+
public void setDefaultMethodMissing(DynamicMethod method) {
defaultMethodMissing = method;
}
+
+ public DynamicMethod getRespondToMethod() {
+ return respondTo;
+ }
+
+ public void setRespondToMethod(DynamicMethod rtm) {
+ this.respondTo = rtm;
+ }
public RubyClass getDummy() {
return dummyClass;
@@ -4307,7 +4329,7 @@ public void setFFI(FFI ffi) {
procSysModule, precisionModule, errnoModule;
private DynamicMethod privateMethodMissing, protectedMethodMissing, variableMethodMissing,
- superMethodMissing, normalMethodMissing, defaultMethodMissing;
+ superMethodMissing, normalMethodMissing, defaultMethodMissing, respondTo;
// record separator var, to speed up io ops that use it
private GlobalVariable recordSeparatorVar;
@@ -4388,8 +4410,6 @@ public void setFFI(FFI ffi) {
// Weak map of all Modules in the system (and by extension, all Classes
private final Set<RubyModule> allModules = new WeakHashSet<RubyModule>();
- private Object respondToMethod;
-
private final Map<String, DateTimeZone> timeZoneCache = new HashMap<String,DateTimeZone>();
/**
* A list of "external" finalizers (the ones, registered via ObjectSpace),
View
10 src/org/jruby/RubyArray.java
@@ -1858,9 +1858,13 @@ public IRubyObject join19(final ThreadContext context, IRubyObject sep) {
if (realLength == 0) return RubyString.newEmptyString(runtime, USASCIIEncoding.INSTANCE);
if (sep.isNil()) sep = runtime.getGlobalVariables().get("$,");
-
- RubyString sepString = sep.convertToString();
- int len = 1 + sepString.size() * (realLength - 1);
+
+ int len = 1;
+ RubyString sepString = null;
+ if (!sep.isNil()) {
+ sepString = sep.convertToString();
+ len += sepString.size() * (realLength - 1);
+ }
for (int i = begin; i < begin + realLength; i++) {
IRubyObject val = safeArrayRef(values, i);
View
12 src/org/jruby/RubyBasicObject.java
@@ -198,11 +198,19 @@ public static RubyClass createBasicObjectClass(Ruby runtime, RubyClass objectCla
objectClass.defineAnnotatedMethods(RubyBasicObject.class);
- runtime.setDefaultMethodMissing(objectClass.searchMethod("method_missing"));
+ recacheBuiltinMethods(runtime);
return objectClass;
}
+ static void recacheBuiltinMethods(Ruby runtime) {
+ RubyModule objectClass = runtime.getBasicObject();
+
+ if (runtime.is1_9()) { // method_missing is in Kernel in 1.9
+ runtime.setDefaultMethodMissing(objectClass.searchMethod("method_missing"));
+ }
+ }
+
@JRubyMethod(name = "initialize", visibility = PRIVATE, compat = RUBY1_9)
public IRubyObject initialize19(ThreadContext context) {
return context.nil;
@@ -578,7 +586,7 @@ public RubyClass getType() {
*/
public final boolean respondsTo(String name) {
DynamicMethod method = getMetaClass().searchMethod("respond_to?");
- if(method == getRuntime().getRespondToMethod()) {
+ if(method.equals(getRuntime().getRespondToMethod())) {
// fastest path; builtin respond_to? which just does isMethodBound
return getMetaClass().isMethodBound(name, false);
} else if (!method.isUndefined()) {
View
9 src/org/jruby/RubyClass.java
@@ -59,6 +59,7 @@
import org.jruby.compiler.impl.SkinnyMethodAdapter;
import org.jruby.exceptions.RaiseException;
import org.jruby.internal.runtime.methods.DynamicMethod;
+import org.jruby.internal.runtime.methods.ProfilingDynamicMethod;
import org.jruby.java.codegen.RealClassGenerator;
import org.jruby.java.codegen.Reified;
import org.jruby.javasupport.Java;
@@ -685,7 +686,7 @@ public IRubyObject finvokeChecked(ThreadContext context, IRubyObject self, Strin
DynamicMethod method = searchMethod(name);
if(method.isUndefined()) {
DynamicMethod methodMissing = searchMethod("method_missing");
- if(methodMissing.isUndefined() || methodMissing == context.getRuntime().getDefaultMethodMissing()) {
+ if(methodMissing.isUndefined() || methodMissing.equals(context.getRuntime().getDefaultMethodMissing())) {
return null;
}
@@ -1732,7 +1733,7 @@ public void smartDump(MarshalStream stream, IRubyObject target) throws IOExcepti
} else {
// recache
DynamicMethod method = searchMethod("respond_to?");
- if (method != runtime.getRespondToMethod() && !method.isUndefined()) {
+ if (!method.equals(runtime.getRespondToMethod()) && !method.isUndefined()) {
// custom respond_to?, always do slow default marshaling
tuple = (cachedDumpMarshal = new MarshalTuple(null, MarshalType.DEFAULT_SLOW, generation));
@@ -1783,7 +1784,7 @@ public IRubyObject smartLoadNewUser(IRubyObject target, IRubyObject data) {
return target;
} else {
DynamicMethod method = searchMethod("respond_to?");
- if (method != runtime.getRespondToMethod() && !method.isUndefined()) {
+ if (!method.equals(runtime.getRespondToMethod()) && !method.isUndefined()) {
// custom respond_to?, cache nothing and use slow path
if (method.call(context, target, this, "respond_to?", runtime.newSymbol("marshal_load")).isTrue()) {
@@ -1834,7 +1835,7 @@ public IRubyObject smartLoadOldUser(IRubyObject data) {
return cache.method.call(context, this, getSingletonClass(), "_load", data);
} else {
DynamicMethod method = getSingletonClass().searchMethod("respond_to?");
- if (method != runtime.getRespondToMethod() && !method.isUndefined()) {
+ if (!method.equals(runtime.getRespondToMethod()) && !method.isUndefined()) {
// custom respond_to?, cache nothing and use slow path
if (method.call(context, this, getSingletonClass(), "respond_to?", runtime.newSymbol("_load")).isTrue()) {
View
3  src/org/jruby/RubyFile.java
@@ -1241,7 +1241,8 @@ private Stream fopen(String path, ModeFlags flags) {
} catch (FileNotFoundException ex) {
// FNFException can be thrown in both cases, when the file
// is not found, or when permission is denied.
- if (Ruby.isSecurityRestricted() || new File(getRuntime().getCurrentDirectory(), path).exists()) {
+ // FIXME: yes, this is indeed gross.
+ if (ex.getMessage().contains(/*P*/"ermission denied")) {
throw getRuntime().newErrnoEACCESError(path);
}
throw getRuntime().newErrnoENOENTError(path);
View
20 src/org/jruby/RubyKernel.java
@@ -107,8 +107,6 @@ public static RubyModule createKernelModule(Ruby runtime) {
module.defineAnnotatedMethods(RubyKernel.class);
- runtime.setRespondToMethod(module.searchMethod("respond_to?"));
-
module.setFlag(RubyObject.USER7_F, false); //Kernel is the only Module that doesn't need an implementor
runtime.setPrivateMethodMissing(new MethodMissingMethod(module) {
@@ -146,11 +144,25 @@ public IRubyObject methodMissing(ThreadContext context, IRubyObject self, RubyMo
}
});
+ recacheBuiltinMethods(runtime);
+
+ return module;
+ }
+
+ /**
+ * Cache built-in versions of several core methods, to improve performance by using identity comparison (==) rather
+ * than going ahead with dynamic dispatch.
+ *
+ * @param runtime
+ */
+ static void recacheBuiltinMethods(Ruby runtime) {
+ RubyModule module = runtime.getKernel();
+
+ runtime.setRespondToMethod(module.searchMethod("respond_to?"));
+
if (!runtime.is1_9()) { // method_missing is in BasicObject in 1.9
runtime.setDefaultMethodMissing(module.searchMethod("method_missing"));
}
-
- return module;
}
@JRubyMethod(module = true, visibility = PRIVATE)
View
25 src/org/jruby/ext/ffi/jffi/JITNativeInvoker.java
@@ -135,6 +135,22 @@ public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule klaz
throw context.getRuntime().newArgumentError(3, arity);
}
+ public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule klazz, String name,
+ IRubyObject arg1, IRubyObject arg2, IRubyObject arg3, IRubyObject arg4) {
+ throw context.getRuntime().newArgumentError(4, arity);
+ }
+
+ public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule klazz, String name,
+ IRubyObject arg1, IRubyObject arg2, IRubyObject arg3, IRubyObject arg4, IRubyObject arg5) {
+ throw context.getRuntime().newArgumentError(5, arity);
+ }
+
+ public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule klazz, String name,
+ IRubyObject arg1, IRubyObject arg2, IRubyObject arg3, IRubyObject arg4,
+ IRubyObject arg5, IRubyObject arg6) {
+ throw context.getRuntime().newArgumentError(6, arity);
+ }
+
@Override
public final IRubyObject call(ThreadContext context, IRubyObject self,
RubyModule clazz, String name, IRubyObject[] args) {
@@ -155,6 +171,15 @@ public final IRubyObject call(ThreadContext context, IRubyObject self,
case 3:
return call(context, self, clazz, name, args[0], args[1], args[2]);
+ case 4:
+ return call(context, self, clazz, name, args[0], args[1], args[2], args[3]);
+
+ case 5:
+ return call(context, self, clazz, name, args[0], args[1], args[2], args[3], args[4]);
+
+ case 6:
+ return call(context, self, clazz, name, args[0], args[1], args[2], args[3], args[4], args[5]);
+
default:
throw context.getRuntime().newArgumentError("too many arguments: " + args.length);
}
View
13 src/org/jruby/internal/runtime/methods/DelegatingDynamicMethod.java
@@ -176,4 +176,17 @@ public CallConfiguration getCallConfig() {
public Arity getArity() {
return delegate.getArity();
}
+
+ @Override
+ /**
+ * We override equals so that for method identity checks we treat delegating wrappers the same as the original
+ * methods. See e.g. RubyClass.finvokeChecked and its method_missing comparison.
+ */
+ public boolean equals(Object other) {
+ if (other instanceof DelegatingDynamicMethod) {
+ return delegate.equals(((DelegatingDynamicMethod)other).getDelegate());
+ }
+
+ return delegate.equals(other);
+ }
}
View
6 src/org/jruby/javasupport/util/RuntimeHelpers.java
@@ -444,7 +444,7 @@ public static DynamicMethod selectMethodMissing(ThreadContext context, IRubyObje
}
DynamicMethod methodMissing = receiver.getMetaClass().searchMethod("method_missing");
- if (methodMissing.isUndefined() || methodMissing == runtime.getDefaultMethodMissing()) {
+ if (methodMissing.isUndefined() || methodMissing.equals(runtime.getDefaultMethodMissing())) {
return selectInternalMM(runtime, visibility, callType);
}
return new MethodMissingMethod(methodMissing, callType);
@@ -458,7 +458,7 @@ public static DynamicMethod selectMethodMissing(ThreadContext context, RubyClass
}
DynamicMethod methodMissing = selfClass.searchMethod("method_missing");
- if (methodMissing.isUndefined() || methodMissing == runtime.getDefaultMethodMissing()) {
+ if (methodMissing.isUndefined() || methodMissing.equals(runtime.getDefaultMethodMissing())) {
return selectInternalMM(runtime, visibility, callType);
}
return new MethodMissingMethod(methodMissing, callType);
@@ -472,7 +472,7 @@ public static DynamicMethod selectMethodMissing(RubyClass selfClass, Visibility
}
DynamicMethod methodMissing = selfClass.searchMethod("method_missing");
- if (methodMissing.isUndefined() || methodMissing == runtime.getDefaultMethodMissing()) {
+ if (methodMissing.isUndefined() || methodMissing.equals(runtime.getDefaultMethodMissing())) {
return selectInternalMM(runtime, visibility, callType);
}
return new MethodMissingMethod(methodMissing, callType);
View
4 src/org/jruby/runtime/callsite/RespondToCallSite.java
@@ -71,7 +71,7 @@ protected IRubyObject cacheAndCall(IRubyObject caller, RubyClass selfType, Threa
// alternate logic to cache the result of respond_to if it's the standard one
// FIXME: 1.9's respond_to_missing breaks this, so we have to bail out
if (!context.runtime.is1_9() &&
- entry.method == context.getRuntime().getRespondToMethod()) {
+ entry.method.equals(context.getRuntime().getRespondToMethod())) {
String name = arg.asJavaString();
RespondToTuple tuple = recacheRespondsTo(entry, name, selfType, true, context);
respondToTuple = tuple;
@@ -95,7 +95,7 @@ protected IRubyObject cacheAndCall(IRubyObject caller, RubyClass selfType, Threa
// FIXME: 1.9's respond_to_missing breaks this, so we have to bail out
// FIXME: 1.9's respond_to_missing breaks this, so we have to bail out
if (!context.runtime.is1_9() &&
- entry.method == context.runtime.getRespondToMethod()) {
+ entry.method.equals(context.runtime.getRespondToMethod())) {
String name = arg0.asJavaString();
RespondToTuple tuple = recacheRespondsTo(entry, name, selfType, !arg1.isTrue(), context);
respondToTuple = tuple;
Please sign in to comment.
Something went wrong with that request. Please try again.