OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 part of js_backend; | 5 part of js_backend; |
6 | 6 |
7 /** | 7 /** |
8 * A function element that represents a closure call. The signature is copied | 8 * A function element that represents a closure call. The signature is copied |
9 * from the given element. | 9 * from the given element. |
10 */ | 10 */ |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
128 : mainBuffer = new CodeBuffer(), | 128 : mainBuffer = new CodeBuffer(), |
129 this.namer = namer, | 129 this.namer = namer, |
130 boundClosureCache = new Map<int, String>(), | 130 boundClosureCache = new Map<int, String>(), |
131 interceptorClosureCache = new Map<int, String>(), | 131 interceptorClosureCache = new Map<int, String>(), |
132 constantEmitter = new ConstantEmitter(compiler, namer), | 132 constantEmitter = new ConstantEmitter(compiler, namer), |
133 super(compiler) { | 133 super(compiler) { |
134 nativeEmitter = new NativeEmitter(this); | 134 nativeEmitter = new NativeEmitter(this); |
135 } | 135 } |
136 | 136 |
137 void addComment(String comment, CodeBuffer buffer) { | 137 void addComment(String comment, CodeBuffer buffer) { |
138 buffer.add(jsAst.prettyPrint(js.comment(comment), compiler)); | 138 buffer.write(jsAst.prettyPrint(js.comment(comment), compiler)); |
139 } | 139 } |
140 | 140 |
141 void computeRequiredTypeChecks() { | 141 void computeRequiredTypeChecks() { |
142 assert(checkedClasses == null && checkedTypedefs == null); | 142 assert(checkedClasses == null && checkedTypedefs == null); |
143 | 143 |
144 compiler.codegenWorld.addImplicitChecks(classesUsingTypeVariableTests); | 144 compiler.codegenWorld.addImplicitChecks(classesUsingTypeVariableTests); |
145 | 145 |
146 checkedClasses = new Set<ClassElement>(); | 146 checkedClasses = new Set<ClassElement>(); |
147 checkedTypedefs = new Set<TypedefElement>(); | 147 checkedTypedefs = new Set<TypedefElement>(); |
148 compiler.codegenWorld.isChecks.forEach((DartType t) { | 148 compiler.codegenWorld.isChecks.forEach((DartType t) { |
(...skipping 462 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
611 | 611 |
612 List buildFinishIsolateConstructor() { | 612 List buildFinishIsolateConstructor() { |
613 return [ | 613 return [ |
614 // $finishIsolateConstructorName = $finishIsolateConstructorFunction | 614 // $finishIsolateConstructorName = $finishIsolateConstructorFunction |
615 js[finishIsolateConstructorName].assign(finishIsolateConstructorFunction) | 615 js[finishIsolateConstructorName].assign(finishIsolateConstructorFunction) |
616 ]; | 616 ]; |
617 } | 617 } |
618 | 618 |
619 void emitFinishIsolateConstructorInvocation(CodeBuffer buffer) { | 619 void emitFinishIsolateConstructorInvocation(CodeBuffer buffer) { |
620 String isolate = namer.isolateName; | 620 String isolate = namer.isolateName; |
621 buffer.add("$isolate = $finishIsolateConstructorName($isolate)$N"); | 621 buffer.write("$isolate = $finishIsolateConstructorName($isolate)$N"); |
622 } | 622 } |
623 | 623 |
624 /** | 624 /** |
625 * Generate stubs to handle invocation of methods with optional | 625 * Generate stubs to handle invocation of methods with optional |
626 * arguments. | 626 * arguments. |
627 * | 627 * |
628 * A method like [: foo([x]) :] may be invoked by the following | 628 * A method like [: foo([x]) :] may be invoked by the following |
629 * calls: [: foo(), foo(1), foo(x: 1) :]. See the sources of this | 629 * calls: [: foo(), foo(1), foo(x: 1) :]. See the sources of this |
630 * function for detailed examples. | 630 * function for detailed examples. |
631 */ | 631 */ |
(...skipping 386 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1018 /** | 1018 /** |
1019 * Generates a holder object if it is needed. A holder is a JavaScript | 1019 * Generates a holder object if it is needed. A holder is a JavaScript |
1020 * object literal with a field [builtin$cls] that contains the name of the | 1020 * object literal with a field [builtin$cls] that contains the name of the |
1021 * class as a string (just like object constructors do). The is-checks for | 1021 * class as a string (just like object constructors do). The is-checks for |
1022 * the class are are added to the holder object later. | 1022 * the class are are added to the holder object later. |
1023 */ | 1023 */ |
1024 void maybeGenerateHolder(ClassElement cls) { | 1024 void maybeGenerateHolder(ClassElement cls) { |
1025 if (!needsHolder(cls)) return; | 1025 if (!needsHolder(cls)) return; |
1026 String holder = namer.isolateAccess(cls); | 1026 String holder = namer.isolateAccess(cls); |
1027 String name = namer.getName(cls); | 1027 String name = namer.getName(cls); |
1028 buffer.add('$holder$_=$_{builtin\$cls:$_"$name"'); | 1028 buffer.write('$holder$_=$_{builtin\$cls:$_"$name"'); |
1029 buffer.add('}$N'); | 1029 buffer.write('}$N'); |
1030 } | 1030 } |
1031 | 1031 |
1032 // Create representation objects for classes that we do not have a class | 1032 // Create representation objects for classes that we do not have a class |
1033 // definition for (because they are uninstantiated or native). | 1033 // definition for (because they are uninstantiated or native). |
1034 for (ClassElement cls in rti.allArguments) { | 1034 for (ClassElement cls in rti.allArguments) { |
1035 maybeGenerateHolder(cls); | 1035 maybeGenerateHolder(cls); |
1036 } | 1036 } |
1037 | 1037 |
1038 // Add checks to the constructors of instantiated classes or to the created | 1038 // Add checks to the constructors of instantiated classes or to the created |
1039 // holder object. | 1039 // holder object. |
1040 for (ClassElement cls in typeChecks) { | 1040 for (ClassElement cls in typeChecks) { |
1041 String holder = namer.isolateAccess(cls); | 1041 String holder = namer.isolateAccess(cls); |
1042 for (ClassElement check in typeChecks[cls]) { | 1042 for (ClassElement check in typeChecks[cls]) { |
1043 buffer.add('$holder.${namer.operatorIs(check)}$_=${_}true$N'); | 1043 buffer.write('$holder.${namer.operatorIs(check)}$_=${_}true$N'); |
1044 String body = rti.getSupertypeSubstitution(cls, check); | 1044 String body = rti.getSupertypeSubstitution(cls, check); |
1045 if (body != null) { | 1045 if (body != null) { |
1046 buffer.add('$holder.${namer.substitutionName(check)}$_=${_}$body$N'); | 1046 buffer.write('$holder.${namer.substitutionName(check)}$_=${_}$body$N')
; |
1047 } | 1047 } |
1048 }; | 1048 }; |
1049 } | 1049 } |
1050 } | 1050 } |
1051 | 1051 |
1052 void visitNativeMixins(ClassElement classElement, | 1052 void visitNativeMixins(ClassElement classElement, |
1053 void visit(MixinApplicationElement mixinApplication)) { | 1053 void visit(MixinApplicationElement mixinApplication)) { |
1054 if (!classElement.isNative()) return; | 1054 if (!classElement.isNative()) return; |
1055 // Use recursion to make sure to visit the superclasses before the | 1055 // Use recursion to make sure to visit the superclasses before the |
1056 // subclasses. Once we start keeping track of the emitted fields | 1056 // subclasses. Once we start keeping track of the emitted fields |
(...skipping 289 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1346 | 1346 |
1347 emitClassConstructor(classElement, builder); | 1347 emitClassConstructor(classElement, builder); |
1348 emitSuper(superName, builder); | 1348 emitSuper(superName, builder); |
1349 emitClassFields(classElement, builder, | 1349 emitClassFields(classElement, builder, |
1350 superClass: superName, classIsNative: false); | 1350 superClass: superName, classIsNative: false); |
1351 emitClassGettersSetters(classElement, builder); | 1351 emitClassGettersSetters(classElement, builder); |
1352 emitInstanceMembers(classElement, builder); | 1352 emitInstanceMembers(classElement, builder); |
1353 | 1353 |
1354 jsAst.Expression init = | 1354 jsAst.Expression init = |
1355 js[classesCollector][className].assign(builder.toObjectInitializer()); | 1355 js[classesCollector][className].assign(builder.toObjectInitializer()); |
1356 buffer.add(jsAst.prettyPrint(init, compiler)); | 1356 buffer.write(jsAst.prettyPrint(init, compiler)); |
1357 buffer.add('$N$n'); | 1357 buffer.write('$N$n'); |
1358 } | 1358 } |
1359 | 1359 |
1360 bool get getterAndSetterCanBeImplementedByFieldSpec => true; | 1360 bool get getterAndSetterCanBeImplementedByFieldSpec => true; |
1361 | 1361 |
1362 int _selectorRank(Selector selector) { | 1362 int _selectorRank(Selector selector) { |
1363 int arity = selector.argumentCount * 3; | 1363 int arity = selector.argumentCount * 3; |
1364 if (selector.isGetter()) return arity + 2; | 1364 if (selector.isGetter()) return arity + 2; |
1365 if (selector.isSetter()) return arity + 1; | 1365 if (selector.isSetter()) return arity + 1; |
1366 return arity; | 1366 return arity; |
1367 } | 1367 } |
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1551 // The closure class could have become necessary because of the generation | 1551 // The closure class could have become necessary because of the generation |
1552 // of stubs. | 1552 // of stubs. |
1553 ClassElement closureClass = compiler.closureClass; | 1553 ClassElement closureClass = compiler.closureClass; |
1554 if (needsClosureClass && !instantiatedClasses.contains(closureClass)) { | 1554 if (needsClosureClass && !instantiatedClasses.contains(closureClass)) { |
1555 generateClass(closureClass, bufferForElement(closureClass, buffer)); | 1555 generateClass(closureClass, bufferForElement(closureClass, buffer)); |
1556 } | 1556 } |
1557 } | 1557 } |
1558 | 1558 |
1559 void emitFinishClassesInvocationIfNecessary(CodeBuffer buffer) { | 1559 void emitFinishClassesInvocationIfNecessary(CodeBuffer buffer) { |
1560 if (needsDefineClass) { | 1560 if (needsDefineClass) { |
1561 buffer.add('$finishClassesName($classesCollector,' | 1561 buffer.write('$finishClassesName($classesCollector,' |
1562 '$_$isolateProperties,' | 1562 '$_$isolateProperties,' |
1563 '${_}null)$N'); | 1563 '${_}null)$N'); |
1564 | 1564 |
1565 // Reset the map. | 1565 // Reset the map. |
1566 buffer.add("$classesCollector$_=${_}null$N$n"); | 1566 buffer.write("$classesCollector$_=${_}null$N$n"); |
1567 } | 1567 } |
1568 } | 1568 } |
1569 | 1569 |
1570 void emitStaticFunction(CodeBuffer buffer, | 1570 void emitStaticFunction(CodeBuffer buffer, |
1571 String name, | 1571 String name, |
1572 jsAst.Expression functionExpression) { | 1572 jsAst.Expression functionExpression) { |
1573 jsAst.Expression assignment = | 1573 jsAst.Expression assignment = |
1574 js[isolateProperties][name].assign(functionExpression); | 1574 js[isolateProperties][name].assign(functionExpression); |
1575 buffer.add(jsAst.prettyPrint(assignment, compiler)); | 1575 buffer.write(jsAst.prettyPrint(assignment, compiler)); |
1576 buffer.add('$N$n'); | 1576 buffer.write('$N$n'); |
1577 } | 1577 } |
1578 | 1578 |
1579 void emitStaticFunctions(CodeBuffer eagerBuffer) { | 1579 void emitStaticFunctions(CodeBuffer eagerBuffer) { |
1580 bool isStaticFunction(Element element) => | 1580 bool isStaticFunction(Element element) => |
1581 !element.isInstanceMember() && !element.isField(); | 1581 !element.isInstanceMember() && !element.isField(); |
1582 | 1582 |
1583 Iterable<Element> elements = | 1583 Iterable<Element> elements = |
1584 backend.generatedCode.keys.where(isStaticFunction); | 1584 backend.generatedCode.keys.where(isStaticFunction); |
1585 Set<Element> pendingElementsWithBailouts = | 1585 Set<Element> pendingElementsWithBailouts = |
1586 backend.generatedBailoutCode.keys | 1586 backend.generatedBailoutCode.keys |
(...skipping 30 matching lines...) Expand all Loading... |
1617 // The static function does not have the correct name. Since | 1617 // The static function does not have the correct name. Since |
1618 // [addParameterStubs] use the name to create its stubs we simply | 1618 // [addParameterStubs] use the name to create its stubs we simply |
1619 // create a fake element with the correct name. | 1619 // create a fake element with the correct name. |
1620 // Note: the callElement will not have any enclosingElement. | 1620 // Note: the callElement will not have any enclosingElement. |
1621 FunctionElement callElement = | 1621 FunctionElement callElement = |
1622 new ClosureInvocationElement(namer.closureInvocationSelectorName, | 1622 new ClosureInvocationElement(namer.closureInvocationSelectorName, |
1623 element); | 1623 element); |
1624 String staticName = namer.getName(element); | 1624 String staticName = namer.getName(element); |
1625 String invocationName = namer.instanceMethodName(callElement); | 1625 String invocationName = namer.instanceMethodName(callElement); |
1626 String fieldAccess = '$isolateProperties.$staticName'; | 1626 String fieldAccess = '$isolateProperties.$staticName'; |
1627 buffer.add("$fieldAccess.$invocationName$_=$_$fieldAccess$N"); | 1627 buffer.write("$fieldAccess.$invocationName$_=$_$fieldAccess$N"); |
1628 | 1628 |
1629 addParameterStubs(callElement, (String name, jsAst.Expression value) { | 1629 addParameterStubs(callElement, (String name, jsAst.Expression value) { |
1630 jsAst.Expression assignment = | 1630 jsAst.Expression assignment = |
1631 js[isolateProperties][staticName][name].assign(value); | 1631 js[isolateProperties][staticName][name].assign(value); |
1632 buffer.add( | 1632 buffer.write(jsAst.prettyPrint(assignment.toStatement(), compiler)); |
1633 jsAst.prettyPrint(assignment.toStatement(), compiler)); | 1633 buffer.write('$N'); |
1634 buffer.add('$N'); | |
1635 }); | 1634 }); |
1636 | 1635 |
1637 // If a static function is used as a closure we need to add its name | 1636 // If a static function is used as a closure we need to add its name |
1638 // in case it is used in spawnFunction. | 1637 // in case it is used in spawnFunction. |
1639 String fieldName = namer.STATIC_CLOSURE_NAME_NAME; | 1638 String fieldName = namer.STATIC_CLOSURE_NAME_NAME; |
1640 buffer.add('$fieldAccess.$fieldName$_=$_"$staticName"$N'); | 1639 buffer.write('$fieldAccess.$fieldName$_=$_"$staticName"$N'); |
1641 getTypedefChecksOn(element.computeType(compiler)).forEach( | 1640 getTypedefChecksOn(element.computeType(compiler)).forEach( |
1642 (Element typedef) { | 1641 (Element typedef) { |
1643 String operator = namer.operatorIs(typedef); | 1642 String operator = namer.operatorIs(typedef); |
1644 buffer.add('$fieldAccess.$operator$_=${_}true$N'); | 1643 buffer.write('$fieldAccess.$operator$_=${_}true$N'); |
1645 } | 1644 } |
1646 ); | 1645 ); |
1647 } | 1646 } |
1648 } | 1647 } |
1649 | 1648 |
1650 void emitBoundClosureClassHeader(String mangledName, | 1649 void emitBoundClosureClassHeader(String mangledName, |
1651 String superName, | 1650 String superName, |
1652 List<String> fieldNames, | 1651 List<String> fieldNames, |
1653 ClassBuilder builder) { | 1652 ClassBuilder builder) { |
1654 builder.addProperty('', | 1653 builder.addProperty('', |
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1874 Iterable<VariableElement> staticNonFinalFields = | 1873 Iterable<VariableElement> staticNonFinalFields = |
1875 handler.getStaticNonFinalFieldsForEmission(); | 1874 handler.getStaticNonFinalFieldsForEmission(); |
1876 for (Element element in Elements.sortedByPosition(staticNonFinalFields)) { | 1875 for (Element element in Elements.sortedByPosition(staticNonFinalFields)) { |
1877 // [:interceptedNames:] is handled in [emitInterceptedNames]. | 1876 // [:interceptedNames:] is handled in [emitInterceptedNames]. |
1878 if (element == backend.interceptedNames) continue; | 1877 if (element == backend.interceptedNames) continue; |
1879 compiler.withCurrentElement(element, () { | 1878 compiler.withCurrentElement(element, () { |
1880 Constant initialValue = handler.getInitialValueFor(element); | 1879 Constant initialValue = handler.getInitialValueFor(element); |
1881 jsAst.Expression init = | 1880 jsAst.Expression init = |
1882 js[isolateProperties][namer.getName(element)].assign( | 1881 js[isolateProperties][namer.getName(element)].assign( |
1883 constantEmitter.referenceInInitializationContext(initialValue)); | 1882 constantEmitter.referenceInInitializationContext(initialValue)); |
1884 buffer.add(jsAst.prettyPrint(init, compiler)); | 1883 buffer.write(jsAst.prettyPrint(init, compiler)); |
1885 buffer.add('$N'); | 1884 buffer.write('$N'); |
1886 }); | 1885 }); |
1887 } | 1886 } |
1888 } | 1887 } |
1889 | 1888 |
1890 void emitLazilyInitializedStaticFields(CodeBuffer buffer) { | 1889 void emitLazilyInitializedStaticFields(CodeBuffer buffer) { |
1891 ConstantHandler handler = compiler.constantHandler; | 1890 ConstantHandler handler = compiler.constantHandler; |
1892 List<VariableElement> lazyFields = | 1891 List<VariableElement> lazyFields = |
1893 handler.getLazilyInitializedFieldsForEmission(); | 1892 handler.getLazilyInitializedFieldsForEmission(); |
1894 if (!lazyFields.isEmpty) { | 1893 if (!lazyFields.isEmpty) { |
1895 needsLazyInitializer = true; | 1894 needsLazyInitializer = true; |
(...skipping 10 matching lines...) Expand all Loading... |
1906 arguments.add(js[isolateProperties]); | 1905 arguments.add(js[isolateProperties]); |
1907 arguments.add(js.string(element.name.slowToString())); | 1906 arguments.add(js.string(element.name.slowToString())); |
1908 arguments.add(js.string(namer.getName(element))); | 1907 arguments.add(js.string(namer.getName(element))); |
1909 arguments.add(js.string(namer.getLazyInitializerName(element))); | 1908 arguments.add(js.string(namer.getLazyInitializerName(element))); |
1910 arguments.add(code); | 1909 arguments.add(code); |
1911 jsAst.Expression getter = buildLazyInitializedGetter(element); | 1910 jsAst.Expression getter = buildLazyInitializedGetter(element); |
1912 if (getter != null) { | 1911 if (getter != null) { |
1913 arguments.add(getter); | 1912 arguments.add(getter); |
1914 } | 1913 } |
1915 jsAst.Expression init = js[lazyInitializerName](arguments); | 1914 jsAst.Expression init = js[lazyInitializerName](arguments); |
1916 buffer.add(jsAst.prettyPrint(init, compiler)); | 1915 buffer.write(jsAst.prettyPrint(init, compiler)); |
1917 buffer.add("$N"); | 1916 buffer.write("$N"); |
1918 } | 1917 } |
1919 } | 1918 } |
1920 } | 1919 } |
1921 | 1920 |
1922 jsAst.Expression buildLazyInitializedGetter(VariableElement element) { | 1921 jsAst.Expression buildLazyInitializedGetter(VariableElement element) { |
1923 // Nothing to do, the 'lazy' function will create the getter. | 1922 // Nothing to do, the 'lazy' function will create the getter. |
1924 return null; | 1923 return null; |
1925 } | 1924 } |
1926 | 1925 |
1927 void emitCompileTimeConstants(CodeBuffer eagerBuffer) { | 1926 void emitCompileTimeConstants(CodeBuffer eagerBuffer) { |
(...skipping 12 matching lines...) Expand all Loading... |
1940 // share the ones that take up too much space (like some strings). | 1939 // share the ones that take up too much space (like some strings). |
1941 if (name == null) continue; | 1940 if (name == null) continue; |
1942 if (!addedMakeConstantList && constant.isList()) { | 1941 if (!addedMakeConstantList && constant.isList()) { |
1943 addedMakeConstantList = true; | 1942 addedMakeConstantList = true; |
1944 emitMakeConstantList(eagerBuffer); | 1943 emitMakeConstantList(eagerBuffer); |
1945 } | 1944 } |
1946 CodeBuffer buffer = | 1945 CodeBuffer buffer = |
1947 bufferForElement(constant.computeType(compiler).element, eagerBuffer); | 1946 bufferForElement(constant.computeType(compiler).element, eagerBuffer); |
1948 jsAst.Expression init = js[isolateProperties][name].assign( | 1947 jsAst.Expression init = js[isolateProperties][name].assign( |
1949 constantInitializerExpression(constant)); | 1948 constantInitializerExpression(constant)); |
1950 buffer.add(jsAst.prettyPrint(init, compiler)); | 1949 buffer.write(jsAst.prettyPrint(init, compiler)); |
1951 buffer.add('$N'); | 1950 buffer.write('$N'); |
1952 } | 1951 } |
1953 } | 1952 } |
1954 | 1953 |
1955 void emitMakeConstantList(CodeBuffer buffer) { | 1954 void emitMakeConstantList(CodeBuffer buffer) { |
1956 buffer.add(namer.isolateName); | 1955 buffer.write(namer.isolateName); |
1957 buffer.add(r'''.makeConstantList = function(list) { | 1956 buffer.write(r'''.makeConstantList = function(list) { |
1958 list.immutable$list = true; | 1957 list.immutable$list = true; |
1959 list.fixed$length = true; | 1958 list.fixed$length = true; |
1960 return list; | 1959 return list; |
1961 }; | 1960 }; |
1962 '''); | 1961 '''); |
1963 } | 1962 } |
1964 | 1963 |
1965 /** | 1964 /** |
1966 * Documentation wanted -- johnniwinther | 1965 * Documentation wanted -- johnniwinther |
1967 * | 1966 * |
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2122 String buildIsolateSetup(CodeBuffer buffer, | 2121 String buildIsolateSetup(CodeBuffer buffer, |
2123 Element appMain, | 2122 Element appMain, |
2124 Element isolateMain) { | 2123 Element isolateMain) { |
2125 String mainAccess = "${namer.isolateAccess(appMain)}"; | 2124 String mainAccess = "${namer.isolateAccess(appMain)}"; |
2126 String currentIsolate = "${namer.CURRENT_ISOLATE}"; | 2125 String currentIsolate = "${namer.CURRENT_ISOLATE}"; |
2127 // Since we pass the closurized version of the main method to | 2126 // Since we pass the closurized version of the main method to |
2128 // the isolate method, we must make sure that it exists. | 2127 // the isolate method, we must make sure that it exists. |
2129 if (!compiler.codegenWorld.staticFunctionsNeedingGetter.contains(appMain)) { | 2128 if (!compiler.codegenWorld.staticFunctionsNeedingGetter.contains(appMain)) { |
2130 Selector selector = new Selector.callClosure(0); | 2129 Selector selector = new Selector.callClosure(0); |
2131 String invocationName = namer.invocationName(selector); | 2130 String invocationName = namer.invocationName(selector); |
2132 buffer.add("$mainAccess.$invocationName = $mainAccess$N"); | 2131 buffer.write("$mainAccess.$invocationName = $mainAccess$N"); |
2133 } | 2132 } |
2134 return "${namer.isolateAccess(isolateMain)}($mainAccess)"; | 2133 return "${namer.isolateAccess(isolateMain)}($mainAccess)"; |
2135 } | 2134 } |
2136 | 2135 |
2137 emitMain(CodeBuffer buffer) { | 2136 emitMain(CodeBuffer buffer) { |
2138 if (compiler.isMockCompilation) return; | 2137 if (compiler.isMockCompilation) return; |
2139 Element main = compiler.mainApp.find(Compiler.MAIN); | 2138 Element main = compiler.mainApp.find(Compiler.MAIN); |
2140 String mainCall = null; | 2139 String mainCall = null; |
2141 if (compiler.hasIsolateSupport()) { | 2140 if (compiler.hasIsolateSupport()) { |
2142 Element isolateMain = | 2141 Element isolateMain = |
2143 compiler.isolateHelperLibrary.find(Compiler.START_ROOT_ISOLATE); | 2142 compiler.isolateHelperLibrary.find(Compiler.START_ROOT_ISOLATE); |
2144 mainCall = buildIsolateSetup(buffer, main, isolateMain); | 2143 mainCall = buildIsolateSetup(buffer, main, isolateMain); |
2145 } else { | 2144 } else { |
2146 mainCall = '${namer.isolateAccess(main)}()'; | 2145 mainCall = '${namer.isolateAccess(main)}()'; |
2147 } | 2146 } |
2148 addComment('BEGIN invoke [main].', buffer); | 2147 addComment('BEGIN invoke [main].', buffer); |
2149 buffer.add(""" | 2148 buffer.write(""" |
2150 if (typeof document !== "undefined" && document.readyState !== "complete") { | 2149 if (typeof document !== "undefined" && document.readyState !== "complete") { |
2151 document.addEventListener("readystatechange", function () { | 2150 document.addEventListener("readystatechange", function () { |
2152 if (document.readyState == "complete") { | 2151 if (document.readyState == "complete") { |
2153 if (typeof dartMainRunner === "function") { | 2152 if (typeof dartMainRunner === "function") { |
2154 dartMainRunner(function() { ${mainCall}; }); | 2153 dartMainRunner(function() { ${mainCall}; }); |
2155 } else { | 2154 } else { |
2156 ${mainCall}; | 2155 ${mainCall}; |
2157 } | 2156 } |
2158 } | 2157 } |
2159 }, false); | 2158 }, false); |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2272 if (hasBool) { | 2271 if (hasBool) { |
2273 block.statements.add(buildInterceptorCheck(backend.jsBoolClass)); | 2272 block.statements.add(buildInterceptorCheck(backend.jsBoolClass)); |
2274 } | 2273 } |
2275 // TODO(ahe): It might be faster to check for Array before | 2274 // TODO(ahe): It might be faster to check for Array before |
2276 // function and bool. | 2275 // function and bool. |
2277 if (hasArray) { | 2276 if (hasArray) { |
2278 block.statements.add(buildInterceptorCheck(backend.jsArrayClass)); | 2277 block.statements.add(buildInterceptorCheck(backend.jsArrayClass)); |
2279 } | 2278 } |
2280 block.statements.add(js.return_(receiver)); | 2279 block.statements.add(js.return_(receiver)); |
2281 | 2280 |
2282 buffer.add(jsAst.prettyPrint( | 2281 buffer.write(jsAst.prettyPrint( |
2283 js[isolateProperties][key].assign(js.fun(['receiver'], block)), | 2282 js[isolateProperties][key].assign(js.fun(['receiver'], block)), |
2284 compiler)); | 2283 compiler)); |
2285 buffer.add(N); | 2284 buffer.write(N); |
2286 } | 2285 } |
2287 | 2286 |
2288 /** | 2287 /** |
2289 * Emit all versions of the [:getInterceptor:] method. | 2288 * Emit all versions of the [:getInterceptor:] method. |
2290 */ | 2289 */ |
2291 void emitGetInterceptorMethods(CodeBuffer buffer) { | 2290 void emitGetInterceptorMethods(CodeBuffer buffer) { |
2292 var specializedGetInterceptors = backend.specializedGetInterceptors; | 2291 var specializedGetInterceptors = backend.specializedGetInterceptors; |
2293 for (String name in specializedGetInterceptors.keys.toList()..sort()) { | 2292 for (String name in specializedGetInterceptors.keys.toList()..sort()) { |
2294 Collection<ClassElement> classes = specializedGetInterceptors[name]; | 2293 Collection<ClassElement> classes = specializedGetInterceptors[name]; |
2295 emitGetInterceptorMethod(buffer, name, classes); | 2294 emitGetInterceptorMethod(buffer, name, classes); |
(...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2548 String invocationName = backend.namer.invocationName(selector); | 2547 String invocationName = backend.namer.invocationName(selector); |
2549 body.add(js.return_( | 2548 body.add(js.return_( |
2550 js[isolateProperties][getInterceptorName]('receiver')[invocationName]( | 2549 js[isolateProperties][getInterceptorName]('receiver')[invocationName]( |
2551 arguments))); | 2550 arguments))); |
2552 | 2551 |
2553 jsAst.Fun function = js.fun(parameters, body); | 2552 jsAst.Fun function = js.fun(parameters, body); |
2554 | 2553 |
2555 jsAst.PropertyAccess property = | 2554 jsAst.PropertyAccess property = |
2556 js[isolateProperties][name]; | 2555 js[isolateProperties][name]; |
2557 | 2556 |
2558 buffer.add(jsAst.prettyPrint(property.assign(function), compiler)); | 2557 buffer.write(jsAst.prettyPrint(property.assign(function), compiler)); |
2559 buffer.add(N); | 2558 buffer.write(N); |
2560 } | 2559 } |
2561 } | 2560 } |
2562 | 2561 |
2563 /** | 2562 /** |
2564 * If [:invokeOn:] has been compiled, emit all the possible selector names | 2563 * If [:invokeOn:] has been compiled, emit all the possible selector names |
2565 * that are intercepted into the [:interceptedNames:] top-level | 2564 * that are intercepted into the [:interceptedNames:] top-level |
2566 * variable. The implementation of [:invokeOn:] will use it to | 2565 * variable. The implementation of [:invokeOn:] will use it to |
2567 * determine whether it should call the method with an extra | 2566 * determine whether it should call the method with an extra |
2568 * parameter. | 2567 * parameter. |
2569 */ | 2568 */ |
2570 void emitInterceptedNames(CodeBuffer buffer) { | 2569 void emitInterceptedNames(CodeBuffer buffer) { |
2571 if (!compiler.enabledInvokeOn) return; | 2570 if (!compiler.enabledInvokeOn) return; |
2572 String name = backend.namer.getName(backend.interceptedNames); | 2571 String name = backend.namer.getName(backend.interceptedNames); |
2573 jsAst.PropertyAccess property = js[isolateProperties][name]; | 2572 jsAst.PropertyAccess property = js[isolateProperties][name]; |
2574 | 2573 |
2575 int index = 0; | 2574 int index = 0; |
2576 List<jsAst.ArrayElement> elements = backend.usedInterceptors.map( | 2575 List<jsAst.ArrayElement> elements = backend.usedInterceptors.map( |
2577 (Selector selector) { | 2576 (Selector selector) { |
2578 jsAst.Literal str = js.string(namer.invocationName(selector)); | 2577 jsAst.Literal str = js.string(namer.invocationName(selector)); |
2579 return new jsAst.ArrayElement(index++, str); | 2578 return new jsAst.ArrayElement(index++, str); |
2580 }).toList(); | 2579 }).toList(); |
2581 jsAst.ArrayInitializer array = new jsAst.ArrayInitializer( | 2580 jsAst.ArrayInitializer array = new jsAst.ArrayInitializer( |
2582 backend.usedInterceptors.length, | 2581 backend.usedInterceptors.length, |
2583 elements); | 2582 elements); |
2584 | 2583 |
2585 buffer.add(jsAst.prettyPrint(property.assign(array), compiler)); | 2584 buffer.write(jsAst.prettyPrint(property.assign(array), compiler)); |
2586 buffer.add(N); | 2585 buffer.write(N); |
2587 } | 2586 } |
2588 | 2587 |
2589 void emitInitFunction(CodeBuffer buffer) { | 2588 void emitInitFunction(CodeBuffer buffer) { |
2590 jsAst.Fun fun = js.fun([], [ | 2589 jsAst.Fun fun = js.fun([], [ |
2591 js['$isolateProperties = {}'], | 2590 js['$isolateProperties = {}'], |
2592 ] | 2591 ] |
2593 ..addAll(buildDefineClassAndFinishClassFunctionsIfNecessary()) | 2592 ..addAll(buildDefineClassAndFinishClassFunctionsIfNecessary()) |
2594 ..addAll(buildLazyInitializerFunctionIfNecessary()) | 2593 ..addAll(buildLazyInitializerFunctionIfNecessary()) |
2595 ..addAll(buildFinishIsolateConstructor()) | 2594 ..addAll(buildFinishIsolateConstructor()) |
2596 ); | 2595 ); |
2597 jsAst.FunctionDeclaration decl = new jsAst.FunctionDeclaration( | 2596 jsAst.FunctionDeclaration decl = new jsAst.FunctionDeclaration( |
2598 new jsAst.VariableDeclaration('init'), fun); | 2597 new jsAst.VariableDeclaration('init'), fun); |
2599 buffer.add(jsAst.prettyPrint(decl, compiler).getText()); | 2598 buffer.write(jsAst.prettyPrint(decl, compiler).getText()); |
2600 } | 2599 } |
2601 | 2600 |
2602 String assembleProgram() { | 2601 String assembleProgram() { |
2603 measure(() { | 2602 measure(() { |
2604 computeNeededClasses(); | 2603 computeNeededClasses(); |
2605 | 2604 |
2606 // Compute the required type checks to know which classes need a | 2605 // Compute the required type checks to know which classes need a |
2607 // 'is$' method. | 2606 // 'is$' method. |
2608 computeRequiredTypeChecks(); | 2607 computeRequiredTypeChecks(); |
2609 | 2608 |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2715 | 2714 |
2716 CodeBuffer bufferForElement(Element element, CodeBuffer eagerBuffer) { | 2715 CodeBuffer bufferForElement(Element element, CodeBuffer eagerBuffer) { |
2717 if (!isDeferred(element)) return eagerBuffer; | 2716 if (!isDeferred(element)) return eagerBuffer; |
2718 emitDeferredPreambleWhenEmpty(deferredBuffer); | 2717 emitDeferredPreambleWhenEmpty(deferredBuffer); |
2719 return deferredBuffer; | 2718 return deferredBuffer; |
2720 } | 2719 } |
2721 | 2720 |
2722 void emitDeferredCode(CodeBuffer buffer) { | 2721 void emitDeferredCode(CodeBuffer buffer) { |
2723 if (buffer.isEmpty) return; | 2722 if (buffer.isEmpty) return; |
2724 | 2723 |
2725 buffer.add(n); | 2724 buffer.write(n); |
2726 | 2725 |
2727 buffer.add('${namer.CURRENT_ISOLATE}$_=${_}old${namer.CURRENT_ISOLATE}$N'); | 2726 buffer.write( |
| 2727 '${namer.CURRENT_ISOLATE}$_=${_}old${namer.CURRENT_ISOLATE}$N'); |
2728 | 2728 |
2729 String code = buffer.getText(); | 2729 String code = buffer.getText(); |
2730 compiler.outputProvider('part', 'js') | 2730 compiler.outputProvider('part', 'js') |
2731 ..add(code) | 2731 ..add(code) |
2732 ..close(); | 2732 ..close(); |
2733 outputSourceMap(buffer, compiler.assembledCode, 'part'); | 2733 outputSourceMap(buffer, compiler.assembledCode, 'part'); |
2734 } | 2734 } |
2735 | 2735 |
2736 void emitDeferredPreambleWhenEmpty(CodeBuffer buffer) { | 2736 void emitDeferredPreambleWhenEmpty(CodeBuffer buffer) { |
2737 if (!buffer.isEmpty) return; | 2737 if (!buffer.isEmpty) return; |
2738 | 2738 |
2739 buffer.add(GENERATED_BY); | 2739 buffer.write(GENERATED_BY); |
2740 | 2740 |
2741 buffer.add('var old${namer.CURRENT_ISOLATE}$_=' | 2741 buffer.write('var old${namer.CURRENT_ISOLATE}$_=' |
2742 '$_${namer.CURRENT_ISOLATE}$N'); | 2742 '$_${namer.CURRENT_ISOLATE}$N'); |
2743 | 2743 |
2744 // TODO(ahe): This defines a lot of properties on the | 2744 // TODO(ahe): This defines a lot of properties on the |
2745 // Isolate.prototype object. We know this will turn it into a | 2745 // Isolate.prototype object. We know this will turn it into a |
2746 // slow object in V8, so instead we should do something similar to | 2746 // slow object in V8, so instead we should do something similar to |
2747 // Isolate.$finishIsolateConstructor. | 2747 // Isolate.$finishIsolateConstructor. |
2748 buffer.add('${namer.CURRENT_ISOLATE}$_=' | 2748 buffer.write('${namer.CURRENT_ISOLATE}$_=' |
2749 '$_${namer.isolateName}.prototype$N$n'); | 2749 '$_${namer.isolateName}.prototype$N$n'); |
2750 } | 2750 } |
2751 | 2751 |
2752 String buildSourceMap(CodeBuffer buffer, SourceFile compiledFile) { | 2752 String buildSourceMap(CodeBuffer buffer, SourceFile compiledFile) { |
2753 SourceMapBuilder sourceMapBuilder = new SourceMapBuilder(); | 2753 SourceMapBuilder sourceMapBuilder = new SourceMapBuilder(); |
2754 buffer.forEachSourceLocation(sourceMapBuilder.addMapping); | 2754 buffer.forEachSourceLocation(sourceMapBuilder.addMapping); |
2755 return sourceMapBuilder.build(compiledFile); | 2755 return sourceMapBuilder.build(compiledFile); |
2756 } | 2756 } |
2757 | 2757 |
2758 void outputSourceMap(CodeBuffer buffer, String code, String name) { | 2758 void outputSourceMap(CodeBuffer buffer, String code, String name) { |
2759 if (!generateSourceMap) return; | 2759 if (!generateSourceMap) return; |
(...skipping 21 matching lines...) Expand all Loading... |
2781 """; | 2781 """; |
2782 const String HOOKS_API_USAGE = """ | 2782 const String HOOKS_API_USAGE = """ |
2783 // The code supports the following hooks: | 2783 // The code supports the following hooks: |
2784 // dartPrint(message) - if this function is defined it is called | 2784 // dartPrint(message) - if this function is defined it is called |
2785 // instead of the Dart [print] method. | 2785 // instead of the Dart [print] method. |
2786 // dartMainRunner(main) - if this function is defined, the Dart [main] | 2786 // dartMainRunner(main) - if this function is defined, the Dart [main] |
2787 // method will not be invoked directly. | 2787 // method will not be invoked directly. |
2788 // Instead, a closure that will invoke [main] is | 2788 // Instead, a closure that will invoke [main] is |
2789 // passed to [dartMainRunner]. | 2789 // passed to [dartMainRunner]. |
2790 """; | 2790 """; |
OLD | NEW |