All Downloads are FREE. Search and download functionalities are using the official Maven repository.

prompto.verifier.ClassVerifier Maven / Gradle / Ivy

The newest version!
package prompto.verifier;

import java.util.concurrent.atomic.AtomicInteger;

import prompto.compiler.ClassConstant;
import prompto.compiler.ClassFile;
import prompto.compiler.FieldConstant;
import prompto.compiler.IConstantOperand;
import prompto.compiler.IOperand;
import prompto.compiler.InterfaceConstant;
import prompto.compiler.MethodConstant;
import prompto.compiler.MethodInfo;
import prompto.compiler.Opcode;
import prompto.compiler.Tags;

/* producing valid stack frames is a challenging task */
/* the JVM verifier raises inconsistent stack frame exceptions, but not with enough details */
/* this Verifier class mimics the JVM verifier to help diagnose issues */
/* the corresponding stack frame verifier code is transcribed from the jdk C++ file */
/* http://hg.openjdk.java.net/jdk8/jdk8/hotspot/file/87ee5ee27509/src/share/vm/classfile/verifier.cpp */

public class ClassVerifier {

	static final byte BYTECODE_OFFSET = 1;
	static final byte NEW_OFFSET = 2;

	Klass _klass;
	VerificationType _this_type;

	public ClassVerifier(ClassFile classFile) {
		this._klass = new Klass(classFile);
		this._this_type = VerificationType.reference_type(_klass.name());
	}

	public void verify() {
		_klass.classFile.getMethods().forEach((m) -> verifyMethod(m));
	}

	public VerificationType current_type() {
		return _this_type;
	}

