Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
   package org.jruby.ir.targets;
   
   import org.jruby.Ruby;
   import org.jruby.RubyBoolean;
   import org.jruby.RubyClass;
   import org.jruby.RubyModule;
   import org.jruby.RubyString;
  
  import java.util.Map;
  
  import static org.jruby.util.CodegenUtils.ci;
  import static org.jruby.util.CodegenUtils.p;
  import static org.jruby.util.CodegenUtils.sig;
  import  org.objectweb.asm.Type;
  import  org.objectweb.asm.commons.Method;

Implementation of IRCompiler for the JVM.
  
  public class JVMVisitor extends IRVisitor {
  
      public static final String DYNAMIC_SCOPE = "$dynamicScope";
 
     public JVMVisitor() {
         this. = new JVM();
     }
 
     public static Class compile(Ruby rubyIRScope scopeJRubyClassLoader jrubyClassLoader) {
         // run compiler
         JVMVisitor target = new JVMVisitor();
 
         target.codegen(scope);
 
 //        try {
 //            FileOutputStream fos = new FileOutputStream("tmp.class");
 //            fos.write(target.code());
 //            fos.close();
 //        } catch (Exception e) {
 //            e.printStackTrace();
 //        }
 
         return jrubyClassLoader.defineClass(JVM.scriptToClass(scope.getName()), target.code());
     }
 
     public byte[] code() {
         return .code();
     }
 
     public void codegen(IRScope scope) {
         if (scope instanceof IRScriptBody) {
             codegen((IRScriptBody)scope);
         }
     }
 
     public void codegen(IRScriptBody script) {
         this. = script;
         emit(script);
     }
 
     public String emitScope(IRScope scopeString nameint arity) {
         this. = scope;
         name = name + scope.getLineNumber();
         .pushmethod(namearity);
 
         Tuple<Instr[], Map<Integer,Label[]>> t = scope.prepareForCompilation();
         Instr[] instrs = t.a;
         Map<IntegerLabel[]> jumpTable = t.b;
 
         IRBytecodeAdapter m = .method();
         for (int i = 0; i < instrs.lengthi++) {
             Instr instr = instrs[i];
 
             if (jumpTable.get(i) != null) {
                 for (Label label : jumpTable.get(i)) m.mark(.methodData().getLabel(label));
             }
             visit(instr);
         }
 
         .popmethod();
 
         return name;
     }
 
     public void emit(IRScriptBody script) {
         String clsName = .scriptToClass(script.getName());
         .pushscript(clsNamescript.getFileName());
 
         emitScope(script"__script__", 0);
 
         .cls().visitEnd();
         .popclass();
     }
 
     public void emit(IRMethod method) {
         String name = emitScope(methodmethod.getName(), method.getCallArgs().length);
 
         // push a method handle for binding purposes
         .method().pushHandle(.clsData().namemethod.getStaticScope().getRequiredArgs());
     }
 
     public void emit(IRModuleBody method) {
         String name = method.getName();
         if (name.indexOf("DUMMY_MC") != -1) {
             name = "METACLASS";
         }
 
         name = emitScope(methodname, 0);
 
         // push a method handle for binding purposes
         .method().pushHandle(.clsData().namemethod.getStaticScope().getRequiredArgs());
     }
 
     public void visit(Instr instr) {
         instr.visit(this);
     }
 
     public void visit(Operand operand) {
         if (operand.hasKnownValue()) {
             operand.visit(this);
         } else if (operand instanceof Variable) {
             emitVariable((Variable)operand);
         } else {
             operand.visit(this);
         }
     }
 
     private int getJVMLocalVarIndex(Variable variable) {
         return .methodData().local(variable);
     }
 
     private int getJVMLocalVarIndex(String specialVar) {
         return .methodData().local(specialVar);
     }
 
     private org.objectweb.asm.Label getJVMLabel(Label label) {
         return .methodData().getLabel(label);
     }
 
     private void jvmStoreLocal(Variable variable) {
         .method().storeLocal(getJVMLocalVarIndex(variable));
     }
 
     private void jvmStoreLocal(String specialVar) {
         .method().storeLocal(getJVMLocalVarIndex(specialVar));
     }
 
     private void jvmLoadLocal(Variable variable) {
         .method().loadLocal(getJVMLocalVarIndex(variable));
     }
 
     private void jvmLoadLocal(String specialVar) {
         .method().loadLocal(getJVMLocalVarIndex(specialVar));
     }
 
     public void emitVariable(Variable variable) {
 //        System.out.println("variable: " + variable);
         int index = getJVMLocalVarIndex(variable);
 //        System.out.println("index: " + index);
         .method().loadLocal(index);
     }
 
 
     // JVM maintains a stack of ClassData (for nested classes being compiled)
     // Each class maintains a stack of MethodData (for methods being compiled in the class)
     // MethodData wraps a IRBytecodeAdapter which wraps a SkinnyMethodAdapter which has a ASM MethodVisitor which emits bytecode
     // A long chain of indirection: JVM -> MethodData -> IRBytecodeAdapter -> SkinnyMethodAdapter -> ASM.MethodVisitor
     // In some places, methods reference JVM -> MethodData -> IRBytecodeAdapter (via jvm.method()) and ask it to walk the last 2 links
     // In other places, methods reference JVM -> MethodData -> IRBytecodeAdapter -> SkinnyMethodAdapter (via jvm.method().adapter) and ask it to walk the last link
     // Can this be cleaned up to either (a) get rid of IRBytecodeAdapter OR (b) implement passthru' methods for SkinnyMethodAdapter methods (like the others it implements)?
 
     @Override
     public void AliasInstr(AliasInstr aliasInstr) {
         IRBytecodeAdapter m = .method();
         m.loadLocal(0);
         m.loadLocal(getJVMLocalVarIndex(aliasInstr.getReceiver()));
         m.adapter.ldc(((StringLiteralaliasInstr.getNewName()).);
         m.adapter.ldc(((StringLiteralaliasInstr.getOldName()).);
         m.invokeHelper("defineAlias"IRubyObject.classThreadContext.classIRubyObject.classObject.classObject.class);
         m.adapter.pop();
     }
 
     @Override
     public void AttrAssignInstr(AttrAssignInstr attrAssignInstr) {
         .method().loadLocal(0);
         visit(attrAssignInstr.getReceiver());
         for (Operand operand : attrAssignInstr.getCallArgs()) {
             visit(operand);
         }
 
         .method().invokeOther(attrAssignInstr.getMethodAddr().getName(), attrAssignInstr.getCallArgs().length);
         .method()..pop();
     }
 
     @Override
     public void BEQInstr(BEQInstr beqInstr) {
         Operand[] args = beqInstr.getOperands();
         .method().loadLocal(0);
         visit(args[0]);
         visit(args[1]);
         .method().invokeHelper("BEQ"boolean.classThreadContext.classIRubyObject.classIRubyObject.class);
         .method()..iftrue(getJVMLabel(beqInstr.getJumpTarget()));
     }
 
     @Override
     public void BFalseInstr(BFalseInstr bFalseInstr) {
         visit(bFalseInstr.getArg1());
         .method().isTrue();
         .method().bfalse(getJVMLabel(bFalseInstr.getJumpTarget()));
     }
 
     @Override
     public void BlockGivenInstr(BlockGivenInstr blockGivenInstr) {
         .method().loadRuntime();
         visit(blockGivenInstr.getBlockArg());
         .method().invokeVirtual(Type.getType(Block.class), Method.getMethod("boolean isGiven()"));
         .method().invokeVirtual(Type.getType(Ruby.class), Method.getMethod("org.jruby.RubyBoolean newBoolean(boolean)"));
         jvmStoreLocal(blockGivenInstr.getResult());
     }
 
     @Override
     public void BNEInstr(BNEInstr bneinstr) {
         Operand[] args = bneinstr.getOperands();
         .method().loadLocal(0);
         visit(args[0]);
         visit(args[1]);
         .method().invokeHelper("BNE"boolean.classThreadContext.classIRubyObject.classIRubyObject.class);
         .method()..iftrue(getJVMLabel(bneinstr.getJumpTarget()));
     }
 
     @Override
     public void BNilInstr(BNilInstr bnilinstr) {
         visit(bnilinstr.getArg1());
         .method().isNil();
         .method().btrue(getJVMLabel(bnilinstr.getJumpTarget()));
     }
 
     @Override
     public void BreakInstr(BreakInstr breakInstr) {
         IRBytecodeAdapter   m = .method();
         SkinnyMethodAdapter a = m.adapter;
         m.loadLocal(0); // context
         a.aload(1); // current scope
         // FIXME: This can also be done in the helper itself
         m.invokeVirtual(Type.getType(IRScope.class), Method.getMethod("org.jruby.ir.IRScope getIRScope()"));
         a.ldc(breakInstr.getScopeToReturnTo().getScopeId());
         visit(breakInstr.getReturnValue());
         // FIXME: emit block-type for the scope that is currently executing
         // For now, it is null
         m.pushNil();
         a.invokestatic(p(IRubyObject.class), "initiateBreak"sig(ThreadContext.classIRScope.classIRScope.classIRubyObject.classBlock.Type.class));
     }
 
     @Override
     public void BTrueInstr(BTrueInstr btrueinstr) {
         visit(btrueinstr.getArg1());
         .method().isTrue();
         .method().btrue(getJVMLabel(btrueinstr.getJumpTarget()));
     }
 
     @Override
     public void BUndefInstr(BUndefInstr bundefinstr) {
         visit(bundefinstr.getArg1());
         .method().pushUndefined();
         .method()..if_acmpeq(getJVMLabel(bundefinstr.getJumpTarget()));
     }
 
     @Override
     public void CallInstr(CallInstr callInstr) {
         IRBytecodeAdapter m = .method();
         String name = callInstr.getMethodAddr().getName();
         Operand[] args = callInstr.getCallArgs();
         int numArgs = args.length;
 
         if (   (name.equals("+") || name.equals("-") || name.equals("*") || name.equals("/"))
             && numArgs == 1
             && args[0] instanceof Fixnum
             && callInstr.getCallType() == .)
         {
             m.loadLocal(0);
             m.loadLocal(2); // dummy to satisfy signature of existing target linker (MathLinker)
             visit(callInstr.getReceiver());
             m.invokeFixnumOp(name, ((Fixnum)args[0]).);
         } else {
             m.loadLocal(0);
             visit(callInstr.getReceiver());
             for (Operand operand : args) {
                 visit(operand);
             }
             switch (callInstr.getCallType()) {
                 case :
                 case :
                     m.invokeSelf(namenumArgs);
                     break;
                 case :
                     m.invokeOther(namenumArgs);
                     break;
                 case :
                     m.invokeSuper(namenumArgs);
                     break;
             }
         }
 
         jvmStoreLocal(callInstr.getResult());
     }
 
     @Override
     public void CheckArgsArrayArityInstr(CheckArgsArrayArityInstr checkargsarrayarityinstr) {
         .method().loadContext();
         visit(checkargsarrayarityinstr.getArgsArray());
         .method()..pushInt(checkargsarrayarityinstr.required);
         .method()..pushInt(checkargsarrayarityinstr.opt);
         .method()..pushInt(checkargsarrayarityinstr.rest);
         .method().invokeStatic(Type.getType(Helpers.class), Method.getMethod("void irCheckArgsArrayArity(org.jruby.runtime.ThreadContext, org.jruby.RubyArray, int, int, int)"));
     }
 
     @Override
     public void CheckArityInstr(CheckArityInstr checkarityinstr) {
         // no-op for now
     }
 
     @Override
     public void ClassSuperInstr(ClassSuperInstr classsuperinstr) {
         super.ClassSuperInstr(classsuperinstr);    //To change body of overridden methods use File | Settings | File Templates.
     }
 
     @Override
     public void ConstMissingInstr(ConstMissingInstr constmissinginstr) {
         visit(constmissinginstr.getReceiver());
         .method()..checkcast("org/jruby/RubyModule");
         .method().loadContext();
         .method()..ldc("const_missing");
         .method().pushSymbol(constmissinginstr.getMissingConst());
         .method().invokeVirtual(Type.getType(RubyModule.class), Method.getMethod("org.jruby.runtime.builtin.IRubyObject callMethod(org.jruby.runtime.ThreadContext, java.lang.String, org.jruby.runtime.builtin.IRubyObject)"));
     }
 
     @Override
     public void CopyInstr(CopyInstr copyinstr) {
         int index = getJVMLocalVarIndex(copyinstr.getResult());
         visit(copyinstr.getSource());
         .method().storeLocal(index);
     }
 
     @Override
     public void DefineClassInstr(DefineClassInstr defineclassinstr) {
         IRClassBody newIRClassBody = defineclassinstr.getNewIRClassBody();
         StaticScope scope = newIRClassBody.getStaticScope();
         if (scope.getRequiredArgs() > 3 || scope.getRestArg() >= 0 || scope.getOptionalArgs() != 0) {
             throw new RuntimeException("can't compile variable method: " + this);
         }
 
         String scopeString = Helpers.encodeScope(scope);
 
         IRBytecodeAdapter   m = .method();
         SkinnyMethodAdapter a = m.adapter;
 
         // new CompiledIRMethod
         a.newobj(p(CompiledIRMethod.class));
         a.dup();
 
         // emit method body and get handle
         emit(newIRClassBody); // handle
 
         // add'l args for CompiledIRMethod constructor
         a.ldc(newIRClassBody.getName());
         a.ldc(newIRClassBody.getFileName());
         a.ldc(newIRClassBody.getLineNumber());
 
         // construct class with Helpers.newClassForIR
         a.aload(0); // ThreadContext
         a.ldc(newIRClassBody.getName()); // class name
         m.loadLocal(2); // self
 
         // create class
         m.loadLocal(0);
         visit(defineclassinstr.getContainer());
         m.invokeHelper("checkIsRubyModule"RubyModule.classThreadContext.classObject.class);
 
         // superclass
         if (defineclassinstr.getSuperClass() instanceof Nil) {
             a.aconst_null();
         } else {
             visit(defineclassinstr.getSuperClass());
         }
 
         // is meta?
         a.ldc(newIRClassBody instanceof IRMetaClassBody);
 
         m.invokeHelper("newClassForIR"RubyClass.classThreadContext.classString.classIRubyObject.classRubyModule.classObject.classboolean.class);
 
         //// static scope
         a.aload(0);
         a.aload(1);
         a.ldc(scopeString);
         a.invokestatic(p(Helpers.class), "decodeScope""(Lorg/jruby/runtime/ThreadContext;Lorg/jruby/parser/StaticScope;Ljava/lang/String;)Lorg/jruby/parser/StaticScope;");
         a.swap();
 
         // set into StaticScope
         a.dup2();
         a.invokevirtual(p(StaticScope.class), "setModule"sig(void.classRubyModule.class));
 
         a.getstatic(p(Visibility.class), "PUBLIC"ci(Visibility.class));
         a.swap();
 
         // invoke constructor
         a.invokespecial(p(CompiledIRMethod.class), "<init>""(Ljava/lang/invoke/MethodHandle;Ljava/lang/String;Ljava/lang/String;ILorg/jruby/parser/StaticScope;Lorg/jruby/runtime/Visibility;Lorg/jruby/RubyModule;)V");
 
         // store
         jvmStoreLocal(defineclassinstr.getResult());
     }
 
     @Override
     public void DefineClassMethodInstr(DefineClassMethodInstr defineclassmethodinstr) {
         super.DefineClassMethodInstr(defineclassmethodinstr);    //To change body of overridden methods use File | Settings | File Templates.
     }
 
     @Override
     public void DefineInstanceMethodInstr(DefineInstanceMethodInstr defineinstancemethodinstr) {
         IRMethod method = defineinstancemethodinstr.getMethod();
         StaticScope scope = method.getStaticScope();
         if (scope.getRequiredArgs() > 3 || scope.getRestArg() >= 0 || scope.getOptionalArgs() != 0) {
             throw new RuntimeException("can't compile variable method: " + this);
         }
 
         String scopeString = Helpers.encodeScope(scope);
 
         IRBytecodeAdapter   m = .method();
         SkinnyMethodAdapter a = m.adapter;
 
         // preamble for addMethod below
         a.aload(0);
         a.invokevirtual(p(ThreadContext.class), "getRubyClass""()Lorg/jruby/RubyModule;");
         a.ldc(method.getName());
 
         // new CompiledIRMethod
         a.newobj(p(CompiledIRMethod.class));
         a.dup();
 
         // emit method body and get handle
         emit(method); // handle
 
         // add'l args for CompiledIRMethod constructor
         a.ldc(method.getName());
         a.ldc(method.getFileName());
         a.ldc(method.getLineNumber());
 
         a.aload(0);
         a.aload(1);
         a.ldc(scopeString);
         a.invokestatic(p(Helpers.class), "decodeScope""(Lorg/jruby/runtime/ThreadContext;Lorg/jruby/parser/StaticScope;Ljava/lang/String;)Lorg/jruby/parser/StaticScope;");
 
         a.aload(0);
         a.invokevirtual(p(ThreadContext.class), "getCurrentVisibility""()Lorg/jruby/runtime/Visibility;");
         a.aload(0);
         a.invokevirtual(p(ThreadContext.class), "getRubyClass""()Lorg/jruby/RubyModule;");
 
         // invoke constructor
         a.invokespecial(p(CompiledIRMethod.class), "<init>""(Ljava/lang/invoke/MethodHandle;Ljava/lang/String;Ljava/lang/String;ILorg/jruby/parser/StaticScope;Lorg/jruby/runtime/Visibility;Lorg/jruby/RubyModule;)V");
 
         // add method
         a.invokevirtual(p(RubyModule.class), "addMethod""(Ljava/lang/String;Lorg/jruby/internal/runtime/methods/DynamicMethod;)V");
     }
 
     @Override
     public void DefineMetaClassInstr(DefineMetaClassInstr definemetaclassinstr) {
         IRModuleBody metaClassBody = definemetaclassinstr.getMetaClassBody();
         StaticScope scope = metaClassBody.getStaticScope();
         if (scope.getRequiredArgs() > 3 || scope.getRestArg() >= 0 || scope.getOptionalArgs() != 0) {
             throw new RuntimeException("can't compile variable method: " + this);
         }
 
         String scopeString = Helpers.encodeScope(scope);
 
         IRBytecodeAdapter   m = .method();
         SkinnyMethodAdapter a = m.adapter;
 
         // new CompiledIRMethod
         a.newobj(p(CompiledIRMethod.class));
         a.dup();
 
         // emit method body and get handle
         emit(metaClassBody); // handle
 
         // add'l args for CompiledIRMethod constructor
         a.ldc(metaClassBody.getName());
         a.ldc(metaClassBody.getFileName());
         a.ldc(metaClassBody.getLineNumber());
 
         //// static scope
         a.aload(0);
         a.aload(1);
         a.ldc(scopeString);
         a.invokestatic(p(Helpers.class), "decodeScope""(Lorg/jruby/runtime/ThreadContext;Lorg/jruby/parser/StaticScope;Ljava/lang/String;)Lorg/jruby/parser/StaticScope;");
 
         // get singleton class
         m.loadRuntime();
         visit(definemetaclassinstr.getObject());
         m.invokeHelper("getSingletonClass"RubyClass.classRuby.classIRubyObject.class);
 
         // set into StaticScope
         a.dup2();
         a.invokevirtual(p(StaticScope.class), "setModule"sig(void.classRubyModule.class));
 
         a.getstatic(p(Visibility.class), "PUBLIC"ci(Visibility.class));
         a.swap();
 
         // invoke constructor
         a.invokespecial(p(CompiledIRMethod.class), "<init>""(Ljava/lang/invoke/MethodHandle;Ljava/lang/String;Ljava/lang/String;ILorg/jruby/parser/StaticScope;Lorg/jruby/runtime/Visibility;Lorg/jruby/RubyModule;)V");
 
         // store
         jvmStoreLocal(definemetaclassinstr.getResult());
     }
 
     @Override
     public void DefineModuleInstr(DefineModuleInstr definemoduleinstr) {
         IRModuleBody newIRModuleBody = definemoduleinstr.getNewIRModuleBody();
         StaticScope scope = newIRModuleBody.getStaticScope();
         if (scope.getRequiredArgs() > 3 || scope.getRestArg() >= 0 || scope.getOptionalArgs() != 0) {
             throw new RuntimeException("can't compile variable method: " + this);
         }
 
         String scopeString = Helpers.encodeScope(scope);
 
         IRBytecodeAdapter   m = .method();
         SkinnyMethodAdapter a = m.adapter;
 
         // new CompiledIRMethod
         a.newobj(p(CompiledIRMethod.class));
         a.dup();
 
         // emit method body and get handle
         emit(newIRModuleBody); // handle
 
         // add'l args for CompiledIRMethod constructor
         a.ldc(newIRModuleBody.getName());
         a.ldc(newIRModuleBody.getFileName());
         a.ldc(newIRModuleBody.getLineNumber());
 
         a.aload(0);
         a.aload(1);
         a.ldc(scopeString);
         a.invokestatic(p(Helpers.class), "decodeScope""(Lorg/jruby/runtime/ThreadContext;Lorg/jruby/parser/StaticScope;Ljava/lang/String;)Lorg/jruby/parser/StaticScope;");
 
         // create module
         m.loadLocal(0);
         visit(definemoduleinstr.getContainer());
         m.invokeHelper("checkIsRubyModule"RubyModule.classThreadContext.classObject.class);
         a.ldc(newIRModuleBody.getName());
         a.invokevirtual(p(RubyModule.class), "defineOrGetModuleUnder"sig(RubyModule.classString.class));
 
         // set into StaticScope
         a.dup2();
         a.invokevirtual(p(StaticScope.class), "setModule"sig(void.classRubyModule.class));
 
         a.getstatic(p(Visibility.class), "PUBLIC"ci(Visibility.class));
         a.swap();
 
         // invoke constructor
         a.invokespecial(p(CompiledIRMethod.class), "<init>""(Ljava/lang/invoke/MethodHandle;Ljava/lang/String;Ljava/lang/String;ILorg/jruby/parser/StaticScope;Lorg/jruby/runtime/Visibility;Lorg/jruby/RubyModule;)V");
 
         // store
         jvmStoreLocal(definemoduleinstr.getResult());
     }
 
     @Override
     public void EnsureRubyArrayInstr(EnsureRubyArrayInstr ensurerubyarrayinstr) {
         visit(ensurerubyarrayinstr.getObject());
         .method()..dup();
         org.objectweb.asm.Label after = new org.objectweb.asm.Label();
         .method()..instance_of("org/jruby/RubyArray");
         .method()..iftrue(after);
         .method()..swap();
         .method().loadRuntime();
         .method()..ldc(false);
         .method().invokeStatic(Type.getType(ArgsUtil.class), Method.getMethod("org.jruby.RubyArray convertToRubyArray(org.jruby.Ruby, org.jruby.runtime.builtin.IRubyObject, boolean)"));
         .method()..label(after);
         jvmStoreLocal(ensurerubyarrayinstr.getResult());
     }
 
     @Override
     public void EQQInstr(EQQInstr eqqinstr) {
         super.EQQInstr(eqqinstr);    //To change body of overridden methods use File | Settings | File Templates.
     }
 
     @Override
     public void ExceptionRegionEndMarkerInstr(ExceptionRegionEndMarkerInstr exceptionregionendmarkerinstr) {
         throw new RuntimeException("Marker instructions shouldn't reach compiler: " + exceptionregionendmarkerinstr);
     }
 
     @Override
     public void ExceptionRegionStartMarkerInstr(ExceptionRegionStartMarkerInstr exceptionregionstartmarkerinstr) {
         throw new RuntimeException("Marker instructions shouldn't reach compiler: " + exceptionregionstartmarkerinstr);
     }
 
     @Override
     public void GetClassVarContainerModuleInstr(GetClassVarContainerModuleInstr getclassvarcontainermoduleinstr) {
         super.GetClassVarContainerModuleInstr(getclassvarcontainermoduleinstr);    //To change body of overridden methods use File | Settings | File Templates.
     }
 
     @Override
     public void GetClassVariableInstr(GetClassVariableInstr getclassvariableinstr) {
         super.GetClassVariableInstr(getclassvariableinstr);    //To change body of overridden methods use File | Settings | File Templates.
     }
 
     @Override
     public void GetFieldInstr(GetFieldInstr getfieldinstr) {
         visit(getfieldinstr.getSource());
         .method().getField(getfieldinstr.getRef());
         jvmStoreLocal(getfieldinstr.getResult());
     }
 
     @Override
     public void GetGlobalVariableInstr(GetGlobalVariableInstr getglobalvariableinstr) {
         super.GetGlobalVariableInstr(getglobalvariableinstr);    //To change body of overridden methods use File | Settings | File Templates.
     }
 
     @Override
     public void GVarAliasInstr(GVarAliasInstr gvaraliasinstr) {
         super.GVarAliasInstr(gvaraliasinstr);    //To change body of overridden methods use File | Settings | File Templates.
     }
 
     @Override
     public void InheritanceSearchConstInstr(InheritanceSearchConstInstr inheritancesearchconstinstr) {
         .method().loadLocal(0);
         visit(inheritancesearchconstinstr.getCurrentModule());
 
         // TODO: private consts
         .method().inheritanceSearchConst(inheritancesearchconstinstr.getConstName());
         jvmStoreLocal(inheritancesearchconstinstr.getResult());
     }
 
     @Override
     public void InstanceSuperInstr(InstanceSuperInstr instancesuperinstr) {
         super.InstanceSuperInstr(instancesuperinstr);    //To change body of overridden methods use File | Settings | File Templates.
     }
 
     @Override
     public void JumpIndirectInstr(JumpIndirectInstr jumpindirectinstr) {
         super.JumpIndirectInstr(jumpindirectinstr);    //To change body of overridden methods use File | Settings | File Templates.
     }
 
     @Override
     public void JumpInstr(JumpInstr jumpinstr) {
         .method().goTo(getJVMLabel(jumpinstr.getJumpTarget()));
     }
 
     @Override
     public void LabelInstr(LabelInstr labelinstr) {
         .method().mark(getJVMLabel(labelinstr.getLabel()));
     }
 
     @Override
     public void LexicalSearchConstInstr(LexicalSearchConstInstr lexicalsearchconstinstr) {
         super.LexicalSearchConstInstr(lexicalsearchconstinstr);    //To change body of overridden methods use File | Settings | File Templates.
     }
 
     @Override
     public void LineNumberInstr(LineNumberInstr linenumberinstr) {
         .method()..line(linenumberinstr.getLineNumber());
     }
 
     @Override
     public void LoadLocalVarInstr(LoadLocalVarInstr loadlocalvarinstr) {
         IRBytecodeAdapter m = .method();
         jvmLoadLocal();
         int depth = loadlocalvarinstr.getLocalVar().getScopeDepth();
         // TODO should not have to subtract 1
         int location = loadlocalvarinstr.getLocalVar().getLocation() - 1;
         // TODO if we can avoid loading nil unnecessarily, it could be a big win
         switch (depth) {
             case 0:
                 switch (location) {
                     case 0:
                         m.pushNil();
                         m.adapter.invokevirtual(p(DynamicScope.class), "getValueZeroDepthZeroOrNil"sig(IRubyObject.classIRubyObject.class));
                         return;
                     case 1:
                         m.pushNil();
                         m.adapter.invokevirtual(p(DynamicScope.class), "getValueOneDepthZeroOrNil"sig(IRubyObject.classIRubyObject.class));
                         return;
                     case 2:
                         m.pushNil();
                         m.adapter.invokevirtual(p(DynamicScope.class), "getValueTwoDepthZeroOrNil"sig(IRubyObject.classIRubyObject.class));
                         return;
                     case 3:
                         m.pushNil();
                         m.adapter.invokevirtual(p(DynamicScope.class), "getValueThreeDepthZeroOrNil"sig(IRubyObject.classIRubyObject.class));
                         return;
                     default:
                         m.adapter.pushInt(location);
                         m.pushNil();
                         m.adapter.invokevirtual(p(DynamicScope.class), "getValueDepthZeroOrNil"sig(IRubyObject.classint.classIRubyObject.class));
                         return;
                 }
             default:
                 m.adapter.pushInt(location);
                 m.adapter.pushInt(depth);
                 m.pushNil();
                 m.adapter.invokevirtual(p(DynamicScope.class), "getValueOrNil"sig(IRubyObject.classint.classint.classIRubyObject.class));
         }
     }
 
     @Override
     public void Match2Instr(Match2Instr match2instr) {
         super.Match2Instr(match2instr);    //To change body of overridden methods use File | Settings | File Templates.
     }
 
     @Override
     public void Match3Instr(Match3Instr match3instr) {
         super.Match3Instr(match3instr);    //To change body of overridden methods use File | Settings | File Templates.
     }
 
     @Override
     public void MatchInstr(MatchInstr matchinstr) {
         super.MatchInstr(matchinstr);    //To change body of overridden methods use File | Settings | File Templates.
     }
 
     @Override
     public void MethodLookupInstr(MethodLookupInstr methodlookupinstr) {
         // SSS FIXME: Unused at this time
         throw new RuntimeException("Unsupported instruction: " + methodlookupinstr);
     }
 
     @Override
     public void ModuleVersionGuardInstr(ModuleVersionGuardInstr moduleversionguardinstr) {
         // SSS FIXME: Unused at this time
         throw new RuntimeException("Unsupported instruction: " + moduleversionguardinstr);
     }
 
     @Override
     public void NopInstr(NopInstr nopinstr) {
         // do nothing
     }
 
     @Override
     public void NoResultCallInstr(NoResultCallInstr noResultCallInstr) {
         IRBytecodeAdapter m = .method();
         m.loadLocal(0);
         visit(noResultCallInstr.getReceiver());
         for (Operand operand : noResultCallInstr.getCallArgs()) {
             visit(operand);
         }
 
         switch (noResultCallInstr.getCallType()) {
             case :
             case :
                 m.invokeSelf(noResultCallInstr.getMethodAddr().getName(), noResultCallInstr.getCallArgs().length);
                 break;
             case :
                 m.invokeOther(noResultCallInstr.getMethodAddr().getName(), noResultCallInstr.getCallArgs().length);
                 break;
             case :
                 m.invokeSuper(noResultCallInstr.getMethodAddr().getName(), noResultCallInstr.getCallArgs().length);
                 break;
         }
 
         m.adapter.pop();
     }
 
     @Override
     public void NotInstr(NotInstr instr) {
         visit(instr.getOperands()[0]);
         // SSS FIXME: Does this really require a helper rather than being inlined?
         .method().invokeHelper("irNot"IRubyObject.classThreadContext.classIRubyObject.class);
     }
 
     @Override
     public void OptArgMultipleAsgnInstr(OptArgMultipleAsgnInstr optargmultipleasgninstr) {
         super.OptArgMultipleAsgnInstr(optargmultipleasgninstr);    //To change body of overridden methods use File | Settings | File Templates.
     }
 
     @Override
     public void PopBindingInstr(PopBindingInstr popbindinginstr) {
         // TODO pop
     }
 
     @Override
     public void ProcessModuleBodyInstr(ProcessModuleBodyInstr processmodulebodyinstr) {
         .method().loadLocal(0);
         visit(processmodulebodyinstr.getModuleBody());
         .method().invokeHelper("invokeModuleBody"IRubyObject.classThreadContext.classCompiledIRMethod.class);
         jvmStoreLocal(processmodulebodyinstr.getResult());
     }
 
     @Override
     public void PushBindingInstr(PushBindingInstr pushbindinginstr) {
         .method().loadStaticScope();
         .method()..invokestatic(p(DynamicScope.class), "newDynamicScope"sig(DynamicScope.classStaticScope.class));
         jvmStoreLocal();
 
         // TODO push
     }
 
     @Override
     public void PutClassVariableInstr(PutClassVariableInstr putclassvariableinstr) {
         super.PutClassVariableInstr(putclassvariableinstr);    //To change body of overridden methods use File | Settings | File Templates.
     }
 
     @Override
     public void PutConstInstr(PutConstInstr putconstinstr) {
         IRBytecodeAdapter m = .method();
         visit(putconstinstr.getTarget());
         m.adapter.checkcast(p(RubyModule.class));
         m.adapter.ldc(putconstinstr.getRef());
         visit(putconstinstr.getValue());
         m.adapter.invokevirtual(p(RubyModule.class), "setConstant"sig(IRubyObject.classString.classIRubyObject.class));
         m.adapter.pop();
     }
 
     @Override
     public void PutFieldInstr(PutFieldInstr putfieldinstr) {
         visit(putfieldinstr.getTarget());
         visit(putfieldinstr.getValue());
         .method().putField(putfieldinstr.getRef());
     }
 
     @Override
     public void PutGlobalVarInstr(PutGlobalVarInstr putglobalvarinstr) {
         super.PutGlobalVarInstr(putglobalvarinstr);    //To change body of overridden methods use File | Settings | File Templates.
     }
 
     @Override
     public void RaiseArgumentErrorInstr(RaiseArgumentErrorInstr raiseargumenterrorinstr) {
         super.RaiseArgumentErrorInstr(raiseargumenterrorinstr);    //To change body of overridden methods use File | Settings | File Templates.
     }
 
     @Override
     public void ReceiveClosureInstr(ReceiveClosureInstr receiveclosureinstr) {
         // -- NOP --
         // The JVM always sets up $block to be at the same lvar index where it comes in.
         // jvmLoadLocal("$block");
         // jvmStoreLocal(receiveclosureinstr.getResult());
     }
 
     @Override