├── .gitattributes
├── .gitignore
├── EmbeddedDart
├── hello_world.dill
├── pubspec.lock
├── analysis_options.yaml
├── pubspec.yaml
├── EmbeddedDart.vcxproj.user
├── hello_world.dart
├── stdafx.cpp
├── targetver.h
├── stdafx.h
├── EmbeddedDart.vcxproj
└── EmbeddedDart.cpp
├── setup_env.ps1
├── dart
├── lib
│ ├── win-debug-x64
│ │ └── libdart.lib
│ └── win-release-x64
│ │ └── libdart.lib
├── platform
│ ├── floating_point_win.h
│ ├── floating_point.h
│ ├── utils_win.h
│ ├── address_sanitizer.h
│ ├── allocation.h
│ ├── memory_sanitizer.h
│ ├── hashmap.h
│ ├── atomic.h
│ ├── growable_array.h
│ ├── priority_queue.h
│ ├── assert.h
│ └── utils.h
├── include
│ ├── dart_version.h
│ ├── internal
│ │ └── dart_api_dl_impl.h
│ ├── bin
│ │ └── dart_io_api.h
│ ├── dart_embedder_api.h
│ ├── dart_native_api.h
│ ├── dart_api_dl.h
│ └── dart_tools_api.h
├── bin
│ ├── gzip.h
│ ├── vmservice_impl.h
│ ├── thread_win.h
│ ├── builtin.h
│ ├── thread.h
│ ├── utils_win.h
│ ├── utils.h
│ ├── platform.h
│ ├── reference_counting.h
│ ├── isolate_data.h
│ ├── dfe.h
│ └── eventhandler_win.h
└── vm
│ ├── base_isolate.h
│ ├── allocation.h
│ └── globals.h
├── EmbeddedDart.sln
└── README.md
/.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/hello_world.dill:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fuzzybinary/dart-embedding-example/HEAD/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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/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/EmbeddedDart.vcxproj.user:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/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/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/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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/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/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/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/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/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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_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 |
--------------------------------------------------------------------------------
/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/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 |
--------------------------------------------------------------------------------
/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/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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/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/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/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------