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.program_builder; | 5 library dart2js.js_emitter.program_builder; |
6 | 6 |
7 import '../js_emitter.dart' show computeMixinClass, Emitter; | 7 import '../js_emitter.dart' show computeMixinClass, Emitter; |
8 import '../model.dart'; | 8 import '../model.dart'; |
9 | 9 |
10 import '../../common.dart'; | 10 import '../../common.dart'; |
11 import '../../closure.dart' show ClosureFieldElement; | 11 import '../../closure.dart' show ClosureFieldElement; |
12 import '../../js/js.dart' as js; | 12 import '../../js/js.dart' as js; |
13 | 13 |
14 import '../../js_backend/js_backend.dart' show | 14 import '../../js_backend/js_backend.dart' show |
15 Namer, | 15 Namer, |
16 JavaScriptBackend, | 16 JavaScriptBackend, |
17 JavaScriptConstantCompiler; | 17 JavaScriptConstantCompiler, |
18 StringBackedName; | |
18 | 19 |
19 import '../js_emitter.dart' show | 20 import '../js_emitter.dart' show |
20 ClassStubGenerator, | 21 ClassStubGenerator, |
21 CodeEmitterTask, | 22 CodeEmitterTask, |
22 InterceptorStubGenerator, | 23 InterceptorStubGenerator, |
23 MainCallStubGenerator, | 24 MainCallStubGenerator, |
24 ParameterStubGenerator, | 25 ParameterStubGenerator, |
25 RuntimeTypeGenerator, | 26 RuntimeTypeGenerator, |
26 TypeTestProperties; | 27 TypeTestProperties; |
27 | 28 |
28 import '../../elements/elements.dart' show | 29 import '../../elements/elements.dart' show |
29 FieldElement, | 30 FieldElement, |
30 MethodElement, | 31 MethodElement, |
32 Name, | |
31 ParameterElement; | 33 ParameterElement; |
32 | 34 |
33 import '../../universe/universe.dart' show Universe, SelectorConstraints; | 35 import '../../universe/universe.dart' show Universe, SelectorConstraints; |
34 import '../../deferred_load.dart' show DeferredLoadTask, OutputUnit; | 36 import '../../deferred_load.dart' show DeferredLoadTask, OutputUnit; |
35 | 37 |
36 part 'collector.dart'; | 38 part 'collector.dart'; |
37 part 'registry.dart'; | 39 part 'registry.dart'; |
38 part 'field_visitor.dart'; | 40 part 'field_visitor.dart'; |
39 | 41 |
40 /// Builds a self-contained representation of the program that can then be | 42 /// Builds a self-contained representation of the program that can then be |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
135 Set<ClassElement> interceptorClassesNeededByConstants = | 137 Set<ClassElement> interceptorClassesNeededByConstants = |
136 collector.computeInterceptorsReferencedFromConstants(); | 138 collector.computeInterceptorsReferencedFromConstants(); |
137 Set<ClassElement> classesModifiedByEmitRTISupport = | 139 Set<ClassElement> classesModifiedByEmitRTISupport = |
138 _task.typeTestRegistry.computeClassesModifiedByEmitRuntimeTypeSupport(); | 140 _task.typeTestRegistry.computeClassesModifiedByEmitRuntimeTypeSupport(); |
139 | 141 |
140 | 142 |
141 _unneededNativeClasses = _task.nativeEmitter.prepareNativeClasses( | 143 _unneededNativeClasses = _task.nativeEmitter.prepareNativeClasses( |
142 nativeClasses, interceptorClassesNeededByConstants, | 144 nativeClasses, interceptorClassesNeededByConstants, |
143 classesModifiedByEmitRTISupport); | 145 classesModifiedByEmitRTISupport); |
144 | 146 |
147 _addJsInteropStubs(_registry.mainLibrariesMap); | |
148 | |
145 MainFragment mainFragment = _buildMainFragment(_registry.mainLibrariesMap); | 149 MainFragment mainFragment = _buildMainFragment(_registry.mainLibrariesMap); |
146 Iterable<Fragment> deferredFragments = | 150 Iterable<Fragment> deferredFragments = |
147 _registry.deferredLibrariesMap.map(_buildDeferredFragment); | 151 _registry.deferredLibrariesMap.map(_buildDeferredFragment); |
148 | 152 |
149 List<Fragment> fragments = new List<Fragment>(_registry.librariesMapCount); | 153 List<Fragment> fragments = new List<Fragment>(_registry.librariesMapCount); |
150 fragments[0] = mainFragment; | 154 fragments[0] = mainFragment; |
151 fragments.setAll(1, deferredFragments); | 155 fragments.setAll(1, deferredFragments); |
152 | 156 |
153 _markEagerClasses(); | 157 _markEagerClasses(); |
154 | 158 |
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
312 | 316 |
313 List<Library> _buildLibraries(LibrariesMap librariesMap) { | 317 List<Library> _buildLibraries(LibrariesMap librariesMap) { |
314 List<Library> libraries = new List<Library>(librariesMap.length); | 318 List<Library> libraries = new List<Library>(librariesMap.length); |
315 int count = 0; | 319 int count = 0; |
316 librariesMap.forEach((LibraryElement library, List<Element> elements) { | 320 librariesMap.forEach((LibraryElement library, List<Element> elements) { |
317 libraries[count++] = _buildLibrary(library, elements); | 321 libraries[count++] = _buildLibrary(library, elements); |
318 }); | 322 }); |
319 return libraries; | 323 return libraries; |
320 } | 324 } |
321 | 325 |
326 void _addJsInteropStubs(LibrariesMap librariesMap) { | |
327 if (_classes.containsKey(_compiler.objectClass)) { | |
328 var toStringInvocation = namer.invocationName(new Selector.call( | |
329 new Name("toString", _compiler.objectClass.library), | |
330 CallStructure.NO_ARGS)); | |
331 // TODO(jacobr): register toString as used so that it is always accessible | |
332 // from JavaScript. | |
333 _classes[_compiler.objectClass].callStubs.add(_buildStubMethod( | |
334 new StringBackedName("toString"), | |
335 js.js('function() { return this.#(this) }', toStringInvocation))); | |
336 } | |
337 | |
338 // We add all members from classes marked with isJsInterop to the base | |
339 // Interceptor class with implementations that directly call the | |
340 // corresponding JavaScript member. We do not attempt to bind this when | |
341 // tearing off JavaScript methods as we cannot distinguish between calling | |
342 // a regular getter that returns a JavaScript function and tearing off | |
343 // a method in the case where there exist multiple JavaScript classes | |
344 // that conflict on whether the member is a getter or a method. | |
345 var interceptorClass = _classes[backend.jsInterceptorClass]; | |
sra1
2015/10/06 21:42:17
Add them to jsJavaScriptObjectClass.
Otherwise you
Jacob
2015/10/13 01:19:23
I thought you would complain about that. done :)
| |
346 var stubNames = new Set<String>(); | |
347 librariesMap.forEach((LibraryElement library, List<Element> elements) { | |
348 for (Element e in elements) { | |
349 if (e is ClassElement && e.isJsInterop) { | |
350 e.declaration.forEachMember((_, Element member) { | |
351 if (!member.isInstanceMember) return; | |
352 if (member.isGetter || member.isField || member.isFunction) { | |
353 var selectors = | |
354 _compiler.codegenWorld.getterInvocationsByName(member.name); | |
355 if (selectors != null && !selectors.isEmpty) { | |
356 for (var selector in selectors.keys) { | |
357 var stubName = namer.invocationName(selector); | |
358 if (stubNames.add(stubName.key)) { | |
359 interceptorClass.callStubs.add(_buildStubMethod( | |
360 stubName, | |
361 js.js( | |
362 'function(obj) { return obj.# }', [member.name]), | |
363 element: member)); | |
364 } | |
365 } | |
366 } | |
367 } | |
368 | |
369 if (member.isSetter || (member.isField && !member.isConst)) { | |
370 var selectors = | |
371 _compiler.codegenWorld.setterInvocationsByName(member.name); | |
372 if (selectors != null && !selectors.isEmpty) { | |
373 var stubName = namer.setterForElement(member); | |
374 if (stubNames.add(stubName.key)) { | |
375 interceptorClass.callStubs.add(_buildStubMethod( | |
376 stubName, | |
377 js.js('function(obj, v) { return obj.# = v }', | |
378 [member.name]), | |
379 element: member)); | |
380 } | |
381 } | |
382 } | |
383 | |
384 if (member.isFunction) { | |
385 var selectors = | |
386 _compiler.codegenWorld.invocationsByName(member.name); | |
387 FunctionElement fn = member; | |
388 // Named arguments are not yet supported. In the future we | |
389 // may want to map named arguments to an object literal containing | |
390 // all named arguments. | |
391 if (selectors != null && !selectors.isEmpty) { | |
392 for (var selector in selectors.keys) { | |
393 // Check whether the arity matches this member. | |
394 var argumentCount = selector.argumentCount; | |
395 if (argumentCount > fn.parameters.length) break; | |
396 if (argumentCount < fn.parameters.length && | |
397 !fn.parameters[argumentCount].isOptional) break; | |
398 var stubName = namer.invocationName(selector); | |
399 if (!stubNames.add(stubName.key)) break; | |
400 var candidateParameterNames = | |
401 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLOMOPQRSTUVWXYZ'; | |
402 var parameters = new List<String>.generate(argumentCount, | |
403 (i) => candidateParameterNames[i]); | |
404 | |
405 interceptorClass.callStubs.add(_buildStubMethod( | |
406 stubName, | |
407 js.js('function(receiver, #) { return receiver.#(#) }', | |
408 [parameters, member.name, parameters]), | |
409 element: member)); | |
410 } | |
411 } | |
412 } | |
413 }); | |
414 } | |
415 } | |
416 }); | |
417 } | |
418 | |
322 // Note that a library-element may have multiple [Library]s, if it is split | 419 // Note that a library-element may have multiple [Library]s, if it is split |
323 // into multiple output units. | 420 // into multiple output units. |
324 Library _buildLibrary(LibraryElement library, List<Element> elements) { | 421 Library _buildLibrary(LibraryElement library, List<Element> elements) { |
325 String uri = library.canonicalUri.toString(); | 422 String uri = library.canonicalUri.toString(); |
326 | 423 |
327 List<StaticMethod> statics = elements | 424 List<StaticMethod> statics = elements |
328 .where((e) => e is FunctionElement) | 425 .where((e) => e is FunctionElement) |
329 .map(_buildStaticMethod) | 426 .map(_buildStaticMethod) |
330 .toList(); | 427 .toList(); |
331 | 428 |
(...skipping 27 matching lines...) Expand all Loading... | |
359 | 456 |
360 return new Class( | 457 return new Class( |
361 element, name, null, [], instanceFields, [], [], [], [], [], [], null, | 458 element, name, null, [], instanceFields, [], [], [], [], [], [], null, |
362 isDirectlyInstantiated: true, | 459 isDirectlyInstantiated: true, |
363 onlyForRti: false, | 460 onlyForRti: false, |
364 isNative: element.isNative); | 461 isNative: element.isNative); |
365 } | 462 } |
366 | 463 |
367 Class _buildClass(ClassElement element) { | 464 Class _buildClass(ClassElement element) { |
368 bool onlyForRti = collector.classesOnlyNeededForRti.contains(element); | 465 bool onlyForRti = collector.classesOnlyNeededForRti.contains(element); |
466 if (element.isJsInterop) { | |
467 // TODO(jacobr): check whether the class has any active static fields | |
468 // if it does not we can suppress it completely. | |
469 onlyForRti = true; | |
470 } | |
369 | 471 |
370 List<Method> methods = []; | 472 List<Method> methods = []; |
371 List<StubMethod> callStubs = <StubMethod>[]; | 473 List<StubMethod> callStubs = <StubMethod>[]; |
372 | 474 |
373 ClassStubGenerator classStubGenerator = | 475 ClassStubGenerator classStubGenerator = |
374 new ClassStubGenerator(_compiler, namer, backend); | 476 new ClassStubGenerator(_compiler, namer, backend); |
375 RuntimeTypeGenerator runtimeTypeGenerator = | 477 RuntimeTypeGenerator runtimeTypeGenerator = |
376 new RuntimeTypeGenerator(_compiler, _task, namer); | 478 new RuntimeTypeGenerator(_compiler, _task, namer); |
377 | 479 |
378 void visitMember(ClassElement enclosing, Element member) { | 480 void visitMember(ClassElement enclosing, Element member) { |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
439 onlyForRti ? const <Field>[] : _buildFields(element, false); | 541 onlyForRti ? const <Field>[] : _buildFields(element, false); |
440 List<Field> staticFieldsForReflection = | 542 List<Field> staticFieldsForReflection = |
441 onlyForRti ? const <Field>[] : _buildFields(element, true); | 543 onlyForRti ? const <Field>[] : _buildFields(element, true); |
442 | 544 |
443 TypeTestProperties typeTests = | 545 TypeTestProperties typeTests = |
444 runtimeTypeGenerator.generateIsTests( | 546 runtimeTypeGenerator.generateIsTests( |
445 element, | 547 element, |
446 storeFunctionTypeInMetadata: _storeFunctionTypesInMetadata); | 548 storeFunctionTypeInMetadata: _storeFunctionTypesInMetadata); |
447 | 549 |
448 List<StubMethod> checkedSetters = <StubMethod>[]; | 550 List<StubMethod> checkedSetters = <StubMethod>[]; |
449 for (Field field in instanceFields) { | 551 List<StubMethod> isChecks = <StubMethod>[]; |
450 if (field.needsCheckedSetter) { | 552 if (element.isJsInterop) { |
451 assert(!field.needsUncheckedSetter); | 553 typeTests.properties.forEach((js.Name name, js.Node code) { |
452 Element element = field.element; | 554 _classes[backend.jsInterceptorClass].isChecks.add( |
453 js.Expression code = backend.generatedCode[element]; | 555 _buildStubMethod(name, code)); |
454 assert(code != null); | 556 }); |
455 js.Name name = namer.deriveSetterName(field.accessorName); | 557 } else { |
456 checkedSetters.add(_buildStubMethod(name, code, element: element)); | 558 for (Field field in instanceFields) { |
559 if (field.needsCheckedSetter) { | |
560 assert(!field.needsUncheckedSetter); | |
561 Element element = field.element; | |
562 js.Expression code = backend.generatedCode[element]; | |
563 assert(code != null); | |
564 js.Name name = namer.deriveSetterName(field.accessorName); | |
565 checkedSetters.add(_buildStubMethod(name, code, element: element)); | |
566 } | |
457 } | 567 } |
568 | |
569 typeTests.properties.forEach((js.Name name, js.Node code) { | |
570 isChecks.add(_buildStubMethod(name, code)); | |
571 }); | |
458 } | 572 } |
459 | 573 |
460 List<StubMethod> isChecks = <StubMethod>[]; | |
461 typeTests.properties.forEach((js.Name name, js.Node code) { | |
462 isChecks.add(_buildStubMethod(name, code)); | |
463 }); | |
464 | |
465 js.Name name = namer.className(element); | 574 js.Name name = namer.className(element); |
466 String holderName = namer.globalObjectFor(element); | 575 String holderName = namer.globalObjectFor(element); |
467 // TODO(floitsch): we shouldn't update the registry in the middle of | 576 // TODO(floitsch): we shouldn't update the registry in the middle of |
468 // building a class. | 577 // building a class. |
469 Holder holder = _registry.registerHolder(holderName); | 578 Holder holder = _registry.registerHolder(holderName); |
470 bool isInstantiated = | 579 bool isInstantiated = element.isJsInterop ? false : |
Siggi Cherem (dart-lang)
2015/10/06 22:38:02
x ? false : y
=>
!x && y
Jacob
2015/10/13 01:19:23
Done.
| |
471 _compiler.codegenWorld.directlyInstantiatedClasses.contains(element); | 580 _compiler.codegenWorld.directlyInstantiatedClasses.contains(element); |
472 | 581 |
473 Class result; | 582 Class result; |
474 if (element.isMixinApplication && !onlyForRti) { | 583 if (element.isMixinApplication && !onlyForRti) { |
475 assert(!element.isNative); | 584 assert(!element.isNative); |
476 assert(methods.isEmpty); | 585 assert(methods.isEmpty); |
477 | 586 |
478 result = new MixinApplication(element, | 587 result = new MixinApplication(element, |
479 name, holder, | 588 name, holder, |
480 instanceFields, | 589 instanceFields, |
(...skipping 348 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
829 Constant constant = new Constant(name, holder, constantValue); | 938 Constant constant = new Constant(name, holder, constantValue); |
830 _constants[constantValue] = constant; | 939 _constants[constantValue] = constant; |
831 } | 940 } |
832 } | 941 } |
833 | 942 |
834 Holder _registerStaticStateHolder() { | 943 Holder _registerStaticStateHolder() { |
835 return _registry.registerHolder( | 944 return _registry.registerHolder( |
836 namer.staticStateHolder, isStaticStateHolder: true); | 945 namer.staticStateHolder, isStaticStateHolder: true); |
837 } | 946 } |
838 } | 947 } |
OLD | NEW |