Skip to content

Commit

Permalink
WIP: args boxing (0/1 arg)
Browse files Browse the repository at this point in the history
  • Loading branch information
subbuss committed Nov 29, 2013
1 parent 21426ab commit 8becd73
Show file tree
Hide file tree
Showing 9 changed files with 120 additions and 59 deletions.
Expand Up @@ -29,7 +29,7 @@ public class InterpretedIRMethod extends DynamicMethod implements IRMethodArgs,
private final IRScope method;
private Arity arity;
boolean displayedCFG = false; // FIXME: Remove when we find nicer way of logging CFG

public InterpretedIRMethod(IRScope method, Visibility visibility, RubyModule implementationClass) {
super(implementationClass, visibility, CallConfiguration.FrameNoneScopeNone);
this.method = method;
Expand All @@ -41,7 +41,7 @@ public InterpretedIRMethod(IRScope method, Visibility visibility, RubyModule imp
public InterpretedIRMethod(IRScope method, RubyModule implementationClass) {
this(method, Visibility.PRIVATE, implementationClass);
}

public IRScope getIRMethod() {
return method;
}
Expand All @@ -62,8 +62,7 @@ public Arity getArity() {
return this.arity;
}

@Override
public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule clazz, String name, IRubyObject[] args, Block block) {
private void prepareMethod(String name) {
// SSS FIXME: Move this out of here to some other place?
// Prepare method if not yet done so we know if the method has an explicit/implicit call protocol
if (method.getInstrsForInterpretation() == null) method.prepareForInterpretation(false);
Expand All @@ -80,15 +79,63 @@ public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule claz
displayedCFG = true;
}
}
}

@Override
public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule clazz, String name, Block block) {
prepareMethod(name);
if (method.hasExplicitCallProtocol()) {
return Interpreter.INTERPRET_METHOD(context, this, self, name, 0, null, null, block, null, false);
} else {
try {
// update call stacks (push: frame, class, scope, etc.)
context.preMethodFrameAndScope(getImplementationClass(), name, self, block, method.getStaticScope());
context.setCurrentVisibility(getVisibility());
return Interpreter.INTERPRET_METHOD(context, this, self, name, 0, null, null, block, null, false);
} finally {
// update call stacks (pop: ..)
context.popFrame();
context.popRubyClass();
context.popScope();
}
}
}

@Override
public IRubyObject call(ThreadContext context, IRubyObject self, RubyModule clazz, String name, IRubyObject arg0, Block block) {
prepareMethod(name);
if (method.hasExplicitCallProtocol()) {
return Interpreter.INTERPRET_METHOD(context, this, self, name, 1, arg0, null, block, null, false);
} else {
try {
// update call stacks (push: frame, class, scope, etc.)
context.preMethodFrameAndScope(getImplementationClass(), name, self, block, method.getStaticScope());
context.setCurrentVisibility(getVisibility());
return Interpreter.INTERPRET_METHOD(context, this, self, name, 1, arg0, null, block, null, false);
} finally {
// update call stacks (pop: ..)
context.popFrame();
context.popRubyClass();
context.popScope();
}
}
}

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

int n = args.length;
IRubyObject arg0 = n >= 1 ? args[0] : null;

