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

Commits on Mar 30, 2015

  1. Copy the full SHA
    8c614e6 View commit details
  2. Copy the full SHA
    86c68cc View commit details
  3. Copy the full SHA
    cb72352 View commit details
Showing with 117 additions and 53 deletions.
  1. +97 −43 core/src/main/java/org/jruby/internal/runtime/methods/CompiledIRMethod.java
  2. +20 −10 core/src/main/java/org/jruby/ir/targets/IRBytecodeAdapter6.java
Original file line number Diff line number Diff line change
@@ -28,6 +28,8 @@ public class CompiledIRMethod extends JavaMethod implements MethodArgs2, Positio
protected final IRScope method;
private final Arity arity;
private String[] parameterList;
private final StaticScope staticScope;
private final boolean hasExplicitCallProtocol;

public CompiledIRMethod(MethodHandle variable, IRScope method, Visibility visibility, RubyModule implementationClass) {
this(variable, null, -1, method, visibility, implementationClass);
@@ -41,6 +43,8 @@ public CompiledIRMethod(MethodHandle variable, MethodHandle specific, int specif
this.method = method;
this.method.getStaticScope().determineModule();
this.arity = calculateArity();
this.staticScope = method.getStaticScope();
this.hasExplicitCallProtocol = method.hasExplicitCallProtocol();

setHandle(variable);
}
@@ -80,105 +84,155 @@ public Arity getArity() {
}

protected void post(ThreadContext context) {
if (!method.hasExplicitCallProtocol()) {
// update call stacks (pop: ..)
context.popFrame();
context.postMethodScopeOnly();
}
// update call stacks (pop: ..)
context.postMethodFrameAndScope();
}

protected void pre(ThreadContext context, IRubyObject self, String name, Block block) {
if (!method.hasExplicitCallProtocol()) {
// update call stacks (push: frame, class, scope, etc.)
RubyModule implementationClass = getImplementationClass();
context.preMethodFrameAndScope(implementationClass, name, self, block, method.getStaticScope());
// FIXME: does not seem right to use this method's visibility as current!!!
// See also PushFrame instruction in org.jruby.ir.targets.JVMVisitor
context.setCurrentVisibility(Visibility.PUBLIC);
}
protected void pre(ThreadContext context, StaticScope staticScope, RubyModule implementationClass, IRubyObject self, String name, Block block) {
// update call stacks (push: frame, class, scope, etc.)
context.preMethodFrameAndScope(implementationClass, name, self, block, staticScope);
context.setCurrentVisibility(Visibility.PUBLIC);
}

@Override
public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule clazz, String name, IRubyObject[] args, Block block) {
pre(context, self, name, block);

try {
return (IRubyObject)this.variable.invokeExact(context, method.getStaticScope(), self, args, block, implementationClass, name);
if (!hasExplicitCallProtocol) return callNoProtocol(context, self, clazz, name, args, block);

return (IRubyObject)this.variable.invokeExact(context, staticScope, self, args, block, implementationClass, name);
} catch (Throwable t) {
Helpers.throwException(t);
// not reached
return null;
} finally {
post(context);
}
}

@Override
public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule clazz, String name, Block block) {
if (specificArity != 0) return call(context, self, clazz, name, IRubyObject.NULL_ARRAY, block);
pre(context, self, name, block);

try {
return (IRubyObject)this.specific.invokeExact(context, method.getStaticScope(), self, block, implementationClass, name);
if (specificArity != 0) return call(context, self, clazz, name, IRubyObject.NULL_ARRAY, block);

if (!hasExplicitCallProtocol) return callNoProtocol(context, self, clazz, name, block);

return (IRubyObject)this.specific.invokeExact(context, staticScope, self, block, implementationClass, name);
} catch (Throwable t) {
Helpers.throwException(t);
// not reached
return null;
} finally {
post(context);
}
}

@Override
public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule clazz, String name, IRubyObject arg0, Block block) {
if (specificArity != 1) return call(context, self, clazz, name, Helpers.arrayOf(arg0), block);
pre(context, self, name, block);

try {
return (IRubyObject)this.specific.invokeExact(context, method.getStaticScope(), self, arg0, block, implementationClass, name);
if (!hasExplicitCallProtocol) return callNoProtocol(context, self, clazz, name, arg0, block);

if (specificArity != 1) return call(context, self, clazz, name, new IRubyObject[]{arg0}, block);

return (IRubyObject)this.specific.invokeExact(context, staticScope, self, arg0, block, implementationClass, name);
} catch (Throwable t) {
Helpers.throwException(t);
// not reached
return null;
} finally {
post(context);
}
}