	@SuppressWarnings("unused")
	private void verifyMethod(MethodInfo m) {
		int max_stack = m.getCodeAttribute().getStackMapTable().getMaxStack();
		int max_locals = m.getCodeAttribute().getStackMapTable().getMaxLocals();
		// Initial stack map frame: offset is 0, stack is initially empty.
		StackMapFrame current_frame = new StackMapFrame(max_locals, max_stack, this);
		// Set initial locals
		VerificationType return_type = current_frame.set_locals_from_arg(m, current_type());

		int stackmap_index = 0; // index to the stackmap array

		int code_length = m.getCodeAttribute().getOpcodes().length;

		// Scan the bytecode and map each instruction's start offset to a
		// number.
		byte[] code_data = generate_code_data(m, code_length);

		int ex_min = code_length;
		int ex_max = -1;

		/*
		 * // Look through each item on the exception table. Each of the fields
		 * must refer // to a legal instruction. verify_exception_handler_table(
		 * code_length, code_data, ex_min, ex_max);
		 * 
		 * // Look through each entry on the local variable table and make sure
		 * // its range of code array offsets is valid. (4169817) if
		 * (m->has_localvariable_table()) {
		 * verify_local_variable_table(code_length, code_data); }
		 */

		StackMapReader reader = new StackMapReader(this, m, code_data, code_length);
		StackMapTable stackmap_table = new StackMapTable(reader, current_frame, max_locals, max_stack, code_data, code_length);

		RawBytecodeStream bcs = new RawBytecodeStream(m.getCodeAttribute().getOpcodes());

		// Scan the byte code linearly from the start to the end
		boolean no_control_flow = false; // Set to true when there is no direct
											// control
											// flow from current instruction to
											// the next
											// instruction in sequence

		Opcode opcode;
		while (!bcs.is_last_bytecode()) {
			opcode = bcs.raw_next();
			int bci = bcs.bci();

			// Set current frame's offset to bci
			current_frame.set_offset(bci);
			current_frame.set_mark();

			// Make sure every offset in stackmap table point to the beginning
			// to
			// an instruction. Match current_frame to stackmap_table entry with
			// the same offset if exists.
			stackmap_index = verify_stackmap_table(stackmap_index, bci, current_frame, stackmap_table, no_control_flow);

			AtomicInteger this_uninit = new AtomicInteger(0); // Set to true
																// when
																// invokespecial
																// 
																// initialized
																// 'this'

			// Merge with the next instruction
			{
				short index;
				int target;
				VerificationType type, type2;
				VerificationType atype;

				switch (opcode) {
				case NOP:
					no_control_flow = false;
					break;
				case ACONST_NULL: 
					current_frame.push_stack(VerificationType.null_type); 
					no_control_flow = false; 
					break;
				case ICONST_M1:
				case ICONST_0:
				case ICONST_1:
				case ICONST_2:
				case ICONST_3:
				case ICONST_4:
				case ICONST_5:
					current_frame.push_stack(VerificationType.integer_type);
					no_control_flow = false;
					break; /*
							 * case lconst_0 : case lconst_1 :
							 * current_frame.push_stack_2(
							 * VerificationType.long_type,
							 * VerificationType.long2_type); no_control_flow =
							 * false; break; case fconst_0 : case fconst_1 :
							 * case fconst_2 : current_frame.push_stack(
							 * VerificationType.float_type); no_control_flow =
							 * false; break; case dconst_0 : case dconst_1 :
							 * current_frame.push_stack_2(
							 * VerificationType.double_type,
							 * VerificationType.double2_type); no_control_flow =
							 * false; break; case sipush : case bipush :
							 * current_frame.push_stack(
							 * VerificationType.integer_type); no_control_flow =
							 * false; break; case ldc : verify_ldc( opcode,
							 * bcs.get_index_u1(), ¤t_frame, cp, bci);
							 * no_control_flow = false; break; case ldc_w : case
							 * ldc2_w : verify_ldc( opcode, bcs.get_index_u2(),
							 * ¤t_frame, cp, bci); no_control_flow =
							 * false; break; case iload :
							 * verify_iload(bcs.get_index(), ¤t_frame);
							 * no_control_flow = false; break; case iload_0 :
							 * case iload_1 : case iload_2 : case iload_3 :
							 * index = opcode - Opcode.iload_0;
							 * verify_iload(index, ¤t_frame);
							 * no_control_flow = false; break; case lload :
							 * verify_lload(bcs.get_index(), ¤t_frame);
							 * no_control_flow = false; break; case lload_0 :
							 * case lload_1 : case lload_2 : case lload_3 :
							 * index = opcode - Opcode.lload_0;
							 * verify_lload(index, ¤t_frame);
							 * no_control_flow = false; break; case fload :
							 * verify_fload(bcs.get_index(), ¤t_frame);
							 * no_control_flow = false; break; case fload_0 :
							 * case fload_1 : case fload_2 : case fload_3 :
							 * index = opcode - Opcode.fload_0;
							 * verify_fload(index, ¤t_frame);
							 * no_control_flow = false; break; case dload :
							 * verify_dload(bcs.get_index(), ¤t_frame);
							 * no_control_flow = false; break; case dload_0 :
							 * case dload_1 : case dload_2 : case dload_3 :
							 * index = opcode - Opcode.dload_0;
							 * verify_dload(index, ¤t_frame);
							 * no_control_flow = false; break; case aload :
							 * verify_aload(bcs.get_index(), ¤t_frame);
							 * no_control_flow = false; break;
							 */
				case ALOAD_0:
				case ALOAD_1:
				case ALOAD_2:
				case ALOAD_3:
					index = (short) (opcode.ordinal() - Opcode.ALOAD_0.ordinal());
					verify_aload(index, current_frame);
					no_control_flow = false;
					break; /*
							 * case iaload : type = current_frame.pop_stack(
							 * VerificationType.integer_type); atype =
							 * current_frame.pop_stack(
							 * VerificationType::reference_check()); if
							 * (!atype.is_int_array()) {
							 * verify_error(ErrorContext::bad_type(bci,
							 * current_frame.stack_top_ctx(), ref_ctx("[I",
							 * THREAD)), bad_type_msg, "iaload"); return; }
							 * current_frame.push_stack(
							 * VerificationType.integer_type); no_control_flow =
							 * false; break; case baload : type =
							 * current_frame.pop_stack(
							 * VerificationType.integer_type); atype =
							 * current_frame.pop_stack(
							 * VerificationType::reference_check()); if
							 * (!atype.is_bool_array() &&
							 * !atype.is_byte_array()) { verify_error(
							 * ErrorContext::bad_type(bci,
							 * current_frame.stack_top_ctx()), bad_type_msg,
							 * "baload"); return; } current_frame.push_stack(
							 * VerificationType.integer_type); no_control_flow =
							 * false; break; case caload : type =
							 * current_frame.pop_stack(
							 * VerificationType.integer_type); atype =
							 * current_frame.pop_stack(
							 * VerificationType::reference_check()); if
							 * (!atype.is_char_array()) {
							 * verify_error(ErrorContext::bad_type(bci,
							 * current_frame.stack_top_ctx(), ref_ctx("[C",
							 * THREAD)), bad_type_msg, "caload"); return; }
							 * current_frame.push_stack(
							 * VerificationType.integer_type); no_control_flow =
							 * false; break; case saload : type =
							 * current_frame.pop_stack(
							 * VerificationType.integer_type); atype =
							 * current_frame.pop_stack(
							 * VerificationType::reference_check()); if
							 * (!atype.is_short_array()) {
							 * verify_error(ErrorContext::bad_type(bci,
							 * current_frame.stack_top_ctx(), ref_ctx("[S",
							 * THREAD)), bad_type_msg, "saload"); return; }
							 * current_frame.push_stack(
							 * VerificationType.integer_type); no_control_flow =
							 * false; break; case laload : type =
							 * current_frame.pop_stack(
							 * VerificationType.integer_type); atype =
							 * current_frame.pop_stack(
							 * VerificationType::reference_check()); if
							 * (!atype.is_long_array()) {
							 * verify_error(ErrorContext::bad_type(bci,
							 * current_frame.stack_top_ctx(), ref_ctx("[J",
							 * THREAD)), bad_type_msg, "laload"); return; }
							 * current_frame.push_stack_2(
							 * VerificationType.long_type,
							 * VerificationType.long2_type); no_control_flow =
							 * false; break; case faload : type =
							 * current_frame.pop_stack(
							 * VerificationType.integer_type); atype =
							 * current_frame.pop_stack(
							 * VerificationType::reference_check()); if
							 * (!atype.is_float_array()) {
							 * verify_error(ErrorContext::bad_type(bci,
							 * current_frame.stack_top_ctx(), ref_ctx("[F",
							 * THREAD)), bad_type_msg, "faload"); return; }
							 * current_frame.push_stack(
							 * VerificationType.float_type); no_control_flow =
							 * false; break; case daload : type =
							 * current_frame.pop_stack(
							 * VerificationType.integer_type); atype =
							 * current_frame.pop_stack(
							 * VerificationType::reference_check()); if
							 * (!atype.is_double_array()) {
							 * verify_error(ErrorContext::bad_type(bci,
							 * current_frame.stack_top_ctx(), ref_ctx("[D",
							 * THREAD)), bad_type_msg, "daload"); return; }
							 * current_frame.push_stack_2(
							 * VerificationType.double_type,
							 * VerificationType.double2_type); no_control_flow =
							 * false; break; case aaload : { type =
							 * current_frame.pop_stack(
							 * VerificationType.integer_type); atype =
							 * current_frame.pop_stack(
							 * VerificationType::reference_check()); if
							 * (!atype.is_reference_array()) {
							 * verify_error(ErrorContext::bad_type(bci,
							 * current_frame.stack_top_ctx(),
							 * TypeOrigin::implicit
							 * (VerificationType::reference_check())),
							 * bad_type_msg, "aaload"); return; } if
							 * (atype.is_null()) { current_frame.push_stack(
							 * VerificationType.null_type); } else {
							 * VerificationType component =
							 * atype.get_component(this);
							 * current_frame.push_stack(component); }
							 * no_control_flow = false; break; } case istore :
							 * verify_istore(bcs.get_index(), ¤t_frame);
							 * no_control_flow = false; break; case istore_0 :
							 * case istore_1 : case istore_2 : case istore_3 :
							 * index = opcode - Opcode.istore_0;
							 * verify_istore(index, ¤t_frame);
							 * no_control_flow = false; break; case lstore :
							 * verify_lstore(bcs.get_index(), ¤t_frame);
							 * no_control_flow = false; break; case lstore_0 :
							 * case lstore_1 : case lstore_2 : case lstore_3 :
							 * index = opcode - Opcode.lstore_0;
							 * verify_lstore(index, ¤t_frame);
							 * no_control_flow = false; break; case fstore :
							 * verify_fstore(bcs.get_index(), ¤t_frame);
							 * no_control_flow = false; break; case fstore_0 :
							 * case fstore_1 : case fstore_2 : case fstore_3 :
							 * index = opcode - Opcode.fstore_0;
							 * verify_fstore(index, ¤t_frame);
							 * no_control_flow = false; break; case dstore :
							 * verify_dstore(bcs.get_index(), ¤t_frame);
							 * no_control_flow = false; break; case dstore_0 :
							 * case dstore_1 : case dstore_2 : case dstore_3 :
							 * index = opcode - Opcode.dstore_0;
							 * verify_dstore(index, ¤t_frame);
							 * no_control_flow = false; break; case astore :
							 * verify_astore(bcs.get_index(), ¤t_frame);
							 * no_control_flow = false; break;
							 */
				case ASTORE_0:
				case ASTORE_1:
				case ASTORE_2:
				case ASTORE_3:
					index = (short) (opcode.ordinal() - Opcode.ASTORE_0.ordinal());
					verify_astore(index, current_frame);
					no_control_flow = false;
					break; /*
							 * case iastore : type = current_frame.pop_stack(
							 * VerificationType.integer_type); type2 =
							 * current_frame.pop_stack(
							 * VerificationType.integer_type); atype =
							 * current_frame.pop_stack(
							 * VerificationType::reference_check()); if
							 * (!atype.is_int_array()) {
							 * verify_error(ErrorContext::bad_type(bci,
							 * current_frame.stack_top_ctx(), ref_ctx("[I",
							 * THREAD)), bad_type_msg, "iastore"); return; }
							 * no_control_flow = false; break; case bastore :
							 * type = current_frame.pop_stack(
							 * VerificationType.integer_type); type2 =
							 * current_frame.pop_stack(
							 * VerificationType.integer_type); atype =
							 * current_frame.pop_stack(
							 * VerificationType::reference_check()); if
							 * (!atype.is_bool_array() &&
							 * !atype.is_byte_array()) { verify_error(
							 * ErrorContext::bad_type(bci,
							 * current_frame.stack_top_ctx()), bad_type_msg,
							 * "bastore"); return; } no_control_flow = false;
							 * break; case castore : current_frame.pop_stack(
							 * VerificationType.integer_type);
							 * current_frame.pop_stack(
							 * VerificationType.integer_type); atype =
							 * current_frame.pop_stack(
							 * VerificationType::reference_check()); if
							 * (!atype.is_char_array()) {
							 * verify_error(ErrorContext::bad_type(bci,
							 * current_frame.stack_top_ctx(), ref_ctx("[C",
							 * THREAD)), bad_type_msg, "castore"); return; }
							 * no_control_flow = false; break; case sastore :
							 * current_frame.pop_stack(
							 * VerificationType.integer_type);
							 * current_frame.pop_stack(
							 * VerificationType.integer_type); atype =
							 * current_frame.pop_stack(
							 * VerificationType::reference_check()); if
							 * (!atype.is_short_array()) {
							 * verify_error(ErrorContext::bad_type(bci,
							 * current_frame.stack_top_ctx(), ref_ctx("[S",
							 * THREAD)), bad_type_msg, "sastore"); return; }
							 * no_control_flow = false; break; case lastore :
							 * current_frame.pop_stack_2(
							 * VerificationType.long2_type,
							 * VerificationType.long_type);
							 * current_frame.pop_stack(
							 * VerificationType.integer_type); atype =
							 * current_frame.pop_stack(
							 * VerificationType::reference_check()); if
							 * (!atype.is_long_array()) {
							 * verify_error(ErrorContext::bad_type(bci,
							 * current_frame.stack_top_ctx(), ref_ctx("[J",
							 * THREAD)), bad_type_msg, "lastore"); return; }
							 * no_control_flow = false; break; case fastore :
							 * current_frame.pop_stack(
							 * VerificationType.float_type);
							 * current_frame.pop_stack
							 * (VerificationType.integer_type); atype =
							 * current_frame.pop_stack(
							 * VerificationType::reference_check()); if
							 * (!atype.is_float_array()) {
							 * verify_error(ErrorContext::bad_type(bci,
							 * current_frame.stack_top_ctx(), ref_ctx("[F",
							 * THREAD)), bad_type_msg, "fastore"); return; }
							 * no_control_flow = false; break; case dastore :
							 * current_frame.pop_stack_2(
							 * VerificationType.double2_type,
							 * VerificationType.double_type);
							 * current_frame.pop_stack(
							 * VerificationType.integer_type); atype =
							 * current_frame.pop_stack(
							 * VerificationType::reference_check()); if
							 * (!atype.is_double_array()) {
							 * verify_error(ErrorContext::bad_type(bci,
							 * current_frame.stack_top_ctx(), ref_ctx("[D",
							 * THREAD)), bad_type_msg, "dastore"); return; }
							 * no_control_flow = false; break; case aastore :
							 * type = current_frame.pop_stack(object_type());
							 * type2 = current_frame.pop_stack(
							 * VerificationType.integer_type); atype =
							 * current_frame.pop_stack(
							 * VerificationType::reference_check()); // more
							 * type-checking is done at runtime if
							 * (!atype.is_reference_array()) {
							 * verify_error(ErrorContext::bad_type(bci,
							 * current_frame.stack_top_ctx(),
							 * TypeOrigin::implicit
							 * (VerificationType::reference_check())),
							 * bad_type_msg, "aastore"); return; } // 4938384:
							 * relaxed constraint in JVMS 3nd edition.
							 * no_control_flow = false; break; case pop :
							 * current_frame.pop_stack(
							 * VerificationType::category1_check());
							 * no_control_flow = false; break; case pop2 : type
							 * = current_frame.pop_stack(CHECK_VERIFY(this)); if
							 * (type.is_category1()) { current_frame.pop_stack(
							 * VerificationType::category1_check()); } else if
							 * (type.is_category2_2nd()) {
							 * current_frame.pop_stack(
							 * VerificationType::category2_check()); } else { /*
							 * Unreachable? Would need a category2_1st on TOS
							 * which does not appear possible.
							 *//*
								 * verify_error( ErrorContext::bad_type(bci,
								 * current_frame.stack_top_ctx()), bad_type_msg,
								 * "pop2"); return; } no_control_flow = false;
								 * break;
								 */
				case DUP:
					type = current_frame.pop_stack(VerificationType.category1_check());
					current_frame.push_stack(type);
					current_frame.push_stack(type);
					no_control_flow = false;
					break;
				/*
				 * case dup_x1 : type = current_frame.pop_stack(
				 * VerificationType::category1_check()); type2 =
				 * current_frame.pop_stack(
				 * VerificationType::category1_check());
				 * current_frame.push_stack(type);
				 * current_frame.push_stack(type2);
				 * current_frame.push_stack(type); no_control_flow = false;
				 * break; case dup_x2 : { VerificationType type3; type =
				 * current_frame.pop_stack(
				 * VerificationType::category1_check()); type2 =
				 * current_frame.pop_stack(CHECK_VERIFY(this)); if
				 * (type2.is_category1()) { type3 = current_frame.pop_stack(
				 * VerificationType::category1_check()); } else if
				 * (type2.is_category2_2nd()) { type3 = current_frame.pop_stack(
				 * VerificationType::category2_check()); } else { /*
				 * Unreachable? Would need a category2_1st at stack depth 2 with
				 * a category1 on TOS which does not appear possible.
				 *//*
					 * verify_error(ErrorContext::bad_type( bci,
					 * current_frame.stack_top_ctx()), bad_type_msg, "dup_x2");
					 * return; } current_frame.push_stack(type);
					 * current_frame.push_stack(type3);
					 * current_frame.push_stack(type2);
					 * current_frame.push_stack(type); no_control_flow = false;
					 * break; } case dup2 : type =
					 * current_frame.pop_stack(CHECK_VERIFY(this)); if
					 * (type.is_category1()) { type2 = current_frame.pop_stack(
					 * VerificationType::category1_check()); } else if
					 * (type.is_category2_2nd()) { type2 =
					 * current_frame.pop_stack(
					 * VerificationType::category2_check()); } else { /*
					 * Unreachable? Would need a category2_1st on TOS which does
					 * not appear possible.
					 *//*
						 * verify_error( ErrorContext::bad_type(bci,
						 * current_frame.stack_top_ctx()), bad_type_msg,
						 * "dup2"); return; } current_frame.push_stack(type2);
						 * current_frame.push_stack(type);
						 * current_frame.push_stack(type2);
						 * current_frame.push_stack(type); no_control_flow =
						 * false; break; case dup2_x1 : { VerificationType
						 * type3; type =
						 * current_frame.pop_stack(CHECK_VERIFY(this)); if
						 * (type.is_category1()) { type2 =
						 * current_frame.pop_stack(
						 * VerificationType::category1_check()); } else if
						 * (type.is_category2_2nd()) { type2 =
						 * current_frame.pop_stack(
						 * VerificationType::category2_check()); } else { /*
						 * Unreachable? Would need a category2_1st on TOS which
						 * does not appear possible.
						 *//*
							 * verify_error( ErrorContext::bad_type(bci,
							 * current_frame.stack_top_ctx()), bad_type_msg,
							 * "dup2_x1"); return; } type3 =
							 * current_frame.pop_stack(
							 * VerificationType::category1_check());
							 * current_frame.push_stack(type2);
							 * current_frame.push_stack(type);
							 * current_frame.push_stack(type3);
							 * current_frame.push_stack(type2);
							 * current_frame.push_stack(type); no_control_flow =
							 * false; break; } case dup2_x2 : { VerificationType
							 * type3, type4; type =
							 * current_frame.pop_stack(CHECK_VERIFY(this)); if
							 * (type.is_category1()) { type2 =
							 * current_frame.pop_stack(
							 * VerificationType::category1_check()); } else if
							 * (type.is_category2_2nd()) { type2 =
							 * current_frame.pop_stack(
							 * VerificationType::category2_check()); } else { /*
							 * Unreachable? Would need a category2_1st on TOS
							 * which does not appear possible.
							 *//*
								 * verify_error( ErrorContext::bad_type(bci,
								 * current_frame.stack_top_ctx()), bad_type_msg,
								 * "dup2_x2"); return; } type3 =
								 * current_frame.pop_stack(CHECK_VERIFY(this));
								 * if (type3.is_category1()) { type4 =
								 * current_frame.pop_stack(
								 * VerificationType::category1_check()); } else
								 * if (type3.is_category2_2nd()) { type4 =
								 * current_frame.pop_stack(
								 * VerificationType::category2_check()); } else
								 * { /* Unreachable? Would need a category2_1st
								 * on TOS after popping a long/double or two
								 * category 1's, which does not appear possible.
								 */
				/*
				 * verify_error( ErrorContext::bad_type(bci,
				 * current_frame.stack_top_ctx()), bad_type_msg, "dup2_x2");
				 * return; } current_frame.push_stack(type2);
				 * current_frame.push_stack(type);
				 * current_frame.push_stack(type4);
				 * current_frame.push_stack(type3);
				 * current_frame.push_stack(type2);
				 * current_frame.push_stack(type); no_control_flow = false;
				 * break; } case swap : type = current_frame.pop_stack(
				 * VerificationType::category1_check()); type2 =
				 * current_frame.pop_stack(
				 * VerificationType::category1_check());
				 * current_frame.push_stack(type);
				 * current_frame.push_stack(type2); no_control_flow = false;
				 * break; case iadd : case isub : case imul : case idiv : case
				 * irem : case ishl : case ishr : case iushr : case ior : case
				 * ixor : case iand : current_frame.pop_stack(
				 * VerificationType.integer_type); // fall through case ineg :
				 * current_frame.pop_stack( VerificationType.integer_type);
				 * current_frame.push_stack( VerificationType.integer_type);
				 * no_control_flow = false; break; case ladd : case lsub : case
				 * lmul : case ldiv : case lrem : case land : case lor : case
				 * lxor : current_frame.pop_stack_2(
				 * VerificationType.long2_type, VerificationType.long_type); //
				 * fall through case lneg : current_frame.pop_stack_2(
				 * VerificationType.long2_type, VerificationType.long_type);
				 * current_frame.push_stack_2( VerificationType.long_type,
				 * VerificationType.long2_type); no_control_flow = false; break;
				 * case lshl : case lshr : case lushr : current_frame.pop_stack(
				 * VerificationType.integer_type); current_frame.pop_stack_2(
				 * VerificationType.long2_type, VerificationType.long_type);
				 * current_frame.push_stack_2( VerificationType.long_type,
				 * VerificationType.long2_type); no_control_flow = false; break;
				 * case fadd : case fsub : case fmul : case fdiv : case frem :
				 * current_frame.pop_stack( VerificationType.float_type); //
				 * fall through case fneg : current_frame.pop_stack(
				 * VerificationType.float_type); current_frame.push_stack(
				 * VerificationType.float_type); no_control_flow = false; break;
				 * case dadd : case dsub : case dmul : case ddiv : case drem :
				 * current_frame.pop_stack_2( VerificationType.double2_type,
				 * VerificationType.double_type); // fall through case dneg :
				 * current_frame.pop_stack_2( VerificationType.double2_type,
				 * VerificationType.double_type); current_frame.push_stack_2(
				 * VerificationType.double_type, VerificationType.double2_type);
				 * no_control_flow = false; break; case iinc :
				 * verify_iinc(bcs.get_index(), ¤t_frame); no_control_flow
				 * = false; break; */
				case I2L: 
					type = current_frame.pop_stack(VerificationType.integer_type); 
					current_frame.push_stack_2(VerificationType.long_type, VerificationType.long2_type);
				 	no_control_flow = false; break; 
				 /*case l2i :
				 * current_frame.pop_stack_2( VerificationType.long2_type,
				 * VerificationType.long_type); current_frame.push_stack(
				 * VerificationType.integer_type); no_control_flow = false;
				 * break; case i2f : current_frame.pop_stack(
				 * VerificationType.integer_type); current_frame.push_stack(
				 * VerificationType.float_type); no_control_flow = false; break;
				 * case i2d : current_frame.pop_stack(
				 * VerificationType.integer_type); current_frame.push_stack_2(
				 * VerificationType.double_type, VerificationType.double2_type);
				 * no_control_flow = false; break; case l2f :
				 * current_frame.pop_stack_2( VerificationType.long2_type,
				 * VerificationType.long_type); current_frame.push_stack(
				 * VerificationType.float_type); no_control_flow = false; break;
				 * case l2d : current_frame.pop_stack_2(
				 * VerificationType.long2_type, VerificationType.long_type);
				 * current_frame.push_stack_2( VerificationType.double_type,
				 * VerificationType.double2_type); no_control_flow = false;
				 * break; case f2i : current_frame.pop_stack(
				 * VerificationType.float_type); current_frame.push_stack(
				 * VerificationType.integer_type); no_control_flow = false;
				 * break; case f2l : current_frame.pop_stack(
				 * VerificationType.float_type); current_frame.push_stack_2(
				 * VerificationType.long_type, VerificationType.long2_type);
				 * no_control_flow = false; break; case f2d :
				 * current_frame.pop_stack( VerificationType.float_type);
				 * current_frame.push_stack_2( VerificationType.double_type,
				 * VerificationType.double2_type); no_control_flow = false;
				 * break; case d2i : current_frame.pop_stack_2(
				 * VerificationType.double2_type, VerificationType.double_type);
				 * current_frame.push_stack( VerificationType.integer_type);
				 * no_control_flow = false; break; case d2l :
				 * current_frame.pop_stack_2( VerificationType.double2_type,
				 * VerificationType.double_type); current_frame.push_stack_2(
				 * VerificationType.long_type, VerificationType.long2_type);
				 * no_control_flow = false; break; case d2f :
				 * current_frame.pop_stack_2( VerificationType.double2_type,
				 * VerificationType.double_type); current_frame.push_stack(
				 * VerificationType.float_type); no_control_flow = false; break;
				 * case i2b : case i2c : case i2s : current_frame.pop_stack(
				 * VerificationType.integer_type); current_frame.push_stack(
				 * VerificationType.integer_type); no_control_flow = false;
				 * break; case lcmp : current_frame.pop_stack_2(
				 * VerificationType.long2_type, VerificationType.long_type);
				 * current_frame.pop_stack_2( VerificationType.long2_type,
				 * VerificationType.long_type); current_frame.push_stack(
				 * VerificationType.integer_type); no_control_flow = false;
				 * break; case fcmpl : case fcmpg : current_frame.pop_stack(
				 * VerificationType.float_type); current_frame.pop_stack(
				 * VerificationType.float_type); current_frame.push_stack(
				 * VerificationType.integer_type); no_control_flow = false;
				 * break; case dcmpl : case dcmpg : current_frame.pop_stack_2(
				 * VerificationType.double2_type, VerificationType.double_type);
				 * current_frame.pop_stack_2( VerificationType.double2_type,
				 * VerificationType.double_type); current_frame.push_stack(
				 * VerificationType.integer_type); no_control_flow = false;
				 * break; case if_icmpeq: case if_icmpne: case if_icmplt: case
				 * if_icmpge: case if_icmpgt: case if_icmple:
				 * current_frame.pop_stack( VerificationType.integer_type); //
				 * fall through case ifeq: case ifne: case iflt: case ifge: case
				 * ifgt: case ifle: current_frame.pop_stack(
				 * VerificationType.integer_type); target = bcs.dest();
				 * stackmap_table.check_jump_target( ¤t_frame, target);
				 * no_control_flow = false; break; */
				 case IF_ACMPEQ : 
				 case IF_ACMPNE : 
					 current_frame.pop_stack(VerificationType.reference_check()); 
					 // fall through 
				 case IFNULL: 
				 case IFNONNULL: 
					 current_frame.pop_stack(VerificationType.reference_check()); 
					 target = bcs.dest();
					 stackmap_table.check_jump_target (current_frame, target);
					 no_control_flow = false; 
					 break; 
				/* case goto : target =
				 * bcs.dest(); stackmap_table.check_jump_target( ¤t_frame,
				 * target); no_control_flow = true; break; case goto_w : target
				 * = bcs.dest_w(); stackmap_table.check_jump_target(
				 * ¤t_frame, target); no_control_flow = true; break; case
				 * tableswitch : case lookupswitch : verify_switch( &bcs,
				 * code_length, code_data, ¤t_frame, &stackmap_table);
				 * no_control_flow = true; break; case ireturn : type =
				 * current_frame.pop_stack( VerificationType.integer_type);
				 * verify_return_value(return_type, type, bci, ¤t_frame);
				 * no_control_flow = true; break; case lreturn : type2 =
				 * current_frame.pop_stack( VerificationType.long2_type); type =
				 * current_frame.pop_stack( VerificationType.long_type);
				 * verify_return_value(return_type, type, bci, ¤t_frame);
				 * no_control_flow = true; break; case freturn : type =
				 * current_frame.pop_stack( ); verify_return_value(return_type,
				 * type, bci, ¤t_frame); no_control_flow = true; break;
				 * case dreturn : type2 = current_frame.pop_stack(
				 * VerificationType.double2_type, CHECK_VERIFY(this)); type =
				 * current_frame.pop_stack( VerificationType.double_type);
				 * verify_return_value(return_type, type, bci, ¤t_frame);
				 * no_control_flow = true; break; case areturn : type =
				 * current_frame.pop_stack(
				 * VerificationType::reference_check());
				 * verify_return_value(return_type, type, bci, ¤t_frame);
				 * no_control_flow = true; break; case return : if (return_type
				 * != VerificationType::bogus_type()) {
				 * verify_error(ErrorContext::bad_code(bci),
				 * "Method expects a return value"); return; } // Make sure
				 * "this" has been initialized if current method is an // 
				 * if (_method->name() == vmSymbols::object_initializer_name()
				 * && current_frame.flag_this_uninit()) {
				 * verify_error(ErrorContext::bad_code(bci),
				 * "Constructor must call super() or this() " "before return");
				 * return; } no_control_flow = true; break; case getstatic :
				 * case putstatic : case getfield : case putfield :
				 * verify_field_instructions( &bcs, ¤t_frame, cp);
				 * no_control_flow = false; break;
				 */
				case INVOKEVIRTUAL:
				case INVOKESPECIAL:
				case INVOKESTATIC:
					verify_invoke_instructions(opcode, bcs, code_length, current_frame, (bci >= ex_min && bci < ex_max), this_uninit, return_type, stackmap_table);
					no_control_flow = false;
					break;
				/*
				 * case invokeinterface : case invokedynamic :
				 * verify_invoke_instructions( &bcs, code_length,
				 * ¤t_frame, (bci >= ex_min && bci < ex_max),
				 * &this_uninit, return_type, cp, &stackmap_table);
				 * no_control_flow = false; break;
				 */
				case NEW: {
					index = bcs.get_index_u2();
					verify_cp_class_type(bci, index);
					VerificationType new_class_type = cp_index_to_type(index);
					if (!new_class_type.is_object()) {
						throw new VerifierException("Illegal new instruction");
					}
					type = VerificationType.uninitialized_type((short) bci);
					current_frame.push_stack(type);
					no_control_flow = false;
					break;
				}
				/*
				 * case newarray : type = get_newarray_type(bcs.get_index(),
				 * bci); current_frame.pop_stack( VerificationType.integer_type,
				 * CHECK_VERIFY(this)); current_frame.push_stack(type);
				 * no_control_flow = false; break; case anewarray :
				 * verify_anewarray( bci, bcs.get_index_u2(), cp,
				 * ¤t_frame); no_control_flow = false; break; case
				 * arraylength : type = current_frame.pop_stack(
				 * VerificationType::reference_check()); if (!(type.is_null() ||
				 * type.is_array())) { verify_error(ErrorContext::bad_type( bci,
				 * current_frame.stack_top_ctx()), bad_type_msg, "arraylength");
				 * } current_frame.push_stack( VerificationType.integer_type);
				 * no_control_flow = false; break; case checkcast : { index =
				 * bcs.get_index_u2(); verify_cp_class_type(bci, index, cp);
				 * current_frame.pop_stack(object_type()); VerificationType
				 * klass_type = cp_index_to_type( index, cp);
				 * current_frame.push_stack(klass_type); no_control_flow =
				 * false; break; } case instanceof : { index =
				 * bcs.get_index_u2(); verify_cp_class_type(bci, index, cp);
				 * current_frame.pop_stack(object_type());
				 * current_frame.push_stack( VerificationType.integer_type);
				 * no_control_flow = false; break; } case monitorenter : case
				 * monitorexit : current_frame.pop_stack(
				 * VerificationType::reference_check()); no_control_flow =
				 * false; break; case multianewarray : { index =
				 * bcs.get_index_u2(); u2 dim = *(bcs.bcp()+3);
				 * verify_cp_class_type(bci, index, cp); VerificationType
				 * new_array_type = cp_index_to_type(index, cp); if
				 * (!new_array_type.is_array()) {
				 * verify_error(ErrorContext::bad_type(bci,
				 * TypeOrigin::cp(index, new_array_type)),
				 * "Illegal constant pool index in multianewarray instruction");
				 * return; } if (dim < 1 || new_array_type.dimensions() < dim) {
				 * verify_error(ErrorContext::bad_code(bci),
				 * "Illegal dimension in multianewarray instruction: %d", dim);
				 * return; } for (int i = 0; i < dim; i++) {
				 * current_frame.pop_stack( VerificationType.integer_type); }
				 * current_frame.push_stack(new_array_type); no_control_flow =
				 * false; break; } case athrow : type =
				 * VerificationType::reference_type(
				 * vmSymbols::java_lang_Throwable());
				 * current_frame.pop_stack(type); no_control_flow = true; break;
				 * default: // We only need to check the valid bytecodes in
				 * class file. // And jsr and ret are not in the new class file
				 * format in JDK1.5. verify_error(ErrorContext::bad_code(bci),
				 * "Bad instruction: %02x", opcode); no_control_flow = false;
				 * return;
				 */
				default:
					throw new UnsupportedOperationException(opcode.name());
				} // end switch
			} // end Merge with the next instruction

			// Look for possible jump target in exception handlers and see if it
			// matches current_frame
			if (bci >= ex_min && bci < ex_max) {
				verify_exception_handler_targets(bci, this_uninit, current_frame, stackmap_table);
			}
		} // end while

		// Make sure that control flow does not fall through end of the method
		if (!no_control_flow) {
			throw new VerifierException("Control flow falls through code end");
		}
	}

