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#include <memory>
6
7#include "vm/dart_api_message.h"
8
9#include "platform/undefined_behavior_sanitizer.h"
10#include "platform/unicode.h"
11#include "vm/object.h"
12#include "vm/snapshot_ids.h"
13#include "vm/symbols.h"
14
15namespace dart {
16
17static const int kNumInitialReferences = 4;
18
19ApiMessageReader::ApiMessageReader(Message* msg)
20 : BaseReader(msg->IsRaw() ? reinterpret_cast<uint8_t*>(
21 static_cast<uword>(msg->raw_obj()))
22 : msg->snapshot(),
23 msg->snapshot_length()),
24 zone_(NULL),
25 backward_references_(kNumInitialReferences),
26 vm_isolate_references_(kNumInitialReferences),
27 vm_symbol_references_(NULL),
28 finalizable_data_(msg->finalizable_data()) {}
29
30ApiMessageReader::~ApiMessageReader() {}
31
32void ApiMessageReader::Init() {
33 // We need to have an enclosing ApiNativeScope.
34 ASSERT(ApiNativeScope::Current() != NULL);
35 zone_ = ApiNativeScope::Current()->zone();
36 ASSERT(zone_ != NULL);
37
38 // Initialize marker objects used to handle Lists.
39 // TODO(sjesse): Remove this when message serialization format is
40 // updated.
41 memset(&type_arguments_marker, 0, sizeof(type_arguments_marker));
42 memset(&dynamic_type_marker, 0, sizeof(dynamic_type_marker));
43 type_arguments_marker.type =
44 static_cast<Dart_CObject_Type>(Dart_CObject_Internal::kTypeArguments);
45 dynamic_type_marker.type =
46 static_cast<Dart_CObject_Type>(Dart_CObject_Internal::kDynamicType);
47}
48
49Dart_CObject* ApiMessageReader::ReadMessage() {
50 Init();
51 if (PendingBytes() > 0) {
52 // Read the object out of the message.
53 return ReadObject();
54 } else {
55 const ObjectPtr raw_obj = static_cast<const ObjectPtr>(
56 reinterpret_cast<uword>(CurrentBufferAddress()));
57 ASSERT(ApiObjectConverter::CanConvert(raw_obj));
58 Dart_CObject* cobj =
59 reinterpret_cast<Dart_CObject*>(allocator(sizeof(Dart_CObject)));
60 ApiObjectConverter::Convert(raw_obj, cobj);
61 return cobj;
62 }
63}
64
65intptr_t ApiMessageReader::LookupInternalClass(intptr_t class_header) {
66 if (IsVMIsolateObject(class_header)) {
67 return GetVMIsolateObjectId(class_header);
68 }
69 ASSERT(SerializedHeaderTag::decode(class_header) == kObjectId);
70 return SerializedHeaderData::decode(class_header);
71}
72
73Dart_CObject* ApiMessageReader::AllocateDartCObject(Dart_CObject_Type type) {
74 Dart_CObject* value =
75 reinterpret_cast<Dart_CObject*>(allocator(sizeof(Dart_CObject)));
76 ASSERT(value != NULL);
77 value->type = type;
78 return value;
79}
80
81Dart_CObject* ApiMessageReader::AllocateDartCObjectUnsupported() {
82 return AllocateDartCObject(Dart_CObject_kUnsupported);
83}
84
85Dart_CObject* ApiMessageReader::AllocateDartCObjectNull() {
86 return AllocateDartCObject(Dart_CObject_kNull);
87}
88
89Dart_CObject* ApiMessageReader::AllocateDartCObjectBool(bool val) {
90 Dart_CObject* value = AllocateDartCObject(Dart_CObject_kBool);
91 value->value.as_bool = val;
92 return value;
93}
94
95Dart_CObject* ApiMessageReader::AllocateDartCObjectInt32(int32_t val) {
96 Dart_CObject* value = AllocateDartCObject(Dart_CObject_kInt32);
97 value->value.as_int32 = val;
98 return value;
99}
100
101Dart_CObject* ApiMessageReader::AllocateDartCObjectInt64(int64_t val) {
102 Dart_CObject* value = AllocateDartCObject(Dart_CObject_kInt64);
103 value->value.as_int64 = val;
104 return value;
105}
106
107Dart_CObject* ApiMessageReader::AllocateDartCObjectDouble(double val) {
108 Dart_CObject* value = AllocateDartCObject(Dart_CObject_kDouble);
109 value->value.as_double = val;
110 return value;
111}
112
113Dart_CObject* ApiMessageReader::AllocateDartCObjectString(intptr_t length) {
114 // Allocate a Dart_CObject structure followed by an array of chars
115 // for the string content. The pointer to the string content is set
116 // up to this area.
117 Dart_CObject* value = reinterpret_cast<Dart_CObject*>(
118 allocator(sizeof(Dart_CObject) + length + 1));
119 ASSERT(value != NULL);
120 value->value.as_string = reinterpret_cast<char*>(value) + sizeof(*value);
121 value->type = Dart_CObject_kString;
122 return value;
123}
124
125static int GetTypedDataSizeInBytes(Dart_TypedData_Type type) {
126 switch (type) {
127 case Dart_TypedData_kInt8:
128 case Dart_TypedData_kUint8:
129 case Dart_TypedData_kUint8Clamped:
130 return 1;
131 case Dart_TypedData_kInt16:
132 case Dart_TypedData_kUint16:
133 return 2;
134 case Dart_TypedData_kInt32:
135 case Dart_TypedData_kUint32:
136 case Dart_TypedData_kFloat32:
137 return 4;
138 case Dart_TypedData_kInt64:
139 case Dart_TypedData_kUint64:
140 case Dart_TypedData_kFloat64:
141 return 8;
142 case Dart_TypedData_kInt32x4:
143 case Dart_TypedData_kFloat32x4:
144 case Dart_TypedData_kFloat64x2:
145 return 16;
146 default:
147 break;
148 }
149 UNREACHABLE();
150 return -1;
151}
152
153Dart_CObject* ApiMessageReader::AllocateDartCObjectTypedData(
154 Dart_TypedData_Type type,
155 intptr_t length) {
156 // Allocate a Dart_CObject structure followed by an array of bytes
157 // for the byte array content. The pointer to the byte array content
158 // is set up to this area.
159 intptr_t length_in_bytes = GetTypedDataSizeInBytes(type) * length;
160 Dart_CObject* value = reinterpret_cast<Dart_CObject*>(
161 allocator(sizeof(Dart_CObject) + length_in_bytes));
162 ASSERT(value != NULL);
163 value->type = Dart_CObject_kTypedData;
164 value->value.as_typed_data.type = type;
165 value->value.as_typed_data.length = length_in_bytes;
166 if (length > 0) {
167 value->value.as_typed_data.values =
168 reinterpret_cast<uint8_t*>(value) + sizeof(*value);
169 } else {
170 value->value.as_typed_data.values = NULL;
171 }
172 return value;
173}
174
175Dart_CObject* ApiMessageReader::AllocateDartCObjectArray(intptr_t length) {
176 // Allocate a Dart_CObject structure followed by an array of
177 // pointers to Dart_CObject structures. The pointer to the array
178 // content is set up to this area.
179 Dart_CObject* value = reinterpret_cast<Dart_CObject*>(
180 allocator(sizeof(Dart_CObject) + length * sizeof(value)));
181 ASSERT(value != NULL);
182 value->type = Dart_CObject_kArray;
183 value->value.as_array.length = length;
184 if (length > 0) {
185 value->value.as_array.values = reinterpret_cast<Dart_CObject**>(value + 1);
186 } else {
187 value->value.as_array.values = NULL;
188 }
189 return value;
190}
191
192Dart_CObject* ApiMessageReader::AllocateDartCObjectVmIsolateObj(intptr_t id) {
193 ObjectPtr raw = VmIsolateSnapshotObject(id);
194 intptr_t cid = raw->GetClassId();
195 switch (cid) {
196 case kOneByteStringCid: {
197 OneByteStringPtr raw_str = static_cast<OneByteStringPtr>(raw);
198 const char* str = reinterpret_cast<const char*>(raw_str->ptr()->data());
199 ASSERT(str != NULL);
200 Dart_CObject* object = NULL;
201 for (intptr_t i = 0; i < vm_isolate_references_.length(); i++) {
202 object = vm_isolate_references_.At(i);
203 if (object->type == Dart_CObject_kString) {
204 if (strcmp(str, object->value.as_string) == 0) {
205 return object;
206 }
207 }
208 }
209 object = CreateDartCObjectString(raw);
210 vm_isolate_references_.Add(object);
211 return object;
212 }
213
214 case kMintCid: {
215 const Mint& obj = Mint::Handle(static_cast<MintPtr>(raw));
216 int64_t value64 = obj.value();
217 if ((kMinInt32 <= value64) && (value64 <= kMaxInt32)) {
218 return GetCanonicalMintObject(Dart_CObject_kInt32, value64);
219 } else {
220 return GetCanonicalMintObject(Dart_CObject_kInt64, value64);
221 }
222 }
223
224 default:
225 UNREACHABLE();
226 return NULL;
227 }
228}
229
230Dart_CObject_Internal* ApiMessageReader::AllocateDartCObjectInternal(
231 Dart_CObject_Internal::Type type) {
232 Dart_CObject_Internal* value = reinterpret_cast<Dart_CObject_Internal*>(
233 allocator(sizeof(Dart_CObject_Internal)));
234 ASSERT(value != NULL);
235 value->type = static_cast<Dart_CObject_Type>(type);
236 return value;
237}
238
239Dart_CObject_Internal* ApiMessageReader::AllocateDartCObjectClass() {
240 return AllocateDartCObjectInternal(Dart_CObject_Internal::kClass);
241}
242
243ApiMessageReader::BackRefNode* ApiMessageReader::AllocateBackRefNode(
244 Dart_CObject* reference,
245 DeserializeState state) {
246 BackRefNode* value =
247 reinterpret_cast<BackRefNode*>(allocator(sizeof(BackRefNode)));
248 value->set_reference(reference);
249 value->set_state(state);
250 return value;
251}
252
253Dart_CObject* ApiMessageReader::ReadInlinedObject(intptr_t object_id) {
254 // Read the class header information and lookup the class.
255 intptr_t class_header = Read<int32_t>();
256 intptr_t tags = ReadTags();
257 USE(tags);
258 intptr_t class_id;
259
260 // There is limited support for reading regular dart instances. Only
261 // typed data views are currently handled.
262 if (SerializedHeaderData::decode(class_header) == kInstanceObjectId) {
263 Dart_CObject_Internal* object =
264 reinterpret_cast<Dart_CObject_Internal*>(GetBackRef(object_id));
265 if (object == NULL) {
266 object =
267 AllocateDartCObjectInternal(Dart_CObject_Internal::kUninitialized);
268 AddBackRef(object_id, object, kIsDeserialized);
269 // Read class of object.
270 object->cls = reinterpret_cast<Dart_CObject_Internal*>(ReadObjectImpl());
271 ASSERT(object->cls->type ==
272 static_cast<Dart_CObject_Type>(Dart_CObject_Internal::kClass));
273 }
274 ASSERT(object->type == static_cast<Dart_CObject_Type>(
275 Dart_CObject_Internal::kUninitialized));
276 return object;
277 }
278
279 ASSERT((class_header & kSmiTagMask) != 0);
280 class_id = LookupInternalClass(class_header);
281 if ((class_id == kArrayCid) || (class_id == kImmutableArrayCid)) {
282 intptr_t len = ReadSmiValue();
283 Dart_CObject* value = GetBackRef(object_id);
284 if (value == NULL) {
285 value = AllocateDartCObjectArray(len);
286 AddBackRef(object_id, value, kIsDeserialized);
287 }
288 // Skip type arguments.
289 // TODO(sjesse): Remove this when message serialization format is
290 // updated (currently type_arguments is leaked).
291 Dart_CObject* type_arguments = ReadObjectImpl();
292 if (type_arguments != &type_arguments_marker &&
293 type_arguments->type != Dart_CObject_kNull) {
294 return AllocateDartCObjectUnsupported();
295 }
296 for (int i = 0; i < len; i++) {
297 value->value.as_array.values[i] = ReadObjectRef();
298 }
299 return value;
300 }
301
302 return ReadInternalVMObject(class_id, object_id);
303}
304
305Dart_CObject* ApiMessageReader::ReadPredefinedSymbol(intptr_t object_id) {
306 ASSERT(Symbols::IsPredefinedSymbolId(object_id));
307 intptr_t symbol_id = object_id - kMaxPredefinedObjectIds;
308 Dart_CObject* object;
309 if (vm_symbol_references_ != NULL &&
310 (object = vm_symbol_references_[symbol_id]) != NULL) {
311 return object;
312 }
313
314 if (vm_symbol_references_ == NULL) {
315 intptr_t size =
316 (sizeof(*vm_symbol_references_) * Symbols::kMaxPredefinedId);
317 vm_symbol_references_ = reinterpret_cast<Dart_CObject**>(allocator(size));
318 memset(vm_symbol_references_, 0, size);
319 }
320
321 object = CreateDartCObjectString(Symbols::GetPredefinedSymbol(object_id));
322 ASSERT(vm_symbol_references_[symbol_id] == NULL);
323 vm_symbol_references_[symbol_id] = object;
324 return object;
325}
326
327intptr_t ApiMessageReader::NextAvailableObjectId() const {
328 return backward_references_.length() + kMaxPredefinedObjectIds;
329}
330
331Dart_CObject* ApiMessageReader::CreateDartCObjectString(ObjectPtr raw) {
332 ASSERT(IsOneByteStringClassId(raw->GetClassId()));
333 OneByteStringPtr raw_str = static_cast<OneByteStringPtr>(raw);
334 intptr_t len = Smi::Value(raw_str->ptr()->length_);
335 Dart_CObject* object = AllocateDartCObjectString(len);
336 char* p = object->value.as_string;
337 memmove(p, raw_str->ptr()->data(), len);
338 p[len] = '\0';
339 return object;
340}
341
342Dart_CObject* ApiMessageReader::GetCanonicalMintObject(Dart_CObject_Type type,
343 int64_t value64) {
344 Dart_CObject* object = NULL;
345 for (intptr_t i = 0; i < vm_isolate_references_.length(); i++) {
346 object = vm_isolate_references_.At(i);
347 if (object->type == type) {
348 if (value64 == object->value.as_int64) {
349 return object;
350 }
351 }
352 }
353 if (type == Dart_CObject_kInt32) {
354 object = AllocateDartCObjectInt32(static_cast<int32_t>(value64));
355 } else {
356 object = AllocateDartCObjectInt64(value64);
357 }
358 vm_isolate_references_.Add(object);
359 return object;
360}
361
362Dart_CObject* ApiMessageReader::ReadObjectRef() {
363 int64_t value64 = Read<int64_t>();
364 if ((value64 & kSmiTagMask) == 0) {
365 int64_t untagged_value = value64 >> kSmiTagShift;
366 if ((kMinInt32 <= untagged_value) && (untagged_value <= kMaxInt32)) {
367 return AllocateDartCObjectInt32(static_cast<int32_t>(untagged_value));
368 } else {
369 return AllocateDartCObjectInt64(untagged_value);
370 }
371 }
372 ASSERT((value64 <= kIntptrMax) && (value64 >= kIntptrMin));
373 intptr_t value = static_cast<intptr_t>(value64);
374 if (IsVMIsolateObject(value)) {
375 return ReadVMIsolateObject(value);
376 }
377 if (SerializedHeaderTag::decode(value) == kObjectId) {
378 return ReadIndexedObject(SerializedHeaderData::decode(value));
379 }
380 ASSERT(SerializedHeaderTag::decode(value) == kInlined);
381 // Read the class header information and lookup the class.
382 intptr_t class_header = Read<int32_t>();
383
384 intptr_t object_id = SerializedHeaderData::decode(value);
385 if (object_id == kOmittedObjectId) {
386 object_id = NextAvailableObjectId();
387 }
388
389 intptr_t tags = ReadTags();
390 USE(tags);
391
392 // Reading of regular dart instances has limited support in order to
393 // read typed data views.
394 if (SerializedHeaderData::decode(class_header) == kInstanceObjectId) {
395 Dart_CObject_Internal* object =
396 AllocateDartCObjectInternal(Dart_CObject_Internal::kUninitialized);
397 AddBackRef(object_id, object, kIsNotDeserialized);
398 // Read class of object.
399 object->cls = reinterpret_cast<Dart_CObject_Internal*>(ReadObjectImpl());
400 ASSERT(object->cls->type ==
401 static_cast<Dart_CObject_Type>(Dart_CObject_Internal::kClass));
402 return object;
403 }
404 ASSERT((class_header & kSmiTagMask) != 0);
405 intptr_t class_id = LookupInternalClass(class_header);
406 if ((class_id == kArrayCid) || (class_id == kImmutableArrayCid)) {
407 ASSERT(GetBackRef(object_id) == NULL);
408 intptr_t len = ReadSmiValue();
409 Dart_CObject* value = AllocateDartCObjectArray(len);
410 AddBackRef(object_id, value, kIsNotDeserialized);
411 return value;
412 }
413 return ReadInternalVMObject(class_id, object_id);
414}
415
416Dart_CObject* ApiMessageReader::ReadVMIsolateObject(intptr_t value) {
417 intptr_t object_id = GetVMIsolateObjectId(value);
418 if (object_id == kNullObject) {
419 return AllocateDartCObjectNull();
420 }
421 if (object_id == kTrueValue) {
422 return AllocateDartCObjectBool(true);
423 }
424 if (object_id == kFalseValue) {
425 return AllocateDartCObjectBool(false);
426 }
427 if (object_id == kDoubleObject) {
428 return AllocateDartCObjectDouble(ReadDouble());
429 }
430 if (Symbols::IsPredefinedSymbolId(object_id)) {
431 return ReadPredefinedSymbol(object_id);
432 }
433 // No other VM isolate objects are supported.
434 return AllocateDartCObjectNull();
435}
436
437Dart_CObject* ApiMessageReader::ReadInternalVMObject(intptr_t class_id,
438 intptr_t object_id) {
439 switch (class_id) {
440 case kClassCid: {
441 Dart_CObject_Internal* object = AllocateDartCObjectClass();
442 AddBackRef(object_id, object, kIsDeserialized);
443 object->internal.as_class.library_url = ReadObjectImpl();
444 ASSERT(object->internal.as_class.library_url->type ==
445 Dart_CObject_kString);
446 object->internal.as_class.class_name = ReadObjectImpl();
447 ASSERT(object->internal.as_class.class_name->type ==
448 Dart_CObject_kString);
449 return object;
450 }
451 case kTypeArgumentsCid: {
452 // TODO(sjesse): Remove this when message serialization format is
453 // updated (currently length is leaked).
454 Dart_CObject* value = &type_arguments_marker;
455 AddBackRef(object_id, value, kIsDeserialized);
456 Dart_CObject* length = ReadObjectImpl();
457 ASSERT(length->type == Dart_CObject_kInt32);
458 // The instantiations_ field is only written to a full snapshot.
459 for (int i = 0; i < length->value.as_int32; i++) {
460 Dart_CObject* type = ReadObjectImpl();
461 if (type != &dynamic_type_marker) {
462 return AllocateDartCObjectUnsupported();
463 }
464 }
465 return value;
466 }
467 case kTypeParameterCid: {
468 Dart_CObject* value = &dynamic_type_marker;
469 AddBackRef(object_id, value, kIsDeserialized);
470 intptr_t index = Read<int32_t>();
471 USE(index);
472 intptr_t token_index = Read<int32_t>();
473 USE(token_index);
474 int8_t type_state = Read<int8_t>();
475 USE(type_state);
476 Dart_CObject* parameterized_class = ReadObjectImpl();
477 // The type parameter is finalized, therefore parameterized_class is null.
478 ASSERT(parameterized_class->type == Dart_CObject_kNull);
479 Dart_CObject* name = ReadObjectImpl();
480 ASSERT(name->type == Dart_CObject_kString);
481 return value;
482 }
483 case kMintCid: {
484 int64_t value64 = Read<int64_t>();
485 Dart_CObject* object;
486 if ((kMinInt32 <= value64) && (value64 <= kMaxInt32)) {
487 object = AllocateDartCObjectInt32(static_cast<int32_t>(value64));
488 } else {
489 object = AllocateDartCObjectInt64(value64);
490 }
491 AddBackRef(object_id, object, kIsDeserialized);
492 return object;
493 }
494 case kDoubleCid: {
495 // Doubles are handled specially when being sent as part of message
496 // snapshots.
497 UNREACHABLE();
498 }
499 case kOneByteStringCid: {
500 intptr_t len = ReadSmiValue();
501 uint8_t* latin1 =
502 reinterpret_cast<uint8_t*>(allocator(len * sizeof(uint8_t)));
503 intptr_t utf8_len = 0;
504 for (intptr_t i = 0; i < len; i++) {
505 latin1[i] = Read<uint8_t>();
506 utf8_len += Utf8::Length(latin1[i]);
507 }
508 Dart_CObject* object = AllocateDartCObjectString(utf8_len);
509 AddBackRef(object_id, object, kIsDeserialized);
510 char* p = object->value.as_string;
511 for (intptr_t i = 0; i < len; i++) {
512 p += Utf8::Encode(latin1[i], p);
513 }
514 *p = '\0';
515 ASSERT(p == (object->value.as_string + utf8_len));
516 return object;
517 }
518 case kTwoByteStringCid: {
519 intptr_t len = ReadSmiValue();
520 uint16_t* utf16 =
521 reinterpret_cast<uint16_t*>(allocator(len * sizeof(uint16_t)));
522 intptr_t utf8_len = 0;
523 // Read all the UTF-16 code units.
524 for (intptr_t i = 0; i < len; i++) {
525 utf16[i] = Read<uint16_t>();
526 }
527 // Calculate the UTF-8 length and check if the string can be
528 // UTF-8 encoded.
529 bool valid = true;
530 intptr_t i = 0;
531 while (i < len && valid) {
532 int32_t ch = Utf16::Next(utf16, &i, len);
533 utf8_len += Utf8::Length(ch);
534 valid = !Utf16::IsSurrogate(ch);
535 }
536 if (!valid) {
537 return AllocateDartCObjectUnsupported();
538 }
539 Dart_CObject* object = AllocateDartCObjectString(utf8_len);
540 AddBackRef(object_id, object, kIsDeserialized);
541 char* p = object->value.as_string;
542 i = 0;
543 while (i < len) {
544 p += Utf8::Encode(Utf16::Next(utf16, &i, len), p);
545 }
546 *p = '\0';
547 ASSERT(p == (object->value.as_string + utf8_len));
548 return object;
549 }
550 case kSendPortCid: {
551 int64_t value64 = Read<int64_t>();
552 int64_t originId = Read<uint64_t>();
553 Dart_CObject* object = AllocateDartCObject(Dart_CObject_kSendPort);
554 object->value.as_send_port.id = value64;
555 object->value.as_send_port.origin_id = originId;
556 AddBackRef(object_id, object, kIsDeserialized);
557 return object;
558 }
559 case kCapabilityCid: {
560 int64_t id = Read<int64_t>();
561 Dart_CObject* object = AllocateDartCObject(Dart_CObject_kCapability);
562 object->value.as_capability.id = id;
563 AddBackRef(object_id, object, kIsDeserialized);
564 return object;
565 }
566
567#define READ_TYPED_DATA(tname, ctype) \
568 { \
569 intptr_t len = ReadSmiValue(); \
570 auto type = Dart_TypedData_k##tname; \
571 intptr_t length_in_bytes = GetTypedDataSizeInBytes(type) * len; \
572 Dart_CObject* object = \
573 reinterpret_cast<Dart_CObject*>(allocator(sizeof(Dart_CObject))); \
574 ASSERT(object != NULL); \
575 object->type = Dart_CObject_kTypedData; \
576 object->value.as_typed_data.type = type; \
577 object->value.as_typed_data.length = length_in_bytes; \
578 if (len > 0) { \
579 Align(Zone::kAlignment); \
580 object->value.as_typed_data.values = \
581 const_cast<uint8_t*>(CurrentBufferAddress()); \
582 Advance(length_in_bytes); \
583 } else { \
584 object->value.as_typed_data.values = NULL; \
585 } \
586 AddBackRef(object_id, object, kIsDeserialized); \
587 return object; \
588 }
589
590#define READ_EXTERNAL_TYPED_DATA(tname, ctype) \
591 { \
592 intptr_t len = ReadSmiValue(); \
593 auto type = Dart_TypedData_k##tname; \
594 intptr_t length_in_bytes = GetTypedDataSizeInBytes(type) * len; \
595 Dart_CObject* object = \
596 reinterpret_cast<Dart_CObject*>(allocator(sizeof(Dart_CObject))); \
597 ASSERT(object != NULL); \
598 object->type = Dart_CObject_kTypedData; \
599 object->value.as_typed_data.type = type; \
600 object->value.as_typed_data.length = length_in_bytes; \
601 object->value.as_typed_data.values = \
602 reinterpret_cast<uint8_t*>(finalizable_data_->Get().data); \
603 AddBackRef(object_id, object, kIsDeserialized); \
604 return object; \
605 }
606
607#define READ_TYPED_DATA_VIEW(tname, ctype) \
608 { \
609 Dart_CObject_Internal* object = \
610 AllocateDartCObjectInternal(Dart_CObject_Internal::kUninitialized); \
611 AddBackRef(object_id, object, kIsDeserialized); \
612 object->type = \
613 static_cast<Dart_CObject_Type>(Dart_CObject_Internal::kView); \
614 object->internal.as_view.offset_in_bytes = ReadSmiValue(); \
615 object->internal.as_view.length = ReadSmiValue(); \
616 object->internal.as_view.buffer = ReadObjectImpl(); \
617 Dart_CObject* buffer = object->internal.as_view.buffer; \
618 RELEASE_ASSERT(buffer->type == Dart_CObject_kTypedData); \
619 \
620 /* Now turn the view into a byte array.*/ \
621 const Dart_TypedData_Type type = Dart_TypedData_k##tname; \
622 object->type = Dart_CObject_kTypedData; \
623 object->value.as_typed_data.type = type; \
624 object->value.as_typed_data.length = \
625 object->internal.as_view.length * GetTypedDataSizeInBytes(type); \
626 object->value.as_typed_data.values = \
627 buffer->value.as_typed_data.values + \
628 object->internal.as_view.offset_in_bytes; \
629 return object; \
630 }
631
632#define TYPED_DATA_LIST(V) \
633 V(Int8, int8_t) \
634 V(Uint8, uint8_t) \
635 V(Uint8Clamped, uint8_t) \
636 V(Int16, int16_t) \
637 V(Uint16, uint16_t) \
638 V(Int32, int32_t) \
639 V(Uint32, uint32_t) \
640 V(Int64, int64_t) \
641 V(Uint64, uint64_t) \
642 V(Float32, float) \
643 V(Float64, double) \
644 V(Int32x4, simd128_value_t) \
645 V(Float32x4, simd128_value_t) \
646 V(Float64x2, simd128_value_t)
647
648#define EMIT_TYPED_DATA_CASES(type, c_type) \
649 case kTypedData##type##ArrayCid: \
650 READ_TYPED_DATA(type, c_type); \
651 case kExternalTypedData##type##ArrayCid: \
652 READ_EXTERNAL_TYPED_DATA(type, c_type); \
653 case kTypedData##type##ArrayViewCid: \
654 READ_TYPED_DATA_VIEW(type, c_type);
655
656 TYPED_DATA_LIST(EMIT_TYPED_DATA_CASES)
657#undef EMIT_TYPED_DATA_CASES
658#undef TYPED_DATA_LIST
659#undef READ_TYPED_DATA
660#undef READ_EXTERNAL_TYPED_DATA
661#undef READ_TYPED_DATA_VIEW
662
663 case kGrowableObjectArrayCid: {
664 // A GrowableObjectArray is serialized as its type arguments and
665 // length followed by its backing store. The backing store is an
666 // array with a length which might be longer than the length of
667 // the GrowableObjectArray.
668 Dart_CObject* value = GetBackRef(object_id);
669 ASSERT(value == NULL);
670 // Allocate an empty array for the GrowableObjectArray which
671 // will be updated to point to the content when the backing
672 // store has been deserialized.
673 value = AllocateDartCObjectArray(0);
674 AddBackRef(object_id, value, kIsDeserialized);
675
676 // Read and skip the type arguments field.
677 // TODO(sjesse): Remove this when message serialization format is
678 // updated (currently type_arguments is leaked).
679 Dart_CObject* type_arguments = ReadObjectImpl();
680 if (type_arguments != &type_arguments_marker &&
681 type_arguments->type != Dart_CObject_kNull) {
682 return AllocateDartCObjectUnsupported();
683 }
684
685 // Read the length field.
686 intptr_t len = ReadSmiValue();
687
688 // Read the content of the GrowableObjectArray.
689 Dart_CObject* content = ReadObjectRef();
690 ASSERT(content->type == Dart_CObject_kArray);
691 // Make the empty array allocated point to the backing store content.
692 value->value.as_array.length = len;
693 value->value.as_array.values = content->value.as_array.values;
694 return value;
695 }
696 default:
697 // Everything else not supported.
698 Dart_CObject* value = AllocateDartCObjectUnsupported();
699 AddBackRef(object_id, value, kIsDeserialized);
700 return value;
701 }
702}
703
704Dart_CObject* ApiMessageReader::ReadIndexedObject(intptr_t object_id) {
705 if (object_id >= kFirstTypeSnapshotId && object_id <= kLastTypeSnapshotId) {
706 // Always return dynamic type (this is only a marker).
707 return &dynamic_type_marker;
708 }
709 if (object_id >= kFirstTypeArgumentsSnapshotId &&
710 object_id <= kLastTypeArgumentsSnapshotId) {
711 return &type_arguments_marker;
712 }
713
714 intptr_t index = object_id - kMaxPredefinedObjectIds;
715 ASSERT((0 <= index) && (index < backward_references_.length()));
716 ASSERT(backward_references_[index]->reference() != NULL);
717 return backward_references_[index]->reference();
718}
719
720Dart_CObject* ApiMessageReader::ReadObject() {
721 Dart_CObject* value = ReadObjectImpl();
722 for (intptr_t i = 0; i < backward_references_.length(); i++) {
723 if (!backward_references_[i]->is_deserialized()) {
724 ReadObjectImpl();
725 backward_references_[i]->set_state(kIsDeserialized);
726 }
727 }
728 return value;
729}
730
731Dart_CObject* ApiMessageReader::ReadObjectImpl() {
732 int64_t value64 = Read<int64_t>();
733 if ((value64 & kSmiTagMask) == 0) {
734 int64_t untagged_value = value64 >> kSmiTagShift;
735 if ((kMinInt32 <= untagged_value) && (untagged_value <= kMaxInt32)) {
736 return AllocateDartCObjectInt32(static_cast<int32_t>(untagged_value));
737 } else {
738 return AllocateDartCObjectInt64(untagged_value);
739 }
740 }
741 ASSERT((value64 <= kIntptrMax) && (value64 >= kIntptrMin));
742 intptr_t value = static_cast<intptr_t>(value64);
743 if (IsVMIsolateObject(value)) {
744 return ReadVMIsolateObject(value);
745 }
746 if (SerializedHeaderTag::decode(value) == kObjectId) {
747 return ReadIndexedObject(SerializedHeaderData::decode(value));
748 }
749 ASSERT(SerializedHeaderTag::decode(value) == kInlined);
750
751 intptr_t object_id = SerializedHeaderData::decode(value);
752 if (object_id == kOmittedObjectId) {
753 object_id = NextAvailableObjectId();
754 }
755 return ReadInlinedObject(object_id);
756}
757
758void ApiMessageReader::AddBackRef(intptr_t id,
759 Dart_CObject* obj,
760 DeserializeState state) {
761 intptr_t index = (id - kMaxPredefinedObjectIds);
762 ASSERT(index == backward_references_.length());
763 BackRefNode* node = AllocateBackRefNode(obj, state);
764 ASSERT(node != NULL);
765 backward_references_.Add(node);
766}
767
768Dart_CObject* ApiMessageReader::GetBackRef(intptr_t id) {
769 ASSERT(id >= kMaxPredefinedObjectIds);
770 intptr_t index = (id - kMaxPredefinedObjectIds);
771 if (index < backward_references_.length()) {
772 return backward_references_[index]->reference();
773 }
774 return NULL;
775}
776
777static uint8_t* malloc_allocator(uint8_t* ptr,
778 intptr_t old_size,
779 intptr_t new_size) {
780 void* new_ptr = realloc(reinterpret_cast<void*>(ptr), new_size);
781 return reinterpret_cast<uint8_t*>(new_ptr);
782}
783
784ApiMessageWriter::ApiMessageWriter()
785 : BaseWriter(malloc_allocator, NULL, kInitialSize),
786 object_id_(0),
787 forward_list_(NULL),
788 forward_list_length_(0),
789 forward_id_(0),
790 finalizable_data_(new MessageFinalizableData()) {
791 ASSERT(kDartCObjectTypeMask >= Dart_CObject_kNumberOfTypes - 1);
792}
793
794ApiMessageWriter::~ApiMessageWriter() {
795 ::free(forward_list_);
796 delete finalizable_data_;
797}
798
799NO_SANITIZE_UNDEFINED(
800 "enum") // TODO(https://github.com/dart-lang/sdk/issues/39427)
801void ApiMessageWriter::MarkCObject(Dart_CObject* object, intptr_t object_id) {
802 // Mark the object as serialized by adding the object id to the
803 // upper bits of the type field in the Dart_CObject structure. Add
804 // an offset for making marking of object id 0 possible.
805 ASSERT(!IsCObjectMarked(object));
806 intptr_t mark_value = object_id + kDartCObjectMarkOffset;
807 object->type = static_cast<Dart_CObject_Type>(
808 ((mark_value) << kDartCObjectTypeBits) | object->type);
809}
810
811NO_SANITIZE_UNDEFINED(
812 "enum") // TODO(https://github.com/dart-lang/sdk/issues/39427)
813void ApiMessageWriter::UnmarkCObject(Dart_CObject* object) {
814 ASSERT(IsCObjectMarked(object));
815 object->type =
816 static_cast<Dart_CObject_Type>(object->type & kDartCObjectTypeMask);
817}
818
819NO_SANITIZE_UNDEFINED(
820 "enum") // TODO(https://github.com/dart-lang/sdk/issues/39427)
821bool ApiMessageWriter::IsCObjectMarked(Dart_CObject* object) {
822 return (object->type & kDartCObjectMarkMask) != 0;
823}
824
825NO_SANITIZE_UNDEFINED(
826 "enum") // TODO(https://github.com/dart-lang/sdk/issues/39427)
827intptr_t ApiMessageWriter::GetMarkedCObjectMark(Dart_CObject* object) {
828 ASSERT(IsCObjectMarked(object));
829 intptr_t mark_value =
830 ((object->type & kDartCObjectMarkMask) >> kDartCObjectTypeBits);
831 // An offset was added to object id for making marking object id 0 possible.
832 return mark_value - kDartCObjectMarkOffset;
833}
834
835void ApiMessageWriter::UnmarkAllCObjects(Dart_CObject* object) {
836 if (!IsCObjectMarked(object)) return;
837 UnmarkCObject(object);
838 if (object->type == Dart_CObject_kArray) {
839 for (int i = 0; i < object->value.as_array.length; i++) {
840 Dart_CObject* element = object->value.as_array.values[i];
841 UnmarkAllCObjects(element);
842 }
843 }
844}
845
846void ApiMessageWriter::AddToForwardList(Dart_CObject* object) {
847 if (forward_id_ >= forward_list_length_) {
848 void* new_list = NULL;
849 if (forward_list_length_ == 0) {
850 forward_list_length_ = 4;
851 intptr_t new_size = forward_list_length_ * sizeof(object);
852 new_list = ::malloc(new_size);
853 } else {
854 forward_list_length_ *= 2;
855 intptr_t new_size = (forward_list_length_ * sizeof(object));
856 new_list = ::realloc(forward_list_, new_size);
857 }
858 ASSERT(new_list != NULL);
859 forward_list_ = reinterpret_cast<Dart_CObject**>(new_list);
860 }
861 forward_list_[forward_id_] = object;
862 forward_id_ += 1;
863}
864
865void ApiMessageWriter::WriteSmi(int64_t value) {
866 ASSERT(Smi::IsValid(value));
867 Write<ObjectPtr>(Smi::New(static_cast<intptr_t>(value)));
868}
869
870void ApiMessageWriter::WriteNullObject() {
871 WriteVMIsolateObject(kNullObject);
872}
873
874void ApiMessageWriter::WriteMint(Dart_CObject* object, int64_t value) {
875 ASSERT(!Smi::IsValid(value));
876 // Write out the serialization header value for mint object.
877 WriteInlinedHeader(object);
878 // Write out the class and tags information.
879 WriteIndexedObject(kMintCid);
880 WriteTags(0);
881 // Write the 64-bit value.
882 Write<int64_t>(value);
883}
884
885void ApiMessageWriter::WriteInt32(Dart_CObject* object) {
886 int64_t value = object->value.as_int32;
887 if (Smi::IsValid(value)) {
888 WriteSmi(value);
889 } else {
890 WriteMint(object, value);
891 }
892}
893
894void ApiMessageWriter::WriteInt64(Dart_CObject* object) {
895 int64_t value = object->value.as_int64;
896 if (Smi::IsValid(value)) {
897 WriteSmi(value);
898 } else {
899 WriteMint(object, value);
900 }
901}
902
903void ApiMessageWriter::WriteInlinedHeader(Dart_CObject* object) {
904 // Write out the serialization header value for this object.
905 WriteInlinedObjectHeader(kMaxPredefinedObjectIds + object_id_);
906 // Mark object with its object id.
907 MarkCObject(object, object_id_);
908 // Advance object id.
909 object_id_++;
910}
911
912bool ApiMessageWriter::WriteCObject(Dart_CObject* object) {
913 if (IsCObjectMarked(object)) {
914 intptr_t object_id = GetMarkedCObjectMark(object);
915 WriteIndexedObject(kMaxPredefinedObjectIds + object_id);
916 return true;
917 }
918
919 Dart_CObject_Type type = object->type;
920 if (type == Dart_CObject_kArray) {
921 const intptr_t array_length = object->value.as_array.length;
922 if (!Array::IsValidLength(array_length)) {
923 return false;
924 }
925
926 // Write out the serialization header value for this object.
927 WriteInlinedHeader(object);
928 // Write out the class and tags information.
929 WriteIndexedObject(kArrayCid);
930 WriteTags(0);
931 // Write out the length information.
932 WriteSmi(array_length);
933 // Write out the type arguments.
934 WriteNullObject();
935 // Write out array elements.
936 for (int i = 0; i < array_length; i++) {
937 bool success = WriteCObjectRef(object->value.as_array.values[i]);
938 if (!success) return false;
939 }
940 return true;
941 }
942 return WriteCObjectInlined(object, type);
943}
944
945bool ApiMessageWriter::WriteCObjectRef(Dart_CObject* object) {
946 if (IsCObjectMarked(object)) {
947 intptr_t object_id = GetMarkedCObjectMark(object);
948 WriteIndexedObject(kMaxPredefinedObjectIds + object_id);
949 return true;
950 }
951
952 Dart_CObject_Type type = object->type;
953 if (type == Dart_CObject_kArray) {
954 const intptr_t array_length = object->value.as_array.length;
955 if (!Array::IsValidLength(array_length)) {
956 return false;
957 }
958 // Write out the serialization header value for this object.
959 WriteInlinedHeader(object);
960 // Write out the class information.
961 WriteIndexedObject(kArrayCid);
962 WriteTags(0);
963 // Write out the length information.
964 WriteSmi(array_length);
965 // Add object to forward list so that this object is serialized later.
966 AddToForwardList(object);
967 return true;
968 }
969 return WriteCObjectInlined(object, type);
970}
971
972NO_SANITIZE_UNDEFINED(
973 "enum") // TODO(https://github.com/dart-lang/sdk/issues/39427)
974bool ApiMessageWriter::WriteForwardedCObject(Dart_CObject* object) {
975 ASSERT(IsCObjectMarked(object));
976 Dart_CObject_Type type =
977 static_cast<Dart_CObject_Type>(object->type & kDartCObjectTypeMask);
978 ASSERT(type == Dart_CObject_kArray);
979 const intptr_t array_length = object->value.as_array.length;
980 if (!Array::IsValidLength(array_length)) {
981 return false;
982 }
983
984 // Write out the serialization header value for this object.
985 intptr_t object_id = GetMarkedCObjectMark(object);
986 WriteInlinedObjectHeader(kMaxPredefinedObjectIds + object_id);
987 // Write out the class and tags information.
988 WriteIndexedObject(kArrayCid);
989 WriteTags(0);
990 // Write out the length information.
991 WriteSmi(array_length);
992 // Write out the type arguments.
993 WriteNullObject();
994 // Write out array elements.
995 for (int i = 0; i < array_length; i++) {
996 bool success = WriteCObjectRef(object->value.as_array.values[i]);
997 if (!success) return false;
998 }
999 return true;
1000}
1001
1002bool ApiMessageWriter::WriteCObjectInlined(Dart_CObject* object,
1003 Dart_CObject_Type type) {
1004 switch (type) {
1005 case Dart_CObject_kNull:
1006 WriteNullObject();
1007 break;
1008 case Dart_CObject_kBool:
1009 if (object->value.as_bool) {
1010 WriteVMIsolateObject(kTrueValue);
1011 } else {
1012 WriteVMIsolateObject(kFalseValue);
1013 }
1014 break;
1015 case Dart_CObject_kInt32:
1016 WriteInt32(object);
1017 break;
1018 case Dart_CObject_kInt64:
1019 WriteInt64(object);
1020 break;
1021 case Dart_CObject_kDouble:
1022 WriteVMIsolateObject(kDoubleObject);
1023 WriteDouble(object->value.as_double);
1024 break;
1025 case Dart_CObject_kString: {
1026 const uint8_t* utf8_str =
1027 reinterpret_cast<const uint8_t*>(object->value.as_string);
1028 intptr_t utf8_len = strlen(object->value.as_string);
1029 if (!Utf8::IsValid(utf8_str, utf8_len)) {
1030 return false;
1031 }
1032
1033 Utf8::Type type = Utf8::kLatin1;
1034 intptr_t len = Utf8::CodeUnitCount(utf8_str, utf8_len, &type);
1035 if (len > String::kMaxElements) {
1036 return false;
1037 }
1038
1039 // Write out the serialization header value for this object.
1040 WriteInlinedHeader(object);
1041 // Write out the class and tags information.
1042 WriteIndexedObject(type == Utf8::kLatin1 ? kOneByteStringCid
1043 : kTwoByteStringCid);
1044 WriteTags(0);
1045 // Write string length and content.
1046 WriteSmi(len);
1047 if (type == Utf8::kLatin1) {
1048 uint8_t* latin1_str =
1049 reinterpret_cast<uint8_t*>(::malloc(len * sizeof(uint8_t)));
1050 bool success =
1051 Utf8::DecodeToLatin1(utf8_str, utf8_len, latin1_str, len);
1052 ASSERT(success);
1053 for (intptr_t i = 0; i < len; i++) {
1054 Write<uint8_t>(latin1_str[i]);
1055 }
1056 ::free(latin1_str);
1057 } else {
1058 uint16_t* utf16_str =
1059 reinterpret_cast<uint16_t*>(::malloc(len * sizeof(uint16_t)));
1060 bool success = Utf8::DecodeToUTF16(utf8_str, utf8_len, utf16_str, len);
1061 ASSERT(success);
1062 for (intptr_t i = 0; i < len; i++) {
1063 Write<uint16_t>(utf16_str[i]);
1064 }
1065 ::free(utf16_str);
1066 }
1067 break;
1068 }
1069 case Dart_CObject_kTypedData: {
1070 // Write out the serialization header value for this object.
1071 WriteInlinedHeader(object);
1072 // Write out the class and tags information.
1073 intptr_t class_id;
1074 switch (object->value.as_typed_data.type) {
1075 case Dart_TypedData_kInt8:
1076 class_id = kTypedDataInt8ArrayCid;
1077 break;
1078 case Dart_TypedData_kUint8:
1079 class_id = kTypedDataUint8ArrayCid;
1080 break;
1081 case Dart_TypedData_kUint32:
1082 class_id = kTypedDataUint32ArrayCid;
1083 break;
1084 default:
1085 class_id = kTypedDataUint8ArrayCid;
1086 UNIMPLEMENTED();
1087 }
1088
1089 intptr_t len = object->value.as_typed_data.length;
1090 if (len < 0 || len > TypedData::MaxElements(class_id)) {
1091 return false;
1092 }
1093
1094 WriteIndexedObject(class_id);
1095 WriteTags(0);
1096 WriteSmi(len);
1097 switch (class_id) {
1098 case kTypedDataInt8ArrayCid:
1099 case kTypedDataUint8ArrayCid: {
1100 uint8_t* bytes = object->value.as_typed_data.values;
1101 Align(Zone::kAlignment);
1102 WriteBytes(bytes, len);
1103 break;
1104 }
1105 case kTypedDataUint32ArrayCid: {
1106 uint8_t* bytes = object->value.as_typed_data.values;
1107 Align(Zone::kAlignment);
1108 WriteBytes(bytes, len * sizeof(uint32_t));
1109 break;
1110 }
1111 default:
1112 UNIMPLEMENTED();
1113 }
1114 break;
1115 }
1116 case Dart_CObject_kExternalTypedData: {
1117 // TODO(ager): we are writing C pointers into the message in
1118 // order to post external arrays through ports. We need to make
1119 // sure that messages containing pointers can never be posted
1120 // to other processes.
1121
1122 // Write out serialization header value for this object.
1123 WriteInlinedHeader(object);
1124 // Write out the class and tag information.
1125 WriteIndexedObject(kExternalTypedDataUint8ArrayCid);
1126 WriteTags(0);
1127 intptr_t length = object->value.as_external_typed_data.length;
1128 if (length < 0 || length > ExternalTypedData::MaxElements(
1129 kExternalTypedDataUint8ArrayCid)) {
1130 return false;
1131 }
1132 uint8_t* data = object->value.as_external_typed_data.data;
1133 void* peer = object->value.as_external_typed_data.peer;
1134 Dart_WeakPersistentHandleFinalizer callback =
1135 object->value.as_external_typed_data.callback;
1136 if (callback == NULL) {
1137 return false;
1138 }
1139 WriteSmi(length);
1140 finalizable_data_->Put(length, reinterpret_cast<void*>(data), peer,
1141 callback);
1142 break;
1143 }
1144 case Dart_CObject_kSendPort: {
1145 WriteInlinedHeader(object);
1146 WriteIndexedObject(kSendPortCid);
1147 WriteTags(0);
1148 Write<int64_t>(object->value.as_send_port.id);
1149 Write<uint64_t>(object->value.as_send_port.origin_id);
1150 break;
1151 }
1152 case Dart_CObject_kCapability: {
1153 WriteInlinedHeader(object);
1154 WriteIndexedObject(kCapabilityCid);
1155 WriteTags(0);
1156 Write<uint64_t>(object->value.as_capability.id);
1157 break;
1158 }
1159 default:
1160 FATAL1("Unexpected Dart_CObject_Type %d\n", type);
1161 }
1162
1163 return true;
1164}
1165
1166std::unique_ptr<Message> ApiMessageWriter::WriteCMessage(
1167 Dart_CObject* object,
1168 Dart_Port dest_port,
1169 Message::Priority priority) {
1170 bool success = WriteCObject(object);
1171 if (!success) {
1172 UnmarkAllCObjects(object);
1173 free(buffer());
1174 return nullptr;
1175 }
1176
1177 // Write out all objects that were added to the forward list and have
1178 // not been serialized yet. These would typically be fields of arrays.
1179 // NOTE: The forward list might grow as we process the list.
1180 for (intptr_t i = 0; i < forward_id_; i++) {
1181 success = WriteForwardedCObject(forward_list_[i]);
1182 if (!success) {
1183 UnmarkAllCObjects(object);
1184 free(buffer());
1185 return nullptr;
1186 }
1187 }
1188
1189 UnmarkAllCObjects(object);
1190 MessageFinalizableData* finalizable_data = finalizable_data_;
1191 finalizable_data_ = NULL;
1192 return Message::New(dest_port, buffer(), BytesWritten(), finalizable_data,
1193 priority);
1194}
1195
1196} // namespace dart
1197