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;
}