@Override
public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule clazz, String name, IRubyObject arg0, IRubyObject arg1, Block block) {
if (specificArity != 2) return call(context, self, clazz, name, Helpers.arrayOf(arg0, arg1), block);
pre(context, self, name, block);

try {
return (IRubyObject)this.specific.invokeExact(context, method.getStaticScope(), self, arg0, arg1, block, implementationClass, name);
if (!hasExplicitCallProtocol) return callNoProtocol(context, self, clazz, name, arg0, arg1, block);

if (specificArity != 2) return call(context, self, clazz, name, new IRubyObject[] {arg0, arg1}, block);

return (IRubyObject)this.specific.invokeExact(context, staticScope, self, arg0, arg1, block, implementationClass, name);
} catch (Throwable t) {
Helpers.throwException(t);
// not reached
return null;
} finally {
post(context);
}
}

@Override
public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule clazz, String name, IRubyObject arg0, IRubyObject arg1, IRubyObject arg2, Block block) {
if (specificArity != 3) return call(context, self, clazz, name, Helpers.arrayOf(arg0, arg1, arg2), block);
pre(context, self, name, block);

try {
return (IRubyObject)this.specific.invokeExact(context, method.getStaticScope(), self, arg0, arg1, arg2, block, implementationClass, name);
if (!hasExplicitCallProtocol) return callNoProtocol(context, self, clazz, name, arg0, arg1, arg2, block);

if (specificArity != 3) return call(context, self, clazz, name, new IRubyObject[] {arg0, arg1, arg2 }, block);

return (IRubyObject)this.specific.invokeExact(context, staticScope, self, arg0, arg1, arg2, block, implementationClass, name);
} catch (Throwable t) {
Helpers.throwException(t);
// not reached
return null;
}
}

private IRubyObject callNoProtocol(ThreadContext context, IRubyObject self, RubyModule clazz, String name, IRubyObject[] args, Block block) throws Throwable {
StaticScope staticScope = this.staticScope;
RubyModule implementationClass = this.implementationClass;
pre(context, staticScope, implementationClass, self, name, block);

try {
return (IRubyObject)this.variable.invokeExact(context, staticScope, self, args, block, implementationClass, name);
} finally {
post(context);
}
}

