harmony-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From mcfi...@apache.org
Subject svn commit: r649574 [4/6] - in /harmony/enhanced/drlvm/trunk: ./ make/vm/ vm/include/open/ vm/vmcore/include/ vm/vmcore/src/verifier-3363/base/ vm/vmcore/src/verifier-3363/java5/ vm/vmcore/src/verifier-3363/java6/ vm/vmcore/src/verifier-3363/x_verifier/
Date Fri, 18 Apr 2008 15:29:41 GMT
Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/java5/context_5.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/java5/context_5.cpp?rev=649574&r1=649573&r2=649574&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/java5/context_5.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/java5/context_5.cpp Fri Apr 18 08:29:36 2008
@@ -14,697 +14,690 @@
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  */
-/** 
- * @author Mikhail Loenko, Vladimir Molotkov
- */  
-
 #include "open/vm_method_access.h"
 
 #include "verifier.h"
 #include "context_5.h"
-namespace CPVerifier_5 {
 
-    /*
-    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_5::parse(Address instr, int dead_code_parsing, FastStack<Address>* deadstack) {
-        // 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;
+/*
+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_5::parse(Address instr, int dead_code_parsing, FastStack<Address>* deadstack) {
+    // 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;
+        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");
-            }
+        // 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);
+        // 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);
+        // 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
+        // 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, "method length is less than required");
+                return error(VF_ErrorInstruction, "compound instruction: 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);
+        // mark this instruction as processed
+        assert( !props.isParsePassed(instr) );
+        props.setParsePassed(instr);
 
-                // 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");
-                }
+        // 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");
             }
+        }
 
-            // 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");
             }
+            
+            mark_stackmap_point(target);
 
+            if( instr_direct(pi, opcode, m_bytecode, instr) ) {
+                if( instr + instr_len < m_code_length ) deadstack->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);
 
-            if( instr_is_regular(pi) ) {
-                //regular instruction - go to the next instruction
+                // go to the next instruction
                 instr += instr_len;
-            } else if( instr_is_jump(pi) ) {
-                // goto, goto_w, if*
+            }
+        } else if( instr_direct(pi, opcode, m_bytecode, instr) ) {
+            // it is not a jump ==> it is return or throw or ret
+            if( instr + instr_len < m_code_length ) deadstack->push(instr + instr_len);
+            return VF_OK;
+        } else {
+            assert( instr_is_switch(pi) );
+
+            Address next_target_adr = (instr & (~3) ) + 4;
 
-                Address target = instr_get_jump_target(pi, m_bytecode, instr);
+            //default target
+            Address target = instr + read_int32(m_bytecode + next_target_adr);
+            stack.push(target);
 
+            mark_stackmap_point(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);
                 mark_stackmap_point(target);
+            }
 
-                if( instr_direct(pi, opcode, m_bytecode, instr) ) {
-                    if( instr + instr_len < m_code_length ) deadstack->push(instr + instr_len);
+            if( instr + instr_len < m_code_length ) deadstack->push(instr + instr_len);
+            return VF_OK;
+        }
+    }
 
-                    instr = target; // it is not an if* - go to jump target
-                } else {
-                    // process conditional jump target or jsr
-                    stack.push(target);
+    //it might be a dead code -- code followed by JSR which never returns
+    //if it's a dead code - it's OK, if it's not - we will catch it on the second pass
+    return VF_OK;
+}
 
-                    // go to the next instruction
-                    instr += instr_len;
-                }
-            } else if( instr_direct(pi, opcode, m_bytecode, instr) ) {
-                // it is not a jump ==> it is return or throw or ret
-                if( instr + instr_len < m_code_length ) deadstack->push(instr + instr_len);
-                return VF_OK;
-            } else {
-                assert( instr_is_switch(pi) );
 
-                Address next_target_adr = (instr & (~3) ) + 4;
+vf_Result vf_Context_5::StartLinearDataflow(Address instr) {
 
-                //default target
-                Address target = instr + read_int32(m_bytecode + next_target_adr);
-                stack.push(target);
-
-                mark_stackmap_point(target);
+    vf_Result tcr;
+    int workmap_is_a_copy_of_stackmap;
 
-                // 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);
-                    mark_stackmap_point(target);
-                }
+    if( props.isDataflowPassed(instr) ) {
+        //passed since it was added to the stack
+        assert(instr);
+        return VF_OK;
+    }
 
-                if( instr + instr_len < m_code_length ) deadstack->push(instr + instr_len);
-                return VF_OK;
-            }
+    if (instr) {
+        workmap_is_a_copy_of_stackmap = true;
+        fill_workmap(instr);
+    } else {
+        //for the first instruction it does not matter if it is multiway or not
+        workmap_is_a_copy_of_stackmap = false;
+        // may return error in case of method's wrong signature
+        if((tcr = create_method_initial_workmap()) != VF_OK ) {
+            return tcr;
         }
-
-        //it might be a dead code -- code followed by JSR which never returns
-        //if it's a dead code - it's OK, if it's not - we will catch it on the second pass
-        return VF_OK;
     }
 
+    //list of handlers unknown
+    next_start_pc = 0;
 
-    vf_Result vf_Context_5::StartLinearDataflow(Address instr) {
+    return DataflowLoop(instr, workmap_is_a_copy_of_stackmap);
+}
 
-        vf_Result tcr;
-        int workmap_is_a_copy_of_stackmap;
+vf_Result vf_Context_5::SubroutineDone(Address subr) {
+    SubroutineData *subrdata = ((PropsHead_5*)props.getInstrProps(subr)->next)->getSubrData(m_max_stack + m_stack_start);
+    subrdata->subrDataflowed = 1;
 
-        if( props.isDataflowPassed(instr) ) {
-            //passed since it was added to the stack
-            assert(instr);
-            return VF_OK;
-        }
+    if( !subrdata->retCount ) {
+        //no ret from subroutine -- dead code follows
+        return VF_OK;
+    }
 
-        if (instr) {
-            workmap_is_a_copy_of_stackmap = true;
-            fill_workmap(instr);
-        } else {
-            //for the first instruction it does not matter if it is multiway or not
-            workmap_is_a_copy_of_stackmap = false;
-            // may return error in case of method's wrong signature
-            if((tcr = create_method_initial_workmap()) != VF_OK ) {
-                return tcr;
-            }
-        }
+    Address jsr = subrdata->caller;
 
-        //list of handlers unknown
-        next_start_pc = 0;
+    OpCode opcode = (OpCode)m_bytecode[jsr];
+    ParseInfo &pi = instr_get_parse_info(opcode);
 
-        return DataflowLoop(instr, workmap_is_a_copy_of_stackmap);
+    processed_instruction = jsr;
+    if (jsr || props.isMultiway(jsr)) {
+        //note that in SubroutineDone unlike StartLinearDataflow we get workmap from stackmap
+        //in case of the first instruction of the method
+        fill_workmap(jsr);
+    } else {
+        vf_Result tcr = create_method_initial_workmap();
+        assert(tcr == VF_OK); // method's signature was already verified in StartLinearDataflow
     }
 
-    vf_Result vf_Context_5::SubroutineDone(Address subr) {
-        SubroutineData *subrdata = ((PropsHead*)props.getInstrProps(subr)->next)->getSubrData(m_max_stack + m_stack_start);
-        subrdata->subrDataflowed = 1;
+    //list of handlers unknown
+    next_start_pc = 0;
 
-        if( !subrdata->retCount ) {
-            //no ret from subroutine -- dead code follows
-            return VF_OK;
-        }
+    restore_workmap_after_jsr(subr);
 
-        Address jsr = subrdata->caller;
+    //make a shift to the instr following jsr
+    Address instr = jsr + (opcode == OP_JSR_W ? 5 : 3);
+    assert(opcode == OP_JSR || opcode == OP_JSR_W);
 
-        OpCode opcode = (OpCode)m_bytecode[jsr];
-        ParseInfo &pi = instr_get_parse_info(opcode);
 
-        processed_instruction = jsr;
-        if (jsr || props.isMultiway(jsr)) {
-            //note that in SubroutineDone unlike StartLinearDataflow we get workmap from stackmap
-            //in case of the first instruction of the method
-            fill_workmap(jsr);
-        } else {
-            vf_Result tcr = create_method_initial_workmap();
-            assert(tcr == VF_OK); // method's signature was already verified in StartLinearDataflow
-        }
+    return DataflowLoop(instr, 0);
+}
 
-        //list of handlers unknown
-        next_start_pc = 0;
 
-        restore_workmap_after_jsr(subr);
 
-        //make a shift to the instr following jsr
-        Address instr = jsr + (opcode == OP_JSR_W ? 5 : 3);
-        assert(opcode == OP_JSR || opcode == OP_JSR_W);
+// iterate thru the instructions starting with 'instr'
+vf_Result vf_Context_5::DataflowLoop (Address instr, int workmap_is_a_copy_of_stackmap) {
 
+    vf_Result tcr;
 
-        return DataflowLoop(instr, 0);
-    }
+    while( instr < m_code_length ) {
+        if( !workmap_is_a_copy_of_stackmap && props.isMultiway(instr) ) {
+            //if instruction has a stackmap and workmap was not just obtained from that stackmap
+            // add constraint: workmap is assignable to stackmap(instr)
+            if( (tcr=new_generic_vector_constraint(instr)) != VF_OK ) {
+                return tcr;
+            }
+
+            if( props.isDataflowPassed(instr) ) {
+                return VF_OK;
+            }
+
+            fill_workmap(instr);
+        }
+        workmap_is_a_copy_of_stackmap = false;
 
+        OpCode opcode = (OpCode)m_bytecode[instr];
+        processed_instruction = instr;
+        // keep all nessesary information about instruction
+        ParseInfo &pi = instr_get_parse_info(opcode);
 
+        //check IN types, create OUT types, check exception
+        if( (tcr=dataflow_instruction(instr)) != VF_OK ) {
+            return tcr;
+        }
 
-    // iterate thru the instructions starting with 'instr'
-    vf_Result vf_Context_5::DataflowLoop (Address instr, int workmap_is_a_copy_of_stackmap) {
+        props.setDataflowPassed(instr);
 
-        vf_Result tcr;
+        unsigned instr_len = instr_get_minlen(pi);
+        if( instr_is_compound(opcode, pi) ) {
+            // get ACTUAL length for variable length insgtructions
+            instr_len = instr_get_len_compound(instr, opcode);
+        }
+
+        if( instr_is_jump(pi) ) {
+            Address target = instr_get_jump_target(pi, m_bytecode, instr);
 
-        while( instr < m_code_length ) {
-            if( !workmap_is_a_copy_of_stackmap && props.isMultiway(instr) ) {
-                //if instruction has a stackmap and workmap was not just obtained from that stackmap
-                // add constraint: workmap is assignable to stackmap(instr)
-                if( (tcr=new_generic_vector_constraint(instr)) != VF_OK ) {
+            if( props.isMultiway(target) || instr_is_jsr(opcode) ) {
+                //TODO: need to test commented out optimization
+                //&& (!instr_direct(pi, opcode, m_bytecode, instr) || props.isDataflowPassed(target))
+                if( (tcr=new_generic_vector_constraint(target)) != VF_OK ) {
                     return tcr;
                 }
+            }
 
-                if( props.isDataflowPassed(instr) ) {
+            if( instr_direct(pi, opcode, m_bytecode, instr) ) {
+                //goto, goto_w
+                if( !props.isDataflowPassed(target) ) {
+                    if( target < instr ) next_start_pc = 0;
+                    instr = target;
+                    continue;
+                } else {
                     return VF_OK;
                 }
-
-                fill_workmap(instr);
             }
-            workmap_is_a_copy_of_stackmap = false;
 
-            OpCode opcode = (OpCode)m_bytecode[instr];
-            processed_instruction = instr;
-            // keep all nessesary information about instruction
-            ParseInfo &pi = instr_get_parse_info(opcode);
-
-            //check IN types, create OUT types, check exception
-            if( (tcr=dataflow_instruction(instr)) != VF_OK ) {
-                return tcr;
-            }
 
-            props.setDataflowPassed(instr);
+            //TODO: makes sense to move the block into dataflow_instruction??
+            if( instr_is_jsr(opcode) ) {
+                PropsHead_5 *target_pro = (PropsHead_5*)props.getInstrProps(target);
 
-            unsigned instr_len = instr_get_minlen(pi);
-            if( instr_is_compound(opcode, pi) ) {
-                // get ACTUAL length for variable length insgtructions
-                instr_len = instr_get_len_compound(instr, opcode);
-            }
-
-            if( instr_is_jump(pi) ) {
-                Address target = instr_get_jump_target(pi, m_bytecode, instr);
-
-                if( props.isMultiway(target) || instr_is_jsr(opcode) ) {
-                    //TODO: need to test commented out optimization
-                    //&& (!instr_direct(pi, opcode, m_bytecode, instr) || props.isDataflowPassed(target))
-                    if( (tcr=new_generic_vector_constraint(target)) != VF_OK ) {
-                        return tcr;
+                if( !props.isDataflowPassed(target) ) {
+                    for( unsigned i = 0; i < m_stack_start; i++ ) {
+                        StackmapElement_5 &el = target_pro->stackmap.elements[i];
+                        el.clearJsrModified();
                     }
-                }
 
-                if( instr_direct(pi, opcode, m_bytecode, instr) ) {
-                    //goto, goto_w
-                    if( !props.isDataflowPassed(target) ) {
-                        if( target < instr ) next_start_pc = 0;
-                        instr = target;
-                        continue;
-                    } else {
-                        return VF_OK;
+                    //create vector for storing ret types coming out of subroutine
+                    PropsHead_5 *retpro = newRetData();
+                    retpro->instr = 0xFFFF;
+                    assert(!target_pro->next || target_pro->next->instr != 0xFFFF );
+                    retpro->next = target_pro->next;
+                    target_pro->next = retpro;
+
+                    SubroutineData *subrdata = retpro->getSubrData(m_stack_start+m_max_stack);
+
+                    if( !props.getInstrProps(instr) && instr) {
+                        //if jsr instruction does not have workmap copy or stackmap, associated with it - create it
+                        assert(workmap->depth);
+                        workmap->depth--; // undo PUSH(SM_RETADDR)
+                        storeWorkmapCopy(instr);
                     }
-                }
 
+                    //need to return to that JSR instr later, when finish subroutine processing
+                    subrdata->caller = instr;
 
-                //TODO: makes sense to move the block into dataflow_instruction??
-                if( instr_is_jsr(opcode) ) {
-                    PropsHead *target_pro = (PropsHead*)props.getInstrProps(target);
-
-                    if( !props.isDataflowPassed(target) ) {
-                        for( unsigned i = 0; i < m_stack_start; i++ ) {
-                            StackmapElement &el = target_pro->stackmap.elements[i];
-                            el.clearJsrModified();
-                        }
-
-                        //create vector for storing ret types coming out of subroutine
-                        PropsHead *retpro = newRetData();
-                        retpro->instr = 0xFFFF;
-                        assert(!target_pro->next || target_pro->next->instr != 0xFFFF );
-                        retpro->next = target_pro->next;
-                        target_pro->next = retpro;
-
-                        SubroutineData *subrdata = retpro->getSubrData(m_stack_start+m_max_stack);
-
-                        if( !props.getInstrProps(instr) && instr) {
-                            //if jsr instruction does not have workmap copy or stackmap, associated with it - create it
-                            assert(workmap->depth);
-                            workmap->depth--; // undo PUSH(SM_RETADDR)
-                            storeWorkmapCopy(instr);
-                        }
+                    //need to postpone some finalizing stuff
+                    stack.xPush(target, MARK_SUBROUTINE_DONE);
 
-                        //need to return to that JSR instr later, when finish subroutine processing
-                        subrdata->caller = instr;
+                    //process subroutine
+                    stack.xPush(target);
 
-                        //need to postpone some finalizing stuff
-                        stack.xPush(target, MARK_SUBROUTINE_DONE);
+                    return VF_OK;
+                } else {
+                    SubroutineData *subrdata = ((PropsHead_5*)target_pro->next)->getSubrData(m_stack_start+m_max_stack);
 
-                        //process subroutine
-                        stack.xPush(target);
+                    if( !subrdata->subrDataflowed ) {
+                        //recursive call?
+                        return error(VF_ErrorDataFlow, "recursive subroutine");
+                    }
 
-                        return VF_OK;
-                    } else {
-                        SubroutineData *subrdata = ((PropsHead*)target_pro->next)->getSubrData(m_stack_start+m_max_stack);
+                    restore_workmap_after_jsr(target);
 
-                        if( !subrdata->subrDataflowed ) {
-                            //recursive call?
-                            return error(VF_ErrorDataFlow, "recursive subroutine");
-                        }
-
-                        restore_workmap_after_jsr(target);
-
-                        if( !subrdata->retCount ) {
-                            //no ret from subroutine -- dead code follows
-                            return VF_OK;
-                        } 
+                    if( !subrdata->retCount ) {
+                        //no ret from subroutine -- dead code follows
+                        return VF_OK;
+                    } 
 
-                        instr += instr_len;
-                        continue;
-                    }
+                    instr += instr_len;
+                    continue;
                 }
+            }
 
-                if( !props.isMultiway(target) ) {
-                    //if* with no stackmap at branch
-                    storeWorkmapCopy(target);
-                    assert( !props.isDataflowPassed(target) );
-                }
+            if( !props.isMultiway(target) ) {
+                //if* with no stackmap at branch
+                storeWorkmapCopy(target);
+                assert( !props.isDataflowPassed(target) );
+            }
 
-                if( !props.isDataflowPassed(target) ) {
-                    stack.xPush(target);
-                }
+            if( !props.isDataflowPassed(target) ) {
+                stack.xPush(target);
+            }
 
-                instr += instr_len;
-            } else if( instr_direct(pi, opcode, m_bytecode, instr) ) {
-                // it is not a jump ==> it is ret, return or throw
-                return VF_OK;
-            } else if( instr_is_switch(pi) ) {
+            instr += instr_len;
+        } else if( instr_direct(pi, opcode, m_bytecode, instr) ) {
+            // it is not a jump ==> it is ret, return or throw
+            return VF_OK;
+        } else if( instr_is_switch(pi) ) {
 
-                Address next_target_adr = (instr & (~3) ) + 4;
+            Address next_target_adr = (instr & (~3) ) + 4;
 
-                //default target
-                Address target = instr + read_int32(m_bytecode + next_target_adr);
+            //default target
+            Address target = instr + read_int32(m_bytecode + next_target_adr);
+            processSwitchTarget(target);
+
+            // in tableswitch instruction target offsets are stored with shift = 4,
+            // in lookupswitch with shift = 8
+            int shift = (opcode == OP_TABLESWITCH) ? 4 : 8;
+
+            // process conditional jump target
+            for (next_target_adr += 12;
+                next_target_adr < instr + instr_len;
+                next_target_adr += shift)
+            {
+                target = instr + read_int32(m_bytecode + next_target_adr);
                 processSwitchTarget(target);
+            }
 
-                // in tableswitch instruction target offsets are stored with shift = 4,
-                // in lookupswitch with shift = 8
-                int shift = (opcode == OP_TABLESWITCH) ? 4 : 8;
+            return VF_OK;
+        } else {
+            assert( instr_is_regular(pi) );
+            instr += instr_len;
+        }
 
-                // process conditional jump target
-                for (next_target_adr += 12;
-                    next_target_adr < instr + instr_len;
-                    next_target_adr += shift)
-                {
-                    target = instr + read_int32(m_bytecode + next_target_adr);
-                    processSwitchTarget(target);
-                }
+    }
 
-                return VF_OK;
-            } else {
-                assert( instr_is_regular(pi) );
-                instr += instr_len;
-            }
+    // control went out of method bounds
+    return error(VF_ErrorCodeEnd, "control went out of method bounds");
+}
 
-        }
+vf_Result vf_Context_5::verify_method(Method_Handle method) {
+    vf_Result tcr;
 
-        // control went out of method bounds
-        return error(VF_ErrorCodeEnd, "control went out of method bounds");
+    //nothing to verify
+    if( !method_get_bytecode_length( method ) ) {
+        return VF_OK;
     }
 
-    vf_Result vf_Context_5::verify_method(Method_Handle method) {
-        vf_Result tcr;
+    //load memory storage, read variable like max_stack, etc
+    init(method);
 
-        //nothing to verify
-        if( !method_get_bytecode_length( method ) ) {
-            return VF_OK;
-        }
+    //////////////////////////// FIRST PASS /////////////////////////
+    pass = 1;
+    stack.push(0);
+
+    uint16 idx;
+    uint16 start_pc;
+    uint16 end_pc;
+    uint16 handler_pc;
+    uint16 handler_cp_index;
+
+    //check validness of try blocks
+    //TODO: is verifier the right place for that?
+    for( idx = 0; idx < m_handlecount; idx++ ) {
+        method_get_exc_handler_info( m_method, idx, &start_pc, &end_pc, &handler_pc, &handler_cp_index );
 
-        //load memory storage, read variable like max_stack, etc
-        init(method);
+        if( start_pc >= end_pc || end_pc > m_code_length ) {
+            return error(VF_ErrorHandler, "start_pc >= end_pc OR end_pc > code_length");
+        }
+    }
 
-        //////////////////////////// FIRST PASS /////////////////////////
-        pass = 1;
-        stack.push(0);
-
-        unsigned short idx;
-        unsigned short start_pc;
-        unsigned short end_pc;
-        unsigned short handler_pc;
-        unsigned short handler_cp_index;
+    FastStack<Address> deadstack;
+    do {
+        while( !stack.is_empty() ) {
+            vf_Result tcr = parse(stack.pop(), false, &deadstack);
+            if( tcr != VF_OK ) {
+                return tcr;
+            }
+        }
 
-        //check validness of try blocks
-        //TODO: is verifier the right place for that?
         for( idx = 0; idx < m_handlecount; idx++ ) {
             method_get_exc_handler_info( m_method, idx, &start_pc, &end_pc, &handler_pc, &handler_cp_index );
 
-            if( start_pc >= end_pc || end_pc > m_code_length ) {
-                return error(VF_ErrorHandler, "start_pc >= end_pc OR end_pc > code_length");
+            if( props.isParsePassed(handler_pc)) {
+                props.setMultiway(handler_pc);
+                continue;
             }
-        }
 
-        FastStack<Address> deadstack;
-        do {
-            while( !stack.is_empty() ) {
-                vf_Result tcr = parse(stack.pop(), false, &deadstack);
-                if( tcr != VF_OK ) {
-                    return tcr;
-                }
+            if( props.isOperand(handler_pc) ) {
+                return error(VF_ErrorCodeEnd, "handler_pc at the middle of an instruction");
             }
 
-            for( idx = 0; idx < m_handlecount; idx++ ) {
-                method_get_exc_handler_info( m_method, idx, &start_pc, &end_pc, &handler_pc, &handler_cp_index );
-
-                if( props.isParsePassed(handler_pc)) {
-                    props.setMultiway(handler_pc);
-                    continue;
+            for( Address i = start_pc; i < end_pc; i++ ) {
+                //check if there was a reachable code in try block
+                if( props.isParsePassed(i) ) {
+                    //push handler if there was
+                    stack.push(handler_pc);
+                    break;
                 }
+            }
+        }
+    } while (!stack.is_empty());
 
-                if( props.isOperand(handler_pc) ) {
-                    return error(VF_ErrorCodeEnd, "handler_pc at the middle of an instruction");
-                }
+    //parsing dead code: check that no invalid opcodes are there and no jumps to the middles of the instructions
+    //clean up the dead stack, (new pushs will go to the regular stack)
+    while( !deadstack.is_empty() ) {
+        vf_Result tcr = parse(deadstack.pop(), true, &stack);
+        if( tcr != VF_OK ) {
+            return tcr;
+        }
+    }
 
-                for( Address i = start_pc; i < end_pc; i++ ) {
-                    //check if there was a reachable code in try block
-                    if( props.isParsePassed(i) ) {
-                        //push handler if there was
-                        stack.push(handler_pc);
-                        break;
-                    }
-                }
-            }
-        } while (!stack.is_empty());
+    //put all handlers, even for the dead try blocks
+    for( idx = 0; idx < m_handlecount; idx++ ) {
+        method_get_exc_handler_info( m_method, idx, &start_pc, &end_pc, &handler_pc, &handler_cp_index );
+        stack.push(handler_pc);
+    }
 
-        //parsing dead code: check that no invalid opcodes are there and no jumps to the middles of the instructions
-        //clean up the dead stack, (new pushs will go to the regular stack)
-        while( !deadstack.is_empty() ) {
-            vf_Result tcr = parse(deadstack.pop(), true, &stack);
-            if( tcr != VF_OK ) {
-                return tcr;
-            }
+    //clean up the stack, (check jumps to the middle)
+    while( !stack.is_empty() ) {
+        vf_Result tcr = parse(stack.pop(), true, &stack);
+        if( tcr != VF_OK ) {
+            return tcr;
         }
+    }
+    //end of dead code parsing
 
-        //put all handlers, even for the dead try blocks
-        for( idx = 0; idx < m_handlecount; idx++ ) {
-            method_get_exc_handler_info( m_method, idx, &start_pc, &end_pc, &handler_pc, &handler_cp_index );
-            stack.push(handler_pc);
+
+    for( idx = 0; idx < m_handlecount; idx++ ) {
+
+        method_get_exc_handler_info( m_method, idx, &start_pc, &end_pc, &handler_pc, &handler_cp_index );
+
+        if( end_pc < m_code_length && props.isOperand(end_pc) || props.isOperand(start_pc) ) {
+            return error(VF_ErrorCodeEnd, "start_pc or end_pc are at the middle of an instruction");
         }
 
-        //clean up the stack, (check jumps to the middle)
-        while( !stack.is_empty() ) {
-            vf_Result tcr = parse(stack.pop(), true, &stack);
-            if( tcr != VF_OK ) {
-                return tcr;
+        SmConstant handler_type;
+        if( handler_cp_index ) {
+            if( !tpool.cpool_get_class(handler_cp_index, &handler_type) ||
+                !tpool.mustbe_assignable(handler_type, tpool.sm_get_const_throwable()) )
+            {
+                return error(VF_ErrorHandler, "incorrect constantpool entry");
             }
+        } else {
+            handler_type = tpool.sm_get_const_throwable();
         }
-        //end of dead code parsing
-
 
-        for( idx = 0; idx < m_handlecount; idx++ ) {
+        props.setMultiway(handler_pc);
+        createHandlerStackmap(handler_pc, handler_type);
+    }
 
-            method_get_exc_handler_info( m_method, idx, &start_pc, &end_pc, &handler_pc, &handler_cp_index );
+    //////////////////////////// SECOND PASS /////////////////////////
+    pass = 2;
+    props.pass2started(stackmapattr_calculation, m_code_length);
+
+    stack.xPush(0);
+    while( !stack.is_empty() ) {
+        Address next;
+        short mark;
 
-            if( end_pc < m_code_length && props.isOperand(end_pc) || props.isOperand(start_pc) ) {
-                return error(VF_ErrorCodeEnd, "start_pc or end_pc are at the middle of an instruction");
-            }
+        stack.xPop(&next, &mark);
 
-            SmConstant handler_type;
-            if( handler_cp_index ) {
-                if( !tpool.cpool_get_class(handler_cp_index, &handler_type) ||
-                    !tpool.mustbe_assignable(handler_type, tpool.sm_get_const_throwable()) )
-                {
-                    return error(VF_ErrorHandler, "incorrect constantpool entry");
-                }
-            } else {
-                handler_type = tpool.sm_get_const_throwable();
-            }
+        if( !mark ) {
+            tcr = StartLinearDataflow(next);
+        } else {
+            assert(mark == MARK_SUBROUTINE_DONE);
+            tcr = SubroutineDone(next);
+        }
 
-            props.setMultiway(handler_pc);
-            createHandlerStackmap(handler_pc, handler_type);
+        if( tcr != VF_OK ) {
+            return tcr;
         }
+    }
 
-        //////////////////////////// SECOND PASS /////////////////////////
-        pass = 2;
-        props.pass2started(stackmapattr_calculation, m_code_length);
+    return VF_OK;
+}
 
-        stack.xPush(0);
-        while( !stack.is_empty() ) {
-            Address next;
-            short mark;
 
-            stack.xPop(&next, &mark);
 
-            if( !mark ) {
-                tcr = StartLinearDataflow(next);
-            } else {
-                assert(mark == MARK_SUBROUTINE_DONE);
-                tcr = SubroutineDone(next);
-            }
 
-            if( tcr != VF_OK ) {
-                return tcr;
-            }
-        }
+vf_Result vf_Context_5::new_ret_vector_constraint(Address jsr_target) {
+    PropsHead_5 *inpro = (PropsHead_5*)props.getInstrProps(jsr_target);
+    PropsHead_5 *outpro = (PropsHead_5*)inpro->next;
+    assert(outpro->instr == 0xFFFF);
 
-        return VF_OK;
-    }
+    SubroutineData *subrdata = outpro->getSubrData(m_stack_start + m_max_stack);
+    subrdata->retCount++;
+
+    //if it is a first ret from the given subroutine (majority of the cases)
+    if( subrdata->retCount == 1 ) {
+        //remove newly appeared ret addresses: it might happen
+        //if non-top subroutine made a ret
+        StackmapHead* original = inpro->getStackmap();
+        unsigned i;
 
+        for( i = 0; i < m_stack_start + workmap->depth; i++ ) {
+            if( i < m_stack_start && !workmap->elements[i].isJsrModified() ) {
+                //nothing new here
+                continue;
+            }
 
+            SmConstant val = workmap->elements[i].getAnyPossibleValue();
+            if( val.isRetAddr() ) {
+                //check if it's a newly appeared ret addfress
 
+                // '-1' is twice below to exclude top of the stack. 
+                // top of the stack contains ret address for the current subroutine
+                // it also cleaned up if it's still there
 
-    vf_Result vf_Context_5::new_ret_vector_constraint(Address jsr_target) {
-        PropsHead *inpro = (PropsHead*)props.getInstrProps(jsr_target);
-        PropsHead *outpro = (PropsHead*)inpro->next;
-        assert(outpro->instr == 0xFFFF);
-
-        SubroutineData *subrdata = outpro->getSubrData(m_stack_start + m_max_stack);
-        subrdata->retCount++;
-
-        //if it is a first ret from the given subroutine (majority of the cases)
-        if( subrdata->retCount == 1 ) {
-            //remove newly appeared ret addresses: it might happen
-            //if non-top subroutine made a ret
-            StackmapHead* original = inpro->getStackmap();
-            unsigned i;
-
-            for( i = 0; i < m_stack_start + workmap->depth; i++ ) {
-                if( i < m_stack_start && !workmap->elements[i].isJsrModified() ) {
-                    //nothing new here
+                if( i < m_stack_start + original->depth - 1 && 
+                    original->elements[i].getAnyIncomingValue() == val ) 
+                {
+                    //most likely: this ret address was there before
                     continue;
                 }
 
-                SmConstant val = workmap->elements[i].getAnyPossibleValue();
-                if( val.isRetAddr() ) {
-                    //check if it's a newly appeared ret addfress
-
-                    // '-1' is twice below to exclude top of the stack. 
-                    // top of the stack contains ret address for the current subroutine
-                    // it also cleaned up if it's still there
-
-                    if( i < m_stack_start + original->depth - 1 && 
-                        original->elements[i].getAnyIncomingValue() == val ) 
-                    {
-                        //most likely: this ret address was there before
-                        continue;
-                    }
-
-                    //iterate thru original types and look for this ret address
-                    int found_in_original = 0;
-                    for( unsigned j = 0; j < m_stack_start + original->depth - 1; j++ ) {
-                        if( original->elements[j].getAnyIncomingValue() == val ) {
-                            found_in_original = 1;
-                            break;
-                        }
-                    }
-                    if( !found_in_original ) {
-                        //original types did not have this ret address
-                        workmap->elements[i] = _WorkmapElement(SM_BOGUS);
+                //iterate thru original types and look for this ret address
+                int found_in_original = 0;
+                for( unsigned j = 0; j < m_stack_start + original->depth - 1; j++ ) {
+                    if( original->elements[j].getAnyIncomingValue() == val ) {
+                        found_in_original = 1;
+                        break;
                     }
                 }
+                if( !found_in_original ) {
+                    //original types did not have this ret address
+                    workmap->elements[i] = _WorkmapElement_5(SM_BOGUS);
+                }
             }
-
-            //TODO make sure incoming was created as JSR transformation
-            tc_memcpy(outpro->getWorkmap(), workmap, sizeof(WorkmapHead) + sizeof(WorkmapElement) * (m_stack_start + workmap->depth));
-            return VF_OK;
         }
 
-        return error(VF_ErrorStackDepth, "Multiple returns to single jsr");
+        //TODO make sure incoming was created as JSR transformation
+        tc_memcpy(outpro->getWorkmap(), workmap, sizeof(WorkmapHead) + sizeof(WorkmapElement_5) * (m_stack_start + workmap->depth));
+        return VF_OK;
     }
 
+    return error(VF_ErrorStackDepth, "Multiple returns to single jsr");
+}
 
-    void vf_Context_5::restore_workmap_after_jsr(Address jsr_target) {
-        PropsHead *inpro = (PropsHead*)props.getInstrProps(jsr_target);
-        PropsHead *outpro = (PropsHead*)inpro->next;
-        SubroutineData *subrdata = outpro->getSubrData(m_stack_start + m_max_stack);
-
-        if( subrdata->retCount ) {
-            assert( subrdata->retCount == 1 );
-            WorkmapHead* outcoming = outpro->getWorkmap();
-            workmap->depth = outcoming->depth;
 
-            unsigned i;
-            for( i = 0; i < m_stack_start; i++ ) {
-                if( outcoming->elements[i].isJsrModified() ) {
-                    workmap->elements[i] = outcoming->elements[i];
-                }
-            }
-            for( ; i < m_stack_start + workmap->depth; i++ ) {
+void vf_Context_5::restore_workmap_after_jsr(Address jsr_target) {
+    PropsHead_5 *inpro = (PropsHead_5*)props.getInstrProps(jsr_target);
+    PropsHead_5 *outpro = (PropsHead_5*)inpro->next;
+    SubroutineData *subrdata = outpro->getSubrData(m_stack_start + m_max_stack);
+
+    if( subrdata->retCount ) {
+        assert( subrdata->retCount == 1 );
+        WorkmapHead* outcoming = outpro->getWorkmap();
+        workmap->depth = outcoming->depth;
+
+        unsigned i;
+        for( i = 0; i < m_stack_start; i++ ) {
+            if( outcoming->elements[i].isJsrModified() ) {
                 workmap->elements[i] = outcoming->elements[i];
-            }    
+            }
         }
+        for( ; i < m_stack_start + workmap->depth; i++ ) {
+            workmap->elements[i] = outcoming->elements[i];
+        }    
     }
+}
 
-    vf_Result vf_Context_5::new_scalar_constraint(WorkmapElement *from, StackmapElement *to) {
-        assert(from->getAnyPossibleValue() != SM_NONE);
+vf_Result vf_Context_5::new_scalar_constraint(WorkmapElement_5 *from, StackmapElement_5 *to) {
+    assert(from->getAnyPossibleValue() != SM_NONE);
 
-        if( from->isJsrModified() ) {
-            //JSR overhead
-            to->setJsrModified();
-        }
-
-        if( !from->isVariable() ) {
-            SmConstant inc_val = from->getConst();
-            return add_incoming_value( inc_val, to );
-        } else {
-            GenericCnstr* gen = from->getVariable()->firstGenericCnstr();
-            while( gen ) {
-                if( gen->variable == to ) return VF_OK;
-                gen = gen->next();
-            }
+    if( from->isJsrModified() ) {
+        //JSR overhead
+        to->setJsrModified();
+    }
 
-            IncomingType *inc = from->getVariable()->firstIncoming();
-            from->getVariable()->newGenericConstraint(&mem, to);
-
-            while( inc ) {
-                vf_Result vcr = add_incoming_value( inc->value, to );
-                if( vcr != VF_OK ) {
-                    return vcr;
-                }
-                inc = inc->next();
-            }
-            return VF_OK;
+    if( !from->isVariable() ) {
+        SmConstant inc_val = from->getConst();
+        return add_incoming_value( inc_val, to );
+    } else {
+        GenericCnstr* gen = from->getVariable()->firstGenericCnstr();
+        while( gen ) {
+            if( gen->variable == to ) return VF_OK;
+            gen = gen->next();
         }
-    }
 
-    vf_Result vf_Context_5::add_incoming_value(SmConstant new_value, StackmapElement *destination) {
-        //check if the node already has such incoming value
-        IncomingType *inc = destination->firstIncoming();
+        IncomingType *inc = from->getVariable()->firstIncoming();
+        from->getVariable()->newGenericConstraint(&mem, to);
+
         while( inc ) {
-            if( new_value == inc->value  || inc->value == SM_BOGUS ) {
-                return VF_OK;
+            vf_Result vcr = add_incoming_value( inc->value, to );
+            if( vcr != VF_OK ) {
+                return vcr;
             }
             inc = inc->next();
         }
+        return VF_OK;
+    }
+}
 
-        if( new_value.isNonMergeable() && destination->firstIncoming() ) {
-            //uninit value merged to any different value is bogus
-            //ret address merged to any different value is bogus
-            //assert - incoming value exists is different - we've already checked that new_value is missing in the list of incoming values
-            new_value = SM_BOGUS;
-        }
-
-        //add incoming value if it does not have
-        Constraint* next = destination->firstOthers();
-        //TODO: optimize memory footprint for new_value == SM_BOGUS
-        destination->newIncomingType(&mem, new_value);
-
-        //check if it contradicts to expected types and further propagate
-        while( next ) {
-            switch (next->type) {
-            case CT_EXPECTED_TYPE:
-                if( !tpool.mustbe_assignable(new_value, next->value) ) return error(VF_ErrorUnknown, "unexpected type on stack or local variable");
-                break;
-            case CT_GENERIC: {
-                vf_Result vcr = add_incoming_value(new_value, next->variable);
-                if( vcr != VF_OK ) return vcr;
-                break;
-                             }
-            case CT_ARRAY2REF: {
-                vf_Result vcr = add_incoming_value( tpool.get_ref_from_array(new_value), next->variable);
-                if( vcr != VF_OK ) return vcr;
-                break;
-                               }
-            default:
-                assert(0);
-                return error(VF_ErrorInternal, "unreachable statement in add_incoming_value");
-            }
-            next = next->next();
+vf_Result vf_Context_5::add_incoming_value(SmConstant new_value, StackmapElement_5 *destination) {
+    //check if the node already has such incoming value
+    IncomingType *inc = destination->firstIncoming();
+    while( inc ) {
+        if( new_value == inc->value  || inc->value == SM_BOGUS ) {
+            return VF_OK;
         }
-        return VF_OK;
+        inc = inc->next();
+    }
+
+    if( new_value.isNonMergeable() && destination->firstIncoming() ) {
+        //uninit value merged to any different value is bogus
+        //ret address merged to any different value is bogus
+        //assert - incoming value exists is different - we've already checked that new_value is missing in the list of incoming values
+        new_value = SM_BOGUS;
     }
 
-} // namespace CPVerifier
+    //add incoming value if it does not have
+    Constraint* next = destination->firstOthers();
+    //TODO: optimize memory footprint for new_value == SM_BOGUS
+    destination->newIncomingType(&mem, new_value);
+
+    //check if it contradicts to expected types and further propagate
+    while( next ) {
+        switch (next->type) {
+        case CT_EXPECTED_TYPE:
+            if( !tpool.mustbe_assignable(new_value, next->value) ) return error(VF_ErrorUnknown, "unexpected type on stack or local variable");
+            break;
+        case CT_GENERIC: {
+            vf_Result vcr = add_incoming_value(new_value, next->variable);
+            if( vcr != VF_OK ) return vcr;
+            break;
+                         }
+        case CT_ARRAY2REF: {
+            vf_Result vcr = add_incoming_value( tpool.get_ref_from_array(new_value), next->variable);
+            if( vcr != VF_OK ) return vcr;
+            break;
+                           }
+        default:
+            assert(0);
+            return error(VF_ErrorInternal, "unreachable statement in add_incoming_value");
+        }
+        next = next->next();
+    }
+    return VF_OK;
+}

Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/java5/context_5.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/java5/context_5.h?rev=649574&r1=649573&r2=649574&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/java5/context_5.h (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/java5/context_5.h Fri Apr 18 08:29:36 2008
@@ -14,10 +14,6 @@
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  */
-/** 
- * @author Mikhail Loenko, Vladimir Molotkov
- */  
-
 #ifndef __CONTEXT5_H__
 #define __CONTEXT5_H__
 
@@ -27,312 +23,304 @@
 #include "stackmap_5.h"
 #include "instr_props_5.h"
 
-using namespace CPVerifier;
-
-
-namespace CPVerifier_5 {
-
-    //
-    // Context - main class of Type Checker
-    //
-
-    class vf_Context_5 : public vf_Context_x<vf_Context_5, WorkmapElement, _WorkmapElement, StackmapElement> {
-    public:
-        vf_Context_5(SharedClasswideData &classwide) :
-          vf_Context_x<vf_Context_5, WorkmapElement, _WorkmapElement, StackmapElement>(classwide) {
-              stackmapattr_calculation = false;
-          }
-
-          vf_Result verify_method(Method_Handle method);
-    protected:
-        // various flags for all the method's bytecode instructions
-        InstrProps props;
-
-        // stack to push instructions like branch targets, etc to go thru the method. the stack is method-wide.
-        MarkableStack stack;
-
-        //we would like to flush StackMapTable attribute from this method
-        bool      stackmapattr_calculation;
-
-        void mark_stackmap_point(Address target) {
-            //in case we prepare for flushing stackmaptable attrribute
-            //make sure we avoid optimization and mark all targets as multiway
-            if( stackmapattr_calculation ) stack.push(target);
-        }
-
-        static const short MARK_SUBROUTINE_DONE = -1;
-
-        //init method-wide data
-        void init(Method_Handle _m_method) {
-            vf_Context_x<vf_Context_5, WorkmapElement, _WorkmapElement, StackmapElement>::init(_m_method);
-            stack.init();
-            props.init(mem, m_code_length);
-        }
-
-        // load derived types previously stored for the given instruction
-        void fill_workmap(Address instr) {
-            PropsHead *head = (PropsHead*)props.getInstrProps(instr);
-            if( head->is_workmap() ) {
-                tc_memcpy(workmap, head->getWorkmap(), sizeof(WorkmapHead) + sizeof(WorkmapElement) * (m_stack_start + head->workmap.depth));
-            } else {
-                StackmapHead *stackmap = head->getStackmap();
+static const short MARK_SUBROUTINE_DONE = -1;
 
-                workmap->depth = stackmap->depth;
-
-                for( unsigned i = 0; i < m_stack_start + stackmap->depth; i++) {
-                    workmap->elements[i] = _WorkmapElement(&stackmap->elements[i]);
-                    assert( workmap->elements[i].getAnyPossibleValue() != SM_NONE );
-                }
+//
+// Context - main class of Type Checker
+//
+class vf_Context_5 : public vf_Context_x<vf_Context_5, WorkmapElement_5, _WorkmapElement_5, StackmapElement_5> {
+public:
+    vf_Context_5(SharedClasswideData &classwide) :
+      vf_Context_x<vf_Context_5, WorkmapElement_5, _WorkmapElement_5, StackmapElement_5>(classwide) {
+          stackmapattr_calculation = false;
+      }
+
+      vf_Result verify_method(Method_Handle method);
+protected:
+    // various flags for all the method's bytecode instructions
+    InstrProps props;
+
+    // stack to push instructions like branch targets, etc to go thru the method. the stack is method-wide.
+    MarkableStack stack;
+
+    //we would like to flush StackMapTable attribute from this method
+    bool      stackmapattr_calculation;
+
+    void mark_stackmap_point(Address target) {
+        //in case we prepare for flushing stackmaptable attrribute
+        //make sure we avoid optimization and mark all targets as multiway
+        if( stackmapattr_calculation ) stack.push(target);
+    }
+
+    //init method-wide data
+    void init(Method_Handle _m_method) {
+        vf_Context_x<vf_Context_5, WorkmapElement_5, _WorkmapElement_5, StackmapElement_5>::init(_m_method);
+        stack.init();
+        props.init(mem, m_code_length);
+    }
+
+    // load derived types previously stored for the given instruction
+    void fill_workmap(Address instr) {
+        PropsHead_5 *head = (PropsHead_5*)props.getInstrProps(instr);
+        if( head->is_workmap() ) {
+            tc_memcpy(workmap, head->getWorkmap(), sizeof(WorkmapHead) + sizeof(WorkmapElement_5) * (m_stack_start + head->workmap.depth));
+        } else {
+            StackmapHead *stackmap = head->getStackmap();
+
+            workmap->depth = stackmap->depth;
+
+            for( unsigned i = 0; i < m_stack_start + stackmap->depth; i++) {
+                workmap->elements[i] = _WorkmapElement_5(&stackmap->elements[i]);
+                assert( workmap->elements[i].getAnyPossibleValue() != SM_NONE );
+            }
+        }
+        no_locals_info = 1;
+    }
+
+    //store a copy of the current workmap for another instruction (such as a branch target)
+    void storeWorkmapCopy(Address target) {
+        int sz = m_stack_start + workmap->depth;
+        PropsHead_5* copy = newWorkmapProps(sz);
+        tc_memcpy(copy->getWorkmap(), workmap, sizeof(WorkmapHead) + sizeof(WorkmapElement_5) * sz);
+
+        props.setInstrProps(target, copy);
+    }
+
+    //create a stackmap vector of the given size sz (max_locals <= sz <= max_locals+max_stack)
+    PropsHead_5* newStackmap(int sz) {
+        return (PropsHead_5*)mem.calloc(sizeof(PropsHead_5) + sizeof(StackmapElement_5) * sz);
+    }
+
+    //create a vector that will be used for JSR procesing. 
+    //It contains ether stackmap or workmap vector, SubrouitineData, and flags vector indicating 
+    //changed locals
+    PropsHead_5 *newRetData() {
+        assert( sizeof(StackmapElement_5) >= sizeof(WorkmapElement_5) );
+
+        int sz = sizeof(PropsHead_5) + sizeof(StackmapElement_5) * (m_max_stack + m_stack_start) + //stackmap
+            ((sizeof(SubroutineData)+ m_stack_start) & (~3)) + 4; // fixed data and changed locals vector
+
+        PropsHead_5 * ret = (PropsHead_5 *) mem.calloc(sz);
+        ret->set_as_workmap();
+        return ret;
+    }
+
+    //creates a temporary variable for converting 
+    StackmapElement_5 *new_variable() {
+        return (StackmapElement_5*) mem.calloc(sizeof(StackmapElement_5));
+    }
+
+    /////////////////////////////////////////////////////////////////////////////////////////////////////
+
+    //First verification pass thru the method. checks that no jump outside the method or to the middle of instruction
+    //checks that opcodes are valid
+    vf_Result parse(Address instr, int dead_code_parsing, FastStack<Address> *deadstack);
+
+    //Second pass: dataflow of a piece of the method starting from the beginning or a branch target and finishing
+    //on return, athrow or hitting previously passed instruction. 
+    //This function initializes workmap and calls DataflowLoop
+    vf_Result StartLinearDataflow(Address start);
+
+    //Second pass: Finilize subroutie processing -- once we are here, then all the RETs from achievable for
+    //the given subroutine are passed, so we can resume passing for JSRs to the given address
+    //This function initializes workmap properly and calls DataflowLoop
+    vf_Result SubroutineDone(Address start);
+
+    //Second pass: dataflow of a piece of the method starting from the beginning or a branch target and finishing
+    //on return, athrow or hitting previously passed instruction
+    vf_Result DataflowLoop(Address start, int workmap_is_a_copy_of_stackmap);
+
+    //constraint propagation
+    vf_Result propagate(StackmapElement_5 *changed, SmConstant new_value);
+
+    //update current derived types according to what was changed in subroutine
+    void restore_workmap_after_jsr(Address jsr_target);
+
+    //create vector constraints for each target of a switch
+    vf_Result processSwitchTarget(Address target) {
+        vf_Result tcr;
+        if( props.isMultiway(target) ) {
+            if( (tcr=new_generic_vector_constraint(target)) != VF_OK ) {
+                return tcr;
             }
-            no_locals_info = 1;
-        }
-
-        //store a copy of the current workmap for another instruction (such as a branch target)
-        void storeWorkmapCopy(Address target) {
-            int sz = m_stack_start + workmap->depth;
-            PropsHead* copy = newWorkmapProps(sz);
-            tc_memcpy(copy->getWorkmap(), workmap, sizeof(WorkmapHead) + sizeof(WorkmapElement) * sz);
 
-            props.setInstrProps(target, copy);
-        }
+            if( !props.isDataflowPassed(target) ) {
+                stack.xPush(target);
+            }
+        } else {
+            assert( !props.isDataflowPassed(target) );
+            storeWorkmapCopy(target);
 
-        //create a stackmap vector of the given size sz (max_locals <= sz <= max_locals+max_stack)
-        PropsHead* newStackmap(int sz) {
-            return (PropsHead*)mem.calloc(sizeof(PropsHead) + sizeof(StackmapElement) * sz);
+            stack.xPush(target);
         }
+        return VF_OK;
+    }
 
-        //create a vector that will be used for JSR procesing. 
-        //It contains ether stackmap or workmap vector, SubrouitineData, and flags vector indicating 
-        //changed locals
-        PropsHead *newRetData() {
-            assert( sizeof(StackmapElement) >= sizeof(WorkmapElement) );
+    ///////////////////////////////////  "VIRTUAL" METHODS /////////////////////////////////////////////
+public:
+    //create constraint vector in case of a branch 
+    //simple conatraints are created for pairs of both locals and stack (current must be assignable to target)
+    vf_Result new_generic_vector_constraint(Address target_instr) {
+        return new_generic_vector_constraint_impl(getStackmap(target_instr, workmap->depth));
+    }
 
-            int sz = sizeof(PropsHead) + sizeof(StackmapElement) * (m_max_stack + m_stack_start) + //stackmap
-                ((sizeof(SubroutineData)+ m_stack_start) & (~3)) + 4; // fixed data and changed locals vector
-
-            PropsHead * ret = (PropsHead *) mem.calloc(sz);
-            ret->set_as_workmap();
-            return ret;
-        }
+    //when we hit RET instruction we update the data for the given subroutine with current derived types
+    vf_Result new_ret_vector_constraint(Address target_instr);
 
-        //creates a temporary variable for converting 
-        StackmapElement *new_variable() {
-            return (StackmapElement*) mem.calloc(sizeof(StackmapElement));
+    // push catch-block to the stack of branches to pass
+    void push_handler(Address handler_pc) {
+        if( !props.isDataflowPassed(handler_pc) ) {
+            stack.xPush(handler_pc);
         }
+    }
 
-        /////////////////////////////////////////////////////////////////////////////////////////////////////
-
-        //First verification pass thru the method. checks that no jump outside the method or to the middle of instruction
-        //checks that opcodes are valid
-        vf_Result parse(Address instr, int dead_code_parsing, FastStack<Address> *deadstack);
-
-        //Second pass: dataflow of a piece of the method starting from the beginning or a branch target and finishing
-        //on return, athrow or hitting previously passed instruction. 
-        //This function initializes workmap and calls DataflowLoop
-        vf_Result StartLinearDataflow(Address start);
-
-        //Second pass: Finilize subroutie processing -- once we are here, then all the RETs from achievable for
-        //the given subroutine are passed, so we can resume passing for JSRs to the given address
-        //This function initializes workmap properly and calls DataflowLoop
-        vf_Result SubroutineDone(Address start);
-
-        //Second pass: dataflow of a piece of the method starting from the beginning or a branch target and finishing
-        //on return, athrow or hitting previously passed instruction
-        vf_Result DataflowLoop(Address start, int workmap_is_a_copy_of_stackmap);
+    //create simple single constraint: "'from' is assingable to 'to'"
+    vf_Result new_scalar_constraint(WorkmapElement_5 *from, StackmapElement_5 *to);
 
-        //constraint propagation
-        vf_Result propagate(StackmapElement *changed, SmConstant new_value);
+    //add one more possible value (type) that can come to the given point (local or stack)
+    vf_Result add_incoming_value(SmConstant new_value, StackmapElement_5 *destination);
 
-        //update current derived types according to what was changed in subroutine
-        void restore_workmap_after_jsr(Address jsr_target);
+    //create stackmap for exception handler start
+    void createHandlerStackmap(Address handler_pc, SmConstant type) {
+        StackmapHead *map = getStackmap(handler_pc, 1);
+        //handler stackmaps are created before any dataflow analysis is done
+        assert(map->depth == 0 || map->depth == 1);
+        map->depth = 1;
 
-        //create vector constraints for each target of a switch
-        vf_Result processSwitchTarget(Address target) {
-            vf_Result tcr;
-            if( props.isMultiway(target) ) {
-                if( (tcr=new_generic_vector_constraint(target)) != VF_OK ) {
-                    return tcr;
-                }
+        vf_Result tcr = add_incoming_value(type, &map->elements[m_stack_start]);
 
-                if( !props.isDataflowPassed(target) ) {
-                    stack.xPush(target);
-                }
-            } else {
-                assert( !props.isDataflowPassed(target) );
-                storeWorkmapCopy(target);
+        // it is initialization stage
+        assert(tcr == VF_OK);
+    }
 
-                stack.xPush(target);
-            }
-            return VF_OK;
-        }
 
-        ///////////////////////////////////  "VIRTUAL" METHODS /////////////////////////////////////////////
-    public:
-        //create constraint vector in case of a branch 
-        //simple conatraints are created for pairs of both locals and stack (current must be assignable to target)
-        vf_Result new_generic_vector_constraint(Address target_instr) {
-            return new_generic_vector_constraint_impl(getStackmap(target_instr, workmap->depth));
-        }
+    //create a workmap vector for the given size sz (max_locals <= sz <= max_locals+max_stack)
+    PropsHead_5 *newWorkmapProps(int sz) {
+        PropsHead_5 * ret = (PropsHead_5*)mem.malloc(sizeof(PropsHead_5) + sizeof(WorkmapElement_5) * sz);
+        ret->set_as_workmap();
+        return ret;
+    }
 
-        //when we hit RET instruction we update the data for the given subroutine with current derived types
-        vf_Result new_ret_vector_constraint(Address target_instr);
-
-        // push catch-block to the stack of branches to pass
-        void push_handler(Address handler_pc) {
-            if( !props.isDataflowPassed(handler_pc) ) {
-                stack.xPush(handler_pc);
-            }
+    //returns stackmap for the 'instr' instruction
+    //if it does not exists yet -- create it. When created use 'depth' as stack depth
+    StackmapHead *getStackmap(Address instr, int depth) {
+        PropsHead_5 *pro = (PropsHead_5*) props.getInstrProps(instr);
+        if( !pro ) {
+            pro = newStackmap(m_stack_start + depth);
+            props.setInstrProps(instr, pro);
+            pro->getStackmap()->depth = depth;
         }
+        return pro->getStackmap();
+    }
 
-        //create simple single constraint: "'from' is assingable to 'to'"
-        vf_Result new_scalar_constraint(WorkmapElement *from, StackmapElement *to);
-
-        //add one more possible value (type) that can come to the given point (local or stack)
-        vf_Result add_incoming_value(SmConstant new_value, StackmapElement *destination);
+    //returns stackmap for the 'instr' instruction. it must exist
+    StackmapHead *getStackmap(Address instr) {
+        PropsHead_5 *pro = (PropsHead_5*)props.getInstrProps(instr);
+        assert(pro);
+        return pro->getStackmap();
+    }
 
-        //create stackmap for exception handler start
-        void createHandlerStackmap(Address handler_pc, SmConstant type) {
-            StackmapHead *map = getStackmap(handler_pc, 1);
-            //handler stackmaps are created before any dataflow analysis is done
-            assert(map->depth == 0 || map->depth == 1);
-            map->depth = 1;
+    /////////////// expect some type //////////////
 
-            vf_Result tcr = add_incoming_value(type, &map->elements[m_stack_start]);
+    //expect exactly this type
+    int workmap_expect_strict( WorkmapElement_5 &el, SmConstant type ) {
+        assert(type != SM_BOGUS);
 
-            // it is initialization stage
-            assert(tcr == VF_OK);
+        if( !el.isVariable() ) {
+            return type == el.getConst();
         }
 
-
-        //create a workmap vector for the given size sz (max_locals <= sz <= max_locals+max_stack)
-        PropsHead *newWorkmapProps(int sz) {
-            PropsHead * ret = (PropsHead*)mem.malloc(sizeof(PropsHead) + sizeof(WorkmapElement) * sz);
-            ret->set_as_workmap();
-            return ret;
-        }
-
-        //returns stackmap for the 'instr' instruction
-        //if it does not exists yet -- create it. When created use 'depth' as stack depth
-        StackmapHead *getStackmap(Address instr, int depth) {
-            PropsHead *pro = (PropsHead*) props.getInstrProps(instr);
-            if( !pro ) {
-                pro = newStackmap(m_stack_start + depth);
-                props.setInstrProps(instr, pro);
-                pro->getStackmap()->depth = depth;
+        IncomingType *in = el.getVariable()->firstIncoming();
+        while( in ) {
+            if( type != in->value ) {
+                return false;
             }
-            return pro->getStackmap();
+            in = in->next();
         }
 
-        //returns stackmap for the 'instr' instruction. it must exist
-        StackmapHead *getStackmap(Address instr) {
-            PropsHead *pro = (PropsHead*)props.getInstrProps(instr);
-            assert(pro);
-            return pro->getStackmap();
+        ExpectedType *exp = el.getVariable()->firstExpected();
+        while( exp ) {
+            if( type == exp->value ) {
+                return true;
+            }
+            exp = exp->next();
         }
 
-        /////////////// expect some type //////////////
+        el.getVariable()->newExpectedType(&mem, type);
 
-        //expect exactly this type
-        int workmap_expect_strict( WorkmapElement &el, SmConstant type ) {
-            assert(type != SM_BOGUS);
+        return true;
+    }
 
-            if( !el.isVariable() ) {
-                return type == el.getConst();
+    int workmap_expect( WorkmapElement_5 &el, SmConstant type ) {
+        if( !el.isVariable() ) {
+            return tpool.mustbe_assignable(el.getConst(), type);
+        } else {
+            ExpectedType* exp = el.getVariable()->firstExpected();
+            while( exp ) {
+                if( type == exp->value ) {
+                    return true;
+                }
+                exp = exp->next();
             }
 
             IncomingType *in = el.getVariable()->firstIncoming();
+            //check that all existing incoming type are assignable to the new expected type
             while( in ) {
-                if( type != in->value ) {
+                if( !tpool.mustbe_assignable(in->value, type) ) {
                     return false;
                 }
                 in = in->next();
             }
-
-            ExpectedType *exp = el.getVariable()->firstExpected();
-            while( exp ) {
-                if( type == exp->value ) {
-                    return true;
-                }
-                exp = exp->next();
-            }
-
+            //add the new expected type
             el.getVariable()->newExpectedType(&mem, type);
-
-            return true;
         }
+        return true;
+    }
 
-        int workmap_expect( WorkmapElement &el, SmConstant type ) {
-            if( !el.isVariable() ) {
-                return tpool.mustbe_assignable(el.getConst(), type);
-            } else {
-                ExpectedType* exp = el.getVariable()->firstExpected();
-                while( exp ) {
-                    if( type == exp->value ) {
-                        return true;
-                    }
-                    exp = exp->next();
-                }
-
-                IncomingType *in = el.getVariable()->firstIncoming();
-                //check that all existing incoming type are assignable to the new expected type
-                while( in ) {
-                    if( !tpool.mustbe_assignable(in->value, type) ) {
-                        return false;
-                    }
-                    in = in->next();
-                }
-                //add the new expected type
-                el.getVariable()->newExpectedType(&mem, type);
-            }
-            return true;
+    //create special type of conatraint: "'from' is an array and it's element is assignable to 'to'"
+    vf_Result new_scalar_array2ref_constraint(WorkmapElement_5 *from, WorkmapElement_5 *to) {
+        if( !from->isVariable() ) {
+            //although new_scalar_conatraint() whould process from constants correctly 
+            // we just do not need new variable if it is really a constant
+            *to = _WorkmapElement_5( tpool.get_ref_from_array(from->getConst()) );
+            return VF_OK;
         }
+        assert( from->isVariable() );
 
-        //create special type of conatraint: "'from' is an array and it's element is assignable to 'to'"
-        vf_Result new_scalar_array2ref_constraint(WorkmapElement *from, WorkmapElement *to) {
-            if( !from->isVariable() ) {
-                //although new_scalar_conatraint() whould process from constants correctly 
-                // we just do not need new variable if it is really a constant
-                *to = _WorkmapElement( tpool.get_ref_from_array(from->getConst()) );
-                return VF_OK;
-            }
-            assert( from->isVariable() );
-
-            ArrayCnstr* arr = from->getVariable()->firstArrayCnstr();
-            //at most one array conversion constraint per variable is possible
-            if( arr ) {
-                *to = _WorkmapElement(arr->variable);
-                return VF_OK;
-            }
-
-            *to = _WorkmapElement( new_variable() );
-
-            IncomingType *inc = from->getVariable()->firstIncoming();
-            from->getVariable()->newArrayConversionConstraint(&mem, to->getVariable());
-
-            while( inc ) {
-                SmConstant inc_val = tpool.get_ref_from_array(inc->value);
-                vf_Result vcr = add_incoming_value( inc_val, to->getVariable() );
-                if( vcr != VF_OK ) {
-                    return vcr;
-                }
-                inc = inc->next();
-            }
+        ArrayCnstr* arr = from->getVariable()->firstArrayCnstr();
+        //at most one array conversion constraint per variable is possible
+        if( arr ) {
+            *to = _WorkmapElement_5(arr->variable);
             return VF_OK;
         }
 
-        void new_bogus_propagation_constraint(WorkmapElement &wm_el, SmConstant init_val) {
-            if( !wm_el.isVariable() ) {
-                wm_el = _WorkmapElement (init_val);
-            } else {
-
-                WorkmapElement wm_init = _WorkmapElement (new_variable());
-                wm_init.var_ptr->newIncomingType(&mem, init_val);
-                wm_el.getVariable()->newGenericConstraint(&mem, wm_init.getVariable());
-                wm_el = wm_init;
-            }
-        }
-    };
+        *to = _WorkmapElement_5( new_variable() );
 
-} // namespace CPVerifier
+        IncomingType *inc = from->getVariable()->firstIncoming();
+        from->getVariable()->newArrayConversionConstraint(&mem, to->getVariable());
+
+        while( inc ) {
+            SmConstant inc_val = tpool.get_ref_from_array(inc->value);
+            vf_Result vcr = add_incoming_value( inc_val, to->getVariable() );
+            if( vcr != VF_OK ) {
+                return vcr;
+            }
+            inc = inc->next();
+        }
+        return VF_OK;
+    }
+
+    void new_bogus_propagation_constraint(WorkmapElement_5 &wm_el, SmConstant init_val) {
+        if( !wm_el.isVariable() ) {
+            wm_el = _WorkmapElement_5 (init_val);
+        } else {
+
+            WorkmapElement_5 wm_init = _WorkmapElement_5 (new_variable());
+            wm_init.var_ptr->newIncomingType(&mem, init_val);
+            wm_el.getVariable()->newGenericConstraint(&mem, wm_init.getVariable());
+            wm_el = wm_init;
+        }
+    }
+};
 
 #endif

Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/java5/instr_props_5.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/java5/instr_props_5.h?rev=649574&r1=649573&r2=649574&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/java5/instr_props_5.h (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/java5/instr_props_5.h Fri Apr 18 08:29:36 2008
@@ -14,130 +14,120 @@
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  */
-/** 
- * @author Mikhail Loenko, Vladimir Molotkov
- */  
-
 #ifndef __INSTR_PROPS5_H_
 #define __INSTR_PROPS5_H_
 
 #include <assert.h>
 #include "../base/stackmap.h"
 
-using namespace CPVerifier;
-
-namespace CPVerifier_5 {
-
-    //store flags and properties (stackmaps, workmaps, etc) for each instruction
-    class InstrProps : public InstrPropsBase {
-    private:
-        //array of bit flags
-        uint8* packed_flags;
-
-        //returns flags for the instruction 'instr'. other bits are not necessary 0s
-        int get_dirty_mask(Address instr) {
-            int b = packed_flags[instr/4];
-            b = b >> ((instr % 4) * 2);
-            return b;
-        }
-
-        //bit OR flags for the instruction 'instr' with 'mask'
-        void fill_mask(Address instr, int mask) {
-            assert((mask & ~3) == 0);
-            mask = mask << ((instr % 4) * 2);
-
-            packed_flags[instr/4] |= mask;
-        }
-
-        //clears bits the are set in the 'mask' (& ~mask) for the instruction 'instr'
-        void clear_mask(Address instr, int mask) {
-            assert((mask & ~3) == 0);
-            mask = mask << (instr % 4) * 2;
-
-            packed_flags[instr/4] &= ~mask;
-        }
-
-    public:
-        //initializes the class. this function is invoked once per method - removes old data in initializes storages.
-        void init(Memory &mem, int code_len) {
-            InstrPropsBase::init(mem, code_len);
-            packed_flags = (uint8*)mem.calloc( ((code_len/4) & ~3) + 4);
-        }
-
-        //pass1: 00 - new (or dead code), 01 - parsed, 10 - middle of instruction, 11 - 'special' parsed (special == has stackmap)
-        //returns 1 if mask is 01 (parsed) or 11 ('special' parsed  special == has stackmap)
-        int isParsePassed(Address instr) {
-            return get_dirty_mask(instr) & 1;
-        }
-
-        //pass1: 00 - new (or dead code), 01 - parsed, 10 - middle of instruction, 11 - 'special' parsed (special == has stackmap)
-        //returns 1 if mask is 10 (middle of instruction)
-        int isOperand(Address instr) {
-            return (get_dirty_mask(instr) & 3) == 2;
-        }
-
-        //pass1: 00 - new (or dead code), 01 - parsed, 10 - middle of instruction, 11 - 'special' parsed (special == has stackmap)
-        //setls low mask bit to 1
-        void setParsePassed(Address instr) {
-            fill_mask(instr, 1);
-        }
-
-        //pass1: 00 - new (or dead code), 01 - parsed, 10 - middle of instruction, 11 - 'special' parsed (special == has stackmap)
-        //sets mask to 10
-        int setOperand(Address instr) {
-            int idx = instr/4;
-            int shift = ((instr % 4) * 2);
-
-            int mask01 = 1 << shift;
-            int mask10 = 2 << shift;
-
-            //is an instruction
-            if( packed_flags[idx] & mask01 ) return 0;
-
-            //mark as a middle
-            packed_flags[idx] |= mask10;
-            return 1;
-        }
-
-        //pass1: 00 - new (or dead code), 01 - parsed, 10 - middle of instruction, 11 - 'special' parsed (special == has stackmap)
-        //when we calculate stackmaps, we set lower bit to 1 after the first pass
-        //set mask to 11
-        void setMultiway(Address instr) {
-            fill_mask(instr, 3);
-        }
-
-        //pass2: 01 - new, 11 - special, 00 - passed (or unused), 10 - special passed (or unused)
-        //when we calculate stackmaps: 01 - beginning of new or dead, 11 - special or middle, 00 passed, 10 special passed
-        //for all instructions (except unuzed) returns 1 if it's 'passed' or 'special passed'
-        //return 0 otherwise
-        int isDataflowPassed(Address instr) {
-            return !(get_dirty_mask(instr) & 1);
-        }
-
-        //return 1 for special and special passed instructions (instructions that are achievable by multiple passes)
-        int isMultiway(Address instr) { //II_MULTIWAY
-            return get_dirty_mask(instr) & 2;
-        }
-
-        //mark instruction as passed
-        void setDataflowPassed(Address instr) {
-            clear_mask(instr, 1);
-        }
-
-        void pass2started(int stackmapattr_calculation, Address code_length) {
-            //touch dead and middles so that we can distinguish between two times passed and dead 
-            if( stackmapattr_calculation ) {
-                for( Address instr = 0; instr < code_length; instr++ ) {
-                    fill_mask(instr, 1);
-                }
+//store flags and properties (stackmaps, workmaps, etc) for each instruction
+class InstrProps : public InstrPropsBase {
+private:
+    //array of bit flags
+    uint8* packed_flags;
+
+    //returns flags for the instruction 'instr'. other bits are not necessary 0s
+    int get_dirty_mask(Address instr) {
+        int b = packed_flags[instr/4];
+        b = b >> ((instr % 4) * 2);
+        return b;
+    }
+
+    //bit OR flags for the instruction 'instr' with 'mask'
+    void fill_mask(Address instr, int mask) {
+        assert((mask & ~3) == 0);
+        mask = mask << ((instr % 4) * 2);
+
+        packed_flags[instr/4] |= mask;
+    }
+
+    //clears bits the are set in the 'mask' (& ~mask) for the instruction 'instr'
+    void clear_mask(Address instr, int mask) {
+        assert((mask & ~3) == 0);
+        mask = mask << (instr % 4) * 2;
+
+        packed_flags[instr/4] &= ~mask;
+    }
+
+public:
+    //initializes the class. this function is invoked once per method - removes old data in initializes storages.
+    void init(Memory &mem, int code_len) {
+        InstrPropsBase::init(mem, code_len);
+        packed_flags = (uint8*)mem.calloc( ((code_len/4) & ~3) + 4);
+    }
+
+    //pass1: 00 - new (or dead code), 01 - parsed, 10 - middle of instruction, 11 - 'special' parsed (special == has stackmap)
+    //returns 1 if mask is 01 (parsed) or 11 ('special' parsed  special == has stackmap)
+    int isParsePassed(Address instr) {
+        return get_dirty_mask(instr) & 1;
+    }
+
+    //pass1: 00 - new (or dead code), 01 - parsed, 10 - middle of instruction, 11 - 'special' parsed (special == has stackmap)
+    //returns 1 if mask is 10 (middle of instruction)
+    int isOperand(Address instr) {
+        return (get_dirty_mask(instr) & 3) == 2;
+    }
+
+    //pass1: 00 - new (or dead code), 01 - parsed, 10 - middle of instruction, 11 - 'special' parsed (special == has stackmap)
+    //setls low mask bit to 1
+    void setParsePassed(Address instr) {
+        fill_mask(instr, 1);
+    }
+
+    //pass1: 00 - new (or dead code), 01 - parsed, 10 - middle of instruction, 11 - 'special' parsed (special == has stackmap)
+    //sets mask to 10
+    int setOperand(Address instr) {
+        int idx = instr/4;
+        int shift = ((instr % 4) * 2);
+
+        int mask01 = 1 << shift;
+        int mask10 = 2 << shift;
+
+        //is an instruction
+        if( packed_flags[idx] & mask01 ) return 0;
+
+        //mark as a middle
+        packed_flags[idx] |= mask10;
+        return 1;
+    }
+
+    //pass1: 00 - new (or dead code), 01 - parsed, 10 - middle of instruction, 11 - 'special' parsed (special == has stackmap)
+    //when we calculate stackmaps, we set lower bit to 1 after the first pass
+    //set mask to 11
+    void setMultiway(Address instr) {
+        fill_mask(instr, 3);
+    }
+
+    //pass2: 01 - new, 11 - special, 00 - passed (or unused), 10 - special passed (or unused)
+    //when we calculate stackmaps: 01 - beginning of new or dead, 11 - special or middle, 00 passed, 10 special passed
+    //for all instructions (except unuzed) returns 1 if it's 'passed' or 'special passed'
+    //return 0 otherwise
+    int isDataflowPassed(Address instr) {
+        return !(get_dirty_mask(instr) & 1);
+    }
+
+    //return 1 for special and special passed instructions (instructions that are achievable by multiple passes)
+    int isMultiway(Address instr) { //II_MULTIWAY
+        return get_dirty_mask(instr) & 2;
+    }
+
+    //mark instruction as passed
+    void setDataflowPassed(Address instr) {
+        clear_mask(instr, 1);
+    }
+
+    void pass2started(int stackmapattr_calculation, Address code_length) {
+        //touch dead and middles so that we can distinguish between two times passed and dead 
+        if( stackmapattr_calculation ) {
+            for( Address instr = 0; instr < code_length; instr++ ) {
+                fill_mask(instr, 1);
             }
         }
+    }
 
-        int isDeadCodeStart(Address instr) { //dead block begins with 01, middles are 11, ends with 10 or 00
-            return (get_dirty_mask(instr) & 3) == 1;
-        }
-    };
-} // namespace CPVerifier
-
+    int isDeadCodeStart(Address instr) { //dead block begins with 01, middles are 11, ends with 10 or 00
+        return (get_dirty_mask(instr) & 3) == 1;
+    }
+};
 
 #endif



Mime
View raw message