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 |