Add SSE2 for memcpy and memuse. caching SVGs too cuz why not

This commit is contained in:
ownedbywuigi 2026-03-27 10:45:45 +00:00
commit 81e2ff2fe2
4 changed files with 133 additions and 13 deletions

3
.vscode/settings.json vendored Normal file
View file

@ -0,0 +1,3 @@
{
"git.ignoreLimitWarning": true
}

View file

@ -16,6 +16,11 @@
#include "nsIURI.h" #include "nsIURI.h"
#include "nsSVGEffects.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) NS_IMPL_NS_NEW_NAMESPACED_SVG_ELEMENT(Use)
namespace mozilla { namespace mozilla {
@ -518,5 +523,8 @@ SVGUseElement::IsAttributeMapped(const nsIAtom* name) const
SVGUseElementBase::IsAttributeMapped(name); SVGUseElementBase::IsAttributeMapped(name);
} }
//cache svgs
static nsDataHashtable<nsStringHashKey, Element*> gIconSymbolCache;
} // namespace dom } // namespace dom
} // namespace mozilla } // namespace mozilla

View file

@ -3,6 +3,8 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <emmintrin.h> // SSE2
#include "vm/ArrayBufferObject-inl.h" #include "vm/ArrayBufferObject-inl.h"
#include "vm/ArrayBufferObject.h" #include "vm/ArrayBufferObject.h"
@ -65,6 +67,58 @@ using mozilla::Nothing;
using namespace js; using namespace js;
using namespace js::gc; 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 * Convert |v| to an array index for an array of length |length| per
* the Typed Array Specification section 7.0, |subarray|. If successful, * the Typed Array Specification section 7.0, |subarray|. If successful,
@ -796,7 +850,7 @@ ArrayBufferObject::prepareForAsmJS(JSContext* cx, Handle<ArrayBufferObject*> buf
} }
void* data = wasmBuf->dataPointer(); void* data = wasmBuf->dataPointer();
memcpy(data, buffer->dataPointer(), length); memcpy_sse2(data, buffer->dataPointer(), length);
// Swap the new elements into the ArrayBufferObject. Mark the // Swap the new elements into the ArrayBufferObject. Mark the
// ArrayBufferObject so we don't do this again. // ArrayBufferObject so we don't do this again.
@ -818,7 +872,7 @@ ArrayBufferObject::prepareForAsmJS(JSContext* cx, Handle<ArrayBufferObject*> buf
BufferContents contents = AllocateArrayBufferContents(cx, buffer->byteLength()); BufferContents contents = AllocateArrayBufferContents(cx, buffer->byteLength());
if (!contents) if (!contents)
return false; return false;
memcpy(contents.data(), buffer->dataPointer(), buffer->byteLength()); memcpy_sse2(contents.data(), buffer->dataPointer(), buffer->byteLength());
buffer->changeContents(cx, contents, OwnsData); buffer->changeContents(cx, contents, OwnsData);
} }
@ -995,7 +1049,7 @@ ArrayBufferObject::wasmMovingGrowToSize(uint32_t newSize,
BufferContents contents = BufferContents::create<WASM>(newRawBuf->dataPointer()); BufferContents contents = BufferContents::create<WASM>(newRawBuf->dataPointer());
newBuf->initialize(newSize, contents, OwnsData); 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)); ArrayBufferObject::detach(cx, oldBuf, BufferContents::createPlain(nullptr));
return true; return true;
} }
@ -1097,7 +1151,7 @@ ArrayBufferObject::create(JSContext* cx, uint32_t nbytes, BufferContents content
if (!contents) { if (!contents) {
void* data = obj->inlineDataPointer(); void* data = obj->inlineDataPointer();
memset(data, 0, nbytes); memset_sse2(data, 0, nbytes);
obj->initialize(nbytes, BufferContents::createPlain(data), DoesntOwnData); obj->initialize(nbytes, BufferContents::createPlain(data), DoesntOwnData);
} else { } else {
obj->initialize(nbytes, contents, ownsState); obj->initialize(nbytes, contents, ownsState);
@ -1182,7 +1236,7 @@ ArrayBufferObject::externalizeContents(JSContext* cx, Handle<ArrayBufferObject*>
BufferContents newContents = AllocateArrayBufferContents(cx, buffer->byteLength()); BufferContents newContents = AllocateArrayBufferContents(cx, buffer->byteLength());
if (!newContents) if (!newContents)
return BufferContents::createPlain(nullptr); return BufferContents::createPlain(nullptr);
memcpy(newContents.data(), contents.data(), buffer->byteLength()); memcpy_sse2(newContents.data(), contents.data(), buffer->byteLength());
buffer->changeContents(cx, newContents, DoesntOwnData); buffer->changeContents(cx, newContents, DoesntOwnData);
return newContents; return newContents;
@ -1217,7 +1271,7 @@ ArrayBufferObject::stealContents(JSContext* cx, Handle<ArrayBufferObject*> buffe
return BufferContents::createPlain(nullptr); return BufferContents::createPlain(nullptr);
if (buffer->byteLength() > 0) if (buffer->byteLength() > 0)
memcpy(contentsCopy.data(), oldContents.data(), buffer->byteLength()); memcpy_sse2(contentsCopy.data(), oldContents.data(), buffer->byteLength());
ArrayBufferObject::detach(cx, buffer, oldContents); ArrayBufferObject::detach(cx, buffer, oldContents);
return contentsCopy; return contentsCopy;
} }
@ -1270,7 +1324,7 @@ ArrayBufferObject::copyData(Handle<ArrayBufferObject*> toBuffer, uint32_t toInde
MOZ_ASSERT(fromBuffer->byteLength() >= fromIndex); MOZ_ASSERT(fromBuffer->byteLength() >= fromIndex);
MOZ_ASSERT(fromBuffer->byteLength() >= fromIndex + count); 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 /* static */ void

View file

@ -3,6 +3,8 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this * 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/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <emmintrin.h> // SSE2
#include "vm/TypedArrayObject.h" #include "vm/TypedArrayObject.h"
#include "mozilla/Alignment.h" #include "mozilla/Alignment.h"
@ -57,6 +59,59 @@ using JS::CanonicalizeNaN;
using JS::ToInt32; using JS::ToInt32;
using JS::ToUint32; 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 * TypedArrayObject
* *
@ -143,7 +198,7 @@ TypedArrayObject::ensureHasBuffer(JSContext* cx, Handle<TypedArrayObject*> tarra
return false; return false;
// tarray is not shared, because if it were it would have a buffer. // 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 // 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. // nursery GC. Free the data slot pointer if the object has no inline data.
@ -538,7 +593,7 @@ class TypedArrayObjectTemplate : public TypedArrayObject
} else { } else {
void* data = obj->fixedData(FIXED_DATA_START); void* data = obj->fixedData(FIXED_DATA_START);
obj->initPrivate(data); obj->initPrivate(data);
memset(data, 0, len * sizeof(NativeType)); memset_sse2(data, 0, len * sizeof(NativeType));
#ifdef DEBUG #ifdef DEBUG
if (len == 0) { if (len == 0) {
uint8_t* elements = static_cast<uint8_t*>(data); uint8_t* elements = static_cast<uint8_t*>(data);
@ -667,7 +722,7 @@ class TypedArrayObjectTemplate : public TypedArrayObject
void* data = tarray->fixedData(FIXED_DATA_START); void* data = tarray->fixedData(FIXED_DATA_START);
tarray->initPrivate(data); tarray->initPrivate(data);
memset(data, 0, nbytes); memset_sse2(data, 0, nbytes);
} }
} }
@ -704,7 +759,7 @@ class TypedArrayObjectTemplate : public TypedArrayObject
return nullptr; return nullptr;
} }
memset(buf, 0, nbytes); memset_sse2(buf, 0, nbytes);
} }
RootedObject tmp(cx, NewObjectWithGroup<TypedArrayObject>(cx, group, allocKind, newKind)); RootedObject tmp(cx, NewObjectWithGroup<TypedArrayObject>(cx, group, allocKind, newKind));
@ -2157,7 +2212,7 @@ struct DataViewIO
static void fromBuffer(DataType* dest, const uint8_t* unalignedBuffer, bool wantSwap) static void fromBuffer(DataType* dest, const uint8_t* unalignedBuffer, bool wantSwap)
{ {
MOZ_ASSERT((reinterpret_cast<uintptr_t>(dest) & (Min<size_t>(MOZ_ALIGNOF(void*), sizeof(DataType)) - 1)) == 0); MOZ_ASSERT((reinterpret_cast<uintptr_t>(dest) & (Min<size_t>(MOZ_ALIGNOF(void*), sizeof(DataType)) - 1)) == 0);
memcpy((void*) dest, unalignedBuffer, sizeof(ReadWriteType)); memcpy_sse2((void*) dest, unalignedBuffer, sizeof(ReadWriteType));
if (wantSwap) { if (wantSwap) {
ReadWriteType* rwDest = reinterpret_cast<ReadWriteType*>(dest); ReadWriteType* rwDest = reinterpret_cast<ReadWriteType*>(dest);
*rwDest = swapBytes(*rwDest); *rwDest = swapBytes(*rwDest);
@ -2170,7 +2225,7 @@ struct DataViewIO
ReadWriteType temp = *reinterpret_cast<const ReadWriteType*>(src); ReadWriteType temp = *reinterpret_cast<const ReadWriteType*>(src);
if (wantSwap) if (wantSwap)
temp = swapBytes(temp); temp = swapBytes(temp);
memcpy(unalignedBuffer, (void*) &temp, sizeof(ReadWriteType)); memcpy_sse2(unalignedBuffer, (void*) &temp, sizeof(ReadWriteType));
} }
}; };