Index: ppapi/native_client/src/trusted/plugin/pnacl_coordinator.cc |
diff --git a/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.cc b/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.cc |
deleted file mode 100644 |
index 74451845226d33a913c597e14b54c0c5690a50da..0000000000000000000000000000000000000000 |
--- a/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.cc |
+++ /dev/null |
@@ -1,458 +0,0 @@ |
-// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
-// Use of this source code is governed by a BSD-style license that can be |
-// found in the LICENSE file. |
- |
-#include "ppapi/native_client/src/trusted/plugin/pnacl_coordinator.h" |
- |
-#include <algorithm> |
-#include <sstream> |
-#include <utility> |
- |
-#include "native_client/src/include/portability_io.h" |
-#include "native_client/src/shared/platform/nacl_check.h" |
-#include "native_client/src/trusted/service_runtime/include/sys/stat.h" |
- |
-#include "ppapi/c/pp_bool.h" |
-#include "ppapi/c/pp_errors.h" |
-#include "ppapi/c/private/ppb_uma_private.h" |
- |
-#include "ppapi/native_client/src/trusted/plugin/plugin.h" |
-#include "ppapi/native_client/src/trusted/plugin/plugin_error.h" |
-#include "ppapi/native_client/src/trusted/plugin/pnacl_translate_thread.h" |
-#include "ppapi/native_client/src/trusted/plugin/service_runtime.h" |
-#include "ppapi/native_client/src/trusted/plugin/temporary_file.h" |
- |
-namespace plugin { |
- |
-namespace { |
- |
-const int32_t kSizeKBMin = 1; |
-const int32_t kSizeKBMax = 512*1024; // very large .pexe / .nexe. |
-const uint32_t kSizeKBBuckets = 100; |
- |
-const int32_t kRatioMin = 10; |
-const int32_t kRatioMax = 10*100; // max of 10x difference. |
-const uint32_t kRatioBuckets = 100; |
- |
-void HistogramSizeKB(pp::UMAPrivate& uma, |
- const std::string& name, int32_t kb) { |
- if (kb < 0) return; |
- uma.HistogramCustomCounts(name, |
- kb, |
- kSizeKBMin, kSizeKBMax, |
- kSizeKBBuckets); |
-} |
- |
-void HistogramRatio(pp::UMAPrivate& uma, |
- const std::string& name, int64_t a, int64_t b) { |
- if (a < 0 || b <= 0) return; |
- uma.HistogramCustomCounts(name, |
- static_cast<int32_t>(100 * a / b), |
- kRatioMin, kRatioMax, |
- kRatioBuckets); |
-} |
- |
-std::string GetArchitectureAttributes(Plugin* plugin) { |
- pp::Var attrs_var(pp::PASS_REF, |
- plugin->nacl_interface()->GetCpuFeatureAttrs()); |
- return attrs_var.AsString(); |
-} |
- |
-void DidCacheHit(void* user_data, PP_FileHandle nexe_file_handle) { |
- PnaclCoordinator* coordinator = static_cast<PnaclCoordinator*>(user_data); |
- coordinator->BitcodeStreamCacheHit(nexe_file_handle); |
-} |
- |
-void DidCacheMiss(void* user_data, int64_t expected_pexe_size, |
- PP_FileHandle temp_nexe_file) { |
- PnaclCoordinator* coordinator = static_cast<PnaclCoordinator*>(user_data); |
- coordinator->BitcodeStreamCacheMiss(expected_pexe_size, |
- temp_nexe_file); |
-} |
- |
-void DidStreamData(void* user_data, const void* stream_data, int32_t length) { |
- PnaclCoordinator* coordinator = static_cast<PnaclCoordinator*>(user_data); |
- coordinator->BitcodeStreamGotData(stream_data, length); |
-} |
- |
-void DidFinishStream(void* user_data, int32_t pp_error) { |
- PnaclCoordinator* coordinator = static_cast<PnaclCoordinator*>(user_data); |
- coordinator->BitcodeStreamDidFinish(pp_error); |
-} |
- |
-PPP_PexeStreamHandler kPexeStreamHandler = { |
- &DidCacheHit, |
- &DidCacheMiss, |
- &DidStreamData, |
- &DidFinishStream |
-}; |
- |
-} // namespace |
- |
-PnaclCoordinator* PnaclCoordinator::BitcodeToNative( |
- Plugin* plugin, |
- const std::string& pexe_url, |
- const PP_PNaClOptions& pnacl_options, |
- const pp::CompletionCallback& translate_notify_callback) { |
- PLUGIN_PRINTF(("PnaclCoordinator::BitcodeToNative (plugin=%p, pexe=%s)\n", |
- static_cast<void*>(plugin), pexe_url.c_str())); |
- PnaclCoordinator* coordinator = |
- new PnaclCoordinator(plugin, pexe_url, |
- pnacl_options, |
- translate_notify_callback); |
- |
- GetNaClInterface()->SetPNaClStartTime(plugin->pp_instance()); |
- 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 |
- // a bitcode->nexe cache hit. |
- coordinator->OpenBitcodeStream(); |
- return coordinator; |
-} |
- |
-PnaclCoordinator::PnaclCoordinator( |
- Plugin* plugin, |
- const std::string& pexe_url, |
- const PP_PNaClOptions& pnacl_options, |
- const pp::CompletionCallback& translate_notify_callback) |
- : translate_finish_error_(PP_OK), |
- plugin_(plugin), |
- translate_notify_callback_(translate_notify_callback), |
- translation_finished_reported_(false), |
- pexe_url_(pexe_url), |
- pnacl_options_(pnacl_options), |
- architecture_attributes_(GetArchitectureAttributes(plugin)), |
- split_module_count_(1), |
- error_already_reported_(false), |
- pexe_size_(0), |
- pexe_bytes_compiled_(0), |
- expected_pexe_size_(-1) { |
- callback_factory_.Initialize(this); |
-} |
- |
-PnaclCoordinator::~PnaclCoordinator() { |
- PLUGIN_PRINTF(("PnaclCoordinator::~PnaclCoordinator (this=%p, " |
- "translate_thread=%p\n", |
- static_cast<void*>(this), translate_thread_.get())); |
- // Stopping the translate thread will cause the translate thread to try to |
- // run translation_complete_callback_ on the main thread. This destructor is |
- // running from the main thread, and by the time it exits, callback_factory_ |
- // will have been destroyed. This will result in the cancellation of |
- // translation_complete_callback_, so no notification will be delivered. |
- if (translate_thread_.get() != NULL) |
- translate_thread_->AbortSubprocesses(); |
- if (!translation_finished_reported_) { |
- plugin_->nacl_interface()->ReportTranslationFinished( |
- plugin_->pp_instance(), |
- PP_FALSE, 0, 0, 0); |
- } |
- // Force deleting the translate_thread now. It must be deleted |
- // before any scoped_* fields hanging off of PnaclCoordinator |
- // since the thread may be accessing those fields. |
- // It will also be accessing obj_files_. |
- translate_thread_.reset(NULL); |
- for (size_t i = 0; i < obj_files_.size(); i++) |
- delete obj_files_[i]; |
-} |
- |
-PP_FileHandle PnaclCoordinator::TakeTranslatedFileHandle() { |
- DCHECK(temp_nexe_file_ != NULL); |
- return temp_nexe_file_->TakeFileHandle(); |
-} |
- |
-void PnaclCoordinator::ReportNonPpapiError(PP_NaClError err_code, |
- const std::string& message) { |
- ErrorInfo error_info; |
- error_info.SetReport(err_code, message); |
- plugin_->ReportLoadError(error_info); |
- ExitWithError(); |
-} |
- |
-void PnaclCoordinator::ReportPpapiError(PP_NaClError err_code, |
- int32_t pp_error, |
- const std::string& message) { |
- std::stringstream ss; |
- ss << "PnaclCoordinator: " << message << " (pp_error=" << pp_error << ")."; |
- ErrorInfo error_info; |
- error_info.SetReport(err_code, ss.str()); |
- plugin_->ReportLoadError(error_info); |
- ExitWithError(); |
-} |
- |
-void PnaclCoordinator::ExitWithError() { |
- PLUGIN_PRINTF(("PnaclCoordinator::ExitWithError\n")); |
- // Free all the intermediate callbacks we ever created. |
- // Note: this doesn't *cancel* the callbacks from the factories attached |
- // to the various helper classes (e.g., pnacl_resources). Thus, those |
- // callbacks may still run asynchronously. We let those run but ignore |
- // any other errors they may generate so that they do not end up running |
- // translate_notify_callback_, which has already been freed. |
- callback_factory_.CancelAll(); |
- if (!error_already_reported_) { |
- error_already_reported_ = true; |
- translation_finished_reported_ = true; |
- plugin_->nacl_interface()->ReportTranslationFinished( |
- plugin_->pp_instance(), |
- PP_FALSE, 0, 0, 0); |
- translate_notify_callback_.Run(PP_ERROR_FAILED); |
- } |
-} |
- |
-// Signal that Pnacl translation completed normally. |
-void PnaclCoordinator::TranslateFinished(int32_t pp_error) { |
- PLUGIN_PRINTF(("PnaclCoordinator::TranslateFinished (pp_error=%" |
- NACL_PRId32 ")\n", pp_error)); |
- // Bail out if there was an earlier error (e.g., pexe load failure), |
- // or if there is an error from the translation thread. |
- if (translate_finish_error_ != PP_OK || pp_error != PP_OK) { |
- plugin_->ReportLoadError(error_info_); |
- ExitWithError(); |
- return; |
- } |
- |
- // Send out one last progress event, to finish up the progress events |
- // that were delayed (see the delay inserted in BitcodeGotCompiled). |
- if (expected_pexe_size_ != -1) { |
- pexe_bytes_compiled_ = expected_pexe_size_; |
- GetNaClInterface()->DispatchEvent(plugin_->pp_instance(), |
- PP_NACL_EVENT_PROGRESS, |
- pexe_url_.c_str(), |
- PP_TRUE, |
- pexe_bytes_compiled_, |
- expected_pexe_size_); |
- } |
- struct nacl_abi_stat stbuf; |
- struct NaClDesc* desc = temp_nexe_file_->read_wrapper()->desc(); |
- if (0 == (*((struct NaClDescVtbl const *)desc->base.vtbl)->Fstat)(desc, |
- &stbuf)) { |
- nacl_abi_off_t nexe_size = stbuf.nacl_abi_st_size; |
- HistogramSizeKB(plugin_->uma_interface(), |
- "NaCl.Perf.Size.PNaClTranslatedNexe", |
- static_cast<int32_t>(nexe_size / 1024)); |
- HistogramRatio(plugin_->uma_interface(), |
- "NaCl.Perf.Size.PexeNexeSizePct", pexe_size_, nexe_size); |
- } |
- // The nexe is written to the temp_nexe_file_. We must Reset() the file |
- // pointer to be able to read it again from the beginning. |
- temp_nexe_file_->Reset(); |
- |
- // Report to the browser that translation finished. The browser will take |
- // care of storing the nexe in the cache. |
- translation_finished_reported_ = true; |
- plugin_->nacl_interface()->ReportTranslationFinished( |
- plugin_->pp_instance(), PP_TRUE, pnacl_options_.opt_level, |
- pexe_size_, translate_thread_->GetCompileTime()); |
- |
- NexeReadDidOpen(PP_OK); |
-} |
- |
-void PnaclCoordinator::NexeReadDidOpen(int32_t pp_error) { |
- PLUGIN_PRINTF(("PnaclCoordinator::NexeReadDidOpen (pp_error=%" |
- NACL_PRId32 ")\n", pp_error)); |
- if (pp_error != PP_OK) { |
- if (pp_error == PP_ERROR_FILENOTFOUND) { |
- ReportPpapiError(PP_NACL_ERROR_PNACL_CACHE_FETCH_NOTFOUND, |
- pp_error, |
- "Failed to open translated nexe (not found)."); |
- return; |
- } |
- if (pp_error == PP_ERROR_NOACCESS) { |
- ReportPpapiError(PP_NACL_ERROR_PNACL_CACHE_FETCH_NOACCESS, |
- pp_error, |
- "Failed to open translated nexe (no access)."); |
- return; |
- } |
- ReportPpapiError(PP_NACL_ERROR_PNACL_CACHE_FETCH_OTHER, |
- pp_error, |
- "Failed to open translated nexe."); |
- return; |
- } |
- |
- translate_notify_callback_.Run(PP_OK); |
-} |
- |
-void PnaclCoordinator::OpenBitcodeStream() { |
- // Even though we haven't started downloading, create the translation |
- // thread object immediately. This ensures that any pieces of the file |
- // that get downloaded before the compilation thread is accepting |
- // SRPCs won't get dropped. |
- translate_thread_.reset(new PnaclTranslateThread()); |
- if (translate_thread_ == NULL) { |
- ReportNonPpapiError( |
- PP_NACL_ERROR_PNACL_THREAD_CREATE, |
- "PnaclCoordinator: could not allocate translation thread."); |
- return; |
- } |
- |
- GetNaClInterface()->StreamPexe(plugin_->pp_instance(), |
- pexe_url_.c_str(), |
- pnacl_options_.opt_level, |
- &kPexeStreamHandler, |
- this); |
-} |
- |
-void PnaclCoordinator::BitcodeStreamCacheHit(PP_FileHandle handle) { |
- if (handle == PP_kInvalidFileHandle) { |
- ReportNonPpapiError( |
- PP_NACL_ERROR_PNACL_CREATE_TEMP, |
- std::string( |
- "PnaclCoordinator: Got bad temp file handle from GetNexeFd")); |
- BitcodeStreamDidFinish(PP_ERROR_FAILED); |
- return; |
- } |
- temp_nexe_file_.reset(new TempFile(plugin_, handle)); |
- // Open it for reading as the cached nexe file. |
- NexeReadDidOpen(temp_nexe_file_->Open(false)); |
-} |
- |
-void PnaclCoordinator::BitcodeStreamCacheMiss(int64_t expected_pexe_size, |
- PP_FileHandle nexe_handle) { |
- // IMPORTANT: Make sure that PnaclResources::StartLoad() is only |
- // called after you receive a response to a request for a .pexe file. |
- // |
- // The component updater's resource throttles + OnDemand update/install |
- // should block the URL request until the compiler is present. Now we |
- // can load the resources (e.g. llc and ld nexes). |
- resources_.reset(new PnaclResources(plugin_)); |
- CHECK(resources_ != NULL); |
- |
- // The first step of loading resources: read the resource info file. |
- if (!resources_->ReadResourceInfo()) { |
- ExitWithError(); |
- return; |
- } |
- |
- // Second step of loading resources: call StartLoad to load pnacl-llc |
- // and pnacl-ld, based on the filenames found in the resource info file. |
- if (!resources_->StartLoad()) { |
- ReportNonPpapiError( |
- PP_NACL_ERROR_PNACL_RESOURCE_FETCH, |
- std::string("The Portable Native Client (pnacl) component is not " |
- "installed. Please consult chrome://components for more " |
- "information.")); |
- return; |
- } |
- |
- expected_pexe_size_ = expected_pexe_size; |
- |
- for (int i = 0; i < split_module_count_; i++) { |
- PP_FileHandle obj_handle = |
- plugin_->nacl_interface()->CreateTemporaryFile(plugin_->pp_instance()); |
- nacl::scoped_ptr<TempFile> temp_file(new TempFile(plugin_, obj_handle)); |
- int32_t pp_error = temp_file->Open(true); |
- if (pp_error != PP_OK) { |
- ReportPpapiError(PP_NACL_ERROR_PNACL_CREATE_TEMP, |
- pp_error, |
- "Failed to open scratch object file."); |
- return; |
- } else { |
- obj_files_.push_back(temp_file.release()); |
- } |
- } |
- invalid_desc_wrapper_.reset(plugin_->wrapper_factory()->MakeInvalid()); |
- |
- temp_nexe_file_.reset(new TempFile(plugin_, nexe_handle)); |
- // Open the nexe file for connecting ld and sel_ldr. |
- // Start translation when done with this last step of setup! |
- RunTranslate(temp_nexe_file_->Open(true)); |
-} |
- |
-void PnaclCoordinator::BitcodeStreamGotData(const void* data, int32_t length) { |
- DCHECK(translate_thread_.get()); |
- |
- translate_thread_->PutBytes(data, length); |
- if (data && length > 0) |
- pexe_size_ += length; |
-} |
- |
-void PnaclCoordinator::BitcodeStreamDidFinish(int32_t pp_error) { |
- PLUGIN_PRINTF(("PnaclCoordinator::BitcodeStreamDidFinish (pp_error=%" |
- NACL_PRId32 ")\n", pp_error)); |
- if (pp_error != PP_OK) { |
- // Defer reporting the error and cleanup until after the translation |
- // thread returns, because it may be accessing the coordinator's |
- // objects or writing to the files. |
- translate_finish_error_ = pp_error; |
- if (pp_error == PP_ERROR_ABORTED) { |
- error_info_.SetReport(PP_NACL_ERROR_PNACL_PEXE_FETCH_ABORTED, |
- "PnaclCoordinator: pexe load failed (aborted)."); |
- } |
- if (pp_error == PP_ERROR_NOACCESS) { |
- error_info_.SetReport(PP_NACL_ERROR_PNACL_PEXE_FETCH_NOACCESS, |
- "PnaclCoordinator: pexe load failed (no access)."); |
- } else { |
- std::stringstream ss; |
- ss << "PnaclCoordinator: pexe load failed (pp_error=" << pp_error << ")."; |
- error_info_.SetReport(PP_NACL_ERROR_PNACL_PEXE_FETCH_OTHER, ss.str()); |
- } |
- |
- if (translate_thread_->started()) |
- translate_thread_->AbortSubprocesses(); |
- else |
- TranslateFinished(pp_error); |
- } else { |
- // Compare download completion pct (100% now), to compile completion pct. |
- HistogramRatio(plugin_->uma_interface(), |
- "NaCl.Perf.PNaClLoadTime.PctCompiledWhenFullyDownloaded", |
- pexe_bytes_compiled_, pexe_size_); |
- translate_thread_->EndStream(); |
- } |
-} |
- |
-void PnaclCoordinator::BitcodeGotCompiled(int32_t pp_error, |
- int64_t bytes_compiled) { |
- DCHECK(pp_error == PP_OK); |
- pexe_bytes_compiled_ += bytes_compiled; |
- // Hold off reporting the last few bytes of progress, since we don't know |
- // when they are actually completely compiled. "bytes_compiled" only means |
- // that bytes were sent to the compiler. |
- if (expected_pexe_size_ != -1) { |
- if (!ShouldDelayProgressEvent()) { |
- GetNaClInterface()->DispatchEvent(plugin_->pp_instance(), |
- PP_NACL_EVENT_PROGRESS, |
- pexe_url_.c_str(), |
- PP_TRUE, |
- pexe_bytes_compiled_, |
- expected_pexe_size_); |
- } |
- } else { |
- GetNaClInterface()->DispatchEvent(plugin_->pp_instance(), |
- PP_NACL_EVENT_PROGRESS, |
- pexe_url_.c_str(), |
- PP_FALSE, |
- pexe_bytes_compiled_, |
- expected_pexe_size_); |
- } |
-} |
- |
-pp::CompletionCallback PnaclCoordinator::GetCompileProgressCallback( |
- int64_t bytes_compiled) { |
- return callback_factory_.NewCallback(&PnaclCoordinator::BitcodeGotCompiled, |
- bytes_compiled); |
-} |
- |
-void PnaclCoordinator::RunTranslate(int32_t pp_error) { |
- PLUGIN_PRINTF(("PnaclCoordinator::RunTranslate (pp_error=%" |
- NACL_PRId32 ")\n", pp_error)); |
- // Invoke llc followed by ld off the main thread. This allows use of |
- // blocking RPCs that would otherwise block the JavaScript main thread. |
- pp::CompletionCallback report_translate_finished = |
- callback_factory_.NewCallback(&PnaclCoordinator::TranslateFinished); |
- |
- CHECK(translate_thread_ != NULL); |
- translate_thread_->RunTranslate(report_translate_finished, |
- &obj_files_, |
- temp_nexe_file_.get(), |
- invalid_desc_wrapper_.get(), |
- &error_info_, |
- resources_.get(), |
- &pnacl_options_, |
- architecture_attributes_, |
- this, |
- plugin_); |
-} |
- |
-} // namespace plugin |