Package org.renjin.compiler

Source Code of org.renjin.compiler.ClosureCompiler$MyClassLoader

package org.renjin.compiler;

import java.io.PrintWriter;
import java.util.List;
import java.util.Map.Entry;

import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.util.TraceClassVisitor;
import org.renjin.compiler.cfg.BasicBlock;
import org.renjin.compiler.cfg.ControlFlowGraph;
import org.renjin.compiler.ir.tac.IRBodyBuilder;
import org.renjin.compiler.ir.tac.IRFunction;
import org.renjin.compiler.ir.tac.IRFunctionTable;
import org.renjin.compiler.ir.tac.statements.Statement;
import org.renjin.sexp.Closure;


public class ClosureCompiler implements Opcodes {

  private IRFunction closure;
  private ClassWriter cw;
  private ClassVisitor cv;
  private GenerationContext generationContext;

  public static Class<Closure> compileAndLoad(IRFunction closure) {
    return new ClosureCompiler("Closure" + System.identityHashCode(closure))
      .doCompileAndLoad(closure);
  }
 
  public static Class<Closure> compileAndLoad(Closure closureSexp) {
    IRFunctionTable functionTable = new IRFunctionTable();
    IRBodyBuilder builder = new IRBodyBuilder(functionTable);
    return compileAndLoad(new IRFunction(closureSexp.getFormals(), closureSexp.getBody(), builder.build(closureSexp.getBody())));
  }
 
  public static byte[] compile(String className, IRFunction closure) {
    return new ClosureCompiler(className)
    .doCompile(closure);   
  }
 
  public ClosureCompiler(String className) {
    super();
   
    this.generationContext = new GenerationContext(className,
        new FieldSexpPool(className),
        new ThunkMap(className + "$thunk$"));
  }

  public byte[] doCompile(IRFunction closure) {
    this.closure = closure;
    startClass();
    writeDoEval();
    writeConstructor();
    writeFormals();
    writeBodySexp();
    generationContext.getSexpPool().writeFields(cv);
    writeClassEnd();
    return cw.toByteArray();
  }

  public Class<Closure> doCompileAndLoad(IRFunction closure) {
    return new MyClassLoader().defineClass(generationContext.getClassName().replace('/', '.'), doCompile(closure));
  }
 
  private void startClass() {
    cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES) {

      @Override
      protected String getCommonSuperClass(String className1, String className2) {
        return super.getCommonSuperClass(
            resolveForwardReference(className1),
            resolveForwardReference(className2));
      }
     
    };
    cv = cw;
    //cv = new TraceClassVisitor(cw, new PrintWriter(System.out));
  //  cv = new CheckClassAdapter(cv);
    cv.visit(V1_6, ACC_PUBLIC + ACC_SUPER, generationContext.getClassName(), null, "org/renjin/sexp/Closure", null);

  }
 
  private String resolveForwardReference(String className) {
    if(className.contains("$closure$")) {
      return "org/renjin/sexp/Closure";
    } else {
      return className;
    }
  }

  private void writeConstructor() {

    MethodVisitor mv = cv.visitMethod(ACC_PUBLIC, "<init>", "(Lorg/renjin/sexp/Environment;)V", null, null);
    mv.visitCode();
    mv.visitVarInsn(ALOAD, 0);
    mv.visitVarInsn(ALOAD, 1);
    mv.visitMethodInsn(INVOKESTATIC, generationContext.getClassName(), "createFormals", "()Lorg/renjin/sexp/PairList;");
    mv.visitMethodInsn(INVOKESTATIC, generationContext.getClassName(), "createBody", "()Lorg/renjin/sexp/SEXP;");
    mv.visitMethodInsn(INVOKESPECIAL, "org/renjin/sexp/Closure", "<init>", "(Lorg/renjin/sexp/Environment;Lorg/renjin/sexp/PairList;Lorg/renjin/sexp/SEXP;)V");
     
    generationContext.getSexpPool().writeConstructorBody(mv);
   
    mv.visitInsn(RETURN);
    mv.visitMaxs(1, 1);
    mv.visitEnd();
  }

  private void writeDoEval() {
    MethodVisitor mv = cv.visitMethod(ACC_PUBLIC, "doApply",
        "(Lorg/renjin/eval/Context;)Lorg/renjin/sexp/SEXP;", null, null);
    mv.visitCode();
    mv.visitVarInsn(ALOAD, 1);
    mv.visitMethodInsn(INVOKEVIRTUAL, "org/renjin/eval/Context", "getEnvironment", "()Lorg/renjin/sexp/Environment;");
    mv.visitVarInsn(ASTORE, 2);

    writeDoEvalBody(mv);
   
    mv.visitMaxs(1, 1);
    mv.visitEnd();
  }
 
  private void writeFormals() {
 
    MethodVisitor mv = cv.visitMethod(ACC_PRIVATE + ACC_STATIC,
        "createFormals", "()Lorg/renjin/sexp/PairList;", null, null);
    mv.visitCode();
   
    ConstantGeneratingVisitor cgv = new ConstantGeneratingVisitor(mv);
    closure.getFormals().accept(cgv);
    mv.visitInsn(ARETURN);
    mv.visitMaxs(1, 0);
    mv.visitEnd();
  }

  private void writeBodySexp() {

    MethodVisitor mv = cv.visitMethod(ACC_PRIVATE + ACC_STATIC,
        "createBody", "()Lorg/renjin/sexp/SEXP;", null, null);
    mv.visitCode();
    ConstantGeneratingVisitor cgv = new ConstantGeneratingVisitor(mv);
    closure.getBodyExpression().accept(cgv);
    mv.visitInsn(ARETURN);
    mv.visitMaxs(1, 0);
    mv.visitEnd();
}
  private void writeDoEvalBody(MethodVisitor mv) {
    ByteCodeVisitor visitor = new ByteCodeVisitor(generationContext, mv);
   
   
    ControlFlowGraph cfg = new ControlFlowGraph(closure.getBody());
    for(BasicBlock bb : cfg.getBasicBlocks()) {
     
      System.out.println(bb.statementsToString());
     
      visitor.startBasicBlock(bb);
     
    //  List<Statement> statements = TreeBuilder.build(bb);
      for(Statement stmt : bb.getStatements()) {
        stmt.accept(visitor);
      }
    }
  }

  private void writeClassEnd() {
    cv.visitEnd();
  }

  class MyClassLoader extends ClassLoader {
    public Class defineClass(String name, byte[] b) {
      return defineClass(name, b, 0, b.length);
   }
  }

  public List<Entry<String, IRFunction>> getNestedClosures() {
    return generationContext.getNestedClosures();
  }

  public ThunkMap getThunkMap() {
    return generationContext.getThunkMap();
  }
}
TOP

Related Classes of org.renjin.compiler.ClosureCompiler$MyClassLoader

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.