Branch: refs/heads/main
  Home:   https://github.com/WebKit/WebKit
  Commit: 55783b94e9df3e359b8f65c7a29e4f17899c0b7f
      
https://github.com/WebKit/WebKit/commit/55783b94e9df3e359b8f65c7a29e4f17899c0b7f
  Author: Yusuke Suzuki <[email protected]>
  Date:   2026-03-28 (Sat, 28 Mar 2026)

  Changed paths:
    M Source/JavaScriptCore/b3/B3LowerMacros.cpp
    M Source/JavaScriptCore/heap/PreciseAllocation.cpp
    M Source/JavaScriptCore/jit/AssemblyHelpers.cpp
    M Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm
    M Source/JavaScriptCore/llint/LowLevelInterpreter64.asm
    M Source/JavaScriptCore/runtime/JSObject.cpp
    M Source/JavaScriptCore/runtime/JSObject.h
    M Source/JavaScriptCore/runtime/JSObjectInlines.h
    M Source/JavaScriptCore/wasm/WasmBBQJIT64.cpp
    M Source/JavaScriptCore/wasm/WasmOMGIRGenerator.cpp
    M Source/JavaScriptCore/wasm/js/JSWebAssemblyArray.h
    M Source/JavaScriptCore/wasm/js/WebAssemblyGCObjectBase.h

  Log Message:
  -----------
  [JSC] Introduce butterfly-less objects
https://bugs.webkit.org/show_bug.cgi?id=310939
rdar://173551949

Reviewed by Mark Lam.

This patch introduces butterfly-less objects. Wasm GC objects have no
way to have any properties, and no way to have any [[Prototype]] etc.
This means that they never cause Structure transitions. And they never have
butterfly. However they are currently having m_butterfly field as it is
JSObject. But this is always nullptr and wasteful.

To make Wasm GC objects size compact, we introduce butterfly-less
objects. Now JSObject does not have m_butterfly. And we introduce a new
class, JSObjectWithButterfly, and it should be a base of all JS objects
types. And instead, WebAssemblyGCObjectBase is inheriting JSObject
directly, thus we no longer has m_butterfly field for them.

But to keep JSObject::butterfly() access very efficient, we implement
JSObject::butterfly in this way.

```
Butterfly* butterfly()
{
    auto* b = *std::bit_cast<Butterfly**>(std::bit_cast<char*>(this) + 
butterflyOffset());
    if (type() == WebAssemblyGCObjectType) [[unlikely]]
        b = nullptr;
    return b;
}
```

Regardless of whether it is WebAssemblyGCObjectBase type, we always load
butterfly field and change it to nullptr when type() is WebAssemblyGCObjectType.
Always loading m_butterfly field is safe since HeapCell atom size is
always >= 16 bytes, thus m_butterfly field (8 byte offset) is always accessible.
The above code makes sure that butterfly() call is branchless, and
type() is also on the same cache, so we will not get any performance
implication from this call.

JIT side of butterfly access does not need special case actually, as we
are always accessing them after doing some checks, like Structure,
indexing type. And WebAssemblyGCObjectBase cannot meet these checks so
we will not reach to the code which accesses to m_butterfly in JIT when
the object is WebAssemblyGCObjectBase.

