Skip to content

Commit 24e0bad

Browse files
radexfacebook-github-bot
authored andcommitted
Make JSCRuntime::createValue 35% faster (#27016)
Summary: JSC does some sort of thread safety locking on every single JSC API call, which makes them ridiculously expensive for a large number of calls (such as when passing a large array over the RN bridge). It would be great if we could lock and unlock once for an entire sequence of JSC calls… but in the meantime, the less we call JSC the better. ![unknown](https://user-images.githubusercontent.com/183747/67624956-08bd6e00-f838-11e9-8f65-e077693f113d.png) In my benchmark environment (Nozbe/WatermelonDB#541), the time spent in JSCRuntime::createValue went down from 1.07s to 0.69s by changing JSValueIsXXXX calls to a single JSValueGetType call. The underlying implementation does the same thing: https://github.com/WebKit/webkit/blob/master/Source/JavaScriptCore/API/JSValueRef.cpp#L58 ## Changelog [General] [Fixed] - Make JSCRuntime::createValue faster Pull Request resolved: #27016 Reviewed By: RSNara Differential Revision: D18769047 Pulled By: mhorowitz fbshipit-source-id: 9d1ee28840303f7721e065c1b3c347e354cd7fef
1 parent a793ed7 commit 24e0bad

File tree

1 file changed

+42
-24
lines changed

1 file changed

+42
-24
lines changed

ReactCommon/jsi/JSCRuntime.cpp

+42-24
Original file line numberDiff line numberDiff line change
@@ -444,10 +444,18 @@ bool JSCRuntime::isInspectable() {
444444
namespace {
445445

446446
bool smellsLikeES6Symbol(JSGlobalContextRef ctx, JSValueRef ref) {
447-
// Empirically, an es6 Symbol is not an object, but its type is
447+
// Since iOS 13, JSValueGetType will return kJSTypeSymbol
448+
// Before: Empirically, an es6 Symbol is not an object, but its type is
448449
// object. This makes no sense, but we'll run with it.
449-
return (
450-
!JSValueIsObject(ctx, ref) && JSValueGetType(ctx, ref) == kJSTypeObject);
450+
// https://github.com/WebKit/webkit/blob/master/Source/JavaScriptCore/API/JSValueRef.cpp#L79-L82
451+
452+
JSType type = JSValueGetType(ctx, ref);
453+
454+
if (type == /* kJSTypeSymbol */ 6) {
455+
return true;
456+
}
457+
458+
return (!JSValueIsObject(ctx, ref) && type == kJSTypeObject);
451459
}
452460

453461
} // namespace
@@ -1339,27 +1347,37 @@ jsi::Object JSCRuntime::createObject(JSObjectRef obj) const {
13391347
}
13401348

13411349
jsi::Value JSCRuntime::createValue(JSValueRef value) const {
1342-
if (JSValueIsNumber(ctx_, value)) {
1343-
return jsi::Value(JSValueToNumber(ctx_, value, nullptr));
1344-
} else if (JSValueIsBoolean(ctx_, value)) {
1345-
return jsi::Value(JSValueToBoolean(ctx_, value));
1346-
} else if (JSValueIsNull(ctx_, value)) {
1347-
return jsi::Value(nullptr);
1348-
} else if (JSValueIsUndefined(ctx_, value)) {
1349-
return jsi::Value();
1350-
} else if (JSValueIsString(ctx_, value)) {
1351-
JSStringRef str = JSValueToStringCopy(ctx_, value, nullptr);
1352-
auto result = jsi::Value(createString(str));
1353-
JSStringRelease(str);
1354-
return result;
1355-
} else if (JSValueIsObject(ctx_, value)) {
1356-
JSObjectRef objRef = JSValueToObject(ctx_, value, nullptr);
1357-
return jsi::Value(createObject(objRef));
1358-
} else if (smellsLikeES6Symbol(ctx_, value)) {
1359-
return jsi::Value(createSymbol(value));
1360-
} else {
1361-
// WHAT ARE YOU
1362-
abort();
1350+
JSType type = JSValueGetType(ctx_, value);
1351+
1352+
switch (type) {
1353+
case kJSTypeNumber:
1354+
return jsi::Value(JSValueToNumber(ctx_, value, nullptr));
1355+
case kJSTypeBoolean:
1356+
return jsi::Value(JSValueToBoolean(ctx_, value));
1357+
case kJSTypeNull:
1358+
return jsi::Value(nullptr);
1359+
case kJSTypeUndefined:
1360+
return jsi::Value();
1361+
case kJSTypeString: {
1362+
JSStringRef str = JSValueToStringCopy(ctx_, value, nullptr);
1363+
auto result = jsi::Value(createString(str));
1364+
JSStringRelease(str);
1365+
return result;
1366+
}
1367+
case kJSTypeObject: {
1368+
JSObjectRef objRef = JSValueToObject(ctx_, value, nullptr);
1369+
return jsi::Value(createObject(objRef));
1370+
}
1371+
// TODO: Uncomment this when all supported JSC versions have this symbol
1372+
// case kJSTypeSymbol:
1373+
default: {
1374+
if (smellsLikeES6Symbol(ctx_, value)) {
1375+
return jsi::Value(createSymbol(value));
1376+
} else {
1377+
// WHAT ARE YOU
1378+
abort();
1379+
}
1380+
}
13631381
}
13641382
}
13651383

0 commit comments

Comments
 (0)