https://bugs.webkit.org/show_bug.cgi?id=120099
Source/JavaScriptCore:
Reviewed by Mark Hahnenberg.
JSDataView should not store the ArrayBuffer* in the butterfly indexing header, since
JSDataView may have ordinary JS indexed properties.
* runtime/ClassInfo.h:
* runtime/JSArrayBufferView.cpp:
(JSC::JSArrayBufferView::ConstructionContext::ConstructionContext):
(JSC::JSArrayBufferView::finishCreation):
* runtime/JSArrayBufferView.h:
(JSC::hasArrayBuffer):
* runtime/JSArrayBufferViewInlines.h:
(JSC::JSArrayBufferView::buffer):
(JSC::JSArrayBufferView::neuter):
(JSC::JSArrayBufferView::byteOffset):
* runtime/JSCell.cpp:
(JSC::JSCell::slowDownAndWasteMemory):
* runtime/JSCell.h:
* runtime/JSDataView.cpp:
(JSC::JSDataView::JSDataView):
(JSC::JSDataView::create):
(JSC::JSDataView::slowDownAndWasteMemory):
* runtime/JSDataView.h:
(JSC::JSDataView::buffer):
* runtime/JSGenericTypedArrayView.h:
* runtime/JSGenericTypedArrayViewInlines.h:
(JSC::::visitChildren):
(JSC::::slowDownAndWasteMemory):
LayoutTests:
Reviewed by Mark Hahnenberg.
* fast/js/regress/ArrayBuffer-DataView-alloc-large-long-lived-expected.txt: Added.
* fast/js/regress/ArrayBuffer-DataView-alloc-large-long-lived.html: Added.
* fast/js/regress/ArrayBuffer-DataView-alloc-long-lived-expected.txt: Added.
* fast/js/regress/ArrayBuffer-DataView-alloc-long-lived.html: Added.
* fast/js/regress/DataView-custom-properties-expected.txt: Added.
* fast/js/regress/DataView-custom-properties.html: Added.
* fast/js/regress/script-tests/ArrayBuffer-DataView-alloc-large-long-lived.js: Added.
* fast/js/regress/script-tests/ArrayBuffer-DataView-alloc-long-lived.js: Added.
* fast/js/regress/script-tests/DataView-custom-properties.js: Added.
* platform/mac/TestExpectations:
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@154408
268f45cc-cd09-0410-ab3c-
d52691b4dbfc
+2013-08-21 Filip Pizlo <fpizlo@apple.com>
+
+ Assertion failure in JSC::SlotVisitor::copyLater when marking JSDataView
+ https://bugs.webkit.org/show_bug.cgi?id=120099
+
+ Reviewed by Mark Hahnenberg.
+
+ * fast/js/regress/ArrayBuffer-DataView-alloc-large-long-lived-expected.txt: Added.
+ * fast/js/regress/ArrayBuffer-DataView-alloc-large-long-lived.html: Added.
+ * fast/js/regress/ArrayBuffer-DataView-alloc-long-lived-expected.txt: Added.
+ * fast/js/regress/ArrayBuffer-DataView-alloc-long-lived.html: Added.
+ * fast/js/regress/DataView-custom-properties-expected.txt: Added.
+ * fast/js/regress/DataView-custom-properties.html: Added.
+ * fast/js/regress/script-tests/ArrayBuffer-DataView-alloc-large-long-lived.js: Added.
+ * fast/js/regress/script-tests/ArrayBuffer-DataView-alloc-long-lived.js: Added.
+ * fast/js/regress/script-tests/DataView-custom-properties.js: Added.
+ * platform/mac/TestExpectations:
+
2013-08-21 Mark Hahnenberg <mhahnenberg@apple.com>
Remove incorrect ASSERT from CopyVisitor::visitItem
--- /dev/null
+JSRegress/ArrayBuffer-DataView-alloc-large-long-lived
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
--- /dev/null
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src="../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script src="resources/regress-pre.js"></script>
+<script src="script-tests/ArrayBuffer-DataView-alloc-large-long-lived.js"></script>
+<script src="resources/regress-post.js"></script>
+<script src="../resources/js-test-post.js"></script>
+</body>
+</html>
--- /dev/null
+JSRegress/ArrayBuffer-DataView-alloc-long-lived
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
--- /dev/null
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src="../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script src="resources/regress-pre.js"></script>
+<script src="script-tests/ArrayBuffer-DataView-alloc-long-lived.js"></script>
+<script src="resources/regress-post.js"></script>
+<script src="../resources/js-test-post.js"></script>
+</body>
+</html>
--- /dev/null
+JSRegress/DataView-custom-properties
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
--- /dev/null
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src="../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script src="resources/regress-pre.js"></script>
+<script src="script-tests/DataView-custom-properties.js"></script>
+<script src="resources/regress-post.js"></script>
+<script src="../resources/js-test-post.js"></script>
+</body>
+</html>
--- /dev/null
+var array = new Array(10000);
+
+for (var i = 0; i < 100000; ++i)
+ array[i % array.length] = new DataView(new ArrayBuffer(1000));
+
+for (var i = 0; i < array.length; ++i) {
+ if (array[i].byteLength != 1000)
+ throw "Error: bad length: " + array[i].byteLength;
+ if (array[i].buffer.byteLength != 1000)
+ throw "Error: bad buffer.byteLength: " + array[i].buffer.byteLength;
+}
--- /dev/null
+var array = new Array(10000);
+
+for (var i = 0; i < 70000; ++i)
+ array[i % array.length] = new DataView(new ArrayBuffer(10));
+
+for (var i = 0; i < array.length; ++i) {
+ if (array[i].byteLength != 10)
+ throw "Error: bad length: " + array[i].byteLength;
+ if (array[i].buffer.byteLength != 10)
+ throw "Error: bad buffer.byteLength: " + array[i].buffer.byteLength;
+}
--- /dev/null
+var array = new Array(10000);
+
+for (var i = 0; i < 100000; ++i) {
+ var thingy = new DataView(new ArrayBuffer(1000));
+ switch (i % 3) {
+ case 0:
+ break;
+ case 1:
+ thingy.f = 42;
+ break;
+ case 2:
+ thingy[0] = 42;
+ break;
+ }
+ array[i % array.length] = thingy;
+}
+
+for (var i = 0; i < array.length; ++i) {
+ if (array[i].byteLength != 1000)
+ throw "Error: bad length: " + array[i].byteLength;
+ if (array[i].buffer.byteLength != 1000)
+ throw "Error: bad buffer.byteLength: " + array[i].buffer.byteLength;
+ switch (i % 3) {
+ case 0:
+ break;
+ case 1:
+ if (array[i].f != 42)
+ throw "Error: bad field 'f': " + array[i].f;
+ break;
+ case 2:
+ if (array[i][0] != 42)
+ throw "Error: bad element 0: " + array[i][0];
+ break;
+ }
+}
webkit.org/b/120087 [ Lion ] fast/forms/submit-to-url-fragment.html [ Pass Crash ]
-webkit.org/b/120099 [ Debug ] fast/canvas/webgl/array-message-passing.html [ Crash ]
+2013-08-21 Filip Pizlo <fpizlo@apple.com>
+
+ Assertion failure in JSC::SlotVisitor::copyLater when marking JSDataView
+ https://bugs.webkit.org/show_bug.cgi?id=120099
+
+ Reviewed by Mark Hahnenberg.
+
+ JSDataView should not store the ArrayBuffer* in the butterfly indexing header, since
+ JSDataView may have ordinary JS indexed properties.
+
+ * runtime/ClassInfo.h:
+ * runtime/JSArrayBufferView.cpp:
+ (JSC::JSArrayBufferView::ConstructionContext::ConstructionContext):
+ (JSC::JSArrayBufferView::finishCreation):
+ * runtime/JSArrayBufferView.h:
+ (JSC::hasArrayBuffer):
+ * runtime/JSArrayBufferViewInlines.h:
+ (JSC::JSArrayBufferView::buffer):
+ (JSC::JSArrayBufferView::neuter):
+ (JSC::JSArrayBufferView::byteOffset):
+ * runtime/JSCell.cpp:
+ (JSC::JSCell::slowDownAndWasteMemory):
+ * runtime/JSCell.h:
+ * runtime/JSDataView.cpp:
+ (JSC::JSDataView::JSDataView):
+ (JSC::JSDataView::create):
+ (JSC::JSDataView::slowDownAndWasteMemory):
+ * runtime/JSDataView.h:
+ (JSC::JSDataView::buffer):
+ * runtime/JSGenericTypedArrayView.h:
+ * runtime/JSGenericTypedArrayViewInlines.h:
+ (JSC::::visitChildren):
+ (JSC::::slowDownAndWasteMemory):
+
2013-08-21 Mark Hahnenberg <mhahnenberg@apple.com>
Remove incorrect ASSERT from CopyVisitor::visitItem
typedef bool (*DefineOwnPropertyFunctionPtr)(JSObject*, ExecState*, PropertyName, PropertyDescriptor&, bool);
DefineOwnPropertyFunctionPtr defineOwnProperty;
- typedef void (*SlowDownAndWasteMemory)(JSArrayBufferView*);
+ typedef ArrayBuffer* (*SlowDownAndWasteMemory)(JSArrayBufferView*);
SlowDownAndWasteMemory slowDownAndWasteMemory;
typedef PassRefPtr<ArrayBufferView> (*GetTypedArrayImpl)(JSArrayBufferView*);
m_butterfly = Butterfly::create(vm, 0, 0, 0, true, indexingHeader, 0);
}
+JSArrayBufferView::ConstructionContext::ConstructionContext(
+ Structure* structure, PassRefPtr<ArrayBuffer> arrayBuffer,
+ unsigned byteOffset, unsigned length, DataViewTag)
+ : m_structure(structure)
+ , m_vector(static_cast<uint8_t*>(arrayBuffer->data()) + byteOffset)
+ , m_length(length)
+ , m_mode(DataViewMode)
+ , m_butterfly(0)
+{
+}
+
JSArrayBufferView::JSArrayBufferView(VM& vm, ConstructionContext& context)
: Base(vm, context.structure(), context.butterfly())
, m_vector(context.vector())
case WastefulTypedArray:
vm.heap.addReference(this, butterfly()->indexingHeader()->arrayBuffer());
return;
+ case DataViewMode:
+ ASSERT(!butterfly());
+ vm.heap.addReference(this, jsCast<JSDataView*>(this)->buffer());
+ return;
}
RELEASE_ASSERT_NOT_REACHED();
}
// vector allocated using who-knows-what, and M = WastefulTypedArray.
// The view does not own the vector.
WastefulTypedArray,
+
+ // A data view. B is unused, V points to a vector allocated using who-
+ // knows-what, and M = DataViewMode. The view does not own the vector.
+ // There is an extra field (in JSDataView) that points to the
+ // ArrayBuffer.
+ DataViewMode
};
+inline bool hasArrayBuffer(TypedArrayMode mode)
+{
+ return mode >= WastefulTypedArray;
+}
+
// When WebCore uses a JSArrayBufferView, it expects to be able to get the native
// ArrayBuffer and little else. This requires slowing down and wasting memory,
// and then accessing things via the Butterfly. When JS uses a JSArrayBufferView
VM&, Structure*, PassRefPtr<ArrayBuffer>,
unsigned byteOffset, unsigned length);
+ enum DataViewTag { DataView };
+ ConstructionContext(
+ Structure*, PassRefPtr<ArrayBuffer>,
+ unsigned byteOffset, unsigned length, DataViewTag);
+
bool operator!() const { return !m_structure; }
Structure* structure() const { return m_structure; }
static void getOwnNonIndexPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
public:
- // Allocates the full-on native buffer. Also moves the data into the C heap
- // if necessary.
- void slowDownAndWasteMemoryIfNecessary();
-
TypedArrayMode mode() const { return m_mode; }
ArrayBuffer* buffer();
PassRefPtr<ArrayBufferView> impl();
#include "ArrayBufferView.h"
#include "JSArrayBufferView.h"
+#include "JSDataView.h"
namespace JSC {
-inline void JSArrayBufferView::slowDownAndWasteMemoryIfNecessary()
-{
- if (m_mode != WastefulTypedArray)
- methodTable()->slowDownAndWasteMemory(this);
-}
-
inline ArrayBuffer* JSArrayBufferView::buffer()
{
- slowDownAndWasteMemoryIfNecessary();
- return butterfly()->indexingHeader()->arrayBuffer();
+ switch (m_mode) {
+ case WastefulTypedArray:
+ return butterfly()->indexingHeader()->arrayBuffer();
+ case DataViewMode:
+ return jsCast<JSDataView*>(this)->buffer();
+ default:
+ return methodTable()->slowDownAndWasteMemory(this);
+ }
}
inline PassRefPtr<ArrayBufferView> JSArrayBufferView::impl()
inline void JSArrayBufferView::neuter()
{
- ASSERT(m_mode == WastefulTypedArray);
+ ASSERT(hasArrayBuffer(m_mode));
m_length = 0;
m_vector = 0;
}
inline unsigned JSArrayBufferView::byteOffset()
{
- if (m_mode != WastefulTypedArray) {
- ASSERT(m_mode == FastTypedArray || m_mode == OversizeTypedArray);
+ if (!hasArrayBuffer(m_mode))
return 0;
- }
ptrdiff_t delta =
static_cast<uint8_t*>(m_vector) - static_cast<uint8_t*>(buffer()->data());
return false;
}
-void JSCell::slowDownAndWasteMemory(JSArrayBufferView*)
+ArrayBuffer* JSCell::slowDownAndWasteMemory(JSArrayBufferView*)
{
RELEASE_ASSERT_NOT_REACHED();
+ return 0;
}
PassRefPtr<ArrayBufferView> JSCell::getTypedArrayImpl(JSArrayBufferView*)
static bool defineOwnProperty(JSObject*, ExecState*, PropertyName, PropertyDescriptor&, bool shouldThrow);
static bool getOwnPropertySlot(JSObject*, ExecState*, PropertyName, PropertySlot&);
static bool getOwnPropertySlotByIndex(JSObject*, ExecState*, unsigned propertyName, PropertySlot&);
- JS_EXPORT_PRIVATE static NO_RETURN_DUE_TO_CRASH void slowDownAndWasteMemory(JSArrayBufferView*);
+ JS_EXPORT_PRIVATE static ArrayBuffer* slowDownAndWasteMemory(JSArrayBufferView*);
JS_EXPORT_PRIVATE static PassRefPtr<ArrayBufferView> getTypedArrayImpl(JSArrayBufferView*);
private:
const ClassInfo JSDataView::s_info = {
"DataView", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(JSDataView)};
-JSDataView::JSDataView(VM& vm, ConstructionContext& context)
+JSDataView::JSDataView(VM& vm, ConstructionContext& context, ArrayBuffer* buffer)
: Base(vm, context)
+ , m_buffer(buffer)
{
}
return 0;
}
VM& vm = exec->vm();
- ConstructionContext context(vm, structure, buffer, byteOffset, byteLength);
+ ConstructionContext context(
+ structure, buffer, byteOffset, byteLength, ConstructionContext::DataView);
ASSERT(context);
JSDataView* result =
- new (NotNull, allocateCell<JSDataView>(vm.heap)) JSDataView(vm, context);
+ new (NotNull, allocateCell<JSDataView>(vm.heap)) JSDataView(vm, context, buffer.get());
result->finishCreation(vm);
return result;
}
return Base::getOwnPropertySlot(thisObject, exec, propertyName, slot);
}
-void JSDataView::slowDownAndWasteMemory(JSArrayBufferView*)
+ArrayBuffer* JSDataView::slowDownAndWasteMemory(JSArrayBufferView*)
{
UNREACHABLE_FOR_PLATFORM();
+ return 0;
}
PassRefPtr<ArrayBufferView> JSDataView::getTypedArrayImpl(JSArrayBufferView* object)
static const unsigned elementSize = 1;
protected:
- JSDataView(VM&, ConstructionContext&);
+ JSDataView(VM&, ConstructionContext&, ArrayBuffer*);
public:
static JSDataView* create(
static JSDataView* create(ExecState*, Structure*, unsigned length);
bool set(ExecState*, JSObject*, unsigned offset, unsigned length);
+ ArrayBuffer* buffer() const { return m_buffer; }
+
PassRefPtr<DataView> typedImpl();
static const TypedArrayType TypedArrayStorageType = TypeDataView;
protected:
static bool getOwnPropertySlot(JSObject*, ExecState*, PropertyName, PropertySlot&);
- static void slowDownAndWasteMemory(JSArrayBufferView*);
+ static ArrayBuffer* slowDownAndWasteMemory(JSArrayBufferView*);
static PassRefPtr<ArrayBufferView> getTypedArrayImpl(JSArrayBufferView*);
public:
static Structure* createStructure(VM&, JSGlobalObject*, JSValue prototype);
DECLARE_EXPORT_INFO;
+
+private:
+ ArrayBuffer* m_buffer;
};
} // namespace JSC
// Allocates the full-on native buffer and moves data into the C heap if
// necessary. Note that this never allocates in the GC heap.
- static void slowDownAndWasteMemory(JSArrayBufferView*);
+ static ArrayBuffer* slowDownAndWasteMemory(JSArrayBufferView*);
static PassRefPtr<ArrayBufferView> getTypedArrayImpl(JSArrayBufferView*);
};
case WastefulTypedArray:
break;
+
+ case DataViewMode:
+ RELEASE_ASSERT_NOT_REACHED();
+ break;
}
Base::visitChildren(thisObject, visitor);
}
template<typename Adaptor>
-void JSGenericTypedArrayView<Adaptor>::slowDownAndWasteMemory(JSArrayBufferView* object)
+ArrayBuffer* JSGenericTypedArrayView<Adaptor>::slowDownAndWasteMemory(JSArrayBufferView* object)
{
JSGenericTypedArrayView* thisObject = jsCast<JSGenericTypedArrayView*>(object);
buffer = ArrayBuffer::createAdopted(thisObject->m_vector, thisObject->byteLength());
break;
- case WastefulTypedArray:
+ default:
RELEASE_ASSERT_NOT_REACHED();
break;
}
thisObject->m_vector = buffer->data();
thisObject->m_mode = WastefulTypedArray;
heap->addReference(thisObject, buffer.get());
+
+ return buffer.get();
}
template<typename Adaptor>