	private void verify_aload(short index, StackMapFrame current_frame) {
		VerificationType type = current_frame.get_local(index, VerificationType.reference_check());
		current_frame.push_stack(type);
	}

	private void verify_astore(short index, StackMapFrame current_frame) {
		VerificationType type = current_frame.pop_stack(VerificationType.reference_check());
		current_frame.set_local(index, type);
	}

	private VerificationType cp_index_to_type(short index) {
		IConstantOperand operand = constantWithIndex(index);
		if (operand instanceof ClassConstant)
			return VerificationType.reference_type(((ClassConstant) operand).getClassName().getValue());
		else
			throw new UnsupportedOperationException(operand.getClass().getName()); // for
																					// now
	}

	private void verify_cp_class_type(int bci, short index) {
		verify_cp_index(bci, index);
		IConstantOperand operand = constantWithIndex(index);
		if (!(operand instanceof ClassConstant))
			throw new VerifierException("Illegal type at constant pool entry " + index);
	}

	private void verify_cp_index(int bci, short index) {
		IConstantOperand operand = constantWithIndex(index);
		if (operand == null)
			throw new VerifierException("Illegal type at constant pool entry " + index);
	}

	private void verify_exception_handler_targets(int bci, AtomicInteger this_uninit, StackMapFrame current_frame, StackMapTable stackmap_table) {
		throw new UnsupportedOperationException();
	}

