Skip to content

Commit

Permalink
Version 3.2.0-141.0.dev
Browse files Browse the repository at this point in the history
Merge 27d321e into dev
  • Loading branch information
Dart CI committed Sep 7, 2023
2 parents 1ee7ef8 + 27d321e commit 913f9ff
Show file tree
Hide file tree
Showing 17 changed files with 835 additions and 147 deletions.
40 changes: 16 additions & 24 deletions pkg/analyzer/lib/src/dart/scanner/scanner.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
// 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:typed_data';

import 'package:_fe_analyzer_shared/src/scanner/errors.dart'
show translateErrorToken;
import 'package:_fe_analyzer_shared/src/scanner/scanner.dart' as fasta;
Expand All @@ -28,6 +30,8 @@ export 'package:analyzer/src/dart/error/syntactic_errors.dart';
/// have any context, so it always resolves such conflicts by scanning the
/// longest possible token.
class Scanner {
static final Uint8List _lineStartsZero = Uint8List(0);

final Source source;

/// The text to be scanned.
Expand All @@ -47,9 +51,7 @@ class Scanner {

/// The flag specifying whether documentation comments should be parsed.
bool _preserveComments = true;

final List<int> lineStarts = <int>[];

List<int>? _lineStarts;
late final Token firstToken;

Version? _overrideVersion;
Expand All @@ -72,9 +74,7 @@ class Scanner {
}

Scanner._(
this.source, this._contents, this._readerOffset, this._errorListener) {
lineStarts.add(0);
}
this.source, this._contents, this._readerOffset, this._errorListener);

/// The features associated with this scanner.
///
Expand All @@ -86,6 +86,8 @@ class Scanner {
/// Use [configureFeatures] to set the features.
FeatureSet get featureSet => _featureSet;

List<int> get lineStarts => _lineStarts ?? _lineStartsZero;

/// The language version override specified for this compilation unit using a
/// token like '// @dart = 2.7', or `null` if no override is specified.
Version? get overrideVersion => _overrideVersion;
Expand Down Expand Up @@ -116,18 +118,6 @@ class Scanner {
);
}

void setSourceStart(int line, int column) {
int offset = _readerOffset;
if (line < 1 || column < 1 || offset < 0 || (line + column - 2) >= offset) {
return;
}
lineStarts.removeAt(0);
for (int i = 2; i < line; i++) {
lineStarts.add(1);
}
lineStarts.add(offset - column + 1);
}

/// The fasta parser handles error tokens produced by the scanner
/// but the old parser used by angular does not
/// and expects that scanner errors to be reported by this method.
Expand All @@ -138,13 +128,15 @@ class Scanner {
includeComments: _preserveComments,
languageVersionChanged: _languageVersionChanged);

// fasta pretends there is an additional line at EOF
result.lineStarts.removeLast();

// for compatibility, there is already a first entry in lineStarts
result.lineStarts.removeAt(0);
// fasta pretends there is an additional line at EOF so we skip the last one.
if (result.lineStarts.last > 65535) {
Uint32List list = _lineStarts = Uint32List(result.lineStarts.length - 1);
list.setRange(0, result.lineStarts.length - 1, result.lineStarts);
} else {
Uint16List list = _lineStarts = Uint16List(result.lineStarts.length - 1);
list.setRange(0, result.lineStarts.length - 1, result.lineStarts);
}

lineStarts.addAll(result.lineStarts);
fasta.Token token = result.tokens;

// The fasta parser handles error tokens produced by the scanner
Expand Down
10 changes: 9 additions & 1 deletion pkg/analyzer/lib/src/services/available_declarations.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import 'dart:async';
import 'dart:collection';
import 'dart:typed_data';

import 'package:_fe_analyzer_shared/src/util/dependency_walker.dart' as graph
show DependencyWalker, Node;
Expand Down Expand Up @@ -1923,7 +1924,14 @@ class _File {
void _readFileDeclarationsFromBytes(List<int> bytes) {
var idlFile = idl.AvailableFile.fromBuffer(bytes);

lineStarts = idlFile.lineStarts.toList();
lineStarts = idlFile.lineStarts;
if (lineStarts.last > 65535) {
Uint32List list = lineStarts = Uint32List(lineStarts.length);
list.setRange(0, lineStarts.length, lineStarts);
} else {
Uint16List list = lineStarts = Uint16List(lineStarts.length);
list.setRange(0, lineStarts.length, lineStarts);
}
lineInfo = LineInfo(lineStarts);

isLibrary = idlFile.isLibrary;
Expand Down
19 changes: 18 additions & 1 deletion pkg/analyzer/lib/src/summary2/informative_data.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1858,7 +1858,8 @@ class _InfoUnit {
return _InfoUnit._(
codeOffset: reader.readUInt30(),
codeLength: reader.readUInt30(),
lineStarts: reader.readUInt30List(),
// Having duplicated line-starts adds up --- deduplicate if possible.
lineStarts: _readUint30ListPossiblyFromCache(cache, reader),
libraryName: _InfoLibraryName(reader),
libraryConstantOffsets: reader.readUInt30List(),
docComment: reader.readStringUtf8(),
Expand Down Expand Up @@ -1929,6 +1930,22 @@ class _InfoUnit {
required this.mixinDeclarations,
required this.topLevelVariable,
});

static Uint32List _readUint30ListPossiblyFromCache(
InfoDeclarationStore cache, SummaryDataReader reader) {
final initialOffset = reader.offset;
final cacheKey = cache.createKey(reader, initialOffset);
final cachedLineStarts =
cache.get<Uint32List>(reader, cacheKey, initialOffset);
if (cachedLineStarts != null) {
return cachedLineStarts;
} else {
// Add to cache.
var lineStarts = reader.readUInt30List();
cache.put(reader, cacheKey, initialOffset, lineStarts);
return lineStarts;
}
}
}

class _OffsetsApplier extends _OffsetsAstVisitor {
Expand Down
2 changes: 1 addition & 1 deletion pkg/dart2wasm/lib/async.dart
Original file line number Diff line number Diff line change
Expand Up @@ -536,7 +536,7 @@ class AsyncCodeGenerator extends CodeGenerator {
@override
void generate() {
closures = Closures(translator, member);
setupParametersAndContexts(member);
setupParametersAndContexts(member.reference);
generateTypeChecks(member.function!.typeParameters, member.function!,
translator.paramInfoFor(reference));
_generateBodies(member.function!);
Expand Down
22 changes: 14 additions & 8 deletions pkg/dart2wasm/lib/class_info.dart
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ class FieldIndex {
static const classId = 0;
static const boxValue = 1;
static const identityHash = 1;
static const objectFieldBase = 2;
static const stringArray = 2;
static const listLength = 3;
static const listArray = 4;
Expand Down Expand Up @@ -174,6 +175,13 @@ class ClassInfo {
assert(expectedIndex == null || expectedIndex == struct.fields.length);
struct.fields.add(fieldType);
}

// This returns the types of all the class's fields (including
// superclass fields), except for the class id and the identity hash
List<w.ValueType> getClassFieldTypes() => [
for (var fieldType in struct.fields.skip(FieldIndex.objectFieldBase))
fieldType.type.unpacked
];
}

ClassInfo upperBound(Set<ClassInfo> classes) {
Expand Down Expand Up @@ -291,8 +299,9 @@ class ClassInfoCollector {
/// This field is initialized when a class with a type parameter is first
/// encountered. Initialization depends on [Translator] visiting the [_Type]
/// class first and creating a [ClassInfo] for it.
late final w.FieldType typeType =
w.FieldType(translator.classInfo[translator.typeClass]!.nullableType);
late final w.FieldType typeType = w.FieldType(
translator.classInfo[translator.typeClass]!.nonNullableType,
mutable: false);

ClassInfoCollector(this.translator);

Expand Down Expand Up @@ -436,7 +445,8 @@ class ClassInfoCollector {
ClassInfo? superInfo = info.superInfo;
if (superInfo == null) {
// Top - add class id field
info._addField(w.FieldType(w.NumType.i32), FieldIndex.classId);
info._addField(
w.FieldType(w.NumType.i32, mutable: false), FieldIndex.classId);
} else if (info.struct != superInfo.struct) {
// Copy fields from superclass
for (w.FieldType fieldType in superInfo.struct.fields) {
Expand All @@ -462,12 +472,8 @@ class ClassInfoCollector {
for (Field field in info.cls!.fields) {
if (field.isInstanceMember) {
w.ValueType wasmType = translator.translateType(field.type);
// TODO(askesc): Generalize this check for finer nullability control
if (wasmType != w.RefType.struct(nullable: false)) {
wasmType = wasmType.withNullability(true);
}
translator.fieldIndex[field] = info.struct.fields.length;
info._addField(w.FieldType(wasmType));
info._addField(w.FieldType(wasmType, mutable: !field.isFinal));
}
}
} else {
Expand Down
62 changes: 52 additions & 10 deletions pkg/dart2wasm/lib/closures.dart
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ class ClosureLayouter extends RecursiveVisitor {
// - A `_FunctionType`
return m.types.defineStruct(name,
fields: [
w.FieldType(w.NumType.i32),
w.FieldType(w.NumType.i32, mutable: false),
w.FieldType(w.NumType.i32),
w.FieldType(w.RefType.struct(nullable: false)),
w.FieldType(w.RefType.def(vtableStruct, nullable: false),
Expand Down Expand Up @@ -980,9 +980,13 @@ class Context {

int get thisFieldIndex {
assert(containsThis);
return 0;

return parent != null ? 1 : 0;
}

// Set if the context is within a constructor (either in an initializer list,
// or within a constructor body function)
bool inConstructor = false;
Context(this.owner, this.parent);
}

Expand Down Expand Up @@ -1055,7 +1059,6 @@ class Closures {
if (!context.isEmpty) {
w.StructType struct = context.struct;
if (context.parent != null) {
assert(!context.containsThis);
assert(!context.parent!.isEmpty);
struct.fields.add(w.FieldType(
w.RefType.def(context.parent!.struct, nullable: true)));
Expand Down Expand Up @@ -1191,7 +1194,9 @@ class CaptureFinder extends RecursiveVisitor {

@override
void visitTypeParameterType(TypeParameterType node) {
if (node.parameter.parent != null &&
if (member is Constructor) {
_visitVariableUse(node.parameter);
} else if (node.parameter.parent != null &&
node.parameter.parent == member.enclosingClass) {
_visitThis();
} else if (node.parameter.parent is FunctionNode) {
Expand Down Expand Up @@ -1255,27 +1260,64 @@ class ContextCollector extends RecursiveVisitor {
}
}

void _newContext(TreeNode node) {
void _newContext(TreeNode node, {bool constructorBody = false}) {
bool outerMost = currentContext == null;
Context? oldContext = currentContext;
Context? parent = currentContext;

while (parent != null && parent.isEmpty) {
parent = parent.parent;
}

currentContext = Context(node, parent);
if (closures.isThisCaptured && outerMost) {

if (parent != null) {
currentContext!.inConstructor = constructorBody || parent.inConstructor;
}

if (closures.isThisCaptured && (outerMost || constructorBody)) {
currentContext!.containsThis = true;
}

closures.contexts[node] = currentContext!;
node.visitChildren(this);
currentContext = oldContext;

if (!constructorBody) {
node.visitChildren(this);
currentContext = oldContext;
}
}

@override
void visitConstructor(Constructor node) {
node.function.accept(this);
currentContext = closures.contexts[node.function]!;
assert(currentContext == null);

currentContext = Context(node, null);
currentContext!.inConstructor = true;

closures.contexts[node] = currentContext!;

visitList(node.enclosingClass.typeParameters, this);

// visit the constructor arguments now so that captures are added to the
// constructor context not the constructor body context.
FunctionNode functionNode = node.function;
visitList(functionNode.typeParameters, this);
visitList(functionNode.positionalParameters, this);
visitList(functionNode.namedParameters, this);
visitList(node.initializers, this);

_newContext(functionNode, constructorBody: true);

functionNode.returnType.accept(this);
functionNode.futureValueType?.accept(this);
functionNode.redirectingFactoryTarget?.target?.acceptReference(this);

if (functionNode.redirectingFactoryTarget?.typeArguments != null) {
visitList(functionNode.redirectingFactoryTarget!.typeArguments!, this);
}

functionNode.body?.accept(this);
currentContext = null;
}

@override
Expand Down
Loading

0 comments on commit 913f9ff

Please sign in to comment.