From bdb1b7124aec3ca42a13dd13309df4c8e4e3cc64 Mon Sep 17 00:00:00 2001 From: Jarred Sumner Date: Tue, 13 Jun 2023 09:15:05 -0700 Subject: Fix crash in CJS (#3294) * Fix crash in CJS * Add std.heap.ArenaAllocator * Use our arena allocator * Reduce JS parser memory usage and make HMR faster * Write some comments * fix test failure & clean up this code * Update javascript.zig * make arena usage safer --------- Co-authored-by: Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com> --- src/bun.js/bindings/ZigSourceProvider.cpp | 95 +++++++++++++++++-------------- 1 file changed, 51 insertions(+), 44 deletions(-) (limited to 'src/bun.js/bindings/ZigSourceProvider.cpp') diff --git a/src/bun.js/bindings/ZigSourceProvider.cpp b/src/bun.js/bindings/ZigSourceProvider.cpp index 7b3a8ffbc..d42d6b445 100644 --- a/src/bun.js/bindings/ZigSourceProvider.cpp +++ b/src/bun.js/bindings/ZigSourceProvider.cpp @@ -5,6 +5,7 @@ #include "ZigSourceProvider.h" #include "JavaScriptCore/BytecodeCacheError.h" +#include "ZigGlobalObject.h" #include "JavaScriptCore/Completion.h" #include "wtf/Scope.h" @@ -26,67 +27,73 @@ using SourceOrigin = JSC::SourceOrigin; using String = WTF::String; using SourceProviderSourceType = JSC::SourceProviderSourceType; -Ref SourceProvider::create(ResolvedSource resolvedSource) +static uintptr_t getSourceProviderMapKey(ResolvedSource& resolvedSource) { - void* allocator = resolvedSource.allocator; + switch (resolvedSource.source_code.tag) { + case BunStringTag::WTFStringImpl: { + return (uintptr_t)resolvedSource.source_code.impl.wtf->characters8(); + } + case BunStringTag::StaticZigString: + case BunStringTag::ZigString: { + return (uintptr_t)Zig::untag(resolvedSource.source_code.impl.zig.ptr); + } + default: { + return 0; + } + } +} - JSC::SourceProviderSourceType sourceType = JSC::SourceProviderSourceType::Module; +Ref SourceProvider::create(Zig::GlobalObject* globalObject, ResolvedSource resolvedSource, JSC::SourceProviderSourceType sourceType) +{ - // // JSC owns the memory - // if (resolvedSource.hash == 1) { - // return adoptRef(*new SourceProvider( - // resolvedSource, WTF::StringImpl::create(resolvedSource.source_code.ptr, resolvedSource.source_code.len), - // JSC::SourceOrigin(WTF::URL::fileURLWithFileSystemPath(toString(resolvedSource.source_url))), - // toStringNotConst(resolvedSource.source_url).isolatedCopy(), TextPosition(), - // sourceType)); - // } + uintptr_t providerKey = 0; + if (globalObject->isThreadLocalDefaultGlobalObject) { + auto& sourceProviderMap = globalObject->sourceProviderMap; + providerKey = getSourceProviderMapKey(resolvedSource); + if (providerKey) { + auto sourceProvider = sourceProviderMap.get(providerKey); + if (sourceProvider != nullptr) { + sourceProvider->ref(); + return adoptRef(*reinterpret_cast(sourceProvider)); + } + } + } + auto stringImpl = Bun::toWTFString(resolvedSource.source_code); + + if (stringImpl.impl()->refCount() > 1) + // Deref because we don't call a destructor for BunString + stringImpl.impl()->deref(); - if (allocator) { - Ref stringImpl_ = WTF::ExternalStringImpl::create( - resolvedSource.source_code.ptr, resolvedSource.source_code.len, - allocator, - RefString__free); - return adoptRef(*new SourceProvider( - resolvedSource, stringImpl_, - JSC::SourceOrigin(WTF::URL::fileURLWithFileSystemPath(toString(resolvedSource.source_url))), - toStringNotConst(resolvedSource.source_url), TextPosition(), - sourceType)); - } else { - Ref stringImpl_ = WTF::ExternalStringImpl::createStatic( - resolvedSource.source_code.ptr, resolvedSource.source_code.len); - return adoptRef(*new SourceProvider( - resolvedSource, stringImpl_, - JSC::SourceOrigin(WTF::URL::fileURLWithFileSystemPath(toString(resolvedSource.source_url))), - toStringNotConst(resolvedSource.source_url), TextPosition(), - sourceType)); + auto provider = adoptRef(*new SourceProvider( + globalObject->isThreadLocalDefaultGlobalObject ? globalObject : nullptr, + resolvedSource, stringImpl.releaseImpl().releaseNonNull(), + JSC::SourceOrigin(WTF::URL::fileURLWithFileSystemPath(toString(resolvedSource.source_url))), + toStringNotConst(resolvedSource.source_url), TextPosition(), + sourceType)); + + if (providerKey) { + globalObject->sourceProviderMap.set(providerKey, provider.copyRef()); } + + return provider; } -unsigned SourceProvider::getHash() +unsigned SourceProvider::hash() const { if (m_hash) { return m_hash; } - m_hash = WTF::StringHash::hash(m_source.get()); - return m_hash; + return m_source->hash(); } void SourceProvider::freeSourceCode() { - if (did_free_source_code) { - return; + if (m_globalObjectForSourceProviderMap) { + m_globalObjectForSourceProviderMap->sourceProviderMap.remove((uintptr_t)m_source.get().characters8()); } - did_free_source_code = true; - if (m_resolvedSource.allocator != 0) { // // WTF::ExternalStringImpl::destroy(m_source.ptr()); - this->m_source = WTF::StringImpl::empty()->isolatedCopy(); - this->m_hash = 0; - m_resolvedSource.allocator = 0; - } - // if (m_resolvedSource.allocator != 0) { - // ZigString__free(m_resolvedSource.source_code.ptr, m_resolvedSource.source_code.len, - // m_resolvedSource.allocator); - // } + + m_source = *WTF::StringImpl::empty(); } void SourceProvider::updateCache(const UnlinkedFunctionExecutable* executable, const SourceCode&, -- cgit v1.2.3