From b510f83b206915a3214a223c3b10d7cb2f674b5d Mon Sep 17 00:00:00 2001 From: Jarred Sumner Date: Fri, 27 Dec 2024 15:32:04 -0800 Subject: [PATCH 1/5] Make creating errors slightly faster --- src/bun.js/bindings/BunCommonStrings.cpp | 8 ++++++++ src/bun.js/bindings/BunCommonStrings.h | 10 +++++++++- src/bun.js/bindings/bindings.cpp | 22 ++++++++++++---------- 3 files changed, 29 insertions(+), 11 deletions(-) diff --git a/src/bun.js/bindings/BunCommonStrings.cpp b/src/bun.js/bindings/BunCommonStrings.cpp index c0327ca6e7e4a4..6cbeefaf53731c 100644 --- a/src/bun.js/bindings/BunCommonStrings.cpp +++ b/src/bun.js/bindings/BunCommonStrings.cpp @@ -20,17 +20,25 @@ using namespace JSC; init.set(jsOwnedString(init.vm, name.string())); \ }); +#define BUN_COMMON_STRINGS_LAZY_PROPERTY_DEFINITION_NOT_BUILTIN_NAMES(jsName) \ + this->m_commonString_##jsName.initLater( \ + [](const JSC::LazyProperty::Initializer& init) { \ + init.set(jsOwnedString(init.vm, #jsName##_s)); \ + }); + #define BUN_COMMON_STRINGS_LAZY_PROPERTY_VISITOR(name) this->m_commonString_##name.visit(visitor); void CommonStrings::initialize() { BUN_COMMON_STRINGS_EACH_NAME(BUN_COMMON_STRINGS_LAZY_PROPERTY_DEFINITION) + BUN_COMMON_STRINGS_EACH_NAME_NOT_BUILTIN_NAMES(BUN_COMMON_STRINGS_LAZY_PROPERTY_DEFINITION_NOT_BUILTIN_NAMES) } template void CommonStrings::visit(Visitor& visitor) { BUN_COMMON_STRINGS_EACH_NAME(BUN_COMMON_STRINGS_LAZY_PROPERTY_VISITOR) + BUN_COMMON_STRINGS_EACH_NAME_NOT_BUILTIN_NAMES(BUN_COMMON_STRINGS_LAZY_PROPERTY_VISITOR) } template void CommonStrings::visit(JSC::AbstractSlotVisitor&); diff --git a/src/bun.js/bindings/BunCommonStrings.h b/src/bun.js/bindings/BunCommonStrings.h index 667ee5b21b48af..0abd69c1dbb35a 100644 --- a/src/bun.js/bindings/BunCommonStrings.h +++ b/src/bun.js/bindings/BunCommonStrings.h @@ -1,10 +1,17 @@ #pragma once // clang-format off +// The items in this list must also be present in BunBuiltinNames.h +// If we use it as an identifier name in hot code, we should put it in this list. #define BUN_COMMON_STRINGS_EACH_NAME(macro) \ macro(require) \ macro(resolve) \ macro(mockedFunction) + +// These ones don't need to be in BunBuiltinNames.h +// If we don't use it as an identifier name, but we want to avoid allocating the string frequently, put it in this list. +#define BUN_COMMON_STRINGS_EACH_NAME_NOT_BUILTIN_NAMES(macro) \ + macro(SystemError) // clang-format on #define BUN_COMMON_STRINGS_ACCESSOR_DEFINITION(name) \ @@ -21,7 +28,7 @@ namespace Bun { class CommonStrings { public: BUN_COMMON_STRINGS_EACH_NAME(BUN_COMMON_STRINGS_ACCESSOR_DEFINITION) - + BUN_COMMON_STRINGS_EACH_NAME_NOT_BUILTIN_NAMES(BUN_COMMON_STRINGS_ACCESSOR_DEFINITION) void initialize(); template @@ -29,6 +36,7 @@ class CommonStrings { private: BUN_COMMON_STRINGS_EACH_NAME(BUN_COMMON_STRINGS_LAZY_PROPERTY_DECLARATION) + BUN_COMMON_STRINGS_EACH_NAME_NOT_BUILTIN_NAMES(BUN_COMMON_STRINGS_LAZY_PROPERTY_DECLARATION) }; } // namespace Bun diff --git a/src/bun.js/bindings/bindings.cpp b/src/bun.js/bindings/bindings.cpp index 45fb786707bbeb..7840f0acf04519 100644 --- a/src/bun.js/bindings/bindings.cpp +++ b/src/bun.js/bindings/bindings.cpp @@ -1,6 +1,8 @@ + #include "root.h" +#include "JavaScriptCore/ErrorType.h" #include "JavaScriptCore/CatchScope.h" #include "JavaScriptCore/Exception.h" #include "ErrorCode+List.h" @@ -1941,45 +1943,45 @@ JSC__JSValue SystemError__toErrorInstance(const SystemError* arg0, message = Bun::toJS(globalObject, err.message); } + auto& names = WebCore::builtinNames(vm); + JSC::JSValue options = JSC::jsUndefined(); - JSC::JSObject* result - = JSC::ErrorInstance::create(globalObject, JSC::ErrorInstance::createStructure(vm, globalObject, globalObject->errorPrototype()), message, options); - - auto clientData = WebCore::clientData(vm); + JSC::JSObject* result = JSC::ErrorInstance::create(globalObject, globalObject->errorStructureWithErrorType(), message, options); if (err.code.tag != BunStringTag::Empty) { JSC::JSValue code = Bun::toJS(globalObject, err.code); - result->putDirect(vm, clientData->builtinNames().codePublicName(), code, + result->putDirect(vm, names.codePublicName(), code, JSC::PropertyAttribute::DontDelete | 0); result->putDirect(vm, vm.propertyNames->name, code, JSC::PropertyAttribute::DontEnum | 0); } else { + auto* domGlobalObject = defaultGlobalObject(globalObject); result->putDirect( vm, vm.propertyNames->name, - JSC::JSValue(jsString(vm, String("SystemError"_s))), + JSC::JSValue(domGlobalObject->commonStrings().SystemErrorString(domGlobalObject)), JSC::PropertyAttribute::DontEnum | 0); } if (err.path.tag != BunStringTag::Empty) { JSC::JSValue path = Bun::toJS(globalObject, err.path); - result->putDirect(vm, clientData->builtinNames().pathPublicName(), path, + result->putDirect(vm, names.pathPublicName(), path, JSC::PropertyAttribute::DontDelete | 0); } if (err.fd != -1) { JSC::JSValue fd = JSC::JSValue(jsNumber(err.fd)); - result->putDirect(vm, JSC::Identifier::fromString(vm, "fd"_s), fd, + result->putDirect(vm, names.fdPublicName(), fd, JSC::PropertyAttribute::DontDelete | 0); } if (err.syscall.tag != BunStringTag::Empty) { JSC::JSValue syscall = Bun::toJS(globalObject, err.syscall); - result->putDirect(vm, clientData->builtinNames().syscallPublicName(), syscall, + result->putDirect(vm, names.syscallPublicName(), syscall, JSC::PropertyAttribute::DontDelete | 0); } - result->putDirect(vm, clientData->builtinNames().errnoPublicName(), JSC::JSValue(err.errno_), + result->putDirect(vm, names.errnoPublicName(), JSC::JSValue(err.errno_), JSC::PropertyAttribute::DontDelete | 0); RETURN_IF_EXCEPTION(scope, {}); From 7dc93da62552e781a68846de812cc9201e85eaf8 Mon Sep 17 00:00:00 2001 From: Jarred Sumner Date: Fri, 27 Dec 2024 17:57:21 -0800 Subject: [PATCH 2/5] Bump --- cmake/tools/SetupWebKit.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/tools/SetupWebKit.cmake b/cmake/tools/SetupWebKit.cmake index b876c54da52e4d..f575ad3c974715 100644 --- a/cmake/tools/SetupWebKit.cmake +++ b/cmake/tools/SetupWebKit.cmake @@ -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 3845bf370ff4e9a5c0b96036255142c7904be963) + set(WEBKIT_VERSION 1a615a40e7f556af1497bd50324249a68e3a2894) endif() if(WEBKIT_LOCAL) From 5d31c79a7a1fc9f091595e8d8c328932971f9904 Mon Sep 17 00:00:00 2001 From: Jarred Sumner Date: Fri, 27 Dec 2024 18:59:39 -0800 Subject: [PATCH 3/5] ram --- cmake/tools/SetupWebKit.cmake | 2 +- src/bun.js/modules/BunJSCModule.h | 22 +++++++++++++++++++++- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/cmake/tools/SetupWebKit.cmake b/cmake/tools/SetupWebKit.cmake index f575ad3c974715..422ff8da6d826f 100644 --- a/cmake/tools/SetupWebKit.cmake +++ b/cmake/tools/SetupWebKit.cmake @@ -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 1a615a40e7f556af1497bd50324249a68e3a2894) + set(WEBKIT_VERSION ca19f5cb4d30f6cbd5b44e5f03d2c5eb6f3c1002) endif() if(WEBKIT_LOCAL) diff --git a/src/bun.js/modules/BunJSCModule.h b/src/bun.js/modules/BunJSCModule.h index 557cdc2f6fad83..562d795cfecea9 100644 --- a/src/bun.js/modules/BunJSCModule.h +++ b/src/bun.js/modules/BunJSCModule.h @@ -903,6 +903,24 @@ JSC_DEFINE_HOST_FUNCTION(functionEstimateDirectMemoryUsageOf, (JSGlobalObject * return JSValue::encode(jsNumber(0)); } +#if USE(BMALLOC_MEMORY_FOOTPRINT_API) + +#include + +JSC_DEFINE_HOST_FUNCTION(functionPercentAvailableMemoryInUse, (JSGlobalObject * globalObject, CallFrame* callFrame)) +{ + return JSValue::encode(jsDoubleNumber(bmalloc::api::percentAvailableMemoryInUse())); +} + +#else + +JSC_DEFINE_HOST_FUNCTION(functionPercentAvailableMemoryInUse, (JSGlobalObject * globalObject, CallFrame* callFrame)) +{ + return JSValue::encode(jsNull()); +} + +#endif + // clang-format off /* Source for BunJSCModuleTable.lut.h @begin BunJSCModuleTable @@ -937,13 +955,14 @@ JSC_DEFINE_HOST_FUNCTION(functionEstimateDirectMemoryUsageOf, (JSGlobalObject * serialize functionSerialize Function 0 deserialize functionDeserialize Function 0 estimateShallowMemoryUsageOf functionEstimateDirectMemoryUsageOf Function 1 + percentAvailableMemoryInUse functionPercentAvailableMemoryInUse Function 0 @end */ namespace Zig { DEFINE_NATIVE_MODULE(BunJSC) { - INIT_NATIVE_MODULE(35); + INIT_NATIVE_MODULE(36); putNativeFn(Identifier::fromString(vm, "callerSourceOrigin"_s), functionCallerSourceOrigin); putNativeFn(Identifier::fromString(vm, "jscDescribe"_s), functionDescribe); @@ -977,6 +996,7 @@ DEFINE_NATIVE_MODULE(BunJSC) putNativeFn(Identifier::fromString(vm, "serialize"_s), functionSerialize); putNativeFn(Identifier::fromString(vm, "deserialize"_s), functionDeserialize); putNativeFn(Identifier::fromString(vm, "estimateShallowMemoryUsageOf"_s), functionEstimateDirectMemoryUsageOf); + putNativeFn(Identifier::fromString(vm, "percentAvailableMemoryInUse"_s), functionPercentAvailableMemoryInUse); // Deprecated putNativeFn(Identifier::fromString(vm, "describe"_s), functionDescribe); From a6e876fa25147247e186104a7171cd751716ecba Mon Sep 17 00:00:00 2001 From: Jarred Sumner Date: Fri, 27 Dec 2024 20:34:46 -0800 Subject: [PATCH 4/5] Update SetupWebKit.cmake --- cmake/tools/SetupWebKit.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/tools/SetupWebKit.cmake b/cmake/tools/SetupWebKit.cmake index 422ff8da6d826f..4de124d9731375 100644 --- a/cmake/tools/SetupWebKit.cmake +++ b/cmake/tools/SetupWebKit.cmake @@ -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 ca19f5cb4d30f6cbd5b44e5f03d2c5eb6f3c1002) + set(WEBKIT_VERSION d90d122238e40af3e04eef8689c7abf1735df84e) endif() if(WEBKIT_LOCAL) From 13810a07c001b67939a1bc5441fad790b539b5d8 Mon Sep 17 00:00:00 2001 From: Jarred Sumner Date: Fri, 27 Dec 2024 22:43:28 -0800 Subject: [PATCH 5/5] one more time --- cmake/tools/SetupWebKit.cmake | 2 +- src/bun.js/bindings/BunProcess.cpp | 16 ++++++++++++---- test/js/node/process/process.test.js | 7 +++++++ 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/cmake/tools/SetupWebKit.cmake b/cmake/tools/SetupWebKit.cmake index 4de124d9731375..27990483751b59 100644 --- a/cmake/tools/SetupWebKit.cmake +++ b/cmake/tools/SetupWebKit.cmake @@ -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 d90d122238e40af3e04eef8689c7abf1735df84e) + set(WEBKIT_VERSION 00e2b186fd25e79cea4cb4d63d9fd388192327f6) endif() if(WEBKIT_LOCAL) diff --git a/src/bun.js/bindings/BunProcess.cpp b/src/bun.js/bindings/BunProcess.cpp index 269e860d07f0a7..d18b1b4fc37892 100644 --- a/src/bun.js/bindings/BunProcess.cpp +++ b/src/bun.js/bindings/BunProcess.cpp @@ -2565,10 +2565,18 @@ JSC_DEFINE_HOST_FUNCTION(Process_functionMemoryUsage, result->putDirectOffset(vm, 3, JSC::jsDoubleNumber(vm.heap.extraMemorySize() + vm.heap.externalMemorySize())); - // We report 0 for this because m_arrayBuffers in JSC::Heap is private and we need to add a binding - // If we use objectTypeCounts(), it's hideously slow because it loops through every single object in the heap - // TODO: add a binding for m_arrayBuffers, registerWrapper() in TypedArrayController doesn't work - result->putDirectOffset(vm, 4, JSC::jsNumber(0)); + // JSC won't count this number until vm.heap.addReference() is called. + // That will only happen in cases like: + // - new ArrayBuffer() + // - new Uint8Array(42).buffer + // - fs.readFile(path, "utf-8") (sometimes) + // - ... + // + // But it won't happen in cases like: + // - new Uint8Array(42) + // - Buffer.alloc(42) + // - new Uint8Array(42).slice() + result->putDirectOffset(vm, 4, JSC::jsDoubleNumber(vm.heap.arrayBufferSize())); RELEASE_AND_RETURN(throwScope, JSC::JSValue::encode(result)); } diff --git a/test/js/node/process/process.test.js b/test/js/node/process/process.test.js index 811abfb4bb3012..70555508479ae0 100644 --- a/test/js/node/process/process.test.js +++ b/test/js/node/process/process.test.js @@ -1056,3 +1056,10 @@ describe("process.exitCode", () => { it("process._exiting", () => { expect(process._exiting).toBe(false); }); + +it("process.memoryUsage.arrayBuffers", () => { + const initial = process.memoryUsage().arrayBuffers; + const array = new ArrayBuffer(1024 * 1024 * 16); + array.buffer; + expect(process.memoryUsage().arrayBuffers).toBeGreaterThanOrEqual(initial + 16 * 1024 * 1024); +});