Skip to content

Commit

Permalink
Add full IC support to IR printing and hook up at point of use.
Browse files Browse the repository at this point in the history
  • Loading branch information
headius committed Jan 20, 2016
1 parent 567509b commit 88725bc
Show file tree
Hide file tree
Showing 8 changed files with 145 additions and 45 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import org.jruby.ir.IRMethod;
import org.jruby.ir.IRScope;
import org.jruby.ir.interpreter.InterpreterContext;
import org.jruby.ir.persistence.IRDumper;
import org.jruby.ir.runtime.IRRuntimeHelpers;
import org.jruby.parser.StaticScope;
import org.jruby.runtime.ArgumentDescriptor;
Expand All @@ -22,6 +23,8 @@
import org.jruby.util.log.Logger;
import org.jruby.util.log.LoggerFactory;

import java.io.ByteArrayOutputStream;

/**
* Method for -X-C (interpreted only execution). See MixedModeIRMethod for inter/JIT method impl.
*/
Expand Down Expand Up @@ -96,6 +99,12 @@ public InterpreterContext ensureInstrsReady() {
interpreterContext = ((IRMethod) method).lazilyAcquireInterpreterContext();
}
interpreterContext = method.getInterpreterContext();

if (Options.IR_PRINT.load()) {
ByteArrayOutputStream baos = IRDumper.printIR(method, false);

LOG.info("Printing simple IR for " + method.getName(), "\n" + new String(baos.toByteArray()));
}
}

return interpreterContext;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import org.jruby.compiler.Compilable;
import org.jruby.ir.*;
import org.jruby.ir.interpreter.InterpreterContext;
import org.jruby.ir.persistence.IRDumper;
import org.jruby.ir.runtime.IRRuntimeHelpers;
import org.jruby.parser.StaticScope;
import org.jruby.runtime.ArgumentDescriptor;
Expand All @@ -21,6 +22,8 @@
import org.jruby.util.log.Logger;
import org.jruby.util.log.LoggerFactory;

import java.io.ByteArrayOutputStream;

