| 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 ssa; | 5 part of ssa; |
| 6 | 6 |
| 7 /** | 7 /** |
| 8 * A special element for the extra parameter taken by intercepted | 8 * A special element for the extra parameter taken by intercepted |
| 9 * methods. We need to override [Element.computeType] because our | 9 * methods. We need to override [Element.computeType] because our |
| 10 * optimizers may look at its declared type. | 10 * optimizers may look at its declared type. |
| (...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 172 void redirectElement(Element from, Element to) { | 172 void redirectElement(Element from, Element to) { |
| 173 assert(redirectionMapping[from] == null); | 173 assert(redirectionMapping[from] == null); |
| 174 redirectionMapping[from] = to; | 174 redirectionMapping[from] = to; |
| 175 assert(isStoredInClosureField(from) || isBoxed(from)); | 175 assert(isStoredInClosureField(from) || isBoxed(from)); |
| 176 } | 176 } |
| 177 | 177 |
| 178 HInstruction createBox() { | 178 HInstruction createBox() { |
| 179 // TODO(floitsch): Clean up this hack. Should we create a box-object by | 179 // TODO(floitsch): Clean up this hack. Should we create a box-object by |
| 180 // just creating an empty object literal? | 180 // just creating an empty object literal? |
| 181 HInstruction box = new HForeign(const LiteralDartString("{}"), | 181 HInstruction box = new HForeign(const LiteralDartString("{}"), |
| 182 const LiteralDartString('Object'), | 182 HType.UNKNOWN, |
| 183 <HInstruction>[]); | 183 <HInstruction>[]); |
| 184 builder.add(box); | 184 builder.add(box); |
| 185 return box; | 185 return box; |
| 186 } | 186 } |
| 187 | 187 |
| 188 /** | 188 /** |
| 189 * If the scope (function or loop) [node] has captured variables then this | 189 * If the scope (function or loop) [node] has captured variables then this |
| 190 * method creates a box and sets up the redirections. | 190 * method creates a box and sets up the redirections. |
| 191 */ | 191 */ |
| 192 void enterScope(Node node, Element element) { | 192 void enterScope(Node node, Element element) { |
| (...skipping 1158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1351 // Call the JavaScript constructor with the fields as argument. | 1351 // Call the JavaScript constructor with the fields as argument. |
| 1352 List<HInstruction> constructorArguments = <HInstruction>[]; | 1352 List<HInstruction> constructorArguments = <HInstruction>[]; |
| 1353 classElement.forEachInstanceField( | 1353 classElement.forEachInstanceField( |
| 1354 (ClassElement enclosingClass, Element member) { | 1354 (ClassElement enclosingClass, Element member) { |
| 1355 constructorArguments.add(potentiallyCheckType( | 1355 constructorArguments.add(potentiallyCheckType( |
| 1356 fieldValues[member], member.computeType(compiler))); | 1356 fieldValues[member], member.computeType(compiler))); |
| 1357 }, | 1357 }, |
| 1358 includeBackendMembers: true, | 1358 includeBackendMembers: true, |
| 1359 includeSuperMembers: true); | 1359 includeSuperMembers: true); |
| 1360 | 1360 |
| 1361 HForeignNew newObject = new HForeignNew(classElement, constructorArguments); | 1361 InterfaceType type = classElement.computeType(compiler); |
| 1362 HType ssaType = new HBoundedType.exact(type); |
| 1363 HForeignNew newObject = new HForeignNew(classElement, |
| 1364 ssaType, |
| 1365 constructorArguments); |
| 1362 add(newObject); | 1366 add(newObject); |
| 1363 | 1367 |
| 1364 // Create the runtime type information, if needed. | 1368 // Create the runtime type information, if needed. |
| 1365 InterfaceType type = classElement.computeType(compiler); | |
| 1366 List<HInstruction> inputs = <HInstruction>[]; | 1369 List<HInstruction> inputs = <HInstruction>[]; |
| 1367 if (compiler.world.needsRti(classElement)) { | 1370 if (compiler.world.needsRti(classElement)) { |
| 1368 classElement.typeVariables.forEach((TypeVariableType typeVariable) { | 1371 classElement.typeVariables.forEach((TypeVariableType typeVariable) { |
| 1369 inputs.add(localsHandler.directLocals[typeVariable.element]); | 1372 inputs.add(localsHandler.directLocals[typeVariable.element]); |
| 1370 }); | 1373 }); |
| 1371 callSetRuntimeTypeInfo(classElement, inputs, newObject); | 1374 callSetRuntimeTypeInfo(classElement, inputs, newObject); |
| 1372 } | 1375 } |
| 1373 | 1376 |
| 1374 // Generate calls to the constructor bodies. | 1377 // Generate calls to the constructor bodies. |
| 1375 for (int index = constructors.length - 1; index >= 0; index--) { | 1378 for (int index = constructors.length - 1; index >= 0; index--) { |
| (...skipping 762 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2138 closureClassElement.forEachBackendMember((Element member) { | 2141 closureClassElement.forEachBackendMember((Element member) { |
| 2139 // The backendMembers also contains the call method(s). We are only | 2142 // The backendMembers also contains the call method(s). We are only |
| 2140 // interested in the fields. | 2143 // interested in the fields. |
| 2141 if (member.isField()) { | 2144 if (member.isField()) { |
| 2142 Element capturedLocal = nestedClosureData.capturedFieldMapping[member]; | 2145 Element capturedLocal = nestedClosureData.capturedFieldMapping[member]; |
| 2143 assert(capturedLocal != null); | 2146 assert(capturedLocal != null); |
| 2144 capturedVariables.add(localsHandler.readLocal(capturedLocal)); | 2147 capturedVariables.add(localsHandler.readLocal(capturedLocal)); |
| 2145 } | 2148 } |
| 2146 }); | 2149 }); |
| 2147 | 2150 |
| 2148 push(new HForeignNew(closureClassElement, capturedVariables)); | 2151 HType type = new HBoundedType.exact( |
| 2152 compiler.functionClass.computeType(compiler)); |
| 2153 push(new HForeignNew(closureClassElement, type, capturedVariables)); |
| 2149 } | 2154 } |
| 2150 | 2155 |
| 2151 visitFunctionDeclaration(FunctionDeclaration node) { | 2156 visitFunctionDeclaration(FunctionDeclaration node) { |
| 2152 visit(node.function); | 2157 visit(node.function); |
| 2153 localsHandler.updateLocal(elements[node], pop()); | 2158 localsHandler.updateLocal(elements[node], pop()); |
| 2154 } | 2159 } |
| 2155 | 2160 |
| 2156 visitIdentifier(Identifier node) { | 2161 visitIdentifier(Identifier node) { |
| 2157 if (node.isThis()) { | 2162 if (node.isThis()) { |
| 2158 stack.add(localsHandler.readThis()); | 2163 stack.add(localsHandler.readThis()); |
| (...skipping 373 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2532 | 2537 |
| 2533 void pushInvokeHelper5(Element helper, HInstruction a0, HInstruction a1, | 2538 void pushInvokeHelper5(Element helper, HInstruction a0, HInstruction a1, |
| 2534 HInstruction a2, HInstruction a3, HInstruction a4) { | 2539 HInstruction a2, HInstruction a3, HInstruction a4) { |
| 2535 HInstruction reference = new HStatic(helper); | 2540 HInstruction reference = new HStatic(helper); |
| 2536 add(reference); | 2541 add(reference); |
| 2537 List<HInstruction> inputs = <HInstruction>[reference, a0, a1, a2, a3, a4]; | 2542 List<HInstruction> inputs = <HInstruction>[reference, a0, a1, a2, a3, a4]; |
| 2538 HInstruction result = new HInvokeStatic(inputs); | 2543 HInstruction result = new HInvokeStatic(inputs); |
| 2539 push(result); | 2544 push(result); |
| 2540 } | 2545 } |
| 2541 | 2546 |
| 2542 HForeign createForeign(String code, String type, List<HInstruction> inputs) { | 2547 HForeign createForeign(String code, HType type, List<HInstruction> inputs) { |
| 2543 return new HForeign(new LiteralDartString(code), | 2548 return new HForeign(new LiteralDartString(code), type, inputs); |
| 2544 new LiteralDartString(type), | |
| 2545 inputs); | |
| 2546 } | 2549 } |
| 2547 | 2550 |
| 2548 HInstruction getRuntimeTypeInfo(HInstruction target) { | 2551 HInstruction getRuntimeTypeInfo(HInstruction target) { |
| 2549 pushInvokeHelper1(backend.getGetRuntimeTypeInfo(), target); | 2552 pushInvokeHelper1(backend.getGetRuntimeTypeInfo(), target); |
| 2550 return pop(); | 2553 return pop(); |
| 2551 } | 2554 } |
| 2552 | 2555 |
| 2553 // TODO(karlklose): change construction of the representations to be GVN'able | 2556 // TODO(karlklose): change construction of the representations to be GVN'able |
| 2554 // (dartbug.com/7182). | 2557 // (dartbug.com/7182). |
| 2555 List<HInstruction> buildTypeArgumentRepresentations(DartType type) { | 2558 List<HInstruction> buildTypeArgumentRepresentations(DartType type) { |
| 2556 HInstruction createForeignArray(String code, inputs) { | 2559 HInstruction createForeignArray(String code, inputs) { |
| 2557 return createForeign(code, '=List', inputs); | 2560 return createForeign(code, HType.READABLE_ARRAY, inputs); |
| 2558 } | 2561 } |
| 2559 HInstruction typeInfo; | 2562 HInstruction typeInfo; |
| 2560 | 2563 |
| 2561 /// Helper to create an instruction that contains the runtime value of | 2564 /// Helper to create an instruction that contains the runtime value of |
| 2562 /// the type variable [variable]. | 2565 /// the type variable [variable]. |
| 2563 HInstruction getTypeArgument(TypeVariableType variable) { | 2566 HInstruction getTypeArgument(TypeVariableType variable) { |
| 2564 if (typeInfo == null) { | 2567 if (typeInfo == null) { |
| 2565 typeInfo = getRuntimeTypeInfo(localsHandler.readThis()); | 2568 typeInfo = getRuntimeTypeInfo(localsHandler.readThis()); |
| 2566 } | 2569 } |
| 2567 int intIndex = RuntimeTypeInformation.getTypeVariableIndex(variable); | 2570 int intIndex = RuntimeTypeInformation.getTypeVariableIndex(variable); |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2647 buildTypeArgumentRepresentations(type); | 2650 buildTypeArgumentRepresentations(type); |
| 2648 // For each type argument, build a call to isSubtype, with the type | 2651 // For each type argument, build a call to isSubtype, with the type |
| 2649 // argument as first and the representation of the tested type as | 2652 // argument as first and the representation of the tested type as |
| 2650 // second argument. | 2653 // second argument. |
| 2651 List<HInstruction> checks = <HInstruction>[]; | 2654 List<HInstruction> checks = <HInstruction>[]; |
| 2652 int index = 0; | 2655 int index = 0; |
| 2653 representations.forEach((HInstruction representation) { | 2656 representations.forEach((HInstruction representation) { |
| 2654 HInstruction position = graph.addConstantInt(index, constantSystem); | 2657 HInstruction position = graph.addConstantInt(index, constantSystem); |
| 2655 // Get the index'th type argument from the runtime type information. | 2658 // Get the index'th type argument from the runtime type information. |
| 2656 HInstruction typeArgument = | 2659 HInstruction typeArgument = |
| 2657 createForeign('#[#]', 'Object', [typeInfo, position]); | 2660 createForeign('#[#]', HType.UNKNOWN, [typeInfo, position]); |
| 2658 add(typeArgument); | 2661 add(typeArgument); |
| 2659 // Create the call to isSubtype. | 2662 // Create the call to isSubtype. |
| 2660 List<HInstruction> inputs = | 2663 List<HInstruction> inputs = |
| 2661 <HInstruction>[isSubtype, typeArgument, representation]; | 2664 <HInstruction>[isSubtype, typeArgument, representation]; |
| 2662 HInstruction call = new HInvokeStatic(inputs); | 2665 HInstruction call = new HInvokeStatic(inputs); |
| 2663 add(call); | 2666 add(call); |
| 2664 checks.add(call); | 2667 checks.add(call); |
| 2665 index++; | 2668 index++; |
| 2666 }); | 2669 }); |
| 2667 instruction = new HIs(type, <HInstruction>[expression]..addAll(checks)); | 2670 instruction = new HIs(type, <HInstruction>[expression]..addAll(checks)); |
| (...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2845 assert(Elements.isLocal(element)); | 2848 assert(Elements.isLocal(element)); |
| 2846 closureTarget = localsHandler.readLocal(element); | 2849 closureTarget = localsHandler.readLocal(element); |
| 2847 } | 2850 } |
| 2848 var inputs = <HInstruction>[]; | 2851 var inputs = <HInstruction>[]; |
| 2849 inputs.add(closureTarget); | 2852 inputs.add(closureTarget); |
| 2850 addDynamicSendArgumentsToList(node, inputs); | 2853 addDynamicSendArgumentsToList(node, inputs); |
| 2851 Selector closureSelector = new Selector.callClosureFrom(selector); | 2854 Selector closureSelector = new Selector.callClosureFrom(selector); |
| 2852 pushWithPosition(new HInvokeClosure(closureSelector, inputs), node); | 2855 pushWithPosition(new HInvokeClosure(closureSelector, inputs), node); |
| 2853 } | 2856 } |
| 2854 | 2857 |
| 2855 void registerForeignTypes(String specString) { | |
| 2856 CodegenEnqueuer enqueuer = compiler.enqueuer.codegen; | |
| 2857 for (final typeString in specString.split('|')) { | |
| 2858 if (typeString == '=List') { | |
| 2859 enqueuer.registerInstantiatedClass(compiler.listClass); | |
| 2860 } else if (typeString == 'int') { | |
| 2861 enqueuer.registerInstantiatedClass(compiler.intClass); | |
| 2862 } else if (typeString == 'double') { | |
| 2863 enqueuer.registerInstantiatedClass(compiler.doubleClass); | |
| 2864 } else if (typeString == 'num') { | |
| 2865 enqueuer.registerInstantiatedClass(compiler.intClass); | |
| 2866 enqueuer.registerInstantiatedClass(compiler.doubleClass); | |
| 2867 } else if (typeString == 'Null') { | |
| 2868 enqueuer.registerInstantiatedClass(compiler.nullClass); | |
| 2869 } else if (typeString == 'String') { | |
| 2870 enqueuer.registerInstantiatedClass(compiler.stringClass); | |
| 2871 } | |
| 2872 } | |
| 2873 } | |
| 2874 | |
| 2875 void handleForeignJs(Send node) { | 2858 void handleForeignJs(Send node) { |
| 2876 Link<Node> link = node.arguments; | 2859 Link<Node> link = node.arguments; |
| 2877 // If the invoke is on foreign code, don't visit the first | 2860 // If the invoke is on foreign code, don't visit the first |
| 2878 // argument, which is the type, and the second argument, | 2861 // argument, which is the type, and the second argument, |
| 2879 // which is the foreign code. | 2862 // which is the foreign code. |
| 2880 if (link.isEmpty || link.tail.isEmpty) { | 2863 if (link.isEmpty || link.tail.isEmpty) { |
| 2881 compiler.cancel('At least two arguments expected', | 2864 compiler.cancel('At least two arguments expected', |
| 2882 node: node.argumentsNode); | 2865 node: node.argumentsNode); |
| 2883 } | 2866 } |
| 2884 List<HInstruction> inputs = <HInstruction>[]; | 2867 List<HInstruction> inputs = <HInstruction>[]; |
| 2885 Node type = link.head; | 2868 Node type = link.head; |
| 2886 Node code = link.tail.head; | 2869 Node code = link.tail.head; |
| 2887 addGenericSendArgumentsToList(link.tail.tail, inputs); | 2870 addGenericSendArgumentsToList(link.tail.tail, inputs); |
| 2888 | 2871 |
| 2889 if (type is !LiteralString) { | 2872 native.NativeBehavior nativeBehavior = |
| 2890 // The type must not be a juxtaposition or interpolation. | 2873 compiler.enqueuer.resolution.nativeEnqueuer.getNativeBehaviorOf(node); |
| 2891 compiler.cancel('The type of a JS expression must be a string literal', | 2874 HType ssaType = mapNativeBehaviorType(nativeBehavior); |
| 2892 node: type); | |
| 2893 } | |
| 2894 LiteralString typeString = type; | |
| 2895 // TODO(ngeoffray): This should be registered in codegen, not here. | |
| 2896 // Also, we should share the type parsing with the native | |
| 2897 // enqueuer. | |
| 2898 registerForeignTypes(typeString.dartString.slowToString()); | |
| 2899 | |
| 2900 if (code is StringNode) { | 2875 if (code is StringNode) { |
| 2901 StringNode codeString = code; | 2876 StringNode codeString = code; |
| 2902 if (!codeString.isInterpolation) { | 2877 if (!codeString.isInterpolation) { |
| 2903 // codeString may not be an interpolation, but may be a juxtaposition. | 2878 // codeString may not be an interpolation, but may be a juxtaposition. |
| 2904 push(new HForeign(codeString.dartString, | 2879 push(new HForeign(codeString.dartString, ssaType, inputs)); |
| 2905 typeString.dartString, | |
| 2906 inputs)); | |
| 2907 return; | 2880 return; |
| 2908 } | 2881 } |
| 2909 } | 2882 } |
| 2910 compiler.cancel('JS code must be a string literal', node: code); | 2883 compiler.cancel('JS code must be a string literal', node: code); |
| 2911 } | 2884 } |
| 2912 | 2885 |
| 2913 void handleForeignJsCurrentIsolate(Send node) { | 2886 void handleForeignJsCurrentIsolate(Send node) { |
| 2914 if (!node.arguments.isEmpty) { | 2887 if (!node.arguments.isEmpty) { |
| 2915 compiler.cancel( | 2888 compiler.cancel( |
| 2916 'Too many arguments to JS_CURRENT_ISOLATE', node: node); | 2889 'Too many arguments to JS_CURRENT_ISOLATE', node: node); |
| 2917 } | 2890 } |
| 2918 | 2891 |
| 2919 if (!compiler.hasIsolateSupport()) { | 2892 if (!compiler.hasIsolateSupport()) { |
| 2920 // If the isolate library is not used, we just generate code | 2893 // If the isolate library is not used, we just generate code |
| 2921 // to fetch the Leg's current isolate. | 2894 // to fetch the Leg's current isolate. |
| 2922 String name = backend.namer.CURRENT_ISOLATE; | 2895 String name = backend.namer.CURRENT_ISOLATE; |
| 2923 push(new HForeign(new DartString.literal(name), | 2896 push(new HForeign(new DartString.literal(name), |
| 2924 const LiteralDartString('var'), | 2897 HType.UNKNOWN, |
| 2925 <HInstruction>[])); | 2898 <HInstruction>[])); |
| 2926 } else { | 2899 } else { |
| 2927 // Call a helper method from the isolate library. The isolate | 2900 // Call a helper method from the isolate library. The isolate |
| 2928 // library uses its own isolate structure, that encapsulates | 2901 // library uses its own isolate structure, that encapsulates |
| 2929 // Leg's isolate. | 2902 // Leg's isolate. |
| 2930 Element element = compiler.isolateHelperLibrary.find( | 2903 Element element = compiler.isolateHelperLibrary.find( |
| 2931 const SourceString('_currentIsolate')); | 2904 const SourceString('_currentIsolate')); |
| 2932 if (element == null) { | 2905 if (element == null) { |
| 2933 compiler.cancel( | 2906 compiler.cancel( |
| 2934 'Isolate library and compiler mismatch', node: node); | 2907 'Isolate library and compiler mismatch', node: node); |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2987 visit(closure); | 2960 visit(closure); |
| 2988 return params; | 2961 return params; |
| 2989 } | 2962 } |
| 2990 | 2963 |
| 2991 void handleForeignDartClosureToJs(Send node, String name) { | 2964 void handleForeignDartClosureToJs(Send node, String name) { |
| 2992 FunctionSignature params = handleForeignRawFunctionRef(node, name); | 2965 FunctionSignature params = handleForeignRawFunctionRef(node, name); |
| 2993 List<HInstruction> inputs = <HInstruction>[pop()]; | 2966 List<HInstruction> inputs = <HInstruction>[pop()]; |
| 2994 String invocationName = backend.namer.invocationName( | 2967 String invocationName = backend.namer.invocationName( |
| 2995 new Selector.callClosure(params.requiredParameterCount)); | 2968 new Selector.callClosure(params.requiredParameterCount)); |
| 2996 push(new HForeign(new DartString.literal('#.$invocationName'), | 2969 push(new HForeign(new DartString.literal('#.$invocationName'), |
| 2997 const LiteralDartString('var'), | 2970 HType.UNKNOWN, |
| 2998 inputs)); | 2971 inputs)); |
| 2999 } | 2972 } |
| 3000 | 2973 |
| 3001 void handleForeignSetCurrentIsolate(Send node) { | 2974 void handleForeignSetCurrentIsolate(Send node) { |
| 3002 if (node.arguments.isEmpty || !node.arguments.tail.isEmpty) { | 2975 if (node.arguments.isEmpty || !node.arguments.tail.isEmpty) { |
| 3003 compiler.cancel('Exactly one argument required', | 2976 compiler.cancel('Exactly one argument required', |
| 3004 node: node.argumentsNode); | 2977 node: node.argumentsNode); |
| 3005 } | 2978 } |
| 3006 visit(node.arguments.head); | 2979 visit(node.arguments.head); |
| 3007 String isolateName = backend.namer.CURRENT_ISOLATE; | 2980 String isolateName = backend.namer.CURRENT_ISOLATE; |
| 3008 push(new HForeign(new DartString.literal("$isolateName = #"), | 2981 push(new HForeign(new DartString.literal("$isolateName = #"), |
| 3009 const LiteralDartString('void'), | 2982 HType.UNKNOWN, |
| 3010 <HInstruction>[pop()])); | 2983 <HInstruction>[pop()])); |
| 3011 } | 2984 } |
| 3012 | 2985 |
| 3013 void handleForeignCreateIsolate(Send node) { | 2986 void handleForeignCreateIsolate(Send node) { |
| 3014 if (!node.arguments.isEmpty) { | 2987 if (!node.arguments.isEmpty) { |
| 3015 compiler.cancel('Too many arguments', | 2988 compiler.cancel('Too many arguments', |
| 3016 node: node.argumentsNode); | 2989 node: node.argumentsNode); |
| 3017 } | 2990 } |
| 3018 String constructorName = backend.namer.isolateName; | 2991 String constructorName = backend.namer.isolateName; |
| 3019 push(new HForeign(new DartString.literal("new $constructorName"), | 2992 push(new HForeign(new DartString.literal("new $constructorName"), |
| 3020 const LiteralDartString('var'), | 2993 HType.UNKNOWN, |
| 3021 <HInstruction>[])); | 2994 <HInstruction>[])); |
| 3022 } | 2995 } |
| 3023 | 2996 |
| 3024 visitForeignSend(Send node) { | 2997 visitForeignSend(Send node) { |
| 3025 Selector selector = elements.getSelector(node); | 2998 Selector selector = elements.getSelector(node); |
| 3026 SourceString name = selector.name; | 2999 SourceString name = selector.name; |
| 3027 if (name == const SourceString('JS')) { | 3000 if (name == const SourceString('JS')) { |
| 3028 handleForeignJs(node); | 3001 handleForeignJs(node); |
| 3029 } else if (name == const SourceString('JS_CURRENT_ISOLATE')) { | 3002 } else if (name == const SourceString('JS_CURRENT_ISOLATE')) { |
| 3030 handleForeignJsCurrentIsolate(node); | 3003 handleForeignJsCurrentIsolate(node); |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3177 inputs.add(localsHandler.readLocal(type.element)); | 3150 inputs.add(localsHandler.readLocal(type.element)); |
| 3178 } else if (member.isInstanceMember() | 3151 } else if (member.isInstanceMember() |
| 3179 || member.isGenerativeConstructor()) { | 3152 || member.isGenerativeConstructor()) { |
| 3180 // The type variable is stored in [this]. | 3153 // The type variable is stored in [this]. |
| 3181 if (typeInfo == null) { | 3154 if (typeInfo == null) { |
| 3182 pushInvokeHelper1(backend.getGetRuntimeTypeInfo(), | 3155 pushInvokeHelper1(backend.getGetRuntimeTypeInfo(), |
| 3183 localsHandler.readThis()); | 3156 localsHandler.readThis()); |
| 3184 typeInfo = pop(); | 3157 typeInfo = pop(); |
| 3185 } | 3158 } |
| 3186 int index = RuntimeTypeInformation.getTypeVariableIndex(type); | 3159 int index = RuntimeTypeInformation.getTypeVariableIndex(type); |
| 3187 HInstruction foreign = createForeign('#[$index]', 'String', | 3160 HInstruction foreign = createForeign('#[$index]', HType.STRING, |
| 3188 <HInstruction>[typeInfo]); | 3161 <HInstruction>[typeInfo]); |
| 3189 add(foreign); | 3162 add(foreign); |
| 3190 inputs.add(foreign); | 3163 inputs.add(foreign); |
| 3191 } else { | 3164 } else { |
| 3192 // TODO(ngeoffray): Match the VM behavior and throw an | 3165 // TODO(ngeoffray): Match the VM behavior and throw an |
| 3193 // exception at runtime. | 3166 // exception at runtime. |
| 3194 compiler.cancel('Unimplemented unresolved type variable', | 3167 compiler.cancel('Unimplemented unresolved type variable', |
| 3195 node: currentNode); | 3168 node: currentNode); |
| 3196 } | 3169 } |
| 3197 } | 3170 } |
| 3198 | 3171 |
| 3199 String template = rti.getTypeRepresentation(argument, | 3172 String template = rti.getTypeRepresentation(argument, |
| 3200 addTypeVariableReference); | 3173 addTypeVariableReference); |
| 3201 HInstruction result = createForeign(template, 'String', inputs); | 3174 HInstruction result = createForeign(template, HType.STRING, inputs); |
| 3202 add(result); | 3175 add(result); |
| 3203 return result; | 3176 return result; |
| 3204 } | 3177 } |
| 3205 | 3178 |
| 3206 void handleListConstructor(InterfaceType type, | 3179 void handleListConstructor(InterfaceType type, |
| 3207 Node currentNode, | 3180 Node currentNode, |
| 3208 HInstruction newObject) { | 3181 HInstruction newObject) { |
| 3209 if (!compiler.world.needsRti(type.element)) return; | 3182 if (!compiler.world.needsRti(type.element)) return; |
| 3210 List<HInstruction> inputs = <HInstruction>[]; | 3183 List<HInstruction> inputs = <HInstruction>[]; |
| 3211 if (!type.isRaw) { | 3184 if (!type.isRaw) { |
| (...skipping 1391 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4603 } | 4576 } |
| 4604 | 4577 |
| 4605 visitTypedef(Typedef node) { | 4578 visitTypedef(Typedef node) { |
| 4606 compiler.unimplemented('SsaBuilder.visitTypedef', node: node); | 4579 compiler.unimplemented('SsaBuilder.visitTypedef', node: node); |
| 4607 } | 4580 } |
| 4608 | 4581 |
| 4609 visitTypeVariable(TypeVariable node) { | 4582 visitTypeVariable(TypeVariable node) { |
| 4610 compiler.internalError('SsaBuilder.visitTypeVariable'); | 4583 compiler.internalError('SsaBuilder.visitTypeVariable'); |
| 4611 } | 4584 } |
| 4612 | 4585 |
| 4586 HType mapBaseType(BaseType baseType) { |
| 4587 if (!baseType.isClass()) return HType.UNKNOWN; |
| 4588 ClassBaseType classBaseType = baseType; |
| 4589 return new HType.fromBoundedType( |
| 4590 classBaseType.element.computeType(compiler), compiler, false); |
| 4591 } |
| 4592 |
| 4613 HType mapInferredType(ConcreteType concreteType) { | 4593 HType mapInferredType(ConcreteType concreteType) { |
| 4614 if (concreteType == null) return HType.UNKNOWN; | 4594 if (concreteType == null) return HType.UNKNOWN; |
| 4615 ClassElement element = concreteType.getUniqueType(); | 4595 HType ssaType = HType.CONFLICTING; |
| 4616 if (element == null) return HType.UNKNOWN; | 4596 for (BaseType baseType in concreteType.baseTypes) { |
| 4617 if (element == builder.compiler.boolClass) return HType.BOOLEAN; | 4597 ssaType = ssaType.union(mapBaseType(baseType), compiler); |
| 4618 if (element == builder.compiler.doubleClass) return HType.DOUBLE; | 4598 } |
| 4619 if (element == builder.compiler.intClass) return HType.INTEGER; | 4599 assert(!ssaType.isConflicting()); |
| 4620 if (element == builder.compiler.listClass) return HType.READABLE_ARRAY; | 4600 return ssaType; |
| 4621 if (element == builder.compiler.nullClass) return HType.NULL; | 4601 } |
| 4622 if (element == builder.compiler.stringClass) return HType.STRING; | 4602 |
| 4623 return HType.UNKNOWN; | 4603 HType mapNativeType(type) { |
| 4604 if (type == native.SpecialType.JsObject) { |
| 4605 return new HBoundedType.exact( |
| 4606 compiler.objectClass.computeType(compiler)); |
| 4607 } else if (type == native.SpecialType.JsArray) { |
| 4608 return HType.READABLE_ARRAY; |
| 4609 } else { |
| 4610 return new HType.fromBoundedType(type, compiler, false); |
| 4611 } |
| 4612 } |
| 4613 |
| 4614 HType mapNativeBehaviorType(native.NativeBehavior nativeBehavior) { |
| 4615 if (nativeBehavior.typesInstantiated.isEmpty) return HType.UNKNOWN; |
| 4616 |
| 4617 HType ssaType = HType.CONFLICTING; |
| 4618 for (final type in nativeBehavior.typesInstantiated) { |
| 4619 ssaType = ssaType.union(mapNativeType(type), compiler); |
| 4620 } |
| 4621 assert(!ssaType.isConflicting()); |
| 4622 return ssaType; |
| 4624 } | 4623 } |
| 4625 } | 4624 } |
| 4626 | 4625 |
| 4627 /** | 4626 /** |
| 4628 * Visitor that handles generation of string literals (LiteralString, | 4627 * Visitor that handles generation of string literals (LiteralString, |
| 4629 * StringInterpolation), and otherwise delegates to the given visitor for | 4628 * StringInterpolation), and otherwise delegates to the given visitor for |
| 4630 * non-literal subexpressions. | 4629 * non-literal subexpressions. |
| 4631 * TODO(lrn): Consider whether to handle compile time constant int/boolean | 4630 * TODO(lrn): Consider whether to handle compile time constant int/boolean |
| 4632 * expressions as well. | 4631 * expressions as well. |
| 4633 */ | 4632 */ |
| (...skipping 367 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5001 new HSubGraphBlockInformation(elseBranch.graph)); | 5000 new HSubGraphBlockInformation(elseBranch.graph)); |
| 5002 | 5001 |
| 5003 HBasicBlock conditionStartBlock = conditionBranch.block; | 5002 HBasicBlock conditionStartBlock = conditionBranch.block; |
| 5004 conditionStartBlock.setBlockFlow(info, joinBlock); | 5003 conditionStartBlock.setBlockFlow(info, joinBlock); |
| 5005 SubGraph conditionGraph = conditionBranch.graph; | 5004 SubGraph conditionGraph = conditionBranch.graph; |
| 5006 HIf branch = conditionGraph.end.last; | 5005 HIf branch = conditionGraph.end.last; |
| 5007 assert(branch is HIf); | 5006 assert(branch is HIf); |
| 5008 branch.blockInformation = conditionStartBlock.blockFlow; | 5007 branch.blockInformation = conditionStartBlock.blockFlow; |
| 5009 } | 5008 } |
| 5010 } | 5009 } |
| OLD | NEW |