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: 4b1b8a8d4297
Choose a base ref
...
head repository: jruby/jruby
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 504daca86a16
Choose a head ref
  • 7 commits
  • 15 files changed
  • 1 contributor

Commits on Jan 7, 2016

  1. Minor whitespace.

    headius committed Jan 7, 2016
    Copy the full SHA
    5c06c34 View commit details
  2. Copy the full SHA
    05e82a8 View commit details
  3. Remove the brackets since they're just extra noise.

    Only ClosureLocalVariable has this flag anyway.
    headius committed Jan 7, 2016
    Copy the full SHA
    ca54287 View commit details
  4. Copy the full SHA
    6408afc View commit details
  5. Add a new pretty-printing IR dumper.

    The goal here is to keep the dumper as simple as possible, so I've
    started out using reflection APIs to walk internal state in the
    IR rather than relying on one-off methods in each Instr.
    
    The reflective field walk will skip any fields marked as
    transient. This is perhaps an unusual overloading of the Java
    transient keyword, but I justify it thusly:
    
    * It's cleaner than introducing and querying an annotation.
    * It is at least somewhat related to externalization of an
      object graph.
    * We have no intention to EVER use automatic serialization for
      our IR.
    * Maintaining a separate map of which fields to display would
      have been error-prone and required custom code in each Instr.
    
    The format is designed to be as readable as possible, so I set it
    up to center on assignment to temp vars (registers) since that is
    what throws off my reading of current IR dumping more than any
    other factor.
    
    ANSI color is supported to help different types of IR object pop
    a bit more.
    headius committed Jan 7, 2016
    Copy the full SHA
    5a18b9c View commit details
  6. Copy the full SHA
    26f3fe5 View commit details
  7. Copy the full SHA
    504daca View commit details
34 changes: 29 additions & 5 deletions core/src/main/java/org/jruby/ir/IRScope.java
Original file line number Diff line number Diff line change
@@ -13,15 +13,19 @@
import org.jruby.ir.operands.Float;
import org.jruby.ir.operands.Boolean;
import org.jruby.ir.passes.*;
import org.jruby.ir.persistence.IRDumper;
import org.jruby.ir.representations.BasicBlock;
import org.jruby.ir.representations.CFG;
import org.jruby.ir.transformations.inlining.CFGInliner;
import org.jruby.ir.transformations.inlining.SimpleCloneInfo;
import org.jruby.parser.StaticScope;

import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;

import org.jruby.util.cli.Options;
import org.jruby.util.log.Logger;
import org.jruby.util.log.LoggerFactory;

