Compare commits

...

3 Commits

Author SHA1 Message Date
Jarred Sumner
ce66b75029 Merge branch 'main' into jarred/big-strings-free-sooner 2025-04-13 09:10:07 -07:00
Jarred Sumner
0b74025a94 Update SetupWebKit.cmake 2025-04-12 03:08:09 -07:00
Jarred Sumner
0aad941495 Make big strings free sooner 2025-04-12 02:25:44 -07:00
5 changed files with 78 additions and 34 deletions

View File

@@ -2,7 +2,7 @@ option(WEBKIT_VERSION "The version of WebKit to use")
option(WEBKIT_LOCAL "If a local version of WebKit should be used instead of downloading")
if(NOT WEBKIT_VERSION)
set(WEBKIT_VERSION 06820714a7990ea77c78157f9eeaabaf56c2098a)
set(WEBKIT_VERSION 2670e34a05342ce98fad07d191aca3f8e6fb2760)
endif()
string(SUBSTRING ${WEBKIT_VERSION} 0 16 WEBKIT_VERSION_PREFIX)

View File

@@ -41,6 +41,19 @@
extern "C" void mi_free(void* ptr);
bool isStringEligibleForEarlyFree(const WTF::StringImpl& impl)
{
return impl.isExternal() && !impl.isStatic() && impl.sizeInBytes() > 1024 * 128;
}
JSC::JSString* jsStringFreeEarly(JSC::VM& vm, WTF::String&& input)
{
ASSERT(isStringEligibleForEarlyFree(*input.impl()));
auto* str = jsString(vm, WTFMove(input));
vm.heap.registerLargeString(str);
return str;
}
using namespace JSC;
extern "C" BunString BunString__fromBytes(const char* bytes, size_t length);
@@ -126,11 +139,17 @@ extern "C" JSC::EncodedJSValue BunString__transferToJS(BunString* bunString, JSC
#endif
bunString->impl.wtf->deref();
*bunString = { .tag = BunStringTag::Dead };
if (!str.isEmpty() && isStringEligibleForEarlyFree(*str.impl())) {
return JSValue::encode(jsStringFreeEarly(vm, WTFMove(str)));
}
return JSValue::encode(jsString(vm, WTFMove(str)));
}
WTF::String str = bunString->toWTFString();
*bunString = { .tag = BunStringTag::Dead };
if (!str.isEmpty() && isStringEligibleForEarlyFree(*str.impl())) {
return JSValue::encode(jsStringFreeEarly(vm, WTFMove(str)));
}
return JSValue::encode(jsString(vm, WTFMove(str)));
}

View File