public class MixedModeIRMethod extends DynamicMethod implements IRMethodArgs, PositionAware, Compilable<DynamicMethod> {
private static final Logger LOG = LoggerFactory.getLogger("InterpretedIRMethod");

Expand Down Expand Up @@ -97,7 +100,16 @@ public InterpreterContext ensureInstrsReady() {
if (method instanceof IRMethod) {
return ((IRMethod) method).lazilyAcquireInterpreterContext();
}
return method.getInterpreterContext();

InterpreterContext ic = method.getInterpreterContext();

if (Options.IR_PRINT.load()) {
ByteArrayOutputStream baos = IRDumper.printIR(method, false);

LOG.info("Printing simple IR for " + method.getName(), "\n" + new String(baos.toByteArray()));
}

return ic;
}

@Override
Expand Down
8 changes: 7 additions & 1 deletion core/src/main/java/org/jruby/ir/IRMethod.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,13 @@
import org.jruby.ast.DefNode;
import org.jruby.ir.interpreter.InterpreterContext;
import org.jruby.ir.operands.LocalVariable;
import org.jruby.ir.persistence.IRDumper;
import org.jruby.ir.representations.BasicBlock;
import org.jruby.parser.StaticScope;
import org.jruby.runtime.ArgumentDescriptor;
import org.jruby.util.cli.Options;

import java.io.ByteArrayOutputStream;

public class IRMethod extends IRScope {
public final boolean isInstanceMethod;
Expand Down Expand Up @@ -45,7 +49,9 @@ public synchronized InterpreterContext lazilyAcquireInterpreterContext() {
public synchronized BasicBlock[] prepareForCompilation() {
if (!hasBeenBuilt()) lazilyAcquireInterpreterContext();

return super.prepareForCompilation();
BasicBlock[] bbs = super.prepareForCompilation();

return bbs;
}

@Override
Expand Down
10 changes: 0 additions & 10 deletions core/src/main/java/org/jruby/ir/IRScope.java
Original file line number Diff line number Diff line change
Expand Up @@ -584,19 +584,9 @@ public synchronized BasicBlock[] prepareForCompilation() {

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
// construct a new fullInterpreterContext. Primary obstacles is JITFlags and linearization of BBs.

Expand Down
107 changes: 82 additions & 25 deletions core/src/main/java/org/jruby/ir/persistence/IRDumper.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import org.jruby.ir.IRVisitor;
import org.jruby.ir.instructions.Instr;
import org.jruby.ir.instructions.ResultInstr;
import org.jruby.ir.interpreter.FullInterpreterContext;
import org.jruby.ir.interpreter.InterpreterContext;
import org.jruby.ir.operands.Array;
import org.jruby.ir.operands.AsString;
Expand Down Expand Up @@ -53,9 +54,12 @@
import org.jruby.ir.operands.UnexecutableNil;
import org.jruby.ir.operands.Variable;
import org.jruby.ir.operands.WrappedIRClosure;
import org.jruby.ir.representations.BasicBlock;
import org.jruby.runtime.Signature;
import org.jruby.util.KeyValuePair;
import org.jruby.util.cli.Options;

import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.lang.reflect.Field;
import java.util.Arrays;
Expand All @@ -72,11 +76,24 @@ public IRDumper(PrintStream ps, boolean color) {
this.color = color;
}

public void visit(IRScope scope, boolean recurse) {
public static ByteArrayOutputStream printIR(IRScope scope, boolean full) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
PrintStream ps = new PrintStream(baos);
IRDumper dumper = new IRDumper(ps, Options.IR_PRINT_COLOR.load());
dumper.visit(scope, full, false);
return baos;
}

public void visit(IRScope scope, boolean full, boolean recurse) {
println("begin " + scope.getScopeType().name() + "<" + scope.getName() + ">");

scope.prepareForCompilation();
InterpreterContext ic = scope.getInterpreterContext();
InterpreterContext ic;

if (full) {
ic = scope.getFullInterpreterContext();
} else {
ic = scope.getInterpreterContext();
}

if (ic.getStaticScope().getSignature() == null) {
println(Signature.NO_ARGUMENTS);
Expand Down Expand Up @@ -108,38 +125,51 @@ public void visit(IRScope scope, boolean recurse) {

// find longest variable name
int longest = 0;

for (Instr i : instrs) {
if (i instanceof ResultInstr) {
Variable result = ((ResultInstr) i).getResult();

longest = Math.max(longest, result.getName().length() + ((result instanceof LocalVariable) ? 1 : 0));
int largestBlock = 0;

if (instrs != null) {
largestBlock = instrs.length;
for (Instr i : instrs) {
if (i instanceof ResultInstr) {
longest = getLongestVariable(longest, (ResultInstr) i);
}
}
} else {
BasicBlock[] bbs = ((FullInterpreterContext)ic).getLinearizedBBList();

for (BasicBlock bb : bbs) {
List<Instr> instrList = bb.getInstrs();
largestBlock = Math.max(largestBlock, instrList.size());
for (Instr i : instrList) {
if (i instanceof ResultInstr) {
longest = getLongestVariable(longest, (ResultInstr) i);
}
}
}
}

int instrLog = (int)Math.log10(instrs.length) + 1;
int instrLog = (int)Math.log10(largestBlock) + 1;

String varFormat = ansiStr(VARIABLE_COLOR, "%" + longest + "s") + " := ";
String varSpaces = spaces(longest + " := ".length());
String ipcFormat = "%0" + instrLog + "d: ";
String ipcFormat = " %0" + instrLog + "d: ";

for (int i = 0; i < instrs.length; i++) {
Instr instr = instrs[i];
if (instrs != null) {
for (int i = 0; i < instrs.length; i++) {
formatInstr(instrs[i], varFormat, varSpaces, ipcFormat, instrs[i], i);
}
} else {
BasicBlock[] bbs = ((FullInterpreterContext)ic).getLinearizedBBList();

printf(ipcFormat, i);
for (BasicBlock bb : bbs) {
printAnsi(BLOCK_COLOR, "\nbasic_block #" + bb.getID() + ": " + bb.getLabel() + "\n");

if (instr instanceof ResultInstr) {
Variable result = ((ResultInstr) instr).getResult();
String sigilName = (result instanceof LocalVariable) ? "*" + result.getName() : result.getName();
List<Instr> instrList = bb.getInstrs();

printf(varFormat, sigilName);
} else {
print(varSpaces);
for (int i = 0; i < instrList.size(); i++) {
formatInstr(instrList.get(i), varFormat, varSpaces, ipcFormat, instrList.get(i), i);
}
}

visit(instrs[i]);

println();
}

if (recurse && !scope.getClosures().isEmpty()) {
Expand All @@ -148,11 +178,37 @@ public void visit(IRScope scope, boolean recurse) {
for (IRClosure closure : scope.getClosures()) {
if (closure == scope) continue;

visit(closure, true);
visit(closure, full, true);
}
}
}

public void formatInstr(Instr instr1, String varFormat, String varSpaces, String ipcFormat, Instr instr2, int i) {
Instr instr = instr2;

printf(ipcFormat, i);

if (instr instanceof ResultInstr) {
Variable result = ((ResultInstr) instr).getResult();
String sigilName = (result instanceof LocalVariable) ? "*" + result.getName() : result.getName();

printf(varFormat, sigilName);
} else {
print(varSpaces);
}

visit(instr1);

println();
}

public int getLongestVariable(int longest, ResultInstr i) {
Variable result = i.getResult();

longest = Math.max(longest, result.getName().length() + ((result instanceof LocalVariable) ? 1 : 0));
return longest;
}

@Override
public void visit(Instr instr) {
printAnsi(INSTR_COLOR, instr.getOperation().toString().toLowerCase());
Expand Down Expand Up @@ -313,5 +369,6 @@ private void printf(String format, Object... objs) {
private static final String OPERAND_COLOR = "\033[1;33m";
private static final String VARIABLE_COLOR = "\033[1;32m";
private static final String FIELD_COLOR = "\033[1;34m";
private static final String BLOCK_COLOR = "\033[4;31m";
private static final String CLEAR_COLOR = "\033[0m";
}
24 changes: 16 additions & 8 deletions core/src/main/java/org/jruby/ir/targets/JVMVisitor.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import org.jruby.ir.operands.Boolean;
import org.jruby.ir.operands.Float;
import org.jruby.ir.operands.Label;
import org.jruby.ir.persistence.IRDumper;
import org.jruby.ir.representations.BasicBlock;
import org.jruby.ir.runtime.IRRuntimeHelpers;
import org.jruby.parser.StaticScope;
Expand All @@ -42,6 +43,7 @@
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.Method;

import java.io.ByteArrayOutputStream;
import java.lang.invoke.MethodType;
import java.util.HashMap;
import java.util.Iterator;
Expand Down Expand Up @@ -130,9 +132,15 @@ public void codegenScriptBody(IRScriptBody script) {
emitScriptBody(script);
}

public void emitScope(IRScope scope, String name, Signature signature, boolean specificArity) {
public void emitScope(IRScope scope, String name, Signature signature, boolean specificArity, boolean print) {
BasicBlock[] bbs = scope.prepareForCompilation();

if (print && Options.IR_PRINT.load()) {
ByteArrayOutputStream baos = IRDumper.printIR(scope, true);

LOG.info("Printing JIT IR for " + scope.getName(), "\n" + new String(baos.toByteArray()));
}

Map <BasicBlock, Label> exceptionTable = scope.buildJVMExceptionTable();

emitClosures(scope);
Expand Down Expand Up @@ -237,7 +245,7 @@ public void emitScriptBody(IRScriptBody script) {
String clsName = jvm.scriptToClass(script.getFileName());
jvm.pushscript(clsName, script.getFileName());

emitScope(script, name, signatureFor(script, false), false);
emitScope(script, name, signatureFor(script, false), false, true);

jvm.cls().visitEnd();
jvm.popclass();
Expand Down Expand Up @@ -265,7 +273,7 @@ public void emitBlockJIT(IRClosure closure, JVMVisitorMethodContext context) {
String name = JavaNameMangler.encodeScopeForBacktrace(closure) + "$" + methodIndex++;
jvm.pushscript(clsName, closure.getFileName());

emitScope(closure, name, CLOSURE_SIGNATURE, false);
emitScope(closure, name, CLOSURE_SIGNATURE, false, true);

context.setJittedName(name);

Expand All @@ -277,12 +285,12 @@ private void emitWithSignatures(IRMethod method, JVMVisitorMethodContext context
context.setJittedName(name);

Signature signature = signatureFor(method, false);
emitScope(method, name, signature, false);
emitScope(method, name, signature, false, true);
context.addNativeSignature(-1, signature.type());

Signature specificSig = signatureFor(method, true);
if (specificSig != null) {
emitScope(method, name, specificSig, true);
emitScope(method, name, specificSig, true, false);
context.addNativeSignature(method.getStaticScope().getSignature().required(), specificSig.type());
}
}
Expand All @@ -294,7 +302,7 @@ public Handle emitModuleBodyJIT(IRModuleBody method) {
jvm.pushscript(clsName, method.getFileName());

Signature signature = signatureFor(method, false);
emitScope(method, name, signature, false);
emitScope(method, name, signature, false, true);

Handle handle = new Handle(Opcodes.H_INVOKESTATIC, jvm.clsData().clsName, name, sig(signature.type().returnType(), signature.type().parameterArray()));

Expand All @@ -315,7 +323,7 @@ public Handle emitClosure(IRClosure closure) {
/* Compile the closure like a method */
String name = JavaNameMangler.encodeScopeForBacktrace(closure) + "$" + methodIndex++;

emitScope(closure, name, CLOSURE_SIGNATURE, false);
emitScope(closure, name, CLOSURE_SIGNATURE, false, true);

return new Handle(Opcodes.H_INVOKESTATIC, jvm.clsData().clsName, name, sig(CLOSURE_SIGNATURE.type().returnType(), CLOSURE_SIGNATURE.type().parameterArray()));
}
Expand All @@ -324,7 +332,7 @@ public Handle emitModuleBody(IRModuleBody method) {
String name = JavaNameMangler.encodeScopeForBacktrace(method) + "$" + methodIndex++;

Signature signature = signatureFor(method, false);
emitScope(method, name, signature, false);
emitScope(method, name, signature, false, true);

return new Handle(Opcodes.H_INVOKESTATIC, jvm.clsData().clsName, name, sig(signature.type().returnType(), signature.type().parameterArray()));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,15 @@
import org.jruby.ir.IRScope;
import org.jruby.ir.interpreter.Interpreter;
import org.jruby.ir.interpreter.InterpreterContext;
import org.jruby.ir.persistence.IRDumper;
import org.jruby.ir.runtime.IRRuntimeHelpers;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.util.cli.Options;
import org.jruby.util.log.Logger;
import org.jruby.util.log.LoggerFactory;

import java.io.ByteArrayOutputStream;

public class InterpretedIRBlockBody extends IRBlockBody implements Compilable<InterpreterContext> {
private static final Logger LOG = LoggerFactory.getLogger("InterpretedIRBlockBody");
protected boolean pushScope;
Expand Down Expand Up @@ -65,6 +68,12 @@ public InterpreterContext ensureInstrsReady() {
}

if (interpreterContext == null) {
if (Options.IR_PRINT.load()) {
ByteArrayOutputStream baos = IRDumper.printIR(closure, false);

LOG.info("Printing simple IR for " + closure.getName(), "\n" + new String(baos.toByteArray()));
}

interpreterContext = closure.getInterpreterContext();
fullInterpreterContext = interpreterContext;
}
Expand Down
Loading

0 comments on commit 88725bc

Please sign in to comment.