	private int verify_stackmap_table(int stackmap_index, int bci, StackMapFrame current_frame, StackMapTable stackmap_table, boolean no_control_flow) {

		if (stackmap_index < stackmap_table.get_frame_count()) {
			int this_offset = stackmap_table.get_offset(stackmap_index);
			if (no_control_flow && this_offset > bci) {
				throw new VerifierException("Expecting a stack map frame");
			}
			if (this_offset == bci) {
				// See if current stack map can be assigned to the frame in table.
				// current_frame is the stackmap frame got from the last instruction.
				// If matched, current_frame will be updated by this method.
				stackmap_table.match_stackmap(current_frame, this_offset, stackmap_index, !no_control_flow, true, false);
				stackmap_index++;
			} else if (this_offset < bci) {
				// current_offset should have met this_offset.
				throw new VerifierException("Bad stack map offset " + this_offset);
			}
		} else if (no_control_flow) {
			throw new VerifierException("Expecting a stack map frame");
		}
		return stackmap_index;
	}

	private byte[] generate_code_data(MethodInfo m, int code_length) {
		byte[] code_data = new byte[code_length];
		RawBytecodeStream bcs = new RawBytecodeStream(m.getCodeAttribute().getOpcodes());
		while (!bcs.is_last_bytecode()) {
			Opcode opcode = bcs.raw_next();
			if (opcode == Opcode.ILLEGAL)
				throw new VerifierException("Illegal opcode");
			int bci = bcs.bci();
			if (opcode == Opcode.NEW)
				code_data[bci] = NEW_OFFSET;
			else
				code_data[bci] = BYTECODE_OFFSET;
		}
		return code_data;
	}

