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/10/12 16:42:23 UTC

svn commit: r584170 [5/7] - in /harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363: base/ java5/ java6/

Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/base/ver_utils.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/base/ver_utils.h?rev=584170&r1=584169&r2=584170&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/base/ver_utils.h (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/base/ver_utils.h Fri Oct 12 07:42:03 2007
@@ -1,425 +1,425 @@
-/*
- *  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 __VER_UTILS_H_
-#define __VER_UTILS_H_
-
-#include <assert.h>
-#include "clog.h"
-#include <iostream>
-using namespace std;
-
-namespace CPVerifier {
-
-    // convenience types
-    typedef unsigned short Address;
-
-    //TODO:
-#define tc_free(ptr)                free(ptr)
-#define tc_realloc(ptr, sz)         realloc(ptr, sz)
-#define tc_malloc(sz)               malloc(sz)
-#define tc_calloc(sz1, sz2)         calloc(sz1, sz2)
-#define tc_memcpy(ptr1, ptr2, sz)   vf_memcpy(ptr1, ptr2, sz)
-#define tc_memset(ptr, i1, i2)      vf_memset(ptr, i1, i2)
-
-    //TODO: delegate to compiler
-    inline void *vf_memcpy(void *dest, const void *src, size_t count) {
-        char *d = (char *)dest;
-        const char *s = (const char *)src;
-        for (; count; count--) {
-            *d++ = *s++;
-        }
-        return dest;
-    }
-
-    //TODO: delegate to compiler
-    inline void *vf_memset(void *dest, int val, size_t count) {
-        char *d = (char *)dest;
-        char v = (char) val;
-        for (; count; count--) {
-            *d++ = v;
-        }
-        return dest;
-    }
-
-    /**
-    * Structure of hash entry.
-    */
-    struct vf_HashEntry_t {
-        const char *key;            // hash entry key
-        int key_size;               // hash entry key size
-        union {                     // hash entry data
-            unsigned data_index;    // when it's an index
-            void* data_ptr;         // when it's data
-        };
-        vf_HashEntry_t *next;       // next hash entry
-    };
-
-    class Stack {
-    protected:
-        int max_depth;
-        Address* stack;
-        int depth;
-
-    public:
-        Stack() :
-          max_depth(0), stack(0), depth(0)
-          {}
-
-
-          ~Stack() {
-              tc_free(stack);
-          }
-
-          void push(Address value) {
-              if( depth == max_depth ) {
-                  max_depth += max_depth/2 + 32;
-                  stack = (Address*) tc_realloc(stack, sizeof(Address) * max_depth);
-              }
-
-              stack[depth++] = value;
-          }
-
-          Address pop() {
-              assert(depth > 0);
-              return stack[--depth];
-          }
-
-          bool is_empty() {
-              return !depth;
-          }
-
-          void init() {
-              depth = 0;
-          }
-    };
-
-    class FastStack : Stack {
-    public:
-        FastStack() : fdepth(0) 
-        {}
-
-        void push(Address value) {
-            if( fdepth < BUFSIZE ) {
-                buffer[fdepth++] = value;
-            } else {
-                Stack::push(value);
-            }
-        }
-
-        Address pop() {
-            assert(fdepth > 0);
-            return Stack::is_empty() ? buffer[--fdepth] : Stack::pop();
-        }
-
-        bool is_empty() {
-            return !fdepth;
-        }
-
-        void init() {
-            fdepth = 0;
-            Stack::init();
-        }
-
-    private:
-        static const int BUFSIZE = 100;
-        int fdepth;
-        Address buffer[BUFSIZE];
-    };
-
-    class MarkableStack : public FastStack {
-        // contains the following entries:
-        // <address, mark> no mask means zero mark
-
-        // <non-zero address, 0> is pushed as {address}
-        // <0, 0> is pushed as {0, 0}
-        // <any address, non-zero mark> is pushed as {address, mark, 0}
-
-    public:
-        void xPop(Address *addr, short *mark) {
-            *addr = pop();
-            *mark = (*addr) ? 0 : pop();
-
-            if( *mark ) {
-                *addr = pop();
-            }
-        }
-
-        void xPush(Address value) {
-            if( value ) { 
-                push(value);
-            } else {
-                push(0);
-                push(0);
-            }
-        }
-
-        void xPush(Address addr, short m) {
-            push(addr);
-            push(m);
-            push(0);
-        }
-    };
-
-    struct MemoryPageHead {
-        MemoryPageHead *next;
-        size_t size;
-
-        MemoryPageHead *get_next(size_t min_size, size_t max_size) {
-            assert(this);
-            MemoryPageHead *ret = this;
-            while ( ret->next && ret->next->size < min_size ) {
-                ret = ret->next;
-            }
-
-            return ret->next ? ret->next : (ret->next = create_next(max_size));
-        }
-
-        MemoryPageHead *create_next(size_t max_size) {
-            MemoryPageHead *ret =(MemoryPageHead*)tc_malloc(max_size + sizeof(MemoryPageHead));
-            ret->size = max_size;
-            ret->next = 0;
-            return ret;
-        }
-    };
-
-    class Memory {
-        MemoryPageHead *static_page;
-        MemoryPageHead *current_page;
-
-        static const int STATICSZ = 2000;
-        uint8           static_mem[STATICSZ + sizeof (MemoryPageHead) ];
-
-        size_t  page_size;
-        size_t  used;
-    public:
-        Memory() 
-        {
-            //in 90% of cases no memory allocation will be required
-            static_page = (MemoryPageHead *)&static_mem;
-            static_page->next = 0;
-            static_page->size = STATICSZ;
-
-            init();
-        }
-
-        ~Memory() {
-            current_page = static_page->next;
-            while (current_page) {
-                MemoryPageHead *next = current_page->next;
-                tc_free(current_page);
-                current_page = next;
-            }
-        }
-
-        void init() {
-            used = 0;
-            current_page = static_page;
-            page_size = current_page->size;
-        }
-
-        void *malloc(size_t sz) {
-            size_t need_on_page = used + sz;
-
-            if( need_on_page > page_size ) {
-                //create next page
-
-                //define new page size - some heuristic formula. subject to change
-                size_t desired_size = need_on_page + need_on_page/2 + 128;
-
-                //allocating next page
-                current_page = current_page->get_next(sz, desired_size);
-                if( !static_page ) {
-                    static_page = current_page;
-                }
-                used = 0;
-                page_size = current_page->size;
-            }
-
-            void *ret = (uint8*)current_page + sizeof(MemoryPageHead) + used;
-            used += sz;
-            return ret;
-        }
-
-        void *calloc(size_t sz) {
-            void *ret = malloc(sz);
-            tc_memset(ret, 0, sz);
-            return ret;
-        }
-
-        void dealloc_last(void* ptr, size_t sz) {
-            assert( ((uint8*)ptr) + sz == (uint8*)current_page + sizeof(MemoryPageHead) + used );
-            used -= sz;
-        }
-    };
-
-    /**
-    * Verifier hash table structure.
-    */
-    struct vf_Hash {
-    public:
-        /**
-        * Hash table constructor.
-        * @note Function allocates memory for hash pool and hash table.
-        */
-        vf_Hash() 
-        {
-            memoryPool.init();
-            m_hash = (vf_HashEntry_t**)memoryPool.calloc(HASH_SIZE * sizeof(vf_HashEntry_t*));
-            assert((0xFFFFFFFF & HASH_MASK) + 1 == HASH_SIZE );
-        } // vf_Hash::vf_Hash
-
-
-        /**
-        * Function looks up hash entry which is identical to given hash key.
-        * @param key - given hash key
-        * @return Hash entry which is identical to given hash key.
-        * @see vf_HashEntry_t
-        */
-        vf_HashEntry_t * Lookup( const char *key ) {
-            assert( key );
-            int length = (int)strlen(key);
-
-            unsigned hash_index = HashFunc( key, length );
-
-            vf_HashEntry_t *hash_entry = m_hash[hash_index];
-            while( hash_entry != NULL ) {
-                if( CheckKey( hash_entry, key, length ) ) {
-                    return hash_entry;
-                }
-                hash_entry = hash_entry->next;
-            }
-            return NULL;
-        } // vf_Hash::Lookup( key )
-
-
-        /**
-        * Function creates hash entry which is identical to given hash key.
-        * @param key - given hash key
-        * @param length - length for the key
-        * @return Hash entry which are identical to given hash key.
-        * @see vf_HashEntry_t
-        * @note Created hash key and hash entry is allocated into hash memory pool.
-        */
-        vf_HashEntry_t * NewHashEntry( const char *key, int length ) {
-            // lookup type in hash
-            assert( key );
-            unsigned hash_index = HashFunc( key, length );
-
-            vf_HashEntry_t *hash_entry = m_hash[hash_index];
-            while( hash_entry != NULL ) {
-                if( CheckKey( hash_entry, key, length ) ) {
-                    return hash_entry;
-                }
-                hash_entry = hash_entry->next;
-            }
-
-            if( !hash_entry ) {
-                // create key string
-                char *hash_key = (char*)memoryPool.malloc( (length & (~3)) + 4);
-                tc_memcpy( hash_key, key, length );
-                hash_key[length] = 0;
-
-                hash_entry = (vf_HashEntry_t*)memoryPool.malloc(sizeof(vf_HashEntry_t));
-                hash_entry->key = hash_key;
-                hash_entry->key_size = length;
-                hash_entry->next = m_hash[hash_index];
-
-                hash_entry->data_ptr = 0;
-                hash_entry->data_index = 0;
-
-                m_hash[hash_index] = hash_entry;
-            }
-
-            return hash_entry;
-        } // vf_Hash::NewHashEntry( key, length )
-
-        /**
-        * Function creates hash entry which is identical to given hash key.
-        * @param key - given hash key
-        * @return Hash entry which are identical to given hash key.
-        * @see vf_HashEntry_t
-        * @note Created hash key and hash entry is allocated into hash memory pool.
-        */
-        vf_HashEntry_t * NewHashEntry( const char *key) {
-            return NewHashEntry(key, (int)strlen(key));
-        } // vf_Hash::NewHashEntry( key )
-
-    private:
-        static const unsigned HASH_SIZE = 128;   ///< hash table size
-        static const unsigned HASH_MASK = 127;   ///< hash table mask to avoid division
-
-        Memory memoryPool;
-        vf_HashEntry_t **m_hash;    ///< hash table
-
-        /**
-        * Function checks key identity.
-        * @param hash_entry - checked hash entry
-        * @param key        - checked key
-        * @return If keys are identical function returns <code>true</code>,
-        *         else returns <code>false</code>.
-        * @see vf_HashEntry_t
-        */
-        int CheckKey( vf_HashEntry_t *hash_entry, const char *key, int length) {
-            if( hash_entry->key_size != length ) return false;
-
-            const char* h_key = hash_entry->key; 
-            int idx = 0;
-
-            for( ; idx < length - 3; idx += 4 ) {
-                if( *((uint32*) (key+idx) ) != *((uint32*) (h_key+idx) ) ) return false;
-            }
-
-            for( ; idx < length; idx++) {
-                if( *(key+idx) != *(h_key+idx) ) return false;
-            }
-
-            return true;
-        }
-
-        /**
-        * Hash function.
-        * @param key - key for hash function
-        * @return Hash index relevant to key.
-        */
-        unsigned HashFunc( const char *key, int length ) {
-            unsigned result = 0;
-
-            int idx = 0;
-
-            for( ; idx < length - 3; idx += 4 ) {
-                result += *((uint32*) (key+idx) );
-            }
-
-            for( ; idx < length; idx++) {
-                result += *(key+idx);
-            }
-
-            uint8 *bres = (uint8*) &result;
-
-            return (bres[0] + bres[1] + bres[2] + bres[3]) & HASH_MASK;
-        } // vf_Hash::HashFunc( key )
-
-    }; // struct vf_Hash
-
-} // namespace CPVerifier
-
-
-#endif
+/*
+ *  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 __VER_UTILS_H_
+#define __VER_UTILS_H_
+
+#include <assert.h>
+#include "clog.h"
+#include <iostream>
+using namespace std;
+
+namespace CPVerifier {
+
+    // convenience types
+    typedef unsigned short Address;
+
+    //TODO:
+#define tc_free(ptr)                free(ptr)
+#define tc_realloc(ptr, sz)         realloc(ptr, sz)
+#define tc_malloc(sz)               malloc(sz)
+#define tc_calloc(sz1, sz2)         calloc(sz1, sz2)
+#define tc_memcpy(ptr1, ptr2, sz)   vf_memcpy(ptr1, ptr2, sz)
+#define tc_memset(ptr, i1, i2)      vf_memset(ptr, i1, i2)
+
+    //TODO: delegate to compiler
+    inline void *vf_memcpy(void *dest, const void *src, size_t count) {
+        char *d = (char *)dest;
+        const char *s = (const char *)src;
+        for (; count; count--) {
+            *d++ = *s++;
+        }
+        return dest;
+    }
+
+    //TODO: delegate to compiler
+    inline void *vf_memset(void *dest, int val, size_t count) {
+        char *d = (char *)dest;
+        char v = (char) val;
+        for (; count; count--) {
+            *d++ = v;
+        }
+        return dest;
+    }
+
+    /**
+    * Structure of hash entry.
+    */
+    struct vf_HashEntry_t {
+        const char *key;            // hash entry key
+        int key_size;               // hash entry key size
+        union {                     // hash entry data
+            unsigned data_index;    // when it's an index
+            void* data_ptr;         // when it's data
+        };
+        vf_HashEntry_t *next;       // next hash entry
+    };
+
+    class Stack {
+    protected:
+        int max_depth;
+        Address* stack;
+        int depth;
+
+    public:
+        Stack() :
+          max_depth(0), stack(0), depth(0)
+          {}
+
+
+          ~Stack() {
+              tc_free(stack);
+          }
+
+          void push(Address value) {
+              if( depth == max_depth ) {
+                  max_depth += max_depth/2 + 32;
+                  stack = (Address*) tc_realloc(stack, sizeof(Address) * max_depth);
+              }
+
+              stack[depth++] = value;
+          }
+
+          Address pop() {
+              assert(depth > 0);
+              return stack[--depth];
+          }
+
+          bool is_empty() {
+              return !depth;
+          }
+
+          void init() {
+              depth = 0;
+          }
+    };
+
+    class FastStack : Stack {
+    public:
+        FastStack() : fdepth(0) 
+        {}
+
+        void push(Address value) {
+            if( fdepth < BUFSIZE ) {
+                buffer[fdepth++] = value;
+            } else {
+                Stack::push(value);
+            }
+        }
+
+        Address pop() {
+            assert(fdepth > 0);
+            return Stack::is_empty() ? buffer[--fdepth] : Stack::pop();
+        }
+
+        bool is_empty() {
+            return !fdepth;
+        }
+
+        void init() {
+            fdepth = 0;
+            Stack::init();
+        }
+
+    private:
+        static const int BUFSIZE = 100;
+        int fdepth;
+        Address buffer[BUFSIZE];
+    };
+
+    class MarkableStack : public FastStack {
+        // contains the following entries:
+        // <address, mark> no mask means zero mark
+
+        // <non-zero address, 0> is pushed as {address}
+        // <0, 0> is pushed as {0, 0}
+        // <any address, non-zero mark> is pushed as {address, mark, 0}
+
+    public:
+        void xPop(Address *addr, short *mark) {
+            *addr = pop();
+            *mark = (*addr) ? 0 : pop();
+
+            if( *mark ) {
+                *addr = pop();
+            }
+        }
+
+        void xPush(Address value) {
+            if( value ) { 
+                push(value);
+            } else {
+                push(0);
+                push(0);
+            }
+        }
+
+        void xPush(Address addr, short m) {
+            push(addr);
+            push(m);
+            push(0);
+        }
+    };
+
+    struct MemoryPageHead {
+        MemoryPageHead *next;
+        size_t size;
+
+        MemoryPageHead *get_next(size_t min_size, size_t max_size) {
+            assert(this);
+            MemoryPageHead *ret = this;
+            while ( ret->next && ret->next->size < min_size ) {
+                ret = ret->next;
+            }
+
+            return ret->next ? ret->next : (ret->next = create_next(max_size));
+        }
+
+        MemoryPageHead *create_next(size_t max_size) {
+            MemoryPageHead *ret =(MemoryPageHead*)tc_malloc(max_size + sizeof(MemoryPageHead));
+            ret->size = max_size;
+            ret->next = 0;
+            return ret;
+        }
+    };
+
+    class Memory {
+        MemoryPageHead *static_page;
+        MemoryPageHead *current_page;
+
+        static const int STATICSZ = 2000;
+        uint8           static_mem[STATICSZ + sizeof (MemoryPageHead) ];
+
+        size_t  page_size;
+        size_t  used;
+    public:
+        Memory() 
+        {
+            //in 90% of cases no memory allocation will be required
+            static_page = (MemoryPageHead *)&static_mem;
+            static_page->next = 0;
+            static_page->size = STATICSZ;
+
+            init();
+        }
+
+        ~Memory() {
+            current_page = static_page->next;
+            while (current_page) {
+                MemoryPageHead *next = current_page->next;
+                tc_free(current_page);
+                current_page = next;
+            }
+        }
+
+        void init() {
+            used = 0;
+            current_page = static_page;
+            page_size = current_page->size;
+        }
+
+        void *malloc(size_t sz) {
+            size_t need_on_page = used + sz;
+
+            if( need_on_page > page_size ) {
+                //create next page
+
+                //define new page size - some heuristic formula. subject to change
+                size_t desired_size = need_on_page + need_on_page/2 + 128;
+
+                //allocating next page
+                current_page = current_page->get_next(sz, desired_size);
+                if( !static_page ) {
+                    static_page = current_page;
+                }
+                used = 0;
+                page_size = current_page->size;
+            }
+
+            void *ret = (uint8*)current_page + sizeof(MemoryPageHead) + used;
+            used += sz;
+            return ret;
+        }
+
+        void *calloc(size_t sz) {
+            void *ret = malloc(sz);
+            tc_memset(ret, 0, sz);
+            return ret;
+        }
+
+        void dealloc_last(void* ptr, size_t sz) {
+            assert( ((uint8*)ptr) + sz == (uint8*)current_page + sizeof(MemoryPageHead) + used );
+            used -= sz;
+        }
+    };
+
+    /**
+    * Verifier hash table structure.
+    */
+    struct vf_Hash {
+    public:
+        /**
+        * Hash table constructor.
+        * @note Function allocates memory for hash pool and hash table.
+        */
+        vf_Hash() 
+        {
+            memoryPool.init();
+            m_hash = (vf_HashEntry_t**)memoryPool.calloc(HASH_SIZE * sizeof(vf_HashEntry_t*));
+            assert((0xFFFFFFFF & HASH_MASK) + 1 == HASH_SIZE );
+        } // vf_Hash::vf_Hash
+
+
+        /**
+        * Function looks up hash entry which is identical to given hash key.
+        * @param key - given hash key
+        * @return Hash entry which is identical to given hash key.
+        * @see vf_HashEntry_t
+        */
+        vf_HashEntry_t * Lookup( const char *key ) {
+            assert( key );
+            int length = (int)strlen(key);
+
+            unsigned hash_index = HashFunc( key, length );
+
+            vf_HashEntry_t *hash_entry = m_hash[hash_index];
+            while( hash_entry != NULL ) {
+                if( CheckKey( hash_entry, key, length ) ) {
+                    return hash_entry;
+                }
+                hash_entry = hash_entry->next;
+            }
+            return NULL;
+        } // vf_Hash::Lookup( key )
+
+
+        /**
+        * Function creates hash entry which is identical to given hash key.
+        * @param key - given hash key
+        * @param length - length for the key
+        * @return Hash entry which are identical to given hash key.
+        * @see vf_HashEntry_t
+        * @note Created hash key and hash entry is allocated into hash memory pool.
+        */
+        vf_HashEntry_t * NewHashEntry( const char *key, int length ) {
+            // lookup type in hash
+            assert( key );
+            unsigned hash_index = HashFunc( key, length );
+
+            vf_HashEntry_t *hash_entry = m_hash[hash_index];
+            while( hash_entry != NULL ) {
+                if( CheckKey( hash_entry, key, length ) ) {
+                    return hash_entry;
+                }
+                hash_entry = hash_entry->next;
+            }
+
+            if( !hash_entry ) {
+                // create key string
+                char *hash_key = (char*)memoryPool.malloc( (length & (~3)) + 4);
+                tc_memcpy( hash_key, key, length );
+                hash_key[length] = 0;
+
+                hash_entry = (vf_HashEntry_t*)memoryPool.malloc(sizeof(vf_HashEntry_t));
+                hash_entry->key = hash_key;
+                hash_entry->key_size = length;
+                hash_entry->next = m_hash[hash_index];
+
+                hash_entry->data_ptr = 0;
+                hash_entry->data_index = 0;
+
+                m_hash[hash_index] = hash_entry;
+            }
+
+            return hash_entry;
+        } // vf_Hash::NewHashEntry( key, length )
+
+        /**
+        * Function creates hash entry which is identical to given hash key.
+        * @param key - given hash key
+        * @return Hash entry which are identical to given hash key.
+        * @see vf_HashEntry_t
+        * @note Created hash key and hash entry is allocated into hash memory pool.
+        */
+        vf_HashEntry_t * NewHashEntry( const char *key) {
+            return NewHashEntry(key, (int)strlen(key));
+        } // vf_Hash::NewHashEntry( key )
+
+    private:
+        static const unsigned HASH_SIZE = 128;   ///< hash table size
+        static const unsigned HASH_MASK = 127;   ///< hash table mask to avoid division
+
+        Memory memoryPool;
+        vf_HashEntry_t **m_hash;    ///< hash table
+
+        /**
+        * Function checks key identity.
+        * @param hash_entry - checked hash entry
+        * @param key        - checked key
+        * @return If keys are identical function returns <code>true</code>,
+        *         else returns <code>false</code>.
+        * @see vf_HashEntry_t
+        */
+        int CheckKey( vf_HashEntry_t *hash_entry, const char *key, int length) {
+            if( hash_entry->key_size != length ) return false;
+
+            const char* h_key = hash_entry->key; 
+            int idx = 0;
+
+            for( ; idx < length - 3; idx += 4 ) {
+                if( *((uint32*) (key+idx) ) != *((uint32*) (h_key+idx) ) ) return false;
+            }
+
+            for( ; idx < length; idx++) {
+                if( *(key+idx) != *(h_key+idx) ) return false;
+            }
+
+            return true;
+        }
+
+        /**
+        * Hash function.
+        * @param key - key for hash function
+        * @return Hash index relevant to key.
+        */
+        unsigned HashFunc( const char *key, int length ) {
+            unsigned result = 0;
+
+            int idx = 0;
+
+            for( ; idx < length - 3; idx += 4 ) {
+                result += *((uint32*) (key+idx) );
+            }
+
+            for( ; idx < length; idx++) {
+                result += *(key+idx);
+            }
+
+            uint8 *bres = (uint8*) &result;
+
+            return (bres[0] + bres[1] + bres[2] + bres[3]) & HASH_MASK;
+        } // vf_Hash::HashFunc( key )
+
+    }; // struct vf_Hash
+
+} // namespace CPVerifier
+
+
+#endif

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

