OLD | NEW |
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, 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 'package:kernel/ast.dart' as ir; | 5 import 'package:kernel/ast.dart' as ir; |
6 | 6 |
7 import '../constants/expressions.dart'; | 7 import '../constants/expressions.dart'; |
8 import '../common.dart'; | 8 import '../common.dart'; |
9 import '../common/names.dart'; | 9 import '../common/names.dart'; |
10 import '../compiler.dart'; | 10 import '../compiler.dart'; |
11 import '../constants/values.dart'; | 11 import '../constants/values.dart'; |
12 import '../dart_types.dart'; | 12 import '../dart_types.dart'; |
13 import '../elements/elements.dart'; | 13 import '../elements/elements.dart'; |
14 import '../js_backend/backend_helpers.dart'; | 14 import '../js_backend/backend_helpers.dart'; |
15 import '../js_backend/js_backend.dart'; | 15 import '../js_backend/js_backend.dart'; |
16 import '../kernel/kernel.dart'; | 16 import '../kernel/kernel.dart'; |
17 import '../kernel/kernel_debug.dart'; | 17 import '../kernel/kernel_debug.dart'; |
18 import '../native/native.dart' show NativeBehavior; | 18 import '../native/native.dart' show NativeBehavior, TypeLookup; |
19 import '../resolution/tree_elements.dart'; | 19 import '../resolution/tree_elements.dart'; |
20 import '../tree/tree.dart' as ast; | 20 import '../tree/tree.dart' as ast; |
21 import '../types/masks.dart'; | 21 import '../types/masks.dart'; |
22 import '../types/types.dart'; | 22 import '../types/types.dart'; |
23 import '../universe/call_structure.dart'; | 23 import '../universe/call_structure.dart'; |
24 import '../universe/selector.dart'; | 24 import '../universe/selector.dart'; |
25 import '../universe/side_effects.dart'; | 25 import '../universe/side_effects.dart'; |
26 import '../world.dart'; | 26 import '../world.dart'; |
27 import 'locals_handler.dart'; | 27 import 'locals_handler.dart'; |
28 import 'types.dart'; | 28 import 'types.dart'; |
(...skipping 322 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
351 | 351 |
352 /// Return `true` if [node] is the `dart:_foreign_helper` library. | 352 /// Return `true` if [node] is the `dart:_foreign_helper` library. |
353 bool isForeignLibrary(ir.Library node) { | 353 bool isForeignLibrary(ir.Library node) { |
354 return node.importUri == BackendHelpers.DART_FOREIGN_HELPER; | 354 return node.importUri == BackendHelpers.DART_FOREIGN_HELPER; |
355 } | 355 } |
356 | 356 |
357 /// Looks up [typeName] for use in the spec-string of a `JS` called. | 357 /// Looks up [typeName] for use in the spec-string of a `JS` called. |
358 // TODO(johnniwinther): Use this in [NativeBehavior] instead of calling the | 358 // TODO(johnniwinther): Use this in [NativeBehavior] instead of calling the |
359 // `ForeignResolver`. | 359 // `ForeignResolver`. |
360 // TODO(johnniwinther): Cache the result to avoid redundant lookups? | 360 // TODO(johnniwinther): Cache the result to avoid redundant lookups? |
361 DartType _typeLookup(String typeName) { | 361 TypeLookup _typeLookup({bool resolveAsRaw: true}) { |
362 DartType findIn(Uri uri) { | 362 return (String typeName) { |
363 LibraryElement library = _compiler.libraryLoader.lookupLibrary(uri); | 363 DartType findIn(Uri uri) { |
364 if (library != null) { | 364 LibraryElement library = _compiler.libraryLoader.lookupLibrary(uri); |
365 Element element = library.find(typeName); | 365 if (library != null) { |
366 if (element != null && element.isClass) { | 366 Element element = library.find(typeName); |
367 ClassElement cls = element; | 367 if (element != null && element.isClass) { |
368 return cls.rawType; | 368 ClassElement cls = element; |
| 369 // TODO(johnniwinther): Align semantics. |
| 370 return resolveAsRaw ? cls.rawType : cls.thisType; |
| 371 } |
369 } | 372 } |
| 373 return null; |
370 } | 374 } |
371 return null; | |
372 } | |
373 | 375 |
374 DartType type = findIn(Uris.dart_core); | 376 DartType type = findIn(Uris.dart_core); |
375 type ??= findIn(BackendHelpers.DART_JS_HELPER); | 377 type ??= findIn(BackendHelpers.DART_JS_HELPER); |
376 type ??= findIn(BackendHelpers.DART_INTERCEPTORS); | 378 type ??= findIn(BackendHelpers.DART_INTERCEPTORS); |
377 type ??= findIn(BackendHelpers.DART_ISOLATE_HELPER); | 379 type ??= findIn(BackendHelpers.DART_ISOLATE_HELPER); |
378 type ??= findIn(Uris.dart_collection); | 380 type ??= findIn(Uris.dart_collection); |
379 type ??= findIn(Uris.dart_html); | 381 type ??= findIn(Uris.dart_html); |
380 return type; | 382 type ??= findIn(Uris.dart_svg); |
| 383 type ??= findIn(Uris.dart_web_audio); |
| 384 type ??= findIn(Uris.dart_web_gl); |
| 385 return type; |
| 386 }; |
381 } | 387 } |
382 | 388 |
383 String _getStringArgument(ir.StaticInvocation node, int index) { | 389 String _getStringArgument(ir.StaticInvocation node, int index) { |
384 return node.arguments.positional[index].accept(new Stringifier()); | 390 return node.arguments.positional[index].accept(new Stringifier()); |
385 } | 391 } |
386 | 392 |
387 /// Computes the [NativeBehavior] for a call to the [JS] function. | 393 /// Computes the [NativeBehavior] for a call to the [JS] function. |
388 // TODO(johnniwinther): Cache this for later use. | 394 // TODO(johnniwinther): Cache this for later use. |
389 NativeBehavior getNativeBehaviorForJsCall(ir.StaticInvocation node) { | 395 NativeBehavior getNativeBehaviorForJsCall(ir.StaticInvocation node) { |
390 if (node.arguments.positional.length < 2 || | 396 if (node.arguments.positional.length < 2 || |
391 node.arguments.named.isNotEmpty) { | 397 node.arguments.named.isNotEmpty) { |
392 reporter.reportErrorMessage( | 398 reporter.reportErrorMessage( |
393 CURRENT_ELEMENT_SPANNABLE, MessageKind.WRONG_ARGUMENT_FOR_JS); | 399 CURRENT_ELEMENT_SPANNABLE, MessageKind.WRONG_ARGUMENT_FOR_JS); |
394 return new NativeBehavior(); | 400 return new NativeBehavior(); |
395 } | 401 } |
396 String specString = _getStringArgument(node, 0); | 402 String specString = _getStringArgument(node, 0); |
397 if (specString == null) { | 403 if (specString == null) { |
398 reporter.reportErrorMessage( | 404 reporter.reportErrorMessage( |
399 CURRENT_ELEMENT_SPANNABLE, MessageKind.WRONG_ARGUMENT_FOR_JS_FIRST); | 405 CURRENT_ELEMENT_SPANNABLE, MessageKind.WRONG_ARGUMENT_FOR_JS_FIRST); |
400 return new NativeBehavior(); | 406 return new NativeBehavior(); |
401 } | 407 } |
402 | 408 |
403 String codeString = _getStringArgument(node, 1); | 409 String codeString = _getStringArgument(node, 1); |
404 if (codeString == null) { | 410 if (codeString == null) { |
405 reporter.reportErrorMessage( | 411 reporter.reportErrorMessage( |
406 CURRENT_ELEMENT_SPANNABLE, MessageKind.WRONG_ARGUMENT_FOR_JS_SECOND); | 412 CURRENT_ELEMENT_SPANNABLE, MessageKind.WRONG_ARGUMENT_FOR_JS_SECOND); |
407 return new NativeBehavior(); | 413 return new NativeBehavior(); |
408 } | 414 } |
409 | 415 |
410 return NativeBehavior.ofJsCall(specString, codeString, _typeLookup, | 416 return NativeBehavior.ofJsCall( |
411 CURRENT_ELEMENT_SPANNABLE, reporter, _compiler.coreTypes); | 417 specString, |
| 418 codeString, |
| 419 _typeLookup(resolveAsRaw: true), |
| 420 CURRENT_ELEMENT_SPANNABLE, |
| 421 reporter, |
| 422 _compiler.coreTypes); |
412 } | 423 } |
413 | 424 |
414 /// Computes the [NativeBehavior] for a call to the [JS_BUILTIN] function. | 425 /// Computes the [NativeBehavior] for a call to the [JS_BUILTIN] function. |
415 // TODO(johnniwinther): Cache this for later use. | 426 // TODO(johnniwinther): Cache this for later use. |
416 NativeBehavior getNativeBehaviorForJsBuiltinCall(ir.StaticInvocation node) { | 427 NativeBehavior getNativeBehaviorForJsBuiltinCall(ir.StaticInvocation node) { |
417 if (node.arguments.positional.length < 1) { | 428 if (node.arguments.positional.length < 1) { |
418 reporter.internalError( | 429 reporter.internalError( |
419 CURRENT_ELEMENT_SPANNABLE, "JS builtin expression has no type."); | 430 CURRENT_ELEMENT_SPANNABLE, "JS builtin expression has no type."); |
420 return new NativeBehavior(); | 431 return new NativeBehavior(); |
421 } | 432 } |
422 if (node.arguments.positional.length < 2) { | 433 if (node.arguments.positional.length < 2) { |
423 reporter.internalError( | 434 reporter.internalError( |
424 CURRENT_ELEMENT_SPANNABLE, "JS builtin is missing name."); | 435 CURRENT_ELEMENT_SPANNABLE, "JS builtin is missing name."); |
425 return new NativeBehavior(); | 436 return new NativeBehavior(); |
426 } | 437 } |
427 String specString = _getStringArgument(node, 0); | 438 String specString = _getStringArgument(node, 0); |
428 if (specString == null) { | 439 if (specString == null) { |
429 reporter.internalError( | 440 reporter.internalError( |
430 CURRENT_ELEMENT_SPANNABLE, "Unexpected first argument."); | 441 CURRENT_ELEMENT_SPANNABLE, "Unexpected first argument."); |
431 return new NativeBehavior(); | 442 return new NativeBehavior(); |
432 } | 443 } |
433 return NativeBehavior.ofJsBuiltinCall(specString, _typeLookup, | 444 return NativeBehavior.ofJsBuiltinCall( |
434 CURRENT_ELEMENT_SPANNABLE, reporter, _compiler.coreTypes); | 445 specString, |
| 446 _typeLookup(resolveAsRaw: true), |
| 447 CURRENT_ELEMENT_SPANNABLE, |
| 448 reporter, |
| 449 _compiler.coreTypes); |
435 } | 450 } |
436 | 451 |
437 /// Computes the [NativeBehavior] for a call to the [JS_EMBEDDED_GLOBAL] | 452 /// Computes the [NativeBehavior] for a call to the [JS_EMBEDDED_GLOBAL] |
438 /// function. | 453 /// function. |
439 // TODO(johnniwinther): Cache this for later use. | 454 // TODO(johnniwinther): Cache this for later use. |
440 NativeBehavior getNativeBehaviorForJsEmbeddedGlobalCall( | 455 NativeBehavior getNativeBehaviorForJsEmbeddedGlobalCall( |
441 ir.StaticInvocation node) { | 456 ir.StaticInvocation node) { |
442 if (node.arguments.positional.length < 1) { | 457 if (node.arguments.positional.length < 1) { |
443 reporter.internalError(CURRENT_ELEMENT_SPANNABLE, | 458 reporter.internalError(CURRENT_ELEMENT_SPANNABLE, |
444 "JS embedded global expression has no type."); | 459 "JS embedded global expression has no type."); |
445 return new NativeBehavior(); | 460 return new NativeBehavior(); |
446 } | 461 } |
447 if (node.arguments.positional.length < 2) { | 462 if (node.arguments.positional.length < 2) { |
448 reporter.internalError( | 463 reporter.internalError( |
449 CURRENT_ELEMENT_SPANNABLE, "JS embedded global is missing name."); | 464 CURRENT_ELEMENT_SPANNABLE, "JS embedded global is missing name."); |
450 return new NativeBehavior(); | 465 return new NativeBehavior(); |
451 } | 466 } |
452 if (node.arguments.positional.length > 2 || | 467 if (node.arguments.positional.length > 2 || |
453 node.arguments.named.isNotEmpty) { | 468 node.arguments.named.isNotEmpty) { |
454 reporter.internalError(CURRENT_ELEMENT_SPANNABLE, | 469 reporter.internalError(CURRENT_ELEMENT_SPANNABLE, |
455 "JS embedded global has more than 2 arguments."); | 470 "JS embedded global has more than 2 arguments."); |
456 return new NativeBehavior(); | 471 return new NativeBehavior(); |
457 } | 472 } |
458 String specString = _getStringArgument(node, 0); | 473 String specString = _getStringArgument(node, 0); |
459 if (specString == null) { | 474 if (specString == null) { |
460 reporter.internalError( | 475 reporter.internalError( |
461 CURRENT_ELEMENT_SPANNABLE, "Unexpected first argument."); | 476 CURRENT_ELEMENT_SPANNABLE, "Unexpected first argument."); |
462 return new NativeBehavior(); | 477 return new NativeBehavior(); |
463 } | 478 } |
464 return NativeBehavior.ofJsEmbeddedGlobalCall(specString, _typeLookup, | 479 return NativeBehavior.ofJsEmbeddedGlobalCall( |
465 CURRENT_ELEMENT_SPANNABLE, reporter, _compiler.coreTypes); | 480 specString, |
| 481 _typeLookup(resolveAsRaw: true), |
| 482 CURRENT_ELEMENT_SPANNABLE, |
| 483 reporter, |
| 484 _compiler.coreTypes); |
466 } | 485 } |
467 | 486 |
468 /// Returns `true` is [node] has a `@Native(...)` annotation. | 487 /// Returns `true` is [node] has a `@Native(...)` annotation. |
469 // TODO(johnniwinther): Cache this for later use. | 488 // TODO(johnniwinther): Cache this for later use. |
470 bool isNative(ir.Class node) { | 489 bool isNative(ir.Class node) { |
471 for (ir.Expression annotation in node.annotations) { | 490 for (ir.Expression annotation in node.annotations) { |
472 if (annotation is ir.ConstructorInvocation) { | 491 if (annotation is ir.ConstructorInvocation) { |
473 ConstructorElement target = getElement(annotation.target).declaration; | 492 ConstructorElement target = getElement(annotation.target).declaration; |
474 if (target.enclosingClass == | 493 if (target.enclosingClass == |
475 _compiler.commonElements.nativeAnnotationClass) { | 494 _compiler.commonElements.nativeAnnotationClass) { |
476 return true; | 495 return true; |
477 } | 496 } |
478 } | 497 } |
479 } | 498 } |
480 return false; | 499 return false; |
481 } | 500 } |
482 | 501 |
483 /// Computes the native behavior for reading the native [field]. | 502 /// Computes the native behavior for reading the native [field]. |
484 // TODO(johnniwinther): Cache this for later use. | 503 // TODO(johnniwinther): Cache this for later use. |
485 NativeBehavior getNativeBehaviorForFieldLoad(ir.Field field) { | 504 NativeBehavior getNativeBehaviorForFieldLoad(ir.Field field) { |
486 DartType type = getDartType(field.type); | 505 DartType type = getDartType(field.type); |
487 List<ConstantExpression> metadata = getMetadata(field.annotations); | 506 List<ConstantExpression> metadata = getMetadata(field.annotations); |
488 return NativeBehavior.ofFieldLoad( | 507 return NativeBehavior.ofFieldLoad(CURRENT_ELEMENT_SPANNABLE, type, metadata, |
489 CURRENT_ELEMENT_SPANNABLE, type, metadata, _typeLookup, _compiler, | 508 _typeLookup(resolveAsRaw: false), _compiler, |
490 isJsInterop: false); | 509 isJsInterop: false); |
491 } | 510 } |
492 | 511 |
493 /// Computes the native behavior for writing to the native [field]. | 512 /// Computes the native behavior for writing to the native [field]. |
494 // TODO(johnniwinther): Cache this for later use. | 513 // TODO(johnniwinther): Cache this for later use. |
495 NativeBehavior getNativeBehaviorForFieldStore(ir.Field field) { | 514 NativeBehavior getNativeBehaviorForFieldStore(ir.Field field) { |
496 DartType type = getDartType(field.type); | 515 DartType type = getDartType(field.type); |
497 return NativeBehavior.ofFieldStore(type, _compiler.resolution); | 516 return NativeBehavior.ofFieldStore(type, _compiler.resolution); |
498 } | 517 } |
499 | 518 |
500 /// Computes the native behavior for calling [procedure]. | 519 /// Computes the native behavior for calling [procedure]. |
501 // TODO(johnniwinther): Cache this for later use. | 520 // TODO(johnniwinther): Cache this for later use. |
502 NativeBehavior getNativeBehaviorForMethod(ir.Procedure procedure) { | 521 NativeBehavior getNativeBehaviorForMethod(ir.Procedure procedure) { |
503 DartType type = getFunctionType(procedure.function); | 522 DartType type = getFunctionType(procedure.function); |
504 List<ConstantExpression> metadata = getMetadata(procedure.annotations); | 523 List<ConstantExpression> metadata = getMetadata(procedure.annotations); |
505 return NativeBehavior.ofMethod( | 524 return NativeBehavior.ofMethod(CURRENT_ELEMENT_SPANNABLE, type, metadata, |
506 CURRENT_ELEMENT_SPANNABLE, type, metadata, _typeLookup, _compiler, | 525 _typeLookup(resolveAsRaw: false), _compiler, |
507 isJsInterop: false); | 526 isJsInterop: false); |
508 } | 527 } |
509 } | 528 } |
510 | 529 |
511 /// Kinds of foreign functions. | 530 /// Kinds of foreign functions. |
512 enum ForeignKind { | 531 enum ForeignKind { |
513 JS, | 532 JS, |
514 JS_BUILTIN, | 533 JS_BUILTIN, |
515 JS_EMBEDDED_GLOBAL, | 534 JS_EMBEDDED_GLOBAL, |
516 JS_INTERCEPTOR_CONSTANT, | 535 JS_INTERCEPTOR_CONSTANT, |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
632 return new ConstructedConstantExpression( | 651 return new ConstructedConstantExpression( |
633 constructor.enclosingClass.thisType.createInstantiation(typeArguments), | 652 constructor.enclosingClass.thisType.createInstantiation(typeArguments), |
634 constructor, | 653 constructor, |
635 new CallStructure( | 654 new CallStructure( |
636 node.arguments.positional.length + argumentNames.length, | 655 node.arguments.positional.length + argumentNames.length, |
637 argumentNames), | 656 argumentNames), |
638 arguments); | 657 arguments); |
639 } | 658 } |
640 | 659 |
641 @override | 660 @override |
| 661 ConstantExpression visitStaticGet(ir.StaticGet node) { |
| 662 Element element = astAdapter.getMember(node.target); |
| 663 if (element.isField) { |
| 664 return new VariableConstantExpression(element); |
| 665 } |
| 666 astAdapter.reporter.internalError( |
| 667 CURRENT_ELEMENT_SPANNABLE, "Unexpected constant target: $element."); |
| 668 return null; |
| 669 } |
| 670 |
| 671 @override |
642 ConstantExpression visitStringLiteral(ir.StringLiteral node) { | 672 ConstantExpression visitStringLiteral(ir.StringLiteral node) { |
643 return new StringConstantExpression(node.value); | 673 return new StringConstantExpression(node.value); |
644 } | 674 } |
645 } | 675 } |
OLD | NEW |