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

Commits on Sep 15, 2014

  1. Copy the full SHA
    95b3d8b View commit details
  2. Copy the full SHA
    158e0dd View commit details
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
package org.jruby.ir.instructions;

import org.jruby.RubyClass;
import org.jruby.RubyModule;
import org.jruby.internal.runtime.methods.DynamicMethod;
import org.jruby.internal.runtime.methods.UndefinedMethod;
import org.jruby.ir.IRVisitor;
import org.jruby.ir.Operation;
import org.jruby.ir.operands.MethAddr;
import org.jruby.ir.operands.Operand;
import org.jruby.ir.operands.Variable;
import org.jruby.ir.runtime.IRRuntimeHelpers;
import org.jruby.ir.transformations.inlining.InlinerInfo;
import org.jruby.parser.StaticScope;
import org.jruby.runtime.*;
@@ -46,11 +44,7 @@ public Object interpret(ThreadContext context, StaticScope currScope, DynamicSco
Block block = prepareBlock(context, self, currScope, currDynScope, temp);
String methodName = methAddr.getName();
RubyModule definingModule = (RubyModule) getDefiningModule().retrieve(context, self, currScope, currDynScope, temp);
RubyClass superClass = definingModule.getMetaClass().getSuperClass();
DynamicMethod method = superClass != null ? superClass.searchMethod(methodName) : UndefinedMethod.INSTANCE;
Object rVal = method.isUndefined() ? Helpers.callMethodMissing(context, self, method.getVisibility(), methodName, CallType.SUPER, args, block)
: method.call(context, self, superClass, methodName, args, block);
return hasUnusedResult() ? null : rVal;
return IRRuntimeHelpers.classSuper(context, self, args, block, methodName, definingModule);
}

@Override
Original file line number Diff line number Diff line change
@@ -13,6 +13,7 @@
import org.jruby.runtime.DynamicScope;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.runtime.opto.ConstantCache;
import org.jruby.runtime.opto.Invalidator;

import java.util.Map;
@@ -28,9 +29,7 @@ public class LexicalSearchConstInstr extends Instr implements ResultInstr, Fixed
private Variable result;

// Constant caching
private volatile transient Object cachedConstant = null;
private Object generation = -1;
private Invalidator invalidator;
private volatile transient ConstantCache cache;