Propchange: harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/base/ver_utils.h
            ('svn:executable' removed)

Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/base/vf_resolve.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/base/vf_resolve.cpp?rev=584170&r1=584169&r2=584170&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/base/vf_resolve.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/base/vf_resolve.cpp Fri Oct 12 07:42:03 2007
@@ -1,94 +1,94 @@
-/*
- *  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 "verifier.h"
-#include "context_base.h"
-#include "time.h"
-
-namespace CPVerifier {
-
-    /**
-    * Function checkes constraint for given class.
-    * Function loads classes if it's needed.
-    */
-    vf_Result
-        vf_force_check_constraint( class_handler klass, 
-        vf_TypeConstraint *constraint )    // class constraint
-    {
-        // get target class
-        class_handler target = vf_resolve_class( klass, constraint->target, true );
-        if( !target ) {
-            return VF_ErrorLoadClass;
-        }
-
-        //no need to load the source
-        if( class_is_interface_(target) ){
-            return VF_OK;
-        }
-
-
-        // get stack reference class
-        class_handler source = vf_resolve_class( klass, constraint->source, true );
-        if( !source ) {
-            return VF_ErrorLoadClass;
-        }
-
-        // check restriction
-        if( !vf_is_extending( source, target ) ) {
-            return VF_ErrorIncompatibleArgument;
-        }
-        return VF_OK;
-    } // vf_force_check_constraint
-
-
-    /**
-    * Returns true if 'from' is (not necessarily directly) extending 'to'
-    */
-    int vf_is_extending(class_handler from, class_handler to) {
-        while (from) {
-            if( from == to ) return true;
-            from = class_get_super_class(from);
-        }
-        return false;
-    }
-
-    /**
-    * Function receives class by given class name, loads it if it's needed.
-    */
-    class_handler
-        vf_resolve_class( class_handler k_class,    // current class
-        const char *name,         // resolved class name
-        bool need_load)      // load flag
-    {
-        class_handler result;
-
-        // get class loader
-        classloader_handler class_loader = class_get_class_loader( k_class );
-
-        result = need_load ? cl_load_class( class_loader, name ) : cl_get_class( class_loader, name );
-
-        //we assume that this pre-defined constant is not a valid class-handler
-        assert(CLASS_NOT_LOADED != result);
-        
-        return result;
-    } // vf_resolve_class
-
-
-} // namespace CPVerifier
+/*
+ *  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 "verifier.h"
+#include "context_base.h"
+#include "time.h"
+
+namespace CPVerifier {
+
+    /**
+    * Function checkes constraint for given class.
+    * Function loads classes if it's needed.
+    */
+    vf_Result
+        vf_force_check_constraint( class_handler klass, 
+        vf_TypeConstraint *constraint )    // class constraint
+    {
+        // get target class
+        class_handler target = vf_resolve_class( klass, constraint->target, true );
+        if( !target ) {
+            return VF_ErrorLoadClass;
+        }
+
+        //no need to load the source
+        if( class_is_interface_(target) ){
+            return VF_OK;
+        }
+
+
+        // get stack reference class
+        class_handler source = vf_resolve_class( klass, constraint->source, true );
+        if( !source ) {
+            return VF_ErrorLoadClass;
+        }
+
+        // check restriction
+        if( !vf_is_extending( source, target ) ) {
+            return VF_ErrorIncompatibleArgument;
+        }
+        return VF_OK;
+    } // vf_force_check_constraint
+
+
+    /**
+    * Returns true if 'from' is (not necessarily directly) extending 'to'
+    */
+    int vf_is_extending(class_handler from, class_handler to) {
+        while (from) {
+            if( from == to ) return true;
+            from = class_get_super_class(from);
+        }
+        return false;
+    }
+
+    /**
+    * Function receives class by given class name, loads it if it's needed.
+    */
+    class_handler
+        vf_resolve_class( class_handler k_class,    // current class
+        const char *name,         // resolved class name
+        bool need_load)      // load flag
+    {
+        class_handler result;
+
+        // get class loader
+        classloader_handler class_loader = class_get_class_loader( k_class );
+
+        result = need_load ? cl_load_class( class_loader, name ) : cl_get_class( class_loader, name );
+
+        //we assume that this pre-defined constant is not a valid class-handler
+        assert(CLASS_NOT_LOADED != result);
+        
+        return result;
+    } // vf_resolve_class
+
+
+} // namespace CPVerifier

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

