def test_ins_imul(): ins = instructions.keywords['imul'] frm = make_frame() frm.stack.append(value_containers.ValueInt(100)) frm.stack.append(value_containers.ValueInt(101)) VM.exec_frame(frm, ins()) assert frm.stack[0] == value_containers.ValueInt(10100)
def test_ins_if_icmplt(): ins = instructions.keywords['if_icmple'] frm = make_frame() frm.stack.append(value_containers.ValueInt(100)) frm.stack.append(value_containers.ValueInt(101)) VM.exec_frame(frm, ins(value_containers.ValueInt(2))) assert frm.pc == 2
def test_ins_iadd(): ins = instructions.keywords['iadd'] frm = make_frame() frm.stack.append(value_containers.ValueInt(100)) frm.stack.append(value_containers.ValueInt(101)) VM.exec_frame(frm, ins()) assert frm.pc == VM_PC_START + 1 assert frm.stack[0] == value_containers.ValueInt(201)
def test_ins_iload(): frm = make_frame() value = value_containers.ValueInt(99) frm.variables[0] = value assert len(frm.stack) == 0 VM.exec_frame(frm, instructions.keywords['iload'](value_containers.ValueInt(0))) assert frm.pc == VM_PC_START + 1 assert frm.stack[0] == value
def test_ins_istore(): ins = instructions.keywords['istore'] frm = make_frame() value = value_containers.ValueInt(99) frm.stack.append(value) VM.exec_frame(frm, ins(value_containers.ValueInt(0))) assert frm.variables[0] == value assert frm.pc == VM_PC_START + 1 assert len(frm.stack) == 0
def test_ins_fdiv(): ins = instructions.keywords['fdiv'] frm = make_frame() frm.stack.append(value_containers.ValueFloat(55.0)) frm.stack.append(value_containers.ValueFloat(10.0)) VM.exec_frame(frm, ins()) assert frm.stack[0] == value_containers.ValueFloat(5.5) frm.stack.append(value_containers.ValueInt(9)) frm.stack.append(value_containers.ValueInt(9)) pytest.raises(TypeError, VM.exec_frame, frm, ins())
def test_verify_load_store(): cc = copy.deepcopy(clean_code) cc['ins'] = [{'label': 'x'}, {'ipush': 1}, 'ireturn'] method = parser.process_yaml(cc) method.code.insert(1, instructions.InsIStore(value_containers.ValueInt(1))) pytest.raises(VerifyException, Verifier(BasicVerifier()).verify_load_store_vars, method) method.code[1] = instructions.InsAStore(value_containers.ValueInt(1)) pytest.raises(VerifyException, Verifier(BasicVerifier()).verify_load_store_vars, method) method.code[1] = instructions.InsFStore(value_containers.ValueInt(1)) assert Verifier(BasicVerifier()).verify_load_store_vars(method)
def test_verify_jump_points(): cc = copy.deepcopy(clean_code) cc['ins'] = [{'label': 'x'}, {'ipush': 1}, 'ireturn'] method = parser.process_yaml(cc) method.code.append(instructions.InsGoto(value_containers.ValueInt(-1))) pytest.raises(VerifyException, Verifier(BasicVerifier()).verify_jump_points, method) method.code[2] = instructions.InsGoto(value_containers.ValueInt(3)) pytest.raises(VerifyException, Verifier(BasicVerifier()).verify_jump_points, method) method.code[2] = instructions.InsGoto(value_containers.ValueInt(0)) assert Verifier(BasicVerifier()).verify_jump_points(method)
def test_ins_if_fcmpeq(): ins = instructions.keywords['if_fcmpeq'] frm = make_frame() frm.stack.append(value_containers.ValueFloat(9.9)) frm.stack.append(value_containers.ValueFloat(9.9)) assert len(frm.stack) == 2 VM.exec_frame(frm, ins(value_containers.ValueInt(2))) assert frm.pc == 2 assert len(frm.stack) == 0 frm = make_frame() frm.stack.append(value_containers.ValueFloat(9.9)) frm.stack.append(value_containers.ValueFloat(9.91)) VM.exec_frame(frm, ins(value_containers.ValueInt(2))) assert frm.pc == VM_PC_START + 1
def test_iastore(): vt = value_containers.ValueInt ins = instructions.keywords['iastore'] frm = make_frame() arr = value_containers.ValueIntArrayRef() arr.allocate(10) arr[2] = value_containers.ValueInt(4) frm.stack.append(arr) frm.stack.append(value_containers.ValueInt(0)) frm.stack.append(value_containers.ValueInt(5)) VM.exec_frame(frm, ins()) assert arr[0] == vt(5) assert arr[1].is_none assert arr[1].__class__ == vt
def test_astore(): ins = instructions.keywords['astore'] frm = make_frame() arr = value_containers.ValueIntArrayRef() frm.stack.append(arr) VM.exec_frame(frm, ins(value_containers.ValueInt(4))) assert frm.variables[4] == arr
def test_ins_ipush(): frm = make_frame() value = value_containers.ValueInt(99) assert len(frm.stack) == 0 VM.exec_frame(frm, instructions.keywords['ipush'](value)) assert frm.pc == VM_PC_START + 1 assert frm.stack[0] == value
def test_ins_pop(): frm = make_frame() frm.stack.append(value_containers.ValueInt(99)) assert len(frm.stack) == 1 VM.exec_frame(frm, instructions.keywords['pop']()) assert frm.pc == VM_PC_START + 1 assert len(frm.stack) == 0
def test_aload(): ins = instructions.keywords['aload'] frm = make_frame() arr = value_containers.ValueIntArrayRef() frm.variables[4] = arr VM.exec_frame(frm, ins(value_containers.ValueInt(4))) assert frm.stack.pop() == arr
def test_faload(): vt = value_containers.ValueFloat ins = instructions.keywords['faload'] frm = make_frame() arr = value_containers.ValueFloatArrayRef() arr.allocate(10) arr[2] = value_containers.ValueFloat(4.0) frm.stack.append(arr) frm.stack.append(value_containers.ValueInt(2)) VM.exec_frame(frm, ins()) assert frm.stack.pop() == vt(4.0) frm.stack.append(arr) frm.stack.append(value_containers.ValueInt(1)) VM.exec_frame(frm, ins()) sv = frm.stack.pop() assert sv.is_none assert sv.__class__ == vt
def test_ins_dup(): frm = make_frame() frm.stack.append(value_containers.ValueInt(99)) assert len(frm.stack) == 1 VM.exec_frame(frm, instructions.keywords['dup']()) assert frm.pc == VM_PC_START + 1 assert len(frm.stack) == 2 assert frm.stack[0].__class__ == frm.stack[1].__class__ assert frm.stack[0].value == frm.stack[1].value
def test_ins_ireturn(): ins = instructions.keywords['ireturn'] frm = make_frame() value = value_containers.ValueInt(99) frm.stack.append(value) VM.exec_frame(frm, ins()) assert frm.pc == VM_PC_START + 1 assert frm.finished is True assert frm.return_value == value
def test_basic_block_simple(): m = Method() m.code = [ instructions.InsIPush(value_containers.ValueInt(1)), instructions.InsIReturn() ] anz = controlflow.ControlFlowAnalyzer() anz.analyze(m) assert len(anz.basic_blocks) == 1 assert anz.basic_blocks == [BasicBlock(instruction_indexes=[0, 1])]
def test_args(): for name, ins in instructions.keywords.items(): if issubclass(ins, instructions.InsArgument): pytest.raises(InstructionException, ins) if issubclass(ins, instructions.InsArgInteger): assert ins(value_containers.ValueInt(1)) is not None elif issubclass(ins, instructions.InsArgFloat): assert ins(value_containers.ValueFloat(1.0)) is not None else: assert ins() is not None
def test_flow_instructions(): # make sure no instruction fall through for name, i in instructions.keywords.items(): m = Method() anz = controlflow.ControlFlowAnalyzer() if issubclass(i, instructions.InsGoto): m.code.append(i(value_containers.ValueInt(3))) m.code.append(instructions.InsNop()) m.code.append(instructions.InsNop()) m.code.append(instructions.InsNop()) anz.analyze(m) assert anz.basic_blocks == [ BasicBlock(instruction_indexes=[0], sucessors=[None]), BasicBlock(instruction_indexes=[1, 2], sucessors=[None]), BasicBlock(instruction_indexes=[3], predecessors=[None, None]) ] elif issubclass(i, instructions.InsBranch): m.code.append(instructions.InsNop()) m.code.append(i(value_containers.ValueInt(0))) anz.analyze(m) assert anz.basic_blocks == [ BasicBlock(instruction_indexes=[0, 1], sucessors=[None], predecessors=[None]) ] elif not issubclass(i, instructions.InsReturn): if issubclass(i, instructions.InsNoArgument): m.code.append(i()) elif issubclass(i, instructions.InsArgInteger): m.code.append(i(value_containers.ValueInt(1))) elif issubclass(i, instructions.InsArgFloat): m.code.append(i(value_containers.ValueFloat(5.0))) else: assert False anz.analyze(m) assert anz.basic_blocks == [BasicBlock(instruction_indexes=[0])] elif issubclass(i, instructions.InsReturn): m.code.append(i()) anz.analyze(m) assert anz.basic_blocks == [BasicBlock(instruction_indexes=[0])] else: assert False
def test_ins_array_length(): ins = instructions.keywords['arraylength'] frm = make_frame() value = value_containers.ValueFloatArrayRef() value.allocate(10) value[2] = value_containers.ValueFloat(4.0) frm.stack.append(value) VM.exec_frame(frm, ins()) assert frm.pc == VM_PC_START + 1 v = frm.stack.pop() assert v == value_containers.ValueInt(10) pytest.raises(IndexError, ins().execute, frm)
def test_basic_block_onejumpforward(): m = Method() anz = controlflow.ControlFlowAnalyzer() m.code.append(instructions.InsGoto(value_containers.ValueInt(3))) m.code.append(instructions.InsNop()) m.code.append(instructions.InsNop()) m.code.append(instructions.InsNop()) m.code.append(instructions.InsNop()) anz.analyze(m) assert anz.basic_blocks == [ BasicBlock(instruction_indexes=[0], sucessors=[None]), BasicBlock(instruction_indexes=[1, 2], sucessors=[None]), BasicBlock(instruction_indexes=[3, 4], predecessors=[None, None]) ]
def test_ins_swap(): frm = make_frame() frm.stack.append(value_containers.ValueInt(99)) frm.stack.append(value_containers.ValueFloat(5.5)) assert len(frm.stack) == 2 assert isinstance(frm.stack[0], value_containers.ValueInt) assert isinstance(frm.stack[1], value_containers.ValueFloat) assert frm.stack[0].value == 99 assert frm.stack[1].value == 5.5 VM.exec_frame(frm, instructions.keywords['swap']()) assert frm.pc == VM_PC_START + 1 assert len(frm.stack) == 2 assert isinstance(frm.stack[1], value_containers.ValueInt) assert isinstance(frm.stack[0], value_containers.ValueFloat) assert frm.stack[1].value == 99 assert frm.stack[0].value == 5.5
def test_ins_goto(): ins = instructions.keywords['goto'] frm = make_frame() VM.exec_frame(frm, ins(value_containers.ValueInt(8))) assert frm.pc == 8
def test_ins_f2i(): ins = instructions.keywords['f2i'] frm = make_frame() frm.stack.append(value_containers.ValueFloat(9.9)) VM.exec_frame(frm, ins()) assert frm.stack[0] == value_containers.ValueInt(9)
def test_newarray(): ins = instructions.keywords['newarray'] frm = make_frame() frm.stack.append(value_containers.ValueInt(10)) VM.exec_frame(frm, ins(value_containers.ValueInt(1))) assert frm.stack.pop().__class__ == value_containers.ValueFloatArrayRef
def test_ins_ifnull(): frm = make_frame() frm.stack.append(value_containers.ValueInt()) VM.exec_frame( frm, instructions.keywords['ifnull'](value_containers.ValueInt(2))) assert frm.pc == 2
def test_execute(): for _, inst in instructions.keywords.items(): for inter in [BasicInterpreter, BasicVerifier]: frame = Frame() frame.add_local(UNINITIALIZED_VALUE) if issubclass(inst, instructions.InsArgInteger): ins = inst(value_containers.ValueInt(0)) elif issubclass(inst, instructions.InsArgFloat): ins = inst(value_containers.ValueFloat(0.0)) else: ins = inst() # prepare frame state if inst.opcode == opcodes.ILOAD: frame.locals[0] = INT_VALUE elif inst.opcode == opcodes.FLOAD: frame.locals[0] = FLOAT_VALUE elif inst.opcode == opcodes.ISTORE: frame.add_local_type(INT_VALUE) frame.push(INT_VALUE) elif inst.opcode == opcodes.FSTORE: frame.add_local_type(FLOAT_VALUE) frame.push(FLOAT_VALUE) elif inst.opcode == opcodes.IRETURN: frame.push(INT_VALUE) frame.return_value = INT_VALUE elif inst.opcode == opcodes.FRETURN: frame.push(FLOAT_VALUE) frame.return_value = FLOAT_VALUE elif inst.opcode == opcodes.POP: frame.push(UNINITIALIZED_VALUE) elif inst.opcode == opcodes.DUP: frame.push(UNINITIALIZED_VALUE) elif inst.opcode == opcodes.SWAP: frame.push(INT_VALUE) frame.push(FLOAT_VALUE) elif opcodes.IF_ICMPEQ <= inst.opcode <= opcodes.IF_ICMPLT: frame.push(INT_VALUE) frame.push(INT_VALUE) elif opcodes.IF_FCMPEQ <= inst.opcode <= opcodes.IF_FCMPLT: frame.push(FLOAT_VALUE) frame.push(FLOAT_VALUE) elif inst.opcode == opcodes.IFNONNULL or inst.opcode == opcodes.IFNULL: frame.push(ARRAY_REF) elif opcodes.IADD <= inst.opcode <= opcodes.IDIV: frame.push(INT_VALUE) frame.push(INT_VALUE) elif opcodes.FADD <= inst.opcode <= opcodes.FDIV: frame.push(FLOAT_VALUE) frame.push(FLOAT_VALUE) elif inst.opcode == opcodes.F2I: frame.push(FLOAT_VALUE) elif inst.opcode == opcodes.I2F: frame.push(INT_VALUE) elif inst.opcode == opcodes.ALOAD: frame.locals[0] = ARRAY_REF elif inst.opcode == opcodes.ASTORE: frame.add_local_type(ARRAY_REF) frame.push(INT_ARRAY_REF) elif inst.opcode == opcodes.IASTORE: frame.push(INT_ARRAY_REF) frame.push(INT_VALUE) frame.push(INT_VALUE) elif inst.opcode == opcodes.IALOAD: frame.push(INT_ARRAY_REF) frame.push(INT_VALUE) elif inst.opcode == opcodes.FASTORE: frame.push(FLOAT_ARRAY_REF) frame.push(INT_VALUE) frame.push(FLOAT_VALUE) elif inst.opcode == opcodes.FALOAD: frame.push(FLOAT_ARRAY_REF) frame.push(INT_VALUE) elif inst.opcode == opcodes.ARETURN: frame.push(ARRAY_REF) frame.return_value = ARRAY_REF elif inst.opcode == opcodes.NEWARRAY: frame.push(INT_VALUE) elif inst.opcode == opcodes.ARRAYLENGTH: frame.push(ARRAY_REF) elif inst.opcode == opcodes.NOP: pass elif inst.opcode == opcodes.GOTO: pass elif inst.opcode == opcodes.IPUSH: pass elif inst.opcode == opcodes.FPUSH: pass else: assert False # execute instruction in frame using and interpreter frame.execute(ins, inter()) # check frame state after execution if inst.opcode == opcodes.ILOAD: assert frame.pop() == INT_VALUE elif inst.opcode == opcodes.FLOAD: assert frame.pop() == FLOAT_VALUE elif inst.opcode == opcodes.ISTORE: assert frame.stack_size == 0 assert frame.locals[0] == INT_VALUE elif inst.opcode == opcodes.FSTORE: assert frame.stack_size == 0 assert frame.locals[0] == FLOAT_VALUE elif inst.opcode == opcodes.IRETURN: assert frame.stack_size == 0 assert frame.return_value == INT_VALUE elif inst.opcode == opcodes.FRETURN: assert frame.stack_size == 0 assert frame.return_value == FLOAT_VALUE elif inst.opcode == opcodes.POP: assert frame.stack_size == 0 elif inst.opcode == opcodes.DUP: assert frame.pop() == UNINITIALIZED_VALUE assert frame.pop() == UNINITIALIZED_VALUE elif inst.opcode == opcodes.SWAP: assert frame.pop() == INT_VALUE assert frame.pop() == FLOAT_VALUE elif opcodes.IF_ICMPEQ <= inst.opcode <= opcodes.IF_ICMPLT or opcodes.IF_FCMPEQ <= inst.opcode <= opcodes.IF_FCMPLT: assert frame.stack_size == 0 elif inst.opcode == opcodes.IFNONNULL or inst.opcode == opcodes.IFNULL: assert frame.stack_size == 0 elif opcodes.IADD <= inst.opcode <= opcodes.IDIV: assert frame.pop() == INT_VALUE elif opcodes.FADD <= inst.opcode <= opcodes.FDIV: assert frame.pop() == FLOAT_VALUE elif inst.opcode == opcodes.F2I: assert frame.pop() == INT_VALUE elif inst.opcode == opcodes.I2F: assert frame.pop() == FLOAT_VALUE elif inst.opcode == opcodes.ALOAD: assert frame.pop() == ARRAY_REF elif inst.opcode == opcodes.ASTORE: assert frame.locals[0] == INT_ARRAY_REF elif inst.opcode == opcodes.IASTORE: assert frame.stack_size == 0 elif inst.opcode == opcodes.IALOAD: assert frame.pop() == INT_VALUE elif inst.opcode == opcodes.FASTORE: assert frame.stack_size == 0 elif inst.opcode == opcodes.FALOAD: assert frame.pop() == FLOAT_VALUE elif inst.opcode == opcodes.ARETURN: assert frame.stack_size == 0 elif inst.opcode == opcodes.NEWARRAY: assert frame.pop() == INT_ARRAY_REF elif inst.opcode == opcodes.ARRAYLENGTH: assert frame.pop() == INT_VALUE elif inst.opcode == opcodes.NOP: pass elif inst.opcode == opcodes.GOTO: pass elif inst.opcode == opcodes.IPUSH: assert frame.pop() == INT_VALUE elif inst.opcode == opcodes.FPUSH: assert frame.pop() == FLOAT_VALUE else: assert False # stack has to be empty assert frame.stack_size == 0