You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by gs...@apache.org on 2007/02/16 19:02:39 UTC

svn commit: r508525 [4/5] - in /harmony/enhanced/drlvm/trunk: build/custom/msvc_2003/vmcore/ vm/vmcore/src/verifier/

Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier/ver_dataflow.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier/ver_dataflow.cpp?view=diff&rev=508525&r1=508524&r2=508525
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier/ver_dataflow.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier/ver_dataflow.cpp Fri Feb 16 10:02:37 2007
@@ -20,6 +20,7 @@
  */  
 
 #include "ver_real.h"
+#include "ver_graph.h"
 
 /**
  * Debug flag macros
@@ -29,11 +30,6 @@
 // Macro prints data flow node instruction vectors
 #define DUMP_NODE_INSTR_VECTOR 0
 
-/**
- * Set namespace Verifier
- */
-namespace Verifier {
-
 /************************************************************
  **************** Graph Data Flow Analysis ******************
  ************************************************************/
@@ -96,7 +92,7 @@
  * Function prints data flow vector into output stream.
  */
 void
-vf_dump_vector( vf_MapVector_t *vector,     // data flow vector
+vf_dump_vector( vf_MapVectorHandle vector,     // data flow vector
                 vf_Code_t *code,            // code instruction
                 ostream *stream)            // output stream (can be NULL)
 {
@@ -152,7 +148,7 @@
     }
     // dump stack vector
     *stream << "S:";
-    for( index = 0; index < vector->m_deep; index++ ) {
+    for( index = 0; index < vector->m_depth; index++ ) {
         vf_dump_vector_entry( &vector->m_stack[index], stream );
         if( vector->m_stack[index].m_is_local ) {
             *stream << "!";
@@ -162,7 +158,7 @@
     }
     *stream << endl;
     // dump stack references
-    for( index = 0; index < vector->m_deep; index++ ) {
+    for( index = 0; index < vector->m_depth; index++ ) {
         if( vector->m_stack[index].m_type == SM_REF ) {
             *stream << " REF #" << index << ": ";
         } else if( vector->m_stack[index].m_type == SM_UNINITIALIZED ) {
@@ -216,10 +212,10 @@
  * If first vector was changed, returns true, else - false.
  */
 static inline bool
-vf_merge_vectors( vf_MapVector_t *first,    // first vector
-                  vf_MapVector_t *second,   // second vector
-                  bool handler_flag,        // if merged node is handler
-                  vf_Context_t *ctex)       // verifier context
+vf_merge_vectors( vf_MapVector* first,          // first vector
+                  vf_MapVectorHandle second,    // second vector
+                  bool handler_flag,            // if merged node is handler
+                  vf_Context_t *ctex)           // verifier context
 {
     bool is_changed = false;
     vf_MapEntry_t zero = {0};
@@ -288,8 +284,8 @@
     }
 
     // merge stack map vector
-    assert( first->m_deep == second->m_deep );
-    for( index = 0; index < second->m_deep; index++ ) {
+    assert( first->m_depth == second->m_depth );
+    for( index = 0; index < second->m_depth; index++ ) {
         // merge entries type
         if( first->m_stack[index].m_type == SM_TOP ) {
             // no need to merge
@@ -327,8 +323,8 @@
  * Function copies source vector to data vector.
  */
 static inline void
-vf_copy_vector( vf_MapVector_t *source,     // copied vector
-                vf_MapVector_t *data)       // data vector
+vf_copy_vector( vf_MapVectorHandle source,     // copied vector
+                vf_MapVector* data)            // data vector
 {
     unsigned index;
     vf_MapEntry_t zero = {0};
@@ -344,8 +340,8 @@
         data->m_local[index] = zero;
     }
     // copy stack
-    data->m_deep = source->m_deep;
-    for( index = 0; index < source->m_deep; index++ ) {
+    data->m_depth = source->m_depth;
+    for( index = 0; index < source->m_depth; index++ ) {
         data->m_stack[index] = source->m_stack[index];
     }
     for( ; index < data->m_maxstack; index++ ) {
@@ -358,14 +354,14 @@
  * Function compares two vectors.
  */
 static inline bool
-vf_compare_vectors( vf_MapVector_t *first,      // first vector
-                    vf_MapVector_t *second)     // second vector
+vf_compare_vectors( vf_MapVectorHandle first,      // first vector
+                    vf_MapVectorHandle second)     // second vector
 {
     // compare vector parameters
     if( first->m_maxlocal != second->m_maxlocal
         || first->m_maxstack != second->m_maxstack
         || first->m_number != second->m_number
-        || first->m_deep != second->m_deep )
+        || first->m_depth != second->m_depth )
     {
         return false;
     }
@@ -383,7 +379,7 @@
         }
     }
     // compare stack
-    for( index = 0; index < first->m_deep; index++ ) {
+    for( index = 0; index < first->m_depth; index++ ) {
         if( first->m_stack[index].m_type != second->m_stack[index].m_type
             || first->m_stack[index].m_vtype != second->m_stack[index].m_vtype ) 
         {
@@ -397,9 +393,9 @@
  * Function check access constraint for two stack map references.
  */
 static inline Verifier_Result
-vf_check_access(vf_MapEntry_t *source,    // stack map entry
-                vf_MapEntry_t *target,    // required map entry
-                vf_Context_t *ctex)       // verifier context
+vf_check_access( vf_MapEntry_t *source,    // stack map entry
+                 vf_MapEntry_t *target,    // required map entry
+                 vf_Context_t *ctex)       // verifier context
 {
     // compare types
     assert( target->m_vtype->number == 1 );
@@ -475,10 +471,7 @@
             //    can be stored in a local variable if backward branch is
             //    taken or the code is protected by exception handler.
         } else {
-            VERIFY_REPORT( ctex, "(class: " << class_get_name( ctex->m_class ) 
-                << ", method: " << method_get_name( ctex->m_method )
-                << method_get_descriptor( ctex->m_method )
-                << ") Uninitialized reference usage" );
+            VERIFY_REPORT_METHOD( ctex, "Uninitialized reference usage" );
             return VER_ErrorDataFlow;
         }
     }
@@ -721,15 +714,15 @@
  * Function clears stack map vector.
  */
 static inline void
-vf_clear_stack( vf_MapVector_t *vector )    // map vector
+vf_clear_stack( vf_MapVector* vector )    // map vector
 {
     vf_MapEntry_t zero_entry = {0};
 
     // zero stack vector
-    for( unsigned index = 0; index < vector->m_deep; index++ ) {
+    for( unsigned index = 0; index < vector->m_depth; index++ ) {
         vector->m_stack[index] = zero_entry;
     }
-    vector->m_deep = 0;
+    vector->m_depth = 0;
 
     return;
 } // vf_clear_stack
@@ -810,10 +803,8 @@
             // check entry types
             result = vf_check_entry_refs( entry, newvector, local_init, ctex );
             if( result != VER_OK ) {
-                VERIFY_REPORT( ctex, "(class: " << class_get_name( ctex->m_class )
-                    << ", method: " << method_get_name( ctex->m_method )
-                    << method_get_descriptor( ctex->m_method )
-                    << ") Incompatible types for array assignment" );
+                VERIFY_REPORT_METHOD( ctex, 
+                    "Incompatible types for array assignment" );
                 return result;
             }
             break;
@@ -822,10 +813,7 @@
             result = vf_check_entry_refs( entry, vector, local_init, ctex );
             if( result != VER_OK ) {
                 if( !ctex->m_error ) {
-                    VERIFY_REPORT( ctex, "(class: " << class_get_name( ctex->m_class ) 
-                        << ", method: " << method_get_name( ctex->m_method )
-                        << method_get_descriptor( ctex->m_method )
-                        << ") Data flow analysis error" );
+                    VERIFY_REPORT_METHOD( ctex, "Data flow analysis error" );
                 }
                 return result;
             }
@@ -835,18 +823,14 @@
             // check entry references
             if( entry->m_type == SM_REF ) {
                 // double initialization
-                VERIFY_REPORT( ctex, "(class: " << class_get_name( ctex->m_class ) 
-                    << ", method: " << method_get_name( ctex->m_method )
-                    << method_get_descriptor( ctex->m_method )
-                    << ") Double initialization of object reference" );
+                VERIFY_REPORT_METHOD( ctex, 
+                    "Double initialization of object reference" );
                 return VER_ErrorDataFlow;
             }
             result = vf_check_entry_refs( entry, vector, local_init, ctex );
             if( result != VER_OK ) {
-                VERIFY_REPORT( ctex, "(class: " << class_get_name( ctex->m_class ) 
-                    << ", method: " << method_get_name( ctex->m_method )
-                    << method_get_descriptor( ctex->m_method )
-                    << ") Data flow analysis error (uninitialized)" );
+                VERIFY_REPORT_METHOD( ctex, 
+                    "Data flow analysis error (uninitialized)" );
                 return result;
             }
             // check initialization class in constructor
@@ -865,10 +849,7 @@
             // check entry types
             result = vf_check_entry_types( entry, vector, local_init, &copy, ctex );
             if( result != VER_OK ) {
-                VERIFY_REPORT( ctex, "(class: " << class_get_name( ctex->m_class ) 
-                    << ", method: " << method_get_name( ctex->m_method )
-                    << method_get_descriptor( ctex->m_method )
-                    << ") Data flow analysis error" );
+                VERIFY_REPORT_METHOD( ctex, "Data flow analysis error" );
                 return result;
             }
         }
@@ -888,7 +869,7 @@
 static Verifier_Result
 vf_get_instruction_out_vector( unsigned node_num,           // graph node
                                vf_Code_t *instr,            // code instruction
-                               vf_MapVector_t *invector,    // incoming data flow vector
+                               vf_MapVector* invector,      // incoming data flow vector
                                vf_MapEntry_t *buf,          // buf storage vector
                                vf_Context_t *ctex)          // verifier context
 {
@@ -897,31 +878,30 @@
     vf_MapEntry_t zero_entry = {0};
 
     // set stack vector
-    assert( invector->m_deep - instr->m_minstack >= 0 );
-    vf_MapEntry_t *stack = invector->m_stack + invector->m_deep - instr->m_minstack;
+    assert( invector->m_depth - instr->m_minstack >= 0 );
+    vf_MapEntry_t *stack = invector->m_stack + invector->m_depth - instr->m_minstack;
     // set locals vector
     vf_MapEntry_t *locals = invector->m_local;
     // check instruction in vector
     Verifier_Result result = vf_check_instruction_in_vector( stack, locals, buf,
-        instr->m_invector, instr->m_inlen, ctex->m_graph->GetNodeInitFlag(node_num),
+        instr->m_invector, instr->m_inlen, ctex->m_graph->GetNodeInitFlag( node_num ),
         &need_init, ctex );
     if( result != VER_OK ) {
         return result;
     }
 
     // create out vector for return instructions
-    if( vf_is_instruction_has_flags( instr, VF_FLAG_RETURN ) ) {
+    if( VF_TYPE_INSTR_RETURN == instr->m_type ) {
         // clear stack
-        unsigned deep = invector->m_deep;
+        unsigned deep = invector->m_depth;
         vf_clear_stack( invector );
         // set result vector stack deep
-        invector->m_deep = (unsigned short)(deep + instr->m_stack);
+        invector->m_depth = (unsigned short)(deep + instr->m_stack);
         // set out vector
         vf_set_return_out_vector( invector->m_stack, buf, instr->m_invector,
                                   instr->m_inlen, ctex );
         return VER_OK;
-    } else if( vf_is_instruction_has_flags( instr, VF_FLAG_THROW ) ) {
-        // set result vector stack deep
+    } else if( VF_TYPE_INSTR_THROW == instr->m_type ) {
         invector->m_stack->m_type = SM_TERMINATE;
         return VER_OK;
     }
@@ -944,7 +924,7 @@
             }
         }
         // init stack reference
-        for( index = 0; index < (unsigned)invector->m_deep - instr->m_minstack; index++ ) {
+        for( index = 0; index < (unsigned)invector->m_depth - instr->m_minstack; index++ ) {
             if( invector->m_stack[index].m_type == SM_UNINITIALIZED
                 && invector->m_stack[index].m_new == buf[0].m_new )
             {
@@ -955,8 +935,8 @@
     }
 
     // set instruction OUT vector
-    invector->m_deep = (unsigned short )(invector->m_deep + instr->m_stack);
-    assert( invector->m_deep <= invector->m_maxstack );
+    invector->m_depth = (unsigned short )(invector->m_depth + instr->m_stack);
+    assert( invector->m_depth <= invector->m_maxstack );
     index = invector->m_number;
     vf_set_instruction_out_vector( instr, stack, locals, &invector->m_number, buf, ctex );
     assert( invector->m_number <= invector->m_maxlocal );
@@ -972,19 +952,25 @@
 } // vf_get_instruction_out_vector
 
 /**
- * Function receives handler OUT data flow vector.
+ * Copies a stored handler vector to the out vector.
  */
 static inline Verifier_Result
-vf_get_handler_out_vector( vf_Code_t *instr,            // handler code instruction
-                           vf_MapVector_t *invector)    // incoming data flow vector
+vf_get_handler_out_vector( vf_MapVector* invector,            // IN handler vector
+                           vf_MapVectorHandle handler_vector) // stored handler vector
 {
+    assert( 0 == invector->m_depth );
+    assert( 1 == handler_vector->m_depth );
+    assert( SM_REF == handler_vector->m_stack->m_type );
+
+    // clear stack for exception handler
+    vf_clear_stack( invector );
+
     // set handler out vector
-    assert( invector->m_deep == 0 );
-    assert( instr->m_outlen == 1 );
-    invector->m_stack->m_type = instr->m_outvector->m_type;
-    invector->m_stack->m_vtype = instr->m_outvector->m_vtype;
+    invector->m_stack->m_type = handler_vector->m_stack->m_type;
+    invector->m_stack->m_vtype = handler_vector->m_stack->m_vtype;
+
     // set modify vector value
-    invector->m_deep++;
+    invector->m_depth = 1;
     return VER_OK;
 } // vf_get_handler_out_vector
 
@@ -993,59 +979,56 @@
  */
 static Verifier_Result
 vf_set_node_out_vector( unsigned node_num,          // graph node number
-                        vf_MapVector_t *invector,   // incoming data flow vector
+                        vf_MapVector* invector,     // incoming data flow vector
                         vf_MapEntry_t *buf,         // buf stack map vector
                         vf_Context_t *ctex)         // verifier context
 {
-    unsigned index,
-             instruction;
-    vf_Code_t *instr;
     Verifier_Result result;
 
     // get node instruction number
-    vf_Graph_t *graph = ctex->m_graph;
-    instruction = graph->GetNodeLastInstr( node_num ) 
-        - graph->GetNodeFirstInstr( node_num ) + 1;
-    // get first instruction
-    instr = &ctex->m_code[graph->GetNodeFirstInstr( node_num )];
+    vf_Graph* graph = ctex->m_graph;
+    vf_NodeHandle node = graph->GetNode( node_num );
 
     /** 
      * For start-entry node doesn't need to check data flow
      */
-    if( vf_is_instruction_has_flags( instr, VF_FLAG_START_ENTRY ) ) {
-        assert( instruction == 1 );
+    if (VF_TYPE_NODE_START_ENTRY == node->m_type) {
         return VER_OK;
-    } else if( vf_is_instruction_has_flags( instr, VF_FLAG_HANDLER ) ) {
-        assert( instruction == 1 );
-        // set out vector for handler node
-        result = vf_get_handler_out_vector( instr, invector );
+    }
+
+    if (VF_TYPE_NODE_HANDLER == node->m_type) {
+        // set OUT vector for a handler node
+        return vf_get_handler_out_vector( invector, &node->m_outMapVector );
+    }
+
+    // get first instruction
+    vf_Code_t* instr = &ctex->m_code[graph->GetNodeFirstInstr( node_num )];
+    unsigned instruction = graph->GetNodeLastInstr( node_num ) 
+        - graph->GetNodeFirstInstr( node_num ) + 1;
+
+    // set out vector for each instruction
+    for( unsigned index = 0; index < instruction; index++ )
+    {
+        if( ( 0 == instr[index].m_inlen + instr[index].m_outlen )
+            && ( VF_TYPE_INSTR_NONE == instr->m_type ) )
+        {
+            continue;
+        } else {
+            result = vf_get_instruction_out_vector( node_num, &instr[index],
+                invector, buf, ctex );
+        }
         if( result != VER_OK ) {
             return result;
         }
-    } else {
-        // set out vector for each instruction
-        for( index = 0; index < instruction; index++ ) {
-            if( instr[index].m_inlen + instr[index].m_outlen == 0 
-                && !vf_is_instruction_has_any_flags( instr ) )
-            {
-                continue;
-            } else {
-                result = vf_get_instruction_out_vector( node_num, &instr[index], invector, 
-                    buf, ctex );
-            }
-            if( result != VER_OK ) {
-                return result;
-            }
 #if _VERIFY_DEBUG
-            if( ctex->m_dump.m_code_vector ) {
-                // dump instruction OUT vector
-                cerr << "-------------- instruction #" << index << " out: " << endl;
-                vf_dump_vector( invector, &instr[index], &cerr );
-            }
-#endif // _VERIFY_DEBUG
+        if( ctex->m_dump.m_code_vector )
+        {
+            // dump instruction OUT vector
+            cerr << "-------------- instruction #" << index << " out: " << endl;
+            vf_dump_vector( invector, &instr[index], &cerr );
         }
+#endif // _VERIFY_DEBUG
     }
-
     return VER_OK;
 } // vf_set_node_out_vector
 
@@ -1054,13 +1037,13 @@
  */
 static Verifier_Result
 vf_create_node_vectors( unsigned node_num,          // graph node number
-                        vf_MapVector_t *incoming,   // vector for instruction data flow change
+                        vf_MapVector* incoming,     // vector for instruction data flow change
                         vf_MapEntry_t *buf,         // buf stack map vector
                         bool *is_out_changed,       // pointer to OUT vector change flag
                         vf_Context_t *ctex)         // verifier context
 {
     // copy IN vector to buf
-    vf_Graph_t *graph = ctex->m_graph;
+    vf_Graph* graph = ctex->m_graph;
     vf_copy_vector( graph->GetNodeInVector( node_num ), incoming );
 
 #if _VERIFY_DEBUG
@@ -1082,12 +1065,12 @@
     }
 
     // set node OUT vector
-    vf_MapVector_t *outcoming = graph->GetNodeOutVector( node_num );
+    vf_MapVector* outcoming = (vf_MapVector*) graph->GetNodeOutVector( node_num );
     if( !outcoming->m_maxlocal || !outcoming->m_maxstack )
     {
         // create node OUT vector
         graph->SetNodeOutVector( node_num, incoming, true );
-        outcoming = graph->GetNodeOutVector( node_num );
+        outcoming = (vf_MapVector*) graph->GetNodeOutVector( node_num );
         *is_out_changed = true;
     } else if( !vf_compare_vectors( outcoming, incoming ) ) {
         // vectors are differ
@@ -1104,32 +1087,27 @@
 #endif // _VERIFY_DEBUG
 
     // check stack modifier
-    assert( (int)((graph->GetNodeOutVector( node_num )->m_deep
-        - graph->GetNodeInVector( node_num )->m_deep))
+    assert( (int)((graph->GetNodeOutVector( node_num )->m_depth
+        - graph->GetNodeInVector( node_num )->m_depth))
         == graph->GetNodeStackModifier( node_num ) );
 
     return VER_OK;
 } // vf_create_node_vectors
 
 /**
- * Function checks data flow for end graph node.
+ * Checks data flow for an end graph node.
  */
 static Verifier_Result
-vf_check_end_node_data_flow( unsigned node_num,         // graph node number
-                             vf_MapVector_t *invector,  // end node incoming data flow vector
-                             vf_Context_t *ctex)        // verifier context
+vf_check_end_node_data_flow( vf_MapVectorHandle invector,  // end node incoming data flow vector
+                             vf_Context_t *ctex)           // verifier context
 {
-    bool copy;
-    unsigned index;
-    vf_MapEntry_t *vector;
-
     // don't need check
     if( invector->m_stack && invector->m_stack->m_type == SM_TERMINATE ) {
         return VER_OK;
     }
 
     // check <init> method
-    if( !memcmp( method_get_name( ctex->m_method ), "<init>", 7 )
+    if( ctex->m_is_constructor
         && ctex->m_vtype.m_class != ctex->m_vtype.m_object )
     {
         if( invector->m_local->m_type != SM_UNINITIALIZED
@@ -1137,19 +1115,16 @@
         {
             // constructor returns initialized reference of a given class
         } else {
-            VERIFY_REPORT( ctex, "(class: " << class_get_name( ctex->m_class ) 
-                << ", method: " << method_get_name( ctex->m_method )
-                << method_get_descriptor( ctex->m_method )
-                << ") Constructor must be invoked" );
+            VERIFY_REPORT_METHOD( ctex, "Constructor must be invoked" );
             return VER_ErrorDataFlow;
         }
     }
 
-    // get first instruction
-    vf_Code_t *instr = &ctex->m_code[ctex->m_graph->GetNodeFirstInstr( node_num )];
+    // get the end entry
+    vf_NodeHandle node = ctex->m_graph->GetNode( ctex->m_nodeNum - 1 );
 
     // check void return
-    if( !instr->m_inlen ) {
+    if( 0 == node->m_inMapVector.m_depth ) {
         if( invector->m_stack ) {
             if( invector->m_stack->m_type == SM_TOP ) {
                 // no return value, empty stack - all is ok
@@ -1159,32 +1134,32 @@
             // no stack, no return value - all is ok
             return VER_OK;
         }
-        VERIFY_REPORT( ctex, "(class: " << class_get_name( ctex->m_class ) 
-            << ", method: " << method_get_name( ctex->m_method )
-            << method_get_descriptor( ctex->m_method )
-            << ") Wrong return type in function" );
+        VERIFY_REPORT_METHOD( ctex, "Wrong return type in function" );
         return VER_ErrorDataFlow;
     }
-    assert( invector->m_deep - instr->m_minstack >= 0 );
+    // stack size should be greater or equal than a minimal
+    // stack size which is a number of words to return (0, 1 or 2)
+    assert( invector->m_depth - node->m_inMapVector.m_depth >= 0 );
 
     /**
      * Check end-entry IN vector
      */
-    for( index = 0, vector = &instr->m_invector[0];
-         index < instr->m_inlen;
-         index++, vector = &instr->m_invector[index] )
+    for( unsigned index = 0;
+         index < node->m_inMapVector.m_depth;
+         index++ )
     {
         // get check entry
+        vf_MapEntry_t* vector = node->m_inMapVector.m_stack + index;
         assert( vector->m_is_local == 0 );
+
         // check stack type
         vf_MapEntry_t *entry = invector->m_stack + index;
+
         // check entry types
+        bool copy;
         Verifier_Result result = vf_check_entry_types( entry, vector, true, &copy, ctex );
         if( result != VER_OK ) {
-            VERIFY_REPORT( ctex, "(class: " << class_get_name( ctex->m_class ) 
-                << ", method: " << method_get_name( ctex->m_method )
-                << method_get_descriptor( ctex->m_method )
-                << ") Wrong return type in function" );
+            VERIFY_REPORT_METHOD( ctex, "Wrong return type in function" );
             return result;
         }
     }
@@ -1196,18 +1171,18 @@
  */
 static Verifier_Result
 vf_check_node_data_flow( unsigned node_num,             // graph node number
-                         vf_MapVector_t *incoming,      // incoming data flow vector
+                         vf_MapVector* incoming,        // incoming data flow vector
                          vf_MapEntry_t *buf,            // buf stack map vector
                          unsigned *node_count,          // last graph node in recursion
                          bool *need_recheck,            // set to true if need to recheck previous nodes
                          vf_Context_t *ctex)            // verifier context
 {
     // get graph
-    vf_Graph_t *graph = ctex->m_graph;
+    vf_Graph* graph = ctex->m_graph;
 
     // skip end-entry node
-    if( vf_is_instruction_has_flags( &ctex->m_code[graph->GetNodeFirstInstr( node_num )],
-            VF_FLAG_END_ENTRY) )
+    vf_NodeHandle node = graph->GetNode( node_num );
+    if( VF_TYPE_NODE_END_ENTRY == node->m_type )
     {
         return VER_OK;
     }
@@ -1233,7 +1208,7 @@
     }
 
     // set incoming vector for following nodes
-    vf_MapVector_t *in_node_vector = graph->GetNodeOutVector( node_num );
+    vf_MapVectorHandle in_node_vector = graph->GetNodeOutVector( node_num );
     for( unsigned out_edge = graph->GetNodeFirstOutEdge( node_num );
          out_edge;
          out_edge = graph->GetEdgeNextOutEdge( out_edge ) )
@@ -1242,12 +1217,10 @@
         unsigned out_node = graph->GetEdgeEndNode( out_edge );
 
         // check vectors for end-entry
-        if( vf_is_instruction_has_flags( 
-            &ctex->m_code[graph->GetNodeFirstInstr( out_node )],
-            VF_FLAG_END_ENTRY) )
+        if( VF_TYPE_NODE_END_ENTRY == graph->GetNode( out_node )->m_type )
         {
-            Verifier_Result result = vf_check_end_node_data_flow( out_node,
-                                        in_node_vector, ctex );
+            Verifier_Result result = 
+                vf_check_end_node_data_flow( in_node_vector, ctex );
             if( result != VER_OK ) {
                 return result;
             }
@@ -1255,13 +1228,12 @@
         }
 
         // get out node IN vector
-        vf_MapVector_t *out_node_vector = graph->GetNodeInVector( out_node );
+        vf_MapVector* out_node_vector = (vf_MapVector*)
+            graph->GetNodeInVector( out_node );
         if( !out_node_vector->m_maxlocal || !out_node_vector->m_maxstack )
         {
             // node's IN vector is invalid, set it
-            if( vf_is_instruction_has_flags( 
-                    &ctex->m_code[graph->GetNodeFirstInstr( out_node )],
-                    VF_FLAG_HANDLER) )
+            if( VF_TYPE_NODE_HANDLER == graph->GetNode( out_node )->m_type )
             {
                 // it's exception node, create IN vector for it
                 vf_copy_vector( in_node_vector, incoming );
@@ -1279,9 +1251,7 @@
             }
 #endif // _VERIFY_DEBUG
             // node's IN vector is valid, merge them
-            bool is_handler = vf_is_instruction_has_flags( 
-                    &ctex->m_code[graph->GetNodeFirstInstr( out_node )],
-                    VF_FLAG_HANDLER);
+            bool is_handler = VF_TYPE_NODE_HANDLER == graph->GetNode( out_node )->m_type;
             is_changed = vf_merge_vectors( out_node_vector, in_node_vector, is_handler, ctex );
             if( is_changed ) {
                 // node IN vector is changed, reset node OUT vector results
@@ -1316,57 +1286,64 @@
 } // vf_check_node_data_flow
 
 /**
- * Function creates initial data flow vector for method.
+ * Creates input and output stack maps.
  */
-static vf_MapVector_t*
-vf_create_method_begin_vector( vf_Context_t *ctex )     // verifier context
+static vf_MapVectorHandle
+vf_create_terminal_maps( vf_Context_t *ctex )     // verifier context
 {
-    int index,
-        count,
-        inlen,
-        begin,
-        outlen;
-    unsigned locals,
-             maxstack;
-    vf_MapEntry_t *invector,
-                  *outvector;
-    vf_MapVector_t *vector;
+    vf_MapEntry_t  *invector;
 
     // get method values
-    locals = method_get_max_local( ctex->m_method );
-    maxstack = method_get_max_stack( ctex->m_method );
+    unsigned locals = method_get_max_local( ctex->m_method );
+    unsigned maxstack = method_get_max_stack( ctex->m_method );
 
     // alloc memory for vector structure
-    vector = (vf_MapVector_t*)ctex->m_graph->AllocMemory( sizeof(vf_MapVector_t) );
+    vf_MapVector* vector = 
+        (vf_MapVector*) ctex->m_graph->AllocMemory( sizeof( vf_MapVector ) );
+        
     // alloc memory for stack vector
     if( maxstack ) {
         vector->m_maxstack = (unsigned short)maxstack;
         vector->m_stack = (vf_MapEntry_t*)ctex->m_graph->
-            AllocMemory( maxstack * sizeof(vf_MapEntry_t) );
+            AllocMemory( maxstack * sizeof( vf_MapEntry_t ) );
     }
     // alloc memory for locals vector
     if( locals ) {
         vector->m_maxlocal = (unsigned short)locals;
         vector->m_local = (vf_MapEntry_t*)ctex->m_graph->
-            AllocMemory( locals * sizeof(vf_MapEntry_t) );
+            AllocMemory( locals * sizeof( vf_MapEntry_t ) );
     }
 
     // get method signature
     const char *descr = method_get_descriptor( ctex->m_method );
 
-    // get method vectors
+    // get the end node IN vector
+    vf_MapVector* p_outvector = 
+        (vf_MapVector*)ctex->m_graph->GetNodeInVector( ctex->m_nodeNum - 1 );
+
+    // get vectors sizes
+    int inlen, outlen;
     vf_parse_description( descr, &inlen, &outlen );
-    vf_set_description_vector( descr, inlen, 0, outlen, &invector, &outvector, ctex );
+    p_outvector->m_depth = outlen;
+
+    // get method vectors
+    vf_set_description_vector( descr, inlen, 0, outlen, &invector,
+        &p_outvector->m_stack, ctex );
+
+    // cache in the context if the method is a constructor
+    ctex->m_is_constructor =
+        memcmp( method_get_name( ctex->m_method ), "<init>", 7 ) == 0;
 
     // set "this" reference in local variable
+    int start;
     if( method_is_static( ctex->m_method ) ) {
-        begin = 0;
+        start = 0;
     } else {
-        begin = 1;
+        start = 1;
         // fill "this" entry
         const char *name = class_get_name( ctex->m_class );
         vf_ValidType_t *type = vf_create_class_valid_type( name, ctex );
-        if( !memcmp( method_get_name( ctex->m_method ), "<init>", 7 ) ) {
+        if( ctex->m_is_constructor ) {
             vector->m_local->m_type = SM_UNINITIALIZED;
         } else {
             vector->m_local->m_type = SM_REF;
@@ -1377,7 +1354,8 @@
     }
 
     // set start vector
-    for( index = begin, count = 0; count < inlen; index++, count++ ) {
+    int index, count;
+    for( index = start, count = 0; count < inlen; index++, count++ ) {
         vector->m_local[index].m_type = invector[count].m_type;
         vector->m_local[index].m_vtype = invector[count].m_vtype;
         vector->m_local[index].m_is_local = 1;
@@ -1385,7 +1363,6 @@
     }
     vector->m_number = (unsigned short)index;
 
-    // FIXME - need set end entry vector
     return vector;
 } // vf_create_method_begin_vector
 
@@ -1396,15 +1373,15 @@
 vf_enumerate_graph_node( vf_Context_t *ctex )
 {
     // clear graph node marks
-    vf_Graph_t *graph = ctex->m_graph;
+    vf_Graph* graph = ctex->m_graph;
     graph->CleanNodesMark();
 
     // set first enumeration node
-    graph->SetStartCountNode(0);
+    graph->SetStartCountNode( 0 );
     graph->SetNodeMark( 0, VERIFY_START_MARK );
 
     // enumerate graph nodes
-    for( unsigned index = 0; index < graph->GetNodeNumber(); index++ ) {
+    for( unsigned index = 0; index < graph->GetNodeCount(); index++ ) {
         // get node by count element
         unsigned node_num = graph->GetCountElementNode( index );
         if( node_num == ~0U ) {
@@ -1447,26 +1424,26 @@
     // enumerate graph
     vf_enumerate_graph_node( ctex );
 
-    // get begin vector
-    vf_MapVector_t *begin = vf_create_method_begin_vector( ctex );
+    // get a start vector
+    vf_MapVector* start = (vf_MapVector*)vf_create_terminal_maps( ctex );
 
     // create buf stack map vector (max 4 entry)
     vf_MapEntry_t *buf = (vf_MapEntry_t*)vf_alloc_pool_memory( ctex->m_pool,
-            sizeof(vf_MapEntry_t) * method_get_max_stack( ctex->m_method ) );
+            sizeof( vf_MapEntry_t ) * method_get_max_stack( ctex->m_method ) );
 
     // clean graph mark
-    vf_Graph_t *graph = ctex->m_graph;
+    vf_Graph* graph = ctex->m_graph;
     graph->CleanNodesMark();
 
     // set start node IN vector
-    graph->SetNodeInVector( 0, begin, true );
+    graph->SetNodeInVector( 0, start, true );
 
     // check graph data flow
     bool need_recheck = false;
     unsigned count = 0;
     do {
         unsigned node = graph->GetCountElementNode( count );
-        Verifier_Result result = vf_check_node_data_flow( node, begin, buf, &count, &need_recheck, ctex );
+        Verifier_Result result = vf_check_node_data_flow( node, start, buf, &count, &need_recheck, ctex );
         if( result != VER_OK ) {
             return result;
         }
@@ -1480,5 +1457,3 @@
 
     return VER_OK;
 } // vf_check_graph_data_flow
-
-} // namespace Verifier

Added: harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier/ver_graph.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier/ver_graph.h?view=auto&rev=508525
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier/ver_graph.h (added)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier/ver_graph.h Fri Feb 16 10:02:37 2007
@@ -0,0 +1,757 @@
+/*
+ *  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 Pavel Rebriy, Alexei Fedotov
+ * @version $Revision: 1.1.2.3.4.4 $
+ */  
+
+
+#ifndef _VERIFIER_GRAPH_H_
+#define _VERIFIER_GRAPH_H_
+/**
+ * @file
+ * Control flow graph structures.
+ */
+
+#include "ver_real.h"
+
+/**
+ * Initial node mark in verifier graph.
+ */
+#define VERIFY_START_MARK       1
+
+
+/**
+ * Each node has a descriptive bitmap.
+ */
+enum vf_NodeType {
+    VF_TYPE_NODE_CODE_RANGE  = 0,
+    VF_TYPE_NODE_START_ENTRY = 1,
+    VF_TYPE_NODE_END_ENTRY   = 2,
+    VF_TYPE_NODE_HANDLER     = 3
+};
+
+/**
+ * @ingroup Handles
+ * The stack map handle vector handle.
+ */
+typedef const struct vf_MapVector* vf_MapVectorHandle;
+/**
+ * @ingroup Handles
+ * The handle of the graph node.
+ */
+typedef const struct vf_Node* vf_NodeHandle;
+/**
+ * @ingroup Handles
+ * The handle of the graph edge.
+ */
+typedef const struct vf_Edge* vf_EdgeHandle;
+/// Declaration of enum with a descriptive bitmap.
+typedef enum vf_NodeType vf_NodeType_t;
+
+/**
+ * Structure of stack map vector.
+ */
+struct vf_MapVector {
+    vf_MapEntry_t *m_stack;         ///< stack map vector
+    vf_MapEntry_t *m_local;         ///< locals map vector
+    unsigned short m_number;        ///< number of locals
+    unsigned short m_depth;         ///< stack depth
+    unsigned short m_maxstack;      ///< max stack length
+    unsigned short m_maxlocal;      ///< max local number
+};
+
+/**
+ * Graph node structure.
+ */
+struct vf_Node
+{
+    vf_MapVector m_inMapVector;     ///< stack map IN node vector
+    vf_MapVector m_outMapVector;    ///< stack map OUT node vector
+    unsigned m_start;               ///< index of the first instruction at vf_Context.m_code
+    unsigned m_end;                 ///< index of the last instruction at vf_Context.m_code
+    unsigned m_inedge;              ///< the first incoming edge
+    unsigned m_outedge;             ///< the first outcoming edge
+    unsigned m_innum;               ///< number of incoming edges
+    unsigned m_outnum;              ///< number of outcoming edges
+    unsigned m_nodecount;           ///< node count in enumeration
+    int m_stack;                    ///< stack depth
+    int m_mark;                     ///< node mark
+    vf_NodeType_t m_type;           ///< node type
+    bool m_initialized : 1;         ///< reference in a local variable 
+                                    ///< should be initialized
+};
+
+/**
+ * Graph edge structure.
+ */
+struct vf_Edge
+{
+    unsigned m_start;       ///< start edge node
+    unsigned m_end;         ///< end edge node
+    unsigned m_innext;      ///< next incoming edge
+    unsigned m_outnext;     ///< next outcoming edge
+};
+
+/**
+ * Graph node container structure.
+ */
+struct vf_NodeContainer
+{
+    vf_NodeContainer* m_next;           ///< next container
+    unsigned m_max;                     ///< max number of nodes in container
+    unsigned m_used;                    ///< number of nodes in container
+    vf_Node m_node[1];                  ///< array of contained nodes
+};
+
+/**
+ * Graph edge container structure.
+ */
+struct vf_EdgeContainer
+{
+    vf_EdgeContainer* m_next;           ///< next container
+    unsigned m_max;                     ///< max number of edges in container
+    unsigned m_used;                    ///< number of edges in container
+    vf_Edge m_edge[1];                  ///< array of contained edges
+};
+
+/**
+ * Verifier control flow graph structure.
+ */
+class vf_Graph
+{
+public:
+    /**
+     * Control flow graph constructor.
+     * @param node - number of graph nodes
+     * @param edge - number of graph edges
+     * @param pool - external memory pool
+     * @note Function allocates memory for graph structure, nodes and edges.
+     */
+    vf_Graph( unsigned node, unsigned edge, vf_VerifyPool_t *pool )
+            : m_nodes(NULL), m_edges(NULL), m_pool(pool), m_enum(NULL),
+            m_nodenum(0), m_edgenum(1), m_enummax(0), m_enumcount(0),
+            m_free(false)
+    {
+        CreateNodes( node );
+        CreateEdges( edge );
+        return;
+    } // vf_Graph
+
+    /**
+     * Control flow graph destructor.
+     * @note Function release memory for graph structure, nodes and edges.
+     */
+    ~vf_Graph()
+    {
+        if( m_free ) {
+            vf_delete_pool( m_pool ); 
+        }
+        return;
+    } // ~vf_Graph
+
+    /**
+     * Function create graph nodes.
+     * @param count - number of graph nodes
+     * @note Function allocates memory for graph nodes.
+     */
+    void CreateNodes( unsigned count );
+
+    /**
+     * Gets a graph node.
+     *
+     * @param[in] node_num  a node number, should be in range
+     * @return a handle of the node
+     */
+    vf_NodeHandle GetNode( unsigned node_num );
+
+    /**
+     * Gets the first node.
+     *
+     * @return a handle of the node
+     */
+    vf_NodeHandle GetFirstNode()
+    {
+        return GetNode( 0 );
+    } // GetFirstNode
+
+    /**
+     * Creates a new node of a specific type.
+     * Node array must have enough free space for a new element.
+     *
+     * @param[in] m_type node type
+     * @param[in] stack  a stack modifier (signed value)
+     * @return a handle of the created node
+     */
+    vf_NodeHandle NewNode( vf_NodeType_t m_type, int stack );
+
+    /**
+     * Creates a new node for a bytecode range.
+     * Node array must have enough free space for a new element.
+     *
+     * @param[in] start   an instruction start index
+     * @param[in] end     an instruction end index
+     * @param[in] stack   a stack modifier (signed value)
+     * @return a handle of the created node
+     */
+    vf_NodeHandle NewNode( unsigned start,
+                           unsigned end,
+                           int stack)
+    {
+        // get node
+        vf_Node* node = (vf_Node*) NewNode( VF_TYPE_NODE_CODE_RANGE, stack );
+        node->m_start = start;
+        node->m_end = end;
+        return node;
+    } // NewNode( start, end, len )
+
+    /**
+     * Gets graph edge.
+     * Parameter <i>edge_num</i> must be in range.
+     *
+     * @param[in] edge_num  - edge number
+     *
+     * @return The pointer to edge structure.
+     */
+    vf_EdgeHandle GetEdge( unsigned edge_num );
+
+    /**
+     * Creates a new edge for graph nodes.
+     *
+     * @param start_node    - start edge node
+     * @param end_node      - end edge node
+     * @note Edge is set as out edge for start_node and as in edge for end_node.
+     */
+    void NewEdge( unsigned start_node,
+                  unsigned end_node);
+
+    /**
+     * Gets the first code instruction of a node.
+     * @param node_num the node number
+     * @return a number of the first code instruction of graph node
+     * @note Assertion is raised if <i>node_num</i> is not a
+     * code range node.
+     */
+    unsigned GetNodeFirstInstr( unsigned node_num )
+    {
+        vf_NodeHandle node = GetNode( node_num );
+        assert( VF_TYPE_NODE_CODE_RANGE == node->m_type );
+        return node->m_start;
+    } // GetNodeFirstInstr
+
+    /**
+     * Gets the last code instruction of a node.
+     * @param node_num the node number
+     * @return a number of the last code instruction of graph node
+     * @note Assertion is raised if <i>node_num</i> is not a
+     * code range node.
+     */
+    unsigned GetNodeLastInstr( unsigned node_num )
+    {
+        vf_NodeHandle node = GetNode( node_num );
+        assert( VF_TYPE_NODE_CODE_RANGE == node->m_type );
+        return node->m_end;
+    } // GetNodeLastInstr
+
+    /**
+     * Gets a bytecode length of a graph node instructions.
+     * @param context a verifier context handle
+     * @param node a node handle
+     * @return a number of the last code instruction of graph node
+     * @note Assertion is raised if <i>node_num</i> is not a
+     * code range node.
+     */
+    unsigned GetNodeBytecodeLen( vf_ContextHandle context,
+                                 vf_NodeHandle node)
+    {
+        assert( VF_TYPE_NODE_CODE_RANGE == node->m_type );
+        unsigned char* code_end = (node->m_end + 1 == context->m_codeNum)
+            ? method_get_bytecode( context->m_method )
+                + method_get_code_length( context->m_method )
+            : context->m_code[node->m_end + 1].m_addr;
+
+        unsigned len = code_end - context->m_code[node->m_start].m_addr;
+        return len;
+    } // GetNodeBytecodeLen
+
+    /**
+     * Gets a stack modifier of a graph node.
+     * @param node_num a node number
+     * @return a stack modifier of graph node
+     */
+    int GetNodeStackModifier( unsigned node_num )
+    {
+        return GetNode( node_num )->m_stack;
+    } // GetNodeStackModifier
+
+    /**
+     * Sets graph node stack modifier.
+     * @param node_num a graph node number
+     * @param stack    a stack modifier (signed value)
+     */
+    void SetNodeStackModifier( unsigned node_num, int stack )
+    {
+        vf_Node* node = (vf_Node*) GetNode( node_num );
+        node->m_stack = stack;
+    } // SetNodeStackModifier
+
+    /**
+     * Counts graph nodes.
+     * @return a number of graph nodes
+     */
+    unsigned GetNodeCount()
+    {
+        return m_nodenum;
+    } // GetNodeCount
+
+    /**
+     * Counts graph edges excluding
+     * the reserved edge.
+     * @return a number of graph edges
+     */
+    unsigned GetEdgeCount()
+    {
+        return m_edgenum - 1;
+    } // GetEdgeCount
+
+    /**
+     * Marks a graph node with a given number.
+     * @param node_num a graph node number
+     * @param mark     a mark
+     */
+    void SetNodeMark( unsigned node_num, int mark )
+    {
+        vf_Node* node = (vf_Node*) GetNode( node_num );
+        node->m_mark = mark;
+    } // SetNodeMark
+
+    /**
+     * Gets a graph node mark.
+     * @param  node_num a node number
+     * @return a graph node mark
+     */
+    int GetNodeMark( unsigned node_num )
+    {
+        return GetNode( node_num )->m_mark;
+    } // GetNodeMark
+
+    /**
+     * Checks if a node is marked.
+     * @param  node_num a graph node number
+     * @return <code>true</code> if node is marked, <code>false</code> otherwise
+     */
+    bool IsNodeMarked( unsigned node_num )
+    {
+        return 0 != GetNode( node_num )->m_mark;
+    } // IsNodeMarked
+
+    /**
+     * Function removes node mark.
+     */
+    void CleanNodesMark()
+    {
+        // clean node's mark
+        assert( m_nodes );
+        vf_NodeContainer* nodes = m_nodes;
+        while( nodes != NULL ) {
+            for( unsigned index = 0; index < nodes->m_used; index++ ) {
+                nodes->m_node[index].m_mark = 0;
+            }
+            nodes = nodes->m_next;
+        }
+        return;
+    } // CleanNodesMark
+
+    /**
+     * Sets local variable reference initialization flag for a anode.
+     * @param node_num a graph node number
+     * @param flag     a node flag
+     */
+    void SetNodeInitFlag( unsigned node_num, bool flag )
+    {
+        vf_Node* node = (vf_Node*) GetNode( node_num );
+        node->m_initialized = flag;
+    } // SetNodeInitFlag
+
+    /**
+     * Gets an initialization flag for local variable reference for a given node.
+     * @param node_num a graph node number
+     * @return <code>true</code> if the local variable reference has
+     * to be initialized, <code>false</code> otherwise.
+     */
+    bool GetNodeInitFlag( unsigned node_num )
+    {
+        return GetNode( node_num )->m_initialized;
+    } // GetNodeInitFlag
+
+    /**
+     * Function creates <i>IN</i> data flow vector of a node.
+     * @param node_num  a graph node number
+     * @param example   a handle of copied data flow vector
+     * @param need_copy a copy flag
+     * @note If copy flag <code>true</code>, incoming vector is copied to <i>IN</i>,
+     *       else if copy flag <code>false</code>, <i>IN</i> vector is created
+     *       with parameters of current vector.
+     */
+    void SetNodeInVector( unsigned node_num,
+                          vf_MapVectorHandle example,
+                          bool need_copy)
+    {
+        SetVector( GetNodeInVector( node_num ), example, need_copy );
+    } // SetNodeInVector
+
+    /**
+     * Creates <i>OUT</i> data flow vector of a node.
+     * @param node_num  a graph node number
+     * @param example   a handle of copied data flow vector
+     * @param need_copy a copy flag
+     * @note If copy flag <code>true</code>, incoming vector is copied to <i>OUT</i>,
+     *       else if copy flag <code>false</code>, <i>OUT</i> vector is created
+     *       with parameters of current vector.
+     */
+    void SetNodeOutVector( unsigned node_num,
+                           vf_MapVectorHandle example,
+                           bool need_copy )
+    {
+        SetVector( GetNodeOutVector( node_num ), example, need_copy );
+    } // SetNodeOutVector
+
+    /**
+     * Gets <i>IN</i> data flow vector for the node.
+     * @param node_num graph node number
+     * @return a reference to <i>IN</i> data flow stack map vector
+     * @note Assertion is raised if <i>node_num</i> is out of range.
+     * @see vf_MapVector_t
+     */
+    vf_MapVectorHandle GetNodeInVector( unsigned node_num )
+    {
+        return &( GetNode( node_num )->m_inMapVector );
+    } // GetNodeInVector
+
+    /**
+     * Gets <i>OUT</i> data flow vector for the node.
+     * @param node_num graph node number
+     * @return a reference to <i>OUT</i> data flow stack map vector
+     * @see vf_MapVector_t
+     */
+    vf_MapVectorHandle GetNodeOutVector( unsigned node_num )
+    {
+        return &( GetNode( node_num )->m_outMapVector );
+    } // GetNodeOutVector
+
+    /**
+     * Function creates graph edges.
+     * @param number - number of edges 
+     */
+    void CreateEdges( unsigned number );
+
+    /**
+     * Function receives next <i>IN</i> edge of graph node.
+     * @param edge_num - number of graph edge
+     * @return Number of next <i>IN</i> edge of node.
+     * @note Assertion is raised if <i>edge_num</i> is out of range.
+     */
+    unsigned GetEdgeNextInEdge( unsigned edge_num )
+    {
+        return GetEdge( edge_num )->m_innext;
+    } // GetEdgeNextInEdge
+
+    /**
+     * Function receives next <i>OUT</i> edge of graph node.
+     * @param edge_num - number of graph edge
+     * @return Number of next <i>OUT</i> edge of node.
+     * @note Assertion is raised if <i>edge_num</i> is out of range.
+     */
+    unsigned GetEdgeNextOutEdge( unsigned edge_num )
+    {
+        return GetEdge( edge_num )->m_outnext;
+    } // GetEdgeNextOutEdge
+
+    /**
+     * Function receives start graph node of edge.
+     * @param edge_num - number of graph edge
+     * @return Number start graph node of edge.
+     * @note Assertion is raised if <i>edge_num</i> is out of range.
+     */
+    unsigned GetEdgeStartNode( unsigned edge_num )
+    {
+        return GetEdge( edge_num )->m_start;
+    } // GetEdgeStartNode
+
+    /**
+     * Function receives end graph node of edge.
+     * @param edge_num - number of graph edge
+     * @return Number end graph node of edge.
+     * @note Assertion is raised if <i>edge_num</i> is out of range.
+     */
+    unsigned GetEdgeEndNode( unsigned edge_num )
+    {
+        return GetEdge( edge_num )->m_end;
+    } // GetEdgeStartNode
+
+    /**
+     * Function receives number of <i>IN</i> edges of graph node.
+     * @param node_num - number of graph node
+     * @return Number of <i>IN</i> edges of graph node.
+     * @note Assertion is raised if <i>node_num</i> is out of range.
+     */
+    unsigned GetNodeInEdgeNumber( unsigned node_num )
+    {
+        return GetNode( node_num )->m_innum;
+    } // GetNodeInEdgeNumber
+
+    /**
+     * Function receives number of <i>OUT</i> edges of graph node.
+     * @param node_num - number of graph node
+     * @return Number of <i>OUT</i> edges of graph node.
+     * @note Assertion is raised if <i>node_num</i> is out of range.
+     */
+    unsigned GetNodeOutEdgeNumber( unsigned node_num )
+    {
+        return GetNode( node_num )->m_outnum;
+    } // GetNodeOutEdgeNumber
+
+    /**
+     * Function receives first <i>IN</i> edge of graph node.
+     * @param node_num - number of graph node
+     * @return First <i>IN</i> edges of node.
+     * @note Assertion is raised if <i>node_num</i> is out of range.
+     */
+    unsigned GetNodeFirstInEdge( unsigned node_num )
+    {
+        return GetNode( node_num )->m_inedge;
+    } // GetNodeFirstInEdge
+
+    /**
+     * Function receives first <i>OUT</i> edge of graph node.
+     * @param node_num - number of graph node
+     * @return First <i>OUT</i> edges of node.
+     * @note Assertion is raised if <i>node_num</i> is out of range.
+     */
+    unsigned GetNodeFirstOutEdge( unsigned node_num )
+    {
+        return GetNode( node_num )->m_outedge;
+    } // GetNodeFirstOutEdge
+
+    /**
+     * Allocates memory from the graph memory pool.
+     * @param size a size of memory block
+     * @return a pointer to allocated memory,
+     *         or <code>NULL</code> if memory allocation failed.
+     */
+    void* AllocMemory( unsigned size ) {
+        assert( size );
+        return vf_alloc_pool_memory( m_pool, size );
+    } // AllocMemory
+
+    /**
+     * Function cleans graph node enumeration, creates new graph
+     * enumeration structure and sets first enumeration element.
+     * @param node_num - first enumeration node
+     * @note Assertion is raised if <i>node_num</i> is out of range.
+     */
+    void SetStartCountNode( unsigned node_num );
+
+    /**
+     * Function receives number of enumerated nodes.
+     * @return Function returns number of enumerated nodes.
+     */
+    unsigned GetEnumCount()
+    {
+        return m_enumcount;
+    } // SetStartCountNode
+
+    /**
+     * Function sets next enumeration element in graph enumeration structure.
+     * @param node_num - next enumeration node
+     * @note Assertion is raised if <i>node_num</i> is out of range.
+     */
+    void SetNextCountNode( unsigned node_num )
+    {
+        // check enumeration count is in range
+        assert( m_enumcount < m_nodenum );
+
+        // set enumeration element for node
+        m_enum[m_enumcount] = node_num;
+
+        // set node enumeration number and increase number of enumerated nodes
+        vf_Node* node = (vf_Node*) GetNode( node_num );
+        node->m_nodecount = m_enumcount++;
+        return;
+    } // SetNextCountNode
+
+    /**
+     * Function receives first enumerated graph node.
+     * @return First enumerated graph node in graph enumeration structure.
+     */
+    unsigned GetStartCountNode()
+    {
+        return m_enum[0];
+    } // GetStartCountNode
+    
+    /**
+     * Function receives graph node relevant to enumeration element.
+     * @param count - given enumeration element
+     * @return Graph node relevant to enumeration element.
+     * @note Assertion is raised if <i>count</i> is out of range.
+     */
+    unsigned GetCountElementNode( unsigned count )
+    {
+        // check element is in range.
+        assert( count < m_nodenum );
+        return m_enum[count];
+    } // GetCountElementNode
+
+    /**
+     * Function receives graph node enumeration count.
+     * @param node_num - given node
+     * @return Graph node enumeration count.
+     * @note Assertion is raised if <i>node_num</i> is out of range.
+     */
+    unsigned GetNodeCountElement( unsigned node_num )
+    {
+        return GetNode( node_num )->m_nodecount;
+    } // GetNodeCountElement
+
+    /**
+     * Function prints graph structure in <code>stderr</code>.
+     * @param context - current verifier context
+     * @note Function is valid in debug mode.
+     * @see vf_Context_t
+     */
+    void DumpGraph( vf_Context_t *context );
+
+    /**
+     * Function dumps verifier graph in file in DOT format.
+     * @param context - current verifier context
+     * @note Function is valid in debug mode.
+     * @note File name is created from class and method names with .dot extension.
+     * @see vf_Context_t
+     */
+    void DumpDotGraph( vf_Context_t *context );
+
+private:
+    vf_NodeContainer* m_nodes;          ///< array of nodes
+    vf_EdgeContainer* m_edges;          ///< array of edges
+    vf_VerifyPool_t *m_pool;            ///< graph memory pool
+    unsigned *m_enum;                   ///< graph node enumeration structure
+    unsigned m_nodenum;                 ///< number of nodes
+    unsigned m_edgenum;                 ///< number of edges
+    unsigned m_enummax;                 ///< max number of enumerated elements
+    unsigned m_enumcount;               ///< number of enumerated elements
+    bool m_free;                        ///< need to free pool
+
+    /**
+     * Creates a data flow vector from a given example.
+     * @param vector_handle a vector to set
+     * @param example   a handle of an example vector
+     * @param need_copy a copy flag
+     * @note If copy flag <code>true</code>, incoming vector is copied to,
+     *       otherwise <i>IN</i> vector is created
+     *       with parameters of current vector.
+     */
+    void SetVector( vf_MapVectorHandle vector_handle,
+                    vf_MapVectorHandle example,
+                    bool need_copy);
+
+    /**
+     * Function prints graph node in <code>stderr</code>.
+     * @param node_num  - number of graph node
+     * @param context      - current verifier context
+     * @note Function is valid in debug mode.
+     * @note Assertion is raised if <i>node_num</i> is out of range.
+     * @see vf_Context_t
+     */
+    void DumpNode( unsigned node_num, vf_Context_t *context );
+
+    /**
+     * Function prints graph node instruction in stream.
+     * @param node_num   - number of graph node
+     * @param context    - current verifier context
+     * @note Function is valid in debug mode.
+     * @note Assertion is raised if <i>node_num</i> is out of range.
+     * @see vf_Context_t
+     */
+    void DumpNodeInternal( unsigned node_num,
+                           vf_Context_t *context);
+
+
+    /**
+     * Function dumps graph header in file in DOT format.
+     * @param graph_name    - graph name
+     * @param fout          - file stream
+     * @note Function is valid in debug mode.
+     * @note Graph name is created from class and method names.
+     */
+    void DumpDotHeader( char *graph_name, ofstream &fout );
+
+    /**
+     * Function dumps graph node in file in DOT format.
+     * @param node_num - number of graph node
+     * @param fout     - file stream
+     * @param context  - current verifier context
+     * @note Function is valid in debug mode.
+     * @note Assertion is raised if <i>node_num</i> is out of range.
+     * @see vf_Context_t
+     */
+    void DumpDotNode( unsigned node_num, ofstream &fout, vf_Context_t *context );
+
+    /**
+     * Function dumps graph node instruction in file stream in DOT format.
+     * @param node_num   - number of graph node
+     * @param next_node  - separator between nodes in stream
+     * @param next_instr - separator between instructions in stream
+     * @param fout       - output file stream
+     * @param context    - current verifier context
+     * @note Function is valid in debug mode.
+     * @note Assertion is raised if <i>node_num</i> is out of range.
+     * @see vf_Context_t
+     */
+    void DumpDotNodeInternal( unsigned node_num,
+                              char *next_node,
+                              char *next_instr,
+                              ofstream &fout,
+                              vf_Context_t *context);
+
+    /**
+     * Function dumps graph end in file in DOT format.
+     * @param fout - output file stream
+     * @note Function is valid in debug mode.
+     */
+    void DumpDotEnd( ofstream &fout );
+
+}; // vf_Graph
+
+/**
+ * Checks if a code range node ends with a specific
+ * instruction type.
+ *
+ * @param[in] context a verifier context
+ * @param[in] node_index the node identifier
+ *
+ * @return a type of the last instruction of code range node
+ */
+static inline vf_CodeType
+vf_get_last_instruction_type( vf_ContextHandle context,
+                              unsigned node_index)
+{
+    vf_NodeHandle node = context->m_graph->GetNode( node_index );
+    assert( VF_TYPE_NODE_CODE_RANGE == node->m_type );
+    return context->m_code[node->m_end].m_type;
+}
+
+#endif // _VERIFIER_GRAPH_H_

Propchange: harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier/ver_graph.h
------------------------------------------------------------------------------
    svn:eol-style = native