You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by ml...@apache.org on 2007/07/16 08:44:56 UTC
svn commit: r556523 [1/4] - in /harmony/enhanced/drlvm/trunk:
build/make/components/vm/ vm/vmcore/src/verifier-3363/
Author: mloenko
Date: Sun Jul 15 23:44:55 2007
New Revision: 556523
URL: http://svn.apache.org/viewvc?view=rev&rev=556523
Log:
integration of HARMONY-3363 (contribution of alternative bytecode verifier). Default behavior not switched yet
Added:
harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/
harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/Pass1.cpp (with props)
harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/Pass2.cpp (with props)
harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/Ver.cpp (with props)
harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/context.h (with props)
harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/instr_props.h (with props)
harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/stackmap.h (with props)
harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/tpool.cpp (with props)
harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/tpool.h (with props)
harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/ver_utils.h (with props)
harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/vf_resolve.cpp (with props)
Modified:
harmony/enhanced/drlvm/trunk/build/make/components/vm/vmcore.xml
Modified: harmony/enhanced/drlvm/trunk/build/make/components/vm/vmcore.xml
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/build/make/components/vm/vmcore.xml?view=diff&rev=556523&r1=556522&r2=556523
==============================================================================
--- harmony/enhanced/drlvm/trunk/build/make/components/vm/vmcore.xml (original)
+++ harmony/enhanced/drlvm/trunk/build/make/components/vm/vmcore.xml Sun Jul 15 23:44:55 2007
@@ -83,7 +83,8 @@
<include name="stack/*.cpp" />
<include name="thread/*.cpp" />
<include name="util/*.cpp" />
- <include name="verifier/*.cpp" />
+ <include name="verifier/*.cpp" unless="use_verifier_3363"/>
+ <include name="verifier-3363/*.cpp" if="use_verifier_3363"/>
</fileset>
<fileset dir="${build.vm.home}/vmcore/src/kernel_classes/native">
Added: harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/Pass1.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/Pass1.cpp?view=auto&rev=556523
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/Pass1.cpp (added)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/Pass1.cpp Sun Jul 15 23:44:55 2007
@@ -0,0 +1,484 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/**
+ * @author Mikhail Loenko, Vladimir Molotkov
+ */
+
+#include "stackmap.h"
+#include "context.h"
+
+namespace CPVerifier {
+
+ // data for parsing for each instruction (length and flags)
+ ParseInfo vf_Context_t::parseTable[255] = {
+
+ /* 0x00 OP_NOP */ { 1, 0 },
+
+ /* 0x01 OP_ACONST_NULL */ { 1, 0 },
+ /* 0x02 OP_ICONST_M1 */ { 1, 0 },
+ /* 0x03 OP_ICONST_0 */ { 1, 0 },
+ /* 0x04 OP_ICONST_1 */ { 1, 0 },
+ /* 0x05 OP_ICONST_2 */ { 1, 0 },
+ /* 0x06 OP_ICONST_3 */ { 1, 0 },
+ /* 0x07 OP_ICONST_4 */ { 1, 0 },
+ /* 0x08 OP_ICONST_5 */ { 1, 0 },
+ /* 0x09 OP_LCONST_0 */ { 1, 0 },
+ /* 0x0a OP_LCONST_1 */ { 1, 0 },
+ /* 0x0b OP_FCONST_0 */ { 1, 0 },
+ /* 0x0c OP_FCONST_1 */ { 1, 0 },
+ /* 0x0d OP_FCONST_2 */ { 1, 0 },
+ /* 0x0e OP_DCONST_0 */ { 1, 0 },
+ /* 0x0f OP_DCONST_1 */ { 1, 0 },
+
+ /* 0x10 OP_BIPUSH */ { 2, 0 },
+ /* 0x11 OP_SIPUSH */ { 3, 0 },
+
+ /* 0x12 OP_LDC */ { 2, 0 },
+ /* 0x13 OP_LDC_W */ { 3, 0 },
+ /* 0x14 OP_LDC2_W */ { 3, 0 },
+
+ /* 0x15 OP_ILOAD */ { 2, PI_CANWIDE },
+ /* 0x16 OP_LLOAD */ { 2, PI_CANWIDE },
+ /* 0x17 OP_FLOAD */ { 2, PI_CANWIDE },
+ /* 0x18 OP_DLOAD */ { 2, PI_CANWIDE },
+ /* 0x19 OP_ALOAD */ { 2, PI_CANWIDE },
+
+ /* 0x1a OP_ILOAD_0 */ { 1, 0 },
+ /* 0x1b OP_ILOAD_1 */ { 1, 0 },
+ /* 0x1c OP_ILOAD_2 */ { 1, 0 },
+ /* 0x1d OP_ILOAD_3 */ { 1, 0 },
+ /* 0x1e OP_LLOAD_0 */ { 1, 0 },
+ /* 0x1f OP_LLOAD_1 */ { 1, 0 },
+ /* 0x20 OP_LLOAD_2 */ { 1, 0 },
+ /* 0x21 OP_LLOAD_3 */ { 1, 0 },
+ /* 0x22 OP_FLOAD_0 */ { 1, 0 },
+ /* 0x23 OP_FLOAD_1 */ { 1, 0 },
+ /* 0x24 OP_FLOAD_2 */ { 1, 0 },
+ /* 0x25 OP_FLOAD_3 */ { 1, 0 },
+ /* 0x26 OP_DLOAD_0 */ { 1, 0 },
+ /* 0x27 OP_DLOAD_1 */ { 1, 0 },
+ /* 0x28 OP_DLOAD_2 */ { 1, 0 },
+ /* 0x29 OP_DLOAD_3 */ { 1, 0 },
+ /* 0x2a OP_ALOAD_0 */ { 1, 0 },
+ /* 0x2b OP_ALOAD_1 */ { 1, 0 },
+ /* 0x2c OP_ALOAD_2 */ { 1, 0 },
+ /* 0x2d OP_ALOAD_3 */ { 1, 0 },
+
+ /* 0x2e OP_IALOAD */ { 1, 0 },
+ /* 0x2f OP_LALOAD */ { 1, 0 },
+ /* 0x30 OP_FALOAD */ { 1, 0 },
+ /* 0x31 OP_DALOAD */ { 1, 0 },
+ /* 0x32 OP_AALOAD */ { 1, 0 },
+ /* 0x33 OP_BALOAD */ { 1, 0 },
+ /* 0x34 OP_CALOAD */ { 1, 0 },
+ /* 0x35 OP_SALOAD */ { 1, 0 },
+
+ /* 0x36 OP_ISTORE */ { 2, PI_CANWIDE },
+ /* 0x37 OP_LSTORE */ { 2, PI_CANWIDE },
+ /* 0x38 OP_FSTORE */ { 2, PI_CANWIDE },
+ /* 0x39 OP_DSTORE */ { 2, PI_CANWIDE },
+ /* 0x3a OP_ASTORE */ { 2, PI_CANWIDE },
+
+ /* 0x3b OP_ISTORE_0 */ { 1, 0 },
+ /* 0x3c OP_ISTORE_1 */ { 1, 0 },
+ /* 0x3d OP_ISTORE_2 */ { 1, 0 },
+ /* 0x3e OP_ISTORE_3 */ { 1, 0 },
+ /* 0x3f OP_LSTORE_0 */ { 1, 0 },
+ /* 0x40 OP_LSTORE_1 */ { 1, 0 },
+ /* 0x41 OP_LSTORE_2 */ { 1, 0 },
+ /* 0x42 OP_LSTORE_3 */ { 1, 0 },
+ /* 0x43 OP_FSTORE_0 */ { 1, 0 },
+ /* 0x44 OP_FSTORE_1 */ { 1, 0 },
+ /* 0x45 OP_FSTORE_2 */ { 1, 0 },
+ /* 0x46 OP_FSTORE_3 */ { 1, 0 },
+ /* 0x47 OP_DSTORE_0 */ { 1, 0 },
+ /* 0x48 OP_DSTORE_1 */ { 1, 0 },
+ /* 0x49 OP_DSTORE_2 */ { 1, 0 },
+ /* 0x4a OP_DSTORE_3 */ { 1, 0 },
+ /* 0x4b OP_ASTORE_0 */ { 1, 0 },
+ /* 0x4c OP_ASTORE_1 */ { 1, 0 },
+ /* 0x4d OP_ASTORE_2 */ { 1, 0 },
+ /* 0x4e OP_ASTORE_3 */ { 1, 0 },
+
+ /* 0x4f OP_IASTORE */ { 1, 0 },
+ /* 0x50 OP_LASTORE */ { 1, 0 },
+ /* 0x51 OP_FASTORE */ { 1, 0 },
+ /* 0x52 OP_DASTORE */ { 1, 0 },
+ /* 0x53 OP_AASTORE */ { 1, 0 },
+ /* 0x54 OP_BASTORE */ { 1, 0 },
+ /* 0x55 OP_CASTORE */ { 1, 0 },
+ /* 0x56 OP_SASTORE */ { 1, 0 },
+
+ /* 0x57 OP_POP */ { 1, 0 },
+ /* 0x58 OP_POP2 */ { 1, 0 },
+
+ /* 0x59 OP_DUP */ { 1, 0 },
+ /* 0x5a OP_DUP_X1 */ { 1, 0 },
+ /* 0x5b OP_DUP_X2 */ { 1, 0 },
+ /* 0x5c OP_DUP2 */ { 1, 0 },
+ /* 0x5d OP_DUP2_X1 */ { 1, 0 },
+ /* 0x5e OP_DUP2_X2 */ { 1, 0 },
+
+ /* 0x5f OP_SWAP */ { 1, 0 },
+
+ /* 0x60 OP_IADD */ { 1, 0 },
+ /* 0x61 OP_LADD */ { 1, 0 },
+ /* 0x62 OP_FADD */ { 1, 0 },
+ /* 0x63 OP_DADD */ { 1, 0 },
+ /* 0x64 OP_ISUB */ { 1, 0 },
+ /* 0x65 OP_LSUB */ { 1, 0 },
+ /* 0x66 OP_FSUB */ { 1, 0 },
+ /* 0x67 OP_DSUB */ { 1, 0 },
+ /* 0x68 OP_IMUL */ { 1, 0 },
+ /* 0x69 OP_LMUL */ { 1, 0 },
+ /* 0x6a OP_FMUL */ { 1, 0 },
+ /* 0x6b OP_DMUL */ { 1, 0 },
+ /* 0x6c OP_IDIV */ { 1, 0 },
+ /* 0x6d OP_LDIV */ { 1, 0 },
+ /* 0x6e OP_FDIV */ { 1, 0 },
+ /* 0x6f OP_DDIV */ { 1, 0 },
+ /* 0x70 OP_IREM */ { 1, 0 },
+ /* 0x71 OP_LREM */ { 1, 0 },
+ /* 0x72 OP_FREM */ { 1, 0 },
+ /* 0x73 OP_DREM */ { 1, 0 },
+ /* 0x74 OP_INEG */ { 1, 0 },
+ /* 0x75 OP_LNEG */ { 1, 0 },
+ /* 0x76 OP_FNEG */ { 1, 0 },
+ /* 0x77 OP_DNEG */ { 1, 0 },
+ /* 0x78 OP_ISHL */ { 1, 0 },
+ /* 0x79 OP_LSHL */ { 1, 0 },
+ /* 0x7a OP_ISHR */ { 1, 0 },
+ /* 0x7b OP_LSHR */ { 1, 0 },
+ /* 0x7c OP_IUSHR */ { 1, 0 },
+ /* 0x7d OP_LUSHR */ { 1, 0 },
+ /* 0x7e OP_IAND */ { 1, 0 },
+ /* 0x7f OP_LAND */ { 1, 0 },
+ /* 0x80 OP_IOR */ { 1, 0 },
+ /* 0x81 OP_LOR */ { 1, 0 },
+ /* 0x82 OP_IXOR */ { 1, 0 },
+ /* 0x83 OP_LXOR */ { 1, 0 },
+
+ /* 0x84 OP_IINC */ { 3, PI_CANWIDE },
+
+ /* 0x85 OP_I2L */ { 1, 0 },
+ /* 0x86 OP_I2F */ { 1, 0 },
+ /* 0x87 OP_I2D */ { 1, 0 },
+ /* 0x88 OP_L2I */ { 1, 0 },
+ /* 0x89 OP_L2F */ { 1, 0 },
+ /* 0x8a OP_L2D */ { 1, 0 },
+ /* 0x8b OP_F2I */ { 1, 0 },
+ /* 0x8c OP_F2L */ { 1, 0 },
+ /* 0x8d OP_F2D */ { 1, 0 },
+ /* 0x8e OP_D2I */ { 1, 0 },
+ /* 0x8f OP_D2L */ { 1, 0 },
+ /* 0x90 OP_D2F */ { 1, 0 },
+ /* 0x91 OP_I2B */ { 1, 0 },
+ /* 0x92 OP_I2C */ { 1, 0 },
+ /* 0x93 OP_I2S */ { 1, 0 },
+
+ /* 0x94 OP_LCMP */ { 1, 0 },
+ /* 0x95 OP_FCMPL */ { 1, 0 },
+ /* 0x96 OP_FCMPG */ { 1, 0 },
+ /* 0x97 OP_DCMPL */ { 1, 0 },
+ /* 0x98 OP_DCMPG */ { 1, 0 },
+
+ /* 0x99 OP_IFEQ */ { 3, PI_JUMP },
+ /* 0x9a OP_IFNE */ { 3, PI_JUMP },
+ /* 0x9b OP_IFLT */ { 3, PI_JUMP },
+ /* 0x9c OP_IFGE */ { 3, PI_JUMP },
+ /* 0x9d OP_IFGT */ { 3, PI_JUMP },
+ /* 0x9e OP_IFLE */ { 3, PI_JUMP },
+ /* 0x9f OP_IF_ICMPEQ */ { 3, PI_JUMP },
+ /* 0xa0 OP_IF_ICMPNE */ { 3, PI_JUMP },
+ /* 0xa1 OP_IF_ICMPLT */ { 3, PI_JUMP },
+ /* 0xa2 OP_IF_ICMPGE */ { 3, PI_JUMP },
+ /* 0xa3 OP_IF_ICMPGT */ { 3, PI_JUMP },
+ /* 0xa4 OP_IF_ICMPLE */ { 3, PI_JUMP },
+ /* 0xa5 OP_IF_ACMPEQ */ { 3, PI_JUMP },
+ /* 0xa6 OP_IF_ACMPNE */ { 3, PI_JUMP },
+
+ /* 0xa7 OP_GOTO */ { 3, PI_JUMP | PI_DIRECT },
+
+ /* 0xa8 OP_JSR */ { 3, PI_JUMP},
+ /* 0xa9 OP_RET */ { 2, PI_DIRECT | PI_CANWIDE },
+
+ /* 0xaa OP_TABLESWITCH */ { 16, PI_SWITCH },
+ /* 0xab OP_LOOKUPSWITCH */ { 9, PI_SWITCH },
+
+ /* 0xac OP_IRETURN */ { 1, PI_DIRECT },
+ /* 0xad OP_LRETURN */ { 1, PI_DIRECT },
+ /* 0xae OP_FRETURN */ { 1, PI_DIRECT },
+ /* 0xaf OP_DRETURN */ { 1, PI_DIRECT },
+ /* 0xb0 OP_ARETURN */ { 1, PI_DIRECT },
+ /* 0xb1 OP_RETURN */ { 1, PI_DIRECT },
+
+ /* 0xb2 OP_GETSTATIC */ { 3, 0 },
+ /* 0xb3 OP_PUTSTATIC */ { 3, 0 },
+ /* 0xb4 OP_GETFIELD */ { 3, 0 },
+ /* 0xb5 OP_PUTFIELD */ { 3, 0 },
+
+ /* 0xb6 OP_INVOKEVIRTUAL */ { 3, 0 },
+ /* 0xb7 OP_INVOKESPECIAL */ { 3, 0 },
+ /* 0xb8 OP_INVOKESTATIC */ { 3, 0 },
+
+ /* 0xb9 OP_INVOKEINTERFACE */ { 5, 0 },
+
+ /* oxba XXX_UNUSED_XXX */ {0, 0},
+
+ /* 0xbb OP_NEW */ { 3, 0 },
+ /* 0xbc OP_NEWARRAY */ { 2, 0 },
+ /* 0xbd OP_ANEWARRAY */ { 3, 0 },
+
+ /* 0xbe OP_ARRAYLENGTH */ { 1, 0 },
+
+ /* 0xbf OP_ATHROW */ { 1, PI_DIRECT },
+
+ /* 0xc0 OP_CHECKCAST */ { 3, 0 },
+ /* 0xc1 OP_INSTANCEOF */ { 3, 0 },
+
+ /* 0xc2 OP_MONITORENTER */ { 1, 0 },
+ /* 0xc3 OP_MONITOREXIT */ { 1, 0 },
+
+ /* 0xc4 OP_WIDE */ { 2, 0 },
+
+ /* 0xc5 OP_MULTIANEWARRAY */{ 4, 0 },
+
+ /* 0xc6 OP_IFNULL */ { 3, PI_JUMP },
+ /* 0xc7 OP_IFNONNULL */ { 3, PI_JUMP },
+
+ /* 0xc8 OP_GOTO_W */ { 5, PI_JUMP | PI_DIRECT | PI_WIDEJUMP },
+ /* 0xc9 OP_JSR_W */ { 5, PI_JUMP | PI_WIDEJUMP },
+ };
+
+ /////////////////////////////////////////////////////////////////////////////////////
+
+ /*
+ * Obtain the length of a compound instruction
+ */
+ inline int vf_Context_t::instr_get_len_compound(Address instr, OpCode opcode) {
+ if( opcode == OP_WIDE ) {
+ ParseInfo &pi = instr_get_parse_info( (OpCode)m_bytecode[instr+1] );
+
+ if( !(pi.flags & PI_CANWIDE) ) {
+ // return some big value - error will occur later
+ return 0x20000123;
+ }
+
+ return 2*pi.instr_min_len;
+ }
+
+
+ Address def_adr = (instr & (~3) ) + 4;
+ if( opcode == OP_TABLESWITCH) {
+ int lowbyte = read_int32(m_bytecode + def_adr + 4);
+ int hibyte = read_int32(m_bytecode + def_adr + 8);
+
+ // protect from integer overflow
+ if( hibyte < lowbyte || hibyte - lowbyte > 0x20000000) {
+ // return some big value - error will occur later
+ return 0x20000123;
+ }
+
+ return def_adr + 12 + (hibyte - lowbyte + 1) * 4 - instr;
+ } else {
+ assert( opcode == OP_LOOKUPSWITCH );
+
+ //minimal length of OP_LOOKUPSWITCH is 9 bytes, while its required value may exceed 9 bytes, have to check bounds
+ if( (unsigned)def_adr + 8 > m_code_length ) {
+ // return some big value - error will occur later
+ return 0x20000123;
+ }
+
+ unsigned npairs = read_int32(m_bytecode + def_adr + 4);
+
+ // protect from integer overflow
+ if( npairs > 0x20000000) {
+ // return some big value - error will occur later
+ return 0x20000123;
+ }
+
+ int next = def_adr + 8;
+
+ if (npairs) {
+ int old_value = read_int32(m_bytecode + next);
+ next += 8;
+ // integer values must be sorted - verify
+ for( unsigned i = 1; i < npairs; i++) {
+ int new_value = read_int32(m_bytecode + next);
+ next += 8;
+ if( old_value >= new_value ) {
+ // return some big value - error will occur later
+ return 0x20000123;
+ }
+ old_value = new_value;
+ }
+ }
+
+ return next - instr;
+ }
+ }
+
+ /*
+ This method makes the first pass through the instruction set.
+ On that pass we check that all instruction have valid opcode, that no
+ jumps, no exception handlers lead to the middle of instruction nor
+ out of the method. it checks that control does not flow out of the method.
+
+ It also finds all instructions that have multiple predecessors
+ (like goto tagrtes), this information will be used on the second Pass
+
+ Method starts with the instruction <code>instr</code> for each it was invoked and go down
+ filling the mask array with the flags. On this pass it distignushes
+ 4 types of instructions:
+ 0 - non-passed instruction or dead code
+ 1 - passed instruction
+ 2 - middle of passed instruction
+ 3 - passed multiway instruction (having many predecessors)
+
+ If the method comes to a return, ret, athrow, or an already passed instruction, it terminates
+ If it comes to a switch, an if, or a jsr then it push all branches onto the stack
+ If it comes to a goto then it continues from the jump target
+ */
+
+ vf_Result vf_Context_t::parse(Address instr) {
+ // instruction is out of the method or in the middle of another instruction
+ if( instr > m_code_length || props.isOperand(instr) ) {
+ return error(VF_ErrorCodeEnd, "jump to the middle of instruction or out of the method");
+ }
+
+ while( instr < m_code_length ) {
+ if( props.isParsePassed(instr) ) {
+ // more than one branch leads to this instruction
+ if( !dead_code_parsing ) {
+ props.setMultiway(instr);
+ }
+ return VF_OK;
+ }
+
+ OpCode opcode = (OpCode)m_bytecode[instr];
+ processed_instruction = instr;
+
+ // does code correspond to any valid instruction?
+ if( !instr_is_valid_bytecode(opcode) ) {
+ return error(VF_ErrorInstruction, "invalid opcode");
+ }
+
+ // keep all nessesary information about instruction
+ ParseInfo &pi = instr_get_parse_info(opcode);
+
+ // get MINIMAL length of the instruction with operands
+ unsigned instr_len = instr_get_minlen(pi);
+
+ // code does not correspond to any valid instruction or method length is less than required
+ if( instr + instr_len > m_code_length ) {
+ return error(VF_ErrorInstruction, "method length is less than required");
+ }
+
+ if( instr_is_compound(opcode, pi) ) {
+ // get ACTUAL length for variable length insgtructions
+ instr_len = instr_get_len_compound(instr, opcode);
+
+ // method length is less than required
+ if( instr + instr_len > m_code_length ) {
+ return error(VF_ErrorInstruction, "compound instruction: method length is less than required");
+ }
+ }
+
+ // mark this instruction as processed
+ assert( !props.isParsePassed(instr) );
+ props.setParsePassed(instr);
+
+ // check that no other instruction jumps to the middle of the current instruction
+ for( Address i = instr + 1; i < instr + instr_len; i++ ) {
+ if( !props.setOperand(i) ) {
+ return error(VF_ErrorUnknown, "jump to the middle of instruction");
+ }
+ }
+
+
+
+ if( instr_is_regular(pi) ) {
+ //regular instruction - go to the next instruction
+ instr += instr_len;
+ } else if( instr_is_jump(pi) ) {
+ // goto, goto_w, if*
+
+ Address target = instr_get_jump_target(pi, m_bytecode, instr);
+
+ // jump out of method or to the middle of an instruction
+ if( target >= m_code_length || props.isOperand(target) ) {
+ return error(VF_ErrorBranch, "jump out of method or to the middle of an instruction");
+ }
+
+ if( instr_direct(pi) ) {
+ //TODO: though the spec does not require to check the dead code for correctness
+ //RI seems to check it and some Harmony negative tests have broken dead code
+
+ dead_code_stack.push(instr+instr_len);
+
+ instr = target; // it is not an if* - go to jump target
+ } else {
+ // process conditional jump target or jsr
+ stack.push(target);
+
+ // go to the next instruction
+ instr += instr_len;
+ }
+ } else if( instr_direct(pi) ) {
+ dead_code_stack.push(instr+instr_len);
+
+ // it is not a jump ==> it is return or throw or ret
+ return VF_OK;
+ } else {
+ assert( instr_is_switch(pi) );
+
+ Address next_target_adr = (instr & (~3) ) + 4;
+
+ //default target
+ Address target = instr + read_int32(m_bytecode + next_target_adr);
+ stack.push(target);
+
+ // in tableswitch instruction target offsets are stored with shift = 4,
+ // in lookupswitch with shift = 8
+ int shift = (opcode == OP_TABLESWITCH) ? 4 : 8;
+
+ for (next_target_adr += 12;
+ next_target_adr < instr + instr_len;
+ next_target_adr += shift)
+ {
+ target = instr + read_int32(m_bytecode + next_target_adr);
+ // jump out of method or to the middle of an instruction
+ if( target >= m_code_length || props.isOperand(target) ) {
+ return error(VF_ErrorBranch, "jump out of method or to the middle of an instruction");
+ }
+ // process conditional jump target
+ stack.push(target);
+ }
+
+ return VF_OK;
+ }
+ }
+
+ if(dead_code_parsing) {
+ return VF_OK;
+ }
+
+ // control went out of method bounds
+ return error(VF_ErrorCodeEnd, "control went out of method bounds");
+ }
+
+} // namespace CPVerifier
Propchange: harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/Pass1.cpp
------------------------------------------------------------------------------
svn:executable = *