Skip to content

Commit

Permalink
Set thread-local call type and visibility around all m_m dispatch.
Browse files Browse the repository at this point in the history
This also simplifies the pre-built "visibility m_m's" and
eliminates a few inner classes.

Fixes #540.
  • Loading branch information
headius committed May 6, 2015
1 parent b50660e commit 2799836
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 44 deletions.
53 changes: 14 additions & 39 deletions core/src/main/java/org/jruby/RubyKernel.java
Expand Up @@ -96,18 +96,22 @@
public class RubyKernel {
public final static Class<?> IRUBY_OBJECT = IRubyObject.class;

public static abstract class MethodMissingMethod extends JavaMethodNBlock {
public MethodMissingMethod(RubyModule implementationClass) {
public static class MethodMissingMethod extends JavaMethodNBlock {
private final Visibility visibility;
private final CallType callType;

public MethodMissingMethod(RubyModule implementationClass, Visibility visibility, CallType callType) {
super(implementationClass, Visibility.PRIVATE, CallConfiguration.FrameFullScopeNone);

this.callType = callType;
this.visibility = visibility;
}

@Override
public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule clazz, String name, IRubyObject[] args, Block block) {
return methodMissing(context, self, clazz, name, args, block);
return RubyKernel.methodMissing(context, self, name, visibility, callType, args, block);
}

public abstract IRubyObject methodMissing(ThreadContext context, IRubyObject self, RubyModule clazz, String name, IRubyObject[] args, Block block);

}
public static RubyModule createKernelModule(Ruby runtime) {
RubyModule module = runtime.defineModule("Kernel");
Expand All @@ -117,40 +121,11 @@ public static RubyModule createKernelModule(Ruby runtime) {

module.setFlag(RubyObject.USER7_F, false); //Kernel is the only Module that doesn't need an implementor

runtime.setPrivateMethodMissing(new MethodMissingMethod(module) {
@Override
public IRubyObject methodMissing(ThreadContext context, IRubyObject self, RubyModule clazz, String name, IRubyObject[] args, Block block) {
return RubyKernel.methodMissing(context, self, name, PRIVATE, CallType.NORMAL, args, block);
}
});

runtime.setProtectedMethodMissing(new MethodMissingMethod(module) {
@Override
public IRubyObject methodMissing(ThreadContext context, IRubyObject self, RubyModule clazz, String name, IRubyObject[] args, Block block) {
return RubyKernel.methodMissing(context, self, name, PROTECTED, CallType.NORMAL, args, block);
}
});

runtime.setVariableMethodMissing(new MethodMissingMethod(module) {
@Override
public IRubyObject methodMissing(ThreadContext context, IRubyObject self, RubyModule clazz, String name, IRubyObject[] args, Block block) {
return RubyKernel.methodMissing(context, self, name, PUBLIC, CallType.VARIABLE, args, block);
}
});

runtime.setSuperMethodMissing(new MethodMissingMethod(module) {
@Override
public IRubyObject methodMissing(ThreadContext context, IRubyObject self, RubyModule clazz, String name, IRubyObject[] args, Block block) {
return RubyKernel.methodMissing(context, self, name, PUBLIC, CallType.SUPER, args, block);
}
});

runtime.setNormalMethodMissing(new MethodMissingMethod(module) {
@Override
public IRubyObject methodMissing(ThreadContext context, IRubyObject self, RubyModule clazz, String name, IRubyObject[] args, Block block) {
return RubyKernel.methodMissing(context, self, name, PUBLIC, CallType.NORMAL, args, block);
}
});
runtime.setPrivateMethodMissing(new MethodMissingMethod(module, PRIVATE, CallType.NORMAL));
runtime.setProtectedMethodMissing(new MethodMissingMethod(module, PROTECTED, CallType.NORMAL));
runtime.setVariableMethodMissing(new MethodMissingMethod(module, PUBLIC, CallType.VARIABLE));
runtime.setSuperMethodMissing(new MethodMissingMethod(module, PUBLIC, CallType.SUPER));
runtime.setNormalMethodMissing(new MethodMissingMethod(module, PUBLIC, CallType.NORMAL));

recacheBuiltinMethods(runtime);

Expand Down
12 changes: 7 additions & 5 deletions core/src/main/java/org/jruby/runtime/Helpers.java
Expand Up @@ -394,7 +394,7 @@ public static DynamicMethod selectMethodMissing(ThreadContext context, IRubyObje
if (methodMissing.isUndefined() || methodMissing.equals(runtime.getDefaultMethodMissing())) {
return selectInternalMM(runtime, visibility, callType);
}
return new MethodMissingMethod(methodMissing, callType);
return new MethodMissingMethod(methodMissing, visibility, callType);
}

public static DynamicMethod selectMethodMissing(ThreadContext context, RubyClass selfClass, Visibility visibility, String name, CallType callType) {
Expand All @@ -408,7 +408,7 @@ public static DynamicMethod selectMethodMissing(ThreadContext context, RubyClass
if (methodMissing.isUndefined() || methodMissing.equals(runtime.getDefaultMethodMissing())) {
return selectInternalMM(runtime, visibility, callType);
}
return new MethodMissingMethod(methodMissing, callType);
return new MethodMissingMethod(methodMissing, visibility, callType);
}

public static DynamicMethod selectMethodMissing(RubyClass selfClass, Visibility visibility, String name, CallType callType) {
Expand All @@ -422,7 +422,7 @@ public static DynamicMethod selectMethodMissing(RubyClass selfClass, Visibility
if (methodMissing.isUndefined() || methodMissing.equals(runtime.getDefaultMethodMissing())) {
return selectInternalMM(runtime, visibility, callType);
}
return new MethodMissingMethod(methodMissing, callType);
return new MethodMissingMethod(methodMissing, visibility, callType);
}

public static final Map<String, String> map(String... keyValues) {
Expand All @@ -440,15 +440,17 @@ public static IRubyObject handleNextJump(ThreadContext context, JumpException.Ne
private static class MethodMissingMethod extends DynamicMethod {
private final DynamicMethod delegate;
private final CallType lastCallStatus;
private final Visibility lastVisibility;

public MethodMissingMethod(DynamicMethod delegate, CallType lastCallStatus) {
public MethodMissingMethod(DynamicMethod delegate, Visibility lastVisibility, CallType lastCallStatus) {
this.delegate = delegate;
this.lastCallStatus = lastCallStatus;
this.lastVisibility = lastVisibility;
}

@Override
public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule clazz, String name, IRubyObject[] args, Block block) {
context.setLastCallStatus(lastCallStatus);
context.setLastCallStatusAndVisibility(lastCallStatus, lastVisibility);
return this.delegate.call(context, self, clazz, "method_missing", prepareMethodMissingArgs(args, context, name), block);
}

Expand Down

0 comments on commit 2799836

Please sign in to comment.