| 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 |