Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rework method invocation to properly super #5627

Merged
merged 46 commits into from Feb 26, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
b45eed9
First pass at using lookup to find proper super location.
headius Feb 5, 2019
af140a0
Enlist UnresolvedSuper in new-style method+impl lookup.
headius Feb 19, 2019
cce173f
Propagate frame class properly for Java-based methods.
headius Feb 19, 2019
53fc9d3
Merge branch 'master' into refinements2
headius Feb 20, 2019
c2ab3f6
Use factory for cache entries.
headius Feb 20, 2019
a41c844
Merge branch 'master' into refinements2
headius Feb 20, 2019
0a137bd
Merge branch 'master' into refinements2
headius Feb 20, 2019
adce679
Expand frame-class passing to more call paths.
headius Feb 20, 2019
5a922d9
Propagate frame class through indy and super sites.
headius Feb 20, 2019
4825abd
Merge branch 'master' into refinements2
headius Feb 20, 2019
6173e21
Restore old pre frame methods without frame class.
headius Feb 20, 2019
cbe478c
Fix instance and class super to pass frame class.
headius Feb 20, 2019
8a69eb6
Properly handle frame class for aliases.
headius Feb 20, 2019
be0ada0
SKip prepended roots when including a stack of modules.
headius Feb 21, 2019
2d0833a
Varargs calls and user-defined m_m were not passing frame class.
headius Feb 21, 2019
d6006f2
Pass frame class through into proc called from ProcMethod.
headius Feb 21, 2019
8f2e32d
Whitespace.
headius Feb 21, 2019
5bb3ee0
Prepend classes should delegate class variables like includes.
headius Feb 21, 2019
072b14a
Fix up alias frame class to not interfere with owner/impl.
headius Feb 21, 2019
1a0fbd7
Audit callers of DynamicMethod.call for frame class.
headius Feb 22, 2019
3e0ecb7
Get new method location before instance super, for prepends.
headius Feb 22, 2019
bbafaa8
More tweaks for Method/UnboundMethod frame class.
headius Feb 22, 2019
51d7981
Restore superClass null checks.
headius Feb 22, 2019
8358617
Fix respond_to_missing? logic in Method capture.
headius Feb 22, 2019
a71eaaa
Unresolves super should jump from refinement to refined class.
headius Feb 22, 2019
081230d
Naming cleanup.
headius Feb 22, 2019
2bf2413
Module#kind_of? and #<= should look for origin.
headius Feb 22, 2019
9db6733
Fix hierarchy search for include and prepend.
headius Feb 22, 2019
5ea603b
Revert "Fix hierarchy search for include and prepend."
headius Feb 22, 2019
6962ff9
Revert "Module#kind_of? and #<= should look for origin."
headius Feb 22, 2019
9ee799e
Whitespace
headius Feb 22, 2019
0939e63
Rework Module#<= to match MRI.
headius Feb 22, 2019
bc716bc
Rework Module#kind_of? logic to match MRI behavior.
headius Feb 22, 2019
d387f34
Tidy up.
headius Feb 22, 2019
2b5f93b
Tweak previously-included search logic to look below method loc.
headius Feb 22, 2019
3a56fcb
Perform implementer search for aliases with super.
headius Feb 23, 2019
db3cb30
Enlist public_send in the new order.
headius Feb 25, 2019
0e37a32
Spec for send/public_send invoking module methods w/ super.
headius Feb 25, 2019
f2b5c54
One more pass over all DynamicMethod.call overloads.
headius Feb 25, 2019
7850bd7
Spec for module method with super turned into proc.
headius Feb 25, 2019
416a1eb
Fix reversed logic for when to require implementer search.
headius Feb 25, 2019
6d23713
Make sure indy zsuper path is using zsuper logic all along.
headius Feb 25, 2019
6314a9d
Proper logic for preparing scope for flags.
headius Feb 25, 2019
fda7aa1
Tweak logic for searching hierarchy for prepend/include dups.
headius Feb 26, 2019
de58f76
More sanitary.
headius Feb 26, 2019
912d21f
Typo
olleolleolle Feb 26, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
11 changes: 7 additions & 4 deletions core/src/main/java/org/jruby/AbstractRubyMethod.java
Expand Up @@ -41,6 +41,7 @@
import org.jruby.runtime.PositionAware;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.runtime.callsite.CacheEntry;
import org.jruby.runtime.marshal.DataType;

/**
Expand All @@ -52,7 +53,9 @@ public abstract class AbstractRubyMethod extends RubyObject implements DataType
protected String methodName;
protected RubyModule originModule;
protected String originName;
protected CacheEntry entry;
protected DynamicMethod method;
protected RubyModule sourceModule;

protected AbstractRubyMethod(Ruby runtime, RubyClass rubyClass) {
super(runtime, rubyClass);
Expand Down Expand Up @@ -147,13 +150,13 @@ public IRubyObject parameters(ThreadContext context) {
protected IRubyObject super_method(ThreadContext context, IRubyObject receiver, RubyModule superClass) {
if (superClass == null) return context.nil;

DynamicMethod newMethod = superClass.searchMethod(methodName);
if (newMethod == UndefinedMethod.INSTANCE) return context.nil;
CacheEntry entry = superClass.searchWithCache(methodName);
if (entry.method == UndefinedMethod.INSTANCE) return context.nil;

if (receiver == null) {
return RubyUnboundMethod.newUnboundMethod(superClass, methodName, superClass, originName, newMethod);
return RubyUnboundMethod.newUnboundMethod(superClass, methodName, superClass, originName, entry);
} else {
return RubyMethod.newMethod(superClass, methodName, superClass, originName, newMethod, receiver);
return RubyMethod.newMethod(superClass, methodName, superClass, originName, entry, receiver);
}
}

Expand Down
10 changes: 10 additions & 0 deletions core/src/main/java/org/jruby/IncludedModule.java
Expand Up @@ -53,6 +53,16 @@ public IRubyObject id() {
return origin.id();
}

@Override
protected synchronized Map<String, IRubyObject> getClassVariables() {
return origin.getClassVariables();
}

@Override
protected Map<String, IRubyObject> getClassVariablesForRead() {
return origin.getClassVariablesForRead();
}

/** The module to which this include origins. */
protected final RubyModule origin;
}
10 changes: 0 additions & 10 deletions core/src/main/java/org/jruby/IncludedModuleWrapper.java
Expand Up @@ -115,16 +115,6 @@ public Map<String, DynamicMethod> getMethodsForWrite() {
return origin.getMethodsForWrite();
}

