Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(562)

Side by Side Diff: pkg/compiler/lib/src/serialization/serialization.dart

Issue 1192103002: Support serialization of the compiler backbone. (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Handle (bypass) external const constructors. Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file.
4
5 library dart2js.serialization;
6
7 import '../elements/elements.dart';
8 import '../constants/expressions.dart';
9 import '../dart_types.dart';
10
11 import 'element_serialization.dart';
12 import 'constant_serialization.dart';
13 import 'type_serialization.dart';
14 import 'keys.dart';
15 import 'json_serializer.dart';
16 import 'values.dart';
17
18 /// An object that supports the encoding an [ObjectValue] for serialization.
19 ///
20 /// The [ObjectEncoder] ensures that nominality and circularities of
21 /// non-primitive values like [Element], [DartType] and [ConstantExpression] are
22 /// handled.
23 class ObjectEncoder extends AbstractEncoder<Key> {
24 /// Creates an [ObjectEncoder] in the scope of [serializer] that uses [map]
25 /// as its internal storage.
26 ObjectEncoder(Serializer serializer, Map<dynamic, Value> map)
27 : super(serializer, map);
28
29 String get _name => 'Object';
30 }
31
32 /// An object that supports the encoding a [MapValue] for serialization.
33 ///
34 /// The [MapEncoder] ensures that nominality and circularities of
35 /// non-primitive values like [Element], [DartType] and [ConstantExpression] are
36 /// handled.
37 class MapEncoder extends AbstractEncoder<String> {
38 /// Creates an [MapEncoder] in the scope of [serializer] that uses [map]
39 /// as its internal storage.
40 MapEncoder(Serializer serializer, Map<String, Value> map)
41 : super(serializer, map);
42
43 String get _name => 'Map';
44 }
45
46 /// An object that supports the encoding a [ListValue] containing [ObjectValue]s
47 /// or [MapValue]s.
48 ///
49 /// The [ListEncoder] ensures that nominality and circularities of
50 /// non-primitive values like [Element], [DartType] and [ConstantExpression] are
51 /// handled.
52 class ListEncoder {
53 final Serializer _serializer;
54 final List<Value> _list;
55
56 /// Creates an [ListEncoder] in the scope of [_serializer] that uses [_list]
57 /// as its internal storage.
58 ListEncoder(this._serializer, this._list);
59
60 /// Creates an [ObjectEncoder] and adds it to the encoded list.
61 ObjectEncoder createObject() {
62 Map<Key, Value> map = <Key, Value>{};
63 _list.add(new ObjectValue(map));
64 return new ObjectEncoder(_serializer, map);
65 }
66
67 /// Creates an [ObjectEncoder] and adds it to the encoded list.
68 MapEncoder createMap() {
69 Map<String, Value> map = {};
70 _list.add(new MapValue(map));
71 return new MapEncoder(_serializer, map);
72 }
73 }
74
75 /// Abstract base implementation for [ObjectEncoder] and [MapEncoder].
76 abstract class AbstractEncoder<K> {
77 final Serializer _serializer;
78 final Map<K, Value> _map;
79
80 AbstractEncoder(this._serializer, this._map);
81
82 /// The name of the encoder kind. Use for error reporting.
83 String get _name;
84
85 void _checkKey(K key) {
86 if (_map.containsKey(key)) {
87 throw new StateError("$_name value '$key' already in $_map.");
88 }
89 }
90
91 /// Maps the [key] entry to the enum [value] in the encoded object.
92 void setEnum(K key, var value) {
93 _checkKey(key);
94 _map[key] = new EnumValue(value);
95 }
96
97 /// Maps the [key] entry to the [element] in the encoded object.
98 void setElement(K key, Element element) {
99 _checkKey(key);
100 _map[key] = _serializer.createElementValue(element);
101 }
102
103 /// Maps the [key] entry to the [elements] in the encoded object.
104 ///
105 /// If [elements] is empty, it is skipped.
106 void setElements(K key, Iterable<Element> elements) {
107 _checkKey(key);
108 if (elements.isNotEmpty) {
109 _map[key] = new ListValue(
110 elements.map(_serializer.createElementValue).toList());
111 }
112 }
113
114 /// Maps the [key] entry to the [constant] in the encoded object.
115 void setConstant(K key, ConstantExpression constant) {
116 _checkKey(key);
117 _map[key] = _serializer.createConstantValue(constant);
118 }
119
120 /// Maps the [key] entry to the [constants] in the encoded object.
121 ///
122 /// If [constants] is empty, it is skipped.
123 void setConstants(K key, Iterable<ConstantExpression> constants) {
124 _checkKey(key);
125 if (constants.isNotEmpty) {
126 _map[key] = new ListValue(
127 constants.map(_serializer.createConstantValue).toList());
128 }
129 }
130
131 /// Maps the [key] entry to the [type] in the encoded object.
132 void setType(K key, DartType type) {
133 _checkKey(key);
134 _map[key] = _serializer.createTypeValue(type);
135 }
136
137 /// Maps the [key] entry to the [types] in the encoded object.
138 ///
139 /// If [types] is empty, it is skipped.
140 void setTypes(K key, Iterable<DartType> types) {
141 _checkKey(key);
142 if (types.isNotEmpty) {
143 _map[key] =
144 new ListValue(types.map(_serializer.createTypeValue).toList());
145 }
146 }
147
148 /// Maps the [key] entry to the [uri] in the encoded object using [baseUri] to
149 /// relatives the encoding.
150 ///
151 /// For instance, a source file like `sdk/lib/core/string.dart` should be
152 /// serialized relative to the library root.
153 void setUri(K key, Uri baseUri, Uri uri) {
154 _checkKey(key);
155 _map[key] = new UriValue(baseUri, uri);
156 }
157
158 /// Maps the [key] entry to the string [value] in the encoded object.
159 void setString(K key, String value) {
160 _checkKey(key);
161 _map[key] = new StringValue(value);
162 }
163
164 /// Maps the [key] entry to the string [values] in the encoded object.
165 ///
166 /// If [values] is empty, it is skipped.
167 void setStrings(K key, Iterable<String> values) {
168 _checkKey(key);
169 if (values.isNotEmpty) {
170 _map[key] = new ListValue(values.map((v) => new StringValue(v)).toList());
171 }
172 }
173
174 /// Maps the [key] entry to the bool [value] in the encoded object.
175 void setBool(K key, bool value) {
176 _checkKey(key);
177 _map[key] = new BoolValue(value);
178 }
179
180 /// Maps the [key] entry to the int [value] in the encoded object.
181 void setInt(K key, int value) {
182 _checkKey(key);
183 _map[key] = new IntValue(value);
184 }
185
186 /// Maps the [key] entry to the int [values] in this serializer.
187 ///
188 /// If [values] is empty, it is skipped.
189 void setInts(K key, Iterable<int> values) {
190 _checkKey(key);
191 if (values.isNotEmpty) {
192 _map[key] = new ListValue(values.map((v) => new IntValue(v)).toList());
193 }
194 }
195
196 /// Maps the [key] entry to the double [value] in the encoded object.
197 void setDouble(K key, double value) {
198 _checkKey(key);
199 _map[key] = new DoubleValue(value);
200 }
201
202 /// Creates and returns an [ObjectEncoder] that is mapped to the [key]
203 /// entry in the encoded object.
204 ObjectEncoder createObject(K key) {
205 Map<Key, Value> map = <Key, Value>{};
206 _map[key] = new ObjectValue(map);
207 return new ObjectEncoder(_serializer, map);
208 }
209
210 /// Creates and returns a [MapEncoder] that is mapped to the [key] entry
211 /// in the encoded object.
212 MapEncoder createMap(K key) {
213 Map<String, Value> map = <String, Value>{};
214 _map[key] = new MapValue(map);
215 return new MapEncoder(_serializer, map);
216 }
217
218 /// Creates and returns a [ListEncoder] that is mapped to the [key] entry
219 /// in the encoded object.
220 ListEncoder createList(K key) {
221 List<Value> list = <Value>[];
222 _map[key] = new ListValue(list);
223 return new ListEncoder(_serializer, list);
224 }
225
226 String toString() => _map.toString();
227 }
228
229 /// [ObjectDecoder] reads serialized values from a [Map] encoded from an
230 /// [ObjectValue] where properties are stored using [Key] values as keys.
231 class ObjectDecoder extends AbstractDecoder<Key> {
232 /// Creates an [ObjectDecoder] that decodes [map] into deserialized values
233 /// using [deserializer] to create canonicalized values.
234 ObjectDecoder(Deserializer deserializer, Map map)
235 : super(deserializer, map);
236
237 @override
238 _getKeyValue(Key key) => _deserializer.decoder.getObjectPropertyValue(key);
239 }
240
241 /// [MapDecoder] reads serialized values from a [Map] encoded from an
242 /// [MapValue] where entries are stored using [String] values as keys.
243 class MapDecoder extends AbstractDecoder<String> {
244 /// Creates an [MapDecoder] that decodes [map] into deserialized values
245 /// using [deserializer] to create canonicalized values.
246 MapDecoder(Deserializer deserializer, Map<String, dynamic> map)
247 : super(deserializer, map);
248
249 @override
250 _getKeyValue(String key) => key;
251
252 /// Applies [f] to every key in the decoded [Map].
253 void forEachKey(f(String key)) {
254 _map.keys.forEach(f);
255 }
256 }
257
258 /// [ListDecoder] reads serialized map or object values from a [List].
259 class ListDecoder {
260 final Deserializer _deserializer;
261 final List _list;
262
263 /// Creates a [ListDecoder] that decodes [_list] using [_deserializer] to
264 /// create canonicalized values.
265 ListDecoder(this._deserializer, this._list);
266
267 /// The number of values in the decoded list.
268 int get length => _list.length;
269
270 /// Returns an [ObjectDecoder] for the [index]th object value in the decoded
271 /// list.
272 ObjectDecoder getObject(int index) {
273 return new ObjectDecoder(_deserializer, _list[index]);
274 }
275
276 /// Returns an [MapDecoder] for the [index]th map value in the decoded list.
277 MapDecoder getMap(int index) {
278 return new MapDecoder(_deserializer, _list[index]);
279 }
280 }
281
282 /// Abstract base implementation for [ObjectDecoder] and [MapDecoder].
283 abstract class AbstractDecoder<K> {
284 final Deserializer _deserializer;
285 final Map<K, dynamic> _map;
286
287 AbstractDecoder(this._deserializer, this._map) {
288 assert(_deserializer != null);
289 assert(_map != null);
290 }
291
292 /// Returns the value for [key] defined by the [SerializationDecoder] in used
293 /// [_deserializer].
294 _getKeyValue(K key);
295
296 /// Returns `true` if [key] has an associated value in the decoded object.
297 bool containsKey(K key) => _map.containsKey(_getKeyValue(key));
298
299 /// Returns the enum value from the [enumValues] associated with [key] in the
300 /// decoded object.
301 ///
302 /// If no value is associated with [key], then if [isOptional] is `true`,
303 /// [defaultValue] is returned, otherwise an exception is thrown.
304 getEnum(K key, List enumValues, {bool isOptional: false, defaultValue}) {
305 int value = _map[_getKeyValue(key)];
306 if (value == null) {
307 if (isOptional || defaultValue != null) {
308 return defaultValue;
309 }
310 throw new StateError("enum value '$key' not found in $_map.");
311 }
312 return enumValues[value];
313 }
314
315 /// Returns the [Element] value associated with [key] in the decoded object.
316 ///
317 /// If no value is associated with [key], then if [isOptional] is `true`,
318 /// `null` is returned, otherwise an exception is thrown.
319 Element getElement(K key, {bool isOptional: false}) {
320 int id = _map[_getKeyValue(key)];
321 if (id == null) {
322 if (isOptional) {
323 return null;
324 }
325 throw new StateError("Element value '$key' not found in $_map.");
326 }
327 return _deserializer.deserializeElement(id);
328 }
329
330 /// Returns the list of [Element] values associated with [key] in the decoded
331 /// object.
332 ///
333 /// If no value is associated with [key], then if [isOptional] is `true`,
334 /// and empty [List] is returned, otherwise an exception is thrown.
335 List<Element> getElements(K key, {bool isOptional: false}) {
336 List list = _map[_getKeyValue(key)];
337 if (list == null) {
338 if (isOptional) {
339 return const [];
340 }
341 throw new StateError("Elements value '$key' not found in $_map.");
342 }
343 return list.map(_deserializer.deserializeElement).toList();
344 }
345
346 /// Returns the [ConstantExpression] value associated with [key] in the
347 /// decoded object.
348 ///
349 /// If no value is associated with [key], then if [isOptional] is `true`,
350 /// `null` is returned, otherwise an exception is thrown.
351 ConstantExpression getConstant(K key, {bool isOptional: false}) {
352 int id = _map[_getKeyValue(key)];
353 if (id == null) {
354 if (isOptional) {
355 return null;
356 }
357 throw new StateError("Constant value '$key' not found in $_map.");
358 }
359 return _deserializer.deserializeConstant(id);
360 }
361
362 /// Returns the list of [ConstantExpression] values associated with [key] in
363 /// the decoded object.
364 ///
365 /// If no value is associated with [key], then if [isOptional] is `true`,
366 /// and empty [List] is returned, otherwise an exception is thrown.
367 List<ConstantExpression> getConstants(K key, {bool isOptional: false}) {
368 List list = _map[_getKeyValue(key)];
369 if (list == null) {
370 if (isOptional) {
371 return const [];
372 }
373 throw new StateError("Constants value '$key' not found in $_map.");
374 }
375 return list.map(_deserializer.deserializeConstant).toList();
376 }
377
378 /// Returns the [DartType] value associated with [key] in the decoded object.
379 ///
380 /// If no value is associated with [key], then if [isOptional] is `true`,
381 /// `null` is returned, otherwise an exception is thrown.
382 DartType getType(K key, {bool isOptional: false}) {
383 int id = _map[_getKeyValue(key)];
384 if (id == null) {
385 if (isOptional) {
386 return null;
387 }
388 throw new StateError("Type value '$key' not found in $_map.");
389 }
390 return _deserializer.deserializeType(id);
391 }
392
393 /// Returns the list of [DartType] values associated with [key] in the decoded
394 /// object.
395 ///
396 /// If no value is associated with [key], then if [isOptional] is `true`,
397 /// and empty [List] is returned, otherwise an exception is thrown.
398 List<DartType> getTypes(K key, {bool isOptional: false}) {
399 List list = _map[_getKeyValue(key)];
400 if (list == null) {
401 if (isOptional) {
402 return const [];
403 }
404 throw new StateError("Types value '$key' not found in $_map.");
405 }
406 return list.map(_deserializer.deserializeType).toList();
407 }
408
409 /// Returns the [Uri] value associated with [key] in the decoded object.
410 ///
411 /// If no value is associated with [key], then if [isOptional] is `true`,
412 /// [defaultValue] is returned, otherwise an exception is thrown.
413 Uri getUri(K key, {bool isOptional: false, Uri defaultValue}) {
414 String value = _map[_getKeyValue(key)];
415 if (value == null) {
416 if (isOptional || defaultValue != null) {
417 return defaultValue;
418 }
419 throw new StateError("Uri value '$key' not found in $_map.");
420 }
421 return Uri.parse(value);
422 }
423
424 /// Returns the [String] value associated with [key] in the decoded object.
425 ///
426 /// If no value is associated with [key], then if [isOptional] is `true`,
427 /// [defaultValue] is returned, otherwise an exception is thrown.
428 String getString(K key, {bool isOptional: false, String defaultValue}) {
429 String value = _map[_getKeyValue(key)];
430 if (value == null) {
431 if (isOptional || defaultValue != null) {
432 return defaultValue;
433 }
434 throw new StateError("String value '$key' not found in $_map.");
435 }
436 return value;
437 }
438
439 /// Returns the list of [String] values associated with [key] in the decoded
440 /// object.
441 ///
442 /// If no value is associated with [key], then if [isOptional] is `true`,
443 /// and empty [List] is returned, otherwise an exception is thrown.
444 List<String> getStrings(K key, {bool isOptional: false}) {
445 List list = _map[_getKeyValue(key)];
446 if (list == null) {
447 if (isOptional) {
448 return const [];
449 }
450 throw new StateError("Strings value '$key' not found in $_map.");
451 }
452 return list;
453 }
454
455 /// Returns the [bool] value associated with [key] in the decoded object.
456 ///
457 /// If no value is associated with [key], then if [isOptional] is `true`,
458 /// [defaultValue] is returned, otherwise an exception is thrown.
459 bool getBool(K key, {bool isOptional: false, bool defaultValue}) {
460 bool value = _map[_getKeyValue(key)];
461 if (value == null) {
462 if (isOptional || defaultValue != null) {
463 return defaultValue;
464 }
465 throw new StateError("bool value '$key' not found in $_map.");
466 }
467 return value;
468 }
469
470 /// Returns the [int] value associated with [key] in the decoded object.
471 ///
472 /// If no value is associated with [key], then if [isOptional] is `true`,
473 /// [defaultValue] is returned, otherwise an exception is thrown.
474 int getInt(K key, {bool isOptional: false, int defaultValue}) {
475 int value = _map[_getKeyValue(key)];
476 if (value == null) {
477 if (isOptional || defaultValue != null) {
478 return defaultValue;
479 }
480 throw new StateError("int value '$key' not found in $_map.");
481 }
482 return value;
483 }
484
485 /// Returns the list of [int] values associated with [key] in the decoded
486 /// object.
487 ///
488 /// If no value is associated with [key], then if [isOptional] is `true`,
489 /// and empty [List] is returned, otherwise an exception is thrown.
490 List<int> getInts(K key, {bool isOptional: false}) {
491 List list = _map[_getKeyValue(key)];
492 if (list == null) {
493 if (isOptional) {
494 return const [];
495 }
496 throw new StateError("Ints value '$key' not found in $_map.");
497 }
498 return list;
499 }
500
501 /// Returns the [double] value associated with [key] in the decoded object.
502 ///
503 /// If no value is associated with [key], then if [isOptional] is `true`,
504 /// [defaultValue] is returned, otherwise an exception is thrown.
505 double getDouble(K key, {bool isOptional: false, double defaultValue}) {
506 double value = _map[_getKeyValue(key)];
507 if (value == null) {
508 if (isOptional || defaultValue != null) {
509 return defaultValue;
510 }
511 throw new StateError("double value '$key' not found in $_map.");
512 }
513 return value;
514 }
515
516 /// Returns an [ObjectDecoder] for the map value associated with [key] in the
517 /// decoded object.
518 ///
519 /// If no value is associated with [key], then if [isOptional] is `true`,
520 /// `null` is returned, otherwise an exception is thrown.
521 ObjectDecoder getObject(K key, {bool isOptional: false}) {
522 Map map = _map[_getKeyValue(key)];
523 if (map == null) {
524 if (isOptional) {
525 return null;
526 }
527 throw new StateError("Object value '$key' not found in $_map.");
528 }
529 return new ObjectDecoder(_deserializer, map);
530 }
531
532 /// Returns an [MapDecoder] for the map value associated with [key] in the
533 /// decoded object.
534 ///
535 /// If no value is associated with [key], then if [isOptional] is `true`,
536 /// `null` is returned, otherwise an exception is thrown.
537 MapDecoder getMap(K key, {bool isOptional: false}) {
538 Map map = _map[_getKeyValue(key)];
539 if (map == null) {
540 if (isOptional) {
541 return null;
542 }
543 throw new StateError("Map value '$key' not found in $_map.");
544 }
545 return new MapDecoder(_deserializer, map);
546 }
547
548 /// Returns an [ListDecoder] for the list value associated with [key] in the
549 /// decoded object.
550 ///
551 /// If no value is associated with [key], then if [isOptional] is `true`,
552 /// `null` is returned, otherwise an exception is thrown.
553 ListDecoder getList(K key, {bool isOptional: false}) {
554 List list = _map[_getKeyValue(key)];
555 if (list == null) {
556 if (isOptional) {
557 return null;
558 }
559 throw new StateError("List value '$key' not found in $_map.");
560 }
561 return new ListDecoder(_deserializer, list);
562 }
563 }
564
565 /// A nominal object containing its serialized value.
566 class DataObject {
567 /// The id for the object.
568 final Value id;
569
570 /// The serialized value of the object.
571 final ObjectValue objectValue;
572
573 DataObject(Value id, EnumValue kind)
574 : this.id = id,
575 this.objectValue =
576 new ObjectValue(<Key, Value>{Key.ID: id, Key.KIND: kind});
577
578 Map<Key, Value> get map => objectValue.map;
579 }
580
581 /// Serializer for the transitive closure of a collection of libraries.
582 ///
583 /// The serializer creates an [ObjectValue] model of the [Element], [DartType]
584 /// and [ConstantExpression] values in the transitive closure of the serialized
585 /// libraries.
586 ///
587 /// The model layout of the produced [objectValue] is:
588 ///
589 /// { // Header object
590 /// Key.ELEMENTS: [
591 /// {...}, // [ObjectValue] of the 0th [Element].
592 /// ...
593 /// {...}, // [ObjectValue] of the n-th [Element].
594 /// ],
595 /// Key.TYPES: [
596 /// {...}, // [ObjectValue] of the 0th [DartType].
597 /// ...
598 /// {...}, // [ObjectValue] of the n-th [DartType].
599 /// ],
600 /// Key.CONSTANTS: [
601 /// {...}, // [ObjectValue] of the 0th [ConstantExpression].
602 /// ...
603 /// {...}, // [ObjectValue] of the n-th [ConstantExpression].
604 /// ],
605 /// }
606 ///
607 // TODO(johnniwinther): Support per-library serialization and dependencies
608 // between serialized subcomponent.
609 class Serializer {
610 final SerializationEncoder _encoder;
611
612 Map<Element, DataObject> _elementMap = <Element, DataObject>{};
613 Map<ConstantExpression, DataObject> _constantMap =
614 <ConstantExpression, DataObject>{};
615 Map<DartType, DataObject> _typeMap = <DartType, DataObject>{};
616 List _pendingList = [];
617
618 Serializer(this._encoder);
619
620 /// Add the transitive closure of [library] to this serializer.
621 void serialize(LibraryElement library) {
622 // Call [_getElementDataObject] for its side-effect: To create a
623 // [DataObject] for [library]. If not already created, this will
624 // put the serialization of [library] in the work queue.
625 _getElementDataObject(library);
626 _emptyWorklist();
627 }
628
629 void _emptyWorklist() {
630 while (_pendingList.isNotEmpty) {
631 _pendingList.removeLast()();
632 }
633 }
634
635 /// Returns the [DataObject] for [element].
636 ///
637 /// If [constant] has no [DataObject], a new [DataObject] is created and
638 /// encoding the [ObjectValue] for [constant] is put into the work queue of
639 /// this serializer.
640 DataObject _getElementDataObject(Element element) {
641 if (element == null) {
642 throw new ArgumentError('Serializer._getElementDataObject(null)');
643 }
644 return _elementMap.putIfAbsent(element, () {
645 // Run through [ELEMENT_SERIALIZERS] sequentially to find the one that
646 // deals with [element].
647 for (ElementSerializer serializer in ELEMENT_SERIALIZERS) {
648 SerializedElementKind kind = serializer.getSerializedKind(element);
649 if (kind != null) {
650 DataObject dataObject = new DataObject(
651 new IntValue(_elementMap.length), new EnumValue(kind));
652 // Delay the serialization of the element itself to avoid loops, and
653 // to keep the call stack small.
654 _pendingList.add(() {
655 serializer.serialize(
656 element, new ObjectEncoder(this, dataObject.map), kind);
657 });
658 return dataObject;
659 }
660 }
661 throw new UnsupportedError(
662 'Unsupported element: $element (${element.kind})');
663 });
664 }
665
666 /// Creates the [ElementValue] for [element].
667 ///
668 /// If [element] has not already been serialized, it is added to the work
669 /// queue of this serializer.
670 ElementValue createElementValue(Element element) {
671 return new ElementValue(element, _getElementDataObject(element).id);
672 }
673
674 /// Returns the [DataObject] for [constant].
675 ///
676 /// If [constant] has no [DataObject], a new [DataObject] is created and
677 /// encoding the [ObjectValue] for [constant] is put into the work queue of
678 /// this serializer.
679 DataObject _getConstantDataObject(ConstantExpression constant) {
680 return _constantMap.putIfAbsent(constant, () {
681 DataObject dataObject = new DataObject(
682 new IntValue(_constantMap.length), new EnumValue(constant.kind));
683 // Delay the serialization of the constant itself to avoid loops, and to
684 // keep the call stack small.
685 _pendingList.add(() => _encodeConstant(constant, dataObject));
686 return dataObject;
687 });
688 }
689
690 /// Encodes [constant] into the [ObjectValue] of [dataObject].
691 void _encodeConstant(ConstantExpression constant, DataObject dataObject) {
692 const ConstantSerializer().visit(constant,
693 new ObjectEncoder(this, dataObject.map));
694 }
695
696 /// Creates the [ConstantValue] for [constant].
697 ///
698 /// If [constant] has not already been serialized, it is added to the work
699 /// queue of this serializer.
700 ConstantValue createConstantValue(ConstantExpression constant) {
701 return new ConstantValue(constant, _getConstantDataObject(constant).id);
702 }
703
704 /// Returns the [DataObject] for [type].
705 ///
706 /// If [type] has no [DataObject], a new [DataObject] is created and
707 /// encoding the [ObjectValue] for [type] is put into the work queue of this
708 /// serializer.
709 DataObject _getTypeDataObject(DartType type) {
710 return _typeMap.putIfAbsent(type, () {
711 DataObject dataObject = new DataObject(
712 new IntValue(_typeMap.length), new EnumValue(type.kind));
713 // Delay the serialization of the type itself to avoid loops, and to keep
714 // the call stack small.
715 _pendingList.add(() => _encodeType(type, dataObject));
716 return dataObject;
717 });
718 }
719
720 /// Encodes [type] into the [ObjectValue] of [dataObject].
721 void _encodeType(DartType type, DataObject dataObject) {
722 const TypeSerializer().visit(type, new ObjectEncoder(this, dataObject.map));
723 }
724
725 /// Creates the [TypeValue] for [type].
726 ///
727 /// If [type] has not already been serialized, it is added to the work
728 /// queue of this serializer.
729 TypeValue createTypeValue(DartType type) {
730 return new TypeValue(type, _getTypeDataObject(type).id);
731 }
732
733 ObjectValue get objectValue {
734 Map<Key, Value> map = <Key, Value>{};
735 map[Key.ELEMENTS] =
736 new ListValue(_elementMap.values.map((l) => l.objectValue).toList());
737 if (_typeMap.isNotEmpty) {
738 map[Key.TYPES] =
739 new ListValue(_typeMap.values.map((l) => l.objectValue).toList());
740 }
741 if (_constantMap.isNotEmpty) {
742 map[Key.CONSTANTS] =
743 new ListValue(_constantMap.values.map((l) => l.objectValue).toList());
744 }
745 return new ObjectValue(map);
746 }
747
748 String toText() {
749 return _encoder.encode(objectValue);
750 }
751
752 String prettyPrint() {
753 PrettyPrintEncoder encoder = new PrettyPrintEncoder();
754 return encoder.toText(objectValue);
755 }
756 }
757
758 /// Deserializer for a closed collection of libraries.
759 // TODO(johnniwinther): Support per-library deserialization and dependencies
760 // between deserialized subcomponent.
761 class Deserializer {
762 final SerializationDecoder decoder;
763 ObjectDecoder _headerObject;
764 ListDecoder _elementList;
765 ListDecoder _typeList;
766 ListDecoder _constantList;
767 Map<int, Element> _elementMap = {};
768 Map<int, DartType> _typeMap = {};
769 Map<int, ConstantExpression> _constantMap = {};
770
771 Deserializer.fromText(String text, this.decoder) {
772 _headerObject = new ObjectDecoder(this, decoder.decode(text));
773 }
774
775 /// Returns the [ListDecoder] for the [Element]s in this deserializer.
776 ListDecoder get elements {
777 if (_elementList == null) {
778 _elementList = _headerObject.getList(Key.ELEMENTS);
779 }
780 return _elementList;
781 }
782
783 /// Returns the [ListDecoder] for the [DartType]s in this deserializer.
784 ListDecoder get types {
785 if (_typeList == null) {
786 _typeList = _headerObject.getList(Key.TYPES);
787 }
788 return _typeList;
789 }
790
791 /// Returns the [ListDecoder] for the [ConstantExpression]s in this
792 /// deserializer.
793 ListDecoder get constants {
794 if (_constantList == null) {
795 _constantList = _headerObject.getList(Key.CONSTANTS);
796 }
797 return _constantList;
798 }
799
800 /// Returns the [LibraryElement] for [uri] if part of the deserializer.
801 LibraryElement lookupLibrary(Uri uri) {
802 // TODO(johnniwinther): Libraries should be stored explicitly in the header.
803 ListDecoder list = elements;
804 for (int i = 0; i < list.length; i++) {
805 ObjectDecoder object = list.getObject(i);
806 SerializedElementKind kind =
807 object.getEnum(Key.KIND, SerializedElementKind.values);
808 if (kind == SerializedElementKind.LIBRARY) {
809 Uri libraryUri = object.getUri(Key.CANONICAL_URI);
810 if (libraryUri == uri) {
811 return deserializeElement(object.getInt(Key.ID));
812 }
813 }
814 }
815 return null;
816 }
817
818 /// Returns the deserialized [Element] for [id].
819 Element deserializeElement(int id) {
820 if (id == null) throw new ArgumentError('Deserializer.getElement(null)');
821 return _elementMap.putIfAbsent(id, () {
822 return ElementDeserializer.deserialize(elements.getObject(id));
823 });
824 }
825
826 /// Returns the deserialized [DartType] for [id].
827 DartType deserializeType(int id) {
828 if (id == null) throw new ArgumentError('Deserializer.getType(null)');
829 return _typeMap.putIfAbsent(id, () {
830 return TypeDeserializer.deserialize(types.getObject(id));
831 });
832 }
833
834 /// Returns the deserialized [ConstantExpression] for [id].
835 ConstantExpression deserializeConstant(int id) {
836 if (id == null) throw new ArgumentError('Deserializer.getConstant(null)');
837 return _constantMap.putIfAbsent(id, () {
838 return ConstantDeserializer.deserialize(constants.getObject(id));
839 });
840 }
841 }
842
843 /// Strategy used by [Serializer] to define the memory and output encoding.
844 abstract class SerializationEncoder {
845 /// Encode [objectValue] into text.
846 String encode(ObjectValue objectValue);
847 }
848
849 /// Strategy used by [Deserializer] for decoding and reading data from a
850 /// serialized output.
851 abstract class SerializationDecoder {
852 /// Decode [text] into [Map] containing the data corresponding to an encoding
853 /// of the serializer header object.
854 Map decode(String text);
855
856 /// Returns the value used to store [key] as a property in the encoding an
857 /// [ObjectValue].
858 ///
859 /// Different encodings have different restrictions and capabilities as how
860 /// to store a [Key] value. For instance: A JSON encoding needs to convert
861 /// [Key] to a [String] to store it in a JSON object; a Dart encoding can
862 /// choose to store a [Key] as an [int] or as the [Key] itself.
863 getObjectPropertyValue(Key key);
864 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/serialization/modelz.dart ('k') | pkg/compiler/lib/src/serialization/task.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698