#!/usr/bin/env dart // Copyright (c) 2022, 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. import 'dart:io'; import 'package:kernel/binary/tag.dart'; import 'package:kernel/kernel.dart'; import 'package:kernel/binary/ast_from_binary.dart'; void main(List args) { List sum = List.filled(255, 0); List> expressionAverages = []; List> initializerAverages = []; List> statementAverages = []; List> typeAverages = []; for (String arg in args) { if (!new File(arg).existsSync()) { print("'$arg' doesn't exist. Skipping."); continue; } List bytes = new File(arg).readAsBytesSync(); try { Component p = new Component(); WrappedBinaryBuilder wrappedBinaryBuilder = new WrappedBinaryBuilder( bytes, )..readComponent(p); expressionAverages.add(average(wrappedBinaryBuilder.expressionTypes)); initializerAverages.add(average(wrappedBinaryBuilder.initializerTypes)); statementAverages.add(average(wrappedBinaryBuilder.statementTypes)); typeAverages.add(average(wrappedBinaryBuilder.typeTypes)); sumInto(sum, wrappedBinaryBuilder.expressionTypes); sumInto(sum, wrappedBinaryBuilder.initializerTypes); sumInto(sum, wrappedBinaryBuilder.statementTypes); sumInto(sum, wrappedBinaryBuilder.typeTypes); } catch (e) { print( "Error when reading '$arg'. Dill file expected.\n" "Got error: '$e'.\n\n" "Skipping.", ); continue; } } printSummary("Expressions: ", expressionAverages, sum); print(""); printSummary("Initializers: ", initializerAverages, sum); print(""); printSummary("Statements: ", statementAverages, sum); print(""); printSummary("Types: ", typeAverages, sum); } void printSummary( String headline, List> data, List totalRead, ) { if (data.isEmpty) { print("$headline: No data."); return; } int length = data.first.length; List summedPercentages = List.filled(length, 0); List minPercentages = List.filled(length, -1); List maxPercentages = List.filled(length, -1); for (List run in data) { assert(run.length == length); for (int i = 0; i < length; i++) { summedPercentages[i] += run[i]; if (run[i] < minPercentages[i] || minPercentages[i] < 0) { minPercentages[i] = run[i]; } if (run[i] > maxPercentages[i]) { maxPercentages[i] = run[i]; } } } print(headline); List printMe = []; for (int i = 0; i < length; i++) { double average = summedPercentages[i] / data.length; if (summedPercentages[i] == 0) continue; String? tagName = getNameOfTag(i); String tagNameExtra = tagName == null ? "" : " ($tagName) "; if (minPercentages[i] != maxPercentages[i]) { printMe.add( new SortableDataString( average, "$i$tagNameExtra: ${formatPercent(average)} (" "${formatPercent(minPercentages[i])} - " "${formatPercent(maxPercentages[i])}) (" "${totalRead[i]} totally recorded).", ), ); } else { printMe.add( new SortableDataString( average, "$i$tagNameExtra: " "${formatPercent(average)} (" "${totalRead[i]} totally recorded).", ), ); } } printMe.sort(); for (int i = printMe.length - 1; i >= 0; i--) { SortableDataString entry = printMe[i]; print(entry.value); } } class SortableDataString implements Comparable { final double data; final String value; new(this.data, this.value); @override String toString() => value; @override int compareTo(SortableDataString other) => data.compareTo(other.data); } String formatPercent(double d) { return "${(d * 100).toStringAsFixed(2)}%"; } List average(List data) { final int length = data.length; final int sum = data.fold(0, (int soFar, int value) => soFar + value); List result = List.filled(length, 0); if (sum <= 0) return result; for (int i = 0; i < length; i++) { int count = data[i]; if (count > 0) result[i] = count / sum; } return result; } void sumInto(List sumInto, List addThis) { if (sumInto.length != addThis.length) throw "Not same size."; for (int i = 0; i < sumInto.length; i++) { sumInto[i] += addThis[i]; } } class WrappedBinaryBuilder extends BinaryBuilder { List expressionTypes = List.filled(255, 0); List initializerTypes = List.filled(255, 0); List statementTypes = List.filled(255, 0); List typeTypes = List.filled(255, 0); new(_bytes) : super( _bytes, disableLazyReading: true, disableLazyClassReading: true, useGrowableLists: false, ); @override Expression readExpression() { int tagByte = peekByte(); int tag = tagByte & Tag.SpecializedTagHighBits == Tag.SpecializedTagHighBits ? (tagByte & Tag.SpecializedTagMask) : tagByte; expressionTypes[tag]++; return super.readExpression(); } @override Initializer readInitializer() { int tagByte = peekByte(); initializerTypes[tagByte]++; return super.readInitializer(); } @override Statement readStatement() { int tagByte = peekByte(); statementTypes[tagByte]++; return super.readStatement(); } @override DartType readDartType({bool forSupertype = false}) { int tagByte = peekByte(); typeTypes[tagByte]++; return super.readDartType(forSupertype: forSupertype); } } String? getNameOfTag(int tag) { if (tag == Tag.InvalidInitializer) return "InvalidInitializer"; if (tag == Tag.FieldInitializer) return "FieldInitializer"; if (tag == Tag.SuperInitializer) return "SuperInitializer"; if (tag == Tag.RedirectingInitializer) return "RedirectingInitializer"; if (tag == Tag.LocalInitializer) return "LocalInitializer"; if (tag == Tag.AssertInitializer) return "AssertInitializer"; if (tag == Tag.CheckLibraryIsLoaded) return "CheckLibraryIsLoaded"; if (tag == Tag.LoadLibrary) return "LoadLibrary"; if (tag == Tag.EqualsNull) return "EqualsNull"; if (tag == Tag.EqualsCall) return "EqualsCall"; if (tag == Tag.StaticTearOff) return "StaticTearOff"; if (tag == Tag.ConstStaticInvocation) return "ConstStaticInvocation"; if (tag == Tag.InvalidExpression) return "InvalidExpression"; if (tag == Tag.VariableGet) return "VariableGet"; if (tag == Tag.VariableSet) return "VariableSet"; if (tag == Tag.AbstractSuperPropertyGet) return "AbstractSuperPropertyGet"; if (tag == Tag.AbstractSuperPropertySet) return "AbstractSuperPropertySet"; if (tag == Tag.SuperPropertyGet) return "SuperPropertyGet"; if (tag == Tag.SuperPropertySet) return "SuperPropertySet"; if (tag == Tag.StaticGet) return "StaticGet"; if (tag == Tag.StaticSet) return "StaticSet"; if (tag == Tag.AbstractSuperMethodInvocation) { return "AbstractSuperMethodInvocation"; } if (tag == Tag.SuperMethodInvocation) return "SuperMethodInvocation"; if (tag == Tag.StaticInvocation) return "StaticInvocation"; if (tag == Tag.ConstructorInvocation) return "ConstructorInvocation"; if (tag == Tag.ConstConstructorInvocation) { return "ConstConstructorInvocation"; } if (tag == Tag.Not) return "Not"; if (tag == Tag.LogicalExpression) return "LogicalExpression"; if (tag == Tag.ConditionalExpression) return "ConditionalExpression"; if (tag == Tag.StringConcatenation) return "StringConcatenation"; if (tag == Tag.IsExpression) return "IsExpression"; if (tag == Tag.AsExpression) return "AsExpression"; if (tag == Tag.StringLiteral) return "StringLiteral"; if (tag == Tag.DoubleLiteral) return "DoubleLiteral"; if (tag == Tag.TrueLiteral) return "TrueLiteral"; if (tag == Tag.FalseLiteral) return "FalseLiteral"; if (tag == Tag.NullLiteral) return "NullLiteral"; if (tag == Tag.SymbolLiteral) return "SymbolLiteral"; if (tag == Tag.TypeLiteral) return "TypeLiteral"; if (tag == Tag.ThisExpression) return "ThisExpression"; if (tag == Tag.Rethrow) return "Rethrow"; if (tag == Tag.Throw) return "Throw"; if (tag == Tag.ListLiteral) return "ListLiteral"; if (tag == Tag.MapLiteral) return "MapLiteral"; if (tag == Tag.AwaitExpression) return "AwaitExpression"; if (tag == Tag.FunctionExpression) return "FunctionExpression"; if (tag == Tag.Let) return "Let"; if (tag == Tag.Instantiation) return "Instantiation"; if (tag == Tag.PositiveIntLiteral) return "PositiveIntLiteral"; if (tag == Tag.NegativeIntLiteral) return "NegativeIntLiteral"; if (tag == Tag.BigIntLiteral) return "BigIntLiteral"; if (tag == Tag.ConstListLiteral) return "ConstListLiteral"; if (tag == Tag.ConstMapLiteral) return "ConstMapLiteral"; if (tag == Tag.ConstructorTearOff) return "ConstructorTearOff"; if (tag == Tag.BlockExpression) return "BlockExpression"; if (tag == Tag.TypedefTearOff) return "TypedefTearOff"; if (tag == Tag.RedirectingFactoryTearOff) return "RedirectingFactoryTearOff"; if (tag == Tag.RecordIndexGet) return "RecordIndexGet"; if (tag == Tag.RecordNameGet) return "RecordNameGet"; if (tag == Tag.RecordLiteral) return "RecordLiteral"; if (tag == Tag.ConstRecordLiteral) return "ConstRecordLiteral"; if (tag == Tag.ConstantExpression) return "ConstantExpression"; if (tag == Tag.SetLiteral) return "SetLiteral"; if (tag == Tag.ConstSetLiteral) return "ConstSetLiteral"; if (tag == Tag.ListConcatenation) return "ListConcatenation"; if (tag == Tag.SetConcatenation) return "SetConcatenation"; if (tag == Tag.MapConcatenation) return "MapConcatenation"; if (tag == Tag.InstanceCreation) return "InstanceCreation"; if (tag == Tag.FileUriExpression) return "FileUriExpression"; if (tag == Tag.NullCheck) return "NullCheck"; if (tag == Tag.InstanceGet) return "InstanceGet"; if (tag == Tag.InstanceSet) return "InstanceSet"; if (tag == Tag.InstanceInvocation) return "InstanceInvocation"; if (tag == Tag.InstanceGetterInvocation) return "InstanceGetterInvocation"; if (tag == Tag.InstanceTearOff) return "InstanceTearOff"; if (tag == Tag.DynamicGet) return "DynamicGet"; if (tag == Tag.DynamicSet) return "DynamicSet"; if (tag == Tag.DynamicInvocation) return "DynamicInvocation"; if (tag == Tag.FunctionInvocation) return "FunctionInvocation"; if (tag == Tag.FunctionTearOff) return "FunctionTearOff"; if (tag == Tag.LocalFunctionInvocation) return "LocalFunctionInvocation"; if (tag == Tag.SpecializedVariableGet) return "SpecializedVariableGet"; if (tag == Tag.SpecializedVariableSet) return "SpecializedVariableSet"; if (tag == Tag.SpecializedIntLiteral) return "SpecializedIntLiteral"; if (tag == Tag.ExpressionStatement) return "ExpressionStatement"; if (tag == Tag.Block) return "Block"; if (tag == Tag.EmptyStatement) return "EmptyStatement"; if (tag == Tag.AssertStatement) return "AssertStatement"; if (tag == Tag.LabeledStatement) return "LabeledStatement"; if (tag == Tag.BreakStatement) return "BreakStatement"; if (tag == Tag.WhileStatement) return "WhileStatement"; if (tag == Tag.DoStatement) return "DoStatement"; if (tag == Tag.ForStatement) return "ForStatement"; if (tag == Tag.ForInStatement) return "ForInStatement"; if (tag == Tag.SwitchStatement) return "SwitchStatement"; if (tag == Tag.ContinueSwitchStatement) return "ContinueSwitchStatement"; if (tag == Tag.IfStatement) return "IfStatement"; if (tag == Tag.ReturnStatement) return "ReturnStatement"; if (tag == Tag.TryCatch) return "TryCatch"; if (tag == Tag.TryFinally) return "TryFinally"; if (tag == Tag.YieldStatement) return "YieldStatement"; if (tag == Tag.VariableStatement) return "VariableStatement"; if (tag == Tag.FunctionDeclaration) return "FunctionDeclaration"; if (tag == Tag.AsyncForInStatement) return "AsyncForInStatement"; if (tag == Tag.AssertBlock) return "AssertBlock"; if (tag == Tag.TypedefType) return "TypedefType"; if (tag == Tag.InvalidType) return "InvalidType"; if (tag == Tag.DynamicType) return "DynamicType"; if (tag == Tag.VoidType) return "VoidType"; if (tag == Tag.InterfaceType) return "InterfaceType"; if (tag == Tag.FunctionType) return "FunctionType"; if (tag == Tag.TypeParameterType) return "TypeParameterType"; if (tag == Tag.SimpleInterfaceType) return "SimpleInterfaceType"; if (tag == Tag.SimpleFunctionType) return "SimpleFunctionType"; if (tag == Tag.NeverType) return "NeverType"; if (tag == Tag.IntersectionType) return "IntersectionType"; if (tag == Tag.RecordType) return "RecordType"; if (tag == Tag.ExtensionType) return "ExtensionType"; if (tag == Tag.VariableDeclaration) return "VariableDeclaration"; if (tag == Tag.LocalVariable) return "LocalVariable"; if (tag == Tag.LateVariable) return "LateVariable"; if (tag == Tag.SyntheticVariable) return "SyntheticVariable"; if (tag == Tag.CatchVariable) return "CatchVariable"; if (tag == Tag.PositionalParameter) return "PositionalParameter"; if (tag == Tag.NamedParameter) return "NamedParameter"; if (tag == Tag.ThisVariable) return "ThisVariable"; if (tag == Tag.LegacyVariable) return "LegacyVariable"; return null; }