You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by mc...@apache.org on 2008/03/05 17:56:30 UTC

svn commit: r633931 - in /harmony/enhanced/drlvm/trunk/vm/vmcore: include/ src/class_support/ src/init/ src/util/

Author: mcfirst
Date: Wed Mar  5 08:56:26 2008
New Revision: 633931

URL: http://svn.apache.org/viewvc?rev=633931&view=rev
Log:
Applying patch from HARMONY-5524 [drlvm][performance] Bootstrap class loader should use single entry cache for sequential jars in boot class path

Modified:
    harmony/enhanced/drlvm/trunk/vm/vmcore/include/Class.h
    harmony/enhanced/drlvm/trunk/vm/vmcore/include/environment.h
    harmony/enhanced/drlvm/trunk/vm/vmcore/include/jarfile_support.h
    harmony/enhanced/drlvm/trunk/vm/vmcore/include/jarfile_util.h
    harmony/enhanced/drlvm/trunk/vm/vmcore/include/manifest.h
    harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/Class.cpp
    harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/classloader.cpp
    harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/manifest.cpp
    harmony/enhanced/drlvm/trunk/vm/vmcore/src/init/vm_init.cpp
    harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/jarfile_support.cpp

Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/include/Class.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/include/Class.h?rev=633931&r1=633930&r2=633931&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/include/Class.h (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/include/Class.h Wed Mar  5 08:56:26 2008
@@ -826,7 +826,7 @@
     int m_is_suitable_for_fast_instanceof;
 
     // string name of file from which this class has been loaded
-    const String* m_class_file_name;
+    const char* m_class_file_name;
     // string name of source java file from which this class has been compiled
     const String* m_src_file_name;
 
@@ -1538,7 +1538,7 @@
      * or to be removed altogether, if possible.
      * Sets the name of a file from which the given class has been loaded.
      * @param[in] cf_name - a class-file name*/
-    void set_class_file_name(const String* cf_name) {
+    void set_class_file_name(const char* cf_name) {
         assert(cf_name);
         m_class_file_name = cf_name;
     }

Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/include/environment.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/include/environment.h?rev=633931&r1=633930&r2=633931&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/include/environment.h (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/include/environment.h Wed Mar  5 08:56:26 2008
@@ -90,6 +90,13 @@
     Lock_Manager *p_suspend_lock;
 
     /**
+     * If set to true, DLRVM will store JARs which are adjacent in boot class path
+     * into single jar entry cache. This will optimize lookups on class loading
+     * with bootstrap class loader.
+     */
+    bool use_common_jar_cache;
+
+    /**
      * If set to true by the <code>-compact_fields</code> command-line option,
      * the VM will not pad out fields of less than 32 bits to four bytes.
      * However, fields will still be aligned to a natural boundary,

Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/include/jarfile_support.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/include/jarfile_support.h?rev=633931&r1=633930&r2=633931&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/include/jarfile_support.h (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/include/jarfile_support.h Wed Mar  5 08:56:26 2008
@@ -94,6 +94,8 @@
 
 typedef long JarCompressedOffset;
 
+class JarFile;
+
 class JarEntry
 {
     unsigned short m_version;
@@ -109,7 +111,6 @@
 
 protected:
     JarCompressedOffset m_contentOffset;
-//    std::string m_jarFileName;
     int m_jarFileIdx;
 
 public:
@@ -121,9 +122,11 @@
     // returns decompressed content in provided buffer;
     // buffer must have at least GetContentSize() bytes length
     // NB! upon erroneous return from GetContent user cannot rely on buffer content
-    bool GetContent( unsigned char* content, JarFile *jf ) const;
+    bool GetContent(unsigned char* content) const;
     // construct fixed part of JarEntryHeader class from input stream
     void ConstructFixed( const unsigned char* stream );
+    // returns index of containing jar file
+    int GetJarIndex() const { return m_jarFileIdx; }
     // verify that "stream" starts with JAR_DIRECTORYENTRY_MAGIC signature
     static bool IsDirEntryMagic( const unsigned char* stream ){
         return (0x01 == stream[0]) && (0x02 == stream[1]);
@@ -143,34 +146,14 @@
 
 protected:
     friend class JarFile;
+    friend class JarEntryCache;
 }; // class JarEntry
 
 
-class JarFile
-{
-    int m_jarFileIdx;
+class JarEntryCache {
+private:
     std::multimap<int, JarEntry> m_entries;
-    Manifest* m_manifest;
-    tl::MemoryPool pool;
 
-    // list of the jar files
-    static std::vector<std::string> m_jars;
-
-public:
-    JarFile() : m_manifest(NULL), jfh(0) {}
-    JarFile( const JarFile& jf ) : jfh(0) {
-        m_jarFileIdx = jf.m_jarFileIdx;
-        m_entries = jf.m_entries;
-        m_manifest = new Manifest( &jf );
-    }
-    ~JarFile() {
-        if (jfh != 0) close(jfh);
-        jfh = 0;
-        if( m_manifest ) delete m_manifest;
-        m_manifest = NULL;
-    }
-    // parses JAR file and stores its structure inside
-    bool Parse( const char* filename );
     // get string hash value
     inline int GetHashValue( const char* je_name ) const{
         // hash fuction is taken from String_Pool class
@@ -188,7 +171,13 @@
         hash = (h1 + (h2 << 8)) & 0x7fffffff;
         return hash;
     }
-    // looks up JAR entry in stored jar structure
+
+public:
+    // inserts new entry in this cache
+    void Insert(JarEntry& je) {
+        m_entries.insert(std::make_pair(GetHashValue(je.m_fileName), je));
+    }
+    // looks up JAR entry in this cache
     const JarEntry* Lookup( const char* je_name ) const {
         const int hash = GetHashValue(je_name);
         std::multimap<int, JarEntry>::const_iterator it = m_entries.find(hash);
@@ -211,10 +200,56 @@
 
         return NULL;
     }
+};
+
+
+class JarFile
+{
+    const char* m_name;
+    JarEntryCache* m_entries;
+    bool m_ownCache;
+    Manifest* m_manifest;
+    tl::MemoryPool pool;
+
+    // list of the jar files
+    static std::vector<JarFile*> m_jars;
+
+public:
+    JarFile(JarEntryCache* jec = NULL)
+        : m_name(NULL), m_entries(jec), m_ownCache(jec == NULL), m_manifest(NULL), jfh(0) {}
+    JarFile( const JarFile& jf ) : jfh(0) {
+        m_name = jf.m_name;
+        m_entries = jf.m_entries;
+        m_manifest = new Manifest(jf.m_manifest);
+    }
+    ~JarFile() {
+        if(m_ownCache)
+            m_entries->~JarEntryCache();
+        m_ownCache = false;
+        m_entries = NULL;
+        if (jfh != 0) close(jfh);
+        jfh = 0;
+        if( m_manifest ) delete m_manifest;
+        m_manifest = NULL;
+    }
+    // parses JAR file and stores its structure inside
+    bool Parse( const char* filename );
+    // returns entry cache (either shared or owned)
+    JarEntryCache* GetCache() { return m_entries; }
+    // returns if this JarFile owns entry cache it holds
+    bool HasSharedCache() { return !m_ownCache; }
+    const JarEntry* Lookup( const char* je_name ) const {
+        return m_entries->Lookup(je_name);
+    }
     // returns manifest from parsed jar archive
-    Manifest* Get_Manifest() { return m_manifest; }
+    Manifest* GetManifest() { return m_manifest; }
     // returns JAR file name
-    const char* GetName() { return m_jars[m_jarFileIdx].c_str(); }
+    const char* GetName() { return m_name; }
+
+    // Return jar from jars array
+    static JarFile* GetJar(int idx) {
+        return m_jars[idx];
+    }
 
     // handle of the jar file
     int jfh;

Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/include/jarfile_util.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/include/jarfile_util.h?rev=633931&r1=633930&r2=633931&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/include/jarfile_util.h (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/include/jarfile_util.h Wed Mar  5 08:56:26 2008
@@ -62,7 +62,7 @@
     assert(jarfl);
 
     // get archive manifest
-    Manifest *manifest = jarfl->Get_Manifest();
+    Manifest *manifest = jarfl->GetManifest();
     if(!manifest) {
         return NULL;
     }

Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/include/manifest.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/include/manifest.h?rev=633931&r1=633930&r2=633931&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/include/manifest.h (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/include/manifest.h Wed Mar  5 08:56:26 2008
@@ -23,6 +23,7 @@
 
 #include "properties.h"
 
+class JarEntry;
 class JarFile;
 
 class Manifest
@@ -30,9 +31,11 @@
     Properties m_main;
     bool m_parsed;
 public:
-    Manifest( const JarFile* jf );
+    Manifest() {}
+    Manifest(const Manifest* mnf);
     ~Manifest();
 
+    bool Parse(const JarEntry* mje);
     Properties* GetMainProperties() { return &m_main; }
     bool operator! () { return !m_parsed; }
 

Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/Class.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/Class.cpp?rev=633931&r1=633930&r2=633931&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/Class.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/Class.cpp Wed Mar  5 08:56:26 2008
@@ -105,7 +105,8 @@
 
     m_const_pool.init();
 
-    m_class_file_name = m_src_file_name = NULL;
+    m_class_file_name = NULL;
+    m_src_file_name = NULL;
 
     m_state = ST_Start;
 

Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/classloader.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/classloader.cpp?rev=633931&r1=633930&r2=633931&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/classloader.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/classloader.cpp Wed Mar  5 08:56:26 2008
@@ -1166,29 +1166,27 @@
         return;
     }
 
-    // allocate and set a new bootsclasspath element
     element = (BCPElement*)apr_palloc(pool, sizeof(BCPElement) );
     element->m_path = new_path;
     element->m_next = NULL;
+    element->m_isJarFile = file_is_archive(new_path->bytes);
+    if(element->m_isJarFile) {
+        JarEntryCache* jec = NULL;
+        if(m_env->use_common_jar_cache
+            &&m_BCPElements.m_last
+            && m_BCPElements.m_last->m_isJarFile)
+        {
+            // if previous boot class path element is jar, reuse the same cache
+            jec = m_BCPElements.m_last->m_jar->GetCache();
+        }
+        void* mem_JarFile = apr_palloc(pool, sizeof(JarFile));
+        element->m_jar = new (mem_JarFile) JarFile(jec);
 
-    // check if it is a archive file
-    if( file_is_archive(new_path->bytes) ) {
-        // create and parse a new archive file structure
-        element->m_isJarFile = true;
-        void* mem_JarFile = apr_palloc(pool, sizeof(JarFile) );
-        element->m_jar = new (mem_JarFile) JarFile();
-        if( element->m_jar && element->m_jar->Parse(new_path->bytes) ) {
+        if(element->m_jar && element->m_jar->Parse(new_path->bytes)) {
             TRACE2("classloader.jar", "opened archive: " << new_path );
-        } else {
-            if( element->m_jar ) {
-                element->m_jar->~JarFile();
-            }
-            return;
         }
-    } else {
-        element->m_isJarFile = false;
     }
-    
+
     // insert element into collection
     if( NULL == m_BCPElements.m_first ) {
         m_BCPElements.m_first = element;
@@ -2059,7 +2057,7 @@
     Class* clss = DefineClass(m_env, class_name->bytes, buf, 0,
         (unsigned)buf_len);
     if(clss) {
-        clss->set_class_file_name(m_env->string_pool.lookup(full_name));
+        clss->set_class_file_name(m_env->string_pool.lookup(full_name)->bytes);
     }
     STD_FREE(buf);
     apr_pool_destroy(local_pool);
@@ -2072,6 +2070,12 @@
 {
     assert(!exn_raised());
 
+    if(jar_file->HasSharedCache()) {
+        // class was looked up earlier
+        *not_found = true;
+        return NULL;
+    }
+
     // find archive entry in archive file
     *not_found = false;
     const JarEntry *entry = jar_file->Lookup(class_name_in_jar);
@@ -2086,7 +2090,7 @@
     unsigned char* buffer = (unsigned char*)STD_MALLOC(size);
     // FIXME: check that memory was allocated
 
-    if(!entry->GetContent(buffer, jar_file)) {
+    if(!entry->GetContent(buffer)) {
         // cannot unpack entry
         *not_found = true;
         STD_FREE(buffer);
@@ -2094,13 +2098,13 @@
     }
 
     // create package information with jar source
-    ProvidePackage(m_env, class_name, jar_file->GetName());
+    ProvidePackage(m_env, class_name, JarFile::GetJar(entry->GetJarIndex())->GetName());
 
     // define class
     Class *clss = DefineClass(m_env, class_name->bytes, buffer, 0, size, NULL);
     if(clss) {
         // set class file name
-        clss->set_class_file_name(m_env->string_pool.lookup(jar_file->GetName()));
+        clss->set_class_file_name(JarFile::GetJar(entry->GetJarIndex())->GetName());
     }
 
     STD_FREE(buffer);

Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/manifest.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/manifest.cpp?rev=633931&r1=633930&r2=633931&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/manifest.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/class_support/manifest.cpp Wed Mar  5 08:56:26 2008
@@ -76,32 +76,25 @@
     return (long)(dst - manifest);
 }
 
-Manifest::Manifest( const JarFile* jf )
+
+bool Manifest::Parse(const JarEntry* manifestJe)
 {
+    assert(manifestJe != NULL);
     m_parsed = false;
-    const JarEntry* manifestJe;
     char* manifest;
     long manifestSize;
-    
-    manifestJe = jf->Lookup( "META-INF/MANIFEST.MF" );
-    if( !manifestJe ) {
-        // no manifest in JAR
-        m_parsed = true;
-        return;
-    }
-    
+
     manifestSize = manifestJe->GetContentSize();
     if( !manifestSize ) {
-        return;
+        return false;
     }
     manifest = new char[manifestSize + 1];
     if( !manifest ) {
-        return;
+        return false;
     }
-    if( !manifestJe->GetContent( reinterpret_cast<unsigned char*>(manifest),
-            const_cast<JarFile *>(jf) ) ) {
+    if(!manifestJe->GetContent(reinterpret_cast<unsigned char*>(manifest))) {
         delete[] manifest;
-        return;
+        return false;
     }
     manifest[manifestSize] = '\0';
 
@@ -169,6 +162,7 @@
     delete[] manifest;
 
     m_parsed = true;
+    return true;
 }
 
 

Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/src/init/vm_init.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/init/vm_init.cpp?rev=633931&r1=633930&r2=633931&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/init/vm_init.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/init/vm_init.cpp Wed Mar  5 08:56:26 2008
@@ -761,6 +761,7 @@
     // see Global_Env::Global_Env for defaults
     vm_env->sort_fields = get_boolean_property("vm.sort_fields", vm_env->sort_fields, VM_PROPERTIES);
     vm_env->compact_fields = get_boolean_property("vm.compact_fields", vm_env->compact_fields, VM_PROPERTIES);
+    vm_env->use_common_jar_cache = get_boolean_property("vm.common_jar_cache", TRUE, VM_PROPERTIES);
 
     vm_env->init_pools();
 

Modified: harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/jarfile_support.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/jarfile_support.cpp?rev=633931&r1=633930&r2=633931&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/jarfile_support.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/src/util/jarfile_support.cpp Wed Mar  5 08:56:26 2008
@@ -46,11 +46,14 @@
         ((unsigned int)stream[44]<<16) + ((unsigned int)stream[45]<<24);
 }
 
-std::vector<std::string> JarFile::m_jars = std::vector<std::string>();
 
-bool JarEntry::GetContent( unsigned char* content, JarFile *jf ) const
+std::vector<JarFile*> JarFile::m_jars = std::vector<JarFile*>();
+
+
+bool JarEntry::GetContent(unsigned char* content) const
 {
     // length of content should be enough for storing m_size_uncompressed bytes
+    JarFile* jf = JarFile::GetJar(m_jarFileIdx);
     int inFile = jf->jfh;
     // gregory - It is necessary to lock per jar file because the file
     // handle is global to all threads, and file operations like seek,
@@ -152,14 +155,14 @@
     jfh = fp;
     if( fp == -1 ) return false;
 
-    m_jars.push_back(fileName);
-    JarEntry je;
-    m_jarFileIdx = je.m_jarFileIdx = (int)(m_jars.size() - 1);
+    m_name = fileName;
 
     struct stat fs;
     if(stat(fileName, &fs) == -1) return false;
     unsigned long fsize = fs.st_size;
 
+    m_jars.push_back(this);
+
     int cd_size = fsize < 67000 ? fsize : 67000;
     lseek(fp, -cd_size, SEEK_END);
     unsigned char *buf = (unsigned char *)STD_ALLOCA(cd_size);
@@ -167,6 +170,9 @@
     long offsetCD; // start of the Central Dir
     int number; // number of entries
 
+    JarEntry je;
+    je.m_jarFileIdx = (int)(m_jars.size() - 1);
+
     while (1){
         if (je.IsPK(buf + off)){
             if (je.IsEODMagic(buf + off + 2)){
@@ -180,6 +186,14 @@
             return false;
     }
 
+    m_manifest = new Manifest();
+    if(!m_manifest) return false;
+
+    if(m_ownCache) {
+        void* jec_mem = pool.alloc(sizeof(JarEntryCache));
+        m_entries = new (jec_mem) JarEntryCache();
+    }
+
     lseek(fp, offsetCD, SEEK_SET);
 
     buf = (unsigned char *)STD_MALLOC(fsize - offsetCD);
@@ -195,18 +209,23 @@
         strncpy(je.m_fileName, (const char *)buf + off + JAR_DIRECTORYENTRY_LEN, je.m_nameLength );
         je.m_fileName[je.m_nameLength] = '\0';
         je.m_contentOffset = je.m_relOffset + JarEntry::sizeFixed + je.m_nameLength + je.m_extraLength;
-        m_entries.insert(make_pair(GetHashValue(je.m_fileName), je));
+        if(!strcmp(je.m_fileName, "META-INF/MANIFEST.MF")) {
+            // parse manifest
+            if(!m_manifest->Parse(&je)) return false;
+            if(!(*m_manifest)) {
+                delete m_manifest;
+                return false;
+            }
+        } else {
+            // Insertion in common cache preserves the order of inserted
+            // elements with the same hash value, so lookup will return
+            // the first occurrence. Although more memory is spent here,
+            // we do not need to lookup on each entry.
+            m_entries->Insert(je);
+        }
         off += JAR_DIRECTORYENTRY_LEN + je.m_nameLength + je.m_extraLength;
     }
     STD_FREE(buf);
-
-    // read and parse manifest from archive
-    m_manifest = new Manifest( this );
-    if( !m_manifest ) return false;
-    if( !(*m_manifest) ) {
-        delete m_manifest;
-        return false;
-    }
 
     return true;
 }