InstrEncoderMap.java
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.jruby.ir.persistence;
import org.jruby.RubyInstanceConfig;
import org.jruby.ir.instructions.*;
import org.jruby.ir.instructions.defined.RestoreErrorInfoInstr;
import org.jruby.ir.operands.GlobalVariable;
import org.jruby.ir.operands.Operand;
/**
*
* @author enebo
*/
public class InstrEncoderMap {
private final IRWriterEncoder e;
public InstrEncoderMap(IRWriterEncoder encoder) {
this.e = encoder;
}
public void encode(Instr instr) {
if (RubyInstanceConfig.IR_WRITING_DEBUG) System.out.println("Instr(" + instr.getOperation() + "): " + instr);
e.encode(instr.getOperation());
if (instr instanceof ResultInstr) {
e.encode(((ResultInstr) instr).getResult());
}
switch(instr.getOperation()) {
case ALIAS: encodeAliasInstr((AliasInstr) instr); break;
case ATTR_ASSIGN: encodeAttrAssignInstr((AttrAssignInstr) instr); break;
case BEQ: encodeBEQInstr((BEQInstr) instr); break;
case BINDING_LOAD: encodeLoadLocalVarInstr((LoadLocalVarInstr) instr); break;
case BINDING_STORE:encodeStoreLocalVarInstr((StoreLocalVarInstr) instr); break;
case BLOCK_GIVEN: encodeBlockGivenInstr((BlockGivenInstr) instr); break;
case BNE: encodeBNEInstr((BNEInstr) instr); break;
case BREAK: encodeBreakInstr((BreakInstr) instr); break;
case B_FALSE: encodeBFalseInstr((BFalseInstr) instr); break;
case B_NIL: encodeBNilInstr((BNilInstr) instr); break;
case B_TRUE: encodeBTrueInstr((BTrueInstr) instr); break;
case B_UNDEF: encodeBUndefInstr((BUndefInstr) instr); break;
case CALL: encodeCallBaseInstr((CallInstr) instr); break;
case CHECK_ARGS_ARRAY_ARITY: encodeCheckArgsArrayArityInstr((CheckArgsArrayArityInstr) instr); break;
case CHECK_ARITY: encodeCheckArityInstr((CheckArityInstr) instr); break;
case CLASS_VAR_MODULE: encodeGetClassVarContainerModuleInstr((GetClassVarContainerModuleInstr) instr); break;
// case BUILD_COMPOUND_STRING: encodeBuildCompoundStringInstr((BuildCompoundStringInstr) instr); break;
// case BUILD_DREGEXP: return encodeBuildDynRegExpInstr();
// case BUILD_RANGE: return encodeBuildRangeInstr();
case CONST_MISSING: encodeConstMissingInstr((ConstMissingInstr) instr); break;
case COPY: encodeCopyInstr((CopyInstr) instr); break;
case DEF_CLASS: encodeDefineClassInstr((DefineClassInstr) instr); break;
case DEF_CLASS_METH: encodeDefineClassMethodInstr((DefineClassMethodInstr) instr); break;
case DEF_INST_METH: encodeDefineInstanceMethodInstr((DefineInstanceMethodInstr) instr); break;
case DEF_META_CLASS: encodeDefineMetaClassInstr((DefineMetaClassInstr) instr); break;
case DEF_MODULE: encodeDefineModuleInstr((DefineModuleInstr) instr); break;
case EQQ: encodeEQQInstr((EQQInstr) instr); break;
case EXC_REGION_END: /* no state */ break;
case EXC_REGION_START: encodeExceptionRegionStartMarkerInstr((ExceptionRegionStartMarkerInstr) instr); break;
case GET_CVAR: encodeGetClassVariableInstr((GetClassVariableInstr) instr); break;
case GET_ENCODING: encodeGetEncodingInstr((GetEncodingInstr) instr); break;
case GET_ERROR_INFO: /* no state */ break;
case GET_FIELD: encodeGetFieldInstr((GetFieldInstr) instr); break;
case GET_GLOBAL_VAR: encodeGetGlobalVariableInstr((GetGlobalVariableInstr) instr); break;
case GVAR_ALIAS: encodeGVarAliasInstr((GVarAliasInstr) instr); break;
case INHERITANCE_SEARCH_CONST: encodeInheritanceSearchConstInstr((InheritanceSearchConstInstr) instr); break;
case JUMP: encodeJumpInstr((JumpInstr) instr); break;
case LABEL: encodeLabelInstr((LabelInstr) instr); break;
case LAMBDA: encodeBuildLambdaInstr((BuildLambdaInstr) instr); break;
case LEXICAL_SEARCH_CONST: encodeLexicalSearchConstInstr((LexicalSearchConstInstr) instr); break;
case LINE_NUM: encodeLineNumberInstr((LineNumberInstr) instr); break;
case MASGN_OPT: encodeOptArgMultipleAsgnInstr((OptArgMultipleAsgnInstr) instr); break;
case MASGN_REQD: encodeReqdArgMultipleAsgnInstr((ReqdArgMultipleAsgnInstr) instr); break;
case MASGN_REST: encodeRestArgMultipleAsgnInstr((RestArgMultipleAsgnInstr) instr); break;
case MATCH: encodeMatchInstr((MatchInstr) instr); break;
case MATCH2: encodeMatch2Instr((Match2Instr) instr); break;
case MATCH3: encodeMatch3Instr((Match3Instr) instr); break;
case NONLOCAL_RETURN: encodeNonlocalReturnInstr((NonlocalReturnInstr) instr); break;
case NOP: /* no state */ break;
case NORESULT_CALL: encodeCallBaseInstr((NoResultCallInstr) instr); break;
case POP_BINDING: /* no state */ break;
case POP_FRAME: /* no state */ break;
case PROCESS_MODULE_BODY: encodeProcessModuleBodyInstr((ProcessModuleBodyInstr) instr); break;
case PUSH_BINDING: /* no state */ break;
case PUSH_FRAME: /* no state */ break;
case PUT_CONST: encodePutConstInstr((PutConstInstr) instr); break;
case PUT_CVAR: encodePutClassVariableInstr((PutClassVariableInstr) instr); break;
case PUT_FIELD: encodePutFieldInstr((PutFieldInstr) instr); break;
case PUT_GLOBAL_VAR: encodePutGlobalVarInstr((PutGlobalVarInstr) instr); break;
case RAISE_ARGUMENT_ERROR: encodeRaiseArgumentErrorInstr((RaiseArgumentErrorInstr) instr); break;
case RECORD_END_BLOCK: encodeRecordEndBlockInstr((RecordEndBlockInstr) instr); break;
case RECV_CLOSURE: /* no state */ break;
case RECV_RUBY_EXC: encodeReceiveRubyExceptionInstr((ReceiveRubyExceptionInstr) instr); break;
case RECV_JRUBY_EXC: encodeReceiveJRubyExceptionInstr((ReceiveJRubyExceptionInstr) instr); break;
case RECV_KW_ARG: encodeReceiveKeywordArgInstr((ReceiveKeywordArgInstr) instr); break;
case RECV_KW_REST_ARG: encodeReceiveKeywordRestArgInstr((ReceiveKeywordRestArgInstr) instr); break;
case RECV_OPT_ARG: encodeReceiveOptArgInstr((ReceiveOptArgInstr) instr); break;
case RECV_POST_REQD_ARG: encodeReceivePostReqdArgInstr((ReceivePostReqdArgInstr) instr); break;
case RECV_PRE_REQD_ARG: encodeReceivePreReqdArgInstr((ReceivePreReqdArgInstr) instr); break;
case RECV_REST_ARG: encodeReceiveRestArgInstr((ReceiveRestArgInstr) instr); break;
case RECV_SELF: /* no state */ break;
case RESCUE_EQQ: encodeRescueEQQInstr((RescueEQQInstr) instr); break;
case RESTORE_ERROR_INFO: encodeRestoreErrorInfoInstr((RestoreErrorInfoInstr) instr); break;
case RETURN: encodeReturnInstr((ReturnInstr) instr); break;
case RUNTIME_HELPER: encodeRuntimeHelperCall((RuntimeHelperCall) instr); break;
case SEARCH_CONST: encodeSearchConstInstr((SearchConstInstr) instr); break;
case CLASS_SUPER: encodeClassSuperInstr((ClassSuperInstr) instr); break;
case INSTANCE_SUPER: encodeInstanceSuperInstr((InstanceSuperInstr) instr); break;
case UNRESOLVED_SUPER: encodeUnresolvedSuperInstr((UnresolvedSuperInstr) instr); break;
case THREAD_POLL: encodeThreadPollInstr((ThreadPollInstr) instr); break;
case THROW: encodeThrowExceptionInstr((ThrowExceptionInstr) instr); break;
case TO_ARY: encodeToAryInstr((ToAryInstr) instr); break;
case UNDEF_METHOD: encodeUndefMethodInstr((UndefMethodInstr) instr); break;
case YIELD: encodeYieldInstr((YieldInstr) instr); break;
case ZSUPER: encodeZSuperInstr((ZSuperInstr) instr); break;
default: throw new IllegalArgumentException("Whoa what am I encoding: " + instr);
}
}
private void encodeAliasInstr(AliasInstr instr) {
e.encode(instr.getNewName());
e.encode(instr.getOldName());
}
private void encodeAttrAssignInstr(AttrAssignInstr instr) {
e.encode(instr.getReceiver());
e.encode(instr.getName());
Operand[] args = instr.getCallArgs();
e.encode(args.length);
for (int i = 0; i < args.length; i++) {
e.encode(args[i]);
}
}
private void encodeBEQInstr(BEQInstr instr) {
encodeTwoOperandBranchInstr(instr);
}
private void encodeLoadLocalVarInstr(LoadLocalVarInstr instr) {
e.encode(instr.getScope());
e.encode(instr.getLocalVar());
}
private void encodeStoreLocalVarInstr(StoreLocalVarInstr instr) {
e.encode(instr.getScope());
e.encode(instr.getLocalVar());
e.encode(instr.getValue());
}
private void encodeBlockGivenInstr(BlockGivenInstr instr) {
e.encode(instr.getBlockArg());
}
private void encodeBNEInstr(BNEInstr instr) {
encodeTwoOperandBranchInstr(instr);
}
private void encodeBreakInstr(BreakInstr instr) {
e.encode(instr.getReturnValue());
e.encode(instr.getScopeName());
}
private void encodeBFalseInstr(BFalseInstr instr) {
encodeOneOperandBranchInstr(instr);
}
private void encodeBNilInstr(BNilInstr instr) {
encodeOneOperandBranchInstr(instr);
}
private void encodeBTrueInstr(BTrueInstr instr) {
encodeOneOperandBranchInstr(instr);
}
private void encodeBUndefInstr(BUndefInstr instr) {
encodeOneOperandBranchInstr(instr);
}
private void encodeCheckArgsArrayArityInstr(CheckArgsArrayArityInstr instr) {
e.encode(instr.getArgsArray());
e.encode(instr.required);
e.encode(instr.opt);
e.encode(instr.rest);
}
private void encodeCheckArityInstr(CheckArityInstr instr) {
e.encode(instr.required);
e.encode(instr.opt);
e.encode(instr.rest);
e.encode(instr.receivesKeywords);
}
private void encodeGetClassVarContainerModuleInstr(GetClassVarContainerModuleInstr instr) {
e.encode(instr.getStartingScope());
e.encode(instr.getObject());
}
/**
private void encodeBuildCompoundStringInstr(BuildCompoundStringInstr instr) {
Encoding encoding = compoundstring.getEncoding();
if (encoding == null) {
encoder.encode("");
} else {
encoder.encode(encoding.toString());
}
List<Operand> pieces = compoundstring.getPieces();
encoder.encode(pieces.size());
for (Operand piece: pieces) {
encode(piece);
}
}
**/
private void encodeConstMissingInstr(ConstMissingInstr instr) {
e.encode(instr.getReceiver());
e.encode(instr.getMissingConst());
}
private void encodeCopyInstr(CopyInstr instr) {
e.encode(instr.getSource());
}
private void encodeDefineClassInstr(DefineClassInstr instr) {
e.encode(instr.getNewIRClassBody());
e.encode(instr.getContainer());
e.encode(instr.getSuperClass());
}
private void encodeDefineClassMethodInstr(DefineClassMethodInstr instr) {
e.encode(instr.getContainer());
e.encode(instr.getMethod());
}
private void encodeDefineInstanceMethodInstr(DefineInstanceMethodInstr instr) {
e.encode(instr.getMethod());
}
private void encodeDefineMetaClassInstr(DefineMetaClassInstr instr) {
e.encode(instr.getObject());
e.encode(instr.getMetaClassBody());
}
private void encodeDefineModuleInstr(DefineModuleInstr instr) {
e.encode(instr.getNewIRModuleBody());
e.encode(instr.getContainer());
}
private void encodeEQQInstr(EQQInstr instr) {
e.encode(instr.getArg1());
e.encode(instr.getArg2());
}
private void encodeExceptionRegionStartMarkerInstr(ExceptionRegionStartMarkerInstr instr) {
e.encode(instr.firstRescueBlockLabel);
}
private void encodeGetClassVariableInstr(GetClassVariableInstr instr) {
encodeGetInstr(instr);
}
// FIXME: We know this is giving us a difficult to lookup name on decode side.
private void encodeGetEncodingInstr(GetEncodingInstr instr) {
e.encode(instr.getEncoding().toString());
}
private void encodeGetFieldInstr(GetFieldInstr instr) {
encodeGetInstr(instr);
}
private void encodeGetGlobalVariableInstr(GetGlobalVariableInstr instr) {
e.encode(((GlobalVariable) instr.getSource()).getName());
}
private void encodeGVarAliasInstr(GVarAliasInstr instr) {
e.encode(instr.getNewName());
e.encode(instr.getOldName());
}
private void encodeInheritanceSearchConstInstr(InheritanceSearchConstInstr instr) {
e.encode(instr.getCurrentModule());
e.encode(instr.getConstName());
e.encode(instr.isNoPrivateConsts());
}
private void encodeJumpInstr(JumpInstr instr) {
e.encode(instr.getJumpTarget());
}
private void encodeLabelInstr(LabelInstr instr) {
e.encode(instr.getLabel());
}
// FIXME: If these always occur in the same source file thet live in we do not need to encode filename
private void encodeBuildLambdaInstr(BuildLambdaInstr instr) {
e.encode(instr.getLambdaBodyName());
e.encode(instr.getPosition().getFile());
e.encode(instr.getPosition().getLine());
}
private void encodeLexicalSearchConstInstr(LexicalSearchConstInstr instr) {
e.encode(instr.getDefiningScope());
e.encode(instr.getConstName());
}
private void encodeLineNumberInstr(LineNumberInstr instr) {
e.encode(instr.getLineNumber());
}
private void encodeOptArgMultipleAsgnInstr(OptArgMultipleAsgnInstr instr) {
e.encode(instr.getArrayArg());
e.encode(instr.getIndex());
e.encode(instr.getMinArgsLength());
}
private void encodeReqdArgMultipleAsgnInstr(ReqdArgMultipleAsgnInstr instr) {
e.encode(instr.getArrayArg());
e.encode(instr.getPreArgsCount());
e.encode(instr.getPostArgsCount());
e.encode(instr.getIndex());
}
private void encodeRestArgMultipleAsgnInstr(RestArgMultipleAsgnInstr instr) {
e.encode(instr.getArrayArg());
e.encode(instr.getPreArgsCount());
e.encode(instr.getPostArgsCount());
e.encode(instr.getIndex());
}
private void encodeMatchInstr(MatchInstr instr) {
e.encode(instr.getReceiver());
}
private void encodeMatch2Instr(Match2Instr instr) {
e.encode(instr.getReceiver());
e.encode(instr.getArg());
}
private void encodeMatch3Instr(Match3Instr instr) {
e.encode(instr.getReceiver());
e.encode(instr.getArg());
}
private void encodeNonlocalReturnInstr(NonlocalReturnInstr instr) {
e.encode(instr.getReturnValue());
e.encode(instr.methodName);
}
private void encodeCallBaseInstr(CallBase instr) {
boolean hasClosure = instr.getClosureArg(null) != null;
e.encode(instr.getCallType().ordinal());
e.encode(instr.getName());
e.encode(instr.getReceiver());
e.encode(calculateArity(instr.getCallArgs(), hasClosure));
for (Operand arg: instr.getCallArgs()) {
e.encode(arg);
}
if (hasClosure) e.encode(instr.getClosureArg(null));
}
private void encodeProcessModuleBodyInstr(ProcessModuleBodyInstr instr) {
e.encode(instr.getModuleBody());
}
private void encodePutConstInstr(PutConstInstr instr) {
encodePutInstr(instr);
}
private void encodePutClassVariableInstr(PutClassVariableInstr instr) {
encodePutInstr(instr);
}
private void encodePutFieldInstr(PutFieldInstr instr) {
encodePutInstr(instr);
}
private void encodePutGlobalVarInstr(PutGlobalVarInstr instr) {
e.encode(((GlobalVariable) instr.getTarget()).getName());
e.encode(instr.getValue());
}
private void encodeRaiseArgumentErrorInstr(RaiseArgumentErrorInstr instr) {
e.encode(instr.getRequired());
e.encode(instr.getOpt());
e.encode(instr.getRest());
e.encode(instr.getNumArgs());
}
private void encodeRecordEndBlockInstr(RecordEndBlockInstr instr) {
e.encode(instr.getDeclaringScope());
e.encode(instr.getEndBlockClosure());
}
private void encodeReceiveRubyExceptionInstr(ReceiveRubyExceptionInstr instr) { }
private void encodeReceiveJRubyExceptionInstr(ReceiveJRubyExceptionInstr instr) { }
private void encodeReceiveKeywordArgInstr(ReceiveKeywordArgInstr instr) {
e.encode(instr.argName);
e.encode(instr.required);
}
private void encodeReceiveKeywordRestArgInstr(ReceiveKeywordRestArgInstr instr) {
e.encode(instr.required);
}
private void encodeReceiveOptArgInstr(ReceiveOptArgInstr instr) {
e.encode(instr.requiredArgs);
e.encode(instr.getPreArgs());
e.encode(instr.getArgIndex());
}
private void encodeReceivePostReqdArgInstr(ReceivePostReqdArgInstr instr) {
e.encode(instr.getArgIndex());
e.encode(instr.preReqdArgsCount);
e.encode(instr.postReqdArgsCount);
}
private void encodeReceivePreReqdArgInstr(ReceivePreReqdArgInstr instr) {
e.encode(instr.getArgIndex());
}
private void encodeReceiveRestArgInstr(ReceiveRestArgInstr instr) {
e.encode(instr.required);
e.encode(instr.getArgIndex());
}
private void encodeRescueEQQInstr(RescueEQQInstr instr) {
e.encode(instr.getArg1());
e.encode(instr.getArg2());
}
private void encodeRestoreErrorInfoInstr(RestoreErrorInfoInstr instr) {
e.encode(instr.getArg());
}
private void encodeReturnInstr(ReturnInstr instr) {
e.encode(instr.getReturnValue());
}
private void encodeSearchConstInstr(SearchConstInstr instr) {
e.encode(instr.getConstName());
e.encode(instr.getStartingScope());
e.encode(instr.isNoPrivateConsts());
}
private void encodeClassSuperInstr(ClassSuperInstr instr) {
encodeCallBaseInstr(instr);
}
private void encodeInstanceSuperInstr(InstanceSuperInstr instr) {
encodeCallBaseInstr(instr);
}
private void encodeUnresolvedSuperInstr(UnresolvedSuperInstr instr) {
boolean hasClosure = instr.getClosureArg(null) != null;
e.encode(instr.getCallType().ordinal());
e.encode(instr.getReceiver());
e.encode(calculateArity(instr.getCallArgs(), hasClosure));
for (Operand arg: instr.getCallArgs()) {
e.encode(arg);
}
if (hasClosure) e.encode(instr.getClosureArg(null));
}
private void encodeThreadPollInstr(ThreadPollInstr instr) {
e.encode(instr.onBackEdge);
}
private void encodeThrowExceptionInstr(ThrowExceptionInstr instr) {
e.encode(instr.getExceptionArg());
}
private void encodeToAryInstr(ToAryInstr instr) {
e.encode(instr.getArrayArg());
}
private void encodeUndefMethodInstr(UndefMethodInstr instr) {
e.encode(instr.getMethodName());
}
private void encodeYieldInstr(YieldInstr instr) {
e.encode(instr.getBlockArg());
e.encode(instr.getYieldArg());
e.encode(instr.isUnwrapArray());
}
private void encodeZSuperInstr(ZSuperInstr instr) {
e.encode(instr.getReceiver());
Operand closure = instr.getClosureArg(null);
boolean hasClosure = closure != null;
e.encode(hasClosure);
if (hasClosure) {
e.encode(closure);
}
e.encode(instr.getCallArgs().length);
for (Operand arg: instr.getCallArgs()) {
e.encode(arg);
}
}
private void encodeTwoOperandBranchInstr(TwoOperandBranchInstr instr) {
e.encode(instr.getArg1());
e.encode(instr.getArg2());
e.encode(instr.getJumpTarget());
}
private void encodeOneOperandBranchInstr(OneOperandBranchInstr instr) {
e.encode(instr.getArg1());
e.encode(instr.getJumpTarget());
}
private void encodeGetInstr(GetInstr instr) {
e.encode(instr.getSource());
e.encode(instr.getRef());
}
private void encodePutInstr(PutInstr instr) {
e.encode(instr.getTarget());
e.encode(instr.getRef());
e.encode(instr.getValue());
}
// -0 is not possible so we add 1 to arguments with closure so we get a valid negative value.
private int calculateArity(Operand[] arguments, boolean hasClosure) {
return hasClosure ? -1*(arguments.length + 1) : arguments.length;
}
private void encodeRuntimeHelperCall(RuntimeHelperCall instr) {
e.encode(instr.getHelperMethod().ordinal());
//FIXME: Probably make an Operand[] encoder
Operand[] args = instr.getArgs();
e.encode(args.length);
for (int i = 0; i < args.length; i++) {
e.encode(args[i]);
}
}
}