From 1af42478d61efe0d0f0e0c05e56c9c607ac6f211 Mon Sep 17 00:00:00 2001 From: Dratwas Date: Wed, 29 May 2019 17:27:19 +0200 Subject: [PATCH 1/2] Add preloading of env and load bundle in preloaded env --- ReactCommon/cxxreact/BundleRegistry.cpp | 52 ++++++++++++++++--------- ReactCommon/cxxreact/BundleRegistry.h | 19 +++++---- ReactCommon/cxxreact/Instance.cpp | 51 ++++++++++++------------ ReactCommon/cxxreact/Instance.h | 2 + 4 files changed, 68 insertions(+), 56 deletions(-) diff --git a/ReactCommon/cxxreact/BundleRegistry.cpp b/ReactCommon/cxxreact/BundleRegistry.cpp index 24cb490653a3..465261b72030 100644 --- a/ReactCommon/cxxreact/BundleRegistry.cpp +++ b/ReactCommon/cxxreact/BundleRegistry.cpp @@ -14,26 +14,39 @@ BundleRegistry::BundleRegistry(JSExecutorFactory* jsExecutorFactory, } BundleRegistry::~BundleRegistry() { - bundleExecutionEnvironments_.clear(); + bundleEnvironments_.clear(); bundles_.clear(); } -void BundleRegistry::runNewExecutionEnvironment(std::unique_ptr initialBundle, - std::function callback) { - std::shared_ptr execEnv = std::make_shared(); +void BundleRegistry::preloadEnvironment(std::string environmentId, std::function callback) { + if (hasEnvironment(environmentId)) { + throw std::runtime_error( + folly::to("Environment with id = ", environmentId, " already exists") + ); + } + std::shared_ptr execEnv = std::make_shared(); execEnv->valid = false; execEnv->jsQueue = jsQueueFactory_(); - bundles_.push_back(std::move(initialBundle)); - execEnv->initialBundle = std::weak_ptr(bundles_.back()); - bundleExecutionEnvironments_.push_back(std::move(execEnv)); + execEnv->initialBundle = std::weak_ptr(); + bundleEnvironments_[environmentId] = std::move(execEnv); - execEnv = bundleExecutionEnvironments_.back(); + execEnv = bundleEnvironments_[environmentId]; execEnv->jsQueue->runOnQueueSync([this, execEnv, callback]() mutable { execEnv->nativeToJsBridge = std::make_unique(jsExecutorFactory_, moduleRegistry_, execEnv->jsQueue, callback_); + callback(); + }); +} +void BundleRegistry::runInPreloadedEnvironment(std::string environmentId, + std::unique_ptr initialBundle) { + std::shared_ptr execEnv = getEnvironment(environmentId).lock(); + bundles_.push_back(std::move(initialBundle)); + execEnv->initialBundle = std::weak_ptr(bundles_.back()); + + execEnv->jsQueue->runOnQueueSync([this, execEnv]() mutable { auto bundle = execEnv->initialBundle.lock(); if (bundle->getBundleType() == BundleType::FileRAMBundle || bundle->getBundleType() == BundleType::IndexedRAMBundle) { @@ -67,11 +80,10 @@ void BundleRegistry::runNewExecutionEnvironment(std::unique_ptr in } execEnv->valid = true; - callback(); }); } -void BundleRegistry::evalInitialBundle(std::shared_ptr execEnv, +void BundleRegistry::evalInitialBundle(std::shared_ptr execEnv, std::unique_ptr startupScript, std::string sourceURL, LoadBundleLambda loadBundle, @@ -88,22 +100,24 @@ BundleRegistry::LoadBundleLambda BundleRegistry::makeLoadBundleLambda() { }; } -void BundleRegistry::disposeExecutionEnvironments() { - for (auto execEnv : bundleExecutionEnvironments_) { - execEnv->nativeToJsBridge->destroy(); +void BundleRegistry::disposeEnvironments() { + for (auto environment : bundleEnvironments_) { + environment.second->nativeToJsBridge->destroy(); } } -std::weak_ptr BundleRegistry::getFirstExecutionEnvironment() { - if (bundleExecutionEnvironments_.size() == 0) { - throw std::runtime_error("Cannot get first BundleExecutionEnvironment"); +std::weak_ptr BundleRegistry::getEnvironment(std::string environmentId) { + if (!hasEnvironment(environmentId)) { + throw std::runtime_error( + folly::to("Cannot get environment with id = ", environmentId) + ); } - return std::weak_ptr(bundleExecutionEnvironments_[0]); + return std::weak_ptr(bundleEnvironments_[environmentId]); } -bool BundleRegistry::hasExecutionEnvironment() { - return bundleExecutionEnvironments_.size() > 0; +bool BundleRegistry::hasEnvironment(std::string environmentId) { + return bundleEnvironments_.find(environmentId) != bundleEnvironments_.end(); } } // react diff --git a/ReactCommon/cxxreact/BundleRegistry.h b/ReactCommon/cxxreact/BundleRegistry.h index cd24e31f51ca..0456747d2063 100644 --- a/ReactCommon/cxxreact/BundleRegistry.h +++ b/ReactCommon/cxxreact/BundleRegistry.h @@ -17,7 +17,7 @@ class BundleRegistry { using LoadBundleLambda = std::function; using GetModuleLambda = std::function; - struct BundleExecutionEnvironment { + struct BundleEnvironment { std::shared_ptr jsQueue; std::unique_ptr nativeToJsBridge; std::weak_ptr initialBundle; @@ -32,16 +32,15 @@ class BundleRegistry { BundleRegistry& operator=(const BundleRegistry&) = delete; ~BundleRegistry(); - void runNewExecutionEnvironment(std::unique_ptr initialBundle, - std::function callback); - void disposeExecutionEnvironments(); - // TODO: get rid of this - std::weak_ptr getFirstExecutionEnvironment(); - bool hasExecutionEnvironment(); + void preloadEnvironment(std::string environmentId, std::function callback); + void runInPreloadedEnvironment(std::string environmentId, std::unique_ptr initialBundle); + void disposeEnvironments(); + std::weak_ptr getEnvironment(std::string environmentId); + bool hasEnvironment(std::string environmentId); private: - std::vector> bundleExecutionEnvironments_; + std::map> bundleEnvironments_; std::vector> bundles_; JSExecutorFactory* jsExecutorFactory_; std::shared_ptr moduleRegistry_; @@ -50,9 +49,9 @@ class BundleRegistry { /** * Setup environment and load initial bundle. Should be called only once - * per BundleExecutionEnvironemnt. + * per BundleEnvironemnt. */ - void evalInitialBundle(std::shared_ptr execEnv, + void evalInitialBundle(std::shared_ptr execEnv, std::unique_ptr startupScript, std::string sourceURL, LoadBundleLambda loadBundle, diff --git a/ReactCommon/cxxreact/Instance.cpp b/ReactCommon/cxxreact/Instance.cpp index 0fd1fb3b384f..db9a0c75235d 100644 --- a/ReactCommon/cxxreact/Instance.cpp +++ b/ReactCommon/cxxreact/Instance.cpp @@ -28,7 +28,7 @@ namespace react { Instance::~Instance() { if (bundleRegistry_) { - bundleRegistry_->disposeExecutionEnvironments(); + bundleRegistry_->disposeEnvironments(); } } @@ -45,16 +45,17 @@ void Instance::initializeBridge( callback_, [jsQueue]() { return jsQueue; } // TODO: use a factory ); + bundleRegistry_->preloadEnvironment(defaultEnvironmentId_,[this]() { + std::lock_guard lock(m_syncMutex); + m_syncReady = true; + m_syncCV.notify_all(); + }); } void Instance::loadBundleAsync(std::unique_ptr bundle) { callback_->incrementPendingJSCalls(); SystraceSection s("Instance::loadBundleAsync", "sourceURL", bundle->getSourceURL()); - bundleRegistry_->runNewExecutionEnvironment(std::move(bundle), [this]() { - std::lock_guard lock(m_syncMutex); - m_syncReady = true; - m_syncCV.notify_all(); - }); + bundleRegistry_->runInPreloadedEnvironment(defaultEnvironmentId_, std::move(bundle)); } void Instance::loadBundleSync(std::unique_ptr bundle) { @@ -62,12 +63,7 @@ void Instance::loadBundleSync(std::unique_ptr bundle) { m_syncCV.wait(lock, [this] { return m_syncReady; }); SystraceSection s("Instance::loadBundleSync", "sourceURL", bundle->getSourceURL()); - bundleRegistry_->runNewExecutionEnvironment(std::move(bundle), [this]() { - // TODO: check if this is needed at all - std::lock_guard lock(m_syncMutex); - m_syncReady = true; - m_syncCV.notify_all(); - }); + bundleRegistry_->runInPreloadedEnvironment(defaultEnvironmentId_, std::move(bundle)); } void Instance::loadBundle(std::unique_ptr bundle, bool loadSynchronously) { @@ -81,17 +77,17 @@ void Instance::loadBundle(std::unique_ptr bundle, bool loadSynchro void Instance::setGlobalVariable(std::string propName, std::unique_ptr jsonValue) { - if (auto execEnv = bundleRegistry_->getFirstExecutionEnvironment().lock()) { + if (auto execEnv = bundleRegistry_->getEnvironment(defaultEnvironmentId_).lock()) { execEnv->nativeToJsBridge->setGlobalVariable(std::move(propName), std::move(jsonValue)); } else { - throw std::runtime_error("BundleExecutionEnvironment pointer is invalid"); + throw std::runtime_error("BundleEnvironment pointer is invalid"); } } void* Instance::getJavaScriptContext() { - if (bundleRegistry_->hasExecutionEnvironment()) { - if (auto execEnv = bundleRegistry_->getFirstExecutionEnvironment().lock()) { + if (bundleRegistry_->hasEnvironment(defaultEnvironmentId_)) { + if (auto execEnv = bundleRegistry_->getEnvironment(defaultEnvironmentId_).lock()) { return execEnv->nativeToJsBridge ? execEnv->nativeToJsBridge->getJavaScriptContext() : nullptr; } } @@ -100,8 +96,8 @@ void* Instance::getJavaScriptContext() { } bool Instance::isInspectable() { - if (bundleRegistry_->hasExecutionEnvironment()) { - if (auto execEnv = bundleRegistry_->getFirstExecutionEnvironment().lock()) { + if (bundleRegistry_->hasEnvironment(defaultEnvironmentId_)) { + if (auto execEnv = bundleRegistry_->getEnvironment(defaultEnvironmentId_).lock()) { return execEnv->nativeToJsBridge ? execEnv->nativeToJsBridge->isInspectable() : false; } } @@ -110,8 +106,8 @@ bool Instance::isInspectable() { } bool Instance::isBatchActive() { - if (bundleRegistry_->hasExecutionEnvironment()) { - if (auto execEnv = bundleRegistry_->getFirstExecutionEnvironment().lock()) { + if (bundleRegistry_->hasEnvironment(defaultEnvironmentId_)) { + if (auto execEnv = bundleRegistry_->getEnvironment(defaultEnvironmentId_).lock()) { return execEnv->nativeToJsBridge ? execEnv->nativeToJsBridge->isBatchActive() : false; } } @@ -119,25 +115,26 @@ bool Instance::isBatchActive() { return false; } -void Instance::callJSFunction(std::string &&module, std::string &&method, +void Instance::callJSFunction(std::string &&module, + std::string &&method, folly::dynamic &¶ms) { callback_->incrementPendingJSCalls(); - if (auto execEnv = bundleRegistry_->getFirstExecutionEnvironment().lock()) { + if (auto execEnv = bundleRegistry_->getEnvironment(defaultEnvironmentId_).lock()) { execEnv->nativeToJsBridge->callFunction(std::move(module), std::move(method), std::move(params)); } else { - throw std::runtime_error("BundleExecutionEnvironment pointer is invalid"); + throw std::runtime_error("BundleEnvironment pointer is invalid"); } } void Instance::callJSCallback(uint64_t callbackId, folly::dynamic &¶ms) { SystraceSection s("Instance::callJSCallback"); callback_->incrementPendingJSCalls(); - if (auto execEnv = bundleRegistry_->getFirstExecutionEnvironment().lock()) { + if (auto execEnv = bundleRegistry_->getEnvironment(defaultEnvironmentId_).lock()) { execEnv->nativeToJsBridge->invokeCallback((double)callbackId, std::move(params)); } else { - throw std::runtime_error("BundleExecutionEnvironment pointer is invalid"); + throw std::runtime_error("BundleEnvironment pointer is invalid"); } } @@ -148,10 +145,10 @@ const ModuleRegistry &Instance::getModuleRegistry() const { ModuleRegistry &Instance::getModuleRegistry() { return *moduleRegistry_; } void Instance::handleMemoryPressure(int pressureLevel) { - if (auto execEnv = bundleRegistry_->getFirstExecutionEnvironment().lock()) { + if (auto execEnv = bundleRegistry_->getEnvironment(defaultEnvironmentId_).lock()) { execEnv->nativeToJsBridge->handleMemoryPressure(pressureLevel); } else { - throw std::runtime_error("BundleExecutionEnvironment pointer is invalid"); + throw std::runtime_error("BundleEnvironment pointer is invalid"); } } diff --git a/ReactCommon/cxxreact/Instance.h b/ReactCommon/cxxreact/Instance.h index f03f45e6a834..50474a0f8228 100644 --- a/ReactCommon/cxxreact/Instance.h +++ b/ReactCommon/cxxreact/Instance.h @@ -68,6 +68,8 @@ class RN_EXPORT Instance { std::shared_ptr moduleRegistry_; std::unique_ptr bundleRegistry_; + std::string defaultEnvironmentId_ = "default"; + std::mutex m_syncMutex; std::condition_variable m_syncCV; bool m_syncReady = false; From 69915d13047a349435073ee3bca401e41660369a Mon Sep 17 00:00:00 2001 From: Dratwas Date: Thu, 30 May 2019 11:56:34 +0200 Subject: [PATCH 2/2] rename BundleEnv --- ReactCommon/cxxreact/BundleRegistry.cpp | 10 +++++----- ReactCommon/cxxreact/BundleRegistry.h | 8 ++++---- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/ReactCommon/cxxreact/BundleRegistry.cpp b/ReactCommon/cxxreact/BundleRegistry.cpp index 465261b72030..d217614e8fe3 100644 --- a/ReactCommon/cxxreact/BundleRegistry.cpp +++ b/ReactCommon/cxxreact/BundleRegistry.cpp @@ -24,7 +24,7 @@ void BundleRegistry::preloadEnvironment(std::string environmentId, std::function folly::to("Environment with id = ", environmentId, " already exists") ); } - std::shared_ptr execEnv = std::make_shared(); + std::shared_ptr execEnv = std::make_shared(); execEnv->valid = false; execEnv->jsQueue = jsQueueFactory_(); execEnv->initialBundle = std::weak_ptr(); @@ -42,7 +42,7 @@ void BundleRegistry::preloadEnvironment(std::string environmentId, std::function void BundleRegistry::runInPreloadedEnvironment(std::string environmentId, std::unique_ptr initialBundle) { - std::shared_ptr execEnv = getEnvironment(environmentId).lock(); + std::shared_ptr execEnv = getEnvironment(environmentId).lock(); bundles_.push_back(std::move(initialBundle)); execEnv->initialBundle = std::weak_ptr(bundles_.back()); @@ -83,7 +83,7 @@ void BundleRegistry::runInPreloadedEnvironment(std::string environmentId, }); } -void BundleRegistry::evalInitialBundle(std::shared_ptr execEnv, +void BundleRegistry::evalInitialBundle(std::shared_ptr execEnv, std::unique_ptr startupScript, std::string sourceURL, LoadBundleLambda loadBundle, @@ -106,14 +106,14 @@ void BundleRegistry::disposeEnvironments() { } } -std::weak_ptr BundleRegistry::getEnvironment(std::string environmentId) { +std::weak_ptr BundleRegistry::getEnvironment(std::string environmentId) { if (!hasEnvironment(environmentId)) { throw std::runtime_error( folly::to("Cannot get environment with id = ", environmentId) ); } - return std::weak_ptr(bundleEnvironments_[environmentId]); + return std::weak_ptr(bundleEnvironments_[environmentId]); } bool BundleRegistry::hasEnvironment(std::string environmentId) { diff --git a/ReactCommon/cxxreact/BundleRegistry.h b/ReactCommon/cxxreact/BundleRegistry.h index 0456747d2063..7d67c67b245c 100644 --- a/ReactCommon/cxxreact/BundleRegistry.h +++ b/ReactCommon/cxxreact/BundleRegistry.h @@ -17,7 +17,7 @@ class BundleRegistry { using LoadBundleLambda = std::function; using GetModuleLambda = std::function; - struct BundleEnvironment { + struct BundleExecutionEnvironment { std::shared_ptr jsQueue; std::unique_ptr nativeToJsBridge; std::weak_ptr initialBundle; @@ -36,11 +36,11 @@ class BundleRegistry { void runInPreloadedEnvironment(std::string environmentId, std::unique_ptr initialBundle); void disposeEnvironments(); - std::weak_ptr getEnvironment(std::string environmentId); + std::weak_ptr getEnvironment(std::string environmentId); bool hasEnvironment(std::string environmentId); private: - std::map> bundleEnvironments_; + std::map> bundleEnvironments_; std::vector> bundles_; JSExecutorFactory* jsExecutorFactory_; std::shared_ptr moduleRegistry_; @@ -51,7 +51,7 @@ class BundleRegistry { * Setup environment and load initial bundle. Should be called only once * per BundleEnvironemnt. */ - void evalInitialBundle(std::shared_ptr execEnv, + void evalInitialBundle(std::shared_ptr execEnv, std::unique_ptr startupScript, std::string sourceURL, LoadBundleLambda loadBundle,