Permalink
Browse files

Receive arguments know enough to extra proper kwargs value itself (fi…

…xes issue that interpreter did not know 100% if last hash args was a kwarg or not
  • Loading branch information...
1 parent 45b8a5b commit 2d4d57c9aee31fe4516b804d82cc9186c6c2dd8b @enebo enebo committed Mar 6, 2014
@@ -6,6 +6,7 @@
import org.jruby.ir.operands.UndefinedValue;
import org.jruby.ir.operands.Variable;
import org.jruby.ir.Operation;
+import org.jruby.ir.runtime.IRRuntimeHelpers;
import org.jruby.runtime.Block;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;
@@ -17,22 +18,22 @@
public class ReceiveKeywordArgInstr extends ReceiveArgBase implements FixedArityInstr {
public final String argName;
- public final int numUsedArgs;
+ public final int required;
- public ReceiveKeywordArgInstr(Variable result, String argName, int numUsedArgs) {
+ public ReceiveKeywordArgInstr(Variable result, String argName, int required) {
super(Operation.RECV_KW_ARG, result, -1);
this.argName = argName;
- this.numUsedArgs = numUsedArgs;
+ this.required = required;
}
@Override
public Operand[] getOperands() {
- return new Operand[] { new Fixnum(numUsedArgs), new StringLiteral(argName) };
+ return new Operand[] { new Fixnum(required), new StringLiteral(argName) };
}
@Override
public String toString() {
- return (isDead() ? "[DEAD]" : "") + (hasUnusedResult() ? "[DEAD-RESULT]" : "") + getResult() + " = " + getOperation() + "(" + numUsedArgs + ", " + argName + ")";
+ return (isDead() ? "[DEAD]" : "") + (hasUnusedResult() ? "[DEAD-RESULT]" : "") + getResult() + " = " + getOperation() + "(" + required + ", " + argName + ")";
}
@Override
@@ -43,14 +44,15 @@ public boolean computeScopeFlags(IRScope scope) {
@Override
public Instr cloneForInlining(InlinerInfo ii) {
- return new ReceiveKeywordArgInstr(ii.getRenamedVariable(result), argName, numUsedArgs);
+ return new ReceiveKeywordArgInstr(ii.getRenamedVariable(result), argName, required);
}
@Override
- public IRubyObject receiveArg(ThreadContext context, IRubyObject[] args, boolean keywordArgumentSupplied) {
- if (!keywordArgumentSupplied) return UndefinedValue.UNDEFINED;
+ public IRubyObject receiveArg(ThreadContext context, IRubyObject[] args, boolean acceptsKeywordArgument) {
+ RubyHash keywordArguments = IRRuntimeHelpers.extractKwargsHash(args, required, acceptsKeywordArgument);
+
+ if (keywordArguments == null) return UndefinedValue.UNDEFINED;
- RubyHash keywordArguments = (RubyHash)args[args.length - 1];
RubySymbol keywordName = context.getRuntime().newSymbol(argName);
if (keywordArguments.fastARef(keywordName) == null) return UndefinedValue.UNDEFINED;
@@ -4,6 +4,7 @@
import org.jruby.ir.IRScope;
import org.jruby.ir.operands.Variable;
import org.jruby.ir.Operation;
+import org.jruby.ir.runtime.IRRuntimeHelpers;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.RubyHash;
@@ -12,21 +13,21 @@
import org.jruby.ir.transformations.inlining.InlinerInfo;
public class ReceiveKeywordRestArgInstr extends ReceiveArgBase implements FixedArityInstr {
- public final int numUsedArgs;
+ public final int required;
- public ReceiveKeywordRestArgInstr(Variable result, int numUsedArgs) {
+ public ReceiveKeywordRestArgInstr(Variable result, int required) {
super(Operation.RECV_KW_REST_ARG, result, -1);
- this.numUsedArgs = numUsedArgs;
+ this.required = required;
}
@Override
public Operand[] getOperands() {
- return new Operand[] { new Fixnum(numUsedArgs) };
+ return new Operand[] { new Fixnum(required) };
}
@Override
public String toString() {
- return (isDead() ? "[DEAD]" : "") + (hasUnusedResult() ? "[DEAD-RESULT]" : "") + getResult() + " = " + getOperation() + "(" + numUsedArgs + ")";
+ return (isDead() ? "[DEAD]" : "") + (hasUnusedResult() ? "[DEAD-RESULT]" : "") + getResult() + " = " + getOperation() + "(" + required + ")";
}
@Override
@@ -37,13 +38,13 @@ public boolean computeScopeFlags(IRScope scope) {
@Override
public Instr cloneForInlining(InlinerInfo ii) {
- return new ReceiveKeywordRestArgInstr(ii.getRenamedVariable(result), numUsedArgs);
+ return new ReceiveKeywordRestArgInstr(ii.getRenamedVariable(result), required);
}
@Override
public IRubyObject receiveArg(ThreadContext context, IRubyObject[] args, boolean keywordArgumentSupplied) {
- if (!keywordArgumentSupplied) return RubyHash.newSmallHash(context.getRuntime());
+ RubyHash keywordArguments = IRRuntimeHelpers.extractKwargsHash(args, required, keywordArgumentSupplied);
- return args[args.length - 1];
+ return keywordArguments == null ? RubyHash.newSmallHash(context.getRuntime()) : keywordArguments;
}
}
@@ -1,11 +1,13 @@
package org.jruby.ir.instructions;
+import org.jruby.RubyHash;
import org.jruby.ir.IRVisitor;
import org.jruby.ir.Operation;
import org.jruby.ir.operands.Fixnum;
import org.jruby.ir.operands.Operand;
import org.jruby.ir.operands.UndefinedValue;
import org.jruby.ir.operands.Variable;
+import org.jruby.ir.runtime.IRRuntimeHelpers;
import org.jruby.ir.transformations.inlining.InlinerInfo;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;
@@ -64,9 +66,10 @@ public Instr cloneForInlining(InlinerInfo ii) {
}
@Override
- public IRubyObject receiveArg(ThreadContext context, IRubyObject[] args, boolean keywordArgumentSupplied) {
+ public IRubyObject receiveArg(ThreadContext context, IRubyObject[] args, boolean acceptsKeywordArgument) {
int optArgIndex = argIndex; // which opt arg we are processing? (first one has index 0, second 1, ...).
- int argsLength = keywordArgumentSupplied ? args.length - 1 : args.length;
+ RubyHash keywordArguments = IRRuntimeHelpers.extractKwargsHash(args, requiredArgs, acceptsKeywordArgument);
+ int argsLength = keywordArguments != null ? args.length - 1 : args.length;
if (requiredArgs + optArgIndex >= argsLength) return UndefinedValue.UNDEFINED; // No more args left
@@ -1,10 +1,12 @@
package org.jruby.ir.instructions;
+import org.jruby.RubyHash;
import org.jruby.ir.IRVisitor;
import org.jruby.ir.Operation;
import org.jruby.ir.operands.Fixnum;
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.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;
@@ -14,45 +16,46 @@
*/
public class ReceiveRestArgInstr extends ReceiveArgBase implements FixedArityInstr {
/** Number of arguments already accounted for */
- public final int numUsedArgs;
+ public final int required;
- public ReceiveRestArgInstr(Variable result, int numUsedArgs, int argIndex) {
+ public ReceiveRestArgInstr(Variable result, int required, int argIndex) {
super(Operation.RECV_REST_ARG, result, argIndex);
- this.numUsedArgs = numUsedArgs;
+ this.required = required;
}
@Override
public String toString() {
- return (isDead() ? "[DEAD]" : "") + (hasUnusedResult() ? "[DEAD-RESULT]" : "") + getResult() + " = " + getOperation() + "(" + numUsedArgs + ", " + argIndex + ")";
+ return (isDead() ? "[DEAD]" : "") + (hasUnusedResult() ? "[DEAD-RESULT]" : "") + getResult() + " = " + getOperation() + "(" + required + ", " + argIndex + ")";
}
@Override
public Operand[] getOperands() {
- return new Operand[] { new Fixnum(numUsedArgs), new Fixnum(argIndex) };
+ return new Operand[] { new Fixnum(required), new Fixnum(argIndex) };
}
@Override
public Instr cloneForInlining(InlinerInfo ii) {
switch (ii.getCloneMode()) {
case ENSURE_BLOCK_CLONE:
case NORMAL_CLONE:
- return new ReceiveRestArgInstr(ii.getRenamedVariable(result), numUsedArgs, argIndex);
+ return new ReceiveRestArgInstr(ii.getRenamedVariable(result), required, argIndex);
default:
if (ii.canMapArgsStatically()) {
// FIXME: Check this
return new CopyInstr(ii.getRenamedVariable(result), ii.getArg(argIndex, true));
} else {
- return new RestArgMultipleAsgnInstr(ii.getRenamedVariable(result), ii.getArgs(), argIndex, (numUsedArgs - argIndex), argIndex);
+ return new RestArgMultipleAsgnInstr(ii.getRenamedVariable(result), ii.getArgs(), argIndex, (required - argIndex), argIndex);
}
}
}
private IRubyObject[] NO_PARAMS = new IRubyObject[0];
@Override
- public IRubyObject receiveArg(ThreadContext context, IRubyObject[] args, boolean keywordArgumentSupplied) {
- int argsLength = keywordArgumentSupplied ? args.length - 1 : args.length;
- int remainingArguments = argsLength - numUsedArgs;
+ public IRubyObject receiveArg(ThreadContext context, IRubyObject[] args, boolean acceptsKeywordArguments) {
+ RubyHash keywordArguments = IRRuntimeHelpers.extractKwargsHash(args, required, acceptsKeywordArguments);
+ int argsLength = keywordArguments != null ? args.length - 1 : args.length;
+ int remainingArguments = argsLength - required;
if (remainingArguments <= 0) return context.runtime.newArray(NO_PARAMS);
@@ -544,8 +544,7 @@ private static IRubyObject interpret(ThreadContext context, IRubyObject self,
boolean debug = IRRuntimeHelpers.isDebug();
boolean profile = IRRuntimeHelpers.inProfileMode();
Integer scopeVersion = profile ? Profiler.initProfiling(scope) : 0;
- // FIXME: As we stand we need to know required args count to know whether a last arg hash is kwargs or just a hash
- boolean receivesKeywordArgument = IRRuntimeHelpers.extractKwargsCount(args, 0, scope.receivesKeywordArgs()) != 0;
+ boolean acceptsKeywordArgument = scope.receivesKeywordArgs();
// Enter the looooop!
while (ipc < n) {
@@ -569,7 +568,7 @@ private static IRubyObject interpret(ThreadContext context, IRubyObject self,
interpretFloatOp((AluInstr)instr, operation, context, floats, booleans, temp);
break;
case ARG_OP:
- receiveArg(context, instr, operation, args, receivesKeywordArgument, currDynScope, temp, exception, block);
+ receiveArg(context, instr, operation, args, acceptsKeywordArgument, currDynScope, temp, exception, block);
break;
case CALL_OP:
if (profile) Profiler.updateCallSite(instr, scope, scopeVersion);
@@ -526,11 +526,11 @@ private void encodeReceiveJRubyExceptionInstr(ReceiveJRubyExceptionInstr instr)
private void encodeReceiveKeywordArgInstr(ReceiveKeywordArgInstr instr) {
e.encode(instr.argName);
- e.encode(instr.numUsedArgs);
+ e.encode(instr.required);
}
private void encodeReceiveKeywordRestArgInstr(ReceiveKeywordRestArgInstr instr) {
- e.encode(instr.numUsedArgs);
+ e.encode(instr.required);
}
private void encodeReceiveOptArgInstr(ReceiveOptArgInstr instr) {
@@ -550,7 +550,7 @@ private void encodeReceivePreReqdArgInstr(ReceivePreReqdArgInstr instr) {
}
private void encodeReceiveRestArgInstr(ReceiveRestArgInstr instr) {
- e.encode(instr.numUsedArgs);
+ e.encode(instr.required);
e.encode(instr.getArgIndex());
}
@@ -1471,7 +1471,7 @@ public void ReceiveRestArgInstr(ReceiveRestArgInstr instr) {
// FIXME: Only works when args is in an array rather than being flattened out
// FIXME: Missing kwargs 2.0 support (kwArgHashCount value)
jvm.method().loadContext();
- jvm.method().adapter.pushInt(instr.numUsedArgs); // MIN reqd args
+ jvm.method().adapter.pushInt(instr.required); // MIN reqd args
jvm.method().adapter.pushInt(instr.getArgIndex()); // args array offset
jvm.method().adapter.aload(3); // index of arg array
jvm.method().invokeHelper("irLoadRestArg", IRubyObject.class, ThreadContext.class, int.class, int.class, IRubyObject[].class);

0 comments on commit 2d4d57c

Please sign in to comment.