| 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 |