From 1d4c2e87542ee4c97c23bc43f779047546584884 Mon Sep 17 00:00:00 2001 From: Jeff Walden Date: Fri, 14 Mar 2014 16:39:23 -0700 Subject: [PATCH] Back out a5377cd1e45e (bug 945152 part 1) to clear way for other fixing. Also should reland in short order once those other fixes land. r=backout --- js/src/gc/Memory.cpp | 117 ------------ js/src/gc/Memory.h | 13 -- js/src/jsapi-tests/moz.build | 1 - js/src/jsapi-tests/testMappedArrayBuffer.cpp | 179 ------------------- js/src/jsapi.h | 20 --- js/src/jsobjinlines.h | 2 - js/src/vm/ArrayBufferObject.cpp | 48 +---- js/src/vm/ArrayBufferObject.h | 43 ----- js/src/vm/ObjectImpl.h | 9 +- js/src/vm/StructuredClone.cpp | 36 ---- 10 files changed, 2 insertions(+), 466 deletions(-) delete mode 100644 js/src/jsapi-tests/testMappedArrayBuffer.cpp diff --git a/js/src/gc/Memory.cpp b/js/src/gc/Memory.cpp index b25f4fc13c0f..c4a1f8703cc4 100644 --- a/js/src/gc/Memory.cpp +++ b/js/src/gc/Memory.cpp @@ -107,21 +107,6 @@ gc::GetPageFaultCount() return pmc.PageFaultCount; } -void * -gc::AllocateMappedObject(int fd, int *new_fd, size_t offset, size_t length, - size_t alignment, size_t header) -{ - // TODO: to be implemented. - return nullptr; -} - -// Deallocate mapped memory for object. -void -gc::DeallocateMappedObject(int fd, void *p, size_t length) -{ - // TODO: to be implemented. -} - #elif defined(SOLARIS) #include @@ -180,28 +165,10 @@ gc::GetPageFaultCount() return 0; } -void * -gc::AllocateMappedObject(int fd, int *new_fd, size_t offset, size_t length, - size_t alignment, size_t header) -{ - // TODO: to be implemented. - return nullptr; -} - -// Deallocate mapped memory for object. -void -gc::DeallocateMappedObject(int fd, void *p, size_t length) -{ - // TODO: to be implemented. -} - #elif defined(XP_UNIX) -#include #include #include -#include -#include #include void @@ -318,90 +285,6 @@ gc::GetPageFaultCount() return usage.ru_majflt; } -void * -gc::AllocateMappedObject(int fd, int *new_fd, size_t offset, size_t length, - size_t alignment, size_t header) -{ -#define NEED_PAGE_ALIGNED 0 - size_t pa_start; // Page aligned starting - size_t pa_end; // Page aligned ending - size_t pa_size; // Total page aligned size - size_t page_size = sysconf(_SC_PAGESIZE); // Page size - bool page_for_header = false; // Do we need an additional page for header? - struct stat st; - uint8_t *buf; - - // Make sure file exists and do sanity check for offset and size. - if (fstat(fd, &st) < 0 || offset >= (size_t) st.st_size || - length == 0 || length > (size_t) st.st_size - offset) - return nullptr; - - // Check for minimal alignment requirement. -#if NEED_PAGE_ALIGNED - alignment = std::max(alignment, page_size); -#endif - if (offset & (alignment - 1)) - return nullptr; - - // Page aligned starting of the offset. - pa_start = offset & ~(page_size - 1); - // Calculate page aligned ending by adding one page to the page aligned - // starting of data end position(offset + length - 1). - pa_end = ((offset + length - 1) & ~(page_size - 1)) + page_size; - pa_size = pa_end - pa_start; - - // Do we need one more page for header? - if (offset - pa_start < header) { - page_for_header = true; - pa_size += page_size; - } - - // Ask for a continuous memory location. - buf = (uint8_t *) MapMemory(pa_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); - if (buf == MAP_FAILED) - return nullptr; - - // Duplicate a new fd for mapping, so each cloned object uses a different fd. - *new_fd = dup(fd); - - // If there's an additional page for header, don't map that page to file. - if (page_for_header) { - buf = (uint8_t *) mmap(buf + page_size, pa_size - page_size, - PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_FIXED, *new_fd, pa_start); - } else { - buf = (uint8_t *) mmap(buf, pa_size, PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_FIXED, *new_fd, pa_start); - } - if (buf == MAP_FAILED) { - close(*new_fd); - return nullptr; - } - - // Reset the data before target file, which we don't need to see. - memset(buf, 0, offset - pa_start); - - // Reset the data after target file, which we don't need to see. - memset(buf + (offset - pa_start) + length, 0, pa_end - (offset + length)); - - return buf + (offset - pa_start) - header; -} - -void -gc::DeallocateMappedObject(int fd, void *p, size_t length) -{ - void *pa_start; // Page aligned starting - size_t page_size = sysconf(_SC_PAGESIZE); // Page size - size_t total_size; // Total allocated size - - // The fd is not needed anymore. - close(fd); - - pa_start = (void *)(uintptr_t(p) & ~(page_size - 1)); - total_size = ((uintptr_t(p) + length) & ~(page_size - 1)) + page_size - uintptr_t(pa_start); - munmap(pa_start, total_size); -} - #else #error "Memory mapping functions are not defined for your OS." #endif diff --git a/js/src/gc/Memory.h b/js/src/gc/Memory.h index c8d2c21e5b95..406888b1f089 100644 --- a/js/src/gc/Memory.h +++ b/js/src/gc/Memory.h @@ -41,19 +41,6 @@ MarkPagesInUse(JSRuntime *rt, void *p, size_t size); size_t GetPageFaultCount(); -// Allocate mapped memory for object from file descriptor, offset and length -// of the file. -// The new_fd is duplicated from original fd, for the purpose of cloned object. -// The offset must be aligned according to alignment requirement. -// An additional page might be allocated depending on offset and header size given. -void * -AllocateMappedObject(int fd, int *new_fd, size_t offset, size_t length, - size_t alignment, size_t header); - -// Deallocate mapped memory of the object. -void -DeallocateMappedObject(int fd, void *p, size_t length); - } // namespace gc } // namespace js diff --git a/js/src/jsapi-tests/moz.build b/js/src/jsapi-tests/moz.build index 64f9d56ef540..a166525daf14 100644 --- a/js/src/jsapi-tests/moz.build +++ b/js/src/jsapi-tests/moz.build @@ -45,7 +45,6 @@ UNIFIED_SOURCES += [ 'testJSEvaluateScript.cpp', 'testLookup.cpp', 'testLooselyEqual.cpp', - 'testMappedArrayBuffer.cpp', 'testNewObject.cpp', 'testNullRoot.cpp', 'testObjectEmulatingUndefined.cpp', diff --git a/js/src/jsapi-tests/testMappedArrayBuffer.cpp b/js/src/jsapi-tests/testMappedArrayBuffer.cpp deleted file mode 100644 index a0387e252f4c..000000000000 --- a/js/src/jsapi-tests/testMappedArrayBuffer.cpp +++ /dev/null @@ -1,179 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * vim: set ts=8 sts=4 et sw=4 tw=99: - */ - -#ifdef XP_UNIX -#include -#include -#include -#include -#include -#include - -#include "jsfriendapi.h" -#include "js/StructuredClone.h" -#include "jsapi-tests/tests.h" -#include "vm/ArrayBufferObject.h" - -const char test_data[] = "1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; -const char test_filename[] = "temp-bug945152_MappedArrayBuffer"; - -BEGIN_TEST(testMappedArrayBuffer_bug945152) -{ - TempFile test_file; - FILE *test_stream = test_file.open(test_filename); - CHECK(fputs(test_data, test_stream) != EOF); - test_file.close(); - - // Offset 0. - CHECK(TestCreateObject(0, 12)); - - // Aligned offset. - CHECK(TestCreateObject(8, 12)); - - // Unaligned offset. - CHECK(CreateNewObject(11, 12) == nullptr); - - // Offset + length greater than file size. - CHECK(CreateNewObject(8, sizeof(test_data) - 7) == nullptr); - - // Release the mapped content. - CHECK(TestReleaseContents()); - -#ifdef JSGC_USE_EXACT_ROOTING - // Ensure that fd is closed after object been GCed. - // Check the fd returned from object created in a function, - // then do the GC, in order to guarantee the object is freed when - // exact rooting is not on. - int fd = GetNewObjectFD(); - GC(cx); - CHECK(!fd_is_valid(fd)); -#endif - - // Neuter mapped array buffer. - CHECK(TestNeuterObject()); - - // Clone mapped array buffer. - CHECK(TestCloneObject()); - - test_file.remove(); - - return true; -} - -JSObject *CreateNewObject(const int offset, const int length) -{ - int fd = open(test_filename, O_RDONLY); - void *ptr; - int new_fd; - if (!JS_CreateMappedArrayBufferContents(fd, &new_fd, offset, length, &ptr)) - return nullptr; - JSObject *obj = JS_NewArrayBufferWithContents(cx, ptr); - close(fd); - - return obj; -} - -// Return the fd from object created in the stack. -int GetNewObjectFD() -{ - JS::RootedObject obj(cx, CreateNewObject(0, 12)); - int fd = getFD(obj); - CHECK(fd_is_valid(fd)); - - return fd; -} - -bool VerifyObject(JS::HandleObject obj, const int offset, const int length) -{ - CHECK(obj != nullptr); - CHECK(JS_IsArrayBufferObject(obj)); - CHECK_EQUAL(JS_GetArrayBufferByteLength(obj), length); - js::ArrayBufferObject *buf = &obj->as(); - CHECK(buf->isMappedArrayBuffer()); - const char *data = reinterpret_cast(JS_GetArrayBufferData(obj)); - CHECK(data != nullptr); - CHECK(memcmp(data, test_data + offset, length) == 0); - - return true; -} - -bool TestCreateObject(const int offset, const int length) -{ - JS::RootedObject obj(cx, CreateNewObject(offset, length)); - CHECK(VerifyObject(obj, offset, length)); - - return true; -} - -bool TestReleaseContents() -{ - int fd = open(test_filename, O_RDONLY); - void *ptr; - int new_fd; - if (!JS_CreateMappedArrayBufferContents(fd, &new_fd, 0, 12, &ptr)) - return false; - CHECK(fd_is_valid(new_fd)); - JS_ReleaseMappedArrayBufferContents(new_fd, ptr, 12); - CHECK(!fd_is_valid(new_fd)); - close(fd); - - return true; -} - -bool TestNeuterObject() -{ - JS::RootedObject obj(cx, CreateNewObject(8, 12)); - CHECK(obj != nullptr); - int fd = getFD(obj); - CHECK(fd_is_valid(fd)); - JS_NeuterArrayBuffer(cx, obj); - CHECK(isNeutered(obj)); - CHECK(!fd_is_valid(fd)); - - return true; -} - -bool TestCloneObject() -{ - JS::RootedObject obj1(cx, CreateNewObject(8, 12)); - CHECK(obj1 != nullptr); - JSAutoStructuredCloneBuffer cloned_buffer; - JS::RootedValue v1(cx, OBJECT_TO_JSVAL(obj1)); - const JSStructuredCloneCallbacks *callbacks = js::GetContextStructuredCloneCallbacks(cx); - CHECK(cloned_buffer.write(cx, v1, callbacks, nullptr)); - JS::RootedValue v2(cx); - CHECK(cloned_buffer.read(cx, &v2, callbacks, nullptr)); - JS::RootedObject obj2(cx, JSVAL_TO_OBJECT(v2)); - CHECK(VerifyObject(obj2, 8, 12)); - - return true; -} - -bool isNeutered(JS::HandleObject obj) -{ - JS::RootedValue v(cx); - return JS_GetProperty(cx, obj, "byteLength", &v) && v.toInt32() == 0; -} - -int getFD(JS::HandleObject obj) -{ - CHECK(obj != nullptr); - js::ArrayBufferObject *buf = &obj->as(); - return buf->getMappingFD(); -} - -static bool fd_is_valid(int fd) -{ - return fcntl(fd, F_GETFD) != -1 || errno != EBADF; -} - -static void GC(JSContext *cx) -{ - JS_GC(JS_GetRuntime(cx)); - // Trigger another to wait for background finalization to end. - JS_GC(JS_GetRuntime(cx)); -} - -END_TEST(testMappedArrayBuffer_bug945152) -#endif diff --git a/js/src/jsapi.h b/js/src/jsapi.h index d37cc9f78b2f..e2b4ec4456c6 100644 --- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -3161,26 +3161,6 @@ JS_AllocateArrayBufferContents(JSContext *maybecx, uint32_t nbytes, void **conte extern JS_PUBLIC_API(bool) JS_ReallocateArrayBufferContents(JSContext *cx, uint32_t nbytes, void **contents, uint8_t **data); -/* - * Create memory mapped array buffer contents. - * For cloning, the fd will not be closed after mapping, and the caller must - * take care of closing fd after calling this function. - * A new duplicated fd used by the mapping is returned in new_fd. - */ -extern JS_PUBLIC_API(bool) -JS_CreateMappedArrayBufferContents(int fd, int *new_fd, size_t offset, - size_t length, void **contents); - -/* - * Release the allocated resource of mapped array buffer contents before the - * object is created. - * If a new object has been created by JS_NewArrayBufferWithContents() with - * this content, then JS_NeuterArrayBuffer() should be used instead to release - * the resource used by the object. - */ -extern JS_PUBLIC_API(void) -JS_ReleaseMappedArrayBufferContents(int fd, void *contents, size_t length); - extern JS_PUBLIC_API(JSIdArray *) JS_Enumerate(JSContext *cx, JSObject *obj); diff --git a/js/src/jsobjinlines.h b/js/src/jsobjinlines.h index 98b76947f2c9..d5976da40026 100644 --- a/js/src/jsobjinlines.h +++ b/js/src/jsobjinlines.h @@ -577,8 +577,6 @@ JSObject::finish(js::FreeOp *fop) js::ObjectElements *elements = getElementsHeader(); if (MOZ_UNLIKELY(elements->isAsmJSArrayBuffer())) js::ArrayBufferObject::releaseAsmJSArrayBuffer(fop, this); - else if (MOZ_UNLIKELY(elements->isMappedArrayBuffer())) - js::ArrayBufferObject::releaseMappedArrayBuffer(fop, this); else fop->free_(elements); } diff --git a/js/src/vm/ArrayBufferObject.cpp b/js/src/vm/ArrayBufferObject.cpp index 696ad54a47b5..fe52c3436ef5 100644 --- a/js/src/vm/ArrayBufferObject.cpp +++ b/js/src/vm/ArrayBufferObject.cpp @@ -30,7 +30,6 @@ #include "gc/Barrier.h" #include "gc/Marking.h" -#include "gc/Memory.h" #include "jit/AsmJS.h" #include "jit/AsmJSModule.h" #include "vm/GlobalObject.h" @@ -479,10 +478,7 @@ ArrayBufferObject::neuter(JSContext *cx) JS_ASSERT(!isSharedArrayBuffer()); JS_ASSERT(cx); - if (isMappedArrayBuffer()) { - releaseMappedArrayBuffer(nullptr, this); - setFixedElements(); - } else if (hasDynamicElements() && !isAsmJSArrayBuffer()) { + if (hasDynamicElements() && !isAsmJSArrayBuffer()) { ObjectElements *oldHeader = getElementsHeader(); changeContents(cx, ObjectElements::fromElements(fixedElements())); @@ -634,33 +630,6 @@ ArrayBufferObject::neuterAsmJSArrayBuffer(JSContext *cx, ArrayBufferObject &buff #endif } -void * -ArrayBufferObject::createMappedArrayBuffer(int fd, int *new_fd, size_t offset, size_t length) -{ - void *ptr = AllocateMappedObject(fd, new_fd, offset, length, 8, - sizeof(MappingInfoHeader) + sizeof(ObjectElements)); - if (!ptr) - return nullptr; - - ptr = reinterpret_cast(uintptr_t(ptr) + sizeof(MappingInfoHeader)); - ObjectElements *header = reinterpret_cast(ptr); - initMappedElementsHeader(header, *new_fd, offset, length); - - return ptr; -} - -void -ArrayBufferObject::releaseMappedArrayBuffer(FreeOp *fop, JSObject *obj) -{ - ArrayBufferObject &buffer = obj->as(); - if(!buffer.isMappedArrayBuffer() || buffer.isNeutered()) - return; - - ObjectElements *header = buffer.getElementsHeader(); - if (header) - DeallocateMappedObject(buffer.getMappingFD(), header, header->initializedLength); -} - void ArrayBufferObject::addView(ArrayBufferViewObject *view) { @@ -1390,21 +1359,6 @@ JS_StealArrayBufferContents(JSContext *cx, HandleObject objArg, void **contents, return true; } -JS_PUBLIC_API(bool) -JS_CreateMappedArrayBufferContents(int fd, int *new_fd, size_t offset, - size_t length, void **contents) -{ - *contents = ArrayBufferObject::createMappedArrayBuffer(fd, new_fd, offset, length); - - return *contents; -} - -JS_PUBLIC_API(void) -JS_ReleaseMappedArrayBufferContents(int fd, void *contents, size_t length) -{ - DeallocateMappedObject(fd, contents, length); -} - JS_FRIEND_API(void *) JS_GetArrayBufferViewData(JSObject *obj) { diff --git a/js/src/vm/ArrayBufferObject.h b/js/src/vm/ArrayBufferObject.h index dc30fb8f9527..1146a719b1ca 100644 --- a/js/src/vm/ArrayBufferObject.h +++ b/js/src/vm/ArrayBufferObject.h @@ -18,13 +18,6 @@ namespace js { class ArrayBufferViewObject; -// Header for mapped array buffer -struct MappingInfoHeader -{ - uint32_t fd; - uint32_t offset; -}; - // The inheritance hierarchy for the various classes relating to typed arrays // is as follows. // @@ -157,33 +150,6 @@ class ArrayBufferObject : public JSObject updateElementsHeader(header, bytes); } - static void initMappedElementsHeader(js::ObjectElements *header, uint32_t fd, - uint32_t offset, uint32_t bytes) { - initElementsHeader(header, bytes); - header->setIsMappedArrayBuffer(); - MappingInfoHeader *mh = getMappingInfoHeader(header); - mh->fd = fd; - mh->offset = offset; - } - - static MappingInfoHeader *getMappingInfoHeader(js::ObjectElements *header) { - MOZ_ASSERT(header->isMappedArrayBuffer()); - return reinterpret_cast(uintptr_t(header) - - sizeof(MappingInfoHeader)); - } - - uint32_t getMappingFD() { - MOZ_ASSERT(getElementsHeader()->isMappedArrayBuffer()); - MappingInfoHeader *mh = getMappingInfoHeader(getElementsHeader()); - return mh->fd; - } - - uint32_t getMappingOffset() const { - MOZ_ASSERT(getElementsHeader()->isMappedArrayBuffer()); - MappingInfoHeader *mh = getMappingInfoHeader(getElementsHeader()); - return mh->offset; - } - static uint32_t headerInitializedLength(const js::ObjectElements *header) { return header->initializedLength; } @@ -236,15 +202,6 @@ class ArrayBufferObject : public JSObject static bool prepareForAsmJS(JSContext *cx, Handle buffer); static bool neuterAsmJSArrayBuffer(JSContext *cx, ArrayBufferObject &buffer); static void releaseAsmJSArrayBuffer(FreeOp *fop, JSObject *obj); - - bool isMappedArrayBuffer() const { - return getElementsHeader()->isMappedArrayBuffer(); - } - void setIsMappedArrayBuffer() { - getElementsHeader()->setIsMappedArrayBuffer(); - } - static void *createMappedArrayBuffer(int fd, int *new_fd, size_t offset, size_t length); - static void releaseMappedArrayBuffer(FreeOp *fop, JSObject *obj); }; /* diff --git a/js/src/vm/ObjectImpl.h b/js/src/vm/ObjectImpl.h index 6ca3ecbe8a9d..7093a1e86377 100644 --- a/js/src/vm/ObjectImpl.h +++ b/js/src/vm/ObjectImpl.h @@ -171,11 +171,10 @@ class ObjectElements ASMJS_ARRAY_BUFFER = 0x2, NEUTERED_BUFFER = 0x4, SHARED_ARRAY_BUFFER = 0x8, - MAPPED_ARRAY_BUFFER = 0x10, // Present only if these elements correspond to an array with // non-writable length; never present for non-arrays. - NONWRITABLE_ARRAY_LENGTH = 0x20, + NONWRITABLE_ARRAY_LENGTH = 0x10 }; private: @@ -250,12 +249,6 @@ class ObjectElements void setIsSharedArrayBuffer() { flags |= SHARED_ARRAY_BUFFER; } - bool isMappedArrayBuffer() const { - return flags & MAPPED_ARRAY_BUFFER; - } - void setIsMappedArrayBuffer() { - flags |= MAPPED_ARRAY_BUFFER; - } bool hasNonwritableArrayLength() const { return flags & NONWRITABLE_ARRAY_LENGTH; } diff --git a/js/src/vm/StructuredClone.cpp b/js/src/vm/StructuredClone.cpp index 8d3ff51e93c6..8c9a75b5cf9a 100644 --- a/js/src/vm/StructuredClone.cpp +++ b/js/src/vm/StructuredClone.cpp @@ -66,7 +66,6 @@ enum StructuredDataType { SCTAG_ARRAY_OBJECT, SCTAG_OBJECT_OBJECT, SCTAG_ARRAY_BUFFER_OBJECT, - SCTAG_MAPPED_ARRAY_BUFFER_OBJECT, SCTAG_BOOLEAN_OBJECT, SCTAG_STRING_OBJECT, SCTAG_NUMBER_OBJECT, @@ -213,7 +212,6 @@ struct JSStructuredCloneReader { JSString *readString(uint32_t nchars); bool readTypedArray(uint32_t arrayType, uint32_t nelems, js::Value *vp, bool v1Read = false); bool readArrayBuffer(uint32_t nbytes, js::Value *vp); - bool readMappedArrayBuffer(Value *vp, uint32_t fd, uint32_t offset, uint32_t length); bool readV1ArrayBuffer(uint32_t arrayType, uint32_t nelems, js::Value *vp); bool readId(jsid *idp); bool startRead(js::Value *vp); @@ -833,12 +831,6 @@ bool JSStructuredCloneWriter::writeArrayBuffer(HandleObject obj) { ArrayBufferObject &buffer = obj->as(); - - if (buffer.isMappedArrayBuffer()) { - return out.writePair(SCTAG_MAPPED_ARRAY_BUFFER_OBJECT, buffer.byteLength()) && - out.writePair(buffer.getMappingFD(), buffer.getMappingOffset()); - } - return out.writePair(SCTAG_ARRAY_BUFFER_OBJECT, buffer.byteLength()) && out.writeBytes(buffer.dataPointer(), buffer.byteLength()); } @@ -1236,26 +1228,6 @@ JSStructuredCloneReader::readArrayBuffer(uint32_t nbytes, Value *vp) return in.readArray(buffer.dataPointer(), nbytes); } -bool -JSStructuredCloneReader::readMappedArrayBuffer(Value *vp, uint32_t fd, - uint32_t offset, uint32_t length) -{ - void *ptr; - int new_fd; - if(!JS_CreateMappedArrayBufferContents(fd, &new_fd, offset, length, &ptr)) { - JS_ReportError(context(), "Failed to create mapped array buffer contents"); - return false; - } - JSObject *obj = JS_NewArrayBufferWithContents(context(), ptr); - if (!obj) { - JS_ReleaseMappedArrayBufferContents(new_fd, ptr, length); - return false; - } - vp->setObject(*obj); - - return true; -} - static size_t bytesPerTypedArrayElement(uint32_t arrayType) { @@ -1440,14 +1412,6 @@ JSStructuredCloneReader::startRead(Value *vp) return false; break; - case SCTAG_MAPPED_ARRAY_BUFFER_OBJECT: - uint32_t fd, offset; - if (!in.readPair(&fd, &offset)) - return false; - if (!readMappedArrayBuffer(vp, fd, offset, data)) - return false; - break; - case SCTAG_TYPED_ARRAY_OBJECT: // readTypedArray adds the array to allObjs uint64_t arrayType;