* Source/JavaScriptCore/b3/B3LowerMacros.cpp:
* Source/JavaScriptCore/heap/PreciseAllocation.cpp:
* Source/JavaScriptCore/jit/AssemblyHelpers.cpp:
(JSC::AssemblyHelpers::loadProperty):
(JSC::AssemblyHelpers::storeProperty):
* Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm:
* Source/JavaScriptCore/llint/LowLevelInterpreter64.asm:
* Source/JavaScriptCore/runtime/JSObject.cpp:
(JSC::JSObjectWithButterfly::markAuxiliaryAndVisitOutOfLineProperties):
(JSC::JSObjectWithButterfly::visitButterfly):
(JSC::JSObjectWithButterfly::visitButterflyImpl):
(JSC::JSObject::estimatedSize):
(JSC::JSObject::visitChildrenImpl):
(JSC::JSObjectWithButterfly::visitChildrenImpl):
(JSC::JSFinalObject::visitChildrenImpl):
(JSC::JSObject::getOwnPropertySlotByIndex):
(JSC::JSObject::putByIndex):
(JSC::JSObject::enterDictionaryIndexingMode):
(JSC::JSObject::createInitialIndexedStorage):
(JSC::JSObject::createArrayStorage):
(JSC::JSObject::convertUndecidedToInt32):
(JSC::JSObject::convertUndecidedToDouble):
(JSC::JSObject::convertUndecidedToContiguous):
(JSC::JSObject::constructConvertedArrayStorageWithoutCopyingElements):
(JSC::JSObject::convertUndecidedToArrayStorage):
(JSC::JSObject::convertInt32ToDouble):
(JSC::JSObject::convertInt32ToContiguous):
(JSC::JSObject::convertInt32ToArrayStorage):
(JSC::JSObject::convertDoubleToContiguous):
(JSC::JSObject::convertDoubleToArrayStorage):
(JSC::JSObject::convertContiguousToArrayStorage):
(JSC::JSObject::convertFromCopyOnWrite):
(JSC::JSObject::setIndexQuicklyToUndecided):
(JSC::JSObject::tryMakeWritableInt32Slow):
(JSC::JSObject::tryMakeWritableDoubleSlow):
(JSC::JSObject::tryMakeWritableContiguousSlow):
(JSC::JSObject::ensureArrayStorageExistsAndEnterDictionaryIndexingMode):
(JSC::JSObject::deletePropertyByIndex):
(JSC::JSObject::getOwnIndexedPropertyNames):
(JSC::JSObject::defineOwnIndexedProperty):
(JSC::JSObject::putByIndexBeyondVectorLengthWithoutAttributes):
(JSC::JSObject::getNewVectorLength):
(JSC::JSObject::countElements):
(JSC::JSObject::ensureLengthSlow):
(JSC::JSObject::reallocateAndShrinkButterfly):
(JSC::JSObject::allocateMoreOutOfLineStorage):
(JSC::JSObject::getEnumerableLength):
(JSC::JSObject::putOwnDataPropertyBatching):
(JSC::JSObject::markAuxiliaryAndVisitOutOfLineProperties): Deleted.
(JSC::JSObject::visitButterfly): Deleted.
(JSC::JSObject::visitButterflyImpl): Deleted.
* Source/JavaScriptCore/runtime/JSObject.h:
(JSC::JSObject::getArrayLength const):
(JSC::JSObject::getVectorLength):
(JSC::JSObject::putDirectIndex):
(JSC::JSObject::setIndexQuickly):
(JSC::JSObject::hasSparseMap):
(JSC::JSObject::inSparseIndexingMode):
(JSC::JSObject::inlineStorageUnsafe const):
(JSC::JSObject::inlineStorageUnsafe):
(JSC::JSObject::outOfLineStorage const):
(JSC::JSObject::outOfLineStorage):
(JSC::JSObject::tryMakeWritableInt32):
(JSC::JSObject::tryMakeWritableDouble):
(JSC::JSObject::tryMakeWritableContiguous):
(JSC::JSObject::ensureArrayStorage):
(JSC::JSObject::butterflyOffset):
(JSC::JSObject::butterflyAddress):
(JSC::JSObject::JSObject):
(JSC::JSObject::arrayStorage):
(JSC::JSObject::arrayStorageOrNull):
(JSC::JSObject::ensureLength):
(JSC::JSObjectWithButterfly::fencedButterfly):
(JSC::JSObjectWithButterfly::outOfLineStorage const):
(JSC::JSObjectWithButterfly::outOfLineStorage):
(JSC::JSObjectWithButterfly::butterflyAddress):
(JSC::JSObjectWithButterfly::JSObjectWithButterfly):
(JSC::JSObject::offsetOfInlineStorage):
(JSC::JSNonFinalObject::JSNonFinalObject):
(JSC::JSObject::setStructure):
(JSC::JSObject::fencedButterfly): Deleted.
* Source/JavaScriptCore/runtime/JSObjectInlines.h:
(JSC::JSObject::setButterfly):
(JSC::JSObject::nukeStructureAndSetButterfly):
(JSC::JSObject::forEachOwnIndexedProperty):
(JSC::JSObject::initializeIndex):
(JSC::JSObject::initializeIndexWithoutBarrier):
(JSC::JSObject::canHaveExistingOwnIndexedGetterSetterProperties):
(JSC::JSObject::canHaveExistingOwnIndexedProperties const):
* Source/JavaScriptCore/wasm/WasmBBQJIT64.cpp:
(JSC::Wasm::BBQJITImpl::BBQJIT::emitAllocateGCArrayUninitialized):
(JSC::Wasm::BBQJITImpl::BBQJIT::emitAllocateGCStructUninitialized):
* Source/JavaScriptCore/wasm/WasmOMGIRGenerator.cpp:
(JSC::Wasm::OMGIRGenerator::allocateWasmGCObject):
* Source/JavaScriptCore/wasm/js/JSWebAssemblyArray.h:
* Source/JavaScriptCore/wasm/js/WebAssemblyGCObjectBase.h:

Canonical link: https://commits.webkit.org/310171@main



To unsubscribe from these emails, change your notification settings at 
https://github.com/WebKit/WebKit/settings/notifications

Reply via email to