Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(11)

Side by Side Diff: sdk/lib/_internal/compiler/implementation/compile_time_constants.dart

Issue 24282005: Move compile-time constant registrations to the backend. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Update status Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | sdk/lib/_internal/compiler/implementation/compiler.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 11 matching lines...) Expand all
22 22
23 /** Set of all registered compiled constants. */ 23 /** Set of all registered compiled constants. */
24 final Set<Constant> compiledConstants; 24 final Set<Constant> compiledConstants;
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. */
33 Element createRuntimeTypeFunction = null;
34
35 /** Caches the setRuntimeTypeInfo function if registered. */
36 Element setRuntimeTypeInfoFunction = null;
37
38 ConstantHandler(Compiler compiler, this.constantSystem, 32 ConstantHandler(Compiler compiler, this.constantSystem,
39 { bool this.isMetadata: false }) 33 { bool this.isMetadata: false })
40 : initialVariableValues = new Map<VariableElement, dynamic>(), 34 : initialVariableValues = new Map<VariableElement, dynamic>(),
41 compiledConstants = new Set<Constant>(), 35 compiledConstants = new Set<Constant>(),
42 pendingVariables = new Set<VariableElement>(), 36 pendingVariables = new Set<VariableElement>(),
43 lazyStatics = new Set<VariableElement>(), 37 lazyStatics = new Set<VariableElement>(),
44 super(compiler); 38 super(compiler);
45 39
46 String get name => 'ConstantHandler'; 40 String get name => 'ConstantHandler';
47 41
48 void registerCompileTimeConstant(Constant constant, TreeElements elements) { 42 void addCompileTimeConstantForEmission(Constant constant) {
49 registerInstantiatedType(constant.computeType(compiler), elements);
50 if (constant.isFunction()) {
51 FunctionConstant function = constant;
52 registerGetOfStaticFunction(function.element);
53 } else if (constant.isInterceptor()) {
54 // An interceptor constant references the class's prototype chain.
55 InterceptorConstant interceptor = constant;
56 registerInstantiatedType(interceptor.dispatchedType, elements);
57 }
58 compiledConstants.add(constant); 43 compiledConstants.add(constant);
59 } 44 }
60 45
61 void registerInstantiatedType(DartType type, TreeElements elements) { 46 Constant getConstantForVariable(VariableElement element) {
62 if (isMetadata) { 47 return initialVariableValues[element];
63 compiler.backend.registerMetadataInstantiatedType(type, elements);
64 return;
65 }
66 compiler.enqueuer.codegen.registerInstantiatedType(type, elements);
67 if (type is InterfaceType &&
68 !type.treatAsRaw &&
69 compiler.backend.classNeedsRti(type.element)) {
70 registerSetRuntimeTypeInfoFunction();
71 }
72 }
73
74 void registerStaticUse(Element element) {
75 if (isMetadata) {
76 compiler.backend.registerMetadataStaticUse(element);
77 return;
78 }
79 compiler.analyzeElement(element.declaration);
80 compiler.enqueuer.codegen.registerStaticUse(element);
81 }
82
83 void registerGetOfStaticFunction(FunctionElement element) {
84 if (isMetadata) {
85 compiler.backend.registerMetadataGetOfStaticFunction(element);
86 return;
87 }
88 compiler.analyzeElement(element.declaration);
89 compiler.enqueuer.codegen.registerGetOfStaticFunction(element);
90 }
91
92 void registerStringInstance(TreeElements elements) {
93 registerInstantiatedType(compiler.stringClass.rawType, elements);
94 }
95
96 void registerSetRuntimeTypeInfoFunction() {
97 if (setRuntimeTypeInfoFunction != null) return;
98 SourceString helperName = const SourceString('setRuntimeTypeInfo');
99 setRuntimeTypeInfoFunction = compiler.findHelper(helperName);
100 registerStaticUse(setRuntimeTypeInfoFunction);
101 }
102
103 void registerCreateRuntimeTypeFunction() {
104 if (createRuntimeTypeFunction != null) return;
105 SourceString helperName = const SourceString('createRuntimeType');
106 createRuntimeTypeFunction = compiler.findHelper(helperName);
107 registerStaticUse(createRuntimeTypeFunction);
108 } 48 }
109 49
110 /** 50 /**
111 * Compiles the initial value of the given field and stores it in an internal
112 * map. Returns the initial value (a constant) if it can be computed
113 * statically. Returns [:null:] if the variable must be initialized lazily.
114 *
115 * [work] must contain a [VariableElement] refering to a global or
116 * static field.
117 */
118 Constant compileWorkItem(CodegenWorkItem work) {
119 return measure(() {
120 assert(work.element.kind == ElementKind.FIELD
121 || work.element.kind == ElementKind.PARAMETER
122 || work.element.kind == ElementKind.FIELD_PARAMETER);
123 VariableElement element = work.element;
124 // Shortcut if it has already been compiled.
125 Constant result = initialVariableValues[element];
126 if (result != null) return result;
127 if (lazyStatics.contains(element)) return null;
128 result = compileVariableWithDefinitions(element, work.resolutionTree);
129 assert(pendingVariables.isEmpty);
130 return result;
131 });
132 }
133
134 /**
135 * Returns a compile-time constant, or reports an error if the element is not 51 * Returns a compile-time constant, or reports an error if the element is not
136 * a compile-time constant. 52 * a compile-time constant.
137 */ 53 */
138 Constant compileConstant(VariableElement element) { 54 Constant compileConstant(VariableElement element) {
139 return compileVariable(element, isConst: true); 55 return compileVariable(element, isConst: true);
140 } 56 }
141 57
142 /** 58 /**
143 * Returns the a compile-time constant if the variable could be compiled 59 * Returns the a compile-time constant if the variable could be compiled
144 * eagerly. Otherwise returns `null`. 60 * eagerly. Otherwise returns `null`.
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
234 TreeElements definitions, 150 TreeElements definitions,
235 {bool isConst: false}) { 151 {bool isConst: false}) {
236 return measure(() { 152 return measure(() {
237 assert(node != null); 153 assert(node != null);
238 CompileTimeConstantEvaluator evaluator = new CompileTimeConstantEvaluator( 154 CompileTimeConstantEvaluator evaluator = new CompileTimeConstantEvaluator(
239 this, definitions, compiler, isConst: isConst); 155 this, definitions, compiler, isConst: isConst);
240 return evaluator.evaluate(node); 156 return evaluator.evaluate(node);
241 }); 157 });
242 } 158 }
243 159
244 /** Attempts to compile a constant expression. Returns null if not possible */
245 Constant tryCompileNodeWithDefinitions(Node node, TreeElements definitions) {
246 return measure(() {
247 assert(node != null);
248 try {
249 TryCompileTimeConstantEvaluator evaluator =
250 new TryCompileTimeConstantEvaluator(this, definitions, compiler);
251 return evaluator.evaluate(node);
252 } on CompileTimeConstantError catch (exn) {
253 return null;
254 }
255 });
256 }
257
258 /** 160 /**
259 * Returns an [Iterable] of static non final fields that need to be 161 * Returns an [Iterable] of static non final fields that need to be
260 * initialized. The fields list must be evaluated in order since they might 162 * initialized. The fields list must be evaluated in order since they might
261 * depend on each other. 163 * depend on each other.
262 */ 164 */
263 Iterable<VariableElement> getStaticNonFinalFieldsForEmission() { 165 Iterable<VariableElement> getStaticNonFinalFieldsForEmission() {
264 return initialVariableValues.keys.where((element) { 166 return initialVariableValues.keys.where((element) {
265 return element.kind == ElementKind.FIELD 167 return element.kind == ElementKind.FIELD
266 && !element.isInstanceMember() 168 && !element.isInstanceMember()
267 && !element.modifiers.isFinal() 169 && !element.modifiers.isFinal()
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
351 isEvaluatingConstant = oldIsEvaluatingConstant; 253 isEvaluatingConstant = oldIsEvaluatingConstant;
352 assert(result != null); 254 assert(result != null);
353 return result; 255 return result;
354 } 256 }
355 257
356 Constant visitNode(Node node) { 258 Constant visitNode(Node node) {
357 return signalNotCompileTimeConstant(node); 259 return signalNotCompileTimeConstant(node);
358 } 260 }
359 261
360 Constant visitLiteralBool(LiteralBool node) { 262 Constant visitLiteralBool(LiteralBool node) {
361 handler.registerInstantiatedType(compiler.boolClass.rawType, elements);
362 return constantSystem.createBool(node.value); 263 return constantSystem.createBool(node.value);
363 } 264 }
364 265
365 Constant visitLiteralDouble(LiteralDouble node) { 266 Constant visitLiteralDouble(LiteralDouble node) {
366 handler.registerInstantiatedType(compiler.doubleClass.rawType, elements);
367 return constantSystem.createDouble(node.value); 267 return constantSystem.createDouble(node.value);
368 } 268 }
369 269
370 Constant visitLiteralInt(LiteralInt node) { 270 Constant visitLiteralInt(LiteralInt node) {
371 handler.registerInstantiatedType(compiler.intClass.rawType, elements);
372 return constantSystem.createInt(node.value); 271 return constantSystem.createInt(node.value);
373 } 272 }
374 273
375 Constant visitLiteralList(LiteralList node) { 274 Constant visitLiteralList(LiteralList node) {
376 if (!node.isConst()) { 275 if (!node.isConst()) {
377 return signalNotCompileTimeConstant(node); 276 return signalNotCompileTimeConstant(node);
378 } 277 }
379 List<Constant> arguments = <Constant>[]; 278 List<Constant> arguments = <Constant>[];
380 for (Link<Node> link = node.elements.nodes; 279 for (Link<Node> link = node.elements.nodes;
381 !link.isEmpty; 280 !link.isEmpty;
382 link = link.tail) { 281 link = link.tail) {
383 arguments.add(evaluateConstant(link.head)); 282 arguments.add(evaluateConstant(link.head));
384 } 283 }
385 DartType type = elements.getType(node); 284 DartType type = elements.getType(node);
386 handler.registerInstantiatedType(type, elements); 285 return new ListConstant(type, arguments);
387 Constant constant = new ListConstant(type, arguments);
388 handler.registerCompileTimeConstant(constant, elements);
389 return constant;
390 } 286 }
391 287
392 Constant visitLiteralMap(LiteralMap node) { 288 Constant visitLiteralMap(LiteralMap node) {
393 if (!node.isConst()) { 289 if (!node.isConst()) {
394 return signalNotCompileTimeConstant(node); 290 return signalNotCompileTimeConstant(node);
395 } 291 }
396 List<Constant> keys = <Constant>[]; 292 List<Constant> keys = <Constant>[];
397 Map<Constant, Constant> map = new Map<Constant, Constant>(); 293 Map<Constant, Constant> map = new Map<Constant, Constant>();
398 for (Link<Node> link = node.entries.nodes; 294 for (Link<Node> link = node.entries.nodes;
399 !link.isEmpty; 295 !link.isEmpty;
(...skipping 24 matching lines...) Expand all
424 InterfaceType sourceType = elements.getType(node); 320 InterfaceType sourceType = elements.getType(node);
425 DartType keysType; 321 DartType keysType;
426 if (sourceType.treatAsRaw) { 322 if (sourceType.treatAsRaw) {
427 keysType = compiler.listClass.rawType; 323 keysType = compiler.listClass.rawType;
428 } else { 324 } else {
429 Link<DartType> arguments = 325 Link<DartType> arguments =
430 new Link<DartType>.fromList([sourceType.typeArguments.head]); 326 new Link<DartType>.fromList([sourceType.typeArguments.head]);
431 keysType = new InterfaceType(compiler.listClass, arguments); 327 keysType = new InterfaceType(compiler.listClass, arguments);
432 } 328 }
433 ListConstant keysList = new ListConstant(keysType, keys); 329 ListConstant keysList = new ListConstant(keysType, keys);
434 if (onlyStringKeys) {
435 handler.registerCompileTimeConstant(keysList, elements);
436 }
437 SourceString className = onlyStringKeys 330 SourceString className = onlyStringKeys
438 ? (hasProtoKey ? MapConstant.DART_PROTO_CLASS 331 ? (hasProtoKey ? MapConstant.DART_PROTO_CLASS
439 : MapConstant.DART_STRING_CLASS) 332 : MapConstant.DART_STRING_CLASS)
440 : MapConstant.DART_GENERAL_CLASS; 333 : MapConstant.DART_GENERAL_CLASS;
441 ClassElement classElement = compiler.jsHelperLibrary.find(className); 334 ClassElement classElement = compiler.jsHelperLibrary.find(className);
442 classElement.ensureResolved(compiler); 335 classElement.ensureResolved(compiler);
443 Link<DartType> typeArgument = sourceType.typeArguments; 336 Link<DartType> typeArgument = sourceType.typeArguments;
444 InterfaceType type; 337 InterfaceType type;
445 if (sourceType.treatAsRaw) { 338 if (sourceType.treatAsRaw) {
446 type = classElement.rawType; 339 type = classElement.rawType;
447 } else { 340 } else {
448 type = new InterfaceType(classElement, typeArgument); 341 type = new InterfaceType(classElement, typeArgument);
449 } 342 }
450 Constant constant = 343 return new MapConstant(type, keysList, values, protoValue, onlyStringKeys);
451 new MapConstant(type, keysList, values, protoValue, onlyStringKeys);
452 handler.registerCompileTimeConstant(constant, elements);
453 return constant;
454 } 344 }
455 345
456 Constant visitLiteralNull(LiteralNull node) { 346 Constant visitLiteralNull(LiteralNull node) {
457 return constantSystem.createNull(); 347 return constantSystem.createNull();
458 } 348 }
459 349
460 Constant visitLiteralString(LiteralString node) { 350 Constant visitLiteralString(LiteralString node) {
461 handler.registerStringInstance(elements);
462 return constantSystem.createString(node.dartString, node); 351 return constantSystem.createString(node.dartString, node);
463 } 352 }
464 353
465 Constant visitStringJuxtaposition(StringJuxtaposition node) { 354 Constant visitStringJuxtaposition(StringJuxtaposition node) {
466 StringConstant left = evaluate(node.first); 355 StringConstant left = evaluate(node.first);
467 StringConstant right = evaluate(node.second); 356 StringConstant right = evaluate(node.second);
468 if (left == null || right == null) return null; 357 if (left == null || right == null) return null;
469 handler.registerStringInstance(elements);
470 return constantSystem.createString( 358 return constantSystem.createString(
471 new DartString.concat(left.value, right.value), node); 359 new DartString.concat(left.value, right.value), node);
472 } 360 }
473 361
474 Constant visitStringInterpolation(StringInterpolation node) { 362 Constant visitStringInterpolation(StringInterpolation node) {
475 StringConstant initialString = evaluate(node.string); 363 StringConstant initialString = evaluate(node.string);
476 if (initialString == null) return null; 364 if (initialString == null) return null;
477 DartString accumulator = initialString.value; 365 DartString accumulator = initialString.value;
478 for (StringInterpolationPart part in node.parts) { 366 for (StringInterpolationPart part in node.parts) {
479 Constant expression = evaluate(part.expression); 367 Constant expression = evaluate(part.expression);
480 DartString expressionString; 368 DartString expressionString;
481 if (expression == null) { 369 if (expression == null) {
482 return signalNotCompileTimeConstant(part.expression); 370 return signalNotCompileTimeConstant(part.expression);
483 } else if (expression.isNum() || expression.isBool()) { 371 } else if (expression.isNum() || expression.isBool()) {
484 PrimitiveConstant primitive = expression; 372 PrimitiveConstant primitive = expression;
485 expressionString = new DartString.literal(primitive.value.toString()); 373 expressionString = new DartString.literal(primitive.value.toString());
486 } else if (expression.isString()) { 374 } else if (expression.isString()) {
487 PrimitiveConstant primitive = expression; 375 PrimitiveConstant primitive = expression;
488 expressionString = primitive.value; 376 expressionString = primitive.value;
489 } else { 377 } else {
490 return signalNotCompileTimeConstant(part.expression); 378 return signalNotCompileTimeConstant(part.expression);
491 } 379 }
492 accumulator = new DartString.concat(accumulator, expressionString); 380 accumulator = new DartString.concat(accumulator, expressionString);
493 StringConstant partString = evaluate(part.string); 381 StringConstant partString = evaluate(part.string);
494 if (partString == null) return null; 382 if (partString == null) return null;
495 accumulator = new DartString.concat(accumulator, partString.value); 383 accumulator = new DartString.concat(accumulator, partString.value);
496 }; 384 };
497 handler.registerStringInstance(elements);
498 return constantSystem.createString(accumulator, node); 385 return constantSystem.createString(accumulator, node);
499 } 386 }
500 387
501 Constant visitLiteralSymbol(LiteralSymbol node) { 388 Constant visitLiteralSymbol(LiteralSymbol node) {
502 handler.registerStringInstance(elements);
503 InterfaceType type = compiler.symbolClass.computeType(compiler); 389 InterfaceType type = compiler.symbolClass.computeType(compiler);
504 List<Constant> createArguments(_) { 390 List<Constant> createArguments(_) {
505 return [constantSystem.createString( 391 return [constantSystem.createString(
506 new DartString.literal(node.slowNameString), node)]; 392 new DartString.literal(node.slowNameString), node)];
507 } 393 }
508 return makeConstructedConstant( 394 return makeConstructedConstant(
509 node, type, compiler.symbolConstructor, createArguments); 395 node, type, compiler.symbolConstructor, createArguments);
510 } 396 }
511 397
512 Constant makeTypeConstant(Element element) { 398 Constant makeTypeConstant(Element element) {
513 DartType elementType = element.computeType(compiler).asRaw(); 399 DartType elementType = element.computeType(compiler).asRaw();
514 compiler.backend.registerTypeLiteral( 400 compiler.backend.registerTypeLiteral(
515 element, compiler.enqueuer.codegen, elements); 401 element, compiler.enqueuer.codegen, elements);
516 DartType constantType = 402 DartType constantType =
517 compiler.backend.typeImplementation.computeType(compiler); 403 compiler.backend.typeImplementation.computeType(compiler);
518 Constant constant = new TypeConstant(elementType, constantType); 404 return new TypeConstant(elementType, constantType);
519 // If we use a type literal in a constant, the compile time
520 // constant emitter will generate a call to the createRuntimeType
521 // helper so we register a use of that.
522 handler.registerCreateRuntimeTypeFunction();
523 handler.registerCompileTimeConstant(constant, elements);
524 return constant;
525 } 405 }
526 406
527 // TODO(floitsch): provide better error-messages. 407 // TODO(floitsch): provide better error-messages.
528 Constant visitSend(Send send) { 408 Constant visitSend(Send send) {
529 Element element = elements[send]; 409 Element element = elements[send];
530 if (send.isPropertyAccess) { 410 if (send.isPropertyAccess) {
531 if (Elements.isStaticOrTopLevelFunction(element)) { 411 if (Elements.isStaticOrTopLevelFunction(element)) {
532 Constant constant = new FunctionConstant(element); 412 return new FunctionConstant(element);
533 handler.registerCompileTimeConstant(constant, elements);
534 return constant;
535 } else if (Elements.isStaticOrTopLevelField(element)) { 413 } else if (Elements.isStaticOrTopLevelField(element)) {
536 Constant result; 414 Constant result;
537 if (element.modifiers.isConst()) { 415 if (element.modifiers.isConst()) {
538 result = handler.compileConstant(element); 416 result = handler.compileConstant(element);
539 } else if (element.modifiers.isFinal() && !isEvaluatingConstant) { 417 } else if (element.modifiers.isFinal() && !isEvaluatingConstant) {
540 result = handler.compileVariable(element); 418 result = handler.compileVariable(element);
541 } 419 }
542 if (result != null) return result; 420 if (result != null) return result;
543 } else if (Elements.isClass(element) || Elements.isTypedef(element)) { 421 } else if (Elements.isClass(element) || Elements.isTypedef(element)) {
544 return makeTypeConstant(element); 422 return makeTypeConstant(element);
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after
746 // initializers are handled correctly. 624 // initializers are handled correctly.
747 constructor = constructor.implementation; 625 constructor = constructor.implementation;
748 assert(invariant(node, constructor.isImplementation)); 626 assert(invariant(node, constructor.isImplementation));
749 627
750 List<Constant> arguments = getArguments(constructor); 628 List<Constant> arguments = getArguments(constructor);
751 ConstructorEvaluator evaluator = 629 ConstructorEvaluator evaluator =
752 new ConstructorEvaluator(constructor, handler, compiler); 630 new ConstructorEvaluator(constructor, handler, compiler);
753 evaluator.evaluateConstructorFieldValues(arguments); 631 evaluator.evaluateConstructorFieldValues(arguments);
754 List<Constant> jsNewArguments = evaluator.buildJsNewArguments(classElement); 632 List<Constant> jsNewArguments = evaluator.buildJsNewArguments(classElement);
755 633
756 handler.registerInstantiatedType(type, elements); 634 return new ConstructedConstant(type, jsNewArguments);
757 Constant constant = new ConstructedConstant(type, jsNewArguments);
758 handler.registerCompileTimeConstant(constant, elements);
759 return constant;
760 } 635 }
761 636
762 Constant visitParenthesizedExpression(ParenthesizedExpression node) { 637 Constant visitParenthesizedExpression(ParenthesizedExpression node) {
763 return node.expression.accept(this); 638 return node.expression.accept(this);
764 } 639 }
765 640
766 error(Node node) { 641 error(Node node) {
767 // TODO(floitsch): get the list of constants that are currently compiled 642 // TODO(floitsch): get the list of constants that are currently compiled
768 // and present some kind of stack-trace. 643 // and present some kind of stack-trace.
769 compiler.reportFatalError( 644 compiler.reportFatalError(
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after
977 if (fieldValue == null) { 852 if (fieldValue == null) {
978 // Use the default value. 853 // Use the default value.
979 fieldValue = handler.compileConstant(field); 854 fieldValue = handler.compileConstant(field);
980 } 855 }
981 jsNewArguments.add(fieldValue); 856 jsNewArguments.add(fieldValue);
982 }, 857 },
983 includeSuperAndInjectedMembers: true); 858 includeSuperAndInjectedMembers: true);
984 return jsNewArguments; 859 return jsNewArguments;
985 } 860 }
986 } 861 }
OLDNEW
« no previous file with comments | « no previous file | sdk/lib/_internal/compiler/implementation/compiler.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698