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 "vm/dart_api_state.h"
6#include "vm/message.h"
7#include "vm/native_entry.h"
8#include "vm/object.h"
9#include "vm/object_store.h"
10#include "vm/snapshot.h"
11#include "vm/stub_code.h"
12#include "vm/symbols.h"
13#include "vm/type_testing_stubs.h"
14#include "vm/visitor.h"
15
16namespace dart {
17
18// TODO(dartbug.com/34796): enable or remove this optimization.
19DEFINE_FLAG(
20 uint64_t,
21 externalize_typed_data_threshold,
22 kMaxUint64,
23 "Convert TypedData to ExternalTypedData when sending through a message"
24 " port after it exceeds certain size in bytes.");
25
26#define OFFSET_OF_FROM(obj) \
27 obj.raw()->from() - reinterpret_cast<ObjectPtr*>(obj.raw()->ptr())
28
29// TODO(18854): Need to assert No GC can happen here, even though
30// allocations may happen.
31#define READ_OBJECT_FIELDS(object, from, to, as_reference) \
32 intptr_t num_flds = (to) - (from); \
33 for (intptr_t i = 0; i <= num_flds; i++) { \
34 (*reader->PassiveObjectHandle()) = reader->ReadObjectImpl(as_reference); \
35 object.StorePointer(((from) + i), reader->PassiveObjectHandle()->raw()); \
36 }
37
38ClassPtr Class::ReadFrom(SnapshotReader* reader,
39 intptr_t object_id,
40 intptr_t tags,
41 Snapshot::Kind kind,
42 bool as_reference) {
43 ASSERT(reader != NULL);
44
45 Class& cls = Class::ZoneHandle(reader->zone(), Class::null());
46 cls = reader->ReadClassId(object_id);
47 return cls.raw();
48}
49
50void ClassLayout::WriteTo(SnapshotWriter* writer,
51 intptr_t object_id,
52 Snapshot::Kind kind,
53 bool as_reference) {
54 ASSERT(writer != NULL);
55
56 // Write out the serialization header value for this object.
57 writer->WriteInlinedObjectHeader(object_id);
58
59 // Write out the class and tags information.
60 writer->WriteVMIsolateObject(kClassCid);
61 writer->WriteTags(writer->GetObjectTags(this));
62
63 if (writer->can_send_any_object() ||
64 writer->AllowObjectsInDartLibrary(library_)) {
65 writer->WriteClassId(this);
66 } else {
67 // We do not allow regular dart instances in isolate messages.
68 writer->SetWriteException(Exceptions::kArgument,
69 "Illegal argument in isolate message"
70 " : (object is a regular Dart Instance)");
71 }
72}
73
74TypePtr Type::ReadFrom(SnapshotReader* reader,
75 intptr_t object_id,
76 intptr_t tags,
77 Snapshot::Kind kind,
78 bool as_reference) {
79 ASSERT(reader != NULL);
80
81 // Determine if the type class of this type is in the full snapshot.
82 reader->Read<bool>();
83
84 // Allocate type object.
85 Type& type = Type::ZoneHandle(reader->zone(), Type::New());
86 bool is_canonical = ObjectLayout::IsCanonical(tags);
87 reader->AddBackRef(object_id, &type, kIsDeserialized);
88
89 // Set all non object fields.
90 type.set_token_pos(TokenPosition::SnapshotDecode(reader->Read<int32_t>()));
91 const uint8_t combined = reader->Read<uint8_t>();
92 type.set_type_state(combined >> 4);
93 type.set_nullability(static_cast<Nullability>(combined & 0xf));
94
95 // Read the code object for the type testing stub and set its entrypoint.
96 reader->EnqueueTypePostprocessing(type);
97
98 // Set all the object fields.
99 READ_OBJECT_FIELDS(type, type.raw()->ptr()->from(), type.raw()->ptr()->to(),
100 as_reference);
101
102 // Read in the type class.
103 (*reader->ClassHandle()) =
104 Class::RawCast(reader->ReadObjectImpl(as_reference));
105 type.set_type_class(*reader->ClassHandle());
106
107 // Fill in the type testing stub.
108 Code& code = *reader->CodeHandle();
109 code = TypeTestingStubGenerator::DefaultCodeForType(type);
110 type.SetTypeTestingStub(code);
111
112 if (is_canonical) {
113 type ^= type.Canonicalize();
114 }
115
116 return type.raw();
117}
118
119void TypeLayout::WriteTo(SnapshotWriter* writer,
120 intptr_t object_id,
121 Snapshot::Kind kind,
122 bool as_reference) {
123 ASSERT(writer != NULL);
124
125 if (signature_ != Function::null()) {
126 writer->SetWriteException(Exceptions::kArgument,
127 "Illegal argument in isolate message"
128 " : (function types are not supported yet)");
129 UNREACHABLE();
130 }
131
132 // Only resolved and finalized types should be written to a snapshot.
133 ASSERT((type_state_ == TypeLayout::kFinalizedInstantiated) ||
134 (type_state_ == TypeLayout::kFinalizedUninstantiated));
135 ASSERT(type_class_id_ != Object::null());
136
137 // Write out the serialization header value for this object.
138 writer->WriteInlinedObjectHeader(object_id);
139
140 // Write out the class and tags information.
141 writer->WriteIndexedObject(kTypeCid);
142 writer->WriteTags(writer->GetObjectTags(this));
143
144 if (type_class_id_->IsHeapObject()) {
145 // Type class is still an unresolved class.
146 UNREACHABLE();
147 }
148
149 // Lookup the type class.
150 SmiPtr raw_type_class_id = Smi::RawCast(type_class_id_);
151 ClassPtr type_class =
152 writer->isolate()->class_table()->At(Smi::Value(raw_type_class_id));
153
154 // Write out typeclass_is_in_fullsnapshot first as this will
155 // help the reader decide on how to canonicalize the type object.
156 intptr_t tags = writer->GetObjectTags(type_class);
157 bool typeclass_is_in_fullsnapshot =
158 (ClassIdTag::decode(tags) == kClassCid) &&
159 Class::IsInFullSnapshot(static_cast<ClassPtr>(type_class));
160 writer->Write<bool>(typeclass_is_in_fullsnapshot);
161
162 // Write out all the non object pointer fields.
163 writer->Write<int32_t>(token_pos_.SnapshotEncode());
164 const uint8_t combined = (type_state_ << 4) | nullability_;
165 ASSERT(type_state_ == (combined >> 4));
166 ASSERT(nullability_ == (combined & 0xf));
167 writer->Write<uint8_t>(combined);
168
169 // Write out all the object pointer fields.
170 ASSERT(type_class_id_ != Object::null());
171 SnapshotWriterVisitor visitor(writer, as_reference);
172 visitor.VisitPointers(from(), to());
173
174 // Write out the type class.
175 writer->WriteObjectImpl(type_class, as_reference);
176}
177
178TypeRefPtr TypeRef::ReadFrom(SnapshotReader* reader,
179 intptr_t object_id,
180 intptr_t tags,
181 Snapshot::Kind kind,
182 bool as_reference) {
183 ASSERT(reader != NULL);
184
185 // Allocate type ref object.
186 TypeRef& type_ref = TypeRef::ZoneHandle(reader->zone(), TypeRef::New());
187 reader->AddBackRef(object_id, &type_ref, kIsDeserialized);
188
189 // Read the code object for the type testing stub and set its entrypoint.
190 reader->EnqueueTypePostprocessing(type_ref);
191
192 // Set all the object fields.
193 READ_OBJECT_FIELDS(type_ref, type_ref.raw()->ptr()->from(),
194 type_ref.raw()->ptr()->to(), kAsReference);
195
196 // Fill in the type testing stub.
197 Code& code = *reader->CodeHandle();
198 code = TypeTestingStubGenerator::DefaultCodeForType(type_ref);
199 type_ref.SetTypeTestingStub(code);
200
201 return type_ref.raw();
202}
203
204void TypeRefLayout::WriteTo(SnapshotWriter* writer,
205 intptr_t object_id,
206 Snapshot::Kind kind,
207 bool as_reference) {
208 ASSERT(writer != NULL);
209
210 // Write out the serialization header value for this object.
211 writer->WriteInlinedObjectHeader(object_id);
212
213 // Write out the class and tags information.
214 writer->WriteIndexedObject(kTypeRefCid);
215 writer->WriteTags(writer->GetObjectTags(this));
216
217 // Write out all the object pointer fields.
218 SnapshotWriterVisitor visitor(writer, kAsReference);
219 visitor.VisitPointers(from(), to());
220}
221
222TypeParameterPtr TypeParameter::ReadFrom(SnapshotReader* reader,
223 intptr_t object_id,
224 intptr_t tags,
225 Snapshot::Kind kind,
226 bool as_reference) {
227 ASSERT(reader != NULL);
228
229 // Allocate type parameter object.
230 TypeParameter& type_parameter =
231 TypeParameter::ZoneHandle(reader->zone(), TypeParameter::New());
232 bool is_canonical = ObjectLayout::IsCanonical(tags);
233 reader->AddBackRef(object_id, &type_parameter, kIsDeserialized);
234
235 // Set all non object fields.
236 type_parameter.set_token_pos(
237 TokenPosition::SnapshotDecode(reader->Read<int32_t>()));
238 type_parameter.set_index(reader->Read<int16_t>());
239 const uint8_t combined = reader->Read<uint8_t>();
240 type_parameter.set_flags(combined >> 4);
241 type_parameter.set_nullability(static_cast<Nullability>(combined & 0xf));
242
243 // Read the code object for the type testing stub and set its entrypoint.
244 reader->EnqueueTypePostprocessing(type_parameter);
245
246 // Set all the object fields.
247 READ_OBJECT_FIELDS(type_parameter, type_parameter.raw()->ptr()->from(),
248 type_parameter.raw()->ptr()->to(), kAsReference);
249
250 if (type_parameter.parameterized_function() == Function::null()) {
251 // Read in the parameterized class.
252 (*reader->ClassHandle()) =
253 Class::RawCast(reader->ReadObjectImpl(kAsReference));
254 } else {
255 (*reader->ClassHandle()) = Class::null();
256 }
257 type_parameter.set_parameterized_class(*reader->ClassHandle());
258
259 // Fill in the type testing stub.
260 Code& code = *reader->CodeHandle();
261 code = TypeTestingStubGenerator::DefaultCodeForType(type_parameter);
262 type_parameter.SetTypeTestingStub(code);
263
264 if (is_canonical) {
265 type_parameter ^= type_parameter.Canonicalize();
266 }
267
268 return type_parameter.raw();
269}
270
271void TypeParameterLayout::WriteTo(SnapshotWriter* writer,
272 intptr_t object_id,
273 Snapshot::Kind kind,
274 bool as_reference) {
275 ASSERT(writer != NULL);
276
277 // Only finalized type parameters should be written to a snapshot.
278 ASSERT(FinalizedBit::decode(flags_));
279
280 // Write out the serialization header value for this object.
281 writer->WriteInlinedObjectHeader(object_id);
282
283 // Write out the class and tags information.
284 writer->WriteIndexedObject(kTypeParameterCid);
285 writer->WriteTags(writer->GetObjectTags(this));
286
287 // Write out all the non object pointer fields.
288 writer->Write<int32_t>(token_pos_.SnapshotEncode());
289 writer->Write<int16_t>(index_);
290 const uint8_t combined = (flags_ << 4) | nullability_;
291 ASSERT(flags_ == (combined >> 4));
292 ASSERT(nullability_ == (combined & 0xf));
293 writer->Write<uint8_t>(combined);
294
295 // Write out all the object pointer fields.
296 SnapshotWriterVisitor visitor(writer, kAsReference);
297 visitor.VisitPointers(from(), to());
298
299 if (parameterized_class_id_ != kFunctionCid) {
300 ASSERT(parameterized_function_ == Function::null());
301 // Write out the parameterized class.
302 ClassPtr param_class =
303 writer->isolate()->class_table()->At(parameterized_class_id_);
304 writer->WriteObjectImpl(param_class, kAsReference);
305 } else {
306 ASSERT(parameterized_function_ != Function::null());
307 }
308}
309
310TypeArgumentsPtr TypeArguments::ReadFrom(SnapshotReader* reader,
311 intptr_t object_id,
312 intptr_t tags,
313 Snapshot::Kind kind,
314 bool as_reference) {
315 ASSERT(reader != NULL);
316
317 // Read the length so that we can determine instance size to allocate.
318 intptr_t len = reader->ReadSmiValue();
319
320 TypeArguments& type_arguments =
321 TypeArguments::ZoneHandle(reader->zone(), TypeArguments::New(len));
322 bool is_canonical = ObjectLayout::IsCanonical(tags);
323 reader->AddBackRef(object_id, &type_arguments, kIsDeserialized);
324
325 // Set the instantiations field, which is only read from a full snapshot.
326 type_arguments.set_instantiations(Object::zero_array());
327
328 // Now set all the type fields.
329 for (intptr_t i = 0; i < len; i++) {
330 *reader->TypeHandle() ^= reader->ReadObjectImpl(as_reference);
331 type_arguments.SetTypeAt(i, *reader->TypeHandle());
332 }
333
334 // Set the canonical bit.
335 if (is_canonical) {
336 type_arguments = type_arguments.Canonicalize();
337 }
338
339 return type_arguments.raw();
340}
341
342void TypeArgumentsLayout::WriteTo(SnapshotWriter* writer,
343 intptr_t object_id,
344 Snapshot::Kind kind,
345 bool as_reference) {
346 ASSERT(writer != NULL);
347
348 // Write out the serialization header value for this object.
349 writer->WriteInlinedObjectHeader(object_id);
350
351 // Write out the class and tags information.
352 writer->WriteVMIsolateObject(kTypeArgumentsCid);
353 writer->WriteTags(writer->GetObjectTags(this));
354
355 // Write out the length field.
356 writer->Write<ObjectPtr>(length_);
357
358 // Write out the individual types.
359 intptr_t len = Smi::Value(length_);
360 for (intptr_t i = 0; i < len; i++) {
361 // The Dart VM reuses type argument lists across instances in order
362 // to reduce memory footprint, this can sometimes lead to a type from
363 // such a shared type argument list being sent over to another isolate.
364 // In such scenarios where it is not appropriate to send the types
365 // across (isolates spawned using spawnURI) we send them as dynamic.
366 if (!writer->can_send_any_object()) {
367 // Lookup the type class.
368 TypePtr raw_type = Type::RawCast(types()[i]);
369 SmiPtr raw_type_class_id = Smi::RawCast(raw_type->ptr()->type_class_id_);
370 ClassPtr type_class =
371 writer->isolate()->class_table()->At(Smi::Value(raw_type_class_id));
372 if (!writer->AllowObjectsInDartLibrary(type_class->ptr()->library_)) {
373 writer->WriteVMIsolateObject(kDynamicType);
374 } else {
375 writer->WriteObjectImpl(types()[i], as_reference);
376 }
377 } else {
378 writer->WriteObjectImpl(types()[i], as_reference);
379 }
380 }
381}
382
383ClosurePtr Closure::ReadFrom(SnapshotReader* reader,
384 intptr_t object_id,
385 intptr_t tags,
386 Snapshot::Kind kind,
387 bool as_reference) {
388 UNREACHABLE();
389 return Closure::null();
390}
391
392void ClosureLayout::WriteTo(SnapshotWriter* writer,
393 intptr_t object_id,
394 Snapshot::Kind kind,
395 bool as_reference) {
396 ASSERT(writer != NULL);
397 ASSERT(kind == Snapshot::kMessage);
398
399 // Check if closure is serializable, throw an exception otherwise.
400 FunctionPtr func = writer->IsSerializableClosure(ClosurePtr(this));
401 if (func != Function::null()) {
402 writer->WriteStaticImplicitClosure(object_id, func,
403 writer->GetObjectTags(this));
404 return;
405 }
406
407 UNREACHABLE();
408}
409
410ContextPtr Context::ReadFrom(SnapshotReader* reader,
411 intptr_t object_id,
412 intptr_t tags,
413 Snapshot::Kind kind,
414 bool as_reference) {
415 ASSERT(reader != NULL);
416
417 // Allocate context object.
418 int32_t num_vars = reader->Read<int32_t>();
419 Context& context = Context::ZoneHandle(reader->zone());
420 reader->AddBackRef(object_id, &context, kIsDeserialized);
421 if (num_vars != 0) {
422 context = Context::New(num_vars);
423
424 // Set all the object fields.
425 // TODO(5411462): Need to assert No GC can happen here, even though
426 // allocations may happen.
427 intptr_t num_flds =
428 (context.raw()->ptr()->to(num_vars) - context.raw()->ptr()->from());
429 for (intptr_t i = 0; i <= num_flds; i++) {
430 (*reader->PassiveObjectHandle()) = reader->ReadObjectImpl(kAsReference);
431 context.StorePointer((context.raw()->ptr()->from() + i),
432 reader->PassiveObjectHandle()->raw());
433 }
434 }
435 return context.raw();
436}
437
438void ContextLayout::WriteTo(SnapshotWriter* writer,
439 intptr_t object_id,
440 Snapshot::Kind kind,
441 bool as_reference) {
442 ASSERT(writer != NULL);
443
444 // Write out the serialization header value for this object.
445 writer->WriteInlinedObjectHeader(object_id);
446
447 // Write out the class and tags information.
448 writer->WriteVMIsolateObject(kContextCid);
449 writer->WriteTags(writer->GetObjectTags(this));
450
451 // Write out num of variables in the context.
452 const int32_t num_variables = num_variables_;
453 writer->Write<int32_t>(num_variables);
454 if (num_variables != 0) {
455 // Write out all the object pointer fields.
456 SnapshotWriterVisitor visitor(writer, kAsReference);
457 visitor.VisitPointers(from(), to(num_variables));
458 }
459}
460
461ContextScopePtr ContextScope::ReadFrom(SnapshotReader* reader,
462 intptr_t object_id,
463 intptr_t tags,
464 Snapshot::Kind kind,
465 bool as_reference) {
466 ASSERT(reader != NULL);
467
468 // Allocate context object.
469 bool is_implicit = reader->Read<bool>();
470 if (is_implicit) {
471 ContextScope& context_scope = ContextScope::ZoneHandle(reader->zone());
472 context_scope = ContextScope::New(1, true);
473 reader->AddBackRef(object_id, &context_scope, kIsDeserialized);
474
475 *reader->TypeHandle() ^= reader->ReadObjectImpl(kAsInlinedObject);
476
477 // Create a descriptor for 'this' variable.
478 context_scope.SetTokenIndexAt(0, TokenPosition::kMinSource);
479 context_scope.SetDeclarationTokenIndexAt(0, TokenPosition::kMinSource);
480 context_scope.SetNameAt(0, Symbols::This());
481 context_scope.SetIsFinalAt(0, true);
482 context_scope.SetIsConstAt(0, false);
483 context_scope.SetTypeAt(0, *reader->TypeHandle());
484 context_scope.SetContextIndexAt(0, 0);
485 context_scope.SetContextLevelAt(0, 0);
486 return context_scope.raw();
487 }
488 UNREACHABLE();
489 return NULL;
490}
491
492void ContextScopeLayout::WriteTo(SnapshotWriter* writer,
493 intptr_t object_id,
494 Snapshot::Kind kind,
495 bool as_reference) {
496 ASSERT(writer != NULL);
497
498 if (is_implicit_) {
499 ASSERT(num_variables_ == 1);
500 const VariableDesc* var = VariableDescAddr(0);
501
502 // Write out the serialization header value for this object.
503 writer->WriteInlinedObjectHeader(object_id);
504
505 // Write out the class and tags information.
506 writer->WriteVMIsolateObject(kContextScopeCid);
507 writer->WriteTags(writer->GetObjectTags(this));
508
509 // Write out is_implicit flag for the context scope.
510 writer->Write<bool>(true);
511
512 // Write out the type of 'this' the variable.
513 writer->WriteObjectImpl(var->type, kAsInlinedObject);
514
515 return;
516 }
517 UNREACHABLE();
518}
519
520#define MESSAGE_SNAPSHOT_UNREACHABLE(type) \
521 type##Ptr type::ReadFrom(SnapshotReader* reader, intptr_t object_id, \
522 intptr_t tags, Snapshot::Kind kind, \
523 bool as_reference) { \
524 UNREACHABLE(); \
525 return type::null(); \
526 } \
527 void type##Layout::WriteTo(SnapshotWriter* writer, intptr_t object_id, \
528 Snapshot::Kind kind, bool as_reference) { \
529 UNREACHABLE(); \
530 }
531
532#define MESSAGE_SNAPSHOT_ILLEGAL(type) \
533 type##Ptr type::ReadFrom(SnapshotReader* reader, intptr_t object_id, \
534 intptr_t tags, Snapshot::Kind kind, \
535 bool as_reference) { \
536 UNREACHABLE(); \
537 return type::null(); \
538 } \
539 void type##Layout::WriteTo(SnapshotWriter* writer, intptr_t object_id, \
540 Snapshot::Kind kind, bool as_reference) { \
541 writer->SetWriteException(Exceptions::kArgument, \
542 "Illegal argument in isolate message" \
543 " : (object is a " #type ")"); \
544 }
545
546MESSAGE_SNAPSHOT_UNREACHABLE(AbstractType);
547MESSAGE_SNAPSHOT_UNREACHABLE(Bool);
548MESSAGE_SNAPSHOT_UNREACHABLE(Bytecode);
549MESSAGE_SNAPSHOT_UNREACHABLE(ClosureData);
550MESSAGE_SNAPSHOT_UNREACHABLE(Code);
551MESSAGE_SNAPSHOT_UNREACHABLE(CodeSourceMap);
552MESSAGE_SNAPSHOT_UNREACHABLE(CompressedStackMaps);
553MESSAGE_SNAPSHOT_UNREACHABLE(Error);
554MESSAGE_SNAPSHOT_UNREACHABLE(ExceptionHandlers);
555MESSAGE_SNAPSHOT_UNREACHABLE(FfiTrampolineData);
556MESSAGE_SNAPSHOT_UNREACHABLE(Field);
557MESSAGE_SNAPSHOT_UNREACHABLE(Function);
558MESSAGE_SNAPSHOT_UNREACHABLE(CallSiteData);
559MESSAGE_SNAPSHOT_UNREACHABLE(ICData);
560MESSAGE_SNAPSHOT_UNREACHABLE(Instructions);
561MESSAGE_SNAPSHOT_UNREACHABLE(InstructionsSection);
562MESSAGE_SNAPSHOT_UNREACHABLE(KernelProgramInfo);
563MESSAGE_SNAPSHOT_UNREACHABLE(Library);
564MESSAGE_SNAPSHOT_UNREACHABLE(LibraryPrefix);
565MESSAGE_SNAPSHOT_UNREACHABLE(LocalVarDescriptors);
566MESSAGE_SNAPSHOT_UNREACHABLE(MegamorphicCache);
567MESSAGE_SNAPSHOT_UNREACHABLE(Namespace);
568MESSAGE_SNAPSHOT_UNREACHABLE(ObjectPool);
569MESSAGE_SNAPSHOT_UNREACHABLE(ParameterTypeCheck);
570MESSAGE_SNAPSHOT_UNREACHABLE(PatchClass);
571MESSAGE_SNAPSHOT_UNREACHABLE(PcDescriptors);
572MESSAGE_SNAPSHOT_UNREACHABLE(RedirectionData);
573MESSAGE_SNAPSHOT_UNREACHABLE(Script);
574MESSAGE_SNAPSHOT_UNREACHABLE(SignatureData);
575MESSAGE_SNAPSHOT_UNREACHABLE(SingleTargetCache);
576MESSAGE_SNAPSHOT_UNREACHABLE(String);
577MESSAGE_SNAPSHOT_UNREACHABLE(SubtypeTestCache);
578MESSAGE_SNAPSHOT_UNREACHABLE(LoadingUnit);
579MESSAGE_SNAPSHOT_UNREACHABLE(TypedDataBase);
580MESSAGE_SNAPSHOT_UNREACHABLE(UnlinkedCall);
581MESSAGE_SNAPSHOT_UNREACHABLE(MonomorphicSmiableCall);
582MESSAGE_SNAPSHOT_UNREACHABLE(UnwindError);
583MESSAGE_SNAPSHOT_UNREACHABLE(FutureOr);
584MESSAGE_SNAPSHOT_UNREACHABLE(WeakSerializationReference);
585
586MESSAGE_SNAPSHOT_ILLEGAL(DynamicLibrary);
587MESSAGE_SNAPSHOT_ILLEGAL(MirrorReference);
588MESSAGE_SNAPSHOT_ILLEGAL(Pointer);
589MESSAGE_SNAPSHOT_ILLEGAL(ReceivePort);
590MESSAGE_SNAPSHOT_ILLEGAL(StackTrace);
591MESSAGE_SNAPSHOT_ILLEGAL(UserTag);
592
593ApiErrorPtr ApiError::ReadFrom(SnapshotReader* reader,
594 intptr_t object_id,
595 intptr_t tags,
596 Snapshot::Kind kind,
597 bool as_reference) {
598 ASSERT(reader != NULL);
599
600 // Allocate ApiError object.
601 ApiError& api_error = ApiError::ZoneHandle(reader->zone(), ApiError::New());
602 reader->AddBackRef(object_id, &api_error, kIsDeserialized);
603
604 // Set all the object fields.
605 READ_OBJECT_FIELDS(api_error, api_error.raw()->ptr()->from(),
606 api_error.raw()->ptr()->to(), kAsReference);
607
608 return api_error.raw();
609}
610
611void ApiErrorLayout::WriteTo(SnapshotWriter* writer,
612 intptr_t object_id,
613 Snapshot::Kind kind,
614 bool as_reference) {
615 ASSERT(writer != NULL);
616
617 // Write out the serialization header value for this object.
618 writer->WriteInlinedObjectHeader(object_id);
619
620 // Write out the class and tags information.
621 writer->WriteVMIsolateObject(kApiErrorCid);
622 writer->WriteTags(writer->GetObjectTags(this));
623
624 // Write out all the object pointer fields.
625 SnapshotWriterVisitor visitor(writer, kAsReference);
626 visitor.VisitPointers(from(), to());
627}
628
629LanguageErrorPtr LanguageError::ReadFrom(SnapshotReader* reader,
630 intptr_t object_id,
631 intptr_t tags,
632 Snapshot::Kind kind,
633 bool as_reference) {
634 ASSERT(reader != NULL);
635
636 // Allocate LanguageError object.
637 LanguageError& language_error =
638 LanguageError::ZoneHandle(reader->zone(), LanguageError::New());
639 reader->AddBackRef(object_id, &language_error, kIsDeserialized);
640
641 // Set all non object fields.
642 language_error.set_token_pos(
643 TokenPosition::SnapshotDecode(reader->Read<int32_t>()));
644 language_error.set_report_after_token(reader->Read<bool>());
645 language_error.set_kind(reader->Read<uint8_t>());
646
647 // Set all the object fields.
648 READ_OBJECT_FIELDS(language_error, language_error.raw()->ptr()->from(),
649 language_error.raw()->ptr()->to(), kAsReference);
650
651 return language_error.raw();
652}
653
654void LanguageErrorLayout::WriteTo(SnapshotWriter* writer,
655 intptr_t object_id,
656 Snapshot::Kind kind,
657 bool as_reference) {
658 ASSERT(writer != NULL);
659
660 // Write out the serialization header value for this object.
661 writer->WriteInlinedObjectHeader(object_id);
662
663 // Write out the class and tags information.
664 writer->WriteVMIsolateObject(kLanguageErrorCid);
665 writer->WriteTags(writer->GetObjectTags(this));
666
667 // Write out all the non object fields.
668 writer->Write<int32_t>(token_pos_.SnapshotEncode());
669 writer->Write<bool>(report_after_token_);
670 writer->Write<uint8_t>(kind_);
671
672 // Write out all the object pointer fields.
673 SnapshotWriterVisitor visitor(writer, kAsReference);
674 visitor.VisitPointers(from(), to());
675}
676
677UnhandledExceptionPtr UnhandledException::ReadFrom(SnapshotReader* reader,
678 intptr_t object_id,
679 intptr_t tags,
680 Snapshot::Kind kind,
681 bool as_reference) {
682 UnhandledException& result =
683 UnhandledException::ZoneHandle(reader->zone(), UnhandledException::New());
684 reader->AddBackRef(object_id, &result, kIsDeserialized);
685
686 // Set all the object fields.
687 READ_OBJECT_FIELDS(result, result.raw()->ptr()->from(),
688 result.raw()->ptr()->to(), kAsReference);
689
690 return result.raw();
691}
692
693void UnhandledExceptionLayout::WriteTo(SnapshotWriter* writer,
694 intptr_t object_id,
695 Snapshot::Kind kind,
696 bool as_reference) {
697 // Write out the serialization header value for this object.
698 writer->WriteInlinedObjectHeader(object_id);
699
700 // Write out the class and tags information.
701 writer->WriteVMIsolateObject(kUnhandledExceptionCid);
702 writer->WriteTags(writer->GetObjectTags(this));
703 // Write out all the object pointer fields.
704 SnapshotWriterVisitor visitor(writer, kAsReference);
705 visitor.VisitPointers(from(), to());
706}
707
708InstancePtr Instance::ReadFrom(SnapshotReader* reader,
709 intptr_t object_id,
710 intptr_t tags,
711 Snapshot::Kind kind,
712 bool as_reference) {
713 ASSERT(reader != NULL);
714
715 // Create an Instance object or get canonical one if it is a canonical
716 // constant.
717 Instance& obj = Instance::ZoneHandle(reader->zone(), Instance::null());
718 obj ^= Object::Allocate(kInstanceCid, Instance::InstanceSize(), Heap::kNew);
719 if (ObjectLayout::IsCanonical(tags)) {
720 const char* error_str = NULL;
721 obj = obj.CheckAndCanonicalize(reader->thread(), &error_str);
722 if (error_str != NULL) {
723 FATAL1("Failed to canonicalize: %s", error_str);
724 }
725 }
726 reader->AddBackRef(object_id, &obj, kIsDeserialized);
727
728 return obj.raw();
729}
730
731void InstanceLayout::WriteTo(SnapshotWriter* writer,
732 intptr_t object_id,
733 Snapshot::Kind kind,
734 bool as_reference) {
735 ASSERT(writer != NULL);
736
737 // Write out the serialization header value for this object.
738 writer->WriteInlinedObjectHeader(object_id);
739
740 // Write out the class and tags information.
741 writer->WriteIndexedObject(kInstanceCid);
742 writer->WriteTags(writer->GetObjectTags(this));
743}
744
745IntegerPtr Mint::ReadFrom(SnapshotReader* reader,
746 intptr_t object_id,
747 intptr_t tags,
748 Snapshot::Kind kind,
749 bool as_reference) {
750 ASSERT(reader != NULL);
751
752 // Read the 64 bit value for the object.
753 int64_t value = reader->Read<int64_t>();
754
755 // Check if the value could potentially fit in a Smi in our current
756 // architecture, if so return the object as a Smi.
757 if (Smi::IsValid(value)) {
758 Smi& smi =
759 Smi::ZoneHandle(reader->zone(), Smi::New(static_cast<intptr_t>(value)));
760 reader->AddBackRef(object_id, &smi, kIsDeserialized);
761 return smi.raw();
762 }
763
764 // Create a Mint object or get canonical one if it is a canonical constant.
765 Mint& mint = Mint::ZoneHandle(reader->zone(), Mint::null());
766 // When reading a script snapshot we need to canonicalize only those object
767 // references that are objects from the core library (loaded from a
768 // full snapshot). Objects that are only in the script need not be
769 // canonicalized as they are already canonical.
770 // When reading a message snapshot we always have to canonicalize.
771 if (ObjectLayout::IsCanonical(tags)) {
772 mint = Mint::NewCanonical(value);
773 ASSERT(mint.IsCanonical());
774 } else {
775 mint = Mint::New(value);
776 }
777 reader->AddBackRef(object_id, &mint, kIsDeserialized);
778 return mint.raw();
779}
780
781void MintLayout::WriteTo(SnapshotWriter* writer,
782 intptr_t object_id,
783 Snapshot::Kind kind,
784 bool as_reference) {
785 ASSERT(writer != NULL);
786
787 // Write out the serialization header value for this object.
788 writer->WriteInlinedObjectHeader(object_id);
789
790 // Write out the class and tags information.
791 writer->WriteIndexedObject(kMintCid);
792 writer->WriteTags(writer->GetObjectTags(this));
793
794 // Write out the 64 bit value.
795 writer->Write<int64_t>(value_);
796}
797
798DoublePtr Double::ReadFrom(SnapshotReader* reader,
799 intptr_t object_id,
800 intptr_t tags,
801 Snapshot::Kind kind,
802 bool as_reference) {
803 ASSERT(reader != NULL);
804 ASSERT(kind != Snapshot::kMessage);
805 // Read the double value for the object.
806 double value = reader->ReadDouble();
807
808 // Create a Double object or get canonical one if it is a canonical constant.
809 Double& dbl = Double::ZoneHandle(reader->zone(), Double::null());
810 // When reading a script snapshot we need to canonicalize only those object
811 // references that are objects from the core library (loaded from a
812 // full snapshot). Objects that are only in the script need not be
813 // canonicalized as they are already canonical.
814 if (ObjectLayout::IsCanonical(tags)) {
815 dbl = Double::NewCanonical(value);
816 ASSERT(dbl.IsCanonical());
817 } else {
818 dbl = Double::New(value);
819 }
820 reader->AddBackRef(object_id, &dbl, kIsDeserialized);
821 return dbl.raw();
822}
823
824void DoubleLayout::WriteTo(SnapshotWriter* writer,
825 intptr_t object_id,
826 Snapshot::Kind kind,
827 bool as_reference) {
828 ASSERT(writer != NULL);
829
830 // Write out the serialization header value for this object.
831 writer->WriteInlinedObjectHeader(object_id);
832
833 // Write out the class and tags information.
834 writer->WriteIndexedObject(kDoubleCid);
835 writer->WriteTags(writer->GetObjectTags(this));
836
837 // Write out the double value.
838 writer->WriteDouble(value_);
839}
840
841template <typename StringType, typename CharacterType, typename CallbackType>
842void String::ReadFromImpl(SnapshotReader* reader,
843 String* str_obj,
844 intptr_t len,
845 intptr_t tags,
846 CallbackType new_symbol,
847 Snapshot::Kind kind) {
848 ASSERT(reader != NULL);
849 if (ObjectLayout::IsCanonical(tags)) {
850 // Set up canonical string object.
851 ASSERT(reader != NULL);
852 CharacterType* ptr = reader->zone()->Alloc<CharacterType>(len);
853 for (intptr_t i = 0; i < len; i++) {
854 ptr[i] = reader->Read<CharacterType>();
855 }
856 *str_obj = (*new_symbol)(reader->thread(), ptr, len);
857 } else {
858 // Set up the string object.
859 *str_obj = StringType::New(len, Heap::kNew);
860 str_obj->SetHash(0); // Will get computed when needed.
861 if (len == 0) {
862 return;
863 }
864 NoSafepointScope no_safepoint;
865 CharacterType* str_addr = StringType::DataStart(*str_obj);
866 for (intptr_t i = 0; i < len; i++) {
867 *str_addr = reader->Read<CharacterType>();
868 str_addr++;
869 }
870 }
871}
872
873OneByteStringPtr OneByteString::ReadFrom(SnapshotReader* reader,
874 intptr_t object_id,
875 intptr_t tags,
876 Snapshot::Kind kind,
877 bool as_reference) {
878 // Read the length so that we can determine instance size to allocate.
879 ASSERT(reader != NULL);
880 intptr_t len = reader->ReadSmiValue();
881 String& str_obj = String::ZoneHandle(reader->zone(), String::null());
882
883 String::ReadFromImpl<OneByteString, uint8_t>(reader, &str_obj, len, tags,
884 Symbols::FromLatin1, kind);
885 reader->AddBackRef(object_id, &str_obj, kIsDeserialized);
886 return raw(str_obj);
887}
888
889TwoByteStringPtr TwoByteString::ReadFrom(SnapshotReader* reader,
890 intptr_t object_id,
891 intptr_t tags,
892 Snapshot::Kind kind,
893 bool as_reference) {
894 // Read the length so that we can determine instance size to allocate.
895 ASSERT(reader != NULL);
896 intptr_t len = reader->ReadSmiValue();
897 String& str_obj = String::ZoneHandle(reader->zone(), String::null());
898
899 String::ReadFromImpl<TwoByteString, uint16_t>(reader, &str_obj, len, tags,
900 Symbols::FromUTF16, kind);
901 reader->AddBackRef(object_id, &str_obj, kIsDeserialized);
902 return raw(str_obj);
903}
904
905template <typename T>
906static void StringWriteTo(SnapshotWriter* writer,
907 intptr_t object_id,
908 Snapshot::Kind kind,
909 intptr_t class_id,
910 intptr_t tags,
911 SmiPtr length,
912 T* data) {
913 ASSERT(writer != NULL);
914 intptr_t len = Smi::Value(length);
915
916 // Write out the serialization header value for this object.
917 writer->WriteInlinedObjectHeader(object_id);
918
919 // Write out the class and tags information.
920 writer->WriteIndexedObject(class_id);
921 writer->WriteTags(tags);
922
923 // Write out the length field.
924 writer->Write<ObjectPtr>(length);
925
926 // Write out the string.
927 if (len > 0) {
928 if (class_id == kOneByteStringCid) {
929 writer->WriteBytes(reinterpret_cast<const uint8_t*>(data), len);
930 } else {
931 for (intptr_t i = 0; i < len; i++) {
932 writer->Write(data[i]);
933 }
934 }
935 }
936}
937
938void OneByteStringLayout::WriteTo(SnapshotWriter* writer,
939 intptr_t object_id,
940 Snapshot::Kind kind,
941 bool as_reference) {
942 StringWriteTo(writer, object_id, kind, kOneByteStringCid,
943 writer->GetObjectTags(this), length_, data());
944}
945
946void TwoByteStringLayout::WriteTo(SnapshotWriter* writer,
947 intptr_t object_id,
948 Snapshot::Kind kind,
949 bool as_reference) {
950 StringWriteTo(writer, object_id, kind, kTwoByteStringCid,
951 writer->GetObjectTags(this), length_, data());
952}
953
954ExternalOneByteStringPtr ExternalOneByteString::ReadFrom(SnapshotReader* reader,
955 intptr_t object_id,
956 intptr_t tags,
957 Snapshot::Kind kind,
958 bool as_reference) {
959 UNREACHABLE();
960 return ExternalOneByteString::null();
961}
962
963ExternalTwoByteStringPtr ExternalTwoByteString::ReadFrom(SnapshotReader* reader,
964 intptr_t object_id,
965 intptr_t tags,
966 Snapshot::Kind kind,
967 bool as_reference) {
968 UNREACHABLE();
969 return ExternalTwoByteString::null();
970}
971
972void ExternalOneByteStringLayout::WriteTo(SnapshotWriter* writer,
973 intptr_t object_id,
974 Snapshot::Kind kind,
975 bool as_reference) {
976 // Serialize as a non-external one byte string.
977 StringWriteTo(writer, object_id, kind, kOneByteStringCid,
978 writer->GetObjectTags(this), length_, external_data_);
979}
980
981void ExternalTwoByteStringLayout::WriteTo(SnapshotWriter* writer,
982 intptr_t object_id,
983 Snapshot::Kind kind,
984 bool as_reference) {
985 // Serialize as a non-external two byte string.
986 StringWriteTo(writer, object_id, kind, kTwoByteStringCid,
987 writer->GetObjectTags(this), length_, external_data_);
988}
989
990ArrayPtr Array::ReadFrom(SnapshotReader* reader,
991 intptr_t object_id,
992 intptr_t tags,
993 Snapshot::Kind kind,
994 bool as_reference) {
995 ASSERT(reader != NULL);
996
997 // Read the length so that we can determine instance size to allocate.
998 intptr_t len = reader->ReadSmiValue();
999 Array* array = NULL;
1000 DeserializeState state;
1001 if (!as_reference) {
1002 array = reinterpret_cast<Array*>(reader->GetBackRef(object_id));
1003 state = kIsDeserialized;
1004 } else {
1005 state = kIsNotDeserialized;
1006 }
1007 if (array == NULL) {
1008 array = &(Array::ZoneHandle(reader->zone(), Array::New(len)));
1009 reader->AddBackRef(object_id, array, state);
1010 }
1011 if (!as_reference) {
1012 // Read all the individual elements for inlined objects.
1013 ASSERT(!ObjectLayout::IsCanonical(tags));
1014 reader->ArrayReadFrom(object_id, *array, len, tags);
1015 }
1016 return array->raw();
1017}
1018
1019ImmutableArrayPtr ImmutableArray::ReadFrom(SnapshotReader* reader,
1020 intptr_t object_id,
1021 intptr_t tags,
1022 Snapshot::Kind kind,
1023 bool as_reference) {
1024 ASSERT(reader != NULL);
1025
1026 // Read the length so that we can determine instance size to allocate.
1027 intptr_t len = reader->ReadSmiValue();
1028 Array* array = NULL;
1029 DeserializeState state;
1030 if (!as_reference) {
1031 array = reinterpret_cast<Array*>(reader->GetBackRef(object_id));
1032 state = kIsDeserialized;
1033 } else {
1034 state = kIsNotDeserialized;
1035 }
1036 if (array == NULL) {
1037 array = &(Array::ZoneHandle(reader->zone(), ImmutableArray::New(len)));
1038 reader->AddBackRef(object_id, array, state);
1039 }
1040 if (!as_reference) {
1041 // Read all the individual elements for inlined objects.
1042 reader->ArrayReadFrom(object_id, *array, len, tags);
1043 if (ObjectLayout::IsCanonical(tags)) {
1044 const char* error_str = NULL;
1045 *array ^= array->CheckAndCanonicalize(reader->thread(), &error_str);
1046 if (error_str != NULL) {
1047 FATAL1("Failed to canonicalize: %s", error_str);
1048 }
1049 }
1050 }
1051 return raw(*array);
1052}
1053
1054void ArrayLayout::WriteTo(SnapshotWriter* writer,
1055 intptr_t object_id,
1056 Snapshot::Kind kind,
1057 bool as_reference) {
1058 ASSERT(!this->IsCanonical());
1059 writer->ArrayWriteTo(object_id, kArrayCid, writer->GetObjectTags(this),
1060 length_, type_arguments_, data(), as_reference);
1061}
1062
1063void ImmutableArrayLayout::WriteTo(SnapshotWriter* writer,
1064 intptr_t object_id,
1065 Snapshot::Kind kind,
1066 bool as_reference) {
1067 writer->ArrayWriteTo(object_id, kImmutableArrayCid,
1068 writer->GetObjectTags(this), length_, type_arguments_,
1069 data(), as_reference);
1070}
1071
1072GrowableObjectArrayPtr GrowableObjectArray::ReadFrom(SnapshotReader* reader,
1073 intptr_t object_id,
1074 intptr_t tags,
1075 Snapshot::Kind kind,
1076 bool as_reference) {
1077 ASSERT(reader != NULL);
1078
1079 // Read the length so that we can determine instance size to allocate.
1080 GrowableObjectArray& array = GrowableObjectArray::ZoneHandle(
1081 reader->zone(), GrowableObjectArray::null());
1082 array = GrowableObjectArray::New(0);
1083 reader->AddBackRef(object_id, &array, kIsDeserialized);
1084
1085 // Read type arguments of growable array object.
1086 *reader->TypeArgumentsHandle() ^= reader->ReadObjectImpl(kAsInlinedObject);
1087 array.StorePointer(&array.raw_ptr()->type_arguments_,
1088 reader->TypeArgumentsHandle()->raw());
1089
1090 // Read length of growable array object.
1091 array.SetLength(reader->ReadSmiValue());
1092
1093 // Read the backing array of growable array object.
1094 *(reader->ArrayHandle()) ^= reader->ReadObjectImpl(kAsReference);
1095 array.SetData(*(reader->ArrayHandle()));
1096
1097 return array.raw();
1098}
1099
1100void GrowableObjectArrayLayout::WriteTo(SnapshotWriter* writer,
1101 intptr_t object_id,
1102 Snapshot::Kind kind,
1103 bool as_reference) {
1104 ASSERT(writer != NULL);
1105
1106 // Write out the serialization header value for this object.
1107 writer->WriteInlinedObjectHeader(object_id);
1108
1109 // Write out the class and tags information.
1110 writer->WriteIndexedObject(kGrowableObjectArrayCid);
1111 writer->WriteTags(writer->GetObjectTags(this));
1112
1113 // Write out the type arguments field.
1114 writer->WriteObjectImpl(type_arguments_, kAsInlinedObject);
1115
1116 // Write out the used length field.
1117 writer->Write<ObjectPtr>(length_);
1118
1119 // Write out the Array object.
1120 writer->WriteObjectImpl(data_, kAsReference);
1121}
1122
1123LinkedHashMapPtr LinkedHashMap::ReadFrom(SnapshotReader* reader,
1124 intptr_t object_id,
1125 intptr_t tags,
1126 Snapshot::Kind kind,
1127 bool as_reference) {
1128 ASSERT(reader != NULL);
1129
1130 LinkedHashMap& map =
1131 LinkedHashMap::ZoneHandle(reader->zone(), LinkedHashMap::null());
1132 // Since the map might contain itself as a key or value, allocate first.
1133 map = LinkedHashMap::NewUninitialized();
1134 reader->AddBackRef(object_id, &map, kIsDeserialized);
1135
1136 // Read the type arguments.
1137 *reader->TypeArgumentsHandle() ^= reader->ReadObjectImpl(kAsInlinedObject);
1138 map.SetTypeArguments(*reader->TypeArgumentsHandle());
1139
1140 // Read the number of key/value pairs.
1141 intptr_t len = reader->ReadSmiValue();
1142 intptr_t used_data = (len << 1);
1143 map.SetUsedData(used_data);
1144
1145 // Allocate the data array.
1146 intptr_t data_size =
1147 Utils::Maximum(Utils::RoundUpToPowerOfTwo(used_data),
1148 static_cast<uintptr_t>(LinkedHashMap::kInitialIndexSize));
1149 Array& data = Array::ZoneHandle(reader->zone(), Array::New(data_size));
1150 map.SetData(data);
1151 map.SetDeletedKeys(0);
1152
1153 // The index and hashMask is regenerated by the maps themselves on demand.
1154 // Thus, the index will probably be allocated in new space (unless it's huge).
1155 // TODO(koda): Eagerly rehash here when no keys have user-defined '==', and
1156 // in particular, if/when (const) maps are needed in the VM isolate snapshot.
1157 ASSERT(reader->isolate() != Dart::vm_isolate());
1158 map.SetHashMask(0); // Prefer sentinel 0 over null for better type feedback.
1159
1160 reader->EnqueueRehashingOfMap(map);
1161
1162 // Read the keys and values.
1163 bool read_as_reference = ObjectLayout::IsCanonical(tags) ? false : true;
1164 for (intptr_t i = 0; i < used_data; i++) {
1165 *reader->PassiveObjectHandle() = reader->ReadObjectImpl(read_as_reference);
1166 data.SetAt(i, *reader->PassiveObjectHandle());
1167 }
1168 return map.raw();
1169}
1170
1171void LinkedHashMapLayout::WriteTo(SnapshotWriter* writer,
1172 intptr_t object_id,
1173 Snapshot::Kind kind,
1174 bool as_reference) {
1175 ASSERT(writer != NULL);
1176
1177 // Write out the serialization header value for this object.
1178 writer->WriteInlinedObjectHeader(object_id);
1179
1180 // Write out the class and tags information.
1181 writer->WriteIndexedObject(kLinkedHashMapCid);
1182 writer->WriteTags(writer->GetObjectTags(this));
1183
1184 // Write out the type arguments.
1185 writer->WriteObjectImpl(type_arguments_, kAsInlinedObject);
1186
1187 const intptr_t used_data = Smi::Value(used_data_);
1188 ASSERT((used_data & 1) == 0); // Keys + values, so must be even.
1189 const intptr_t deleted_keys = Smi::Value(deleted_keys_);
1190
1191 // Write out the number of (not deleted) key/value pairs that will follow.
1192 writer->Write<ObjectPtr>(Smi::New((used_data >> 1) - deleted_keys));
1193
1194 // Write out the keys and values.
1195 const bool write_as_reference = this->IsCanonical() ? false : true;
1196 ArrayPtr data_array = data_;
1197 ObjectPtr* data_elements = data_array->ptr()->data();
1198 ASSERT(used_data <= Smi::Value(data_array->ptr()->length_));
1199#if defined(DEBUG)
1200 intptr_t deleted_keys_found = 0;
1201#endif // DEBUG
1202 for (intptr_t i = 0; i < used_data; i += 2) {
1203 ObjectPtr key = data_elements[i];
1204 if (key == data_array) {
1205#if defined(DEBUG)
1206 ++deleted_keys_found;
1207#endif // DEBUG
1208 continue;
1209 }
1210 ObjectPtr value = data_elements[i + 1];
1211 writer->WriteObjectImpl(key, write_as_reference);
1212 writer->WriteObjectImpl(value, write_as_reference);
1213 }
1214 DEBUG_ASSERT(deleted_keys_found == deleted_keys);
1215}
1216
1217Float32x4Ptr Float32x4::ReadFrom(SnapshotReader* reader,
1218 intptr_t object_id,
1219 intptr_t tags,
1220 Snapshot::Kind kind,
1221 bool as_reference) {
1222 ASSERT(reader != NULL);
1223 // Read the values.
1224 float value0 = reader->Read<float>();
1225 float value1 = reader->Read<float>();
1226 float value2 = reader->Read<float>();
1227 float value3 = reader->Read<float>();
1228
1229 // Create a Float32x4 object.
1230 Float32x4& simd = Float32x4::ZoneHandle(reader->zone(), Float32x4::null());
1231 simd = Float32x4::New(value0, value1, value2, value3);
1232 reader->AddBackRef(object_id, &simd, kIsDeserialized);
1233 return simd.raw();
1234}
1235
1236void Float32x4Layout::WriteTo(SnapshotWriter* writer,
1237 intptr_t object_id,
1238 Snapshot::Kind kind,
1239 bool as_reference) {
1240 ASSERT(writer != NULL);
1241
1242 // Write out the serialization header value for this object.
1243 writer->WriteInlinedObjectHeader(object_id);
1244
1245 // Write out the class and tags information.
1246 writer->WriteIndexedObject(kFloat32x4Cid);
1247 writer->WriteTags(writer->GetObjectTags(this));
1248
1249 // Write out the float values.
1250 writer->Write<float>(value_[0]);
1251 writer->Write<float>(value_[1]);
1252 writer->Write<float>(value_[2]);
1253 writer->Write<float>(value_[3]);
1254}
1255
1256Int32x4Ptr Int32x4::ReadFrom(SnapshotReader* reader,
1257 intptr_t object_id,
1258 intptr_t tags,
1259 Snapshot::Kind kind,
1260 bool as_reference) {
1261 ASSERT(reader != NULL);
1262 // Read the values.
1263 uint32_t value0 = reader->Read<uint32_t>();
1264 uint32_t value1 = reader->Read<uint32_t>();
1265 uint32_t value2 = reader->Read<uint32_t>();
1266 uint32_t value3 = reader->Read<uint32_t>();
1267
1268 // Create a Float32x4 object.
1269 Int32x4& simd = Int32x4::ZoneHandle(reader->zone(), Int32x4::null());
1270 simd = Int32x4::New(value0, value1, value2, value3);
1271 reader->AddBackRef(object_id, &simd, kIsDeserialized);
1272 return simd.raw();
1273}
1274
1275void Int32x4Layout::WriteTo(SnapshotWriter* writer,
1276 intptr_t object_id,
1277 Snapshot::Kind kind,
1278 bool as_reference) {
1279 ASSERT(writer != NULL);
1280
1281 // Write out the serialization header value for this object.
1282 writer->WriteInlinedObjectHeader(object_id);
1283
1284 // Write out the class and tags information.
1285 writer->WriteIndexedObject(kInt32x4Cid);
1286 writer->WriteTags(writer->GetObjectTags(this));
1287
1288 // Write out the mask values.
1289 writer->Write<uint32_t>(value_[0]);
1290 writer->Write<uint32_t>(value_[1]);
1291 writer->Write<uint32_t>(value_[2]);
1292 writer->Write<uint32_t>(value_[3]);
1293}
1294
1295Float64x2Ptr Float64x2::ReadFrom(SnapshotReader* reader,
1296 intptr_t object_id,
1297 intptr_t tags,
1298 Snapshot::Kind kind,
1299 bool as_reference) {
1300 ASSERT(reader != NULL);
1301 // Read the values.
1302 double value0 = reader->Read<double>();
1303 double value1 = reader->Read<double>();
1304
1305 // Create a Float64x2 object.
1306 Float64x2& simd = Float64x2::ZoneHandle(reader->zone(), Float64x2::null());
1307 simd = Float64x2::New(value0, value1);
1308 reader->AddBackRef(object_id, &simd, kIsDeserialized);
1309 return simd.raw();
1310}
1311
1312void Float64x2Layout::WriteTo(SnapshotWriter* writer,
1313 intptr_t object_id,
1314 Snapshot::Kind kind,
1315 bool as_reference) {
1316 ASSERT(writer != NULL);
1317
1318 // Write out the serialization header value for this object.
1319 writer->WriteInlinedObjectHeader(object_id);
1320
1321 // Write out the class and tags information.
1322 writer->WriteIndexedObject(kFloat64x2Cid);
1323 writer->WriteTags(writer->GetObjectTags(this));
1324
1325 // Write out the float values.
1326 writer->Write<double>(value_[0]);
1327 writer->Write<double>(value_[1]);
1328}
1329
1330TypedDataPtr TypedData::ReadFrom(SnapshotReader* reader,
1331 intptr_t object_id,
1332 intptr_t tags,
1333 Snapshot::Kind kind,
1334 bool as_reference) {
1335 ASSERT(reader != NULL);
1336
1337 intptr_t cid = ObjectLayout::ClassIdTag::decode(tags);
1338 intptr_t len = reader->ReadSmiValue();
1339 TypedData& result =
1340 TypedData::ZoneHandle(reader->zone(), TypedData::New(cid, len));
1341 reader->AddBackRef(object_id, &result, kIsDeserialized);
1342
1343 // Setup the array elements.
1344 intptr_t element_size = ElementSizeInBytes(cid);
1345 intptr_t length_in_bytes = len * element_size;
1346 NoSafepointScope no_safepoint;
1347 uint8_t* data = reinterpret_cast<uint8_t*>(result.DataAddr(0));
1348 reader->Align(Zone::kAlignment);
1349 reader->ReadBytes(data, length_in_bytes);
1350
1351 // If it is a canonical constant make it one.
1352 // When reading a full snapshot we don't need to canonicalize the object
1353 // as it would already be a canonical object.
1354 // When reading a script snapshot or a message snapshot we always have
1355 // to canonicalize the object.
1356 if (ObjectLayout::IsCanonical(tags)) {
1357 const char* error_str = NULL;
1358 result ^= result.CheckAndCanonicalize(reader->thread(), &error_str);
1359 if (error_str != NULL) {
1360 FATAL1("Failed to canonicalize: %s", error_str);
1361 }
1362 ASSERT(!result.IsNull());
1363 ASSERT(result.IsCanonical());
1364 }
1365 return result.raw();
1366}
1367
1368ExternalTypedDataPtr ExternalTypedData::ReadFrom(SnapshotReader* reader,
1369 intptr_t object_id,
1370 intptr_t tags,
1371 Snapshot::Kind kind,
1372 bool as_reference) {
1373 ASSERT(!Snapshot::IsFull(kind));
1374 intptr_t cid = ObjectLayout::ClassIdTag::decode(tags);
1375 intptr_t length = reader->ReadSmiValue();
1376
1377 FinalizableData finalizable_data =
1378 static_cast<MessageSnapshotReader*>(reader)->finalizable_data()->Take();
1379 uint8_t* data = reinterpret_cast<uint8_t*>(finalizable_data.data);
1380 ExternalTypedData& obj =
1381 ExternalTypedData::ZoneHandle(ExternalTypedData::New(cid, data, length));
1382 reader->AddBackRef(object_id, &obj, kIsDeserialized);
1383 intptr_t external_size = obj.LengthInBytes();
1384 obj.AddFinalizer(finalizable_data.peer, finalizable_data.callback,
1385 external_size);
1386 return obj.raw();
1387}
1388
1389// This function's name can appear in Observatory.
1390static void IsolateMessageTypedDataFinalizer(void* isolate_callback_data,
1391 Dart_WeakPersistentHandle handle,
1392 void* buffer) {
1393 free(buffer);
1394}
1395
1396void TypedDataLayout::WriteTo(SnapshotWriter* writer,
1397 intptr_t object_id,
1398 Snapshot::Kind kind,
1399 bool as_reference) {
1400 ASSERT(writer != NULL);
1401 intptr_t cid = this->GetClassId();
1402 intptr_t length = Smi::Value(length_); // In elements.
1403 intptr_t external_cid;
1404 intptr_t bytes;
1405 switch (cid) {
1406 case kTypedDataInt8ArrayCid:
1407 external_cid = kExternalTypedDataInt8ArrayCid;
1408 bytes = length * sizeof(int8_t);
1409 break;
1410 case kTypedDataUint8ArrayCid:
1411 external_cid = kExternalTypedDataUint8ArrayCid;
1412 bytes = length * sizeof(uint8_t);
1413 break;
1414 case kTypedDataUint8ClampedArrayCid:
1415 external_cid = kExternalTypedDataUint8ClampedArrayCid;
1416 bytes = length * sizeof(uint8_t);
1417 break;
1418 case kTypedDataInt16ArrayCid:
1419 external_cid = kExternalTypedDataInt16ArrayCid;
1420 bytes = length * sizeof(int16_t);
1421 break;
1422 case kTypedDataUint16ArrayCid:
1423 external_cid = kExternalTypedDataUint16ArrayCid;
1424 bytes = length * sizeof(uint16_t);
1425 break;
1426 case kTypedDataInt32ArrayCid:
1427 external_cid = kExternalTypedDataInt32ArrayCid;
1428 bytes = length * sizeof(int32_t);
1429 break;
1430 case kTypedDataUint32ArrayCid:
1431 external_cid = kExternalTypedDataUint32ArrayCid;
1432 bytes = length * sizeof(uint32_t);
1433 break;
1434 case kTypedDataInt64ArrayCid:
1435 external_cid = kExternalTypedDataInt64ArrayCid;
1436 bytes = length * sizeof(int64_t);
1437 break;
1438 case kTypedDataUint64ArrayCid:
1439 external_cid = kExternalTypedDataUint64ArrayCid;
1440 bytes = length * sizeof(uint64_t);
1441 break;
1442 case kTypedDataFloat32ArrayCid:
1443 external_cid = kExternalTypedDataFloat32ArrayCid;
1444 bytes = length * sizeof(float);
1445 break;
1446 case kTypedDataFloat64ArrayCid:
1447 external_cid = kExternalTypedDataFloat64ArrayCid;
1448 bytes = length * sizeof(double);
1449 break;
1450 case kTypedDataInt32x4ArrayCid:
1451 external_cid = kExternalTypedDataInt32x4ArrayCid;
1452 bytes = length * sizeof(int32_t) * 4;
1453 break;
1454 case kTypedDataFloat32x4ArrayCid:
1455 external_cid = kExternalTypedDataFloat32x4ArrayCid;
1456 bytes = length * sizeof(float) * 4;
1457 break;
1458 case kTypedDataFloat64x2ArrayCid:
1459 external_cid = kExternalTypedDataFloat64x2ArrayCid;
1460 bytes = length * sizeof(double) * 2;
1461 break;
1462 default:
1463 external_cid = kIllegalCid;
1464 bytes = 0;
1465 UNREACHABLE();
1466 }
1467
1468 // Write out the serialization header value for this object.
1469 writer->WriteInlinedObjectHeader(object_id);
1470
1471 if ((kind == Snapshot::kMessage) &&
1472 (static_cast<uint64_t>(bytes) >= FLAG_externalize_typed_data_threshold)) {
1473 // Write as external.
1474 writer->WriteIndexedObject(external_cid);
1475 writer->WriteTags(writer->GetObjectTags(this));
1476 writer->Write<ObjectPtr>(length_);
1477 uint8_t* data = reinterpret_cast<uint8_t*>(this->data());
1478 void* passed_data = malloc(bytes);
1479 if (passed_data == NULL) {
1480 OUT_OF_MEMORY();
1481 }
1482 memmove(passed_data, data, bytes);
1483 static_cast<MessageWriter*>(writer)->finalizable_data()->Put(
1484 bytes,
1485 passed_data, // data
1486 passed_data, // peer,
1487 IsolateMessageTypedDataFinalizer);
1488 } else {
1489 // Write as internal.
1490 writer->WriteIndexedObject(cid);
1491 writer->WriteTags(writer->GetObjectTags(this));
1492 writer->Write<ObjectPtr>(length_);
1493 uint8_t* data = reinterpret_cast<uint8_t*>(this->data());
1494 writer->Align(Zone::kAlignment);
1495 writer->WriteBytes(data, bytes);
1496 }
1497}
1498
1499void ExternalTypedDataLayout::WriteTo(SnapshotWriter* writer,
1500 intptr_t object_id,
1501 Snapshot::Kind kind,
1502 bool as_reference) {
1503 ASSERT(writer != NULL);
1504 intptr_t cid = this->GetClassId();
1505 intptr_t length = Smi::Value(length_); // In elements.
1506 intptr_t bytes;
1507 switch (cid) {
1508 case kExternalTypedDataInt8ArrayCid:
1509 bytes = length * sizeof(int8_t);
1510 break;
1511 case kExternalTypedDataUint8ArrayCid:
1512 bytes = length * sizeof(uint8_t);
1513 break;
1514 case kExternalTypedDataUint8ClampedArrayCid:
1515 bytes = length * sizeof(uint8_t);
1516 break;
1517 case kExternalTypedDataInt16ArrayCid:
1518 bytes = length * sizeof(int16_t);
1519 break;
1520 case kExternalTypedDataUint16ArrayCid:
1521 bytes = length * sizeof(uint16_t);
1522 break;
1523 case kExternalTypedDataInt32ArrayCid:
1524 bytes = length * sizeof(int32_t);
1525 break;
1526 case kExternalTypedDataUint32ArrayCid:
1527 bytes = length * sizeof(uint32_t);
1528 break;
1529 case kExternalTypedDataInt64ArrayCid:
1530 bytes = length * sizeof(int64_t);
1531 break;
1532 case kExternalTypedDataUint64ArrayCid:
1533 bytes = length * sizeof(uint64_t);
1534 break;
1535 case kExternalTypedDataFloat32ArrayCid:
1536 bytes = length * sizeof(float); // NOLINT.
1537 break;
1538 case kExternalTypedDataFloat64ArrayCid:
1539 bytes = length * sizeof(double); // NOLINT.
1540 break;
1541 case kExternalTypedDataInt32x4ArrayCid:
1542 bytes = length * sizeof(int32_t) * 4;
1543 break;
1544 case kExternalTypedDataFloat32x4ArrayCid:
1545 bytes = length * sizeof(float) * 4;
1546 break;
1547 case kExternalTypedDataFloat64x2ArrayCid:
1548 bytes = length * sizeof(double) * 2;
1549 break;
1550 default:
1551 bytes = 0;
1552 UNREACHABLE();
1553 }
1554
1555 // Write out the serialization header value for this object.
1556 writer->WriteInlinedObjectHeader(object_id);
1557
1558 // Write as external.
1559 writer->WriteIndexedObject(cid);
1560 writer->WriteTags(writer->GetObjectTags(this));
1561 writer->Write<ObjectPtr>(length_);
1562 uint8_t* data = reinterpret_cast<uint8_t*>(data_);
1563 void* passed_data = malloc(bytes);
1564 if (passed_data == NULL) {
1565 OUT_OF_MEMORY();
1566 }
1567 memmove(passed_data, data, bytes);
1568 static_cast<MessageWriter*>(writer)->finalizable_data()->Put(
1569 bytes,
1570 passed_data, // data
1571 passed_data, // peer,
1572 IsolateMessageTypedDataFinalizer);
1573}
1574
1575void TypedDataViewLayout::WriteTo(SnapshotWriter* writer,
1576 intptr_t object_id,
1577 Snapshot::Kind kind,
1578 bool as_reference) {
1579 // Views have always a backing store.
1580 ASSERT(typed_data_ != Object::null());
1581
1582 // Write out the serialization header value for this object.
1583 writer->WriteInlinedObjectHeader(object_id);
1584
1585 // Write out the class and tags information.
1586 writer->WriteIndexedObject(GetClassId());
1587 writer->WriteTags(writer->GetObjectTags(this));
1588
1589 // Write members.
1590 writer->Write<ObjectPtr>(offset_in_bytes_);
1591 writer->Write<ObjectPtr>(length_);
1592 writer->WriteObjectImpl(typed_data_, as_reference);
1593}
1594
1595TypedDataViewPtr TypedDataView::ReadFrom(SnapshotReader* reader,
1596 intptr_t object_id,
1597 intptr_t tags,
1598 Snapshot::Kind kind,
1599 bool as_reference) {
1600 auto& typed_data = *reader->TypedDataBaseHandle();
1601 const classid_t cid = ObjectLayout::ClassIdTag::decode(tags);
1602
1603 auto& view = *reader->TypedDataViewHandle();
1604 view = TypedDataView::New(cid);
1605 reader->AddBackRef(object_id, &view, kIsDeserialized);
1606
1607 const intptr_t offset_in_bytes = reader->ReadSmiValue();
1608 const intptr_t length = reader->ReadSmiValue();
1609 typed_data ^= reader->ReadObjectImpl(as_reference);
1610 view.InitializeWith(typed_data, offset_in_bytes, length);
1611
1612 return view.raw();
1613}
1614
1615CapabilityPtr Capability::ReadFrom(SnapshotReader* reader,
1616 intptr_t object_id,
1617 intptr_t tags,
1618 Snapshot::Kind kind,
1619 bool as_reference) {
1620 uint64_t id = reader->Read<uint64_t>();
1621
1622 Capability& result =
1623 Capability::ZoneHandle(reader->zone(), Capability::New(id));
1624 reader->AddBackRef(object_id, &result, kIsDeserialized);
1625 return result.raw();
1626}
1627
1628void CapabilityLayout::WriteTo(SnapshotWriter* writer,
1629 intptr_t object_id,
1630 Snapshot::Kind kind,
1631 bool as_reference) {
1632 // Write out the serialization header value for this object.
1633 writer->WriteInlinedObjectHeader(object_id);
1634
1635 // Write out the class and tags information.
1636 writer->WriteIndexedObject(kCapabilityCid);
1637 writer->WriteTags(writer->GetObjectTags(this));
1638
1639 writer->Write<uint64_t>(id_);
1640}
1641
1642SendPortPtr SendPort::ReadFrom(SnapshotReader* reader,
1643 intptr_t object_id,
1644 intptr_t tags,
1645 Snapshot::Kind kind,
1646 bool as_reference) {
1647 ASSERT(kind == Snapshot::kMessage);
1648
1649 uint64_t id = reader->Read<uint64_t>();
1650 uint64_t origin_id = reader->Read<uint64_t>();
1651
1652 SendPort& result =
1653 SendPort::ZoneHandle(reader->zone(), SendPort::New(id, origin_id));
1654 reader->AddBackRef(object_id, &result, kIsDeserialized);
1655 return result.raw();
1656}
1657
1658void SendPortLayout::WriteTo(SnapshotWriter* writer,
1659 intptr_t object_id,
1660 Snapshot::Kind kind,
1661 bool as_reference) {
1662 // Write out the serialization header value for this object.
1663 writer->WriteInlinedObjectHeader(object_id);
1664
1665 // Write out the class and tags information.
1666 writer->WriteIndexedObject(kSendPortCid);
1667 writer->WriteTags(writer->GetObjectTags(this));
1668
1669 writer->Write<uint64_t>(id_);
1670 writer->Write<uint64_t>(origin_id_);
1671}
1672
1673TransferableTypedDataPtr TransferableTypedData::ReadFrom(SnapshotReader* reader,
1674 intptr_t object_id,
1675 intptr_t tags,
1676 Snapshot::Kind kind,
1677 bool as_reference) {
1678 ASSERT(reader != nullptr);
1679
1680 ASSERT(!Snapshot::IsFull(kind));
1681 const intptr_t length = reader->Read<int32_t>();
1682
1683 const FinalizableData finalizable_data =
1684 static_cast<MessageSnapshotReader*>(reader)->finalizable_data()->Take();
1685 uint8_t* data = reinterpret_cast<uint8_t*>(finalizable_data.data);
1686 auto& transferableTypedData = TransferableTypedData::ZoneHandle(
1687 reader->zone(), TransferableTypedData::New(data, length));
1688 reader->AddBackRef(object_id, &transferableTypedData, kIsDeserialized);
1689 return transferableTypedData.raw();
1690}
1691
1692void TransferableTypedDataLayout::WriteTo(SnapshotWriter* writer,
1693 intptr_t object_id,
1694 Snapshot::Kind kind,
1695 bool as_reference) {
1696 ASSERT(writer != nullptr);
1697 ASSERT(GetClassId() == kTransferableTypedDataCid);
1698 void* peer = writer->thread()->heap()->GetPeer(ObjectPtr(this));
1699 // Assume that object's Peer is only used to track transferrability state.
1700 ASSERT(peer != nullptr);
1701 TransferableTypedDataPeer* tpeer =
1702 reinterpret_cast<TransferableTypedDataPeer*>(peer);
1703 intptr_t length = tpeer->length(); // In bytes.
1704 void* data = tpeer->data();
1705 if (data == nullptr) {
1706 writer->SetWriteException(
1707 Exceptions::kArgument,
1708 "Illegal argument in isolate message"
1709 " : (TransferableTypedData has been transferred already)");
1710 return;
1711 }
1712
1713 // Write out the serialization header value for this object.
1714 writer->WriteInlinedObjectHeader(object_id);
1715
1716 writer->WriteIndexedObject(GetClassId());
1717 writer->WriteTags(writer->GetObjectTags(this));
1718 writer->Write<int32_t>(length);
1719
1720 static_cast<MessageWriter*>(writer)->finalizable_data()->Put(
1721 length, data, tpeer,
1722 // Finalizer does nothing - in case of failure to serialize,
1723 // [data] remains wrapped in sender's [TransferableTypedData].
1724 [](void* data, Dart_WeakPersistentHandle handle, void* peer) {},
1725 // This is invoked on successful serialization of the message
1726 [](void* data, Dart_WeakPersistentHandle handle, void* peer) {
1727 TransferableTypedDataPeer* tpeer =
1728 reinterpret_cast<TransferableTypedDataPeer*>(peer);
1729 tpeer->handle()->EnsureFreedExternal(IsolateGroup::Current());
1730 tpeer->ClearData();
1731 });
1732}
1733
1734RegExpPtr RegExp::ReadFrom(SnapshotReader* reader,
1735 intptr_t object_id,
1736 intptr_t tags,
1737 Snapshot::Kind kind,
1738 bool as_reference) {
1739 ASSERT(reader != NULL);
1740
1741 // Allocate RegExp object.
1742 RegExp& regex = RegExp::ZoneHandle(reader->zone(), RegExp::New());
1743 reader->AddBackRef(object_id, &regex, kIsDeserialized);
1744
1745 // Read and Set all the other fields.
1746 regex.StoreSmi(&regex.raw_ptr()->num_bracket_expressions_,
1747 reader->ReadAsSmi());
1748
1749 *reader->ArrayHandle() ^= reader->ReadObjectImpl(kAsInlinedObject);
1750 regex.set_capture_name_map(*reader->ArrayHandle());
1751 *reader->StringHandle() ^= reader->ReadObjectImpl(kAsInlinedObject);
1752 regex.set_pattern(*reader->StringHandle());
1753
1754 regex.StoreNonPointer(&regex.raw_ptr()->num_one_byte_registers_,
1755 reader->Read<int32_t>());
1756 regex.StoreNonPointer(&regex.raw_ptr()->num_two_byte_registers_,
1757 reader->Read<int32_t>());
1758 regex.StoreNonPointer(&regex.raw_ptr()->type_flags_, reader->Read<int8_t>());
1759
1760 const Function& no_function = Function::Handle(reader->zone());
1761 for (intptr_t cid = kOneByteStringCid; cid <= kExternalTwoByteStringCid;
1762 cid++) {
1763 regex.set_function(cid, /*sticky=*/false, no_function);
1764 regex.set_function(cid, /*sticky=*/true, no_function);
1765 }
1766
1767 return regex.raw();
1768}
1769
1770void RegExpLayout::WriteTo(SnapshotWriter* writer,
1771 intptr_t object_id,
1772 Snapshot::Kind kind,
1773 bool as_reference) {
1774 ASSERT(writer != NULL);
1775
1776 // Write out the serialization header value for this object.
1777 writer->WriteInlinedObjectHeader(object_id);
1778
1779 // Write out the class and tags information.
1780 writer->WriteIndexedObject(kRegExpCid);
1781 writer->WriteTags(writer->GetObjectTags(this));
1782
1783 // Write out all the other fields.
1784 writer->Write<ObjectPtr>(num_bracket_expressions_);
1785 writer->WriteObjectImpl(pattern_, kAsInlinedObject);
1786 writer->Write<int32_t>(num_one_byte_registers_);
1787 writer->Write<int32_t>(num_two_byte_registers_);
1788 writer->Write<int8_t>(type_flags_);
1789}
1790
1791WeakPropertyPtr WeakProperty::ReadFrom(SnapshotReader* reader,
1792 intptr_t object_id,
1793 intptr_t tags,
1794 Snapshot::Kind kind,
1795 bool as_reference) {
1796 ASSERT(reader != NULL);
1797
1798 // Allocate the weak property object.
1799 WeakProperty& weak_property =
1800 WeakProperty::ZoneHandle(reader->zone(), WeakProperty::New());
1801 reader->AddBackRef(object_id, &weak_property, kIsDeserialized);
1802
1803 // Set all the object fields.
1804 READ_OBJECT_FIELDS(weak_property, weak_property.raw()->ptr()->from(),
1805 weak_property.raw()->ptr()->to(), kAsReference);
1806
1807 return weak_property.raw();
1808}
1809
1810void WeakPropertyLayout::WriteTo(SnapshotWriter* writer,
1811 intptr_t object_id,
1812 Snapshot::Kind kind,
1813 bool as_reference) {
1814 ASSERT(writer != NULL);
1815
1816 // Write out the serialization header value for this object.
1817 writer->WriteInlinedObjectHeader(object_id);
1818
1819 // Write out the class and tags information.
1820 writer->WriteIndexedObject(kWeakPropertyCid);
1821 writer->WriteTags(writer->GetObjectTags(this));
1822
1823 // Write out all the object pointer fields.
1824 SnapshotWriterVisitor visitor(writer, kAsReference);
1825 visitor.VisitPointers(from(), to());
1826}
1827
1828} // namespace dart
1829