├── .gitattributes ├── .gitignore ├── EmbeddedDart.sln ├── EmbeddedDart ├── EmbeddedDart.cpp ├── EmbeddedDart.vcxproj ├── EmbeddedDart.vcxproj.user ├── analysis_options.yaml ├── hello_world.dart ├── hello_world.dill ├── pubspec.lock ├── pubspec.yaml ├── stdafx.cpp ├── stdafx.h └── targetver.h ├── README.md ├── dart ├── bin │ ├── builtin.h │ ├── dartutils.h │ ├── dfe.h │ ├── eventhandler.h │ ├── eventhandler_win.h │ ├── gzip.h │ ├── isolate_data.h │ ├── platform.h │ ├── reference_counting.h │ ├── thread.h │ ├── thread_win.h │ ├── utils.h │ ├── utils_win.h │ └── vmservice_impl.h ├── include │ ├── bin │ │ └── dart_io_api.h │ ├── dart_api.h │ ├── dart_api_dl.h │ ├── dart_embedder_api.h │ ├── dart_native_api.h │ ├── dart_tools_api.h │ ├── dart_version.h │ └── internal │ │ └── dart_api_dl_impl.h ├── lib │ ├── win-debug-x64 │ │ └── libdart.lib │ └── win-release-x64 │ │ └── libdart.lib ├── platform │ ├── address_sanitizer.h │ ├── allocation.h │ ├── assert.h │ ├── atomic.h │ ├── floating_point.h │ ├── floating_point_win.h │ ├── globals.h │ ├── growable_array.h │ ├── hashmap.h │ ├── memory_sanitizer.h │ ├── priority_queue.h │ ├── utils.h │ └── utils_win.h └── vm │ ├── allocation.h │ ├── base_isolate.h │ └── globals.h └── setup_env.ps1 /.gitattributes: -------------------------------------------------------------------------------- 1 | *.lib filter=lfs diff=lfs merge=lfs -text 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .vs/ 2 | DartTest2/.idea/ 3 | DartTest2/Debug/ 4 | DartTest2/x64/ 5 | x64/ 6 | Debug/ 7 | .dart_tool/ 8 | .packages -------------------------------------------------------------------------------- /EmbeddedDart.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30320.27 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{A01F8E10-9BCC-469C-983C-C68DE9FBAD54}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "EmbeddedDart", "EmbeddedDart\EmbeddedDart.vcxproj", "{489F4F6A-B87F-4D19-963A-C7AE926BA74A}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|x64 = Debug|x64 13 | Debug|x86 = Debug|x86 14 | Release|x64 = Release|x64 15 | Release|x86 = Release|x86 16 | EndGlobalSection 17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 18 | {489F4F6A-B87F-4D19-963A-C7AE926BA74A}.Debug|x64.ActiveCfg = Debug|x64 19 | {489F4F6A-B87F-4D19-963A-C7AE926BA74A}.Debug|x64.Build.0 = Debug|x64 20 | {489F4F6A-B87F-4D19-963A-C7AE926BA74A}.Debug|x86.ActiveCfg = Debug|Win32 21 | {489F4F6A-B87F-4D19-963A-C7AE926BA74A}.Debug|x86.Build.0 = Debug|Win32 22 | {489F4F6A-B87F-4D19-963A-C7AE926BA74A}.Release|x64.ActiveCfg = Release|x64 23 | {489F4F6A-B87F-4D19-963A-C7AE926BA74A}.Release|x64.Build.0 = Release|x64 24 | {489F4F6A-B87F-4D19-963A-C7AE926BA74A}.Release|x86.ActiveCfg = Release|Win32 25 | {489F4F6A-B87F-4D19-963A-C7AE926BA74A}.Release|x86.Build.0 = Release|Win32 26 | EndGlobalSection 27 | GlobalSection(SolutionProperties) = preSolution 28 | HideSolutionNode = FALSE 29 | EndGlobalSection 30 | GlobalSection(ExtensibilityGlobals) = postSolution 31 | SolutionGuid = {31C78DA3-8333-4E97-AFB0-F1BECE84BB0D} 32 | EndGlobalSection 33 | EndGlobal 34 | -------------------------------------------------------------------------------- /EmbeddedDart/EmbeddedDart.cpp: -------------------------------------------------------------------------------- 1 | // DartTest.cpp : Defines the entry point for the console application. 2 | // 3 | #include "stdafx.h" 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "include/dart_api.h" 11 | #include "include/dart_tools_api.h" 12 | #include "include/dart_embedder_api.h" 13 | 14 | #include "bin/dfe.h" 15 | #include "bin/platform.h" 16 | #include "bin/vmservice_impl.h" 17 | #include "bin/isolate_data.h" 18 | #include "bin/utils.h" 19 | #include "bin/eventhandler.h" 20 | #include "bin/thread.h" 21 | #include "bin/gzip.h" 22 | 23 | using namespace dart::bin; 24 | 25 | namespace dart 26 | { 27 | extern bool FLAG_trace_service; 28 | extern bool FLAG_trace_service_verbose; 29 | } 30 | 31 | extern "C" 32 | { 33 | extern const uint8_t kDartVmSnapshotData[]; 34 | extern const uint8_t kDartVmSnapshotInstructions[]; 35 | extern const uint8_t kDartCoreIsolateSnapshotData[]; 36 | extern const uint8_t kDartCoreIsolateSnapshotInstructions[]; 37 | } 38 | 39 | namespace dart 40 | { 41 | namespace bin 42 | { 43 | extern unsigned int observatory_assets_archive_len; 44 | extern const uint8_t* observatory_assets_archive; 45 | } 46 | } 47 | 48 | Dart_Handle GetVMServiceAssetsArchiveCallback() 49 | { 50 | uint8_t* decompressed = NULL; 51 | intptr_t decompressed_len = 0; 52 | Decompress(observatory_assets_archive, observatory_assets_archive_len, 53 | &decompressed, &decompressed_len); 54 | Dart_Handle tar_file = 55 | DartUtils::MakeUint8Array(decompressed, decompressed_len); 56 | // Free decompressed memory as it has been copied into a Dart array. 57 | free(decompressed); 58 | return tar_file; 59 | } 60 | 61 | Dart_Handle HandleError(Dart_Handle handle) 62 | { 63 | if (Dart_IsError(handle)) 64 | Dart_PropagateError(handle); 65 | return handle; 66 | } 67 | 68 | void SimplePrint(Dart_NativeArguments arguments) 69 | { 70 | bool success = false; 71 | Dart_Handle string = HandleError(Dart_GetNativeArgument(arguments, 0)); 72 | if (Dart_IsString(string)) 73 | { 74 | const char* cstring; 75 | Dart_StringToCString(string, &cstring); 76 | std::cout << cstring; 77 | } 78 | } 79 | 80 | Dart_NativeFunction ResolveName(Dart_Handle name, int argc, bool* auto_setup_scope) 81 | { 82 | if (!Dart_IsString(name)) 83 | return nullptr; 84 | Dart_NativeFunction result = NULL; 85 | 86 | const char* cname; 87 | HandleError(Dart_StringToCString(name, &cname)); 88 | 89 | if (strcmp("SimplePrint", cname) == 0) result = SimplePrint; 90 | 91 | return result; 92 | } 93 | 94 | Dart_Handle Dart_Error(const char* format, ...) 95 | { 96 | char message[512]; 97 | 98 | va_list valist; 99 | va_start(valist, format); 100 | 101 | vsprintf_s(message, format, valist); 102 | auto handle = Dart_NewApiError(message); 103 | va_end(valist); 104 | 105 | return handle; 106 | } 107 | 108 | Dart_Handle LibraryTagHandler(Dart_LibraryTag tag, Dart_Handle library, Dart_Handle url) 109 | { 110 | const char* url_str = NULL; 111 | Dart_Handle result = Dart_StringToCString(url, &url_str); 112 | if (Dart_IsError(result)) 113 | return result; 114 | 115 | // If you want to import other files into your library, you have to implement this, 116 | // but for single files there's no need. 117 | assert(false); 118 | return Dart_Null(); 119 | } 120 | 121 | static Dart_Handle SetupCoreLibraries(Dart_Isolate isolate, 122 | IsolateData* isolate_data, 123 | bool is_isolate_group_start, 124 | const char** resolved_packages_config) { 125 | auto isolate_group_data = isolate_data->isolate_group_data(); 126 | const auto packages_file = isolate_data->packages_file(); 127 | const auto script_uri = isolate_group_data->script_url; 128 | 129 | Dart_Handle result; 130 | 131 | // Prepare builtin and other core libraries for use to resolve URIs. 132 | // Set up various closures, e.g: printing, timers etc. 133 | // Set up package configuration for URI resolution. 134 | result = DartUtils::PrepareForScriptLoading(false, true); 135 | if (Dart_IsError(result)) return result; 136 | 137 | // Setup packages config if specified. 138 | result = DartUtils::SetupPackageConfig(packages_file); 139 | if (Dart_IsError(result)) return result; 140 | if (!Dart_IsNull(result) && resolved_packages_config != nullptr) { 141 | result = Dart_StringToCString(result, resolved_packages_config); 142 | if (Dart_IsError(result)) return result; 143 | ASSERT(*resolved_packages_config != nullptr); 144 | if (is_isolate_group_start) { 145 | isolate_group_data->set_resolved_packages_config( 146 | *resolved_packages_config); 147 | } 148 | else { 149 | ASSERT(strcmp(isolate_group_data->resolved_packages_config(), 150 | *resolved_packages_config) == 0); 151 | } 152 | } 153 | 154 | result = Dart_SetEnvironmentCallback(DartUtils::EnvironmentCallback); 155 | if (Dart_IsError(result)) return result; 156 | 157 | // Setup the native resolver as the snapshot does not carry it. 158 | Builtin::SetNativeResolver(Builtin::kBuiltinLibrary); 159 | Builtin::SetNativeResolver(Builtin::kIOLibrary); 160 | Builtin::SetNativeResolver(Builtin::kCLILibrary); 161 | VmService::SetNativeResolver(); 162 | 163 | result = 164 | DartUtils::SetupIOLibrary(NULL, script_uri, true); 165 | if (Dart_IsError(result)) return result; 166 | 167 | return Dart_Null(); 168 | } 169 | 170 | static Dart_Isolate CreateAndSetupKernelIsolate( 171 | const char* script_uri, 172 | const char* packages_config, 173 | Dart_IsolateFlags* flags, 174 | char** error) 175 | { 176 | const char* kernel_snapshot_uri = dfe.frontend_filename(); 177 | const char* uri = 178 | kernel_snapshot_uri != NULL ? kernel_snapshot_uri : script_uri; 179 | 180 | Dart_Isolate isolate = NULL; 181 | IsolateData* isolate_data = NULL; 182 | 183 | const uint8_t* kernel_service_buffer = NULL; 184 | intptr_t kernel_service_buffer_size = 0; 185 | dfe.LoadKernelService(&kernel_service_buffer, &kernel_service_buffer_size); 186 | ASSERT(kernel_service_buffer != NULL); 187 | IsolateGroupData* isolate_group_data = new IsolateGroupData(uri, packages_config, nullptr, false); 188 | isolate_group_data->SetKernelBufferUnowned( 189 | const_cast(kernel_service_buffer), 190 | kernel_service_buffer_size); 191 | isolate_data = new IsolateData(isolate_group_data); 192 | isolate = Dart_CreateIsolateGroupFromKernel( 193 | DART_KERNEL_ISOLATE_NAME, DART_KERNEL_ISOLATE_NAME, 194 | kernel_service_buffer, kernel_service_buffer_size, flags, 195 | isolate_group_data, isolate_data, error); 196 | 197 | if (isolate == NULL) { 198 | delete isolate_data; 199 | delete isolate_group_data; 200 | return NULL; 201 | } 202 | 203 | Dart_EnterScope(); 204 | 205 | Dart_Handle result = Dart_SetLibraryTagHandler(LibraryTagHandler); 206 | SetupCoreLibraries(isolate, isolate_data, false, nullptr); 207 | 208 | Dart_Handle dartScriptUri = Dart_NewStringFromCString(script_uri); 209 | //CHECK_RESULT(uri); 210 | Dart_Handle resolved_script_uri = DartUtils::ResolveScript(dartScriptUri); 211 | //CHECK_RESULT(resolved_script_uri); 212 | result = Dart_LoadScriptFromKernel(kernel_service_buffer, kernel_service_buffer_size); 213 | //CHECK_RESULT(result); 214 | 215 | Dart_ExitScope(); 216 | Dart_ExitIsolate(); 217 | *error = Dart_IsolateMakeRunnable(isolate); 218 | 219 | return isolate; 220 | } 221 | 222 | Dart_Isolate CreateServiceIsolate( 223 | const char* script_uri, 224 | const char* packages_config, 225 | Dart_IsolateFlags* flags, 226 | char** error) 227 | { 228 | Dart_Isolate isolate = nullptr; 229 | auto isolate_group_data = 230 | new IsolateGroupData(script_uri, packages_config, nullptr, false); 231 | 232 | flags->load_vmservice_library = true; 233 | const uint8_t* isolate_snapshot_data = kDartCoreIsolateSnapshotData; 234 | const uint8_t* isolate_snapshot_instructions = kDartCoreIsolateSnapshotInstructions; 235 | isolate = Dart_CreateIsolateGroup( 236 | script_uri, DART_VM_SERVICE_ISOLATE_NAME, isolate_snapshot_data, 237 | isolate_snapshot_instructions, flags, isolate_group_data, 238 | /*isolate_data=*/nullptr, error); 239 | 240 | Dart_EnterScope(); 241 | 242 | const char* ip = "127.0.0.1"; 243 | const intptr_t port = 5858; 244 | const bool disable_websocket_origin_check = false; 245 | const bool service_isolate_booted = VmService::Setup(ip, port, false, disable_websocket_origin_check, 246 | NULL, true, true, true, true); 247 | assert(service_isolate_booted); 248 | 249 | Dart_Handle result = Dart_SetEnvironmentCallback(DartUtils::EnvironmentCallback); 250 | 251 | Dart_ExitScope(); 252 | Dart_ExitIsolate(); 253 | return isolate; 254 | } 255 | 256 | Dart_Isolate CreateIsolate( 257 | bool isMainIsolate, 258 | const char* script_uri, 259 | const char* name, 260 | const char* packages_config, 261 | Dart_IsolateFlags* flags, 262 | void* callback_data, 263 | char** error) 264 | { 265 | std::cout << __FUNCTION__ << ": " << script_uri << ", " << (name ? name : "NULL") << std::endl; 266 | 267 | uint8_t* kernel_buffer = NULL; 268 | intptr_t kernel_buffer_size = 0; 269 | 270 | PathSanitizer script_uri_sanitizer(script_uri); 271 | PathSanitizer packages_config_sanitizer(packages_config); 272 | dfe.ReadScript(script_uri, &kernel_buffer, &kernel_buffer_size); 273 | flags->null_safety = true; 274 | 275 | auto isolate_group_data = new IsolateGroupData( 276 | script_uri, packages_config, nullptr, false); 277 | isolate_group_data->SetKernelBufferNewlyOwned(kernel_buffer, kernel_buffer_size); 278 | 279 | const uint8_t* platform_kernel_buffer = NULL; 280 | intptr_t platform_kernel_buffer_size = 0; 281 | dfe.LoadPlatform(&platform_kernel_buffer, &platform_kernel_buffer_size); 282 | if (platform_kernel_buffer == NULL) { 283 | platform_kernel_buffer = kernel_buffer; 284 | platform_kernel_buffer_size = kernel_buffer_size; 285 | } 286 | 287 | auto isolate_data = new IsolateData(isolate_group_data); 288 | Dart_Isolate isolate = Dart_CreateIsolateGroupFromKernel( 289 | script_uri, name, platform_kernel_buffer, platform_kernel_buffer_size, 290 | flags, isolate_group_data, isolate_data, error); 291 | assert(isolate); 292 | 293 | std::cout << "Created isolate" << std::endl; 294 | Dart_EnterScope(); 295 | 296 | Dart_Handle result = Dart_SetLibraryTagHandler(LibraryTagHandler); 297 | const char* resolvedPackagesConfig = nullptr; 298 | SetupCoreLibraries(isolate, isolate_data, true, &resolvedPackagesConfig); 299 | 300 | if (kernel_buffer == nullptr && !Dart_IsKernelIsolate(isolate)) 301 | { 302 | uint8_t* application_kernel_buffer = NULL; 303 | intptr_t application_kernel_buffer_size = 0; 304 | int exit_code = 0; 305 | dfe.CompileAndReadScript(script_uri, &application_kernel_buffer, 306 | &application_kernel_buffer_size, error, &exit_code, 307 | resolvedPackagesConfig, 308 | true); 309 | if (application_kernel_buffer == NULL) { 310 | Dart_ExitScope(); 311 | Dart_ShutdownIsolate(); 312 | return NULL; 313 | } 314 | 315 | isolate_group_data->SetKernelBufferNewlyOwned( 316 | application_kernel_buffer, application_kernel_buffer_size); 317 | kernel_buffer = application_kernel_buffer; 318 | kernel_buffer_size = application_kernel_buffer_size; 319 | } 320 | 321 | if (kernel_buffer != NULL) { 322 | Dart_Handle uri = Dart_NewStringFromCString(script_uri); 323 | //CHECK_RESULT(uri); 324 | Dart_Handle resolved_script_uri = DartUtils::ResolveScript(uri); 325 | //CHECK_RESULT(resolved_script_uri); 326 | result = Dart_LoadScriptFromKernel(kernel_buffer, kernel_buffer_size); 327 | if (Dart_IsError(result)) 328 | { 329 | printf("Error loading script: %s", Dart_GetError(result)); 330 | return nullptr; 331 | } 332 | } 333 | 334 | Dart_ExitScope(); 335 | Dart_ExitIsolate(); 336 | *error = Dart_IsolateMakeRunnable(isolate); 337 | if (*error != nullptr) 338 | { 339 | Dart_EnterIsolate(isolate); 340 | Dart_ShutdownIsolate(); 341 | return nullptr; 342 | } 343 | 344 | return isolate; 345 | } 346 | 347 | 348 | Dart_Isolate CreateIsolateGroupAndSetup( 349 | const char* script_uri, 350 | const char* main, 351 | const char* package_root, 352 | const char* package_config, 353 | Dart_IsolateFlags* flags, 354 | void* callback_data, 355 | char** error) 356 | { 357 | if (strcmp(script_uri, DART_VM_SERVICE_ISOLATE_NAME) == 0) 358 | { 359 | return CreateServiceIsolate(script_uri, package_config, flags, error); 360 | } 361 | else if (strcmp(script_uri, DART_KERNEL_ISOLATE_NAME) == 0) 362 | { 363 | int exit_code; 364 | return CreateAndSetupKernelIsolate(script_uri, package_config, flags, error); 365 | } 366 | else 367 | { 368 | int exitCode; 369 | auto isolate = CreateIsolate(false, script_uri, main, package_config, flags, callback_data, error); 370 | if (isolate == nullptr) 371 | { 372 | std::cerr << "Failed to create Isolate: " << script_uri << "|" << (main ? main : "(NULL)") 373 | << ": " << error << std::endl; 374 | } 375 | } 376 | 377 | return nullptr; 378 | } 379 | 380 | static bool OnIsolateInitialize(void** child_callback_data, char** error) 381 | { 382 | Dart_Isolate isolate = Dart_CurrentIsolate(); 383 | ASSERT(isolate != nullptr); 384 | 385 | auto isolate_group_data = 386 | reinterpret_cast(Dart_CurrentIsolateGroupData()); 387 | 388 | auto isolate_data = new IsolateData(isolate_group_data); 389 | *child_callback_data = isolate_data; 390 | 391 | Dart_EnterScope(); 392 | const auto script_uri = isolate_group_data->script_url; 393 | const bool isolate_run_app_snapshot = 394 | isolate_group_data->RunFromAppSnapshot(); 395 | Dart_Handle result = SetupCoreLibraries(isolate, isolate_data, 396 | /*group_start=*/false, 397 | /*resolved_packages_config=*/nullptr); 398 | if (Dart_IsError(result)) goto failed; 399 | 400 | 401 | result = DartUtils::ResolveScript(Dart_NewStringFromCString(script_uri)); 402 | if (Dart_IsError(result)) return result != nullptr; 403 | 404 | if (isolate_group_data->kernel_buffer().get() != nullptr) { 405 | // Various core-library parts will send requests to the Loader to resolve 406 | // relative URIs and perform other related tasks. We need Loader to be 407 | // initialized for this to work because loading from Kernel binary 408 | // bypasses normal source code loading paths that initialize it. 409 | const char* resolved_script_uri = NULL; 410 | result = Dart_StringToCString(result, &resolved_script_uri); 411 | if (Dart_IsError(result)) goto failed; 412 | } 413 | 414 | // Make the isolate runnable so that it is ready to handle messages. 415 | Dart_ExitScope(); 416 | Dart_ExitIsolate(); 417 | *error = Dart_IsolateMakeRunnable(isolate); 418 | Dart_EnterIsolate(isolate); 419 | return *error == nullptr; 420 | 421 | failed: 422 | *error = _strdup(Dart_GetError(result)); 423 | Dart_ExitScope(); 424 | return false; 425 | } 426 | 427 | static void OnIsolateShutdown(void* isolate_group_data, void* isolate_data) 428 | { 429 | Dart_EnterScope(); 430 | Dart_Handle sticky_error = Dart_GetStickyError(); 431 | if (!Dart_IsNull(sticky_error) && !Dart_IsFatalError(sticky_error)) { 432 | printf("%s\n", Dart_GetError(sticky_error)); 433 | } 434 | Dart_ExitScope(); 435 | } 436 | 437 | static void DeleteIsolateData(void* isolate_group_data, void* callback_data) { 438 | auto isolate_data = reinterpret_cast(callback_data); 439 | delete isolate_data; 440 | } 441 | 442 | static void DeleteIsolateGroupData(void* callback_data) { 443 | auto isolate_group_data = reinterpret_cast(callback_data); 444 | delete isolate_group_data; 445 | } 446 | 447 | int main(int argc, const char** argv) 448 | { 449 | dart::FLAG_trace_service = true; 450 | //dart::FLAG_trace_service_verbose = true; 451 | 452 | Dart_SetVMFlags(argc, argv); 453 | Platform::SetExecutableName(argv[0]); 454 | if(!Platform::Initialize()) { 455 | return -1; 456 | } 457 | 458 | char* error = nullptr; 459 | if (!dart::embedder::InitOnce(&error)) 460 | { 461 | printf("Standalone embedde: %s\n", error); 462 | free(error); 463 | return -1; 464 | } 465 | 466 | bool loadDill = true; 467 | const char* scriptFile = loadDill ? "hello_world.dill" : "hello_world.dart"; 468 | const char* packageConfig = ".dart_tool/package_config.json"; 469 | 470 | dfe.Init(); 471 | dfe.set_use_dfe(); 472 | 473 | /*uint8_t* applicationKernelBuffer = nullptr; 474 | intptr_t applicationKernelBufferSize = 0; 475 | dfe.ReadScript(scriptFile, &applicationKernelBuffer, &applicationKernelBufferSize); 476 | if (applicationKernelBuffer != nullptr) 477 | { 478 | dfe.set_application_kernel_buffer(applicationKernelBuffer, applicationKernelBufferSize); 479 | }*/ 480 | 481 | Dart_InitializeParams params = {}; 482 | params.version = DART_INITIALIZE_PARAMS_CURRENT_VERSION; 483 | params.vm_snapshot_data = kDartVmSnapshotData; 484 | params.vm_snapshot_instructions = kDartVmSnapshotInstructions; 485 | params.create_group = CreateIsolateGroupAndSetup; 486 | params.initialize_isolate = OnIsolateInitialize; 487 | params.shutdown_isolate = OnIsolateShutdown; 488 | params.cleanup_isolate = DeleteIsolateData; 489 | params.cleanup_group = DeleteIsolateGroupData; 490 | params.entropy_source = DartUtils::EntropySource; 491 | params.get_service_assets = GetVMServiceAssetsArchiveCallback; 492 | params.start_kernel_isolate = dfe.UseDartFrontend() && dfe.CanUseDartFrontend(); 493 | char* initError = Dart_Initialize(¶ms); 494 | if (initError) 495 | { 496 | printf("Dart_Init failed: %s\n", error); 497 | return 0; 498 | } 499 | 500 | 501 | Dart_IsolateFlags isolateFlags; 502 | Dart_IsolateFlagsInitialize(&isolateFlags); 503 | 504 | Dart_Isolate isolate = CreateIsolate(true, scriptFile, "main", packageConfig, &isolateFlags, nullptr, &error); 505 | if (isolate == nullptr) 506 | { 507 | printf("Failed creating isolate: %s\n", error); 508 | return -1; 509 | } 510 | 511 | Dart_EnterIsolate(isolate); 512 | Dart_EnterScope(); 513 | 514 | Dart_Handle library = Dart_RootLibrary(); 515 | 516 | Dart_SetNativeResolver(library, ResolveName, nullptr); 517 | 518 | Dart_Handle mainClosure = Dart_GetField(library, Dart_NewStringFromCString("main")); 519 | if (!Dart_IsClosure(mainClosure)) 520 | { 521 | std::cout << "Unable to find 'main' in root library " << "hello_world.dart"; 522 | } 523 | 524 | // Call _startIsolate in the isolate library to enable dispatching the 525 | // initial startup message. 526 | const intptr_t kNumIsolateArgs = 2; 527 | Dart_Handle isolateArgs[2] = { 528 | mainClosure, 529 | Dart_Null() 530 | }; 531 | Dart_Handle isolateLib = Dart_LookupLibrary(Dart_NewStringFromCString("dart:isolate")); 532 | Dart_Handle result = Dart_Invoke(isolateLib, Dart_NewStringFromCString("_startMainIsolate"), 533 | kNumIsolateArgs, isolateArgs); 534 | 535 | // Keep handling messages until the last active receive port is closed. 536 | result = Dart_RunLoop(); 537 | 538 | if (Dart_IsError(result)) 539 | { 540 | std::cerr << "Failed to invoke main: " << Dart_GetError(result); 541 | } 542 | 543 | Dart_ExitScope(); 544 | Dart_ShutdownIsolate(); 545 | 546 | Dart_Cleanup(); 547 | 548 | dart::embedder::Cleanup(); 549 | 550 | return 0; 551 | } 552 | 553 | -------------------------------------------------------------------------------- /EmbeddedDart/EmbeddedDart.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 15.0 23 | {489F4F6A-B87F-4D19-963A-C7AE926BA74A} 24 | Win32Proj 25 | DartTest2 26 | 10.0 27 | 28 | 29 | 30 | Application 31 | true 32 | v142 33 | Unicode 34 | 35 | 36 | Application 37 | false 38 | v142 39 | true 40 | Unicode 41 | 42 | 43 | Application 44 | true 45 | v142 46 | Unicode 47 | 48 | 49 | Application 50 | false 51 | v142 52 | true 53 | Unicode 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | true 76 | 77 | 78 | true 79 | 80 | 81 | false 82 | 83 | 84 | false 85 | 86 | 87 | 88 | Use 89 | Level3 90 | Disabled 91 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 92 | true 93 | $(SolutionDir);$(SolutionDir)dart;%(AdditionalIncludeDirectories) 94 | 95 | 96 | Console 97 | true 98 | $(SolutionDir)\dart 99 | libdart_jit.lib;libdart_builtin.lib;libdart_platform.lib;%(AdditionalDependencies) 100 | 101 | 102 | 103 | 104 | Use 105 | Level3 106 | Disabled 107 | DEBUG;_DEBUG;_CONSOLE;_HAS_ITERATOR_DEBUGGING=0;%(PreprocessorDefinitions) 108 | true 109 | $(SolutionDir);$(SolutionDir)dart;%(AdditionalIncludeDirectories) 110 | MultiThreadedDebugDLL 111 | 112 | 113 | Console 114 | true 115 | $(SolutionDir)/dart/lib/win-debug-x64 116 | libdart.lib;dbghelp.lib;rpcrt4.lib;ws2_32.lib;Iphlpapi.lib;Psapi.lib;shlwapi.lib;%(AdditionalDependencies) 117 | 118 | 119 | 120 | 121 | Use 122 | Level3 123 | MaxSpeed 124 | true 125 | true 126 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 127 | true 128 | $(SolutionDir);$(SolutionDir)dart;%(AdditionalIncludeDirectories) 129 | 130 | 131 | Console 132 | true 133 | true 134 | true 135 | $(SolutionDir)\dart 136 | libdart_jit.lib;libdart_builtin.lib;libdart_platform.lib;%(AdditionalDependencies) 137 | 138 | 139 | 140 | 141 | Use 142 | Level3 143 | MaxSpeed 144 | true 145 | true 146 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 147 | true 148 | $(SolutionDir);$(SolutionDir)dart;%(AdditionalIncludeDirectories) 149 | MultiThreadedDLL 150 | 151 | 152 | Console 153 | true 154 | true 155 | true 156 | $(SolutionDir)/dart/lib/win-release-x64 157 | libdart.lib;dbghelp.lib;rpcrt4.lib;ws2_32.lib;Iphlpapi.lib;Psapi.lib;shlwapi.lib;%(AdditionalDependencies) 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | Create 168 | Create 169 | Create 170 | Create 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | -------------------------------------------------------------------------------- /EmbeddedDart/EmbeddedDart.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /EmbeddedDart/analysis_options.yaml: -------------------------------------------------------------------------------- 1 | analyzer: 2 | strong-mode: 3 | implicit-casts: false 4 | implicit-dynamic: false 5 | 6 | errors: 7 | native_function_body_in_non_sdk_code: ignore 8 | -------------------------------------------------------------------------------- /EmbeddedDart/hello_world.dart: -------------------------------------------------------------------------------- 1 | import 'dart:io'; 2 | 3 | void simplePrint(String s) native "SimplePrint"; 4 | 5 | void main() { 6 | simplePrint("hello world\n"); 7 | sleep(Duration(seconds: 3)); 8 | } 9 | -------------------------------------------------------------------------------- /EmbeddedDart/hello_world.dill: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fuzzybinary/dart-embedding-example/131dc9e33a112a313ce49e1d25c6b4db82b1e77d/EmbeddedDart/hello_world.dill -------------------------------------------------------------------------------- /EmbeddedDart/pubspec.lock: -------------------------------------------------------------------------------- 1 | # Generated by pub 2 | # See https://dart.dev/tools/pub/glossary#lockfile 3 | packages: {} 4 | sdks: 5 | dart: ">=2.12.0 <3.0.0" 6 | -------------------------------------------------------------------------------- /EmbeddedDart/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: native_test 2 | description: "A description of this native test library" 3 | publish_to: "none" 4 | 5 | version: 1.0.0+1 6 | 7 | environment: 8 | sdk: '>=2.12.0 <3.0.0' 9 | -------------------------------------------------------------------------------- /EmbeddedDart/stdafx.cpp: -------------------------------------------------------------------------------- 1 | // stdafx.cpp : source file that includes just the standard includes 2 | // $safeprojectname$.pch will be the pre-compiled header 3 | // stdafx.obj will contain the pre-compiled type information 4 | 5 | #include "stdafx.h" 6 | 7 | // TODO: reference any additional headers you need in STDAFX.H 8 | // and not in this file 9 | -------------------------------------------------------------------------------- /EmbeddedDart/stdafx.h: -------------------------------------------------------------------------------- 1 | // stdafx.h : include file for standard system include files, 2 | // or project specific include files that are used frequently, but 3 | // are changed infrequently 4 | // 5 | 6 | #pragma once 7 | 8 | #include "targetver.h" 9 | 10 | #include 11 | #include 12 | 13 | 14 | 15 | // TODO: reference additional headers your program requires here 16 | -------------------------------------------------------------------------------- /EmbeddedDart/targetver.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Including SDKDDKVer.h defines the highest available Windows platform. 4 | 5 | // If you wish to build your application for a previous Windows platform, include WinSDKVer.h and 6 | // set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h. 7 | 8 | #include 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ⚠ NOTE - DEPRECATED ⚠ 2 | 3 | I'm now working more on using Dart from a .dll / so, as well as building / linking from 4 | a Dart repo directly. That effort is hosted [here](https://github.com/fuzzybinary/dart_shared_libray). 5 | That repo includes more examples and scripts for building Dart directly, as well as 6 | CMAKE scripts for building for both Mac and Linux. 7 | 8 | # How to use this 9 | 10 | _Updated 07/24/2021 - Updated to Dart 2.13.4_ 11 | 12 | You can clone this repo and pull out the dart directory which contains all the headers and libraries 13 | you'll need (see Other Notes about some gotchas with these libs). 14 | 15 | DartTest2/DartTest2.cpp does all of the embedding work. Note: 16 | 17 | - I tried simplifying this as much as I can but there's still some complexities and code formatting 18 | differences between my style and the dart team. Sorry. 19 | - You can use `Dart_Invoke` over `Dart_RunLoop` to execute a single Dart function, but doing so does 20 | not drain the message queue. To do so see [Draining the Message 21 | Queue](#draining-the-message-queue) 22 | - Debugging should work provided the service isolate starts up correctly. 23 | - Hot reloading works, but requires a you write your own watcher script to trigger it, as VSCode 24 | doesn't implement it for anything other than Flutter projects. see [this 25 | issue](https://github.com/Dart-Code/Dart-Code/issues/2708) for more information. 26 | - The [Hotreloader](https://pub.dev/packages/hotreloader) pub package implements hot reloading 27 | for the current process, but the code can be ported for connecting to an embedded instance. 28 | - This does not take into account loading pre-compiled dart libraries. 29 | 30 | Other Notes - 31 | 32 | - This is taken from main.cc in runtime/bin which is complicated because it supports all the various 33 | ways of booting the dart runtime in AOT, and other modes. I would like to see how to accomplish 34 | that moving forward 35 | - The startup time is high, mostly because of the overhead of booting the kernel and service 36 | isolates and compiling the dart. 37 | - The way this is currently written assumes sound null safety. There is a function 38 | `Dart_DetectNullSafety` that you could use instead of setting the `flags->null_safety` parameter 39 | directly. 40 | - This can now load a .dill precompiled kernel over a .dart file! Change `loadDill` in main to 41 | switch between using the .dart file and the .dill 42 | 43 | # How I did this 44 | 45 | Dart doesn't have anything available that makes embedding easy. The dart.lib and header files 46 | included in the SDK are for creating extensions, not for embedding, so unfortunately, you'll have to 47 | build it yourself. 48 | 49 | ## Get The Dart Source 50 | 51 | Get the Dart SDK source according to the instructions provided at the Dart home page: 52 | https://github.com/dart-lang/sdk/wiki/Building 53 | 54 | I most recently compiled this with Visual Studio Community 2019, but 2017 is the only "supported" 55 | version You can override the executable for building this by setting the following environment 56 | variables 57 | 58 | ``` 59 | set GYP_MSVS_VERSION=2017 60 | set DEPOT_TOOLS_WIN_TOOLCHAIN=0 61 | set GYP_MSVS_OVERRIDE_PATH="C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\" 62 | ``` 63 | 64 | Make sure depot_tools is also on your path **and** if you have Python 3 installed on your system 65 | make sure depot_tools comes first in your path. Otherwise portions of the build that require Python 66 | 2 will fail. 67 | 68 | ## Build the SDK 69 | 70 | Just in case, let's make sure everything builds properly. 71 | 72 | As of this writing, this just involves doing `python tools/build.py --mode=release create_sdk` 73 | 74 | ## Modify some GN files 75 | 76 | Dart needs a lot of extra stuff on top of the VM to get a lot of the embedding story working. 77 | Instead of trying to figure out what was necessary and not, I basically created a library that is 78 | all of dart.exe minus "main.cc" and called it "dart_lib". To do this: 79 | 80 | - See modifications below 81 | - Regenerate your ninja files for Dart (buildtools\gn.exe gen out\DebugX64) 82 | - Build the library 83 | - Move to out\DebugX64 84 | - ninja libdart 85 | - The new library will be in out\DebugX64\obj\runtime\bin 86 | - I copied over a bunch of header files into the dart directory locally. You could just reference 87 | them directly if you had the dart directory in your include path. You can look in the repo and 88 | see what I needed to copy other than the dart_api headers 89 | 90 | I made other changes to GN files to suit my development style. For example, I no longer use the 91 | statically linked C runtime when I can avoid it, but dart does. If you are building this for 92 | yourself, you may need to change these settings to suit your needs. 93 | 94 | ### Current .gn modifications 95 | 96 | For simplicity, here are the current full modifications I made to the dart-sdk gn files for the libs 97 | included in this repo. These modifications are current as of the version at the top of the file. 98 | 99 | In _runtime/bin/BUILD.gn_ add the following: 100 | 101 | ``` 102 | static_library("libdart") { 103 | deps = [ 104 | ":standalone_dart_io", 105 | "..:libdart_jit", 106 | "../platform:libdart_platform_jit", 107 | ":dart_snapshot_cc", 108 | ":dart_kernel_platform_cc", 109 | "//third_party/boringssl", 110 | "//third_party/zlib", 111 | ] 112 | if (dart_runtime_mode != "release") { 113 | deps += [ "../observatory:standalone_observatory_archive" ] 114 | } 115 | 116 | complete_static_lib = true 117 | 118 | if (dart_use_tcmalloc) { 119 | deps += [ "//third_party/tcmalloc" ] 120 | } 121 | 122 | include_dirs = [ 123 | "..", 124 | "//third_party", 125 | ] 126 | 127 | sources = [ 128 | "builtin.cc", 129 | "error_exit.cc", 130 | "error_exit.h", 131 | "vmservice_impl.cc", 132 | "vmservice_impl.h", 133 | "snapshot_utils.cc", 134 | "snapshot_utils.h", 135 | "gzip.cc", 136 | "gzip.h", 137 | "dfe.cc", 138 | "dfe.h", 139 | "loader.cc", 140 | "loader.h", 141 | "dart_embedder_api_impl.cc", 142 | ] 143 | if (dart_runtime_mode == "release") { 144 | sources += [ "observatory_assets_empty.cc" ] 145 | } 146 | } 147 | ``` 148 | 149 | In _build/config/compiler/BUILD.gn_ change the following (around line 424): 150 | 151 | ```diff 152 | - # Static CRT. 153 | + # Dynamic CRT. 154 | if (is_win) { 155 | if (is_debug) { 156 | - cflags += [ "/MTd" ] 157 | + cflags += [ "/MDd" ] 158 | } else { 159 | - cflags += [ "/MT" ] 160 | + cflags += [ "/MD" ] 161 | } 162 | defines += [ 163 | "__STD_C", 164 | "_CRT_RAND_S", 165 | "_CRT_SECURE_NO_DEPRECATE", 166 | + "_ITERATOR_DEBUG_LEVEL=0", 167 | "_HAS_EXCEPTIONS=0", 168 | "_SCL_SECURE_NO_DEPRECATE", 169 | ] 170 | ``` 171 | 172 | # Draining the Message Queue 173 | 174 | If you are using Dart_Invoke over Dart_RunLoop, this doesn't give dart any time to drain its message 175 | queue or perform async operations. To get this to work, you need to invoke a private method in the 176 | `dart:isolate` library for now. Here's the code 177 | 178 | ```cpp 179 | Dart_Handle libraryName = Dart_NewStringFromCString("dart:isolate"); 180 | Dart_Handle isolateLib = Dart_LookupLibrary(libraryName); 181 | if (!Dart_IsError(isolateLib)) 182 | { 183 | Dart_Handle invokeName = Dart_NewStringFromCString("_runPendingImmediateCallback"); 184 | Dart_Handle result = Dart_Invoke(isolateLib, invokeName, 0, nullptr); 185 | if (Dart_IsError(result)) 186 | { 187 | // Handle error when drainging the microtask queue 188 | } 189 | result = Dart_HandleMessage(); 190 | if (Dart_IsError(result)) 191 | { 192 | // Handle error when drainging the microtask queue 193 | } 194 | } 195 | ``` 196 | 197 | # Like this? 198 | 199 | Follow me [(@fuzzybinary)](http://twitter.com/fuzzybinary) on Twitter and let me know. I'd love to 200 | hear from you! 201 | -------------------------------------------------------------------------------- /dart/bin/builtin.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | #ifndef RUNTIME_BIN_BUILTIN_H_ 6 | #define RUNTIME_BIN_BUILTIN_H_ 7 | 8 | #include 9 | #include 10 | 11 | #include "include/dart_api.h" 12 | 13 | #include "platform/assert.h" 14 | #include "platform/globals.h" 15 | 16 | namespace dart { 17 | namespace bin { 18 | 19 | #define FUNCTION_NAME(name) Builtin_##name 20 | #define REGISTER_FUNCTION(name, count) {"" #name, FUNCTION_NAME(name), count}, 21 | #define DECLARE_FUNCTION(name, count) \ 22 | extern void FUNCTION_NAME(name)(Dart_NativeArguments args); 23 | 24 | class Builtin { 25 | public: 26 | // Note: Changes to this enum should be accompanied with changes to 27 | // the builtin_libraries_ array in builtin.cc and builtin_nolib.cc. 28 | enum BuiltinLibraryId { 29 | kInvalidLibrary = -1, 30 | kBuiltinLibrary = 0, 31 | kIOLibrary, 32 | kHttpLibrary, 33 | kCLILibrary, 34 | }; 35 | 36 | // Setup native resolver method built in library specified in 'id'. 37 | static void SetNativeResolver(BuiltinLibraryId id); 38 | 39 | // Check if built in library specified in 'id' is already loaded, if not 40 | // load it. 41 | static Dart_Handle LoadAndCheckLibrary(BuiltinLibraryId id); 42 | 43 | private: 44 | // Native method support. 45 | static Dart_NativeFunction NativeLookup(Dart_Handle name, 46 | int argument_count, 47 | bool* auto_setup_scope); 48 | 49 | static const uint8_t* NativeSymbol(Dart_NativeFunction nf); 50 | 51 | static const int num_libs_; 52 | 53 | typedef struct { 54 | const char* url_; 55 | bool has_natives_; 56 | } builtin_lib_props; 57 | static builtin_lib_props builtin_libraries_[]; 58 | 59 | DISALLOW_ALLOCATION(); 60 | DISALLOW_IMPLICIT_CONSTRUCTORS(Builtin); 61 | }; 62 | 63 | } // namespace bin 64 | } // namespace dart 65 | 66 | #endif // RUNTIME_BIN_BUILTIN_H_ 67 | -------------------------------------------------------------------------------- /dart/bin/dfe.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | #ifndef RUNTIME_BIN_DFE_H_ 6 | #define RUNTIME_BIN_DFE_H_ 7 | 8 | #include 9 | 10 | #include "include/dart_api.h" 11 | #include "include/dart_native_api.h" 12 | #include "platform/assert.h" 13 | #include "platform/globals.h" 14 | #include "platform/utils.h" 15 | 16 | namespace dart { 17 | namespace bin { 18 | 19 | class DFE { 20 | public: 21 | DFE(); 22 | ~DFE(); 23 | 24 | // Call Init before Dart_Initialize to prevent races between the 25 | // different isolates. 26 | void Init(); 27 | 28 | char* frontend_filename() const { return frontend_filename_; } 29 | 30 | void set_frontend_filename(const char* name) { 31 | if (frontend_filename_ != nullptr) { 32 | free(frontend_filename_); 33 | } 34 | frontend_filename_ = Utils::StrDup(name); 35 | set_use_dfe(); 36 | } 37 | void set_use_dfe(bool value = true) { use_dfe_ = value; } 38 | bool UseDartFrontend() const { return use_dfe_; } 39 | 40 | void set_use_incremental_compiler(bool value) { 41 | use_incremental_compiler_ = value; 42 | } 43 | bool use_incremental_compiler() const { return use_incremental_compiler_; } 44 | 45 | void set_verbosity(Dart_KernelCompilationVerbosityLevel verbosity) { 46 | verbosity_ = verbosity; 47 | } 48 | Dart_KernelCompilationVerbosityLevel verbosity() const { return verbosity_; } 49 | 50 | // Returns the platform binary file name if the path to 51 | // kernel binaries was set using SetKernelBinaries. 52 | const char* GetPlatformBinaryFilename(); 53 | 54 | // Set the kernel program for the main application if it was specified 55 | // as a dill file. 56 | void set_application_kernel_buffer(uint8_t* buffer, intptr_t size) { 57 | application_kernel_buffer_ = buffer; 58 | application_kernel_buffer_size_ = size; 59 | } 60 | void application_kernel_buffer(const uint8_t** buffer, intptr_t* size) const { 61 | *buffer = application_kernel_buffer_; 62 | *size = application_kernel_buffer_size_; 63 | } 64 | 65 | // Compiles specified script. 66 | // Returns result from compiling the script. 67 | // 68 | // `snapshot` is used by the frontend to determine if compilation 69 | // related information should be printed to console (e.g., null safety mode). 70 | Dart_KernelCompilationResult CompileScript(const char* script_uri, 71 | bool incremental, 72 | const char* package_config, 73 | bool snapshot); 74 | 75 | // Compiles specified script and reads the resulting kernel file. 76 | // If the compilation is successful, returns a valid in memory kernel 77 | // representation of the script, NULL otherwise 78 | // 'error' and 'exit_code' have the error values in case of errors. 79 | // 80 | // `snapshot` is used by the frontend to determine if compilation 81 | // related information should be printed to console (e.g., null safety mode). 82 | void CompileAndReadScript(const char* script_uri, 83 | uint8_t** kernel_buffer, 84 | intptr_t* kernel_buffer_size, 85 | char** error, 86 | int* exit_code, 87 | const char* package_config, 88 | bool snapshot); 89 | 90 | // Reads the script kernel file if specified 'script_uri' is a kernel file. 91 | // Returns an in memory kernel representation of the specified script is a 92 | // valid kernel file, false otherwise. 93 | void ReadScript(const char* script_uri, 94 | uint8_t** kernel_buffer, 95 | intptr_t* kernel_buffer_size) const; 96 | 97 | bool KernelServiceDillAvailable() const; 98 | 99 | // Tries to read [script_uri] as a Kernel IR file. 100 | // Returns `true` if successful and sets [kernel_file] and [kernel_length] 101 | // to be the kernel IR contents. 102 | // The caller is responsible for free()ing [kernel_file] if `true` 103 | // was returned. 104 | static bool TryReadKernelFile(const char* script_uri, 105 | uint8_t** kernel_buffer, 106 | intptr_t* kernel_buffer_size); 107 | 108 | // We distinguish between "intent to use Dart frontend" vs "can actually 109 | // use Dart frontend". The method UseDartFrontend tells us about the 110 | // intent to use DFE. This method tells us if Dart frontend can actually 111 | // be used. 112 | bool CanUseDartFrontend() const; 113 | 114 | void LoadPlatform(const uint8_t** kernel_buffer, 115 | intptr_t* kernel_buffer_size); 116 | void LoadKernelService(const uint8_t** kernel_service_buffer, 117 | intptr_t* kernel_service_buffer_size); 118 | 119 | private: 120 | bool use_dfe_; 121 | bool use_incremental_compiler_; 122 | char* frontend_filename_; 123 | Dart_KernelCompilationVerbosityLevel verbosity_ = 124 | Dart_KernelCompilationVerbosityLevel_All; 125 | 126 | // Kernel binary specified on the cmd line. 127 | uint8_t* application_kernel_buffer_; 128 | intptr_t application_kernel_buffer_size_; 129 | 130 | void InitKernelServiceAndPlatformDills(); 131 | 132 | DISALLOW_COPY_AND_ASSIGN(DFE); 133 | }; 134 | 135 | class PathSanitizer { 136 | public: 137 | explicit PathSanitizer(const char* path); 138 | const char* sanitized_uri() const; 139 | 140 | private: 141 | #if defined(HOST_OS_WINDOWS) 142 | std::unique_ptr sanitized_uri_; 143 | #else 144 | const char* sanitized_uri_; 145 | #endif // defined(HOST_OS_WINDOWS) 146 | 147 | DISALLOW_COPY_AND_ASSIGN(PathSanitizer); 148 | }; 149 | 150 | #if !defined(DART_PRECOMPILED_RUNTIME) 151 | extern DFE dfe; 152 | #endif 153 | 154 | } // namespace bin 155 | } // namespace dart 156 | 157 | #endif // RUNTIME_BIN_DFE_H_ 158 | -------------------------------------------------------------------------------- /dart/bin/eventhandler_win.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | #ifndef RUNTIME_BIN_EVENTHANDLER_WIN_H_ 6 | #define RUNTIME_BIN_EVENTHANDLER_WIN_H_ 7 | 8 | #if !defined(RUNTIME_BIN_EVENTHANDLER_H_) 9 | #error Do not include eventhandler_win.h directly; use eventhandler.h instead. 10 | #endif 11 | 12 | #include 13 | #include 14 | #include 15 | 16 | #include "bin/builtin.h" 17 | #include "bin/reference_counting.h" 18 | #include "bin/thread.h" 19 | 20 | namespace dart { 21 | namespace bin { 22 | 23 | // Forward declarations. 24 | class EventHandlerImplementation; 25 | class Handle; 26 | class FileHandle; 27 | class SocketHandle; 28 | class ClientSocket; 29 | class ListenSocket; 30 | 31 | // An OverlappedBuffer encapsulates the OVERLAPPED structure and the 32 | // associated data buffer. For accept it also contains the pre-created 33 | // socket for the client. 34 | class OverlappedBuffer { 35 | public: 36 | enum Operation { 37 | kAccept, 38 | kRead, 39 | kRecvFrom, 40 | kWrite, 41 | kSendTo, 42 | kDisconnect, 43 | kConnect 44 | }; 45 | 46 | static OverlappedBuffer* AllocateAcceptBuffer(int buffer_size); 47 | static OverlappedBuffer* AllocateReadBuffer(int buffer_size); 48 | static OverlappedBuffer* AllocateRecvFromBuffer(int buffer_size); 49 | static OverlappedBuffer* AllocateWriteBuffer(int buffer_size); 50 | static OverlappedBuffer* AllocateSendToBuffer(int buffer_size); 51 | static OverlappedBuffer* AllocateDisconnectBuffer(); 52 | static OverlappedBuffer* AllocateConnectBuffer(); 53 | static void DisposeBuffer(OverlappedBuffer* buffer); 54 | 55 | // Find the IO buffer from the OVERLAPPED address. 56 | static OverlappedBuffer* GetFromOverlapped(OVERLAPPED* overlapped); 57 | 58 | // Read data from a buffer which has been received. It will read up 59 | // to num_bytes bytes of data returning the actual number of bytes 60 | // read. This will update the index of the next byte in the buffer 61 | // so calling Read several times will keep returning new data from 62 | // the buffer until all data have been read. 63 | int Read(void* buffer, int num_bytes); 64 | 65 | // Write data to a buffer before sending it. Returns the number of bytes 66 | // actually written to the buffer. Calls to Write will always write to 67 | // the buffer from the beginning. 68 | int Write(const void* buffer, int num_bytes); 69 | 70 | // Check the amount of data in a read buffer which has not been read yet. 71 | int GetRemainingLength(); 72 | bool IsEmpty() { return GetRemainingLength() == 0; } 73 | 74 | Operation operation() const { return operation_; } 75 | SOCKET client() const { return client_; } 76 | char* GetBufferStart() { return reinterpret_cast(&buffer_data_); } 77 | int GetBufferSize() const { return buflen_; } 78 | struct sockaddr* from() const { 79 | return from_; 80 | } 81 | socklen_t* from_len_addr() const { return from_len_addr_; } 82 | socklen_t from_len() const { return from_ == NULL ? 0 : *from_len_addr_; } 83 | 84 | // Returns the address of the OVERLAPPED structure with all fields 85 | // initialized to zero. 86 | OVERLAPPED* GetCleanOverlapped() { 87 | memset(&overlapped_, 0, sizeof(overlapped_)); 88 | return &overlapped_; 89 | } 90 | 91 | // Returns a WASBUF structure initialized with the data in this IO buffer. 92 | WSABUF* GetWASBUF() { 93 | wbuf_.buf = GetBufferStart(); 94 | wbuf_.len = GetBufferSize(); 95 | return &wbuf_; 96 | } 97 | 98 | void set_data_length(int data_length) { data_length_ = data_length; } 99 | 100 | private: 101 | OverlappedBuffer(int buffer_size, Operation operation) 102 | : operation_(operation), buflen_(buffer_size) { 103 | memset(GetBufferStart(), 0, GetBufferSize()); 104 | if (operation == kRecvFrom) { 105 | // Reserve part of the buffer for the length of source sockaddr 106 | // and source sockaddr. 107 | const int kAdditionalSize = 108 | sizeof(struct sockaddr_storage) + sizeof(socklen_t); 109 | ASSERT(buflen_ > kAdditionalSize); 110 | buflen_ -= kAdditionalSize; 111 | from_len_addr_ = 112 | reinterpret_cast(GetBufferStart() + GetBufferSize()); 113 | *from_len_addr_ = sizeof(struct sockaddr_storage); 114 | from_ = reinterpret_cast(from_len_addr_ + 1); 115 | } else { 116 | from_len_addr_ = NULL; 117 | from_ = NULL; 118 | } 119 | index_ = 0; 120 | data_length_ = 0; 121 | if (operation_ == kAccept) { 122 | client_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 123 | } 124 | } 125 | 126 | void* operator new(size_t size, int buffer_size) { 127 | return malloc(size + buffer_size); 128 | } 129 | 130 | void operator delete(void* buffer) { free(buffer); } 131 | 132 | // Allocate an overlapped buffer for thse specified amount of data and 133 | // operation. Some operations need additional buffer space, which is 134 | // handled by this method. 135 | static OverlappedBuffer* AllocateBuffer(int buffer_size, Operation operation); 136 | 137 | OVERLAPPED overlapped_; // OVERLAPPED structure for overlapped IO. 138 | SOCKET client_; // Used for AcceptEx client socket. 139 | int buflen_; // Length of the buffer. 140 | Operation operation_; // Type of operation issued. 141 | 142 | int index_; // Index for next read from read buffer. 143 | int data_length_; // Length of the actual data in the buffer. 144 | 145 | WSABUF wbuf_; // Structure for passing buffer to WSA functions. 146 | 147 | // For the recvfrom operation additional storace is allocated for the 148 | // source sockaddr. 149 | socklen_t* from_len_addr_; // Pointer to source sockaddr size storage. 150 | struct sockaddr* from_; // Pointer to source sockaddr storage. 151 | 152 | // Buffer for recv/send/AcceptEx. This must be at the end of the 153 | // object as the object is allocated larger than it's definition 154 | // indicate to extend this array. 155 | uint8_t buffer_data_[1]; 156 | 157 | DISALLOW_COPY_AND_ASSIGN(OverlappedBuffer); 158 | }; 159 | 160 | // Abstract super class for holding information on listen and connected 161 | // sockets. 162 | class Handle : public ReferenceCounted, public DescriptorInfoBase { 163 | public: 164 | enum Type { 165 | kFile, 166 | kStd, 167 | kDirectoryWatch, 168 | kClientSocket, 169 | kListenSocket, 170 | kDatagramSocket 171 | }; 172 | 173 | // Socket interface exposing normal socket operations. 174 | intptr_t Available(); 175 | bool DataReady(); 176 | intptr_t Read(void* buffer, intptr_t num_bytes); 177 | intptr_t RecvFrom(void* buffer, 178 | intptr_t num_bytes, 179 | struct sockaddr* sa, 180 | socklen_t addr_len); 181 | virtual intptr_t Write(const void* buffer, intptr_t num_bytes); 182 | virtual intptr_t SendTo(const void* buffer, 183 | intptr_t num_bytes, 184 | struct sockaddr* sa, 185 | socklen_t sa_len); 186 | 187 | // Internal interface used by the event handler. 188 | virtual bool IssueRead(); 189 | virtual bool IssueRecvFrom(); 190 | virtual bool IssueWrite(); 191 | virtual bool IssueSendTo(struct sockaddr* sa, socklen_t sa_len); 192 | bool HasPendingRead(); 193 | bool HasPendingWrite(); 194 | void ReadComplete(OverlappedBuffer* buffer); 195 | void RecvFromComplete(OverlappedBuffer* buffer); 196 | void WriteComplete(OverlappedBuffer* buffer); 197 | 198 | bool IsClosing() { return (flags_ & (1 << kClosing)) != 0; } 199 | bool IsClosedRead() { return (flags_ & (1 << kCloseRead)) != 0; } 200 | bool IsClosedWrite() { return (flags_ & (1 << kCloseWrite)) != 0; } 201 | bool IsError() { return (flags_ & (1 << kError)) != 0; } 202 | void MarkClosing() { flags_ |= (1 << kClosing); } 203 | void MarkClosedRead() { flags_ |= (1 << kCloseRead); } 204 | void MarkClosedWrite() { flags_ |= (1 << kCloseWrite); } 205 | void MarkError() { flags_ |= (1 << kError); } 206 | 207 | virtual void EnsureInitialized(EventHandlerImplementation* event_handler) = 0; 208 | 209 | HANDLE handle() { return handle_; } 210 | 211 | bool CreateCompletionPort(HANDLE completion_port); 212 | 213 | void Close(); 214 | virtual void DoClose(); 215 | virtual bool IsClosed() = 0; 216 | 217 | bool IsHandleClosed() const { return handle_ == INVALID_HANDLE_VALUE; } 218 | 219 | Type type() { return type_; } 220 | bool is_file() { return type_ == kFile; } 221 | bool is_socket() { 222 | return type_ == kListenSocket || type_ == kClientSocket || 223 | type_ == kDatagramSocket; 224 | } 225 | bool is_listen_socket() { return type_ == kListenSocket; } 226 | bool is_client_socket() { return type_ == kClientSocket; } 227 | bool is_datagram_socket() { return type_ == kDatagramSocket; } 228 | 229 | void MarkDoesNotSupportOverlappedIO() { 230 | flags_ |= (1 << kDoesNotSupportOverlappedIO); 231 | } 232 | bool SupportsOverlappedIO() { 233 | return (flags_ & (1 << kDoesNotSupportOverlappedIO)) == 0; 234 | } 235 | 236 | void ReadSyncCompleteAsync(); 237 | 238 | DWORD last_error() { return last_error_; } 239 | void set_last_error(DWORD last_error) { last_error_ = last_error; } 240 | 241 | void set_completion_port(HANDLE completion_port) { 242 | completion_port_ = completion_port; 243 | } 244 | 245 | void set_event_handler(EventHandlerImplementation* event_handler) { 246 | event_handler_ = event_handler; 247 | } 248 | 249 | protected: 250 | // For access to monitor_; 251 | friend class EventHandlerImplementation; 252 | 253 | enum Flags { 254 | kClosing = 0, 255 | kCloseRead = 1, 256 | kCloseWrite = 2, 257 | kDoesNotSupportOverlappedIO = 3, 258 | kError = 4 259 | }; 260 | 261 | explicit Handle(intptr_t handle); 262 | virtual ~Handle(); 263 | 264 | virtual void HandleIssueError(); 265 | 266 | Monitor monitor_; 267 | Type type_; 268 | HANDLE handle_; 269 | HANDLE completion_port_; 270 | EventHandlerImplementation* event_handler_; 271 | 272 | OverlappedBuffer* data_ready_; // Buffer for data ready to be read. 273 | OverlappedBuffer* pending_read_; // Buffer for pending read. 274 | OverlappedBuffer* pending_write_; // Buffer for pending write 275 | 276 | DWORD last_error_; 277 | 278 | ThreadId read_thread_id_; 279 | HANDLE read_thread_handle_; 280 | bool read_thread_starting_; 281 | bool read_thread_finished_; 282 | 283 | private: 284 | void WaitForReadThreadStarted(); 285 | void NotifyReadThreadStarted(); 286 | void WaitForReadThreadFinished(); 287 | void NotifyReadThreadFinished(); 288 | 289 | int flags_; 290 | 291 | friend class ReferenceCounted; 292 | DISALLOW_COPY_AND_ASSIGN(Handle); 293 | }; 294 | 295 | class FileHandle : public DescriptorInfoSingleMixin { 296 | public: 297 | explicit FileHandle(HANDLE handle) 298 | : DescriptorInfoSingleMixin(reinterpret_cast(handle), true) { 299 | type_ = kFile; 300 | } 301 | 302 | virtual void EnsureInitialized(EventHandlerImplementation* event_handler); 303 | virtual bool IsClosed(); 304 | 305 | private: 306 | DISALLOW_COPY_AND_ASSIGN(FileHandle); 307 | }; 308 | 309 | class StdHandle : public FileHandle { 310 | public: 311 | static StdHandle* Stdin(HANDLE handle); 312 | 313 | virtual void DoClose(); 314 | virtual intptr_t Write(const void* buffer, intptr_t num_bytes); 315 | 316 | void WriteSyncCompleteAsync(); 317 | void RunWriteLoop(); 318 | 319 | #if defined(DEBUG) 320 | static StdHandle* StdinPtr() { return stdin_; } 321 | #endif 322 | 323 | private: 324 | static Mutex* stdin_mutex_; 325 | static StdHandle* stdin_; 326 | 327 | explicit StdHandle(HANDLE handle) 328 | : FileHandle(handle), 329 | thread_id_(Thread::kInvalidThreadId), 330 | thread_handle_(NULL), 331 | thread_wrote_(0), 332 | write_thread_exists_(false), 333 | write_thread_running_(false) { 334 | type_ = kStd; 335 | } 336 | 337 | ThreadId thread_id_; 338 | HANDLE thread_handle_; 339 | intptr_t thread_wrote_; 340 | bool write_thread_exists_; 341 | bool write_thread_running_; 342 | 343 | DISALLOW_COPY_AND_ASSIGN(StdHandle); 344 | }; 345 | 346 | class DirectoryWatchHandle : public DescriptorInfoSingleMixin { 347 | public: 348 | DirectoryWatchHandle(HANDLE handle, int events, bool recursive) 349 | : DescriptorInfoSingleMixin(reinterpret_cast(handle), true), 350 | events_(events), 351 | recursive_(recursive) { 352 | type_ = kDirectoryWatch; 353 | } 354 | 355 | virtual void EnsureInitialized(EventHandlerImplementation* event_handler); 356 | virtual bool IsClosed(); 357 | 358 | virtual bool IssueRead(); 359 | 360 | void Stop(); 361 | 362 | private: 363 | int events_; 364 | bool recursive_; 365 | 366 | DISALLOW_COPY_AND_ASSIGN(DirectoryWatchHandle); 367 | }; 368 | 369 | class SocketHandle : public Handle { 370 | public: 371 | SOCKET socket() const { return socket_; } 372 | 373 | protected: 374 | explicit SocketHandle(intptr_t s) : Handle(s), socket_(s) {} 375 | 376 | virtual void HandleIssueError(); 377 | 378 | private: 379 | const SOCKET socket_; 380 | 381 | DISALLOW_COPY_AND_ASSIGN(SocketHandle); 382 | }; 383 | 384 | // Information on listen sockets. 385 | class ListenSocket : public DescriptorInfoMultipleMixin { 386 | public: 387 | explicit ListenSocket(intptr_t s) 388 | : DescriptorInfoMultipleMixin(s, true), 389 | AcceptEx_(NULL), 390 | pending_accept_count_(0), 391 | accepted_head_(NULL), 392 | accepted_tail_(NULL), 393 | accepted_count_(0) { 394 | type_ = kListenSocket; 395 | } 396 | virtual ~ListenSocket() { 397 | ASSERT(!HasPendingAccept()); 398 | ASSERT(accepted_head_ == NULL); 399 | ASSERT(accepted_tail_ == NULL); 400 | } 401 | 402 | // Socket interface exposing normal socket operations. 403 | ClientSocket* Accept(); 404 | bool CanAccept(); 405 | 406 | // Internal interface used by the event handler. 407 | bool HasPendingAccept() { return pending_accept_count_ > 0; } 408 | bool IssueAccept(); 409 | void AcceptComplete(OverlappedBuffer* buffer, HANDLE completion_port); 410 | 411 | virtual void EnsureInitialized(EventHandlerImplementation* event_handler); 412 | virtual void DoClose(); 413 | virtual bool IsClosed(); 414 | 415 | int pending_accept_count() { return pending_accept_count_; } 416 | 417 | int accepted_count() { return accepted_count_; } 418 | 419 | private: 420 | bool LoadAcceptEx(); 421 | 422 | LPFN_ACCEPTEX AcceptEx_; 423 | 424 | // The number of asynchronous `IssueAccept` operations which haven't completed 425 | // yet. 426 | int pending_accept_count_; 427 | 428 | // Linked list of accepted connections provided by completion code. Ready to 429 | // be handed over through accept. 430 | ClientSocket* accepted_head_; 431 | ClientSocket* accepted_tail_; 432 | 433 | // The number of accepted connections which are waiting to be removed from 434 | // this queue and processed by dart isolates. 435 | int accepted_count_; 436 | 437 | DISALLOW_COPY_AND_ASSIGN(ListenSocket); 438 | }; 439 | 440 | // Information on connected sockets. 441 | class ClientSocket : public DescriptorInfoSingleMixin { 442 | public: 443 | explicit ClientSocket(intptr_t s) 444 | : DescriptorInfoSingleMixin(s, true), 445 | DisconnectEx_(NULL), 446 | next_(NULL), 447 | connected_(false), 448 | closed_(false) { 449 | LoadDisconnectEx(); 450 | type_ = kClientSocket; 451 | } 452 | 453 | virtual ~ClientSocket() { 454 | // Don't delete this object until all pending requests have been handled. 455 | ASSERT(!HasPendingRead()); 456 | ASSERT(!HasPendingWrite()); 457 | ASSERT(next_ == NULL); 458 | ASSERT(closed_ == true); 459 | } 460 | 461 | void Shutdown(int how); 462 | 463 | // Internal interface used by the event handler. 464 | virtual bool IssueRead(); 465 | virtual bool IssueWrite(); 466 | void IssueDisconnect(); 467 | void DisconnectComplete(OverlappedBuffer* buffer); 468 | 469 | void ConnectComplete(OverlappedBuffer* buffer); 470 | 471 | virtual void EnsureInitialized(EventHandlerImplementation* event_handler); 472 | virtual void DoClose(); 473 | virtual bool IsClosed(); 474 | 475 | ClientSocket* next() { return next_; } 476 | void set_next(ClientSocket* next) { next_ = next; } 477 | 478 | void mark_connected() { connected_ = true; } 479 | bool is_connected() const { return connected_; } 480 | 481 | void mark_closed() { closed_ = true; } 482 | 483 | #if defined(DEBUG) 484 | static intptr_t disconnecting() { return disconnecting_; } 485 | #endif 486 | 487 | private: 488 | bool LoadDisconnectEx(); 489 | 490 | LPFN_DISCONNECTEX DisconnectEx_; 491 | ClientSocket* next_; 492 | bool connected_; 493 | bool closed_; 494 | 495 | #if defined(DEBUG) 496 | static intptr_t disconnecting_; 497 | #endif 498 | 499 | DISALLOW_COPY_AND_ASSIGN(ClientSocket); 500 | }; 501 | 502 | class DatagramSocket : public DescriptorInfoSingleMixin { 503 | public: 504 | explicit DatagramSocket(intptr_t s) : DescriptorInfoSingleMixin(s, true) { 505 | type_ = kDatagramSocket; 506 | } 507 | 508 | virtual ~DatagramSocket() { 509 | // Don't delete this object until all pending requests have been handled. 510 | ASSERT(!HasPendingRead()); 511 | ASSERT(!HasPendingWrite()); 512 | } 513 | 514 | // Internal interface used by the event handler. 515 | virtual bool IssueRecvFrom(); 516 | virtual bool IssueSendTo(sockaddr* sa, socklen_t sa_len); 517 | 518 | virtual void EnsureInitialized(EventHandlerImplementation* event_handler); 519 | virtual void DoClose(); 520 | virtual bool IsClosed(); 521 | 522 | private: 523 | DISALLOW_COPY_AND_ASSIGN(DatagramSocket); 524 | }; 525 | 526 | // Event handler. 527 | class EventHandlerImplementation { 528 | public: 529 | EventHandlerImplementation(); 530 | virtual ~EventHandlerImplementation(); 531 | 532 | void SendData(intptr_t id, Dart_Port dart_port, int64_t data); 533 | void Start(EventHandler* handler); 534 | void Shutdown(); 535 | 536 | static void EventHandlerEntry(uword args); 537 | 538 | int64_t GetTimeout(); 539 | void HandleInterrupt(InterruptMessage* msg); 540 | void HandleTimeout(); 541 | void HandleAccept(ListenSocket* listen_socket, OverlappedBuffer* buffer); 542 | void TryDispatchingPendingAccepts(ListenSocket* listen_socket); 543 | void HandleRead(Handle* handle, int bytes, OverlappedBuffer* buffer); 544 | void HandleRecvFrom(Handle* handle, int bytes, OverlappedBuffer* buffer); 545 | void HandleWrite(Handle* handle, int bytes, OverlappedBuffer* buffer); 546 | void HandleDisconnect(ClientSocket* client_socket, 547 | int bytes, 548 | OverlappedBuffer* buffer); 549 | void HandleConnect(ClientSocket* client_socket, 550 | int bytes, 551 | OverlappedBuffer* buffer); 552 | void HandleIOCompletion(DWORD bytes, ULONG_PTR key, OVERLAPPED* overlapped); 553 | 554 | void HandleCompletionOrInterrupt(BOOL ok, 555 | DWORD bytes, 556 | ULONG_PTR key, 557 | OVERLAPPED* overlapped); 558 | 559 | HANDLE completion_port() { return completion_port_; } 560 | 561 | private: 562 | Monitor startup_monitor_; 563 | ThreadId handler_thread_id_; 564 | HANDLE handler_thread_handle_; 565 | 566 | TimeoutQueue timeout_queue_; // Time for next timeout. 567 | bool shutdown_; 568 | HANDLE completion_port_; 569 | 570 | DISALLOW_COPY_AND_ASSIGN(EventHandlerImplementation); 571 | }; 572 | 573 | } // namespace bin 574 | } // namespace dart 575 | 576 | #endif // RUNTIME_BIN_EVENTHANDLER_WIN_H_ 577 | -------------------------------------------------------------------------------- /dart/bin/gzip.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | #ifndef RUNTIME_BIN_GZIP_H_ 6 | #define RUNTIME_BIN_GZIP_H_ 7 | 8 | #include "platform/globals.h" 9 | 10 | namespace dart { 11 | namespace bin { 12 | 13 | // |input| is assumed to be a gzipped stream. 14 | // This function allocates the output buffer in the C heap and the caller 15 | // is responsible for freeing it. 16 | void Decompress(const uint8_t* input, 17 | intptr_t input_len, 18 | uint8_t** output, 19 | intptr_t* output_length); 20 | 21 | } // namespace bin 22 | } // namespace dart 23 | 24 | #endif // RUNTIME_BIN_GZIP_H_ 25 | -------------------------------------------------------------------------------- /dart/bin/isolate_data.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | #ifndef RUNTIME_BIN_ISOLATE_DATA_H_ 6 | #define RUNTIME_BIN_ISOLATE_DATA_H_ 7 | 8 | #include 9 | #include 10 | 11 | #include "include/dart_api.h" 12 | #include "platform/assert.h" 13 | #include "platform/globals.h" 14 | #include "platform/growable_array.h" 15 | #include "platform/utils.h" 16 | 17 | namespace dart { 18 | 19 | // Forward declaration. 20 | template 21 | class MallocGrowableArray; 22 | 23 | } // namespace dart 24 | 25 | namespace dart { 26 | namespace bin { 27 | 28 | // Forward declaration. 29 | class AppSnapshot; 30 | class EventHandler; 31 | class Loader; 32 | 33 | // Data associated with every isolate group in the standalone VM 34 | // embedding. This is used to free external resources for each isolate 35 | // group when the isolate group shuts down. 36 | class IsolateGroupData { 37 | public: 38 | IsolateGroupData(const char* url, 39 | const char* packages_file, 40 | AppSnapshot* app_snapshot, 41 | bool isolate_run_app_snapshot); 42 | ~IsolateGroupData(); 43 | 44 | char* script_url; 45 | 46 | const std::shared_ptr& kernel_buffer() const { 47 | return kernel_buffer_; 48 | } 49 | 50 | intptr_t kernel_buffer_size() const { return kernel_buffer_size_; } 51 | 52 | // Associate the given kernel buffer with this IsolateGroupData without 53 | // giving it ownership of the buffer. 54 | void SetKernelBufferUnowned(uint8_t* buffer, intptr_t size) { 55 | ASSERT(kernel_buffer_.get() == NULL); 56 | kernel_buffer_ = std::shared_ptr(buffer, FreeUnownedKernelBuffer); 57 | kernel_buffer_size_ = size; 58 | } 59 | 60 | // Associate the given kernel buffer with this IsolateGroupData and give it 61 | // ownership of the buffer. This IsolateGroupData is the first one to own the 62 | // buffer. 63 | void SetKernelBufferNewlyOwned(uint8_t* buffer, intptr_t size) { 64 | ASSERT(kernel_buffer_.get() == NULL); 65 | kernel_buffer_ = std::shared_ptr(buffer, free); 66 | kernel_buffer_size_ = size; 67 | } 68 | 69 | // Associate the given kernel buffer with this IsolateGroupData and give it 70 | // ownership of the buffer. The buffer is already owned by another 71 | // IsolateGroupData. 72 | void SetKernelBufferAlreadyOwned(std::shared_ptr buffer, 73 | intptr_t size) { 74 | ASSERT(kernel_buffer_.get() == NULL); 75 | kernel_buffer_ = std::move(buffer); 76 | kernel_buffer_size_ = size; 77 | } 78 | 79 | const char* resolved_packages_config() const { 80 | return resolved_packages_config_; 81 | } 82 | 83 | void set_resolved_packages_config(const char* packages_config) { 84 | if (resolved_packages_config_ != NULL) { 85 | free(resolved_packages_config_); 86 | resolved_packages_config_ = NULL; 87 | } 88 | resolved_packages_config_ = Utils::StrDup(packages_config); 89 | } 90 | 91 | bool RunFromAppSnapshot() const { 92 | // If the main isolate is using an app snapshot the [app_snapshot_] pointer 93 | // will be still nullptr (see main.cc:CreateIsolateGroupAndSetupHelper) 94 | // 95 | // Because of thus we have an additional boolean signaling whether the 96 | // isolate was started from an app snapshot. 97 | return app_snapshot_ != nullptr || isolate_run_app_snapshot_; 98 | } 99 | 100 | void AddLoadingUnit(AppSnapshot* loading_unit) { 101 | loading_units_.Add(loading_unit); 102 | } 103 | 104 | private: 105 | friend class IsolateData; // For packages_file_ 106 | 107 | std::unique_ptr app_snapshot_; 108 | MallocGrowableArray loading_units_; 109 | char* resolved_packages_config_; 110 | std::shared_ptr kernel_buffer_; 111 | intptr_t kernel_buffer_size_; 112 | char* packages_file_ = nullptr; 113 | bool isolate_run_app_snapshot_; 114 | 115 | static void FreeUnownedKernelBuffer(uint8_t*) {} 116 | 117 | DISALLOW_COPY_AND_ASSIGN(IsolateGroupData); 118 | }; 119 | 120 | // Data associated with every isolate in the standalone VM 121 | // embedding. This is used to free external resources for each isolate 122 | // when the isolate shuts down. 123 | class IsolateData { 124 | public: 125 | explicit IsolateData(IsolateGroupData* isolate_group_data); 126 | ~IsolateData(); 127 | 128 | IsolateGroupData* isolate_group_data() const { return isolate_group_data_; } 129 | 130 | void UpdatePackagesFile(const char* packages_file) { 131 | if (packages_file != nullptr) { 132 | free(packages_file_); 133 | packages_file_ = nullptr; 134 | } 135 | packages_file_ = Utils::StrDup(packages_file); 136 | } 137 | 138 | // While loading a loader is associated with the isolate. 139 | bool HasLoader() const { return loader_ != NULL; } 140 | Loader* loader() const { 141 | ASSERT(loader_ != NULL); 142 | return loader_; 143 | } 144 | void set_loader(Loader* loader) { 145 | ASSERT((loader_ == NULL) || (loader == NULL)); 146 | loader_ = loader; 147 | } 148 | 149 | const char* packages_file() const { return packages_file_; } 150 | 151 | private: 152 | IsolateGroupData* isolate_group_data_; 153 | Loader* loader_; 154 | char* packages_file_; 155 | 156 | DISALLOW_COPY_AND_ASSIGN(IsolateData); 157 | }; 158 | 159 | } // namespace bin 160 | } // namespace dart 161 | 162 | #endif // RUNTIME_BIN_ISOLATE_DATA_H_ 163 | -------------------------------------------------------------------------------- /dart/bin/platform.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | #ifndef RUNTIME_BIN_PLATFORM_H_ 6 | #define RUNTIME_BIN_PLATFORM_H_ 7 | 8 | #include "bin/builtin.h" 9 | #include "platform/globals.h" 10 | #include "platform/utils.h" 11 | 12 | #if defined(HOST_OS_MACOS) 13 | #include "bin/platform_macos.h" 14 | #endif // defined(HOST_OS_MACOS) 15 | 16 | namespace dart { 17 | namespace bin { 18 | 19 | class Platform { 20 | public: 21 | // Perform platform specific initialization. 22 | static bool Initialize(); 23 | 24 | // Returns the number of processors on the machine. 25 | static int NumberOfProcessors(); 26 | 27 | // Returns a string representing the operating system ("linux", 28 | // "macos", "windows", or "android"). The returned string should not be 29 | // deallocated by the caller. 30 | static const char* OperatingSystem(); 31 | 32 | // Returns a string representing the version of the operating system. The 33 | // format of the string is determined by the platform. The returned string 34 | // should not be deallocated by the caller. 35 | static const char* OperatingSystemVersion(); 36 | 37 | // Returns the architecture name of the processor the VM is running on 38 | // (ia32, x64, arm, or arm64). 39 | static const char* HostArchitecture() { 40 | #if defined(HOST_ARCH_ARM) 41 | return "arm"; 42 | #elif defined(HOST_ARCH_ARM64) 43 | return "arm64"; 44 | #elif defined(HOST_ARCH_IA32) 45 | return "ia32"; 46 | #elif defined(HOST_ARCH_X64) 47 | return "x64"; 48 | #else 49 | #error Architecture detection failed. 50 | #endif 51 | } 52 | 53 | static const char* LibraryPrefix(); 54 | 55 | // Returns a string representing the operating system's shared library 56 | // extension (e.g. 'so', 'dll', ...). The returned string should not be 57 | // deallocated by the caller. 58 | static const char* LibraryExtension(); 59 | 60 | // Extracts the local hostname. 61 | static bool LocalHostname(char* buffer, intptr_t buffer_length); 62 | 63 | static const char* LocaleName(); 64 | 65 | // Extracts the environment variables for the current process. The array of 66 | // strings is Dart_ScopeAllocated. The number of elements in the array is 67 | // returned in the count argument. 68 | static char** Environment(intptr_t* count); 69 | 70 | static const char* ResolveExecutablePath(); 71 | 72 | // This has the same effect as calling ResolveExecutablePath except that 73 | // Dart_ScopeAllocate is not called and that the result goes into the given 74 | // parameters. 75 | // WARNING: On Fuchsia it returns -1, i.e. doesn't work. 76 | // Note that `result` should be pre-allocated with size `result_size`. 77 | // The return-value is the length read into `result` or -1 on failure. 78 | static intptr_t ResolveExecutablePathInto(char* result, size_t result_size); 79 | 80 | // Stores the executable name. 81 | static void SetExecutableName(const char* executable_name) { 82 | executable_name_ = executable_name; 83 | } 84 | static const char* GetExecutableName(); 85 | static const char* GetResolvedExecutableName() { 86 | if (resolved_executable_name_ == NULL) { 87 | // Try to resolve the executable path using platform specific APIs. 88 | const char* resolved_name = Platform::ResolveExecutablePath(); 89 | if (resolved_name != NULL) { 90 | resolved_executable_name_ = Utils::StrDup(resolved_name); 91 | } 92 | } 93 | return resolved_executable_name_; 94 | } 95 | 96 | // Stores and gets the flags passed to the executable. 97 | static void SetExecutableArguments(int script_index, char** argv) { 98 | script_index_ = script_index; 99 | argv_ = argv; 100 | } 101 | static int GetScriptIndex() { return script_index_; } 102 | static char** GetArgv() { return argv_; } 103 | 104 | DART_NORETURN static void Exit(int exit_code); 105 | 106 | static void SetCoreDumpResourceLimit(int value); 107 | 108 | private: 109 | // The path to the executable. 110 | static const char* executable_name_; 111 | // The path to the resolved executable. 112 | static char* resolved_executable_name_; 113 | 114 | static int script_index_; 115 | static char** argv_; // VM flags are argv_[1 ... script_index_ - 1] 116 | 117 | DISALLOW_ALLOCATION(); 118 | DISALLOW_IMPLICIT_CONSTRUCTORS(Platform); 119 | }; 120 | 121 | } // namespace bin 122 | } // namespace dart 123 | 124 | #endif // RUNTIME_BIN_PLATFORM_H_ 125 | -------------------------------------------------------------------------------- /dart/bin/reference_counting.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | #ifndef RUNTIME_BIN_REFERENCE_COUNTING_H_ 6 | #define RUNTIME_BIN_REFERENCE_COUNTING_H_ 7 | 8 | #include 9 | 10 | namespace dart { 11 | namespace bin { 12 | 13 | // Forward declaration. 14 | template 15 | class RefCntReleaseScope; 16 | 17 | // Inherit from this class where instances of the derived class should be 18 | // reference counted. Reference counts on instances are incremented and 19 | // decremented explicitly with calls to Retain() and Release(). E.g.: 20 | // 21 | // class Foo : public ReferenceCounted { 22 | // public: 23 | // Foo() : ReferenceCounted() {} 24 | // ... 25 | // }; 26 | // 27 | // void DoStuffWithAFoo() { 28 | // Foo* foo = new Foo(); // Reference count starts at 1, so no explicit 29 | // // call to Retain is needed after allocation. 30 | // ... 31 | // foo->Release(); 32 | // } 33 | template 34 | class ReferenceCounted { 35 | public: 36 | ReferenceCounted() : ref_count_(1) { 37 | #if defined(DEBUG) 38 | instances_.fetch_add(1u, std::memory_order_relaxed); 39 | #endif // defined(DEBUG) 40 | } 41 | 42 | virtual ~ReferenceCounted() { 43 | ASSERT(ref_count_ == 0); 44 | #if defined(DEBUG) 45 | instances_.fetch_sub(1u, std::memory_order_relaxed); 46 | #endif // defined(DEBUG) 47 | } 48 | 49 | void Retain() { 50 | intptr_t old = ref_count_.fetch_add(1u, std::memory_order_relaxed); 51 | ASSERT(old > 0); 52 | } 53 | 54 | void Release() { 55 | intptr_t old = ref_count_.fetch_sub(1u, std::memory_order_acq_rel); 56 | ASSERT(old > 0); 57 | if (old == 1) { 58 | delete static_cast(this); 59 | } 60 | } 61 | 62 | #if defined(DEBUG) 63 | static intptr_t instances() { 64 | return instances_.load(std::memory_order_relaxed); 65 | } 66 | #endif // defined(DEBUG) 67 | 68 | private: 69 | #if defined(DEBUG) 70 | static std::atomic instances_; 71 | #endif // defined(DEBUG) 72 | 73 | std::atomic ref_count_; 74 | 75 | // These are used only in the ASSERT below in RefCntReleaseScope. 76 | intptr_t ref_count() const { 77 | return ref_count_.load(std::memory_order_relaxed); 78 | } 79 | friend class RefCntReleaseScope; 80 | DISALLOW_COPY_AND_ASSIGN(ReferenceCounted); 81 | }; 82 | 83 | #if defined(DEBUG) 84 | template 85 | std::atomic ReferenceCounted::instances_ = {0}; 86 | #endif 87 | 88 | // Creates a scope at the end of which a reference counted object is 89 | // Released. This is useful for reference counted objects received by the IO 90 | // Service, which have already been Retained E.g.: 91 | // 92 | // CObject* Foo::FooRequest(const CObjectArray& request) { 93 | // Foo* foo = CObjectToFoo(request[0]); 94 | // RefCntReleaseScope rs(foo); 95 | // ... 96 | // } 97 | template 98 | class RefCntReleaseScope { 99 | public: 100 | explicit RefCntReleaseScope(ReferenceCounted* t) : target_(t) { 101 | ASSERT(target_ != NULL); 102 | ASSERT(target_->ref_count() > 0); 103 | } 104 | ~RefCntReleaseScope() { target_->Release(); } 105 | 106 | private: 107 | ReferenceCounted* target_; 108 | 109 | DISALLOW_ALLOCATION(); 110 | DISALLOW_COPY_AND_ASSIGN(RefCntReleaseScope); 111 | }; 112 | 113 | // Instances of RetainedPointer manage Retaining and Releasing reference counted 114 | // objects. There are two ways to use it. First, it can be used as a field in 115 | // a class, e.g.: 116 | // 117 | // class Foo { 118 | // private: 119 | // RetainedPointer bar_; 120 | // public: 121 | // explicit Foo(Bar* b) : bar_(b) {} 122 | // } 123 | // 124 | // In this case, b will be Retained in Foo's constructor, and Released 125 | // automatically during Foo's destructor. 126 | // 127 | // RetainedPointer can also be used as a scope, as with RefCntReleaseScope, 128 | // with the difference that entering the scope also Retains the pointer, e.g.: 129 | // 130 | // void RetainAndDoStuffWithFoo(Foo* foo) { 131 | // RetainedPointer retained(foo); 132 | // .. 133 | // } 134 | // 135 | // This Retains foo on entry and Releases foo at every exit from the scope. 136 | // 137 | // The underlying pointer can be accessed with the get() and set() methods. 138 | // Overwriting a non-NULL pointer with set causes that pointer to be Released. 139 | template 140 | class RetainedPointer { 141 | public: 142 | RetainedPointer() : target_(NULL) {} 143 | 144 | explicit RetainedPointer(ReferenceCounted* t) : target_(t) { 145 | if (target_ != NULL) { 146 | target_->Retain(); 147 | } 148 | } 149 | 150 | ~RetainedPointer() { 151 | if (target_ != NULL) { 152 | target_->Release(); 153 | } 154 | } 155 | 156 | void set(ReferenceCounted* t) { 157 | if (target_ != NULL) { 158 | target_->Release(); 159 | } 160 | target_ = t; 161 | if (target_ != NULL) { 162 | target_->Retain(); 163 | } 164 | } 165 | 166 | Target* get() const { return static_cast(target_); } 167 | 168 | private: 169 | ReferenceCounted* target_; 170 | 171 | DISALLOW_ALLOCATION(); 172 | DISALLOW_COPY_AND_ASSIGN(RetainedPointer); 173 | }; 174 | 175 | } // namespace bin 176 | } // namespace dart 177 | 178 | #endif // RUNTIME_BIN_REFERENCE_COUNTING_H_ 179 | -------------------------------------------------------------------------------- /dart/bin/thread.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | #ifndef RUNTIME_BIN_THREAD_H_ 6 | #define RUNTIME_BIN_THREAD_H_ 7 | 8 | #include "platform/globals.h" 9 | 10 | namespace dart { 11 | namespace bin { 12 | class Thread; 13 | class Mutex; 14 | class Monitor; 15 | } // namespace bin 16 | } // namespace dart 17 | 18 | // Declare the OS-specific types ahead of defining the generic classes. 19 | #if defined(HOST_OS_ANDROID) 20 | #include "bin/thread_android.h" 21 | #elif defined(HOST_OS_FUCHSIA) 22 | #include "bin/thread_fuchsia.h" 23 | #elif defined(HOST_OS_LINUX) 24 | #include "bin/thread_linux.h" 25 | #elif defined(HOST_OS_MACOS) 26 | #include "bin/thread_macos.h" 27 | #elif defined(HOST_OS_WINDOWS) 28 | #include "bin/thread_win.h" 29 | #else 30 | #error Unknown target os. 31 | #endif 32 | 33 | namespace dart { 34 | namespace bin { 35 | 36 | class Thread { 37 | public: 38 | static const ThreadLocalKey kUnsetThreadLocalKey; 39 | static const ThreadId kInvalidThreadId; 40 | 41 | typedef void (*ThreadStartFunction)(uword parameter); 42 | 43 | // Start a thread running the specified function. Returns 0 if the 44 | // thread started successfuly and a system specific error code if 45 | // the thread failed to start. 46 | static int Start(const char* name, 47 | ThreadStartFunction function, 48 | uword parameters); 49 | 50 | static ThreadLocalKey CreateThreadLocal(); 51 | static void DeleteThreadLocal(ThreadLocalKey key); 52 | static uword GetThreadLocal(ThreadLocalKey key) { 53 | return ThreadInlineImpl::GetThreadLocal(key); 54 | } 55 | static void SetThreadLocal(ThreadLocalKey key, uword value); 56 | static intptr_t GetMaxStackSize(); 57 | static ThreadId GetCurrentThreadId(); 58 | static intptr_t ThreadIdToIntPtr(ThreadId id); 59 | static bool Compare(ThreadId a, ThreadId b); 60 | 61 | static void InitOnce(); 62 | 63 | private: 64 | DISALLOW_ALLOCATION(); 65 | DISALLOW_IMPLICIT_CONSTRUCTORS(Thread); 66 | }; 67 | 68 | class Mutex { 69 | public: 70 | Mutex(); 71 | ~Mutex(); 72 | 73 | void Lock(); 74 | bool TryLock(); 75 | void Unlock(); 76 | 77 | private: 78 | MutexData data_; 79 | 80 | DISALLOW_COPY_AND_ASSIGN(Mutex); 81 | }; 82 | 83 | class Monitor { 84 | public: 85 | enum WaitResult { kNotified, kTimedOut }; 86 | 87 | static const int64_t kNoTimeout = 0; 88 | 89 | Monitor(); 90 | ~Monitor(); 91 | 92 | void Enter(); 93 | void Exit(); 94 | 95 | // Wait for notification or timeout. 96 | WaitResult Wait(int64_t millis); 97 | WaitResult WaitMicros(int64_t micros); 98 | 99 | // Notify waiting threads. 100 | void Notify(); 101 | void NotifyAll(); 102 | 103 | private: 104 | MonitorData data_; // OS-specific data. 105 | 106 | DISALLOW_COPY_AND_ASSIGN(Monitor); 107 | }; 108 | 109 | } // namespace bin 110 | } // namespace dart 111 | 112 | #endif // RUNTIME_BIN_THREAD_H_ 113 | -------------------------------------------------------------------------------- /dart/bin/thread_win.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | #ifndef RUNTIME_BIN_THREAD_WIN_H_ 6 | #define RUNTIME_BIN_THREAD_WIN_H_ 7 | 8 | #if !defined(RUNTIME_BIN_THREAD_H_) 9 | #error Do not include thread_win.h directly; use thread.h instead. 10 | #endif 11 | 12 | #include "platform/assert.h" 13 | #include "platform/globals.h" 14 | 15 | namespace dart { 16 | namespace bin { 17 | 18 | typedef DWORD ThreadLocalKey; 19 | typedef DWORD ThreadId; 20 | 21 | class ThreadInlineImpl { 22 | private: 23 | ThreadInlineImpl() {} 24 | ~ThreadInlineImpl() {} 25 | 26 | static uword GetThreadLocal(ThreadLocalKey key) { 27 | static ThreadLocalKey kUnsetThreadLocalKey = TLS_OUT_OF_INDEXES; 28 | ASSERT(key != kUnsetThreadLocalKey); 29 | return reinterpret_cast(TlsGetValue(key)); 30 | } 31 | 32 | friend class Thread; 33 | friend unsigned int __stdcall ThreadEntry(void* data_ptr); 34 | 35 | DISALLOW_ALLOCATION(); 36 | DISALLOW_COPY_AND_ASSIGN(ThreadInlineImpl); 37 | }; 38 | 39 | class MutexData { 40 | private: 41 | MutexData() {} 42 | ~MutexData() {} 43 | 44 | SRWLOCK lock_; 45 | 46 | friend class Mutex; 47 | 48 | DISALLOW_ALLOCATION(); 49 | DISALLOW_COPY_AND_ASSIGN(MutexData); 50 | }; 51 | 52 | class MonitorData { 53 | private: 54 | MonitorData() {} 55 | ~MonitorData() {} 56 | 57 | CRITICAL_SECTION cs_; 58 | CONDITION_VARIABLE cond_; 59 | 60 | friend class Monitor; 61 | 62 | DISALLOW_ALLOCATION(); 63 | DISALLOW_COPY_AND_ASSIGN(MonitorData); 64 | }; 65 | 66 | } // namespace bin 67 | } // namespace dart 68 | 69 | #endif // RUNTIME_BIN_THREAD_WIN_H_ 70 | -------------------------------------------------------------------------------- /dart/bin/utils.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | #ifndef RUNTIME_BIN_UTILS_H_ 6 | #define RUNTIME_BIN_UTILS_H_ 7 | 8 | #include 9 | #include 10 | 11 | #include "include/dart_api.h" 12 | #include "platform/globals.h" 13 | #include "platform/utils.h" 14 | 15 | namespace dart { 16 | namespace bin { 17 | 18 | class OSError { 19 | public: 20 | enum SubSystem { kSystem, kGetAddressInfo, kBoringSSL, kUnknown = -1 }; 21 | 22 | OSError(); 23 | OSError(int code, const char* message, SubSystem sub_system) { 24 | sub_system_ = sub_system; 25 | code_ = code; 26 | message_ = NULL; // SetMessage will free existing message. 27 | SetMessage(message); 28 | } 29 | virtual ~OSError() { free(message_); } 30 | 31 | // Reload this OSError with the current OS error, discarding the previous. 32 | void Reload(); 33 | 34 | SubSystem sub_system() { return sub_system_; } 35 | int code() { return code_; } 36 | char* message() { return message_; } 37 | void SetCodeAndMessage(SubSystem sub_system, int code); 38 | 39 | private: 40 | void set_sub_system(SubSystem sub_system) { sub_system_ = sub_system; } 41 | void set_code(int code) { code_ = code; } 42 | void SetMessage(const char* message) { 43 | free(message_); 44 | if (message == NULL) { 45 | message_ = NULL; 46 | } else { 47 | message_ = Utils::StrDup(message); 48 | } 49 | } 50 | 51 | SubSystem sub_system_; 52 | int code_; 53 | char* message_; 54 | 55 | DISALLOW_COPY_AND_ASSIGN(OSError); 56 | }; 57 | 58 | class StringUtils { 59 | public: 60 | // The following methods convert the argument if needed. The 61 | // conversions are only needed on Windows. If the methods returns a 62 | // pointer that is different from the input pointer, the returned 63 | // pointer is allocated with malloc and should be freed using free. 64 | // 65 | // If the len argument is passed then that number of characters are 66 | // converted. If len is -1, conversion will stop at the first NUL 67 | // character. If result_len is not NUL, it is used to set the number 68 | // of characters in the result. 69 | // 70 | // These conversion functions are only implemented on Windows as the 71 | // Dart code only hit this path on Windows. 72 | static const char* ConsoleStringToUtf8(const char* str, 73 | intptr_t len = -1, 74 | intptr_t* result_len = NULL); 75 | static char* ConsoleStringToUtf8(char* str, 76 | intptr_t len = -1, 77 | intptr_t* result_len = NULL); 78 | static const char* Utf8ToConsoleString(const char* utf8, 79 | intptr_t len = -1, 80 | intptr_t* result_len = NULL); 81 | static char* Utf8ToConsoleString(char* utf8, 82 | intptr_t len = -1, 83 | intptr_t* result_len = NULL); 84 | 85 | private: 86 | DISALLOW_ALLOCATION(); 87 | DISALLOW_IMPLICIT_CONSTRUCTORS(StringUtils); 88 | }; 89 | 90 | class ShellUtils { 91 | public: 92 | // Convert all the arguments to UTF8. On Windows, the arguments are 93 | // encoded in the current code page and not UTF8. 94 | // 95 | // Returns true if the arguments are converted. In that case 96 | // each of the arguments need to be deallocated using free. 97 | static bool GetUtf8Argv(int argc, char** argv); 98 | 99 | private: 100 | DISALLOW_ALLOCATION(); 101 | DISALLOW_IMPLICIT_CONSTRUCTORS(ShellUtils); 102 | }; 103 | 104 | class TimerUtils { 105 | public: 106 | static void InitOnce(); 107 | static int64_t GetCurrentMonotonicMicros(); 108 | static int64_t GetCurrentMonotonicMillis(); 109 | static void Sleep(int64_t millis); 110 | 111 | private: 112 | DISALLOW_ALLOCATION(); 113 | DISALLOW_IMPLICIT_CONSTRUCTORS(TimerUtils); 114 | }; 115 | 116 | } // namespace bin 117 | } // namespace dart 118 | 119 | #endif // RUNTIME_BIN_UTILS_H_ 120 | -------------------------------------------------------------------------------- /dart/bin/utils_win.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | #ifndef RUNTIME_BIN_UTILS_WIN_H_ 6 | #define RUNTIME_BIN_UTILS_WIN_H_ 7 | 8 | #include 9 | 10 | #include "platform/utils.h" 11 | 12 | #include "platform/allocation.h" 13 | 14 | #define MAX_LONG_PATH 32767 15 | 16 | namespace dart { 17 | namespace bin { 18 | 19 | void FormatMessageIntoBuffer(DWORD code, wchar_t* buffer, int buffer_length); 20 | 21 | // These string utility functions return strings that have been allocated with 22 | // Dart_ScopeAllocate(). They should be used only when we are inside an API 23 | // scope. If a string returned by one of these functions must persist beyond 24 | // the scope, then copy the results into a suitable buffer that you have 25 | // allocated. 26 | class StringUtilsWin { 27 | public: 28 | static char* WideToUtf8(wchar_t* wide, 29 | intptr_t len = -1, 30 | intptr_t* result_len = NULL); 31 | static const char* WideToUtf8(const wchar_t* wide, 32 | intptr_t len = -1, 33 | intptr_t* result_len = NULL); 34 | static wchar_t* Utf8ToWide(char* utf8, 35 | intptr_t len = -1, 36 | intptr_t* result_len = NULL); 37 | static const wchar_t* Utf8ToWide(const char* utf8, 38 | intptr_t len = -1, 39 | intptr_t* result_len = NULL); 40 | 41 | private: 42 | DISALLOW_ALLOCATION(); 43 | DISALLOW_IMPLICIT_CONSTRUCTORS(StringUtilsWin); 44 | }; 45 | 46 | // These scopes provide strings converted as indicated by the scope names. 47 | // The provided strings are allocated with 'malloc' and have the same lifetime 48 | // as the scope. 49 | class WideToUtf8Scope { 50 | public: 51 | explicit WideToUtf8Scope(const wchar_t* wide) 52 | : utf8_(Utils::CreateCStringUniquePtr(nullptr)) { 53 | intptr_t utf8_len = 54 | WideCharToMultiByte(CP_UTF8, 0, wide, -1, NULL, 0, NULL, NULL); 55 | char* utf8 = reinterpret_cast(malloc(utf8_len)); 56 | WideCharToMultiByte(CP_UTF8, 0, wide, -1, utf8, utf8_len, NULL, NULL); 57 | length_ = utf8_len; 58 | utf8_ = Utils::CreateCStringUniquePtr(utf8); 59 | } 60 | 61 | char* utf8() const { return utf8_.get(); } 62 | intptr_t length() const { return length_; } 63 | 64 | // Release the ownership of the converted string and return it. 65 | Utils::CStringUniquePtr release() { return std::move(utf8_); } 66 | 67 | private: 68 | intptr_t length_; 69 | Utils::CStringUniquePtr utf8_; 70 | 71 | DISALLOW_ALLOCATION(); 72 | DISALLOW_IMPLICIT_CONSTRUCTORS(WideToUtf8Scope); 73 | }; 74 | 75 | class Utf8ToWideScope { 76 | public: 77 | explicit Utf8ToWideScope(const char* utf8, intptr_t length = -1) { 78 | int wide_len = MultiByteToWideChar(CP_UTF8, 0, utf8, length, NULL, 0); 79 | wchar_t* wide = 80 | reinterpret_cast(malloc(sizeof(wchar_t) * wide_len)); 81 | MultiByteToWideChar(CP_UTF8, 0, utf8, length, wide, wide_len); 82 | length_ = wide_len; 83 | wide_ = wide; 84 | } 85 | 86 | ~Utf8ToWideScope() { free(wide_); } 87 | 88 | wchar_t* wide() const { return wide_; } 89 | intptr_t length() const { return length_; } 90 | intptr_t size_in_bytes() const { return length_ * sizeof(*wide_); } 91 | 92 | private: 93 | intptr_t length_; 94 | wchar_t* wide_; 95 | 96 | DISALLOW_ALLOCATION(); 97 | DISALLOW_IMPLICIT_CONSTRUCTORS(Utf8ToWideScope); 98 | }; 99 | 100 | } // namespace bin 101 | } // namespace dart 102 | 103 | #endif // RUNTIME_BIN_UTILS_WIN_H_ 104 | -------------------------------------------------------------------------------- /dart/bin/vmservice_impl.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | #ifndef RUNTIME_BIN_VMSERVICE_IMPL_H_ 6 | #define RUNTIME_BIN_VMSERVICE_IMPL_H_ 7 | 8 | #include "include/dart_api.h" 9 | 10 | #include "platform/globals.h" 11 | 12 | namespace dart { 13 | namespace bin { 14 | 15 | class VmService { 16 | public: 17 | static bool Setup(const char* server_ip, 18 | intptr_t server_port, 19 | bool dev_mode_server, 20 | bool auth_codes_disabled, 21 | const char* write_service_info_filename, 22 | bool trace_loading, 23 | bool deterministic, 24 | bool enable_service_port_fallback, 25 | bool wait_for_dds_to_advertise_service); 26 | 27 | static void SetNativeResolver(); 28 | 29 | // Error message if startup failed. 30 | static const char* GetErrorMessage(); 31 | 32 | // HTTP Server's address. 33 | static const char* GetServerAddress() { return &server_uri_[0]; } 34 | 35 | private: 36 | static const intptr_t kServerUriStringBufferSize = 1024; 37 | friend void NotifyServerState(Dart_NativeArguments args); 38 | 39 | static void SetServerAddress(const char* server_uri_); 40 | 41 | static const char* error_msg_; 42 | static char server_uri_[kServerUriStringBufferSize]; 43 | 44 | DISALLOW_ALLOCATION(); 45 | DISALLOW_IMPLICIT_CONSTRUCTORS(VmService); 46 | }; 47 | 48 | } // namespace bin 49 | } // namespace dart 50 | 51 | #endif // RUNTIME_BIN_VMSERVICE_IMPL_H_ 52 | -------------------------------------------------------------------------------- /dart/include/bin/dart_io_api.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | #ifndef RUNTIME_INCLUDE_BIN_DART_IO_API_H_ 6 | #define RUNTIME_INCLUDE_BIN_DART_IO_API_H_ 7 | 8 | #include "dart_tools_api.h" 9 | 10 | namespace dart { 11 | namespace bin { 12 | 13 | // Bootstraps 'dart:io'. 14 | void BootstrapDartIo(); 15 | 16 | // Cleans up 'dart:io'. 17 | void CleanupDartIo(); 18 | 19 | // Lets dart:io know where the system temporary directory is located. 20 | // Currently only wired up on Android. 21 | void SetSystemTempDirectory(const char* system_temp); 22 | 23 | // Tells the system whether to capture Stdout events. 24 | void SetCaptureStdout(bool value); 25 | 26 | // Tells the system whether to capture Stderr events. 27 | void SetCaptureStderr(bool value); 28 | 29 | // Should Stdout events be captured? 30 | bool ShouldCaptureStdout(); 31 | 32 | // Should Stderr events be captured? 33 | bool ShouldCaptureStderr(); 34 | 35 | // Set the executable name used by Platform.executable. 36 | void SetExecutableName(const char* executable_name); 37 | 38 | // Set the arguments used by Platform.executableArguments. 39 | void SetExecutableArguments(int script_index, char** argv); 40 | 41 | // Set dart:io implementation specific fields of Dart_EmbedderInformation. 42 | void GetIOEmbedderInformation(Dart_EmbedderInformation* info); 43 | 44 | // Generates 'length' random bytes into 'buffer'. Returns true on success 45 | // and false on failure. This is appropriate to assign to 46 | // Dart_InitializeParams.entropy_source. 47 | bool GetEntropy(uint8_t* buffer, intptr_t length); 48 | 49 | // Performs a lookup of the I/O Dart_NativeFunction with a specified 'name' and 50 | // 'argument_count'. Returns NULL if no I/O native function with a matching 51 | // name and parameter count is found. 52 | Dart_NativeFunction LookupIONative(Dart_Handle name, 53 | int argument_count, 54 | bool* auto_setup_scope); 55 | 56 | // Returns the symbol for I/O native function 'nf'. Returns NULL if 'nf' is not 57 | // a valid I/O native function. 58 | const uint8_t* LookupIONativeSymbol(Dart_NativeFunction nf); 59 | 60 | } // namespace bin 61 | } // namespace dart 62 | 63 | #endif // RUNTIME_INCLUDE_BIN_DART_IO_API_H_ 64 | -------------------------------------------------------------------------------- /dart/include/dart_api_dl.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file 3 | * for details. All rights reserved. Use of this source code is governed by a 4 | * BSD-style license that can be found in the LICENSE file. 5 | */ 6 | 7 | #ifndef RUNTIME_INCLUDE_DART_API_DL_H_ 8 | #define RUNTIME_INCLUDE_DART_API_DL_H_ 9 | 10 | #include "dart_api.h" /* NOLINT */ 11 | #include "dart_native_api.h" /* NOLINT */ 12 | 13 | /** \mainpage Dynamically Linked Dart API 14 | * 15 | * This exposes a subset of symbols from dart_api.h and dart_native_api.h 16 | * available in every Dart embedder through dynamic linking. 17 | * 18 | * All symbols are postfixed with _DL to indicate that they are dynamically 19 | * linked and to prevent conflicts with the original symbol. 20 | * 21 | * Link `dart_api_dl.c` file into your library and invoke 22 | * `Dart_InitializeApiDL` with `NativeApi.initializeApiDLData`. 23 | */ 24 | 25 | #ifdef __cplusplus 26 | #define DART_EXTERN extern "C" 27 | #else 28 | #define DART_EXTERN extern 29 | #endif 30 | 31 | DART_EXTERN intptr_t Dart_InitializeApiDL(void* data); 32 | 33 | // ============================================================================ 34 | // IMPORTANT! Never update these signatures without properly updating 35 | // DART_API_DL_MAJOR_VERSION and DART_API_DL_MINOR_VERSION. 36 | // 37 | // Verbatim copy of `dart_native_api.h` and `dart_api.h` symbol names and types 38 | // to trigger compile-time errors if the sybols in those files are updated 39 | // without updating these. 40 | // 41 | // Function return and argument types, and typedefs are carbon copied. Structs 42 | // are typechecked nominally in C/C++, so they are not copied, instead a 43 | // comment is added to their definition. 44 | typedef int64_t Dart_Port_DL; 45 | 46 | typedef void (*Dart_NativeMessageHandler_DL)(Dart_Port_DL dest_port_id, 47 | Dart_CObject* message); 48 | 49 | // dart_native_api.h symbols can be called on any thread. 50 | #define DART_NATIVE_API_DL_SYMBOLS(F) \ 51 | /***** dart_native_api.h *****/ \ 52 | /* Dart_Port */ \ 53 | F(Dart_PostCObject, bool, (Dart_Port_DL port_id, Dart_CObject * message)) \ 54 | F(Dart_PostInteger, bool, (Dart_Port_DL port_id, int64_t message)) \ 55 | F(Dart_NewNativePort, Dart_Port_DL, \ 56 | (const char* name, Dart_NativeMessageHandler_DL handler, \ 57 | bool handle_concurrently)) \ 58 | F(Dart_CloseNativePort, bool, (Dart_Port_DL native_port_id)) 59 | 60 | // dart_api.h symbols can only be called on Dart threads. 61 | #define DART_API_DL_SYMBOLS(F) \ 62 | /***** dart_api.h *****/ \ 63 | /* Errors */ \ 64 | F(Dart_IsError, bool, (Dart_Handle handle)) \ 65 | F(Dart_IsApiError, bool, (Dart_Handle handle)) \ 66 | F(Dart_IsUnhandledExceptionError, bool, (Dart_Handle handle)) \ 67 | F(Dart_IsCompilationError, bool, (Dart_Handle handle)) \ 68 | F(Dart_IsFatalError, bool, (Dart_Handle handle)) \ 69 | F(Dart_GetError, const char*, (Dart_Handle handle)) \ 70 | F(Dart_ErrorHasException, bool, (Dart_Handle handle)) \ 71 | F(Dart_ErrorGetException, Dart_Handle, (Dart_Handle handle)) \ 72 | F(Dart_ErrorGetStackTrace, Dart_Handle, (Dart_Handle handle)) \ 73 | F(Dart_NewApiError, Dart_Handle, (const char* error)) \ 74 | F(Dart_NewCompilationError, Dart_Handle, (const char* error)) \ 75 | F(Dart_NewUnhandledExceptionError, Dart_Handle, (Dart_Handle exception)) \ 76 | F(Dart_PropagateError, void, (Dart_Handle handle)) \ 77 | /* Dart_Handle, Dart_PersistentHandle, Dart_WeakPersistentHandle */ \ 78 | F(Dart_HandleFromPersistent, Dart_Handle, (Dart_PersistentHandle object)) \ 79 | F(Dart_HandleFromWeakPersistent, Dart_Handle, \ 80 | (Dart_WeakPersistentHandle object)) \ 81 | F(Dart_NewPersistentHandle, Dart_PersistentHandle, (Dart_Handle object)) \ 82 | F(Dart_SetPersistentHandle, void, \ 83 | (Dart_PersistentHandle obj1, Dart_Handle obj2)) \ 84 | F(Dart_DeletePersistentHandle, void, (Dart_PersistentHandle object)) \ 85 | F(Dart_NewWeakPersistentHandle, Dart_WeakPersistentHandle, \ 86 | (Dart_Handle object, void* peer, intptr_t external_allocation_size, \ 87 | Dart_HandleFinalizer callback)) \ 88 | F(Dart_DeleteWeakPersistentHandle, void, (Dart_WeakPersistentHandle object)) \ 89 | F(Dart_UpdateExternalSize, void, \ 90 | (Dart_WeakPersistentHandle object, intptr_t external_allocation_size)) \ 91 | F(Dart_NewFinalizableHandle, Dart_FinalizableHandle, \ 92 | (Dart_Handle object, void* peer, intptr_t external_allocation_size, \ 93 | Dart_HandleFinalizer callback)) \ 94 | F(Dart_DeleteFinalizableHandle, void, \ 95 | (Dart_FinalizableHandle object, Dart_Handle strong_ref_to_object)) \ 96 | F(Dart_UpdateFinalizableExternalSize, void, \ 97 | (Dart_FinalizableHandle object, Dart_Handle strong_ref_to_object, \ 98 | intptr_t external_allocation_size)) \ 99 | /* Dart_Port */ \ 100 | F(Dart_Post, bool, (Dart_Port_DL port_id, Dart_Handle object)) \ 101 | F(Dart_NewSendPort, Dart_Handle, (Dart_Port_DL port_id)) \ 102 | F(Dart_SendPortGetId, Dart_Handle, \ 103 | (Dart_Handle port, Dart_Port_DL * port_id)) \ 104 | /* Scopes */ \ 105 | F(Dart_EnterScope, void, ()) \ 106 | F(Dart_ExitScope, void, ()) 107 | 108 | #define DART_API_ALL_DL_SYMBOLS(F) \ 109 | DART_NATIVE_API_DL_SYMBOLS(F) \ 110 | DART_API_DL_SYMBOLS(F) 111 | // IMPORTANT! Never update these signatures without properly updating 112 | // DART_API_DL_MAJOR_VERSION and DART_API_DL_MINOR_VERSION. 113 | // 114 | // End of verbatim copy. 115 | // ============================================================================ 116 | 117 | #define DART_API_DL_DECLARATIONS(name, R, A) \ 118 | typedef R(*name##_Type) A; \ 119 | DART_EXTERN name##_Type name##_DL; 120 | 121 | DART_API_ALL_DL_SYMBOLS(DART_API_DL_DECLARATIONS) 122 | 123 | #undef DART_API_DL_DEFINITIONS 124 | 125 | #undef DART_EXTERN 126 | 127 | #endif /* RUNTIME_INCLUDE_DART_API_DL_H_ */ /* NOLINT */ 128 | -------------------------------------------------------------------------------- /dart/include/dart_embedder_api.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | #ifndef RUNTIME_INCLUDE_DART_EMBEDDER_API_H_ 6 | #define RUNTIME_INCLUDE_DART_EMBEDDER_API_H_ 7 | 8 | #include "include/dart_api.h" 9 | #include "include/dart_tools_api.h" 10 | 11 | namespace dart { 12 | namespace embedder { 13 | 14 | // Initialize all subsystems of the embedder. 15 | // 16 | // Must be called before the `Dart_Initialize()` call to initialize the 17 | // Dart VM. 18 | // 19 | // Returns true on success and false otherwise, in which case error would 20 | // contain error message. 21 | DART_WARN_UNUSED_RESULT bool InitOnce(char** error); 22 | 23 | // Cleans up all subsystems of the embedder. 24 | // 25 | // Must be called after the `Dart_Cleanup()` call to initialize the 26 | // Dart VM. 27 | void Cleanup(); 28 | 29 | // Common arguments that are passed to isolate creation callback and to 30 | // API methods that create isolates. 31 | struct IsolateCreationData { 32 | // URI for the main script that will be running in the isolate. 33 | const char* script_uri; 34 | 35 | // Advisory name of the main method that will be run by isolate. 36 | // Only used for error messages. 37 | const char* main; 38 | 39 | // Isolate creation flags. Might be absent. 40 | Dart_IsolateFlags* flags; 41 | 42 | // Isolate group callback data. 43 | void* isolate_group_data; 44 | 45 | // Isolate callback data. 46 | void* isolate_data; 47 | }; 48 | 49 | // Create and initialize kernel-service isolate. This method should be used 50 | // when VM invokes isolate creation callback with DART_KERNEL_ISOLATE_NAME as 51 | // script_uri. 52 | // The isolate is created from the given snapshot (might be kernel data or 53 | // app-jit snapshot). 54 | DART_WARN_UNUSED_RESULT Dart_Isolate 55 | CreateKernelServiceIsolate(const IsolateCreationData& data, 56 | const uint8_t* buffer, 57 | intptr_t buffer_size, 58 | char** error); 59 | 60 | // Service isolate configuration. 61 | struct VmServiceConfiguration { 62 | enum { 63 | kBindHttpServerToAFreePort = 0, 64 | kDoNotAutoStartHttpServer = -1 65 | }; 66 | 67 | // Address to which HTTP server will be bound. 68 | const char* ip; 69 | 70 | // Default port. See enum above for special values. 71 | int port; 72 | 73 | // If non-null, connection information for the VM service will be output to a 74 | // file in JSON format at the location specified. 75 | const char* write_service_info_filename; 76 | 77 | // TODO(vegorov) document these ones. 78 | bool dev_mode; 79 | bool deterministic; 80 | bool disable_auth_codes; 81 | }; 82 | 83 | // Create and initialize vm-service isolate from the given AOT snapshot, which 84 | // is expected to contain all necessary 'vm-service' libraries. 85 | // This method should be used when VM invokes isolate creation callback with 86 | // DART_VM_SERVICE_ISOLATE_NAME as script_uri. 87 | DART_WARN_UNUSED_RESULT Dart_Isolate 88 | CreateVmServiceIsolate(const IsolateCreationData& data, 89 | const VmServiceConfiguration& config, 90 | const uint8_t* isolate_data, 91 | const uint8_t* isolate_instr, 92 | char** error); 93 | 94 | // Create and initialize vm-service isolate from the given kernel binary, which 95 | // is expected to contain all necessary 'vm-service' libraries. 96 | // This method should be used when VM invokes isolate creation callback with 97 | // DART_VM_SERVICE_ISOLATE_NAME as script_uri. 98 | DART_WARN_UNUSED_RESULT Dart_Isolate 99 | CreateVmServiceIsolateFromKernel(const IsolateCreationData& data, 100 | const VmServiceConfiguration& config, 101 | const uint8_t* kernel_buffer, 102 | intptr_t kernel_buffer_size, 103 | char** error); 104 | 105 | } // namespace embedder 106 | } // namespace dart 107 | 108 | #endif // RUNTIME_INCLUDE_DART_EMBEDDER_API_H_ 109 | -------------------------------------------------------------------------------- /dart/include/dart_native_api.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 3 | * for details. All rights reserved. Use of this source code is governed by a 4 | * BSD-style license that can be found in the LICENSE file. 5 | */ 6 | 7 | #ifndef RUNTIME_INCLUDE_DART_NATIVE_API_H_ 8 | #define RUNTIME_INCLUDE_DART_NATIVE_API_H_ 9 | 10 | #include "dart_api.h" /* NOLINT */ 11 | 12 | /* 13 | * ========================================== 14 | * Message sending/receiving from native code 15 | * ========================================== 16 | */ 17 | 18 | /** 19 | * A Dart_CObject is used for representing Dart objects as native C 20 | * data outside the Dart heap. These objects are totally detached from 21 | * the Dart heap. Only a subset of the Dart objects have a 22 | * representation as a Dart_CObject. 23 | * 24 | * The string encoding in the 'value.as_string' is UTF-8. 25 | * 26 | * All the different types from dart:typed_data are exposed as type 27 | * kTypedData. The specific type from dart:typed_data is in the type 28 | * field of the as_typed_data structure. The length in the 29 | * as_typed_data structure is always in bytes. 30 | * 31 | * The data for kTypedData is copied on message send and ownership remains with 32 | * the caller. The ownership of data for kExternalTyped is passed to the VM on 33 | * message send and returned when the VM invokes the 34 | * Dart_HandleFinalizer callback; a non-NULL callback must be provided. 35 | */ 36 | typedef enum { 37 | Dart_CObject_kNull = 0, 38 | Dart_CObject_kBool, 39 | Dart_CObject_kInt32, 40 | Dart_CObject_kInt64, 41 | Dart_CObject_kDouble, 42 | Dart_CObject_kString, 43 | Dart_CObject_kArray, 44 | Dart_CObject_kTypedData, 45 | Dart_CObject_kExternalTypedData, 46 | Dart_CObject_kSendPort, 47 | Dart_CObject_kCapability, 48 | Dart_CObject_kUnsupported, 49 | Dart_CObject_kNumberOfTypes 50 | } Dart_CObject_Type; 51 | 52 | typedef struct _Dart_CObject { 53 | Dart_CObject_Type type; 54 | union { 55 | bool as_bool; 56 | int32_t as_int32; 57 | int64_t as_int64; 58 | double as_double; 59 | char* as_string; 60 | struct { 61 | Dart_Port id; 62 | Dart_Port origin_id; 63 | } as_send_port; 64 | struct { 65 | int64_t id; 66 | } as_capability; 67 | struct { 68 | intptr_t length; 69 | struct _Dart_CObject** values; 70 | } as_array; 71 | struct { 72 | Dart_TypedData_Type type; 73 | intptr_t length; 74 | uint8_t* values; 75 | } as_typed_data; 76 | struct { 77 | Dart_TypedData_Type type; 78 | intptr_t length; 79 | uint8_t* data; 80 | void* peer; 81 | Dart_HandleFinalizer callback; 82 | } as_external_typed_data; 83 | } value; 84 | } Dart_CObject; 85 | // This struct is versioned by DART_API_DL_MAJOR_VERSION, bump the version when 86 | // changing this struct. 87 | 88 | /** 89 | * Posts a message on some port. The message will contain the Dart_CObject 90 | * object graph rooted in 'message'. 91 | * 92 | * While the message is being sent the state of the graph of Dart_CObject 93 | * structures rooted in 'message' should not be accessed, as the message 94 | * generation will make temporary modifications to the data. When the message 95 | * has been sent the graph will be fully restored. 96 | * 97 | * If true is returned, the message was enqueued, and finalizers for external 98 | * typed data will eventually run, even if the receiving isolate shuts down 99 | * before processing the message. If false is returned, the message was not 100 | * enqueued and ownership of external typed data in the message remains with the 101 | * caller. 102 | * 103 | * This function may be called on any thread when the VM is running (that is, 104 | * after Dart_Initialize has returned and before Dart_Cleanup has been called). 105 | * 106 | * \param port_id The destination port. 107 | * \param message The message to send. 108 | * 109 | * \return True if the message was posted. 110 | */ 111 | DART_EXPORT bool Dart_PostCObject(Dart_Port port_id, Dart_CObject* message); 112 | 113 | /** 114 | * Posts a message on some port. The message will contain the integer 'message'. 115 | * 116 | * \param port_id The destination port. 117 | * \param message The message to send. 118 | * 119 | * \return True if the message was posted. 120 | */ 121 | DART_EXPORT bool Dart_PostInteger(Dart_Port port_id, int64_t message); 122 | 123 | /** 124 | * A native message handler. 125 | * 126 | * This handler is associated with a native port by calling 127 | * Dart_NewNativePort. 128 | * 129 | * The message received is decoded into the message structure. The 130 | * lifetime of the message data is controlled by the caller. All the 131 | * data references from the message are allocated by the caller and 132 | * will be reclaimed when returning to it. 133 | */ 134 | typedef void (*Dart_NativeMessageHandler)(Dart_Port dest_port_id, 135 | Dart_CObject* message); 136 | 137 | /** 138 | * Creates a new native port. When messages are received on this 139 | * native port, then they will be dispatched to the provided native 140 | * message handler. 141 | * 142 | * \param name The name of this port in debugging messages. 143 | * \param handler The C handler to run when messages arrive on the port. 144 | * \param handle_concurrently Is it okay to process requests on this 145 | * native port concurrently? 146 | * 147 | * \return If successful, returns the port id for the native port. In 148 | * case of error, returns ILLEGAL_PORT. 149 | */ 150 | DART_EXPORT Dart_Port Dart_NewNativePort(const char* name, 151 | Dart_NativeMessageHandler handler, 152 | bool handle_concurrently); 153 | /* TODO(turnidge): Currently handle_concurrently is ignored. */ 154 | 155 | /** 156 | * Closes the native port with the given id. 157 | * 158 | * The port must have been allocated by a call to Dart_NewNativePort. 159 | * 160 | * \param native_port_id The id of the native port to close. 161 | * 162 | * \return Returns true if the port was closed successfully. 163 | */ 164 | DART_EXPORT bool Dart_CloseNativePort(Dart_Port native_port_id); 165 | 166 | /* 167 | * ================== 168 | * Verification Tools 169 | * ================== 170 | */ 171 | 172 | /** 173 | * Forces all loaded classes and functions to be compiled eagerly in 174 | * the current isolate.. 175 | * 176 | * TODO(turnidge): Document. 177 | */ 178 | DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle Dart_CompileAll(); 179 | 180 | /** 181 | * Finalizes all classes. 182 | */ 183 | DART_EXPORT DART_WARN_UNUSED_RESULT Dart_Handle Dart_FinalizeAllClasses(); 184 | 185 | /* This function is intentionally undocumented. 186 | * 187 | * It should not be used outside internal tests. 188 | */ 189 | DART_EXPORT void* Dart_ExecuteInternalCommand(const char* command, void* arg); 190 | 191 | #endif /* INCLUDE_DART_NATIVE_API_H_ */ /* NOLINT */ 192 | -------------------------------------------------------------------------------- /dart/include/dart_tools_api.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | #ifndef RUNTIME_INCLUDE_DART_TOOLS_API_H_ 6 | #define RUNTIME_INCLUDE_DART_TOOLS_API_H_ 7 | 8 | #include "dart_api.h" /* NOLINT */ 9 | 10 | /** \mainpage Dart Tools Embedding API Reference 11 | * 12 | * This reference describes the Dart embedding API for tools. Tools include 13 | * a debugger, service protocol, and timeline. 14 | * 15 | * NOTE: The APIs described in this file are unstable and subject to change. 16 | * 17 | * This reference is generated from the header include/dart_tools_api.h. 18 | */ 19 | 20 | /* 21 | * ======== 22 | * Debugger 23 | * ======== 24 | */ 25 | 26 | /** 27 | * ILLEGAL_ISOLATE_ID is a number guaranteed never to be associated with a 28 | * valid isolate. 29 | */ 30 | #define ILLEGAL_ISOLATE_ID ILLEGAL_PORT 31 | 32 | 33 | /* 34 | * ======= 35 | * Service 36 | * ======= 37 | */ 38 | 39 | /** 40 | * A service request callback function. 41 | * 42 | * These callbacks, registered by the embedder, are called when the VM receives 43 | * a service request it can't handle and the service request command name 44 | * matches one of the embedder registered handlers. 45 | * 46 | * The return value of the callback indicates whether the response 47 | * should be used as a regular result or an error result. 48 | * Specifically, if the callback returns true, a regular JSON-RPC 49 | * response is built in the following way: 50 | * 51 | * { 52 | * "jsonrpc": "2.0", 53 | * "result": , 54 | * "id": , 55 | * } 56 | * 57 | * If the callback returns false, a JSON-RPC error is built like this: 58 | * 59 | * { 60 | * "jsonrpc": "2.0", 61 | * "error": , 62 | * "id": , 63 | * } 64 | * 65 | * \param method The rpc method name. 66 | * \param param_keys Service requests can have key-value pair parameters. The 67 | * keys and values are flattened and stored in arrays. 68 | * \param param_values The values associated with the keys. 69 | * \param num_params The length of the param_keys and param_values arrays. 70 | * \param user_data The user_data pointer registered with this handler. 71 | * \param result A C string containing a valid JSON object. The returned 72 | * pointer will be freed by the VM by calling free. 73 | * 74 | * \return True if the result is a regular JSON-RPC response, false if the 75 | * result is a JSON-RPC error. 76 | */ 77 | typedef bool (*Dart_ServiceRequestCallback)(const char* method, 78 | const char** param_keys, 79 | const char** param_values, 80 | intptr_t num_params, 81 | void* user_data, 82 | const char** json_object); 83 | 84 | /** 85 | * Register a Dart_ServiceRequestCallback to be called to handle 86 | * requests for the named rpc on a specific isolate. The callback will 87 | * be invoked with the current isolate set to the request target. 88 | * 89 | * \param method The name of the method that this callback is responsible for. 90 | * \param callback The callback to invoke. 91 | * \param user_data The user data passed to the callback. 92 | * 93 | * NOTE: If multiple callbacks with the same name are registered, only 94 | * the last callback registered will be remembered. 95 | */ 96 | DART_EXPORT void Dart_RegisterIsolateServiceRequestCallback( 97 | const char* method, 98 | Dart_ServiceRequestCallback callback, 99 | void* user_data); 100 | 101 | /** 102 | * Register a Dart_ServiceRequestCallback to be called to handle 103 | * requests for the named rpc. The callback will be invoked without a 104 | * current isolate. 105 | * 106 | * \param method The name of the command that this callback is responsible for. 107 | * \param callback The callback to invoke. 108 | * \param user_data The user data passed to the callback. 109 | * 110 | * NOTE: If multiple callbacks with the same name are registered, only 111 | * the last callback registered will be remembered. 112 | */ 113 | DART_EXPORT void Dart_RegisterRootServiceRequestCallback( 114 | const char* method, 115 | Dart_ServiceRequestCallback callback, 116 | void* user_data); 117 | 118 | /** 119 | * Embedder information which can be requested by the VM for internal or 120 | * reporting purposes. 121 | * 122 | * The pointers in this structure are not going to be cached or freed by the VM. 123 | */ 124 | 125 | #define DART_EMBEDDER_INFORMATION_CURRENT_VERSION (0x00000001) 126 | 127 | typedef struct { 128 | int32_t version; 129 | const char* name; // [optional] The name of the embedder 130 | int64_t current_rss; // [optional] the current RSS of the embedder 131 | int64_t max_rss; // [optional] the maximum RSS of the embedder 132 | } Dart_EmbedderInformation; 133 | 134 | /** 135 | * Callback provided by the embedder that is used by the vm to request 136 | * information. 137 | * 138 | * \return Returns a pointer to a Dart_EmbedderInformation structure. 139 | * The embedder keeps the ownership of the structure and any field in it. 140 | * The embedder must ensure that the structure will remain valid until the 141 | * next invokation of the callback. 142 | */ 143 | typedef void (*Dart_EmbedderInformationCallback)( 144 | Dart_EmbedderInformation* info); 145 | 146 | /** 147 | * Register a Dart_ServiceRequestCallback to be called to handle 148 | * requests for the named rpc. The callback will be invoked without a 149 | * current isolate. 150 | * 151 | * \param method The name of the command that this callback is responsible for. 152 | * \param callback The callback to invoke. 153 | * \param user_data The user data passed to the callback. 154 | * 155 | * NOTE: If multiple callbacks with the same name are registered, only 156 | * the last callback registered will be remembered. 157 | */ 158 | DART_EXPORT void Dart_SetEmbedderInformationCallback( 159 | Dart_EmbedderInformationCallback callback); 160 | 161 | /** 162 | * Invoke a vm-service method and wait for its result. 163 | * 164 | * \param request_json The utf8-encoded json-rpc request. 165 | * \param request_json_length The length of the json-rpc request. 166 | * 167 | * \param response_json The returned utf8-encoded json response, must be 168 | * free()ed by caller. 169 | * \param response_json_length The length of the returned json response. 170 | * \param error An optional error, must be free()ed by caller. 171 | * 172 | * \return Whether the call was sucessfully performed. 173 | * 174 | * NOTE: This method does not need a current isolate and must not have the 175 | * vm-isolate being the current isolate. It must be called after 176 | * Dart_Initialize() and before Dart_Cleanup(). 177 | */ 178 | DART_EXPORT bool Dart_InvokeVMServiceMethod(uint8_t* request_json, 179 | intptr_t request_json_length, 180 | uint8_t** response_json, 181 | intptr_t* response_json_length, 182 | char** error); 183 | 184 | /* 185 | * ======== 186 | * Event Streams 187 | * ======== 188 | */ 189 | 190 | /** 191 | * A callback invoked when the VM service gets a request to listen to 192 | * some stream. 193 | * 194 | * \return Returns true iff the embedder supports the named stream id. 195 | */ 196 | typedef bool (*Dart_ServiceStreamListenCallback)(const char* stream_id); 197 | 198 | /** 199 | * A callback invoked when the VM service gets a request to cancel 200 | * some stream. 201 | */ 202 | typedef void (*Dart_ServiceStreamCancelCallback)(const char* stream_id); 203 | 204 | /** 205 | * Adds VM service stream callbacks. 206 | * 207 | * \param listen_callback A function pointer to a listen callback function. 208 | * A listen callback function should not be already set when this function 209 | * is called. A NULL value removes the existing listen callback function 210 | * if any. 211 | * 212 | * \param cancel_callback A function pointer to a cancel callback function. 213 | * A cancel callback function should not be already set when this function 214 | * is called. A NULL value removes the existing cancel callback function 215 | * if any. 216 | * 217 | * \return Success if the callbacks were added. Otherwise, returns an 218 | * error handle. 219 | */ 220 | DART_EXPORT char* Dart_SetServiceStreamCallbacks( 221 | Dart_ServiceStreamListenCallback listen_callback, 222 | Dart_ServiceStreamCancelCallback cancel_callback); 223 | 224 | /** 225 | * A callback invoked when the VM service receives an event. 226 | */ 227 | typedef void (*Dart_NativeStreamConsumer)(const uint8_t* event_json, 228 | intptr_t event_json_length); 229 | 230 | /** 231 | * Sets the native VM service stream callbacks for a particular stream. 232 | * Note: The function may be called on multiple threads concurrently. 233 | * 234 | * \param consumer A function pointer to an event handler callback function. 235 | * A NULL value removes the existing listen callback function if any. 236 | * 237 | * \param stream_id The ID of the stream on which to set the callback. 238 | */ 239 | DART_EXPORT void Dart_SetNativeServiceStreamCallback( 240 | Dart_NativeStreamConsumer consumer, 241 | const char* stream_id); 242 | 243 | /** 244 | * Sends a data event to clients of the VM Service. 245 | * 246 | * A data event is used to pass an array of bytes to subscribed VM 247 | * Service clients. For example, in the standalone embedder, this is 248 | * function used to provide WriteEvents on the Stdout and Stderr 249 | * streams. 250 | * 251 | * If the embedder passes in a stream id for which no client is 252 | * subscribed, then the event is ignored. 253 | * 254 | * \param stream_id The id of the stream on which to post the event. 255 | * 256 | * \param event_kind A string identifying what kind of event this is. 257 | * For example, 'WriteEvent'. 258 | * 259 | * \param bytes A pointer to an array of bytes. 260 | * 261 | * \param bytes_length The length of the byte array. 262 | * 263 | * \return NULL if the arguments are well formed. Otherwise, returns an 264 | * error string. The caller is responsible for freeing the error message. 265 | */ 266 | DART_EXPORT char* Dart_ServiceSendDataEvent(const char* stream_id, 267 | const char* event_kind, 268 | const uint8_t* bytes, 269 | intptr_t bytes_length); 270 | 271 | /** 272 | * Usage statistics for a space/generation at a particular moment in time. 273 | * 274 | * \param used Amount of memory used, in bytes. 275 | * 276 | * \param capacity Memory capacity, in bytes. 277 | * 278 | * \param external External memory, in bytes. 279 | * 280 | * \param collections How many times the garbage collector has run in this 281 | * space. 282 | * 283 | * \param time Cumulative time spent collecting garbage in this space, in 284 | * seconds. 285 | * 286 | * \param avg_collection_period Average time between garbage collector running 287 | * in this space, in milliseconds. 288 | */ 289 | typedef struct { 290 | intptr_t used; 291 | intptr_t capacity; 292 | intptr_t external; 293 | intptr_t collections; 294 | double time; 295 | double avg_collection_period; 296 | } Dart_GCStats; 297 | 298 | /** 299 | * A Garbage Collection event with memory usage statistics. 300 | * 301 | * \param type The event type. Static lifetime. 302 | * 303 | * \param reason The reason for the GC event. Static lifetime. 304 | * 305 | * \param new_space Data for New Space. 306 | * 307 | * \param old_space Data for Old Space. 308 | */ 309 | typedef struct { 310 | const char* type; 311 | const char* reason; 312 | const char* isolate_id; 313 | 314 | Dart_GCStats new_space; 315 | Dart_GCStats old_space; 316 | } Dart_GCEvent; 317 | 318 | /** 319 | * A callback invoked when the VM emits a GC event. 320 | * 321 | * \param event The GC event data. Pointer only valid for the duration of the 322 | * callback. 323 | */ 324 | typedef void (*Dart_GCEventCallback)(Dart_GCEvent* event); 325 | 326 | /** 327 | * Sets the native GC event callback. 328 | * 329 | * \param callback A function pointer to an event handler callback function. 330 | * A NULL value removes the existing listen callback function if any. 331 | */ 332 | DART_EXPORT void Dart_SetGCEventCallback(Dart_GCEventCallback callback); 333 | 334 | /* 335 | * ======== 336 | * Reload support 337 | * ======== 338 | * 339 | * These functions are used to implement reloading in the Dart VM. 340 | * This is an experimental feature, so embedders should be prepared 341 | * for these functions to change. 342 | */ 343 | 344 | /** 345 | * A callback which determines whether the file at some url has been 346 | * modified since some time. If the file cannot be found, true should 347 | * be returned. 348 | */ 349 | typedef bool (*Dart_FileModifiedCallback)(const char* url, int64_t since); 350 | 351 | DART_EXPORT char* Dart_SetFileModifiedCallback( 352 | Dart_FileModifiedCallback file_modified_callback); 353 | 354 | /** 355 | * Returns true if isolate is currently reloading. 356 | */ 357 | DART_EXPORT bool Dart_IsReloading(); 358 | 359 | /* 360 | * ======== 361 | * Timeline 362 | * ======== 363 | */ 364 | 365 | /** 366 | * Returns a timestamp in microseconds. This timestamp is suitable for 367 | * passing into the timeline system, and uses the same monotonic clock 368 | * as dart:developer's Timeline.now. 369 | * 370 | * \return A timestamp that can be passed to the timeline system. 371 | */ 372 | DART_EXPORT int64_t Dart_TimelineGetMicros(); 373 | 374 | /** Timeline stream for Dart API calls */ 375 | #define DART_TIMELINE_STREAM_API (1 << 0) 376 | /** Timeline stream for compiler events */ 377 | #define DART_TIMELINE_STREAM_COMPILER (1 << 1) 378 | /** Timeline stream for Dart provided events */ 379 | #define DART_TIMELINE_STREAM_DART (1 << 2) 380 | /** Timeline stream for debugger provided events */ 381 | #define DART_TIMELINE_STREAM_DEBUGGER (1 << 3) 382 | /** Timeline stream for embedder provided events */ 383 | #define DART_TIMELINE_STREAM_EMBEDDER (1 << 4) 384 | /** Timeline stream for GC events */ 385 | #define DART_TIMELINE_STREAM_GC (1 << 5) 386 | /** Timeline stream for isolate events */ 387 | #define DART_TIMELINE_STREAM_ISOLATE (1 << 6) 388 | /** Timeline stream for VM events */ 389 | #define DART_TIMELINE_STREAM_VM (1 << 7) 390 | 391 | /** All timeline streams */ 392 | #define DART_TIMELINE_STREAM_ALL \ 393 | (DART_TIMELINE_STREAM_API | DART_TIMELINE_STREAM_COMPILER | \ 394 | DART_TIMELINE_STREAM_DART | DART_TIMELINE_STREAM_DEBUGGER | \ 395 | DART_TIMELINE_STREAM_EMBEDDER | DART_TIMELINE_STREAM_GC | \ 396 | DART_TIMELINE_STREAM_ISOLATE | DART_TIMELINE_STREAM_VM) 397 | 398 | /** Disable all timeline stream recording */ 399 | #define DART_TIMELINE_STREAM_DISABLE 0 400 | 401 | /** 402 | * Start recording timeline events for the entire VM (including all isolates). 403 | * 404 | * \param stream_mask A bitmask of streams that should be recorded. 405 | * 406 | * NOTE: Calling with 0 disables recording of all streams. 407 | */ 408 | DART_EXPORT void Dart_GlobalTimelineSetRecordedStreams(int64_t stream_mask); 409 | 410 | typedef enum { 411 | Dart_Timeline_Event_Begin, // Phase = 'B'. 412 | Dart_Timeline_Event_End, // Phase = 'E'. 413 | Dart_Timeline_Event_Instant, // Phase = 'i'. 414 | Dart_Timeline_Event_Duration, // Phase = 'X'. 415 | Dart_Timeline_Event_Async_Begin, // Phase = 'b'. 416 | Dart_Timeline_Event_Async_End, // Phase = 'e'. 417 | Dart_Timeline_Event_Async_Instant, // Phase = 'n'. 418 | Dart_Timeline_Event_Counter, // Phase = 'C'. 419 | Dart_Timeline_Event_Flow_Begin, // Phase = 's'. 420 | Dart_Timeline_Event_Flow_Step, // Phase = 't'. 421 | Dart_Timeline_Event_Flow_End, // Phase = 'f'. 422 | } Dart_Timeline_Event_Type; 423 | 424 | /** 425 | * Add a timeline event to the embedder stream. 426 | * 427 | * \param label The name of the event. Its lifetime must extend at least until 428 | * Dart_Cleanup. 429 | * \param timestamp0 The first timestamp of the event. 430 | * \param timestamp1_or_async_id The second timestamp of the event or 431 | * the async id. 432 | * \param argument_count The number of argument names and values. 433 | * \param argument_names An array of names of the arguments. The lifetime of the 434 | * names must extend at least until Dart_Cleanup. The array may be reclaimed 435 | * when this call returns. 436 | * \param argument_values An array of values of the arguments. The values and 437 | * the array may be reclaimed when this call returns. 438 | */ 439 | DART_EXPORT void Dart_TimelineEvent(const char* label, 440 | int64_t timestamp0, 441 | int64_t timestamp1_or_async_id, 442 | Dart_Timeline_Event_Type type, 443 | intptr_t argument_count, 444 | const char** argument_names, 445 | const char** argument_values); 446 | 447 | /** 448 | * Associates a name with the current thread. This name will be used to name 449 | * threads in the timeline. Can only be called after a call to Dart_Initialize. 450 | * 451 | * \param name The name of the thread. 452 | */ 453 | DART_EXPORT void Dart_SetThreadName(const char* name); 454 | 455 | /* 456 | * ======= 457 | * Metrics 458 | * ======= 459 | */ 460 | 461 | /** 462 | * Return metrics gathered for the VM and individual isolates. 463 | * 464 | * NOTE: Non-heap metrics are not available in PRODUCT builds of Dart. 465 | * Calling the non-heap metric functions on a PRODUCT build might return invalid metrics. 466 | */ 467 | DART_EXPORT int64_t Dart_VMIsolateCountMetric(); // Counter 468 | DART_EXPORT int64_t Dart_VMCurrentRSSMetric(); // Byte 469 | DART_EXPORT int64_t Dart_VMPeakRSSMetric(); // Byte 470 | DART_EXPORT int64_t 471 | Dart_IsolateHeapOldUsedMetric(Dart_Isolate isolate); // Byte 472 | DART_EXPORT int64_t 473 | Dart_IsolateHeapOldUsedMaxMetric(Dart_Isolate isolate); // Byte 474 | DART_EXPORT int64_t 475 | Dart_IsolateHeapOldCapacityMetric(Dart_Isolate isolate); // Byte 476 | DART_EXPORT int64_t 477 | Dart_IsolateHeapOldCapacityMaxMetric(Dart_Isolate isolate); // Byte 478 | DART_EXPORT int64_t 479 | Dart_IsolateHeapOldExternalMetric(Dart_Isolate isolate); // Byte 480 | DART_EXPORT int64_t 481 | Dart_IsolateHeapNewUsedMetric(Dart_Isolate isolate); // Byte 482 | DART_EXPORT int64_t 483 | Dart_IsolateHeapNewUsedMaxMetric(Dart_Isolate isolate); // Byte 484 | DART_EXPORT int64_t 485 | Dart_IsolateHeapNewCapacityMetric(Dart_Isolate isolate); // Byte 486 | DART_EXPORT int64_t 487 | Dart_IsolateHeapNewCapacityMaxMetric(Dart_Isolate isolate); // Byte 488 | DART_EXPORT int64_t 489 | Dart_IsolateHeapNewExternalMetric(Dart_Isolate isolate); // Byte 490 | DART_EXPORT int64_t 491 | Dart_IsolateHeapGlobalUsedMetric(Dart_Isolate isolate); // Byte 492 | DART_EXPORT int64_t 493 | Dart_IsolateHeapGlobalUsedMaxMetric(Dart_Isolate isolate); // Byte 494 | DART_EXPORT int64_t 495 | Dart_IsolateRunnableLatencyMetric(Dart_Isolate isolate); // Microsecond 496 | DART_EXPORT int64_t 497 | Dart_IsolateRunnableHeapSizeMetric(Dart_Isolate isolate); // Byte 498 | 499 | #endif // RUNTIME_INCLUDE_DART_TOOLS_API_H_ 500 | -------------------------------------------------------------------------------- /dart/include/dart_version.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file 3 | * for details. All rights reserved. Use of this source code is governed by a 4 | * BSD-style license that can be found in the LICENSE file. 5 | */ 6 | 7 | #ifndef RUNTIME_INCLUDE_DART_VERSION_H_ 8 | #define RUNTIME_INCLUDE_DART_VERSION_H_ 9 | 10 | // On breaking changes the major version is increased. 11 | // On backwards compatible changes the minor version is increased. 12 | // The versioning covers the symbols exposed in dart_api_dl.h 13 | #define DART_API_DL_MAJOR_VERSION 2 14 | #define DART_API_DL_MINOR_VERSION 0 15 | 16 | #endif /* RUNTIME_INCLUDE_DART_VERSION_H_ */ /* NOLINT */ 17 | -------------------------------------------------------------------------------- /dart/include/internal/dart_api_dl_impl.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file 3 | * for details. All rights reserved. Use of this source code is governed by a 4 | * BSD-style license that can be found in the LICENSE file. 5 | */ 6 | 7 | #ifndef RUNTIME_INCLUDE_INTERNAL_DART_API_DL_IMPL_H_ 8 | #define RUNTIME_INCLUDE_INTERNAL_DART_API_DL_IMPL_H_ 9 | 10 | typedef struct { 11 | const char* name; 12 | void (*function)(); 13 | } DartApiEntry; 14 | 15 | typedef struct { 16 | const int major; 17 | const int minor; 18 | const DartApiEntry* const functions; 19 | } DartApi; 20 | 21 | #endif /* RUNTIME_INCLUDE_INTERNAL_DART_API_DL_IMPL_H_ */ /* NOLINT */ 22 | -------------------------------------------------------------------------------- /dart/lib/win-debug-x64/libdart.lib: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:bbcd01bee3cf8e15dccd521c855636bf12dc43a5e01459fcb31d5f086ae8302b 3 | size 321566934 4 | -------------------------------------------------------------------------------- /dart/lib/win-release-x64/libdart.lib: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:15b11ac9bd0b204346d66b7bb6b7dd739c07173627b955cf99816df63062ac1e 3 | size 282769130 4 | -------------------------------------------------------------------------------- /dart/platform/address_sanitizer.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | #ifndef RUNTIME_PLATFORM_ADDRESS_SANITIZER_H_ 6 | #define RUNTIME_PLATFORM_ADDRESS_SANITIZER_H_ 7 | 8 | #include "platform/globals.h" 9 | 10 | // Allow the use of ASan (AddressSanitizer). This is needed as ASan needs to be 11 | // told about areas where the VM does the equivalent of a long-jump. 12 | #if defined(__has_feature) 13 | #if __has_feature(address_sanitizer) 14 | #define USING_ADDRESS_SANITIZER 15 | #endif 16 | #endif 17 | 18 | #if defined(USING_ADDRESS_SANITIZER) 19 | extern "C" void __asan_unpoison_memory_region(void*, size_t); 20 | #define NO_SANITIZE_ADDRESS __attribute__((no_sanitize("address"))) 21 | #define ASAN_UNPOISON(ptr, len) __asan_unpoison_memory_region(ptr, len) 22 | #else // defined(USING_ADDRESS_SANITIZER) 23 | #define NO_SANITIZE_ADDRESS 24 | #define ASAN_UNPOISON(ptr, len) \ 25 | do { \ 26 | } while (false && (ptr) == 0 && (len) == 0) 27 | #endif // defined(USING_ADDRESS_SANITIZER) 28 | 29 | #endif // RUNTIME_PLATFORM_ADDRESS_SANITIZER_H_ 30 | -------------------------------------------------------------------------------- /dart/platform/allocation.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | #ifndef RUNTIME_PLATFORM_ALLOCATION_H_ 6 | #define RUNTIME_PLATFORM_ALLOCATION_H_ 7 | 8 | #include "platform/address_sanitizer.h" 9 | #include "platform/assert.h" 10 | 11 | namespace dart { 12 | 13 | // Stack allocated objects subclass from this base class. Objects of this type 14 | // cannot be allocated on either the C or object heaps. Destructors for objects 15 | // of this type will not be run unless the stack is unwound through normal 16 | // program control flow. 17 | class ValueObject { 18 | public: 19 | ValueObject() {} 20 | ~ValueObject() {} 21 | 22 | private: 23 | DISALLOW_ALLOCATION(); 24 | DISALLOW_COPY_AND_ASSIGN(ValueObject); 25 | }; 26 | 27 | // Static allocated classes only contain static members and can never 28 | // be instantiated in the heap or on the stack. 29 | class AllStatic { 30 | private: 31 | DISALLOW_ALLOCATION(); 32 | DISALLOW_IMPLICIT_CONSTRUCTORS(AllStatic); 33 | }; 34 | 35 | class MallocAllocated { 36 | public: 37 | MallocAllocated() {} 38 | 39 | // Intercept operator new to produce clearer error messages when we run out 40 | // of memory. Don't do this when running under ASAN so it can continue to 41 | // check malloc/new/new[] are paired with free/delete/delete[] respectively. 42 | #if !defined(USING_ADDRESS_SANITIZER) 43 | void* operator new(size_t size) { 44 | void* result = ::malloc(size); 45 | if (result == nullptr) { 46 | OUT_OF_MEMORY(); 47 | } 48 | return result; 49 | } 50 | 51 | void* operator new[](size_t size) { 52 | void* result = ::malloc(size); 53 | if (result == nullptr) { 54 | OUT_OF_MEMORY(); 55 | } 56 | return result; 57 | } 58 | 59 | void operator delete(void* pointer) { ::free(pointer); } 60 | 61 | void operator delete[](void* pointer) { ::free(pointer); } 62 | #endif 63 | }; 64 | 65 | void* malloc(size_t size); 66 | void* realloc(void* ptr, size_t size); 67 | 68 | } // namespace dart 69 | 70 | #endif // RUNTIME_PLATFORM_ALLOCATION_H_ 71 | -------------------------------------------------------------------------------- /dart/platform/assert.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | #ifndef RUNTIME_PLATFORM_ASSERT_H_ 6 | #define RUNTIME_PLATFORM_ASSERT_H_ 7 | 8 | #include "platform/globals.h" 9 | #include "platform/memory_sanitizer.h" 10 | 11 | #if !defined(DEBUG) && !defined(NDEBUG) 12 | #error neither DEBUG nor NDEBUG defined 13 | #elif defined(DEBUG) && defined(NDEBUG) 14 | #error both DEBUG and NDEBUG defined 15 | #endif 16 | 17 | // TODO(5411406): include sstream for now, once we have a Utils::toString() 18 | // implemented for all the primitive types we can replace the usage of 19 | // sstream by Utils::toString() 20 | #if defined(DEBUG) || defined(TESTING) 21 | #include 22 | #include 23 | #endif 24 | 25 | namespace dart { 26 | 27 | class DynamicAssertionHelper { 28 | public: 29 | DynamicAssertionHelper(const char* file, int line) 30 | : file_(file), line_(line) {} 31 | 32 | protected: 33 | void Print(const char* format, va_list arguments, bool will_abort = false); 34 | 35 | const char* const file_; 36 | const int line_; 37 | 38 | DISALLOW_IMPLICIT_CONSTRUCTORS(DynamicAssertionHelper); 39 | }; 40 | 41 | class Assert : public DynamicAssertionHelper { 42 | public: 43 | Assert(const char* file, int line) : DynamicAssertionHelper(file, line) {} 44 | 45 | DART_NORETURN void Fail(const char* format, ...) PRINTF_ATTRIBUTE(2, 3); 46 | 47 | template 48 | T NotNull(const T p); 49 | }; 50 | 51 | class Expect : public DynamicAssertionHelper { 52 | public: 53 | Expect(const char* file, int line) : DynamicAssertionHelper(file, line) {} 54 | 55 | void Fail(const char* format, ...) PRINTF_ATTRIBUTE(2, 3); 56 | 57 | #if defined(TESTING) 58 | template 59 | void Equals(const E& expected, const A& actual); 60 | 61 | template 62 | void NotEquals(const E& not_expected, const A& actual); 63 | 64 | template 65 | void FloatEquals(const E& expected, const A& actual, const T& tol); 66 | 67 | void StringEquals(const char* expected, const char* actual); 68 | 69 | void IsSubstring(const char* needle, const char* haystack); 70 | 71 | void IsNotSubstring(const char* needle, const char* haystack); 72 | 73 | template 74 | void LessThan(const E& left, const A& right); 75 | 76 | template 77 | void LessEqual(const E& left, const A& right); 78 | 79 | template 80 | void GreaterThan(const E& left, const A& right); 81 | 82 | template 83 | void GreaterEqual(const E& left, const A& right); 84 | 85 | template 86 | void NotNull(const T p); 87 | 88 | template 89 | void Null(const T p); 90 | #endif 91 | 92 | static bool failed() { return failed_; } 93 | 94 | private: 95 | static bool failed_; 96 | }; 97 | 98 | template 99 | T Assert::NotNull(const T p) { 100 | if (p != NULL) return p; 101 | Fail("expected: not NULL, found NULL"); 102 | return NULL; 103 | } 104 | 105 | #if defined(TESTING) 106 | // Only allow the expensive (with respect to code size) assertions 107 | // in testing code. 108 | template 109 | void Expect::Equals(const E& expected, const A& actual) { 110 | if (actual == expected) return; 111 | std::ostringstream ess, ass; 112 | ess << expected; 113 | ass << actual; 114 | std::string es = ess.str(), as = ass.str(); 115 | Fail("expected: <%s> but was: <%s>", es.c_str(), as.c_str()); 116 | } 117 | 118 | template 119 | void Expect::NotEquals(const E& not_expected, const A& actual) { 120 | if (actual != not_expected) return; 121 | std::ostringstream ness; 122 | ness << not_expected; 123 | std::string nes = ness.str(); 124 | Fail("did not expect: <%s>", nes.c_str()); 125 | } 126 | 127 | template 128 | void Expect::FloatEquals(const E& expected, const A& actual, const T& tol) { 129 | if (((expected - tol) <= actual) && (actual <= (expected + tol))) { 130 | return; 131 | } 132 | std::ostringstream ess, ass, tolss; 133 | ess << expected; 134 | ass << actual; 135 | tolss << tol; 136 | std::string es = ess.str(), as = ass.str(), tols = tolss.str(); 137 | Fail("expected: <%s> but was: <%s> (tolerance: <%s>)", es.c_str(), as.c_str(), 138 | tols.c_str()); 139 | } 140 | 141 | inline void Expect::StringEquals(const char* expected, const char* actual) { 142 | if (strcmp(expected, actual) == 0) return; 143 | if (actual == nullptr) { 144 | Fail("expected:\n<\"%s\">\nbut was nullptr", expected); 145 | } else { 146 | if (strcmp(expected, actual) == 0) return; 147 | Fail("expected:\n<\"%s\">\nbut was:\n<\"%s\">", expected, actual); 148 | } 149 | } 150 | 151 | inline void Expect::IsSubstring(const char* needle, const char* haystack) { 152 | if (strstr(haystack, needle) != nullptr) return; 153 | Fail("expected <\"%s\"> to be a substring of <\"%s\">", needle, haystack); 154 | } 155 | 156 | inline void Expect::IsNotSubstring(const char* needle, const char* haystack) { 157 | if (strstr(haystack, needle) == nullptr) return; 158 | Fail("expected <\"%s\"> to not be a substring of <\"%s\">", needle, haystack); 159 | } 160 | 161 | template 162 | void Expect::LessThan(const E& left, const A& right) { 163 | if (left < right) return; 164 | std::ostringstream ess, ass; 165 | ess << left; 166 | ass << right; 167 | std::string es = ess.str(), as = ass.str(); 168 | Fail("expected: %s < %s", es.c_str(), as.c_str()); 169 | } 170 | 171 | template 172 | void Expect::LessEqual(const E& left, const A& right) { 173 | if (left <= right) return; 174 | std::ostringstream ess, ass; 175 | ess << left; 176 | ass << right; 177 | std::string es = ess.str(), as = ass.str(); 178 | Fail("expected: %s <= %s", es.c_str(), as.c_str()); 179 | } 180 | 181 | template 182 | void Expect::GreaterThan(const E& left, const A& right) { 183 | if (left > right) return; 184 | std::ostringstream ess, ass; 185 | ess << left; 186 | ass << right; 187 | std::string es = ess.str(), as = ass.str(); 188 | Fail("expected: %s > %s", es.c_str(), as.c_str()); 189 | } 190 | 191 | template 192 | void Expect::GreaterEqual(const E& left, const A& right) { 193 | if (left >= right) return; 194 | std::ostringstream ess, ass; 195 | ess << left; 196 | ass << right; 197 | std::string es = ess.str(), as = ass.str(); 198 | Fail("expected: %s >= %s", es.c_str(), as.c_str()); 199 | } 200 | 201 | template 202 | void Expect::NotNull(const T p) { 203 | if (p != NULL) return; 204 | Fail("expected: not NULL, found NULL"); 205 | } 206 | 207 | template 208 | void Expect::Null(const T p) { 209 | if (p == nullptr) return; 210 | Fail("expected: nullptr, found not null pointer"); 211 | } 212 | #endif 213 | 214 | } // namespace dart 215 | 216 | #if defined(_MSC_VER) 217 | #define FATAL(format, ...) \ 218 | dart::Assert(__FILE__, __LINE__).Fail(format, __VA_ARGS__); 219 | #else 220 | #define FATAL(format, ...) \ 221 | dart::Assert(__FILE__, __LINE__).Fail(format, ##__VA_ARGS__); 222 | #endif 223 | 224 | // Leaving old non-varargs versions to avoid having to rewrite all uses. 225 | 226 | #define FATAL1(format, p1) dart::Assert(__FILE__, __LINE__).Fail(format, (p1)) 227 | 228 | #define FATAL2(format, p1, p2) \ 229 | dart::Assert(__FILE__, __LINE__).Fail(format, (p1), (p2)) 230 | 231 | #define FATAL3(format, p1, p2, p3) \ 232 | dart::Assert(__FILE__, __LINE__).Fail(format, (p1), (p2), (p3)) 233 | 234 | #define UNIMPLEMENTED() FATAL("unimplemented code") 235 | 236 | #define UNREACHABLE() FATAL("unreachable code") 237 | 238 | #define OUT_OF_MEMORY() FATAL("Out of memory.") 239 | 240 | #if defined(DEBUG) 241 | // DEBUG binaries use assertions in the code. 242 | // Note: We wrap the if statement in a do-while so that we get a compile 243 | // error if there is no semicolon after ASSERT(condition). This 244 | // ensures that we get the same behavior on DEBUG and RELEASE builds. 245 | 246 | #define ASSERT(cond) \ 247 | do { \ 248 | if (!(cond)) dart::Assert(__FILE__, __LINE__).Fail("expected: %s", #cond); \ 249 | } while (false) 250 | 251 | #define ASSERT_EQUAL(actual, expected) \ 252 | do { \ 253 | if ((expected) != (actual)) { \ 254 | const std::string actual_str = std::to_string(actual); \ 255 | const std::string expected_str = std::to_string(expected); \ 256 | dart::Assert(__FILE__, __LINE__) \ 257 | .Fail("expected \"%s\" = %s, actual \"%s\" = %s", #expected, \ 258 | expected_str.c_str(), #actual, actual_str.c_str()); \ 259 | } \ 260 | } while (false) 261 | 262 | // DEBUG_ASSERT allows identifiers in condition to be undeclared in release 263 | // mode. 264 | #define DEBUG_ASSERT(cond) ASSERT(cond) 265 | 266 | // Returns 'ptr'; useful for initializer lists: 267 | // class Foo { Foo(int* ptr) : ptr_(ASSERT_NOTNULL(ptr)) ... 268 | #define ASSERT_NOTNULL(ptr) dart::Assert(__FILE__, __LINE__).NotNull((ptr)) 269 | 270 | #else // if defined(DEBUG) 271 | 272 | // In order to avoid variable unused warnings for code that only uses 273 | // a variable in an ASSERT or EXPECT, we make sure to use the macro 274 | // argument. 275 | #define ASSERT(condition) \ 276 | do { \ 277 | } while (false && (condition)) 278 | 279 | #define ASSERT_EQUAL(expected, actual) \ 280 | do { \ 281 | } while (false && (expected) != (actual)) 282 | 283 | #define DEBUG_ASSERT(cond) 284 | 285 | #define ASSERT_NOTNULL(ptr) (ptr) 286 | 287 | #endif // if defined(DEBUG) 288 | 289 | #define RELEASE_ASSERT(cond) \ 290 | do { \ 291 | if (!(cond)) dart::Assert(__FILE__, __LINE__).Fail("expected: %s", #cond); \ 292 | } while (false) 293 | 294 | #define COMPILE_ASSERT(expr) static_assert(expr, "") 295 | 296 | #if defined(TESTING) 297 | 298 | // EXPECT and FAIL are equivalent to ASSERT and FATAL except that they do not 299 | // cause early termination of the unit test. This allows testing to proceed 300 | // further to be able to report other failures before reporting the overall 301 | // unit tests as failing. 302 | 303 | #define EXPECT(condition) \ 304 | if (!(condition)) { \ 305 | dart::Expect(__FILE__, __LINE__).Fail("expected: %s", #condition); \ 306 | } 307 | 308 | #define EXPECT_EQ(expected, actual) \ 309 | dart::Expect(__FILE__, __LINE__).Equals((expected), (actual)) 310 | 311 | #define EXPECT_NE(not_expected, actual) \ 312 | dart::Expect(__FILE__, __LINE__).NotEquals((not_expected), (actual)) 313 | 314 | #define EXPECT_FLOAT_EQ(expected, actual, tol) \ 315 | dart::Expect(__FILE__, __LINE__).FloatEquals((expected), (actual), (tol)) 316 | 317 | #define EXPECT_STREQ(expected, actual) \ 318 | dart::Expect(__FILE__, __LINE__).StringEquals((expected), (actual)) 319 | 320 | #define EXPECT_SUBSTRING(needle, haystack) \ 321 | dart::Expect(__FILE__, __LINE__).IsSubstring((needle), (haystack)) 322 | 323 | #define EXPECT_NOTSUBSTRING(needle, haystack) \ 324 | dart::Expect(__FILE__, __LINE__).IsNotSubstring((needle), (haystack)) 325 | 326 | #define EXPECT_LT(left, right) \ 327 | dart::Expect(__FILE__, __LINE__).LessThan((left), (right)) 328 | 329 | #define EXPECT_LE(left, right) \ 330 | dart::Expect(__FILE__, __LINE__).LessEqual((left), (right)) 331 | 332 | #define EXPECT_GT(left, right) \ 333 | dart::Expect(__FILE__, __LINE__).GreaterThan((left), (right)) 334 | 335 | #define EXPECT_GE(left, right) \ 336 | dart::Expect(__FILE__, __LINE__).GreaterEqual((left), (right)) 337 | 338 | #define EXPECT_NOTNULL(ptr) dart::Expect(__FILE__, __LINE__).NotNull((ptr)) 339 | 340 | #define EXPECT_NULLPTR(ptr) dart::Expect(__FILE__, __LINE__).Null((ptr)) 341 | 342 | #define FAIL(error) dart::Expect(__FILE__, __LINE__).Fail("%s", error) 343 | 344 | #define FAIL1(format, p1) dart::Expect(__FILE__, __LINE__).Fail(format, (p1)) 345 | 346 | #define FAIL2(format, p1, p2) \ 347 | dart::Expect(__FILE__, __LINE__).Fail(format, (p1), (p2)) 348 | 349 | #endif // defined(TESTING) 350 | 351 | #endif // RUNTIME_PLATFORM_ASSERT_H_ 352 | -------------------------------------------------------------------------------- /dart/platform/atomic.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | #ifndef RUNTIME_PLATFORM_ATOMIC_H_ 6 | #define RUNTIME_PLATFORM_ATOMIC_H_ 7 | 8 | #include 9 | 10 | namespace dart { 11 | 12 | // Like std::atomic, but operations default to relaxed ordering instead of 13 | // sequential consistency. 14 | template 15 | class RelaxedAtomic { 16 | public: 17 | constexpr RelaxedAtomic() : value_() {} 18 | constexpr RelaxedAtomic(T arg) : value_(arg) {} // NOLINT 19 | RelaxedAtomic(const RelaxedAtomic& arg) : value_(arg) {} // NOLINT 20 | 21 | T load(std::memory_order order = std::memory_order_relaxed) const { 22 | return value_.load(order); 23 | } 24 | void store(T arg, std::memory_order order = std::memory_order_relaxed) { 25 | value_.store(arg, order); 26 | } 27 | 28 | T fetch_add(T arg, std::memory_order order = std::memory_order_relaxed) { 29 | return value_.fetch_add(arg, order); 30 | } 31 | T fetch_sub(T arg, std::memory_order order = std::memory_order_relaxed) { 32 | return value_.fetch_sub(arg, order); 33 | } 34 | T fetch_or(T arg, std::memory_order order = std::memory_order_relaxed) { 35 | return value_.fetch_or(arg, order); 36 | } 37 | T fetch_and(T arg, std::memory_order order = std::memory_order_relaxed) { 38 | return value_.fetch_and(arg, order); 39 | } 40 | 41 | bool compare_exchange_weak( 42 | T& expected, // NOLINT 43 | T desired, 44 | std::memory_order order = std::memory_order_relaxed) { 45 | return value_.compare_exchange_weak(expected, desired, order, order); 46 | } 47 | bool compare_exchange_strong( 48 | T& expected, // NOLINT 49 | T desired, 50 | std::memory_order order = std::memory_order_relaxed) { 51 | return value_.compare_exchange_strong(expected, desired, order, order); 52 | } 53 | 54 | operator T() const { return load(); } 55 | T operator=(T arg) { 56 | store(arg); 57 | return arg; 58 | } 59 | T operator=(const RelaxedAtomic& arg) { 60 | T loaded_once = arg; 61 | store(loaded_once); 62 | return loaded_once; 63 | } 64 | T operator+=(T arg) { return fetch_add(arg) + arg; } 65 | T operator-=(T arg) { return fetch_sub(arg) - arg; } 66 | 67 | private: 68 | std::atomic value_; 69 | }; 70 | 71 | // Like std::atomic, but operations default to acquire for load, release for 72 | // stores, and acquire-release for read-and-updates. 73 | template 74 | class AcqRelAtomic { 75 | public: 76 | constexpr AcqRelAtomic() : value_() {} 77 | constexpr AcqRelAtomic(T arg) : value_(arg) {} // NOLINT 78 | AcqRelAtomic(const AcqRelAtomic& arg) = delete; 79 | 80 | T load(std::memory_order order = std::memory_order_acquire) const { 81 | return value_.load(order); 82 | } 83 | void store(T arg, std::memory_order order = std::memory_order_release) { 84 | value_.store(arg, order); 85 | } 86 | 87 | T fetch_add(T arg, std::memory_order order = std::memory_order_acq_rel) { 88 | return value_.fetch_add(arg, order); 89 | } 90 | T fetch_sub(T arg, std::memory_order order = std::memory_order_acq_rel) { 91 | return value_.fetch_sub(arg, order); 92 | } 93 | T fetch_or(T arg, std::memory_order order = std::memory_order_acq_rel) { 94 | return value_.fetch_or(arg, order); 95 | } 96 | T fetch_and(T arg, std::memory_order order = std::memory_order_acq_rel) { 97 | return value_.fetch_and(arg, order); 98 | } 99 | 100 | bool compare_exchange_weak( 101 | T& expected, // NOLINT 102 | T desired, 103 | std::memory_order success_order = std::memory_order_acq_rel, 104 | std::memory_order failure_order = std::memory_order_seq_cst) { 105 | return value_.compare_exchange_weak(expected, desired, success_order, 106 | failure_order); 107 | } 108 | bool compare_exchange_strong( 109 | T& expected, // NOLINT 110 | T desired, 111 | std::memory_order success_order = std::memory_order_acq_rel, 112 | std::memory_order failure_order = std::memory_order_seq_cst) { 113 | return value_.compare_exchange_strong(expected, desired, success_order, 114 | failure_order); 115 | } 116 | 117 | // Require explicit loads and stores. 118 | operator T() const = delete; 119 | T operator=(T arg) = delete; 120 | T operator=(const AcqRelAtomic& arg) = delete; 121 | T operator+=(T arg) = delete; 122 | T operator-=(T arg) = delete; 123 | 124 | private: 125 | std::atomic value_; 126 | }; 127 | 128 | } // namespace dart 129 | 130 | #endif // RUNTIME_PLATFORM_ATOMIC_H_ 131 | -------------------------------------------------------------------------------- /dart/platform/floating_point.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | #ifndef RUNTIME_PLATFORM_FLOATING_POINT_H_ 6 | #define RUNTIME_PLATFORM_FLOATING_POINT_H_ 7 | 8 | #include 9 | 10 | inline double fmod_ieee(double x, double y) { 11 | return fmod(x, y); 12 | } 13 | inline double atan2_ieee(double y, double x) { 14 | return atan2(y, x); 15 | } 16 | 17 | #endif // RUNTIME_PLATFORM_FLOATING_POINT_H_ 18 | -------------------------------------------------------------------------------- /dart/platform/floating_point_win.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | #ifndef RUNTIME_PLATFORM_FLOATING_POINT_WIN_H_ 6 | #define RUNTIME_PLATFORM_FLOATING_POINT_WIN_H_ 7 | 8 | double atan2_ieee(double x, double y); 9 | double fmod_ieee(double x, double y); 10 | 11 | #endif // RUNTIME_PLATFORM_FLOATING_POINT_WIN_H_ 12 | -------------------------------------------------------------------------------- /dart/platform/growable_array.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | // Defines growable array classes, that differ where they are allocated: 5 | // - GrowableArray: allocated on stack. 6 | // - ZoneGrowableArray: allocated in the zone. 7 | // - MallocGrowableArray: allocates using malloc/realloc; free is only called 8 | // at destruction. 9 | 10 | #ifndef RUNTIME_PLATFORM_GROWABLE_ARRAY_H_ 11 | #define RUNTIME_PLATFORM_GROWABLE_ARRAY_H_ 12 | 13 | #include "platform/allocation.h" 14 | #include "platform/utils.h" 15 | 16 | namespace dart { 17 | 18 | template 19 | class BaseGrowableArray : public B { 20 | public: 21 | explicit BaseGrowableArray(Allocator* allocator) 22 | : length_(0), capacity_(0), data_(NULL), allocator_(allocator) {} 23 | 24 | BaseGrowableArray(intptr_t initial_capacity, Allocator* allocator) 25 | : length_(0), capacity_(0), data_(NULL), allocator_(allocator) { 26 | if (initial_capacity > 0) { 27 | capacity_ = Utils::RoundUpToPowerOfTwo(initial_capacity); 28 | data_ = allocator_->template Alloc(capacity_); 29 | } 30 | } 31 | 32 | BaseGrowableArray(BaseGrowableArray&& other) 33 | : length_(other.length_), 34 | capacity_(other.capacity_), 35 | data_(other.data_), 36 | allocator_(other.allocator_) { 37 | other.length_ = 0; 38 | other.capacity_ = 0; 39 | other.data_ = NULL; 40 | } 41 | 42 | ~BaseGrowableArray() { allocator_->template Free(data_, capacity_); } 43 | 44 | BaseGrowableArray& operator=(BaseGrowableArray&& other) { 45 | intptr_t temp = other.length_; 46 | other.length_ = length_; 47 | length_ = temp; 48 | temp = other.capacity_; 49 | other.capacity_ = capacity_; 50 | capacity_ = temp; 51 | T* temp_data = other.data_; 52 | other.data_ = data_; 53 | data_ = temp_data; 54 | Allocator* temp_allocator = other.allocator_; 55 | other.allocator_ = allocator_; 56 | allocator_ = temp_allocator; 57 | return *this; 58 | } 59 | 60 | intptr_t length() const { return length_; } 61 | T* data() const { return data_; } 62 | bool is_empty() const { return length_ == 0; } 63 | 64 | void TruncateTo(intptr_t length) { 65 | ASSERT(length_ >= length); 66 | length_ = length; 67 | } 68 | 69 | void Add(const T& value) { 70 | Resize(length() + 1); 71 | Last() = value; 72 | } 73 | 74 | T& RemoveLast() { 75 | ASSERT(length_ > 0); 76 | T& result = operator[](length_ - 1); 77 | length_--; 78 | return result; 79 | } 80 | 81 | T& operator[](intptr_t index) const { 82 | ASSERT(0 <= index); 83 | ASSERT(index < length_); 84 | ASSERT(length_ <= capacity_); 85 | return data_[index]; 86 | } 87 | 88 | void FillWith(const T& value, intptr_t start, intptr_t length) { 89 | ASSERT(start >= 0); 90 | ASSERT(length >= 0); 91 | ASSERT(start <= length_); 92 | 93 | Resize(start + length); 94 | for (intptr_t i = 0; i < length; ++i) { 95 | data_[start + i] = value; 96 | } 97 | } 98 | 99 | void EnsureLength(intptr_t new_length, const T& default_value) { 100 | const intptr_t old_length = length_; 101 | if (old_length < new_length) { 102 | Resize(new_length); 103 | for (intptr_t i = old_length; i < new_length; ++i) { 104 | (*this)[i] = default_value; 105 | } 106 | } 107 | } 108 | 109 | const T& At(intptr_t index) const { return operator[](index); } 110 | 111 | T& Last() const { 112 | ASSERT(length_ > 0); 113 | return operator[](length_ - 1); 114 | } 115 | 116 | void AddArray(const BaseGrowableArray& src) { 117 | for (intptr_t i = 0; i < src.length(); i++) { 118 | Add(src[i]); 119 | } 120 | } 121 | 122 | void Clear() { length_ = 0; } 123 | 124 | void InsertAt(intptr_t idx, const T& value) { 125 | Resize(length() + 1); 126 | for (intptr_t i = length_ - 2; i >= idx; i--) { 127 | data_[i + 1] = data_[i]; 128 | } 129 | data_[idx] = value; 130 | } 131 | 132 | void Reverse() { 133 | for (intptr_t i = 0; i < length_ / 2; i++) { 134 | const intptr_t j = length_ - 1 - i; 135 | T temp = data_[i]; 136 | data_[i] = data_[j]; 137 | data_[j] = temp; 138 | } 139 | } 140 | 141 | // Swap entries |i| and |j|. 142 | void Swap(intptr_t i, intptr_t j) { 143 | ASSERT(i >= 0); 144 | ASSERT(j >= 0); 145 | ASSERT(i < length_); 146 | ASSERT(j < length_); 147 | T temp = data_[i]; 148 | data_[i] = data_[j]; 149 | data_[j] = temp; 150 | } 151 | 152 | // NOTE: Does not preserve array order. 153 | void RemoveAt(intptr_t i) { 154 | ASSERT(i >= 0); 155 | ASSERT(i < length_); 156 | intptr_t last = length_ - 1; 157 | if (i < last) { 158 | Swap(i, last); 159 | } 160 | RemoveLast(); 161 | } 162 | 163 | // Preserves array order. 164 | void EraseAt(intptr_t idx) { 165 | ASSERT(idx >= 0); 166 | ASSERT(idx < length_); 167 | for (intptr_t i = idx; i < length_ - 1; i++) { 168 | data_[i] = data_[i + 1]; 169 | } 170 | RemoveLast(); 171 | } 172 | 173 | // The content is uninitialized after calling it. 174 | void SetLength(intptr_t new_length); 175 | 176 | // Sort the array in place. 177 | inline void Sort(int compare(const T*, const T*)); 178 | 179 | void StealBuffer(T** buffer, intptr_t* length) { 180 | *buffer = data_; 181 | *length = length_; 182 | data_ = NULL; 183 | length_ = 0; 184 | capacity_ = 0; 185 | } 186 | 187 | T* begin() { return &data_[0]; } 188 | const T* begin() const { return &data_[0]; } 189 | 190 | T* end() { return &data_[length_]; } 191 | const T* end() const { return &data_[length_]; } 192 | 193 | private: 194 | intptr_t length_; 195 | intptr_t capacity_; 196 | T* data_; 197 | Allocator* allocator_; // Used to (re)allocate the array. 198 | 199 | // Used for growing the array. 200 | void Resize(intptr_t new_length); 201 | 202 | DISALLOW_COPY_AND_ASSIGN(BaseGrowableArray); 203 | }; 204 | 205 | template 206 | inline void BaseGrowableArray::Sort(int compare(const T*, 207 | const T*)) { 208 | // Avoid calling qsort with a null array. 209 | if (length_ == 0) return; 210 | 211 | typedef int (*CompareFunction)(const void*, const void*); 212 | qsort(data_, length_, sizeof(T), reinterpret_cast(compare)); 213 | } 214 | 215 | template 216 | void BaseGrowableArray::Resize(intptr_t new_length) { 217 | if (new_length > capacity_) { 218 | intptr_t new_capacity = Utils::RoundUpToPowerOfTwo(new_length); 219 | T* new_data = 220 | allocator_->template Realloc(data_, capacity_, new_capacity); 221 | ASSERT(new_data != NULL); 222 | data_ = new_data; 223 | capacity_ = new_capacity; 224 | } 225 | length_ = new_length; 226 | } 227 | 228 | template 229 | void BaseGrowableArray::SetLength(intptr_t new_length) { 230 | if (new_length > capacity_) { 231 | T* new_data = allocator_->template Alloc(new_length); 232 | ASSERT(new_data != NULL); 233 | data_ = new_data; 234 | capacity_ = new_length; 235 | } 236 | length_ = new_length; 237 | } 238 | 239 | class Malloc : public AllStatic { 240 | public: 241 | template 242 | static inline T* Alloc(intptr_t len) { 243 | return reinterpret_cast(dart::malloc(len * sizeof(T))); 244 | } 245 | 246 | template 247 | static inline T* Realloc(T* old_array, intptr_t old_len, intptr_t new_len) { 248 | return reinterpret_cast(dart::realloc(old_array, new_len * sizeof(T))); 249 | } 250 | 251 | template 252 | static inline void Free(T* old_array, intptr_t old_len) { 253 | free(old_array); 254 | } 255 | }; 256 | 257 | template 258 | class MallocGrowableArray 259 | : public BaseGrowableArray { 260 | public: 261 | explicit MallocGrowableArray(intptr_t initial_capacity) 262 | : BaseGrowableArray(initial_capacity, NULL) {} 263 | MallocGrowableArray() : BaseGrowableArray(NULL) {} 264 | }; 265 | 266 | } // namespace dart 267 | 268 | #endif // RUNTIME_PLATFORM_GROWABLE_ARRAY_H_ 269 | -------------------------------------------------------------------------------- /dart/platform/hashmap.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | #ifndef RUNTIME_PLATFORM_HASHMAP_H_ 6 | #define RUNTIME_PLATFORM_HASHMAP_H_ 7 | 8 | #include "platform/globals.h" 9 | 10 | namespace dart { 11 | 12 | class SimpleHashMap { 13 | public: 14 | typedef bool (*MatchFun)(void* key1, void* key2); 15 | 16 | typedef void (*ClearFun)(void* value); 17 | 18 | // initial_capacity is the size of the initial hash map; 19 | // it must be a power of 2 (and thus must not be 0). 20 | SimpleHashMap(MatchFun match, uint32_t initial_capacity); 21 | 22 | ~SimpleHashMap(); 23 | 24 | static bool SamePointerValue(void* key1, void* key2) { return key1 == key2; } 25 | 26 | static uint32_t StringHash(char* key) { 27 | uint32_t hash_ = 0; 28 | if (key == NULL) return hash_; 29 | int len = strlen(key); 30 | for (int i = 0; i < len; i++) { 31 | hash_ += key[i]; 32 | hash_ += hash_ << 10; 33 | hash_ ^= hash_ >> 6; 34 | } 35 | hash_ += hash_ << 3; 36 | hash_ ^= hash_ >> 11; 37 | hash_ += hash_ << 15; 38 | return hash_ == 0 ? 1 : hash_; 39 | } 40 | 41 | static bool SameStringValue(void* key1, void* key2) { 42 | return strcmp(reinterpret_cast(key1), 43 | reinterpret_cast(key2)) == 0; 44 | } 45 | 46 | // SimpleHashMap entries are (key, value, hash) triplets. 47 | // Some clients may not need to use the value slot 48 | // (e.g. implementers of sets, where the key is the value). 49 | struct Entry { 50 | Entry() : key(NULL), value(NULL), hash(0) {} 51 | void* key; 52 | void* value; 53 | uint32_t hash; // The full hash value for key. 54 | }; 55 | 56 | // If an entry with matching key is found, Lookup() 57 | // returns that entry. If no matching entry is found, 58 | // but insert is set, a new entry is inserted with 59 | // corresponding key, key hash, and NULL value. 60 | // Otherwise, NULL is returned. 61 | Entry* Lookup(void* key, uint32_t hash, bool insert); 62 | 63 | // Removes the entry with matching key. 64 | // 65 | // WARNING: This method cannot be called while iterating a `SimpleHashMap` 66 | // otherwise the iteration might step over elements! 67 | void Remove(void* key, uint32_t hash); 68 | 69 | // Empties the hash map (occupancy() == 0), and calls the function 'clear' on 70 | // each of the values if given. 71 | void Clear(ClearFun clear = NULL); 72 | 73 | // The number of entries stored in the table. 74 | intptr_t size() const { return occupancy_; } 75 | 76 | // The capacity of the table. The implementation 77 | // makes sure that occupancy is at most 80% of 78 | // the table capacity. 79 | intptr_t capacity() const { return capacity_; } 80 | 81 | // Iteration 82 | // 83 | // for (Entry* p = map.Start(); p != NULL; p = map.Next(p)) { 84 | // ... 85 | // } 86 | // 87 | // If entries are inserted during iteration, the effect of 88 | // calling Next() is undefined. 89 | Entry* Start() const; 90 | Entry* Next(Entry* p) const; 91 | 92 | private: 93 | MatchFun match_; 94 | Entry* map_; 95 | uint32_t capacity_; 96 | uint32_t occupancy_; 97 | 98 | Entry* map_end() const { return map_ + capacity_; } 99 | Entry* Probe(void* key, uint32_t hash); 100 | void Initialize(uint32_t capacity); 101 | void Resize(); 102 | 103 | friend class IntSet; // From hashmap_test.cc 104 | DISALLOW_COPY_AND_ASSIGN(SimpleHashMap); 105 | }; 106 | 107 | } // namespace dart 108 | 109 | #endif // RUNTIME_PLATFORM_HASHMAP_H_ 110 | -------------------------------------------------------------------------------- /dart/platform/memory_sanitizer.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | #ifndef RUNTIME_PLATFORM_MEMORY_SANITIZER_H_ 6 | #define RUNTIME_PLATFORM_MEMORY_SANITIZER_H_ 7 | 8 | #include "platform/globals.h" 9 | 10 | // Allow the use of Msan (MemorySanitizer). This is needed as Msan needs to be 11 | // told about areas that are initialized by generated code. 12 | #if defined(__has_feature) 13 | #if __has_feature(memory_sanitizer) 14 | extern "C" void __msan_poison(const volatile void*, size_t); 15 | extern "C" void __msan_unpoison(const volatile void*, size_t); 16 | extern "C" void __msan_check_mem_is_initialized(const volatile void*, size_t); 17 | #define MSAN_POISON(ptr, len) __msan_poison(ptr, len) 18 | #define MSAN_UNPOISON(ptr, len) __msan_unpoison(ptr, len) 19 | #define MSAN_CHECK_INITIALIZED(ptr, len) \ 20 | __msan_check_mem_is_initialized(ptr, len) 21 | #define NO_SANITIZE_MEMORY __attribute__((no_sanitize("memory"))) 22 | #else // __has_feature(memory_sanitizer) 23 | #define MSAN_POISON(ptr, len) \ 24 | do { \ 25 | } while (false && (ptr) == 0 && (len) == 0) 26 | #define MSAN_UNPOISON(ptr, len) \ 27 | do { \ 28 | } while (false && (ptr) == 0 && (len) == 0) 29 | #define MSAN_CHECK_INITIALIZED(ptr, len) \ 30 | do { \ 31 | } while (false && (ptr) == 0 && (len) == 0) 32 | #define NO_SANITIZE_MEMORY 33 | #endif // __has_feature(memory_sanitizer) 34 | #else // defined(__has_feature) 35 | #define MSAN_POISON(ptr, len) \ 36 | do { \ 37 | } while (false && (ptr) == 0 && (len) == 0) 38 | #define MSAN_UNPOISON(ptr, len) \ 39 | do { \ 40 | } while (false && (ptr) == 0 && (len) == 0) 41 | #define MSAN_CHECK_INITIALIZED(ptr, len) \ 42 | do { \ 43 | } while (false && (ptr) == 0 && (len) == 0) 44 | #define NO_SANITIZE_MEMORY 45 | #endif // defined(__has_feature) 46 | 47 | #endif // RUNTIME_PLATFORM_MEMORY_SANITIZER_H_ 48 | -------------------------------------------------------------------------------- /dart/platform/priority_queue.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | #ifndef RUNTIME_PLATFORM_PRIORITY_QUEUE_H_ 6 | #define RUNTIME_PLATFORM_PRIORITY_QUEUE_H_ 7 | 8 | #include "platform/assert.h" 9 | #include "platform/globals.h" 10 | #include "platform/hashmap.h" 11 | #include "platform/utils.h" 12 | 13 | namespace dart { 14 | 15 | // A min-priority queue with deletion support. 16 | // 17 | // The [PriorityQueue] allows insertion of entries with a priority [P] and a 18 | // value [V]. The minimum element can be queried in O(1) time. 19 | // Insertion/Deletion operations have O(N) time. 20 | // 21 | // In addition to the normal insert/minimum/remove-minimum operations this 22 | // priority queue allows deletion-by-value. We have therefore an invariant 23 | // is that the value must be unique amongst all entries. 24 | template 25 | class PriorityQueue { 26 | public: 27 | static const intptr_t kMinimumSize = 16; 28 | 29 | struct Entry { 30 | P priority; 31 | V value; 32 | }; 33 | 34 | PriorityQueue() : hashmap_(&MatchFun, kMinimumSize) { 35 | min_heap_size_ = kMinimumSize; 36 | min_heap_ = 37 | reinterpret_cast(malloc(sizeof(Entry) * min_heap_size_)); 38 | if (min_heap_ == nullptr) FATAL("Cannot allocate memory."); 39 | size_ = 0; 40 | } 41 | 42 | ~PriorityQueue() { free(min_heap_); } 43 | 44 | // Whether the queue is empty. 45 | bool IsEmpty() const { return size_ == 0; } 46 | 47 | // Inserts a new entry with [priority] and [value], requires there to be no 48 | // existing entry with given [value]. 49 | void Insert(const P& priority, const V& value) { 50 | ASSERT(!ContainsValue(value)); 51 | 52 | if (size_ == min_heap_size_) { 53 | Resize(min_heap_size_ << 1); 54 | } 55 | 56 | Set(size_, {priority, value}); 57 | BubbleUp(size_); 58 | 59 | size_++; 60 | } 61 | 62 | // Returns a reference to the minimum entry. 63 | // 64 | // The caller can access it's priority and value in read-only mode only. 65 | const Entry& Minimum() const { 66 | ASSERT(!IsEmpty()); 67 | return min_heap_[0]; 68 | } 69 | 70 | // Removes the minimum entry. 71 | void RemoveMinimum() { 72 | ASSERT(!IsEmpty()); 73 | RemoveAt(0); 74 | } 75 | 76 | // Removes an existing entry with the given [value]. 77 | // 78 | // Returns true if such an entry was removed. 79 | bool RemoveByValue(const V& value) { 80 | auto entry = FindMapEntry(value); 81 | if (entry != nullptr) { 82 | const intptr_t offset = ValueOfMapEntry(entry); 83 | RemoveAt(offset); 84 | 85 | ASSERT(hashmap_.size() == size_); 86 | return true; 87 | } 88 | return false; 89 | } 90 | 91 | // Whether the priority queue contains an entry with the given [value]. 92 | bool ContainsValue(const V& value) { return FindMapEntry(value) != nullptr; } 93 | 94 | // Changes the priority of an existing entry with given [value] or adds a 95 | // new entry. 96 | bool InsertOrChangePriority(const P& priority, const V& value) { 97 | auto map_entry = FindMapEntry(value); 98 | if (map_entry == nullptr) { 99 | Insert(priority, value); 100 | return true; 101 | } 102 | 103 | const intptr_t offset = ValueOfMapEntry(map_entry); 104 | ASSERT(offset < size_); 105 | 106 | Entry& entry = min_heap_[offset]; 107 | entry.priority = priority; 108 | if (offset == 0) { 109 | BubbleDown(offset); 110 | } else { 111 | intptr_t parent = (offset - 1) / 2; 112 | intptr_t diff = entry.priority - min_heap_[parent].priority; 113 | if (diff < 0) { 114 | BubbleUp(offset); 115 | } else if (diff > 0) { 116 | BubbleDown(offset); 117 | } 118 | } 119 | return false; 120 | } 121 | 122 | #ifdef TESTING 123 | intptr_t min_heap_size() { return min_heap_size_; } 124 | #endif // TESTING 125 | 126 | private: 127 | // Utility functions dealing with the SimpleHashMap interface. 128 | static bool MatchFun(void* key1, void* key2) { return key1 == key2; } 129 | 130 | SimpleHashMap::Entry* FindMapEntry(const V& key, bool insert = false) { 131 | return hashmap_.Lookup(CastKey(key), HashKey(key), insert); 132 | } 133 | void RemoveMapEntry(const V& key) { 134 | ASSERT(FindMapEntry(key) != nullptr); 135 | hashmap_.Remove(CastKey(key), HashKey(key)); 136 | } 137 | void SetMapEntry(const V& key, intptr_t value) { 138 | FindMapEntry(key, /*insert=*/true)->value = reinterpret_cast(value); 139 | } 140 | static uint32_t HashKey(const V& key) { 141 | return static_cast(reinterpret_cast(CastKey(key))); 142 | } 143 | static intptr_t ValueOfMapEntry(SimpleHashMap::Entry* entry) { 144 | return reinterpret_cast(entry->value); 145 | } 146 | static void* CastKey(const V& key) { 147 | return reinterpret_cast((const_cast(key))); 148 | } 149 | 150 | void RemoveAt(intptr_t offset) { 151 | ASSERT(offset < size_); 152 | 153 | size_--; 154 | 155 | if (offset == size_) { 156 | RemoveMapEntry(min_heap_[offset].value); 157 | } else { 158 | Replace(offset, size_); 159 | BubbleDown(offset); 160 | } 161 | 162 | if (size_ <= (min_heap_size_ >> 2) && 163 | kMinimumSize <= (min_heap_size_ >> 1)) { 164 | Resize(min_heap_size_ >> 1); 165 | } 166 | } 167 | 168 | void BubbleUp(intptr_t offset) { 169 | while (true) { 170 | if (offset == 0) return; 171 | 172 | intptr_t parent = (offset - 1) / 2; 173 | if (min_heap_[parent].priority > min_heap_[offset].priority) { 174 | Swap(parent, offset); 175 | } 176 | offset = parent; 177 | } 178 | } 179 | 180 | void BubbleDown(intptr_t offset) { 181 | while (true) { 182 | intptr_t left_child_index = 2 * offset + 1; 183 | bool has_left_child = left_child_index < size_; 184 | 185 | if (!has_left_child) return; 186 | 187 | intptr_t smallest_index = offset; 188 | 189 | if (min_heap_[left_child_index].priority < min_heap_[offset].priority) { 190 | smallest_index = left_child_index; 191 | } 192 | 193 | intptr_t right_child_index = left_child_index + 1; 194 | bool has_right_child = right_child_index < size_; 195 | if (has_right_child) { 196 | if (min_heap_[right_child_index].priority < 197 | min_heap_[smallest_index].priority) { 198 | smallest_index = right_child_index; 199 | } 200 | } 201 | 202 | if (offset == smallest_index) { 203 | return; 204 | } 205 | 206 | Swap(offset, smallest_index); 207 | offset = smallest_index; 208 | } 209 | } 210 | 211 | void Set(intptr_t offset1, const Entry& entry) { 212 | min_heap_[offset1] = entry; 213 | SetMapEntry(entry.value, offset1); 214 | } 215 | 216 | void Swap(intptr_t offset1, intptr_t offset2) { 217 | Entry temp = min_heap_[offset1]; 218 | min_heap_[offset1] = min_heap_[offset2]; 219 | min_heap_[offset2] = temp; 220 | 221 | SetMapEntry(min_heap_[offset1].value, offset1); 222 | SetMapEntry(min_heap_[offset2].value, offset2); 223 | } 224 | 225 | void Replace(intptr_t index, intptr_t with_other) { 226 | RemoveMapEntry(min_heap_[index].value); 227 | 228 | const Entry& entry = min_heap_[with_other]; 229 | SetMapEntry(entry.value, index); 230 | min_heap_[index] = entry; 231 | } 232 | 233 | void Resize(intptr_t new_min_heap_size) { 234 | ASSERT(size_ < new_min_heap_size); 235 | ASSERT(new_min_heap_size != min_heap_size_); 236 | 237 | Entry* new_backing = reinterpret_cast( 238 | realloc(min_heap_, sizeof(Entry) * new_min_heap_size)); 239 | 240 | if (new_backing == NULL) FATAL("Cannot allocate memory."); 241 | 242 | min_heap_ = new_backing; 243 | min_heap_size_ = new_min_heap_size; 244 | } 245 | 246 | // The array is representing a tree structure with guaranteed log(n) height. 247 | // It has the property that the value of node N is always equal or smaller 248 | // than the value of N's children. Furthermore it is a "dense" tree in the 249 | // sense that all rows/layers of the tree are fully occupied except the last 250 | // one. The way to represent such "dense" trees is via an array that allows 251 | // finding left/right children by <2*index+1><2*index+2> and the parent by 252 | // <(index-1)/2>. 253 | // 254 | // Insertion operations can be performed by adding one more entry at the end 255 | // (bottom right) and bubbling it up until the tree invariant is satisfied 256 | // again. 257 | // 258 | // Deletion operations can be performed by replacing the minimum element 259 | // (first entry) by the last entry (bottom right) and bubbling it down until 260 | // the tree invariant is satisified again. 261 | Entry* min_heap_; 262 | intptr_t min_heap_size_; 263 | intptr_t size_; 264 | SimpleHashMap hashmap_; 265 | }; 266 | 267 | } // namespace dart 268 | 269 | #endif // RUNTIME_PLATFORM_PRIORITY_QUEUE_H_ 270 | -------------------------------------------------------------------------------- /dart/platform/utils.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | #ifndef RUNTIME_PLATFORM_UTILS_H_ 6 | #define RUNTIME_PLATFORM_UTILS_H_ 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | #include "platform/assert.h" 13 | #include "platform/globals.h" 14 | 15 | namespace dart { 16 | 17 | class Utils { 18 | public: 19 | template 20 | static inline T Minimum(T x, T y) { 21 | return x < y ? x : y; 22 | } 23 | 24 | template 25 | static constexpr inline T Maximum(T x, T y) { 26 | return x > y ? x : y; 27 | } 28 | 29 | // Calculates absolute value of a given signed integer. 30 | // `x` must not be equal to minimum value representable by `T` 31 | // as its absolute value is out of range. 32 | template 33 | static inline T Abs(T x) { 34 | // Note: as a general rule, it is not OK to use STL in Dart VM. 35 | // However, std::numeric_limits::min() and max() are harmless 36 | // and worthwhile exception from this rule. 37 | ASSERT(x != std::numeric_limits::min()); 38 | if (x < 0) return -x; 39 | return x; 40 | } 41 | 42 | // Calculates absolute value of a given signed integer with saturation. 43 | // If `x` equals to minimum value representable by `T`, then 44 | // absolute value is saturated to the maximum value representable by `T`. 45 | template 46 | static inline T AbsWithSaturation(T x) { 47 | if (x < 0) { 48 | // Note: as a general rule, it is not OK to use STL in Dart VM. 49 | // However, std::numeric_limits::min() and max() are harmless 50 | // and worthwhile exception from this rule. 51 | if (x == std::numeric_limits::min()) { 52 | return std::numeric_limits::max(); 53 | } 54 | return -x; 55 | } 56 | return x; 57 | } 58 | 59 | template 60 | static constexpr bool IsPowerOfTwo(T x) { 61 | return ((x & (x - 1)) == 0) && (x != 0); 62 | } 63 | 64 | template 65 | static inline int ShiftForPowerOfTwo(T x) { 66 | ASSERT(IsPowerOfTwo(x)); 67 | int num_shifts = 0; 68 | while (x > 1) { 69 | num_shifts++; 70 | x = x >> 1; 71 | } 72 | return num_shifts; 73 | } 74 | 75 | template 76 | static constexpr bool IsAligned(T x, intptr_t n) { 77 | assert(IsPowerOfTwo(n)); 78 | return (x & (n - 1)) == 0; 79 | } 80 | 81 | template 82 | static constexpr bool IsAligned(T* x, intptr_t n) { 83 | return IsAligned(reinterpret_cast(x), n); 84 | } 85 | 86 | template 87 | static inline T RoundDown(T x, intptr_t n) { 88 | ASSERT(IsPowerOfTwo(n)); 89 | return (x & -n); 90 | } 91 | 92 | template 93 | static inline T* RoundDown(T* x, intptr_t n) { 94 | return reinterpret_cast(RoundDown(reinterpret_cast(x), n)); 95 | } 96 | 97 | template 98 | static inline T RoundUp(T x, intptr_t n) { 99 | return RoundDown(x + n - 1, n); 100 | } 101 | 102 | template 103 | static inline T* RoundUp(T* x, intptr_t n) { 104 | return reinterpret_cast(RoundUp(reinterpret_cast(x), n)); 105 | } 106 | 107 | static uintptr_t RoundUpToPowerOfTwo(uintptr_t x); 108 | 109 | static int CountOneBits64(uint64_t x); 110 | static int CountOneBits32(uint32_t x); 111 | 112 | static int CountOneBitsWord(uword x) { 113 | #ifdef ARCH_IS_64_BIT 114 | return CountOneBits64(x); 115 | #else 116 | return CountOneBits32(x); 117 | #endif 118 | } 119 | 120 | static int HighestBit(int64_t v); 121 | 122 | static int BitLength(int64_t value) { 123 | // Flip bits if negative (-1 becomes 0). 124 | value ^= value >> (8 * sizeof(value) - 1); 125 | return (value == 0) ? 0 : (Utils::HighestBit(value) + 1); 126 | } 127 | 128 | static int CountLeadingZeros64(uint64_t x); 129 | static int CountLeadingZeros32(uint32_t x); 130 | 131 | static int CountLeadingZerosWord(uword x) { 132 | #ifdef ARCH_IS_64_BIT 133 | return CountLeadingZeros64(x); 134 | #else 135 | return CountLeadingZeros32(x); 136 | #endif 137 | } 138 | 139 | static int CountTrailingZeros64(uint64_t x); 140 | static int CountTrailingZeros32(uint32_t x); 141 | 142 | static int CountTrailingZerosWord(uword x) { 143 | #ifdef ARCH_IS_64_BIT 144 | return CountTrailingZeros64(x); 145 | #else 146 | return CountTrailingZeros32(x); 147 | #endif 148 | } 149 | 150 | static uint64_t ReverseBits64(uint64_t x); 151 | static uint32_t ReverseBits32(uint32_t x); 152 | 153 | static uword ReverseBitsWord(uword x) { 154 | #ifdef ARCH_IS_64_BIT 155 | return ReverseBits64(x); 156 | #else 157 | return ReverseBits32(x); 158 | #endif 159 | } 160 | 161 | // Computes magic numbers to implement DIV or MOD operator. 162 | static void CalculateMagicAndShiftForDivRem(int64_t divisor, 163 | int64_t* magic, 164 | int64_t* shift); 165 | 166 | // Computes a hash value for the given string. 167 | static uint32_t StringHash(const char* data, int length); 168 | 169 | // Computes a hash value for the given word. 170 | static uint32_t WordHash(intptr_t key); 171 | 172 | // Check whether an N-bit two's-complement representation can hold value. 173 | template 174 | static inline bool IsInt(int N, T value) { 175 | ASSERT((0 < N) && 176 | (static_cast(N) < (kBitsPerByte * sizeof(value)))); 177 | T limit = static_cast(1) << (N - 1); 178 | return (-limit <= value) && (value < limit); 179 | } 180 | 181 | template 182 | static inline bool IsUint(int N, T value) { 183 | ASSERT((0 < N) && 184 | (static_cast(N) < (kBitsPerByte * sizeof(value)))); 185 | const auto limit = 186 | (static_cast::type>(1) << N) - 1; 187 | return (0 <= value) && 188 | (static_cast::type>(value) <= limit); 189 | } 190 | 191 | // Check whether the magnitude of value fits in N bits, i.e., whether an 192 | // (N+1)-bit sign-magnitude representation can hold value. 193 | template 194 | static inline bool IsAbsoluteUint(int N, T value) { 195 | ASSERT((0 < N) && 196 | (static_cast(N) < (kBitsPerByte * sizeof(value)))); 197 | if (value < 0) value = -value; 198 | return IsUint(N, value); 199 | } 200 | 201 | static inline int32_t Low16Bits(int32_t value) { 202 | return static_cast(value & 0xffff); 203 | } 204 | 205 | static inline int32_t High16Bits(int32_t value) { 206 | return static_cast(value >> 16); 207 | } 208 | 209 | static inline int32_t Low32Bits(int64_t value) { 210 | return static_cast(value); 211 | } 212 | 213 | static inline int32_t High32Bits(int64_t value) { 214 | return static_cast(value >> 32); 215 | } 216 | 217 | static inline int64_t LowHighTo64Bits(uint32_t low, int32_t high) { 218 | return (static_cast(high) << 32) | (low & 0x0ffffffffLL); 219 | } 220 | 221 | static inline constexpr bool IsAlphaNumeric(uint32_t c) { 222 | return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || 223 | IsDecimalDigit(c); 224 | } 225 | 226 | static inline constexpr bool IsDecimalDigit(uint32_t c) { 227 | return ('0' <= c) && (c <= '9'); 228 | } 229 | 230 | static bool IsHexDigit(char c) { 231 | return IsDecimalDigit(c) || (('A' <= c) && (c <= 'F')) || 232 | (('a' <= c) && (c <= 'f')); 233 | } 234 | 235 | static int HexDigitToInt(char c) { 236 | ASSERT(IsHexDigit(c)); 237 | if (IsDecimalDigit(c)) return c - '0'; 238 | if (('A' <= c) && (c <= 'F')) return 10 + (c - 'A'); 239 | return 10 + (c - 'a'); 240 | } 241 | 242 | static char IntToHexDigit(int i) { 243 | ASSERT(0 <= i && i < 16); 244 | if (i < 10) return static_cast('0' + i); 245 | return static_cast('A' + (i - 10)); 246 | } 247 | 248 | // Perform a range check, checking if 249 | // offset + count <= length 250 | // without the risk of integer overflow. 251 | static inline bool RangeCheck(intptr_t offset, 252 | intptr_t count, 253 | intptr_t length) { 254 | return offset >= 0 && count >= 0 && length >= 0 && 255 | count <= (length - offset); 256 | } 257 | 258 | static inline bool WillAddOverflow(int64_t a, int64_t b) { 259 | return ((b > 0) && (a > (kMaxInt64 - b))) || 260 | ((b < 0) && (a < (kMinInt64 - b))); 261 | } 262 | 263 | static inline bool WillSubOverflow(int64_t a, int64_t b) { 264 | return ((b > 0) && (a < (kMinInt64 + b))) || 265 | ((b < 0) && (a > (kMaxInt64 + b))); 266 | } 267 | 268 | // Adds two int64_t values with wrapping around 269 | // (two's complement arithmetic). 270 | template 271 | static inline T AddWithWrapAround(T a, T b) { 272 | // Avoid undefined behavior by doing arithmetic in the unsigned type. 273 | using Unsigned = typename std::make_unsigned::type; 274 | return static_cast(static_cast(a) + static_cast(b)); 275 | } 276 | 277 | // Subtracts two int64_t values with wrapping around 278 | // (two's complement arithmetic). 279 | template 280 | static inline T SubWithWrapAround(T a, T b) { 281 | // Avoid undefined behavior by doing arithmetic in the unsigned type. 282 | using Unsigned = typename std::make_unsigned::type; 283 | return static_cast(static_cast(a) - static_cast(b)); 284 | } 285 | 286 | // Multiplies two int64_t values with wrapping around 287 | // (two's complement arithmetic). 288 | template 289 | static inline T MulWithWrapAround(T a, T b) { 290 | // Avoid undefined behavior by doing arithmetic in the unsigned type. 291 | using Unsigned = typename std::make_unsigned::type; 292 | return static_cast(static_cast(a) * static_cast(b)); 293 | } 294 | 295 | template 296 | static inline T NegWithWrapAround(T a) { 297 | // Avoid undefined behavior by doing arithmetic in the unsigned type. 298 | using Unsigned = typename std::make_unsigned::type; 299 | return static_cast(-static_cast(a)); 300 | } 301 | 302 | // Shifts int64_t value left. Supports any non-negative number of bits and 303 | // silently discards shifted out bits. 304 | static inline int64_t ShiftLeftWithTruncation(int64_t a, int64_t b) { 305 | ASSERT(b >= 0); 306 | if (b >= kBitsPerInt64) { 307 | return 0; 308 | } 309 | // Avoid undefined behavior by doing arithmetic in the unsigned type. 310 | return static_cast(static_cast(a) << b); 311 | } 312 | 313 | template 314 | static inline T RotateLeft(T value, uint8_t rotate) { 315 | const uint8_t width = sizeof(T) * kBitsPerByte; 316 | ASSERT(0 <= rotate); 317 | ASSERT(rotate <= width); 318 | using Unsigned = typename std::make_unsigned::type; 319 | return (static_cast(value) << rotate) | 320 | (static_cast(value) >> ((width - rotate) & (width - 1))); 321 | } 322 | template 323 | static inline T RotateRight(T value, uint8_t rotate) { 324 | const uint8_t width = sizeof(T) * kBitsPerByte; 325 | ASSERT(0 <= rotate); 326 | ASSERT(rotate <= width); 327 | using Unsigned = typename std::make_unsigned::type; 328 | return (static_cast(value) >> rotate) | 329 | (static_cast(value) << ((width - rotate) & (width - 1))); 330 | } 331 | 332 | // Utility functions for converting values from host endianness to 333 | // big or little endian values. 334 | static uint16_t HostToBigEndian16(uint16_t host_value); 335 | static uint32_t HostToBigEndian32(uint32_t host_value); 336 | static uint64_t HostToBigEndian64(uint64_t host_value); 337 | static uint16_t HostToLittleEndian16(uint16_t host_value); 338 | static uint32_t HostToLittleEndian32(uint32_t host_value); 339 | static uint64_t HostToLittleEndian64(uint64_t host_value); 340 | 341 | // Going between Host <-> LE/BE is the same operation for all practical 342 | // purposes. 343 | static inline uint32_t BigEndianToHost32(uint32_t be_value) { 344 | return HostToBigEndian32(be_value); 345 | } 346 | static inline uint64_t LittleEndianToHost64(uint64_t le_value) { 347 | return HostToLittleEndian64(le_value); 348 | } 349 | 350 | static bool DoublesBitEqual(const double a, const double b) { 351 | return bit_cast(a) == bit_cast(b); 352 | } 353 | 354 | // A double-to-integer conversion that avoids undefined behavior. 355 | // Out of range values and NaNs are converted to minimum value 356 | // for type T. 357 | template 358 | static T SafeDoubleToInt(double v) { 359 | const double min = static_cast(std::numeric_limits::min()); 360 | const double max = static_cast(std::numeric_limits::max()); 361 | return (min <= v && v <= max) ? static_cast(v) 362 | : std::numeric_limits::min(); 363 | } 364 | 365 | // dart2js represents integers as double precision floats, which can 366 | // represent anything in the range -2^53 ... 2^53. 367 | static bool IsJavascriptInt(int64_t value) { 368 | return ((-0x20000000000000LL <= value) && (value <= 0x20000000000000LL)); 369 | } 370 | 371 | static constexpr uword NBitMaskUnsafe(uint32_t n) { 372 | static_assert((sizeof(uword) * kBitsPerByte) == kBitsPerWord, 373 | "Unexpected uword size"); 374 | return n == kBitsPerWord ? std::numeric_limits::max() 375 | : (static_cast(1) << n) - 1; 376 | } 377 | 378 | // The lowest n bits are 1, the others are 0. 379 | static uword NBitMask(uint32_t n) { 380 | ASSERT(n <= kBitsPerWord); 381 | return NBitMaskUnsafe(n); 382 | } 383 | 384 | static word SignedNBitMask(uint32_t n) { 385 | uword mask = NBitMask(n); 386 | return bit_cast(mask); 387 | } 388 | 389 | template 390 | static T Bit(uint32_t n) { 391 | ASSERT(n < sizeof(T) * kBitsPerByte); 392 | T bit = 1; 393 | return bit << n; 394 | } 395 | 396 | template 397 | DART_FORCE_INLINE static bool TestBit(T mask, intptr_t position) { 398 | ASSERT(position < static_cast(sizeof(T) * kBitsPerByte)); 399 | return ((mask >> position) & 1) != 0; 400 | } 401 | 402 | static char* StrError(int err, char* buffer, size_t bufsize); 403 | 404 | // Not all platforms support strndup. 405 | static char* StrNDup(const char* s, intptr_t n); 406 | static char* StrDup(const char* s); 407 | static intptr_t StrNLen(const char* s, intptr_t n); 408 | 409 | static int Close(int fildes); 410 | static size_t Read(int filedes, void* buf, size_t nbyte); 411 | static int Unlink(const char* path); 412 | 413 | // Print formatted output info a buffer. 414 | // 415 | // Does not write more than size characters (including the trailing '\0'). 416 | // 417 | // Returns the number of characters (excluding the trailing '\0') 418 | // that would been written if the buffer had been big enough. If 419 | // the return value is greater or equal than the given size then the 420 | // output has been truncated. The return value is never negative. 421 | // 422 | // The buffer will always be terminated by a '\0', unless the buffer 423 | // is of size 0. The buffer might be NULL if the size is 0. 424 | // 425 | // This specification conforms to C99 standard which is implemented 426 | // by glibc 2.1+ with one exception: the C99 standard allows a 427 | // negative return value. We will terminate the vm rather than let 428 | // that occur. 429 | static int SNPrint(char* str, size_t size, const char* format, ...) 430 | PRINTF_ATTRIBUTE(3, 4); 431 | static int VSNPrint(char* str, size_t size, const char* format, va_list args); 432 | 433 | // Allocate a string and print formatted output into a malloc'd buffer. 434 | static char* SCreate(const char* format, ...) PRINTF_ATTRIBUTE(1, 2); 435 | static char* VSCreate(const char* format, va_list args); 436 | 437 | typedef std::unique_ptr CStringUniquePtr; 438 | 439 | // Returns str in a unique_ptr with free used as its deleter. 440 | static CStringUniquePtr CreateCStringUniquePtr(char* str); 441 | }; 442 | 443 | } // namespace dart 444 | 445 | #if defined(HOST_OS_ANDROID) 446 | #include "platform/utils_android.h" 447 | #elif defined(HOST_OS_FUCHSIA) 448 | #include "platform/utils_fuchsia.h" 449 | #elif defined(HOST_OS_LINUX) 450 | #include "platform/utils_linux.h" 451 | #elif defined(HOST_OS_MACOS) 452 | #include "platform/utils_macos.h" 453 | #elif defined(HOST_OS_WINDOWS) 454 | #include "platform/utils_win.h" 455 | #else 456 | #error Unknown target os. 457 | #endif 458 | 459 | #endif // RUNTIME_PLATFORM_UTILS_H_ 460 | -------------------------------------------------------------------------------- /dart/platform/utils_win.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | #ifndef RUNTIME_PLATFORM_UTILS_WIN_H_ 6 | #define RUNTIME_PLATFORM_UTILS_WIN_H_ 7 | 8 | #if !defined(RUNTIME_PLATFORM_UTILS_H_) 9 | #error Do not include utils_win.h directly; use utils.h instead. 10 | #endif 11 | 12 | #include 13 | #include 14 | 15 | namespace dart { 16 | 17 | // WARNING: The below functions assume host is always Little Endian! 18 | 19 | inline uint16_t Utils::HostToBigEndian16(uint16_t value) { 20 | return _byteswap_ushort(value); 21 | } 22 | 23 | inline uint32_t Utils::HostToBigEndian32(uint32_t value) { 24 | return _byteswap_ulong(value); 25 | } 26 | 27 | inline uint64_t Utils::HostToBigEndian64(uint64_t value) { 28 | return _byteswap_uint64(value); 29 | } 30 | 31 | inline uint16_t Utils::HostToLittleEndian16(uint16_t value) { 32 | return value; 33 | } 34 | 35 | inline uint32_t Utils::HostToLittleEndian32(uint32_t value) { 36 | return value; 37 | } 38 | 39 | inline uint64_t Utils::HostToLittleEndian64(uint64_t value) { 40 | return value; 41 | } 42 | 43 | } // namespace dart 44 | 45 | #endif // RUNTIME_PLATFORM_UTILS_WIN_H_ 46 | -------------------------------------------------------------------------------- /dart/vm/allocation.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | #ifndef RUNTIME_VM_ALLOCATION_H_ 6 | #define RUNTIME_VM_ALLOCATION_H_ 7 | 8 | #include "platform/allocation.h" 9 | #include "platform/assert.h" 10 | #include "vm/globals.h" 11 | 12 | namespace dart { 13 | 14 | // Forward declarations. 15 | class ThreadState; 16 | class Zone; 17 | 18 | // Stack resources subclass from this base class. The VM will ensure that the 19 | // destructors of these objects are called before the stack is unwound past the 20 | // objects location on the stack. Use stack resource objects if objects 21 | // need to be destroyed even in the case of exceptions when a Longjump is done 22 | // to a stack frame above the frame where these objects were allocated. 23 | class StackResource { 24 | public: 25 | explicit StackResource(ThreadState* thread) : thread_(NULL), previous_(NULL) { 26 | Init(thread); 27 | } 28 | 29 | virtual ~StackResource(); 30 | 31 | // The thread that owns this resource. 32 | ThreadState* thread() const { return thread_; } 33 | 34 | // Destroy stack resources of thread until top exit frame. 35 | static void Unwind(ThreadState* thread) { UnwindAbove(thread, NULL); } 36 | // Destroy stack resources of thread above new_top, exclusive. 37 | static void UnwindAbove(ThreadState* thread, StackResource* new_top); 38 | 39 | private: 40 | void Init(ThreadState* thread); 41 | 42 | ThreadState* thread_; 43 | StackResource* previous_; 44 | 45 | DISALLOW_ALLOCATION(); 46 | DISALLOW_IMPLICIT_CONSTRUCTORS(StackResource); 47 | }; 48 | 49 | // Zone allocated objects cannot be individually deallocated, but have 50 | // to rely on the destructor of Zone which is called when the Zone 51 | // goes out of scope to reclaim memory. 52 | class ZoneAllocated { 53 | public: 54 | ZoneAllocated() {} 55 | 56 | // Implicitly allocate the object in the current zone. 57 | void* operator new(size_t size); 58 | 59 | // Allocate the object in the given zone, which must be the current zone. 60 | void* operator new(size_t size, Zone* zone); 61 | 62 | // Ideally, the delete operator should be protected instead of 63 | // public, but unfortunately the compiler sometimes synthesizes 64 | // (unused) destructors for classes derived from ZoneObject, which 65 | // require the operator to be visible. MSVC requires the delete 66 | // operator to be public. 67 | 68 | // Disallow explicit deallocation of nodes. Nodes can only be 69 | // deallocated by invoking DeleteAll() on the zone they live in. 70 | void operator delete(void* pointer) { UNREACHABLE(); } 71 | 72 | private: 73 | DISALLOW_COPY_AND_ASSIGN(ZoneAllocated); 74 | }; 75 | 76 | } // namespace dart 77 | 78 | #endif // RUNTIME_VM_ALLOCATION_H_ 79 | -------------------------------------------------------------------------------- /dart/vm/base_isolate.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | #ifndef RUNTIME_VM_BASE_ISOLATE_H_ 6 | #define RUNTIME_VM_BASE_ISOLATE_H_ 7 | 8 | #include "platform/assert.h" 9 | #include "vm/globals.h" 10 | 11 | namespace dart { 12 | 13 | class HandleScope; 14 | class StackResource; 15 | class Thread; 16 | class Zone; 17 | 18 | // A BaseIsolate contains just enough functionality to allocate 19 | // StackResources. This allows us to inline the StackResource 20 | // constructor/destructor for performance. 21 | class BaseIsolate { 22 | public: 23 | #if defined(DEBUG) 24 | void AssertCurrentThreadIsMutator() const; 25 | #else 26 | void AssertCurrentThreadIsMutator() const {} 27 | #endif // DEBUG 28 | 29 | #if defined(DEBUG) 30 | static void AssertCurrent(BaseIsolate* isolate); 31 | #endif 32 | 33 | protected: 34 | BaseIsolate() {} 35 | 36 | ~BaseIsolate() { 37 | // Do not delete stack resources: top_resource_ and current_zone_. 38 | } 39 | 40 | Thread* scheduled_mutator_thread_ = nullptr; 41 | 42 | // TODO(asiva): Currently we treat a mutator thread as a special thread 43 | // and always schedule execution of Dart code on the same mutator thread 44 | // object. The ApiLocalScope has been made thread specific but we still 45 | // have scenarios where we do a temporary exit of an Isolate with live 46 | // zones/handles in the API scope : 47 | // - Dart_RunLoop() 48 | // - IsolateSaver in Dart_NewNativePort 49 | // We probably need a mechanism to return to the specific thread only 50 | // for these specific cases. We should also determine if the embedder 51 | // should allow exiting an isolate with live state in zones/handles in 52 | // which case a new API for returning to the specific thread needs to be 53 | // added. 54 | Thread* mutator_thread_ = nullptr; 55 | 56 | private: 57 | DISALLOW_COPY_AND_ASSIGN(BaseIsolate); 58 | }; 59 | 60 | } // namespace dart 61 | 62 | #endif // RUNTIME_VM_BASE_ISOLATE_H_ 63 | -------------------------------------------------------------------------------- /dart/vm/globals.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | #ifndef RUNTIME_VM_GLOBALS_H_ 6 | #define RUNTIME_VM_GLOBALS_H_ 7 | 8 | // This file contains global definitions for the VM library only. Anything that 9 | // is more globally useful should be added to 'vm/globals.h'. 10 | 11 | #include "platform/globals.h" 12 | 13 | #if defined(_WIN32) 14 | // Undef conflicting defines. 15 | #undef PARITY_EVEN 16 | #undef PARITY_ODD 17 | #undef near 18 | #endif // defined(_WIN32) 19 | 20 | namespace dart { 21 | // Smi value range is from -(2^N) to (2^N)-1. 22 | // N=30 (32-bit build) or N=62 (64-bit build). 23 | #if !defined(DART_COMPRESSED_POINTERS) 24 | const intptr_t kSmiBits = kBitsPerWord - 2; 25 | #else 26 | const intptr_t kSmiBits = 30; 27 | #endif 28 | const intptr_t kSmiMax = (static_cast(1) << kSmiBits) - 1; 29 | const intptr_t kSmiMin = -(static_cast(1) << kSmiBits); 30 | 31 | // Hard coded from above but for 32-bit architectures. 32 | const intptr_t kSmiBits32 = kBitsPerInt32 - 2; 33 | const intptr_t kSmiMax32 = (static_cast(1) << kSmiBits32) - 1; 34 | const intptr_t kSmiMin32 = -(static_cast(1) << kSmiBits32); 35 | 36 | // Number of bytes per BigInt digit. 37 | const intptr_t kBytesPerBigIntDigit = 4; 38 | 39 | // The default old gen heap size in MB, where 0 == unlimited. 40 | // 32-bit: OS limit is 2 or 3 GB 41 | // 64-bit: Linux's limit is 42 | // sysctl vm.max_map_count (default 2^16) * 512 KB OldPages = 32 GB 43 | // Set the VM limit below the OS limit to increase the likelihood of failing 44 | // gracefully with a Dart OutOfMemory exception instead of SIGABORT. 45 | const intptr_t kDefaultMaxOldGenHeapSize = (kWordSize <= 4) ? 1536 : 30720; 46 | 47 | #define kPosInfinity bit_cast(DART_UINT64_C(0x7ff0000000000000)) 48 | #define kNegInfinity bit_cast(DART_UINT64_C(0xfff0000000000000)) 49 | 50 | // The expression ARRAY_SIZE(array) is a compile-time constant of type 51 | // size_t which represents the number of elements of the given 52 | // array. You should only use ARRAY_SIZE on statically allocated 53 | // arrays. 54 | #define ARRAY_SIZE(array) \ 55 | ((sizeof(array) / sizeof(*(array))) / \ 56 | static_cast(!(sizeof(array) % sizeof(*(array))))) // NOLINT 57 | 58 | #if defined(PRODUCT) && defined(DEBUG) 59 | #error Both PRODUCT and DEBUG defined. 60 | #endif // defined(PRODUCT) && defined(DEBUG) 61 | 62 | #if defined(PRODUCT) 63 | #define NOT_IN_PRODUCT(code) 64 | #else // defined(PRODUCT) 65 | #define NOT_IN_PRODUCT(code) code 66 | #endif // defined(PRODUCT) 67 | 68 | #if defined(DART_PRECOMPILED_RUNTIME) && defined(DART_PRECOMPILER) 69 | #error DART_PRECOMPILED_RUNTIME and DART_PRECOMPILER are mutually exclusive 70 | #endif // defined(DART_PRECOMPILED_RUNTIME) && defined(DART_PRECOMPILER) 71 | 72 | #if defined(DART_PRECOMPILED_RUNTIME) && defined(DART_NOSNAPSHOT) 73 | #error DART_PRECOMPILED_RUNTIME and DART_NOSNAPSHOT are mutually exclusive 74 | #endif // defined(DART_PRECOMPILED_RUNTIME) && defined(DART_NOSNAPSHOT) 75 | 76 | #if defined(DART_PRECOMPILED_RUNTIME) 77 | #define NOT_IN_PRECOMPILED(code) 78 | #else 79 | #define NOT_IN_PRECOMPILED(code) code 80 | #endif // defined(DART_PRECOMPILED_RUNTIME) 81 | 82 | #if defined(DART_PRECOMPILED_RUNTIME) 83 | #define ONLY_IN_PRECOMPILED(code) code 84 | #else 85 | #define ONLY_IN_PRECOMPILED(code) 86 | #endif // defined(DART_PRECOMPILED_RUNTIME) 87 | 88 | #if defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_ARM64) || \ 89 | defined(TARGET_ARCH_X64) 90 | #define ONLY_IN_ARM_ARM64_X64(code) code 91 | #else 92 | #define ONLY_IN_ARM_ARM64_X64(code) 93 | #endif 94 | 95 | #if defined(DART_PRECOMPILED_RUNTIME) 96 | #define NOT_IN_PRECOMPILED_RUNTIME(code) 97 | #else 98 | #define NOT_IN_PRECOMPILED_RUNTIME(code) code 99 | #endif // defined(DART_PRECOMPILED_RUNTIME) 100 | 101 | #if !defined(PRODUCT) || defined(HOST_OS_FUCHSIA) || defined(TARGET_OS_FUCHSIA) 102 | #define SUPPORT_TIMELINE 1 103 | #endif 104 | 105 | #if defined(ARCH_IS_64_BIT) && !defined(IS_SIMARM_X64) 106 | #define HASH_IN_OBJECT_HEADER 1 107 | #endif 108 | 109 | // The expression OFFSET_OF(type, field) computes the byte-offset of 110 | // the specified field relative to the containing type. 111 | // 112 | // The expression OFFSET_OF_RETURNED_VALUE(type, accessor) computes the 113 | // byte-offset of the return value of the accessor to the containing type. 114 | // 115 | // None of these use 0 or NULL, which causes a problem with the compiler 116 | // warnings we have enabled (which is also why 'offsetof' doesn't seem to work). 117 | // The workaround is to use the non-zero value kOffsetOfPtr. 118 | const intptr_t kOffsetOfPtr = 32; 119 | 120 | #define OFFSET_OF(type, field) \ 121 | (reinterpret_cast( \ 122 | &(reinterpret_cast(kOffsetOfPtr)->field)) - \ 123 | kOffsetOfPtr) // NOLINT 124 | 125 | #define OFFSET_OF_RETURNED_VALUE(type, accessor) \ 126 | (reinterpret_cast( \ 127 | (reinterpret_cast(kOffsetOfPtr)->accessor())) - \ 128 | kOffsetOfPtr) // NOLINT 129 | 130 | #define SIZE_OF_RETURNED_VALUE(type, method) \ 131 | sizeof(reinterpret_cast(kOffsetOfPtr)->method()) 132 | 133 | #define SIZE_OF_DEREFERENCED_RETURNED_VALUE(type, method) \ 134 | sizeof(*(reinterpret_cast(kOffsetOfPtr))->method()) 135 | 136 | #define OPEN_ARRAY_START(type, align) \ 137 | do { \ 138 | const uword result = reinterpret_cast(this) + sizeof(*this); \ 139 | ASSERT(Utils::IsAligned(result, sizeof(align))); \ 140 | return reinterpret_cast(result); \ 141 | } while (0) 142 | 143 | // A type large enough to contain the value of the C++ vtable. This is needed 144 | // to support the handle operations. 145 | typedef uword cpp_vtable; 146 | 147 | // When using GCC we can use GCC attributes to ensure that certain 148 | // constants are 8 or 16 byte aligned. 149 | #if defined(HOST_OS_WINDOWS) 150 | #define ALIGN8 __declspec(align(8)) 151 | #define ALIGN16 __declspec(align(16)) 152 | #else 153 | #define ALIGN8 __attribute__((aligned(8))) 154 | #define ALIGN16 __attribute__((aligned(16))) 155 | #endif 156 | 157 | // Zap value used to indicate uninitialized handle area (debug purposes). 158 | #if defined(ARCH_IS_32_BIT) 159 | static const uword kZapUninitializedWord = 0xabababab; 160 | #else 161 | static const uword kZapUninitializedWord = 0xabababababababab; 162 | #endif 163 | 164 | // Macros to get the contents of the fp register. 165 | #if defined(HOST_OS_WINDOWS) 166 | 167 | // clang-format off 168 | #if defined(HOST_ARCH_IA32) 169 | #define COPY_FP_REGISTER(fp) \ 170 | __asm { mov fp, ebp} \ 171 | ; // NOLINT 172 | // clang-format on 173 | #elif defined(HOST_ARCH_X64) 174 | // We don't have the asm equivalent to get at the frame pointer on 175 | // windows x64, return the stack pointer instead. 176 | #define COPY_FP_REGISTER(fp) fp = OSThread::GetCurrentStackPointer(); 177 | #else 178 | #error Unknown host architecture. 179 | #endif 180 | 181 | #else // !defined(HOST_OS_WINDOWS)) 182 | 183 | // Assume GCC-compatible builtins. 184 | #define COPY_FP_REGISTER(fp) \ 185 | fp = reinterpret_cast(__builtin_frame_address(0)); 186 | 187 | #endif // !defined(HOST_OS_WINDOWS)) 188 | 189 | #if defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_ARM64) || \ 190 | defined(TARGET_ARCH_X64) 191 | #define TARGET_USES_OBJECT_POOL 1 192 | #endif 193 | 194 | #if defined(DART_PRECOMPILER) && \ 195 | (defined(TARGET_ARCH_X64) || defined(TARGET_ARCH_ARM) || \ 196 | defined(TARGET_ARCH_ARM64)) 197 | #define DART_SUPPORT_PRECOMPILATION 1 198 | #endif 199 | 200 | } // namespace dart 201 | 202 | #endif // RUNTIME_VM_GLOBALS_H_ 203 | -------------------------------------------------------------------------------- /setup_env.ps1: -------------------------------------------------------------------------------- 1 | $Env:GYP_MSVS_OVERRIDE_PATH="C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\" 2 | $Env:GYP_MSVS_VERSION=2017 3 | $Env:DEPOT_TOOLS_WIN_TOOLCHAIN=0 4 | --------------------------------------------------------------------------------