	public int change_sig_to_verificationType(SignatureStream sig_type, VerificationType[] inference_types, int index) {
		BasicType bt = sig_type.type();
		switch (bt) {
		case T_OBJECT:
		case T_ARRAY:
			inference_types[index] = VerificationType.reference_type(sig_type.as_symbol());
			return 1;
		case T_LONG:
			inference_types[index] = VerificationType.long_type;
			inference_types[index + 1] = VerificationType.long2_type;
			return 2;
		case T_DOUBLE:
			inference_types[index] = VerificationType.double_type;
			inference_types[index + 1] = VerificationType.double2_type;
			return 2;
		case T_INT:
		case T_BOOLEAN:
		case T_BYTE:
		case T_CHAR:
		case T_SHORT:
			inference_types[index] = VerificationType.integer_type;
			return 1;
		case T_FLOAT:
			inference_types[index] = VerificationType.float_type;
			return 1;
		default:
			throw new UnsupportedOperationException();
		}
	}

	void verify_invoke_instructions(Opcode opcode, RawBytecodeStream bcs, int code_length, StackMapFrame current_frame, boolean in_try_block, AtomicInteger this_uninit, VerificationType return_type,
			StackMapTable stackmap_table) {
		// Make sure the constant pool item is the right type
		short index = bcs.get_index_u2();
		int types;
		switch (opcode) {
		case INVOKEINTERFACE:
			types = 1 << Tags.CONSTANT_InterfaceMethodref;
			break;
		case INVOKEDYNAMIC:
			types = 1 << Tags.CONSTANT_InvokeDynamic;
			break;
		case INVOKESPECIAL:
		case INVOKESTATIC:
			types = (1 << Tags.CONSTANT_InterfaceMethodref) | (1 << Tags.CONSTANT_Methodref);
			break;
		default:
			types = 1 << Tags.CONSTANT_Methodref;
		}
		verify_cp_type(bcs.bci(), index, types);

		// Get method name and signature
		IOperand operand = constantWithIndex(index);
		String method_name = ((MethodConstant) operand).getMethodNameAndType().getName().getValue();
		String method_sig = ((MethodConstant) operand).getMethodNameAndType().getDescriptor().toString();

		if (!SignatureVerifier.is_valid_method_signature(method_sig)) {
			throw new VerifierException("Invalid method signature: " + method_sig);
		}

		// Get referenced class type
		VerificationType ref_class_type = cp_ref_index_to_type(index);

		int size = ArgumentSizeComputer.size(method_sig);
		VerificationType[] sig_types = new VerificationType[size];
		SignatureStream sig_stream = new SignatureStream(method_sig);
		int sig_i = 0;
		while (!sig_stream.at_return_type()) {
			sig_i += change_sig_to_verificationType(sig_stream, sig_types, sig_i);
			sig_stream.next();
		}
		int nargs = sig_i;

		// Check instruction operands
		int bci = bcs.bci();
		if (opcode == Opcode.INVOKEINTERFACE) {

			// 4905268: count operand in invokeinterface should be nargs+1, not nargs.
			// JSR202 spec: The count operand of an invokeinterface instruction is valid if it is
			// the difference between the size of the operand stack before and after the instruction
			// executes.
			if (bcs.get_index_u1_at(bci + 3) != (nargs + 1)) {
				throw new VerifierException("Inconsistent args count operand in invokeinterface");
			}
			if (bcs.get_index_u1_at(bci + 4) != 0) {
				throw new VerifierException("Fourth operand byte of invokeinterface must be zero");
			}
		}

		if (opcode == Opcode.INVOKEDYNAMIC) {
			if (bcs.get_index_u1_at(bci + 3) != 0 || bcs.get_index_u1_at(bci + 4) != 0) {
				throw new VerifierException("Third and fourth operand bytes of invokedynamic must be zero");
			}
		}

		if (method_name.charAt(0) == '<') {
			// Make sure  can only be invoked by invokespecial
			if (opcode != Opcode.INVOKESPECIAL || !"".equals(method_name)) {
				throw new VerifierException("Illegal call to internal method");
			}
		} else if (opcode == Opcode.INVOKESPECIAL && !is_same_or_direct_interface(current_class(), current_type(), ref_class_type)
				&& !ref_class_type.equals(VerificationType.reference_type(_klass.superclass_name()))) {
			boolean subtype = false;
			operand = constantWithIndex(index);
			boolean have_imr_indirect = operand instanceof InterfaceConstant;
			if (!current_class().is_anonymous()) {
				subtype = ref_class_type.is_assignable_from(current_type(), false, this);
			} else {
				VerificationType host_klass_type = VerificationType.reference_type(current_class().host_klass().name());
				subtype = ref_class_type.is_assignable_from(host_klass_type, false, this);

				// If invokespecial of IMR, need to recheck for same or
				// direct interface relative to the host class
				have_imr_indirect = false; 
				/*
				 * (have_imr_indirect &&
				 * !is_same_or_direct_interface(
				 * InstanceKlass
				 * ::cast(current_class(
				 * )->host_klass()),
				 * host_klass_type,
				 * ref_class_type));
				 */
			}
			if (!subtype) {
				throw new VerifierException("Bad invokespecial instruction: current class isn't assignable to reference class.");
			} else if (have_imr_indirect) {
				throw new VerifierException("Bad invokespecial instruction: interface method reference is in an indirect superinterface.");
			}

		}
		// Match method descriptor with operand stack
		for (int i = nargs - 1; i >= 0; i--) { // Run backwards
			current_frame.pop_stack(sig_types[i]);
		}
		// Check objectref on operand stack
		if (opcode != Opcode.INVOKESTATIC && opcode != Opcode.INVOKEDYNAMIC) {
			if ("".equals(method_name)) { //  method
				verify_invoke_init(bcs, index, ref_class_type, current_frame, code_length, in_try_block, this_uninit, stackmap_table);
			} else { // other methods
				// Ensures that target class is assignable to method class.
				if (opcode == Opcode.INVOKESPECIAL) {
					if (!current_class().is_anonymous()) {
						current_frame.pop_stack(current_type());
					} else {
						// anonymous class invokespecial calls: check if the
						// objectref is a subtype of the host_klass of the
						// current class
						// to allow an anonymous class to reference methods in
						// the host_klass
						VerificationType top = current_frame.pop_stack();
						VerificationType hosttype = VerificationType.reference_type(current_class().host_klass().name());
						boolean subtype = hosttype.is_assignable_from(top, false, this);
						if (!subtype) {
							throw new VerifierException("Bad type on operand stack");
						}
					}
				} else if (opcode == Opcode.INVOKEVIRTUAL) { /*
															 * VerificationType
															 * stack_object_type
															 * = current_frame.
															 * pop_stack
															 * (ref_class_type);
															 * if
															 * (current_type()
															 * !=
															 * stack_object_type
															 * ) { operand =
															 * classFile
															 * .getConstantsPool
															 * (
															 * ).constantWithIndex
															 * (index); String
															 * ref_class_name =
															 * ((ClassConstant)
															 * operand
															 * ).getClassName
															 * ().getValue(); //
															 * See the comments
															 * in
															 * verify_field_instructions
															 * () for // the
															 * rationale behind
															 * this. if
															 * (name_in_supers
															 * (ref_class_name,
															 * current_class()))
															 * { Klass*
															 * ref_class =
															 * load_class
															 * (ref_class_name,
															 * CHECK); if
															 * (is_protected_access
															 * ( _klass,
															 * ref_class,
															 * method_name,
															 * method_sig,
															 * true)) { // It's
															 * protected access,
															 * check if stack
															 * object is //
															 * assignable to
															 * current class.
															 * bool
															 * is_assignable =
															 * current_type
															 * ().is_assignable_from
															 * (
															 * stack_object_type
															 * , this, true,
															 * CHECK_VERIFY
															 * (this)); if
															 * (!is_assignable)
															 * { if
															 * (ref_class_type
															 * .name() ==
															 * vmSymbols
															 * ::java_lang_Object
															 * () &&
															 * stack_object_type
															 * .is_array() &&
															 * method_name ==
															 * vmSymbols
															 * ::clone_name()) {
															 * // Special case:
															 * arrays pretend to
															 * implement public
															 * Object //
															 * clone(). } else {
															 * verify_error
															 * (ErrorContext
															 * ::bad_type(bci,
															 * current_frame
															 * ->stack_top_ctx
															 * (),
															 * TypeOrigin::implicit
															 * (
															 * current_type())),
															 * "Bad access to protected data in invokevirtual"
															 * ); return; } } }
															 * } }
															 */
				} else {
					if (opcode != Opcode.INVOKEINTERFACE)
						throw new VerifierException("Unexpected opcode encountered");
					current_frame.pop_stack(ref_class_type);
				}
			}
		}
		// Push the result type.
		if (sig_stream.type() != BasicType.T_VOID) {
			if ("".equals(method_name)) {
				//  method must have a void return type
				/*
				 * Unreachable? Class file parser verifies that methods with '<'
				 * have void return
				 */
				throw new VerifierException("Return type must be void in  method");
			}
			VerificationType[] return_types = new VerificationType[2];
			int n = change_sig_to_verificationType(sig_stream, return_types, 0);
			for (int i = 0; i < n; i++) {
				current_frame.push_stack(return_types[i]); // push types
															// backwards
			}
		}
	}

