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. 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_