[JSC] JSWrapperMap should not use Objective-C Weak map (NSMapTable with NSPointerFunc...
authorysuzuki@apple.com <ysuzuki@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 30 Mar 2019 01:30:16 +0000 (01:30 +0000)
committerysuzuki@apple.com <ysuzuki@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 30 Mar 2019 01:30:16 +0000 (01:30 +0000)
commitc2a1fa421e2be712b50ea7f2392f09eb4c2c520b
tree0a3d649201a6b4128dbcf0bbb06855ea845fe2a1
parent36bb4338cd19b0ffe5bcafca3a471ea2f94e48c6
[JSC] JSWrapperMap should not use Objective-C Weak map (NSMapTable with NSPointerFunctionsWeakMemory) for m_cachedObjCWrappers
https://bugs.webkit.org/show_bug.cgi?id=196392

Reviewed by Saam Barati.

Weak representation in Objective-C is surprisingly costly in terms of memory. We can see that very easy program shows 10KB memory consumption due to
this weak wrapper map in JavaScriptCore.framework. But we do not need this weak map since Objective-C JSValue has a dealloc. We can unregister itself
from the map when it is deallocated without using Objective-C weak mechanism. And since Objective-C JSValue is tightly coupled to a specific JSContext,
and wrapper map is created per JSContext, JSValue wrapper and actual JavaScriptCore value is one-on-one, and [JSValue dealloc] knows which JSContext's
wrapper map holds itself.

1. We do not use Objective-C weak mechanism. We use WTF::HashSet instead. When JSValue is allocated, we register it to JSWrapperMap's HashSet. And unregister
   JSValue from this map when JSValue is deallocated.
2. We use HashSet<JSValue> (logically) instead of HashMap<JSValueRef, JSValue> to keep JSValueRef and JSValue relationship. We can achieve it because JSValue
   holds JSValueRef inside it.

* API/JSContext.mm:
(-[JSContext removeWrapper:]):
* API/JSContextInternal.h:
* API/JSValue.mm:
(-[JSValue dealloc]):
(-[JSValue initWithValue:inContext:]):
* API/JSWrapperMap.h:
* API/JSWrapperMap.mm:
(WrapperKey::hashTableDeletedValue):
(WrapperKey::WrapperKey):
(WrapperKey::isHashTableDeletedValue const):
(WrapperKey::Hash::hash):
(WrapperKey::Hash::equal):
(WrapperKey::Traits::isEmptyValue):
(WrapperKey::Translator::hash):
(WrapperKey::Translator::equal):
(WrapperKey::Translator::translate):
(-[JSWrapperMap initWithGlobalContextRef:]):
(-[JSWrapperMap dealloc]):
(-[JSWrapperMap objcWrapperForJSValueRef:inContext:]):
(-[JSWrapperMap removeWrapper:]):
* API/tests/testapi.mm:
(testObjectiveCAPIMain):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@243672 268f45cc-cd09-0410-ab3c-d52691b4dbfc
Source/JavaScriptCore/API/JSContext.mm
Source/JavaScriptCore/API/JSContextInternal.h
Source/JavaScriptCore/API/JSValue.mm
Source/JavaScriptCore/API/JSWrapperMap.h
Source/JavaScriptCore/API/JSWrapperMap.mm
Source/JavaScriptCore/API/tests/testapi.mm
Source/JavaScriptCore/ChangeLog