public boolean hasExplicitCallProtocol() {
return method.hasExplicitCallProtocol();
public IRubyObject callNoProtocol(ThreadContext context, IRubyObject self, RubyModule clazz, String name, Block block) throws Throwable {
if (specificArity != 0) return call(context, self, clazz, name, IRubyObject.NULL_ARRAY, block);

StaticScope staticScope = this.staticScope;
RubyModule implementationClass = this.implementationClass;
pre(context, staticScope, implementationClass, self, name, block);

try {
return (IRubyObject)this.specific.invokeExact(context, staticScope, self, block, implementationClass, name);
} finally {
post(context);
}
}

public IRubyObject callNoProtocol(ThreadContext context, IRubyObject self, RubyModule clazz, String name, IRubyObject arg0, Block block) throws Throwable {
if (specificArity != 1) return call(context, self, clazz, name, Helpers.arrayOf(arg0), block);

StaticScope staticScope = this.staticScope;
RubyModule implementationClass = this.implementationClass;
pre(context, staticScope, implementationClass, self, name, block);

try {
return (IRubyObject)this.specific.invokeExact(context, staticScope, self, arg0, block, implementationClass, name);
} finally {
post(context);
}
}

public IRubyObject callNoProtocol(ThreadContext context, IRubyObject self, RubyModule clazz, String name, IRubyObject arg0, IRubyObject arg1, Block block) throws Throwable {
if (specificArity != 2) return call(context, self, clazz, name, Helpers.arrayOf(arg0, arg1), block);

StaticScope staticScope = this.staticScope;
RubyModule implementationClass = this.implementationClass;
pre(context, staticScope, implementationClass, self, name, block);

try {
return (IRubyObject)this.specific.invokeExact(context, staticScope, self, arg0, arg1, block, implementationClass, name);
} finally {
post(context);
}
}

public IRubyObject callNoProtocol(ThreadContext context, IRubyObject self, RubyModule clazz, String name, IRubyObject arg0, IRubyObject arg1, IRubyObject arg2, Block block) throws Throwable {
if (specificArity != 3) return call(context, self, clazz, name, Helpers.arrayOf(arg0, arg1, arg2), block);

StaticScope staticScope = this.staticScope;
RubyModule implementationClass = this.implementationClass;
pre(context, staticScope, implementationClass, self, name, block);

try {
return (IRubyObject)this.specific.invokeExact(context, staticScope, self, arg0, arg1, arg2, block, implementationClass, name);
} finally {
post(context);
}
}

@Override
30 changes: 20 additions & 10 deletions core/src/main/java/org/jruby/ir/targets/IRBytecodeAdapter6.java
Original file line number Diff line number Diff line change
@@ -29,8 +29,10 @@
import org.jruby.ir.runtime.IRRuntimeHelpers;
import org.jruby.parser.StaticScope;
import org.jruby.runtime.Block;
import org.jruby.runtime.CallSite;
import org.jruby.runtime.CallType;
import org.jruby.runtime.Helpers;
import org.jruby.runtime.MethodIndex;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.runtime.callsite.CachingCallSite;
@@ -407,6 +409,10 @@ public static void buildArrayFromLocals(SkinnyMethodAdapter adapter2, int base,
}

public void invokeOtherOneFixnum(String name, long fixnum) {
if (!MethodIndex.hasFastFixnumOps(name)) {
pushFixnum(fixnum);
invokeOther(name, 1, false);
}
SkinnyMethodAdapter adapter2;
String incomingSig = sig(JVM.OBJECT, params(ThreadContext.class, JVM.OBJECT, JVM.OBJECT));
String outgoingSig = sig(JVM.OBJECT, params(ThreadContext.class, JVM.OBJECT, JVM.OBJECT, long.class));
@@ -422,18 +428,18 @@ public void invokeOtherOneFixnum(String name, long fixnum) {
null);

// call site object field
adapter.getClassVisitor().visitField(Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC, methodName, ci(CachingCallSite.class), null, null).visitEnd();
adapter.getClassVisitor().visitField(Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC, methodName, ci(CallSite.class), null, null).visitEnd();

// lazily construct it
adapter2.getstatic(getClassData().clsName, methodName, ci(CachingCallSite.class));
adapter2.getstatic(getClassData().clsName, methodName, ci(CallSite.class));
adapter2.dup();
Label doCall = new Label();
adapter2.ifnonnull(doCall);
adapter2.pop();
adapter2.ldc(name);
adapter2.invokestatic(p(IRRuntimeHelpers.class), "newNormalCachingCallSite", sig(NormalCachingCallSite.class, String.class));
adapter2.invokestatic(p(MethodIndex.class), "getFastFixnumOpsCallSite", sig(CallSite.class, String.class));
adapter2.dup();
adapter2.putstatic(getClassData().clsName, methodName, ci(CachingCallSite.class));
adapter2.putstatic(getClassData().clsName, methodName, ci(CallSite.class));

// use call site to invoke
adapter2.label(doCall);
@@ -442,7 +448,7 @@ public void invokeOtherOneFixnum(String name, long fixnum) {
adapter2.aload(2); // target
adapter2.ldc(fixnum); // fixnum

adapter2.invokevirtual(p(CachingCallSite.class), "call", outgoingSig);
adapter2.invokevirtual(p(CallSite.class), "call", outgoingSig);
adapter2.areturn();
adapter2.end();

@@ -451,6 +457,10 @@ public void invokeOtherOneFixnum(String name, long fixnum) {
}

public void invokeOtherOneFloat(String name, double flote) {
if (!MethodIndex.hasFastFloatOps(name)) {
pushFloat(flote);
invokeOther(name, 1, false);
}
SkinnyMethodAdapter adapter2;
String incomingSig = sig(JVM.OBJECT, params(ThreadContext.class, JVM.OBJECT, JVM.OBJECT));
String outgoingSig = sig(JVM.OBJECT, params(ThreadContext.class, JVM.OBJECT, JVM.OBJECT, double.class));
@@ -466,18 +476,18 @@ public void invokeOtherOneFloat(String name, double flote) {
null);

// call site object field
adapter.getClassVisitor().visitField(Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC, methodName, ci(CachingCallSite.class), null, null).visitEnd();
adapter.getClassVisitor().visitField(Opcodes.ACC_PRIVATE | Opcodes.ACC_STATIC, methodName, ci(CallSite.class), null, null).visitEnd();

// lazily construct it
adapter2.getstatic(getClassData().clsName, methodName, ci(CachingCallSite.class));
adapter2.getstatic(getClassData().clsName, methodName, ci(CallSite.class));
adapter2.dup();
Label doCall = new Label();
adapter2.ifnonnull(doCall);
adapter2.pop();
adapter2.ldc(name);
adapter2.invokestatic(p(IRRuntimeHelpers.class), "newNormalCachingCallSite", sig(NormalCachingCallSite.class, String.class));
adapter2.invokestatic(p(MethodIndex.class), "getFastFloatOpsCallSite", sig(CallSite.class, String.class));
adapter2.dup();
adapter2.putstatic(getClassData().clsName, methodName, ci(CachingCallSite.class));
adapter2.putstatic(getClassData().clsName, methodName, ci(CallSite.class));

// use call site to invoke
adapter2.label(doCall);
@@ -486,7 +496,7 @@ public void invokeOtherOneFloat(String name, double flote) {
adapter2.aload(2); // target
adapter2.ldc(flote); // float

adapter2.invokevirtual(p(CachingCallSite.class), "call", outgoingSig);
adapter2.invokevirtual(p(CallSite.class), "call", outgoingSig);
adapter2.areturn();
adapter2.end();