Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(478)

Side by Side Diff: pkg/compiler/lib/src/ssa/builder.dart

Issue 2479323003: Adding check or trust type checks to builder_kernel.dart. (Closed)
Patch Set: .. Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | pkg/compiler/lib/src/ssa/builder_kernel.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 import 'dart:collection'; 5 import 'dart:collection';
6 6
7 import 'package:js_runtime/shared/embedded_names.dart'; 7 import 'package:js_runtime/shared/embedded_names.dart';
8 8
9 import '../closure.dart'; 9 import '../closure.dart';
10 import '../common.dart'; 10 import '../common.dart';
(...skipping 18 matching lines...) Expand all
29 import '../js_emitter/js_emitter.dart' show CodeEmitterTask, NativeEmitter; 29 import '../js_emitter/js_emitter.dart' show CodeEmitterTask, NativeEmitter;
30 import '../native/native.dart' as native; 30 import '../native/native.dart' as native;
31 import '../resolution/operators.dart'; 31 import '../resolution/operators.dart';
32 import '../resolution/semantic_visitor.dart'; 32 import '../resolution/semantic_visitor.dart';
33 import '../resolution/tree_elements.dart' show TreeElements; 33 import '../resolution/tree_elements.dart' show TreeElements;
34 import '../tree/tree.dart' as ast; 34 import '../tree/tree.dart' as ast;
35 import '../types/types.dart'; 35 import '../types/types.dart';
36 import '../universe/call_structure.dart' show CallStructure; 36 import '../universe/call_structure.dart' show CallStructure;
37 import '../universe/selector.dart' show Selector; 37 import '../universe/selector.dart' show Selector;
38 import '../universe/side_effects.dart' show SideEffects; 38 import '../universe/side_effects.dart' show SideEffects;
39 import '../universe/use.dart' show DynamicUse, StaticUse, TypeUse; 39 import '../universe/use.dart' show DynamicUse, StaticUse;
40 import '../util/util.dart'; 40 import '../util/util.dart';
41 import '../world.dart' show ClosedWorld; 41 import '../world.dart' show ClosedWorld;
42 42
43 import 'graph_builder.dart'; 43 import 'graph_builder.dart';
44 import 'jump_handler.dart'; 44 import 'jump_handler.dart';
45 import 'locals_handler.dart'; 45 import 'locals_handler.dart';
46 import 'loop_handler.dart'; 46 import 'loop_handler.dart';
47 import 'nodes.dart'; 47 import 'nodes.dart';
48 import 'optimize.dart'; 48 import 'optimize.dart';
49 import 'ssa_branch_builder.dart'; 49 import 'ssa_branch_builder.dart';
50 import 'type_builder.dart';
50 import 'types.dart'; 51 import 'types.dart';
51 52
52 class SsaBuilderTask extends CompilerTask { 53 class SsaBuilderTask extends CompilerTask {
53 final CodeEmitterTask emitter; 54 final CodeEmitterTask emitter;
54 final JavaScriptBackend backend; 55 final JavaScriptBackend backend;
55 final SourceInformationStrategy sourceInformationFactory; 56 final SourceInformationStrategy sourceInformationFactory;
56 final Compiler compiler; 57 final Compiler compiler;
57 58
58 String get name => 'SSA builder'; 59 String get name => 'SSA builder';
59 60
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
181 /// Returns `true` if the current element is an `async` function. 182 /// Returns `true` if the current element is an `async` function.
182 bool get isBuildingAsyncFunction { 183 bool get isBuildingAsyncFunction {
183 Element element = sourceElement; 184 Element element = sourceElement;
184 return (element is FunctionElement && 185 return (element is FunctionElement &&
185 element.asyncMarker == AsyncMarker.ASYNC); 186 element.asyncMarker == AsyncMarker.ASYNC);
186 } 187 }
187 188
188 /// Handles the building of loops. 189 /// Handles the building of loops.
189 LoopHandler<ast.Node> loopHandler; 190 LoopHandler<ast.Node> loopHandler;
190 191
192 /// Handles type check building.
193 TypeBuilder typeBuilder;
194
191 // TODO(sigmund): make most args optional 195 // TODO(sigmund): make most args optional
192 SsaBuilder( 196 SsaBuilder(
193 this.target, 197 this.target,
194 this.resolvedAst, 198 this.resolvedAst,
195 this.registry, 199 this.registry,
196 JavaScriptBackend backend, 200 JavaScriptBackend backend,
197 this.nativeEmitter, 201 this.nativeEmitter,
198 SourceInformationStrategy sourceInformationFactory) 202 SourceInformationStrategy sourceInformationFactory)
199 : this.infoReporter = backend.compiler.dumpInfoTask, 203 : this.infoReporter = backend.compiler.dumpInfoTask,
200 this.backend = backend, 204 this.backend = backend,
201 this.constantSystem = backend.constantSystem, 205 this.constantSystem = backend.constantSystem,
202 this.rti = backend.rti, 206 this.rti = backend.rti,
203 this.inferenceResults = backend.compiler.globalInference.results { 207 this.inferenceResults = backend.compiler.globalInference.results {
204 assert(target.isImplementation); 208 assert(target.isImplementation);
205 compiler = backend.compiler; 209 compiler = backend.compiler;
206 elementInferenceResults = _resultOf(target); 210 elementInferenceResults = _resultOf(target);
207 assert(elementInferenceResults != null); 211 assert(elementInferenceResults != null);
208 graph.element = target; 212 graph.element = target;
209 sourceElementStack.add(target); 213 sourceElementStack.add(target);
210 sourceInformationBuilder = 214 sourceInformationBuilder =
211 sourceInformationFactory.createBuilderForContext(resolvedAst); 215 sourceInformationFactory.createBuilderForContext(resolvedAst);
212 graph.sourceInformation = 216 graph.sourceInformation =
213 sourceInformationBuilder.buildVariableDeclaration(); 217 sourceInformationBuilder.buildVariableDeclaration();
214 localsHandler = new LocalsHandler(this, target, null, compiler); 218 localsHandler = new LocalsHandler(this, target, null, compiler);
215 loopHandler = new SsaLoopHandler(this); 219 loopHandler = new SsaLoopHandler(this);
220 typeBuilder = new TypeBuilder(this);
216 } 221 }
217 222
218 BackendHelpers get helpers => backend.helpers; 223 BackendHelpers get helpers => backend.helpers;
219 224
220 RuntimeTypesEncoder get rtiEncoder => backend.rtiEncoder; 225 RuntimeTypesEncoder get rtiEncoder => backend.rtiEncoder;
221 226
222 DiagnosticReporter get reporter => compiler.reporter; 227 DiagnosticReporter get reporter => compiler.reporter;
223 228
224 CoreClasses get coreClasses => compiler.coreClasses; 229 CoreClasses get coreClasses => compiler.coreClasses;
225 230
231 Element get targetElement => target;
232
226 /// Reference to resolved elements in [target]'s AST. 233 /// Reference to resolved elements in [target]'s AST.
227 TreeElements get elements => resolvedAst.elements; 234 TreeElements get elements => resolvedAst.elements;
228 235
229 @override 236 @override
230 SemanticSendVisitor get sendVisitor => this; 237 SemanticSendVisitor get sendVisitor => this;
231 238
232 @override 239 @override
233 void visitNode(ast.Node node) { 240 void visitNode(ast.Node node) {
234 internalError(node, "Unhandled node: $node"); 241 internalError(node, "Unhandled node: $node");
235 } 242 }
236 243
237 @override 244 @override
238 void apply(ast.Node node, [_]) { 245 void apply(ast.Node node, [_]) {
239 node.accept(this); 246 node.accept(this);
240 } 247 }
241 248
242 /// Returns the current source element. 249 /// Returns the current source element.
243 /// 250 ///
244 /// The returned element is a declaration element. 251 /// The returned element is a declaration element.
245 // TODO(johnniwinther): Check that all usages of sourceElement agree on 252 // TODO(johnniwinther): Check that all usages of sourceElement agree on
246 // implementation/declaration distinction. 253 // implementation/declaration distinction.
254 @override
247 Element get sourceElement => sourceElementStack.last; 255 Element get sourceElement => sourceElementStack.last;
248 256
249 /// Helper to retrieve global inference results for [element] with special 257 /// Helper to retrieve global inference results for [element] with special
250 /// care for `ConstructorBodyElement`s which don't exist at the time the 258 /// care for `ConstructorBodyElement`s which don't exist at the time the
251 /// global analysis run. 259 /// global analysis run.
252 /// 260 ///
253 /// Note: this helper is used selectively. When we know that we are in a 261 /// Note: this helper is used selectively. When we know that we are in a
254 /// context were we don't expect to see a constructor body element, we 262 /// context were we don't expect to see a constructor body element, we
255 /// directly fetch the data from the global inference results. 263 /// directly fetch the data from the global inference results.
256 GlobalTypeInferenceElementResult _resultOf(AstElement element) => 264 GlobalTypeInferenceElementResult _resultOf(AstElement element) =>
257 inferenceResults.resultOf( 265 inferenceResults.resultOf(
258 element is ConstructorBodyElementX ? element.constructor : element); 266 element is ConstructorBodyElementX ? element.constructor : element);
259 267
260 bool get _checkOrTrustTypes =>
261 compiler.options.enableTypeAssertions ||
262 compiler.options.trustTypeAnnotations;
263
264 /// Build the graph for [target]. 268 /// Build the graph for [target].
265 HGraph build() { 269 HGraph build() {
266 assert(invariant(target, target.isImplementation)); 270 assert(invariant(target, target.isImplementation));
267 HInstruction.idCounter = 0; 271 HInstruction.idCounter = 0;
268 // TODO(sigmund): remove `result` and return graph directly, need to ensure 272 // TODO(sigmund): remove `result` and return graph directly, need to ensure
269 // that it can never be null (see result in buildFactory for instance). 273 // that it can never be null (see result in buildFactory for instance).
270 var result; 274 var result;
271 if (target.isGenerativeConstructor) { 275 if (target.isGenerativeConstructor) {
272 result = buildFactory(resolvedAst); 276 result = buildFactory(resolvedAst);
273 } else if (target.isGenerativeConstructorBody || 277 } else if (target.isGenerativeConstructorBody ||
(...skipping 13 matching lines...) Expand all
287 reporter.internalError(target, 'Unexpected element kind $target.'); 291 reporter.internalError(target, 'Unexpected element kind $target.');
288 } 292 }
289 assert(result.isValid()); 293 assert(result.isValid());
290 return result; 294 return result;
291 } 295 }
292 296
293 void addWithPosition(HInstruction instruction, ast.Node node) { 297 void addWithPosition(HInstruction instruction, ast.Node node) {
294 add(attachPosition(instruction, node)); 298 add(attachPosition(instruction, node));
295 } 299 }
296 300
301 HTypeConversion buildFunctionTypeConversion(
302 HInstruction original, DartType type, int kind) {
303 String name =
304 kind == HTypeConversion.CAST_TYPE_CHECK ? '_asCheck' : '_assertCheck';
305
306 List<HInstruction> arguments = <HInstruction>[
307 buildFunctionType(type),
308 original
309 ];
310 pushInvokeDynamic(
311 null,
312 new Selector.call(
313 new Name(name, helpers.jsHelperLibrary), CallStructure.ONE_ARG),
314 null,
315 arguments);
316
317 return new HTypeConversion(type, kind, original.instructionType, pop());
318 }
319
297 /** 320 /**
298 * Returns a complete argument list for a call of [function]. 321 * Returns a complete argument list for a call of [function].
299 */ 322 */
300 List<HInstruction> completeSendArgumentsList( 323 List<HInstruction> completeSendArgumentsList(
301 FunctionElement function, 324 FunctionElement function,
302 Selector selector, 325 Selector selector,
303 List<HInstruction> providedArguments, 326 List<HInstruction> providedArguments,
304 ast.Node currentNode) { 327 ast.Node currentNode) {
305 assert(invariant(function, function.isImplementation)); 328 assert(invariant(function, function.isImplementation));
306 assert(providedArguments != null); 329 assert(providedArguments != null);
(...skipping 437 matching lines...) Expand 10 before | Expand all | Expand 10 after
744 ResolvedAst resolvedAst = field.resolvedAst; 767 ResolvedAst resolvedAst = field.resolvedAst;
745 openFunction(field, resolvedAst.node); 768 openFunction(field, resolvedAst.node);
746 HInstruction thisInstruction = localsHandler.readThis(); 769 HInstruction thisInstruction = localsHandler.readThis();
747 // Use dynamic type because the type computed by the inferrer is 770 // Use dynamic type because the type computed by the inferrer is
748 // narrowed to the type annotation. 771 // narrowed to the type annotation.
749 HInstruction parameter = new HParameterValue(field, backend.dynamicType); 772 HInstruction parameter = new HParameterValue(field, backend.dynamicType);
750 // Add the parameter as the last instruction of the entry block. 773 // Add the parameter as the last instruction of the entry block.
751 // If the method is intercepted, we want the actual receiver 774 // If the method is intercepted, we want the actual receiver
752 // to be the first parameter. 775 // to be the first parameter.
753 graph.entry.addBefore(graph.entry.last, parameter); 776 graph.entry.addBefore(graph.entry.last, parameter);
754 HInstruction value = potentiallyCheckOrTrustType(parameter, field.type); 777 HInstruction value =
778 typeBuilder.potentiallyCheckOrTrustType(parameter, field.type);
755 add(new HFieldSet(field, thisInstruction, value)); 779 add(new HFieldSet(field, thisInstruction, value));
756 return closeFunction(); 780 return closeFunction();
757 } 781 }
758 782
759 HGraph buildLazyInitializer(VariableElement variable) { 783 HGraph buildLazyInitializer(VariableElement variable) {
760 assert(invariant(variable, resolvedAst.element == variable, 784 assert(invariant(variable, resolvedAst.element == variable,
761 message: "Unexpected variable $variable for $resolvedAst.")); 785 message: "Unexpected variable $variable for $resolvedAst."));
762 inLazyInitializerExpression = true; 786 inLazyInitializerExpression = true;
763 ast.VariableDefinitions node = resolvedAst.node; 787 ast.VariableDefinitions node = resolvedAst.node;
764 ast.Node initializer = resolvedAst.body; 788 ast.Node initializer = resolvedAst.body;
765 assert(invariant(variable, initializer != null, 789 assert(invariant(variable, initializer != null,
766 message: "Non-constant variable $variable has no initializer.")); 790 message: "Non-constant variable $variable has no initializer."));
767 openFunction(variable, node); 791 openFunction(variable, node);
768 visit(initializer); 792 visit(initializer);
769 HInstruction value = pop(); 793 HInstruction value = pop();
770 value = potentiallyCheckOrTrustType(value, variable.type); 794 value = typeBuilder.potentiallyCheckOrTrustType(value, variable.type);
771 // In the case of multiple declarations (and some definitions) on the same 795 // In the case of multiple declarations (and some definitions) on the same
772 // line, the source pointer needs to point to the right initialized 796 // line, the source pointer needs to point to the right initialized
773 // variable. So find the specific initialized variable we are referring to. 797 // variable. So find the specific initialized variable we are referring to.
774 ast.Node sourceInfoNode = initializer; 798 ast.Node sourceInfoNode = initializer;
775 for (var definition in node.definitions) { 799 for (var definition in node.definitions) {
776 if (definition is ast.SendSet && 800 if (definition is ast.SendSet &&
777 definition.selector.asIdentifier().source == variable.name) { 801 definition.selector.asIdentifier().source == variable.name) {
778 sourceInfoNode = definition.assignmentOperator; 802 sourceInfoNode = definition.assignmentOperator;
779 break; 803 break;
780 } 804 }
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
892 elementInferenceResults = state.oldElementInferenceResults; 916 elementInferenceResults = state.oldElementInferenceResults;
893 returnType = state.oldReturnType; 917 returnType = state.oldReturnType;
894 assert(stack.isEmpty); 918 assert(stack.isEmpty);
895 stack = state.oldStack; 919 stack = state.oldStack;
896 } 920 }
897 921
898 /** 922 /**
899 * Run this builder on the body of the [function] to be inlined. 923 * Run this builder on the body of the [function] to be inlined.
900 */ 924 */
901 void visitInlinedFunction(ResolvedAst resolvedAst) { 925 void visitInlinedFunction(ResolvedAst resolvedAst) {
902 potentiallyCheckInlinedParameterTypes(resolvedAst.element.implementation); 926 typeBuilder.potentiallyCheckInlinedParameterTypes(
927 resolvedAst.element.implementation);
903 928
904 if (resolvedAst.element.isGenerativeConstructor) { 929 if (resolvedAst.element.isGenerativeConstructor) {
905 buildFactory(resolvedAst); 930 buildFactory(resolvedAst);
906 } else { 931 } else {
907 ast.FunctionExpression functionNode = resolvedAst.node; 932 ast.FunctionExpression functionNode = resolvedAst.node;
908 functionNode.body.accept(this); 933 functionNode.body.accept(this);
909 } 934 }
910 } 935 }
911 936
912 addInlinedInstantiation(DartType type) { 937 addInlinedInstantiation(DartType type) {
(...skipping 12 matching lines...) Expand all
925 /* When inlining the iterator methods generated for a [:for-in:] loop, the 950 /* When inlining the iterator methods generated for a [:for-in:] loop, the
926 * [currentNode] is the [ForIn] tree. The compiler-generated iterator 951 * [currentNode] is the [ForIn] tree. The compiler-generated iterator
927 * invocations are known to have fully specified argument lists, no default 952 * invocations are known to have fully specified argument lists, no default
928 * arguments are used. See invocations of [pushInvokeDynamic] in 953 * arguments are used. See invocations of [pushInvokeDynamic] in
929 * [visitForIn]. 954 * [visitForIn].
930 */ 955 */
931 return currentNode.asForIn() != null; 956 return currentNode.asForIn() != null;
932 } 957 }
933 958
934 /** 959 /**
935 * In checked mode, generate type tests for the parameters of the inlined
936 * function.
937 */
938 void potentiallyCheckInlinedParameterTypes(FunctionElement function) {
939 if (!_checkOrTrustTypes) return;
940
941 FunctionSignature signature = function.functionSignature;
942 signature.orderedForEachParameter((ParameterElement parameter) {
943 HInstruction argument = localsHandler.readLocal(parameter);
944 potentiallyCheckOrTrustType(argument, parameter.type);
945 });
946 }
947
948 /**
949 * Documentation wanted -- johnniwinther 960 * Documentation wanted -- johnniwinther
950 * 961 *
951 * Invariant: [constructors] must contain only implementation elements. 962 * Invariant: [constructors] must contain only implementation elements.
952 */ 963 */
953 void inlineSuperOrRedirect( 964 void inlineSuperOrRedirect(
954 ResolvedAst constructorResolvedAst, 965 ResolvedAst constructorResolvedAst,
955 List<HInstruction> compiledArguments, 966 List<HInstruction> compiledArguments,
956 List<ResolvedAst> constructorResolvedAsts, 967 List<ResolvedAst> constructorResolvedAsts,
957 Map<Element, HInstruction> fieldValues, 968 Map<Element, HInstruction> fieldValues,
958 FunctionElement caller) { 969 FunctionElement caller) {
(...skipping 14 matching lines...) Expand all
973 List<DartType> arguments = type.typeArguments; 984 List<DartType> arguments = type.typeArguments;
974 List<DartType> typeVariables = enclosingClass.typeVariables; 985 List<DartType> typeVariables = enclosingClass.typeVariables;
975 if (!type.isRaw) { 986 if (!type.isRaw) {
976 assert(arguments.length == typeVariables.length); 987 assert(arguments.length == typeVariables.length);
977 Iterator<DartType> variables = typeVariables.iterator; 988 Iterator<DartType> variables = typeVariables.iterator;
978 type.typeArguments.forEach((DartType argument) { 989 type.typeArguments.forEach((DartType argument) {
979 variables.moveNext(); 990 variables.moveNext();
980 TypeVariableType typeVariable = variables.current; 991 TypeVariableType typeVariable = variables.current;
981 localsHandler.updateLocal( 992 localsHandler.updateLocal(
982 localsHandler.getTypeVariableAsLocal(typeVariable), 993 localsHandler.getTypeVariableAsLocal(typeVariable),
983 analyzeTypeArgument(argument)); 994 typeBuilder.analyzeTypeArgument(argument, sourceElement));
984 }); 995 });
985 } else { 996 } else {
986 // If the supertype is a raw type, we need to set to null the 997 // If the supertype is a raw type, we need to set to null the
987 // type variables. 998 // type variables.
988 for (TypeVariableType variable in typeVariables) { 999 for (TypeVariableType variable in typeVariables) {
989 localsHandler.updateLocal( 1000 localsHandler.updateLocal(
990 localsHandler.getTypeVariableAsLocal(variable), 1001 localsHandler.getTypeVariableAsLocal(variable),
991 graph.addConstantNull(compiler)); 1002 graph.addConstantNull(compiler));
992 } 1003 }
993 } 1004 }
(...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after
1275 (ClassElement enclosingClass, FieldElement member) { 1286 (ClassElement enclosingClass, FieldElement member) {
1276 HInstruction value = fieldValues[member]; 1287 HInstruction value = fieldValues[member];
1277 if (value == null) { 1288 if (value == null) {
1278 // Uninitialized native fields are pre-initialized by the native 1289 // Uninitialized native fields are pre-initialized by the native
1279 // implementation. 1290 // implementation.
1280 assert(invariant( 1291 assert(invariant(
1281 member, isNativeUpgradeFactory || compiler.compilationFailed)); 1292 member, isNativeUpgradeFactory || compiler.compilationFailed));
1282 } else { 1293 } else {
1283 fields.add(member); 1294 fields.add(member);
1284 DartType type = localsHandler.substInContext(member.type); 1295 DartType type = localsHandler.substInContext(member.type);
1285 constructorArguments.add(potentiallyCheckOrTrustType(value, type)); 1296 constructorArguments
1297 .add(typeBuilder.potentiallyCheckOrTrustType(value, type));
1286 } 1298 }
1287 }, includeSuperAndInjectedMembers: true); 1299 }, includeSuperAndInjectedMembers: true);
1288 1300
1289 InterfaceType type = classElement.thisType; 1301 InterfaceType type = classElement.thisType;
1290 TypeMask ssaType = new TypeMask.nonNullExact( 1302 TypeMask ssaType = new TypeMask.nonNullExact(
1291 classElement.declaration, compiler.closedWorld); 1303 classElement.declaration, compiler.closedWorld);
1292 List<DartType> instantiatedTypes; 1304 List<DartType> instantiatedTypes;
1293 addInlinedInstantiation(type); 1305 addInlinedInstantiation(type);
1294 if (!currentInlinedInstantiations.isEmpty) { 1306 if (!currentInlinedInstantiations.isEmpty) {
1295 instantiatedTypes = new List<DartType>.from(currentInlinedInstantiations); 1307 instantiatedTypes = new List<DartType>.from(currentInlinedInstantiations);
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after
1473 // 1485 //
1474 // class A { 1486 // class A {
1475 // A(String foo) = A.b; 1487 // A(String foo) = A.b;
1476 // A(int foo) { print(foo); } 1488 // A(int foo) { print(foo); }
1477 // } 1489 // }
1478 // main() { 1490 // main() {
1479 // new A(499); // valid even in checked mode. 1491 // new A(499); // valid even in checked mode.
1480 // new A("foo"); // invalid in checked mode. 1492 // new A("foo"); // invalid in checked mode.
1481 // 1493 //
1482 // Only the final target is allowed to check for the argument types. 1494 // Only the final target is allowed to check for the argument types.
1483 newParameter = 1495 newParameter = typeBuilder.potentiallyCheckOrTrustType(
1484 potentiallyCheckOrTrustType(newParameter, parameterElement.type); 1496 newParameter, parameterElement.type);
1485 } 1497 }
1486 localsHandler.directLocals[parameterElement] = newParameter; 1498 localsHandler.directLocals[parameterElement] = newParameter;
1487 }); 1499 });
1488 1500
1489 returnType = signature.type.returnType; 1501 returnType = signature.type.returnType;
1490 } else { 1502 } else {
1491 // Otherwise it is a lazy initializer which does not have parameters. 1503 // Otherwise it is a lazy initializer which does not have parameters.
1492 assert(element is VariableElement); 1504 assert(element is VariableElement);
1493 } 1505 }
1494 1506
(...skipping 17 matching lines...) Expand all
1512 if (JavaScriptBackend.TRACE_METHOD == 'post') { 1524 if (JavaScriptBackend.TRACE_METHOD == 'post') {
1513 if (element == backend.traceHelper) return; 1525 if (element == backend.traceHelper) return;
1514 // TODO(sigmund): create a better uuid for elements. 1526 // TODO(sigmund): create a better uuid for elements.
1515 HConstant idConstant = graph.addConstantInt(element.hashCode, compiler); 1527 HConstant idConstant = graph.addConstantInt(element.hashCode, compiler);
1516 HConstant nameConstant = addConstantString(element.name); 1528 HConstant nameConstant = addConstantString(element.name);
1517 add(new HInvokeStatic(backend.traceHelper, 1529 add(new HInvokeStatic(backend.traceHelper,
1518 <HInstruction>[idConstant, nameConstant], backend.dynamicType)); 1530 <HInstruction>[idConstant, nameConstant], backend.dynamicType));
1519 } 1531 }
1520 } 1532 }
1521 1533
1522 /// Check that [type] is valid in the context of `localsHandler.contextClass`.
1523 /// This should only be called in assertions.
1524 bool assertTypeInContext(DartType type, [Spannable spannable]) {
1525 return invariant(spannable == null ? CURRENT_ELEMENT_SPANNABLE : spannable,
1526 () {
1527 ClassElement contextClass = Types.getClassContext(type);
1528 return contextClass == null || contextClass == localsHandler.contextClass;
1529 },
1530 message: "Type '$type' is not valid context of "
1531 "${localsHandler.contextClass}.");
1532 }
1533
1534 /// Build a [HTypeConversion] for converting [original] to type [type].
1535 ///
1536 /// Invariant: [type] must be valid in the context.
1537 /// See [LocalsHandler.substInContext].
1538 HInstruction buildTypeConversion(
1539 HInstruction original, DartType type, int kind) {
1540 if (type == null) return original;
1541 // GENERIC_METHODS: The following statement was added for parsing and
1542 // ignoring method type variables; must be generalized for full support of
1543 // generic methods.
1544 type = type.dynamifyMethodTypeVariableType;
1545 type = type.unaliased;
1546 assert(assertTypeInContext(type, original));
1547 if (type.isInterfaceType && !type.treatAsRaw) {
1548 TypeMask subtype =
1549 new TypeMask.subtype(type.element, compiler.closedWorld);
1550 HInstruction representations = buildTypeArgumentRepresentations(type);
1551 add(representations);
1552 return new HTypeConversion.withTypeRepresentation(
1553 type, kind, subtype, original, representations);
1554 } else if (type.isTypeVariable) {
1555 TypeMask subtype = original.instructionType;
1556 HInstruction typeVariable = addTypeVariableReference(type);
1557 return new HTypeConversion.withTypeRepresentation(
1558 type, kind, subtype, original, typeVariable);
1559 } else if (type.isFunctionType) {
1560 String name =
1561 kind == HTypeConversion.CAST_TYPE_CHECK ? '_asCheck' : '_assertCheck';
1562
1563 List<HInstruction> arguments = <HInstruction>[
1564 buildFunctionType(type),
1565 original
1566 ];
1567 pushInvokeDynamic(
1568 null,
1569 new Selector.call(
1570 new Name(name, helpers.jsHelperLibrary), CallStructure.ONE_ARG),
1571 null,
1572 arguments);
1573
1574 return new HTypeConversion(type, kind, original.instructionType, pop());
1575 } else {
1576 return original.convertType(compiler, type, kind);
1577 }
1578 }
1579
1580 HInstruction _trustType(HInstruction original, DartType type) {
1581 assert(compiler.options.trustTypeAnnotations);
1582 assert(type != null);
1583 type = localsHandler.substInContext(type);
1584 type = type.unaliased;
1585 if (type.isDynamic) return original;
1586 if (!type.isInterfaceType) return original;
1587 if (type.isObject) return original;
1588 // The type element is either a class or the void element.
1589 Element element = type.element;
1590 TypeMask mask = new TypeMask.subtype(element, compiler.closedWorld);
1591 return new HTypeKnown.pinned(mask, original);
1592 }
1593
1594 HInstruction _checkType(HInstruction original, DartType type, int kind) {
1595 assert(compiler.options.enableTypeAssertions);
1596 assert(type != null);
1597 type = localsHandler.substInContext(type);
1598 HInstruction other = buildTypeConversion(original, type, kind);
1599 // TODO(johnniwinther): This operation on `registry` may be inconsistent.
1600 // If it is needed then it seems likely that similar invocations of
1601 // `buildTypeConversion` in `SsaBuilder.visitAs` should also be followed by
1602 // a similar operation on `registry`; otherwise, this one might not be
1603 // needed.
1604 registry?.registerTypeUse(new TypeUse.isCheck(type));
1605 return other;
1606 }
1607
1608 HInstruction potentiallyCheckOrTrustType(HInstruction original, DartType type,
1609 {int kind: HTypeConversion.CHECKED_MODE_CHECK}) {
1610 if (type == null) return original;
1611 HInstruction checkedOrTrusted = original;
1612 if (compiler.options.trustTypeAnnotations) {
1613 checkedOrTrusted = _trustType(original, type);
1614 } else if (compiler.options.enableTypeAssertions) {
1615 checkedOrTrusted = _checkType(original, type, kind);
1616 }
1617 if (checkedOrTrusted == original) return original;
1618 add(checkedOrTrusted);
1619 return checkedOrTrusted;
1620 }
1621
1622 void assertIsSubtype( 1534 void assertIsSubtype(
1623 ast.Node node, DartType subtype, DartType supertype, String message) { 1535 ast.Node node, DartType subtype, DartType supertype, String message) {
1624 HInstruction subtypeInstruction = 1536 HInstruction subtypeInstruction = typeBuilder.analyzeTypeArgument(
1625 analyzeTypeArgument(localsHandler.substInContext(subtype)); 1537 localsHandler.substInContext(subtype), sourceElement);
1626 HInstruction supertypeInstruction = 1538 HInstruction supertypeInstruction = typeBuilder.analyzeTypeArgument(
1627 analyzeTypeArgument(localsHandler.substInContext(supertype)); 1539 localsHandler.substInContext(supertype), sourceElement);
1628 HInstruction messageInstruction = 1540 HInstruction messageInstruction =
1629 graph.addConstantString(new ast.DartString.literal(message), compiler); 1541 graph.addConstantString(new ast.DartString.literal(message), compiler);
1630 MethodElement element = helpers.assertIsSubtype; 1542 MethodElement element = helpers.assertIsSubtype;
1631 var inputs = <HInstruction>[ 1543 var inputs = <HInstruction>[
1632 subtypeInstruction, 1544 subtypeInstruction,
1633 supertypeInstruction, 1545 supertypeInstruction,
1634 messageInstruction 1546 messageInstruction
1635 ]; 1547 ];
1636 HInstruction assertIsSubtype = 1548 HInstruction assertIsSubtype =
1637 new HInvokeStatic(element, inputs, subtypeInstruction.instructionType); 1549 new HInvokeStatic(element, inputs, subtypeInstruction.instructionType);
1638 registry?.registerTypeVariableBoundsSubtypeCheck(subtype, supertype); 1550 registry?.registerTypeVariableBoundsSubtypeCheck(subtype, supertype);
1639 add(assertIsSubtype); 1551 add(assertIsSubtype);
1640 } 1552 }
1641 1553
1642 HGraph closeFunction() { 1554 HGraph closeFunction() {
1643 // TODO(kasperl): Make this goto an implicit return. 1555 // TODO(kasperl): Make this goto an implicit return.
1644 if (!isAborted()) closeAndGotoExit(new HGoto()); 1556 if (!isAborted()) closeAndGotoExit(new HGoto());
1645 graph.finalize(); 1557 graph.finalize();
1646 return graph; 1558 return graph;
1647 } 1559 }
1648 1560
1649 void pushWithPosition(HInstruction instruction, ast.Node node) { 1561 void pushWithPosition(HInstruction instruction, ast.Node node) {
1650 push(attachPosition(instruction, node)); 1562 push(attachPosition(instruction, node));
1651 } 1563 }
1652 1564
1565 /// Pops the most recent instruction from the stack and 'boolifies' it.
1566 ///
1567 /// Boolification is checking if the value is '=== true'.
1653 @override 1568 @override
1654 HInstruction popBoolified() { 1569 HInstruction popBoolified() {
1655 HInstruction value = pop(); 1570 HInstruction value = pop();
1656 if (_checkOrTrustTypes) { 1571 if (typeBuilder.checkOrTrustTypes) {
1657 return potentiallyCheckOrTrustType(value, compiler.coreTypes.boolType, 1572 return typeBuilder.potentiallyCheckOrTrustType(
1573 value, compiler.coreTypes.boolType,
1658 kind: HTypeConversion.BOOLEAN_CONVERSION_CHECK); 1574 kind: HTypeConversion.BOOLEAN_CONVERSION_CHECK);
1659 } 1575 }
1660 HInstruction result = new HBoolify(value, backend.boolType); 1576 HInstruction result = new HBoolify(value, backend.boolType);
1661 add(result); 1577 add(result);
1662 return result; 1578 return result;
1663 } 1579 }
1664 1580
1665 HInstruction attachPosition(HInstruction target, ast.Node node) { 1581 HInstruction attachPosition(HInstruction target, ast.Node node) {
1666 if (node != null) { 1582 if (node != null) {
1667 target.sourceInformation = sourceInformationBuilder.buildGeneric(node); 1583 target.sourceInformation = sourceInformationBuilder.buildGeneric(node);
(...skipping 770 matching lines...) Expand 10 before | Expand all | Expand 10 after
2438 } 2354 }
2439 assert(invariant( 2355 assert(invariant(
2440 location, send == null || !Elements.isInstanceSend(send, elements), 2356 location, send == null || !Elements.isInstanceSend(send, elements),
2441 message: "Unexpected non instance setter: $element.")); 2357 message: "Unexpected non instance setter: $element."));
2442 if (Elements.isStaticOrTopLevelField(element)) { 2358 if (Elements.isStaticOrTopLevelField(element)) {
2443 if (element.isSetter) { 2359 if (element.isSetter) {
2444 pushInvokeStatic(location, element, <HInstruction>[value]); 2360 pushInvokeStatic(location, element, <HInstruction>[value]);
2445 pop(); 2361 pop();
2446 } else { 2362 } else {
2447 FieldElement field = element; 2363 FieldElement field = element;
2448 value = potentiallyCheckOrTrustType(value, field.type); 2364 value = typeBuilder.potentiallyCheckOrTrustType(value, field.type);
2449 addWithPosition(new HStaticStore(field, value), location); 2365 addWithPosition(new HStaticStore(field, value), location);
2450 } 2366 }
2451 stack.add(value); 2367 stack.add(value);
2452 } else if (Elements.isError(element)) { 2368 } else if (Elements.isError(element)) {
2453 generateNoSuchSetter(location, element, send == null ? null : value); 2369 generateNoSuchSetter(location, element, send == null ? null : value);
2454 } else if (Elements.isMalformed(element)) { 2370 } else if (Elements.isMalformed(element)) {
2455 // TODO(ahe): Do something like [generateWrongArgumentCountError]. 2371 // TODO(ahe): Do something like [generateWrongArgumentCountError].
2456 stack.add(graph.addConstantNull(compiler)); 2372 stack.add(graph.addConstantNull(compiler));
2457 } else { 2373 } else {
2458 stack.add(value); 2374 stack.add(value);
2459 LocalElement local = element; 2375 LocalElement local = element;
2460 // If the value does not already have a name, give it here. 2376 // If the value does not already have a name, give it here.
2461 if (value.sourceElement == null) { 2377 if (value.sourceElement == null) {
2462 value.sourceElement = local; 2378 value.sourceElement = local;
2463 } 2379 }
2464 HInstruction checkedOrTrusted = 2380 HInstruction checkedOrTrusted =
2465 potentiallyCheckOrTrustType(value, local.type); 2381 typeBuilder.potentiallyCheckOrTrustType(value, local.type);
2466 if (!identical(checkedOrTrusted, value)) { 2382 if (!identical(checkedOrTrusted, value)) {
2467 pop(); 2383 pop();
2468 stack.add(checkedOrTrusted); 2384 stack.add(checkedOrTrusted);
2469 } 2385 }
2470 2386
2471 localsHandler.updateLocal(local, checkedOrTrusted, 2387 localsHandler.updateLocal(local, checkedOrTrusted,
2472 sourceInformation: 2388 sourceInformation:
2473 sourceInformationBuilder.buildAssignment(location)); 2389 sourceInformationBuilder.buildAssignment(location));
2474 } 2390 }
2475 } 2391 }
2476 2392
2477 HInstruction invokeInterceptor(HInstruction receiver) { 2393 HInstruction invokeInterceptor(HInstruction receiver) {
2478 HInterceptor interceptor = new HInterceptor(receiver, backend.nonNullType); 2394 HInterceptor interceptor = new HInterceptor(receiver, backend.nonNullType);
2479 add(interceptor); 2395 add(interceptor);
2480 return interceptor; 2396 return interceptor;
2481 } 2397 }
2482 2398
2483 HLiteralList buildLiteralList(List<HInstruction> inputs) { 2399 HLiteralList buildLiteralList(List<HInstruction> inputs) {
2484 return new HLiteralList(inputs, backend.extendableArrayType); 2400 return new HLiteralList(inputs, backend.extendableArrayType);
2485 } 2401 }
2486 2402
2487 HInstruction buildTypeArgumentRepresentations(DartType type) {
2488 assert(!type.isTypeVariable);
2489 // Compute the representation of the type arguments, including access
2490 // to the runtime type information for type variables as instructions.
2491 assert(type.element.isClass);
2492 InterfaceType interface = type;
2493 List<HInstruction> inputs = <HInstruction>[];
2494 for (DartType argument in interface.typeArguments) {
2495 inputs.add(analyzeTypeArgument(argument));
2496 }
2497 HInstruction representation = new HTypeInfoExpression(
2498 TypeInfoExpressionKind.INSTANCE,
2499 interface.element.thisType,
2500 inputs,
2501 backend.dynamicType);
2502 return representation;
2503 }
2504
2505 @override 2403 @override
2506 void visitAs(ast.Send node, ast.Node expression, DartType type, _) { 2404 void visitAs(ast.Send node, ast.Node expression, DartType type, _) {
2507 HInstruction expressionInstruction = visitAndPop(expression); 2405 HInstruction expressionInstruction = visitAndPop(expression);
2508 if (type.isMalformed) { 2406 if (type.isMalformed) {
2509 if (type is MalformedType) { 2407 if (type is MalformedType) {
2510 ErroneousElement element = type.element; 2408 ErroneousElement element = type.element;
2511 generateTypeError(node, element.message); 2409 generateTypeError(node, element.message);
2512 } else { 2410 } else {
2513 assert(type is MethodTypeVariableType); 2411 assert(type is MethodTypeVariableType);
2514 stack.add(expressionInstruction); 2412 stack.add(expressionInstruction);
2515 } 2413 }
2516 } else { 2414 } else {
2517 HInstruction converted = buildTypeConversion(expressionInstruction, 2415 HInstruction converted = typeBuilder.buildTypeConversion(
2518 localsHandler.substInContext(type), HTypeConversion.CAST_TYPE_CHECK); 2416 expressionInstruction,
2417 localsHandler.substInContext(type),
2418 HTypeConversion.CAST_TYPE_CHECK);
2519 if (converted != expressionInstruction) add(converted); 2419 if (converted != expressionInstruction) add(converted);
2520 stack.add(converted); 2420 stack.add(converted);
2521 } 2421 }
2522 } 2422 }
2523 2423
2524 @override 2424 @override
2525 void visitIs(ast.Send node, ast.Node expression, DartType type, _) { 2425 void visitIs(ast.Send node, ast.Node expression, DartType type, _) {
2526 HInstruction expressionInstruction = visitAndPop(expression); 2426 HInstruction expressionInstruction = visitAndPop(expression);
2527 push(buildIsNode(node, type, expressionInstruction)); 2427 push(buildIsNode(node, type, expressionInstruction));
2528 } 2428 }
(...skipping 25 matching lines...) Expand all
2554 } else if (type.isFunctionType) { 2454 } else if (type.isFunctionType) {
2555 List arguments = [buildFunctionType(type), expression]; 2455 List arguments = [buildFunctionType(type), expression];
2556 pushInvokeDynamic( 2456 pushInvokeDynamic(
2557 node, 2457 node,
2558 new Selector.call(new PrivateName('_isTest', helpers.jsHelperLibrary), 2458 new Selector.call(new PrivateName('_isTest', helpers.jsHelperLibrary),
2559 CallStructure.ONE_ARG), 2459 CallStructure.ONE_ARG),
2560 null, 2460 null,
2561 arguments); 2461 arguments);
2562 return new HIs.compound(type, expression, pop(), backend.boolType); 2462 return new HIs.compound(type, expression, pop(), backend.boolType);
2563 } else if (type.isTypeVariable) { 2463 } else if (type.isTypeVariable) {
2564 HInstruction runtimeType = addTypeVariableReference(type); 2464 HInstruction runtimeType =
2465 typeBuilder.addTypeVariableReference(type, sourceElement);
2565 Element helper = helpers.checkSubtypeOfRuntimeType; 2466 Element helper = helpers.checkSubtypeOfRuntimeType;
2566 List<HInstruction> inputs = <HInstruction>[expression, runtimeType]; 2467 List<HInstruction> inputs = <HInstruction>[expression, runtimeType];
2567 pushInvokeStatic(null, helper, inputs, typeMask: backend.boolType); 2468 pushInvokeStatic(null, helper, inputs, typeMask: backend.boolType);
2568 HInstruction call = pop(); 2469 HInstruction call = pop();
2569 return new HIs.variable(type, expression, call, backend.boolType); 2470 return new HIs.variable(type, expression, call, backend.boolType);
2570 } else if (RuntimeTypes.hasTypeArguments(type)) { 2471 } else if (RuntimeTypes.hasTypeArguments(type)) {
2571 ClassElement element = type.element; 2472 ClassElement element = type.element;
2572 Element helper = helpers.checkSubtype; 2473 Element helper = helpers.checkSubtype;
2573 HInstruction representations = buildTypeArgumentRepresentations(type); 2474 HInstruction representations =
2475 typeBuilder.buildTypeArgumentRepresentations(type, sourceElement);
2574 add(representations); 2476 add(representations);
2575 js.Name operator = backend.namer.operatorIs(element); 2477 js.Name operator = backend.namer.operatorIs(element);
2576 HInstruction isFieldName = addConstantStringFromName(operator); 2478 HInstruction isFieldName = addConstantStringFromName(operator);
2577 HInstruction asFieldName = compiler.closedWorld 2479 HInstruction asFieldName = compiler.closedWorld
2578 .hasAnyStrictSubtype(element) 2480 .hasAnyStrictSubtype(element)
2579 ? addConstantStringFromName(backend.namer.substitutionName(element)) 2481 ? addConstantStringFromName(backend.namer.substitutionName(element))
2580 : graph.addConstantNull(compiler); 2482 : graph.addConstantNull(compiler);
2581 List<HInstruction> inputs = <HInstruction>[ 2483 List<HInstruction> inputs = <HInstruction>[
2582 expression, 2484 expression,
2583 isFieldName, 2485 isFieldName,
2584 representations, 2486 representations,
2585 asFieldName 2487 asFieldName
2586 ]; 2488 ];
2587 pushInvokeStatic(node, helper, inputs, typeMask: backend.boolType); 2489 pushInvokeStatic(node, helper, inputs, typeMask: backend.boolType);
2588 HInstruction call = pop(); 2490 HInstruction call = pop();
2589 return new HIs.compound(type, expression, call, backend.boolType); 2491 return new HIs.compound(type, expression, call, backend.boolType);
2590 } else { 2492 } else {
2591 if (backend.hasDirectCheckFor(type)) { 2493 if (backend.hasDirectCheckFor(type)) {
2592 return new HIs.direct(type, expression, backend.boolType); 2494 return new HIs.direct(type, expression, backend.boolType);
2593 } 2495 }
2594 // The interceptor is not always needed. It is removed by optimization 2496 // The interceptor is not always needed. It is removed by optimization
2595 // when the receiver type or tested type permit. 2497 // when the receiver type or tested type permit.
2596 return new HIs.raw( 2498 return new HIs.raw(
2597 type, expression, invokeInterceptor(expression), backend.boolType); 2499 type, expression, invokeInterceptor(expression), backend.boolType);
2598 } 2500 }
2599 } 2501 }
2600 2502
2601 HInstruction buildFunctionType(FunctionType type) {
2602 type.accept(new TypeBuilder(compiler.closedWorld), this);
2603 return pop();
2604 }
2605
2606 void addDynamicSendArgumentsToList(ast.Send node, List<HInstruction> list) { 2503 void addDynamicSendArgumentsToList(ast.Send node, List<HInstruction> list) {
2607 CallStructure callStructure = elements.getSelector(node).callStructure; 2504 CallStructure callStructure = elements.getSelector(node).callStructure;
2608 if (callStructure.namedArgumentCount == 0) { 2505 if (callStructure.namedArgumentCount == 0) {
2609 addGenericSendArgumentsToList(node.arguments, list); 2506 addGenericSendArgumentsToList(node.arguments, list);
2610 } else { 2507 } else {
2611 // Visit positional arguments and add them to the list. 2508 // Visit positional arguments and add them to the list.
2612 Link<ast.Node> arguments = node.arguments; 2509 Link<ast.Node> arguments = node.arguments;
2613 int positionalArgumentCount = callStructure.positionalArgumentCount; 2510 int positionalArgumentCount = callStructure.positionalArgumentCount;
2614 for (int i = 0; 2511 for (int i = 0;
2615 i < positionalArgumentCount; 2512 i < positionalArgumentCount;
(...skipping 766 matching lines...) Expand 10 before | Expand all | Expand 10 after
3382 bool needsSubstitutionForTypeVariableAccess(ClassElement cls) { 3279 bool needsSubstitutionForTypeVariableAccess(ClassElement cls) {
3383 ClosedWorld closedWorld = compiler.closedWorld; 3280 ClosedWorld closedWorld = compiler.closedWorld;
3384 if (closedWorld.isUsedAsMixin(cls)) return true; 3281 if (closedWorld.isUsedAsMixin(cls)) return true;
3385 3282
3386 return compiler.closedWorld.anyStrictSubclassOf(cls, 3283 return compiler.closedWorld.anyStrictSubclassOf(cls,
3387 (ClassElement subclass) { 3284 (ClassElement subclass) {
3388 return !rti.isTrivialSubstitution(subclass, cls); 3285 return !rti.isTrivialSubstitution(subclass, cls);
3389 }); 3286 });
3390 } 3287 }
3391 3288
3392 /**
3393 * Generate code to extract the type argument from the object.
3394 */
3395 HInstruction readTypeVariable(TypeVariableType variable,
3396 {SourceInformation sourceInformation}) {
3397 assert(sourceElement.isInstanceMember);
3398 assert(variable is! MethodTypeVariableType);
3399 HInstruction target = localsHandler.readThis();
3400 push(new HTypeInfoReadVariable(variable, target, backend.dynamicType)
3401 ..sourceInformation = sourceInformation);
3402 return pop();
3403 }
3404
3405 // TODO(karlklose): this is needed to avoid a bug where the resolved type is
3406 // not stored on a type annotation in the closure translator. Remove when
3407 // fixed.
3408 bool hasDirectLocal(Local local) {
3409 return !localsHandler.isAccessedDirectly(local) ||
3410 localsHandler.directLocals[local] != null;
3411 }
3412
3413 /**
3414 * Helper to create an instruction that gets the value of a type variable.
3415 */
3416 HInstruction addTypeVariableReference(TypeVariableType type,
3417 {SourceInformation sourceInformation}) {
3418 assert(assertTypeInContext(type));
3419 if (type is MethodTypeVariableType) {
3420 return graph.addConstantNull(compiler);
3421 }
3422 Element member = sourceElement;
3423 bool isClosure = member.enclosingElement.isClosure;
3424 if (isClosure) {
3425 ClosureClassElement closureClass = member.enclosingElement;
3426 member = closureClass.methodElement;
3427 member = member.outermostEnclosingMemberOrTopLevel;
3428 }
3429 bool isInConstructorContext =
3430 member.isConstructor || member.isGenerativeConstructorBody;
3431 Local typeVariableLocal = localsHandler.getTypeVariableAsLocal(type);
3432 if (isClosure) {
3433 if (member.isFactoryConstructor ||
3434 (isInConstructorContext && hasDirectLocal(typeVariableLocal))) {
3435 // The type variable is used from a closure in a factory constructor.
3436 // The value of the type argument is stored as a local on the closure
3437 // itself.
3438 return localsHandler.readLocal(typeVariableLocal,
3439 sourceInformation: sourceInformation);
3440 } else if (member.isFunction ||
3441 member.isGetter ||
3442 member.isSetter ||
3443 isInConstructorContext) {
3444 // The type variable is stored on the "enclosing object" and needs to be
3445 // accessed using the this-reference in the closure.
3446 return readTypeVariable(type, sourceInformation: sourceInformation);
3447 } else {
3448 assert(member.isField);
3449 // The type variable is stored in a parameter of the method.
3450 return localsHandler.readLocal(typeVariableLocal);
3451 }
3452 } else if (isInConstructorContext ||
3453 // When [member] is a field, we can be either
3454 // generating a checked setter or inlining its
3455 // initializer in a constructor. An initializer is
3456 // never built standalone, so in that case [target] is not
3457 // the [member] itself.
3458 (member.isField && member != target)) {
3459 // The type variable is stored in a parameter of the method.
3460 return localsHandler.readLocal(typeVariableLocal,
3461 sourceInformation: sourceInformation);
3462 } else if (member.isInstanceMember) {
3463 // The type variable is stored on the object.
3464 return readTypeVariable(type, sourceInformation: sourceInformation);
3465 } else {
3466 reporter.internalError(
3467 type.element, 'Unexpected type variable in static context.');
3468 return null;
3469 }
3470 }
3471
3472 HInstruction analyzeTypeArgument(DartType argument,
3473 {SourceInformation sourceInformation}) {
3474 assert(assertTypeInContext(argument));
3475 argument = argument.unaliased;
3476 if (argument.treatAsDynamic) {
3477 // Represent [dynamic] as [null].
3478 return graph.addConstantNull(compiler);
3479 }
3480
3481 if (argument.isTypeVariable) {
3482 return addTypeVariableReference(argument,
3483 sourceInformation: sourceInformation);
3484 }
3485
3486 List<HInstruction> inputs = <HInstruction>[];
3487 argument.forEachTypeVariable((variable) {
3488 if (variable is! MethodTypeVariableType) {
3489 inputs.add(analyzeTypeArgument(variable));
3490 }
3491 });
3492 HInstruction result = new HTypeInfoExpression(
3493 TypeInfoExpressionKind.COMPLETE, argument, inputs, backend.dynamicType)
3494 ..sourceInformation = sourceInformation;
3495 add(result);
3496 return result;
3497 }
3498
3499 HInstruction handleListConstructor( 3289 HInstruction handleListConstructor(
3500 InterfaceType type, ast.Node currentNode, HInstruction newObject) { 3290 InterfaceType type, ast.Node currentNode, HInstruction newObject) {
3501 if (!backend.classNeedsRti(type.element) || type.treatAsRaw) { 3291 if (!backend.classNeedsRti(type.element) || type.treatAsRaw) {
3502 return newObject; 3292 return newObject;
3503 } 3293 }
3504 List<HInstruction> inputs = <HInstruction>[]; 3294 List<HInstruction> inputs = <HInstruction>[];
3505 type = localsHandler.substInContext(type); 3295 type = localsHandler.substInContext(type);
3506 type.typeArguments.forEach((DartType argument) { 3296 type.typeArguments.forEach((DartType argument) {
3507 inputs.add(analyzeTypeArgument(argument)); 3297 inputs.add(typeBuilder.analyzeTypeArgument(argument, sourceElement));
3508 }); 3298 });
3509 // TODO(15489): Register at codegen. 3299 // TODO(15489): Register at codegen.
3510 registry?.registerInstantiation(type); 3300 registry?.registerInstantiation(type);
3511 return callSetRuntimeTypeInfoWithTypeArguments( 3301 return callSetRuntimeTypeInfoWithTypeArguments(
3512 type.element, inputs, newObject); 3302 type.element, inputs, newObject);
3513 } 3303 }
3514 3304
3515 HInstruction callSetRuntimeTypeInfoWithTypeArguments(ClassElement element, 3305 HInstruction callSetRuntimeTypeInfoWithTypeArguments(ClassElement element,
3516 List<HInstruction> rtiInputs, HInstruction newObject) { 3306 List<HInstruction> rtiInputs, HInstruction newObject) {
3517 if (!backend.classNeedsRti(element)) { 3307 if (!backend.classNeedsRti(element)) {
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after
3745 if (backend.classNeedsRti(coreClasses.listClass) && 3535 if (backend.classNeedsRti(coreClasses.listClass) &&
3746 (isFixedListConstructorCall || 3536 (isFixedListConstructorCall ||
3747 isGrowableListConstructorCall || 3537 isGrowableListConstructorCall ||
3748 isJSArrayTypedConstructor)) { 3538 isJSArrayTypedConstructor)) {
3749 newInstance = handleListConstructor(type, send, pop()); 3539 newInstance = handleListConstructor(type, send, pop());
3750 stack.add(newInstance); 3540 stack.add(newInstance);
3751 } 3541 }
3752 3542
3753 // Finally, if we called a redirecting factory constructor, check the type. 3543 // Finally, if we called a redirecting factory constructor, check the type.
3754 if (isRedirected) { 3544 if (isRedirected) {
3755 HInstruction checked = potentiallyCheckOrTrustType(newInstance, type); 3545 HInstruction checked =
3546 typeBuilder.potentiallyCheckOrTrustType(newInstance, type);
3756 if (checked != newInstance) { 3547 if (checked != newInstance) {
3757 pop(); 3548 pop();
3758 stack.add(checked); 3549 stack.add(checked);
3759 } 3550 }
3760 } 3551 }
3761 } 3552 }
3762 3553
3763 void potentiallyAddTypeArguments( 3554 void potentiallyAddTypeArguments(
3764 List<HInstruction> inputs, ClassElement cls, InterfaceType expectedType, 3555 List<HInstruction> inputs, ClassElement cls, InterfaceType expectedType,
3765 {SourceInformation sourceInformation}) { 3556 {SourceInformation sourceInformation}) {
3766 if (!backend.classNeedsRti(cls)) return; 3557 if (!backend.classNeedsRti(cls)) return;
3767 assert(cls.typeVariables.length == expectedType.typeArguments.length); 3558 assert(cls.typeVariables.length == expectedType.typeArguments.length);
3768 expectedType.typeArguments.forEach((DartType argument) { 3559 expectedType.typeArguments.forEach((DartType argument) {
3769 inputs.add( 3560 inputs.add(typeBuilder.analyzeTypeArgument(argument, sourceElement,
3770 analyzeTypeArgument(argument, sourceInformation: sourceInformation)); 3561 sourceInformation: sourceInformation));
3771 }); 3562 });
3772 } 3563 }
3773 3564
3774 /// In checked mode checks the [type] of [node] to be well-bounded. The method 3565 /// In checked mode checks the [type] of [node] to be well-bounded. The method
3775 /// returns [:true:] if an error can be statically determined. 3566 /// returns [:true:] if an error can be statically determined.
3776 bool checkTypeVariableBounds(ast.NewExpression node, InterfaceType type) { 3567 bool checkTypeVariableBounds(ast.NewExpression node, InterfaceType type) {
3777 if (!compiler.options.enableTypeAssertions) return false; 3568 if (!compiler.options.enableTypeAssertions) return false;
3778 3569
3779 Map<DartType, Set<DartType>> seenChecksMap = 3570 Map<DartType, Set<DartType>> seenChecksMap =
3780 new Map<DartType, Set<DartType>>(); 3571 new Map<DartType, Set<DartType>>();
(...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after
4032 /// Generate the literal for [typeVariable] in the current context. 3823 /// Generate the literal for [typeVariable] in the current context.
4033 void generateTypeVariableLiteral( 3824 void generateTypeVariableLiteral(
4034 ast.Send node, TypeVariableType typeVariable) { 3825 ast.Send node, TypeVariableType typeVariable) {
4035 // GENERIC_METHODS: This provides thin support for method type variables 3826 // GENERIC_METHODS: This provides thin support for method type variables
4036 // by treating them as malformed when evaluated as a literal. For full 3827 // by treating them as malformed when evaluated as a literal. For full
4037 // support of generic methods this must be revised. 3828 // support of generic methods this must be revised.
4038 if (typeVariable is MethodTypeVariableType) { 3829 if (typeVariable is MethodTypeVariableType) {
4039 generateTypeError(node, "Method type variables are not reified"); 3830 generateTypeError(node, "Method type variables are not reified");
4040 } else { 3831 } else {
4041 DartType type = localsHandler.substInContext(typeVariable); 3832 DartType type = localsHandler.substInContext(typeVariable);
4042 HInstruction value = analyzeTypeArgument(type, 3833 HInstruction value = typeBuilder.analyzeTypeArgument(type, sourceElement,
4043 sourceInformation: sourceInformationBuilder.buildGet(node)); 3834 sourceInformation: sourceInformationBuilder.buildGet(node));
4044 pushInvokeStatic(node, helpers.runtimeTypeToString, [value], 3835 pushInvokeStatic(node, helpers.runtimeTypeToString, [value],
4045 typeMask: backend.stringType); 3836 typeMask: backend.stringType);
4046 pushInvokeStatic(node, helpers.createRuntimeType, [pop()]); 3837 pushInvokeStatic(node, helpers.createRuntimeType, [pop()]);
4047 } 3838 }
4048 } 3839 }
4049 3840
4050 /// Generate a call to a type literal. 3841 /// Generate a call to a type literal.
4051 void generateTypeLiteralCall(ast.Send node) { 3842 void generateTypeLiteralCall(ast.Send node) {
4052 // This send is of the form 'e(...)', where e is resolved to a type 3843 // This send is of the form 'e(...)', where e is resolved to a type
(...skipping 1305 matching lines...) Expand 10 before | Expand all | Expand 10 after
5358 } 5149 }
5359 } 5150 }
5360 5151
5361 ClassElement targetClass = targetConstructor.enclosingClass; 5152 ClassElement targetClass = targetConstructor.enclosingClass;
5362 if (backend.classNeedsRti(targetClass)) { 5153 if (backend.classNeedsRti(targetClass)) {
5363 ClassElement cls = redirectingConstructor.enclosingClass; 5154 ClassElement cls = redirectingConstructor.enclosingClass;
5364 InterfaceType targetType = 5155 InterfaceType targetType =
5365 redirectingConstructor.computeEffectiveTargetType(cls.thisType); 5156 redirectingConstructor.computeEffectiveTargetType(cls.thisType);
5366 targetType = localsHandler.substInContext(targetType); 5157 targetType = localsHandler.substInContext(targetType);
5367 targetType.typeArguments.forEach((DartType argument) { 5158 targetType.typeArguments.forEach((DartType argument) {
5368 inputs.add(analyzeTypeArgument(argument)); 5159 inputs.add(typeBuilder.analyzeTypeArgument(argument, sourceElement));
5369 }); 5160 });
5370 } 5161 }
5371 pushInvokeStatic(node, targetConstructor.declaration, inputs); 5162 pushInvokeStatic(node, targetConstructor.declaration, inputs);
5372 HInstruction value = pop(); 5163 HInstruction value = pop();
5373 emitReturn(value, node); 5164 emitReturn(value, node);
5374 } 5165 }
5375 5166
5376 /// Returns true if the [type] is a valid return type for an asynchronous 5167 /// Returns true if the [type] is a valid return type for an asynchronous
5377 /// function. 5168 /// function.
5378 /// 5169 ///
(...skipping 29 matching lines...) Expand all
5408 if (isBuildingAsyncFunction) { 5199 if (isBuildingAsyncFunction) {
5409 if (compiler.options.enableTypeAssertions && 5200 if (compiler.options.enableTypeAssertions &&
5410 !isValidAsyncReturnType(returnType)) { 5201 !isValidAsyncReturnType(returnType)) {
5411 String message = "Async function returned a Future, " 5202 String message = "Async function returned a Future, "
5412 "was declared to return a $returnType."; 5203 "was declared to return a $returnType.";
5413 generateTypeError(node, message); 5204 generateTypeError(node, message);
5414 pop(); 5205 pop();
5415 return; 5206 return;
5416 } 5207 }
5417 } else { 5208 } else {
5418 value = potentiallyCheckOrTrustType(value, returnType); 5209 value = typeBuilder.potentiallyCheckOrTrustType(value, returnType);
5419 } 5210 }
5420 } 5211 }
5421 5212
5422 handleInTryStatement(); 5213 handleInTryStatement();
5423 emitReturn(value, node); 5214 emitReturn(value, node);
5424 } 5215 }
5425 5216
5426 visitThrow(ast.Throw node) { 5217 visitThrow(ast.Throw node) {
5427 visitThrowExpression(node.expression); 5218 visitThrowExpression(node.expression);
5428 if (isReachable) { 5219 if (isReachable) {
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
5470 } 5261 }
5471 } 5262 }
5472 5263
5473 HInstruction setRtiIfNeeded(HInstruction object, ast.Node node) { 5264 HInstruction setRtiIfNeeded(HInstruction object, ast.Node node) {
5474 InterfaceType type = localsHandler.substInContext(elements.getType(node)); 5265 InterfaceType type = localsHandler.substInContext(elements.getType(node));
5475 if (!backend.classNeedsRti(type.element) || type.treatAsRaw) { 5266 if (!backend.classNeedsRti(type.element) || type.treatAsRaw) {
5476 return object; 5267 return object;
5477 } 5268 }
5478 List<HInstruction> arguments = <HInstruction>[]; 5269 List<HInstruction> arguments = <HInstruction>[];
5479 for (DartType argument in type.typeArguments) { 5270 for (DartType argument in type.typeArguments) {
5480 arguments.add(analyzeTypeArgument(argument)); 5271 arguments.add(typeBuilder.analyzeTypeArgument(argument, sourceElement));
5481 } 5272 }
5482 // TODO(15489): Register at codegen. 5273 // TODO(15489): Register at codegen.
5483 registry?.registerInstantiation(type); 5274 registry?.registerInstantiation(type);
5484 return callSetRuntimeTypeInfoWithTypeArguments( 5275 return callSetRuntimeTypeInfoWithTypeArguments(
5485 type.element, arguments, object); 5276 type.element, arguments, object);
5486 } 5277 }
5487 5278
5488 visitLiteralList(ast.LiteralList node) { 5279 visitLiteralList(ast.LiteralList node) {
5489 HInstruction instruction; 5280 HInstruction instruction;
5490 5281
(...skipping 427 matching lines...) Expand 10 before | Expand all | Expand 10 after
5918 InterfaceType type = elements.getType(node); 5709 InterfaceType type = elements.getType(node);
5919 InterfaceType expectedType = 5710 InterfaceType expectedType =
5920 functionElement.computeEffectiveTargetType(type); 5711 functionElement.computeEffectiveTargetType(type);
5921 expectedType = localsHandler.substInContext(expectedType); 5712 expectedType = localsHandler.substInContext(expectedType);
5922 5713
5923 ClassElement cls = constructor.enclosingClass; 5714 ClassElement cls = constructor.enclosingClass;
5924 5715
5925 if (backend.classNeedsRti(cls)) { 5716 if (backend.classNeedsRti(cls)) {
5926 List<HInstruction> typeInputs = <HInstruction>[]; 5717 List<HInstruction> typeInputs = <HInstruction>[];
5927 expectedType.typeArguments.forEach((DartType argument) { 5718 expectedType.typeArguments.forEach((DartType argument) {
5928 typeInputs.add(analyzeTypeArgument(argument)); 5719 typeInputs
5720 .add(typeBuilder.analyzeTypeArgument(argument, sourceElement));
5929 }); 5721 });
5930 5722
5931 // We lift this common call pattern into a helper function to save space 5723 // We lift this common call pattern into a helper function to save space
5932 // in the output. 5724 // in the output.
5933 if (typeInputs.every((HInstruction input) => input.isNull())) { 5725 if (typeInputs.every((HInstruction input) => input.isNull())) {
5934 if (listInputs.isEmpty) { 5726 if (listInputs.isEmpty) {
5935 constructor = helpers.mapLiteralUntypedEmptyMaker; 5727 constructor = helpers.mapLiteralUntypedEmptyMaker;
5936 } else { 5728 } else {
5937 constructor = helpers.mapLiteralUntypedMaker; 5729 constructor = helpers.mapLiteralUntypedMaker;
5938 } 5730 }
(...skipping 1056 matching lines...) Expand 10 before | Expand all | Expand 10 after
6995 this.oldReturnLocal, 6787 this.oldReturnLocal,
6996 this.oldReturnType, 6788 this.oldReturnType,
6997 this.oldResolvedAst, 6789 this.oldResolvedAst,
6998 this.oldStack, 6790 this.oldStack,
6999 this.oldLocalsHandler, 6791 this.oldLocalsHandler,
7000 this.inTryStatement, 6792 this.inTryStatement,
7001 this.allFunctionsCalledOnce, 6793 this.allFunctionsCalledOnce,
7002 this.oldElementInferenceResults) 6794 this.oldElementInferenceResults)
7003 : super(function); 6795 : super(function);
7004 } 6796 }
7005
7006 class TypeBuilder implements DartTypeVisitor<dynamic, SsaBuilder> {
7007 final ClosedWorld closedWorld;
7008
7009 TypeBuilder(this.closedWorld);
7010
7011 void visit(DartType type, SsaBuilder builder) => type.accept(this, builder);
7012
7013 void visitVoidType(VoidType type, SsaBuilder builder) {
7014 ClassElement cls = builder.backend.helpers.VoidRuntimeType;
7015 builder.push(new HVoidType(type, new TypeMask.exact(cls, closedWorld)));
7016 }
7017
7018 void visitTypeVariableType(TypeVariableType type, SsaBuilder builder) {
7019 ClassElement cls = builder.backend.helpers.RuntimeType;
7020 TypeMask instructionType = new TypeMask.subclass(cls, closedWorld);
7021 if (!builder.sourceElement.enclosingElement.isClosure &&
7022 builder.sourceElement.isInstanceMember) {
7023 HInstruction receiver = builder.localsHandler.readThis();
7024 builder.push(new HReadTypeVariable(type, receiver, instructionType));
7025 } else {
7026 builder.push(new HReadTypeVariable.noReceiver(
7027 type, builder.addTypeVariableReference(type), instructionType));
7028 }
7029 }
7030
7031 void visitFunctionType(FunctionType type, SsaBuilder builder) {
7032 type.returnType.accept(this, builder);
7033 HInstruction returnType = builder.pop();
7034 List<HInstruction> inputs = <HInstruction>[returnType];
7035
7036 for (DartType parameter in type.parameterTypes) {
7037 parameter.accept(this, builder);
7038 inputs.add(builder.pop());
7039 }
7040
7041 for (DartType parameter in type.optionalParameterTypes) {
7042 parameter.accept(this, builder);
7043 inputs.add(builder.pop());
7044 }
7045
7046 List<DartType> namedParameterTypes = type.namedParameterTypes;
7047 List<String> names = type.namedParameters;
7048 for (int index = 0; index < names.length; index++) {
7049 ast.DartString dartString = new ast.DartString.literal(names[index]);
7050 inputs.add(builder.graph.addConstantString(dartString, builder.compiler));
7051 namedParameterTypes[index].accept(this, builder);
7052 inputs.add(builder.pop());
7053 }
7054
7055 ClassElement cls = builder.backend.helpers.RuntimeFunctionType;
7056 builder.push(
7057 new HFunctionType(inputs, type, new TypeMask.exact(cls, closedWorld)));
7058 }
7059
7060 void visitMalformedType(MalformedType type, SsaBuilder builder) {
7061 visitDynamicType(const DynamicType(), builder);
7062 }
7063
7064 void visitStatementType(StatementType type, SsaBuilder builder) {
7065 throw 'not implemented visitStatementType($type)';
7066 }
7067
7068 void visitInterfaceType(InterfaceType type, SsaBuilder builder) {
7069 List<HInstruction> inputs = <HInstruction>[];
7070 for (DartType typeArgument in type.typeArguments) {
7071 typeArgument.accept(this, builder);
7072 inputs.add(builder.pop());
7073 }
7074 ClassElement cls;
7075 if (type.typeArguments.isEmpty) {
7076 cls = builder.backend.helpers.RuntimeTypePlain;
7077 } else {
7078 cls = builder.backend.helpers.RuntimeTypeGeneric;
7079 }
7080 builder.push(
7081 new HInterfaceType(inputs, type, new TypeMask.exact(cls, closedWorld)));
7082 }
7083
7084 void visitTypedefType(TypedefType type, SsaBuilder builder) {
7085 DartType unaliased = type.unaliased;
7086 if (unaliased is TypedefType) throw 'unable to unalias $type';
7087 unaliased.accept(this, builder);
7088 }
7089
7090 void visitDynamicType(DynamicType type, SsaBuilder builder) {
7091 JavaScriptBackend backend = builder.compiler.backend;
7092 ClassElement cls = backend.helpers.DynamicRuntimeType;
7093 builder.push(new HDynamicType(type, new TypeMask.exact(cls, closedWorld)));
7094 }
7095 }
OLDNEW
« no previous file with comments | « no previous file | pkg/compiler/lib/src/ssa/builder_kernel.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698