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); |
| 64 if (type is InterfaceType && !type.isRaw && | |
|
ngeoffray
2013/06/19 19:55:48
nit: move !type.isRaw to a new line.
karlklose
2013/06/20 12:49:21
Done.
| |
| 65 compiler.backend.needsRti(type.element)) { | |
| 66 registerSetRuntimeTypeInfoFunction(); | |
| 67 } | |
| 61 } | 68 } |
| 62 | 69 |
| 63 void registerStaticUse(Element element) { | 70 void registerStaticUse(Element element) { |
| 64 if (isMetadata) return; | 71 if (isMetadata) return; |
| 65 compiler.analyzeElement(element.declaration); | 72 compiler.analyzeElement(element.declaration); |
| 66 compiler.enqueuer.codegen.registerStaticUse(element); | 73 compiler.enqueuer.codegen.registerStaticUse(element); |
| 67 } | 74 } |
| 68 | 75 |
| 69 void registerGetOfStaticFunction(FunctionElement element) { | 76 void registerGetOfStaticFunction(FunctionElement element) { |
| 70 if (isMetadata) return; | 77 if (isMetadata) return; |
| 71 compiler.analyzeElement(element.declaration); | 78 compiler.analyzeElement(element.declaration); |
| 72 compiler.enqueuer.codegen.registerGetOfStaticFunction(element); | 79 compiler.enqueuer.codegen.registerGetOfStaticFunction(element); |
| 73 } | 80 } |
| 74 | 81 |
| 75 void registerStringInstance(TreeElements elements) { | 82 void registerStringInstance(TreeElements elements) { |
| 76 registerInstantiatedClass(compiler.stringClass, elements); | 83 registerInstantiatedType(compiler.stringClass.rawType, elements); |
| 84 } | |
| 85 | |
| 86 void registerSetRuntimeTypeInfoFunction() { | |
| 87 if (setRuntimeTypeInfoFunction != null) return; | |
| 88 SourceString helperName = const SourceString('setRuntimeTypeInfo'); | |
| 89 setRuntimeTypeInfoFunction = compiler.findHelper(helperName); | |
| 90 registerStaticUse(setRuntimeTypeInfoFunction); | |
| 77 } | 91 } |
| 78 | 92 |
| 79 void registerCreateRuntimeTypeFunction() { | 93 void registerCreateRuntimeTypeFunction() { |
| 80 if (createRuntimeTypeFunction != null) return; | 94 if (createRuntimeTypeFunction != null) return; |
| 81 SourceString helperName = const SourceString('createRuntimeType'); | 95 SourceString helperName = const SourceString('createRuntimeType'); |
| 82 createRuntimeTypeFunction = compiler.findHelper(helperName); | 96 createRuntimeTypeFunction = compiler.findHelper(helperName); |
| 83 registerStaticUse(createRuntimeTypeFunction); | 97 registerStaticUse(createRuntimeTypeFunction); |
| 84 } | 98 } |
| 85 | 99 |
| 86 /** | 100 /** |
| (...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 311 isEvaluatingConstant = oldIsEvaluatingConstant; | 325 isEvaluatingConstant = oldIsEvaluatingConstant; |
| 312 assert(result != null); | 326 assert(result != null); |
| 313 return result; | 327 return result; |
| 314 } | 328 } |
| 315 | 329 |
| 316 Constant visitNode(Node node) { | 330 Constant visitNode(Node node) { |
| 317 return signalNotCompileTimeConstant(node); | 331 return signalNotCompileTimeConstant(node); |
| 318 } | 332 } |
| 319 | 333 |
| 320 Constant visitLiteralBool(LiteralBool node) { | 334 Constant visitLiteralBool(LiteralBool node) { |
| 321 handler.registerInstantiatedClass(compiler.boolClass, elements); | 335 handler.registerInstantiatedType(compiler.boolClass.rawType, elements); |
| 322 return constantSystem.createBool(node.value); | 336 return constantSystem.createBool(node.value); |
| 323 } | 337 } |
| 324 | 338 |
| 325 Constant visitLiteralDouble(LiteralDouble node) { | 339 Constant visitLiteralDouble(LiteralDouble node) { |
| 326 handler.registerInstantiatedClass(compiler.doubleClass, elements); | 340 handler.registerInstantiatedType(compiler.doubleClass.rawType, elements); |
| 327 return constantSystem.createDouble(node.value); | 341 return constantSystem.createDouble(node.value); |
| 328 } | 342 } |
| 329 | 343 |
| 330 Constant visitLiteralInt(LiteralInt node) { | 344 Constant visitLiteralInt(LiteralInt node) { |
| 331 handler.registerInstantiatedClass(compiler.intClass, elements); | 345 handler.registerInstantiatedType(compiler.intClass.rawType, elements); |
| 332 return constantSystem.createInt(node.value); | 346 return constantSystem.createInt(node.value); |
| 333 } | 347 } |
| 334 | 348 |
| 335 Constant visitLiteralList(LiteralList node) { | 349 Constant visitLiteralList(LiteralList node) { |
| 336 if (!node.isConst()) { | 350 if (!node.isConst()) { |
| 337 return signalNotCompileTimeConstant(node); | 351 return signalNotCompileTimeConstant(node); |
| 338 } | 352 } |
| 339 List<Constant> arguments = <Constant>[]; | 353 List<Constant> arguments = <Constant>[]; |
| 340 for (Link<Node> link = node.elements.nodes; | 354 for (Link<Node> link = node.elements.nodes; |
| 341 !link.isEmpty; | 355 !link.isEmpty; |
| 342 link = link.tail) { | 356 link = link.tail) { |
| 343 arguments.add(evaluateConstant(link.head)); | 357 arguments.add(evaluateConstant(link.head)); |
| 344 } | 358 } |
| 345 // TODO(9476): get type parameters. | 359 DartType type = elements.getType(node); |
| 346 compiler.listClass.computeType(compiler); | 360 handler.registerInstantiatedType(type, elements); |
| 347 DartType type = compiler.listClass.rawType; | |
| 348 Constant constant = new ListConstant(type, arguments); | 361 Constant constant = new ListConstant(type, arguments); |
| 349 handler.registerCompileTimeConstant(constant, elements); | 362 handler.registerCompileTimeConstant(constant, elements); |
| 350 return constant; | 363 return constant; |
| 351 } | 364 } |
| 352 | 365 |
| 353 Constant visitLiteralMap(LiteralMap node) { | 366 Constant visitLiteralMap(LiteralMap node) { |
| 354 if (!node.isConst()) { | 367 if (!node.isConst()) { |
| 355 return signalNotCompileTimeConstant(node); | 368 return signalNotCompileTimeConstant(node); |
| 356 } | 369 } |
| 357 List<StringConstant> keys = <StringConstant>[]; | 370 List<StringConstant> keys = <StringConstant>[]; |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 372 List<Constant> values = <Constant>[]; | 385 List<Constant> values = <Constant>[]; |
| 373 Constant protoValue = null; | 386 Constant protoValue = null; |
| 374 for (StringConstant key in keys) { | 387 for (StringConstant key in keys) { |
| 375 if (key.value == MapConstant.PROTO_PROPERTY) { | 388 if (key.value == MapConstant.PROTO_PROPERTY) { |
| 376 protoValue = map[key]; | 389 protoValue = map[key]; |
| 377 } else { | 390 } else { |
| 378 values.add(map[key]); | 391 values.add(map[key]); |
| 379 } | 392 } |
| 380 } | 393 } |
| 381 bool hasProtoKey = (protoValue != null); | 394 bool hasProtoKey = (protoValue != null); |
| 382 // TODO(9476): this should be a List<String> type. | 395 InterfaceType sourceType = elements.getType(node); |
| 383 compiler.listClass.computeType(compiler); | 396 Link<DartType> arguments = |
| 384 DartType keysType = compiler.listClass.rawType; | 397 new Link<DartType>.fromList([compiler.stringClass.rawType]); |
| 398 DartType keysType = new InterfaceType(compiler.listClass, arguments); | |
| 385 ListConstant keysList = new ListConstant(keysType, keys); | 399 ListConstant keysList = new ListConstant(keysType, keys); |
| 386 handler.registerCompileTimeConstant(keysList, elements); | 400 handler.registerCompileTimeConstant(keysList, elements); |
| 387 SourceString className = hasProtoKey | 401 SourceString className = hasProtoKey |
| 388 ? MapConstant.DART_PROTO_CLASS | 402 ? MapConstant.DART_PROTO_CLASS |
| 389 : MapConstant.DART_CLASS; | 403 : MapConstant.DART_CLASS; |
| 390 ClassElement classElement = compiler.jsHelperLibrary.find(className); | 404 ClassElement classElement = compiler.jsHelperLibrary.find(className); |
| 391 classElement.ensureResolved(compiler); | 405 classElement.ensureResolved(compiler); |
| 392 // TODO(9476): copy over the generic type. | 406 Link<DartType> typeArgument = sourceType.typeArguments.tail; |
| 393 DartType type = classElement.rawType; | 407 InterfaceType type = new InterfaceType(classElement, typeArgument); |
| 394 handler.registerInstantiatedClass(classElement, elements); | 408 handler.registerInstantiatedType(type, elements); |
| 395 Constant constant = new MapConstant(type, keysList, values, protoValue); | 409 Constant constant = new MapConstant(type, keysList, values, protoValue); |
| 396 handler.registerCompileTimeConstant(constant, elements); | 410 handler.registerCompileTimeConstant(constant, elements); |
| 397 return constant; | 411 return constant; |
| 398 } | 412 } |
| 399 | 413 |
| 400 Constant visitLiteralNull(LiteralNull node) { | 414 Constant visitLiteralNull(LiteralNull node) { |
| 401 return constantSystem.createNull(); | 415 return constantSystem.createNull(); |
| 402 } | 416 } |
| 403 | 417 |
| 404 Constant visitLiteralString(LiteralString node) { | 418 Constant visitLiteralString(LiteralString node) { |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 438 if (partString == null) return null; | 452 if (partString == null) return null; |
| 439 accumulator = new DartString.concat(accumulator, partString.value); | 453 accumulator = new DartString.concat(accumulator, partString.value); |
| 440 }; | 454 }; |
| 441 handler.registerStringInstance(elements); | 455 handler.registerStringInstance(elements); |
| 442 return constantSystem.createString(accumulator, node); | 456 return constantSystem.createString(accumulator, node); |
| 443 } | 457 } |
| 444 | 458 |
| 445 Constant makeTypeConstant(Element element) { | 459 Constant makeTypeConstant(Element element) { |
| 446 DartType elementType = element.computeType(compiler).asRaw(); | 460 DartType elementType = element.computeType(compiler).asRaw(); |
| 447 if (compiler.mirrorsEnabled) { | 461 if (compiler.mirrorsEnabled) { |
| 448 handler.registerInstantiatedClass(element, elements); | 462 handler.registerInstantiatedType(elementType, elements); |
| 449 } | 463 } |
| 450 DartType constantType = | 464 DartType constantType = |
| 451 compiler.backend.typeImplementation.computeType(compiler); | 465 compiler.backend.typeImplementation.computeType(compiler); |
| 452 Constant constant = new TypeConstant(elementType, constantType); | 466 Constant constant = new TypeConstant(elementType, constantType); |
| 453 // If we use a type literal in a constant, the compile time | 467 // If we use a type literal in a constant, the compile time |
| 454 // constant emitter will generate a call to the createRuntimeType | 468 // constant emitter will generate a call to the createRuntimeType |
| 455 // helper so we register a use of that. | 469 // helper so we register a use of that. |
| 456 handler.registerCreateRuntimeTypeFunction(); | 470 handler.registerCreateRuntimeTypeFunction(); |
| 457 handler.registerCompileTimeConstant(constant, elements); | 471 handler.registerCompileTimeConstant(constant, elements); |
| 458 return constant; | 472 return constant; |
| (...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 642 } | 656 } |
| 643 return compiledArguments; | 657 return compiledArguments; |
| 644 } | 658 } |
| 645 | 659 |
| 646 Constant visitNewExpression(NewExpression node) { | 660 Constant visitNewExpression(NewExpression node) { |
| 647 if (!node.isConst()) { | 661 if (!node.isConst()) { |
| 648 return signalNotCompileTimeConstant(node); | 662 return signalNotCompileTimeConstant(node); |
| 649 } | 663 } |
| 650 | 664 |
| 651 Send send = node.send; | 665 Send send = node.send; |
| 652 FunctionElement constructor = elements[send]; | 666 FunctionElement functionElement = elements[send]; |
| 667 FunctionElement constructor = functionElement; | |
|
ngeoffray
2013/06/19 19:55:48
Didn't you say you removed this?
karlklose
2013/06/20 12:49:21
It was needed to preserve the original constructor
| |
| 653 // TODO(ahe): This is nasty: we must eagerly analyze the | 668 // TODO(ahe): This is nasty: we must eagerly analyze the |
| 654 // constructor to ensure the redirectionTarget has been computed | 669 // constructor to ensure the redirectionTarget has been computed |
| 655 // correctly. Find a way to avoid this. | 670 // correctly. Find a way to avoid this. |
| 656 compiler.analyzeElement(constructor.declaration); | 671 compiler.analyzeElement(constructor.declaration); |
| 657 constructor = constructor.redirectionTarget; | 672 constructor = constructor.redirectionTarget; |
| 658 ClassElement classElement = constructor.getEnclosingClass(); | 673 ClassElement classElement = constructor.getEnclosingClass(); |
| 659 // The constructor must be an implementation to ensure that field | 674 // The constructor must be an implementation to ensure that field |
| 660 // initializers are handled correctly. | 675 // initializers are handled correctly. |
| 661 constructor = constructor.implementation; | 676 constructor = constructor.implementation; |
| 662 assert(invariant(node, constructor.isImplementation)); | 677 assert(invariant(node, constructor.isImplementation)); |
| 663 | 678 |
| 664 Selector selector = elements.getSelector(send); | 679 Selector selector = elements.getSelector(send); |
| 665 List<Constant> arguments = evaluateArgumentsToConstructor( | 680 List<Constant> arguments = evaluateArgumentsToConstructor( |
| 666 node, selector, send.arguments, constructor); | 681 node, selector, send.arguments, constructor); |
| 667 ConstructorEvaluator evaluator = | 682 ConstructorEvaluator evaluator = |
| 668 new ConstructorEvaluator(node, constructor, handler, compiler); | 683 new ConstructorEvaluator(node, constructor, handler, compiler); |
| 669 evaluator.evaluateConstructorFieldValues(arguments); | 684 evaluator.evaluateConstructorFieldValues(arguments); |
| 670 List<Constant> jsNewArguments = evaluator.buildJsNewArguments(classElement); | 685 List<Constant> jsNewArguments = evaluator.buildJsNewArguments(classElement); |
| 671 | 686 |
| 672 handler.registerInstantiatedClass(classElement, elements); | 687 InterfaceType type = elements.getType(node); |
| 673 // TODO(9476): take generic types into account. | 688 bool isRedirected = functionElement.isRedirectingFactory; |
| 674 classElement.computeType(compiler); | 689 if (isRedirected) { |
| 675 DartType type = classElement.rawType; | 690 type = functionElement.computeTargetType(compiler, type); |
| 691 } | |
| 692 | |
| 693 handler.registerInstantiatedType(type, elements); | |
| 676 Constant constant = new ConstructedConstant(type, jsNewArguments); | 694 Constant constant = new ConstructedConstant(type, jsNewArguments); |
| 677 handler.registerCompileTimeConstant(constant, elements); | 695 handler.registerCompileTimeConstant(constant, elements); |
| 678 return constant; | 696 return constant; |
| 679 } | 697 } |
| 680 | 698 |
| 681 Constant visitParenthesizedExpression(ParenthesizedExpression node) { | 699 Constant visitParenthesizedExpression(ParenthesizedExpression node) { |
| 682 return node.expression.accept(this); | 700 return node.expression.accept(this); |
| 683 } | 701 } |
| 684 | 702 |
| 685 error(Node node) { | 703 error(Node node) { |
| (...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 890 if (fieldValue == null) { | 908 if (fieldValue == null) { |
| 891 // Use the default value. | 909 // Use the default value. |
| 892 fieldValue = handler.compileConstant(field); | 910 fieldValue = handler.compileConstant(field); |
| 893 } | 911 } |
| 894 jsNewArguments.add(fieldValue); | 912 jsNewArguments.add(fieldValue); |
| 895 }, | 913 }, |
| 896 includeSuperAndInjectedMembers: true); | 914 includeSuperAndInjectedMembers: true); |
| 897 return jsNewArguments; | 915 return jsNewArguments; |
| 898 } | 916 } |
| 899 } | 917 } |
| OLD | NEW |