| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "components/nacl/renderer/plugin/pnacl_coordinator.h" | 5 #include "components/nacl/renderer/plugin/pnacl_coordinator.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <sstream> | 8 #include <sstream> |
| 9 #include <utility> | 9 #include <utility> |
| 10 | 10 |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 94 const pp::CompletionCallback& translate_notify_callback) { | 94 const pp::CompletionCallback& translate_notify_callback) { |
| 95 PLUGIN_PRINTF(("PnaclCoordinator::BitcodeToNative (plugin=%p, pexe=%s)\n", | 95 PLUGIN_PRINTF(("PnaclCoordinator::BitcodeToNative (plugin=%p, pexe=%s)\n", |
| 96 static_cast<void*>(plugin), pexe_url.c_str())); | 96 static_cast<void*>(plugin), pexe_url.c_str())); |
| 97 PnaclCoordinator* coordinator = | 97 PnaclCoordinator* coordinator = |
| 98 new PnaclCoordinator(plugin, pexe_url, | 98 new PnaclCoordinator(plugin, pexe_url, |
| 99 pnacl_options, | 99 pnacl_options, |
| 100 translate_notify_callback); | 100 translate_notify_callback); |
| 101 | 101 |
| 102 GetNaClInterface()->SetPNaClStartTime(plugin->pp_instance()); | 102 GetNaClInterface()->SetPNaClStartTime(plugin->pp_instance()); |
| 103 int cpus = plugin->nacl_interface()->GetNumberOfProcessors(); | 103 int cpus = plugin->nacl_interface()->GetNumberOfProcessors(); |
| 104 coordinator->split_module_count_ = std::min(4, std::max(1, cpus)); | 104 coordinator->num_threads_ = std::min(4, std::max(1, cpus)); |
| 105 | 105 if (pnacl_options.use_subzero) { |
| 106 coordinator->split_module_count_ = 1; |
| 107 } else { |
| 108 coordinator->split_module_count_ = coordinator->num_threads_; |
| 109 } |
| 106 // First start a network request for the pexe, to tickle the component | 110 // First start a network request for the pexe, to tickle the component |
| 107 // updater's On-Demand resource throttler, and to get Last-Modified/ETag | 111 // updater's On-Demand resource throttler, and to get Last-Modified/ETag |
| 108 // cache information. We can cancel the request later if there's | 112 // cache information. We can cancel the request later if there's |
| 109 // a bitcode->nexe cache hit. | 113 // a bitcode->nexe cache hit. |
| 110 coordinator->OpenBitcodeStream(); | 114 coordinator->OpenBitcodeStream(); |
| 111 return coordinator; | 115 return coordinator; |
| 112 } | 116 } |
| 113 | 117 |
| 114 PnaclCoordinator::PnaclCoordinator( | 118 PnaclCoordinator::PnaclCoordinator( |
| 115 Plugin* plugin, | 119 Plugin* plugin, |
| 116 const std::string& pexe_url, | 120 const std::string& pexe_url, |
| 117 const PP_PNaClOptions& pnacl_options, | 121 const PP_PNaClOptions& pnacl_options, |
| 118 const pp::CompletionCallback& translate_notify_callback) | 122 const pp::CompletionCallback& translate_notify_callback) |
| 119 : translate_finish_error_(PP_OK), | 123 : translate_finish_error_(PP_OK), |
| 120 plugin_(plugin), | 124 plugin_(plugin), |
| 121 translate_notify_callback_(translate_notify_callback), | 125 translate_notify_callback_(translate_notify_callback), |
| 122 translation_finished_reported_(false), | 126 translation_finished_reported_(false), |
| 123 pexe_url_(pexe_url), | 127 pexe_url_(pexe_url), |
| 124 pnacl_options_(pnacl_options), | 128 pnacl_options_(pnacl_options), |
| 125 architecture_attributes_(GetArchitectureAttributes(plugin)), | 129 architecture_attributes_(GetArchitectureAttributes(plugin)), |
| 126 split_module_count_(1), | 130 split_module_count_(0), |
| 127 error_already_reported_(false), | 131 num_threads_(0), |
| 128 pexe_size_(0), | 132 error_already_reported_(false), |
| 129 pexe_bytes_compiled_(0), | 133 pexe_size_(0), |
| 130 expected_pexe_size_(-1) { | 134 pexe_bytes_compiled_(0), |
| 135 expected_pexe_size_(-1) { |
| 131 callback_factory_.Initialize(this); | 136 callback_factory_.Initialize(this); |
| 132 } | 137 } |
| 133 | 138 |
| 134 PnaclCoordinator::~PnaclCoordinator() { | 139 PnaclCoordinator::~PnaclCoordinator() { |
| 135 PLUGIN_PRINTF(("PnaclCoordinator::~PnaclCoordinator (this=%p, " | 140 PLUGIN_PRINTF(("PnaclCoordinator::~PnaclCoordinator (this=%p, " |
| 136 "translate_thread=%p\n", | 141 "translate_thread=%p\n", |
| 137 static_cast<void*>(this), translate_thread_.get())); | 142 static_cast<void*>(this), translate_thread_.get())); |
| 138 // Stopping the translate thread will cause the translate thread to try to | 143 // Stopping the translate thread will cause the translate thread to try to |
| 139 // run translation_complete_callback_ on the main thread. This destructor is | 144 // run translation_complete_callback_ on the main thread. This destructor is |
| 140 // running from the main thread, and by the time it exits, callback_factory_ | 145 // running from the main thread, and by the time it exits, callback_factory_ |
| 141 // will have been destroyed. This will result in the cancellation of | 146 // will have been destroyed. This will result in the cancellation of |
| 142 // translation_complete_callback_, so no notification will be delivered. | 147 // translation_complete_callback_, so no notification will be delivered. |
| 143 if (translate_thread_.get() != NULL) | 148 if (translate_thread_.get() != NULL) |
| 144 translate_thread_->AbortSubprocesses(); | 149 translate_thread_->AbortSubprocesses(); |
| 145 if (!translation_finished_reported_) { | 150 if (!translation_finished_reported_) { |
| 146 plugin_->nacl_interface()->ReportTranslationFinished( | 151 plugin_->nacl_interface()->ReportTranslationFinished( |
| 147 plugin_->pp_instance(), | 152 plugin_->pp_instance(), PP_FALSE, pnacl_options_.opt_level, |
| 148 PP_FALSE, 0, 0, 0); | 153 pnacl_options_.use_subzero, 0, 0); |
| 149 } | 154 } |
| 150 // Force deleting the translate_thread now. It must be deleted | 155 // Force deleting the translate_thread now. It must be deleted |
| 151 // before any scoped_* fields hanging off of PnaclCoordinator | 156 // before any scoped_* fields hanging off of PnaclCoordinator |
| 152 // since the thread may be accessing those fields. | 157 // since the thread may be accessing those fields. |
| 153 // It will also be accessing obj_files_. | 158 // It will also be accessing obj_files_. |
| 154 translate_thread_.reset(NULL); | 159 translate_thread_.reset(NULL); |
| 155 for (size_t i = 0; i < obj_files_.size(); i++) | 160 for (size_t i = 0; i < obj_files_.size(); i++) |
| 156 delete obj_files_[i]; | 161 delete obj_files_[i]; |
| 157 } | 162 } |
| 158 | 163 |
| (...skipping 27 matching lines...) Expand all Loading... |
| 186 // Note: this doesn't *cancel* the callbacks from the factories attached | 191 // Note: this doesn't *cancel* the callbacks from the factories attached |
| 187 // to the various helper classes (e.g., pnacl_resources). Thus, those | 192 // to the various helper classes (e.g., pnacl_resources). Thus, those |
| 188 // callbacks may still run asynchronously. We let those run but ignore | 193 // callbacks may still run asynchronously. We let those run but ignore |
| 189 // any other errors they may generate so that they do not end up running | 194 // any other errors they may generate so that they do not end up running |
| 190 // translate_notify_callback_, which has already been freed. | 195 // translate_notify_callback_, which has already been freed. |
| 191 callback_factory_.CancelAll(); | 196 callback_factory_.CancelAll(); |
| 192 if (!error_already_reported_) { | 197 if (!error_already_reported_) { |
| 193 error_already_reported_ = true; | 198 error_already_reported_ = true; |
| 194 translation_finished_reported_ = true; | 199 translation_finished_reported_ = true; |
| 195 plugin_->nacl_interface()->ReportTranslationFinished( | 200 plugin_->nacl_interface()->ReportTranslationFinished( |
| 196 plugin_->pp_instance(), | 201 plugin_->pp_instance(), PP_FALSE, pnacl_options_.opt_level, |
| 197 PP_FALSE, 0, 0, 0); | 202 pnacl_options_.use_subzero, 0, 0); |
| 198 translate_notify_callback_.Run(PP_ERROR_FAILED); | 203 translate_notify_callback_.Run(PP_ERROR_FAILED); |
| 199 } | 204 } |
| 200 } | 205 } |
| 201 | 206 |
| 202 // Signal that Pnacl translation completed normally. | 207 // Signal that Pnacl translation completed normally. |
| 203 void PnaclCoordinator::TranslateFinished(int32_t pp_error) { | 208 void PnaclCoordinator::TranslateFinished(int32_t pp_error) { |
| 204 PLUGIN_PRINTF(("PnaclCoordinator::TranslateFinished (pp_error=%" | 209 PLUGIN_PRINTF(("PnaclCoordinator::TranslateFinished (pp_error=%" |
| 205 NACL_PRId32 ")\n", pp_error)); | 210 NACL_PRId32 ")\n", pp_error)); |
| 206 // Bail out if there was an earlier error (e.g., pexe load failure), | 211 // Bail out if there was an earlier error (e.g., pexe load failure), |
| 207 // or if there is an error from the translation thread. | 212 // or if there is an error from the translation thread. |
| (...skipping 27 matching lines...) Expand all Loading... |
| 235 } | 240 } |
| 236 // The nexe is written to the temp_nexe_file_. We must Reset() the file | 241 // The nexe is written to the temp_nexe_file_. We must Reset() the file |
| 237 // pointer to be able to read it again from the beginning. | 242 // pointer to be able to read it again from the beginning. |
| 238 temp_nexe_file_->Reset(); | 243 temp_nexe_file_->Reset(); |
| 239 | 244 |
| 240 // Report to the browser that translation finished. The browser will take | 245 // Report to the browser that translation finished. The browser will take |
| 241 // care of storing the nexe in the cache. | 246 // care of storing the nexe in the cache. |
| 242 translation_finished_reported_ = true; | 247 translation_finished_reported_ = true; |
| 243 plugin_->nacl_interface()->ReportTranslationFinished( | 248 plugin_->nacl_interface()->ReportTranslationFinished( |
| 244 plugin_->pp_instance(), PP_TRUE, pnacl_options_.opt_level, | 249 plugin_->pp_instance(), PP_TRUE, pnacl_options_.opt_level, |
| 245 pexe_size_, translate_thread_->GetCompileTime()); | 250 pnacl_options_.use_subzero, pexe_size_, |
| 251 translate_thread_->GetCompileTime()); |
| 246 | 252 |
| 247 NexeReadDidOpen(PP_OK); | 253 NexeReadDidOpen(PP_OK); |
| 248 } | 254 } |
| 249 | 255 |
| 250 void PnaclCoordinator::NexeReadDidOpen(int32_t pp_error) { | 256 void PnaclCoordinator::NexeReadDidOpen(int32_t pp_error) { |
| 251 PLUGIN_PRINTF(("PnaclCoordinator::NexeReadDidOpen (pp_error=%" | 257 PLUGIN_PRINTF(("PnaclCoordinator::NexeReadDidOpen (pp_error=%" |
| 252 NACL_PRId32 ")\n", pp_error)); | 258 NACL_PRId32 ")\n", pp_error)); |
| 253 if (pp_error != PP_OK) { | 259 if (pp_error != PP_OK) { |
| 254 if (pp_error == PP_ERROR_FILENOTFOUND) { | 260 if (pp_error == PP_ERROR_FILENOTFOUND) { |
| 255 ReportPpapiError(PP_NACL_ERROR_PNACL_CACHE_FETCH_NOTFOUND, | 261 ReportPpapiError(PP_NACL_ERROR_PNACL_CACHE_FETCH_NOTFOUND, |
| (...skipping 22 matching lines...) Expand all Loading... |
| 278 // that get downloaded before the compilation thread is accepting | 284 // that get downloaded before the compilation thread is accepting |
| 279 // SRPCs won't get dropped. | 285 // SRPCs won't get dropped. |
| 280 translate_thread_.reset(new PnaclTranslateThread()); | 286 translate_thread_.reset(new PnaclTranslateThread()); |
| 281 if (translate_thread_ == NULL) { | 287 if (translate_thread_ == NULL) { |
| 282 ReportNonPpapiError( | 288 ReportNonPpapiError( |
| 283 PP_NACL_ERROR_PNACL_THREAD_CREATE, | 289 PP_NACL_ERROR_PNACL_THREAD_CREATE, |
| 284 "PnaclCoordinator: could not allocate translation thread."); | 290 "PnaclCoordinator: could not allocate translation thread."); |
| 285 return; | 291 return; |
| 286 } | 292 } |
| 287 | 293 |
| 288 GetNaClInterface()->StreamPexe(plugin_->pp_instance(), | 294 GetNaClInterface()->StreamPexe( |
| 289 pexe_url_.c_str(), | 295 plugin_->pp_instance(), pexe_url_.c_str(), pnacl_options_.opt_level, |
| 290 pnacl_options_.opt_level, | 296 pnacl_options_.use_subzero, &kPexeStreamHandler, this); |
| 291 &kPexeStreamHandler, | |
| 292 this); | |
| 293 } | 297 } |
| 294 | 298 |
| 295 void PnaclCoordinator::BitcodeStreamCacheHit(PP_FileHandle handle) { | 299 void PnaclCoordinator::BitcodeStreamCacheHit(PP_FileHandle handle) { |
| 296 if (handle == PP_kInvalidFileHandle) { | 300 if (handle == PP_kInvalidFileHandle) { |
| 297 ReportNonPpapiError( | 301 ReportNonPpapiError( |
| 298 PP_NACL_ERROR_PNACL_CREATE_TEMP, | 302 PP_NACL_ERROR_PNACL_CREATE_TEMP, |
| 299 std::string( | 303 std::string( |
| 300 "PnaclCoordinator: Got bad temp file handle from GetNexeFd")); | 304 "PnaclCoordinator: Got bad temp file handle from GetNexeFd")); |
| 301 BitcodeStreamDidFinish(PP_ERROR_FAILED); | 305 BitcodeStreamDidFinish(PP_ERROR_FAILED); |
| 302 return; | 306 return; |
| 303 } | 307 } |
| 304 temp_nexe_file_.reset(new TempFile(plugin_, handle)); | 308 temp_nexe_file_.reset(new TempFile(plugin_, handle)); |
| 305 // Open it for reading as the cached nexe file. | 309 // Open it for reading as the cached nexe file. |
| 306 NexeReadDidOpen(temp_nexe_file_->Open(false)); | 310 NexeReadDidOpen(temp_nexe_file_->Open(false)); |
| 307 } | 311 } |
| 308 | 312 |
| 309 void PnaclCoordinator::BitcodeStreamCacheMiss(int64_t expected_pexe_size, | 313 void PnaclCoordinator::BitcodeStreamCacheMiss(int64_t expected_pexe_size, |
| 310 PP_FileHandle nexe_handle) { | 314 PP_FileHandle nexe_handle) { |
| 311 // IMPORTANT: Make sure that PnaclResources::StartLoad() is only | 315 // IMPORTANT: Make sure that PnaclResources::StartLoad() is only |
| 312 // called after you receive a response to a request for a .pexe file. | 316 // called after you receive a response to a request for a .pexe file. |
| 313 // | 317 // |
| 314 // The component updater's resource throttles + OnDemand update/install | 318 // The component updater's resource throttles + OnDemand update/install |
| 315 // should block the URL request until the compiler is present. Now we | 319 // should block the URL request until the compiler is present. Now we |
| 316 // can load the resources (e.g. llc and ld nexes). | 320 // can load the resources (e.g. llc and ld nexes). |
| 317 resources_.reset(new PnaclResources(plugin_)); | 321 resources_.reset(new PnaclResources(plugin_, pnacl_options_.use_subzero)); |
| 318 CHECK(resources_ != NULL); | 322 CHECK(resources_ != NULL); |
| 319 | 323 |
| 320 // The first step of loading resources: read the resource info file. | 324 // The first step of loading resources: read the resource info file. |
| 321 if (!resources_->ReadResourceInfo()) { | 325 if (!resources_->ReadResourceInfo()) { |
| 322 ExitWithError(); | 326 ExitWithError(); |
| 323 return; | 327 return; |
| 324 } | 328 } |
| 325 | 329 |
| 326 // Second step of loading resources: call StartLoad to load pnacl-llc | 330 // Second step of loading resources: call StartLoad to load pnacl-llc |
| 327 // and pnacl-ld, based on the filenames found in the resource info file. | 331 // and pnacl-ld, based on the filenames found in the resource info file. |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 434 | 438 |
| 435 void PnaclCoordinator::RunTranslate(int32_t pp_error) { | 439 void PnaclCoordinator::RunTranslate(int32_t pp_error) { |
| 436 PLUGIN_PRINTF(("PnaclCoordinator::RunTranslate (pp_error=%" | 440 PLUGIN_PRINTF(("PnaclCoordinator::RunTranslate (pp_error=%" |
| 437 NACL_PRId32 ")\n", pp_error)); | 441 NACL_PRId32 ")\n", pp_error)); |
| 438 // Invoke llc followed by ld off the main thread. This allows use of | 442 // Invoke llc followed by ld off the main thread. This allows use of |
| 439 // blocking RPCs that would otherwise block the JavaScript main thread. | 443 // blocking RPCs that would otherwise block the JavaScript main thread. |
| 440 pp::CompletionCallback report_translate_finished = | 444 pp::CompletionCallback report_translate_finished = |
| 441 callback_factory_.NewCallback(&PnaclCoordinator::TranslateFinished); | 445 callback_factory_.NewCallback(&PnaclCoordinator::TranslateFinished); |
| 442 | 446 |
| 443 CHECK(translate_thread_ != NULL); | 447 CHECK(translate_thread_ != NULL); |
| 444 translate_thread_->RunTranslate(report_translate_finished, | 448 translate_thread_->RunTranslate(report_translate_finished, &obj_files_, |
| 445 &obj_files_, | 449 num_threads_, temp_nexe_file_.get(), |
| 446 temp_nexe_file_.get(), | 450 invalid_desc_wrapper_.get(), &error_info_, |
| 447 invalid_desc_wrapper_.get(), | 451 resources_.get(), &pnacl_options_, |
| 448 &error_info_, | 452 architecture_attributes_, this, plugin_); |
| 449 resources_.get(), | |
| 450 &pnacl_options_, | |
| 451 architecture_attributes_, | |
| 452 this, | |
| 453 plugin_); | |
| 454 } | 453 } |
| 455 | 454 |
| 456 } // namespace plugin | 455 } // namespace plugin |
| OLD | NEW |