mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
4830085f40
Summary:
## Motivation
We got this crash T67304907, which shows a `EXC_BAD_ACCESS / KERN_INVALID_ADDRESS` when calling this line:
```
NativeModulePerfLogger::getInstance().asyncMethodCallBatchPreprocessStart();
```
There are no arguments in that call, so I figured the only error could be when we try to invoke `getInstance()` or `asyncMethodCallBatchPreprocessStart()`.
This diff:
1. Removes the `NativeModulePerfLogger::getInstance()` bit. Now NativeModulePerfLogger is used via regular static C functions. So, there's no way that simply invoking one of the logging functions crashes the application: there's no vtable lookup.
2. Inside each logging function, when perf-logging is disabled, the global perflogger should be `nullptr`. This diff makes it so that in that case, we won't execute any code in the control group of the perf-logging experiment.
## Changes
**How do we enable NativeModule perf-logging?**
- Previously:
- `NativeModulePerfLogger::setInstance(std::make_shared<FBReactNativeModulePerfLogger>(...))`
- `TurboModulePerfLogger::setInstance(std::make_shared<FBReactNativeModulePerfLogger>(...))`.
- Now:
- `BridgeNativeModulePerfLogger::enableLogging(std::make_unique<FBReactNativeModulePerfLogger>(...))`
- `TurboModulePerfLogger::enableLogging(std::make_unique<FBReactNativeModulePerfLogger>(...))`
**How do we do NativeModule perf-logging now?**
- Previously:
- `NativeModulePerfLogger::getInstance().command(...args)`
- `TurboModulePerfLogger::getInstance().command(...args)`.
- Now:
- `BridgeNativeModulePerfLogger::command(...args)`
- `TurboModulePerfLogger::command(...args)`.
The benefit of this approach is that each method in `BridgeNativeModulePerfLogger` is guarded with an if check. Example:
```
void moduleCreateConstructStart(const char *moduleName, int32_t id) {
NativeModulePerfLogger *logger = g_perfLogger.get();
if (logger != nullptr) {
logger->moduleCreateConstructStart(moduleName, id);
}
}
```
Therefore, we don't actually execute any code when perf-logging is disabled.
Changelog:
[Internal]
Reviewed By: fkgozali
Differential Revision: D21669888
fbshipit-source-id: 80c73754c430ce787404b563878bad146295e01f
106 lines
2.7 KiB
C++
106 lines
2.7 KiB
C++
/*
|
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
*
|
|
* This source code is licensed under the MIT license found in the
|
|
* LICENSE file in the root directory of this source tree.
|
|
*/
|
|
|
|
#include "jsireact/JSINativeModules.h"
|
|
#include <reactperflogger/BridgeNativeModulePerfLogger.h>
|
|
|
|
#include <glog/logging.h>
|
|
|
|
#include <cxxreact/ReactMarker.h>
|
|
|
|
#include <jsi/JSIDynamic.h>
|
|
|
|
#include <string>
|
|
|
|
using namespace facebook::jsi;
|
|
|
|
namespace facebook {
|
|
namespace react {
|
|
|
|
JSINativeModules::JSINativeModules(
|
|
std::shared_ptr<ModuleRegistry> moduleRegistry)
|
|
: m_moduleRegistry(std::move(moduleRegistry)) {}
|
|
|
|
Value JSINativeModules::getModule(Runtime &rt, const PropNameID &name) {
|
|
if (!m_moduleRegistry) {
|
|
return nullptr;
|
|
}
|
|
|
|
std::string moduleName = name.utf8(rt);
|
|
|
|
BridgeNativeModulePerfLogger::moduleJSRequireBeginningStart(
|
|
moduleName.c_str());
|
|
|
|
const auto it = m_objects.find(moduleName);
|
|
if (it != m_objects.end()) {
|
|
BridgeNativeModulePerfLogger::moduleJSRequireBeginningCacheHit(
|
|
moduleName.c_str());
|
|
BridgeNativeModulePerfLogger::moduleJSRequireBeginningEnd(
|
|
moduleName.c_str());
|
|
return Value(rt, it->second);
|
|
}
|
|
|
|
auto module = createModule(rt, moduleName);
|
|
if (!module.hasValue()) {
|
|
BridgeNativeModulePerfLogger::moduleJSRequireEndingFail(moduleName.c_str());
|
|
// Allow lookup to continue in the objects own properties, which allows for
|
|
// overrides of NativeModules
|
|
return nullptr;
|
|
}
|
|
|
|
auto result =
|
|
m_objects.emplace(std::move(moduleName), std::move(*module)).first;
|
|
|
|
Value ret = Value(rt, result->second);
|
|
BridgeNativeModulePerfLogger::moduleJSRequireEndingEnd(moduleName.c_str());
|
|
return ret;
|
|
}
|
|
|
|
void JSINativeModules::reset() {
|
|
m_genNativeModuleJS = folly::none;
|
|
m_objects.clear();
|
|
}
|
|
|
|
folly::Optional<Object> JSINativeModules::createModule(
|
|
Runtime &rt,
|
|
const std::string &name) {
|
|
bool hasLogger(ReactMarker::logTaggedMarker);
|
|
if (hasLogger) {
|
|
ReactMarker::logTaggedMarker(
|
|
ReactMarker::NATIVE_MODULE_SETUP_START, name.c_str());
|
|
}
|
|
|
|
if (!m_genNativeModuleJS) {
|
|
m_genNativeModuleJS =
|
|
rt.global().getPropertyAsFunction(rt, "__fbGenNativeModule");
|
|
}
|
|
|
|
auto result = m_moduleRegistry->getConfig(name);
|
|
if (!result.hasValue()) {
|
|
return folly::none;
|
|
}
|
|
|
|
Value moduleInfo = m_genNativeModuleJS->call(
|
|
rt,
|
|
valueFromDynamic(rt, result->config),
|
|
static_cast<double>(result->index));
|
|
CHECK(!moduleInfo.isNull()) << "Module returned from genNativeModule is null";
|
|
|
|
folly::Optional<Object> module(
|
|
moduleInfo.asObject(rt).getPropertyAsObject(rt, "module"));
|
|
|
|
if (hasLogger) {
|
|
ReactMarker::logTaggedMarker(
|
|
ReactMarker::NATIVE_MODULE_SETUP_STOP, name.c_str());
|
|
}
|
|
|
|
return module;
|
|
}
|
|
|
|
} // namespace react
|
|
} // namespace facebook
|