if (method.hasExplicitCallProtocol()) {
return Interpreter.INTERPRET_METHOD(context, this, self, name, args, block, null, false);
return Interpreter.INTERPRET_METHOD(context, this, self, name, n, arg0, args, block, null, false);
} else {
try {
// update call stacks (push: frame, class, scope, etc.)
context.preMethodFrameAndScope(getImplementationClass(), name, self, block, method.getStaticScope());
context.setCurrentVisibility(getVisibility());
return Interpreter.INTERPRET_METHOD(context, this, self, name, args, block, null, false);
return Interpreter.INTERPRET_METHOD(context, this, self, name, n, arg0, args, block, null, false);
} finally {
// update call stacks (pop: ..)
context.popFrame();
Expand Down
Expand Up @@ -59,7 +59,7 @@ public Object interpret(ThreadContext context, DynamicScope currDynScope, IRubyO
InterpretedIRMethod bodyMethod = (InterpretedIRMethod)moduleBody.retrieve(context, self, currDynScope, temp);
RubyModule implClass = bodyMethod.getImplementationClass();
// SSS FIXME: Rather than pass the block implicitly, should we add %block as another operand to ProcessModuleBody, DefineModule instrs?
return bodyMethod.call(context, implClass, implClass, "", new IRubyObject[]{}, block);
return bodyMethod.call(context, implClass, implClass, "", block);
}

@Override
Expand Down
Expand Up @@ -44,7 +44,11 @@ public String toString() {
return super.toString() + "(" + argIndex + ")";
}

public IRubyObject receiveArg(ThreadContext context, int kwArgHashCount, IRubyObject[] args) {
public IRubyObject receiveArg(ThreadContext context, int kwArgHashCount, int numArgs, IRubyObject arg0, IRubyObject[] args) {
throw new RuntimeException("ReceiveArgBase.interpret called! " + this.getClass().getName() + " does not define receiveArg");
}

public static IRubyObject fetchArgFromArgs(int index, IRubyObject arg0, IRubyObject[] args) {
return (index == 0) ? arg0 : args[index];
}
}
Expand Up @@ -26,16 +26,16 @@ public String toString() {
}

@Override
public IRubyObject receiveArg(ThreadContext context, int kwArgHashCount, IRubyObject[] args) {
public IRubyObject receiveArg(ThreadContext context, int kwArgHashCount, int numArgs, IRubyObject arg0, IRubyObject[] args) {
if (kwArgHashCount == 0) {
return UndefinedValue.UNDEFINED;
} else {
RubyHash lastArg = (RubyHash)args[args.length - 1];
if (numUsedArgs == args.length) {
if (numUsedArgs == numArgs) {
/* throw ArgumentError */
Arity.raiseArgumentError(context.getRuntime(), args.length-1, numUsedArgs, -1);
Arity.raiseArgumentError(context.getRuntime(), numArgs-1, numUsedArgs, -1);
}

RubyHash lastArg = (RubyHash)ReceiveArgBase.fetchArgFromArgs(numArgs - 1, arg0, args);
// If the key exists in the hash, delete and return it.
RubySymbol argName = context.getRuntime().newSymbol(getResult().getName());
if (lastArg.fastARef(argName) != null) {
Expand Down
Expand Up @@ -25,16 +25,16 @@ public String toString() {
}

@Override
public IRubyObject receiveArg(ThreadContext context, int kwArgHashCount, IRubyObject[] args) {
public IRubyObject receiveArg(ThreadContext context, int kwArgHashCount, int numArgs, IRubyObject arg0, IRubyObject[] args) {
if (kwArgHashCount == 0) {
return RubyHash.newSmallHash(context.getRuntime());
} else {
if (numUsedArgs == args.length) {
if (numUsedArgs == numArgs) {
/* throw ArgumentError */
Arity.raiseArgumentError(context.getRuntime(), args.length-1, numUsedArgs, -1);
Arity.raiseArgumentError(context.getRuntime(), numArgs - 1, numUsedArgs, -1);
}

return args[args.length - 1];
return ReceiveArgBase.fetchArgFromArgs(numArgs - 1, arg0, args);
}
}
}
Expand Up @@ -50,11 +50,15 @@ public Instr cloneForBlockCloning(InlinerInfo ii) {
return new ReceiveOptArgInstr(ii.getRenamedVariable(result), numUsedArgs, argOffset, optArgIndex);
}

public IRubyObject receiveOptArg(IRubyObject[] args, int kwArgHashCount) {
public IRubyObject receiveOptArg(int numArgs, IRubyObject arg0, IRubyObject[] args, int kwArgHashCount) {
// Added this copy for code clarity
// argIndex is relative to start of opt args and not the start of arg array
int optArgIndex = this.argIndex;
return (optArgIndex + numUsedArgs + kwArgHashCount < args.length ? args[argOffset + optArgIndex] : UndefinedValue.UNDEFINED);
if (optArgIndex + numUsedArgs + kwArgHashCount < numArgs) {
return ReceiveArgBase.fetchArgFromArgs(argOffset+optArgIndex, arg0, args);
} else {
return UndefinedValue.UNDEFINED;
}
}

@Override
Expand Down
Expand Up @@ -54,13 +54,13 @@ public Instr cloneForBlockCloning(InlinerInfo ii) {
return new ReceivePostReqdArgInstr(ii.getRenamedVariable(result), argIndex, preReqdArgsCount, postReqdArgsCount);
}

public IRubyObject receivePostReqdArg(IRubyObject[] args, int kwArgHashCount) {
int n = args.length;
int remaining = n - preReqdArgsCount - kwArgHashCount;
public IRubyObject receivePostReqdArg(int numArgs, IRubyObject arg0, IRubyObject[] args, int kwArgHashCount) {
int remaining = numArgs - preReqdArgsCount - kwArgHashCount;
if (remaining <= argIndex) {
return null; // For blocks!
} else {
return (remaining > postReqdArgsCount) ? args[n - postReqdArgsCount - kwArgHashCount + argIndex] : args[preReqdArgsCount + argIndex];
int index = (remaining > postReqdArgsCount) ? numArgs - postReqdArgsCount - kwArgHashCount + argIndex : preReqdArgsCount + argIndex;
return ReceiveArgBase.fetchArgFromArgs(index, arg0, args);
}
}

Expand Down
Expand Up @@ -42,13 +42,17 @@ public Instr cloneForBlockCloning(InlinerInfo ii) {
private IRubyObject[] NO_PARAMS = new IRubyObject[0];

@Override
public IRubyObject receiveArg(ThreadContext context, int kwArgLoss, IRubyObject[] parameters) {
public IRubyObject receiveArg(ThreadContext context, int kwArgLoss, int numArgs, IRubyObject arg0, IRubyObject[] parameters) {
IRubyObject[] args;
int numAvailableArgs = parameters.length - numUsedArgs - kwArgLoss;
int numAvailableArgs = numArgs - numUsedArgs - kwArgLoss;
if (numAvailableArgs <= 0) {
args = NO_PARAMS;
} else {
args = new IRubyObject[numAvailableArgs];
// SSS: Quick simple hack
if (parameters == null) {
parameters = new IRubyObject[] { arg0 };
}
System.arraycopy(parameters, argIndex, args, 0, numAvailableArgs);
}

Expand Down

0 comments on commit 8becd73

Please sign in to comment.