You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by ml...@apache.org on 2007/07/16 08:44:56 UTC

svn commit: r556523 [3/4] - in /harmony/enhanced/drlvm/trunk: build/make/components/vm/ vm/vmcore/src/verifier-3363/

Propchange: harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/Pass2.cpp
------------------------------------------------------------------------------
    svn:executable = *

Added: harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/Ver.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/Ver.cpp?view=auto&rev=556523
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/Ver.cpp (added)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/Ver.cpp Sun Jul 15 23:44:55 2007
@@ -0,0 +1,132 @@
+/*
+ *  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 "verifier.h"
+#include "context.h"
+#include "time.h"
+
+using namespace CPVerifier;
+char  err_message[5000];
+
+/**
+* Function provides initial verification of class.
+*
+* If when verifying the class a check of type "class A must be assignable to class B" needs to be done 
+* and either A or B is not loaded at the moment then a constraint 
+* "class A must be assignable to class B" is recorded into the classloader's data
+*/
+vf_Result
+vf_verify_class( class_handler klass, unsigned verifyAll, char **error )
+{
+    int index;
+    vf_Result result = VF_OK;
+
+    // Create context
+    vf_Context_t context(klass);
+
+    // Verify method
+    for( index = 0; index < class_get_method_number( klass ); index++ ) {
+        result = context.verify_method(class_get_method( klass, index ));
+
+        if (result != VF_OK) {
+            *error = &(err_message[0]);
+            method_handler method = class_get_method( klass, index );
+            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 );
+            break;
+        }
+    }
+
+    /**
+    * Set method constraints
+    */
+    context.set_class_constraints();
+
+    return result;
+} // vf_verify_class
+
+
+/**
+* Function verifies all the constraints "class A must be assignable to class B"
+* that are recorded into the classloader for the given class
+* If some class is not loaded yet -- load it now
+*/
+vf_Result
+vf_verify_class_constraints( class_handler klass, unsigned verifyAll, char **error )
+{
+
+    // get class loader of current class
+    classloader_handler class_loader = class_get_class_loader( klass );
+
+    // get class loader verify data
+    vf_ClassLoaderData_t *cl_data =
+        (vf_ClassLoaderData_t*)cl_get_verify_data_ptr( class_loader );
+
+    // check class loader data
+    if( cl_data == NULL ) {
+        // no constraint data
+        return VF_OK;
+    }
+
+    // get class hash and memory pool
+    vf_Hash_t *hash = cl_data->hash;
+
+    // get constraints for class
+    vf_HashEntry_t *hash_entry = hash->Lookup( class_get_name( klass ) );
+    if( !hash_entry || !hash_entry->data ) {
+        // no constraint data
+        return VF_OK;
+    }
+
+    // check method constraints
+    vf_TypeConstraint_t *constraint = (vf_TypeConstraint_t*)hash_entry->data;
+    for( ; constraint; constraint = constraint->next )
+    {
+        vf_Result result = vf_force_check_constraint( klass, constraint );
+        if( result != VF_OK ) {
+            *error = &(err_message[0]);
+            sprintf(*error, "constraint check failed, class: %s, source: %s, target: %s", class_get_name( klass ), constraint->source, constraint->target);
+            return result;
+        }
+    }
+
+    return VF_OK;
+} // vf_verify_method_constraints
+
+
+/**
+* Function releases verify data in class loader (used to store constraints)
+*/
+void
+vf_release_verify_data( void *data )
+{
+    vf_ClassLoaderData_t *cl_data = (vf_ClassLoaderData_t*)data;
+
+    delete cl_data->string;
+    delete cl_data->hash;
+    delete cl_data->pool;
+} // vf_release_verify_data
+

Propchange: harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/Ver.cpp
------------------------------------------------------------------------------
    svn:executable = *

