Common subdirectories: 9/trunk/working_vm/vm/vmcore/src/verifier/.svn and 91/trunk/working_vm/vm/vmcore/src/verifier/.svn diff -pu 9/trunk/working_vm/vm/vmcore/src/verifier/Graph.cpp 91/trunk/working_vm/vm/vmcore/src/verifier/Graph.cpp --- 9/trunk/working_vm/vm/vmcore/src/verifier/Graph.cpp 2007-03-20 18:34:52.251548100 +0300 +++ 91/trunk/working_vm/vm/vmcore/src/verifier/Graph.cpp 2007-03-21 04:10:18.189579200 +0300 @@ -22,265 +22,6 @@ #include "ver_real.h" #include "ver_graph.h" -/** - * Function evaluates stack depth of graph node. - */ -static int vf_get_node_stack_depth( vf_Code_t * start, // from start instruction - vf_Code_t * end ); // to end instruction - -/** - * Function checks graph nodes stack depth consistency. It's recursive function. - * Function returns result of check. - */ -static Verifier_Result vf_check_stack_depth( unsigned nodenum, // graph node number - int stack_depth, // initial stack depth of node - unsigned maxstack, // maximal stack - unsigned *count, // pointer to checked node count - vf_Context_t * ctex ); // verifier context - -/************************************************************ - ******************* Graph Implementation ******************* - ************************************************************/ - -/** - * Function create graph nodes. - */ -void -vf_Graph::CreateNodes( unsigned number ) // number of nodes -{ - assert( number > 0 ); - vf_NodeContainer *nodes = - (vf_NodeContainer*)AllocMemory( sizeof( vf_NodeContainer ) - + ( number - - 1 ) * sizeof( vf_Node ) ); - nodes->m_max = number; - nodes->m_next = m_nodes; - nodes->m_max = number; - if( m_nodes == NULL ) { - m_nodes = nodes; - } else { - vf_NodeContainer *index = m_nodes->m_next; - while( index->m_next ) { - index = index->m_next; - } - index->m_next = nodes; - } -} // vf_Graph::CreateNodes - -/** - * Gets graph node. - */ -vf_NodeHandle -vf_Graph::GetNode( unsigned node_num ) // graph node number -{ - // get node - assert( m_nodes ); - assert( node_num < m_nodenum ); - unsigned count = node_num; - vf_NodeContainer *nodes = m_nodes; - while( count > nodes->m_max ) { - count -= nodes->m_max; - nodes = nodes->m_next; - assert( nodes ); - } - return &nodes->m_node[count]; -} // vf_Graph::GetNode - -/** - * Creates a new node of a specific type. - */ -vf_NodeHandle -vf_Graph::NewNode( vf_NodeType_t type, // node type - int stack ) // a stack modifier -{ - // get node - assert( m_nodes ); - unsigned count = m_nodenum; - vf_NodeContainer *nodes = m_nodes; - while( count > nodes->m_max ) { - count -= nodes->m_max; - nodes = nodes->m_next; - assert( nodes ); - } - - // increment nodes count - m_nodenum++; - nodes->m_used++; - assert( nodes->m_used <= nodes->m_max ); - - // set node - vf_Node *node = &nodes->m_node[count]; - node->m_type = type; - node->m_stack = stack; - return node; -} // vf_Graph::NewNode - -/** - * Gets graph edge. - */ -vf_EdgeHandle vf_Graph::GetEdge( unsigned edge_num ) // graph edge number -{ - // get edge - assert( m_edges ); - assert( edge_num < m_edgenum ); - assert( edge_num ); // zero edge is reserved - unsigned - count = edge_num; - vf_EdgeContainer * - edges = m_edges; - while( count > edges->m_max ) { - count -= edges->m_max; - edges = edges->m_next; - assert( edges ); - } - return &edges->m_edge[count]; -} // vf_Graph::GetEdge - -/** - * Creates a new edge for graph nodes. - */ -void -vf_Graph::NewEdge( unsigned start, // start graph node of edge - unsigned end ) // end graph node of edge -{ - // check node numbers are in range - assert( start < m_nodenum ); - assert( end < m_nodenum ); - - // get edge - assert( m_edges ); - unsigned count = m_edgenum; - vf_EdgeContainer *edges = m_edges; - while( count > edges->m_max ) { - count -= edges->m_max; - edges = edges->m_next; - assert( edges ); - } - - // get a new edge and edge's nodes - vf_Edge *edge = &edges->m_edge[count]; - vf_Node *node_start = (vf_Node*)GetNode( start ); - vf_Node *node_end = (vf_Node*)GetNode( end ); - - // set a new edge - edge->m_start = start; - edge->m_end = end; - edge->m_outnext = node_start->m_outedge; - node_start->m_outedge = m_edgenum; - node_start->m_outnum++; - edge->m_innext = node_end->m_inedge; - node_end->m_inedge = m_edgenum; - node_end->m_innum++; - - // increment edge count - m_edgenum++; - edges->m_used++; - assert( edges->m_used <= edges->m_max ); - - return; -} // vf_Graph::NewEdge - -/** - * Creates a data flow vector from the given example. - */ -void -vf_Graph::SetVector( vf_MapVectorHandle vector_handle, // vector to set - vf_MapVectorHandle example, // current data flow vector - bool need_copy ) // copy flag -{ - assert( example ); - vf_MapVector *vector = (vf_MapVector*)vector_handle; - - // create and set local vector - if( example->m_maxlocal ) { - vector->m_local = (vf_MapEntry_t*) AllocMemory( example->m_maxlocal - * - sizeof - ( vf_MapEntry_t ) ); - assert( vector->m_local ); - vector->m_number = example->m_number; - vector->m_maxlocal = example->m_maxlocal; - } - // create and set stack vector - if( example->m_maxstack ) { - vector->m_stack = (vf_MapEntry_t*) AllocMemory( example->m_maxstack - * - sizeof - ( vf_MapEntry_t ) ); - vector->m_depth = example->m_depth; - vector->m_maxstack = example->m_maxstack; - } - if( need_copy ) { - unsigned index; - for( index = 0; index < example->m_number; index++ ) { - vector->m_local[index] = example->m_local[index]; - } - for( index = 0; index < example->m_depth; index++ ) { - vector->m_stack[index] = example->m_stack[index]; - } - } -} // vf_Graph::SetVector - -/** - * Function creates graph edges. - */ -void -vf_Graph::CreateEdges( unsigned number ) // number of edges -{ - assert( number > 0 ); - vf_EdgeContainer *edges = - (vf_EdgeContainer*)AllocMemory( sizeof( vf_EdgeContainer ) - + number * sizeof( vf_Edge ) ); - edges->m_max = number + 1; // zero edge is reserved - if( m_edges == NULL ) { - m_edges = edges; - } else { - vf_EdgeContainer *index = m_edges->m_next; - while( index->m_next ) { - index = index->m_next; - } - index->m_next = edges; - } - return; -} // vf_Graph::CreateEdges - -/** - * Function cleans graph node enumeration, creates new graph - * enumeration structure and sets first enumeration node. - */ -void -vf_Graph::SetStartCountNode( unsigned node_num ) // graph node number -{ - // check node number is in range - assert( m_nodes ); - assert( node_num < m_nodenum ); - - // create memory - if( m_enummax < m_nodenum ) { - m_enum = ( unsigned * )AllocMemory( sizeof( unsigned ) * m_nodenum ); - } - // clean node enumeration - vf_NodeContainer *nodes = m_nodes; - unsigned count = 0; - while( nodes != NULL ) { - for( unsigned index = 0; index < nodes->m_used; index++, count++ ) { - nodes->m_node[index].m_nodecount = ~0U; - m_enum[count] = ~0U; - } - nodes = nodes->m_next; - } - assert( count == m_nodenum ); - - // set enumeration first element; - m_enum[0] = node_num; - m_enumcount = 1; - - // set node enumeration number - vf_Node *node = (vf_Node*)GetNode( node_num ); - node->m_nodecount = 0; - return; -} // vf_Graph::SetStartCountNode - /************************************************************ **************** Debug Graph Implementation **************** ************************************************************/ @@ -289,103 +30,91 @@ vf_Graph::SetStartCountNode( unsigned no * Function prints graph structure in stderr. */ void -vf_Graph::DumpGraph( vf_Context_t * ctex ) // verifier context +vf_Graph::DumpGraph() { -#if _VERIFY_DEBUG - VERIFY_DEBUG( "Method: " << class_get_name( ctex->m_class ) << "::" - << method_get_name( ctex->m_method ) - << method_get_descriptor( ctex->m_method ) << endl ); - VERIFY_DEBUG( "-- start --" ); - for( unsigned index = 0; index < GetNodeCount(); index++ ) { - DumpNode( index, ctex ); +#if _VF_DEBUG + VF_DEBUG( "Method: " << class_get_name( m_ctx->m_class ) << "::" + << method_get_name( m_ctx->m_method ) + << method_get_descriptor( m_ctx->m_method ) << endl ); + VF_DEBUG( "-- start --" ); + ResetNodeIterator(); + while( HasMoreElements() ) { + DumpNode( GetNextNode() ); } -#endif // _VERIFY_DEBUG - return; +#endif // _VF_DEBUG } // vf_Graph::DumpGraph /** * Function prints graph node in stderr. */ void -vf_Graph::DumpNode( unsigned num, // graph node number - vf_Context_t * ctex ) // verifier context +vf_Graph::DumpNode( vf_NodeHandle node ) // a graph node { -#if _VERIFY_DEBUG +#if _VF_DEBUG // print node incoming edges - unsigned index; - unsigned edge_num; - for( index = 0, edge_num = GetNode( num )->m_inedge; - index < GetNode( num )->m_innum; index++ ) { - vf_EdgeHandle edge = GetEdge( edge_num ); - VERIFY_DEBUG( " [" << edge->m_start << "] -->" ); - edge_num = edge->m_innext; - } - - vf_NodeHandle node = GetNode( num ); - // print node - if( VF_TYPE_NODE_START_ENTRY == node->m_type ) { // start node - VERIFY_DEBUG( "node[" << num << "]: " << node-> - m_start << "[-] start" ); - } else if( VF_TYPE_NODE_END_ENTRY == node->m_type ) { // end node - VERIFY_DEBUG( "node[" << num << "]: " << node->m_start << "[-] end" ); - VERIFY_DEBUG( "-- end --" ); - } else if( VF_TYPE_NODE_HANDLER == node->m_type ) { // handler node - VERIFY_DEBUG( "node[" << num << "]: " << num << "handler entry" ); - } else { // another nodes - DumpNodeInternal( num, ctex ); + vf_EdgeHandle edge; + for( edge = node->m_inedge; edge; edge = edge->m_innext ) { + VF_DEBUG( " [" << GetNodeNum( edge->m_start ) << "] -->" ); + } + + switch ( node->m_type ) { + case VF_NODE_START_ENTRY: + VF_DEBUG( "node[" << GetNodeNum( node ) << "]: start node" ); + break; + case VF_NODE_END_ENTRY: + VF_DEBUG( "node[" << GetNodeNum( node ) << "]: end node" ); + break; + case VF_NODE_HANDLER: + VF_DEBUG( "node[" << GetNodeNum( node ) << "]: exception handler" ); + break; + default: + DumpNodeInternal( node ); } // print node outcoming edges - for( index = 0, edge_num = GetNode( num )->m_outedge; - index < GetNode( num )->m_outnum; index++ ) { - vf_EdgeHandle edge = GetEdge( edge_num ); - VERIFY_DEBUG( " --> [" << edge->m_end << "]" ); - edge_num = edge->m_outnext; - } - VERIFY_DEBUG( "" ); -#endif // _VERIFY_DEBUG - return; + for( edge = node->m_outedge; edge; edge = edge->m_outnext ) { + VF_DEBUG( " --> [" << GetNodeNum( edge->m_end ) << "]" ); + } + VF_DEBUG( "" ); +#endif // _VF_DEBUG } // vf_Graph::DumpNode /** * Function prints graph node instruction in stream. */ void -vf_Graph::DumpNodeInternal( unsigned num, // graph node number - vf_Context_t * ctex ) // verifier context +vf_Graph::DumpNodeInternal( vf_NodeHandle node ) // graph node number { -#if _VERIFY_DEBUG +#if _VF_DEBUG // print node header - VERIFY_DEBUG( "Node #" << num ); - VERIFY_DEBUG( "Stack mod: " << GetNode( num )->m_stack ); + VF_DEBUG( "Node #" << GetNodeNum( node ) ); + VF_DEBUG( "Stack mod: " << node->m_stack ); + DumpSub( node->m_sub ); // get code instructions - unsigned count = GetNode( num )->m_end - GetNode( num )->m_start + 1; - vf_Code_t *instr = &( ctex->m_code[GetNode( num )->m_start] ); + unsigned count = node->m_end - node->m_start + 1; + vf_InstrHandle instr = node->m_start; // print node instructions for( unsigned index = 0; index < count; index++, instr++ ) { - VERIFY_DEBUG( index << ": " << ( ( instr->m_stack < 0 ) ? "[" : "[ " ) - << instr->m_stack << "| " << instr->m_minstack << "] " - << vf_opcode_names[*( instr->m_addr )] ); + VF_DEBUG( index << ": " << ( ( instr->m_stack < 0 ) ? "[" : "[ " ) + << instr->m_stack << "| " << instr->m_minstack << "] " + << vf_opcode_names[*( instr->m_addr )] ); } -#endif // _VERIFY_DEBUG - return; +#endif // _VF_DEBUG } // vf_Graph::DumpNodeInternal /** * Function dumps graph node in file in DOT format. */ void -vf_Graph::DumpDotGraph( vf_Context_t * ctex ) // verifier context +vf_Graph::DumpDotGraph() { -#if _VERIFY_DEBUG - unsigned index; - +#if _VF_DEBUG // get class and method name - const char *class_name = class_get_name( ctex->m_class ); - const char *method_name = method_get_name( ctex->m_method ); - const char *method_desc = method_get_descriptor( ctex->m_method ); + const char *class_name = class_get_name( m_ctx->m_class ); + const char *method_name = method_get_name( m_ctx->m_method ); + const char *method_desc = method_get_descriptor( m_ctx->m_method ); // create file name size_t len = strlen( class_name ) + strlen( method_name ) @@ -417,35 +146,44 @@ vf_Graph::DumpDotGraph( vf_Context_t * c // create .dot file ofstream fout( fname ); if( fout.fail() ) { - VERIFY_DEBUG( "vf_Graph::DumpDotGraph: error opening file: " << - fname ); - vf_error(); + VF_DEBUG( "vf_Graph::DumpDotGraph: error opening file: " << fname ); + return; } // create name of graph sprintf( fname, "%s::%s%s", class_name, method_name, method_desc ); // print graph to file DumpDotHeader( fname, fout ); - for( index = 0; index < m_nodenum; index++ ) { - DumpDotNode( index, fout, ctex ); + ResetNodeIterator(); + while( HasMoreElements() ) { + DumpDotNode( GetNextNode(), fout ); } DumpDotEnd( fout ); // close file fout.flush(); fout.close(); -#endif // _VERIFY_DEBUG - return; +#endif // _VF_DEBUG } // vf_Graph::DumpDotGraph /** + * Graphviz has a hardcoded label length limit. + */ +const int MAX_LABEL_LENGTH = 80; + +/** * Function dumps graph header in file in DOT format. */ void vf_Graph::DumpDotHeader( char *graph_name, // graph name ofstream &out ) // output file stream { -#if _VERIFY_DEBUG +#if _VF_DEBUG + string label( graph_name ); + if( label.size() > MAX_LABEL_LENGTH ) { + label.erase( 0, label.size() - MAX_LABEL_LENGTH ); + } + out << "digraph dotgraph {" << endl << "center=TRUE;" << endl << "margin=\".2,.2\";" << endl @@ -455,77 +193,71 @@ vf_Graph::DumpDotHeader( char *graph_nam << "ratio=auto;" << endl << "node [color=lightblue2, style=filled, shape=record, " << "fontname=\"Courier\", fontsize=9];" << endl - << "label=\"" << graph_name << "\";" << endl; -#endif // _VERIFY_DEBUG - return; + << "label=\"" << label << "\";" << endl; + +#endif // _VF_DEBUG } // vf_Graph::DumpDotHeader /** * Function dumps graph node in file in DOT format. */ void -vf_Graph::DumpDotNode( unsigned num, // graph node number - ofstream &out, // output file stream - vf_Context_t * ctex ) // verifier contex +vf_Graph::DumpDotNode( vf_NodeHandle node, // graph node number + ofstream &out ) // output file stream { -#if _VERIFY_DEBUG - vf_NodeHandle node = GetNode( num ); - +#if _VF_DEBUG // print node to dot file - if( VF_TYPE_NODE_START_ENTRY == node->m_type ) { // start node - out << "node" << num << " [label=\"START\", color=limegreen]" << endl; - } else if( VF_TYPE_NODE_END_ENTRY == node->m_type ) { // end node - out << "node" << num << " [label=\"END\", color=orangered]" << endl; - } else if( VF_TYPE_NODE_HANDLER == node->m_type ) { // handler node - out << "node" << num << " [label=\"Handler #" - << num << "\", shape=ellipse, color=aquamarine]" << endl; + out << "node" << GetNodeNum( node ); + if( VF_NODE_START_ENTRY == node->m_type ) { // start node + out << " [label=\"START\", color=limegreen]" << endl; + } else if( VF_NODE_END_ENTRY == node->m_type ) { // end node + out << " [label=\"END\", color=orangered]" << endl; + } else if( VF_NODE_HANDLER == node->m_type ) { // handler node + out << " [label=\"Handler #" + << GetNodeNum( node ) << "\", shape=ellipse, color="; + if( node->m_sub ) { + out << "\"#B7FFE" << hex + << ( vf_get_sub_num( node, m_ctx ) % 16 ) << dec << "\""; + } else { + out << "aquamarine"; + } + out << "]" << endl; } else { // other nodes - out << "node" << num << " [label=\""; - DumpDotNodeInternal( num, "\\n---------\\n", "\\l", out, ctex ); - out << "\"]" << endl; + DumpDotNodeInternal( node, "\\n---------\\n", "\\l", out ); } // print node outcoming edges to dot file - unsigned index; - unsigned edge_num; - for( index = 0, edge_num = node->m_outedge; - index < node->m_outnum; index++ ) { - vf_EdgeHandle edge = GetEdge( edge_num ); - - out << "node" << num << " -> " << "node" << edge->m_end; - if( VF_TYPE_NODE_HANDLER == GetNode( edge->m_end )->m_type ) { + for( vf_EdgeHandle edge = node->m_outedge; edge; edge = edge->m_outnext ) { + out << "node" << GetNodeNum( node ) << " -> " + << "node" << GetNodeNum( edge->m_end ); + if( VF_NODE_HANDLER == edge->m_end->m_type ) { out << "[color=red]" << endl; - } else if( ( VF_TYPE_NODE_CODE_RANGE == node->m_type ) - && ( VF_TYPE_INSTR_SUBROUTINE == - vf_get_last_instruction_type( ctex, - edge->m_start ) ) ) { + } else if( vf_is_jsr_branch( edge, m_ctx ) ) { out << "[color=blue]" << endl; } out << ";" << endl; - edge_num = edge->m_outnext; } -#endif // _VERIFY_DEBUG - return; +#endif // _VF_DEBUG } // vf_Graph::DumpDotNode /** * Function dumps graph node instruction in file stream in DOT format. */ void -vf_Graph::DumpDotNodeInternal( unsigned num, // graph node number +vf_Graph::DumpDotNodeInternal( vf_NodeHandle node, // graph node number char *next_node, // separator between nodes in stream char *next_instr, // separator between instructions in stream - ofstream &out, // output file stream - vf_Context_t * ctex ) // verifier contex + ofstream &out ) // output file stream { -#if _VERIFY_DEBUG +#if _VF_DEBUG // print node header - out << "Node " << num << next_node - << "Stack mod: " << GetNode( num )->m_stack << next_node; + out << " [label=\""; + out << "Node " << GetNodeNum( node ) << next_node + << "Stack mod: " << node->m_stack << next_node; // get code instructions - unsigned count = GetNode( num )->m_end - GetNode( num )->m_start + 1; - vf_Code_t *instr = &( ctex->m_code[GetNode( num )->m_start] ); + unsigned count = node->m_end - node->m_start + 1; + vf_InstrHandle instr = node->m_start; // print node instructions for( unsigned index = 0; index < count; index++, instr++ ) { @@ -533,8 +265,14 @@ vf_Graph::DumpDotNodeInternal( unsigned << instr->m_stack << "\\| " << instr->m_minstack << "] " << vf_opcode_names[*( instr->m_addr )] << next_instr; } -#endif // _VERIFY_DEBUG - return; + out << "\"" << endl; + + if( node->m_sub ) { + out << ", color=\"#B2F" << hex + << ( vf_get_sub_num( node, m_ctx ) % 16 ) << dec << "EE\""; + } + out << "]" << endl; +#endif // _VF_DEBUG } // vf_Graph::DumpDotNodeInternal /** @@ -543,139 +281,188 @@ vf_Graph::DumpDotNodeInternal( unsigned void vf_Graph::DumpDotEnd( ofstream &out ) // output file stream { -#if _VERIFY_DEBUG +#if _VF_DEBUG out << "}" << endl; -#endif // _VERIFY_DEBUG - return; +#endif // _VF_DEBUG } // vf_Graph::DumpDotEnd + /************************************************************ ********************** Graph Creation ********************** ************************************************************/ /** * Creates bytecode control flow graph. */ -Verifier_Result -vf_create_graph( vf_Context_t * ctex ) // verifier context +vf_Result +vf_create_graph( vf_Context *ctx ) // verification context { - // allocate memory for graph structure - void *mem_graph = - vf_alloc_pool_memory( ctex->m_pool, sizeof( vf_Graph ) ); + vf_BCode *bc = ctx->m_bc; + + /** + * Count edges from basic blocks from exception range to the + * corresponding exception handlers. + */ + unsigned edges = 0; + unsigned short handler_count = + method_get_exc_handler_number( ctx->m_method ); + for( unsigned short handler_index = 0; handler_index < handler_count; + handler_index++ ) { + unsigned short start_pc, end_pc, handler_pc, handler_cp_index, count; + method_get_exc_handler_info( ctx->m_method, handler_index, + &start_pc, &end_pc, &handler_pc, + &handler_cp_index ); + + // number of basic blocks in the exception range + unsigned handler_edges = 0; + for( count = start_pc; count < end_pc; count++ ) { + if( bc[count].m_basic_block_start ) { + handler_edges++; + } + } - // for creation of graph use numbers pre-calculated at vf_parse_bytecode - ctex->m_graph = new( mem_graph ) vf_Graph( ctex->m_nodeNum, - ctex->m_edgeNum, - ctex->m_pool ); - vf_Graph *graph = ctex->m_graph; - - // the array contains a corresponding node for each instruction - unsigned *code2node = ( unsigned * )vf_alloc_pool_memory( ctex->m_pool, - ctex-> - m_codeNum * - sizeof - ( unsigned ) ); + edges += handler_edges; + } - // create start-entry node - graph->NewNode( VF_TYPE_NODE_START_ENTRY, 0 ); + /** + * Initialize a node counter with handler nodes + * and 2 terminator nodes. + */ + unsigned nodes = handler_count + 2; + + /** + * Check instruction offsets, count basic blocks and edges. + */ + for( unsigned index = 0; index < ctx->m_len; index++ ) { + vf_InstrHandle instr = bc[index].m_instr; + if( NULL == instr ) { + if( bc[index].m_basic_block_start ) { + VF_REPORT( ctx, "Illegal target of jump or branch" ); + return VER_ErrorBranch; + } else { + continue; + } + } + + if( bc[index].m_basic_block_start ) { + ( (vf_Instr*) instr )->m_basic_block_start = true; + nodes++; + } + + if( instr->m_offcount ) { + // basic block should start next, so we will + // count one branch anyway + edges += instr->m_offcount - 1; + } + } + + /** + * Each node except the end node and ret nodes emits at least one + * branch. + */ + edges += nodes - 1 - ctx->m_retnum; + + // allocate memory for graph structure + void *mem_graph = vf_palloc( ctx->m_pool, sizeof( vf_Graph ) ); + // for graph creation use pre-calculated numbers + vf_Graph *graph = new( mem_graph ) vf_Graph( nodes, edges, ctx ); + ctx->m_graph = graph; + + /** + * Create nodes. + */ + graph->NewNode( VF_NODE_START_ENTRY ); // create handler nodes unsigned node_index; - unsigned short handler_count = - method_get_exc_handler_number( ctex->m_method ); for( node_index = 1; node_index <= ( unsigned )handler_count; node_index++ ) { - graph->NewNode( VF_TYPE_NODE_HANDLER, 1 ); + graph->NewNode( VF_NODE_HANDLER ); } - /** - * Create code range nodes. New node correspond to the subsequent - * basic blocks of instructions. - * Note: code range nodes follow after the last handler node. - */ - // adding a basic block which starts - for( unsigned bb_start = 0; bb_start < ctex->m_codeNum; node_index++ ) { + // create code range nodes right after the last handler node + // a new node correspond to a subsequent basic block of instructions + for( vf_InstrHandle bb_start = ctx->m_instr; + bb_start < ctx->m_last_instr; node_index++ ) { // find a basic block end - unsigned next_bb_start = bb_start + 1; - while( ( next_bb_start < ctex->m_codeNum ) - && ( !ctex->m_code[next_bb_start].m_basic_block_start ) ) { + vf_InstrHandle next_bb_start = bb_start + 1; + while( ( next_bb_start < ctx->m_last_instr ) + && ( !next_bb_start->m_basic_block_start ) ) { next_bb_start++; } - int stack = vf_get_node_stack_depth( &ctex->m_code[bb_start], - &ctex->m_code[next_bb_start - - 1] ); - graph->NewNode( bb_start, next_bb_start - 1, stack ); - code2node[bb_start] = node_index; + ( (vf_Instr*) bb_start )->m_node = + graph->NewNode( bb_start, next_bb_start - 1 ); bb_start = next_bb_start; } // create exit-entry node - graph->NewNode( VF_TYPE_NODE_END_ENTRY, 0 ); + graph->AddEndNode(); unsigned node_num = node_index + 1; - assert( ctex->m_nodeNum == node_num ); + assert( 0 == graph->HasMoreNodeSpace() ); /** - * Create edges + * Create edges. */ + vf_Node *node = (vf_Node*)graph->GetNode( handler_count + 1 ); - // from start-entry node to the first code node - node_index = handler_count + 1; - graph->NewEdge( 0, node_index ); + // from start-entry node to the first code range node + graph->NewEdge( (vf_Node*)graph->GetStartNode(), node ); // create code range edges - for( ; node_index < node_num - 1; node_index++ ) { - vf_Code_t *code = - &ctex->m_code[graph->GetNodeLastInstr( node_index )]; + for( ; VF_NODE_CODE_RANGE == node->m_type; node++ ) { + vf_InstrHandle instr = node->m_end; // set control flow edges - if( code->m_offcount ) { - for( unsigned count = 0; count < code->m_offcount; count++ ) { - int offset = vf_get_code_branch( code, count ); - unsigned node = code2node[ctex->m_bc[offset].m_instr - 1]; + if( instr->m_offcount ) { + for( unsigned count = 0; count < instr->m_offcount; count++ ) { + int offset = vf_get_instr_branch( instr, count ); + vf_Node *next_node = + (vf_Node*)graph->GetNodeFromBytecodeIndex( offset ); assert( node ); - graph->NewEdge( node_index, node ); - if( node < node_index ) { + graph->NewEdge( node, next_node ); + if( next_node < node ) { // node has a backward branch, thus any // object on the stack should be initialized - graph->SetNodeInitFlag( node, true ); + node->m_initialized = true; } } - } else if( code->m_type ) { - // FIXME compatibility issue - no need to - // have these branches for VF_TYPE_INSTR_SUBROUTINE - graph->NewEdge( node_index, node_num - 1 ); - } else if( node_index + 1 < node_num ) { - graph->NewEdge( node_index, node_index + 1 ); + } else if( VF_INSTR_RETURN == instr->m_type + || VF_INSTR_THROW == instr->m_type ) { + graph->NewEdge( node, (vf_Node*)graph->GetEndNode() ); + } else if( VF_INSTR_RET == instr->m_type ) { + // no edges from ret + } else if( VF_NODE_CODE_RANGE == ( node + 1 )->m_type ) { + graph->NewEdge( node, node + 1 ); } else { - VERIFY_REPORT_METHOD( ctex, "Falling off the end of the code" ); + VF_REPORT( ctx, "Falling off the end of the code" ); return VER_ErrorBranch; } } + assert( VF_NODE_END_ENTRY == node->m_type ); // create OUT map vectors for handler nodes - unsigned char *start_bc = method_get_bytecode( ctex->m_method ); - unsigned bytecode_len = method_get_code_length( ctex->m_method ); + unsigned char *start_bc = method_get_bytecode( ctx->m_method ); for( unsigned short handler_index = 0; handler_index < handler_count; handler_index++ ) { unsigned short start_pc, end_pc, handler_pc, handler_cp_index; - method_get_exc_handler_info( ctex->m_method, + method_get_exc_handler_info( ctx->m_method, handler_index, &start_pc, &end_pc, &handler_pc, &handler_cp_index ); - vf_ValidType_t *type = NULL; + vf_ValidType *type = NULL; if( handler_cp_index ) { - const char *name = vf_get_cp_class_name( ctex->m_class, + const char *name = vf_get_cp_class_name( ctx->m_class, handler_cp_index ); assert( name ); - type = vf_create_class_valid_type( name, ctex ); + type = vf_create_class_valid_type( name, ctx ); // set restriction for handler class - if( ctex->m_vtype.m_throwable->string[0] != type->string[0] ) { - ctex->m_type->SetRestriction( ctex->m_vtype.m_throwable-> - string[0], type->string[0], 0, - VF_CHECK_SUPER ); + if( ctx->m_vtype.m_throwable->string[0] != type->string[0] ) { + ctx->m_type->SetRestriction( ctx->m_vtype.m_throwable-> + string[0], type->string[0], 0, + VF_CHECK_SUPER ); } } @@ -687,163 +474,244 @@ vf_create_graph( vf_Context_t * ctex ) * created with during the process of merge. */ vf_MapVector *p_outvector = (vf_MapVector*) - graph->GetNodeOutVector( handler_index + 1 ); + &graph->GetNode( handler_index + 1 )->m_outmap; p_outvector->m_stack = - (vf_MapEntry_t*) graph->AllocMemory( sizeof( vf_MapEntry_t ) ); + (vf_MapEntry*)graph->AllocMemory( sizeof( vf_MapEntry ) * + ctx->m_maxstack ); p_outvector->m_depth = 1; vf_set_vector_stack_entry_ref( p_outvector->m_stack, 0, type ); // outcoming handler edge - graph->NewEdge( handler_index + 1, - code2node[ctex->m_bc[handler_pc].m_instr - 1] ); + vf_Node *handler_node = + (vf_Node*)graph->GetNode( handler_index + 1 ); + graph->NewEdge( handler_node, + (vf_Node*)graph-> + GetNodeFromBytecodeIndex( handler_pc ) ); // node range start - node_index = code2node[ctex->m_bc[start_pc].m_instr - 1]; + node = (vf_Node*)graph->GetNodeFromBytecodeIndex( start_pc ); - unsigned last_node = ( end_pc == bytecode_len ) - ? node_num - 1 : code2node[ctex->m_bc[end_pc].m_instr - 1]; + vf_NodeHandle last_node = ( end_pc == ctx->m_len ) + ? graph->GetEndNode() + : graph->GetNodeFromBytecodeIndex( end_pc ); - for( ; node_index < last_node; node_index++ ) { + for( ; node < last_node; node++ ) { // node is protected by exception handler, thus the // reference in local variables have to be initialized - graph->SetNodeInitFlag( node_index, true ); - graph->NewEdge( node_index, handler_index + 1 ); + node->m_initialized = true; + graph->NewEdge( node, handler_node ); } } // one edge is reserved - assert( graph->GetEdgeCount() == ctex->m_edgeNum ); + assert( 0 == graph->HasMoreEdgeSpace() ); -#if _VERIFY_DEBUG - if( ctex->m_dump.m_graph ) { - graph->DumpGraph( ctex ); + if( vf_is_trace_enabled( DUMP_GRAPH ) ) { + graph->DumpGraph(); } - if( ctex->m_dump.m_dot_graph ) { - graph->DumpDotGraph( ctex ); + if( vf_is_trace_enabled( DUMP_DOT ) ) { + graph->DumpDotGraph(); } -#endif // _VERIFY_DEBUG return VER_OK; } // vf_create_graph /************************************************************ - *************** Graph Stack Deep Analysis ****************** + *************** Graph Stack Depth Analysis ***************** ************************************************************/ +/** + * Checks stack depth of a node. + */ +vf_Result +vf_check_node_stack_depth( vf_Node *node, // a graph node + unsigned &depth, // initial stack depth + vf_Context *ctx ) // verification context +{ + if( node->m_mark ) { + if( ( depth == node->m_inmap.m_depth ) + || ( VF_NODE_CODE_RANGE != node->m_type ) ) { + // consistent stack depth in the node + return VER_OK; + } else { + // inconsistent stack depth + VF_REPORT( ctx, "Inconsistent stack depth: " + << node->m_inmap.m_depth << " != " << depth ); + return VER_ErrorStackDepth; + } + } + // mark the node + node->m_mark = VF_START_MARK; + + // count the node + vf_Graph *graph = ctx->m_graph; + graph->IncrementReachableCount(); + + if( VF_NODE_CODE_RANGE != node->m_type ) { + if( VF_NODE_HANDLER == node->m_type ) { + depth = 1; + node->m_stack = 1; + } else if( VF_NODE_END_ENTRY == node->m_type ) { + return VER_OK; + } + return VER_Continue; + } + node->m_inmap.m_depth = depth; + + // calculate a stack depth after the last node instruction + int stack_depth = 0; + for( vf_InstrHandle instr = node->m_start; instr <= node->m_end; instr++ ) { + if( instr->m_minstack > depth ) { + VF_REPORT( ctx, "Unable to pop operand off an empty stack" ); + return VER_ErrorStackOverflow; + } + stack_depth += instr->m_stack; + depth += instr->m_stack; + if( depth > ctx->m_maxstack || ( int )depth < 0 ) { + VF_REPORT( ctx, "Instruction stack overflow" ); + return VER_ErrorStackOverflow; + } + } + + node->m_stack = stack_depth; + node->m_outmap.m_depth = depth; + return VER_Continue; +} // vf_check_node_stack_depth /** - * Function evaluates stack depth of graph code range node. + * Checks graph nodes stack depth consistency recursively. + * Returns result of a check. */ -static int -vf_get_node_stack_depth( vf_Code_t * start, // beginning instruction - vf_Code_t * end ) // ending instruction +static vf_Result +vf_check_stack_depth( vf_Node *node, // a graph node + unsigned stack_depth, // initial stack depth of node + vf_Context *ctx ) // verification context +{ + // check for node stack overflow + vf_Result result = vf_check_node_stack_depth( node, stack_depth, ctx ); + if( result != VER_Continue ) { + return result; + } + // iterate over out edges and set stack depth for out nodes + for( vf_EdgeHandle outedge = node->m_outedge; + outedge; outedge = outedge->m_outnext ) { + // get out node + vf_Node *outnode = (vf_Node*)outedge->m_end; + // mark out node with its out nodes + result = vf_check_stack_depth( outnode, stack_depth, ctx ); + if( result != VER_OK ) { + return result; + } + } + return VER_OK; +} // vf_check_stack_depth + +/** + * Identifies dead nodes and fills them by nop instruction. + */ +static void +vf_nullify_unreachable_bytecode( vf_ContextHandle ctx ) // verification context { - assert( start <= end ); + unsigned short handle_count = + method_get_exc_handler_number( ctx->m_method ); - /** - * Evaluate stack depth - */ - int result = 0; - for( vf_Code_t * pointer = start; pointer <= end; pointer++ ) { - result += pointer->m_stack; + vf_Node *node = (vf_Node*)ctx->m_graph->GetNode( handle_count + 1 ); + for( ; node->m_type != VF_NODE_END_ENTRY; node++ ) { + assert( VF_NODE_CODE_RANGE == node->m_type ); + if( !node->m_mark ) { + unsigned char *instr = node->m_start->m_addr; + const unsigned char *end = vf_get_instr_end( node->m_end, ctx ); + while( instr < end ) { + *( instr++ ) = OPCODE_NOP; + } + node->m_stack = 0; + } } - return result; -} // vf_get_node_stack_depth - +} /** - * Function provides some checks of control flow and data flow structures of graph. + * Function provides checks of control flow and data flow structures of graph. */ -Verifier_Result -vf_check_graph( vf_Context_t * ctex ) // verifier context +vf_Result +vf_check_graph( vf_Context *ctx ) // verification context { - unsigned count, inedge, innode; + vf_Graph *graph = ctx->m_graph; + vf_InstrHandle instr = ctx->m_instr; - /** - * Gem method max stack - */ - vf_Graph *vGraph = ctex->m_graph; - unsigned maxstack = method_get_max_stack( ctex->m_method ); - unsigned short handlcount = - method_get_exc_handler_number( ctex->m_method ); - vf_Code_t *code = ctex->m_code; + vf_Result result; - /** - * Check stack depth correspondence - */ - unsigned index = 1; - Verifier_Result result = vf_check_stack_depth( 0, VERIFY_START_MARK, - maxstack + - VERIFY_START_MARK, &index, - ctex ); - if( result != VER_OK ) { - goto labelEnd_bypassGraphStructure; + // allocate a current stack map vector + ctx->m_map = (vf_MapVector*)vf_palloc( ctx->m_pool, + sizeof( vf_MapVector ) ); + ctx->m_graph->AllocVector( ctx->m_map ); + + // create a buf stack map vector (max 4 entries) + ctx->m_buf = (vf_MapEntry*)vf_palloc( ctx->m_pool, + sizeof( vf_MapEntry ) + * ctx->m_maxstack ); + + if( ctx->m_retnum ) { + result = vf_mark_subroutines( ctx ); + if( VER_OK != result ) { + return result; + } + } else { + result = + vf_check_stack_depth( (vf_Node*)graph->GetStartNode(), 0, + ctx ); + if( result != VER_OK ) { + return result; + } } - assert( index <= vGraph->GetNodeCount() ); - /** - * Determine dead code nodes - */ - index = vGraph->GetNodeCount() - index; // number of dead code nodes + // there could be only nop opcodes in the bytecode, in this case + // the code is already checked during previous step + if( ctx->m_maxstack == 0 ) { + return VER_OK; + } + // override all dead nodes + assert( graph->GetReachableNodeCount() <= graph->GetNodeCount() ); + if( graph->GetReachableNodeCount() < graph->GetNodeCount() ) { + vf_nullify_unreachable_bytecode( ctx ); + } - /** - * Override all dead nodes - */ - if( index ) { - /** - * Identify dead code nodes and fill by nop instruction. - */ - for( index = handlcount + 1; index < vGraph->GetNodeCount() - 1; - index++ ) { - if( !vGraph->IsNodeMarked( index ) ) { - unsigned char *instr = - code[vGraph->GetNodeFirstInstr( index )].m_addr; - unsigned len = - vGraph->GetNodeBytecodeLen( ctex, - vGraph->GetNode( index ) ); - for( count = 0; count < len; count++ ) { - instr[count] = OPCODE_NOP; - } - vGraph->SetNodeStackModifier( index, 0 ); - } + if( ctx->m_retnum ) { + result = vf_inline_subroutines( ctx ); + if( VER_OK != result ) { + return result; } } -#if _VERIFY_DEBUG - if( ctex->m_dump.m_mod_graph ) { - vGraph->DumpGraph( ctex ); + + if( vf_is_trace_enabled( DUMP_MOD ) ) { + graph->DumpGraph(); } - if( ctex->m_dump.m_dot_mod_graph ) { - vGraph->DumpDotGraph( ctex ); + if( vf_is_trace_enabled( DUMP_DOT_MOD ) ) { + graph->DumpDotGraph(); } -#endif // _VERIFY_DEBUG /** * Check that execution flow terminates with * return or athrow bytecodes. * Override all incoming edges to the end-entry node. */ - for( inedge = vGraph->GetNodeFirstInEdge( vGraph->GetNodeCount() - 1 ); - inedge; inedge = vGraph->GetEdgeNextInEdge( inedge ) ) { + for( vf_EdgeHandle inedge = + graph->GetEndNode()->m_inedge; inedge; + inedge = inedge->m_innext ) { // get incoming node - innode = vGraph->GetEdgeStartNode( inedge ); - // check last node instruction, skip dead code nodes - if( vGraph->IsNodeMarked( innode ) ) { - // get node last instruction - unsigned char *instr = - code[vGraph->GetNodeLastInstr( innode )].m_addr; - if( !instr || !( ( *instr ) >= OPCODE_IRETURN && ( *instr ) <= OPCODE_RETURN || ( *instr ) == OPCODE_ATHROW ) ) { // illegal instruction - VERIFY_REPORT_METHOD( ctex, - "Falling off the end of the code" ); - result = VER_ErrorCodeEnd; - goto labelEnd_bypassGraphStructure; - } + vf_NodeHandle innode = inedge->m_start; + // get node last instruction + vf_InstrType type = innode->m_end->m_type; + + if( ( VF_INSTR_RETURN != type ) && ( VF_INSTR_THROW != type ) ) { + // illegal instruction + VF_REPORT( ctx, "Falling off the end of the code" ); + return VER_ErrorCodeEnd; } } /** * Make data flow analysis */ - result = vf_check_graph_data_flow( ctex ); + result = vf_check_graph_data_flow( ctx ); - labelEnd_bypassGraphStructure: return result; } // vf_check_graph @@ -851,144 +719,10 @@ vf_check_graph( vf_Context_t * ctex ) * Frees memory allocated for graph, if any. */ void -vf_free_graph( vf_Context_t * context ) // verifier context +vf_free_graph( vf_Context *ctx ) // verification context { - if( context->m_graph ) { - context->m_graph->~vf_Graph(); - context->m_graph = NULL; + if( ctx->m_graph ) { + ctx->m_graph->~vf_Graph(); + ctx->m_graph = NULL; } } // vf_free_graph - -/** - * Function checks stack overflow of graph node instruction. - */ -static inline Verifier_Result -vf_check_node_stack_depth( unsigned nodenum, // graph node number - int depth, // initial stack depth - unsigned max_stack, // maximal stack - vf_Context_t * ctex ) // verifier context -{ - // get checked node - vf_NodeHandle node = ctex->m_graph->GetNode( nodenum ); - - /** - * For start, end and handler nodes - */ - if( node->m_type != VF_TYPE_NODE_CODE_RANGE ) { - return VER_OK; - } - - /** - * Get begin and end code instruction of graph node - */ - unsigned start = node->m_start; - unsigned end = node->m_end; - assert( start <= end ); - - /** - * Evaluate stack depth - */ - unsigned index; - vf_Code_t *pointer; - int stack_depth = 0; - for( index = start, pointer = &ctex->m_code[index]; index <= end; - index++, pointer++ ) { - if( pointer->m_minstack + VERIFY_START_MARK > stack_depth + depth ) { - VERIFY_REPORT_METHOD( ctex, - "Unable to pop operand off an empty stack" ); - return VER_ErrorStackOverflow; - } - stack_depth += pointer->m_stack; - if( stack_depth + depth > ( int )max_stack - || stack_depth + depth < VERIFY_START_MARK ) { - VERIFY_REPORT_METHOD( ctex, "Instruction stack overflow" ); - return VER_ErrorStackOverflow; - } - } -#if _VERIFY_DEBUG - if( stack_depth != ctex->m_graph->GetNodeStackModifier( nodenum ) ) { - VERIFY_DEBUG - ( "vf_check_node_stack_depth: error stack modifier calculate" ); - vf_error(); - } -#endif // _VERIFY_DEBUG - - return VER_OK; -} // vf_check_node_stack_depth - -/** - * Function checks graph nodes stack depth consistency. It's recursive function. - * Function returns result of check. - */ -static Verifier_Result -vf_check_stack_depth( unsigned nodenum, // graph node number - int stack_depth, // initial stack depth of node - unsigned maxstack, // maximal stack - unsigned *count, // pointer to checked node count - vf_Context_t * ctex ) // verifier context -{ - // get checked node - vf_NodeHandle node = ctex->m_graph->GetNode( nodenum ); - - /** - * Skip end-entry node - */ - if( VF_TYPE_NODE_END_ENTRY == node->m_type ) { - return VER_OK; - } - - /** - * Check handler node - */ - if( VF_TYPE_NODE_HANDLER == node->m_type ) { - // Reset stack for handler nodes - stack_depth = VERIFY_START_MARK; - } - - /** - * Check node stack depth - */ - int depth = ctex->m_graph->GetNodeMark( nodenum ); - if( !depth ) { - // stack depth don't set, mark node by his stack depth - ctex->m_graph->SetNodeMark( nodenum, stack_depth ); - ( *count )++; - } else { - if( stack_depth == depth ) { - // consistent stack depth in graph - return VER_OK; - } else { - // inconsistent stack depth in graph - VERIFY_REPORT_METHOD( ctex, "Inconsistent stack depth: " - << stack_depth - VERIFY_START_MARK << " != " - << depth - VERIFY_START_MARK ); - return VER_ErrorStackDeep; - } - } - - /** - * Check node stack overflow - */ - Verifier_Result result = - vf_check_node_stack_depth( nodenum, stack_depth, maxstack, ctex ); - if( result != VER_OK ) { - return result; - } - - /** - * Override all out edges and set stack depth for out nodes - */ - depth = stack_depth + ctex->m_graph->GetNodeStackModifier( nodenum ); - for( unsigned outedge = ctex->m_graph->GetNodeFirstOutEdge( nodenum ); - outedge; outedge = ctex->m_graph->GetEdgeNextOutEdge( outedge ) ) { - // get out node - unsigned outnode = ctex->m_graph->GetEdgeEndNode( outedge ); - // mark out node with its out nodes - result = - vf_check_stack_depth( outnode, depth, maxstack, count, ctex ); - if( result != VER_OK ) { - return result; - } - } - return result; -} // vf_check_stack_depth diff -pu 9/trunk/working_vm/vm/vmcore/src/verifier/Verifier.cpp 91/trunk/working_vm/vm/vmcore/src/verifier/Verifier.cpp --- 9/trunk/working_vm/vm/vmcore/src/verifier/Verifier.cpp 2007-03-20 18:34:52.762297800 +0300 +++ 91/trunk/working_vm/vm/vmcore/src/verifier/Verifier.cpp 2007-03-21 04:10:18.610184000 +0300 @@ -26,21 +26,21 @@ * Debug flag macros */ // Macro sets verification only for defined class -#define VERIFY_CLASS 0 +#define VF_CLASS 0 // Macro sets verification only for defined method -#define VERIFY_METHOD 0 +#define VF_METHOD 0 /** - * Function parse bytecode, determines code instructions, fills code array and + * Parses bytecode, determines instruction boundaries and * provides checks of simple verifications. */ -static Verifier_Result vf_parse_bytecode( vf_Context_t * context ); // verifier context +static vf_Result vf_parse_bytecode( vf_Context *ctx ); // verification context -#if _VERIFY_DEBUG +#if _VF_DEBUG /** * Function prints code instruction array in stream. */ -void vf_dump_bytecode( vf_Context_t * context ); // verifier context +void vf_dump_bytecode( vf_ContextHandle ); // verification context /** * Array of opcode names. Available in debug mode. @@ -51,18 +51,18 @@ const char *vf_opcode_names[256] = { "FCONST_1", "FCONST_2", "DCONST_0", "DCONST_1", "BIPUSH", "SIPUSH", "LDC", "LDC_W", "LDC2_W", "ILOAD", "LLOAD", "FLOAD", "DLOAD", "ALOAD", "ILOAD_0", "ILOAD_1", "ILOAD_2", "ILOAD_3", "LLOAD_0", "LLOAD_1", - "LLOAD_2", + "LLOAD_2", "LLOAD_3", "FLOAD_0", "FLOAD_1", "FLOAD_2", "FLOAD_3", "DLOAD_0", - "DLOAD_1", + "DLOAD_1", "DLOAD_2", "DLOAD_3", "ALOAD_0", "ALOAD_1", "ALOAD_2", "ALOAD_3", - "IALOAD", + "IALOAD", "LALOAD", "FALOAD", "DALOAD", "AALOAD", "BALOAD", "CALOAD", "SALOAD", "ISTORE", "LSTORE", "FSTORE", "DSTORE", "ASTORE", "ISTORE_0", "ISTORE_1", "ISTORE_2", "ISTORE_3", "LSTORE_0", "LSTORE_1", "LSTORE_2", "LSTORE_3", "FSTORE_0", "FSTORE_1", "FSTORE_2", "FSTORE_3", "DSTORE_0", "DSTORE_1", "DSTORE_2", "DSTORE_3", "ASTORE_0", "ASTORE_1", "ASTORE_2", "ASTORE_3", "IASTORE", "LASTORE", "FASTORE", "DASTORE", "AASTORE", "BASTORE", - "CASTORE", + "CASTORE", "SASTORE", "POP", "POP2", "DUP", "DUP_X1", "DUP_X2", "DUP2", "DUP2_X1", "DUP2_X2", "SWAP", "IADD", "LADD", "FADD", "DADD", "ISUB", "LSUB", "FSUB", "DSUB", "IMUL", "LMUL", "FMUL", "DMUL", "IDIV", "LDIV", "FDIV", "DDIV", @@ -73,82 +73,53 @@ const char *vf_opcode_names[256] = { "FCMPG", "DCMPL", "DCMPG", "IFEQ", "IFNE", "IFLT", "IFGE", "IFGT", "IFLE", "IF_ICMPEQ", "IF_ICMPNE", "IF_ICMPLT", "IF_ICMPGE", "IF_ICMPGT", "IF_ICMPLE", "IF_ACMPEQ", "IF_ACMPNE", "GOTO", "JSR", "RET", - "TABLESWITCH", + "TABLESWITCH", "LOOKUPSWITCH", "IRETURN", "LRETURN", "FRETURN", "DRETURN", "ARETURN", "RETURN", "GETSTATIC", "PUTSTATIC", "GETFIELD", "PUTFIELD", - "INVOKEVIRTUAL", + "INVOKEVIRTUAL", "INVOKESPECIAL", "INVOKESTATIC", "INVOKEINTERFACE", "_OPCODE_UNDEFINED", "NEW", "NEWARRAY", "ANEWARRAY", "ARRAYLENGTH", "ATHROW", "CHECKCAST", "INSTANCEOF", "MONITORENTER", "MONITOREXIT", "WIDE", "MULTIANEWARRAY", "IFNULL", "IFNONNULL", "GOTO_W", "JSR_W", }; -#endif // _VERIFY_DEBUG +#endif // _VF_DEBUG /** * Function provides method bytecode verifications. */ -static Verifier_Result -vf_verify_method_bytecode( vf_Context_t * ctex ) // verifier context +static vf_Result +vf_verify_method_bytecode( vf_Context *ctx ) // verification context { - unsigned len; - Verifier_Result result = VER_OK; + vf_Result result = VER_OK; - VERIFY_TRACE( "method", - "verify method: " << class_get_name( ctex->m_class ) - << "." << method_get_name( ctex-> - m_method ) << - method_get_descriptor( ctex->m_method ) ); - - /** - * Getting bytecode array and its length - */ - if( !( len = method_get_code_length( ctex->m_method ) ) ) { - return VER_OK; - } + VF_TRACE( "method", "verify method: " << class_get_name( ctx->m_class ) + << "." << method_get_name( ctx-> + m_method ) << + method_get_descriptor( ctx->m_method ) ); /** * Set method for type pool */ - ctex->m_type->SetMethod( ctex->m_method ); - - /** - * Allocate memory for code and bytecode annotations. - */ - ctex->m_code = (vf_Code_t*) vf_alloc_pool_memory( ctex->m_pool, - len * - sizeof - ( vf_Code_t ) ); - ctex->m_bc = - (vf_BCode_t*) vf_alloc_pool_memory( ctex->m_pool, - len * sizeof( vf_BCode_t ) ); + ctx->m_type->SetMethod( ctx->m_method ); - /** - * Parse bytecode, fill instruction code. - */ - result = vf_parse_bytecode( ctex ); + // parse bytecode, fill instruction instr + result = vf_parse_bytecode( ctx ); if( result != VER_OK ) { goto labelEnd_verifyClassBytecode; } - /** - * Build bytecode graph - */ - result = vf_create_graph( ctex ); - if( ctex->m_dump.m_with_subroutine ) { - result = VER_NoSupportJSR; + // build a control flow graph + result = vf_create_graph( ctx ); + if( result != VER_OK ) { goto labelEnd_verifyClassBytecode; - result = vf_inline_subroutines( ctex ); - if( VER_OK != result ) { - goto labelEnd_verifyClassBytecode; - } } - // check control and data flow - result = vf_check_graph( ctex ); + + result = vf_check_graph( ctx ); if( result != VER_OK ) { goto labelEnd_verifyClassBytecode; } labelEnd_verifyClassBytecode: - vf_free_graph( ctex ); + vf_free_graph( ctx ); return result; } // vf_verify_method_bytecode @@ -158,45 +129,41 @@ vf_verify_method_bytecode( vf_Context_t ************************************************************/ /** - * Function creates array of instruction branch offsets. + * Creates array of instruction branch offsets. */ static inline void -vf_create_code_offset( vf_Code_t * code, // given instruction - unsigned offcount, // number of offets - vf_VerifyPool_t * pool ) // memory pool -{ - assert( !code->m_off ); - code->m_off = - ( unsigned * )vf_alloc_pool_memory( pool, - offcount * sizeof( unsigned ) ); - code->m_offcount = offcount; - return; +vf_create_instr_offset( vf_Instr * instr, // given instruction + unsigned offcount, // number of offets + vf_Pool *pool ) // memory pool +{ + assert( !instr->m_off ); + instr->m_off = + ( unsigned * )vf_palloc( pool, offcount * sizeof( unsigned ) ); + instr->m_offcount = offcount; } // vf_create_instruction_offset /** - * Function sets code branch offset. + * Sets instruction branch offset. */ static inline void -vf_set_code_offset( vf_Code_t * code, // given instruction - unsigned offnum, // offset index in array - unsigned value ) // offset value +vf_set_instr_offset( vf_InstrHandle instr, // given instruction + unsigned offnum, // offset index in array + unsigned value ) // offset value { - assert( code->m_off && offnum < code->m_offcount ); - code->m_off[offnum] = value; - return; + assert( instr->m_off && offnum < instr->m_offcount ); + instr->m_off[offnum] = value; } // vf_set_instruction_offset /** * Function creates a single branch. */ static inline void -vf_set_single_branch_offset( vf_Code_t * code, // given instruction +vf_set_single_branch_offset( vf_Instr * instr, // given instruction unsigned value, // offset value - vf_VerifyPool_t * pool ) // memory pool + vf_Pool *pool ) // memory pool { - vf_create_code_offset( code, 1, pool ); - vf_set_code_offset( code, 0, value ); - return; + vf_create_instr_offset( instr, 1, pool ); + vf_set_instr_offset( instr, 0, value ); } // vf_set_single_instruction_offset /************************************************************ @@ -207,60 +174,61 @@ vf_set_single_branch_offset( vf_Code_t * * Function sets stack modifier attribute for given code instruction. */ static inline void -vf_set_stack_modifier( vf_Code_t * code, // code instruction +vf_set_stack_modifier( vf_Instr * instr, // code instruction int modify ) // stack modifier value { // set stack modifier for instruction - code->m_stack = ( short )modify; - return; + instr->m_stack = ( short )modify; } // vf_set_stack_modifier /** * Function sets minimal stack attribute for given code instruction. */ static inline void -vf_set_min_stack( vf_Code_t * code, // code instruction +vf_set_min_stack( vf_Instr * instr, // code instruction unsigned min_stack ) // minimal stack value { // set minimal stack for instruction - code->m_minstack = ( unsigned short )min_stack; - return; + instr->m_minstack = ( unsigned short )min_stack; } // vf_set_min_stack /** * Function sets basic block attribute for instruction. */ +const unsigned GOTO_W_LEN = 5; +/** + * Function sets basic block attribute for instruction. + */ static inline void -vf_set_basic_block_flag( vf_BCode_t * code ) // instruction +vf_set_basic_block_flag( unsigned short pc, vf_ContextHandle ctx ) { + assert( pc < ctx->m_len + GOTO_W_LEN ); // set begin of basic block for instruction - code->m_mark = 1; - return; + ctx->m_bc[pc].m_basic_block_start = true; } // vf_set_basic_block_flag + /** * Sets flags for the instruction. */ static inline void -vf_set_code_type( vf_Code_t * code, // instruction - vf_CodeType type ) // given flags +vf_set_instr_type( vf_Instr * instr, // instruction + vf_InstrType type ) // given flags { // set flag for instruction - code->m_type = type; - return; -} // vf_set_code_type + instr->m_type = type; +} // vf_set_instr_type /** * Function checks local number. */ -static inline Verifier_Result +static inline vf_Result vf_check_local_var_number( unsigned local, // local number - unsigned maxlocal, // max local - vf_Context_t * ctex ) // verifier context + vf_Context *ctx ) // verification context { // check local variable number - if( local >= maxlocal ) { - VERIFY_REPORT_METHOD( ctex, "Incorrect usage of local variable" ); + if( local >= ctx->m_maxlocal ) { + VF_REPORT( ctx, "Incorrect usage of local variable" ); return VER_ErrorLocals; } return VER_OK; @@ -269,40 +237,39 @@ vf_check_local_var_number( unsigned loca /** * Function checks branch offset. */ -static inline Verifier_Result +static inline vf_Result vf_check_branch_offset( int offset, // given instruction offset - unsigned maxlen, // bytecode length - vf_Context_t * ctex ) // verifier context + vf_Context *ctx ) // verification context { - if( offset < 0 || ( unsigned )offset >= maxlen ) { - VERIFY_REPORT_METHOD( ctex, - "Instruction branch offset is out of range" ); + if( offset < 0 || ( unsigned )offset >= ctx->m_len ) { + VF_REPORT( ctx, "Instruction branch offset is out of range" ); return VER_ErrorBranch; } + ctx->m_bc[offset].m_basic_block_start = true; return VER_OK; } // vf_check_branch_offset /** * Function parses local variable number from instruction bytecode. */ -static inline unsigned -vf_get_local_var_number( vf_Code_t * code, // code instruction +static inline unsigned short +vf_get_local_var_number( vf_InstrHandle instr, // code instruction unsigned char *bytecode, // method bytecode unsigned *index_p, // index in bytecode array bool wide_flag ) // if this is a wide instruction { - unsigned local; + unsigned short local; if( ( wide_flag ) ) { // get number of local variable local = - ( unsigned )( ( bytecode[( *index_p )] << 8 ) | - ( bytecode[( *index_p ) + 1] ) ); + ( unsigned short )( ( bytecode[( *index_p )] << 8 ) | + ( bytecode[( *index_p ) + 1] ) ); // skip parameter (u2) ( *index_p ) += 2; } else { // get number of local variable - local = ( unsigned )bytecode[( *index_p )]; + local = ( unsigned short )bytecode[( *index_p )]; // skip parameter (u1) ( *index_p )++; } @@ -353,16 +320,16 @@ vf_get_word_offset( unsigned code_pc, * sets into instruction and returns it. */ static inline int -vf_get_single_hword_branch_offset( vf_Code_t * code, // instruction +vf_get_single_hword_branch_offset( vf_Instr * instr, // instruction unsigned code_pc, // offset in bytecode array unsigned char *bytecode, // bytecode array unsigned *index_p, // offset index in bytecode array - vf_VerifyPool_t * pool ) // memory pool + vf_Pool *pool ) // memory pool { // get first branch offset int offset = vf_get_hword_offset( code_pc, bytecode, index_p ); // create and set edge branch for instruction - vf_set_single_branch_offset( code, offset, pool ); + vf_set_single_branch_offset( instr, offset, pool ); return offset; } // vf_get_single_hword_branch_offset @@ -371,16 +338,16 @@ vf_get_single_hword_branch_offset( vf_Co * sets into instruction and returns it. */ static inline int -vf_get_single_word_branch_offset( vf_Code_t * code, // instruction +vf_get_single_word_branch_offset( vf_Instr * instr, // instruction unsigned code_pc, // offset in bytecode array unsigned char *bytecode, // bytecode array unsigned *index_p, // offset index in bytecode array - vf_VerifyPool_t * pool ) // memory pool + vf_Pool *pool ) // memory pool { // get first branch offset int offset = vf_get_word_offset( code_pc, bytecode, index_p ); // create and set edge branch for instruction - vf_set_single_branch_offset( code, offset, pool ); + vf_set_single_branch_offset( instr, offset, pool ); return offset; } // vf_get_single_word_branch_offset @@ -390,20 +357,20 @@ vf_get_single_word_branch_offset( vf_Cod * Function returns received offset. */ static inline int -vf_get_double_hword_branch_offset( vf_Code_t * code, // instruction +vf_get_double_hword_branch_offset( vf_Instr * instr, // instruction unsigned code_pc, // instruction offset in bytcode array unsigned char *bytecode, // bytecode array unsigned *index_p, // offset index in bytecode array - vf_VerifyPool_t * pool ) // memory pool + vf_Pool *pool ) // memory pool { // get first branch offset int offset = vf_get_hword_offset( code_pc, bytecode, index_p ); // create and set edge branches for instruction - vf_create_code_offset( code, 2, pool ); + vf_create_instr_offset( instr, 2, pool ); // set first edge branch for instruction - vf_set_code_offset( code, 0, offset ); + vf_set_instr_offset( instr, 0, offset ); // set second edge branch for instruction - vf_set_code_offset( code, 1, ( *index_p ) ); + vf_set_instr_offset( instr, 1, ( *index_p ) ); return offset; } // vf_get_double_hword_branch_offset @@ -413,20 +380,20 @@ vf_get_double_hword_branch_offset( vf_Co * Function returns received offset. */ static inline int -vf_get_double_word_branch_offset( vf_Code_t * code, // instruction +vf_get_double_word_branch_offset( vf_Instr * instr, // instruction unsigned code_pc, // instruction offset in bytcode array unsigned char *bytecode, // bytecode array unsigned *index_p, // offset index in bytecode array - vf_VerifyPool_t * pool ) // memory pool + vf_Pool *pool ) // memory pool { // get first branch offset int offset = vf_get_word_offset( code_pc, bytecode, index_p ); // create and set edge branches for instruction - vf_create_code_offset( code, 2, pool ); + vf_create_instr_offset( instr, 2, pool ); // set first edge branch for instruction - vf_set_code_offset( code, 0, offset ); + vf_set_instr_offset( instr, 0, offset ); // set second edge branch for instruction - vf_set_code_offset( code, 1, ( *index_p ) ); + vf_set_instr_offset( instr, 1, ( *index_p ) ); return offset; } // vf_get_double_word_branch_offset @@ -436,7 +403,7 @@ vf_get_double_word_branch_offset( vf_Cod * Function returns received branch. */ static inline int -vf_get_tableswitch_alternative( vf_Code_t * code, // instruction +vf_get_tableswitch_alternative( vf_InstrHandle instr, // instruction unsigned code_pc, // offset in bytcode array unsigned alternative, // number of tableswitch branch unsigned char *bytecode, // bytecode array @@ -445,7 +412,7 @@ vf_get_tableswitch_alternative( vf_Code_ // get first branch offset int offset = vf_get_word_offset( code_pc, bytecode, index_p ); // set first edge branch for instruction - vf_set_code_offset( code, alternative, offset ); + vf_set_instr_offset( instr, alternative, offset ); return offset; } // vf_get_tableswitch_alternative @@ -455,11 +422,11 @@ vf_get_tableswitch_alternative( vf_Code_ * Function returns number of alternatives. */ static inline int -vf_set_tableswitch_offsets( vf_Code_t * code, // instruction +vf_set_tableswitch_offsets( vf_Instr * instr, // instruction unsigned code_pc, // instruction offset in bytecode array unsigned *index_p, // offset index in bytecode array unsigned char *bytecode, // bytecode array - vf_VerifyPool_t * pool ) // memory pool + vf_Pool *pool ) // memory pool { // skip padding unsigned default_off = ( ( *index_p ) + 0x3 ) & ( ~0x3U ); @@ -471,13 +438,13 @@ vf_set_tableswitch_offsets( vf_Code_t * int high = vf_get_word_offset( code_pc, bytecode, &index ); int number = high - low + 2; // create tableswitch branches - vf_create_code_offset( code, number, pool ); + vf_create_instr_offset( instr, number, pool ); // set default offset - vf_get_tableswitch_alternative( code, code_pc, 0, bytecode, + vf_get_tableswitch_alternative( instr, code_pc, 0, bytecode, &default_off ); // set another instruction offsets for( int count = 1; count < number; count++ ) { - vf_get_tableswitch_alternative( code, code_pc, count, bytecode, + vf_get_tableswitch_alternative( instr, code_pc, count, bytecode, &index ); } // set index next instruction @@ -490,13 +457,13 @@ vf_set_tableswitch_offsets( vf_Code_t * * sets them into instruction. * Function returns number of alternatives. */ -static inline Verifier_Result -vf_set_lookupswitch_offsets( vf_Code_t * code, // instruction +static inline vf_Result +vf_set_lookupswitch_offsets( vf_Instr * instr, // instruction unsigned code_pc, // instruction offset in bytecode unsigned *index_p, // offset index in bytecode array unsigned char *bytecode, // array of bytecode unsigned *branch_p, // number of alternatives - vf_Context_t * ctex ) // verifier context + vf_Context *ctx ) // verification context { // skip padding unsigned default_off = ( ( *index_p ) + 0x3 ) & ( ~0x3U ); @@ -507,9 +474,9 @@ vf_set_lookupswitch_offsets( vf_Code_t * int number = vf_get_word_offset( 0, bytecode, &index ) + 1; *branch_p = number; // create and tableswitch branches - vf_create_code_offset( code, number, ctex->m_pool ); + vf_create_instr_offset( instr, number, ctx->m_pool ); // set default offset - vf_get_tableswitch_alternative( code, code_pc, 0, bytecode, + vf_get_tableswitch_alternative( instr, code_pc, 0, bytecode, &default_off ); // set another instruction offsets int old_key = INT_MIN; @@ -519,12 +486,12 @@ vf_set_lookupswitch_offsets( vf_Code_t * if( old_key < key ) { old_key = key; } else if( key != INT_MIN ) { - VERIFY_REPORT_METHOD( ctex, - "Instruction lookupswitch has unsorted key values" ); + VF_REPORT( ctx, + "Instruction lookupswitch has unsorted key values" ); return VER_ErrorInstruction; } // get lookupswitch alternative and set offset to instruction - vf_get_tableswitch_alternative( code, code_pc, count, bytecode, + vf_get_tableswitch_alternative( instr, code_pc, count, bytecode, &index ); } // set index next instruction @@ -540,36 +507,34 @@ vf_set_lookupswitch_offsets( vf_Code_t * * Function sets check type for a given stack map vector entry. */ static inline void -vf_set_vector_check( vf_MapEntry_t * vector, // stack map vector +vf_set_vector_check( vf_MapEntry *vector, // stack map vector unsigned num, // vector entry number - vf_CheckConstraint_t check ) // constraint check type + vf_CheckConstraint check ) // constraint check type { // set check for map vector entry assert( check < VF_CHECK_NUM ); vector[num].m_ctype = check; - return; } // vf_set_vector_check /** * Function sets constraint pool index for a given stack map vector entry. */ static inline void -vf_set_vector_check_index( vf_MapEntry_t * vector, // stack map vector +vf_set_vector_check_index( vf_MapEntry *vector, // stack map vector unsigned num, // vector entry number unsigned short index ) // constraint pool index { // set index for a map vector entry vector[num].m_index = index; - return; } // vf_set_vector_check_index /** * Function sets a given data type to stack map vector entry. */ static inline void -vf_set_vector_type( vf_MapEntry_t * vector, // stack map vector +vf_set_vector_type( vf_MapEntry *vector, // stack map vector unsigned num, // vector entry number - vf_MapType_t type ) // stack map entry type + vf_MapType type ) // stack map entry type { assert( type < SM_NUMBER ); vector[num].m_type = type; @@ -579,69 +544,64 @@ vf_set_vector_type( vf_MapEntry_t * vect * Function sets null data type for given stack map vector entry. */ static inline void -vf_set_vector_stack_entry_null( vf_MapEntry_t * vector, // stack map vector +vf_set_vector_stack_entry_null( vf_MapEntry *vector, // stack map vector unsigned num ) // vector entry number { // set stack map vector entry by null vector[num].m_type = SM_NULL; - return; } // vf_set_vector_stack_entry_null /** * Function sets int data type for given stack map vector entry. */ static inline void -vf_set_vector_stack_entry_int( vf_MapEntry_t * vector, // stack map vector +vf_set_vector_stack_entry_int( vf_MapEntry *vector, // stack map vector unsigned num ) // vector entry number { // set stack map vector entry by int vector[num].m_type = SM_INT; - return; } // vf_set_vector_stack_entry_int /** * Function sets float data type for given stack map vector entry. */ static inline void -vf_set_vector_stack_entry_float( vf_MapEntry_t * vector, // stack map vector +vf_set_vector_stack_entry_float( vf_MapEntry *vector, // stack map vector unsigned num ) // vector entry number { // set stack map vector entry by float vector[num].m_type = SM_FLOAT; - return; } // vf_set_vector_stack_entry_float /** * Function sets long data type for given stack map vector entry. */ static inline void -vf_set_vector_stack_entry_long( vf_MapEntry_t * vector, // stack map vector +vf_set_vector_stack_entry_long( vf_MapEntry *vector, // stack map vector unsigned num ) // vector entry number { // set stack map vector entry by long vector[num].m_type = SM_LONG_HI; vector[num + 1].m_type = SM_LONG_LO; - return; } // vf_set_vector_stack_entry_long /** * Function sets double data type for given stack map vector entry. */ static inline void -vf_set_vector_stack_entry_double( vf_MapEntry_t * vector, // stack map vector +vf_set_vector_stack_entry_double( vf_MapEntry *vector, // stack map vector unsigned num ) // vector entry number { // set stack map vector entry by double vector[num].m_type = SM_DOUBLE_HI; vector[num + 1].m_type = SM_DOUBLE_LO; - return; } // vf_set_vector_stack_entry_double /** * Function sets return address data type for given stack map vector entry. */ static inline void -vf_set_vector_stack_entry_addr( vf_MapEntry_t * vector, // stack map vector +vf_set_vector_stack_entry_addr( vf_MapEntry *vector, // stack map vector unsigned num, // vector entry number unsigned count ) // program count { @@ -654,32 +614,30 @@ vf_set_vector_stack_entry_addr( vf_MapEn * Function sets single word data type for given stack map vector entry. */ static inline void -vf_set_vector_stack_entry_word( vf_MapEntry_t * vector, // stack map vector +vf_set_vector_stack_entry_word( vf_MapEntry *vector, // stack map vector unsigned num ) // vector entry number { // set stack map vector entry by word vector[num].m_type = SM_WORD; - return; } // vf_set_vector_stack_entry_word /** * Function sets double word data type for given stack map vector entry. */ static inline void -vf_set_vector_stack_entry_word2( vf_MapEntry_t * vector, // stack map vector +vf_set_vector_stack_entry_word2( vf_MapEntry *vector, // stack map vector unsigned num ) // vector entry number { // set stack map vector entry by double word vector[num].m_type = SM_WORD2_HI; vector[num + 1].m_type = SM_WORD2_LO; - return; } // vf_set_vector_stack_entry_word2 /** * Function sets int data type for given local variable vector entry. */ static inline void -vf_set_vector_local_var_int( vf_MapEntry_t * vector, // local variable vector +vf_set_vector_local_var_int( vf_MapEntry *vector, // local variable vector unsigned num, // vector entry number unsigned local ) // number of local variable { @@ -687,14 +645,13 @@ vf_set_vector_local_var_int( vf_MapEntry vector[num].m_type = SM_INT; vector[num].m_is_local = true; vector[num].m_local = ( unsigned short )local; - return; } // vf_set_vector_local_var_int /** * Function sets float data type for given local variable vector entry. */ static inline void -vf_set_vector_local_var_float( vf_MapEntry_t * vector, // local variable vector +vf_set_vector_local_var_float( vf_MapEntry *vector, // local variable vector unsigned num, // vector entry number unsigned local ) // number of local variable { @@ -702,14 +659,13 @@ vf_set_vector_local_var_float( vf_MapEnt vector[num].m_type = SM_FLOAT; vector[num].m_is_local = true; vector[num].m_local = ( unsigned short )local; - return; } // vf_set_vector_local_var_float /** * Function sets long data type for given local variable vector entry. */ static inline void -vf_set_vector_local_var_long( vf_MapEntry_t * vector, // local variable vector +vf_set_vector_local_var_long( vf_MapEntry *vector, // local variable vector unsigned num, // vector entry number unsigned local ) // number of local variable { @@ -720,14 +676,13 @@ vf_set_vector_local_var_long( vf_MapEntr vector[num + 1].m_type = SM_LONG_LO; vector[num + 1].m_is_local = true; vector[num + 1].m_local = ( unsigned short )( local + 1 ); - return; } // vf_set_vector_local_var_long /** * Function sets double data type for given local variable vector entry. */ static inline void -vf_set_vector_local_var_double( vf_MapEntry_t * vector, // local variable vector +vf_set_vector_local_var_double( vf_MapEntry *vector, // local variable vector unsigned num, // vector entry number unsigned local ) // number of local variable { @@ -738,16 +693,15 @@ vf_set_vector_local_var_double( vf_MapEn vector[num + 1].m_type = SM_DOUBLE_LO; vector[num + 1].m_is_local = true; vector[num + 1].m_local = ( unsigned short )( local + 1 ); - return; } // vf_set_vector_local_var_double /** * Function sets reference data type for given local variable vector entry. */ static inline void -vf_set_vector_local_var_ref( vf_MapEntry_t * vector, // local variable vector +vf_set_vector_local_var_ref( vf_MapEntry *vector, // local variable vector unsigned num, // vector entry number - vf_ValidType_t * type, // reference type + vf_ValidType *type, // reference type unsigned local ) // number of local variable { // set stack map vector entry by reference @@ -755,14 +709,13 @@ vf_set_vector_local_var_ref( vf_MapEntry vector[num].m_vtype = type; vector[num].m_is_local = true; vector[num].m_local = ( unsigned short )local; - return; } // vf_set_vector_local_var_ref /** * Function sets return address data type for given local variable vector entry. */ static inline void -vf_set_vector_local_var_addr( vf_MapEntry_t * vector, // stack map vector +vf_set_vector_local_var_addr( vf_MapEntry *vector, // stack map vector unsigned num, // vector entry number unsigned count, // program count unsigned local ) // number of local variable @@ -778,16 +731,15 @@ vf_set_vector_local_var_addr( vf_MapEntr * Function sets a given data type for a given local variable vector entry. */ static inline void -vf_set_vector_local_var_type( vf_MapEntry_t * vector, // local variable vector +vf_set_vector_local_var_type( vf_MapEntry *vector, // local variable vector unsigned num, // vector entry number - vf_MapType_t type, // stack map entry type + vf_MapType type, // stack map entry type unsigned local ) // number of local variable { // set stack map vector entry by reference vector[num].m_type = type; vector[num].m_is_local = true; vector[num].m_local = ( unsigned short )local; - return; } // vf_set_vector_local_var_type /************************************************************ @@ -798,229 +750,196 @@ vf_set_vector_local_var_type( vf_MapEntr * Allocates memory for new code instruction in the IN stack map vector. */ static inline void -vf_new_in_vector( vf_Code_t * code, // code instruction +vf_new_in_vector( vf_Instr * instr, // code instruction unsigned len, // vector length - vf_VerifyPool_t * pool ) // memory pool + vf_Pool *pool ) // memory pool { // create IN vector - code->m_inlen = ( unsigned short )len; - code->m_invector = - (vf_MapEntry_t*) vf_alloc_pool_memory( pool, - len * - sizeof( vf_MapEntry_t ) ); - return; + instr->m_inlen = ( unsigned short )len; + instr->m_invector = + (vf_MapEntry*)vf_palloc( pool, len * sizeof( vf_MapEntry ) ); } // vf_new_in_vector /** * Sets check attribute for a code instruction in the IN stack map vector entry. */ static inline void -vf_set_in_vector_check( vf_Code_t * code, // code instruction +vf_set_in_vector_check( vf_InstrHandle instr, // code instruction unsigned num, // IN vector entry number - vf_CheckConstraint_t check ) // constraint check type + vf_CheckConstraint check ) // constraint check type { - vf_set_vector_check( code->m_invector, num, check ); - return; + vf_set_vector_check( instr->m_invector, num, check ); } // vf_set_in_vector_check /** * Function sets constant pool index for a code instruction IN stack map vector entry. */ static inline void -vf_set_in_vector_check_index( vf_Code_t * code, // code instruction +vf_set_in_vector_check_index( vf_InstrHandle instr, // code instruction unsigned num, // IN vector entry number unsigned short index ) // constraint pool index { - vf_set_vector_check_index( code->m_invector, num, index ); - return; + vf_set_vector_check_index( instr->m_invector, num, index ); } // vf_set_in_vector_check_index /** * Function sets a given data type to stack map vector entry. */ static inline void -vf_set_in_vector_type( vf_Code_t * code, // code instruction +vf_set_in_vector_type( vf_InstrHandle instr, // code instruction unsigned num, // vector entry number - vf_MapType_t type ) // stack map entry type + vf_MapType type ) // stack map entry type { - vf_set_vector_type( code->m_invector, num, type ); - return; + vf_set_vector_type( instr->m_invector, num, type ); } // vf_set_in_vector_type /** * Function sets null data type for code instruction IN stack map vector entry. */ static inline void UNUSED -vf_set_in_vector_stack_entry_null( vf_Code_t * code, // code instruction +vf_set_in_vector_stack_entry_null( vf_InstrHandle instr, // code instruction unsigned num ) // IN vector entry number { - vf_set_vector_stack_entry_null( code->m_invector, num ); - return; + vf_set_vector_stack_entry_null( instr->m_invector, num ); } // vf_set_in_vector_stack_entry_null /** * Function sets int data type for code instruction IN stack map vector entry. */ static inline void -vf_set_in_vector_stack_entry_int( vf_Code_t * code, // code instruction +vf_set_in_vector_stack_entry_int( vf_InstrHandle instr, // code instruction unsigned num ) // IN vector entry number { - vf_set_vector_stack_entry_int( code->m_invector, num ); - return; + vf_set_vector_stack_entry_int( instr->m_invector, num ); } // vf_set_vector_stack_entry_int /** * Function sets float data type for code instruction IN stack map vector entry. */ static inline void -vf_set_in_vector_stack_entry_float( vf_Code_t * code, // code instruction +vf_set_in_vector_stack_entry_float( vf_InstrHandle instr, // code instruction unsigned num ) // IN vector entry number { - vf_set_vector_stack_entry_float( code->m_invector, num ); - return; + vf_set_vector_stack_entry_float( instr->m_invector, num ); } // vf_set_in_vector_stack_entry_float /** * Function sets long data type for code instruction IN stack map vector entry. */ static inline void -vf_set_in_vector_stack_entry_long( vf_Code_t * code, // code instruction +vf_set_in_vector_stack_entry_long( vf_InstrHandle instr, // code instruction unsigned num ) // IN vector entry number { - vf_set_vector_stack_entry_long( code->m_invector, num ); - return; + vf_set_vector_stack_entry_long( instr->m_invector, num ); } // vf_set_in_vector_stack_entry_long /** * Function sets double data type for code instruction IN stack map vector entry. */ static inline void -vf_set_in_vector_stack_entry_double( vf_Code_t * code, // code instruction +vf_set_in_vector_stack_entry_double( vf_InstrHandle instr, // code instruction unsigned num ) // IN vector entry number { - vf_set_vector_stack_entry_double( code->m_invector, num ); - return; + vf_set_vector_stack_entry_double( instr->m_invector, num ); } // vf_set_in_vector_stack_entry_double /** * Function sets reference data type for code instruction IN stack map vector entry. */ static inline void -vf_set_in_vector_stack_entry_ref( vf_Code_t * code, // code instruction +vf_set_in_vector_stack_entry_ref( vf_InstrHandle instr, // code instruction unsigned num, // IN vector entry number - vf_ValidType_t * type ) // reference type + vf_ValidType *type ) // reference type { - vf_set_vector_stack_entry_ref( code->m_invector, num, type ); - return; + vf_set_vector_stack_entry_ref( instr->m_invector, num, type ); } // vf_set_in_vector_stack_entry_ref /** * Function sets single word data type for code instruction IN stack map vector entry. */ static inline void -vf_set_in_vector_stack_entry_word( vf_Code_t * code, // code instruction +vf_set_in_vector_stack_entry_word( vf_InstrHandle instr, // code instruction unsigned num ) // IN vector entry number { - vf_set_vector_stack_entry_word( code->m_invector, num ); - return; + vf_set_vector_stack_entry_word( instr->m_invector, num ); } // vf_set_in_vector_stack_entry_word /** * Function sets double word data type for code instruction IN stack map vector entry. */ static inline void -vf_set_in_vector_stack_entry_word2( vf_Code_t * code, // code instruction +vf_set_in_vector_stack_entry_word2( vf_InstrHandle instr, // code instruction unsigned num ) // IN vector entry number { - vf_set_vector_stack_entry_word2( code->m_invector, num ); - return; + vf_set_vector_stack_entry_word2( instr->m_invector, num ); } // vf_set_in_vector_stack_entry_word2 /** * Function sets int data type for code instruction IN local variable vector entry. */ static inline void -vf_set_in_vector_local_var_int( vf_Code_t * code, // code instruction +vf_set_in_vector_local_var_int( vf_InstrHandle instr, // code instruction unsigned num, // IN vector entry number unsigned local ) // local variable number { - vf_set_vector_local_var_int( code->m_invector, num, local ); - return; + vf_set_vector_local_var_int( instr->m_invector, num, local ); } // vf_set_in_vector_local_var_int /** * Function sets float data type for code instruction IN local variable vector entry. */ static inline void -vf_set_in_vector_local_var_float( vf_Code_t * code, // code instruction +vf_set_in_vector_local_var_float( vf_InstrHandle instr, // code instruction unsigned num, // IN vector entry number unsigned local ) // local variable number { - vf_set_vector_local_var_float( code->m_invector, num, local ); - return; + vf_set_vector_local_var_float( instr->m_invector, num, local ); } // vf_set_in_vector_local_var_float /** * Function sets long data type for code instruction IN local variable vector entry. */ static inline void -vf_set_in_vector_local_var_long( vf_Code_t * code, // code instruction +vf_set_in_vector_local_var_long( vf_InstrHandle instr, // code instruction unsigned num, // IN vector entry number unsigned local ) // local variable number { - vf_set_vector_local_var_long( code->m_invector, num, local ); - return; + vf_set_vector_local_var_long( instr->m_invector, num, local ); } // vf_set_in_vector_local_var_long /** * Function sets double data type for code instruction IN local variable vector entry. */ static inline void -vf_set_in_vector_local_var_double( vf_Code_t * code, // code instruction +vf_set_in_vector_local_var_double( vf_InstrHandle instr, // code instruction unsigned num, // IN vector entry number unsigned local ) // local variable number { - vf_set_vector_local_var_double( code->m_invector, num, local ); - return; + vf_set_vector_local_var_double( instr->m_invector, num, local ); } // vf_set_in_vector_local_var_double /** * Function sets reference data type for code instruction IN local variable vector entry. */ static inline void -vf_set_in_vector_local_var_ref( vf_Code_t * code, // code instruction +vf_set_in_vector_local_var_ref( vf_InstrHandle instr, // code instruction unsigned num, // IN vector entry number - vf_ValidType_t * type, // reference type + vf_ValidType *type, // reference type unsigned local ) // local variable number { - vf_set_vector_local_var_ref( code->m_invector, num, type, local ); - return; + vf_set_vector_local_var_ref( instr->m_invector, num, type, local ); } // vf_set_in_vector_local_var_ref /** - * Function sets return address data type for code instruction IN local variable vector entry. - */ -static inline void -vf_set_in_vector_local_var_addr( vf_Code_t * code, // code instruction - unsigned num, // IN vector entry number - unsigned count, // program count - unsigned local ) // local variable number -{ - vf_set_vector_local_var_addr( code->m_invector, num, count, local ); - return; -} // vf_set_in_vector_local_var_addr - -/** * Function sets a given data type for code instruction IN local variable vector entry. */ static inline void UNUSED -vf_set_in_vector_local_var_type( vf_Code_t * code, // code instruction +vf_set_in_vector_local_var_type( vf_InstrHandle instr, // code instruction unsigned num, // IN vector entry number - vf_MapType_t type, // stack map entry + vf_MapType type, // stack map entry unsigned local ) // local variable number { - vf_set_vector_local_var_type( code->m_invector, num, type, local ); - return; + vf_set_vector_local_var_type( instr->m_invector, num, type, local ); } // vf_set_in_vector_local_var_type /************************************************************ @@ -1031,218 +950,187 @@ vf_set_in_vector_local_var_type( vf_Code * Function allocates memory for new code instruction OUT stack map vector. */ static inline void -vf_new_out_vector( vf_Code_t * code, // code instruction +vf_new_out_vector( vf_Instr * instr, // code instruction unsigned len, // vector length - vf_VerifyPool_t * pool ) // memory pool + vf_Pool *pool ) // memory pool { // create stack map OUT vector - code->m_outlen = ( unsigned short )len; - code->m_outvector = - (vf_MapEntry_t*) vf_alloc_pool_memory( pool, - len * - sizeof( vf_MapEntry_t ) ); - return; + instr->m_outlen = ( unsigned short )len; + instr->m_outvector = + (vf_MapEntry*)vf_palloc( pool, len * sizeof( vf_MapEntry ) ); } // vf_new_out_vector /** * Function sets check attribute for a code instruction OUT stack map vector entry. */ static inline void UNUSED -vf_set_out_vector_check( vf_Code_t * code, // code instruction +vf_set_out_vector_check( vf_InstrHandle instr, // code instruction unsigned num, // OUT vector entry number - vf_CheckConstraint_t check ) // constraint check type + vf_CheckConstraint check ) // constraint check type { - vf_set_vector_check( code->m_outvector, num, check ); - return; + vf_set_vector_check( instr->m_outvector, num, check ); } // vf_set_out_vector_check /** * Function sets check attribute for code instruction OUT stack map vector entry. */ static inline void UNUSED -vf_set_out_vector_check_index( vf_Code_t * code, // code instruction +vf_set_out_vector_check_index( vf_InstrHandle instr, // code instruction unsigned num, // OUT vector entry number unsigned short index ) // constraint pool index { - vf_set_vector_check_index( code->m_outvector, num, index ); - return; + vf_set_vector_check_index( instr->m_outvector, num, index ); } // vf_set_out_vector_check_index /** * Function sets a given data type to stack map OUT vector entry. */ static inline void -vf_set_out_vector_type( vf_Code_t * code, // code instruction +vf_set_out_vector_type( vf_InstrHandle instr, // code instruction unsigned num, // vector entry number - vf_MapType_t type ) // stack map entry type + vf_MapType type ) // stack map entry type { - vf_set_vector_type( code->m_outvector, num, type ); - return; + vf_set_vector_type( instr->m_outvector, num, type ); } // vf_set_out_vector_type /** * Function sets a given program counter to stack map OUT vector entry. */ static inline void -vf_set_out_vector_opcode_new( vf_Code_t * code, // code instruction +vf_set_out_vector_opcode_new( vf_InstrHandle instr, // code instruction unsigned num, // vector entry number unsigned opcode_new ) // new opcode { - code->m_outvector[num].m_new = opcode_new; - return; + instr->m_outvector[num].m_new = opcode_new; } // vf_set_out_vector_opcode_new /** * Function sets null data type for code instruction OUT stack map vector entry. */ static inline void UNUSED -vf_set_out_vector_stack_entry_null( vf_Code_t * code, // code instruction +vf_set_out_vector_stack_entry_null( vf_InstrHandle instr, // code instruction unsigned num ) // OUT vector entry number { - vf_set_vector_stack_entry_null( code->m_outvector, num ); - return; + vf_set_vector_stack_entry_null( instr->m_outvector, num ); } // vf_set_out_vector_stack_entry_null /** * Function sets int data type for code instruction OUT stack map vector entry. */ static inline void -vf_set_out_vector_stack_entry_int( vf_Code_t * code, // code instruction +vf_set_out_vector_stack_entry_int( vf_InstrHandle instr, // code instruction unsigned num ) // OUT vector entry number { - vf_set_vector_stack_entry_int( code->m_outvector, num ); - return; + vf_set_vector_stack_entry_int( instr->m_outvector, num ); } // vf_set_vector_stack_entry_int /** * Function sets float data type for code instruction OUT stack map vector entry. */ static inline void -vf_set_out_vector_stack_entry_float( vf_Code_t * code, // code instruction +vf_set_out_vector_stack_entry_float( vf_InstrHandle instr, // code instruction unsigned num ) // OUT vector entry number { - vf_set_vector_stack_entry_float( code->m_outvector, num ); - return; + vf_set_vector_stack_entry_float( instr->m_outvector, num ); } // vf_set_out_vector_stack_entry_float /** * Function sets long data type for code instruction OUT stack map vector entry. */ static inline void -vf_set_out_vector_stack_entry_long( vf_Code_t * code, // code instruction +vf_set_out_vector_stack_entry_long( vf_InstrHandle instr, // code instruction unsigned num ) // OUT vector entry number { - vf_set_vector_stack_entry_long( code->m_outvector, num ); - return; + vf_set_vector_stack_entry_long( instr->m_outvector, num ); } // vf_set_out_vector_stack_entry_long /** * Function sets double data type for code instruction OUT stack map vector entry. */ static inline void -vf_set_out_vector_stack_entry_double( vf_Code_t * code, // code instruction +vf_set_out_vector_stack_entry_double( vf_InstrHandle instr, // code instruction unsigned num ) // OUT vector entry number { - vf_set_vector_stack_entry_double( code->m_outvector, num ); - return; + vf_set_vector_stack_entry_double( instr->m_outvector, num ); } // vf_set_out_vector_stack_entry_double /** * Function sets reference data type for code instruction OUT stack map vector entry. */ static inline void -vf_set_out_vector_stack_entry_ref( vf_Code_t * code, // code instruction +vf_set_out_vector_stack_entry_ref( vf_InstrHandle instr, // code instruction unsigned num, // OUT vector entry number - vf_ValidType_t * type ) // reference type + vf_ValidType *type ) // reference type { - vf_set_vector_stack_entry_ref( code->m_outvector, num, type ); - return; + vf_set_vector_stack_entry_ref( instr->m_outvector, num, type ); } // vf_set_out_vector_stack_entry_ref /** - * Function sets return address data type for code instruction OUT stack map vector entry. - */ -static inline void -vf_set_out_vector_stack_entry_addr( vf_Code_t * code, // code instruction - unsigned num, // OUT vector entry number - unsigned count ) // program count -{ - vf_set_vector_stack_entry_addr( code->m_outvector, num, count ); - return; -} // vf_set_out_vector_stack_entry_addr - -/** * Function sets int data type for code instruction OUT local variable vector entry. */ static inline void -vf_set_out_vector_local_var_int( vf_Code_t * code, // code instruction +vf_set_out_vector_local_var_int( vf_InstrHandle instr, // code instruction unsigned num, // OUT vector entry number unsigned local ) // local variable number { - vf_set_vector_local_var_int( code->m_outvector, num, local ); - return; + vf_set_vector_local_var_int( instr->m_outvector, num, local ); } // vf_set_out_vector_local_var_int /** * Function sets float data type for code instruction OUT local variable vector entry. */ static inline void -vf_set_out_vector_local_var_float( vf_Code_t * code, // code instruction +vf_set_out_vector_local_var_float( vf_InstrHandle instr, // code instruction unsigned num, // OUT vector entry number unsigned local ) // local variable number { - vf_set_vector_local_var_float( code->m_outvector, num, local ); - return; + vf_set_vector_local_var_float( instr->m_outvector, num, local ); } // vf_set_out_vector_local_var_float /** * Function sets long data type for code instruction OUT local variable vector entry. */ static inline void -vf_set_out_vector_local_var_long( vf_Code_t * code, // code instruction +vf_set_out_vector_local_var_long( vf_InstrHandle instr, // code instruction unsigned num, // OUT vector entry number unsigned local ) // local variable number { - vf_set_vector_local_var_long( code->m_outvector, num, local ); - return; + vf_set_vector_local_var_long( instr->m_outvector, num, local ); } // vf_set_out_vector_local_var_long /** * Function sets double data type for code instruction OUT local variable vector entry. */ static inline void -vf_set_out_vector_local_var_double( vf_Code_t * code, // code instruction +vf_set_out_vector_local_var_double( vf_InstrHandle instr, // code instruction unsigned num, // OUT vector entry number unsigned local ) // local variable number { - vf_set_vector_local_var_double( code->m_outvector, num, local ); - return; + vf_set_vector_local_var_double( instr->m_outvector, num, local ); } // vf_set_out_vector_local_var_double /** * Function sets reference data type for code instruction OUT local variable vector entry. */ static inline void UNUSED -vf_set_out_vector_local_var_ref( vf_Code_t * code, // code instruction +vf_set_out_vector_local_var_ref( vf_InstrHandle instr, // code instruction unsigned num, // OUT vector entry number - vf_ValidType_t * type, // reference type + vf_ValidType *type, // reference type unsigned local ) // local variable number { - vf_set_vector_local_var_ref( code->m_outvector, num, type, local ); - return; + vf_set_vector_local_var_ref( instr->m_outvector, num, type, local ); } // vf_set_out_vector_local_var_ref /** * Function sets a given data type for code instruction OUT local variable vector entry. */ static inline void -vf_set_out_vector_local_var_type( vf_Code_t * code, // code instruction +vf_set_out_vector_local_var_type( vf_InstrHandle instr, // code instruction unsigned num, // OUT vector entry number - vf_MapType_t type, // stack map entry + vf_MapType type, // stack map entry unsigned local ) // local variable number { - vf_set_vector_local_var_type( code->m_outvector, num, type, local ); - return; + vf_set_vector_local_var_type( instr->m_outvector, num, type, local ); } // vf_set_in_vector_local_var_type /************************************************************ @@ -1280,13 +1168,13 @@ vf_parse_description( const char *descr, // skip method name do { index++; -#if _VERIFY_DEBUG +#if _VF_DEBUG if( !descr[index] ) { - VERIFY_DEBUG + VF_DEBUG ( "vf_parse_description: incorrect structure of constant pool" ); vf_error(); } -#endif // _VERIFY_DEBUG +#endif // _VF_DEBUG } while( descr[index] != ';' ); case 'B': case 'C': @@ -1314,13 +1202,13 @@ vf_parse_description( const char *descr, // skip array structure do { index++; -#if _VERIFY_DEBUG +#if _VF_DEBUG if( !descr[index] ) { - VERIFY_DEBUG + VF_DEBUG ( "vf_parse_description: incorrect structure of constant pool" ); vf_error(); } -#endif // _VERIFY_DEBUG +#endif // _VF_DEBUG } while( descr[index] == '[' ); index--; ( *count )++; // increase stack value @@ -1339,20 +1227,17 @@ vf_parse_description( const char *descr, break; } } - return; } // vf_parse_description static inline void vf_set_array_ref( const char *type, unsigned len, - vf_MapEntry_t * vector, - unsigned *index, vf_Context_t * ctex ) + vf_MapEntry *vector, unsigned *index, vf_ContextHandle ctx ) { // set array reference entry - vf_ValidType_t *valid = ctex->m_type->NewType( type, len ); + vf_ValidType *valid = ctx->m_type->NewType( type, len ); vf_set_vector_stack_entry_ref( vector, *index, valid ); ( *index )++; - return; } // vf_set_array_ref /** @@ -1364,15 +1249,15 @@ vf_set_description_vector( const char *d int add, // additional number of entries // to IN data flow vector int outlen, // number of entries for OUT vector - vf_MapEntry_t ** invector, // pointer to IN vector - vf_MapEntry_t ** outvector, // pointer to OUT vector - vf_Context_t * ctex ) // verifier context + vf_MapEntry **invector, // pointer to IN vector + vf_MapEntry **outvector, // pointer to OUT vector + vf_ContextHandle ctx ) // verification context { const char *type = 0; unsigned index, count = 0, vector_index; - vf_MapEntry_t **vector; - vf_ValidType_t *valid; - vf_VerifyPool_t *pool = ctex->m_pool; + vf_MapEntry **vector; + vf_ValidType *valid; + vf_Pool *pool = ctx->m_pool; /** * Check parameters @@ -1409,12 +1294,12 @@ vf_set_description_vector( const char *d } while( descr[index] != ';' ); if( !array ) { // set vector reference entry - valid = ctex->m_type->NewType( type, index - count ); + valid = ctx->m_type->NewType( type, index - count ); vf_set_vector_stack_entry_ref( *vector, vector_index, valid ); vector_index++; } else { vf_set_array_ref( type, index - count, *vector, &vector_index, - ctex ); + ctx ); // reset array structure array = false; } @@ -1428,13 +1313,13 @@ vf_set_description_vector( const char *d // set integer array type unsigned iter; unsigned len = index - count + 1; - char *int_array = (char*)vf_alloc_pool_memory( pool, len ); + char *int_array = (char*)vf_palloc( pool, len ); for( iter = 0; iter < len - 1; iter++ ) { int_array[iter] = '['; } int_array[iter] = 'B'; vf_set_array_ref( int_array, len, *vector, &vector_index, - ctex ); + ctx ); // reset array structure array = false; } @@ -1449,7 +1334,7 @@ vf_set_description_vector( const char *d vector_index++; } else { vf_set_array_ref( type, index - count + 1, *vector, - &vector_index, ctex ); + &vector_index, ctx ); // reset array structure array = false; } @@ -1461,7 +1346,7 @@ vf_set_description_vector( const char *d vector_index++; } else { vf_set_array_ref( type, index - count + 1, *vector, - &vector_index, ctex ); + &vector_index, ctx ); // reset array structure array = false; } @@ -1473,7 +1358,7 @@ vf_set_description_vector( const char *d vector_index += 2; } else { vf_set_array_ref( type, index - count + 1, *vector, - &vector_index, ctex ); + &vector_index, ctx ); // reset array structure array = false; } @@ -1485,7 +1370,7 @@ vf_set_description_vector( const char *d vector_index += 2; } else { vf_set_array_ref( type, index - count + 1, *vector, - &vector_index, ctex ); + &vector_index, ctx ); // reset array structure array = false; } @@ -1516,7 +1401,6 @@ vf_set_description_vector( const char *d break; } } - return; } // vf_set_description_vector /************************************************************ @@ -1528,14 +1412,13 @@ vf_set_description_vector( const char *d */ static inline const char * vf_get_name_from_cp_nameandtype( unsigned short index, // constant pool entry index - vf_Context_t * ctex ) // verifier context + vf_ContextHandle ctx ) // verification context { // get name constant pool index unsigned short name_cp_index = - class_get_cp_name_index( ctex->m_class, index ); + class_get_cp_name_index( ctx->m_class, index ); // get name string from NameAndType constant pool entry - const char *name = - class_get_cp_utf8_bytes( ctex->m_class, name_cp_index ); + const char *name = class_get_cp_utf8_bytes( ctx->m_class, name_cp_index ); return name; } // vf_get_name_from_cp_nameandtype @@ -1545,14 +1428,14 @@ vf_get_name_from_cp_nameandtype( unsigne */ static inline const char * vf_get_decriptor_from_cp_nameandtype( unsigned short index, // constant pool entry index - vf_Context_t * ctex ) // verifier context + vf_ContextHandle ctx ) // verification context { // get description constant pool index unsigned short descr_cp_index = - class_get_cp_descriptor_index( ctex->m_class, index ); + class_get_cp_descriptor_index( ctx->m_class, index ); // get descriptor from NameAndType constant pool entry const char *descr = - class_get_cp_utf8_bytes( ctex->m_class, descr_cp_index ); + class_get_cp_utf8_bytes( ctx->m_class, descr_cp_index ); return descr; } // vf_get_cp_nameandtype @@ -1564,7 +1447,7 @@ static inline const char * vf_get_class_valid_type( const char *class_name, // class name size_t name_len, // class name length size_t * len, // length of created string - vf_VerifyPool_t * pool ) // memory pool + vf_Pool *pool ) // memory pool { char *result; @@ -1582,7 +1465,7 @@ vf_get_class_valid_type( const char *cla switch ( class_name[name_len - 1] ) { case 'Z': // set integer array type - result = (char*)vf_alloc_pool_memory( pool, ( *len ) + 1 ); + result = (char*)vf_palloc( pool, ( *len ) + 1 ); memcpy( result, class_name, name_len ); result[name_len - 1] = 'B'; break; @@ -1595,7 +1478,7 @@ vf_get_class_valid_type( const char *cla } else { // create class signature *len = name_len + 1; - result = (char*)vf_alloc_pool_memory( pool, ( *len ) + 1 ); + result = (char*)vf_palloc( pool, ( *len ) + 1 ); result[0] = 'L'; memcpy( &result[1], class_name, name_len ); } @@ -1605,19 +1488,19 @@ vf_get_class_valid_type( const char *cla /** * Function creates valid type by given class name. */ -vf_ValidType_t * +vf_ValidType * vf_create_class_valid_type( const char *class_name, // class name - vf_Context_t * ctex ) // verifier context + vf_ContextHandle ctx ) // verification context { size_t len; - vf_ValidType_t *result; + vf_ValidType *result; // get class valid type const char *type = vf_get_class_valid_type( class_name, strlen( class_name ), - &len, ctex->m_pool ); + &len, ctx->m_pool ); // create valid type - result = ctex->m_type->NewType( type, len ); + result = ctx->m_type->NewType( type, len ); return result; } // vf_create_class_valid_type @@ -1631,7 +1514,7 @@ vf_check_cp_ref( unsigned short index, const char **name, // pointer to name const char **descr, // pointer to descriptor const char **class_name, // pointer to class name - vf_Context_t * ctex ) // verifier context + vf_ContextHandle ctx ) // verification context { assert( name ); assert( descr ); @@ -1639,16 +1522,15 @@ vf_check_cp_ref( unsigned short index, // get class name if it's needed if( class_name ) { unsigned short class_cp_index = - class_get_cp_ref_class_index( ctex->m_class, index ); - *class_name = vf_get_cp_class_name( ctex->m_class, class_cp_index ); + class_get_cp_ref_class_index( ctx->m_class, index ); + *class_name = vf_get_cp_class_name( ctx->m_class, class_cp_index ); } // get name and descriptor from NameAndType constant pool entry unsigned short name_and_type_cp_index = - class_get_cp_ref_name_and_type_index( ctex->m_class, index ); - *name = vf_get_name_from_cp_nameandtype( name_and_type_cp_index, ctex ); + class_get_cp_ref_name_and_type_index( ctx->m_class, index ); + *name = vf_get_name_from_cp_nameandtype( name_and_type_cp_index, ctx ); *descr = - vf_get_decriptor_from_cp_nameandtype( name_and_type_cp_index, ctex ); - return; + vf_get_decriptor_from_cp_nameandtype( name_and_type_cp_index, ctx ); } // vf_check_cp_ref /** @@ -1656,23 +1538,23 @@ vf_check_cp_ref( unsigned short index, * Function sets IN and OUT vectors for constant pool entries. * Function returns result of check. */ -static Verifier_Result +static vf_Result vf_check_cp_method( unsigned short index, // constant pool entry index - vf_Parse_t * cp_parse, // entry parse result structure + vf_Parse * cp_parse, // entry parse result structure bool is_interface, // interface flag bool stack_with_ref, // stack with this reference flag - vf_Context_t * ctex ) // verifier context + vf_Context *ctx ) // verification context { // get constant pool length - unsigned short len = class_get_cp_size( ctex->m_class ); + unsigned short len = class_get_cp_size( ctx->m_class ); // check constant pool index - CHECK_CONST_POOL_ID( index, len, ctex ); + CHECK_CONST_POOL_ID( index, len, ctx ); // check constant pool type if( is_interface ) { - CHECK_CONST_POOL_INTERFACE( ctex, index ); + CHECK_CONST_POOL_INTERFACE( ctx, index ); } else { - CHECK_CONST_POOL_METHOD( ctex, index ); + CHECK_CONST_POOL_METHOD( ctx, index ); } // get method description and name @@ -1680,7 +1562,7 @@ vf_check_cp_method( unsigned short index const char *descr = NULL; const char *class_name; vf_check_cp_ref( index, &name, &descr, - ( stack_with_ref ? &class_name : NULL ), ctex ); + ( stack_with_ref ? &class_name : NULL ), ctx ); // check result assert( name ); assert( descr ); @@ -1697,17 +1579,17 @@ vf_check_cp_method( unsigned short index 1 /* ref + vector */ , cp_parse->method.m_outlen, &cp_parse->method.m_invector, - &cp_parse->method.m_outvector, ctex ); + &cp_parse->method.m_outvector, ctx ); // set first ref cp_parse->method.m_inlen += 1; - vf_ValidType_t *type = vf_create_class_valid_type( class_name, ctex ); + vf_ValidType *type = vf_create_class_valid_type( class_name, ctx ); vf_set_vector_stack_entry_ref( cp_parse->method.m_invector, 0, type ); } else { vf_set_description_vector( descr, cp_parse->method.m_inlen, 0 /* only vector */ , cp_parse->method.m_outlen, &cp_parse->method.m_invector, - &cp_parse->method.m_outvector, ctex ); + &cp_parse->method.m_outvector, ctx ); } return VER_OK; } // vf_check_cp_method @@ -1717,23 +1599,23 @@ vf_check_cp_method( unsigned short index * Function sets data flow vector for constant pool entry. * Function returns result of check. */ -static Verifier_Result +static vf_Result vf_check_cp_field( unsigned short index, // constant pool entry index - vf_Parse_t * cp_parse, // entry parse result structure + vf_Parse * cp_parse, // entry parse result structure bool stack_with_ref, // stack with this reference flag - vf_Context_t * ctex ) // verifier context + vf_Context *ctx ) // verification context { // check constant pool index and type - unsigned short len = class_get_cp_size( ctex->m_class ); - CHECK_CONST_POOL_ID( index, len, ctex ); - CHECK_CONST_POOL_FIELD( ctex, index ); + unsigned short len = class_get_cp_size( ctx->m_class ); + CHECK_CONST_POOL_ID( index, len, ctx ); + CHECK_CONST_POOL_FIELD( ctx, index ); // get field description and name const char *name = NULL; const char *descr = NULL; const char *class_name; vf_check_cp_ref( index, &name, &descr, - ( stack_with_ref ? &class_name : NULL ), ctex ); + ( stack_with_ref ? &class_name : NULL ), ctx ); // check result assert( name ); assert( descr ); @@ -1744,15 +1626,15 @@ vf_check_cp_field( unsigned short index, if( stack_with_ref ) { vf_set_description_vector( descr, cp_parse->field.f_vlen, 1 /* ref + vector */ , - 0, &cp_parse->field.f_vector, NULL, ctex ); + 0, &cp_parse->field.f_vector, NULL, ctx ); // set first ref cp_parse->field.f_vlen += 1; - vf_ValidType_t *type = vf_create_class_valid_type( class_name, ctex ); + vf_ValidType *type = vf_create_class_valid_type( class_name, ctx ); vf_set_vector_stack_entry_ref( cp_parse->field.f_vector, 0, type ); } else { vf_set_description_vector( descr, cp_parse->field.f_vlen, 0 /* only vector */ , - 0, &cp_parse->field.f_vector, NULL, ctex ); + 0, &cp_parse->field.f_vector, NULL, ctx ); } return VER_OK; } // vf_check_cp_field @@ -1762,21 +1644,21 @@ vf_check_cp_field( unsigned short index, * Function sets data flow vector for constant pool entry. * Function returns result of check. */ -static inline Verifier_Result +static inline vf_Result vf_check_cp_single_const( unsigned short index, // constant pool entry index - vf_Parse_t * cp_parse, // entry parse result structure - vf_Context_t * ctex ) // verifier context + vf_Parse * cp_parse, // entry parse result structure + vf_Context *ctx ) // verification context { // check constant pool index - unsigned short len = class_get_cp_size( ctex->m_class ); - CHECK_CONST_POOL_ID( index, len, ctex ); + unsigned short len = class_get_cp_size( ctx->m_class ); + CHECK_CONST_POOL_ID( index, len, ctx ); // create stack map entry cp_parse->field.f_vlen = 1; - vf_new_vector( &( cp_parse->field.f_vector ), 1, ctex->m_pool ); + vf_new_vector( &( cp_parse->field.f_vector ), 1, ctx->m_pool ); // check constant pool type and set stack map entry - vf_ValidType_t *type; - switch ( class_get_cp_tag( ctex->m_class, index ) ) { + vf_ValidType *type; + switch ( class_get_cp_tag( ctx->m_class, index ) ) { case _CONSTANT_Integer: vf_set_vector_stack_entry_int( cp_parse->field.f_vector, 0 ); break; @@ -1784,26 +1666,26 @@ vf_check_cp_single_const( unsigned short vf_set_vector_stack_entry_float( cp_parse->field.f_vector, 0 ); break; case _CONSTANT_String: - type = ctex->m_type->NewType( "Ljava/lang/String", 17 ); + type = ctx->m_type->NewType( "Ljava/lang/String", 17 ); vf_set_vector_stack_entry_ref( cp_parse->field.f_vector, 0, type ); break; case _CONSTANT_Class: - if( !vf_is_class_version_14( ctex ) ) { - type = ctex->m_type->NewType( "Ljava/lang/Class", 16 ); + if( !vf_is_class_version_14( ctx ) ) { + type = ctx->m_type->NewType( "Ljava/lang/Class", 16 ); vf_set_vector_stack_entry_ref( cp_parse->field.f_vector, 0, type ); break; } // if class version is 1.4 verifier fails in default default: - VERIFY_REPORT_METHOD( ctex, "Illegal type for constant pool entry #" - << index << ( vf_is_class_version_14( ctex ) - ? - ": CONSTANT_Integer, CONSTANT_Float or CONSTANT_String" - : - ": CONSTANT_Integer, CONSTANT_Float, CONSTANT_String " - "or CONSTANT_Class" ) - << " are expected for ldc/ldc_w instruction" ); + VF_REPORT( ctx, "Illegal type for constant pool entry #" + << index << ( vf_is_class_version_14( ctx ) + ? + ": CONSTANT_Integer, CONSTANT_Float or CONSTANT_String" + : + ": CONSTANT_Integer, CONSTANT_Float, CONSTANT_String " + "or CONSTANT_Class" ) + << " are expected for ldc/ldc_w instruction" ); return VER_ErrorConstantPool; } return VER_OK; @@ -1814,20 +1696,20 @@ vf_check_cp_single_const( unsigned short * Function sets data flow vector for constant pool entry. * Function returns result of check. */ -static inline Verifier_Result +static inline vf_Result vf_check_cp_double_const( unsigned short index, // constant pool entry index - vf_Parse_t * cp_parse, // entry parse result structure - vf_Context_t * ctex ) // verifier context + vf_Parse * cp_parse, // entry parse result structure + vf_Context *ctx ) // verification context { // check constant pool index - unsigned short len = class_get_cp_size( ctex->m_class ); - CHECK_CONST_POOL_ID( index, len, ctex ); + unsigned short len = class_get_cp_size( ctx->m_class ); + CHECK_CONST_POOL_ID( index, len, ctx ); // create stack map entry cp_parse->field.f_vlen = 2; - vf_new_vector( &( cp_parse->field.f_vector ), 2, ctex->m_pool ); + vf_new_vector( &( cp_parse->field.f_vector ), 2, ctx->m_pool ); // check constant pool type and set stack map entry - switch ( class_get_cp_tag( ctex->m_class, index ) ) { + switch ( class_get_cp_tag( ctx->m_class, index ) ) { case _CONSTANT_Double: vf_set_vector_stack_entry_double( cp_parse->field.f_vector, 0 ); break; @@ -1835,9 +1717,9 @@ vf_check_cp_double_const( unsigned short vf_set_vector_stack_entry_long( cp_parse->field.f_vector, 0 ); break; default: - VERIFY_REPORT_METHOD( ctex, "Illegal type in constant pool, " - << index << - ": CONSTANT_Double or CONSTANT_Long are expected" ); + VF_REPORT( ctx, "Illegal type in constant pool, " + << index << + ": CONSTANT_Double or CONSTANT_Long are expected" ); return VER_ErrorConstantPool; } return VER_OK; @@ -1848,26 +1730,26 @@ vf_check_cp_double_const( unsigned short * Function sets data flow vector for constant pool entry (if it's needed). * Function returns result of check. */ -static Verifier_Result +static vf_Result vf_check_cp_class( unsigned short index, // constant pool entry index - vf_Parse_t * cp_parse, // entry parse result structure - vf_Context_t * ctex ) // verifier context + vf_Parse * cp_parse, // entry parse result structure + vf_Context *ctx ) // verification context { // check constant pool index and type - unsigned short len = class_get_cp_size( ctex->m_class ); - CHECK_CONST_POOL_ID( index, len, ctex ); - CHECK_CONST_POOL_CLASS( ctex, index ); + unsigned short len = class_get_cp_size( ctx->m_class ); + CHECK_CONST_POOL_ID( index, len, ctx ); + CHECK_CONST_POOL_CLASS( ctx, index ); if( cp_parse ) { // create valid type - const char *name = vf_get_cp_class_name( ctex->m_class, index ); + const char *name = vf_get_cp_class_name( ctx->m_class, index ); // check result assert( name ); // create valid type for class - vf_ValidType_t *type = vf_create_class_valid_type( name, ctex ); + vf_ValidType *type = vf_create_class_valid_type( name, ctx ); // create stack map vector cp_parse->field.f_vlen = 1; - vf_new_vector( &cp_parse->field.f_vector, 1, ctex->m_pool ); + vf_new_vector( &cp_parse->field.f_vector, 1, ctx->m_pool ); vf_set_vector_stack_entry_ref( cp_parse->field.f_vector, 0, type ); } return VER_OK; @@ -1878,55 +1760,55 @@ vf_check_cp_class( unsigned short index, * Function sets data flow vectors for current constant pool entry. * Function returns parse result. */ -static Verifier_Result -vf_parse_const_pool( unsigned char code, // opcode number +static vf_Result +vf_parse_const_pool( unsigned char instr, // opcode number unsigned short index, // constant pool entry index - vf_Parse_t * cp_parse, // entry parse result structure - vf_Context_t * ctex ) // verifier context + vf_Parse * cp_parse, // entry parse result structure + vf_Context *ctx ) // verification context { - Verifier_Result result; + vf_Result result; - switch ( code ) { + switch ( instr ) { case OPCODE_INVOKEVIRTUAL: - result = vf_check_cp_method( index, cp_parse, false, true, ctex ); + result = vf_check_cp_method( index, cp_parse, false, true, ctx ); break; case OPCODE_INVOKESPECIAL: - result = vf_check_cp_method( index, cp_parse, false, true, ctex ); + result = vf_check_cp_method( index, cp_parse, false, true, ctx ); break; case OPCODE_INVOKESTATIC: - result = vf_check_cp_method( index, cp_parse, false, false, ctex ); + result = vf_check_cp_method( index, cp_parse, false, false, ctx ); break; case OPCODE_INVOKEINTERFACE: - result = vf_check_cp_method( index, cp_parse, true, true, ctex ); + result = vf_check_cp_method( index, cp_parse, true, true, ctx ); break; case OPCODE_GETSTATIC: case OPCODE_PUTSTATIC: - result = vf_check_cp_field( index, cp_parse, false, ctex ); + result = vf_check_cp_field( index, cp_parse, false, ctx ); break; case OPCODE_GETFIELD: case OPCODE_PUTFIELD: - result = vf_check_cp_field( index, cp_parse, true, ctex ); + result = vf_check_cp_field( index, cp_parse, true, ctx ); break; case OPCODE_LDC: case OPCODE_LDC_W: - result = vf_check_cp_single_const( index, cp_parse, ctex ); + result = vf_check_cp_single_const( index, cp_parse, ctx ); break; case OPCODE_LDC2_W: - result = vf_check_cp_double_const( index, cp_parse, ctex ); + result = vf_check_cp_double_const( index, cp_parse, ctx ); break; case OPCODE_NEW: - result = vf_check_cp_class( index, cp_parse, ctex ); + result = vf_check_cp_class( index, cp_parse, ctx ); break; case OPCODE_ANEWARRAY: case OPCODE_CHECKCAST: - result = vf_check_cp_class( index, cp_parse, ctex ); + result = vf_check_cp_class( index, cp_parse, ctx ); break; case OPCODE_INSTANCEOF: case OPCODE_MULTIANEWARRAY: - result = vf_check_cp_class( index, NULL, ctex ); + result = vf_check_cp_class( index, NULL, ctx ); break; default: - VERIFY_DEBUG + VF_DEBUG ( "vf_parse_const_pool: incorrect parse of code instruction" ); return VER_ErrorInternal; } @@ -1941,90 +1823,85 @@ vf_parse_const_pool( unsigned char code, * Function sets code instruction structure for opcode null. */ static inline void -vf_opcode_aconst_null( vf_Code_t * code, // code instruction - vf_VerifyPool_t * pool ) // memory pool +vf_opcode_aconst_null( vf_Instr * instr, // code instruction + vf_Pool *pool ) // memory pool { - vf_set_stack_modifier( code, 1 ); - vf_new_out_vector( code, 1, pool ); - vf_set_out_vector_stack_entry_ref( code, 0, NULL ); - return; + vf_set_stack_modifier( instr, 1 ); + vf_new_out_vector( instr, 1, pool ); + vf_set_out_vector_stack_entry_ref( instr, 0, NULL ); } // vf_opcode_aconst_null /** * Function sets code instruction structure for opcode iconst_n. */ static inline void -vf_opcode_iconst_n( vf_Code_t * code, // code instruction - vf_VerifyPool_t * pool ) // memory pool +vf_opcode_iconst_n( vf_Instr * instr, // code instruction + vf_Pool *pool ) // memory pool { - vf_set_stack_modifier( code, 1 ); - vf_new_out_vector( code, 1, pool ); - vf_set_out_vector_stack_entry_int( code, 0 ); - return; + vf_set_stack_modifier( instr, 1 ); + vf_new_out_vector( instr, 1, pool ); + vf_set_out_vector_stack_entry_int( instr, 0 ); } // vf_opcode_iconst_n /** * Function sets code instruction structure for opcode lconst_n. */ static inline void -vf_opcode_lconst_n( vf_Code_t * code, // code instruction - vf_VerifyPool_t * pool ) // memory pool +vf_opcode_lconst_n( vf_Instr * instr, // code instruction + vf_Pool *pool ) // memory pool { - vf_set_stack_modifier( code, 2 ); - vf_new_out_vector( code, 2, pool ); - vf_set_out_vector_stack_entry_long( code, 0 ); - return; + vf_set_stack_modifier( instr, 2 ); + vf_new_out_vector( instr, 2, pool ); + vf_set_out_vector_stack_entry_long( instr, 0 ); } // vf_opcode_lconst_n /** * Function sets code instruction structure for opcode fconst_n. */ static inline void -vf_opcode_fconst_n( vf_Code_t * code, // code instruction - vf_VerifyPool_t * pool ) // memory pool +vf_opcode_fconst_n( vf_Instr * instr, // code instruction + vf_Pool *pool ) // memory pool { - vf_set_stack_modifier( code, 1 ); - vf_new_out_vector( code, 1, pool ); - vf_set_out_vector_stack_entry_float( code, 0 ); - return; + vf_set_stack_modifier( instr, 1 ); + vf_new_out_vector( instr, 1, pool ); + vf_set_out_vector_stack_entry_float( instr, 0 ); } // vf_opcode_fconst_n /** * Function sets code instruction structure for opcode dconst_n. */ static inline void -vf_opcode_dconst_n( vf_Code_t * code, // code instruction - vf_VerifyPool_t * pool ) // memory pool +vf_opcode_dconst_n( vf_Instr * instr, // code instruction + vf_Pool *pool ) // memory pool { - vf_set_stack_modifier( code, 2 ); - vf_new_out_vector( code, 2, pool ); - vf_set_out_vector_stack_entry_double( code, 0 ); - return; + vf_set_stack_modifier( instr, 2 ); + vf_new_out_vector( instr, 2, pool ); + vf_set_out_vector_stack_entry_double( instr, 0 ); } // vf_opcode_dconst_n /** * Function sets code instruction structure for opcodes ldcx. */ -static inline Verifier_Result -vf_opcode_ldcx( vf_Code_t * code, // code instruction +static inline vf_Result +vf_opcode_ldcx( vf_Instr * instr, // code instruction int modifier, // instruction stack modifier unsigned short cp_index, // constant pool entry index - vf_Context_t * ctex ) // verifier context + vf_Context *ctx ) // verification context { - Verifier_Result result; - vf_Parse_t cp_parse = { 0 }; + vf_Result result; + vf_Parse cp_parse = { 0 }; // check constant pool for instruction result = - vf_parse_const_pool( *( code->m_addr ), cp_index, &cp_parse, ctex ); + vf_parse_const_pool( *( instr->m_addr ), cp_index, &cp_parse, ctx ); if( result != VER_OK ) { return result; } // set stack modifier for instruction - vf_set_stack_modifier( code, modifier ); + vf_set_stack_modifier( instr, modifier ); // set stack out vector - code->m_outvector = cp_parse.field.f_vector; - code->m_outlen = ( unsigned short )cp_parse.field.f_vlen; + instr->m_outvector = cp_parse.field.f_vector; + instr->m_outlen = ( unsigned short )cp_parse.field.f_vlen; return VER_OK; } // vf_opcode_ldcx @@ -2032,1663 +1909,1587 @@ vf_opcode_ldcx( vf_Code_t * code, * Function sets code instruction structure for opcodes iloadx. */ static inline void -vf_opcode_iloadx( vf_Code_t * code, // code instruction +vf_opcode_iloadx( vf_Instr * instr, // code instruction unsigned local, // local variable number - vf_VerifyPool_t * pool ) // memory pool + vf_Pool *pool ) // memory pool { // set stack modifier for instruction - vf_set_stack_modifier( code, 1 ); + vf_set_stack_modifier( instr, 1 ); // create in vector - vf_new_in_vector( code, 1, pool ); - vf_set_in_vector_local_var_int( code, 0, local ); + vf_new_in_vector( instr, 1, pool ); + vf_set_in_vector_local_var_int( instr, 0, local ); // create out vector - vf_new_out_vector( code, 1, pool ); - vf_set_out_vector_stack_entry_int( code, 0 ); - return; + vf_new_out_vector( instr, 1, pool ); + vf_set_out_vector_stack_entry_int( instr, 0 ); } // vf_opcode_iloadx /** * Function sets code instruction structure for opcodes lloadx. */ static inline void -vf_opcode_lloadx( vf_Code_t * code, // code instruction +vf_opcode_lloadx( vf_Instr * instr, // code instruction unsigned local, // local variable number - vf_VerifyPool_t * pool ) // memory pool + vf_Pool *pool ) // memory pool { // set stack modifier for instruction - vf_set_stack_modifier( code, 2 ); + vf_set_stack_modifier( instr, 2 ); // create in vector - vf_new_in_vector( code, 2, pool ); - vf_set_in_vector_local_var_long( code, 0, local ); + vf_new_in_vector( instr, 2, pool ); + vf_set_in_vector_local_var_long( instr, 0, local ); // create out vector - vf_new_out_vector( code, 2, pool ); - vf_set_out_vector_stack_entry_long( code, 0 ); - return; + vf_new_out_vector( instr, 2, pool ); + vf_set_out_vector_stack_entry_long( instr, 0 ); } // vf_opcode_lloadx /** * Function sets code instruction structure for opcodes floadx. */ static inline void -vf_opcode_floadx( vf_Code_t * code, // code instruction +vf_opcode_floadx( vf_Instr * instr, // code instruction unsigned local, // local variable number - vf_VerifyPool_t * pool ) // memory pool + vf_Pool *pool ) // memory pool { // set stack modifier for instruction - vf_set_stack_modifier( code, 1 ); + vf_set_stack_modifier( instr, 1 ); // create in vector - vf_new_in_vector( code, 1, pool ); - vf_set_in_vector_local_var_float( code, 0, local ); + vf_new_in_vector( instr, 1, pool ); + vf_set_in_vector_local_var_float( instr, 0, local ); // create out vector - vf_new_out_vector( code, 1, pool ); - vf_set_out_vector_stack_entry_float( code, 0 ); - return; + vf_new_out_vector( instr, 1, pool ); + vf_set_out_vector_stack_entry_float( instr, 0 ); } // vf_opcode_floadx /** * Function sets code instruction structure for opcodes dloadx. */ static inline void -vf_opcode_dloadx( vf_Code_t * code, // code instruction +vf_opcode_dloadx( vf_Instr * instr, // code instruction unsigned local, // local variable number - vf_VerifyPool_t * pool ) // memory pool + vf_Pool *pool ) // memory pool { // set stack modifier for instruction - vf_set_stack_modifier( code, 2 ); + vf_set_stack_modifier( instr, 2 ); // create in vector - vf_new_in_vector( code, 2, pool ); - vf_set_in_vector_local_var_double( code, 0, local ); + vf_new_in_vector( instr, 2, pool ); + vf_set_in_vector_local_var_double( instr, 0, local ); // create out vector - vf_new_out_vector( code, 2, pool ); - vf_set_out_vector_stack_entry_double( code, 0 ); - return; + vf_new_out_vector( instr, 2, pool ); + vf_set_out_vector_stack_entry_double( instr, 0 ); } // vf_opcode_dloadx /** * Function sets code instruction structure for opcodes aloadx. */ static inline void -vf_opcode_aloadx( vf_Code_t * code, // code instruction +vf_opcode_aloadx( vf_Instr * instr, // code instruction unsigned local, // local variable number - vf_VerifyPool_t * pool ) // memory pool + vf_Pool *pool ) // memory pool { // set stack modifier for instruction - vf_set_stack_modifier( code, 1 ); + vf_set_stack_modifier( instr, 1 ); // create in vector - vf_new_in_vector( code, 1, pool ); - vf_set_in_vector_local_var_ref( code, 0, NULL, local ); - vf_set_vector_check( code->m_invector, 0, VF_CHECK_UNINITIALIZED_THIS ); + vf_new_in_vector( instr, 1, pool ); + vf_set_in_vector_local_var_ref( instr, 0, NULL, local ); + vf_set_vector_check( instr->m_invector, 0, VF_CHECK_UNINITIALIZED_THIS ); // create out vector - vf_new_out_vector( code, 1, pool ); - vf_set_out_vector_type( code, 0, SM_COPY_0 ); - return; + vf_new_out_vector( instr, 1, pool ); + vf_set_out_vector_type( instr, 0, SM_COPY_0 ); } // vf_opcode_aloadx /** * Function sets code instruction structure for opcode iaload. */ static inline void -vf_opcode_iaload( vf_Code_t * code, // code instruction - vf_Context_t * ctex ) // verifier context +vf_opcode_iaload( vf_Instr * instr, // code instruction + vf_ContextHandle ctx ) // verification context { // set stack modifier for instruction - vf_set_stack_modifier( code, -1 ); + vf_set_stack_modifier( instr, -1 ); // set minimal stack for instruction - vf_set_min_stack( code, 2 ); + vf_set_min_stack( instr, 2 ); // create in vector - vf_new_in_vector( code, 2, ctex->m_pool ); + vf_new_in_vector( instr, 2, ctx->m_pool ); // create type - vf_ValidType_t *type = ctex->m_type->NewType( "[I", 2 ); - vf_set_in_vector_stack_entry_ref( code, 0, type ); - vf_set_in_vector_stack_entry_int( code, 1 ); + vf_ValidType *type = ctx->m_type->NewType( "[I", 2 ); + vf_set_in_vector_stack_entry_ref( instr, 0, type ); + vf_set_in_vector_stack_entry_int( instr, 1 ); // set check - vf_set_in_vector_check( code, 0, VF_CHECK_EQUAL ); + vf_set_in_vector_check( instr, 0, VF_CHECK_EQUAL ); // create out vector - vf_new_out_vector( code, 1, ctex->m_pool ); - vf_set_out_vector_stack_entry_int( code, 0 ); - return; + vf_new_out_vector( instr, 1, ctx->m_pool ); + vf_set_out_vector_stack_entry_int( instr, 0 ); } // vf_opcode_iaload /** * Function sets code instruction structure for opcode baload. */ static inline void -vf_opcode_baload( vf_Code_t * code, // code instruction - vf_Context_t * ctex ) // verifier context +vf_opcode_baload( vf_Instr * instr, // code instruction + vf_ContextHandle ctx ) // verification context { // set stack modifier for instruction - vf_set_stack_modifier( code, -1 ); + vf_set_stack_modifier( instr, -1 ); // set minimal stack for instruction - vf_set_min_stack( code, 2 ); + vf_set_min_stack( instr, 2 ); // create in vector - vf_new_in_vector( code, 2, ctex->m_pool ); + vf_new_in_vector( instr, 2, ctx->m_pool ); // create type - vf_ValidType_t *type = ctex->m_type->NewType( "[B", 2 ); - vf_set_in_vector_stack_entry_ref( code, 0, type ); - vf_set_in_vector_stack_entry_int( code, 1 ); + vf_ValidType *type = ctx->m_type->NewType( "[B", 2 ); + vf_set_in_vector_stack_entry_ref( instr, 0, type ); + vf_set_in_vector_stack_entry_int( instr, 1 ); // set check - vf_set_in_vector_check( code, 0, VF_CHECK_EQUAL ); + vf_set_in_vector_check( instr, 0, VF_CHECK_EQUAL ); // create out vector - vf_new_out_vector( code, 1, ctex->m_pool ); - vf_set_out_vector_stack_entry_int( code, 0 ); - return; + vf_new_out_vector( instr, 1, ctx->m_pool ); + vf_set_out_vector_stack_entry_int( instr, 0 ); } // vf_opcode_baload /** * Function sets code instruction structure for opcode caload. */ static inline void -vf_opcode_caload( vf_Code_t * code, // code instruction - vf_Context_t * ctex ) // verifier context +vf_opcode_caload( vf_Instr * instr, // code instruction + vf_ContextHandle ctx ) // verification context { // set stack modifier for instruction - vf_set_stack_modifier( code, -1 ); + vf_set_stack_modifier( instr, -1 ); // set minimal stack for instruction - vf_set_min_stack( code, 2 ); + vf_set_min_stack( instr, 2 ); // create in vector - vf_new_in_vector( code, 2, ctex->m_pool ); + vf_new_in_vector( instr, 2, ctx->m_pool ); // create type - vf_ValidType_t *type = ctex->m_type->NewType( "[C", 2 ); - vf_set_in_vector_stack_entry_ref( code, 0, type ); - vf_set_in_vector_stack_entry_int( code, 1 ); + vf_ValidType *type = ctx->m_type->NewType( "[C", 2 ); + vf_set_in_vector_stack_entry_ref( instr, 0, type ); + vf_set_in_vector_stack_entry_int( instr, 1 ); // set check - vf_set_in_vector_check( code, 0, VF_CHECK_EQUAL ); + vf_set_in_vector_check( instr, 0, VF_CHECK_EQUAL ); // create out vector - vf_new_out_vector( code, 1, ctex->m_pool ); - vf_set_out_vector_stack_entry_int( code, 0 ); - return; + vf_new_out_vector( instr, 1, ctx->m_pool ); + vf_set_out_vector_stack_entry_int( instr, 0 ); } // vf_opcode_caload /** * Function sets code instruction structure for opcode saload. */ static inline void -vf_opcode_saload( vf_Code_t * code, // code instruction - vf_Context_t * ctex ) // verifier context +vf_opcode_saload( vf_Instr * instr, // code instruction + vf_ContextHandle ctx ) // verification context { // set stack modifier for instruction - vf_set_stack_modifier( code, -1 ); + vf_set_stack_modifier( instr, -1 ); // set minimal stack for instruction - vf_set_min_stack( code, 2 ); + vf_set_min_stack( instr, 2 ); // create in vector - vf_new_in_vector( code, 2, ctex->m_pool ); + vf_new_in_vector( instr, 2, ctx->m_pool ); // create type - vf_ValidType_t *type = ctex->m_type->NewType( "[S", 2 ); - vf_set_in_vector_stack_entry_ref( code, 0, type ); - vf_set_in_vector_stack_entry_int( code, 1 ); + vf_ValidType *type = ctx->m_type->NewType( "[S", 2 ); + vf_set_in_vector_stack_entry_ref( instr, 0, type ); + vf_set_in_vector_stack_entry_int( instr, 1 ); // set check - vf_set_in_vector_check( code, 0, VF_CHECK_EQUAL ); + vf_set_in_vector_check( instr, 0, VF_CHECK_EQUAL ); // create out vector - vf_new_out_vector( code, 1, ctex->m_pool ); - vf_set_out_vector_stack_entry_int( code, 0 ); - return; + vf_new_out_vector( instr, 1, ctx->m_pool ); + vf_set_out_vector_stack_entry_int( instr, 0 ); } // vf_opcode_saload /** * Function sets code instruction structure for opcode laload. */ static inline void -vf_opcode_laload( vf_Code_t * code, // code instruction - vf_Context_t * ctex ) // verifier context +vf_opcode_laload( vf_Instr * instr, // code instruction + vf_ContextHandle ctx ) // verification context { // set minimal stack for instruction - vf_set_min_stack( code, 2 ); + vf_set_min_stack( instr, 2 ); // create in vector - vf_new_in_vector( code, 2, ctex->m_pool ); + vf_new_in_vector( instr, 2, ctx->m_pool ); // create type - vf_ValidType_t *type = ctex->m_type->NewType( "[J", 2 ); - vf_set_in_vector_stack_entry_ref( code, 0, type ); - vf_set_in_vector_stack_entry_int( code, 1 ); + vf_ValidType *type = ctx->m_type->NewType( "[J", 2 ); + vf_set_in_vector_stack_entry_ref( instr, 0, type ); + vf_set_in_vector_stack_entry_int( instr, 1 ); // set check - vf_set_in_vector_check( code, 0, VF_CHECK_EQUAL ); + vf_set_in_vector_check( instr, 0, VF_CHECK_EQUAL ); // create out vector - vf_new_out_vector( code, 2, ctex->m_pool ); - vf_set_out_vector_stack_entry_long( code, 0 ); - return; + vf_new_out_vector( instr, 2, ctx->m_pool ); + vf_set_out_vector_stack_entry_long( instr, 0 ); } // vf_opcode_laload /** * Function sets code instruction structure for opcode faload. */ static inline void -vf_opcode_faload( vf_Code_t * code, // code instruction - vf_Context_t * ctex ) // verifier context +vf_opcode_faload( vf_Instr * instr, // code instruction + vf_ContextHandle ctx ) // verification context { // set stack modifier for instruction - vf_set_stack_modifier( code, -1 ); + vf_set_stack_modifier( instr, -1 ); // set minimal stack for instruction - vf_set_min_stack( code, 2 ); + vf_set_min_stack( instr, 2 ); // create in vector - vf_new_in_vector( code, 2, ctex->m_pool ); + vf_new_in_vector( instr, 2, ctx->m_pool ); // create type - vf_ValidType_t *type = ctex->m_type->NewType( "[F", 2 ); - vf_set_in_vector_stack_entry_ref( code, 0, type ); - vf_set_in_vector_stack_entry_int( code, 1 ); + vf_ValidType *type = ctx->m_type->NewType( "[F", 2 ); + vf_set_in_vector_stack_entry_ref( instr, 0, type ); + vf_set_in_vector_stack_entry_int( instr, 1 ); // set check - vf_set_in_vector_check( code, 0, VF_CHECK_EQUAL ); + vf_set_in_vector_check( instr, 0, VF_CHECK_EQUAL ); // create out vector - vf_new_out_vector( code, 1, ctex->m_pool ); - vf_set_out_vector_stack_entry_float( code, 0 ); - return; + vf_new_out_vector( instr, 1, ctx->m_pool ); + vf_set_out_vector_stack_entry_float( instr, 0 ); } // vf_opcode_faload /** * Function sets code instruction structure for opcode daload. */ static inline void -vf_opcode_daload( vf_Code_t * code, // code instruction - vf_Context_t * ctex ) // verifier context +vf_opcode_daload( vf_Instr * instr, // code instruction + vf_ContextHandle ctx ) // verification context { // set minimal stack for instruction - vf_set_min_stack( code, 2 ); + vf_set_min_stack( instr, 2 ); // create in vector - vf_new_in_vector( code, 2, ctex->m_pool ); + vf_new_in_vector( instr, 2, ctx->m_pool ); // create type - vf_ValidType_t *type = ctex->m_type->NewType( "[D", 2 ); - vf_set_in_vector_stack_entry_ref( code, 0, type ); - vf_set_in_vector_stack_entry_int( code, 1 ); + vf_ValidType *type = ctx->m_type->NewType( "[D", 2 ); + vf_set_in_vector_stack_entry_ref( instr, 0, type ); + vf_set_in_vector_stack_entry_int( instr, 1 ); // set check - vf_set_in_vector_check( code, 0, VF_CHECK_EQUAL ); + vf_set_in_vector_check( instr, 0, VF_CHECK_EQUAL ); // create out vector - vf_new_out_vector( code, 2, ctex->m_pool ); - vf_set_out_vector_stack_entry_double( code, 0 ); - return; + vf_new_out_vector( instr, 2, ctx->m_pool ); + vf_set_out_vector_stack_entry_double( instr, 0 ); } // vf_opcode_daload /** * Function sets code instruction structure for opcode aaload. */ static inline void -vf_opcode_aaload( vf_Code_t * code, // code instruction - vf_Context_t * ctex ) // verifier context +vf_opcode_aaload( vf_Instr * instr, // code instruction + vf_ContextHandle ctx ) // verification context { // set stack modifier for instruction - vf_set_stack_modifier( code, -1 ); + vf_set_stack_modifier( instr, -1 ); // set minimal stack for instruction - vf_set_min_stack( code, 2 ); + vf_set_min_stack( instr, 2 ); // create in vector - vf_new_in_vector( code, 2, ctex->m_pool ); + vf_new_in_vector( instr, 2, ctx->m_pool ); // create type - vf_set_in_vector_stack_entry_ref( code, 0, NULL ); - vf_set_in_vector_check( code, 0, VF_CHECK_REF_ARRAY ); - vf_set_in_vector_stack_entry_int( code, 1 ); - // create out vector - vf_new_out_vector( code, 1, ctex->m_pool ); - vf_set_out_vector_type( code, 0, SM_UP_ARRAY ); - return; + vf_set_in_vector_stack_entry_ref( instr, 0, NULL ); + vf_set_in_vector_check( instr, 0, VF_CHECK_REF_ARRAY ); + vf_set_in_vector_stack_entry_int( instr, 1 ); + // create out vector + vf_new_out_vector( instr, 1, ctx->m_pool ); + vf_set_out_vector_type( instr, 0, SM_UP_ARRAY ); } // vf_opcode_aaload /** * Function sets code instruction structure for opcodes istorex. */ static inline void -vf_opcode_istorex( vf_Code_t * code, // code instruction +vf_opcode_istorex( vf_Instr * instr, // code instruction unsigned local, // local variable number - vf_VerifyPool_t * pool ) // memory pool + vf_Pool *pool ) // memory pool { // set stack modifier for instruction - vf_set_stack_modifier( code, -1 ); + vf_set_stack_modifier( instr, -1 ); // set minimal stack for instruction - vf_set_min_stack( code, 1 ); + vf_set_min_stack( instr, 1 ); // create in vector - vf_new_in_vector( code, 1, pool ); - vf_set_in_vector_stack_entry_int( code, 0 ); + vf_new_in_vector( instr, 1, pool ); + vf_set_in_vector_stack_entry_int( instr, 0 ); // create out vector - vf_new_out_vector( code, 1, pool ); - vf_set_out_vector_local_var_int( code, 0, local ); - return; + vf_new_out_vector( instr, 1, pool ); + vf_set_out_vector_local_var_int( instr, 0, local ); } // vf_opcode_istorex /** * Function sets code instruction structure for opcodes lstorex. */ static inline void -vf_opcode_lstorex( vf_Code_t * code, // code instruction +vf_opcode_lstorex( vf_Instr * instr, // code instruction unsigned local, // local variable number - vf_VerifyPool_t * pool ) // memory pool + vf_Pool *pool ) // memory pool { // set stack modifier for instruction - vf_set_stack_modifier( code, -2 ); + vf_set_stack_modifier( instr, -2 ); // set minimal stack for instruction - vf_set_min_stack( code, 2 ); + vf_set_min_stack( instr, 2 ); // create in vector - vf_new_in_vector( code, 2, pool ); - vf_set_in_vector_stack_entry_long( code, 0 ); + vf_new_in_vector( instr, 2, pool ); + vf_set_in_vector_stack_entry_long( instr, 0 ); // create out vector - vf_new_out_vector( code, 2, pool ); - vf_set_out_vector_local_var_long( code, 0, local ); - return; + vf_new_out_vector( instr, 2, pool ); + vf_set_out_vector_local_var_long( instr, 0, local ); } // vf_opcode_lstorex /** * Function sets code instruction structure for opcodes fstorex. */ static inline void -vf_opcode_fstorex( vf_Code_t * code, // code instruction +vf_opcode_fstorex( vf_Instr * instr, // code instruction unsigned local, // local variable number - vf_VerifyPool_t * pool ) // memory pool + vf_Pool *pool ) // memory pool { // set stack modifier for instruction - vf_set_stack_modifier( code, -1 ); + vf_set_stack_modifier( instr, -1 ); // set minimal stack for instruction - vf_set_min_stack( code, 1 ); + vf_set_min_stack( instr, 1 ); // create in vector - vf_new_in_vector( code, 1, pool ); - vf_set_in_vector_stack_entry_float( code, 0 ); + vf_new_in_vector( instr, 1, pool ); + vf_set_in_vector_stack_entry_float( instr, 0 ); // create out vector - vf_new_out_vector( code, 1, pool ); - vf_set_out_vector_local_var_float( code, 0, local ); - return; + vf_new_out_vector( instr, 1, pool ); + vf_set_out_vector_local_var_float( instr, 0, local ); } // vf_opcode_fstorex /** * Function sets code instruction structure for opcodes dstorex. */ static inline void -vf_opcode_dstorex( vf_Code_t * code, // code instruction +vf_opcode_dstorex( vf_Instr * instr, // code instruction unsigned local, // local variable number - vf_VerifyPool_t * pool ) // memory pool + vf_Pool *pool ) // memory pool { // set stack modifier for instruction - vf_set_stack_modifier( code, -2 ); + vf_set_stack_modifier( instr, -2 ); // set minimal stack for instruction - vf_set_min_stack( code, 2 ); + vf_set_min_stack( instr, 2 ); // create in vector - vf_new_in_vector( code, 2, pool ); - vf_set_in_vector_stack_entry_double( code, 0 ); + vf_new_in_vector( instr, 2, pool ); + vf_set_in_vector_stack_entry_double( instr, 0 ); // create out vector - vf_new_out_vector( code, 2, pool ); - vf_set_out_vector_local_var_double( code, 0, local ); - return; + vf_new_out_vector( instr, 2, pool ); + vf_set_out_vector_local_var_double( instr, 0, local ); } // vf_opcode_dstorex /** * Function sets code instruction structure for opcodes astorex. */ static inline void -vf_opcode_astorex( vf_Code_t * code, // code instruction +vf_opcode_astorex( vf_Instr * instr, // code instruction unsigned local, // local variable number - vf_VerifyPool_t * pool ) // memory pool + vf_Pool *pool ) // memory pool { // set stack modifier for instruction - vf_set_stack_modifier( code, -1 ); + vf_set_stack_modifier( instr, -1 ); // set minimal stack for instruction - vf_set_min_stack( code, 1 ); + vf_set_min_stack( instr, 1 ); // create in vector - vf_new_in_vector( code, 1, pool ); - vf_set_in_vector_stack_entry_ref( code, 0, NULL ); - vf_set_vector_check( code->m_invector, 0, VF_CHECK_UNINITIALIZED_THIS ); + vf_new_in_vector( instr, 1, pool ); + vf_set_in_vector_stack_entry_ref( instr, 0, NULL ); + vf_set_vector_check( instr->m_invector, 0, VF_CHECK_UNINITIALIZED_THIS ); // create out vector - vf_new_out_vector( code, 1, pool ); - vf_set_out_vector_local_var_type( code, 0, SM_COPY_0, local ); - return; + vf_new_out_vector( instr, 1, pool ); + vf_set_out_vector_local_var_type( instr, 0, SM_COPY_0, local ); } // vf_opcode_astorex /** * Function sets code instruction structure for opcode iastore. */ static inline void -vf_opcode_iastore( vf_Code_t * code, // code instruction - vf_Context_t * ctex ) // verifier context +vf_opcode_iastore( vf_Instr * instr, // code instruction + vf_ContextHandle ctx ) // verification context { // set stack modifier for instruction - vf_set_stack_modifier( code, -3 ); + vf_set_stack_modifier( instr, -3 ); // set minimal stack for instruction - vf_set_min_stack( code, 3 ); + vf_set_min_stack( instr, 3 ); // create in vector - vf_new_in_vector( code, 3, ctex->m_pool ); + vf_new_in_vector( instr, 3, ctx->m_pool ); // create type - vf_ValidType_t *type = ctex->m_type->NewType( "[I", 2 ); - vf_set_in_vector_stack_entry_ref( code, 0, type ); - vf_set_in_vector_stack_entry_int( code, 1 ); - vf_set_in_vector_stack_entry_int( code, 2 ); + vf_ValidType *type = ctx->m_type->NewType( "[I", 2 ); + vf_set_in_vector_stack_entry_ref( instr, 0, type ); + vf_set_in_vector_stack_entry_int( instr, 1 ); + vf_set_in_vector_stack_entry_int( instr, 2 ); // set check - vf_set_in_vector_check( code, 0, VF_CHECK_EQUAL ); - return; + vf_set_in_vector_check( instr, 0, VF_CHECK_EQUAL ); } // vf_opcode_iastore /** * Function sets code instruction structure for opcode bastore. */ static inline void -vf_opcode_bastore( vf_Code_t * code, // code instruction - vf_Context_t * ctex ) // verifier context +vf_opcode_bastore( vf_Instr * instr, // code instruction + vf_ContextHandle ctx ) // verification context { // set stack modifier for instruction - vf_set_stack_modifier( code, -3 ); + vf_set_stack_modifier( instr, -3 ); // set minimal stack for instruction - vf_set_min_stack( code, 3 ); + vf_set_min_stack( instr, 3 ); // create in vector - vf_new_in_vector( code, 3, ctex->m_pool ); + vf_new_in_vector( instr, 3, ctx->m_pool ); // create type - vf_ValidType_t *type = ctex->m_type->NewType( "[B", 2 ); - vf_set_in_vector_stack_entry_ref( code, 0, type ); - vf_set_in_vector_stack_entry_int( code, 1 ); - vf_set_in_vector_stack_entry_int( code, 2 ); + vf_ValidType *type = ctx->m_type->NewType( "[B", 2 ); + vf_set_in_vector_stack_entry_ref( instr, 0, type ); + vf_set_in_vector_stack_entry_int( instr, 1 ); + vf_set_in_vector_stack_entry_int( instr, 2 ); // set check - vf_set_in_vector_check( code, 0, VF_CHECK_EQUAL ); - return; + vf_set_in_vector_check( instr, 0, VF_CHECK_EQUAL ); } // vf_opcode_bastore /** * Function sets code instruction structure for opcode castore. */ static inline void -vf_opcode_castore( vf_Code_t * code, // code instruction - vf_Context_t * ctex ) // verifier context +vf_opcode_castore( vf_Instr * instr, // code instruction + vf_ContextHandle ctx ) // verification context { // set stack modifier for instruction - vf_set_stack_modifier( code, -3 ); + vf_set_stack_modifier( instr, -3 ); // set minimal stack for instruction - vf_set_min_stack( code, 3 ); + vf_set_min_stack( instr, 3 ); // create in vector - vf_new_in_vector( code, 3, ctex->m_pool ); + vf_new_in_vector( instr, 3, ctx->m_pool ); // create type - vf_ValidType_t *type = ctex->m_type->NewType( "[C", 2 ); - vf_set_in_vector_stack_entry_ref( code, 0, type ); - vf_set_in_vector_stack_entry_int( code, 1 ); - vf_set_in_vector_stack_entry_int( code, 2 ); + vf_ValidType *type = ctx->m_type->NewType( "[C", 2 ); + vf_set_in_vector_stack_entry_ref( instr, 0, type ); + vf_set_in_vector_stack_entry_int( instr, 1 ); + vf_set_in_vector_stack_entry_int( instr, 2 ); // set check - vf_set_in_vector_check( code, 0, VF_CHECK_EQUAL ); - return; + vf_set_in_vector_check( instr, 0, VF_CHECK_EQUAL ); } // vf_opcode_castore /** * Function sets code instruction structure for opcode sastore. */ static inline void -vf_opcode_sastore( vf_Code_t * code, // code instruction - vf_Context_t * ctex ) // verifier context +vf_opcode_sastore( vf_Instr * instr, // code instruction + vf_ContextHandle ctx ) // verification context { // set stack modifier for instruction - vf_set_stack_modifier( code, -3 ); + vf_set_stack_modifier( instr, -3 ); // set minimal stack for instruction - vf_set_min_stack( code, 3 ); + vf_set_min_stack( instr, 3 ); // create in vector - vf_new_in_vector( code, 3, ctex->m_pool ); + vf_new_in_vector( instr, 3, ctx->m_pool ); // create type - vf_ValidType_t *type = ctex->m_type->NewType( "[S", 2 ); - vf_set_in_vector_stack_entry_ref( code, 0, type ); - vf_set_in_vector_stack_entry_int( code, 1 ); - vf_set_in_vector_stack_entry_int( code, 2 ); + vf_ValidType *type = ctx->m_type->NewType( "[S", 2 ); + vf_set_in_vector_stack_entry_ref( instr, 0, type ); + vf_set_in_vector_stack_entry_int( instr, 1 ); + vf_set_in_vector_stack_entry_int( instr, 2 ); // set check - vf_set_in_vector_check( code, 0, VF_CHECK_EQUAL ); - return; + vf_set_in_vector_check( instr, 0, VF_CHECK_EQUAL ); } // vf_opcode_sastore /** * Function sets code instruction structure for opcode lastore. */ static inline void -vf_opcode_lastore( vf_Code_t * code, // code instruction - vf_Context_t * ctex ) // verifier context +vf_opcode_lastore( vf_Instr * instr, // code instruction + vf_ContextHandle ctx ) // verification context { // set stack modifier for instruction - vf_set_stack_modifier( code, -4 ); + vf_set_stack_modifier( instr, -4 ); // set minimal stack for instruction - vf_set_min_stack( code, 4 ); + vf_set_min_stack( instr, 4 ); // create in vector - vf_new_in_vector( code, 4, ctex->m_pool ); + vf_new_in_vector( instr, 4, ctx->m_pool ); // create type - vf_ValidType_t *type = ctex->m_type->NewType( "[J", 2 ); - vf_set_in_vector_stack_entry_ref( code, 0, type ); - vf_set_in_vector_stack_entry_int( code, 1 ); - vf_set_in_vector_stack_entry_long( code, 2 ); + vf_ValidType *type = ctx->m_type->NewType( "[J", 2 ); + vf_set_in_vector_stack_entry_ref( instr, 0, type ); + vf_set_in_vector_stack_entry_int( instr, 1 ); + vf_set_in_vector_stack_entry_long( instr, 2 ); // set check - vf_set_in_vector_check( code, 0, VF_CHECK_EQUAL ); - return; + vf_set_in_vector_check( instr, 0, VF_CHECK_EQUAL ); } // vf_opcode_lastore /** * Function sets code instruction structure for opcode fastore. */ static inline void -vf_opcode_fastore( vf_Code_t * code, // code instruction - vf_Context_t * ctex ) // verifier context +vf_opcode_fastore( vf_Instr * instr, // code instruction + vf_ContextHandle ctx ) // verification context { // set stack modifier for instruction - vf_set_stack_modifier( code, -3 ); + vf_set_stack_modifier( instr, -3 ); // set minimal stack for instruction - vf_set_min_stack( code, 3 ); + vf_set_min_stack( instr, 3 ); // create in vector - vf_new_in_vector( code, 3, ctex->m_pool ); + vf_new_in_vector( instr, 3, ctx->m_pool ); // create type - vf_ValidType_t *type = ctex->m_type->NewType( "[F", 2 ); - vf_set_in_vector_stack_entry_ref( code, 0, type ); - vf_set_in_vector_stack_entry_int( code, 1 ); - vf_set_in_vector_stack_entry_float( code, 2 ); + vf_ValidType *type = ctx->m_type->NewType( "[F", 2 ); + vf_set_in_vector_stack_entry_ref( instr, 0, type ); + vf_set_in_vector_stack_entry_int( instr, 1 ); + vf_set_in_vector_stack_entry_float( instr, 2 ); // set check - vf_set_in_vector_check( code, 0, VF_CHECK_EQUAL ); - return; + vf_set_in_vector_check( instr, 0, VF_CHECK_EQUAL ); } // vf_opcode_fastore /** * Function sets code instruction structure for opcode dastore. */ static inline void -vf_opcode_dastore( vf_Code_t * code, // code instruction - vf_Context_t * ctex ) // verifier context +vf_opcode_dastore( vf_Instr * instr, // code instruction + vf_ContextHandle ctx ) // verification context { // set stack modifier for instruction - vf_set_stack_modifier( code, -4 ); + vf_set_stack_modifier( instr, -4 ); // set minimal stack for instruction - vf_set_min_stack( code, 4 ); + vf_set_min_stack( instr, 4 ); // create in vector - vf_new_in_vector( code, 4, ctex->m_pool ); + vf_new_in_vector( instr, 4, ctx->m_pool ); // create type - vf_ValidType_t *type = ctex->m_type->NewType( "[D", 2 ); - vf_set_in_vector_stack_entry_ref( code, 0, type ); - vf_set_in_vector_stack_entry_int( code, 1 ); - vf_set_in_vector_stack_entry_double( code, 2 ); + vf_ValidType *type = ctx->m_type->NewType( "[D", 2 ); + vf_set_in_vector_stack_entry_ref( instr, 0, type ); + vf_set_in_vector_stack_entry_int( instr, 1 ); + vf_set_in_vector_stack_entry_double( instr, 2 ); // set check - vf_set_in_vector_check( code, 0, VF_CHECK_EQUAL ); - return; + vf_set_in_vector_check( instr, 0, VF_CHECK_EQUAL ); } // vf_opcode_dastore /** * Function sets code instruction structure for opcode aastore. */ static inline void -vf_opcode_aastore( vf_Code_t * code, // code instruction - vf_Context_t * ctex ) // verifier context +vf_opcode_aastore( vf_Instr * instr, // code instruction + vf_ContextHandle ctx ) // verification context { // set stack modifier for instruction - vf_set_stack_modifier( code, -3 ); + vf_set_stack_modifier( instr, -3 ); // set minimal stack for instruction - vf_set_min_stack( code, 3 ); + vf_set_min_stack( instr, 3 ); // create in vector - vf_new_in_vector( code, 3, ctex->m_pool ); + vf_new_in_vector( instr, 3, ctx->m_pool ); // create type - vf_set_in_vector_stack_entry_ref( code, 0, NULL ); - vf_set_in_vector_check( code, 0, VF_CHECK_REF_ARRAY ); - vf_set_in_vector_stack_entry_int( code, 1 ); - if( vf_is_class_version_14( ctex ) ) { - vf_set_in_vector_type( code, 2, SM_UP_ARRAY ); + vf_set_in_vector_stack_entry_ref( instr, 0, NULL ); + vf_set_in_vector_check( instr, 0, VF_CHECK_REF_ARRAY ); + vf_set_in_vector_stack_entry_int( instr, 1 ); + if( vf_is_class_version_14( ctx ) ) { + vf_set_in_vector_type( instr, 2, SM_UP_ARRAY ); } else { - vf_set_in_vector_stack_entry_ref( code, 2, NULL ); + vf_set_in_vector_stack_entry_ref( instr, 2, NULL ); } - return; } // vf_opcode_aastore /** * Function sets code instruction structure for opcode pop. */ static inline void -vf_opcode_pop( vf_Code_t * code, // code instruction - vf_VerifyPool_t * pool ) // memory pool +vf_opcode_pop( vf_Instr * instr, // code instruction + vf_Pool *pool ) // memory pool { // set stack modifier for instruction - vf_set_stack_modifier( code, -1 ); + vf_set_stack_modifier( instr, -1 ); // set minimal stack for instruction - vf_set_min_stack( code, 1 ); + vf_set_min_stack( instr, 1 ); // create in vector - vf_new_in_vector( code, 1, pool ); - vf_set_in_vector_stack_entry_word( code, 0 ); - return; + vf_new_in_vector( instr, 1, pool ); + vf_set_in_vector_stack_entry_word( instr, 0 ); } // vf_opcode_pop /** * Function sets code instruction structure for opcode pop2. */ static inline void -vf_opcode_pop2( vf_Code_t * code, // code instruction - vf_VerifyPool_t * pool ) // memory pool +vf_opcode_pop2( vf_Instr * instr, // code instruction + vf_Pool *pool ) // memory pool { // set stack modifier for instruction - vf_set_stack_modifier( code, -2 ); + vf_set_stack_modifier( instr, -2 ); // set minimal stack for instruction - vf_set_min_stack( code, 2 ); + vf_set_min_stack( instr, 2 ); // create in vector - vf_new_in_vector( code, 2, pool ); - vf_set_in_vector_stack_entry_word2( code, 0 ); - return; + vf_new_in_vector( instr, 2, pool ); + vf_set_in_vector_stack_entry_word2( instr, 0 ); } // vf_opcode_pop2 /** * Function sets code instruction structure for opcode dup. */ static inline void -vf_opcode_dup( vf_Code_t * code, // code instruction - vf_VerifyPool_t * pool ) // memory pool +vf_opcode_dup( vf_Instr * instr, // code instruction + vf_Pool *pool ) // memory pool { // set stack modifier for instruction - vf_set_stack_modifier( code, 1 ); + vf_set_stack_modifier( instr, 1 ); // set minimal stack for instruction - vf_set_min_stack( code, 1 ); + vf_set_min_stack( instr, 1 ); // create in vector - vf_new_in_vector( code, 1, pool ); - vf_set_in_vector_stack_entry_word( code, 0 ); + vf_new_in_vector( instr, 1, pool ); + vf_set_in_vector_stack_entry_word( instr, 0 ); // create out vector - vf_new_out_vector( code, 2, pool ); - vf_set_out_vector_type( code, 0, SM_COPY_0 ); - vf_set_out_vector_type( code, 1, SM_COPY_0 ); - return; + vf_new_out_vector( instr, 2, pool ); + vf_set_out_vector_type( instr, 0, SM_COPY_0 ); + vf_set_out_vector_type( instr, 1, SM_COPY_0 ); } // vf_opcode_dup /** * Function sets code instruction structure for opcode dup_x1. */ static inline void -vf_opcode_dup_x1( vf_Code_t * code, // code instruction - vf_VerifyPool_t * pool ) // memory pool +vf_opcode_dup_x1( vf_Instr * instr, // code instruction + vf_Pool *pool ) // memory pool { // set stack modifier for instruction - vf_set_stack_modifier( code, 1 ); + vf_set_stack_modifier( instr, 1 ); // set minimal stack for instruction - vf_set_min_stack( code, 2 ); + vf_set_min_stack( instr, 2 ); // create in vector - vf_new_in_vector( code, 2, pool ); - vf_set_in_vector_stack_entry_word( code, 0 ); - vf_set_in_vector_stack_entry_word( code, 1 ); + vf_new_in_vector( instr, 2, pool ); + vf_set_in_vector_stack_entry_word( instr, 0 ); + vf_set_in_vector_stack_entry_word( instr, 1 ); // create out vector - vf_new_out_vector( code, 3, pool ); - vf_set_out_vector_type( code, 0, SM_COPY_1 ); - vf_set_out_vector_type( code, 1, SM_COPY_0 ); - vf_set_out_vector_type( code, 2, SM_COPY_1 ); - return; + vf_new_out_vector( instr, 3, pool ); + vf_set_out_vector_type( instr, 0, SM_COPY_1 ); + vf_set_out_vector_type( instr, 1, SM_COPY_0 ); + vf_set_out_vector_type( instr, 2, SM_COPY_1 ); } // vf_opcode_dup_x1 /** * Function sets code instruction structure for opcode dup_x2. */ static inline void -vf_opcode_dup_x2( vf_Code_t * code, // code instruction - vf_VerifyPool_t * pool ) // memory pool +vf_opcode_dup_x2( vf_Instr * instr, // code instruction + vf_Pool *pool ) // memory pool { // set stack modifier for instruction - vf_set_stack_modifier( code, 1 ); + vf_set_stack_modifier( instr, 1 ); // set minimal stack for instruction - vf_set_min_stack( code, 3 ); + vf_set_min_stack( instr, 3 ); // create in vector - vf_new_in_vector( code, 3, pool ); - vf_set_in_vector_stack_entry_word2( code, 0 ); - vf_set_in_vector_stack_entry_word( code, 2 ); + vf_new_in_vector( instr, 3, pool ); + vf_set_in_vector_stack_entry_word2( instr, 0 ); + vf_set_in_vector_stack_entry_word( instr, 2 ); // create out vector - vf_new_out_vector( code, 4, pool ); - vf_set_out_vector_type( code, 0, SM_COPY_2 ); - vf_set_out_vector_type( code, 1, SM_COPY_0 ); - vf_set_out_vector_type( code, 2, SM_COPY_1 ); - vf_set_out_vector_type( code, 3, SM_COPY_2 ); - return; + vf_new_out_vector( instr, 4, pool ); + vf_set_out_vector_type( instr, 0, SM_COPY_2 ); + vf_set_out_vector_type( instr, 1, SM_COPY_0 ); + vf_set_out_vector_type( instr, 2, SM_COPY_1 ); + vf_set_out_vector_type( instr, 3, SM_COPY_2 ); } // vf_opcode_dup_x2 /** * Function sets code instruction structure for opcode dup2. */ static inline void -vf_opcode_dup2( vf_Code_t * code, // code instruction - vf_VerifyPool_t * pool ) // memory pool +vf_opcode_dup2( vf_Instr * instr, // code instruction + vf_Pool *pool ) // memory pool { // set stack modifier for instruction - vf_set_stack_modifier( code, 2 ); + vf_set_stack_modifier( instr, 2 ); // set minimal stack for instruction - vf_set_min_stack( code, 2 ); + vf_set_min_stack( instr, 2 ); // create in vector - vf_new_in_vector( code, 2, pool ); - vf_set_in_vector_stack_entry_word2( code, 0 ); + vf_new_in_vector( instr, 2, pool ); + vf_set_in_vector_stack_entry_word2( instr, 0 ); // create out vector - vf_new_out_vector( code, 4, pool ); - vf_set_out_vector_type( code, 0, SM_COPY_0 ); - vf_set_out_vector_type( code, 1, SM_COPY_1 ); - vf_set_out_vector_type( code, 2, SM_COPY_0 ); - vf_set_out_vector_type( code, 3, SM_COPY_1 ); - return; + vf_new_out_vector( instr, 4, pool ); + vf_set_out_vector_type( instr, 0, SM_COPY_0 ); + vf_set_out_vector_type( instr, 1, SM_COPY_1 ); + vf_set_out_vector_type( instr, 2, SM_COPY_0 ); + vf_set_out_vector_type( instr, 3, SM_COPY_1 ); } // vf_opcode_dup2 /** * Function sets code instruction structure for opcode dup2_x1. */ static inline void -vf_opcode_dup2_x1( vf_Code_t * code, // code instruction - vf_VerifyPool_t * pool ) // memory pool +vf_opcode_dup2_x1( vf_Instr * instr, // code instruction + vf_Pool *pool ) // memory pool { // set stack modifier for instruction - vf_set_stack_modifier( code, 2 ); + vf_set_stack_modifier( instr, 2 ); // set minimal stack for instruction - vf_set_min_stack( code, 3 ); + vf_set_min_stack( instr, 3 ); // create in vector - vf_new_in_vector( code, 3, pool ); - vf_set_in_vector_stack_entry_word( code, 0 ); - vf_set_in_vector_stack_entry_word2( code, 1 ); + vf_new_in_vector( instr, 3, pool ); + vf_set_in_vector_stack_entry_word( instr, 0 ); + vf_set_in_vector_stack_entry_word2( instr, 1 ); // create out vector - vf_new_out_vector( code, 5, pool ); - vf_set_out_vector_type( code, 0, SM_COPY_1 ); - vf_set_out_vector_type( code, 1, SM_COPY_2 ); - vf_set_out_vector_type( code, 2, SM_COPY_0 ); - vf_set_out_vector_type( code, 3, SM_COPY_1 ); - vf_set_out_vector_type( code, 4, SM_COPY_2 ); - return; + vf_new_out_vector( instr, 5, pool ); + vf_set_out_vector_type( instr, 0, SM_COPY_1 ); + vf_set_out_vector_type( instr, 1, SM_COPY_2 ); + vf_set_out_vector_type( instr, 2, SM_COPY_0 ); + vf_set_out_vector_type( instr, 3, SM_COPY_1 ); + vf_set_out_vector_type( instr, 4, SM_COPY_2 ); } // vf_opcode_dup2_x1 /** * Function sets code instruction structure for opcode dup2_x2. */ static inline void -vf_opcode_dup2_x2( vf_Code_t * code, // code instruction - vf_VerifyPool_t * pool ) // memory pool +vf_opcode_dup2_x2( vf_Instr * instr, // code instruction + vf_Pool *pool ) // memory pool { // set stack modifier for instruction - vf_set_stack_modifier( code, 2 ); + vf_set_stack_modifier( instr, 2 ); // set minimal stack for instruction - vf_set_min_stack( code, 4 ); + vf_set_min_stack( instr, 4 ); // create in vector - vf_new_in_vector( code, 4, pool ); - vf_set_in_vector_stack_entry_word2( code, 0 ); - vf_set_in_vector_stack_entry_word2( code, 2 ); - // create out vector - vf_new_out_vector( code, 6, pool ); - vf_set_out_vector_type( code, 0, SM_COPY_2 ); - vf_set_out_vector_type( code, 1, SM_COPY_3 ); - vf_set_out_vector_type( code, 2, SM_COPY_0 ); - vf_set_out_vector_type( code, 3, SM_COPY_1 ); - vf_set_out_vector_type( code, 4, SM_COPY_2 ); - vf_set_out_vector_type( code, 5, SM_COPY_3 ); - return; + vf_new_in_vector( instr, 4, pool ); + vf_set_in_vector_stack_entry_word2( instr, 0 ); + vf_set_in_vector_stack_entry_word2( instr, 2 ); + // create out vector + vf_new_out_vector( instr, 6, pool ); + vf_set_out_vector_type( instr, 0, SM_COPY_2 ); + vf_set_out_vector_type( instr, 1, SM_COPY_3 ); + vf_set_out_vector_type( instr, 2, SM_COPY_0 ); + vf_set_out_vector_type( instr, 3, SM_COPY_1 ); + vf_set_out_vector_type( instr, 4, SM_COPY_2 ); + vf_set_out_vector_type( instr, 5, SM_COPY_3 ); } // vf_opcode_dup2_x2 /** * Function sets code instruction structure for opcode swap. */ static inline void -vf_opcode_swap( vf_Code_t * code, // code instruction - vf_VerifyPool_t * pool ) // memory pool +vf_opcode_swap( vf_Instr * instr, // code instruction + vf_Pool *pool ) // memory pool { // set minimal stack for instruction - vf_set_min_stack( code, 2 ); + vf_set_min_stack( instr, 2 ); // create in vector - vf_new_in_vector( code, 2, pool ); - vf_set_in_vector_stack_entry_word( code, 0 ); - vf_set_in_vector_stack_entry_word( code, 1 ); + vf_new_in_vector( instr, 2, pool ); + vf_set_in_vector_stack_entry_word( instr, 0 ); + vf_set_in_vector_stack_entry_word( instr, 1 ); // create out vector - vf_new_out_vector( code, 2, pool ); - vf_set_out_vector_type( code, 0, SM_COPY_1 ); - vf_set_out_vector_type( code, 1, SM_COPY_0 ); - return; + vf_new_out_vector( instr, 2, pool ); + vf_set_out_vector_type( instr, 0, SM_COPY_1 ); + vf_set_out_vector_type( instr, 1, SM_COPY_0 ); } // vf_opcode_swap /** * Function sets code instruction structure for opcode iadd. */ static inline void -vf_opcode_iadd( vf_Code_t * code, // code instruction - vf_VerifyPool_t * pool ) // memory pool +vf_opcode_iadd( vf_Instr * instr, // code instruction + vf_Pool *pool ) // memory pool { // set stack modifier for instruction - vf_set_stack_modifier( code, -1 ); + vf_set_stack_modifier( instr, -1 ); // set minimal stack for instruction - vf_set_min_stack( code, 2 ); + vf_set_min_stack( instr, 2 ); // create in vector - vf_new_in_vector( code, 2, pool ); - vf_set_in_vector_stack_entry_int( code, 0 ); - vf_set_in_vector_stack_entry_int( code, 1 ); + vf_new_in_vector( instr, 2, pool ); + vf_set_in_vector_stack_entry_int( instr, 0 ); + vf_set_in_vector_stack_entry_int( instr, 1 ); // create out vector - vf_new_out_vector( code, 1, pool ); - vf_set_out_vector_stack_entry_int( code, 0 ); - return; + vf_new_out_vector( instr, 1, pool ); + vf_set_out_vector_stack_entry_int( instr, 0 ); } // vf_opcode_iadd /** * Function sets code instruction structure for opcode ladd. */ static inline void -vf_opcode_ladd( vf_Code_t * code, // code instruction - vf_VerifyPool_t * pool ) // memory pool +vf_opcode_ladd( vf_Instr * instr, // code instruction + vf_Pool *pool ) // memory pool { // set stack modifier for instruction - vf_set_stack_modifier( code, -2 ); + vf_set_stack_modifier( instr, -2 ); // set minimal stack for instruction - vf_set_min_stack( code, 4 ); + vf_set_min_stack( instr, 4 ); // create in vector - vf_new_in_vector( code, 4, pool ); - vf_set_in_vector_stack_entry_long( code, 0 ); - vf_set_in_vector_stack_entry_long( code, 2 ); + vf_new_in_vector( instr, 4, pool ); + vf_set_in_vector_stack_entry_long( instr, 0 ); + vf_set_in_vector_stack_entry_long( instr, 2 ); // create out vector - vf_new_out_vector( code, 2, pool ); - vf_set_out_vector_stack_entry_long( code, 0 ); - return; + vf_new_out_vector( instr, 2, pool ); + vf_set_out_vector_stack_entry_long( instr, 0 ); } // vf_opcode_ladd /** * Function sets code instruction structure for opcode fadd. */ static inline void -vf_opcode_fadd( vf_Code_t * code, // code instruction - vf_VerifyPool_t * pool ) // memory pool +vf_opcode_fadd( vf_Instr * instr, // code instruction + vf_Pool *pool ) // memory pool { // set stack modifier for instruction - vf_set_stack_modifier( code, -1 ); + vf_set_stack_modifier( instr, -1 ); // set minimal stack for instruction - vf_set_min_stack( code, 2 ); + vf_set_min_stack( instr, 2 ); // create in vector - vf_new_in_vector( code, 2, pool ); - vf_set_in_vector_stack_entry_float( code, 0 ); - vf_set_in_vector_stack_entry_float( code, 1 ); + vf_new_in_vector( instr, 2, pool ); + vf_set_in_vector_stack_entry_float( instr, 0 ); + vf_set_in_vector_stack_entry_float( instr, 1 ); // create out vector - vf_new_out_vector( code, 1, pool ); - vf_set_out_vector_stack_entry_float( code, 0 ); - return; + vf_new_out_vector( instr, 1, pool ); + vf_set_out_vector_stack_entry_float( instr, 0 ); } // vf_opcode_fadd /** * Function sets code instruction structure for opcode dadd. */ static inline void -vf_opcode_dadd( vf_Code_t * code, // code instruction - vf_VerifyPool_t * pool ) // memory pool +vf_opcode_dadd( vf_Instr * instr, // code instruction + vf_Pool *pool ) // memory pool { // set stack modifier for instruction - vf_set_stack_modifier( code, -2 ); + vf_set_stack_modifier( instr, -2 ); // set minimal stack for instruction - vf_set_min_stack( code, 4 ); + vf_set_min_stack( instr, 4 ); // create in vector - vf_new_in_vector( code, 4, pool ); - vf_set_in_vector_stack_entry_double( code, 0 ); - vf_set_in_vector_stack_entry_double( code, 2 ); + vf_new_in_vector( instr, 4, pool ); + vf_set_in_vector_stack_entry_double( instr, 0 ); + vf_set_in_vector_stack_entry_double( instr, 2 ); // create out vector - vf_new_out_vector( code, 2, pool ); - vf_set_out_vector_stack_entry_double( code, 0 ); - return; + vf_new_out_vector( instr, 2, pool ); + vf_set_out_vector_stack_entry_double( instr, 0 ); } // vf_opcode_dadd /** * Function sets code instruction structure for opcode ineg. */ static inline void -vf_opcode_ineg( vf_Code_t * code, // code instruction - vf_VerifyPool_t * pool ) // memory pool +vf_opcode_ineg( vf_Instr * instr, // code instruction + vf_Pool *pool ) // memory pool { // set minimal stack for instruction - vf_set_min_stack( code, 1 ); + vf_set_min_stack( instr, 1 ); // create in vector - vf_new_in_vector( code, 1, pool ); - vf_set_in_vector_stack_entry_int( code, 0 ); + vf_new_in_vector( instr, 1, pool ); + vf_set_in_vector_stack_entry_int( instr, 0 ); // create out vector - vf_new_out_vector( code, 1, pool ); - vf_set_out_vector_stack_entry_int( code, 0 ); - return; + vf_new_out_vector( instr, 1, pool ); + vf_set_out_vector_stack_entry_int( instr, 0 ); } // vf_opcode_ineg /** * Function sets code instruction structure for opcode lneg. */ static inline void -vf_opcode_lneg( vf_Code_t * code, // code instruction - vf_VerifyPool_t * pool ) // memory pool +vf_opcode_lneg( vf_Instr * instr, // code instruction + vf_Pool *pool ) // memory pool { // set minimal stack for instruction - vf_set_min_stack( code, 2 ); + vf_set_min_stack( instr, 2 ); // create in vector - vf_new_in_vector( code, 2, pool ); - vf_set_in_vector_stack_entry_long( code, 0 ); + vf_new_in_vector( instr, 2, pool ); + vf_set_in_vector_stack_entry_long( instr, 0 ); // create out vector - vf_new_out_vector( code, 2, pool ); - vf_set_out_vector_stack_entry_long( code, 0 ); - return; + vf_new_out_vector( instr, 2, pool ); + vf_set_out_vector_stack_entry_long( instr, 0 ); } // vf_opcode_lneg /** * Function sets code instruction structure for opcode fneg. */ static inline void -vf_opcode_fneg( vf_Code_t * code, // code instruction - vf_VerifyPool_t * pool ) // memory pool +vf_opcode_fneg( vf_Instr * instr, // code instruction + vf_Pool *pool ) // memory pool { // set minimal stack for instruction - vf_set_min_stack( code, 1 ); + vf_set_min_stack( instr, 1 ); // create in vector - vf_new_in_vector( code, 1, pool ); - vf_set_in_vector_stack_entry_float( code, 0 ); + vf_new_in_vector( instr, 1, pool ); + vf_set_in_vector_stack_entry_float( instr, 0 ); // create out vector - vf_new_out_vector( code, 1, pool ); - vf_set_out_vector_stack_entry_float( code, 0 ); - return; + vf_new_out_vector( instr, 1, pool ); + vf_set_out_vector_stack_entry_float( instr, 0 ); } // vf_opcode_fneg /** * Function sets code instruction structure for opcode dneg. */ static inline void -vf_opcode_dneg( vf_Code_t * code, // code instruction - vf_VerifyPool_t * pool ) // memory pool +vf_opcode_dneg( vf_Instr * instr, // code instruction + vf_Pool *pool ) // memory pool { // set minimal stack for instruction - vf_set_min_stack( code, 2 ); + vf_set_min_stack( instr, 2 ); // create in vector - vf_new_in_vector( code, 2, pool ); - vf_set_in_vector_stack_entry_double( code, 0 ); + vf_new_in_vector( instr, 2, pool ); + vf_set_in_vector_stack_entry_double( instr, 0 ); // create out vector - vf_new_out_vector( code, 2, pool ); - vf_set_out_vector_stack_entry_double( code, 0 ); - return; + vf_new_out_vector( instr, 2, pool ); + vf_set_out_vector_stack_entry_double( instr, 0 ); } // vf_opcode_dneg /** * Function sets code instruction structure for bit operation opcodes. */ static inline void -vf_opcode_ibit( vf_Code_t * code, // code instruction - vf_VerifyPool_t * pool ) // memory pool +vf_opcode_ibit( vf_Instr * instr, // code instruction + vf_Pool *pool ) // memory pool { // set stack modifier for instruction - vf_set_stack_modifier( code, -1 ); + vf_set_stack_modifier( instr, -1 ); // set minimal stack for instruction - vf_set_min_stack( code, 2 ); + vf_set_min_stack( instr, 2 ); // create in vector - vf_new_in_vector( code, 2, pool ); - vf_set_in_vector_stack_entry_int( code, 0 ); - vf_set_in_vector_stack_entry_int( code, 1 ); + vf_new_in_vector( instr, 2, pool ); + vf_set_in_vector_stack_entry_int( instr, 0 ); + vf_set_in_vector_stack_entry_int( instr, 1 ); // create out vector - vf_new_out_vector( code, 1, pool ); - vf_set_out_vector_stack_entry_int( code, 0 ); - return; + vf_new_out_vector( instr, 1, pool ); + vf_set_out_vector_stack_entry_int( instr, 0 ); } // vf_opcode_ibit /** * Function sets code instruction structure for opcodes lshx. */ static inline void -vf_opcode_lshx( vf_Code_t * code, // code instruction - vf_VerifyPool_t * pool ) // memory pool +vf_opcode_lshx( vf_Instr * instr, // code instruction + vf_Pool *pool ) // memory pool { // set stack modifier for instruction - vf_set_stack_modifier( code, -1 ); + vf_set_stack_modifier( instr, -1 ); // set minimal stack for instruction - vf_set_min_stack( code, 3 ); + vf_set_min_stack( instr, 3 ); // create in vector - vf_new_in_vector( code, 3, pool ); - vf_set_in_vector_stack_entry_long( code, 0 ); - vf_set_in_vector_stack_entry_int( code, 2 ); + vf_new_in_vector( instr, 3, pool ); + vf_set_in_vector_stack_entry_long( instr, 0 ); + vf_set_in_vector_stack_entry_int( instr, 2 ); // create out vector - vf_new_out_vector( code, 2, pool ); - vf_set_out_vector_stack_entry_long( code, 0 ); - return; + vf_new_out_vector( instr, 2, pool ); + vf_set_out_vector_stack_entry_long( instr, 0 ); } // vf_opcode_lshx /** * Function sets code instruction structure for opcode land. */ static inline void -vf_opcode_land( vf_Code_t * code, // code instruction - vf_VerifyPool_t * pool ) // memory pool +vf_opcode_land( vf_Instr * instr, // code instruction + vf_Pool *pool ) // memory pool { // set stack modifier for instruction - vf_set_stack_modifier( code, -2 ); + vf_set_stack_modifier( instr, -2 ); // set minimal stack for instruction - vf_set_min_stack( code, 4 ); + vf_set_min_stack( instr, 4 ); // create in vector - vf_new_in_vector( code, 4, pool ); - vf_set_in_vector_stack_entry_long( code, 0 ); - vf_set_in_vector_stack_entry_long( code, 2 ); + vf_new_in_vector( instr, 4, pool ); + vf_set_in_vector_stack_entry_long( instr, 0 ); + vf_set_in_vector_stack_entry_long( instr, 2 ); // create out vector - vf_new_out_vector( code, 2, pool ); - vf_set_out_vector_stack_entry_long( code, 0 ); - return; + vf_new_out_vector( instr, 2, pool ); + vf_set_out_vector_stack_entry_long( instr, 0 ); } // vf_opcode_land /** * Function sets code instruction structure for opcode iinc. */ static inline void -vf_opcode_iinc( vf_Code_t * code, // code instruction +vf_opcode_iinc( vf_Instr * instr, // code instruction unsigned local, // local variable number - vf_VerifyPool_t * pool ) // memory pool + vf_Pool *pool ) // memory pool { // create in vector - vf_new_in_vector( code, 1, pool ); - vf_set_in_vector_local_var_int( code, 0, local ); - return; + vf_new_in_vector( instr, 1, pool ); + vf_set_in_vector_local_var_int( instr, 0, local ); } // vf_opcode_iinc /** * Function sets code instruction structure for opcode i2l. */ static inline void -vf_opcode_i2l( vf_Code_t * code, // code instruction - vf_VerifyPool_t * pool ) // memory pool +vf_opcode_i2l( vf_Instr * instr, // code instruction + vf_Pool *pool ) // memory pool { // set stack modifier for instruction - vf_set_stack_modifier( code, 1 ); + vf_set_stack_modifier( instr, 1 ); // set minimal stack for instruction - vf_set_min_stack( code, 1 ); + vf_set_min_stack( instr, 1 ); // create in vector - vf_new_in_vector( code, 1, pool ); - vf_set_in_vector_stack_entry_int( code, 0 ); + vf_new_in_vector( instr, 1, pool ); + vf_set_in_vector_stack_entry_int( instr, 0 ); // create out vector - vf_new_out_vector( code, 2, pool ); - vf_set_out_vector_stack_entry_long( code, 0 ); - return; + vf_new_out_vector( instr, 2, pool ); + vf_set_out_vector_stack_entry_long( instr, 0 ); } // vf_opcode_i2l /** * Function sets code instruction structure for opcode i2f. */ static inline void -vf_opcode_i2f( vf_Code_t * code, // code instruction - vf_VerifyPool_t * pool ) // memory pool +vf_opcode_i2f( vf_Instr * instr, // code instruction + vf_Pool *pool ) // memory pool { // set minimal stack for instruction - vf_set_min_stack( code, 1 ); + vf_set_min_stack( instr, 1 ); // create in vector - vf_new_in_vector( code, 1, pool ); - vf_set_in_vector_stack_entry_int( code, 0 ); + vf_new_in_vector( instr, 1, pool ); + vf_set_in_vector_stack_entry_int( instr, 0 ); // create out vector - vf_new_out_vector( code, 1, pool ); - vf_set_out_vector_stack_entry_float( code, 0 ); - return; + vf_new_out_vector( instr, 1, pool ); + vf_set_out_vector_stack_entry_float( instr, 0 ); } // vf_opcode_i2f /** * Function sets code instruction structure for opcode i2d. */ static inline void -vf_opcode_i2d( vf_Code_t * code, // code instruction - vf_VerifyPool_t * pool ) // memory pool +vf_opcode_i2d( vf_Instr * instr, // code instruction + vf_Pool *pool ) // memory pool { // set stack modifier for instruction - vf_set_stack_modifier( code, 1 ); + vf_set_stack_modifier( instr, 1 ); // set minimal stack for instruction - vf_set_min_stack( code, 1 ); + vf_set_min_stack( instr, 1 ); // create in vector - vf_new_in_vector( code, 1, pool ); - vf_set_in_vector_stack_entry_int( code, 0 ); + vf_new_in_vector( instr, 1, pool ); + vf_set_in_vector_stack_entry_int( instr, 0 ); // create out vector - vf_new_out_vector( code, 2, pool ); - vf_set_out_vector_stack_entry_double( code, 0 ); - return; + vf_new_out_vector( instr, 2, pool ); + vf_set_out_vector_stack_entry_double( instr, 0 ); } // vf_opcode_i2d /** * Function sets code instruction structure for opcode l2i. */ static inline void -vf_opcode_l2i( vf_Code_t * code, // code instruction - vf_VerifyPool_t * pool ) // memory pool +vf_opcode_l2i( vf_Instr * instr, // code instruction + vf_Pool *pool ) // memory pool { // set stack modifier for instruction - vf_set_stack_modifier( code, -1 ); + vf_set_stack_modifier( instr, -1 ); // set minimal stack for instruction - vf_set_min_stack( code, 2 ); + vf_set_min_stack( instr, 2 ); // create in vector - vf_new_in_vector( code, 2, pool ); - vf_set_in_vector_stack_entry_long( code, 0 ); + vf_new_in_vector( instr, 2, pool ); + vf_set_in_vector_stack_entry_long( instr, 0 ); // create out vector - vf_new_out_vector( code, 1, pool ); - vf_set_out_vector_stack_entry_int( code, 0 ); - return; + vf_new_out_vector( instr, 1, pool ); + vf_set_out_vector_stack_entry_int( instr, 0 ); } // vf_opcode_l2i /** * Function sets code instruction structure for opcode l2f. */ static inline void -vf_opcode_l2f( vf_Code_t * code, // code instruction - vf_VerifyPool_t * pool ) // memory pool +vf_opcode_l2f( vf_Instr * instr, // code instruction + vf_Pool *pool ) // memory pool { // set stack modifier for instruction - vf_set_stack_modifier( code, -1 ); + vf_set_stack_modifier( instr, -1 ); // set minimal stack for instruction - vf_set_min_stack( code, 2 ); + vf_set_min_stack( instr, 2 ); // create in vector - vf_new_in_vector( code, 2, pool ); - vf_set_in_vector_stack_entry_long( code, 0 ); + vf_new_in_vector( instr, 2, pool ); + vf_set_in_vector_stack_entry_long( instr, 0 ); // create out vector - vf_new_out_vector( code, 1, pool ); - vf_set_out_vector_stack_entry_float( code, 0 ); - return; + vf_new_out_vector( instr, 1, pool ); + vf_set_out_vector_stack_entry_float( instr, 0 ); } // vf_opcode_l2f /** * Function sets code instruction structure for opcode l2d. */ static inline void -vf_opcode_l2d( vf_Code_t * code, // code instruction - vf_VerifyPool_t * pool ) // memory pool +vf_opcode_l2d( vf_Instr * instr, // code instruction + vf_Pool *pool ) // memory pool { // set minimal stack for instruction - vf_set_min_stack( code, 2 ); + vf_set_min_stack( instr, 2 ); // create in vector - vf_new_in_vector( code, 2, pool ); - vf_set_in_vector_stack_entry_long( code, 0 ); + vf_new_in_vector( instr, 2, pool ); + vf_set_in_vector_stack_entry_long( instr, 0 ); // create out vector - vf_new_out_vector( code, 2, pool ); - vf_set_out_vector_stack_entry_double( code, 0 ); - return; + vf_new_out_vector( instr, 2, pool ); + vf_set_out_vector_stack_entry_double( instr, 0 ); } // vf_opcode_l2d /** * Function sets code instruction structure for opcode f2i. */ static inline void -vf_opcode_f2i( vf_Code_t * code, // code instruction - vf_VerifyPool_t * pool ) // memory pool +vf_opcode_f2i( vf_Instr * instr, // code instruction + vf_Pool *pool ) // memory pool { // set minimal stack for instruction - vf_set_min_stack( code, 1 ); + vf_set_min_stack( instr, 1 ); // create in vector - vf_new_in_vector( code, 1, pool ); - vf_set_in_vector_stack_entry_float( code, 0 ); + vf_new_in_vector( instr, 1, pool ); + vf_set_in_vector_stack_entry_float( instr, 0 ); // create out vector - vf_new_out_vector( code, 1, pool ); - vf_set_out_vector_stack_entry_int( code, 0 ); - return; + vf_new_out_vector( instr, 1, pool ); + vf_set_out_vector_stack_entry_int( instr, 0 ); } // vf_opcode_f2i /** * Function sets code instruction structure for opcode f2l. */ static inline void -vf_opcode_f2l( vf_Code_t * code, // code instruction - vf_VerifyPool_t * pool ) // memory pool +vf_opcode_f2l( vf_Instr * instr, // code instruction + vf_Pool *pool ) // memory pool { // set stack modifier for instruction - vf_set_stack_modifier( code, 1 ); + vf_set_stack_modifier( instr, 1 ); // set minimal stack for instruction - vf_set_min_stack( code, 1 ); + vf_set_min_stack( instr, 1 ); // create in vector - vf_new_in_vector( code, 1, pool ); - vf_set_in_vector_stack_entry_float( code, 0 ); + vf_new_in_vector( instr, 1, pool ); + vf_set_in_vector_stack_entry_float( instr, 0 ); // create out vector - vf_new_out_vector( code, 2, pool ); - vf_set_out_vector_stack_entry_long( code, 0 ); - return; + vf_new_out_vector( instr, 2, pool ); + vf_set_out_vector_stack_entry_long( instr, 0 ); } // vf_opcode_f2l /** * Function sets code instruction structure for opcode f2d. */ static inline void -vf_opcode_f2d( vf_Code_t * code, // code instruction - vf_VerifyPool_t * pool ) // memory pool +vf_opcode_f2d( vf_Instr * instr, // code instruction + vf_Pool *pool ) // memory pool { // set stack modifier for instruction - vf_set_stack_modifier( code, 1 ); + vf_set_stack_modifier( instr, 1 ); // set minimal stack for instruction - vf_set_min_stack( code, 1 ); + vf_set_min_stack( instr, 1 ); // create in vector - vf_new_in_vector( code, 1, pool ); - vf_set_in_vector_stack_entry_float( code, 0 ); + vf_new_in_vector( instr, 1, pool ); + vf_set_in_vector_stack_entry_float( instr, 0 ); // create out vector - vf_new_out_vector( code, 2, pool ); - vf_set_out_vector_stack_entry_double( code, 0 ); - return; + vf_new_out_vector( instr, 2, pool ); + vf_set_out_vector_stack_entry_double( instr, 0 ); } // vf_opcode_f2d /** * Function sets code instruction structure for opcode d2i. */ static inline void -vf_opcode_d2i( vf_Code_t * code, // code instruction - vf_VerifyPool_t * pool ) // memory pool +vf_opcode_d2i( vf_Instr * instr, // code instruction + vf_Pool *pool ) // memory pool { // set stack modifier for instruction - vf_set_stack_modifier( code, -1 ); + vf_set_stack_modifier( instr, -1 ); // set minimal stack for instruction - vf_set_min_stack( code, 2 ); + vf_set_min_stack( instr, 2 ); // create in vector - vf_new_in_vector( code, 2, pool ); - vf_set_in_vector_stack_entry_double( code, 0 ); + vf_new_in_vector( instr, 2, pool ); + vf_set_in_vector_stack_entry_double( instr, 0 ); // create out vector - vf_new_out_vector( code, 1, pool ); - vf_set_out_vector_stack_entry_int( code, 0 ); - return; + vf_new_out_vector( instr, 1, pool ); + vf_set_out_vector_stack_entry_int( instr, 0 ); } // vf_opcode_d2i /** * Function sets code instruction structure for opcode d2l. */ static inline void -vf_opcode_d2l( vf_Code_t * code, // code instruction - vf_VerifyPool_t * pool ) // memory pool +vf_opcode_d2l( vf_Instr * instr, // code instruction + vf_Pool *pool ) // memory pool { // set minimal stack for instruction - vf_set_min_stack( code, 2 ); + vf_set_min_stack( instr, 2 ); // create in vector - vf_new_in_vector( code, 2, pool ); - vf_set_in_vector_stack_entry_double( code, 0 ); + vf_new_in_vector( instr, 2, pool ); + vf_set_in_vector_stack_entry_double( instr, 0 ); // create out vector - vf_new_out_vector( code, 2, pool ); - vf_set_out_vector_stack_entry_long( code, 0 ); - return; + vf_new_out_vector( instr, 2, pool ); + vf_set_out_vector_stack_entry_long( instr, 0 ); } // vf_opcode_d2l /** * Function sets code instruction structure for opcode d2f. */ static inline void -vf_opcode_d2f( vf_Code_t * code, // code instruction - vf_VerifyPool_t * pool ) // memory pool +vf_opcode_d2f( vf_Instr * instr, // code instruction + vf_Pool *pool ) // memory pool { // set stack modifier for instruction - vf_set_stack_modifier( code, -1 ); + vf_set_stack_modifier( instr, -1 ); // set minimal stack for instruction - vf_set_min_stack( code, 2 ); + vf_set_min_stack( instr, 2 ); // create in vector - vf_new_in_vector( code, 2, pool ); - vf_set_in_vector_stack_entry_double( code, 0 ); + vf_new_in_vector( instr, 2, pool ); + vf_set_in_vector_stack_entry_double( instr, 0 ); // create out vector - vf_new_out_vector( code, 1, pool ); - vf_set_out_vector_stack_entry_float( code, 0 ); - return; + vf_new_out_vector( instr, 1, pool ); + vf_set_out_vector_stack_entry_float( instr, 0 ); } // vf_opcode_d2f /** * Function sets code instruction structure for opcode i2b. */ static inline void -vf_opcode_i2b( vf_Code_t * code, // code instruction - vf_VerifyPool_t * pool ) // memory pool +vf_opcode_i2b( vf_Instr * instr, // code instruction + vf_Pool *pool ) // memory pool { // set minimal stack for instruction - vf_set_min_stack( code, 1 ); + vf_set_min_stack( instr, 1 ); // create in vector - vf_new_in_vector( code, 1, pool ); - vf_set_in_vector_stack_entry_int( code, 0 ); + vf_new_in_vector( instr, 1, pool ); + vf_set_in_vector_stack_entry_int( instr, 0 ); // create out vector - vf_new_out_vector( code, 1, pool ); - vf_set_out_vector_stack_entry_int( code, 0 ); - return; + vf_new_out_vector( instr, 1, pool ); + vf_set_out_vector_stack_entry_int( instr, 0 ); } // vf_opcode_i2b /** * Function sets code instruction structure for opcode lcmp. */ static inline void -vf_opcode_lcmp( vf_Code_t * code, // code instruction - vf_VerifyPool_t * pool ) // memory pool +vf_opcode_lcmp( vf_Instr * instr, // code instruction + vf_Pool *pool ) // memory pool { // set stack modifier for instruction - vf_set_stack_modifier( code, -3 ); + vf_set_stack_modifier( instr, -3 ); // set minimal stack for instruction - vf_set_min_stack( code, 4 ); + vf_set_min_stack( instr, 4 ); // create in vector - vf_new_in_vector( code, 4, pool ); - vf_set_in_vector_stack_entry_long( code, 0 ); - vf_set_in_vector_stack_entry_long( code, 2 ); + vf_new_in_vector( instr, 4, pool ); + vf_set_in_vector_stack_entry_long( instr, 0 ); + vf_set_in_vector_stack_entry_long( instr, 2 ); // create out vector - vf_new_out_vector( code, 1, pool ); - vf_set_out_vector_stack_entry_int( code, 0 ); - return; + vf_new_out_vector( instr, 1, pool ); + vf_set_out_vector_stack_entry_int( instr, 0 ); } // vf_opcode_lcmp /** * Function sets code instruction structure for opcodes fcmpx. */ static inline void -vf_opcode_fcmpx( vf_Code_t * code, // code instruction - vf_VerifyPool_t * pool ) // memory pool +vf_opcode_fcmpx( vf_Instr * instr, // code instruction + vf_Pool *pool ) // memory pool { // set stack modifier for instruction - vf_set_stack_modifier( code, -1 ); + vf_set_stack_modifier( instr, -1 ); // set minimal stack for instruction - vf_set_min_stack( code, 2 ); + vf_set_min_stack( instr, 2 ); // create in vector - vf_new_in_vector( code, 2, pool ); - vf_set_in_vector_stack_entry_float( code, 0 ); - vf_set_in_vector_stack_entry_float( code, 1 ); + vf_new_in_vector( instr, 2, pool ); + vf_set_in_vector_stack_entry_float( instr, 0 ); + vf_set_in_vector_stack_entry_float( instr, 1 ); // create out vector - vf_new_out_vector( code, 1, pool ); - vf_set_out_vector_stack_entry_int( code, 0 ); - return; + vf_new_out_vector( instr, 1, pool ); + vf_set_out_vector_stack_entry_int( instr, 0 ); } // vf_opcode_fcmpx /** * Function sets code instruction structure for opcodes dcmpx. */ static inline void -vf_opcode_dcmpx( vf_Code_t * code, // code instruction - vf_VerifyPool_t * pool ) // memory pool +vf_opcode_dcmpx( vf_Instr * instr, // code instruction + vf_Pool *pool ) // memory pool { // set stack modifier for instruction - vf_set_stack_modifier( code, -3 ); + vf_set_stack_modifier( instr, -3 ); // set minimal stack for instruction - vf_set_min_stack( code, 4 ); + vf_set_min_stack( instr, 4 ); // create in vector - vf_new_in_vector( code, 4, pool ); - vf_set_in_vector_stack_entry_double( code, 0 ); - vf_set_in_vector_stack_entry_double( code, 2 ); + vf_new_in_vector( instr, 4, pool ); + vf_set_in_vector_stack_entry_double( instr, 0 ); + vf_set_in_vector_stack_entry_double( instr, 2 ); // create out vector - vf_new_out_vector( code, 1, pool ); - vf_set_out_vector_stack_entry_int( code, 0 ); - return; + vf_new_out_vector( instr, 1, pool ); + vf_set_out_vector_stack_entry_int( instr, 0 ); } // vf_opcode_dcmpx /** * Function sets code instruction structure for opcode ifeq. */ static inline void -vf_opcode_ifeq( vf_Code_t * code, // code instruction - vf_BCode_t * icode1, // first branch instruction - vf_BCode_t * icode2, // second branch instruction - vf_VerifyPool_t * pool ) // memory pool +vf_opcode_ifeq( vf_Instr * instr, // code instruction + vf_BCode *icode1, // first branch instruction + vf_BCode *icode2, // second branch instruction + vf_Pool *pool ) // memory pool { // set stack modifier for instruction - vf_set_stack_modifier( code, -1 ); + vf_set_stack_modifier( instr, -1 ); // set minimal stack for instruction - vf_set_min_stack( code, 1 ); + vf_set_min_stack( instr, 1 ); // set begin of basic block for branch instruction - vf_set_basic_block_flag( icode1 ); + icode1->m_basic_block_start = true; // set begin of basic block for branch instruction - vf_set_basic_block_flag( icode2 ); + icode2->m_basic_block_start = true; // create in vector - vf_new_in_vector( code, 1, pool ); - vf_set_in_vector_stack_entry_int( code, 0 ); - return; + vf_new_in_vector( instr, 1, pool ); + vf_set_in_vector_stack_entry_int( instr, 0 ); } // vf_opcode_ifeq /** * Function sets code instruction structure for opcode if_icmpeq. */ static inline void -vf_opcode_if_icmpeq( vf_Code_t * code, // code instruction - vf_BCode_t * icode1, // first branch instruction - vf_BCode_t * icode2, // second branch instruction - vf_VerifyPool_t * pool ) // memory pool +vf_opcode_if_icmpeq( vf_Instr * instr, // code instruction + vf_BCode *icode1, // first branch instruction + vf_BCode *icode2, // second branch instruction + vf_Pool *pool ) // memory pool { // set stack modifier for instruction - vf_set_stack_modifier( code, -2 ); + vf_set_stack_modifier( instr, -2 ); // set minimal stack for instruction - vf_set_min_stack( code, 2 ); + vf_set_min_stack( instr, 2 ); // set begin of basic block for branch instruction - vf_set_basic_block_flag( icode1 ); + icode1->m_basic_block_start = true; // set begin of basic block for branch instruction - vf_set_basic_block_flag( icode2 ); + icode2->m_basic_block_start = true; // create in vector - vf_new_in_vector( code, 2, pool ); - vf_set_in_vector_stack_entry_int( code, 0 ); - vf_set_in_vector_stack_entry_int( code, 1 ); - return; + vf_new_in_vector( instr, 2, pool ); + vf_set_in_vector_stack_entry_int( instr, 0 ); + vf_set_in_vector_stack_entry_int( instr, 1 ); } // vf_opcode_if_icmpeq /** * Function sets code instruction structure for opcode if_acmpeq. */ static inline void -vf_opcode_if_acmpeq( vf_Code_t * code, // code instruction - vf_BCode_t * icode1, // first branch instruction - vf_BCode_t * icode2, // second branch instruction - vf_VerifyPool_t * pool ) // memory pool +vf_opcode_if_acmpeq( vf_Instr * instr, // code instruction + vf_BCode *icode1, // first branch instruction + vf_BCode *icode2, // second branch instruction + vf_Pool *pool ) // memory pool { // set stack modifier for instruction - vf_set_stack_modifier( code, -2 ); + vf_set_stack_modifier( instr, -2 ); // set minimal stack for instruction - vf_set_min_stack( code, 2 ); + vf_set_min_stack( instr, 2 ); // set begin of basic block for branch instruction - vf_set_basic_block_flag( icode1 ); + icode1->m_basic_block_start = true; // set begin of basic block for branch instruction - vf_set_basic_block_flag( icode2 ); + icode2->m_basic_block_start = true; // create in vector - vf_new_in_vector( code, 2, pool ); - vf_set_in_vector_stack_entry_ref( code, 0, NULL ); - vf_set_in_vector_stack_entry_ref( code, 1, NULL ); - return; + vf_new_in_vector( instr, 2, pool ); + vf_set_in_vector_stack_entry_ref( instr, 0, NULL ); + vf_set_in_vector_stack_entry_ref( instr, 1, NULL ); } // vf_opcode_if_acmpeq /** * Function sets code instruction structure for opcode switch. */ static inline void -vf_opcode_switch( vf_Code_t * code, // code instruction - vf_VerifyPool_t * pool ) // memory pool +vf_opcode_switch( vf_Instr * instr, // code instruction + vf_Pool *pool ) // memory pool { // set stack modifier for instruction - vf_set_stack_modifier( code, -1 ); + vf_set_stack_modifier( instr, -1 ); // set minimal stack for instruction - vf_set_min_stack( code, 1 ); + vf_set_min_stack( instr, 1 ); // create in vector - vf_new_in_vector( code, 1, pool ); - vf_set_in_vector_stack_entry_int( code, 0 ); - return; + vf_new_in_vector( instr, 1, pool ); + vf_set_in_vector_stack_entry_int( instr, 0 ); } // vf_opcode_switch /** * Function sets code instruction structure for opcode ireturn. */ static inline void -vf_opcode_ireturn( vf_Code_t * code, // code instruction - vf_VerifyPool_t * pool ) // memory pool +vf_opcode_ireturn( vf_Instr * instr, // code instruction + vf_Pool *pool ) // memory pool { // set instruction flag - vf_set_code_type( code, VF_TYPE_INSTR_RETURN ); + vf_set_instr_type( instr, VF_INSTR_RETURN ); // set minimal stack for instruction - vf_set_min_stack( code, 1 ); + vf_set_min_stack( instr, 1 ); // create in vector - vf_new_in_vector( code, 1, pool ); - vf_set_in_vector_stack_entry_int( code, 0 ); - return; + vf_new_in_vector( instr, 1, pool ); + vf_set_in_vector_stack_entry_int( instr, 0 ); } // vf_opcode_ireturn /** * Function sets code instruction structure for opcode lreturn. */ static inline void -vf_opcode_lreturn( vf_Code_t * code, // code instruction - vf_VerifyPool_t * pool ) // memory pool +vf_opcode_lreturn( vf_Instr * instr, // code instruction + vf_Pool *pool ) // memory pool { // set instruction flag - vf_set_code_type( code, VF_TYPE_INSTR_RETURN ); + vf_set_instr_type( instr, VF_INSTR_RETURN ); // set minimal stack for instruction - vf_set_min_stack( code, 2 ); + vf_set_min_stack( instr, 2 ); // create in vector - vf_new_in_vector( code, 2, pool ); - vf_set_in_vector_stack_entry_long( code, 0 ); - return; + vf_new_in_vector( instr, 2, pool ); + vf_set_in_vector_stack_entry_long( instr, 0 ); } // vf_opcode_lreturn /** * Function sets code instruction structure for opcode freturn. */ static inline void -vf_opcode_freturn( vf_Code_t * code, // code instruction - vf_VerifyPool_t * pool ) // memory pool +vf_opcode_freturn( vf_Instr * instr, // code instruction + vf_Pool *pool ) // memory pool { // set instruction flag - vf_set_code_type( code, VF_TYPE_INSTR_RETURN ); + vf_set_instr_type( instr, VF_INSTR_RETURN ); // set minimal stack for instruction - vf_set_min_stack( code, 1 ); + vf_set_min_stack( instr, 1 ); // create in vector - vf_new_in_vector( code, 1, pool ); - vf_set_in_vector_stack_entry_float( code, 0 ); - return; + vf_new_in_vector( instr, 1, pool ); + vf_set_in_vector_stack_entry_float( instr, 0 ); } // vf_opcode_freturn /** * Function sets code instruction structure for opcode dreturn. */ static inline void -vf_opcode_dreturn( vf_Code_t * code, // code instruction - vf_VerifyPool_t * pool ) // memory pool +vf_opcode_dreturn( vf_Instr * instr, // code instruction + vf_Pool *pool ) // memory pool { // set instruction flag - vf_set_code_type( code, VF_TYPE_INSTR_RETURN ); + vf_set_instr_type( instr, VF_INSTR_RETURN ); // set minimal stack for instruction - vf_set_min_stack( code, 2 ); + vf_set_min_stack( instr, 2 ); // create in vector - vf_new_in_vector( code, 2, pool ); - vf_set_in_vector_stack_entry_double( code, 0 ); - return; + vf_new_in_vector( instr, 2, pool ); + vf_set_in_vector_stack_entry_double( instr, 0 ); } // vf_opcode_dreturn /** * Function sets code instruction structure for opcode areturn. */ static inline void -vf_opcode_areturn( vf_Code_t * code, // code instruction - vf_VerifyPool_t * pool ) // memory pool +vf_opcode_areturn( vf_Instr * instr, // code instruction + vf_Pool *pool ) // memory pool { // set instruction flag - vf_set_code_type( code, VF_TYPE_INSTR_RETURN ); + vf_set_instr_type( instr, VF_INSTR_RETURN ); // set minimal stack for instruction - vf_set_min_stack( code, 1 ); + vf_set_min_stack( instr, 1 ); // create in vector - vf_new_in_vector( code, 1, pool ); - vf_set_in_vector_stack_entry_ref( code, 0, NULL ); - return; + vf_new_in_vector( instr, 1, pool ); + vf_set_in_vector_stack_entry_ref( instr, 0, NULL ); } // vf_opcode_areturn /** * Function sets code instruction structure for opcode getstatic. */ -static inline Verifier_Result -vf_opcode_getstatic( vf_Code_t * code, // code instruction +static inline vf_Result +vf_opcode_getstatic( vf_Instr * instr, // code instruction unsigned short cp_index, // constant pool entry index - vf_Context_t * ctex ) // verifier context + vf_Context *ctx ) // verification context { - Verifier_Result result; - vf_Parse_t cp_parse = { 0 }; + vf_Result result; + vf_Parse cp_parse = { 0 }; // check constant pool for instruction result = - vf_parse_const_pool( OPCODE_GETSTATIC, cp_index, &cp_parse, ctex ); + vf_parse_const_pool( OPCODE_GETSTATIC, cp_index, &cp_parse, ctx ); if( result != VER_OK ) { return result; } // set stack modifier for instruction - vf_set_stack_modifier( code, cp_parse.field.f_vlen ); + vf_set_stack_modifier( instr, cp_parse.field.f_vlen ); // set stack out vector - code->m_outvector = cp_parse.field.f_vector; - code->m_outlen = ( unsigned short )cp_parse.field.f_vlen; + instr->m_outvector = cp_parse.field.f_vector; + instr->m_outlen = ( unsigned short )cp_parse.field.f_vlen; return VER_OK; } // vf_opcode_getstatic /** * Function sets code instruction structure for opcode putstatic. */ -static inline Verifier_Result -vf_opcode_putstatic( vf_Code_t * code, // code instruction +static inline vf_Result +vf_opcode_putstatic( vf_Instr * instr, // code instruction unsigned short cp_index, // constant pool entry index - vf_Context_t * ctex ) // verifier context + vf_Context *ctx ) // verification context { - Verifier_Result result; - vf_Parse_t cp_parse = { 0 }; + vf_Result result; + vf_Parse cp_parse = { 0 }; // check constant pool for instruction result = - vf_parse_const_pool( OPCODE_PUTSTATIC, cp_index, &cp_parse, ctex ); + vf_parse_const_pool( OPCODE_PUTSTATIC, cp_index, &cp_parse, ctx ); if( result != VER_OK ) { return result; } // set stack modifier for instruction - vf_set_stack_modifier( code, -( int )cp_parse.field.f_vlen ); + vf_set_stack_modifier( instr, -( int )cp_parse.field.f_vlen ); // set minimal stack for instruction - vf_set_min_stack( code, cp_parse.field.f_vlen ); + vf_set_min_stack( instr, cp_parse.field.f_vlen ); // set stack out vector - code->m_invector = cp_parse.field.f_vector; - code->m_inlen = ( unsigned short )cp_parse.field.f_vlen; + instr->m_invector = cp_parse.field.f_vector; + instr->m_inlen = ( unsigned short )cp_parse.field.f_vlen; // set assign check - vf_set_in_vector_check( code, code->m_inlen - 1, VF_CHECK_ASSIGN ); + vf_set_in_vector_check( instr, instr->m_inlen - 1, VF_CHECK_ASSIGN ); return VER_OK; } // vf_opcode_putstatic /** * Function sets code instruction structure for opcode getfield. */ -static inline Verifier_Result -vf_opcode_getfield( vf_Code_t * code, // code instruction +static inline vf_Result +vf_opcode_getfield( vf_Instr * instr, // code instruction unsigned short cp_index, // constant pool entry index - vf_Context_t * ctex ) // verifier context + vf_Context *ctx ) // verification context { - Verifier_Result result; - vf_Parse_t cp_parse = { 0 }; + vf_Result result; + vf_Parse cp_parse = { 0 }; // check constant pool for instruction - result = - vf_parse_const_pool( OPCODE_GETFIELD, cp_index, &cp_parse, ctex ); + result = vf_parse_const_pool( OPCODE_GETFIELD, cp_index, &cp_parse, ctx ); if( result != VER_OK ) { return result; } // set stack modifier for instruction, remove double this reference - vf_set_stack_modifier( code, cp_parse.field.f_vlen - 2 ); + vf_set_stack_modifier( instr, cp_parse.field.f_vlen - 2 ); // set minimal stack for instruction - vf_set_min_stack( code, 1 ); + vf_set_min_stack( instr, 1 ); // set stack in vector - code->m_invector = cp_parse.field.f_vector; - code->m_inlen = 1; + instr->m_invector = cp_parse.field.f_vector; + instr->m_inlen = 1; // set field access check - vf_set_in_vector_check( code, 0, VF_CHECK_ACCESS_FIELD ); - vf_set_in_vector_check_index( code, 0, cp_index ); + vf_set_in_vector_check( instr, 0, VF_CHECK_ACCESS_FIELD ); + vf_set_in_vector_check_index( instr, 0, cp_index ); // set stack out vector, skip this reference - code->m_outvector = cp_parse.field.f_vector + 1; - code->m_outlen = ( unsigned short )cp_parse.field.f_vlen - 1; + instr->m_outvector = cp_parse.field.f_vector + 1; + instr->m_outlen = ( unsigned short )cp_parse.field.f_vlen - 1; return VER_OK; } // vf_opcode_getfield /** * Function sets code instruction structure for opcode putfield. */ -static inline Verifier_Result -vf_opcode_putfield( vf_Code_t * code, // code instruction +static inline vf_Result +vf_opcode_putfield( vf_Instr * instr, // code instruction unsigned short cp_index, // constant pool entry index - vf_Context_t * ctex ) // verifier context + vf_Context *ctx ) // verification context { - Verifier_Result result; - vf_Parse_t cp_parse = { 0 }; + vf_Result result; + vf_Parse cp_parse = { 0 }; // check constant pool for instruction - result = - vf_parse_const_pool( OPCODE_PUTFIELD, cp_index, &cp_parse, ctex ); + result = vf_parse_const_pool( OPCODE_PUTFIELD, cp_index, &cp_parse, ctx ); if( result != VER_OK ) { return result; } // set stack modifier for instruction - vf_set_stack_modifier( code, -cp_parse.field.f_vlen ); + vf_set_stack_modifier( instr, -cp_parse.field.f_vlen ); // set minimal stack for instruction - vf_set_min_stack( code, cp_parse.field.f_vlen ); + vf_set_min_stack( instr, cp_parse.field.f_vlen ); // set stack in vector - code->m_invector = cp_parse.field.f_vector; - code->m_inlen = ( unsigned short )cp_parse.field.f_vlen; + instr->m_invector = cp_parse.field.f_vector; + instr->m_inlen = ( unsigned short )cp_parse.field.f_vlen; // set assign check - vf_set_in_vector_check( code, code->m_inlen - 1, VF_CHECK_ASSIGN ); + vf_set_in_vector_check( instr, instr->m_inlen - 1, VF_CHECK_ASSIGN ); // set field access check - vf_set_in_vector_check( code, 0, VF_CHECK_ACCESS_FIELD ); - vf_set_in_vector_check_index( code, 0, cp_index ); + vf_set_in_vector_check( instr, 0, VF_CHECK_ACCESS_FIELD ); + vf_set_in_vector_check_index( instr, 0, cp_index ); return VER_OK; } // vf_opcode_putfield /** * Function sets code instruction structure for invokes opcodes. */ -static inline Verifier_Result -vf_opcode_invoke( vf_Code_t * code, // code instruction +static inline vf_Result +vf_opcode_invoke( vf_Instr * instr, // code instruction unsigned short cp_index, // constant pool entry index - vf_Context_t * ctex ) // verifier context + vf_Context *ctx ) // verification context { - Verifier_Result result; - vf_Parse_t cp_parse = { 0 }; + vf_Result result; + vf_Parse cp_parse = { 0 }; // check constant pool for instruction result = - vf_parse_const_pool( *( code->m_addr ), cp_index, &cp_parse, ctex ); + vf_parse_const_pool( *( instr->m_addr ), cp_index, &cp_parse, ctx ); if( result != VER_OK ) { return result; } // check method name if( cp_parse.method.m_name[0] == '<' ) { - VERIFY_REPORT_METHOD( ctex, - "Must call initializers using invokespecial" ); + VF_REPORT( ctx, "Must call initializers using invokespecial" ); return VER_ErrorConstantPool; } // check number of arguments if( cp_parse.method.m_inlen > 255 ) { - VERIFY_REPORT_METHOD( ctex, - "The number of method parameters is limited to 255" ); + VF_REPORT( ctx, "The number of method parameters is limited to 255" ); return VER_ErrorInstruction; } // set stack modifier for instruction - vf_set_stack_modifier( code, + vf_set_stack_modifier( instr, cp_parse.method.m_outlen - cp_parse.method.m_inlen ); // set minimal stack for instruction - vf_set_min_stack( code, cp_parse.method.m_inlen ); + vf_set_min_stack( instr, cp_parse.method.m_inlen ); // set stack in vector - code->m_invector = cp_parse.method.m_invector; - code->m_inlen = ( unsigned short )cp_parse.method.m_inlen; + instr->m_invector = cp_parse.method.m_invector; + instr->m_inlen = ( unsigned short )cp_parse.method.m_inlen; // set stack out vector - code->m_outvector = cp_parse.method.m_outvector; - code->m_outlen = ( unsigned short )cp_parse.method.m_outlen; + instr->m_outvector = cp_parse.method.m_outvector; + instr->m_outlen = ( unsigned short )cp_parse.method.m_outlen; // set method access check for opcode invokevirtual - if( ( *code->m_addr ) == OPCODE_INVOKEVIRTUAL ) { - vf_set_in_vector_check( code, 0, VF_CHECK_ACCESS_METHOD ); - vf_set_in_vector_check_index( code, 0, cp_index ); + if( ( *instr->m_addr ) == OPCODE_INVOKEVIRTUAL ) { + vf_set_in_vector_check( instr, 0, VF_CHECK_ACCESS_METHOD ); + vf_set_in_vector_check_index( instr, 0, cp_index ); } return VER_OK; } // vf_opcode_invoke @@ -3697,132 +3498,130 @@ vf_opcode_invoke( vf_Code_t * code, /** * Function sets code instruction structure for invokes opcodes. */ -static inline Verifier_Result -vf_opcode_invokespecial( vf_Code_t * code, // code instruction +static inline vf_Result +vf_opcode_invokespecial( vf_Instr * instr, // code instruction unsigned short cp_index, // constant pool entry index - vf_Context_t * ctex ) // verifier context + vf_Context *ctx ) // verification context { - Verifier_Result result; - vf_Parse_t cp_parse = { 0 }; + vf_Result result; + vf_Parse cp_parse = { 0 }; // check constant pool for instruction result = - vf_parse_const_pool( *( code->m_addr ), cp_index, &cp_parse, ctex ); + vf_parse_const_pool( *( instr->m_addr ), cp_index, &cp_parse, ctx ); if( result != VER_OK ) { return result; } // check number of arguments if( cp_parse.method.m_inlen > 255 ) { - VERIFY_REPORT_METHOD( ctex, - "The number of method parameters is limited to 255" ); + VF_REPORT( ctx, "The number of method parameters is limited to 255" ); return VER_ErrorInstruction; } // set stack modifier for instruction - vf_set_stack_modifier( code, + vf_set_stack_modifier( instr, cp_parse.method.m_outlen - cp_parse.method.m_inlen ); // set minimal stack for instruction - vf_set_min_stack( code, cp_parse.method.m_inlen ); + vf_set_min_stack( instr, cp_parse.method.m_inlen ); // set stack in vector - code->m_invector = cp_parse.method.m_invector; - code->m_inlen = ( unsigned short )cp_parse.method.m_inlen; + instr->m_invector = cp_parse.method.m_invector; + instr->m_inlen = ( unsigned short )cp_parse.method.m_inlen; // set stack out vector - code->m_outvector = cp_parse.method.m_outvector; - code->m_outlen = ( unsigned short )cp_parse.method.m_outlen; + instr->m_outvector = cp_parse.method.m_outvector; + instr->m_outlen = ( unsigned short )cp_parse.method.m_outlen; // set method check for opcode invokespecial if( !strcmp( cp_parse.method.m_name, "" ) ) { // set uninitialized check - vf_set_in_vector_type( code, 0, SM_UNINITIALIZED ); - vf_set_in_vector_check( code, 0, VF_CHECK_DIRECT_SUPER ); + vf_set_in_vector_type( instr, 0, SM_UNINITIALIZED ); + vf_set_in_vector_check( instr, 0, VF_CHECK_DIRECT_SUPER ); } else { // set method access check - vf_set_in_vector_check( code, 0, VF_CHECK_INVOKESPECIAL ); + vf_set_in_vector_check( instr, 0, VF_CHECK_INVOKESPECIAL ); } - vf_set_in_vector_check_index( code, 0, cp_index ); + vf_set_in_vector_check_index( instr, 0, cp_index ); return VER_OK; } // vf_opcode_invokespecial /** * Function sets code instruction structure for opcode new. */ -static inline Verifier_Result -vf_opcode_new( vf_Code_t * code, // code instruction +static inline vf_Result +vf_opcode_new( vf_Instr * instr, // code instruction unsigned short cp_index, // constant pool entry index unsigned opcode_new, // number of opcode new - vf_Context_t * ctex ) // verifier context + vf_Context *ctx ) // verification context { - Verifier_Result result; - vf_Parse_t cp_parse = { 0 }; + vf_Result result; + vf_Parse cp_parse = { 0 }; // check constant pool for instruction - result = vf_parse_const_pool( OPCODE_NEW, cp_index, &cp_parse, ctex ); + result = vf_parse_const_pool( OPCODE_NEW, cp_index, &cp_parse, ctx ); if( result != VER_OK ) { return result; } // set stack modifier for instruction - vf_set_stack_modifier( code, 1 ); + vf_set_stack_modifier( instr, 1 ); // check created reference assert( cp_parse.field.f_vector->m_vtype->number == 1 ); if( cp_parse.field.f_vector->m_vtype->string[0][0] != 'L' ) { - VERIFY_REPORT_METHOD( ctex, "Illegal creation of array" ); + VF_REPORT( ctx, "Illegal creation of array" ); return VER_ErrorInstruction; } // set stack out vector - code->m_outvector = cp_parse.field.f_vector; - code->m_outlen = ( unsigned short )cp_parse.field.f_vlen; + instr->m_outvector = cp_parse.field.f_vector; + instr->m_outlen = ( unsigned short )cp_parse.field.f_vlen; // set uninitialized reference - vf_set_out_vector_type( code, 0, SM_UNINITIALIZED ); + vf_set_out_vector_type( instr, 0, SM_UNINITIALIZED ); // set opcode program counter - vf_set_out_vector_opcode_new( code, 0, opcode_new ); + vf_set_out_vector_opcode_new( instr, 0, opcode_new ); return VER_OK; } // vf_opcode_new /** * Function sets code instruction structure for opcode newarray. */ -static inline Verifier_Result -vf_opcode_newarray( vf_Code_t * code, // code instruction +static inline vf_Result +vf_opcode_newarray( vf_Instr * instr, // code instruction unsigned char type, // array element type - vf_Context_t * ctex ) // verifier context + vf_Context *ctx ) // verification context { - vf_ValidType_t *vtype; + vf_ValidType *vtype; switch ( type ) { case 4: // boolean case 8: // byte - vtype = ctex->m_type->NewType( "[B", 2 ); + vtype = ctx->m_type->NewType( "[B", 2 ); break; case 5: // char - vtype = ctex->m_type->NewType( "[C", 2 ); + vtype = ctx->m_type->NewType( "[C", 2 ); break; case 9: // short - vtype = ctex->m_type->NewType( "[S", 2 ); + vtype = ctx->m_type->NewType( "[S", 2 ); break; case 10: // int - vtype = ctex->m_type->NewType( "[I", 2 ); + vtype = ctx->m_type->NewType( "[I", 2 ); break; case 6: // float - vtype = ctex->m_type->NewType( "[F", 2 ); + vtype = ctx->m_type->NewType( "[F", 2 ); break; case 7: // double - vtype = ctex->m_type->NewType( "[D", 2 ); + vtype = ctx->m_type->NewType( "[D", 2 ); break; case 11: // long - vtype = ctex->m_type->NewType( "[J", 2 ); + vtype = ctx->m_type->NewType( "[J", 2 ); break; default: - VERIFY_REPORT_METHOD( ctex, - "Incorrect type in instruction newarray" ); + VF_REPORT( ctx, "Incorrect type in newarray instruction" ); return VER_ErrorInstruction; } // set minimal stack for instruction - vf_set_min_stack( code, 1 ); + vf_set_min_stack( instr, 1 ); // create in vector - vf_new_in_vector( code, 1, ctex->m_pool ); - vf_set_in_vector_stack_entry_int( code, 0 ); + vf_new_in_vector( instr, 1, ctx->m_pool ); + vf_set_in_vector_stack_entry_int( instr, 0 ); // create out vector - vf_new_out_vector( code, 1, ctex->m_pool ); - vf_set_out_vector_stack_entry_ref( code, 0, vtype ); + vf_new_out_vector( instr, 1, ctx->m_pool ); + vf_set_out_vector_stack_entry_ref( instr, 0, vtype ); return VER_OK; } // vf_opcode_newarray @@ -3834,7 +3633,7 @@ vf_get_class_array_valid_type( const cha size_t name_len, // element name length unsigned dimension, // dimension of array size_t * result_len, // pointer to result string length - vf_VerifyPool_t * pool ) // memory pool + vf_Pool *pool ) // memory pool { size_t len; unsigned index; @@ -3853,7 +3652,7 @@ vf_get_class_array_valid_type( const cha switch ( element_name[name_len - 1] ) { case 'Z': // set integer array type - result = (char*)vf_alloc_pool_memory( pool, len + 1 ); + result = (char*)vf_palloc( pool, len + 1 ); for( index = 0; index < dimension; index++ ) { result[index] = '['; } @@ -3866,7 +3665,7 @@ vf_get_class_array_valid_type( const cha break; } } - result = (char*)vf_alloc_pool_memory( pool, len + 1 ); + result = (char*)vf_palloc( pool, len + 1 ); for( index = 0; index < dimension; index++ ) { result[index] = '['; } @@ -3874,7 +3673,7 @@ vf_get_class_array_valid_type( const cha } else { // create class signature len = name_len + dimension + 1; - result = (char*)vf_alloc_pool_memory( pool, len + 1 ); + result = (char*)vf_palloc( pool, len + 1 ); for( index = 0; index < dimension; index++ ) { result[index] = '['; } @@ -3888,26 +3687,26 @@ vf_get_class_array_valid_type( const cha /** * Function sets code instruction structure for opcode anewarray. */ -static inline Verifier_Result -vf_opcode_anewarray( vf_Code_t * code, // code instruction +static inline vf_Result +vf_opcode_anewarray( vf_Instr * instr, // code instruction unsigned short cp_index, // constant pool entry index - vf_Context_t * ctex ) // verifier context + vf_Context *ctx ) // verification context { // check constant pool for instruction - Verifier_Result result = vf_parse_const_pool( OPCODE_ANEWARRAY, - cp_index, NULL, ctex ); + vf_Result result = vf_parse_const_pool( OPCODE_ANEWARRAY, + cp_index, NULL, ctx ); if( result != VER_OK ) { return result; } // get array element type name - const char *name = vf_get_cp_class_name( ctex->m_class, cp_index ); + const char *name = vf_get_cp_class_name( ctx->m_class, cp_index ); assert( name ); // create valid type string size_t len; const char *array = vf_get_class_array_valid_type( name, strlen( name ), 1, - &len, ctex->m_pool ); + &len, ctx->m_pool ); // check dimension unsigned short index; @@ -3915,20 +3714,20 @@ vf_opcode_anewarray( vf_Code_t * code, continue; } if( index > 255 ) { - VERIFY_REPORT_METHOD( ctex, "Array with too many dimensions" ); + VF_REPORT( ctx, "Array with too many dimensions" ); return VER_ErrorInstruction; } // create valid type - vf_ValidType_t *type = ctex->m_type->NewType( array, len ); + vf_ValidType *type = ctx->m_type->NewType( array, len ); // set minimal stack for instruction - vf_set_min_stack( code, 1 ); + vf_set_min_stack( instr, 1 ); // create in vector - vf_new_in_vector( code, 1, ctex->m_pool ); - vf_set_in_vector_stack_entry_int( code, 0 ); + vf_new_in_vector( instr, 1, ctx->m_pool ); + vf_set_in_vector_stack_entry_int( instr, 0 ); // create out vector - vf_new_out_vector( code, 1, ctex->m_pool ); - vf_set_out_vector_stack_entry_ref( code, 0, type ); + vf_new_out_vector( instr, 1, ctx->m_pool ); + vf_set_out_vector_stack_entry_ref( instr, 0, type ); return VER_OK; } // vf_opcode_anewarray @@ -3936,93 +3735,90 @@ vf_opcode_anewarray( vf_Code_t * code, * Function sets code instruction structure for opcode arraylength. */ static inline void -vf_opcode_arraylength( vf_Code_t * code, // code instruction - vf_Context_t * ctex ) // verifier context +vf_opcode_arraylength( vf_Instr * instr, // code instruction + vf_ContextHandle ctx ) // verification context { // set minimal stack for instruction - vf_set_min_stack( code, 1 ); + vf_set_min_stack( instr, 1 ); // create in vector - vf_new_in_vector( code, 1, ctex->m_pool ); + vf_new_in_vector( instr, 1, ctx->m_pool ); // create type - vf_set_in_vector_stack_entry_ref( code, 0, NULL ); + vf_set_in_vector_stack_entry_ref( instr, 0, NULL ); // set check - vf_set_in_vector_check( code, 0, VF_CHECK_ARRAY ); + vf_set_in_vector_check( instr, 0, VF_CHECK_ARRAY ); // create out vector - vf_new_out_vector( code, 1, ctex->m_pool ); - vf_set_out_vector_stack_entry_int( code, 0 ); - return; + vf_new_out_vector( instr, 1, ctx->m_pool ); + vf_set_out_vector_stack_entry_int( instr, 0 ); } // vf_opcode_arraylength /** * Function sets code instruction structure for opcode athrow. */ static inline void -vf_opcode_athrow( vf_Code_t * code, // code instruction - vf_Context_t * ctex ) // verifier context +vf_opcode_athrow( vf_Instr * instr, // code instruction + vf_ContextHandle ctx ) // verification context { // set instruction flag - vf_set_code_type( code, VF_TYPE_INSTR_THROW ); + vf_set_instr_type( instr, VF_INSTR_THROW ); // set minimal stack for instruction - vf_set_min_stack( code, 1 ); + vf_set_min_stack( instr, 1 ); // create in vector - vf_new_in_vector( code, 1, ctex->m_pool ); + vf_new_in_vector( instr, 1, ctx->m_pool ); // create type - vf_ValidType_t *type = - ctex->m_type->NewType( "Ljava/lang/Throwable", 20 ); - vf_set_in_vector_stack_entry_ref( code, 0, type ); - return; + vf_ValidType *type = ctx->m_type->NewType( "Ljava/lang/Throwable", 20 ); + vf_set_in_vector_stack_entry_ref( instr, 0, type ); } // vf_opcode_athrow /** * Function sets code instruction structure for opcode checkcast. */ -static inline Verifier_Result -vf_opcode_checkcast( vf_Code_t * code, // code instruction +static inline vf_Result +vf_opcode_checkcast( vf_Instr * instr, // code instruction unsigned short cp_index, // constant pool entry index - vf_Context_t * ctex ) // verifier context + vf_Context *ctx ) // verification context { - Verifier_Result result; - vf_Parse_t cp_parse = { 0 }; + vf_Result result; + vf_Parse cp_parse = { 0 }; // check constant pool for instruction result = - vf_parse_const_pool( OPCODE_CHECKCAST, cp_index, &cp_parse, ctex ); + vf_parse_const_pool( OPCODE_CHECKCAST, cp_index, &cp_parse, ctx ); if( result != VER_OK ) { return result; } // set minimal stack for instruction - vf_set_min_stack( code, 1 ); + vf_set_min_stack( instr, 1 ); // create in vector - vf_new_in_vector( code, 1, ctex->m_pool ); - vf_set_in_vector_stack_entry_ref( code, 0, NULL ); + vf_new_in_vector( instr, 1, ctx->m_pool ); + vf_set_in_vector_stack_entry_ref( instr, 0, NULL ); // set stack out vector - code->m_outvector = cp_parse.field.f_vector; - code->m_outlen = ( unsigned short )cp_parse.field.f_vlen; + instr->m_outvector = cp_parse.field.f_vector; + instr->m_outlen = ( unsigned short )cp_parse.field.f_vlen; return VER_OK; } // vf_opcode_checkcast /** * Function sets code instruction structure for opcode instanceof. */ -static inline Verifier_Result -vf_opcode_instanceof( vf_Code_t * code, // code instruction +static inline vf_Result +vf_opcode_instanceof( vf_Instr * instr, // code instruction unsigned short cp_index, // constant pool entry index - vf_Context_t * ctex ) // verifier context + vf_Context *ctx ) // verification context { // check constant pool for instruction - Verifier_Result result = - vf_parse_const_pool( OPCODE_INSTANCEOF, cp_index, NULL, ctex ); + vf_Result result = + vf_parse_const_pool( OPCODE_INSTANCEOF, cp_index, NULL, ctx ); if( result != VER_OK ) { return result; } // set minimal stack for instruction - vf_set_min_stack( code, 1 ); + vf_set_min_stack( instr, 1 ); // create in vector - vf_new_in_vector( code, 1, ctex->m_pool ); - vf_set_in_vector_stack_entry_ref( code, 0, NULL ); + vf_new_in_vector( instr, 1, ctx->m_pool ); + vf_set_in_vector_stack_entry_ref( instr, 0, NULL ); // set stack out vector - vf_new_out_vector( code, 1, ctex->m_pool ); - vf_set_out_vector_stack_entry_int( code, 0 ); + vf_new_out_vector( instr, 1, ctx->m_pool ); + vf_set_out_vector_stack_entry_int( instr, 0 ); return VER_OK; } // vf_opcode_instanceof @@ -4030,71 +3826,70 @@ vf_opcode_instanceof( vf_Code_t * code, * Function sets code instruction structure for opcodes monitorx. */ static inline void -vf_opcode_monitorx( vf_Code_t * code, // code instruction - vf_VerifyPool_t * pool ) // memory pool +vf_opcode_monitorx( vf_Instr * instr, // code instruction + vf_Pool *pool ) // memory pool { // set stack modifier for instruction - vf_set_stack_modifier( code, -1 ); + vf_set_stack_modifier( instr, -1 ); // set minimal stack for instruction - vf_set_min_stack( code, 1 ); + vf_set_min_stack( instr, 1 ); // create in vector - vf_new_in_vector( code, 1, pool ); - vf_set_in_vector_stack_entry_ref( code, 0, NULL ); - return; + vf_new_in_vector( instr, 1, pool ); + vf_set_in_vector_stack_entry_ref( instr, 0, NULL ); } // vf_opcode_monitorx /** * Function sets code instruction structure for opcode multianewarray. */ -static inline Verifier_Result -vf_opcode_multianewarray( vf_Code_t * code, // code instruction +static inline vf_Result +vf_opcode_multianewarray( vf_Instr * instr, // code instruction unsigned short cp_index, // constant pool entry index unsigned char dimensions, // dimension of array - vf_Context_t * ctex ) // verifier context + vf_Context *ctx ) // verification context { // check constant pool for instruction - Verifier_Result result = - vf_parse_const_pool( OPCODE_MULTIANEWARRAY, cp_index, NULL, ctex ); + vf_Result result = + vf_parse_const_pool( OPCODE_MULTIANEWARRAY, cp_index, NULL, ctx ); if( result != VER_OK ) { return result; } // get array element type name - const char *name = vf_get_cp_class_name( ctex->m_class, cp_index ); + const char *name = vf_get_cp_class_name( ctx->m_class, cp_index ); assert( name ); // get valid type string size_t len; const char *array = vf_get_class_valid_type( name, strlen( name ), - &len, ctex->m_pool ); + &len, ctx->m_pool ); // check dimension unsigned short index; for( index = 0; array[index] == '['; index++ ) { continue; } if( index > 255 ) { - VERIFY_REPORT_METHOD( ctex, "Array with too many dimensions" ); + VF_REPORT( ctx, "Array with too many dimensions" ); return VER_ErrorInstruction; } if( dimensions == 0 || index < dimensions ) { - VERIFY_REPORT_METHOD( ctex, "Illegal dimension argument" ); + VF_REPORT( ctx, "Illegal dimension argument" ); return VER_ErrorInstruction; } // create valid type - vf_ValidType_t *type = ctex->m_type->NewType( array, len ); + vf_ValidType *type = ctx->m_type->NewType( array, len ); // set stack modifier for instruction - vf_set_stack_modifier( code, 1 - dimensions ); + vf_set_stack_modifier( instr, 1 - dimensions ); // set minimal stack for instruction - vf_set_min_stack( code, dimensions ); + vf_set_min_stack( instr, dimensions ); // create in vector - vf_new_in_vector( code, dimensions, ctex->m_pool ); + vf_new_in_vector( instr, dimensions, ctx->m_pool ); for( index = 0; index < dimensions; index++ ) { - vf_set_in_vector_stack_entry_int( code, index ); + vf_set_in_vector_stack_entry_int( instr, index ); } // create out vector - vf_new_out_vector( code, 1, ctex->m_pool ); - vf_set_out_vector_stack_entry_ref( code, 0, type ); + vf_new_out_vector( instr, 1, ctx->m_pool ); + vf_set_out_vector_stack_entry_ref( instr, 0, type ); return VER_OK; } // vf_opcode_multianewarray @@ -4102,100 +3897,101 @@ vf_opcode_multianewarray( vf_Code_t * co * Function sets code instruction structure for opcodes ifxnull. */ static inline void -vf_opcode_ifxnull( vf_Code_t * code, // code instruction - vf_BCode_t * icode1, // first branch instruction - vf_BCode_t * icode2, // second branch instruction - vf_VerifyPool_t * pool ) // memory pool +vf_opcode_ifxnull( vf_Instr * instr, // code instruction + vf_BCode *icode1, // first branch instruction + vf_BCode *icode2, // second branch instruction + vf_Pool *pool ) // memory pool { // set stack modifier for instruction - vf_set_stack_modifier( code, -1 ); + vf_set_stack_modifier( instr, -1 ); // set minimal stack for instruction - vf_set_min_stack( code, 1 ); + vf_set_min_stack( instr, 1 ); // set begin of basic block for branch instruction - vf_set_basic_block_flag( icode1 ); + icode1->m_basic_block_start = true; // set begin of basic block for branch instruction - vf_set_basic_block_flag( icode2 ); + icode2->m_basic_block_start = true; // create in vector - vf_new_in_vector( code, 1, pool ); - vf_set_in_vector_stack_entry_ref( code, 0, NULL ); - return; + vf_new_in_vector( instr, 1, pool ); + vf_set_in_vector_stack_entry_ref( instr, 0, NULL ); } // vf_opcode_ifxnull /** * Function sets code instruction structure for opcodes jsr and jsr_w. */ static inline void -vf_opcode_jsr( vf_Code_t * code, // code instruction - unsigned code_num, // program count of instruction - vf_VerifyPool_t * pool ) // memory pool +vf_opcode_jsr( vf_Instr * instr, // code instruction + unsigned entry_point_pc, // an pc of subroutine entry point + vf_Pool *pool ) // memory pool { // set instruction flag - vf_set_code_type( code, VF_TYPE_INSTR_SUBROUTINE ); + vf_set_instr_type( instr, VF_INSTR_JSR ); // set stack modifier for instruction - vf_set_stack_modifier( code, 1 ); + vf_set_stack_modifier( instr, 1 ); // create out vector - vf_new_out_vector( code, 1, pool ); - vf_set_out_vector_stack_entry_addr( code, 0, code_num ); - return; + vf_new_out_vector( instr, 1, pool ); + vf_set_vector_stack_entry_addr( instr->m_outvector, 0, entry_point_pc ); } // vf_opcode_jsr /** * Function sets code instruction structure for opcode ret. */ static inline void -vf_opcode_ret( vf_Code_t * code, // code instruction +vf_opcode_ret( vf_Instr * instr, // code instruction unsigned local, // local variable number - vf_VerifyPool_t * pool ) // memory pool + vf_Pool *pool ) // memory pool { + // set instruction flag + vf_set_instr_type( instr, VF_INSTR_RET ); // create in vector - vf_new_in_vector( code, 1, pool ); - vf_set_in_vector_local_var_addr( code, 0, 0, local ); - return; + vf_new_in_vector( instr, 1, pool ); + vf_set_vector_local_var_addr( instr->m_invector, 0, 0, local ); } // vf_opcode_ret /** - * Parses bytecode, determines code instructions, fills code array and - * provides simple verifications. + * Parses bytecode, determines code instructions, fills instruction and bytecode + * arrays and provides simple verifications. */ -static Verifier_Result -vf_parse_bytecode( vf_Context_t * ctex ) +static vf_Result +vf_parse_bytecode( vf_Context *ctx ) { - int offset; - unsigned index, count; - unsigned short local, const_index; - unsigned char u1; - - Verifier_Result result = VER_OK; + // get bytecode parameters + unsigned len = ctx->m_len; + unsigned char *bytecode = ctx->m_bytes; /** - * Getting bytecode parameters + * Allocate memory bytecode annotations. Add additional + * bytes at the end to simplify basic block marking for + * jsr instructions and exception handlers. + * Also this guards against a case when parsing doesn't stop + * at the end of the method. If bc[len - 1] represents jsr_w, + * then bc[len + 4] will be marked with basic block end. */ - unsigned len = method_get_code_length( ctex->m_method ); - unsigned char *bytecode = method_get_bytecode( ctex->m_method ); - unsigned short locals = method_get_max_local( ctex->m_method ); + vf_Pool *pool = ctx->m_pool; + vf_BCode *bc = (vf_BCode*)vf_palloc( pool, ( len + GOTO_W_LEN ) + * sizeof( vf_BCode ) ); + ctx->m_bc = bc; // first instruction is always begin of basic block - vf_BCode_t *bc = ctex->m_bc; - bc[0].m_mark = 1; + bc[0].m_basic_block_start = true; - /** - * Parse bytecode instructions and fill a code array - */ - unsigned instr; + // allocate memory for instructions + ctx->m_instr = + ( vf_InstrHandle ) vf_palloc( pool, len * sizeof( vf_Instr ) ); + + int offset; + unsigned index, count; + unsigned short local, const_index; + unsigned char u1; + vf_Result result = VER_OK; unsigned branches; - unsigned codeNum = 0; + unsigned ret_num = 0; - vf_Code_t *code; - vf_VerifyPool_t *pool = ctex->m_pool; - for( index = 0; index < len; codeNum++ ) { - code = &ctex->m_code[codeNum]; - code->m_addr = &bytecode[index]; - // Note: - // bc[ index ].m_instr is assigned to a positive - // value to differentiate with non-assignd values: - // the correspondent index in vf_Context.m_code array - // is increased by one. - bc[index].m_instr = codeNum + 1; + vf_Instr *instr = (vf_Instr*) ctx->m_instr; + + // parse bytecode instructions and fill a instruction array + for( index = 0; index < len; instr++ ) { + instr->m_addr = &bytecode[index]; + bc[index].m_instr = instr; bool wide = ( OPCODE_WIDE == bytecode[index] ); /* 0xc4 */ if( wide ) { @@ -4215,21 +4011,21 @@ vf_parse_bytecode( vf_Context_t * ctex ) case OPCODE_IINC: break; default: - VERIFY_REPORT_METHOD( ctex, - "Instruction wide should be followed " - "by iload, fload, aload, lload, dload, istore, fstore, astore, " - "lstore, dstore, ret or iinc" ); + VF_REPORT( ctx, + "Instruction wide should be followed " + "by iload, fload, aload, lload, dload, istore, fstore, astore, " + "lstore, dstore, ret or iinc" ); return VER_ErrorInstruction; } } - instr = index; // remember offset of instruction + unsigned prev_index = index; // remember offset of instruction index++; // skip bytecode - switch ( bytecode[instr] ) { + switch ( bytecode[prev_index] ) { case OPCODE_NOP: /* 0x00 */ break; case OPCODE_ACONST_NULL: /* 0x01 */ - vf_opcode_aconst_null( code, pool ); + vf_opcode_aconst_null( instr, pool ); break; case OPCODE_SIPUSH: /* 0x11 + s2 */ index++; // skip parameter (s2) @@ -4242,27 +4038,27 @@ vf_parse_bytecode( vf_Context_t * ctex ) case OPCODE_ICONST_3: /* 0x06 */ case OPCODE_ICONST_4: /* 0x07 */ case OPCODE_ICONST_5: /* 0x08 */ - vf_opcode_iconst_n( code, pool ); + vf_opcode_iconst_n( instr, pool ); break; case OPCODE_LCONST_0: /* 0x09 */ case OPCODE_LCONST_1: /* 0x0a */ - vf_opcode_lconst_n( code, pool ); + vf_opcode_lconst_n( instr, pool ); break; case OPCODE_FCONST_0: /* 0x0b */ case OPCODE_FCONST_1: /* 0x0c */ case OPCODE_FCONST_2: /* 0x0d */ - vf_opcode_fconst_n( code, pool ); + vf_opcode_fconst_n( instr, pool ); break; case OPCODE_DCONST_0: /* 0x0e */ case OPCODE_DCONST_1: /* 0x0f */ - vf_opcode_dconst_n( code, pool ); + vf_opcode_dconst_n( instr, pool ); break; case OPCODE_LDC: /* 0x12 + u1 */ // get constant pool index const_index = ( unsigned short )bytecode[index]; // skip constant pool index (u1) index++; - result = vf_opcode_ldcx( code, 1, const_index, ctex ); + result = vf_opcode_ldcx( instr, 1, const_index, ctx ); if( result != VER_OK ) { return result; } @@ -4276,346 +4072,336 @@ vf_parse_bytecode( vf_Context_t * ctex ) // skip constant pool index (u2) index += 2; result = - vf_opcode_ldcx( code, bytecode[instr] - OPCODE_LDC, - const_index, ctex ); + vf_opcode_ldcx( instr, bytecode[prev_index] - OPCODE_LDC, + const_index, ctx ); if( result != VER_OK ) { return result; } break; case OPCODE_ILOAD: /* 0x15 + u1|u2 */ - local = - ( unsigned short )vf_get_local_var_number( code, bytecode, - &index, wide ); - result = vf_check_local_var_number( local, locals, ctex ); + local = vf_get_local_var_number( instr, bytecode, &index, wide ); + result = vf_check_local_var_number( local, ctx ); if( result != VER_OK ) { return result; } - vf_opcode_iloadx( code, local, pool ); + vf_opcode_iloadx( instr, local, pool ); break; case OPCODE_LLOAD: /* 0x16 + u1|u2 */ - local = - ( unsigned short )vf_get_local_var_number( code, bytecode, - &index, wide ); - result = vf_check_local_var_number( local + 1, locals, ctex ); + local = vf_get_local_var_number( instr, bytecode, &index, wide ); + result = vf_check_local_var_number( local + 1, ctx ); if( result != VER_OK ) { return result; } - vf_opcode_lloadx( code, local, pool ); + vf_opcode_lloadx( instr, local, pool ); break; case OPCODE_FLOAD: /* 0x17 + u1|u2 */ - local = - ( unsigned short )vf_get_local_var_number( code, bytecode, - &index, wide ); - result = vf_check_local_var_number( local, locals, ctex ); + local = vf_get_local_var_number( instr, bytecode, &index, wide ); + result = vf_check_local_var_number( local, ctx ); if( result != VER_OK ) { return result; } - vf_opcode_floadx( code, local, pool ); + vf_opcode_floadx( instr, local, pool ); break; case OPCODE_DLOAD: /* 0x18 + u1|u2 */ - local = - ( unsigned short )vf_get_local_var_number( code, bytecode, - &index, wide ); - result = vf_check_local_var_number( local + 1, locals, ctex ); + local = vf_get_local_var_number( instr, bytecode, &index, wide ); + result = vf_check_local_var_number( local + 1, ctx ); if( result != VER_OK ) { return result; } - vf_opcode_dloadx( code, local, pool ); + vf_opcode_dloadx( instr, local, pool ); break; case OPCODE_ALOAD: /* 0x19 + u1|u2 */ - local = - ( unsigned short )vf_get_local_var_number( code, bytecode, - &index, wide ); - result = vf_check_local_var_number( local, locals, ctex ); + local = vf_get_local_var_number( instr, bytecode, &index, wide ); + result = vf_check_local_var_number( local, ctx ); if( result != VER_OK ) { return result; } - vf_opcode_aloadx( code, local, pool ); + vf_opcode_aloadx( instr, local, pool ); break; case OPCODE_ILOAD_0: /* 0x1a */ case OPCODE_ILOAD_1: /* 0x1b */ case OPCODE_ILOAD_2: /* 0x1c */ case OPCODE_ILOAD_3: /* 0x1d */ // get number of local variable - local = ( unsigned short )( bytecode[instr] - OPCODE_ILOAD_0 ); - result = vf_check_local_var_number( local, locals, ctex ); + local = + ( unsigned short )( bytecode[prev_index] - OPCODE_ILOAD_0 ); + result = vf_check_local_var_number( local, ctx ); if( result != VER_OK ) { return result; } - vf_opcode_iloadx( code, local, pool ); + vf_opcode_iloadx( instr, local, pool ); break; case OPCODE_LLOAD_0: /* 0x1e */ case OPCODE_LLOAD_1: /* 0x1f */ case OPCODE_LLOAD_2: /* 0x20 */ case OPCODE_LLOAD_3: /* 0x21 */ // get number of local variable - local = ( unsigned short )( bytecode[instr] - OPCODE_LLOAD_0 ); - result = vf_check_local_var_number( local + 1, locals, ctex ); + local = + ( unsigned short )( bytecode[prev_index] - OPCODE_LLOAD_0 ); + result = vf_check_local_var_number( local + 1, ctx ); if( result != VER_OK ) { return result; } - vf_opcode_lloadx( code, local, pool ); + vf_opcode_lloadx( instr, local, pool ); break; case OPCODE_FLOAD_0: /* 0x22 */ case OPCODE_FLOAD_1: /* 0x23 */ case OPCODE_FLOAD_2: /* 0x24 */ case OPCODE_FLOAD_3: /* 0x25 */ // get number of local variable - local = ( unsigned short )( bytecode[instr] - OPCODE_FLOAD_0 ); - result = vf_check_local_var_number( local, locals, ctex ); + local = + ( unsigned short )( bytecode[prev_index] - OPCODE_FLOAD_0 ); + result = vf_check_local_var_number( local, ctx ); if( result != VER_OK ) { return result; } - vf_opcode_floadx( code, local, pool ); + vf_opcode_floadx( instr, local, pool ); break; case OPCODE_DLOAD_0: /* 0x26 */ case OPCODE_DLOAD_1: /* 0x27 */ case OPCODE_DLOAD_2: /* 0x28 */ case OPCODE_DLOAD_3: /* 0x29 */ // get number of local variable - local = ( unsigned short )( bytecode[instr] - OPCODE_DLOAD_0 ); - result = vf_check_local_var_number( local + 1, locals, ctex ); + local = + ( unsigned short )( bytecode[prev_index] - OPCODE_DLOAD_0 ); + result = vf_check_local_var_number( local + 1, ctx ); if( result != VER_OK ) { return result; } - vf_opcode_dloadx( code, local, pool ); + vf_opcode_dloadx( instr, local, pool ); break; case OPCODE_ALOAD_0: /* 0x2a */ case OPCODE_ALOAD_1: /* 0x2b */ case OPCODE_ALOAD_2: /* 0x2c */ case OPCODE_ALOAD_3: /* 0x2d */ // get number of local variable - local = ( unsigned short )( bytecode[instr] - OPCODE_ALOAD_0 ); - result = vf_check_local_var_number( local, locals, ctex ); + local = + ( unsigned short )( bytecode[prev_index] - OPCODE_ALOAD_0 ); + result = vf_check_local_var_number( local, ctx ); if( result != VER_OK ) { return result; } - vf_opcode_aloadx( code, local, pool ); + vf_opcode_aloadx( instr, local, pool ); break; case OPCODE_IALOAD: /* 0x2e */ - vf_opcode_iaload( code, ctex ); + vf_opcode_iaload( instr, ctx ); break; case OPCODE_BALOAD: /* 0x33 */ - vf_opcode_baload( code, ctex ); + vf_opcode_baload( instr, ctx ); break; case OPCODE_CALOAD: /* 0x34 */ - vf_opcode_caload( code, ctex ); + vf_opcode_caload( instr, ctx ); break; case OPCODE_SALOAD: /* 0x35 */ - vf_opcode_saload( code, ctex ); + vf_opcode_saload( instr, ctx ); break; case OPCODE_LALOAD: /* 0x2f */ - vf_opcode_laload( code, ctex ); + vf_opcode_laload( instr, ctx ); break; case OPCODE_FALOAD: /* 0x30 */ - vf_opcode_faload( code, ctex ); + vf_opcode_faload( instr, ctx ); break; case OPCODE_DALOAD: /* 0x31 */ - vf_opcode_daload( code, ctex ); + vf_opcode_daload( instr, ctx ); break; case OPCODE_AALOAD: /* 0x32 */ - vf_opcode_aaload( code, ctex ); + vf_opcode_aaload( instr, ctx ); break; case OPCODE_ISTORE: /* 0x36 + u1|u2 */ - local = - ( unsigned short )vf_get_local_var_number( code, bytecode, - &index, wide ); - result = vf_check_local_var_number( local, locals, ctex ); + local = vf_get_local_var_number( instr, bytecode, &index, wide ); + result = vf_check_local_var_number( local, ctx ); if( result != VER_OK ) { return result; } - vf_opcode_istorex( code, local, pool ); + vf_opcode_istorex( instr, local, pool ); break; case OPCODE_LSTORE: /* 0x37 + u1|u2 */ - local = - ( unsigned short )vf_get_local_var_number( code, bytecode, - &index, wide ); - result = vf_check_local_var_number( local + 1, locals, ctex ); + local = vf_get_local_var_number( instr, bytecode, &index, wide ); + result = vf_check_local_var_number( local + 1, ctx ); if( result != VER_OK ) { return result; } - vf_opcode_lstorex( code, local, pool ); + vf_opcode_lstorex( instr, local, pool ); break; case OPCODE_FSTORE: /* 0x38 + u1|u2 */ - local = - ( unsigned short )vf_get_local_var_number( code, bytecode, - &index, wide ); - result = vf_check_local_var_number( local, locals, ctex ); + local = vf_get_local_var_number( instr, bytecode, &index, wide ); + result = vf_check_local_var_number( local, ctx ); if( result != VER_OK ) { return result; } - vf_opcode_fstorex( code, local, pool ); + vf_opcode_fstorex( instr, local, pool ); break; case OPCODE_DSTORE: /* 0x39 + u1|u2 */ - local = - ( unsigned short )vf_get_local_var_number( code, bytecode, - &index, wide ); - result = vf_check_local_var_number( local + 1, locals, ctex ); + local = vf_get_local_var_number( instr, bytecode, &index, wide ); + result = vf_check_local_var_number( local + 1, ctx ); if( result != VER_OK ) { return result; } - vf_opcode_dstorex( code, local, pool ); + vf_opcode_dstorex( instr, local, pool ); break; case OPCODE_ASTORE: /* 0x3a + u1|u2 */ - local = - ( unsigned short )vf_get_local_var_number( code, bytecode, - &index, wide ); - result = vf_check_local_var_number( local, locals, ctex ); + local = vf_get_local_var_number( instr, bytecode, &index, wide ); + result = vf_check_local_var_number( local, ctx ); if( result != VER_OK ) { return result; } - vf_opcode_astorex( code, local, pool ); + vf_opcode_astorex( instr, local, pool ); break; case OPCODE_ISTORE_0: /* 0x3b */ case OPCODE_ISTORE_1: /* 0x3c */ case OPCODE_ISTORE_2: /* 0x3d */ case OPCODE_ISTORE_3: /* 0x3e */ // get number of local variable - local = ( unsigned short )( bytecode[instr] - OPCODE_ISTORE_0 ); - result = vf_check_local_var_number( local, locals, ctex ); + local = + ( unsigned short )( bytecode[prev_index] - OPCODE_ISTORE_0 ); + result = vf_check_local_var_number( local, ctx ); if( result != VER_OK ) { return result; } - vf_opcode_istorex( code, local, pool ); + vf_opcode_istorex( instr, local, pool ); break; case OPCODE_LSTORE_0: /* 0x3f */ case OPCODE_LSTORE_1: /* 0x40 */ case OPCODE_LSTORE_2: /* 0x41 */ case OPCODE_LSTORE_3: /* 0x42 */ // get number of local variable - local = ( unsigned short )( bytecode[instr] - OPCODE_LSTORE_0 ); - result = vf_check_local_var_number( local + 1, locals, ctex ); + local = + ( unsigned short )( bytecode[prev_index] - OPCODE_LSTORE_0 ); + result = vf_check_local_var_number( local + 1, ctx ); if( result != VER_OK ) { return result; } - vf_opcode_lstorex( code, local, pool ); + vf_opcode_lstorex( instr, local, pool ); break; case OPCODE_FSTORE_0: /* 0x43 */ case OPCODE_FSTORE_1: /* 0x44 */ case OPCODE_FSTORE_2: /* 0x45 */ case OPCODE_FSTORE_3: /* 0x46 */ // get number of local variable - local = ( unsigned short )( bytecode[instr] - OPCODE_FSTORE_0 ); - result = vf_check_local_var_number( local, locals, ctex ); + local = + ( unsigned short )( bytecode[prev_index] - OPCODE_FSTORE_0 ); + result = vf_check_local_var_number( local, ctx ); if( result != VER_OK ) { return result; } - vf_opcode_fstorex( code, local, pool ); + vf_opcode_fstorex( instr, local, pool ); break; case OPCODE_DSTORE_0: /* 0x47 */ case OPCODE_DSTORE_1: /* 0x48 */ case OPCODE_DSTORE_2: /* 0x49 */ case OPCODE_DSTORE_3: /* 0x4a */ // get number of local variable - local = ( unsigned short )( bytecode[instr] - OPCODE_DSTORE_0 ); - result = vf_check_local_var_number( local + 1, locals, ctex ); + local = + ( unsigned short )( bytecode[prev_index] - OPCODE_DSTORE_0 ); + result = vf_check_local_var_number( local + 1, ctx ); if( result != VER_OK ) { return result; } - vf_opcode_dstorex( code, local, pool ); + vf_opcode_dstorex( instr, local, pool ); break; case OPCODE_ASTORE_0: /* 0x4b */ case OPCODE_ASTORE_1: /* 0x4c */ case OPCODE_ASTORE_2: /* 0x4d */ case OPCODE_ASTORE_3: /* 0x4e */ // get number of local variable - local = ( unsigned short )( bytecode[instr] - OPCODE_ASTORE_0 ); - result = vf_check_local_var_number( local, locals, ctex ); + local = + ( unsigned short )( bytecode[prev_index] - OPCODE_ASTORE_0 ); + result = vf_check_local_var_number( local, ctx ); if( result != VER_OK ) { return result; } - vf_opcode_astorex( code, local, pool ); + vf_opcode_astorex( instr, local, pool ); break; case OPCODE_IASTORE: /* 0x4f */ - vf_opcode_iastore( code, ctex ); + vf_opcode_iastore( instr, ctx ); break; case OPCODE_BASTORE: /* 0x54 */ - vf_opcode_bastore( code, ctex ); + vf_opcode_bastore( instr, ctx ); break; case OPCODE_CASTORE: /* 0x55 */ - vf_opcode_castore( code, ctex ); + vf_opcode_castore( instr, ctx ); break; case OPCODE_SASTORE: /* 0x56 */ - vf_opcode_sastore( code, ctex ); + vf_opcode_sastore( instr, ctx ); break; case OPCODE_LASTORE: /* 0x50 */ - vf_opcode_lastore( code, ctex ); + vf_opcode_lastore( instr, ctx ); break; case OPCODE_FASTORE: /* 0x51 */ - vf_opcode_fastore( code, ctex ); + vf_opcode_fastore( instr, ctx ); break; case OPCODE_DASTORE: /* 0x52 */ - vf_opcode_dastore( code, ctex ); + vf_opcode_dastore( instr, ctx ); break; case OPCODE_AASTORE: /* 0x53 */ - vf_opcode_aastore( code, ctex ); + vf_opcode_aastore( instr, ctx ); break; case OPCODE_POP: /* 0x57 */ - vf_opcode_pop( code, pool ); + vf_opcode_pop( instr, pool ); break; case OPCODE_POP2: /* 0x58 */ - vf_opcode_pop2( code, pool ); + vf_opcode_pop2( instr, pool ); break; case OPCODE_DUP: /* 0x59 */ - vf_opcode_dup( code, pool ); + vf_opcode_dup( instr, pool ); break; case OPCODE_DUP_X1: /* 0x5a */ - vf_opcode_dup_x1( code, pool ); + vf_opcode_dup_x1( instr, pool ); break; case OPCODE_DUP_X2: /* 0x5b */ - vf_opcode_dup_x2( code, pool ); + vf_opcode_dup_x2( instr, pool ); break; case OPCODE_DUP2: /* 0x5c */ - vf_opcode_dup2( code, pool ); + vf_opcode_dup2( instr, pool ); break; case OPCODE_DUP2_X1: /* 0x5d */ - vf_opcode_dup2_x1( code, pool ); + vf_opcode_dup2_x1( instr, pool ); break; case OPCODE_DUP2_X2: /* 0x5e */ - vf_opcode_dup2_x2( code, pool ); + vf_opcode_dup2_x2( instr, pool ); break; case OPCODE_SWAP: /* 0x5f */ - vf_opcode_swap( code, pool ); + vf_opcode_swap( instr, pool ); break; case OPCODE_IADD: /* 0x60 */ case OPCODE_ISUB: /* 0x64 */ case OPCODE_IMUL: /* 0x68 */ case OPCODE_IDIV: /* 0x6c */ case OPCODE_IREM: /* 0x70 */ - vf_opcode_iadd( code, pool ); + vf_opcode_iadd( instr, pool ); break; case OPCODE_LADD: /* 0x61 */ case OPCODE_LSUB: /* 0x65 */ case OPCODE_LMUL: /* 0x69 */ case OPCODE_LDIV: /* 0x6d */ case OPCODE_LREM: /* 0x71 */ - vf_opcode_ladd( code, pool ); + vf_opcode_ladd( instr, pool ); break; case OPCODE_FADD: /* 0x62 */ case OPCODE_FSUB: /* 0x66 */ case OPCODE_FMUL: /* 0x6a */ case OPCODE_FDIV: /* 0x6e */ case OPCODE_FREM: /* 0x72 */ - vf_opcode_fadd( code, pool ); + vf_opcode_fadd( instr, pool ); break; case OPCODE_DADD: /* 0x63 */ case OPCODE_DSUB: /* 0x67 */ case OPCODE_DMUL: /* 0x6b */ case OPCODE_DDIV: /* 0x6f */ case OPCODE_DREM: /* 0x73 */ - vf_opcode_dadd( code, pool ); + vf_opcode_dadd( instr, pool ); break; case OPCODE_INEG: /* 0x74 */ - vf_opcode_ineg( code, pool ); + vf_opcode_ineg( instr, pool ); break; case OPCODE_LNEG: /* 0x75 */ - vf_opcode_lneg( code, pool ); + vf_opcode_lneg( instr, pool ); break; case OPCODE_FNEG: /* 0x76 */ - vf_opcode_fneg( code, pool ); + vf_opcode_fneg( instr, pool ); break; case OPCODE_DNEG: /* 0x77 */ - vf_opcode_dneg( code, pool ); + vf_opcode_dneg( instr, pool ); break; case OPCODE_ISHL: /* 0x78 */ case OPCODE_ISHR: /* 0x7a */ @@ -4623,83 +4409,81 @@ vf_parse_bytecode( vf_Context_t * ctex ) case OPCODE_IAND: /* 0x7e */ case OPCODE_IOR: /* 0x80 */ case OPCODE_IXOR: /* 0x82 */ - vf_opcode_ibit( code, pool ); + vf_opcode_ibit( instr, pool ); break; case OPCODE_LSHL: /* 0x79 */ case OPCODE_LSHR: /* 0x7b */ case OPCODE_LUSHR: /* 0x7d */ - vf_opcode_lshx( code, pool ); + vf_opcode_lshx( instr, pool ); break; case OPCODE_LAND: /* 0x7f */ case OPCODE_LOR: /* 0x81 */ case OPCODE_LXOR: /* 0x83 */ - vf_opcode_land( code, pool ); + vf_opcode_land( instr, pool ); break; case OPCODE_IINC: /* 0x84 + u1|u2 + s1|s2 */ count = index; - local = - ( unsigned short )vf_get_local_var_number( code, bytecode, - &index, wide ); + local = vf_get_local_var_number( instr, bytecode, &index, wide ); count = index - count; - result = vf_check_local_var_number( local, locals, ctex ); + result = vf_check_local_var_number( local, ctx ); if( result != VER_OK ) { return result; } - vf_opcode_iinc( code, local, pool ); + vf_opcode_iinc( instr, local, pool ); // skip 2nd parameter (s1|s2) index += count; break; case OPCODE_I2L: /* 0x85 */ - vf_opcode_i2l( code, pool ); + vf_opcode_i2l( instr, pool ); break; case OPCODE_I2F: /* 0x86 */ - vf_opcode_i2f( code, pool ); + vf_opcode_i2f( instr, pool ); break; case OPCODE_I2D: /* 0x87 */ - vf_opcode_i2d( code, pool ); + vf_opcode_i2d( instr, pool ); break; case OPCODE_L2I: /* 0x88 */ - vf_opcode_l2i( code, pool ); + vf_opcode_l2i( instr, pool ); break; case OPCODE_L2F: /* 0x89 */ - vf_opcode_l2f( code, pool ); + vf_opcode_l2f( instr, pool ); break; case OPCODE_L2D: /* 0x8a */ - vf_opcode_l2d( code, pool ); + vf_opcode_l2d( instr, pool ); break; case OPCODE_F2I: /* 0x8b */ - vf_opcode_f2i( code, pool ); + vf_opcode_f2i( instr, pool ); break; case OPCODE_F2L: /* 0x8c */ - vf_opcode_f2l( code, pool ); + vf_opcode_f2l( instr, pool ); break; case OPCODE_F2D: /* 0x8d */ - vf_opcode_f2d( code, pool ); + vf_opcode_f2d( instr, pool ); break; case OPCODE_D2I: /* 0x8e */ - vf_opcode_d2i( code, pool ); + vf_opcode_d2i( instr, pool ); break; case OPCODE_D2L: /* 0x8f */ - vf_opcode_d2l( code, pool ); + vf_opcode_d2l( instr, pool ); break; case OPCODE_D2F: /* 0x90 */ - vf_opcode_d2f( code, pool ); + vf_opcode_d2f( instr, pool ); break; case OPCODE_I2B: /* 0x91 */ case OPCODE_I2C: /* 0x92 */ case OPCODE_I2S: /* 0x93 */ - vf_opcode_i2b( code, pool ); + vf_opcode_i2b( instr, pool ); break; case OPCODE_LCMP: /* 0x94 */ - vf_opcode_lcmp( code, pool ); + vf_opcode_lcmp( instr, pool ); break; case OPCODE_FCMPL: /* 0x95 */ case OPCODE_FCMPG: /* 0x96 */ - vf_opcode_fcmpx( code, pool ); + vf_opcode_fcmpx( instr, pool ); break; case OPCODE_DCMPL: /* 0x97 */ case OPCODE_DCMPG: /* 0x98 */ - vf_opcode_dcmpx( code, pool ); + vf_opcode_dcmpx( instr, pool ); break; case OPCODE_IFEQ: /* 0x99 + s2 */ case OPCODE_IFNE: /* 0x9a + s2 */ @@ -4707,18 +4491,18 @@ vf_parse_bytecode( vf_Context_t * ctex ) case OPCODE_IFGE: /* 0x9c + s2 */ case OPCODE_IFGT: /* 0x9d + s2 */ case OPCODE_IFLE: /* 0x9e + s2 */ - offset = vf_get_double_hword_branch_offset( code, - instr, bytecode, + offset = vf_get_double_hword_branch_offset( instr, + prev_index, bytecode, &index, pool ); - result = vf_check_branch_offset( offset, len, ctex ); + result = vf_check_branch_offset( offset, ctx ); if( result != VER_OK ) { return result; } - result = vf_check_branch_offset( index, len, ctex ); + result = vf_check_branch_offset( index, ctx ); if( result != VER_OK ) { return result; } - vf_opcode_ifeq( code, &bc[offset], &bc[index], pool ); + vf_opcode_ifeq( instr, &bc[offset], &bc[index], pool ); break; case OPCODE_IF_ICMPEQ: /* 0x9f + s2 */ case OPCODE_IF_ICMPNE: /* 0xa0 + s2 */ @@ -4726,159 +4510,133 @@ vf_parse_bytecode( vf_Context_t * ctex ) case OPCODE_IF_ICMPGE: /* 0xa2 + s2 */ case OPCODE_IF_ICMPGT: /* 0xa3 + s2 */ case OPCODE_IF_ICMPLE: /* 0xa4 + s2 */ - offset = vf_get_double_hword_branch_offset( code, - instr, bytecode, + offset = vf_get_double_hword_branch_offset( instr, + prev_index, bytecode, &index, pool ); - result = vf_check_branch_offset( offset, len, ctex ); + result = vf_check_branch_offset( offset, ctx ); if( result != VER_OK ) { return result; } - result = vf_check_branch_offset( index, len, ctex ); + result = vf_check_branch_offset( index, ctx ); if( result != VER_OK ) { return result; } - vf_opcode_if_icmpeq( code, &bc[offset], &bc[index], pool ); + vf_opcode_if_icmpeq( instr, &bc[offset], &bc[index], pool ); break; case OPCODE_IF_ACMPEQ: /* 0xa5 + s2 */ case OPCODE_IF_ACMPNE: /* 0xa6 + s2 */ - offset = vf_get_double_hword_branch_offset( code, - instr, bytecode, + offset = vf_get_double_hword_branch_offset( instr, + prev_index, bytecode, &index, pool ); - result = vf_check_branch_offset( offset, len, ctex ); + result = vf_check_branch_offset( offset, ctx ); if( result != VER_OK ) { return result; } - result = vf_check_branch_offset( index, len, ctex ); + result = vf_check_branch_offset( index, ctx ); if( result != VER_OK ) { return result; } - vf_opcode_if_acmpeq( code, &bc[offset], &bc[index], pool ); + vf_opcode_if_acmpeq( instr, &bc[offset], &bc[index], pool ); break; case OPCODE_GOTO: /* 0xa7 + s2 */ - offset = vf_get_single_hword_branch_offset( code, - instr, bytecode, + offset = vf_get_single_hword_branch_offset( instr, + prev_index, bytecode, &index, pool ); - result = vf_check_branch_offset( offset, len, ctex ); + result = vf_check_branch_offset( offset, ctx ); if( result != VER_OK ) { return result; } - vf_set_basic_block_flag( &bc[offset] ); - if( index < len ) { - vf_set_basic_block_flag( &bc[index] ); - } + vf_set_basic_block_flag( index, ctx ); break; case OPCODE_JSR: /* 0xa8 + s2 */ - offset = vf_get_single_hword_branch_offset( code, - instr, bytecode, + offset = vf_get_single_hword_branch_offset( instr, + prev_index, bytecode, &index, pool ); - result = vf_check_branch_offset( offset, len, ctex ); - if( result != VER_OK ) { - return result; - } - result = vf_check_branch_offset( index, len, ctex ); + result = vf_check_branch_offset( offset, ctx ); if( result != VER_OK ) { return result; } - vf_opcode_jsr( code, codeNum, pool ); - ctex->m_dump.m_with_subroutine = 1; - vf_set_basic_block_flag( &bc[offset] ); - vf_set_basic_block_flag( &bc[index] ); + vf_opcode_jsr( instr, offset, pool ); + vf_set_basic_block_flag( index, ctx ); break; case OPCODE_RET: /* 0xa9 + u1|u2 */ - local = - ( unsigned short )vf_get_local_var_number( code, bytecode, - &index, wide ); - result = vf_check_local_var_number( local, locals, ctex ); + local = vf_get_local_var_number( instr, bytecode, &index, wide ); + result = vf_check_local_var_number( local, ctx ); if( result != VER_OK ) { return result; } - vf_opcode_ret( code, local, pool ); + vf_opcode_ret( instr, local, pool ); // create and set edge branch to exit - if( index < len ) { - vf_set_basic_block_flag( &bc[index] ); - } + vf_set_basic_block_flag( index, ctx ); + ret_num++; break; case OPCODE_TABLESWITCH: /* 0xaa + pad + s4 * (3 + N) */ - vf_opcode_switch( code, pool ); - branches = vf_set_tableswitch_offsets( code, - instr, &index, bytecode, - pool ); + vf_opcode_switch( instr, pool ); + branches = vf_set_tableswitch_offsets( instr, + prev_index, &index, + bytecode, pool ); // check tableswitch branches and set begin of basic blocks for( count = 0; count < branches; count++ ) { - offset = vf_get_code_branch( code, count ); - result = vf_check_branch_offset( offset, len, ctex ); + offset = vf_get_instr_branch( instr, count ); + result = vf_check_branch_offset( offset, ctx ); if( result != VER_OK ) { return result; } - vf_set_basic_block_flag( &bc[offset] ); } if( index < len ) { - vf_set_basic_block_flag( &bc[index] ); + vf_set_basic_block_flag( index, ctx ); } break; case OPCODE_LOOKUPSWITCH: /* 0xab + pad + s4 * 2 * (N + 1) */ - vf_opcode_switch( code, pool ); - result = vf_set_lookupswitch_offsets( code, - instr, &index, bytecode, - &branches, ctex ); + vf_opcode_switch( instr, pool ); + result = vf_set_lookupswitch_offsets( instr, + prev_index, &index, + bytecode, &branches, ctx ); if( result != VER_OK ) { return result; } // check tableswitch branches and set begin of basic blocks for( count = 0; count < branches; count++ ) { - offset = vf_get_code_branch( code, count ); - result = vf_check_branch_offset( offset, len, ctex ); + offset = vf_get_instr_branch( instr, count ); + result = vf_check_branch_offset( offset, ctx ); if( result != VER_OK ) { return result; } - vf_set_basic_block_flag( &bc[offset] ); } if( index < len ) { - vf_set_basic_block_flag( &bc[index] ); + vf_set_basic_block_flag( index, ctx ); } break; case OPCODE_IRETURN: /* 0xac */ - vf_opcode_ireturn( code, pool ); + vf_opcode_ireturn( instr, pool ); // create and set edge branch to exit - if( index < len ) { - vf_set_basic_block_flag( &bc[index] ); - } + vf_set_basic_block_flag( index, ctx ); break; case OPCODE_LRETURN: /* 0xad */ - vf_opcode_lreturn( code, pool ); + vf_opcode_lreturn( instr, pool ); // create and set edge branch to exit - if( index < len ) { - vf_set_basic_block_flag( &bc[index] ); - } + vf_set_basic_block_flag( index, ctx ); break; case OPCODE_FRETURN: /* 0xae */ - vf_opcode_freturn( code, pool ); + vf_opcode_freturn( instr, pool ); // create and set edge branch to exit - if( index < len ) { - vf_set_basic_block_flag( &bc[index] ); - } + vf_set_basic_block_flag( index, ctx ); break; case OPCODE_DRETURN: /* 0xaf */ - vf_opcode_dreturn( code, pool ); + vf_opcode_dreturn( instr, pool ); // create and set edge branch to exit - if( index < len ) { - vf_set_basic_block_flag( &bc[index] ); - } + vf_set_basic_block_flag( index, ctx ); break; case OPCODE_ARETURN: /* 0xb0 */ - vf_opcode_areturn( code, pool ); + vf_opcode_areturn( instr, pool ); // create and set edge branch to exit - if( index < len ) { - vf_set_basic_block_flag( &bc[index] ); - } + vf_set_basic_block_flag( index, ctx ); break; case OPCODE_RETURN: /* 0xb1 */ // set instruction flag - vf_set_code_type( code, VF_TYPE_INSTR_RETURN ); + vf_set_instr_type( instr, VF_INSTR_RETURN ); // create and set edge branch to exit - if( index < len ) { - vf_set_basic_block_flag( &bc[index] ); - } + vf_set_basic_block_flag( index, ctx ); break; case OPCODE_GETSTATIC: /* 0xb2 + u2 */ // get constant pool index @@ -4887,7 +4645,7 @@ vf_parse_bytecode( vf_Context_t * ctex ) ( bytecode[index + 1] ) ); // skip constant pool index (u2) index += 2; - result = vf_opcode_getstatic( code, const_index, ctex ); + result = vf_opcode_getstatic( instr, const_index, ctx ); if( result != VER_OK ) { return result; } @@ -4899,7 +4657,7 @@ vf_parse_bytecode( vf_Context_t * ctex ) ( bytecode[index + 1] ) ); // skip constant pool index (u2) index += 2; - result = vf_opcode_putstatic( code, const_index, ctex ); + result = vf_opcode_putstatic( instr, const_index, ctx ); if( result != VER_OK ) { return result; } @@ -4911,7 +4669,7 @@ vf_parse_bytecode( vf_Context_t * ctex ) ( bytecode[index + 1] ) ); // skip constant pool index (u2) index += 2; - result = vf_opcode_getfield( code, const_index, ctex ); + result = vf_opcode_getfield( instr, const_index, ctx ); if( result != VER_OK ) { return result; } @@ -4923,7 +4681,7 @@ vf_parse_bytecode( vf_Context_t * ctex ) ( bytecode[index + 1] ) ); // skip constant pool index (u2) index += 2; - result = vf_opcode_putfield( code, const_index, ctex ); + result = vf_opcode_putfield( instr, const_index, ctx ); if( result != VER_OK ) { return result; } @@ -4935,7 +4693,7 @@ vf_parse_bytecode( vf_Context_t * ctex ) ( bytecode[index + 1] ) ); // skip constant pool index (u2) index += 2; - result = vf_opcode_invoke( code, const_index, ctex ); + result = vf_opcode_invoke( instr, const_index, ctx ); if( result != VER_OK ) { return result; } @@ -4947,7 +4705,7 @@ vf_parse_bytecode( vf_Context_t * ctex ) ( bytecode[index + 1] ) ); // skip constant pool index (u2) index += 2; - result = vf_opcode_invokespecial( code, const_index, ctex ); + result = vf_opcode_invokespecial( instr, const_index, ctx ); if( result != VER_OK ) { return result; } @@ -4959,7 +4717,7 @@ vf_parse_bytecode( vf_Context_t * ctex ) ( bytecode[index + 1] ) ); // skip constant pool index (u2) index += 2; - result = vf_opcode_invoke( code, const_index, ctex ); + result = vf_opcode_invoke( instr, const_index, ctx ); if( result != VER_OK ) { return result; } @@ -4971,16 +4729,14 @@ vf_parse_bytecode( vf_Context_t * ctex ) ( bytecode[index + 1] ) ); // skip constant pool index (u2) index += 2; - result = vf_opcode_invoke( code, const_index, ctex ); + result = vf_opcode_invoke( instr, const_index, ctx ); if( result != VER_OK ) { return result; } // check the number of arguments and last opcode byte - if( ctex->m_code[codeNum].m_inlen != - ( unsigned short )bytecode[index] + if( instr->m_inlen != ( unsigned short )bytecode[index] || bytecode[index + 1] != 0 ) { - VERIFY_REPORT_METHOD( ctex, - "Incorrect operand byte of invokeinterface" ); + VF_REPORT( ctx, "Incorrect operand byte of invokeinterface" ); return VER_ErrorInstruction; } // skip 2 parameters (u1 + u1) @@ -4993,8 +4749,11 @@ vf_parse_bytecode( vf_Context_t * ctex ) ( bytecode[index + 1] ) ); // skip constant pool index (u2) index += 2; - // Zero number of opcode new is reserved for "uninitialized this" - result = vf_opcode_new( code, const_index, codeNum + 1, ctex ); + // zero number of opcode new is reserved for "uninitialized this" + result = + vf_opcode_new( instr, const_index, instr - ctx->m_instr + 1, + ctx ); + if( result != VER_OK ) { return result; } @@ -5004,7 +4763,7 @@ vf_parse_bytecode( vf_Context_t * ctex ) u1 = ( unsigned char )bytecode[index]; // skip parameter (u1) index++; - result = vf_opcode_newarray( code, u1, ctex ); + result = vf_opcode_newarray( instr, u1, ctx ); if( result != VER_OK ) { return result; } @@ -5016,20 +4775,18 @@ vf_parse_bytecode( vf_Context_t * ctex ) ( bytecode[index + 1] ) ); // skip constant pool index (u2) index += 2; - result = vf_opcode_anewarray( code, const_index, ctex ); + result = vf_opcode_anewarray( instr, const_index, ctx ); if( result != VER_OK ) { return result; } break; case OPCODE_ARRAYLENGTH: /* 0xbe */ - vf_opcode_arraylength( code, ctex ); + vf_opcode_arraylength( instr, ctx ); break; case OPCODE_ATHROW: /* 0xbf */ - vf_opcode_athrow( code, ctex ); + vf_opcode_athrow( instr, ctx ); // create and set edge branch to exit - if( index < len ) { - vf_set_basic_block_flag( &bc[index] ); - } + vf_set_basic_block_flag( index, ctx ); break; case OPCODE_CHECKCAST: /* 0xc0 + u2 */ // get constant pool index @@ -5038,7 +4795,7 @@ vf_parse_bytecode( vf_Context_t * ctex ) ( bytecode[index + 1] ) ); // skip constant pool index (u2) index += 2; - result = vf_opcode_checkcast( code, const_index, ctex ); + result = vf_opcode_checkcast( instr, const_index, ctx ); if( result != VER_OK ) { return result; } @@ -5050,14 +4807,14 @@ vf_parse_bytecode( vf_Context_t * ctex ) ( bytecode[index + 1] ) ); // skip constant pool index (u2) index += 2; - result = vf_opcode_instanceof( code, const_index, ctex ); + result = vf_opcode_instanceof( instr, const_index, ctx ); if( result != VER_OK ) { return result; } break; case OPCODE_MONITORENTER: /* 0xc2 */ case OPCODE_MONITOREXIT: /* 0xc3 */ - vf_opcode_monitorx( code, pool ); + vf_opcode_monitorx( instr, pool ); break; case OPCODE_MULTIANEWARRAY: /* 0xc5 + u2 + u1 */ // get constant pool index @@ -5070,67 +4827,56 @@ vf_parse_bytecode( vf_Context_t * ctex ) u1 = bytecode[index]; // skip dimensions of array (u1) index++; - result = vf_opcode_multianewarray( code, const_index, u1, ctex ); + result = vf_opcode_multianewarray( instr, const_index, u1, ctx ); if( result != VER_OK ) { return result; } break; case OPCODE_IFNULL: /* 0xc6 + s2 */ case OPCODE_IFNONNULL: /* 0xc7 + s2 */ - offset = vf_get_double_hword_branch_offset( code, - instr, bytecode, + offset = vf_get_double_hword_branch_offset( instr, + prev_index, bytecode, &index, pool ); - result = vf_check_branch_offset( offset, len, ctex ); + result = vf_check_branch_offset( offset, ctx ); if( result != VER_OK ) { return result; } - result = vf_check_branch_offset( index, len, ctex ); + result = vf_check_branch_offset( index, ctx ); if( result != VER_OK ) { return result; } - vf_opcode_ifxnull( &ctex->m_code[codeNum], &bc[offset], - &bc[index], pool ); + vf_opcode_ifxnull( instr, &bc[offset], &bc[index], pool ); break; case OPCODE_GOTO_W: /* 0xc8 + s4 */ - offset = vf_get_single_word_branch_offset( code, - instr, bytecode, + offset = vf_get_single_word_branch_offset( instr, + prev_index, bytecode, &index, pool ); - result = vf_check_branch_offset( offset, len, ctex ); + result = vf_check_branch_offset( offset, ctx ); if( result != VER_OK ) { return result; } - vf_set_basic_block_flag( &bc[offset] ); - if( index < len ) { - vf_set_basic_block_flag( &bc[index] ); - } + vf_set_basic_block_flag( index, ctx ); break; case OPCODE_JSR_W: /* 0xc9 + s4 */ - offset = vf_get_single_word_branch_offset( code, - instr, bytecode, + offset = vf_get_single_word_branch_offset( instr, + prev_index, bytecode, &index, pool ); - result = vf_check_branch_offset( offset, len, ctex ); - if( result != VER_OK ) { - return result; - } - result = vf_check_branch_offset( index, len, ctex ); + result = vf_check_branch_offset( offset, ctx ); if( result != VER_OK ) { return result; } - vf_opcode_jsr( code, codeNum, pool ); - ctex->m_dump.m_with_subroutine = 1; - vf_set_basic_block_flag( &bc[offset] ); - vf_set_basic_block_flag( &bc[index] ); + vf_opcode_jsr( instr, offset, pool ); + vf_set_basic_block_flag( index, ctx ); break; case _OPCODE_UNDEFINED: /* 0xba */ default: - VERIFY_REPORT_METHOD( ctex, "Unknown bytecode instruction " ); + VF_REPORT( ctx, "Unknown bytecode instruction " ); return VER_ErrorInstruction; } } if( index > len ) { - VERIFY_REPORT_METHOD( ctex, - "The last instruction doesn't fit bytecode array" ); + VF_REPORT( ctx, "The last instruction doesn't fit bytecode array" ); return VER_ErrorInstruction; } @@ -5138,218 +4884,153 @@ vf_parse_bytecode( vf_Context_t * ctex ) * Set handler basic blocks. */ unsigned short handler_count = - method_get_exc_handler_number( ctex->m_method ); - unsigned short constLen = class_get_cp_size( ctex->m_class ); + method_get_exc_handler_number( ctx->m_method ); + unsigned short constLen = class_get_cp_size( ctx->m_class ); for( unsigned short handler_index = 0; handler_index < handler_count; handler_index++ ) { unsigned short start_pc, end_pc, handler_pc, handler_cp_index; - method_get_exc_handler_info( ctex->m_method, + method_get_exc_handler_info( ctx->m_method, handler_index, &start_pc, &end_pc, &handler_pc, &handler_cp_index ); // check instruction range if( ( start_pc >= len ) || ( end_pc > len ) || ( handler_pc >= len ) ) { - VERIFY_REPORT_METHOD( ctex, - "Exception handler pc is out of range" ); + VF_REPORT( ctx, "Exception handler pc is out of range" ); return VER_ErrorHandler; } if( start_pc >= end_pc ) { - VERIFY_REPORT_METHOD( ctex, - "Exception handler range starting point should be before ending point" ); + VF_REPORT( ctx, + "Exception handler range starting point should be before ending point" ); return VER_ErrorHandler; } // check that handlers point to instruction // boundaries - if( bc[start_pc].m_instr == 0 - || bc[end_pc].m_instr == 0 || bc[handler_pc].m_instr == 0 ) { - VERIFY_REPORT_METHOD( ctex, "Exception handler parameters [" - << start_pc << ", " << end_pc << ", " << - handler_pc << - "] are out of instruction set" ); + if( NULL == bc[start_pc].m_instr + || NULL == bc[end_pc].m_instr + || NULL == bc[handler_pc].m_instr ) { + VF_REPORT( ctx, + "At least one of exception handler parameters [" + << start_pc << ", " << end_pc << ", " << + handler_pc << "] are out of instruction set" ); return VER_ErrorHandler; } - bc[start_pc].m_mark = 1; - if( end_pc < len ) { - bc[end_pc].m_mark = 1; - } - bc[handler_pc].m_mark = 1; - } - - /** - * Count edges from basic blocks from exception range to the - * corresponding exception handlers. - */ - unsigned edges = 0; - for( unsigned short handler_index = 0; - handler_index < handler_count; handler_index++ ) { - unsigned short start_pc, end_pc, handler_pc, handler_cp_index; - method_get_exc_handler_info( ctex->m_method, handler_index, - &start_pc, &end_pc, &handler_pc, - &handler_cp_index ); - - // number of basic blocks in the exception range - unsigned handler_edges = 0; - for( count = start_pc; count < end_pc; count++ ) { - handler_edges += bc[count].m_mark; - } - - edges += handler_edges; + bc[start_pc].m_basic_block_start = true; + bc[end_pc].m_basic_block_start = true; + bc[handler_pc].m_basic_block_start = true; } - /** - * Initialize a node counter with handler nodes - * and 2 terminator nodes. - */ - unsigned nodes = handler_count + 2; - - /** - * Check code offsets, count basic blocks and edges. - */ - for( index = 0; index < len; index++ ) { - instr = bc[index].m_instr; - if( instr == 0 ) { - if( bc[index].m_mark ) { - VERIFY_REPORT_METHOD( ctex, - "Illegal target of jump or branch" ); - return VER_ErrorBranch; - } else { - continue; - } - } - - code = &ctex->m_code[instr - 1]; - if( bc[index].m_mark ) { - code->m_basic_block_start = true; - nodes++; - } - - if( code->m_offcount ) { - // basic block should start next, so we will - // count one branch anyway - edges += code->m_offcount - 1; - } - } - - /** - * Each node except the ending node emits at least one branch. - */ - edges += nodes - 1; - // store context values - ctex->m_codeNum = codeNum; - ctex->m_nodeNum = nodes; - ctex->m_edgeNum = edges; - -#if _VERIFY_DEBUG - if( ctex->m_dump.m_code ) { - vf_dump_bytecode( ctex ); + ctx->m_last_instr = instr; + ctx->m_retnum = ret_num; + + if( vf_is_trace_enabled( DUMP_INSTR ) ) { + vf_dump_bytecode( ctx ); } -#endif // _VERIFY_DEBUG return result; } // vf_parse_bytecode -#if _VERIFY_DEBUG +#if _VF_DEBUG /** * Function prints code instruction array in stream. */ void -vf_dump_bytecode( vf_Context_t * ctex ) // verifier context +vf_dump_bytecode( vf_ContextHandle ctx ) // verification context { - VERIFY_DEBUG + VF_DEBUG ( "======================== VERIFIER METHOD DUMP ========================" ); - VERIFY_DEBUG( "Method: " << class_get_name( ctex->m_class ) - << "." << method_get_name( ctex->m_method ) - << method_get_descriptor( ctex->m_method ) << endl ); - VERIFY_DEBUG( "0 [-]: -> START-ENTRY" ); + VF_DEBUG( "Method: " << class_get_name( ctx->m_class ) + << "." << method_get_name( ctx->m_method ) + << method_get_descriptor( ctx->m_method ) << endl ); + VF_DEBUG( "0 [-]: -> START-ENTRY" ); unsigned short handler_count = - method_get_exc_handler_number( ctex->m_method ); + method_get_exc_handler_number( ctx->m_method ); for( unsigned short handler_index = 0; handler_index < handler_count; handler_index++ ) { - VERIFY_DEBUG( handler_index + - 1 << " [-]: -> HANDLER #" << handler_index + 1 ); + VF_DEBUG( handler_index + + 1 << " [-]: -> HANDLER #" << handler_index + 1 ); unsigned short start_pc, end_pc, handler_pc, handler_cp_index; - method_get_exc_handler_info( ctex->m_method, + method_get_exc_handler_info( ctx->m_method, handler_index, &start_pc, &end_pc, &handler_pc, &handler_cp_index ); - VERIFY_DEBUG( " from " << ctex->m_bc[start_pc].m_instr + handler_count - << " [" << start_pc << "]" - " to " << ctex->m_bc[end_pc].m_instr + handler_count - << " [" << end_pc << "]" - " --> " << ctex->m_bc[handler_pc].m_instr + - handler_count << " [" << handler_pc << "]" ", CP type " - << handler_cp_index ); + VF_DEBUG( " from " << vf_bc_to_instr_index( start_pc, ctx ) + + handler_count << " [" << start_pc << "]" " to " << + vf_bc_to_instr_index( end_pc, + ctx ) + + handler_count << " [" << end_pc << "]" " --> " << + vf_bc_to_instr_index( handler_pc, + ctx ) + + handler_count << " [" << handler_pc << "]" ", CP type " + << handler_cp_index ); } - unsigned char *bytecode = method_get_bytecode( ctex->m_method ); - unsigned end_code = ctex->m_codeNum + handler_count + 1; - vf_Code_t *code = ctex->m_code; + unsigned char *bytecode = method_get_bytecode( ctx->m_method ); + vf_InstrHandle instr = ctx->m_instr; for( unsigned index = handler_count + 1; - index < end_code; index++, code++ ) { - VERIFY_DEBUG( index - << " [" << code->m_addr - bytecode << "]:" - << ( ( code->m_basic_block_start ) ? " -> " : " " ) - << ( ( code->m_stack < 0 ) ? "" : " " ) - << code->m_stack - << "|" << code->m_minstack << " " - << vf_opcode_names[*( code->m_addr )] ); - for( unsigned count = 0; count < code->m_offcount; count++ ) { - unsigned offset = code->m_off[count]; - VERIFY_DEBUG( " --> " - << ctex->m_bc[offset].m_instr + handler_count - << " [" << offset << "]" ); + instr < ctx->m_last_instr; index++, instr++ ) { + VF_DEBUG( index + << " [" << instr->m_addr - bytecode << "]:" + << ( ( instr->m_basic_block_start ) ? " -> " : " " ) + << ( ( instr->m_stack < 0 ) ? "" : " " ) + << instr->m_stack + << "|" << instr->m_minstack << " " + << vf_opcode_names[*( instr->m_addr )] ); + for( unsigned count = 0; count < instr->m_offcount; count++ ) { + unsigned offset = instr->m_off[count]; + VF_DEBUG( " --> " + << vf_bc_to_instr_index( offset, + ctx ) + + handler_count << " [" << offset << "]" ); } } - VERIFY_DEBUG( end_code << " [-]: -> END-ENTRY" << endl ); - VERIFY_DEBUG + VF_DEBUG( index << " [-]: -> END-ENTRY" << endl ); + VF_DEBUG ( "======================================================================" ); - return; } // vf_dump_bytecode -#endif //_VERIFY_DEBUG +#endif //_VF_DEBUG /** * Function provides initial verification of class. */ -Verifier_Result +vf_Result vf_verify_class( class_handler klass, // verified class unsigned verifyAll, // verification level flag char **message ) // verifier error message { assert( klass ); assert( message ); -#if VERIFY_CLASS +#if VF_CLASS if( strcmp( class_get_name( klass ), "" ) ) { return VER_OK; } -#endif // VERIFY_CLASS +#endif // VF_CLASS - VERIFY_TRACE( "class.bytecode", - "verify class: " << class_get_name( klass ) ); + VF_TRACE( "class.bytecode", "verify class: " << class_get_name( klass ) ); /** * Create context */ - vf_Context_t context; + vf_Context ctx; /** * Set current class */ - context.m_class = klass; + ctx.m_class = klass; /** * Create type pool */ - context.m_type = new vf_TypePool(); + ctx.m_type = new vf_TypePool(); /** * Create memory pool */ - context.m_pool = vf_create_pool(); + ctx.m_pool = vf_create_pool(); /** * Set valid types @@ -5361,49 +5042,45 @@ vf_verify_class( class_handler klass, memcpy( &type_name[1], class_name, class_name_len ); type_name[0] = 'L'; type_name[class_name_len + 1] = '\0'; - context.m_vtype.m_class = - context.m_type->NewType( type_name, class_name_len + 1 ); - context.m_vtype.m_throwable = - context.m_type->NewType( "Ljava/lang/Throwable", 20 ); - context.m_vtype.m_object = - context.m_type->NewType( "Ljava/lang/Object", 17 ); - context.m_vtype.m_array = - context.m_type->NewType( "[Ljava/lang/Object", 18 ); - context.m_vtype.m_clone = - context.m_type->NewType( "Ljava/lang/Cloneable", 20 ); - context.m_vtype.m_serialize = - context.m_type->NewType( "Ljava/io/Serializable", 21 ); + ctx.m_vtype.m_class = + ctx.m_type->NewType( type_name, class_name_len + 1 ); + ctx.m_vtype.m_throwable = + ctx.m_type->NewType( "Ljava/lang/Throwable", 20 ); + ctx.m_vtype.m_object = ctx.m_type->NewType( "Ljava/lang/Object", 17 ); + ctx.m_vtype.m_array = ctx.m_type->NewType( "[Ljava/lang/Object", 18 ); + ctx.m_vtype.m_clone = ctx.m_type->NewType( "Ljava/lang/Cloneable", 20 ); + ctx.m_vtype.m_serialize = + ctx.m_type->NewType( "Ljava/io/Serializable", 21 ); /** * Set verification level flag */ - context.m_dump.m_verify = verifyAll ? 1 : 0; + ctx.m_verify_all = verifyAll ? true : false; /** * Verify bytecode of methods */ - Verifier_Result result = VER_OK; + vf_Result result = VER_OK; unsigned short number = class_get_method_number( klass ); for( unsigned short index = 0; index < number; index++ ) { -#if VERIFY_METHOD +#if VF_METHOD if( !strcmp ( method_get_name( class_get_method( klass, index ) ), "" ) ) -#endif // VERIFY_METHOD +#endif // VF_METHOD { /** * Set verified method */ - context.m_method = class_get_method( klass, index ); - //context.m_dump.m_node_vector = 1; - //context.m_dump.m_code_vector = 1; - //context.m_dump.m_merge_vector = 1; - //context.m_dump.m_dot_graph = 1; - result = vf_verify_method_bytecode( &context ); - context.ClearContext(); + ctx.SetMethod( class_get_method( klass, index ) ); + //ctx.m_dump.m_node_vector = 1; + //ctx.m_dump.m_instr_vector = 1; + //ctx.m_dump.m_merge_vector = 1; + //ctx.m_dump.m_dot_graph = 1; + //ctx.m_dump.m_dot_mod_graph = 1; + result = vf_verify_method_bytecode( &ctx ); + ctx.ClearContext(); } - if( result == VER_NoSupportJSR ) { - result = VER_OK; - } else if( result != VER_OK ) { + if( result != VER_OK ) { goto labelEnd_verifyClass; } } @@ -5411,27 +5088,22 @@ vf_verify_class( class_handler klass, /** * Check and set class constraints */ -#if _VERIFY_DEBUG - if( context.m_dump.m_constraint ) { - context.m_type->DumpTypeConstraints( NULL ); + if( vf_is_trace_enabled( DUMP_CONSTRAINT ) ) { + ctx.m_type->DumpTypeConstraints( NULL ); } -#endif // _VERIFY_DEBUG - result = vf_check_class_constraints( &context ); + result = vf_check_class_constraints( &ctx ); if( result != VER_OK ) { goto labelEnd_verifyClass; } labelEnd_verifyClass: - vf_delete_pool( context.m_pool ); - delete context.m_type; - *message = context.m_error; -#if _VERIFY_DEBUG + *message = ctx.m_error; +#if _VF_DEBUG if( result != VER_OK ) { TRACE2( "verifier", - "VerifyError: " << ( context.m_error ? context. - m_error : "NULL" ) ); + "VerifyError: " << ( ctx.m_error ? ctx.m_error : "NULL" ) ); } -#endif // _VERIFY_DEBUG +#endif // _VF_DEBUG return result; } // vf_verify_class diff -pu 9/trunk/working_vm/vm/vmcore/src/verifier/ver_dataflow.cpp 91/trunk/working_vm/vm/vmcore/src/verifier/ver_dataflow.cpp --- 9/trunk/working_vm/vm/vmcore/src/verifier/ver_dataflow.cpp 2007-03-20 18:34:53.092782900 +0300 +++ 91/trunk/working_vm/vm/vmcore/src/verifier/ver_dataflow.cpp 2007-03-21 04:10:18.950673600 +0300 @@ -34,13 +34,13 @@ **************** Graph Data Flow Analysis ****************** ************************************************************/ -#if _VERIFY_DEBUG +#if _VF_DEBUG /** * Function prints stack map entry into output stream. */ static void -vf_dump_vector_entry( vf_MapEntry_t * entry, // stack map entry +vf_dump_vector_entry( vf_MapEntry *entry, // stack map entry ostream *stream ) // output stream { switch ( entry->m_type ) { @@ -81,10 +81,12 @@ vf_dump_vector_entry( vf_MapEntry_t * en case SM_UNINITIALIZED_THIS: *stream << " [THIS]"; break; + case SM_ANY: + *stream << " [ANY ]"; + break; default: *stream << " [? " << entry->m_type << "]"; } - return; } // vf_dump_vector_entry /** @@ -92,7 +94,7 @@ vf_dump_vector_entry( vf_MapEntry_t * en */ void vf_dump_vector( vf_MapVectorHandle vector, // data flow vector - vf_Code_t * code, // code instruction + vf_InstrHandle instr, // code instruction ostream *stream ) // output stream (can be NULL) { unsigned index, count; @@ -102,10 +104,10 @@ vf_dump_vector( vf_MapVectorHandle vecto stream = &cerr; } // dump code instruction if it's needed - if( code != NULL ) { - *stream << ( ( code->m_stack < 0 ) ? "[" : "[ " ) - << code->m_stack << "| " << code->m_minstack << "] " - << vf_opcode_names[*( code->m_addr )] << endl; + if( instr != NULL ) { + *stream << ( ( instr->m_stack < 0 ) ? "[" : "[ " ) + << instr->m_stack << "| " << instr->m_minstack << "] " + << vf_opcode_names[*( instr->m_addr )] << endl; } // dump locals vector *stream << "L:"; @@ -133,7 +135,7 @@ vf_dump_vector( vf_MapVectorHandle vecto continue; } if( vector->m_local[index].m_vtype ) { - vf_ValidType_t *type = vector->m_local[index].m_vtype; + vf_ValidType *type = vector->m_local[index].m_vtype; *stream << type; for( count = 0; count < type->number; count++ ) { *stream << " " << type->string[count]; @@ -169,7 +171,7 @@ vf_dump_vector( vf_MapVectorHandle vecto continue; } if( vector->m_stack[index].m_vtype ) { - vf_ValidType_t *type = vector->m_stack[index].m_vtype; + vf_ValidType *type = vector->m_stack[index].m_vtype; *stream << type; for( count = 0; count < type->number; count++ ) { *stream << " " << type->string[count]; @@ -179,17 +181,16 @@ vf_dump_vector( vf_MapVectorHandle vecto } *stream << endl; } - return; } // vf_dump_vector -#endif // _VERIFY_DEBUG +#endif // _VF_DEBUG /** * Function compares two valid types. */ bool -vf_is_types_equal( vf_ValidType_t * type1, // first checked type - vf_ValidType_t * type2 ) // second checked type +vf_is_types_equal( vf_ValidType *type1, // first checked type + vf_ValidType *type2 ) // second checked type { if( type1 == type2 ) { return true; @@ -214,14 +215,10 @@ static inline bool vf_merge_vectors( vf_MapVector *first, // first vector vf_MapVectorHandle second, // second vector bool handler_flag, // if merged node is handler - vf_Context_t * ctex ) // verifier context + vf_ContextHandle ctx ) // verification context { bool is_changed = false; - vf_MapEntry_t zero = { 0 }; - - // check vectors parameters - assert( first->m_maxlocal == second->m_maxlocal ); - assert( first->m_maxstack == second->m_maxstack ); + vf_MapEntry zero = { 0 }; // merge local variable vector unsigned index; @@ -240,9 +237,9 @@ vf_merge_vectors( vf_MapVector *first, is_changed = true; } else if( first->m_local[index].m_type == SM_REF ) { // reference types, merge them - vf_ValidType_t *type = - ctex->m_type->MergeTypes( first->m_local[index].m_vtype, - second->m_local[index].m_vtype ); + vf_ValidType *type = + ctx->m_type->MergeTypes( first->m_local[index].m_vtype, + second->m_local[index].m_vtype ); if( type ) { // set merged type first->m_local[index].m_vtype = type; @@ -250,9 +247,9 @@ vf_merge_vectors( vf_MapVector *first, } } else if( first->m_local[index].m_type == SM_UNINITIALIZED ) { // reference types, merge them - vf_ValidType_t *type = - ctex->m_type->MergeTypes( first->m_local[index].m_vtype, - second->m_local[index].m_vtype ); + vf_ValidType *type = + ctx->m_type->MergeTypes( first->m_local[index].m_vtype, + second->m_local[index].m_vtype ); if( type || first->m_local[index].m_new != second->m_local[index].m_new ) { @@ -297,9 +294,9 @@ vf_merge_vectors( vf_MapVector *first, is_changed = true; } else if( first->m_stack[index].m_type == SM_REF ) { // reference types, merge them - vf_ValidType_t *type = - ctex->m_type->MergeTypes( first->m_stack[index].m_vtype, - second->m_stack[index].m_vtype ); + vf_ValidType *type = + ctx->m_type->MergeTypes( first->m_stack[index].m_vtype, + second->m_stack[index].m_vtype ); if( type ) { // set merged type first->m_stack[index].m_vtype = type; @@ -307,9 +304,9 @@ vf_merge_vectors( vf_MapVector *first, } } else if( first->m_stack[index].m_type == SM_UNINITIALIZED ) { // reference types, merge them - vf_ValidType_t *type = - ctex->m_type->MergeTypes( first->m_stack[index].m_vtype, - second->m_stack[index].m_vtype ); + vf_ValidType *type = + ctx->m_type->MergeTypes( first->m_stack[index].m_vtype, + second->m_stack[index].m_vtype ); if( type || first->m_stack[index].m_new != second->m_stack[index].m_new ) { @@ -323,37 +320,6 @@ vf_merge_vectors( vf_MapVector *first, } // vf_merge_vectors /** - * Function copies source vector to data vector. - */ -static inline void -vf_copy_vector( vf_MapVectorHandle source, // copied vector - vf_MapVector *data ) // data vector -{ - unsigned index; - vf_MapEntry_t zero = { 0 }; - - assert( source->m_maxlocal <= data->m_maxlocal ); - assert( source->m_maxstack <= data->m_maxstack ); - // copy locals - data->m_number = source->m_number; - for( index = 0; index < source->m_number; index++ ) { - data->m_local[index] = source->m_local[index]; - } - for( ; index < data->m_maxlocal; index++ ) { - data->m_local[index] = zero; - } - // copy stack - data->m_depth = source->m_depth; - for( index = 0; index < source->m_depth; index++ ) { - data->m_stack[index] = source->m_stack[index]; - } - for( ; index < data->m_maxstack; index++ ) { - data->m_stack[index] = zero; - } - return; -} // vf_copy_vector - -/** * Function compares two vectors. */ static inline bool @@ -361,9 +327,7 @@ vf_compare_vectors( vf_MapVectorHandle f vf_MapVectorHandle second ) // second vector { // compare vector parameters - if( first->m_maxlocal != second->m_maxlocal - || first->m_maxstack != second->m_maxstack - || first->m_number != second->m_number + if( first->m_number != second->m_number || first->m_depth != second->m_depth ) { return false; } @@ -393,40 +357,40 @@ vf_compare_vectors( vf_MapVectorHandle f /** * Function check access constraint for two stack map references. */ -static inline Verifier_Result -vf_check_access( vf_MapEntry_t * source, // stack map entry - vf_MapEntry_t * target, // required map entry - vf_Context_t * ctex ) // verifier context +static inline vf_Result +vf_check_access( vf_MapEntry *source, // stack map entry + vf_MapEntry *target, // required map entry + vf_Context *ctx ) // verification context { // compare types assert( target->m_vtype->number == 1 ); - vf_CheckConstraint_t check = ( target->m_ctype == VF_CHECK_ACCESS_FIELD ) + vf_CheckConstraint check = ( target->m_ctype == VF_CHECK_ACCESS_FIELD ) ? VF_CHECK_ASSIGN : VF_CHECK_PARAM; for( unsigned index = 0; index < source->m_vtype->number; index++ ) { // set constraints for differing types if( target->m_vtype->string[0] != source->m_vtype->string[index] ) { - ctex->m_type->SetRestriction( target->m_vtype->string[0], - source->m_vtype->string[index], 0, - check ); + ctx->m_type->SetRestriction( target->m_vtype->string[0], + source->m_vtype->string[index], 0, + check ); } // set access constraints for differing types - if( ctex->m_vtype.m_class->string[0] != + if( ctx->m_vtype.m_class->string[0] != source->m_vtype->string[index] ) { // not the same class - Verifier_Result result = + vf_Result result = vf_check_access_constraint( target->m_vtype->string[0], source->m_vtype->string[index], target->m_index, - ( vf_CheckConstraint_t ) target-> - m_ctype, ctex ); + ( vf_CheckConstraint ) + target->m_ctype, + ctx ); if( result == VER_ClassNotLoaded ) { // cannot complete check, set restriction - ctex->m_type->SetRestriction( ctex->m_vtype.m_class-> - string[0], - source->m_vtype->string[index], - 0, - ( vf_CheckConstraint_t ) - target->m_ctype ); + ctx->m_type->SetRestriction( ctx->m_vtype.m_class-> + string[0], + source->m_vtype->string[index], + 0, ( vf_CheckConstraint ) + target->m_ctype ); } else if( result != VER_OK ) { // return error return result; @@ -439,26 +403,40 @@ vf_check_access( vf_MapEntry_t * source, /** * Function checks two stack map references. */ -static inline Verifier_Result -vf_check_entry_refs( vf_MapEntry_t * source, // stack map entry - vf_MapEntry_t * target, // required map entry +static inline vf_Result +vf_check_entry_refs( vf_MapEntry *source, // stack map entry + vf_MapEntry *target, // required map entry bool local_init, // initialization flag of locals - vf_Context_t * ctex ) // verifier context + vf_Context *ctx ) // verification context { - // check entries type - if( !( source->m_type == SM_REF || source->m_type == SM_UNINITIALIZED ) - || !( target->m_type == SM_REF - || target->m_type == SM_UNINITIALIZED ) ) { - return VER_ErrorDataFlow; - } // check local variable type if( source->m_is_local && ( !target->m_is_local || source->m_local != target->m_local ) ) { return VER_ErrorDataFlow; } + // check entries type + if( !( SM_REF == source->m_type || SM_UNINITIALIZED == source->m_type ) + || !( SM_REF == target->m_type + || SM_UNINITIALIZED == target->m_type ) ) { + if( SM_ANY == source->m_type ) { + return VER_OK; + } + // only aload and astore get SM_REF/VF_CHECK_UNINITIALIZED_THIS + if( SM_RETURN_ADDR == source->m_type + && VF_CHECK_UNINITIALIZED_THIS == target->m_ctype ) { + if( source->m_is_local ) { + // aload a return address + return VER_ErrorJsrLoadRetAddr; + } else { + // astore a return address + return VER_OK; + } + } + return VER_ErrorDataFlow; + } // check available entry if( source->m_vtype == NULL ) { - // nothing checks + // nothing to check return VER_OK; } // check initialization @@ -467,7 +445,7 @@ vf_check_entry_refs( vf_MapEntry_t * sou if( ( source->m_new == 0 && target->m_ctype == VF_CHECK_ACCESS_FIELD ) || ( local_init == false && target->m_ctype == VF_CHECK_UNINITIALIZED_THIS ) - || ( !ctex->m_dump.m_verify && source->m_new == 0 + || ( !ctx->m_verify_all && source->m_new == 0 && target->m_ctype == VF_CHECK_UNINITIALIZED_THIS ) ) { // 1. In initialization method instance fields of this // that are declared in the current class may be assigned @@ -480,7 +458,7 @@ vf_check_entry_refs( vf_MapEntry_t * sou // can be stored in a local variable if backward branch is // taken or the code is protected by exception handler. } else { - VERIFY_REPORT_METHOD( ctex, "Uninitialized reference usage" ); + VF_REPORT( ctx, "Uninitialized reference usage" ); return VER_ErrorDataFlow; } } @@ -491,50 +469,52 @@ vf_check_entry_refs( vf_MapEntry_t * sou case VF_CHECK_UNINITIALIZED_THIS: case VF_CHECK_PARAM: // check method invocation conversion if( target->m_vtype != NULL ) { - is_error = ctex->m_type->CheckTypes( target->m_vtype, - source->m_vtype, 0, - VF_CHECK_PARAM ); + is_error = ctx->m_type->CheckTypes( target->m_vtype, + source->m_vtype, 0, + VF_CHECK_PARAM ); } break; case VF_CHECK_ARRAY: // check if source reference is array is_error = - ctex->m_type->CheckTypes( NULL, source->m_vtype, 0, - VF_CHECK_ARRAY ); + ctx->m_type->CheckTypes( NULL, source->m_vtype, 0, + VF_CHECK_ARRAY ); break; case VF_CHECK_REF_ARRAY: is_error = - ctex->m_type->CheckTypes( NULL, source->m_vtype, 0, - VF_CHECK_REF_ARRAY ); + ctx->m_type->CheckTypes( NULL, source->m_vtype, 0, + VF_CHECK_REF_ARRAY ); break; case VF_CHECK_EQUAL: // check if references are equal - is_error = ctex->m_type->CheckTypes( target->m_vtype, - source->m_vtype, 0, - VF_CHECK_EQUAL ); + is_error = ctx->m_type->CheckTypes( target->m_vtype, + source->m_vtype, 0, + VF_CHECK_EQUAL ); break; case VF_CHECK_ASSIGN: // check assignment conversion case VF_CHECK_ASSIGN_WEAK: // check weak assignment conversion assert( target->m_vtype != NULL ); - is_error = ctex->m_type->CheckTypes( target->m_vtype, - source->m_vtype, 0, - ( vf_CheckConstraint_t ) target-> - m_ctype ); + is_error = ctx->m_type->CheckTypes( target->m_vtype, + source->m_vtype, 0, + ( vf_CheckConstraint ) target-> + m_ctype ); break; case VF_CHECK_ACCESS_FIELD: // check field access case VF_CHECK_ACCESS_METHOD: // check method access { assert( target->m_vtype != NULL ); // not null reference assert( target->m_local != 0 ); // constant pool index is set - Verifier_Result result = vf_check_access( source, target, ctex ); + vf_Result result = vf_check_access( source, target, ctx ); return result; } break; case VF_CHECK_DIRECT_SUPER: // check is target class is direct super class of source - is_error = ctex->m_type->CheckTypes( target->m_vtype, source->m_vtype, - 0, VF_CHECK_DIRECT_SUPER ); + is_error = + ctx->m_type->CheckTypes( target->m_vtype, source->m_vtype, 0, + VF_CHECK_DIRECT_SUPER ); break; case VF_CHECK_INVOKESPECIAL: // check invokespecial object reference - is_error = ctex->m_type->CheckTypes( target->m_vtype, source->m_vtype, - 0, VF_CHECK_INVOKESPECIAL ); + is_error = + ctx->m_type->CheckTypes( target->m_vtype, source->m_vtype, 0, + VF_CHECK_INVOKESPECIAL ); break; default: LDIE( 38, "Verifier: vf_check_entry_refs: unknown check in switch" ); @@ -550,22 +530,30 @@ vf_check_entry_refs( vf_MapEntry_t * sou /** * Function checks two stack map entries. */ -static inline Verifier_Result -vf_check_entry_types( vf_MapEntry_t * entry1, // stack map entry - vf_MapEntry_t * entry2, // required map entry +static inline vf_Result +vf_check_entry_types( vf_MapEntry *entry1, // stack map entry + vf_MapEntry *entry2, // required map entry bool local_init, // initialization flag of locals bool *need_copy, // pointer to copy flag - vf_Context_t * ctex ) // verifier context + vf_Context *ctx ) // verification context { + if( SM_ANY == entry1->m_type ) { + return VER_OK; + } switch ( entry2->m_type ) { case SM_REF: // check reference entries { - Verifier_Result result = - vf_check_entry_refs( entry1, entry2, local_init, ctex ); + vf_Result result = + vf_check_entry_refs( entry1, entry2, local_init, ctx ); *need_copy = true; return result; } + case SM_RETURN_ADDR: + if( entry1->m_type != entry2->m_type ) { + return VER_ErrorDataFlow; + } + *need_copy = true; break; case SM_TOP: case SM_INT: @@ -617,34 +605,33 @@ vf_check_entry_types( vf_MapEntry_t * en * Function creates array element valid type. */ static inline void -vf_set_array_element_type( vf_MapEntry_t * buf, // result data flow vector entry - vf_MapEntry_t * vector, // data flow vector entry - vf_MapEntry_t * array, // array data flow vector entry - vf_Context_t * ctex ) // verifier context +vf_set_array_element_type( vf_MapEntry *buf, // result data flow vector entry + vf_MapEntry *vector, // data flow vector entry + vf_MapEntry *array, // array data flow vector entry + vf_ContextHandle ctx ) // verification context { - assert( array->m_type == SM_REF ); + assert( SM_REF == array->m_type || SM_ANY == array->m_type ); buf->m_type = array->m_type; buf->m_vtype = array->m_vtype; buf->m_local = vector->m_local; buf->m_is_local = vector->m_is_local; if( buf->m_vtype ) { // create cell array type - buf->m_vtype = ctex->m_type->NewArrayElemType( buf->m_vtype ); + buf->m_vtype = ctx->m_type->NewArrayElemType( buf->m_vtype ); } - return; } // vf_set_array_element_type /** * Function receives IN data flow vector entry for code instruction. */ -static inline vf_MapEntry_t * -vf_set_new_in_vector( vf_Code_t * code, // code instruction - vf_MapEntry_t * vector, // data flow vector entry - vf_MapEntry_t * stack_buf, // stack map vector - vf_Context_t * ctex ) // verifier context +static inline vf_MapEntry * +vf_set_new_in_vector( vf_InstrHandle instr, // code instruction + vf_MapEntry *vector, // data flow vector entry + vf_ContextHandle ctx ) // verification context { short number; - vf_MapEntry_t *newvector; + vf_MapEntry *stack_buf = ctx->m_buf; + vf_MapEntry *newvector; switch ( vector->m_type ) { case SM_COPY_0: @@ -653,12 +640,12 @@ vf_set_new_in_vector( vf_Code_t * code, case SM_COPY_3: // it's a copy type, copy value from IN vector number = ( short )( vector->m_type - SM_COPY_0 ); - assert( number < code->m_inlen ); - newvector = &code->m_invector[number]; + assert( number < instr->m_inlen ); + newvector = &instr->m_invector[number]; if( newvector->m_type == SM_TOP || newvector->m_type >= SM_WORD - || ( newvector->m_type == SM_REF && newvector->m_vtype == NULL ) ) - { + || ( newvector->m_type == SM_REF + && newvector->m_vtype == NULL ) ) { // copy value from saved stack entry newvector = &stack_buf[number]; newvector->m_local = vector->m_local; @@ -668,7 +655,7 @@ vf_set_new_in_vector( vf_Code_t * code, case SM_UP_ARRAY: // set reference array element newvector = &stack_buf[0]; - vf_set_array_element_type( newvector, vector, &stack_buf[0], ctex ); + vf_set_array_element_type( newvector, vector, &stack_buf[0], ctx ); break; default: newvector = vector; @@ -681,22 +668,20 @@ vf_set_new_in_vector( vf_Code_t * code, * Function sets OUT data flow vector for code instruction. */ static inline void -vf_set_instruction_out_vector( vf_Code_t * code, // code instruction - vf_MapEntry_t * stack, // stack map vector - vf_MapEntry_t * locals, // local variable vector +vf_set_instruction_out_vector( vf_InstrHandle instr, // code instruction + vf_MapEntry *stack, // stack map vector + vf_MapEntry *locals, // local variable vector unsigned short *number, // pointer to local variables number - vf_MapEntry_t * buf, // memory buf array - vf_Context_t * ctex ) // verifier context + vf_ContextHandle ctx ) // verification context { unsigned index; - vf_MapEntry_t *entry, *vector; + vf_MapEntry *entry, *vector; // set instruction out vector - for( index = 0, vector = code->m_outvector; - index < code->m_outlen; - index++, vector = &code->m_outvector[index] ) { - vf_MapEntry_t *newvector = - vf_set_new_in_vector( code, vector, buf, ctex ); + for( index = 0, vector = instr->m_outvector; + index < instr->m_outlen; + index++, vector = &instr->m_outvector[index] ) { + vf_MapEntry *newvector = vf_set_new_in_vector( instr, vector, ctx ); if( newvector->m_is_local ) { // get local variable entry = locals + newvector->m_local; @@ -716,7 +701,6 @@ vf_set_instruction_out_vector( vf_Code_t entry->m_new = newvector->m_new; entry->m_vtype = newvector->m_vtype; } - return; } // vf_set_instruction_out_vector /** @@ -725,7 +709,7 @@ vf_set_instruction_out_vector( vf_Code_t static inline void vf_clear_stack( vf_MapVector *vector ) // map vector { - vf_MapEntry_t zero_entry = { 0 }; + vf_MapEntry zero_entry = { 0 }; // zero stack vector for( unsigned index = 0; index < vector->m_depth; index++ ) { @@ -733,21 +717,20 @@ vf_clear_stack( vf_MapVector *vector ) } vector->m_depth = 0; - return; } // vf_clear_stack /** * Function sets stack map vector for return instructions. */ static inline void -vf_set_return_out_vector( vf_MapEntry_t * stack, // stack map vector - vf_MapEntry_t * buf, // stored values vector - vf_MapEntry_t * invector, // IN data flow vector +vf_set_return_out_vector( vf_MapEntry *stack, // stack map vector + vf_MapEntry *buf, // stored values vector + vf_MapEntry *invector, // IN data flow vector unsigned len, // IN vector length - vf_Context_t * UNREF ctex ) // verifier context + vf_Context *UNREF ctx ) // verification context { unsigned index; - vf_MapEntry_t *entry; + vf_MapEntry *entry; // set return instruction out vector for( index = 0, entry = invector; @@ -759,25 +742,24 @@ vf_set_return_out_vector( vf_MapEntry_t stack[index].m_type = entry->m_type; } } - return; } // vf_set_return_out_vector /** * Function checks data flow for code instruction. */ -static inline Verifier_Result -vf_check_instruction_in_vector( vf_MapEntry_t * stack, // stack map vector - vf_MapEntry_t * locals, // local variable vector - vf_MapEntry_t * buf, // buf storage vector - vf_MapEntry_t * invector, // code instruction IN vector +static inline vf_Result +vf_check_instruction_in_vector( vf_MapEntry *stack, // stack map vector + vf_MapEntry *locals, // local variable vector + vf_MapEntry *buf, // buf storage vector + vf_MapEntry *invector, // code instruction IN vector unsigned len, // IN vector length bool local_init, // initialization flag of locals bool *need_init, // init uninitialized entry - vf_Context_t * ctex ) // verifier context + vf_Context *ctx ) // verification context { unsigned index; - vf_MapEntry_t *entry, *vector, *newvector; - Verifier_Result result; + vf_MapEntry *entry, *vector, *newvector; + vf_Result result; // check IN vector entries for( index = 0, vector = invector; @@ -796,27 +778,32 @@ vf_check_instruction_in_vector( vf_MapEn assert( index > 0 ); newvector = &buf[index]; // check assignment conversion - vf_set_array_element_type( newvector, vector, &buf[0], ctex ); + vf_set_array_element_type( newvector, vector, &buf[0], ctx ); if( newvector->m_vtype ) { newvector->m_ctype = VF_CHECK_ASSIGN_WEAK; + } else if( SM_ANY == newvector->m_type ) { + break; // anything can be assigned to such array } else { newvector->m_ctype = VF_CHECK_NONE; } // check entry types - result = - vf_check_entry_refs( entry, newvector, local_init, ctex ); + result = vf_check_entry_refs( entry, newvector, local_init, ctx ); if( result != VER_OK ) { - VERIFY_REPORT_METHOD( ctex, - "Incompatible types for array assignment" ); + VF_REPORT( ctx, "Incompatible types for array assignment" ); return result; } break; case SM_REF: // check entry references - result = vf_check_entry_refs( entry, vector, local_init, ctex ); + result = vf_check_entry_refs( entry, vector, local_init, ctx ); if( result != VER_OK ) { - if( !ctex->m_error ) { - VERIFY_REPORT_METHOD( ctex, "Data flow analysis error" ); + if( VER_ErrorJsrLoadRetAddr == result ) { + VF_REPORT( ctx, + "Cannot load a return address from a local variable " + << entry->m_local ); + } + if( !ctx->m_error ) { + VF_REPORT( ctx, "Data flow analysis error" ); } return result; } @@ -826,14 +813,12 @@ vf_check_instruction_in_vector( vf_MapEn // check entry references if( entry->m_type == SM_REF ) { // double initialization - VERIFY_REPORT_METHOD( ctex, - "Double initialization of object reference" ); + VF_REPORT( ctx, "Double initialization of object reference" ); return VER_ErrorDataFlow; } - result = vf_check_entry_refs( entry, vector, local_init, ctex ); + result = vf_check_entry_refs( entry, vector, local_init, ctx ); if( result != VER_OK ) { - VERIFY_REPORT_METHOD( ctex, - "Data flow analysis error (uninitialized)" ); + VF_REPORT( ctx, "Data flow analysis error (uninitialized)" ); return result; } // check initialization class in constructor @@ -841,9 +826,10 @@ vf_check_instruction_in_vector( vf_MapEn // initialization of this reference in class construction assert( entry->m_vtype->number == 1 ); if( vector->m_vtype->string[0] != entry->m_vtype->string[0] ) { - ctex->m_type->SetRestriction( vector->m_vtype->string[0], - entry->m_vtype->string[0], - 0, VF_CHECK_DIRECT_SUPER ); + ctx->m_type->SetRestriction( vector->m_vtype-> + string[0], + entry->m_vtype->string[0], 0, + VF_CHECK_DIRECT_SUPER ); } } *need_init = true; @@ -852,10 +838,9 @@ vf_check_instruction_in_vector( vf_MapEn default: // check entry types result = - vf_check_entry_types( entry, vector, local_init, ©, - ctex ); + vf_check_entry_types( entry, vector, local_init, ©, ctx ); if( result != VER_OK ) { - VERIFY_REPORT_METHOD( ctex, "Data flow analysis error" ); + VF_REPORT( ctx, "Data flow analysis error" ); return result; } } @@ -872,45 +857,44 @@ vf_check_instruction_in_vector( vf_MapEn /** * Function receives code instruction OUT data flow vector. */ -static Verifier_Result -vf_get_instruction_out_vector( unsigned node_num, // graph node - vf_Code_t * instr, // code instruction +static vf_Result +vf_get_instruction_out_vector( vf_NodeHandle node, // graph node + vf_InstrHandle instr, // code instruction vf_MapVector *invector, // incoming data flow vector - vf_MapEntry_t * buf, // buf storage vector - vf_Context_t * ctex ) // verifier context + vf_Context *ctx ) // verification context { unsigned index; bool need_init = false; - vf_MapEntry_t zero_entry = { 0 }; + vf_MapEntry *buf = ctx->m_buf; + vf_MapEntry zero_entry = { 0 }; // set stack vector assert( invector->m_depth - instr->m_minstack >= 0 ); - vf_MapEntry_t *stack = + vf_MapEntry *stack = invector->m_stack + invector->m_depth - instr->m_minstack; // set locals vector - vf_MapEntry_t *locals = invector->m_local; + vf_MapEntry *locals = invector->m_local; // check instruction in vector - Verifier_Result result = - vf_check_instruction_in_vector( stack, locals, buf, - instr->m_invector, instr->m_inlen, - ctex->m_graph-> - GetNodeInitFlag( node_num ), - &need_init, ctex ); + vf_Result result = vf_check_instruction_in_vector( stack, locals, buf, + instr->m_invector, + instr->m_inlen, + node->m_initialized, + &need_init, ctx ); if( result != VER_OK ) { return result; } // create out vector for return instructions - if( VF_TYPE_INSTR_RETURN == instr->m_type ) { + if( VF_INSTR_RETURN == instr->m_type ) { // clear stack - unsigned deep = invector->m_depth; + unsigned depth = invector->m_depth; vf_clear_stack( invector ); // set result vector stack deep - invector->m_depth = ( unsigned short )( deep + instr->m_stack ); + invector->m_depth = ( unsigned short )( depth + instr->m_stack ); // set out vector - vf_set_return_out_vector( invector->m_stack, buf, instr->m_invector, - instr->m_inlen, ctex ); + vf_set_return_out_vector( invector->m_stack, buf, + instr->m_invector, instr->m_inlen, ctx ); return VER_OK; - } else if( VF_TYPE_INSTR_THROW == instr->m_type ) { + } else if( VF_INSTR_THROW == instr->m_type ) { invector->m_stack->m_type = SM_TERMINATE; return VER_OK; } @@ -942,13 +926,14 @@ vf_get_instruction_out_vector( unsigned } } // set instruction OUT vector + vf_GraphHandle graph = ctx->m_graph; invector->m_depth = ( unsigned short )( invector->m_depth + instr->m_stack ); - assert( invector->m_depth <= invector->m_maxstack ); + assert( invector->m_depth <= ctx->m_maxstack ); index = invector->m_number; vf_set_instruction_out_vector( instr, stack, locals, &invector->m_number, - buf, ctex ); - assert( invector->m_number <= invector->m_maxlocal ); + ctx ); + assert( invector->m_number <= ctx->m_maxlocal ); // set local variable numbers for( ; index < invector->m_number; index++ ) { if( !locals[index].m_is_local ) { @@ -963,7 +948,7 @@ vf_get_instruction_out_vector( unsigned /** * Copies a stored handler vector to the out vector. */ -static inline Verifier_Result +static inline vf_Result vf_get_handler_out_vector( vf_MapVector *invector, // IN handler vector vf_MapVectorHandle handler_vector ) // stored handler vector { @@ -986,147 +971,154 @@ vf_get_handler_out_vector( vf_MapVector /** * Function sets graph node OUT data flow vector. */ -static Verifier_Result -vf_set_node_out_vector( unsigned node_num, // graph node number +vf_Result +vf_set_node_out_vector( vf_NodeHandle node, // a graph node vf_MapVector *invector, // incoming data flow vector - vf_MapEntry_t * buf, // buf stack map vector - vf_Context_t * ctex ) // verifier context + vf_Context *ctx ) // verification context { - Verifier_Result result; + vf_Result result; // get node instruction number - vf_Graph *graph = ctex->m_graph; - vf_NodeHandle node = graph->GetNode( node_num ); + vf_Graph *graph = ctx->m_graph; /** * For start-entry node doesn't need to check data flow */ - if( VF_TYPE_NODE_START_ENTRY == node->m_type ) { + if( VF_NODE_START_ENTRY == node->m_type ) { return VER_OK; } - if( VF_TYPE_NODE_HANDLER == node->m_type ) { + if( VF_NODE_HANDLER == node->m_type ) { // set OUT vector for a handler node - return vf_get_handler_out_vector( invector, &node->m_outMapVector ); + return vf_get_handler_out_vector( invector, &node->m_outmap ); } // get first instruction - vf_Code_t *instr = &ctex->m_code[graph->GetNodeFirstInstr( node_num )]; - unsigned instruction = graph->GetNodeLastInstr( node_num ) - - graph->GetNodeFirstInstr( node_num ) + 1; + vf_InstrHandle instr = node->m_start; + unsigned instruction = node->m_end - node->m_start + 1; // set out vector for each instruction for( unsigned index = 0; index < instruction; index++ ) { if( ( 0 == instr[index].m_inlen + instr[index].m_outlen ) - && ( VF_TYPE_INSTR_NONE == instr[index].m_type ) ) { + && ( VF_INSTR_NONE == instr[index].m_type ) ) { continue; } else { - result = vf_get_instruction_out_vector( node_num, &instr[index], - invector, buf, ctex ); + result = vf_get_instruction_out_vector( node, &instr[index], + invector, ctx ); } if( result != VER_OK ) { return result; } -#if _VERIFY_DEBUG - if( ctex->m_dump.m_code_vector ) { + if( vf_is_trace_enabled( DUMP_INSTR_MAP ) ) { // dump instruction OUT vector cerr << "-------------- instruction #" << index << " out: " << endl; vf_dump_vector( invector, &instr[index], &cerr ); } -#endif // _VERIFY_DEBUG } return VER_OK; } // vf_set_node_out_vector +struct vf_MapMark +{ + bool in_set:1; + bool out_set:1; + bool out_updated:1; +}; + +static inline vf_MapMark * +vf_get_node_mapmark( vf_NodeHandle node ) +{ + assert( sizeof( vf_MapMark ) <= sizeof( node->m_mark ) ); + return (vf_MapMark*) & node->m_mark; +} + /** - * Function creates and sets graph node OUT vector. + * Creates and sets graph node OUT vector. */ -static Verifier_Result -vf_create_node_vectors( unsigned node_num, // graph node number - vf_MapVector *incoming, // vector for instruction data flow change - vf_MapEntry_t * buf, // buf stack map vector - bool *is_out_changed, // pointer to OUT vector change flag - vf_Context_t * ctex ) // verifier context -{ - // copy IN vector to buf - vf_Graph *graph = ctex->m_graph; - vf_copy_vector( graph->GetNodeInVector( node_num ), incoming ); +static vf_Result +vf_create_node_vectors( vf_NodeHandle node, // a graph node + vf_MapVector *incoming, // a vector for instruction data flow change + vf_Context *ctx ) // a verifier context +{ + vf_Graph *graph = ctx->m_graph; + assert( vf_get_node_mapmark( node )->in_set ); + graph->CopyFullVector( &node->m_inmap, incoming ); -#if _VERIFY_DEBUG - if( ctex->m_dump.m_code_vector || ctex->m_dump.m_node_vector ) { +#if _VF_DEBUG + if( vf_is_trace_enabled( DUMP_INSTR_MAP ) + || vf_is_trace_enabled( DUMP_NODE_MAP ) ) { // dump node number - cerr << endl << "-------------- Node #" << node_num << endl; - if( ctex->m_dump.m_node_vector ) { + cerr << endl << "-------------- Node #" << node->m_nodecount << endl; + if( vf_is_trace_enabled( DUMP_NODE_MAP ) ) { // dump in vector cerr << "IN vector :" << endl; vf_dump_vector( incoming, NULL, &cerr ); } } -#endif // _VERIFY_DEBUG +#endif // _VF_DEBUG // calculate OUT node vector - Verifier_Result result = - vf_set_node_out_vector( node_num, incoming, buf, ctex ); + vf_Result result = vf_set_node_out_vector( node, incoming, ctx ); if( result != VER_OK ) { return result; } // set node OUT vector - vf_MapVector *outcoming = - (vf_MapVector*)graph->GetNodeOutVector( node_num ); - if( !outcoming->m_maxlocal || !outcoming->m_maxstack ) { + vf_MapVector *outcoming = (vf_MapVector*)&node->m_outmap; + bool is_out_changed = false; + if( !vf_get_node_mapmark( node )->out_set ) { // create node OUT vector - graph->SetNodeOutVector( node_num, incoming, true ); - outcoming = (vf_MapVector*)graph->GetNodeOutVector( node_num ); - *is_out_changed = true; + vf_get_node_mapmark( node )->out_set = true; + graph->AllocVector( outcoming ); + graph->CopyVector( incoming, outcoming ); + is_out_changed = true; } else if( !vf_compare_vectors( outcoming, incoming ) ) { - // vectors are differ - vf_copy_vector( incoming, outcoming ); - *is_out_changed = true; + // vectors differ + graph->CopyFullVector( incoming, outcoming ); + is_out_changed = true; } -#if _VERIFY_DEBUG - if( ctex->m_dump.m_node_vector ) { +#if _VF_DEBUG + if( vf_is_trace_enabled( DUMP_NODE_MAP ) ) { // dump out vector - cerr << "-------------- Node #" << node_num << endl << "OUT vector :" - << endl; + cerr << "-------------- Node #" << node-> + m_nodecount << endl << "OUT vector :" << endl; vf_dump_vector( outcoming, NULL, &cerr ); } -#endif // _VERIFY_DEBUG +#endif // _VF_DEBUG // check stack modifier - assert( ( int )( ( graph->GetNodeOutVector( node_num )->m_depth - - graph->GetNodeInVector( node_num )->m_depth ) ) - == graph->GetNodeStackModifier( node_num ) ); + assert( ( int )( node->m_outmap.m_depth + - node->m_inmap.m_depth ) == node->m_stack ); - return VER_OK; + return ( is_out_changed ) ? VER_Continue : VER_OK; } // vf_create_node_vectors /** * Checks data flow for an end graph node. */ -static Verifier_Result +static vf_Result vf_check_end_node_data_flow( vf_MapVectorHandle invector, // end node incoming data flow vector - vf_Context_t * ctex ) // verifier context + vf_Context *ctx ) // verification context { // don't need check if( invector->m_stack && invector->m_stack->m_type == SM_TERMINATE ) { return VER_OK; } // check method - if( ctex->m_is_constructor - && ctex->m_vtype.m_class != ctex->m_vtype.m_object ) { + if( ctx->m_is_constructor + && ctx->m_vtype.m_class != ctx->m_vtype.m_object ) { if( invector->m_local->m_type != SM_UNINITIALIZED - && invector->m_local->m_vtype == ctex->m_vtype.m_class ) { + && invector->m_local->m_vtype == ctx->m_vtype.m_class ) { // constructor returns initialized reference of a given class } else { - VERIFY_REPORT_METHOD( ctex, "Constructor must be invoked" ); + VF_REPORT( ctx, "Constructor must be invoked" ); return VER_ErrorDataFlow; } } // get the end entry - vf_NodeHandle node = ctex->m_graph->GetNode( ctex->m_nodeNum - 1 ); + vf_NodeHandle node = ctx->m_graph->GetEndNode(); // check void return - if( 0 == node->m_inMapVector.m_depth ) { + if( 0 == node->m_inmap.m_depth ) { if( invector->m_stack ) { if( invector->m_stack->m_type == SM_TOP ) { // no return value, empty stack - all is ok @@ -1136,30 +1128,30 @@ vf_check_end_node_data_flow( vf_MapVecto // no stack, no return value - all is ok return VER_OK; } - VERIFY_REPORT_METHOD( ctex, "Wrong return type in function" ); + VF_REPORT( ctx, "Wrong return type in function" ); return VER_ErrorDataFlow; } // stack size should be greater or equal than a minimal // stack size which is a number of words to return (0, 1 or 2) - assert( invector->m_depth - node->m_inMapVector.m_depth >= 0 ); + assert( invector->m_depth - node->m_inmap.m_depth >= 0 ); /** * Check end-entry IN vector */ - for( unsigned index = 0; index < node->m_inMapVector.m_depth; index++ ) { + for( unsigned index = 0; index < node->m_inmap.m_depth; index++ ) { // get check entry - vf_MapEntry_t *vector = node->m_inMapVector.m_stack + index; + vf_MapEntry *vector = node->m_inmap.m_stack + index; assert( vector->m_is_local == 0 ); // check stack type - vf_MapEntry_t *entry = invector->m_stack + index; + vf_MapEntry *entry = invector->m_stack + index; // check entry types bool copy; - Verifier_Result result = - vf_check_entry_types( entry, vector, true, ©, ctex ); + vf_Result result = + vf_check_entry_types( entry, vector, true, ©, ctx ); if( result != VER_OK ) { - VERIFY_REPORT_METHOD( ctex, "Wrong return type in function" ); + VF_REPORT( ctx, "Wrong return type in function" ); return result; } } @@ -1169,113 +1161,102 @@ vf_check_end_node_data_flow( vf_MapVecto /** * Function checks data flow for graph node. */ -static Verifier_Result -vf_check_node_data_flow( unsigned node_num, // graph node number - vf_MapVector *incoming, // incoming data flow vector - vf_MapEntry_t * buf, // buf stack map vector +static vf_Result +vf_check_node_data_flow( vf_NodeHandle node, // a graph node unsigned *node_count, // last graph node in recursion bool *need_recheck, // set to true if need to recheck previous nodes - vf_Context_t * ctex ) // verifier context + vf_Context *ctx ) // verification context { // get graph - vf_Graph *graph = ctex->m_graph; + vf_Graph *graph = ctx->m_graph; + vf_MapVector *incoming = ctx->m_map; // incoming data flow vector // skip end-entry node - vf_NodeHandle node = graph->GetNode( node_num ); - if( VF_TYPE_NODE_END_ENTRY == node->m_type ) { + if( VF_NODE_END_ENTRY == node->m_type ) { return VER_OK; } - // set node vectors - bool is_changed = false; - int node_mark = graph->GetNodeMark( node_num ); - if( !node_mark ) { - // node isn't end-entry node, end-entry node no need to check - Verifier_Result result = vf_create_node_vectors( node_num, - incoming, buf, - &is_changed, ctex ); - if( result != VER_OK ) { + + if( !vf_get_node_mapmark( node )->out_updated ) { + vf_Result result = vf_create_node_vectors( node, + incoming, ctx ); + vf_get_node_mapmark( node )->out_updated = true; + if( result != VER_Continue ) { return result; } - graph->SetNodeMark( node_num, VERIFY_START_MARK ); - } - if( !is_changed ) { - /** - * Node OUT vector isn't changed, - * no need change data flow vectors for following out nodes. - */ + } else { return VER_OK; } + // set incoming vector for following nodes - vf_MapVectorHandle in_node_vector = graph->GetNodeOutVector( node_num ); - for( unsigned out_edge = graph->GetNodeFirstOutEdge( node_num ); - out_edge; out_edge = graph->GetEdgeNextOutEdge( out_edge ) ) { + vf_MapVectorHandle innode_vector = &node->m_outmap; + for( vf_EdgeHandle outedge = node->m_outedge; + outedge; outedge = outedge->m_outnext ) { // get in node, mark and enumeration count - unsigned out_node = graph->GetEdgeEndNode( out_edge ); + vf_NodeHandle outnode = outedge->m_end; // check vectors for end-entry - if( VF_TYPE_NODE_END_ENTRY == graph->GetNode( out_node )->m_type ) { - Verifier_Result result = - vf_check_end_node_data_flow( in_node_vector, ctex ); + if( VF_NODE_END_ENTRY == outnode->m_type ) { + vf_Result result = + vf_check_end_node_data_flow( innode_vector, ctx ); if( result != VER_OK ) { return result; } continue; } // get out node IN vector - vf_MapVector *out_node_vector = (vf_MapVector*) - graph->GetNodeInVector( out_node ); - if( !out_node_vector->m_maxlocal || !out_node_vector->m_maxstack ) { + vf_MapVector *outnode_vector = (vf_MapVector*)&outnode->m_inmap; + + if( !vf_get_node_mapmark( outnode )->in_set ) { + vf_get_node_mapmark( outnode )->in_set = true; + graph->AllocVector( outnode_vector ); // node's IN vector is invalid, set it - if( VF_TYPE_NODE_HANDLER == graph->GetNode( out_node )->m_type ) { + if( VF_NODE_HANDLER == outnode->m_type ) { // it's exception node, create IN vector for it - vf_copy_vector( in_node_vector, incoming ); + graph->CopyFullVector( innode_vector, incoming ); vf_clear_stack( incoming ); - graph->SetNodeInVector( out_node, incoming, true ); + graph->CopyVector( incoming, outnode_vector ); } else { // other nodes - graph->SetNodeInVector( out_node, in_node_vector, true ); + graph->CopyVector( innode_vector, outnode_vector ); } } else { -#if _VERIFY_DEBUG - if( ctex->m_dump.m_merge_vector ) { +#if _VF_DEBUG + if( vf_is_trace_enabled( DUMP_MERGE_MAP ) ) { // copy out node IN vector for dump - vf_copy_vector( out_node_vector, incoming ); + graph->CopyFullVector( outnode_vector, incoming ); } -#endif // _VERIFY_DEBUG +#endif // _VF_DEBUG // node's IN vector is valid, merge them - bool is_handler = - VF_TYPE_NODE_HANDLER == graph->GetNode( out_node )->m_type; - is_changed = - vf_merge_vectors( out_node_vector, in_node_vector, is_handler, - ctex ); + bool is_handler = VF_NODE_HANDLER == outnode->m_type; + bool is_changed = vf_merge_vectors( outnode_vector, innode_vector, + is_handler, ctx ); if( is_changed ) { // node IN vector is changed, reset node OUT vector results - graph->SetNodeMark( out_node, 0 ); + vf_get_node_mapmark( outnode )->out_updated = false; // set node for re-verification if it's needed. - unsigned count = graph->GetNodeCountElement( out_node ); + unsigned count = outnode->m_nodecount; if( count <= ( *node_count ) ) { *node_count = count; *need_recheck = true; } } -#if _VERIFY_DEBUG - if( ctex->m_dump.m_merge_vector && is_changed ) { +#if _VF_DEBUG + if( vf_is_trace_enabled( DUMP_MERGE_MAP ) && is_changed ) { // dump out vectors cerr << "============== merge IN vector for Node #" << - out_node << endl; + outnode << endl; cerr << "IN vectors:" << endl; cerr << "1: --------------" << endl; vf_dump_vector( incoming, NULL, &cerr ); cerr << "2: --------------" << endl; - vf_dump_vector( in_node_vector, NULL, &cerr ); + vf_dump_vector( innode_vector, NULL, &cerr ); // dump out vector cerr << "result: --------------" << endl; - vf_dump_vector( out_node_vector, NULL, &cerr ); + vf_dump_vector( outnode_vector, NULL, &cerr ); cerr << "### Recount from " << *node_count - << " (now " << graph-> - GetNodeCountElement( node_num ) << ")" << endl; + << " (now " << node->m_nodecount << ")" << endl; } -#endif // _VERIFY_DEBUG +#endif // _VF_DEBUG } } @@ -1285,39 +1266,25 @@ vf_check_node_data_flow( unsigned node_n /** * Creates input and output stack maps. */ -static vf_MapVectorHandle -vf_create_terminal_maps( vf_Context_t * ctex ) // verifier context +static void +vf_create_terminal_maps( vf_Context *ctx ) // verification context { - vf_MapEntry_t *invector; + vf_MapEntry *invector; + vf_Graph *graph = ctx->m_graph; - // get method values - unsigned locals = method_get_max_local( ctex->m_method ); - unsigned maxstack = method_get_max_stack( ctex->m_method ); // alloc memory for vector structure - vf_MapVector *vector = - (vf_MapVector*)ctex->m_graph-> - AllocMemory( sizeof( vf_MapVector ) ); - - // alloc memory for stack vector - if( maxstack ) { - vector->m_maxstack = ( unsigned short )maxstack; - vector->m_stack = (vf_MapEntry_t*) ctex->m_graph-> - AllocMemory( maxstack * sizeof( vf_MapEntry_t ) ); - } - // alloc memory for locals vector - if( locals ) { - vector->m_maxlocal = ( unsigned short )locals; - vector->m_local = (vf_MapEntry_t*) ctex->m_graph-> - AllocMemory( locals * sizeof( vf_MapEntry_t ) ); - } + vf_Node *start_node = (vf_Node*)graph->GetStartNode(); + vf_MapVector *vector = (vf_MapVector*)&start_node->m_inmap; + graph->AllocVector( vector ); + vf_get_node_mapmark( start_node )->in_set = true; + // get method signature - const char *descr = method_get_descriptor( ctex->m_method ); + const char *descr = method_get_descriptor( ctx->m_method ); // get the end node IN vector vf_MapVector *p_outvector = - (vf_MapVector*)ctex->m_graph->GetNodeInVector( ctex->m_nodeNum - - 1 ); + (vf_MapVector*)&graph->GetEndNode()->m_inmap; // get vectors sizes int inlen, outlen; @@ -1326,22 +1293,18 @@ vf_create_terminal_maps( vf_Context_t * // get method vectors vf_set_description_vector( descr, inlen, 0, outlen, &invector, - &p_outvector->m_stack, ctex ); - - // cache in the context if the method is a constructor - ctex->m_is_constructor = - memcmp( method_get_name( ctex->m_method ), "", 7 ) == 0; + &p_outvector->m_stack, ctx ); // set "this" reference in local variable int start; - if( method_is_static( ctex->m_method ) ) { + if( method_is_static( ctx->m_method ) ) { start = 0; } else { start = 1; // fill "this" entry - const char *name = class_get_name( ctex->m_class ); - vf_ValidType_t *type = vf_create_class_valid_type( name, ctex ); - if( ctex->m_is_constructor ) { + const char *name = class_get_name( ctx->m_class ); + vf_ValidType *type = vf_create_class_valid_type( name, ctx ); + if( ctx->m_is_constructor ) { vector->m_local->m_type = SM_UNINITIALIZED; } else { vector->m_local->m_type = SM_REF; @@ -1361,89 +1324,72 @@ vf_create_terminal_maps( vf_Context_t * } vector->m_number = ( unsigned short )index; - return vector; -} // vf_create_method_begin_vector +} // vf_create_terminal_maps /** * Function enumerates graph nodes by wave numeration. */ void -vf_enumerate_graph_node( vf_Context_t * ctex ) +vf_enumerate_graph_node( vf_ContextHandle ctx ) { // clear graph node marks - vf_Graph *graph = ctex->m_graph; - graph->CleanNodesMark(); + vf_Graph *graph = ctx->m_graph; + graph->CleanNodeMarks(); // set first enumeration node - graph->SetStartCountNode( 0 ); - graph->SetNodeMark( 0, VERIFY_START_MARK ); + vf_Node *start_node = (vf_Node*)graph->GetStartNode(); + graph->SetStartCountNode( start_node ); + start_node->m_mark = VF_START_MARK; // enumerate graph nodes - for( unsigned index = 0; index < graph->GetNodeCount(); index++ ) { + for( unsigned index = 0; index < graph->GetReachableNodeCount(); + index++ ) { // get node by count element - unsigned node_num = graph->GetCountElementNode( index ); - if( node_num == ~0U ) { - // remove dead nodes from enumeration - continue; - } + vf_NodeHandle node = graph->GetReachableNode( index ); + assert( node ); + // get node mark - int mark = graph->GetNodeMark( node_num ); + int mark = node->m_mark; // override all out edges of node - for( unsigned out_edge = graph->GetNodeFirstOutEdge( node_num ); - out_edge; out_edge = graph->GetEdgeNextOutEdge( out_edge ) ) { + for( vf_EdgeHandle outedge = node->m_outedge; + outedge; outedge = outedge->m_outnext ) { // get out node and its mark - unsigned out_node = graph->GetEdgeEndNode( out_edge ); - int out_node_mark = graph->GetNodeMark( out_node ); + vf_Node *outnode = (vf_Node*)outedge->m_end; + int out_node_mark = outnode->m_mark; if( !out_node_mark ) { // it's unnumerated node, enumerate it - graph->SetNextCountNode( out_node ); - graph->SetNodeMark( out_node, mark + 1 ); + graph->AddReachableNode( outnode ); + outnode->m_mark = mark + 1; } } } - return; } // vf_enumerate_graph_node /** * Function provides data flow checks of verifier graph structure. */ -Verifier_Result -vf_check_graph_data_flow( vf_Context_t * ctex ) // verifier context +vf_Result +vf_check_graph_data_flow( vf_Context *ctx ) // verification context { - if( method_get_max_local( ctex->m_method ) + - method_get_max_stack( ctex->m_method ) == 0 ) { - // nothing verify - return VER_OK; - } // enumerate graph - vf_enumerate_graph_node( ctex ); - - // get a start vector - vf_MapVector *start = (vf_MapVector*)vf_create_terminal_maps( ctex ); + vf_enumerate_graph_node( ctx ); - // create buf stack map vector (max 4 entry) - vf_MapEntry_t *buf = - (vf_MapEntry_t*) vf_alloc_pool_memory( ctex->m_pool, - sizeof( vf_MapEntry_t ) * - method_get_max_stack( ctex-> - m_method ) ); - - // clean graph mark - vf_Graph *graph = ctex->m_graph; - graph->CleanNodesMark(); + // clean node marks, set a mark bit when IN or OUT node stack maps + // get initialized + vf_Graph *graph = ctx->m_graph; + graph->CleanNodeMarks(); - // set start node IN vector - graph->SetNodeInVector( 0, start, true ); + // set maps for start and end nodes + vf_create_terminal_maps( ctx ); // check graph data flow bool need_recheck = false; unsigned count = 0; do { - unsigned node = graph->GetCountElementNode( count ); - Verifier_Result result = - vf_check_node_data_flow( node, start, buf, &count, &need_recheck, - ctex ); + vf_NodeHandle node = graph->GetReachableNode( count ); + vf_Result result = + vf_check_node_data_flow( node, &count, &need_recheck, ctx ); if( result != VER_OK ) { return result; } @@ -1453,7 +1399,8 @@ vf_check_graph_data_flow( vf_Context_t * } else { need_recheck = false; } - } while( count < graph->GetEnumCount() ); + } + while( count < graph->GetReachableNodeCount() ); return VER_OK; } // vf_check_graph_data_flow diff -pu 9/trunk/working_vm/vm/vmcore/src/verifier/ver_graph.h 91/trunk/working_vm/vm/vmcore/src/verifier/ver_graph.h --- 9/trunk/working_vm/vm/vmcore/src/verifier/ver_graph.h 2007-03-20 18:34:50.478946200 +0300 +++ 91/trunk/working_vm/vm/vmcore/src/verifier/ver_graph.h 2007-03-21 04:10:17.288283200 +0300 @@ -30,70 +30,76 @@ #include "ver_real.h" /** - * Initial node mark in verifier graph. - */ -#define VERIFY_START_MARK 1 - - -/** * Each node has a descriptive bitmap. */ enum vf_NodeType { - VF_TYPE_NODE_CODE_RANGE = 0, - VF_TYPE_NODE_START_ENTRY = 1, - VF_TYPE_NODE_END_ENTRY = 2, - VF_TYPE_NODE_HANDLER = 3 + VF_NODE_CODE_RANGE = 0, + VF_NODE_START_ENTRY = 1, + VF_NODE_END_ENTRY = 2, + VF_NODE_HANDLER = 3 }; +const unsigned TOP_MARK = ~0U; + /** * @ingroup Handles - * The stack map handle vector handle. + * A handle of a stack map vector. */ typedef const struct vf_MapVector *vf_MapVectorHandle; /** * @ingroup Handles - * The handle of the graph node. + * A handle of a graph edge. */ -typedef const struct vf_Node *vf_NodeHandle; +typedef const struct vf_Edge *vf_EdgeHandle; /** * @ingroup Handles - * The handle of the graph edge. + * A handle of a container. */ -typedef const struct vf_Edge *vf_EdgeHandle; -/// Declaration of enum with a descriptive bitmap. -typedef enum vf_NodeType vf_NodeType_t; +typedef const struct vf_Container *vf_ContainerHandle; +/** + * @ingroup Handles + * A subroutine handle. + */ +typedef const struct vf_Sub *vf_SubHandle; /** * Structure of stack map vector. */ struct vf_MapVector { - vf_MapEntry_t *m_stack; ///< stack map vector - vf_MapEntry_t *m_local; ///< locals map vector + vf_MapEntry *m_stack; ///< stack map vector + vf_MapEntry *m_local; ///< locals map vector unsigned short m_number; ///< number of locals unsigned short m_depth; ///< stack depth - unsigned short m_maxstack; ///< max stack length - unsigned short m_maxlocal; ///< max local number }; /** + * Node marks are greater or equal to this, zero mark means + * unmarked node. + */ +const unsigned VF_START_MARK = 1; + +/** * Graph node structure. */ struct vf_Node { - vf_MapVector m_inMapVector; ///< stack map IN node vector - vf_MapVector m_outMapVector; ///< stack map OUT node vector - unsigned m_start; ///< index of the first instruction at vf_Context.m_code - unsigned m_end; ///< index of the last instruction at vf_Context.m_code - unsigned m_inedge; ///< the first incoming edge - unsigned m_outedge; ///< the first outcoming edge + vf_MapVector m_inmap; ///< stack map IN node vector + vf_MapVector m_outmap; ///< stack map OUT node vector + vf_InstrHandle m_start; ///< the first instruction + vf_InstrHandle m_end; ///< the last instruction + vf_EdgeHandle m_inedge; ///< the first incoming edge + vf_EdgeHandle m_outedge; ///< the first outcoming edge unsigned m_innum; ///< number of incoming edges unsigned m_outnum; ///< number of outcoming edges unsigned m_nodecount; ///< node count in enumeration - int m_stack; ///< stack depth + ///< 0 for unreachable and start nodes + int m_stack; ///< stack depth modifier int m_mark; ///< node mark - vf_NodeType_t m_type; ///< node type + vf_SubHandle m_sub; ///< if this is a subroutine node, this refers + ///< to the corresponding subroutine descriptor + vf_NodeType m_type; ///< node type bool m_initialized:1; ///< reference in a local variable ///< should be initialized }; @@ -103,446 +109,538 @@ struct vf_Node */ struct vf_Edge { - unsigned m_start; ///< start edge node - unsigned m_end; ///< end edge node - unsigned m_innext; ///< next incoming edge - unsigned m_outnext; ///< next outcoming edge + vf_NodeHandle m_start; ///< start edge node + vf_NodeHandle m_end; ///< end edge node + vf_EdgeHandle m_innext; ///< next incoming edge + vf_EdgeHandle m_outnext; ///< next outcoming edge }; /** - * Graph node container structure. + * A generic container. */ -struct vf_NodeContainer +struct vf_Container { - vf_NodeContainer *m_next; ///< next container + vf_ContainerHandle m_next; ///< next container unsigned m_max; ///< max number of nodes in container unsigned m_used; ///< number of nodes in container - vf_Node m_node[1]; ///< array of contained nodes }; /** - * Graph edge container structure. + * Locates a container for an object by its number. + * @param[in] container a container to start a search from + * @param[in] n an object number + * @param[out] n an object index in a returned container + * @return a container + */ +static inline vf_ContainerHandle vf_get_container(vf_ContainerHandle + container, unsigned &n) +{ + while (n >= container->m_max) { + n -= container->m_max; + container = container->m_next; + assert(container); + assert(container->m_max); + } + return container; +} + +/** + * Adds a new container to the container list. + * @param[in, out] head the first list element + * @param[in] new_container a new container to be placed at the end of the list + */ +static inline void vf_add_container(vf_ContainerHandle head, + vf_ContainerHandle new_container) +{ + while (head->m_next) { + head = head->m_next; + } + ((vf_Container *) head)->m_next = new_container; +} + + +/** + * Checks amount of used space for given containers. + */ +static inline unsigned vf_used_space(vf_ContainerHandle container) +{ + unsigned used = 0; + + for (; container; container = container->m_next) { + used += container->m_used; + } + return used; +} // vf_used_space + +/** + * Checks amount of pre-allocated space for given containers. + */ +static inline unsigned vf_total_space(vf_ContainerHandle container) +{ + unsigned total_space = 0; + + for (; container; container = container->m_next) { + total_space += container->m_max; + } + return total_space; +} // vf_total_space + + + +/** + * A linked list of containers containing arrays of nodes. + */ +struct vf_NodeContainer +{ + vf_Container container; ///< a container + vf_Node m_node[1]; ///< an array of nodes +}; + +/** + * A linked list of containers containing arrays of edges. */ struct vf_EdgeContainer { - vf_EdgeContainer *m_next; ///< next container - unsigned m_max; ///< max number of edges in container - unsigned m_used; ///< number of edges in container - vf_Edge m_edge[1]; ///< array of contained edges + vf_Container container; ///< a container + vf_Edge m_edge[1]; ///< an array of edges }; /** - * Verifier control flow graph structure. + * An iterator over nodes. */ -class vf_Graph +class vf_Iterator { - public: - /** - * Control flow graph constructor. - * @param node - number of graph nodes - * @param edge - number of graph edges - * @param pool - external memory pool - * @note Function allocates memory for graph structure, nodes and edges. - */ - vf_Graph(unsigned node, unsigned edge, vf_VerifyPool_t * pool) - : m_nodes(NULL), m_edges(NULL), m_pool(pool), m_enum(NULL), - m_nodenum(0), m_edgenum(1), m_enummax(0), m_enumcount(0), - m_free(false) - { - CreateNodes(node); - CreateEdges(edge); - return; - } // vf_Graph + vf_ContainerHandle m_container; ///< a container + unsigned m_index; ///< an index in this container /** - * Control flow graph destructor. - * @note Function release memory for graph structure, nodes and edges. + * Go to the next container. */ - ~vf_Graph() + void SkipContainer() { - if (m_free) { - vf_delete_pool(m_pool); - } - return; - } // ~vf_Graph + m_container = m_container->m_next; + m_index = 0; + } /** - * Function create graph nodes. - * @param count - number of graph nodes - * @note Function allocates memory for graph nodes. + * Advances iterator to the next object. */ - void CreateNodes(unsigned count); - + void Advance() + { + m_index++; + if (m_index < m_container->m_max) { + return; + } + SkipContainer(); + } +public: /** - * Gets a graph node. - * - * @param[in] node_num a node number, should be in range - * @return a handle of the node + * Empty constructor. */ - vf_NodeHandle GetNode(unsigned node_num); + vf_Iterator () + { + } /** - * Gets the first node. - * - * @return a handle of the node + * Creates an iterator for given containers. + * @param[in] container the first container */ - vf_NodeHandle GetFirstNode() + vf_Iterator (vf_ContainerHandle container) { - return GetNode(0); - } // GetFirstNode + Reset(container); + } /** - * Creates a new node of a specific type. - * Node array must have enough free space for a new element. - * - * @param[in] m_type node type - * @param[in] stack a stack modifier (signed value) - * @return a handle of the created node + * Resets an iterator for given containers. + * @param[in] container the first container */ - vf_NodeHandle NewNode(vf_NodeType_t m_type, int stack); + void Reset(vf_ContainerHandle container) + { + m_container = container; + m_index = 0; + } /** - * Creates a new node for a bytecode range. - * Node array must have enough free space for a new element. - * - * @param[in] start an instruction start index - * @param[in] end an instruction end index - * @param[in] stack a stack modifier (signed value) - * @return a handle of the created node + * Gets a current node. */ - vf_NodeHandle NewNode(unsigned start, unsigned end, int stack) + vf_NodeHandle GetNextNode() { - // get node - vf_Node *node = (vf_Node *) NewNode(VF_TYPE_NODE_CODE_RANGE, stack); - node->m_start = start; - node->m_end = end; + vf_NodeHandle node = + ((vf_NodeContainer *) m_container)->m_node + m_index; + Advance(); return node; - } // NewNode( start, end, len ) + } /** - * Gets graph edge. - * Parameter edge_num must be in range. - * - * @param[in] edge_num - edge number - * - * @return The pointer to edge structure. + * @return true if the iterator can be advanced further. */ - vf_EdgeHandle GetEdge(unsigned edge_num); + bool HasMoreElements() const + { + return m_container; + } +}; // vf_Iterator - /** - * Creates a new edge for graph nodes. - * - * @param start_node - start edge node - * @param end_node - end edge node - * @note Edge is set as out edge for start_node and as in edge for end_node. - */ - void NewEdge(unsigned start_node, unsigned end_node); +/** + * Verifier control flow graph structure. + */ +class vf_Graph +{ + vf_NodeContainer *m_nodes; ///< array of nodes + vf_EdgeContainer *m_edges; ///< array of edges + vf_Pool *m_pool; ///< graph memory pool + vf_NodeHandle *m_enum; ///< graph node enumeration + unsigned m_nodenum; ///< number of nodes + unsigned m_edgenum; ///< number of edges + unsigned m_enumcount; ///< number of enumerated elements + vf_NodeHandle m_endnode; ///< control flow end + vf_ContextHandle m_ctx; ///< a verification context + vf_Iterator iterator; ///< an embedded graph iterator + bool m_free; ///< need to free pool /** - * Gets the first code instruction of a node. - * @param node_num the node number - * @return a number of the first code instruction of graph node - * @note Assertion is raised if node_num is not a - * code range node. + * Prints a graph node in stderr. + * @param node a graph node */ - unsigned GetNodeFirstInstr(unsigned node_num) - { - vf_NodeHandle node = GetNode(node_num); - assert(VF_TYPE_NODE_CODE_RANGE == node->m_type); - return node->m_start; - } // GetNodeFirstInstr + void DumpNode(vf_NodeHandle node); /** - * Gets the last code instruction of a node. - * @param node_num the node number - * @return a number of the last code instruction of graph node - * @note Assertion is raised if node_num is not a - * code range node. + * Prints graph node instructions in stderr. + * @param node_num a graph node + * @note Empty in release mode. */ - unsigned GetNodeLastInstr(unsigned node_num) - { - vf_NodeHandle node = GetNode(node_num); - assert(VF_TYPE_NODE_CODE_RANGE == node->m_type); - return node->m_end; - } // GetNodeLastInstr + void DumpNodeInternal(vf_NodeHandle node); +#ifdef _VF_DEBUG /** - * Gets a bytecode length of a graph node instructions. - * @param context a verifier context handle - * @param node a node handle - * @return a number of the last code instruction of graph node - * @note Assertion is raised if node_num is not a - * code range node. + * Prints subroutine information in stderr. + * @param sub a subroutine handle */ - unsigned GetNodeBytecodeLen(vf_ContextHandle context, vf_NodeHandle node) - { - assert(VF_TYPE_NODE_CODE_RANGE == node->m_type); - unsigned char *code_end = (node->m_end + 1 == context->m_codeNum) - ? method_get_bytecode(context->m_method) - + method_get_code_length(context->m_method) - : context->m_code[node->m_end + 1].m_addr; - - unsigned len = (unsigned) (code_end - - context->m_code[node->m_start].m_addr); - return len; - } // GetNodeBytecodeLen + void DumpSub(vf_SubHandle sub); /** - * Gets a stack modifier of a graph node. - * @param node_num a node number - * @return a stack modifier of graph node + * Checks if node maps are allocated. + * @param[in] vector to check */ - int GetNodeStackModifier(unsigned node_num) + bool AreMapsAllocated(vf_MapVectorHandle vector) const { - return GetNode(node_num)->m_stack; - } // GetNodeStackModifier + return (!m_ctx->m_maxlocal || vector->m_local) + && (!m_ctx->m_maxstack || vector->m_stack); + } +#endif // _VF_DEBUG /** - * Sets graph node stack modifier. - * @param node_num a graph node number - * @param stack a stack modifier (signed value) + * Function dumps graph header in file in DOT format. + * @param graph_name - graph name + * @param fout - file stream + * @note Empty in release mode. + * @note Graph name is created from class and method names. */ - void SetNodeStackModifier(unsigned node_num, int stack) - { - vf_Node *node = (vf_Node *) GetNode(node_num); - node->m_stack = stack; - } // SetNodeStackModifier + void DumpDotHeader(char *graph_name, ofstream &fout); /** - * Counts graph nodes. - * @return a number of graph nodes + * Dumps a graph node in a file in DOT format. + * @param node a graph node + * @param fout a file stream + * @note Empty in release mode. + */ + void DumpDotNode(vf_NodeHandle node, ofstream &fout); + + /** + * Dumps graph node instructions in a file stream in DOT format. + * @param node a graph node + * @param next_node a separator between nodes in stream + * @param next_instr a separator between instructions in stream + * @param fout an output file stream + * @note Empty in release mode. */ - unsigned GetNodeCount() - { - return m_nodenum; - } // GetNodeCount + void DumpDotNodeInternal(vf_NodeHandle node, + char *next_node, char *next_instr, ofstream &fout); /** - * Counts graph edges excluding - * the reserved edge. - * @return a number of graph edges + * Function dumps graph end in file in DOT format. + * @param fout - output file stream + * @note Empty in release mode. */ - unsigned GetEdgeCount() - { - return m_edgenum - 1; - } // GetEdgeCount + void DumpDotEnd(ofstream &fout); +public: /** - * Marks a graph node with a given number. - * @param node_num a graph node number - * @param mark a mark - */ - void SetNodeMark(unsigned node_num, int mark) + * Constructs a control flow graph and allocates memory for + * graph structure, nodes and edges. + * @param nodenum a number of graph nodes + * @param edgenum a number of graph edges + * @param ctx a verification context + */ + vf_Graph(unsigned nodenum, unsigned edgenum, + vf_ContextHandle ctx):m_nodes(NULL), m_edges(NULL), + m_pool(ctx->m_pool), m_enum(NULL), m_nodenum(0), m_edgenum(0), + m_enumcount(0), m_ctx(ctx), m_free(false) { - vf_Node *node = (vf_Node *) GetNode(node_num); - node->m_mark = mark; - } // SetNodeMark + CreateNodes(nodenum); + CreateEdges(edgenum); + } // vf_Graph /** - * Gets a graph node mark. - * @param node_num a node number - * @return a graph node mark + * Control flow graph destructor. + * @note Function release memory for graph structure, nodes and edges. */ - int GetNodeMark(unsigned node_num) - { - return GetNode(node_num)->m_mark; - } // GetNodeMark + ~vf_Graph() { + if (m_free) { + vf_delete_pool(m_pool); + } + } // ~vf_Graph /** - * Checks if a node is marked. - * @param node_num a graph node number - * @return true if node is marked, false otherwise + * Allocates memory for graph nodes. + * @param count a number of nodes */ - bool IsNodeMarked(unsigned node_num) + void CreateNodes(unsigned count) { - return 0 != GetNode(node_num)->m_mark; - } // IsNodeMarked + assert(count > 0); + vf_NodeContainer *nodes = + (vf_NodeContainer *) AllocMemory(sizeof(vf_NodeContainer) + + (count - 1) * sizeof(vf_Node)); + + nodes->container.m_max = count; + if (m_nodes == NULL) { + m_nodes = nodes; + } else { + vf_add_container(&m_nodes->container, &nodes->container); + } + } /** - * Function removes node mark. + * Allocates a container for graph edges. + * @param count a number of edges */ - void CleanNodesMark() + void CreateEdges(unsigned count) { - // clean node's mark - assert(m_nodes); - vf_NodeContainer *nodes = m_nodes; - while (nodes != NULL) { - for (unsigned index = 0; index < nodes->m_used; index++) { - nodes->m_node[index].m_mark = 0; - } - nodes = nodes->m_next; + assert(count > 0); + vf_EdgeContainer *edges = + (vf_EdgeContainer *) AllocMemory(sizeof(vf_EdgeContainer) + + (count - 1) * sizeof(vf_Edge)); + edges->container.m_max = count; + if (m_edges == NULL) { + m_edges = edges; + } else { + vf_add_container(&m_edges->container, &edges->container); } - return; - } // CleanNodesMark + } /** - * Sets local variable reference initialization flag for a anode. - * @param node_num a graph node number - * @param flag a node flag + * Gets a graph node. + * @param[in] node_num a node number, should be in range + * @return a handle of the node */ - void SetNodeInitFlag(unsigned node_num, bool flag) + vf_NodeHandle GetNode(unsigned node_num) const { - vf_Node *node = (vf_Node *) GetNode(node_num); - node->m_initialized = flag; - } // SetNodeInitFlag + // get node + assert(m_nodes); + assert(node_num < m_nodenum); + + vf_NodeContainer *nodes = + (vf_NodeContainer *) vf_get_container(&m_nodes->container, + node_num); + return nodes->m_node + node_num; + } // GetNode + /** - * Gets an initialization flag for local variable reference for a given node. - * @param node_num a graph node number - * @return true if the local variable reference has - * to be initialized, false otherwise. + * Gets a graph node from a program counter. + * + * @param[in] pc a bytecode index at a node start + * @return a handle of a node */ - bool GetNodeInitFlag(unsigned node_num) + vf_NodeHandle GetNodeFromBytecodeIndex(unsigned pc) const { - return GetNode(node_num)->m_initialized; - } // GetNodeInitFlag + vf_InstrHandle instr = m_ctx->m_bc[pc].m_instr; + assert(instr); + assert(m_ctx->m_bc[pc].m_instr->m_addr - m_ctx->m_bytes == pc); + return instr->m_node; + } /** - * Function creates IN data flow vector of a node. - * @param node_num a graph node number - * @param example a handle of copied data flow vector - * @param need_copy a copy flag - * @note If copy flag true, incoming vector is copied to IN, - * else if copy flag false, IN vector is created - * with parameters of current vector. + * Gets the start node. + * @return the handle of the start node */ - void SetNodeInVector(unsigned node_num, - vf_MapVectorHandle example, bool need_copy) + vf_NodeHandle GetStartNode() { - SetVector(GetNodeInVector(node_num), example, need_copy); - } // SetNodeInVector + return m_nodes->m_node; + } // GetStartNode /** - * Creates OUT data flow vector of a node. - * @param node_num a graph node number - * @param example a handle of copied data flow vector - * @param need_copy a copy flag - * @note If copy flag true, incoming vector is copied to OUT, - * else if copy flag false, OUT vector is created - * with parameters of current vector. + * Adds the end node. + * @return the handle of the end node */ - void SetNodeOutVector(unsigned node_num, - vf_MapVectorHandle example, bool need_copy) + vf_NodeHandle AddEndNode() { - SetVector(GetNodeOutVector(node_num), example, need_copy); - } // SetNodeOutVector + m_endnode = NewNode(VF_NODE_END_ENTRY); + return m_endnode; + } // GetEndNode /** - * Gets IN data flow vector for the node. - * @param node_num graph node number - * @return a reference to IN data flow stack map vector - * @note Assertion is raised if node_num is out of range. - * @see vf_MapVector_t + * Gets the end node. + * @return the handle of the end node */ - vf_MapVectorHandle GetNodeInVector(unsigned node_num) + vf_NodeHandle GetEndNode() { - return &(GetNode(node_num)->m_inMapVector); - } // GetNodeInVector + return m_endnode; + } // GetEndNode /** - * Gets OUT data flow vector for the node. - * @param node_num graph node number - * @return a reference to OUT data flow stack map vector - * @see vf_MapVector_t + * Creates a new node of a specific type. + * A node array must have enough free space for a new element. + * @param[in] type node type + * @return a handle of the created node */ - vf_MapVectorHandle GetNodeOutVector(unsigned node_num) + vf_NodeHandle NewNode(vf_NodeType type) { - return &(GetNode(node_num)->m_outMapVector); - } // GetNodeOutVector + // get node + assert(m_nodes); + unsigned count = m_nodenum; + vf_NodeContainer *nodes = + (vf_NodeContainer *) vf_get_container(&m_nodes->container, count); + + // increment nodes count + m_nodenum++; + nodes->container.m_used++; + assert(nodes->container.m_used <= nodes->container.m_max); + + // set node + vf_Node *node = nodes->m_node + count; + node->m_type = type; + return node; + } // NewNode + /** - * Function creates graph edges. - * @param number - number of edges + * Creates a new node for a bytecode range. + * A node array must have enough free space for a new element. + * @param[in] start the first instruction + * @param[in] end the last instruction + * @return a handle of the created node */ - void CreateEdges(unsigned number); + vf_NodeHandle NewNode(vf_InstrHandle start, vf_InstrHandle end) + { + // get node + vf_Node *node = (vf_Node *) NewNode(VF_NODE_CODE_RANGE); + node->m_start = start; + node->m_end = end; + return node; + } // NewNode(start, end) /** - * Function receives next IN edge of graph node. - * @param edge_num - number of graph edge - * @return Number of next IN edge of node. - * @note Assertion is raised if edge_num is out of range. + * Copies a node from existing node. + * A node array must have enough free space for a new element. + * @param[in] node a handle of an existing node + * @return a handle of the created node */ - unsigned GetEdgeNextInEdge(unsigned edge_num) + vf_NodeHandle NewNode(vf_NodeHandle node) { - return GetEdge(edge_num)->m_innext; - } // GetEdgeNextInEdge + // get node + vf_Node *new_node = (vf_Node *) NewNode(node->m_type); + *new_node = *node; + // edges are outdated, delete them + new_node->m_inedge = new_node->m_outedge = NULL; + new_node->m_innum = new_node->m_outnum = NULL; + return new_node; + } // NewNode(vf_NodeHandle node) /** - * Function receives next OUT edge of graph node. - * @param edge_num - number of graph edge - * @return Number of next OUT edge of node. - * @note Assertion is raised if edge_num is out of range. + * Creates a new edge between graph nodes. + * + * @param start_node an edge start + * @param end_node an edge end + * @return a handle of a created edge */ - unsigned GetEdgeNextOutEdge(unsigned edge_num) + vf_EdgeHandle NewEdge(vf_Node *start_node, vf_Node *end_node) { - return GetEdge(edge_num)->m_outnext; - } // GetEdgeNextOutEdge + // get edge + assert(m_edges); + + VF_TRACE("graph", + "Creating a new edge from " << GetNodeNum(start_node) + << " to " << GetNodeNum(end_node)); + unsigned count = m_edgenum; + vf_EdgeContainer *edges = + (vf_EdgeContainer *) vf_get_container(&m_edges->container, count); + + // get a new edge and edge's nodes + vf_Edge *edge = edges->m_edge + count; + + // set a new edge + edge->m_start = start_node; + edge->m_end = end_node; + edge->m_outnext = start_node->m_outedge; + start_node->m_outedge = edge; + start_node->m_outnum++; + edge->m_innext = end_node->m_inedge; + end_node->m_inedge = edge; + end_node->m_innum++; + + // increment edge count + m_edgenum++; + edges->container.m_used++; + assert(edges->container.m_used <= edges->container.m_max); + return edge; + } // NewEdge /** - * Function receives start graph node of edge. - * @param edge_num - number of graph edge - * @return Number start graph node of edge. - * @note Assertion is raised if edge_num is out of range. + * Resets an internal graph node iterator. */ - unsigned GetEdgeStartNode(unsigned edge_num) + void ResetNodeIterator() { - return GetEdge(edge_num)->m_start; - } // GetEdgeStartNode + iterator.Reset(&m_nodes->container); + } /** - * Function receives end graph node of edge. - * @param edge_num - number of graph edge - * @return Number end graph node of edge. - * @note Assertion is raised if edge_num is out of range. + * Gets a next node. */ - unsigned GetEdgeEndNode(unsigned edge_num) + vf_NodeHandle GetNextNode() { - return GetEdge(edge_num)->m_end; - } // GetEdgeStartNode + return iterator.GetNextNode(); + } /** - * Function receives number of IN edges of graph node. - * @param node_num - number of graph node - * @return Number of IN edges of graph node. - * @note Assertion is raised if node_num is out of range. + * Checks if there are still elements to iterate. */ - unsigned GetNodeInEdgeNumber(unsigned node_num) + bool HasMoreElements() const { - return GetNode(node_num)->m_innum; - } // GetNodeInEdgeNumber + return iterator.HasMoreElements(); + } /** - * Function receives number of OUT edges of graph node. - * @param node_num - number of graph node - * @return Number of OUT edges of graph node. - * @note Assertion is raised if node_num is out of range. + * Counts graph nodes. + * @return a number of graph nodes */ - unsigned GetNodeOutEdgeNumber(unsigned node_num) + unsigned GetNodeCount() { - return GetNode(node_num)->m_outnum; - } // GetNodeOutEdgeNumber + return m_nodenum; + } // GetNodeCount /** - * Function receives first IN edge of graph node. - * @param node_num - number of graph node - * @return First IN edges of node. - * @note Assertion is raised if node_num is out of range. + * Counts graph edges excluding + * the reserved edge. + * @return a number of graph edges */ - unsigned GetNodeFirstInEdge(unsigned node_num) + unsigned GetEdgeCount() const { - return GetNode(node_num)->m_inedge; - } // GetNodeFirstInEdge + return m_edgenum; + } // GetEdgeCount /** - * Function receives first OUT edge of graph node. - * @param node_num - number of graph node - * @return First OUT edges of node. - * @note Assertion is raised if node_num is out of range. + * Removes marks for all nodes. */ - unsigned GetNodeFirstOutEdge(unsigned node_num) + void CleanNodeMarks() { - return GetNode(node_num)->m_outedge; - } // GetNodeFirstOutEdge + assert(m_nodes); + ResetNodeIterator(); + + // clean node marks + while (HasMoreElements()) { + ((vf_Node *) GetNextNode())->m_mark = 0; + } + } // CleanNodeMarks /** * Allocates memory from the graph memory pool. @@ -553,199 +651,285 @@ class vf_Graph void *AllocMemory(unsigned size) { assert(size); - return vf_alloc_pool_memory(m_pool, size); + return vf_palloc(m_pool, size); } // AllocMemory /** - * Function cleans graph node enumeration, creates new graph - * enumeration structure and sets first enumeration element. - * @param node_num - first enumeration node - * @note Assertion is raised if node_num is out of range. + * Allocates a graph node enumeration sequence and + * sets first enumeration element. + * @param node a first enumeration node */ - void SetStartCountNode(unsigned node_num); + void SetStartCountNode(vf_Node *node) + { + // check node number is in range + assert(m_nodes); + assert(node); + + // allocate memory + m_enum = (vf_NodeHandle *) vf_palloc(m_pool, sizeof(vf_NodeHandle) + * m_nodenum); + + // clean node enumeration + ResetNodeIterator(); + while (HasMoreElements()) { + ((vf_Node *) GetNextNode())->m_nodecount = TOP_MARK; + } + + // set node enumeration number + node->m_nodecount = 0; + + // set enumeration first element; + m_enum[0] = node; + m_enumcount = 1; + } /** * Function receives number of enumerated nodes. * @return Function returns number of enumerated nodes. */ - unsigned GetEnumCount() + unsigned GetReachableNodeCount() { return m_enumcount; } // SetStartCountNode /** - * Function sets next enumeration element in graph enumeration structure. - * @param node_num - next enumeration node - * @note Assertion is raised if node_num is out of range. + * Sets a next enumeration element in a graph enumeration + * and stores the index in the node. + * @param node a node handle */ - void SetNextCountNode(unsigned node_num) + void AddReachableNode(vf_Node *node) { // check enumeration count is in range assert(m_enumcount < m_nodenum); // set enumeration element for node - m_enum[m_enumcount] = node_num; + m_enum[m_enumcount] = node; // set node enumeration number and increase number of enumerated nodes - vf_Node *node = (vf_Node *) GetNode(node_num); node->m_nodecount = m_enumcount++; - return; } // SetNextCountNode /** - * Function receives first enumerated graph node. - * @return First enumerated graph node in graph enumeration structure. + * Suits for counting reachable nodes. + * @param node a node handle */ - unsigned GetStartCountNode() + void IncrementReachableCount() { - return m_enum[0]; - } // GetStartCountNode + m_enumcount++; + } // IncreaseReachableCount /** - * Function receives graph node relevant to enumeration element. - * @param count - given enumeration element - * @return Graph node relevant to enumeration element. - * @note Assertion is raised if count is out of range. + * Gets a graph node by enumeration index. + * @param count given enumeration index + * @return a graph node handle */ - unsigned GetCountElementNode(unsigned count) + vf_NodeHandle GetReachableNode(unsigned count) { - // check element is in range. - assert(count < m_nodenum); return m_enum[count]; } // GetCountElementNode /** - * Function receives graph node enumeration count. - * @param node_num - given node - * @return Graph node enumeration count. - * @note Assertion is raised if node_num is out of range. + * Copies a data flow vector from a given source. + * @param source a handle of a source vector + * @param dest a pointer to a vector to set */ - unsigned GetNodeCountElement(unsigned node_num) + void CopyVector(vf_MapVectorHandle source, vf_MapVector *dest) { - return GetNode(node_num)->m_nodecount; - } // GetNodeCountElement + assert(AreMapsAllocated(source)); + assert(AreMapsAllocated(dest)); + + dest->m_number = source->m_number; + dest->m_depth = source->m_depth; + + unsigned index; + for (index = 0; index < source->m_number; index++) { + dest->m_local[index] = source->m_local[index]; + } + for (index = 0; index < source->m_depth; index++) { + dest->m_stack[index] = source->m_stack[index]; + } + } /** - * Function prints graph structure in stderr. - * @param context - current verifier context - * @note Function is valid in debug mode. - * @see vf_Context_t + * Copies a data flow vector from a given source, + * nullifies the rest of the destination. + * @param source a handle of a source vector + * @param dest a pointer to a vector to set */ - void DumpGraph(vf_Context_t * context); + void CopyFullVector(vf_MapVectorHandle source, vf_MapVector *dest) + { + assert(AreMapsAllocated(source)); + assert(AreMapsAllocated(dest)); + + unsigned index; + vf_MapEntry zero = { 0 }; + + dest->m_number = source->m_number; + dest->m_depth = source->m_depth; + + // copy locals + for (index = 0; index < source->m_number; index++) { + dest->m_local[index] = source->m_local[index]; + } + for (; index < m_ctx->m_maxlocal; index++) { + dest->m_local[index] = zero; + } + // copy stack + for (index = 0; index < source->m_depth; index++) { + dest->m_stack[index] = source->m_stack[index]; + } + for (; index < m_ctx->m_maxstack; index++) { + dest->m_stack[index] = zero; + } + } /** - * Function dumps verifier graph in file in DOT format. - * @param context - current verifier context - * @note Function is valid in debug mode. - * @note File name is created from class and method names with .dot extension. - * @see vf_Context_t + * Allocates a vector with maximum storage capacity. + * @param[out] vector map to allocate */ - void DumpDotGraph(vf_Context_t * context); - - private: - vf_NodeContainer *m_nodes; ///< array of nodes - vf_EdgeContainer *m_edges; ///< array of edges - vf_VerifyPool_t *m_pool; ///< graph memory pool - unsigned *m_enum; ///< graph node enumeration structure - unsigned m_nodenum; ///< number of nodes - unsigned m_edgenum; ///< number of edges - unsigned m_enummax; ///< max number of enumerated elements - unsigned m_enumcount; ///< number of enumerated elements - bool m_free; ///< need to free pool + void AllocVector(vf_MapVector *vector) + { + // create and set local vector + if (m_ctx->m_maxlocal && !vector->m_local) { + vector->m_local = + (vf_MapEntry *) vf_palloc(m_pool, + m_ctx->m_maxlocal * sizeof(vf_MapEntry)); + } + // create and set stack vector + if (m_ctx->m_maxstack && !vector->m_stack) { + vector->m_stack = + (vf_MapEntry *) vf_palloc(m_pool, + m_ctx->m_maxstack * sizeof(vf_MapEntry)); + } + } /** - * Creates a data flow vector from a given example. - * @param vector_handle a vector to set - * @param example a handle of an example vector - * @param need_copy a copy flag - * @note If copy flag true, incoming vector is copied to, - * otherwise IN vector is created - * with parameters of current vector. - */ - void SetVector(vf_MapVectorHandle vector_handle, - vf_MapVectorHandle example, bool need_copy); - - /** - * Function prints graph node in stderr. - * @param node_num - number of graph node - * @param context - current verifier context - * @note Function is valid in debug mode. - * @note Assertion is raised if node_num is out of range. - * @see vf_Context_t - */ - void DumpNode(unsigned node_num, vf_Context_t * context); - - /** - * Function prints graph node instruction in stream. - * @param node_num - number of graph node - * @param context - current verifier context - * @note Function is valid in debug mode. - * @note Assertion is raised if node_num is out of range. - * @see vf_Context_t + * Prints a graph structure in stderr. + * @note Empty in release mode. */ - void DumpNodeInternal(unsigned node_num, vf_Context_t * context); + void DumpGraph(); + /** + * Dumps a graph in a file in DOT format. + * @note Empty in release mode. + * @note File name is created from class and method names with .dot extension. + */ + void DumpDotGraph(); +#if _VF_DEBUG /** - * Function dumps graph header in file in DOT format. - * @param graph_name - graph name - * @param fout - file stream - * @note Function is valid in debug mode. - * @note Graph name is created from class and method names. + * Gets a graph node number for debugging purposes. + * + * @param[in] node a node handle + * @return a subsequent node number */ - void DumpDotHeader(char *graph_name, ofstream &fout); + unsigned GetNodeNum(vf_NodeHandle node) const + { + assert(node); + unsigned node_num = 0; + vf_NodeContainer *nodes = m_nodes; + while (nodes) { + unsigned index = node - nodes->m_node; + if (index < nodes->container.m_max) { + node_num += index; + assert(node_num < m_nodenum); + return node_num; + } + node_num += nodes->container.m_max; + nodes = (vf_NodeContainer *) nodes->container.m_next; + } + LDIE(1, "Verifier: vf_Graph::GetNodeNum: cannot find an node"); + } /** - * Function dumps graph node in file in DOT format. - * @param node_num - number of graph node - * @param fout - file stream - * @param context - current verifier context - * @note Function is valid in debug mode. - * @note Assertion is raised if node_num is out of range. - * @see vf_Context_t - */ - void DumpDotNode(unsigned node_num, ofstream &fout, - vf_Context_t * context); - - /** - * Function dumps graph node instruction in file stream in DOT format. - * @param node_num - number of graph node - * @param next_node - separator between nodes in stream - * @param next_instr - separator between instructions in stream - * @param fout - output file stream - * @param context - current verifier context - * @note Function is valid in debug mode. - * @note Assertion is raised if node_num is out of range. - * @see vf_Context_t - */ - void DumpDotNodeInternal(unsigned node_num, - char *next_node, - char *next_instr, ofstream &fout, vf_Context_t * context); + * Checks amount of pre-allocated space for nodes in the graph. + */ + unsigned HasMoreNodeSpace() const + { + unsigned used = vf_used_space(&m_nodes->container); + assert(used == m_nodenum); + return vf_total_space(&m_nodes->container) - used; + } // HasMoreNodeSpace /** - * Function dumps graph end in file in DOT format. - * @param fout - output file stream - * @note Function is valid in debug mode. + * Checks amount of pre-allocated space for edges in the graph. */ - void DumpDotEnd(ofstream &fout); + unsigned HasMoreEdgeSpace() const + { + unsigned used = vf_used_space(&m_edges->container); + assert(used == m_edgenum); + return vf_total_space(&m_edges->container) - used; + } // HasMoreEdgeSpace + +#endif // _VF_DEBUG }; // vf_Graph + /** - * Checks if a code range node ends with a specific - * instruction type. - * - * @param[in] context a verifier context - * @param[in] node_index the node identifier - * - * @return a type of the last instruction of code range node + * Gets a type of the ending instruction of the code range. + * @param[in] node a node handle + * @param[in] ctx a verification context + * @return a type of the last instruction of the code range node */ -static inline vf_CodeType -vf_get_last_instruction_type(vf_ContextHandle context, unsigned node_index) +static inline vf_InstrType +vf_get_last_instruction_type(vf_NodeHandle node, vf_ContextHandle ctx) { - vf_NodeHandle node = context->m_graph->GetNode(node_index); - assert(VF_TYPE_NODE_CODE_RANGE == node->m_type); - return context->m_code[node->m_end].m_type; + assert(VF_NODE_CODE_RANGE == node->m_type); + return node->m_end->m_type; +} // vf_get_last_instruction_type + +/** + * Checks if a given edge is a subroutine call branch. + * @param[in] edge an edge handle + * @param[in] ctx a verification context + * @return true if this branch is a jsr call branch + */ +static inline bool vf_is_jsr_branch(vf_EdgeHandle edge, vf_ContextHandle ctx) +{ + vf_NodeHandle node = edge->m_start; + return (VF_NODE_CODE_RANGE == node->m_type) + && (VF_INSTR_JSR == node->m_end->m_type) + && (VF_NODE_CODE_RANGE == edge->m_end->m_type); } +/** + * Gets a subroutine number for debugging purposes. + * + * @param[in] sub a subroutine handle + * @param[in] csub a subroutine context + * @return a subsequent subroutine number + */ +unsigned vf_get_sub_num(vf_NodeHandle node, vf_ContextHandle ctx); + +/** + * Checks that a stack depth is the same as during last visit, calculates + * a stack modifier, counts a number of visited nodes, for each instruction checks + * that stack doesn't overflow. + * @param[in, out] node a pointer to a node structure, m_mark is + * modified during the call + * @param[in, out] depth starts as node depth before the first node instruction and ends + * as a node depth after the last node instruction + * @param[in] ctx a verifier context + * @return VER_Continue if this node wasn't visited before, and analysis of + * subsequent nodes is needed, VER_OK if the stack depth is consistent, an + * error code otherwise + */ +vf_Result vf_check_node_stack_depth(vf_Node *node, // a graph node + unsigned &depth, // stack depth + vf_Context *ctx); // verification context + +/** + * Creates and sets graph node OUT vector. + * @param[in] node a graph node handle + * @param[in, out] invector an IN vector, then OUT vector + * @param[in] ctx a verifier context + * @return VER_OK if OUT vector wasn't changed, + * VER_Continue + * if the vector was changed successfully, an error code otherwise + */ +vf_Result +vf_set_node_out_vector(vf_NodeHandle node, + vf_MapVector *invector, vf_Context *ctx); + #endif // _VERIFIER_GRAPH_H_ diff -pu 9/trunk/working_vm/vm/vmcore/src/verifier/ver_real.h 91/trunk/working_vm/vm/vmcore/src/verifier/ver_real.h --- 9/trunk/working_vm/vm/vmcore/src/verifier/ver_real.h 2007-03-20 18:34:51.911048300 +0300 +++ 91/trunk/working_vm/vm/vmcore/src/verifier/ver_real.h 2007-03-21 04:10:17.899161600 +0300 @@ -45,55 +45,82 @@ using namespace std; */ //=========================================================== /** - * Define debug mode for verifier. + * Defines a debug mode for verifier. */ #ifdef NDEBUG -#define _VERIFY_DEBUG 0 +#define _VF_DEBUG 0 #else // NDEBUG -#define _VERIFY_DEBUG 1 +#define _VF_DEBUG 1 #endif // NDEBUG /** - * Debugging and trace message defines. - * @note Debug messages is available only in debug mode, - * trace messages is available in any mode. - * @note Verifier trace looks like: 'verifier' + component of verifier - */ -#if _VERIFY_DEBUG -#define VERIFY_DEBUG(info) ECHO("vf_debug: " << info) -#else // _VERIFY_DEBUG -#define VERIFY_DEBUG(info) -#endif // _VERIFY_DEBUG -#define VERIFY_TRACE(comp, mess) TRACE2("verifier." comp, mess) -#define VERIFY_REPORT(context, error_message ) \ + * Both debug and trace channels are available only at debug mode. + * A debug channel is visible for a user while a trace channel should be + * enabled via -Xtrace:verifier command line option. + */ +#if _VF_DEBUG +#define VF_DEBUG(info) ECHO("vf_debug: " << info) +#else // _VF_DEBUG +#define VF_DEBUG(info) +#endif // _VF_DEBUG + +#define VF_TRACE(comp, message) TRACE2("verifier." comp, message) +/** + * Verifer dump domains. They can be specified in a command line in + * a following form -Xtrace:vfdump.<domain>. + */ +/** Type constraints for a class. */ +#define DUMP_CONSTRAINT "constraint" +/** An instruction array. */ +#define DUMP_INSTR "instr" +/** A control flow graph. */ +#define DUMP_GRAPH "graph" +/** A graph with cleaned dead nodes and inlined subroutines. */ +#define DUMP_MOD "mod_graph" +/** A graph in a dot format. */ +#define DUMP_DOT "dot" +/** A modified graph in a dot format. */ +#define DUMP_DOT_MOD "mod_dot" +/** Node map vectors. */ +#define DUMP_NODE_MAP "map.node" +/** Instruction map vectors. */ +#define DUMP_INSTR_MAP "map.instr" +/** Merged map vectors */ +#define DUMP_MERGE_MAP "map.merge" + +#ifdef _VF_DEBUG +#define vf_is_trace_enabled(domain) is_enabled( "vfdump." domain, TRACE ) +#else // _VF_DEBUG +#define vf_is_trace_enabled(domain) false +#endif // _VF_DEBUG + + +#define VF_SET_CTX( ctx, error_message ) \ { \ stringstream stream; \ stream << error_message; \ - vf_set_error_message( stream, (context) ); \ + vf_set_error_message( stream, ( ctx ) ); \ } -#define VERIFY_REPORT_CLASS(context, method, error_message ) \ - VERIFY_REPORT(context, \ - "(class: " << class_get_name( (context)->m_class ) \ - << ", method: " << method_get_name( method ) \ - << method_get_descriptor( method ) \ - << ") " << error_message ) -#define VERIFY_REPORT_METHOD(context, error_message ) \ - VERIFY_REPORT_CLASS(context, (context)->m_method, error_message ) +#define VF_REPORT_CTX( ctx ) "(class: " << class_get_name( (ctx)->m_class ) \ + << ", method: " << method_get_name( (ctx)->m_method ) \ + << method_get_descriptor( (ctx)->m_method ) << ") " +#define VF_REPORT( ctx, error_message ) \ + VF_SET_CTX( ctx, VF_REPORT_CTX( ctx ) << error_message ) /** * Define source code line and source file name parameters and arguments. */ -#if _VERIFY_DEBUG -#define VERIFY_SOURCE_PARAMS UNREF int line_, UNREF const char *file_ -#define VERIFY_SOURCE_ARGS0 __LINE__, __FILE__ -#define VERIFY_SOURCE_ARGS1 line_, file_ -#define VERIFY_REPORT_SOURCE file_ << "(" << line_ << "): " -#else // _VERIFY_DEBUG -#define VERIFY_SOURCE_PARAMS int -#define VERIFY_SOURCE_ARGS0 0 -#define VERIFY_SOURCE_ARGS1 0 -#define VERIFY_REPORT_SOURCE "" -#endif // _VERIFY_DEBUG +#if _VF_DEBUG +#define VF_SOURCE_PARAMS UNREF int line_, UNREF const char *file_ +#define VF_SOURCE_ARGS0 __LINE__, __FILE__ +#define VF_SOURCE_ARGS1 line_, file_ +#define VF_REPORT_SOURCE file_ << "(" << line_ << "): " +#else // _VF_DEBUG +#define VF_SOURCE_PARAMS int +#define VF_SOURCE_ARGS0 0 +#define VF_SOURCE_ARGS1 0 +#define VF_REPORT_SOURCE "" +#endif // _VF_DEBUG //=========================================================== // Verifier contant pool checks @@ -105,60 +132,60 @@ using namespace std; // for handler id = 0 is legal value #define CHECK_HANDLER_CONST_POOL_ID( id, len, context ) \ if( (id) >= (len) ) { \ - VERIFY_REPORT_METHOD( context, "Illegal constant pool index in handler" ); \ + VF_REPORT( context, "Illegal constant pool index in handler" ); \ return VER_ErrorHandler; \ } // for handler id = 0 is legal value #define CHECK_HANDLER_CONST_POOL_CLASS( context, id ) \ if( (id) && class_get_cp_tag( (context)->m_class, (id) ) != _CONSTANT_Class ) { \ - VERIFY_REPORT_METHOD( context, "Illegal type in constant pool for handler, " \ + VF_REPORT( context, "Illegal type in constant pool for handler, " \ << id << ": CONSTANT_Class is expected" ); \ return VER_ErrorHandler; \ } #define CHECK_CONST_POOL_ID( id, len, context ) \ if( !(id) || (id) >= (len) ) { \ - VERIFY_REPORT_METHOD( context, "Illegal constant pool index" ); \ + VF_REPORT( context, "Illegal constant pool index" ); \ return VER_ErrorConstantPool; \ } #define CHECK_CONST_POOL_CLASS( context, id ) \ if( class_get_cp_tag( (context)->m_class, (id) ) != _CONSTANT_Class ) { \ - VERIFY_REPORT_METHOD( context, "Illegal type in constant pool, " \ + VF_REPORT( context, "Illegal type in constant pool, " \ << id << ": CONSTANT_Class is expected" ); \ return VER_ErrorConstantPool; \ } #define CHECK_CONST_POOL_METHOD( context, id ) \ if( class_get_cp_tag( (context)->m_class, (id) ) != _CONSTANT_Methodref ) { \ - VERIFY_REPORT_METHOD( context, "Illegal type in constant pool, " \ + VF_REPORT( context, "Illegal type in constant pool, " \ << id << ": CONSTANT_Methodref is expected" ); \ return VER_ErrorConstantPool; \ } #define CHECK_CONST_POOL_INTERFACE( context, id ) \ if( class_get_cp_tag( (context)->m_class, (id) ) != _CONSTANT_InterfaceMethodref ) { \ - VERIFY_REPORT_METHOD( context, "Illegal type in constant pool, " \ + VF_REPORT( context, "Illegal type in constant pool, " \ << id << ": CONSTANT_InterfaceMethodref is expected" ); \ return VER_ErrorConstantPool; \ } #define CHECK_CONST_POOL_FIELD( context, id ) \ if( class_get_cp_tag( (context)->m_class, (id) ) != _CONSTANT_Fieldref ) { \ - VERIFY_REPORT_METHOD( context, "Illegal type in constant pool, " \ + VF_REPORT( context, "Illegal type in constant pool, " \ << id << ": CONSTANT_Fieldref is expected" ); \ return VER_ErrorConstantPool; \ } #define CHECK_CONST_POOL_TYPE( context, id ) \ if( class_get_cp_tag( (context)->m_class, (id) ) != _CONSTANT_NameAndType ) { \ - VERIFY_REPORT_METHOD( context, "Illegal type in constant pool, " \ + VF_REPORT( context, "Illegal type in constant pool, " \ << id << ": CONSTANT_NameAndType is expected" ); \ return VER_ErrorConstantPool; \ } #define CHECK_CONST_POOL_STRING( context, id ) \ if( class_get_cp_tag( (context)->m_class, (id) ) != _CONSTANT_String ) { \ - VERIFY_REPORT_METHOD( context, "Illegal type in constant pool, " \ + VF_REPORT( context, "Illegal type in constant pool, " \ << id << ": CONSTANT_String is expected" ); \ return VER_ErrorConstantPool; \ } #define CHECK_CONST_POOL_UTF8( context, id ) \ if( class_get_cp_tag( (context)->m_class, (id) ) != _CONSTANT_Utf8) { \ - VERIFY_REPORT_METHOD( context, "Illegal type in constant pool, " \ + VF_REPORT( context, "Illegal type in constant pool, " \ << id << ": CONSTANT_Utf8 is expected" ); \ return VER_ErrorConstantPool; \ } @@ -168,6 +195,11 @@ using namespace std; //=========================================================== /** + * Verifier error codes. + */ +typedef Verifier_Result vf_Result; + +/** * Constraint check types enum. */ typedef enum @@ -187,7 +219,7 @@ typedef enum VF_CHECK_INVOKESPECIAL, VF_CHECK_UNINITIALIZED_THIS, VF_CHECK_NUM -} vf_CheckConstraint_t; +} vf_CheckConstraint; /** * Stack map entry types enum. @@ -208,6 +240,7 @@ typedef enum SM_DOUBLE_HI, SM_RETURN_ADDR, // additional types + SM_ANY, // matches any value SM_COPY_0, SM_COPY_1, SM_COPY_2, @@ -219,18 +252,19 @@ typedef enum SM_WORD2_LO, SM_WORD2_HI, SM_NUMBER -} vf_MapType_t; +} vf_MapType; /** * Each instruction has a descriptive bitmap. */ typedef enum { - VF_TYPE_INSTR_NONE = 0, - VF_TYPE_INSTR_RETURN = 1, - VF_TYPE_INSTR_THROW = 2, - VF_TYPE_INSTR_SUBROUTINE = 3 -} vf_CodeType; + VF_INSTR_NONE = 0, + VF_INSTR_RETURN = 1, + VF_INSTR_THROW = 2, + VF_INSTR_JSR = 3, + VF_INSTR_RET = 4 +} vf_InstrType; //=========================================================== // Verifier predefined structures @@ -238,37 +272,147 @@ typedef enum /** * @ingroup Handles - * The handle of the verifier context. + * A handle of a verifier context. */ typedef const struct vf_Context *vf_ContextHandle; +/** + * @ingroup Handles + * A handle of a subroutine information. + */ +typedef const struct vf_SubContext *vf_SubContextHandle; +/** + * @ingroup Handles + * A graph handle. + */ +typedef const class vf_Graph *vf_GraphHandle; +/** + * @ingroup Handles + * A handle of a graph node. + */ +typedef const struct vf_Node *vf_NodeHandle; +/** + * @ingroup Handles + * A map vector handle. + */ +typedef const struct vf_MapVector *vf_MapVectorHandle; +/** + * @ingroup Handles + * A handle of an instruction. + */ +typedef const struct vf_Instr *vf_InstrHandle; + +//=========================================================== +// Code instruction structures. +//=========================================================== + +/** + * Valid types structure. + */ +struct vf_ValidType +{ + unsigned number; ///< number of types + const char *string[1]; ///< type array +}; + +/** + * Stack map entry structure. + */ +struct vf_MapEntry +{ + vf_ValidType *m_vtype; ///< valid type for reference + union + { + unsigned m_new; ///< program count of opcode new for uninitialized + unsigned m_pc; ///< program count of return address for subroutine + }; + union + { + unsigned short m_local; ///< number of local variable + unsigned short m_index; ///< constant pool index for access check + }; + unsigned short m_type:5; ///< stack map type @see vf_MapType + unsigned short m_ctype:4; ///< constraint type @see vf_CheckConstraint + unsigned short m_is_local:1; ///< local variable modify flag + ///< true - modify local, false - modify stack +}; + +/** + * A bytecode instruction. + */ +struct vf_Instr +{ + unsigned char *m_addr; ///< a start of a bytecode instruction + unsigned *m_off; ///< an array of instruction branches + vf_MapEntry *m_invector; ///< a stack map IN instruction vector + vf_MapEntry *m_outvector; ///< a stack map OUT instruction vector + unsigned m_offcount; ///< a number of instruction branches + union + { + vf_NodeHandle m_node; ///< contains a node handle if the corresponding + ///< basic block starts at the instruction, NULL otherwise + bool m_basic_block_start; ///< begin of a basic block + }; + unsigned short m_minstack; ///< a minimal stack for instruction + unsigned short m_inlen; ///< an IN stack vector length + unsigned short m_outlen; ///< an OUT stack vector length + short m_stack; ///< a stack change + vf_InstrType m_type; ///< an instruction type @see vf_InstrType +}; -/// Verifier context structure. -typedef struct vf_Context vf_Context_t; -/// Verifier structure for a byte of a bytecode. -typedef struct vf_BCode vf_BCode_t; -/// Verifier valid types structure. -typedef struct vf_ValidType vf_ValidType_t; -/// Verifier stack map entry structure. -typedef struct vf_MapEntry vf_MapEntry_t; -/// Verifier code instruction structure. -typedef struct vf_Code vf_Code_t; -/// Verifier constant pool parse structure. -typedef union vf_Parse vf_Parse_t; -/// Verifier graph structure declaration. -class vf_Graph; -/// Verifier type constraint structure. -typedef struct vf_TypeConstraint vf_TypeConstraint_t; -/// Verifier hash table structure. -typedef struct vf_Hash vf_Hash_t; -/// Verifier hash table entry structure. -typedef struct vf_HashEntry vf_HashEntry_t; -/// Verifier pool structure. -typedef struct vf_VerifyPool vf_VerifyPool_t; -/// Verifier pool internal structure. -typedef struct vf_VerifyPoolInternal vf_VerifyPoolInternal_t; -/// Verifier structure of class loader constraint data. -typedef struct vf_ClassLoaderData vf_ClassLoaderData_t; +/** + * A byte of a bytecode. + */ +struct vf_BCode +{ + vf_InstrHandle m_instr; ///< a pointer to vf_Context.m_instr + bool m_basic_block_start:1; ///< true if the block starts here +}; +/** + * Constant pool parse structure. + */ +union vf_Parse +{ + struct + { + vf_MapEntry *m_invector; ///< method IN stack vector + vf_MapEntry *m_outvector; ///< method OUT stack vector + const char *m_name; ///< invoked method name + int m_inlen; ///< IN vector length + int m_outlen; ///< OUT vector length + } method; + struct + { + vf_MapEntry *f_vector; ///< field type map vector + int f_vlen; ///< field type map vector len + } field; +}; + +//=========================================================== +// Pool structures. +//=========================================================== + +/** + * Internal structure of memory pool. + */ +struct vf_PoolInternal +{ + void *m_memory; ///< pool entry memory + char *m_free; ///< free space in pool entry + vf_PoolInternal *m_next; ///< next pool entry + size_t m_freesize; ///< size of free space in pool entry +}; + +/** + * Head structure of memory pool. + */ +struct vf_Pool +{ + vf_PoolInternal *m_pool; ///< pool entry + size_t m_memory; ///< allocated memory size + size_t m_used; ///< used memory size + size_t m_maxuse; ///< max used memory size +}; //=========================================================== // Verifier memory management functions diclarations @@ -277,222 +421,137 @@ typedef struct vf_ClassLoaderData vf_Cla /** * Memory pool entry size. */ -#define VERIFY_POOL_ENTRY_SIZE 0x2000 +#define VF_POOL_ENTRY_SIZE 0x2000 /** * Macros hide source line and source file name function arguments. */ #define vf_error() \ - vf_error_func(VERIFY_SOURCE_ARGS0) + vf_error_func(VF_SOURCE_ARGS0) #define vf_calloc(number, size_element) \ - vf_calloc_func((number), (size_element), VERIFY_SOURCE_ARGS0) + vf_calloc_func((number), (size_element), VF_SOURCE_ARGS0) #define vf_malloc(size) \ - vf_malloc_func((size), VERIFY_SOURCE_ARGS0) + vf_malloc_func((size), VF_SOURCE_ARGS0) #define vf_free(pointer) \ - vf_free_func((pointer), VERIFY_SOURCE_ARGS0) + vf_free_func((pointer), VF_SOURCE_ARGS0) #define vf_realloc(pointer, resize) \ - vf_realloc_func((pointer), (resize), VERIFY_SOURCE_ARGS0) + vf_realloc_func((pointer), (resize), VF_SOURCE_ARGS0) #define vf_create_pool() \ - vf_create_pool_func(VERIFY_SOURCE_ARGS0) -#define vf_alloc_pool_memory(pool, size) \ - vf_alloc_pool_memory_func((pool), (size), VERIFY_SOURCE_ARGS0) -#define vf_clean_pool_memory(pool) \ - vf_clean_pool_memory_func((pool), VERIFY_SOURCE_ARGS0) + vf_create_pool_func(VF_SOURCE_ARGS0) +#define vf_palloc(pool, size) \ + vf_palloc_func((pool), (size), VF_SOURCE_ARGS0) +#define vf_clean_pool(pool) \ + vf_clean_pool_func((pool), VF_SOURCE_ARGS0) #define vf_delete_pool(pool) \ - vf_delete_pool_func((pool), VERIFY_SOURCE_ARGS0) + vf_delete_pool_func((pool), VF_SOURCE_ARGS0) /** * Function performs abend exit from VM. - * @note VERIFY_SOURCE_PARAMS - debug parameters source line and source file name - * @see VERIFY_SOURCE_PARAMS + * @note VF_SOURCE_PARAMS - debug parameters source line and source file name + * @see VF_SOURCE_PARAMS * @see vf_error */ -void vf_error_func( VERIFY_SOURCE_PARAMS ); +void vf_error_func( VF_SOURCE_PARAMS ); /** * Function allocates an array in memory with elements initialized to zero. * @param number - number of elements * @param element_size - size of element - * @note VERIFY_SOURCE_PARAMS - debug parameters source line and source file name + * @note VF_SOURCE_PARAMS - debug parameters source line and source file name * @return Pointer to allocated memory block. - * @see VERIFY_SOURCE_PARAMS + * @see VF_SOURCE_PARAMS * @see vf_calloc * @note Assertion is raised if number or element_size * are equal to zero or if out of memory error is arisen. * @note Trace is available with argument verifier:memory. */ void *vf_calloc_func( unsigned number, size_t element_size, - VERIFY_SOURCE_PARAMS ); + VF_SOURCE_PARAMS ); /** * Function allocates memory blocks. * @param size - size of memory block - * @note VERIFY_SOURCE_PARAMS - debug parameters source line and source file name + * @note VF_SOURCE_PARAMS - debug parameters source line and source file name * @return Pointer to allocated memory block. - * @see VERIFY_SOURCE_PARAMS + * @see VF_SOURCE_PARAMS * @see vf_malloc * @note Assertion is raised if size is equal to zero * or if out of memory error is arisen. * @note Trace is available with argument verifier:memory. */ -void *vf_malloc_func( size_t size, VERIFY_SOURCE_PARAMS ); +void *vf_malloc_func( size_t size, VF_SOURCE_PARAMS ); /** * Function releases allocated memory blocks. * @param pointer - pointer to allocated block - * @note VERIFY_SOURCE_PARAMS - debug parameters source line and source file name - * @see VERIFY_SOURCE_PARAMS + * @note VF_SOURCE_PARAMS - debug parameters source line and source file name + * @see VF_SOURCE_PARAMS * @see vf_free * @note Assertion is raised if pointer is equal to null. * @note Trace is available with argument verifier:memory. */ -void vf_free_func( void *pointer, VERIFY_SOURCE_PARAMS ); +void vf_free_func( void *pointer, VF_SOURCE_PARAMS ); /** * Function reallocates memory blocks. * @param pointer - pointer to allocated block * @param resize - new size of memory block - * @note VERIFY_SOURCE_PARAMS - debug parameters source line and source file name + * @note VF_SOURCE_PARAMS - debug parameters source line and source file name * @return Pointer to reallocated memory block. - * @see VERIFY_SOURCE_PARAMS + * @see VF_SOURCE_PARAMS * @see vf_realloc * @note Assertion is raised if resize is equal to zero * or if out of memory error is arisen. * @note If pointer is equal to null function works like vf_malloc_func. * @note Trace is available with argument verifier:memory. */ -void *vf_realloc_func( void *pointer, size_t resize, VERIFY_SOURCE_PARAMS ); +void *vf_realloc_func( void *pointer, size_t resize, VF_SOURCE_PARAMS ); /** * Function creates memory pool structure. - * @note VERIFY_SOURCE_PARAMS - debug parameters source line and source file name + * @note VF_SOURCE_PARAMS - debug parameters source line and source file name * @return Pointer to created memory pool. - * @see VERIFY_SOURCE_PARAMS + * @see VF_SOURCE_PARAMS * @see vf_create_pool - * @see vf_VerifyPool_t + * @see vf_Pool * @note Trace is available with argument verifier:memory:pool. */ -vf_VerifyPool_t *vf_create_pool_func( VERIFY_SOURCE_PARAMS ); +vf_Pool *vf_create_pool_func( VF_SOURCE_PARAMS ); /** * Function allocates memory blocks in current pool. * @param pool - pointer to memory pool structure * @param size - memory block size - * @note VERIFY_SOURCE_PARAMS - debug parameters source line and source file name + * @note VF_SOURCE_PARAMS - debug parameters source line and source file name * @return Pointer to allocated memory block. - * @see VERIFY_SOURCE_PARAMS - * @see vf_alloc_pool_memory - * @see vf_VerifyPool_t + * @see VF_SOURCE_PARAMS + * @see vf_palloc + * @see vf_Pool * @note Trace is available with argument verifier:memory:pool. */ -void *vf_alloc_pool_memory_func( vf_VerifyPool_t * pool, size_t size, - VERIFY_SOURCE_PARAMS ); +void *vf_palloc_func( vf_Pool *pool, size_t size, VF_SOURCE_PARAMS ); /** * Function cleans given pool. * @param pool - memory pool structure - * @note VERIFY_SOURCE_PARAMS - debug parameters source line and source file name - * @see VERIFY_SOURCE_PARAMS - * @see vf_clean_pool_memory - * @see vf_VerifyPool_t + * @note VF_SOURCE_PARAMS - debug parameters source line and source file name + * @see VF_SOURCE_PARAMS + * @see vf_clean_pool + * @see vf_Pool * @note Trace is available with argument verifier:memory:pool. */ -void -vf_clean_pool_memory_func( vf_VerifyPool_t * pool, VERIFY_SOURCE_PARAMS ); +void vf_clean_pool_func( vf_Pool *pool, VF_SOURCE_PARAMS ); /** * Function releases memory from given pool. * @param pool - memory pool structure - * @note VERIFY_SOURCE_PARAMS - debug parameters source line and source file name - * @see VERIFY_SOURCE_PARAMS + * @note VF_SOURCE_PARAMS - debug parameters source line and source file name + * @see VF_SOURCE_PARAMS * @see vf_delete_pool - * @see vf_VerifyPool_t + * @see vf_Pool * @note Trace is available with argument verifier:memory:pool. */ -void vf_delete_pool_func( vf_VerifyPool_t * pool, VERIFY_SOURCE_PARAMS ); - -//=========================================================== -// Code instruction structures. -//=========================================================== - -/** - * A byte of a bytecode. - */ -struct vf_BCode -{ - unsigned m_instr; ///< a number + 1 of code instruction at - ///< vf_Context.m_code - unsigned m_mark:1; ///< control flow branch flag -}; - -/** - * Valid types structure. - */ -struct vf_ValidType -{ - unsigned number; ///< number of types - const char *string[1]; ///< type array -}; - -/** - * Stack map entry structure. - */ -struct vf_MapEntry -{ - vf_ValidType_t *m_vtype; ///< valid type for reference - union - { - unsigned m_new; ///< program count of opcode new for uninitialized - unsigned m_pc; ///< program count of return address for subroutine - }; - union - { - unsigned short m_local; ///< number of local variable - unsigned short m_index; ///< constant pool index for access check - }; - unsigned short m_type:5; ///< stack map type @see vf_MapType_t - unsigned short m_ctype:4; ///< constraint type @see vf_CheckConstraint_t - unsigned short m_is_local:1; ///< local variable modify flag - ///< true - modify local, false - modify stack -}; - -/** - * Complete struct of bytecode instructions. - */ -struct vf_Code -{ - unsigned char *m_addr; ///< address of bytecode instruction - unsigned *m_off; ///< array of instruction branches - vf_MapEntry_t *m_invector; ///< stack map IN instruction vector - vf_MapEntry_t *m_outvector; ///< stack map OUT instruction vector - unsigned m_offcount; ///< number of instruction branches - unsigned short m_minstack; ///< minimal stack for instruction - unsigned short m_inlen; ///< stack map IN instruction vector length - unsigned short m_outlen; ///< stack map OUT instruction vector length - short m_stack; ///< stack change for instruction - vf_CodeType m_type; ///< instruction flag @see vf_CodeType_t - bool m_basic_block_start:1; ///< begin of a basic block -}; - -/** - * Constant pool parse structure. - */ -union vf_Parse -{ - struct - { - vf_MapEntry_t *m_invector; ///< method IN stack vector - vf_MapEntry_t *m_outvector; ///< method OUT stack vector - const char *m_name; ///< invoked method name - int m_inlen; ///< IN vector length - int m_outlen; ///< OUT vector length - } method; - struct - { - vf_MapEntry_t *f_vector; ///< field type map vector - int f_vlen; ///< field type map vector len - } field; -}; +void vf_delete_pool_func( vf_Pool *pool, VF_SOURCE_PARAMS ); //=========================================================== // Verifier hash table structures. @@ -505,7 +564,7 @@ struct vf_HashEntry { const char *key; ///< hash entry key void *data; ///< pointer to hash entry data - vf_HashEntry_t *next; ///< next hash entry + vf_HashEntry *next; ///< next hash entry }; /** @@ -513,7 +572,7 @@ struct vf_HashEntry */ struct vf_Hash { - public: +public: /** * Hash table constructor. * @note Function allocates memory for hash pool and hash table. @@ -525,7 +584,7 @@ struct vf_Hash * @param pool - external memory pool * @note Function allocates memory for hash pool and hash table. */ - vf_Hash ( vf_VerifyPool_t * pool ); + vf_Hash ( vf_Pool *pool ); /** * Hash table destructor. @@ -537,41 +596,41 @@ struct vf_Hash * Function looks up hash entry which is identical to given hash key. * @param key - given hash key * @return Hash entry which is identical to given hash key. - * @see vf_HashEntry_t + * @see vf_HashEntry */ - vf_HashEntry_t *Lookup( const char *key ); + vf_HashEntry *Lookup( const char *key ); /** * Function looks up hash entry which is identical to given hash key. * @param key - given hash key * @param len - hash key length * @return Hash entry which is identical to given hash key. - * @see vf_HashEntry_t + * @see vf_HashEntry */ - vf_HashEntry_t *Lookup( const char *key, unsigned len ); + vf_HashEntry *Lookup( const char *key, size_t len ); /** * Function creates hash entry which is identical to given hash key. * @param key - given hash key * @return Hash entry which are identical to given hash key. - * @see vf_HashEntry_t + * @see vf_HashEntry * @note Created hash key and hash entry is allocated into hash memory pool. */ - vf_HashEntry_t *NewHashEntry( const char *key ); + vf_HashEntry *NewHashEntry( const char *key ); /** * Function creates hash entry which is identical to given hash key. * @param key - given hash key * @param len - hash key length * @return Hash entry which are identical to given hash key. - * @see vf_HashEntry_t + * @see vf_HashEntry * @note Created hash key and hash entry is allocated into hash memory pool. */ - vf_HashEntry_t *NewHashEntry( const char *key, size_t len ); + vf_HashEntry *NewHashEntry( const char *key, size_t len ); private: - vf_VerifyPool_t * m_pool; ///< hash memory pool - vf_HashEntry_t **m_hash; ///< hash table + vf_Pool *m_pool; ///< hash memory pool + vf_HashEntry **m_hash; ///< hash table const unsigned HASH_SIZE; ///< hash table size bool m_free; ///< need to free pool @@ -581,9 +640,9 @@ struct vf_Hash * @param key - checked key * @return If keys are identical function returns true, * else returns false. - * @see vf_HashEntry_t + * @see vf_HashEntry */ - bool CheckKey( vf_HashEntry_t * hash_entry, const char *key ); + bool CheckKey( vf_HashEntry *hash_entry, const char *key ); /** * Function checks key identity. @@ -592,9 +651,9 @@ struct vf_Hash * @param len - checked key length * @return If keys are identical function returns true, * else returns false. - * @see vf_HashEntry_t + * @see vf_HashEntry */ - bool CheckKey( vf_HashEntry_t * hash_entry, const char *key, size_t len ); + bool CheckKey( vf_HashEntry *hash_entry, const char *key, size_t len ); /** * Hash function. @@ -624,9 +683,9 @@ struct vf_TypeConstraint const char *source; ///< constraint source class name const char *target; ///< constraint target class name method_handler method; ///< constraint for method - vf_TypeConstraint_t *next; ///< next constraint + vf_TypeConstraint *next; ///< next constraint unsigned short index; ///< constant pool index - unsigned short check_type; ///< constraint check type @see vf_CheckConstraint_t + unsigned short check_type; ///< constraint check type @see vf_CheckConstraint }; /** @@ -634,7 +693,7 @@ struct vf_TypeConstraint */ struct vf_TypePool { - public: +public: /** * Type constraint collection constructor. * @note Function allocates memory for collection memory pool and hash table. @@ -652,17 +711,17 @@ struct vf_TypePool * @param type - given class name * @param len - class name length * @return Created valid type structure. - * @see vf_ValidType_t + * @see vf_ValidType */ - vf_ValidType_t *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. * @param array - array valid type * @return Created valid type of a given array element. - * @see vf_ValidType_t + * @see vf_ValidType */ - vf_ValidType_t *NewArrayElemType( vf_ValidType_t * array ); + vf_ValidType *NewArrayElemType( vf_ValidType *array ); /** * Function checks types and create constraints if it's necessarily. @@ -673,12 +732,12 @@ struct vf_TypePool * @return If available type satisfy to required type * function will return false (is it error?), * else will return true (is it error?). - * @see vf_ValidType_t - * @see vf_CheckConstraint_t + * @see vf_ValidType + * @see vf_CheckConstraint */ - bool CheckTypes( vf_ValidType_t * required, - vf_ValidType_t * available, - unsigned short index, vf_CheckConstraint_t check_type ); + bool CheckTypes( vf_ValidType *required, + vf_ValidType *available, + unsigned short index, vf_CheckConstraint check_type ); /** * Function merges two valid types. @@ -686,10 +745,9 @@ struct vf_TypePool * @param second - second merged type * @return Function returns created valid type corresponding with merge result. * @return Function returns NULL if vector wasn't merged. - * @see vf_ValidType_t + * @see vf_ValidType */ - vf_ValidType_t *MergeTypes( vf_ValidType_t * first, - vf_ValidType_t * second ); + vf_ValidType *MergeTypes( vf_ValidType *first, vf_ValidType *second ); /** * Function dumps constraint collection in stream. @@ -701,9 +759,9 @@ struct vf_TypePool /** * Function returns the methods constraints array. * @return Array of the methods constraints. - * @see vf_TypeConstraint_t + * @see vf_TypeConstraint */ - vf_TypeConstraint_t *GetClassConstraint(); + vf_TypeConstraint *GetClassConstraint(); /** * Function sets current context method. @@ -717,116 +775,129 @@ struct vf_TypePool * @param source - source class name * @param index - constant pool index * @param check_type - constraint check type - * @see vf_CheckConstraint_t + * @see vf_CheckConstraint */ void SetRestriction( const char *target, const char *source, unsigned short index, - vf_CheckConstraint_t check_type ); + vf_CheckConstraint check_type ); private: - vf_VerifyPool_t * m_pool; ///< collection memory pool - vf_Hash_t *m_Hash; ///< hash table + vf_Pool *m_pool; ///< collection memory pool + vf_Hash *m_Hash; ///< hash table method_handler m_method; ///< current context method - vf_TypeConstraint_t *m_restriction; ///< array of the class constraints + vf_TypeConstraint *m_restriction; ///< array of the class constraints }; // vf_TypePool //=========================================================== // Verifier type constraint structures. //=========================================================== -void vf_clean_pool_memory_func( vf_VerifyPool_t * pool, - VERIFY_SOURCE_PARAMS ); +void vf_clean_pool_func( vf_Pool *pool, VF_SOURCE_PARAMS ); /** - * Structure of verifier context + * Verification context. */ struct vf_Context { - public: +public: /** * Verifier context constructor */ vf_Context ():m_class( NULL ), m_type( NULL ), m_error( NULL ), - m_method( NULL ), m_graph( NULL ), m_pool( NULL ), m_code( NULL ), - m_codeNum( 0 ), m_nodeNum( 0 ), m_edgeNum( 0 ) + m_method( NULL ), m_graph( NULL ), m_pool( NULL ), m_instr( NULL ), + m_last_instr( NULL ), m_retnum( 0 ), m_verify_all( false ) { - vf_ContextDump zero1 = { 0 }; vf_ContextVType zero2 = { 0 }; - - m_dump = zero1; m_vtype = zero2; } + void SetMethod( method_handler method ) + { + m_method = method; + + // get method limitations + m_len = method_get_code_length( method ); + m_bytes = method_get_bytecode( m_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( method_get_name( method ), "", 7 ) == 0; + } + /** * Verifier context destructor */ ~vf_Context () { + if( m_pool ) { + vf_delete_pool( m_pool ); + } + if( m_type ) { + delete m_type; + } } /** - * Function clears context. + * Clears context. */ void ClearContext() { m_method = NULL; m_is_constructor = false; m_graph = NULL; - m_code = NULL; + m_instr = NULL; m_bc = NULL; - m_codeNum = 0; - m_nodeNum = 0; - m_edgeNum = 0; - vf_clean_pool_memory( m_pool ); + m_last_instr = NULL; + m_retnum = 0; + vf_clean_pool( m_pool ); } // vf_ClearContext - public: - vf_TypePool * m_type; ///< context type constraint collection +public: + vf_TypePool *m_type; ///< context type constraint collection char *m_error; ///< context error message - vf_Graph *m_graph; ///< context control flow graph - vf_VerifyPool_t *m_pool; ///< context memory pool - vf_Code_t *m_code; ///< context code instruction of method - vf_BCode_t *m_bc; ///< bytecode to code mapping + vf_Graph *m_graph; ///< control flow graph + vf_Pool *m_pool; ///< memory pool + vf_InstrHandle m_instr; ///< method instructions + vf_InstrHandle m_last_instr; ///< the pointer follows + ///< the last instruction at m_instr + vf_BCode *m_bc; ///< bytecode to instruction mapping + unsigned m_retnum; ///< a number of rets + + /** + * Cached method info. + */ class_handler m_class; ///< context class method_handler m_method; ///< context method - unsigned m_codeNum; ///< code instruction number - unsigned m_nodeNum; ///< graph node number - unsigned m_edgeNum; ///< graph edge number + unsigned m_len; ///< bytecode length + unsigned char *m_bytes; ///< bytecode location + unsigned short m_maxstack; ///< max stack length + unsigned short m_maxlocal; ///< max local number bool m_is_constructor; ///< true if the ///< method is a constructor + 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_buf; ///< used to store intermediate stack states + ///< during data flow analysis + + bool m_verify_all; ///< if true need to verify more checks + /** - * Structure contains useful valid types + * Contains useful valid types. */ struct vf_ContextVType { - vf_ValidType_t *m_class; ///< context a given class valid type - vf_ValidType_t *m_throwable; ///< context java/lang/Throwable valid type - vf_ValidType_t *m_object; ///< context java/lang/Object valid type - vf_ValidType_t *m_array; ///< context [Ljava/lang/Object; valid type - vf_ValidType_t *m_clone; ///< context java/lang/Cloneable valid type - vf_ValidType_t *m_serialize; ///< context java/io/Serializable valid type + vf_ValidType *m_class; ///< context a given class valid type + vf_ValidType *m_throwable; ///< context java/lang/Throwable valid type + vf_ValidType *m_object; ///< context java/lang/Object valid type + vf_ValidType *m_array; ///< context [Ljava/lang/Object; valid type + vf_ValidType *m_clone; ///< context java/lang/Cloneable valid type + vf_ValidType *m_serialize; ///< context java/io/Serializable valid type } m_vtype; - - /** - * Structure contains debug dump flags - */ - struct vf_ContextDump - { - unsigned m_verify:1; ///< verify all flag - unsigned m_with_subroutine:1; ///< verified method has subroutine - unsigned m_constraint:1; ///< dump type constraints for class - unsigned m_code:1; ///< print code array in stream - unsigned m_graph:1; ///< print original control flow graph - unsigned m_mod_graph:1; ///< print modified control flow graph - unsigned m_dot_graph:1; ///< dump original control flow graph in file in DOT format - unsigned m_dot_mod_graph:1; ///< dump modified control flow graph in file in DOT format - unsigned m_node_vector:1; ///< print data flow node vectors - unsigned m_code_vector:1; ///< print data flow node code instruction vectors - unsigned m_merge_vector:1; ///< print result of merge data flow vectors - } m_dump; - }; // struct vf_Context //=========================================================== @@ -834,36 +905,15 @@ struct vf_Context //=========================================================== /** - * Head structure of memory pool. - */ -struct vf_VerifyPool -{ - vf_VerifyPoolInternal_t *m_pool; ///< pool entry - size_t m_memory; ///< allocated memory size - size_t m_used; ///< used memory size - size_t m_maxuse; ///< max used memory size -}; - -/** - * Internal structure of memory pool. - */ -struct vf_VerifyPoolInternal -{ - void *m_memory; ///< pool entry memory - char *m_free; ///< free space in pool entry - vf_VerifyPoolInternal_t *m_next; ///< next pool entry - size_t m_freesize; ///< size of free space in pool entry -}; - -/** * Structure of class loader constraint data. */ struct vf_ClassLoaderData { - vf_VerifyPool_t *pool; ///< constraint memory pool - vf_Hash_t *string; ///< string pool hash table + vf_Pool *pool; ///< constraint memory pool + vf_Hash *string; ///< string pool hash table }; + //=========================================================== // Verifier debug data //=========================================================== @@ -871,9 +921,9 @@ struct vf_ClassLoaderData /** * Array of opcode names. Available in debug mode. */ -#if _VERIFY_DEBUG +#if _VF_DEBUG extern const char *vf_opcode_names[]; -#endif // _VERIFY_DEBUG +#endif // _VF_DEBUG //=========================================================== // Verifier functions. @@ -881,12 +931,12 @@ extern const char *vf_opcode_names[]; /** * Function creates bytecode control flow graph. - * @param context - verifier context + * @param ctx - verifier context * @return Result of graph creation. - * @see vf_Context_t - * @see Verifier_Result + * @see vf_Context + * @see vf_Result */ -Verifier_Result vf_create_graph( vf_Context_t * context ); +vf_Result vf_create_graph( vf_Context *ctx ); /** * Checks control flow and data flow of graph. @@ -895,16 +945,16 @@ Verifier_Result vf_create_graph( vf_Cont * * @return a result of graph checks */ -Verifier_Result vf_check_graph( vf_Context_t * context ); +vf_Result vf_check_graph( vf_Context *ctx ); /** * Function provides data flow checks of verifier graph structure. - * @param context - verifier context + * @param ctx - verifier context * @return Check result. - * @see vf_Context_t - * @see Verifier_Result + * @see vf_Context + * @see vf_Result */ -Verifier_Result vf_check_graph_data_flow( vf_Context_t * context ); +vf_Result vf_check_graph_data_flow( vf_Context *ctx ); /** * Function parses method, class or field descriptors. @@ -917,30 +967,27 @@ Verifier_Result vf_check_graph_data_flow void vf_parse_description( const char *descr, int *inlen, int *outlen ); /** - * Function parses descriptor and sets input and output data flow vectors. - * @param descr - descriptor of method, class or field - * @param inlen - number of entries for IN data flow vector - * @param add - additional number of entries to IN data flow vector - * @param outlen - number of entries for OUT data flow vector (for method) - * @param invector - pointer to IN data flow vector - * @param outvector - pointer to OUT data flow vector - * @param context - verifier context + * Parses a descriptor and sets input and output data flow vectors. + * @param descr a descriptor of method, class or field + * @param inlen a number of entries for IN data flow vector + * @param add an additional number of entries to IN data flow vector + * @param outlen a number of entries for OUT data flow vector (for method) + * @param invector a pointer to IN data flow vector + * @param outvector a pointer to OUT data flow vector + * @param ctx a verifier context * @note Assertion is raised if descr is equal to null. * @note Parameter invector may be equal to null * if sum of parameters inlen + add is equal to zero. * @note Parameter outvector may be equal to null * if parameter outlen is equal to zero. - * @see vf_MapEntry_t - * @see vf_Context_t */ void vf_set_description_vector( const char *descr, int inlen, int add, int outlen, - vf_MapEntry_t ** invector, - vf_MapEntry_t ** outvector, - vf_Context_t * context ); + vf_MapEntry **invector, + vf_MapEntry **outvector, vf_ContextHandle ctx ); /** * Gets a class name from a constant pool. @@ -960,35 +1007,33 @@ vf_get_cp_class_name( class_handler klas } // vf_get_cp_class_name /** - * Function creates valid type by given class name. - * @param class_name - class name - * @param context - verifier context - * @return Valid type structure corresponding to given class name. - * @see vf_ValidType_t - * @see vf_Context_t + * Creates a valid type from a given class name. + * @param class_name a class name + * @param ctx a verifier context + * @return a valid type structure corresponding to the given class name */ -vf_ValidType_t *vf_create_class_valid_type( const char *class_name, - vf_Context_t * context ); +vf_ValidType *vf_create_class_valid_type( const char *class_name, + vf_ContextHandle ctx ); /** * Function provides constraint checks for current class. - * @param context - verifier context + * @param ctx - verifier context * @return Check result. * @note Provides only checks with loaded classes. * @note All unchecked constraints are saved to class loader verify data. - * @see vf_Context_t - * @see Verifier_Result + * @see vf_Context + * @see vf_Result */ -Verifier_Result vf_check_class_constraints( vf_Context_t * context ); +vf_Result vf_check_class_constraints( vf_Context *ctx ); /** * Function compares two valid types. * @param type1 - first checked type * @param type2 - second checked type * @return If types are equal returns true, else returns false. - * @see vf_ValidType_t + * @see vf_ValidType */ -bool vf_is_types_equal( vf_ValidType_t * type1, vf_ValidType_t * type2 ); +bool vf_is_types_equal( vf_ValidType *type1, vf_ValidType *type2 ); /** * Function checks access to protected field/method. @@ -999,42 +1044,41 @@ bool vf_is_types_equal( vf_ValidType_t * * @param instance_name - name of instance class * @param index - constant pool index * @param check_type - access check type - * @param ctex - verifier context + * @param ctx - verifier context * @return Check result. * @note Provides only checks with loaded classes. - * @see vf_CheckConstraint_t - * @see vf_Context_t - * @see Verifier_Result - */ -Verifier_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_t check_type, // access check type - vf_Context_t * ctex ); // verifier context + * @see vf_CheckConstraint + * @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 /** - * Sets error message of verifier. + * Sets error message of a verifier. * * @param[in] stream stringstream object with a message - * @param[in] ctex a verifier context + * @param[in] ctx a verifier context */ static inline void -vf_set_error_message( stringstream & stream, vf_Context_t * ctex ) +vf_set_error_message( stringstream & stream, vf_Context *ctx ) { - if( ctex->m_error ) { + if( ctx->m_error ) { // free old message - vf_free( ctex->m_error ); + vf_free( ctx->m_error ); } // create message size_t len = stream.str().length(); if( len ) { - ctex->m_error = (char*)vf_malloc( len + 1 ); - memcpy( ctex->m_error, stream.str().c_str(), len ); - ctex->m_error[len] = '\0'; + ctx->m_error = (char*)vf_malloc( len + 1 ); + memcpy( ctx->m_error, stream.str().c_str(), len ); + ctx->m_error[len] = '\0'; } else { - ctex->m_error = NULL; + ctx->m_error = NULL; } - return; } // vf_set_error_message /** @@ -1045,25 +1089,25 @@ vf_set_error_message( stringstream & str * @return true if a class version is less than 1.4 */ static inline bool -vf_is_class_version_14( vf_Context_t * context ) +vf_is_class_version_14( vf_ContextHandle ctx ) { - return ( class_get_version( context->m_class ) < 49 ) ? true : false; + return ( class_get_version( ctx->m_class ) < 49 ) ? true : false; } // vf_is_class_version_14 /** * Returns branch target for a given branch number. * - * @param[in] code a reference to instruction + * @param[in] instr a reference to instruction * @param[in] branch_num a branch number * * @return an absolute bytecode position to which the executuion * branches */ static inline int -vf_get_code_branch( vf_Code_t * code, unsigned branch_num ) +vf_get_instr_branch( vf_InstrHandle instr, unsigned branch_num ) { - assert( branch_num < code->m_offcount ); - return code->m_off[branch_num]; + assert( branch_num < instr->m_offcount ); + return instr->m_off[branch_num]; } // vf_get_instruction_branch /** @@ -1074,14 +1118,11 @@ vf_get_code_branch( vf_Code_t * code, un * @param[in] pool memory pool */ static inline void -vf_new_vector( vf_MapEntry_t ** vector, unsigned len, vf_VerifyPool_t * pool ) +vf_new_vector( vf_MapEntry **vector, unsigned len, vf_Pool *pool ) { // create new vector - ( *vector ) = (vf_MapEntry_t*) vf_alloc_pool_memory( pool, - len * - sizeof - ( vf_MapEntry_t ) ); - return; + ( *vector ) = (vf_MapEntry*)vf_palloc( pool, + len * sizeof( vf_MapEntry ) ); } // vf_new_vector /** @@ -1092,8 +1133,8 @@ vf_new_vector( vf_MapEntry_t ** vector, * @param[in] type reference type */ static inline void -vf_set_vector_stack_entry_ref( vf_MapEntry_t * vector, - unsigned num, vf_ValidType_t * 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; @@ -1101,14 +1142,44 @@ vf_set_vector_stack_entry_ref( vf_MapEnt } // vf_set_vector_stack_entry_ref /** + * Calculates an index of instruction. + * @param[in] pc a bytecode index at instruction start + * @param[in] ctx a verification context + * @return an instruction index + */ +static inline unsigned +vf_bc_to_instr_index( unsigned short pc, vf_ContextHandle ctx ) +{ + vf_InstrHandle instr = ctx->m_bc[pc].m_instr; + assert( instr ); + return instr - ctx->m_instr; +} + +/** + * For a given instruction gets a start pointer of the next instruction or the + * pointer which follows the last bytecode of the method for the last instruction. + * @param[in] instr an instruction handle + * @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 ) +{ + if( instr + 1 == ctx->m_last_instr ) { + return ctx->m_bytes + ctx->m_len; + } + return ( instr + 1 )->m_addr; +} + +/** * Calls destructor of graph, if any. * * @param[in] context a context of verifier */ -void vf_free_graph( vf_Context_t * context ); +void vf_free_graph( vf_Context *context ); /** - * Inline subroutines in the call graph. + * Mark subroutine instr. * *

Here is the algorithm sketch: we define subroutine boundaries with * simplified data flow analysis and duplicate subroutine nodes @@ -1116,10 +1187,19 @@ void vf_free_graph( vf_Context_t * conte * wiki * page.

* - * @param[in] context a verifier context + * @param ctx a verifier context + * @return VER_OK if no graph structure inconsistencies were detected during marking, + * an error code otherwise + */ +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, * an error code otherwise */ -Verifier_Result vf_inline_subroutines( vf_ContextHandle context ); +vf_Result vf_inline_subroutines( vf_Context *ctx ); #endif // _VERIFIER_REAL_H_ diff -pu 9/trunk/working_vm/vm/vmcore/src/verifier/ver_subroutine.cpp 91/trunk/working_vm/vm/vmcore/src/verifier/ver_subroutine.cpp --- 9/trunk/working_vm/vm/vmcore/src/verifier/ver_subroutine.cpp 2007-03-20 18:34:51.400298600 +0300 +++ 91/trunk/working_vm/vm/vmcore/src/verifier/ver_subroutine.cpp 2007-03-21 04:10:17.578700800 +0300 @@ -16,24 +16,564 @@ */ #include "ver_subroutine.h" -static vf_Result MarkTopcode(vf_ContextHandle context, vf_NodeHandle nh) +#ifdef _VF_DEBUG +/** + * Gets a subroutine number for debugging purposes. + */ +unsigned vf_get_sub_num(vf_NodeHandle node, vf_ContextHandle ctx) +{ + unsigned num = node->m_sub - ctx->m_sub_ctx->m_subs; + assert(num < ctx->m_sub_ctx->m_subnum); + return num; +} +#endif // _VF_DEBUG + + +/** + * Allocates memory for subroutine context. + * @param count a number of subroutines + */ +static void CreateSubs(vf_Context *ctx) { + vf_Pool *pool = ctx->m_pool; + + vf_SubContext *csub = (vf_SubContext *) vf_palloc(pool, + sizeof(vf_SubContext)); + ctx->m_sub_ctx = csub; + csub->m_pool = pool; + csub->m_subs = (vf_Sub *) vf_palloc(pool, ctx->m_retnum * sizeof(vf_Sub)); + csub->m_path = + (vf_NodeHandle *) vf_palloc(pool, + ctx->m_graph->GetNodeCount() * sizeof(vf_NodeHandle)); +} // CreateSubs + + +/** + * Adds a new subroutine into subroutine array. + * @param ret_node a node containing a corresponding ret + * @return a sub handle + */ +static vf_Sub *AddSub(vf_NodeHandle ret_node, vf_SubContext * csub) +{ + vf_Sub *sub = &csub->m_subs[csub->m_subnum++]; + sub->m_ret = ret_node; + return sub; +} // AddSub + + +#ifdef _VF_DEBUG +void vf_Graph::DumpSub(vf_SubHandle sub) +{ + if (sub) { + VF_DEBUG("Subroutine:"); + if (sub->m_entry) { + VF_DEBUG(" Entry node: " << vf_Graph:: + GetNodeNum(sub->m_entry)); + } else { + VF_DEBUG(" Entry node undefined"); + } + if (sub->m_ret) { + VF_DEBUG(" Return node: " << vf_Graph::GetNodeNum(sub->m_ret)); + } else { + VF_DEBUG(" Return node undefined"); + } + } +} // vf_Graph::DumpSub +#endif // _VF_DEBUG + +static vf_Result +ResolveSubroutineEntryPoint(vf_Sub *sub, unsigned pathlen, vf_Context *ctx) +{ + // a pointer to the first node in the path + vf_NodeHandle *p_node; + + //initialize vector + vf_MapVector *map = ctx->m_map; + + if (ctx->m_sub_ctx->m_pathfork) { + // continue with previous map vector + p_node = ctx->m_sub_ctx->m_path + ctx->m_sub_ctx->m_pathfork; + } else { + p_node = ctx->m_sub_ctx->m_path; + map->m_number = ctx->m_maxlocal; + for (unsigned index = 0; index < map->m_number; index++) { + map->m_local[index].m_type = SM_ANY; + } + + map->m_depth = (*p_node)->m_inmap.m_depth; + for (unsigned 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 = (*p_node)->m_start->m_addr - ctx->m_bytes; + } + + for (unsigned index = ctx->m_sub_ctx->m_pathfork; + index < pathlen; index++, p_node++) { + vf_Result result = vf_set_node_out_vector(*p_node, map, ctx); + if (result != VER_OK) { + return result; + } + } + + sub->m_entry = ctx->m_graph->GetNodeFromBytecodeIndex(ctx->m_buf->m_pc); return VER_OK; -} // MarkTopcode +} // ResolveSubroutineEntryPoint -static vf_Result InlineMarkedSubNodes(vf_ContextHandle context) +static vf_Result +MarkCode(vf_Node *node, unsigned pathlen, unsigned stack_depth, + vf_Context *ctx); + +static vf_Result +MergeSubMarks(vf_Node *node, vf_NodeHandle next_node, vf_Context *ctx) { + if (next_node->m_sub) { + VF_TRACE("sub.mark", "sub[" << ctx->m_graph->GetNodeNum(node) + << "] := sub[" << ctx->m_graph->GetNodeNum(next_node-> + m_sub->m_ret) + << "] (" << vf_get_sub_num(next_node, ctx) << ")"); + if (node->m_sub == NULL) { + node->m_sub = next_node->m_sub; + } else if (node->m_sub != next_node->m_sub) { + VF_REPORT(ctx, + "A subroutine splits execution into " + "several ret instructions"); + return VER_ErrorJsrMultipleRet; + } + } return VER_OK; -} // InlineMarkedSubNodes +} // MergeSubMarks -vf_Result vf_inline_subroutines(vf_ContextHandle context) + +static vf_Result +FollowEdge(vf_Node *node, vf_Node *next_node, unsigned pathlen, + unsigned stack_depth, vf_Context *ctx) +{ + vf_Result r = MarkCode((vf_Node *) next_node, pathlen, stack_depth, ctx); + if (VER_OK != r) { + return r; + } + + return MergeSubMarks(node, next_node, ctx); +} // FollowEdge + +static vf_Result +FollowJsrEdge(vf_Node *node, vf_Node *next_node, + unsigned pathlen, unsigned stack_depth, vf_Context *ctx) { + unsigned pathfork = (TOP_MARK == pathlen) ? 0 : pathlen; + vf_Result r = MarkCode(next_node, pathfork, stack_depth, ctx); + if (VER_OK != r) { + return r; + } + + if (next_node->m_sub) { + if (next_node->m_sub->m_entry != next_node) { + VF_REPORT(ctx, "Subroutines merge their execution"); + return VER_ErrorDataFlow; + } + + stack_depth = next_node->m_sub->m_ret->m_outmap.m_depth; + ctx->m_sub_ctx->m_pathfork = pathfork; + + // select and check a next node + next_node = node + 1; + if (VF_NODE_END_ENTRY == next_node->m_type) { + VF_REPORT(ctx, "Falling off the end of the code"); + return VER_ErrorBranch; + } + assert(VF_NODE_CODE_RANGE == next_node->m_type); - vf_Result r = MarkTopcode(context, context->m_graph->GetFirstNode()); + r = MarkCode(next_node, pathlen, stack_depth, ctx); + ctx->m_sub_ctx->m_pathfork = 0; + if (VER_OK != r) { + return r; + } + } + + return MergeSubMarks(node, next_node, ctx); if (VER_OK != r) { return r; } +} // FollowJsrEdge + + +static vf_Result +MarkCode(vf_Node *node, unsigned pathlen, unsigned stack_depth, + vf_Context *ctx) +{ + vf_Graph *graph = ctx->m_graph; + vf_EdgeHandle outedge = node->m_outedge; + vf_Result r; + + vf_Result result = vf_check_node_stack_depth(node, stack_depth, ctx); + if (result != VER_Continue) { + return result; + } + VF_TRACE("sub.mark", "Processing node " << graph->GetNodeNum(node)); + + if (pathlen != TOP_MARK) { + assert(pathlen < graph->GetNodeCount()); + ctx->m_sub_ctx->m_path[pathlen++] = node; + } + + if (VF_NODE_CODE_RANGE == node->m_type) { + vf_InstrType last_instr_type = + vf_get_last_instruction_type(node, ctx); + + if (VF_INSTR_RET == last_instr_type) { + vf_Sub *sub = AddSub(node, ctx->m_sub_ctx); + node->m_sub = sub; + r = ResolveSubroutineEntryPoint(sub, pathlen, ctx); + if (VER_OK != r) { + return r; + } + } else if (VF_INSTR_JSR == last_instr_type) { + vf_NodeHandle next_node; + for (; outedge; outedge = outedge->m_outnext) { + next_node = outedge->m_end; + if (VF_NODE_HANDLER == next_node->m_type) { + r = FollowEdge(node, (vf_Node *) outedge->m_end, pathlen, + stack_depth, ctx); + if (VER_OK != r) { + return r; + } + } else { + break; + } + } + assert(VF_NODE_CODE_RANGE == next_node->m_type); + assert(!outedge->m_outnext); + return FollowJsrEdge(node, (vf_Node *) outedge->m_end, pathlen, + stack_depth, ctx); + } + } - r = InlineMarkedSubNodes(context); + for (; outedge; outedge = outedge->m_outnext) { + r = FollowEdge(node, (vf_Node *) outedge->m_end, pathlen, stack_depth, + ctx); + if (VER_OK != r) { + return r; + } + } + + return VER_OK; +} // MarkCode + + +vf_Result vf_mark_subroutines(vf_Context *ctx) +{ + vf_Graph *graph = ctx->m_graph; + CreateSubs(ctx); + + vf_Result r = + MarkCode((vf_Node *) ctx->m_graph->GetStartNode(), TOP_MARK, 0, ctx); return r; -} // InlineSubroutines +} // vf_mark_subroutines + + +static vf_Result CalculateSubNums(vf_ContextHandle ctx) +{ + vf_Graph *graph = ctx->m_graph; + graph->ResetNodeIterator(); + while (graph->HasMoreElements()) { + vf_NodeHandle node = graph->GetNextNode(); + + if (node->m_sub) { + vf_Sub *sub = (vf_Sub *) node->m_sub; + sub->m_nodenum++; + sub->m_out_edgenum += node->m_outnum; + } + } + return VER_OK; +} + +static vf_Result AddDupCount(vf_Sub *sub, unsigned &count, vf_Context *ctx) +{ + if (TOP_MARK == sub->m_dupcount) { + VF_REPORT(ctx, "Found a recursive subroutine call sequence"); + return VER_ErrorJsrRecursive; + } + + if (!sub->m_dupcount) { + sub->m_dupcount = TOP_MARK; + + unsigned sum = 0; + for (vf_EdgeHandle inedge = sub->m_entry->m_inedge; + inedge; inedge = inedge->m_innext) { + vf_NodeHandle node = inedge->m_start; + + if (vf_is_jsr_branch(inedge, ctx)) { + assert(!inedge->m_outnext); + if (node->m_sub == NULL) { + sum++; + } else if (node->m_sub != sub) { + AddDupCount((vf_Sub *) node->m_sub, sum, ctx); + } // 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; + } + } + sub->m_dupcount = sum; + } + + count += sub->m_dupcount; + return VER_OK; +} // AddSubDupCount + +static void InlineSubNodes(vf_ContextHandle ctx) +{ + vf_Graph *graph = ctx->m_graph; + vf_Sub *sub; + unsigned sub_index; + + for (sub_index = 0, sub = ctx->m_sub_ctx->m_subs; + sub_index < ctx->m_sub_ctx->m_subnum; sub_index++, sub++) { + sub->m_nodes = + (vf_NodeHandle *) vf_palloc(ctx->m_sub_ctx->m_pool, + sub->m_nodenum * sizeof(vf_NodeHandle)); + } + + // populate subroutine node get the next node after the start node + vf_Node *node = (vf_Node *) graph->GetStartNode() + 1; + for (; VF_NODE_END_ENTRY != node->m_type; node++) { + if (node->m_sub) { + vf_Sub *sub = (vf_Sub *) node->m_sub; + node->m_nodecount = sub->m_index; + sub->m_nodes[sub->m_index++] = node; + } + } + + // clear sub indices + for (sub_index = 0, sub = ctx->m_sub_ctx->m_subs; + sub_index < ctx->m_sub_ctx->m_subnum; sub_index++, sub++) { + assert(sub->m_nodenum == sub->m_index); + sub->m_index = 0; + } + + // duplicate subroutine nodes + for (sub_index = 0, sub = ctx->m_sub_ctx->m_subs; + sub_index < ctx->m_sub_ctx->m_subnum; sub_index++, sub++) { + + vf_NodeHandle *p_node = sub->m_nodes; + vf_NodeHandle new_node; + for (unsigned node_index = 0; node_index < sub->m_nodenum; + node_index++, p_node++) { + + for (unsigned index = 1; index < sub->m_dupcount; index++) { + new_node = ctx->m_graph->NewNode(*p_node); + VF_TRACE("sub.inline", + "Copied node " << graph->GetNodeNum(*p_node) + << " to " << graph->GetNodeNum(new_node)); + } + + } + if (sub->m_dupcount > 1) { + sub->m_copies = + (vf_Node *) new_node - (sub->m_dupcount - + 1) * sub->m_nodenum + 1; + } + } + assert(0 == ctx->m_graph->HasMoreNodeSpace()); + +} // InlineSubNodes + +/** + * Redirects subroutine calls to separate subroutine copies. + */ +static void InlineInEdges(vf_ContextHandle ctx) +{ + vf_Graph *graph = ctx->m_graph; + + vf_Sub *sub = ctx->m_sub_ctx->m_subs; + for (unsigned sub_index = 0; sub_index < ctx->m_sub_ctx->m_subnum; + sub_index++, sub++) { + + sub->m_nexts = (vf_Node **) vf_palloc(ctx->m_sub_ctx->m_pool, + sub->m_dupcount * sizeof(vf_Node *)); + vf_NodeHandle sub_entry_copy = + sub->m_copies + sub->m_entry->m_nodecount * (sub->m_dupcount - + 1) - 1; + vf_EdgeHandle *p_next_edge = + (vf_EdgeHandle *) & sub->m_entry->m_inedge; + vf_Edge *inedge = (vf_Edge *) sub->m_entry->m_inedge; + while (inedge) { + if (vf_is_jsr_branch(inedge, ctx)) { + if (sub->m_index) { + assert(sub->m_copies); + assert(sub->m_dupcount); + // remove the edge from the list + *p_next_edge = inedge->m_innext; + // redirect jsr edge to correspondent subroutine copy + inedge->m_end = sub_entry_copy + sub->m_index; + } + // store return point + vf_Node *next_node = (vf_Node *) inedge->m_start + 1; + assert(VF_NODE_CODE_RANGE == next_node->m_type); + sub->m_nexts[sub->m_index++] = next_node; + } + p_next_edge = &inedge->m_innext; + inedge = (vf_Edge *) inedge->m_innext; + } + assert(sub->m_index); // there was at least one branch + } +} // InlineInEdges + +/** + * Subroutine calls are redirected to correspondent subroutine copies, + * other edges are just duplicated. + */ +static void InlineOutEdges(vf_ContextHandle ctx) +{ + vf_Graph *graph = ctx->m_graph; + + vf_Sub *sub = ctx->m_sub_ctx->m_subs; + for (unsigned sub_index = 0; sub_index < ctx->m_sub_ctx->m_subnum; + sub_index++, sub++) { + + if (!sub->m_copies) { + continue; + } + + vf_Node *copy = sub->m_copies; + for (unsigned node_index = 0; node_index < sub->m_nodenum; + 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) { + vf_NodeHandle end_node = outedge->m_end; + vf_SubHandle end_sub = end_node->m_sub; + + vf_Node *c = copy; + if (NULL == end_sub) { + for (unsigned index = 1; index < sub->m_dupcount; index++) { + graph->NewEdge(c++, (vf_Node *) end_node); + } + } else if (node->m_sub == end_sub) { + vf_Node *e = sub->m_copies + + end_node->m_nodecount * (sub->m_dupcount - 1); + for (unsigned index = 1; index < sub->m_dupcount; index++) { + graph->NewEdge(c++, e++); + } + } else { + assert(vf_is_jsr_branch(outedge, ctx)); + assert(!outedge->m_outnext); + // an end node + vf_Node *e = end_sub->m_copies + + end_sub->m_entry->m_nodecount * + (end_sub->m_dupcount - 1) - 1; + // 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++) { + // 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_nexts[((vf_Sub *) end_sub)->m_index++] = + n++; + } + } + } + } + } +} // InlineOutEdges + +/** + * Adds a back branch from ret nodes to a node + * which follows the correspondent jsr call node. + */ +static void InlineRetEdges(vf_ContextHandle ctx) +{ + vf_Graph *graph = ctx->m_graph; + vf_Sub *sub = ctx->m_sub_ctx->m_subs; + for (unsigned sub_index = 0; sub_index < ctx->m_sub_ctx->m_subnum; + sub_index++, sub++) { + + vf_Node *ret_node = (vf_Node *) sub->m_ret; + vf_Node **next_node = sub->m_nexts; + graph->NewEdge(ret_node, *(next_node++)); + + vf_Node *ret_node_copy = + sub->m_copies + ret_node->m_nodecount * (sub->m_dupcount - 1); + for (unsigned index = 1; index < sub->m_dupcount; index++) { + // direct ret entry to the return point + graph->NewEdge(ret_node_copy++, *(next_node++)); + } + } + assert(0 == ctx->m_graph->HasMoreEdgeSpace()); +} // InlineRetEdges + +/** + * Checks that every subroutine copy gets its call and + * all edges are created. + */ +static void CheckDupCounts(vf_ContextHandle ctx) +{ +#if _VF_DEBUG + vf_Sub *sub = ctx->m_sub_ctx->m_subs; + for (unsigned sub_index = 0; sub_index < ctx->m_sub_ctx->m_subnum; + sub_index++, sub++) { + assert(sub->m_dupcount == sub->m_index); + } +#endif // _VF_DEBUG +} + +/** + * Calculates a number of additional nodes and edges and adds them + * to the graph. + */ +static vf_Result DoInlining(vf_Context *ctx) +{ + unsigned count; + unsigned nodes = 0, edges = 0; + vf_Sub *sub = ctx->m_sub_ctx->m_subs; + for (unsigned sub_index = 0; sub_index < ctx->m_sub_ctx->m_subnum; + sub_index++, sub++) { + vf_Result r = AddDupCount(sub, count, ctx); + if (VER_OK != r) { + return r; + } + // one copy already present in the graph + nodes += (sub->m_dupcount - 1) * sub->m_nodenum; + edges += (sub->m_dupcount - 1) * sub->m_out_edgenum; + // there is an additional edge from every ret + edges += sub->m_dupcount; + } + ctx->m_graph->CreateEdges(edges); + + if (nodes) { + ctx->m_graph->CreateNodes(nodes); + InlineSubNodes(ctx); + } + InlineInEdges(ctx); + + if (nodes) { + InlineOutEdges(ctx); + } + + CheckDupCounts(ctx); + InlineRetEdges(ctx); + return VER_OK; +} + +vf_Result vf_inline_subroutines(vf_Context *ctx) +{ + if (0 == ctx->m_sub_ctx->m_subnum) { + return VER_OK; + } + + vf_Result r = CalculateSubNums(ctx); + assert(VER_OK == r); + + r = DoInlining(ctx); + if (VER_OK != r) { + return r; + } + + return VER_OK; +} // vf_inline_subroutines diff -pu 9/trunk/working_vm/vm/vmcore/src/verifier/ver_subroutine.h 91/trunk/working_vm/vm/vmcore/src/verifier/ver_subroutine.h --- 9/trunk/working_vm/vm/vmcore/src/verifier/ver_subroutine.h 2007-03-20 18:34:50.929607700 +0300 +++ 91/trunk/working_vm/vm/vmcore/src/verifier/ver_subroutine.h 2007-03-21 04:10:17.428484800 +0300 @@ -16,8 +16,87 @@ */ #include "ver_graph.h" +/** + * @ingroup Handles + * A handle of subroutine verification context. + */ +typedef const struct vf_SubContext *vf_SubContextHandle; + +/** + * Subroutine info. + */ +struct vf_Sub +{ + /** + * A node which starts with subroutine entry point. + */ + vf_NodeHandle m_entry; + /** + * A node which ends with ret instruction. + */ + vf_NodeHandle m_ret; + /** + * A number of different jsr sequences to access + * this subroutine. + */ + unsigned m_dupcount; + /** + * A number of nodes for this subroutine. + */ + unsigned m_nodenum; + /** + * Subroutine nodes. + */ + vf_NodeHandle *m_nodes; + /** + * Subroutine node copies. For each of m_nodenum nodes + * from m_nodes the (m_dupcount - 1) node copies follow + * one by one starting from this pointer. + * NULL when m_dupcount == 1. + */ + vf_Node *m_copies; + /** + * For each of m_dupcount subroutine copies contain a return node for + * this copy. + */ + vf_Node **m_nexts; + /** + * A number of edges between subroutine nodes. + */ + unsigned m_out_edgenum; + /** + * A current duplication index. + */ + unsigned m_index; +}; /** - * Verifier error codes. + * Aggregated subroutine data. */ -typedef Verifier_Result vf_Result; +struct vf_SubContext +{ + /** + * Dedicated memory pool. + */ + vf_Pool *m_pool; + /** + * Descriptors. + */ + vf_Sub *m_subs; + /** + * An number of reachable subroutines, it doesn't include + * unreachable rets. + */ + unsigned m_subnum; + /** + * Path to the current ret. + */ + vf_NodeHandle *m_path; + /** + * After the ret is resolved a ctx->m_map contains a + * correct input map for a node which follows jsr call. This is + * the index of the node in m_path. When this index is 0 we may start + * ret data flow analysis for from the empty map. + */ + unsigned m_pathfork; +}; diff -pu 9/trunk/working_vm/vm/vmcore/src/verifier/ver_utils.cpp 91/trunk/working_vm/vm/vmcore/src/verifier/ver_utils.cpp --- 9/trunk/working_vm/vm/vmcore/src/verifier/ver_utils.cpp 2007-03-20 18:34:53.473341500 +0300 +++ 91/trunk/working_vm/vm/vmcore/src/verifier/ver_utils.cpp 2007-03-21 04:10:19.241091200 +0300 @@ -26,7 +26,7 @@ * Debug flag macros */ // Macro enable verifier memory trace -#define VERIFY_TRACE_MEMORY 0 +#define VF_TRACE_MEMORY 0 /************************************************************ *********************** Hash class ************************* @@ -39,25 +39,21 @@ vf_Hash::vf_Hash ():HASH_SIZE( 127 ), m_free( true ) { m_pool = vf_create_pool(); - m_hash = (vf_HashEntry_t**) vf_alloc_pool_memory( m_pool, - HASH_SIZE * - sizeof - ( vf_HashEntry_t - * ) ); + m_hash = (vf_HashEntry**)vf_palloc( m_pool, + HASH_SIZE * + sizeof(vf_HashEntry*) ); } // vf_Hash::vf_Hash /** * Hash table constructor. */ -vf_Hash::vf_Hash ( vf_VerifyPool_t * pool ):HASH_SIZE( 127 ), +vf_Hash::vf_Hash ( vf_Pool *pool ):HASH_SIZE( 127 ), m_free( false ) { m_pool = pool; - m_hash = (vf_HashEntry_t**) vf_alloc_pool_memory( m_pool, - HASH_SIZE * - sizeof - ( vf_HashEntry_t - * ) ); + m_hash = (vf_HashEntry**)vf_palloc( m_pool, + HASH_SIZE * + sizeof(vf_HashEntry*) ); } // vf_Hash::vf_Hash /** @@ -73,7 +69,7 @@ vf_Hash::~vf_Hash () /** * Function checks key identity. */ -inline bool vf_Hash::CheckKey( vf_HashEntry_t * hash_entry, // checked hash entry +inline bool vf_Hash::CheckKey( vf_HashEntry *hash_entry, // checked hash entry const char *key ) // checked key { if( !strcmp( hash_entry->key, key ) ) { @@ -85,7 +81,7 @@ inline bool vf_Hash::CheckKey( vf_HashEn /** * Function checks key identity. */ -inline bool vf_Hash::CheckKey( vf_HashEntry_t * hash_entry, // checked hash entry +inline bool vf_Hash::CheckKey( vf_HashEntry *hash_entry, // checked hash entry const char *key, // checked key size_t len ) // key length { @@ -127,12 +123,12 @@ inline unsigned vf_Hash::HashFunc( const /** * Function looks up hash entry which is identical to current key. */ -inline vf_HashEntry_t *vf_Hash::Lookup( const char *key ) // hash key +inline vf_HashEntry *vf_Hash::Lookup( const char *key ) // hash key { assert( key ); unsigned hash_index = HashFunc( key ); hash_index = hash_index % HASH_SIZE; - vf_HashEntry_t *hash_entry = m_hash[hash_index]; + vf_HashEntry *hash_entry = m_hash[hash_index]; while( hash_entry != NULL ) { if( CheckKey( hash_entry, key ) ) { return hash_entry; @@ -145,14 +141,14 @@ inline vf_HashEntry_t *vf_Hash::Lookup( /** * Function looks up hash entry which is identical to current key. */ -inline vf_HashEntry_t *vf_Hash::Lookup( const char *key, // hash key - unsigned len ) // key length +inline vf_HashEntry *vf_Hash::Lookup( const char *key, // hash key + size_t len ) // key length { assert( key ); assert( len ); unsigned hash_index = HashFunc( key, len ); hash_index = hash_index % HASH_SIZE; - vf_HashEntry_t *hash_entry = m_hash[hash_index]; + vf_HashEntry *hash_entry = m_hash[hash_index]; while( hash_entry != NULL ) { if( CheckKey( hash_entry, key, len ) ) { return hash_entry; @@ -165,13 +161,13 @@ inline vf_HashEntry_t *vf_Hash::Lookup( /** * Function creates hash entry which is identical to current key. */ -inline vf_HashEntry_t *vf_Hash::NewHashEntry( const char *key ) // hash key +inline vf_HashEntry *vf_Hash::NewHashEntry( const char *key ) // hash key { // lookup type in hash assert( key ); unsigned hash_index = HashFunc( key ); hash_index = hash_index % HASH_SIZE; - vf_HashEntry_t *hash_entry = m_hash[hash_index]; + vf_HashEntry *hash_entry = m_hash[hash_index]; while( hash_entry != NULL ) { if( CheckKey( hash_entry, key ) ) { return hash_entry; @@ -181,13 +177,12 @@ inline vf_HashEntry_t *vf_Hash::NewHashE // create key string size_t len = strlen( key ); - char *hash_key = (char*)vf_alloc_pool_memory( m_pool, len + 1 ); + char *hash_key = (char*)vf_palloc( m_pool, len + 1 ); memcpy( hash_key, key, len ); // create hash entry hash_entry = - (vf_HashEntry_t*) vf_alloc_pool_memory( m_pool, - sizeof( vf_HashEntry_t ) ); + (vf_HashEntry*)vf_palloc( m_pool, sizeof( vf_HashEntry ) ); hash_entry->key = hash_key; hash_entry->next = m_hash[hash_index]; m_hash[hash_index] = hash_entry; @@ -198,15 +193,15 @@ inline vf_HashEntry_t *vf_Hash::NewHashE /** * Function creates hash entry which is identical to current key. */ -inline vf_HashEntry_t *vf_Hash::NewHashEntry( const char *key, // hash key - size_t len ) // key length +inline vf_HashEntry *vf_Hash::NewHashEntry( const char *key, // hash key + size_t len ) // key length { // lookup type in hash assert( key ); assert( len ); unsigned hash_index = HashFunc( key, len ); hash_index = hash_index % HASH_SIZE; - vf_HashEntry_t *hash_entry = m_hash[hash_index]; + vf_HashEntry *hash_entry = m_hash[hash_index]; while( hash_entry != NULL ) { if( CheckKey( hash_entry, key, len ) ) { return hash_entry; @@ -215,13 +210,12 @@ inline vf_HashEntry_t *vf_Hash::NewHashE } // create key string - char *hash_key = (char*)vf_alloc_pool_memory( m_pool, len + 1 ); + char *hash_key = (char*)vf_palloc( m_pool, len + 1 ); memcpy( hash_key, key, len ); // create hash entry hash_entry = - (vf_HashEntry_t*) vf_alloc_pool_memory( m_pool, - sizeof( vf_HashEntry_t ) ); + (vf_HashEntry*)vf_palloc( m_pool, sizeof( vf_HashEntry ) ); hash_entry->key = hash_key; hash_entry->next = m_hash[hash_index]; m_hash[hash_index] = hash_entry; @@ -240,7 +234,6 @@ vf_TypePool::vf_TypePool():m_method( NUL { m_pool = vf_create_pool(); m_Hash = new vf_Hash ( m_pool ); - return; } // vf_TypePool::vf_TypePool /** @@ -255,23 +248,21 @@ vf_TypePool::~vf_TypePool() /** * Function creates valid type which is identical to current class. */ -vf_ValidType_t * +vf_ValidType * vf_TypePool::NewType( const char *type, // class name size_t len ) // name length { - vf_ValidType_t *result; - vf_HashEntry_t *hash; + vf_ValidType *result; + vf_HashEntry *hash; // find type in hash hash = m_Hash->NewHashEntry( type, len ); if( hash->data ) { - assert( ( (vf_ValidType_t*) hash->data )->number == 1 ); - return (vf_ValidType_t*) hash->data; + assert( ( (vf_ValidType*)hash->data )->number == 1 ); + return (vf_ValidType*)hash->data; } // create and set type - result = - (vf_ValidType_t*) vf_alloc_pool_memory( m_pool, - sizeof( vf_ValidType_t ) ); + result = (vf_ValidType*)vf_palloc( m_pool, sizeof( vf_ValidType ) ); result->number = 1; result->string[0] = hash->key; // set type in hash @@ -296,26 +287,23 @@ vf_type_string_compare( const void *type /** * Function creates valid type which is identical to an element of a given array type. */ -vf_ValidType_t * -vf_TypePool::NewArrayElemType( vf_ValidType_t * array ) // array type +vf_ValidType * +vf_TypePool::NewArrayElemType( vf_ValidType *array ) // array type { - vf_ValidType_t *result; - vf_HashEntry_t *hash; + vf_ValidType *result; + vf_HashEntry *hash; // lookup type in hash hash = m_Hash->NewHashEntry( &array->string[0][1] ); if( array->number == 1 && hash->data ) { - assert( ( (vf_ValidType_t*) hash->data )->number == 1 ); - return (vf_ValidType_t*) hash->data; + assert( ( (vf_ValidType*)hash->data )->number == 1 ); + return (vf_ValidType*)hash->data; } // create and set type - result = (vf_ValidType_t*) vf_alloc_pool_memory( m_pool, - sizeof - ( vf_ValidType_t ) + - ( array->number - - 1 ) * - sizeof( const char - * ) ); + result = (vf_ValidType*)vf_palloc( m_pool, + sizeof( vf_ValidType ) + + ( array->number - + 1 ) * sizeof( const char * ) ); result->number = array->number; // set sting type result->string[0] = hash->key; @@ -345,7 +333,7 @@ vf_TypePool::DumpTypeConstraints( ostrea if( out == NULL ) { out = &cerr; } - for( vf_TypeConstraint_t * constraint = m_restriction; + for( vf_TypeConstraint *constraint = m_restriction; constraint; constraint = constraint->next ) { *out << "CONSTRAINT: have \"" << constraint->source << "\" need \"" << constraint-> @@ -354,13 +342,12 @@ vf_TypePool::DumpTypeConstraints( ostrea method_get_name( m_method ) << method_get_descriptor( m_method ) << endl; } - return; } // vf_TypePool::DumpTypeConstraints /** * Function returns the methods constraints array. */ -inline vf_TypeConstraint_t * +inline vf_TypeConstraint * vf_TypePool::GetClassConstraint() { return m_restriction; @@ -374,7 +361,6 @@ vf_TypePool::SetMethod( method_handler m { // set method m_method = method; - return; } // vf_TypePool::SetMethod /** @@ -384,9 +370,9 @@ void vf_TypePool::SetRestriction( const char *target, // target class name const char *source, // source class name unsigned short index, // constant pool index - vf_CheckConstraint_t check_type ) // constraint check type + vf_CheckConstraint check_type ) // constraint check type { - vf_TypeConstraint_t *restriction; + vf_TypeConstraint *restriction; // lookup restriction for( restriction = m_restriction; @@ -401,9 +387,9 @@ vf_TypePool::SetRestriction( const char } // set restriction - restriction = (vf_TypeConstraint_t*) vf_alloc_pool_memory( m_pool, - sizeof - ( vf_TypeConstraint_t ) ); + restriction = (vf_TypeConstraint*)vf_palloc( m_pool, + sizeof + ( vf_TypeConstraint ) ); restriction->target = target; restriction->source = source; restriction->index = index; @@ -414,31 +400,30 @@ vf_TypePool::SetRestriction( const char // trace restriction if( index ) { - VERIFY_TRACE( "constraint", "CONSTRAINT: for class \"" - << class_get_name( method_get_class( m_method ) ) << - "\" CP index #" << index << " check access: have \"" << - source << "\" need \"" << target << "\" for method " << - class_get_name( method_get_class( m_method ) ) << "." << - method_get_name( m_method ) << - method_get_descriptor( m_method ) ); + VF_TRACE( "constraint", "CONSTRAINT: for class \"" + << class_get_name( method_get_class( m_method ) ) << + "\" CP index #" << index << " check access: have \"" << + source << "\" need \"" << target << "\" for method " << + class_get_name( method_get_class( m_method ) ) << "." << + method_get_name( m_method ) << + method_get_descriptor( m_method ) ); } else { - VERIFY_TRACE( "constraint", "CONSTRAINT: have \"" - << source << "\" need \"" << target << "\" for method " - << class_get_name( method_get_class( m_method ) ) << "." - << method_get_name( m_method ) << - method_get_descriptor( m_method ) ); + VF_TRACE( "constraint", "CONSTRAINT: have \"" + << source << "\" need \"" << target << "\" for method " + << class_get_name( method_get_class( m_method ) ) << "." + << method_get_name( m_method ) << + method_get_descriptor( m_method ) ); } - return; } // vf_TypePool::SetRestriction /** * Function checks types and create constraints if it's necessarily. */ bool -vf_TypePool::CheckTypes( vf_ValidType_t * required, // required type - vf_ValidType_t * available, // available type +vf_TypePool::CheckTypes( vf_ValidType *required, // required type + vf_ValidType *available, // available type unsigned short index, // constant pool index - vf_CheckConstraint_t check_type ) // constraint check type + vf_CheckConstraint check_type ) // constraint check type { unsigned index1, index2; @@ -537,7 +522,7 @@ vf_TypePool::CheckTypes( vf_ValidType_t LDIE( 39, "Verifier: CompareTypes: unknown check type in switch" ); return true; } - // unreachable code + // unreachable instr assert( 0 ); } // vf_TypePool::CheckTypes @@ -545,9 +530,9 @@ vf_TypePool::CheckTypes( vf_ValidType_t * Function merges two valid types. * Function returns NULL if vector wasn't merged. */ -vf_ValidType_t * -vf_TypePool::MergeTypes( vf_ValidType_t * first, // first merged type - vf_ValidType_t * second ) // second merged type +vf_ValidType * +vf_TypePool::MergeTypes( vf_ValidType *first, // first merged type + vf_ValidType *second ) // second merged type { // check null reference if( first == NULL ) { @@ -578,17 +563,12 @@ vf_TypePool::MergeTypes( vf_ValidType_t return NULL; } // create merged type - vf_ValidType_t *type = (vf_ValidType_t*) vf_alloc_pool_memory( m_pool, - sizeof - ( vf_ValidType_t ) - + - ( count - - - 1 ) * - sizeof - ( const - char - * ) ); + vf_ValidType *type = (vf_ValidType*)vf_palloc( m_pool, + sizeof( vf_ValidType ) + + ( count - + 1 ) * + sizeof + ( const char * ) ); type->number = count; // set type in ascending order of types string @@ -618,44 +598,41 @@ vf_TypePool::MergeTypes( vf_ValidType_t * Function sets constraint for method in class loader verify data. */ static void -vf_set_class_constraint( vf_TypeConstraint_t * collection, // constraint for the class - vf_Context_t * ctex ) // verifier context +vf_set_class_constraint( vf_TypeConstraint *collection, // constraint for the class + vf_ContextHandle ctx ) // verification context { // get class loader of current class - classloader_handler class_loader = - class_get_class_loader( ctex->m_class ); + classloader_handler class_loader = class_get_class_loader( ctx->m_class ); // lock data modification cl_acquire_lock( class_loader ); - vf_ClassLoaderData_t *cl_data = - (vf_ClassLoaderData_t*) cl_get_verify_data_ptr( class_loader ); + vf_ClassLoaderData *cl_data = + (vf_ClassLoaderData*) cl_get_verify_data_ptr( class_loader ); // create class loader data if( cl_data == NULL ) { - vf_VerifyPool_t *new_pool = vf_create_pool(); - cl_data = (vf_ClassLoaderData_t*) vf_alloc_pool_memory( new_pool, - sizeof - ( vf_ClassLoaderData_t ) ); + vf_Pool *new_pool = vf_create_pool(); + cl_data = (vf_ClassLoaderData*) vf_palloc( new_pool, + sizeof + ( vf_ClassLoaderData ) ); cl_data->pool = new_pool; cl_data->string = new vf_Hash ( new_pool ); // set verify data for class loader cl_set_verify_data_ptr( class_loader, cl_data ); } - vf_VerifyPool_t *pool = cl_data->pool; - vf_Hash_t *hash = cl_data->string; + vf_Pool *pool = cl_data->pool; + vf_Hash *hash = cl_data->string; // create class constraints collection - vf_TypeConstraint_t *save_collection = NULL; - for( vf_TypeConstraint_t * restriction = collection; + vf_TypeConstraint *save_collection = NULL; + for( vf_TypeConstraint *restriction = collection; restriction; restriction = restriction->next ) { // create constraint - vf_TypeConstraint_t *constraint = - (vf_TypeConstraint_t*) vf_alloc_pool_memory( pool, - sizeof - ( vf_TypeConstraint_t ) ); + vf_TypeConstraint *constraint = + (vf_TypeConstraint*)vf_palloc( pool, + sizeof( vf_TypeConstraint ) ); // create entry in string pool for target class - vf_HashEntry_t *hash_entry = - hash->NewHashEntry( restriction->target ); + vf_HashEntry *hash_entry = hash->NewHashEntry( restriction->target ); constraint->target = hash_entry->key; // create entry in string pool for checked class hash_entry = hash->NewHashEntry( restriction->source ); @@ -668,12 +645,11 @@ vf_set_class_constraint( vf_TypeConstrai assert( save_collection ); // save method verify data - assert( class_get_verify_data_ptr( ctex->m_class ) == NULL ); - class_set_verify_data_ptr( ctex->m_class, save_collection ); + assert( class_get_verify_data_ptr( ctx->m_class ) == NULL ); + class_set_verify_data_ptr( ctx->m_class, save_collection ); // unlock data modification cl_release_lock( class_loader ); - return; } // vf_set_class_constraint /** @@ -682,7 +658,7 @@ vf_set_class_constraint( vf_TypeConstrai static class_handler vf_resolve_class( const char *name, // resolved class name bool need_load, // load flag - vf_Context_t * ctex ) // verifier context + vf_ContextHandle ctx ) // verification context { // get class name if( name[0] == 'L' ) { @@ -706,14 +682,13 @@ vf_resolve_class( const char *name, } // get class loader - classloader_handler class_loader = - class_get_class_loader( ctex->m_class ); + classloader_handler class_loader = class_get_class_loader( ctx->m_class ); // receive class class_handler result; if( need_load ) { // trace verifier loads - VERIFY_TRACE( "load", "verify load: class " << name ); + VF_TRACE( "load", "verify load: class " << name ); result = cl_load_class( class_loader, name ); } else { result = cl_get_class( class_loader, name ); @@ -755,8 +730,8 @@ vf_is_super_interface( class_handler sou for( unsigned index = 0; index < class_get_superinterface_number( source ); index++ ) { if( vf_is_super_interface - ( class_get_superinterface( source, ( unsigned short )index ), - target ) ) { + ( class_get_superinterface + ( source, ( unsigned short )index ), target ) ) { return true; } } @@ -1038,40 +1013,33 @@ vf_is_valid( class_handler source, * Sets verifier error. */ static inline void -vf_set_error( method_handler method, // failed method - unsigned check, // failed check - vf_Context_t * ctex ) // verifier context +vf_set_error( unsigned check, // failed check + vf_Context *ctx ) // verification context { switch ( check ) { case VF_CHECK_PARAM: - VERIFY_REPORT_CLASS( ctex, method, - "Incompatible argument for function" ); + VF_REPORT( ctx, "Incompatible argument for function" ); return; case VF_CHECK_ASSIGN: - VERIFY_REPORT_CLASS( ctex, method, - "Incompatible types for field assignment" ); + VF_REPORT( ctx, "Incompatible types for field assignment" ); return; case VF_CHECK_ASSIGN_WEAK: - VERIFY_REPORT_CLASS( ctex, method, - "Incompatible types for array assignment" ); + VF_REPORT( ctx, "Incompatible types for array assignment" ); return; case VF_CHECK_SUPER: - VERIFY_REPORT_CLASS( ctex, method, - "Exception class not a subclass of Throwable" ); + VF_REPORT( ctx, "Exception class not a subclass of Throwable" ); return; case VF_CHECK_ACCESS_FIELD: - VERIFY_REPORT_CLASS( ctex, method, "Bad access to protected field" ); + VF_REPORT( ctx, "Bad access to protected field" ); return; case VF_CHECK_ACCESS_METHOD: - VERIFY_REPORT_CLASS( ctex, method, "Bad access to protected method" ); + VF_REPORT( ctx, "Bad access to protected method" ); return; case VF_CHECK_DIRECT_SUPER: - VERIFY_REPORT_CLASS( ctex, method, - "Call to wrong initialization method" ); + VF_REPORT( ctx, "Call to wrong initialization method" ); return; case VF_CHECK_INVOKESPECIAL: - VERIFY_REPORT_CLASS( ctex, method, - "Incompatible object argument for invokespecial" ); + VF_REPORT( ctx, "Incompatible object argument for invokespecial" ); return; } LDIE( 41, "Verifier: vf_set_error: unknown check type" ); @@ -1080,9 +1048,9 @@ vf_set_error( method_handler method, /** * Checks some constraints without loading of needed classes. */ -static inline Verifier_Result -vf_check_without_loading( vf_TypeConstraint_t * restriction, // checked constraint - vf_Context_t * ctex ) // verifier context +static inline vf_Result +vf_check_without_loading( vf_TypeConstraint *restriction, // checked constraint + vf_Context *ctx ) // verification context { switch ( restriction->check_type ) { case VF_CHECK_SUPER: @@ -1090,7 +1058,7 @@ vf_check_without_loading( vf_TypeConstra * Extension for class java/lang/Object doesn't check * because it's expected all references extend it. */ - if( restriction->target == ctex->m_vtype.m_object->string[0] ) { + if( restriction->target == ctx->m_vtype.m_object->string[0] ) { // no need to check return VER_OK; } @@ -1101,7 +1069,7 @@ vf_check_without_loading( vf_TypeConstra * Extension for class java/lang/Object doesn't check * because it's expected all references extend it. */ - if( restriction->target == ctex->m_vtype.m_object->string[0] ) { + if( restriction->target == ctx->m_vtype.m_object->string[0] ) { // no need to check return VER_OK; } @@ -1111,7 +1079,7 @@ vf_check_without_loading( vf_TypeConstra * because it's expected all arrays extend it. * Just check is source array. */ - if( restriction->target == ctex->m_vtype.m_array->string[0] + if( restriction->target == ctx->m_vtype.m_array->string[0] && restriction->source[0] == '[' && ( restriction->source[1] == '[' || restriction->source[1] == 'L' ) ) { @@ -1124,8 +1092,8 @@ vf_check_without_loading( vf_TypeConstra * interfaces doesn't check because it's expected all arrays extend it. * Just check is source array. */ - if( ( restriction->target == ctex->m_vtype.m_clone->string[0] - || restriction->target == ctex->m_vtype.m_serialize->string[0] ) + if( ( restriction->target == ctx->m_vtype.m_clone->string[0] + || restriction->target == ctx->m_vtype.m_serialize->string[0] ) && restriction->source[0] == '[' ) { // no need to check return VER_OK; @@ -1138,7 +1106,7 @@ vf_check_without_loading( vf_TypeConstra if( ( restriction->target[0] != '[' && restriction->source[0] == '[' ) || ( restriction->target[0] != '[' && restriction->source[0] == '[' ) ) { - vf_set_error( ctex->m_method, VF_CHECK_PARAM, ctex ); + vf_set_error( VF_CHECK_PARAM, ctx ); return VER_ErrorIncompatibleArgument; } break; @@ -1161,12 +1129,12 @@ vf_check_without_loading( vf_TypeConstra // or java/lang/Serializable interface return VER_OK; } else if( restriction->target == - ctex->m_vtype.m_object->string[0] ) { + ctx->m_vtype.m_object->string[0] ) { // target class is java/lang/Object return VER_OK; } else if( restriction->target[0] != '[' ) { // target class isn't array class - vf_set_error( ctex->m_method, restriction->check_type, ctex ); + vf_set_error( restriction->check_type, ctx ); return VER_ErrorIncompatibleArgument; } } @@ -1184,16 +1152,15 @@ vf_check_without_loading( vf_TypeConstra * If any class isn't loaded, function returns unloaded error * to store restriction to the class for future constraint check. */ -static inline Verifier_Result -vf_check_constraint( vf_TypeConstraint_t * restriction, // checked constraint - vf_Context_t * ctex ) // verifier context +static inline vf_Result +vf_check_constraint( vf_TypeConstraint *restriction, // checked constraint + vf_Context *ctx ) // verification context { /** * Try to provide some checks without classes loading */ - if( !ctex->m_dump.m_verify ) { - Verifier_Result result = - vf_check_without_loading( restriction, ctex ); + if( !ctx->m_verify_all ) { + vf_Result result = vf_check_without_loading( restriction, ctx ); if( result != VER_ClassNotLoaded ) { // no need to check return result; @@ -1201,10 +1168,10 @@ vf_check_constraint( vf_TypeConstraint_t } // get target class handler class_handler target = - vf_resolve_class( restriction->target, false, ctex ); + vf_resolve_class( restriction->target, false, ctx ); // get checked class class_handler source = - vf_resolve_class( restriction->source, false, ctex ); + vf_resolve_class( restriction->source, false, ctx ); // check classes are loaded? if( !target || !source ) { return VER_ClassNotLoaded; @@ -1217,15 +1184,15 @@ vf_check_constraint( vf_TypeConstraint_t * To be compatible with those applications we should do full constraint * checks only if -Xverify:all option is present in command line. */ - if( !ctex->m_dump.m_verify && class_is_interface_( target ) ) { + if( !ctx->m_verify_all && class_is_interface_( target ) ) { // skip constraint check return VER_OK; } // check restriction if( !vf_is_valid - ( source, target, ctex->m_class, restriction->check_type ) ) { + ( source, target, ctx->m_class, restriction->check_type ) ) { // return error - vf_set_error( ctex->m_method, restriction->check_type, ctex ); + vf_set_error( restriction->check_type, ctx ); return VER_ErrorIncompatibleArgument; } return VER_OK; @@ -1237,21 +1204,21 @@ vf_check_constraint( vf_TypeConstraint_t * function return unloaded error to store restriction to the class * for future constraint check. */ -Verifier_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_t check_type, // access check type - vf_Context_t * ctex ) // verifier context + vf_CheckConstraint check_type, // access check type + vf_Context *ctx ) // verification context { // get class handler of super class - class_handler super_class = vf_resolve_class( super_name, false, ctex ); - if( !super_class || !vf_is_super_class( ctex->m_class, super_class ) ) { + class_handler super_class = vf_resolve_class( super_name, false, ctx ); + if( !super_class || !vf_is_super_class( ctx->m_class, super_class ) ) { // obtained class isn't super class of a given class, no need to check return VER_OK; } // check if a class and a parent class is in the same package - if( class_is_same_package( ctex->m_class, super_class ) ) { + if( class_is_same_package( ctx->m_class, super_class ) ) { // class and parent class is in the same package, // no need check access to protect members return VER_OK; @@ -1260,32 +1227,30 @@ vf_check_access_constraint( const char * bool need_check = false; if( check_type == VF_CHECK_ACCESS_FIELD ) { field_handler field = - class_resolve_nonstatic_field( ctex->m_class, index ); + class_resolve_nonstatic_field( ctx->m_class, index ); if( !field ) { // NoSuchFieldError or IllegalAccessError - nothing to check - VERIFY_DEBUG( "verifying class " << - class_get_name( ctex->m_class ) - << " (method " << method_get_name( ctex->m_method ) - << method_get_descriptor( ctex->m_method ) - << - ") couldn't resolve field with constant pool index #" - << index ); + VF_DEBUG( "verifying class " << class_get_name( ctx->m_class ) + << " (method " << method_get_name( ctx->m_method ) + << method_get_descriptor( ctx->m_method ) + << + ") couldn't resolve field with constant pool index #" + << index ); return VER_OK; } if( field_is_protected( field ) ) { need_check = true; } } else { - method_handler method = class_resolve_method( ctex->m_class, index ); + method_handler method = class_resolve_method( ctx->m_class, index ); if( !method || method_is_static( method ) ) { // NoSuchMethodError or IllegalAccessError - nothing to check - VERIFY_DEBUG( "verifying class " << - class_get_name( ctex->m_class ) - << " (method " << method_get_name( ctex->m_method ) - << method_get_descriptor( ctex->m_method ) - << - ") couldn't resolve method with constant pool index #" - << index ); + VF_DEBUG( "verifying class " << class_get_name( ctx->m_class ) + << " (method " << method_get_name( ctx->m_method ) + << method_get_descriptor( ctx->m_method ) + << + ") couldn't resolve method with constant pool index #" + << index ); return VER_OK; } if( method_is_protected( method ) ) { @@ -1302,15 +1267,15 @@ vf_check_access_constraint( const char * return VER_OK; } // get instance class - class_handler instance = vf_resolve_class( instance_name, false, ctex ); + class_handler instance = vf_resolve_class( instance_name, false, ctx ); if( !instance ) { // instance class isn't loaded return VER_ClassNotLoaded; } // check access constraint - if( !vf_is_valid( instance, NULL, ctex->m_class, check_type ) ) { + if( !vf_is_valid( instance, NULL, ctx->m_class, check_type ) ) { // return error - vf_set_error( ctex->m_method, check_type, ctex ); + vf_set_error( check_type, ctx ); return VER_ErrorIncompatibleArgument; } return VER_OK; @@ -1320,21 +1285,21 @@ vf_check_access_constraint( const char * * Function provides initial constraint checks for current class. * Function checks only loaded classes, and stores restriction for unloaded ones. */ -Verifier_Result -vf_check_class_constraints( vf_Context_t * ctex ) // verifier context +vf_Result +vf_check_class_constraints( vf_Context *ctx ) // verification context { // set class restriction collection - vf_TypeConstraint_t *last = NULL; - vf_TypeConstraint_t *collection = ctex->m_type->GetClassConstraint(); + vf_TypeConstraint *last = NULL; + vf_TypeConstraint *collection = ctx->m_type->GetClassConstraint(); // check constraints - for( vf_TypeConstraint_t * constraint = collection; + for( vf_TypeConstraint *constraint = collection; constraint; constraint = constraint->next ) { // set context method - ctex->m_method = constraint->method; + ctx->m_method = constraint->method; // check constraint - Verifier_Result result = vf_check_constraint( constraint, ctex ); + vf_Result result = vf_check_constraint( constraint, ctx ); if( result == VER_OK ) { // constraint checked, remove constraint from the collection if( !last ) { @@ -1352,7 +1317,7 @@ vf_check_class_constraints( vf_Context_t } if( collection ) { // set constraint for further checking - vf_set_class_constraint( collection, ctex ); + vf_set_class_constraint( collection, ctx ); } return VER_OK; @@ -1362,44 +1327,42 @@ vf_check_class_constraints( vf_Context_t * Function checks constraint for given class. * Function loads classes if it's needed. */ -static inline Verifier_Result -vf_force_check_constraint( vf_TypeConstraint_t * constraint, // class constraint - vf_Context_t * ctex ) // verifier context +static inline vf_Result +vf_force_check_constraint( vf_TypeConstraint *constraint, // class constraint + vf_Context *ctx ) // verification context { // check if constraint is already verified if( constraint->check_type == VF_CHECK_NONE ) { // already verified - VERIFY_TRACE( "constraint.checked", "verify constraint: have \"" - << constraint->source << "\" need \"" << constraint-> - target << "\" already done (check #1) for class " << - class_get_name( ctex->m_class ) ); + VF_TRACE( "constraint.checked", "verify constraint: have \"" + << constraint->source << "\" need \"" << constraint-> + target << "\" already done (check #1) for class " << + class_get_name( ctx->m_class ) ); return VER_OK; } // get target class - class_handler target = vf_resolve_class( constraint->target, true, ctex ); + class_handler target = vf_resolve_class( constraint->target, true, ctx ); + ctx->m_method = constraint->method; if( !target ) { - VERIFY_DEBUG( "verifying class " << class_get_name( ctex->m_class ) - << " (method " << method_get_name( constraint->method ) - << method_get_descriptor( constraint->method ) - << ") couldn't load class \"" - << ( ( constraint->target[0] == 'L' ) - ? &( constraint->target[1] ) : constraint->target ) - << "\"" ); + VF_DEBUG( VF_REPORT_CTX( ctx ) << "couldn't load class \"" + << ( ( constraint->target[0] == 'L' ) + ? &( constraint->target[1] ) : constraint-> + target ) << "\"" ); unsigned index = 0; while( constraint->target[index++] != 'L' ) { assert( constraint->target[index] != '\0' ); } - VERIFY_REPORT( ctex, "Couldn't load class: " - << &( constraint->target[index] ) ); + VF_REPORT( ctx, "Couldn't load class: " + << &( constraint->target[index] ) ); return VER_ErrorLoadClass; } // check if constraint is already verified if( constraint->check_type == VF_CHECK_NONE ) { // already verified - VERIFY_TRACE( "constraint.checked", "verify constraint: have \"" - << constraint->source << "\" need \"" << constraint-> - target << "\" already done (check #2) for class " << - class_get_name( ctex->m_class ) ); + VF_TRACE( "constraint.checked", VF_REPORT_CTX( ctx ) + << "verify constraint: have \"" + << constraint->source << "\" need \"" << constraint-> + target << "\" already done (check #2)" ); return VER_OK; } @@ -1410,7 +1373,7 @@ vf_force_check_constraint( vf_TypeConstr * To be compatible with those applications we should do full constraint * checks only if -Xverify:all option is present in command line. */ - if( !ctex->m_dump.m_verify && class_is_interface_( target ) ) { + if( !ctx->m_verify_all && class_is_interface_( target ) ) { // skip constraint check // reset constraint to successful constraint->check_type = VF_CHECK_NONE; @@ -1419,47 +1382,43 @@ vf_force_check_constraint( vf_TypeConstr // check if constraint is already verified if( constraint->check_type == VF_CHECK_NONE ) { // already verified - VERIFY_TRACE( "constraint.checked", "verify constraint: have \"" - << constraint->source << "\" need \"" << constraint-> - target << "\" already done (check #3) for class " << - class_get_name( ctex->m_class ) ); + VF_TRACE( "constraint.checked", + VF_REPORT_CTX( ctx ) << "verify constraint: have \"" << + constraint->source << "\" need \"" << constraint-> + target << "\" already done (check #3)" ); return VER_OK; } // get stack reference class - class_handler source = vf_resolve_class( constraint->source, true, ctex ); + class_handler source = vf_resolve_class( constraint->source, true, ctx ); if( !source ) { - VERIFY_DEBUG( "verifying class " << class_get_name( ctex->m_class ) - << " (method " << method_get_name( constraint->method ) - << method_get_descriptor( constraint->method ) - << ") couldn't load class \"" - << ( ( constraint->source[0] == 'L' ) - ? &( constraint->source[1] ) : constraint->source ) - << "\"" ); + VF_DEBUG( VF_REPORT_CTX( ctx ) << "couldn't load class \"" + << ( ( constraint->source[0] == 'L' ) + ? &( constraint->source[1] ) : constraint->source ) + << "\"" ); unsigned index = 0; while( constraint->source[index++] != 'L' ) { assert( constraint->source[index] != '\0' ); } - VERIFY_REPORT( ctex, "Couldn't load class: " - << &( constraint->source[index] ) ); + VF_REPORT( ctx, "Couldn't load class: " + << &( constraint->source[index] ) ); return VER_ErrorLoadClass; } // store constraint check type (it could be changed during validation check) - vf_CheckConstraint_t check = - ( vf_CheckConstraint_t ) constraint->check_type; + vf_CheckConstraint check = ( vf_CheckConstraint ) constraint->check_type; // check if constraint is already verified if( check == VF_CHECK_NONE ) { // already verified - VERIFY_TRACE( "constraint.checked", "verify constraint: have \"" - << constraint->source << "\" need \"" << constraint-> - target << "\" already done (check #4) for class " << - class_get_name( ctex->m_class ) ); + VF_TRACE( "constraint.checked", + VF_REPORT_CTX( ctx ) << "verify constraint: have \"" << + constraint->source << "\" need \"" << constraint-> + target << "\" already done (check #4)" ); return VER_OK; } // check restriction - if( !vf_is_valid( source, target, ctex->m_class, check ) ) { + if( !vf_is_valid( source, target, ctx->m_class, check ) ) { // return error - vf_set_error( constraint->method, check, ctex ); + vf_set_error( check, ctx ); return VER_ErrorIncompatibleArgument; } // reset constraint to successful @@ -1470,23 +1429,23 @@ vf_force_check_constraint( vf_TypeConstr /** * Function verifies class constraints. */ -static Verifier_Result -vf_verify_class_constraints( vf_Context_t * ctex ) // verifier context +static vf_Result +vf_verify_class_constraints( vf_Context *ctx ) // verification context { // get method verify data - vf_TypeConstraint_t *constraint = - (vf_TypeConstraint_t*) class_get_verify_data_ptr( ctex->m_class ); + vf_TypeConstraint *constraint = + (vf_TypeConstraint*)class_get_verify_data_ptr( ctx->m_class ); if( constraint == NULL ) { return VER_OK; } // trace verified class - VERIFY_TRACE( "class.constraint", - "verify constraints: " << class_get_name( ctex->m_class ) ); + VF_TRACE( "class.constraint", + "verify constraints: " << class_get_name( ctx->m_class ) ); // check method constraints - Verifier_Result result = VER_OK; + vf_Result result = VER_OK; for( ; constraint; constraint = constraint->next ) { - result = vf_force_check_constraint( constraint, ctex ); + result = vf_force_check_constraint( constraint, ctx ); if( result != VER_OK ) { break; } @@ -1502,9 +1461,9 @@ vf_verify_class_constraints( vf_Context_ * Function performs abend exit from VM. */ void -vf_error_func( VERIFY_SOURCE_PARAMS ) +vf_error_func( VF_SOURCE_PARAMS ) { - LDIE( 42, "{0} Verifier: abort!" << VERIFY_REPORT_SOURCE ); + LDIE( 42, "{0} Verifier: abort!" << VF_REPORT_SOURCE ); exit( 1 ); } // vf_error_func @@ -1514,7 +1473,7 @@ vf_error_func( VERIFY_SOURCE_PARAMS ) void * vf_calloc_func( unsigned num, // number of elements size_t size, // size of element - VERIFY_SOURCE_PARAMS ) // debug info + VF_SOURCE_PARAMS ) // debug info { assert( num ); assert( size ); @@ -1524,13 +1483,13 @@ vf_calloc_func( unsigned num, // numbe LECHO( 41, "Verifier: {0}: out of memory" << "vf_calloc_func" ); vf_error(); } -#if VERIFY_TRACE_MEMORY +#if VF_TRACE_MEMORY // trace memory - VERIFY_TRACE( "memory", VERIFY_REPORT_SOURCE - << "(calloc) allocate memory addr: " << result - << ", size: " << size * - num << " (" << num << " by " << size << ")" ); -#endif // VERIFY_TRACE_MEMORY + VF_TRACE( "memory", VF_REPORT_SOURCE + << "(calloc) allocate memory addr: " << result + << ", size: " << size * + num << " (" << num << " by " << size << ")" ); +#endif // VF_TRACE_MEMORY return result; } // vf_calloc_func @@ -1540,7 +1499,7 @@ vf_calloc_func( unsigned num, // numbe */ void * vf_malloc_func( size_t size, // size of memory block - VERIFY_SOURCE_PARAMS ) // debug info + VF_SOURCE_PARAMS ) // debug info { assert( size ); void *result = STD_MALLOC( size ); @@ -1549,12 +1508,12 @@ vf_malloc_func( size_t size, // size LECHO( 41, "Verifier: {0}: out of memory" << "vf_malloc_func" ); vf_error(); } -#if VERIFY_TRACE_MEMORY +#if VF_TRACE_MEMORY // trace memory - VERIFY_TRACE( "memory", VERIFY_REPORT_SOURCE - << "(malloc) allocate memory addr: " << result - << ", size: " << size ); -#endif // VERIFY_TRACE_MEMORY + VF_TRACE( "memory", VF_REPORT_SOURCE + << "(malloc) allocate memory addr: " << result + << ", size: " << size ); +#endif // VF_TRACE_MEMORY return result; } // vf_malloc_func @@ -1565,7 +1524,7 @@ vf_malloc_func( size_t size, // size void * vf_realloc_func( void *pointer, // old pointer size_t size, // size of memory block - VERIFY_SOURCE_PARAMS ) // debug info + VF_SOURCE_PARAMS ) // debug info { assert( size ); void *result = STD_REALLOC( pointer, size ); @@ -1574,12 +1533,12 @@ vf_realloc_func( void *pointer, // old p LECHO( 41, "Verifier: {0}: out of memory" << "vf_realloc_func" ); vf_error(); } -#if VERIFY_TRACE_MEMORY +#if VF_TRACE_MEMORY // trace memory - VERIFY_TRACE( "memory", VERIFY_REPORT_SOURCE - << "(realloc) reallocate memory from addr: " << pointer - << " to addr: " << result << ", size: " << size ); -#endif // VERIFY_TRACE_MEMORY + VF_TRACE( "memory", VF_REPORT_SOURCE + << "(realloc) reallocate memory from addr: " << pointer + << " to addr: " << result << ", size: " << size ); +#endif // VF_TRACE_MEMORY return result; } // vf_realloc_func @@ -1589,7 +1548,7 @@ vf_realloc_func( void *pointer, // old p */ void vf_free_func( void *pointer, // free pointer - VERIFY_SOURCE_PARAMS ) // debug info + VF_SOURCE_PARAMS ) // debug info { if( pointer ) { STD_FREE( pointer ); @@ -1598,41 +1557,39 @@ vf_free_func( void *pointer, // free vf_error(); } -#if VERIFY_TRACE_MEMORY +#if VF_TRACE_MEMORY // trace memory - VERIFY_TRACE( "memory", VERIFY_REPORT_SOURCE - << "(free) free memory addr: " << ( void * )pointer ); -#endif // VERIFY_TRACE_MEMORY + VF_TRACE( "memory", VF_REPORT_SOURCE + << "(free) free memory addr: " << ( void * )pointer ); +#endif // VF_TRACE_MEMORY - return; } // vf_free_func /** * Function creates wide memory pool structure. */ -static inline vf_VerifyPoolInternal_t * +static inline vf_PoolInternal * vf_create_pool_element( size_t size, // initial pool size - VERIFY_SOURCE_PARAMS ) // debug info + VF_SOURCE_PARAMS ) // debug info { - vf_VerifyPoolInternal_t *result; + vf_PoolInternal *result; // create pool new entry and allocate memory for it - result = (vf_VerifyPoolInternal_t*) - vf_malloc_func( sizeof( vf_VerifyPoolInternal_t ) + size, - VERIFY_SOURCE_ARGS1 ); - result->m_memory = (char*)result + sizeof( vf_VerifyPoolInternal_t ); + result = (vf_PoolInternal*) + vf_malloc_func( sizeof( vf_PoolInternal ) + size, VF_SOURCE_ARGS1 ); + result->m_memory = (char*)result + sizeof( vf_PoolInternal ); result->m_free = (char*)result->m_memory; result->m_freesize = size; result->m_next = NULL; memset( result->m_memory, 0, size ); -#if VERIFY_TRACE_MEMORY +#if VF_TRACE_MEMORY // trace memory - VERIFY_TRACE( "memory.pool.element", VERIFY_REPORT_SOURCE - << "(pool) create pool element: " << result - << ", memory: " << result-> - m_memory << ", size: " << result->m_freesize ); -#endif // VERIFY_TRACE_MEMORY + VF_TRACE( "memory.pool.element", VF_REPORT_SOURCE + << "(pool) create pool element: " << result + << ", memory: " << result-> + m_memory << ", size: " << result->m_freesize ); +#endif // VF_TRACE_MEMORY return result; } // vf_create_pool_element @@ -1640,31 +1597,29 @@ vf_create_pool_element( size_t size, /** * Function creates memory pool structure. */ -vf_VerifyPool_t * -vf_create_pool_func( VERIFY_SOURCE_PARAMS ) +vf_Pool * +vf_create_pool_func( VF_SOURCE_PARAMS ) { // create new pool element - vf_VerifyPoolInternal_t *pool = - vf_create_pool_element( sizeof( vf_VerifyPool_t ) + - VERIFY_POOL_ENTRY_SIZE, - VERIFY_SOURCE_ARGS1 ); + vf_PoolInternal *pool = + vf_create_pool_element( sizeof( vf_Pool ) + VF_POOL_ENTRY_SIZE, + VF_SOURCE_ARGS1 ); // set head pool - vf_VerifyPool_t *result = (vf_VerifyPool_t*) pool->m_free; - pool->m_memory = pool->m_free + sizeof( vf_VerifyPool_t ); + vf_Pool *result = (vf_Pool*)pool->m_free; + pool->m_memory = pool->m_free + sizeof( vf_Pool ); pool->m_free = (char*)pool->m_memory; - pool->m_freesize = VERIFY_POOL_ENTRY_SIZE; + pool->m_freesize = VF_POOL_ENTRY_SIZE; result->m_pool = pool; - result->m_memory = - sizeof( vf_VerifyPoolInternal_t ) + sizeof( vf_VerifyPool_t ) - + VERIFY_POOL_ENTRY_SIZE; + result->m_memory = sizeof( vf_PoolInternal ) + sizeof( vf_Pool ) + + VF_POOL_ENTRY_SIZE; result->m_used = 0; result->m_maxuse = 0; -#if VERIFY_TRACE_MEMORY +#if VF_TRACE_MEMORY // trace memory - VERIFY_TRACE( "memory.pool", VERIFY_REPORT_SOURCE - << "(pool) create pool: " << result ); -#endif // VERIFY_TRACE_MEMORY + VF_TRACE( "memory.pool", VF_REPORT_SOURCE + << "(pool) create pool: " << result ); +#endif // VF_TRACE_MEMORY return result; } // vf_create_pool_func @@ -1673,26 +1628,26 @@ vf_create_pool_func( VERIFY_SOURCE_PARAM * Function allocates memory block in current pool. */ void * -vf_alloc_pool_memory_func( vf_VerifyPool_t * hpool, // a given pool - size_t size, // memory size - VERIFY_SOURCE_PARAMS ) // debug info +vf_palloc_func( vf_Pool *hpool, // a given pool + size_t size, // memory size + VF_SOURCE_PARAMS ) // debug info { const unsigned align = sizeof( void * ) - 1; void *result = NULL; - vf_VerifyPoolInternal_t *pool = hpool->m_pool; + vf_PoolInternal *pool = hpool->m_pool; // align allocate size size = ( size + align ) & ( ~align ); // find free space - if( size > VERIFY_POOL_ENTRY_SIZE ) { + if( size > VF_POOL_ENTRY_SIZE ) { // create new wide pool entry - pool = vf_create_pool_element( size, VERIFY_SOURCE_ARGS1 ); + pool = vf_create_pool_element( size, VF_SOURCE_ARGS1 ); pool->m_next = hpool->m_pool; hpool->m_pool = pool; - hpool->m_memory += sizeof( vf_VerifyPoolInternal_t ) + size; + hpool->m_memory += sizeof( vf_PoolInternal ) + size; } else if( pool->m_freesize < size ) { - vf_VerifyPoolInternal_t *last = NULL; - vf_VerifyPoolInternal_t *entry = pool->m_next; + vf_PoolInternal *last = NULL; + vf_PoolInternal *entry = pool->m_next; while( entry ) { last = pool; pool = entry; @@ -1705,12 +1660,10 @@ vf_alloc_pool_memory_func( vf_VerifyPool if( !entry ) { // create new pool element pool = - vf_create_pool_element( VERIFY_POOL_ENTRY_SIZE, - VERIFY_SOURCE_ARGS1 ); + vf_create_pool_element( VF_POOL_ENTRY_SIZE, VF_SOURCE_ARGS1 ); pool->m_next = hpool->m_pool; hpool->m_pool = pool; - hpool->m_memory += - sizeof( vf_VerifyPoolInternal_t ) + VERIFY_POOL_ENTRY_SIZE; + hpool->m_memory += sizeof( vf_PoolInternal ) + VF_POOL_ENTRY_SIZE; } else { assert( last != NULL ); last->m_next = pool->m_next; @@ -1724,38 +1677,37 @@ vf_alloc_pool_memory_func( vf_VerifyPool pool->m_freesize -= size; hpool->m_used += size; -#if VERIFY_TRACE_MEMORY +#if VF_TRACE_MEMORY // trace memory - VERIFY_TRACE( "memory.pool", VERIFY_REPORT_SOURCE - << "(pool) allocate memory in pool: " << hpool - << ", memory: " << result << ", size: " << size - << ", element: " << pool << ", free: " << pool-> - m_freesize ); -#endif // VERIFY_TRACE_MEMORY + VF_TRACE( "memory.pool", VF_REPORT_SOURCE + << "(pool) allocate memory in pool: " << hpool + << ", memory: " << result << ", size: " << size + << ", element: " << pool << ", free: " << pool->m_freesize ); +#endif // VF_TRACE_MEMORY return result; -} // vf_alloc_pool_memory_func +} // vf_palloc_func /** * Function cleans given pool. */ void -vf_clean_pool_memory_func( vf_VerifyPool_t * hpool, // memory pool - VERIFY_SOURCE_PARAMS ) // debug info +vf_clean_pool_func( vf_Pool *hpool, // memory pool + VF_SOURCE_PARAMS ) // debug info { // set max used value if( hpool->m_used > hpool->m_maxuse ) { hpool->m_maxuse = hpool->m_used; } -#if VERIFY_TRACE_MEMORY +#if VF_TRACE_MEMORY // trace memory - VERIFY_TRACE( "memory.pool", VERIFY_REPORT_SOURCE - << "(pool) clean pool: " << hpool - << ", allocated: " << hpool-> - m_memory << ", used: " << hpool->m_used ); -#endif // VERIFY_TRACE_MEMORY + VF_TRACE( "memory.pool", VF_REPORT_SOURCE + << "(pool) clean pool: " << hpool + << ", allocated: " << hpool-> + m_memory << ", used: " << hpool->m_used ); +#endif // VF_TRACE_MEMORY - vf_VerifyPoolInternal_t *pool = hpool->m_pool; + vf_PoolInternal *pool = hpool->m_pool; while( pool ) { // clean pool element space unsigned used_size = @@ -1765,58 +1717,56 @@ vf_clean_pool_memory_func( vf_VerifyPool pool->m_freesize += used_size; hpool->m_used -= used_size; -#if VERIFY_TRACE_MEMORY +#if VF_TRACE_MEMORY // trace memory - VERIFY_TRACE( "memory.pool.element", VERIFY_REPORT_SOURCE - << "(pool) clean pool element: " << pool - << ", size: " << used_size ); -#endif // VERIFY_TRACE_MEMORY + VF_TRACE( "memory.pool.element", VF_REPORT_SOURCE + << "(pool) clean pool element: " << pool + << ", size: " << used_size ); +#endif // VF_TRACE_MEMORY // get next pool entry pool = pool->m_next; } - return; -} // vf_clean_pool_memory_func +} // vf_clean_pool_func /** * Function releases memory from given pool. */ void -vf_delete_pool_func( vf_VerifyPool_t * hpool, // memory pool - VERIFY_SOURCE_PARAMS ) // debug info +vf_delete_pool_func( vf_Pool *hpool, // memory pool + VF_SOURCE_PARAMS ) // debug info { -#if VERIFY_TRACE_MEMORY +#if VF_TRACE_MEMORY // trace memory - VERIFY_TRACE( "memory.pool", VERIFY_REPORT_SOURCE - << "(pool) delete pool: " << hpool - << ", allocated: " << hpool->m_memory - << ", used: " - << ( hpool->m_used > - hpool->m_maxuse ? hpool->m_used : hpool->m_maxuse ) ); -#endif // VERIFY_TRACE_MEMORY + VF_TRACE( "memory.pool", VF_REPORT_SOURCE + << "(pool) delete pool: " << hpool + << ", allocated: " << hpool->m_memory + << ", used: " + << ( hpool->m_used > + hpool->m_maxuse ? hpool->m_used : hpool->m_maxuse ) ); +#endif // VF_TRACE_MEMORY - vf_VerifyPoolInternal_t *pool = hpool->m_pool; + vf_PoolInternal *pool = hpool->m_pool; while( pool ) { -#if VERIFY_TRACE_MEMORY +#if VF_TRACE_MEMORY // trace memory - VERIFY_TRACE( "memory.pool.element", VERIFY_REPORT_SOURCE - << "(pool) delete pool element: " << pool ); -#endif // VERIFY_TRACE_MEMORY + VF_TRACE( "memory.pool.element", VF_REPORT_SOURCE + << "(pool) delete pool element: " << pool ); +#endif // VF_TRACE_MEMORY // store pool element - vf_VerifyPoolInternal_t *entry = pool; + vf_PoolInternal *entry = pool; // get next pool element pool = pool->m_next; // free pool element - vf_free_func( entry, VERIFY_SOURCE_ARGS1 ); + vf_free_func( entry, VF_SOURCE_ARGS1 ); } - return; } // vf_delete_pool_func /** * Function provides final constraint checks for a given class. */ -Verifier_Result +vf_Result vf_verify_class_constraints( class_handler klass, // a given class unsigned verifyAll, // verification level flag char **message ) // verifier error message @@ -1825,19 +1775,19 @@ vf_verify_class_constraints( class_handl assert( message ); // create context - vf_Context_t context; + vf_Context context; context.m_class = klass; - context.m_dump.m_verify = verifyAll ? 1 : 0; + context.m_verify_all = verifyAll ? true : false; // verified constraint for a given method - Verifier_Result result = vf_verify_class_constraints( &context ); + vf_Result result = vf_verify_class_constraints( &context ); *message = context.m_error; -#if _VERIFY_DEBUG +#if _VF_DEBUG if( result != VER_OK ) { - VERIFY_DEBUG( "VerifyError: " << context.m_error ); + VF_DEBUG( "VerifyError: " << context.m_error ); } -#endif // _VERIFY_DEBUG +#endif // _VF_DEBUG return result; } // vf_verify_class_constraints @@ -1848,9 +1798,8 @@ vf_verify_class_constraints( class_handl void vf_release_verify_data( void *data ) { - vf_ClassLoaderData_t *cl_data = (vf_ClassLoaderData_t*) data; + vf_ClassLoaderData *cl_data = (vf_ClassLoaderData*) data; delete cl_data->string; vf_delete_pool( cl_data->pool ); - return; } // vf_release_verify_data