Skip to content
Permalink
Browse files
Merge branch 'master' into truffle-head
  • Loading branch information
chrisseaton committed Oct 12, 2014
2 parents 0e19718 + a870e57 commit 450c4b57d6a437fbaee96c8edb3755a45ed873c4
Show file tree
Hide file tree
Showing 42 changed files with 233 additions and 186 deletions.
@@ -285,7 +285,9 @@ public int getNestingDepth() {

protected IRClosure cloneForInlining(CloneInfo ii, IRClosure clone) {
clone.nestingDepth = this.nestingDepth;
clone.parameterList = this.parameterList;
// FIXME: This is fragile. Untangle this state.
// Why is this being copied over to InterpretedIRBlockBody?
clone.setParameterList(this.parameterList);

SimpleCloneInfo clonedII = ii.cloneForCloningClosure(clone);

@@ -20,6 +20,7 @@
import org.jruby.ir.representations.CFG;
import org.jruby.ir.representations.CFGLinearizer;
import org.jruby.ir.transformations.inlining.CFGInliner;
import org.jruby.ir.transformations.inlining.SimpleCloneInfo;
import org.jruby.parser.StaticScope;
import org.jruby.util.log.Logger;
import org.jruby.util.log.LoggerFactory;
@@ -111,7 +112,6 @@ public abstract class IRScope implements ParseResult {

private Instr[] linearizedInstrArray;
private List<BasicBlock> linearizedBBList;
private Map<Integer, Integer> rescueMap;
protected int temporaryVariableIndex;
protected int floatVariableIndex;
protected int fixnumVariableIndex;
@@ -475,16 +475,17 @@ private synchronized Instr[] prepareInstructions() {

setupLinearization();

// Set up IPCs
SimpleCloneInfo cloneInfo = new SimpleCloneInfo(this, false);

// FIXME: If CFG (or linearizedBBList) knew number of instrs we could end up allocing better

// Pass 1. Set up IPCs for labels and instruct and build linear instr list
List<Instr> newInstrs = new ArrayList<Instr>();
HashMap<Label, Integer> labelIPCMap = new HashMap<Label, Integer>();
int ipc = 0;
for (BasicBlock b: linearizedBBList) {
Label l = b.getLabel();
labelIPCMap.put(l, ipc);
// This assumes if multiple equal/same labels exist which are scattered around the scope
// must be the same Java instance or only this one will get a targetPC set.
l.setTargetPC(ipc);
// All same-named labels must be same Java instance for this to work or we would need
// to examine all Label operands and update this as well which would be expensive.
b.getLabel().setTargetPC(ipc);
List<Instr> bbInstrs = b.getInstrs();
int bbInstrsLength = bbInstrs.size();
for (int i = 0; i < bbInstrsLength; i++) {
@@ -503,28 +504,29 @@ private synchronized Instr[] prepareInstructions() {
}
}

cfg().getExitBB().getLabel().setTargetPC(ipc + 1); // Exit BB ipc

// System.out.println("SCOPE: " + getName());
// System.out.println("INSTRS: " + cfg().toStringInstrs());

// Exit BB ipc
cfg().getExitBB().getLabel().setTargetPC(ipc + 1);

// Set up rescue map
setupRescueMap();

linearizedInstrArray = newInstrs.toArray(new Instr[newInstrs.size()]);
return linearizedInstrArray;
}

public void setupRescueMap() {
this.rescueMap = new HashMap<Integer, Integer>();
// Pass 2: Use ipc info from previous to mark all linearized instrs rpc
ipc = 0;
for (BasicBlock b : linearizedBBList) {
BasicBlock rescuerBB = cfg().getRescuerBBFor(b);
int rescuerPC = (rescuerBB == null) ? -1 : rescuerBB.getLabel().getTargetPC();
for (Instr i : b.getInstrs()) {
rescueMap.put(i.getIPC(), rescuerPC);
for (Instr instr : b.getInstrs()) {
// FIXME: If we did not omit instrs from previous pass we could end up just doing a
// a size and for loop this n times instead of walking an examining each instr
if (!(instr instanceof ReceiveSelfInstr)) {
linearizedInstrArray[ipc].setRPC(rescuerPC);
ipc++;
}
}
}

return linearizedInstrArray;
}

private boolean isUnsafeScope() {
@@ -1079,10 +1081,6 @@ public List<BasicBlock> buildLinearization() {
return linearizedBBList;
}

public Map<Integer, Integer> getRescueMap() {
return this.rescueMap;
}

public List<BasicBlock> linearization() {
depends(cfg());

@@ -1118,7 +1116,6 @@ public void resetState() {
flags.remove(HAS_NONLOCAL_RETURNS);
flags.remove(CAN_RECEIVE_BREAKS);
flags.remove(CAN_RECEIVE_NONLOCAL_RETURNS);
rescueMap = null;

// Invalidate compiler pass state.
//
@@ -94,7 +94,8 @@ public Instr clone(CloneInfo info) {
return new BreakInstr(returnValue.cloneForInlining(ii), scopeName);
}

return super.clone(ii);
throw new UnsupportedOperationException();
//return super.clone(ii);
}

@Override
@@ -33,7 +33,8 @@
public abstract class Instr {
public static final Operand[] EMPTY_OPERANDS = new Operand[] {};

private int ipc;
private int ipc; // Interpreter-only: instruction pointer
private int rpc; // Interpreter-only: rescue pointer
private final Operation operation;
// Is this instruction live or dead? During optimization passes, if this instruction
// causes no side-effects and the result of the instruction is not needed by anyone else,
@@ -43,6 +44,7 @@ public abstract class Instr {

public Instr(Operation operation) {
this.ipc = -1;
this.rpc = -1;
this.operation = operation;
}

@@ -56,10 +58,18 @@ public Operation getOperation() {
return operation;
}

@Interp
public int getIPC() { return ipc; }

@Interp
public void setIPC(int ipc) { this.ipc = ipc; }

@Interp
public int getRPC() { return rpc; }

@Interp
public void setRPC(int rpc) { this.rpc = rpc; }

// Does this instruction have side effects as a result of its operation
// This information is used in optimization phases to impact dead code elimination
// and other optimization passes
@@ -167,9 +177,7 @@ public void renameVars(Map<Operand, Operand> renameMap) {
* args and return values.
* @return a new instruction that can be used in the target scope.
*/
public Instr clone(CloneInfo info) {
throw new RuntimeException("clone: Not implemented for: " + this.getOperation());
}
public abstract Instr clone(CloneInfo info);

/**
* This method takes as input a map of operands to their values, and outputs
@@ -29,8 +29,8 @@ public String toString() {

@Override
public Instr clone(CloneInfo ii) {
// SSS FIXME: This is buggy! 'scope' might have changed because of cloning.
return this;
// Use original scope even if inlined -- so debugging / stack-traces are meaningful
return new LineNumberInstr(scope, lineNumber);
}

@Override
@@ -49,7 +49,8 @@ public Instr clone(CloneInfo info) {
return new NonlocalReturnInstr(returnValue.cloneForInlining(ii), methodName, maybeLambda);
}

return super.clone(ii);
throw new UnsupportedOperationException();
//return super.clone(ii);
}

@Override
@@ -54,7 +54,7 @@ public int getRest() {

@Override
public Instr clone(CloneInfo ii) {
return this;
return new RaiseArgumentErrorInstr(required, opt, rest, numArgs);
}

@Override
@@ -3,6 +3,7 @@
import org.jruby.ir.IRVisitor;
import org.jruby.ir.Operation;
import org.jruby.ir.operands.Operand;
import org.jruby.ir.transformations.inlining.CloneInfo;
import org.jruby.parser.StaticScope;
import org.jruby.runtime.DynamicScope;
import org.jruby.runtime.ThreadContext;
@@ -25,6 +26,11 @@ public Operand[] getOperands() {
return new Operand[0];
}

@Override
public Instr clone(CloneInfo ii) {
return new RaiseRequiredKeywordArgumentError(name);
}

@Override
public Object interpret(ThreadContext context, StaticScope currScope, DynamicScope currDynScope, IRubyObject self, Object[] temp) {
throw context.runtime.newArgumentError("missing keyword: " + name);
@@ -3,6 +3,7 @@
import org.jruby.ir.Operation;
import org.jruby.ir.operands.Operand;
import org.jruby.ir.operands.Variable;
import org.jruby.ir.transformations.inlining.CloneInfo;

public class ReceiveExceptionBase extends Instr implements ResultInstr, FixedArityInstr {
protected Variable result;
@@ -33,4 +34,10 @@ public String toString() {
public void updateResult(Variable v) {
this.result = v;
}

@Override
public Instr clone(CloneInfo info) {
throw new UnsupportedOperationException();
}

}
@@ -1,11 +1,16 @@
package org.jruby.ir.instructions;

import org.jruby.ir.IRVisitor;
import org.jruby.ir.Interp;
import org.jruby.ir.Operation;
import org.jruby.ir.operands.Operand;
import org.jruby.ir.operands.Variable;
import org.jruby.ir.transformations.inlining.CloneInfo;
import org.jruby.ir.transformations.inlining.SimpleCloneInfo;
import org.jruby.parser.StaticScope;
import org.jruby.runtime.DynamicScope;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;

public class ReceiveSelfInstr extends Instr implements ResultInstr, FixedArityInstr {
private Variable result;
@@ -26,10 +26,10 @@ public Operand[] getOperands() {

@Override
public Instr clone(CloneInfo ii) {
if (ii instanceof SimpleCloneInfo) return this;
if (ii instanceof SimpleCloneInfo) return new ThreadPollInstr(onBackEdge);

// Get rid of non-back-edge thread-poll instructions when scopes are inlined
return onBackEdge ? this : null;
return onBackEdge ? new ThreadPollInstr(onBackEdge) : null;
}

@Override
@@ -5,6 +5,7 @@
import org.jruby.ir.instructions.ResultInstr;
import org.jruby.ir.operands.Operand;
import org.jruby.ir.operands.Variable;
import org.jruby.ir.transformations.inlining.CloneInfo;

import java.util.Map;

@@ -44,4 +45,10 @@ public void simplifyOperands(Map<Operand, Operand> valueMap, boolean force) {
public String toString() {
return getResult() + " = " + getOperation() + "(" + val + ")";
}

@Override
public Instr clone(CloneInfo info) {
throw new UnsupportedOperationException();
}

}
@@ -510,11 +510,8 @@ private static void processOtherOp(ThreadContext context, Instr instr, Operation
}

private static IRubyObject interpret(ThreadContext context, IRubyObject self,
IRScope scope, Visibility visibility, RubyModule implClass, String name, IRubyObject[] args, Block block, Block.Type blockType)
{
IRScope scope, Visibility visibility, RubyModule implClass, String name, IRubyObject[] args, Block block, Block.Type blockType) {
Instr[] instrs = scope.getInstrsForInterpretation(blockType == Block.Type.LAMBDA);
Map<Integer, Integer> rescueMap = scope.getRescueMap();

int numTempVars = scope.getTemporaryVariablesCount();
Object[] temp = numTempVars > 0 ? new Object[numTempVars] : null;
int numFloatVars = scope.getFloatVariablesCount();
@@ -598,7 +595,7 @@ private static IRubyObject interpret(ThreadContext context, IRubyObject self,
extractToMethodToAvoidC2Crash(context, instr, t);

if (debug) LOG.info("in scope: " + scope + ", caught Java throwable: " + t + "; excepting instr: " + instr);
ipc = rescueMap.get(instr.getIPC());
ipc = instr.getRPC();
if (debug) LOG.info("ipc for rescuer: " + ipc);

if (ipc == -1) {
@@ -35,7 +35,7 @@ public void addUsedVariables(List<Variable> l) {
}

public Operand cloneForInlining(CloneInfo ii) {
return symbolName.cloneForInlining(ii);
return new DynamicSymbol(symbolName.cloneForInlining(ii));
}

@Override
@@ -50,7 +50,9 @@ public boolean equals(Object o) {
}

public Label clone() {
return new Label(prefix, id);
Label newL = new Label(prefix, id);
newL.setTargetPC(getTargetPC()); // Strictly not necessary, but, copy everything over
return newL;
}

@Override
@@ -1,5 +1,7 @@
package org.jruby.ir.operands;

import org.jruby.ir.transformations.inlining.SimpleCloneInfo;

/**
* When we optimize full local variables to be temporary ones we like to keep the name
* of what we renamed them as. This is just enough wrapper for us to maintain a nice
@@ -15,6 +17,11 @@ public TemporaryLocalReplacementVariable(String oldName, int offset) {
this.oldName = oldName;
}

@Override
public Variable clone(SimpleCloneInfo ii) {
return new TemporaryLocalReplacementVariable(oldName, offset);
}

@Override
public String getPrefix() {
return "%t_" + oldName + "_";
@@ -30,6 +30,16 @@ public abstract class CompilerPass {
*/
public abstract String getLabel();

@Override
public int hashCode() {
return getLabel().hashCode();
}

@Override
public boolean equals(Object other) {
return (other != null) && (other instanceof CompilerPass) && (getLabel() == ((CompilerPass)other).getLabel());
}

/**
* Meat of an individual pass. run will call this after dependency
* resolution.
@@ -177,6 +177,7 @@ public void cloneInstrs(SimpleCloneInfo ii) {
for (Instr i: oldInstrs) {
Instr clonedInstr = i.clone(ii);
clonedInstr.setIPC(i.getIPC());
clonedInstr.setRPC(i.getRPC());
instrs.add(clonedInstr);
}
}

0 comments on commit 450c4b5

Please sign in to comment.