Added: harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/context.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/context.h?view=auto&rev=556523
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/context.h (added)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/context.h Sun Jul 15 23:44:55 2007
@@ -0,0 +1,605 @@
+/*
+ *  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 __CONTEXT_H__
+#define __CONTEXT_H__
+
+#include <assert.h>
+#include <string.h>
+#include "verifier.h"
+#include "stackmap.h"
+#include "memory.h"
+#include "tpool.h"
+#include "instr_props.h"
+
+namespace CPVerifier {
+
+    //
+    // Context - main class of Type Checker
+    //
+
+    class vf_Context_t {
+    public:
+        vf_Context_t(class_handler _klass) :
+
+#pragma warning( push )
+#pragma warning( disable : 4355 )
+          k_class(_klass), tpool(this, 256),
+#pragma warning( pop )
+
+              constraintPool(), class_constraints(0)
+          {
+              k_major = class_get_version( _klass );
+          }
+
+          vf_Result verify_method(method_handler method);
+          void set_class_constraints();
+          Address processed_instruction;
+          int  pass;
+
+          const char *error_message;
+    protected:
+        friend class vf_TypePool;
+
+        //class handler for the current class
+		class_handler  k_class;
+
+        //major version of current class
+		unsigned short  k_major;
+
+        //method handler for the method being verified
+        method_handler m_method;
+
+        //method's bytecode
+        unsigned char  *m_bytecode;
+
+        //legth of the code in the method being verified
+        unsigned       m_code_length;
+
+        //max number of locals for the method being verified (as recorded in the classfile)
+        unsigned       m_max_locals;
+
+        //is the current method construcor (and current class in not a j.l.Object)?
+        bool           m_is_constructor;
+
+        //m_max_locals or m_max_locals+1 if it's a constructor
+        unsigned       m_stack_start;
+
+        //max stack size for the method being verified (as recorded in the classfile)
+        unsigned       m_max_stack;
+
+        //number of exception handlers for the being verified (as recorded in the classfile)
+        unsigned short m_handlecount;
+
+        //stores constraints in the classloader for reuse in vf_verify_class_constraints()
+        vf_TypeConstraint_s *class_constraints;
+
+        //storage for these constraints. class-wide
+        //TODO: makes sense to unite it with tpool containing other class-wide data?
+        Memory constraintPool;
+
+
+        /*****************/
+
+        // method's return type
+        SmConstant return_type;
+
+        // various flags for all the method's bytecode instructions
+        InstrProps props;
+
+        // table used to get various info (type, length, etc) about possible bytecode instructions
+        static ParseInfo parseTable[255];
+
+        // current set of derived types
+        WorkmapHead *workmap;
+
+        // stack to push instrauctions like branch targets, etc to go thru the method. the stack is method-wide.
+        MarkableStack stack;
+
+        FastStack dead_code_stack;
+        bool      dead_code_parsing;
+
+        static const short MARK_SUBROUTINE_DONE = -1;
+    public:
+        // basic storage for most of the method-wide data
+        Memory mem;
+    protected:
+
+        //basic storage for class-wide data, like mapping from Java classes to SmConstant types
+        vf_TypePool tpool;
+
+        /******* exception handling **********/
+
+        //flag array. if a local var i was changed by the previous instruction ==> changed_locals[i]=1, otherwise it's 0
+        byte *changed_locals;
+
+        //if there is at least one local changed
+        int locals_changed;
+
+        //if we don't know whether previous instruction changed locals (like if we are at the branch target)
+        int no_locals_info;
+
+        //number of the first handler valid for the given instruction
+        int loop_start;
+
+        //<number of the last handler valid for the given instruction> + 1
+        int loop_finish;
+
+        //start of the nearest next try block. 0 means "don't know"
+        Address next_start_pc;
+
+        /*****************/
+
+        //report verify error and store a message if any
+        vf_Result error(vf_Result result, const char* message) {
+            error_message = message ? message : "";
+            //assert(0);
+            return result;
+        }
+
+        //init method-wide data
+        void init(method_handler _m_method) {
+            //store method's parameters
+            //TODO: it might be mot slower not to store them
+            m_method = _m_method;
+            m_max_locals = method_get_max_local( m_method );
+            m_max_stack = method_get_max_stack( m_method );
+            m_code_length = method_get_code_length( m_method );
+            m_handlecount = method_get_exc_handler_number( m_method );
+            m_bytecode = method_get_bytecode( m_method );
+
+            m_is_constructor = !strcmp(method_get_name(m_method), "<init>") 
+                && class_get_super_class(k_class);
+
+            m_stack_start = m_max_locals + (m_is_constructor ? 1 : 0);
+
+            // initialize own parameters
+            mem.init();
+            props.init(mem, m_code_length);
+
+            stack.init();
+            dead_code_stack.init();
+
+            changed_locals = (byte*)mem.malloc((m_stack_start & ~3) + 4);
+
+            //to correct it later
+            return_type = SM_TOP;
+        }
+
+        // load derived types previously stored for the given instruction
+        void fill_workmap(Address instr) {
+            PropsHead *head = props.getInstrProps(instr);
+            if( head->is_workmap() ) {
+                tc_memcpy(workmap, head->getWorkmap(), sizeof(WorkmapHead) + sizeof(WorkmapElement) * (m_stack_start + head->workmap.depth));
+            } else {
+                StackmapHead *stackmap = head->getStackmap();
+
+                workmap->depth = stackmap->depth;
+
+                for( unsigned i = 0; i < m_stack_start + stackmap->depth; i++) {
+                    workmap->elements[i] = _WorkmapElement(&stackmap->elements[i]);
+                    assert( workmap->elements[i].getAnyPossibleValue() != SM_TOP );
+                }
+            }
+            no_locals_info = 1;
+        }
+
+        //store a copy of the current workmap for another instruction (such as a branch target)
+        void storeWorkmapCopy(Address target) {
+            int sz = m_stack_start + workmap->depth;
+            PropsHead* copy = newWorkmap(sz);
+            tc_memcpy(copy->getWorkmap(), workmap, sizeof(WorkmapHead) + sizeof(WorkmapElement) * sz);
+
+            props.setInstrProps(target, copy);
+        }
+
+        //create a stackmap vector of the given size sz (max_locals <= sz <= max_locals+max_stack)
+        PropsHead* newStackmap(int sz) {
+            return (PropsHead*)mem.calloc(sizeof(PropsHead) + sizeof(StackmapElement) * sz);
+        }
+
+        //create a workmap vector for the given size sz (max_locals <= sz <= max_locals+max_stack)
+        PropsHead *newWorkmap(int sz) {
+            PropsHead * ret = (PropsHead*)mem.malloc(sizeof(PropsHead) + sizeof(WorkmapElement) * sz);
+            ret->set_as_workmap();
+            return ret;
+        }
+
+        //create a vector that will be used for JSR procesing. 
+        //It contains ether stackmap or workmap vector, SubrouitineData, and flags vector indicating 
+        //changed locals
+        PropsHead *newRetData() {
+            assert( sizeof(StackmapElement) >= sizeof(WorkmapElement) );
+
+            int sz = sizeof(PropsHead) + sizeof(StackmapElement) * (m_max_stack + m_stack_start) + //stackmap
+                ((sizeof(SubroutineData)+ m_stack_start) & (~3)) + 4; // fixed data and changed locals vector
+
+            PropsHead * ret = (PropsHead *) mem.calloc(sz);
+            ret->set_as_workmap();
+            return ret;
+        }
+
+        //creates a temporary variable for converting 
+        StackmapElement *new_variable() {
+            return (StackmapElement *)mem.calloc(sizeof(StackmapElement));
+        }
+
+        /////////////////////////////////////////////////////////////////////////////////////////////////////
+
+        //First verification pass thru the method. checks that no jump outside the method or to the middle of instruction
+        //checks that opcodes are valid
+        vf_Result parse(Address instr);
+
+        //Second pass: dataflow of a piece of the method starting from the beginning or a branch target and finishing
+        //on return, athrow or hitting previously passed instruction. 
+        //This function initializes workmap and calls DataflowLoop
+        vf_Result StartLinearDataflow(Address start);
+
+        //Second pass: Finilize subroutie processing -- once we are here, then all the RETs from achievable for
+        //the given subroutine are passed, so we can resume passing for JSRs to the given address
+        //This function initializes workmap properly and calls DataflowLoop
+        vf_Result SubroutineDone(Address start);
+
+        //Second pass: dataflow of a piece of the method starting from the beginning or a branch target and finishing
+        //on return, athrow or hitting previously passed instruction
+        vf_Result DataflowLoop(Address start, int workmap_is_a_copy_of_stackmap);
+
+        //Second pass: check type-safety of a single instruction
+        vf_Result dataflow_instruction(Address instr);
+
+        //Second pass: check type-safety for exception handlers of a single instruction
+        vf_Result dataflow_handlers(Address instr);
+
+        //specail care for <init> calls is in try blocks
+        vf_Result propagate_bogus_to_handlers(Address instr, SmConstant uninit_value);
+
+        //create constraint vector in case of a branch 
+        //simple conatraints are created for pairs of both locals and stack (current must be assignable to target)
+        vf_Result new_generic_vector_constraint(Address target);
+
+        //create constraint vector for exception handler
+        //simple conatraints are created for pairs of local variable (current must be assignable to start of exception handler)
+        vf_Result new_handler_vector_constraint(Address handler);
+
+        //create simple single constraint: "'from' is assingable to 'to'"
+        vf_Result new_scalar_constraint(WorkmapElement *from, StackmapElement *to);
+
+        //create special type of conatraint: "'from' is an array and it's element is assignable to 'to'"
+        vf_Result new_scalar_array2ref_constraint(WorkmapElement *from, WorkmapElement *to);
+
+        //constraint propagation
+        vf_Result propagate(StackmapElement *changed, SmConstant new_value);
+
+        //update current derived types according to what was changed in subroutine
+        void restore_workmap_after_jsr(Address jsr_target);
+
+        //when we hit RET instruction we update the data for the given subroutine with current derived types
+        vf_Result vf_Context_t::new_ret_vector_constraint(Address target_instr);
+
+        /////////////////////////////////////////////////////////////////////////////////////////////////////
+
+        //add one more possible value (type) that can come to the given point (local or stack)
+        vf_Result add_incoming_value(SmConstant new_value, StackmapElement *destination);
+
+        //returns stackmap for the 'instr' instruction
+        //if it does not exists yet -- create it. When created use 'depth' as stack depth
+        StackmapHead *getStackmap(Address instr, int depth) {
+            PropsHead *pro = props.getInstrProps(instr);
+            if( !pro ) {
+                pro = newStackmap(m_stack_start + depth);
+                props.setInstrProps(instr, pro);
+                pro->getStackmap()->depth = depth;
+            }
+            return pro->getStackmap();
+        }
+
+        //create stackmap for exception handler start
+        void createHandlerStackmap(Address handler_pc, SmConstant type) {
+            StackmapHead *map = getStackmap(handler_pc, 1);
+            //handler stackmaps are created before any dataflow analysis is done
+            assert(map->depth == 0 || map->depth == 1);
+            map->depth = 1;
+
+            vf_Result tcr = add_incoming_value(type, &map->elements[m_stack_start]);
+
+            // it is initialization stage
+            assert(tcr == VF_OK);
+        }
+
+
+        /////////////// set, get locals; push, pop stack; check... //////////////
+
+        //when exercizing instructions: POP operand from the stack
+        WorkmapElement workmap_pop() {
+            assert( workmap_can_pop(1) );
+            return workmap->elements[ (--workmap->depth) + m_stack_start ];
+        }
+
+        //looking the operand stack
+        WorkmapElement workmap_stackview(int depth) {
+            assert( depth >= 0 && workmap_can_pop(depth+1) );
+            return workmap->elements[ workmap->depth + m_stack_start - depth - 1];
+        }
+
+        //when exercizing instructions: PUSH operand to the stack
+        void workmap_push(WorkmapElement el) {
+            assert( workmap_can_push(1) );
+            workmap->elements[ (workmap->depth++) + m_stack_start ] = el;
+        }
+
+        //when exercizing instructions: PUSH a const (known) type to the stack (except long and double)
+        void workmap_push_const(SmConstant value) {
+            assert( workmap_can_push(1) );
+            workmap->elements[ workmap->depth + m_stack_start ] = _WorkmapElement(value);
+            workmap->depth++;
+        }
+
+        //when exercizing instructions: PUSH a const (known) long or double type to the stack
+        void workmap_2w_push_const(SmConstant value) {
+            workmap_push_const(SM_HIGH_WORD);
+            workmap_push_const(value);
+        }
+
+        //when exercizing instructions: check if the local idx is valid for long and double
+        bool workmap_valid_2w_local(unsigned idx) {
+            return workmap_valid_local(idx + 1);
+        }
+
+        //when exercizing instructions: check if the local idx is valid (except long and double)
+        bool workmap_valid_local(unsigned idx) {
+            return idx < m_max_locals;
+        }
+
+        //get local type by idx
+        WorkmapElement workmap_get_local(unsigned idx) {
+            assert( workmap_valid_local(idx) );
+            return workmap->elements[ idx ];
+        }
+
+        //set local type
+        void workmap_set_local(unsigned idx, WorkmapElement &el) {
+            assert( workmap_valid_local(idx) );
+
+            changed_locals[ idx ] = 1;
+            locals_changed = true;
+
+            el.setJsrModified();
+            workmap->elements[ idx ] = el;		
+        }
+
+        //set local to a const (known) type except long and double
+        void workmap_set_local_const(unsigned idx, SmConstant value) {
+            assert( workmap_valid_local(idx) );
+
+            changed_locals[ idx ] = 1;
+            locals_changed = true;
+
+            workmap->elements[idx] = _WorkmapElement(value);
+
+            //don't need to set "jsr modified" flag for constants
+            //because they are already odd
+            assert(workmap->elements[idx].isJsrModified());
+        }                                                              
+
+        //set local to a const (known) long or double type
+        void workmap_set_2w_local_const(unsigned idx, SmConstant value) {
+            assert( workmap_valid_2w_local(idx) );
+            workmap_set_local_const(idx + 1, value);
+            workmap_set_local_const(idx, SM_HIGH_WORD);
+        }
+
+        //check whether we can pop 'number' elements from the operand stack
+        int workmap_can_pop(unsigned number) {
+            return workmap->depth >= number;
+        }
+
+        //check whether we can push 'number' elements to the operand stack
+        int workmap_can_push(unsigned number) {
+            return workmap->depth + number <= m_max_stack;
+        }
+
+        /////////////// expect some type //////////////
+
+        //expect exactly this type (or SM_TOP)
+        int workmap_expect_strict( WorkmapElement &el, SmConstant type ) {
+            assert(type != SM_BOGUS);
+
+            if( !el.isVariable() ) {
+                return type == el.getConst();
+            }
+
+            IncomingType *in = el.getVariable()->firstIncoming();
+            while( in ) {
+                if( type != in->value ) {
+                    return false;
+                }
+                in = in->next();
+            }
+
+            ExpectedType *exp = el.getVariable()->firstExpected();
+            while( exp ) {
+                if( type == exp->value ) {
+                    return true;
+                }
+                exp = exp->next();
+            }
+
+            el.getVariable()->newExpectedType(&mem, type);
+
+            return true;
+        }
+
+        int workmap_expect( WorkmapElement &el, SmConstant type ) {
+            if( !el.isVariable() ) {
+                return tpool.mustbe_assignable(el.getConst(), type);
+            } else {
+                ExpectedType* exp = el.getVariable()->firstExpected();
+                while( exp ) {
+                    if( type == exp->value ) {
+                        return true;
+                    }
+                    exp = exp->next();
+                }
+
+                IncomingType *in = el.getVariable()->firstIncoming();
+                //check that all existing incoming type are assignable to the new expected type
+                while( in ) {
+                    if( !tpool.mustbe_assignable(in->value, type) ) {
+                        return false;
+                    }
+                    in = in->next();
+                }
+                //add the new expected type
+                el.getVariable()->newExpectedType(&mem, type);
+            }
+            return true;
+        }
+
+        vf_Result create_method_initial_workmap();
+
+
+        //////////////// get constant SM_ELEMENTs ///////////////////////
+
+        //for given uninit_value create SmConstant for initialized value
+        //this function is used when <init>s and invoked
+        SmConstant sm_convert_to_initialized(SmConstant uninit_value) {
+            if( uninit_value == SM_THISUNINIT ) {
+                return tpool.sm_get_const_this();
+            }
+
+            if( uninit_value.isNewObject() ) {
+                Address addr = uninit_value.getNewInstr();
+
+                unsigned cp_idx = read_int16(m_bytecode + addr + 1);
+                SmConstant new_type;
+                if( !tpool.cpool_get_class(cp_idx, &new_type) ) {
+                    assert(0);
+                    return SM_BOGUS;
+                }
+                return new_type;
+            }
+
+            assert(0);
+            return SM_BOGUS;
+        }
+
+        //create vector constraints for each target of a switch
+        vf_Result processSwitchTarget(Address target) {
+            vf_Result tcr;
+            if( props.isMultiway(target) ) {
+                if( (tcr=new_generic_vector_constraint(target)) != VF_OK ) {
+                    return tcr;
+                }
+
+                if( !props.isDataflowPassed(target) ) {
+                    stack.xPush(target);
+                }
+            } else {
+                assert( !props.isDataflowPassed(target) );
+                storeWorkmapCopy(target);
+
+                stack.xPush(target);
+            }
+            return VF_OK;
+        }
+
+        /////////////////////// convinient methods //////////////////////////////////////////
+
+        //get length of variable size instruction (WIDE, *SWITCH)
+        int instr_get_len_compound(Address instr, OpCode opcode);
+
+        //read two-byte value
+        static int16 read_int16(byte* ptr) {
+            return (ptr[0] << 8) | ptr[1];
+        }
+
+        //read four-byte value
+        static int32 read_int32(byte* ptr) {
+            return (ptr[0] << 24) | (ptr[1] << 16) | (ptr[2] << 8) | ptr[3];
+        }
+
+        //get properties specific for the given opcode
+        static ParseInfo &instr_get_parse_info(OpCode opcode) {
+            return parseTable[opcode];
+        }
+
+        //get the length of the given instruction or minimal length if unknown
+        static byte instr_get_minlen(ParseInfo &pi) {
+            return pi.instr_min_len;
+        }
+
+        //whether this instruction GOTO, IF*, or JSR
+        static int instr_is_jump(ParseInfo &pi) {
+            return pi.flags & PI_JUMP;
+        }
+
+        //whether this instruction GOTO, RETURN, ATHROW, or RET
+        static int instr_direct(ParseInfo &pi) {
+            return pi.flags & PI_DIRECT;
+        }
+
+        //whether this instruction a *SWITCH
+        static int instr_is_switch(ParseInfo &pi) {
+            return pi.flags & PI_SWITCH;
+        }
+
+        //other types of instructions
+        static int instr_is_regular(ParseInfo &pi) {
+            return !(pi.flags & (PI_SWITCH|PI_JUMP|PI_DIRECT));
+        }
+
+        //whether instruction length is unknown
+        static int instr_is_compound(OpCode opcode, ParseInfo &pi) {
+            return (pi.flags & PI_SWITCH) || opcode == OP_WIDE;
+        }
+
+        //JSR ?
+        static int instr_is_jsr(OpCode opcode) {
+            return opcode == OP_JSR || opcode == OP_JSR_W;
+        }
+
+        //RET ?
+        static int instr_is_ret(OpCode opcode, byte* code, Address instr) {
+            return opcode == OP_RET || opcode == OP_WIDE && code[instr + 1] == OP_RET;
+        }
+
+        //return the jump target for the given instruction
+        static Address instr_get_jump_target(ParseInfo &pi, byte* code, Address instr) {
+            if( pi.flags & PI_WIDEJUMP ) {
+                return instr + read_int32(code + instr + 1);
+            } else {
+                return instr + read_int16(code + instr + 1);
+            }        
+        }
+
+        //is this opcode valid?
+        static int instr_is_valid_bytecode(OpCode opcode) {
+            return opcode <= OP_MAXCODE && opcode != OP_XXX_UNUSED_XXX;
+        }
+    };
+
+    //check conatraints stored in the classloader data. force loading if necessary
+    vf_Result
+        vf_force_check_constraint(class_handler klass,
+        vf_TypeConstraint_t *constraint);
+
+} // namespace CPVerifier
+
+#endif