Propchange: harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/base/vf_resolve.cpp
            ('svn:executable' removed)

Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/java5/context_5.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/java5/context_5.cpp?rev=584170&r1=584169&r2=584170&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/java5/context_5.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/java5/context_5.cpp Fri Oct 12 07:42:03 2007
@@ -1,680 +1,680 @@
-/*
- *  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 "context_5.h"
-namespace CPVerifier_5 {
-
-    /*
-    This method makes the first pass through the instruction set.
-    On that pass we check that all instruction have valid opcode, that no
-    jumps, no exception handlers lead to the middle of instruction nor 
-    out of the method. it checks that control does not flow out of the method.
-
-    It also finds all instructions that have multiple predecessors 
-    (like goto tagrtes), this information will be used on the second Pass
-
-    Method starts with the instruction <code>instr</code> for each it was invoked and go down 
-    filling the mask array with the flags. On this pass it distignushes
-    4 types of instructions:
-    0 - non-passed instruction or dead code
-    1 - passed instruction
-    2 - middle of passed instruction
-    3 - passed multiway instruction (having many predecessors)
-
-    If the method comes to a return, ret, athrow, or an already passed instruction, it terminates
-    If it comes to a switch, an if, or a jsr then it push all branches onto the stack
-    If it comes to a goto then it continues from the jump target
-    */
-
-    vf_Result vf_Context_5::parse(Address instr) {
-        // instruction is out of the method or in the middle of another instruction
-        if( instr > m_code_length || props.isOperand(instr) ) {
-            return error(VF_ErrorCodeEnd, "jump to the middle of instruction or out of the method");
-        }
-
-        while( instr < m_code_length ) {
-            if( props.isParsePassed(instr) ) {
-                // more than one branch leads to this instruction
-                if( !dead_code_parsing ) {
-                    props.setMultiway(instr);
-                }
-                return VF_OK;
-            }
-
-            OpCode opcode = (OpCode)m_bytecode[instr];
-            processed_instruction = instr;
-
-            // does code correspond to any valid instruction?
-            if( !instr_is_valid_bytecode(opcode) ) {
-                return error(VF_ErrorInstruction, "invalid opcode");
-            }
-
-            // keep all nessesary information about instruction
-            ParseInfo &pi = instr_get_parse_info(opcode);
-
-            // get MINIMAL length of the instruction with operands
-            unsigned instr_len = instr_get_minlen(pi);
-
-            // code does not correspond to any valid instruction or method length is less than required
-            if( instr + instr_len > m_code_length ) {
-                return error(VF_ErrorInstruction, "method length is less than required");
-            }
-
-            if( instr_is_compound(opcode, pi) ) {
-                // get ACTUAL length for variable length insgtructions
-                instr_len = instr_get_len_compound(instr, opcode);
-
-                // method length is less than required
-                if( instr + instr_len > m_code_length ) {
-                    return error(VF_ErrorInstruction, "compound instruction: method length is less than required");
-                }
-            }
-
-            // mark this instruction as processed
-            assert( !props.isParsePassed(instr) );
-            props.setParsePassed(instr);
-
-            // check that no other instruction jumps to the middle of the current instruction
-            for( Address i = instr + 1; i < instr + instr_len; i++ ) {
-                if( !props.setOperand(i) ) {
-                    return error(VF_ErrorUnknown, "jump to the middle of instruction");
-                }
-            }
-
-
-
-            if( instr_is_regular(pi) ) {
-                //regular instruction - go to the next instruction
-                instr += instr_len;
-            } else if( instr_is_jump(pi) ) {
-                // goto, goto_w, if*
-
-                Address target = instr_get_jump_target(pi, m_bytecode, instr);
-
-                // jump out of method or to the middle of an instruction
-                if( target >= m_code_length || props.isOperand(target) ) {
-                    return error(VF_ErrorBranch, "jump out of method or to the middle of an instruction");
-                }
-
-                if( instr_direct(pi, opcode, m_bytecode, instr) ) {
-                    //TODO: though the spec does not require to check the dead code for correctness
-                    //RI seems to check it and some Harmony negative tests have broken dead code
-
-                    dead_code_stack.push(instr+instr_len);
-
-                    instr = target; // it is not an if* - go to jump target
-                } else {
-                    // process conditional jump target or jsr
-                    stack.push(target);
-
-                    // go to the next instruction
-                    instr += instr_len;
-                }
-            } else if( instr_direct(pi, opcode, m_bytecode, instr) ) {
-                dead_code_stack.push(instr+instr_len);
-
-                // it is not a jump ==> it is return or throw or ret
-                return VF_OK;
-            } else {
-                assert( instr_is_switch(pi) );
-
-                Address next_target_adr = (instr & (~3) ) + 4;
-
-                //default target
-                Address target = instr + read_int32(m_bytecode + next_target_adr);
-                stack.push(target);
-
-                // in tableswitch instruction target offsets are stored with shift = 4,
-                // in lookupswitch with shift = 8
-                int shift = (opcode == OP_TABLESWITCH) ? 4 : 8;
-
-                for (next_target_adr += 12;
-                    next_target_adr < instr + instr_len;
-                    next_target_adr += shift)
-                {
-                    target = instr + read_int32(m_bytecode + next_target_adr);
-                    // jump out of method or to the middle of an instruction
-                    if( target >= m_code_length || props.isOperand(target) ) {
-                        return error(VF_ErrorBranch, "jump out of method or to the middle of an instruction");
-                    }
-                    // process conditional jump target
-                    stack.push(target);
-                }
-
-                return VF_OK;
-            }
-        }
-
-        //it might be a dead code -- code followed by JSR which never returns
-        //if it's a dead code - it's OK, if it's not - we will catch it on the second pass
-        return VF_OK;
-    }
-
-
-    vf_Result vf_Context_5::StartLinearDataflow(Address instr) {
-
-        vf_Result tcr;
-        int workmap_is_a_copy_of_stackmap;
-
-        if( props.isDataflowPassed(instr) ) {
-            //passed since it was added to the stack
-            assert(instr);
-            return VF_OK;
-        }
-
-        if (instr) {
-            workmap_is_a_copy_of_stackmap = true;
-            fill_workmap(instr);
-        } else {
-            //for the first instruction it does not matter if it is multiway or not
-            workmap_is_a_copy_of_stackmap = false;
-            // may return error in case of method's wrong signature
-            if((tcr = create_method_initial_workmap()) != VF_OK ) {
-                return tcr;
-            }
-        }
-
-        //list of handlers unknown
-        next_start_pc = 0;
-
-        return DataflowLoop(instr, workmap_is_a_copy_of_stackmap);
-    }
-
-    vf_Result vf_Context_5::SubroutineDone(Address subr) {
-        SubroutineData *subrdata = ((PropsHead*)props.getInstrProps(subr)->next)->getSubrData(m_max_stack + m_stack_start);
-        subrdata->subrDataflowed = 1;
-
-        if( !subrdata->retCount ) {
-            //no ret from subroutine -- dead code follows
-            return VF_OK;
-        }
-
-        Address jsr = subrdata->caller;
-
-        OpCode opcode = (OpCode)m_bytecode[jsr];
-        ParseInfo &pi = instr_get_parse_info(opcode);
-
-        processed_instruction = jsr;
-        if (jsr || props.isMultiway(jsr)) {
-            //note that in SubroutineDone unlike StartLinearDataflow we get workmap from stackmap
-            //in case of the first instruction of the method
-            fill_workmap(jsr);
-        } else {
-            vf_Result tcr = create_method_initial_workmap();
-            assert(tcr == VF_OK); // method's signature was already verified in StartLinearDataflow
-        }
-
-        //list of handlers unknown
-        next_start_pc = 0;
-
-        restore_workmap_after_jsr(subr);
-
-        //make a shift to the instr following jsr
-        Address instr = jsr + (opcode == OP_JSR_W ? 5 : 3);
-        assert(opcode == OP_JSR || opcode == OP_JSR_W);
-
-
-        return DataflowLoop(instr, 0);
-    }
-
-
-
-    // iterate thru the instructions starting with 'instr'
-    vf_Result vf_Context_5::DataflowLoop (Address instr, int workmap_is_a_copy_of_stackmap) {
-
-        vf_Result tcr;
-
-        while( instr < m_code_length ) {
-            if( !workmap_is_a_copy_of_stackmap && props.isMultiway(instr) ) {
-                //if instruction has a stackmap and workmap was not just obtained from that stackmap
-                // add constraint: workmap is assignable to stackmap(instr)
-                if( (tcr=new_generic_vector_constraint(instr)) != VF_OK ) {
-                    return tcr;
-                }
-
-                if( props.isDataflowPassed(instr) ) {
-                    return VF_OK;
-                }
-
-                fill_workmap(instr);
-            }
-            workmap_is_a_copy_of_stackmap = false;
-
-            OpCode opcode = (OpCode)m_bytecode[instr];
-            processed_instruction = instr;
-            // keep all nessesary information about instruction
-            ParseInfo &pi = instr_get_parse_info(opcode);
-
-            //check IN types, create OUT types, check exception
-            if( (tcr=dataflow_instruction(instr)) != VF_OK ) {
-                return tcr;
-            }
-
-            props.setDataflowPassed(instr);
-
-            unsigned instr_len = instr_get_minlen(pi);
-            if( instr_is_compound(opcode, pi) ) {
-                // get ACTUAL length for variable length insgtructions
-                instr_len = instr_get_len_compound(instr, opcode);
-            }
-
-            if( instr_is_jump(pi) ) {
-                Address target = instr_get_jump_target(pi, m_bytecode, instr);
-
-                if( props.isMultiway(target) || instr_is_jsr(opcode) ) {
-                    //TODO: need to test commented out optimization
-                    //&& (!instr_direct(pi, opcode, m_bytecode, instr) || props.isDataflowPassed(target))
-                    if( (tcr=new_generic_vector_constraint(target)) != VF_OK ) {
-                        return tcr;
-                    }
-                }
-
-                if( instr_direct(pi, opcode, m_bytecode, instr) ) {
-                    //goto, goto_w
-                    if( !props.isDataflowPassed(target) ) {
-                        if( target < instr ) next_start_pc = 0;
-
-                        //if we like to flush StackMapTable attribute from this method
-                        if( stackmapattr_calculation && !props.isMultiway(target) ) {
-                            //store workmap to flush it further
-                            assert(!props.getInstrProps(target));
-                            storeWorkmapCopy(target);
-                        }
-
-                        instr = target;
-                        continue;
-                    } else {
-                        return VF_OK;
-                    }
-                }
-
-
-                //TODO: makes sense to move the block into dataflow_instruction??
-                if( instr_is_jsr(opcode) ) {
-                    PropsHead *target_pro = (PropsHead*)props.getInstrProps(target);
-
-                    if( !props.isDataflowPassed(target) ) {
-                        for( unsigned i = 0; i < m_stack_start; i++ ) {
-                            StackmapElement &el = target_pro->stackmap.elements[i];
-                            el.clearJsrModified();
-                        }
-
-                        //create vector for storing ret types coming out of subroutine
-                        PropsHead *retpro = newRetData();
-                        retpro->instr = 0xFFFF;
-                        assert(!target_pro->next || target_pro->next->instr != 0xFFFF );
-                        retpro->next = target_pro->next;
-                        target_pro->next = retpro;
-
-                        SubroutineData *subrdata = retpro->getSubrData(m_stack_start+m_max_stack);
-
-                        if( !props.getInstrProps(instr) && instr) {
-                            //if jsr instruction does not have workmap copy or stackmap, associated with it - create it
-                            assert(workmap->depth);
-                            workmap->depth--; // undo PUSH(SM_RETADDR)
-                            storeWorkmapCopy(instr);
-                        }
-
-                        //need to return to that JSR instr later, when finish subroutine processing
-                        subrdata->caller = instr;
-
-                        //need to postpone some finalizing stuff
-                        stack.xPush(target, MARK_SUBROUTINE_DONE);
-
-                        //process subroutine
-                        stack.xPush(target);
-
-                        return VF_OK;
-                    } else {
-                        SubroutineData *subrdata = ((PropsHead*)target_pro->next)->getSubrData(m_stack_start+m_max_stack);
-
-                        if( !subrdata->subrDataflowed ) {
-                            //recursive call?
-                            return error(VF_ErrorDataFlow, "recursive subroutine");
-                        }
-
-                        restore_workmap_after_jsr(target);
-
-                        if( !subrdata->retCount ) {
-                            //no ret from subroutine -- dead code follows
-                            return VF_OK;
-                        } 
-
-                        instr += instr_len;
-                        continue;
-                    }
-                }
-
-                if( !props.isMultiway(target) ) {
-                    //if* with no stackmap at branch
-                    storeWorkmapCopy(target);
-                    assert( !props.isDataflowPassed(target) );
-                }
-
-                if( !props.isDataflowPassed(target) ) {
-                    stack.xPush(target);
-                }
-
-                instr += instr_len;
-            } else if( instr_direct(pi, opcode, m_bytecode, instr) ) {
-                // it is not a jump ==> it is ret, return or throw
-                return VF_OK;
-            } else if( instr_is_switch(pi) ) {
-
-                Address next_target_adr = (instr & (~3) ) + 4;
-
-                //default target
-                Address target = instr + read_int32(m_bytecode + next_target_adr);
-                processSwitchTarget(target);
-
-                // in tableswitch instruction target offsets are stored with shift = 4,
-                // in lookupswitch with shift = 8
-                int shift = (opcode == OP_TABLESWITCH) ? 4 : 8;
-
-                // process conditional jump target
-                for (next_target_adr += 12;
-                    next_target_adr < instr + instr_len;
-                    next_target_adr += shift)
-                {
-                    target = instr + read_int32(m_bytecode + next_target_adr);
-                    processSwitchTarget(target);
-                }
-
-                return VF_OK;
-            } else {
-                assert( instr_is_regular(pi) );
-                instr += instr_len;
-            }
-
-        }
-
-        // control went out of method bounds
-        return error(VF_ErrorCodeEnd, "control went out of method bounds");
-    }
-
-    vf_Result vf_Context_5::verify_method(method_handler method) {
-        vf_Result tcr;
-
-        //nothing to verify
-        if( !method_get_code_length( method ) ) {
-            return VF_OK;
-        }
-
-        //load memory storage, read variable like max_stack, etc
-        init(method);
-
-        //////////////////////////// FIRST PASS /////////////////////////
-        pass = 1;
-        stack.push(0);
-
-        unsigned short idx;
-        unsigned short start_pc;
-        unsigned short end_pc;
-        unsigned short handler_pc;
-        unsigned short handler_cp_index;
-
-        for( 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 >= end_pc || end_pc > m_code_length ) {
-                return error(VF_ErrorHandler, "start_pc >= end_pc OR end_pc > code_length");
-            }
-            stack.push(handler_pc);
-        }
-
-        //we have different slightly rules for processing dead and live code
-        //e.g. it's not a problem if dead code runs out of the method
-        //but we still have to verify it for corrupted instructions to follow RI
-        dead_code_parsing = 0;
-        do {
-            while( !stack.is_empty() ) {
-                vf_Result tcr = parse(stack.pop());
-                if( tcr != VF_OK ) {
-                    return tcr;
-                }
-            }
-
-            dead_code_parsing = 1;
-
-            while( !dead_code_stack.is_empty() ) {
-                vf_Result tcr = parse(dead_code_stack.pop());
-                if( tcr != VF_OK ) {
-                    return tcr;
-                }
-            }
-        } while (!stack.is_empty());
-
-
-
-        for( idx = 0; idx < m_handlecount; idx++ ) {
-
-            method_get_exc_handler_info( m_method, idx, &start_pc, &end_pc,
-                &handler_pc, &handler_cp_index );
-
-            if( end_pc < m_code_length && props.isOperand(end_pc) || props.isOperand(start_pc) ) {
-                return error(VF_ErrorCodeEnd, "start_pc or end_pc are at the middle of an instruction");
-            }
-
-            SmConstant handler_type;
-            if( handler_cp_index ) {
-                if( !tpool.cpool_get_class(handler_cp_index, &handler_type) ||
-                    !tpool.mustbe_assignable(handler_type, tpool.sm_get_const_throwable()) )
-                {
-                    return error(VF_ErrorHandler, "incorrect constantpool entry");
-                }
-            } else {
-                handler_type = tpool.sm_get_const_throwable();
-            }
-
-            props.setMultiway(handler_pc);
-            createHandlerStackmap(handler_pc, handler_type);
-        }
-
-        //////////////////////////// SECOND PASS /////////////////////////
-        pass = 2;
-
-        stack.xPush(0);
-        while( !stack.is_empty() ) {
-            Address next;
-            short mark;
-
-            stack.xPop(&next, &mark);
-
-            if( !mark ) {
-                tcr = StartLinearDataflow(next);
-            } else {
-                assert(mark == MARK_SUBROUTINE_DONE);
-                tcr = SubroutineDone(next);
-            }
-
-            if( tcr != VF_OK ) {
-                return tcr;
-            }
-        }
-
-        return VF_OK;
-    }
-
-
-
-
-    vf_Result vf_Context_5::new_ret_vector_constraint(Address jsr_target) {
-        PropsHead *inpro = (PropsHead*)props.getInstrProps(jsr_target);
-        PropsHead *outpro = (PropsHead*)inpro->next;
-        assert(outpro->instr == 0xFFFF);
-
-        SubroutineData *subrdata = outpro->getSubrData(m_stack_start + m_max_stack);
-        subrdata->retCount++;
-
-        //if it is a first ret from the given subroutine (majority of the cases)
-        if( subrdata->retCount == 1 ) {
-            //remove newly appeared ret addresses: it might happen
-            //if non-top subroutine made a ret
-            StackmapHead* original = inpro->getStackmap();
-            unsigned i;
-
-            for( i = 0; i < m_stack_start + workmap->depth; i++ ) {
-                if( i < m_stack_start && !workmap->elements[i].isJsrModified() ) {
-                    //nothing new here
-                    continue;
-                }
-
-                SmConstant val = workmap->elements[i].getAnyPossibleValue();
-                if( val.isRetAddr() ) {
-                    //check if it's a newly appeared ret addfress
-
-                    // '-1' is twice below to exclude top of the stack. 
-                    // top of the stack contains ret address for the current subroutine
-                    // it also cleaned up if it's still there
-
-                    if( i < m_stack_start + original->depth - 1 && 
-                        original->elements[i].getAnyIncomingValue() == val ) 
-                    {
-                        //most likely: this ret address was there before
-                        continue;
-                    }
-
-                    //iterate thru original types and look for this ret address
-                    int found_in_original = 0;
-                    for( unsigned j = 0; j < m_stack_start + original->depth - 1; j++ ) {
-                        if( original->elements[j].getAnyIncomingValue() == val ) {
-                            found_in_original = 1;
-                            break;
-                        }
-                    }
-                    if( !found_in_original ) {
-                        //original types did not have this ret address
-                        workmap->elements[i] = _WorkmapElement(SM_BOGUS);
-                    }
-                }
-            }
-
-            //TODO make sure incoming was created as JSR transformation
-            tc_memcpy(outpro->getWorkmap(), workmap, sizeof(WorkmapHead) + sizeof(WorkmapElement) * (m_stack_start + workmap->depth));
-            return VF_OK;
-        }
-
-        return error(VF_ErrorStackDepth, "Multiple returns to single jsr");
-    }
-
-
-    void vf_Context_5::restore_workmap_after_jsr(Address jsr_target) {
-        PropsHead *inpro = (PropsHead*)props.getInstrProps(jsr_target);
-        PropsHead *outpro = (PropsHead*)inpro->next;
-        SubroutineData *subrdata = outpro->getSubrData(m_stack_start + m_max_stack);
-
-        if( subrdata->retCount ) {
-            assert( subrdata->retCount == 1 );
-            WorkmapHead* outcoming = outpro->getWorkmap();
-            workmap->depth = outcoming->depth;
-
-            unsigned i;
-            for( i = 0; i < m_stack_start; i++ ) {
-                if( outcoming->elements[i].isJsrModified() ) {
-                    workmap->elements[i] = outcoming->elements[i];
-                }
-            }
-            for( ; i < m_stack_start + workmap->depth; i++ ) {
-                workmap->elements[i] = outcoming->elements[i];
-            }    
-        }
-    }
-
-    vf_Result vf_Context_5::new_scalar_constraint(WorkmapElement *from, StackmapElement *to) {
-        assert(from->getAnyPossibleValue() != SM_NONE);
-
-        if( from->isJsrModified() ) {
-            //JSR overhead
-            to->setJsrModified();
-        }
-
-        if( !from->isVariable() ) {
-            SmConstant inc_val = from->getConst();
-            return add_incoming_value( inc_val, to );
-        } else {
-            GenericCnstr* gen = from->getVariable()->firstGenericCnstr();
-            while( gen ) {
-                if( gen->variable == to ) return VF_OK;
-                gen = gen->next();
-            }
-
-            IncomingType *inc = from->getVariable()->firstIncoming();
-            from->getVariable()->newGenericConstraint(&mem, to);
-
-            while( inc ) {
-                vf_Result vcr = add_incoming_value( inc->value, to );
-                if( vcr != VF_OK ) {
-                    return vcr;
-                }
-                inc = inc->next();
-            }
-            return VF_OK;
-        }
-    }
-
-    vf_Result vf_Context_5::add_incoming_value(SmConstant new_value, StackmapElement *destination) {
-        //check if the node already has such incoming value
-        IncomingType *inc = destination->firstIncoming();
-        while( inc ) {
-            if( new_value == inc->value  || inc->value == SM_BOGUS ) {
-                return VF_OK;
-            }
-            inc = inc->next();
-        }
-
-        if( new_value.isNonMergeable() && destination->firstIncoming() ) {
-            //uninit value merged to any different value is bogus
-            //ret address merged to any different value is bogus
-            //assert - incoming value exists is different - we've already checked that new_value is missing in the list of incoming values
-            new_value = SM_BOGUS;
-        }
-
-        //add incoming value if it does not have
-        Constraint* next = destination->firstOthers();
-        //TODO: optimize memory footprint for new_value == SM_BOGUS
-        destination->newIncomingType(&mem, new_value);
-
-        //check if it contradicts to expected types and further propagate
-        while( next ) {
-            switch (next->type) {
-            case CT_EXPECTED_TYPE:
-                if( !tpool.mustbe_assignable(new_value, next->value) ) return error(VF_ErrorUnknown, "unexpected type on stack or local variable");
-                break;
-            case CT_GENERIC: {
-                vf_Result vcr = add_incoming_value(new_value, next->variable);
-                if( vcr != VF_OK ) return vcr;
-                break;
-                             }
-            case CT_ARRAY2REF: {
-                vf_Result vcr = add_incoming_value( tpool.get_ref_from_array(new_value), next->variable);
-                if( vcr != VF_OK ) return vcr;
-                break;
-                               }
-            default:
-                assert(0);
-                return error(VF_ErrorInternal, "unreachable statement in add_incoming_value");
-            }
-            next = next->next();
-        }
-        return VF_OK;
-    }
-
-} // namespace CPVerifier
+/*
+ *  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 "context_5.h"
+namespace CPVerifier_5 {
+
+    /*
+    This method makes the first pass through the instruction set.
+    On that pass we check that all instruction have valid opcode, that no
+    jumps, no exception handlers lead to the middle of instruction nor 
+    out of the method. it checks that control does not flow out of the method.
+
+    It also finds all instructions that have multiple predecessors 
+    (like goto tagrtes), this information will be used on the second Pass
+
+    Method starts with the instruction <code>instr</code> for each it was invoked and go down 
+    filling the mask array with the flags. On this pass it distignushes
+    4 types of instructions:
+    0 - non-passed instruction or dead code
+    1 - passed instruction
+    2 - middle of passed instruction
+    3 - passed multiway instruction (having many predecessors)
+
+    If the method comes to a return, ret, athrow, or an already passed instruction, it terminates
+    If it comes to a switch, an if, or a jsr then it push all branches onto the stack
+    If it comes to a goto then it continues from the jump target
+    */
+
+    vf_Result vf_Context_5::parse(Address instr) {
+        // instruction is out of the method or in the middle of another instruction
+        if( instr > m_code_length || props.isOperand(instr) ) {
+            return error(VF_ErrorCodeEnd, "jump to the middle of instruction or out of the method");
+        }
+
+        while( instr < m_code_length ) {
+            if( props.isParsePassed(instr) ) {
+                // more than one branch leads to this instruction
+                if( !dead_code_parsing ) {
+                    props.setMultiway(instr);
+                }
+                return VF_OK;
+            }
+
+            OpCode opcode = (OpCode)m_bytecode[instr];
+            processed_instruction = instr;
+
+            // does code correspond to any valid instruction?
+            if( !instr_is_valid_bytecode(opcode) ) {
+                return error(VF_ErrorInstruction, "invalid opcode");
+            }
+
+            // keep all nessesary information about instruction
+            ParseInfo &pi = instr_get_parse_info(opcode);
+
+            // get MINIMAL length of the instruction with operands
+            unsigned instr_len = instr_get_minlen(pi);
+
+            // code does not correspond to any valid instruction or method length is less than required
+            if( instr + instr_len > m_code_length ) {
+                return error(VF_ErrorInstruction, "method length is less than required");
+            }
+
+            if( instr_is_compound(opcode, pi) ) {
+                // get ACTUAL length for variable length insgtructions
+                instr_len = instr_get_len_compound(instr, opcode);
+
+                // method length is less than required
+                if( instr + instr_len > m_code_length ) {
+                    return error(VF_ErrorInstruction, "compound instruction: method length is less than required");
+                }
+            }
+
+            // mark this instruction as processed
+            assert( !props.isParsePassed(instr) );
+            props.setParsePassed(instr);
+
+            // check that no other instruction jumps to the middle of the current instruction
+            for( Address i = instr + 1; i < instr + instr_len; i++ ) {
+                if( !props.setOperand(i) ) {
+                    return error(VF_ErrorUnknown, "jump to the middle of instruction");
+                }
+            }
+
+
+
+            if( instr_is_regular(pi) ) {
+                //regular instruction - go to the next instruction
+                instr += instr_len;
+            } else if( instr_is_jump(pi) ) {
+                // goto, goto_w, if*
+
+                Address target = instr_get_jump_target(pi, m_bytecode, instr);
+
+                // jump out of method or to the middle of an instruction
+                if( target >= m_code_length || props.isOperand(target) ) {
+                    return error(VF_ErrorBranch, "jump out of method or to the middle of an instruction");
+                }
+
+                if( instr_direct(pi, opcode, m_bytecode, instr) ) {
+                    //TODO: though the spec does not require to check the dead code for correctness
+                    //RI seems to check it and some Harmony negative tests have broken dead code
+
+                    dead_code_stack.push(instr+instr_len);
+
+                    instr = target; // it is not an if* - go to jump target
+                } else {
+                    // process conditional jump target or jsr
+                    stack.push(target);
+
+                    // go to the next instruction
+                    instr += instr_len;
+                }
+            } else if( instr_direct(pi, opcode, m_bytecode, instr) ) {
+                dead_code_stack.push(instr+instr_len);
+
+                // it is not a jump ==> it is return or throw or ret
+                return VF_OK;
+            } else {
+                assert( instr_is_switch(pi) );
+
+                Address next_target_adr = (instr & (~3) ) + 4;
+
+                //default target
+                Address target = instr + read_int32(m_bytecode + next_target_adr);
+                stack.push(target);
+
+                // in tableswitch instruction target offsets are stored with shift = 4,
+                // in lookupswitch with shift = 8
+                int shift = (opcode == OP_TABLESWITCH) ? 4 : 8;
+
+                for (next_target_adr += 12;
+                    next_target_adr < instr + instr_len;
+                    next_target_adr += shift)
+                {
+                    target = instr + read_int32(m_bytecode + next_target_adr);
+                    // jump out of method or to the middle of an instruction
+                    if( target >= m_code_length || props.isOperand(target) ) {
+                        return error(VF_ErrorBranch, "jump out of method or to the middle of an instruction");
+                    }
+                    // process conditional jump target
+                    stack.push(target);
+                }
+
+                return VF_OK;
+            }
+        }
+
+        //it might be a dead code -- code followed by JSR which never returns
+        //if it's a dead code - it's OK, if it's not - we will catch it on the second pass
+        return VF_OK;
+    }
+
+
+    vf_Result vf_Context_5::StartLinearDataflow(Address instr) {
+
+        vf_Result tcr;
+        int workmap_is_a_copy_of_stackmap;
+
+        if( props.isDataflowPassed(instr) ) {
+            //passed since it was added to the stack
+            assert(instr);
+            return VF_OK;
+        }
+
+        if (instr) {
+            workmap_is_a_copy_of_stackmap = true;
+            fill_workmap(instr);
+        } else {
+            //for the first instruction it does not matter if it is multiway or not
+            workmap_is_a_copy_of_stackmap = false;
+            // may return error in case of method's wrong signature
+            if((tcr = create_method_initial_workmap()) != VF_OK ) {
+                return tcr;
+            }
+        }
+
+        //list of handlers unknown
+        next_start_pc = 0;
+
+        return DataflowLoop(instr, workmap_is_a_copy_of_stackmap);
+    }
+
+    vf_Result vf_Context_5::SubroutineDone(Address subr) {
+        SubroutineData *subrdata = ((PropsHead*)props.getInstrProps(subr)->next)->getSubrData(m_max_stack + m_stack_start);
+        subrdata->subrDataflowed = 1;
+
+        if( !subrdata->retCount ) {
+            //no ret from subroutine -- dead code follows
+            return VF_OK;
+        }
+
+        Address jsr = subrdata->caller;
+
+        OpCode opcode = (OpCode)m_bytecode[jsr];
+        ParseInfo &pi = instr_get_parse_info(opcode);
+
+        processed_instruction = jsr;
+        if (jsr || props.isMultiway(jsr)) {
+            //note that in SubroutineDone unlike StartLinearDataflow we get workmap from stackmap
+            //in case of the first instruction of the method
+            fill_workmap(jsr);
+        } else {
+            vf_Result tcr = create_method_initial_workmap();
+            assert(tcr == VF_OK); // method's signature was already verified in StartLinearDataflow
+        }
+
+        //list of handlers unknown
+        next_start_pc = 0;
+
+        restore_workmap_after_jsr(subr);
+
+        //make a shift to the instr following jsr
+        Address instr = jsr + (opcode == OP_JSR_W ? 5 : 3);
+        assert(opcode == OP_JSR || opcode == OP_JSR_W);
+
+
+        return DataflowLoop(instr, 0);
+    }
+
+
+
+    // iterate thru the instructions starting with 'instr'
+    vf_Result vf_Context_5::DataflowLoop (Address instr, int workmap_is_a_copy_of_stackmap) {
+
+        vf_Result tcr;
+
+        while( instr < m_code_length ) {
+            if( !workmap_is_a_copy_of_stackmap && props.isMultiway(instr) ) {
+                //if instruction has a stackmap and workmap was not just obtained from that stackmap
+                // add constraint: workmap is assignable to stackmap(instr)
+                if( (tcr=new_generic_vector_constraint(instr)) != VF_OK ) {
+                    return tcr;
+                }
+
+                if( props.isDataflowPassed(instr) ) {
+                    return VF_OK;
+                }
+
+                fill_workmap(instr);
+            }
+            workmap_is_a_copy_of_stackmap = false;
+
+            OpCode opcode = (OpCode)m_bytecode[instr];
+            processed_instruction = instr;
+            // keep all nessesary information about instruction
+            ParseInfo &pi = instr_get_parse_info(opcode);
+
+            //check IN types, create OUT types, check exception
+            if( (tcr=dataflow_instruction(instr)) != VF_OK ) {
+                return tcr;
+            }
+
+            props.setDataflowPassed(instr);
+
+            unsigned instr_len = instr_get_minlen(pi);
+            if( instr_is_compound(opcode, pi) ) {
+                // get ACTUAL length for variable length insgtructions
+                instr_len = instr_get_len_compound(instr, opcode);
+            }
+
+            if( instr_is_jump(pi) ) {
+                Address target = instr_get_jump_target(pi, m_bytecode, instr);
+
+                if( props.isMultiway(target) || instr_is_jsr(opcode) ) {
+                    //TODO: need to test commented out optimization
+                    //&& (!instr_direct(pi, opcode, m_bytecode, instr) || props.isDataflowPassed(target))
+                    if( (tcr=new_generic_vector_constraint(target)) != VF_OK ) {
+                        return tcr;
+                    }
+                }
+
+                if( instr_direct(pi, opcode, m_bytecode, instr) ) {
+                    //goto, goto_w
+                    if( !props.isDataflowPassed(target) ) {
+                        if( target < instr ) next_start_pc = 0;
+
+                        //if we like to flush StackMapTable attribute from this method
+                        if( stackmapattr_calculation && !props.isMultiway(target) ) {
+                            //store workmap to flush it further
+                            assert(!props.getInstrProps(target));
+                            storeWorkmapCopy(target);
+                        }
+
+                        instr = target;
+                        continue;
+                    } else {
+                        return VF_OK;
+                    }
+                }
+
+
+                //TODO: makes sense to move the block into dataflow_instruction??
+                if( instr_is_jsr(opcode) ) {
+                    PropsHead *target_pro = (PropsHead*)props.getInstrProps(target);
+
+                    if( !props.isDataflowPassed(target) ) {
+                        for( unsigned i = 0; i < m_stack_start; i++ ) {
+                            StackmapElement &el = target_pro->stackmap.elements[i];
+                            el.clearJsrModified();
+                        }
+
+                        //create vector for storing ret types coming out of subroutine
+                        PropsHead *retpro = newRetData();
+                        retpro->instr = 0xFFFF;
+                        assert(!target_pro->next || target_pro->next->instr != 0xFFFF );
+                        retpro->next = target_pro->next;
+                        target_pro->next = retpro;
+
+                        SubroutineData *subrdata = retpro->getSubrData(m_stack_start+m_max_stack);
+
+                        if( !props.getInstrProps(instr) && instr) {
+                            //if jsr instruction does not have workmap copy or stackmap, associated with it - create it
+                            assert(workmap->depth);
+                            workmap->depth--; // undo PUSH(SM_RETADDR)
+                            storeWorkmapCopy(instr);
+                        }
+
+                        //need to return to that JSR instr later, when finish subroutine processing
+                        subrdata->caller = instr;
+
+                        //need to postpone some finalizing stuff
+                        stack.xPush(target, MARK_SUBROUTINE_DONE);
+
+                        //process subroutine
+                        stack.xPush(target);
+
+                        return VF_OK;
+                    } else {
+                        SubroutineData *subrdata = ((PropsHead*)target_pro->next)->getSubrData(m_stack_start+m_max_stack);
+
+                        if( !subrdata->subrDataflowed ) {
+                            //recursive call?
+                            return error(VF_ErrorDataFlow, "recursive subroutine");
+                        }
+
+                        restore_workmap_after_jsr(target);
+
+                        if( !subrdata->retCount ) {
+                            //no ret from subroutine -- dead code follows
+                            return VF_OK;
+                        } 
+
+                        instr += instr_len;
+                        continue;
+                    }
+                }
+
+                if( !props.isMultiway(target) ) {
+                    //if* with no stackmap at branch
+                    storeWorkmapCopy(target);
+                    assert( !props.isDataflowPassed(target) );
+                }
+
+                if( !props.isDataflowPassed(target) ) {
+                    stack.xPush(target);
+                }
+
+                instr += instr_len;
+            } else if( instr_direct(pi, opcode, m_bytecode, instr) ) {
+                // it is not a jump ==> it is ret, return or throw
+                return VF_OK;
+            } else if( instr_is_switch(pi) ) {
+
+                Address next_target_adr = (instr & (~3) ) + 4;
+
+                //default target
+                Address target = instr + read_int32(m_bytecode + next_target_adr);
+                processSwitchTarget(target);
+
+                // in tableswitch instruction target offsets are stored with shift = 4,
+                // in lookupswitch with shift = 8
+                int shift = (opcode == OP_TABLESWITCH) ? 4 : 8;
+
+                // process conditional jump target
+                for (next_target_adr += 12;
+                    next_target_adr < instr + instr_len;
+                    next_target_adr += shift)
+                {
+                    target = instr + read_int32(m_bytecode + next_target_adr);
+                    processSwitchTarget(target);
+                }
+
+                return VF_OK;
+            } else {
+                assert( instr_is_regular(pi) );
+                instr += instr_len;
+            }
+
+        }
+
+        // control went out of method bounds
+        return error(VF_ErrorCodeEnd, "control went out of method bounds");
+    }
+
+    vf_Result vf_Context_5::verify_method(method_handler method) {
+        vf_Result tcr;
+
+        //nothing to verify
+        if( !method_get_code_length( method ) ) {
+            return VF_OK;
+        }
+
+        //load memory storage, read variable like max_stack, etc
+        init(method);
+
+        //////////////////////////// FIRST PASS /////////////////////////
+        pass = 1;
+        stack.push(0);
+
+        unsigned short idx;
+        unsigned short start_pc;
+        unsigned short end_pc;
+        unsigned short handler_pc;
+        unsigned short handler_cp_index;
+
+        for( 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 >= end_pc || end_pc > m_code_length ) {
+                return error(VF_ErrorHandler, "start_pc >= end_pc OR end_pc > code_length");
+            }
+            stack.push(handler_pc);
+        }
+
+        //we have different slightly rules for processing dead and live code
+        //e.g. it's not a problem if dead code runs out of the method
+        //but we still have to verify it for corrupted instructions to follow RI
+        dead_code_parsing = 0;
+        do {
+            while( !stack.is_empty() ) {
+                vf_Result tcr = parse(stack.pop());
+                if( tcr != VF_OK ) {
+                    return tcr;
+                }
+            }
+
+            dead_code_parsing = 1;
+
+            while( !dead_code_stack.is_empty() ) {
+                vf_Result tcr = parse(dead_code_stack.pop());
+                if( tcr != VF_OK ) {
+                    return tcr;
+                }
+            }
+        } while (!stack.is_empty());
+
+
+
+        for( idx = 0; idx < m_handlecount; idx++ ) {
+
+            method_get_exc_handler_info( m_method, idx, &start_pc, &end_pc,
+                &handler_pc, &handler_cp_index );
+
+            if( end_pc < m_code_length && props.isOperand(end_pc) || props.isOperand(start_pc) ) {
+                return error(VF_ErrorCodeEnd, "start_pc or end_pc are at the middle of an instruction");
+            }
+
+            SmConstant handler_type;
+            if( handler_cp_index ) {
+                if( !tpool.cpool_get_class(handler_cp_index, &handler_type) ||
+                    !tpool.mustbe_assignable(handler_type, tpool.sm_get_const_throwable()) )
+                {
+                    return error(VF_ErrorHandler, "incorrect constantpool entry");
+                }
+            } else {
+                handler_type = tpool.sm_get_const_throwable();
+            }
+
+            props.setMultiway(handler_pc);
+            createHandlerStackmap(handler_pc, handler_type);
+        }
+
+        //////////////////////////// SECOND PASS /////////////////////////
+        pass = 2;
+
+        stack.xPush(0);
+        while( !stack.is_empty() ) {
+            Address next;
+            short mark;
+
+            stack.xPop(&next, &mark);
+
+            if( !mark ) {
+                tcr = StartLinearDataflow(next);
+            } else {
+                assert(mark == MARK_SUBROUTINE_DONE);
+                tcr = SubroutineDone(next);
+            }
+
+            if( tcr != VF_OK ) {
+                return tcr;
+            }
+        }
+
+        return VF_OK;
+    }
+
+
+
+
+    vf_Result vf_Context_5::new_ret_vector_constraint(Address jsr_target) {
+        PropsHead *inpro = (PropsHead*)props.getInstrProps(jsr_target);
+        PropsHead *outpro = (PropsHead*)inpro->next;
+        assert(outpro->instr == 0xFFFF);
+
+        SubroutineData *subrdata = outpro->getSubrData(m_stack_start + m_max_stack);
+        subrdata->retCount++;
+
+        //if it is a first ret from the given subroutine (majority of the cases)
+        if( subrdata->retCount == 1 ) {
+            //remove newly appeared ret addresses: it might happen
+            //if non-top subroutine made a ret
+            StackmapHead* original = inpro->getStackmap();
+            unsigned i;
+
+            for( i = 0; i < m_stack_start + workmap->depth; i++ ) {
+                if( i < m_stack_start && !workmap->elements[i].isJsrModified() ) {
+                    //nothing new here
+                    continue;
+                }
+
+                SmConstant val = workmap->elements[i].getAnyPossibleValue();
+                if( val.isRetAddr() ) {
+                    //check if it's a newly appeared ret addfress
+
+                    // '-1' is twice below to exclude top of the stack. 
+                    // top of the stack contains ret address for the current subroutine
+                    // it also cleaned up if it's still there
+
+                    if( i < m_stack_start + original->depth - 1 && 
+                        original->elements[i].getAnyIncomingValue() == val ) 
+                    {
+                        //most likely: this ret address was there before
+                        continue;
+                    }
+
+                    //iterate thru original types and look for this ret address
+                    int found_in_original = 0;
+                    for( unsigned j = 0; j < m_stack_start + original->depth - 1; j++ ) {
+                        if( original->elements[j].getAnyIncomingValue() == val ) {
+                            found_in_original = 1;
+                            break;
+                        }
+                    }
+                    if( !found_in_original ) {
+                        //original types did not have this ret address
+                        workmap->elements[i] = _WorkmapElement(SM_BOGUS);
+                    }
+                }
+            }
+
+            //TODO make sure incoming was created as JSR transformation
+            tc_memcpy(outpro->getWorkmap(), workmap, sizeof(WorkmapHead) + sizeof(WorkmapElement) * (m_stack_start + workmap->depth));
+            return VF_OK;
+        }
+
+        return error(VF_ErrorStackDepth, "Multiple returns to single jsr");
+    }
+
+
+    void vf_Context_5::restore_workmap_after_jsr(Address jsr_target) {
+        PropsHead *inpro = (PropsHead*)props.getInstrProps(jsr_target);
+        PropsHead *outpro = (PropsHead*)inpro->next;
+        SubroutineData *subrdata = outpro->getSubrData(m_stack_start + m_max_stack);
+
+        if( subrdata->retCount ) {
+            assert( subrdata->retCount == 1 );
+            WorkmapHead* outcoming = outpro->getWorkmap();
+            workmap->depth = outcoming->depth;
+
+            unsigned i;
+            for( i = 0; i < m_stack_start; i++ ) {
+                if( outcoming->elements[i].isJsrModified() ) {
+                    workmap->elements[i] = outcoming->elements[i];
+                }
+            }
+            for( ; i < m_stack_start + workmap->depth; i++ ) {
+                workmap->elements[i] = outcoming->elements[i];
+            }    
+        }
+    }
+
+    vf_Result vf_Context_5::new_scalar_constraint(WorkmapElement *from, StackmapElement *to) {
+        assert(from->getAnyPossibleValue() != SM_NONE);
+
+        if( from->isJsrModified() ) {
+            //JSR overhead
+            to->setJsrModified();
+        }
+
+        if( !from->isVariable() ) {
+            SmConstant inc_val = from->getConst();
+            return add_incoming_value( inc_val, to );
+        } else {
+            GenericCnstr* gen = from->getVariable()->firstGenericCnstr();
+            while( gen ) {
+                if( gen->variable == to ) return VF_OK;
+                gen = gen->next();
+            }
+
+            IncomingType *inc = from->getVariable()->firstIncoming();
+            from->getVariable()->newGenericConstraint(&mem, to);
+
+            while( inc ) {
+                vf_Result vcr = add_incoming_value( inc->value, to );
+                if( vcr != VF_OK ) {
+                    return vcr;
+                }
+                inc = inc->next();
+            }
+            return VF_OK;
+        }
+    }
+
+    vf_Result vf_Context_5::add_incoming_value(SmConstant new_value, StackmapElement *destination) {
+        //check if the node already has such incoming value
+        IncomingType *inc = destination->firstIncoming();
+        while( inc ) {
+            if( new_value == inc->value  || inc->value == SM_BOGUS ) {
+                return VF_OK;
+            }
+            inc = inc->next();
+        }
+
+        if( new_value.isNonMergeable() && destination->firstIncoming() ) {
+            //uninit value merged to any different value is bogus
+            //ret address merged to any different value is bogus
+            //assert - incoming value exists is different - we've already checked that new_value is missing in the list of incoming values
+            new_value = SM_BOGUS;
+        }
+
+        //add incoming value if it does not have
+        Constraint* next = destination->firstOthers();
+        //TODO: optimize memory footprint for new_value == SM_BOGUS
+        destination->newIncomingType(&mem, new_value);
+
+        //check if it contradicts to expected types and further propagate
+        while( next ) {
+            switch (next->type) {
+            case CT_EXPECTED_TYPE:
+                if( !tpool.mustbe_assignable(new_value, next->value) ) return error(VF_ErrorUnknown, "unexpected type on stack or local variable");
+                break;
+            case CT_GENERIC: {
+                vf_Result vcr = add_incoming_value(new_value, next->variable);
+                if( vcr != VF_OK ) return vcr;
+                break;
+                             }
+            case CT_ARRAY2REF: {
+                vf_Result vcr = add_incoming_value( tpool.get_ref_from_array(new_value), next->variable);
+                if( vcr != VF_OK ) return vcr;
+                break;
+                               }
+            default:
+                assert(0);
+                return error(VF_ErrorInternal, "unreachable statement in add_incoming_value");
+            }
+            next = next->next();
+        }
+        return VF_OK;
+    }
+
+} // namespace CPVerifier

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

Propchange: harmony/enhanced/drlvm/trunk/vm/vmcore/src/verifier-3363/java5/context_5.cpp
            ('svn:executable' removed)