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 '../../closure.dart' show ClosureFieldElement; | 7 import '../../closure.dart' show ClosureFieldElement; |
8 import '../../common.dart'; | 8 import '../../common.dart'; |
9 import '../../common/names.dart' show Names, Selectors; | 9 import '../../common/names.dart' show Names, Selectors; |
10 import '../../compiler.dart' show Compiler; | 10 import '../../compiler.dart' show Compiler; |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
77 ClosedWorld closedWorld, Set<ClassElement> rtiNeededClasses) | 77 ClosedWorld closedWorld, Set<ClassElement> rtiNeededClasses) |
78 : this._compiler = compiler, | 78 : this._compiler = compiler, |
79 this.namer = namer, | 79 this.namer = namer, |
80 this.closedWorld = closedWorld, | 80 this.closedWorld = closedWorld, |
81 this.collector = new Collector( | 81 this.collector = new Collector( |
82 compiler, namer, closedWorld, rtiNeededClasses, emitter), | 82 compiler, namer, closedWorld, rtiNeededClasses, emitter), |
83 this._registry = new Registry(compiler); | 83 this._registry = new Registry(compiler); |
84 | 84 |
85 JavaScriptBackend get backend => _compiler.backend; | 85 JavaScriptBackend get backend => _compiler.backend; |
86 BackendHelpers get helpers => backend.helpers; | 86 BackendHelpers get helpers => backend.helpers; |
87 CodegenWorldBuilder get universe => _compiler.codegenWorld; | 87 CodegenWorldBuilder get worldBuilder => _compiler.codegenWorldBuilder; |
88 | 88 |
89 /// Mapping from [ClassElement] to constructed [Class]. We need this to | 89 /// Mapping from [ClassElement] to constructed [Class]. We need this to |
90 /// update the superclass in the [Class]. | 90 /// update the superclass in the [Class]. |
91 final Map<ClassElement, Class> _classes = <ClassElement, Class>{}; | 91 final Map<ClassElement, Class> _classes = <ClassElement, Class>{}; |
92 | 92 |
93 /// Mapping from [OutputUnit] to constructed [Fragment]. We need this to | 93 /// Mapping from [OutputUnit] to constructed [Fragment]. We need this to |
94 /// generate the deferredLoadingMap (to know which hunks to load). | 94 /// generate the deferredLoadingMap (to know which hunks to load). |
95 final Map<OutputUnit, Fragment> _outputs = <OutputUnit, Fragment>{}; | 95 final Map<OutputUnit, Fragment> _outputs = <OutputUnit, Fragment>{}; |
96 | 96 |
97 /// Mapping from [ConstantValue] to constructed [Constant]. We need this to | 97 /// Mapping from [ConstantValue] to constructed [Constant]. We need this to |
(...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
347 var interceptorClass = _classes[helpers.jsJavaScriptObjectClass]; | 347 var interceptorClass = _classes[helpers.jsJavaScriptObjectClass]; |
348 var stubNames = new Set<String>(); | 348 var stubNames = new Set<String>(); |
349 librariesMap.forEach((LibraryElement library, List<Element> elements) { | 349 librariesMap.forEach((LibraryElement library, List<Element> elements) { |
350 for (Element e in elements) { | 350 for (Element e in elements) { |
351 if (e is ClassElement && backend.isJsInterop(e)) { | 351 if (e is ClassElement && backend.isJsInterop(e)) { |
352 e.declaration.forEachMember((_, Element member) { | 352 e.declaration.forEachMember((_, Element member) { |
353 var jsName = | 353 var jsName = |
354 backend.nativeData.getUnescapedJSInteropName(member.name); | 354 backend.nativeData.getUnescapedJSInteropName(member.name); |
355 if (!member.isInstanceMember) return; | 355 if (!member.isInstanceMember) return; |
356 if (member.isGetter || member.isField || member.isFunction) { | 356 if (member.isGetter || member.isField || member.isFunction) { |
357 var selectors = | 357 var selectors = worldBuilder.getterInvocationsByName(member.name); |
358 _compiler.codegenWorld.getterInvocationsByName(member.name); | |
359 if (selectors != null && !selectors.isEmpty) { | 358 if (selectors != null && !selectors.isEmpty) { |
360 for (var selector in selectors.keys) { | 359 for (var selector in selectors.keys) { |
361 var stubName = namer.invocationName(selector); | 360 var stubName = namer.invocationName(selector); |
362 if (stubNames.add(stubName.key)) { | 361 if (stubNames.add(stubName.key)) { |
363 interceptorClass.callStubs.add(_buildStubMethod(stubName, | 362 interceptorClass.callStubs.add(_buildStubMethod(stubName, |
364 js.js('function(obj) { return obj.# }', [jsName]), | 363 js.js('function(obj) { return obj.# }', [jsName]), |
365 element: member)); | 364 element: member)); |
366 } | 365 } |
367 } | 366 } |
368 } | 367 } |
369 } | 368 } |
370 | 369 |
371 if (member.isSetter || (member.isField && !member.isConst)) { | 370 if (member.isSetter || (member.isField && !member.isConst)) { |
372 var selectors = | 371 var selectors = worldBuilder.setterInvocationsByName(member.name); |
373 _compiler.codegenWorld.setterInvocationsByName(member.name); | |
374 if (selectors != null && !selectors.isEmpty) { | 372 if (selectors != null && !selectors.isEmpty) { |
375 var stubName = namer.setterForElement(member); | 373 var stubName = namer.setterForElement(member); |
376 if (stubNames.add(stubName.key)) { | 374 if (stubNames.add(stubName.key)) { |
377 interceptorClass.callStubs.add(_buildStubMethod(stubName, | 375 interceptorClass.callStubs.add(_buildStubMethod(stubName, |
378 js.js('function(obj, v) { return obj.# = v }', [jsName]), | 376 js.js('function(obj, v) { return obj.# = v }', [jsName]), |
379 element: member)); | 377 element: member)); |
380 } | 378 } |
381 } | 379 } |
382 } | 380 } |
383 | 381 |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
416 if (isFunctionLike || functionType != null) { | 414 if (isFunctionLike || functionType != null) { |
417 int minArgs; | 415 int minArgs; |
418 int maxArgs; | 416 int maxArgs; |
419 if (functionType != null) { | 417 if (functionType != null) { |
420 minArgs = functionType.parameterTypes.length; | 418 minArgs = functionType.parameterTypes.length; |
421 maxArgs = minArgs + functionType.optionalParameterTypes.length; | 419 maxArgs = minArgs + functionType.optionalParameterTypes.length; |
422 } else { | 420 } else { |
423 minArgs = 0; | 421 minArgs = 0; |
424 maxArgs = 32767; | 422 maxArgs = 32767; |
425 } | 423 } |
426 var selectors = | 424 var selectors = worldBuilder.invocationsByName(member.name); |
427 _compiler.codegenWorld.invocationsByName(member.name); | |
428 // Named arguments are not yet supported. In the future we | 425 // Named arguments are not yet supported. In the future we |
429 // may want to map named arguments to an object literal containing | 426 // may want to map named arguments to an object literal containing |
430 // all named arguments. | 427 // all named arguments. |
431 if (selectors != null && !selectors.isEmpty) { | 428 if (selectors != null && !selectors.isEmpty) { |
432 for (var selector in selectors.keys) { | 429 for (var selector in selectors.keys) { |
433 // Check whether the arity matches this member. | 430 // Check whether the arity matches this member. |
434 var argumentCount = selector.argumentCount; | 431 var argumentCount = selector.argumentCount; |
435 // JS interop does not support named arguments. | 432 // JS interop does not support named arguments. |
436 if (selector.namedArgumentCount > 0) continue; | 433 if (selector.namedArgumentCount > 0) continue; |
437 if (argumentCount < minArgs) continue; | 434 if (argumentCount < minArgs) continue; |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
515 if (backend.isJsInterop(element)) { | 512 if (backend.isJsInterop(element)) { |
516 // TODO(jacobr): check whether the class has any active static fields | 513 // TODO(jacobr): check whether the class has any active static fields |
517 // if it does not we can suppress it completely. | 514 // if it does not we can suppress it completely. |
518 onlyForRti = true; | 515 onlyForRti = true; |
519 } | 516 } |
520 | 517 |
521 List<Method> methods = []; | 518 List<Method> methods = []; |
522 List<StubMethod> callStubs = <StubMethod>[]; | 519 List<StubMethod> callStubs = <StubMethod>[]; |
523 | 520 |
524 ClassStubGenerator classStubGenerator = new ClassStubGenerator( | 521 ClassStubGenerator classStubGenerator = new ClassStubGenerator( |
525 namer, backend, universe, closedWorld, | 522 namer, backend, worldBuilder, closedWorld, |
526 enableMinification: _compiler.options.enableMinification); | 523 enableMinification: _compiler.options.enableMinification); |
527 RuntimeTypeGenerator runtimeTypeGenerator = | 524 RuntimeTypeGenerator runtimeTypeGenerator = |
528 new RuntimeTypeGenerator(_compiler, _task, namer); | 525 new RuntimeTypeGenerator(_compiler, _task, namer); |
529 | 526 |
530 void visitMember(ClassElement enclosing, Element member) { | 527 void visitMember(ClassElement enclosing, Element member) { |
531 assert(invariant(element, member.isDeclaration)); | 528 assert(invariant(element, member.isDeclaration)); |
532 assert(invariant(element, element == enclosing)); | 529 assert(invariant(element, element == enclosing)); |
533 | 530 |
534 if (Elements.isNonAbstractInstanceMember(member)) { | 531 if (Elements.isNonAbstractInstanceMember(member)) { |
535 // TODO(herhut): Remove once _buildMethod can no longer return null. | 532 // TODO(herhut): Remove once _buildMethod can no longer return null. |
536 Method method = _buildMethod(member); | 533 Method method = _buildMethod(member); |
537 if (method != null) methods.add(method); | 534 if (method != null) methods.add(method); |
538 } | 535 } |
539 if (member.isGetter || member.isField) { | 536 if (member.isGetter || member.isField) { |
540 Map<Selector, SelectorConstraints> selectors = | 537 Map<Selector, SelectorConstraints> selectors = |
541 _compiler.codegenWorld.invocationsByName(member.name); | 538 worldBuilder.invocationsByName(member.name); |
542 if (selectors != null && !selectors.isEmpty) { | 539 if (selectors != null && !selectors.isEmpty) { |
543 Map<js.Name, js.Expression> callStubsForMember = | 540 Map<js.Name, js.Expression> callStubsForMember = |
544 classStubGenerator.generateCallStubsForGetter(member, selectors); | 541 classStubGenerator.generateCallStubsForGetter(member, selectors); |
545 callStubsForMember.forEach((js.Name name, js.Expression code) { | 542 callStubsForMember.forEach((js.Name name, js.Expression code) { |
546 callStubs.add(_buildStubMethod(name, code, element: member)); | 543 callStubs.add(_buildStubMethod(name, code, element: member)); |
547 }); | 544 }); |
548 } | 545 } |
549 } | 546 } |
550 } | 547 } |
551 | 548 |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
617 isChecks.add(_buildStubMethod(name, code)); | 614 isChecks.add(_buildStubMethod(name, code)); |
618 }); | 615 }); |
619 } | 616 } |
620 | 617 |
621 js.Name name = namer.className(element); | 618 js.Name name = namer.className(element); |
622 String holderName = namer.globalObjectFor(element); | 619 String holderName = namer.globalObjectFor(element); |
623 // TODO(floitsch): we shouldn't update the registry in the middle of | 620 // TODO(floitsch): we shouldn't update the registry in the middle of |
624 // building a class. | 621 // building a class. |
625 Holder holder = _registry.registerHolder(holderName); | 622 Holder holder = _registry.registerHolder(holderName); |
626 bool isInstantiated = !backend.isJsInterop(element) && | 623 bool isInstantiated = !backend.isJsInterop(element) && |
627 _compiler.codegenWorld.directlyInstantiatedClasses.contains(element); | 624 worldBuilder.directlyInstantiatedClasses.contains(element); |
628 | 625 |
629 Class result; | 626 Class result; |
630 if (element.isMixinApplication && !onlyForRti) { | 627 if (element.isMixinApplication && !onlyForRti) { |
631 assert(!backend.isNative(element)); | 628 assert(!backend.isNative(element)); |
632 assert(methods.isEmpty); | 629 assert(methods.isEmpty); |
633 | 630 |
634 result = new MixinApplication( | 631 result = new MixinApplication( |
635 element, | 632 element, |
636 name, | 633 name, |
637 holder, | 634 holder, |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
734 : null; | 731 : null; |
735 | 732 |
736 if (isNotApplyTarget) { | 733 if (isNotApplyTarget) { |
737 canTearOff = false; | 734 canTearOff = false; |
738 } else { | 735 } else { |
739 if (element.enclosingClass.isClosure) { | 736 if (element.enclosingClass.isClosure) { |
740 canTearOff = false; | 737 canTearOff = false; |
741 isClosureCallMethod = true; | 738 isClosureCallMethod = true; |
742 } else { | 739 } else { |
743 // Careful with operators. | 740 // Careful with operators. |
744 canTearOff = universe.hasInvokedGetter(element, closedWorld) || | 741 canTearOff = worldBuilder.hasInvokedGetter(element, closedWorld) || |
745 (canBeReflected && !element.isOperator); | 742 (canBeReflected && !element.isOperator); |
746 assert(canTearOff || | 743 assert(canTearOff || |
747 !universe.methodsNeedingSuperGetter.contains(element)); | 744 !worldBuilder.methodsNeedingSuperGetter.contains(element)); |
748 tearOffName = namer.getterForElement(element); | 745 tearOffName = namer.getterForElement(element); |
749 } | 746 } |
750 } | 747 } |
751 | 748 |
752 if (canTearOff) { | 749 if (canTearOff) { |
753 assert(invariant(element, !element.isGenerativeConstructor)); | 750 assert(invariant(element, !element.isGenerativeConstructor)); |
754 assert(invariant(element, !element.isGenerativeConstructorBody)); | 751 assert(invariant(element, !element.isGenerativeConstructorBody)); |
755 assert(invariant(element, !element.isConstructor)); | 752 assert(invariant(element, !element.isConstructor)); |
756 } | 753 } |
757 | 754 |
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
928 js.Name name = namer.methodPropertyName(element); | 925 js.Name name = namer.methodPropertyName(element); |
929 String holder = namer.globalObjectFor(element); | 926 String holder = namer.globalObjectFor(element); |
930 js.Expression code = backend.generatedCode[element]; | 927 js.Expression code = backend.generatedCode[element]; |
931 | 928 |
932 bool isApplyTarget = !element.isConstructor && !element.isAccessor; | 929 bool isApplyTarget = !element.isConstructor && !element.isAccessor; |
933 bool canBeApplied = _methodCanBeApplied(element); | 930 bool canBeApplied = _methodCanBeApplied(element); |
934 bool canBeReflected = _methodCanBeReflected(element); | 931 bool canBeReflected = _methodCanBeReflected(element); |
935 | 932 |
936 bool needsTearOff = isApplyTarget && | 933 bool needsTearOff = isApplyTarget && |
937 (canBeReflected || | 934 (canBeReflected || |
938 universe.staticFunctionsNeedingGetter.contains(element)); | 935 worldBuilder.staticFunctionsNeedingGetter.contains(element)); |
939 | 936 |
940 js.Name tearOffName = | 937 js.Name tearOffName = |
941 needsTearOff ? namer.staticClosureName(element) : null; | 938 needsTearOff ? namer.staticClosureName(element) : null; |
942 | 939 |
943 js.Name callName = null; | 940 js.Name callName = null; |
944 if (needsTearOff) { | 941 if (needsTearOff) { |
945 Selector callSelector = | 942 Selector callSelector = |
946 new Selector.fromElement(element).toCallSelector(); | 943 new Selector.fromElement(element).toCallSelector(); |
947 callName = namer.invocationName(callSelector); | 944 callName = namer.invocationName(callSelector); |
948 } | 945 } |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
990 Constant constant = new Constant(name, holder, constantValue); | 987 Constant constant = new Constant(name, holder, constantValue); |
991 _constants[constantValue] = constant; | 988 _constants[constantValue] = constant; |
992 } | 989 } |
993 } | 990 } |
994 | 991 |
995 Holder _registerStaticStateHolder() { | 992 Holder _registerStaticStateHolder() { |
996 return _registry.registerHolder(namer.staticStateHolder, | 993 return _registry.registerHolder(namer.staticStateHolder, |
997 isStaticStateHolder: true); | 994 isStaticStateHolder: true); |
998 } | 995 } |
999 } | 996 } |
OLD | NEW |