blob: da78cab8552b3808ca1bd84dea2402858b06db83 [file] [log] [blame]
// Copyright (c) 2017, 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.procedure_attributes;
import 'package:kernel/ast.dart';
/// Metadata for annotating procedures with various attributes.
class ProcedureAttributesMetadata {
static const int kInvalidSelectorId = 0;
final bool methodOrSetterCalledDynamically;
final bool getterCalledDynamically;
final bool hasThisUses;
final bool hasNonThisUses;
final bool hasTearOffUses;
final int methodOrSetterSelectorId;
final int getterSelectorId;
const ProcedureAttributesMetadata(
{this.methodOrSetterCalledDynamically: true,
this.getterCalledDynamically: true,
this.hasThisUses: true,
this.hasNonThisUses: true,
this.hasTearOffUses: true,
this.methodOrSetterSelectorId: kInvalidSelectorId,
this.getterSelectorId: kInvalidSelectorId});
const ProcedureAttributesMetadata.noDynamicUses()
: this(
methodOrSetterCalledDynamically: false,
getterCalledDynamically: false);
@override
String toString() {
final attrs = <String>[];
if (!methodOrSetterCalledDynamically) {
attrs.add('methodOrSetterCalledDynamically:false');
}
if (!getterCalledDynamically) attrs.add('getterCalledDynamically:false');
if (!hasThisUses) attrs.add('hasThisUses:false');
if (!hasNonThisUses) attrs.add('hasNonThisUses:false');
if (!hasTearOffUses) attrs.add('hasTearOffUses:false');
if (methodOrSetterSelectorId != kInvalidSelectorId) {
attrs.add('methodOrSetterSelectorId:$methodOrSetterSelectorId');
}
if (getterSelectorId != kInvalidSelectorId) {
attrs.add('getterSelectorId:$getterSelectorId');
}
return attrs.join(',');
}
}
/// Repository for [ProcedureAttributesMetadata].
class ProcedureAttributesMetadataRepository
extends MetadataRepository<ProcedureAttributesMetadata> {
static const int kMethodOrSetterCalledDynamicallyBit = 1 << 0;
static const int kNonThisUsesBit = 1 << 1;
static const int kTearOffUsesBit = 1 << 2;
static const int kThisUsesBit = 1 << 3;
static const int kGetterCalledDynamicallyBit = 1 << 4;
static const repositoryTag = 'vm.procedure-attributes.metadata';
@override
final String tag = repositoryTag;
@override
final Map<TreeNode, ProcedureAttributesMetadata> mapping =
<TreeNode, ProcedureAttributesMetadata>{};
int _getFlags(ProcedureAttributesMetadata metadata) {
int flags = 0;
if (metadata.methodOrSetterCalledDynamically) {
flags |= kMethodOrSetterCalledDynamicallyBit;
}
if (metadata.getterCalledDynamically) {
flags |= kGetterCalledDynamicallyBit;
}
if (metadata.hasThisUses) {
flags |= kThisUsesBit;
}
if (metadata.hasNonThisUses) {
flags |= kNonThisUsesBit;
}
if (metadata.hasTearOffUses) {
flags |= kTearOffUsesBit;
}
return flags;
}
@override
void writeToBinary(
ProcedureAttributesMetadata metadata, Node node, BinarySink sink) {
sink.writeByte(_getFlags(metadata));
sink.writeUInt30(metadata.methodOrSetterSelectorId);
sink.writeUInt30(metadata.getterSelectorId);
}
@override
ProcedureAttributesMetadata readFromBinary(Node node, BinarySource source) {
final int flags = source.readByte();
final bool methodOrSetterCalledDynamically =
(flags & kMethodOrSetterCalledDynamicallyBit) != 0;
final bool getterCalledDynamically =
(flags & kGetterCalledDynamicallyBit) != 0;
final bool hasThisUses = (flags & kThisUsesBit) != 0;
final bool hasNonThisUses = (flags & kNonThisUsesBit) != 0;
final bool hasTearOffUses = (flags & kTearOffUsesBit) != 0;
final int methodOrSetterSelectorId = source.readUInt30();
final int getterSelectorId = source.readUInt30();
return new ProcedureAttributesMetadata(
methodOrSetterCalledDynamically: methodOrSetterCalledDynamically,
getterCalledDynamically: getterCalledDynamically,
hasThisUses: hasThisUses,
hasNonThisUses: hasNonThisUses,
hasTearOffUses: hasTearOffUses,
methodOrSetterSelectorId: methodOrSetterSelectorId,
getterSelectorId: getterSelectorId);
}
}