| 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 24 matching lines...) Expand all Loading... |
| 35 ConstantHandler(Compiler compiler, this.constantSystem, | 35 ConstantHandler(Compiler compiler, this.constantSystem, |
| 36 { bool this.isMetadata: false }) | 36 { bool this.isMetadata: false }) |
| 37 : initialVariableValues = new Map<VariableElement, dynamic>(), | 37 : initialVariableValues = new Map<VariableElement, dynamic>(), |
| 38 compiledConstants = new Set<Constant>(), | 38 compiledConstants = new Set<Constant>(), |
| 39 pendingVariables = new Set<VariableElement>(), | 39 pendingVariables = new Set<VariableElement>(), |
| 40 lazyStatics = new Set<VariableElement>(), | 40 lazyStatics = new Set<VariableElement>(), |
| 41 super(compiler); | 41 super(compiler); |
| 42 | 42 |
| 43 String get name => 'ConstantHandler'; | 43 String get name => 'ConstantHandler'; |
| 44 | 44 |
| 45 void registerCompileTimeConstant(Constant constant) { | 45 void registerCompileTimeConstant(Constant constant, TreeElements elements) { |
| 46 registerInstantiatedClass(constant.computeType(compiler).element); | 46 registerInstantiatedClass(constant.computeType(compiler).element, elements); |
| 47 if (constant.isFunction()) { | 47 if (constant.isFunction()) { |
| 48 FunctionConstant function = constant; | 48 FunctionConstant function = constant; |
| 49 registerGetOfStaticFunction(function.element); | 49 registerGetOfStaticFunction(function.element); |
| 50 } else if (constant.isInterceptor()) { | 50 } else if (constant.isInterceptor()) { |
| 51 // An interceptor constant references the class's prototype chain. | 51 // An interceptor constant references the class's prototype chain. |
| 52 InterceptorConstant interceptor = constant; | 52 InterceptorConstant interceptor = constant; |
| 53 registerInstantiatedClass(interceptor.dispatchedType.element); | 53 registerInstantiatedClass(interceptor.dispatchedType.element, elements); |
| 54 } | 54 } |
| 55 compiledConstants.add(constant); | 55 compiledConstants.add(constant); |
| 56 } | 56 } |
| 57 | 57 |
| 58 void registerInstantiatedClass(ClassElement element) { | 58 void registerInstantiatedClass(ClassElement element, TreeElements elements) { |
| 59 if (isMetadata) return; | 59 if (isMetadata) return; |
| 60 compiler.enqueuer.codegen.registerInstantiatedClass(element); | 60 compiler.enqueuer.codegen.registerInstantiatedClass(element, elements); |
| 61 } | 61 } |
| 62 | 62 |
| 63 void registerStaticUse(Element element) { | 63 void registerStaticUse(Element element) { |
| 64 if (isMetadata) return; | 64 if (isMetadata) return; |
| 65 compiler.enqueuer.codegen.registerStaticUse(element); | 65 compiler.enqueuer.codegen.registerStaticUse(element); |
| 66 } | 66 } |
| 67 | 67 |
| 68 void registerGetOfStaticFunction(FunctionElement element) { | 68 void registerGetOfStaticFunction(FunctionElement element) { |
| 69 if (isMetadata) return; | 69 if (isMetadata) return; |
| 70 compiler.enqueuer.codegen.registerGetOfStaticFunction(element); | 70 compiler.enqueuer.codegen.registerGetOfStaticFunction(element); |
| 71 } | 71 } |
| 72 | 72 |
| 73 void registerStringInstance() { | 73 void registerStringInstance(TreeElements elements) { |
| 74 registerInstantiatedClass(compiler.stringClass); | 74 registerInstantiatedClass(compiler.stringClass, elements); |
| 75 } | 75 } |
| 76 | 76 |
| 77 void registerCreateRuntimeTypeFunction() { | 77 void registerCreateRuntimeTypeFunction() { |
| 78 if (createRuntimeTypeFunction != null) return; | 78 if (createRuntimeTypeFunction != null) return; |
| 79 SourceString helperName = const SourceString('createRuntimeType'); | 79 SourceString helperName = const SourceString('createRuntimeType'); |
| 80 createRuntimeTypeFunction = compiler.findHelper(helperName); | 80 createRuntimeTypeFunction = compiler.findHelper(helperName); |
| 81 registerStaticUse(createRuntimeTypeFunction); | 81 registerStaticUse(createRuntimeTypeFunction); |
| 82 } | 82 } |
| 83 | 83 |
| 84 /** | 84 /** |
| (...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 309 isEvaluatingConstant = oldIsEvaluatingConstant; | 309 isEvaluatingConstant = oldIsEvaluatingConstant; |
| 310 assert(result != null); | 310 assert(result != null); |
| 311 return result; | 311 return result; |
| 312 } | 312 } |
| 313 | 313 |
| 314 Constant visitNode(Node node) { | 314 Constant visitNode(Node node) { |
| 315 return signalNotCompileTimeConstant(node); | 315 return signalNotCompileTimeConstant(node); |
| 316 } | 316 } |
| 317 | 317 |
| 318 Constant visitLiteralBool(LiteralBool node) { | 318 Constant visitLiteralBool(LiteralBool node) { |
| 319 handler.registerInstantiatedClass(compiler.boolClass); | 319 handler.registerInstantiatedClass(compiler.boolClass, elements); |
| 320 return constantSystem.createBool(node.value); | 320 return constantSystem.createBool(node.value); |
| 321 } | 321 } |
| 322 | 322 |
| 323 Constant visitLiteralDouble(LiteralDouble node) { | 323 Constant visitLiteralDouble(LiteralDouble node) { |
| 324 handler.registerInstantiatedClass(compiler.doubleClass); | 324 handler.registerInstantiatedClass(compiler.doubleClass, elements); |
| 325 return constantSystem.createDouble(node.value); | 325 return constantSystem.createDouble(node.value); |
| 326 } | 326 } |
| 327 | 327 |
| 328 Constant visitLiteralInt(LiteralInt node) { | 328 Constant visitLiteralInt(LiteralInt node) { |
| 329 handler.registerInstantiatedClass(compiler.intClass); | 329 handler.registerInstantiatedClass(compiler.intClass, elements); |
| 330 return constantSystem.createInt(node.value); | 330 return constantSystem.createInt(node.value); |
| 331 } | 331 } |
| 332 | 332 |
| 333 Constant visitLiteralList(LiteralList node) { | 333 Constant visitLiteralList(LiteralList node) { |
| 334 if (!node.isConst()) { | 334 if (!node.isConst()) { |
| 335 return signalNotCompileTimeConstant(node); | 335 return signalNotCompileTimeConstant(node); |
| 336 } | 336 } |
| 337 List<Constant> arguments = <Constant>[]; | 337 List<Constant> arguments = <Constant>[]; |
| 338 for (Link<Node> link = node.elements.nodes; | 338 for (Link<Node> link = node.elements.nodes; |
| 339 !link.isEmpty; | 339 !link.isEmpty; |
| 340 link = link.tail) { | 340 link = link.tail) { |
| 341 arguments.add(evaluateConstant(link.head)); | 341 arguments.add(evaluateConstant(link.head)); |
| 342 } | 342 } |
| 343 // TODO(floitsch): get type parameters. | 343 // TODO(floitsch): get type parameters. |
| 344 compiler.listClass.computeType(compiler); | 344 compiler.listClass.computeType(compiler); |
| 345 DartType type = compiler.listClass.rawType; | 345 DartType type = compiler.listClass.rawType; |
| 346 Constant constant = new ListConstant(type, arguments); | 346 Constant constant = new ListConstant(type, arguments); |
| 347 handler.registerCompileTimeConstant(constant); | 347 handler.registerCompileTimeConstant(constant, elements); |
| 348 return constant; | 348 return constant; |
| 349 } | 349 } |
| 350 | 350 |
| 351 Constant visitLiteralMap(LiteralMap node) { | 351 Constant visitLiteralMap(LiteralMap node) { |
| 352 if (!node.isConst()) { | 352 if (!node.isConst()) { |
| 353 return signalNotCompileTimeConstant(node); | 353 return signalNotCompileTimeConstant(node); |
| 354 } | 354 } |
| 355 List<StringConstant> keys = <StringConstant>[]; | 355 List<StringConstant> keys = <StringConstant>[]; |
| 356 Map<StringConstant, Constant> map = new Map<StringConstant, Constant>(); | 356 Map<StringConstant, Constant> map = new Map<StringConstant, Constant>(); |
| 357 for (Link<Node> link = node.entries.nodes; | 357 for (Link<Node> link = node.entries.nodes; |
| (...skipping 16 matching lines...) Expand all Loading... |
| 374 protoValue = map[key]; | 374 protoValue = map[key]; |
| 375 } else { | 375 } else { |
| 376 values.add(map[key]); | 376 values.add(map[key]); |
| 377 } | 377 } |
| 378 } | 378 } |
| 379 bool hasProtoKey = (protoValue != null); | 379 bool hasProtoKey = (protoValue != null); |
| 380 // TODO(floitsch): this should be a List<String> type. | 380 // TODO(floitsch): this should be a List<String> type. |
| 381 compiler.listClass.computeType(compiler); | 381 compiler.listClass.computeType(compiler); |
| 382 DartType keysType = compiler.listClass.rawType; | 382 DartType keysType = compiler.listClass.rawType; |
| 383 ListConstant keysList = new ListConstant(keysType, keys); | 383 ListConstant keysList = new ListConstant(keysType, keys); |
| 384 handler.registerCompileTimeConstant(keysList); | 384 handler.registerCompileTimeConstant(keysList, elements); |
| 385 SourceString className = hasProtoKey | 385 SourceString className = hasProtoKey |
| 386 ? MapConstant.DART_PROTO_CLASS | 386 ? MapConstant.DART_PROTO_CLASS |
| 387 : MapConstant.DART_CLASS; | 387 : MapConstant.DART_CLASS; |
| 388 ClassElement classElement = compiler.jsHelperLibrary.find(className); | 388 ClassElement classElement = compiler.jsHelperLibrary.find(className); |
| 389 classElement.ensureResolved(compiler); | 389 classElement.ensureResolved(compiler); |
| 390 // TODO(floitsch): copy over the generic type. | 390 // TODO(floitsch): copy over the generic type. |
| 391 DartType type = classElement.rawType; | 391 DartType type = classElement.rawType; |
| 392 handler.registerInstantiatedClass(classElement); | 392 handler.registerInstantiatedClass(classElement, elements); |
| 393 Constant constant = new MapConstant(type, keysList, values, protoValue); | 393 Constant constant = new MapConstant(type, keysList, values, protoValue); |
| 394 handler.registerCompileTimeConstant(constant); | 394 handler.registerCompileTimeConstant(constant, elements); |
| 395 return constant; | 395 return constant; |
| 396 } | 396 } |
| 397 | 397 |
| 398 Constant visitLiteralNull(LiteralNull node) { | 398 Constant visitLiteralNull(LiteralNull node) { |
| 399 return constantSystem.createNull(); | 399 return constantSystem.createNull(); |
| 400 } | 400 } |
| 401 | 401 |
| 402 Constant visitLiteralString(LiteralString node) { | 402 Constant visitLiteralString(LiteralString node) { |
| 403 handler.registerStringInstance(); | 403 handler.registerStringInstance(elements); |
| 404 return constantSystem.createString(node.dartString, node); | 404 return constantSystem.createString(node.dartString, node); |
| 405 } | 405 } |
| 406 | 406 |
| 407 Constant visitStringJuxtaposition(StringJuxtaposition node) { | 407 Constant visitStringJuxtaposition(StringJuxtaposition node) { |
| 408 StringConstant left = evaluate(node.first); | 408 StringConstant left = evaluate(node.first); |
| 409 StringConstant right = evaluate(node.second); | 409 StringConstant right = evaluate(node.second); |
| 410 if (left == null || right == null) return null; | 410 if (left == null || right == null) return null; |
| 411 handler.registerStringInstance(); | 411 handler.registerStringInstance(elements); |
| 412 return constantSystem.createString( | 412 return constantSystem.createString( |
| 413 new DartString.concat(left.value, right.value), node); | 413 new DartString.concat(left.value, right.value), node); |
| 414 } | 414 } |
| 415 | 415 |
| 416 Constant visitStringInterpolation(StringInterpolation node) { | 416 Constant visitStringInterpolation(StringInterpolation node) { |
| 417 StringConstant initialString = evaluate(node.string); | 417 StringConstant initialString = evaluate(node.string); |
| 418 if (initialString == null) return null; | 418 if (initialString == null) return null; |
| 419 DartString accumulator = initialString.value; | 419 DartString accumulator = initialString.value; |
| 420 for (StringInterpolationPart part in node.parts) { | 420 for (StringInterpolationPart part in node.parts) { |
| 421 Constant expression = evaluate(part.expression); | 421 Constant expression = evaluate(part.expression); |
| 422 DartString expressionString; | 422 DartString expressionString; |
| 423 if (expression == null) { | 423 if (expression == null) { |
| 424 return signalNotCompileTimeConstant(part.expression); | 424 return signalNotCompileTimeConstant(part.expression); |
| 425 } else if (expression.isNum() || expression.isBool()) { | 425 } else if (expression.isNum() || expression.isBool()) { |
| 426 PrimitiveConstant primitive = expression; | 426 PrimitiveConstant primitive = expression; |
| 427 expressionString = new DartString.literal(primitive.value.toString()); | 427 expressionString = new DartString.literal(primitive.value.toString()); |
| 428 } else if (expression.isString()) { | 428 } else if (expression.isString()) { |
| 429 PrimitiveConstant primitive = expression; | 429 PrimitiveConstant primitive = expression; |
| 430 expressionString = primitive.value; | 430 expressionString = primitive.value; |
| 431 } else { | 431 } else { |
| 432 return signalNotCompileTimeConstant(part.expression); | 432 return signalNotCompileTimeConstant(part.expression); |
| 433 } | 433 } |
| 434 accumulator = new DartString.concat(accumulator, expressionString); | 434 accumulator = new DartString.concat(accumulator, expressionString); |
| 435 StringConstant partString = evaluate(part.string); | 435 StringConstant partString = evaluate(part.string); |
| 436 if (partString == null) return null; | 436 if (partString == null) return null; |
| 437 accumulator = new DartString.concat(accumulator, partString.value); | 437 accumulator = new DartString.concat(accumulator, partString.value); |
| 438 }; | 438 }; |
| 439 handler.registerStringInstance(); | 439 handler.registerStringInstance(elements); |
| 440 return constantSystem.createString(accumulator, node); | 440 return constantSystem.createString(accumulator, node); |
| 441 } | 441 } |
| 442 | 442 |
| 443 Constant makeTypeConstant(Element element) { | 443 Constant makeTypeConstant(Element element) { |
| 444 DartType elementType = element.computeType(compiler).asRaw(); | 444 DartType elementType = element.computeType(compiler).asRaw(); |
| 445 DartType constantType = compiler.typeClass.computeType(compiler); | 445 DartType constantType = compiler.typeClass.computeType(compiler); |
| 446 Constant constant = new TypeConstant(elementType, constantType); | 446 Constant constant = new TypeConstant(elementType, constantType); |
| 447 // If we use a type literal in a constant, the compile time | 447 // If we use a type literal in a constant, the compile time |
| 448 // constant emitter will generate a call to the createRuntimeType | 448 // constant emitter will generate a call to the createRuntimeType |
| 449 // helper so we register a use of that. | 449 // helper so we register a use of that. |
| 450 handler.registerCreateRuntimeTypeFunction(); | 450 handler.registerCreateRuntimeTypeFunction(); |
| 451 handler.registerCompileTimeConstant(constant); | 451 handler.registerCompileTimeConstant(constant, elements); |
| 452 return constant; | 452 return constant; |
| 453 } | 453 } |
| 454 | 454 |
| 455 // TODO(floitsch): provide better error-messages. | 455 // TODO(floitsch): provide better error-messages. |
| 456 Constant visitSend(Send send) { | 456 Constant visitSend(Send send) { |
| 457 Element element = elements[send]; | 457 Element element = elements[send]; |
| 458 if (send.isPropertyAccess) { | 458 if (send.isPropertyAccess) { |
| 459 if (Elements.isStaticOrTopLevelFunction(element)) { | 459 if (Elements.isStaticOrTopLevelFunction(element)) { |
| 460 Constant constant = new FunctionConstant(element); | 460 Constant constant = new FunctionConstant(element); |
| 461 handler.registerCompileTimeConstant(constant); | 461 handler.registerCompileTimeConstant(constant, elements); |
| 462 return constant; | 462 return constant; |
| 463 } else if (Elements.isStaticOrTopLevelField(element)) { | 463 } else if (Elements.isStaticOrTopLevelField(element)) { |
| 464 Constant result; | 464 Constant result; |
| 465 if (element.modifiers.isConst()) { | 465 if (element.modifiers.isConst()) { |
| 466 result = handler.compileConstant(element); | 466 result = handler.compileConstant(element); |
| 467 } else if (element.modifiers.isFinal() && !isEvaluatingConstant) { | 467 } else if (element.modifiers.isFinal() && !isEvaluatingConstant) { |
| 468 result = handler.compileVariable(element); | 468 result = handler.compileVariable(element); |
| 469 } | 469 } |
| 470 if (result != null) return result; | 470 if (result != null) return result; |
| 471 } else if (Elements.isClass(element) || Elements.isTypedef(element)) { | 471 } else if (Elements.isClass(element) || Elements.isTypedef(element)) { |
| (...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 657 assert(invariant(node, constructor.isImplementation)); | 657 assert(invariant(node, constructor.isImplementation)); |
| 658 | 658 |
| 659 Selector selector = elements.getSelector(send); | 659 Selector selector = elements.getSelector(send); |
| 660 List<Constant> arguments = evaluateArgumentsToConstructor( | 660 List<Constant> arguments = evaluateArgumentsToConstructor( |
| 661 node, selector, send.arguments, constructor); | 661 node, selector, send.arguments, constructor); |
| 662 ConstructorEvaluator evaluator = | 662 ConstructorEvaluator evaluator = |
| 663 new ConstructorEvaluator(node, constructor, handler, compiler); | 663 new ConstructorEvaluator(node, constructor, handler, compiler); |
| 664 evaluator.evaluateConstructorFieldValues(arguments); | 664 evaluator.evaluateConstructorFieldValues(arguments); |
| 665 List<Constant> jsNewArguments = evaluator.buildJsNewArguments(classElement); | 665 List<Constant> jsNewArguments = evaluator.buildJsNewArguments(classElement); |
| 666 | 666 |
| 667 handler.registerInstantiatedClass(classElement); | 667 handler.registerInstantiatedClass(classElement, elements); |
| 668 // TODO(floitsch): take generic types into account. | 668 // TODO(floitsch): take generic types into account. |
| 669 classElement.computeType(compiler); | 669 classElement.computeType(compiler); |
| 670 DartType type = classElement.rawType; | 670 DartType type = classElement.rawType; |
| 671 Constant constant = new ConstructedConstant(type, jsNewArguments); | 671 Constant constant = new ConstructedConstant(type, jsNewArguments); |
| 672 handler.registerCompileTimeConstant(constant); | 672 handler.registerCompileTimeConstant(constant, elements); |
| 673 return constant; | 673 return constant; |
| 674 } | 674 } |
| 675 | 675 |
| 676 Constant visitParenthesizedExpression(ParenthesizedExpression node) { | 676 Constant visitParenthesizedExpression(ParenthesizedExpression node) { |
| 677 return node.expression.accept(this); | 677 return node.expression.accept(this); |
| 678 } | 678 } |
| 679 | 679 |
| 680 error(Node node) { | 680 error(Node node) { |
| 681 // TODO(floitsch): get the list of constants that are currently compiled | 681 // TODO(floitsch): get the list of constants that are currently compiled |
| 682 // and present some kind of stack-trace. | 682 // and present some kind of stack-trace. |
| (...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 886 // Use the default value. | 886 // Use the default value. |
| 887 fieldValue = handler.compileConstant(field); | 887 fieldValue = handler.compileConstant(field); |
| 888 } | 888 } |
| 889 jsNewArguments.add(fieldValue); | 889 jsNewArguments.add(fieldValue); |
| 890 }, | 890 }, |
| 891 includeBackendMembers: true, | 891 includeBackendMembers: true, |
| 892 includeSuperMembers: true); | 892 includeSuperMembers: true); |
| 893 return jsNewArguments; | 893 return jsNewArguments; |
| 894 } | 894 } |
| 895 } | 895 } |
| OLD | NEW |