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

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
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_verifier.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 TypeVerifier typeVerifier;
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 typeVerifier = new TypeVerifier(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(HInstruction original,
302 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 = typeVerifier.potentiallyCheckOrTrustType(
778 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 = typeVerifier.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 typeVerifier.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 typeVerifier.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.add(typeVerifier.potentiallyCheckOrTrustType(
1297 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 178 matching lines...) Expand 10 before | Expand all | Expand 10 after
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 =
1484 potentiallyCheckOrTrustType(newParameter, parameterElement.type); 1496 typeVerifier.potentiallyCheckOrTrustType(
1497 newParameter, parameterElement.type);
1485 } 1498 }
1486 localsHandler.directLocals[parameterElement] = newParameter; 1499 localsHandler.directLocals[parameterElement] = newParameter;
1487 }); 1500 });
1488 1501
1489 returnType = signature.type.returnType; 1502 returnType = signature.type.returnType;
1490 } else { 1503 } else {
1491 // Otherwise it is a lazy initializer which does not have parameters. 1504 // Otherwise it is a lazy initializer which does not have parameters.
1492 assert(element is VariableElement); 1505 assert(element is VariableElement);
1493 } 1506 }
1494 1507
(...skipping 17 matching lines...) Expand all
1512 if (JavaScriptBackend.TRACE_METHOD == 'post') { 1525 if (JavaScriptBackend.TRACE_METHOD == 'post') {
1513 if (element == backend.traceHelper) return; 1526 if (element == backend.traceHelper) return;
1514 // TODO(sigmund): create a better uuid for elements. 1527 // TODO(sigmund): create a better uuid for elements.
1515 HConstant idConstant = graph.addConstantInt(element.hashCode, compiler); 1528 HConstant idConstant = graph.addConstantInt(element.hashCode, compiler);
1516 HConstant nameConstant = addConstantString(element.name); 1529 HConstant nameConstant = addConstantString(element.name);
1517 add(new HInvokeStatic(backend.traceHelper, 1530 add(new HInvokeStatic(backend.traceHelper,
1518 <HInstruction>[idConstant, nameConstant], backend.dynamicType)); 1531 <HInstruction>[idConstant, nameConstant], backend.dynamicType));
1519 } 1532 }
1520 } 1533 }
1521 1534
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( 1535 void assertIsSubtype(
1623 ast.Node node, DartType subtype, DartType supertype, String message) { 1536 ast.Node node, DartType subtype, DartType supertype, String message) {
1624 HInstruction subtypeInstruction = 1537 HInstruction subtypeInstruction =
1625 analyzeTypeArgument(localsHandler.substInContext(subtype)); 1538 typeVerifier.analyzeTypeArgument(localsHandler.substInContext(subtype),
1626 HInstruction supertypeInstruction = 1539 sourceElement);
1627 analyzeTypeArgument(localsHandler.substInContext(supertype)); 1540 HInstruction supertypeInstruction = typeVerifier.analyzeTypeArgument(
1541 localsHandler.substInContext(supertype), sourceElement);
1628 HInstruction messageInstruction = 1542 HInstruction messageInstruction =
1629 graph.addConstantString(new ast.DartString.literal(message), compiler); 1543 graph.addConstantString(new ast.DartString.literal(message), compiler);
1630 MethodElement element = helpers.assertIsSubtype; 1544 MethodElement element = helpers.assertIsSubtype;
1631 var inputs = <HInstruction>[ 1545 var inputs = <HInstruction>[
1632 subtypeInstruction, 1546 subtypeInstruction,
1633 supertypeInstruction, 1547 supertypeInstruction,
1634 messageInstruction 1548 messageInstruction
1635 ]; 1549 ];
1636 HInstruction assertIsSubtype = 1550 HInstruction assertIsSubtype =
1637 new HInvokeStatic(element, inputs, subtypeInstruction.instructionType); 1551 new HInvokeStatic(element, inputs, subtypeInstruction.instructionType);
1638 registry?.registerTypeVariableBoundsSubtypeCheck(subtype, supertype); 1552 registry?.registerTypeVariableBoundsSubtypeCheck(subtype, supertype);
1639 add(assertIsSubtype); 1553 add(assertIsSubtype);
1640 } 1554 }
1641 1555
1642 HGraph closeFunction() { 1556 HGraph closeFunction() {
1643 // TODO(kasperl): Make this goto an implicit return. 1557 // TODO(kasperl): Make this goto an implicit return.
1644 if (!isAborted()) closeAndGotoExit(new HGoto()); 1558 if (!isAborted()) closeAndGotoExit(new HGoto());
1645 graph.finalize(); 1559 graph.finalize();
1646 return graph; 1560 return graph;
1647 } 1561 }
1648 1562
1649 void pushWithPosition(HInstruction instruction, ast.Node node) { 1563 void pushWithPosition(HInstruction instruction, ast.Node node) {
1650 push(attachPosition(instruction, node)); 1564 push(attachPosition(instruction, node));
1651 } 1565 }
1652 1566
1567 /// Pops the most recent instruction from the stack and 'boolifies' it.
1568 ///
1569 /// Boolification is checking if the value is '=== true'.
1653 @override 1570 @override
1654 HInstruction popBoolified() { 1571 HInstruction popBoolified() {
1655 HInstruction value = pop(); 1572 HInstruction value = pop();
1656 if (_checkOrTrustTypes) { 1573 if (typeVerifier.checkOrTrustTypes) {
1657 return potentiallyCheckOrTrustType(value, compiler.coreTypes.boolType, 1574 return typeVerifier.potentiallyCheckOrTrustType(
1575 value, compiler.coreTypes.boolType,
1658 kind: HTypeConversion.BOOLEAN_CONVERSION_CHECK); 1576 kind: HTypeConversion.BOOLEAN_CONVERSION_CHECK);
1659 } 1577 }
1660 HInstruction result = new HBoolify(value, backend.boolType); 1578 HInstruction result = new HBoolify(value, backend.boolType);
1661 add(result); 1579 add(result);
1662 return result; 1580 return result;
1663 } 1581 }
1664 1582
1665 HInstruction attachPosition(HInstruction target, ast.Node node) { 1583 HInstruction attachPosition(HInstruction target, ast.Node node) {
1666 if (node != null) { 1584 if (node != null) {
1667 target.sourceInformation = sourceInformationBuilder.buildGeneric(node); 1585 target.sourceInformation = sourceInformationBuilder.buildGeneric(node);
(...skipping 770 matching lines...) Expand 10 before | Expand all | Expand 10 after
2438 } 2356 }
2439 assert(invariant( 2357 assert(invariant(
2440 location, send == null || !Elements.isInstanceSend(send, elements), 2358 location, send == null || !Elements.isInstanceSend(send, elements),
2441 message: "Unexpected non instance setter: $element.")); 2359 message: "Unexpected non instance setter: $element."));
2442 if (Elements.isStaticOrTopLevelField(element)) { 2360 if (Elements.isStaticOrTopLevelField(element)) {
2443 if (element.isSetter) { 2361 if (element.isSetter) {
2444 pushInvokeStatic(location, element, <HInstruction>[value]); 2362 pushInvokeStatic(location, element, <HInstruction>[value]);
2445 pop(); 2363 pop();
2446 } else { 2364 } else {
2447 FieldElement field = element; 2365 FieldElement field = element;
2448 value = potentiallyCheckOrTrustType(value, field.type); 2366 value = typeVerifier.potentiallyCheckOrTrustType(value, field.type);
2449 addWithPosition(new HStaticStore(field, value), location); 2367 addWithPosition(new HStaticStore(field, value), location);
2450 } 2368 }
2451 stack.add(value); 2369 stack.add(value);
2452 } else if (Elements.isError(element)) { 2370 } else if (Elements.isError(element)) {
2453 generateNoSuchSetter(location, element, send == null ? null : value); 2371 generateNoSuchSetter(location, element, send == null ? null : value);
2454 } else if (Elements.isMalformed(element)) { 2372 } else if (Elements.isMalformed(element)) {
2455 // TODO(ahe): Do something like [generateWrongArgumentCountError]. 2373 // TODO(ahe): Do something like [generateWrongArgumentCountError].
2456 stack.add(graph.addConstantNull(compiler)); 2374 stack.add(graph.addConstantNull(compiler));
2457 } else { 2375 } else {
2458 stack.add(value); 2376 stack.add(value);
2459 LocalElement local = element; 2377 LocalElement local = element;
2460 // If the value does not already have a name, give it here. 2378 // If the value does not already have a name, give it here.
2461 if (value.sourceElement == null) { 2379 if (value.sourceElement == null) {
2462 value.sourceElement = local; 2380 value.sourceElement = local;
2463 } 2381 }
2464 HInstruction checkedOrTrusted = 2382 HInstruction checkedOrTrusted =
2465 potentiallyCheckOrTrustType(value, local.type); 2383 typeVerifier.potentiallyCheckOrTrustType(value, local.type);
2466 if (!identical(checkedOrTrusted, value)) { 2384 if (!identical(checkedOrTrusted, value)) {
2467 pop(); 2385 pop();
2468 stack.add(checkedOrTrusted); 2386 stack.add(checkedOrTrusted);
2469 } 2387 }
2470 2388
2471 localsHandler.updateLocal(local, checkedOrTrusted, 2389 localsHandler.updateLocal(local, checkedOrTrusted,
2472 sourceInformation: 2390 sourceInformation:
2473 sourceInformationBuilder.buildAssignment(location)); 2391 sourceInformationBuilder.buildAssignment(location));
2474 } 2392 }
2475 } 2393 }
2476 2394
2477 HInstruction invokeInterceptor(HInstruction receiver) { 2395 HInstruction invokeInterceptor(HInstruction receiver) {
2478 HInterceptor interceptor = new HInterceptor(receiver, backend.nonNullType); 2396 HInterceptor interceptor = new HInterceptor(receiver, backend.nonNullType);
2479 add(interceptor); 2397 add(interceptor);
2480 return interceptor; 2398 return interceptor;
2481 } 2399 }
2482 2400
2483 HLiteralList buildLiteralList(List<HInstruction> inputs) { 2401 HLiteralList buildLiteralList(List<HInstruction> inputs) {
2484 return new HLiteralList(inputs, backend.extendableArrayType); 2402 return new HLiteralList(inputs, backend.extendableArrayType);
2485 } 2403 }
2486 2404
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 2405 @override
2506 void visitAs(ast.Send node, ast.Node expression, DartType type, _) { 2406 void visitAs(ast.Send node, ast.Node expression, DartType type, _) {
2507 HInstruction expressionInstruction = visitAndPop(expression); 2407 HInstruction expressionInstruction = visitAndPop(expression);
2508 if (type.isMalformed) { 2408 if (type.isMalformed) {
2509 if (type is MalformedType) { 2409 if (type is MalformedType) {
2510 ErroneousElement element = type.element; 2410 ErroneousElement element = type.element;
2511 generateTypeError(node, element.message); 2411 generateTypeError(node, element.message);
2512 } else { 2412 } else {
2513 assert(type is MethodTypeVariableType); 2413 assert(type is MethodTypeVariableType);
2514 stack.add(expressionInstruction); 2414 stack.add(expressionInstruction);
2515 } 2415 }
2516 } else { 2416 } else {
2517 HInstruction converted = buildTypeConversion(expressionInstruction, 2417 HInstruction converted = typeVerifier.buildTypeConversion(
2518 localsHandler.substInContext(type), HTypeConversion.CAST_TYPE_CHECK); 2418 expressionInstruction, localsHandler.substInContext(type),
2419 HTypeConversion.CAST_TYPE_CHECK);
2519 if (converted != expressionInstruction) add(converted); 2420 if (converted != expressionInstruction) add(converted);
2520 stack.add(converted); 2421 stack.add(converted);
2521 } 2422 }
2522 } 2423 }
2523 2424
2524 @override 2425 @override
2525 void visitIs(ast.Send node, ast.Node expression, DartType type, _) { 2426 void visitIs(ast.Send node, ast.Node expression, DartType type, _) {
2526 HInstruction expressionInstruction = visitAndPop(expression); 2427 HInstruction expressionInstruction = visitAndPop(expression);
2527 push(buildIsNode(node, type, expressionInstruction)); 2428 push(buildIsNode(node, type, expressionInstruction));
2528 } 2429 }
(...skipping 25 matching lines...) Expand all
2554 } else if (type.isFunctionType) { 2455 } else if (type.isFunctionType) {
2555 List arguments = [buildFunctionType(type), expression]; 2456 List arguments = [buildFunctionType(type), expression];
2556 pushInvokeDynamic( 2457 pushInvokeDynamic(
2557 node, 2458 node,
2558 new Selector.call(new PrivateName('_isTest', helpers.jsHelperLibrary), 2459 new Selector.call(new PrivateName('_isTest', helpers.jsHelperLibrary),
2559 CallStructure.ONE_ARG), 2460 CallStructure.ONE_ARG),
2560 null, 2461 null,
2561 arguments); 2462 arguments);
2562 return new HIs.compound(type, expression, pop(), backend.boolType); 2463 return new HIs.compound(type, expression, pop(), backend.boolType);
2563 } else if (type.isTypeVariable) { 2464 } else if (type.isTypeVariable) {
2564 HInstruction runtimeType = addTypeVariableReference(type); 2465 HInstruction runtimeType = typeVerifier.addTypeVariableReference(
2466 type, sourceElement);
2565 Element helper = helpers.checkSubtypeOfRuntimeType; 2467 Element helper = helpers.checkSubtypeOfRuntimeType;
2566 List<HInstruction> inputs = <HInstruction>[expression, runtimeType]; 2468 List<HInstruction> inputs = <HInstruction>[expression, runtimeType];
2567 pushInvokeStatic(null, helper, inputs, typeMask: backend.boolType); 2469 pushInvokeStatic(null, helper, inputs, typeMask: backend.boolType);
2568 HInstruction call = pop(); 2470 HInstruction call = pop();
2569 return new HIs.variable(type, expression, call, backend.boolType); 2471 return new HIs.variable(type, expression, call, backend.boolType);
2570 } else if (RuntimeTypes.hasTypeArguments(type)) { 2472 } else if (RuntimeTypes.hasTypeArguments(type)) {
2571 ClassElement element = type.element; 2473 ClassElement element = type.element;
2572 Element helper = helpers.checkSubtype; 2474 Element helper = helpers.checkSubtype;
2573 HInstruction representations = buildTypeArgumentRepresentations(type); 2475 HInstruction representations =
2476 typeVerifier.buildTypeArgumentRepresentations(type, sourceElement);
2574 add(representations); 2477 add(representations);
2575 js.Name operator = backend.namer.operatorIs(element); 2478 js.Name operator = backend.namer.operatorIs(element);
2576 HInstruction isFieldName = addConstantStringFromName(operator); 2479 HInstruction isFieldName = addConstantStringFromName(operator);
2577 HInstruction asFieldName = compiler.closedWorld 2480 HInstruction asFieldName = compiler.closedWorld
2578 .hasAnyStrictSubtype(element) 2481 .hasAnyStrictSubtype(element)
2579 ? addConstantStringFromName(backend.namer.substitutionName(element)) 2482 ? addConstantStringFromName(backend.namer.substitutionName(element))
2580 : graph.addConstantNull(compiler); 2483 : graph.addConstantNull(compiler);
2581 List<HInstruction> inputs = <HInstruction>[ 2484 List<HInstruction> inputs = <HInstruction>[
2582 expression, 2485 expression,
2583 isFieldName, 2486 isFieldName,
2584 representations, 2487 representations,
2585 asFieldName 2488 asFieldName
2586 ]; 2489 ];
2587 pushInvokeStatic(node, helper, inputs, typeMask: backend.boolType); 2490 pushInvokeStatic(node, helper, inputs, typeMask: backend.boolType);
2588 HInstruction call = pop(); 2491 HInstruction call = pop();
2589 return new HIs.compound(type, expression, call, backend.boolType); 2492 return new HIs.compound(type, expression, call, backend.boolType);
2590 } else { 2493 } else {
2591 if (backend.hasDirectCheckFor(type)) { 2494 if (backend.hasDirectCheckFor(type)) {
2592 return new HIs.direct(type, expression, backend.boolType); 2495 return new HIs.direct(type, expression, backend.boolType);
2593 } 2496 }
2594 // The interceptor is not always needed. It is removed by optimization 2497 // The interceptor is not always needed. It is removed by optimization
2595 // when the receiver type or tested type permit. 2498 // when the receiver type or tested type permit.
2596 return new HIs.raw( 2499 return new HIs.raw(
2597 type, expression, invokeInterceptor(expression), backend.boolType); 2500 type, expression, invokeInterceptor(expression), backend.boolType);
2598 } 2501 }
2599 } 2502 }
2600 2503
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) { 2504 void addDynamicSendArgumentsToList(ast.Send node, List<HInstruction> list) {
2607 CallStructure callStructure = elements.getSelector(node).callStructure; 2505 CallStructure callStructure = elements.getSelector(node).callStructure;
2608 if (callStructure.namedArgumentCount == 0) { 2506 if (callStructure.namedArgumentCount == 0) {
2609 addGenericSendArgumentsToList(node.arguments, list); 2507 addGenericSendArgumentsToList(node.arguments, list);
2610 } else { 2508 } else {
2611 // Visit positional arguments and add them to the list. 2509 // Visit positional arguments and add them to the list.
2612 Link<ast.Node> arguments = node.arguments; 2510 Link<ast.Node> arguments = node.arguments;
2613 int positionalArgumentCount = callStructure.positionalArgumentCount; 2511 int positionalArgumentCount = callStructure.positionalArgumentCount;
2614 for (int i = 0; 2512 for (int i = 0;
2615 i < positionalArgumentCount; 2513 i < positionalArgumentCount;
(...skipping 766 matching lines...) Expand 10 before | Expand all | Expand 10 after
3382 bool needsSubstitutionForTypeVariableAccess(ClassElement cls) { 3280 bool needsSubstitutionForTypeVariableAccess(ClassElement cls) {
3383 ClosedWorld closedWorld = compiler.closedWorld; 3281 ClosedWorld closedWorld = compiler.closedWorld;
3384 if (closedWorld.isUsedAsMixin(cls)) return true; 3282 if (closedWorld.isUsedAsMixin(cls)) return true;
3385 3283
3386 return compiler.closedWorld.anyStrictSubclassOf(cls, 3284 return compiler.closedWorld.anyStrictSubclassOf(cls,
3387 (ClassElement subclass) { 3285 (ClassElement subclass) {
3388 return !rti.isTrivialSubstitution(subclass, cls); 3286 return !rti.isTrivialSubstitution(subclass, cls);
3389 }); 3287 });
3390 } 3288 }
3391 3289
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( 3290 HInstruction handleListConstructor(
3500 InterfaceType type, ast.Node currentNode, HInstruction newObject) { 3291 InterfaceType type, ast.Node currentNode, HInstruction newObject) {
3501 if (!backend.classNeedsRti(type.element) || type.treatAsRaw) { 3292 if (!backend.classNeedsRti(type.element) || type.treatAsRaw) {
3502 return newObject; 3293 return newObject;
3503 } 3294 }
3504 List<HInstruction> inputs = <HInstruction>[]; 3295 List<HInstruction> inputs = <HInstruction>[];
3505 type = localsHandler.substInContext(type); 3296 type = localsHandler.substInContext(type);
3506 type.typeArguments.forEach((DartType argument) { 3297 type.typeArguments.forEach((DartType argument) {
3507 inputs.add(analyzeTypeArgument(argument)); 3298 inputs.add(typeVerifier.analyzeTypeArgument(argument, sourceElement));
3508 }); 3299 });
3509 // TODO(15489): Register at codegen. 3300 // TODO(15489): Register at codegen.
3510 registry?.registerInstantiation(type); 3301 registry?.registerInstantiation(type);
3511 return callSetRuntimeTypeInfoWithTypeArguments( 3302 return callSetRuntimeTypeInfoWithTypeArguments(
3512 type.element, inputs, newObject); 3303 type.element, inputs, newObject);
3513 } 3304 }
3514 3305
3515 HInstruction callSetRuntimeTypeInfoWithTypeArguments(ClassElement element, 3306 HInstruction callSetRuntimeTypeInfoWithTypeArguments(ClassElement element,
3516 List<HInstruction> rtiInputs, HInstruction newObject) { 3307 List<HInstruction> rtiInputs, HInstruction newObject) {
3517 if (!backend.classNeedsRti(element)) { 3308 if (!backend.classNeedsRti(element)) {
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after
3745 if (backend.classNeedsRti(coreClasses.listClass) && 3536 if (backend.classNeedsRti(coreClasses.listClass) &&
3746 (isFixedListConstructorCall || 3537 (isFixedListConstructorCall ||
3747 isGrowableListConstructorCall || 3538 isGrowableListConstructorCall ||
3748 isJSArrayTypedConstructor)) { 3539 isJSArrayTypedConstructor)) {
3749 newInstance = handleListConstructor(type, send, pop()); 3540 newInstance = handleListConstructor(type, send, pop());
3750 stack.add(newInstance); 3541 stack.add(newInstance);
3751 } 3542 }
3752 3543
3753 // Finally, if we called a redirecting factory constructor, check the type. 3544 // Finally, if we called a redirecting factory constructor, check the type.
3754 if (isRedirected) { 3545 if (isRedirected) {
3755 HInstruction checked = potentiallyCheckOrTrustType(newInstance, type); 3546 HInstruction checked = typeVerifier.potentiallyCheckOrTrustType(
3547 newInstance, type);
3756 if (checked != newInstance) { 3548 if (checked != newInstance) {
3757 pop(); 3549 pop();
3758 stack.add(checked); 3550 stack.add(checked);
3759 } 3551 }
3760 } 3552 }
3761 } 3553 }
3762 3554
3763 void potentiallyAddTypeArguments( 3555 void potentiallyAddTypeArguments(
3764 List<HInstruction> inputs, ClassElement cls, InterfaceType expectedType, 3556 List<HInstruction> inputs, ClassElement cls, InterfaceType expectedType,
3765 {SourceInformation sourceInformation}) { 3557 {SourceInformation sourceInformation}) {
3766 if (!backend.classNeedsRti(cls)) return; 3558 if (!backend.classNeedsRti(cls)) return;
3767 assert(cls.typeVariables.length == expectedType.typeArguments.length); 3559 assert(cls.typeVariables.length == expectedType.typeArguments.length);
3768 expectedType.typeArguments.forEach((DartType argument) { 3560 expectedType.typeArguments.forEach((DartType argument) {
3769 inputs.add( 3561 inputs.add(
3770 analyzeTypeArgument(argument, sourceInformation: sourceInformation)); 3562 typeVerifier.analyzeTypeArgument(argument, sourceElement,
3563 sourceInformation: sourceInformation));
3771 }); 3564 });
3772 } 3565 }
3773 3566
3774 /// In checked mode checks the [type] of [node] to be well-bounded. The method 3567 /// In checked mode checks the [type] of [node] to be well-bounded. The method
3775 /// returns [:true:] if an error can be statically determined. 3568 /// returns [:true:] if an error can be statically determined.
3776 bool checkTypeVariableBounds(ast.NewExpression node, InterfaceType type) { 3569 bool checkTypeVariableBounds(ast.NewExpression node, InterfaceType type) {
3777 if (!compiler.options.enableTypeAssertions) return false; 3570 if (!compiler.options.enableTypeAssertions) return false;
3778 3571
3779 Map<DartType, Set<DartType>> seenChecksMap = 3572 Map<DartType, Set<DartType>> seenChecksMap =
3780 new Map<DartType, Set<DartType>>(); 3573 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. 3825 /// Generate the literal for [typeVariable] in the current context.
4033 void generateTypeVariableLiteral( 3826 void generateTypeVariableLiteral(
4034 ast.Send node, TypeVariableType typeVariable) { 3827 ast.Send node, TypeVariableType typeVariable) {
4035 // GENERIC_METHODS: This provides thin support for method type variables 3828 // GENERIC_METHODS: This provides thin support for method type variables
4036 // by treating them as malformed when evaluated as a literal. For full 3829 // by treating them as malformed when evaluated as a literal. For full
4037 // support of generic methods this must be revised. 3830 // support of generic methods this must be revised.
4038 if (typeVariable is MethodTypeVariableType) { 3831 if (typeVariable is MethodTypeVariableType) {
4039 generateTypeError(node, "Method type variables are not reified"); 3832 generateTypeError(node, "Method type variables are not reified");
4040 } else { 3833 } else {
4041 DartType type = localsHandler.substInContext(typeVariable); 3834 DartType type = localsHandler.substInContext(typeVariable);
4042 HInstruction value = analyzeTypeArgument(type, 3835 HInstruction value = typeVerifier.analyzeTypeArgument(type, sourceElement,
4043 sourceInformation: sourceInformationBuilder.buildGet(node)); 3836 sourceInformation: sourceInformationBuilder.buildGet(node));
4044 pushInvokeStatic(node, helpers.runtimeTypeToString, [value], 3837 pushInvokeStatic(node, helpers.runtimeTypeToString, [value],
4045 typeMask: backend.stringType); 3838 typeMask: backend.stringType);
4046 pushInvokeStatic(node, helpers.createRuntimeType, [pop()]); 3839 pushInvokeStatic(node, helpers.createRuntimeType, [pop()]);
4047 } 3840 }
4048 } 3841 }
4049 3842
4050 /// Generate a call to a type literal. 3843 /// Generate a call to a type literal.
4051 void generateTypeLiteralCall(ast.Send node) { 3844 void generateTypeLiteralCall(ast.Send node) {
4052 // This send is of the form 'e(...)', where e is resolved to a type 3845 // 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 } 5151 }
5359 } 5152 }
5360 5153
5361 ClassElement targetClass = targetConstructor.enclosingClass; 5154 ClassElement targetClass = targetConstructor.enclosingClass;
5362 if (backend.classNeedsRti(targetClass)) { 5155 if (backend.classNeedsRti(targetClass)) {
5363 ClassElement cls = redirectingConstructor.enclosingClass; 5156 ClassElement cls = redirectingConstructor.enclosingClass;
5364 InterfaceType targetType = 5157 InterfaceType targetType =
5365 redirectingConstructor.computeEffectiveTargetType(cls.thisType); 5158 redirectingConstructor.computeEffectiveTargetType(cls.thisType);
5366 targetType = localsHandler.substInContext(targetType); 5159 targetType = localsHandler.substInContext(targetType);
5367 targetType.typeArguments.forEach((DartType argument) { 5160 targetType.typeArguments.forEach((DartType argument) {
5368 inputs.add(analyzeTypeArgument(argument)); 5161 inputs.add(typeVerifier.analyzeTypeArgument(argument, sourceElement));
5369 }); 5162 });
5370 } 5163 }
5371 pushInvokeStatic(node, targetConstructor.declaration, inputs); 5164 pushInvokeStatic(node, targetConstructor.declaration, inputs);
5372 HInstruction value = pop(); 5165 HInstruction value = pop();
5373 emitReturn(value, node); 5166 emitReturn(value, node);
5374 } 5167 }
5375 5168
5376 /// Returns true if the [type] is a valid return type for an asynchronous 5169 /// Returns true if the [type] is a valid return type for an asynchronous
5377 /// function. 5170 /// function.
5378 /// 5171 ///
(...skipping 29 matching lines...) Expand all
5408 if (isBuildingAsyncFunction) { 5201 if (isBuildingAsyncFunction) {
5409 if (compiler.options.enableTypeAssertions && 5202 if (compiler.options.enableTypeAssertions &&
5410 !isValidAsyncReturnType(returnType)) { 5203 !isValidAsyncReturnType(returnType)) {
5411 String message = "Async function returned a Future, " 5204 String message = "Async function returned a Future, "
5412 "was declared to return a $returnType."; 5205 "was declared to return a $returnType.";
5413 generateTypeError(node, message); 5206 generateTypeError(node, message);
5414 pop(); 5207 pop();
5415 return; 5208 return;
5416 } 5209 }
5417 } else { 5210 } else {
5418 value = potentiallyCheckOrTrustType(value, returnType); 5211 value = typeVerifier.potentiallyCheckOrTrustType(value, returnType);
5419 } 5212 }
5420 } 5213 }
5421 5214
5422 handleInTryStatement(); 5215 handleInTryStatement();
5423 emitReturn(value, node); 5216 emitReturn(value, node);
5424 } 5217 }
5425 5218
5426 visitThrow(ast.Throw node) { 5219 visitThrow(ast.Throw node) {
5427 visitThrowExpression(node.expression); 5220 visitThrowExpression(node.expression);
5428 if (isReachable) { 5221 if (isReachable) {
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
5470 } 5263 }
5471 } 5264 }
5472 5265
5473 HInstruction setRtiIfNeeded(HInstruction object, ast.Node node) { 5266 HInstruction setRtiIfNeeded(HInstruction object, ast.Node node) {
5474 InterfaceType type = localsHandler.substInContext(elements.getType(node)); 5267 InterfaceType type = localsHandler.substInContext(elements.getType(node));
5475 if (!backend.classNeedsRti(type.element) || type.treatAsRaw) { 5268 if (!backend.classNeedsRti(type.element) || type.treatAsRaw) {
5476 return object; 5269 return object;
5477 } 5270 }
5478 List<HInstruction> arguments = <HInstruction>[]; 5271 List<HInstruction> arguments = <HInstruction>[];
5479 for (DartType argument in type.typeArguments) { 5272 for (DartType argument in type.typeArguments) {
5480 arguments.add(analyzeTypeArgument(argument)); 5273 arguments.add(typeVerifier.analyzeTypeArgument(argument, sourceElement));
5481 } 5274 }
5482 // TODO(15489): Register at codegen. 5275 // TODO(15489): Register at codegen.
5483 registry?.registerInstantiation(type); 5276 registry?.registerInstantiation(type);
5484 return callSetRuntimeTypeInfoWithTypeArguments( 5277 return callSetRuntimeTypeInfoWithTypeArguments(
5485 type.element, arguments, object); 5278 type.element, arguments, object);
5486 } 5279 }
5487 5280
5488 visitLiteralList(ast.LiteralList node) { 5281 visitLiteralList(ast.LiteralList node) {
5489 HInstruction instruction; 5282 HInstruction instruction;
5490 5283
(...skipping 427 matching lines...) Expand 10 before | Expand all | Expand 10 after
5918 InterfaceType type = elements.getType(node); 5711 InterfaceType type = elements.getType(node);
5919 InterfaceType expectedType = 5712 InterfaceType expectedType =
5920 functionElement.computeEffectiveTargetType(type); 5713 functionElement.computeEffectiveTargetType(type);
5921 expectedType = localsHandler.substInContext(expectedType); 5714 expectedType = localsHandler.substInContext(expectedType);
5922 5715
5923 ClassElement cls = constructor.enclosingClass; 5716 ClassElement cls = constructor.enclosingClass;
5924 5717
5925 if (backend.classNeedsRti(cls)) { 5718 if (backend.classNeedsRti(cls)) {
5926 List<HInstruction> typeInputs = <HInstruction>[]; 5719 List<HInstruction> typeInputs = <HInstruction>[];
5927 expectedType.typeArguments.forEach((DartType argument) { 5720 expectedType.typeArguments.forEach((DartType argument) {
5928 typeInputs.add(analyzeTypeArgument(argument)); 5721 typeInputs.add(typeVerifier.analyzeTypeArgument(
5722 argument, sourceElement));
5929 }); 5723 });
5930 5724
5931 // We lift this common call pattern into a helper function to save space 5725 // We lift this common call pattern into a helper function to save space
5932 // in the output. 5726 // in the output.
5933 if (typeInputs.every((HInstruction input) => input.isNull())) { 5727 if (typeInputs.every((HInstruction input) => input.isNull())) {
5934 if (listInputs.isEmpty) { 5728 if (listInputs.isEmpty) {
5935 constructor = helpers.mapLiteralUntypedEmptyMaker; 5729 constructor = helpers.mapLiteralUntypedEmptyMaker;
5936 } else { 5730 } else {
5937 constructor = helpers.mapLiteralUntypedMaker; 5731 constructor = helpers.mapLiteralUntypedMaker;
5938 } 5732 }
(...skipping 1078 matching lines...) Expand 10 before | Expand all | Expand 10 after
7017 6811
7018 void visitTypeVariableType(TypeVariableType type, SsaBuilder builder) { 6812 void visitTypeVariableType(TypeVariableType type, SsaBuilder builder) {
7019 ClassElement cls = builder.backend.helpers.RuntimeType; 6813 ClassElement cls = builder.backend.helpers.RuntimeType;
7020 TypeMask instructionType = new TypeMask.subclass(cls, closedWorld); 6814 TypeMask instructionType = new TypeMask.subclass(cls, closedWorld);
7021 if (!builder.sourceElement.enclosingElement.isClosure && 6815 if (!builder.sourceElement.enclosingElement.isClosure &&
7022 builder.sourceElement.isInstanceMember) { 6816 builder.sourceElement.isInstanceMember) {
7023 HInstruction receiver = builder.localsHandler.readThis(); 6817 HInstruction receiver = builder.localsHandler.readThis();
7024 builder.push(new HReadTypeVariable(type, receiver, instructionType)); 6818 builder.push(new HReadTypeVariable(type, receiver, instructionType));
7025 } else { 6819 } else {
7026 builder.push(new HReadTypeVariable.noReceiver( 6820 builder.push(new HReadTypeVariable.noReceiver(
7027 type, builder.addTypeVariableReference(type), instructionType)); 6821 type, builder.typeVerifier.addTypeVariableReference(
6822 type, builder.sourceElement), instructionType));
7028 } 6823 }
7029 } 6824 }
7030 6825
7031 void visitFunctionType(FunctionType type, SsaBuilder builder) { 6826 void visitFunctionType(FunctionType type, SsaBuilder builder) {
7032 type.returnType.accept(this, builder); 6827 type.returnType.accept(this, builder);
7033 HInstruction returnType = builder.pop(); 6828 HInstruction returnType = builder.pop();
7034 List<HInstruction> inputs = <HInstruction>[returnType]; 6829 List<HInstruction> inputs = <HInstruction>[returnType];
7035 6830
7036 for (DartType parameter in type.parameterTypes) { 6831 for (DartType parameter in type.parameterTypes) {
7037 parameter.accept(this, builder); 6832 parameter.accept(this, builder);
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
7086 if (unaliased is TypedefType) throw 'unable to unalias $type'; 6881 if (unaliased is TypedefType) throw 'unable to unalias $type';
7087 unaliased.accept(this, builder); 6882 unaliased.accept(this, builder);
7088 } 6883 }
7089 6884
7090 void visitDynamicType(DynamicType type, SsaBuilder builder) { 6885 void visitDynamicType(DynamicType type, SsaBuilder builder) {
7091 JavaScriptBackend backend = builder.compiler.backend; 6886 JavaScriptBackend backend = builder.compiler.backend;
7092 ClassElement cls = backend.helpers.DynamicRuntimeType; 6887 ClassElement cls = backend.helpers.DynamicRuntimeType;
7093 builder.push(new HDynamicType(type, new TypeMask.exact(cls, closedWorld))); 6888 builder.push(new HDynamicType(type, new TypeMask.exact(cls, closedWorld)));
7094 } 6889 }
7095 } 6890 }
OLDNEW
« no previous file with comments | « no previous file | pkg/compiler/lib/src/ssa/builder_kernel.dart » ('j') | pkg/compiler/lib/src/ssa/builder_kernel.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698