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

Side by Side Diff: pkg/compiler/lib/src/ssa/kernel_ast_adapter.dart

Issue 2467493003: Compute NativeBehavior for native methods and fields. (Closed)
Patch Set: Remove commented code. Created 4 years, 1 month 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/ssa/builder.dart ('k') | pkg/compiler/lib/src/ssa/kernel_impact.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) 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 '../common.dart'; 8 import '../common.dart';
8 import '../common/names.dart'; 9 import '../common/names.dart';
9 import '../compiler.dart'; 10 import '../compiler.dart';
10 import '../constants/values.dart'; 11 import '../constants/values.dart';
11 import '../dart_types.dart'; 12 import '../dart_types.dart';
12 import '../elements/elements.dart'; 13 import '../elements/elements.dart';
13 import '../js_backend/backend_helpers.dart'; 14 import '../js_backend/backend_helpers.dart';
14 import '../js_backend/js_backend.dart'; 15 import '../js_backend/js_backend.dart';
15 import '../kernel/kernel.dart'; 16 import '../kernel/kernel.dart';
16 import '../kernel/kernel_debug.dart'; 17 import '../kernel/kernel_debug.dart';
(...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after
278 .inferredReturnTypeForElement(_backend.helpers.assertThrow, _compiler); 279 .inferredReturnTypeForElement(_backend.helpers.assertThrow, _compiler);
279 280
280 DartType getDartType(ir.DartType type) { 281 DartType getDartType(ir.DartType type) {
281 return type.accept(_typeConverter); 282 return type.accept(_typeConverter);
282 } 283 }
283 284
284 List<DartType> getDartTypes(List<ir.DartType> types) { 285 List<DartType> getDartTypes(List<ir.DartType> types) {
285 return types.map(getDartType).toList(); 286 return types.map(getDartType).toList();
286 } 287 }
287 288
289 /// Computes the function type corresponding the signature of [node].
290 FunctionType getFunctionType(ir.FunctionNode node) {
291 DartType returnType = getDartType(node.returnType);
292 List<DartType> parameterTypes = <DartType>[];
293 List<DartType> optionalParameterTypes = <DartType>[];
294 for (ir.VariableDeclaration variable in node.positionalParameters) {
295 if (parameterTypes.length == node.requiredParameterCount) {
296 optionalParameterTypes.add(getDartType(variable.type));
297 } else {
298 parameterTypes.add(getDartType(variable.type));
299 }
300 }
301 List<String> namedParameters = <String>[];
302 List<DartType> namedParameterTypes = <DartType>[];
303 List<ir.VariableDeclaration> sortedNamedParameters =
304 node.namedParameters.toList()..sort((a, b) => a.name.compareTo(b.name));
305 for (ir.VariableDeclaration variable in sortedNamedParameters) {
306 namedParameters.add(variable.name);
307 namedParameterTypes.add(getDartType(variable.type));
308 }
309 return new FunctionType.synthesized(returnType, parameterTypes,
310 optionalParameterTypes, namedParameters, namedParameterTypes);
311 }
312
313 /// Converts [annotations] into a list of [ConstantExpression]s.
314 List<ConstantExpression> getMetadata(List<ir.Expression> annotations) {
315 List<ConstantExpression> metadata = <ConstantExpression>[];
316 annotations.forEach((ir.Expression node) {
317 ConstantExpression constant = node.accept(new Constantifier(this));
318 if (constant == null) {
319 throw new UnsupportedError(
320 'No constant for ${DebugPrinter.prettyPrint(node)}');
321 }
322 metadata.add(constant);
323 });
324 return metadata;
325 }
326
327 /// Compute the kind of foreign helper function called by [node], if any.
288 @override 328 @override
289 ForeignKind getForeignKind(ir.StaticInvocation node) { 329 ForeignKind getForeignKind(ir.StaticInvocation node) {
290 if (isForeignLibrary(node.target.enclosingLibrary)) { 330 if (isForeignLibrary(node.target.enclosingLibrary)) {
291 switch (node.target.name.name) { 331 switch (node.target.name.name) {
292 case BackendHelpers.JS: 332 case BackendHelpers.JS:
293 return ForeignKind.JS; 333 return ForeignKind.JS;
294 case BackendHelpers.JS_BUILTIN: 334 case BackendHelpers.JS_BUILTIN:
295 return ForeignKind.JS_BUILTIN; 335 return ForeignKind.JS_BUILTIN;
296 case BackendHelpers.JS_EMBEDDED_GLOBAL: 336 case BackendHelpers.JS_EMBEDDED_GLOBAL:
297 return ForeignKind.JS_EMBEDDED_GLOBAL; 337 return ForeignKind.JS_EMBEDDED_GLOBAL;
298 case BackendHelpers.JS_INTERCEPTOR_CONSTANT: 338 case BackendHelpers.JS_INTERCEPTOR_CONSTANT:
299 return ForeignKind.JS_INTERCEPTOR_CONSTANT; 339 return ForeignKind.JS_INTERCEPTOR_CONSTANT;
300 } 340 }
301 } 341 }
302 return ForeignKind.NONE; 342 return ForeignKind.NONE;
303 } 343 }
304 344
345 /// Return `true` if [node] is the `dart:_foregin_helper` library.
Harry Terkelsen 2016/11/01 17:26:27 foreign_helper
Johnni Winther 2016/11/02 15:16:27 Done.
305 bool isForeignLibrary(ir.Library node) { 346 bool isForeignLibrary(ir.Library node) {
306 return node.importUri == BackendHelpers.DART_FOREIGN_HELPER; 347 return node.importUri == BackendHelpers.DART_FOREIGN_HELPER;
307 } 348 }
308 349
350 /// Looks up [typeName] for use in the spec-string of a `JS` called.
351 // TODO(johnniwinther): Use this in [NativeBehavior] instead of calling the
352 // `ForeignResolver`.
353 // TODO(johnniwinther): Cache the result to avoid redundany lookups?
Harry Terkelsen 2016/11/01 17:26:27 redundant
Johnni Winther 2016/11/02 15:16:27 Done.
309 DartType _typeLookup(String typeName) { 354 DartType _typeLookup(String typeName) {
310 DartType findIn(Uri uri) { 355 DartType findIn(Uri uri) {
311 LibraryElement library = _compiler.libraryLoader.lookupLibrary(uri); 356 LibraryElement library = _compiler.libraryLoader.lookupLibrary(uri);
312 if (library != null) { 357 if (library != null) {
313 Element element = library.find(typeName); 358 Element element = library.find(typeName);
314 if (element != null && element.isClass) { 359 if (element != null && element.isClass) {
315 ClassElement cls = element; 360 ClassElement cls = element;
316 return cls.rawType; 361 return cls.rawType;
317 } 362 }
318 } 363 }
319 return null; 364 return null;
320 } 365 }
321 366
322 DartType type = findIn(Uris.dart_core); 367 DartType type = findIn(Uris.dart_core);
323 type ??= findIn(BackendHelpers.DART_JS_HELPER); 368 type ??= findIn(BackendHelpers.DART_JS_HELPER);
324 type ??= findIn(BackendHelpers.DART_INTERCEPTORS); 369 type ??= findIn(BackendHelpers.DART_INTERCEPTORS);
325 type ??= findIn(BackendHelpers.DART_ISOLATE_HELPER); 370 type ??= findIn(BackendHelpers.DART_ISOLATE_HELPER);
326 type ??= findIn(Uris.dart_collection); 371 type ??= findIn(Uris.dart_collection);
327 type ??= findIn(Uris.dart_html); 372 type ??= findIn(Uris.dart_html);
328 return type; 373 return type;
329 } 374 }
330 375
376 /// Computes the [NativeBehavior] for a call to the [JS] function.
377 // TODO(johnniwinther): Cache this for later use.
331 NativeBehavior getNativeBehaviorForJsCall(ir.StaticInvocation node) { 378 NativeBehavior getNativeBehaviorForJsCall(ir.StaticInvocation node) {
332 if (node.arguments.positional.length < 2 || 379 if (node.arguments.positional.length < 2 ||
333 node.arguments.named.isNotEmpty) { 380 node.arguments.named.isNotEmpty) {
334 reporter.reportErrorMessage( 381 reporter.reportErrorMessage(
335 CURRENT_ELEMENT_SPANNABLE, MessageKind.WRONG_ARGUMENT_FOR_JS); 382 CURRENT_ELEMENT_SPANNABLE, MessageKind.WRONG_ARGUMENT_FOR_JS);
336 return new NativeBehavior(); 383 return new NativeBehavior();
337 } 384 }
338 String specString = node.arguments.positional[0].accept(new Stringifier()); 385 String specString = node.arguments.positional[0].accept(new Stringifier());
339 if (specString == null) { 386 if (specString == null) {
340 reporter.reportErrorMessage( 387 reporter.reportErrorMessage(
341 CURRENT_ELEMENT_SPANNABLE, MessageKind.WRONG_ARGUMENT_FOR_JS_FIRST); 388 CURRENT_ELEMENT_SPANNABLE, MessageKind.WRONG_ARGUMENT_FOR_JS_FIRST);
342 return new NativeBehavior(); 389 return new NativeBehavior();
343 } 390 }
344 391
345 String codeString = node.arguments.positional[1].accept(new Stringifier()); 392 String codeString = node.arguments.positional[1].accept(new Stringifier());
346 if (codeString == null) { 393 if (codeString == null) {
347 reporter.reportErrorMessage( 394 reporter.reportErrorMessage(
348 CURRENT_ELEMENT_SPANNABLE, MessageKind.WRONG_ARGUMENT_FOR_JS_SECOND); 395 CURRENT_ELEMENT_SPANNABLE, MessageKind.WRONG_ARGUMENT_FOR_JS_SECOND);
349 return new NativeBehavior(); 396 return new NativeBehavior();
350 } 397 }
351 398
352 return NativeBehavior.ofJsCall(specString, codeString, _typeLookup, 399 return NativeBehavior.ofJsCall(specString, codeString, _typeLookup,
353 CURRENT_ELEMENT_SPANNABLE, reporter, _compiler.coreTypes); 400 CURRENT_ELEMENT_SPANNABLE, reporter, _compiler.coreTypes);
354 } 401 }
355 402
403 /// Computes the [NativeBehavior] for a call to the [JS_BUILTIN] function.
404 // TODO(johnniwinther): Cache this for later use.
356 NativeBehavior getNativeBehaviorForJsBuiltinCall(ir.StaticInvocation node) { 405 NativeBehavior getNativeBehaviorForJsBuiltinCall(ir.StaticInvocation node) {
357 if (node.arguments.positional.length < 1) { 406 if (node.arguments.positional.length < 1) {
358 reporter.internalError( 407 reporter.internalError(
359 CURRENT_ELEMENT_SPANNABLE, "JS builtin expression has no type."); 408 CURRENT_ELEMENT_SPANNABLE, "JS builtin expression has no type.");
360 return new NativeBehavior(); 409 return new NativeBehavior();
361 } 410 }
362 if (node.arguments.positional.length < 2) { 411 if (node.arguments.positional.length < 2) {
363 reporter.internalError( 412 reporter.internalError(
364 CURRENT_ELEMENT_SPANNABLE, "JS builtin is missing name."); 413 CURRENT_ELEMENT_SPANNABLE, "JS builtin is missing name.");
365 return new NativeBehavior(); 414 return new NativeBehavior();
366 } 415 }
367 String specString = node.arguments.positional[0].accept(new Stringifier()); 416 String specString = node.arguments.positional[0].accept(new Stringifier());
368 if (specString == null) { 417 if (specString == null) {
369 reporter.internalError( 418 reporter.internalError(
370 CURRENT_ELEMENT_SPANNABLE, "Unexpected first argument."); 419 CURRENT_ELEMENT_SPANNABLE, "Unexpected first argument.");
371 return new NativeBehavior(); 420 return new NativeBehavior();
372 } 421 }
373 return NativeBehavior.ofJsBuiltinCall(specString, _typeLookup, 422 return NativeBehavior.ofJsBuiltinCall(specString, _typeLookup,
374 CURRENT_ELEMENT_SPANNABLE, reporter, _compiler.coreTypes); 423 CURRENT_ELEMENT_SPANNABLE, reporter, _compiler.coreTypes);
375 } 424 }
376 425
426 /// Computes the [NativeBehavior] for a call to the [JS_EMBEDDED_GLOBAL]
427 /// function.
428 // TODO(johnniwinther): Cache this for later use.
377 NativeBehavior getNativeBehaviorForJsEmbeddedGlobalCall( 429 NativeBehavior getNativeBehaviorForJsEmbeddedGlobalCall(
378 ir.StaticInvocation node) { 430 ir.StaticInvocation node) {
379 if (node.arguments.positional.length < 1) { 431 if (node.arguments.positional.length < 1) {
380 reporter.internalError(CURRENT_ELEMENT_SPANNABLE, 432 reporter.internalError(CURRENT_ELEMENT_SPANNABLE,
381 "JS embedded global expression has no type."); 433 "JS embedded global expression has no type.");
382 return new NativeBehavior(); 434 return new NativeBehavior();
383 } 435 }
384 if (node.arguments.positional.length < 2) { 436 if (node.arguments.positional.length < 2) {
385 reporter.internalError( 437 reporter.internalError(
386 CURRENT_ELEMENT_SPANNABLE, "JS embedded global is missing name."); 438 CURRENT_ELEMENT_SPANNABLE, "JS embedded global is missing name.");
387 return new NativeBehavior(); 439 return new NativeBehavior();
388 } 440 }
389 if (node.arguments.positional.length > 2 || 441 if (node.arguments.positional.length > 2 ||
390 node.arguments.named.isNotEmpty) { 442 node.arguments.named.isNotEmpty) {
391 reporter.internalError(CURRENT_ELEMENT_SPANNABLE, 443 reporter.internalError(CURRENT_ELEMENT_SPANNABLE,
392 "JS embedded global has more than 2 arguments."); 444 "JS embedded global has more than 2 arguments.");
393 return new NativeBehavior(); 445 return new NativeBehavior();
394 } 446 }
395 String specString = node.arguments.positional[0].accept(new Stringifier()); 447 String specString = node.arguments.positional[0].accept(new Stringifier());
396 if (specString == null) { 448 if (specString == null) {
397 reporter.internalError( 449 reporter.internalError(
398 CURRENT_ELEMENT_SPANNABLE, "Unexpected first argument."); 450 CURRENT_ELEMENT_SPANNABLE, "Unexpected first argument.");
399 return new NativeBehavior(); 451 return new NativeBehavior();
400 } 452 }
401 return NativeBehavior.ofJsEmbeddedGlobalCall(specString, _typeLookup, 453 return NativeBehavior.ofJsEmbeddedGlobalCall(specString, _typeLookup,
402 CURRENT_ELEMENT_SPANNABLE, reporter, _compiler.coreTypes); 454 CURRENT_ELEMENT_SPANNABLE, reporter, _compiler.coreTypes);
403 } 455 }
456
457 /// Returns `true` is [node] has a `@Native(...)` annotation.
458 // TODO(johnniwinther): Cache this for later use.
459 bool isNative(ir.Class node) {
460 for (ir.Expression annotation in node.annotations) {
461 if (annotation is ir.ConstructorInvocation) {
462 ConstructorElement target = getElement(annotation.target).declaration;
463 if (target.enclosingClass ==
464 _compiler.commonElements.nativeAnnotationClass) {
465 return true;
466 }
467 }
468 }
469 return false;
470 }
471
472 /// Computes the native behavior for reading the native [field].
473 // TODO(johnniwinther): Cache this for later use.
474 NativeBehavior getNativeBehaviorForFieldLoad(ir.Field field) {
475 DartType type = getDartType(field.type);
476 List<ConstantExpression> metadata = getMetadata(field.annotations);
477 return NativeBehavior.ofFieldLoad(
478 CURRENT_ELEMENT_SPANNABLE, type, metadata, _typeLookup, _compiler,
479 isJsInterop: false);
480 }
481
482 /// Computes the native behavior for writing to the native [field].
483 // TODO(johnniwinther): Cache this for later use.
484 NativeBehavior getNativeBehaviorForFieldStore(ir.Field field) {
485 DartType type = getDartType(field.type);
486 return NativeBehavior.ofFieldStore(type, _compiler.resolution);
487 }
488
489 /// Computes the native behavior for calling [procedure].
490 // TODO(johnniwinther): Cache this for later use.
491 NativeBehavior getNativeBehaviorForMethod(ir.Procedure procedure) {
492 DartType type = getFunctionType(procedure.function);
493 List<ConstantExpression> metadata = getMetadata(procedure.annotations);
494 return NativeBehavior.ofMethod(
495 CURRENT_ELEMENT_SPANNABLE, type, metadata, _typeLookup, _compiler,
496 isJsInterop: false);
497 }
404 } 498 }
405 499
500 /// Kinds of foreign functions.
406 enum ForeignKind { 501 enum ForeignKind {
407 JS, 502 JS,
408 JS_BUILTIN, 503 JS_BUILTIN,
409 JS_EMBEDDED_GLOBAL, 504 JS_EMBEDDED_GLOBAL,
410 JS_INTERCEPTOR_CONSTANT, 505 JS_INTERCEPTOR_CONSTANT,
411 NONE, 506 NONE,
412 } 507 }
413 508
509 /// Visitor that converts kernel dart types into [DartType].
414 class DartTypeConverter extends ir.DartTypeVisitor<DartType> { 510 class DartTypeConverter extends ir.DartTypeVisitor<DartType> {
415 final KernelAstAdapter astAdapter; 511 final KernelAstAdapter astAdapter;
416 512
417 DartTypeConverter(this.astAdapter); 513 DartTypeConverter(this.astAdapter);
418 514
419 DartType visitType(ir.DartType type) => type.accept(this); 515 DartType visitType(ir.DartType type) => type.accept(this);
420 516
421 List<DartType> visitTypes(List<ir.DartType> types) { 517 List<DartType> visitTypes(List<ir.DartType> types) {
422 return new List.generate( 518 return new List.generate(
423 types.length, (int index) => types[index].accept(this)); 519 types.length, (int index) => types[index].accept(this));
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
486 String visitStringConcatenation(ir.StringConcatenation node) { 582 String visitStringConcatenation(ir.StringConcatenation node) {
487 StringBuffer sb = new StringBuffer(); 583 StringBuffer sb = new StringBuffer();
488 for (ir.Expression expression in node.expressions) { 584 for (ir.Expression expression in node.expressions) {
489 String value = expression.accept(this); 585 String value = expression.accept(this);
490 if (value == null) return null; 586 if (value == null) return null;
491 sb.write(value); 587 sb.write(value);
492 } 588 }
493 return sb.toString(); 589 return sb.toString();
494 } 590 }
495 } 591 }
592
593 /// Visitor that converts a kernel constant expression into a
594 /// [ConstantExpression].
595 class Constantifier extends ir.ExpressionVisitor<ConstantExpression> {
596 final KernelAstAdapter astAdapter;
597
598 Constantifier(this.astAdapter);
599
600 @override
601 ConstantExpression visitConstructorInvocation(ir.ConstructorInvocation node) {
602 ConstructorElement constructor =
603 astAdapter.getElement(node.target).declaration;
Harry Terkelsen 2016/11/01 17:26:27 it seems like 'getElement(...).declaration' is com
Johnni Winther 2016/11/02 15:16:27 Agree. In progress in https://codereview.chromium.
604 List<DartType> typeArguments = <DartType>[];
605 for (ir.DartType type in node.arguments.types) {
606 typeArguments.add(astAdapter.getDartType(type));
607 }
608 List<ConstantExpression> arguments = <ConstantExpression>[];
609 List<String> argumentNames = <String>[];
610 for (ir.Expression argument in node.arguments.positional) {
611 ConstantExpression constant = argument.accept(this);
612 if (constant == null) return null;
613 arguments.add(constant);
614 }
615 for (ir.NamedExpression argument in node.arguments.named) {
616 argumentNames.add(argument.name);
617 ConstantExpression constant = argument.value.accept(this);
618 if (constant == null) return null;
619 arguments.add(constant);
620 }
621 return new ConstructedConstantExpression(
622 constructor.enclosingClass.thisType.createInstantiation(typeArguments),
623 constructor,
624 new CallStructure(
625 node.arguments.positional.length + argumentNames.length,
626 argumentNames),
627 arguments);
628 }
629
630 @override
631 ConstantExpression visitStringLiteral(ir.StringLiteral node) {
632 return new StringConstantExpression(node.value);
633 }
634 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/ssa/builder.dart ('k') | pkg/compiler/lib/src/ssa/kernel_impact.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698