harmony-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From mloe...@apache.org
Subject svn commit: r619847 - in /harmony/enhanced/drlvm/trunk: make/vm/ vm/vmcore/src/verifier-3363/x_verifier/
Date Fri, 08 Feb 2008 11:53:13 GMT
Author: mloenko
Date: Fri Feb  8 03:53:11 2008
New Revision: 619847

URL: http://svn.apache.org/viewvc?rev=619847&view=rev
Log:
intergration of HARMONY-5142 (implementation of recompute stackmap) - patch was modified a bit

Added:
    harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/x_verifier/
    harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/x_verifier/recompute.cpp   (with props)
    harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/x_verifier/recompute.h   (with props)
    harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/x_verifier/write_attr.cpp   (with props)
    harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/x_verifier/x_class_interface.h   (with props)
    harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/x_verifier/x_verifier.cpp   (with props)
    harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/x_verifier/x_verifier.h   (with props)
Modified:
    harmony/enhanced/drlvm/trunk/make/vm/verifier.xml

Modified: harmony/enhanced/drlvm/trunk/make/vm/verifier.xml
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/make/vm/verifier.xml?rev=619847&r1=619846&r2=619847&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/make/vm/verifier.xml (original)
+++ harmony/enhanced/drlvm/trunk/make/vm/verifier.xml Fri Feb  8 03:53:11 2008
@@ -32,7 +32,9 @@
             <compiler extends="common.cpp.compiler">
                 <fileset dir="${vm.home}/vmcore/src">
                     <include name="verifier/*.cpp" if="use_original_verifier"/>
-                    <include name="verifier-3363/*/*.cpp" unless="use_original_verifier"/>
+                    <include name="verifier-3363/base/*.cpp" unless="use_original_verifier"/>
+                    <include name="verifier-3363/java5/*.cpp" unless="use_original_verifier"/>
+                    <include name="verifier-3363/java6/*.cpp" unless="use_original_verifier"/>
                 </fileset>
             </compiler>
         </make-native>

