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

Side by Side Diff: pkg/compiler/lib/src/native/behavior.dart

Issue 1859343004: dartfmt pkg/compiler (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 8 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
« no previous file with comments | « pkg/compiler/lib/src/mirrors_used.dart ('k') | pkg/compiler/lib/src/native/enqueue.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) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, 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 import '../common.dart'; 5 import '../common.dart';
6 import '../common/backend_api.dart' show 6 import '../common/backend_api.dart' show ForeignResolver;
7 ForeignResolver; 7 import '../common/resolution.dart' show Parsing, Resolution;
8 import '../common/resolution.dart' show 8 import '../compiler.dart' show Compiler;
9 Parsing,
10 Resolution;
11 import '../compiler.dart' show
12 Compiler;
13 import '../constants/values.dart'; 9 import '../constants/values.dart';
14 import '../core_types.dart' show 10 import '../core_types.dart' show CoreTypes;
15 CoreTypes;
16 import '../dart_types.dart'; 11 import '../dart_types.dart';
17 import '../elements/elements.dart'; 12 import '../elements/elements.dart';
18 import '../js/js.dart' as js; 13 import '../js/js.dart' as js;
19 import '../js_backend/js_backend.dart'; 14 import '../js_backend/js_backend.dart';
20 import '../tree/tree.dart'; 15 import '../tree/tree.dart';
21 import '../universe/side_effects.dart' show 16 import '../universe/side_effects.dart' show SideEffects;
22 SideEffects;
23 import '../util/util.dart'; 17 import '../util/util.dart';
24 18
25 import 'enqueue.dart'; 19 import 'enqueue.dart';
26 import 'js.dart'; 20 import 'js.dart';
27 21
28 /// This class is a temporary work-around until we get a more powerful DartType. 22 /// This class is a temporary work-around until we get a more powerful DartType.
29 class SpecialType { 23 class SpecialType {
30 final String name; 24 final String name;
31 const SpecialType._(this.name); 25 const SpecialType._(this.name);
32 26
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
102 * If there is one or more `@Returns` annotations, the union of the named types 96 * If there is one or more `@Returns` annotations, the union of the named types
103 * replaces the declared return type. 97 * replaces the declared return type.
104 * 98 *
105 * @Returns('IDBRequest') 99 * @Returns('IDBRequest')
106 * IDBRequest openCursor(); 100 * IDBRequest openCursor();
107 * 101 *
108 * Types in annotations are non-nullable, so include `@Returns('Null')` if 102 * Types in annotations are non-nullable, so include `@Returns('Null')` if
109 * `null` may be returned. 103 * `null` may be returned.
110 */ 104 */
111 class NativeBehavior { 105 class NativeBehavior {
112
113 /// [DartType]s or [SpecialType]s returned or yielded by the native element. 106 /// [DartType]s or [SpecialType]s returned or yielded by the native element.
114 final List typesReturned = []; 107 final List typesReturned = [];
115 108
116 /// [DartType]s or [SpecialType]s instantiated by the native element. 109 /// [DartType]s or [SpecialType]s instantiated by the native element.
117 final List typesInstantiated = []; 110 final List typesInstantiated = [];
118 111
119 // If this behavior is for a JS expression, [codeTemplate] contains the 112 // If this behavior is for a JS expression, [codeTemplate] contains the
120 // parsed tree. 113 // parsed tree.
121 js.Template codeTemplate; 114 js.Template codeTemplate;
122 115
123 final SideEffects sideEffects = new SideEffects.empty(); 116 final SideEffects sideEffects = new SideEffects.empty();
124 117
125 NativeThrowBehavior throwBehavior = NativeThrowBehavior.MAY; 118 NativeThrowBehavior throwBehavior = NativeThrowBehavior.MAY;
126 119
127 bool isAllocation = false; 120 bool isAllocation = false;
128 bool useGvn = false; 121 bool useGvn = false;
129 122
130 // TODO(sra): Make NativeBehavior immutable so PURE and PURE_ALLOCATION can be 123 // TODO(sra): Make NativeBehavior immutable so PURE and PURE_ALLOCATION can be
131 // final constant-like objects. 124 // final constant-like objects.
132 static NativeBehavior get PURE => NativeBehavior._makePure(); 125 static NativeBehavior get PURE => NativeBehavior._makePure();
133 static NativeBehavior get PURE_ALLOCATION => 126 static NativeBehavior get PURE_ALLOCATION =>
134 NativeBehavior._makePure(isAllocation: true); 127 NativeBehavior._makePure(isAllocation: true);
135 static NativeBehavior get CHANGES_OTHER => NativeBehavior._makeChangesOther(); 128 static NativeBehavior get CHANGES_OTHER => NativeBehavior._makeChangesOther();
136 static NativeBehavior get DEPENDS_OTHER => NativeBehavior._makeDependsOther(); 129 static NativeBehavior get DEPENDS_OTHER => NativeBehavior._makeDependsOther();
137 130
138
139 String toString() { 131 String toString() {
140 return 'NativeBehavior(' 132 return 'NativeBehavior('
141 'returns: ${typesReturned}' 133 'returns: ${typesReturned}'
142 ', creates: ${typesInstantiated}' 134 ', creates: ${typesInstantiated}'
143 ', sideEffects: ${sideEffects}' 135 ', sideEffects: ${sideEffects}'
144 ', throws: ${throwBehavior}' 136 ', throws: ${throwBehavior}'
145 '${isAllocation ? ", isAllocation" : ""}' 137 '${isAllocation ? ", isAllocation" : ""}'
146 '${useGvn ? ", useGvn" : ""}' 138 '${useGvn ? ", useGvn" : ""}'
147 ')'; 139 ')';
148 } 140 }
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
231 /// Each tag kind (including the 'type-tag's) can only occur once in the 223 /// Each tag kind (including the 'type-tag's) can only occur once in the
232 /// sequence. 224 /// sequence.
233 /// 225 ///
234 /// [specString] is the specification string, [resolveType] resolves named 226 /// [specString] is the specification string, [resolveType] resolves named
235 /// types into type values, [typesReturned] and [typesInstantiated] collects 227 /// types into type values, [typesReturned] and [typesInstantiated] collects
236 /// the types defined by the specification string, and [objectType] and 228 /// the types defined by the specification string, and [objectType] and
237 /// [nullType] define the types for `Object` and `Null`, respectively. The 229 /// [nullType] define the types for `Object` and `Null`, respectively. The
238 /// latter is used for the type strings of the form '' and 'var'. 230 /// latter is used for the type strings of the form '' and 'var'.
239 /// [validTags] can be used to restrict which tags are accepted. 231 /// [validTags] can be used to restrict which tags are accepted.
240 static void processSpecString( 232 static void processSpecString(
241 DiagnosticReporter reporter, 233 DiagnosticReporter reporter, Spannable spannable, String specString,
242 Spannable spannable,
243 String specString,
244 {Iterable<String> validTags, 234 {Iterable<String> validTags,
245 void setSideEffects(SideEffects newEffects), 235 void setSideEffects(SideEffects newEffects),
246 void setThrows(NativeThrowBehavior throwKind), 236 void setThrows(NativeThrowBehavior throwKind),
247 void setIsAllocation(bool isAllocation), 237 void setIsAllocation(bool isAllocation),
248 void setUseGvn(bool useGvn), 238 void setUseGvn(bool useGvn),
249 dynamic resolveType(String typeString), 239 dynamic resolveType(String typeString),
250 List typesReturned, 240 List typesReturned,
251 List typesInstantiated, 241 List typesInstantiated,
252 objectType, nullType}) { 242 objectType,
253 243 nullType}) {
254
255 bool seenError = false; 244 bool seenError = false;
256 245
257 void reportError(String message) { 246 void reportError(String message) {
258 seenError = true; 247 seenError = true;
259 reporter.reportErrorMessage( 248 reporter.reportErrorMessage(
260 spannable, MessageKind.GENERIC, {'text': message}); 249 spannable, MessageKind.GENERIC, {'text': message});
261 } 250 }
262 251
263 const List<String> knownTags = const [ 252 const List<String> knownTags = const [
264 'creates', 'returns', 'depends', 'effects', 253 'creates',
265 'throws', 'gvn', 'new']; 254 'returns',
255 'depends',
256 'effects',
257 'throws',
258 'gvn',
259 'new'
260 ];
266 261
267 /// Resolve a type string of one of the three forms: 262 /// Resolve a type string of one of the three forms:
268 /// * 'void' - in which case [onVoid] is called, 263 /// * 'void' - in which case [onVoid] is called,
269 /// * '' or 'var' - in which case [onVar] is called, 264 /// * '' or 'var' - in which case [onVar] is called,
270 /// * 'T1|...|Tn' - in which case [onType] is called for each resolved Ti. 265 /// * 'T1|...|Tn' - in which case [onType] is called for each resolved Ti.
271 void resolveTypesString(String typesString, 266 void resolveTypesString(String typesString,
272 {onVoid(), onVar(), onType(type)}) { 267 {onVoid(), onVar(), onType(type)}) {
273 // Various things that are not in fact types. 268 // Various things that are not in fact types.
274 if (typesString == 'void') { 269 if (typesString == 'void') {
275 if (onVoid != null) { 270 if (onVoid != null) {
276 onVoid(); 271 onVoid();
277 } 272 }
278 return; 273 return;
279 } 274 }
280 if (typesString == '' || typesString == 'var') { 275 if (typesString == '' || typesString == 'var') {
281 if (onVar != null) { 276 if (onVar != null) {
282 onVar(); 277 onVar();
(...skipping 10 matching lines...) Expand all
293 resolveTypesString(specString.trim(), onVar: () { 288 resolveTypesString(specString.trim(), onVar: () {
294 typesReturned.add(objectType); 289 typesReturned.add(objectType);
295 typesReturned.add(nullType); 290 typesReturned.add(nullType);
296 }, onType: (type) { 291 }, onType: (type) {
297 typesInstantiated.add(type); 292 typesInstantiated.add(type);
298 typesReturned.add(type); 293 typesReturned.add(type);
299 }); 294 });
300 return; 295 return;
301 } 296 }
302 297
303 List<String> specs = specString.split(';') 298 List<String> specs = specString.split(';').map((s) => s.trim()).toList();
304 .map((s) => s.trim()) 299 if (specs.last == "") specs.removeLast(); // Allow separator to terminate.
305 .toList();
306 if (specs.last == "") specs.removeLast(); // Allow separator to terminate.
307 300
308 assert(validTags == null || 301 assert(
309 (validTags.toSet()..removeAll(validTags)).isEmpty); 302 validTags == null || (validTags.toSet()..removeAll(validTags)).isEmpty);
310 if (validTags == null) validTags = knownTags; 303 if (validTags == null) validTags = knownTags;
311 304
312 Map<String, String> values = <String, String>{}; 305 Map<String, String> values = <String, String>{};
313 306
314 for (String spec in specs) { 307 for (String spec in specs) {
315 List<String> tagAndValue = spec.split(':'); 308 List<String> tagAndValue = spec.split(':');
316 if (tagAndValue.length != 2) { 309 if (tagAndValue.length != 2) {
317 reportError("Invalid <tag>:<value> pair '$spec'."); 310 reportError("Invalid <tag>:<value> pair '$spec'.");
318 continue; 311 continue;
319 } 312 }
(...skipping 24 matching lines...) Expand all
344 if (tagString == null) return null; 337 if (tagString == null) return null;
345 var value = map[tagString]; 338 var value = map[tagString];
346 if (value == null) { 339 if (value == null) {
347 reportError("Unknown '$tag' specification: '$tagString'."); 340 reportError("Unknown '$tag' specification: '$tagString'.");
348 } 341 }
349 return value; 342 return value;
350 } 343 }
351 344
352 String returns = values['returns']; 345 String returns = values['returns'];
353 if (returns != null) { 346 if (returns != null) {
354 resolveTypesString(returns, 347 resolveTypesString(returns, onVar: () {
355 onVar: () { 348 typesReturned.add(objectType);
356 typesReturned.add(objectType); 349 typesReturned.add(nullType);
357 typesReturned.add(nullType); 350 }, onType: (type) {
358 }, 351 typesReturned.add(type);
359 onType: (type) { 352 });
360 typesReturned.add(type);
361 });
362 } 353 }
363 354
364 String creates = values['creates']; 355 String creates = values['creates'];
365 if (creates != null) { 356 if (creates != null) {
366 resolveTypesString(creates, 357 resolveTypesString(creates, onVoid: () {
367 onVoid: () { 358 reportError("Invalid type string 'creates:$creates'");
368 reportError("Invalid type string 'creates:$creates'"); 359 }, onType: (type) {
369 }, 360 typesInstantiated.add(type);
370 onType: (type) { 361 });
371 typesInstantiated.add(type);
372 });
373 } else if (returns != null) { 362 } else if (returns != null) {
374 resolveTypesString(returns, 363 resolveTypesString(returns, onType: (type) {
375 onType: (type) { 364 typesInstantiated.add(type);
376 typesInstantiated.add(type); 365 });
377 });
378 } 366 }
379 367
380 const throwsOption = const <String, NativeThrowBehavior>{ 368 const throwsOption = const <String, NativeThrowBehavior>{
381 'never': NativeThrowBehavior.NEVER, 369 'never': NativeThrowBehavior.NEVER,
382 'null(1)': NativeThrowBehavior.MAY_THROW_ONLY_ON_FIRST_ARGUMENT_ACCESS, 370 'null(1)': NativeThrowBehavior.MAY_THROW_ONLY_ON_FIRST_ARGUMENT_ACCESS,
383 'may': NativeThrowBehavior.MAY, 371 'may': NativeThrowBehavior.MAY,
384 'must': NativeThrowBehavior.MUST }; 372 'must': NativeThrowBehavior.MUST
373 };
385 374
386 const boolOptions = const<String, bool>{'true': true, 'false': false}; 375 const boolOptions = const <String, bool>{'true': true, 'false': false};
387 376
388 SideEffects sideEffects = processEffects(reportError, 377 SideEffects sideEffects =
389 values['effects'], values['depends']); 378 processEffects(reportError, values['effects'], values['depends']);
390 NativeThrowBehavior throwsKind = tagValueLookup('throws', throwsOption); 379 NativeThrowBehavior throwsKind = tagValueLookup('throws', throwsOption);
391 bool isAllocation = tagValueLookup('new', boolOptions); 380 bool isAllocation = tagValueLookup('new', boolOptions);
392 bool useGvn = tagValueLookup('gvn', boolOptions); 381 bool useGvn = tagValueLookup('gvn', boolOptions);
393 382
394 if (isAllocation == true && useGvn == true) { 383 if (isAllocation == true && useGvn == true) {
395 reportError("'new' and 'gvn' are incompatible"); 384 reportError("'new' and 'gvn' are incompatible");
396 } 385 }
397 386
398 if (seenError) return; // Avoid callbacks. 387 if (seenError) return; // Avoid callbacks.
399 388
400 // TODO(sra): Simplify [throwBehavior] using [sideEffects]. 389 // TODO(sra): Simplify [throwBehavior] using [sideEffects].
401 390
402 if (sideEffects != null) setSideEffects(sideEffects); 391 if (sideEffects != null) setSideEffects(sideEffects);
403 if (throwsKind != null) setThrows(throwsKind); 392 if (throwsKind != null) setThrows(throwsKind);
404 if (isAllocation != null) setIsAllocation(isAllocation); 393 if (isAllocation != null) setIsAllocation(isAllocation);
405 if (useGvn != null) setUseGvn(useGvn); 394 if (useGvn != null) setUseGvn(useGvn);
406 } 395 }
407 396
408 static SideEffects processEffects( 397 static SideEffects processEffects(
409 void reportError(String message), 398 void reportError(String message), String effects, String depends) {
410 String effects,
411 String depends) {
412
413 if (effects == null && depends == null) return null; 399 if (effects == null && depends == null) return null;
414 400
415 if (effects == null || depends == null) { 401 if (effects == null || depends == null) {
416 reportError("'effects' and 'depends' must occur together."); 402 reportError("'effects' and 'depends' must occur together.");
417 return null; 403 return null;
418 } 404 }
419 405
420 SideEffects sideEffects = new SideEffects(); 406 SideEffects sideEffects = new SideEffects();
421 if (effects == "none") { 407 if (effects == "none") {
422 sideEffects.clearAllSideEffects(); 408 sideEffects.clearAllSideEffects();
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
466 break; 452 break;
467 default: 453 default:
468 reportError("Unrecognized side-effect flag: '$dependency'."); 454 reportError("Unrecognized side-effect flag: '$dependency'.");
469 } 455 }
470 } 456 }
471 } 457 }
472 458
473 return sideEffects; 459 return sideEffects;
474 } 460 }
475 461
476 static NativeBehavior ofJsCall( 462 static NativeBehavior ofJsCall(Send jsCall, DiagnosticReporter reporter,
477 Send jsCall, 463 Parsing parsing, CoreTypes coreTypes, ForeignResolver resolver) {
478 DiagnosticReporter reporter,
479 Parsing parsing,
480 CoreTypes coreTypes,
481 ForeignResolver resolver) {
482 // The first argument of a JS-call is a string encoding various attributes 464 // The first argument of a JS-call is a string encoding various attributes
483 // of the code. 465 // of the code.
484 // 466 //
485 // 'Type1|Type2'. A union type. 467 // 'Type1|Type2'. A union type.
486 // '=Object'. A JavaScript Object, no subtype. 468 // '=Object'. A JavaScript Object, no subtype.
487 469
488 NativeBehavior behavior = new NativeBehavior(); 470 NativeBehavior behavior = new NativeBehavior();
489 471
490 var argNodes = jsCall.arguments; 472 var argNodes = jsCall.arguments;
491 if (argNodes.isEmpty || argNodes.tail.isEmpty) { 473 if (argNodes.isEmpty || argNodes.tail.isEmpty) {
492 reporter.reportErrorMessage( 474 reporter.reportErrorMessage(jsCall, MessageKind.GENERIC,
493 jsCall,
494 MessageKind.GENERIC,
495 {'text': "JS expression takes two or more arguments."}); 475 {'text': "JS expression takes two or more arguments."});
496 return behavior; 476 return behavior;
497 } 477 }
498 478
499 var specArgument = argNodes.head; 479 var specArgument = argNodes.head;
500 if (specArgument is !StringNode || specArgument.isInterpolation) { 480 if (specArgument is! StringNode || specArgument.isInterpolation) {
501 reporter.reportErrorMessage( 481 reporter.reportErrorMessage(specArgument, MessageKind.GENERIC,
502 specArgument, MessageKind.GENERIC,
503 {'text': "JS first argument must be a string literal."}); 482 {'text': "JS first argument must be a string literal."});
504 return behavior; 483 return behavior;
505 } 484 }
506 485
507 var codeArgument = argNodes.tail.head; 486 var codeArgument = argNodes.tail.head;
508 if (codeArgument is !StringNode || codeArgument.isInterpolation) { 487 if (codeArgument is! StringNode || codeArgument.isInterpolation) {
509 reporter.reportErrorMessage( 488 reporter.reportErrorMessage(codeArgument, MessageKind.GENERIC,
510 codeArgument, MessageKind.GENERIC,
511 {'text': "JS second argument must be a string literal."}); 489 {'text': "JS second argument must be a string literal."});
512 return behavior; 490 return behavior;
513 } 491 }
514 492
515 behavior.codeTemplate = 493 behavior.codeTemplate =
516 js.js.parseForeignJS(codeArgument.dartString.slowToString()); 494 js.js.parseForeignJS(codeArgument.dartString.slowToString());
517 495
518 String specString = specArgument.dartString.slowToString(); 496 String specString = specArgument.dartString.slowToString();
519 497
520 dynamic resolveType(String typeString) { 498 dynamic resolveType(String typeString) {
(...skipping 18 matching lines...) Expand all
539 } 517 }
540 518
541 void setIsAllocation(bool isAllocation) { 519 void setIsAllocation(bool isAllocation) {
542 behavior.isAllocation = isAllocation; 520 behavior.isAllocation = isAllocation;
543 } 521 }
544 522
545 void setUseGvn(bool useGvn) { 523 void setUseGvn(bool useGvn) {
546 behavior.useGvn = useGvn; 524 behavior.useGvn = useGvn;
547 } 525 }
548 526
549 processSpecString( 527 processSpecString(reporter, specArgument, specString,
550 reporter,
551 specArgument,
552 specString,
553 setSideEffects: setSideEffects, 528 setSideEffects: setSideEffects,
554 setThrows: setThrows, 529 setThrows: setThrows,
555 setIsAllocation: setIsAllocation, 530 setIsAllocation: setIsAllocation,
556 setUseGvn: setUseGvn, 531 setUseGvn: setUseGvn,
557 resolveType: resolveType, 532 resolveType: resolveType,
558 typesReturned: behavior.typesReturned, 533 typesReturned: behavior.typesReturned,
559 typesInstantiated: behavior.typesInstantiated, 534 typesInstantiated: behavior.typesInstantiated,
560 objectType: coreTypes.objectType, 535 objectType: coreTypes.objectType,
561 nullType: coreTypes.nullType); 536 nullType: coreTypes.nullType);
562 537
(...skipping 10 matching lines...) Expand all
573 } 548 }
574 549
575 static void _fillNativeBehaviorOfBuiltinOrEmbeddedGlobal( 550 static void _fillNativeBehaviorOfBuiltinOrEmbeddedGlobal(
576 NativeBehavior behavior, 551 NativeBehavior behavior,
577 Send jsBuiltinOrEmbeddedGlobalCall, 552 Send jsBuiltinOrEmbeddedGlobalCall,
578 DiagnosticReporter reporter, 553 DiagnosticReporter reporter,
579 Parsing parsing, 554 Parsing parsing,
580 CoreTypes coreTypes, 555 CoreTypes coreTypes,
581 ForeignResolver resolver, 556 ForeignResolver resolver,
582 {bool isBuiltin, 557 {bool isBuiltin,
583 List<String> validTags}) { 558 List<String> validTags}) {
584 // The first argument of a JS-embedded global call is a string encoding 559 // The first argument of a JS-embedded global call is a string encoding
585 // the type of the code. 560 // the type of the code.
586 // 561 //
587 // 'Type1|Type2'. A union type. 562 // 'Type1|Type2'. A union type.
588 // '=Object'. A JavaScript Object, no subtype. 563 // '=Object'. A JavaScript Object, no subtype.
589 564
590 String builtinOrGlobal = isBuiltin ? "builtin" : "embedded global"; 565 String builtinOrGlobal = isBuiltin ? "builtin" : "embedded global";
591 566
592 Link<Node> argNodes = jsBuiltinOrEmbeddedGlobalCall.arguments; 567 Link<Node> argNodes = jsBuiltinOrEmbeddedGlobalCall.arguments;
593 if (argNodes.isEmpty) { 568 if (argNodes.isEmpty) {
(...skipping 30 matching lines...) Expand all
624 typeString, 599 typeString,
625 parsing, 600 parsing,
626 (name) => resolver.resolveTypeFromString(specLiteral, name), 601 (name) => resolver.resolveTypeFromString(specLiteral, name),
627 jsBuiltinOrEmbeddedGlobalCall); 602 jsBuiltinOrEmbeddedGlobalCall);
628 } 603 }
629 604
630 void setSideEffects(SideEffects newEffects) { 605 void setSideEffects(SideEffects newEffects) {
631 behavior.sideEffects.setTo(newEffects); 606 behavior.sideEffects.setTo(newEffects);
632 } 607 }
633 608
634 processSpecString( 609 processSpecString(reporter, jsBuiltinOrEmbeddedGlobalCall, specString,
635 reporter,
636 jsBuiltinOrEmbeddedGlobalCall,
637 specString,
638 validTags: validTags, 610 validTags: validTags,
639 resolveType: resolveType, 611 resolveType: resolveType,
640 setSideEffects: setSideEffects, 612 setSideEffects: setSideEffects,
641 typesReturned: behavior.typesReturned, 613 typesReturned: behavior.typesReturned,
642 typesInstantiated: behavior.typesInstantiated, 614 typesInstantiated: behavior.typesInstantiated,
643 objectType: coreTypes.objectType, 615 objectType: coreTypes.objectType,
644 nullType: coreTypes.nullType); 616 nullType: coreTypes.nullType);
645 } 617 }
646 618
647 static NativeBehavior ofJsBuiltinCall( 619 static NativeBehavior ofJsBuiltinCall(
648 Send jsBuiltinCall, 620 Send jsBuiltinCall,
649 DiagnosticReporter reporter, 621 DiagnosticReporter reporter,
650 Parsing parsing, 622 Parsing parsing,
651 CoreTypes coreTypes, 623 CoreTypes coreTypes,
652 ForeignResolver resolver) { 624 ForeignResolver resolver) {
653 NativeBehavior behavior = new NativeBehavior(); 625 NativeBehavior behavior = new NativeBehavior();
654 behavior.sideEffects.setTo(new SideEffects()); 626 behavior.sideEffects.setTo(new SideEffects());
655 627
656 _fillNativeBehaviorOfBuiltinOrEmbeddedGlobal( 628 _fillNativeBehaviorOfBuiltinOrEmbeddedGlobal(
657 behavior, 629 behavior, jsBuiltinCall, reporter, parsing, coreTypes, resolver,
658 jsBuiltinCall,
659 reporter,
660 parsing,
661 coreTypes,
662 resolver,
663 isBuiltin: true); 630 isBuiltin: true);
664 631
665 return behavior; 632 return behavior;
666 } 633 }
667 634
668 static NativeBehavior ofJsEmbeddedGlobalCall( 635 static NativeBehavior ofJsEmbeddedGlobalCall(
669 Send jsEmbeddedGlobalCall, 636 Send jsEmbeddedGlobalCall,
670 DiagnosticReporter reporter, 637 DiagnosticReporter reporter,
671 Parsing parsing, 638 Parsing parsing,
672 CoreTypes coreTypes, 639 CoreTypes coreTypes,
673 ForeignResolver resolver) { 640 ForeignResolver resolver) {
674 NativeBehavior behavior = new NativeBehavior(); 641 NativeBehavior behavior = new NativeBehavior();
675 // TODO(sra): Allow the use site to override these defaults. 642 // TODO(sra): Allow the use site to override these defaults.
676 // Embedded globals are usually pre-computed data structures or JavaScript 643 // Embedded globals are usually pre-computed data structures or JavaScript
677 // functions that never change. 644 // functions that never change.
678 behavior.sideEffects.setTo(new SideEffects.empty()); 645 behavior.sideEffects.setTo(new SideEffects.empty());
679 behavior.throwBehavior = NativeThrowBehavior.NEVER; 646 behavior.throwBehavior = NativeThrowBehavior.NEVER;
680 647
681 _fillNativeBehaviorOfBuiltinOrEmbeddedGlobal( 648 _fillNativeBehaviorOfBuiltinOrEmbeddedGlobal(
682 behavior, 649 behavior, jsEmbeddedGlobalCall, reporter, parsing, coreTypes, resolver,
683 jsEmbeddedGlobalCall, 650 isBuiltin: false, validTags: const ['returns', 'creates']);
684 reporter,
685 parsing,
686 coreTypes,
687 resolver,
688 isBuiltin: false,
689 validTags: const ['returns', 'creates']);
690 651
691 return behavior; 652 return behavior;
692 } 653 }
693 654
694 static NativeBehavior ofMethod(FunctionElement method, Compiler compiler) { 655 static NativeBehavior ofMethod(FunctionElement method, Compiler compiler) {
695 FunctionType type = method.computeType(compiler.resolution); 656 FunctionType type = method.computeType(compiler.resolution);
696 var behavior = new NativeBehavior(); 657 var behavior = new NativeBehavior();
697 var returnType = type.returnType; 658 var returnType = type.returnType;
698 bool isInterop = compiler.backend.isJsInterop(method); 659 bool isInterop = compiler.backend.isJsInterop(method);
699 // Note: For dart:html and other internal libraries we maintain, we can 660 // Note: For dart:html and other internal libraries we maintain, we can
700 // trust the return type and use it to limit what we enqueue. We have to 661 // trust the return type and use it to limit what we enqueue. We have to
701 // be more conservative about JS interop types and assume they can return 662 // be more conservative about JS interop types and assume they can return
702 // anything (unless the user provides the experimental flag to trust the 663 // anything (unless the user provides the experimental flag to trust the
703 // type of js-interop APIs). We do restrict the allocation effects and say 664 // type of js-interop APIs). We do restrict the allocation effects and say
704 // that interop calls create only interop types (which may be unsound if 665 // that interop calls create only interop types (which may be unsound if
705 // an interop call returns a DOM type and declares a dynamic return type, 666 // an interop call returns a DOM type and declares a dynamic return type,
706 // but otherwise we would include a lot of code by default). 667 // but otherwise we would include a lot of code by default).
707 // TODO(sigmund,sra): consider doing something better for numeric types. 668 // TODO(sigmund,sra): consider doing something better for numeric types.
708 behavior.typesReturned.add( 669 behavior.typesReturned.add(
709 !isInterop || compiler.options.trustJSInteropTypeAnnotations 670 !isInterop || compiler.options.trustJSInteropTypeAnnotations
710 ? returnType : const DynamicType()); 671 ? returnType
672 : const DynamicType());
711 if (!type.returnType.isVoid) { 673 if (!type.returnType.isVoid) {
712 // Declared types are nullable. 674 // Declared types are nullable.
713 behavior.typesReturned.add(compiler.coreTypes.nullType); 675 behavior.typesReturned.add(compiler.coreTypes.nullType);
714 } 676 }
715 behavior._capture(type, compiler.resolution, 677 behavior._capture(type, compiler.resolution,
716 isInterop: isInterop, compiler: compiler); 678 isInterop: isInterop, compiler: compiler);
717 679
718 // TODO(sra): Optional arguments are currently missing from the 680 // TODO(sra): Optional arguments are currently missing from the
719 // DartType. This should be fixed so the following work-around can be 681 // DartType. This should be fixed so the following work-around can be
720 // removed. 682 // removed.
721 method.functionSignature.forEachOptionalParameter( 683 method.functionSignature
722 (ParameterElement parameter) { 684 .forEachOptionalParameter((ParameterElement parameter) {
723 behavior._escape(parameter.type, compiler.resolution); 685 behavior._escape(parameter.type, compiler.resolution);
724 }); 686 });
725 687
726 behavior._overrideWithAnnotations(method, compiler); 688 behavior._overrideWithAnnotations(method, compiler);
727 return behavior; 689 return behavior;
728 } 690 }
729 691
730 static NativeBehavior ofFieldLoad(MemberElement field, Compiler compiler) { 692 static NativeBehavior ofFieldLoad(MemberElement field, Compiler compiler) {
731 Resolution resolution = compiler.resolution; 693 Resolution resolution = compiler.resolution;
732 DartType type = field.computeType(resolution); 694 DartType type = field.computeType(resolution);
733 var behavior = new NativeBehavior(); 695 var behavior = new NativeBehavior();
734 bool isInterop = compiler.backend.isJsInterop(field); 696 bool isInterop = compiler.backend.isJsInterop(field);
735 // TODO(sigmund,sra): consider doing something better for numeric types. 697 // TODO(sigmund,sra): consider doing something better for numeric types.
736 behavior.typesReturned.add( 698 behavior.typesReturned.add(
737 !isInterop || compiler.options.trustJSInteropTypeAnnotations 699 !isInterop || compiler.options.trustJSInteropTypeAnnotations
738 ? type : const DynamicType()); 700 ? type
701 : const DynamicType());
739 // Declared types are nullable. 702 // Declared types are nullable.
740 behavior.typesReturned.add(resolution.coreTypes.nullType); 703 behavior.typesReturned.add(resolution.coreTypes.nullType);
741 behavior._capture(type, resolution, 704 behavior._capture(type, resolution,
742 isInterop: isInterop, compiler: compiler); 705 isInterop: isInterop, compiler: compiler);
743 behavior._overrideWithAnnotations(field, compiler); 706 behavior._overrideWithAnnotations(field, compiler);
744 return behavior; 707 return behavior;
745 } 708 }
746 709
747 static NativeBehavior ofFieldStore(MemberElement field, Compiler compiler) { 710 static NativeBehavior ofFieldStore(MemberElement field, Compiler compiler) {
748 Resolution resolution = compiler.resolution; 711 Resolution resolution = compiler.resolution;
(...skipping 11 matching lines...) Expand all
760 DartType lookup(String name) { 723 DartType lookup(String name) {
761 Element e = element.buildScope().lookup(name); 724 Element e = element.buildScope().lookup(name);
762 if (e == null) return null; 725 if (e == null) return null;
763 if (e is! ClassElement) return null; 726 if (e is! ClassElement) return null;
764 ClassElement cls = e; 727 ClassElement cls = e;
765 cls.ensureResolved(compiler.resolution); 728 cls.ensureResolved(compiler.resolution);
766 return cls.thisType; 729 return cls.thisType;
767 } 730 }
768 731
769 NativeEnqueuer enqueuer = compiler.enqueuer.resolution.nativeEnqueuer; 732 NativeEnqueuer enqueuer = compiler.enqueuer.resolution.nativeEnqueuer;
770 var creates = _collect(element, compiler, enqueuer.annotationCreatesClass, 733 var creates =
771 lookup); 734 _collect(element, compiler, enqueuer.annotationCreatesClass, lookup);
772 var returns = _collect(element, compiler, enqueuer.annotationReturnsClass, 735 var returns =
773 lookup); 736 _collect(element, compiler, enqueuer.annotationReturnsClass, lookup);
774 737
775 if (creates != null) { 738 if (creates != null) {
776 typesInstantiated..clear()..addAll(creates); 739 typesInstantiated
740 ..clear()
741 ..addAll(creates);
777 } 742 }
778 if (returns != null) { 743 if (returns != null) {
779 typesReturned..clear()..addAll(returns); 744 typesReturned
745 ..clear()
746 ..addAll(returns);
780 } 747 }
781 } 748 }
782 749
783 /** 750 /**
784 * Returns a list of type constraints from the annotations of 751 * Returns a list of type constraints from the annotations of
785 * [annotationClass]. 752 * [annotationClass].
786 * Returns `null` if no constraints. 753 * Returns `null` if no constraints.
787 */ 754 */
788 static _collect(Element element, Compiler compiler, Element annotationClass, 755 static _collect(Element element, Compiler compiler, Element annotationClass,
789 lookup(str)) { 756 lookup(str)) {
790 DiagnosticReporter reporter = compiler.reporter; 757 DiagnosticReporter reporter = compiler.reporter;
791 var types = null; 758 var types = null;
792 for (MetadataAnnotation annotation in element.implementation.metadata) { 759 for (MetadataAnnotation annotation in element.implementation.metadata) {
793 annotation.ensureResolved(compiler.resolution); 760 annotation.ensureResolved(compiler.resolution);
794 ConstantValue value = 761 ConstantValue value =
795 compiler.constants.getConstantValue(annotation.constant); 762 compiler.constants.getConstantValue(annotation.constant);
796 if (!value.isConstructedObject) continue; 763 if (!value.isConstructedObject) continue;
797 ConstructedConstantValue constructedObject = value; 764 ConstructedConstantValue constructedObject = value;
798 if (constructedObject.type.element != annotationClass) continue; 765 if (constructedObject.type.element != annotationClass) continue;
799 766
800 Iterable<ConstantValue> fields = constructedObject.fields.values; 767 Iterable<ConstantValue> fields = constructedObject.fields.values;
801 // TODO(sra): Better validation of the constant. 768 // TODO(sra): Better validation of the constant.
802 if (fields.length != 1 || !fields.single.isString) { 769 if (fields.length != 1 || !fields.single.isString) {
803 reporter.internalError(annotation, 770 reporter.internalError(
804 'Annotations needs one string: ${annotation.node}'); 771 annotation, 'Annotations needs one string: ${annotation.node}');
805 } 772 }
806 StringConstantValue specStringConstant = fields.single; 773 StringConstantValue specStringConstant = fields.single;
807 String specString = specStringConstant.toDartString().slowToString(); 774 String specString = specStringConstant.toDartString().slowToString();
808 for (final typeString in specString.split('|')) { 775 for (final typeString in specString.split('|')) {
809 var type = _parseType(typeString, compiler.parsing, lookup, annotation); 776 var type = _parseType(typeString, compiler.parsing, lookup, annotation);
810 if (types == null) types = []; 777 if (types == null) types = [];
811 types.add(type); 778 types.add(type);
812 } 779 }
813 } 780 }
814 return types; 781 return types;
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
853 if (!isInterop) { 820 if (!isInterop) {
854 typesInstantiated.add(type); 821 typesInstantiated.add(type);
855 } else { 822 } else {
856 if (type.element != null && backend.isNative(type.element)) { 823 if (type.element != null && backend.isNative(type.element)) {
857 // Any declared native or interop type (isNative implies isJsInterop) 824 // Any declared native or interop type (isNative implies isJsInterop)
858 // is assumed to be allocated. 825 // is assumed to be allocated.
859 typesInstantiated.add(type); 826 typesInstantiated.add(type);
860 } 827 }
861 828
862 if (!compiler.options.trustJSInteropTypeAnnotations || 829 if (!compiler.options.trustJSInteropTypeAnnotations ||
863 type.isDynamic || type.isObject) { 830 type.isDynamic ||
831 type.isObject) {
864 // By saying that only JS-interop types can be created, we prevent 832 // By saying that only JS-interop types can be created, we prevent
865 // pulling in every other native type (e.g. all of dart:html) when a 833 // pulling in every other native type (e.g. all of dart:html) when a
866 // JS interop API returns dynamic or when we don't trust the type 834 // JS interop API returns dynamic or when we don't trust the type
867 // annotations. This means that to some degree we still use the return 835 // annotations. This means that to some degree we still use the return
868 // type to decide whether to include native types, even if we don't 836 // type to decide whether to include native types, even if we don't
869 // trust the type annotation. 837 // trust the type annotation.
870 ClassElement cls = backend.helpers.jsJavaScriptObjectClass; 838 ClassElement cls = backend.helpers.jsJavaScriptObjectClass;
871 cls.ensureResolved(resolution); 839 cls.ensureResolved(resolution);
872 typesInstantiated.add(cls.thisType); 840 typesInstantiated.add(cls.thisType);
873 } else { 841 } else {
874 // Otherwise, when the declared type is a Dart type, we do not 842 // Otherwise, when the declared type is a Dart type, we do not
875 // register an allocation because we assume it cannot be instantiated 843 // register an allocation because we assume it cannot be instantiated
876 // from within the JS-interop code. It must have escaped from another 844 // from within the JS-interop code. It must have escaped from another
877 // API. 845 // API.
878 } 846 }
879 } 847 }
880 } 848 }
881 } 849 }
882 850
883 static dynamic _parseType( 851 static dynamic _parseType(
884 String typeString, 852 String typeString, Parsing parsing, lookup(name), locationNodeOrElement) {
885 Parsing parsing,
886 lookup(name),
887 locationNodeOrElement) {
888 DiagnosticReporter reporter = parsing.reporter; 853 DiagnosticReporter reporter = parsing.reporter;
889 if (typeString == '=Object') return SpecialType.JsObject; 854 if (typeString == '=Object') return SpecialType.JsObject;
890 if (typeString == 'dynamic') { 855 if (typeString == 'dynamic') {
891 return const DynamicType(); 856 return const DynamicType();
892 } 857 }
893 var type = lookup(typeString); 858 var type = lookup(typeString);
894 if (type != null) return type; 859 if (type != null) return type;
895 860
896 int index = typeString.indexOf('<'); 861 int index = typeString.indexOf('<');
897 if (index < 1) { 862 if (index < 1) {
898 reporter.reportErrorMessage( 863 reporter.reportErrorMessage(_errorNode(locationNodeOrElement, parsing),
899 _errorNode(locationNodeOrElement, parsing), 864 MessageKind.GENERIC, {'text': "Type '$typeString' not found."});
900 MessageKind.GENERIC,
901 {'text': "Type '$typeString' not found."});
902 return const DynamicType(); 865 return const DynamicType();
903 } 866 }
904 type = lookup(typeString.substring(0, index)); 867 type = lookup(typeString.substring(0, index));
905 if (type != null) { 868 if (type != null) {
906 // TODO(sra): Parse type parameters. 869 // TODO(sra): Parse type parameters.
907 return type; 870 return type;
908 } 871 }
909 reporter.reportErrorMessage( 872 reporter.reportErrorMessage(_errorNode(locationNodeOrElement, parsing),
910 _errorNode(locationNodeOrElement, parsing), 873 MessageKind.GENERIC, {'text': "Type '$typeString' not found."});
911 MessageKind.GENERIC,
912 {'text': "Type '$typeString' not found."});
913 return const DynamicType(); 874 return const DynamicType();
914 } 875 }
915 876
916 static _errorNode(locationNodeOrElement, Parsing parsing) { 877 static _errorNode(locationNodeOrElement, Parsing parsing) {
917 if (locationNodeOrElement is Node) return locationNodeOrElement; 878 if (locationNodeOrElement is Node) return locationNodeOrElement;
918 return locationNodeOrElement.parseNode(parsing); 879 return locationNodeOrElement.parseNode(parsing);
919 } 880 }
920 } 881 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/mirrors_used.dart ('k') | pkg/compiler/lib/src/native/enqueue.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698