From aa8145a03daffa327eb0aa03f77e472b33aabfb3 Mon Sep 17 00:00:00 2001 From: Vyacheslav Egorov Date: Thu, 16 Aug 2018 12:30:56 +0000 Subject: [PATCH] [vm/kernel] Add a transformation that annotates invocations with receiver type. Currently we only annotate those call-sites that would result in generic covariant checks performed on the callee side. Bug: https://github.com/dart-lang/sdk/issues/31798 Change-Id: Ifcf60032036575f615015d716276484a7c1236b3 Reviewed-on: https://dart-review.googlesource.com/69580 Commit-Queue: Vyacheslav Egorov Reviewed-by: Kevin Millikin Reviewed-by: Martin Kustermann --- .../lib/src/kernel/dart2js_target.dart | 6 +- pkg/dev_compiler/lib/src/kernel/target.dart | 6 +- .../lib/src/base/processed_options.dart | 3 +- .../lib/src/fasta/incremental_compiler.dart | 9 +- .../lib/src/fasta/kernel/kernel_target.dart | 12 ++- pkg/front_end/lib/src/fasta/kernel/utils.dart | 1 + pkg/front_end/lib/src/fasta/messages.dart | 5 +- .../lib/src/incremental/kernel_driver.dart | 3 +- pkg/front_end/test/fasta/testing/suite.dart | 12 +-- pkg/kernel/lib/target/targets.dart | 47 ++-------- pkg/vm/bin/dump_kernel.dart | 4 + pkg/vm/lib/incremental_compiler.dart | 2 + pkg/vm/lib/metadata/call_site_attributes.dart | 42 +++++++++ pkg/vm/lib/target/vm.dart | 18 ++-- .../transformations/call_site_annotator.dart | 88 +++++++++++++++++++ .../testcases/bytecode/closures.dart.expect | 4 +- .../frontend/kernel_binary_flowgraph.h | 4 +- .../frontend/kernel_translation_helper.cc | 28 ++++++ .../frontend/kernel_translation_helper.h | 24 +++++ 19 files changed, 238 insertions(+), 80 deletions(-) create mode 100644 pkg/vm/lib/metadata/call_site_attributes.dart create mode 100644 pkg/vm/lib/transformations/call_site_annotator.dart diff --git a/pkg/compiler/lib/src/kernel/dart2js_target.dart b/pkg/compiler/lib/src/kernel/dart2js_target.dart index 891f7926d5b3..e6d05b3d7150 100644 --- a/pkg/compiler/lib/src/kernel/dart2js_target.dart +++ b/pkg/compiler/lib/src/kernel/dart2js_target.dart @@ -45,14 +45,10 @@ class Dart2jsTarget extends Target { bool get errorOnUnexactWebIntLiterals => true; @override - void performModularTransformationsOnLibraries( + void performModularTransformationsOnLibraries(ir.Component component, CoreTypes coreTypes, ClassHierarchy hierarchy, List libraries, {void logger(String msg)}) {} - @override - void performGlobalTransformations(CoreTypes coreTypes, ir.Component component, - {void logger(String msg)}) {} - @override ir.Expression instantiateInvocation( CoreTypes coreTypes, diff --git a/pkg/dev_compiler/lib/src/kernel/target.dart b/pkg/dev_compiler/lib/src/kernel/target.dart index 56f5b5f188e0..ea955ac1c978 100644 --- a/pkg/dev_compiler/lib/src/kernel/target.dart +++ b/pkg/dev_compiler/lib/src/kernel/target.dart @@ -64,14 +64,10 @@ class DevCompilerTarget extends Target { bool get enableNoSuchMethodForwarders => true; @override - void performModularTransformationsOnLibraries( + void performModularTransformationsOnLibraries(Component component, CoreTypes coreTypes, ClassHierarchy hierarchy, List libraries, {void logger(String msg)}) {} - @override - void performGlobalTransformations(CoreTypes coreTypes, Component component, - {void logger(String msg)}) {} - @override Expression instantiateInvocation(CoreTypes coreTypes, Expression receiver, String name, Arguments arguments, int offset, bool isSuper) { diff --git a/pkg/front_end/lib/src/base/processed_options.dart b/pkg/front_end/lib/src/base/processed_options.dart index c4086f79de05..61d1e6bf04f6 100644 --- a/pkg/front_end/lib/src/base/processed_options.dart +++ b/pkg/front_end/lib/src/base/processed_options.dart @@ -375,7 +375,8 @@ class ProcessedOptions { /// Helper to load a .dill file from [uri] using the existing [nameRoot]. Component loadComponent(List bytes, CanonicalName nameRoot) { - Component component = new Component(nameRoot: nameRoot); + Component component = + target.configureComponent(new Component(nameRoot: nameRoot)); // TODO(ahe): Pass file name to BinaryBuilder. // TODO(ahe): Control lazy loading via an option. new BinaryBuilder(bytes, filename: null, disableLazyReading: false) diff --git a/pkg/front_end/lib/src/fasta/incremental_compiler.dart b/pkg/front_end/lib/src/fasta/incremental_compiler.dart index 4bdff1a57d3b..88fbeafbf243 100644 --- a/pkg/front_end/lib/src/fasta/incremental_compiler.dart +++ b/pkg/front_end/lib/src/fasta/incremental_compiler.dart @@ -245,8 +245,8 @@ class IncrementalCompiler implements IncrementalKernelGenerator { } userCode.loader.builders.clear(); userCode = userCodeOld; - return new Component( - libraries: compiledLibraries, uriToSource: {}); + return context.options.target.configureComponent(new Component( + libraries: compiledLibraries, uriToSource: {})); } if (componentWithDill != null) { this.invalidatedUris.clear(); @@ -281,7 +281,8 @@ class IncrementalCompiler implements IncrementalKernelGenerator { } // This is the incremental component. - return new Component(libraries: outputLibraries, uriToSource: uriToSource) + return context.options.target.configureComponent( + new Component(libraries: outputLibraries, uriToSource: uriToSource)) ..mainMethod = mainMethod; }); } @@ -348,7 +349,7 @@ class IncrementalCompiler implements IncrementalKernelGenerator { if (summaryBytes != null) { ticker.logMs("Read ${c.options.sdkSummary}"); - data.component = new Component(); + data.component = c.options.target.configureComponent(new Component()); new BinaryBuilder(summaryBytes, disableLazyReading: false) .readComponent(data.component); ticker.logMs("Deserialized ${c.options.sdkSummary}"); diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart index 483f0650e1a9..52eb21b581f0 100644 --- a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart +++ b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart @@ -392,8 +392,11 @@ class KernelTarget extends TargetImplementation { this.uriToSource.forEach(copySource); dillTarget.loader.uriToSource.forEach(copySource); - Component component = new Component( - nameRoot: nameRoot, libraries: libraries, uriToSource: uriToSource); + Component component = CompilerContext.current.options.target + .configureComponent(new Component( + nameRoot: nameRoot, + libraries: libraries, + uriToSource: uriToSource)); if (loader.first != null) { // TODO(sigmund): do only for full program Declaration declaration = @@ -601,7 +604,8 @@ class KernelTarget extends TargetImplementation { libraries.add(library.target); } } - Component plaformLibraries = new Component(); + Component plaformLibraries = CompilerContext.current.options.target + .configureComponent(new Component()); // Add libraries directly to prevent that their parents are changed. plaformLibraries.libraries.addAll(libraries); loader.computeCoreTypes(plaformLibraries); @@ -728,7 +732,7 @@ class KernelTarget extends TargetImplementation { /// libraries for the first time. void runBuildTransformations() { backendTarget.performModularTransformationsOnLibraries( - loader.coreTypes, loader.hierarchy, loader.libraries, + component, loader.coreTypes, loader.hierarchy, loader.libraries, logger: (String msg) => ticker.logMs(msg)); } diff --git a/pkg/front_end/lib/src/fasta/kernel/utils.dart b/pkg/front_end/lib/src/fasta/kernel/utils.dart index c799f7ef6c1b..239709ce32f5 100644 --- a/pkg/front_end/lib/src/fasta/kernel/utils.dart +++ b/pkg/front_end/lib/src/fasta/kernel/utils.dart @@ -92,6 +92,7 @@ List serializeProcedure(Procedure procedure) { procedure.parent = fakeLibrary; } + // TODO(vegorov) find a way to preserve metadata. Component program = new Component(libraries: [fakeLibrary]); return serializeComponent(program); } diff --git a/pkg/front_end/lib/src/fasta/messages.dart b/pkg/front_end/lib/src/fasta/messages.dart index 397ce96b821c..a6895531794f 100644 --- a/pkg/front_end/lib/src/fasta/messages.dart +++ b/pkg/front_end/lib/src/fasta/messages.dart @@ -34,8 +34,9 @@ Location getLocationFromNode(TreeNode node) { parent = parent.parent; } if (parent is Library) { - Component component = - new Component(uriToSource: CompilerContext.current.uriToSource); + Component component = CompilerContext.current.options.target + .configureComponent( + new Component(uriToSource: CompilerContext.current.uriToSource)); component.libraries.add(parent); parent.parent = component; Location result = node.location; diff --git a/pkg/front_end/lib/src/incremental/kernel_driver.dart b/pkg/front_end/lib/src/incremental/kernel_driver.dart index 3de52a2a7af8..c23eb4e2c1cd 100644 --- a/pkg/front_end/lib/src/incremental/kernel_driver.dart +++ b/pkg/front_end/lib/src/incremental/kernel_driver.dart @@ -418,7 +418,8 @@ class KernelDriver { List bytes = _byteStore.get(kernelKey); if (bytes != null) { return _logger.runAsync('Read serialized libraries', () async { - var component = new Component(nameRoot: nameRoot); + var component = _options.target + .configureComponent(new Component(nameRoot: nameRoot)); _readComponent(component, bytes); await appendNewDillLibraries(component); diff --git a/pkg/front_end/test/fasta/testing/suite.dart b/pkg/front_end/test/fasta/testing/suite.dart index b23f99858c63..26527d446320 100644 --- a/pkg/front_end/test/fasta/testing/suite.dart +++ b/pkg/front_end/test/fasta/testing/suite.dart @@ -342,20 +342,14 @@ class TestVmTarget extends VmTarget { String get name => "vm"; - void performModularTransformationsOnLibraries( + @override + void performModularTransformationsOnLibraries(Component component, CoreTypes coreTypes, ClassHierarchy hierarchy, List libraries, {void logger(String msg)}) { if (enabled) { super.performModularTransformationsOnLibraries( - coreTypes, hierarchy, libraries, + component, coreTypes, hierarchy, libraries, logger: logger); } } - - void performGlobalTransformations(CoreTypes coreTypes, Component component, - {void logger(String msg)}) { - if (enabled) { - super.performGlobalTransformations(coreTypes, component, logger: logger); - } - } } diff --git a/pkg/kernel/lib/target/targets.dart b/pkg/kernel/lib/target/targets.dart index 9604ad8a74f0..38e7c2e887f3 100644 --- a/pkg/kernel/lib/target/targets.dart +++ b/pkg/kernel/lib/target/targets.dart @@ -103,48 +103,11 @@ abstract class Target { /// slowing down compilation. void performOutlineTransformations(Component component) {} - /// Perform target-specific modular transformations on the given component. - /// - /// These transformations should not be whole-component transformations. They - /// should expect that the component will contain external libraries. - void performModularTransformationsOnComponent( - CoreTypes coreTypes, ClassHierarchy hierarchy, Component component, - {void logger(String msg)}) { - performModularTransformationsOnLibraries( - coreTypes, hierarchy, component.libraries, - logger: logger); - } - /// Perform target-specific modular transformations on the given libraries. - /// - /// The intent of this method is to perform the transformations only on some - /// subset of the component libraries and avoid packing them into a temporary - /// [Component] instance to pass into [performModularTransformationsOnComponent]. - /// - /// Note that the following should be equivalent: - /// - /// target.performModularTransformationsOnComponent(coreTypes, component); - /// - /// and - /// - /// target.performModularTransformationsOnLibraries( - /// coreTypes, component.libraries); - void performModularTransformationsOnLibraries( + void performModularTransformationsOnLibraries(Component component, CoreTypes coreTypes, ClassHierarchy hierarchy, List libraries, {void logger(String msg)}); - /// Perform target-specific whole-program transformations. - /// - /// These transformations should be optimizations and not required for - /// correctness. Everything should work if a simple and fast linker chooses - /// not to apply these transformations. - /// - /// Note that [performGlobalTransformations] doesn't have -OnComponent and - /// -OnLibraries alternatives, because the global knowledge required by the - /// transformations is assumed to be retrieved from a [Component] instance. - void performGlobalTransformations(CoreTypes coreTypes, Component component, - {void logger(String msg)}); - /// Perform target-specific modular transformations on the given program. /// /// This is used when an individual expression is compiled, e.g. for debugging @@ -226,6 +189,10 @@ abstract class Target { return new InvalidExpression(message)..fileOffset = offset; } + /// Configure the given [Component] in a target specific way. + /// Returns the configured component. + Component configureComponent(Component component) => component; + String toString() => 'Target($name)'; } @@ -237,11 +204,9 @@ class NoneTarget extends Target { bool get strongMode => flags.strongMode; String get name => 'none'; List get extraRequiredLibraries => []; - void performModularTransformationsOnLibraries( + void performModularTransformationsOnLibraries(Component component, CoreTypes coreTypes, ClassHierarchy hierarchy, List libraries, {void logger(String msg)}) {} - void performGlobalTransformations(CoreTypes coreTypes, Component component, - {void logger(String msg)}) {} @override Expression instantiateInvocation(CoreTypes coreTypes, Expression receiver, diff --git a/pkg/vm/bin/dump_kernel.dart b/pkg/vm/bin/dump_kernel.dart index 2add7634fe12..f49a33279118 100644 --- a/pkg/vm/bin/dump_kernel.dart +++ b/pkg/vm/bin/dump_kernel.dart @@ -17,6 +17,9 @@ import 'package:vm/metadata/procedure_attributes.dart' import 'package:vm/metadata/unreachable.dart' show UnreachableNodeMetadataRepository; +import 'package:vm/metadata/call_site_attributes.dart' + show CallSiteAttributesMetadataRepository; + final String _usage = ''' Usage: dump_kernel input.dill output.txt Dumps kernel binary file with VM-specific metadata. @@ -39,6 +42,7 @@ main(List arguments) async { component.addMetadataRepository(new ProcedureAttributesMetadataRepository()); component.addMetadataRepository(new UnreachableNodeMetadataRepository()); component.addMetadataRepository(new BytecodeMetadataRepository()); + component.addMetadataRepository(new CallSiteAttributesMetadataRepository()); final List bytes = new File(input).readAsBytesSync(); new BinaryBuilderWithMetadata(bytes).readComponent(component); diff --git a/pkg/vm/lib/incremental_compiler.dart b/pkg/vm/lib/incremental_compiler.dart index f52a72a38f3e..8238343cda7a 100644 --- a/pkg/vm/lib/incremental_compiler.dart +++ b/pkg/vm/lib/incremental_compiler.dart @@ -56,6 +56,8 @@ class IncrementalCompiler { combined[library.importUri] = library; } } + + // TODO(vegorov) this needs to merge metadata repositories from deltas. return new Component(libraries: combined.values.toList()) ..mainMethod = mainMethod; } diff --git a/pkg/vm/lib/metadata/call_site_attributes.dart b/pkg/vm/lib/metadata/call_site_attributes.dart new file mode 100644 index 000000000000..2a9fc0341789 --- /dev/null +++ b/pkg/vm/lib/metadata/call_site_attributes.dart @@ -0,0 +1,42 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +library vm.metadata.call_site_attributes; + +import 'package:kernel/ast.dart'; + +/// Metadata for annotating call sites with various attributes. +class CallSiteAttributesMetadata { + final DartType receiverType; + + const CallSiteAttributesMetadata({this.receiverType}); + + @override + String toString() => "receiverType:$receiverType"; +} + +/// Repository for [CallSiteAttributesMetadata]. +class CallSiteAttributesMetadataRepository + extends MetadataRepository { + static final repositoryTag = 'vm.call-site-attributes.metadata'; + + @override + final String tag = repositoryTag; + + @override + final Map mapping = + {}; + + @override + void writeToBinary( + CallSiteAttributesMetadata metadata, Node node, BinarySink sink) { + sink.writeDartType(metadata.receiverType); + } + + @override + CallSiteAttributesMetadata readFromBinary(Node node, BinarySource source) { + final type = source.readDartType(); + return new CallSiteAttributesMetadata(receiverType: type); + } +} diff --git a/pkg/vm/lib/target/vm.dart b/pkg/vm/lib/target/vm.dart index 71eb1caff4ca..0889b465716d 100644 --- a/pkg/vm/lib/target/vm.dart +++ b/pkg/vm/lib/target/vm.dart @@ -14,6 +14,8 @@ import 'package:kernel/transformations/mixin_full_resolution.dart' import 'package:kernel/transformations/continuation.dart' as transformAsync show transformLibraries, transformProcedure; +import '../transformations/call_site_annotator.dart' as callSiteAnnotator; + /// Specializes the kernel IR to the Dart VM. class VmTarget extends Target { final TargetFlags flags; @@ -56,7 +58,7 @@ class VmTarget extends Target { ]; @override - void performModularTransformationsOnLibraries( + void performModularTransformationsOnLibraries(Component component, CoreTypes coreTypes, ClassHierarchy hierarchy, List libraries, {void logger(String msg)}) { transformMixins.transformLibraries(this, coreTypes, hierarchy, libraries, @@ -66,11 +68,11 @@ class VmTarget extends Target { // TODO(kmillikin): Make this run on a per-method basis. transformAsync.transformLibraries(coreTypes, libraries, flags.syncAsync); logger?.call("Transformed async methods"); - } - @override - void performGlobalTransformations(CoreTypes coreTypes, Component component, - {void logger(String msg)}) {} + callSiteAnnotator.transformLibraries( + component, libraries, coreTypes, hierarchy); + logger?.call("Annotated call sites"); + } @override void performTransformationsOnProcedure( @@ -284,4 +286,10 @@ class VmTarget extends Target { @override bool get nativeExtensionExpectsString => true; + + @override + Component configureComponent(Component component) { + callSiteAnnotator.addRepositoryTo(component); + return super.configureComponent(component); + } } diff --git a/pkg/vm/lib/transformations/call_site_annotator.dart b/pkg/vm/lib/transformations/call_site_annotator.dart new file mode 100644 index 000000000000..dd87e57f2c49 --- /dev/null +++ b/pkg/vm/lib/transformations/call_site_annotator.dart @@ -0,0 +1,88 @@ +// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +// This transformation annotates call sites with the receiver type. +// This is done to avoid reimplementing [Expression.getStaticType] in +// C++. +// We don't annotate all call-sites, but only those where VM could benefit from +// knowing static type of the receiver. +library vm.transformations.call_site_annotator; + +import 'package:kernel/ast.dart'; +import 'package:kernel/class_hierarchy.dart' show ClassHierarchy; +import 'package:kernel/core_types.dart' show CoreTypes; +import 'package:kernel/type_environment.dart' show TypeEnvironment; + +import '../metadata/call_site_attributes.dart'; + +CallSiteAttributesMetadataRepository addRepositoryTo(Component component) { + return component.metadata.putIfAbsent( + CallSiteAttributesMetadataRepository.repositoryTag, + () => new CallSiteAttributesMetadataRepository()); +} + +void transformLibraries(Component component, List libraries, + CoreTypes coreTypes, ClassHierarchy hierarchy) { + final transformer = + new AnnotateWithStaticTypes(component, coreTypes, hierarchy); + libraries.forEach(transformer.visitLibrary); +} + +class AnnotateWithStaticTypes extends RecursiveVisitor { + final CallSiteAttributesMetadataRepository _metadata; + final TypeEnvironment env; + + AnnotateWithStaticTypes( + Component component, CoreTypes coreTypes, ClassHierarchy hierarchy) + : _metadata = addRepositoryTo(component), + env = new TypeEnvironment(coreTypes, hierarchy, strongMode: true); + + @override + visitProcedure(Procedure proc) { + if (!proc.isStatic) { + env.thisType = proc.enclosingClass?.thisType; + } + super.visitProcedure(proc); + env.thisType = null; + } + + @override + visitConstructor(Constructor proc) { + env.thisType = proc.enclosingClass?.thisType; + super.visitConstructor(proc); + env.thisType = null; + } + + @override + visitMethodInvocation(MethodInvocation node) { + super.visitMethodInvocation(node); + + if (shouldAnnotate(node)) { + _metadata.mapping[node] = new CallSiteAttributesMetadata( + receiverType: node.receiver.getStaticType(env)); + } + } + + // TODO(vegorov) handle setters as well. + static bool shouldAnnotate(MethodInvocation node) => + node.interfaceTarget != null && + hasGenericCovariantParameters(node.interfaceTarget); + + /// Return [true] if the given list of [VariableDeclaration] contains + /// any annotated with generic-covariant-impl. + static bool containsGenericCovariantImpl(List decls) => + decls.any((p) => p.isGenericCovariantImpl); + + /// Returns [true] if the given [member] has any parameters annotated with + /// generic-covariant-impl attribute. + static bool hasGenericCovariantParameters(Member member) { + if (member is Procedure) { + return containsGenericCovariantImpl( + member.function.positionalParameters) || + containsGenericCovariantImpl(member.function.namedParameters); + } + + return false; + } +} diff --git a/pkg/vm/testcases/bytecode/closures.dart.expect b/pkg/vm/testcases/bytecode/closures.dart.expect index 9fe49260117b..b05d8a6a76fb 100644 --- a/pkg/vm/testcases/bytecode/closures.dart.expect +++ b/pkg/vm/testcases/bytecode/closures.dart.expect @@ -1056,8 +1056,8 @@ Closure CP#25 { core::List getI = []; core::List setI = []; for (core::int i = 0; i.{core::num::<}(10); i = i.{core::num::+}(1)) { - getI.{core::List::add}(() → core::int => i.{core::num::+}(delta)); - setI.{core::List::add}((core::int ii) → core::Null { + [@vm.call-site-attributes.metadata=receiverType:dart.core::List] getI.{core::List::add}(() → core::int => i.{core::num::+}(delta)); + [@vm.call-site-attributes.metadata=receiverType:dart.core::List] setI.{core::List::add}((core::int ii) → core::Null { i = ii.{core::num::+}(delta); }); } diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h index 50bc69367552..8178218ffefa 100644 --- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h +++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h @@ -44,7 +44,8 @@ class StreamingFlowGraphBuilder : public KernelReaderHelper { #endif // defined(DART_USE_INTERPRETER) direct_call_metadata_helper_(this), inferred_type_metadata_helper_(this), - procedure_attributes_metadata_helper_(this) { + procedure_attributes_metadata_helper_(this), + call_site_attributes_metadata_helper_(this, &type_translator_) { } virtual ~StreamingFlowGraphBuilder() {} @@ -366,6 +367,7 @@ class StreamingFlowGraphBuilder : public KernelReaderHelper { DirectCallMetadataHelper direct_call_metadata_helper_; InferredTypeMetadataHelper inferred_type_metadata_helper_; ProcedureAttributesMetadataHelper procedure_attributes_metadata_helper_; + CallSiteAttributesMetadataHelper call_site_attributes_metadata_helper_; friend class KernelLoader; diff --git a/runtime/vm/compiler/frontend/kernel_translation_helper.cc b/runtime/vm/compiler/frontend/kernel_translation_helper.cc index 02047bdf3058..14a60fe1cfdf 100644 --- a/runtime/vm/compiler/frontend/kernel_translation_helper.cc +++ b/runtime/vm/compiler/frontend/kernel_translation_helper.cc @@ -1670,6 +1670,34 @@ ProcedureAttributesMetadataHelper::GetProcedureAttributes( return metadata; } +CallSiteAttributesMetadataHelper::CallSiteAttributesMetadataHelper( + KernelReaderHelper* helper, + TypeTranslator* type_translator) + : MetadataHelper(helper, tag(), /* precompiler_only = */ false), + type_translator_(*type_translator) {} + +bool CallSiteAttributesMetadataHelper::ReadMetadata( + intptr_t node_offset, + CallSiteAttributesMetadata* metadata) { + intptr_t md_offset = GetNextMetadataPayloadOffset(node_offset); + if (md_offset < 0) { + return false; + } + + AlternativeReadingScope alt(&helper_->reader_, &H.metadata_payloads(), + md_offset); + + metadata->receiver_type = &type_translator_.BuildType(); + return true; +} + +CallSiteAttributesMetadata +CallSiteAttributesMetadataHelper::GetCallSiteAttributes(intptr_t node_offset) { + CallSiteAttributesMetadata metadata; + ReadMetadata(node_offset, &metadata); + return metadata; +} + intptr_t KernelReaderHelper::ReaderOffset() const { return reader_.offset(); } diff --git a/runtime/vm/compiler/frontend/kernel_translation_helper.h b/runtime/vm/compiler/frontend/kernel_translation_helper.h index ea2f79b18365..cac95bc45bd6 100644 --- a/runtime/vm/compiler/frontend/kernel_translation_helper.h +++ b/runtime/vm/compiler/frontend/kernel_translation_helper.h @@ -16,6 +16,7 @@ namespace dart { namespace kernel { class KernelReaderHelper; +class TypeTranslator; class TranslationHelper { public: @@ -900,6 +901,28 @@ class ProcedureAttributesMetadataHelper : public MetadataHelper { DISALLOW_COPY_AND_ASSIGN(ProcedureAttributesMetadataHelper); }; +struct CallSiteAttributesMetadata { + const AbstractType* receiver_type = nullptr; +}; + +// Helper class which provides access to direct call metadata. +class CallSiteAttributesMetadataHelper : public MetadataHelper { + public: + static const char* tag() { return "vm.call-site-attributes.metadata"; } + + CallSiteAttributesMetadataHelper(KernelReaderHelper* helper, + TypeTranslator* type_translator); + + CallSiteAttributesMetadata GetCallSiteAttributes(intptr_t node_offset); + + private: + bool ReadMetadata(intptr_t node_offset, CallSiteAttributesMetadata* metadata); + + TypeTranslator& type_translator_; + + DISALLOW_COPY_AND_ASSIGN(CallSiteAttributesMetadataHelper); +}; + class KernelReaderHelper { public: KernelReaderHelper(Zone* zone, @@ -1019,6 +1042,7 @@ class KernelReaderHelper { intptr_t data_program_offset_; friend class ClassHelper; + friend class CallSiteAttributesMetadataHelper; friend class ConstantEvaluator; friend class ConstantHelper; friend class ConstructorHelper;