@@ -5,6 +5,13 @@
#include <wtf/text/WTFString.h>
#include <wtf/text/CString.h>
namespace JSC {
class JSString;
class VM;
}
JSC::JSString* jsStringFreeEarly(JSC::VM& vm, WTF::String&& input);
bool isStringEligibleForEarlyFree(const WTF::StringImpl& impl);
namespace Bun {
class UTF8View {
public:

View File

@@ -131,7 +131,7 @@
#include <JavaScriptCore/VMInlines.h>
#include "wtf-bindings.h"
#include "BunString.h"
#if OS(DARWIN)
#if BUN_DEBUG
#if !__has_feature(address_sanitizer)
@@ -3043,8 +3043,13 @@ JSC__JSValue ZigString__toExternalU16(const uint16_t* arg0, size_t len, JSC__JSG
auto ref = String(ExternalStringImpl::create({ reinterpret_cast<const UChar*>(arg0), len }, reinterpret_cast<void*>(const_cast<uint16_t*>(arg0)), free_global_string));
return JSC::JSValue::encode(JSC::JSValue(JSC::jsString(
global->vm(), WTFMove(ref))));
if (isStringEligibleForEarlyFree(*ref.impl())) {
return JSC::JSValue::encode(jsStringFreeEarly(global->vm(), WTFMove(ref)));
}
auto* str = JSC::jsString(global->vm(), WTFMove(ref));
return JSC::JSValue::encode(JSC::JSValue(str));
}
// This must be a globally allocated string
JSC__JSValue ZigString__toExternalValue(const ZigString* arg0, JSC__JSGlobalObject* arg1)
@@ -3055,17 +3060,16 @@ JSC__JSValue ZigString__toExternalValue(const ZigString* arg0, JSC__JSGlobalObje
return JSC::JSValue::encode(JSC::jsEmptyString(arg1->vm()));
}
if (Zig::isTaggedUTF16Ptr(str.ptr)) {
auto ref = String(ExternalStringImpl::create({ reinterpret_cast<const UChar*>(Zig::untag(str.ptr)), str.len }, Zig::untagVoid(str.ptr), free_global_string));
auto ref = Zig::isTaggedUTF16Ptr(str.ptr)
? String(ExternalStringImpl::create({ reinterpret_cast<const UChar*>(Zig::untag(str.ptr)), str.len }, Zig::untagVoid(str.ptr), free_global_string))
: String(ExternalStringImpl::create({ Zig::untag(str.ptr), str.len }, Zig::untagVoid(str.ptr), free_global_string));
return JSC::JSValue::encode(JSC::JSValue(JSC::jsString(
arg1->vm(), WTFMove(ref))));
} else {
auto ref = String(ExternalStringImpl::create({ Zig::untag(str.ptr), str.len }, Zig::untagVoid(str.ptr), free_global_string));
return JSC::JSValue::encode(JSC::JSValue(JSC::jsString(
arg1->vm(),
WTFMove(ref))));
if (!ref.isEmpty() && isStringEligibleForEarlyFree(*ref.impl())) {
return JSC::JSValue::encode(jsStringFreeEarly(arg1->vm(), WTFMove(ref)));
}
return JSC::JSValue::encode(JSC::JSValue(JSC::jsString(
arg1->vm(), WTFMove(ref))));
}
VirtualMachine* JSC__JSGlobalObject__bunVM(JSC__JSGlobalObject* arg0)
@@ -3109,17 +3113,18 @@ void JSC__JSValue__toZigString(JSC__JSValue JSValue0, ZigString* arg1, JSC__JSGl
JSC__JSValue ZigString__external(const ZigString* arg0, JSC__JSGlobalObject* arg1, void* arg2, void (*ArgFn3)(void* arg0, void* arg1, size_t arg2))
{
ZigString str
= *arg0;
if (Zig::isTaggedUTF16Ptr(str.ptr)) {
return JSC::JSValue::encode(JSC::JSValue(JSC::jsString(
arg1->vm(),
WTF::String(ExternalStringImpl::create({ reinterpret_cast<const UChar*>(Zig::untag(str.ptr)), str.len }, arg2, ArgFn3)))));
} else {
return JSC::JSValue::encode(JSC::JSValue(JSC::jsString(
arg1->vm(),
WTF::String(ExternalStringImpl::create({ reinterpret_cast<const LChar*>(Zig::untag(str.ptr)), str.len }, arg2, ArgFn3)))));
ZigString str = *arg0;
auto ref = Zig::isTaggedUTF16Ptr(str.ptr)
? String(ExternalStringImpl::create({ reinterpret_cast<const UChar*>(Zig::untag(str.ptr)), str.len }, arg2, ArgFn3))
: String(ExternalStringImpl::create({ Zig::untag(str.ptr), str.len }, arg2, ArgFn3));
if (!ref.isEmpty() && isStringEligibleForEarlyFree(*ref.impl())) {
return JSC::JSValue::encode(jsStringFreeEarly(arg1->vm(), WTFMove(ref)));
}
return JSC::JSValue::encode(JSC::JSValue(JSC::jsString(
arg1->vm(),
WTFMove(ref))));
}
JSC__JSValue ZigString__toExternalValueWithCallback(const ZigString* arg0, JSC__JSGlobalObject* arg1, void (*ArgFn2)(void* arg2, void* arg0, size_t arg1))
@@ -3127,15 +3132,15 @@ JSC__JSValue ZigString__toExternalValueWithCallback(const ZigString* arg0, JSC__
ZigString str
= *arg0;
if (Zig::isTaggedUTF16Ptr(str.ptr)) {
return JSC::JSValue::encode(JSC::JSValue(JSC::jsOwnedString(
arg1->vm(),
WTF::String(ExternalStringImpl::create({ reinterpret_cast<const UChar*>(Zig::untag(str.ptr)), str.len }, nullptr, ArgFn2)))));
} else {
return JSC::JSValue::encode(JSC::JSValue(JSC::jsOwnedString(
arg1->vm(),
WTF::String(ExternalStringImpl::create({ reinterpret_cast<const LChar*>(Zig::untag(str.ptr)), str.len }, nullptr, ArgFn2)))));
auto ref = Zig::isTaggedUTF16Ptr(str.ptr)
? String(ExternalStringImpl::create({ reinterpret_cast<const UChar*>(Zig::untag(str.ptr)), str.len }, nullptr, ArgFn2))
: String(ExternalStringImpl::create({ Zig::untag(str.ptr), str.len }, nullptr, ArgFn2));
if (!ref.isEmpty() && isStringEligibleForEarlyFree(*ref.impl())) {
return JSC::JSValue::encode(jsStringFreeEarly(arg1->vm(), WTFMove(ref)));
}
return JSC::JSValue::encode(JSC::jsString(arg1->vm(), WTFMove(ref)));
}
JSC__JSValue ZigString__toErrorInstance(const ZigString* str, JSC__JSGlobalObject* globalObject)

View File

@@ -75,7 +75,7 @@
#include <JavaScriptCore/BuiltinNames.h>
#include <wtf/TZoneMallocInlines.h>
#include "AsyncContextFrame.h"
#include "BunString.h"
using namespace JSC;
using namespace Zig;
@@ -772,7 +772,14 @@ node_api_create_external_string_latin1(napi_env env,
});
Zig::GlobalObject* globalObject = toJS(env);
JSString* out = JSC::jsString(JSC::getVM(globalObject), WTF::String(WTFMove(impl)));
auto& vm = JSC::getVM(globalObject);
JSString* out;
if (isStringEligibleForEarlyFree(impl)) {
out = jsStringFreeEarly(vm, WTF::String(WTFMove(impl)));
} else {
out = JSC::jsString(vm, WTF::String(WTFMove(impl)));
}
ensureStillAliveHere(out);
*result = toNapi(out, globalObject);
ensureStillAliveHere(out);
@@ -807,8 +814,14 @@ node_api_create_external_string_utf16(napi_env env,
env->doFinalizer(finalize_callback, str, hint);
});
Zig::GlobalObject* globalObject = toJS(env);
auto& vm = JSC::getVM(globalObject);
JSString* out = JSC::jsString(JSC::getVM(globalObject), WTF::String(WTFMove(impl)));
JSString* out;
if (isStringEligibleForEarlyFree(impl)) {
out = jsStringFreeEarly(vm, WTF::String(WTFMove(impl)));
} else {
out = JSC::jsString(vm, WTF::String(WTFMove(impl)));
}
ensureStillAliveHere(out);
*result = toNapi(out, globalObject);
ensureStillAliveHere(out);