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_DARTUTILS_H_
6#define RUNTIME_BIN_DARTUTILS_H_
7
8#include "bin/isolate_data.h"
9#include "include/dart_api.h"
10#include "include/dart_native_api.h"
11#include "platform/assert.h"
12#include "platform/globals.h"
13#include "platform/hashmap.h"
14
15namespace dart {
16namespace bin {
17
18// Forward declarations.
19class File;
20class OSError;
21
22/* Handles error handles returned from Dart API functions. If a value
23 * is an error, uses Dart_PropagateError to throw it to the enclosing
24 * Dart activation. Otherwise, returns the original handle.
25 *
26 * This function can be used to wrap most API functions, but API
27 * functions can also be nested without this error check, since all
28 * API functions return any error handles passed in as arguments, unchanged.
29 */
30static inline Dart_Handle ThrowIfError(Dart_Handle handle) {
31 if (Dart_IsError(handle)) {
32 Dart_PropagateError(handle);
33 }
34 return handle;
35}
36
37static inline void* GetHashmapKeyFromString(char* key) {
38 return reinterpret_cast<void*>(key);
39}
40
41class CommandLineOptions {
42 public:
43 explicit CommandLineOptions(int max_count)
44 : count_(0), max_count_(max_count), arguments_(NULL) {
45 static const int kWordSize = sizeof(intptr_t);
46 arguments_ = reinterpret_cast<const char**>(malloc(max_count * kWordSize));
47 if (arguments_ == NULL) {
48 max_count_ = 0;
49 }
50 }
51 ~CommandLineOptions() {
52 free(arguments_);
53 count_ = 0;
54 max_count_ = 0;
55 arguments_ = NULL;
56 }
57
58 void Reset() { count_ = 0; }
59
60 int count() const { return count_; }
61 int max_count() const { return max_count_; }
62 const char** arguments() const { return arguments_; }
63
64 const char* GetArgument(int index) const {
65 return (index >= 0 && index < count_) ? arguments_[index] : NULL;
66 }
67 void AddArgument(const char* argument) {
68 if (count_ < max_count_) {
69 arguments_[count_] = argument;
70 count_ += 1;
71 } else {
72 abort(); // We should never get into this situation.
73 }
74 }
75
76 void AddArguments(const char** argv, int argc) {
77 if (count_ + argc >= max_count_) {
78 abort(); // We should never get into this situation.
79 }
80 for (int i = 0; i < argc; ++i) {
81 arguments_[count_++] = argv[i];
82 }
83 }
84
85 Dart_Handle CreateRuntimeOptions();
86
87 void operator delete(void* pointer) { abort(); }
88
89 private:
90 void* operator new(size_t size);
91
92 int count_;
93 int max_count_;
94 const char** arguments_;
95
96 DISALLOW_COPY_AND_ASSIGN(CommandLineOptions);
97};
98
99class DartUtils {
100 public:
101 // Returns the integer value of a Dart object. If the object is not
102 // an integer value an API error is propagated.
103 static int64_t GetIntegerValue(Dart_Handle value_obj);
104 // Returns the integer value of a Dart object. If the object is not
105 // an integer value or outside the requested range an API error is
106 // propagated.
107 static int64_t GetInt64ValueCheckRange(Dart_Handle value_obj,
108 int64_t lower,
109 int64_t upper);
110 // Returns the intptr_t value of a Dart object. If the object is not
111 // an integer value or the value is outside the intptr_t range an
112 // API error is propagated.
113 static intptr_t GetIntptrValue(Dart_Handle value_obj);
114 // Checks that the value object is an integer object that fits in a
115 // signed 64-bit integer. If it is, the value is returned in the
116 // value out parameter and true is returned. Otherwise, false is
117 // returned.
118 static bool GetInt64Value(Dart_Handle value_obj, int64_t* value);
119 // Returns the string value of a Dart object. If the object is not
120 // a string value an API error is propagated.
121 static const char* GetStringValue(Dart_Handle str_obj);
122 // Returns the boolean value of a Dart object. If the object is not
123 // a boolean value an API error is propagated.
124 static bool GetBooleanValue(Dart_Handle bool_obj);
125 // Returns the boolean value of the argument at index. If the argument
126 // is not a boolean value an API error is propagated.
127 static bool GetNativeBooleanArgument(Dart_NativeArguments args,
128 intptr_t index);
129 // Returns the integer value of the argument at index. If the argument
130 // is not an integer value an API error is propagated.
131 static int64_t GetNativeIntegerArgument(Dart_NativeArguments args,
132 intptr_t index);
133 // Returns the intptr_t value of the argument at index. If the argument
134 // is not an integer value or the value is outside the intptr_t range an
135 // API error is propagated.
136 static intptr_t GetNativeIntptrArgument(Dart_NativeArguments args,
137 intptr_t index);
138 // Returns the string value of the argument at index. If the argument
139 // is not a string value an API error is propagated.
140 static const char* GetNativeStringArgument(Dart_NativeArguments args,
141 intptr_t index);
142 static Dart_Handle SetIntegerField(Dart_Handle handle,
143 const char* name,
144 int64_t val);
145 static Dart_Handle SetStringField(Dart_Handle handle,
146 const char* name,
147 const char* val);
148 static bool IsDartSchemeURL(const char* url_name);
149 static bool IsDartExtensionSchemeURL(const char* url_name);
150 static bool IsDartIOLibURL(const char* url_name);
151 static bool IsDartCLILibURL(const char* url_name);
152 static bool IsDartHttpLibURL(const char* url_name);
153 static bool IsDartBuiltinLibURL(const char* url_name);
154 static bool IsHttpSchemeURL(const char* url_name);
155 static const char* RemoveScheme(const char* url);
156 static char* DirName(const char* url);
157 static void* MapExecutable(const char* name, intptr_t* file_len);
158 static void* OpenFile(const char* name, bool write);
159 static void* OpenFileUri(const char* uri, bool write);
160 static void ReadFile(uint8_t** data, intptr_t* file_len, void* stream);
161 static void WriteFile(const void* buffer, intptr_t num_bytes, void* stream);
162 static void CloseFile(void* stream);
163 static bool EntropySource(uint8_t* buffer, intptr_t length);
164 static Dart_Handle ReadStringFromFile(const char* filename);
165 static Dart_Handle MakeUint8Array(const uint8_t* buffer, intptr_t length);
166 static Dart_Handle PrepareForScriptLoading(bool is_service_isolate,
167 bool trace_loading);
168 static Dart_Handle SetupPackageConfig(const char* packages_file);
169
170 static Dart_Handle SetupIOLibrary(const char* namespc_path,
171 const char* script_uri,
172 bool disable_exit);
173
174 static bool PostNull(Dart_Port port_id);
175 static bool PostInt32(Dart_Port port_id, int32_t value);
176 static bool PostInt64(Dart_Port port_id, int64_t value);
177
178 static Dart_Handle GetDartType(const char* library_url,
179 const char* class_name);
180 // Create a new Dart OSError object with the current OS error.
181 static Dart_Handle NewDartOSError();
182 // Create a new Dart OSError object with the provided OS error.
183 static Dart_Handle NewDartOSError(OSError* os_error);
184 static Dart_Handle NewDartExceptionWithOSError(const char* library_url,
185 const char* exception_name,
186 const char* message,
187 Dart_Handle os_error);
188 static Dart_Handle NewDartExceptionWithMessage(const char* library_url,
189 const char* exception_name,
190 const char* message);
191 static Dart_Handle NewDartArgumentError(const char* message);
192 static Dart_Handle NewDartFormatException(const char* message);
193 static Dart_Handle NewDartUnsupportedError(const char* message);
194 static Dart_Handle NewDartIOException(const char* exception_name,
195 const char* message,
196 Dart_Handle os_error);
197
198 // Create a new Dart String object from a C String.
199 static Dart_Handle NewString(const char* str) {
200 ASSERT(str != NULL);
201 return Dart_NewStringFromUTF8(reinterpret_cast<const uint8_t*>(str),
202 strlen(str));
203 }
204
205 // Allocate length bytes for a C string with Dart_ScopeAllocate.
206 static char* ScopedCString(intptr_t length) {
207 char* result = NULL;
208 result =
209 reinterpret_cast<char*>(Dart_ScopeAllocate(length * sizeof(*result)));
210 return result;
211 }
212
213 // Copy str into a buffer allocated with Dart_ScopeAllocate.
214 static char* ScopedCopyCString(const char* str) {
215 size_t str_len = strlen(str);
216 char* result = ScopedCString(str_len + 1);
217 memmove(result, str, str_len);
218 result[str_len] = '\0';
219 return result;
220 }
221
222 // Create a new Dart InternalError object with the provided message.
223 static Dart_Handle NewError(const char* format, ...);
224 static Dart_Handle NewInternalError(const char* message);
225
226 static Dart_Handle LookupBuiltinLib() {
227 return Dart_LookupLibrary(NewString(kBuiltinLibURL));
228 }
229
230 static bool SetOriginalWorkingDirectory();
231
232 static Dart_Handle ResolveScript(Dart_Handle url);
233
234 enum MagicNumber {
235 kAppJITMagicNumber,
236 kKernelMagicNumber,
237 kKernelListMagicNumber,
238 kGzipMagicNumber,
239 kUnknownMagicNumber
240 };
241
242 // Checks if the buffer is a script snapshot, kernel file, or gzip file.
243 static MagicNumber SniffForMagicNumber(const char* filename);
244
245 // Checks if the buffer is a script snapshot, kernel file, or gzip file.
246 static MagicNumber SniffForMagicNumber(const uint8_t* text_buffer,
247 intptr_t buffer_len);
248
249 // Global state that stores the original working directory..
250 static const char* original_working_directory;
251
252 static const char* const kDartScheme;
253 static const char* const kDartExtensionScheme;
254 static const char* const kAsyncLibURL;
255 static const char* const kBuiltinLibURL;
256 static const char* const kCoreLibURL;
257 static const char* const kInternalLibURL;
258 static const char* const kIsolateLibURL;
259 static const char* const kHttpLibURL;
260 static const char* const kIOLibURL;
261 static const char* const kIOLibPatchURL;
262 static const char* const kCLILibURL;
263 static const char* const kCLILibPatchURL;
264 static const char* const kUriLibURL;
265 static const char* const kHttpScheme;
266 static const char* const kVMServiceLibURL;
267
268 static void SetEnvironment(dart::SimpleHashMap* environment);
269 static Dart_Handle EnvironmentCallback(Dart_Handle name);
270
271 private:
272 static Dart_Handle SetWorkingDirectory();
273 static Dart_Handle PrepareBuiltinLibrary(Dart_Handle builtin_lib,
274 Dart_Handle internal_lib,
275 bool is_service_isolate,
276 bool trace_loading);
277 static Dart_Handle PrepareCoreLibrary(Dart_Handle core_lib,
278 Dart_Handle io_lib,
279 bool is_service_isolate);
280 static Dart_Handle PrepareAsyncLibrary(Dart_Handle async_lib,
281 Dart_Handle isolate_lib);
282 static Dart_Handle PrepareIOLibrary(Dart_Handle io_lib);
283 static Dart_Handle PrepareIsolateLibrary(Dart_Handle isolate_lib);
284 static Dart_Handle PrepareCLILibrary(Dart_Handle cli_lib);
285
286 static dart::SimpleHashMap* environment_;
287
288 DISALLOW_ALLOCATION();
289 DISALLOW_IMPLICIT_CONSTRUCTORS(DartUtils);
290};
291
292class CObject {
293 public:
294 // These match the constants in sdk/lib/io/common.dart.
295 static const int kSuccess = 0;
296 static const int kArgumentError = 1;
297 static const int kOSError = 2;
298 static const int kFileClosedError = 3;
299
300 explicit CObject(Dart_CObject* cobject) : cobject_(cobject) {}
301 Dart_CObject_Type type() { return cobject_->type; }
302 Dart_TypedData_Type byte_array_type() {
303 ASSERT(type() == Dart_CObject_kTypedData ||
304 type() == Dart_CObject_kExternalTypedData);
305 return cobject_->value.as_typed_data.type;
306 }
307
308 bool IsNull() { return type() == Dart_CObject_kNull; }
309 bool IsBool() { return type() == Dart_CObject_kBool; }
310 bool IsInt32() { return type() == Dart_CObject_kInt32; }
311 bool IsInt64() { return type() == Dart_CObject_kInt64; }
312 bool IsInt32OrInt64() { return IsInt32() || IsInt64(); }
313 bool IsIntptr() { return IsInt32OrInt64(); }
314 bool IsDouble() { return type() == Dart_CObject_kDouble; }
315 bool IsString() { return type() == Dart_CObject_kString; }
316 bool IsArray() { return type() == Dart_CObject_kArray; }
317 bool IsTypedData() { return type() == Dart_CObject_kTypedData; }
318 bool IsUint8Array() {
319 return type() == Dart_CObject_kTypedData &&
320 byte_array_type() == Dart_TypedData_kUint8;
321 }
322 bool IsSendPort() { return type() == Dart_CObject_kSendPort; }
323
324 bool IsTrue() {
325 return type() == Dart_CObject_kBool && cobject_->value.as_bool;
326 }
327
328 bool IsFalse() {
329 return type() == Dart_CObject_kBool && !cobject_->value.as_bool;
330 }
331
332 void* operator new(size_t size) { return Dart_ScopeAllocate(size); }
333
334 static CObject* Null();
335 static CObject* True();
336 static CObject* False();
337 static CObject* Bool(bool value);
338 static Dart_CObject* NewInt32(int32_t value);
339 static Dart_CObject* NewInt64(int64_t value);
340 static Dart_CObject* NewIntptr(intptr_t value);
341 static Dart_CObject* NewDouble(double value);
342 static Dart_CObject* NewString(intptr_t length);
343 static Dart_CObject* NewString(const char* str);
344 static Dart_CObject* NewArray(intptr_t length);
345 static Dart_CObject* NewUint8Array(intptr_t length);
346 static Dart_CObject* NewUint32Array(intptr_t length);
347 static Dart_CObject* NewExternalUint8Array(
348 intptr_t length,
349 uint8_t* data,
350 void* peer,
351 Dart_WeakPersistentHandleFinalizer callback);
352
353 static Dart_CObject* NewIOBuffer(int64_t length);
354 static void FreeIOBufferData(Dart_CObject* object);
355
356 Dart_CObject* AsApiCObject() { return cobject_; }
357
358 // Create a new CObject array with an illegal arguments error.
359 static CObject* IllegalArgumentError();
360 // Create a new CObject array with a file closed error.
361 static CObject* FileClosedError();
362 // Create a new CObject array with the current OS error.
363 static CObject* NewOSError();
364 // Create a new CObject array with the specified OS error.
365 static CObject* NewOSError(OSError* os_error);
366
367 protected:
368 CObject() : cobject_(NULL) {}
369 Dart_CObject* cobject_;
370
371 private:
372 static Dart_CObject* New(Dart_CObject_Type type, int additional_bytes = 0);
373
374 static Dart_CObject api_null_;
375 static Dart_CObject api_true_;
376 static Dart_CObject api_false_;
377 static CObject null_;
378 static CObject true_;
379 static CObject false_;
380
381 private:
382 DISALLOW_COPY_AND_ASSIGN(CObject);
383};
384
385#define DECLARE_COBJECT_CONSTRUCTORS(t) \
386 explicit CObject##t(Dart_CObject* cobject) : CObject(cobject) { \
387 ASSERT(type() == Dart_CObject_k##t); \
388 cobject_ = cobject; \
389 } \
390 explicit CObject##t(CObject* cobject) : CObject() { \
391 ASSERT(cobject != NULL); \
392 ASSERT(cobject->type() == Dart_CObject_k##t); \
393 cobject_ = cobject->AsApiCObject(); \
394 }
395
396#define DECLARE_COBJECT_TYPED_DATA_CONSTRUCTORS(t) \
397 explicit CObject##t##Array(Dart_CObject* cobject) : CObject(cobject) { \
398 ASSERT(type() == Dart_CObject_kTypedData); \
399 ASSERT(byte_array_type() == Dart_TypedData_k##t); \
400 cobject_ = cobject; \
401 } \
402 explicit CObject##t##Array(CObject* cobject) : CObject() { \
403 ASSERT(cobject != NULL); \
404 ASSERT(cobject->type() == Dart_CObject_kTypedData); \
405 ASSERT(cobject->byte_array_type() == Dart_TypedData_k##t); \
406 cobject_ = cobject->AsApiCObject(); \
407 }
408
409#define DECLARE_COBJECT_EXTERNAL_TYPED_DATA_CONSTRUCTORS(t) \
410 explicit CObjectExternal##t##Array(Dart_CObject* cobject) \
411 : CObject(cobject) { \
412 ASSERT(type() == Dart_CObject_kExternalTypedData); \
413 ASSERT(byte_array_type() == Dart_TypedData_k##t); \
414 cobject_ = cobject; \
415 } \
416 explicit CObjectExternal##t##Array(CObject* cobject) : CObject() { \
417 ASSERT(cobject != NULL); \
418 ASSERT(cobject->type() == Dart_CObject_kExternalTypedData); \
419 ASSERT(cobject->byte_array_type() == Dart_TypedData_k##t); \
420 cobject_ = cobject->AsApiCObject(); \
421 }
422
423class CObjectBool : public CObject {
424 public:
425 DECLARE_COBJECT_CONSTRUCTORS(Bool)
426
427 bool Value() const { return cobject_->value.as_bool; }
428
429 private:
430 DISALLOW_COPY_AND_ASSIGN(CObjectBool);
431};
432
433class CObjectInt32 : public CObject {
434 public:
435 DECLARE_COBJECT_CONSTRUCTORS(Int32)
436
437 int32_t Value() const { return cobject_->value.as_int32; }
438
439 private:
440 DISALLOW_COPY_AND_ASSIGN(CObjectInt32);
441};
442
443class CObjectInt64 : public CObject {
444 public:
445 DECLARE_COBJECT_CONSTRUCTORS(Int64)
446
447 int64_t Value() const { return cobject_->value.as_int64; }
448
449 private:
450 DISALLOW_COPY_AND_ASSIGN(CObjectInt64);
451};
452
453class CObjectIntptr : public CObject {
454 public:
455 explicit CObjectIntptr(Dart_CObject* cobject) : CObject(cobject) {
456 ASSERT(type() == Dart_CObject_kInt32 || type() == Dart_CObject_kInt64);
457 cobject_ = cobject;
458 }
459 explicit CObjectIntptr(CObject* cobject) : CObject() {
460 ASSERT(cobject != NULL);
461 ASSERT(cobject->type() == Dart_CObject_kInt64 ||
462 cobject->type() == Dart_CObject_kInt32);
463 cobject_ = cobject->AsApiCObject();
464 }
465
466 intptr_t Value() {
467 intptr_t result;
468 if (type() == Dart_CObject_kInt32) {
469 result = cobject_->value.as_int32;
470 } else {
471 ASSERT(sizeof(result) == 8);
472 result = static_cast<intptr_t>(cobject_->value.as_int64);
473 }
474 return result;
475 }
476
477 private:
478 DISALLOW_COPY_AND_ASSIGN(CObjectIntptr);
479};
480
481class CObjectDouble : public CObject {
482 public:
483 DECLARE_COBJECT_CONSTRUCTORS(Double)
484
485 double Value() const { return cobject_->value.as_double; }
486
487 private:
488 DISALLOW_COPY_AND_ASSIGN(CObjectDouble);
489};
490
491class CObjectString : public CObject {
492 public:
493 DECLARE_COBJECT_CONSTRUCTORS(String)
494
495 intptr_t Length() const { return strlen(cobject_->value.as_string); }
496 char* CString() const { return cobject_->value.as_string; }
497
498 private:
499 DISALLOW_COPY_AND_ASSIGN(CObjectString);
500};
501
502class CObjectArray : public CObject {
503 public:
504 DECLARE_COBJECT_CONSTRUCTORS(Array)
505
506 intptr_t Length() const { return cobject_->value.as_array.length; }
507 CObject* operator[](intptr_t index) const {
508 return new CObject(cobject_->value.as_array.values[index]);
509 }
510 void SetAt(intptr_t index, CObject* value) {
511 cobject_->value.as_array.values[index] = value->AsApiCObject();
512 }
513
514 private:
515 DISALLOW_COPY_AND_ASSIGN(CObjectArray);
516};
517
518class CObjectSendPort : public CObject {
519 public:
520 DECLARE_COBJECT_CONSTRUCTORS(SendPort)
521
522 Dart_Port Value() const { return cobject_->value.as_send_port.id; }
523 Dart_Port OriginId() const { return cobject_->value.as_send_port.origin_id; }
524
525 private:
526 DISALLOW_COPY_AND_ASSIGN(CObjectSendPort);
527};
528
529class CObjectTypedData : public CObject {
530 public:
531 explicit CObjectTypedData(Dart_CObject* cobject) : CObject(cobject) {
532 ASSERT(type() == Dart_CObject_kTypedData);
533 cobject_ = cobject;
534 }
535 explicit CObjectTypedData(CObject* cobject) : CObject() {
536 ASSERT(cobject != NULL);
537 ASSERT(cobject->type() == Dart_CObject_kTypedData);
538 cobject_ = cobject->AsApiCObject();
539 }
540
541 Dart_TypedData_Type Type() const {
542 return cobject_->value.as_typed_data.type;
543 }
544 intptr_t Length() const { return cobject_->value.as_typed_data.length; }
545 uint8_t* Buffer() const { return cobject_->value.as_typed_data.values; }
546
547 private:
548 DISALLOW_COPY_AND_ASSIGN(CObjectTypedData);
549};
550
551class CObjectUint8Array : public CObject {
552 public:
553 DECLARE_COBJECT_TYPED_DATA_CONSTRUCTORS(Uint8)
554
555 intptr_t Length() const { return cobject_->value.as_typed_data.length; }
556 uint8_t* Buffer() const { return cobject_->value.as_typed_data.values; }
557
558 private:
559 DISALLOW_COPY_AND_ASSIGN(CObjectUint8Array);
560};
561
562class CObjectExternalUint8Array : public CObject {
563 public:
564 DECLARE_COBJECT_EXTERNAL_TYPED_DATA_CONSTRUCTORS(Uint8)
565
566 intptr_t Length() const {
567 return cobject_->value.as_external_typed_data.length;
568 }
569 void SetLength(intptr_t length) {
570 cobject_->value.as_external_typed_data.length = length;
571 }
572 uint8_t* Data() const { return cobject_->value.as_external_typed_data.data; }
573 void* Peer() const { return cobject_->value.as_external_typed_data.peer; }
574 Dart_WeakPersistentHandleFinalizer Callback() const {
575 return cobject_->value.as_external_typed_data.callback;
576 }
577
578 private:
579 DISALLOW_COPY_AND_ASSIGN(CObjectExternalUint8Array);
580};
581
582class ScopedBlockingCall {
583 public:
584 ScopedBlockingCall() { Dart_ThreadDisableProfiling(); }
585
586 ~ScopedBlockingCall() { Dart_ThreadEnableProfiling(); }
587
588 private:
589 DISALLOW_ALLOCATION();
590 DISALLOW_COPY_AND_ASSIGN(ScopedBlockingCall);
591};
592
593struct MagicNumberData {
594 static const intptr_t kMaxLength = 8;
595
596 intptr_t length;
597 const uint8_t bytes[kMaxLength];
598};
599
600extern MagicNumberData appjit_magic_number;
601extern MagicNumberData kernel_magic_number;
602extern MagicNumberData kernel_list_magic_number;
603extern MagicNumberData gzip_magic_number;
604
605} // namespace bin
606} // namespace dart
607
608#endif // RUNTIME_BIN_DARTUTILS_H_
609