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

Side by Side Diff: sdk/lib/_internal/compiler/js_lib/isolate_serialization.dart

Issue 1212513002: sdk files reorganization to make dart2js a proper package (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: renamed 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) 2014, 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 _isolate_helper;
6
7 /// Serialize [message].
8 _serializeMessage(message) {
9 return new _Serializer().serialize(message);
10 }
11
12 /// Deserialize [message].
13 _deserializeMessage(message) {
14 return new _Deserializer().deserialize(message);
15 }
16
17 /// Clones the message.
18 ///
19 /// Contrary to a `_deserializeMessage(_serializeMessage(x))` the `_clone`
20 /// function will not try to adjust SendPort values and pass them through.
21 _clone(message) {
22 _Serializer serializer = new _Serializer(serializeSendPorts: false);
23 _Deserializer deserializer = new _Deserializer();
24 return deserializer.deserialize(serializer.serialize(message));
25 }
26
27 class _Serializer {
28 final bool _serializeSendPorts;
29 Map<dynamic, int> serializedObjectIds = new Map<dynamic, int>.identity();
30
31 _Serializer({serializeSendPorts: true})
32 : _serializeSendPorts = serializeSendPorts;
33
34 /// Returns a message that can be transmitted through web-worker channels.
35 serialize(x) {
36 if (isPrimitive(x)) return serializePrimitive(x);
37
38 int serializationId = serializedObjectIds[x];
39 if (serializationId != null) return makeRef(serializationId);
40
41 serializationId = serializedObjectIds.length;
42 serializedObjectIds[x] = serializationId;
43
44 if (x is NativeByteBuffer) return serializeByteBuffer(x);
45 if (x is NativeTypedData) return serializeTypedData(x);
46 if (x is JSIndexable) return serializeJSIndexable(x);
47 if (x is InternalMap) return serializeMap(x);
48
49 if (x is JSObject) return serializeJSObject(x);
50
51 // We should not have any interceptors any more.
52 if (x is Interceptor) unsupported(x);
53
54 if (x is RawReceivePort) {
55 unsupported(x, "RawReceivePorts can't be transmitted:");
56 }
57
58 // SendPorts need their workerIds adjusted (either during serialization or
59 // deserialization).
60 if (x is _NativeJsSendPort) return serializeJsSendPort(x);
61 if (x is _WorkerSendPort) return serializeWorkerSendPort(x);
62
63 if (x is Closure) return serializeClosure(x);
64
65 return serializeDartObject(x);
66 }
67
68 void unsupported(x, [String message]) {
69 if (message == null) message = "Can't transmit:";
70 throw new UnsupportedError("$message $x");
71 }
72
73 makeRef(int serializationId) => ["ref", serializationId];
74
75 bool isPrimitive(x) => x == null || x is String || x is num || x is bool;
76 serializePrimitive(primitive) => primitive;
77
78 serializeByteBuffer(NativeByteBuffer buffer) {
79 return ["buffer", buffer];
80 }
81
82 serializeTypedData(NativeTypedData data) {
83 return ["typed", data];
84 }
85
86 serializeJSIndexable(JSIndexable indexable) {
87 // Strings are JSIndexable but should have been treated earlier.
88 assert(indexable is! String);
89 List serialized = serializeArray(indexable);
90 if (indexable is JSFixedArray) return ["fixed", serialized];
91 if (indexable is JSExtendableArray) return ["extendable", serialized];
92 // MutableArray check must be last, since JSFixedArray and JSExtendableArray
93 // extend JSMutableArray.
94 if (indexable is JSMutableArray) return ["mutable", serialized];
95 // The only JSArrays left are the const Lists (as in `const [1, 2]`).
96 if (indexable is JSArray) return ["const", serialized];
97 unsupported(indexable, "Can't serialize indexable: ");
98 return null;
99 }
100
101 serializeArray(JSArray x) {
102 List serialized = [];
103 serialized.length = x.length;
104 for (int i = 0; i < x.length; i++) {
105 serialized[i] = serialize(x[i]);
106 }
107 return serialized;
108 }
109
110 serializeArrayInPlace(JSArray x) {
111 for (int i = 0; i < x.length; i++) {
112 x[i] = serialize(x[i]);
113 }
114 return x;
115 }
116
117 serializeMap(Map x) {
118 Function serializeTearOff = serialize;
119 return ['map',
120 x.keys.map(serializeTearOff).toList(),
121 x.values.map(serializeTearOff).toList()];
122 }
123
124 serializeJSObject(JSObject x) {
125 // Don't serialize objects if their `constructor` property isn't `Object`
126 // or undefined/null.
127 // A different constructor is taken as a sign that the object has complex
128 // internal state, or that it is a function, and won't be serialized.
129 if (JS('bool', '!!(#.constructor)', x) &&
130 JS('bool', 'x.constructor !== Object')) {
131 unsupported(x, "Only plain JS Objects are supported:");
132 }
133 List keys = JS('JSArray', 'Object.keys(#)', x);
134 List values = [];
135 values.length = keys.length;
136 for (int i = 0; i < keys.length; i++) {
137 values[i] = serialize(JS('', '#[#]', x, keys[i]));
138 }
139 return ['js-object', keys, values];
140 }
141
142 serializeWorkerSendPort(_WorkerSendPort x) {
143 if (_serializeSendPorts) {
144 return ['sendport', x._workerId, x._isolateId, x._receivePortId];
145 }
146 return ['raw sendport', x];
147 }
148
149 serializeJsSendPort(_NativeJsSendPort x) {
150 if (_serializeSendPorts) {
151 int workerId = _globalState.currentManagerId;
152 return ['sendport', workerId, x._isolateId, x._receivePort._id];
153 }
154 return ['raw sendport', x];
155 }
156
157 serializeCapability(CapabilityImpl x) => ['capability', x._id];
158
159 serializeClosure(Closure x) {
160 final name = IsolateNatives._getJSFunctionName(x);
161 if (name == null) {
162 unsupported(x, "Closures can't be transmitted:");
163 }
164 return ['function', name];
165 }
166
167 serializeDartObject(x) {
168 if (!isDartObject(x)) unsupported(x);
169 var classExtractor = JS_EMBEDDED_GLOBAL('', CLASS_ID_EXTRACTOR);
170 var fieldsExtractor = JS_EMBEDDED_GLOBAL('', CLASS_FIELDS_EXTRACTOR);
171 String classId = JS('String', '#(#)', classExtractor, x);
172 List fields = JS('JSArray', '#(#)', fieldsExtractor, x);
173 return ['dart', classId, serializeArrayInPlace(fields)];
174 }
175 }
176
177 class _Deserializer {
178 /// When `true`, encodes sendports specially so that they can be adjusted on
179 /// the receiving end.
180 ///
181 /// When `false`, sendports are cloned like any other object.
182 final bool _adjustSendPorts;
183
184 List<dynamic> deserializedObjects = new List<dynamic>();
185
186 _Deserializer({adjustSendPorts: true}) : _adjustSendPorts = adjustSendPorts;
187
188 /// Returns a message that can be transmitted through web-worker channels.
189 deserialize(x) {
190 if (isPrimitive(x)) return deserializePrimitive(x);
191
192 if (x is! JSArray) throw new ArgumentError("Bad serialized message: $x");
193
194 switch (x.first) {
195 case "ref": return deserializeRef(x);
196 case "buffer": return deserializeByteBuffer(x);
197 case "typed": return deserializeTypedData(x);
198 case "fixed": return deserializeFixed(x);
199 case "extendable": return deserializeExtendable(x);
200 case "mutable": return deserializeMutable(x);
201 case "const": return deserializeConst(x);
202 case "map": return deserializeMap(x);
203 case "sendport": return deserializeSendPort(x);
204 case "raw sendport": return deserializeRawSendPort(x);
205 case "js-object": return deserializeJSObject(x);
206 case "function": return deserializeClosure(x);
207 case "dart": return deserializeDartObject(x);
208 default: throw "couldn't deserialize: $x";
209 }
210 }
211
212 bool isPrimitive(x) => x == null || x is String || x is num || x is bool;
213 deserializePrimitive(x) => x;
214
215 // ['ref', id].
216 deserializeRef(x) {
217 assert(x[0] == 'ref');
218 int serializationId = x[1];
219 return deserializedObjects[serializationId];
220 }
221
222 // ['buffer', <byte buffer>].
223 NativeByteBuffer deserializeByteBuffer(x) {
224 assert(x[0] == 'buffer');
225 NativeByteBuffer result = x[1];
226 deserializedObjects.add(result);
227 return result;
228 }
229
230 // ['typed', <typed array>].
231 NativeTypedData deserializeTypedData(x) {
232 assert(x[0] == 'typed');
233 NativeTypedData result = x[1];
234 deserializedObjects.add(result);
235 return result;
236 }
237
238 // Updates the given array in place with its deserialized content.
239 List deserializeArrayInPlace(JSArray x) {
240 for (int i = 0; i < x.length; i++) {
241 x[i] = deserialize(x[i]);
242 }
243 return x;
244 }
245
246 // ['fixed', <array>].
247 List deserializeFixed(x) {
248 assert(x[0] == 'fixed');
249 List result = x[1];
250 deserializedObjects.add(result);
251 return new JSArray.markFixed(deserializeArrayInPlace(result));
252 }
253
254 // ['extendable', <array>].
255 List deserializeExtendable(x) {
256 assert(x[0] == 'extendable');
257 List result = x[1];
258 deserializedObjects.add(result);
259 return new JSArray.markGrowable(deserializeArrayInPlace(result));
260 }
261
262 // ['mutable', <array>].
263 List deserializeMutable(x) {
264 assert(x[0] == 'mutable');
265 List result = x[1];
266 deserializedObjects.add(result);
267 return deserializeArrayInPlace(result);
268 }
269
270 // ['const', <array>].
271 List deserializeConst(x) {
272 assert(x[0] == 'const');
273 List result = x[1];
274 deserializedObjects.add(result);
275 // TODO(floitsch): need to mark list as non-changeable.
276 return new JSArray.markFixed(deserializeArrayInPlace(result));
277 }
278
279 // ['map', <key-list>, <value-list>].
280 Map deserializeMap(x) {
281 assert(x[0] == 'map');
282 List keys = x[1];
283 List values = x[2];
284 Map result = {};
285 deserializedObjects.add(result);
286 // We need to keep the order of how objects were serialized.
287 // First deserialize all keys, and then only deserialize the values.
288 keys = keys.map(deserialize).toList();
289
290 for (int i = 0; i < keys.length; i++) {
291 result[keys[i]] = deserialize(values[i]);
292 }
293 return result;
294 }
295
296 // ['sendport', <managerId>, <isolateId>, <receivePortId>].
297 SendPort deserializeSendPort(x) {
298 assert(x[0] == 'sendport');
299 int managerId = x[1];
300 int isolateId = x[2];
301 int receivePortId = x[3];
302 SendPort result;
303 // If two isolates are in the same manager, we use NativeJsSendPorts to
304 // deliver messages directly without using postMessage.
305 if (managerId == _globalState.currentManagerId) {
306 var isolate = _globalState.isolates[isolateId];
307 if (isolate == null) return null; // Isolate has been closed.
308 var receivePort = isolate.lookup(receivePortId);
309 if (receivePort == null) return null; // Port has been closed.
310 result = new _NativeJsSendPort(receivePort, isolateId);
311 } else {
312 result = new _WorkerSendPort(managerId, isolateId, receivePortId);
313 }
314 deserializedObjects.add(result);
315 return result;
316 }
317
318 // ['raw sendport', <sendport>].
319 SendPort deserializeRawSendPort(x) {
320 assert(x[0] == 'raw sendport');
321 SendPort result = x[1];
322 deserializedObjects.add(result);
323 return result;
324 }
325
326 // ['js-object', <key-list>, <value-list>].
327 deserializeJSObject(x) {
328 assert(x[0] == 'js-object');
329 List keys = x[1];
330 List values = x[2];
331 var o = JS('', '{}');
332 deserializedObjects.add(o);
333 for (int i = 0; i < keys.length; i++) {
334 JS('', '#[#]=#', o, keys[i], deserialize(values[i]));
335 }
336 return o;
337 }
338
339 // ['function', <name>].
340 Function deserializeClosure(x) {
341 assert(x[0] == 'function');
342 String name = x[1];
343 Function result = IsolateNatives._getJSFunctionFromName(name);
344 deserializedObjects.add(result);
345 return result;
346 }
347
348 // ['dart', <class-id>, <field-list>].
349 deserializeDartObject(x) {
350 assert(x[0] == 'dart');
351 String classId = x[1];
352 List fields = x[2];
353 var instanceFromClassId = JS_EMBEDDED_GLOBAL('', INSTANCE_FROM_CLASS_ID);
354 var initializeObject = JS_EMBEDDED_GLOBAL('', INITIALIZE_EMPTY_INSTANCE);
355
356 var emptyInstance = JS('', '#(#)', instanceFromClassId, classId);
357 deserializedObjects.add(emptyInstance);
358 deserializeArrayInPlace(fields);
359 return JS('', '#(#, #, #)',
360 initializeObject, classId, emptyInstance, fields);
361 }
362 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698