diff options
author | dschuff@chromium.org <dschuff@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-02-15 00:36:53 +0000 |
---|---|---|
committer | dschuff@chromium.org <dschuff@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-02-15 00:36:53 +0000 |
commit | a91b574d029d385afd93652e0fb34b48271eb702 (patch) | |
tree | e5438705fa543e8d21e9ef9af79d7d22f6fead46 /ppapi | |
parent | 4532c970cc7dd85d59da72ef51e21f3c3b5799c4 (diff) | |
download | chromium_src-a91b574d029d385afd93652e0fb34b48271eb702.zip chromium_src-a91b574d029d385afd93652e0fb34b48271eb702.tar.gz chromium_src-a91b574d029d385afd93652e0fb34b48271eb702.tar.bz2 |
PnaclCoordinator: Use llc's module-splitting for pexe compilation
When there is more than 1 core in the system, request extra temp files
and use LLC's StreamInitWithSplit rpc to enable module splitting.
If the RPC fails, fall back to StreamInitWithOverrides.
Add a private Pepper interface to get the cpu count rather than
duplicating base::SysInfo in the plugin.
TEST=browser_tests --gtest_filter=NaClBrowserTstPnacl.*
BUG= https://code.google.com/p/nativeclient/issues/detail?id=3777
R=jschuh@chromium.org, jvoung@chromium.org, teravest@chromium.org
Review URL: https://codereview.chromium.org/165433003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@251458 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ppapi')
7 files changed, 169 insertions, 41 deletions
diff --git a/ppapi/api/private/ppb_nacl_private.idl b/ppapi/api/private/ppb_nacl_private.idl index 6dfbff7..a674328 100644 --- a/ppapi/api/private/ppb_nacl_private.idl +++ b/ppapi/api/private/ppb_nacl_private.idl @@ -110,6 +110,9 @@ interface PPB_NaCl_Private { */ PP_FileHandle CreateTemporaryFile([in] PP_Instance instance); + /* Return the number of processors in the system as reported by the OS */ + int32_t GetNumberOfProcessors(); + /* Create a temporary file, which will be deleted by the time the * last handle is closed (or earlier on POSIX systems), to use for * the nexe with the cache information given by |pexe_url|, diff --git a/ppapi/c/private/ppb_nacl_private.h b/ppapi/c/private/ppb_nacl_private.h index 0001148..dde686b 100644 --- a/ppapi/c/private/ppb_nacl_private.h +++ b/ppapi/c/private/ppb_nacl_private.h @@ -3,7 +3,7 @@ * found in the LICENSE file. */ -/* From private/ppb_nacl_private.idl modified Mon Feb 10 11:05:29 2014. */ +/* From private/ppb_nacl_private.idl modified Thu Feb 13 15:50:26 2014. */ #ifndef PPAPI_C_PRIVATE_PPB_NACL_PRIVATE_H_ #define PPAPI_C_PRIVATE_PPB_NACL_PRIVATE_H_ @@ -127,6 +127,8 @@ struct PPB_NaCl_Private_1_0 { * returns a posix handle to that temporary file. */ PP_FileHandle (*CreateTemporaryFile)(PP_Instance instance); + /* Return the number of processors in the system as reported by the OS */ + int32_t (*GetNumberOfProcessors)(void); /* Create a temporary file, which will be deleted by the time the * last handle is closed (or earlier on POSIX systems), to use for * the nexe with the cache information given by |pexe_url|, diff --git a/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.cc b/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.cc index 9e96f0d..91112a0 100644 --- a/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.cc +++ b/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.cc @@ -200,6 +200,9 @@ PnaclCoordinator* PnaclCoordinator::BitcodeToNative( PLUGIN_PRINTF(("PnaclCoordinator::BitcodeToNative (manifest=%p, ", reinterpret_cast<const void*>(coordinator->manifest_.get()))); + int cpus = plugin->nacl_interface()->GetNumberOfProcessors(); + coordinator->split_module_count_ = std::min(4, std::max(1, cpus)); + // First start a network request for the pexe, to tickle the component // updater's On-Demand resource throttler, and to get Last-Modified/ETag // cache information. We can cancel the request later if there's @@ -220,6 +223,8 @@ PnaclCoordinator::PnaclCoordinator( manifest_(new PnaclManifest()), pexe_url_(pexe_url), pnacl_options_(pnacl_options), + split_module_count_(1), + num_object_files_opened_(0), is_cache_hit_(PP_FALSE), error_already_reported_(false), pnacl_init_time_(0), @@ -248,6 +253,9 @@ PnaclCoordinator::~PnaclCoordinator() { plugin_->pp_instance(), PP_FALSE); } + for (int i = 0; i < num_object_files_opened_; i++) { + delete obj_files_[i]; + } } nacl::DescWrapper* PnaclCoordinator::ReleaseTranslatedFD() { @@ -531,10 +539,14 @@ void PnaclCoordinator::NexeFdDidOpen(int32_t pp_error) { } else { // Open an object file first so the translator can start writing to it // during streaming translation. - obj_file_.reset(new TempFile(plugin_)); - pp::CompletionCallback obj_cb = - callback_factory_.NewCallback(&PnaclCoordinator::ObjectFileDidOpen); - obj_file_->Open(obj_cb, true); + for (int i = 0; i < split_module_count_; i++) { + obj_files_.push_back(new TempFile(plugin_)); + + pp::CompletionCallback obj_cb = + callback_factory_.NewCallback(&PnaclCoordinator::ObjectFileDidOpen); + obj_files_[i]->Open(obj_cb, true); + } + invalid_desc_wrapper_.reset(plugin_->wrapper_factory()->MakeInvalid()); // Meanwhile, a miss means we know we need to stream the bitcode, so stream // the rest of it now. (Calling FinishStreaming means that the downloader @@ -643,11 +655,14 @@ void PnaclCoordinator::ObjectFileDidOpen(int32_t pp_error) { "Failed to open scratch object file."); return; } - // Open the nexe file for connecting ld and sel_ldr. - // Start translation when done with this last step of setup! - pp::CompletionCallback cb = - callback_factory_.NewCallback(&PnaclCoordinator::RunTranslate); - temp_nexe_file_->Open(cb, true); + num_object_files_opened_++; + if (num_object_files_opened_ == split_module_count_) { + // Open the nexe file for connecting ld and sel_ldr. + // Start translation when done with this last step of setup! + pp::CompletionCallback cb = + callback_factory_.NewCallback(&PnaclCoordinator::RunTranslate); + temp_nexe_file_->Open(cb, true); + } } void PnaclCoordinator::RunTranslate(int32_t pp_error) { @@ -661,8 +676,9 @@ void PnaclCoordinator::RunTranslate(int32_t pp_error) { CHECK(translate_thread_ != NULL); translate_thread_->RunTranslate(report_translate_finished, manifest_.get(), - obj_file_.get(), + &obj_files_, temp_nexe_file_.get(), + invalid_desc_wrapper_.get(), &error_info_, resources_.get(), &pnacl_options_, diff --git a/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.h b/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.h index e38cbc0..9475b9e 100644 --- a/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.h +++ b/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.h @@ -77,6 +77,9 @@ class TempFile; // Complete when NexeReadDidOpen is invoked. class PnaclCoordinator: public CallbackSource<FileStreamData> { public: + // Maximum number of object files passable to the translator. Cannot be + // changed without changing the RPC signatures. + const static size_t kMaxTranslatorObjectFiles = 16; virtual ~PnaclCoordinator(); // The factory method for translations. @@ -202,7 +205,12 @@ class PnaclCoordinator: public CallbackSource<FileStreamData> { PnaclOptions pnacl_options_; // Object file, produced by the translator and consumed by the linker. - nacl::scoped_ptr<TempFile> obj_file_; + std::vector<TempFile*> obj_files_; + nacl::scoped_ptr<nacl::DescWrapper> invalid_desc_wrapper_; + // Number of split modules (threads) for llc + int split_module_count_; + int num_object_files_opened_; + // Translated nexe file, produced by the linker. nacl::scoped_ptr<TempFile> temp_nexe_file_; // Passed to the browser, which sets it to true if there is a translation diff --git a/ppapi/native_client/src/trusted/plugin/pnacl_translate_thread.cc b/ppapi/native_client/src/trusted/plugin/pnacl_translate_thread.cc index d51efe4..2093aaf 100644 --- a/ppapi/native_client/src/trusted/plugin/pnacl_translate_thread.cc +++ b/ppapi/native_client/src/trusted/plugin/pnacl_translate_thread.cc @@ -4,6 +4,8 @@ #include "ppapi/native_client/src/trusted/plugin/pnacl_translate_thread.h" +#include <iterator> + #include "native_client/src/trusted/desc/nacl_desc_wrapper.h" #include "ppapi/native_client/src/trusted/plugin/plugin.h" #include "ppapi/native_client/src/trusted/plugin/plugin_error.h" @@ -19,7 +21,7 @@ PnaclTranslateThread::PnaclTranslateThread() : llc_subprocess_active_(false), done_(false), time_stats_(), manifest_(NULL), - obj_file_(NULL), + obj_files_(NULL), nexe_file_(NULL), coordinator_error_info_(NULL), resources_(NULL), @@ -33,8 +35,9 @@ PnaclTranslateThread::PnaclTranslateThread() : llc_subprocess_active_(false), void PnaclTranslateThread::RunTranslate( const pp::CompletionCallback& finish_callback, const Manifest* manifest, - TempFile* obj_file, + const std::vector<TempFile*>* obj_files, TempFile* nexe_file, + nacl::DescWrapper* invalid_desc_wrapper, ErrorInfo* error_info, PnaclResources* resources, PnaclOptions* pnacl_options, @@ -42,8 +45,9 @@ void PnaclTranslateThread::RunTranslate( Plugin* plugin) { PLUGIN_PRINTF(("PnaclStreamingTranslateThread::RunTranslate)\n")); manifest_ = manifest; - obj_file_ = obj_file; + obj_files_ = obj_files; nexe_file_ = nexe_file; + invalid_desc_wrapper_ = invalid_desc_wrapper; coordinator_error_info_ = error_info; resources_ = resources; pnacl_options_ = pnacl_options; @@ -130,7 +134,14 @@ void WINAPI PnaclTranslateThread::DoTranslateThread(void* arg) { void PnaclTranslateThread::DoTranslate() { ErrorInfo error_info; SrpcParams params; - nacl::DescWrapper* llc_out_file = obj_file_->write_wrapper(); + std::vector<nacl::DescWrapper*> llc_out_files; + size_t i; + for (i = 0; i < obj_files_->size(); i++) { + llc_out_files.push_back((*obj_files_)[i]->write_wrapper()); + } + for (; i < PnaclCoordinator::kMaxTranslatorObjectFiles; i++) { + llc_out_files.push_back(invalid_desc_wrapper_); + } { nacl::MutexLocker ml(&subprocess_mu_); @@ -149,19 +160,60 @@ void PnaclTranslateThread::DoTranslate() { // Run LLC. PluginReverseInterface* llc_reverse = llc_subprocess_->service_runtime()->rev_interface(); - llc_reverse->AddTempQuotaManagedFile(obj_file_->identifier()); + for (size_t i = 0; i < obj_files_->size(); i++) { + llc_reverse->AddTempQuotaManagedFile((*obj_files_)[i]->identifier()); + } } int64_t compile_start_time = NaClGetTimeOfDayMicroseconds(); bool init_success; std::vector<char> options = pnacl_options_->GetOptCommandline(); + + // Try to init with splitting + // TODO(dschuff): This CL override is ugly. Change llc to default to using + // the number of modules specified in the first param, and ignore multiple + // uses of -split-module + std::vector<char> split_args; + nacl::stringstream ss; + ss << "-split-module=" << obj_files_->size(); + nacl::string split_arg = ss.str(); + std::copy(split_arg.begin(), split_arg.end(), std::back_inserter(split_args)); + split_args.push_back('\x00'); + std::copy(options.begin(), options.end(), std::back_inserter(split_args)); + int modules_used = static_cast<int>(obj_files_->size()); init_success = llc_subprocess_->InvokeSrpcMethod( - "StreamInitWithOverrides", - "hC", + "StreamInitWithSplit", + "ihhhhhhhhhhhhhhhhC", ¶ms, - llc_out_file->desc(), - &options[0], - options.size()); + modules_used, + llc_out_files[0]->desc(), + llc_out_files[1]->desc(), + llc_out_files[2]->desc(), + llc_out_files[3]->desc(), + llc_out_files[4]->desc(), + llc_out_files[5]->desc(), + llc_out_files[6]->desc(), + llc_out_files[7]->desc(), + llc_out_files[8]->desc(), + llc_out_files[9]->desc(), + llc_out_files[10]->desc(), + llc_out_files[11]->desc(), + llc_out_files[12]->desc(), + llc_out_files[13]->desc(), + llc_out_files[14]->desc(), + llc_out_files[15]->desc(), + &split_args[0], + split_args.size()); + if (!init_success) { + init_success = llc_subprocess_->InvokeSrpcMethod( + "StreamInitWithOverrides", + "hC", + ¶ms, + llc_out_files[0]->desc(), + &options[0], + options.size()); + modules_used = 1; + } if (!init_success) { if (llc_subprocess_->srpc_client()->GetLastError() == @@ -256,25 +308,36 @@ void PnaclTranslateThread::DoTranslate() { llc_subprocess_.reset(NULL); NaClXMutexUnlock(&subprocess_mu_); - if(!RunLdSubprocess(is_shared_library, soname, lib_dependencies)) { + if(!RunLdSubprocess( + modules_used, is_shared_library, soname, lib_dependencies)) { return; } core->CallOnMainThread(0, report_translate_finished_, PP_OK); } -bool PnaclTranslateThread::RunLdSubprocess(int is_shared_library, +bool PnaclTranslateThread::RunLdSubprocess(int modules_used, + int is_shared_library, const nacl::string& soname, const nacl::string& lib_dependencies ) { ErrorInfo error_info; SrpcParams params; - // Reset object file for reading first. - if (!obj_file_->Reset()) { - TranslateFailed(ERROR_PNACL_LD_SETUP, - "Link process could not reset object file"); - return false; + + std::vector<nacl::DescWrapper*> ld_in_files; + size_t i; + for (i = 0; i < obj_files_->size(); i++) { + // Reset object file for reading first. + if (!(*obj_files_)[i]->Reset()) { + TranslateFailed(ERROR_PNACL_LD_SETUP, + "Link process could not reset object file"); + return false; + } + ld_in_files.push_back((*obj_files_)[i]->read_wrapper()); } - nacl::DescWrapper* ld_in_file = obj_file_->read_wrapper(); + for (; i < PnaclCoordinator::kMaxTranslatorObjectFiles; i++) { + ld_in_files.push_back(invalid_desc_wrapper_); + } + nacl::DescWrapper* ld_out_file = nexe_file_->write_wrapper(); { @@ -299,14 +362,41 @@ bool PnaclTranslateThread::RunLdSubprocess(int is_shared_library, int64_t link_start_time = NaClGetTimeOfDayMicroseconds(); // Run LD. - if (!ld_subprocess_->InvokeSrpcMethod("RunWithDefaultCommandLine", - "hhiss", - ¶ms, - ld_in_file->desc(), - ld_out_file->desc(), - is_shared_library, - soname.c_str(), - lib_dependencies.c_str())) { + bool success; + // If we ran LLC with module splitting, we can't fall back here. + if (modules_used > 1) { + success = ld_subprocess_->InvokeSrpcMethod("RunWithSplit", + "ihhhhhhhhhhhhhhhhh", + ¶ms, + modules_used, + ld_in_files[0]->desc(), + ld_in_files[1]->desc(), + ld_in_files[2]->desc(), + ld_in_files[3]->desc(), + ld_in_files[4]->desc(), + ld_in_files[5]->desc(), + ld_in_files[6]->desc(), + ld_in_files[7]->desc(), + ld_in_files[8]->desc(), + ld_in_files[9]->desc(), + ld_in_files[10]->desc(), + ld_in_files[11]->desc(), + ld_in_files[12]->desc(), + ld_in_files[13]->desc(), + ld_in_files[14]->desc(), + ld_in_files[15]->desc(), + ld_out_file->desc()); + } else { + success = ld_subprocess_->InvokeSrpcMethod("RunWithDefaultCommandLine", + "hhiss", + ¶ms, + ld_in_files[0]->desc(), + ld_out_file->desc(), + is_shared_library, + soname.c_str(), + lib_dependencies.c_str()); + } + if (!success) { TranslateFailed(ERROR_PNACL_LD_INTERNAL, "link failed."); return false; diff --git a/ppapi/native_client/src/trusted/plugin/pnacl_translate_thread.h b/ppapi/native_client/src/trusted/plugin/pnacl_translate_thread.h index 31981eb..11473b4 100644 --- a/ppapi/native_client/src/trusted/plugin/pnacl_translate_thread.h +++ b/ppapi/native_client/src/trusted/plugin/pnacl_translate_thread.h @@ -50,8 +50,9 @@ class PnaclTranslateThread { // as it is passed in with PutBytes. void RunTranslate(const pp::CompletionCallback& finish_callback, const Manifest* manifest, - TempFile* obj_file, + const std::vector<TempFile*>* obj_files, TempFile* nexe_file, + nacl::DescWrapper* invalid_desc_wrapper, ErrorInfo* error_info, PnaclResources* resources, PnaclOptions* pnacl_options, @@ -85,7 +86,8 @@ class PnaclTranslateThread { void TranslateFailed(enum PluginErrorCode err_code, const nacl::string& error_string); // Run the LD subprocess, returning true on success - bool RunLdSubprocess(int is_shared_library, + bool RunLdSubprocess(int modules_used, + int is_shared_library, const nacl::string& soname, const nacl::string& lib_dependencies); @@ -121,8 +123,9 @@ class PnaclTranslateThread { // Data about the translation files, owned by the coordinator const Manifest* manifest_; - TempFile* obj_file_; + const std::vector<TempFile*>* obj_files_; TempFile* nexe_file_; + nacl::DescWrapper* invalid_desc_wrapper_; ErrorInfo* coordinator_error_info_; PnaclResources* resources_; PnaclOptions* pnacl_options_; diff --git a/ppapi/native_client/src/untrusted/pnacl_irt_shim/pnacl_shim.c b/ppapi/native_client/src/untrusted/pnacl_irt_shim/pnacl_shim.c index 8696279..330c966 100644 --- a/ppapi/native_client/src/untrusted/pnacl_irt_shim/pnacl_shim.c +++ b/ppapi/native_client/src/untrusted/pnacl_irt_shim/pnacl_shim.c @@ -3144,6 +3144,11 @@ static PP_FileHandle Pnacl_M25_PPB_NaCl_Private_CreateTemporaryFile(PP_Instance return iface->CreateTemporaryFile(instance); } +static int32_t Pnacl_M25_PPB_NaCl_Private_GetNumberOfProcessors(void) { + const struct PPB_NaCl_Private_1_0 *iface = Pnacl_WrapperInfo_PPB_NaCl_Private_1_0.real_iface; + return iface->GetNumberOfProcessors(); +} + static int32_t Pnacl_M25_PPB_NaCl_Private_GetNexeFd(PP_Instance instance, const char* pexe_url, uint32_t abi_version, uint32_t opt_level, const char* last_modified, const char* etag, PP_Bool has_no_store_header, PP_Bool* is_hit, PP_FileHandle* nexe_handle, struct PP_CompletionCallback* callback) { const struct PPB_NaCl_Private_1_0 *iface = Pnacl_WrapperInfo_PPB_NaCl_Private_1_0.real_iface; return iface->GetNexeFd(instance, pexe_url, abi_version, opt_level, last_modified, etag, has_no_store_header, is_hit, nexe_handle, *callback); @@ -5045,6 +5050,7 @@ static struct PPB_NaCl_Private_1_0 Pnacl_Wrappers_PPB_NaCl_Private_1_0 = { .BrokerDuplicateHandle = (int32_t (*)(PP_FileHandle source_handle, uint32_t process_id, PP_FileHandle* target_handle, uint32_t desired_access, uint32_t options))&Pnacl_M25_PPB_NaCl_Private_BrokerDuplicateHandle, .GetReadonlyPnaclFd = (PP_FileHandle (*)(const char* filename))&Pnacl_M25_PPB_NaCl_Private_GetReadonlyPnaclFd, .CreateTemporaryFile = (PP_FileHandle (*)(PP_Instance instance))&Pnacl_M25_PPB_NaCl_Private_CreateTemporaryFile, + .GetNumberOfProcessors = (int32_t (*)(void))&Pnacl_M25_PPB_NaCl_Private_GetNumberOfProcessors, .GetNexeFd = (int32_t (*)(PP_Instance instance, const char* pexe_url, uint32_t abi_version, uint32_t opt_level, const char* last_modified, const char* etag, PP_Bool has_no_store_header, PP_Bool* is_hit, PP_FileHandle* nexe_handle, struct PP_CompletionCallback callback))&Pnacl_M25_PPB_NaCl_Private_GetNexeFd, .ReportTranslationFinished = (void (*)(PP_Instance instance, PP_Bool success))&Pnacl_M25_PPB_NaCl_Private_ReportTranslationFinished, .ReportNaClError = (PP_ExternalPluginResult (*)(PP_Instance instance, PP_NaClError message_id))&Pnacl_M25_PPB_NaCl_Private_ReportNaClError, |