public LexicalSearchConstInstr(Variable result, Operand definingScope, String constName) {
super(Operation.LEXICAL_SEARCH_CONST);
@@ -80,44 +79,34 @@ public Instr cloneForInlining(InlinerInfo ii) {
return new LexicalSearchConstInstr(ii.getRenamedVariable(result), definingScope.cloneForInlining(ii), constName);
}

private Object cache(ThreadContext context, StaticScope currScope, DynamicScope currDynScope, IRubyObject self, Object[] temp, Ruby runtime, Object constant) {
private Object cache(ThreadContext context, StaticScope currScope, DynamicScope currDynScope, IRubyObject self, Object[] temp) {
StaticScope staticScope = (StaticScope) definingScope.retrieve(context, self, currScope, currDynScope, temp);
RubyModule object = runtime.getObject();
// SSS FIXME: IRManager objects dont have a static-scope yet, so this hack of looking up the module right away
// This IR needs fixing!
constant = (staticScope == null) ? object.getConstant(constName) : staticScope.getConstantInner(constName);

// CON FIXME: Removed SSS hack for IRManager objects not having a static scope, so we can find and fix

IRubyObject constant = staticScope.getConstantInner(constName);

if (constant == null) {
constant = UndefinedValue.UNDEFINED;
} else {
// recache
generation = invalidator(runtime).getData();
cachedConstant = constant;
Invalidator invalidator = context.runtime.getConstantInvalidator(constName);
cache = new ConstantCache(constant, invalidator.getData(), invalidator);
}
return constant;
}

private boolean isCached(Ruby runtime, Object value) {
return value != null && generation == invalidator(runtime).getData();
return constant;
}

@Override
public Object interpret(ThreadContext context, StaticScope currScope, DynamicScope currDynScope, IRubyObject self, Object[] temp) {
Ruby runtime = context.runtime;
Object constant = cachedConstant; // Store to temp so it does null out on us mid-stream
if (!isCached(runtime, constant)) constant = cache(context, currScope, currDynScope, self, temp, runtime, constant);
ConstantCache cache = this.cache; // Store to temp so it does null out on us mid-stream
if (!ConstantCache.isCached(cache)) return cache(context, currScope, currDynScope, self, temp);

return constant;
return cache.value;
}

@Override
public void visit(IRVisitor visitor) {
visitor.LexicalSearchConstInstr(this);
}

private Invalidator invalidator(Ruby runtime) {
if (invalidator == null) {
invalidator = runtime.getConstantInvalidator(constName);
}
return invalidator;
}
}
8 changes: 8 additions & 0 deletions core/src/main/java/org/jruby/ir/runtime/IRRuntimeHelpers.java
Original file line number Diff line number Diff line change
@@ -784,4 +784,12 @@ public static IRubyObject setCapturedVar(ThreadContext context, IRubyObject matc

return val;
}

public static Object classSuper(ThreadContext context, IRubyObject self, IRubyObject[] args, Block block, String methodName, RubyModule definingModule) {
RubyClass superClass = definingModule.getMetaClass().getSuperClass();
DynamicMethod method = superClass != null ? superClass.searchMethod(methodName) : UndefinedMethod.INSTANCE;
Object rVal = method.isUndefined() ? Helpers.callMethodMissing(context, self, method.getVisibility(), methodName, CallType.SUPER, args, block)
: method.call(context, self, superClass, methodName, args, block);
return rVal;
}
}
82 changes: 54 additions & 28 deletions core/src/main/java/org/jruby/ir/targets/Bootstrap.java
Original file line number Diff line number Diff line change
@@ -253,8 +253,10 @@ public static CallSite invokeClassSuper(Lookup lookup, String name, MethodType t
return new ConstantCallSite(handle);
}