	private boolean is_same_or_direct_interface(Klass current_class, VerificationType current_type, VerificationType ref_class_type) {
		throw new UnsupportedOperationException();
	}

	public Klass current_class() {
		return _klass;
	}

	private void verify_invoke_init(RawBytecodeStream bcs, int ref_class_index, VerificationType ref_class_type, StackMapFrame current_frame, int code_length, boolean in_try_block,
			AtomicInteger this_uninit, StackMapTable stackmap_table) {
		int bci = bcs.bci();
		VerificationType type = current_frame.pop_stack(VerificationType.reference_check());
		if (type == VerificationType.uninitialized_this_type) {
			/*
			 * // The method must be an  method of this class or its
			 * superclass Klass superk = current_class().superclass(); if
			 * (ref_class_type.name() != current_class().name() &&
			 * ref_class_type.name() != superk->name()) { throw new
			 * VerifierException("Bad  method call"); }
			 * 
			 * // If this invokespecial call is done from inside of a TRY block
			 * then make // sure that all catch clause paths end in a throw.
			 * Otherwise, this can // result in returning an incomplete object.
			 * if (in_try_block) { ExceptionTable exhandlers(_method()); int
			 * exlength = exhandlers.length(); for(int i = 0; i < exlength; i++)
			 * { u2 start_pc = exhandlers.start_pc(i); u2 end_pc =
			 * exhandlers.end_pc(i);
			 * 
			 * if (bci >= start_pc && bci < end_pc) { if
			 * (!ends_in_athrow(exhandlers.handler_pc(i))) {
			 * verify_error(ErrorContext::bad_code(bci),
			 * "Bad  method call from after the start of a try block");
			 * return; } else if (VerboseVerification) { ResourceMark rm;
			 * tty->print_cr( "Survived call to ends_in_athrow(): %s",
			 * current_class()->name()->as_C_string()); } } }
			 * 
			 * // Check the exception handler target stackmaps with the locals
			 * from the // incoming stackmap (before initialize_object() changes
			 * them to outgoing // state). verify_exception_handler_targets(bci,
			 * true, current_frame, stackmap_table, CHECK_VERIFY(this)); } //
			 * in_try_block
			 */
			current_frame.initialize_object(type, current_type());
			this_uninit.set(1);
		} else if (type.is_uninitialized()) {
			byte[] code_data = bcs.opcodes;
			short new_offset = type.bci();
			int new_bci = bcs.bci() - bci + new_offset;
			if (new_offset > (code_length - 3) || ((code_data[new_bci] & 0xFF) != Opcode.NEW.opcode)) {
				// Unreachable? Stack map parsing ensures valid type and new
				// instructions have a valid BCI.
				throw new VerifierException("Expecting new instruction");
			}
			short new_class_index = bcs.get_index_u2_at(new_bci + 1);
			verify_cp_class_type(bci, new_class_index);

			// The method must be an  method of the indicated class
			VerificationType new_class_type = cp_index_to_type(new_class_index);
			if (!new_class_type.equals(ref_class_type)) {
				throw new VerifierException("Call to wrong  method");
			}
			/*
			 * // According to the VM spec, if the referent class is a
			 * superclass of the // current class, and is in a different runtime
			 * package, and the method is // protected, then the objectref must
			 * be the current class or a subclass // of the current class.
			 * VerificationType objectref_type = new_class_type; if
			 * (name_in_supers(ref_class_type.name(), current_class())) { Klass*
			 * ref_klass = load_class( ref_class_type.name(),
			 * CHECK_VERIFY(this)); Method* m =
			 * InstanceKlass::cast(ref_klass)->uncached_lookup_method(
			 * vmSymbols::object_initializer_name(),
			 * cp->signature_ref_at(bcs->get_index_u2()), Klass::normal); // Do
			 * nothing if method is not found. Let resolution detect the error.
			 * if (m != NULL) { instanceKlassHandle mh(THREAD,
			 * m->method_holder()); if (m->is_protected() &&
			 * !mh->is_same_class_package(_klass())) { bool assignable =
			 * current_type().is_assignable_from( objectref_type, this, true,
			 * CHECK_VERIFY(this)); if (!assignable) {
			 * verify_error(ErrorContext::bad_type(bci,
			 * TypeOrigin::cp(new_class_index, objectref_type),
			 * TypeOrigin::implicit(current_type())),
			 * "Bad access to protected  method"); return; } } } }
			 */
			// Check the exception handler target stackmaps with the locals from
			// the
			// incoming stackmap (before initialize_object() changes them to
			// outgoing
			// state).
			if (in_try_block) {
				verify_exception_handler_targets(bci, this_uninit, current_frame, stackmap_table);
			}
			current_frame.initialize_object(type, new_class_type);
		} else {
			throw new VerifierException("Bad operand type when invoking ");
		}
	}

	private VerificationType cp_ref_index_to_type(short index) {
		IConstantOperand operand = constantWithIndex(index);
		if (operand instanceof FieldConstant)
			return cp_index_to_type((short) ((FieldConstant) operand).getClassName().getIndexInConstantPool());
		else if (operand instanceof MethodConstant) // or InterfaceConstant
			return cp_index_to_type((short) ((MethodConstant) operand).getClassName().getIndexInConstantPool());
		else
			throw new VerifierException("Corrupted constant pool");
	}

	private void verify_cp_type(int bci, short index, int types) {
		verify_cp_index(bci, index);
		int tag = _klass.tag_at(index);
		if ((types & (1 << tag)) == 0) {
			throw new VerifierException("Illegal type at constant pool entry " + index);
		}
	}

	public IConstantOperand constantWithIndex(int index) {
		return _klass.constantWithIndex(index);
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy