| // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| |
| #ifndef RUNTIME_BIN_LOADER_H_ |
| #define RUNTIME_BIN_LOADER_H_ |
| |
| #include "bin/isolate_data.h" |
| #include "include/dart_api.h" |
| #include "include/dart_native_api.h" |
| #include "platform/assert.h" |
| #include "platform/globals.h" |
| #include "bin/thread.h" |
| |
| namespace dart { |
| namespace bin { |
| |
| class Loader { |
| public: |
| explicit Loader(IsolateData* isolate_data); |
| ~Loader(); |
| |
| static void InitForSnapshot(const char* snapshot_uri); |
| |
| static Dart_Handle ReloadNativeExtensions(); |
| |
| // Loads contents of the specified url. |
| static Dart_Handle LoadUrlContents(Dart_Handle url, |
| uint8_t** payload, |
| intptr_t* payload_length); |
| |
| |
| // A static tag handler that hides all usage of a loader for an isolate. |
| static Dart_Handle LibraryTagHandler(Dart_LibraryTag tag, |
| Dart_Handle library, |
| Dart_Handle url); |
| |
| Dart_Handle error() const { return error_; } |
| |
| static void InitOnce(); |
| |
| private: |
| // The port assigned to our native message handler. |
| Dart_Port port_; |
| // Each Loader is associated with an Isolate via its IsolateData. |
| IsolateData* isolate_data_; |
| // Remember the first error that occurs during loading. |
| Dart_Handle error_; |
| // This monitor is used to protect the pending operations count and the |
| // I/O result queue. |
| Monitor* monitor_; |
| |
| // The number of operations dispatched to the service isolate for loading. |
| // Must be accessed with monitor_ held. |
| intptr_t pending_operations_; |
| |
| // The result of an I/O request to the service isolate. Payload is either |
| // a UInt8Array or a C string containing an error message. |
| struct IOResult { |
| uint8_t* payload; |
| intptr_t payload_length; |
| char* library_uri; |
| char* uri; |
| char* resolved_uri; |
| int8_t tag; |
| |
| void Setup(Dart_CObject* message); |
| void Cleanup(); |
| }; |
| // An array of I/O results queued from the service isolate. |
| IOResult* results_; |
| intptr_t results_length_; |
| intptr_t results_capacity_; |
| uint8_t* payload_; |
| intptr_t payload_length_; |
| typedef bool (*ProcessResult)(Loader* loader, IOResult* result); |
| |
| intptr_t results_length() { |
| return *static_cast<volatile intptr_t*>(&results_length_); |
| } |
| |
| // Send the loader init request to the service isolate. |
| void Init(const char* package_root, |
| const char* packages_file, |
| const char* working_directory, |
| const char* root_script_uri); |
| |
| // Send a request for a dart-ext: import to the service isolate. |
| void SendImportExtensionRequest(Dart_Handle url, Dart_Handle library_url); |
| |
| // Send a request from the tag handler to the service isolate. |
| void SendRequest(Dart_LibraryTag tag, |
| Dart_Handle url, |
| Dart_Handle library_url); |
| |
| // Send a request from the tag handler to the kernel isolate. |
| void SendKernelRequest(Dart_LibraryTag tag, Dart_Handle url); |
| |
| /// Queue |message| and notify the loader that a message is available. |
| void QueueMessage(Dart_CObject* message); |
| |
| /// Blocks the caller until the loader is finished. |
| void BlockUntilComplete(ProcessResult process_result); |
| |
| /// Returns false if |result| is an error and the loader should quit. |
| static bool ProcessResultLocked(Loader* loader, IOResult* result); |
| |
| /// Returns false if |result| is an error and the loader should quit. |
| static bool ProcessUrlLoadResultLocked(Loader* loader, IOResult* result); |
| |
| /// Returns false if an error occurred and the loader should quit. |
| bool ProcessQueueLocked(ProcessResult process_result); |
| |
| // Special inner tag handler for dart: uris. |
| static Dart_Handle DartColonLibraryTagHandler(Dart_LibraryTag tag, |
| Dart_Handle library, |
| Dart_Handle url, |
| const char* library_url_string, |
| const char* url_string); |
| |
| // We use one native message handler callback for N loaders. The native |
| // message handler callback provides us with the Dart_Port which we use as a |
| // key into our map of active loaders from |port| to |isolate_data|. |
| |
| // Static information to map Dart_Port back to the isolate in question. |
| struct LoaderInfo { |
| Dart_Port port; |
| IsolateData* isolate_data; |
| }; |
| |
| // The map of active loaders. |
| static Mutex* loader_infos_lock_; |
| static LoaderInfo* loader_infos_; |
| static intptr_t loader_infos_length_; |
| static intptr_t loader_infos_capacity_; |
| |
| static void AddLoader(Dart_Port port, IsolateData* data); |
| static void RemoveLoader(Dart_Port port); |
| static intptr_t LoaderIndexFor(Dart_Port port); |
| static Loader* LoaderFor(Dart_Port port); |
| static Loader* LoaderForLocked(Dart_Port port); |
| |
| // This is the global callback for the native message handlers. |
| static void NativeMessageHandler(Dart_Port dest_port_id, |
| Dart_CObject* message); |
| }; |
| |
| } // namespace bin |
| } // namespace dart |
| |
| #endif // RUNTIME_BIN_LOADER_H_ |