@@ -89,10 +93,10 @@ public abstract class IRScope implements ParseResult {
private final StaticScope staticScope;

/** Local variables defined in this scope */
private Set<Variable> definedLocalVars;
private Set<LocalVariable> definedLocalVars;

/** Local variables used in this scope */
private Set<Variable> usedLocalVars;
private Set<LocalVariable> usedLocalVars;

/** Startup interpretation depends on this */
protected InterpreterContext interpreterContext;
@@ -563,6 +567,7 @@ public synchronized FullInterpreterContext prepareFullBuild() {
if (!isUnsafeScope()) new AddCallProtocolInstructions().run(this);

fullInterpreterContext.generateInstructionsForIntepretation();

return fullInterpreterContext;
}

@@ -577,7 +582,19 @@ public synchronized BasicBlock[] prepareForCompilation() {

runCompilerPasses(getManager().getJITPasses(this));

return fullInterpreterContext.linearizeBasicBlocks();
BasicBlock[] bbs = fullInterpreterContext.linearizeBasicBlocks();

if (Options.IR_PRINT.load()) printIR();

return bbs;
}

public void printIR() {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
PrintStream ps = new PrintStream(baos);
IRDumper dumper = new IRDumper(ps, Options.IR_PRINT_COLOR.load());
dumper.visit(this, false);
LOG.info("Printing final IR for " + getName(), "\n" + new String(baos.toByteArray()));
}

// FIXME: For inlining, culmulative or extra passes run based on profiled execution we need to re-init data or even
@@ -760,6 +777,13 @@ public Map<String, LocalVariable> getLocalVariables() {
return localVars;
}

/**
* Get all variables referenced by this scope.
*/
public Set<LocalVariable> getUsedLocalVariables() {
return usedLocalVars;
}

/**
* Set the local variables for this scope. This should only be used by persistence layer.
*/
@@ -920,13 +944,13 @@ public void setUpUseDefLocalVarMaps() {
for (BasicBlock bb : getCFG().getBasicBlocks()) {
for (Instr i : bb.getInstrs()) {
for (Variable v : i.getUsedVariables()) {
if (v instanceof LocalVariable) usedLocalVars.add(v);
if (v instanceof LocalVariable) usedLocalVars.add((LocalVariable) v);
}

if (i instanceof ResultInstr) {
Variable v = ((ResultInstr) i).getResult();

if (v instanceof LocalVariable) definedLocalVars.add(v);
if (v instanceof LocalVariable) definedLocalVars.add((LocalVariable) v);
}
}
}
24 changes: 12 additions & 12 deletions core/src/main/java/org/jruby/ir/instructions/CallBase.java
Original file line number Diff line number Diff line change
@@ -22,20 +22,20 @@
public abstract class CallBase extends NOperandInstr implements ClosureAcceptingInstr {
private static long callSiteCounter = 1;

public final long callSiteId;
public transient final long callSiteId;
private final CallType callType;
protected String name;
protected CallSite callSite;
protected int argsCount;
protected boolean hasClosure;

private boolean flagsComputed;
private boolean canBeEval;
private boolean targetRequiresCallersBinding; // Does this call make use of the caller's binding?
private boolean targetRequiresCallersFrame; // Does this call make use of the caller's frame?
private boolean dontInline;
private boolean containsArgSplat;
private boolean procNew;
protected transient CallSite callSite;
protected transient int argsCount;
protected transient boolean hasClosure;

private transient boolean flagsComputed;
private transient boolean canBeEval;
private transient boolean targetRequiresCallersBinding; // Does this call make use of the caller's binding?
private transient boolean targetRequiresCallersFrame; // Does this call make use of the caller's frame?
private transient boolean dontInline;
private transient boolean containsArgSplat;
private transient boolean procNew;
private boolean potentiallyRefined;

protected CallBase(Operation op, CallType callType, String name, Operand receiver, Operand[] args, Operand closure,
Original file line number Diff line number Diff line change
@@ -20,7 +20,7 @@
* args field: [self, receiver, *args]
*/
public class CallInstr extends CallBase implements ResultInstr {
protected Variable result;
protected transient Variable result;

public static CallInstr create(IRScope scope, Variable result, String name, Operand receiver, Operand[] args, Operand closure) {
return create(scope, CallType.NORMAL, result, name, receiver, args, closure);
8 changes: 4 additions & 4 deletions core/src/main/java/org/jruby/ir/instructions/Instr.java
Original file line number Diff line number Diff line change
@@ -36,13 +36,13 @@
public abstract class Instr {
public static final Operand[] EMPTY_OPERANDS = new Operand[0];

private int ipc; // Interpreter-only: instruction pointer
private int rpc; // Interpreter-only: rescue pointer
private final Operation operation;
private transient int ipc; // Interpreter-only: instruction pointer
private transient int rpc; // Interpreter-only: rescue pointer
private transient 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,
// we can remove this instruction altogether without affecting program correctness.
private boolean isDead;
private transient boolean isDead;

public Instr(Operation operation) {
this.ipc = -1;
Original file line number Diff line number Diff line change
@@ -7,7 +7,7 @@
* For Instrs with an arbitrary number of Operands.
*/
public abstract class NOperandInstr extends Instr {
protected Operand[] operands;
protected transient Operand[] operands;

public NOperandInstr(Operation operation, Operand[] operands) {
super(operation);
Original file line number Diff line number Diff line change
@@ -8,7 +8,7 @@
* Created by enebo on 7/28/15.
*/
public abstract class NOperandResultBaseInstr extends ResultBaseInstr {
private Operand[] operands;
private transient Operand[] operands;

public NOperandResultBaseInstr(Operation operation, Variable result, Operand[] operands) {
super(operation, result);
Original file line number Diff line number Diff line change
@@ -7,7 +7,7 @@
* Created by enebo on 7/27/15.
*/
public abstract class OneOperandInstr extends Instr {
private Operand operand1;
private transient Operand operand1;

public OneOperandInstr(Operation operation, Operand operand1) {
super(operation);
Original file line number Diff line number Diff line change
@@ -8,7 +8,7 @@
* Result Instr with one operand.
*/
public abstract class OneOperandResultBaseInstr extends ResultBaseInstr {
private Operand operand1;
private transient Operand operand1;

public OneOperandResultBaseInstr(Operation operation, Variable result, Operand operand1) {
super(operation, result);
Original file line number Diff line number Diff line change
@@ -10,7 +10,7 @@
* logic.
*/
public abstract class ResultBaseInstr extends Instr implements ResultInstr {
protected Variable result;
protected transient Variable result;

public ResultBaseInstr(Operation operation, Variable result) {
super(operation);
Original file line number Diff line number Diff line change
@@ -8,8 +8,8 @@
* Result Instr with two operands.
*/
public abstract class TwoOperandResultBaseInstr extends ResultBaseInstr {
private Operand operand1;
private Operand operand2;
private transient Operand operand1;
private transient Operand operand2;

public TwoOperandResultBaseInstr(Operation operation, Variable result, Operand operand1, Operand operand2) {
super(operation, result);
Original file line number Diff line number Diff line change
@@ -72,6 +72,6 @@ public void encode(IRWriterEncoder e) {

@Override
public String toString() {
return "<" + name + "(" + scopeDepth + ":" + offset + ":local=" + definedLocally + ")>";
return name + "(" + scopeDepth + ":" + offset + ":local=" + definedLocally + ")";
}
}
84 changes: 45 additions & 39 deletions core/src/main/java/org/jruby/ir/operands/OperandType.java
Original file line number Diff line number Diff line change
@@ -7,50 +7,52 @@

public enum OperandType {

ARRAY((byte) 'A'),
AS_STRING((byte) 'a'),
BIGNUM((byte) 'B'),
BOOLEAN((byte) 'b'),
LOCAL_VARIABLE((byte) 'l'), // Also applicable for ClosureLocalVariable
COMPLEX((byte) 'C'),
CURRENT_SCOPE((byte) 's'),
DYNAMIC_SYMBOL((byte) 'd'),
FIXNUM((byte) 'f'),
FLOAT((byte) 'F'),
GLOBAL_VARIABLE((byte) '$'),
HASH((byte) '{'),
IR_EXCEPTION((byte) '!'),
LABEL((byte) 'L'),
NIL((byte) 'N'),
NTH_REF((byte) '1'),
OBJECT_CLASS((byte) 'O'),
RANGE((byte) '.'),
RATIONAL((byte) 'r'),
REGEXP((byte) '/'),
SCOPE_MODULE((byte) '_'),
SELF((byte) 'S'),
SPLAT((byte) '*'),
STANDARD_ERROR((byte) 'E'),
STRING_LITERAL((byte) '\''),
SVALUE((byte) 'V'),
SYMBOL((byte) ':'),
TEMPORARY_VARIABLE((byte) 't'),
UNBOXED_BOOLEAN((byte) 'v'),
UNBOXED_FIXNUM((byte) 'j'),
UNBOXED_FLOAT((byte) 'J'),
UNDEFINED_VALUE((byte) 'u'),
UNEXECUTABLE_NIL((byte) 'n'),
WRAPPED_IR_CLOSURE((byte) 'w'),
FROZEN_STRING((byte) 'z'),
NULL_BLOCK((byte) 'o'),
FILENAME((byte) 'm'),
SYMBOL_PROC((byte) 'P')
ARRAY("ary", (byte) 'A'),
AS_STRING("tostr", (byte) 'a'),
BIGNUM("big", (byte) 'B'),
BOOLEAN("bool", (byte) 'b'),
COMPLEX("com", (byte) 'C'),
CURRENT_SCOPE("scope", (byte) 's'),
DYNAMIC_SYMBOL("dsym", (byte) 'd'),
FIXNUM("fix", (byte) 'f'),
FLOAT("flo", (byte) 'F'),
GLOBAL_VARIABLE("$", (byte) '$'),
HASH("hash", (byte) '{'),
IR_EXCEPTION("ir_ex", (byte) '!'),
LABEL("ipc", (byte) 'L'),
LOCAL_VARIABLE("*", (byte) 'l'), // Also applicable for ClosureLocalVariable
NIL("nil", (byte) 'N'),
NTH_REF("nth", (byte) '1'),
OBJECT_CLASS("objcls", (byte) 'O'),
RANGE("rng", (byte) '.'),
RATIONAL("rat", (byte) 'r'),
REGEXP("reg", (byte) '/'),
SCOPE_MODULE("mod", (byte) '_'),
SELF("self", (byte) 'S'),
SPLAT("splat", (byte) '*'),
STANDARD_ERROR("stderr", (byte) 'E'),
STRING_LITERAL("str", (byte) '\''),
SVALUE("sval", (byte) 'V'),
SYMBOL("sym", (byte) ':'),
TEMPORARY_VARIABLE("reg", (byte) 't'),
UNBOXED_BOOLEAN("rawbool", (byte) 'v'),
UNBOXED_FIXNUM("rawfix", (byte) 'j'),
UNBOXED_FLOAT("rawflo", (byte) 'J'),
UNDEFINED_VALUE("undef", (byte) 'u'),
UNEXECUTABLE_NIL("noex", (byte) 'n'),
WRAPPED_IR_CLOSURE("block", (byte) 'w'),
FROZEN_STRING("fstr", (byte) 'z'),
NULL_BLOCK("noblock", (byte) 'o'),
FILENAME("file", (byte) 'm'),
SYMBOL_PROC("symproc", (byte) 'P')
;

private final String shortName;
private final byte coded;
private static final OperandType[] byteToOperand = new OperandType[256];

OperandType(byte coded) {
OperandType(String shortName, byte coded) {
this.shortName = shortName;
this.coded = coded;
}

@@ -63,6 +65,10 @@ public String toString() {
return name().toLowerCase();
};

public String shortName() {
return shortName;
}

public static OperandType fromCoded(byte coded) {
return byteToOperand[coded];
}
Loading