Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 part of dart2js; | 5 part of dart2js; |
| 6 | 6 |
| 7 /** | 7 /** |
| 8 * The [ConstantHandler] keeps track of compile-time constants, | 8 * The [ConstantHandler] keeps track of compile-time constants, |
| 9 * initializations of global and static fields, and default values of | 9 * initializations of global and static fields, and default values of |
| 10 * optional parameters. | 10 * optional parameters. |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 25 | 25 |
| 26 /** The set of variable elements that are in the process of being computed. */ | 26 /** The set of variable elements that are in the process of being computed. */ |
| 27 final Set<VariableElement> pendingVariables; | 27 final Set<VariableElement> pendingVariables; |
| 28 | 28 |
| 29 /** Caches the statics where the initial value cannot be eagerly compiled. */ | 29 /** Caches the statics where the initial value cannot be eagerly compiled. */ |
| 30 final Set<VariableElement> lazyStatics; | 30 final Set<VariableElement> lazyStatics; |
| 31 | 31 |
| 32 /** Caches the createRuntimeType function if registered. */ | 32 /** Caches the createRuntimeType function if registered. */ |
| 33 Element createRuntimeTypeFunction = null; | 33 Element createRuntimeTypeFunction = null; |
| 34 | 34 |
| 35 /** Caches the setRuntimeTypeInfo function if registered. */ | |
| 36 Element setRuntimeTypeInfoFunction = null; | |
| 37 | |
| 35 ConstantHandler(Compiler compiler, this.constantSystem, | 38 ConstantHandler(Compiler compiler, this.constantSystem, |
| 36 { bool this.isMetadata: false }) | 39 { bool this.isMetadata: false }) |
| 37 : initialVariableValues = new Map<VariableElement, dynamic>(), | 40 : initialVariableValues = new Map<VariableElement, dynamic>(), |
| 38 compiledConstants = new Set<Constant>(), | 41 compiledConstants = new Set<Constant>(), |
| 39 pendingVariables = new Set<VariableElement>(), | 42 pendingVariables = new Set<VariableElement>(), |
| 40 lazyStatics = new Set<VariableElement>(), | 43 lazyStatics = new Set<VariableElement>(), |
| 41 super(compiler); | 44 super(compiler); |
| 42 | 45 |
| 43 String get name => 'ConstantHandler'; | 46 String get name => 'ConstantHandler'; |
| 44 | 47 |
| 45 void registerCompileTimeConstant(Constant constant, TreeElements elements) { | 48 void registerCompileTimeConstant(Constant constant, TreeElements elements) { |
| 46 registerInstantiatedClass(constant.computeType(compiler).element, elements); | 49 registerInstantiatedType(constant.computeType(compiler), elements); |
| 47 if (constant.isFunction()) { | 50 if (constant.isFunction()) { |
| 48 FunctionConstant function = constant; | 51 FunctionConstant function = constant; |
| 49 registerGetOfStaticFunction(function.element); | 52 registerGetOfStaticFunction(function.element); |
| 50 } else if (constant.isInterceptor()) { | 53 } else if (constant.isInterceptor()) { |
| 51 // An interceptor constant references the class's prototype chain. | 54 // An interceptor constant references the class's prototype chain. |
| 52 InterceptorConstant interceptor = constant; | 55 InterceptorConstant interceptor = constant; |
| 53 registerInstantiatedClass(interceptor.dispatchedType.element, elements); | 56 registerInstantiatedType(interceptor.dispatchedType, elements); |
| 54 } | 57 } |
| 55 compiledConstants.add(constant); | 58 compiledConstants.add(constant); |
| 56 } | 59 } |
| 57 | 60 |
| 58 void registerInstantiatedClass(ClassElement element, TreeElements elements) { | 61 void registerInstantiatedType(DartType type, TreeElements elements) { |
| 59 if (isMetadata) return; | 62 if (isMetadata) return; |
| 60 compiler.enqueuer.codegen.registerInstantiatedClass(element, elements); | 63 compiler.enqueuer.codegen.registerInstantiatedType(type, elements); |
| 61 } | 64 } |
| 62 | 65 |
| 63 void registerStaticUse(Element element) { | 66 void registerStaticUse(Element element) { |
| 64 if (isMetadata) return; | 67 if (isMetadata) return; |
| 65 compiler.analyzeElement(element.declaration); | 68 compiler.analyzeElement(element.declaration); |
| 66 compiler.enqueuer.codegen.registerStaticUse(element); | 69 compiler.enqueuer.codegen.registerStaticUse(element); |
| 67 } | 70 } |
| 68 | 71 |
| 69 void registerGetOfStaticFunction(FunctionElement element) { | 72 void registerGetOfStaticFunction(FunctionElement element) { |
| 70 if (isMetadata) return; | 73 if (isMetadata) return; |
| 71 compiler.analyzeElement(element.declaration); | 74 compiler.analyzeElement(element.declaration); |
| 72 compiler.enqueuer.codegen.registerGetOfStaticFunction(element); | 75 compiler.enqueuer.codegen.registerGetOfStaticFunction(element); |
| 73 } | 76 } |
| 74 | 77 |
| 75 void registerStringInstance(TreeElements elements) { | 78 void registerStringInstance(TreeElements elements) { |
| 76 registerInstantiatedClass(compiler.stringClass, elements); | 79 registerInstantiatedType(compiler.stringClass.rawType, elements); |
| 80 } | |
| 81 | |
| 82 void registerSetRuntimeTypeInfoFunction() { | |
| 83 if (setRuntimeTypeInfoFunction != null) return; | |
|
ngeoffray
2013/06/17 09:15:03
In non-checked mode, how do you make sure this hel
karlklose
2013/06/19 15:29:05
Added a check.
| |
| 84 SourceString helperName = const SourceString('setRuntimeTypeInfo'); | |
| 85 setRuntimeTypeInfoFunction = compiler.findHelper(helperName); | |
| 86 registerStaticUse(setRuntimeTypeInfoFunction); | |
| 77 } | 87 } |
| 78 | 88 |
| 79 void registerCreateRuntimeTypeFunction() { | 89 void registerCreateRuntimeTypeFunction() { |
| 80 if (createRuntimeTypeFunction != null) return; | 90 if (createRuntimeTypeFunction != null) return; |
| 81 SourceString helperName = const SourceString('createRuntimeType'); | 91 SourceString helperName = const SourceString('createRuntimeType'); |
| 82 createRuntimeTypeFunction = compiler.findHelper(helperName); | 92 createRuntimeTypeFunction = compiler.findHelper(helperName); |
| 83 registerStaticUse(createRuntimeTypeFunction); | 93 registerStaticUse(createRuntimeTypeFunction); |
| 84 } | 94 } |
| 85 | 95 |
| 86 /** | 96 /** |
| (...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 311 isEvaluatingConstant = oldIsEvaluatingConstant; | 321 isEvaluatingConstant = oldIsEvaluatingConstant; |
| 312 assert(result != null); | 322 assert(result != null); |
| 313 return result; | 323 return result; |
| 314 } | 324 } |
| 315 | 325 |
| 316 Constant visitNode(Node node) { | 326 Constant visitNode(Node node) { |
| 317 return signalNotCompileTimeConstant(node); | 327 return signalNotCompileTimeConstant(node); |
| 318 } | 328 } |
| 319 | 329 |
| 320 Constant visitLiteralBool(LiteralBool node) { | 330 Constant visitLiteralBool(LiteralBool node) { |
| 321 handler.registerInstantiatedClass(compiler.boolClass, elements); | 331 handler.registerInstantiatedType(compiler.boolClass.rawType, elements); |
| 322 return constantSystem.createBool(node.value); | 332 return constantSystem.createBool(node.value); |
| 323 } | 333 } |
| 324 | 334 |
| 325 Constant visitLiteralDouble(LiteralDouble node) { | 335 Constant visitLiteralDouble(LiteralDouble node) { |
| 326 handler.registerInstantiatedClass(compiler.doubleClass, elements); | 336 handler.registerInstantiatedType(compiler.doubleClass.rawType, elements); |
| 327 return constantSystem.createDouble(node.value); | 337 return constantSystem.createDouble(node.value); |
| 328 } | 338 } |
| 329 | 339 |
| 330 Constant visitLiteralInt(LiteralInt node) { | 340 Constant visitLiteralInt(LiteralInt node) { |
| 331 handler.registerInstantiatedClass(compiler.intClass, elements); | 341 handler.registerInstantiatedType(compiler.intClass.rawType, elements); |
| 332 return constantSystem.createInt(node.value); | 342 return constantSystem.createInt(node.value); |
| 333 } | 343 } |
| 334 | 344 |
| 335 Constant visitLiteralList(LiteralList node) { | 345 Constant visitLiteralList(LiteralList node) { |
| 336 if (!node.isConst()) { | 346 if (!node.isConst()) { |
| 337 return signalNotCompileTimeConstant(node); | 347 return signalNotCompileTimeConstant(node); |
| 338 } | 348 } |
| 339 List<Constant> arguments = <Constant>[]; | 349 List<Constant> arguments = <Constant>[]; |
| 340 for (Link<Node> link = node.elements.nodes; | 350 for (Link<Node> link = node.elements.nodes; |
| 341 !link.isEmpty; | 351 !link.isEmpty; |
| 342 link = link.tail) { | 352 link = link.tail) { |
| 343 arguments.add(evaluateConstant(link.head)); | 353 arguments.add(evaluateConstant(link.head)); |
| 344 } | 354 } |
| 345 // TODO(9476): get type parameters. | 355 DartType type = elements.getType(node); |
| 346 compiler.listClass.computeType(compiler); | 356 handler.registerInstantiatedType(type, elements); |
| 347 DartType type = compiler.listClass.rawType; | 357 if (!type.isRaw) { |
| 358 handler.registerSetRuntimeTypeInfoFunction(); | |
|
ngeoffray
2013/06/17 09:15:03
Move this check to [registerInstantiatedType]?
karlklose
2013/06/19 15:29:05
Done.
| |
| 359 } | |
| 348 Constant constant = new ListConstant(type, arguments); | 360 Constant constant = new ListConstant(type, arguments); |
| 349 handler.registerCompileTimeConstant(constant, elements); | 361 handler.registerCompileTimeConstant(constant, elements); |
| 350 return constant; | 362 return constant; |
| 351 } | 363 } |
| 352 | 364 |
| 353 Constant visitLiteralMap(LiteralMap node) { | 365 Constant visitLiteralMap(LiteralMap node) { |
| 354 if (!node.isConst()) { | 366 if (!node.isConst()) { |
| 355 return signalNotCompileTimeConstant(node); | 367 return signalNotCompileTimeConstant(node); |
| 356 } | 368 } |
| 357 List<StringConstant> keys = <StringConstant>[]; | 369 List<StringConstant> keys = <StringConstant>[]; |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 372 List<Constant> values = <Constant>[]; | 384 List<Constant> values = <Constant>[]; |
| 373 Constant protoValue = null; | 385 Constant protoValue = null; |
| 374 for (StringConstant key in keys) { | 386 for (StringConstant key in keys) { |
| 375 if (key.value == MapConstant.PROTO_PROPERTY) { | 387 if (key.value == MapConstant.PROTO_PROPERTY) { |
| 376 protoValue = map[key]; | 388 protoValue = map[key]; |
| 377 } else { | 389 } else { |
| 378 values.add(map[key]); | 390 values.add(map[key]); |
| 379 } | 391 } |
| 380 } | 392 } |
| 381 bool hasProtoKey = (protoValue != null); | 393 bool hasProtoKey = (protoValue != null); |
| 382 // TODO(9476): this should be a List<String> type. | 394 InterfaceType sourceType = elements.getType(node); |
| 383 compiler.listClass.computeType(compiler); | 395 Link<DartType> arguments = |
| 384 DartType keysType = compiler.listClass.rawType; | 396 new Link<DartType>.fromList([compiler.stringClass.rawType]); |
| 397 DartType keysType = new InterfaceType(compiler.listClass, arguments); | |
| 385 ListConstant keysList = new ListConstant(keysType, keys); | 398 ListConstant keysList = new ListConstant(keysType, keys); |
| 386 handler.registerCompileTimeConstant(keysList, elements); | 399 handler.registerCompileTimeConstant(keysList, elements); |
| 387 SourceString className = hasProtoKey | 400 SourceString className = hasProtoKey |
| 388 ? MapConstant.DART_PROTO_CLASS | 401 ? MapConstant.DART_PROTO_CLASS |
| 389 : MapConstant.DART_CLASS; | 402 : MapConstant.DART_CLASS; |
| 390 ClassElement classElement = compiler.jsHelperLibrary.find(className); | 403 ClassElement classElement = compiler.jsHelperLibrary.find(className); |
| 391 classElement.ensureResolved(compiler); | 404 classElement.ensureResolved(compiler); |
| 392 // TODO(9476): copy over the generic type. | 405 Link<DartType> typeArgument = sourceType.typeArguments.tail; |
| 393 DartType type = classElement.rawType; | 406 InterfaceType type = new InterfaceType(classElement, typeArgument); |
| 394 handler.registerInstantiatedClass(classElement, elements); | 407 handler.registerInstantiatedType(type, elements); |
| 408 if (!type.isRaw) { | |
|
ngeoffray
2013/06/17 09:15:03
Ditto.
karlklose
2013/06/19 15:29:05
Done.
| |
| 409 handler.registerSetRuntimeTypeInfoFunction(); | |
| 410 } | |
| 395 Constant constant = new MapConstant(type, keysList, values, protoValue); | 411 Constant constant = new MapConstant(type, keysList, values, protoValue); |
| 396 handler.registerCompileTimeConstant(constant, elements); | 412 handler.registerCompileTimeConstant(constant, elements); |
| 397 return constant; | 413 return constant; |
| 398 } | 414 } |
| 399 | 415 |
| 400 Constant visitLiteralNull(LiteralNull node) { | 416 Constant visitLiteralNull(LiteralNull node) { |
| 401 return constantSystem.createNull(); | 417 return constantSystem.createNull(); |
| 402 } | 418 } |
| 403 | 419 |
| 404 Constant visitLiteralString(LiteralString node) { | 420 Constant visitLiteralString(LiteralString node) { |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 438 if (partString == null) return null; | 454 if (partString == null) return null; |
| 439 accumulator = new DartString.concat(accumulator, partString.value); | 455 accumulator = new DartString.concat(accumulator, partString.value); |
| 440 }; | 456 }; |
| 441 handler.registerStringInstance(elements); | 457 handler.registerStringInstance(elements); |
| 442 return constantSystem.createString(accumulator, node); | 458 return constantSystem.createString(accumulator, node); |
| 443 } | 459 } |
| 444 | 460 |
| 445 Constant makeTypeConstant(Element element) { | 461 Constant makeTypeConstant(Element element) { |
| 446 DartType elementType = element.computeType(compiler).asRaw(); | 462 DartType elementType = element.computeType(compiler).asRaw(); |
| 447 if (compiler.mirrorsEnabled) { | 463 if (compiler.mirrorsEnabled) { |
| 448 handler.registerInstantiatedClass(element, elements); | 464 handler.registerInstantiatedType(elementType, elements); |
| 449 } | 465 } |
| 450 DartType constantType = | 466 DartType constantType = |
| 451 compiler.backend.typeImplementation.computeType(compiler); | 467 compiler.backend.typeImplementation.computeType(compiler); |
| 452 Constant constant = new TypeConstant(elementType, constantType); | 468 Constant constant = new TypeConstant(elementType, constantType); |
| 453 // If we use a type literal in a constant, the compile time | 469 // If we use a type literal in a constant, the compile time |
| 454 // constant emitter will generate a call to the createRuntimeType | 470 // constant emitter will generate a call to the createRuntimeType |
| 455 // helper so we register a use of that. | 471 // helper so we register a use of that. |
| 456 handler.registerCreateRuntimeTypeFunction(); | 472 handler.registerCreateRuntimeTypeFunction(); |
| 457 handler.registerCompileTimeConstant(constant, elements); | 473 handler.registerCompileTimeConstant(constant, elements); |
| 458 return constant; | 474 return constant; |
| (...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 642 } | 658 } |
| 643 return compiledArguments; | 659 return compiledArguments; |
| 644 } | 660 } |
| 645 | 661 |
| 646 Constant visitNewExpression(NewExpression node) { | 662 Constant visitNewExpression(NewExpression node) { |
| 647 if (!node.isConst()) { | 663 if (!node.isConst()) { |
| 648 return signalNotCompileTimeConstant(node); | 664 return signalNotCompileTimeConstant(node); |
| 649 } | 665 } |
| 650 | 666 |
| 651 Send send = node.send; | 667 Send send = node.send; |
| 652 FunctionElement constructor = elements[send]; | 668 FunctionElement functionElement = elements[send]; |
| 669 FunctionElement constructor = functionElement; | |
|
ngeoffray
2013/06/17 09:15:03
What is this double assignment for? If line 678 ch
karlklose
2013/06/19 15:29:05
Yes, this is left-over code. Removed.
| |
| 653 // TODO(ahe): This is nasty: we must eagerly analyze the | 670 // TODO(ahe): This is nasty: we must eagerly analyze the |
| 654 // constructor to ensure the redirectionTarget has been computed | 671 // constructor to ensure the redirectionTarget has been computed |
| 655 // correctly. Find a way to avoid this. | 672 // correctly. Find a way to avoid this. |
| 656 compiler.analyzeElement(constructor.declaration); | 673 compiler.analyzeElement(constructor.declaration); |
| 657 constructor = constructor.redirectionTarget; | 674 constructor = constructor.redirectionTarget; |
| 658 ClassElement classElement = constructor.getEnclosingClass(); | 675 ClassElement classElement = constructor.getEnclosingClass(); |
| 659 // The constructor must be an implementation to ensure that field | 676 // The constructor must be an implementation to ensure that field |
| 660 // initializers are handled correctly. | 677 // initializers are handled correctly. |
| 661 constructor = constructor.implementation; | 678 constructor = constructor.implementation; |
| 662 assert(invariant(node, constructor.isImplementation)); | 679 assert(invariant(node, constructor.isImplementation)); |
| 663 | 680 |
| 664 Selector selector = elements.getSelector(send); | 681 Selector selector = elements.getSelector(send); |
| 665 List<Constant> arguments = evaluateArgumentsToConstructor( | 682 List<Constant> arguments = evaluateArgumentsToConstructor( |
| 666 node, selector, send.arguments, constructor); | 683 node, selector, send.arguments, constructor); |
| 667 ConstructorEvaluator evaluator = | 684 ConstructorEvaluator evaluator = |
| 668 new ConstructorEvaluator(node, constructor, handler, compiler); | 685 new ConstructorEvaluator(node, constructor, handler, compiler); |
| 669 evaluator.evaluateConstructorFieldValues(arguments); | 686 evaluator.evaluateConstructorFieldValues(arguments); |
| 670 List<Constant> jsNewArguments = evaluator.buildJsNewArguments(classElement); | 687 List<Constant> jsNewArguments = evaluator.buildJsNewArguments(classElement); |
| 671 | 688 |
| 672 handler.registerInstantiatedClass(classElement, elements); | 689 InterfaceType type = elements.getType(node); |
| 673 // TODO(9476): take generic types into account. | 690 bool isRedirected = functionElement.isRedirectingFactory; |
| 674 classElement.computeType(compiler); | 691 if (isRedirected) { |
| 675 DartType type = classElement.rawType; | 692 type = functionElement.computeTargetType(compiler, type); |
| 693 } | |
| 694 | |
| 695 handler.registerInstantiatedType(type, elements); | |
| 696 if (type is InterfaceType && !type.isRaw) { | |
| 697 handler.registerSetRuntimeTypeInfoFunction(); | |
| 698 } | |
| 676 Constant constant = new ConstructedConstant(type, jsNewArguments); | 699 Constant constant = new ConstructedConstant(type, jsNewArguments); |
| 677 handler.registerCompileTimeConstant(constant, elements); | 700 handler.registerCompileTimeConstant(constant, elements); |
| 678 return constant; | 701 return constant; |
| 679 } | 702 } |
| 680 | 703 |
| 681 Constant visitParenthesizedExpression(ParenthesizedExpression node) { | 704 Constant visitParenthesizedExpression(ParenthesizedExpression node) { |
| 682 return node.expression.accept(this); | 705 return node.expression.accept(this); |
| 683 } | 706 } |
| 684 | 707 |
| 685 error(Node node) { | 708 error(Node node) { |
| (...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 890 if (fieldValue == null) { | 913 if (fieldValue == null) { |
| 891 // Use the default value. | 914 // Use the default value. |
| 892 fieldValue = handler.compileConstant(field); | 915 fieldValue = handler.compileConstant(field); |
| 893 } | 916 } |
| 894 jsNewArguments.add(fieldValue); | 917 jsNewArguments.add(fieldValue); |
| 895 }, | 918 }, |
| 896 includeSuperAndInjectedMembers: true); | 919 includeSuperAndInjectedMembers: true); |
| 897 return jsNewArguments; | 920 return jsNewArguments; |
| 898 } | 921 } |
| 899 } | 922 } |
| OLD | NEW |