| Index: ppapi/native_client/src/trusted/plugin/pnacl_coordinator.cc
|
| ===================================================================
|
| --- ppapi/native_client/src/trusted/plugin/pnacl_coordinator.cc (revision 113812)
|
| +++ ppapi/native_client/src/trusted/plugin/pnacl_coordinator.cc (working copy)
|
| @@ -17,22 +17,318 @@
|
| #include "native_client/src/trusted/plugin/plugin.h"
|
| #include "native_client/src/trusted/plugin/plugin_error.h"
|
| #include "native_client/src/trusted/plugin/pnacl_srpc_lib.h"
|
| -#include "native_client/src/trusted/plugin/scriptable_handle.h"
|
| #include "native_client/src/trusted/plugin/utility.h"
|
|
|
| #include "ppapi/c/pp_errors.h"
|
| +#include "ppapi/c/ppb_file_io.h"
|
| +#include "ppapi/cpp/file_io.h"
|
|
|
| +namespace plugin {
|
| +
|
| +class Plugin;
|
| +
|
| namespace {
|
|
|
| -typedef std::vector<nacl::string> string_vector;
|
| -int32_t kArbitraryStackSize = 128 << 10;
|
| +const char kLlcUrl[] = "llc";
|
| +const char kLdUrl[] = "ld";
|
|
|
| +// Fake filename for the object file generated by llvm.
|
| +nacl::string ResourceBaseUrl() {
|
| + return nacl::string("pnacl_support/") + GetSandboxISA() + "/";
|
| +}
|
| +
|
| +// Lookup service called by translator nexes.
|
| +// TODO(sehr): replace this lookup by ReverseService.
|
| +void LookupInputFile(NaClSrpcRpc* rpc,
|
| + NaClSrpcArg** inputs,
|
| + NaClSrpcArg** outputs,
|
| + NaClSrpcClosure* done) {
|
| + NaClSrpcClosureRunner runner(done);
|
| + rpc->result = NACL_SRPC_RESULT_APP_ERROR;
|
| + const char* file_name = inputs[0]->arrays.str;
|
| + PnaclTranslationUnit* translation = reinterpret_cast<PnaclTranslationUnit*>(
|
| + rpc->channel->server_instance_data);
|
| + PnaclCoordinator* coordinator = translation->coordinator;
|
| + PnaclResources* resources = coordinator->resources();
|
| + // This filename is part of the contract with the linker.
|
| + // TODO(sehr): Pass the FD in, and move lookup for this file to the linker.
|
| + const nacl::string kGeneratedObjectFileName = "___PNACL_GENERATED";
|
| + if (nacl::string(file_name) == kGeneratedObjectFileName) {
|
| + outputs[0]->u.hval = translation->obj_file->read_wrapper()->desc();
|
| + } else {
|
| + nacl::DescWrapper* wrapper = translation->LookupDesc(inputs[0]->arrays.str);
|
| + outputs[0]->u.hval = wrapper->desc();
|
| + }
|
| + rpc->result = NACL_SRPC_RESULT_OK;
|
| +}
|
| +
|
| +NaClSrpcHandlerDesc lookup_methods[] = {
|
| + { "LookupInputFile:s:h", LookupInputFile },
|
| + { NULL, NULL }
|
| +};
|
| +
|
| +void AbortTranslateThread(PnaclTranslationUnit* translation_unit,
|
| + const nacl::string& error_string) {
|
| + pp::Core* core = pp::Module::Get()->core();
|
| + translation_unit->error_info.SetReport(ERROR_UNKNOWN, error_string);
|
| + core->CallOnMainThread(0, translation_unit->translate_done_cb,
|
| + PP_ERROR_FAILED);
|
| + NaClThreadExit(1);
|
| +}
|
| +
|
| +void WINAPI DoTranslateThread(void* arg) {
|
| + PnaclTranslationUnit* trans = reinterpret_cast<PnaclTranslationUnit*>(arg);
|
| + PnaclCoordinator* coordinator = trans->coordinator;
|
| + NaClSubprocess* llc_subprocess = coordinator->llc_subprocess();
|
| + Plugin* plugin = coordinator->plugin();
|
| + BrowserInterface* browser_interface = plugin->browser_interface();
|
| +
|
| + // Run LLC.
|
| + SrpcParams params;
|
| + nacl::DescWrapper* llc_out_file = trans->obj_file->write_wrapper();
|
| + if (!PnaclSrpcLib::InvokeSrpcMethod(browser_interface,
|
| + llc_subprocess,
|
| + "RunWithDefaultCommandLine",
|
| + "hh",
|
| + ¶ms,
|
| + trans->pexe_wrapper->desc(),
|
| + llc_out_file->desc())) {
|
| + AbortTranslateThread(trans, "PnaclCoordinator compile failed.");
|
| + }
|
| + // LLC returns values that are used to determine how linking is cone.
|
| + int is_shared_library = (params.outs()[0]->u.ival != 0);
|
| + nacl::string soname = params.outs()[1]->arrays.str;
|
| + nacl::string lib_dependencies = params.outs()[2]->arrays.str;
|
| + PLUGIN_PRINTF(("PnaclCoordinator::Compile (trans=%p) succeeded"
|
| + " is_shared_library=%d, soname='%s', lib_dependencies='%s')\n",
|
| + arg, is_shared_library, soname.c_str(),
|
| + lib_dependencies.c_str()));
|
| + if (coordinator->SubprocessesShouldDie()) {
|
| + NaClThreadExit(1);
|
| + }
|
| + // Set up the lookup service for filename to handle resolution.
|
| + NaClSrpcService* service =
|
| + reinterpret_cast<NaClSrpcService*>(calloc(1, sizeof(*service)));
|
| + if (NULL == service) {
|
| + AbortTranslateThread(trans,
|
| + "PnaclCoordinator: lookup service alloc failed.");
|
| + }
|
| + if (!NaClSrpcServiceHandlerCtor(service, lookup_methods)) {
|
| + free(service);
|
| + AbortTranslateThread(trans,
|
| + "PnaclCoordinator: lookup service ctor failed.");
|
| + }
|
| + char* service_string = const_cast<char*>(service->service_string);
|
| + NaClSubprocess* ld_subprocess = coordinator->ld_subprocess();
|
| + ld_subprocess->srpc_client()->AttachService(service, trans);
|
| + nacl::DescWrapper* ld_out_file = trans->nexe_file->write_wrapper();
|
| + if (!PnaclSrpcLib::InvokeSrpcMethod(browser_interface,
|
| + ld_subprocess,
|
| + "RunWithDefaultCommandLine",
|
| + "ChiCC",
|
| + ¶ms,
|
| + service_string,
|
| + ld_out_file->desc(),
|
| + is_shared_library,
|
| + soname.c_str(),
|
| + lib_dependencies.c_str())) {
|
| + AbortTranslateThread(trans, "PnaclCoordinator link failed.");
|
| + }
|
| + PLUGIN_PRINTF(("PnaclCoordinator Link(trans=%p) succeeded", arg));
|
| + if (coordinator->SubprocessesShouldDie()) {
|
| + NaClThreadExit(1);
|
| + }
|
| + pp::Core* core = pp::Module::Get()->core();
|
| + core->CallOnMainThread(0, trans->translate_done_cb, PP_OK);
|
| + NaClThreadExit(0);
|
| +}
|
| +
|
| } // namespace
|
|
|
| -namespace plugin {
|
| +//////////////////////////////////////////////////////////////////////
|
| +PnaclFileDescPair::PnaclFileDescPair(pp::FileSystem* file_system,
|
| + PnaclCoordinator* coordinator)
|
| + : file_system_(file_system),
|
| + coordinator_(coordinator) {
|
| + callback_factory_.Initialize(this);
|
| + CHECK(NaClDescRngCtor(&rng_desc_));
|
| + file_io_trusted_= static_cast<const PPB_FileIOTrusted*>(
|
| + pp::Module::Get()->GetBrowserInterface(PPB_FILEIOTRUSTED_INTERFACE));
|
| + // Get a random temp file name.
|
| + struct NaClDesc* desc = reinterpret_cast<struct NaClDesc*>(&rng_desc_);
|
| + const struct NaClDescVtbl* vtbl =
|
| + reinterpret_cast<const struct NaClDescVtbl*>(desc->base.vtbl);
|
| + // Filename consists of a slash then 32 random characters.
|
| + filename_ = "/";
|
| + const int32_t kTempFileNameWords = 4;
|
| + for (int32_t i = 0; i < kTempFileNameWords; ++i) {
|
| + int32_t num;
|
| + CHECK(sizeof num == vtbl->Read(desc,
|
| + reinterpret_cast<char*>(&num),
|
| + sizeof num));
|
| + char frag[16];
|
| + SNPRINTF(frag, sizeof frag, "%08x", num);
|
| + filename_ += nacl::string(frag);
|
| + }
|
| +}
|
|
|
| -class Plugin;
|
| +PnaclFileDescPair::~PnaclFileDescPair() {
|
| + NaClDescUnref(reinterpret_cast<NaClDesc*>(&rng_desc_));
|
| +}
|
|
|
| +void PnaclFileDescPair::Open(const pp::CompletionCallback& cb) {
|
| + PLUGIN_PRINTF(("PnaclFileDescPair::Open\n"));
|
| + done_callback_ = cb;
|
| +
|
| + write_ref_.reset(new pp::FileRef(*file_system_, filename_.c_str()));
|
| + write_io_.reset(new pp::FileIO(coordinator_->plugin()));
|
| + read_ref_.reset(new pp::FileRef(*file_system_, filename_.c_str()));
|
| + read_io_.reset(new pp::FileIO(coordinator_->plugin()));
|
| +
|
| + pp::CompletionCallback open_write_cb =
|
| + callback_factory_.NewCallback(&PnaclFileDescPair::WriteFileDidOpen);
|
| + // Open the writeable file.
|
| + write_io_->Open(*write_ref_,
|
| + PP_FILEOPENFLAG_WRITE | PP_FILEOPENFLAG_CREATE,
|
| + open_write_cb);
|
| +}
|
| +
|
| +int32_t PnaclFileDescPair::GetFD(int32_t pp_error,
|
| + const pp::Resource& resource,
|
| + const nacl::string& component) {
|
| + if (pp_error != PP_OK) {
|
| + coordinator_->ReportPpapiError(pp_error,
|
| + nacl::string("PnaclFileDescPair: Open ") +
|
| + component + " failed\n");
|
| + return -1;
|
| + }
|
| + int32_t file_desc = file_io_trusted_->GetOSFileDescriptor(
|
| + resource.pp_resource());
|
| +#if NACL_WINDOWS
|
| + // Convert the Windows HANDLE from Pepper to a POSIX file descriptor.
|
| + int32_t posix_desc = _open_osfhandle(file_desc, _O_RDWR | _O_BINARY);
|
| + if (posix_desc == -1) {
|
| + // Close the Windows HANDLE if it can't be converted.
|
| + CloseHandle(reinterpret_cast<HANDLE>(file_desc));
|
| + return NACL_NO_FILE_DESC;
|
| + }
|
| + file_desc = posix_desc;
|
| +#endif
|
| + int32_t file_desc_ok_to_close = DUP(file_desc);
|
| + if (file_desc_ok_to_close == NACL_NO_FILE_DESC) {
|
| + coordinator_->ReportPpapiError(pp_error,
|
| + nacl::string("PnaclFileDescPair: FD for ") +
|
| + component + " failed\n");
|
| + return -1;
|
| + }
|
| + return file_desc_ok_to_close;
|
| +}
|
| +
|
| +void PnaclFileDescPair::WriteFileDidOpen(int32_t pp_error) {
|
| + PLUGIN_PRINTF(("PnaclFileDescPair::WriteFileDidOpen (pp_error=%"
|
| + NACL_PRId32")\n", pp_error));
|
| + // Remember the object temporary file descriptor.
|
| + int32_t fd = GetFD(pp_error, *write_io_, "write");
|
| + if (fd < 0) {
|
| + return;
|
| + }
|
| + write_wrapper_.reset(
|
| + coordinator_->plugin()->wrapper_factory()->MakeFileDesc(fd, O_RDWR));
|
| + pp::CompletionCallback open_read_cb =
|
| + callback_factory_.NewCallback(&PnaclFileDescPair::ReadFileDidOpen);
|
| + // Open the read only file.
|
| + read_io_->Open(*read_ref_, PP_FILEOPENFLAG_READ, open_read_cb);
|
| +}
|
| +
|
| +void PnaclFileDescPair::ReadFileDidOpen(int32_t pp_error) {
|
| + PLUGIN_PRINTF(("PnaclFileDescPair::ReadFileDidOpen (pp_error=%"
|
| + NACL_PRId32")\n", pp_error));
|
| + // Remember the object temporary file descriptor.
|
| + int32_t fd = GetFD(pp_error, *read_io_, "read");
|
| + if (fd < 0) {
|
| + return;
|
| + }
|
| + read_wrapper_.reset(
|
| + coordinator_->plugin()->wrapper_factory()->MakeFileDesc(fd, O_RDONLY));
|
| + // Run the client's completion callback.
|
| + pp::Core* core = pp::Module::Get()->core();
|
| + core->CallOnMainThread(0, done_callback_, PP_OK);
|
| +}
|
| +
|
| +//////////////////////////////////////////////////////////////////////
|
| +void PnaclTranslationUnit::LoadOneFile(int32_t pp_error,
|
| + const nacl::string& url,
|
| + nacl::DescWrapper** wrapper,
|
| + pp::CompletionCallback& done_cb) {
|
| + PLUGIN_PRINTF(("PnaclCoordinator::LoadOneFile (pp_error=%"
|
| + NACL_PRId32", url=%s)\n", pp_error, url.c_str()));
|
| + Plugin* plugin = coordinator->plugin();
|
| + const nacl::string& full_url = coordinator->resource_base_url() + url;
|
| + pp::CompletionCallback callback =
|
| + callback_factory.NewCallback(&PnaclTranslationUnit::DidLoadFile,
|
| + full_url,
|
| + wrapper,
|
| + done_cb);
|
| + if (!plugin->StreamAsFile(full_url, callback.pp_completion_callback())) {
|
| + coordinator->ReportNonPpapiError("PnaclCoordinator: Failed to load: " +
|
| + url + "\n");
|
| + }
|
| +}
|
| +
|
| +void PnaclTranslationUnit::DidLoadFile(int32_t pp_error,
|
| + const nacl::string& full_url,
|
| + nacl::DescWrapper** wrapper,
|
| + pp::CompletionCallback& done_cb) {
|
| + PLUGIN_PRINTF(("PnaclCoordinator::DidLoadFile (pp_error=%"
|
| + NACL_PRId32", url=%s)\n", pp_error, full_url.c_str()));
|
| + int32_t fd = coordinator->GetLoadedFileDesc(pp_error, full_url, "resource");
|
| + if (fd < 0) {
|
| + return;
|
| + }
|
| + Plugin* plugin = coordinator->plugin();
|
| + *wrapper = plugin->wrapper_factory()->MakeFileDesc(fd, O_RDONLY);
|
| + done_cb.Run(PP_OK);
|
| +}
|
| +
|
| +void PnaclTranslationUnit::ResumeLookup(int32_t pp_error,
|
| + PnaclTranslationUnit* trans) {
|
| + UNREFERENCED_PARAMETER(pp_error);
|
| + nacl::MutexLocker ml(&mu);
|
| + trans->lookup_is_complete = true;
|
| + NaClXCondVarBroadcast(&cv);
|
| +}
|
| +
|
| +nacl::DescWrapper* PnaclTranslationUnit::LookupDesc(const nacl::string& url) {
|
| + nacl::DescWrapper* wrapper;
|
| + // Create the callback used to report when lookup is done.
|
| + pp::CompletionCallback resume_cb =
|
| + callback_factory.NewCallback(&PnaclTranslationUnit::ResumeLookup, this);
|
| + // Run the lookup request on the main thread.
|
| + lookup_is_complete = false;
|
| + pp::CompletionCallback load_cb =
|
| + callback_factory.NewCallback(&PnaclTranslationUnit::LoadOneFile,
|
| + url, &wrapper, resume_cb);
|
| + pp::Core* core = pp::Module::Get()->core();
|
| + core->CallOnMainThread(0, load_cb, PP_OK);
|
| + // Wait for completion (timeout every 10ms to check for process end).
|
| + const int32_t kTenMilliseconds = 10 * 1000 * 1000;
|
| + NACL_TIMESPEC_T reltime;
|
| + reltime.tv_sec = 0;
|
| + reltime.tv_nsec = kTenMilliseconds;
|
| + NaClXMutexLock(&mu);
|
| + while (!lookup_is_complete) {
|
| + // Check for termination.
|
| + if (coordinator->SubprocessesShouldDie()) {
|
| + NaClXMutexUnlock(&mu);
|
| + NaClThreadExit(0);
|
| + }
|
| + NaClXCondVarTimedWaitRelative(&cv, &mu, &reltime);
|
| + }
|
| + NaClXMutexUnlock(&mu);
|
| + return wrapper;
|
| +}
|
| +
|
| +//////////////////////////////////////////////////////////////////////
|
| void PnaclCoordinator::Initialize(Plugin* plugin) {
|
| PLUGIN_PRINTF(("PnaclCoordinator::Initialize (this=%p)\n",
|
| static_cast<void*>(this)));
|
| @@ -40,62 +336,72 @@
|
| CHECK(plugin_ == NULL); // Can only initialize once.
|
| plugin_ = plugin;
|
| callback_factory_.Initialize(this);
|
| + // Open the temporary file system.
|
| + file_system_.reset(new pp::FileSystem(plugin,
|
| + PP_FILESYSTEMTYPE_LOCALTEMPORARY));
|
| + CHECK(file_system_ != NULL);
|
| + // Preload llc and ld.
|
| + resource_base_url_ = ResourceBaseUrl();
|
| resources_.reset(new PnaclResources(plugin, this));
|
| + CHECK(resources_ != NULL);
|
| resources_->Initialize();
|
| + pp::CompletionCallback resources_cb =
|
| + callback_factory_.NewCallback(&PnaclCoordinator::ResourcesDidLoad);
|
| + resources_->AddResourceUrl(kLlcUrl);
|
| + resources_->AddResourceUrl(kLdUrl);
|
| + resources_->RunWhenAllLoaded(resources_cb);
|
| + resources_->StartDownloads();
|
| + // ResourcesDidLoad will be invoked when all resources have been received.
|
| + // Initialization of the file system continues through that chain.
|
| }
|
|
|
| PnaclCoordinator::~PnaclCoordinator() {
|
| PLUGIN_PRINTF(("PnaclCoordinator::~PnaclCoordinator (this=%p)\n",
|
| static_cast<void*>(this)));
|
| -
|
| - // Join helper threads which will block the page from refreshing while a
|
| + // Join helper thread which will block the page from refreshing while a
|
| // translation is happening.
|
| - if (translate_thread_.get() != NULL || link_thread_.get() != NULL) {
|
| - SetSubprocessesShouldDie(true);
|
| - }
|
| if (translate_thread_.get() != NULL) {
|
| + SetSubprocessesShouldDie(true);
|
| NaClThreadJoin(translate_thread_.get());
|
| }
|
| - if (link_thread_.get() != NULL) {
|
| - NaClThreadJoin(link_thread_.get());
|
| - }
|
| }
|
|
|
| -void PnaclCoordinator::ReportLoadAbort() {
|
| - plugin_->ReportLoadAbort();
|
| +void PnaclCoordinator::ReportNonPpapiError(const nacl::string& message) {
|
| + ErrorInfo error_info;
|
| + error_info.SetReport(ERROR_UNKNOWN, message);
|
| + ReportPpapiError(PP_ERROR_FAILED, error_info);
|
| }
|
|
|
| -void PnaclCoordinator::ReportLoadError(const ErrorInfo& error) {
|
| - plugin_->ReportLoadError(error);
|
| +void PnaclCoordinator::ReportPpapiError(int32_t pp_error,
|
| + const nacl::string& message) {
|
| + ErrorInfo error_info;
|
| + error_info.SetReport(ERROR_UNKNOWN, message);
|
| + ReportPpapiError(pp_error, error_info);
|
| }
|
|
|
| -void PnaclCoordinator::PnaclPpapiError(int32_t pp_error) {
|
| - // Attempt to free all the intermediate callbacks we ever created.
|
| +void PnaclCoordinator::ReportPpapiError(int32_t pp_error,
|
| + const ErrorInfo& error_info) {
|
| + plugin()->ReportLoadError(error_info);
|
| + // Free all the intermediate callbacks we ever created.
|
| callback_factory_.CancelAll();
|
| translate_notify_callback_.Run(pp_error);
|
| }
|
|
|
| -void PnaclCoordinator::PnaclNonPpapiError() {
|
| - PnaclPpapiError(PP_ERROR_FAILED);
|
| -}
|
| -
|
| void PnaclCoordinator::PnaclDidFinish(int32_t pp_error,
|
| PnaclTranslationUnit* translation_unit) {
|
| PLUGIN_PRINTF(("PnaclCoordinator::PnaclDidFinish (pp_error=%"
|
| NACL_PRId32")\n", pp_error));
|
| if (pp_error != PP_OK) {
|
| - ReportLoadError(translation_unit->error_info);
|
| - PnaclPpapiError(pp_error);
|
| + ReportPpapiError(pp_error, translation_unit->error_info);
|
| return;
|
| }
|
| // Transfer ownership of the nexe wrapper to the coordinator.
|
| - translated_fd_.reset(translation_unit->nexe_wrapper.release());
|
| + // TODO(sehr): need to release the translation unit here while transferring.
|
| + translated_fd_.reset(translation_unit->nexe_file->read_wrapper());
|
| plugin_->EnqueueProgressEvent(Plugin::kProgressEventProgress);
|
| translate_notify_callback_.Run(pp_error);
|
| }
|
|
|
| -//////////////////////////////////////////////////////////////////////
|
| -
|
| int32_t PnaclCoordinator::GetLoadedFileDesc(int32_t pp_error,
|
| const nacl::string& url,
|
| const nacl::string& component) {
|
| @@ -103,59 +409,34 @@
|
| int32_t file_desc = plugin_->GetPOSIXFileDesc(url);
|
| if (pp_error != PP_OK || file_desc == NACL_NO_FILE_DESC) {
|
| if (pp_error == PP_ERROR_ABORTED) {
|
| - ReportLoadAbort();
|
| + plugin_->ReportLoadAbort();
|
| } else {
|
| - // TODO(jvoung): Make a generic load error, or just use ERROR_UNKNOWN?
|
| - error_info.SetReport(ERROR_UNKNOWN,
|
| - "PNaCl " + component + " load failed.");
|
| - ReportLoadError(error_info);
|
| + ReportPpapiError(pp_error,
|
| + "PnaclCoordinator: " + component + " load failed.\n");
|
| }
|
| return -1;
|
| }
|
| int32_t file_desc_ok_to_close = DUP(file_desc);
|
| if (file_desc_ok_to_close == NACL_NO_FILE_DESC) {
|
| - // TODO(jvoung): Make a generic load error, or just use ERROR_UNKNOWN?
|
| - error_info.SetReport(ERROR_UNKNOWN,
|
| - "PNaCl " + component + " load failed: "
|
| - "could not dup fd.");
|
| - ReportLoadError(error_info);
|
| + ReportPpapiError(PP_ERROR_FAILED,
|
| + "PnaclCoordinator: " + component + " could not dup fd.\n");
|
| return -1;
|
| }
|
| return file_desc_ok_to_close;
|
| }
|
|
|
| -bool PnaclCoordinator::StartLlcSubProcess() {
|
| +NaClSubprocess* PnaclCoordinator::StartSubProcess(const nacl::string& url) {
|
| ErrorInfo error_info;
|
| - nacl::DescWrapper* wrapper = resources_->WrapperForUrl(llc_url_);
|
| - NaClSubprocessId llc_id = plugin_->LoadHelperNaClModule(wrapper, &error_info);
|
| - PLUGIN_PRINTF(("PnaclCoordinator::StartLlcSubProcess (nexe_id=%"
|
| - NACL_PRId32")\n", llc_id));
|
| - if (kInvalidNaClSubprocessId == llc_id) {
|
| - error_info.SetReport(ERROR_UNKNOWN, "Could not load pnacl compiler nexe");
|
| - ReportLoadError(error_info);
|
| - PnaclNonPpapiError();
|
| + nacl::DescWrapper* wrapper = resources_->WrapperForUrl(url);
|
| + NaClSubprocessId id = plugin_->LoadHelperNaClModule(wrapper, &error_info);
|
| + PLUGIN_PRINTF(("PnaclCoordinator::StartSubProcess (nexe_id=%"
|
| + NACL_PRId32", url=%s)\n", id, url.c_str()));
|
| + if (kInvalidNaClSubprocessId == id) {
|
| return NULL;
|
| }
|
| - llc_subprocess_ = plugin_->nacl_subprocess(llc_id);
|
| - return (llc_subprocess_ != NULL);
|
| + return plugin_->nacl_subprocess(id);
|
| }
|
|
|
| -bool PnaclCoordinator::StartLdSubProcess() {
|
| - ErrorInfo error_info;
|
| - nacl::DescWrapper* wrapper = resources_->WrapperForUrl(ld_url_);
|
| - NaClSubprocessId ld_id = plugin_->LoadHelperNaClModule(wrapper, &error_info);
|
| - PLUGIN_PRINTF(("PnaclCoordinator::StartLdSubProcess (nexe_id=%"
|
| - NACL_PRId32")\n", ld_id));
|
| - if (kInvalidNaClSubprocessId == ld_id) {
|
| - error_info.SetReport(ERROR_UNKNOWN, "Could not load pnacl linker nexe");
|
| - ReportLoadError(error_info);
|
| - PnaclNonPpapiError();
|
| - return NULL;
|
| - }
|
| - ld_subprocess_ = plugin_->nacl_subprocess(ld_id);
|
| - return (ld_subprocess_ != NULL);
|
| -}
|
| -
|
| bool PnaclCoordinator::SubprocessesShouldDie() {
|
| nacl::MutexLocker ml(&subprocess_mu_);
|
| return subprocesses_should_die_;
|
| @@ -166,428 +447,127 @@
|
| subprocesses_should_die_ = subprocesses_should_die;
|
| }
|
|
|
| -//////////////////////////////////////////////////////////////////////
|
| -// First few callbacks.
|
| -
|
| -//////////////////////////////////////////////////////////////////////
|
| -
|
| -namespace {
|
| -void AbortTranslateThread(PnaclTranslationUnit* translation_unit,
|
| - const nacl::string& error_string) {
|
| - pp::Core* core = pp::Module::Get()->core();
|
| - translation_unit->error_info.SetReport(ERROR_UNKNOWN, error_string);
|
| - core->CallOnMainThread(0, translation_unit->translate_done_cb,
|
| - PP_ERROR_FAILED);
|
| - NaClThreadExit(1);
|
| -}
|
| -
|
| -void WINAPI DoTranslateThread(void* arg) {
|
| - PnaclTranslationUnit* p = reinterpret_cast<PnaclTranslationUnit*>(arg);
|
| - PnaclCoordinator* coordinator = p->coordinator;
|
| - NaClSubprocess* llc_subprocess = coordinator->llc_subprocess();
|
| - Plugin* plugin = coordinator->plugin();
|
| - BrowserInterface* browser = plugin->browser_interface();
|
| -
|
| - // Set up LLC flags first.
|
| - // TODO(jvoung): Bake these into the llc nexe?
|
| - // May also want to improve scriptability, but the only thing we need
|
| - // probably is PIC vs non-PIC and micro-arch specification.
|
| - const char* llc_args_x8632[] = { "-march=x86",
|
| - "-mcpu=pentium4",
|
| - "-mtriple=i686-none-nacl-gnu",
|
| - "-asm-verbose=false",
|
| - "-filetype=obj" };
|
| - const char* llc_args_x8664[] = { "-march=x86-64",
|
| - "-mcpu=core2",
|
| - "-mtriple=x86_64-none-nacl-gnu",
|
| - "-asm-verbose=false",
|
| - "-filetype=obj" };
|
| - const char* llc_args_arm[] = { "-march=arm",
|
| - "-mcpu=cortex-a8",
|
| - "-mtriple=armv7a-none-nacl-gnueabi",
|
| - "-asm-verbose=false",
|
| - "-filetype=obj",
|
| - "-arm-reserve-r9",
|
| - "-sfi-disable-cp",
|
| - "-arm_static_tls",
|
| - "-sfi-store",
|
| - "-sfi-load",
|
| - "-sfi-stack",
|
| - "-sfi-branch",
|
| - "-sfi-data",
|
| - "-no-inline-jumptables" };
|
| -
|
| - nacl::string sandbox_isa = GetSandboxISA();
|
| - const char** llc_args;
|
| - size_t num_args;
|
| -
|
| - if (sandbox_isa.compare("x86-32") == 0) {
|
| - llc_args = llc_args_x8632;
|
| - num_args = NACL_ARRAY_SIZE(llc_args_x8632);
|
| - } else if (sandbox_isa.compare("x86-64") == 0) {
|
| - llc_args = llc_args_x8664;
|
| - num_args = NACL_ARRAY_SIZE(llc_args_x8664);
|
| - } else if (sandbox_isa.compare("arm") == 0) {
|
| - llc_args = llc_args_arm;
|
| - num_args = NACL_ARRAY_SIZE(llc_args_arm);
|
| - } else {
|
| - AbortTranslateThread(p,
|
| - "PnaclCoordinator compiler unhandled ISA " +
|
| - sandbox_isa + ".");
|
| - return;
|
| - }
|
| -
|
| - for (uint32_t i = 0; i < num_args; i++) {
|
| - if (coordinator->SubprocessesShouldDie()) {
|
| - NaClThreadExit(1);
|
| - }
|
| - SrpcParams dummy_params;
|
| - if (!PnaclSrpcLib::InvokeSrpcMethod(browser,
|
| - llc_subprocess,
|
| - "AddArg",
|
| - "C",
|
| - &dummy_params,
|
| - llc_args[i])) {
|
| - AbortTranslateThread(p,
|
| - "PnaclCoordinator compiler AddArg(" +
|
| - nacl::string(llc_args[i]) + ") failed.");
|
| - }
|
| - }
|
| -
|
| - if (coordinator->SubprocessesShouldDie()) {
|
| - NaClThreadExit(1);
|
| - }
|
| - SrpcParams params;
|
| - if (!PnaclSrpcLib::InvokeSrpcMethod(browser,
|
| - llc_subprocess,
|
| - "Translate",
|
| - "h",
|
| - ¶ms,
|
| - p->pexe_wrapper->desc())) {
|
| - AbortTranslateThread(p,
|
| - "PnaclCoordinator compile failed.");
|
| - } else {
|
| - // Grab the outparams.
|
| - p->obj_wrapper.reset(
|
| - plugin->wrapper_factory()->MakeGeneric(params.outs()[0]->u.hval));
|
| - p->obj_len = params.outs()[1]->u.ival;
|
| - p->is_shared_library = params.outs()[2]->u.ival != 0;
|
| - p->soname = params.outs()[3]->arrays.str;
|
| - p->lib_dependencies = params.outs()[4]->arrays.str;
|
| - PLUGIN_PRINTF(("PnaclCoordinator::Translate SRPC succeeded (bytes=%"
|
| - NACL_PRId32", is_shared_library=%d, soname='%s', "
|
| - "lib_dependencies='%s')\n", p->obj_len,
|
| - p->is_shared_library, p->soname.c_str(),
|
| - p->lib_dependencies.c_str()));
|
| - }
|
| - if (coordinator->SubprocessesShouldDie()) {
|
| - NaClThreadExit(1);
|
| - }
|
| - pp::Core* core = pp::Module::Get()->core();
|
| - core->CallOnMainThread(0, p->translate_done_cb, PP_OK);
|
| - NaClThreadExit(0);
|
| -}
|
| -
|
| -} // namespace
|
| -
|
| void PnaclCoordinator::RunTranslate(int32_t pp_error,
|
| - const nacl::string& pexe_url,
|
| PnaclTranslationUnit* translation_unit) {
|
| PLUGIN_PRINTF(("PnaclCoordinator::RunTranslate (pp_error=%"
|
| NACL_PRId32")\n", pp_error));
|
| - // pp_error is checked by GetLoadedFileDesc.
|
| - int32_t fd = GetLoadedFileDesc(pp_error, pexe_url, "pexe");
|
| + int32_t fd = GetLoadedFileDesc(pp_error, translation_unit->pexe_url, "pexe");
|
| if (fd < 0) {
|
| - PnaclPpapiError(pp_error);
|
| return;
|
| }
|
| translation_unit->pexe_wrapper.reset(
|
| plugin_->wrapper_factory()->MakeFileDesc(fd, O_RDONLY));
|
| - if (!StartLlcSubProcess()) {
|
| - ErrorInfo error_info;
|
| - error_info.SetReport(ERROR_UNKNOWN,
|
| - "Could not start compiler subprocess\n");
|
| - ReportLoadError(error_info);
|
| - PnaclNonPpapiError();
|
| + llc_subprocess_ = StartSubProcess(kLlcUrl);
|
| + if (llc_subprocess_ == NULL) {
|
| + ReportNonPpapiError(
|
| + "PnaclCoordinator: Could not start compiler subprocess\n");
|
| return;
|
| }
|
| - // Invoke llvm asynchronously.
|
| - // RunLink runs on the main thread when llvm is done.
|
| + ld_subprocess_ = StartSubProcess(kLdUrl);
|
| + if (ld_subprocess_ == NULL) {
|
| + ReportNonPpapiError(
|
| + "PnaclCoordinator: Could not start linker subprocess\n");
|
| + return;
|
| + }
|
| + // Invoke llc followed by ld off the main thread. This allows use of
|
| + // blocking RPCs that would otherwise block the JavaScript main thread.
|
| translation_unit->translate_done_cb =
|
| - callback_factory_.NewCallback(&PnaclCoordinator::RunLink,
|
| + callback_factory_.NewCallback(&PnaclCoordinator::PnaclDidFinish,
|
| translation_unit);
|
| translate_thread_.reset(new NaClThread);
|
| if (translate_thread_ == NULL) {
|
| - ErrorInfo error_info;
|
| - error_info.SetReport(ERROR_UNKNOWN,
|
| - "Could not allocate DoTranslateThread()\n");
|
| - ReportLoadError(error_info);
|
| - PnaclNonPpapiError();
|
| + ReportNonPpapiError("PnaclCoordinator: Could not allocate thread struct\n");
|
| return;
|
| }
|
| + const int32_t kArbitraryStackSize = 128 << 10;
|
| if (!NaClThreadCreateJoinable(translate_thread_.get(),
|
| DoTranslateThread,
|
| translation_unit,
|
| kArbitraryStackSize)) {
|
| - ErrorInfo error_info;
|
| - error_info.SetReport(ERROR_UNKNOWN,
|
| - "Could not create a translator thread.\n");
|
| - ReportLoadError(error_info);
|
| - PnaclNonPpapiError();
|
| + ReportNonPpapiError("PnaclCoordinator: Could not create thread\n");
|
| }
|
| }
|
|
|
| -//////////////////////////////////////////////////////////////////////
|
| -// Helper functions for loading native libs.
|
| -// Done here to avoid hacking on the manifest parser further...
|
| -
|
| -namespace {
|
| -
|
| -// Fake filename for the object file generated by llvm.
|
| -nacl::string GeneratedObjectFileName() {
|
| - return nacl::string("___PNACL_GENERATED");
|
| -}
|
| -
|
| -nacl::string ResourceBaseUrl() {
|
| - nacl::string sandbox_isa = GetSandboxISA();
|
| - nacl::string base_url = "pnacl_support/" + sandbox_isa + "/";
|
| - return base_url;
|
| -}
|
| -
|
| -string_vector LinkResources(const nacl::string& sandbox_isa,
|
| - bool withGenerated) {
|
| - string_vector results;
|
| - // NOTE: order of items == link order.
|
| - if (sandbox_isa.compare("x86-64") == 0) {
|
| - results.push_back("libpnacl_irt_shim.a");
|
| +void PnaclCoordinator::ResourcesDidLoad(int32_t pp_error) {
|
| + PLUGIN_PRINTF(("PnaclCoordinator::ResourcesDidLoad (pp_error=%"
|
| + NACL_PRId32")\n", pp_error));
|
| + if (pp_error != PP_OK) {
|
| + ReportPpapiError(pp_error, "PnaclCoordinator: resources failed to load\n");
|
| + return;
|
| }
|
| - results.push_back("crtbegin.o");
|
| - if (withGenerated) {
|
| - results.push_back(GeneratedObjectFileName());
|
| + // Open the local temporary file system to create the temporary files
|
| + // for the object and nexe.
|
| + pp::CompletionCallback cb =
|
| + callback_factory_.NewCallback(&PnaclCoordinator::FileSystemDidOpen);
|
| + if (!file_system_->Open(0, cb)) {
|
| + ReportNonPpapiError("PnaclCoordinator: failed to open file system.\n");
|
| }
|
| - results.push_back("libcrt_platform.a");
|
| - results.push_back("libgcc.a");
|
| - results.push_back("libgcc_eh.a");
|
| - results.push_back("crtend.o");
|
| - return results;
|
| }
|
|
|
| -} // namespace
|
| -
|
| -//////////////////////////////////////////////////////////////////////
|
| -// Final link callbacks.
|
| -
|
| -namespace {
|
| -
|
| -void AbortLinkThread(PnaclTranslationUnit* translation_unit,
|
| - const nacl::string& error_string) {
|
| - ErrorInfo error_info;
|
| - pp::Core* core = pp::Module::Get()->core();
|
| - translation_unit->error_info.SetReport(ERROR_UNKNOWN, error_string);
|
| - core->CallOnMainThread(0, translation_unit->link_done_cb, PP_ERROR_FAILED);
|
| - NaClThreadExit(1);
|
| -}
|
| -
|
| -void WINAPI DoLinkThread(void* arg) {
|
| - PnaclTranslationUnit* p = reinterpret_cast<PnaclTranslationUnit*>(arg);
|
| - PnaclCoordinator* coordinator = p->coordinator;
|
| - NaClSubprocess* ld_subprocess = coordinator->ld_subprocess();
|
| - Plugin* plugin = coordinator->plugin();
|
| - BrowserInterface* browser_interface = plugin->browser_interface();
|
| -
|
| - // Set up command line arguments (flags then files).
|
| -
|
| - //// Flags.
|
| - // TODO(jvoung): Be able to handle the dynamic linking flags too,
|
| - // and don't hardcode so much here.
|
| - string_vector flags;
|
| - nacl::string sandbox_isa = GetSandboxISA();
|
| - flags.push_back("-nostdlib");
|
| - flags.push_back("-m");
|
| - if (sandbox_isa.compare("x86-32") == 0) {
|
| - flags.push_back("elf_nacl");
|
| - } else if (sandbox_isa.compare("x86-64") == 0) {
|
| - flags.push_back("elf64_nacl");
|
| - flags.push_back("-entry=_pnacl_wrapper_start");
|
| - } else if (sandbox_isa.compare("arm") == 0) {
|
| - flags.push_back("armelf_nacl");
|
| - } else {
|
| - AbortLinkThread(p,
|
| - "PnaclCoordinator linker unhandled ISA " +
|
| - sandbox_isa + ".");
|
| +void PnaclCoordinator::FileSystemDidOpen(int32_t pp_error) {
|
| + PLUGIN_PRINTF(("PnaclCoordinator::FileSystemDidOpen (pp_error=%"
|
| + NACL_PRId32")\n", pp_error));
|
| + if (pp_error != PP_OK) {
|
| + ReportPpapiError(pp_error, "PnaclCoordinator: file system didn't open.\n");
|
| + return;
|
| }
|
| -
|
| - for (string_vector::iterator i = flags.begin(), e = flags.end();
|
| - i != e; ++i) {
|
| - const nacl::string& flag = *i;
|
| - if (coordinator->SubprocessesShouldDie()) {
|
| - NaClThreadExit(1);
|
| - }
|
| - SrpcParams dummy_params;
|
| - if (!PnaclSrpcLib::InvokeSrpcMethod(browser_interface,
|
| - ld_subprocess,
|
| - "AddArg",
|
| - "C",
|
| - &dummy_params,
|
| - flag.c_str())) {
|
| - AbortLinkThread(p,
|
| - "PnaclCoordinator linker AddArg(" + flag +
|
| - ") failed.");
|
| - }
|
| + file_system_is_initialized_ = true;
|
| + // If there was a pending translation unit, start translating it.
|
| + PnaclTranslationUnit* translation_unit = translation_unit_.release();
|
| + if (translation_unit != NULL) {
|
| + DoStartTranslation(PP_OK, translation_unit);
|
| }
|
| -
|
| - //// Files.
|
| - string_vector files = LinkResources(sandbox_isa, true);
|
| - PnaclResources* resources = coordinator->resources();
|
| - for (string_vector::iterator i = files.begin(), e = files.end();
|
| - i != e; ++i) {
|
| - const nacl::string& link_file = *i;
|
| - if (coordinator->SubprocessesShouldDie()) {
|
| - NaClThreadExit(1);
|
| - }
|
| - // Add as argument.
|
| - SrpcParams dummy_params;
|
| - if (!PnaclSrpcLib::InvokeSrpcMethod(browser_interface,
|
| - ld_subprocess,
|
| - "AddArg",
|
| - "C",
|
| - &dummy_params,
|
| - link_file.c_str())) {
|
| - AbortLinkThread(p,
|
| - "PnaclCoordinator linker AddArg(" +
|
| - link_file + ") failed.");
|
| - }
|
| - // Also map the file name to descriptor.
|
| - if (i->compare(GeneratedObjectFileName()) == 0) {
|
| - SrpcParams dummy_params2;
|
| - if (!PnaclSrpcLib::InvokeSrpcMethod(browser_interface,
|
| - ld_subprocess,
|
| - "AddFileWithSize",
|
| - "Chi",
|
| - &dummy_params2,
|
| - link_file.c_str(),
|
| - p->obj_wrapper->desc(),
|
| - p->obj_len)) {
|
| - AbortLinkThread(p,
|
| - "PnaclCoordinator linker AddFileWithSize"
|
| - "(" + link_file + ") failed.");
|
| - }
|
| - } else {
|
| - SrpcParams dummy_params2;
|
| - NaClDesc* link_file_desc = resources->WrapperForUrl(link_file)->desc();
|
| - if (!PnaclSrpcLib::InvokeSrpcMethod(browser_interface,
|
| - ld_subprocess,
|
| - "AddFile",
|
| - "Ch",
|
| - &dummy_params2,
|
| - link_file.c_str(),
|
| - link_file_desc)) {
|
| - AbortLinkThread(p,
|
| - "PnaclCoordinator linker AddFile(" + link_file +
|
| - ") failed.");
|
| - }
|
| - }
|
| - }
|
| -
|
| - if (coordinator->SubprocessesShouldDie()) {
|
| - NaClThreadExit(1);
|
| - }
|
| -
|
| - // Finally, do the Link!
|
| - SrpcParams params;
|
| - if (!PnaclSrpcLib::InvokeSrpcMethod(browser_interface,
|
| - ld_subprocess,
|
| - "Link",
|
| - "",
|
| - ¶ms)) {
|
| - AbortLinkThread(p, "PnaclCoordinator link failed.");
|
| - } else {
|
| - // Grab the outparams.
|
| - p->nexe_wrapper.reset(
|
| - plugin->wrapper_factory()->MakeGeneric(params.outs()[0]->u.hval));
|
| - int32_t nexe_size = params.outs()[1]->u.ival; // only for debug.
|
| - PLUGIN_PRINTF(("PnaclCoordinator::InvokeLink succeeded (bytes=%"
|
| - NACL_PRId32")\n", nexe_size));
|
| - }
|
| - if (coordinator->SubprocessesShouldDie()) {
|
| - NaClThreadExit(1);
|
| - }
|
| - pp::Core* core = pp::Module::Get()->core();
|
| - core->CallOnMainThread(0, p->link_done_cb, PP_OK);
|
| - NaClThreadExit(0);
|
| }
|
|
|
| -} // namespace
|
| -
|
| -void PnaclCoordinator::RunLink(int32_t pp_error,
|
| - PnaclTranslationUnit* translation_unit) {
|
| - PLUGIN_PRINTF(("PnaclCoordinator::RunLink (pp_error=%"
|
| +void PnaclCoordinator::DoStartTranslation(int32_t pp_error,
|
| + PnaclTranslationUnit* translation) {
|
| + PLUGIN_PRINTF(("PnaclCoordinator::DoStartTranslation (pp_error=%"
|
| NACL_PRId32")\n", pp_error));
|
| if (pp_error != PP_OK) {
|
| - ReportLoadError(translation_unit->error_info);
|
| - PnaclPpapiError(pp_error);
|
| + ReportPpapiError(pp_error, translation->error_info);
|
| return;
|
| }
|
| - plugin_->EnqueueProgressEvent(Plugin::kProgressEventProgress);
|
| - if (!StartLdSubProcess()) {
|
| - ErrorInfo error_info;
|
| - error_info.SetReport(ERROR_UNKNOWN,
|
| - "Could not start linker subprocess\n");
|
| - ReportLoadError(error_info);
|
| - PnaclNonPpapiError();
|
| - return;
|
| - }
|
| + // Create the object file pair for connecting llc and ld.
|
| + translation->obj_file.reset(new PnaclFileDescPair(file_system_.get(), this));
|
| + pp::CompletionCallback cb =
|
| + callback_factory_.NewCallback(&PnaclCoordinator::ObjectPairDidOpen,
|
| + translation);
|
| + translation->obj_file->Open(cb);
|
| +}
|
|
|
| - // Invoke ld asynchronously.
|
| - // When ld has completed, PnaclDidFinish is run on the main thread.
|
| - translation_unit->link_done_cb =
|
| - callback_factory_.NewCallback(&PnaclCoordinator::PnaclDidFinish,
|
| - translation_unit);
|
| - link_thread_.reset(new NaClThread);
|
| - if (link_thread_ == NULL) {
|
| - ErrorInfo error_info;
|
| - error_info.SetReport(ERROR_UNKNOWN,
|
| - "Could not allocate DoLinkThread()\n");
|
| - ReportLoadError(error_info);
|
| - PnaclNonPpapiError();
|
| +void PnaclCoordinator::ObjectPairDidOpen(int32_t pp_error,
|
| + PnaclTranslationUnit* translation) {
|
| + PLUGIN_PRINTF(("PnaclCoordinator::ObjectPairDidOpen (pp_error=%"
|
| + NACL_PRId32")\n", pp_error));
|
| + if (pp_error != PP_OK) {
|
| + ReportPpapiError(pp_error, translation->error_info);
|
| return;
|
| }
|
| - if (!NaClThreadCreateJoinable(link_thread_.get(),
|
| - DoLinkThread,
|
| - translation_unit,
|
| - kArbitraryStackSize)) {
|
| - ErrorInfo error_info;
|
| - error_info.SetReport(ERROR_UNKNOWN,
|
| - "Could not create a linker thread.\n");
|
| - ReportLoadError(error_info);
|
| - PnaclNonPpapiError();
|
| - }
|
| + // Create the nexe file pair for connecting ld and sel_ldr.
|
| + translation->nexe_file.reset(new PnaclFileDescPair(file_system_.get(), this));
|
| + pp::CompletionCallback cb =
|
| + callback_factory_.NewCallback(&PnaclCoordinator::NexePairDidOpen,
|
| + translation);
|
| + translation->nexe_file->Open(cb);
|
| }
|
|
|
| -//////////////////////////////////////////////////////////////////////
|
| -
|
| -void PnaclCoordinator::ResourcesDidLoad(int32_t pp_error,
|
| - const nacl::string& pexe_url,
|
| - PnaclTranslationUnit* translation) {
|
| - PLUGIN_PRINTF(("PnaclCoordinator::ResourcesDidLoad (pp_error=%"
|
| +void PnaclCoordinator::NexePairDidOpen(int32_t pp_error,
|
| + PnaclTranslationUnit* translation) {
|
| + PLUGIN_PRINTF(("PnaclCoordinator::NexePairDidOpen (pp_error=%"
|
| NACL_PRId32")\n", pp_error));
|
| if (pp_error != PP_OK) {
|
| - ReportLoadError(translation->error_info);
|
| - PnaclPpapiError(pp_error);
|
| + ReportPpapiError(pp_error, translation->error_info);
|
| return;
|
| }
|
| + // Load the pexe file and get the translation started.
|
| pp::CompletionCallback cb =
|
| callback_factory_.NewCallback(&PnaclCoordinator::RunTranslate,
|
| - pexe_url,
|
| translation);
|
|
|
| - if (!plugin_->StreamAsFile(pexe_url, cb.pp_completion_callback())) {
|
| - ErrorInfo error_info;
|
| - error_info.SetReport(ERROR_UNKNOWN,
|
| - "PnaclCoordinator: Failed to download file: " +
|
| - pexe_url + "\n");
|
| - ReportLoadError(error_info);
|
| - PnaclNonPpapiError();
|
| + if (!plugin_->StreamAsFile(translation->pexe_url,
|
| + cb.pp_completion_callback())) {
|
| + ReportNonPpapiError("PnaclCoordinator: failed to download file: " +
|
| + translation->pexe_url + "\n");
|
| }
|
| }
|
|
|
| @@ -596,43 +576,17 @@
|
| const pp::CompletionCallback& finish_callback) {
|
| PLUGIN_PRINTF(("PnaclCoordinator::BitcodeToNative (pexe=%s)\n",
|
| pexe_url.c_str()));
|
| - // The base URL for finding all the resources will be obtained from the
|
| - // PNaCl manifest file.
|
| - // Also, the llc and ld pathnames should be read from the manifest.
|
| - // TODO(sehr): change to use the manifest file when ready.
|
| - resource_base_url_ = ResourceBaseUrl();
|
| - llc_url_ = "llc";
|
| - ld_url_ = "ld";
|
| translate_notify_callback_ = finish_callback;
|
|
|
| - // Steps:
|
| - // (1) Schedule downloads for llc, ld nexes, and native libraries (resources).
|
| - // (2) When resources have been downloaded, download pexe.
|
| - // (3) When pexe download has completed, start translation.
|
| - // (4) When llc translation has finished do the link.
|
| - // (5) When the link is done, we are done, call the finish_callback.
|
| - // Hand off the SHM file descriptor returned by link.
|
| + PnaclTranslationUnit* translation_unit =
|
| + new PnaclTranslationUnit(this, pexe_url);
|
|
|
| - // Set up async callbacks for these steps in reverse order.
|
| -
|
| - translation_unit_.reset(new PnaclTranslationUnit(this));
|
| -
|
| - // When resources loading completes, this causes the pexe download.
|
| - pp::CompletionCallback resources_cb =
|
| - callback_factory_.NewCallback(&PnaclCoordinator::ResourcesDidLoad,
|
| - pexe_url,
|
| - translation_unit_.get());
|
| - resources_->AddResourceUrl(llc_url_);
|
| - resources_->AddResourceUrl(ld_url_);
|
| - string_vector link_resources = LinkResources(GetSandboxISA(), false);
|
| - for (string_vector::iterator
|
| - i = link_resources.begin(), e = link_resources.end();
|
| - i != e;
|
| - ++i) {
|
| - resources_->AddResourceUrl(*i);
|
| + if (file_system_is_initialized_) {
|
| + DoStartTranslation(PP_OK, translation_unit_.get());
|
| + } else {
|
| + // Hold translation unit until file system initialization is complete.
|
| + translation_unit_.reset(translation_unit);
|
| }
|
| - resources_->RunWhenAllLoaded(resources_cb);
|
| - resources_->StartDownloads();
|
| }
|
|
|
| } // namespace plugin
|
|
|