From 81e2ff2fe23f66e48ed1d983b0d7b19446356d32 Mon Sep 17 00:00:00 2001 From: ownedbywuigi Date: Fri, 27 Mar 2026 10:45:45 +0000 Subject: [PATCH] Add SSE2 for memcpy and memuse. caching SVGs too cuz why not --- .vscode/settings.json | 3 ++ dom/svg/SVGUseElement.cpp | 8 ++++ js/src/vm/ArrayBufferObject.cpp | 68 +++++++++++++++++++++++++++++---- js/src/vm/TypedArrayObject.cpp | 67 +++++++++++++++++++++++++++++--- 4 files changed, 133 insertions(+), 13 deletions(-) create mode 100644 .vscode/settings.json diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000000..ca6fe06853 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "git.ignoreLimitWarning": true +} \ No newline at end of file diff --git a/dom/svg/SVGUseElement.cpp b/dom/svg/SVGUseElement.cpp index acd8941b4e..89e70cb2bd 100644 --- a/dom/svg/SVGUseElement.cpp +++ b/dom/svg/SVGUseElement.cpp @@ -16,6 +16,11 @@ #include "nsIURI.h" #include "nsSVGEffects.h" +#include "nsDataHashtable.h" +#include "nsHashKeys.h" +#include "nsString.h" +#include "mozilla/dom/Element.h" + NS_IMPL_NS_NEW_NAMESPACED_SVG_ELEMENT(Use) namespace mozilla { @@ -518,5 +523,8 @@ SVGUseElement::IsAttributeMapped(const nsIAtom* name) const SVGUseElementBase::IsAttributeMapped(name); } +//cache svgs +static nsDataHashtable gIconSymbolCache; + } // namespace dom } // namespace mozilla diff --git a/js/src/vm/ArrayBufferObject.cpp b/js/src/vm/ArrayBufferObject.cpp index 7def8c7e1d..cb4f607505 100644 --- a/js/src/vm/ArrayBufferObject.cpp +++ b/js/src/vm/ArrayBufferObject.cpp @@ -3,6 +3,8 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include // SSE2 + #include "vm/ArrayBufferObject-inl.h" #include "vm/ArrayBufferObject.h" @@ -65,6 +67,58 @@ using mozilla::Nothing; using namespace js; using namespace js::gc; +// SSE2 version of memcpy_sse2_sse2 and memset_sse2_sse2 for faster JS n shit +static inline void +memcpy_sse2(void* dst, const void* src, size_t n) +{ + uint8_t* d = (uint8_t*)dst; + const uint8_t* s = (const uint8_t*)src; + + // Align to 16 bytes + while (((uintptr_t)d & 15) && n) { + *d++ = *s++; + n--; + } + + // 16‑byte chunks + while (n >= 16) { + __m128i v = _mm_loadu_si128((__m128i*)s); + _mm_storeu_si128((__m128i*)d, v); + s += 16; + d += 16; + n -= 16; + } + + // tail + while (n--) { + *d++ = *s++; + } +} + +static inline void +memset_sse2(void* dst, uint8_t value, size_t n) +{ + uint8_t* d = (uint8_t*)dst; + + // Align + while (((uintptr_t)d & 15) && n) { + *d++ = value; + n--; + } + + __m128i v = _mm_set1_epi8(value); + + while (n >= 16) { + _mm_storeu_si128((__m128i*)d, v); + d += 16; + n -= 16; + } + + while (n--) { + *d++ = value; + } +} + /* * Convert |v| to an array index for an array of length |length| per * the Typed Array Specification section 7.0, |subarray|. If successful, @@ -796,7 +850,7 @@ ArrayBufferObject::prepareForAsmJS(JSContext* cx, Handle buf } void* data = wasmBuf->dataPointer(); - memcpy(data, buffer->dataPointer(), length); + memcpy_sse2(data, buffer->dataPointer(), length); // Swap the new elements into the ArrayBufferObject. Mark the // ArrayBufferObject so we don't do this again. @@ -818,7 +872,7 @@ ArrayBufferObject::prepareForAsmJS(JSContext* cx, Handle buf BufferContents contents = AllocateArrayBufferContents(cx, buffer->byteLength()); if (!contents) return false; - memcpy(contents.data(), buffer->dataPointer(), buffer->byteLength()); + memcpy_sse2(contents.data(), buffer->dataPointer(), buffer->byteLength()); buffer->changeContents(cx, contents, OwnsData); } @@ -995,7 +1049,7 @@ ArrayBufferObject::wasmMovingGrowToSize(uint32_t newSize, BufferContents contents = BufferContents::create(newRawBuf->dataPointer()); newBuf->initialize(newSize, contents, OwnsData); - memcpy(newBuf->dataPointer(), oldBuf->dataPointer(), oldBuf->byteLength()); + memcpy_sse2(newBuf->dataPointer(), oldBuf->dataPointer(), oldBuf->byteLength()); ArrayBufferObject::detach(cx, oldBuf, BufferContents::createPlain(nullptr)); return true; } @@ -1097,7 +1151,7 @@ ArrayBufferObject::create(JSContext* cx, uint32_t nbytes, BufferContents content if (!contents) { void* data = obj->inlineDataPointer(); - memset(data, 0, nbytes); + memset_sse2(data, 0, nbytes); obj->initialize(nbytes, BufferContents::createPlain(data), DoesntOwnData); } else { obj->initialize(nbytes, contents, ownsState); @@ -1182,7 +1236,7 @@ ArrayBufferObject::externalizeContents(JSContext* cx, Handle BufferContents newContents = AllocateArrayBufferContents(cx, buffer->byteLength()); if (!newContents) return BufferContents::createPlain(nullptr); - memcpy(newContents.data(), contents.data(), buffer->byteLength()); + memcpy_sse2(newContents.data(), contents.data(), buffer->byteLength()); buffer->changeContents(cx, newContents, DoesntOwnData); return newContents; @@ -1217,7 +1271,7 @@ ArrayBufferObject::stealContents(JSContext* cx, Handle buffe return BufferContents::createPlain(nullptr); if (buffer->byteLength() > 0) - memcpy(contentsCopy.data(), oldContents.data(), buffer->byteLength()); + memcpy_sse2(contentsCopy.data(), oldContents.data(), buffer->byteLength()); ArrayBufferObject::detach(cx, buffer, oldContents); return contentsCopy; } @@ -1270,7 +1324,7 @@ ArrayBufferObject::copyData(Handle toBuffer, uint32_t toInde MOZ_ASSERT(fromBuffer->byteLength() >= fromIndex); MOZ_ASSERT(fromBuffer->byteLength() >= fromIndex + count); - memcpy(toBuffer->dataPointer() + toIndex, fromBuffer->dataPointer() + fromIndex, count); + memcpy_sse2(toBuffer->dataPointer() + toIndex, fromBuffer->dataPointer() + fromIndex, count); } /* static */ void diff --git a/js/src/vm/TypedArrayObject.cpp b/js/src/vm/TypedArrayObject.cpp index 232fde02d3..e3fec2f894 100644 --- a/js/src/vm/TypedArrayObject.cpp +++ b/js/src/vm/TypedArrayObject.cpp @@ -3,6 +3,8 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include // SSE2 + #include "vm/TypedArrayObject.h" #include "mozilla/Alignment.h" @@ -57,6 +59,59 @@ using JS::CanonicalizeNaN; using JS::ToInt32; using JS::ToUint32; +// SSE2 version of memcpy_sse2 and memset_sse2 for faster JS n shit +static inline void +memcpy_sse2(void* dst, const void* src, size_t n) +{ + uint8_t* d = (uint8_t*)dst; + const uint8_t* s = (const uint8_t*)src; + + // Align to 16 bytes + while (((uintptr_t)d & 15) && n) { + *d++ = *s++; + n--; + } + + // 16‑byte chunks + while (n >= 16) { + __m128i v = _mm_loadu_si128((__m128i*)s); + _mm_storeu_si128((__m128i*)d, v); + s += 16; + d += 16; + n -= 16; + } + + // tail + while (n--) { + *d++ = *s++; + } +} + +static inline void +memset_sse2(void* dst, uint8_t value, size_t n) +{ + uint8_t* d = (uint8_t*)dst; + + // Align + while (((uintptr_t)d & 15) && n) { + *d++ = value; + n--; + } + + __m128i v = _mm_set1_epi8(value); + + while (n >= 16) { + _mm_storeu_si128((__m128i*)d, v); + d += 16; + n -= 16; + } + + while (n--) { + *d++ = value; + } +} + + /* * TypedArrayObject * @@ -143,7 +198,7 @@ TypedArrayObject::ensureHasBuffer(JSContext* cx, Handle tarra return false; // tarray is not shared, because if it were it would have a buffer. - memcpy(buffer->dataPointer(), tarray->viewDataUnshared(), tarray->byteLength()); + memcpy_sse2(buffer->dataPointer(), tarray->viewDataUnshared(), tarray->byteLength()); // If the object is in the nursery, the buffer will be freed by the next // nursery GC. Free the data slot pointer if the object has no inline data. @@ -538,7 +593,7 @@ class TypedArrayObjectTemplate : public TypedArrayObject } else { void* data = obj->fixedData(FIXED_DATA_START); obj->initPrivate(data); - memset(data, 0, len * sizeof(NativeType)); + memset_sse2(data, 0, len * sizeof(NativeType)); #ifdef DEBUG if (len == 0) { uint8_t* elements = static_cast(data); @@ -667,7 +722,7 @@ class TypedArrayObjectTemplate : public TypedArrayObject void* data = tarray->fixedData(FIXED_DATA_START); tarray->initPrivate(data); - memset(data, 0, nbytes); + memset_sse2(data, 0, nbytes); } } @@ -704,7 +759,7 @@ class TypedArrayObjectTemplate : public TypedArrayObject return nullptr; } - memset(buf, 0, nbytes); + memset_sse2(buf, 0, nbytes); } RootedObject tmp(cx, NewObjectWithGroup(cx, group, allocKind, newKind)); @@ -2157,7 +2212,7 @@ struct DataViewIO static void fromBuffer(DataType* dest, const uint8_t* unalignedBuffer, bool wantSwap) { MOZ_ASSERT((reinterpret_cast(dest) & (Min(MOZ_ALIGNOF(void*), sizeof(DataType)) - 1)) == 0); - memcpy((void*) dest, unalignedBuffer, sizeof(ReadWriteType)); + memcpy_sse2((void*) dest, unalignedBuffer, sizeof(ReadWriteType)); if (wantSwap) { ReadWriteType* rwDest = reinterpret_cast(dest); *rwDest = swapBytes(*rwDest); @@ -2170,7 +2225,7 @@ struct DataViewIO ReadWriteType temp = *reinterpret_cast(src); if (wantSwap) temp = swapBytes(temp); - memcpy(unalignedBuffer, (void*) &temp, sizeof(ReadWriteType)); + memcpy_sse2(unalignedBuffer, (void*) &temp, sizeof(ReadWriteType)); } };