Added: harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/x_verifier/recompute.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/x_verifier/recompute.cpp?rev=619847&view=auto
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/x_verifier/recompute.cpp (added)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/x_verifier/recompute.cpp Fri Feb  8 03:53:11 2008
@@ -0,0 +1,717 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/** 
+ * @author Mikhail Loenko, Vladimir Molotkov
+ */  
+
+
+
+#include <iostream>
+
+using namespace std;
+
+#include "recompute.h"
+#include "../java5/stackmap_5.h"
+#include "time.h"
+
+using namespace CPVerifier;
+using namespace CPVerifier_5;
+
+
+static char err_message[5000];
+
+/**
+* Function recomputes StackMapTable attribute.
+*
+*/
+vf_Result
+vf_recompute_stackmaptable( method_handler method, uint8 **attrBytes, char **error, void *trustedPairs )
+{
+    class_handler klass = method_get_class(method);
+    vf_Result result = VF_OK;
+
+    // Create context
+    SharedClasswideData classwide(klass);
+    vf_Context_5e context(classwide, trustedPairs);
+
+    // Verify method with Java5 verifier
+    result = context.recompute_stackmaptable(method);
+
+    if (result != VF_OK) {
+        *error = &(err_message[0]);
+        sprintf(*error, "%s/%s%s, pass: %d, instr: %d, reason: %s", class_get_name( klass ), method_get_name( method ), 
+            method_get_descriptor( method ), context.pass, context.processed_instruction, context.error_message );
+    }
+
+    *attrBytes = context.written_stackmap;
+    return result;
+} // vf_recompute_stackmaptable
+
+vf_Result vf_Context_5e::recompute_stackmaptable( method_handler method ) {
+    written_stackmap = 0;
+
+    //nothing to verify
+    if( !method_get_code_length( method ) ) {
+        return VF_OK;
+    }
+
+
+    vf_Result tcr;
+    int entryNo = 0;
+    parsedDataSz = 0;
+
+    // Verify method with Java5 verifier
+    if( (tcr=verify_method(method)) != VF_OK) {
+        return tcr;
+    }
+
+    if( (tcr=do_recompute()) != VF_OK) {
+        return tcr;
+    }
+
+    create_method_initial_workmap();
+    lastLocalsNo = m_max_locals;
+    while( lastLocalsNo ) {
+        if( workmap->elements[lastLocalsNo-1].getConst() != SM_BOGUS ) {
+            break;
+        }
+        lastLocalsNo--;
+    }
+    lastInstr = -1;
+
+    curFrame = newWorkmap(m_stack_start + m_max_stack);
+    for( Address instr = 0; instr < m_code_length; instr++) {
+        PropsHead *head = (PropsHead*)props.getInstrProps(instr);
+        if (head) {
+            if( (tcr=fillCurFrame(head)) != VF_OK ) {
+                return tcr;
+            }
+            entryNo++;
+            writeStackMapFrame(head->instr);
+
+            /////////////////////////////////
+            workmap->depth = curFrame->depth;
+            tc_memcpy(&workmap->elements[0], &curFrame->elements[0], sizeof(WorkmapElement) * (m_stack_start + workmap->depth));
+        }
+    }
+
+    if( written_stackmap ) {
+        written_stackmap[7] = entryNo & 0xFF;
+        entryNo >>= 8;
+
+        written_stackmap[6] = entryNo & 0xFF;
+        ////////////
+        written_stackmap[5] = attrLen & 0xFF;
+        attrLen >>= 8;
+
+        written_stackmap[4] = attrLen & 0xFF;
+        attrLen >>= 8;
+
+        written_stackmap[3] = attrLen & 0xFF;
+        attrLen >>= 8;
+
+        written_stackmap[2] = attrLen & 0xFF;
+    }
+
+    return VF_OK;
+} // recompute_stackmaptable
+
+vf_Result vf_Context_5e::fillCurFrame(PropsHead *head) {
+    curFrame->depth = head->is_workmap() ? head->getWorkmap()->depth : head->getStackmap()->depth;
+    
+    int high_word_expected = false;
+
+    for( unsigned i = 0; i < m_stack_start + curFrame->depth; i++ ) {
+        if( i == m_max_locals && i < m_stack_start ) continue;
+
+        SmConstant value = get_node_value(head, i);
+
+        if( high_word_expected && value != SM_HIGH_WORD ) {
+            curFrame->elements[i-1].const_val = SmConstant(SM_BOGUS);
+        }
+
+        high_word_expected = value.isLongOrDouble();
+        curFrame->elements[i].const_val = value.isLongOrDouble() && (i + 1 == m_max_locals || i + 1 == m_stack_start + curFrame->depth) ? SM_BOGUS : value;
+    }
+    return VF_OK;
+}
+
+vf_Result vf_Context_5e::do_recompute( ) {
+    parseTrustedPairs();
+
+    vf_Result tcr;
+    //we skip workmap vectors when do iteration
+    //workmap vectors may contain constant, refs to stackmap elements that are parts of other vectrs
+    //(and thus iterated thru), or temporary stackmap elements created by 
+    //iterate thru all stackmaps
+    ITERATE_THRU_STACKMAP_VECTORS({
+        //insert back refs to split to sub-graphs later
+        if( (tcr = mantain_node_consistency(el)) != VF_OK ) {
+            return tcr;
+        }
+        insert_back_refs(el);
+    });
+
+
+    if( (tcr = mantain_arc_consistency(0)) != VF_OK ) {
+        return tcr;
+    }
+
+    //iterate thru all stackmaps
+    ITERATE_THRU_STACKMAP_VECTORS({
+        //fully calculate subgraph that contains this node
+        //if it's not yet calculated
+        if( (tcr = calculate_subgraph(el)) != VF_OK ) {
+            return tcr;
+        }
+    });
+
+
+    for( Address instr = 0; instr < m_code_length; instr++ ) {
+        if( props.isDeadCodeStart(instr) ) { //dead block begins with 01, middles are 11, ends with 10 or 00
+            Address dead_code_start = instr;
+            //replace dead code with {NOP, NOP, ..., NOP, ATHROW}
+            while( !props.isDataflowPassed(instr) ) {
+                m_bytecode[instr++] = OP_NOP;
+            }
+            m_bytecode[instr-1] = OP_ATHROW;
+
+
+            //dead code start: place workmap here
+            assert(!props.getInstrProps(dead_code_start));
+
+            PropsHead* dead = newWorkmapProps(m_stack_start + 1);
+            props.setInstrProps(dead_code_start, dead);
+            WorkmapHead *wm = dead->getWorkmap();
+
+            PropsHead* alive = (PropsHead*)props.getInstrProps(instr);
+            assert( alive );
+
+            for( unsigned i = 0; i < m_stack_start; i++ ) {
+                wm->elements[i].const_val = get_node_value(alive, 1);
+            }
+
+            wm->depth = 1;
+            wm->elements[m_stack_start].const_val = SmConstant(SM_NULL);
+
+            reduceTryBlocks(dead_code_start, instr);
+        }
+    }
+    return VF_OK;
+}
+
+
+//insert reversed generic constraints
+void vf_Context_5e::insert_back_refs(StackmapElement *el) {
+    //stackmap is know already for this element ==> it won't participae in backtracking
+    if (is_node_calculated(el)) return;
+
+    GenericCnstr *gen = el->firstGenericCnstr();
+    while( gen ) {
+        ((StackmapElement_Ex*)(gen->variable))->newReversedGenericCnstr_safe(&mem, el);
+        gen = gen->next();
+    }
+
+    //add incoming value if it does not have
+    ArrayCnstr *arr = el->firstArrayCnstr();
+    if ( arr && ((StackmapElement_Ex*)(arr->variable))->newReversedArrayCnstr_safe(&mem, el) ) {
+        //we need this recursion to cover temporary values created at AALOAD instr
+        //since they are not covered by ITERATE_THRU_STACKMAP_VECTORS
+        insert_back_refs(arr->variable);
+    }
+}
+
+//calculates simple cases: if we can define for sure least general superclass to all incoming classes
+//or we deal with primitives, we replease all incoming types with "the right" type which will be recorded
+//to the attribute later
+//
+//otherwise we build a list of candidates (probably containing just single element though)
+//a difference between list of candidates of single element and reliable "the right" type is that
+//when we have more classes loaded, list of candidates might be wider, but the "right" type would be the same
+//this difference is intended and maintained for future use, e.g. if we gt instrumentation and can't
+//build attribute for the class, we may consider further algorithm improving
+vf_Result vf_Context_5e::mantain_node_consistency(StackmapElement *el) {
+
+    vf_Result tcr;
+
+    //first we call this function for ArrayConstraint target since they are not accessible by ITERATE_THRU_STACKMAP_VECTORS
+    ArrayCnstr *arr = el->firstArrayCnstr(); 
+    if( arr && (tcr = mantain_node_consistency(arr->variable)) != VF_OK ) {
+        return tcr;
+    }
+
+    assert( el->firstIncoming() );
+    assert(!((StackmapElement_Ex*)el)->firstStackmapAttrCnstr());
+
+    if( el->firstIncoming()->value == SM_THISUNINIT && !el->firstIncoming()->next() ) {
+        //preserve uninits (don't replace with BOGUS even if nobody's checking this local) 
+        //for proper calculation of the flag
+        return VF_OK;
+    }
+
+    if( !el->firstExpected() && !el->firstGenericCnstr() && !el->firstArrayCnstr() ) {
+        //it's safe to put it before "if( !el->firstIncoming()->next() ) return VF_OK;"
+        //since we treat as target as multiway and thus each constant remains constant 
+        //in Java6 verification
+        //(we don't record expected values for constants that was the risk)
+        
+        //otherwise: nobody cares
+        el->firstIncoming()->value = SM_BOGUS;
+        el->firstIncoming()->nxt = 0;
+        return VF_OK;
+    }
+
+    if( !el->firstIncoming()->next() ) return VF_OK;
+
+    //MORE THAN ONE incoming element exists
+
+    SmConstant any_resolved = SM_NONE;
+    int array_of_primitive_exists = false;
+    int assignable_from_object_exists = false;
+
+    unsigned max_arr_dims = 0;
+    unsigned min_arr_dims = 0xFFFFFFFF;
+
+    //first we remove NULLs from incoming values, check whether non-references exist among incomings
+    //see arrays and compare their dimensions, see if there is Object or arrays of Object among incoming
+    //and see if any resolved type exist among incomings
+    for( IncomingType *inc = el->firstIncoming(); inc; inc = inc->next() ) {
+        //we don't use isNonMergeable() here since there are different merging rules for Java5 and Java6
+        if( inc->value == SM_NULL ) {
+            //remove SM_NULLs
+            ((StackmapElement_Ex*)el)->removeIncoming(inc);
+        } else if( !SmConstant(inc->value).isReference() ) {
+            //we can merge objects only: all other types produce SM_BOGUS
+            el->firstIncoming()->value = SM_BOGUS;
+            el->firstIncoming()->nxt = 0;
+            return VF_OK;
+        } else {
+            //if there are arrays of differetn dimensions incoming ==> we know how to handle this, see below
+            unsigned dims = array_dims(inc->value);
+            max_arr_dims = max_arr_dims < dims ? dims : max_arr_dims;
+            min_arr_dims = min_arr_dims > dims ? dims : min_arr_dims;
+
+            //if inerface or object is coming
+            SmConstant z = get_zerodim(inc->value);
+
+            if( z.isPrimitive()) {
+                array_of_primitive_exists = true;
+            } else {
+                assignable_from_object_exists |= isObjectOrInterface(z);
+
+                //remember any resolved type if it exists
+                if( any_resolved == SM_NONE && (tpool.sm_get_handler(z) != CLASS_NOT_LOADED) ) {
+                    any_resolved = z;
+                }
+            }
+        }
+    }
+
+    //after removing of NULL only a single element remained?
+    if( !el->firstIncoming()->next() ) return VF_OK;
+
+    if( max_arr_dims != min_arr_dims || assignable_from_object_exists ) {
+        //incoming types contain arrays of different dimensions
+        //we can calculae most general type: array of dimension min_arr_dims and element type java/lang/Object
+
+        //if all dimensions are the same but there is an object or interface there
+        //we also can calculate
+        el->firstIncoming()->value = get_object_array(min_arr_dims).c;
+        el->firstIncoming()->nxt = 0;
+        return VF_OK;
+    }
+
+    if( array_of_primitive_exists ) {
+        //there is a mix of arrays of primitive and other arrays of the same dimensions
+        assert(min_arr_dims);
+        //reduce dimensions by one and create array ob objects
+        el->firstIncoming()->value = get_object_array(min_arr_dims - 1).c;
+        el->firstIncoming()->nxt = 0;
+        return VF_OK;
+    }
+
+    //////////////////////////////// NOW WE CALCULATE BACKTRACKING DATA //////////////////////////////
+
+    //first we reduce set of expected values: we remove interfaces, Objects, all primitive types, and arrays of objects
+    //(if we have array of less dimension than incoming type than its elements are objects or interfaces)
+    for( ExpectedType *exp = el->firstExpected(); exp; exp=exp->next() ) {
+        SmConstant value = exp->value;
+        if( !value.isReference() || array_dims(value) < min_arr_dims || isObjectOrInterface(get_zerodim(value)) ) {
+            ((StackmapElement_Ex*)el)->removeOther(exp);
+        }
+    }
+
+
+    //if there is a resolved type then solution for this element is 
+    //a super class of the resolved class or the resolved class itself
+    if( any_resolved != SM_NONE ) {
+        
+        IncomingType *inc = el->firstIncoming();
+        tryResolve(inc->value);
+
+        SmConstant general_type = any_resolved;
+        for (; general_type != tpool.sm_get_const_object(); general_type = sm_get_super(general_type) ) {
+            //we don't reinitialize 'inc' since all previous are assignable to a sub class 
+            //of 'general_type' and thus to 'general_type' as well
+            for( ; inc; inc = inc->next() ) {
+                if( !knownly_assignable( get_zerodim(inc->value), general_type) ) {
+                    break;
+                }
+            }
+
+            if( !inc ) { //all are assignable
+                break;
+            }
+        }
+        SmConstant found_solution = get_ref_array(min_arr_dims, general_type);
+
+        //we COULD use TRUSTED_DATA to compute solution of this mode
+        //here we validate solution to report the error sooner
+        for( ExpectedType *exp = el->firstExpected(); exp; exp = exp->next() ) {
+            if( !knownly_assignable(found_solution, exp->value) ) {
+                return error(VF_ErrorInternal, "not enough data to build stackmaptable attr: need to load more classes");
+            }
+        }
+
+        //now each incoming type s assignable to general_type
+        ((StackmapElement_Ex*)el)->newStackmapAttrCnstr(&mem, found_solution);
+    } else {
+        //now we need to create a set of possible stackmap solutions
+        //S={s_i} so that each s_i is a super class of each incoming and a sub class of each expected value
+        SmConstant sm_value = el->firstIncoming()->value;
+        SmConstant z = get_zerodim(sm_value);
+
+        parseTrustedData(z);
+
+        if( tpool.sm_get_handler(z) != CLASS_NOT_LOADED ) {
+            assert(tpool.sm_get_handler(z));
+
+            while( z != SM_NONE ) {
+                sm_value = get_ref_array(min_arr_dims, z);
+                if( check_possible_stackmap(el, sm_value) ) {
+                    ((StackmapElement_Ex*)el)->newStackmapAttrCnstr(&mem, sm_value);
+                    //we don't put those classes that have subclasses in this set ==> break
+                    break;
+                }
+                z = sm_get_super(z);
+            }
+
+            if( z == SM_NONE ) {
+                return error(VF_ErrorInternal, "not enough data to build stackmaptable attr: need to load more classes");
+            }
+        } else {
+            int possible_stackmap_cnt = 0;
+            for( SmConstant *sm = parsedTrustedData[z.getReferenceIdx()].subclasses(); *sm != SM_NONE; sm++ ) {
+                sm_value = get_ref_array(min_arr_dims, *sm);
+                if( check_possible_stackmap(el, sm_value) ) {
+                    ((StackmapElement_Ex*)el)->newStackmapAttrCnstr(&mem, sm_value);
+                    possible_stackmap_cnt++;
+                }
+            }
+
+            if( !possible_stackmap_cnt ) {
+                return error(VF_ErrorInternal, "not enough data to build stackmaptable attr: need to load more classes");
+            }
+
+            //now we reduce the set by eliminating those classes that have subclasses in this set
+            if( possible_stackmap_cnt > 1 ) {
+                for( StackmapAttrCnstr* sm1 = ((StackmapElement_Ex*)el)->firstStackmapAttrCnstr(); sm1; sm1 = sm1->next() ) {
+                    for( StackmapAttrCnstr* sm2 = sm1->next(); sm2; sm2 = sm2->next() ) {
+
+                        if( knownly_assignable(sm1->value, sm2->value) ) {
+                            //remove this stackmap element, since its subclass exists in the set
+                            ((StackmapElement_Ex*)el)->removeOther(sm2);
+                            break;
+                        }
+
+                        if( knownly_assignable(sm2->value, sm1->value) ) {
+                            //replace sm1 with sm2 and remove original sm2 
+                            //i.e. remove sm1 actually, since its subclass exists in the set
+                            sm1->value = sm2->value; 
+                            assert(sm1->depth == sm2->depth);
+                            ((StackmapElement_Ex*)el)->removeOther(sm2);
+                            break;
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    arc_stack.push(el);
+
+    return VF_OK;
+}
+
+
+vf_Result vf_Context_5e::mantain_arc_consistency(int depth) {
+    vf_Result tcr;
+    while( !arc_stack.is_empty() ) {
+        if( (tcr=arc_consistensy_in_node( arc_stack.pop(), depth)) != VF_OK ) {
+            return tcr;
+        }
+    }
+    return VF_OK;
+}
+
+//check that each stackmap candidates in the nodes accessible from the current one
+//has an arc-consitent value in the current mode 
+//the method is called each time set of candidates for the given node is changed
+vf_Result vf_Context_5e::arc_consistensy_in_node(StackmapElement *el, int depth) {
+
+    for( Constraint *adjacent = el->firstOthers(); adjacent; adjacent = adjacent->next() ) {
+        if( !is_arc(adjacent) ) continue;
+
+        int possible_stackmap_cnt = 0;
+        int changed = false;
+
+        for( StackmapAttrCnstr *sm2 = ((StackmapElement_Ex*)adjacent->variable)->firstStackmapAttrCnstr(); sm2; sm2 = sm2->next()) {
+
+            //is a stackmap and not removed
+            if( !sm2->depth ) {
+
+                StackmapAttrCnstr *sm_this = ((StackmapElement_Ex*)el)->firstStackmapAttrCnstr();
+                for(; sm_this; sm_this=sm_this->next() ) {
+                    //temporarily removed element?
+                    if( sm_this->depth ) continue;
+
+                    int valid_arc_found = is_direct_arc(adjacent) ? 
+                        knownly_assignable(sm_this->value, sm2->value, adjacent->type == CT_ARRAY2REF) :
+                        knownly_assignable(sm2->value, sm_this->value, adjacent->type == CTX_REVERSED_ARRAY2REF);
+
+                    if( valid_arc_found ) {
+                        //stackmap has a subclass in a branch target ==> this arc is OK, check next one
+                        possible_stackmap_cnt++;
+                        break;
+                    }
+                }
+
+                if( !sm_this ) {
+                    //no valid arcs - remove possible stackmap
+                    if( depth ) {
+                        //remove temporarily
+                        sm2->depth = depth;
+                    } else {
+                        //remove permanently {
+                        ((StackmapElement_Ex*)adjacent->variable)->removeOther(sm2);
+                    }
+                    changed = true;
+                }
+            }
+        }
+
+        if( changed ) {
+            if( !possible_stackmap_cnt ) {
+                return depth ? VF_ErrorInternal : 
+                error(VF_ErrorInternal, "not enough data to build stackmaptable attr: need to load more classes");
+            }
+            arc_stack.push( adjacent->variable );
+        }
+    }
+    return VF_OK;
+}
+
+void vf_Context_5e::push_subgraph(StackmapElement *el) {
+    if( subgraph_stack.instack( el ) ) return;
+
+    subgraph_stack.push( el );
+
+    for( Constraint *adjacent = el->firstOthers(); adjacent; adjacent = adjacent->next() ) {
+        if( is_arc(adjacent) ) push_subgraph(adjacent->variable);
+    }
+}
+
+
+vf_Result vf_Context_5e::calculate_subgraph(StackmapElement *el) {
+    if( is_node_calculated(el) || no_stackmap_choice((StackmapElement_Ex*)el) ) return VF_OK;
+
+    subgraph_stack.init();
+
+    //push all elements accessible from el on stack
+    push_subgraph(el);
+
+    //TODO: remove calculated nodes
+
+    //do backtracking
+    return do_backtracking(0);
+}
+
+vf_Result vf_Context_5e::do_backtracking(int old_depth) {
+    if( old_depth == subgraph_stack.get_depth() ) {
+        //put breakpoint here
+        //solution found!!!
+        return VF_OK;
+    }
+
+    StackmapElement_Ex *cur = (StackmapElement_Ex*)subgraph_stack.at(old_depth);
+    int depth = old_depth + 1;
+
+    if( is_node_calculated(cur) || no_stackmap_choice((StackmapElement_Ex*)cur) ) {
+        return do_backtracking(depth);
+    }
+
+    //first 'remove' all remaining stackmaps
+    for( StackmapAttrCnstr *sm = cur->firstStackmapAttrCnstr(); sm; sm = sm->next() ) {
+        assert(sm->depth < depth);
+        if( !sm->depth ) sm->depth = depth;
+    }
+
+    //then try to include them one-by-one 
+    for( StackmapAttrCnstr *sm = cur->firstStackmapAttrCnstr(); sm; sm = sm->next() ) {
+        if( sm->depth != depth ) continue;
+
+        sm->depth = 0;
+        arc_stack.push(cur);
+        if( mantain_arc_consistency(depth) == VF_OK && do_backtracking(depth) == VF_OK ) {
+            //solution has been found
+            return VF_OK;
+        }
+
+        //the value is inconsistent ==> do cleanup
+        for( int i = depth; i < subgraph_stack.get_depth(); i++) {
+            for( StackmapAttrCnstr *sm = ((StackmapElement_Ex*)subgraph_stack.at(i))->firstStackmapAttrCnstr(); sm; sm = sm->next() ) {
+                assert(sm->depth <= depth + 1);
+                if( sm->depth >= depth ) sm->depth = 0;
+            }
+        }
+        sm->depth = depth;
+    }
+    return depth ? VF_ErrorInternal : error(VF_ErrorInternal, "not enough data to build stackmaptable attr: need to load more classes");
+}
+
+void vf_Context_5e::parseTrustedData(SmConstant value, int knownly_interface) {
+    int idx = value.getReferenceIdx();
+
+    if( idx >= parsedDataSz ) {
+        parsedTrustedData = (RefInfo*)tc_realloc(parsedTrustedData, (idx+1)*sizeof(RefInfo));
+        for( int i = parsedDataSz; i <= idx; i++ ) {
+            parsedTrustedData[i].init();
+        }
+        parsedDataSz = idx + 1;
+    }
+
+    if( parsedTrustedData[idx].is_calculated() ) return;
+
+    if( parsedTrustedData[idx].is_being_calculated() || knownly_interface) {
+         //already on stack
+        parsedTrustedData[idx].set_interface();
+        return;
+    }
+    parsedTrustedData[idx].set_being_calculated();
+
+    vf_ValidType *t = tpool.getVaildType(idx);
+    if( !t->cls ) {
+        t->cls = vf_resolve_class(k_class, t->name, false);
+        if( !t->cls ) t->cls = CLASS_NOT_LOADED;
+    }
+
+    if( t->cls != CLASS_NOT_LOADED ) {
+        if( class_is_interface_(t->cls) ) {
+            parsedTrustedData[idx].set_interface();
+        } else {
+            SmConstant* subcls = (SmConstant*)mem.malloc(2*sizeof(SmConstant));
+            subcls[0] = value;
+            subcls[1] = SM_NONE;
+            
+            parsedTrustedData[idx].set_subclasses(subcls);
+        }
+        return;
+    }
+
+    int c;
+    for( c = 0; c < trustedPairsCnt; c++ ) {
+        if( trustedPairs[c].from == value ) {
+            parseTrustedData(trustedPairs[c].to);
+        }
+    }
+
+    class_stack.init();
+    class_stack.push(tpool.sm_get_const_object());
+    class_stack.push(value);
+    for( c = 0; c < trustedPairsCnt; c++ ) {
+        if( trustedPairs[c].from == value ) {
+            for( SmConstant *sm = parsedTrustedData[trustedPairs[c].to.getReferenceIdx()].subclasses(); *sm != SM_NONE; sm++ ) {
+                if( !class_stack.instack(*sm) ) class_stack.push(*sm);
+            }
+        }
+    }
+
+    if( parsedTrustedData[idx].is_interface() ) {
+        while ( !class_stack.is_empty() ) parsedTrustedData[class_stack.pop().getReferenceIdx()].set_interface();
+    } else {
+        SmConstant* subcls = (SmConstant*)mem.malloc((class_stack.get_depth()+1)*sizeof(SmConstant));
+
+        parsedTrustedData[idx].set_subclasses(subcls);
+        int i = 0;
+        while ( !class_stack.is_empty() ) subcls[i++] = class_stack.pop();
+        subcls[i] = SM_NONE;
+    }
+}
+
+void vf_Context_5e::parseTrustedPairs() {
+    trustedPairsCnt = 0;
+    if( !class_constraints ) return;
+
+    for( vf_TypeConstraint *constraint = (vf_TypeConstraint*)unparsedPairs; constraint; constraint = constraint->next ) {
+        trustedPairsCnt++;
+    }
+    trustedPairs = (TrustedPair*)mem.malloc(trustedPairsCnt * sizeof(TrustedPair));
+
+    int i = 0;
+    for( vf_TypeConstraint *constraint = (vf_TypeConstraint*)unparsedPairs; constraint; constraint = constraint->next ) {
+        trustedPairs[i].from = tpool.get_ref_type(constraint->source);
+        tryResolve(trustedPairs[i].from);
+
+        trustedPairs[i].to = tpool.get_ref_type(constraint->target);
+        tryResolve(trustedPairs[i].to);
+
+        i++;
+    }
+
+    //find all classes that are subclasses of the loaded classes but due to broken 
+    //delegation model in classloaders are not loaded (this is necessary because
+    //we don't check against trusted pairs when we check assignability and 'from' is loaded
+    int changed;
+    do {
+        changed = false;
+        for( i = 0; i < trustedPairsCnt; i++ ) {
+            class_handler from_cls = tpool.sm_get_handler(trustedPairs[i].from);
+
+            if( from_cls != CLASS_NOT_LOADED && 
+                tpool.sm_get_handler(trustedPairs[i].to) == CLASS_NOT_LOADED ) 
+            {
+                class_handler to_cls = class_is_extending_class(from_cls, tpool.sm_get_refname(trustedPairs[i].to));
+
+                if( to_cls ) {
+                    tpool.getVaildType(trustedPairs[i].to.getReferenceIdx())->cls = to_cls;
+                    changed = true;
+                }
+            }
+        }
+    } while (changed);
+
+    for( i = 0; i < trustedPairsCnt; i++ ) {
+        if( tpool.sm_get_handler(trustedPairs[i].from) != CLASS_NOT_LOADED && 
+            tpool.sm_get_handler(trustedPairs[i].to) == CLASS_NOT_LOADED ) 
+        {
+            parseTrustedData(trustedPairs[i].to, true);
+        }
+    }
+
+    tryResolve(tpool.sm_get_const_object());
+    tryResolve(tpool.sm_get_const_this());
+}

Propchange: harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/x_verifier/recompute.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

Added: harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/x_verifier/recompute.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/x_verifier/recompute.h?rev=619847&view=auto
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/x_verifier/recompute.h (added)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/x_verifier/recompute.h Fri Feb  8 03:53:11 2008
@@ -0,0 +1,499 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/** 
+ * @author Mikhail Loenko, Vladimir Molotkov
+ */  
+
+#ifndef __RECOMPUTE_H__
+#define __RECOMPUTE_H__
+
+#include <assert.h>
+#include <string.h>
+#include "../java5/context_5.h"
+#include "x_class_interface.h"
+
+
+vf_Result vf_recompute_stackmaptable( method_handler method, uint8 **attrBytes, char **error, void *trustedPairs );
+
+namespace CPVerifier_5 {
+
+    //possible relations between verificaton types
+    enum ConstraintType_Ex {
+        CTX_REVERSED_GENERIC = 4,
+        CTX_REVERSED_ARRAY2REF = 5,
+        CTX_POSSIBLE_STACKMAP = 6
+    };
+
+    struct ReversedGenericCnstr : Constraint {
+        ReversedGenericCnstr *next() {
+            return (ReversedGenericCnstr *) Constraint::next(Constraint::next(), CTX_REVERSED_GENERIC);
+        }
+    };
+
+    struct ReversedArrayCnstr : Constraint {
+        ReversedArrayCnstr *next() {
+            return (ReversedArrayCnstr *) Constraint::next(Constraint::next(), CTX_REVERSED_ARRAY2REF);
+        }
+    };
+
+    struct StackmapAttrCnstr : Constraint {
+        int depth;
+
+        StackmapAttrCnstr *next() {
+            return (StackmapAttrCnstr *) Constraint::next(Constraint::next(), CTX_POSSIBLE_STACKMAP);
+        }
+    };
+
+    struct StackmapElement_Ex : StackmapElement { //TODO: should be rewritten to save footprint
+        ReversedGenericCnstr *firstReversedGenericCnstr() {
+            return (ReversedGenericCnstr*)Constraint::next(others, CTX_REVERSED_GENERIC);
+        }
+
+        ReversedArrayCnstr *firstReversedArrayCnstr() {
+            return (ReversedArrayCnstr*)Constraint::next(others, CTX_REVERSED_ARRAY2REF);
+        }
+
+        StackmapAttrCnstr *firstStackmapAttrCnstr() {
+            return (StackmapAttrCnstr*)Constraint::next(others, CTX_POSSIBLE_STACKMAP);
+        }
+
+        int newReversedGenericCnstr_safe(Memory *mem, StackmapElement *to) {
+            ReversedGenericCnstr *rgen = firstReversedGenericCnstr();
+            while( rgen ) {
+                if( rgen->variable == to ) return false;
+                rgen = rgen->next();
+            }
+            newConstraint(mem, CTX_REVERSED_GENERIC)->variable = to;
+            return true;
+        }
+
+        int newReversedArrayCnstr_safe(Memory *mem, StackmapElement *to) {
+            ReversedArrayCnstr *rarr = firstReversedArrayCnstr();
+            while( rarr ) {
+                if( rarr->variable == to ) return false;
+                rarr = rarr->next();
+            }
+            newConstraint(mem, CTX_REVERSED_ARRAY2REF)->variable = to;
+            return true;
+        }
+
+        void newStackmapAttrCnstr(Memory *mem, SmConstant value) {
+            StackmapAttrCnstr *sm = (StackmapAttrCnstr *)mem->malloc(sizeof(StackmapAttrCnstr));
+
+            sm->nxt = others;
+            sm->type = (ConstraintType)CTX_POSSIBLE_STACKMAP;
+            sm->value = value.c;
+            sm->depth = 0;
+
+            others = sm;
+        }
+
+        void removeIncoming(IncomingType *inc) {
+            IncomingType *ptr = firstIncoming();
+            assert(ptr);
+
+            if( inc == ptr ) {
+                POINTER_SIZE_INT mask = (POINTER_SIZE_INT)incoming & 3;
+                incoming = (IncomingType *) ((POINTER_SIZE_INT)inc->next() | mask);
+            } else {
+                while( ptr->next() != inc ) {
+                    ptr = ptr->next();
+                    assert(ptr);
+                }
+                ptr->nxt = inc->nxt;
+            }
+        }
+
+        void removeOther(Constraint *o) {
+            Constraint *ptr = firstOthers();
+            assert(ptr);
+
+            if( o == ptr ) {
+                others = o->next();
+            } else {
+                while( ptr->next() != o ) {
+                    ptr = ptr->next();
+                    assert(ptr);
+                }
+                ptr->nxt = o->nxt;
+            }
+        }
+
+    };
+
+    struct RefInfo {
+        union {
+            SmConstant *subcls;
+            unsigned    mask;
+        };
+
+        void init() {
+            mask = 0xFFFFFFFF;
+        }
+
+        int is_being_calculated() {
+            return mask == 0xFFFFFFFE;
+        }
+
+        void set_being_calculated() {
+            mask = 0xFFFFFFFE;
+        }
+
+        int is_calculated() {
+            return mask != 0xFFFFFFFF && !is_being_calculated();
+        }
+
+        int is_interface() {
+            return !subcls;
+        }
+
+        void set_interface() {
+            subcls = 0;
+            *((SmConstant*)&mask) = SM_NONE;
+        }
+
+        SmConstant *subclasses() {
+            //always return valis pointer
+            return subcls ? subcls : (SmConstant*)&mask;
+        }
+
+        void set_subclasses(SmConstant *s) {
+            mask = 0; //just in case
+            subcls = s;
+        }
+    };
+
+    struct TrustedPair {
+        SmConstant from;
+        SmConstant to;
+    };
+
+    //
+    // Context - main class of Type Checker
+    //
+
+    class vf_Context_5e : public vf_Context_5 {
+    public:
+        vf_Context_5e(SharedClasswideData &classwide, void *_unparsedPairs) :
+          vf_Context_5(classwide), parsedTrustedData(0), parsedDataSz(0), unparsedPairs(_unparsedPairs)
+          {
+              //we would like to flush StackMapTable attribute from this method
+              stackmapattr_calculation = true;
+          }
+
+        vf_Result recompute_stackmaptable( method_handler method );
+
+        ~vf_Context_5e() {
+            tc_free(parsedTrustedData);
+        }
+            
+        uint8* written_stackmap;
+
+    protected:
+        void writeStackMapFrame( Address instr);
+        vf_Result fillCurFrame(PropsHead *head);
+        void writeStackMapFrame_Full( uint32 offset);
+        void writeStackMapFrame_SameLocalsOneStack( uint32 offset);
+        void writeStackMapFrame_Same( uint32 offset);
+        void writeStackMapFrame_Cut( uint32 offset, int attr_delta, int workmap_delta);
+        void writeStackMapFrame_Append( uint32 offset, int attr_delta, int workmap_delta);
+        void writeStackMapElements( uint32 start, uint32 cnt);
+
+        void writeByte(uint8 byte) {
+            if( !written_stackmap ) {
+                attrLen = 2; // reserve uint16 for number of enries
+                attrSz = 0;
+            }
+
+
+
+            if( attrLen + 6 >= attrSz ) {
+                attrSz += 4096;
+                written_stackmap = (uint8*) tc_realloc(written_stackmap, attrSz);
+            }
+
+            written_stackmap[attrLen + 6] = byte;
+            attrLen++;
+        }
+
+
+        unsigned lastLocalsNo;
+        int lastInstr;
+        WorkmapHead *curFrame;
+        ///////////////////////
+        vf_Result do_recompute();
+        vf_Result mantain_node_consistency(StackmapElement *el);
+        vf_Result arc_consistensy_in_node(StackmapElement *el, int depth);
+        vf_Result mantain_arc_consistency(int depth);
+        vf_Result calculate_subgraph(StackmapElement *el);
+        vf_Result do_backtracking(int depth);
+
+        void push_subgraph(StackmapElement *el);
+        void insert_back_refs(StackmapElement *el);
+
+        SmConstant get_node_value(PropsHead *head, int i) {
+            StackmapElement_Ex *el;
+
+            if( head->is_workmap() ) {
+                WorkmapHead *w = head->getWorkmap();
+                if( !w->elements[i].isVariable() ) {
+                    return w->elements[i].getConst();
+                }
+
+                el = (StackmapElement_Ex*)(w->elements[i].getVariable());
+            } else {
+                el = (StackmapElement_Ex*)(&head->getStackmap()->elements[i]);
+            }
+
+            if( is_node_calculated(el) ) {
+                return el->firstIncoming()->value;
+            }
+            assert(no_stackmap_choice(el));
+
+            for( StackmapAttrCnstr *sm = el->firstStackmapAttrCnstr(); sm; sm=sm->next() ) {
+                if( !sm->depth ) {
+                    return sm->value;
+                }
+            }
+            assert(0);
+            return SM_BOGUS;
+        }
+
+        int is_node_calculated(StackmapElement *el) {
+            assert(el->firstIncoming());
+            //assert( el->firstIncoming()->next() || !SmConstant(el->firstIncoming()->value).isReference() || class_get_cp_class_entry(k_class, tpool.sm_get_refname(el->firstIncoming()->value)));
+            return !el->firstIncoming()->next();
+        }
+
+        int no_stackmap_choice(StackmapElement_Ex *el) {
+            assert(el->firstStackmapAttrCnstr());
+            int stackmapcnt = 0;
+            for( StackmapAttrCnstr *sm = el->firstStackmapAttrCnstr(); sm; sm=sm->next() ) {
+                if( !sm->depth ) {
+                    stackmapcnt++;
+                    if( stackmapcnt == 2 ) return false;
+                }
+            }
+            assert(stackmapcnt == 1);
+            //assert( class_get_cp_class_entry(k_class, tpool.sm_get_refname(el->firstStackmapAttrCnstr()->value)));
+            return true;
+        }
+
+        SmConstant get_object_array(int dimension) {
+            return dimension ? get_ref_array(dimension, "java/lang/Object") : tpool.sm_get_const_object();
+        }
+
+        SmConstant get_ref_array(int dimension, SmConstant ref) {
+            return dimension ? get_ref_array(dimension, tpool.sm_get_refname(ref)) : ref;
+        }
+
+        SmConstant get_ref_array(int dimension, const char* ref_name) {
+            assert(dimension);
+            int name_len = (int)strlen(ref_name);
+
+            char *name = (char*)mem.malloc(name_len + dimension + 2);
+            tc_memset(name, '[', dimension);
+            name[dimension] = 'L';
+            tc_memcpy(name + dimension + 1, ref_name, name_len);
+            name[dimension + name_len + 1] = ';';
+
+            SmConstant ret = tpool.get_ref_type(name, name_len + dimension + 2);
+            mem.dealloc_last(name, name_len + dimension + 2);
+            return ret;
+        }
+
+
+        SmConstant get_zerodim(SmConstant value) {
+            const char* name = tpool.sm_get_refname(value);
+            if( name[0] != '[' ) return value;
+
+            while( name[0] == '[' ) name++;
+            return tpool.get_type(name);
+        }
+
+        unsigned array_dims(SmConstant ref) {
+            const char* start = tpool.sm_get_refname(ref);
+            const char* name = start;
+            while( name[0] == '[' ) name++;
+            return (unsigned)(name-start);
+        }
+
+        int isObjectOrInterface(SmConstant ref) {
+            if( ref == tpool.sm_get_const_object() ) return true;
+
+            class_handler h = tpool.sm_get_handler(ref);
+            if( h && h != CLASS_NOT_LOADED ) return class_is_interface_(h);
+
+            parseTrustedData(ref);
+            return parsedTrustedData[ref.getReferenceIdx()].is_interface();
+        }
+
+        int knownly_assignable(SmConstant from, SmConstant to, int array_element = 0) {
+            if( from == to && !array_element ) return true;
+
+            unsigned from_dims = array_dims(from);
+            unsigned to_dims = array_dims(to) + (array_element ? 1 : 0);
+
+            if( to_dims > from_dims ) return false;
+            if( to_dims < from_dims ) return isObjectOrInterface( get_zerodim(to) );
+
+            from = get_zerodim(from);
+            to = get_zerodim(to);
+
+            if( isObjectOrInterface(to) ) return true;
+
+            parseTrustedData(from); // it may change class_handler for 'to'
+
+            class_handler f = tpool.sm_get_handler(from);
+            assert(f);
+            class_handler t = tpool.sm_get_handler(to);
+            assert(t);
+
+            if( f != CLASS_NOT_LOADED ) {
+                return t != CLASS_NOT_LOADED && vf_is_extending(f, t);
+            }
+
+            for( SmConstant *sm = parsedTrustedData[from.getReferenceIdx()].subclasses(); *sm != SM_NONE; sm++ ) {
+                if( *sm == to ) {
+                    return true;
+                }
+
+                if( t != CLASS_NOT_LOADED ) {
+                    class_handler f1 = tpool.sm_get_handler(*sm);
+                    if( f1 != CLASS_NOT_LOADED && vf_is_extending(f1, t) ) return true;
+                }                
+            }
+            return false;
+        }
+
+
+        int check_possible_stackmap(StackmapElement *el, SmConstant sm) {
+            for( IncomingType *inc = el->firstIncoming()->next(); inc; inc = inc->next()) {
+                if( !knownly_assignable(inc->value, sm) ) {
+                    //bad stackmap element
+                    return false;
+                }
+            }
+
+            for( ExpectedType *exp = el->firstExpected(); exp; exp = exp->next() ) {
+                if( !knownly_assignable(sm, exp->value) ) {
+                    //bad stackmap element
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        SmConstant sm_get_super(SmConstant value) {
+            class_handler h = tpool.sm_get_handler(value);
+            assert(h && h!= CLASS_NOT_LOADED);
+            h = class_get_super_class(h);
+            if( h ) {
+                SmConstant sup = tpool.get_ref_type( class_get_name(h));
+                vf_ValidType *s = tpool.getVaildType(sup.getReferenceIdx());
+                s->cls = h;
+
+                return sup;
+            }
+            return SM_NONE;
+        }
+
+        int is_arc(Constraint *c) {
+            return is_direct_arc(c) || is_reversed_arc(c);
+        }
+
+        int is_direct_arc(Constraint *c) {
+            return c->type == CT_GENERIC || c->type == CT_ARRAY2REF;
+        }
+
+        int is_reversed_arc(Constraint *c) {
+            return c->type == CTX_REVERSED_GENERIC || c->type == CTX_REVERSED_ARRAY2REF;
+        }
+
+
+        void reduceTryBlocks(Address dead_code_start, Address dead_code_end) {
+            unsigned short start_pc;
+            unsigned short end_pc;
+            unsigned short handler_pc;
+            unsigned short handler_cp_index;
+
+            for( unsigned idx = 0; idx < m_handlecount; idx++ ) {
+                method_get_exc_handler_info( m_method, idx, &start_pc, &end_pc, &handler_pc, &handler_cp_index );
+
+                if( start_pc >= dead_code_start && end_pc <= dead_code_end ) {
+                    method_remove_exc_handler( m_method, idx );
+                    idx--;
+                } else if( end_pc > dead_code_start && end_pc <= dead_code_end ) {
+                    method_modify_exc_handler_info( m_method, idx, start_pc, dead_code_start, handler_pc, handler_cp_index );
+                } else if( start_pc >= dead_code_start && start_pc < dead_code_end  ) {
+                    method_modify_exc_handler_info( m_method, idx, dead_code_end, end_pc, handler_pc, handler_cp_index );
+                }
+            }
+        }
+
+        void parseTrustedData(SmConstant value, int knownly_interface = false);
+        void parseTrustedPairs();
+
+        void tryResolve(SmConstant ref) {
+            vf_ValidType *f = tpool.getVaildType(ref.getReferenceIdx());
+            if( !f->cls ) {
+                f->cls = vf_resolve_class(k_class, f->name, false);
+                if( !f->cls ) f->cls = CLASS_NOT_LOADED;
+            }
+        }
+
+
+        FastStack<StackmapElement*> arc_stack;
+        FastStack<StackmapElement*> subgraph_stack;
+        FastStack<SmConstant> class_stack;
+        
+        RefInfo *parsedTrustedData;
+        int parsedDataSz;
+
+        TrustedPair* trustedPairs;
+        int trustedPairsCnt;
+        void* unparsedPairs;
+
+
+        uint32 attrLen;
+        uint32 attrSz;
+    };
+
+
+
+#define ITERATE_THRU_STACKMAP_VECTORS(CODE)                                         \
+    for( int i = 0; i < props.hash_size; i++ ) {                                    \
+        PropsHead *pro = (PropsHead*)(props.propHashTable[i]);                      \
+        while(pro) {                                                                \
+            if( !pro->is_workmap() ) {                                              \
+                StackmapHead *sm = pro->getStackmap();                              \
+                                                                                    \
+                for( unsigned j = 0; j < m_stack_start + sm->depth; j++ ) {         \
+                    /*skip uninit flag*/                                            \
+                    if( j == m_max_locals && j < m_stack_start ) continue;          \
+                                                                                    \
+                    StackmapElement *el = &(sm->elements[j]);                       \
+                    CODE;                                                           \
+                }                                                                   \
+            }                                                                       \
+            pro=(PropsHead *)pro->next;                                             \
+        }                                                                           \
+    }                                                                               \
+
+} // namespace CPVerifier_5
+
+#endif

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

Added: harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/x_verifier/write_attr.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/x_verifier/write_attr.cpp?rev=619847&view=auto
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/x_verifier/write_attr.cpp (added)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/x_verifier/write_attr.cpp Fri Feb  8 03:53:11 2008
@@ -0,0 +1,252 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/** 
+ * @author Mikhail Loenko, Vladimir Molotkov
+ */  
+
+
+
+#include <iostream>
+
+using namespace std;
+
+#include "recompute.h"
+#include "../java6/stackmap_6.h"
+#include "time.h"
+
+using namespace CPVerifier;
+using namespace CPVerifier_5;
+using namespace CPVerifier_6;
+
+static char err_message[5000];
+
+
+void vf_Context_5e::writeStackMapFrame( Address instr )
+{
+    assert(instr != -1 || 1 + lastInstr < instr );
+    uint32 offset = lastInstr == -1 ? instr : instr - lastInstr - 1;
+    lastInstr = instr;
+
+    if( curFrame->depth == 0 ) {
+        //possible variants when not the whole frame is recorded: 
+        //locals are the same, 0-2 locals are cut, locals are extended by 0-2 elements
+        bool all_locals_same = true;
+        unsigned first_changed_local = 0;
+        unsigned last_changed_local = 0;
+
+        for( int i = (int)m_max_locals - 1; i >= 0; i-- ) {
+            if( curFrame->elements[i].getConst() != workmap->elements[i].getConst() ) {
+                all_locals_same = false;
+                first_changed_local = i;
+                if( !last_changed_local ) last_changed_local = i;
+            }
+        }
+
+        if( all_locals_same ) {
+            return writeStackMapFrame_Same(offset);
+        } 
+
+        if( first_changed_local < lastLocalsNo ) {
+            //check whether it's a CUT
+            if( last_changed_local >= lastLocalsNo ) {
+                return writeStackMapFrame_Full(offset);
+            }
+
+            int cut_sz = 0; // number of elements cut in attribute (long and double are single size units)
+            int cut_realsz = 0; // number of elements cut in workmap structure (long and double are double size units)
+            for( unsigned i = first_changed_local; i < lastLocalsNo; i++ ) {
+                if( curFrame->elements[i].getConst() != SM_BOGUS ) {
+                    return writeStackMapFrame_Full(offset);
+                }
+
+                cut_realsz++;
+                if( workmap->elements[i].getConst() != SM_HIGH_WORD ) {
+                    //can't cut more than 3 elements
+                    cut_sz++;
+                }
+            }
+            if( cut_sz > 3 ) {
+                return writeStackMapFrame_Full(offset);
+            }
+            return writeStackMapFrame_Cut(offset, cut_sz, cut_realsz);
+        } else {
+            //check whether it's an APPEND
+            int app_sz = 0;  // number of elements appended in attribute (long and double are single size units)
+            int app_realsz = 0; // number of elements appended in workmap structure (long and double are double size units)
+            for( unsigned i = lastLocalsNo; i < last_changed_local + 1; i++ ) {
+                assert( workmap->elements[i].getConst() == SM_BOGUS );
+
+                app_realsz++;
+                if( curFrame->elements[i].getConst() != SM_HIGH_WORD ) {
+                    app_sz++;
+                }
+            }
+            if( app_sz > 3 ) {
+                //can't append more than 3 elements
+                return writeStackMapFrame_Full(offset);
+            }
+            return writeStackMapFrame_Append(offset, app_sz, app_realsz);
+        }
+    } else if( curFrame->depth == 1 || curFrame->depth == 2 && curFrame->elements[m_stack_start + 1].getConst() == SM_HIGH_WORD) {
+        for( unsigned i = 0; i < m_max_locals; i++ ) {
+            if( curFrame->elements[i].getConst() != workmap->elements[i].getConst() ) {
+                return writeStackMapFrame_Full(offset);
+            }
+        }
+        return writeStackMapFrame_SameLocalsOneStack(offset);
+    } else {
+        return writeStackMapFrame_Full(offset);
+    }
+
+} // writeStackMapFrame
+
+void vf_Context_5e::writeStackMapFrame_Full( uint32 offset ) {
+    writeByte(255); // full stack frame
+
+    writeByte(offset >> 8); // offset
+    writeByte(offset & 0xFF); // offset
+
+    unsigned locals_realsz; // number of elements in workmap structure (long and double are double size units)
+    for( locals_realsz = m_max_locals; locals_realsz > 0; locals_realsz-- ) {
+        if( curFrame->elements[locals_realsz - 1].getConst() != SM_BOGUS ) {
+             break;
+        }
+    }
+
+    unsigned locals_sz = 0; // number of elements in attribute (long and double are single size units)
+    for( unsigned i = 0; i < locals_realsz; i++ ) {
+        if( curFrame->elements[i].getConst() != SM_HIGH_WORD ) {
+             locals_sz++;
+        }
+    }
+
+    writeByte(locals_sz >> 8); // locals_sz
+    writeByte(locals_sz & 0xFF); // locals_sz
+
+    writeStackMapElements(0, locals_realsz);
+    lastLocalsNo = locals_realsz;
+
+    /////////////////////////////////
+
+    unsigned stack_sz = 0; // number of stack elements in attribute (long and double are single size units)
+    for( unsigned i = 0; i < curFrame->depth; i++ ) {
+        if( curFrame->elements[m_stack_start + i].getConst() != SM_HIGH_WORD ) {
+             stack_sz++;
+        }
+    }
+
+    writeByte(stack_sz >> 8); // stack depth
+    writeByte(stack_sz & 0xFF); // stack depth
+
+    writeStackMapElements(m_stack_start, curFrame->depth);
+
+}
+
+void vf_Context_5e::writeStackMapFrame_SameLocalsOneStack( uint32 offset ) {
+    
+    if( offset < 64 ) {
+        writeByte(offset + 64); // same locals one stack item
+        writeStackMapElements(m_stack_start, 1);
+    } else {
+        writeByte(247); // one stack extended
+
+        writeByte(offset >> 8); // offset
+        writeByte(offset & 0xFF); // offset
+        writeStackMapElements(m_stack_start, 1);
+    }
+}
+
+void vf_Context_5e::writeStackMapFrame_Same( uint32 offset ) {
+
+    if( offset < 64 ) {
+        writeByte(offset); // same
+    } else {
+        writeByte(251); // same extended
+        writeByte(offset >> 8); // offset
+        writeByte(offset & 0xFF); // offset
+    }
+}
+
+void vf_Context_5e::writeStackMapFrame_Cut( uint32 offset, int cut_sz, int cut_realsz ) {
+
+    writeByte(251 - cut_sz); // same extended
+
+    writeByte(offset >> 8); // offset
+    writeByte(offset & 0xFF); // offset
+
+    lastLocalsNo -= cut_realsz;
+}
+
+void vf_Context_5e::writeStackMapFrame_Append( uint32 offset, int app_sz, int app_realsz ) {
+
+    writeByte(251 + app_sz); // same extended
+
+    writeByte(offset >> 8); // offset
+    writeByte(offset & 0xFF); // offset
+
+    writeStackMapElements(lastLocalsNo, app_realsz);
+
+    lastLocalsNo += app_realsz;
+}
+
+void vf_Context_5e::writeStackMapElements( uint32 start, uint32 cnt ) {
+    while( cnt ) {
+        SmConstant el = curFrame->elements[start].const_val;
+        workmap->elements[start].const_val = el;
+
+        if( el.isReference() ) {
+            writeByte(ITEM_OBJECT);
+
+            uint16 cp_idx = class_get_cp_class_entry( k_class, tpool.sm_get_refname(el));
+            writeByte(cp_idx >> 8);
+            writeByte(cp_idx & 0xFF);
+        } else if( el.isNewObject() ) {
+            writeByte(ITEM_UNINITIALIZED);
+
+            uint16 instr = el.getNewInstr();
+            writeByte(instr >> 8);
+            writeByte(instr & 0xFF);
+        } else switch ( el.c ) {
+            case SM_HIGH_WORD:
+                break;
+            case SM_NULL:
+                writeByte(ITEM_NULL);
+                break;
+            case SM_INTEGER:
+                writeByte(ITEM_INTEGER);
+                break;
+            case SM_FLOAT:
+                writeByte(ITEM_FLOAT);
+                break;
+            case SM_LONG:
+                writeByte(ITEM_LONG);
+                break;
+            case SM_DOUBLE:
+                writeByte(ITEM_DOUBLE);
+                break;
+            case SM_THISUNINIT:
+                writeByte(ITEM_UNINITIALIZEDTHIS);
+                break;
+            default:
+                writeByte(ITEM_TOP);
+                break;
+        }
+        start++;
+        cnt--;
+    }
+}
+

Propchange: harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/x_verifier/write_attr.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

Added: harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/x_verifier/x_class_interface.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/x_verifier/x_class_interface.h?rev=619847&view=auto
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/x_verifier/x_class_interface.h (added)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/x_verifier/x_class_interface.h Fri Feb  8 03:53:11 2008
@@ -0,0 +1,41 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/** 
+ * @author Mikhail Loenko, Vladimir Molotkov
+ */  
+
+#ifndef __X_CLASS_INTERFACE_H__
+#define __X_CLASS_INTERFACE_H__
+
+
+/**
+ * returns constantpool index for the given class
+ */
+unsigned short class_get_cp_class_entry(class_handler k_class, const char* name);
+
+/**
+ * removes given exception handler (handlers with greater indexes shift)
+ */
+void method_remove_exc_handler( method_handler method, unsigned short idx );
+
+/**
+ * modifies start_pc, end_pc 
+ */
+void method_modify_exc_handler_info( method_handler method, unsigned short idx, unsigned short start_pc, 
+                                    unsigned short end_pc, unsigned short handler_pc, unsigned short handler_cp_index );
+
+#endif

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

Added: harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/x_verifier/x_verifier.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/x_verifier/x_verifier.cpp?rev=619847&view=auto
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/x_verifier/x_verifier.cpp (added)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/x_verifier/x_verifier.cpp Fri Feb  8 03:53:11 2008
@@ -0,0 +1,97 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/** 
+ * @author Mikhail Loenko
+ */  
+
+
+
+#include <iostream>
+
+using namespace std;
+
+#include "recompute.h"
+#include "x_verifier.h"
+#include "../java6/context_6.h"
+#include "time.h"
+
+using namespace CPVerifier;
+using namespace CPVerifier_6;
+
+
+/**
+ * Allocates an empty verification context for a class, 
+ * to be passed back to the verifier upon verification requests.
+ * Memory must be disposed by calling free_verification_context 
+ * (see below).
+ * @param klass - class handler
+ * @return a verification context for the class
+ */
+verification_context
+allocate_verification_context(class_handler klass) {
+    return (verification_context) (new SharedClasswideData(klass));
+}
+
+
+/**
+ * Initializes the verification context with method's information. 
+ * This function must be called before instrumenting the method.
+ * The resulting context should be passed back to the verifier 
+ * upon verification requests
+ * @param method - method handler
+ * @param[in,out] context - verification context of the 
+ * method's defining class
+ * @return error code 
+ */
+vf_Result 
+init_verification_context_for_method(method_handler method, verification_context context) {
+    vf_Context_6 context6( *((SharedClasswideData*)context) );
+    return context6.verify_method(method);
+}
+
+
+/**
+ * Recomputes the StackMapTable of a method using the verification 
+ * context created and initialized prior
+ * to method instrumentation
+ * @param[out] attrBytes - a pointer to a newly allocated StackMapTable
+ * attribute. Memory must be disposed by calling free_stackmaptable
+ * (see below).
+ * @param method - method handler
+ * @param context - class and method verification context
+ * @return error code
+ */
+vf_Result recompute_stackmaptable(uint8 **attrBytes, method_handler method, verification_context context) {
+    char *error_message;
+    return vf_recompute_stackmaptable(method, attrBytes, &error_message, ((SharedClasswideData*)context)->class_constraints);
+}
+
+
+/**
+ * Frees memory allocated for a StackMapTable attribute
+ */
+void free_stackmaptable(uint8 *attrBytes) {
+    tc_free(attrBytes);
+}
+
+/**
+ * Frees memory allocated for a verification context
+ */
+void free_verification_context (verification_context context) {
+    delete ((SharedClasswideData*)context);
+}
+

Propchange: harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/x_verifier/x_verifier.cpp
------------------------------------------------------------------------------
    svn:eol-style = native

Added: harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/x_verifier/x_verifier.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/x_verifier/x_verifier.h?rev=619847&view=auto
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/x_verifier/x_verifier.h (added)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/x_verifier/x_verifier.h Fri Feb  8 03:53:11 2008
@@ -0,0 +1,79 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+/** 
+ * @author Mikhail Loenko
+ */  
+
+
+
+#ifndef __X_VERIFIER_H__
+#define __X_VERIFIER_H__
+
+#include "verifier.h"
+
+typedef struct Context_* verification_context;
+
+
+/**
+ * Allocates an empty verification context for a class, 
+ * to be passed back to the verifier upon verification requests.
+ * Memory must be disposed by calling free_verification_context 
+ * (see below).
+ * @param klass - class handler
+ * @return a verification context for the class
+ */
+verification_context allocate_verification_context(class_handler klass);
+
+/**
+ * Initializes the verification context with method's information. 
+ * This function must be called before instrumenting the method.
+ * The resulting context should be passed back to the verifier 
+ * upon verification requests
+ * @param method - method handler
+ * @param[in,out] context - verification context of the 
+ * method's defining class
+ * @return error code 
+ */
+vf_Result 
+init_verification_context_for_method(method_handler method, verification_context context);
+
+/**
+ * Recomputes the StackMapTable of a method using the verification 
+ * context created and initialized prior
+ * to method instrumentation
+ * @param[out] attrBytes - a pointer to a newly allocated StackMapTable
+ * attribute. Memory must be disposed by calling free_stackmaptable
+ * (see below).
+ * @param method - method handler
+ * @param context - class and method verification context
+ * @return error code
+ */
+vf_Result recompute_stackmaptable(uint8 **attrBytes, 
+  method_handler method, verification_context context);
+
+
+/**
+ * Frees memory allocated for a StackMapTable attribute
+ */
+void free_stackmaptable(uint8 *attrBytes);
+
+/**
+ * Frees memory allocated for a verification context
+ */
+void free_verification_context (verification_context context);
+
+#endif

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



Mime
View raw message