Make Strong use less ram (#20437)

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
Co-authored-by: Jarred Sumner <Jarred-Sumner@users.noreply.github.com>
This commit is contained in:
Jarred Sumner
2025-06-17 13:30:58 -07:00
committed by GitHub
parent 978540902c
commit 6274f10096
4 changed files with 37 additions and 58 deletions

View File

@@ -7,7 +7,6 @@
#include <JavaScriptCore/JSGlobalObjectDebugger.h>
#include <JavaScriptCore/Debugger.h>
#include "ScriptExecutionContext.h"
#include "Strong.h"
#include "debug-helpers.h"
#include "BunInjectedScriptHost.h"
#include <JavaScriptCore/JSGlobalObjectInspectorController.h>
@@ -311,7 +310,7 @@ public:
this->debuggerThreadMessages.swap(messages);
}
JSFunction* onMessageFn = jsCast<JSFunction*>(jsBunDebuggerOnMessageFunction->m_cell.get());
JSFunction* onMessageFn = jsCast<JSFunction*>(jsBunDebuggerOnMessageFunction.get());
MarkedArgumentBuffer arguments;
arguments.ensureCapacity(messages.size());
auto& vm = debuggerGlobalObject->vm();
@@ -381,7 +380,7 @@ public:
JSC::JSGlobalObject* globalObject;
ScriptExecutionContextIdentifier scriptExecutionContextIdentifier;
Bun::StrongRef* jsBunDebuggerOnMessageFunction = nullptr;
JSC::Strong<JSC::Unknown> jsBunDebuggerOnMessageFunction {};
WTF::Lock jsWaitForMessageFromInspectorLock;
std::atomic<ConnectionStatus> status = ConnectionStatus::Pending;
@@ -567,7 +566,7 @@ JSC_DEFINE_HOST_FUNCTION(jsFunctionCreateConnection, (JSGlobalObject * globalObj
connections.append(connection);
inspectorConnections->set(targetContext->identifier(), connections);
}
connection->jsBunDebuggerOnMessageFunction = new Bun::StrongRef(vm, onMessageFn);
connection->jsBunDebuggerOnMessageFunction = { vm, onMessageFn };
connection->connect();
return JSValue::encode(JSBunInspectorConnection::create(vm, JSBunInspectorConnection::createStructure(vm, globalObject, globalObject->objectPrototype()), connection));

View File

@@ -1,37 +1,53 @@
#include "root.h"
#include <JavaScriptCore/Strong.h>
#include <JavaScriptCore/StrongInlines.h>
#include "BunClientData.h"
#include "wtf/DebugHeap.h"
#include "Strong.h"
namespace Bun {
#include "ZigGlobalObject.h"
#if ENABLE(MALLOC_BREAKDOWN)
DEFINE_ALLOCATOR_WITH_HEAP_IDENTIFIER(StrongRef);
#endif
}
extern "C" void Bun__StrongRef__delete(Bun::StrongRef* strongRef)
extern "C" void Bun__StrongRef__delete(JSC::JSValue* _Nonnull handleSlot)
{
delete strongRef;
// deallocate() will correctly remove the handle from the strong list if it's currently on it.
JSC::HandleSet::heapFor(handleSlot)->deallocate(handleSlot);
}
extern "C" Bun::StrongRef* Bun__StrongRef__new(JSC::JSGlobalObject* globalObject, JSC::EncodedJSValue encodedValue)
extern "C" JSC::JSValue* Bun__StrongRef__new(JSC::JSGlobalObject* globalObject, JSC::EncodedJSValue encodedValue)
{
return new Bun::StrongRef(globalObject->vm(), JSC::JSValue::decode(encodedValue));
auto& vm = globalObject->vm();
JSC::HandleSet* handleSet = vm.heap.handleSet();
JSC::HandleSlot handleSlot = handleSet->allocate();
JSC::JSValue value = JSC::JSValue::decode(encodedValue);
// The write barrier must be called to add the handle to the strong
// list if the new value is a cell. We must use <false> because the value
// might be a primitive.
handleSet->writeBarrier<false>(handleSlot, value);
*handleSlot = value;
return handleSlot;
}
extern "C" JSC::EncodedJSValue Bun__StrongRef__get(Bun::StrongRef* strongRef)
extern "C" JSC::EncodedJSValue Bun__StrongRef__get(JSC::JSValue* _Nonnull handleSlot)
{
return JSC::JSValue::encode(strongRef->m_cell.get());
return JSC::JSValue::encode(*handleSlot);
}
extern "C" void Bun__StrongRef__set(Bun::StrongRef* strongRef, JSC::JSGlobalObject* globalObject, JSC::EncodedJSValue value)
extern "C" void Bun__StrongRef__set(JSC::JSValue* _Nonnull handleSlot, JSC::JSGlobalObject* globalObject, JSC::EncodedJSValue encodedValue)
{
strongRef->m_cell.set(globalObject->vm(), JSC::JSValue::decode(value));
auto& vm = globalObject->vm();
JSC::JSValue value = JSC::JSValue::decode(encodedValue);
// The write barrier must be called *before* the value in the slot is updated
// to correctly update the handle's status in the strong list (e.g. moving
// from strong to not strong or vice versa).
// Use <false> because the new value can be a primitive.
vm.heap.handleSet()->writeBarrier<false>(handleSlot, value);
*handleSlot = value;
}
extern "C" void Bun__StrongRef__clear(Bun::StrongRef* strongRef)
extern "C" void Bun__StrongRef__clear(JSC::JSValue* _Nonnull handleSlot)
{
strongRef->m_cell.clear();
// The write barrier must be called *before* the value is cleared
// to correctly remove the handle from the strong list if it held a cell.
JSC::HandleSet::heapFor(handleSlot)->writeBarrier<false>(handleSlot, JSC::JSValue());
*handleSlot = JSC::JSValue();
}

View File

@@ -1,35 +0,0 @@
#pragma once
#include "root.h"
#include "wtf/DebugHeap.h"
#include <JavaScriptCore/Strong.h>
namespace Bun {
// We tried to pool these
// But it was very complicated
#if ENABLE(MALLOC_BREAKDOWN)
DECLARE_ALLOCATOR_WITH_HEAP_IDENTIFIER(StrongRef);
#endif
class StrongRef {
#if ENABLE(MALLOC_BREAKDOWN)
WTF_MAKE_FAST_ALLOCATED_WITH_HEAP_IDENTIFIER(StrongRef);
#else
WTF_MAKE_TZONE_ALLOCATED(StrongRef);
#endif
public:
StrongRef(JSC::VM& vm, JSC::JSValue value)
: m_cell(vm, value)
{
}
StrongRef()
: m_cell()
{
}
JSC::Strong<JSC::Unknown> m_cell;
};
}

View File

@@ -58,7 +58,6 @@
#include <JavaScriptCore/BigIntObject.h>
#include <JavaScriptCore/JSWeakMapInlines.h>
#include "ScriptExecutionContext.h"
#include "Strong.h"
#include "../modules/ObjectModule.h"