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 | |
15 | namespace dart { |
16 | |
17 | static const int kNumInitialReferences = 4; |
18 | |
19 | ApiMessageReader::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 | |
30 | ApiMessageReader::~ApiMessageReader() {} |
31 | |
32 | void 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 | |
49 | Dart_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 | |
65 | intptr_t ApiMessageReader::LookupInternalClass(intptr_t ) { |
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 | |
73 | Dart_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 | |
81 | Dart_CObject* ApiMessageReader::AllocateDartCObjectUnsupported() { |
82 | return AllocateDartCObject(Dart_CObject_kUnsupported); |
83 | } |
84 | |
85 | Dart_CObject* ApiMessageReader::AllocateDartCObjectNull() { |
86 | return AllocateDartCObject(Dart_CObject_kNull); |
87 | } |
88 | |
89 | Dart_CObject* ApiMessageReader::AllocateDartCObjectBool(bool val) { |
90 | Dart_CObject* value = AllocateDartCObject(Dart_CObject_kBool); |
91 | value->value.as_bool = val; |
92 | return value; |
93 | } |
94 | |
95 | Dart_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 | |
101 | Dart_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 | |
107 | Dart_CObject* ApiMessageReader::AllocateDartCObjectDouble(double val) { |
108 | Dart_CObject* value = AllocateDartCObject(Dart_CObject_kDouble); |
109 | value->value.as_double = val; |
110 | return value; |
111 | } |
112 | |
113 | Dart_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 | |
125 | static 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 | |
153 | Dart_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 | |
175 | Dart_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 | |
192 | Dart_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 | |
230 | Dart_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 | |
239 | Dart_CObject_Internal* ApiMessageReader::AllocateDartCObjectClass() { |
240 | return AllocateDartCObjectInternal(Dart_CObject_Internal::kClass); |
241 | } |
242 | |
243 | ApiMessageReader::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 | |
253 | Dart_CObject* ApiMessageReader::ReadInlinedObject(intptr_t object_id) { |
254 | // Read the class header information and lookup the class. |
255 | intptr_t = 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 | |
305 | Dart_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 | |
327 | intptr_t ApiMessageReader::NextAvailableObjectId() const { |
328 | return backward_references_.length() + kMaxPredefinedObjectIds; |
329 | } |
330 | |
331 | Dart_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 | |
342 | Dart_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 | |
362 | Dart_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 = 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 | |
416 | Dart_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 | |
437 | Dart_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 | |
704 | Dart_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 | |
720 | Dart_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 | |
731 | Dart_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 | |
758 | void 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 | |
768 | Dart_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 | |
777 | static 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 | |
784 | ApiMessageWriter::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 | |
794 | ApiMessageWriter::~ApiMessageWriter() { |
795 | ::free(forward_list_); |
796 | delete finalizable_data_; |
797 | } |
798 | |
799 | NO_SANITIZE_UNDEFINED( |
800 | "enum" ) // TODO(https://github.com/dart-lang/sdk/issues/39427) |
801 | void 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 | |
811 | NO_SANITIZE_UNDEFINED( |
812 | "enum" ) // TODO(https://github.com/dart-lang/sdk/issues/39427) |
813 | void ApiMessageWriter::UnmarkCObject(Dart_CObject* object) { |
814 | ASSERT(IsCObjectMarked(object)); |
815 | object->type = |
816 | static_cast<Dart_CObject_Type>(object->type & kDartCObjectTypeMask); |
817 | } |
818 | |
819 | NO_SANITIZE_UNDEFINED( |
820 | "enum" ) // TODO(https://github.com/dart-lang/sdk/issues/39427) |
821 | bool ApiMessageWriter::IsCObjectMarked(Dart_CObject* object) { |
822 | return (object->type & kDartCObjectMarkMask) != 0; |
823 | } |
824 | |
825 | NO_SANITIZE_UNDEFINED( |
826 | "enum" ) // TODO(https://github.com/dart-lang/sdk/issues/39427) |
827 | intptr_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 | |
835 | void 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 | |
846 | void 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 | |
865 | void ApiMessageWriter::WriteSmi(int64_t value) { |
866 | ASSERT(Smi::IsValid(value)); |
867 | Write<ObjectPtr>(Smi::New(static_cast<intptr_t>(value))); |
868 | } |
869 | |
870 | void ApiMessageWriter::WriteNullObject() { |
871 | WriteVMIsolateObject(kNullObject); |
872 | } |
873 | |
874 | void 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 | |
885 | void 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 | |
894 | void 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 | |
903 | void ApiMessageWriter::(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 | |
912 | bool 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 | |
945 | bool 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 | |
972 | NO_SANITIZE_UNDEFINED( |
973 | "enum" ) // TODO(https://github.com/dart-lang/sdk/issues/39427) |
974 | bool 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 | |
1002 | bool 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 | |
1166 | std::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 | |