@Override
protected synchronized Map<String, IRubyObject> getClassVariables() {
return origin.getClassVariables();
}

@Override
protected Map<String, IRubyObject> getClassVariablesForRead() {
return origin.getClassVariablesForRead();
}

@Override
protected boolean variableTableContains(String name) {
return origin.variableTableContains(name);
Expand Down
14 changes: 6 additions & 8 deletions core/src/main/java/org/jruby/PrependedModule.java
Expand Up @@ -44,16 +44,14 @@
*/
public class PrependedModule extends IncludedModule {

public PrependedModule(Ruby runtime, RubyClass superClass, RubyModule origin) {
super(runtime, superClass, origin);
this.methods = origin.methods;
origin.methods = Collections.EMPTY_MAP;
origin.methodLocation = this;
public PrependedModule(Ruby runtime, RubyClass superClass, RubyModule klass) {
super(runtime, superClass, klass);
this.methods = klass.methods;
klass.methods = Collections.EMPTY_MAP;
klass.methodLocation = this;
for (Map.Entry<String, DynamicMethod> entry : methods.entrySet()) {
DynamicMethod method = entry.getValue();
method.setImplementationClass(this);
method.setDefinedClass(origin);
if (moveRefinedMethod(entry.getKey(), method, origin)) {
if (moveRefinedMethod(entry.getKey(), method, klass)) {
methods.remove(entry.getKey());
}
}
Expand Down
19 changes: 11 additions & 8 deletions core/src/main/java/org/jruby/RubyBasicObject.java
Expand Up @@ -34,6 +34,7 @@
import org.jruby.runtime.CallSite;
import org.jruby.runtime.JavaSites;
import org.jruby.runtime.JavaSites.BasicObjectSites;
import org.jruby.runtime.callsite.CacheEntry;
import org.jruby.runtime.ivars.VariableAccessor;
import java.io.IOException;
import java.io.ObjectInputStream;
Expand Down Expand Up @@ -586,7 +587,8 @@ public final RubyClass getType() {
@Override
public final boolean respondsTo(String name) {
final Ruby runtime = getRuntime();
final DynamicMethod respondTo = getMetaClass().searchMethod("respond_to?");
final CacheEntry entry = getMetaClass().searchWithCache("respond_to?");
final DynamicMethod respondTo = entry.method;

// fastest path; builtin respond_to? and respond_to_missing? so we just check isMethodBound
if ( respondTo.equals(runtime.getRespondToMethod()) &&
Expand All @@ -609,14 +611,14 @@ public final boolean respondsTo(String name) {
final Arity arity = respondTo.getArity();
if ( arity.isFixed() ) {
if ( arity.required() == 1 ) {
return respondTo.call(context, this, metaClass, respondName, mname).isTrue();
return respondTo.call(context, this, entry.sourceModule, respondName, mname).isTrue();
}
if ( arity.required() != 2 ) {
throw runtime.newArgumentError(str(runtime, ids(runtime, respondName), " must accept 1 or 2 arguments (requires " + arity.getValue() + ")"));
}
}

return respondTo.call(context, this, metaClass, respondName, mname, runtime.getTrue()).isTrue();
return respondTo.call(context, this, entry.sourceModule, respondName, mname, runtime.getTrue()).isTrue();
}

/**
Expand All @@ -632,11 +634,12 @@ public final boolean respondsToMissing(String name) {
*/
@Override
public final boolean respondsToMissing(String name, boolean incPrivate) {
DynamicMethod method = getMetaClass().searchMethod("respond_to_missing?");
CacheEntry entry = getMetaClass().searchWithCache("respond_to_missing?");
DynamicMethod method = entry.method;
// perhaps should try a smart version as for respondsTo above?
if ( method.isUndefined() ) return false;
final Ruby runtime = getRuntime();
return method.call(runtime.getCurrentContext(), this, getMetaClass(),
return method.call(runtime.getCurrentContext(), this, entry.sourceModule,
"respond_to_missing?", runtime.newSymbol(name), runtime.newBoolean(incPrivate)
).isTrue();
}
Expand Down Expand Up @@ -2492,9 +2495,9 @@ public IRubyObject singleton_method(IRubyObject name) {
final String methodName = symbol.idString();
final RubyClass klass = metaClass;
if (klass.isSingleton()) {
DynamicMethod method = klass.searchMethod(methodName);
if (klass == method.getDefinedClass()) { // ! method.isUndefined()
AbstractRubyMethod newMethod = RubyMethod.newMethod(klass, methodName, klass, methodName, method, this);
CacheEntry entry = klass.searchWithCache(methodName);
if (klass == entry.method.getDefinedClass()) { // ! method.isUndefined()
AbstractRubyMethod newMethod = RubyMethod.newMethod(klass, methodName, klass, methodName, entry, this);
newMethod.infectBy(this);
return newMethod;
}
Expand Down