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 10 matching lines...) Expand all Loading... | |
21 | 21 |
22 /** Set of all registered compiled constants. */ | 22 /** Set of all registered compiled constants. */ |
23 final Set<Constant> compiledConstants; | 23 final Set<Constant> compiledConstants; |
24 | 24 |
25 /** The set of variable elements that are in the process of being computed. */ | 25 /** The set of variable elements that are in the process of being computed. */ |
26 final Set<VariableElement> pendingVariables; | 26 final Set<VariableElement> pendingVariables; |
27 | 27 |
28 /** Caches the statics where the initial value cannot be eagerly compiled. */ | 28 /** Caches the statics where the initial value cannot be eagerly compiled. */ |
29 final Set<VariableElement> lazyStatics; | 29 final Set<VariableElement> lazyStatics; |
30 | 30 |
31 | |
32 ConstantHandler(Compiler compiler, this.constantSystem) | 31 ConstantHandler(Compiler compiler, this.constantSystem) |
33 : initialVariableValues = new Map<VariableElement, dynamic>(), | 32 : initialVariableValues = new Map<VariableElement, dynamic>(), |
34 compiledConstants = new Set<Constant>(), | 33 compiledConstants = new Set<Constant>(), |
35 pendingVariables = new Set<VariableElement>(), | 34 pendingVariables = new Set<VariableElement>(), |
36 lazyStatics = new Set<VariableElement>(), | 35 lazyStatics = new Set<VariableElement>(), |
37 super(compiler); | 36 super(compiler); |
38 String get name => 'ConstantHandler'; | 37 String get name => 'ConstantHandler'; |
39 | 38 |
40 void registerCompileTimeConstant(Constant constant) { | 39 void registerCompileTimeConstant(Constant constant) { |
41 compiler.enqueuer.codegen.registerInstantiatedClass( | 40 compiler.enqueuer.codegen.registerInstantiatedClass( |
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
241 } | 240 } |
242 return initialValue; | 241 return initialValue; |
243 } | 242 } |
244 } | 243 } |
245 | 244 |
246 class CompileTimeConstantEvaluator extends Visitor { | 245 class CompileTimeConstantEvaluator extends Visitor { |
247 bool isEvaluatingConstant; | 246 bool isEvaluatingConstant; |
248 final ConstantSystem constantSystem; | 247 final ConstantSystem constantSystem; |
249 final TreeElements elements; | 248 final TreeElements elements; |
250 final Compiler compiler; | 249 final Compiler compiler; |
250 bool enabledRuntimeTypeSupport = false; | |
251 | 251 |
252 CompileTimeConstantEvaluator(this.constantSystem, | 252 CompileTimeConstantEvaluator(this.constantSystem, |
253 this.elements, | 253 this.elements, |
254 this.compiler, | 254 this.compiler, |
255 {bool isConst: false}) | 255 {bool isConst: false}) |
256 : this.isEvaluatingConstant = isConst; | 256 : this.isEvaluatingConstant = isConst; |
257 | 257 |
258 Constant evaluate(Node node) { | 258 Constant evaluate(Node node) { |
259 return node.accept(this); | 259 return node.accept(this); |
260 } | 260 } |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
393 } | 393 } |
394 accumulator = new DartString.concat(accumulator, expressionString); | 394 accumulator = new DartString.concat(accumulator, expressionString); |
395 StringConstant partString = evaluate(part.string); | 395 StringConstant partString = evaluate(part.string); |
396 if (partString == null) return null; | 396 if (partString == null) return null; |
397 accumulator = new DartString.concat(accumulator, partString.value); | 397 accumulator = new DartString.concat(accumulator, partString.value); |
398 }; | 398 }; |
399 registerStringInstance(); | 399 registerStringInstance(); |
400 return constantSystem.createString(accumulator, node); | 400 return constantSystem.createString(accumulator, node); |
401 } | 401 } |
402 | 402 |
403 Constant makeTypeConstant(Element element) { | |
404 // If we use a type literal in a constant, the compile time constant | |
405 // emitter will generate a call to the runtime type cache helper, so we | |
406 // resolve it and put it into the codegen work list. | |
407 if (!enabledRuntimeTypeSupport) { | |
ngeoffray
2012/11/19 16:54:09
Instead of having a helper, you can have an implem
karlklose
2012/11/20 14:04:38
As discussed offline, I'll leave that change for n
| |
408 SourceString helperName = const SourceString('createRuntimeType'); | |
409 Element helper = compiler.findHelper(helperName); | |
410 compiler.enqueuer.resolution.addToWorkList(helper); | |
411 compiler.enqueuer.codegen.addToWorkList(helper); | |
412 enabledRuntimeTypeSupport = true; | |
413 } | |
414 | |
415 DartType elementType = element.computeType(compiler).asRaw(); | |
416 DartType constantType = compiler.typeClass.computeType(compiler); | |
417 Constant constant = new TypeConstant(elementType, constantType); | |
418 compiler.constantHandler.registerCompileTimeConstant(constant); | |
419 return constant; | |
420 } | |
421 | |
403 // TODO(floitsch): provide better error-messages. | 422 // TODO(floitsch): provide better error-messages. |
404 Constant visitSend(Send send) { | 423 Constant visitSend(Send send) { |
405 Element element = elements[send]; | 424 Element element = elements[send]; |
406 if (send.isPropertyAccess) { | 425 if (send.isPropertyAccess) { |
407 if (Elements.isStaticOrTopLevelFunction(element)) { | 426 if (Elements.isStaticOrTopLevelFunction(element)) { |
408 compiler.codegenWorld.staticFunctionsNeedingGetter.add(element); | 427 compiler.codegenWorld.staticFunctionsNeedingGetter.add(element); |
409 Constant constant = new FunctionConstant(element); | 428 Constant constant = new FunctionConstant(element); |
410 compiler.constantHandler.registerCompileTimeConstant(constant); | 429 compiler.constantHandler.registerCompileTimeConstant(constant); |
411 compiler.enqueuer.codegen.registerStaticUse(element); | 430 compiler.enqueuer.codegen.registerStaticUse(element); |
412 return constant; | 431 return constant; |
413 } else if (Elements.isStaticOrTopLevelField(element)) { | 432 } else if (Elements.isStaticOrTopLevelField(element)) { |
414 Constant result; | 433 Constant result; |
415 if (element.modifiers.isConst()) { | 434 if (element.modifiers.isConst()) { |
416 result = compiler.compileConstant(element); | 435 result = compiler.compileConstant(element); |
417 } else if (element.modifiers.isFinal() && !isEvaluatingConstant) { | 436 } else if (element.modifiers.isFinal() && !isEvaluatingConstant) { |
418 result = compiler.compileVariable(element); | 437 result = compiler.compileVariable(element); |
419 } | 438 } |
420 if (result != null) return result; | 439 if (result != null) return result; |
440 } else if (Elements.isClass(element) || Elements.isTypedef(element)) { | |
ngeoffray
2012/11/19 16:54:09
Could you use element.impliesType instead?
karlklose
2012/11/20 14:04:38
That is not the same because type variables imply
| |
441 return makeTypeConstant(element); | |
421 } | 442 } |
422 return signalNotCompileTimeConstant(send); | 443 return signalNotCompileTimeConstant(send); |
423 } else if (send.isCall) { | 444 } else if (send.isCall) { |
424 if (identical(element, compiler.identicalFunction) | 445 if (identical(element, compiler.identicalFunction) |
425 && send.argumentCount() == 2) { | 446 && send.argumentCount() == 2) { |
426 Constant left = evaluate(send.argumentsNode.nodes.head); | 447 Constant left = evaluate(send.argumentsNode.nodes.head); |
427 Constant right = evaluate(send.argumentsNode.nodes.tail.head); | 448 Constant right = evaluate(send.argumentsNode.nodes.tail.head); |
428 Constant result = constantSystem.identity.fold(left, right); | 449 Constant result = constantSystem.identity.fold(left, right); |
429 if (result != null) return result; | 450 if (result != null) return result; |
451 } else if (Elements.isClass(element) || Elements.isTypedef(element)) { | |
ngeoffray
2012/11/19 16:54:09
ditto
karlklose
2012/11/20 14:04:38
ditto
| |
452 return makeTypeConstant(element); | |
430 } | 453 } |
431 return signalNotCompileTimeConstant(send); | 454 return signalNotCompileTimeConstant(send); |
432 } else if (send.isPrefix) { | 455 } else if (send.isPrefix) { |
433 assert(send.isOperator); | 456 assert(send.isOperator); |
434 Constant receiverConstant = evaluate(send.receiver); | 457 Constant receiverConstant = evaluate(send.receiver); |
435 if (receiverConstant == null) return null; | 458 if (receiverConstant == null) return null; |
436 Operator op = send.selector; | 459 Operator op = send.selector; |
437 Constant folded; | 460 Constant folded; |
438 switch (op.source.stringValue) { | 461 switch (op.source.stringValue) { |
439 case "!": | 462 case "!": |
(...skipping 383 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
823 // Use the default value. | 846 // Use the default value. |
824 fieldValue = compiler.compileConstant(field); | 847 fieldValue = compiler.compileConstant(field); |
825 } | 848 } |
826 jsNewArguments.add(fieldValue); | 849 jsNewArguments.add(fieldValue); |
827 }, | 850 }, |
828 includeBackendMembers: true, | 851 includeBackendMembers: true, |
829 includeSuperMembers: true); | 852 includeSuperMembers: true); |
830 return jsNewArguments; | 853 return jsNewArguments; |
831 } | 854 } |
832 } | 855 } |
OLD | NEW |