jdk/src/java.base/share/native/libjimage/imageFile.cpp
changeset 36511 9d0388c6b336
parent 35784 ddeed53a1c5a
child 39759 427916042881
--- a/jdk/src/java.base/share/native/libjimage/imageFile.cpp	Tue Mar 15 13:48:26 2016 -0700
+++ b/jdk/src/java.base/share/native/libjimage/imageFile.cpp	Thu Mar 17 19:04:16 2016 +0000
@@ -41,7 +41,7 @@
 #include "osSupport.hpp"
 
 // Map the full jimage, only with 64 bit addressing.
-bool MemoryMapImage = sizeof(void *) == 8;
+bool ImageFileReader::memory_map_image = sizeof(void *) == 8;
 
 #ifdef WIN32
 const char FileSeparator = '\\';
@@ -144,142 +144,69 @@
 }
 
 // ImageModuleData constructor maps out sub-tables for faster access.
-ImageModuleData::ImageModuleData(const ImageFileReader* image_file,
-                const char* module_data_name) :
+ImageModuleData::ImageModuleData(const ImageFileReader* image_file) :
         _image_file(image_file),
-        _endian(image_file->endian()),
-        _strings(image_file->get_strings()) {
-    // Retrieve the resource containing the module data for the image file.
-    ImageLocation location;
-    bool found = image_file->find_location(module_data_name, location);
-    if (found) {
-        u8 data_size = location.get_attribute(ImageLocation::ATTRIBUTE_UNCOMPRESSED);
-        _data = new u1[(size_t)data_size];
-        assert(_data != NULL && "allocation failed");
-        _image_file->get_resource(location, _data);
-        // Map out the header.
-        _header = (Header*)_data;
-        // Get the package to module entry count.
-        u4 ptm_count = _header->ptm_count(_endian);
-        // Get the module to package entry count.
-        u4 mtp_count = _header->mtp_count(_endian);
-        // Compute the offset of the package to module perfect hash redirect.
-        u4 ptm_redirect_offset = sizeof(Header);
-        // Compute the offset of the package to module data.
-        u4 ptm_data_offset = ptm_redirect_offset + ptm_count * sizeof(s4);
-        // Compute the offset of the module to package perfect hash redirect.
-        u4 mtp_redirect_offset = ptm_data_offset + ptm_count * sizeof(PTMData);
-        // Compute the offset of the module to package data.
-        u4 mtp_data_offset = mtp_redirect_offset + mtp_count * sizeof(s4);
-        // Compute the offset of the module to package tables.
-        u4 mtp_packages_offset = mtp_data_offset + mtp_count * sizeof(MTPData);
-        // Compute the address of the package to module perfect hash redirect.
-        _ptm_redirect = (s4*)(_data + ptm_redirect_offset);
-        // Compute the address of the package to module data.
-        _ptm_data = (PTMData*)(_data + ptm_data_offset);
-        // Compute the address of the module to package perfect hash redirect.
-        _mtp_redirect = (s4*)(_data + mtp_redirect_offset);
-        // Compute the address of the module to package data.
-        _mtp_data = (MTPData*)(_data + mtp_data_offset);
-        // Compute the address of the module to package tables.
-        _mtp_packages = (s4*)(_data + mtp_packages_offset);
-    } else {
-        // No module data present.
-        _data = NULL;
-        _header = NULL;
-        _ptm_redirect = NULL;
-        _ptm_data = NULL;
-        _mtp_redirect = NULL;
-        _mtp_data = NULL;
-        _mtp_packages = NULL;
-    }
+        _endian(image_file->endian()) {
 }
 
 // Release module data resource.
 ImageModuleData::~ImageModuleData() {
-    if (_data) {
-        delete[] _data;
-    }
 }
 
-// Return the name of the module data resource.  Ex. "./lib/modules/file.jimage"
-// yields "file.jdata"
-void ImageModuleData::module_data_name(char* buffer, const char* image_file_name) {
-    // Locate the last slash in the file name path.
-    const char* slash = strrchr(image_file_name, FileSeparator);
-    // Trim the path to name and extension.
-    const char* name = slash ? slash + 1 : (char *)image_file_name;
-    // Locate the extension period.
-    const char* dot = strrchr(name, '.');
-    assert(dot && "missing extension on jimage name");
-    // Trim to only base name.
-    int length = (int)(dot - name);
-    strncpy(buffer, name, length);
-    buffer[length] = '\0';
-    // Append extension.
-    strcat(buffer, ".jdata");
-}
 
 // Return the module in which a package resides.    Returns NULL if not found.
 const char* ImageModuleData::package_to_module(const char* package_name) {
-    // Test files may contain no module data.
-    if (_data != NULL) {
-        // Search the package to module table.
-        s4 index = ImageStrings::find(_endian, package_name, _ptm_redirect,
-                                      _header->ptm_count(_endian));
-        // If entry is found.
-        if (index != ImageStrings::NOT_FOUND) {
-            // Retrieve the package to module entry.
-            PTMData* data = _ptm_data + index;
-            // Verify that it is the correct data.
-            if (strcmp(package_name, get_string(data->name_offset(_endian))) != 0) {
-                return NULL;
-            }
-            // Return the module name.
-            return get_string(data->module_name_offset(_endian));
-        }
+    // replace all '/' by '.'
+    char* replaced = new char[(int) strlen(package_name) + 1];
+    assert(replaced != NULL && "allocation failed");
+    int i;
+    for (i = 0; package_name[i] != '\0'; i++) {
+      replaced[i] = package_name[i] == '/' ? '.' : package_name[i];
     }
-    return NULL;
-}
+    replaced[i] = '\0';
+
+    // build path /packages/<package_name>
+    const char* radical = "/packages/";
+    char* path = new char[(int) strlen(radical) + (int) strlen(package_name) + 1];
+    assert(path != NULL && "allocation failed");
+    strcpy(path, radical);
+    strcat(path, replaced);
+    delete[] replaced;
 
-// Returns all the package names in a module in a NULL terminated array.
-// Returns NULL if module not found.
-const char** ImageModuleData::module_to_packages(const char* module_name) {
-    // Test files may contain no module data.
-    if (_data != NULL) {
-        // Search the module to package table.
-        s4 index = ImageStrings::find(_endian, module_name, _mtp_redirect,
-                                      _header->mtp_count(_endian));
-        // If entry is found.
-        if (index != ImageStrings::NOT_FOUND) {
-            // Retrieve the module to package entry.
-            MTPData* data = _mtp_data + index;
-            // Verify that it is the correct data.
-            if (strcmp(module_name, get_string(data->name_offset(_endian))) != 0) {
-                return NULL;
-            }
-            // Construct an array of all the package entries.
-            u4 count = data->package_count(_endian);
-            const char** packages = new const char*[count + 1];
-            assert(packages != NULL && "allocation failed");
-            s4 package_offset = data->package_offset(_endian);
-            for (u4 i = 0; i < count; i++) {
-                u4 package_name_offset = mtp_package(package_offset + i);
-                const char* package_name = get_string(package_name_offset);
-                packages[i] = package_name;
-            }
-            packages[count] = NULL;
-            return packages;
+    // retrieve package location
+    ImageLocation location;
+    bool found = _image_file->find_location(path, location);
+    if (!found) {
+        delete[] path;
+        return NULL;
+    }
+
+    // retrieve offsets to module name
+    int size = (int)location.get_attribute(ImageLocation::ATTRIBUTE_UNCOMPRESSED);
+    u1* content = new u1[size];
+    assert(content != NULL && "allocation failed");
+    _image_file->get_resource(location, content);
+    u1* ptr = content;
+    // sequence of sizeof(8) isEmpty|offset. Use the first module that is not empty.
+    u4 offset = 0;
+    for (i = 0; i < size; i+=8) {
+        u4 isEmpty = _endian->get(*((u4*)ptr));
+        ptr += 4;
+        if (!isEmpty) {
+            offset = _endian->get(*((u4*)ptr));
+            break;
         }
+        ptr += 4;
     }
-    return NULL;
+    delete[] content;
+    return _image_file->get_strings().get(offset);
 }
 
 // Manage a table of open image files.  This table allows multiple access points
 // to share an open image.
 ImageFileReaderTable::ImageFileReaderTable() : _count(0), _max(_growth) {
     _table = new ImageFileReader*[_max];
-    assert( _table != NULL && "allocation failed");
+    assert(_table != NULL && "allocation failed");
 }
 
 ImageFileReaderTable::~ImageFileReaderTable() {
@@ -326,26 +253,34 @@
 
 SimpleCriticalSection _reader_table_lock;
 
+// Locate an image if file already open.
+ImageFileReader* ImageFileReader::find_image(const char* name) {
+    // Lock out _reader_table.
+    SimpleCriticalSectionLock cs(&_reader_table_lock);
+    // Search for an exist image file.
+    for (u4 i = 0; i < _reader_table.count(); i++) {
+        // Retrieve table entry.
+        ImageFileReader* reader = _reader_table.get(i);
+        // If name matches, then reuse (bump up use count.)
+        assert(reader->name() != NULL && "reader->name must not be null");
+        if (strcmp(reader->name(), name) == 0) {
+            reader->inc_use();
+            return reader;
+        }
+    }
+
+    return NULL;
+}
+
 // Open an image file, reuse structure if file already open.
 ImageFileReader* ImageFileReader::open(const char* name, bool big_endian) {
-    {
-        // Lock out _reader_table.
-        SimpleCriticalSectionLock cs(&_reader_table_lock);
-        // Search for an exist image file.
-        for (u4 i = 0; i < _reader_table.count(); i++) {
-            // Retrieve table entry.
-            ImageFileReader* reader = _reader_table.get(i);
-            // If name matches, then reuse (bump up use count.)
-            assert(reader->name() != NULL && "reader->name must not be null");
-            if (strcmp(reader->name(), name) == 0) {
-                reader->inc_use();
-                return reader;
-            }
-        }
-    } // Unlock the mutex
+    ImageFileReader* reader = find_image(name);
+    if (reader != NULL) {
+        return reader;
+    }
 
     // Need a new image reader.
-    ImageFileReader* reader = new ImageFileReader(name, big_endian);
+    reader = new ImageFileReader(name, big_endian);
     if (reader == NULL || !reader->open()) {
         // Failed to open.
         delete reader;
@@ -385,21 +320,21 @@
 }
 
 // Return an id for the specifed ImageFileReader.
-u8 ImageFileReader::readerToID(ImageFileReader *reader) {
+u8 ImageFileReader::reader_to_ID(ImageFileReader *reader) {
     // ID is just the cloaked reader address.
     return (u8)reader;
 }
 
 // Validate the image id.
-bool ImageFileReader::idCheck(u8 id) {
+bool ImageFileReader::id_check(u8 id) {
     // Make sure the ID is a managed (_reader_table) reader.
     SimpleCriticalSectionLock cs(&_reader_table_lock);
     return _reader_table.contains((ImageFileReader*)id);
 }
 
 // Return an id for the specifed ImageFileReader.
-ImageFileReader* ImageFileReader::idToReader(u8 id) {
-    assert(idCheck(id) && "invalid image id");
+ImageFileReader* ImageFileReader::id_to_reader(u8 id) {
+    assert(id_check(id) && "invalid image id");
     return (ImageFileReader*)id;
 }
 
@@ -429,8 +364,6 @@
 
 // Open image file for read access.
 bool ImageFileReader::open() {
-    char buffer[IMAGE_MAX_PATH];
-
     // If file exists open for reading.
     _fd = osSupport::openReadOnly(_name);
     if (_fd == -1) {
@@ -454,19 +387,17 @@
     if (_file_size < _index_size) {
         return false;
     }
-    // Determine how much of the image is memory mapped.
-    size_t map_size = (size_t)(MemoryMapImage ? _file_size : _index_size);
     // Memory map image (minimally the index.)
-    _index_data = (u1*)osSupport::map_memory(_fd, _name, 0, map_size);
+    _index_data = (u1*)osSupport::map_memory(_fd, _name, 0, (size_t)map_size());
     assert(_index_data && "image file not memory mapped");
     // Retrieve length of index perfect hash table.
     u4 length = table_length();
     // Compute offset of the perfect hash table redirect table.
     u4 redirect_table_offset = (u4)header_size;
     // Compute offset of index attribute offsets.
-    u4 offsets_table_offset = redirect_table_offset + length * sizeof(s4);
+    u4 offsets_table_offset = redirect_table_offset + length * (u4)sizeof(s4);
     // Compute offset of index location attribute data.
-    u4 location_bytes_offset = offsets_table_offset + length * sizeof(u4);
+    u4 location_bytes_offset = offsets_table_offset + length * (u4)sizeof(u4);
     // Compute offset of index string table.
     u4 string_bytes_offset = location_bytes_offset + locations_size();
     // Compute address of the perfect hash table redirect table.
@@ -479,8 +410,7 @@
     _string_bytes = _index_data + string_bytes_offset;
 
     // Initialize the module data
-    ImageModuleData::module_data_name(buffer, _name);
-    module_data = new ImageModuleData(this, buffer);
+    module_data = new ImageModuleData(this);
     // Successful open (if memory allocation succeeded).
     return module_data != NULL;
 }
@@ -660,10 +590,10 @@
     if (compressed_size != 0) {
         u1* compressed_data;
         // If not memory mapped read in bytes.
-        if (!MemoryMapImage) {
+        if (!memory_map_image) {
             // Allocate buffer for compression.
-            compressed_data = new u1[(u4)compressed_size];
-            assert (compressed_data != NULL && "allocation failed");
+            compressed_data = new u1[(size_t)compressed_size];
+            assert(compressed_data != NULL && "allocation failed");
             // Read bytes from offset beyond the image index.
             bool is_read = read_at(compressed_data, compressed_size, _index_size + offset);
             assert(is_read && "error reading from image or short read");
@@ -673,10 +603,10 @@
         // Get image string table.
         const ImageStrings strings = get_strings();
         // Decompress resource.
-        ImageDecompressor::decompress_resource(compressed_data, uncompressed_data, (u4)uncompressed_size,
-                        &strings);
+        ImageDecompressor::decompress_resource(compressed_data, uncompressed_data, uncompressed_size,
+                        &strings, _endian);
         // If not memory mapped then release temporary buffer.
-        if (!MemoryMapImage) {
+        if (!memory_map_image) {
                 delete[] compressed_data;
         }
     } else {