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

Side by Side Diff: pkg/compiler/lib/src/kernel/element_adapter.dart

Issue 2679913006: Add KernelNativeBehaviorComputer (Closed)
Patch Set: Rebased Created 3 years, 10 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 | « no previous file | pkg/compiler/lib/src/kernel/elements.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) 2017, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2017, 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 '../common.dart'; 7 import '../common.dart';
8 import '../common/names.dart'; 8 import '../common/names.dart';
9 import '../constants/constructors.dart';
9 import '../constants/expressions.dart'; 10 import '../constants/expressions.dart';
10 import '../core_types.dart'; 11 import '../core_types.dart';
11 import '../elements/elements.dart'; 12 import '../elements/elements.dart';
12 import '../elements/entities.dart'; 13 import '../elements/entities.dart';
13 import '../elements/types.dart'; 14 import '../elements/types.dart';
14 import '../js_backend/backend_helpers.dart'; 15 import '../js_backend/backend_helpers.dart';
15 import '../native/native.dart' as native; 16 import '../native/native.dart' as native;
16 import '../universe/call_structure.dart'; 17 import '../universe/call_structure.dart';
17 import '../universe/selector.dart'; 18 import '../universe/selector.dart';
18 import 'kernel_debug.dart'; 19 import 'kernel_debug.dart';
19 20
20 /// Interface that translates between Kernel IR nodes and entities. 21 /// Interface that translates between Kernel IR nodes and entities.
21 abstract class KernelElementAdapter { 22 abstract class KernelElementAdapter {
22 /// Access to the commonly used elements and types. 23 /// Access to the commonly used elements and types.
23 CommonElements get commonElements; 24 CommonElements get commonElements;
24 25
26 /// [ElementEnvironment] for library, class and member lookup.
27 ElementEnvironment get elementEnvironment;
28
25 /// Returns the [DartType] corresponding to [type]. 29 /// Returns the [DartType] corresponding to [type].
26 DartType getDartType(ir.DartType type); 30 DartType getDartType(ir.DartType type);
27 31
28 /// Returns the list of [DartType]s corresponding to [types]. 32 /// Returns the list of [DartType]s corresponding to [types].
29 List<DartType> getDartTypes(List<ir.DartType> types); 33 List<DartType> getDartTypes(List<ir.DartType> types);
30 34
31 /// Returns the [InterfaceType] corresponding to [type]. 35 /// Returns the [InterfaceType] corresponding to [type].
32 InterfaceType getInterfaceType(ir.InterfaceType type); 36 InterfaceType getInterfaceType(ir.InterfaceType type);
33 37
34 /// Return the [InterfaceType] corresponding to the [cls] with the given 38 /// Return the [InterfaceType] corresponding to the [cls] with the given
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
109 enum ForeignKind { 113 enum ForeignKind {
110 JS, 114 JS,
111 JS_BUILTIN, 115 JS_BUILTIN,
112 JS_EMBEDDED_GLOBAL, 116 JS_EMBEDDED_GLOBAL,
113 JS_INTERCEPTOR_CONSTANT, 117 JS_INTERCEPTOR_CONSTANT,
114 NONE, 118 NONE,
115 } 119 }
116 120
117 abstract class KernelElementAdapterMixin implements KernelElementAdapter { 121 abstract class KernelElementAdapterMixin implements KernelElementAdapter {
118 DiagnosticReporter get reporter; 122 DiagnosticReporter get reporter;
119 CommonElements get commonElements; 123 FunctionType getFunctionType(ir.FunctionNode node);
120 124 native.BehaviorBuilder get nativeBehaviorBuilder;
121 LibraryEntity lookupLibrary(Uri uri);
122 ClassEntity lookupClass(LibraryEntity library, String name);
123 InterfaceType getRawType(ClassEntity cls);
124 InterfaceType getThisType(ClassEntity cls);
125 125
126 @override 126 @override
127 Name getName(ir.Name name) { 127 Name getName(ir.Name name) {
128 return new Name( 128 return new Name(
129 name.name, name.isPrivate ? getLibrary(name.library) : null); 129 name.name, name.isPrivate ? getLibrary(name.library) : null);
130 } 130 }
131 131
132 @override 132 @override
133 CallStructure getCallStructure(ir.Arguments arguments) { 133 CallStructure getCallStructure(ir.Arguments arguments) {
134 int argumentCount = arguments.positional.length + arguments.named.length; 134 int argumentCount = arguments.positional.length + arguments.named.length;
135 List<String> namedArguments = arguments.named.map((e) => e.name).toList(); 135 List<String> namedArguments = arguments.named.map((e) => e.name).toList();
136 return new CallStructure(argumentCount, namedArguments); 136 return new CallStructure(argumentCount, namedArguments);
137 } 137 }
138 138
139 @override 139 @override
140 Selector getSelector(ir.Expression node) { 140 Selector getSelector(ir.Expression node) {
141 // TODO(efortuna): This is screaming for a common interface between 141 // TODO(efortuna): This is screaming for a common interface between
142 // PropertyGet and SuperPropertyGet (and same for *Get). Talk to kernel 142 // PropertyGet and SuperPropertyGet (and same for *Get). Talk to kernel
143 // folks. 143 // folks.
144 if (node is ir.PropertyGet) { 144 if (node is ir.PropertyGet) {
145 return getGetterSelector((node as ir.PropertyGet).name); 145 return getGetterSelector(node.name);
146 } 146 }
147 if (node is ir.SuperPropertyGet) { 147 if (node is ir.SuperPropertyGet) {
148 return getGetterSelector((node as ir.SuperPropertyGet).name); 148 return getGetterSelector(node.name);
149 } 149 }
150 if (node is ir.PropertySet) { 150 if (node is ir.PropertySet) {
151 return getSetterSelector((node as ir.PropertySet).name); 151 return getSetterSelector(node.name);
152 } 152 }
153 if (node is ir.SuperPropertySet) { 153 if (node is ir.SuperPropertySet) {
154 return getSetterSelector((node as ir.SuperPropertySet).name); 154 return getSetterSelector(node.name);
155 } 155 }
156 if (node is ir.InvocationExpression) return getInvocationSelector(node); 156 if (node is ir.InvocationExpression) {
157 return getInvocationSelector(node);
158 }
157 throw new SpannableAssertionFailure( 159 throw new SpannableAssertionFailure(
158 CURRENT_ELEMENT_SPANNABLE, 160 CURRENT_ELEMENT_SPANNABLE,
159 "Can only get the selector for a property get or an invocation: " 161 "Can only get the selector for a property get or an invocation: "
160 "${node}"); 162 "${node}");
161 } 163 }
162 164
163 Selector getInvocationSelector(ir.InvocationExpression invocation) { 165 Selector getInvocationSelector(ir.InvocationExpression invocation) {
164 Name name = getName(invocation.name); 166 Name name = getName(invocation.name);
165 SelectorKind kind; 167 SelectorKind kind;
166 if (Elements.isOperatorName(invocation.name.name)) { 168 if (Elements.isOperatorName(invocation.name.name)) {
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
239 return node.importUri == BackendHelpers.DART_FOREIGN_HELPER; 241 return node.importUri == BackendHelpers.DART_FOREIGN_HELPER;
240 } 242 }
241 243
242 /// Looks up [typeName] for use in the spec-string of a `JS` called. 244 /// Looks up [typeName] for use in the spec-string of a `JS` called.
243 // TODO(johnniwinther): Use this in [native.NativeBehavior] instead of calling 245 // TODO(johnniwinther): Use this in [native.NativeBehavior] instead of calling
244 // the `ForeignResolver`. 246 // the `ForeignResolver`.
245 // TODO(johnniwinther): Cache the result to avoid redundant lookups? 247 // TODO(johnniwinther): Cache the result to avoid redundant lookups?
246 native.TypeLookup typeLookup({bool resolveAsRaw: true}) { 248 native.TypeLookup typeLookup({bool resolveAsRaw: true}) {
247 return (String typeName) { 249 return (String typeName) {
248 DartType findIn(Uri uri) { 250 DartType findIn(Uri uri) {
249 LibraryEntity library = lookupLibrary(uri); 251 LibraryEntity library = elementEnvironment.lookupLibrary(uri);
250 if (library != null) { 252 if (library != null) {
251 ClassEntity cls = lookupClass(library, typeName); 253 ClassEntity cls = elementEnvironment.lookupClass(library, typeName);
252 if (cls != null) { 254 if (cls != null) {
253 // TODO(johnniwinther): Align semantics. 255 // TODO(johnniwinther): Align semantics.
254 return resolveAsRaw ? getRawType(cls) : getThisType(cls); 256 return resolveAsRaw
257 ? elementEnvironment.getRawType(cls)
258 : elementEnvironment.getThisType(cls);
255 } 259 }
256 } 260 }
257 return null; 261 return null;
258 } 262 }
259 263
260 DartType type = findIn(Uris.dart_core); 264 DartType type = findIn(Uris.dart_core);
261 type ??= findIn(BackendHelpers.DART_JS_HELPER); 265 type ??= findIn(BackendHelpers.DART_JS_HELPER);
262 type ??= findIn(BackendHelpers.DART_INTERCEPTORS); 266 type ??= findIn(BackendHelpers.DART_INTERCEPTORS);
263 type ??= findIn(BackendHelpers.DART_ISOLATE_HELPER); 267 type ??= findIn(BackendHelpers.DART_ISOLATE_HELPER);
264 type ??= findIn(Uris.dart_collection); 268 type ??= findIn(Uris.dart_collection);
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
377 node.arguments.named.isNotEmpty) { 381 node.arguments.named.isNotEmpty) {
378 reporter.reportErrorMessage(CURRENT_ELEMENT_SPANNABLE, 382 reporter.reportErrorMessage(CURRENT_ELEMENT_SPANNABLE,
379 MessageKind.WRONG_ARGUMENT_FOR_JS_INTERCEPTOR_CONSTANT); 383 MessageKind.WRONG_ARGUMENT_FOR_JS_INTERCEPTOR_CONSTANT);
380 } 384 }
381 ir.Node argument = node.arguments.positional.first; 385 ir.Node argument = node.arguments.positional.first;
382 if (argument is ir.TypeLiteral && argument.type is ir.InterfaceType) { 386 if (argument is ir.TypeLiteral && argument.type is ir.InterfaceType) {
383 return getInterfaceType(argument.type); 387 return getInterfaceType(argument.type);
384 } 388 }
385 return null; 389 return null;
386 } 390 }
391
392 /// Computes the native behavior for reading the native [field].
393 // TODO(johnniwinther): Cache this for later use.
394 native.NativeBehavior getNativeBehaviorForFieldLoad(ir.Field field) {
395 DartType type = getDartType(field.type);
396 List<ConstantExpression> metadata = getMetadata(field.annotations);
397 // TODO(johnniwinther): Provide the correct value for [isJsInterop].
398 return nativeBehaviorBuilder.buildFieldLoadBehavior(
399 type, metadata, typeLookup(resolveAsRaw: false),
400 isJsInterop: false);
401 }
402
403 /// Computes the native behavior for writing to the native [field].
404 // TODO(johnniwinther): Cache this for later use.
405 native.NativeBehavior getNativeBehaviorForFieldStore(ir.Field field) {
406 DartType type = getDartType(field.type);
407 return nativeBehaviorBuilder.buildFieldStoreBehavior(type);
408 }
409
410 /// Computes the native behavior for calling [procedure].
411 // TODO(johnniwinther): Cache this for later use.
412 native.NativeBehavior getNativeBehaviorForMethod(ir.Procedure procedure) {
413 DartType type = getFunctionType(procedure.function);
414 List<ConstantExpression> metadata = getMetadata(procedure.annotations);
415 // TODO(johnniwinther): Provide the correct value for [isJsInterop].
416 return nativeBehaviorBuilder.buildMethodBehavior(
417 type, metadata, typeLookup(resolveAsRaw: false),
418 isJsInterop: false);
419 }
387 } 420 }
388 421
389 /// Visitor that converts string literals and concatenations of string literals 422 /// Visitor that converts string literals and concatenations of string literals
390 /// into the string value. 423 /// into the string value.
391 class Stringifier extends ir.ExpressionVisitor<String> { 424 class Stringifier extends ir.ExpressionVisitor<String> {
392 @override 425 @override
393 String visitStringLiteral(ir.StringLiteral node) => node.value; 426 String visitStringLiteral(ir.StringLiteral node) => node.value;
394 427
395 @override 428 @override
396 String visitStringConcatenation(ir.StringConcatenation node) { 429 String visitStringConcatenation(ir.StringConcatenation node) {
397 StringBuffer sb = new StringBuffer(); 430 StringBuffer sb = new StringBuffer();
398 for (ir.Expression expression in node.expressions) { 431 for (ir.Expression expression in node.expressions) {
399 String value = expression.accept(this); 432 String value = expression.accept(this);
400 if (value == null) return null; 433 if (value == null) return null;
401 sb.write(value); 434 sb.write(value);
402 } 435 }
403 return sb.toString(); 436 return sb.toString();
404 } 437 }
405 } 438 }
406 439
407 /// Visitor that converts a kernel constant expression into a 440 /// Visitor that converts a kernel constant expression into a
408 /// [ConstantExpression]. 441 /// [ConstantExpression].
409 class Constantifier extends ir.ExpressionVisitor<ConstantExpression> { 442 class Constantifier extends ir.ExpressionVisitor<ConstantExpression> {
410 final KernelElementAdapter elementAdapter; 443 final KernelElementAdapter elementAdapter;
411 444
412 Constantifier(this.elementAdapter); 445 Constantifier(this.elementAdapter);
413 446
414 @override 447 ConstantExpression defaultExpression(ir.Expression node) {
415 ConstantExpression visitConstructorInvocation(ir.ConstructorInvocation node) { 448 throw new UnimplementedError(
449 'Unimplemented constant expression $node (${node.runtimeType})');
450 }
451
452 List<ConstantExpression> _computeArguments(ir.Arguments node) {
416 List<ConstantExpression> arguments = <ConstantExpression>[]; 453 List<ConstantExpression> arguments = <ConstantExpression>[];
417 List<String> argumentNames = <String>[]; 454 for (ir.Expression argument in node.positional) {
418 for (ir.Expression argument in node.arguments.positional) {
419 ConstantExpression constant = argument.accept(this); 455 ConstantExpression constant = argument.accept(this);
420 if (constant == null) return null; 456 if (constant == null) return null;
421 arguments.add(constant); 457 arguments.add(constant);
422 } 458 }
423 for (ir.NamedExpression argument in node.arguments.named) { 459 for (ir.NamedExpression argument in node.named) {
424 argumentNames.add(argument.name);
425 ConstantExpression constant = argument.value.accept(this); 460 ConstantExpression constant = argument.value.accept(this);
426 if (constant == null) return null; 461 if (constant == null) return null;
427 arguments.add(constant); 462 arguments.add(constant);
428 } 463 }
464 return arguments;
465 }
466
467 ConstructedConstantExpression _computeConstructorInvocation(
468 ir.Constructor target, ir.Arguments arguments) {
429 return new ConstructedConstantExpression( 469 return new ConstructedConstantExpression(
430 elementAdapter.createInterfaceType( 470 elementAdapter.createInterfaceType(
431 node.target.enclosingClass, node.arguments.types), 471 target.enclosingClass, arguments.types),
432 elementAdapter.getConstructor(node.target), 472 elementAdapter.getConstructor(target),
433 new CallStructure( 473 elementAdapter.getCallStructure(arguments),
434 node.arguments.positional.length + argumentNames.length, 474 _computeArguments(arguments));
435 argumentNames),
436 arguments);
437 } 475 }
438 476
439 @override 477 @override
478 ConstantExpression visitConstructorInvocation(ir.ConstructorInvocation node) {
479 return _computeConstructorInvocation(node.target, node.arguments);
480 }
481
482 @override
483 ConstantExpression visitVariableGet(ir.VariableGet node) {
484 if (node.variable.parent is ir.FunctionNode) {
485 ir.FunctionNode function = node.variable.parent;
486 int index = function.positionalParameters.indexOf(node.variable);
487 if (index != -1) {
488 return new PositionalArgumentReference(index);
489 } else {
490 assert(function.namedParameters.contains(node.variable));
491 return new NamedArgumentReference(node.variable.name);
492 }
493 }
494 throw new UnimplementedError(
495 'Unimplemented constant expression $node (${node.runtimeType})');
496 }
497
498 @override
440 ConstantExpression visitStaticGet(ir.StaticGet node) { 499 ConstantExpression visitStaticGet(ir.StaticGet node) {
441 return new FieldConstantExpression(elementAdapter.getField(node.target)); 500 return new FieldConstantExpression(elementAdapter.getField(node.target));
442 } 501 }
443 502
444 @override 503 @override
445 ConstantExpression visitStringLiteral(ir.StringLiteral node) { 504 ConstantExpression visitStringLiteral(ir.StringLiteral node) {
446 return new StringConstantExpression(node.value); 505 return new StringConstantExpression(node.value);
447 } 506 }
507
508 /// Compute the [ConstantConstructor] corresponding to the const constructor
509 /// [node].
510 ConstantConstructor computeConstantConstructor(ir.Constructor node) {
511 assert(node.isConst);
512 ir.Class cls = node.enclosingClass;
513 InterfaceType type = elementAdapter.elementEnvironment
514 .getThisType(elementAdapter.getClass(cls));
515
516 Map<dynamic, ConstantExpression> defaultValues =
517 <dynamic, ConstantExpression>{};
518 int parameterIndex = 0;
519 node.function.positionalParameters
520 .forEach((ir.VariableDeclaration parameter) {
521 if (parameter.initializer != null) {
522 defaultValues[parameterIndex] = parameter.initializer.accept(this);
523 }
524 parameterIndex++;
525 });
526 node.function.namedParameters.forEach((ir.VariableDeclaration parameter) {
527 defaultValues[parameter.name] = parameter.initializer.accept(this);
528 });
529
530 bool isRedirecting = node.initializers.length == 1 &&
531 node.initializers.single is ir.RedirectingInitializer;
532
533 Map<FieldEntity, ConstantExpression> fieldMap =
534 <FieldEntity, ConstantExpression>{};
535
536 void registerField(ir.Field field, ConstantExpression constant) {
537 fieldMap[elementAdapter.getField(field)] = constant;
538 }
539
540 if (!isRedirecting) {
541 for (ir.Field field in cls.fields) {
542 if (field.initializer != null) {
543 registerField(field, field.initializer.accept(this));
544 }
545 }
546 }
547
548 ConstructedConstantExpression superConstructorInvocation;
549 for (ir.Initializer initializer in node.initializers) {
550 if (initializer is ir.FieldInitializer) {
551 registerField(initializer.field, initializer.value.accept(this));
552 } else if (initializer is ir.SuperInitializer) {
553 superConstructorInvocation = _computeConstructorInvocation(
554 initializer.target, initializer.arguments);
555 } else if (initializer is ir.RedirectingInitializer) {
556 superConstructorInvocation = _computeConstructorInvocation(
557 initializer.target, initializer.arguments);
558 } else {
559 throw new UnsupportedError(
560 'Unexpected initializer $node (${node.runtimeType})');
561 }
562 }
563 if (isRedirecting) {
564 return new RedirectingGenerativeConstantConstructor(
565 defaultValues, superConstructorInvocation);
566 } else {
567 return new GenerativeConstantConstructor(
568 type, defaultValues, fieldMap, superConstructorInvocation);
569 }
570 }
448 } 571 }
OLDNEW
« no previous file with comments | « no previous file | pkg/compiler/lib/src/kernel/elements.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698