Skip to content
Permalink
Browse files
Merge branch 'master' into truffle-head
  • Loading branch information
chrisseaton committed Jan 26, 2015
2 parents 231b213 + 0d1d636 commit 7d26b4b2027cc02abacdd71355d51a583c231f75
Showing 349 changed files with 2,538 additions and 1,569 deletions.
@@ -6,6 +6,6 @@
public List<String[]> getParameterList();

public enum ArgType {
key, keyrest, block, opt, rest, req
key, keyreq, keyrest, block, opt, rest, req
}
}
@@ -1879,12 +1879,12 @@ public void receiveArgs(final ArgsNode argsNode) {
String argName = ((INameNode) kasgn).getName();
Variable av = getNewLocalVariable(argName, 0);
Label l = getNewLabel();
if (scope instanceof IRMethod) ((IRMethod) scope).addArgDesc(IRMethodArgs.ArgType.key, argName);
if (scope instanceof IRMethod) addKeyArgDesc(kasgn, argName);
addInstr(new ReceiveKeywordArgInstr(av, argName, required));
addInstr(BNEInstr.create(av, UndefinedValue.UNDEFINED, l)); // if 'av' is not undefined, we are done

// Required kwargs have no value and check_arity will throw if they are not provided.
if (kasgn.getValueNode().getNodeType() != NodeType.REQUIRED_KEYWORD_ARGUMENT_VALUE) {
if (!isRequiredKeywordArgumentValue(kasgn)) {
build(kasgn);
} else {
addInstr(new RaiseRequiredKeywordArgumentError(argName));
@@ -1906,6 +1906,18 @@ public void receiveArgs(final ArgsNode argsNode) {
receiveBlockArg(argsNode);
}

private void addKeyArgDesc(AssignableNode kasgn, String argName) {
if (isRequiredKeywordArgumentValue(kasgn)) {
((IRMethod) scope).addArgDesc(IRMethodArgs.ArgType.keyreq, argName);
} else {
((IRMethod) scope).addArgDesc(IRMethodArgs.ArgType.key, argName);
}
}

private boolean isRequiredKeywordArgumentValue(AssignableNode kasgn) {
return (kasgn.getValueNode().getNodeType()) == NodeType.REQUIRED_KEYWORD_ARGUMENT_VALUE;
}

// This method is called to build arguments
public void buildArgsMasgn(Node node, Operand argsArray, boolean isMasgnRoot, int preArgsCount, int postArgsCount, int index, boolean isSplat) {
Variable v;
@@ -3387,7 +3399,6 @@ public Operand buildZArray() {
}

private Operand buildZSuperIfNest(final Operand block) {
final IRScope s = scope;
// If we are in a block, we cannot make any assumptions about what args
// the super instr is going to get -- if there were no 'define_method'
// for defining methods, we could guarantee that the super is going to
@@ -3407,9 +3418,9 @@ public Operand run() {

Label allDoneLabel = getNewLabel();

IRScope superScope = s;
int depthFromSuper = 0;
Label next = null;
IRScope superScope = scope;

// Loop and generate a block for each possible value of depthFromSuper
Variable zsuperResult = createTemporaryVariable();
@@ -3418,7 +3429,7 @@ public Operand run() {
if (next != null) addInstr(new LabelInstr(next));
next = getNewLabel();
addInstr(BNEInstr.create(new Fixnum(depthFromSuper), scopeDepth, next));
Operand[] args = adjustVariableDepth(((IRClosure)superScope).getBlockArgs(), depthFromSuper);
Operand[] args = adjustVariableDepth(superScope.getCallArgs(), depthFromSuper);
addInstr(new ZSuperInstr(zsuperResult, buildSelf(), args, block));
addInstr(new JumpInstr(allDoneLabel));

@@ -3431,7 +3442,7 @@ public Operand run() {

// If we hit a method, this is known to always succeed
if (superScope instanceof IRMethod) {
Operand[] args = adjustVariableDepth(((IRMethod)superScope).getCallArgs(), depthFromSuper);
Operand[] args = adjustVariableDepth(superScope.getCallArgs(), depthFromSuper);
addInstr(new ZSuperInstr(zsuperResult, buildSelf(), args, block));
} //else {
// FIXME: Do or don't ... there is no try
@@ -3455,7 +3466,7 @@ public Operand buildZSuper(ZSuperNode zsuperNode) {

// Enebo:ZSuper in for (or nested for) can be statically resolved like method but it needs to fixup depth.
if (scope instanceof IRMethod) {
return buildSuperInstr(block, ((IRMethod) scope).getCallArgs());
return buildSuperInstr(block, scope.getCallArgs());
} else {
return buildZSuperIfNest(block);
}
@@ -1,6 +1,5 @@
package org.jruby.ir;

import org.jcodings.specific.USASCIIEncoding;
import org.jruby.ir.instructions.*;
import org.jruby.ir.interpreter.ClosureInterpreterContext;
import org.jruby.ir.interpreter.InterpreterContext;
@@ -14,12 +13,8 @@
import org.jruby.runtime.IRBlockBody;
import org.jruby.runtime.InterpretedIRBlockBody;
import org.jruby.runtime.Signature;
import org.jruby.util.KeyValuePair;
import org.objectweb.asm.Handle;

import java.util.ArrayList;
import java.util.List;

// Closures are contexts/scopes for the purpose of IR building. They are self-contained and accumulate instructions
// that don't merge into the flow of the containing scope. They are manipulated as an unit.
// Their parents are always execution scopes.
@@ -33,10 +28,6 @@

private boolean isBeginEndBlock;

// Block parameters
private List<Operand> blockArgs;
private List<KeyValuePair<Operand, Operand>> keywordArgs;

/** The parameter names, for Proc#parameters */
private String[] parameterList;

@@ -83,8 +74,7 @@ protected IRClosure(IRClosure c, IRScope lexicalParent, int closureId, String fu
} else {
this.body = new InterpretedIRBlockBody(this, c.body.getSignature());
}
this.blockArgs = new ArrayList<>();
this.keywordArgs = new ArrayList<>();

this.signature = c.signature;
}

@@ -98,8 +88,6 @@ public IRClosure(IRManager manager, IRScope lexicalParent, int lineNumber, Stati

public IRClosure(IRManager manager, IRScope lexicalParent, int lineNumber, StaticScope staticScope, Signature signature, int argumentType, String prefix, boolean isBeginEndBlock) {
this(manager, lexicalParent, lexicalParent.getFileName(), lineNumber, staticScope, prefix);
this.blockArgs = new ArrayList<>();
this.keywordArgs = new ArrayList<>();
this.argumentType = argumentType;
this.signature = signature;
lexicalParent.addClosure(this);
@@ -132,9 +120,8 @@ public boolean isBeginEndBlock() {

public void setParameterList(String[] parameterList) {
this.parameterList = parameterList;
if (!getManager().isDryRun()) {
((InterpretedIRBlockBody)this.body).setParameterList(parameterList);
}

if (!getManager().isDryRun()) this.body.setParameterList(parameterList);
}

public String[] getParameterList() {
@@ -186,39 +173,6 @@ public boolean isFlipScope() {
return false;
}

@Override
public void addInstr(Instr i) {
// Accumulate block arguments
if (i instanceof ReceiveKeywordRestArgInstr) {
// Always add the keyword rest arg to the beginning
keywordArgs.add(0, new KeyValuePair<Operand, Operand>(Symbol.KW_REST_ARG_DUMMY, ((ReceiveArgBase) i).getResult()));
} else if (i instanceof ReceiveKeywordArgInstr) {
ReceiveKeywordArgInstr rkai = (ReceiveKeywordArgInstr)i;
// FIXME: This lost encoding information when name was converted to string earlier in IRBuilder
keywordArgs.add(new KeyValuePair<Operand, Operand>(new Symbol(rkai.argName, USASCIIEncoding.INSTANCE), rkai.getResult()));
} else if (i instanceof ReceiveRestArgInstr) {
blockArgs.add(new Splat(((ReceiveRestArgInstr)i).getResult()));
} else if (i instanceof ReceiveArgBase) {
blockArgs.add(((ReceiveArgBase) i).getResult());
}

super.addInstr(i);
}

public Operand[] getBlockArgs() {
if (receivesKeywordArgs()) {
int i = 0;
Operand[] args = new Operand[blockArgs.size() + 1];
for (Operand arg: blockArgs) {
args[i++] = arg;
}
args[i] = new Hash(keywordArgs, true);
return args;
} else {
return blockArgs.toArray(new Operand[blockArgs.size()]);
}
}

public String toStringBody() {
StringBuilder buf = new StringBuilder();
buf.append(getName()).append(" = { \n");
@@ -8,7 +8,6 @@
import org.jruby.ir.interpreter.InterpreterContext;
import org.jruby.ir.operands.Label;
import org.jruby.ir.operands.LocalVariable;
import org.jruby.ir.operands.Operand;
import org.jruby.parser.StaticScope;

public class IREvalScript extends IRClosure {
@@ -50,11 +49,6 @@ public IRScopeType getScopeType() {
return IRScopeType.EVAL_SCRIPT;
}

@Override
public Operand[] getBlockArgs() {
return new Operand[0];
}

public boolean isModuleOrInstanceEval() {
return evalType == EvalType.MODULE_EVAL || evalType == EvalType.INSTANCE_EVAL;
}
@@ -1,21 +1,10 @@
package org.jruby.ir;

import org.jcodings.specific.USASCIIEncoding;
import org.jruby.ast.MethodDefNode;
import org.jruby.internal.runtime.methods.IRMethodArgs;
import org.jruby.ir.instructions.Instr;
import org.jruby.ir.instructions.ReceiveArgBase;
import org.jruby.ir.instructions.ReceiveKeywordArgInstr;
import org.jruby.ir.instructions.ReceiveKeywordRestArgInstr;
import org.jruby.ir.instructions.ReceiveRestArgInstr;
import org.jruby.ir.interpreter.InterpreterContext;
import org.jruby.ir.operands.LocalVariable;
import org.jruby.ir.operands.Operand;
import org.jruby.ir.operands.Symbol;
import org.jruby.ir.operands.Hash;
import org.jruby.ir.operands.Splat;
import org.jruby.ir.representations.BasicBlock;
import org.jruby.util.KeyValuePair;
import org.jruby.parser.StaticScope;

import java.lang.invoke.MethodType;
@@ -28,13 +17,6 @@
public class IRMethod extends IRScope {
public final boolean isInstanceMethod;

// Note that if operands from the method are modified,
// callArgs would have to be updated as well
//
// Call parameters
private List<Operand> callArgs;
private List<KeyValuePair<Operand, Operand>> keywordArgs;

// Argument description of the form [:req, "a"], [:opt, "b"] ..
private List<String[]> argDesc;

@@ -52,8 +34,6 @@ public IRMethod(IRManager manager, IRScope lexicalParent, MethodDefNode defn, St

this.defn = defn;
this.isInstanceMethod = isInstanceMethod;
this.callArgs = new ArrayList<>();
this.keywordArgs = new ArrayList<>();
this.argDesc = new ArrayList<>();
this.signatures = new HashMap<>();

@@ -85,25 +65,6 @@ public IRScopeType getScopeType() {
return isInstanceMethod ? IRScopeType.INSTANCE_METHOD : IRScopeType.CLASS_METHOD;
}

@Override
public void addInstr(Instr i) {
// Accumulate call arguments
if (i instanceof ReceiveKeywordRestArgInstr) {
// Always add the keyword rest arg to the beginning
keywordArgs.add(0, new KeyValuePair<Operand, Operand>(Symbol.KW_REST_ARG_DUMMY, ((ReceiveArgBase) i).getResult()));
} else if (i instanceof ReceiveKeywordArgInstr) {
ReceiveKeywordArgInstr rkai = (ReceiveKeywordArgInstr)i;
// FIXME: This lost encoding information when name was converted to string earlier in IRBuilder
keywordArgs.add(new KeyValuePair<Operand, Operand>(new Symbol(rkai.argName, USASCIIEncoding.INSTANCE), rkai.getResult()));
} else if (i instanceof ReceiveRestArgInstr) {
callArgs.add(new Splat(((ReceiveRestArgInstr)i).getResult()));
} else if (i instanceof ReceiveArgBase) {
callArgs.add(((ReceiveArgBase) i).getResult());
}

super.addInstr(i);
}

public void addArgDesc(IRMethodArgs.ArgType type, String argName) {
argDesc.add(new String[]{type.name(), argName});
}
@@ -112,20 +73,6 @@ public void addArgDesc(IRMethodArgs.ArgType type, String argName) {
return argDesc;
}

public Operand[] getCallArgs() {
if (receivesKeywordArgs()) {
int i = 0;
Operand[] args = new Operand[callArgs.size() + 1];
for (Operand arg: callArgs) {
args[i++] = arg;
}
args[i] = new Hash(keywordArgs, true);
return args;
} else {
return callArgs.toArray(new Operand[callArgs.size()]);
}
}

@Override
protected LocalVariable findExistingLocalVariable(String name, int scopeDepth) {
assert scopeDepth == 0: "Local variable depth in IRMethod should always be zero (" + name + " had depth of " + scopeDepth + ")";
@@ -1,5 +1,6 @@
package org.jruby.ir;

import org.jcodings.specific.USASCIIEncoding;
import org.jruby.ParseResult;
import org.jruby.RubyInstanceConfig;
import org.jruby.RubyModule;
@@ -17,6 +18,7 @@
import org.jruby.ir.transformations.inlining.CFGInliner;
import org.jruby.ir.transformations.inlining.SimpleCloneInfo;
import org.jruby.parser.StaticScope;
import org.jruby.util.KeyValuePair;
import org.jruby.util.log.Logger;
import org.jruby.util.log.LoggerFactory;

@@ -1011,6 +1013,63 @@ public boolean definesLocalVariable(Variable v) {
return false;
}

/**
* Extract all call arguments from the specified scope (only useful for Closures and Methods) so that
* we can convert zsupers to supers with explicit arguments.
*
* Note: This is fairly expensive because we walk entire scope when we could potentially stop earlier
* if we knew when recv_* were done.
*/
public Operand[] getCallArgs() {
List<Operand> callArgs = new ArrayList<>(5);
List<KeyValuePair<Operand, Operand>> keywordArgs = new ArrayList<>(3);

// We have two paths. eval and non-eval.
if (instrList == null) { // CFG already made. eval has zsuper and we walk back to some executing method/script
for (BasicBlock bb: getCFG().getBasicBlocks()) {
for (Instr instr: bb.getInstrs()) {
extractCallOperands(callArgs, keywordArgs, instr);
}
}
} else { // common zsuper case. non-eval and at build time entirely.
for (Instr instr : getInstrs()) {
extractCallOperands(callArgs, keywordArgs, instr);
}
}

return getCallOperands(callArgs, keywordArgs);
}


private void extractCallOperands(List<Operand> callArgs, List<KeyValuePair<Operand, Operand>> keywordArgs, Instr instr) {
if (instr instanceof ReceiveKeywordRestArgInstr) {
// Always add the keyword rest arg to the beginning
keywordArgs.add(0, new KeyValuePair<Operand, Operand>(Symbol.KW_REST_ARG_DUMMY, ((ReceiveArgBase) instr).getResult()));
} else if (instr instanceof ReceiveKeywordArgInstr) {
ReceiveKeywordArgInstr rkai = (ReceiveKeywordArgInstr) instr;
// FIXME: This lost encoding information when name was converted to string earlier in IRBuilder
keywordArgs.add(new KeyValuePair<Operand, Operand>(new Symbol(rkai.argName, USASCIIEncoding.INSTANCE), rkai.getResult()));
} else if (instr instanceof ReceiveRestArgInstr) {
callArgs.add(new Splat(((ReceiveRestArgInstr) instr).getResult()));
} else if (instr instanceof ReceiveArgBase) {
callArgs.add(((ReceiveArgBase) instr).getResult());
}
}

private Operand[] getCallOperands(List<Operand> callArgs, List<KeyValuePair<Operand, Operand>> keywordArgs) {
if (receivesKeywordArgs()) {
int i = 0;
Operand[] args = new Operand[callArgs.size() + 1];
for (Operand arg: callArgs) {
args[i++] = arg;
}
args[i] = new Hash(keywordArgs, true);
return args;
}

return callArgs.toArray(new Operand[callArgs.size()]);
}

public void setDataFlowSolution(String name, DataFlowProblem p) {
dfProbs.put(name, p);
}
Loading

0 comments on commit 7d26b4b

Please sign in to comment.