- Revision
- 243617
- Author
- [email protected]
- Date
- 2019-03-28 12:37:58 -0700 (Thu, 28 Mar 2019)
Log Message
[JSC] Drop VM and Context cache map in _javascript_Core.framework
https://bugs.webkit.org/show_bug.cgi?id=196341
Reviewed by Saam Barati.
Previously, we created Objective-C weak map to maintain JSVirtualMachine and JSContext wrappers corresponding to VM and JSGlobalObject.
But Objective-C weak map is really memory costly. Even if the entry is only one, it consumes 2.5KB per weak map. Since we can modify
JSC intrusively for _javascript_Core.framework (and we already did it, like, holding JSWrapperMap in JSGlobalObject), we can just hold
a pointer to a wrapper in VM and JSGlobalObject.
This patch adds void* members to VM and JSGlobalObject, which holds a non-strong reference to a wrapper. When a wrapper is gone, we
clear this pointer too. This removes unnecessary two Objective-C weak maps, and save 5KB.
* API/JSContext.mm:
(-[JSContext initWithVirtualMachine:]):
(-[JSContext dealloc]):
(-[JSContext initWithGlobalContextRef:]):
(-[JSContext wrapperMap]):
(+[JSContext contextWithJSGlobalContextRef:]):
* API/JSVirtualMachine.mm:
(-[JSVirtualMachine initWithContextGroupRef:]):
(-[JSVirtualMachine dealloc]):
(+[JSVirtualMachine virtualMachineWithContextGroupRef:]):
(scanExternalObjectGraph):
(scanExternalRememberedSet):
(initWrapperCache): Deleted.
(wrapperCache): Deleted.
(+[JSVMWrapperCache addWrapper:forJSContextGroupRef:]): Deleted.
(+[JSVMWrapperCache wrapperForJSContextGroupRef:]): Deleted.
(-[JSVirtualMachine contextForGlobalContextRef:]): Deleted.
(-[JSVirtualMachine addContext:forGlobalContextRef:]): Deleted.
* API/JSVirtualMachineInternal.h:
* runtime/JSGlobalObject.h:
(JSC::JSGlobalObject::setAPIWrapper):
(JSC::JSGlobalObject::apiWrapper const):
* runtime/VM.h:
Modified Paths
Diff
Modified: trunk/Source/_javascript_Core/API/JSContext.mm (243616 => 243617)
--- trunk/Source/_javascript_Core/API/JSContext.mm 2019-03-28 19:32:53 UTC (rev 243616)
+++ trunk/Source/_javascript_Core/API/JSContext.mm 2019-03-28 19:37:58 UTC (rev 243617)
@@ -85,13 +85,15 @@
};
[self ensureWrapperMap];
- [m_virtualMachine addContext:self forGlobalContextRef:m_context];
+ toJSGlobalObject(m_context)->setAPIWrapper((__bridge void*)self);
+
return self;
}
- (void)dealloc
{
+ toJSGlobalObject(m_context)->setAPIWrapper((__bridge void*)nil);
m_exception.clear();
JSGlobalContextRelease(m_context);
[m_virtualMachine release];
@@ -308,7 +310,7 @@
context.exception = exceptionValue;
};
- [m_virtualMachine addContext:self forGlobalContextRef:m_context];
+ toJSGlobalObject(m_context)->setAPIWrapper((__bridge void*)self);
return self;
}
@@ -358,7 +360,7 @@
- (JSWrapperMap *)wrapperMap
{
- return toJS(m_context)->lexicalGlobalObject()->wrapperMap();
+ return toJSGlobalObject(m_context)->wrapperMap();
}
- (JSValue *)wrapperForJSObject:(JSValueRef)value
@@ -369,8 +371,7 @@
+ (JSContext *)contextWithJSGlobalContextRef:(JSGlobalContextRef)globalContext
{
- JSVirtualMachine *virtualMachine = [JSVirtualMachine virtualMachineWithContextGroupRef:toRef(&toJS(globalContext)->vm())];
- JSContext *context = [virtualMachine contextForGlobalContextRef:globalContext];
+ JSContext *context = (__bridge JSContext *)toJSGlobalObject(globalContext)->apiWrapper();
if (!context)
context = [[[JSContext alloc] initWithGlobalContextRef:globalContext] autorelease];
return context;
Modified: trunk/Source/_javascript_Core/API/JSVirtualMachine.mm (243616 => 243617)
--- trunk/Source/_javascript_Core/API/JSVirtualMachine.mm 2019-03-28 19:32:53 UTC (rev 243616)
+++ trunk/Source/_javascript_Core/API/JSVirtualMachine.mm 2019-03-28 19:37:58 UTC (rev 243617)
@@ -41,50 +41,9 @@
#import <wtf/BlockPtr.h>
#import <wtf/Lock.h>
-static NSMapTable *globalWrapperCache = 0;
-
-static Lock wrapperCacheMutex;
-
-static void initWrapperCache()
-{
- ASSERT(!globalWrapperCache);
- NSPointerFunctionsOptions keyOptions = NSPointerFunctionsOpaqueMemory | NSPointerFunctionsOpaquePersonality;
- NSPointerFunctionsOptions valueOptions = NSPointerFunctionsWeakMemory | NSPointerFunctionsObjectPersonality;
- globalWrapperCache = [[NSMapTable alloc] initWithKeyOptions:keyOptions valueOptions:valueOptions capacity:0];
-}
-
-static NSMapTable *wrapperCache()
-{
- if (!globalWrapperCache)
- initWrapperCache();
- return globalWrapperCache;
-}
-
-@interface JSVMWrapperCache : NSObject
-+ (void)addWrapper:(JSVirtualMachine *)wrapper forJSContextGroupRef:(JSContextGroupRef)group;
-+ (JSVirtualMachine *)wrapperForJSContextGroupRef:(JSContextGroupRef)group;
-@end
-
-@implementation JSVMWrapperCache
-
-+ (void)addWrapper:(JSVirtualMachine *)wrapper forJSContextGroupRef:(JSContextGroupRef)group
-{
- std::lock_guard<Lock> lock(wrapperCacheMutex);
- NSMapInsert(wrapperCache(), group, (__bridge void*)wrapper);
-}
-
-+ (JSVirtualMachine *)wrapperForJSContextGroupRef:(JSContextGroupRef)group
-{
- std::lock_guard<Lock> lock(wrapperCacheMutex);
- return (__bridge JSVirtualMachine *)NSMapGet(wrapperCache(), group);
-}
-
-@end
-
@implementation JSVirtualMachine {
JSContextGroupRef m_group;
Lock m_externalDataMutex;
- NSMapTable *m_contextCache;
NSMapTable *m_externalObjectGraph;
NSMapTable *m_externalRememberedSet;
}
@@ -106,10 +65,6 @@
m_group = JSContextGroupRetain(group);
- NSPointerFunctionsOptions keyOptions = NSPointerFunctionsOpaqueMemory | NSPointerFunctionsOpaquePersonality;
- NSPointerFunctionsOptions valueOptions = NSPointerFunctionsWeakMemory | NSPointerFunctionsObjectPersonality;
- m_contextCache = [[NSMapTable alloc] initWithKeyOptions:keyOptions valueOptions:valueOptions capacity:0];
-
NSPointerFunctionsOptions weakIDOptions = NSPointerFunctionsWeakMemory | NSPointerFunctionsObjectPersonality;
NSPointerFunctionsOptions strongIDOptions = NSPointerFunctionsStrongMemory | NSPointerFunctionsObjectPersonality;
m_externalObjectGraph = [[NSMapTable alloc] initWithKeyOptions:weakIDOptions valueOptions:strongIDOptions capacity:0];
@@ -116,8 +71,8 @@
NSPointerFunctionsOptions integerOptions = NSPointerFunctionsOpaqueMemory | NSPointerFunctionsIntegerPersonality;
m_externalRememberedSet = [[NSMapTable alloc] initWithKeyOptions:weakIDOptions valueOptions:integerOptions capacity:0];
-
- [JSVMWrapperCache addWrapper:self forJSContextGroupRef:group];
+
+ toJS(group)->m_apiWrapper = (__bridge void*)self;
return self;
}
@@ -124,8 +79,8 @@
- (void)dealloc
{
+ toJS(m_group)->m_apiWrapper = (__bridge void*)nil;
JSContextGroupRelease(m_group);
- [m_contextCache release];
[m_externalObjectGraph release];
[m_externalRememberedSet release];
[super dealloc];
@@ -237,22 +192,13 @@
+ (JSVirtualMachine *)virtualMachineWithContextGroupRef:(JSContextGroupRef)group
{
- JSVirtualMachine *virtualMachine = [JSVMWrapperCache wrapperForJSContextGroupRef:group];
+ auto* vm = toJS(group);
+ JSVirtualMachine *virtualMachine = (__bridge JSVirtualMachine *)vm->m_apiWrapper;
if (!virtualMachine)
virtualMachine = [[[JSVirtualMachine alloc] initWithContextGroupRef:group] autorelease];
return virtualMachine;
}
-- (JSContext *)contextForGlobalContextRef:(JSGlobalContextRef)globalContext
-{
- return (__bridge JSContext *)NSMapGet(m_contextCache, globalContext);
-}
-
-- (void)addContext:(JSContext *)wrapper forGlobalContextRef:(JSGlobalContextRef)globalContext
-{
- NSMapInsert(m_contextCache, globalContext, (__bridge void*)wrapper);
-}
-
- (Lock&)externalDataMutex
{
return m_externalDataMutex;
@@ -312,7 +258,7 @@
static void scanExternalObjectGraph(JSC::VM& vm, JSC::SlotVisitor& visitor, void* root, bool lockAcquired)
{
@autoreleasepool {
- JSVirtualMachine *virtualMachine = [JSVMWrapperCache wrapperForJSContextGroupRef:toRef(&vm)];
+ JSVirtualMachine *virtualMachine = (__bridge JSVirtualMachine *)vm.m_apiWrapper;
if (!virtualMachine)
return;
NSMapTable *externalObjectGraph = [virtualMachine externalObjectGraph];
@@ -350,7 +296,7 @@
void scanExternalRememberedSet(JSC::VM& vm, JSC::SlotVisitor& visitor)
{
@autoreleasepool {
- JSVirtualMachine *virtualMachine = [JSVMWrapperCache wrapperForJSContextGroupRef:toRef(&vm)];
+ JSVirtualMachine *virtualMachine = (__bridge JSVirtualMachine *)vm.m_apiWrapper;
if (!virtualMachine)
return;
Lock& externalDataMutex = [virtualMachine externalDataMutex];
Modified: trunk/Source/_javascript_Core/API/JSVirtualMachineInternal.h (243616 => 243617)
--- trunk/Source/_javascript_Core/API/JSVirtualMachineInternal.h 2019-03-28 19:32:53 UTC (rev 243616)
+++ trunk/Source/_javascript_Core/API/JSVirtualMachineInternal.h 2019-03-28 19:37:58 UTC (rev 243617)
@@ -44,8 +44,6 @@
+ (JSVirtualMachine *)virtualMachineWithContextGroupRef:(JSContextGroupRef)group;
-- (JSContext *)contextForGlobalContextRef:(JSGlobalContextRef)globalContext;
-- (void)addContext:(JSContext *)wrapper forGlobalContextRef:(JSGlobalContextRef)globalContext;
- (JSC::VM&)vm;
@end
Modified: trunk/Source/_javascript_Core/ChangeLog (243616 => 243617)
--- trunk/Source/_javascript_Core/ChangeLog 2019-03-28 19:32:53 UTC (rev 243616)
+++ trunk/Source/_javascript_Core/ChangeLog 2019-03-28 19:37:58 UTC (rev 243617)
@@ -1,3 +1,42 @@
+2019-03-27 Yusuke Suzuki <[email protected]>
+
+ [JSC] Drop VM and Context cache map in _javascript_Core.framework
+ https://bugs.webkit.org/show_bug.cgi?id=196341
+
+ Reviewed by Saam Barati.
+
+ Previously, we created Objective-C weak map to maintain JSVirtualMachine and JSContext wrappers corresponding to VM and JSGlobalObject.
+ But Objective-C weak map is really memory costly. Even if the entry is only one, it consumes 2.5KB per weak map. Since we can modify
+ JSC intrusively for _javascript_Core.framework (and we already did it, like, holding JSWrapperMap in JSGlobalObject), we can just hold
+ a pointer to a wrapper in VM and JSGlobalObject.
+
+ This patch adds void* members to VM and JSGlobalObject, which holds a non-strong reference to a wrapper. When a wrapper is gone, we
+ clear this pointer too. This removes unnecessary two Objective-C weak maps, and save 5KB.
+
+ * API/JSContext.mm:
+ (-[JSContext initWithVirtualMachine:]):
+ (-[JSContext dealloc]):
+ (-[JSContext initWithGlobalContextRef:]):
+ (-[JSContext wrapperMap]):
+ (+[JSContext contextWithJSGlobalContextRef:]):
+ * API/JSVirtualMachine.mm:
+ (-[JSVirtualMachine initWithContextGroupRef:]):
+ (-[JSVirtualMachine dealloc]):
+ (+[JSVirtualMachine virtualMachineWithContextGroupRef:]):
+ (scanExternalObjectGraph):
+ (scanExternalRememberedSet):
+ (initWrapperCache): Deleted.
+ (wrapperCache): Deleted.
+ (+[JSVMWrapperCache addWrapper:forJSContextGroupRef:]): Deleted.
+ (+[JSVMWrapperCache wrapperForJSContextGroupRef:]): Deleted.
+ (-[JSVirtualMachine contextForGlobalContextRef:]): Deleted.
+ (-[JSVirtualMachine addContext:forGlobalContextRef:]): Deleted.
+ * API/JSVirtualMachineInternal.h:
+ * runtime/JSGlobalObject.h:
+ (JSC::JSGlobalObject::setAPIWrapper):
+ (JSC::JSGlobalObject::apiWrapper const):
+ * runtime/VM.h:
+
2019-03-28 Tadeu Zagallo <[email protected]>
In-memory code cache should not share bytecode across domains
Modified: trunk/Source/_javascript_Core/runtime/JSGlobalObject.h (243616 => 243617)
--- trunk/Source/_javascript_Core/runtime/JSGlobalObject.h 2019-03-28 19:32:53 UTC (rev 243616)
+++ trunk/Source/_javascript_Core/runtime/JSGlobalObject.h 2019-03-28 19:37:58 UTC (rev 243617)
@@ -1005,6 +1005,8 @@
#if JSC_OBJC_API_ENABLED
JSWrapperMap* wrapperMap() const { return m_wrapperMap.get(); }
void setWrapperMap(JSWrapperMap* map) { m_wrapperMap = map; }
+ void setAPIWrapper(void* apiWrapper) { m_apiWrapper = apiWrapper; }
+ void* apiWrapper() const { return m_apiWrapper; }
#endif
#ifdef JSC_GLIB_API_ENABLED
WrapperMap* wrapperMap() const { return m_wrapperMap.get(); }
@@ -1047,6 +1049,7 @@
bool m_needsSiteSpecificQuirks { false };
#if JSC_OBJC_API_ENABLED
RetainPtr<JSWrapperMap> m_wrapperMap;
+ void* m_apiWrapper { nullptr };
#endif
#ifdef JSC_GLIB_API_ENABLED
std::unique_ptr<WrapperMap> m_wrapperMap;
Modified: trunk/Source/_javascript_Core/runtime/VM.h (243616 => 243617)
--- trunk/Source/_javascript_Core/runtime/VM.h 2019-03-28 19:32:53 UTC (rev 243616)
+++ trunk/Source/_javascript_Core/runtime/VM.h 2019-03-28 19:37:58 UTC (rev 243617)
@@ -804,6 +804,10 @@
RTTraceList* m_rtTraceList;
#endif
+#if JSC_OBJC_API_ENABLED
+ void* m_apiWrapper { nullptr };
+#endif
+
JS_EXPORT_PRIVATE void resetDateCache();
RegExpCache* regExpCache() { return m_regExpCache; }