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/06/13 17:17:11 UTC

svn commit: r546915 [4/5] - in /harmony/enhanced/drlvm/trunk: src/test/regression/H3225/ vm/vmcore/include/ vm/vmcore/src/class_support/ vm/vmcore/src/verifier/

Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier/ver_real.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier/ver_real.h?view=diff&rev=546915&r1=546914&r2=546915
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier/ver_real.h (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier/ver_real.h Wed Jun 13 08:17:09 2007
@@ -20,8 +20,8 @@
  */
 
 
-#ifndef _VERIFIER_REAL_H_
-#define _VERIFIER_REAL_H_
+#ifndef _VF_REAL_H_
+#define _VF_REAL_H_
 
 /**
  * @file
@@ -149,61 +149,61 @@
 #define CHECK_HANDLER_CONST_POOL_ID( id, len, ctx ) \
     if( (id) >= (len) ) { \
         VF_REPORT( ctx, "Illegal constant pool index in handler" ); \
-        return VER_ErrorHandler; \
+        return VF_ErrorHandler; \
     }
 // for handler id = 0 is legal value
 #define CHECK_HANDLER_CONST_POOL_CLASS( ctx, id ) \
     if( (id) && class_get_cp_tag( (ctx)->m_class, (id) ) != _CONSTANT_Class ) { \
         VF_REPORT( ctx, "Illegal type in constant pool for handler, " \
             << id << ": CONSTANT_Class is expected" ); \
-        return VER_ErrorHandler; \
+        return VF_ErrorHandler; \
     }
 #define CHECK_CONST_POOL_ID( id, len, ctx ) \
     if( !(id) || (id) >= (len) ) { \
         VF_REPORT( ctx, "Illegal constant pool index" ); \
-        return VER_ErrorConstantPool; \
+        return VF_ErrorConstantPool; \
     }
 #define CHECK_CONST_POOL_CLASS( ctx, id ) \
     if( class_get_cp_tag( (ctx)->m_class, (id) ) != _CONSTANT_Class ) { \
         VF_REPORT( ctx, "Illegal type in constant pool, " \
             << id << ": CONSTANT_Class is expected" ); \
-        return VER_ErrorConstantPool; \
+        return VF_ErrorConstantPool; \
     }
 #define CHECK_CONST_POOL_METHOD( ctx, id ) \
     if( class_get_cp_tag( (ctx)->m_class, (id) ) != _CONSTANT_Methodref ) { \
         VF_REPORT( ctx, "Illegal type in constant pool, " \
             << id << ": CONSTANT_Methodref is expected" ); \
-        return VER_ErrorConstantPool; \
+        return VF_ErrorConstantPool; \
     }
 #define CHECK_CONST_POOL_INTERFACE( ctx, id ) \
     if( class_get_cp_tag( (ctx)->m_class, (id) ) != _CONSTANT_InterfaceMethodref ) { \
         VF_REPORT( ctx, "Illegal type in constant pool, " \
             << id << ": CONSTANT_InterfaceMethodref is expected" ); \
-        return VER_ErrorConstantPool; \
+        return VF_ErrorConstantPool; \
     }
 #define CHECK_CONST_POOL_FIELD( ctx, id ) \
     if( class_get_cp_tag( (ctx)->m_class, (id) ) != _CONSTANT_Fieldref ) { \
         VF_REPORT( ctx, "Illegal type in constant pool, " \
             << id << ": CONSTANT_Fieldref is expected" ); \
-        return VER_ErrorConstantPool; \
+        return VF_ErrorConstantPool; \
     }
 #define CHECK_CONST_POOL_TYPE( ctx, id ) \
     if( class_get_cp_tag( (ctx)->m_class, (id) ) != _CONSTANT_NameAndType ) { \
         VF_REPORT( ctx, "Illegal type in constant pool, " \
             << id << ": CONSTANT_NameAndType is expected" ); \
-        return VER_ErrorConstantPool; \
+        return VF_ErrorConstantPool; \
     }
 #define CHECK_CONST_POOL_STRING( ctx, id ) \
     if( class_get_cp_tag( (ctx)->m_class, (id) ) != _CONSTANT_String ) { \
         VF_REPORT( ctx, "Illegal type in constant pool, " \
             << id << ": CONSTANT_String is expected" ); \
-        return VER_ErrorConstantPool; \
+        return VF_ErrorConstantPool; \
     }
 #define CHECK_CONST_POOL_UTF8( ctx, id ) \
     if( class_get_cp_tag( (ctx)->m_class, (id) ) != _CONSTANT_Utf8) { \
         VF_REPORT( ctx, "Illegal type in constant pool, " \
             << id << ": CONSTANT_Utf8 is expected" ); \
-        return VER_ErrorConstantPool; \
+        return VF_ErrorConstantPool; \
     }
 
 //===========================================================
@@ -211,11 +211,6 @@
 //===========================================================
 
 /**
- * Verifier error codes.
- */
-typedef Verifier_Result vf_Result;
-
-/**
  * Constraint check types enum.
  */
 typedef enum
@@ -337,6 +332,8 @@
     {
         unsigned m_new;         ///< program count of opcode new for uninitialized
         unsigned m_pc;          ///< program count of return address for subroutine
+        unsigned m_mappos;      ///< for SM_ANY a position in the initial stack map,
+        ///< positions in the stack start from ctx->m_maxlocal
     };
     union
     {
@@ -468,8 +465,7 @@
  *       are equal to zero or if out of memory error is arisen.
  * @note Trace is available with argument <b>verifier:memory</b>.
  */
-void *vf_calloc_func( unsigned number, size_t element_size,
-                      VF_SOURCE_PARAMS );
+void *vf_calloc_func(unsigned number, size_t element_size, VF_SOURCE_PARAMS);
 
 /**
  * Function allocates memory blocks.
@@ -482,7 +478,7 @@
  *       or if out of memory error is arisen.
  * @note Trace is available with argument <b>verifier:memory</b>.
  */
-void *vf_malloc_func( size_t size, VF_SOURCE_PARAMS );
+void *vf_malloc_func(size_t size, VF_SOURCE_PARAMS);
 
 /**
  * Function releases allocated memory blocks.
@@ -493,7 +489,7 @@
  * @note Assertion is raised if <i>pointer</i> is equal to null.
  * @note Trace is available with argument <b>verifier:memory</b>.
  */
-void vf_free_func( void *pointer, VF_SOURCE_PARAMS );
+void vf_free_func(void *pointer, VF_SOURCE_PARAMS);
 
 /**
  * Function reallocates memory blocks.
@@ -508,7 +504,7 @@
  * @note If <i>pointer</i> is equal to null function works like vf_malloc_func.
  * @note Trace is available with argument <b>verifier:memory</b>.
  */
-void *vf_realloc_func( void *pointer, size_t resize, VF_SOURCE_PARAMS );
+void *vf_realloc_func(void *pointer, size_t resize, VF_SOURCE_PARAMS);
 
 /**
  * Function creates memory pool structure.
@@ -519,7 +515,7 @@
  * @see vf_Pool
  * @note Trace is available with argument <b>verifier:memory:pool</b>.
  */
-vf_Pool *vf_create_pool_func( VF_SOURCE_PARAMS );
+vf_Pool *vf_create_pool_func(VF_SOURCE_PARAMS);
 
 /**
  * Function allocates memory blocks in current pool.
@@ -532,7 +528,7 @@
  * @see vf_Pool
  * @note Trace is available with argument <b>verifier:memory:pool</b>.
  */
-void *vf_palloc_func( vf_Pool *pool, size_t size, VF_SOURCE_PARAMS );
+void *vf_palloc_func(vf_Pool *pool, size_t size, VF_SOURCE_PARAMS);
 
 /**
  * Function cleans given pool.
@@ -543,7 +539,7 @@
  * @see vf_Pool
  * @note Trace is available with argument <b>verifier:memory:pool</b>.
  */
-void vf_clean_pool_func( vf_Pool *pool, VF_SOURCE_PARAMS );
+void vf_clean_pool_func(vf_Pool *pool, VF_SOURCE_PARAMS);
 
 /**
  * Function releases memory from given pool.
@@ -554,7 +550,7 @@
  * @see vf_Pool
  * @note Trace is available with argument <b>verifier:memory:pool</b>.
  */
-void vf_delete_pool_func( vf_Pool *pool, VF_SOURCE_PARAMS );
+void vf_delete_pool_func(vf_Pool *pool, VF_SOURCE_PARAMS);
 
 //===========================================================
 // Verifier hash table structures.
@@ -587,13 +583,13 @@
      * @param pool - external memory pool
      * @note Function allocates memory for hash pool and hash table.
      */
-    vf_Hash ( vf_Pool *pool );
+    vf_Hash (vf_Pool *pool);
 
     /**
      * Hash table destructor.
      * @note Function release memory for hash pool and hash table.
      */
-           ~vf_Hash ();
+    ~vf_Hash();
 
     /**
      * Function looks up hash entry which is identical to given hash key.
@@ -601,7 +597,7 @@
      * @return Hash entry which is identical to given hash key.
      * @see vf_HashEntry
      */
-    vf_HashEntry *Lookup( const char *key );
+    vf_HashEntry *Lookup(const char *key);
 
     /**
      * Function looks up hash entry which is identical to given hash key.
@@ -610,7 +606,7 @@
      * @return Hash entry which is identical to given hash key.
      * @see vf_HashEntry
      */
-    vf_HashEntry *Lookup( const char *key, size_t len );
+    vf_HashEntry *Lookup(const char *key, size_t len);
 
     /**
      * Function creates hash entry which is identical to given hash key.
@@ -619,7 +615,7 @@
      * @see vf_HashEntry
      * @note Created hash key and hash entry is allocated into hash memory pool.
      */
-    vf_HashEntry *NewHashEntry( const char *key );
+    vf_HashEntry *NewHashEntry(const char *key);
 
     /**
      * Function creates hash entry which is identical to given hash key.
@@ -629,7 +625,7 @@
      * @see vf_HashEntry
      * @note Created hash key and hash entry is allocated into hash memory pool.
      */
-    vf_HashEntry *NewHashEntry( const char *key, size_t len );
+    vf_HashEntry *NewHashEntry(const char *key, size_t len);
 
   private:
     vf_Pool *m_pool;            ///< hash memory pool
@@ -645,7 +641,7 @@
      *         else returns <code>false</code>.
      * @see vf_HashEntry
      */
-    bool CheckKey( vf_HashEntry *hash_entry, const char *key );
+    bool CheckKey(vf_HashEntry *hash_entry, const char *key);
 
     /**
      * Checks key identity.
@@ -656,14 +652,14 @@
      *         else returns <code>false</code>.
      * @see vf_HashEntry
      */
-    bool CheckKey( vf_HashEntry *hash_entry, const char *key, size_t len );
+    bool CheckKey(vf_HashEntry *hash_entry, const char *key, size_t len);
 
     /**
      * Hash function.
      * @param key - key for hash function
      * @return Hash index relevant to key.
      */
-    unsigned HashFunc( const char *key );
+    unsigned HashFunc(const char *key);
 
     /**
      * Hash function.
@@ -671,7 +667,7 @@
      * @param len - key length
      * @return Hash index relevant to key.
      */
-    unsigned HashFunc( const char *key, size_t len );
+    unsigned HashFunc(const char *key, size_t len);
 };                              // struct vf_Hash
 
 //===========================================================
@@ -683,14 +679,14 @@
  */
 struct vf_TypeConstraint
 {
-    const char *m_source;           ///< constraint source class name
-    const char *m_target;           ///< constraint target class name
-    method_handler m_method;        ///< constraint for method
-    const char *m_name;             ///< constraint method name
-    const char *m_descriptor;       ///< constraint method descriptor
-    vf_TypeConstraint *m_next;      ///< next constraint
-    unsigned short m_index;         ///< constant pool index
-    unsigned short m_check_type;    ///< constraint check type @see vf_CheckConstraint
+    const char *m_source;       ///< constraint source class name
+    const char *m_target;       ///< constraint target class name
+    method_handler m_method;    ///< constraint for method
+    const char *m_name;         ///< constraint method name
+    const char *m_descriptor;   ///< constraint method descriptor
+    vf_TypeConstraint *m_next;  ///< next constraint
+    unsigned short m_index;     ///< constant pool index
+    unsigned short m_check_type;        ///< constraint check type @see vf_CheckConstraint
 };
 
 /**
@@ -709,7 +705,7 @@
      * Type constraint collection destructor.
      * @note Function release memory for collection memory pool and hash table.
      */
-    ~vf_TypePool ();
+    ~vf_TypePool();
 
     /**
      * Function creates valid type which is identical to given class.
@@ -718,7 +714,7 @@
      * @return Created valid type structure.
      * @see vf_ValidType
      */
-    vf_ValidType *NewType( const char *type, size_t len );
+    vf_ValidType *NewType(const char *type, size_t len);
 
     /**
      * Function creates valid type which is identical to an element of a given array type.
@@ -726,7 +722,7 @@
      * @return Created valid type of a given array element.
      * @see vf_ValidType
      */
-    vf_ValidType *NewArrayElemType( vf_ValidType *array );
+    vf_ValidType *NewArrayElemType(vf_ValidType *array);
 
     /**
      * Checks types and create constraints if it's necessarily.
@@ -740,9 +736,9 @@
      * @see vf_ValidType
      * @see vf_CheckConstraint
      */
-    bool CheckTypes( vf_ValidType *required,
-                     vf_ValidType *available,
-                     unsigned short index, vf_CheckConstraint check_type );
+    bool CheckTypes(vf_ValidType *required,
+                    vf_ValidType *available,
+                    unsigned short index, vf_CheckConstraint check_type);
 
     /**
      * Function merges two valid types.
@@ -752,14 +748,14 @@
      * @return Function returns <code>NULL</code> if vector wasn't merged.
      * @see vf_ValidType
      */
-    vf_ValidType *MergeTypes( vf_ValidType *first, vf_ValidType *second );
+    vf_ValidType *MergeTypes(vf_ValidType *first, vf_ValidType *second);
 
     /**
      * Dumps constraint collection in stream.
      * @param out - pointer to output stream
      * @note If <i>out</i> is equal to null, output stream is <i>cerr</i>.
      */
-    void DumpTypeConstraints( ostream *out );
+    void DumpTypeConstraints(ostream *out);
 
     /**
      * Function returns the methods constraints array.
@@ -772,7 +768,7 @@
      * Sets current context method.
      * @param ctx - current verifier context
      */
-    void SetMethod( vf_ContextHandle ctx );
+    void SetMethod(vf_ContextHandle ctx);
 
     /**
      * Sets restriction from target class to source class.
@@ -782,10 +778,9 @@
      * @param check_type    - constraint check type
      * @see vf_CheckConstraint
      */
-    void SetRestriction( const char *target,
-                         const char *source,
-                         unsigned short index,
-                         vf_CheckConstraint check_type );
+    void SetRestriction(const char *target,
+                        const char *source,
+                        unsigned short index, vf_CheckConstraint check_type);
 
   private:
     vf_Pool *m_pool;            ///< collection memory pool
@@ -800,7 +795,7 @@
 // Verifier type constraint structures.
 //===========================================================
 
-void vf_clean_pool_func( vf_Pool *pool, VF_SOURCE_PARAMS );
+void vf_clean_pool_func(vf_Pool *pool, VF_SOURCE_PARAMS);
 
 /**
  * Verification context.
@@ -811,16 +806,16 @@
     /**
      * Verifier context constructor
      */
-    vf_Context ():m_class( NULL ), m_type( NULL ), m_error( NULL ),
-        m_method( NULL ), m_name(NULL), m_descriptor(NULL), m_graph( NULL ),
-        m_pool( NULL ), m_instr( NULL ), m_last_instr( NULL ), m_retnum( 0 ),
-        m_verify_all( false )
+    vf_Context ():m_class(NULL), m_type(NULL), m_error(NULL),
+        m_method(NULL), m_name(NULL), m_descriptor(NULL), m_graph(NULL),
+        m_pool(NULL), m_instr(NULL), m_last_instr(NULL), m_retnum(0),
+        m_verify_all(false)
     {
         vf_ContextVType zero2 = { 0 };
         m_vtype = zero2;
     }
 
-    void SetMethod( method_handler method )
+    void SetMethod(method_handler method)
     {
         assert(method);
         m_method = method;
@@ -828,27 +823,27 @@
         m_descriptor = method_get_descriptor(method);
 
         // get method parameters
-        m_len = method_get_code_length( method );
-        m_bytes = method_get_bytecode( method );
-        m_handlers = method_get_exc_handler_number( method );
+        m_len = method_get_code_length(method);
+        m_bytes = method_get_bytecode(method);
+        m_handlers = method_get_exc_handler_number(method);
 
         // get method limitations
-        m_maxlocal = method_get_max_local( method );
-        m_maxstack = method_get_max_stack( method );
+        m_maxlocal = method_get_max_local(method);
+        m_maxstack = method_get_max_stack(method);
 
         // cache in the context if the method is a constructor
-        m_is_constructor = (memcmp( m_name, "<init>", 7 ) == 0);
+        m_is_constructor = (memcmp(m_name, "<init>", 7) == 0);
     }
 
     /**
      * Verifier context destructor
      */
-    ~vf_Context ()
+    ~vf_Context()
     {
-        if( m_pool ) {
-            vf_delete_pool( m_pool );
+        if (m_pool) {
+            vf_delete_pool(m_pool);
         }
-        if( m_type ) {
+        if (m_type) {
             delete m_type;
         }
     }
@@ -867,7 +862,7 @@
         m_bc = NULL;
         m_last_instr = NULL;
         m_retnum = 0;
-        vf_clean_pool( m_pool );
+        vf_clean_pool(m_pool);
     }                           // vf_ClearContext
 
   public:
@@ -892,13 +887,13 @@
     unsigned short m_maxstack;  ///< max stack length
     unsigned short m_maxlocal;  ///< max local number
     bool m_is_constructor;      ///< <code>true</code> if the
-                                ///< method is a constructor
+    ///< method is a constructor
 
     // Subrotine info
-    vf_SubContext *m_sub_ctx;           ///< aggregate subroutine info
-    vf_MapVector *m_map;                ///< a stack map for control flow
-                                        ///< analysis, vectors themselves are
-                                        ///< allocated from the graph pool
+    vf_SubContext *m_sub_ctx;   ///< aggregate subroutine info
+    vf_MapVector *m_map;        ///< a stack map for control flow
+    ///< analysis, vectors themselves are
+    ///< allocated from the graph pool
     vf_MapEntry *m_method_invector;     ///< method parameters
     unsigned short m_method_inlen;      ///< a length of <code>m_method_invector</code>
     vf_MapEntry *m_method_outvector;    ///< method return value
@@ -906,7 +901,7 @@
 
     // Data flow analisys info
     vf_MapEntry *m_buf;         ///< used to store intermediate stack states
-                                ///< during data flow analysis
+    ///< during data flow analysis
 
     bool m_verify_all;          ///< if <code>true</code> need to verify more checks
 
@@ -915,11 +910,11 @@
      */
     struct vf_ContextVType
     {
-        vf_ValidType *m_class;          ///< a given class
+        vf_ValidType *m_class;  ///< a given class
         vf_ValidType *m_throwable;      ///< java/lang/Throwable
-        vf_ValidType *m_object;         ///< java/lang/Object
-        vf_ValidType *m_array;          ///< [Ljava/lang/Object;
-        vf_ValidType *m_clone;          ///< java/lang/Cloneable
+        vf_ValidType *m_object; ///< java/lang/Object
+        vf_ValidType *m_array;  ///< [Ljava/lang/Object;
+        vf_ValidType *m_clone;  ///< java/lang/Cloneable
         vf_ValidType *m_serialize;      ///< java/io/Serializable
     } m_vtype;
 
@@ -961,7 +956,7 @@
  * @see vf_Context
  * @see vf_Result
  */
-vf_Result vf_create_graph( vf_Context *ctx );
+vf_Result vf_create_graph(vf_Context *ctx);
 
 /**
  * Checks control flow and data flow of graph.
@@ -970,7 +965,7 @@
  *
  * @return a result of graph checks
  */
-vf_Result vf_check_graph( vf_Context *ctx );
+vf_Result vf_check_graph(vf_Context *ctx);
 
 /**
  * Provides data flow checks of verifier graph structure.
@@ -979,7 +974,7 @@
  * @see vf_Context
  * @see vf_Result
  */
-vf_Result vf_check_graph_data_flow( vf_Context *ctx );
+vf_Result vf_check_graph_data_flow(vf_Context *ctx);
 
 /**
  * Parses method, class or field descriptors.
@@ -989,8 +984,8 @@
  * @note Assertion is raised if <i>descr</i> or <i>inlen</i> are equal to <code>NULL</code>.
  * @note Parameter <i>outlen</i> may be equal to null (for class or field descriptor).
  */
-void vf_parse_description( const char *descr, unsigned short *inlen,
-                           unsigned short *outlen );
+void vf_parse_description(const char *descr, unsigned short *inlen,
+                          unsigned short *outlen);
 
 /**
  * Parses a descriptor and sets input and output data flow vectors.
@@ -1008,12 +1003,12 @@
  *       if parameter <i>outlen</i> is equal to zero.
  */
 void
-vf_set_description_vector( const char *descr,
-                           unsigned short inlen,
-                           unsigned short add,
-                           unsigned short outlen,
-                           vf_MapEntry **invector,
-                           vf_MapEntry **outvector, vf_ContextHandle ctx );
+vf_set_description_vector(const char *descr,
+                          unsigned short inlen,
+                          unsigned short add,
+                          unsigned short outlen,
+                          vf_MapEntry **invector,
+                          vf_MapEntry **outvector, vf_ContextHandle ctx);
 
 /**
  * Gets a class name from a constant pool.
@@ -1023,12 +1018,12 @@
  *
  * @return a pointer to UTF8 constant pool entry
  */
-static inline const char *
-vf_get_cp_class_name( class_handler klass, unsigned short index )
+static inline const char *vf_get_cp_class_name(class_handler klass,
+                                               unsigned short index)
 {
     unsigned short class_name_index =
-        class_get_cp_class_name_index( klass, index );
-    const char *name = class_get_cp_utf8_bytes( klass, class_name_index );
+        class_get_cp_class_name_index(klass, index);
+    const char *name = class_get_cp_utf8_bytes(klass, class_name_index);
     return name;
 }                               // vf_get_cp_class_name
 
@@ -1038,8 +1033,8 @@
  * @param ctx    a verifier context
  * @return a valid type structure corresponding to the given class name
  */
-vf_ValidType *vf_create_class_valid_type( const char *class_name,
-                                          vf_ContextHandle ctx );
+vf_ValidType *vf_create_class_valid_type(const char *class_name,
+                                         vf_ContextHandle ctx);
 
 /**
  * Provides constraint checks for current class.
@@ -1050,7 +1045,7 @@
  * @see vf_Context
  * @see vf_Result
  */
-vf_Result vf_check_class_constraints( vf_Context *ctx );
+vf_Result vf_check_class_constraints(vf_Context *ctx);
 
 /**
  * Function compares two valid types.
@@ -1059,7 +1054,7 @@
  * @return If types are equal returns <code>true</code>, else returns <code>false</code>.
  * @see vf_ValidType
  */
-bool vf_is_types_equal( vf_ValidType *type1, vf_ValidType *type2 );
+bool vf_is_types_equal(vf_ValidType *type1, vf_ValidType *type2);
 
 /**
  * Checks access to protected field/method.
@@ -1077,11 +1072,11 @@
  * @see vf_Context
  * @see vf_Result
  */
-vf_Result vf_check_access_constraint( const char *super_name,   // name of super class
-                                      const char *instance_name,        // name of instance class
-                                      unsigned short index,     // constant pool index
-                                      vf_CheckConstraint check_type,    // access check type
-                                      vf_Context *ctx );        // verification context
+vf_Result vf_check_access_constraint(const char *super_name,    // name of super class
+                                     const char *instance_name, // name of instance class
+                                     unsigned short index,      // constant pool index
+                                     vf_CheckConstraint check_type,     // access check type
+                                     vf_Context *ctx);  // verification context
 
 /**
  * Sets error message of a verifier.
@@ -1090,17 +1085,17 @@
  * @param[in] ctx   a verifier context
  */
 static inline void
-vf_set_error_message( stringstream & stream, vf_Context *ctx )
+vf_set_error_message(stringstream & stream, vf_Context *ctx)
 {
-    if( ctx->m_error ) {
+    if (ctx->m_error) {
         // free old message
-        vf_free( ctx->m_error );
+        vf_free(ctx->m_error);
     }
     // create message
     size_t len = stream.str().length();
-    if( len ) {
-        ctx->m_error = (char*)vf_malloc( len + 1 );
-        memcpy( ctx->m_error, stream.str().c_str(), len );
+    if (len) {
+        ctx->m_error = (char *) vf_malloc(len + 1);
+        memcpy(ctx->m_error, stream.str().c_str(), len);
         ctx->m_error[len] = '\0';
     } else {
         ctx->m_error = NULL;
@@ -1114,10 +1109,9 @@
  *
  * @return <code>true</code> if a class version is less than 1.4
  */
-static inline bool
-vf_is_class_version_14( vf_ContextHandle ctx )
+static inline bool vf_is_class_version_14(vf_ContextHandle ctx)
 {
-    return ( class_get_version( ctx->m_class ) < 49 ) ? true : false;
+    return (class_get_version(ctx->m_class) < 49) ? true : false;
 }                               // vf_is_class_version_14
 
 /**
@@ -1130,9 +1124,9 @@
  * branches
  */
 static inline int
-vf_get_instr_branch( vf_InstrHandle instr, unsigned branch_num )
+vf_get_instr_branch(vf_InstrHandle instr, unsigned branch_num)
 {
-    assert( branch_num < instr->m_offcount );
+    assert(branch_num < instr->m_offcount);
     return instr->m_off[branch_num];
 }                               // vf_get_instruction_branch
 
@@ -1144,11 +1138,10 @@
  * @param[in]  pool   memory pool
  */
 static inline void
-vf_new_vector( vf_MapEntry **vector, unsigned len, vf_Pool *pool )
+vf_new_vector(vf_MapEntry **vector, unsigned len, vf_Pool *pool)
 {
     // create new vector
-    ( *vector ) =    (vf_MapEntry*)vf_palloc( pool,
-                                              len * sizeof( vf_MapEntry ) );
+    (*vector) = (vf_MapEntry *) vf_palloc(pool, len * sizeof(vf_MapEntry));
 }                               // vf_new_vector
 
 /**
@@ -1159,8 +1152,8 @@
  * @param[in]      type   reference type
  */
 static inline void
-vf_set_vector_stack_entry_ref( vf_MapEntry *vector,
-                               unsigned num, vf_ValidType *type )
+vf_set_vector_stack_entry_ref(vf_MapEntry *vector,
+                              unsigned num, vf_ValidType *type)
 {
     // set a stack map vector entry by ref
     vector[num].m_type = SM_REF;
@@ -1174,9 +1167,9 @@
  * @return    an instruction index
  */
 static inline unsigned
-vf_get_instr_index( vf_InstrHandle instr, vf_ContextHandle ctx )
+vf_get_instr_index(vf_InstrHandle instr, vf_ContextHandle ctx)
 {
-    return ( unsigned )( instr - ctx->m_instr );
+    return (unsigned) (instr - ctx->m_instr);
 }
 
 /**
@@ -1186,11 +1179,11 @@
  * @return    an instruction index
  */
 static inline unsigned
-vf_bc_to_instr_index( unsigned short pc, vf_ContextHandle ctx )
+vf_bc_to_instr_index(unsigned short pc, vf_ContextHandle ctx)
 {
     vf_InstrHandle instr = ctx->m_bc[pc].m_instr;
-    assert( instr );
-    return vf_get_instr_index( instr, ctx );
+    assert(instr);
+    return vf_get_instr_index(instr, ctx);
 }
 
 /**
@@ -1200,13 +1193,13 @@
  * @param[in] ctx   a verification context
  * @return a pointer which follows a given instruction
  */
-static inline const unsigned char *
-vf_get_instr_end( vf_InstrHandle instr, vf_ContextHandle ctx )
+static inline const unsigned char *vf_get_instr_end(vf_InstrHandle instr,
+                                                    vf_ContextHandle ctx)
 {
-    if( instr + 1 == ctx->m_last_instr ) {
+    if (instr + 1 == ctx->m_last_instr) {
         return ctx->m_bytes + ctx->m_len;
     }
-    return ( instr + 1 )->m_addr;
+    return (instr + 1)->m_addr;
 }
 
 /**
@@ -1214,7 +1207,7 @@
  *
  * @param[in] context a context of verifier
  */
-void vf_free_graph( vf_Context *context );
+void vf_free_graph(vf_Context *context);
 
 /**
  * Mark subroutine code.
@@ -1226,18 +1219,18 @@
  * page</a>.</p>
  *
  * @param ctx a verifier context
- * @return VER_OK if no graph structure inconsistencies were detected during marking,
+ * @return VF_OK if no graph structure inconsistencies were detected during marking,
  * an error code otherwise
  */
-vf_Result vf_mark_subroutines( vf_Context *ctx );
+vf_Result vf_mark_subroutines(vf_Context *ctx);
 
 /**
  * Inline subroutines in the call graph.
  *
  * @param ctx a verifier context
- * @return VER_OK if subroutines were inlined successfully,
+ * @return VF_OK if subroutines were inlined successfully,
  * an error code otherwise
  */
-vf_Result vf_inline_subroutines( vf_Context *ctx );
+vf_Result vf_inline_subroutines(vf_Context *ctx);
 
-#endif // _VERIFIER_REAL_H_
+#endif // _VF_REAL_H_

Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier/ver_subroutine.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier/ver_subroutine.cpp?view=diff&rev=546915&r1=546914&r2=546915
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier/ver_subroutine.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier/ver_subroutine.cpp Wed Jun 13 08:17:09 2007
@@ -26,16 +26,17 @@
  */
 unsigned vf_get_sub_num(vf_SubHandle sub, vf_ContextHandle ctx)
 {
-    unsigned index = 0;
     for (vf_SubHandle s = ctx->m_sub_ctx->m_sub; s; s = s->m_next) {
         if (s == sub) {         // subroutine found
+            unsigned index = 0;
+            while (s = s->m_next)
+                index++;
             return index;
         }
-        index++;
     }
     VF_DIE("vf_get_sub_num: Cannot find a subroutine " << sub <<
-        " in a list");
-    return 0;
+           " in a list");
+    return ALL_BITS_SET;
 }
 
 void vf_Graph::DumpSub(vf_SubHandle sub)
@@ -58,18 +59,12 @@
 static void DumpNodeStack(vf_Context *ctx)
 {
     vf_NodeStackHandle p_element = ctx->m_sub_ctx->m_path_start;
-    bool fork_found = false;
     unsigned count = 0;
 
     VF_DEBUG("Dumping path: ");
     for (; p_element; p_element = p_element->m_next, count++) {
-        if (p_element == ctx->m_sub_ctx->m_path_fork) {
-            fork_found = true;
-            VF_DEBUG("Fork");
-        }
         VF_DEBUG("  Node #" << ctx->m_graph->GetNodeNum(p_element->m_node));
     }
-    assert(fork_found || !ctx->m_sub_ctx->m_path_fork);
     VF_DEBUG("Totally " << count << " nodes");
 }                               // DumpNodeStack
 #endif //  _VF_DEBUG
@@ -84,9 +79,13 @@
     vf_Pool *pool = ctx->m_pool;
 
     vf_SubContext *sub_ctx = (vf_SubContext *) vf_palloc(pool,
-        sizeof(vf_SubContext));
+                                                         sizeof
+                                                         (vf_SubContext));
     ctx->m_sub_ctx = sub_ctx;
     sub_ctx->m_pool = pool;
+    sub_ctx->m_tmpmap = (vf_MapVector *) vf_palloc(pool,
+                                                   sizeof(vf_MapVector));
+    ctx->m_graph->AllocVector(sub_ctx->m_tmpmap);
 }                               // AllocateSubContext
 
 
@@ -96,7 +95,7 @@
  * @param[in] sub_ctx  a subroutine verification context
  * @return a sub handle
  */
-static vf_Sub *AddNewSub(vf_NodeHandle ret_node, vf_SubContext * sub_ctx)
+static vf_Sub *AddNewSub(vf_NodeHandle ret_node, vf_SubContext *sub_ctx)
 {
     vf_Sub *sub = (vf_Sub *) vf_palloc(sub_ctx->m_pool, sizeof(vf_Sub));
     sub->m_next = sub_ctx->m_sub;
@@ -120,45 +119,156 @@
     sub->m_out_edgenum += node->m_outnum;
 }                               // AddSubNode
 
-static inline vf_Result ResolveSubroutineEntryPoint(vf_Node *node,
-    vf_Context *ctx)
+/**
+ * Updates a stack map following a path through a subroutine.
+ * @param sub   a sub to update a map
+ * @param ctx   a verification context
+ */
+static inline void UpdateStackMapWithSub(vf_SubHandle sub, vf_Context *ctx)
 {
-    //initialize vector
     vf_MapVector *map = ctx->m_map;
+    vf_MapVector *outmap = sub->m_outmap;
+    vf_MapVector *tmpmap = ctx->m_sub_ctx->m_tmpmap;
 
-    // the path element node to iterate from
-    vf_NodeStackHandle p_element = ctx->m_sub_ctx->m_path_fork;
-    if (!p_element) {
-        p_element = ctx->m_sub_ctx->m_path_start;
-        map->m_number = ctx->m_maxlocal;
-        unsigned index;
-        for (index = 0; index < map->m_number; index++) {
-            map->m_local[index].m_type = SM_ANY;
-            map->m_local[index].m_is_local = true;
-            map->m_local[index].m_local = index;
-        }
-
-        map->m_depth = p_element->m_node->m_inmap.m_depth;
-        // FIXME - stack depth should be greater then 0
-        // assert(map->m_depth);
-        for (index = 0; index + 1 < map->m_depth; index++) {
-            map->m_stack[index].m_type = SM_ANY;
-        }
-        map->m_stack[index].m_type = SM_RETURN_ADDR;
-        map->m_stack[index++].m_pc =
-            (unsigned) (p_element->m_node->m_start->m_addr - ctx->m_bytes);
-        // FIXME - index should be equal to stack depth
-        // assert(index == map->m_depth);
-        for (; index < ctx->m_maxstack; index++) {
-            map->m_stack[index].m_type = SM_TOP;
+    tmpmap->m_number = outmap->m_number;
+    tmpmap->m_depth = outmap->m_depth;
+
+
+    VF_DUMP(DUMP_MERGE_MAP, {
+            // dump out vectors
+            cerr << "============== merging OUT map of subroutine #"
+            << vf_get_sub_num(sub, ctx) << endl;
+            cerr << "calling node IN vector:" << endl;
+            vf_dump_vector(map, NULL, &cerr);
+            cerr << "subroutine OUT vector:" << endl;
+            vf_dump_vector(outmap, NULL, &cerr);}
+    );
+
+    unsigned short index;
+    vf_MapEntry *map_entry = map->m_local;
+    vf_MapEntry *outmap_entry = outmap->m_local;
+    vf_MapEntry *tmpmap_entry = tmpmap->m_local;
+
+    // merge local variable vector
+    for (index = 0; index < outmap->m_number;
+         index++, map_entry++, outmap_entry++, tmpmap_entry++) {
+        // merge entries type
+        vf_MapEntry *result_entry;
+        if (SM_RETURN_ADDR == outmap_entry->m_type
+            && SM_RETURN_ADDR == map_entry->m_type) {
+            // the return address in local
+            // local variable might be overridden only using a value from
+            // the stack, and input stacks for the subroutine should be
+            // the same, hence in this case the value will be overridden 
+            // with the same value
+            result_entry = map_entry;
+        } else if (SM_ANY != outmap_entry->m_type) {
+            result_entry = outmap_entry;
+        } else if (outmap_entry->m_mappos < ctx->m_maxlocal) {
+            result_entry = map->m_local + outmap_entry->m_mappos;
+        } else {
+            result_entry =
+                map->m_stack + (outmap_entry->m_mappos - ctx->m_maxlocal);
         }
-    }
+        tmpmap_entry->m_type = result_entry->m_type;
+        tmpmap_entry->m_vtype = result_entry->m_vtype;
+        tmpmap_entry->m_new = result_entry->m_new;
+    }
+
+    // merge stack map vector
+    map_entry = map->m_stack;
+    outmap_entry = outmap->m_stack;
+    tmpmap_entry = tmpmap->m_stack;
+    for (index = 0; index < outmap->m_depth;
+         index++, map_entry++, outmap_entry++, tmpmap_entry++) {
+        // merge entries type
+        vf_MapEntry *result_entry;
+        if (SM_ANY != outmap_entry->m_type) {
+            result_entry = outmap_entry;
+        } else if (outmap_entry->m_mappos < ctx->m_maxlocal) {
+            result_entry = map->m_local + outmap_entry->m_mappos;
+        } else {
+            result_entry =
+                map->m_stack + (outmap_entry->m_mappos - ctx->m_maxlocal);
+        }
+        tmpmap_entry->m_type = result_entry->m_type;
+        tmpmap_entry->m_vtype = result_entry->m_vtype;
+        tmpmap_entry->m_new = result_entry->m_new;
+    }
+
+    VF_DUMP(DUMP_MERGE_MAP, {
+            // dump out vectors
+            cerr << "============== result map" << endl;
+            vf_dump_vector(tmpmap, NULL, &cerr);}
+    );
 
+    ctx->m_graph->CopyFullVector(tmpmap, map);
+    return;
+}
+
+/**
+ * Initializes path and a stack map with <code>SM_RETURN_ADDR</code> and
+ * <code>SM_ANY</code> values if the map is not yet initialized.
+ * @param stack a reference of a stack for the end node of the <code>jsr</code> edge
+ * @param ctx   a verification context
+ */
+static inline void EnsureStackMapInitialized(vf_Context *ctx)
+{
     VF_DUMP(DUMP_NODESTACK, DumpNodeStack(ctx));
+
+    if (ctx->m_sub_ctx->m_path_map_initialized) {
+        return;
+    }
+    vf_MapVector *map = ctx->m_map;
+    map->m_number = ctx->m_maxlocal;
+    unsigned mappos = 0;
+    unsigned index;
+    for (index = 0; index < map->m_number; index++) {
+        map->m_local[index].m_type = SM_ANY;
+        map->m_local[index].m_mappos = mappos++;
+        map->m_local[index].m_is_local = true;
+        map->m_local[index].m_local = index;
+    }
+
+    map->m_depth = ctx->m_sub_ctx->m_path_start->m_node->m_inmap.m_depth;
+    assert(map->m_depth);
+    mappos = ctx->m_maxlocal;
+    for (index = 0; index + 1 < map->m_depth; index++) {
+        map->m_stack[index].m_type = SM_ANY;
+        map->m_stack[index].m_mappos = mappos++;
+    }
+    map->m_stack[index].m_type = SM_RETURN_ADDR;
+    map->m_stack[index++].m_pc =
+        (unsigned) (ctx->m_sub_ctx->m_path_start->m_node->m_start->m_addr -
+                    ctx->m_bytes);
+    assert(index == map->m_depth);
+    for (; index < ctx->m_maxstack; index++) {
+        map->m_stack[index].m_type = SM_TOP;
+    }
+    ctx->m_sub_ctx->m_path_map_initialized = true;
+}
+
+/**
+ * @param[in] node a node, which contains <code>ret</code> instruction
+ * @param[in] ctx  a verification context
+ * @return VF_OK if marking was successful, an error code in case of data flow
+ * error
+ */
+static inline vf_Result ResolveSubroutineEntryPoint(vf_Node *node,
+                                                    vf_Context *ctx)
+{
+    // initialize a vector shortcut
+    vf_MapVector *map = ctx->m_map;
+
+    // the path element node to iterate from
+    vf_NodeStackHandle p_element = ctx->m_sub_ctx->m_path_start;
+
+    EnsureStackMapInitialized(ctx);
     for (; p_element; p_element = p_element->m_next) {
+        assert(p_element);
         vf_Result result =
             vf_set_node_out_vector(p_element->m_node, map, ctx);
-        if (result != VER_OK) {
+        if (VF_OK != result) {
             return result;
         }
     }
@@ -166,12 +276,24 @@
     // since a copy flag is set for SM_RETURN_ADDR entries,
     // <code>ctx->m_buf</code> contains the last processed entry, i.&nbsp;e.
     // an entry for <code>ret</code>
-    assert(ctx->m_buf->m_pc);
+    unsigned entry_pc = ctx->m_buf->m_pc;
+    // subroutine cannot start at zero instruction
+    assert(entry_pc);
     assert(SM_RETURN_ADDR == ctx->m_buf->m_type);
     assert(node->m_outmap.m_depth == ctx->m_map->m_depth);
-    ((vf_Sub *) node->m_sub)->m_entry =
-        ctx->m_graph->GetNodeFromBytecodeIndex(ctx->m_buf->m_pc);
-    return VER_OK;
+
+    vf_NodeHandle entry = ctx->m_graph->GetNodeFromBytecodeIndex(entry_pc);
+
+    vf_Sub *sub = (vf_Sub *) node->m_sub;
+    sub->m_entry = entry;
+
+    // store the out map of the node
+    // TODO may be skipped for subroutines which have less than two calls to them
+    sub->m_outmap = (vf_MapVector *) vf_palloc(ctx->m_sub_ctx->m_pool,
+                                               sizeof(vf_MapVector));
+    ctx->m_graph->AllocVector(sub->m_outmap);
+    ctx->m_graph->CopyVector(ctx->m_map, sub->m_outmap);
+    return VF_OK;
 }                               // ResolveSubroutineEntryPoint
 
 static vf_Result MarkNode(vf_NodeStack &stack, vf_Context *ctx);
@@ -183,23 +305,23 @@
  * @param[in] node a node which is a part of a subroutine
  * @param[in,out] ctx a verification context
  * @return if the mark of this node is already set and is not equal to 
- * <code>sub</code>, <code>VER_ErrorJsrMultipleRet</code> is reported
+ * <code>sub</code>, <code>VF_ErrorJsrMultipleRet</code> is reported
  */
 static inline vf_Result
 SetSubMarks(vf_SubHandle sub, vf_Node *node, vf_Context *ctx)
 {
     assert(sub);
     VF_TRACE("sub.mark", "sub[" << ctx->m_graph->GetNodeNum(node)
-        << "] := sub[" << ctx->m_graph->GetNodeNum(sub->m_ret)
-        << "] (" << vf_get_sub_num(sub, ctx) << ")");
+             << "] := sub[" << ctx->m_graph->GetNodeNum(sub->m_ret)
+             << "] (" << vf_get_sub_num(sub, ctx) << ")");
     if (node->m_sub == sub) {
-        return VER_OK;          // already marked
+        return VF_OK;           // already marked
     }
 
     if (NULL == node->m_sub) {
         if (node == ctx->m_graph->GetStartNode()) {
             VF_REPORT(ctx, "Reached ret not using jsr branches");
-            return VER_ErrorJsrOther;
+            return VF_ErrorJsrOther;
         }
 
         node->m_sub = sub;
@@ -208,88 +330,172 @@
             AddSubNode(node);
         }
         for (vf_EdgeHandle inedge = node->m_inedge;
-            inedge; inedge = inedge->m_innext) {
+             inedge; inedge = inedge->m_innext) {
+            VF_TRACE("edge", "Marking subroutines: following edge #"
+                     << ctx->m_graph->GetNodeNum(inedge->m_start) << " -> #"
+                     << ctx->m_graph->GetNodeNum(inedge->m_end));
             if (vf_is_jsr_branch(inedge, ctx)) {
+                VF_TRACE("edge", "    This is jsr edge, skipping");
                 continue;
             }
             vf_Result result =
                 SetSubMarks(sub, (vf_Node *) inedge->m_start, ctx);
-            if (result != VER_OK) {
+            if (VF_OK != result) {
                 return result;
             }
         }
-        return VER_OK;
+        return VF_OK;
     }
 
     assert(node->m_sub != sub);
     VF_REPORT(ctx,
-        "A subroutine splits execution into several ret instructions");
-    return VER_ErrorJsrMultipleRet;
+              "A subroutine splits execution into several ret instructions");
+    return VF_ErrorJsrMultipleRet;
 }                               // SetSubMarks
 
 /**
  * Marks a <code>jsr</code> edge end node. If the subroutine returns, marks a node, which
  * follows the edge start node.
+ * @param node  a start node for the <code>jsr</code> edge
+ * @param stack a reference of a stack for the end node of the <code>jsr</code> edge
+ * @param ctx   a verification context
+ * @return VF_OK if marking was successful, an error code in case of data flow
+ * error
  */
 static inline vf_Result
 FollowJsrEdge(vf_Node *node, vf_NodeStack &stack, vf_Context *ctx)
 {
     vf_NodeStackHandle path_start = ctx->m_sub_ctx->m_path_start;
-    if (!path_start) {
-        ctx->m_sub_ctx->m_path_start = &stack;
+    bool path_initialized = ctx->m_sub_ctx->m_path_map_initialized;
+
+    VF_TRACE("edge", "Following jsr edge #"
+             << ctx->m_graph->GetNodeNum(node) << " -> #"
+             << ctx->m_graph->GetNodeNum(stack.m_node));
+
+    if (stack.m_node->m_mark) {
+        // FIXME subroutine node copies might have different stack maps, though
+        // this is not a security threat, just incompatibility with RI.
+        if (path_start) {
+            if (!stack.m_node->m_sub) {
+                // we assume that the branch is to the top
+                // level code, or the same subroutine, so there
+                // is no return
+                return VF_OK;
+            }
+
+            if (stack.m_node->m_sub->m_entry != stack.m_node) {
+                VF_REPORT(ctx,
+                          "A subroutine splits execution into "
+                          "several ret instructions");
+                return VF_ErrorJsrMultipleRet;
+            }
+
+            EnsureStackMapInitialized(ctx);
+            vf_NodeStackHandle &p_element = ctx->m_sub_ctx->m_path_start;
+            for (; p_element != &stack; p_element = p_element->m_next) {
+                assert(p_element);
+                assert(p_element->m_node->m_inmap.m_depth ==
+                       ctx->m_map->m_depth);
+                vf_Result result =
+                    vf_set_node_out_vector(p_element->m_node, ctx->m_map,
+                                           ctx);
+                if (VF_OK != result) {
+                    return result;
+                }
+                assert(p_element->m_node->m_outmap.m_depth ==
+                       ctx->m_map->m_depth);
+            }
+            assert(ctx->m_map->m_depth == stack.m_node->m_inmap.m_depth);
+            UpdateStackMapWithSub(stack.m_node->m_sub, ctx);
+        }
+    } else {
+        if (!path_start) {
+            VF_TRACE("path", "Entering subroutine from the top level code, "
+                     "assigning a node #"
+                     << ctx->m_graph->GetNodeNum(stack.m_node)
+                     << " as a path start");
+            ctx->m_sub_ctx->m_path_start = &stack;
+            ctx->m_sub_ctx->m_path_map_initialized = false;
+        }                       // else continue existing path
     }
 
-    vf_Result r = MarkNode(stack, ctx);
-    if (VER_OK != r) {
-        return r;
+    vf_Result result = MarkNode(stack, ctx);
+    if (VF_OK != result) {
+        return result;
     }
 
-    if (stack.m_node->m_sub->m_entry == stack.m_node) {
+    if (stack.m_node->m_sub && (stack.m_node->m_sub->m_entry == stack.m_node)) {
         // this jsr returns, and we need to process a node which
         // follows after edge start node
-        ctx->m_sub_ctx->m_path_fork = &stack;
+
         // select and check the following node
         stack.Set(node + 1, stack.m_node->m_sub->m_ret->m_outmap.m_depth);
         if (VF_NODE_END_ENTRY == stack.m_node->m_type) {
             VF_REPORT(ctx, "Falling off the end of the code");
-            return VER_ErrorBranch;
+            return VF_ErrorBranch;
         }
         assert(VF_NODE_CODE_RANGE == stack.m_node->m_type);
-        r = MarkNode(stack, ctx);
-        if (VER_OK != r) {
-            return r;
+
+        if (path_start) {
+            VF_TRACE("path", "Continuing a subroutine path at the "
+                     "following node when the nested subroutine returns, "
+                     "assigning a node #"
+                     << ctx->m_graph->GetNodeNum(stack.m_node)
+                     << " as a path start");
+            ctx->m_sub_ctx->m_path_start = &stack;
+            assert(!stack.m_node->m_mark
+                   || (ctx->m_map->m_depth == stack.m_node->m_inmap.m_depth));
+        } else {
+            VF_TRACE("path", "Cleaning a subroutine path at the "
+                     "following node when the subroutine returns to the top code");
+            ctx->m_sub_ctx->m_path_start = NULL;
+        }
+        result = MarkNode(stack, ctx);
+        if (VF_OK != result) {
+            return result;
         }
-        ctx->m_sub_ctx->m_path_fork = NULL;
     }
-
+    // merge subroutines via jsr edge
     if (stack.m_node->m_sub) {
-        r = SetSubMarks(stack.m_node->m_sub, node, ctx);
-        if (VER_OK != r) {
-            return r;
+        VF_TRACE("edge", "Marking subroutines: node #"
+                 << ctx->m_graph->GetNodeNum(node) << " is followed by #"
+                 << ctx->m_graph->GetNodeNum(stack.m_node)
+                 << " which belongs to the sub #"
+                 << vf_get_sub_num(stack.m_node->m_sub, ctx));
+        result = SetSubMarks(stack.m_node->m_sub, node, ctx);
+        if (VF_OK != result) {
+            return result;
         }
     }
 
+    if (path_start) {
+        VF_TRACE("path", "Restoring a node #"
+                 << ctx->m_graph->GetNodeNum(path_start->m_node)
+                 << " as a path start");
+    } else {
+        VF_TRACE("path", "Cleaning the path on return to the top code");
+    }
     ctx->m_sub_ctx->m_path_start = path_start;
-    return r;
+    ctx->m_sub_ctx->m_path_map_initialized = path_initialized;
+    return VF_OK;
 }                               // FollowJsrEdge
 
 /**
  * Marks a given node and follows <i>out</i> edges.
  * @param[in] stack a reference to the stack element for the given node
  * @param[in] ctx   a verification context
- * @return VER_OK if marking was successful, an error code otherwise
+ * @return VF_OK if marking was successful, an error code otherwise
  */
 static vf_Result MarkNode(vf_NodeStack &stack, vf_Context *ctx)
 {
     vf_Graph *graph = ctx->m_graph;
-    vf_Result r;
     vf_Result result =
         vf_check_node_stack_depth(stack.m_node, stack.m_depth, ctx);
-    if (result != VER_Continue) {
+    if (VF_Continue != result) {
         return result;
     }
     VF_TRACE("sub.mark",
-        "Processing node " << graph->GetNodeNum(stack.m_node));
+             "Processing node " << graph->GetNodeNum(stack.m_node));
     if (stack.m_node->m_sub) {
         AddSubNode(stack.m_node);
     }
@@ -297,33 +503,32 @@
     if ((VF_NODE_CODE_RANGE == stack.m_node->m_type)
         && (VF_INSTR_RET == stack.m_node->m_end->m_type)) {
         vf_Sub *sub = AddNewSub(stack.m_node, ctx->m_sub_ctx);
-        r = SetSubMarks(sub, stack.m_node, ctx);
-        if (VER_OK != r) {
-            return r;
-        }
-        r = ResolveSubroutineEntryPoint(stack.m_node, ctx);
-        if (VER_OK != r) {
-            return r;
+        result = SetSubMarks(sub, stack.m_node, ctx);
+        assert(ctx->m_sub_ctx->m_path_start);
+        if (VF_OK != result) {
+            return result;
+        }
+        result = ResolveSubroutineEntryPoint(stack.m_node, ctx);
+        if (VF_OK != result) {
+            return result;
         }
     }
 
     vf_NodeStack next_stack;
     stack.m_next = &next_stack;
     for (vf_EdgeHandle outedge = stack.m_node->m_outedge;
-        outedge; outedge = outedge->m_outnext) {
+         outedge; outedge = outedge->m_outnext) {
         next_stack.Set(outedge->m_end, stack.m_depth);
         if (!vf_is_jsr_branch(outedge, ctx)) {
-            r = MarkNode(next_stack, ctx);
+            result = MarkNode(next_stack, ctx);
         } else {
-            assert(VF_NODE_CODE_RANGE == outedge->m_end->m_type);
-            assert(!outedge->m_outnext);
-            r = FollowJsrEdge(stack.m_node, next_stack, ctx);
+            result = FollowJsrEdge(stack.m_node, next_stack, ctx);
         }
-        if (VER_OK != r) {
-            return r;
+        if (VF_OK != result) {
+            return result;
         }
     }
-    return VER_OK;
+    return VF_OK;
 }                               // MarkNode
 
 
@@ -334,25 +539,25 @@
     vf_NodeStack bottom = {
         (vf_Node *) ctx->m_graph->GetStartNode(), 0, NULL
     };
-    vf_Result r = MarkNode(bottom, ctx);
-    return r;
+    vf_Result result = MarkNode(bottom, ctx);
+    return result;
 }                               // vf_mark_subroutines
 
 static vf_Result AddDupCount(vf_Sub *sub, unsigned &count, vf_Context *ctx)
 {
     VF_TRACE("dupcount",
-        "Calculating a duplication count for a subroutine #" <<
-        vf_get_sub_num(sub, ctx));
+             "Calculating a duplication count for a subroutine #" <<
+             vf_get_sub_num(sub, ctx));
     if (ALL_BITS_SET == sub->m_dupcount) {
         VF_REPORT(ctx, "Found a recursive subroutine call sequence");
-        return VER_ErrorJsrRecursive;
+        return VF_ErrorJsrRecursive;
     }
 
     if (!sub->m_dupcount) {
         sub->m_dupcount = ALL_BITS_SET;
         unsigned sum = 0;
         for (vf_EdgeHandle inedge = sub->m_entry->m_inedge;
-            inedge; inedge = inedge->m_innext) {
+             inedge; inedge = inedge->m_innext) {
             vf_NodeHandle node = inedge->m_start;
             if (vf_is_jsr_branch(inedge, ctx)) {
                 assert(!inedge->m_outnext);
@@ -363,19 +568,20 @@
                 }               // else this call served as unconditional internal branch
             } else if (node->m_sub != sub) {
                 VF_REPORT(ctx,
-                    "A subroutine splits execution into "
-                    "several ret instructions");
-                return VER_ErrorJsrMultipleRet;
+                          "A subroutine splits execution into "
+                          "several ret instructions");
+                return VF_ErrorJsrMultipleRet;
             }
         }
         sub->m_dupcount = sum;
     }
 
     VF_TRACE("dupcount",
-        "A duplication count for a subroutine #" << vf_get_sub_num(sub,
-            ctx) << " is " << sub->m_dupcount);
+             "A duplication count for a subroutine #" << vf_get_sub_num(sub,
+                                                                        ctx)
+             << " is " << sub->m_dupcount);
     count += sub->m_dupcount;
-    return VER_OK;
+    return VF_OK;
 }                               // AddSubDupCount
 
 static void InlineSubNodes(vf_ContextHandle ctx)
@@ -385,7 +591,8 @@
     for (sub = ctx->m_sub_ctx->m_sub; sub; sub = sub->m_next) {
         sub->m_nodes =
             (vf_NodeHandle *) vf_palloc(ctx->m_sub_ctx->m_pool,
-            sub->m_nodenum * sizeof(vf_NodeHandle));
+                                        sub->m_nodenum *
+                                        sizeof(vf_NodeHandle));
     }
 
     // populate subroutine node get the next node after the start node
@@ -411,16 +618,16 @@
         vf_Node *new_node = sub->m_copies =
             graph->AddNodes((sub->m_dupcount - 1) * sub->m_nodenum);
         for (unsigned node_index = 0; node_index < sub->m_nodenum;
-            node_index++, p_node++) {
+             node_index++, p_node++) {
             for (unsigned index = 1; index < sub->m_dupcount;
-                index++, new_node++) {
+                 index++, new_node++) {
                 *new_node = **p_node;
                 // edges are outdated, delete them
                 new_node->m_inedge = new_node->m_outedge = NULL;
                 new_node->m_outnum = 0;
                 VF_TRACE("sub.inline",
-                    "Copied node " << graph->GetNodeNum(*p_node)
-                    << " to " << graph->GetNodeNum(new_node));
+                         "Copied node " << graph->GetNodeNum(*p_node)
+                         << " to " << graph->GetNodeNum(new_node));
             }
         }
     }
@@ -436,10 +643,10 @@
     for (vf_SubHandle sub = ctx->m_sub_ctx->m_sub; sub; sub = sub->m_next) {
         ((vf_Sub *) sub)->m_following_nodes =
             (vf_Node **) vf_palloc(ctx->m_sub_ctx->m_pool,
-            sub->m_dupcount * sizeof(vf_Node *));
+                                   sub->m_dupcount * sizeof(vf_Node *));
         vf_NodeHandle sub_entry_copy =
             sub->m_copies + sub->m_entry->m_nodecount * (sub->m_dupcount -
-            1) - 1;
+                                                         1) - 1;
         vf_EdgeHandle *p_next_edge =
             (vf_EdgeHandle *) & sub->m_entry->m_inedge;
         vf_Edge *inedge = (vf_Edge *) sub->m_entry->m_inedge;
@@ -479,10 +686,10 @@
         }
         vf_Node *copy = sub->m_copies;
         for (unsigned node_index = 0; node_index < sub->m_nodenum;
-            node_index++, copy += sub->m_dupcount - 1) {
+             node_index++, copy += sub->m_dupcount - 1) {
             vf_NodeHandle node = sub->m_nodes[node_index];
             for (vf_EdgeHandle outedge = node->m_outedge; outedge;
-                outedge = outedge->m_outnext) {
+                 outedge = outedge->m_outnext) {
                 vf_NodeHandle end_node = outedge->m_end;
                 vf_SubHandle end_sub = end_node->m_sub;
                 vf_Node *c = copy;
@@ -506,13 +713,13 @@
                     // a node next to the start node
                     vf_Node *n = c + (sub->m_dupcount - 1);
                     for (unsigned index = 1;
-                        index < node->m_sub->m_dupcount; index++) {
+                         index < node->m_sub->m_dupcount; index++) {
                         // direct jsr edge to correspondent subroutine copy
                         graph->NewEdge(c++, e + end_sub->m_index);
                         // store return point
                         assert(VF_NODE_CODE_RANGE == n->m_type);
                         end_sub->m_following_nodes[((vf_Sub *) end_sub)->
-                            m_index++] = n++;
+                                                   m_index++] = n++;
                     }
                 }
             }
@@ -563,15 +770,15 @@
 {
     if (NULL == ctx->m_sub_ctx->m_sub) {
         // subroutines are not reachable
-        return VER_OK;
+        return VF_OK;
     }
 
     unsigned count;
     unsigned nodes = 0, edges = 0;
     for (vf_Sub *sub = ctx->m_sub_ctx->m_sub; sub; sub = sub->m_next) {
-        vf_Result r = AddDupCount(sub, count, ctx);
-        if (VER_OK != r) {
-            return r;
+        vf_Result result = AddDupCount(sub, count, ctx);
+        if (VF_OK != result) {
+            return result;
         }
         // one copy already present in the graph
         nodes += (sub->m_dupcount - 1) * sub->m_nodenum;
@@ -591,5 +798,5 @@
 
     CheckDupCounts(ctx);
     InlineRetEdges(ctx);
-    return VER_OK;
+    return VF_OK;
 }                               // vf_inline_subroutines

Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier/ver_subroutine.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier/ver_subroutine.h?view=diff&rev=546915&r1=546914&r2=546915
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier/ver_subroutine.h (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier/ver_subroutine.h Wed Jun 13 08:17:09 2007
@@ -14,6 +14,9 @@
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  */
+#ifndef _VF_SUBROUTINE_H_
+#define _VF_SUBROUTINE_H_
+
 #include "ver_graph.h"
 
 /**
@@ -77,6 +80,10 @@
      * A current duplication index.
      */
     unsigned m_index;
+    /**
+     * An OUT stack map of the <code>ret</code> node.
+     */
+    vf_MapVector *m_outmap;
 };
 
 /**
@@ -125,10 +132,12 @@
      */
     vf_NodeStackHandle m_path_start;
     /**
-     * After the <code>ret</code> is resolved a <code>ctx->m_map</code> contains a
-     * correct input map for a node which follows <code>jsr</code> call. This is
-     * a pointer to the corresponding node stack. If this pointer is
-     * <code>NULL</code> we start from <code>m_path_start</code> stack entry.
+     * Equals to <code>true</code> when the map gets initialized.
+     */
+    bool m_path_map_initialized;
+    /**
+     * A temporary map for subroutine data flow analysis.
      */
-    vf_NodeStackHandle m_path_fork;
+    vf_MapVector *m_tmpmap;
 };
+#endif // _VF_SUBROUTINE_H_