diff --git a/src/library.js b/src/library.js index 3d00a4d5dbd6e..3a2b6d82401fd 100644 --- a/src/library.js +++ b/src/library.js @@ -3601,30 +3601,44 @@ LibraryManager.library = { * this implementation simply uses malloc underneath the call to * mmap. */ + var MAP_PRIVATE = 2; + var allocated = false; + if (!_mmap.mappings) _mmap.mappings = {}; + if (stream == -1) { var ptr = _malloc(num); + if (!ptr) return -1; + _memset(ptr, 0, num); + allocated = true; } else { var info = FS.streams[stream]; if (!info) return -1; var contents = info.object.contents; - contents = Array.prototype.slice.call(contents, offset, offset+num); - ptr = allocate(contents, 'i8', ALLOC_NORMAL); - } - // align to page size - var ret = ptr; - if (ptr % PAGE_SIZE != 0) { - var old = ptr; - ptr = _malloc(num + PAGE_SIZE); - ret = alignMemoryPage(ptr); - _memcpy(ret, old, num); - _free(old); - } - if (stream == -1) { - _memset(ret, 0, num); + // Only make a new copy when MAP_PRIVATE is specified. + if (flags & MAP_PRIVATE == 0) { + // We can't emulate MAP_SHARED when the file is not backed by HEAP. + assert(contents.buffer === HEAPU8.buffer); + ptr = contents.byteOffset; + allocated = false; + } else { + // Try to avoid unnecessary slices. + if (offset > 0 || offset + num < contents.length) { + if (contents.subarray) { + contents = contents.subarray(offset, offset+num); + } else { + contents = Array.prototype.slice.call(contents, offset, offset+num); + } + } + ptr = _malloc(num); + if (!ptr) return -1; + HEAPU8.set(contents, ptr); + allocated = true; + } } - _mmap.mappings[ret] = { malloc: ptr, num: num }; - return ret; + + _mmap.mappings[ptr] = { malloc: ptr, num: num, allocated: allocated }; + return ptr; }, __01mmap64_: 'mmap', @@ -3635,7 +3649,9 @@ LibraryManager.library = { if (!info) return 0; if (num == info.num) { _mmap.mappings[start] = null; - _free(info.malloc); + if (info.allocated) { + _free(info.malloc); + } } return 0; }, diff --git a/src/preamble.js b/src/preamble.js index 7538b19c35a0a..db4f02eb85385 100644 --- a/src/preamble.js +++ b/src/preamble.js @@ -462,7 +462,11 @@ function allocate(slab, types, allocator, ptr) { #if USE_TYPED_ARRAYS == 2 if (singleType === 'i8') { - HEAPU8.set(new Uint8Array(slab), ret); + if (slab.subarray || slab.slice) { + HEAPU8.set(slab, ret); + } else { + HEAPU8.set(new Uint8Array(slab), ret); + } return ret; } #endif diff --git a/tests/runner.py b/tests/runner.py index 99c536e3ecfaa..16fdc5a7bc0ad 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -6991,7 +6991,9 @@ def test_mmap(self): for (int i = 0; i < 10; i++) { int* map = (int*)mmap(0, 5000, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0); + /* TODO: Should we align to 4k? assert(((int)map) % 4096 == 0); // aligned + */ assert(munmap(map, 5000) == 0); } diff --git a/tools/file_packager.py b/tools/file_packager.py index 73ff4919bc83b..21027999706c1 100644 --- a/tools/file_packager.py +++ b/tools/file_packager.py @@ -321,9 +321,12 @@ def was_seen(name): if file_['mode'] == 'preload': use_data += ''' curr = DataRequest.prototype.requests['%s']; - curr.response = byteArray.subarray(%d,%d); + var data = byteArray.subarray(%d, %d); + var ptr = _malloc(%d); + HEAPU8.set(data, ptr); + curr.response = HEAPU8.subarray(ptr, ptr + %d); curr.onload(); - ''' % (file_['name'], file_['data_start'], file_['data_end']) + ''' % (file_['name'], file_['data_start'], file_['data_end'], file_['data_end'] - file_['data_start'], file_['data_end'] - file_['data_start']) use_data += " Module['removeRunDependency']('datafile_%s');\n" % data_target if Compression.on: @@ -365,9 +368,9 @@ def was_seen(name): num++; } total = Math.ceil(total * Module.expectedDataFileDownloads/num); - Module['setStatus']('Downloading data... (' + loaded + '/' + total + ')'); + if (Module['setStatus']) Module['setStatus']('Downloading data... (' + loaded + '/' + total + ')'); } else if (!Module.dataFileDownloads) { - Module['setStatus']('Downloading data...'); + if (Module['setStatus']) Module['setStatus']('Downloading data...'); } } dataFile.open('GET', '%s', true);