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/26 07:22:17 UTC

svn commit: r641169 - in /harmony/enhanced/drlvm/trunk/vm/vmcore: include/environment.h include/jarfile_support.h src/class_support/classloader.cpp src/init/vm_init.cpp src/util/jarfile_support.cpp

Author: mcfirst
Date: Tue Mar 25 23:22:16 2008
New Revision: 641169

URL: http://svn.apache.org/viewvc?rev=641169&view=rev
Log:
Applying patch from HARMONY-5281 [drlvm][startup][performance][classloader] mapping bootstrap jars directly into memory. The option vm.map_bootstrap_jars is turned off by default.

Modified:
    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/src/class_support/classloader.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/environment.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/vmcore/include/environment.h?rev=641169&r1=641168&r2=641169&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/include/environment.h (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/include/environment.h Tue Mar 25 23:22:16 2008
@@ -94,6 +94,12 @@
     bool use_common_jar_cache;
 
     /**
+     * If set to true, jar files are mapped into memory instead of reading
+     * them from disk.
+     */
+    bool map_bootsrtap_jars;
+
+    /**
      * 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=641169&r1=641168&r2=641169&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/vmcore/include/jarfile_support.h (original)
+++ harmony/enhanced/drlvm/trunk/vm/vmcore/include/jarfile_support.h Tue Mar 25 23:22:16 2008
@@ -33,6 +33,7 @@
 #else
 #include <io.h>
 #endif
+#include "apr_mmap.h"
 
 #include "properties.h"
 #include "manifest.h"
@@ -209,31 +210,39 @@
     JarEntryCache* m_entries;
     bool m_ownCache;
     Manifest* m_manifest;
-    tl::MemoryPool pool;
+    tl::MemoryPool m_pool;
+    // handle of the jar file
+    int m_file_handle;
+    // associated lock
+    Lock_Manager m_lock;
+    // should jar support use mmap instead of open/read
+    bool m_use_mmap;
+    // apr pool to use with mmap
+    apr_pool_t* m_mappool;
+    // apr file object for mapping
+    apr_file_t* m_jarfile;
+    // memory location for jar
+    apr_mmap_t* m_mmap;
 
     // 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);
-    }
+        : m_name(NULL), m_entries(jec), m_ownCache(jec == NULL), m_manifest(NULL), m_file_handle(0),
+          m_use_mmap(false), m_mmap(NULL) {}
     ~JarFile() {
         if(m_ownCache)
             m_entries->~JarEntryCache();
         m_ownCache = false;
         m_entries = NULL;
-        if (jfh != 0) close(jfh);
-        jfh = 0;
+        if (m_file_handle != 0) close(m_file_handle);
+        m_file_handle = 0;
         if( m_manifest ) delete m_manifest;
         m_manifest = NULL;
     }
     // parses JAR file and stores its structure inside
-    bool Parse( const char* filename );
+    bool Parse( const char* filename, bool do_map );
     // returns entry cache (either shared or owned)
     JarEntryCache* GetCache() { return m_entries; }
     // returns if this JarFile owns entry cache it holds
@@ -241,6 +250,7 @@
     const JarEntry* Lookup( const char* je_name ) const {
         return m_entries->Lookup(je_name);
     }
+    bool ReadEntry(unsigned char* buf, long entry_offset, int entry_length);
     // returns manifest from parsed jar archive
     Manifest* GetManifest() { return m_manifest; }
     // returns JAR file name
@@ -250,10 +260,6 @@
     static JarFile* GetJar(int idx) {
         return m_jars[idx];
     }
-
-    // handle of the jar file
-    int jfh;
-    Lock_Manager lock;
 }; // class JarFile
 
 

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=641169&r1=641168&r2=641169&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 Tue Mar 25 23:22:16 2008
@@ -1182,7 +1182,8 @@
         void* mem_JarFile = apr_palloc(pool, sizeof(JarFile));
         element->m_jar = new (mem_JarFile) JarFile(jec);
 
-        if(element->m_jar && element->m_jar->Parse(new_path->bytes)) {
+        if(element->m_jar && element->m_jar->Parse(new_path->bytes, m_env->map_bootsrtap_jars))
+        {
             TRACE2("classloader.jar", "opened archive: " << new_path );
         }
     }

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=641169&r1=641168&r2=641169&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 Tue Mar 25 23:22:16 2008
@@ -842,6 +842,7 @@
     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->map_bootsrtap_jars = get_boolean_property("vm.map_bootstrap_jars", FALSE, 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=641169&r1=641168&r2=641169&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 Tue Mar 25 23:22:16 2008
@@ -54,19 +54,11 @@
 {
     // 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,
-    // read, etc may be confused when many threads operate on the same
-    // jar file
-    LMAutoUnlock lock(&jf->lock);
-
-    if( lseek( inFile, m_contentOffset, SEEK_SET ) == -1 ) return false;
 
     switch( m_method )
     {
     case JAR_FILE_STORED:
-        return ( read( inFile, content, m_sizeCompressed ) == m_sizeCompressed );
+        return jf->ReadEntry(content, m_contentOffset, m_sizeCompressed);
     case JAR_FILE_SHRUNK:
         printf( "Found SHRUNK content. No support as of yet.\n" );
         return false;
@@ -96,7 +88,7 @@
         {
             unsigned char* data = (unsigned char*)STD_MALLOC(m_sizeCompressed + 1);
             // FIXME: check that memory was allocated
-            if( read( inFile, data, m_sizeCompressed ) < m_sizeCompressed ) {
+            if(!jf->ReadEntry(data, m_contentOffset, m_sizeCompressed)) {
                 STD_FREE(data);
                 return false;
             }
@@ -121,6 +113,8 @@
             infRes = inflate( &inf, Z_FINISH );
             STD_FREE(data);
             if( infRes != Z_STREAM_END ) {
+                // FIXME: this is broken stream actually
+                // and breaking will result in "Invalid class magic" later on
                 break;
             }
             infRes = inflateEnd( &inf );
@@ -145,31 +139,60 @@
 #pragma warning( disable: 4786 ) // identifier was truncated to 255 characters in the browser information
 #endif
 
-bool JarFile::Parse( const char* fileName )
+bool JarFile::Parse( const char* fileName, bool do_map )
 {
-    int flags = O_RDONLY;
-#ifndef PLATFORM_POSIX
-    flags |= O_BINARY;
-#endif
-    int fp = open( fileName, flags, 0 );
-    jfh = fp;
-    if( fp == -1 ) return false;
+    int fp;
+    long off;
+    unsigned char* buf;
+    unsigned long fsize = 0;
 
+    m_use_mmap = do_map;
     m_name = fileName;
 
-    struct stat fs;
-    if(stat(fileName, &fs) == -1) return false;
-    unsigned long fsize = fs.st_size;
+    if(!m_use_mmap) {
+        int flags = O_RDONLY;
+#ifndef PLATFORM_POSIX
+        flags |= O_BINARY;
+#endif
+        fp = open( fileName, flags, 0 );
+        if( fp == -1 ) return false;
+
+        m_file_handle = fp;
 
-    m_jars.push_back(this);
+        struct stat fs;
+        if(stat(fileName, &fs) == -1) return false;
+        fsize = fs.st_size;
+
+        int cd_size = fsize < 67000 ? fsize : 67000;
+        lseek(fp, -cd_size, SEEK_END);
+        buf = (unsigned char*)STD_ALLOCA(cd_size);
+        off = read(fp, buf, cd_size) - 22; // 22 - EOD size
+    } else {
+        apr_pool_create(&m_mappool, NULL);
+
+        apr_status_t status =
+            apr_file_open(&m_jarfile, fileName, APR_READ, APR_OS_DEFAULT, m_mappool);
+        assert(!status);
+
+        apr_off_t _fsize = 0;
+        status = apr_file_seek(m_jarfile, APR_END, &_fsize);
+        assert(!status);
+        fsize = (unsigned long)_fsize;
+
+        status = apr_mmap_create(&m_mmap, m_jarfile, 0, (apr_size_t)fsize,
+            APR_MMAP_READ, m_mappool);
+        assert(!status);
+
+        int cd_size = fsize < 67000 ? fsize : 67000;
+        off = cd_size - 22;
+        buf = (unsigned char*)m_mmap->mm + fsize - cd_size;
+    }
 
-    int cd_size = fsize < 67000 ? fsize : 67000;
-    lseek(fp, -cd_size, SEEK_END);
-    unsigned char *buf = (unsigned char *)STD_ALLOCA(cd_size);
-    long off = read(fp, buf, cd_size) - 22; // 22 - EOD size
     long offsetCD; // start of the Central Dir
     int number; // number of entries
 
+    m_jars.push_back(this);
+
     JarEntry je;
     je.m_jarFileIdx = (int)(m_jars.size() - 1);
 
@@ -186,18 +209,19 @@
             return false;
     }
 
-    m_manifest = new Manifest();
-    if(!m_manifest) return false;
-
     if(m_ownCache) {
-        void* jec_mem = pool.alloc(sizeof(JarEntryCache));
+        void* jec_mem = m_pool.alloc(sizeof(JarEntryCache));
         m_entries = new (jec_mem) JarEntryCache();
     }
 
-    lseek(fp, offsetCD, SEEK_SET);
+    if(!m_use_mmap) {
+        lseek(fp, offsetCD, SEEK_SET);
 
-    buf = (unsigned char *)STD_MALLOC(fsize - offsetCD);
-    fsize = read(fp, buf, fsize - offsetCD);
+        buf = (unsigned char *)STD_MALLOC(fsize - offsetCD);
+        fsize = read(fp, buf, fsize - offsetCD);
+    } else {
+        buf = (unsigned char*)m_mmap->mm + offsetCD;
+    }
 
     off = 0;
     for (int i = 0; i < number; i++){
@@ -205,14 +229,15 @@
             return false;
 
         je.ConstructFixed(buf + off);
-        je.m_fileName = (char *)pool.alloc(je.m_nameLength + 1);
+        je.m_fileName = (char *)m_pool.alloc(je.m_nameLength + 1);
         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;
         if(!strcmp(je.m_fileName, "META-INF/MANIFEST.MF")) {
             // parse manifest
-            if(!m_manifest->Parse(&je)) return false;
-            if(!(*m_manifest)) {
+            m_manifest = new Manifest();
+            if(!m_manifest) return false;
+            if(!m_manifest->Parse(&je) || !(*m_manifest)) {
                 delete m_manifest;
                 return false;
             }
@@ -225,7 +250,29 @@
         }
         off += JAR_DIRECTORYENTRY_LEN + je.m_nameLength + je.m_extraLength;
     }
-    STD_FREE(buf);
+    if(!m_use_mmap) {
+        STD_FREE(buf);
+    }
+
+    return true;
+}
+
+
+bool JarFile::ReadEntry(unsigned char* buf, long entry_offset, int entry_length)
+{
+    if(!m_use_mmap) {
+        // gregory - It is necessary to lock per jar file because the file
+        // handle is global to all threads, and file operations like seek,
+        // read, etc may be confused when many threads operate on the same
+        // jar file
+        LMAutoUnlock llock(&m_lock);
+
+        if(lseek(m_file_handle, entry_offset, SEEK_SET) == -1) return false;
+
+        if(read(m_file_handle, buf, entry_length) < entry_length) return false;
+    } else {
+        memcpy(buf, (char*)m_mmap->mm + entry_offset, entry_length*sizeof(char));
+    }
 
     return true;
 }