| 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 class JavaScriptItemCompilationContext extends ItemCompilationContext { | 7 class JavaScriptItemCompilationContext extends ItemCompilationContext { |
| 8 final Set<HInstruction> boundsChecked; | 8 final Set<HInstruction> boundsChecked; |
| 9 | 9 |
| 10 JavaScriptItemCompilationContext() | 10 JavaScriptItemCompilationContext() |
| (...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 326 /// List of symbols that the user has requested for reflection. | 326 /// List of symbols that the user has requested for reflection. |
| 327 final Set<String> symbolsUsed = new Set<String>(); | 327 final Set<String> symbolsUsed = new Set<String>(); |
| 328 | 328 |
| 329 /// List of elements that the user has requested for reflection. | 329 /// List of elements that the user has requested for reflection. |
| 330 final Set<Element> targetsUsed = new Set<Element>(); | 330 final Set<Element> targetsUsed = new Set<Element>(); |
| 331 | 331 |
| 332 /// List of annotations provided by user that indicate that the annotated | 332 /// List of annotations provided by user that indicate that the annotated |
| 333 /// element must be retained. | 333 /// element must be retained. |
| 334 final Set<Element> metaTargetsUsed = new Set<Element>(); | 334 final Set<Element> metaTargetsUsed = new Set<Element>(); |
| 335 | 335 |
| 336 /// List of elements that the backend may use. |
| 337 final Set<Element> helpersUsed = new Set<Element>(); |
| 338 |
| 336 JavaScriptBackend(Compiler compiler, bool generateSourceMap, bool disableEval) | 339 JavaScriptBackend(Compiler compiler, bool generateSourceMap, bool disableEval) |
| 337 : namer = determineNamer(compiler), | 340 : namer = determineNamer(compiler), |
| 338 oneShotInterceptors = new Map<String, Selector>(), | 341 oneShotInterceptors = new Map<String, Selector>(), |
| 339 interceptedElements = new Map<SourceString, Set<Element>>(), | 342 interceptedElements = new Map<SourceString, Set<Element>>(), |
| 340 rti = new RuntimeTypes(compiler), | 343 rti = new RuntimeTypes(compiler), |
| 341 specializedGetInterceptors = new Map<String, Set<ClassElement>>(), | 344 specializedGetInterceptors = new Map<String, Set<ClassElement>>(), |
| 342 super(compiler, JAVA_SCRIPT_CONSTANT_SYSTEM) { | 345 super(compiler, JAVA_SCRIPT_CONSTANT_SYSTEM) { |
| 343 emitter = disableEval | 346 emitter = disableEval |
| 344 ? new CodeEmitterNoEvalTask(compiler, namer, generateSourceMap) | 347 ? new CodeEmitterNoEvalTask(compiler, namer, generateSourceMap) |
| 345 : new CodeEmitterTask(compiler, namer, generateSourceMap); | 348 : new CodeEmitterTask(compiler, namer, generateSourceMap); |
| 346 builder = new SsaBuilderTask(this); | 349 builder = new SsaBuilderTask(this); |
| 347 optimizer = new SsaOptimizerTask(this); | 350 optimizer = new SsaOptimizerTask(this); |
| 348 generator = new SsaCodeGeneratorTask(this); | 351 generator = new SsaCodeGeneratorTask(this); |
| 349 } | 352 } |
| 350 | 353 |
| 351 static Namer determineNamer(Compiler compiler) { | 354 static Namer determineNamer(Compiler compiler) { |
| 352 return compiler.enableMinification ? | 355 return compiler.enableMinification ? |
| 353 new MinifyNamer(compiler) : | 356 new MinifyNamer(compiler) : |
| 354 new Namer(compiler); | 357 new Namer(compiler); |
| 355 } | 358 } |
| 356 | 359 |
| 360 bool canBeUsedForGlobalOptimizations(Element element) { |
| 361 return !helpersUsed.contains(element.declaration); |
| 362 } |
| 363 |
| 357 bool isInterceptorClass(ClassElement element) { | 364 bool isInterceptorClass(ClassElement element) { |
| 358 if (element == null) return false; | 365 if (element == null) return false; |
| 359 if (element.isNative()) return true; | 366 if (element.isNative()) return true; |
| 360 if (interceptedClasses.contains(element)) return true; | 367 if (interceptedClasses.contains(element)) return true; |
| 361 if (classesMixedIntoNativeClasses.contains(element)) return true; | 368 if (classesMixedIntoNativeClasses.contains(element)) return true; |
| 362 return false; | 369 return false; |
| 363 } | 370 } |
| 364 | 371 |
| 365 String registerOneShotInterceptor(Selector selector) { | 372 String registerOneShotInterceptor(Selector selector) { |
| 366 Set<ClassElement> classes = getInterceptedClassesOn(selector.name); | 373 Set<ClassElement> classes = getInterceptedClassesOn(selector.name); |
| (...skipping 367 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 734 world.registerStaticUse( | 741 world.registerStaticUse( |
| 735 compiler.findInterceptor(const SourceString('dispatchPropertyName'))); | 742 compiler.findInterceptor(const SourceString('dispatchPropertyName'))); |
| 736 } | 743 } |
| 737 | 744 |
| 738 if (compiler.enableTypeAssertions) { | 745 if (compiler.enableTypeAssertions) { |
| 739 // Unconditionally register the helper that checks if the | 746 // Unconditionally register the helper that checks if the |
| 740 // expression in an if/while/for is a boolean. | 747 // expression in an if/while/for is a boolean. |
| 741 // TODO(ngeoffray): Should we have the resolver register those instead? | 748 // TODO(ngeoffray): Should we have the resolver register those instead? |
| 742 Element e = | 749 Element e = |
| 743 compiler.findHelper(const SourceString('boolConversionCheck')); | 750 compiler.findHelper(const SourceString('boolConversionCheck')); |
| 744 if (e != null) world.addToWorkList(e); | 751 if (e != null) enqueue(world, e, elements); |
| 745 } | 752 } |
| 746 } | 753 } |
| 747 | 754 |
| 748 onResolutionComplete() => rti.computeClassesNeedingRti(); | 755 onResolutionComplete() => rti.computeClassesNeedingRti(); |
| 749 | 756 |
| 750 void registerStringInterpolation(TreeElements elements) { | 757 void registerStringInterpolation(TreeElements elements) { |
| 751 enqueueInResolution(getStringInterpolationHelper(), elements); | 758 enqueueInResolution(getStringInterpolationHelper(), elements); |
| 752 } | 759 } |
| 753 | 760 |
| 754 void registerCatchStatement(Enqueuer enqueuer, TreeElements elements) { | 761 void registerCatchStatement(Enqueuer enqueuer, TreeElements elements) { |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 838 } | 845 } |
| 839 | 846 |
| 840 void registerIsCheck(DartType type, Enqueuer world, TreeElements elements) { | 847 void registerIsCheck(DartType type, Enqueuer world, TreeElements elements) { |
| 841 type = type.unalias(compiler); | 848 type = type.unalias(compiler); |
| 842 world.registerInstantiatedClass(compiler.boolClass, elements); | 849 world.registerInstantiatedClass(compiler.boolClass, elements); |
| 843 bool inCheckedMode = compiler.enableTypeAssertions; | 850 bool inCheckedMode = compiler.enableTypeAssertions; |
| 844 // [registerIsCheck] is also called for checked mode checks, so we | 851 // [registerIsCheck] is also called for checked mode checks, so we |
| 845 // need to register checked mode helpers. | 852 // need to register checked mode helpers. |
| 846 if (inCheckedMode) { | 853 if (inCheckedMode) { |
| 847 CheckedModeHelper helper = getCheckedModeHelper(type, typeCast: false); | 854 CheckedModeHelper helper = getCheckedModeHelper(type, typeCast: false); |
| 848 if (helper != null) world.addToWorkList(helper.getElement(compiler)); | 855 if (helper != null) enqueue(world, helper.getElement(compiler), elements); |
| 849 // We also need the native variant of the check (for DOM types). | 856 // We also need the native variant of the check (for DOM types). |
| 850 helper = getNativeCheckedModeHelper(type, typeCast: false); | 857 helper = getNativeCheckedModeHelper(type, typeCast: false); |
| 851 if (helper != null) world.addToWorkList(helper.getElement(compiler)); | 858 if (helper != null) enqueue(world, helper.getElement(compiler), elements); |
| 852 } | 859 } |
| 853 bool isTypeVariable = type.kind == TypeKind.TYPE_VARIABLE; | 860 bool isTypeVariable = type.kind == TypeKind.TYPE_VARIABLE; |
| 854 if (!type.isRaw || type.containsTypeVariables) { | 861 if (!type.isRaw || type.containsTypeVariables) { |
| 855 enqueueInResolution(getSetRuntimeTypeInfo(), elements); | 862 enqueueInResolution(getSetRuntimeTypeInfo(), elements); |
| 856 enqueueInResolution(getGetRuntimeTypeInfo(), elements); | 863 enqueueInResolution(getGetRuntimeTypeInfo(), elements); |
| 857 enqueueInResolution(getGetRuntimeTypeArgument(), elements); | 864 enqueueInResolution(getGetRuntimeTypeArgument(), elements); |
| 858 if (inCheckedMode) { | 865 if (inCheckedMode) { |
| 859 enqueueInResolution(getAssertSubtype(), elements); | 866 enqueueInResolution(getAssertSubtype(), elements); |
| 860 } | 867 } |
| 861 enqueueInResolution(getCheckSubtype(), elements); | 868 enqueueInResolution(getCheckSubtype(), elements); |
| 862 if (isTypeVariable) { | 869 if (isTypeVariable) { |
| 863 enqueueInResolution(getCheckSubtypeOfRuntimeType(), elements); | 870 enqueueInResolution(getCheckSubtypeOfRuntimeType(), elements); |
| 864 if (inCheckedMode) { | 871 if (inCheckedMode) { |
| 865 enqueueInResolution(getAssertSubtypeOfRuntimeType(), elements); | 872 enqueueInResolution(getAssertSubtypeOfRuntimeType(), elements); |
| 866 } | 873 } |
| 867 } | 874 } |
| 868 world.registerInstantiatedClass(compiler.listClass, elements); | 875 world.registerInstantiatedClass(compiler.listClass, elements); |
| 869 } | 876 } |
| 870 if (type is FunctionType) { | 877 if (type is FunctionType) { |
| 871 enqueueInResolution(getCheckFunctionSubtype(), elements); | 878 enqueueInResolution(getCheckFunctionSubtype(), elements); |
| 872 } | 879 } |
| 873 if (type.element.isNative()) { | 880 if (type.element.isNative()) { |
| 874 // We will neeed to add the "$is" and "$as" properties on the | 881 // We will neeed to add the "$is" and "$as" properties on the |
| 875 // JavaScript object prototype, so we make sure | 882 // JavaScript object prototype, so we make sure |
| 876 // [:defineProperty:] is compiled. | 883 // [:defineProperty:] is compiled. |
| 877 world.addToWorkList( | 884 enqueue(world, |
| 878 compiler.findHelper(const SourceString('defineProperty'))); | 885 compiler.findHelper(const SourceString('defineProperty')), |
| 886 elements); |
| 879 } | 887 } |
| 880 } | 888 } |
| 881 | 889 |
| 882 void registerAsCheck(DartType type, TreeElements elements) { | 890 void registerAsCheck(DartType type, TreeElements elements) { |
| 883 type = type.unalias(compiler); | 891 type = type.unalias(compiler); |
| 884 CheckedModeHelper helper = getCheckedModeHelper(type, typeCast: true); | 892 CheckedModeHelper helper = getCheckedModeHelper(type, typeCast: true); |
| 885 enqueueInResolution(helper.getElement(compiler), elements); | 893 enqueueInResolution(helper.getElement(compiler), elements); |
| 886 // We also need the native variant of the check (for DOM types). | 894 // We also need the native variant of the check (for DOM types). |
| 887 helper = getNativeCheckedModeHelper(type, typeCast: true); | 895 helper = getNativeCheckedModeHelper(type, typeCast: true); |
| 888 if (helper != null) { | 896 if (helper != null) { |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 969 return classElement == compiler.objectClass | 977 return classElement == compiler.objectClass |
| 970 || classElement == jsInterceptorClass | 978 || classElement == jsInterceptorClass |
| 971 || classElement == jsNullClass; | 979 || classElement == jsNullClass; |
| 972 } | 980 } |
| 973 | 981 |
| 974 bool methodNeedsRti(FunctionElement function) { | 982 bool methodNeedsRti(FunctionElement function) { |
| 975 return rti.methodsNeedingRti.contains(function) || | 983 return rti.methodsNeedingRti.contains(function) || |
| 976 compiler.enabledRuntimeType; | 984 compiler.enabledRuntimeType; |
| 977 } | 985 } |
| 978 | 986 |
| 987 // Enqueue [e] in [enqueuer]. |
| 988 // |
| 989 // The backend must *always* call this method when enqueuing an |
| 990 // element. Calls done by the backend are not seen by global |
| 991 // optimizations, so they would make these optimizations unsound. |
| 992 // Therefore we need to collect the list of helpers the backend may |
| 993 // use. |
| 979 void enqueue(Enqueuer enqueuer, Element e, TreeElements elements) { | 994 void enqueue(Enqueuer enqueuer, Element e, TreeElements elements) { |
| 995 helpersUsed.add(e.declaration); |
| 980 enqueuer.addToWorkList(e); | 996 enqueuer.addToWorkList(e); |
| 981 elements.registerDependency(e); | 997 elements.registerDependency(e); |
| 982 } | 998 } |
| 983 | 999 |
| 984 void enqueueInResolution(Element e, TreeElements elements) { | 1000 void enqueueInResolution(Element e, TreeElements elements) { |
| 985 if (e == null) return; | 1001 if (e == null) return; |
| 986 ResolutionEnqueuer enqueuer = compiler.enqueuer.resolution; | 1002 ResolutionEnqueuer enqueuer = compiler.enqueuer.resolution; |
| 987 enqueue(enqueuer, e, elements); | 1003 enqueue(enqueuer, e, elements); |
| 988 } | 1004 } |
| 989 | 1005 |
| (...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1322 } | 1338 } |
| 1323 | 1339 |
| 1324 Element getCreateInvocationMirror() { | 1340 Element getCreateInvocationMirror() { |
| 1325 return compiler.findHelper(Compiler.CREATE_INVOCATION_MIRROR); | 1341 return compiler.findHelper(Compiler.CREATE_INVOCATION_MIRROR); |
| 1326 } | 1342 } |
| 1327 | 1343 |
| 1328 Element getCyclicThrowHelper() { | 1344 Element getCyclicThrowHelper() { |
| 1329 return compiler.findHelper(const SourceString("throwCyclicInit")); | 1345 return compiler.findHelper(const SourceString("throwCyclicInit")); |
| 1330 } | 1346 } |
| 1331 | 1347 |
| 1332 /** | |
| 1333 * Remove [element] from the set of generated code, and put it back | |
| 1334 * into the worklist. | |
| 1335 * | |
| 1336 * Invariant: [element] must be a declaration element. | |
| 1337 */ | |
| 1338 void eagerRecompile(Element element) { | |
| 1339 assert(invariant(element, element.isDeclaration)); | |
| 1340 generatedCode.remove(element); | |
| 1341 generatedBailoutCode.remove(element); | |
| 1342 compiler.enqueuer.codegen.addToWorkList(element); | |
| 1343 } | |
| 1344 | |
| 1345 bool isNullImplementation(ClassElement cls) { | 1348 bool isNullImplementation(ClassElement cls) { |
| 1346 return cls == jsNullClass; | 1349 return cls == jsNullClass; |
| 1347 } | 1350 } |
| 1348 | 1351 |
| 1349 ClassElement get intImplementation => jsIntClass; | 1352 ClassElement get intImplementation => jsIntClass; |
| 1350 ClassElement get doubleImplementation => jsDoubleClass; | 1353 ClassElement get doubleImplementation => jsDoubleClass; |
| 1351 ClassElement get numImplementation => jsNumberClass; | 1354 ClassElement get numImplementation => jsNumberClass; |
| 1352 ClassElement get stringImplementation => jsStringClass; | 1355 ClassElement get stringImplementation => jsStringClass; |
| 1353 ClassElement get listImplementation => jsArrayClass; | 1356 ClassElement get listImplementation => jsArrayClass; |
| 1354 ClassElement get constListImplementation => jsArrayClass; | 1357 ClassElement get constListImplementation => jsArrayClass; |
| (...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1577 copy(constant.values); | 1580 copy(constant.values); |
| 1578 copy(constant.protoValue); | 1581 copy(constant.protoValue); |
| 1579 copy(constant); | 1582 copy(constant); |
| 1580 } | 1583 } |
| 1581 | 1584 |
| 1582 void visitConstructed(ConstructedConstant constant) { | 1585 void visitConstructed(ConstructedConstant constant) { |
| 1583 copy(constant.fields); | 1586 copy(constant.fields); |
| 1584 copy(constant); | 1587 copy(constant); |
| 1585 } | 1588 } |
| 1586 } | 1589 } |
| OLD | NEW |