From eae2a63b648203cda3f8bc9e26b990ec715ae998 Mon Sep 17 00:00:00 2001 From: Neil Dhar Date: Sun, 12 Nov 2023 18:45:42 -0800 Subject: [PATCH] Add JSI method for adjusting external memory size Summary: Add a JSI API for associating some native memory with a JS object. This is intended to provide a mechanism to trigger more frequent garbage collection when JS retains large external memory allocations, in order to avoid memory buildup. This diff just adds the JSI method, without any implementations. Changelog: [General][Added] - Added JSI method for reporting native memory to the GC. Differential Revision: D50524912 --- .../react-native/ReactCommon/jsc/JSCRuntime.cpp | 5 +++++ .../react-native/ReactCommon/jsi/jsi/decorator.h | 4 ++++ .../react-native/ReactCommon/jsi/jsi/jsi-inl.h | 5 +++++ packages/react-native/ReactCommon/jsi/jsi/jsi.h | 15 +++++++++++++++ 4 files changed, 29 insertions(+) diff --git a/packages/react-native/ReactCommon/jsc/JSCRuntime.cpp b/packages/react-native/ReactCommon/jsc/JSCRuntime.cpp index 34f43c0c08e9a0..6560fb935a13ad 100644 --- a/packages/react-native/ReactCommon/jsc/JSCRuntime.cpp +++ b/packages/react-native/ReactCommon/jsc/JSCRuntime.cpp @@ -233,6 +233,7 @@ class JSCRuntime : public jsi::Runtime { bool strictEquals(const jsi::String& a, const jsi::String& b) const override; bool strictEquals(const jsi::Object& a, const jsi::Object& b) const override; bool instanceOf(const jsi::Object& o, const jsi::Function& f) override; + void adjustExternalMemoryPressure(const jsi::Object&, intptr_t) override; private: // Basically convenience casts @@ -1403,6 +1404,10 @@ bool JSCRuntime::instanceOf(const jsi::Object& o, const jsi::Function& f) { return res; } +void JSCRuntime::adjustExternalMemoryPressure(const jsi::Object&, intptr_t) { + throw std::logic_error("Not implemented"); +} + jsi::Runtime::PointerValue* JSCRuntime::makeSymbolValue( JSValueRef symbolRef) const { #ifndef NDEBUG diff --git a/packages/react-native/ReactCommon/jsi/jsi/decorator.h b/packages/react-native/ReactCommon/jsi/jsi/decorator.h index baece80fe71d0f..5385381f104714 100644 --- a/packages/react-native/ReactCommon/jsi/jsi/decorator.h +++ b/packages/react-native/ReactCommon/jsi/jsi/decorator.h @@ -252,6 +252,10 @@ class RuntimeDecorator : public Base, private jsi::Instrumentation { plain_.setNativeState(o, state); } + void adjustExternalMemoryPressure(const Object& obj, intptr_t amt) override { + plain_.adjustExternalMemoryPressure(obj, amt); + } + Value getProperty(const Object& o, const PropNameID& name) override { return plain_.getProperty(o, name); }; diff --git a/packages/react-native/ReactCommon/jsi/jsi/jsi-inl.h b/packages/react-native/ReactCommon/jsi/jsi/jsi-inl.h index 4ce00adb883c59..563e9a799f67c2 100644 --- a/packages/react-native/ReactCommon/jsi/jsi/jsi-inl.h +++ b/packages/react-native/ReactCommon/jsi/jsi/jsi-inl.h @@ -227,6 +227,11 @@ inline void Object::setNativeState( runtime.setNativeState(*this, state); } +inline void Object::adjustExternalMemoryPressure(Runtime& runtime, intptr_t amt) + const { + runtime.adjustExternalMemoryPressure(*this, amt); +} + inline Array Object::getPropertyNames(Runtime& runtime) const { return runtime.getPropertyNames(*this); } diff --git a/packages/react-native/ReactCommon/jsi/jsi/jsi.h b/packages/react-native/ReactCommon/jsi/jsi/jsi.h index e5112b753b69d1..5b65ac2c79d471 100644 --- a/packages/react-native/ReactCommon/jsi/jsi/jsi.h +++ b/packages/react-native/ReactCommon/jsi/jsi/jsi.h @@ -387,6 +387,11 @@ class JSI_EXPORT Runtime { virtual bool instanceOf(const Object& o, const Function& f) = 0; + /// See Object::adjustExternalMemoryPressure. + virtual void adjustExternalMemoryPressure( + const jsi::Object& obj, + intptr_t amount) = 0; + // These exist so derived classes can access the private parts of // Value, Symbol, String, and Object, which are all friends of Runtime. template @@ -834,6 +839,16 @@ class JSI_EXPORT Object : public Pointer { /// works. I only need it in one place.) Array getPropertyNames(Runtime& runtime) const; + /// Inform the runtime that there is additional memory associated with a given + /// JavaScript object that is not visible to the GC. This can be used if an + /// object is known to retain some native memory, and may be used to guide + /// decisions about when to run garbage collection. + /// This can be called multiple times on an object to increase or decrease the + /// associated external memory. Once the object is garbage collected, the + /// associated external memory will be considered freed and may no longer + /// factor into GC decisions. + void adjustExternalMemoryPressure(Runtime& runtime, intptr_t amt) const; + protected: void setPropertyValue( Runtime& runtime,