public static CallSite invokeInstanceSuper(Lookup lookup, String name, MethodType type, int hasUnusedResult) {
String superName = JavaNameMangler.demangleMethodName(name.split(":")[1]);
public static CallSite invokeSuper(Lookup lookup, String name, MethodType type, int hasUnusedResult) {
String[] targetAndMethod = name.split(":");
String superName = JavaNameMangler.demangleMethodName(targetAndMethod[1]);

InvokeSite site = new InvokeSite(type, name, CallType.SUPER);
MethodHandle handle;

@@ -270,7 +272,7 @@ public static CallSite invokeInstanceSuper(Lookup lookup, String name, MethodTyp
.collect("args", "arg[0-9]+");
}

handle = binder.invokeStaticQuiet(lookup, Bootstrap.class, "invokeInstanceSuper").handle();
handle = binder.invokeStaticQuiet(lookup, Bootstrap.class, targetAndMethod[0]).handle();

site.setTarget(handle);

@@ -301,23 +303,7 @@ public static CallSite searchConst(Lookup lookup, String name, MethodType type,
.from(lookup, type)
.append(site, constName.intern())
.append(noPrivateConsts == 0 ? false : true)
.invokeStaticQuiet(LOOKUP, Bootstrap.class, "searchConst");

site.setTarget(handle);

return site;
}

public static CallSite inheritanceSearchConst(Lookup lookup, String name, MethodType type, int noPrivateConsts) {
MutableCallSite site = new MutableCallSite(type);
String[] bits = name.split(":");
String constName = bits[1];

MethodHandle handle = Binder
.from(lookup, type)
.append(site, constName.intern())
.append(noPrivateConsts == 0 ? false : true)
.invokeStaticQuiet(LOOKUP, Bootstrap.class, "inheritanceSearchConst");
.invokeStaticQuiet(LOOKUP, Bootstrap.class, bits[0]);

site.setTarget(handle);

@@ -364,8 +350,8 @@ public static Handle invokeClassSuper() {
return new Handle(Opcodes.H_INVOKESTATIC, p(Bootstrap.class), "invokeClassSuper", sig(CallSite.class, Lookup.class, String.class, MethodType.class));
}

public static Handle invokeInstanceSuper() {
return new Handle(Opcodes.H_INVOKESTATIC, p(Bootstrap.class), "invokeInstanceSuper", sig(CallSite.class, Lookup.class, String.class, MethodType.class, int.class));
public static Handle invokeSuper() {
return new Handle(Opcodes.H_INVOKESTATIC, p(Bootstrap.class), "invokeSuper", sig(CallSite.class, Lookup.class, String.class, MethodType.class, int.class));
}

public static Handle invokeFixnumOp() {
@@ -384,10 +370,6 @@ public static Handle searchConst() {
return new Handle(Opcodes.H_INVOKESTATIC, p(Bootstrap.class), "searchConst", sig(CallSite.class, Lookup.class, String.class, MethodType.class, int.class));
}

public static Handle inheritanceSearchConst() {
return new Handle(Opcodes.H_INVOKESTATIC, p(Bootstrap.class), "inheritanceSearchConst", sig(CallSite.class, Lookup.class, String.class, MethodType.class, int.class));
}

public static RubyString string(ByteList value, ThreadContext context) {
return RubyString.newStringShared(context.runtime, value);
}
@@ -661,6 +643,7 @@ public static IRubyObject invokeClassSuper(String methodName, ThreadContext cont

public static IRubyObject invokeInstanceSuper(InvokeSite site, String methodName, boolean hasUnusedResult, ThreadContext context, IRubyObject caller, IRubyObject self, RubyClass definingModule, IRubyObject[] args, Block block) throws Throwable {
// TODO: get rid of caller
// TODO: caching
RubyClass superClass = definingModule.getSuperClass();
DynamicMethod method = superClass != null ? superClass.searchMethod(methodName) : UndefinedMethod.INSTANCE;
IRubyObject rVal = method.isUndefined() ? Helpers.callMethodMissing(context, self, method.getVisibility(), methodName, CallType.SUPER, args, block)
@@ -670,13 +653,34 @@ public static IRubyObject invokeInstanceSuper(InvokeSite site, String methodName

public static IRubyObject invokeInstanceSuper(InvokeSite site, String methodName, boolean hasUnusedResult, ThreadContext context, IRubyObject caller, IRubyObject self, RubyClass definingModule, Block block) throws Throwable {
// TODO: get rid of caller
// TODO: caching
RubyClass superClass = definingModule.getSuperClass();
DynamicMethod method = superClass != null ? superClass.searchMethod(methodName) : UndefinedMethod.INSTANCE;
IRubyObject rVal = method.isUndefined() ? Helpers.callMethodMissing(context, self, method.getVisibility(), methodName, CallType.SUPER, IRubyObject.NULL_ARRAY, block)
: method.call(context, self, superClass, methodName, IRubyObject.NULL_ARRAY, block);
return hasUnusedResult ? null : rVal;
}

public static IRubyObject invokeClassSuper(InvokeSite site, String methodName, boolean hasUnusedResult, ThreadContext context, IRubyObject caller, IRubyObject self, RubyClass definingModule, IRubyObject[] args, Block block) throws Throwable {
// TODO: get rid of caller
// TODO: caching
RubyClass superClass = definingModule.getMetaClass().getSuperClass();
DynamicMethod method = superClass != null ? superClass.searchMethod(methodName) : UndefinedMethod.INSTANCE;
IRubyObject rVal = method.isUndefined() ? Helpers.callMethodMissing(context, self, method.getVisibility(), methodName, CallType.SUPER, args, block)
: method.call(context, self, superClass, methodName, args, block);
return hasUnusedResult ? null : rVal;
}

public static IRubyObject invokeClassSuper(InvokeSite site, String methodName, boolean hasUnusedResult, ThreadContext context, IRubyObject caller, IRubyObject self, RubyClass definingModule, Block block) throws Throwable {
// TODO: get rid of caller
// TODO: caching
RubyClass superClass = definingModule.getMetaClass().getSuperClass();
DynamicMethod method = superClass != null ? superClass.searchMethod(methodName) : UndefinedMethod.INSTANCE;
IRubyObject rVal = method.isUndefined() ? Helpers.callMethodMissing(context, self, method.getVisibility(), methodName, CallType.SUPER, IRubyObject.NULL_ARRAY, block)
: method.call(context, self, superClass, methodName, IRubyObject.NULL_ARRAY, block);
return hasUnusedResult ? null : rVal;
}

public static IRubyObject attrAssign(InvokeSite site, ThreadContext context, IRubyObject caller, IRubyObject self, IRubyObject arg0) throws Throwable {
RubyClass selfClass = self.getMetaClass();
String methodName = site.name;
@@ -1291,8 +1295,30 @@ public static IRubyObject inheritanceSearchConst(ThreadContext context, IRubyObj
return constant;
}

///////////////////////////////////////////////////////////////////////////
// COMPLETED WORK BELOW
public static IRubyObject lexicalSearchConst(ThreadContext context, StaticScope scope, MutableCallSite site, String constName, boolean noPrivateConsts) throws Throwable {
Ruby runtime = context.runtime;

IRubyObject constant = scope.getConstantInner(constName);

if (constant == null) {
constant = UndefinedValue.UNDEFINED;
}

SwitchPoint switchPoint = (SwitchPoint)runtime.getConstantInvalidator(constName).getData();

// bind constant until invalidated
MethodHandle target = Binder.from(site.type())
.drop(0, 2)
.constant(constant);
MethodHandle fallback = Binder.from(site.type())
.append(site, constName)
.append(noPrivateConsts)
.invokeStatic(LOOKUP, Bootstrap.class, "lexicalSearchConst");

site.setTarget(switchPoint.guardWithTest(target, fallback));

return constant;
}

///////////////////////////////////////////////////////////////////////////
// Symbol binding
18 changes: 11 additions & 7 deletions core/src/main/java/org/jruby/ir/targets/IRBytecodeAdapter.java
Original file line number Diff line number Diff line change
@@ -166,19 +166,19 @@ public void invokeSelf(String name, int arity, boolean hasClosure) {
}
}

public void invokeClassSuper(String name, int arity, boolean hasClosure) {
public void invokeInstanceSuper(String name, boolean hasUnusedResult, int arity, boolean hasClosure) {
if (hasClosure) {
adapter.invokedynamic("invokeClassSuper:" + JavaNameMangler.mangleMethodName(name), sig(JVM.OBJECT, params(ThreadContext.class, JVM.OBJECT, JVM.OBJECT, JVM.OBJECT, arity, Block.class)), Bootstrap.invokeSelf());
adapter.invokedynamic("invokeInstanceSuper:" + JavaNameMangler.mangleMethodName(name), sig(JVM.OBJECT, params(ThreadContext.class, JVM.OBJECT, JVM.OBJECT, RubyClass.class, JVM.OBJECT, arity, Block.class)), Bootstrap.invokeSuper(), hasUnusedResult ? 1 : 0);
} else {
adapter.invokedynamic("invokeClassSuper:" + JavaNameMangler.mangleMethodName(name), sig(JVM.OBJECT, params(ThreadContext.class, JVM.OBJECT, JVM.OBJECT, JVM.OBJECT, arity)), Bootstrap.invokeSelf());
adapter.invokedynamic("invokeInstanceSuper:" + JavaNameMangler.mangleMethodName(name), sig(JVM.OBJECT, params(ThreadContext.class, JVM.OBJECT, JVM.OBJECT, RubyClass.class, JVM.OBJECT, arity)), Bootstrap.invokeSuper(), hasUnusedResult ? 1 : 0);
}
}

public void invokeInstanceSuper(String name, boolean hasUnusedResult, int arity, boolean hasClosure) {
public void invokeClassSuper(String name, boolean hasUnusedResult, int arity, boolean hasClosure) {
if (hasClosure) {
adapter.invokedynamic("invokeInstanceSuper:" + JavaNameMangler.mangleMethodName(name), sig(JVM.OBJECT, params(ThreadContext.class, JVM.OBJECT, JVM.OBJECT, RubyClass.class, JVM.OBJECT, arity, Block.class)), Bootstrap.invokeInstanceSuper(), hasUnusedResult ? 1 : 0);
adapter.invokedynamic("invokeClassSuper:" + JavaNameMangler.mangleMethodName(name), sig(JVM.OBJECT, params(ThreadContext.class, JVM.OBJECT, JVM.OBJECT, RubyClass.class, JVM.OBJECT, arity, Block.class)), Bootstrap.invokeSuper(), hasUnusedResult ? 1 : 0);
} else {
adapter.invokedynamic("invokeInstanceSuper:" + JavaNameMangler.mangleMethodName(name), sig(JVM.OBJECT, params(ThreadContext.class, JVM.OBJECT, JVM.OBJECT, RubyClass.class, JVM.OBJECT, arity)), Bootstrap.invokeInstanceSuper(), hasUnusedResult ? 1 : 0);
adapter.invokedynamic("invokeClassSuper:" + JavaNameMangler.mangleMethodName(name), sig(JVM.OBJECT, params(ThreadContext.class, JVM.OBJECT, JVM.OBJECT, RubyClass.class, JVM.OBJECT, arity)), Bootstrap.invokeSuper(), hasUnusedResult ? 1 : 0);
}
}

@@ -211,7 +211,11 @@ public void searchConst(String name, boolean noPrivateConsts) {
}

public void inheritanceSearchConst(String name, boolean noPrivateConsts) {
adapter.invokedynamic("inheritanceSearchConst:" + name, sig(JVM.OBJECT, params(ThreadContext.class, IRubyObject.class)), Bootstrap.inheritanceSearchConst(), noPrivateConsts?1:0);
adapter.invokedynamic("inheritanceSearchConst:" + name, sig(JVM.OBJECT, params(ThreadContext.class, IRubyObject.class)), Bootstrap.searchConst(), noPrivateConsts?1:0);
}

public void lexicalSearchConst(String name) {
adapter.invokedynamic("lexicalSearchConst:" + name, sig(JVM.OBJECT, params(ThreadContext.class, StaticScope.class)), Bootstrap.searchConst(), 0);
}

public void goTo(org.objectweb.asm.Label label) {
17 changes: 12 additions & 5 deletions core/src/main/java/org/jruby/ir/targets/JVMVisitor.java
Original file line number Diff line number Diff line change
@@ -773,17 +773,19 @@ public void CheckArityInstr(CheckArityInstr checkarityinstr) {

@Override
public void ClassSuperInstr(ClassSuperInstr classsuperinstr) {
// disable for now
super.ClassSuperInstr(classsuperinstr);

// TODO: Nearly identical to InstanceSuperInstr
IRBytecodeAdapter m = jvmMethod();
String name = classsuperinstr.getMethodAddr().getName();
Operand[] args = classsuperinstr.getCallArgs();

m.loadContext();
m.loadSelf(); // TODO: get rid of caller
m.loadSelf();
visit(classsuperinstr.getDefiningModule());

// TODO: CON: is this safe?
jvmAdapter().checkcast(p(RubyClass.class));

for (int i = 0; i < args.length; i++) {
Operand operand = args[i];
visit(operand);
@@ -799,7 +801,7 @@ public void ClassSuperInstr(ClassSuperInstr classsuperinstr) {
m.adapter.getstatic(p(Block.class), "NULL_BLOCK", ci(Block.class));
}

m.invokeClassSuper(name, args.length, hasClosure);
m.invokeClassSuper(name, classsuperinstr.hasUnusedResult(), args.length, hasClosure);

jvmStoreLocal(classsuperinstr.getResult());
}
@@ -1204,7 +1206,12 @@ public void LabelInstr(LabelInstr labelinstr) {

@Override
public void LexicalSearchConstInstr(LexicalSearchConstInstr lexicalsearchconstinstr) {
super.LexicalSearchConstInstr(lexicalsearchconstinstr); //To change body of overridden methods use File | Settings | File Templates.
jvmMethod().loadContext();
visit(lexicalsearchconstinstr.getDefiningScope());

jvmMethod().lexicalSearchConst(lexicalsearchconstinstr.getConstName());

jvmStoreLocal(lexicalsearchconstinstr.getResult());
}

@Override