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

Side by Side Diff: sdk/lib/isolate/mangler.dart

Issue 11783009: Big merge from experimental to bleeding edge. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 11 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 | Annotate | Revision Log
« no previous file with comments | « sdk/lib/isolate/isolate_stream.dart ('k') | sdk/lib/isolate/timer.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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 part of dart.isolate;
6
7 class _IsolateEncoder {
8 final manglingToken;
9 // TODO(floitsch): switch to identity set.
10 final Map _encoded = new Map();
11 final Map _visiting = new Map();
12 final Function _mangle;
13 static const int _REFERENCE = 0;
14 static const int _DECLARATION = 1;
15 static const int _ESCAPED = 2;
16 static const int _MANGLED = 3;
17
18 _IsolateEncoder(this.manglingToken, mangle(data))
19 : this._mangle = mangle;
20
21 encode(var data) {
22 if (data is num || data is String || data is bool || data == null) {
23 return data;
24 }
25
26 if (_encoded.containsKey(data)) return _encoded[data];
27 if (_visiting.containsKey(data)) {
28 // Self reference.
29 var selfReference = _visiting[data];
30 if (selfReference == data) {
31 // Nobody used the self-reference yet.
32 selfReference = _createReference();
33 _visiting[data] = selfReference;
34 }
35 return selfReference;
36 }
37 _visiting[data] = data;
38
39 var result;
40
41 if (data is List) {
42 bool hasBeenDuplicated = false;
43 result = data;
44 for (int i = 0; i < data.length; i++) {
45 var mangled = encode(data[i]);
46 if (mangled != data[i] && !hasBeenDuplicated) {
47 result = new List.fixedLength(data.length);
48 for (int j = 0; j < i; j++) {
49 result[j] = data[j];
50 }
51 hasBeenDuplicated = true;
52 }
53 if (hasBeenDuplicated) {
54 result[i] = mangled;
55 }
56 }
57 result = _escapeIfNecessary(result);
58 } else if (data is Set) {
59 // TODO(floitsch): should we accept sets?
60 bool needsCopy = false;
61 for (var entry in data) {
62 var encoded = encode(entry);
63 if (encoded != entry) {
64 needsCopy = true;
65 break;
66 }
67 }
68 result = data;
69 if (needsCopy) {
70 result = new Set();
71 data.forEach((entry) {
72 result.add(encode(entry));
73 });
74 }
75 } else if (data is Map) {
76 bool needsCopy = false;
77 data.forEach((key, value) {
78 var encodedKey = encode(key);
79 var encodedValue = encode(value);
80 if (encodedKey != key) needsCopy = true;
81 if (encodedValue != value) needsCopy = true;
82 });
83 result = data;
84 if (needsCopy) {
85 result = new Map();
86 data.forEach((key, value) {
87 result[encode(key)] = encode(value);
88 });
89 }
90 } else {
91 // We don't handle self-references for user data.
92 // TODO(floitsch): we could keep the reference and throw when we see it
93 // again. However now the user has at least the possibility to do
94 // cyclic data-structures.
95 _visiting.remove(data);
96 result = _mangle(data);
97 if (result != data) {
98 result = _wrapMangled(encode(result));
99 }
100 }
101
102 var selfReference = _visiting[data];
103 if (selfReference != null && selfReference != data) {
104 // A self-reference has been used.
105 result = _declareReference(selfReference, result);
106 }
107 _encoded[data] = result;
108
109 _visiting.remove(data);
110 return result;
111 }
112
113 _createReference() => [manglingToken, _REFERENCE];
114 _declareReference(reference, data) {
115 return [manglingToken, _DECLARATION, reference, data];
116 }
117
118 _wrapMangled(data) => [manglingToken, _MANGLED, data];
119 _escapeIfNecessary(List list) {
120 if (!list.isEmpty && list[0] == manglingToken) {
121 return [manglingToken, _ESCAPED, list];
122 } else {
123 return list;
124 }
125 }
126 }
127
128 class _IsolateDecoder {
129 final manglingToken;
130 final Map _decoded = new Map();
131 final Function _unmangle;
132 static const int _REFERENCE = _IsolateEncoder._REFERENCE;
133 static const int _DECLARATION = _IsolateEncoder._DECLARATION;
134 static const int _ESCAPED = _IsolateEncoder._ESCAPED;
135 static const int _MANGLED = _IsolateEncoder._MANGLED;
136
137 _IsolateDecoder(this.manglingToken, unmangle(data))
138 : this._unmangle = unmangle;
139
140 decode(var data) {
141 if (data is num || data is String || data is bool || data == null) {
142 return data;
143 }
144
145 if (_decoded.containsKey(data)) return _decoded[data];
146
147 if (_isDeclaration(data)) {
148 var reference = _extractReference(data);
149 var declared = _extractDeclared(data);
150 return _decodeObject(declared, reference);
151 } else {
152 return _decodeObject(data, null);
153 }
154 }
155
156 _decodeObject(data, reference) {
157 if (_decoded.containsKey(data)) {
158 assert(reference == null);
159 return _decoded[data];
160 }
161
162 // If the data was a reference then we would have found it in the _decoded
163 // map.
164 assert(!_isReference(data));
165
166 var result;
167 if (_isMangled(data)) {
168 assert(reference == null);
169 List mangled = _extractMangled(data);
170 var decoded = decode(mangled);
171 result = _unmangle(decoded);
172 } else if (data is List) {
173 if (_isEscaped(data)) data = _extractEscaped(data);
174 assert(!_isMarked(data));
175 result = data;
176 bool hasBeenDuplicated = false;
177 List duplicate() {
178 assert(!hasBeenDuplicated);
179 result = new List();
180 result.length = data.length;
181 if (reference != null) _decoded[reference] = result;
182 hasBeenDuplicated = true;
183 }
184
185 if (reference != null) duplicate();
186 for (int i = 0; i < data.length; i++) {
187 var decoded = decode(data[i]);
188 if (decoded != data[i] && !hasBeenDuplicated) {
189 duplicate();
190 for (int j = 0; j < i; j++) {
191 result[j] = data[j];
192 }
193 }
194 if (hasBeenDuplicated) {
195 result[i] = decoded;
196 }
197 }
198 } else if (data is Set) {
199 bool needsCopy = reference != null;
200 if (!needsCopy) {
201 for (var entry in data) {
202 var decoded = decode(entry);
203 if (decoded != entry) {
204 needsCopy = true;
205 break;
206 }
207 }
208 }
209 result = data;
210 if (needsCopy) {
211 result = new Set();
212 if (reference != null) _decoded[reference] = result;
213 for (var entry in data) {
214 result.add(decode(entry));
215 }
216 }
217 } else if (data is Map) {
218 bool needsCopy = reference != null;
219 if (!needsCopy) {
220 data.forEach((key, value) {
221 var decodedKey = decode(key);
222 var decodedValue = decode(value);
223 if (decodedKey != key) needsCopy = true;
224 if (decodedValue != value) needsCopy = true;
225 });
226 }
227 result = data;
228 if (needsCopy) {
229 result = new Map();
230 if (reference != null) _decoded[reference] = result;
231 data.forEach((key, value) {
232 result[decode(key)] = decode(value);
233 });
234 }
235 } else {
236 result = data;
237 }
238 _decoded[data] = result;
239 return result;
240 }
241
242 _isMarked(data) {
243 if (data is List && !data.isEmpty && data[0] == manglingToken) {
244 assert(data.length > 1);
245 return true;
246 }
247 return false;
248 }
249 _isReference(data) => _isMarked(data) && data[1] == _REFERENCE;
250 _isDeclaration(data) => _isMarked(data) && data[1] == _DECLARATION;
251 _isMangled(data) => _isMarked(data) && data[1] == _MANGLED;
252 _isEscaped(data) => _isMarked(data) && data[1] == _ESCAPED;
253
254 _extractReference(declaration) {
255 assert(_isDeclaration(declaration));
256 return declaration[2];
257 }
258 _extractDeclared(declaration) {
259 assert(_isDeclaration(declaration));
260 return declaration[3];
261 }
262 _extractMangled(wrappedMangled) {
263 assert(_isMangled(wrappedMangled));
264 return wrappedMangled[2];
265 }
266 _extractEscaped(data) {
267 assert(_isEscaped(data));
268 return data[2];
269 }
270 }
OLDNEW
« no previous file with comments | « sdk/lib/isolate/isolate_stream.dart ('k') | sdk/lib/isolate/timer.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698