OLD | NEW |
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 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 | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 library dart2js.js_emitter.full_emitter; | 5 library dart2js.js_emitter.full_emitter; |
6 | 6 |
7 import 'dart:convert'; | 7 import 'dart:convert'; |
8 import 'dart:collection' show HashMap; | 8 import 'dart:collection' show HashMap; |
9 | 9 |
10 import 'package:js_runtime/shared/embedded_names.dart' as embeddedNames; | 10 import 'package:js_runtime/shared/embedded_names.dart' as embeddedNames; |
11 import 'package:js_runtime/shared/embedded_names.dart' show | 11 import 'package:js_runtime/shared/embedded_names.dart' |
12 JsBuiltin, | 12 show JsBuiltin, JsGetName; |
13 JsGetName; | |
14 | 13 |
15 import '../headers.dart'; | 14 import '../headers.dart'; |
16 import '../js_emitter.dart' hide Emitter; | 15 import '../js_emitter.dart' hide Emitter; |
17 import '../js_emitter.dart' as js_emitter show Emitter; | 16 import '../js_emitter.dart' as js_emitter show Emitter; |
18 import '../model.dart'; | 17 import '../model.dart'; |
19 import '../program_builder/program_builder.dart'; | 18 import '../program_builder/program_builder.dart'; |
20 import '../constant_ordering.dart' show deepCompareConstants; | 19 import '../constant_ordering.dart' show deepCompareConstants; |
21 | 20 |
22 import '../../common.dart'; | 21 import '../../common.dart'; |
23 import '../../common/names.dart' show | 22 import '../../common/names.dart' show Names; |
24 Names; | 23 import '../../compiler.dart' show Compiler; |
25 import '../../compiler.dart' show | |
26 Compiler; | |
27 import '../../constants/values.dart'; | 24 import '../../constants/values.dart'; |
28 import '../../core_types.dart' show | 25 import '../../core_types.dart' show CoreClasses; |
29 CoreClasses; | 26 import '../../dart_types.dart' show DartType; |
30 import '../../dart_types.dart' show | |
31 DartType; | |
32 import '../../deferred_load.dart' show OutputUnit; | 27 import '../../deferred_load.dart' show OutputUnit; |
33 import '../../elements/elements.dart' show | 28 import '../../elements/elements.dart' |
34 ClassElement, | 29 show |
35 ConstructorBodyElement, | 30 ClassElement, |
36 Element, | 31 ConstructorBodyElement, |
37 Elements, | 32 Element, |
38 ElementKind, | 33 Elements, |
39 FieldElement, | 34 ElementKind, |
40 FunctionElement, | 35 FieldElement, |
41 FunctionSignature, | 36 FunctionElement, |
42 LibraryElement, | 37 FunctionSignature, |
43 MetadataAnnotation, | 38 LibraryElement, |
44 MethodElement, | 39 MetadataAnnotation, |
45 MemberElement, | 40 MethodElement, |
46 Name, | 41 MemberElement, |
47 ParameterElement, | 42 Name, |
48 TypedefElement, | 43 ParameterElement, |
49 TypeVariableElement, | 44 TypedefElement, |
50 VariableElement; | 45 TypeVariableElement, |
| 46 VariableElement; |
51 import '../../hash/sha1.dart' show Hasher; | 47 import '../../hash/sha1.dart' show Hasher; |
52 import '../../io/code_output.dart'; | 48 import '../../io/code_output.dart'; |
53 import '../../io/line_column_provider.dart' show | 49 import '../../io/line_column_provider.dart' |
54 LineColumnCollector, | 50 show LineColumnCollector, LineColumnProvider; |
55 LineColumnProvider; | 51 import '../../io/source_map_builder.dart' show SourceMapBuilder; |
56 import '../../io/source_map_builder.dart' show | |
57 SourceMapBuilder; | |
58 import '../../js/js.dart' as jsAst; | 52 import '../../js/js.dart' as jsAst; |
59 import '../../js/js.dart' show js; | 53 import '../../js/js.dart' show js; |
60 import '../../js_backend/backend_helpers.dart' show | 54 import '../../js_backend/backend_helpers.dart' show BackendHelpers; |
61 BackendHelpers; | 55 import '../../js_backend/js_backend.dart' |
62 import '../../js_backend/js_backend.dart' show | 56 show |
63 CheckedModeHelper, | 57 CheckedModeHelper, |
64 CompoundName, | 58 CompoundName, |
65 ConstantEmitter, | 59 ConstantEmitter, |
66 CustomElementsAnalysis, | 60 CustomElementsAnalysis, |
67 GetterName, | 61 GetterName, |
68 JavaScriptBackend, | 62 JavaScriptBackend, |
69 JavaScriptConstantCompiler, | 63 JavaScriptConstantCompiler, |
70 Namer, | 64 Namer, |
71 RuntimeTypes, | 65 RuntimeTypes, |
72 SetterName, | 66 SetterName, |
73 Substitution, | 67 Substitution, |
74 TypeCheck, | 68 TypeCheck, |
75 TypeChecks, | 69 TypeChecks, |
76 TypeVariableHandler; | 70 TypeVariableHandler; |
77 import '../../universe/call_structure.dart' show | 71 import '../../universe/call_structure.dart' show CallStructure; |
78 CallStructure; | 72 import '../../universe/selector.dart' show Selector; |
79 import '../../universe/selector.dart' show | 73 import '../../util/characters.dart' show $$, $A, $HASH, $PERIOD, $Z, $a, $z; |
80 Selector; | 74 import '../../util/uri_extras.dart' show relativize; |
81 import '../../util/characters.dart' show | 75 import '../../util/util.dart' show equalElements; |
82 $$, | |
83 $A, | |
84 $HASH, | |
85 $PERIOD, | |
86 $Z, | |
87 $a, | |
88 $z; | |
89 import '../../util/uri_extras.dart' show | |
90 relativize; | |
91 import '../../util/util.dart' show | |
92 equalElements; | |
93 | 76 |
94 part 'class_builder.dart'; | 77 part 'class_builder.dart'; |
95 part 'class_emitter.dart'; | 78 part 'class_emitter.dart'; |
96 part 'code_emitter_helper.dart'; | 79 part 'code_emitter_helper.dart'; |
97 part 'container_builder.dart'; | 80 part 'container_builder.dart'; |
98 part 'declarations.dart'; | 81 part 'declarations.dart'; |
99 part 'deferred_output_unit_hash.dart'; | 82 part 'deferred_output_unit_hash.dart'; |
100 part 'interceptor_emitter.dart'; | 83 part 'interceptor_emitter.dart'; |
101 part 'nsm_emitter.dart'; | 84 part 'nsm_emitter.dart'; |
102 part 'setup_program_builder.dart'; | 85 part 'setup_program_builder.dart'; |
103 | 86 |
104 | |
105 class Emitter implements js_emitter.Emitter { | 87 class Emitter implements js_emitter.Emitter { |
106 final Compiler compiler; | 88 final Compiler compiler; |
107 final CodeEmitterTask task; | 89 final CodeEmitterTask task; |
108 | 90 |
109 // The following fields will be set to copies of the program-builder's | 91 // The following fields will be set to copies of the program-builder's |
110 // collector. | 92 // collector. |
111 Map<OutputUnit, List<VariableElement>> outputStaticNonFinalFieldLists; | 93 Map<OutputUnit, List<VariableElement>> outputStaticNonFinalFieldLists; |
112 Map<OutputUnit, Set<LibraryElement>> outputLibraryLists; | 94 Map<OutputUnit, Set<LibraryElement>> outputLibraryLists; |
113 List<TypedefElement> typedefsNeededForReflection; | 95 List<TypedefElement> typedefsNeededForReflection; |
114 | 96 |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
195 containerBuilder.emitter = this; | 177 containerBuilder.emitter = this; |
196 classEmitter.emitter = this; | 178 classEmitter.emitter = this; |
197 nsmEmitter.emitter = this; | 179 nsmEmitter.emitter = this; |
198 interceptorEmitter.emitter = this; | 180 interceptorEmitter.emitter = this; |
199 } | 181 } |
200 | 182 |
201 DiagnosticReporter get reporter => compiler.reporter; | 183 DiagnosticReporter get reporter => compiler.reporter; |
202 | 184 |
203 List<jsAst.Node> cspPrecompiledFunctionFor(OutputUnit outputUnit) { | 185 List<jsAst.Node> cspPrecompiledFunctionFor(OutputUnit outputUnit) { |
204 return _cspPrecompiledFunctions.putIfAbsent( | 186 return _cspPrecompiledFunctions.putIfAbsent( |
205 outputUnit, | 187 outputUnit, () => new List<jsAst.Node>()); |
206 () => new List<jsAst.Node>()); | |
207 } | 188 } |
208 | 189 |
209 List<jsAst.Expression> cspPrecompiledConstructorNamesFor( | 190 List<jsAst.Expression> cspPrecompiledConstructorNamesFor( |
210 OutputUnit outputUnit) { | 191 OutputUnit outputUnit) { |
211 return _cspPrecompiledConstructorNames.putIfAbsent( | 192 return _cspPrecompiledConstructorNames.putIfAbsent( |
212 outputUnit, | 193 outputUnit, () => new List<jsAst.Expression>()); |
213 () => new List<jsAst.Expression>()); | |
214 } | 194 } |
215 | 195 |
216 /// Erases the precompiled information for csp mode for all output units. | 196 /// Erases the precompiled information for csp mode for all output units. |
217 /// Used by the incremental compiler. | 197 /// Used by the incremental compiler. |
218 void clearCspPrecompiledNodes() { | 198 void clearCspPrecompiledNodes() { |
219 _cspPrecompiledFunctions.clear(); | 199 _cspPrecompiledFunctions.clear(); |
220 _cspPrecompiledConstructorNames.clear(); | 200 _cspPrecompiledConstructorNames.clear(); |
221 } | 201 } |
222 | 202 |
223 @override | 203 @override |
224 String get patchVersion => "full"; | 204 String get patchVersion => "full"; |
225 | 205 |
226 @override | 206 @override |
227 bool isConstantInlinedOrAlreadyEmitted(ConstantValue constant) { | 207 bool isConstantInlinedOrAlreadyEmitted(ConstantValue constant) { |
228 if (constant.isFunction) return true; // Already emitted. | 208 if (constant.isFunction) return true; // Already emitted. |
229 if (constant.isPrimitive) return true; // Inlined. | 209 if (constant.isPrimitive) return true; // Inlined. |
230 if (constant.isDummy) return true; // Inlined. | 210 if (constant.isDummy) return true; // Inlined. |
231 // The name is null when the constant is already a JS constant. | 211 // The name is null when the constant is already a JS constant. |
232 // TODO(floitsch): every constant should be registered, so that we can | 212 // TODO(floitsch): every constant should be registered, so that we can |
233 // share the ones that take up too much space (like some strings). | 213 // share the ones that take up too much space (like some strings). |
234 if (namer.constantName(constant) == null) return true; | 214 if (namer.constantName(constant) == null) return true; |
235 return false; | 215 return false; |
236 } | 216 } |
237 | 217 |
238 @override | 218 @override |
239 int compareConstants(ConstantValue a, ConstantValue b) { | 219 int compareConstants(ConstantValue a, ConstantValue b) { |
240 // Inlined constants don't affect the order and sometimes don't even have | 220 // Inlined constants don't affect the order and sometimes don't even have |
(...skipping 22 matching lines...) Expand all Loading... |
263 if (value.isFunction) { | 243 if (value.isFunction) { |
264 FunctionConstantValue functionConstant = value; | 244 FunctionConstantValue functionConstant = value; |
265 return isolateStaticClosureAccess(functionConstant.element); | 245 return isolateStaticClosureAccess(functionConstant.element); |
266 } | 246 } |
267 | 247 |
268 // We are only interested in the "isInlined" part, but it does not hurt to | 248 // We are only interested in the "isInlined" part, but it does not hurt to |
269 // test for the other predicates. | 249 // test for the other predicates. |
270 if (isConstantInlinedOrAlreadyEmitted(value)) { | 250 if (isConstantInlinedOrAlreadyEmitted(value)) { |
271 return constantEmitter.generate(value); | 251 return constantEmitter.generate(value); |
272 } | 252 } |
273 return js('#.#', [namer.globalObjectForConstant(value), | 253 return js('#.#', |
274 namer.constantName(value)]); | 254 [namer.globalObjectForConstant(value), namer.constantName(value)]); |
275 } | 255 } |
276 | 256 |
277 jsAst.Expression constantInitializerExpression(ConstantValue value) { | 257 jsAst.Expression constantInitializerExpression(ConstantValue value) { |
278 return constantEmitter.generate(value); | 258 return constantEmitter.generate(value); |
279 } | 259 } |
280 | 260 |
281 String get name => 'CodeEmitter'; | 261 String get name => 'CodeEmitter'; |
282 | 262 |
283 String get finishIsolateConstructorName | 263 String get finishIsolateConstructorName => |
284 => '${namer.isolateName}.\$finishIsolateConstructor'; | 264 '${namer.isolateName}.\$finishIsolateConstructor'; |
285 String get isolatePropertiesName | 265 String get isolatePropertiesName => |
286 => '${namer.isolateName}.${namer.isolatePropertiesName}'; | 266 '${namer.isolateName}.${namer.isolatePropertiesName}'; |
287 String get lazyInitializerProperty | 267 String get lazyInitializerProperty => r'$lazy'; |
288 => r'$lazy'; | 268 String get lazyInitializerName => |
289 String get lazyInitializerName | 269 '${namer.isolateName}.${lazyInitializerProperty}'; |
290 => '${namer.isolateName}.${lazyInitializerProperty}'; | |
291 String get initName => 'init'; | 270 String get initName => 'init'; |
292 | 271 |
293 jsAst.Name get makeConstListProperty | 272 jsAst.Name get makeConstListProperty => |
294 => namer.internalGlobal('makeConstantList'); | 273 namer.internalGlobal('makeConstantList'); |
295 | 274 |
296 /// The name of the property that contains all field names. | 275 /// The name of the property that contains all field names. |
297 /// | 276 /// |
298 /// This property is added to constructors when isolate support is enabled. | 277 /// This property is added to constructors when isolate support is enabled. |
299 static const String FIELD_NAMES_PROPERTY_NAME = r"$__fields__"; | 278 static const String FIELD_NAMES_PROPERTY_NAME = r"$__fields__"; |
300 | 279 |
301 /// For deferred loading we communicate the initializers via this global var. | 280 /// For deferred loading we communicate the initializers via this global var. |
302 final String deferredInitializers = r"$dart_deferred_initializers$"; | 281 final String deferredInitializers = r"$dart_deferred_initializers$"; |
303 | 282 |
304 /// Contains the global state that is needed to initialize and load a | 283 /// Contains the global state that is needed to initialize and load a |
305 /// deferred library. | 284 /// deferred library. |
306 String get globalsHolder => r"$globals$"; | 285 String get globalsHolder => r"$globals$"; |
307 | 286 |
308 @override | 287 @override |
309 bool get supportsReflection => true; | 288 bool get supportsReflection => true; |
310 | 289 |
311 @override | 290 @override |
312 jsAst.Expression generateEmbeddedGlobalAccess(String global) { | 291 jsAst.Expression generateEmbeddedGlobalAccess(String global) { |
313 return js(generateEmbeddedGlobalAccessString(global)); | 292 return js(generateEmbeddedGlobalAccessString(global)); |
314 } | 293 } |
315 | 294 |
316 String generateEmbeddedGlobalAccessString(String global) { | 295 String generateEmbeddedGlobalAccessString(String global) { |
317 // TODO(floitsch): don't use 'init' as global embedder storage. | 296 // TODO(floitsch): don't use 'init' as global embedder storage. |
318 return '$initName.$global'; | 297 return '$initName.$global'; |
319 } | 298 } |
320 | 299 |
321 jsAst.PropertyAccess globalPropertyAccess(Element element) { | 300 jsAst.PropertyAccess globalPropertyAccess(Element element) { |
322 jsAst.Name name = namer.globalPropertyName(element); | 301 jsAst.Name name = namer.globalPropertyName(element); |
323 jsAst.PropertyAccess pa = new jsAst.PropertyAccess( | 302 jsAst.PropertyAccess pa = new jsAst.PropertyAccess( |
324 new jsAst.VariableUse(namer.globalObjectFor(element)), | 303 new jsAst.VariableUse(namer.globalObjectFor(element)), name); |
325 name); | |
326 return pa; | 304 return pa; |
327 } | 305 } |
328 | 306 |
329 @override | 307 @override |
330 jsAst.Expression isolateLazyInitializerAccess(FieldElement element) { | 308 jsAst.Expression isolateLazyInitializerAccess(FieldElement element) { |
331 return jsAst.js('#.#', [namer.globalObjectFor(element), | 309 return jsAst.js('#.#', |
332 namer.lazyInitializerName(element)]); | 310 [namer.globalObjectFor(element), namer.lazyInitializerName(element)]); |
333 } | 311 } |
334 | 312 |
335 @override | 313 @override |
336 jsAst.Expression isolateStaticClosureAccess(FunctionElement element) { | 314 jsAst.Expression isolateStaticClosureAccess(FunctionElement element) { |
337 return jsAst.js('#.#()', | 315 return jsAst.js('#.#()', |
338 [namer.globalObjectFor(element), namer.staticClosureName(element)]); | 316 [namer.globalObjectFor(element), namer.staticClosureName(element)]); |
339 } | 317 } |
340 | 318 |
341 @override | 319 @override |
342 jsAst.PropertyAccess staticFieldAccess(FieldElement element) { | 320 jsAst.PropertyAccess staticFieldAccess(FieldElement element) { |
343 return globalPropertyAccess(element); | 321 return globalPropertyAccess(element); |
344 } | 322 } |
345 | 323 |
346 @override | 324 @override |
347 jsAst.PropertyAccess staticFunctionAccess(FunctionElement element) { | 325 jsAst.PropertyAccess staticFunctionAccess(FunctionElement element) { |
348 return globalPropertyAccess(element); | 326 return globalPropertyAccess(element); |
349 } | 327 } |
350 | 328 |
351 @override | 329 @override |
352 jsAst.PropertyAccess constructorAccess(ClassElement element) { | 330 jsAst.PropertyAccess constructorAccess(ClassElement element) { |
353 return globalPropertyAccess(element); | 331 return globalPropertyAccess(element); |
354 } | 332 } |
355 | 333 |
356 @override | 334 @override |
357 jsAst.PropertyAccess prototypeAccess(ClassElement element, | 335 jsAst.PropertyAccess prototypeAccess( |
358 bool hasBeenInstantiated) { | 336 ClassElement element, bool hasBeenInstantiated) { |
359 return jsAst.js('#.prototype', constructorAccess(element)); | 337 return jsAst.js('#.prototype', constructorAccess(element)); |
360 } | 338 } |
361 | 339 |
362 @override | 340 @override |
363 jsAst.PropertyAccess interceptorClassAccess(ClassElement element) { | 341 jsAst.PropertyAccess interceptorClassAccess(ClassElement element) { |
364 return globalPropertyAccess(element); | 342 return globalPropertyAccess(element); |
365 } | 343 } |
366 | 344 |
367 @override | 345 @override |
368 jsAst.PropertyAccess typeAccess(Element element) { | 346 jsAst.PropertyAccess typeAccess(Element element) { |
369 return globalPropertyAccess(element); | 347 return globalPropertyAccess(element); |
370 } | 348 } |
371 | 349 |
372 @override | 350 @override |
373 jsAst.Template templateForBuiltin(JsBuiltin builtin) { | 351 jsAst.Template templateForBuiltin(JsBuiltin builtin) { |
374 switch (builtin) { | 352 switch (builtin) { |
375 case JsBuiltin.dartObjectConstructor: | 353 case JsBuiltin.dartObjectConstructor: |
376 return jsAst.js.expressionTemplateYielding( | 354 return jsAst.js |
377 typeAccess(coreClasses.objectClass)); | 355 .expressionTemplateYielding(typeAccess(coreClasses.objectClass)); |
378 | 356 |
379 case JsBuiltin.isCheckPropertyToJsConstructorName: | 357 case JsBuiltin.isCheckPropertyToJsConstructorName: |
380 int isPrefixLength = namer.operatorIsPrefix.length; | 358 int isPrefixLength = namer.operatorIsPrefix.length; |
381 return jsAst.js.expressionTemplateFor('#.substring($isPrefixLength)'); | 359 return jsAst.js.expressionTemplateFor('#.substring($isPrefixLength)'); |
382 | 360 |
383 case JsBuiltin.isFunctionType: | 361 case JsBuiltin.isFunctionType: |
384 return backend.rtiEncoder.templateForIsFunctionType; | 362 return backend.rtiEncoder.templateForIsFunctionType; |
385 | 363 |
386 case JsBuiltin.rawRtiToJsConstructorName: | 364 case JsBuiltin.rawRtiToJsConstructorName: |
387 return jsAst.js.expressionTemplateFor("#.$typeNameProperty"); | 365 return jsAst.js.expressionTemplateFor("#.$typeNameProperty"); |
388 | 366 |
389 case JsBuiltin.rawRuntimeType: | 367 case JsBuiltin.rawRuntimeType: |
390 return jsAst.js.expressionTemplateFor("#.constructor"); | 368 return jsAst.js.expressionTemplateFor("#.constructor"); |
391 | 369 |
392 case JsBuiltin.createFunctionTypeRti: | 370 case JsBuiltin.createFunctionTypeRti: |
393 return backend.rtiEncoder.templateForCreateFunctionType; | 371 return backend.rtiEncoder.templateForCreateFunctionType; |
394 | 372 |
395 case JsBuiltin.isSubtype: | 373 case JsBuiltin.isSubtype: |
396 // TODO(floitsch): move this closer to where is-check properties are | 374 // TODO(floitsch): move this closer to where is-check properties are |
397 // built. | 375 // built. |
398 String isPrefix = namer.operatorIsPrefix; | 376 String isPrefix = namer.operatorIsPrefix; |
399 return jsAst.js.expressionTemplateFor( | 377 return jsAst.js |
400 "('$isPrefix' + #) in #.prototype"); | 378 .expressionTemplateFor("('$isPrefix' + #) in #.prototype"); |
401 | 379 |
402 case JsBuiltin.isGivenTypeRti: | 380 case JsBuiltin.isGivenTypeRti: |
403 return jsAst.js.expressionTemplateFor('#.$typeNameProperty === #'); | 381 return jsAst.js.expressionTemplateFor('#.$typeNameProperty === #'); |
404 | 382 |
405 case JsBuiltin.getMetadata: | 383 case JsBuiltin.getMetadata: |
406 String metadataAccess = | 384 String metadataAccess = |
407 generateEmbeddedGlobalAccessString(embeddedNames.METADATA); | 385 generateEmbeddedGlobalAccessString(embeddedNames.METADATA); |
408 return jsAst.js.expressionTemplateFor("$metadataAccess[#]"); | 386 return jsAst.js.expressionTemplateFor("$metadataAccess[#]"); |
409 | 387 |
410 case JsBuiltin.getType: | 388 case JsBuiltin.getType: |
411 String typesAccess = | 389 String typesAccess = |
412 generateEmbeddedGlobalAccessString(embeddedNames.TYPES); | 390 generateEmbeddedGlobalAccessString(embeddedNames.TYPES); |
413 return jsAst.js.expressionTemplateFor("$typesAccess[#]"); | 391 return jsAst.js.expressionTemplateFor("$typesAccess[#]"); |
414 | 392 |
415 case JsBuiltin.createDartClosureFromNameOfStaticFunction: | 393 case JsBuiltin.createDartClosureFromNameOfStaticFunction: |
416 // The global-functions map contains a map from name to tear-off | 394 // The global-functions map contains a map from name to tear-off |
417 // getters. | 395 // getters. |
418 String functionGettersMap = | 396 String functionGettersMap = |
419 generateEmbeddedGlobalAccessString(embeddedNames.GLOBAL_FUNCTIONS); | 397 generateEmbeddedGlobalAccessString(embeddedNames.GLOBAL_FUNCTIONS); |
420 return jsAst.js.expressionTemplateFor("$functionGettersMap[#]()"); | 398 return jsAst.js.expressionTemplateFor("$functionGettersMap[#]()"); |
421 | 399 |
422 default: | 400 default: |
423 reporter.internalError(NO_LOCATION_SPANNABLE, | 401 reporter.internalError( |
424 "Unhandled Builtin: $builtin"); | 402 NO_LOCATION_SPANNABLE, "Unhandled Builtin: $builtin"); |
425 return null; | 403 return null; |
426 } | 404 } |
427 } | 405 } |
428 | 406 |
429 List<jsAst.Statement> buildTrivialNsmHandlers(){ | 407 List<jsAst.Statement> buildTrivialNsmHandlers() { |
430 return nsmEmitter.buildTrivialNsmHandlers(); | 408 return nsmEmitter.buildTrivialNsmHandlers(); |
431 } | 409 } |
432 | 410 |
433 jsAst.Statement buildNativeInfoHandler( | 411 jsAst.Statement buildNativeInfoHandler( |
434 jsAst.Expression infoAccess, | 412 jsAst.Expression infoAccess, |
435 jsAst.Expression constructorAccess, | 413 jsAst.Expression constructorAccess, |
436 jsAst.Expression subclassReadGenerator(jsAst.Expression subclass), | 414 jsAst.Expression subclassReadGenerator(jsAst.Expression subclass), |
437 jsAst.Expression interceptorsByTagAccess, | 415 jsAst.Expression interceptorsByTagAccess, |
438 jsAst.Expression leafTagsAccess) { | 416 jsAst.Expression leafTagsAccess) { |
439 return NativeGenerator.buildNativeInfoHandler(infoAccess, constructorAccess, | 417 return NativeGenerator.buildNativeInfoHandler(infoAccess, constructorAccess, |
440 subclassReadGenerator, | 418 subclassReadGenerator, interceptorsByTagAccess, leafTagsAccess); |
441 interceptorsByTagAccess, | |
442 leafTagsAccess); | |
443 } | 419 } |
444 | 420 |
445 jsAst.ObjectInitializer generateInterceptedNamesSet() { | 421 jsAst.ObjectInitializer generateInterceptedNamesSet() { |
446 return interceptorEmitter.generateInterceptedNamesSet(); | 422 return interceptorEmitter.generateInterceptedNamesSet(); |
447 } | 423 } |
448 | 424 |
449 /// In minified mode we want to keep the name for the most common core types. | 425 /// In minified mode we want to keep the name for the most common core types. |
450 bool _isNativeTypeNeedingReflectionName(Element element) { | 426 bool _isNativeTypeNeedingReflectionName(Element element) { |
451 if (!element.isClass) return false; | 427 if (!element.isClass) return false; |
452 return (element == coreClasses.intClass || | 428 return (element == coreClasses.intClass || |
453 element == coreClasses.doubleClass || | 429 element == coreClasses.doubleClass || |
454 element == coreClasses.numClass || | 430 element == coreClasses.numClass || |
455 element == coreClasses.stringClass || | 431 element == coreClasses.stringClass || |
456 element == coreClasses.boolClass || | 432 element == coreClasses.boolClass || |
457 element == coreClasses.nullClass || | 433 element == coreClasses.nullClass || |
458 element == coreClasses.listClass); | 434 element == coreClasses.listClass); |
459 } | 435 } |
460 | 436 |
461 /// Returns the "reflection name" of an [Element] or [Selector]. | 437 /// Returns the "reflection name" of an [Element] or [Selector]. |
462 /// The reflection name of a getter 'foo' is 'foo'. | 438 /// The reflection name of a getter 'foo' is 'foo'. |
463 /// The reflection name of a setter 'foo' is 'foo='. | 439 /// The reflection name of a setter 'foo' is 'foo='. |
464 /// The reflection name of a method 'foo' is 'foo:N:M:O', where N is the | 440 /// The reflection name of a method 'foo' is 'foo:N:M:O', where N is the |
465 /// number of required arguments, M is the number of optional arguments, and | 441 /// number of required arguments, M is the number of optional arguments, and |
466 /// O is the named arguments. | 442 /// O is the named arguments. |
467 /// The reflection name of a constructor is similar to a regular method but | 443 /// The reflection name of a constructor is similar to a regular method but |
468 /// starts with 'new '. | 444 /// starts with 'new '. |
469 /// The reflection name of class 'C' is 'C'. | 445 /// The reflection name of class 'C' is 'C'. |
470 /// An anonymous mixin application has no reflection name. | 446 /// An anonymous mixin application has no reflection name. |
471 /// This is used by js_mirrors.dart. | 447 /// This is used by js_mirrors.dart. |
472 String getReflectionName(elementOrSelector, jsAst.Name mangledName) { | 448 String getReflectionName(elementOrSelector, jsAst.Name mangledName) { |
473 String name = elementOrSelector.name; | 449 String name = elementOrSelector.name; |
474 if (backend.shouldRetainName(name) || | 450 if (backend.shouldRetainName(name) || |
475 elementOrSelector is Element && | 451 elementOrSelector is Element && |
476 // Make sure to retain names of unnamed constructors, and | 452 // Make sure to retain names of unnamed constructors, and |
477 // for common native types. | 453 // for common native types. |
478 ((name == '' && | 454 ((name == '' && |
479 backend.isAccessibleByReflection(elementOrSelector)) || | 455 backend.isAccessibleByReflection(elementOrSelector)) || |
480 _isNativeTypeNeedingReflectionName(elementOrSelector))) { | 456 _isNativeTypeNeedingReflectionName(elementOrSelector))) { |
481 | |
482 // TODO(ahe): Enable the next line when I can tell the difference between | 457 // TODO(ahe): Enable the next line when I can tell the difference between |
483 // an instance method and a global. They may have the same mangled name. | 458 // an instance method and a global. They may have the same mangled name. |
484 // if (recordedMangledNames.contains(mangledName)) return null; | 459 // if (recordedMangledNames.contains(mangledName)) return null; |
485 recordedMangledNames.add(mangledName); | 460 recordedMangledNames.add(mangledName); |
486 return getReflectionNameInternal(elementOrSelector, mangledName); | 461 return getReflectionNameInternal(elementOrSelector, mangledName); |
487 } | 462 } |
488 return null; | 463 return null; |
489 } | 464 } |
490 | 465 |
491 String getReflectionNameInternal(elementOrSelector, | 466 String getReflectionNameInternal(elementOrSelector, jsAst.Name mangledName) { |
492 jsAst.Name mangledName) { | |
493 String name = namer.privateName(elementOrSelector.memberName); | 467 String name = namer.privateName(elementOrSelector.memberName); |
494 if (elementOrSelector.isGetter) return name; | 468 if (elementOrSelector.isGetter) return name; |
495 if (elementOrSelector.isSetter) { | 469 if (elementOrSelector.isSetter) { |
496 if (mangledName is! SetterName) return '$name='; | 470 if (mangledName is! SetterName) return '$name='; |
497 SetterName setterName = mangledName; | 471 SetterName setterName = mangledName; |
498 jsAst.Name base = setterName.base; | 472 jsAst.Name base = setterName.base; |
499 jsAst.Name getter = namer.deriveGetterName(base); | 473 jsAst.Name getter = namer.deriveGetterName(base); |
500 mangledFieldNames.putIfAbsent(getter, () => name); | 474 mangledFieldNames.putIfAbsent(getter, () => name); |
501 assert(mangledFieldNames[getter] == name); | 475 assert(mangledFieldNames[getter] == name); |
502 recordedMangledNames.add(getter); | 476 recordedMangledNames.add(getter); |
503 // TODO(karlklose,ahe): we do not actually need to store information | 477 // TODO(karlklose,ahe): we do not actually need to store information |
504 // about the name of this setter in the output, but it is needed for | 478 // about the name of this setter in the output, but it is needed for |
505 // marking the function as invokable by reflection. | 479 // marking the function as invokable by reflection. |
506 return '$name='; | 480 return '$name='; |
507 } | 481 } |
508 if (elementOrSelector is Element && elementOrSelector.isClosure) { | 482 if (elementOrSelector is Element && elementOrSelector.isClosure) { |
509 // Closures are synthesized and their name might conflict with existing | 483 // Closures are synthesized and their name might conflict with existing |
510 // globals. Assign an illegal name, and make sure they don't clash | 484 // globals. Assign an illegal name, and make sure they don't clash |
511 // with each other. | 485 // with each other. |
512 return " $name"; | 486 return " $name"; |
513 } | 487 } |
514 if (elementOrSelector is Selector | 488 if (elementOrSelector is Selector || |
515 || elementOrSelector.isFunction | 489 elementOrSelector.isFunction || |
516 || elementOrSelector.isConstructor) { | 490 elementOrSelector.isConstructor) { |
517 int positionalParameterCount; | 491 int positionalParameterCount; |
518 String namedArguments = ''; | 492 String namedArguments = ''; |
519 bool isConstructor = false; | 493 bool isConstructor = false; |
520 if (elementOrSelector is Selector) { | 494 if (elementOrSelector is Selector) { |
521 CallStructure callStructure = elementOrSelector.callStructure; | 495 CallStructure callStructure = elementOrSelector.callStructure; |
522 positionalParameterCount = callStructure.positionalArgumentCount; | 496 positionalParameterCount = callStructure.positionalArgumentCount; |
523 namedArguments = namedParametersAsReflectionNames(callStructure); | 497 namedArguments = namedParametersAsReflectionNames(callStructure); |
524 } else { | 498 } else { |
525 FunctionElement function = elementOrSelector; | 499 FunctionElement function = elementOrSelector; |
526 if (function.isConstructor) { | 500 if (function.isConstructor) { |
(...skipping 25 matching lines...) Expand all Loading... |
552 Element element = elementOrSelector; | 526 Element element = elementOrSelector; |
553 if (element.isGenerativeConstructorBody) { | 527 if (element.isGenerativeConstructorBody) { |
554 return null; | 528 return null; |
555 } else if (element.isClass) { | 529 } else if (element.isClass) { |
556 ClassElement cls = element; | 530 ClassElement cls = element; |
557 if (cls.isUnnamedMixinApplication) return null; | 531 if (cls.isUnnamedMixinApplication) return null; |
558 return cls.name; | 532 return cls.name; |
559 } else if (element.isTypedef) { | 533 } else if (element.isTypedef) { |
560 return element.name; | 534 return element.name; |
561 } | 535 } |
562 throw reporter.internalError(element, | 536 throw reporter.internalError( |
563 'Do not know how to reflect on this $element.'); | 537 element, 'Do not know how to reflect on this $element.'); |
564 } | 538 } |
565 | 539 |
566 String namedParametersAsReflectionNames(CallStructure structure) { | 540 String namedParametersAsReflectionNames(CallStructure structure) { |
567 if (structure.isUnnamed) return ''; | 541 if (structure.isUnnamed) return ''; |
568 String names = structure.getOrderedNamedArguments().join(':'); | 542 String names = structure.getOrderedNamedArguments().join(':'); |
569 return ':$names'; | 543 return ':$names'; |
570 } | 544 } |
571 | 545 |
572 jsAst.Statement buildCspPrecompiledFunctionFor( | 546 jsAst.Statement buildCspPrecompiledFunctionFor(OutputUnit outputUnit) { |
573 OutputUnit outputUnit) { | |
574 if (compiler.options.useContentSecurityPolicy) { | 547 if (compiler.options.useContentSecurityPolicy) { |
575 // TODO(ahe): Compute a hash code. | 548 // TODO(ahe): Compute a hash code. |
576 // TODO(sigurdm): Avoid this precompiled function. Generated | 549 // TODO(sigurdm): Avoid this precompiled function. Generated |
577 // constructor-functions and getter/setter functions can be stored in the | 550 // constructor-functions and getter/setter functions can be stored in the |
578 // library-description table. Setting properties on these can be moved to | 551 // library-description table. Setting properties on these can be moved to |
579 // finishClasses. | 552 // finishClasses. |
580 return js.statement(r""" | 553 return js.statement( |
| 554 r""" |
581 #precompiled = function ($collectedClasses$) { | 555 #precompiled = function ($collectedClasses$) { |
582 #norename; | 556 #norename; |
583 var $desc; | 557 var $desc; |
584 #functions; | 558 #functions; |
585 return #result; | 559 return #result; |
586 };""", | 560 };""", |
587 {'norename': new jsAst.Comment("// ::norenaming:: "), | 561 { |
588 'precompiled': generateEmbeddedGlobalAccess(embeddedNames.PRECOMPILED), | 562 'norename': new jsAst.Comment("// ::norenaming:: "), |
589 'functions': cspPrecompiledFunctionFor(outputUnit), | 563 'precompiled': |
590 'result': new jsAst.ArrayInitializer( | 564 generateEmbeddedGlobalAccess(embeddedNames.PRECOMPILED), |
591 cspPrecompiledConstructorNamesFor(outputUnit))}); | 565 'functions': cspPrecompiledFunctionFor(outputUnit), |
| 566 'result': new jsAst.ArrayInitializer( |
| 567 cspPrecompiledConstructorNamesFor(outputUnit)) |
| 568 }); |
592 } else { | 569 } else { |
593 return js.comment("Constructors are generated at runtime."); | 570 return js.comment("Constructors are generated at runtime."); |
594 } | 571 } |
595 } | 572 } |
596 | 573 |
597 void assembleClass(Class cls, ClassBuilder enclosingBuilder, | 574 void assembleClass( |
598 Fragment fragment) { | 575 Class cls, ClassBuilder enclosingBuilder, Fragment fragment) { |
599 ClassElement classElement = cls.element; | 576 ClassElement classElement = cls.element; |
600 reporter.withCurrentElement(classElement, () { | 577 reporter.withCurrentElement(classElement, () { |
601 if (compiler.options.hasIncrementalSupport) { | 578 if (compiler.options.hasIncrementalSupport) { |
602 ClassBuilder cachedBuilder = | 579 ClassBuilder cachedBuilder = |
603 cachedClassBuilders.putIfAbsent(classElement, () { | 580 cachedClassBuilders.putIfAbsent(classElement, () { |
604 ClassBuilder builder = | 581 ClassBuilder builder = new ClassBuilder.forClass(classElement, namer); |
605 new ClassBuilder.forClass(classElement, namer); | 582 classEmitter.emitClass(cls, builder, fragment); |
606 classEmitter.emitClass(cls, builder, fragment); | 583 return builder; |
607 return builder; | 584 }); |
608 }); | |
609 invariant(classElement, cachedBuilder.fields.isEmpty); | 585 invariant(classElement, cachedBuilder.fields.isEmpty); |
610 invariant(classElement, cachedBuilder.superName == null); | 586 invariant(classElement, cachedBuilder.superName == null); |
611 invariant(classElement, cachedBuilder.functionType == null); | 587 invariant(classElement, cachedBuilder.functionType == null); |
612 invariant(classElement, cachedBuilder.fieldMetadata == null); | 588 invariant(classElement, cachedBuilder.fieldMetadata == null); |
613 enclosingBuilder.properties.addAll(cachedBuilder.properties); | 589 enclosingBuilder.properties.addAll(cachedBuilder.properties); |
614 } else { | 590 } else { |
615 classEmitter.emitClass(cls, enclosingBuilder, fragment); | 591 classEmitter.emitClass(cls, enclosingBuilder, fragment); |
616 } | 592 } |
617 }); | 593 }); |
618 } | 594 } |
619 | 595 |
620 void assembleStaticFunctions(Iterable<Method> staticFunctions, | 596 void assembleStaticFunctions( |
621 Fragment fragment) { | 597 Iterable<Method> staticFunctions, Fragment fragment) { |
622 if (staticFunctions == null) return; | 598 if (staticFunctions == null) return; |
623 | 599 |
624 for (Method method in staticFunctions) { | 600 for (Method method in staticFunctions) { |
625 Element element = method.element; | 601 Element element = method.element; |
626 // We need to filter out null-elements for the interceptors. | 602 // We need to filter out null-elements for the interceptors. |
627 // TODO(floitsch): use the precomputed interceptors here. | 603 // TODO(floitsch): use the precomputed interceptors here. |
628 if (element == null) continue; | 604 if (element == null) continue; |
629 ClassBuilder builder = new ClassBuilder.forStatics(element, namer); | 605 ClassBuilder builder = new ClassBuilder.forStatics(element, namer); |
630 containerBuilder.addMemberMethod(method, builder); | 606 containerBuilder.addMemberMethod(method, builder); |
631 getElementDescriptor(element, fragment).properties | 607 getElementDescriptor(element, fragment) |
| 608 .properties |
632 .addAll(builder.properties); | 609 .addAll(builder.properties); |
633 } | 610 } |
634 } | 611 } |
635 | 612 |
636 jsAst.Statement buildStaticNonFinalFieldInitializations( | 613 jsAst.Statement buildStaticNonFinalFieldInitializations( |
637 OutputUnit outputUnit) { | 614 OutputUnit outputUnit) { |
638 jsAst.Statement buildInitialization(Element element, | 615 jsAst.Statement buildInitialization( |
639 jsAst.Expression initialValue) { | 616 Element element, jsAst.Expression initialValue) { |
640 return js.statement('${namer.staticStateHolder}.# = #', | 617 return js.statement('${namer.staticStateHolder}.# = #', |
641 [namer.globalPropertyName(element), initialValue]); | 618 [namer.globalPropertyName(element), initialValue]); |
642 } | 619 } |
643 | 620 |
644 bool inMainUnit = (outputUnit == compiler.deferredLoadTask.mainOutputUnit); | 621 bool inMainUnit = (outputUnit == compiler.deferredLoadTask.mainOutputUnit); |
645 JavaScriptConstantCompiler handler = backend.constants; | 622 JavaScriptConstantCompiler handler = backend.constants; |
646 List<jsAst.Statement> parts = <jsAst.Statement>[]; | 623 List<jsAst.Statement> parts = <jsAst.Statement>[]; |
647 | 624 |
648 Iterable<Element> fields = outputStaticNonFinalFieldLists[outputUnit]; | 625 Iterable<Element> fields = outputStaticNonFinalFieldLists[outputUnit]; |
649 // If the outputUnit does not contain any static non-final fields, then | 626 // If the outputUnit does not contain any static non-final fields, then |
650 // [fields] is `null`. | 627 // [fields] is `null`. |
651 if (fields != null) { | 628 if (fields != null) { |
652 for (Element element in fields) { | 629 for (Element element in fields) { |
653 reporter.withCurrentElement(element, () { | 630 reporter.withCurrentElement(element, () { |
654 ConstantValue constant = handler.getInitialValueFor(element); | 631 ConstantValue constant = handler.getInitialValueFor(element); |
655 parts.add(buildInitialization(element, constantReference(constant))); | 632 parts.add(buildInitialization(element, constantReference(constant))); |
656 }); | 633 }); |
657 } | 634 } |
658 } | 635 } |
659 | 636 |
660 if (inMainUnit && outputStaticNonFinalFieldLists.length > 1) { | 637 if (inMainUnit && outputStaticNonFinalFieldLists.length > 1) { |
661 // In the main output-unit we output a stub initializer for deferred | 638 // In the main output-unit we output a stub initializer for deferred |
662 // variables, so that `isolateProperties` stays a fast object. | 639 // variables, so that `isolateProperties` stays a fast object. |
663 outputStaticNonFinalFieldLists.forEach( | 640 outputStaticNonFinalFieldLists.forEach( |
664 (OutputUnit fieldsOutputUnit, Iterable<VariableElement> fields) { | 641 (OutputUnit fieldsOutputUnit, Iterable<VariableElement> fields) { |
665 if (fieldsOutputUnit == outputUnit) return; // Skip the main unit. | 642 if (fieldsOutputUnit == outputUnit) return; // Skip the main unit. |
666 for (Element element in fields) { | 643 for (Element element in fields) { |
667 reporter.withCurrentElement(element, () { | 644 reporter.withCurrentElement(element, () { |
668 parts.add(buildInitialization(element, jsAst.number(0))); | 645 parts.add(buildInitialization(element, jsAst.number(0))); |
669 }); | 646 }); |
670 } | 647 } |
671 }); | 648 }); |
672 } | 649 } |
673 | 650 |
674 return new jsAst.Block(parts); | 651 return new jsAst.Block(parts); |
675 } | 652 } |
676 | 653 |
677 jsAst.Statement buildLazilyInitializedStaticFields( | 654 jsAst.Statement buildLazilyInitializedStaticFields( |
678 Iterable<StaticField> lazyFields, {bool isMainFragment: true}) { | 655 Iterable<StaticField> lazyFields, |
| 656 {bool isMainFragment: true}) { |
679 if (lazyFields.isNotEmpty) { | 657 if (lazyFields.isNotEmpty) { |
680 needsLazyInitializer = true; | 658 needsLazyInitializer = true; |
681 List<jsAst.Expression> laziesInfo = | 659 List<jsAst.Expression> laziesInfo = |
682 buildLaziesInfo(lazyFields, isMainFragment); | 660 buildLaziesInfo(lazyFields, isMainFragment); |
683 return js.statement(''' | 661 return js.statement( |
| 662 ''' |
684 (function(lazies) { | 663 (function(lazies) { |
685 for (var i = 0; i < lazies.length; ) { | 664 for (var i = 0; i < lazies.length; ) { |
686 var fieldName = lazies[i++]; | 665 var fieldName = lazies[i++]; |
687 var getterName = lazies[i++]; | 666 var getterName = lazies[i++]; |
688 var lazyValue = lazies[i++]; | 667 var lazyValue = lazies[i++]; |
689 if (#notMinified) { | 668 if (#notMinified) { |
690 var staticName = lazies[i++]; | 669 var staticName = lazies[i++]; |
691 } | 670 } |
692 if (#isDeferredFragment) { | 671 if (#isDeferredFragment) { |
693 var fieldHolder = lazies[i++]; | 672 var fieldHolder = lazies[i++]; |
(...skipping 10 matching lines...) Expand all Loading... |
704 } | 683 } |
705 } else { | 684 } else { |
706 if (#notMinified) { | 685 if (#notMinified) { |
707 #lazy(fieldName, getterName, lazyValue, staticName, fieldHolder); | 686 #lazy(fieldName, getterName, lazyValue, staticName, fieldHolder); |
708 } else { | 687 } else { |
709 #lazy(fieldName, getterName, lazyValue, null, fieldHolder); | 688 #lazy(fieldName, getterName, lazyValue, null, fieldHolder); |
710 } | 689 } |
711 } | 690 } |
712 } | 691 } |
713 })(#laziesInfo) | 692 })(#laziesInfo) |
714 ''', {'notMinified': !compiler.options.enableMinification, | 693 ''', |
| 694 { |
| 695 'notMinified': !compiler.options.enableMinification, |
715 'laziesInfo': new jsAst.ArrayInitializer(laziesInfo), | 696 'laziesInfo': new jsAst.ArrayInitializer(laziesInfo), |
716 'lazy': js(lazyInitializerName), | 697 'lazy': js(lazyInitializerName), |
717 'isMainFragment': isMainFragment, | 698 'isMainFragment': isMainFragment, |
718 'isDeferredFragment': !isMainFragment}); | 699 'isDeferredFragment': !isMainFragment |
| 700 }); |
719 } else { | 701 } else { |
720 return js.comment("No lazy statics."); | 702 return js.comment("No lazy statics."); |
721 } | 703 } |
722 } | 704 } |
723 | 705 |
724 List<jsAst.Expression> buildLaziesInfo( | 706 List<jsAst.Expression> buildLaziesInfo( |
725 Iterable<StaticField> lazies, bool isMainFragment) { | 707 Iterable<StaticField> lazies, bool isMainFragment) { |
726 List<jsAst.Expression> laziesInfo = <jsAst.Expression>[]; | 708 List<jsAst.Expression> laziesInfo = <jsAst.Expression>[]; |
727 for (StaticField field in lazies) { | 709 for (StaticField field in lazies) { |
728 laziesInfo.add(js.quoteName(field.name)); | 710 laziesInfo.add(js.quoteName(field.name)); |
729 laziesInfo.add(js.quoteName(namer.deriveLazyInitializerName(field.name))); | 711 laziesInfo.add(js.quoteName(namer.deriveLazyInitializerName(field.name))); |
730 laziesInfo.add(field.code); | 712 laziesInfo.add(field.code); |
731 if (!compiler.options.enableMinification) { | 713 if (!compiler.options.enableMinification) { |
732 laziesInfo.add(js.quoteName(field.name)); | 714 laziesInfo.add(js.quoteName(field.name)); |
733 } | 715 } |
734 if (!isMainFragment) { | 716 if (!isMainFragment) { |
735 laziesInfo.add(js('#', field.holder.name)); | 717 laziesInfo.add(js('#', field.holder.name)); |
736 } | 718 } |
737 } | 719 } |
738 return laziesInfo; | 720 return laziesInfo; |
739 } | 721 } |
740 | 722 |
741 // TODO(sra): Remove this unused function. | 723 // TODO(sra): Remove this unused function. |
742 jsAst.Expression buildLazilyInitializedStaticField( | 724 jsAst.Expression buildLazilyInitializedStaticField(VariableElement element, |
743 VariableElement element, {String isolateProperties}) { | 725 {String isolateProperties}) { |
744 jsAst.Expression code = backend.generatedCode[element]; | 726 jsAst.Expression code = backend.generatedCode[element]; |
745 // The code is null if we ended up not needing the lazily | 727 // The code is null if we ended up not needing the lazily |
746 // initialized field after all because of constant folding | 728 // initialized field after all because of constant folding |
747 // before code generation. | 729 // before code generation. |
748 if (code == null) return null; | 730 if (code == null) return null; |
749 // The code only computes the initial value. We build the lazy-check | 731 // The code only computes the initial value. We build the lazy-check |
750 // here: | 732 // here: |
751 // lazyInitializer(fieldName, getterName, initial, name, prototype); | 733 // lazyInitializer(fieldName, getterName, initial, name, prototype); |
752 // The name is used for error reporting. The 'initial' must be a | 734 // The name is used for error reporting. The 'initial' must be a |
753 // closure that constructs the initial value. | 735 // closure that constructs the initial value. |
754 if (isolateProperties != null) { | 736 if (isolateProperties != null) { |
755 // This is currently only used in incremental compilation to patch | 737 // This is currently only used in incremental compilation to patch |
756 // in new lazy values. | 738 // in new lazy values. |
757 return js('#(#,#,#,#,#)', | 739 return js('#(#,#,#,#,#)', [ |
758 [js(lazyInitializerName), | 740 js(lazyInitializerName), |
759 js.quoteName(namer.globalPropertyName(element)), | 741 js.quoteName(namer.globalPropertyName(element)), |
760 js.quoteName(namer.lazyInitializerName(element)), | 742 js.quoteName(namer.lazyInitializerName(element)), |
761 code, | 743 code, |
762 js.string(element.name), | 744 js.string(element.name), |
763 isolateProperties]); | 745 isolateProperties |
| 746 ]); |
764 } | 747 } |
765 | 748 |
766 if (compiler.options.enableMinification) { | 749 if (compiler.options.enableMinification) { |
767 return js('#(#,#,#)', | 750 return js('#(#,#,#)', [ |
768 [js(lazyInitializerName), | 751 js(lazyInitializerName), |
769 js.quoteName(namer.globalPropertyName(element)), | 752 js.quoteName(namer.globalPropertyName(element)), |
770 js.quoteName(namer.lazyInitializerName(element)), | 753 js.quoteName(namer.lazyInitializerName(element)), |
771 code]); | 754 code |
| 755 ]); |
772 } else { | 756 } else { |
773 return js('#(#,#,#,#)', | 757 return js('#(#,#,#,#)', [ |
774 [js(lazyInitializerName), | 758 js(lazyInitializerName), |
775 js.quoteName(namer.globalPropertyName(element)), | 759 js.quoteName(namer.globalPropertyName(element)), |
776 js.quoteName(namer.lazyInitializerName(element)), | 760 js.quoteName(namer.lazyInitializerName(element)), |
777 code, | 761 code, |
778 js.string(element.name)]); | 762 js.string(element.name) |
| 763 ]); |
779 } | 764 } |
780 } | 765 } |
781 | 766 |
782 jsAst.Statement buildMetadata(Program program, OutputUnit outputUnit) { | 767 jsAst.Statement buildMetadata(Program program, OutputUnit outputUnit) { |
783 List<jsAst.Statement> parts = <jsAst.Statement>[]; | 768 List<jsAst.Statement> parts = <jsAst.Statement>[]; |
784 | 769 |
785 jsAst.Expression types = program.metadataTypesForOutputUnit(outputUnit); | 770 jsAst.Expression types = program.metadataTypesForOutputUnit(outputUnit); |
786 | 771 |
787 if (outputUnit == compiler.deferredLoadTask.mainOutputUnit) { | 772 if (outputUnit == compiler.deferredLoadTask.mainOutputUnit) { |
788 jsAst.Expression metadataAccess = | 773 jsAst.Expression metadataAccess = |
789 generateEmbeddedGlobalAccess(embeddedNames.METADATA); | 774 generateEmbeddedGlobalAccess(embeddedNames.METADATA); |
790 jsAst.Expression typesAccess = | 775 jsAst.Expression typesAccess = |
791 generateEmbeddedGlobalAccess(embeddedNames.TYPES); | 776 generateEmbeddedGlobalAccess(embeddedNames.TYPES); |
792 | 777 |
793 parts..add(js.statement('# = #;', [metadataAccess, program.metadata])) | 778 parts |
794 ..add(js.statement('# = #;', [typesAccess, types])); | 779 ..add(js.statement('# = #;', [metadataAccess, program.metadata])) |
| 780 ..add(js.statement('# = #;', [typesAccess, types])); |
795 } else if (types != null) { | 781 } else if (types != null) { |
796 parts.add(js.statement('var ${namer.deferredTypesName} = #;', | 782 parts.add(js.statement('var ${namer.deferredTypesName} = #;', types)); |
797 types)); | |
798 } | 783 } |
799 return new jsAst.Block(parts); | 784 return new jsAst.Block(parts); |
800 } | 785 } |
801 | 786 |
802 jsAst.Statement buildCompileTimeConstants(List<Constant> constants, | 787 jsAst.Statement buildCompileTimeConstants(List<Constant> constants, |
803 {bool isMainFragment}) { | 788 {bool isMainFragment}) { |
804 assert(isMainFragment != null); | 789 assert(isMainFragment != null); |
805 | 790 |
806 if (constants.isEmpty) return js.comment("No constants in program."); | 791 if (constants.isEmpty) return js.comment("No constants in program."); |
807 List<jsAst.Statement> parts = <jsAst.Statement>[]; | 792 List<jsAst.Statement> parts = <jsAst.Statement>[]; |
808 if (compiler.options.hasIncrementalSupport && isMainFragment) { | 793 if (compiler.options.hasIncrementalSupport && isMainFragment) { |
809 parts = cachedEmittedConstantsAst; | 794 parts = cachedEmittedConstantsAst; |
810 } | 795 } |
811 for (Constant constant in constants) { | 796 for (Constant constant in constants) { |
812 ConstantValue constantValue = constant.value; | 797 ConstantValue constantValue = constant.value; |
813 if (compiler.options.hasIncrementalSupport && isMainFragment) { | 798 if (compiler.options.hasIncrementalSupport && isMainFragment) { |
814 if (cachedEmittedConstants.contains(constantValue)) continue; | 799 if (cachedEmittedConstants.contains(constantValue)) continue; |
815 cachedEmittedConstants.add(constantValue); | 800 cachedEmittedConstants.add(constantValue); |
816 } | 801 } |
817 parts.add(buildConstantInitializer(constantValue)); | 802 parts.add(buildConstantInitializer(constantValue)); |
818 } | 803 } |
819 | 804 |
820 return new jsAst.Block(parts); | 805 return new jsAst.Block(parts); |
821 } | 806 } |
822 | 807 |
823 jsAst.Statement buildConstantInitializer(ConstantValue constant) { | 808 jsAst.Statement buildConstantInitializer(ConstantValue constant) { |
824 jsAst.Name name = namer.constantName(constant); | 809 jsAst.Name name = namer.constantName(constant); |
825 jsAst.Statement initializer = js.statement('#.# = #', | 810 jsAst.Statement initializer = js.statement('#.# = #', [ |
826 [namer.globalObjectForConstant(constant), name, | 811 namer.globalObjectForConstant(constant), |
827 constantInitializerExpression(constant)]); | 812 name, |
| 813 constantInitializerExpression(constant) |
| 814 ]); |
828 compiler.dumpInfoTask.registerConstantAst(constant, initializer); | 815 compiler.dumpInfoTask.registerConstantAst(constant, initializer); |
829 return initializer; | 816 return initializer; |
830 } | 817 } |
831 | 818 |
832 jsAst.Expression constantListGenerator(jsAst.Expression array) { | 819 jsAst.Expression constantListGenerator(jsAst.Expression array) { |
833 // TODO(floitsch): there is no harm in caching the template. | 820 // TODO(floitsch): there is no harm in caching the template. |
834 return js('${namer.isolateName}.#(#)', [makeConstListProperty, array]); | 821 return js('${namer.isolateName}.#(#)', [makeConstListProperty, array]); |
835 } | 822 } |
836 | 823 |
837 jsAst.Statement buildMakeConstantList(bool outputContainsConstantList) { | 824 jsAst.Statement buildMakeConstantList(bool outputContainsConstantList) { |
838 if (outputContainsConstantList) { | 825 if (outputContainsConstantList) { |
839 return js.statement(r''' | 826 return js.statement( |
| 827 r''' |
840 // Functions are stored in the hidden class and not as properties in | 828 // Functions are stored in the hidden class and not as properties in |
841 // the object. We never actually look at the value, but only want | 829 // the object. We never actually look at the value, but only want |
842 // to know if the property exists. | 830 // to know if the property exists. |
843 #.# = function (list) { | 831 #.# = function (list) { |
844 list.immutable$list = Array; | 832 list.immutable$list = Array; |
845 list.fixed$length = Array; | 833 list.fixed$length = Array; |
846 return list; | 834 return list; |
847 }''', | 835 }''', |
848 [namer.isolateName, makeConstListProperty]); | 836 [namer.isolateName, makeConstListProperty]); |
849 } else { | 837 } else { |
850 return js.comment("Output contains no constant list."); | 838 return js.comment("Output contains no constant list."); |
851 } | 839 } |
852 } | 840 } |
853 | 841 |
854 jsAst.Statement buildFunctionThatReturnsNull() { | 842 jsAst.Statement buildFunctionThatReturnsNull() { |
855 return js.statement('#.# = function() {}', | 843 return js.statement('#.# = function() {}', |
856 [namer.isolateName, | 844 [namer.isolateName, backend.rtiEncoder.getFunctionThatReturnsNullName]); |
857 backend.rtiEncoder.getFunctionThatReturnsNullName]); | |
858 } | 845 } |
859 | 846 |
860 jsAst.Expression generateFunctionThatReturnsNull() { | 847 jsAst.Expression generateFunctionThatReturnsNull() { |
861 return js("#.#", [namer.isolateName, | 848 return js("#.#", |
862 backend.rtiEncoder.getFunctionThatReturnsNullName]); | 849 [namer.isolateName, backend.rtiEncoder.getFunctionThatReturnsNullName]); |
863 } | 850 } |
864 | 851 |
865 buildMain(jsAst.Statement invokeMain) { | 852 buildMain(jsAst.Statement invokeMain) { |
866 if (compiler.isMockCompilation) return js.comment("Mock compilation"); | 853 if (compiler.isMockCompilation) return js.comment("Mock compilation"); |
867 | 854 |
868 List<jsAst.Statement> parts = <jsAst.Statement>[]; | 855 List<jsAst.Statement> parts = <jsAst.Statement>[]; |
869 | 856 |
870 if (NativeGenerator.needsIsolateAffinityTagInitialization(backend)) { | 857 if (NativeGenerator.needsIsolateAffinityTagInitialization(backend)) { |
871 parts.add( | 858 parts.add(NativeGenerator.generateIsolateAffinityTagInitialization( |
872 NativeGenerator.generateIsolateAffinityTagInitialization( | 859 backend, |
873 backend, | 860 generateEmbeddedGlobalAccess, |
874 generateEmbeddedGlobalAccess, | 861 js( |
875 js(""" | 862 """ |
876 // On V8, the 'intern' function converts a string to a symbol, which | 863 // On V8, the 'intern' function converts a string to a symbol, which |
877 // makes property access much faster. | 864 // makes property access much faster. |
878 function (s) { | 865 function (s) { |
879 var o = {}; | 866 var o = {}; |
880 o[s] = 1; | 867 o[s] = 1; |
881 return Object.keys(convertToFastObject(o))[0]; | 868 return Object.keys(convertToFastObject(o))[0]; |
882 }""", []))); | 869 }""", |
| 870 []))); |
883 } | 871 } |
884 | 872 |
885 parts..add(js.comment('BEGIN invoke [main].')) | 873 parts |
886 ..add(invokeMain) | 874 ..add(js.comment('BEGIN invoke [main].')) |
887 ..add(js.comment('END invoke [main].')); | 875 ..add(invokeMain) |
| 876 ..add(js.comment('END invoke [main].')); |
888 | 877 |
889 return new jsAst.Block(parts); | 878 return new jsAst.Block(parts); |
890 } | 879 } |
891 | 880 |
892 jsAst.Statement buildInitFunction(bool outputContainsConstantList) { | 881 jsAst.Statement buildInitFunction(bool outputContainsConstantList) { |
893 jsAst.Expression allClassesAccess = | 882 jsAst.Expression allClassesAccess = |
894 generateEmbeddedGlobalAccess(embeddedNames.ALL_CLASSES); | 883 generateEmbeddedGlobalAccess(embeddedNames.ALL_CLASSES); |
895 jsAst.Expression getTypeFromNameAccess = | 884 jsAst.Expression getTypeFromNameAccess = |
896 generateEmbeddedGlobalAccess(embeddedNames.GET_TYPE_FROM_NAME); | 885 generateEmbeddedGlobalAccess(embeddedNames.GET_TYPE_FROM_NAME); |
897 jsAst.Expression interceptorsByTagAccess = | 886 jsAst.Expression interceptorsByTagAccess = |
898 generateEmbeddedGlobalAccess(embeddedNames.INTERCEPTORS_BY_TAG); | 887 generateEmbeddedGlobalAccess(embeddedNames.INTERCEPTORS_BY_TAG); |
899 jsAst.Expression leafTagsAccess = | 888 jsAst.Expression leafTagsAccess = |
900 generateEmbeddedGlobalAccess(embeddedNames.LEAF_TAGS); | 889 generateEmbeddedGlobalAccess(embeddedNames.LEAF_TAGS); |
901 jsAst.Expression finishedClassesAccess = | 890 jsAst.Expression finishedClassesAccess = |
902 generateEmbeddedGlobalAccess(embeddedNames.FINISHED_CLASSES); | 891 generateEmbeddedGlobalAccess(embeddedNames.FINISHED_CLASSES); |
903 jsAst.Expression cyclicThrow = | 892 jsAst.Expression cyclicThrow = |
904 staticFunctionAccess(backend.helpers.cyclicThrowHelper); | 893 staticFunctionAccess(backend.helpers.cyclicThrowHelper); |
905 jsAst.Expression laziesAccess = | 894 jsAst.Expression laziesAccess = |
906 generateEmbeddedGlobalAccess(embeddedNames.LAZIES); | 895 generateEmbeddedGlobalAccess(embeddedNames.LAZIES); |
907 | 896 |
908 return js.statement(''' | 897 return js.statement( |
| 898 ''' |
909 function init() { | 899 function init() { |
910 $isolatePropertiesName = Object.create(null); | 900 $isolatePropertiesName = Object.create(null); |
911 #allClasses = map(); | 901 #allClasses = map(); |
912 #getTypeFromName = function(name) {return #allClasses[name];}; | 902 #getTypeFromName = function(name) {return #allClasses[name];}; |
913 #interceptorsByTag = map(); | 903 #interceptorsByTag = map(); |
914 #leafTags = map(); | 904 #leafTags = map(); |
915 #finishedClasses = map(); | 905 #finishedClasses = map(); |
916 | 906 |
917 if (#needsLazyInitializer) { | 907 if (#needsLazyInitializer) { |
918 // [staticName] is only provided in non-minified mode. If missing, we | 908 // [staticName] is only provided in non-minified mode. If missing, we |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1008 } | 998 } |
1009 Isolate.#functionThatReturnsNullProperty = | 999 Isolate.#functionThatReturnsNullProperty = |
1010 oldIsolate.#functionThatReturnsNullProperty; | 1000 oldIsolate.#functionThatReturnsNullProperty; |
1011 if (#hasIncrementalSupport) { | 1001 if (#hasIncrementalSupport) { |
1012 Isolate.#lazyInitializerProperty = | 1002 Isolate.#lazyInitializerProperty = |
1013 oldIsolate.#lazyInitializerProperty; | 1003 oldIsolate.#lazyInitializerProperty; |
1014 } | 1004 } |
1015 return Isolate; | 1005 return Isolate; |
1016 } | 1006 } |
1017 | 1007 |
1018 }''', {'allClasses': allClassesAccess, | 1008 }''', |
1019 'getTypeFromName': getTypeFromNameAccess, | 1009 { |
1020 'interceptorsByTag': interceptorsByTagAccess, | 1010 'allClasses': allClassesAccess, |
1021 'leafTags': leafTagsAccess, | 1011 'getTypeFromName': getTypeFromNameAccess, |
1022 'finishedClasses': finishedClassesAccess, | 1012 'interceptorsByTag': interceptorsByTagAccess, |
1023 'needsLazyInitializer': needsLazyInitializer, | 1013 'leafTags': leafTagsAccess, |
1024 'lazies': laziesAccess, 'cyclicThrow': cyclicThrow, | 1014 'finishedClasses': finishedClassesAccess, |
1025 'isolatePropertiesName': namer.isolatePropertiesName, | 1015 'needsLazyInitializer': needsLazyInitializer, |
1026 'outputContainsConstantList': outputContainsConstantList, | 1016 'lazies': laziesAccess, |
1027 'makeConstListProperty': makeConstListProperty, | 1017 'cyclicThrow': cyclicThrow, |
1028 'functionThatReturnsNullProperty': | 1018 'isolatePropertiesName': namer.isolatePropertiesName, |
1029 backend.rtiEncoder.getFunctionThatReturnsNullName, | 1019 'outputContainsConstantList': outputContainsConstantList, |
1030 'hasIncrementalSupport': compiler.options.hasIncrementalSupport, | 1020 'makeConstListProperty': makeConstListProperty, |
1031 'lazyInitializerProperty': lazyInitializerProperty,}); | 1021 'functionThatReturnsNullProperty': |
| 1022 backend.rtiEncoder.getFunctionThatReturnsNullName, |
| 1023 'hasIncrementalSupport': compiler.options.hasIncrementalSupport, |
| 1024 'lazyInitializerProperty': lazyInitializerProperty, |
| 1025 }); |
1032 } | 1026 } |
1033 | 1027 |
1034 jsAst.Statement buildConvertToFastObjectFunction() { | 1028 jsAst.Statement buildConvertToFastObjectFunction() { |
1035 List<jsAst.Statement> debugCode = <jsAst.Statement>[]; | 1029 List<jsAst.Statement> debugCode = <jsAst.Statement>[]; |
1036 if (DEBUG_FAST_OBJECTS) { | 1030 if (DEBUG_FAST_OBJECTS) { |
1037 debugCode.add(js.statement(r''' | 1031 debugCode.add(js.statement(r''' |
1038 // The following only works on V8 when run with option | 1032 // The following only works on V8 when run with option |
1039 // "--allow-natives-syntax". We use'new Function' because the | 1033 // "--allow-natives-syntax". We use'new Function' because the |
1040 // miniparser does not understand V8 native syntax. | 1034 // miniparser does not understand V8 native syntax. |
1041 if (typeof print === "function") { | 1035 if (typeof print === "function") { |
1042 var HasFastProperties = | 1036 var HasFastProperties = |
1043 new Function("a", "return %HasFastProperties(a)"); | 1037 new Function("a", "return %HasFastProperties(a)"); |
1044 print("Size of global object: " | 1038 print("Size of global object: " |
1045 + String(Object.getOwnPropertyNames(properties).length) | 1039 + String(Object.getOwnPropertyNames(properties).length) |
1046 + ", fast properties " + HasFastProperties(properties)); | 1040 + ", fast properties " + HasFastProperties(properties)); |
1047 }''')); | 1041 }''')); |
1048 } | 1042 } |
1049 | 1043 |
1050 return js.statement(r''' | 1044 return js.statement( |
| 1045 r''' |
1051 function convertToFastObject(properties) { | 1046 function convertToFastObject(properties) { |
1052 // Create an instance that uses 'properties' as prototype. This should | 1047 // Create an instance that uses 'properties' as prototype. This should |
1053 // make 'properties' a fast object. | 1048 // make 'properties' a fast object. |
1054 function MyClass() {}; | 1049 function MyClass() {}; |
1055 MyClass.prototype = properties; | 1050 MyClass.prototype = properties; |
1056 new MyClass(); | 1051 new MyClass(); |
1057 #; | 1052 #; |
1058 return properties; | 1053 return properties; |
1059 }''', [debugCode]); | 1054 }''', |
| 1055 [debugCode]); |
1060 } | 1056 } |
1061 | 1057 |
1062 jsAst.Statement buildConvertToSlowObjectFunction() { | 1058 jsAst.Statement buildConvertToSlowObjectFunction() { |
1063 return js.statement(r''' | 1059 return js.statement(r''' |
1064 function convertToSlowObject(properties) { | 1060 function convertToSlowObject(properties) { |
1065 // Add and remove a property to make the object transition into hashmap | 1061 // Add and remove a property to make the object transition into hashmap |
1066 // mode. | 1062 // mode. |
1067 properties.__MAGIC_SLOW_PROPERTY = 1; | 1063 properties.__MAGIC_SLOW_PROPERTY = 1; |
1068 delete properties.__MAGIC_SLOW_PROPERTY; | 1064 delete properties.__MAGIC_SLOW_PROPERTY; |
1069 return properties; | 1065 return properties; |
(...skipping 15 matching lines...) Expand all Loading... |
1085 var object = new cls(); | 1081 var object = new cls(); |
1086 return object.__proto__ && | 1082 return object.__proto__ && |
1087 object.__proto__.p === cls.prototype.p; | 1083 object.__proto__.p === cls.prototype.p; |
1088 })(); | 1084 })(); |
1089 '''); | 1085 '''); |
1090 } | 1086 } |
1091 | 1087 |
1092 return supportsDirectProtoAccess; | 1088 return supportsDirectProtoAccess; |
1093 } | 1089 } |
1094 | 1090 |
1095 jsAst.Expression generateLibraryDescriptor(LibraryElement library, | 1091 jsAst.Expression generateLibraryDescriptor( |
1096 Fragment fragment) { | 1092 LibraryElement library, Fragment fragment) { |
1097 var uri = ""; | 1093 var uri = ""; |
1098 if (!compiler.options.enableMinification || backend.mustPreserveUris) { | 1094 if (!compiler.options.enableMinification || backend.mustPreserveUris) { |
1099 uri = library.canonicalUri; | 1095 uri = library.canonicalUri; |
1100 if (uri.scheme == 'file' && compiler.options.outputUri != null) { | 1096 if (uri.scheme == 'file' && compiler.options.outputUri != null) { |
1101 uri = relativize( | 1097 uri = |
1102 compiler.options.outputUri, library.canonicalUri, false); | 1098 relativize(compiler.options.outputUri, library.canonicalUri, false); |
1103 } | 1099 } |
1104 } | 1100 } |
1105 | 1101 |
1106 String libraryName = (!compiler.options.enableMinification || | 1102 String libraryName = (!compiler.options.enableMinification || |
1107 backend.mustRetainLibraryNames) ? library.libraryName : ""; | 1103 backend.mustRetainLibraryNames) ? library.libraryName : ""; |
1108 | 1104 |
1109 jsAst.Fun metadata = task.metadataCollector.buildMetadataFunction(library); | 1105 jsAst.Fun metadata = task.metadataCollector.buildMetadataFunction(library); |
1110 | 1106 |
1111 ClassBuilder descriptor = elementDescriptors[fragment][library]; | 1107 ClassBuilder descriptor = elementDescriptors[fragment][library]; |
1112 | 1108 |
1113 jsAst.ObjectInitializer initializer; | 1109 jsAst.ObjectInitializer initializer; |
1114 if (descriptor == null) { | 1110 if (descriptor == null) { |
1115 // Nothing of the library was emitted. | 1111 // Nothing of the library was emitted. |
1116 // TODO(floitsch): this should not happen. We currently have an example | 1112 // TODO(floitsch): this should not happen. We currently have an example |
1117 // with language/prefix6_negative_test.dart where we have an instance | 1113 // with language/prefix6_negative_test.dart where we have an instance |
1118 // method without its corresponding class. | 1114 // method without its corresponding class. |
1119 initializer = new jsAst.ObjectInitializer([]); | 1115 initializer = new jsAst.ObjectInitializer([]); |
1120 } else { | 1116 } else { |
1121 initializer = descriptor.toObjectInitializer(); | 1117 initializer = descriptor.toObjectInitializer(); |
1122 } | 1118 } |
1123 | 1119 |
1124 compiler.dumpInfoTask.registerElementAst(library, metadata); | 1120 compiler.dumpInfoTask.registerElementAst(library, metadata); |
1125 compiler.dumpInfoTask.registerElementAst(library, initializer); | 1121 compiler.dumpInfoTask.registerElementAst(library, initializer); |
1126 | 1122 |
1127 List<jsAst.Expression> parts = <jsAst.Expression>[]; | 1123 List<jsAst.Expression> parts = <jsAst.Expression>[]; |
1128 parts..add(js.string(libraryName)) | 1124 parts |
1129 ..add(js.string(uri.toString())) | 1125 ..add(js.string(libraryName)) |
1130 ..add(metadata == null ? new jsAst.ArrayHole() : metadata) | 1126 ..add(js.string(uri.toString())) |
1131 ..add(js('#', namer.globalObjectFor(library))) | 1127 ..add(metadata == null ? new jsAst.ArrayHole() : metadata) |
1132 ..add(initializer); | 1128 ..add(js('#', namer.globalObjectFor(library))) |
| 1129 ..add(initializer); |
1133 if (library == compiler.mainApp) { | 1130 if (library == compiler.mainApp) { |
1134 parts.add(js.number(1)); | 1131 parts.add(js.number(1)); |
1135 } | 1132 } |
1136 | 1133 |
1137 return new jsAst.ArrayInitializer(parts); | 1134 return new jsAst.ArrayInitializer(parts); |
1138 } | 1135 } |
1139 | 1136 |
1140 void assemblePrecompiledConstructor(OutputUnit outputUnit, | 1137 void assemblePrecompiledConstructor( |
1141 jsAst.Name constructorName, | 1138 OutputUnit outputUnit, |
1142 jsAst.Expression constructorAst, | 1139 jsAst.Name constructorName, |
1143 List<jsAst.Name> fields) { | 1140 jsAst.Expression constructorAst, |
1144 cspPrecompiledFunctionFor(outputUnit).add( | 1141 List<jsAst.Name> fields) { |
1145 new jsAst.FunctionDeclaration(constructorName, constructorAst)); | 1142 cspPrecompiledFunctionFor(outputUnit) |
| 1143 .add(new jsAst.FunctionDeclaration(constructorName, constructorAst)); |
1146 | 1144 |
1147 String fieldNamesProperty = FIELD_NAMES_PROPERTY_NAME; | 1145 String fieldNamesProperty = FIELD_NAMES_PROPERTY_NAME; |
1148 bool hasIsolateSupport = compiler.hasIsolateSupport; | 1146 bool hasIsolateSupport = compiler.hasIsolateSupport; |
1149 jsAst.Node fieldNamesArray; | 1147 jsAst.Node fieldNamesArray; |
1150 if (hasIsolateSupport) { | 1148 if (hasIsolateSupport) { |
1151 fieldNamesArray = | 1149 fieldNamesArray = |
1152 new jsAst.ArrayInitializer(fields.map(js.quoteName).toList()); | 1150 new jsAst.ArrayInitializer(fields.map(js.quoteName).toList()); |
1153 } else { | 1151 } else { |
1154 fieldNamesArray = new jsAst.LiteralNull(); | 1152 fieldNamesArray = new jsAst.LiteralNull(); |
1155 } | 1153 } |
1156 | 1154 |
1157 cspPrecompiledFunctionFor(outputUnit).add(js.statement(r''' | 1155 cspPrecompiledFunctionFor(outputUnit).add(js.statement( |
| 1156 r''' |
1158 { | 1157 { |
1159 #constructorName.#typeNameProperty = #constructorNameString; | 1158 #constructorName.#typeNameProperty = #constructorNameString; |
1160 // IE does not have a name property. | 1159 // IE does not have a name property. |
1161 if (!("name" in #constructorName)) | 1160 if (!("name" in #constructorName)) |
1162 #constructorName.name = #constructorNameString; | 1161 #constructorName.name = #constructorNameString; |
1163 $desc = $collectedClasses$.#constructorName[1]; | 1162 $desc = $collectedClasses$.#constructorName[1]; |
1164 #constructorName.prototype = $desc; | 1163 #constructorName.prototype = $desc; |
1165 ''' /* next string is not a raw string */ ''' | 1164 ''' /* next string is not a raw string */ ''' |
1166 if (#hasIsolateSupport) { | 1165 if (#hasIsolateSupport) { |
1167 #constructorName.$fieldNamesProperty = #fieldNamesArray; | 1166 #constructorName.$fieldNamesProperty = #fieldNamesArray; |
1168 } | 1167 } |
1169 }''', | 1168 }''', |
1170 {"constructorName": constructorName, | 1169 { |
1171 "typeNameProperty": typeNameProperty, | 1170 "constructorName": constructorName, |
1172 "constructorNameString": js.quoteName(constructorName), | 1171 "typeNameProperty": typeNameProperty, |
1173 "hasIsolateSupport": hasIsolateSupport, | 1172 "constructorNameString": js.quoteName(constructorName), |
1174 "fieldNamesArray": fieldNamesArray})); | 1173 "hasIsolateSupport": hasIsolateSupport, |
| 1174 "fieldNamesArray": fieldNamesArray |
| 1175 })); |
1175 | 1176 |
1176 cspPrecompiledConstructorNamesFor(outputUnit).add(js('#', constructorName)); | 1177 cspPrecompiledConstructorNamesFor(outputUnit).add(js('#', constructorName)); |
1177 } | 1178 } |
1178 | 1179 |
1179 void assembleTypedefs(Program program) { | 1180 void assembleTypedefs(Program program) { |
1180 Fragment mainFragment = program.mainFragment; | 1181 Fragment mainFragment = program.mainFragment; |
1181 OutputUnit mainOutputUnit = mainFragment.outputUnit; | 1182 OutputUnit mainOutputUnit = mainFragment.outputUnit; |
1182 | 1183 |
1183 // Emit all required typedef declarations into the main output unit. | 1184 // Emit all required typedef declarations into the main output unit. |
1184 // TODO(karlklose): unify required classes and typedefs to declarations | 1185 // TODO(karlklose): unify required classes and typedefs to declarations |
1185 // and have builders for each kind. | 1186 // and have builders for each kind. |
1186 for (TypedefElement typedef in typedefsNeededForReflection) { | 1187 for (TypedefElement typedef in typedefsNeededForReflection) { |
1187 LibraryElement library = typedef.library; | 1188 LibraryElement library = typedef.library; |
1188 // TODO(karlklose): add a TypedefBuilder and move this code there. | 1189 // TODO(karlklose): add a TypedefBuilder and move this code there. |
1189 DartType type = typedef.alias; | 1190 DartType type = typedef.alias; |
1190 // TODO(zarah): reify type variables once reflection on type arguments of | 1191 // TODO(zarah): reify type variables once reflection on type arguments of |
1191 // typedefs is supported. | 1192 // typedefs is supported. |
1192 jsAst.Expression typeIndex = | 1193 jsAst.Expression typeIndex = |
1193 task.metadataCollector.reifyType(type, ignoreTypeVariables: true); | 1194 task.metadataCollector.reifyType(type, ignoreTypeVariables: true); |
1194 ClassBuilder builder = new ClassBuilder.forStatics(typedef, namer); | 1195 ClassBuilder builder = new ClassBuilder.forStatics(typedef, namer); |
1195 builder.addPropertyByName(embeddedNames.TYPEDEF_TYPE_PROPERTY_NAME, | 1196 builder.addPropertyByName( |
1196 typeIndex); | 1197 embeddedNames.TYPEDEF_TYPE_PROPERTY_NAME, typeIndex); |
1197 builder.addPropertyByName(embeddedNames.TYPEDEF_PREDICATE_PROPERTY_NAME, | 1198 builder.addPropertyByName( |
1198 js.boolean(true)); | 1199 embeddedNames.TYPEDEF_PREDICATE_PROPERTY_NAME, js.boolean(true)); |
1199 | 1200 |
1200 // We can be pretty sure that the objectClass is initialized, since | 1201 // We can be pretty sure that the objectClass is initialized, since |
1201 // typedefs are only emitted with reflection, which requires lots of | 1202 // typedefs are only emitted with reflection, which requires lots of |
1202 // classes. | 1203 // classes. |
1203 assert(coreClasses.objectClass != null); | 1204 assert(coreClasses.objectClass != null); |
1204 builder.superName = namer.className(coreClasses.objectClass); | 1205 builder.superName = namer.className(coreClasses.objectClass); |
1205 jsAst.Node declaration = builder.toObjectInitializer(); | 1206 jsAst.Node declaration = builder.toObjectInitializer(); |
1206 jsAst.Name mangledName = namer.globalPropertyName(typedef); | 1207 jsAst.Name mangledName = namer.globalPropertyName(typedef); |
1207 String reflectionName = getReflectionName(typedef, mangledName); | 1208 String reflectionName = getReflectionName(typedef, mangledName); |
1208 getElementDescriptor(library, mainFragment) | 1209 getElementDescriptor(library, mainFragment) |
1209 ..addProperty(mangledName, declaration) | 1210 ..addProperty(mangledName, declaration) |
1210 ..addPropertyByName("+$reflectionName", js.string('')); | 1211 ..addPropertyByName("+$reflectionName", js.string('')); |
1211 // Also emit a trivial constructor for CSP mode. | 1212 // Also emit a trivial constructor for CSP mode. |
1212 jsAst.Name constructorName = mangledName; | 1213 jsAst.Name constructorName = mangledName; |
1213 jsAst.Expression constructorAst = js('function() {}'); | 1214 jsAst.Expression constructorAst = js('function() {}'); |
1214 List<jsAst.Name> fieldNames = []; | 1215 List<jsAst.Name> fieldNames = []; |
1215 assemblePrecompiledConstructor(mainOutputUnit, | 1216 assemblePrecompiledConstructor( |
1216 constructorName, | 1217 mainOutputUnit, constructorName, constructorAst, fieldNames); |
1217 constructorAst, | |
1218 fieldNames); | |
1219 } | 1218 } |
1220 } | 1219 } |
1221 | 1220 |
1222 jsAst.Statement buildGlobalObjectSetup(bool isProgramSplit) { | 1221 jsAst.Statement buildGlobalObjectSetup(bool isProgramSplit) { |
1223 List<jsAst.Statement> parts = <jsAst.Statement>[]; | 1222 List<jsAst.Statement> parts = <jsAst.Statement>[]; |
1224 | 1223 |
1225 parts.add(js.comment(""" | 1224 parts.add(js.comment(""" |
1226 // The global objects start as so-called "slow objects". For V8, this | 1225 // The global objects start as so-called "slow objects". For V8, this |
1227 // means that it won't try to make map transitions as we add properties | 1226 // means that it won't try to make map transitions as we add properties |
1228 // to these objects. Later on, we attempt to turn these objects into | 1227 // to these objects. Later on, we attempt to turn these objects into |
1229 // fast objects by calling "convertToFastObject" (see | 1228 // fast objects by calling "convertToFastObject" (see |
1230 // [emitConvertToFastObjectFunction]). | 1229 // [emitConvertToFastObjectFunction]). |
1231 """)); | 1230 """)); |
1232 | 1231 |
1233 for (String globalObject in Namer.reservedGlobalObjectNames) { | 1232 for (String globalObject in Namer.reservedGlobalObjectNames) { |
1234 if (isProgramSplit) { | 1233 if (isProgramSplit) { |
1235 String template = | 1234 String template = |
1236 "var #globalObject = #globalsHolder.#globalObject = map();"; | 1235 "var #globalObject = #globalsHolder.#globalObject = map();"; |
1237 parts.add(js.statement(template, {"globalObject": globalObject, | 1236 parts.add(js.statement(template, |
1238 "globalsHolder": globalsHolder})); | 1237 {"globalObject": globalObject, "globalsHolder": globalsHolder})); |
1239 } else { | 1238 } else { |
1240 parts.add(js.statement("var #globalObject = map();", | 1239 parts.add(js.statement( |
1241 {"globalObject": globalObject})); | 1240 "var #globalObject = map();", {"globalObject": globalObject})); |
1242 } | 1241 } |
1243 | |
1244 } | 1242 } |
1245 | 1243 |
1246 return new jsAst.Block(parts); | 1244 return new jsAst.Block(parts); |
1247 } | 1245 } |
1248 | 1246 |
1249 jsAst.Statement buildConvertGlobalObjectToFastObjects() { | 1247 jsAst.Statement buildConvertGlobalObjectToFastObjects() { |
1250 List<jsAst.Statement> parts = <jsAst.Statement>[]; | 1248 List<jsAst.Statement> parts = <jsAst.Statement>[]; |
1251 | 1249 |
1252 for (String globalObject in Namer.reservedGlobalObjectNames) { | 1250 for (String globalObject in Namer.reservedGlobalObjectNames) { |
1253 parts.add(js.statement( | 1251 parts.add(js.statement( |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1285 + String(Object.getOwnPropertyNames(C).length) | 1283 + String(Object.getOwnPropertyNames(C).length) |
1286 + ", fast properties " + HasFastProperties(C)); | 1284 + ", fast properties " + HasFastProperties(C)); |
1287 var names = Object.getOwnPropertyNames($); | 1285 var names = Object.getOwnPropertyNames($); |
1288 for (var i = 0; i < names.length; i++) { | 1286 for (var i = 0; i < names.length; i++) { |
1289 print("$." + names[i]); | 1287 print("$." + names[i]); |
1290 } | 1288 } |
1291 } | 1289 } |
1292 ''')); | 1290 ''')); |
1293 | 1291 |
1294 for (String object in Namer.userGlobalObjects) { | 1292 for (String object in Namer.userGlobalObjects) { |
1295 parts.add(js.statement(''' | 1293 parts.add(js.statement( |
| 1294 ''' |
1296 if (typeof print === "function") { | 1295 if (typeof print === "function") { |
1297 print("Size of " + #objectString + ": " | 1296 print("Size of " + #objectString + ": " |
1298 + String(Object.getOwnPropertyNames(#object).length) | 1297 + String(Object.getOwnPropertyNames(#object).length) |
1299 + ", fast properties " + HasFastProperties(#object)); | 1298 + ", fast properties " + HasFastProperties(#object)); |
1300 } | 1299 } |
1301 ''', {"object": object, "objectString": js.string(object)})); | 1300 ''', |
| 1301 {"object": object, "objectString": js.string(object)})); |
1302 } | 1302 } |
1303 } | 1303 } |
1304 | 1304 |
1305 return new jsAst.Block(parts); | 1305 return new jsAst.Block(parts); |
1306 } | 1306 } |
1307 | 1307 |
1308 jsAst.Statement buildMangledNames() { | 1308 jsAst.Statement buildMangledNames() { |
1309 List<jsAst.Statement> parts = <jsAst.Statement>[]; | 1309 List<jsAst.Statement> parts = <jsAst.Statement>[]; |
1310 | 1310 |
1311 if (!mangledFieldNames.isEmpty) { | 1311 if (!mangledFieldNames.isEmpty) { |
1312 List<jsAst.Name> keys = mangledFieldNames.keys.toList()..sort(); | 1312 List<jsAst.Name> keys = mangledFieldNames.keys.toList()..sort(); |
1313 var properties = []; | 1313 var properties = []; |
1314 for (jsAst.Name key in keys) { | 1314 for (jsAst.Name key in keys) { |
1315 var value = js.string(mangledFieldNames[key]); | 1315 var value = js.string(mangledFieldNames[key]); |
1316 properties.add(new jsAst.Property(key, value)); | 1316 properties.add(new jsAst.Property(key, value)); |
1317 } | 1317 } |
1318 | 1318 |
1319 jsAst.Expression mangledNamesAccess = | 1319 jsAst.Expression mangledNamesAccess = |
1320 generateEmbeddedGlobalAccess(embeddedNames.MANGLED_NAMES); | 1320 generateEmbeddedGlobalAccess(embeddedNames.MANGLED_NAMES); |
1321 var map = new jsAst.ObjectInitializer(properties); | 1321 var map = new jsAst.ObjectInitializer(properties); |
1322 parts.add(js.statement('# = #', [mangledNamesAccess, map])); | 1322 parts.add(js.statement('# = #', [mangledNamesAccess, map])); |
1323 } | 1323 } |
1324 | 1324 |
1325 if (!mangledGlobalFieldNames.isEmpty) { | 1325 if (!mangledGlobalFieldNames.isEmpty) { |
1326 List<jsAst.Name> keys = mangledGlobalFieldNames.keys.toList() | 1326 List<jsAst.Name> keys = mangledGlobalFieldNames.keys.toList()..sort(); |
1327 ..sort(); | |
1328 List<jsAst.Property> properties = <jsAst.Property>[]; | 1327 List<jsAst.Property> properties = <jsAst.Property>[]; |
1329 for (jsAst.Name key in keys) { | 1328 for (jsAst.Name key in keys) { |
1330 jsAst.Literal value = js.string(mangledGlobalFieldNames[key]); | 1329 jsAst.Literal value = js.string(mangledGlobalFieldNames[key]); |
1331 properties.add(new jsAst.Property(js.quoteName(key), value)); | 1330 properties.add(new jsAst.Property(js.quoteName(key), value)); |
1332 } | 1331 } |
1333 jsAst.Expression mangledGlobalNamesAccess = | 1332 jsAst.Expression mangledGlobalNamesAccess = |
1334 generateEmbeddedGlobalAccess(embeddedNames.MANGLED_GLOBAL_NAMES); | 1333 generateEmbeddedGlobalAccess(embeddedNames.MANGLED_GLOBAL_NAMES); |
1335 jsAst.ObjectInitializer map = new jsAst.ObjectInitializer(properties); | 1334 jsAst.ObjectInitializer map = new jsAst.ObjectInitializer(properties); |
1336 parts.add(js.statement('# = #', [mangledGlobalNamesAccess, map])); | 1335 parts.add(js.statement('# = #', [mangledGlobalNamesAccess, map])); |
1337 } | 1336 } |
1338 | 1337 |
1339 return new jsAst.Block(parts); | 1338 return new jsAst.Block(parts); |
1340 } | 1339 } |
1341 | 1340 |
1342 void checkEverythingEmitted(Iterable<Element> elements) { | 1341 void checkEverythingEmitted(Iterable<Element> elements) { |
1343 List<Element> pendingStatics; | 1342 List<Element> pendingStatics; |
1344 if (!compiler.options.hasIncrementalSupport) { | 1343 if (!compiler.options.hasIncrementalSupport) { |
1345 pendingStatics = | 1344 pendingStatics = |
1346 Elements.sortedByPosition(elements.where((e) => !e.isLibrary)); | 1345 Elements.sortedByPosition(elements.where((e) => !e.isLibrary)); |
1347 | 1346 |
1348 pendingStatics.forEach((element) => | 1347 pendingStatics.forEach((element) => reporter.reportInfo( |
1349 reporter.reportInfo( | 1348 element, MessageKind.GENERIC, {'text': 'Pending statics.'})); |
1350 element, MessageKind.GENERIC, {'text': 'Pending statics.'})); | |
1351 } | 1349 } |
1352 | 1350 |
1353 if (pendingStatics != null && !pendingStatics.isEmpty) { | 1351 if (pendingStatics != null && !pendingStatics.isEmpty) { |
1354 reporter.internalError(pendingStatics.first, | 1352 reporter.internalError( |
1355 'Pending statics (see above).'); | 1353 pendingStatics.first, 'Pending statics (see above).'); |
1356 } | 1354 } |
1357 } | 1355 } |
1358 | 1356 |
1359 void assembleLibrary(Library library, Fragment fragment) { | 1357 void assembleLibrary(Library library, Fragment fragment) { |
1360 LibraryElement libraryElement = library.element; | 1358 LibraryElement libraryElement = library.element; |
1361 | 1359 |
1362 assembleStaticFunctions(library.statics, fragment); | 1360 assembleStaticFunctions(library.statics, fragment); |
1363 | 1361 |
1364 ClassBuilder libraryBuilder = | 1362 ClassBuilder libraryBuilder = |
1365 getElementDescriptor(libraryElement, fragment); | 1363 getElementDescriptor(libraryElement, fragment); |
(...skipping 11 matching lines...) Expand all Loading... |
1377 } | 1375 } |
1378 } | 1376 } |
1379 assembleTypedefs(program); | 1377 assembleTypedefs(program); |
1380 } | 1378 } |
1381 | 1379 |
1382 jsAst.Statement buildDeferredHeader() { | 1380 jsAst.Statement buildDeferredHeader() { |
1383 /// For deferred loading we communicate the initializers via this global | 1381 /// For deferred loading we communicate the initializers via this global |
1384 /// variable. The deferred hunks will add their initialization to this. | 1382 /// variable. The deferred hunks will add their initialization to this. |
1385 /// The semicolon is important in minified mode, without it the | 1383 /// The semicolon is important in minified mode, without it the |
1386 /// following parenthesis looks like a call to the object literal. | 1384 /// following parenthesis looks like a call to the object literal. |
1387 return js.statement('self.#deferredInitializers = ' | 1385 return js.statement( |
1388 'self.#deferredInitializers || Object.create(null);', | 1386 'self.#deferredInitializers = ' |
1389 {'deferredInitializers': deferredInitializers}); | 1387 'self.#deferredInitializers || Object.create(null);', |
| 1388 {'deferredInitializers': deferredInitializers}); |
1390 } | 1389 } |
1391 | 1390 |
1392 jsAst.Program buildOutputAstForMain(Program program, | 1391 jsAst.Program buildOutputAstForMain(Program program, |
1393 Map<OutputUnit, _DeferredOutputUnitHash> deferredLoadHashes) { | 1392 Map<OutputUnit, _DeferredOutputUnitHash> deferredLoadHashes) { |
1394 MainFragment mainFragment = program.mainFragment; | 1393 MainFragment mainFragment = program.mainFragment; |
1395 OutputUnit mainOutputUnit = mainFragment.outputUnit; | 1394 OutputUnit mainOutputUnit = mainFragment.outputUnit; |
1396 bool isProgramSplit = program.isSplit; | 1395 bool isProgramSplit = program.isSplit; |
1397 | 1396 |
1398 List<jsAst.Statement> statements = <jsAst.Statement>[]; | 1397 List<jsAst.Statement> statements = <jsAst.Statement>[]; |
1399 | 1398 |
1400 statements..add(buildGeneratedBy()) | 1399 statements..add(buildGeneratedBy())..add(js.comment(HOOKS_API_USAGE)); |
1401 ..add(js.comment(HOOKS_API_USAGE)); | |
1402 | 1400 |
1403 if (isProgramSplit) { | 1401 if (isProgramSplit) { |
1404 statements.add(buildDeferredHeader()); | 1402 statements.add(buildDeferredHeader()); |
1405 } | 1403 } |
1406 | 1404 |
1407 // Collect the AST for the decriptors | 1405 // Collect the AST for the decriptors |
1408 Map<Element, ClassBuilder> descriptors = elementDescriptors[mainFragment]; | 1406 Map<Element, ClassBuilder> descriptors = elementDescriptors[mainFragment]; |
1409 if (descriptors == null) descriptors = const {}; | 1407 if (descriptors == null) descriptors = const {}; |
1410 | 1408 |
1411 checkEverythingEmitted(descriptors.keys); | 1409 checkEverythingEmitted(descriptors.keys); |
1412 | 1410 |
1413 Iterable<LibraryElement> libraries = outputLibraryLists[mainOutputUnit]; | 1411 Iterable<LibraryElement> libraries = outputLibraryLists[mainOutputUnit]; |
1414 if (libraries == null) libraries = <LibraryElement>[]; | 1412 if (libraries == null) libraries = <LibraryElement>[]; |
1415 | 1413 |
1416 List<jsAst.Expression> parts = <jsAst.Expression>[]; | 1414 List<jsAst.Expression> parts = <jsAst.Expression>[]; |
1417 for (LibraryElement library in Elements.sortedByPosition(libraries)) { | 1415 for (LibraryElement library in Elements.sortedByPosition(libraries)) { |
1418 parts.add(generateLibraryDescriptor(library, mainFragment)); | 1416 parts.add(generateLibraryDescriptor(library, mainFragment)); |
1419 descriptors.remove(library); | 1417 descriptors.remove(library); |
1420 } | 1418 } |
1421 | 1419 |
1422 if (descriptors.isNotEmpty) { | 1420 if (descriptors.isNotEmpty) { |
1423 List<Element> remainingLibraries = descriptors.keys | 1421 List<Element> remainingLibraries = |
1424 .where((Element e) => e is LibraryElement) | 1422 descriptors.keys.where((Element e) => e is LibraryElement).toList(); |
1425 .toList(); | |
1426 | 1423 |
1427 // The remaining descriptors are only accessible through reflection. | 1424 // The remaining descriptors are only accessible through reflection. |
1428 // The program builder does not collect libraries that only | 1425 // The program builder does not collect libraries that only |
1429 // contain typedefs that are used for reflection. | 1426 // contain typedefs that are used for reflection. |
1430 for (LibraryElement element in remainingLibraries) { | 1427 for (LibraryElement element in remainingLibraries) { |
1431 assert(element is LibraryElement || | 1428 assert(element is LibraryElement || |
1432 compiler.options.hasIncrementalSupport); | 1429 compiler.options.hasIncrementalSupport); |
1433 if (element is LibraryElement) { | 1430 if (element is LibraryElement) { |
1434 parts.add(generateLibraryDescriptor(element, mainFragment)); | 1431 parts.add(generateLibraryDescriptor(element, mainFragment)); |
1435 descriptors.remove(element); | 1432 descriptors.remove(element); |
1436 } | 1433 } |
1437 } | 1434 } |
1438 } | 1435 } |
1439 jsAst.ArrayInitializer descriptorsAst = new jsAst.ArrayInitializer(parts); | 1436 jsAst.ArrayInitializer descriptorsAst = new jsAst.ArrayInitializer(parts); |
1440 | 1437 |
1441 // Using a named function here produces easier to read stack traces in | 1438 // Using a named function here produces easier to read stack traces in |
1442 // Chrome/V8. | 1439 // Chrome/V8. |
1443 statements.add(js.statement(""" | 1440 statements.add(js.statement( |
| 1441 """ |
1444 (function() { | 1442 (function() { |
1445 // No renaming in the top-level function to save the locals for the | 1443 // No renaming in the top-level function to save the locals for the |
1446 // nested context where they will be used more. We have to put the | 1444 // nested context where they will be used more. We have to put the |
1447 // comment into a hole as the parser strips out comments right away. | 1445 // comment into a hole as the parser strips out comments right away. |
1448 #disableVariableRenaming; | 1446 #disableVariableRenaming; |
1449 #supportsDirectProtoAccess; | 1447 #supportsDirectProtoAccess; |
1450 | 1448 |
1451 if (#hasIncrementalSupport) { | 1449 if (#hasIncrementalSupport) { |
1452 #helper = #helper || Object.create(null); | 1450 #helper = #helper || Object.create(null); |
1453 #helper.patch = function(a) { eval(a)}; | 1451 #helper.patch = function(a) { eval(a)}; |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1543 #convertToFastObject; | 1541 #convertToFastObject; |
1544 #convertToSlowObject; | 1542 #convertToSlowObject; |
1545 | 1543 |
1546 #convertGlobalObjectsToFastObjects; | 1544 #convertGlobalObjectsToFastObjects; |
1547 #debugFastObjects; | 1545 #debugFastObjects; |
1548 | 1546 |
1549 #init; | 1547 #init; |
1550 | 1548 |
1551 #main; | 1549 #main; |
1552 })(); | 1550 })(); |
1553 """, { | 1551 """, |
1554 "disableVariableRenaming": js.comment("/* ::norenaming:: */"), | 1552 { |
1555 "hasIncrementalSupport": compiler.options.hasIncrementalSupport, | 1553 "disableVariableRenaming": js.comment("/* ::norenaming:: */"), |
1556 "helper": js('this.#', [namer.incrementalHelperName]), | 1554 "hasIncrementalSupport": compiler.options.hasIncrementalSupport, |
1557 "schemaChange": buildSchemaChangeFunction(), | 1555 "helper": js('this.#', [namer.incrementalHelperName]), |
1558 "addMethod": buildIncrementalAddMethod(), | 1556 "schemaChange": buildSchemaChangeFunction(), |
1559 "isProgramSplit": isProgramSplit, | 1557 "addMethod": buildIncrementalAddMethod(), |
1560 "supportsDirectProtoAccess": buildSupportsDirectProtoAccess(), | 1558 "isProgramSplit": isProgramSplit, |
1561 "globalsHolder": globalsHolder, | 1559 "supportsDirectProtoAccess": buildSupportsDirectProtoAccess(), |
1562 "globalObjectSetup": buildGlobalObjectSetup(isProgramSplit), | 1560 "globalsHolder": globalsHolder, |
1563 "isolateName": namer.isolateName, | 1561 "globalObjectSetup": buildGlobalObjectSetup(isProgramSplit), |
1564 "isolatePropertiesName": js(isolatePropertiesName), | 1562 "isolateName": namer.isolateName, |
1565 "initName": initName, | 1563 "isolatePropertiesName": js(isolatePropertiesName), |
1566 "functionThatReturnsNull": buildFunctionThatReturnsNull(), | 1564 "initName": initName, |
1567 "mangledNames": buildMangledNames(), | 1565 "functionThatReturnsNull": buildFunctionThatReturnsNull(), |
1568 "setupProgram": buildSetupProgram(program, compiler, backend, namer, this)
, | 1566 "mangledNames": buildMangledNames(), |
1569 "setupProgramName": setupProgramName, | 1567 "setupProgram": |
1570 "descriptors": descriptorsAst, | 1568 buildSetupProgram(program, compiler, backend, namer, this), |
1571 "cspPrecompiledFunctions": buildCspPrecompiledFunctionFor(mainOutputUnit), | 1569 "setupProgramName": setupProgramName, |
1572 "getInterceptorMethods": interceptorEmitter.buildGetInterceptorMethods(), | 1570 "descriptors": descriptorsAst, |
1573 "oneShotInterceptors": interceptorEmitter.buildOneShotInterceptors(), | 1571 "cspPrecompiledFunctions": |
1574 "makeConstantList": | 1572 buildCspPrecompiledFunctionFor(mainOutputUnit), |
1575 buildMakeConstantList(program.outputContainsConstantList), | 1573 "getInterceptorMethods": |
1576 "compileTimeConstants": buildCompileTimeConstants(mainFragment.constants, | 1574 interceptorEmitter.buildGetInterceptorMethods(), |
1577 isMainFragment: true), | 1575 "oneShotInterceptors": interceptorEmitter.buildOneShotInterceptors(), |
1578 "deferredBoilerPlate": buildDeferredBoilerPlate(deferredLoadHashes), | 1576 "makeConstantList": |
1579 "staticNonFinalInitializers": buildStaticNonFinalFieldInitializations( | 1577 buildMakeConstantList(program.outputContainsConstantList), |
1580 mainOutputUnit), | 1578 "compileTimeConstants": buildCompileTimeConstants( |
1581 "typeToInterceptorMap": | 1579 mainFragment.constants, |
1582 interceptorEmitter.buildTypeToInterceptorMap(program), | 1580 isMainFragment: true), |
1583 "lazyStaticFields": buildLazilyInitializedStaticFields( | 1581 "deferredBoilerPlate": buildDeferredBoilerPlate(deferredLoadHashes), |
1584 mainFragment.staticLazilyInitializedFields), | 1582 "staticNonFinalInitializers": |
1585 "metadata": buildMetadata(program, mainOutputUnit), | 1583 buildStaticNonFinalFieldInitializations(mainOutputUnit), |
1586 "convertToFastObject": buildConvertToFastObjectFunction(), | 1584 "typeToInterceptorMap": |
1587 "convertToSlowObject": buildConvertToSlowObjectFunction(), | 1585 interceptorEmitter.buildTypeToInterceptorMap(program), |
1588 "convertGlobalObjectsToFastObjects": | 1586 "lazyStaticFields": buildLazilyInitializedStaticFields( |
1589 buildConvertGlobalObjectToFastObjects(), | 1587 mainFragment.staticLazilyInitializedFields), |
1590 "debugFastObjects": buildDebugFastObjectCode(), | 1588 "metadata": buildMetadata(program, mainOutputUnit), |
1591 "init": buildInitFunction(program.outputContainsConstantList), | 1589 "convertToFastObject": buildConvertToFastObjectFunction(), |
1592 "main": buildMain(mainFragment.invokeMain) | 1590 "convertToSlowObject": buildConvertToSlowObjectFunction(), |
1593 })); | 1591 "convertGlobalObjectsToFastObjects": |
| 1592 buildConvertGlobalObjectToFastObjects(), |
| 1593 "debugFastObjects": buildDebugFastObjectCode(), |
| 1594 "init": buildInitFunction(program.outputContainsConstantList), |
| 1595 "main": buildMain(mainFragment.invokeMain) |
| 1596 })); |
1594 | 1597 |
1595 return new jsAst.Program(statements); | 1598 return new jsAst.Program(statements); |
1596 } | 1599 } |
1597 | 1600 |
1598 void emitMainOutputUnit(OutputUnit mainOutputUnit, jsAst.Program program) { | 1601 void emitMainOutputUnit(OutputUnit mainOutputUnit, jsAst.Program program) { |
1599 LineColumnCollector lineColumnCollector; | 1602 LineColumnCollector lineColumnCollector; |
1600 List<CodeOutputListener> codeOutputListeners; | 1603 List<CodeOutputListener> codeOutputListeners; |
1601 if (generateSourceMap) { | 1604 if (generateSourceMap) { |
1602 lineColumnCollector = new LineColumnCollector(); | 1605 lineColumnCollector = new LineColumnCollector(); |
1603 codeOutputListeners = <CodeOutputListener>[lineColumnCollector]; | 1606 codeOutputListeners = <CodeOutputListener>[lineColumnCollector]; |
1604 } | 1607 } |
1605 | 1608 |
1606 CodeOutput mainOutput = | 1609 CodeOutput mainOutput = new StreamCodeOutput( |
1607 new StreamCodeOutput(compiler.outputProvider('', 'js'), | 1610 compiler.outputProvider('', 'js'), codeOutputListeners); |
1608 codeOutputListeners); | |
1609 outputBuffers[mainOutputUnit] = mainOutput; | 1611 outputBuffers[mainOutputUnit] = mainOutput; |
1610 | 1612 |
1611 | 1613 mainOutput.addBuffer(jsAst.createCodeBuffer(program, compiler, |
1612 mainOutput.addBuffer(jsAst.createCodeBuffer( | 1614 monitor: compiler.dumpInfoTask)); |
1613 program, compiler, monitor: compiler.dumpInfoTask)); | |
1614 | 1615 |
1615 if (compiler.options.deferredMapUri != null) { | 1616 if (compiler.options.deferredMapUri != null) { |
1616 outputDeferredMap(); | 1617 outputDeferredMap(); |
1617 } | 1618 } |
1618 | 1619 |
1619 if (generateSourceMap) { | 1620 if (generateSourceMap) { |
1620 mainOutput.add(generateSourceMapTag( | 1621 mainOutput.add(generateSourceMapTag( |
1621 compiler.options.sourceMapUri, compiler.options.outputUri)); | 1622 compiler.options.sourceMapUri, compiler.options.outputUri)); |
1622 } | 1623 } |
1623 | 1624 |
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1767 descriptors.remove(library); | 1768 descriptors.remove(library); |
1768 } | 1769 } |
1769 | 1770 |
1770 outputs[outputUnit] = new jsAst.ArrayInitializer(parts); | 1771 outputs[outputUnit] = new jsAst.ArrayInitializer(parts); |
1771 } | 1772 } |
1772 } | 1773 } |
1773 | 1774 |
1774 return outputs; | 1775 return outputs; |
1775 } | 1776 } |
1776 | 1777 |
1777 void finalizeTokensInAst(jsAst.Program main, | 1778 void finalizeTokensInAst( |
1778 Iterable<jsAst.Program> deferredParts) { | 1779 jsAst.Program main, Iterable<jsAst.Program> deferredParts) { |
1779 jsAst.TokenCounter counter = new jsAst.TokenCounter(); | 1780 jsAst.TokenCounter counter = new jsAst.TokenCounter(); |
1780 counter.countTokens(main); | 1781 counter.countTokens(main); |
1781 deferredParts.forEach(counter.countTokens); | 1782 deferredParts.forEach(counter.countTokens); |
1782 task.metadataCollector.finalizeTokens(); | 1783 task.metadataCollector.finalizeTokens(); |
1783 if (backend.namer is jsAst.TokenFinalizer) { | 1784 if (backend.namer is jsAst.TokenFinalizer) { |
1784 var finalizer = backend.namer; | 1785 var finalizer = backend.namer; |
1785 finalizer.finalizeTokens(); | 1786 finalizer.finalizeTokens(); |
1786 } | 1787 } |
1787 } | 1788 } |
1788 | 1789 |
1789 int emitProgram(ProgramBuilder programBuilder) { | 1790 int emitProgram(ProgramBuilder programBuilder) { |
1790 Program program = | 1791 Program program = |
1791 programBuilder.buildProgram(storeFunctionTypesInMetadata: true); | 1792 programBuilder.buildProgram(storeFunctionTypesInMetadata: true); |
1792 | 1793 |
1793 outputStaticNonFinalFieldLists = | 1794 outputStaticNonFinalFieldLists = |
1794 programBuilder.collector.outputStaticNonFinalFieldLists; | 1795 programBuilder.collector.outputStaticNonFinalFieldLists; |
1795 outputLibraryLists = programBuilder.collector.outputLibraryLists; | 1796 outputLibraryLists = programBuilder.collector.outputLibraryLists; |
1796 typedefsNeededForReflection = | 1797 typedefsNeededForReflection = |
1797 programBuilder.collector.typedefsNeededForReflection; | 1798 programBuilder.collector.typedefsNeededForReflection; |
1798 | 1799 |
1799 assembleProgram(program); | 1800 assembleProgram(program); |
1800 | 1801 |
1801 // Construct the ASTs for all deferred output units. | 1802 // Construct the ASTs for all deferred output units. |
1802 Map<OutputUnit, jsAst.Program> deferredParts = | 1803 Map<OutputUnit, jsAst.Program> deferredParts = |
1803 buildOutputAstForDeferredCode(program); | 1804 buildOutputAstForDeferredCode(program); |
1804 | 1805 |
1805 Map<OutputUnit, _DeferredOutputUnitHash> deferredHashTokens = | 1806 Map<OutputUnit, _DeferredOutputUnitHash> deferredHashTokens = |
1806 new Map<OutputUnit, _DeferredOutputUnitHash>.fromIterables( | 1807 new Map<OutputUnit, _DeferredOutputUnitHash>.fromIterables( |
1807 deferredParts.keys, | 1808 deferredParts.keys, deferredParts.keys.map((OutputUnit unit) { |
1808 deferredParts.keys.map((OutputUnit unit) { | 1809 return new _DeferredOutputUnitHash(unit); |
1809 return new _DeferredOutputUnitHash(unit); | 1810 })); |
1810 }) | |
1811 ); | |
1812 | 1811 |
1813 jsAst.Program mainOutput = | 1812 jsAst.Program mainOutput = |
1814 buildOutputAstForMain(program, deferredHashTokens); | 1813 buildOutputAstForMain(program, deferredHashTokens); |
1815 | 1814 |
1816 finalizeTokensInAst(mainOutput, deferredParts.values); | 1815 finalizeTokensInAst(mainOutput, deferredParts.values); |
1817 | 1816 |
1818 // Emit deferred units first, so we have their hashes. | 1817 // Emit deferred units first, so we have their hashes. |
1819 // Map from OutputUnit to a hash of its content. The hash uniquely | 1818 // Map from OutputUnit to a hash of its content. The hash uniquely |
1820 // identifies the code of the output-unit. It does not include | 1819 // identifies the code of the output-unit. It does not include |
1821 // boilerplate JS code, like the sourcemap directives or the hash | 1820 // boilerplate JS code, like the sourcemap directives or the hash |
1822 // itself. | 1821 // itself. |
1823 Map<OutputUnit, String> deferredLoadHashes = | 1822 Map<OutputUnit, String> deferredLoadHashes = |
1824 emitDeferredOutputUnits(deferredParts); | 1823 emitDeferredOutputUnits(deferredParts); |
1825 | 1824 |
1826 deferredHashTokens.forEach((OutputUnit key, _DeferredOutputUnitHash token) { | 1825 deferredHashTokens.forEach((OutputUnit key, _DeferredOutputUnitHash token) { |
1827 token.setHash(deferredLoadHashes[key]); | 1826 token.setHash(deferredLoadHashes[key]); |
1828 }); | 1827 }); |
1829 emitMainOutputUnit(program.mainFragment.outputUnit, mainOutput); | 1828 emitMainOutputUnit(program.mainFragment.outputUnit, mainOutput); |
1830 | 1829 |
1831 if (backend.requiresPreamble && | 1830 if (backend.requiresPreamble && !backend.htmlLibraryIsLoaded) { |
1832 !backend.htmlLibraryIsLoaded) { | 1831 reporter.reportHintMessage(NO_LOCATION_SPANNABLE, MessageKind.PREAMBLE); |
1833 reporter.reportHintMessage( | |
1834 NO_LOCATION_SPANNABLE, MessageKind.PREAMBLE); | |
1835 } | 1832 } |
1836 // Return the total program size. | 1833 // Return the total program size. |
1837 return outputBuffers.values.fold(0, (a, b) => a + b.length); | 1834 return outputBuffers.values.fold(0, (a, b) => a + b.length); |
1838 } | 1835 } |
1839 | 1836 |
1840 String generateSourceMapTag(Uri sourceMapUri, Uri fileUri) { | 1837 String generateSourceMapTag(Uri sourceMapUri, Uri fileUri) { |
1841 if (sourceMapUri != null && fileUri != null) { | 1838 if (sourceMapUri != null && fileUri != null) { |
1842 String sourceMapFileName = relativize(fileUri, sourceMapUri, false); | 1839 String sourceMapFileName = relativize(fileUri, sourceMapUri, false); |
1843 return ''' | 1840 return ''' |
1844 | 1841 |
1845 //# sourceMappingURL=$sourceMapFileName | 1842 //# sourceMappingURL=$sourceMapFileName |
1846 '''; | 1843 '''; |
1847 } | 1844 } |
1848 return ''; | 1845 return ''; |
1849 } | 1846 } |
1850 | 1847 |
1851 ClassBuilder getElementDescriptor(Element element, Fragment fragment) { | 1848 ClassBuilder getElementDescriptor(Element element, Fragment fragment) { |
1852 Element owner = element.library; | 1849 Element owner = element.library; |
1853 if (!element.isLibrary && | 1850 if (!element.isLibrary && |
1854 !element.isTopLevel && | 1851 !element.isTopLevel && |
1855 !backend.isNative(element)) { | 1852 !backend.isNative(element)) { |
1856 // For static (not top level) elements, record their code in a buffer | 1853 // For static (not top level) elements, record their code in a buffer |
1857 // specific to the class. For now, not supported for native classes and | 1854 // specific to the class. For now, not supported for native classes and |
1858 // native elements. | 1855 // native elements. |
1859 ClassElement cls = | 1856 ClassElement cls = element.enclosingClassOrCompilationUnit.declaration; |
1860 element.enclosingClassOrCompilationUnit.declaration; | |
1861 if (compiler.codegenWorld.directlyInstantiatedClasses.contains(cls) && | 1857 if (compiler.codegenWorld.directlyInstantiatedClasses.contains(cls) && |
1862 !backend.isNative(cls) && | 1858 !backend.isNative(cls) && |
1863 compiler.deferredLoadTask.outputUnitForElement(element) == | 1859 compiler.deferredLoadTask.outputUnitForElement(element) == |
1864 compiler.deferredLoadTask.outputUnitForElement(cls)) { | 1860 compiler.deferredLoadTask.outputUnitForElement(cls)) { |
1865 owner = cls; | 1861 owner = cls; |
1866 } | 1862 } |
1867 } | 1863 } |
1868 if (owner == null) { | 1864 if (owner == null) { |
1869 reporter.internalError(element, 'Owner is null.'); | 1865 reporter.internalError(element, 'Owner is null.'); |
1870 } | 1866 } |
1871 return elementDescriptors | 1867 return elementDescriptors |
1872 .putIfAbsent(fragment, () => new Map<Element, ClassBuilder>()) | 1868 .putIfAbsent(fragment, () => new Map<Element, ClassBuilder>()) |
1873 .putIfAbsent(owner, () { | 1869 .putIfAbsent(owner, () { |
1874 return new ClassBuilder(owner, namer, owner.isClass); | 1870 return new ClassBuilder(owner, namer, owner.isClass); |
1875 }); | 1871 }); |
1876 } | 1872 } |
1877 | 1873 |
1878 /// Emits support-code for deferred loading into [output]. | 1874 /// Emits support-code for deferred loading into [output]. |
1879 jsAst.Statement buildDeferredBoilerPlate( | 1875 jsAst.Statement buildDeferredBoilerPlate( |
1880 Map<OutputUnit, _DeferredOutputUnitHash> deferredLoadHashes) { | 1876 Map<OutputUnit, _DeferredOutputUnitHash> deferredLoadHashes) { |
1881 List<jsAst.Statement> parts = <jsAst.Statement>[]; | 1877 List<jsAst.Statement> parts = <jsAst.Statement>[]; |
1882 | 1878 |
1883 parts.add(js.statement(''' | 1879 parts.add(js.statement( |
| 1880 ''' |
1884 { | 1881 { |
1885 // Function for checking if a hunk is loaded given its hash. | 1882 // Function for checking if a hunk is loaded given its hash. |
1886 #isHunkLoaded = function(hunkHash) { | 1883 #isHunkLoaded = function(hunkHash) { |
1887 return !!$deferredInitializers[hunkHash]; | 1884 return !!$deferredInitializers[hunkHash]; |
1888 }; | 1885 }; |
1889 #deferredInitialized = new Object(null); | 1886 #deferredInitialized = new Object(null); |
1890 // Function for checking if a hunk is initialized given its hash. | 1887 // Function for checking if a hunk is initialized given its hash. |
1891 #isHunkInitialized = function(hunkHash) { | 1888 #isHunkInitialized = function(hunkHash) { |
1892 return #deferredInitialized[hunkHash]; | 1889 return #deferredInitialized[hunkHash]; |
1893 }; | 1890 }; |
1894 // Function for initializing a loaded hunk, given its hash. | 1891 // Function for initializing a loaded hunk, given its hash. |
1895 #initializeLoadedHunk = function(hunkHash) { | 1892 #initializeLoadedHunk = function(hunkHash) { |
1896 $deferredInitializers[hunkHash]( | 1893 $deferredInitializers[hunkHash]( |
1897 #globalsHolder, ${namer.staticStateHolder}); | 1894 #globalsHolder, ${namer.staticStateHolder}); |
1898 #deferredInitialized[hunkHash] = true; | 1895 #deferredInitialized[hunkHash] = true; |
1899 }; | 1896 }; |
1900 } | 1897 } |
1901 ''', {"globalsHolder": globalsHolder, | 1898 ''', |
1902 "isHunkLoaded": generateEmbeddedGlobalAccess( | 1899 { |
1903 embeddedNames.IS_HUNK_LOADED), | 1900 "globalsHolder": globalsHolder, |
1904 "isHunkInitialized": generateEmbeddedGlobalAccess( | 1901 "isHunkLoaded": |
1905 embeddedNames.IS_HUNK_INITIALIZED), | 1902 generateEmbeddedGlobalAccess(embeddedNames.IS_HUNK_LOADED), |
1906 "initializeLoadedHunk": generateEmbeddedGlobalAccess( | 1903 "isHunkInitialized": |
1907 embeddedNames.INITIALIZE_LOADED_HUNK), | 1904 generateEmbeddedGlobalAccess(embeddedNames.IS_HUNK_INITIALIZED), |
1908 "deferredInitialized": generateEmbeddedGlobalAccess( | 1905 "initializeLoadedHunk": generateEmbeddedGlobalAccess( |
1909 embeddedNames.DEFERRED_INITIALIZED)})); | 1906 embeddedNames.INITIALIZE_LOADED_HUNK), |
| 1907 "deferredInitialized": |
| 1908 generateEmbeddedGlobalAccess(embeddedNames.DEFERRED_INITIALIZED) |
| 1909 })); |
1910 | 1910 |
1911 // Write a javascript mapping from Deferred import load ids (derrived | 1911 // Write a javascript mapping from Deferred import load ids (derrived |
1912 // from the import prefix.) to a list of lists of uris of hunks to load, | 1912 // from the import prefix.) to a list of lists of uris of hunks to load, |
1913 // and a corresponding mapping to a list of hashes used by | 1913 // and a corresponding mapping to a list of hashes used by |
1914 // INITIALIZE_LOADED_HUNK and IS_HUNK_LOADED. | 1914 // INITIALIZE_LOADED_HUNK and IS_HUNK_LOADED. |
1915 Map<String, List<jsAst.LiteralString>> deferredLibraryUris = | 1915 Map<String, List<jsAst.LiteralString>> deferredLibraryUris = |
1916 new Map<String, List<jsAst.LiteralString>>(); | 1916 new Map<String, List<jsAst.LiteralString>>(); |
1917 Map<String, List<_DeferredOutputUnitHash>> deferredLibraryHashes = | 1917 Map<String, List<_DeferredOutputUnitHash>> deferredLibraryHashes = |
1918 new Map<String, List<_DeferredOutputUnitHash>>(); | 1918 new Map<String, List<_DeferredOutputUnitHash>>(); |
1919 compiler.deferredLoadTask.hunksToLoad.forEach( | 1919 compiler.deferredLoadTask.hunksToLoad |
1920 (String loadId, List<OutputUnit>outputUnits) { | 1920 .forEach((String loadId, List<OutputUnit> outputUnits) { |
1921 List<jsAst.LiteralString> uris = new List<jsAst.LiteralString>(); | 1921 List<jsAst.LiteralString> uris = new List<jsAst.LiteralString>(); |
1922 List<_DeferredOutputUnitHash> hashes = | 1922 List<_DeferredOutputUnitHash> hashes = |
1923 new List<_DeferredOutputUnitHash>(); | 1923 new List<_DeferredOutputUnitHash>(); |
1924 deferredLibraryHashes[loadId] = new List<_DeferredOutputUnitHash>(); | 1924 deferredLibraryHashes[loadId] = new List<_DeferredOutputUnitHash>(); |
1925 for (OutputUnit outputUnit in outputUnits) { | 1925 for (OutputUnit outputUnit in outputUnits) { |
1926 uris.add(js.escapedString( | 1926 uris.add( |
1927 backend.deferredPartFileName(outputUnit.name))); | 1927 js.escapedString(backend.deferredPartFileName(outputUnit.name))); |
1928 hashes.add(deferredLoadHashes[outputUnit]); | 1928 hashes.add(deferredLoadHashes[outputUnit]); |
1929 } | 1929 } |
1930 | 1930 |
1931 deferredLibraryUris[loadId] = uris; | 1931 deferredLibraryUris[loadId] = uris; |
1932 deferredLibraryHashes[loadId] = hashes; | 1932 deferredLibraryHashes[loadId] = hashes; |
1933 }); | 1933 }); |
1934 | 1934 |
1935 void emitMapping(String name, Map<String, List<jsAst.Expression>> mapping) { | 1935 void emitMapping(String name, Map<String, List<jsAst.Expression>> mapping) { |
1936 List<jsAst.Property> properties = new List<jsAst.Property>(); | 1936 List<jsAst.Property> properties = new List<jsAst.Property>(); |
1937 mapping.forEach((String key, List<jsAst.Expression> values) { | 1937 mapping.forEach((String key, List<jsAst.Expression> values) { |
1938 properties.add(new jsAst.Property(js.escapedString(key), | 1938 properties.add(new jsAst.Property( |
1939 new jsAst.ArrayInitializer(values))); | 1939 js.escapedString(key), new jsAst.ArrayInitializer(values))); |
1940 }); | 1940 }); |
1941 jsAst.Node initializer = | 1941 jsAst.Node initializer = |
1942 new jsAst.ObjectInitializer(properties, isOneLiner: true); | 1942 new jsAst.ObjectInitializer(properties, isOneLiner: true); |
1943 | 1943 |
1944 jsAst.Node globalName = generateEmbeddedGlobalAccess(name); | 1944 jsAst.Node globalName = generateEmbeddedGlobalAccess(name); |
1945 parts.add(js.statement("# = #", [globalName, initializer])); | 1945 parts.add(js.statement("# = #", [globalName, initializer])); |
1946 } | 1946 } |
1947 | 1947 |
1948 emitMapping(embeddedNames.DEFERRED_LIBRARY_URIS, deferredLibraryUris); | 1948 emitMapping(embeddedNames.DEFERRED_LIBRARY_URIS, deferredLibraryUris); |
1949 emitMapping(embeddedNames.DEFERRED_LIBRARY_HASHES, | 1949 emitMapping(embeddedNames.DEFERRED_LIBRARY_HASHES, deferredLibraryHashes); |
1950 deferredLibraryHashes); | |
1951 | 1950 |
1952 return new jsAst.Block(parts); | 1951 return new jsAst.Block(parts); |
1953 } | 1952 } |
1954 | 1953 |
1955 Map <OutputUnit, jsAst.Program> buildOutputAstForDeferredCode( | 1954 Map<OutputUnit, jsAst.Program> buildOutputAstForDeferredCode( |
1956 Program program) { | 1955 Program program) { |
1957 if (!program.isSplit) return const <OutputUnit, jsAst.Program>{}; | 1956 if (!program.isSplit) return const <OutputUnit, jsAst.Program>{}; |
1958 | 1957 |
1959 Map<OutputUnit, jsAst.Program> result = | 1958 Map<OutputUnit, jsAst.Program> result = |
1960 new Map<OutputUnit, jsAst.Program>(); | 1959 new Map<OutputUnit, jsAst.Program>(); |
1961 | 1960 |
1962 Map<OutputUnit, jsAst.Expression> deferredAsts = | 1961 Map<OutputUnit, jsAst.Expression> deferredAsts = |
1963 buildDescriptorsForOutputUnits(program); | 1962 buildDescriptorsForOutputUnits(program); |
1964 | 1963 |
1965 for (Fragment fragment in program.deferredFragments) { | 1964 for (Fragment fragment in program.deferredFragments) { |
1966 OutputUnit outputUnit = fragment.outputUnit; | 1965 OutputUnit outputUnit = fragment.outputUnit; |
1967 jsAst.Expression libraryDescriptor = deferredAsts[outputUnit]; | 1966 jsAst.Expression libraryDescriptor = deferredAsts[outputUnit]; |
1968 List<jsAst.Statement> body = <jsAst.Statement>[]; | 1967 List<jsAst.Statement> body = <jsAst.Statement>[]; |
1969 | 1968 |
1970 // No renaming in the top-level function to save the locals for the | 1969 // No renaming in the top-level function to save the locals for the |
1971 // nested context where they will be used more. | 1970 // nested context where they will be used more. |
1972 body.add(js.comment("/* ::norenaming:: ")); | 1971 body.add(js.comment("/* ::norenaming:: ")); |
1973 | 1972 |
1974 for (String globalObject in Namer.reservedGlobalObjectNames) { | 1973 for (String globalObject in Namer.reservedGlobalObjectNames) { |
1975 body.add(js.statement('var #object = #globalsHolder.#object;', | 1974 body.add(js.statement('var #object = #globalsHolder.#object;', |
1976 {'globalsHolder': globalsHolder, | 1975 {'globalsHolder': globalsHolder, 'object': globalObject})); |
1977 'object': globalObject})); | |
1978 } | 1976 } |
1979 body..add(js.statement('var init = #globalsHolder.init;', | 1977 body |
1980 {'globalsHolder': globalsHolder})) | 1978 ..add(js.statement('var init = #globalsHolder.init;', |
1981 ..add(js.statement('var $setupProgramName = ' | 1979 {'globalsHolder': globalsHolder})) |
1982 '#globalsHolder.$setupProgramName;', | 1980 ..add(js.statement( |
1983 {'globalsHolder': globalsHolder})) | 1981 'var $setupProgramName = ' |
1984 ..add(js.statement('var ${namer.isolateName} = ' | 1982 '#globalsHolder.$setupProgramName;', |
1985 '#globalsHolder.${namer.isolateName};', | 1983 {'globalsHolder': globalsHolder})) |
1986 {'globalsHolder': globalsHolder})); | 1984 ..add(js.statement( |
| 1985 'var ${namer.isolateName} = ' |
| 1986 '#globalsHolder.${namer.isolateName};', |
| 1987 {'globalsHolder': globalsHolder})); |
1987 String typesAccess = | 1988 String typesAccess = |
1988 generateEmbeddedGlobalAccessString(embeddedNames.TYPES); | 1989 generateEmbeddedGlobalAccessString(embeddedNames.TYPES); |
1989 if (libraryDescriptor != null) { | 1990 if (libraryDescriptor != null) { |
1990 // The argument to reflectionDataParser is assigned to a temporary | 1991 // The argument to reflectionDataParser is assigned to a temporary |
1991 // 'dart' so that 'dart.' will appear as the prefix to dart methods | 1992 // 'dart' so that 'dart.' will appear as the prefix to dart methods |
1992 // in stack traces and profile entries. | 1993 // in stack traces and profile entries. |
1993 body.add(js.statement('var dart = #', libraryDescriptor)); | 1994 body.add(js.statement('var dart = #', libraryDescriptor)); |
1994 | 1995 |
1995 if (compiler.options.useContentSecurityPolicy) { | 1996 if (compiler.options.useContentSecurityPolicy) { |
1996 body.add(buildCspPrecompiledFunctionFor(outputUnit)); | 1997 body.add(buildCspPrecompiledFunctionFor(outputUnit)); |
1997 } | 1998 } |
1998 body.add( | 1999 body.add( |
1999 js.statement('$setupProgramName(dart, ${typesAccess}.length);')); | 2000 js.statement('$setupProgramName(dart, ${typesAccess}.length);')); |
2000 } | 2001 } |
2001 | 2002 |
2002 body..add(buildMetadata(program, outputUnit)) | 2003 body |
2003 ..add(js.statement('${typesAccess}.push.apply(${typesAccess}, ' | 2004 ..add(buildMetadata(program, outputUnit)) |
2004 '${namer.deferredTypesName});')); | 2005 ..add(js.statement('${typesAccess}.push.apply(${typesAccess}, ' |
| 2006 '${namer.deferredTypesName});')); |
2005 | 2007 |
2006 body.add(buildCompileTimeConstants(fragment.constants, | 2008 body.add( |
2007 isMainFragment: false)); | 2009 buildCompileTimeConstants(fragment.constants, isMainFragment: false)); |
2008 body.add(buildStaticNonFinalFieldInitializations(outputUnit)); | 2010 body.add(buildStaticNonFinalFieldInitializations(outputUnit)); |
2009 body.add(buildLazilyInitializedStaticFields( | 2011 body.add(buildLazilyInitializedStaticFields( |
2010 fragment.staticLazilyInitializedFields, isMainFragment: false)); | 2012 fragment.staticLazilyInitializedFields, |
| 2013 isMainFragment: false)); |
2011 | 2014 |
2012 List<jsAst.Statement> statements = <jsAst.Statement>[]; | 2015 List<jsAst.Statement> statements = <jsAst.Statement>[]; |
2013 | 2016 |
2014 statements | 2017 statements |
2015 ..add(buildGeneratedBy()) | 2018 ..add(buildGeneratedBy()) |
2016 ..add(buildDeferredHeader()) | 2019 ..add(buildDeferredHeader()) |
2017 ..add(js.statement('${deferredInitializers}.current = ' | 2020 ..add(js.statement( |
2018 """function (#, ${namer.staticStateHolder}) { | 2021 '${deferredInitializers}.current = ' |
| 2022 """function (#, ${namer.staticStateHolder}) { |
2019 # | 2023 # |
2020 } | 2024 } |
2021 """, [globalsHolder, body])); | 2025 """, |
| 2026 [globalsHolder, body])); |
2022 | 2027 |
2023 result[outputUnit] = new jsAst.Program(statements); | 2028 result[outputUnit] = new jsAst.Program(statements); |
2024 } | 2029 } |
2025 | 2030 |
2026 return result; | 2031 return result; |
2027 } | 2032 } |
2028 | 2033 |
2029 /// Returns a map from OutputUnit to a hash of its content. The hash uniquely | 2034 /// Returns a map from OutputUnit to a hash of its content. The hash uniquely |
2030 /// identifies the code of the output-unit. It does not include | 2035 /// identifies the code of the output-unit. It does not include |
2031 /// boilerplate JS code, like the sourcemap directives or the hash | 2036 /// boilerplate JS code, like the sourcemap directives or the hash |
2032 /// itself. | 2037 /// itself. |
2033 Map<OutputUnit, String> emitDeferredOutputUnits( | 2038 Map<OutputUnit, String> emitDeferredOutputUnits( |
2034 Map<OutputUnit, jsAst.Program> outputAsts) { | 2039 Map<OutputUnit, jsAst.Program> outputAsts) { |
2035 | |
2036 Map<OutputUnit, String> hunkHashes = new Map<OutputUnit, String>(); | 2040 Map<OutputUnit, String> hunkHashes = new Map<OutputUnit, String>(); |
2037 | 2041 |
2038 for (OutputUnit outputUnit in outputAsts.keys) { | 2042 for (OutputUnit outputUnit in outputAsts.keys) { |
2039 List<CodeOutputListener> outputListeners = <CodeOutputListener>[]; | 2043 List<CodeOutputListener> outputListeners = <CodeOutputListener>[]; |
2040 Hasher hasher = new Hasher(); | 2044 Hasher hasher = new Hasher(); |
2041 outputListeners.add(hasher); | 2045 outputListeners.add(hasher); |
2042 | 2046 |
2043 LineColumnCollector lineColumnCollector; | 2047 LineColumnCollector lineColumnCollector; |
2044 if (generateSourceMap) { | 2048 if (generateSourceMap) { |
2045 lineColumnCollector = new LineColumnCollector(); | 2049 lineColumnCollector = new LineColumnCollector(); |
2046 outputListeners.add(lineColumnCollector); | 2050 outputListeners.add(lineColumnCollector); |
2047 } | 2051 } |
2048 | 2052 |
2049 String partPrefix = | 2053 String partPrefix = |
2050 backend.deferredPartFileName(outputUnit.name, addExtension: false); | 2054 backend.deferredPartFileName(outputUnit.name, addExtension: false); |
2051 CodeOutput output = new StreamCodeOutput( | 2055 CodeOutput output = new StreamCodeOutput( |
2052 compiler.outputProvider(partPrefix, 'part.js'), | 2056 compiler.outputProvider(partPrefix, 'part.js'), outputListeners); |
2053 outputListeners); | |
2054 | 2057 |
2055 outputBuffers[outputUnit] = output; | 2058 outputBuffers[outputUnit] = output; |
2056 | 2059 |
2057 output.addBuffer(jsAst.createCodeBuffer( | 2060 output.addBuffer(jsAst.createCodeBuffer(outputAsts[outputUnit], compiler, |
2058 outputAsts[outputUnit], compiler, monitor: compiler.dumpInfoTask)); | 2061 monitor: compiler.dumpInfoTask)); |
2059 | 2062 |
2060 // Make a unique hash of the code (before the sourcemaps are added) | 2063 // Make a unique hash of the code (before the sourcemaps are added) |
2061 // This will be used to retrieve the initializing function from the global | 2064 // This will be used to retrieve the initializing function from the global |
2062 // variable. | 2065 // variable. |
2063 String hash = hasher.getHash(); | 2066 String hash = hasher.getHash(); |
2064 | 2067 |
2065 output.add('$N${deferredInitializers}["$hash"]$_=$_' | 2068 output.add('$N${deferredInitializers}["$hash"]$_=$_' |
2066 '${deferredInitializers}.current$N'); | 2069 '${deferredInitializers}.current$N'); |
2067 | 2070 |
2068 if (generateSourceMap) { | 2071 if (generateSourceMap) { |
2069 Uri mapUri, partUri; | 2072 Uri mapUri, partUri; |
2070 Uri sourceMapUri = compiler.options.sourceMapUri; | 2073 Uri sourceMapUri = compiler.options.sourceMapUri; |
2071 Uri outputUri = compiler.options.outputUri; | 2074 Uri outputUri = compiler.options.outputUri; |
2072 | 2075 |
2073 String partName = "$partPrefix.part"; | 2076 String partName = "$partPrefix.part"; |
2074 | 2077 |
2075 if (sourceMapUri != null) { | 2078 if (sourceMapUri != null) { |
2076 String mapFileName = partName + ".js.map"; | 2079 String mapFileName = partName + ".js.map"; |
2077 List<String> mapSegments = sourceMapUri.pathSegments.toList(); | 2080 List<String> mapSegments = sourceMapUri.pathSegments.toList(); |
2078 mapSegments[mapSegments.length - 1] = mapFileName; | 2081 mapSegments[mapSegments.length - 1] = mapFileName; |
2079 mapUri = compiler.options.sourceMapUri | 2082 mapUri = |
2080 .replace(pathSegments: mapSegments); | 2083 compiler.options.sourceMapUri.replace(pathSegments: mapSegments); |
2081 } | 2084 } |
2082 | 2085 |
2083 if (outputUri != null) { | 2086 if (outputUri != null) { |
2084 String partFileName = partName + ".js"; | 2087 String partFileName = partName + ".js"; |
2085 List<String> partSegments = outputUri.pathSegments.toList(); | 2088 List<String> partSegments = outputUri.pathSegments.toList(); |
2086 partSegments[partSegments.length - 1] = partFileName; | 2089 partSegments[partSegments.length - 1] = partFileName; |
2087 partUri = compiler.options.outputUri.replace( | 2090 partUri = |
2088 pathSegments: partSegments); | 2091 compiler.options.outputUri.replace(pathSegments: partSegments); |
2089 } | 2092 } |
2090 | 2093 |
2091 output.add(generateSourceMapTag(mapUri, partUri)); | 2094 output.add(generateSourceMapTag(mapUri, partUri)); |
2092 output.close(); | 2095 output.close(); |
2093 outputSourceMap(output, lineColumnCollector, partName, | 2096 outputSourceMap(output, lineColumnCollector, partName, mapUri, partUri); |
2094 mapUri, partUri); | |
2095 } else { | 2097 } else { |
2096 output.close(); | 2098 output.close(); |
2097 } | 2099 } |
2098 | 2100 |
2099 hunkHashes[outputUnit] = hash; | 2101 hunkHashes[outputUnit] = hash; |
2100 } | 2102 } |
2101 return hunkHashes; | 2103 return hunkHashes; |
2102 } | 2104 } |
2103 | 2105 |
2104 jsAst.Comment buildGeneratedBy() { | 2106 jsAst.Comment buildGeneratedBy() { |
2105 List<String> options = []; | 2107 List<String> options = []; |
2106 if (compiler.mirrorsLibrary != null) options.add('mirrors'); | 2108 if (compiler.mirrorsLibrary != null) options.add('mirrors'); |
2107 if (compiler.options.useContentSecurityPolicy) options.add("CSP"); | 2109 if (compiler.options.useContentSecurityPolicy) options.add("CSP"); |
2108 return new jsAst.Comment(generatedBy(compiler, flavor: options.join(", "))); | 2110 return new jsAst.Comment(generatedBy(compiler, flavor: options.join(", "))); |
2109 } | 2111 } |
2110 | 2112 |
2111 void outputSourceMap(CodeOutput output, | 2113 void outputSourceMap( |
2112 LineColumnProvider lineColumnProvider, | 2114 CodeOutput output, LineColumnProvider lineColumnProvider, String name, |
2113 String name, | 2115 [Uri sourceMapUri, Uri fileUri]) { |
2114 [Uri sourceMapUri, | |
2115 Uri fileUri]) { | |
2116 if (!generateSourceMap) return; | 2116 if (!generateSourceMap) return; |
2117 // Create a source file for the compilation output. This allows using | 2117 // Create a source file for the compilation output. This allows using |
2118 // [:getLine:] to transform offsets to line numbers in [SourceMapBuilder]. | 2118 // [:getLine:] to transform offsets to line numbers in [SourceMapBuilder]. |
2119 SourceMapBuilder sourceMapBuilder = | 2119 SourceMapBuilder sourceMapBuilder = |
2120 new SourceMapBuilder(sourceMapUri, fileUri, lineColumnProvider); | 2120 new SourceMapBuilder(sourceMapUri, fileUri, lineColumnProvider); |
2121 output.forEachSourceLocation(sourceMapBuilder.addMapping); | 2121 output.forEachSourceLocation(sourceMapBuilder.addMapping); |
2122 String sourceMap = sourceMapBuilder.build(); | 2122 String sourceMap = sourceMapBuilder.build(); |
2123 compiler.outputProvider(name, 'js.map') | 2123 compiler.outputProvider(name, 'js.map') |
2124 ..add(sourceMap) | 2124 ..add(sourceMap) |
2125 ..close(); | 2125 ..close(); |
2126 } | 2126 } |
2127 | 2127 |
2128 void outputDeferredMap() { | 2128 void outputDeferredMap() { |
2129 Map<String, dynamic> mapping = new Map<String, dynamic>(); | 2129 Map<String, dynamic> mapping = new Map<String, dynamic>(); |
2130 // Json does not support comments, so we embed the explanation in the | 2130 // Json does not support comments, so we embed the explanation in the |
2131 // data. | 2131 // data. |
2132 mapping["_comment"] = "This mapping shows which compiled `.js` files are " | 2132 mapping["_comment"] = "This mapping shows which compiled `.js` files are " |
2133 "needed for a given deferred library import."; | 2133 "needed for a given deferred library import."; |
2134 mapping.addAll(compiler.deferredLoadTask.computeDeferredMap()); | 2134 mapping.addAll(compiler.deferredLoadTask.computeDeferredMap()); |
2135 compiler.outputProvider( | 2135 compiler.outputProvider( |
2136 compiler.options.deferredMapUri.path, 'deferred_map') | 2136 compiler.options.deferredMapUri.path, 'deferred_map') |
2137 ..add(const JsonEncoder.withIndent(" ").convert(mapping)) | 2137 ..add(const JsonEncoder.withIndent(" ").convert(mapping)) |
2138 ..close(); | 2138 ..close(); |
2139 } | 2139 } |
2140 | 2140 |
2141 void invalidateCaches() { | 2141 void invalidateCaches() { |
2142 if (!compiler.options.hasIncrementalSupport) return; | 2142 if (!compiler.options.hasIncrementalSupport) return; |
2143 if (cachedElements.isEmpty) return; | 2143 if (cachedElements.isEmpty) return; |
2144 for (Element element in compiler.enqueuer.codegen.newlyEnqueuedElements) { | 2144 for (Element element in compiler.enqueuer.codegen.newlyEnqueuedElements) { |
2145 if (element.isInstanceMember) { | 2145 if (element.isInstanceMember) { |
2146 cachedClassBuilders.remove(element.enclosingClass); | 2146 cachedClassBuilders.remove(element.enclosingClass); |
2147 | 2147 |
2148 nativeEmitter.cachedBuilders.remove(element.enclosingClass); | 2148 nativeEmitter.cachedBuilders.remove(element.enclosingClass); |
2149 | |
2150 } | 2149 } |
2151 } | 2150 } |
2152 } | 2151 } |
2153 } | 2152 } |
OLD | NEW |