Index: ppapi/native_client/src/trusted/plugin/pnacl_translate_thread.cc |
diff --git a/ppapi/native_client/src/trusted/plugin/pnacl_translate_thread.cc b/ppapi/native_client/src/trusted/plugin/pnacl_translate_thread.cc |
deleted file mode 100644 |
index 12f776c97f01b2d29bea602b2af60081260c8193..0000000000000000000000000000000000000000 |
--- a/ppapi/native_client/src/trusted/plugin/pnacl_translate_thread.cc |
+++ /dev/null |
@@ -1,443 +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_translate_thread.h" |
- |
-#include <iterator> |
-#include <sstream> |
- |
-#include "native_client/src/shared/platform/nacl_check.h" |
-#include "native_client/src/trusted/desc/nacl_desc_wrapper.h" |
-#include "ppapi/cpp/var.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_resources.h" |
-#include "ppapi/native_client/src/trusted/plugin/srpc_params.h" |
-#include "ppapi/native_client/src/trusted/plugin/temporary_file.h" |
-#include "ppapi/native_client/src/trusted/plugin/utility.h" |
- |
-namespace plugin { |
-namespace { |
- |
-template <typename Val> |
-std::string MakeCommandLineArg(const char* key, const Val val) { |
- std::stringstream ss; |
- ss << key << val; |
- return ss.str(); |
-} |
- |
-void GetLlcCommandLine(Plugin* plugin, |
- std::vector<char>* split_args, |
- size_t obj_files_size, |
- int32_t opt_level, |
- bool is_debug, |
- const std::string &architecture_attributes) { |
- typedef std::vector<std::string> Args; |
- Args args; |
- |
- // 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 |
- args.push_back(MakeCommandLineArg("-split-module=", obj_files_size)); |
- args.push_back(MakeCommandLineArg("-O=", opt_level)); |
- if (is_debug) |
- args.push_back("-bitcode-format=llvm"); |
- if (!architecture_attributes.empty()) |
- args.push_back("-mattr=" + architecture_attributes); |
- |
- for (Args::const_iterator arg(args.begin()); arg != args.end(); ++arg) { |
- std::copy(arg->begin(), arg->end(), std::back_inserter(*split_args)); |
- split_args->push_back('\x00'); |
- } |
-} |
- |
-} // namespace |
- |
-PnaclTranslateThread::PnaclTranslateThread() : llc_subprocess_active_(false), |
- ld_subprocess_active_(false), |
- subprocesses_aborted_(false), |
- done_(false), |
- compile_time_(0), |
- obj_files_(NULL), |
- nexe_file_(NULL), |
- coordinator_error_info_(NULL), |
- resources_(NULL), |
- coordinator_(NULL), |
- plugin_(NULL) { |
- NaClXMutexCtor(&subprocess_mu_); |
- NaClXMutexCtor(&cond_mu_); |
- NaClXCondVarCtor(&buffer_cond_); |
-} |
- |
-void PnaclTranslateThread::RunTranslate( |
- const pp::CompletionCallback& finish_callback, |
- const std::vector<TempFile*>* obj_files, |
- TempFile* nexe_file, |
- nacl::DescWrapper* invalid_desc_wrapper, |
- ErrorInfo* error_info, |
- PnaclResources* resources, |
- PP_PNaClOptions* pnacl_options, |
- const std::string &architecture_attributes, |
- PnaclCoordinator* coordinator, |
- Plugin* plugin) { |
- PLUGIN_PRINTF(("PnaclStreamingTranslateThread::RunTranslate)\n")); |
- 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; |
- architecture_attributes_ = architecture_attributes; |
- coordinator_ = coordinator; |
- plugin_ = plugin; |
- |
- // Invoke llc followed by ld off the main thread. This allows use of |
- // blocking RPCs that would otherwise block the JavaScript main thread. |
- report_translate_finished_ = finish_callback; |
- translate_thread_.reset(new NaClThread); |
- if (translate_thread_ == NULL) { |
- TranslateFailed(PP_NACL_ERROR_PNACL_THREAD_CREATE, |
- "could not allocate thread struct."); |
- return; |
- } |
- const int32_t kArbitraryStackSize = 128 * 1024; |
- if (!NaClThreadCreateJoinable(translate_thread_.get(), |
- DoTranslateThread, |
- this, |
- kArbitraryStackSize)) { |
- TranslateFailed(PP_NACL_ERROR_PNACL_THREAD_CREATE, |
- "could not create thread."); |
- translate_thread_.reset(NULL); |
- } |
-} |
- |
-// Called from main thread to send bytes to the translator. |
-void PnaclTranslateThread::PutBytes(const void* bytes, int32_t count) { |
- CHECK(bytes != NULL); |
- NaClXMutexLock(&cond_mu_); |
- data_buffers_.push_back(std::vector<char>()); |
- data_buffers_.back().insert(data_buffers_.back().end(), |
- static_cast<const char*>(bytes), |
- static_cast<const char*>(bytes) + count); |
- NaClXCondVarSignal(&buffer_cond_); |
- NaClXMutexUnlock(&cond_mu_); |
-} |
- |
-void PnaclTranslateThread::EndStream() { |
- NaClXMutexLock(&cond_mu_); |
- done_ = true; |
- NaClXCondVarSignal(&buffer_cond_); |
- NaClXMutexUnlock(&cond_mu_); |
-} |
- |
-void WINAPI PnaclTranslateThread::DoTranslateThread(void* arg) { |
- PnaclTranslateThread* translator = |
- reinterpret_cast<PnaclTranslateThread*>(arg); |
- translator->DoTranslate(); |
-} |
- |
-void PnaclTranslateThread::DoTranslate() { |
- ErrorInfo error_info; |
- SrpcParams params; |
- 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_); |
- |
- pp::Core* core = pp::Module::Get()->core(); |
- int64_t llc_start_time = NaClGetTimeOfDayMicroseconds(); |
- PP_NaClFileInfo llc_file_info = resources_->TakeLlcFileInfo(); |
- // On success, ownership of llc_file_info is transferred. |
- NaClSubprocess* llc_subprocess = plugin_->LoadHelperNaClModule( |
- resources_->GetLlcUrl(), llc_file_info, &error_info); |
- if (llc_subprocess == NULL) { |
- if (llc_file_info.handle != PP_kInvalidFileHandle) |
- CloseFileHandle(llc_file_info.handle); |
- TranslateFailed(PP_NACL_ERROR_PNACL_LLC_SETUP, |
- "Compile process could not be created: " + |
- error_info.message()); |
- return; |
- } |
- GetNaClInterface()->LogTranslateTime( |
- "NaCl.Perf.PNaClLoadTime.LoadCompiler", |
- NaClGetTimeOfDayMicroseconds() - llc_start_time); |
- |
- { |
- nacl::MutexLocker ml(&subprocess_mu_); |
- // If we received a call to AbortSubprocesses() before we had a chance to |
- // set llc_subprocess_, shut down and clean up the subprocess started here. |
- if (subprocesses_aborted_) { |
- llc_subprocess->service_runtime()->Shutdown(); |
- delete llc_subprocess; |
- return; |
- } |
- llc_subprocess_.reset(llc_subprocess); |
- llc_subprocess = NULL; |
- llc_subprocess_active_ = true; |
- } |
- |
- int64_t compile_start_time = NaClGetTimeOfDayMicroseconds(); |
- bool init_success; |
- |
- std::vector<char> split_args; |
- GetLlcCommandLine(plugin_, |
- &split_args, |
- obj_files_->size(), |
- pnacl_options_->opt_level, |
- pnacl_options_->is_debug, |
- architecture_attributes_); |
- init_success = llc_subprocess_->InvokeSrpcMethod( |
- "StreamInitWithSplit", |
- "ihhhhhhhhhhhhhhhhC", |
- ¶ms, |
- static_cast<int>(obj_files_->size()), |
- 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) { |
- if (llc_subprocess_->srpc_client()->GetLastError() == |
- NACL_SRPC_RESULT_APP_ERROR) { |
- // The error message is only present if the error was returned from llc |
- TranslateFailed(PP_NACL_ERROR_PNACL_LLC_INTERNAL, |
- std::string("Stream init failed: ") + |
- std::string(params.outs()[0]->arrays.str)); |
- } else { |
- TranslateFailed(PP_NACL_ERROR_PNACL_LLC_INTERNAL, |
- "Stream init internal error"); |
- } |
- return; |
- } |
- PLUGIN_PRINTF(("PnaclCoordinator: StreamInit successful\n")); |
- |
- // llc process is started. |
- while(!done_ || data_buffers_.size() > 0) { |
- NaClXMutexLock(&cond_mu_); |
- while(!done_ && data_buffers_.size() == 0) { |
- NaClXCondVarWait(&buffer_cond_, &cond_mu_); |
- } |
- PLUGIN_PRINTF(("PnaclTranslateThread awake (done=%d, size=%" NACL_PRIuS |
- ")\n", |
- done_, data_buffers_.size())); |
- if (data_buffers_.size() > 0) { |
- std::vector<char> data; |
- data.swap(data_buffers_.front()); |
- data_buffers_.pop_front(); |
- NaClXMutexUnlock(&cond_mu_); |
- PLUGIN_PRINTF(("StreamChunk\n")); |
- if (!llc_subprocess_->InvokeSrpcMethod("StreamChunk", |
- "C", |
- ¶ms, |
- &data[0], |
- data.size())) { |
- if (llc_subprocess_->srpc_client()->GetLastError() != |
- NACL_SRPC_RESULT_APP_ERROR) { |
- // If the error was reported by the translator, then we fall through |
- // and call StreamEnd, which returns a string describing the error, |
- // which we can then send to the Javascript console. Otherwise just |
- // fail here, since the translator has probably crashed or asserted. |
- TranslateFailed(PP_NACL_ERROR_PNACL_LLC_INTERNAL, |
- "Compile stream chunk failed. " |
- "The PNaCl translator has probably crashed."); |
- return; |
- } |
- break; |
- } else { |
- PLUGIN_PRINTF(("StreamChunk Successful\n")); |
- core->CallOnMainThread( |
- 0, |
- coordinator_->GetCompileProgressCallback(data.size()), |
- PP_OK); |
- } |
- } else { |
- NaClXMutexUnlock(&cond_mu_); |
- } |
- } |
- PLUGIN_PRINTF(("PnaclTranslateThread done with chunks\n")); |
- // Finish llc. |
- if (!llc_subprocess_->InvokeSrpcMethod("StreamEnd", std::string(), ¶ms)) { |
- PLUGIN_PRINTF(("PnaclTranslateThread StreamEnd failed\n")); |
- if (llc_subprocess_->srpc_client()->GetLastError() == |
- NACL_SRPC_RESULT_APP_ERROR) { |
- // The error string is only present if the error was sent back from llc. |
- TranslateFailed(PP_NACL_ERROR_PNACL_LLC_INTERNAL, |
- params.outs()[3]->arrays.str); |
- } else { |
- TranslateFailed(PP_NACL_ERROR_PNACL_LLC_INTERNAL, |
- "Compile StreamEnd internal error"); |
- } |
- return; |
- } |
- compile_time_ = NaClGetTimeOfDayMicroseconds() - compile_start_time; |
- GetNaClInterface()->LogTranslateTime("NaCl.Perf.PNaClLoadTime.CompileTime", |
- compile_time_); |
- |
- // Shut down the llc subprocess. |
- NaClXMutexLock(&subprocess_mu_); |
- llc_subprocess_active_ = false; |
- llc_subprocess_.reset(NULL); |
- NaClXMutexUnlock(&subprocess_mu_); |
- |
- if(!RunLdSubprocess()) { |
- return; |
- } |
- core->CallOnMainThread(0, report_translate_finished_, PP_OK); |
-} |
- |
-bool PnaclTranslateThread::RunLdSubprocess() { |
- ErrorInfo error_info; |
- SrpcParams params; |
- |
- 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(PP_NACL_ERROR_PNACL_LD_SETUP, |
- "Link process could not reset object file"); |
- return false; |
- } |
- ld_in_files.push_back((*obj_files_)[i]->read_wrapper()); |
- } |
- for (; i < PnaclCoordinator::kMaxTranslatorObjectFiles; i++) |
- ld_in_files.push_back(invalid_desc_wrapper_); |
- |
- nacl::DescWrapper* ld_out_file = nexe_file_->write_wrapper(); |
- int64_t ld_start_time = NaClGetTimeOfDayMicroseconds(); |
- PP_NaClFileInfo ld_file_info = resources_->TakeLdFileInfo(); |
- // On success, ownership of ld_file_info is transferred. |
- nacl::scoped_ptr<NaClSubprocess> ld_subprocess( |
- plugin_->LoadHelperNaClModule(resources_->GetLdUrl(), |
- ld_file_info, |
- &error_info)); |
- if (ld_subprocess.get() == NULL) { |
- if (ld_file_info.handle != PP_kInvalidFileHandle) |
- CloseFileHandle(ld_file_info.handle); |
- TranslateFailed(PP_NACL_ERROR_PNACL_LD_SETUP, |
- "Link process could not be created: " + |
- error_info.message()); |
- return false; |
- } |
- GetNaClInterface()->LogTranslateTime( |
- "NaCl.Perf.PNaClLoadTime.LoadLinker", |
- NaClGetTimeOfDayMicroseconds() - ld_start_time); |
- { |
- nacl::MutexLocker ml(&subprocess_mu_); |
- // If we received a call to AbortSubprocesses() before we had a chance to |
- // set llc_subprocess_, shut down and clean up the subprocess started here. |
- if (subprocesses_aborted_) { |
- ld_subprocess->service_runtime()->Shutdown(); |
- return false; |
- } |
- DCHECK(ld_subprocess_.get() == NULL); |
- ld_subprocess_.swap(ld_subprocess); |
- ld_subprocess_active_ = true; |
- } |
- |
- int64_t link_start_time = NaClGetTimeOfDayMicroseconds(); |
- // Run LD. |
- bool success = ld_subprocess_->InvokeSrpcMethod( |
- "RunWithSplit", |
- "ihhhhhhhhhhhhhhhhh", |
- ¶ms, |
- static_cast<int>(obj_files_->size()), |
- 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()); |
- if (!success) { |
- TranslateFailed(PP_NACL_ERROR_PNACL_LD_INTERNAL, |
- "link failed."); |
- return false; |
- } |
- GetNaClInterface()->LogTranslateTime( |
- "NaCl.Perf.PNaClLoadTime.LinkTime", |
- NaClGetTimeOfDayMicroseconds() - link_start_time); |
- PLUGIN_PRINTF(("PnaclCoordinator: link (translator=%p) succeeded\n", |
- this)); |
- // Shut down the ld subprocess. |
- NaClXMutexLock(&subprocess_mu_); |
- ld_subprocess_active_ = false; |
- ld_subprocess_.reset(NULL); |
- NaClXMutexUnlock(&subprocess_mu_); |
- return true; |
-} |
- |
-void PnaclTranslateThread::TranslateFailed( |
- PP_NaClError err_code, |
- const std::string& error_string) { |
- PLUGIN_PRINTF(("PnaclTranslateThread::TranslateFailed (error_string='%s')\n", |
- error_string.c_str())); |
- pp::Core* core = pp::Module::Get()->core(); |
- if (coordinator_error_info_->message().empty()) { |
- // Only use our message if one hasn't already been set by the coordinator |
- // (e.g. pexe load failed). |
- coordinator_error_info_->SetReport(err_code, |
- std::string("PnaclCoordinator: ") + |
- error_string); |
- } |
- core->CallOnMainThread(0, report_translate_finished_, PP_ERROR_FAILED); |
-} |
- |
-void PnaclTranslateThread::AbortSubprocesses() { |
- PLUGIN_PRINTF(("PnaclTranslateThread::AbortSubprocesses\n")); |
- NaClXMutexLock(&subprocess_mu_); |
- if (llc_subprocess_ != NULL && llc_subprocess_active_) { |
- llc_subprocess_->service_runtime()->Shutdown(); |
- llc_subprocess_active_ = false; |
- } |
- if (ld_subprocess_ != NULL && ld_subprocess_active_) { |
- ld_subprocess_->service_runtime()->Shutdown(); |
- ld_subprocess_active_ = false; |
- } |
- subprocesses_aborted_ = true; |
- NaClXMutexUnlock(&subprocess_mu_); |
- nacl::MutexLocker ml(&cond_mu_); |
- done_ = true; |
- // Free all buffered bitcode chunks |
- data_buffers_.clear(); |
- NaClXCondVarSignal(&buffer_cond_); |
-} |
- |
-PnaclTranslateThread::~PnaclTranslateThread() { |
- PLUGIN_PRINTF(("~PnaclTranslateThread (translate_thread=%p)\n", this)); |
- AbortSubprocesses(); |
- if (translate_thread_ != NULL) |
- NaClThreadJoin(translate_thread_.get()); |
- PLUGIN_PRINTF(("~PnaclTranslateThread joined\n")); |
- NaClCondVarDtor(&buffer_cond_); |
- NaClMutexDtor(&cond_mu_); |
- NaClMutexDtor(&subprocess_mu_); |
-} |
- |
-} // namespace plugin |