Version 2.17.0-80.0.dev
Merge commit '0ec4c3a1b54cd8732795ba46c2617e0b47667d39' into 'dev'
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_completion_resolve.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_completion_resolve.dart
index d2d2bec..fa99c2b 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_completion_resolve.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_completion_resolve.dart
@@ -132,11 +132,13 @@
// the file we're importing into, rather than the full URI.
final pathContext = server.resourceProvider.pathContext;
final autoImportDisplayUri = libraryUri.isScheme('file')
- ? pathContext.relative(
+ // Compute the relative path and then put into a URI so the display
+ // always uses forward slashes (as a URI) regardless of platform.
+ ? Uri.file(pathContext.relative(
libraryUri.toFilePath(),
from: pathContext.dirname(file),
- )
- : libraryUri.toString();
+ ))
+ : libraryUri;
return success(CompletionItem(
label: item.label,
diff --git a/pkg/analysis_server/test/client/impl/completion_driver.dart b/pkg/analysis_server/test/client/impl/completion_driver.dart
index 4c4cafb..63d8ec0 100644
--- a/pkg/analysis_server/test/client/impl/completion_driver.dart
+++ b/pkg/analysis_server/test/client/impl/completion_driver.dart
@@ -125,7 +125,7 @@
Future<List<CompletionSuggestion>> getSuggestions() async {
var request = CompletionGetSuggestionsParams(
- server.testFilePath,
+ server.convertPath(server.testFilePath),
completionOffset,
).toRequest('0');
var response = await server.handleRequest(request);
@@ -138,7 +138,7 @@
Future<List<CompletionSuggestion>> getSuggestions2() async {
var request = CompletionGetSuggestions2Params(
- server.testFilePath,
+ server.convertPath(server.testFilePath),
completionOffset,
1 << 16,
timeout: 60 * 1000,
diff --git a/pkg/analysis_server/test/src/services/correction/fix/add_required_test.dart b/pkg/analysis_server/test/src/services/correction/fix/add_required_test.dart
index 1da0c9d..6aff080 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/add_required_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/add_required_test.dart
@@ -81,6 +81,25 @@
''');
}
+ Future<void> test_nonNullable_superParameter() async {
+ await resolveTestCode('''
+class C {
+ C({required int param});
+}
+class D extends C {
+ D({super.param});
+}
+''');
+ await assertHasFix('''
+class C {
+ C({required int param});
+}
+class D extends C {
+ D({required super.param});
+}
+''');
+ }
+
Future<void> test_withRequiredAnnotation() async {
writeTestPackageConfig(meta: true);
diff --git a/pkg/analysis_server/test/src/services/correction/fix/add_trailing_comma_test.dart b/pkg/analysis_server/test/src/services/correction/fix/add_trailing_comma_test.dart
index bf7c774..f8ba15b 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/add_trailing_comma_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/add_trailing_comma_test.dart
@@ -72,7 +72,22 @@
@override
String get lintCode => LintNames.require_trailing_commas;
- Future<void> test_comma() async {
+ Future<void> test_named() async {
+ await resolveTestCode('''
+void f({a, b}) {
+ f(a: 'a',
+ b: 'b');
+}
+''');
+ await assertHasFix('''
+void f({a, b}) {
+ f(a: 'a',
+ b: 'b',);
+}
+''');
+ }
+
+ Future<void> test_positional() async {
await resolveTestCode('''
void f(a, b) {
f('a',
diff --git a/pkg/analysis_server/test/src/services/correction/fix/convert_to_generic_function_syntax_test.dart b/pkg/analysis_server/test/src/services/correction/fix/convert_to_generic_function_syntax_test.dart
index d904bf6..a549699 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/convert_to_generic_function_syntax_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/convert_to_generic_function_syntax_test.dart
@@ -114,14 +114,29 @@
}
@reflectiveTest
-class UseFunctionTypeSyntaxForParametersTest extends FixProcessorLintTest
- with WithNullSafetyLintMixin {
+class UseFunctionTypeSyntaxForParametersTest extends FixProcessorLintTest {
@override
FixKind get kind => DartFixKind.CONVERT_TO_GENERIC_FUNCTION_SYNTAX;
@override
String get lintCode => LintNames.use_function_type_syntax_for_parameters;
+ @FailingTest(issue: 'https://github.com/dart-lang/linter/issues/3212')
+ Future<void> test_functionTypedParameter_fieldFormal() async {
+ await resolveTestCode('''
+class C {
+ String Function(int) f;
+ C(String this.f(int x));
+}
+''');
+ await assertHasFix('''
+class C {
+ String Function(int) f;
+ C(String Function(int x) this.f);
+}
+''');
+ }
+
Future<void> test_functionTypedParameter_noParameterTypes() async {
await resolveTestCode('''
g(String f(x)) {}
@@ -155,4 +170,24 @@
g(String Function(int x) f) {}
''');
}
+
+ @FailingTest(issue: 'https://github.com/dart-lang/linter/issues/3212')
+ Future<void> test_functionTypedParameter_superParameter() async {
+ await resolveTestCode('''
+class C {
+ C(String Function(int x) f);
+}
+class D extends C {
+ D(String super.f(int x));
+}
+''');
+ await assertHasFix('''
+class C {
+ C(String Function(int x) f);
+}
+class D extends C {
+ D(String Function(int x) super.f);
+}
+''');
+ }
}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/fix_processor.dart b/pkg/analysis_server/test/src/services/correction/fix/fix_processor.dart
index fc0eaa0..7de85d0 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/fix_processor.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/fix_processor.dart
@@ -236,6 +236,7 @@
void setUp() {
super.setUp();
createAnalysisOptionsFile(
+ experiments: experiments,
lints: [lintCode],
);
}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/remove_argument_test.dart b/pkg/analysis_server/test/src/services/correction/fix/remove_argument_test.dart
index 9d27944..c9ab551 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/remove_argument_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/remove_argument_test.dart
@@ -107,9 +107,6 @@
''');
}
- @FailingTest(
- issue: 'https://github.com/dart-lang/linter/issues/3082',
- )
Future<void> test_named_betweenRequiredPositional() async {
await resolveTestCode('''
void foo(int a, int b, {bool c = true}) {}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/remove_initializer_test.dart b/pkg/analysis_server/test/src/services/correction/fix/remove_initializer_test.dart
index 573a033..1992d3f 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/remove_initializer_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/remove_initializer_test.dart
@@ -106,6 +106,25 @@
''');
}
+ Future<void> test_parameter_super() async {
+ await resolveTestCode('''
+class C {
+ C({String? s});
+}
+class D extends C {
+ D({super.s = null});
+}
+''');
+ await assertHasFix('''
+class C {
+ C({String? s});
+}
+class D extends C {
+ D({super.s});
+}
+''');
+ }
+
Future<void> test_topLevel() async {
await resolveTestCode('''
var x = null;
diff --git a/pkg/analysis_server/test/src/services/correction/fix/remove_type_annotation_test.dart b/pkg/analysis_server/test/src/services/correction/fix/remove_type_annotation_test.dart
index f92c463..deefa32 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/remove_type_annotation_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/remove_type_annotation_test.dart
@@ -231,7 +231,7 @@
@override
String get lintCode => LintNames.type_init_formals;
- Future<void> test_void() async {
+ Future<void> test_formalFieldParameter() async {
await resolveTestCode('''
class C {
int f;
@@ -245,4 +245,23 @@
}
''');
}
+
+ @FailingTest(issue: 'https://github.com/dart-lang/linter/issues/3210')
+ Future<void> test_superParameter() async {
+ // If this issue gets closed as "won't fix," remove this test.
+ await resolveTestCode('''
+class C {
+ C(int f);
+}
+class D extends C {
+ D(int super.f);
+}
+''');
+ await assertHasFix('''
+class C {
+ int f;
+ C(super.f);
+}
+''');
+ }
}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/replace_colon_with_equals_test.dart b/pkg/analysis_server/test/src/services/correction/fix/replace_colon_with_equals_test.dart
index 6c5fb20..39f4ed5 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/replace_colon_with_equals_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/replace_colon_with_equals_test.dart
@@ -55,4 +55,23 @@
void f({int a = 1}) => null;
''');
}
+
+ Future<void> test_superParameter() async {
+ await resolveTestCode('''
+class C {
+ C({int? i});
+}
+class D extends C {
+ D({int? super.i: 1});
+}
+''');
+ await assertHasFix('''
+class C {
+ C({int? i});
+}
+class D extends C {
+ D({int? super.i = 1});
+}
+''');
+ }
}
diff --git a/pkg/analyzer/CHANGELOG.md b/pkg/analyzer/CHANGELOG.md
index a819b7f..e75af1d 100644
--- a/pkg/analyzer/CHANGELOG.md
+++ b/pkg/analyzer/CHANGELOG.md
@@ -1,5 +1,7 @@
## 3.3.0-dev
* Added `getField` to `ExtensionElement`.
+* Added `isGenerative` to `ConstructorElement`.
+* Added `isDartCoreEnum` to `ClassElement` and `DartType`.
## 3.2.0
* Deprecated `changes` getter in `File` and `Folder`, use `watch()` instead.
diff --git a/pkg/analyzer/lib/dart/element/element.dart b/pkg/analyzer/lib/dart/element/element.dart
index 2ee4830..e0478a0 100644
--- a/pkg/analyzer/lib/dart/element/element.dart
+++ b/pkg/analyzer/lib/dart/element/element.dart
@@ -104,6 +104,10 @@
/// <i>abstract</i> is different from <i>has unimplemented members</i>.
bool get isAbstract;
+ /// Return `true` if this class represents the class 'Enum' defined in the
+ /// dart:core library.
+ bool get isDartCoreEnum;
+
/// Return `true` if this class represents the class 'Object' defined in the
/// dart:core library.
bool get isDartCoreObject;
@@ -468,6 +472,9 @@
/// Return `true` if this constructor represents a factory constructor.
bool get isFactory;
+ /// Return `true` if this constructor represents a generative constructor.
+ bool get isGenerative;
+
@override
String get name;
diff --git a/pkg/analyzer/lib/dart/element/type.dart b/pkg/analyzer/lib/dart/element/type.dart
index e3f102e..2f479bd 100644
--- a/pkg/analyzer/lib/dart/element/type.dart
+++ b/pkg/analyzer/lib/dart/element/type.dart
@@ -69,6 +69,10 @@
/// dart:core library.
bool get isDartCoreDouble;
+ /// Return `true` if this type represents the type 'Enum' defined in the
+ /// dart:core library.
+ bool get isDartCoreEnum;
+
/// Return `true` if this type represents the type 'Function' defined in the
/// dart:core library.
bool get isDartCoreFunction;
diff --git a/pkg/analyzer/lib/error/error.dart b/pkg/analyzer/lib/error/error.dart
index d643def..79182f9 100644
--- a/pkg/analyzer/lib/error/error.dart
+++ b/pkg/analyzer/lib/error/error.dart
@@ -208,6 +208,7 @@
CompileTimeErrorCode.IF_ELEMENT_CONDITION_FROM_DEFERRED_LIBRARY,
CompileTimeErrorCode.ILLEGAL_ASYNC_GENERATOR_RETURN_TYPE,
CompileTimeErrorCode.ILLEGAL_ASYNC_RETURN_TYPE,
+ CompileTimeErrorCode.ILLEGAL_LANGUAGE_VERSION_OVERRIDE,
CompileTimeErrorCode.ILLEGAL_SYNC_GENERATOR_RETURN_TYPE,
CompileTimeErrorCode.IMPLEMENTS_DEFERRED_CLASS,
CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS,
diff --git a/pkg/analyzer/lib/src/dart/ast/ast.dart b/pkg/analyzer/lib/src/dart/ast/ast.dart
index 97b16e1..834d75a 100644
--- a/pkg/analyzer/lib/src/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/src/dart/ast/ast.dart
@@ -5107,6 +5107,11 @@
/// The body of the function.
FunctionBodyImpl _body;
+ /// If resolution has been performed, this boolean indicates whether a
+ /// function type was supplied via context for this function expression.
+ /// `false` if resolution hasn't been performed yet.
+ bool wasFunctionTypeSupplied = false;
+
@override
ExecutableElement? declaredElement;
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index df1d7da..b0f4037 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -125,6 +125,11 @@
}
@override
+ bool get isDartCoreEnum {
+ return name == 'Enum' && library.isDartCore;
+ }
+
+ @override
bool get isDartCoreObject => false;
@override
@@ -1473,6 +1478,11 @@
// OK, can be used as default constructor
return true;
}
+
+ @override
+ bool get isGenerative {
+ return !isFactory;
+ }
}
/// A [TopLevelVariableElement] for a top-level 'const' variable that has an
diff --git a/pkg/analyzer/lib/src/dart/element/extensions.dart b/pkg/analyzer/lib/src/dart/element/extensions.dart
index 69fc60b..decbd59 100644
--- a/pkg/analyzer/lib/src/dart/element/extensions.dart
+++ b/pkg/analyzer/lib/src/dart/element/extensions.dart
@@ -8,18 +8,6 @@
import 'package:analyzer/src/generated/utilities_dart.dart';
import 'package:meta/meta_meta.dart';
-extension ClassElementExtension on ClassElement {
- bool get isDartCoreEnum {
- return name == 'Enum' && library.isDartCore;
- }
-}
-
-extension ConstructorElementExtension on ConstructorElement {
- bool get isGenerative {
- return !isFactory;
- }
-}
-
extension ElementAnnotationExtensions on ElementAnnotation {
static final Map<String, TargetKind> _targetKindsByName = {
for (final kind in TargetKind.values) kind.toString(): kind,
@@ -121,12 +109,6 @@
}
}
-extension InterfaceTypeExtension on InterfaceType {
- bool get isDartCoreEnum {
- return element.isDartCoreEnum;
- }
-}
-
extension ParameterElementExtensions on ParameterElement {
/// Return [ParameterElement] with the specified properties replaced.
ParameterElement copyWith({
diff --git a/pkg/analyzer/lib/src/dart/element/type.dart b/pkg/analyzer/lib/src/dart/element/type.dart
index 70f398c..b367dd1 100644
--- a/pkg/analyzer/lib/src/dart/element/type.dart
+++ b/pkg/analyzer/lib/src/dart/element/type.dart
@@ -532,6 +532,11 @@
}
@override
+ bool get isDartCoreEnum {
+ return element.isDartCoreEnum;
+ }
+
+ @override
bool get isDartCoreFunction {
return element.name == "Function" && element.library.isDartCore;
}
@@ -988,6 +993,9 @@
bool get isDartCoreDouble => false;
@override
+ bool get isDartCoreEnum => false;
+
+ @override
bool get isDartCoreFunction => false;
@override
diff --git a/pkg/analyzer/lib/src/dart/resolver/assignment_expression_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/assignment_expression_resolver.dart
index 718c99b..1009c21 100644
--- a/pkg/analyzer/lib/src/dart/resolver/assignment_expression_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/assignment_expression_resolver.dart
@@ -69,13 +69,14 @@
// TODO(scheglov) Use VariableElement and do in resolveForWrite() ?
_assignmentShared.checkFinalAlreadyAssigned(left);
+ DartType? rhsContext;
{
var leftType = node.writeType;
if (writeElement is VariableElement) {
leftType = _resolver.localVariableTypeProvider
.getType(left as SimpleIdentifier, isRead: false);
}
- _setRhsContext(node, leftType!, operator, right);
+ rhsContext = _computeRhsContext(node, leftType!, operator, right);
}
var flow = _resolver.flowAnalysis.flow;
@@ -83,7 +84,7 @@
flow.ifNullExpression_rightBegin(left, node.readType!);
}
- right.accept(_resolver);
+ _resolver.analyzeExpression(right, rhsContext);
right = node.rightHandSide;
var whyNotPromoted = flow?.whyNotPromoted(right);
@@ -147,6 +148,28 @@
return true;
}
+ DartType? _computeRhsContext(AssignmentExpressionImpl node, DartType leftType,
+ TokenType operator, Expression right) {
+ switch (operator) {
+ case TokenType.EQ:
+ case TokenType.QUESTION_QUESTION_EQ:
+ return leftType;
+ case TokenType.AMPERSAND_AMPERSAND_EQ:
+ case TokenType.BAR_BAR_EQ:
+ return _typeProvider.boolType;
+ default:
+ var method = node.staticElement;
+ if (method != null) {
+ var parameters = method.parameters;
+ if (parameters.isNotEmpty) {
+ return _typeSystem.refineNumericInvocationContext(
+ leftType, method, leftType, parameters[0].type);
+ }
+ }
+ return null;
+ }
+ }
+
void _resolveOperator(AssignmentExpressionImpl node) {
var left = node.leftHandSide;
var operator = node.operator;
@@ -260,32 +283,6 @@
whyNotPromoted: whyNotPromoted);
}
}
-
- void _setRhsContext(AssignmentExpressionImpl node, DartType leftType,
- TokenType operator, Expression right) {
- switch (operator) {
- case TokenType.EQ:
- case TokenType.QUESTION_QUESTION_EQ:
- InferenceContext.setType(right, leftType);
- break;
- case TokenType.AMPERSAND_AMPERSAND_EQ:
- case TokenType.BAR_BAR_EQ:
- InferenceContext.setType(right, _typeProvider.boolType);
- break;
- default:
- var method = node.staticElement;
- if (method != null) {
- var parameters = method.parameters;
- if (parameters.isNotEmpty) {
- InferenceContext.setType(
- right,
- _typeSystem.refineNumericInvocationContext(
- leftType, method, leftType, parameters[0].type));
- }
- }
- break;
- }
- }
}
class AssignmentExpressionShared {
diff --git a/pkg/analyzer/lib/src/dart/resolver/binary_expression_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/binary_expression_resolver.dart
index ad08e2b..927a635 100644
--- a/pkg/analyzer/lib/src/dart/resolver/binary_expression_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/binary_expression_resolver.dart
@@ -140,9 +140,8 @@
if (leftContextType != null && _isNonNullableByDefault) {
leftContextType = _typeSystem.makeNullable(leftContextType);
}
- InferenceContext.setType(left, leftContextType);
- left.accept(_resolver);
+ _resolver.analyzeExpression(left, leftContextType);
left = node.leftOperand;
var leftType = left.typeOrThrow;
@@ -150,10 +149,9 @@
if (rightContextType == null || rightContextType.isDynamic) {
rightContextType = leftType;
}
- InferenceContext.setType(right, rightContextType);
flow?.ifNullExpression_rightBegin(left, leftType);
- right.accept(_resolver);
+ _resolver.analyzeExpression(right, rightContextType);
right = node.rightOperand;
flow?.ifNullExpression_end();
@@ -172,18 +170,15 @@
var right = node.rightOperand;
var flow = _resolver.flowAnalysis.flow;
- InferenceContext.setType(left, _typeProvider.boolType);
- InferenceContext.setType(right, _typeProvider.boolType);
-
flow?.logicalBinaryOp_begin();
- left.accept(_resolver);
+ _resolver.analyzeExpression(left, _typeProvider.boolType);
left = node.leftOperand;
var leftWhyNotPromoted = _resolver.flowAnalysis.flow?.whyNotPromoted(left);
flow?.logicalBinaryOp_rightBegin(left, node, isAnd: true);
_resolver.checkUnreachableNode(right);
- right.accept(_resolver);
+ _resolver.analyzeExpression(right, _typeProvider.boolType);
right = node.rightOperand;
var rightWhyNotPromoted =
_resolver.flowAnalysis.flow?.whyNotPromoted(right);
@@ -202,18 +197,15 @@
var right = node.rightOperand;
var flow = _resolver.flowAnalysis.flow;
- InferenceContext.setType(left, _typeProvider.boolType);
- InferenceContext.setType(right, _typeProvider.boolType);
-
flow?.logicalBinaryOp_begin();
- left.accept(_resolver);
+ _resolver.analyzeExpression(left, _typeProvider.boolType);
left = node.leftOperand;
var leftWhyNotPromoted = _resolver.flowAnalysis.flow?.whyNotPromoted(left);
flow?.logicalBinaryOp_rightBegin(left, node, isAnd: false);
_resolver.checkUnreachableNode(right);
- right.accept(_resolver);
+ _resolver.analyzeExpression(right, _typeProvider.boolType);
right = node.rightOperand;
var rightWhyNotPromoted =
_resolver.flowAnalysis.flow?.whyNotPromoted(right);
@@ -251,20 +243,19 @@
_resolveUserDefinableElement(node, operator.lexeme);
var invokeType = node.staticInvokeType;
+ DartType? contextType;
if (invokeType != null && invokeType.parameters.isNotEmpty) {
// If this is a user-defined operator, set the right operand context
// using the operator method's parameter type.
var rightParam = invokeType.parameters[0];
- InferenceContext.setType(
- right,
- _typeSystem.refineNumericInvocationContext(
- left.staticType,
- node.staticElement,
- InferenceContext.getContext(node),
- rightParam.type));
+ contextType = _typeSystem.refineNumericInvocationContext(
+ left.staticType,
+ node.staticElement,
+ InferenceContext.getContext(node),
+ rightParam.type);
}
- right.accept(_resolver);
+ _resolver.analyzeExpression(right, contextType);
right = node.rightOperand;
var whyNotPromoted = _resolver.flowAnalysis.flow?.whyNotPromoted(right);
diff --git a/pkg/analyzer/lib/src/dart/resolver/for_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/for_resolver.dart
index 82ca086..dceec2d 100644
--- a/pkg/analyzer/lib/src/dart/resolver/for_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/for_resolver.dart
@@ -24,11 +24,14 @@
void resolveElement(ForElementImpl node, CollectionLiteralContext? context) {
var forLoopParts = node.forLoopParts;
+ void visitBody() {
+ node.body.resolveElement(_resolver, context);
+ }
+
if (forLoopParts is ForPartsImpl) {
- _forParts(node, forLoopParts, node.body, context: context);
+ _forParts(node, forLoopParts, visitBody);
} else if (forLoopParts is ForEachPartsImpl) {
- _forEachParts(node, node.awaitKeyword != null, forLoopParts, node.body,
- context: context);
+ _forEachParts(node, node.awaitKeyword != null, forLoopParts, visitBody);
}
}
@@ -36,10 +39,14 @@
_resolver.checkUnreachableNode(node);
var forLoopParts = node.forLoopParts;
+ void visitBody() {
+ node.body.accept(_resolver);
+ }
+
if (forLoopParts is ForPartsImpl) {
- _forParts(node, forLoopParts, node.body);
+ _forParts(node, forLoopParts, visitBody);
} else if (forLoopParts is ForEachPartsImpl) {
- _forEachParts(node, node.awaitKeyword != null, forLoopParts, node.body);
+ _forEachParts(node, node.awaitKeyword != null, forLoopParts, visitBody);
}
}
@@ -68,9 +75,8 @@
}
}
- void _forEachParts(
- AstNode node, bool isAsync, ForEachParts forEachParts, AstNode body,
- {CollectionLiteralContext? context}) {
+ void _forEachParts(AstNode node, bool isAsync, ForEachParts forEachParts,
+ void Function() visitBody) {
Expression iterable = forEachParts.iterable;
DeclaredIdentifier? loopVariable;
SimpleIdentifier? identifier;
@@ -103,14 +109,14 @@
}
}
}
+ InterfaceType? targetType;
if (valueType != null) {
- InterfaceType targetType = isAsync
+ targetType = isAsync
? _resolver.typeProvider.streamType(valueType)
: _resolver.typeProvider.iterableType(valueType);
- InferenceContext.setType(iterable, targetType);
}
- iterable.accept(_resolver);
+ _resolver.analyzeExpression(iterable, targetType);
iterable = forEachParts.iterable;
_resolver.nullableDereferenceVerifier.expression(
@@ -139,13 +145,12 @@
elementType ?? DynamicTypeImpl.instance, null);
}
- _visitBody(body, context);
+ visitBody();
_resolver.flowAnalysis.flow?.forEach_end();
}
- void _forParts(AstNode node, ForParts forParts, AstNode body,
- {CollectionLiteralContext? context}) {
+ void _forParts(AstNode node, ForParts forParts, void Function() visitBody) {
if (forParts is ForPartsWithDeclarations) {
forParts.variables.accept(_resolver);
} else if (forParts is ForPartsWithExpression) {
@@ -156,8 +161,7 @@
var condition = forParts.condition;
if (condition != null) {
- InferenceContext.setType(condition, _resolver.typeProvider.boolType);
- condition.accept(_resolver);
+ _resolver.analyzeExpression(condition, _resolver.typeProvider.boolType);
condition = forParts.condition!;
var whyNotPromoted =
_resolver.flowAnalysis.flow?.whyNotPromoted(condition);
@@ -166,20 +170,11 @@
}
_resolver.flowAnalysis.for_bodyBegin(node, condition);
- _visitBody(body, context);
+ visitBody();
_resolver.flowAnalysis.flow?.for_updaterBegin();
forParts.updaters.accept(_resolver);
_resolver.flowAnalysis.flow?.for_end();
}
-
- void _visitBody(AstNode body, CollectionLiteralContext? context) {
- if (body is CollectionElementImpl) {
- body.resolveElement(_resolver, context);
- } else {
- assert(body is Statement);
- body.accept(_resolver);
- }
- }
}
diff --git a/pkg/analyzer/lib/src/dart/resolver/function_expression_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/function_expression_resolver.dart
index 7204620..94ee5b4 100644
--- a/pkg/analyzer/lib/src/dart/resolver/function_expression_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/function_expression_resolver.dart
@@ -43,8 +43,10 @@
}
var contextType = InferenceContext.getContext(node);
+ bool wasFunctionTypeSupplied = contextType is FunctionType;
+ node.wasFunctionTypeSupplied = wasFunctionTypeSupplied;
DartType? imposedType;
- if (contextType is FunctionType) {
+ if (wasFunctionTypeSupplied) {
contextType = _matchTypeParameters(
node.typeParameters,
contextType,
diff --git a/pkg/analyzer/lib/src/dart/resolver/postfix_expression_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/postfix_expression_resolver.dart
index 376a9d7..f6d223d 100644
--- a/pkg/analyzer/lib/src/dart/resolver/postfix_expression_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/postfix_expression_resolver.dart
@@ -197,14 +197,11 @@
}
var contextType = InferenceContext.getContext(node);
- if (contextType != null) {
- if (_isNonNullableByDefault) {
- contextType = _typeSystem.makeNullable(contextType);
- }
- InferenceContext.setType(operand, contextType);
+ if (contextType != null && _isNonNullableByDefault) {
+ contextType = _typeSystem.makeNullable(contextType);
}
- operand.accept(_resolver);
+ _resolver.analyzeExpression(operand, contextType);
operand = node.operand;
var operandType = operand.typeOrThrow;
diff --git a/pkg/analyzer/lib/src/dart/resolver/prefix_expression_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/prefix_expression_resolver.dart
index a108a8b..c94eb2b 100644
--- a/pkg/analyzer/lib/src/dart/resolver/prefix_expression_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/prefix_expression_resolver.dart
@@ -213,9 +213,8 @@
void _resolveNegation(PrefixExpressionImpl node) {
var operand = node.operand;
- InferenceContext.setType(operand, _typeProvider.boolType);
- operand.accept(_resolver);
+ _resolver.analyzeExpression(operand, _typeProvider.boolType);
operand = node.operand;
var whyNotPromoted = _resolver.flowAnalysis.flow?.whyNotPromoted(operand);
diff --git a/pkg/analyzer/lib/src/dart/resolver/variable_declaration_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/variable_declaration_resolver.dart
index 5cbf8db..3dd455d 100644
--- a/pkg/analyzer/lib/src/dart/resolver/variable_declaration_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/variable_declaration_resolver.dart
@@ -49,8 +49,7 @@
_resolver.flowAnalysis.flow?.lateInitializer_begin(node);
}
- InferenceContext.setType(initializer, element.type);
- initializer.accept(_resolver);
+ _resolver.analyzeExpression(initializer, element.type);
initializer = node.initializer!;
var whyNotPromoted =
_resolver.flowAnalysis.flow?.whyNotPromoted(initializer);
diff --git a/pkg/analyzer/lib/src/dart/resolver/yield_statement_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/yield_statement_resolver.dart
index 0016d66..c8c5504 100644
--- a/pkg/analyzer/lib/src/dart/resolver/yield_statement_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/yield_statement_resolver.dart
@@ -133,13 +133,30 @@
}
}
+ DartType? _computeContextType(
+ BodyInferenceContext bodyContext,
+ YieldStatement node,
+ ) {
+ var elementType = bodyContext.contextType;
+ if (elementType != null) {
+ var contextType = elementType;
+ if (node.star != null) {
+ contextType = bodyContext.isSynchronous
+ ? _typeProvider.iterableType(elementType)
+ : _typeProvider.streamType(elementType);
+ }
+ return contextType;
+ } else {
+ return null;
+ }
+ }
+
void _resolve_generator(
BodyInferenceContext bodyContext,
YieldStatement node,
) {
- _setContextType(bodyContext, node);
-
- node.expression.accept(_resolver);
+ _resolver.analyzeExpression(
+ node.expression, _computeContextType(bodyContext, node));
if (node.star != null) {
_resolver.nullableDereferenceVerifier.expression(
@@ -167,20 +184,4 @@
_checkForUseOfVoidResult(node.expression);
}
-
- void _setContextType(
- BodyInferenceContext bodyContext,
- YieldStatement node,
- ) {
- var elementType = bodyContext.contextType;
- if (elementType != null) {
- var contextType = elementType;
- if (node.star != null) {
- contextType = bodyContext.isSynchronous
- ? _typeProvider.iterableType(elementType)
- : _typeProvider.streamType(elementType);
- }
- InferenceContext.setType(node.expression, contextType);
- }
- }
}
diff --git a/pkg/analyzer/lib/src/error/best_practices_verifier.dart b/pkg/analyzer/lib/src/error/best_practices_verifier.dart
index 45dce24..74bf441 100644
--- a/pkg/analyzer/lib/src/error/best_practices_verifier.dart
+++ b/pkg/analyzer/lib/src/error/best_practices_verifier.dart
@@ -32,7 +32,6 @@
import 'package:analyzer/src/error/null_safe_api_verifier.dart';
import 'package:analyzer/src/generated/constant.dart';
import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/generated/resolver.dart';
import 'package:analyzer/src/lint/linter.dart';
import 'package:analyzer/src/utilities/extensions/string.dart';
import 'package:analyzer/src/workspace/workspace.dart';
@@ -529,8 +528,7 @@
if (node.parent is! FunctionDeclaration) {
_checkForMissingReturn(node.body, node);
}
- var functionType = InferenceContext.getContext(node);
- if (functionType is! FunctionType) {
+ if (!(node as FunctionExpressionImpl).wasFunctionTypeSupplied) {
_checkStrictInferenceInParameters(node.parameters, body: node.body);
}
super.visitFunctionExpression(node);
diff --git a/pkg/analyzer/lib/src/error/codes.g.dart b/pkg/analyzer/lib/src/error/codes.g.dart
index 9666c16..e3bf80e 100644
--- a/pkg/analyzer/lib/src/error/codes.g.dart
+++ b/pkg/analyzer/lib/src/error/codes.g.dart
@@ -5690,6 +5690,14 @@
hasPublishedDocs: true,
);
+ static const CompileTimeErrorCode ILLEGAL_LANGUAGE_VERSION_OVERRIDE =
+ CompileTimeErrorCode(
+ 'ILLEGAL_LANGUAGE_VERSION_OVERRIDE',
+ "The language version must be {0}.",
+ correctionMessage:
+ "Try removing the language version override and migrating the code.",
+ );
+
/**
* No parameters.
*/
diff --git a/pkg/analyzer/lib/src/error/inheritance_override.dart b/pkg/analyzer/lib/src/error/inheritance_override.dart
index 5b3d27f..fec81ec 100644
--- a/pkg/analyzer/lib/src/error/inheritance_override.dart
+++ b/pkg/analyzer/lib/src/error/inheritance_override.dart
@@ -12,7 +12,6 @@
import 'package:analyzer/error/listener.dart';
import 'package:analyzer/src/dart/ast/extensions.dart';
import 'package:analyzer/src/dart/element/element.dart';
-import 'package:analyzer/src/dart/element/extensions.dart';
import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
import 'package:analyzer/src/dart/element/type_system.dart';
import 'package:analyzer/src/error/codes.dart';
diff --git a/pkg/analyzer/lib/src/generated/engine.dart b/pkg/analyzer/lib/src/generated/engine.dart
index 6741d98..bc9aba5 100644
--- a/pkg/analyzer/lib/src/generated/engine.dart
+++ b/pkg/analyzer/lib/src/generated/engine.dart
@@ -224,6 +224,10 @@
@override
VersionConstraint? sdkVersionConstraint;
+ /// The constraint on the language version for every Dart file.
+ /// Violations will be reported as analysis errors.
+ VersionConstraint? sourceLanguageConstraint;
+
ExperimentStatus _contextFeatures = ExperimentStatus();
/// The language version to use for libraries that are not in a package.
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index 6d17094..b46f83c 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -22,7 +22,6 @@
import 'package:analyzer/src/dart/ast/extensions.dart';
import 'package:analyzer/src/dart/element/class_hierarchy.dart';
import 'package:analyzer/src/dart/element/element.dart';
-import 'package:analyzer/src/dart/element/extensions.dart';
import 'package:analyzer/src/dart/element/inheritance_manager3.dart';
import 'package:analyzer/src/dart/element/type.dart';
import 'package:analyzer/src/dart/element/type_provider.dart';
@@ -488,6 +487,7 @@
_featureSet = node.featureSet;
_duplicateDefinitionVerifier.checkUnit(node);
_checkForDeferredPrefixCollisions(node);
+ _checkForIllegalLanguageOverride(node);
super.visitCompilationUnit(node);
_featureSet = null;
}
@@ -2687,6 +2687,29 @@
}
}
+ void _checkForIllegalLanguageOverride(CompilationUnit node) {
+ var sourceLanguageConstraint = _options.sourceLanguageConstraint;
+ if (sourceLanguageConstraint == null) {
+ return;
+ }
+
+ var languageVersionToken = node.languageVersionToken;
+ if (languageVersionToken == null) {
+ return;
+ }
+
+ var languageVersion = _currentLibrary.languageVersion.effective;
+ if (sourceLanguageConstraint.allows(languageVersion)) {
+ return;
+ }
+
+ errorReporter.reportErrorForToken(
+ CompileTimeErrorCode.ILLEGAL_LANGUAGE_VERSION_OVERRIDE,
+ languageVersionToken,
+ ['$sourceLanguageConstraint'],
+ );
+ }
+
/// Verify that the given implements [clause] does not implement classes such
/// as 'num' or 'String'.
///
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index 8506477..375c076 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -957,8 +957,7 @@
hasWrite: true,
);
- InferenceContext.setType(node.index, result.indexContextType);
- node.index.accept(this);
+ analyzeExpression(node.index, result.indexContextType);
var whyNotPromoted = flowAnalysis.flow?.whyNotPromoted(node.index);
checkIndexExpressionIndex(
node.index,
@@ -1174,9 +1173,8 @@
@override
void visitAssertInitializer(AssertInitializer node) {
- InferenceContext.setType(node.condition, typeProvider.boolType);
flowAnalysis.flow?.assert_begin();
- node.condition.accept(this);
+ analyzeExpression(node.condition, typeProvider.boolType);
boolExpressionVerifier.checkForNonBoolExpression(
node.condition,
errorCode: CompileTimeErrorCode.NON_BOOL_EXPRESSION,
@@ -1189,9 +1187,8 @@
@override
void visitAssertStatement(AssertStatement node) {
- InferenceContext.setType(node.condition, typeProvider.boolType);
flowAnalysis.flow?.assert_begin();
- node.condition.accept(this);
+ analyzeExpression(node.condition, typeProvider.boolType);
boolExpressionVerifier.checkForNonBoolExpression(
node.condition,
errorCode: CompileTimeErrorCode.NON_BOOL_EXPRESSION,
@@ -1211,12 +1208,12 @@
@override
void visitAwaitExpression(AwaitExpression node) {
var contextType = InferenceContext.getContext(node);
+ DartType? futureUnion;
if (contextType != null) {
- var futureUnion = _createFutureOr(contextType);
- InferenceContext.setType(node.expression, futureUnion);
+ futureUnion = _createFutureOr(contextType);
}
checkUnreachableNode(node);
- node.visitChildren(this);
+ analyzeExpression(node.expression, futureUnion);
typeAnalyzer.visitAwaitExpression(node as AwaitExpressionImpl);
insertGenericFunctionInstantiation(node);
}
@@ -1273,8 +1270,7 @@
@override
void visitCascadeExpression(covariant CascadeExpressionImpl node) {
- InferenceContext.setTypeFromNode(node.target, node);
- node.target.accept(this);
+ analyzeExpression(node.target, InferenceContext.getContext(node));
if (node.isNullAware) {
flowAnalysis.flow!.nullAwareAccess_rightBegin(
@@ -1349,38 +1345,35 @@
@override
void visitConditionalExpression(ConditionalExpression node) {
+ var contextType = InferenceContext.getContext(node);
Expression condition = node.condition;
var flow = flowAnalysis.flow;
flow?.conditional_conditionBegin();
// TODO(scheglov) Do we need these checks for null?
- InferenceContext.setType(node.condition, typeProvider.boolType);
- condition.accept(this);
+ analyzeExpression(node.condition, typeProvider.boolType);
condition = node.condition;
var whyNotPromoted = flowAnalysis.flow?.whyNotPromoted(condition);
boolExpressionVerifier.checkForNonBoolCondition(condition,
whyNotPromoted: whyNotPromoted);
- InferenceContext.setTypeFromNode(node.thenExpression, node);
-
if (flow != null) {
flow.conditional_thenBegin(condition, node);
checkUnreachableNode(node.thenExpression);
}
- node.thenExpression.accept(this);
+ analyzeExpression(node.thenExpression, contextType);
nullSafetyDeadCodeVerifier.flowEnd(node.thenExpression);
Expression elseExpression = node.elseExpression;
- InferenceContext.setTypeFromNode(elseExpression, node);
if (flow != null) {
flow.conditional_elseBegin(node.thenExpression);
checkUnreachableNode(elseExpression);
- elseExpression.accept(this);
+ analyzeExpression(elseExpression, contextType);
flow.conditional_end(node, elseExpression);
nullSafetyDeadCodeVerifier.flowEnd(elseExpression);
} else {
- elseExpression.accept(this);
+ analyzeExpression(elseExpression, contextType);
}
elseExpression = node.elseExpression;
@@ -1440,8 +1433,7 @@
var fieldElement = enclosingClass!.getField(node.fieldName.name);
var fieldType = fieldElement?.type;
var expression = node.expression;
- InferenceContext.setType(expression, fieldType);
- expression.accept(this);
+ analyzeExpression(expression, fieldType);
expression = node.expression;
var whyNotPromoted = flowAnalysis.flow?.whyNotPromoted(expression);
elementResolver.visitConstructorFieldInitializer(
@@ -1497,13 +1489,16 @@
@override
void visitDefaultFormalParameter(DefaultFormalParameter node) {
- InferenceContext.setType(node.defaultValue, node.declaredElement?.type);
checkUnreachableNode(node);
- node.visitChildren(this);
+ node.parameter.accept(this);
+ var defaultValue = node.defaultValue;
+ if (defaultValue != null) {
+ analyzeExpression(defaultValue, node.declaredElement?.type);
+ }
ParameterElement element = node.declaredElement!;
if (element is DefaultParameterElementImpl && node.isOfLocalFunction) {
- element.constantInitializer = node.defaultValue;
+ element.constantInitializer = defaultValue;
}
}
@@ -1517,8 +1512,7 @@
node.body.accept(this);
flowAnalysis.flow?.doStatement_conditionBegin();
- InferenceContext.setType(condition, typeProvider.boolType);
- condition.accept(this);
+ analyzeExpression(condition, typeProvider.boolType);
condition = node.condition;
var whyNotPromoted = flowAnalysis.flow?.whyNotPromoted(condition);
boolExpressionVerifier.checkForNonBoolCondition(condition,
@@ -1579,11 +1573,7 @@
parameters: constructor.parameters,
);
for (var argument in argumentList.arguments) {
- var parameter = argument.staticParameterElement;
- if (parameter != null) {
- InferenceContext.setType(argument, parameter.type);
- }
- argument.accept(this);
+ analyzeExpression(argument, argument.staticParameterElement?.type);
}
}
arguments.typeArguments?.accept(this);
@@ -1625,14 +1615,13 @@
try {
inferenceContext.pushFunctionBodyContext(node, imposedType);
- InferenceContext.setType(
- node.expression,
- inferenceContext.bodyContext!.contextType,
- );
_thisAccessTracker.enterFunctionBody(node);
checkUnreachableNode(node);
- node.visitChildren(this);
+ analyzeExpression(
+ node.expression,
+ inferenceContext.bodyContext!.contextType,
+ );
insertImplicitCallReference(node.expression);
flowAnalysis.flow?.handleExit();
@@ -1747,13 +1736,16 @@
);
var functionType = node.declaredElement!.type;
- InferenceContext.setType(node.functionExpression, functionType);
var outerFunction = _enclosingFunction;
try {
_enclosingFunction = node.declaredElement;
checkUnreachableNode(node);
- node.visitChildren(this);
+ node.documentationComment?.accept(this);
+ node.metadata.accept(this);
+ node.returnType?.accept(this);
+ node.name.accept(this);
+ analyzeExpression(node.functionExpression, functionType);
elementResolver.visitFunctionDeclaration(node);
} finally {
_enclosingFunction = outerFunction;
@@ -1845,8 +1837,7 @@
void visitIfElement(IfElement node, {CollectionLiteralContext? context}) {
flowAnalysis.flow?.ifStatement_conditionBegin();
Expression condition = node.condition;
- InferenceContext.setType(condition, typeProvider.boolType);
- condition.accept(this);
+ analyzeExpression(condition, typeProvider.boolType);
condition = node.condition;
var whyNotPromoted = flowAnalysis.flow?.whyNotPromoted(condition);
@@ -1874,8 +1865,7 @@
Expression condition = node.condition;
- InferenceContext.setType(condition, typeProvider.boolType);
- condition.accept(this);
+ analyzeExpression(condition, typeProvider.boolType);
condition = node.condition;
var whyNotPromoted = flowAnalysis.flow?.whyNotPromoted(condition);
@@ -1929,8 +1919,7 @@
var element = result.readElement;
node.staticElement = element as MethodElement?;
- InferenceContext.setType(node.index, result.indexContextType);
- node.index.accept(this);
+ analyzeExpression(node.index, result.indexContextType);
var whyNotPromoted = flowAnalysis.flow?.whyNotPromoted(node.index);
checkIndexExpressionIndex(
node.index,
@@ -2114,9 +2103,10 @@
@override
void visitNamedExpression(NamedExpression node) {
- InferenceContext.setTypeFromNode(node.expression, node);
+ var contextType = InferenceContext.getContext(node);
checkUnreachableNode(node);
- node.visitChildren(this);
+ node.name.accept(this);
+ analyzeExpression(node.expression, contextType);
typeAnalyzer.visitNamedExpression(node as NamedExpressionImpl);
// Any "why not promoted" information that flow analysis had associated with
// `node.expression` now needs to be forwarded to `node`, so that when
@@ -2163,9 +2153,8 @@
@override
void visitParenthesizedExpression(ParenthesizedExpression node) {
- InferenceContext.setTypeFromNode(node.expression, node);
checkUnreachableNode(node);
- node.visitChildren(this);
+ analyzeExpression(node.expression, InferenceContext.getContext(node));
typeAnalyzer
.visitParenthesizedExpression(node as ParenthesizedExpressionImpl);
flowAnalysis.flow?.parenthesizedExpression(node, node.expression);
@@ -2274,18 +2263,20 @@
@override
void visitReturnStatement(ReturnStatement node) {
- InferenceContext.setType(
- node.expression,
- inferenceContext.bodyContext?.contextType,
- );
-
checkUnreachableNode(node);
- node.visitChildren(this);
+ var expression = node.expression;
+ if (expression != null) {
+ analyzeExpression(
+ expression,
+ inferenceContext.bodyContext?.contextType,
+ );
+ // Pick up the expression again in case it was rewritten.
+ expression = node.expression;
+ }
- inferenceContext.bodyContext?.addReturnExpression(node.expression);
+ inferenceContext.bodyContext?.addReturnExpression(expression);
flowAnalysis.flow?.handleExit();
- var expression = node.expression;
if (expression != null) {
insertImplicitCallReference(expression);
}
@@ -2379,10 +2370,10 @@
void visitSwitchCase(SwitchCase node) {
checkUnreachableNode(node);
- InferenceContext.setType(
- node.expression, _enclosingSwitchStatementExpressionType);
checkUnreachableNode(node);
- node.visitChildren(this);
+ node.labels.accept(this);
+ analyzeExpression(node.expression, _enclosingSwitchStatementExpressionType);
+ node.statements.accept(this);
var flow = flowAnalysis.flow;
if (flow != null && flow.isReachable && _isNonNullableByDefault) {
@@ -2578,10 +2569,9 @@
checkUnreachableNode(node);
Expression condition = node.condition;
- InferenceContext.setType(condition, typeProvider.boolType);
flowAnalysis.flow?.whileStatement_conditionBegin(node);
- condition.accept(this);
+ analyzeExpression(condition, typeProvider.boolType);
condition = node.condition;
var whyNotPromoted = flowAnalysis.flow?.whyNotPromoted(condition);
diff --git a/pkg/analyzer/lib/src/summary2/ast_resolver.dart b/pkg/analyzer/lib/src/summary2/ast_resolver.dart
index ead4620..e3976e43 100644
--- a/pkg/analyzer/lib/src/summary2/ast_resolver.dart
+++ b/pkg/analyzer/lib/src/summary2/ast_resolver.dart
@@ -93,14 +93,11 @@
node.accept(_resolutionVisitor);
// Node may have been rewritten so get it again.
node = getNode();
- if (contextType != null) {
- InferenceContext.setType(node, contextType);
- }
node.accept(_scopeResolverVisitor);
}
_prepareEnclosingDeclarations();
_flowAnalysis.topLevelDeclaration_enter(node.parent!, null);
- node.accept(_resolverVisitor);
+ _resolverVisitor.analyzeExpression(node, contextType);
_flowAnalysis.topLevelDeclaration_exit();
}
diff --git a/pkg/analyzer/lib/src/summary2/element_builder.dart b/pkg/analyzer/lib/src/summary2/element_builder.dart
index 5764311..892c2fb 100644
--- a/pkg/analyzer/lib/src/summary2/element_builder.dart
+++ b/pkg/analyzer/lib/src/summary2/element_builder.dart
@@ -220,9 +220,6 @@
hasConstConstructor: true,
);
- var needsImplicitConstructor =
- !node.members.any((e) => e is ConstructorDeclaration);
-
// Build fields for all enum constants.
var constants = node.constants;
var valuesElements = <Expression>[];
@@ -353,6 +350,10 @@
_visitPropertyFirst<FieldDeclaration>(node.members);
});
+ var needsImplicitConstructor = !holder.constructors.any(
+ (e) => e.name.isEmpty || e.isGenerative,
+ );
+
if (needsImplicitConstructor) {
holder.addConstructor(
ConstructorElementImpl('', -1)
diff --git a/pkg/analyzer/lib/src/workspace/bazel.dart b/pkg/analyzer/lib/src/workspace/bazel.dart
index 5198c44..ae54e97 100644
--- a/pkg/analyzer/lib/src/workspace/bazel.dart
+++ b/pkg/analyzer/lib/src/workspace/bazel.dart
@@ -692,13 +692,16 @@
.getFolder(root)
.getChildAssumingFile('BUILD')
.readAsStringSync();
- var hasNonNullableFlag = buildContent
+ var flattenedBuildContent = buildContent
.split('\n')
.map((e) => e.trim())
.where((e) => !e.startsWith('#'))
.map((e) => e.replaceAll(' ', ''))
- .join()
- .contains('dart_package(null_safety=True');
+ .join();
+ var hasNonNullableFlag = const {
+ 'dart_package(null_safety=True',
+ 'dart_package(sound_null_safety=True',
+ }.any(flattenedBuildContent.contains);
if (hasNonNullableFlag) {
// Enabled by default.
} else {
diff --git a/pkg/analyzer/messages.yaml b/pkg/analyzer/messages.yaml
index 8fa7b1a..50014bb 100644
--- a/pkg/analyzer/messages.yaml
+++ b/pkg/analyzer/messages.yaml
@@ -4992,6 +4992,9 @@
```dart
int f() => 0;
```
+ ILLEGAL_LANGUAGE_VERSION_OVERRIDE:
+ problemMessage: The language version must be {0}.
+ correctionMessage: Try removing the language version override and migrating the code.
ILLEGAL_SYNC_GENERATOR_RETURN_TYPE:
problemMessage: "Functions marked 'sync*' must have a return type that is a supertype of 'Iterable<T>' for some type 'T'."
correctionMessage: "Try fixing the return type of the function, or removing the modifier 'sync*' from the function body."
diff --git a/pkg/analyzer/test/src/dart/resolution/context_collection_resolution.dart b/pkg/analyzer/test/src/dart/resolution/context_collection_resolution.dart
index 9f2e227..fd06856 100644
--- a/pkg/analyzer/test/src/dart/resolution/context_collection_resolution.dart
+++ b/pkg/analyzer/test/src/dart/resolution/context_collection_resolution.dart
@@ -212,6 +212,10 @@
);
}
+ /// Override this method to update [analysisOptions] for every context root,
+ /// the default or already updated with `analysis_options.yaml` file.
+ void updateAnalysisOptions(AnalysisOptionsImpl analysisOptions) {}
+
/// Call this method if the test needs to use the empty byte store, without
/// any information cached.
void useEmptyByteStore() {
@@ -241,6 +245,7 @@
resourceProvider: resourceProvider,
retainDataForTesting: retainDataForTesting,
sdkPath: sdkRoot.path,
+ updateAnalysisOptions: updateAnalysisOptions,
);
verifyCreatedCollection();
diff --git a/pkg/analyzer/test/src/dart/resolution/non_nullable_bazel_workspace_test.dart b/pkg/analyzer/test/src/dart/resolution/non_nullable_bazel_workspace_test.dart
index 8340942..65aaa92 100644
--- a/pkg/analyzer/test/src/dart/resolution/non_nullable_bazel_workspace_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/non_nullable_bazel_workspace_test.dart
@@ -125,6 +125,21 @@
assertType(findNode.namedType('int v'), 'int');
}
+ test_buildFile_nonNullable_soundNullSafety() async {
+ newFile('$myPackageRootPath/BUILD', content: r'''
+dart_package(
+ sound_null_safety = True
+)
+''');
+
+ await resolveFileCode(
+ '$myPackageRootPath/lib/a.dart',
+ 'int v = 0;',
+ );
+ assertNoErrorsInResult();
+ assertType(findNode.namedType('int v'), 'int');
+ }
+
test_buildFile_nonNullable_withComments() async {
newFile('$myPackageRootPath/BUILD', content: r'''
dart_package(
diff --git a/pkg/analyzer/test/src/diagnostics/illegal_language_version_override_test.dart b/pkg/analyzer/test/src/diagnostics/illegal_language_version_override_test.dart
new file mode 100644
index 0000000..a212ea3
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/illegal_language_version_override_test.dart
@@ -0,0 +1,54 @@
+// 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 'package:analyzer/src/error/codes.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:pub_semver/src/version_constraint.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/context_collection_resolution.dart';
+
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(IllegalLanguageVersionOverrideTest);
+ });
+}
+
+@reflectiveTest
+class IllegalLanguageVersionOverrideTest extends PubPackageResolutionTest {
+ test_hasOverride_equal() async {
+ await assertNoErrorsInCode(r'''
+// @dart = 2.12
+void f() {}
+''');
+ }
+
+ test_hasOverride_greater() async {
+ await assertNoErrorsInCode(r'''
+// @dart = 2.14
+void f() {}
+''');
+ }
+
+ test_hasOverride_less() async {
+ await assertErrorsInCode(r'''
+// @dart = 2.9
+int a = null;
+''', [
+ error(CompileTimeErrorCode.ILLEGAL_LANGUAGE_VERSION_OVERRIDE, 0, 14),
+ ]);
+ }
+
+ test_noOverride() async {
+ await assertNoErrorsInCode(r'''
+void f() {}
+''');
+ }
+
+ @override
+ void updateAnalysisOptions(AnalysisOptionsImpl analysisOptions) {
+ analysisOptions.sourceLanguageConstraint =
+ VersionConstraint.parse('>= 2.12.0');
+ }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/test_all.dart b/pkg/analyzer/test/src/diagnostics/test_all.dart
index 32e5d07..d8504b1 100644
--- a/pkg/analyzer/test/src/diagnostics/test_all.dart
+++ b/pkg/analyzer/test/src/diagnostics/test_all.dart
@@ -241,6 +241,8 @@
import 'illegal_async_generator_return_type_test.dart'
as illegal_async_generator_return_type;
import 'illegal_async_return_type_test.dart' as illegal_async_return_type;
+import 'illegal_language_version_override_test.dart'
+ as illegal_language_version_override;
import 'illegal_sync_generator_return_type_test.dart'
as illegal_sync_generator_return_type;
import 'implements_deferred_class_test.dart' as implements_deferred_class;
@@ -912,6 +914,7 @@
if_element_condition_from_deferred_library.main();
illegal_async_generator_return_type.main();
illegal_async_return_type.main();
+ illegal_language_version_override.main();
illegal_sync_generator_return_type.main();
implements_deferred_class.main();
implements_disallowed_class.main();
diff --git a/pkg/analyzer/test/src/summary/resynthesize_common.dart b/pkg/analyzer/test/src/summary/resynthesize_common.dart
index 84c2a4a..7ca0145 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_common.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_common.dart
@@ -17702,6 +17702,137 @@
''');
}
+ test_enum_constructor_factory_named() async {
+ var library = await checkLibrary(r'''
+enum E {
+ v;
+ factory E.named() => v;
+}
+''');
+ checkElementText(library, r'''
+library
+ definingUnit
+ enums
+ enum E @5
+ supertype: Enum
+ fields
+ static const enumConstant v @11
+ type: E
+ constantInitializer
+ InstanceCreationExpression
+ argumentList: ArgumentList
+ leftParenthesis: ( @0
+ rightParenthesis: ) @0
+ constructorName: ConstructorName
+ name: SimpleIdentifier
+ staticElement: self::@enum::E::@constructor::•
+ staticType: null
+ token: @-1
+ period: . @0
+ staticElement: self::@enum::E::@constructor::•
+ type: NamedType
+ name: SimpleIdentifier
+ staticElement: self::@enum::E
+ staticType: null
+ token: E @-1
+ type: E
+ staticType: E
+ synthetic static const values @-1
+ type: List<E>
+ constantInitializer
+ ListLiteral
+ elements
+ SimpleIdentifier
+ staticElement: self::@enum::E::@getter::v
+ staticType: E
+ token: v @-1
+ leftBracket: [ @0
+ rightBracket: ] @0
+ staticType: List<E>
+ synthetic final index @-1
+ type: int
+ constructors
+ factory named @26
+ periodOffset: 25
+ nameEnd: 31
+ synthetic const @-1
+ accessors
+ synthetic static get v @-1
+ returnType: E
+ synthetic static get values @-1
+ returnType: List<E>
+ synthetic get index @-1
+ returnType: int
+ methods
+ synthetic toString @-1
+ returnType: String
+''');
+ }
+
+ test_enum_constructor_factory_unnamed() async {
+ var library = await checkLibrary(r'''
+enum E {
+ v;
+ factory E() => v;
+}
+''');
+ checkElementText(library, r'''
+library
+ definingUnit
+ enums
+ enum E @5
+ supertype: Enum
+ fields
+ static const enumConstant v @11
+ type: E
+ constantInitializer
+ InstanceCreationExpression
+ argumentList: ArgumentList
+ leftParenthesis: ( @0
+ rightParenthesis: ) @0
+ constructorName: ConstructorName
+ name: SimpleIdentifier
+ staticElement: self::@enum::E::@constructor::•
+ staticType: null
+ token: @-1
+ period: . @0
+ staticElement: self::@enum::E::@constructor::•
+ type: NamedType
+ name: SimpleIdentifier
+ staticElement: self::@enum::E
+ staticType: null
+ token: E @-1
+ type: E
+ staticType: E
+ synthetic static const values @-1
+ type: List<E>
+ constantInitializer
+ ListLiteral
+ elements
+ SimpleIdentifier
+ staticElement: self::@enum::E::@getter::v
+ staticType: E
+ token: v @-1
+ leftBracket: [ @0
+ rightBracket: ] @0
+ staticType: List<E>
+ synthetic final index @-1
+ type: int
+ constructors
+ factory @24
+ accessors
+ synthetic static get v @-1
+ returnType: E
+ synthetic static get values @-1
+ returnType: List<E>
+ synthetic get index @-1
+ returnType: int
+ methods
+ synthetic toString @-1
+ returnType: String
+''');
+ }
+
test_enum_constructor_fieldFormal_functionTyped_withReturnType() async {
var library = await checkLibrary(r'''
enum E {
@@ -18143,7 +18274,7 @@
''');
}
- test_enum_constructor_named() async {
+ test_enum_constructor_generative_named() async {
var library = await checkLibrary(r'''
enum E {
v.named(42);
@@ -18216,7 +18347,7 @@
''');
}
- test_enum_constructor_unnamed() async {
+ test_enum_constructor_generative_unnamed() async {
var library = await checkLibrary(r'''
enum E {
v(42);
diff --git a/pkg/dds/test/dap/integration/test_support.dart b/pkg/dds/test/dap/integration/test_support.dart
index ebabce8..5e4c792 100644
--- a/pkg/dds/test/dap/integration/test_support.dart
+++ b/pkg/dds/test/dap/integration/test_support.dart
@@ -33,7 +33,12 @@
/// This is useful for debugging locally or on the bots and will include both
/// DAP traffic (between the test DAP client and the DAP server) and the VM
/// Service traffic (wrapped in a custom 'dart.log' event).
-final verboseLogging = Platform.environment['DAP_TEST_VERBOSE'] == 'true';
+///
+/// Verbose logging is temporarily enabled for all test runs to try and
+/// understand failures noted at https://github.com/dart-lang/sdk/issues/48274.
+/// Once resolved, this variable can be set back to the result of:
+/// Platform.environment['DAP_TEST_VERBOSE'] == 'true'
+final verboseLogging = true;
/// A [RegExp] that matches the `path` part of a VM Service URI that contains
/// an authentication token.
diff --git a/runtime/third_party/binary_size/README.dart b/runtime/third_party/binary_size/README.dart
deleted file mode 100644
index 0f2124e..0000000
--- a/runtime/third_party/binary_size/README.dart
+++ /dev/null
@@ -1 +0,0 @@
-A local copy of tools/binary_size from Chromium project.
\ No newline at end of file
diff --git a/runtime/third_party/binary_size/src/binary_size_utils.py b/runtime/third_party/binary_size/src/binary_size_utils.py
deleted file mode 100644
index 8ef283e..0000000
--- a/runtime/third_party/binary_size/src/binary_size_utils.py
+++ /dev/null
@@ -1,69 +0,0 @@
-# Copyright 2014 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-"""Common utilities for tools that deal with binary size information.
-"""
-
-import logging
-import re
-
-
-def ParseNm(nm_lines):
- """Parse nm output, returning data for all relevant (to binary size)
- symbols and ignoring the rest.
-
- Args:
- nm_lines: an iterable over lines of nm output.
-
- Yields:
- (symbol name, symbol type, symbol size, source file path).
-
- Path may be None if nm couldn't figure out the source file.
- """
-
- # Match lines with size, symbol, optional location, optional discriminator
- sym_re = re.compile(r'^([0-9a-f]{8,}) ' # address (8+ hex digits)
- '([0-9a-f]{8,}) ' # size (8+ hex digits)
- '(.) ' # symbol type, one character
- '([^\t]+)' # symbol name, separated from next by tab
- '(?:\t(.*):[\d\?]+)?.*$') # location
- # Match lines with addr but no size.
- addr_re = re.compile(r'^[0-9a-f]{8,} (.) ([^\t]+)(?:\t.*)?$')
- # Match lines that don't have an address at all -- typically external symbols.
- noaddr_re = re.compile(r'^ {8,} (.) (.*)$')
- # Match lines with no symbol name, only addr and type
- addr_only_re = re.compile(r'^[0-9a-f]{8,} (.)$')
-
- seen_lines = set()
- for line in nm_lines:
- line = line.rstrip()
- if line in seen_lines:
- # nm outputs identical lines at times. We don't want to treat
- # those as distinct symbols because that would make no sense.
- continue
- seen_lines.add(line)
- match = sym_re.match(line)
- if match:
- address, size, sym_type, sym = match.groups()[0:4]
- size = int(size, 16)
- if sym_type in ('B', 'b'):
- continue # skip all BSS for now.
- path = match.group(5)
- yield sym, sym_type, size, path, address
- continue
- match = addr_re.match(line)
- if match:
- # sym_type, sym = match.groups()[0:2]
- continue # No size == we don't care.
- match = noaddr_re.match(line)
- if match:
- sym_type, sym = match.groups()
- if sym_type in ('U', 'w'):
- continue # external or weak symbol
- match = addr_only_re.match(line)
- if match:
- continue # Nothing to do.
-
- # If we reach this part of the loop, there was something in the
- # line that we didn't expect or recognize.
- logging.warning('nm output parser failed to parse: %s', repr(line))
diff --git a/runtime/third_party/binary_size/src/elf_symbolizer.py b/runtime/third_party/binary_size/src/elf_symbolizer.py
deleted file mode 100644
index 5154a9b..0000000
--- a/runtime/third_party/binary_size/src/elf_symbolizer.py
+++ /dev/null
@@ -1,490 +0,0 @@
-# Copyright 2014 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import collections
-import datetime
-import logging
-import multiprocessing
-import os
-import posixpath
-import queue
-import re
-import subprocess
-import sys
-import threading
-import time
-
-# addr2line builds a possibly infinite memory cache that can exhaust
-# the computer's memory if allowed to grow for too long. This constant
-# controls how many lookups we do before restarting the process. 4000
-# gives near peak performance without extreme memory usage.
-ADDR2LINE_RECYCLE_LIMIT = 4000
-
-
-class ELFSymbolizer(object):
- """An uber-fast (multiprocessing, pipelined and asynchronous) ELF symbolizer.
-
- This class is a frontend for addr2line (part of GNU binutils), designed to
- symbolize batches of large numbers of symbols for a given ELF file. It
- supports sharding symbolization against many addr2line instances and
- pipelining of multiple requests per each instance (in order to hide addr2line
- internals and OS pipe latencies).
-
- The interface exhibited by this class is a very simple asynchronous interface,
- which is based on the following three methods:
- - SymbolizeAsync(): used to request (enqueue) resolution of a given address.
- - The |callback| method: used to communicated back the symbol information.
- - Join(): called to conclude the batch to gather the last outstanding results.
- In essence, before the Join method returns, this class will have issued as
- many callbacks as the number of SymbolizeAsync() calls. In this regard, note
- that due to multiprocess sharding, callbacks can be delivered out of order.
-
- Some background about addr2line:
- - it is invoked passing the elf path in the cmdline, piping the addresses in
- its stdin and getting results on its stdout.
- - it has pretty large response times for the first requests, but it
- works very well in streaming mode once it has been warmed up.
- - it doesn't scale by itself (on more cores). However, spawning multiple
- instances at the same time on the same file is pretty efficient as they
- keep hitting the pagecache and become mostly CPU bound.
- - it might hang or crash, mostly for OOM. This class deals with both of these
- problems.
-
- Despite the "scary" imports and the multi* words above, (almost) no multi-
- threading/processing is involved from the python viewpoint. Concurrency
- here is achieved by spawning several addr2line subprocesses and handling their
- output pipes asynchronously. Therefore, all the code here (with the exception
- of the Queue instance in Addr2Line) should be free from mind-blowing
- thread-safety concerns.
-
- The multiprocess sharding works as follows:
- The symbolizer tries to use the lowest number of addr2line instances as
- possible (with respect of |max_concurrent_jobs|) and enqueue all the requests
- in a single addr2line instance. For few symbols (i.e. dozens) sharding isn't
- worth the startup cost.
- The multiprocess logic kicks in as soon as the queues for the existing
- instances grow. Specifically, once all the existing instances reach the
- |max_queue_size| bound, a new addr2line instance is kicked in.
- In the case of a very eager producer (i.e. all |max_concurrent_jobs| instances
- have a backlog of |max_queue_size|), back-pressure is applied on the caller by
- blocking the SymbolizeAsync method.
-
- This module has been deliberately designed to be dependency free (w.r.t. of
- other modules in this project), to allow easy reuse in external projects.
- """
-
- def __init__(self,
- elf_file_path,
- addr2line_path,
- callback,
- inlines=False,
- max_concurrent_jobs=None,
- addr2line_timeout=30,
- max_queue_size=50,
- source_root_path=None,
- strip_base_path=None):
- """Args:
- elf_file_path: path of the elf file to be symbolized.
- addr2line_path: path of the toolchain's addr2line binary.
- callback: a callback which will be invoked for each resolved symbol with
- the two args (sym_info, callback_arg). The former is an instance of
- |ELFSymbolInfo| and contains the symbol information. The latter is an
- embedder-provided argument which is passed to SymbolizeAsync().
- inlines: when True, the ELFSymbolInfo will contain also the details about
- the outer inlining functions. When False, only the innermost function
- will be provided.
- max_concurrent_jobs: Max number of addr2line instances spawned.
- Parallelize responsibly, addr2line is a memory and I/O monster.
- max_queue_size: Max number of outstanding requests per addr2line instance.
- addr2line_timeout: Max time (in seconds) to wait for a addr2line response.
- After the timeout, the instance will be considered hung and respawned.
- source_root_path: In some toolchains only the name of the source file is
- is output, without any path information; disambiguation searches
- through the source directory specified by |source_root_path| argument
- for files whose name matches, adding the full path information to the
- output. For example, if the toolchain outputs "unicode.cc" and there
- is a file called "unicode.cc" located under |source_root_path|/foo,
- the tool will replace "unicode.cc" with
- "|source_root_path|/foo/unicode.cc". If there are multiple files with
- the same name, disambiguation will fail because the tool cannot
- determine which of the files was the source of the symbol.
- strip_base_path: Rebases the symbols source paths onto |source_root_path|
- (i.e replace |strip_base_path| with |source_root_path).
- """
- assert (os.path.isfile(addr2line_path)), 'Cannot find ' + addr2line_path
- self.elf_file_path = elf_file_path
- self.addr2line_path = addr2line_path
- self.callback = callback
- self.inlines = inlines
- self.max_concurrent_jobs = (max_concurrent_jobs or
- min(multiprocessing.cpu_count(), 4))
- self.max_queue_size = max_queue_size
- self.addr2line_timeout = addr2line_timeout
- self.requests_counter = 0 # For generating monotonic request IDs.
- self._a2l_instances = [] # Up to |max_concurrent_jobs| _Addr2Line inst.
-
- # If necessary, create disambiguation lookup table
- self.disambiguate = source_root_path is not None
- self.disambiguation_table = {}
- self.strip_base_path = strip_base_path
- if (self.disambiguate):
- self.source_root_path = os.path.abspath(source_root_path)
- self._CreateDisambiguationTable()
-
- # Create one addr2line instance. More instances will be created on demand
- # (up to |max_concurrent_jobs|) depending on the rate of the requests.
- self._CreateNewA2LInstance()
-
- def SymbolizeAsync(self, addr, callback_arg=None):
- """Requests symbolization of a given address.
-
- This method is not guaranteed to return immediately. It generally does, but
- in some scenarios (e.g. all addr2line instances have full queues) it can
- block to create back-pressure.
-
- Args:
- addr: address to symbolize.
- callback_arg: optional argument which will be passed to the |callback|."""
- assert (isinstance(addr, int))
-
- # Process all the symbols that have been resolved in the meanwhile.
- # Essentially, this drains all the addr2line(s) out queues.
- for a2l_to_purge in self._a2l_instances:
- a2l_to_purge.ProcessAllResolvedSymbolsInQueue()
- a2l_to_purge.RecycleIfNecessary()
-
- # Find the best instance according to this logic:
- # 1. Find an existing instance with the shortest queue.
- # 2. If all of instances' queues are full, but there is room in the pool,
- # (i.e. < |max_concurrent_jobs|) create a new instance.
- # 3. If there were already |max_concurrent_jobs| instances and all of them
- # had full queues, make back-pressure.
-
- # 1.
- def _SortByQueueSizeAndReqID(a2l):
- return (a2l.queue_size, a2l.first_request_id)
-
- a2l = min(self._a2l_instances, key=_SortByQueueSizeAndReqID)
-
- # 2.
- if (a2l.queue_size >= self.max_queue_size and
- len(self._a2l_instances) < self.max_concurrent_jobs):
- a2l = self._CreateNewA2LInstance()
-
- # 3.
- if a2l.queue_size >= self.max_queue_size:
- a2l.WaitForNextSymbolInQueue()
-
- a2l.EnqueueRequest(addr, callback_arg)
-
- def Join(self):
- """Waits for all the outstanding requests to complete and terminates."""
- for a2l in self._a2l_instances:
- a2l.WaitForIdle()
- a2l.Terminate()
-
- def _CreateNewA2LInstance(self):
- assert (len(self._a2l_instances) < self.max_concurrent_jobs)
- a2l = ELFSymbolizer.Addr2Line(self)
- self._a2l_instances.append(a2l)
- return a2l
-
- def _CreateDisambiguationTable(self):
- """ Non-unique file names will result in None entries"""
- start_time = time.time()
- logging.info('Collecting information about available source files...')
- self.disambiguation_table = {}
-
- for root, _, filenames in os.walk(self.source_root_path):
- for f in filenames:
- self.disambiguation_table[f] = os.path.join(
- root, f) if (f not in self.disambiguation_table) else None
- logging.info(
- 'Finished collecting information about '
- 'possible files (took %.1f s).', (time.time() - start_time))
-
- class Addr2Line(object):
- """A python wrapper around an addr2line instance.
-
- The communication with the addr2line process looks as follows:
- [STDIN] [STDOUT] (from addr2line's viewpoint)
- > f001111
- > f002222
- < Symbol::Name(foo, bar) for f001111
- < /path/to/source/file.c:line_number
- > f003333
- < Symbol::Name2() for f002222
- < /path/to/source/file.c:line_number
- < Symbol::Name3() for f003333
- < /path/to/source/file.c:line_number
- """
-
- SYM_ADDR_RE = re.compile(r'([^:]+):(\?|\d+).*')
-
- def __init__(self, symbolizer):
- self._symbolizer = symbolizer
- self._lib_file_name = posixpath.basename(symbolizer.elf_file_path)
-
- # The request queue (i.e. addresses pushed to addr2line's stdin and not
- # yet retrieved on stdout)
- self._request_queue = collections.deque()
-
- # This is essentially len(self._request_queue). It has been optimized to a
- # separate field because turned out to be a perf hot-spot.
- self.queue_size = 0
-
- # Keep track of the number of symbols a process has processed to
- # avoid a single process growing too big and using all the memory.
- self._processed_symbols_count = 0
-
- # Objects required to handle the addr2line subprocess.
- self._proc = None # Subprocess.Popen(...) instance.
- self._thread = None # Threading.thread instance.
- self._out_queue = None # queue.Queue instance (for buffering a2l stdout).
- self._RestartAddr2LineProcess()
-
- def EnqueueRequest(self, addr, callback_arg):
- """Pushes an address to addr2line's stdin (and keeps track of it)."""
- self._symbolizer.requests_counter += 1 # For global "age" of requests.
- req_idx = self._symbolizer.requests_counter
- self._request_queue.append((addr, callback_arg, req_idx))
- self.queue_size += 1
- self._WriteToA2lStdin(addr)
-
- def WaitForIdle(self):
- """Waits until all the pending requests have been symbolized."""
- while self.queue_size > 0:
- self.WaitForNextSymbolInQueue()
-
- def WaitForNextSymbolInQueue(self):
- """Waits for the next pending request to be symbolized."""
- if not self.queue_size:
- return
-
- # This outer loop guards against a2l hanging (detecting stdout timeout).
- while True:
- start_time = datetime.datetime.now()
- timeout = datetime.timedelta(
- seconds=self._symbolizer.addr2line_timeout)
-
- # The inner loop guards against a2l crashing (checking if it exited).
- while (datetime.datetime.now() - start_time < timeout):
- # poll() returns !None if the process exited. a2l should never exit.
- if self._proc.poll():
- logging.warning(
- 'addr2line crashed, respawning (lib: %s).' %
- self._lib_file_name)
- self._RestartAddr2LineProcess()
- # TODO(primiano): the best thing to do in this case would be
- # shrinking the pool size as, very likely, addr2line is crashed
- # due to low memory (and the respawned one will die again soon).
-
- try:
- lines = self._out_queue.get(block=True, timeout=0.25)
- except queue.Empty:
- # On timeout (1/4 s.) repeat the inner loop and check if either the
- # addr2line process did crash or we waited its output for too long.
- continue
-
- # In nominal conditions, we get straight to this point.
- self._ProcessSymbolOutput(lines)
- return
-
- # If this point is reached, we waited more than |addr2line_timeout|.
- logging.warning('Hung addr2line process, respawning (lib: %s).'
- % self._lib_file_name)
- self._RestartAddr2LineProcess()
-
- def ProcessAllResolvedSymbolsInQueue(self):
- """Consumes all the addr2line output lines produced (without blocking)."""
- if not self.queue_size:
- return
- while True:
- try:
- lines = self._out_queue.get_nowait()
- except queue.Empty:
- break
- self._ProcessSymbolOutput(lines)
-
- def RecycleIfNecessary(self):
- """Restarts the process if it has been used for too long.
-
- A long running addr2line process will consume excessive amounts
- of memory without any gain in performance."""
- if self._processed_symbols_count >= ADDR2LINE_RECYCLE_LIMIT:
- self._RestartAddr2LineProcess()
-
- def Terminate(self):
- """Kills the underlying addr2line process.
-
- The poller |_thread| will terminate as well due to the broken pipe."""
- try:
- self._proc.kill()
- self._proc.communicate(
- ) # Essentially wait() without risking deadlock.
- except Exception: # An exception while terminating? How interesting.
- pass
- self._proc = None
-
- def _WriteToA2lStdin(self, addr):
- self._proc.stdin.write(('%s\n' % hex(addr)).encode())
- if self._symbolizer.inlines:
- # In the case of inlines we output an extra blank line, which causes
- # addr2line to emit a (??,??:0) tuple that we use as a boundary marker.
- self._proc.stdin.write('\n')
- self._proc.stdin.flush()
-
- def _ProcessSymbolOutput(self, lines):
- """Parses an addr2line symbol output and triggers the client callback."""
- (_, callback_arg, _) = self._request_queue.popleft()
- self.queue_size -= 1
-
- innermost_sym_info = None
- sym_info = None
- for (line1, line2) in lines:
- prev_sym_info = sym_info
- name = line1 if not line1.startswith('?') else None
- source_path = None
- source_line = None
- m = ELFSymbolizer.Addr2Line.SYM_ADDR_RE.match(line2)
- if m:
- if not m.group(1).startswith('?'):
- source_path = m.group(1)
- if not m.group(2).startswith('?'):
- source_line = int(m.group(2))
- else:
- logging.warning(
- 'Got invalid symbol path from addr2line: %s' % line2)
-
- # In case disambiguation is on, and needed
- was_ambiguous = False
- disambiguated = False
- if self._symbolizer.disambiguate:
- if source_path and not posixpath.isabs(source_path):
- path = self._symbolizer.disambiguation_table.get(
- source_path)
- was_ambiguous = True
- disambiguated = path is not None
- source_path = path if disambiguated else source_path
-
- # Use absolute paths (so that paths are consistent, as disambiguation
- # uses absolute paths)
- if source_path and not was_ambiguous:
- source_path = os.path.abspath(source_path)
-
- if source_path and self._symbolizer.strip_base_path:
- # Strip the base path
- source_path = re.sub(
- '^' + self._symbolizer.strip_base_path,
- self._symbolizer.source_root_path or '', source_path)
-
- sym_info = ELFSymbolInfo(name, source_path, source_line,
- was_ambiguous, disambiguated)
- if prev_sym_info:
- prev_sym_info.inlined_by = sym_info
- if not innermost_sym_info:
- innermost_sym_info = sym_info
-
- self._processed_symbols_count += 1
- self._symbolizer.callback(innermost_sym_info, callback_arg)
-
- def _RestartAddr2LineProcess(self):
- if self._proc:
- self.Terminate()
-
- # The only reason of existence of this Queue (and the corresponding
- # Thread below) is the lack of a subprocess.stdout.poll_avail_lines().
- # Essentially this is a pipe able to extract a couple of lines atomically.
- self._out_queue = queue.Queue()
-
- # Start the underlying addr2line process in line buffered mode.
-
- cmd = [
- self._symbolizer.addr2line_path, '--functions', '--demangle',
- '--exe=' + self._symbolizer.elf_file_path
- ]
- if self._symbolizer.inlines:
- cmd += ['--inlines']
- self._proc = subprocess.Popen(
- cmd,
- stdout=subprocess.PIPE,
- stdin=subprocess.PIPE,
- stderr=sys.stderr,
- close_fds=True)
-
- # Start the poller thread, which simply moves atomically the lines read
- # from the addr2line's stdout to the |_out_queue|.
- self._thread = threading.Thread(
- target=ELFSymbolizer.Addr2Line.StdoutReaderThread,
- args=(self._proc.stdout, self._out_queue,
- self._symbolizer.inlines))
- self._thread.daemon = True # Don't prevent early process exit.
- self._thread.start()
-
- self._processed_symbols_count = 0
-
- # Replay the pending requests on the new process (only for the case
- # of a hung addr2line timing out during the game).
- for (addr, _, _) in self._request_queue:
- self._WriteToA2lStdin(addr)
-
- @staticmethod
- def StdoutReaderThread(process_pipe, queue, inlines):
- """The poller thread fn, which moves the addr2line stdout to the |queue|.
-
- This is the only piece of code not running on the main thread. It merely
- writes to a Queue, which is thread-safe. In the case of inlines, it
- detects the ??,??:0 marker and sends the lines atomically, such that the
- main thread always receives all the lines corresponding to one symbol in
- one shot."""
- try:
- lines_for_one_symbol = []
- while True:
- line1 = process_pipe.readline().decode().rstrip('\r\n')
- line2 = process_pipe.readline().decode().rstrip('\r\n')
- if not line1 or not line2:
- break
- inline_has_more_lines = inlines and (
- len(lines_for_one_symbol) == 0 or
- (line1 != '??' and line2 != '??:0'))
- if not inlines or inline_has_more_lines:
- lines_for_one_symbol += [(line1, line2)]
- if inline_has_more_lines:
- continue
- queue.put(lines_for_one_symbol)
- lines_for_one_symbol = []
- process_pipe.close()
-
- # Every addr2line processes will die at some point, please die silently.
- except (IOError, OSError):
- pass
-
- @property
- def first_request_id(self):
- """Returns the request_id of the oldest pending request in the queue."""
- return self._request_queue[0][2] if self._request_queue else 0
-
-
-class ELFSymbolInfo(object):
- """The result of the symbolization passed as first arg. of each callback."""
-
- def __init__(self,
- name,
- source_path,
- source_line,
- was_ambiguous=False,
- disambiguated=False):
- """All the fields here can be None (if addr2line replies with '??')."""
- self.name = name
- self.source_path = source_path
- self.source_line = source_line
- # In the case of |inlines|=True, the |inlined_by| points to the outer
- # function inlining the current one (and so on, to form a chain).
- self.inlined_by = None
- self.disambiguated = disambiguated
- self.was_ambiguous = was_ambiguous
-
- def __str__(self):
- return '%s [%s:%d]' % (self.name or '??', self.source_path or '??',
- self.source_line or 0)
diff --git a/runtime/third_party/binary_size/src/explain_binary_size_delta.py b/runtime/third_party/binary_size/src/explain_binary_size_delta.py
deleted file mode 100755
index 13f7c12..0000000
--- a/runtime/third_party/binary_size/src/explain_binary_size_delta.py
+++ /dev/null
@@ -1,519 +0,0 @@
-#!/usr/bin/env python3
-# Copyright 2014 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-"""Describe the size difference of two binaries.
-
-Generates a description of the size difference of two binaries based
-on the difference of the size of various symbols.
-
-This tool needs "nm" dumps of each binary with full symbol
-information. You can obtain the necessary dumps by running the
-run_binary_size_analysis.py script upon each binary, with the
-"--nm-out" parameter set to the location in which you want to save the
-dumps. Example:
-
- # obtain symbol data from first binary in /tmp/nm1.dump
- cd $CHECKOUT1_SRC
- ninja -C out/Release binary_size_tool
- tools/binary_size/run_binary_size_analysis \
- --library <path_to_library>
- --destdir /tmp/throwaway
- --nm-out /tmp/nm1.dump
-
- # obtain symbol data from second binary in /tmp/nm2.dump
- cd $CHECKOUT2_SRC
- ninja -C out/Release binary_size_tool
- tools/binary_size/run_binary_size_analysis \
- --library <path_to_library>
- --destdir /tmp/throwaway
- --nm-out /tmp/nm2.dump
-
- # cleanup useless files
- rm -r /tmp/throwaway
-
- # run this tool
- explain_binary_size_delta.py --nm1 /tmp/nm1.dump --nm2 /tmp/nm2.dump
-"""
-
-import collections
-from collections import Counter
-from math import ceil
-import operator
-import optparse
-import os
-import sys
-
-import binary_size_utils
-
-
-def CalculateSharedAddresses(symbols):
- """Checks how many symbols share the same memory space. This returns a
-Counter result where result[address] will tell you how many times address was
-used by symbols."""
- count = Counter()
- for _, _, _, _, address in symbols:
- count[address] += 1
-
- return count
-
-
-def CalculateEffectiveSize(share_count, address, symbol_size):
- """Given a raw symbol_size and an address, this method returns the
- size we should blame on this symbol considering it might share the
- machine code/data with other symbols. Using the raw symbol_size for
- each symbol would in those cases over estimate the true cost of that
- block.
-
- """
- shared_count = share_count[address]
- if shared_count == 1:
- return symbol_size
-
- assert shared_count > 1
- return int(ceil(symbol_size / float(shared_count)))
-
-
-class SymbolDelta(object):
- """Stores old size, new size and some metadata."""
-
- def __init__(self, shared):
- self.old_size = None
- self.new_size = None
- self.shares_space_with_other_symbols = shared
-
- def __eq__(self, other):
- return (self.old_size == other.old_size and
- self.new_size == other.new_size and
- self.shares_space_with_other_symbols == other.
- shares_space_with_other_symbols)
-
- def __ne__(self, other):
- return not self.__eq__(other)
-
- def copy_symbol_delta(self):
- symbol_delta = SymbolDelta(self.shares_space_with_other_symbols)
- symbol_delta.old_size = self.old_size
- symbol_delta.new_size = self.new_size
- return symbol_delta
-
-
-class DeltaInfo(SymbolDelta):
- """Summary of a the change for one symbol between two instances."""
-
- def __init__(self, file_path, symbol_type, symbol_name, shared):
- SymbolDelta.__init__(self, shared)
- self.file_path = file_path
- self.symbol_type = symbol_type
- self.symbol_name = symbol_name
-
- def __eq__(self, other):
- return (self.file_path == other.file_path and
- self.symbol_type == other.symbol_type and
- self.symbol_name == other.symbol_name and
- SymbolDelta.__eq__(self, other))
-
- def __ne__(self, other):
- return not self.__eq__(other)
-
- def ExtractSymbolDelta(self):
- """Returns a copy of the SymbolDelta for this DeltaInfo."""
- return SymbolDelta.copy_symbol_delta(self)
-
-
-def Compare(symbols1, symbols2):
- """Executes a comparison of the symbols in symbols1 and symbols2.
-
- Returns:
- tuple of lists: (added_symbols, removed_symbols, changed_symbols, others)
- where each list contains DeltaInfo objects.
- """
- added = [] # tuples
- removed = [] # tuples
- changed = [] # tuples
- unchanged = [] # tuples
-
- cache1 = {}
- cache2 = {}
- # Make a map of (file, symbol_type) : (symbol_name, effective_symbol_size)
- share_count1 = CalculateSharedAddresses(symbols1)
- share_count2 = CalculateSharedAddresses(symbols2)
- for cache, symbols, share_count in ((cache1, symbols1, share_count1),
- (cache2, symbols2, share_count2)):
- for symbol_name, symbol_type, symbol_size, file_path, address in symbols:
- if 'vtable for ' in symbol_name:
- symbol_type = '@' # hack to categorize these separately
- if file_path:
- file_path = os.path.normpath(file_path)
- if sys.platform.startswith('win'):
- file_path = file_path.replace('\\', '/')
- else:
- file_path = '(No Path)'
- # Take into consideration that multiple symbols might share the same
- # block of code.
- effective_symbol_size = CalculateEffectiveSize(
- share_count, address, symbol_size)
- key = (file_path, symbol_type)
- bucket = cache.setdefault(key, {})
- size_list = bucket.setdefault(symbol_name, [])
- size_list.append((effective_symbol_size,
- effective_symbol_size != symbol_size))
-
- # Now diff them. We iterate over the elements in cache1. For each symbol
- # that we find in cache2, we record whether it was deleted, changed, or
- # unchanged. We then remove it from cache2; all the symbols that remain
- # in cache2 at the end of the iteration over cache1 are the 'new' symbols.
- for key, bucket1 in cache1.items():
- bucket2 = cache2.get(key)
- file_path, symbol_type = key
- if not bucket2:
- # A file was removed. Everything in bucket1 is dead.
- for symbol_name, symbol_size_list in bucket1.items():
- for (symbol_size, shared) in symbol_size_list:
- delta_info = DeltaInfo(file_path, symbol_type, symbol_name,
- shared)
- delta_info.old_size = symbol_size
- removed.append(delta_info)
- else:
- # File still exists, look for changes within.
- for symbol_name, symbol_size_list in bucket1.items():
- size_list2 = bucket2.get(symbol_name)
- if size_list2 is None:
- # Symbol no longer exists in bucket2.
- for (symbol_size, shared) in symbol_size_list:
- delta_info = DeltaInfo(file_path, symbol_type,
- symbol_name, shared)
- delta_info.old_size = symbol_size
- removed.append(delta_info)
- else:
- del bucket2[
- symbol_name] # Symbol is not new, delete from cache2.
- if len(symbol_size_list) == 1 and len(size_list2) == 1:
- symbol_size, shared1 = symbol_size_list[0]
- size2, shared2 = size_list2[0]
- delta_info = DeltaInfo(file_path, symbol_type,
- symbol_name, shared1 or shared2)
- delta_info.old_size = symbol_size
- delta_info.new_size = size2
- if symbol_size != size2:
- # Symbol has change size in bucket.
- changed.append(delta_info)
- else:
- # Symbol is unchanged.
- unchanged.append(delta_info)
- else:
- # Complex comparison for when a symbol exists multiple times
- # in the same file (where file can be "unknown file").
- symbol_size_counter = collections.Counter(
- symbol_size_list)
- delta_counter = collections.Counter(symbol_size_list)
- delta_counter.subtract(size_list2)
- for delta_counter_key in sorted(delta_counter.keys()):
- delta = delta_counter[delta_counter_key]
- unchanged_count = symbol_size_counter[
- delta_counter_key]
- (symbol_size, shared) = delta_counter_key
- if delta > 0:
- unchanged_count -= delta
- for _ in range(unchanged_count):
- delta_info = DeltaInfo(file_path, symbol_type,
- symbol_name, shared)
- delta_info.old_size = symbol_size
- delta_info.new_size = symbol_size
- unchanged.append(delta_info)
- if delta > 0: # Used to be more of these than there is now.
- for _ in range(delta):
- delta_info = DeltaInfo(
- file_path, symbol_type, symbol_name,
- shared)
- delta_info.old_size = symbol_size
- removed.append(delta_info)
- elif delta < 0: # More of this (symbol,size) now.
- for _ in range(-delta):
- delta_info = DeltaInfo(
- file_path, symbol_type, symbol_name,
- shared)
- delta_info.new_size = symbol_size
- added.append(delta_info)
-
- if len(bucket2) == 0:
- del cache1[
- key] # Entire bucket is empty, delete from cache2
-
- # We have now analyzed all symbols that are in cache1 and removed all of
- # the encountered symbols from cache2. What's left in cache2 is the new
- # symbols.
- for key, bucket2 in cache2.items():
- file_path, symbol_type = key
- for symbol_name, symbol_size_list in bucket2.items():
- for (symbol_size, shared) in symbol_size_list:
- delta_info = DeltaInfo(file_path, symbol_type, symbol_name,
- shared)
- delta_info.new_size = symbol_size
- added.append(delta_info)
- return (added, removed, changed, unchanged)
-
-
-def DeltaStr(number):
- """Returns the number as a string with a '+' prefix if it's > 0 and
- a '-' prefix if it's < 0."""
- result = str(number)
- if number > 0:
- result = '+' + result
- return result
-
-
-def SharedInfoStr(symbol_info):
- """Returns a string (prefixed by space) explaining that numbers are
- adjusted because of shared space between symbols, or an empty string
- if space had not been shared."""
-
- if symbol_info.shares_space_with_other_symbols:
- return " (adjusted sizes because of memory sharing)"
-
- return ""
-
-
-class CrunchStatsData(object):
- """Stores a summary of data of a certain kind."""
-
- def __init__(self, symbols):
- self.symbols = symbols
- self.sources = set()
- self.before_size = 0
- self.after_size = 0
- self.symbols_by_path = {}
-
-
-def CrunchStats(added, removed, changed, unchanged, showsources, showsymbols):
- """Outputs to stdout a summary of changes based on the symbol lists."""
- # Split changed into grown and shrunk because that is easier to
- # discuss.
- grown = []
- shrunk = []
- for item in changed:
- if item.old_size < item.new_size:
- grown.append(item)
- else:
- shrunk.append(item)
-
- new_symbols = CrunchStatsData(added)
- removed_symbols = CrunchStatsData(removed)
- grown_symbols = CrunchStatsData(grown)
- shrunk_symbols = CrunchStatsData(shrunk)
- sections = [new_symbols, removed_symbols, grown_symbols, shrunk_symbols]
- for section in sections:
- for item in section.symbols:
- section.sources.add(item.file_path)
- if item.old_size is not None:
- section.before_size += item.old_size
- if item.new_size is not None:
- section.after_size += item.new_size
- bucket = section.symbols_by_path.setdefault(item.file_path, [])
- bucket.append((item.symbol_name, item.symbol_type,
- item.ExtractSymbolDelta()))
-
- total_change = sum(s.after_size - s.before_size for s in sections)
- summary = 'Total change: %s bytes' % DeltaStr(total_change)
- print(summary)
- print('=' * len(summary))
- for section in sections:
- if not section.symbols:
- continue
- if section.before_size == 0:
- description = (
- 'added, totalling %s bytes' % DeltaStr(section.after_size))
- elif section.after_size == 0:
- description = (
- 'removed, totalling %s bytes' % DeltaStr(-section.before_size))
- else:
- if section.after_size > section.before_size:
- type_str = 'grown'
- else:
- type_str = 'shrunk'
- description = (
- '%s, for a net change of %s bytes '
- '(%d bytes before, %d bytes after)' %
- (type_str, DeltaStr(section.after_size - section.before_size),
- section.before_size, section.after_size))
- print(' %d %s across %d sources' % (len(section.symbols), description,
- len(section.sources)))
-
- maybe_unchanged_sources = set()
- unchanged_symbols_size = 0
- for item in unchanged:
- maybe_unchanged_sources.add(item.file_path)
- unchanged_symbols_size += item.old_size # == item.new_size
- print(' %d unchanged, totalling %d bytes' % (len(unchanged),
- unchanged_symbols_size))
-
- # High level analysis, always output.
- unchanged_sources = maybe_unchanged_sources
- for section in sections:
- unchanged_sources = unchanged_sources - section.sources
- new_sources = (
- new_symbols.sources - maybe_unchanged_sources - removed_symbols.sources)
- removed_sources = (
- removed_symbols.sources - maybe_unchanged_sources - new_symbols.sources)
- partially_changed_sources = (
- grown_symbols.sources | shrunk_symbols.sources | new_symbols.sources |
- removed_symbols.sources) - removed_sources - new_sources
- allFiles = set()
- for section in sections:
- allFiles = allFiles | section.sources
- allFiles = allFiles | maybe_unchanged_sources
- print('Source stats:')
- print(' %d sources encountered.' % len(allFiles))
- print(' %d completely new.' % len(new_sources))
- print(' %d removed completely.' % len(removed_sources))
- print(' %d partially changed.' % len(partially_changed_sources))
- print(' %d completely unchanged.' % len(unchanged_sources))
- remainder = (allFiles - new_sources - removed_sources -
- partially_changed_sources - unchanged_sources)
- assert len(remainder) == 0
-
- if not showsources:
- return # Per-source analysis, only if requested
- print('Per-source Analysis:')
- delta_by_path = {}
- for section in sections:
- for path in section.symbols_by_path:
- entry = delta_by_path.get(path)
- if not entry:
- entry = {'plus': 0, 'minus': 0}
- delta_by_path[path] = entry
- for symbol_name, symbol_type, symbol_delta in \
- section.symbols_by_path[path]:
- if symbol_delta.old_size is None:
- delta = symbol_delta.new_size
- elif symbol_delta.new_size is None:
- delta = -symbol_delta.old_size
- else:
- delta = symbol_delta.new_size - symbol_delta.old_size
-
- if delta > 0:
- entry['plus'] += delta
- else:
- entry['minus'] += (-1 * delta)
-
- def delta_sort_key(item):
- _path, size_data = item
- growth = size_data['plus'] - size_data['minus']
- return growth
-
- for path, size_data in sorted(delta_by_path.items(),
- key=delta_sort_key,
- reverse=True):
- gain = size_data['plus']
- loss = size_data['minus']
- delta = size_data['plus'] - size_data['minus']
- header = ' %s - Source: %s - (gained %d, lost %d)' % (DeltaStr(delta),
- path, gain, loss)
- divider = '-' * len(header)
- print('')
- print(divider)
- print(header)
- print(divider)
- if showsymbols:
-
- def ExtractNewSize(tup):
- symbol_delta = tup[2]
- return symbol_delta.new_size
-
- def ExtractOldSize(tup):
- symbol_delta = tup[2]
- return symbol_delta.old_size
-
- if path in new_symbols.symbols_by_path:
- print(' New symbols:')
- for symbol_name, symbol_type, symbol_delta in \
- sorted(new_symbols.symbols_by_path[path],
- key=ExtractNewSize,
- reverse=True):
- print(' %8s: %s type=%s, size=%d bytes%s' %
- (DeltaStr(symbol_delta.new_size), symbol_name,
- symbol_type, symbol_delta.new_size,
- SharedInfoStr(symbol_delta)))
- if path in removed_symbols.symbols_by_path:
- print(' Removed symbols:')
- for symbol_name, symbol_type, symbol_delta in \
- sorted(removed_symbols.symbols_by_path[path],
- key=ExtractOldSize):
- print(' %8s: %s type=%s, size=%d bytes%s' %
- (DeltaStr(-symbol_delta.old_size), symbol_name,
- symbol_type, symbol_delta.old_size,
- SharedInfoStr(symbol_delta)))
- for (changed_symbols_by_path,
- type_str) in [(grown_symbols.symbols_by_path, "Grown"),
- (shrunk_symbols.symbols_by_path, "Shrunk")]:
- if path in changed_symbols_by_path:
- print(' %s symbols:' % type_str)
-
- def changed_symbol_sortkey(item):
- symbol_name, _symbol_type, symbol_delta = item
- return (symbol_delta.old_size - symbol_delta.new_size,
- symbol_name)
-
- for symbol_name, symbol_type, symbol_delta in \
- sorted(changed_symbols_by_path[path], key=changed_symbol_sortkey):
- print(
- ' %8s: %s type=%s, (was %d bytes, now %d bytes)%s'
- % (DeltaStr(symbol_delta.new_size -
- symbol_delta.old_size), symbol_name,
- symbol_type,
- symbol_delta.old_size, symbol_delta.new_size,
- SharedInfoStr(symbol_delta)))
-
-
-def main():
- usage = """%prog [options]
-
- Analyzes the symbolic differences between two binary files
- (typically, not necessarily, two different builds of the same
- library) and produces a detailed description of symbols that have
- been added, removed, or whose size has changed.
-
- Example:
- explain_binary_size_delta.py --nm1 /tmp/nm1.dump --nm2 /tmp/nm2.dump
-
- Options are available via '--help'.
- """
- parser = optparse.OptionParser(usage=usage)
- parser.add_option(
- '--nm1', metavar='PATH', help='the nm dump of the first library')
- parser.add_option(
- '--nm2', metavar='PATH', help='the nm dump of the second library')
- parser.add_option(
- '--showsources',
- action='store_true',
- default=False,
- help='show per-source statistics')
- parser.add_option(
- '--showsymbols',
- action='store_true',
- default=False,
- help='show all symbol information; implies --showsources')
- parser.add_option(
- '--verbose',
- action='store_true',
- default=False,
- help='output internal debugging stuff')
- opts, _args = parser.parse_args()
-
- if not opts.nm1:
- parser.error('--nm1 is required')
- if not opts.nm2:
- parser.error('--nm2 is required')
- symbols = []
- for path in [opts.nm1, opts.nm2]:
- with open(path, 'r') as nm_input:
- if opts.verbose:
- print('parsing ' + path + '...')
- symbols.append(list(binary_size_utils.ParseNm(nm_input)))
- (added, removed, changed, unchanged) = Compare(symbols[0], symbols[1])
- CrunchStats(added, removed, changed, unchanged,
- opts.showsources | opts.showsymbols, opts.showsymbols)
-
-
-if __name__ == '__main__':
- sys.exit(main())
diff --git a/runtime/third_party/binary_size/src/run_binary_size_analysis.py b/runtime/third_party/binary_size/src/run_binary_size_analysis.py
deleted file mode 100755
index dfd5b97..0000000
--- a/runtime/third_party/binary_size/src/run_binary_size_analysis.py
+++ /dev/null
@@ -1,710 +0,0 @@
-#!/usr/bin/env python3
-# Copyright 2014 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-"""Generate a spatial analysis against an arbitrary library.
-
-To use, build the 'binary_size_tool' target. Then run this tool, passing
-in the location of the library to be analyzed along with any other options
-you desire.
-"""
-
-import json
-import logging
-import multiprocessing
-import optparse
-import os
-import re
-import shutil
-import struct
-import subprocess
-import sys
-import tempfile
-import time
-
-import binary_size_utils
-import elf_symbolizer
-
-# Node dictionary keys. These are output in json read by the webapp so
-# keep them short to save file size.
-# Note: If these change, the webapp must also change.
-NODE_TYPE_KEY = 'k'
-NODE_NAME_KEY = 'n'
-NODE_CHILDREN_KEY = 'children'
-NODE_SYMBOL_TYPE_KEY = 't'
-NODE_SYMBOL_SIZE_KEY = 'value'
-NODE_MAX_DEPTH_KEY = 'maxDepth'
-NODE_LAST_PATH_ELEMENT_KEY = 'lastPathElement'
-
-# The display name of the bucket where we put symbols without path.
-NAME_NO_PATH_BUCKET = '(No Path)'
-
-# Try to keep data buckets smaller than this to avoid killing the
-# graphing lib.
-BIG_BUCKET_LIMIT = 3000
-
-
-def _MkChild(node, name):
- child = node[NODE_CHILDREN_KEY].get(name)
- if child is None:
- child = {NODE_NAME_KEY: name, NODE_CHILDREN_KEY: {}}
- node[NODE_CHILDREN_KEY][name] = child
- return child
-
-
-def SplitNoPathBucket(node):
- """NAME_NO_PATH_BUCKET can be too large for the graphing lib to
- handle. Split it into sub-buckets in that case."""
- root_children = node[NODE_CHILDREN_KEY]
- if NAME_NO_PATH_BUCKET in root_children:
- no_path_bucket = root_children[NAME_NO_PATH_BUCKET]
- old_children = no_path_bucket[NODE_CHILDREN_KEY]
- count = 0
- for symbol_type, symbol_bucket in old_children.items():
- count += len(symbol_bucket[NODE_CHILDREN_KEY])
- if count > BIG_BUCKET_LIMIT:
- new_children = {}
- no_path_bucket[NODE_CHILDREN_KEY] = new_children
- current_bucket = None
- index = 0
- for symbol_type, symbol_bucket in old_children.items():
- for symbol_name, value in symbol_bucket[
- NODE_CHILDREN_KEY].items():
- if index % BIG_BUCKET_LIMIT == 0:
- group_no = (index / BIG_BUCKET_LIMIT) + 1
- current_bucket = _MkChild(
- no_path_bucket,
- '%s subgroup %d' % (NAME_NO_PATH_BUCKET, group_no))
- assert not NODE_TYPE_KEY in node or node[
- NODE_TYPE_KEY] == 'p'
- node[NODE_TYPE_KEY] = 'p' # p for path
- index += 1
- symbol_size = value[NODE_SYMBOL_SIZE_KEY]
- AddSymbolIntoFileNode(current_bucket, symbol_type,
- symbol_name, symbol_size)
-
-
-def MakeChildrenDictsIntoLists(node):
- largest_list_len = 0
- if NODE_CHILDREN_KEY in node:
- largest_list_len = len(node[NODE_CHILDREN_KEY])
- child_list = []
- for child in node[NODE_CHILDREN_KEY].values():
- child_largest_list_len = MakeChildrenDictsIntoLists(child)
- if child_largest_list_len > largest_list_len:
- largest_list_len = child_largest_list_len
- child_list.append(child)
- node[NODE_CHILDREN_KEY] = child_list
-
- return largest_list_len
-
-
-def AddSymbolIntoFileNode(node, symbol_type, symbol_name, symbol_size):
- """Puts symbol into the file path node |node|.
- Returns the number of added levels in tree. I.e. returns 2."""
-
- # 'node' is the file node and first step is to find its symbol-type bucket.
- node[NODE_LAST_PATH_ELEMENT_KEY] = True
- node = _MkChild(node, symbol_type)
- assert not NODE_TYPE_KEY in node or node[NODE_TYPE_KEY] == 'b'
- node[NODE_SYMBOL_TYPE_KEY] = symbol_type
- node[NODE_TYPE_KEY] = 'b' # b for bucket
-
- # 'node' is now the symbol-type bucket. Make the child entry.
- node = _MkChild(node, symbol_name)
- if NODE_CHILDREN_KEY in node:
- if node[NODE_CHILDREN_KEY]:
- logging.warning(
- 'A container node used as symbol for %s.' % symbol_name)
- # This is going to be used as a leaf so no use for child list.
- del node[NODE_CHILDREN_KEY]
- node[NODE_SYMBOL_SIZE_KEY] = symbol_size
- node[NODE_SYMBOL_TYPE_KEY] = symbol_type
- node[NODE_TYPE_KEY] = 's' # s for symbol
-
- return 2 # Depth of the added subtree.
-
-
-def MakeCompactTree(symbols, symbol_path_origin_dir):
- result = {
- NODE_NAME_KEY: '/',
- NODE_CHILDREN_KEY: {},
- NODE_TYPE_KEY: 'p',
- NODE_MAX_DEPTH_KEY: 0
- }
- seen_symbol_with_path = False
- cwd = os.path.abspath(os.getcwd())
- for symbol_name, symbol_type, symbol_size, file_path, _address in symbols:
-
- if 'vtable for ' in symbol_name:
- symbol_type = '@' # hack to categorize these separately
- # Take path like '/foo/bar/baz', convert to ['foo', 'bar', 'baz']
- if file_path and file_path != "??":
- file_path = os.path.abspath(
- os.path.join(symbol_path_origin_dir, file_path))
- # Let the output structure be relative to $CWD if inside $CWD,
- # otherwise relative to the disk root. This is to avoid
- # unnecessary click-through levels in the output.
- if file_path.startswith(cwd + os.sep):
- file_path = file_path[len(cwd):]
- if file_path.startswith('/'):
- file_path = file_path[1:]
- seen_symbol_with_path = True
- else:
- file_path = NAME_NO_PATH_BUCKET
-
- path_parts = file_path.split('/')
-
- # Find pre-existing node in tree, or update if it already exists
- node = result
- depth = 0
- while len(path_parts) > 0:
- path_part = path_parts.pop(0)
- if len(path_part) == 0:
- continue
- depth += 1
- node = _MkChild(node, path_part)
- assert not NODE_TYPE_KEY in node or node[NODE_TYPE_KEY] == 'p'
- node[NODE_TYPE_KEY] = 'p' # p for path
-
- depth += AddSymbolIntoFileNode(node, symbol_type, symbol_name,
- symbol_size)
- result[NODE_MAX_DEPTH_KEY] = max(result[NODE_MAX_DEPTH_KEY], depth)
-
- if not seen_symbol_with_path:
- logging.warning('Symbols lack paths. Data will not be structured.')
-
- # The (no path) bucket can be extremely large if we failed to get
- # path information. Split it into subgroups if needed.
- SplitNoPathBucket(result)
-
- largest_list_len = MakeChildrenDictsIntoLists(result)
-
- if largest_list_len > BIG_BUCKET_LIMIT:
- logging.warning('There are sections with %d nodes. '
- 'Results might be unusable.' % largest_list_len)
- return result
-
-
-def DumpCompactTree(symbols, symbol_path_origin_dir, outfile):
- tree_root = MakeCompactTree(symbols, symbol_path_origin_dir)
- with open(outfile, 'w') as out:
- out.write('var tree_data=')
- # Use separators without whitespace to get a smaller file.
- json.dump(tree_root, out, separators=(',', ':'))
- print('Writing %d bytes json' % os.path.getsize(outfile))
-
-
-def MakeSourceMap(symbols):
- sources = {}
- for _sym, _symbol_type, size, path, _address in symbols:
- key = None
- if path:
- key = os.path.normpath(path)
- else:
- key = '[no path]'
- if key not in sources:
- sources[key] = {'path': path, 'symbol_count': 0, 'size': 0}
- record = sources[key]
- record['size'] += size
- record['symbol_count'] += 1
- return sources
-
-
-# Regex for parsing "nm" output. A sample line looks like this:
-# 0167b39c 00000018 t ACCESS_DESCRIPTION_free /path/file.c:95
-#
-# The fields are: address, size, type, name, source location
-# Regular expression explained ( see also: https://xkcd.com/208 ):
-# ([0-9a-f]{8,}+) The address
-# [\s]+ Whitespace separator
-# ([0-9a-f]{8,}+) The size. From here on out it's all optional.
-# [\s]+ Whitespace separator
-# (\S?) The symbol type, which is any non-whitespace char
-# [\s*] Whitespace separator
-# ([^\t]*) Symbol name, any non-tab character (spaces ok!)
-# [\t]? Tab separator
-# (.*) The location (filename[:linennum|?][ (discriminator n)]
-sNmPattern = re.compile(
- r'([0-9a-f]{8,})[\s]+([0-9a-f]{8,})[\s]*(\S?)[\s*]([^\t]*)[\t]?(.*)')
-
-
-class Progress():
-
- def __init__(self):
- self.count = 0
- self.skip_count = 0
- self.collisions = 0
- self.time_last_output = time.time()
- self.count_last_output = 0
- self.disambiguations = 0
- self.was_ambiguous = 0
-
-
-def RunElfSymbolizer(outfile, library, addr2line_binary, nm_binary, jobs,
- disambiguate, src_path):
- nm_output = RunNm(library, nm_binary)
- nm_output_lines = nm_output.splitlines()
- nm_output_lines_len = len(nm_output_lines)
- address_symbol = {}
- progress = Progress()
-
- def map_address_symbol(symbol, addr):
- progress.count += 1
- if addr in address_symbol:
- # 'Collision between %s and %s.' % (str(symbol.name),
- # str(address_symbol[addr].name))
- progress.collisions += 1
- else:
- if symbol.disambiguated:
- progress.disambiguations += 1
- if symbol.was_ambiguous:
- progress.was_ambiguous += 1
-
- address_symbol[addr] = symbol
-
- progress_output()
-
- def progress_output():
- progress_chunk = 100
- if progress.count % progress_chunk == 0:
- time_now = time.time()
- time_spent = time_now - progress.time_last_output
- if time_spent > 1.0:
- # Only output at most once per second.
- progress.time_last_output = time_now
- chunk_size = progress.count - progress.count_last_output
- progress.count_last_output = progress.count
- if time_spent > 0:
- speed = chunk_size / time_spent
- else:
- speed = 0
- progress_percent = (100.0 * (
- progress.count + progress.skip_count) / nm_output_lines_len)
- disambiguation_percent = 0
- if progress.disambiguations != 0:
- disambiguation_percent = (100.0 * progress.disambiguations /
- progress.was_ambiguous)
-
- sys.stdout.write(
- '\r%.1f%%: Looked up %d symbols (%d collisions, '
- '%d disambiguations where %.1f%% succeeded)'
- ' - %.1f lookups/s.' %
- (progress_percent, progress.count, progress.collisions,
- progress.disambiguations, disambiguation_percent, speed))
-
- # In case disambiguation was disabled, we remove the source path (which upon
- # being set signals the symbolizer to enable disambiguation)
- if not disambiguate:
- src_path = None
- symbolizer = elf_symbolizer.ELFSymbolizer(
- library,
- addr2line_binary,
- map_address_symbol,
- max_concurrent_jobs=jobs,
- source_root_path=src_path)
- user_interrupted = False
- try:
- for binary_line in nm_output_lines:
- line = binary_line.decode()
- match = sNmPattern.match(line)
- if match:
- location = match.group(5)
- if not location:
- addr = int(match.group(1), 16)
- size = int(match.group(2), 16)
- if addr in address_symbol: # Already looked up, shortcut
- # ELFSymbolizer.
- map_address_symbol(address_symbol[addr], addr)
- continue
- elif size == 0:
- # Save time by not looking up empty symbols (do they even exist?)
- print('Empty symbol: ' + line)
- else:
- symbolizer.SymbolizeAsync(addr, addr)
- continue
-
- progress.skip_count += 1
- except KeyboardInterrupt:
- user_interrupted = True
- print('Interrupting - killing subprocesses. Please wait.')
-
- try:
- symbolizer.Join()
- except KeyboardInterrupt:
- # Don't want to abort here since we will be finished in a few seconds.
- user_interrupted = True
- print('Patience you must have my young padawan.')
-
- print('')
-
- if user_interrupted:
- print('Skipping the rest of the file mapping. '
- 'Output will not be fully classified.')
-
- symbol_path_origin_dir = os.path.dirname(os.path.abspath(library))
-
- with open(outfile, 'w') as out:
- for binary_line in nm_output_lines:
- line = binary_line.decode()
- match = sNmPattern.match(line)
- if match:
- location = match.group(5)
- if not location:
- addr = int(match.group(1), 16)
- symbol = address_symbol.get(addr)
- if symbol is not None:
- path = '??'
- if symbol.source_path is not None:
- path = os.path.abspath(
- os.path.join(symbol_path_origin_dir,
- symbol.source_path))
- line_number = 0
- if symbol.source_line is not None:
- line_number = symbol.source_line
- out.write('%s\t%s:%d\n' % (line, path, line_number))
- continue
-
- out.write('%s\n' % line)
-
- print('%d symbols in the results.' % len(address_symbol))
-
-
-def RunNm(binary, nm_binary):
- cmd = [
- nm_binary, '-C', '--print-size', '--size-sort', '--reverse-sort', binary
- ]
- nm_process = subprocess.Popen(
- cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
- (process_output, err_output) = nm_process.communicate()
-
- if nm_process.returncode != 0:
- if err_output:
- raise Exception(err_output)
- else:
- raise Exception(process_output)
-
- return process_output
-
-
-def GetNmSymbols(nm_infile, outfile, library, jobs, verbose, addr2line_binary,
- nm_binary, disambiguate, src_path):
- if nm_infile is None:
- if outfile is None:
- outfile = tempfile.NamedTemporaryFile(delete=False).name
-
- if verbose:
- print('Running parallel addr2line, dumping symbols to ' + outfile)
- RunElfSymbolizer(outfile, library, addr2line_binary, nm_binary, jobs,
- disambiguate, src_path)
-
- nm_infile = outfile
-
- elif verbose:
- print('Using nm input from ' + nm_infile)
- with open(nm_infile, 'r') as infile:
- return list(binary_size_utils.ParseNm(infile))
-
-
-PAK_RESOURCE_ID_TO_STRING = {"inited": False}
-
-
-def LoadPakIdsFromResourceFile(filename):
- """Given a file name, it loads everything that looks like a resource id
- into PAK_RESOURCE_ID_TO_STRING."""
- with open(filename) as resource_header:
- for line in resource_header:
- if line.startswith("#define "):
- line_data = line.split()
- if len(line_data) == 3:
- try:
- resource_number = int(line_data[2])
- resource_name = line_data[1]
- PAK_RESOURCE_ID_TO_STRING[
- resource_number] = resource_name
- except ValueError:
- pass
-
-
-def GetReadablePakResourceName(pak_file, resource_id):
- """Pak resources have a numeric identifier. It is not helpful when
- trying to locate where footprint is generated. This does its best to
- map the number to a usable string."""
- if not PAK_RESOURCE_ID_TO_STRING['inited']:
- # Try to find resource header files generated by grit when
- # building the pak file. We'll look for files named *resources.h"
- # and lines of the type:
- # #define MY_RESOURCE_JS 1234
- PAK_RESOURCE_ID_TO_STRING['inited'] = True
- gen_dir = os.path.join(os.path.dirname(pak_file), 'gen')
- if os.path.isdir(gen_dir):
- for dirname, _dirs, files in os.walk(gen_dir):
- for filename in files:
- if filename.endswith('resources.h'):
- LoadPakIdsFromResourceFile(
- os.path.join(dirname, filename))
- return PAK_RESOURCE_ID_TO_STRING.get(resource_id,
- 'Pak Resource %d' % resource_id)
-
-
-def AddPakData(symbols, pak_file):
- """Adds pseudo-symbols from a pak file."""
- pak_file = os.path.abspath(pak_file)
- with open(pak_file, 'rb') as pak:
- data = pak.read()
-
- PAK_FILE_VERSION = 4
- HEADER_LENGTH = 2 * 4 + 1 # Two uint32s. (file version, number of entries)
- # and one uint8 (encoding of text resources)
- INDEX_ENTRY_SIZE = 2 + 4 # Each entry is a uint16 and a uint32.
- version, num_entries, _encoding = struct.unpack('<IIB',
- data[:HEADER_LENGTH])
- assert version == PAK_FILE_VERSION, (
- 'Unsupported pak file '
- 'version (%d) in %s. Only '
- 'support version %d' % (version, pak_file, PAK_FILE_VERSION))
- if num_entries > 0:
- # Read the index and data.
- data = data[HEADER_LENGTH:]
- for _ in range(num_entries):
- resource_id, offset = struct.unpack('<HI', data[:INDEX_ENTRY_SIZE])
- data = data[INDEX_ENTRY_SIZE:]
- _next_id, next_offset = struct.unpack('<HI',
- data[:INDEX_ENTRY_SIZE])
- resource_size = next_offset - offset
-
- symbol_name = GetReadablePakResourceName(pak_file, resource_id)
- symbol_path = pak_file
- symbol_type = 'd' # Data. Approximation.
- symbol_size = resource_size
- symbols.append((symbol_name, symbol_type, symbol_size, symbol_path))
-
-
-def _find_in_system_path(binary):
- """Locate the full path to binary in the system path or return None
- if not found."""
- system_path = os.environ["PATH"].split(os.pathsep)
- for path in system_path:
- binary_path = os.path.join(path, binary)
- if os.path.isfile(binary_path):
- return binary_path
- return None
-
-
-def CheckDebugFormatSupport(library, addr2line_binary):
- """Kills the program if debug data is in an unsupported format.
-
- There are two common versions of the DWARF debug formats and
- since we are right now transitioning from DWARF2 to newer formats,
- it's possible to have a mix of tools that are not compatible. Detect
- that and abort rather than produce meaningless output."""
- tool_output = subprocess.check_output([addr2line_binary,
- '--version']).decode()
- version_re = re.compile(r'^GNU [^ ]+ .* (\d+).(\d+).*?$', re.M)
- parsed_output = version_re.match(tool_output)
- major = int(parsed_output.group(1))
- minor = int(parsed_output.group(2))
- supports_dwarf4 = major > 2 or major == 2 and minor > 22
-
- if supports_dwarf4:
- return
-
- print('Checking version of debug information in %s.' % library)
- debug_info = subprocess.check_output(
- ['readelf', '--debug-dump=info', '--dwarf-depth=1', library])
- dwarf_version_re = re.compile(r'^\s+Version:\s+(\d+)$', re.M)
- parsed_dwarf_format_output = dwarf_version_re.search(debug_info)
- version = int(parsed_dwarf_format_output.group(1))
- if version > 2:
- print(
- 'The supplied tools only support DWARF2 debug data but the binary\n'
- + 'uses DWARF%d. Update the tools or compile the binary\n' % version
- + 'with -gdwarf-2.')
- sys.exit(1)
-
-
-def main():
- usage = """%prog [options]
-
- Runs a spatial analysis on a given library, looking up the source locations
- of its symbols and calculating how much space each directory, source file,
- and so on is taking. The result is a report that can be used to pinpoint
- sources of large portions of the binary, etceteras.
-
- Under normal circumstances, you only need to pass two arguments, thusly:
-
- %prog --library /path/to/library --destdir /path/to/output
-
- In this mode, the program will dump the symbols from the specified library
- and map those symbols back to source locations, producing a web-based
- report in the specified output directory.
-
- Other options are available via '--help'.
- """
- parser = optparse.OptionParser(usage=usage)
- parser.add_option(
- '--nm-in',
- metavar='PATH',
- help='if specified, use nm input from <path> instead of '
- 'generating it. Note that source locations should be '
- 'present in the file; i.e., no addr2line symbol lookups '
- 'will be performed when this option is specified. '
- 'Mutually exclusive with --library.')
- parser.add_option(
- '--destdir',
- metavar='PATH',
- help='write output to the specified directory. An HTML '
- 'report is generated here along with supporting files; '
- 'any existing report will be overwritten.')
- parser.add_option(
- '--library',
- metavar='PATH',
- help='if specified, process symbols in the library at '
- 'the specified path. Mutually exclusive with --nm-in.')
- parser.add_option(
- '--pak',
- metavar='PATH',
- help='if specified, includes the contents of the '
- 'specified *.pak file in the output.')
- parser.add_option(
- '--nm-binary',
- help='use the specified nm binary to analyze library. '
- 'This is to be used when the nm in the path is not for '
- 'the right architecture or of the right version.')
- parser.add_option(
- '--addr2line-binary',
- help='use the specified addr2line binary to analyze '
- 'library. This is to be used when the addr2line in '
- 'the path is not for the right architecture or '
- 'of the right version.')
- parser.add_option(
- '--jobs',
- type='int',
- help='number of jobs to use for the parallel '
- 'addr2line processing pool; defaults to 1. More '
- 'jobs greatly improve throughput but eat RAM like '
- 'popcorn, and take several gigabytes each. Start low '
- 'and ramp this number up until your machine begins to '
- 'struggle with RAM. '
- 'This argument is only valid when using --library.')
- parser.add_option(
- '-v',
- '--verbose',
- dest='verbose',
- action='store_true',
- help='be verbose, printing lots of status information.')
- parser.add_option(
- '--nm-out',
- metavar='PATH',
- help='(deprecated) No-op. nm.out is stored in --destdir.')
- parser.add_option(
- '--no-nm-out',
- action='store_true',
- help='do not keep the nm output file. This file is useful '
- 'if you want to see the fully processed nm output after '
- 'the symbols have been mapped to source locations, or if '
- 'you plan to run explain_binary_size_delta.py. By default '
- 'the file \'nm.out\' is placed alongside the generated '
- 'report. The nm.out file is only created when using '
- '--library.')
- parser.add_option(
- '--disable-disambiguation',
- action='store_true',
- help='disables the disambiguation process altogether,'
- ' NOTE: this may, depending on your toolchain, produce'
- ' output with some symbols at the top layer if addr2line'
- ' could not get the entire source path.')
- parser.add_option(
- '--source-path',
- default='./',
- help='the path to the source code of the output binary, '
- 'default set to current directory. Used in the'
- ' disambiguation process.')
- opts, _args = parser.parse_args()
-
- if ((not opts.library) and
- (not opts.nm_in)) or (opts.library and opts.nm_in):
- parser.error('exactly one of --library or --nm-in is required')
- if opts.nm_out:
- print('WARNING: --nm-out is deprecated and has no effect.',
- file=sys.stderr)
- if (opts.nm_in):
- if opts.jobs:
- print('WARNING: --jobs has no effect when used with --nm-in',
- file=sys.stderr)
- if not opts.destdir:
- parser.error('--destdir is a required argument')
- if not opts.jobs:
- # Use the number of processors but cap between 2 and 4 since raw
- # CPU power isn't the limiting factor. It's I/O limited, memory
- # bus limited and available-memory-limited. Too many processes and
- # the computer will run out of memory and it will be slow.
- opts.jobs = max(2, min(4, multiprocessing.cpu_count()))
-
- if opts.addr2line_binary:
- assert os.path.isfile(opts.addr2line_binary)
- addr2line_binary = opts.addr2line_binary
- else:
- addr2line_binary = _find_in_system_path('addr2line')
- assert addr2line_binary, 'Unable to find addr2line in the path. '\
- 'Use --addr2line-binary to specify location.'
-
- if opts.nm_binary:
- assert os.path.isfile(opts.nm_binary)
- nm_binary = opts.nm_binary
- else:
- nm_binary = _find_in_system_path('nm')
- assert nm_binary, 'Unable to find nm in the path. Use --nm-binary '\
- 'to specify location.'
-
- if opts.pak:
- assert os.path.isfile(opts.pak), 'Could not find ' % opts.pak
-
- print('addr2line: %s' % addr2line_binary)
- print('nm: %s' % nm_binary)
-
- if opts.library:
- CheckDebugFormatSupport(opts.library, addr2line_binary)
-
- # Prepare output directory and report guts
- if not os.path.exists(opts.destdir):
- os.makedirs(opts.destdir, 0o755)
- nm_out = os.path.join(opts.destdir, 'nm.out')
- if opts.no_nm_out:
- nm_out = None
-
- # Copy report boilerplate into output directory. This also proves that the
- # output directory is safe for writing, so there should be no problems writing
- # the nm.out file later.
- data_js_file_name = os.path.join(opts.destdir, 'data.js')
- d3_out = os.path.join(opts.destdir, 'd3')
- if not os.path.exists(d3_out):
- os.makedirs(d3_out, 0o755)
- d3_src = os.path.join(os.path.dirname(__file__), '..', '..', 'd3', 'src')
- template_src = os.path.join(os.path.dirname(__file__), 'template')
- shutil.copy(os.path.join(d3_src, 'LICENSE'), d3_out)
- shutil.copy(os.path.join(d3_src, 'd3.js'), d3_out)
- shutil.copy(os.path.join(template_src, 'index.html'), opts.destdir)
- shutil.copy(os.path.join(template_src, 'D3SymbolTreeMap.js'), opts.destdir)
-
- # Run nm and/or addr2line to gather the data
- symbols = GetNmSymbols(opts.nm_in, nm_out, opts.library, opts.jobs,
- opts.verbose is True, addr2line_binary, nm_binary,
- opts.disable_disambiguation is None,
- opts.source_path)
-
- # Post-processing
- if opts.pak:
- AddPakData(symbols, opts.pak)
- if opts.library:
- symbol_path_origin_dir = os.path.dirname(os.path.abspath(opts.library))
- else:
- # Just a guess. Hopefully all paths in the input file are absolute.
- symbol_path_origin_dir = os.path.abspath(os.getcwd())
- # Dump JSON for the HTML report.
- DumpCompactTree(symbols, symbol_path_origin_dir, data_js_file_name)
- print('Report saved to ' + opts.destdir + '/index.html')
-
-
-if __name__ == '__main__':
- sys.exit(main())
diff --git a/runtime/third_party/binary_size/src/template/D3SymbolTreeMap.js b/runtime/third_party/binary_size/src/template/D3SymbolTreeMap.js
deleted file mode 100644
index 88dd692..0000000
--- a/runtime/third_party/binary_size/src/template/D3SymbolTreeMap.js
+++ /dev/null
@@ -1,938 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// TODO:
-// 1. Visibility functions: base on boxPadding.t, not 15
-// 2. Track a maxDisplayDepth that is user-settable:
-// maxDepth == currentRoot.depth + maxDisplayDepth
-function D3SymbolTreeMap(mapWidth, mapHeight, levelsToShow) {
- this._mapContainer = undefined;
- this._mapWidth = mapWidth;
- this._mapHeight = mapHeight;
- this.boxPadding = {'l': 5, 'r': 5, 't': 20, 'b': 5};
- this.infobox = undefined;
- this._maskContainer = undefined;
- this._highlightContainer = undefined;
- // Transition in this order:
- // 1. Exiting items go away.
- // 2. Updated items move.
- // 3. New items enter.
- this._exitDuration=500;
- this._updateDuration=500;
- this._enterDuration=500;
- this._firstTransition=true;
- this._layout = undefined;
- this._currentRoot = undefined;
- this._currentNodes = undefined;
- this._treeData = undefined;
- this._maxLevelsToShow = levelsToShow;
- this._currentMaxDepth = this._maxLevelsToShow;
-}
-
-/**
- * Make a number pretty, with comma separators.
- */
-D3SymbolTreeMap._pretty = function(num) {
- var asString = String(num);
- var result = '';
- var counter = 0;
- for (var x = asString.length - 1; x >= 0; x--) {
- counter++;
- if (counter === 4) {
- result = ',' + result;
- counter = 1;
- }
- result = asString.charAt(x) + result;
- }
- return result;
-}
-
-/**
- * Express a number in terms of KiB, MiB, GiB, etc.
- * Note that these are powers of 2, not of 10.
- */
-D3SymbolTreeMap._byteify = function(num) {
- var suffix;
- if (num >= 1024) {
- if (num >= 1024 * 1024 * 1024) {
- suffix = 'GiB';
- num = num / (1024 * 1024 * 1024);
- } else if (num >= 1024 * 1024) {
- suffix = 'MiB';
- num = num / (1024 * 1024);
- } else if (num >= 1024) {
- suffix = 'KiB'
- num = num / 1024;
- }
- return num.toFixed(2) + ' ' + suffix;
- }
- return num + ' B';
-}
-
-D3SymbolTreeMap._NM_SYMBOL_TYPE_DESCRIPTIONS = {
- // Definitions concisely derived from the nm 'man' page
- 'A': 'Global absolute (A)',
- 'B': 'Global uninitialized data (B)',
- 'b': 'Local uninitialized data (b)',
- 'C': 'Global uninitialized common (C)',
- 'D': 'Global initialized data (D)',
- 'd': 'Local initialized data (d)',
- 'G': 'Global small initialized data (G)',
- 'g': 'Local small initialized data (g)',
- 'i': 'Indirect function (i)',
- 'N': 'Debugging (N)',
- 'p': 'Stack unwind (p)',
- 'R': 'Global read-only data (R)',
- 'r': 'Local read-only data (r)',
- 'S': 'Global small uninitialized data (S)',
- 's': 'Local small uninitialized data (s)',
- 'T': 'Global code (T)',
- 't': 'Local code (t)',
- 'U': 'Undefined (U)',
- 'u': 'Unique (u)',
- 'V': 'Global weak object (V)',
- 'v': 'Local weak object (v)',
- 'W': 'Global weak symbol (W)',
- 'w': 'Local weak symbol (w)',
- '@': 'Vtable entry (@)', // non-standard, hack.
- '-': 'STABS debugging (-)',
- '?': 'Unrecognized (?)',
-};
-D3SymbolTreeMap._NM_SYMBOL_TYPES = '';
-for (var symbol_type in D3SymbolTreeMap._NM_SYMBOL_TYPE_DESCRIPTIONS) {
- D3SymbolTreeMap._NM_SYMBOL_TYPES += symbol_type;
-}
-
-/**
- * Given a symbol type code, look up and return a human-readable description
- * of that symbol type. If the symbol type does not match one of the known
- * types, the unrecognized description (corresponding to symbol type '?') is
- * returned instead of null or undefined.
- */
-D3SymbolTreeMap._getSymbolDescription = function(type) {
- var result = D3SymbolTreeMap._NM_SYMBOL_TYPE_DESCRIPTIONS[type];
- if (result === undefined) {
- result = D3SymbolTreeMap._NM_SYMBOL_TYPE_DESCRIPTIONS['?'];
- }
- return result;
-}
-
-// Qualitative 12-value pastel Brewer palette.
-D3SymbolTreeMap._colorArray = [
- 'rgb(141,211,199)',
- 'rgb(255,255,179)',
- 'rgb(190,186,218)',
- 'rgb(251,128,114)',
- 'rgb(128,177,211)',
- 'rgb(253,180,98)',
- 'rgb(179,222,105)',
- 'rgb(252,205,229)',
- 'rgb(217,217,217)',
- 'rgb(188,128,189)',
- 'rgb(204,235,197)',
- 'rgb(255,237,111)'];
-
-D3SymbolTreeMap._initColorMap = function() {
- var map = {};
- var numColors = D3SymbolTreeMap._colorArray.length;
- var count = 0;
- for (var key in D3SymbolTreeMap._NM_SYMBOL_TYPE_DESCRIPTIONS) {
- var index = count++ % numColors;
- map[key] = d3.rgb(D3SymbolTreeMap._colorArray[index]);
- }
- D3SymbolTreeMap._colorMap = map;
-}
-D3SymbolTreeMap._initColorMap();
-
-D3SymbolTreeMap.getColorForType = function(type) {
- var result = D3SymbolTreeMap._colorMap[type];
- if (result === undefined) return d3.rgb('rgb(255,255,255)');
- return result;
-}
-
-D3SymbolTreeMap.prototype.init = function() {
- this.infobox = this._createInfoBox();
- this._mapContainer = d3.select('body').append('div')
- .style('position', 'relative')
- .style('width', this._mapWidth)
- .style('height', this._mapHeight)
- .style('padding', 0)
- .style('margin', 0)
- .style('box-shadow', '5px 5px 5px #888');
- this._layout = this._createTreeMapLayout();
- this._setData(tree_data); // TODO: Don't use global 'tree_data'
-}
-
-/**
- * Sets the data displayed by the treemap and layint out the map.
- */
-D3SymbolTreeMap.prototype._setData = function(data) {
- this._treeData = data;
- console.time('_crunchStats');
- this._crunchStats(data);
- console.timeEnd('_crunchStats');
- this._currentRoot = this._treeData;
- this._currentNodes = this._layout.nodes(this._currentRoot);
- this._currentMaxDepth = this._maxLevelsToShow;
- this._doLayout();
-}
-
-/**
- * Recursively traverses the entire tree starting from the specified node,
- * computing statistics and recording metadata as it goes. Call this method
- * only once per imported tree.
- */
-D3SymbolTreeMap.prototype._crunchStats = function(node) {
- var stack = [];
- stack.idCounter = 0;
- this._crunchStatsHelper(stack, node);
-}
-
-/**
- * Invoke the specified visitor function on all data elements currently shown
- * in the treemap including any and all of their children, starting at the
- * currently-displayed root and descending recursively. The function will be
- * passed the datum element representing each node. No traversal guarantees
- * are made.
- */
-D3SymbolTreeMap.prototype.visitFromDisplayedRoot = function(visitor) {
- this._visit(this._currentRoot, visitor);
-}
-
-/**
- * Helper function for visit functions.
- */
-D3SymbolTreeMap.prototype._visit = function(datum, visitor) {
- visitor.call(this, datum);
- if (datum.children) for (var i = 0; i < datum.children.length; i++) {
- this._visit(datum.children[i], visitor);
- }
-}
-
-D3SymbolTreeMap.prototype._crunchStatsHelper = function(stack, node) {
- // Only overwrite the node ID if it isn't already set.
- // This allows stats to be crunched multiple times on subsets of data
- // without breaking the data-to-ID bindings. New nodes get new IDs.
- if (node.id === undefined) node.id = stack.idCounter++;
- if (node.children === undefined) {
- // Leaf node (symbol); accumulate stats.
- for (var i = 0; i < stack.length; i++) {
- var ancestor = stack[i];
- if (!ancestor.symbol_stats) ancestor.symbol_stats = {};
- if (ancestor.symbol_stats[node.t] === undefined) {
- // New symbol type we haven't seen before, just record.
- ancestor.symbol_stats[node.t] = {'count': 1,
- 'size': node.value};
- } else {
- // Existing symbol type, increment.
- ancestor.symbol_stats[node.t].count++;
- ancestor.symbol_stats[node.t].size += node.value;
- }
- }
- } else for (var i = 0; i < node.children.length; i++) {
- stack.push(node);
- this._crunchStatsHelper(stack, node.children[i]);
- stack.pop();
- }
-}
-
-D3SymbolTreeMap.prototype._createTreeMapLayout = function() {
- var result = d3.layout.treemap()
- .padding([this.boxPadding.t, this.boxPadding.r,
- this.boxPadding.b, this.boxPadding.l])
- .size([this._mapWidth, this._mapHeight]);
- return result;
-}
-
-D3SymbolTreeMap.prototype.resize = function(width, height) {
- this._mapWidth = width;
- this._mapHeight = height;
- this._mapContainer.style('width', width).style('height', height);
- this._layout.size([this._mapWidth, this._mapHeight]);
- this._currentNodes = this._layout.nodes(this._currentRoot);
- this._doLayout();
-}
-
-D3SymbolTreeMap.prototype._zoomDatum = function(datum) {
- if (this._currentRoot === datum) return; // already here
- this._hideHighlight(datum);
- this._hideInfoBox(datum);
- this._currentRoot = datum;
- this._currentNodes = this._layout.nodes(this._currentRoot);
- this._currentMaxDepth = this._currentRoot.depth + this._maxLevelsToShow;
- console.log('zooming into datum ' + this._currentRoot.n);
- this._doLayout();
-}
-
-D3SymbolTreeMap.prototype.setMaxLevels = function(levelsToShow) {
- this._maxLevelsToShow = levelsToShow;
- this._currentNodes = this._layout.nodes(this._currentRoot);
- this._currentMaxDepth = this._currentRoot.depth + this._maxLevelsToShow;
- console.log('setting max levels to show: ' + this._maxLevelsToShow);
- this._doLayout();
-}
-
-/**
- * Clone the specified tree, returning an independent copy of the data.
- * Only the original attributes expected to exist prior to invoking
- * _crunchStatsHelper are retained, with the exception of the 'id' attribute
- * (which must be retained for proper transitions).
- * If the optional filter parameter is provided, it will be called with 'this'
- * set to this treemap instance and passed the 'datum' object as an argument.
- * When specified, the copy will retain only the data for which the filter
- * function returns true.
- */
-D3SymbolTreeMap.prototype._clone = function(datum, filter) {
- var trackingStats = false;
- if (this.__cloneState === undefined) {
- console.time('_clone');
- trackingStats = true;
- this.__cloneState = {'accepted': 0, 'rejected': 0,
- 'forced': 0, 'pruned': 0};
- }
-
- // Must go depth-first. All parents of children that are accepted by the
- // filter must be preserved!
- var copy = {'n': datum.n, 'k': datum.k};
- var childAccepted = false;
- if (datum.children !== undefined) {
- for (var i = 0; i < datum.children.length; i++) {
- var copiedChild = this._clone(datum.children[i], filter);
- if (copiedChild !== undefined) {
- childAccepted = true; // parent must also be accepted.
- if (copy.children === undefined) copy.children = [];
- copy.children.push(copiedChild);
- }
- }
- }
-
- // Ignore nodes that don't match the filter, when present.
- var accept = false;
- if (childAccepted) {
- // Parent of an accepted child must also be accepted.
- this.__cloneState.forced++;
- accept = true;
- } else if (filter !== undefined && filter.call(this, datum) !== true) {
- this.__cloneState.rejected++;
- } else if (datum.children === undefined) {
- // Accept leaf nodes that passed the filter
- this.__cloneState.accepted++;
- accept = true;
- } else {
- // Non-leaf node. If no children are accepted, prune it.
- this.__cloneState.pruned++;
- }
-
- if (accept) {
- if (datum.id !== undefined) copy.id = datum.id;
- if (datum.lastPathElement !== undefined) {
- copy.lastPathElement = datum.lastPathElement;
- }
- if (datum.t !== undefined) copy.t = datum.t;
- if (datum.value !== undefined && datum.children === undefined) {
- copy.value = datum.value;
- }
- } else {
- // Discard the copy we were going to return
- copy = undefined;
- }
-
- if (trackingStats === true) {
- // We are the fist call in the recursive chain.
- console.timeEnd('_clone');
- var totalAccepted = this.__cloneState.accepted +
- this.__cloneState.forced;
- console.log(
- totalAccepted + ' nodes retained (' +
- this.__cloneState.forced + ' forced by accepted children, ' +
- this.__cloneState.accepted + ' accepted on their own merits), ' +
- this.__cloneState.rejected + ' nodes (and their children) ' +
- 'filtered out,' +
- this.__cloneState.pruned + ' nodes pruned because because no ' +
- 'children remained.');
- delete this.__cloneState;
- }
- return copy;
-}
-
-D3SymbolTreeMap.prototype.filter = function(filter) {
- // Ensure we have a copy of the original root.
- if (this._backupTree === undefined) this._backupTree = this._treeData;
- this._mapContainer.selectAll('div').remove();
- this._setData(this._clone(this._backupTree, filter));
-}
-
-D3SymbolTreeMap.prototype._doLayout = function() {
- console.time('_doLayout');
- this._handleInodes();
- this._handleLeaves();
- this._firstTransition = false;
- console.timeEnd('_doLayout');
-}
-
-D3SymbolTreeMap.prototype._highlightElement = function(datum, selection) {
- this._showHighlight(datum, selection);
-}
-
-D3SymbolTreeMap.prototype._unhighlightElement = function(datum, selection) {
- this._hideHighlight(datum, selection);
-}
-
-D3SymbolTreeMap.prototype._handleInodes = function() {
- console.time('_handleInodes');
- var thisTreeMap = this;
- var inodes = this._currentNodes.filter(function(datum){
- return (datum.depth <= thisTreeMap._currentMaxDepth) &&
- datum.children !== undefined;
- });
- var cellsEnter = this._mapContainer.selectAll('div.inode')
- .data(inodes, function(datum) { return datum.id; })
- .enter()
- .append('div').attr('class', 'inode').attr('id', function(datum){
- return 'node-' + datum.id;});
-
-
- // Define enter/update/exit for inodes
- cellsEnter
- .append('div')
- .attr('class', 'rect inode_rect_entering')
- .style('z-index', function(datum) { return datum.id * 2; })
- .style('position', 'absolute')
- .style('left', function(datum) { return datum.x; })
- .style('top', function(datum){ return datum.y; })
- .style('width', function(datum){ return datum.dx; })
- .style('height', function(datum){ return datum.dy; })
- .style('opacity', '0')
- .style('border', '1px solid black')
- .style('background-image', function(datum) {
- return thisTreeMap._makeSymbolBucketBackgroundImage.call(
- thisTreeMap, datum);
- })
- .style('background-color', function(datum) {
- if (datum.t === undefined) return 'rgb(220,220,220)';
- return D3SymbolTreeMap.getColorForType(datum.t).toString();
- })
- .on('mouseover', function(datum){
- thisTreeMap._highlightElement.call(
- thisTreeMap, datum, d3.select(this));
- thisTreeMap._showInfoBox.call(thisTreeMap, datum);
- })
- .on('mouseout', function(datum){
- thisTreeMap._unhighlightElement.call(
- thisTreeMap, datum, d3.select(this));
- thisTreeMap._hideInfoBox.call(thisTreeMap, datum);
- })
- .on('mousemove', function(){
- thisTreeMap._moveInfoBox.call(thisTreeMap, event);
- })
- .on('dblclick', function(datum){
- if (datum !== thisTreeMap._currentRoot) {
- // Zoom into the selection
- thisTreeMap._zoomDatum(datum);
- } else if (datum.parent) {
- console.log('event.shiftKey=' + event.shiftKey);
- if (event.shiftKey === true) {
- // Back to root
- thisTreeMap._zoomDatum(thisTreeMap._treeData);
- } else {
- // Zoom out of the selection
- thisTreeMap._zoomDatum(datum.parent);
- }
- }
- });
- cellsEnter
- .append('div')
- .attr('class', 'label inode_label_entering')
- .style('z-index', function(datum) { return (datum.id * 2) + 1; })
- .style('position', 'absolute')
- .style('left', function(datum){ return datum.x; })
- .style('top', function(datum){ return datum.y; })
- .style('width', function(datum) { return datum.dx; })
- .style('height', function(datum) { return thisTreeMap.boxPadding.t; })
- .style('opacity', '0')
- .style('pointer-events', 'none')
- .style('-webkit-user-select', 'none')
- .style('overflow', 'hidden') // required for ellipsis
- .style('white-space', 'nowrap') // required for ellipsis
- .style('text-overflow', 'ellipsis')
- .style('text-align', 'center')
- .style('vertical-align', 'top')
- .style('visibility', function(datum) {
- return (datum.dx < 15 || datum.dy < 15) ? 'hidden' : 'visible';
- })
- .text(function(datum) {
- var sizeish = ' [' + D3SymbolTreeMap._byteify(datum.value) + ']'
- var text;
- if (datum.k === 'b') { // bucket
- if (datum === thisTreeMap._currentRoot) {
- text = thisTreeMap.pathFor(datum) + ': '
- + D3SymbolTreeMap._getSymbolDescription(datum.t)
- } else {
- text = D3SymbolTreeMap._getSymbolDescription(datum.t);
- }
- } else if (datum === thisTreeMap._currentRoot) {
- // The top-most level should always show the complete path
- text = thisTreeMap.pathFor(datum);
- } else {
- // Anything that isn't a bucket or a leaf (symbol) or the
- // current root should just show its name.
- text = datum.n;
- }
- return text + sizeish;
- }
- );
-
- // Complicated transition logic:
- // For nodes that are entering, we want to fade them in in-place AFTER
- // any adjusting nodes have resized and moved around. That way, new nodes
- // seamlessly appear in the right spot after their containers have resized
- // and moved around.
- // To do this we do some trickery:
- // 1. Define a '_entering' class on the entering elements
- // 2. Use this to select only the entering elements and apply the opacity
- // transition.
- // 3. Use the same transition to drop the '_entering' suffix, so that they
- // will correctly update in later zoom/resize/whatever operations.
- // 4. The update transition is achieved by selecting the elements without
- // the '_entering_' suffix and applying movement and resizing transition
- // effects.
- this._mapContainer.selectAll('div.inode_rect_entering').transition()
- .duration(thisTreeMap._enterDuration).delay(
- this._firstTransition ? 0 : thisTreeMap._exitDuration +
- thisTreeMap._updateDuration)
- .attr('class', 'rect inode_rect')
- .style('opacity', '1')
- this._mapContainer.selectAll('div.inode_label_entering').transition()
- .duration(thisTreeMap._enterDuration).delay(
- this._firstTransition ? 0 : thisTreeMap._exitDuration +
- thisTreeMap._updateDuration)
- .attr('class', 'label inode_label')
- .style('opacity', '1')
- this._mapContainer.selectAll('div.inode_rect').transition()
- .duration(thisTreeMap._updateDuration).delay(thisTreeMap._exitDuration)
- .style('opacity', '1')
- .style('background-image', function(datum) {
- return thisTreeMap._makeSymbolBucketBackgroundImage.call(
- thisTreeMap, datum);
- })
- .style('left', function(datum) { return datum.x; })
- .style('top', function(datum){ return datum.y; })
- .style('width', function(datum){ return datum.dx; })
- .style('height', function(datum){ return datum.dy; });
- this._mapContainer.selectAll('div.inode_label').transition()
- .duration(thisTreeMap._updateDuration).delay(thisTreeMap._exitDuration)
- .style('opacity', '1')
- .style('visibility', function(datum) {
- return (datum.dx < 15 || datum.dy < 15) ? 'hidden' : 'visible';
- })
- .style('left', function(datum){ return datum.x; })
- .style('top', function(datum){ return datum.y; })
- .style('width', function(datum) { return datum.dx; })
- .style('height', function(datum) { return thisTreeMap.boxPadding.t; })
- .text(function(datum) {
- var sizeish = ' [' + D3SymbolTreeMap._byteify(datum.value) + ']'
- var text;
- if (datum.k === 'b') {
- if (datum === thisTreeMap._currentRoot) {
- text = thisTreeMap.pathFor(datum) + ': ' +
- D3SymbolTreeMap._getSymbolDescription(datum.t)
- } else {
- text = D3SymbolTreeMap._getSymbolDescription(datum.t);
- }
- } else if (datum === thisTreeMap._currentRoot) {
- // The top-most level should always show the complete path
- text = thisTreeMap.pathFor(datum);
- } else {
- // Anything that isn't a bucket or a leaf (symbol) or the
- // current root should just show its name.
- text = datum.n;
- }
- return text + sizeish;
- });
- var exit = this._mapContainer.selectAll('div.inode')
- .data(inodes, function(datum) { return 'inode-' + datum.id; })
- .exit();
- exit.selectAll('div.inode_rect').transition().duration(
- thisTreeMap._exitDuration).style('opacity', 0);
- exit.selectAll('div.inode_label').transition().duration(
- thisTreeMap._exitDuration).style('opacity', 0);
- exit.transition().delay(thisTreeMap._exitDuration + 1).remove();
-
- console.log(inodes.length + ' inodes layed out.');
- console.timeEnd('_handleInodes');
-}
-
-D3SymbolTreeMap.prototype._handleLeaves = function() {
- console.time('_handleLeaves');
- var color_fn = d3.scale.category10();
- var thisTreeMap = this;
- var leaves = this._currentNodes.filter(function(datum){
- return (datum.depth <= thisTreeMap._currentMaxDepth) &&
- datum.children === undefined; });
- var cellsEnter = this._mapContainer.selectAll('div.leaf')
- .data(leaves, function(datum) { return datum.id; })
- .enter()
- .append('div').attr('class', 'leaf').attr('id', function(datum){
- return 'node-' + datum.id;
- });
-
- // Define enter/update/exit for leaves
- cellsEnter
- .append('div')
- .attr('class', 'rect leaf_rect_entering')
- .style('z-index', function(datum) { return datum.id * 2; })
- .style('position', 'absolute')
- .style('left', function(datum){ return datum.x; })
- .style('top', function(datum){ return datum.y; })
- .style('width', function(datum){ return datum.dx; })
- .style('height', function(datum){ return datum.dy; })
- .style('opacity', '0')
- .style('background-color', function(datum) {
- if (datum.t === undefined) return 'rgb(220,220,220)';
- return D3SymbolTreeMap.getColorForType(datum.t)
- .darker(0.3).toString();
- })
- .style('border', '1px solid black')
- .on('mouseover', function(datum){
- thisTreeMap._highlightElement.call(
- thisTreeMap, datum, d3.select(this));
- thisTreeMap._showInfoBox.call(thisTreeMap, datum);
- })
- .on('mouseout', function(datum){
- thisTreeMap._unhighlightElement.call(
- thisTreeMap, datum, d3.select(this));
- thisTreeMap._hideInfoBox.call(thisTreeMap, datum);
- })
- .on('mousemove', function(){ thisTreeMap._moveInfoBox.call(
- thisTreeMap, event);
- });
- cellsEnter
- .append('div')
- .attr('class', 'label leaf_label_entering')
- .style('z-index', function(datum) { return (datum.id * 2) + 1; })
- .style('position', 'absolute')
- .style('left', function(datum){ return datum.x; })
- .style('top', function(datum){ return datum.y; })
- .style('width', function(datum) { return datum.dx; })
- .style('height', function(datum) { return datum.dy; })
- .style('opacity', '0')
- .style('pointer-events', 'none')
- .style('-webkit-user-select', 'none')
- .style('overflow', 'hidden') // required for ellipsis
- .style('white-space', 'nowrap') // required for ellipsis
- .style('text-overflow', 'ellipsis')
- .style('text-align', 'center')
- .style('vertical-align', 'middle')
- .style('visibility', function(datum) {
- return (datum.dx < 15 || datum.dy < 15) ? 'hidden' : 'visible';
- })
- .text(function(datum) { return datum.n; });
-
- // Complicated transition logic: See note in _handleInodes()
- this._mapContainer.selectAll('div.leaf_rect_entering').transition()
- .duration(thisTreeMap._enterDuration).delay(
- this._firstTransition ? 0 : thisTreeMap._exitDuration +
- thisTreeMap._updateDuration)
- .attr('class', 'rect leaf_rect')
- .style('opacity', '1')
- this._mapContainer.selectAll('div.leaf_label_entering').transition()
- .duration(thisTreeMap._enterDuration).delay(
- this._firstTransition ? 0 : thisTreeMap._exitDuration +
- thisTreeMap._updateDuration)
- .attr('class', 'label leaf_label')
- .style('opacity', '1')
- this._mapContainer.selectAll('div.leaf_rect').transition()
- .duration(thisTreeMap._updateDuration).delay(thisTreeMap._exitDuration)
- .style('opacity', '1')
- .style('left', function(datum){ return datum.x; })
- .style('top', function(datum){ return datum.y; })
- .style('width', function(datum){ return datum.dx; })
- .style('height', function(datum){ return datum.dy; });
- this._mapContainer.selectAll('div.leaf_label').transition()
- .duration(thisTreeMap._updateDuration).delay(thisTreeMap._exitDuration)
- .style('opacity', '1')
- .style('visibility', function(datum) {
- return (datum.dx < 15 || datum.dy < 15) ? 'hidden' : 'visible';
- })
- .style('left', function(datum){ return datum.x; })
- .style('top', function(datum){ return datum.y; })
- .style('width', function(datum) { return datum.dx; })
- .style('height', function(datum) { return datum.dy; });
- var exit = this._mapContainer.selectAll('div.leaf')
- .data(leaves, function(datum) { return 'leaf-' + datum.id; })
- .exit();
- exit.selectAll('div.leaf_rect').transition()
- .duration(thisTreeMap._exitDuration)
- .style('opacity', 0);
- exit.selectAll('div.leaf_label').transition()
- .duration(thisTreeMap._exitDuration)
- .style('opacity', 0);
- exit.transition().delay(thisTreeMap._exitDuration + 1).remove();
-
- console.log(leaves.length + ' leaves layed out.');
- console.timeEnd('_handleLeaves');
-}
-
-D3SymbolTreeMap.prototype._makeSymbolBucketBackgroundImage = function(datum) {
- if (!(datum.t === undefined && datum.depth == this._currentMaxDepth)) {
- return 'none';
- }
- var text = '';
- var lastStop = 0;
- for (var x = 0; x < D3SymbolTreeMap._NM_SYMBOL_TYPES.length; x++) {
- symbol_type = D3SymbolTreeMap._NM_SYMBOL_TYPES.charAt(x);
- var stats = datum.symbol_stats[symbol_type];
- if (stats !== undefined) {
- if (text.length !== 0) {
- text += ', ';
- }
- var percent = 100 * (stats.size / datum.value);
- var nowStop = lastStop + percent;
- var tempcolor = D3SymbolTreeMap.getColorForType(symbol_type);
- var color = d3.rgb(tempcolor).toString();
- text += color + ' ' + lastStop + '%, ' + color + ' ' +
- nowStop + '%';
- lastStop = nowStop;
- }
- }
- return 'linear-gradient(' + (datum.dx > datum.dy ? 'to right' :
- 'to bottom') + ', ' + text + ')';
-}
-
-D3SymbolTreeMap.prototype.pathFor = function(datum) {
- if (datum.__path) return datum.__path;
- parts=[];
- node = datum;
- while (node) {
- if (node.k === 'p') { // path node
- if(node.n !== '/') parts.unshift(node.n);
- }
- node = node.parent;
- }
- datum.__path = '/' + parts.join('/');
- return datum.__path;
-}
-
-D3SymbolTreeMap.prototype._createHighlight = function(datum, selection) {
- var x = parseInt(selection.style('left'));
- var y = parseInt(selection.style('top'));
- var w = parseInt(selection.style('width'));
- var h = parseInt(selection.style('height'));
- datum.highlight = this._mapContainer.append('div')
- .attr('id', 'h-' + datum.id)
- .attr('class', 'highlight')
- .style('pointer-events', 'none')
- .style('-webkit-user-select', 'none')
- .style('z-index', '999999')
- .style('position', 'absolute')
- .style('top', y-2)
- .style('left', x-2)
- .style('width', w+4)
- .style('height', h+4)
- .style('margin', 0)
- .style('padding', 0)
- .style('border', '4px outset rgba(250,40,200,0.9)')
- .style('box-sizing', 'border-box')
- .style('opacity', 0.0);
-}
-
-D3SymbolTreeMap.prototype._showHighlight = function(datum, selection) {
- if (datum === this._currentRoot) return;
- if (datum.highlight === undefined) {
- this._createHighlight(datum, selection);
- }
- datum.highlight.transition().duration(200).style('opacity', 1.0);
-}
-
-D3SymbolTreeMap.prototype._hideHighlight = function(datum, selection) {
- if (datum.highlight === undefined) return;
- datum.highlight.transition().duration(750)
- .style('opacity', 0)
- .each('end', function(){
- if (datum.highlight) datum.highlight.remove();
- delete datum.highlight;
- });
-}
-
-D3SymbolTreeMap.prototype._createInfoBox = function() {
- return d3.select('body')
- .append('div')
- .attr('id', 'infobox')
- .style('z-index', '2147483647') // (2^31) - 1: Hopefully safe :)
- .style('position', 'absolute')
- .style('visibility', 'hidden')
- .style('background-color', 'rgba(255,255,255, 0.9)')
- .style('border', '1px solid black')
- .style('padding', '10px')
- .style('-webkit-user-select', 'none')
- .style('box-shadow', '3px 3px rgba(70,70,70,0.5)')
- .style('border-radius', '10px')
- .style('white-space', 'nowrap');
-}
-
-D3SymbolTreeMap.prototype._showInfoBox = function(datum) {
- this.infobox.text('');
- var numSymbols = 0;
- var sizeish = D3SymbolTreeMap._pretty(datum.value) + ' bytes (' +
- D3SymbolTreeMap._byteify(datum.value) + ')';
- if (datum.k === 'p' || datum.k === 'b') { // path or bucket
- if (datum.symbol_stats) { // can be empty if filters are applied
- for (var x = 0; x < D3SymbolTreeMap._NM_SYMBOL_TYPES.length; x++) {
- symbol_type = D3SymbolTreeMap._NM_SYMBOL_TYPES.charAt(x);
- var stats = datum.symbol_stats[symbol_type];
- if (stats !== undefined) numSymbols += stats.count;
- }
- }
- } else if (datum.k === 's') { // symbol
- numSymbols = 1;
- }
-
- if (datum.k === 'p' && !datum.lastPathElement) {
- this.infobox.append('div').text('Directory: ' + this.pathFor(datum))
- this.infobox.append('div').text('Size: ' + sizeish);
- } else {
- if (datum.k === 'p') { // path
- this.infobox.append('div').text('File: ' + this.pathFor(datum))
- this.infobox.append('div').text('Size: ' + sizeish);
- } else if (datum.k === 'b') { // bucket
- this.infobox.append('div').text('Symbol Bucket: ' +
- D3SymbolTreeMap._getSymbolDescription(datum.t));
- this.infobox.append('div').text('Count: ' + numSymbols);
- this.infobox.append('div').text('Size: ' + sizeish);
- this.infobox.append('div').text('Location: ' + this.pathFor(datum))
- } else if (datum.k === 's') { // symbol
- this.infobox.append('div').text('Symbol: ' + datum.n);
- this.infobox.append('div').text('Type: ' +
- D3SymbolTreeMap._getSymbolDescription(datum.t));
- this.infobox.append('div').text('Size: ' + sizeish);
- this.infobox.append('div').text('Location: ' + this.pathFor(datum))
- }
- }
- if (datum.k === 'p') {
- this.infobox.append('div')
- .text('Number of symbols: ' + D3SymbolTreeMap._pretty(numSymbols));
- if (datum.symbol_stats) { // can be empty if filters are applied
- var table = this.infobox.append('table')
- .attr('border', 1).append('tbody');
- var header = table.append('tr');
- header.append('th').text('Type');
- header.append('th').text('Count');
- header.append('th')
- .style('white-space', 'nowrap')
- .text('Total Size (Bytes)');
- for (var x = 0; x < D3SymbolTreeMap._NM_SYMBOL_TYPES.length; x++) {
- symbol_type = D3SymbolTreeMap._NM_SYMBOL_TYPES.charAt(x);
- var stats = datum.symbol_stats[symbol_type];
- if (stats !== undefined) {
- var tr = table.append('tr');
- tr.append('td')
- .style('white-space', 'nowrap')
- .text(D3SymbolTreeMap._getSymbolDescription(
- symbol_type));
- tr.append('td').text(D3SymbolTreeMap._pretty(stats.count));
- tr.append('td').text(D3SymbolTreeMap._pretty(stats.size));
- }
- }
- }
- }
- this.infobox.style('visibility', 'visible');
-}
-
-D3SymbolTreeMap.prototype._hideInfoBox = function(datum) {
- this.infobox.style('visibility', 'hidden');
-}
-
-D3SymbolTreeMap.prototype._moveInfoBox = function(event) {
- var element = document.getElementById('infobox');
- var w = element.offsetWidth;
- var h = element.offsetHeight;
- var offsetLeft = 10;
- var offsetTop = 10;
-
- var rightLimit = window.innerWidth;
- var rightEdge = event.pageX + offsetLeft + w;
- if (rightEdge > rightLimit) {
- // Too close to screen edge, reflect around the cursor
- offsetLeft = -1 * (w + offsetLeft);
- }
-
- var bottomLimit = window.innerHeight;
- var bottomEdge = event.pageY + offsetTop + h;
- if (bottomEdge > bottomLimit) {
- // Too close ot screen edge, reflect around the cursor
- offsetTop = -1 * (h + offsetTop);
- }
-
- this.infobox.style('top', (event.pageY + offsetTop) + 'px')
- .style('left', (event.pageX + offsetLeft) + 'px');
-}
-
-D3SymbolTreeMap.prototype.biggestSymbols = function(maxRecords) {
- var result = undefined;
- var smallest = undefined;
- var sortFunction = function(a,b) {
- var result = b.value - a.value;
- if (result !== 0) return result; // sort by size
- var pathA = treemap.pathFor(a); // sort by path
- var pathB = treemap.pathFor(b);
- if (pathA > pathB) return 1;
- if (pathB > pathA) return -1;
- return a.n - b.n; // sort by symbol name
- };
- this.visitFromDisplayedRoot(function(datum) {
- if (datum.children) return; // ignore non-leaves
- if (!result) { // first element
- result = [datum];
- smallest = datum.value;
- return;
- }
- if (result.length < maxRecords) { // filling the array
- result.push(datum);
- return;
- }
- if (datum.value > smallest) { // array is already full
- result.push(datum);
- result.sort(sortFunction);
- result.pop(); // get rid of smallest element
- smallest = result[maxRecords - 1].value; // new threshold for entry
- }
- });
- result.sort(sortFunction);
- return result;
-}
-
-D3SymbolTreeMap.prototype.biggestPaths = function(maxRecords) {
- var result = undefined;
- var smallest = undefined;
- var sortFunction = function(a,b) {
- var result = b.value - a.value;
- if (result !== 0) return result; // sort by size
- var pathA = treemap.pathFor(a); // sort by path
- var pathB = treemap.pathFor(b);
- if (pathA > pathB) return 1;
- if (pathB > pathA) return -1;
- console.log('warning, multiple entries for the same path: ' + pathA);
- return 0; // should be impossible
- };
- this.visitFromDisplayedRoot(function(datum) {
- if (!datum.lastPathElement) return; // ignore non-files
- if (!result) { // first element
- result = [datum];
- smallest = datum.value;
- return;
- }
- if (result.length < maxRecords) { // filling the array
- result.push(datum);
- return;
- }
- if (datum.value > smallest) { // array is already full
- result.push(datum);
- result.sort(sortFunction);
- result.pop(); // get rid of smallest element
- smallest = result[maxRecords - 1].value; // new threshold for entry
- }
- });
- result.sort(sortFunction);
- return result;
-}
diff --git a/runtime/third_party/binary_size/src/template/index.html b/runtime/third_party/binary_size/src/template/index.html
deleted file mode 100644
index 7e1a1fc..0000000
--- a/runtime/third_party/binary_size/src/template/index.html
+++ /dev/null
@@ -1,525 +0,0 @@
-<!--
- Copyright 2014 The Chromium Authors. All rights reserved.
- Use of this source code is governed by a BSD-style license that can be
- found in the LICENSE file.
--->
-<html>
-<head>
-<title>Binary Size Analysis</title>
-<script src="d3/d3.js" charset="utf-8"></script>
-<script src="D3SymbolTreeMap.js" charset="utf-8"></script>
-<script src="data.js" charset="utf-8"></script>
-<style>
-body {
- margin: 0px;
- padding: 5px;
-}
-.swatch {
- border: 1px solid rgb(100,100,100);
- -webkit-user-select: none;
- cursor: default;
-}
-</style>
-<script>
-var treemap;
-var filterChanging = false;
-var savedSettings = {};
-
-function init() {
- if (window.metadata !== undefined && window.metadata.subtitle) {
- document.getElementById('subtitle').innerHTML = ': ' + escape(metadata.subtitle);
- }
- initFilterOptions();
- treemap = new D3SymbolTreeMap(
- savedSettings.width,
- savedSettings.height,
- savedSettings.maxLevels);
- treemap.init();
-}
-
-function getIdealSizes() {
- var width = window.innerWidth - 20;
- var height = window.innerHeight - 70;
- return {'width': width, 'height': height};
-}
-
-function showReport(title, data, headers, dataFunction, styleFunction) {
- var div = d3.select('body').append('div')
- .style('margin', '0')
- .style('padding', '5px')
- .style('position', 'absolute')
- .style('top', '10%')
- .style('left', '10%')
- .style('background-color', 'rgba(255,255,255,0.9)')
- .style('width', '80%')
- .style('height', '80%')
- .style('z-index', '2147483647')
- .style('border', '3px ridge grey')
- .style('box-shadow', '10px 10px 5px rgba(80,80,80,0.7)')
- .style('text-align', 'center')
- .style('border-radius', '10px');
- var titlebar = div.append('div')
- .style('margin', '0')
- .style('padding', '5px')
- .style('position', 'absolute')
- .style('top', '0%')
- .style('left', '0%')
- .style('width', '100%')
- .style('height', '10%')
- .style('font-size', 'x-large');
- titlebar.text(title);
- var controls = div.append('div')
- .style('margin', '0')
- .style('padding', '5px')
- .style('position', 'absolute')
- .style('top', '90%')
- .style('left', '0%')
- .style('width', '100%')
- .style('height', '10%');
- controls.append('input').attr('type', 'button')
- .attr('value', 'Dismiss')
- .on('click', function(){div.remove();});
-
- var tableDiv = div.append('div')
- .style('overflow', 'auto')
- .style('position', 'absolute')
- .style('top', '10%')
- .style('left', '0%')
- .style('width', '100%')
- .style('height', '80%')
- .style('border-top', '1px solid rgb(230,230,230)')
- .style('border-bottom', '1px solid rgb(230,230,230)');
- var table = tableDiv.append('table')
- .attr('border', '1')
- .attr('cellspacing', '0')
- .attr('cellpadding', '2')
- .style('margin-left', 'auto')
- .style('margin-right', 'auto');
- var header = table.append('tr');
- for (var i = 0; i < headers.length; i++) {
- header.append('th').text(headers[i]);
- }
-
- for (var i = 0; i < data.length; i++) {
- var row = table.append('tr');
- for (j = 0; j < headers.length; j++) {
- var td = row.append('td');
- if (styleFunction) {
- styleFunction.call(this, td, j);
- }
- dataFunction.call(this, data[i], j, td);
- }
- }
-}
-
-function bigSymbolsReport() {
- var list = treemap.biggestSymbols(100);
- var headers = ['Rank', 'Size (Bytes)', 'Type', 'Location'];
- var styleFunction = function(selection, index) {
- if (index === 3) {
- selection.style('font-family', 'monospace');
- }
- };
- var recordIndex = 1;
- var dataFunction = function(record, index, cell) {
- if (index === 0) {
- cell.text(recordIndex++);
- } else if (index === 1) {
- cell.text(D3SymbolTreeMap._pretty(record.value));
- } else if (index === 2) {
- cell.text(record.t);
- } else {
- if (treemap.pathFor(record).indexOf('/out') == 0) {
- cell.append('span').text(treemap.pathFor(record));
- cell.append('br');
- cell.append('span').text('Symbol: ');
- cell.append('span').text(record.n);
- } else {
- var href = 'https://code.google.com/p/chromium/codesearch#chromium/src'
- + treemap.pathFor(record)
- + '&q='
- + record.n;
- cell.append('a')
- .attr('href', href)
- .attr('target', '_blank')
- .text(treemap.pathFor(record));
- cell.append('br');
- cell.append('span').text('Symbol: ');
- cell.append('span').text(record.n);
- }
- }
- };
- showReport('100 Largest Symbols', list, headers, dataFunction, styleFunction);
-}
-
-function bigPathsReport() {
- var list = treemap.biggestPaths(100);
- var headers = ['Rank', 'Size (Bytes)', 'Location'];
- var styleFunction = function(selection, index) {
- if (index === 2) {
- selection.style('font-family', 'monospace');
- }
- };
- var recordIndex = 1;
- var dataFunction = function(record, index, cell) {
- if (index === 0) {
- cell.text(recordIndex++);
- } else if (index === 1) {
- cell.text(D3SymbolTreeMap._pretty(record.value));
- } else if (index === 2) {
- if (treemap.pathFor(record).indexOf('/out') == 0) {
- cell.text(treemap.pathFor(record));
- } else {
- var href = 'https://code.google.com/p/chromium/codesearch#chromium/src' + treemap.pathFor(record);
- cell.append('a')
- .attr('href', href)
- .attr('target', '_blank')
- .text(treemap.pathFor(record));
- }
-
- }
- };
- showReport('100 Largest Paths', list, headers, dataFunction, styleFunction);
-}
-
-function symbolFilterTextChanged() {
- if (filterChanging) return true;
- filterChanging = true;
- var enabled = document.getElementById('symbol_types_filter').value;
- for (var x=0; x<=25; x++) {
- var checkBox = document.getElementById('check_' + x);
- checkBox.checked = (enabled.indexOf(checkBox.value) != -1);
- }
- filterChanging = false;
-}
-
-function updateFilterText() {
- if (filterChanging) return true;
- filterChanging = true;
- var text = '';
- for (var x=0; x<=25; x++) {
- var checkBox = document.getElementById('check_' + x);
- if (checkBox.checked) {
- text += checkBox.value;
- }
- }
- document.getElementById('symbol_types_filter').value=text;
- filterChanging = false;
-}
-
-function initFilterOptions() {
- updateFilterText();
- for (var x=0; x<=25; x++) {
- var checkBox = document.getElementById('check_' + x);
- checkBox.onchange=updateFilterText;
- var swatch = document.getElementById('swatch_' + x);
- swatch.style.backgroundColor = D3SymbolTreeMap.getColorForType(checkBox.value).toString();
- }
- var gteCheckbox = document.getElementById('check_gte');
- gteCheckbox.onchange = function() {
- document.getElementById('symbol_filter_gte').disabled = !gteCheckbox.checked;
- }
- var regexCheckbox = document.getElementById('check_regex');
- regexCheckbox.onchange = function() {
- document.getElementById('symbol_filter_regex').disabled = !regexCheckbox.checked;
- }
- var excludeRegexCheckbox = document.getElementById('check_exclude_regex');
- excludeRegexCheckbox.onchange = function() {
- document.getElementById('symbol_filter_exclude_regex').disabled = !excludeRegexCheckbox.checked;
- }
- var idealSizes = getIdealSizes();
- document.getElementById('width').value = idealSizes.width;
- document.getElementById('height').value = idealSizes.height;
- saveFilterSettings();
-}
-
-function filterSetAll(enabled) {
- for (var x=0; x<=25; x++) {
- var checkBox = document.getElementById('check_' + x);
- checkBox.checked = enabled;
- }
- updateFilterText();
-}
-
-function showOptions() {
- loadFilterSettings();
- var container = document.getElementById('options_container');
- var w = container.offsetWidth;
- var h = container.offsetHeight;
- container.style.margin = '-' + (h/2) + 'px 0 0 -' + (w/2) + 'px';
- container.style.visibility = 'visible';
-}
-
-function hideOptions() {
- var container = document.getElementById('options_container');
- container.style.visibility = 'hidden';
-}
-
-function applySettings() {
- hideOptions();
- var oldWidth = savedSettings.width;
- var oldHeight = savedSettings.height;
- var oldSymbols = savedSettings.symbolTypes;
- var oldRegex = savedSettings.regex;
- var oldExcludeRegex = savedSettings.excludeRegex;
- var oldGte = savedSettings.gte;
- var oldMaxLevels = savedSettings.maxLevels;
- saveFilterSettings();
- var resizeNeeded = oldWidth !== savedSettings.width || oldHeight !== savedSettings.height;
- var regexChanged = oldRegex !== savedSettings.regex;
- var excludeRegexChanged = oldExcludeRegex !== savedSettings.excludeRegex;
- var symbolsChanged = oldSymbols !== savedSettings.symbolTypes;
- var gteChanged = oldGte !== savedSettings.gte;
- var filterChanged = regexChanged || excludeRegexChanged || symbolsChanged || gteChanged;
- var maxLevelsChanged = oldMaxLevels !== savedSettings.maxLevels;
-
- if (filterChanged) {
- // Type filters
- typeFilter = function(datum) {
- if (datum.depth === 0) return true; // root node
- if (datum.t === undefined) return true;
- return savedSettings.symbolTypes !== undefined &&
- savedSettings.symbolTypes.indexOf(datum.t) !== -1;
- }
-
- // Regex filter
- var regexFilter = undefined;
- if (savedSettings.regex !== undefined && savedSettings.regex.length > 0) {
- console.log('filter: regex is "' + savedSettings.regex + '"');
- var regex = new RegExp(savedSettings.regex);
- regexFilter = function(datum) {
- if (datum.depth === 0) return true; // root node
- var fullName = this.pathFor(datum);
- if (datum.children === undefined) { // it is a leaf node (symbol)
- fullName += ':' + datum.n;
- }
- return regex.test(fullName);
- }
- }
-
- // Exclude regex filter
- var excludeRegexFilter = undefined;
- if (savedSettings.excludeRegex !== undefined && savedSettings.excludeRegex.length > 0) {
- console.log('filter: exclude-regex is "' + savedSettings.excludeRegex + '"');
- var excludeRegex = new RegExp(savedSettings.excludeRegex);
- excludeRegexFilter = function(datum) {
- if (datum.depth === 0) return true; // root node
- var fullName = this.pathFor(datum);
- if (datum.children === undefined) { // it is a leaf node (symbol)
- fullName += ':' + datum.n;
- }
- return !excludeRegex.test(fullName);
- }
- }
-
- // Size filter
- var sizeFilter = undefined;
- if (savedSettings.gte !== undefined) {
- console.log('filter: minimum size is ' + savedSettings.gte + ' bytes');
- sizeFilter = function(datum) {
- if (datum.children !== undefined) return true; // non-leaf
- if (datum.value === undefined) console.log('whoops');
- return datum.value >= savedSettings.gte;
- }
- }
-
- // Make a filter to apply to the tree
- var filter = function(datum) {
- if (typeFilter && !typeFilter.call(this, datum)) return false;
- if (regexFilter && !regexFilter.call(this, datum)) return false;
- if (excludeRegexFilter && !excludeRegexFilter.call(this, datum)) return false;
- if (sizeFilter && !sizeFilter.call(this, datum)) return false;
- return true;
- };
- treemap.filter(filter);
- }
-
- // Adjust levels if needed.
- if (maxLevelsChanged) {
- treemap.setMaxLevels(savedSettings.maxLevels);
- }
-
- // Resize map if necessary.
- if (resizeNeeded) {
- console.log('desired treemap dimensions have changed, requesting resize');
- treemap.resize(savedSettings.width, savedSettings.height);
- }
-}
-
-function cancelSettings() {
- hideOptions();
- loadFilterSettings();
-}
-
-function saveFilterSettings() {
- savedSettings.symbolTypes = document.getElementById('symbol_types_filter').value;
- if (document.getElementById('check_regex').checked) {
- savedSettings.regex = document.getElementById('symbol_filter_regex').value;
- } else {
- savedSettings.regex = undefined;
- }
- if (document.getElementById('check_exclude_regex').checked) {
- savedSettings.excludeRegex = document.getElementById('symbol_filter_exclude_regex').value;
- } else {
- savedSettings.excludeRegex = undefined;
- }
- if (document.getElementById('check_gte').checked) {
- savedSettings.gte = parseInt(document.getElementById('symbol_filter_gte').value);
- } else {
- savedSettings.gte = undefined;
- }
- savedSettings.width = parseInt(document.getElementById('width').value);
- savedSettings.height = parseInt(document.getElementById('height').value);
- savedSettings.maxLevels = parseInt(document.getElementById('max_levels').value);
-}
-
-function loadFilterSettings() {
- document.getElementById('symbol_types_filter').value = savedSettings.symbolTypes;
- symbolFilterTextChanged();
- if (savedSettings.regex !== undefined) {
- document.getElementById('check_regex').checked = true;
- document.getElementById('symbol_filter_regex').value = savedSettings.regex;
- } else {
- document.getElementById('check_regex').checked = false;
- }
- if (savedSettings.excludeRegex !== undefined) {
- document.getElementById('check_exclude_regex').checked = true;
- document.getElementById('symbol_filter_exclude_regex').value = savedSettings.excludeRegex;
- } else {
- document.getElementById('check_exclude_regex').checked = false;
- }
- if (savedSettings.gte !== undefined) {
- document.getElementById('check_gte').checked = true;
- document.getElementById('symbol_filter_gte').value = savedSettings.gte;
- } else {
- document.getElementById('check_gte').checked = false;
- }
- document.getElementById('width').value = savedSettings.width;
- document.getElementById('height').value = savedSettings.height;
- document.getElementById('max_levels').value = savedSettings.maxLevels;
-}
-
-function escape(str) {
- return str.replace(/&/g, '&')
- .replace(/"/g, '"')
- .replace(/</g, '<')
- .replace(/>/g, '>');
-}
-</script>
-</head>
-<body onload='init()'>
-<div style='position: absolute; top: 5px; left: 5px;'>
- <input type='button' onclick='showOptions()' value='Options & Legend...'>
- <span style='-webkit-user-select: none; cursor: help;' title='Click to view the symbol legend or to configure filters and options for the treemap'>[?]</span>
-</div>
-<div style='position: absolute; right: 5px; top: 5px; white-space: nowrap;'>
- Reports:
- <input type='button' onclick='bigSymbolsReport()' value='Large Symbols' title='Click to view a report of the largest 100 symbols that are with the bounds of the treemap that is currently displayed.'>
- <input type='button' onclick='bigPathsReport()' value='Large Files' title='Click to view a report of the largest 100 source files that are with the bounds of the treemap that is currently displayed.'>
-</div>
-<div style='text-align: center; margin-bottom: 5px;'>
- <span style='font-size: x-large; font-weight: bold; font-variant: small-caps'>Binary Size Analysis<span id='subtitle'></span></span>
- <br><span style='font-size: small; font-style: italic;'>Double-click a box to zoom in, double-click outermost title to zoom out.</span>
-</div>
-<table id='options_container' style='visibility: hidden; border: 3px ridge grey; padding: 0px; top: 50%; left: 50%; position: fixed; z-index: 2147483646; overflow: auto; background-color: rgba(255,255,255,0.9); border-radius: 10px; box-shadow: 10px 10px 5px rgba(80,80,80,0.7);'><tr><td style='vertical-align: top'>
- <table cellspacing=0 cellborder=0 style='width:100%'>
- <tr><th colspan=3 style='padding-bottom: .25em; text-decoration: underline;'>Symbol Types To Show</th></tr>
- <tr>
- <td style='width: 33%; white-space: nowrap; vertical-align: top;'>
- <span class='swatch' id='swatch_0'> </span><input checked type='checkbox' id='check_0' value='A'>Global absolute (A)
- <br><span class='swatch' id='swatch_1'> </span><input checked type='checkbox' id='check_1' value='B'>Global uninitialized data (B)
- <br><span class='swatch' id='swatch_2'> </span><input checked type='checkbox' id='check_2' value='b'>Local uninitialized data (b)
- <br><span class='swatch' id='swatch_3'> </span><input checked type='checkbox' id='check_3' value='C'>Global uninitialized common (C)
- <br><span class='swatch' id='swatch_4'> </span><input checked type='checkbox' id='check_4' value='D'>Global initialized data (D)
- <br><span class='swatch' id='swatch_5'> </span><input checked type='checkbox' id='check_5' value='d'>Local initialized data (d)
- <br><span class='swatch' id='swatch_6'> </span><input checked type='checkbox' id='check_6' value='G'>Global small initialized data (G)
- <br><span class='swatch' id='swatch_7'> </span><input checked type='checkbox' id='check_7' value='g'>Local small initialized data (g)
- <br><span class='swatch' id='swatch_8'> </span><input checked type='checkbox' id='check_8' value='i'>Indirect function (i)
- </td>
- <td style='width: 33%; white-space: nowrap; vertical-align: top;'>
- <span class='swatch' id='swatch_9'> </span><input checked type='checkbox' id='check_9' value='N'>Debugging (N)
- <br><span class='swatch' id='swatch_10'> </span><input checked type='checkbox' id='check_10' value='p'>Stack unwind (p)
- <br><span class='swatch' id='swatch_11'> </span><input checked type='checkbox' id='check_11' value='R'>Global read-only data (R)
- <br><span class='swatch' id='swatch_12'> </span><input checked type='checkbox' id='check_12' value='r'>Local read-only data (r)
- <br><span class='swatch' id='swatch_13'> </span><input checked type='checkbox' id='check_13' value='S'>Global small uninitialized data (S)
- <br><span class='swatch' id='swatch_14'> </span><input checked type='checkbox' id='check_14' value='s'>Local small uninitialized data (s)
- <br><span class='swatch' id='swatch_15'> </span><input checked type='checkbox' id='check_15' value='T'>Global code (T)
- <br><span class='swatch' id='swatch_16'> </span><input checked type='checkbox' id='check_16' value='t'>Local code (t)
- <br><span class='swatch' id='swatch_17'> </span><input checked type='checkbox' id='check_17' value='U'>Undefined (U)
- </td>
- <td style='width: 33%; white-space: nowrap; vertical-align: top;'>
- <span class='swatch' id='swatch_18'> </span><input checked type='checkbox' id='check_18' value='u'>Unique (u)
- <br><span class='swatch' id='swatch_19'> </span><input checked type='checkbox' id='check_19' value='V'>Global weak object (V)
- <br><span class='swatch' id='swatch_20'> </span><input checked type='checkbox' id='check_20' value='v'>Local weak object (v)
- <br><span class='swatch' id='swatch_21'> </span><input checked type='checkbox' id='check_21' value='W'>Global weak symbol (W)
- <br><span class='swatch' id='swatch_22'> </span><input checked type='checkbox' id='check_22' value='w'>Local weak symbol (w)
- <br><span class='swatch' id='swatch_23'> </span><input checked type='checkbox' id='check_23' value='@'>Vtable entry (@)
- <br><span class='swatch' id='swatch_24'> </span><input checked type='checkbox' id='check_24' value='-'>STABS debugging (-)
- <br><span class='swatch' id='swatch_25'> </span><input checked type='checkbox' id='check_25' value='?'>Unrecognized (?)
- </td>
- </tr>
- <tr><td colspan=3 style='text-align: center; white-space: nowrap; padding-top: 1em;'>
- Select <input type='button' onclick='filterSetAll(true)' value='All'>,
- <input type='button' onclick='filterSetAll(false)' value='None'>,
- or type a string: <input id='symbol_types_filter' size=30 value='' onkeyup='symbolFilterTextChanged()' onblur='updateFilterText()'>
- <span style='-webkit-user-select: none; cursor: help;' title='Enter codes from the list above for the symbols you want to see. The checkboxes will update automatically to match the string that you enter.'>[?]</span>
- </td></tr>
- </table>
-</td></tr><tr><td style='vertical-align: top; padding-top: 10px; border-top: 1px solid grey;'>
- <table cellspacing=0 cellborder=0 style='width: 100%'>
- <tr><th colspan=2 style='padding-bottom: .25em; text-decoration: underline;'>Advanced Options</th></tr>
- <tr>
- <td style='white-space: nowrap; vertical-align: top;'>
- <input type='checkbox' id='check_regex'>
- Only include symbols matching this regex:
- </td>
- <td style='text-align: right; vertical-align: top;'>
- <input disabled id='symbol_filter_regex' size=30 value='' style='text-align: right;'>
- <span style='-webkit-user-select: none; cursor: help;' title='Enter a javascript regex. Only symbols that match this regex will be shown. This filter applies before any exclusion regex specified below. The format of each symbol is [path]:[symbol_name]'>[?]</span>
- </td>
- </tr>
- <tr>
- <td style='white-space: nowrap; vertical-align: top;'>
- <input type='checkbox' id='check_exclude_regex'>
- Exclude all symbols matching this regex:
- </td>
- <td style='text-align: right; vertical-align: top;'>
- <input disabled id='symbol_filter_exclude_regex' size=30 value='' style='text-align: right;'>
- <span style='-webkit-user-select: none; cursor: help;' title='Enter a javascript regex. Symbols that match this tegex will not be shown. This filter applies after any inclusion filter specified above. The format of each symbol is [path]:[symbol_name]'>[?]</span>
- </td>
- </tr>
- <tr>
- <td style='white-space: nowrap; vertical-align: top;'>
- <input type='checkbox' id='check_gte'>
- Only include symbols that are at least <span style='font-style: italic;'>n</span> bytes:
- </td>
- <td style='text-align: right; vertical-align: top;'>
- <input disabled id='symbol_filter_gte' size=8 value='' style='text-align: right;'>
- <span style='-webkit-user-select: none; cursor: help;' title='Symbols whose size is less than this value will be hidden.'>[?]</span>
- </td>
- </tr>
- <tr>
- <td style='white-space: nowrap vertical-align: top;;'>
- Show at most <span style='font-style: italic;'>n</span> levels of detail at a time:
- </td>
- <td style='text-align: right; vertical-align: top;'>
- <input id='max_levels' size=4 value='2' style='text-align: right;'><span style='-webkit-user-select: none; cursor: help;' title='Increasing this value shows more detail without the need to zoom, but uses more computing power.'>[?]</span>
- </td>
- </tr>
- <tr>
- <td style='white-space: nowrap vertical-align: top;;'>
- Set the size of the treemap to <span style='font-style: italic;'>W x H</span> pixels:
- </td>
- <td style='text-align: right; vertical-align: top;'>
- <input id='width' size=4 value='' style='text-align: right;'>
- x <input id='height' size=4 value='' style='text-align: right;'>
- </td>
- </tr>
- </table>
-</td></tr>
-<tr><td style='padding-top: 10px; text-align: right; border-top: 1px solid grey'>
- <input type='button' value='Apply' onclick='applySettings()'>
- <input type='button' value='Cancel' onclick='cancelSettings()'>
-</td></tr></table>
-</body>
-</html>
diff --git a/runtime/third_party/binary_size/src/template/test-data-generator.html b/runtime/third_party/binary_size/src/template/test-data-generator.html
deleted file mode 100644
index 9c6790a..0000000
--- a/runtime/third_party/binary_size/src/template/test-data-generator.html
+++ /dev/null
@@ -1,157 +0,0 @@
-<!DOCTYPE html>
-<!--
- Copyright 2014 The Chromium Authors. All rights reserved.
- Use of this source code is governed by a BSD-style license that can be
- found in the LICENSE file.
--->
-<html>
-<head>
-<script>
-function rnd(max) {
- return Math.round(Math.random()*max);
-}
-
-function gen() {
- var dirs1=['usr1', 'etc1', 'var1'];
- var dirs2=['aaa2', 'bbb2', 'ccc2', 'ddd2', 'eee2', 'fff2', 'ggg2', 'hhh2',
- 'frobozz2', 'kazaam2', 'shazam2'];
- var dirs3=['iii3', 'jjj3', 'kkk3', 'lll3', 'mmm3', 'nnn3', 'ooo3', 'ppp3',
- 'wonderllama3', 'excelsior3', 'src3'];
- var filenames=['awesome.cc', 'rad.h', 'tubular.cxx', 'cool.cc', 'groovy.h',
- 'excellent.c', 'gnarly.h', 'green.C', 'articulate.cc'];
- //All possible types (we only see a subset in practice): 'ABbCDdGgiNpRrSsTtUuVvWw-?';
- var nm_symbol_types = 'trd';
- var minSize = 4;
- var maxSize = 10000;
- var numGen = 300000;
- var text = 'var nm_data=[\n';
- var vtablePercent = 5;
- for (var x=0; x<numGen; x++) {
- var path = '/' +
- dirs1[rnd(dirs1.length - 1)] + '/' +
- dirs2[rnd(dirs2.length - 1)] + '/' +
- dirs3[rnd(dirs3.length - 1)] + '/' +
- filenames[rnd(filenames.length - 1)];
- var isVtable = Math.floor((Math.random()*100)+1) <= vtablePercent;
- var size = rnd(maxSize);
- var symbol_name;
- var type;
- if (!isVtable) {
- symbol_name = 'sym' + x.toString(16);
- type = nm_symbol_types.charAt(rnd(nm_symbol_types.length - 1));
- } else {
- symbol_name = 'vtable for ' + x.toString(16);
- type = '@'
- }
- text = text + "{'n': '" + symbol_name +
- "', 't': '" + type +
- "', 's': " + size +
- ", 'p': '" + path + "'},\n";
- }
- text += '];';
-
- eval(text);
- var treeified = to_d3_tree(nm_data);
- generateDownloadLink('tree_data=' + JSON.stringify(treeified));
-}
-
-function generateDownloadLink(content) {
- var blob = new Blob([content], {type: 'text/plain'});
- var link = document.createElement('a');
- link.download = 'generated-content.txt';
- link.href = window.URL.createObjectURL(blob);
- link.textContent = 'Download ready, click here.';
- link.dataset.downloadurl = ['text/plain', link.download, link.href].join(':');
- link.onclick = function(e) {
- if ('disabled' in this.dataset) { return false; }
- link.dataset.disabled = true;
- setTimeout(function() { window.URL.revokeObjectURL(link.href); }, 1500);
- };
- document.getElementById('linkcontainer').innerHTML = '';
- document.getElementById('linkcontainer').appendChild(link);
-}
-
-/**
- * This function takes in an array of nm records and converts them into a
- * hierarchical data structure suitable for use in a d3-base treemap layout.
- * Leaves are individual symbols. The parents of the leaves are logical
- * groupings by common symbol-type (for BSS, read-only data, code, etc).
- * Above this, each node represents part of a filesystem path relative
- * to the parent node. The root node has the name '/', and represents
- * a root (though not necessarily THE root) of a file system traversal.
- * The root node also has a special property, 'maxDepth', to which is bound
- * the deepest level of nesting that was found during conversion: for the
- * record at path /a/b/c/d.foo, the maxDepth will be 6; the file 'd.foo'
- * is at depth 4, the type-bucket is depth 5 and the symbols are depth 6.
- */
-function to_d3_tree(records) {
- var result = {'n': '/', 'children': [], 'k': 'p'};
- var maxDepth = 0;
- //{'n': 'symbol1', 't': 'b', 's': 1000, 'p': '/usr/local/foo/foo.cc'},
- for (index in records) {
- var record = records[index];
- var parts = record.p.split("/");
- var node = result;
- var depth = 0;
- // Walk the tree and find the file that is named by the "location"
- // field of the record. We create any intermediate nodes required.
- // This is directly analogous to "mkdir -p".
- while(parts.length > 0) {
- var part = parts.shift();
- if (part.length == 0) continue;
- depth++;
- node = _mk_child(node, part, record.s);
- node.k = 'p'; // p for path
- }
- node.lastPathElement = true;
-
- // 'node' is now the file node. Find the symbol-type bucket.
- node = _mk_child(node, record.t, record.s);
- node.t = record.t;
- node.k = 'b'; // b for bucket
- depth++;
- // 'node' is now the symbol-type bucket. Make the child entry.
- node = _mk_child(node, record.n, record.s);
- delete node.children;
- node.value = record.s;
- node.t = record.t;
- node.k = 's'; // s for symbol
- depth++;
-
- maxDepth = Math.max(maxDepth, depth);
- }
- result.maxDepth = maxDepth;
- return result;
-}
-
-/**
- * Given a node and a name, return the child within node.children whose
- * name matches the specified name. If necessary, a new child node is
- * created and appended to node.children.
- * If this method creates a new node, the 'name' attribute is set to the
- * specified name and the 'children' attribute is an empty array, and
- * total_size is the specified size. Otherwise, the existing node is
- * returned and its total_size value is incremented by the specified size.
- */
-function _mk_child(node, name, size) {
- var child = undefined;
- for (child_index in node.children) {
- if (node.children[child_index].n == name) {
- child = node.children[child_index];
- }
- }
- if (child === undefined) {
- child = {'n': name, 'children': []};
- node.children.push(child);
- }
- return child;
-}
-</script>
-</head>
-<body style='white-space: pre; font-family: monospace;'>
-This script generates sample data for use in D3SymbolTreeMap, and can be used
-for testing.
-<input type=button onclick='gen();' value='Generate data'></input>
-<div id='linkcontainer'></div>
-</body>
-</html>
diff --git a/runtime/tools/binary_size b/runtime/tools/binary_size
new file mode 100755
index 0000000..5621bf5
--- /dev/null
+++ b/runtime/tools/binary_size
@@ -0,0 +1,402 @@
+#!/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";
+
+class Symbol {
+ String? name;
+ String? type;
+ int? shallowSize;
+ int? retainedSize;
+ List<Symbol> children = <Symbol>[];
+
+ Symbol compressTrivialPaths() {
+ for (var i = 0; i < children.length; i++) {
+ children[i] = children[i].compressTrivialPaths();
+ }
+ if ((type == "path") && (children.length == 1)) {
+ return children[0];
+ }
+ return this;
+ }
+
+ int computeRetainedSize() {
+ var s = shallowSize!;
+ for (var child in children) {
+ s += child.computeRetainedSize();
+ }
+ retainedSize = s;
+ return s;
+ }
+
+ writeJson(StringBuffer out) {
+ out.write("{");
+ out.write('"name": "$name",');
+ out.write('"shallowSize": $shallowSize,');
+ out.write('"retainedSize": $retainedSize,');
+ out.write('"type": "$type",');
+ out.write('"children": [');
+ bool first = true;
+ for (var child in children) {
+ if (first) {
+ first = false;
+ } else {
+ out.write(",");
+ }
+ child.writeJson(out);
+ }
+ out.write("]}");
+ }
+}
+
+const filteredPathComponents = <String>[
+ "",
+ ".",
+ "..",
+ "out",
+ "src",
+ "source",
+ "third_party",
+ "DebugX64",
+ "ReleaseX64",
+ "ProductX64",
+];
+
+String prettyPath(String path) {
+ return path
+ .split("/")
+ .where((component) => !filteredPathComponents.contains(component))
+ .join("/");
+}
+
+main(List<String> args) {
+ if (args.isEmpty) {
+ print("Usage: binary_size <binaries>");
+ exit(1);
+ }
+
+ for (var arg in args) {
+ analyze(arg);
+ }
+}
+
+analyze(String binaryPath) {
+ var nmExec = "nm";
+ var nmArgs = ["--demangle", "--line-numbers", "--print-size", binaryPath];
+ var nmResult = Process.runSync(nmExec, nmArgs);
+ if (nmResult.exitCode != 0) {
+ print("+ ${nmExec} ${nmArgs.join(' ')}");
+ print(nmResult.exitCode);
+ print(nmResult.stdout);
+ print(nmResult.stderr);
+ exit(1);
+ }
+
+ var root = new Symbol();
+ root.name = binaryPath;
+ root.type = "path";
+ root.shallowSize = 0;
+ var paths = new Map<String, Symbol>();
+ paths[""] = root;
+ addToPath(Symbol s, String path) {
+ Symbol? p = paths[path];
+ if (p == null) {
+ p = new Symbol();
+ p.name = path;
+ p.type = "path";
+ p.shallowSize = 0;
+ paths[path] = p;
+
+ var i = path.lastIndexOf("/");
+ if (i != -1) {
+ p.name = path.substring(i + 1);
+ addToPath(p, path.substring(0, i));
+ } else {
+ root.children.add(p);
+ }
+ }
+ p.children.add(s);
+ }
+
+ var lines = nmResult.stdout.split("\n");
+ var regex = new RegExp("([0-9a-f]+) ([0-9a-f]+) ([a-zA-z]) (.*)");
+ for (var line in lines) {
+ var match = regex.firstMatch(line);
+ if (match == null) {
+ continue;
+ }
+
+ var address = int.parse(match[1]!, radix: 16);
+ var size = int.parse(match[2]!, radix: 16);
+ var type = match[3];
+ if (type == "b" || type == "B") {
+ // Uninitialized data does not contribute to file size.
+ continue;
+ }
+
+ var nameAndPath = match[4]!.split("\t");
+ var name = nameAndPath[0].trim();
+ var path = nameAndPath.length == 1
+ ? ""
+ : prettyPath(nameAndPath[1].trim().split(":")[0]);
+
+ var s = new Symbol();
+ s.name = name;
+ s.type = type;
+ s.shallowSize = size;
+ addToPath(s, path);
+ }
+
+ root.compressTrivialPaths();
+ root.computeRetainedSize();
+
+ var json = new StringBuffer();
+ root.writeJson(json);
+
+ var html = viewer.replaceAll("__DATA__", json.toString());
+ new File("${binaryPath}.html").writeAsStringSync(html);
+
+ // This written as a URL instead of path because some terminals will
+ // automatically recognize it and make it a link.
+ var url = Directory.current.uri.resolve("${binaryPath}.html");
+ print("Wrote $url");
+}
+
+var viewer = """
+<html>
+<head>
+<style>
+.treemapTile {
+ position: absolute;
+ box-sizing: border-box;
+ border: solid 1px;
+ font-size: 10;
+ text-align: center;
+ overflow: hidden;
+ white-space: nowrap;
+ cursor: default;
+}
+</style>
+</head>
+<body>
+<script>
+var root = __DATA__;
+
+function hash(string) {
+ // Jenkin's one_at_a_time.
+ let h = string.length;
+ for (let i = 0; i < string.length; i++) {
+ h += string.charCodeAt(i);
+ h += h << 10;
+ h ^= h >> 6;
+ }
+ h += h << 3;
+ h ^= h >> 11;
+ h += h << 15;
+ return h;
+}
+
+function color(string) {
+ let hue = hash(string) % 360;
+ return "hsl(" + hue + ",60%,60%)";
+}
+
+function prettySize(size) {
+ if (size < 1024) return size + "B";
+ size /= 1024;
+ if (size < 1024) return size.toFixed(1) + "KiB";
+ size /= 1024;
+ if (size < 1024) return size.toFixed(1) + "MiB";
+ size /= 1024;
+ return size.toFixed(1) + "GiB";
+}
+
+function createTreemapTile(v, width, height, depth) {
+ let div = document.createElement("div");
+ div.className = "treemapTile";
+ div.style["background-color"] = color(v.type);
+ div.ondblclick = function(event) {
+ event.stopPropagation();
+ if (depth == 0) {
+ let parent = v.parent;
+ if (parent === undefined) {
+ // Already at root.
+ } else {
+ showDominatorTree(parent); // Zoom out.
+ }
+ } else {
+ showDominatorTree(v); // Zoom in.
+ }
+ };
+
+ let left = 0;
+ let top = 0;
+
+ const kPadding = 5;
+ const kBorder = 1;
+ left += kPadding - kBorder;
+ top += kPadding - kBorder;
+ width -= 2 * kPadding;
+ height -= 2 * kPadding;
+
+ div.title =
+ v.name +
+ " \\ntype: " + v.type +
+ " \\nretained: " + v.retainedSize +
+ " \\nshallow: " + v.shallowSize;
+
+ if (width < 10 || height < 10) {
+ // Too small: don't render label or children.
+ return div;
+ }
+
+ let label = v.name + " [" + prettySize(v.retainedSize) + "]";
+ div.appendChild(document.createTextNode(label));
+ const kLabelHeight = 9;
+ top += kLabelHeight;
+ height -= kLabelHeight;
+
+ if (depth > 2) {
+ // Too deep: don't render children.
+ return div;
+ }
+ if (width < 4 || height < 4) {
+ // Too small: don't render children.
+ return div;
+ }
+
+ let children = new Array();
+ v.children.forEach(function(c) {
+ // Size 0 children seem to confuse the layout algorithm (accumulating
+ // rounding errors?).
+ if (c.retainedSize > 0) {
+ children.push(c);
+ }
+ });
+ children.sort(function (a, b) {
+ return b.retainedSize - a.retainedSize;
+ });
+
+ const scale = width * height / v.retainedSize;
+
+ // Bruls M., Huizing K., van Wijk J.J. (2000) Squarified Treemaps. In: de
+ // Leeuw W.C., van Liere R. (eds) Data Visualization 2000. Eurographics.
+ // Springer, Vienna.
+ for (let rowStart = 0; // Index of first child in the next row.
+ rowStart < children.length;) {
+ // Prefer wider rectangles, the better to fit text labels.
+ const GOLDEN_RATIO = 1.61803398875;
+ let verticalSplit = (width / height) > GOLDEN_RATIO;
+
+ let space;
+ if (verticalSplit) {
+ space = height;
+ } else {
+ space = width;
+ }
+
+ let rowMin = children[rowStart].retainedSize * scale;
+ let rowMax = rowMin;
+ let rowSum = 0;
+ let lastRatio = 0;
+
+ let rowEnd; // One after index of last child in the next row.
+ for (rowEnd = rowStart; rowEnd < children.length; rowEnd++) {
+ let size = children[rowEnd].retainedSize * scale;
+ if (size < rowMin) rowMin = size;
+ if (size > rowMax) rowMax = size;
+ rowSum += size;
+
+ let ratio = Math.max((space * space * rowMax) / (rowSum * rowSum),
+ (rowSum * rowSum) / (space * space * rowMin));
+ if ((lastRatio != 0) && (ratio > lastRatio)) {
+ // Adding the next child makes the aspect ratios worse: remove it and
+ // add the row.
+ rowSum -= size;
+ break;
+ }
+ lastRatio = ratio;
+ }
+
+ let rowLeft = left;
+ let rowTop = top;
+ let rowSpace = rowSum / space;
+
+ for (let i = rowStart; i < rowEnd; i++) {
+ let child = children[i];
+ let size = child.retainedSize * scale;
+
+ let childWidth;
+ let childHeight;
+ if (verticalSplit) {
+ childWidth = rowSpace;
+ childHeight = size / childWidth;
+ } else {
+ childHeight = rowSpace;
+ childWidth = size / childHeight;
+ }
+
+ let childDiv = createTreemapTile(child, childWidth, childHeight, depth + 1);
+ childDiv.style.left = rowLeft + "px";
+ childDiv.style.top = rowTop + "px";
+ // Oversize the final div by kBorder to make the borders overlap.
+ childDiv.style.width = (childWidth + kBorder) + "px";
+ childDiv.style.height = (childHeight + kBorder) + "px";
+ div.appendChild(childDiv);
+
+ if (verticalSplit)
+ rowTop += childHeight;
+ else
+ rowLeft += childWidth;
+ }
+
+ if (verticalSplit) {
+ left += rowSpace;
+ width -= rowSpace;
+ } else {
+ top += rowSpace;
+ height -= rowSpace;
+ }
+
+ rowStart = rowEnd;
+ }
+
+ return div;
+}
+
+function showDominatorTree(v) {
+ // Add the content div to the document first so the browser will calculate
+ // the available width and height.
+ let w = document.body.offsetWidth;
+ let h = document.body.offsetHeight;
+
+ let topTile = createTreemapTile(v, w, h, 0);
+ topTile.style.width = w;
+ topTile.style.height = h;
+ setBody(topTile);
+}
+
+function setBody(div) {
+ let body = document.body;
+ while (body.firstChild) {
+ body.removeChild(body.firstChild);
+ }
+ body.appendChild(div);
+}
+
+function setParents(v) {
+ v.children.forEach(function (child) {
+ child.parent = v;
+ setParents(child);
+ });
+}
+
+setParents(root);
+showDominatorTree(root);
+
+</script>
+</body>
+</html>
+""";
diff --git a/runtime/vm/compiler/asm_intrinsifier_arm.cc b/runtime/vm/compiler/asm_intrinsifier_arm.cc
index 77cb516..822cb23 100644
--- a/runtime/vm/compiler/asm_intrinsifier_arm.cc
+++ b/runtime/vm/compiler/asm_intrinsifier_arm.cc
@@ -302,10 +302,10 @@
// R4 = n ~/ _DIGIT_BITS
__ Asr(R4, R3, Operand(5));
// R8 = &x_digits[0]
- __ add(R8, R1, Operand(target::TypedData::data_offset() - kHeapObjectTag));
+ __ add(R8, R1, Operand(target::TypedData::payload_offset() - kHeapObjectTag));
// R6 = &r_digits[1]
__ add(R6, R2,
- Operand(target::TypedData::data_offset() - kHeapObjectTag +
+ Operand(target::TypedData::payload_offset() - kHeapObjectTag +
kBytesPerBigIntDigit));
// R2 = &x_digits[x_used]
__ add(R2, R8, Operand(R0, LSL, 1));
@@ -342,9 +342,9 @@
// R4 = n ~/ _DIGIT_BITS
__ Asr(R4, R3, Operand(5));
// R6 = &r_digits[0]
- __ add(R6, R2, Operand(target::TypedData::data_offset() - kHeapObjectTag));
+ __ add(R6, R2, Operand(target::TypedData::payload_offset() - kHeapObjectTag));
// R2 = &x_digits[n ~/ _DIGIT_BITS]
- __ add(R2, R1, Operand(target::TypedData::data_offset() - kHeapObjectTag));
+ __ add(R2, R1, Operand(target::TypedData::payload_offset() - kHeapObjectTag));
__ add(R2, R2, Operand(R4, LSL, 2));
// R8 = &r_digits[x_used - n ~/ _DIGIT_BITS - 1]
__ add(R4, R4, Operand(1));
@@ -382,17 +382,17 @@
// R0 = used, R1 = digits
__ ldrd(R0, R1, SP, 3 * target::kWordSize);
// R1 = &digits[0]
- __ add(R1, R1, Operand(target::TypedData::data_offset() - kHeapObjectTag));
+ __ add(R1, R1, Operand(target::TypedData::payload_offset() - kHeapObjectTag));
// R2 = a_used, R3 = a_digits
__ ldrd(R2, R3, SP, 1 * target::kWordSize);
// R3 = &a_digits[0]
- __ add(R3, R3, Operand(target::TypedData::data_offset() - kHeapObjectTag));
+ __ add(R3, R3, Operand(target::TypedData::payload_offset() - kHeapObjectTag));
// R8 = r_digits
__ ldr(R8, Address(SP, 0 * target::kWordSize));
// R8 = &r_digits[0]
- __ add(R8, R8, Operand(target::TypedData::data_offset() - kHeapObjectTag));
+ __ add(R8, R8, Operand(target::TypedData::payload_offset() - kHeapObjectTag));
// R2 = &digits[a_used >> 1], a_used is Smi.
__ add(R2, R1, Operand(R2, LSL, 1));
@@ -442,17 +442,17 @@
// R0 = used, R1 = digits
__ ldrd(R0, R1, SP, 3 * target::kWordSize);
// R1 = &digits[0]
- __ add(R1, R1, Operand(target::TypedData::data_offset() - kHeapObjectTag));
+ __ add(R1, R1, Operand(target::TypedData::payload_offset() - kHeapObjectTag));
// R2 = a_used, R3 = a_digits
__ ldrd(R2, R3, SP, 1 * target::kWordSize);
// R3 = &a_digits[0]
- __ add(R3, R3, Operand(target::TypedData::data_offset() - kHeapObjectTag));
+ __ add(R3, R3, Operand(target::TypedData::payload_offset() - kHeapObjectTag));
// R8 = r_digits
__ ldr(R8, Address(SP, 0 * target::kWordSize));
// R8 = &r_digits[0]
- __ add(R8, R8, Operand(target::TypedData::data_offset() - kHeapObjectTag));
+ __ add(R8, R8, Operand(target::TypedData::payload_offset() - kHeapObjectTag));
// R2 = &digits[a_used >> 1], a_used is Smi.
__ add(R2, R1, Operand(R2, LSL, 1));
@@ -522,7 +522,7 @@
// R3 = x, no_op if x == 0
__ ldrd(R0, R1, SP, 5 * target::kWordSize); // R0 = xi as Smi, R1 = x_digits.
__ add(R1, R1, Operand(R0, LSL, 1));
- __ ldr(R3, FieldAddress(R1, target::TypedData::data_offset()));
+ __ ldr(R3, FieldAddress(R1, target::TypedData::payload_offset()));
__ tst(R3, Operand(R3));
__ b(&done, EQ);
@@ -534,12 +534,12 @@
// R4 = mip = &m_digits[i >> 1]
__ ldrd(R0, R1, SP, 3 * target::kWordSize); // R0 = i as Smi, R1 = m_digits.
__ add(R1, R1, Operand(R0, LSL, 1));
- __ add(R4, R1, Operand(target::TypedData::data_offset() - kHeapObjectTag));
+ __ add(R4, R1, Operand(target::TypedData::payload_offset() - kHeapObjectTag));
// R9 = ajp = &a_digits[j >> 1]
__ ldrd(R0, R1, SP, 1 * target::kWordSize); // R0 = j as Smi, R1 = a_digits.
__ add(R1, R1, Operand(R0, LSL, 1));
- __ add(R9, R1, Operand(target::TypedData::data_offset() - kHeapObjectTag));
+ __ add(R9, R1, Operand(target::TypedData::payload_offset() - kHeapObjectTag));
// R1 = c = 0
__ mov(R1, Operand(0));
@@ -624,7 +624,7 @@
// R4 = xip = &x_digits[i >> 1]
__ ldrd(R2, R3, SP, 2 * target::kWordSize); // R2 = i as Smi, R3 = x_digits
__ add(R3, R3, Operand(R2, LSL, 1));
- __ add(R4, R3, Operand(target::TypedData::data_offset() - kHeapObjectTag));
+ __ add(R4, R3, Operand(target::TypedData::payload_offset() - kHeapObjectTag));
// R3 = x = *xip++, return if x == 0
Label x_zero;
@@ -635,7 +635,7 @@
// R6 = ajp = &a_digits[i]
__ ldr(R1, Address(SP, 1 * target::kWordSize)); // a_digits
__ add(R1, R1, Operand(R2, LSL, 2)); // j == 2*i, i is Smi.
- __ add(R6, R1, Operand(target::TypedData::data_offset() - kHeapObjectTag));
+ __ add(R6, R1, Operand(target::TypedData::payload_offset() - kHeapObjectTag));
// R8:R0 = t = x*x + *ajp
__ ldr(R0, Address(R6, 0));
@@ -727,19 +727,19 @@
__ ldr(R4, Address(SP, 2 * target::kWordSize)); // args
// R3 = rho = args[2]
- __ ldr(R3, FieldAddress(R4, target::TypedData::data_offset() +
+ __ ldr(R3, FieldAddress(R4, target::TypedData::payload_offset() +
2 * kBytesPerBigIntDigit));
// R2 = digits[i >> 1]
__ ldrd(R0, R1, SP, 0 * target::kWordSize); // R0 = i as Smi, R1 = digits
__ add(R1, R1, Operand(R0, LSL, 1));
- __ ldr(R2, FieldAddress(R1, target::TypedData::data_offset()));
+ __ ldr(R2, FieldAddress(R1, target::TypedData::payload_offset()));
// R1:R0 = t = rho*d
__ umull(R0, R1, R2, R3);
// args[4] = t mod DIGIT_BASE = low32(t)
- __ str(R0, FieldAddress(R4, target::TypedData::data_offset() +
+ __ str(R0, FieldAddress(R4, target::TypedData::payload_offset() +
4 * kBytesPerBigIntDigit));
__ mov(R0, Operand(target::ToRawSmi(1))); // One digit processed.
diff --git a/runtime/vm/compiler/asm_intrinsifier_arm64.cc b/runtime/vm/compiler/asm_intrinsifier_arm64.cc
index 600e28c..fac75ab 100644
--- a/runtime/vm/compiler/asm_intrinsifier_arm64.cc
+++ b/runtime/vm/compiler/asm_intrinsifier_arm64.cc
@@ -226,12 +226,12 @@
// R0 = n ~/ (2*_DIGIT_BITS)
__ AsrImmediate(R0, R5, 6);
// R6 = &x_digits[0]
- __ add(R6, R3, Operand(target::TypedData::data_offset() - kHeapObjectTag));
+ __ add(R6, R3, Operand(target::TypedData::payload_offset() - kHeapObjectTag));
// R7 = &x_digits[2*R2]
__ add(R7, R6, Operand(R2, LSL, 3));
// R8 = &r_digits[2*1]
__ add(R8, R4,
- Operand(target::TypedData::data_offset() - kHeapObjectTag +
+ Operand(target::TypedData::payload_offset() - kHeapObjectTag +
2 * kBytesPerBigIntDigit));
// R8 = &r_digits[2*(R2 + n ~/ (2*_DIGIT_BITS) + 1)]
__ add(R0, R0, Operand(R2));
@@ -276,9 +276,9 @@
// R0 = n ~/ (2*_DIGIT_BITS)
__ AsrImmediate(R0, R5, 6);
// R8 = &r_digits[0]
- __ add(R8, R4, Operand(target::TypedData::data_offset() - kHeapObjectTag));
+ __ add(R8, R4, Operand(target::TypedData::payload_offset() - kHeapObjectTag));
// R7 = &x_digits[2*(n ~/ (2*_DIGIT_BITS))]
- __ add(R7, R3, Operand(target::TypedData::data_offset() - kHeapObjectTag));
+ __ add(R7, R3, Operand(target::TypedData::payload_offset() - kHeapObjectTag));
__ add(R7, R7, Operand(R0, LSL, 3));
// R6 = &r_digits[2*(R2 - n ~/ (2*_DIGIT_BITS) - 1)]
__ add(R0, R0, Operand(1));
@@ -323,7 +323,7 @@
__ add(R2, R2, Operand(2)); // used > 0, Smi. R2 = used + 1, round up.
__ add(R2, ZR, Operand(R2, ASR, 2)); // R2 = num of digit pairs to process.
// R3 = &digits[0]
- __ add(R3, R3, Operand(target::TypedData::data_offset() - kHeapObjectTag));
+ __ add(R3, R3, Operand(target::TypedData::payload_offset() - kHeapObjectTag));
// R4 = a_used, R5 = a_digits
__ ldp(R4, R5, Address(SP, 1 * target::kWordSize, Address::PairOffset));
@@ -333,12 +333,12 @@
__ add(R4, R4, Operand(2)); // a_used > 0, Smi. R4 = a_used + 1, round up.
__ add(R4, ZR, Operand(R4, ASR, 2)); // R4 = num of digit pairs to process.
// R5 = &a_digits[0]
- __ add(R5, R5, Operand(target::TypedData::data_offset() - kHeapObjectTag));
+ __ add(R5, R5, Operand(target::TypedData::payload_offset() - kHeapObjectTag));
// R6 = r_digits
__ ldr(R6, Address(SP, 0 * target::kWordSize));
// R6 = &r_digits[0]
- __ add(R6, R6, Operand(target::TypedData::data_offset() - kHeapObjectTag));
+ __ add(R6, R6, Operand(target::TypedData::payload_offset() - kHeapObjectTag));
// R7 = &digits[a_used rounded up to even number].
__ add(R7, R3, Operand(R4, LSL, 3));
@@ -395,7 +395,7 @@
__ add(R2, R2, Operand(2)); // used > 0, Smi. R2 = used + 1, round up.
__ add(R2, ZR, Operand(R2, ASR, 2)); // R2 = num of digit pairs to process.
// R3 = &digits[0]
- __ add(R3, R3, Operand(target::TypedData::data_offset() - kHeapObjectTag));
+ __ add(R3, R3, Operand(target::TypedData::payload_offset() - kHeapObjectTag));
// R4 = a_used, R5 = a_digits
__ ldp(R4, R5, Address(SP, 1 * target::kWordSize, Address::PairOffset));
@@ -405,12 +405,12 @@
__ add(R4, R4, Operand(2)); // a_used > 0, Smi. R4 = a_used + 1, round up.
__ add(R4, ZR, Operand(R4, ASR, 2)); // R4 = num of digit pairs to process.
// R5 = &a_digits[0]
- __ add(R5, R5, Operand(target::TypedData::data_offset() - kHeapObjectTag));
+ __ add(R5, R5, Operand(target::TypedData::payload_offset() - kHeapObjectTag));
// R6 = r_digits
__ ldr(R6, Address(SP, 0 * target::kWordSize));
// R6 = &r_digits[0]
- __ add(R6, R6, Operand(target::TypedData::data_offset() - kHeapObjectTag));
+ __ add(R6, R6, Operand(target::TypedData::payload_offset() - kHeapObjectTag));
// R7 = &digits[a_used rounded up to even number].
__ add(R7, R3, Operand(R4, LSL, 3));
@@ -485,7 +485,7 @@
__ sxtw(R0, R0);
#endif
__ add(R1, R1, Operand(R0, LSL, 1));
- __ ldr(R3, FieldAddress(R1, target::TypedData::data_offset()));
+ __ ldr(R3, FieldAddress(R1, target::TypedData::payload_offset()));
__ tst(R3, Operand(R3));
__ b(&done, EQ);
@@ -505,7 +505,7 @@
__ sxtw(R0, R0);
#endif
__ add(R1, R1, Operand(R0, LSL, 1));
- __ add(R4, R1, Operand(target::TypedData::data_offset() - kHeapObjectTag));
+ __ add(R4, R1, Operand(target::TypedData::payload_offset() - kHeapObjectTag));
// R5 = ajp = &a_digits[j >> 1]
// R0 = j as Smi, R1 = a_digits.
@@ -514,7 +514,7 @@
__ sxtw(R0, R0);
#endif
__ add(R1, R1, Operand(R0, LSL, 1));
- __ add(R5, R1, Operand(target::TypedData::data_offset() - kHeapObjectTag));
+ __ add(R5, R1, Operand(target::TypedData::payload_offset() - kHeapObjectTag));
// R1 = c = 0
__ mov(R1, ZR);
@@ -605,7 +605,7 @@
__ sxtw(R2, R2);
#endif
__ add(R3, R3, Operand(R2, LSL, 1));
- __ add(R4, R3, Operand(target::TypedData::data_offset() - kHeapObjectTag));
+ __ add(R4, R3, Operand(target::TypedData::payload_offset() - kHeapObjectTag));
// R3 = x = *xip++, return if x == 0
Label x_zero;
@@ -616,7 +616,7 @@
// R5 = ajp = &a_digits[i]
__ ldr(R1, Address(SP, 1 * target::kWordSize)); // a_digits
__ add(R1, R1, Operand(R2, LSL, 2)); // j == 2*i, i is Smi.
- __ add(R5, R1, Operand(target::TypedData::data_offset() - kHeapObjectTag));
+ __ add(R5, R1, Operand(target::TypedData::payload_offset() - kHeapObjectTag));
// R6:R1 = t = x*x + *ajp
__ ldr(R0, Address(R5, 0));
@@ -741,7 +741,7 @@
__ ldr(R4, Address(SP, 2 * target::kWordSize)); // args
// R3 = yt = args[0..1]
- __ ldr(R3, FieldAddress(R4, target::TypedData::data_offset()));
+ __ ldr(R3, FieldAddress(R4, target::TypedData::payload_offset()));
// R2 = dh = digits[(i >> 1) - 1 .. i >> 1]
// R0 = i as Smi, R1 = digits
@@ -750,8 +750,8 @@
__ sxtw(R0, R0);
#endif
__ add(R1, R1, Operand(R0, LSL, 1));
- __ ldr(R2, FieldAddress(
- R1, target::TypedData::data_offset() - kBytesPerBigIntDigit));
+ __ ldr(R2, FieldAddress(R1, target::TypedData::payload_offset() -
+ kBytesPerBigIntDigit));
// R0 = qd = (DIGIT_MASK << 32) | DIGIT_MASK = -1
__ movn(R0, Immediate(0), 0);
@@ -762,7 +762,7 @@
__ b(&return_qd, EQ);
// R1 = dl = digits[(i >> 1) - 3 .. (i >> 1) - 2]
- __ ldr(R1, FieldAddress(R1, target::TypedData::data_offset() -
+ __ ldr(R1, FieldAddress(R1, target::TypedData::payload_offset() -
3 * kBytesPerBigIntDigit));
// R5 = yth = yt >> 32
@@ -867,7 +867,7 @@
__ Bind(&return_qd);
// args[2..3] = qd
- __ str(R0, FieldAddress(R4, target::TypedData::data_offset() +
+ __ str(R0, FieldAddress(R4, target::TypedData::payload_offset() +
2 * kBytesPerBigIntDigit));
__ LoadImmediate(R0, target::ToRawSmi(2)); // Two digits processed.
@@ -889,7 +889,7 @@
__ ldr(R4, Address(SP, 2 * target::kWordSize)); // args
// R3 = rho = args[2..3]
- __ ldr(R3, FieldAddress(R4, target::TypedData::data_offset() +
+ __ ldr(R3, FieldAddress(R4, target::TypedData::payload_offset() +
2 * kBytesPerBigIntDigit));
// R2 = digits[i >> 1 .. (i >> 1) + 1]
@@ -899,13 +899,13 @@
__ sxtw(R0, R0);
#endif
__ add(R1, R1, Operand(R0, LSL, 1));
- __ ldr(R2, FieldAddress(R1, target::TypedData::data_offset()));
+ __ ldr(R2, FieldAddress(R1, target::TypedData::payload_offset()));
// R0 = rho*d mod DIGIT_BASE
__ mul(R0, R2, R3); // R0 = low64(R2*R3).
// args[4 .. 5] = R0
- __ str(R0, FieldAddress(R4, target::TypedData::data_offset() +
+ __ str(R0, FieldAddress(R4, target::TypedData::payload_offset() +
4 * kBytesPerBigIntDigit));
__ LoadImmediate(R0, target::ToRawSmi(2)); // Two digits processed.
diff --git a/runtime/vm/compiler/asm_intrinsifier_ia32.cc b/runtime/vm/compiler/asm_intrinsifier_ia32.cc
index 341c285..b744428 100644
--- a/runtime/vm/compiler/asm_intrinsifier_ia32.cc
+++ b/runtime/vm/compiler/asm_intrinsifier_ia32.cc
@@ -317,13 +317,13 @@
__ movl(ESI, ECX);
__ sarl(ESI, Immediate(5)); // ESI = n ~/ _DIGIT_BITS.
__ leal(EBX,
- FieldAddress(EBX, ESI, TIMES_4, target::TypedData::data_offset()));
+ FieldAddress(EBX, ESI, TIMES_4, target::TypedData::payload_offset()));
__ movl(ESI, Address(ESP, 4 * target::kWordSize)); // x_used > 0, Smi.
__ SmiUntag(ESI);
__ decl(ESI);
__ xorl(EAX, EAX); // EAX = 0.
__ movl(EDX,
- FieldAddress(EDI, ESI, TIMES_4, target::TypedData::data_offset()));
+ FieldAddress(EDI, ESI, TIMES_4, target::TypedData::payload_offset()));
__ shldl(EAX, EDX, ECX);
__ movl(Address(EBX, ESI, TIMES_4, kBytesPerBigIntDigit), EAX);
Label last;
@@ -334,7 +334,7 @@
__ movl(EAX, EDX);
__ movl(EDX, FieldAddress(
EDI, ESI, TIMES_4,
- target::TypedData::data_offset() - kBytesPerBigIntDigit));
+ target::TypedData::payload_offset() - kBytesPerBigIntDigit));
__ shldl(EAX, EDX, ECX);
__ movl(Address(EBX, ESI, TIMES_4, 0), EAX);
__ decl(ESI);
@@ -368,11 +368,11 @@
__ decl(ESI);
// EDI = &x_digits[x_used - 1].
__ leal(EDI,
- FieldAddress(EDI, ESI, TIMES_4, target::TypedData::data_offset()));
+ FieldAddress(EDI, ESI, TIMES_4, target::TypedData::payload_offset()));
__ subl(ESI, EDX);
// EBX = &r_digits[x_used - 1 - (n ~/ 32)].
__ leal(EBX,
- FieldAddress(EBX, ESI, TIMES_4, target::TypedData::data_offset()));
+ FieldAddress(EBX, ESI, TIMES_4, target::TypedData::payload_offset()));
__ negl(ESI);
__ movl(EDX, Address(EDI, ESI, TIMES_4, 0));
Label last;
@@ -424,10 +424,10 @@
__ Bind(&add_loop);
// Loop a_used times, ECX = a_used, ECX > 0.
__ movl(EAX,
- FieldAddress(EDI, EDX, TIMES_4, target::TypedData::data_offset()));
+ FieldAddress(EDI, EDX, TIMES_4, target::TypedData::payload_offset()));
__ adcl(EAX,
- FieldAddress(ESI, EDX, TIMES_4, target::TypedData::data_offset()));
- __ movl(FieldAddress(EBX, EDX, TIMES_4, target::TypedData::data_offset()),
+ FieldAddress(ESI, EDX, TIMES_4, target::TypedData::payload_offset()));
+ __ movl(FieldAddress(EBX, EDX, TIMES_4, target::TypedData::payload_offset()),
EAX);
__ incl(EDX); // Does not affect carry flag.
__ decl(ECX); // Does not affect carry flag.
@@ -442,9 +442,9 @@
__ Bind(&carry_loop);
// Loop used - a_used times, ECX = used - a_used, ECX > 0.
__ movl(EAX,
- FieldAddress(EDI, EDX, TIMES_4, target::TypedData::data_offset()));
+ FieldAddress(EDI, EDX, TIMES_4, target::TypedData::payload_offset()));
__ adcl(EAX, Immediate(0));
- __ movl(FieldAddress(EBX, EDX, TIMES_4, target::TypedData::data_offset()),
+ __ movl(FieldAddress(EBX, EDX, TIMES_4, target::TypedData::payload_offset()),
EAX);
__ incl(EDX); // Does not affect carry flag.
__ decl(ECX); // Does not affect carry flag.
@@ -453,7 +453,7 @@
__ Bind(&last_carry);
__ movl(EAX, Immediate(0));
__ adcl(EAX, Immediate(0));
- __ movl(FieldAddress(EBX, EDX, TIMES_4, target::TypedData::data_offset()),
+ __ movl(FieldAddress(EBX, EDX, TIMES_4, target::TypedData::payload_offset()),
EAX);
// Restore THR and return.
@@ -490,10 +490,10 @@
__ Bind(&sub_loop);
// Loop a_used times, ECX = a_used, ECX > 0.
__ movl(EAX,
- FieldAddress(EDI, EDX, TIMES_4, target::TypedData::data_offset()));
+ FieldAddress(EDI, EDX, TIMES_4, target::TypedData::payload_offset()));
__ sbbl(EAX,
- FieldAddress(ESI, EDX, TIMES_4, target::TypedData::data_offset()));
- __ movl(FieldAddress(EBX, EDX, TIMES_4, target::TypedData::data_offset()),
+ FieldAddress(ESI, EDX, TIMES_4, target::TypedData::payload_offset()));
+ __ movl(FieldAddress(EBX, EDX, TIMES_4, target::TypedData::payload_offset()),
EAX);
__ incl(EDX); // Does not affect carry flag.
__ decl(ECX); // Does not affect carry flag.
@@ -508,9 +508,9 @@
__ Bind(&carry_loop);
// Loop used - a_used times, ECX = used - a_used, ECX > 0.
__ movl(EAX,
- FieldAddress(EDI, EDX, TIMES_4, target::TypedData::data_offset()));
+ FieldAddress(EDI, EDX, TIMES_4, target::TypedData::payload_offset()));
__ sbbl(EAX, Immediate(0));
- __ movl(FieldAddress(EBX, EDX, TIMES_4, target::TypedData::data_offset()),
+ __ movl(FieldAddress(EBX, EDX, TIMES_4, target::TypedData::payload_offset()),
EAX);
__ incl(EDX); // Does not affect carry flag.
__ decl(ECX); // Does not affect carry flag.
@@ -557,7 +557,7 @@
__ movl(ECX, Address(ESP, 7 * target::kWordSize)); // x_digits
__ movl(EAX, Address(ESP, 6 * target::kWordSize)); // xi is Smi
__ movl(EBX,
- FieldAddress(ECX, EAX, TIMES_2, target::TypedData::data_offset()));
+ FieldAddress(ECX, EAX, TIMES_2, target::TypedData::payload_offset()));
__ testl(EBX, EBX);
__ j(ZERO, &no_op, Assembler::kNearJump);
@@ -574,13 +574,13 @@
__ movl(EDI, Address(ESP, 6 * target::kWordSize)); // m_digits
__ movl(EAX, Address(ESP, 5 * target::kWordSize)); // i is Smi
__ leal(EDI,
- FieldAddress(EDI, EAX, TIMES_2, target::TypedData::data_offset()));
+ FieldAddress(EDI, EAX, TIMES_2, target::TypedData::payload_offset()));
// ESI = ajp = &a_digits[j >> 1]
__ movl(ESI, Address(ESP, 4 * target::kWordSize)); // a_digits
__ movl(EAX, Address(ESP, 3 * target::kWordSize)); // j is Smi
__ leal(ESI,
- FieldAddress(ESI, EAX, TIMES_2, target::TypedData::data_offset()));
+ FieldAddress(ESI, EAX, TIMES_2, target::TypedData::payload_offset()));
// Save n
__ pushl(EDX);
@@ -678,7 +678,7 @@
__ movl(EDI, Address(ESP, 4 * target::kWordSize)); // x_digits
__ movl(EAX, Address(ESP, 3 * target::kWordSize)); // i is Smi
__ leal(EDI,
- FieldAddress(EDI, EAX, TIMES_2, target::TypedData::data_offset()));
+ FieldAddress(EDI, EAX, TIMES_2, target::TypedData::payload_offset()));
// EBX = x = *xip++, return if x == 0
Label x_zero;
@@ -694,7 +694,7 @@
// ESI = ajp = &a_digits[i]
__ movl(ESI, Address(ESP, 3 * target::kWordSize)); // a_digits
__ leal(ESI,
- FieldAddress(ESI, EAX, TIMES_4, target::TypedData::data_offset()));
+ FieldAddress(ESI, EAX, TIMES_4, target::TypedData::payload_offset()));
// EDX:EAX = t = x*x + *ajp
__ movl(EAX, EBX);
@@ -803,14 +803,14 @@
__ movl(EDI, Address(ESP, 3 * target::kWordSize)); // args
// ECX = yt = args[1]
- __ movl(ECX, FieldAddress(EDI, target::TypedData::data_offset() +
+ __ movl(ECX, FieldAddress(EDI, target::TypedData::payload_offset() +
kBytesPerBigIntDigit));
// EBX = dp = &digits[i >> 1]
__ movl(EBX, Address(ESP, 2 * target::kWordSize)); // digits
__ movl(EAX, Address(ESP, 1 * target::kWordSize)); // i is Smi
__ leal(EBX,
- FieldAddress(EBX, EAX, TIMES_2, target::TypedData::data_offset()));
+ FieldAddress(EBX, EAX, TIMES_2, target::TypedData::payload_offset()));
// EDX = dh = dp[0]
__ movl(EDX, Address(EBX, 0));
@@ -831,8 +831,8 @@
__ Bind(&return_qd);
// args[2] = qd
- __ movl(FieldAddress(
- EDI, target::TypedData::data_offset() + 2 * kBytesPerBigIntDigit),
+ __ movl(FieldAddress(EDI, target::TypedData::payload_offset() +
+ 2 * kBytesPerBigIntDigit),
EAX);
__ movl(EAX, Immediate(target::ToRawSmi(1))); // One digit processed.
@@ -854,21 +854,21 @@
__ movl(EDI, Address(ESP, 3 * target::kWordSize)); // args
// ECX = rho = args[2]
- __ movl(ECX, FieldAddress(EDI, target::TypedData::data_offset() +
+ __ movl(ECX, FieldAddress(EDI, target::TypedData::payload_offset() +
2 * kBytesPerBigIntDigit));
// EAX = digits[i >> 1]
__ movl(EBX, Address(ESP, 2 * target::kWordSize)); // digits
__ movl(EAX, Address(ESP, 1 * target::kWordSize)); // i is Smi
__ movl(EAX,
- FieldAddress(EBX, EAX, TIMES_2, target::TypedData::data_offset()));
+ FieldAddress(EBX, EAX, TIMES_2, target::TypedData::payload_offset()));
// EDX:EAX = t = rho*d
__ mull(ECX);
// args[4] = t mod DIGIT_BASE = low32(t)
- __ movl(FieldAddress(
- EDI, target::TypedData::data_offset() + 4 * kBytesPerBigIntDigit),
+ __ movl(FieldAddress(EDI, target::TypedData::payload_offset() +
+ 4 * kBytesPerBigIntDigit),
EAX);
__ movl(EAX, Immediate(target::ToRawSmi(1))); // One digit processed.
diff --git a/runtime/vm/compiler/asm_intrinsifier_x64.cc b/runtime/vm/compiler/asm_intrinsifier_x64.cc
index 656bce9..2720da8 100644
--- a/runtime/vm/compiler/asm_intrinsifier_x64.cc
+++ b/runtime/vm/compiler/asm_intrinsifier_x64.cc
@@ -238,10 +238,10 @@
__ movq(RSI, RCX);
__ sarq(RSI, Immediate(6)); // RSI = n ~/ (2*_DIGIT_BITS).
__ leaq(RBX,
- FieldAddress(RBX, RSI, TIMES_8, target::TypedData::data_offset()));
+ FieldAddress(RBX, RSI, TIMES_8, target::TypedData::payload_offset()));
__ xorq(RAX, RAX); // RAX = 0.
__ movq(RDX,
- FieldAddress(RDI, R8, TIMES_8, target::TypedData::data_offset()));
+ FieldAddress(RDI, R8, TIMES_8, target::TypedData::payload_offset()));
__ shldq(RAX, RDX, RCX);
__ movq(Address(RBX, R8, TIMES_8, 2 * kBytesPerBigIntDigit), RAX);
Label last;
@@ -251,7 +251,7 @@
__ Bind(&loop);
__ movq(RAX, RDX);
__ movq(RDX, FieldAddress(RDI, R8, TIMES_8,
- target::TypedData::data_offset() -
+ target::TypedData::payload_offset() -
2 * kBytesPerBigIntDigit));
__ shldq(RAX, RDX, RCX);
__ movq(Address(RBX, R8, TIMES_8, 0), RAX);
@@ -284,10 +284,10 @@
__ subq(RSI, Immediate(2)); // x_used > 0, Smi. RSI = x_used - 1, round up.
__ sarq(RSI, Immediate(2));
__ leaq(RDI,
- FieldAddress(RDI, RSI, TIMES_8, target::TypedData::data_offset()));
+ FieldAddress(RDI, RSI, TIMES_8, target::TypedData::payload_offset()));
__ subq(RSI, RDX); // RSI + 1 = number of digit pairs to read.
__ leaq(RBX,
- FieldAddress(RBX, RSI, TIMES_8, target::TypedData::data_offset()));
+ FieldAddress(RBX, RSI, TIMES_8, target::TypedData::payload_offset()));
__ negq(RSI);
__ movq(RDX, Address(RDI, RSI, TIMES_8, 0));
Label last;
@@ -339,10 +339,10 @@
__ Bind(&add_loop);
// Loop (a_used+1)/2 times, RCX > 0.
__ movq(RAX,
- FieldAddress(RDI, RDX, TIMES_8, target::TypedData::data_offset()));
+ FieldAddress(RDI, RDX, TIMES_8, target::TypedData::payload_offset()));
__ adcq(RAX,
- FieldAddress(RSI, RDX, TIMES_8, target::TypedData::data_offset()));
- __ movq(FieldAddress(RBX, RDX, TIMES_8, target::TypedData::data_offset()),
+ FieldAddress(RSI, RDX, TIMES_8, target::TypedData::payload_offset()));
+ __ movq(FieldAddress(RBX, RDX, TIMES_8, target::TypedData::payload_offset()),
RAX);
__ incq(RDX); // Does not affect carry flag.
__ decq(RCX); // Does not affect carry flag.
@@ -356,9 +356,9 @@
__ Bind(&carry_loop);
// Loop (used+1)/2 - (a_used+1)/2 times, R8 > 0.
__ movq(RAX,
- FieldAddress(RDI, RDX, TIMES_8, target::TypedData::data_offset()));
+ FieldAddress(RDI, RDX, TIMES_8, target::TypedData::payload_offset()));
__ adcq(RAX, Immediate(0));
- __ movq(FieldAddress(RBX, RDX, TIMES_8, target::TypedData::data_offset()),
+ __ movq(FieldAddress(RBX, RDX, TIMES_8, target::TypedData::payload_offset()),
RAX);
__ incq(RDX); // Does not affect carry flag.
__ decq(R8); // Does not affect carry flag.
@@ -367,7 +367,7 @@
__ Bind(&last_carry);
Label done;
__ j(NOT_CARRY, &done);
- __ movq(FieldAddress(RBX, RDX, TIMES_8, target::TypedData::data_offset()),
+ __ movq(FieldAddress(RBX, RDX, TIMES_8, target::TypedData::payload_offset()),
Immediate(1));
__ Bind(&done);
@@ -406,10 +406,10 @@
__ Bind(&sub_loop);
// Loop (a_used+1)/2 times, RCX > 0.
__ movq(RAX,
- FieldAddress(RDI, RDX, TIMES_8, target::TypedData::data_offset()));
+ FieldAddress(RDI, RDX, TIMES_8, target::TypedData::payload_offset()));
__ sbbq(RAX,
- FieldAddress(RSI, RDX, TIMES_8, target::TypedData::data_offset()));
- __ movq(FieldAddress(RBX, RDX, TIMES_8, target::TypedData::data_offset()),
+ FieldAddress(RSI, RDX, TIMES_8, target::TypedData::payload_offset()));
+ __ movq(FieldAddress(RBX, RDX, TIMES_8, target::TypedData::payload_offset()),
RAX);
__ incq(RDX); // Does not affect carry flag.
__ decq(RCX); // Does not affect carry flag.
@@ -423,9 +423,9 @@
__ Bind(&carry_loop);
// Loop (used+1)/2 - (a_used+1)/2 times, R8 > 0.
__ movq(RAX,
- FieldAddress(RDI, RDX, TIMES_8, target::TypedData::data_offset()));
+ FieldAddress(RDI, RDX, TIMES_8, target::TypedData::payload_offset()));
__ sbbq(RAX, Immediate(0));
- __ movq(FieldAddress(RBX, RDX, TIMES_8, target::TypedData::data_offset()),
+ __ movq(FieldAddress(RBX, RDX, TIMES_8, target::TypedData::payload_offset()),
RAX);
__ incq(RDX); // Does not affect carry flag.
__ decq(R8); // Does not affect carry flag.
@@ -474,7 +474,7 @@
__ movsxd(RAX, RAX);
#endif
__ movq(RBX,
- FieldAddress(RCX, RAX, TIMES_2, target::TypedData::data_offset()));
+ FieldAddress(RCX, RAX, TIMES_2, target::TypedData::payload_offset()));
__ testq(RBX, RBX);
__ j(ZERO, &done, Assembler::kNearJump);
@@ -494,7 +494,7 @@
__ movsxd(RAX, RAX);
#endif
__ leaq(RDI,
- FieldAddress(RDI, RAX, TIMES_2, target::TypedData::data_offset()));
+ FieldAddress(RDI, RAX, TIMES_2, target::TypedData::payload_offset()));
// RSI = ajp = &a_digits[j >> 1]
__ movq(RSI, Address(RSP, 3 * target::kWordSize)); // a_digits
@@ -503,7 +503,7 @@
__ movsxd(RAX, RAX);
#endif
__ leaq(RSI,
- FieldAddress(RSI, RAX, TIMES_2, target::TypedData::data_offset()));
+ FieldAddress(RSI, RAX, TIMES_2, target::TypedData::payload_offset()));
// RCX = c = 0
__ xorq(RCX, RCX);
@@ -594,7 +594,7 @@
__ movsxd(RAX, RAX);
#endif
__ leaq(RDI,
- FieldAddress(RDI, RAX, TIMES_2, target::TypedData::data_offset()));
+ FieldAddress(RDI, RAX, TIMES_2, target::TypedData::payload_offset()));
// RBX = x = *xip++, return if x == 0
Label x_zero;
@@ -606,7 +606,7 @@
// RSI = ajp = &a_digits[i]
__ movq(RSI, Address(RSP, 2 * target::kWordSize)); // a_digits
__ leaq(RSI,
- FieldAddress(RSI, RAX, TIMES_4, target::TypedData::data_offset()));
+ FieldAddress(RSI, RAX, TIMES_4, target::TypedData::payload_offset()));
// RDX:RAX = t = x*x + *ajp
__ movq(RAX, RBX);
@@ -706,7 +706,7 @@
__ movq(RDI, Address(RSP, 3 * target::kWordSize)); // args
// RCX = yt = args[0..1]
- __ movq(RCX, FieldAddress(RDI, target::TypedData::data_offset()));
+ __ movq(RCX, FieldAddress(RDI, target::TypedData::payload_offset()));
// RBX = dp = &digits[(i >> 1) - 1]
__ movq(RBX, Address(RSP, 2 * target::kWordSize)); // digits
@@ -716,7 +716,7 @@
#endif
__ leaq(RBX, FieldAddress(
RBX, RAX, TIMES_2,
- target::TypedData::data_offset() - kBytesPerBigIntDigit));
+ target::TypedData::payload_offset() - kBytesPerBigIntDigit));
// RDX = dh = dp[0]
__ movq(RDX, Address(RBX, 0));
@@ -737,8 +737,8 @@
__ Bind(&return_qd);
// args[2..3] = qd
- __ movq(FieldAddress(
- RDI, target::TypedData::data_offset() + 2 * kBytesPerBigIntDigit),
+ __ movq(FieldAddress(RDI, target::TypedData::payload_offset() +
+ 2 * kBytesPerBigIntDigit),
RAX);
__ movq(RAX, Immediate(target::ToRawSmi(2))); // Two digits processed.
@@ -760,7 +760,7 @@
__ movq(RDI, Address(RSP, 3 * target::kWordSize)); // args
// RCX = rho = args[2 .. 3]
- __ movq(RCX, FieldAddress(RDI, target::TypedData::data_offset() +
+ __ movq(RCX, FieldAddress(RDI, target::TypedData::payload_offset() +
2 * kBytesPerBigIntDigit));
// RAX = digits[i >> 1 .. (i >> 1) + 1]
@@ -770,14 +770,14 @@
__ movsxd(RAX, RAX);
#endif
__ movq(RAX,
- FieldAddress(RBX, RAX, TIMES_2, target::TypedData::data_offset()));
+ FieldAddress(RBX, RAX, TIMES_2, target::TypedData::payload_offset()));
// RDX:RAX = t = rho*d
__ mulq(RCX);
// args[4 .. 5] = t mod DIGIT_BASE^2 = low64(t)
- __ movq(FieldAddress(
- RDI, target::TypedData::data_offset() + 4 * kBytesPerBigIntDigit),
+ __ movq(FieldAddress(RDI, target::TypedData::payload_offset() +
+ 4 * kBytesPerBigIntDigit),
RAX);
__ movq(RAX, Immediate(target::ToRawSmi(2))); // Two digits processed.
diff --git a/runtime/vm/compiler/backend/il.cc b/runtime/vm/compiler/backend/il.cc
index 0a52e22..8991d8d 100644
--- a/runtime/vm/compiler/backend/il.cc
+++ b/runtime/vm/compiler/backend/il.cc
@@ -2753,7 +2753,7 @@
}
}
}
- } else if (slot().kind() == Slot::Kind::kTypedDataView_data) {
+ } else if (slot().kind() == Slot::Kind::kTypedDataView_typed_data) {
// This case cover the first explicit argument to typed data view
// factories, the data (buffer).
ASSERT(!calls_initializer());
@@ -6529,10 +6529,9 @@
zone_, pointer_loc.payload_type(), pointer_loc.container_type(),
temp);
compiler->EmitNativeMove(dst, pointer_loc, &temp_alloc);
- __ LoadField(
- temp,
- compiler::FieldAddress(
- temp, compiler::target::TypedDataBase::data_field_offset()));
+ __ LoadField(temp,
+ compiler::FieldAddress(
+ temp, compiler::target::PointerBase::data_offset()));
// Copy chuncks.
const intptr_t sp_offset =
@@ -6594,10 +6593,9 @@
__ LoadMemoryValue(temp0, FPREG, 0);
__ LoadMemoryValue(temp0, temp0, typed_data_loc.ToStackSlotOffset());
}
- __ LoadField(
- temp0,
- compiler::FieldAddress(
- temp0, compiler::target::TypedDataBase::data_field_offset()));
+ __ LoadField(temp0,
+ compiler::FieldAddress(
+ temp0, compiler::target::PointerBase::data_offset()));
if (returnLocation.IsPointerToMemory()) {
// Copy blocks from the stack location to TypedData.
@@ -6774,10 +6772,10 @@
if (dst1.IsMultiple()) {
Register typed_data_reg = locs()->in(0).reg();
// Load the data pointer out of the TypedData/Pointer.
- __ LoadField(typed_data_reg,
- compiler::FieldAddress(
- typed_data_reg,
- compiler::target::TypedDataBase::data_field_offset()));
+ __ LoadField(
+ typed_data_reg,
+ compiler::FieldAddress(typed_data_reg,
+ compiler::target::PointerBase::data_offset()));
const auto& multiple = dst1.AsMultiple();
int offset_in_bytes = 0;
diff --git a/runtime/vm/compiler/backend/il_arm.cc b/runtime/vm/compiler/backend/il_arm.cc
index d15b079..2d14822 100644
--- a/runtime/vm/compiler/backend/il_arm.cc
+++ b/runtime/vm/compiler/backend/il_arm.cc
@@ -232,10 +232,9 @@
Register array_reg,
Register start_reg) {
if (IsTypedDataBaseClassId(array_cid)) {
- __ ldr(
- array_reg,
- compiler::FieldAddress(
- array_reg, compiler::target::TypedDataBase::data_field_offset()));
+ __ ldr(array_reg,
+ compiler::FieldAddress(
+ array_reg, compiler::target::PointerBase::data_offset()));
} else {
switch (array_cid) {
case kOneByteStringCid:
@@ -1780,7 +1779,7 @@
// Address of input bytes.
__ LoadFieldFromOffset(bytes_reg, bytes_reg,
- compiler::target::TypedDataBase::data_field_offset());
+ compiler::target::PointerBase::data_offset());
// Table.
__ AddImmediate(
diff --git a/runtime/vm/compiler/backend/il_arm64.cc b/runtime/vm/compiler/backend/il_arm64.cc
index 979c8ba..33b02c1 100644
--- a/runtime/vm/compiler/backend/il_arm64.cc
+++ b/runtime/vm/compiler/backend/il_arm64.cc
@@ -232,10 +232,9 @@
Register array_reg,
Register start_reg) {
if (IsTypedDataBaseClassId(array_cid)) {
- __ ldr(
- array_reg,
- compiler::FieldAddress(
- array_reg, compiler::target::TypedDataBase::data_field_offset()));
+ __ ldr(array_reg,
+ compiler::FieldAddress(
+ array_reg, compiler::target::PointerBase::data_offset()));
} else {
switch (array_cid) {
case kOneByteStringCid:
@@ -1627,7 +1626,7 @@
// Address of input bytes.
__ LoadFieldFromOffset(bytes_reg, bytes_reg,
- compiler::target::TypedDataBase::data_field_offset());
+ compiler::target::PointerBase::data_offset());
// Table.
__ AddImmediate(
diff --git a/runtime/vm/compiler/backend/il_ia32.cc b/runtime/vm/compiler/backend/il_ia32.cc
index 60dd46e..99b20f7 100644
--- a/runtime/vm/compiler/backend/il_ia32.cc
+++ b/runtime/vm/compiler/backend/il_ia32.cc
@@ -131,10 +131,9 @@
Register start_reg) {
intptr_t offset;
if (IsTypedDataBaseClassId(array_cid)) {
- __ movl(
- array_reg,
- compiler::FieldAddress(
- array_reg, compiler::target::TypedDataBase::data_field_offset()));
+ __ movl(array_reg,
+ compiler::FieldAddress(
+ array_reg, compiler::target::PointerBase::data_offset()));
offset = 0;
} else {
switch (array_cid) {
@@ -1328,8 +1327,8 @@
// Address of input bytes.
__ movl(bytes_reg,
- compiler::FieldAddress(
- bytes_reg, compiler::target::TypedDataBase::data_field_offset()));
+ compiler::FieldAddress(bytes_reg,
+ compiler::target::PointerBase::data_offset()));
// Pointers to start, end and end-16.
__ leal(bytes_ptr_reg, compiler::Address(bytes_reg, start_reg, TIMES_1, 0));
diff --git a/runtime/vm/compiler/backend/il_riscv.cc b/runtime/vm/compiler/backend/il_riscv.cc
index 244a95e..882a6db 100644
--- a/runtime/vm/compiler/backend/il_riscv.cc
+++ b/runtime/vm/compiler/backend/il_riscv.cc
@@ -274,8 +274,8 @@
Register start_reg) {
if (IsTypedDataBaseClassId(array_cid)) {
__ lx(array_reg,
- compiler::FieldAddress(
- array_reg, compiler::target::TypedDataBase::data_field_offset()));
+ compiler::FieldAddress(array_reg,
+ compiler::target::PointerBase::data_offset()));
} else {
switch (array_cid) {
case kOneByteStringCid:
@@ -1771,7 +1771,7 @@
// Address of input bytes.
__ LoadFieldFromOffset(bytes_reg, bytes_reg,
- compiler::target::TypedDataBase::data_field_offset());
+ compiler::target::PointerBase::data_offset());
// Table.
__ AddImmediate(
diff --git a/runtime/vm/compiler/backend/il_x64.cc b/runtime/vm/compiler/backend/il_x64.cc
index c966f53..de70052 100644
--- a/runtime/vm/compiler/backend/il_x64.cc
+++ b/runtime/vm/compiler/backend/il_x64.cc
@@ -196,10 +196,9 @@
Register start_reg) {
intptr_t offset;
if (IsTypedDataBaseClassId(array_cid)) {
- __ movq(
- array_reg,
- compiler::FieldAddress(
- array_reg, compiler::target::TypedDataBase::data_field_offset()));
+ __ movq(array_reg,
+ compiler::FieldAddress(
+ array_reg, compiler::target::PointerBase::data_offset()));
offset = 0;
} else {
switch (array_cid) {
@@ -1534,8 +1533,8 @@
// Address of input bytes.
__ movq(bytes_reg,
- compiler::FieldAddress(
- bytes_reg, compiler::target::TypedDataBase::data_field_offset()));
+ compiler::FieldAddress(bytes_reg,
+ compiler::target::PointerBase::data_offset()));
// Pointers to start, end and end-16.
__ leaq(bytes_ptr_reg, compiler::Address(bytes_reg, start_reg, TIMES_1, 0));
diff --git a/runtime/vm/compiler/backend/inliner.cc b/runtime/vm/compiler/backend/inliner.cc
index dd1e62c..3adbb0c 100644
--- a/runtime/vm/compiler/backend/inliner.cc
+++ b/runtime/vm/compiler/backend/inliner.cc
@@ -2601,9 +2601,8 @@
*array = elements;
array_cid = kArrayCid;
} else if (IsExternalTypedDataClassId(array_cid)) {
- LoadUntaggedInstr* elements = new (Z)
- LoadUntaggedInstr(new (Z) Value(*array),
- compiler::target::TypedDataBase::data_field_offset());
+ LoadUntaggedInstr* elements = new (Z) LoadUntaggedInstr(
+ new (Z) Value(*array), compiler::target::PointerBase::data_offset());
*cursor = flow_graph->AppendTo(*cursor, elements, NULL, FlowGraph::kValue);
*array = elements;
}
@@ -2998,9 +2997,8 @@
Instruction** cursor) {
if (array_cid == kDynamicCid || IsExternalTypedDataClassId(array_cid)) {
// Internal or External typed data: load untagged.
- auto elements = new (Z)
- LoadUntaggedInstr(new (Z) Value(*array),
- compiler::target::TypedDataBase::data_field_offset());
+ auto elements = new (Z) LoadUntaggedInstr(
+ new (Z) Value(*array), compiler::target::PointerBase::data_offset());
*cursor = flow_graph->AppendTo(*cursor, elements, NULL, FlowGraph::kValue);
*array = elements;
} else {
diff --git a/runtime/vm/compiler/backend/range_analysis.cc b/runtime/vm/compiler/backend/range_analysis.cc
index d2824a2..0d25a71 100644
--- a/runtime/vm/compiler/backend/range_analysis.cc
+++ b/runtime/vm/compiler/backend/range_analysis.cc
@@ -2803,8 +2803,7 @@
case Slot::Kind::kFunctionType_parameter_types:
case Slot::Kind::kFunctionType_type_parameters:
case Slot::Kind::kInstance_native_fields_array:
- case Slot::Kind::kPointerBase_data_field:
- case Slot::Kind::kTypedDataView_data:
+ case Slot::Kind::kTypedDataView_typed_data:
case Slot::Kind::kType_arguments:
case Slot::Kind::kTypeArgumentsIndex:
case Slot::Kind::kTypeParameters_names:
diff --git a/runtime/vm/compiler/backend/slot.cc b/runtime/vm/compiler/backend/slot.cc
index 75afb9a..db64e39 100644
--- a/runtime/vm/compiler/backend/slot.cc
+++ b/runtime/vm/compiler/backend/slot.cc
@@ -215,7 +215,7 @@
case Slot::Kind::kInstance_native_fields_array:
case Slot::Kind::kTypeArguments:
case Slot::Kind::kTypedDataView_offset_in_bytes:
- case Slot::Kind::kTypedDataView_data:
+ case Slot::Kind::kTypedDataView_typed_data:
case Slot::Kind::kGrowableObjectArray_data:
case Slot::Kind::kArray_type_arguments:
case Slot::Kind::kContext_parent:
@@ -232,7 +232,6 @@
case Slot::Kind::kFunctionType_named_parameter_names:
case Slot::Kind::kFunctionType_parameter_types:
case Slot::Kind::kFunctionType_type_parameters:
- case Slot::Kind::kPointerBase_data_field:
case Slot::Kind::kType_arguments:
case Slot::Kind::kTypeArgumentsIndex:
case Slot::Kind::kTypeParameters_names:
diff --git a/runtime/vm/compiler/backend/slot.h b/runtime/vm/compiler/backend/slot.h
index 88c1dd8..09b1186 100644
--- a/runtime/vm/compiler/backend/slot.h
+++ b/runtime/vm/compiler/backend/slot.h
@@ -96,7 +96,7 @@
V(GrowableObjectArray, UntaggedGrowableObjectArray, data, Array, VAR) \
V(TypedDataBase, UntaggedTypedDataBase, length, Smi, FINAL) \
V(TypedDataView, UntaggedTypedDataView, offset_in_bytes, Smi, FINAL) \
- V(TypedDataView, UntaggedTypedDataView, data, Dynamic, FINAL) \
+ V(TypedDataView, UntaggedTypedDataView, typed_data, Dynamic, FINAL) \
V(String, UntaggedString, length, Smi, FINAL) \
V(LinkedHashBase, UntaggedLinkedHashBase, index, TypedDataUint32Array, VAR) \
V(LinkedHashBase, UntaggedLinkedHashBase, data, Array, VAR) \
@@ -109,7 +109,6 @@
V(ArgumentsDescriptor, UntaggedArray, positional_count, Smi, FINAL) \
V(ArgumentsDescriptor, UntaggedArray, count, Smi, FINAL) \
V(ArgumentsDescriptor, UntaggedArray, size, Smi, FINAL) \
- V(PointerBase, UntaggedPointerBase, data_field, Dynamic, FINAL) \
V(TypeArguments, UntaggedTypeArguments, length, Smi, FINAL) \
V(TypeParameters, UntaggedTypeParameters, names, Array, FINAL) \
V(TypeParameter, UntaggedTypeParameter, bound, Dynamic, FINAL) \
@@ -154,8 +153,7 @@
FINAL) \
V(FunctionType, UntaggedFunctionType, packed_type_parameter_counts, Uint16, \
FINAL) \
- V(Pointer, UntaggedPointer, data_field, FfiIntPtr, FINAL) \
- V(TypedDataBase, UntaggedTypedDataBase, data_field, IntPtr, VAR) \
+ V(PointerBase, UntaggedPointerBase, data, IntPtr, VAR) \
V(TypeParameter, UntaggedTypeParameter, flags, Uint8, FINAL)
// For uses that do not need the exact_type (boxed) or representation (unboxed)
diff --git a/runtime/vm/compiler/call_specializer.cc b/runtime/vm/compiler/call_specializer.cc
index c6325a5..ae363e2 100644
--- a/runtime/vm/compiler/call_specializer.cc
+++ b/runtime/vm/compiler/call_specializer.cc
@@ -1676,9 +1676,8 @@
const intptr_t element_size = TypedDataBase::ElementSizeFor(cid);
const intptr_t index_scale = element_size;
- auto data = new (Z)
- LoadUntaggedInstr(new (Z) Value(array),
- compiler::target::TypedDataBase::data_field_offset());
+ auto data = new (Z) LoadUntaggedInstr(
+ new (Z) Value(array), compiler::target::PointerBase::data_offset());
flow_graph_->InsertBefore(call, data, call->env(), FlowGraph::kValue);
Definition* load = new (Z) LoadIndexedInstr(
@@ -1754,9 +1753,8 @@
break;
}
- auto data = new (Z)
- LoadUntaggedInstr(new (Z) Value(array),
- compiler::target::TypedDataBase::data_field_offset());
+ auto data = new (Z) LoadUntaggedInstr(
+ new (Z) Value(array), compiler::target::PointerBase::data_offset());
flow_graph_->InsertBefore(call, data, call->env(), FlowGraph::kValue);
auto store = new (Z) StoreIndexedInstr(
diff --git a/runtime/vm/compiler/frontend/kernel_to_il.cc b/runtime/vm/compiler/frontend/kernel_to_il.cc
index 5147fdc..9fd1243 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.cc
+++ b/runtime/vm/compiler/frontend/kernel_to_il.cc
@@ -1115,7 +1115,7 @@
case MethodRecognizer::kTypedDataViewTypedData:
ASSERT_EQUAL(function.NumParameters(), 1);
body += LoadLocal(parsed_function_->RawParameterVariable(0));
- body += LoadNativeField(Slot::TypedDataView_data());
+ body += LoadNativeField(Slot::TypedDataView_typed_data());
break;
case MethodRecognizer::kClassIDgetID:
ASSERT_EQUAL(function.NumParameters(), 1);
@@ -1374,7 +1374,7 @@
body += LoadLocal(arg_pointer);
body += CheckNullOptimized(String::ZoneHandle(Z, function.name()));
// No GC from here til LoadIndexed.
- body += LoadUntagged(compiler::target::PointerBase::data_field_offset());
+ body += LoadUntagged(compiler::target::PointerBase::data_offset());
body += LoadLocal(arg_offset_not_null);
body += UnboxTruncate(kUnboxedFfiIntPtr);
body += LoadIndexed(typed_data_cid, /*index_scale=*/1,
@@ -1415,8 +1415,8 @@
LocalVariable* pointer = MakeTemporary();
body += LoadLocal(pointer);
body += LoadLocal(address);
- body += UnboxTruncate(kUnboxedFfiIntPtr);
- body += StoreNativeField(Slot::Pointer_data_field());
+ body += UnboxTruncate(kUnboxedIntPtr);
+ body += StoreNativeField(Slot::PointerBase_data());
body += DropTempsPreserveTop(1); // Drop [address] keep [pointer].
}
body += DropTempsPreserveTop(1); // Drop [arg_offset].
@@ -1487,13 +1487,13 @@
body += LoadLocal(arg_pointer); // Pointer.
body += CheckNullOptimized(String::ZoneHandle(Z, function.name()));
// No GC from here til StoreIndexed.
- body += LoadUntagged(compiler::target::PointerBase::data_field_offset());
+ body += LoadUntagged(compiler::target::PointerBase::data_offset());
body += LoadLocal(arg_offset_not_null);
body += UnboxTruncate(kUnboxedFfiIntPtr);
body += LoadLocal(arg_value_not_null);
if (kind == MethodRecognizer::kFfiStorePointer) {
// This can only be Pointer, so it is always safe to LoadUntagged.
- body += LoadUntagged(compiler::target::Pointer::data_field_offset());
+ body += LoadUntagged(compiler::target::PointerBase::data_offset());
body += ConvertUntaggedToUnboxed(kUnboxedFfiIntPtr);
} else {
// Avoid any unnecessary (and potentially deoptimizing) int
@@ -1524,15 +1524,15 @@
body += LoadLocal(MakeTemporary()); // Duplicate Pointer.
body += LoadLocal(parsed_function_->RawParameterVariable(0)); // Address.
body += CheckNullOptimized(String::ZoneHandle(Z, function.name()));
- body += UnboxTruncate(kUnboxedFfiIntPtr);
- body += StoreNativeField(Slot::Pointer_data_field());
+ body += UnboxTruncate(kUnboxedIntPtr);
+ body += StoreNativeField(Slot::PointerBase_data());
} break;
case MethodRecognizer::kFfiGetAddress: {
ASSERT_EQUAL(function.NumParameters(), 1);
body += LoadLocal(parsed_function_->RawParameterVariable(0)); // Pointer.
body += CheckNullOptimized(String::ZoneHandle(Z, function.name()));
// This can only be Pointer, so it is always safe to LoadUntagged.
- body += LoadUntagged(compiler::target::Pointer::data_field_offset());
+ body += LoadUntagged(compiler::target::PointerBase::data_offset());
body += ConvertUntaggedToUnboxed(kUnboxedFfiIntPtr);
body += Box(kUnboxedFfiIntPtr);
} break;
@@ -1582,9 +1582,9 @@
// Initialize the result's data pointer field.
body += LoadLocal(typed_data_object);
body += LoadLocal(arg_pointer);
- body += LoadUntagged(compiler::target::Pointer::data_field_offset());
+ body += LoadUntagged(compiler::target::PointerBase::data_offset());
body += ConvertUntaggedToUnboxed(kUnboxedIntPtr);
- body += StoreNativeField(Slot::TypedDataBase_data_field(),
+ body += StoreNativeField(Slot::PointerBase_data(),
StoreInstanceFieldInstr::Kind::kInitializing,
kNoStoreBarrier);
} break;
@@ -1673,7 +1673,7 @@
body += LoadLocal(view_object);
body += LoadLocal(typed_data);
- body += StoreNativeField(token_pos, Slot::TypedDataView_data(),
+ body += StoreNativeField(token_pos, Slot::TypedDataView_typed_data(),
StoreInstanceFieldInstr::Kind::kInitializing);
body += LoadLocal(view_object);
@@ -1694,12 +1694,12 @@
// instructions!
body += LoadLocal(view_object);
body += LoadLocal(typed_data);
- body += LoadUntagged(compiler::target::TypedDataBase::data_field_offset());
+ body += LoadUntagged(compiler::target::PointerBase::data_offset());
body += ConvertUntaggedToUnboxed(kUnboxedIntPtr);
body += LoadLocal(offset_in_bytes);
body += UnboxSmiToIntptr();
body += AddIntptrIntegers();
- body += StoreNativeField(Slot::TypedDataBase_data_field());
+ body += StoreNativeField(Slot::PointerBase_data());
return body;
}
@@ -4082,8 +4082,8 @@
LocalVariable* pointer = MakeTemporary();
code += LoadLocal(pointer);
code += LoadLocal(address);
- code += UnboxTruncate(kUnboxedFfiIntPtr);
- code += StoreNativeField(Slot::Pointer_data_field());
+ code += UnboxTruncate(kUnboxedIntPtr);
+ code += StoreNativeField(Slot::PointerBase_data());
code += StoreLocal(TokenPosition::kNoSource, result);
code += Drop(); // StoreLocal^
code += Drop(); // address
@@ -4145,7 +4145,7 @@
for (intptr_t i = 0; i < num_defs; i++) {
body += LoadLocal(variable);
body += LoadTypedDataBaseFromCompound();
- body += LoadUntagged(compiler::target::Pointer::data_field_offset());
+ body += LoadUntagged(compiler::target::PointerBase::data_offset());
body += IntConstant(offset_in_bytes);
const Representation representation = representations[i];
offset_in_bytes += RepresentationUtils::ValueSize(representation);
@@ -4167,7 +4167,7 @@
for (intptr_t i = 0; i < num_defs; i++) {
const Representation representation = representations[i];
body += LoadLocal(uint8_list);
- body += LoadUntagged(compiler::target::TypedDataBase::data_field_offset());
+ body += LoadUntagged(compiler::target::PointerBase::data_offset());
body += IntConstant(offset_in_bytes);
body += LoadLocal(definitions->At(i));
body += StoreIndexedTypedDataUnboxed(representation, /*index_scale=*/1,
@@ -4221,7 +4221,7 @@
const classid_t typed_data_cidd = typed_data_cid(chunk_sizee);
body += LoadLocal(typed_data_base);
- body += LoadUntagged(compiler::target::TypedDataBase::data_field_offset());
+ body += LoadUntagged(compiler::target::PointerBase::data_offset());
body += IntConstant(offset_in_bytes);
body += LoadIndexed(typed_data_cidd, /*index_scale=*/1,
/*index_unboxed=*/false);
@@ -4266,7 +4266,7 @@
LocalVariable* chunk_value = MakeTemporary("chunk_value");
body += LoadLocal(typed_data_base);
- body += LoadUntagged(compiler::target::TypedDataBase::data_field_offset());
+ body += LoadUntagged(compiler::target::PointerBase::data_offset());
body += IntConstant(offset_in_bytes);
body += LoadLocal(chunk_value);
body += StoreIndexedTypedData(typed_data_cidd, /*index_scale=*/1,
@@ -4425,7 +4425,7 @@
Fragment body;
if (marshaller.IsPointer(arg_index)) {
// This can only be Pointer, so it is always safe to LoadUntagged.
- body += LoadUntagged(compiler::target::Pointer::data_field_offset());
+ body += LoadUntagged(compiler::target::PointerBase::data_offset());
body += ConvertUntaggedToUnboxed(kUnboxedFfiIntPtr);
} else if (marshaller.IsHandle(arg_index)) {
body += WrapHandle(api_local_scope);
@@ -4557,7 +4557,7 @@
->context_variables()[0]));
// This can only be Pointer, so it is always safe to LoadUntagged.
- body += LoadUntagged(compiler::target::Pointer::data_field_offset());
+ body += LoadUntagged(compiler::target::PointerBase::data_offset());
body += ConvertUntaggedToUnboxed(kUnboxedFfiIntPtr);
if (marshaller.PassTypedData()) {
diff --git a/runtime/vm/compiler/graph_intrinsifier.cc b/runtime/vm/compiler/graph_intrinsifier.cc
index 18abb34..5f6ec71 100644
--- a/runtime/vm/compiler/graph_intrinsifier.cc
+++ b/runtime/vm/compiler/graph_intrinsifier.cc
@@ -236,7 +236,7 @@
if (IsExternalTypedDataClassId(array_cid)) {
array = builder.AddDefinition(new LoadUntaggedInstr(
- new Value(array), target::TypedDataBase::data_field_offset()));
+ new Value(array), target::PointerBase::data_offset()));
}
Definition* result = builder.AddDefinition(new LoadIndexedInstr(
@@ -420,7 +420,7 @@
if (IsExternalTypedDataClassId(array_cid)) {
array = builder.AddDefinition(new LoadUntaggedInstr(
- new Value(array), target::TypedDataBase::data_field_offset()));
+ new Value(array), target::PointerBase::data_offset()));
}
// No store barrier.
ASSERT(IsExternalTypedDataClassId(array_cid) ||
diff --git a/runtime/vm/compiler/runtime_api.cc b/runtime/vm/compiler/runtime_api.cc
index 8f78177d5..51062e6 100644
--- a/runtime/vm/compiler/runtime_api.cc
+++ b/runtime/vm/compiler/runtime_api.cc
@@ -509,7 +509,7 @@
return 0;
}
if (dart::IsTypedDataClassId(cid)) {
- return TypedData::data_offset();
+ return TypedData::payload_offset();
}
switch (cid) {
case kArrayCid:
diff --git a/runtime/vm/compiler/runtime_api.h b/runtime/vm/compiler/runtime_api.h
index 6a51005..a23de21 100644
--- a/runtime/vm/compiler/runtime_api.h
+++ b/runtime/vm/compiler/runtime_api.h
@@ -615,10 +615,10 @@
class PointerBase : public AllStatic {
public:
- static word data_field_offset();
+ static word data_offset();
};
-class TypedDataBase : public PointerBase {
+class TypedDataBase : public AllStatic {
public:
static word length_offset();
static word InstanceSize();
@@ -627,7 +627,7 @@
class TypedData : public AllStatic {
public:
- static word data_offset();
+ static word payload_offset();
static word HeaderSize();
static word InstanceSize();
static word InstanceSize(word lengthInBytes);
@@ -636,7 +636,6 @@
class ExternalTypedData : public AllStatic {
public:
- static word data_offset();
static word InstanceSize();
FINAL_CLASS();
};
@@ -644,7 +643,7 @@
class TypedDataView : public AllStatic {
public:
static word offset_in_bytes_offset();
- static word data_offset();
+ static word typed_data_offset();
static word InstanceSize();
FINAL_CLASS();
};
@@ -700,7 +699,7 @@
static word ptr_offset();
};
-class Pointer : public PointerBase {
+class Pointer : public AllStatic {
public:
static word type_arguments_offset();
static word InstanceSize();
diff --git a/runtime/vm/compiler/runtime_offsets_extracted.h b/runtime/vm/compiler/runtime_offsets_extracted.h
index adeab04..5b0ad83 100644
--- a/runtime/vm/compiler/runtime_offsets_extracted.h
+++ b/runtime/vm/compiler/runtime_offsets_extracted.h
@@ -226,7 +226,7 @@
static constexpr dart::compiler::target::word ObjectStore_type_type_offset =
104;
static constexpr dart::compiler::target::word OneByteString_data_offset = 12;
-static constexpr dart::compiler::target::word PointerBase_data_field_offset = 4;
+static constexpr dart::compiler::target::word PointerBase_data_offset = 4;
static constexpr dart::compiler::target::word Pointer_type_arguments_offset = 8;
static constexpr dart::compiler::target::word
SingleTargetCache_entry_point_offset = 8;
@@ -469,10 +469,11 @@
static constexpr dart::compiler::target::word TypeParameter_flags_offset = 24;
static constexpr dart::compiler::target::word TypeRef_type_offset = 12;
static constexpr dart::compiler::target::word TypedDataBase_length_offset = 8;
-static constexpr dart::compiler::target::word TypedDataView_data_offset = 12;
+static constexpr dart::compiler::target::word TypedDataView_typed_data_offset =
+ 12;
static constexpr dart::compiler::target::word
TypedDataView_offset_in_bytes_offset = 16;
-static constexpr dart::compiler::target::word TypedData_data_offset = 12;
+static constexpr dart::compiler::target::word TypedData_payload_offset = 12;
static constexpr dart::compiler::target::word
UnhandledException_exception_offset = 4;
static constexpr dart::compiler::target::word
@@ -792,7 +793,7 @@
static constexpr dart::compiler::target::word ObjectStore_type_type_offset =
208;
static constexpr dart::compiler::target::word OneByteString_data_offset = 16;
-static constexpr dart::compiler::target::word PointerBase_data_field_offset = 8;
+static constexpr dart::compiler::target::word PointerBase_data_offset = 8;
static constexpr dart::compiler::target::word Pointer_type_arguments_offset =
16;
static constexpr dart::compiler::target::word
@@ -1041,10 +1042,11 @@
static constexpr dart::compiler::target::word TypeParameter_flags_offset = 44;
static constexpr dart::compiler::target::word TypeRef_type_offset = 24;
static constexpr dart::compiler::target::word TypedDataBase_length_offset = 16;
-static constexpr dart::compiler::target::word TypedDataView_data_offset = 24;
+static constexpr dart::compiler::target::word TypedDataView_typed_data_offset =
+ 24;
static constexpr dart::compiler::target::word
TypedDataView_offset_in_bytes_offset = 32;
-static constexpr dart::compiler::target::word TypedData_data_offset = 24;
+static constexpr dart::compiler::target::word TypedData_payload_offset = 24;
static constexpr dart::compiler::target::word
UnhandledException_exception_offset = 8;
static constexpr dart::compiler::target::word
@@ -1363,7 +1365,7 @@
static constexpr dart::compiler::target::word ObjectStore_type_type_offset =
104;
static constexpr dart::compiler::target::word OneByteString_data_offset = 12;
-static constexpr dart::compiler::target::word PointerBase_data_field_offset = 4;
+static constexpr dart::compiler::target::word PointerBase_data_offset = 4;
static constexpr dart::compiler::target::word Pointer_type_arguments_offset = 8;
static constexpr dart::compiler::target::word
SingleTargetCache_entry_point_offset = 8;
@@ -1606,10 +1608,11 @@
static constexpr dart::compiler::target::word TypeParameter_flags_offset = 24;
static constexpr dart::compiler::target::word TypeRef_type_offset = 12;
static constexpr dart::compiler::target::word TypedDataBase_length_offset = 8;
-static constexpr dart::compiler::target::word TypedDataView_data_offset = 12;
+static constexpr dart::compiler::target::word TypedDataView_typed_data_offset =
+ 12;
static constexpr dart::compiler::target::word
TypedDataView_offset_in_bytes_offset = 16;
-static constexpr dart::compiler::target::word TypedData_data_offset = 12;
+static constexpr dart::compiler::target::word TypedData_payload_offset = 12;
static constexpr dart::compiler::target::word
UnhandledException_exception_offset = 4;
static constexpr dart::compiler::target::word
@@ -1926,7 +1929,7 @@
static constexpr dart::compiler::target::word ObjectStore_type_type_offset =
208;
static constexpr dart::compiler::target::word OneByteString_data_offset = 16;
-static constexpr dart::compiler::target::word PointerBase_data_field_offset = 8;
+static constexpr dart::compiler::target::word PointerBase_data_offset = 8;
static constexpr dart::compiler::target::word Pointer_type_arguments_offset =
16;
static constexpr dart::compiler::target::word
@@ -2175,10 +2178,11 @@
static constexpr dart::compiler::target::word TypeParameter_flags_offset = 44;
static constexpr dart::compiler::target::word TypeRef_type_offset = 24;
static constexpr dart::compiler::target::word TypedDataBase_length_offset = 16;
-static constexpr dart::compiler::target::word TypedDataView_data_offset = 24;
+static constexpr dart::compiler::target::word TypedDataView_typed_data_offset =
+ 24;
static constexpr dart::compiler::target::word
TypedDataView_offset_in_bytes_offset = 32;
-static constexpr dart::compiler::target::word TypedData_data_offset = 24;
+static constexpr dart::compiler::target::word TypedData_payload_offset = 24;
static constexpr dart::compiler::target::word
UnhandledException_exception_offset = 8;
static constexpr dart::compiler::target::word
@@ -2498,7 +2502,7 @@
static constexpr dart::compiler::target::word ObjectStore_type_type_offset =
208;
static constexpr dart::compiler::target::word OneByteString_data_offset = 16;
-static constexpr dart::compiler::target::word PointerBase_data_field_offset = 8;
+static constexpr dart::compiler::target::word PointerBase_data_offset = 8;
static constexpr dart::compiler::target::word Pointer_type_arguments_offset =
16;
static constexpr dart::compiler::target::word
@@ -2747,10 +2751,11 @@
static constexpr dart::compiler::target::word TypeParameter_flags_offset = 36;
static constexpr dart::compiler::target::word TypeRef_type_offset = 24;
static constexpr dart::compiler::target::word TypedDataBase_length_offset = 20;
-static constexpr dart::compiler::target::word TypedDataView_data_offset = 24;
+static constexpr dart::compiler::target::word TypedDataView_typed_data_offset =
+ 24;
static constexpr dart::compiler::target::word
TypedDataView_offset_in_bytes_offset = 28;
-static constexpr dart::compiler::target::word TypedData_data_offset = 24;
+static constexpr dart::compiler::target::word TypedData_payload_offset = 24;
static constexpr dart::compiler::target::word
UnhandledException_exception_offset = 8;
static constexpr dart::compiler::target::word
@@ -3069,7 +3074,7 @@
static constexpr dart::compiler::target::word ObjectStore_type_type_offset =
208;
static constexpr dart::compiler::target::word OneByteString_data_offset = 16;
-static constexpr dart::compiler::target::word PointerBase_data_field_offset = 8;
+static constexpr dart::compiler::target::word PointerBase_data_offset = 8;
static constexpr dart::compiler::target::word Pointer_type_arguments_offset =
16;
static constexpr dart::compiler::target::word
@@ -3318,10 +3323,11 @@
static constexpr dart::compiler::target::word TypeParameter_flags_offset = 36;
static constexpr dart::compiler::target::word TypeRef_type_offset = 24;
static constexpr dart::compiler::target::word TypedDataBase_length_offset = 20;
-static constexpr dart::compiler::target::word TypedDataView_data_offset = 24;
+static constexpr dart::compiler::target::word TypedDataView_typed_data_offset =
+ 24;
static constexpr dart::compiler::target::word
TypedDataView_offset_in_bytes_offset = 28;
-static constexpr dart::compiler::target::word TypedData_data_offset = 24;
+static constexpr dart::compiler::target::word TypedData_payload_offset = 24;
static constexpr dart::compiler::target::word
UnhandledException_exception_offset = 8;
static constexpr dart::compiler::target::word
@@ -3641,7 +3647,7 @@
static constexpr dart::compiler::target::word ObjectStore_type_type_offset =
104;
static constexpr dart::compiler::target::word OneByteString_data_offset = 12;
-static constexpr dart::compiler::target::word PointerBase_data_field_offset = 4;
+static constexpr dart::compiler::target::word PointerBase_data_offset = 4;
static constexpr dart::compiler::target::word Pointer_type_arguments_offset = 8;
static constexpr dart::compiler::target::word
SingleTargetCache_entry_point_offset = 8;
@@ -3884,10 +3890,11 @@
static constexpr dart::compiler::target::word TypeParameter_flags_offset = 24;
static constexpr dart::compiler::target::word TypeRef_type_offset = 12;
static constexpr dart::compiler::target::word TypedDataBase_length_offset = 8;
-static constexpr dart::compiler::target::word TypedDataView_data_offset = 12;
+static constexpr dart::compiler::target::word TypedDataView_typed_data_offset =
+ 12;
static constexpr dart::compiler::target::word
TypedDataView_offset_in_bytes_offset = 16;
-static constexpr dart::compiler::target::word TypedData_data_offset = 12;
+static constexpr dart::compiler::target::word TypedData_payload_offset = 12;
static constexpr dart::compiler::target::word
UnhandledException_exception_offset = 4;
static constexpr dart::compiler::target::word
@@ -4209,7 +4216,7 @@
static constexpr dart::compiler::target::word ObjectStore_type_type_offset =
208;
static constexpr dart::compiler::target::word OneByteString_data_offset = 16;
-static constexpr dart::compiler::target::word PointerBase_data_field_offset = 8;
+static constexpr dart::compiler::target::word PointerBase_data_offset = 8;
static constexpr dart::compiler::target::word Pointer_type_arguments_offset =
16;
static constexpr dart::compiler::target::word
@@ -4458,10 +4465,11 @@
static constexpr dart::compiler::target::word TypeParameter_flags_offset = 44;
static constexpr dart::compiler::target::word TypeRef_type_offset = 24;
static constexpr dart::compiler::target::word TypedDataBase_length_offset = 16;
-static constexpr dart::compiler::target::word TypedDataView_data_offset = 24;
+static constexpr dart::compiler::target::word TypedDataView_typed_data_offset =
+ 24;
static constexpr dart::compiler::target::word
TypedDataView_offset_in_bytes_offset = 32;
-static constexpr dart::compiler::target::word TypedData_data_offset = 24;
+static constexpr dart::compiler::target::word TypedData_payload_offset = 24;
static constexpr dart::compiler::target::word
UnhandledException_exception_offset = 8;
static constexpr dart::compiler::target::word
@@ -4777,7 +4785,7 @@
static constexpr dart::compiler::target::word ObjectStore_type_type_offset =
104;
static constexpr dart::compiler::target::word OneByteString_data_offset = 12;
-static constexpr dart::compiler::target::word PointerBase_data_field_offset = 4;
+static constexpr dart::compiler::target::word PointerBase_data_offset = 4;
static constexpr dart::compiler::target::word Pointer_type_arguments_offset = 8;
static constexpr dart::compiler::target::word
SingleTargetCache_entry_point_offset = 8;
@@ -5020,10 +5028,11 @@
static constexpr dart::compiler::target::word TypeParameter_flags_offset = 24;
static constexpr dart::compiler::target::word TypeRef_type_offset = 12;
static constexpr dart::compiler::target::word TypedDataBase_length_offset = 8;
-static constexpr dart::compiler::target::word TypedDataView_data_offset = 12;
+static constexpr dart::compiler::target::word TypedDataView_typed_data_offset =
+ 12;
static constexpr dart::compiler::target::word
TypedDataView_offset_in_bytes_offset = 16;
-static constexpr dart::compiler::target::word TypedData_data_offset = 12;
+static constexpr dart::compiler::target::word TypedData_payload_offset = 12;
static constexpr dart::compiler::target::word
UnhandledException_exception_offset = 4;
static constexpr dart::compiler::target::word
@@ -5337,7 +5346,7 @@
static constexpr dart::compiler::target::word ObjectStore_type_type_offset =
208;
static constexpr dart::compiler::target::word OneByteString_data_offset = 16;
-static constexpr dart::compiler::target::word PointerBase_data_field_offset = 8;
+static constexpr dart::compiler::target::word PointerBase_data_offset = 8;
static constexpr dart::compiler::target::word Pointer_type_arguments_offset =
16;
static constexpr dart::compiler::target::word
@@ -5586,10 +5595,11 @@
static constexpr dart::compiler::target::word TypeParameter_flags_offset = 44;
static constexpr dart::compiler::target::word TypeRef_type_offset = 24;
static constexpr dart::compiler::target::word TypedDataBase_length_offset = 16;
-static constexpr dart::compiler::target::word TypedDataView_data_offset = 24;
+static constexpr dart::compiler::target::word TypedDataView_typed_data_offset =
+ 24;
static constexpr dart::compiler::target::word
TypedDataView_offset_in_bytes_offset = 32;
-static constexpr dart::compiler::target::word TypedData_data_offset = 24;
+static constexpr dart::compiler::target::word TypedData_payload_offset = 24;
static constexpr dart::compiler::target::word
UnhandledException_exception_offset = 8;
static constexpr dart::compiler::target::word
@@ -5902,7 +5912,7 @@
static constexpr dart::compiler::target::word ObjectStore_type_type_offset =
104;
static constexpr dart::compiler::target::word OneByteString_data_offset = 12;
-static constexpr dart::compiler::target::word PointerBase_data_field_offset = 4;
+static constexpr dart::compiler::target::word PointerBase_data_offset = 4;
static constexpr dart::compiler::target::word Pointer_type_arguments_offset = 8;
static constexpr dart::compiler::target::word
SingleTargetCache_entry_point_offset = 8;
@@ -6145,10 +6155,11 @@
static constexpr dart::compiler::target::word TypeParameter_flags_offset = 24;
static constexpr dart::compiler::target::word TypeRef_type_offset = 12;
static constexpr dart::compiler::target::word TypedDataBase_length_offset = 8;
-static constexpr dart::compiler::target::word TypedDataView_data_offset = 12;
+static constexpr dart::compiler::target::word TypedDataView_typed_data_offset =
+ 12;
static constexpr dart::compiler::target::word
TypedDataView_offset_in_bytes_offset = 16;
-static constexpr dart::compiler::target::word TypedData_data_offset = 12;
+static constexpr dart::compiler::target::word TypedData_payload_offset = 12;
static constexpr dart::compiler::target::word
UnhandledException_exception_offset = 4;
static constexpr dart::compiler::target::word
@@ -6459,7 +6470,7 @@
static constexpr dart::compiler::target::word ObjectStore_type_type_offset =
208;
static constexpr dart::compiler::target::word OneByteString_data_offset = 16;
-static constexpr dart::compiler::target::word PointerBase_data_field_offset = 8;
+static constexpr dart::compiler::target::word PointerBase_data_offset = 8;
static constexpr dart::compiler::target::word Pointer_type_arguments_offset =
16;
static constexpr dart::compiler::target::word
@@ -6708,10 +6719,11 @@
static constexpr dart::compiler::target::word TypeParameter_flags_offset = 44;
static constexpr dart::compiler::target::word TypeRef_type_offset = 24;
static constexpr dart::compiler::target::word TypedDataBase_length_offset = 16;
-static constexpr dart::compiler::target::word TypedDataView_data_offset = 24;
+static constexpr dart::compiler::target::word TypedDataView_typed_data_offset =
+ 24;
static constexpr dart::compiler::target::word
TypedDataView_offset_in_bytes_offset = 32;
-static constexpr dart::compiler::target::word TypedData_data_offset = 24;
+static constexpr dart::compiler::target::word TypedData_payload_offset = 24;
static constexpr dart::compiler::target::word
UnhandledException_exception_offset = 8;
static constexpr dart::compiler::target::word
@@ -7025,7 +7037,7 @@
static constexpr dart::compiler::target::word ObjectStore_type_type_offset =
208;
static constexpr dart::compiler::target::word OneByteString_data_offset = 16;
-static constexpr dart::compiler::target::word PointerBase_data_field_offset = 8;
+static constexpr dart::compiler::target::word PointerBase_data_offset = 8;
static constexpr dart::compiler::target::word Pointer_type_arguments_offset =
16;
static constexpr dart::compiler::target::word
@@ -7274,10 +7286,11 @@
static constexpr dart::compiler::target::word TypeParameter_flags_offset = 36;
static constexpr dart::compiler::target::word TypeRef_type_offset = 24;
static constexpr dart::compiler::target::word TypedDataBase_length_offset = 20;
-static constexpr dart::compiler::target::word TypedDataView_data_offset = 24;
+static constexpr dart::compiler::target::word TypedDataView_typed_data_offset =
+ 24;
static constexpr dart::compiler::target::word
TypedDataView_offset_in_bytes_offset = 28;
-static constexpr dart::compiler::target::word TypedData_data_offset = 24;
+static constexpr dart::compiler::target::word TypedData_payload_offset = 24;
static constexpr dart::compiler::target::word
UnhandledException_exception_offset = 8;
static constexpr dart::compiler::target::word
@@ -7590,7 +7603,7 @@
static constexpr dart::compiler::target::word ObjectStore_type_type_offset =
208;
static constexpr dart::compiler::target::word OneByteString_data_offset = 16;
-static constexpr dart::compiler::target::word PointerBase_data_field_offset = 8;
+static constexpr dart::compiler::target::word PointerBase_data_offset = 8;
static constexpr dart::compiler::target::word Pointer_type_arguments_offset =
16;
static constexpr dart::compiler::target::word
@@ -7839,10 +7852,11 @@
static constexpr dart::compiler::target::word TypeParameter_flags_offset = 36;
static constexpr dart::compiler::target::word TypeRef_type_offset = 24;
static constexpr dart::compiler::target::word TypedDataBase_length_offset = 20;
-static constexpr dart::compiler::target::word TypedDataView_data_offset = 24;
+static constexpr dart::compiler::target::word TypedDataView_typed_data_offset =
+ 24;
static constexpr dart::compiler::target::word
TypedDataView_offset_in_bytes_offset = 28;
-static constexpr dart::compiler::target::word TypedData_data_offset = 24;
+static constexpr dart::compiler::target::word TypedData_payload_offset = 24;
static constexpr dart::compiler::target::word
UnhandledException_exception_offset = 8;
static constexpr dart::compiler::target::word
@@ -8156,7 +8170,7 @@
static constexpr dart::compiler::target::word ObjectStore_type_type_offset =
104;
static constexpr dart::compiler::target::word OneByteString_data_offset = 12;
-static constexpr dart::compiler::target::word PointerBase_data_field_offset = 4;
+static constexpr dart::compiler::target::word PointerBase_data_offset = 4;
static constexpr dart::compiler::target::word Pointer_type_arguments_offset = 8;
static constexpr dart::compiler::target::word
SingleTargetCache_entry_point_offset = 8;
@@ -8399,10 +8413,11 @@
static constexpr dart::compiler::target::word TypeParameter_flags_offset = 24;
static constexpr dart::compiler::target::word TypeRef_type_offset = 12;
static constexpr dart::compiler::target::word TypedDataBase_length_offset = 8;
-static constexpr dart::compiler::target::word TypedDataView_data_offset = 12;
+static constexpr dart::compiler::target::word TypedDataView_typed_data_offset =
+ 12;
static constexpr dart::compiler::target::word
TypedDataView_offset_in_bytes_offset = 16;
-static constexpr dart::compiler::target::word TypedData_data_offset = 12;
+static constexpr dart::compiler::target::word TypedData_payload_offset = 12;
static constexpr dart::compiler::target::word
UnhandledException_exception_offset = 4;
static constexpr dart::compiler::target::word
@@ -8718,7 +8733,7 @@
static constexpr dart::compiler::target::word ObjectStore_type_type_offset =
208;
static constexpr dart::compiler::target::word OneByteString_data_offset = 16;
-static constexpr dart::compiler::target::word PointerBase_data_field_offset = 8;
+static constexpr dart::compiler::target::word PointerBase_data_offset = 8;
static constexpr dart::compiler::target::word Pointer_type_arguments_offset =
16;
static constexpr dart::compiler::target::word
@@ -8967,10 +8982,11 @@
static constexpr dart::compiler::target::word TypeParameter_flags_offset = 44;
static constexpr dart::compiler::target::word TypeRef_type_offset = 24;
static constexpr dart::compiler::target::word TypedDataBase_length_offset = 16;
-static constexpr dart::compiler::target::word TypedDataView_data_offset = 24;
+static constexpr dart::compiler::target::word TypedDataView_typed_data_offset =
+ 24;
static constexpr dart::compiler::target::word
TypedDataView_offset_in_bytes_offset = 32;
-static constexpr dart::compiler::target::word TypedData_data_offset = 24;
+static constexpr dart::compiler::target::word TypedData_payload_offset = 24;
static constexpr dart::compiler::target::word
UnhandledException_exception_offset = 8;
static constexpr dart::compiler::target::word
@@ -9318,8 +9334,7 @@
104;
static constexpr dart::compiler::target::word AOT_OneByteString_data_offset =
12;
-static constexpr dart::compiler::target::word
- AOT_PointerBase_data_field_offset = 4;
+static constexpr dart::compiler::target::word AOT_PointerBase_data_offset = 4;
static constexpr dart::compiler::target::word
AOT_Pointer_type_arguments_offset = 8;
static constexpr dart::compiler::target::word
@@ -9589,11 +9604,11 @@
static constexpr dart::compiler::target::word AOT_TypeRef_type_offset = 12;
static constexpr dart::compiler::target::word AOT_TypedDataBase_length_offset =
8;
-static constexpr dart::compiler::target::word AOT_TypedDataView_data_offset =
- 12;
+static constexpr dart::compiler::target::word
+ AOT_TypedDataView_typed_data_offset = 12;
static constexpr dart::compiler::target::word
AOT_TypedDataView_offset_in_bytes_offset = 16;
-static constexpr dart::compiler::target::word AOT_TypedData_data_offset = 12;
+static constexpr dart::compiler::target::word AOT_TypedData_payload_offset = 12;
static constexpr dart::compiler::target::word
AOT_UnhandledException_exception_offset = 4;
static constexpr dart::compiler::target::word
@@ -9950,8 +9965,7 @@
208;
static constexpr dart::compiler::target::word AOT_OneByteString_data_offset =
16;
-static constexpr dart::compiler::target::word
- AOT_PointerBase_data_field_offset = 8;
+static constexpr dart::compiler::target::word AOT_PointerBase_data_offset = 8;
static constexpr dart::compiler::target::word
AOT_Pointer_type_arguments_offset = 16;
static constexpr dart::compiler::target::word
@@ -10222,11 +10236,11 @@
static constexpr dart::compiler::target::word AOT_TypeRef_type_offset = 24;
static constexpr dart::compiler::target::word AOT_TypedDataBase_length_offset =
16;
-static constexpr dart::compiler::target::word AOT_TypedDataView_data_offset =
- 24;
+static constexpr dart::compiler::target::word
+ AOT_TypedDataView_typed_data_offset = 24;
static constexpr dart::compiler::target::word
AOT_TypedDataView_offset_in_bytes_offset = 32;
-static constexpr dart::compiler::target::word AOT_TypedData_data_offset = 24;
+static constexpr dart::compiler::target::word AOT_TypedData_payload_offset = 24;
static constexpr dart::compiler::target::word
AOT_UnhandledException_exception_offset = 8;
static constexpr dart::compiler::target::word
@@ -10588,8 +10602,7 @@
208;
static constexpr dart::compiler::target::word AOT_OneByteString_data_offset =
16;
-static constexpr dart::compiler::target::word
- AOT_PointerBase_data_field_offset = 8;
+static constexpr dart::compiler::target::word AOT_PointerBase_data_offset = 8;
static constexpr dart::compiler::target::word
AOT_Pointer_type_arguments_offset = 16;
static constexpr dart::compiler::target::word
@@ -10860,11 +10873,11 @@
static constexpr dart::compiler::target::word AOT_TypeRef_type_offset = 24;
static constexpr dart::compiler::target::word AOT_TypedDataBase_length_offset =
16;
-static constexpr dart::compiler::target::word AOT_TypedDataView_data_offset =
- 24;
+static constexpr dart::compiler::target::word
+ AOT_TypedDataView_typed_data_offset = 24;
static constexpr dart::compiler::target::word
AOT_TypedDataView_offset_in_bytes_offset = 32;
-static constexpr dart::compiler::target::word AOT_TypedData_data_offset = 24;
+static constexpr dart::compiler::target::word AOT_TypedData_payload_offset = 24;
static constexpr dart::compiler::target::word
AOT_UnhandledException_exception_offset = 8;
static constexpr dart::compiler::target::word
@@ -11223,8 +11236,7 @@
208;
static constexpr dart::compiler::target::word AOT_OneByteString_data_offset =
16;
-static constexpr dart::compiler::target::word
- AOT_PointerBase_data_field_offset = 8;
+static constexpr dart::compiler::target::word AOT_PointerBase_data_offset = 8;
static constexpr dart::compiler::target::word
AOT_Pointer_type_arguments_offset = 16;
static constexpr dart::compiler::target::word
@@ -11495,11 +11507,11 @@
static constexpr dart::compiler::target::word AOT_TypeRef_type_offset = 24;
static constexpr dart::compiler::target::word AOT_TypedDataBase_length_offset =
20;
-static constexpr dart::compiler::target::word AOT_TypedDataView_data_offset =
- 24;
+static constexpr dart::compiler::target::word
+ AOT_TypedDataView_typed_data_offset = 24;
static constexpr dart::compiler::target::word
AOT_TypedDataView_offset_in_bytes_offset = 28;
-static constexpr dart::compiler::target::word AOT_TypedData_data_offset = 24;
+static constexpr dart::compiler::target::word AOT_TypedData_payload_offset = 24;
static constexpr dart::compiler::target::word
AOT_UnhandledException_exception_offset = 8;
static constexpr dart::compiler::target::word
@@ -11857,8 +11869,7 @@
208;
static constexpr dart::compiler::target::word AOT_OneByteString_data_offset =
16;
-static constexpr dart::compiler::target::word
- AOT_PointerBase_data_field_offset = 8;
+static constexpr dart::compiler::target::word AOT_PointerBase_data_offset = 8;
static constexpr dart::compiler::target::word
AOT_Pointer_type_arguments_offset = 16;
static constexpr dart::compiler::target::word
@@ -12129,11 +12140,11 @@
static constexpr dart::compiler::target::word AOT_TypeRef_type_offset = 24;
static constexpr dart::compiler::target::word AOT_TypedDataBase_length_offset =
20;
-static constexpr dart::compiler::target::word AOT_TypedDataView_data_offset =
- 24;
+static constexpr dart::compiler::target::word
+ AOT_TypedDataView_typed_data_offset = 24;
static constexpr dart::compiler::target::word
AOT_TypedDataView_offset_in_bytes_offset = 28;
-static constexpr dart::compiler::target::word AOT_TypedData_data_offset = 24;
+static constexpr dart::compiler::target::word AOT_TypedData_payload_offset = 24;
static constexpr dart::compiler::target::word
AOT_UnhandledException_exception_offset = 8;
static constexpr dart::compiler::target::word
@@ -12492,8 +12503,7 @@
104;
static constexpr dart::compiler::target::word AOT_OneByteString_data_offset =
12;
-static constexpr dart::compiler::target::word
- AOT_PointerBase_data_field_offset = 4;
+static constexpr dart::compiler::target::word AOT_PointerBase_data_offset = 4;
static constexpr dart::compiler::target::word
AOT_Pointer_type_arguments_offset = 8;
static constexpr dart::compiler::target::word
@@ -12763,11 +12773,11 @@
static constexpr dart::compiler::target::word AOT_TypeRef_type_offset = 12;
static constexpr dart::compiler::target::word AOT_TypedDataBase_length_offset =
8;
-static constexpr dart::compiler::target::word AOT_TypedDataView_data_offset =
- 12;
+static constexpr dart::compiler::target::word
+ AOT_TypedDataView_typed_data_offset = 12;
static constexpr dart::compiler::target::word
AOT_TypedDataView_offset_in_bytes_offset = 16;
-static constexpr dart::compiler::target::word AOT_TypedData_data_offset = 12;
+static constexpr dart::compiler::target::word AOT_TypedData_payload_offset = 12;
static constexpr dart::compiler::target::word
AOT_UnhandledException_exception_offset = 4;
static constexpr dart::compiler::target::word
@@ -13126,8 +13136,7 @@
208;
static constexpr dart::compiler::target::word AOT_OneByteString_data_offset =
16;
-static constexpr dart::compiler::target::word
- AOT_PointerBase_data_field_offset = 8;
+static constexpr dart::compiler::target::word AOT_PointerBase_data_offset = 8;
static constexpr dart::compiler::target::word
AOT_Pointer_type_arguments_offset = 16;
static constexpr dart::compiler::target::word
@@ -13398,11 +13407,11 @@
static constexpr dart::compiler::target::word AOT_TypeRef_type_offset = 24;
static constexpr dart::compiler::target::word AOT_TypedDataBase_length_offset =
16;
-static constexpr dart::compiler::target::word AOT_TypedDataView_data_offset =
- 24;
+static constexpr dart::compiler::target::word
+ AOT_TypedDataView_typed_data_offset = 24;
static constexpr dart::compiler::target::word
AOT_TypedDataView_offset_in_bytes_offset = 32;
-static constexpr dart::compiler::target::word AOT_TypedData_data_offset = 24;
+static constexpr dart::compiler::target::word AOT_TypedData_payload_offset = 24;
static constexpr dart::compiler::target::word
AOT_UnhandledException_exception_offset = 8;
static constexpr dart::compiler::target::word
@@ -13756,8 +13765,7 @@
104;
static constexpr dart::compiler::target::word AOT_OneByteString_data_offset =
12;
-static constexpr dart::compiler::target::word
- AOT_PointerBase_data_field_offset = 4;
+static constexpr dart::compiler::target::word AOT_PointerBase_data_offset = 4;
static constexpr dart::compiler::target::word
AOT_Pointer_type_arguments_offset = 8;
static constexpr dart::compiler::target::word
@@ -14027,11 +14035,11 @@
static constexpr dart::compiler::target::word AOT_TypeRef_type_offset = 12;
static constexpr dart::compiler::target::word AOT_TypedDataBase_length_offset =
8;
-static constexpr dart::compiler::target::word AOT_TypedDataView_data_offset =
- 12;
+static constexpr dart::compiler::target::word
+ AOT_TypedDataView_typed_data_offset = 12;
static constexpr dart::compiler::target::word
AOT_TypedDataView_offset_in_bytes_offset = 16;
-static constexpr dart::compiler::target::word AOT_TypedData_data_offset = 12;
+static constexpr dart::compiler::target::word AOT_TypedData_payload_offset = 12;
static constexpr dart::compiler::target::word
AOT_UnhandledException_exception_offset = 4;
static constexpr dart::compiler::target::word
@@ -14381,8 +14389,7 @@
208;
static constexpr dart::compiler::target::word AOT_OneByteString_data_offset =
16;
-static constexpr dart::compiler::target::word
- AOT_PointerBase_data_field_offset = 8;
+static constexpr dart::compiler::target::word AOT_PointerBase_data_offset = 8;
static constexpr dart::compiler::target::word
AOT_Pointer_type_arguments_offset = 16;
static constexpr dart::compiler::target::word
@@ -14653,11 +14660,11 @@
static constexpr dart::compiler::target::word AOT_TypeRef_type_offset = 24;
static constexpr dart::compiler::target::word AOT_TypedDataBase_length_offset =
16;
-static constexpr dart::compiler::target::word AOT_TypedDataView_data_offset =
- 24;
+static constexpr dart::compiler::target::word
+ AOT_TypedDataView_typed_data_offset = 24;
static constexpr dart::compiler::target::word
AOT_TypedDataView_offset_in_bytes_offset = 32;
-static constexpr dart::compiler::target::word AOT_TypedData_data_offset = 24;
+static constexpr dart::compiler::target::word AOT_TypedData_payload_offset = 24;
static constexpr dart::compiler::target::word
AOT_UnhandledException_exception_offset = 8;
static constexpr dart::compiler::target::word
@@ -15012,8 +15019,7 @@
208;
static constexpr dart::compiler::target::word AOT_OneByteString_data_offset =
16;
-static constexpr dart::compiler::target::word
- AOT_PointerBase_data_field_offset = 8;
+static constexpr dart::compiler::target::word AOT_PointerBase_data_offset = 8;
static constexpr dart::compiler::target::word
AOT_Pointer_type_arguments_offset = 16;
static constexpr dart::compiler::target::word
@@ -15284,11 +15290,11 @@
static constexpr dart::compiler::target::word AOT_TypeRef_type_offset = 24;
static constexpr dart::compiler::target::word AOT_TypedDataBase_length_offset =
16;
-static constexpr dart::compiler::target::word AOT_TypedDataView_data_offset =
- 24;
+static constexpr dart::compiler::target::word
+ AOT_TypedDataView_typed_data_offset = 24;
static constexpr dart::compiler::target::word
AOT_TypedDataView_offset_in_bytes_offset = 32;
-static constexpr dart::compiler::target::word AOT_TypedData_data_offset = 24;
+static constexpr dart::compiler::target::word AOT_TypedData_payload_offset = 24;
static constexpr dart::compiler::target::word
AOT_UnhandledException_exception_offset = 8;
static constexpr dart::compiler::target::word
@@ -15640,8 +15646,7 @@
208;
static constexpr dart::compiler::target::word AOT_OneByteString_data_offset =
16;
-static constexpr dart::compiler::target::word
- AOT_PointerBase_data_field_offset = 8;
+static constexpr dart::compiler::target::word AOT_PointerBase_data_offset = 8;
static constexpr dart::compiler::target::word
AOT_Pointer_type_arguments_offset = 16;
static constexpr dart::compiler::target::word
@@ -15912,11 +15917,11 @@
static constexpr dart::compiler::target::word AOT_TypeRef_type_offset = 24;
static constexpr dart::compiler::target::word AOT_TypedDataBase_length_offset =
20;
-static constexpr dart::compiler::target::word AOT_TypedDataView_data_offset =
- 24;
+static constexpr dart::compiler::target::word
+ AOT_TypedDataView_typed_data_offset = 24;
static constexpr dart::compiler::target::word
AOT_TypedDataView_offset_in_bytes_offset = 28;
-static constexpr dart::compiler::target::word AOT_TypedData_data_offset = 24;
+static constexpr dart::compiler::target::word AOT_TypedData_payload_offset = 24;
static constexpr dart::compiler::target::word
AOT_UnhandledException_exception_offset = 8;
static constexpr dart::compiler::target::word
@@ -16267,8 +16272,7 @@
208;
static constexpr dart::compiler::target::word AOT_OneByteString_data_offset =
16;
-static constexpr dart::compiler::target::word
- AOT_PointerBase_data_field_offset = 8;
+static constexpr dart::compiler::target::word AOT_PointerBase_data_offset = 8;
static constexpr dart::compiler::target::word
AOT_Pointer_type_arguments_offset = 16;
static constexpr dart::compiler::target::word
@@ -16539,11 +16543,11 @@
static constexpr dart::compiler::target::word AOT_TypeRef_type_offset = 24;
static constexpr dart::compiler::target::word AOT_TypedDataBase_length_offset =
20;
-static constexpr dart::compiler::target::word AOT_TypedDataView_data_offset =
- 24;
+static constexpr dart::compiler::target::word
+ AOT_TypedDataView_typed_data_offset = 24;
static constexpr dart::compiler::target::word
AOT_TypedDataView_offset_in_bytes_offset = 28;
-static constexpr dart::compiler::target::word AOT_TypedData_data_offset = 24;
+static constexpr dart::compiler::target::word AOT_TypedData_payload_offset = 24;
static constexpr dart::compiler::target::word
AOT_UnhandledException_exception_offset = 8;
static constexpr dart::compiler::target::word
@@ -16895,8 +16899,7 @@
104;
static constexpr dart::compiler::target::word AOT_OneByteString_data_offset =
12;
-static constexpr dart::compiler::target::word
- AOT_PointerBase_data_field_offset = 4;
+static constexpr dart::compiler::target::word AOT_PointerBase_data_offset = 4;
static constexpr dart::compiler::target::word
AOT_Pointer_type_arguments_offset = 8;
static constexpr dart::compiler::target::word
@@ -17166,11 +17169,11 @@
static constexpr dart::compiler::target::word AOT_TypeRef_type_offset = 12;
static constexpr dart::compiler::target::word AOT_TypedDataBase_length_offset =
8;
-static constexpr dart::compiler::target::word AOT_TypedDataView_data_offset =
- 12;
+static constexpr dart::compiler::target::word
+ AOT_TypedDataView_typed_data_offset = 12;
static constexpr dart::compiler::target::word
AOT_TypedDataView_offset_in_bytes_offset = 16;
-static constexpr dart::compiler::target::word AOT_TypedData_data_offset = 12;
+static constexpr dart::compiler::target::word AOT_TypedData_payload_offset = 12;
static constexpr dart::compiler::target::word
AOT_UnhandledException_exception_offset = 4;
static constexpr dart::compiler::target::word
@@ -17522,8 +17525,7 @@
208;
static constexpr dart::compiler::target::word AOT_OneByteString_data_offset =
16;
-static constexpr dart::compiler::target::word
- AOT_PointerBase_data_field_offset = 8;
+static constexpr dart::compiler::target::word AOT_PointerBase_data_offset = 8;
static constexpr dart::compiler::target::word
AOT_Pointer_type_arguments_offset = 16;
static constexpr dart::compiler::target::word
@@ -17794,11 +17796,11 @@
static constexpr dart::compiler::target::word AOT_TypeRef_type_offset = 24;
static constexpr dart::compiler::target::word AOT_TypedDataBase_length_offset =
16;
-static constexpr dart::compiler::target::word AOT_TypedDataView_data_offset =
- 24;
+static constexpr dart::compiler::target::word
+ AOT_TypedDataView_typed_data_offset = 24;
static constexpr dart::compiler::target::word
AOT_TypedDataView_offset_in_bytes_offset = 32;
-static constexpr dart::compiler::target::word AOT_TypedData_data_offset = 24;
+static constexpr dart::compiler::target::word AOT_TypedData_payload_offset = 24;
static constexpr dart::compiler::target::word
AOT_UnhandledException_exception_offset = 8;
static constexpr dart::compiler::target::word
diff --git a/runtime/vm/compiler/runtime_offsets_list.h b/runtime/vm/compiler/runtime_offsets_list.h
index bff550b..0d36d9b 100644
--- a/runtime/vm/compiler/runtime_offsets_list.h
+++ b/runtime/vm/compiler/runtime_offsets_list.h
@@ -177,7 +177,7 @@
FIELD(ObjectStore, string_type_offset) \
FIELD(ObjectStore, type_type_offset) \
FIELD(OneByteString, data_offset) \
- FIELD(PointerBase, data_field_offset) \
+ FIELD(PointerBase, data_offset) \
FIELD(Pointer, type_arguments_offset) \
FIELD(SingleTargetCache, entry_point_offset) \
FIELD(SingleTargetCache, lower_limit_offset) \
@@ -322,9 +322,9 @@
FIELD(TypeParameter, flags_offset) \
FIELD(TypeRef, type_offset) \
FIELD(TypedDataBase, length_offset) \
- FIELD(TypedDataView, data_offset) \
+ FIELD(TypedDataView, typed_data_offset) \
FIELD(TypedDataView, offset_in_bytes_offset) \
- FIELD(TypedData, data_offset) \
+ FIELD(TypedData, payload_offset) \
FIELD(UnhandledException, exception_offset) \
FIELD(UnhandledException, stacktrace_offset) \
FIELD(UserTag, tag_offset) \
diff --git a/runtime/vm/compiler/stub_code_compiler_arm.cc b/runtime/vm/compiler/stub_code_compiler_arm.cc
index 602dfb2..5174ca8 100644
--- a/runtime/vm/compiler/stub_code_compiler_arm.cc
+++ b/runtime/vm/compiler/stub_code_compiler_arm.cc
@@ -3515,7 +3515,7 @@
__ mov(R9, Operand(R8));
__ AddImmediate(R3, R0, target::TypedData::HeaderSize() - 1);
__ StoreInternalPointer(
- R0, FieldAddress(R0, target::TypedDataBase::data_field_offset()), R3);
+ R0, FieldAddress(R0, target::PointerBase::data_offset()), R3);
Label init_loop;
__ Bind(&init_loop);
__ AddImmediate(R3, 2 * target::kWordSize);
diff --git a/runtime/vm/compiler/stub_code_compiler_arm64.cc b/runtime/vm/compiler/stub_code_compiler_arm64.cc
index 4d22204..e5fe61f 100644
--- a/runtime/vm/compiler/stub_code_compiler_arm64.cc
+++ b/runtime/vm/compiler/stub_code_compiler_arm64.cc
@@ -3726,7 +3726,7 @@
/* data area to be initialized. */
__ AddImmediate(R2, R0, target::TypedData::HeaderSize() - 1);
__ StoreInternalPointer(
- R0, FieldAddress(R0, target::TypedDataBase::data_field_offset()), R2);
+ R0, FieldAddress(R0, target::PointerBase::data_offset()), R2);
Label init_loop, done;
__ Bind(&init_loop);
__ cmp(R2, Operand(R1));
diff --git a/runtime/vm/compiler/stub_code_compiler_ia32.cc b/runtime/vm/compiler/stub_code_compiler_ia32.cc
index e75588c..68b3b4c 100644
--- a/runtime/vm/compiler/stub_code_compiler_ia32.cc
+++ b/runtime/vm/compiler/stub_code_compiler_ia32.cc
@@ -3059,8 +3059,7 @@
__ xorl(ECX, ECX); /* Zero. */
__ leal(EDI, FieldAddress(EAX, target::TypedData::HeaderSize()));
__ StoreInternalPointer(
- EAX, FieldAddress(EAX, target::TypedDataBase::data_field_offset()),
- EDI);
+ EAX, FieldAddress(EAX, target::PointerBase::data_offset()), EDI);
Label done, init_loop;
__ Bind(&init_loop);
__ cmpl(EDI, EBX);
diff --git a/runtime/vm/compiler/stub_code_compiler_riscv.cc b/runtime/vm/compiler/stub_code_compiler_riscv.cc
index ec19d60..c9f604b 100644
--- a/runtime/vm/compiler/stub_code_compiler_riscv.cc
+++ b/runtime/vm/compiler/stub_code_compiler_riscv.cc
@@ -3619,7 +3619,7 @@
/* data area to be initialized. */
__ AddImmediate(T3, A0, target::TypedData::HeaderSize() - 1);
__ StoreInternalPointer(
- A0, FieldAddress(A0, target::TypedDataBase::data_field_offset()), T3);
+ A0, FieldAddress(A0, target::PointerBase::data_offset()), T3);
Label init_loop, done;
__ Bind(&init_loop);
__ bgeu(T3, T4, &done);
diff --git a/runtime/vm/compiler/stub_code_compiler_x64.cc b/runtime/vm/compiler/stub_code_compiler_x64.cc
index fb870b5..5e3ba12 100644
--- a/runtime/vm/compiler/stub_code_compiler_x64.cc
+++ b/runtime/vm/compiler/stub_code_compiler_x64.cc
@@ -3782,8 +3782,7 @@
__ xorq(RBX, RBX); /* Zero. */
__ leaq(RDI, FieldAddress(RAX, target::TypedData::HeaderSize()));
__ StoreInternalPointer(
- RAX, FieldAddress(RAX, target::TypedDataBase::data_field_offset()),
- RDI);
+ RAX, FieldAddress(RAX, target::PointerBase::data_offset()), RDI);
Label done, init_loop;
__ Bind(&init_loop);
__ cmpq(RDI, RCX);
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index d3cb9c6..0a98a83 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -19685,7 +19685,7 @@
return 0;
}
if (IsTypedDataClassId(cid)) {
- return TypedData::data_offset();
+ return TypedData::payload_offset();
}
switch (cid) {
case kArrayCid:
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index b830f12..6b5cb1b 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -10686,7 +10686,7 @@
class PointerBase : public Instance {
public:
- static intptr_t data_field_offset() {
+ static intptr_t data_offset() {
return OFFSET_OF(UntaggedPointerBase, data_);
}
};
@@ -10830,7 +10830,9 @@
#undef TYPED_GETTER_SETTER
- static intptr_t data_offset() { return UntaggedTypedData::payload_offset(); }
+ static intptr_t payload_offset() {
+ return UntaggedTypedData::payload_offset();
+ }
static intptr_t InstanceSize() {
ASSERT(sizeof(UntaggedTypedData) ==
@@ -10940,10 +10942,6 @@
Dart_HandleFinalizer callback,
intptr_t external_size) const;
- static intptr_t data_offset() {
- return OFFSET_OF(UntaggedExternalTypedData, data_);
- }
-
static intptr_t InstanceSize() {
return RoundedAllocationSize(sizeof(UntaggedExternalTypedData));
}
@@ -11016,7 +11014,7 @@
return IsExternalTypedDataClassId(cid);
}
- static intptr_t data_offset() {
+ static intptr_t typed_data_offset() {
return OFFSET_OF(UntaggedTypedDataView, typed_data_);
}
diff --git a/sdk/lib/html/dart2js/html_dart2js.dart b/sdk/lib/html/dart2js/html_dart2js.dart
index 33e2611..0c9b5d0 100644
--- a/sdk/lib/html/dart2js/html_dart2js.dart
+++ b/sdk/lib/html/dart2js/html_dart2js.dart
@@ -13389,10 +13389,14 @@
} else if (alignment == ScrollAlignment.BOTTOM) {
this._scrollIntoView(false);
} else if (hasScrollIntoViewIfNeeded) {
+ // TODO(srujzs): This method shouldn't be calling out to
+ // `scrollIntoViewIfNeeded`. Remove this and make `scrollIntoView` match
+ // the browser definition. If you intend to use `scrollIntoViewIfNeeded`,
+ // use the `Element.scrollIntoViewIfNeeded` method.
if (alignment == ScrollAlignment.CENTER) {
- this._scrollIntoViewIfNeeded(true);
+ this.scrollIntoViewIfNeeded(true);
} else {
- this._scrollIntoViewIfNeeded();
+ this.scrollIntoViewIfNeeded();
}
} else {
this._scrollIntoView();
@@ -14896,8 +14900,18 @@
@JSName('scrollIntoView')
void _scrollIntoView([Object? arg]) native;
- @JSName('scrollIntoViewIfNeeded')
- void _scrollIntoViewIfNeeded([bool? centerIfNeeded]) native;
+ /**
+ * Nonstandard version of `scrollIntoView` that scrolls the current element
+ * into the visible area of the browser window if it's not already within the
+ * visible area of the browser window. If the element is already within the
+ * visible area of the browser window, then no scrolling takes place.
+ *
+ * ## Other resources
+ *
+ * * [Element.scrollIntoViewIfNeeded](https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoViewIfNeeded)
+ * from MDN.
+ */
+ void scrollIntoViewIfNeeded([bool? centerIfNeeded]) native;
void scrollTo([options_OR_x, num? y]) {
if (options_OR_x == null && y == null) {
diff --git a/tools/VERSION b/tools/VERSION
index afae815..551b152 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 17
PATCH 0
-PRERELEASE 79
+PRERELEASE 80
PRERELEASE_PATCH 0
\ No newline at end of file
diff --git a/tools/dom/docs.json b/tools/dom/docs.json
index e1a453b..2dfd29c 100644
--- a/tools/dom/docs.json
+++ b/tools/dom/docs.json
@@ -1270,6 +1270,19 @@
" * See [EventStreamProvider] for usage information.",
" */"
],
+ "scrollIntoViewIfNeeded": [
+ "/**",
+ " * Nonstandard version of `scrollIntoView` that scrolls the current element",
+ " * into the visible area of the browser window if it's not already within the",
+ " * visible area of the browser window. If the element is already within the",
+ " * visible area of the browser window, then no scrolling takes place.",
+ " *",
+ " * ## Other resources",
+ " *",
+ " * * [Element.scrollIntoViewIfNeeded](https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoViewIfNeeded)",
+ " * from MDN.",
+ " */"
+ ],
"searchEvent": [
"/**",
" * Static factory designed to expose `search` events to event",
diff --git a/tools/dom/scripts/htmlrenamer.py b/tools/dom/scripts/htmlrenamer.py
index 30fa1af..13f18fb 100644
--- a/tools/dom/scripts/htmlrenamer.py
+++ b/tools/dom/scripts/htmlrenamer.py
@@ -403,7 +403,6 @@
'Element.getElementsByTagName',
'Element.insertAdjacentHTML',
'Element.scrollIntoView',
- 'Element.scrollIntoViewIfNeeded',
'Element.getAttribute',
'Element.getAttributeNS',
'Element.hasAttribute',
diff --git a/tools/dom/templates/html/impl/impl_Element.darttemplate b/tools/dom/templates/html/impl/impl_Element.darttemplate
index a0ce567..3ff4bcc 100644
--- a/tools/dom/templates/html/impl/impl_Element.darttemplate
+++ b/tools/dom/templates/html/impl/impl_Element.darttemplate
@@ -1007,10 +1007,14 @@
} else if (alignment == ScrollAlignment.BOTTOM) {
this._scrollIntoView(false);
} else if (hasScrollIntoViewIfNeeded) {
+ // TODO(srujzs): This method shouldn't be calling out to
+ // `scrollIntoViewIfNeeded`. Remove this and make `scrollIntoView` match
+ // the browser definition. If you intend to use `scrollIntoViewIfNeeded`,
+ // use the `Element.scrollIntoViewIfNeeded` method.
if (alignment == ScrollAlignment.CENTER) {
- this._scrollIntoViewIfNeeded(true);
+ this.scrollIntoViewIfNeeded(true);
} else {
- this._scrollIntoViewIfNeeded();
+ this.scrollIntoViewIfNeeded();
}
} else {
this._scrollIntoView();