Propchange: harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/context.h
------------------------------------------------------------------------------
    svn:executable = *

Added: harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/instr_props.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/instr_props.h?view=auto&rev=556523
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/instr_props.h (added)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/instr_props.h Sun Jul 15 23:44:55 2007
@@ -0,0 +1,395 @@
+/*
+ *  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 __INSTR_PROPS_H_
+#define __INSTR_PROPS_H_
+
+#include <assert.h>
+#include "stackmap.h"
+
+namespace CPVerifier {
+
+    //store flags and properties (stackmaps, workmaps, etc) for each instruction
+    class InstrProps {
+    private:
+        //array of bit flags
+        byte* packed_flags;
+
+        //hash table to store data for instructions
+        PropsHead **propHashTable;
+
+        //storage for all the data
+        Memory *memory;
+
+        //to avoid divisions we do bit AND with hash_mask when looking a starting index in hash table list
+        int hash_mask;
+
+        //returns flags for the instruction 'instr'. other bits are not necessary 0s
+        int get_dirty_mask(Address instr) {
+            int b = packed_flags[instr/4];
+            b = b >> ((instr % 4) * 2);
+            return b;
+        }
+
+        //bit OR flags for the instruction 'instr' with 'mask'
+        void fill_mask(Address instr, int mask) {
+            assert((mask & ~3) == 0);
+            mask = mask << ((instr % 4) * 2);
+
+            packed_flags[instr/4] |= mask;
+        }
+
+        //clears bits the are set in the 'mask' (& ~mask) for the instruction 'instr'
+        void clear_mask(Address instr, int mask) {
+            assert((mask & ~3) == 0);
+            mask = mask << (instr % 4) * 2;
+
+            packed_flags[instr/4] &= ~mask;
+        }
+
+    public:
+        //initializes the class. this function is invoked once per method - removes old data in initializes storages.
+        void init(Memory &mem, int code_len) {
+            memory = &mem;
+            packed_flags = (byte*)mem.calloc( ((code_len/4) & ~3) + 4);
+
+            //calcluate hash_size
+            int hash_size = 16;
+            int clen = code_len >> 8;
+            while( clen ) {
+                hash_size = hash_size << 1;
+                clen = clen >> 1;
+            }
+
+            hash_mask = hash_size - 1;
+            propHashTable = (PropsHead**)mem.calloc(hash_size * sizeof(PropsHead*));
+        }
+
+        //pass1: 00 - new (or dead code), 01 - parsed, 10 - middle of instruction, 11 - 'special' parsed (special == has stackmap)
+        //returns 1 if mask is 01 (parsed) or 11 ('special' parsed  special == has stackmap)
+        int isParsePassed(Address instr) {
+            return get_dirty_mask(instr) & 1;
+        }
+
+        //pass1: 00 - new (or dead code), 01 - parsed, 10 - middle of instruction, 11 - 'special' parsed (special == has stackmap)
+        //returns 1 if mask is 10 (middle of instruction)
+        int isOperand(Address instr) {
+            return (get_dirty_mask(instr) & 3) == 2;
+        }
+
+        //pass1: 00 - new (or dead code), 01 - parsed, 10 - middle of instruction, 11 - 'special' parsed (special == has stackmap)
+        //setls low mask bit to 1
+        void setParsePassed(Address instr) {
+            fill_mask(instr, 1);
+        }
+
+        //pass1: 00 - new (or dead code), 01 - parsed, 10 - middle of instruction, 11 - 'special' parsed (special == has stackmap)
+        //sets mask to 10
+        int setOperand(Address instr) {
+            int idx = instr/4;
+            int shift = ((instr % 4) * 2);
+
+            int mask01 = 1 << shift;
+            int mask10 = 2 << shift;
+
+            //is an instruction
+            if( packed_flags[idx] & mask01 ) return 0;
+
+            //mark as a middle
+            packed_flags[idx] |= mask10;
+            return 1;
+        }
+
+        //pass1: 00 - new (or dead code), 01 - parsed, 10 - middle of instruction, 11 - 'special' parsed (special == has stackmap)
+        //set mask to 11
+        void setMultiway(Address instr) {
+            fill_mask(instr, 3);
+        }
+
+        //pass2: 01 - new, 11 - special, 00 - passed (or unused), 10 - special passed (or unused)
+        //for all instructions (except unuzed) returns 1 if it's 'passed' or 'special passed'
+        //return 0 otherwise
+        int isDataflowPassed(Address instr) {
+            return !(get_dirty_mask(instr) & 1);
+        }
+
+        //return 1 for special and special passed instructions (instructions that are achievable by multiple passes)
+        int isMultiway(Address instr) { //II_MULTIWAY
+            return get_dirty_mask(instr) & 2;
+        }
+
+        //mark instruction as passed
+        void setDataflowPassed(Address instr) {
+            clear_mask(instr, 1);
+        }
+
+        ////////////////////////////////////////////////////////setting getting properties
+
+        //return properties for the given instruction
+        PropsHead* getInstrProps(Address instr) {
+            PropsHead *pro = propHashTable[instr & hash_mask];
+            while( pro && pro->instr != instr ) {
+                pro = pro->next;
+            }
+            return pro;
+        }
+
+        //sets properties for the given instruction
+        void setInstrProps(Address instr, PropsHead *map) {
+            //properties for the instruction don't exit yet
+            assert(!getInstrProps(instr));
+
+            int hash = instr & hash_mask;
+            map->next = propHashTable[hash];
+            map->instr = instr;
+            propHashTable[hash] = map;
+
+        }
+    };
+
+    //
+    // instruction's possible characteristics (flags)
+    //
+    const byte PI_JUMP = 1;
+    const byte PI_WIDEJUMP = 2;
+    const byte PI_DIRECT = 4;
+    const byte PI_SWITCH = 8;
+    const byte PI_CANWIDE = 16;
+
+    struct ParseInfo {
+        byte instr_min_len;   // length of the instruction with operands
+        byte flags;           // union of appropriate masks, see above 
+    };
+
+
+    //
+    // instruction's opcodes
+    //
+    enum OpCode {
+        OP_AALOAD            = 0x32,
+        OP_AASTORE           = 0x53,
+        OP_ACONST_NULL       = 0x01,
+        OP_ALOAD             = 0x19,
+        OP_ALOAD_0           = 0x2a,
+        OP_ALOAD_1           = 0x2b,
+        OP_ALOAD_2           = 0x2c,
+        OP_ALOAD_3           = 0x2d,
+        OP_ANEWARRAY         = 0xbd,
+        OP_ARETURN           = 0xb0,
+        OP_ARRAYLENGTH       = 0xbe,
+        OP_ASTORE            = 0x3a,
+        OP_ASTORE_0          = 0x4b,
+        OP_ASTORE_1          = 0x4c,
+        OP_ASTORE_2          = 0x4d,
+        OP_ASTORE_3          = 0x4e,
+        OP_ATHROW            = 0xbf,
+        OP_BALOAD            = 0x33,
+        OP_BASTORE           = 0x54,
+        OP_BIPUSH            = 0x10,
+        OP_CALOAD            = 0x34,
+        OP_CASTORE           = 0x55,
+        OP_CHECKCAST         = 0xc0,
+        OP_D2F               = 0x90,
+        OP_D2I               = 0x8e,
+        OP_D2L               = 0x8f,
+        OP_DADD              = 0x63,
+        OP_DALOAD            = 0x31,
+        OP_DASTORE           = 0x52,
+        OP_DCMPG             = 0x98,
+        OP_DCMPL             = 0x97,
+        OP_DCONST_0          = 0x0e,
+        OP_DCONST_1          = 0x0f,
+        OP_DDIV              = 0x6f,
+        OP_DLOAD             = 0x18,
+        OP_DLOAD_0           = 0x26,
+        OP_DLOAD_1           = 0x27,
+        OP_DLOAD_2           = 0x28,
+        OP_DLOAD_3           = 0x29,
+        OP_DMUL              = 0x6b,
+        OP_DNEG              = 0x77,
+        OP_DREM              = 0x73,
+        OP_DRETURN           = 0xaf,
+        OP_DSTORE            = 0x39,
+        OP_DSTORE_0          = 0x47,
+        OP_DSTORE_1          = 0x48,
+        OP_DSTORE_2          = 0x49,
+        OP_DSTORE_3          = 0x4a,
+        OP_DSUB              = 0x67,
+        OP_DUP               = 0x59,
+        OP_DUP_X1            = 0x5a,
+        OP_DUP_X2            = 0x5b,
+        OP_DUP2              = 0x5c,
+        OP_DUP2_X1           = 0x5d,
+        OP_DUP2_X2           = 0x5e,
+        OP_F2D               = 0x8d,
+        OP_F2I               = 0x8b,
+        OP_F2L               = 0x8c,
+        OP_FADD              = 0x62,
+        OP_FALOAD            = 0x30,
+        OP_FASTORE           = 0x51,
+        OP_FCMPG             = 0x96,
+        OP_FCMPL             = 0x95,
+        OP_FCONST_0          = 0x0b,
+        OP_FCONST_1          = 0x0c,
+        OP_FCONST_2          = 0x0d,
+        OP_FDIV              = 0x6e,
+        OP_FLOAD             = 0x17,
+        OP_FLOAD_0           = 0x22,
+        OP_FLOAD_1           = 0x23,
+        OP_FLOAD_2           = 0x24,
+        OP_FLOAD_3           = 0x25,
+        OP_FMUL              = 0x6a,
+        OP_FNEG              = 0x76,
+        OP_FREM              = 0x72,
+        OP_FRETURN           = 0xae,
+        OP_FSTORE            = 0x38,
+        OP_FSTORE_0          = 0x43,
+        OP_FSTORE_1          = 0x44,
+        OP_FSTORE_2          = 0x45,
+        OP_FSTORE_3          = 0x46,
+        OP_FSUB              = 0x66,
+        OP_GETFIELD          = 0xb4,
+        OP_GETSTATIC         = 0xb2,
+        OP_GOTO              = 0xa7,
+        OP_GOTO_W            = 0xc8,
+        OP_I2B               = 0x91,
+        OP_I2C               = 0x92,
+        OP_I2D               = 0x87,
+        OP_I2F               = 0x86,
+        OP_I2L               = 0x85,
+        OP_I2S               = 0x93,
+        OP_IADD              = 0x60,
+        OP_IALOAD            = 0x2e,
+        OP_IAND              = 0x7e,
+        OP_IASTORE           = 0x4f,
+        OP_ICONST_0          = 0x03,
+        OP_ICONST_1          = 0x04,
+        OP_ICONST_2          = 0x05,
+        OP_ICONST_3          = 0x06,
+        OP_ICONST_4          = 0x07,
+        OP_ICONST_5          = 0x08,
+        OP_ICONST_M1         = 0x02,
+        OP_IDIV              = 0x6c,
+        OP_IF_ACMPEQ         = 0xa5,
+        OP_IF_ACMPNE         = 0xa6,
+        OP_IF_ICMPEQ         = 0x9f,
+        OP_IF_ICMPGE         = 0xa2,
+        OP_IF_ICMPGT         = 0xa3,
+        OP_IF_ICMPLE         = 0xa4,
+        OP_IF_ICMPLT         = 0xa1,
+        OP_IF_ICMPNE         = 0xa0,
+        OP_IFEQ              = 0x99,
+        OP_IFGE              = 0x9c,
+        OP_IFGT              = 0x9d,
+        OP_IFLE              = 0x9e,
+        OP_IFLT              = 0x9b,
+        OP_IFNE              = 0x9a,
+        OP_IFNONNULL         = 0xc7,
+        OP_IFNULL            = 0xc6,
+        OP_IINC              = 0x84,
+        OP_ILOAD             = 0x15,
+        OP_ILOAD_0           = 0x1a,
+        OP_ILOAD_1           = 0x1b,
+        OP_ILOAD_2           = 0x1c,
+        OP_ILOAD_3           = 0x1d,
+        OP_IMUL              = 0x68,
+        OP_INEG              = 0x74,
+        OP_INSTANCEOF        = 0xc1,
+        OP_INVOKEINTERFACE   = 0xb9,
+        OP_INVOKESPECIAL     = 0xb7,
+        OP_INVOKESTATIC      = 0xb8,
+        OP_INVOKEVIRTUAL     = 0xb6,
+        OP_IOR               = 0x80,
+        OP_IREM              = 0x70,
+        OP_IRETURN           = 0xac,
+        OP_ISHL              = 0x78,
+        OP_ISHR              = 0x7a,
+        OP_ISTORE            = 0x36,
+        OP_ISTORE_0          = 0x3b,
+        OP_ISTORE_1          = 0x3c,
+        OP_ISTORE_2          = 0x3d,
+        OP_ISTORE_3          = 0x3e,
+        OP_ISUB              = 0x64,
+        OP_IUSHR             = 0x7c,
+        OP_IXOR              = 0x82,
+        OP_JSR               = 0xa8,
+        OP_JSR_W             = 0xc9,
+        OP_L2D               = 0x8a,
+        OP_L2F               = 0x89,
+        OP_L2I               = 0x88,
+        OP_LADD              = 0x61,
+        OP_LALOAD            = 0x2f,
+        OP_LAND              = 0x7f,
+        OP_LASTORE           = 0x50,
+        OP_LCMP              = 0x94,
+        OP_LCONST_0          = 0x09,
+        OP_LCONST_1          = 0x0a,
+        OP_LDC               = 0x12,
+        OP_LDC_W             = 0x13,
+        OP_LDC2_W            = 0x14,
+        OP_LDIV              = 0x6d,
+        OP_LLOAD             = 0x16,
+        OP_LLOAD_0           = 0x1e,
+        OP_LLOAD_1           = 0x1f,
+        OP_LLOAD_2           = 0x20,
+        OP_LLOAD_3           = 0x21,
+        OP_LMUL              = 0x69,
+        OP_LNEG              = 0x75,
+        OP_LOOKUPSWITCH      = 0xab,
+        OP_LOR               = 0x81,
+        OP_LREM              = 0x71,
+        OP_LRETURN           = 0xad,
+        OP_LSHL              = 0x79,
+        OP_LSHR              = 0x7b,
+        OP_LSTORE            = 0x37,
+        OP_LSTORE_0          = 0x3f,
+        OP_LSTORE_1          = 0x40,
+        OP_LSTORE_2          = 0x41,
+        OP_LSTORE_3          = 0x42,
+        OP_LSUB              = 0x65,
+        OP_LUSHR             = 0x7d,
+        OP_LXOR              = 0x83,
+        OP_MONITORENTER      = 0xc2,
+        OP_MONITOREXIT       = 0xc3,
+        OP_MULTIANEWARRAY    = 0xc5,
+        OP_NEW               = 0xbb,
+        OP_NEWARRAY          = 0xbc,
+        OP_NOP               = 0x00,
+        OP_POP               = 0x57,
+        OP_POP2              = 0x58,
+        OP_PUTFIELD          = 0xb5,
+        OP_PUTSTATIC         = 0xb3,
+        OP_RET               = 0xa9,
+        OP_RETURN            = 0xb1,
+        OP_SALOAD            = 0x35,
+        OP_SASTORE           = 0x56,
+        OP_SIPUSH            = 0x11,
+        OP_SWAP              = 0x5f,
+        OP_TABLESWITCH       = 0xaa,
+        OP_WIDE              = 0xc4,
+
+        OP_XXX_UNUSED_XXX    = 0xba,
+        OP_MAXCODE           = 0xc9,
+    };
+
+} // namespace CPVerifier
+
+
+#endif

Propchange: harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/instr_props.h
------------------------------------------------------------------------------
    svn:executable = *

Added: harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/stackmap.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/stackmap.h?view=auto&rev=556523
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/stackmap.h (added)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/stackmap.h Sun Jul 15 23:44:55 2007
@@ -0,0 +1,536 @@
+/*
+ *  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 __STACKMAP_H__
+#define __STACKMAP_H__
+
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include "ver_utils.h"
+
+#ifdef WIN32
+#define intptr int64
+#else
+#define intptr long
+#endif
+
+namespace CPVerifier {
+
+    //predefined verification types
+    enum SmConstPredefined {
+        SM_TOP                          = 0,
+        SM_ONEWORDED                    = 1,
+        SM_REF_OR_UNINIT_OR_RETADR      = 3,
+        SM_REF_OR_UNINIT                = 5,
+        SM_THISUNINIT                   = 7,
+        SM_ANYARRAY                     = 9,
+        SM_NULL                         = 11,
+        SM_HIGH_WORD                    = 13,
+        SM_INTEGER                      = 15,
+        SM_FLOAT                        = 17,
+        SM_BOGUS                        = 19,
+        SM_LONG                         = 21,
+        SM_DOUBLE                       = 23,
+    };
+
+    //verification types with comparision operators
+    struct _SmConstant {
+        unsigned c;
+
+        int operator ==(_SmConstant other) {
+            return c == other.c;
+        }
+
+        int operator ==(unsigned other) {
+            return c == other;
+        }
+
+        int operator !=(_SmConstant other) {
+            return c != other.c;
+        }
+
+        int operator !=(unsigned other) {
+            return c != other;
+        }
+
+
+    };
+
+    //verification types with convinient functions
+    struct SmConstant : _SmConstant {
+        //all constants except SM_TOP must be odd
+
+        //default constructor
+        SmConstant() {}
+
+        //creating from unsigned
+        SmConstant(unsigned int other) {
+            c = other;
+        }
+
+        //copy constructor
+        SmConstant(const _SmConstant other) {
+            c = other.c;
+        }
+
+        ///////////////////////////////////////
+
+        //is it a RETADDR verification type? (that's pushed by JSR instructions)
+        int isRetAddr() {
+            return c & TYPE_RETADDR;
+        }
+
+        //is it a reference? (like Object)
+        int isReference() {
+            return c & TYPE_REFERENCE;
+        }
+
+        //is it a new object? (e.g. just created by 'new' instruction)
+        int isNewObject() {
+            return c & TYPE_NEWOBJECT;
+        }
+
+        //is it a primitive verification type? (e.g. int, long)
+        int isPrimitive() {
+            return !(c & (TYPE_NEWOBJECT | TYPE_REFERENCE | TYPE_RETADDR));
+        }
+
+        //is it a two-word type?
+        int isLongOrDouble() {
+            return c == SM_LONG || c == SM_DOUBLE;
+        }
+
+        //does merge with any other type results in SM_BOGUS?
+        int isNonMergeable() {
+            return (c & (TYPE_NEWOBJECT|TYPE_RETADDR)) || c == SM_THISUNINIT;
+        }
+
+        ///////////////////////////////////////
+
+        //for a reference: return class id in the table (see tpool)
+        int getReferenceIdx() {
+            assert(isReference());
+            return (c & ~TYPE_REFERENCE) >> 1;
+        }
+
+        //for 'new' type: return address of the 'new' instruction created this SmConstant
+        Address getNewInstr() {
+            assert(isNewObject());
+            return (c & ~TYPE_NEWOBJECT) >> 1;
+        }
+
+        //for RetAddress: return address of the subroutine start (i.e. target of JSR instruction)
+        //Note: this is different from what is recorded in RetAddress type when actual execution happens
+        Address getRetInstr() {
+            assert(isRetAddr());
+            return (c & ~TYPE_RETADDR) >> 1;
+        }
+
+        ///////////////////////////////////////
+
+        //create "new object" verification type corresponding to 'instr'
+        static SmConstant getNewObject(Address instr) {
+            return ((instr<<1) | (TYPE_NEWOBJECT | 1));
+        }
+
+        //create "ret address" verification type corresponding to subroutine startig at 'instr'
+        //Note: this is different from what is recorded in RetAddress type when actual execution happens
+        static SmConstant getRetAddr(Address instr) {
+            return ((instr<<1) | (TYPE_RETADDR | 1));
+        }
+
+        //create "object" verification type
+        static SmConstant getReference(unsigned idx) {
+            return ((idx<<1) | (TYPE_REFERENCE | 1));
+        }
+
+        ////////////////////////////////////////
+
+        static const unsigned TYPE_RETADDR   = 0x2000000;
+        static const unsigned TYPE_REFERENCE = 0x4000000;
+        static const unsigned TYPE_NEWOBJECT = 0x8000000;
+
+    };
+
+    //possible relations between verificaton types
+    enum ConstraintType {
+        CT_GENERIC,         // sub-defined type A is assignable to sub-defined type B
+        CT_ARRAY2REF,       // A is a known-type array. element of A is assignable to sub-defined type B
+        CT_EXPECTED_TYPE,   // sub-defined type A is assignable to known-type B
+        CT_INCOMING_VALUE   // known-type A is assignable to sub-defined type B
+    };
+
+    struct StackmapHead;
+    struct WorkmapHead;
+    struct StackmapElement;
+
+    //structure for maintaining subroutine-specific data
+    //until subroutine is passed with the second (dataflow) pass we record to the wait list all JSR instructions
+    //calling this subroutine. Once the subroutine is over we continue 2nd pass for each wait-listed instruction
+    //see vf_Context_t::SubroutineDone
+    struct SubroutineData {
+        Address caller;         //first JSR instruction that called this subroutine
+        short retCount;         //number of ret instructions for this subroutine
+        byte  subrDataflowed;   // =1 if dataflow pass for the subroutine is over
+    };
+
+    //list constant verification type (i.e. known-type) that are assignable to some sub-definite type (i.e. StackMapElement)
+    //see StackmapElement
+    struct IncomingType {
+        //next in the list
+        IncomingType *nxt;
+
+        //value of the verification type recorded as int
+        //TODO: don't remember why it's 'int' rather than 'SmConstant'
+        int value;
+
+        //simple next in the list
+        IncomingType *next() {
+            return nxt;
+        }
+    };
+
+    //list of constraints for some sub-definite verification type (i.e. StackMapElement)
+    //see StackmapElement
+
+    struct Constraint {
+        //next in the list
+        Constraint *nxt;
+
+        //either
+        union {
+            StackmapElement *variable; // sub-definite verificarion type
+            int value;                 // or constant (known) verification type rcorded as int
+        };
+
+        //consatrint type
+        ConstraintType type;
+
+        //next constrait of type 't'
+        static Constraint *next(Constraint *cur, ConstraintType t) {
+            while( cur && cur->type != t ) {
+                cur = (Constraint*)cur->next();
+            }
+            return cur;
+        }
+
+        //simple next in the list
+        Constraint *next() {
+            return nxt;
+        }
+    };
+
+    //constraint of the CT_EXPECTED_TYPE type: sub-defined type A is assignable to known-type B
+    struct ExpectedType : Constraint {
+        ExpectedType *next() {
+            return (ExpectedType *) Constraint::next(Constraint::next(), CT_EXPECTED_TYPE);
+        }
+    };
+
+    //constraint of the CT_GENERIC type: sub-defined type A is assignable to sub-defined type B
+    struct GenericCnstr : Constraint {
+        GenericCnstr *next() {
+            return (GenericCnstr *) Constraint::next(Constraint::next(), CT_GENERIC);
+        }
+    };
+
+    //constraint of the CT_ARRAY2REF type: A is a known-type array. element of A is assignable to sub-defined type B
+    struct ArrayCnstr : Constraint {
+        //there can be only one CT_ARRAY2REF per StackMap Element
+        ArrayCnstr *next() {
+            assert(0);
+            return 0;
+        }
+    };
+
+
+    //StackMapElement structure represens sub-definite verification type: we don't know what type is it, but
+    //we know about instructions that expect ExpectedTypes here and we know that IncomingValues can be here
+    //we also know that this type must be assignable to other sub-defenite types as indicated by CT_GENERIC
+    //constrains and there can be special limitations represented by CT_ARRAY2REF constraints
+    struct StackmapElement { //TODO: should be rewritten to save footprint
+        //list of IncomingType constraint
+        IncomingType *incoming;
+
+        //list of all the conatraints of other types
+        Constraint *others;
+
+        //return value from any IncomingType constraint
+        //when we need to compae to some unmergable type we don;t need to interate thru the list
+        //also used to assert that an IncomingValue constraint exists
+        SmConstant getAnyIncomingValue() {
+            assert(firstIncoming());
+            return firstIncoming()->value;
+        }
+
+        //return first IncomingType constraint
+        IncomingType *firstIncoming() {
+            //TODO: I have to store somewhere the "modified" bit. Sorry.
+            return (IncomingType*)( (intptr)incoming & ~3 );
+        }
+
+        //return first conatrint of any type except IncomingType
+        Constraint *firstOthers() {
+            return others;
+        }
+
+        //return first CT_EXPECTED_TYPE constraint
+        ExpectedType *firstExpected() {
+            return (ExpectedType*)Constraint::next(others, CT_EXPECTED_TYPE);
+        }
+
+        //return first CT_GENERIC constraint
+        GenericCnstr *firstGenericCnstr() {
+            return (GenericCnstr*)Constraint::next(others, CT_GENERIC);
+        }
+
+        //return first (and the only) CT_ARRAY2REF constraint
+        ArrayCnstr *firstArrayCnstr() {
+            return (ArrayCnstr*)Constraint::next(others, CT_ARRAY2REF);
+        }
+
+        //clean-up
+        void init() {
+            incoming = 0;
+            others = 0;
+        }
+
+        //add incoming type with the 'value' value
+        void newIncomingType(Memory *mem, SmConstant value) {
+            IncomingType *in = (IncomingType *)mem->malloc(sizeof(IncomingType));
+
+            intptr mask = (intptr)incoming & 3;
+            incoming = (IncomingType *) ((intptr)incoming & ~3);
+
+            in->nxt = value == SM_BOGUS ? 0 : incoming;
+            //in->type = CT_INCOMING_VALUE;
+            in->value = value.c;
+
+            incoming = in;
+
+            incoming = (IncomingType *) ((intptr)incoming | mask);
+        }
+
+        //add expected type with the 'value' value
+        void newExpectedType(Memory *mem, SmConstant value) {
+            Constraint *o = (Constraint *)mem->malloc(sizeof(Constraint));
+
+            o->nxt = others;
+            o->type = CT_EXPECTED_TYPE;
+            o->value = value.c;
+
+            others = o;
+        }
+
+        //add generic constraint ('this' is assignable to 'to')
+        void newGenericConstraint(Memory *mem, StackmapElement *to) {
+            Constraint *o = (Constraint *)mem->malloc(sizeof(Constraint));
+
+            o->nxt = others;
+            o->type = CT_GENERIC;
+            o->variable = to;
+
+            others = o;
+        }
+
+        //add generic constraint ('this' is an array, which element is assignable to 'to')
+        void newArrayConversionConstraint(Memory *mem, StackmapElement *to) {
+            assert(!firstArrayCnstr());
+            Constraint *o = (Constraint *)mem->malloc(sizeof(Constraint));
+
+            //at most one array conversion constraint per variable is possible
+            o->nxt = others;
+            o->type = CT_ARRAY2REF;
+            o->variable = to;
+
+            others = o;
+        }
+
+        // return 'modified' flag for the stackmap. the flag is stored in the first bit of the 'incoming' pointer
+        // "modified" is about subroutines: you have to track which locals were changed
+        int isJsrModified() {
+            return (int)(intptr)incoming & 1;
+        }
+
+        //set 'modified' flag for the stackmap. the flag is stored in the first bit of the 'incoming' pointer
+        // "modified" is about subroutines: you have to track which locals were changed
+        void setJsrModified() {
+            incoming = (IncomingType *) ((intptr)incoming | 1);
+        }
+
+        //clear 'modified' flag for the stackmap. the flag is stored in the first bit of the 'incoming' pointer
+        // "modified" is about subroutines: you have to track which locals were changed
+        void clearJsrModified() {
+            incoming = (IncomingType *) ((intptr)incoming & ~1);
+        }
+    };
+
+    //WorkMapElement structure represent an element of the workmap vector -- vector of the derived types
+    //a type might be either constant (or known) (e.g. if some previous instruction has put something on stack or locals)
+    //or sub-definite (e.g. if we've recently passed a branch target and don't know which types were on stack or locals)
+    struct WorkmapElement {
+        //value. two low bits a used to store flags
+        union {
+            _SmConstant const_val;      //either a constant (known-type)
+            StackmapElement *var_ptr;   //or a variable (sub-definite type)
+        };
+
+        //is it a sub-definite (not constant) type?
+        int isVariable() {
+            assert(const_val != SM_TOP);
+            return !((intptr)var_ptr & 1);
+        }
+
+        //get value for the constant (known) verification type
+        SmConstant getConst() {
+            return const_val;
+        }
+
+        //get variable representing sub-definite verification type
+        StackmapElement *getVariable() {
+            return (StackmapElement *) ((intptr)var_ptr & ~3);
+        }
+
+        //when we need to compae to some unmergable type we don;t need to interate thru the list
+        //also used to assert that an IncomingValue constraint exists
+        SmConstant getAnyPossibleValue() {
+            SmConstant ret = isVariable() ? getVariable()->getAnyIncomingValue() : const_val;
+            assert(ret != SM_TOP);
+            return ret;
+        }
+
+        // return 'modified' flag for the workmap element. the flag is stored in the second bit of the union
+        //"modified" is about subroutines: you have to track which locals were changed
+        //it's easier to think of all the constants as "modified"
+        int isJsrModified() {
+            return (int)(intptr)var_ptr & 3;
+        }
+
+        // set 'modified' flag for the workmap element. the flag is stored in the second bit of the union
+        void setJsrModified() {
+            if( isVariable() ) {
+                var_ptr = (StackmapElement*)((intptr)var_ptr | 2);
+            }
+        }
+    };
+
+    //WorkmapElement type with some constructors
+    struct _WorkmapElement : WorkmapElement{
+        _WorkmapElement(WorkmapElement other) {
+            const_val = other.const_val;
+        }
+
+        _WorkmapElement(StackmapElement *s) {
+            var_ptr = s;
+            if( s->isJsrModified() ) {
+                setJsrModified();
+            }
+        }
+
+        _WorkmapElement(SmConstant c) {
+            const_val = c;
+        }
+    };
+
+#pragma warning( push )
+#pragma warning( disable : 4200 )
+
+    //vector of StackMap elements. the size is known at the moment of allocation
+    struct StackmapHead {
+        unsigned short depth;
+        StackmapElement elements[0];
+    };
+
+    //vector of WorkMap elements. the size is known at the moment of allocation
+    struct WorkmapHead {
+        unsigned short depth;
+        WorkmapElement elements[0];
+    };
+
+#pragma warning( pop )
+
+    //Store various data for the given instruction. Possible data are: StackMap vector, WorkMap vector,
+    //Subroutine-specific data
+    //for a single instruction it might be either
+    // 1) no data
+    // 2) workmap only
+    // 3) stackmap only
+    // 4) stackmap and subroutine data. in this case two PropsHead structures are created the first one for the StackMap,
+    //    it's 'next' points to the second PropsHead containing Subroutine info. In this case second PropsHead keeps 0xFFFF
+    //    instead of 'instr'
+    // the list is used to organize storing Props as a HashTable
+    struct PropsHead {
+        // Address of the instruction for which this properties are stored
+        // or 0xFFFF if this is a subroutine data for previous PropsHead
+        // TODO: if instr_flags are not optimized, introduce a 'subroutine data' flag and get rid of 0xFFFF instructions
+        Address instr;
+
+        //next property in the list
+        PropsHead* next;
+
+        // really one bit is used: FF_ISWORKMAP. TODO: merge with (Stack|Work)map->flags
+        unsigned short instr_flags; 
+
+        //possible flag value
+        static const short FF_ISWORKMAP = 1;
+
+        //actual properties
+        union {
+            WorkmapHead workmap;
+            StackmapHead stackmap;
+        };
+
+        //get workmap stored here
+        WorkmapHead *getWorkmap() {
+            assert(is_workmap());
+            return &workmap;
+        }
+
+        //get stackmap stored here
+        StackmapHead *getStackmap() {
+            assert(!is_workmap());
+            return &stackmap;
+        }
+
+        //get subroutine data stored here
+        SubroutineData *getSubrData(int el_cnt) {
+            assert(instr == 0xFFFF);
+            return (SubroutineData *) &stackmap.elements[el_cnt];
+        }
+
+        //is it a workmap?
+        int is_workmap() {
+            return instr_flags & FF_ISWORKMAP;
+        }
+
+        //set 'is workmap' flag
+        void set_as_workmap() {
+            instr_flags |= FF_ISWORKMAP;
+        }
+
+        //clear flag
+        void clearInstrFlag(short flag) {
+            instr_flags &= ~flag;
+        }
+    };
+} // namespace CPVerifier
+
+#endif

Propchange: harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/stackmap.h
------------------------------------------------------------------------------
    svn:executable = *

Added: harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/tpool.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/tpool.cpp?view=auto&rev=556523
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/tpool.cpp (added)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/tpool.cpp Sun Jul 15 23:44:55 2007
@@ -0,0 +1,511 @@
+/*
+ *  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 <assert.h>
+#include "tpool.h"
+#include "context.h"
+
+namespace CPVerifier {
+
+    vf_TypePool::vf_TypePool(vf_Context_t *_context, unsigned init_table_size)
+        : context(_context), k_class(_context->k_class), tableIncr(init_table_size),
+        tableSize(init_table_size), currentTypeId(0)
+    {
+        validTypes = (vf_ValidType *)tc_malloc(sizeof(vf_ValidType)*tableIncr);
+
+        const_object = const_class = const_string = const_throwable = const_arrayref_of_bb =
+            const_arrayref_of_char = const_arrayref_of_double = const_arrayref_of_float =
+            const_arrayref_of_integer = const_arrayref_of_long = const_arrayref_of_short = 
+            const_arrayref_of_object = const_this = SM_TOP;
+
+        k_cp_length = class_get_cp_size( k_class );
+    }
+
+    /*
+    * Returns name length if it is array of boolean or 0
+    */
+    inline int vf_TypePool::is_bool_array_conv_needed(const char *type_name, int length) {
+        return length > 1 && type_name[length - 1] == 'Z' && type_name[length - 2] == '[';
+    }
+
+    /*
+    * Get SmConstant by type name.
+    */
+    SmConstant vf_TypePool::get_ref_type(const char *type_name, int length) {
+        assert(type_name[0] != 'L');
+
+        int index = -1;
+        // find type in hash
+        vf_HashEntry_t *entry = hash.NewHashEntry( type_name, length );
+        if( entry->data ) {
+            index = (int)((vf_ValidType*)entry->data - validTypes);
+            assert(index >= 0 && (unsigned)index < tableSize);
+        } else {
+            //convert array of booleans to array of bytes
+            if( is_bool_array_conv_needed(type_name, length) ) {
+                char *new_name = (char*)context->mem.malloc(length+1);
+                tc_memcpy(new_name, type_name, length);
+                new_name[length-1] = 'B';
+                index = get_ref_type(new_name, length).getReferenceIdx();
+                context->mem.dealloc_last(new_name, length+1);
+            }
+            // Get next free table entry index
+            if( index == -1 ) {
+                index = check_table();
+                (validTypes+index)->cls = 0;
+                (validTypes+index)->name = entry->key;
+            }
+            entry->data = (void*)(validTypes+index);
+        }
+        return SmConstant::getReference(index);
+    }
+
+    SmConstant vf_TypePool::get_primitive_type(const char type_char) {
+        switch( type_char ) {
+        case 'I':
+        case 'B':
+        case 'Z':
+        case 'C':
+        case 'S':
+            return SM_INTEGER;
+        case 'J':
+            return SM_LONG;
+        case 'F':
+            return SM_FLOAT;
+        case 'V':
+            return SM_BOGUS;
+        case 'D':
+            return SM_DOUBLE;
+        default:
+            assert(0);
+            return SM_BOGUS;
+        }
+    }
+
+    SmConstant vf_TypePool::get_type(const char *type_name, int name_len) {
+        if( name_len > 1 ) {
+            if( type_name[0] == '[' ) {
+                return get_ref_type(type_name, name_len);
+            }
+
+            if( type_name[0] == 'L' ) {
+                return get_ref_type(type_name + 1, name_len - 2);
+            }
+
+            return SM_BOGUS;
+        } else {
+            return get_primitive_type(type_name[0]);
+        }
+    }
+
+
+    SmConstant vf_TypePool::get_ref_from_array(SmConstant element) {
+        if( element == SM_NULL ) return SM_NULL;
+
+        assert(element.isReference());
+        assert(sm_get_refname(element)[0] == '[');
+        return get_type(sm_get_refname(element) + 1);
+    }
+
+
+    int vf_TypePool::mustbe_assignable(SmConstant from, SmConstant to) {
+        if( from == to || to == SM_TOP ) return true;
+        if( from == SM_BOGUS ) return false;
+
+        if( to.isReference() ) {
+            if( from == SM_NULL ) return true;
+
+            if( from.isReference() ) {
+                return ref_mustbe_assignable(from, to);
+            }
+
+            return false;
+        }
+
+        if( !to.isPrimitive() ) {
+            assert( to != from ); // checked above
+            return false;
+        }
+
+        //migth have to change switch below if merging is done with constants
+        assert( from != SM_TOP );
+        assert( from != SM_ONEWORDED );
+        assert( from != SM_REF_OR_UNINIT_OR_RETADR );
+        assert( from != SM_REF_OR_UNINIT );
+        assert( from != SM_ANYARRAY );
+        assert( from != SM_TOP );
+        assert( from != SM_BOGUS );
+
+        switch ( to.c ) {
+        case SM_ONEWORDED:
+            return !from.isLongOrDouble();
+
+        case SM_REF_OR_UNINIT_OR_RETADR:
+            return from == SM_NULL || from == SM_THISUNINIT || !from.isPrimitive();
+
+        case SM_REF_OR_UNINIT:
+            return from == SM_NULL || from == SM_THISUNINIT || from.isNewObject() || from.isReference();
+
+        case SM_ANYARRAY:
+            return from == SM_NULL || from.isReference() && sm_get_refname(from)[0] == '[';
+
+        case SM_NULL:
+        case SM_THISUNINIT:
+            assert(0);
+            return false;
+
+        case SM_HIGH_WORD:
+        case SM_INTEGER:
+        case SM_FLOAT:
+        case SM_LONG:
+        case SM_DOUBLE:
+        case SM_BOGUS:
+            return false;
+        default:
+            assert(0);
+            return false;
+        }
+    }
+
+    int vf_TypePool::ref_mustbe_assignable(SmConstant from, SmConstant to) {
+        if( to == sm_get_const_object() ) return true;
+
+        vf_ValidType *to_type = &validTypes[to.getReferenceIdx()];
+        vf_ValidType *from_type = &validTypes[from.getReferenceIdx()];
+
+        const char *to_name = to_type->name;
+        const char *from_name = from_type->name;
+
+        int to_array = to_name[0] == '[';
+        int from_array = from_name[0] == '[';
+
+        if( to_array && !from_array ) {
+            return false;
+        } else if( to_array && from_array ) {
+            int dim = 0;
+            while( to_name[dim] == '[' && from_name[dim] == '[' ) dim++;
+
+            if( from_name[dim] != 'L' && from_name[dim] != '[' ) {
+                //primitive type
+                dim--;
+            }
+
+            if( to_name[dim] != 'L' ) return false;
+
+            if( from_name[dim] == 'L' ) {
+                //merge refs
+                return ref_mustbe_assignable(get_type(from_name + dim), get_type(to_name + dim) );
+            } else {
+                //to must be Object or an interface
+                return ref_mustbe_assignable(sm_get_const_object(), get_type(to_name + dim) );
+            }
+        } else {
+            //check whether TO class is loaded
+            if( !to_type->cls ) {
+                to_type->cls = vf_resolve_class(k_class, to_type->name, false);
+                if( !to_type->cls ) to_type->cls = CLASS_NOT_LOADED;
+            }
+
+            if( to_type->cls && to_type->cls != CLASS_NOT_LOADED ) {
+                //if to is loaded and it is an interface, treat it as an object
+                if( class_is_interface_( to_type->cls ) ) {
+                    return true;
+                }
+            } else {
+                NewConstraint(from_type->name, to_type->name);
+                return true;
+            }
+
+
+            //check whether FROM class is loaded
+
+            if( from_array ) from = sm_get_const_object();
+
+            if( !from_type->cls ) {
+                from_type->cls = vf_resolve_class(k_class, from_type->name, false);
+                if( !from_type->cls ) from_type->cls = CLASS_NOT_LOADED;
+            }
+
+            if( from_type->cls && from_type->cls != CLASS_NOT_LOADED ) {
+                return vf_is_valid(from_type->cls, to_type->cls);
+            } else {
+                NewConstraint(from_type->name, to_type->name);
+                return 1;
+            }
+        }
+    }
+
+    void vf_TypePool::NewConstraint(const char *available,
+        const char *required)
+    {
+        vf_TypeConstraint_s *constraint;
+
+        // lookup constraint
+        for( constraint = context->class_constraints; constraint; constraint = constraint->next) {
+            if( constraint->target == required && constraint->source == available ) {
+                // this constraint is already present
+                return;
+            }
+        }
+
+        // set constraint
+        constraint = (vf_TypeConstraint_s*)context->constraintPool.malloc(sizeof(vf_TypeConstraint_s));
+        constraint->target = required;
+        constraint->source = available;
+        constraint->next = context->class_constraints;
+        context->class_constraints = constraint;
+
+        return;
+    }
+
+    SmConstant vf_TypePool::cpool_get_ldcarg(unsigned short cp_idx) {
+        if( cp_idx >= k_cp_length || !cp_idx ) return SM_BOGUS;
+
+        switch (class_get_cp_tag( k_class, cp_idx ) ) {
+        case _CONSTANT_String: 
+            return sm_get_const_string();
+
+        case _CONSTANT_Integer: 
+            return SM_INTEGER;
+
+        case _CONSTANT_Float:
+            return SM_FLOAT;
+
+        case _CONSTANT_Class:
+            //check if it's a 1.5 class (major version is 49)
+            return context->k_major < 49 ? SM_BOGUS : sm_get_const_class();
+
+        default:
+            return SM_BOGUS;
+        }
+    }
+
+
+    SmConstant vf_TypePool::cpool_get_ldc2arg(unsigned short cp_idx) {
+        if( cp_idx >= k_cp_length || !cp_idx ) return SM_BOGUS;
+
+        switch (class_get_cp_tag( k_class, cp_idx ) ) {
+        case _CONSTANT_Double: 
+            return SM_DOUBLE;
+
+        case _CONSTANT_Long: 
+            return SM_LONG;
+
+        default:
+            return SM_BOGUS;
+        }
+    }
+
+
+    int vf_TypePool::cpool_is_reftype(unsigned short cp_idx) {
+        return cp_idx && cp_idx < k_cp_length && class_get_cp_tag( k_class, cp_idx ) == _CONSTANT_Class;
+    }
+
+
+    int vf_TypePool::cpool_get_class(unsigned short cp_idx, SmConstant *ref, int expected_dim) {
+        if( !cpool_is_reftype(cp_idx) ) return false;
+
+        unsigned short name_idx = class_get_cp_class_name_index(k_class, cp_idx);
+        if( name_idx >= k_cp_length ) return false;
+
+        const char* name = class_get_cp_utf8_bytes( k_class, name_idx );
+
+        //validate dimensions
+        int ptr = 0;
+        while (name[ptr] == '[' ) {
+            ptr++;
+        }
+        //'name' already contains final '[', so max dimension of class 'name' is 255
+        if( ptr <  expected_dim || ptr > 255 ) return false;
+
+        //array is not allowed here
+        if( ptr && expected_dim == -1 ) return false;
+
+
+        //TODO: do we need to resolve if we don't need SmConstant?
+        //e.g. do we need to resolve class of a static variable?
+        //constantpool validation should be done whereever else
+        if( ref ) *ref = get_ref_type(name, (int)strlen(name));
+
+        return true;
+    }
+
+    int vf_TypePool::cpool_get_array(unsigned short cp_idx, SmConstant *ref) {
+        assert(ref);
+        if( !cpool_is_reftype(cp_idx) ) return false;
+
+        unsigned short name_idx = class_get_cp_class_name_index(k_class, cp_idx);
+        if( name_idx >= k_cp_length ) return false;
+
+        const char* name = class_get_cp_utf8_bytes( k_class, name_idx );
+        int len = (int)strlen(name);
+
+
+        //validate dimensions
+        int ptr = 0;
+        while (name[ptr] == '[' ) {
+            ptr++;
+        }
+
+        //'name' does not contain final '[', so max dimension of class 'name' is 254
+        if( ptr > 254 ) return false;
+
+
+
+        char* arr_name = (char*)context->mem.malloc(len + 4);
+        arr_name[0] = '[';
+
+        if( name[0] == '[' ) {
+            tc_memcpy(arr_name + 1, name, len);
+            *ref = get_ref_type(arr_name, len + 1);
+        } else {
+            arr_name[1] = 'L';
+            tc_memcpy(arr_name + 2, name, len);
+            arr_name[len + 2] = ';';
+            *ref = get_ref_type(arr_name, len + 3);
+        }
+
+        context->mem.dealloc_last(arr_name, len + 4);
+        return true;
+    }
+
+
+    int vf_TypePool::cpool_get_field(unsigned short cp_idx, SmConstant *ref, SmConstant *value) {
+        //check it is a field
+        if( !cp_idx || cp_idx >= k_cp_length || class_get_cp_tag( k_class, cp_idx ) != _CONSTANT_Fieldref ) {
+            return false;
+        }
+
+        unsigned short class_idx = class_get_cp_ref_class_index( k_class, cp_idx );
+        if( !cpool_get_class(class_idx, ref) ) return false;
+
+        unsigned short name_and_type_idx = class_get_cp_ref_name_and_type_index( k_class, cp_idx );
+        if( !name_and_type_idx || name_and_type_idx >= k_cp_length || class_get_cp_tag( k_class, name_and_type_idx ) != _CONSTANT_NameAndType ) return false;
+
+        //TODO: do we need this check?
+        //unsigned short name_idx = class_get_cp_name_index( k_class, name_and_type_idx );
+        //if( !name_idx || name_idx >= k_cp_length || class_get_cp_tag( k_class, name_idx ) != _CONSTANT_Utf8 ) return false;
+
+        //get filed type
+        unsigned short type_idx = class_get_cp_descriptor_index( k_class, name_and_type_idx );
+        if( !type_idx || type_idx >= k_cp_length || class_get_cp_tag( k_class, type_idx ) != _CONSTANT_Utf8 ) return false;
+
+        const char *type = class_get_cp_utf8_bytes( k_class, type_idx );
+        *value = get_type(type);
+
+        return true;
+    }
+
+    int vf_TypePool::cpool_method_start(unsigned short cp_idx, const char **state, SmConstant *objectref, 
+        unsigned short *name_idx, int opcode) {
+
+            ClassConstantPoolTags expected_tag = opcode == OP_INVOKEINTERFACE ? _CONSTANT_InterfaceMethodref : _CONSTANT_Methodref;
+
+            //check it is a method
+            if( !cp_idx || cp_idx >= k_cp_length || class_get_cp_tag( k_class, cp_idx ) != expected_tag ) {
+                return false;
+            }
+
+            unsigned short class_idx = class_get_cp_ref_class_index( k_class, cp_idx );
+            if( opcode == OP_INVOKEVIRTUAL || opcode == OP_INVOKESPECIAL ) {
+                if( !cpool_get_class(class_idx, objectref) ) return false;
+            } else {
+                if( !cpool_get_class(class_idx, 0) ) return false;
+                (*objectref) = sm_get_const_object();
+            }
+
+            unsigned short name_and_type_idx = class_get_cp_ref_name_and_type_index( k_class, cp_idx );
+            if( !name_and_type_idx || name_and_type_idx >= k_cp_length || class_get_cp_tag( k_class, name_and_type_idx ) != _CONSTANT_NameAndType ) return false;
+
+            *name_idx = class_get_cp_name_index( k_class, name_and_type_idx );
+            //TODO: do we need this check?
+            if( !(*name_idx) || *name_idx >= k_cp_length || class_get_cp_tag( k_class, *name_idx ) != _CONSTANT_Utf8 ) return false;
+
+            //get filed type or function args & rettype
+            unsigned short type_idx = class_get_cp_descriptor_index( k_class, name_and_type_idx );
+            if( !type_idx || type_idx >= k_cp_length || class_get_cp_tag( k_class, type_idx ) != _CONSTANT_Utf8 ) return false;
+
+            (*state) = class_get_cp_utf8_bytes( k_class, type_idx );
+            return true;
+        }
+
+
+        //find return type and count number of arguments
+        int vf_TypePool::cpool_method_get_rettype(const char **state, SmConstant *rettype, int *args_sz) {
+            const char *name = (*state);
+            if( name[0] != '(' ) return 0;
+
+            int i = 1;
+            //count number of args: skip '['s and all between 'L' and ';'
+            (*args_sz) = 0;
+            bool on = true;
+            char current;
+            while ( (current = name[i]) != ')' ) {
+                if( !current ) return 0;
+                if( current == 'L' ) on = false;
+                if( current == ';' ) on = true;
+                if( on && current != '[') {
+                    (*args_sz)++;
+                    //it is long or double and not an array of long or double
+                    if ((current == 'J' || current == 'D') && name[i-1] != '[') {
+                        (*args_sz)++;
+                    }
+                }
+                i++;
+            }
+            (*state) = i == 1 ? 0 : name + 1;
+            name = name + i + 1;
+
+            *rettype = get_type(name);
+            return 1;
+        }
+
+        int vf_TypePool::cpool_method_next_arg(const char **state, SmConstant *argument) {
+            const char *name = (*state);
+
+            //define name length
+            int len = 0;
+            //skip '['s
+            if ((*state)[len] == '[') {
+                while( (*state)[++len] == '[' ) ;//len++;
+            }
+            //skip up to ';'
+            if( (*state)[len] == 'L' ) {
+                while( (*state)[++len] != ';' ) ;
+                // already checked for '\0' by cpool_method_getrettype
+                //        {
+                //            assert((*state)[len]);
+                //            if( !(*state)[len] ) return false;
+                //            len++;
+                //        }
+            }
+            len++;
+
+            *argument = get_type((*state), len);
+
+            (*state) = (*state)[len] == ')' ? 0 : (*state) + len;
+            return true;
+        }
+
+        int vf_TypePool::cpool_method_is_constructor_call(unsigned short name_idx) {
+            return !strcmp(class_get_cp_utf8_bytes( k_class, name_idx ), "<init>");
+        }
+
+} // namespace CPVerifier

Propchange: harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/tpool.cpp
------------------------------------------------------------------------------
    svn:executable = *