Version 1.13.0-dev.1.0
Merge commit '07d68c5c3acc4a148de07a801b346eff3b673244' into dev
diff --git a/DEPS b/DEPS
index 8b2d8d8..a111db0 100644
--- a/DEPS
+++ b/DEPS
@@ -108,7 +108,7 @@
"utf_rev": "@1f55027068759e2d52f2c12de6a57cce5f3c5ee6",
"unittest_tag": "@0.11.6",
"usage_rev": "@b5080dac0d26a5609b266f8fdb0d053bc4c1c638",
- "watcher_tag": "@0.9.6",
+ "watcher_tag": "@0.9.7",
"when_tag": "@0.2.0+2",
"which_tag": "@0.1.3+1",
"web_components_rev": "@0e636b534d9b12c9e96f841e6679398e91a986ec",
@@ -370,8 +370,8 @@
'--no_resume',
'--bucket',
'dart-dependencies',
- '-d',
- '-r',
+ '--recursive',
+ '--directory',
Var('dart_root') + '/tools/testing/bin',
],
},
@@ -384,10 +384,25 @@
'--no_resume',
'--bucket',
'dart-dependencies',
- '-d',
- '-r',
+ '--recursive',
+ '--directory',
Var('dart_root') + '/third_party/d8',
],
},
-
+ {
+ "name": "checked_in_dart_sdks",
+ "pattern": ".",
+ "action": [
+ "download_from_google_storage",
+ "--no_auth",
+ "--no_resume",
+ "--bucket",
+ "dart-dependencies",
+ "--recursive",
+ "--auto_platform",
+ "--extract",
+ "--directory",
+ Var('dart_root') + "/tools/sdks",
+ ],
+ },
]
diff --git a/pkg/analysis_server/lib/analysis/navigation/navigation_core.dart b/pkg/analysis_server/lib/analysis/navigation/navigation_core.dart
new file mode 100644
index 0000000..c708d9a
--- /dev/null
+++ b/pkg/analysis_server/lib/analysis/navigation/navigation_core.dart
@@ -0,0 +1,40 @@
+// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library analysis_server.analysis.navigation.navigation_core;
+
+import 'package:analysis_server/src/protocol.dart'
+ show ElementKind, Location, NavigationRegion, NavigationTarget;
+import 'package:analyzer/src/generated/engine.dart' show AnalysisContext;
+import 'package:analyzer/src/generated/source.dart' show Source;
+
+/**
+ * An object used to produce navigation regions.
+ *
+ * Clients are expected to subtype this class when implementing plugins.
+ */
+abstract class NavigationContributor {
+ /**
+ * Contribute navigation regions for a part of the given [source] into the
+ * given [holder]. The part is specified by the [offset] and [length].
+ * The [context] can be used to get analysis results.
+ */
+ void computeNavigation(NavigationHolder holder, AnalysisContext context,
+ Source source, int offset, int length);
+}
+
+/**
+ * An object that [NavigationContributor]s use to record navigation regions
+ * into.
+ *
+ * Clients are not expected to subtype this class.
+ */
+abstract class NavigationHolder {
+ /**
+ * Record a new navigation region with the given [offset] and [length] that
+ * should navigation to the given [targetLocation].
+ */
+ void addRegion(
+ int offset, int length, ElementKind targetKind, Location targetLocation);
+}
diff --git a/pkg/analysis_server/lib/plugin/navigation.dart b/pkg/analysis_server/lib/plugin/navigation.dart
new file mode 100644
index 0000000..23603f0
--- /dev/null
+++ b/pkg/analysis_server/lib/plugin/navigation.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2015, 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.
+
+/**
+ * Support for client code that extends the analysis server by adding new
+ * navigation contributors.
+ */
+library analysis_server.plugin.navigation;
+
+import 'package:analysis_server/analysis/navigation/navigation_core.dart';
+import 'package:analysis_server/src/plugin/server_plugin.dart';
+import 'package:plugin/plugin.dart';
+
+/**
+ * The identifier of the extension point that allows plugins to register
+ * navigation contributors. The object used as an extension must be
+ * a [NavigationContributor].
+ */
+final String NAVIGATION_CONTRIBUTOR_EXTENSION_POINT_ID = Plugin.join(
+ ServerPlugin.UNIQUE_IDENTIFIER,
+ ServerPlugin.NAVIGATION_CONTRIBUTOR_EXTENSION_POINT);
diff --git a/pkg/analysis_server/lib/src/analysis_server.dart b/pkg/analysis_server/lib/src/analysis_server.dart
index 87c6509..5d0fb7d 100644
--- a/pkg/analysis_server/lib/src/analysis_server.dart
+++ b/pkg/analysis_server/lib/src/analysis_server.dart
@@ -961,6 +961,9 @@
// Dart unit notifications.
if (AnalysisEngine.isDartFileName(file)) {
Source source = contextSource.source;
+ // TODO(scheglov) This way to get resolved information is very Dart
+ // specific. OTOH as it is planned now Angular results are not
+ // flushable.
CompilationUnit dartUnit =
_getResolvedCompilationUnitToResendNotification(context, source);
if (dartUnit != null) {
@@ -969,8 +972,7 @@
sendAnalysisNotificationHighlights(this, file, dartUnit);
break;
case AnalysisService.NAVIGATION:
- // TODO(scheglov) consider support for one unit in 2+ libraries
- sendAnalysisNotificationNavigation(this, file, dartUnit);
+ sendAnalysisNotificationNavigation(this, context, source);
break;
case AnalysisService.OCCURRENCES:
sendAnalysisNotificationOccurrences(this, file, dartUnit);
diff --git a/pkg/analysis_server/lib/src/collections.dart b/pkg/analysis_server/lib/src/collections.dart
index 8ab3da8..1a1ba38 100644
--- a/pkg/analysis_server/lib/src/collections.dart
+++ b/pkg/analysis_server/lib/src/collections.dart
@@ -28,3 +28,20 @@
}
return list;
}
+
+/// A pair of values.
+class Pair<E, F> {
+ final E first;
+ final F last;
+
+ Pair(this.first, this.last);
+
+ int get hashCode => first.hashCode ^ last.hashCode;
+
+ bool operator ==(other) {
+ if (other is! Pair) return false;
+ return other.first == first && other.last == last;
+ }
+
+ String toString() => '($first, $last)';
+}
diff --git a/pkg/analysis_server/lib/src/computer/computer_outline.dart b/pkg/analysis_server/lib/src/computer/computer_outline.dart
index 81e9b50..a052b13 100644
--- a/pkg/analysis_server/lib/src/computer/computer_outline.dart
+++ b/pkg/analysis_server/lib/src/computer/computer_outline.dart
@@ -137,7 +137,7 @@
}
// unit or class member
if (parent is CompilationUnit) {
- firstOffset = 0;
+ firstOffset = node.offset;
siblings = parent.declarations;
} else if (parent is ClassDeclaration) {
firstOffset = parent.leftBracket.end;
@@ -160,7 +160,10 @@
SimpleIdentifier nameNode = node.name;
String name = nameNode.name;
_SourceRegion sourceRegion = _getSourceRegion(node);
- Element element = new Element(ElementKind.CLASS, name, Element.makeFlags(
+ Element element = new Element(
+ ElementKind.CLASS,
+ name,
+ Element.makeFlags(
isPrivate: Identifier.isPrivateName(name),
isDeprecated: _isDeprecated(node),
isAbstract: node.isAbstract),
@@ -174,11 +177,13 @@
SimpleIdentifier nameNode = node.name;
String name = nameNode.name;
_SourceRegion sourceRegion = _getSourceRegion(node);
- Element element = new Element(ElementKind.CLASS_TYPE_ALIAS, name, Element
- .makeFlags(
- isPrivate: Identifier.isPrivateName(name),
- isDeprecated: _isDeprecated(node),
- isAbstract: node.isAbstract),
+ Element element = new Element(
+ ElementKind.CLASS_TYPE_ALIAS,
+ name,
+ Element.makeFlags(
+ isPrivate: Identifier.isPrivateName(name),
+ isDeprecated: _isDeprecated(node),
+ isAbstract: node.isAbstract),
location: _getLocationNode(nameNode),
typeParameters: _getTypeParametersStr(node.typeParameters));
return new Outline(element, sourceRegion.offset, sourceRegion.length);
@@ -201,9 +206,11 @@
_SourceRegion sourceRegion = _getSourceRegion(constructor);
FormalParameterList parameters = constructor.parameters;
String parametersStr = parameters != null ? parameters.toSource() : '';
- Element element = new Element(ElementKind.CONSTRUCTOR, name, Element
- .makeFlags(
- isPrivate: isPrivate, isDeprecated: _isDeprecated(constructor)),
+ Element element = new Element(
+ ElementKind.CONSTRUCTOR,
+ name,
+ Element.makeFlags(
+ isPrivate: isPrivate, isDeprecated: _isDeprecated(constructor)),
location: _getLocationOffsetLength(offset, length),
parameters: parametersStr);
List<Outline> contents = _addLocalFunctionOutlines(constructor.body);
@@ -217,10 +224,12 @@
SimpleIdentifier nameNode = node.name;
String name = nameNode.name;
_SourceRegion sourceRegion = _getSourceRegion(node);
- Element element = new Element(ElementKind.ENUM_CONSTANT, name, Element
- .makeFlags(
- isPrivate: Identifier.isPrivateName(name),
- isDeprecated: _isDeprecated(node)),
+ Element element = new Element(
+ ElementKind.ENUM_CONSTANT,
+ name,
+ Element.makeFlags(
+ isPrivate: Identifier.isPrivateName(name),
+ isDeprecated: _isDeprecated(node)),
location: _getLocationNode(nameNode));
return new Outline(element, sourceRegion.offset, sourceRegion.length);
}
@@ -229,7 +238,10 @@
SimpleIdentifier nameNode = node.name;
String name = nameNode.name;
_SourceRegion sourceRegion = _getSourceRegion(node);
- Element element = new Element(ElementKind.ENUM, name, Element.makeFlags(
+ Element element = new Element(
+ ElementKind.ENUM,
+ name,
+ Element.makeFlags(
isPrivate: Identifier.isPrivateName(name),
isDeprecated: _isDeprecated(node)),
location: _getLocationNode(nameNode));
@@ -254,7 +266,10 @@
_SourceRegion sourceRegion = _getSourceRegion(function);
String parametersStr = parameters != null ? parameters.toSource() : '';
String returnTypeStr = returnType != null ? returnType.toSource() : '';
- Element element = new Element(kind, name, Element.makeFlags(
+ Element element = new Element(
+ kind,
+ name,
+ Element.makeFlags(
isPrivate: Identifier.isPrivateName(name),
isDeprecated: _isDeprecated(function),
isStatic: isStatic),
@@ -276,10 +291,12 @@
FormalParameterList parameters = node.parameters;
String parametersStr = parameters != null ? parameters.toSource() : '';
String returnTypeStr = returnType != null ? returnType.toSource() : '';
- Element element = new Element(ElementKind.FUNCTION_TYPE_ALIAS, name, Element
- .makeFlags(
- isPrivate: Identifier.isPrivateName(name),
- isDeprecated: _isDeprecated(node)),
+ Element element = new Element(
+ ElementKind.FUNCTION_TYPE_ALIAS,
+ name,
+ Element.makeFlags(
+ isPrivate: Identifier.isPrivateName(name),
+ isDeprecated: _isDeprecated(node)),
location: _getLocationNode(nameNode),
parameters: parametersStr,
returnType: returnTypeStr,
@@ -303,7 +320,10 @@
_SourceRegion sourceRegion = _getSourceRegion(method);
String parametersStr = parameters != null ? parameters.toSource() : null;
String returnTypeStr = returnType != null ? returnType.toSource() : '';
- Element element = new Element(kind, name, Element.makeFlags(
+ Element element = new Element(
+ kind,
+ name,
+ Element.makeFlags(
isPrivate: Identifier.isPrivateName(name),
isDeprecated: _isDeprecated(method),
isAbstract: method.isAbstract,
@@ -338,13 +358,17 @@
SimpleIdentifier nameNode = variable.name;
String name = nameNode.name;
_SourceRegion sourceRegion = _getSourceRegion(variable);
- Element element = new Element(kind, name, Element.makeFlags(
+ Element element = new Element(
+ kind,
+ name,
+ Element.makeFlags(
isPrivate: Identifier.isPrivateName(name),
isDeprecated: _isDeprecated(variable),
isStatic: isStatic,
isConst: variable.isConst,
isFinal: variable.isFinal),
- location: _getLocationNode(nameNode), returnType: typeName);
+ location: _getLocationNode(nameNode),
+ returnType: typeName);
Outline outline =
new Outline(element, sourceRegion.offset, sourceRegion.length);
return outline;
diff --git a/pkg/analysis_server/lib/src/domain_analysis.dart b/pkg/analysis_server/lib/src/domain_analysis.dart
index c0492bf..655ca2f 100644
--- a/pkg/analysis_server/lib/src/domain_analysis.dart
+++ b/pkg/analysis_server/lib/src/domain_analysis.dart
@@ -9,12 +9,13 @@
import 'package:analysis_server/src/analysis_server.dart';
import 'package:analysis_server/src/computer/computer_hover.dart';
-import 'package:analysis_server/src/computer/computer_navigation.dart';
import 'package:analysis_server/src/constants.dart';
+import 'package:analysis_server/src/domains/analysis/navigation.dart';
import 'package:analysis_server/src/protocol_server.dart';
import 'package:analysis_server/src/services/dependencies/library_dependencies.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/src/generated/ast.dart';
+import 'package:analyzer/src/generated/element.dart';
import 'package:analyzer/src/generated/engine.dart' as engine;
/**
@@ -125,15 +126,15 @@
if (units.isEmpty) {
server.sendResponse(new Response.getNavigationInvalidFile(request));
} else {
- DartUnitNavigationComputer computer =
- new DartUnitNavigationComputer();
- _GetNavigationAstVisitor visitor = new _GetNavigationAstVisitor(
- params.offset, params.offset + params.length, computer);
- for (CompilationUnit unit in units) {
- unit.accept(visitor);
- }
+ CompilationUnitElement unitElement = units.first.element;
+ NavigationHolderImpl holder = computeNavigation(
+ server,
+ unitElement.context,
+ unitElement.source,
+ params.offset,
+ params.length);
server.sendResponse(new AnalysisGetNavigationResult(
- computer.files, computer.targets, computer.regions)
+ holder.files, holder.targets, holder.regions)
.toResponse(request.id));
}
break;
@@ -290,36 +291,3 @@
return new AnalysisUpdateOptionsResult().toResponse(request.id);
}
}
-
-/**
- * An AST visitor that computer navigation regions in the givne region.
- */
-class _GetNavigationAstVisitor extends UnifyingAstVisitor {
- final int rangeStart;
- final int rangeEnd;
- final DartUnitNavigationComputer computer;
-
- _GetNavigationAstVisitor(this.rangeStart, this.rangeEnd, this.computer);
-
- bool isInRange(int offset) {
- return rangeStart <= offset && offset <= rangeEnd;
- }
-
- @override
- visitNode(AstNode node) {
- // The node ends before the range starts.
- if (node.end < rangeStart) {
- return;
- }
- // The node starts after the range ends.
- if (node.offset > rangeEnd) {
- return;
- }
- // The node starts or ends in the range.
- if (isInRange(node.offset) || isInRange(node.end)) {
- computer.compute(node);
- return;
- }
- super.visitNode(node);
- }
-}
diff --git a/pkg/analysis_server/lib/src/domains/analysis/navigation.dart b/pkg/analysis_server/lib/src/domains/analysis/navigation.dart
new file mode 100644
index 0000000..8cb08ae
--- /dev/null
+++ b/pkg/analysis_server/lib/src/domains/analysis/navigation.dart
@@ -0,0 +1,99 @@
+// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library domains.analysis.navigation;
+
+import 'dart:collection';
+
+import 'package:analysis_server/analysis/navigation/navigation_core.dart';
+import 'package:analysis_server/src/analysis_server.dart';
+import 'package:analysis_server/src/collections.dart';
+import 'package:analysis_server/src/protocol_server.dart' as protocol;
+import 'package:analyzer/src/generated/engine.dart'
+ show AnalysisContext, AnalysisEngine;
+import 'package:analyzer/src/generated/java_engine.dart' show CaughtException;
+import 'package:analyzer/src/generated/source.dart' show Source;
+
+/**
+ * Compute all known navigation information for the given part of [source].
+ */
+NavigationHolderImpl computeNavigation(AnalysisServer server,
+ AnalysisContext context, Source source, int offset, int length) {
+ NavigationHolderImpl holder = new NavigationHolderImpl();
+ List<NavigationContributor> contributors =
+ server.serverPlugin.navigationContributors;
+ for (NavigationContributor contributor in contributors) {
+ try {
+ contributor.computeNavigation(holder, context, source, offset, length);
+ } catch (exception, stackTrace) {
+ AnalysisEngine.instance.logger.logError(
+ 'Exception from navigation contributor: ${contributor.runtimeType}',
+ new CaughtException(exception, stackTrace));
+ }
+ }
+ return holder;
+}
+
+/**
+ * A concrete implementation of [NavigationHolder].
+ */
+class NavigationHolderImpl implements NavigationHolder {
+ /**
+ * A list of navigation regions.
+ */
+ final List<protocol.NavigationRegion> regions = <protocol.NavigationRegion>[];
+
+ /**
+ * All the unique targets referenced by [regions].
+ */
+ final List<protocol.NavigationTarget> targets = <protocol.NavigationTarget>[];
+ final Map<Pair<protocol.ElementKind, protocol.Location>, int> targetMap =
+ new HashMap<Pair<protocol.ElementKind, protocol.Location>, int>();
+
+ /**
+ * All the unique files referenced by [targets].
+ */
+ final List<String> files = <String>[];
+ final Map<String, int> fileMap = new HashMap<String, int>();
+
+ @override
+ void addRegion(int offset, int length, protocol.ElementKind targetKind,
+ protocol.Location targetLocation) {
+ int targetIndex = _addTarget(targetKind, targetLocation);
+ protocol.NavigationRegion region =
+ new protocol.NavigationRegion(offset, length, <int>[targetIndex]);
+ regions.add(region);
+ }
+
+ int _addFile(String file) {
+ int index = fileMap[file];
+ if (index == null) {
+ index = files.length;
+ files.add(file);
+ fileMap[file] = index;
+ }
+ return index;
+ }
+
+ int _addTarget(protocol.ElementKind kind, protocol.Location location) {
+ var pair =
+ new Pair<protocol.ElementKind, protocol.Location>(kind, location);
+ int index = targetMap[pair];
+ if (index == null) {
+ String file = location.file;
+ int fileIndex = _addFile(file);
+ index = targets.length;
+ protocol.NavigationTarget target = new protocol.NavigationTarget(
+ kind,
+ fileIndex,
+ location.offset,
+ location.length,
+ location.startLine,
+ location.startColumn);
+ targets.add(target);
+ targetMap[pair] = index;
+ }
+ return index;
+ }
+}
diff --git a/pkg/analysis_server/lib/src/computer/computer_navigation.dart b/pkg/analysis_server/lib/src/domains/analysis/navigation_dart.dart
similarity index 72%
rename from pkg/analysis_server/lib/src/computer/computer_navigation.dart
rename to pkg/analysis_server/lib/src/domains/analysis/navigation_dart.dart
index b1caf9b..37aaac1b 100644
--- a/pkg/analysis_server/lib/src/computer/computer_navigation.dart
+++ b/pkg/analysis_server/lib/src/domains/analysis/navigation_dart.dart
@@ -2,99 +2,47 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-library computer.navigation;
+library domains.analysis.navigation_dart;
-import 'dart:collection';
-
+import 'package:analysis_server/analysis/navigation/navigation_core.dart';
import 'package:analysis_server/src/protocol_server.dart' as protocol;
import 'package:analyzer/src/generated/ast.dart';
import 'package:analyzer/src/generated/element.dart';
+import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/scanner.dart';
import 'package:analyzer/src/generated/source.dart';
/**
* A computer for navigation regions in a Dart [CompilationUnit].
*/
-class DartUnitNavigationComputer {
- final List<String> files = <String>[];
- final Map<String, int> fileMap = new HashMap<String, int>();
- final List<protocol.NavigationTarget> targets = <protocol.NavigationTarget>[];
- final Map<Element, int> targetMap = new HashMap<Element, int>();
- final List<protocol.NavigationRegion> regions = <protocol.NavigationRegion>[];
-
- /**
- * Computes [regions], [targets] and [files].
- */
- void compute(AstNode node) {
- node.accept(new _DartUnitNavigationComputerVisitor(this));
- }
-
- int _addFile(String file) {
- int index = fileMap[file];
- if (index == null) {
- index = files.length;
- files.add(file);
- fileMap[file] = index;
+class DartNavigationComputer implements NavigationContributor {
+ @override
+ void computeNavigation(NavigationHolder holder, AnalysisContext context,
+ Source source, int offset, int length) {
+ List<Source> libraries = context.getLibrariesContaining(source);
+ if (libraries.isNotEmpty) {
+ CompilationUnit unit =
+ context.getResolvedCompilationUnit2(source, libraries.first);
+ if (unit != null) {
+ _DartNavigationHolder dartHolder = new _DartNavigationHolder(holder);
+ _DartNavigationComputerVisitor visitor =
+ new _DartNavigationComputerVisitor(dartHolder);
+ if (offset == null || length == null) {
+ unit.accept(visitor);
+ } else {
+ _DartRangeAstVisitor partVisitor =
+ new _DartRangeAstVisitor(offset, offset + length, visitor);
+ unit.accept(partVisitor);
+ }
+ }
}
- return index;
- }
-
- void _addRegion(int offset, int length, Element element) {
- if (element is FieldFormalParameterElement) {
- element = (element as FieldFormalParameterElement).field;
- }
- if (element == null || element == DynamicElementImpl.instance) {
- return;
- }
- if (element.location == null) {
- return;
- }
- int targetIndex = _addTarget(element);
- regions
- .add(new protocol.NavigationRegion(offset, length, <int>[targetIndex]));
- }
-
- void _addRegion_nodeStart_nodeEnd(AstNode a, AstNode b, Element element) {
- int offset = a.offset;
- int length = b.end - offset;
- _addRegion(offset, length, element);
- }
-
- void _addRegion_tokenStart_nodeEnd(Token a, AstNode b, Element element) {
- int offset = a.offset;
- int length = b.end - offset;
- _addRegion(offset, length, element);
- }
-
- void _addRegionForNode(AstNode node, Element element) {
- int offset = node.offset;
- int length = node.length;
- _addRegion(offset, length, element);
- }
-
- void _addRegionForToken(Token token, Element element) {
- int offset = token.offset;
- int length = token.length;
- _addRegion(offset, length, element);
- }
-
- int _addTarget(Element element) {
- int index = targetMap[element];
- if (index == null) {
- index = targets.length;
- protocol.NavigationTarget target =
- protocol.newNavigationTarget_fromElement(element, _addFile);
- targets.add(target);
- targetMap[element] = index;
- }
- return index;
}
}
-class _DartUnitNavigationComputerVisitor extends RecursiveAstVisitor {
- final DartUnitNavigationComputer computer;
+class _DartNavigationComputerVisitor extends RecursiveAstVisitor {
+ final _DartNavigationHolder computer;
- _DartUnitNavigationComputerVisitor(this.computer);
+ _DartNavigationComputerVisitor(this.computer);
@override
visitAssignmentExpression(AssignmentExpression node) {
@@ -273,3 +221,90 @@
}
}
}
+
+/**
+ * A Dart specific wrapper around [NavigationHolder].
+ */
+class _DartNavigationHolder {
+ final NavigationHolder holder;
+
+ _DartNavigationHolder(this.holder);
+
+ void _addRegion(int offset, int length, Element element) {
+ if (element is FieldFormalParameterElement) {
+ element = (element as FieldFormalParameterElement).field;
+ }
+ if (element == null || element == DynamicElementImpl.instance) {
+ return;
+ }
+ if (element.location == null) {
+ return;
+ }
+ protocol.ElementKind kind =
+ protocol.newElementKind_fromEngine(element.kind);
+ protocol.Location location = protocol.newLocation_fromElement(element);
+ if (location == null) {
+ return;
+ }
+ holder.addRegion(offset, length, kind, location);
+ }
+
+ void _addRegion_nodeStart_nodeEnd(AstNode a, AstNode b, Element element) {
+ int offset = a.offset;
+ int length = b.end - offset;
+ _addRegion(offset, length, element);
+ }
+
+ void _addRegion_tokenStart_nodeEnd(Token a, AstNode b, Element element) {
+ int offset = a.offset;
+ int length = b.end - offset;
+ _addRegion(offset, length, element);
+ }
+
+ void _addRegionForNode(AstNode node, Element element) {
+ int offset = node.offset;
+ int length = node.length;
+ _addRegion(offset, length, element);
+ }
+
+ void _addRegionForToken(Token token, Element element) {
+ int offset = token.offset;
+ int length = token.length;
+ _addRegion(offset, length, element);
+ }
+}
+
+/**
+ * An AST visitor that forwards nodes intersecting with the range from
+ * [start] to [end] to the given [visitor].
+ */
+class _DartRangeAstVisitor extends UnifyingAstVisitor {
+ final int start;
+ final int end;
+ final AstVisitor visitor;
+
+ _DartRangeAstVisitor(this.start, this.end, this.visitor);
+
+ bool isInRange(int offset) {
+ return start <= offset && offset <= end;
+ }
+
+ @override
+ visitNode(AstNode node) {
+ // The node ends before the range starts.
+ if (node.end < start) {
+ return;
+ }
+ // The node starts after the range ends.
+ if (node.offset > end) {
+ return;
+ }
+ // The node starts or ends in the range.
+ if (isInRange(node.offset) || isInRange(node.end)) {
+ node.accept(visitor);
+ return;
+ }
+ // Go deeper.
+ super.visitNode(node);
+ }
+}
diff --git a/pkg/analysis_server/lib/src/operation/operation_analysis.dart b/pkg/analysis_server/lib/src/operation/operation_analysis.dart
index 70b1e9b..f18ad32 100644
--- a/pkg/analysis_server/lib/src/operation/operation_analysis.dart
+++ b/pkg/analysis_server/lib/src/operation/operation_analysis.dart
@@ -7,10 +7,10 @@
import 'package:analysis_server/src/analysis_server.dart';
import 'package:analysis_server/src/computer/computer_highlights.dart';
import 'package:analysis_server/src/computer/computer_highlights2.dart';
-import 'package:analysis_server/src/computer/computer_navigation.dart';
import 'package:analysis_server/src/computer/computer_occurrences.dart';
import 'package:analysis_server/src/computer/computer_outline.dart';
import 'package:analysis_server/src/computer/computer_overrides.dart';
+import 'package:analysis_server/src/domains/analysis/navigation.dart';
import 'package:analysis_server/src/operation/operation.dart';
import 'package:analysis_server/src/protocol_server.dart' as protocol;
import 'package:analysis_server/src/services/dependencies/library_dependencies.dart';
@@ -53,9 +53,14 @@
* Schedules sending notifications for the given [file] using the resolved
* [resolvedDartUnit].
*/
-void scheduleNotificationOperations(AnalysisServer server, String file,
- LineInfo lineInfo, AnalysisContext context, CompilationUnit parsedDartUnit,
- CompilationUnit resolvedDartUnit, List<AnalysisError> errors) {
+void scheduleNotificationOperations(
+ AnalysisServer server,
+ String file,
+ LineInfo lineInfo,
+ AnalysisContext context,
+ CompilationUnit parsedDartUnit,
+ CompilationUnit resolvedDartUnit,
+ List<AnalysisError> errors) {
// If the file belongs to any analysis root, check whether we're in it now.
AnalysisContext containingContext = server.getContainingContext(file);
if (containingContext != null && context != containingContext) {
@@ -162,12 +167,13 @@
}
void sendAnalysisNotificationNavigation(
- AnalysisServer server, String file, CompilationUnit dartUnit) {
+ AnalysisServer server, AnalysisContext context, Source source) {
_sendNotification(server, () {
- var computer = new DartUnitNavigationComputer();
- computer.compute(dartUnit);
+ NavigationHolderImpl holder =
+ computeNavigation(server, context, source, null, null);
+ String file = source.fullName;
var params = new protocol.AnalysisNavigationParams(
- file, computer.regions, computer.targets, computer.files);
+ file, holder.regions, holder.targets, holder.files);
server.sendNotification(params.toNotification());
});
}
@@ -381,7 +387,8 @@
@override
void perform(AnalysisServer server) {
- sendAnalysisNotificationNavigation(server, file, unit);
+ Source source = unit.element.source;
+ sendAnalysisNotificationNavigation(server, context, source);
}
}
diff --git a/pkg/analysis_server/lib/src/plugin/server_plugin.dart b/pkg/analysis_server/lib/src/plugin/server_plugin.dart
index be413c6..6139725 100644
--- a/pkg/analysis_server/lib/src/plugin/server_plugin.dart
+++ b/pkg/analysis_server/lib/src/plugin/server_plugin.dart
@@ -5,17 +5,20 @@
library analysis_server.src.plugin.server_plugin;
import 'package:analysis_server/analysis/index/index_core.dart';
+import 'package:analysis_server/analysis/navigation/navigation_core.dart';
import 'package:analysis_server/completion/completion_core.dart';
import 'package:analysis_server/edit/assist/assist_core.dart';
import 'package:analysis_server/edit/fix/fix_core.dart';
import 'package:analysis_server/plugin/analyzed_files.dart';
import 'package:analysis_server/plugin/assist.dart';
import 'package:analysis_server/plugin/fix.dart';
+import 'package:analysis_server/plugin/navigation.dart';
import 'package:analysis_server/src/analysis_server.dart';
import 'package:analysis_server/src/domain_analysis.dart';
import 'package:analysis_server/src/domain_completion.dart';
import 'package:analysis_server/src/domain_execution.dart';
import 'package:analysis_server/src/domain_server.dart';
+import 'package:analysis_server/src/domains/analysis/navigation_dart.dart';
import 'package:analysis_server/src/edit/edit_domain.dart';
import 'package:analysis_server/src/protocol.dart';
import 'package:analysis_server/src/search/search_domain.dart';
@@ -74,6 +77,13 @@
static const String INDEX_CONTRIBUTOR_EXTENSION_POINT = 'indexContributor';
/**
+ * The simple identifier of the extension point that allows plugins to
+ * register navigation contributors.
+ */
+ static const String NAVIGATION_CONTRIBUTOR_EXTENSION_POINT =
+ 'navigationContributor';
+
+ /**
* The unique identifier of this plugin.
*/
static const String UNIQUE_IDENTIFIER = 'analysis_server.core';
@@ -113,6 +123,11 @@
ExtensionPoint indexContributorExtensionPoint;
/**
+ * The extension point that allows plugins to register navigation contributors.
+ */
+ ExtensionPoint navigationContributorExtensionPoint;
+
+ /**
* Initialize a newly created plugin.
*/
ServerPlugin();
@@ -151,6 +166,13 @@
List<IndexContributor> get indexContributors =>
indexContributorExtensionPoint.extensions;
+ /**
+ * Return a list containing all of the navigation contributors that were
+ * contributed.
+ */
+ List<NavigationContributor> get navigationContributors =>
+ navigationContributorExtensionPoint.extensions;
+
@override
String get uniqueIdentifier => UNIQUE_IDENTIFIER;
@@ -183,6 +205,9 @@
FIX_CONTRIBUTOR_EXTENSION_POINT, _validateFixContributorExtension);
indexContributorExtensionPoint = registerExtensionPoint(
INDEX_CONTRIBUTOR_EXTENSION_POINT, _validateIndexContributorExtension);
+ navigationContributorExtensionPoint = registerExtensionPoint(
+ NAVIGATION_CONTRIBUTOR_EXTENSION_POINT,
+ _validateNavigationContributorExtension);
}
@override
@@ -190,7 +215,8 @@
//
// Register analyze file functions.
//
- registerExtension(ANALYZE_FILE_EXTENSION_POINT_ID,
+ registerExtension(
+ ANALYZE_FILE_EXTENSION_POINT_ID,
(File file) => AnalysisEngine.isDartFileName(file.path) ||
AnalysisEngine.isHtmlFileName(file.path));
//
@@ -204,6 +230,11 @@
// TODO(brianwilkerson) Register the completion contributors.
// registerExtension(COMPLETION_CONTRIBUTOR_EXTENSION_POINT_ID, ???);
//
+ // Register navigation contributors.
+ //
+ registerExtension(NAVIGATION_CONTRIBUTOR_EXTENSION_POINT_ID,
+ new DartNavigationComputer());
+ //
// Register domains.
//
String domainId = Plugin.join(UNIQUE_IDENTIFIER, DOMAIN_EXTENSION_POINT);
@@ -300,4 +331,16 @@
throw new ExtensionError('Extensions to $id must be an IndexContributor');
}
}
+
+ /**
+ * Validate the given extension by throwing an [ExtensionError] if it is not a
+ * valid navigation contributor.
+ */
+ void _validateNavigationContributorExtension(Object extension) {
+ if (extension is! NavigationContributor) {
+ String id = navigationContributorExtensionPoint.uniqueIdentifier;
+ throw new ExtensionError(
+ 'Extensions to $id must be an NavigationContributor');
+ }
+ }
}
diff --git a/pkg/analysis_server/lib/src/protocol_server.dart b/pkg/analysis_server/lib/src/protocol_server.dart
index ea94457..ff98970 100644
--- a/pkg/analysis_server/lib/src/protocol_server.dart
+++ b/pkg/analysis_server/lib/src/protocol_server.dart
@@ -257,16 +257,6 @@
return _locationForArgs(context, source, range);
}
-NavigationTarget newNavigationTarget_fromElement(
- engine.Element element, int fileToIndex(String file)) {
- ElementKind kind = newElementKind_fromEngine(element.kind);
- Location location = newLocation_fromElement(element);
- String file = location.file;
- int fileIndex = fileToIndex(file);
- return new NavigationTarget(kind, fileIndex, location.offset, location.length,
- location.startLine, location.startColumn);
-}
-
/**
* Construct based on an element from the analyzer engine.
*/
diff --git a/pkg/analysis_server/lib/src/services/completion/dart_completion_manager.dart b/pkg/analysis_server/lib/src/services/completion/dart_completion_manager.dart
index b3a78e6..6186079 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart_completion_manager.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart_completion_manager.dart
@@ -16,7 +16,7 @@
import 'package:analysis_server/src/services/completion/completion_manager.dart';
import 'package:analysis_server/src/services/completion/completion_target.dart';
import 'package:analysis_server/src/services/completion/dart_completion_cache.dart';
-import 'package:analysis_server/src/services/completion/import_uri_contributor.dart';
+import 'package:analysis_server/src/services/completion/uri_contributor.dart';
import 'package:analysis_server/src/services/completion/imported_reference_contributor.dart';
import 'package:analysis_server/src/services/completion/keyword_contributor.dart';
import 'package:analysis_server/src/services/completion/local_reference_contributor.dart';
@@ -92,7 +92,7 @@
new ArgListContributor(),
new CombinatorContributor(),
new PrefixedElementContributor(),
- new ImportUriContributor(),
+ new UriContributor(),
];
}
if (commonUsageComputer == null) {
diff --git a/pkg/analysis_server/lib/src/services/completion/import_uri_contributor.dart b/pkg/analysis_server/lib/src/services/completion/uri_contributor.dart
similarity index 95%
rename from pkg/analysis_server/lib/src/services/completion/import_uri_contributor.dart
rename to pkg/analysis_server/lib/src/services/completion/uri_contributor.dart
index 498c289..cb32012 100644
--- a/pkg/analysis_server/lib/src/services/completion/import_uri_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/uri_contributor.dart
@@ -22,12 +22,12 @@
* A contributor for calculating uri suggestions
* for import and part directives.
*/
-class ImportUriContributor extends DartCompletionContributor {
- _ImportUriSuggestionBuilder builder;
+class UriContributor extends DartCompletionContributor {
+ _UriSuggestionBuilder builder;
@override
bool computeFast(DartCompletionRequest request) {
- builder = new _ImportUriSuggestionBuilder(request);
+ builder = new _UriSuggestionBuilder(request);
return builder.computeFast(request.target.containingNode);
}
@@ -37,10 +37,10 @@
}
}
-class _ImportUriSuggestionBuilder extends SimpleAstVisitor {
+class _UriSuggestionBuilder extends SimpleAstVisitor {
final DartCompletionRequest request;
- _ImportUriSuggestionBuilder(this.request);
+ _UriSuggestionBuilder(this.request);
bool computeFast(AstNode node) {
node.accept(this);
diff --git a/pkg/analysis_server/lib/src/services/refactoring/rename.dart b/pkg/analysis_server/lib/src/services/refactoring/rename.dart
index 012b7a1..b22d74d 100644
--- a/pkg/analysis_server/lib/src/services/refactoring/rename.dart
+++ b/pkg/analysis_server/lib/src/services/refactoring/rename.dart
@@ -151,7 +151,8 @@
@override
Future<SourceChange> createChange() async {
- change = new SourceChange(refactoringName);
+ String changeName = "$refactoringName '$oldName' to '$newName'";
+ change = new SourceChange(changeName);
await fillChange();
return change;
}
diff --git a/pkg/analysis_server/test/analysis/notification_outline_test.dart b/pkg/analysis_server/test/analysis/notification_outline_test.dart
index 2d459ac..fdac6b5 100644
--- a/pkg/analysis_server/test/analysis/notification_outline_test.dart
+++ b/pkg/analysis_server/test/analysis/notification_outline_test.dart
@@ -577,6 +577,8 @@
test_sourceRange_inUnit() {
addTestFile('''
+library lib;
+/// My first class.
class A {
} // endA
class B {
@@ -593,7 +595,7 @@
expect(element.kind, ElementKind.CLASS);
expect(element.name, "A");
{
- int offset = 0;
+ int offset = testCode.indexOf("/// My first class.");
int end = testCode.indexOf(" // endA");
expect(outline.offset, offset);
expect(outline.length, end - offset);
diff --git a/pkg/analysis_server/test/services/completion/test_all.dart b/pkg/analysis_server/test/services/completion/test_all.dart
index d2035b8..34d49c2 100644
--- a/pkg/analysis_server/test/services/completion/test_all.dart
+++ b/pkg/analysis_server/test/services/completion/test_all.dart
@@ -13,7 +13,6 @@
import 'completion_computer_test.dart' as completion_computer_test;
import 'completion_manager_test.dart' as completion_manager_test;
import 'completion_target_test.dart' as completion_target_test;
-import 'import_uri_contributor_test.dart' as import_uri_test;
import 'imported_reference_contributor_test.dart' as imported_test;
import 'keyword_contributor_test.dart' as keyword_test;
import 'local_declaration_visitor_test.dart' as local_declaration_visitor_test;
@@ -21,6 +20,7 @@
as local_reference_contributor_test;
import 'optype_test.dart' as optype_test;
import 'prefixed_element_contributor_test.dart' as invocation_test;
+import 'uri_contributor_test.dart' as uri_contributor_test;
/// Utility for manually running all tests.
main() {
@@ -32,12 +32,12 @@
completion_computer_test.main();
completion_manager_test.main();
completion_target_test.main();
- import_uri_test.main();
imported_test.main();
invocation_test.main();
keyword_test.main();
local_declaration_visitor_test.main();
local_reference_contributor_test.main();
optype_test.main();
+ uri_contributor_test.main();
});
}
diff --git a/pkg/analysis_server/test/services/completion/import_uri_contributor_test.dart b/pkg/analysis_server/test/services/completion/uri_contributor_test.dart
similarity index 97%
rename from pkg/analysis_server/test/services/completion/import_uri_contributor_test.dart
rename to pkg/analysis_server/test/services/completion/uri_contributor_test.dart
index 527410e..9742dbd 100644
--- a/pkg/analysis_server/test/services/completion/import_uri_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/uri_contributor_test.dart
@@ -6,7 +6,7 @@
import 'package:analysis_server/src/protocol.dart';
import 'package:analysis_server/src/services/completion/dart_completion_manager.dart';
-import 'package:analysis_server/src/services/completion/import_uri_contributor.dart';
+import 'package:analysis_server/src/services/completion/uri_contributor.dart';
import 'package:analyzer/file_system/memory_file_system.dart';
import 'package:path/path.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -17,15 +17,15 @@
main() {
initializeTestEnvironment();
- defineReflectiveTests(ImportUriContributorTest);
- defineReflectiveTests(ImportUriContributorWindowsTest);
+ defineReflectiveTests(UriContributorTest);
+ defineReflectiveTests(UriContributorWindowsTest);
}
@reflectiveTest
-class ImportUriContributorTest extends AbstractCompletionTest {
+class UriContributorTest extends AbstractCompletionTest {
@override
void setUpContributor() {
- contributor = new ImportUriContributor();
+ contributor = new UriContributor();
}
test_import() {
@@ -284,10 +284,10 @@
}
@reflectiveTest
-class ImportUriContributorWindowsTest extends AbstractCompletionTest {
+class UriContributorWindowsTest extends AbstractCompletionTest {
@override
void setUpContributor() {
- contributor = new ImportUriContributor();
+ contributor = new UriContributor();
}
@override
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index bd316bf..eb7bacf 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -10851,7 +10851,8 @@
}
if (propagatedType != null) {
overrideVariable(loopElement, propagatedType, true);
- _recordPropagatedType(loopVariable.identifier, propagatedType);
+ recordPropagatedTypeIfBetter(
+ loopVariable.identifier, propagatedType);
}
}
} else if (identifier != null && iterable != null) {
@@ -10859,7 +10860,7 @@
if (identifierElement is VariableElement) {
DartType iteratorElementType = _getIteratorElementType(iterable);
overrideVariable(identifierElement, iteratorElementType, true);
- _recordPropagatedType(identifier, iteratorElementType);
+ recordPropagatedTypeIfBetter(identifier, iteratorElementType);
}
}
visitStatementInScope(body);
@@ -11599,18 +11600,6 @@
_propagateTrueState(condition.expression);
}
}
-
- /**
- * Record that the propagated type of the given node is the given type.
- *
- * @param expression the node whose type is to be recorded
- * @param type the propagated type of the node
- */
- void _recordPropagatedType(Expression expression, DartType type) {
- if (type != null && !type.isDynamic) {
- expression.propagatedType = type;
- }
- }
}
/**
diff --git a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
index 720f8bb..bffeaad 100644
--- a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
+++ b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
@@ -303,6 +303,14 @@
return null;
}
+ @override
+ Object visitDeclaredIdentifier(DeclaredIdentifier node) {
+ super.visitDeclaredIdentifier(node);
+ if (_resolver.definingLibrary.context.analysisOptions.strongMode) {
+ _inferForEachLoopVariableType(node);
+ }
+ }
+
/**
* The Dart Language Specification, 12.3: <blockquote>The static type of a literal double is
* double.</blockquote>
@@ -1181,19 +1189,6 @@
return null;
}
- void _inferLocalVariableType(
- VariableDeclaration node, Expression initializer) {
- if (initializer != null &&
- (node.parent as VariableDeclarationList).type == null &&
- (node.element is LocalVariableElementImpl) &&
- (initializer.staticType != null) &&
- (!initializer.staticType.isBottom)) {
- LocalVariableElementImpl element = node.element;
- element.type = initializer.staticType;
- node.name.staticType = initializer.staticType;
- }
- }
-
@override
Object visitVariableDeclaration(VariableDeclaration node) {
Expression initializer = node.initializer;
@@ -1400,6 +1395,43 @@
}
}
+ // TODO(vsm): Use leafp's matchType here?
+ DartType _findIteratedType(InterfaceType type, DartType targetType) {
+ // Set by _find if match is found
+ DartType result = null;
+ // Elements we've already visited on a given inheritance path.
+ HashSet<ClassElement> visitedClasses = null;
+
+ bool _find(InterfaceType type) {
+ ClassElement element = type.element;
+ if (type == _typeProvider.objectType || element == null) {
+ return false;
+ }
+ if (element == targetType.element) {
+ List<DartType> typeArguments = type.typeArguments;
+ assert(typeArguments.length == 1);
+ result = typeArguments[0];
+ return true;
+ }
+ if (visitedClasses == null) {
+ visitedClasses = new HashSet<ClassElement>();
+ }
+ // Already visited this class along this path
+ if (!visitedClasses.add(element)) {
+ return false;
+ }
+ try {
+ return _find(type.superclass) ||
+ type.interfaces.any(_find) ||
+ type.mixins.any(_find);
+ } finally {
+ visitedClasses.remove(element);
+ }
+ }
+ _find(type);
+ return result;
+ }
+
/**
* Return the best type of the given [expression].
*/
@@ -1621,6 +1653,42 @@
return returnType;
}
+ void _inferForEachLoopVariableType(DeclaredIdentifier loopVariable) {
+ if (loopVariable != null &&
+ loopVariable.type == null &&
+ loopVariable.parent is ForEachStatement) {
+ ForEachStatement loop = loopVariable.parent;
+ if (loop.iterable != null) {
+ Expression expr = loop.iterable;
+ LocalVariableElementImpl element = loopVariable.element;
+ DartType exprType = expr.staticType;
+ if (exprType is InterfaceType) {
+ DartType targetType = (loop.awaitKeyword == null)
+ ? _typeProvider.iterableType
+ : _typeProvider.streamType;
+ DartType iteratedType = _findIteratedType(exprType, targetType);
+ if (element != null && iteratedType != null) {
+ element.type = iteratedType;
+ loopVariable.identifier.staticType = iteratedType;
+ }
+ }
+ }
+ }
+ }
+
+ void _inferLocalVariableType(
+ VariableDeclaration node, Expression initializer) {
+ if (initializer != null &&
+ (node.parent as VariableDeclarationList).type == null &&
+ (node.element is LocalVariableElementImpl) &&
+ (initializer.staticType != null) &&
+ (!initializer.staticType.isBottom)) {
+ LocalVariableElementImpl element = node.element;
+ element.type = initializer.staticType;
+ node.name.staticType = initializer.staticType;
+ }
+ }
+
/**
* Return `true` if the given [Type] is the `Future` form the 'dart:async'
* library.
diff --git a/pkg/analyzer/test/generated/resolver_test.dart b/pkg/analyzer/test/generated/resolver_test.dart
index 9c30594..6463a7b 100644
--- a/pkg/analyzer/test/generated/resolver_test.dart
+++ b/pkg/analyzer/test/generated/resolver_test.dart
@@ -8054,6 +8054,17 @@
}
/**
+ * @param code the code that iterates using variable "v". We check that
+ * "v" has expected static and propagated type.
+ */
+ void _assertPropagatedIterationType(String code, DartType expectedStaticType,
+ DartType expectedPropagatedType) {
+ SimpleIdentifier identifier = _findMarkedIdentifier(code, "v in ");
+ expect(identifier.staticType, same(expectedStaticType));
+ expect(identifier.propagatedType, same(expectedPropagatedType));
+ }
+
+ /**
* @param code the code that assigns the value to the variable "v", no matter how. We check that
* "v" has expected static and propagated type.
*/
@@ -13738,6 +13749,72 @@
_assertTypeOfMarkedExpression(
code, typeProvider.dynamicType, typeProvider.intType);
}
+
+ void test_foreachInference_var() {
+ String code = r'''
+main() {
+ var list = <int>[];
+ for (var v in list) {
+ v; // marker
+ }
+}''';
+ _assertPropagatedIterationType(code, typeProvider.intType, null);
+ _assertTypeOfMarkedExpression(code, typeProvider.intType, null);
+ }
+
+ void test_foreachInference_var_iterable() {
+ String code = r'''
+main() {
+ Iterable<int> list = <int>[];
+ for (var v in list) {
+ v; // marker
+ }
+}''';
+ _assertPropagatedIterationType(code, typeProvider.intType, null);
+ _assertTypeOfMarkedExpression(code, typeProvider.intType, null);
+ }
+
+ void test_foreachInference_var_stream() {
+ String code = r'''
+import 'dart:async';
+main() async {
+ Stream<int> stream = null;
+ await for (var v in stream) {
+ v; // marker
+ }
+}''';
+ _assertPropagatedIterationType(code, typeProvider.intType, null);
+ _assertTypeOfMarkedExpression(code, typeProvider.intType, null);
+ }
+
+ void test_foreachInference_dynamic_disabled() {
+ String code = r'''
+main() {
+ var list = <int>[];
+ for (dynamic v in list) {
+ v; // marker
+ }
+}''';
+ _assertPropagatedIterationType(
+ code, typeProvider.dynamicType, typeProvider.intType);
+ _assertTypeOfMarkedExpression(
+ code, typeProvider.dynamicType, typeProvider.intType);
+ }
+
+ void test_foreachInference_reusedVar_disabled() {
+ String code = r'''
+main() {
+ var list = <int>[];
+ var v;
+ for (v in list) {
+ v; // marker
+ }
+}''';
+ _assertPropagatedIterationType(
+ code, typeProvider.dynamicType, typeProvider.intType);
+ _assertTypeOfMarkedExpression(
+ code, typeProvider.dynamicType, typeProvider.intType);
+ }
}
@reflectiveTest
diff --git a/pkg/compiler/lib/src/closure.dart b/pkg/compiler/lib/src/closure.dart
index d95c3f7..f7d74f8 100644
--- a/pkg/compiler/lib/src/closure.dart
+++ b/pkg/compiler/lib/src/closure.dart
@@ -24,7 +24,7 @@
import 'elements/visitor.dart' show ElementVisitor;
import 'js_backend/js_backend.dart' show JavaScriptBackend;
import 'resolution/tree_elements.dart' show TreeElements;
-import 'scanner/scannerlib.dart' show Token;
+import 'tokens/token.dart' show Token;
import 'tree/tree.dart';
import 'util/util.dart';
import 'universe/universe.dart' show
diff --git a/pkg/compiler/lib/src/common/backend_api.dart b/pkg/compiler/lib/src/common/backend_api.dart
index 63b112e..e715f29 100644
--- a/pkg/compiler/lib/src/common/backend_api.dart
+++ b/pkg/compiler/lib/src/common/backend_api.dart
@@ -339,6 +339,10 @@
return true;
}
+ /// Called after the queue is closed. [onQueueEmpty] may be called multiple
+ /// times, but [onQueueClosed] is only called once.
+ void onQueueClosed() {}
+
/// Called after [element] has been resolved.
// TODO(johnniwinther): Change [TreeElements] to [Registry] or a dependency
// node. [elements] is currently unused by the implementation.
diff --git a/pkg/compiler/lib/src/common/codegen.dart b/pkg/compiler/lib/src/common/codegen.dart
index 538b06d..323822b 100644
--- a/pkg/compiler/lib/src/common/codegen.dart
+++ b/pkg/compiler/lib/src/common/codegen.dart
@@ -112,7 +112,6 @@
void registerCompileTimeConstant(ConstantValue constant) {
backend.registerCompileTimeConstant(constant, this);
- backend.constants.addCompileTimeConstantForEmission(constant);
}
void registerTypeVariableBoundsSubtypeCheck(DartType subtype,
@@ -146,6 +145,7 @@
void registerTypeConstant(ClassElement element) {
backend.customElementsAnalysis.registerTypeConstant(element, world);
+ backend.lookupMapAnalysis.registerTypeConstant(element);
}
void registerStaticInvocation(Element element) {
diff --git a/pkg/compiler/lib/src/compiler.dart b/pkg/compiler/lib/src/compiler.dart
index fad09bc..e04c88a 100644
--- a/pkg/compiler/lib/src/compiler.dart
+++ b/pkg/compiler/lib/src/compiler.dart
@@ -91,6 +91,11 @@
import 'null_compiler_output.dart' show
NullCompilerOutput,
NullSink;
+import 'parser/diet_parser_task.dart' show
+ DietParserTask;
+import 'parser/parser_task.dart' show
+ DietParserTask,
+ ParserTask;
import 'patch_parser.dart' show
PatchParserTask;
import 'resolution/registry.dart' show
@@ -99,17 +104,8 @@
ResolverTask;
import 'resolution/tree_elements.dart' show
TreeElementMapping;
-import 'scanner/token_map.dart' show
- TokenMap;
-import 'scanner/scannerlib.dart' show
- COMMENT_TOKEN,
- DietParserTask,
- EOF_TOKEN,
- ParserTask,
- ScannerTask,
- StringToken,
- Token,
- TokenPair;
+import 'scanner/scanner_task.dart' show
+ ScannerTask;
import 'serialization/task.dart' show
SerializationTask;
import 'script.dart' show
@@ -118,6 +114,15 @@
HInstruction;
import 'tracer.dart' show
Tracer;
+import 'tokens/token.dart' show
+ StringToken,
+ Token,
+ TokenPair;
+import 'tokens/token_constants.dart' as Tokens show
+ COMMENT_TOKEN,
+ EOF_TOKEN;
+import 'tokens/token_map.dart' show
+ TokenMap;
import 'tree/tree.dart' show
Node;
import 'typechecker.dart' show
@@ -1235,6 +1240,7 @@
}
emptyQueue(world);
world.queueIsClosed = true;
+ backend.onQueueClosed();
assert(compilationFailed || world.checkNoEnqueuedInvokedInstanceMethods());
}
@@ -1520,10 +1526,10 @@
Token processAndStripComments(Token currentToken) {
Token firstToken = currentToken;
Token prevToken;
- while (currentToken.kind != EOF_TOKEN) {
- if (identical(currentToken.kind, COMMENT_TOKEN)) {
+ while (currentToken.kind != Tokens.EOF_TOKEN) {
+ if (identical(currentToken.kind, Tokens.COMMENT_TOKEN)) {
Token firstCommentToken = currentToken;
- while (identical(currentToken.kind, COMMENT_TOKEN)) {
+ while (identical(currentToken.kind, Tokens.COMMENT_TOKEN)) {
currentToken = currentToken.next;
}
commentMap[currentToken] = firstCommentToken;
diff --git a/pkg/compiler/lib/src/cps_ir/cps_fragment.dart b/pkg/compiler/lib/src/cps_ir/cps_fragment.dart
index 9bdb9ea..a9190dd 100644
--- a/pkg/compiler/lib/src/cps_ir/cps_fragment.dart
+++ b/pkg/compiler/lib/src/cps_ir/cps_fragment.dart
@@ -33,19 +33,19 @@
///
/// If `condition` is true then invoke `cont1`, else `cont2`.
///
-/// cps.ifTrue(condition).invokeContinuation(cont1, []);
+/// cps.ifTruthy(condition).invokeContinuation(cont1, []);
/// cps.invokeContinuation(cont2, []);
///
/// If `condition` is true then invoke `cont` with a bound primitive:
///
-/// CpsFragment branch = cps.ifTrue(condition);
+/// CpsFragment branch = cps.ifTruthy(condition);
/// branch.invokeContinuation(cont, [branch.letPrim(arg)]);
///
/// Loop and call a method until it returns false:
///
/// Continuation loop = cps.beginLoop();
/// var result = cps.invokeMethod(receiver, selector, ...);
-/// cps.ifFalse(result).invokeContinuation(exit, []);
+/// cps.ifFalsy(result).invokeContinuation(exit, []);
/// cps.continueLoop(loop);
///
class CpsFragment {
@@ -198,11 +198,11 @@
/// Returns a new fragment for the 'then' branch.
///
/// The 'else' branch becomes the new hole.
- CpsFragment ifTrue(Primitive condition) {
+ CpsFragment ifTruthy(Primitive condition) {
Continuation trueCont = new Continuation(<Parameter>[]);
Continuation falseCont = new Continuation(<Parameter>[]);
put(new LetCont.two(trueCont, falseCont,
- new Branch(new IsTrue(condition), trueCont, falseCont)));
+ new Branch.loose(condition, trueCont, falseCont)));
context = falseCont;
return new CpsFragment(sourceInformation, trueCont);
}
@@ -212,11 +212,11 @@
/// Returns a new fragment for the 'else' branch.
///
/// The 'then' branch becomes the new hole.
- CpsFragment ifFalse(Primitive condition) {
+ CpsFragment ifFalsy(Primitive condition) {
Continuation trueCont = new Continuation(<Parameter>[]);
Continuation falseCont = new Continuation(<Parameter>[]);
put(new LetCont.two(trueCont, falseCont,
- new Branch(new IsTrue(condition), trueCont, falseCont)));
+ new Branch.loose(condition, trueCont, falseCont)));
context = trueCont;
return new CpsFragment(sourceInformation, falseCont);
}
diff --git a/pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart b/pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart
index f97d15e..e4cb699 100644
--- a/pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart
+++ b/pkg/compiler/lib/src/cps_ir/cps_ir_builder.dart
@@ -773,9 +773,9 @@
elseContinuation.body = elseBuilder._root;
add(new ir.LetCont(join.continuation,
new ir.LetCont.two(thenContinuation, elseContinuation,
- new ir.Branch(new ir.IsTrue(condition),
- thenContinuation,
- elseContinuation))));
+ new ir.Branch.strict(condition,
+ thenContinuation,
+ elseContinuation))));
environment = join.environment;
return environment.discard(1);
}
@@ -1117,9 +1117,9 @@
ir.Expression result =
new ir.LetCont.many(arms,
- new ir.Branch(new ir.IsTrue(condition),
- thenContinuation,
- elseContinuation));
+ new ir.Branch.strict(condition,
+ thenContinuation,
+ elseContinuation));
JumpCollector join; // Null if there is no join.
if (thenBuilder.isOpen && elseBuilder.isOpen) {
@@ -1288,9 +1288,9 @@
// be filled by LetCont.plug.
ir.LetCont branch =
new ir.LetCont.two(exitContinuation, bodyContinuation,
- new ir.Branch(new ir.IsTrue(condition),
- bodyContinuation,
- exitContinuation));
+ new ir.Branch.strict(condition,
+ bodyContinuation,
+ exitContinuation));
// If there are breaks in the body, then there must be a join-point
// continuation for the normal exit and the breaks. Otherwise, the
// successor is translated in the hole in the exit continuation.
@@ -1449,9 +1449,9 @@
// be filled by LetCont.plug.
ir.LetCont branch =
new ir.LetCont.two(exitContinuation, bodyContinuation,
- new ir.Branch(new ir.IsTrue(condition),
- bodyContinuation,
- exitContinuation));
+ new ir.Branch.strict(condition,
+ bodyContinuation,
+ exitContinuation));
// If there are breaks in the body, then there must be a join-point
// continuation for the normal exit and the breaks. Otherwise, the
// successor is translated in the hole in the exit continuation.
@@ -1524,9 +1524,9 @@
// be filled by LetCont.plug.
ir.LetCont branch =
new ir.LetCont.two(exitContinuation, bodyContinuation,
- new ir.Branch(new ir.IsTrue(condition),
- bodyContinuation,
- exitContinuation));
+ new ir.Branch.strict(condition,
+ bodyContinuation,
+ exitContinuation));
// If there are breaks in the body, then there must be a join-point
// continuation for the normal exit and the breaks. Otherwise, the
// successor is translated in the hole in the exit continuation.
@@ -1610,9 +1610,9 @@
continueBuilder.add(
new ir.LetCont.two(exitContinuation, repeatContinuation,
- new ir.Branch(new ir.IsTrue(condition),
- repeatContinuation,
- exitContinuation)));
+ new ir.Branch.strict(condition,
+ repeatContinuation,
+ exitContinuation)));
continueCollector.continuation.body = continueBuilder._root;
// Construct the loop continuation (i.e., the body and condition).
@@ -1676,9 +1676,9 @@
// else continuation first.
casesBuilder.add(
new ir.LetCont.two(elseContinuation, thenContinuation,
- new ir.Branch(new ir.IsTrue(condition),
- thenContinuation,
- elseContinuation)));
+ new ir.Branch.strict(condition,
+ thenContinuation,
+ elseContinuation)));
}
if (defaultCase != null) {
@@ -1883,9 +1883,9 @@
clause.type,
isTypeTest: true);
checkBuilder.add(new ir.LetCont.two(thenContinuation, elseContinuation,
- new ir.Branch(new ir.IsTrue(typeMatches),
- thenContinuation,
- elseContinuation)));
+ new ir.Branch.strict(typeMatches,
+ thenContinuation,
+ elseContinuation)));
catchBody = checkBuilder._root;
}
builder.add(catchBody);
@@ -2232,9 +2232,9 @@
add(new ir.LetCont(joinContinuation,
new ir.LetCont.two(thenContinuation, elseContinuation,
- new ir.Branch(new ir.IsTrue(condition),
- thenContinuation,
- elseContinuation))));
+ new ir.Branch.strict(condition,
+ thenContinuation,
+ elseContinuation))));
return resultParameter;
}
@@ -2292,9 +2292,9 @@
// The right subexpression has two continuations.
rightBuilder.add(
new ir.LetCont.two(rightTrueContinuation, rightFalseContinuation,
- new ir.Branch(new ir.IsTrue(rightValue),
- rightTrueContinuation,
- rightFalseContinuation)));
+ new ir.Branch.strict(rightValue,
+ rightTrueContinuation,
+ rightFalseContinuation)));
// Depending on the operator, the left subexpression's continuations are
// either the right subexpression or an invocation of the join-point
// continuation.
@@ -2308,9 +2308,9 @@
add(new ir.LetCont(join.continuation,
new ir.LetCont.two(leftTrueContinuation, leftFalseContinuation,
- new ir.Branch(new ir.IsTrue(leftValue),
- leftTrueContinuation,
- leftFalseContinuation))));
+ new ir.Branch.strict(leftValue,
+ leftTrueContinuation,
+ leftFalseContinuation))));
environment = join.environment;
return environment.discard(1);
}
diff --git a/pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart b/pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart
index 24938d4..b685c45 100644
--- a/pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart
+++ b/pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart
@@ -654,29 +654,36 @@
accept(Visitor visitor) => visitor.visitInvokeContinuation(this);
}
-/// The base class of things which can be tested and branched on.
-abstract class Condition extends Node {
-}
-
-class IsTrue extends Condition {
- final Reference<Primitive> value;
-
- IsTrue(Primitive val) : value = new Reference<Primitive>(val);
-
- accept(Visitor visitor) => visitor.visitIsTrue(this);
-}
-
/// Choose between a pair of continuations based on a condition value.
///
/// The two continuations must not declare any parameters.
class Branch extends TailExpression {
- final Condition condition;
+ final Reference<Primitive> condition;
final Reference<Continuation> trueContinuation;
final Reference<Continuation> falseContinuation;
- Branch(this.condition, Continuation trueCont, Continuation falseCont)
- : trueContinuation = new Reference<Continuation>(trueCont),
- falseContinuation = new Reference<Continuation>(falseCont);
+ /// If true, only the value `true` satisfies the condition. Otherwise, any
+ /// truthy value satisfies the check.
+ ///
+ /// Non-strict checks are preferable when the condition is known to be a
+ /// boolean.
+ bool isStrictCheck;
+
+ Branch.strict(Primitive condition,
+ Continuation trueCont,
+ Continuation falseCont)
+ : this.condition = new Reference<Primitive>(condition),
+ trueContinuation = new Reference<Continuation>(trueCont),
+ falseContinuation = new Reference<Continuation>(falseCont),
+ isStrictCheck = true;
+
+ Branch.loose(Primitive condition,
+ Continuation trueCont,
+ Continuation falseCont)
+ : this.condition = new Reference<Primitive>(condition),
+ trueContinuation = new Reference<Continuation>(trueCont),
+ falseContinuation = new Reference<Continuation>(falseCont),
+ this.isStrictCheck = false;
accept(Visitor visitor) => visitor.visitBranch(this);
}
@@ -716,6 +723,8 @@
bool get isSafeForElimination => objectIsNotNull;
bool get isSafeForReordering => false;
+
+ toString() => 'GetField($field)';
}
/// Get the length of a string or native list.
@@ -865,6 +874,8 @@
bool get isSafeForElimination => true;
bool get isSafeForReordering => true;
+
+ toString() => 'CreateInstance($classElement)';
}
class Interceptor extends Primitive {
@@ -1191,9 +1202,6 @@
T visitGetIndex(GetIndex node);
T visitSetIndex(SetIndex node);
- // Conditions.
- T visitIsTrue(IsTrue node);
-
// Support for literal foreign code.
T visitForeignCode(ForeignCode node);
}
@@ -1201,9 +1209,6 @@
/// Visits all non-recursive children of a CPS term, i.e. anything
/// not of type [Expression] or [Continuation].
///
-/// Note that the non-recursive nodes can contain other nodes inside of them,
-/// e.g. [Branch] contains an [IsTrue] which contains a [Reference].
-///
/// The `process*` methods are called in pre-order for every node visited.
/// These can be overridden without disrupting the visitor traversal.
class LeafVisitor implements Visitor {
@@ -1300,7 +1305,7 @@
processBranch(node);
processReference(node.trueContinuation);
processReference(node.falseContinuation);
- visit(node.condition);
+ processReference(node.condition);
}
processTypeCast(TypeCast node) {}
@@ -1379,12 +1384,6 @@
node.parameters.forEach(visitParameter);
}
- processIsTrue(IsTrue node) {}
- visitIsTrue(IsTrue node) {
- processIsTrue(node);
- processReference(node.value);
- }
-
processInterceptor(Interceptor node) {}
visitInterceptor(Interceptor node) {
processInterceptor(node);
diff --git a/pkg/compiler/lib/src/cps_ir/cps_ir_nodes_sexpr.dart b/pkg/compiler/lib/src/cps_ir/cps_ir_nodes_sexpr.dart
index a04fb4e..988ee69 100644
--- a/pkg/compiler/lib/src/cps_ir/cps_ir_nodes_sexpr.dart
+++ b/pkg/compiler/lib/src/cps_ir/cps_ir_nodes_sexpr.dart
@@ -192,10 +192,11 @@
}
String visitBranch(Branch node) {
- String condition = visit(node.condition);
+ String condition = access(node.condition);
String trueCont = access(node.trueContinuation);
String falseCont = access(node.falseContinuation);
- return '$indentation(Branch $condition $trueCont $falseCont)';
+ String strict = node.isStrictCheck ? 'Strict' : 'NonStrict';
+ return '$indentation(Branch $condition $trueCont $falseCont $strict)';
}
String visitUnreachable(Unreachable node) {
@@ -251,11 +252,6 @@
return '(LiteralMap ($keys) ($values))';
}
- String visitIsTrue(IsTrue node) {
- String value = access(node.value);
- return '(IsTrue $value)';
- }
-
String visitSetField(SetField node) {
String object = access(node.object);
String field = node.field.name;
diff --git a/pkg/compiler/lib/src/cps_ir/cps_ir_tracer.dart b/pkg/compiler/lib/src/cps_ir/cps_ir_tracer.dart
index c802aa6..ecbe343 100644
--- a/pkg/compiler/lib/src/cps_ir/cps_ir_tracer.dart
+++ b/pkg/compiler/lib/src/cps_ir/cps_ir_tracer.dart
@@ -227,10 +227,11 @@
visitBranch(cps_ir.Branch node) {
String dummy = names.name(node);
- String condition = visit(node.condition);
+ String condition = formatReference(node.condition);
String trueCont = formatReference(node.trueContinuation);
String falseCont = formatReference(node.falseContinuation);
- printStmt(dummy, "Branch $condition ($trueCont, $falseCont)");
+ String strict = node.isStrictCheck ? "Strict" : "NonStrict";
+ printStmt(dummy, "Branch $condition ($trueCont, $falseCont) $strict");
}
visitSetMutable(cps_ir.SetMutable node) {
@@ -266,10 +267,6 @@
return "Continuation ${names.name(node)}";
}
- visitIsTrue(cps_ir.IsTrue node) {
- return "IsTrue(${names.name(node.value.definition)})";
- }
-
visitSetField(cps_ir.SetField node) {
String object = formatReference(node.object);
String field = node.field.name;
@@ -607,10 +604,6 @@
unexpectedNode(node);
}
- visitIsTrue(cps_ir.IsTrue node) {
- unexpectedNode(node);
- }
-
visitInterceptor(cps_ir.Interceptor node) {
unexpectedNode(node);
}
diff --git a/pkg/compiler/lib/src/cps_ir/optimizers.dart b/pkg/compiler/lib/src/cps_ir/optimizers.dart
index 9a6d2a7..11c9fae 100644
--- a/pkg/compiler/lib/src/cps_ir/optimizers.dart
+++ b/pkg/compiler/lib/src/cps_ir/optimizers.dart
@@ -8,6 +8,7 @@
import '../constants/values.dart';
export 'type_propagation.dart' show TypePropagator;
+export 'scalar_replacement.dart' show ScalarReplacer;
export 'redundant_phi.dart' show RedundantPhiEliminator;
export 'redundant_join.dart' show RedundantJoinEliminator;
export 'shrinking_reductions.dart' show ShrinkingReducer, ParentVisitor;
diff --git a/pkg/compiler/lib/src/cps_ir/redundant_join.dart b/pkg/compiler/lib/src/cps_ir/redundant_join.dart
index 2a1a584..4acb2ef 100644
--- a/pkg/compiler/lib/src/cps_ir/redundant_join.dart
+++ b/pkg/compiler/lib/src/cps_ir/redundant_join.dart
@@ -94,8 +94,7 @@
// enclosing continuation.
// Note: Do not use the parent pointer for this check, because parameters
// are temporarily shared between different continuations during this pass.
- IsTrue isTrue = branch.condition;
- Primitive condition = isTrue.value.definition;
+ Primitive condition = branch.condition.definition;
int parameterIndex = branchCont.parameters.indexOf(condition);
if (parameterIndex == -1) return;
diff --git a/pkg/compiler/lib/src/cps_ir/scalar_replacement.dart b/pkg/compiler/lib/src/cps_ir/scalar_replacement.dart
new file mode 100644
index 0000000..114d8a0
--- /dev/null
+++ b/pkg/compiler/lib/src/cps_ir/scalar_replacement.dart
@@ -0,0 +1,251 @@
+// Copyright (c) 2015, 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 'optimizers.dart';
+
+import 'dart:collection' show Queue;
+
+import '../closure.dart' show
+ ClosureClassElement, Identifiers;
+import '../common/names.dart' show
+ Selectors, Identifiers;
+import '../compiler.dart' as dart2js show
+ Compiler;
+import '../constants/constant_system.dart';
+import '../constants/values.dart';
+import '../dart_types.dart' as types;
+import '../diagnostics/invariant.dart' as dart2js show
+ InternalErrorFunction;
+import '../elements/elements.dart';
+import '../io/source_information.dart' show SourceInformation;
+import '../resolution/access_semantics.dart';
+import '../resolution/operators.dart';
+import '../resolution/send_structure.dart';
+import '../tree/tree.dart' as ast;
+import '../types/types.dart';
+import '../types/constants.dart' show computeTypeMask;
+import '../universe/universe.dart';
+import '../world.dart' show World;
+import 'cps_fragment.dart';
+import 'cps_ir_nodes.dart';
+import 'cps_ir_nodes_sexpr.dart' show SExpressionStringifier;
+
+/**
+ * Replaces aggregates with a set of local values. Performs inlining of
+ * single-use closures to generate more replacable aggregates.
+ */
+class ScalarReplacer extends Pass {
+ String get passName => 'Scalar replacement';
+
+ final dart2js.InternalErrorFunction _internalError;
+
+ ScalarReplacer(dart2js.Compiler compiler)
+ : _internalError = compiler.internalError;
+
+ @override
+ void rewrite(FunctionDefinition root) {
+ // Set all parent pointers.
+ new ParentVisitor().visit(root);
+ ScalarReplacementVisitor analyzer =
+ new ScalarReplacementVisitor(_internalError);
+ analyzer.analyze(root);
+ analyzer.process();
+ }
+}
+
+/**
+ * Do scalar replacement of aggregates on instances. Since scalar replacement
+ * can create new candidiates, iterate until all scalar replacements are done.
+ */
+class ScalarReplacementVisitor extends RecursiveVisitor {
+
+ final dart2js.InternalErrorFunction internalError;
+ ScalarReplacementRemovalVisitor removalVisitor;
+
+ Primitive _current = null;
+ Set<Primitive> _allocations = new Set<Primitive>();
+ Queue<Primitive> _queue = new Queue<Primitive>();
+
+ ScalarReplacementVisitor(this.internalError) {
+ removalVisitor = new ScalarReplacementRemovalVisitor(this);
+ }
+
+ void analyze(FunctionDefinition root) {
+ visit(root);
+ }
+
+ void process() {
+ while (_queue.isNotEmpty) {
+ Primitive allocation = _queue.removeFirst();
+ _allocations.remove(allocation);
+ _current = allocation;
+ tryScalarReplacement(allocation);
+ }
+ }
+
+ void tryScalarReplacement(Primitive allocation) {
+
+ // We can do scalar replacement of an aggregate if all uses of an allocation
+ // are reads or writes.
+ for (Reference ref = allocation.firstRef; ref != null; ref = ref.next) {
+ Node use = ref.parent;
+ if (use is GetField) continue;
+ if (use is SetField && use.object == ref) continue;
+ return;
+ }
+
+ Set<FieldElement> reads = new Set<FieldElement>();
+ Set<FieldElement> writes = new Set<FieldElement>();
+ for (Reference ref = allocation.firstRef; ref != null; ref = ref.next) {
+ Node use = ref.parent;
+ if (use is GetField) {
+ reads.add(use.field);
+ } else if (use is SetField) {
+ writes.add(use.field);
+ } else {
+ assert(false);
+ }
+ }
+
+ // Find the initial values of the fields. A CreateBox has no initial
+ // values. CreateInstance has initial values in the order of the fields.
+ Map<FieldElement, Primitive> fieldInitialValues =
+ <FieldElement, Primitive>{};
+ if (allocation is CreateInstance) {
+ int i = 0;
+ allocation.classElement.forEachInstanceField(
+ (ClassElement enclosingClass, FieldElement field) {
+ Primitive argument = allocation.arguments[i++].definition;
+ fieldInitialValues[field] = argument;
+ });
+ }
+
+ // Create [MutableVariable]s for each written field. Initialize the
+ // MutableVariable with the value from the allocator, or initialize with a
+ // `null` constant if there is not initial value.
+ Map<FieldElement, MutableVariable> cells =
+ <FieldElement, MutableVariable>{};
+ InteriorNode insertionPoint = allocation.parent; // LetPrim
+ for (FieldElement field in writes) {
+ MutableVariable variable = new MutableVariable(field);
+ cells[field] = variable;
+ Primitive initialValue = fieldInitialValues[field];
+ if (initialValue == null) {
+ assert(allocation is CreateBox);
+ initialValue = new Constant(new NullConstantValue());
+ LetPrim let = new LetPrim(initialValue);
+ let.primitive.parent = let;
+ insertionPoint = insertAtBody(insertionPoint, let);
+ }
+ LetMutable let = new LetMutable(variable, initialValue);
+ let.value.parent = let;
+ insertionPoint = insertAtBody(insertionPoint, let);
+ }
+
+ // Replace references with MutableVariable operations or references to the
+ // field's value.
+ for (Reference ref = allocation.firstRef; ref != null; ref = ref.next) {
+ Node use = ref.parent;
+ if (use is GetField) {
+ GetField getField = use;
+ MutableVariable variable = cells[getField.field];
+ if (variable != null) {
+ GetMutable getter = new GetMutable(variable);
+ getter.variable.parent = getter;
+ getter.substituteFor(getField);
+ replacePrimitive(getField, getter);
+ deletePrimitive(getField);
+ } else {
+ Primitive value = fieldInitialValues[getField.field];
+ value.substituteFor(getField);
+ deleteLetPrimOf(getField);
+ }
+ } else if (use is SetField && use.object == ref) {
+ SetField setField = use;
+ MutableVariable variable = cells[setField.field];
+ Primitive value = setField.value.definition;
+ SetMutable setter = new SetMutable(variable, value);
+ setter.variable.parent = setter;
+ setter.value.parent = setter;
+ setter.substituteFor(setField);
+ replacePrimitive(setField, setter);
+ deletePrimitive(setField);
+ } else {
+ assert(false);
+ }
+ }
+
+ // Delete [allocation] since that might 'free' another scalar replacement
+ // candidate by deleting the last non-field-access.
+ deleteLetPrimOf(allocation);
+ }
+
+ InteriorNode insertAtBody(
+ InteriorNode insertionPoint, InteriorExpression let) {
+ let.parent = insertionPoint;
+ let.body = insertionPoint.body;
+ let.body.parent = let;
+ insertionPoint.body = let;
+ return let;
+ }
+
+ /// Replaces [old] with [primitive] in [old]'s parent [LetPrim].
+ void replacePrimitive(Primitive old, Primitive primitive) {
+ LetPrim letPrim = old.parent;
+ letPrim.primitive = primitive;
+ }
+
+ void deleteLetPrimOf(Primitive primitive) {
+ assert(primitive.hasNoUses);
+ LetPrim letPrim = primitive.parent;
+ Node child = letPrim.body;
+ InteriorNode parent = letPrim.parent;
+ child.parent = parent;
+ parent.body = child;
+
+ deletePrimitive(primitive);
+ }
+
+ void deletePrimitive(Primitive primitive) {
+ assert(primitive.hasNoUses);
+ removalVisitor.visit(primitive);
+ }
+
+ void reconsider(Definition node) {
+ if (node is CreateInstance || node is CreateBox) {
+ if (node == _current) return;
+ enqueue(node);
+ }
+ }
+
+ void enqueue(Primitive node) {
+ assert(node is CreateInstance || node is CreateBox);
+ if (_allocations.contains(node)) return;
+ _allocations.add(node);
+ _queue.add(node);
+ }
+
+ // -------------------------- Visitor overrides ------------------------------
+ void visitCreateInstance(CreateInstance node) {
+ enqueue(node);
+ }
+
+ void visitCreateBox(CreateBox node) {
+ enqueue(node);
+ }
+}
+
+
+/// Visit a just-deleted subterm and unlink all [Reference]s in it. Reconsider
+/// allocations for scalar replacement.
+class ScalarReplacementRemovalVisitor extends RecursiveVisitor {
+ ScalarReplacementVisitor process;
+
+ ScalarReplacementRemovalVisitor(this.process);
+
+ processReference(Reference reference) {
+ process.reconsider(reference.definition);
+ reference.unlink();
+ }
+}
diff --git a/pkg/compiler/lib/src/cps_ir/shrinking_reductions.dart b/pkg/compiler/lib/src/cps_ir/shrinking_reductions.dart
index 1c85d15..011af0f 100644
--- a/pkg/compiler/lib/src/cps_ir/shrinking_reductions.dart
+++ b/pkg/compiler/lib/src/cps_ir/shrinking_reductions.dart
@@ -610,10 +610,6 @@
});
}
- processIsTrue(IsTrue node) {
- node.value.parent = node;
- }
-
processInterceptor(Interceptor node) {
node.input.parent = node;
}
diff --git a/pkg/compiler/lib/src/cps_ir/type_propagation.dart b/pkg/compiler/lib/src/cps_ir/type_propagation.dart
index 1cc1b97..3212f94 100644
--- a/pkg/compiler/lib/src/cps_ir/type_propagation.dart
+++ b/pkg/compiler/lib/src/cps_ir/type_propagation.dart
@@ -4,8 +4,10 @@
import 'optimizers.dart';
+import '../closure.dart' show
+ ClosureClassElement, Identifiers;
import '../common/names.dart' show
- Selectors;
+ Selectors, Identifiers;
import '../compiler.dart' as dart2js show
Compiler;
import '../constants/constant_system.dart';
@@ -27,6 +29,7 @@
import '../world.dart' show World;
import 'cps_fragment.dart';
import 'cps_ir_nodes.dart';
+import 'cps_ir_nodes_sexpr.dart' show SExpressionStringifier;
enum AbstractBool {
True, False, Maybe, Nothing
@@ -262,6 +265,11 @@
}
return AbstractBool.Maybe;
}
+
+ AbstractBool strictBoolify(TypeMask type) {
+ if (areDisjoint(type, boolType)) return AbstractBool.False;
+ return AbstractBool.Maybe;
+ }
}
class ConstantPropagationLattice {
@@ -534,6 +542,15 @@
return typeSystem.boolify(value.type);
}
+ /// Returns whether [value] is the value `true`.
+ AbstractBool strictBoolify(AbstractValue value) {
+ if (value.isNothing) return AbstractBool.Nothing;
+ if (value.isConstant) {
+ return value.constant.isTrue ? AbstractBool.True : AbstractBool.False;
+ }
+ return typeSystem.strictBoolify(value.type);
+ }
+
/// The possible return types of a method that may be targeted by
/// [typedSelector]. If the given selector is not a [TypedSelector], any
/// reachable method matching the selector may be targeted.
@@ -822,11 +839,17 @@
void visitBranch(Branch node) {
Continuation trueCont = node.trueContinuation.definition;
Continuation falseCont = node.falseContinuation.definition;
- IsTrue conditionNode = node.condition;
- Primitive condition = conditionNode.value.definition;
-
+ Primitive condition = node.condition.definition;
AbstractValue conditionValue = getValue(condition);
- AbstractBool boolifiedValue = lattice.boolify(conditionValue);
+
+ // Change to non-strict check if the condition is a boolean or null.
+ if (lattice.isDefinitelyBool(conditionValue, allowNull: true)) {
+ node.isStrictCheck = false;
+ }
+
+ AbstractBool boolifiedValue = node.isStrictCheck
+ ? lattice.strictBoolify(conditionValue)
+ : lattice.boolify(conditionValue);
if (boolifiedValue == AbstractBool.True) {
replaceSubtree(falseCont.body, new Unreachable());
@@ -856,12 +879,12 @@
// if (x == null) S1 else S2
// =>
// if (x) S2 else S1 (note the swapped branches)
- Branch branch = new Branch(new IsTrue(leftArg), falseCont, trueCont);
+ Branch branch = new Branch.loose(leftArg, falseCont, trueCont);
replaceSubtree(node, branch);
return;
} else if (left.isNullConstant &&
lattice.isDefinitelyNotNumStringBool(right)) {
- Branch branch = new Branch(new IsTrue(rightArg), falseCont, trueCont);
+ Branch branch = new Branch.loose(rightArg, falseCont, trueCont);
replaceSubtree(node, branch);
return;
} else if (right.isTrueConstant &&
@@ -870,12 +893,12 @@
// if (x == true) S1 else S2
// =>
// if (x) S1 else S2
- Branch branch = new Branch(new IsTrue(leftArg), trueCont, falseCont);
+ Branch branch = new Branch.loose(leftArg, trueCont, falseCont);
replaceSubtree(node, branch);
return;
} else if (left.isTrueConstant &&
lattice.isDefinitelyBool(right, allowNull: true)) {
- Branch branch = new Branch(new IsTrue(rightArg), trueCont, falseCont);
+ Branch branch = new Branch.loose(rightArg, trueCont, falseCont);
replaceSubtree(node, branch);
return;
}
@@ -1074,11 +1097,11 @@
Primitive isTooSmall = cps.applyBuiltin(
BuiltinOperator.NumLt,
<Primitive>[index, cps.makeZero()]);
- cps.ifTrue(isTooSmall).invokeContinuation(fail);
+ cps.ifTruthy(isTooSmall).invokeContinuation(fail);
Primitive isTooLarge = cps.applyBuiltin(
BuiltinOperator.NumGe,
<Primitive>[index, cps.letPrim(new GetLength(list))]);
- cps.ifTrue(isTooLarge).invokeContinuation(fail);
+ cps.ifTruthy(isTooLarge).invokeContinuation(fail);
cps.insideContinuation(fail).invokeStaticThrower(
backend.getThrowIndexOutOfBoundsError(),
<Primitive>[list, index]);
@@ -1097,7 +1120,7 @@
Primitive lengthChanged = cps.applyBuiltin(
BuiltinOperator.StrictNeq,
<Primitive>[originalLength, cps.letPrim(new GetLength(list))]);
- cps.ifTrue(lengthChanged).invokeStaticThrower(
+ cps.ifTruthy(lengthChanged).invokeStaticThrower(
backend.getThrowConcurrentModificationError(),
<Primitive>[list]);
return cps;
@@ -1405,7 +1428,7 @@
[cps.getMutable(index), cps.letPrim(new GetLength(list))]);
// Return false if there are no more.
- CpsFragment falseBranch = cps.ifFalse(hasMore);
+ CpsFragment falseBranch = cps.ifFalsy(hasMore);
falseBranch
..setMutable(current, falseBranch.makeNull())
..invokeContinuation(useCont, [falseBranch.makeFalse()]);
@@ -1574,6 +1597,70 @@
return false;
}
+ /// Inlines a single-use closure if it leaves the closure object with only
+ /// field accesses. This is optimized later by [ScalarReplacer].
+ bool specializeSingleUseClosureCall(InvokeMethod node) {
+ Selector call = node.selector;
+ if (!call.isClosureCall) return false;
+
+ assert(!isInterceptedSelector(call));
+ assert(call.argumentCount == node.arguments.length);
+
+ Primitive receiver = node.receiver.definition;
+ if (receiver is !CreateInstance) return false;
+ CreateInstance createInstance = receiver;
+ if (!createInstance.hasExactlyOneUse) return false;
+
+ // Inline only closures. This avoids inlining the 'call' method of a class
+ // that has many allocation sites.
+ if (createInstance.classElement is !ClosureClassElement) return false;
+
+ ClosureClassElement closureClassElement = createInstance.classElement;
+ Element element = closureClassElement.localLookup(Identifiers.call);
+
+ if (element == null || !element.isFunction) return false;
+ FunctionElement functionElement = element;
+ if (functionElement.asyncMarker != AsyncMarker.SYNC) return false;
+
+ if (!call.signatureApplies(functionElement)) return false;
+ // Inline only for exact match.
+ // TODO(sra): Handle call with defaulted arguments.
+ Selector targetSelector = new Selector.fromElement(functionElement);
+ if (call.callStructure != targetSelector.callStructure) return false;
+
+ FunctionDefinition target =
+ functionCompiler.compileToCpsIR(functionElement);
+
+ // Accesses to closed-over values are field access primitives. We we don't
+ // inline if there are other uses of 'this' since that could be an escape or
+ // a recursive call.
+ for (Reference ref = target.thisParameter.firstRef;
+ ref != null;
+ ref = ref.next) {
+ Node use = ref.parent;
+ if (use is GetField) continue;
+ // Closures do not currently have writable fields, but closure conversion
+ // could esily be changed to allocate some cells in a closure object.
+ if (use is SetField && ref == use.object) continue;
+ return false;
+ }
+
+ // Don't inline if [target] contains try-catch or try-finally. JavaScript
+ // engines typically do poor optimization of the entire function containing
+ // the 'try'.
+ if (ContainsTry.analyze(target)) return false;
+
+ node.receiver.definition.substituteFor(target.thisParameter);
+ for (int i = 0; i < node.arguments.length; ++i) {
+ node.arguments[i].definition.substituteFor(target.parameters[i]);
+ }
+ node.continuation.definition.substituteFor(target.returnContinuation);
+
+ replaceSubtree(node, target.body);
+ push(target.body);
+ return true;
+ }
+
/// Side-effect free expressions with constant results are be replaced by:
///
/// (LetPrim p = constant (InvokeContinuation k p)).
@@ -1598,6 +1685,7 @@
if (specializeFieldAccess(node)) return;
if (specializeIndexableAccess(node)) return;
if (specializeArrayAccess(node)) return;
+ if (specializeSingleUseClosureCall(node)) return;
if (specializeClosureCall(node)) return;
AbstractValue receiver = getValue(node.receiver.definition);
@@ -2415,9 +2503,10 @@
}
void visitBranch(Branch node) {
- IsTrue isTrue = node.condition;
- AbstractValue conditionCell = getValue(isTrue.value.definition);
- AbstractBool boolifiedValue = lattice.boolify(conditionCell);
+ AbstractValue conditionCell = getValue(node.condition.definition);
+ AbstractBool boolifiedValue = node.isStrictCheck
+ ? lattice.strictBoolify(conditionCell)
+ : lattice.boolify(conditionCell);
switch (boolifiedValue) {
case AbstractBool.Nothing:
break;
@@ -2545,11 +2634,6 @@
setValue(returnValue, nonConstant(typeSystem.getFieldType(node.element)));
}
- void visitIsTrue(IsTrue node) {
- Branch branch = node.parent;
- visitBranch(branch);
- }
-
void visitInterceptor(Interceptor node) {
push(node.input.definition);
AbstractValue value = getValue(node.input.definition);
@@ -2753,3 +2837,25 @@
values.remove(node.variable);
}
}
+
+
+class ContainsTry extends RecursiveVisitor {
+ bool _found = false;
+ ContainsTry._();
+
+ /// Scans [root] for evidence of try-catch and try-finally.
+ static bool analyze(Node root) {
+ ContainsTry visitor = new ContainsTry._();
+ visitor.visit(root);
+ return visitor._found;
+ }
+
+ visit(Node node) {
+ if (_found) return; // Early exit if we know the answer.
+ super.visit(node);
+ }
+
+ processLetHandler(LetHandler node) {
+ _found = true;
+ }
+}
diff --git a/pkg/compiler/lib/src/dart_backend/backend_ast_to_frontend_ast.dart b/pkg/compiler/lib/src/dart_backend/backend_ast_to_frontend_ast.dart
index a004418..d215de3 100644
--- a/pkg/compiler/lib/src/dart_backend/backend_ast_to_frontend_ast.dart
+++ b/pkg/compiler/lib/src/dart_backend/backend_ast_to_frontend_ast.dart
@@ -11,8 +11,11 @@
import '../elements/elements.dart' as elements;
import '../resolution/tree_elements.dart' show
TreeElementMapping;
+import '../tokens/token.dart';
+import '../tokens/token_constants.dart';
+import '../tokens/precedence.dart';
+import '../tokens/precedence_constants.dart';
import '../tree/tree.dart' as tree;
-import '../scanner/scannerlib.dart';
import '../util/util.dart';
import 'backend_ast_nodes.dart';
import 'backend_ast_emitter.dart' show TypeGenerator;
diff --git a/pkg/compiler/lib/src/dart_backend/dart_backend.dart b/pkg/compiler/lib/src/dart_backend/dart_backend.dart
index 6757353..2e754f8 100644
--- a/pkg/compiler/lib/src/dart_backend/dart_backend.dart
+++ b/pkg/compiler/lib/src/dart_backend/dart_backend.dart
@@ -49,13 +49,8 @@
import '../resolution/tree_elements.dart' show
TreeElements,
TreeElementMapping;
-import '../scanner/scannerlib.dart' show
- StringToken,
- Keyword,
- OPEN_PAREN_INFO,
- CLOSE_PAREN_INFO,
- SEMICOLON_INFO,
- IDENTIFIER_INFO;
+import '../tokens/keyword.dart' show
+ Keyword;
import '../tree/tree.dart';
import '../universe/universe.dart' show
Selector,
diff --git a/pkg/compiler/lib/src/diagnostics/messages.dart b/pkg/compiler/lib/src/diagnostics/messages.dart
index b8f6d3c..99aa824 100644
--- a/pkg/compiler/lib/src/diagnostics/messages.dart
+++ b/pkg/compiler/lib/src/diagnostics/messages.dart
@@ -63,11 +63,14 @@
library dart2js.messages;
+import '../tokens/token.dart' show
+ ErrorToken,
+ Token;
+
import 'invariant.dart' show
invariant;
import 'spannable.dart' show
CURRENT_ELEMENT_SPANNABLE;
-import '../scanner/scannerlib.dart';
const DONT_KNOW_HOW_TO_FIX = "Computer says no!";
diff --git a/pkg/compiler/lib/src/diagnostics/source_span.dart b/pkg/compiler/lib/src/diagnostics/source_span.dart
index 9fe080c..95c3c75 100644
--- a/pkg/compiler/lib/src/diagnostics/source_span.dart
+++ b/pkg/compiler/lib/src/diagnostics/source_span.dart
@@ -4,7 +4,7 @@
library dart2js.diagnostics.source_span;
-import '../scanner/scannerlib.dart' show
+import '../tokens/token.dart' show
Token;
import '../tree/tree.dart' show
Node;
diff --git a/pkg/compiler/lib/src/elements/elements.dart b/pkg/compiler/lib/src/elements/elements.dart
index 78c8b45..219349b 100644
--- a/pkg/compiler/lib/src/elements/elements.dart
+++ b/pkg/compiler/lib/src/elements/elements.dart
@@ -21,11 +21,11 @@
import '../resolution/tree_elements.dart' show
TreeElements;
import '../ordered_typeset.dart' show OrderedTypeSet;
-import '../scanner/scannerlib.dart' show
+import '../script.dart';
+import '../tokens/token.dart' show
Token,
isUserDefinableOperator,
isMinusOperator;
-import '../script.dart';
import '../tree/tree.dart';
import '../util/characters.dart' show $_;
import '../util/util.dart';
diff --git a/pkg/compiler/lib/src/elements/modelx.dart b/pkg/compiler/lib/src/elements/modelx.dart
index 33410f7..6574231 100644
--- a/pkg/compiler/lib/src/elements/modelx.dart
+++ b/pkg/compiler/lib/src/elements/modelx.dart
@@ -35,11 +35,12 @@
TreeElements;
import '../resolution/typedefs.dart' show
TypedefCyclicVisitor;
-import '../scanner/scannerlib.dart' show
- EOF_TOKEN,
+import '../script.dart';
+import '../tokens/token.dart' show
ErrorToken,
Token;
-import '../script.dart';
+import '../tokens/token_constants.dart' as Tokens show
+ EOF_TOKEN;
import '../tree/tree.dart';
import '../util/util.dart';
@@ -138,7 +139,7 @@
String needle = isConstructor ? enclosingClassName : name;
// The unary '-' operator has a special element name (specified).
if (needle == 'unary-') needle = '-';
- for (Token t = token; EOF_TOKEN != t.kind; t = t.next) {
+ for (Token t = token; Tokens.EOF_TOKEN != t.kind; t = t.next) {
if (t is !ErrorToken && needle == t.value) return t;
}
return token;
@@ -2325,7 +2326,11 @@
bool get isEnumClass => false;
InterfaceType computeType(Compiler compiler) {
- if (thisTypeCache == null) {
+ if (isPatch) {
+ origin.computeType(compiler);
+ thisTypeCache = origin.thisType;
+ rawTypeCache = origin.rawType;
+ } else if (thisTypeCache == null) {
computeThisAndRawType(compiler, computeTypeParameters(compiler));
}
return thisTypeCache;
diff --git a/pkg/compiler/lib/src/enqueue.dart b/pkg/compiler/lib/src/enqueue.dart
index 2656ee9..6ad5177 100644
--- a/pkg/compiler/lib/src/enqueue.dart
+++ b/pkg/compiler/lib/src/enqueue.dart
@@ -53,6 +53,8 @@
ResolverVisitor;
import 'tree/tree.dart' show
Send;
+import 'types/types.dart' show
+ TypeMaskStrategy;
import 'universe/universe.dart';
import 'util/util.dart' show
Link,
@@ -122,7 +124,7 @@
= new Map<String, Set<Element>>();
final Set<ClassElement> _processedClasses = new Set<ClassElement>();
Set<ClassElement> recentClasses = new Setlet<ClassElement>();
- final Universe universe = new Universe();
+ final Universe universe = new Universe(const TypeMaskStrategy());
static final TRACE_MIRROR_ENQUEUING =
const bool.fromEnvironment("TRACE_MIRROR_ENQUEUING");
diff --git a/pkg/compiler/lib/src/io/start_end_information.dart b/pkg/compiler/lib/src/io/start_end_information.dart
index 6e0d558..794aa7a 100644
--- a/pkg/compiler/lib/src/io/start_end_information.dart
+++ b/pkg/compiler/lib/src/io/start_end_information.dart
@@ -17,7 +17,7 @@
LocalElement;
import '../js/js.dart' as js;
import '../js/js_source_mapping.dart';
-import '../scanner/scannerlib.dart' show Token;
+import '../tokens/token.dart' show Token;
import '../tree/tree.dart' show Node, Send;
import 'source_file.dart';
diff --git a/pkg/compiler/lib/src/js_backend/backend.dart b/pkg/compiler/lib/src/js_backend/backend.dart
index ce801a9..f8ba241 100644
--- a/pkg/compiler/lib/src/js_backend/backend.dart
+++ b/pkg/compiler/lib/src/js_backend/backend.dart
@@ -233,6 +233,8 @@
new Uri(scheme: 'dart', path: '_js_embedded_names');
static final Uri DART_ISOLATE_HELPER =
new Uri(scheme: 'dart', path: '_isolate_helper');
+ static final Uri PACKAGE_LOOKUP_MAP =
+ new Uri(scheme: 'package', path: 'lookup_map/lookup_map.dart');
static const String INVOKE_ON = '_getCachedInvocation';
static const String START_ROOT_ISOLATE = 'startRootIsolate';
@@ -608,6 +610,9 @@
/// constructors for custom elements.
CustomElementsAnalysis customElementsAnalysis;
+ /// Codegen support for tree-shaking entries of `LookupMap`.
+ LookupMapAnalysis lookupMapAnalysis;
+
/// Support for classifying `noSuchMethod` implementations.
NoSuchMethodRegistry noSuchMethodRegistry;
@@ -641,6 +646,7 @@
compiler, namer, generateSourceMap, useStartupEmitter);
typeVariableHandler = new TypeVariableHandler(compiler);
customElementsAnalysis = new CustomElementsAnalysis(this);
+ lookupMapAnalysis = new LookupMapAnalysis(this);
noSuchMethodRegistry = new NoSuchMethodRegistry(this);
constantCompilerTask = new JavaScriptConstantTask(compiler);
resolutionCallbacks = new JavaScriptResolutionCallbacks(this);
@@ -949,11 +955,23 @@
}
}
- void registerCompileTimeConstant(ConstantValue constant, Registry registry) {
+ void registerCompileTimeConstant(ConstantValue constant, Registry registry,
+ {bool addForEmission: true}) {
registerCompileTimeConstantInternal(constant, registry);
- for (ConstantValue dependency in constant.getDependencies()) {
- registerCompileTimeConstant(dependency, registry);
+
+ if (!registry.isForResolution &&
+ lookupMapAnalysis.isLookupMap(constant)) {
+ // Note: internally, this registration will temporarily remove the
+ // constant dependencies and add them later on-demand.
+ lookupMapAnalysis.registerLookupMapReference(constant);
}
+
+ for (ConstantValue dependency in constant.getDependencies()) {
+ registerCompileTimeConstant(dependency, registry,
+ addForEmission: false);
+ }
+
+ if (addForEmission) constants.addCompileTimeConstantForEmission(constant);
}
void registerCompileTimeConstantInternal(ConstantValue constant,
@@ -971,6 +989,11 @@
} else if (constant.isType) {
enqueueInResolution(getCreateRuntimeType(), registry);
registry.registerInstantiation(typeImplementation.rawType);
+ TypeConstantValue typeConstant = constant;
+ DartType representedType = typeConstant.representedType;
+ if (representedType != const DynamicType()) {
+ lookupMapAnalysis.registerTypeConstant(representedType.element);
+ }
}
}
@@ -996,7 +1019,7 @@
Registry registry) {
assert(registry.isForResolution);
ConstantValue constant = constants.getConstantValueForMetadata(metadata);
- registerCompileTimeConstant(constant, registry);
+ registerCompileTimeConstant(constant, registry, addForEmission: false);
metadataConstants.add(new Dependency(constant, annotatedElement));
}
@@ -1129,6 +1152,13 @@
}
customElementsAnalysis.registerInstantiatedClass(cls, enqueuer);
+ if (!enqueuer.isResolutionQueue) {
+ lookupMapAnalysis.registerInstantiatedClass(cls);
+ }
+ }
+
+ void registerInstantiatedType(InterfaceType type, Registry registry) {
+ lookupMapAnalysis.registerInstantiatedType(type, registry);
}
void registerUseInterceptor(Enqueuer enqueuer) {
@@ -1438,7 +1468,6 @@
constants.getConstantValueForVariable(element);
if (initialValue != null) {
registerCompileTimeConstant(initialValue, work.registry);
- constants.addCompileTimeConstantForEmission(initialValue);
// We don't need to generate code for static or top-level
// variables. For instance variables, we may need to generate
// the checked setter.
@@ -2133,6 +2162,8 @@
jsBuiltinEnum = find(library, 'JsBuiltin');
} else if (uri == Uris.dart_html) {
htmlLibraryIsLoaded = true;
+ } else if (uri == PACKAGE_LOOKUP_MAP) {
+ lookupMapAnalysis.initRuntimeClass(find(library, 'LookupMap'));
}
annotations.onLibraryScanned(library);
});
@@ -2569,7 +2600,8 @@
registerCompileTimeConstant(
dependency.constant,
new CodegenRegistry(compiler,
- dependency.annotatedElement.analyzableElement.treeElements));
+ dependency.annotatedElement.analyzableElement.treeElements),
+ addForEmission: false);
}
metadataConstants.clear();
}
@@ -2577,6 +2609,8 @@
return true;
}
+ void onQueueClosed() => lookupMapAnalysis.onQueueClosed();
+
void onElementResolved(Element element, TreeElements elements) {
if ((element.isFunction || element.isGenerativeConstructor) &&
annotations.noInline(element)) {
diff --git a/pkg/compiler/lib/src/js_backend/codegen/task.dart b/pkg/compiler/lib/src/js_backend/codegen/task.dart
index 00cd5b9..16c882a 100644
--- a/pkg/compiler/lib/src/js_backend/codegen/task.dart
+++ b/pkg/compiler/lib/src/js_backend/codegen/task.dart
@@ -175,6 +175,7 @@
dumpTypedIR(cpsNode, typePropagator);
applyCpsPass(new LoopInvariantCodeMotion());
applyCpsPass(new ShareInterceptors());
+ applyCpsPass(new ScalarReplacer(compiler));
applyCpsPass(new ShrinkingReducer());
applyCpsPass(new MutableVariableEliminator());
applyCpsPass(new RedundantJoinEliminator());
diff --git a/pkg/compiler/lib/src/js_backend/codegen/unsugar.dart b/pkg/compiler/lib/src/js_backend/codegen/unsugar.dart
index 9913065..4fa59bb 100644
--- a/pkg/compiler/lib/src/js_backend/codegen/unsugar.dart
+++ b/pkg/compiler/lib/src/js_backend/codegen/unsugar.dart
@@ -31,7 +31,6 @@
/// special nodes that respect JavaScript behavior.
///
/// Performs the following rewrites:
-/// - Rewrite [IsTrue] in a [Branch] to do boolean conversion.
/// - Add interceptors at call sites that use interceptor calling convention.
/// - Add explicit receiver argument for methods that are called in interceptor
/// calling convention.
@@ -140,10 +139,7 @@
new LetCont.many(<Continuation>[returnFalse, originalBody],
new LetPrim(nullPrimitive,
new LetPrim(test,
- new Branch(
- new IsTrue(test),
- returnFalse,
- originalBody))));
+ new Branch.loose(test, returnFalse, originalBody))));
function.body = newBody;
}
@@ -281,41 +277,6 @@
node.receiver = new Reference<Primitive>(newReceiver);
}
- processBranch(Branch node) {
- // TODO(karlklose): implement the checked mode part of boolean conversion.
- InteriorNode parent = node.parent;
- IsTrue condition = node.condition;
-
- // Do not rewrite conditions that are foreign code.
- // It is redundant, and causes infinite recursion (if not optimized)
- // in the implementation of identical, which itself contains a condition.
- Primitive value = condition.value.definition;
- if (value is Parameter && value.parent is Continuation) {
- Continuation cont = value.parent;
- if (cont.hasExactlyOneUse && cont.firstRef.parent is ForeignCode) {
- ForeignCode foreign = cont.firstRef.parent;
- if (foreign.type.containsOnlyBool(_glue.classWorld)) {
- return;
- }
- }
- }
-
- Primitive t = trueConstant;
- Primitive i = new ApplyBuiltinOperator(
- BuiltinOperator.Identical,
- <Primitive>[condition.value.definition, t],
- condition.value.definition.sourceInformation);
- LetPrim newNode = new LetPrim(t,
- new LetPrim(i,
- new Branch(new IsTrue(i),
- node.trueContinuation.definition,
- node.falseContinuation.definition)));
- condition.value.unlink();
- node.trueContinuation.unlink();
- node.falseContinuation.unlink();
- parent.body = newNode;
- }
-
processInterceptor(Interceptor node) {
_glue.registerSpecializedGetInterceptor(node.interceptedClasses);
}
diff --git a/pkg/compiler/lib/src/js_backend/custom_elements_analysis.dart b/pkg/compiler/lib/src/js_backend/custom_elements_analysis.dart
index a13db64..1cd0c43 100644
--- a/pkg/compiler/lib/src/js_backend/custom_elements_analysis.dart
+++ b/pkg/compiler/lib/src/js_backend/custom_elements_analysis.dart
@@ -169,7 +169,6 @@
ConstantValue constant = makeTypeConstant(classElement);
backend.registerCompileTimeConstant(
constant, compiler.globalDependencies);
- backend.constants.addCompileTimeConstantForEmission(constant);
}
}
activeClasses.addAll(newActiveClasses);
diff --git a/pkg/compiler/lib/src/js_backend/js_backend.dart b/pkg/compiler/lib/src/js_backend/js_backend.dart
index 9f2e82e..af8df51 100644
--- a/pkg/compiler/lib/src/js_backend/js_backend.dart
+++ b/pkg/compiler/lib/src/js_backend/js_backend.dart
@@ -88,6 +88,7 @@
import 'codegen/task.dart';
import 'constant_system_javascript.dart';
import 'patch_resolver.dart';
+import 'lookup_map_analysis.dart' show LookupMapAnalysis;
part 'backend.dart';
part 'checked_mode_helpers.dart';
diff --git a/pkg/compiler/lib/src/js_backend/lookup_map_analysis.dart b/pkg/compiler/lib/src/js_backend/lookup_map_analysis.dart
new file mode 100644
index 0000000..9d44af1
--- /dev/null
+++ b/pkg/compiler/lib/src/js_backend/lookup_map_analysis.dart
@@ -0,0 +1,335 @@
+// Copyright (c) 2015, 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.
+
+/// Analysis to determine how to generate code for `LookupMap`s.
+library compiler.src.js_backend.lookup_map_analysis;
+
+import '../common/registry.dart' show Registry;
+import '../compiler.dart' show Compiler;
+import '../constants/values.dart' show
+ ConstantValue,
+ ConstructedConstantValue,
+ ListConstantValue,
+ NullConstantValue,
+ TypeConstantValue;
+import '../dart_types.dart' show DartType;
+import '../elements/elements.dart' show Elements, Element, ClassElement,
+ FieldElement, FunctionElement, FunctionSignature;
+import '../enqueue.dart' show Enqueuer;
+import 'js_backend.dart' show JavaScriptBackend;
+import '../dart_types.dart' show DynamicType, InterfaceType;
+
+/// An analysis and optimization to remove unused entries from a `LookupMap`.
+///
+/// `LookupMaps` are defined in `package:lookup_map/lookup_map.dart`. They are
+/// simple maps that contain constant expressions as keys, and that only support
+/// the lookup operation.
+///
+/// This analysis and optimization will tree-shake the contents of the maps by
+/// looking at the program and finding which keys are clearly unused. Not all
+/// constants can be approximated statically, so this optimization is limited to
+/// the following keys:
+///
+/// * Const expressions that can only be created via const constructors. This
+/// excludes primitives, strings, and any const type that overrides the ==
+/// operator.
+///
+/// * Type literals.
+///
+/// Type literals are more complex than const expressions because they can be
+/// created in multiple ways. We can approximate the possible set of keys if we
+/// follow these rules:
+///
+/// * Include all type-literals used explicitly in the code (excluding
+/// obviously the uses that can be removed from LookupMaps)
+///
+/// * Include every reflectable type-literal if a mirror API is used to create
+/// types (e.g. ClassMirror.reflectedType).
+///
+/// * Include all allocated types if the program contains `e.runtimeType`
+/// expressions.
+///
+/// * Include all generic-type arguments, if the program uses type
+/// variables in expressions such as `class A<T> { Type get extract => T }`.
+///
+// TODO(sigmund): add support for const expressions, currently this
+// implementation only supports Type literals. To support const expressions we
+// need to change some of the invariants below (e.g. we can no longer use the
+// ClassElement of a type to refer to keys we need to discover).
+// TODO(sigmund): detect uses of mirrors
+class LookupMapAnalysis {
+ /// Reference to [JavaScriptBackend] to be able to enqueue work when we
+ /// discover that a key in a map is potentially used.
+ final JavaScriptBackend backend;
+
+ /// The resolved [ClassElement] associated with `LookupMap`.
+ ClassElement typeLookupMapClass;
+
+ /// The resolved [FieldElement] for `LookupMap._entries`.
+ FieldElement entriesField;
+
+ /// The resolved [FieldElement] for `LookupMap._key`.
+ FieldElement keyField;
+
+ /// The resolved [FieldElement] for `LookupMap._value`.
+ FieldElement valueField;
+
+ /// Constant instances of `LookupMap` and information about them tracked by
+ /// this analysis.
+ final Map<ConstantValue, _LookupMapInfo> _lookupMaps = {};
+
+ /// Types that we have discovered to be in use in the program.
+ final _inUse = new Set<ClassElement>();
+
+ /// Pending work to do if we discover that a new type is in use. For each type
+ /// that we haven't seen, we record the list of lookup-maps that use such type
+ /// as a key.
+ final _pending = <ClassElement, List<_LookupMapInfo>>{};
+
+ /// Whether the backend is currently processing the codegen queue.
+ // TODO(sigmund): is there a better way to do this. Do we need to plumb the
+ // enqueuer on each callback?
+ bool get _inCodegen => backend.compiler.phase == Compiler.PHASE_COMPILING;
+
+ LookupMapAnalysis(this.backend);
+
+ /// Whether this analysis and optimization is enabled.
+ bool get _isEnabled {
+ // `lookupMap==off` kept here to make it easy to test disabling this feature
+ if (const String.fromEnvironment('lookupMap') == 'off') return false;
+ return typeLookupMapClass != null;
+ }
+
+ /// Initializes this analysis by providing the resolver information of
+ /// `LookupMap`.
+ void initRuntimeClass(ClassElement cls) {
+ cls.computeType(backend.compiler);
+ entriesField = cls.lookupMember('_entries');
+ keyField = cls.lookupMember('_key');
+ valueField = cls.lookupMember('_value');
+ // TODO(sigmund): Maybe inline nested maps make the output code smaller?
+ typeLookupMapClass = cls;
+ }
+
+ /// Whether [constant] is an instance of a `LookupMap`.
+ bool isLookupMap(ConstantValue constant) =>
+ _isEnabled &&
+ constant is ConstructedConstantValue &&
+ constant.type.asRaw().element.isSubclassOf(typeLookupMapClass);
+
+ /// Registers an instance of a lookup-map with the analysis.
+ void registerLookupMapReference(ConstantValue lookupMap) {
+ if (!_isEnabled || !_inCodegen) return;
+ assert(isLookupMap(lookupMap));
+ _lookupMaps.putIfAbsent(lookupMap,
+ () => new _LookupMapInfo(lookupMap, this).._updateUsed());
+ }
+
+ /// Records that [type] is used in the program, and updates every map that
+ /// has it as a key.
+ void _addUse(ClassElement type) {
+ if (_inUse.add(type)) {
+ _pending[type]?.forEach((info) => info._markUsed(type));
+ _pending.remove(type);
+ }
+ }
+
+ /// Callback from the enqueuer, invoked when [element] is instantiated.
+ void registerInstantiatedClass(ClassElement element) {
+ if (!_isEnabled || !_inCodegen) return;
+ // TODO(sigmund): only add if .runtimeType is ever used
+ _addUse(element);
+ }
+
+ /// Callback from the enqueuer, invoked when [type] is instantiated.
+ void registerInstantiatedType(InterfaceType type, Registry registry) {
+ if (!_isEnabled || !_inCodegen) return;
+ // TODO(sigmund): only add if .runtimeType is ever used
+ _addUse(type.element);
+ // TODO(sigmund): only do this when type-argument expressions are used?
+ _addGenerics(type, registry);
+ }
+
+ /// Records generic type arguments in [type], in case they are retrieved and
+ /// returned using a type-argument expression.
+ void _addGenerics(InterfaceType type, Registry registry) {
+ if (!type.isGeneric) return;
+ for (var arg in type.typeArguments) {
+ if (arg is InterfaceType) {
+ _addUse(arg.element);
+ // Note: this call was needed to generate correct code for
+ // type_lookup_map/generic_type_test
+ // TODO(sigmund): can we get rid of this?
+ backend.registerInstantiatedConstantType(
+ backend.typeImplementation.rawType, registry);
+ _addGenerics(arg, registry);
+ }
+ }
+ }
+
+ /// Callback from the codegen enqueuer, invoked when a type constant
+ /// corresponding to the [element] is used in the program.
+ void registerTypeConstant(Element element) {
+ if (!_isEnabled || !_inCodegen) return;
+ assert(element.isClass);
+ _addUse(element);
+ }
+
+ /// Callback from the backend, invoked when reaching the end of the enqueuing
+ /// process, but before emitting the code. At this moment we have discovered
+ /// all types used in the program and we can tree-shake anything that is
+ /// unused.
+ void onQueueClosed() {
+ if (!_isEnabled || !_inCodegen) return;
+
+ _lookupMaps.values.forEach((info) {
+ assert (!info.emitted);
+ info.emitted = true;
+ info._prepareForEmission();
+ });
+
+ // When --verbose is passed, we show the total number and set of keys that
+ // were tree-shaken from lookup maps.
+ Compiler compiler = backend.compiler;
+ if (compiler.verbose) {
+ var sb = new StringBuffer();
+ int count = 0;
+ for (var info in _lookupMaps.values) {
+ for (var key in info.unusedEntries.keys) {
+ if (count != 0) sb.write(',');
+ sb.write(key.unparse());
+ count++;
+ }
+ }
+ compiler.log(count == 0
+ ? 'lookup-map: nothing was tree-shaken'
+ : 'lookup-map: found $count unused keys ($sb)');
+ }
+ }
+}
+
+/// Internal information about the entries on a lookup-map.
+class _LookupMapInfo {
+ /// The original reference to the constant value.
+ ///
+ /// This reference will be mutated in place to remove it's entries when the
+ /// map is first seen during codegen, and to restore them (or a subset of
+ /// them) when we have finished discovering which entries are used. This has
+ /// the side-effect that `orignal.getDependencies()` will be empty during
+ /// most of codegen until we are ready to emit the constants. However,
+ /// restoring the entries before emitting code lets us keep the emitter logic
+ /// agnostic of this optimization.
+ final ConstructedConstantValue original;
+
+ /// Reference to the lookup map analysis to be able to refer to data shared
+ /// accross infos.
+ final LookupMapAnalysis analysis;
+
+ /// Whether we have already emitted this constant.
+ bool emitted = false;
+
+ /// Whether the `LookupMap` constant was built using the `LookupMap.pair`
+ /// constructor.
+ bool singlePair;
+
+ /// Entries in the lookup map whose keys have not been seen in the rest of the
+ /// program.
+ Map<ClassElement, ConstantValue> unusedEntries =
+ <ClassElement, ConstantValue>{};
+
+ /// Entries that have been used, and thus will be part of the generated code.
+ Map<ClassElement, ConstantValue> usedEntries =
+ <ClassElement, ConstantValue>{};
+
+ /// Internal helper to memoize the mapping between map class elements and
+ /// their corresponding type constants.
+ Map<ClassElement, TypeConstantValue> _typeConstants =
+ <ClassElement, TypeConstantValue>{};
+
+ /// Creates and initializes the information containing all keys of the
+ /// original map marked as unused.
+ _LookupMapInfo(this.original, this.analysis) {
+ ConstantValue key = original.fields[analysis.keyField];
+ singlePair = !key.isNull;
+
+ if (singlePair) {
+ TypeConstantValue typeKey = key;
+ ClassElement cls = typeKey.representedType.element;
+ _typeConstants[cls] = typeKey;
+ unusedEntries[cls] = original.fields[analysis.valueField];
+
+ // Note: we modify the constant in-place, see comment in [original].
+ original.fields[analysis.keyField] = new NullConstantValue();
+ original.fields[analysis.valueField] = new NullConstantValue();
+ } else {
+ ListConstantValue list = original.fields[analysis.entriesField];
+ List<ConstantValue> keyValuePairs = list.entries;
+ for (int i = 0; i < keyValuePairs.length; i += 2) {
+ TypeConstantValue type = keyValuePairs[i];
+ ClassElement cls = type.representedType.element;
+ if (cls == null || !cls.isClass) {
+ // TODO(sigmund): report an error
+ continue;
+ }
+ _typeConstants[cls] = type;
+ unusedEntries[cls] = keyValuePairs[i + 1];
+ }
+
+ // Note: we modify the constant in-place, see comment in [original].
+ original.fields[analysis.entriesField] =
+ new ListConstantValue(list.type, []);
+ }
+ }
+
+ /// Check every key in unusedEntries and mark it as used if the analysis has
+ /// already discovered them. This is meant to be called once to finalize
+ /// initialization after constructing an instance of this class. Afterwards,
+ /// we call [_markUsed] on each individual key as it gets discovered.
+ void _updateUsed() {
+ // Note: we call toList because `_markUsed` modifies the map.
+ for (ClassElement type in unusedEntries.keys.toList()) {
+ if (analysis._inUse.contains(type)) {
+ _markUsed(type);
+ } else {
+ analysis._pending.putIfAbsent(type, () => []).add(this);
+ }
+ }
+ }
+
+ /// Marks that [type] is a key that has been seen, and thus, the corresponding
+ /// entry in this map should be considered reachable.
+ void _markUsed(ClassElement type) {
+ assert(!emitted);
+ assert(unusedEntries.containsKey(type));
+ assert(!usedEntries.containsKey(type));
+ ConstantValue constant = unusedEntries.remove(type);
+ usedEntries[type] = constant;
+ analysis.backend.registerCompileTimeConstant(constant,
+ analysis.backend.compiler.globalDependencies,
+ addForEmission: false);
+ }
+
+ /// Restores [original] to contain all of the entries marked as possibly used.
+ void _prepareForEmission() {
+ ListConstantValue originalEntries = original.fields[analysis.entriesField];
+ DartType listType = originalEntries.type;
+ List<ConstantValue> keyValuePairs = <ConstantValue>[];
+ usedEntries.forEach((key, value) {
+ keyValuePairs.add(_typeConstants[key]);
+ keyValuePairs.add(value);
+ });
+
+ // Note: we are restoring the entries here, see comment in [original].
+ if (singlePair) {
+ assert (keyValuePairs.length == 0 || keyValuePairs.length == 2);
+ if (keyValuePairs.length == 2) {
+ original.fields[analysis.keyField] = keyValuePairs[0];
+ original.fields[analysis.valueField] = keyValuePairs[1];
+ }
+ } else {
+ original.fields[analysis.entriesField] =
+ new ListConstantValue(listType, keyValuePairs);
+ }
+ }
+}
diff --git a/pkg/compiler/lib/src/js_emitter/class_stub_generator.dart b/pkg/compiler/lib/src/js_emitter/class_stub_generator.dart
index f293870..c8d478b 100644
--- a/pkg/compiler/lib/src/js_emitter/class_stub_generator.dart
+++ b/pkg/compiler/lib/src/js_emitter/class_stub_generator.dart
@@ -48,7 +48,7 @@
* Invariant: [member] must be a declaration element.
*/
Map<jsAst.Name, jsAst.Expression> generateCallStubsForGetter(
- Element member, Map<Selector, TypeMaskSet> selectors) {
+ Element member, Map<Selector, ReceiverMaskSet> selectors) {
assert(invariant(member, member.isDeclaration));
// If the method is intercepted, the stub gets the
@@ -84,12 +84,7 @@
for (Selector selector in selectors.keys) {
if (generatedSelectors.contains(selector)) continue;
if (!selector.appliesUnnamed(member, compiler.world)) continue;
- for (TypeMask mask in selectors[selector].masks) {
- if (mask != null &&
- !mask.canHit(member, selector, compiler.world)) {
- continue;
- }
-
+ if (selectors[selector].applies(member, selector, compiler.world)) {
generatedSelectors.add(selector);
jsAst.Name invocationName = namer.invocationName(selector);
@@ -129,20 +124,12 @@
}
void addNoSuchMethodHandlers(String ignore,
- Map<Selector, TypeMaskSet> selectors) {
- TypeMask objectSubclassTypeMask =
- new TypeMask.subclass(compiler.objectClass, compiler.world);
-
+ Map<Selector, ReceiverMaskSet> selectors) {
for (Selector selector in selectors.keys) {
- TypeMaskSet maskSet = selectors[selector];
- for (TypeMask mask in maskSet.masks) {
- if (mask == null) mask = objectSubclassTypeMask;
-
- if (mask.needsNoSuchMethodHandling(selector, compiler.world)) {
- jsAst.Name jsName = namer.invocationMirrorInternalName(selector);
- jsNames[jsName] = selector;
- break;
- }
+ ReceiverMaskSet maskSet = selectors[selector];
+ if (maskSet.needsNoSuchMethodHandling(selector, compiler.world)) {
+ jsAst.Name jsName = namer.invocationMirrorInternalName(selector);
+ jsNames[jsName] = selector;
}
}
}
diff --git a/pkg/compiler/lib/src/js_emitter/js_emitter.dart b/pkg/compiler/lib/src/js_emitter/js_emitter.dart
index b46e60d..2f2dffd 100644
--- a/pkg/compiler/lib/src/js_emitter/js_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/js_emitter.dart
@@ -61,7 +61,7 @@
import 'startup_emitter/emitter.dart' as startup_js_emitter;
import '../universe/universe.dart' show
- TypeMaskSet,
+ ReceiverMaskSet,
TypedSelector;
import '../util/util.dart' show
diff --git a/pkg/compiler/lib/src/js_emitter/parameter_stub_generator.dart b/pkg/compiler/lib/src/js_emitter/parameter_stub_generator.dart
index 44350b5..07398b3 100644
--- a/pkg/compiler/lib/src/js_emitter/parameter_stub_generator.dart
+++ b/pkg/compiler/lib/src/js_emitter/parameter_stub_generator.dart
@@ -200,14 +200,14 @@
// The set of selectors that apply to `member`. For example, for
// a member `foo(x, [y])` the following selectors may apply:
// `foo(x)`, and `foo(x, y)`.
- Map<Selector, TypeMaskSet> selectors;
+ Map<Selector, ReceiverMaskSet> selectors;
// The set of selectors that apply to `member` if it's name was `call`.
// This happens when a member is torn off. In that case calls to the
// function use the name `call`, and we must be able to handle every
// `call` invocation that matches the signature. For example, for
// a member `foo(x, [y])` the following selectors would be possible
// call-selectors: `call(x)`, and `call(x, y)`.
- Map<Selector, TypeMaskSet> callSelectors;
+ Map<Selector, ReceiverMaskSet> callSelectors;
// Only instance members (not static methods) need stubs.
if (member.isInstanceMember) {
@@ -220,8 +220,9 @@
}
assert(emptySelectorSet.isEmpty);
- if (selectors == null) selectors = const <Selector, TypeMaskSet>{};
- if (callSelectors == null) callSelectors = const <Selector, TypeMaskSet>{};
+ if (selectors == null) selectors = const <Selector, ReceiverMaskSet>{};
+ if (callSelectors == null) callSelectors =
+ const <Selector, ReceiverMaskSet>{};
List<ParameterStubMethod> stubs = <ParameterStubMethod>[];
diff --git a/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart b/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
index 1b9b6ef..b10abf2a 100644
--- a/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
+++ b/pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart
@@ -30,7 +30,7 @@
MethodElement,
ParameterElement;
-import '../../universe/universe.dart' show Universe, TypeMaskSet;
+import '../../universe/universe.dart' show Universe, ReceiverMaskSet;
import '../../deferred_load.dart' show DeferredLoadTask, OutputUnit;
part 'collector.dart';
@@ -385,7 +385,7 @@
if (method != null) methods.add(method);
}
if (member.isGetter || member.isField) {
- Map<Selector, TypeMaskSet> selectors =
+ Map<Selector, ReceiverMaskSet> selectors =
_compiler.codegenWorld.invocationsByName(member.name);
if (selectors != null && !selectors.isEmpty) {
diff --git a/pkg/compiler/lib/src/mirror_renamer/mirror_renamer.dart b/pkg/compiler/lib/src/mirror_renamer/mirror_renamer.dart
index 9be4b75..d157b74 100644
--- a/pkg/compiler/lib/src/mirror_renamer/mirror_renamer.dart
+++ b/pkg/compiler/lib/src/mirror_renamer/mirror_renamer.dart
@@ -4,12 +4,15 @@
library mirror_renamer;
-import '../compiler.dart' show Compiler;
-import '../tree/tree.dart';
-import '../scanner/scannerlib.dart' show Token;
+import '../compiler.dart' show
+ Compiler;
+import '../dart_backend/dart_backend.dart' show
+ DartBackend,
+ PlaceholderCollector;
import '../elements/elements.dart';
-import '../dart_backend/dart_backend.dart' show DartBackend,
- PlaceholderCollector;
+import '../tokens/token.dart' show
+ Token;
+import '../tree/tree.dart';
part 'renamer.dart';
diff --git a/pkg/compiler/lib/src/mirrors/dart2js_mirrors.dart b/pkg/compiler/lib/src/mirrors/dart2js_mirrors.dart
index df44e28..c35fd8b 100644
--- a/pkg/compiler/lib/src/mirrors/dart2js_mirrors.dart
+++ b/pkg/compiler/lib/src/mirrors/dart2js_mirrors.dart
@@ -20,8 +20,9 @@
import '../elements/elements.dart';
import '../resolution/scope.dart' show
Scope;
-import '../scanner/scannerlib.dart';
import '../script.dart';
+import '../tokens/token.dart';
+import '../tokens/token_constants.dart' as Tokens;
import '../tree/tree.dart';
import '../util/util.dart'
show Link,
@@ -214,7 +215,7 @@
String toString() => _element.toString();
void _appendCommentTokens(Token commentToken) {
- while (commentToken != null && commentToken.kind == COMMENT_TOKEN) {
+ while (commentToken != null && commentToken.kind == Tokens.COMMENT_TOKEN) {
_metadata.add(new Dart2JsCommentInstanceMirror(
mirrorSystem, commentToken.value));
commentToken = commentToken.next;
diff --git a/pkg/compiler/lib/src/native/enqueue.dart b/pkg/compiler/lib/src/native/enqueue.dart
index d936d58..1f9b47b 100644
--- a/pkg/compiler/lib/src/native/enqueue.dart
+++ b/pkg/compiler/lib/src/native/enqueue.dart
@@ -263,7 +263,7 @@
if (token.stringValue != 'extends') return null;
token = token.next;
Token id = token;
- while (token.kind != EOF_TOKEN) {
+ while (token.kind != Tokens.EOF_TOKEN) {
token = token.next;
if (token.stringValue != '.') break;
token = token.next;
diff --git a/pkg/compiler/lib/src/native/native.dart b/pkg/compiler/lib/src/native/native.dart
index 281009d..ebe88a9 100644
--- a/pkg/compiler/lib/src/native/native.dart
+++ b/pkg/compiler/lib/src/native/native.dart
@@ -13,7 +13,8 @@
import '../constants/values.dart';
import '../dart_types.dart';
import '../diagnostics/diagnostic_listener.dart';
-import '../diagnostics/messages.dart' show MessageKind;
+import '../diagnostics/messages.dart' show
+ MessageKind;
import '../diagnostics/spannable.dart' show
NO_LOCATION_SPANNABLE,
Spannable;
@@ -28,10 +29,24 @@
LibraryElementX;
import '../js/js.dart' as js;
import '../js_backend/js_backend.dart';
-import '../js_emitter/js_emitter.dart' show CodeEmitterTask, NativeEmitter;
-import '../resolution/members.dart' show ResolverVisitor;
-import '../scanner/scannerlib.dart';
+import '../js_emitter/js_emitter.dart' show
+ CodeEmitterTask,
+ NativeEmitter;
+import '../parser/listener.dart' show
+ Listener;
+import '../parser/element_listener.dart' show
+ ElementListener;
+import '../parser/partial_elements.dart' show
+ PartialMetadataAnnotation;
+import '../resolution/members.dart' show
+ ResolverVisitor;
import '../ssa/ssa.dart';
+import '../tokens/token.dart' show
+ BeginGroupToken,
+ Token;
+import '../tokens/token_constants.dart' as Tokens show
+ EOF_TOKEN,
+ STRING_TOKEN;
import '../tree/tree.dart';
import '../universe/universe.dart' show SideEffects;
import '../util/util.dart';
diff --git a/pkg/compiler/lib/src/native/scanner.dart b/pkg/compiler/lib/src/native/scanner.dart
index bbbbb2e..cfdb703 100644
--- a/pkg/compiler/lib/src/native/scanner.dart
+++ b/pkg/compiler/lib/src/native/scanner.dart
@@ -13,7 +13,7 @@
Token handleNativeBlockToSkip(Listener listener, Token token) {
checkAllowedLibrary(listener, token);
token = token.next;
- if (identical(token.kind, STRING_TOKEN)) {
+ if (identical(token.kind, Tokens.STRING_TOKEN)) {
token = token.next;
}
if (identical(token.stringValue, '{')) {
@@ -29,7 +29,7 @@
listener.beginReturnStatement(token);
token = token.next;
bool hasExpression = false;
- if (identical(token.kind, STRING_TOKEN)) {
+ if (identical(token.kind, Tokens.STRING_TOKEN)) {
hasExpression = true;
listener.beginLiteralString(token);
listener.endLiteralString(0);
diff --git a/pkg/compiler/lib/src/parser/class_element_parser.dart b/pkg/compiler/lib/src/parser/class_element_parser.dart
new file mode 100644
index 0000000..745665d
--- /dev/null
+++ b/pkg/compiler/lib/src/parser/class_element_parser.dart
@@ -0,0 +1,19 @@
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library dart2js.parser.classes;
+
+import '../tokens/token.dart' show
+ Token;
+
+import 'listener.dart' show
+ Listener;
+import 'partial_parser.dart' show
+ PartialParser;
+
+class ClassElementParser extends PartialParser {
+ ClassElementParser(Listener listener) : super(listener);
+
+ Token parseClassBody(Token token) => fullParseClassBody(token);
+}
diff --git a/pkg/compiler/lib/src/parser/diet_parser_task.dart b/pkg/compiler/lib/src/parser/diet_parser_task.dart
new file mode 100644
index 0000000..ee22ae9
--- /dev/null
+++ b/pkg/compiler/lib/src/parser/diet_parser_task.dart
@@ -0,0 +1,42 @@
+// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library dart2js.parser.diet.task;
+
+import '../common/tasks.dart' show
+ CompilerTask;
+import '../compiler.dart' show
+ Compiler;
+import '../elements/elements.dart' show
+ CompilationUnitElement;
+import '../diagnostics/invariant.dart' show
+ invariant;
+import '../tokens/token.dart' show
+ Token;
+
+import 'listener.dart' show
+ ParserError;
+import 'element_listener.dart' show
+ ElementListener;
+import 'partial_parser.dart' show
+ PartialParser;
+
+class DietParserTask extends CompilerTask {
+ DietParserTask(Compiler compiler) : super(compiler);
+ final String name = 'Diet Parser';
+
+ dietParse(CompilationUnitElement compilationUnit, Token tokens) {
+ measure(() {
+ Function idGenerator = compiler.getNextFreeClassId;
+ ElementListener listener =
+ new ElementListener(compiler, compilationUnit, idGenerator);
+ PartialParser parser = new PartialParser(listener);
+ try {
+ parser.parseUnit(tokens);
+ } on ParserError catch(_) {
+ assert(invariant(compilationUnit, compiler.compilationFailed));
+ }
+ });
+ }
+}
diff --git a/pkg/compiler/lib/src/parser/element_listener.dart b/pkg/compiler/lib/src/parser/element_listener.dart
new file mode 100644
index 0000000..00ec535
--- /dev/null
+++ b/pkg/compiler/lib/src/parser/element_listener.dart
@@ -0,0 +1,755 @@
+// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library dart2js.parser.element_listener;
+
+import '../diagnostics/diagnostic_listener.dart';
+import '../diagnostics/messages.dart';
+import '../diagnostics/spannable.dart' show
+ Spannable;
+import '../elements/elements.dart' show
+ Element,
+ LibraryElement,
+ MetadataAnnotation;
+import '../elements/modelx.dart' show
+ CompilationUnitElementX,
+ DeclarationSite,
+ ElementX,
+ EnumClassElementX,
+ FieldElementX,
+ LibraryElementX,
+ MixinApplicationElementX,
+ VariableList;
+import '../native/native.dart' as native;
+import '../string_validator.dart' show
+ StringValidator;
+import '../tokens/keyword.dart' show
+ Keyword;
+import '../tokens/precedence_constants.dart' as Precedence show
+ BAD_INPUT_INFO;
+import '../tokens/token.dart' show
+ BeginGroupToken,
+ ErrorToken,
+ KeywordToken,
+ Token;
+import '../tokens/token_constants.dart' as Tokens show
+ EOF_TOKEN;
+import '../tree/tree.dart';
+import '../util/util.dart' show
+ Link;
+
+import 'partial_elements.dart' show
+ PartialClassElement,
+ PartialElement,
+ PartialFieldList,
+ PartialFunctionElement,
+ PartialMetadataAnnotation,
+ PartialTypedefElement;
+import 'listener.dart' show
+ closeBraceFor,
+ Listener,
+ ParserError,
+ VERBOSE;
+
+typedef int IdGenerator();
+
+/**
+ * A parser event listener designed to work with [PartialParser]. It
+ * builds elements representing the top-level declarations found in
+ * the parsed compilation unit and records them in
+ * [compilationUnitElement].
+ */
+class ElementListener extends Listener {
+ final IdGenerator idGenerator;
+ final DiagnosticListener listener;
+ final CompilationUnitElementX compilationUnitElement;
+ final StringValidator stringValidator;
+ Link<StringQuoting> interpolationScope;
+
+ Link<Node> nodes = const Link<Node>();
+
+ Link<MetadataAnnotation> metadata = const Link<MetadataAnnotation>();
+
+ /// Records a stack of booleans for each member parsed (a stack is used to
+ /// support nested members which isn't currently possible, but it also serves
+ /// as a simple way to tell we're currently parsing a member). In this case,
+ /// member refers to members of a library or a class (but currently, classes
+ /// themselves are not considered members). If the top of the stack
+ /// (memberErrors.head) is true, the current member has already reported at
+ /// least one parse error.
+ Link<bool> memberErrors = const Link<bool>();
+
+ bool suppressParseErrors = false;
+
+ ElementListener(
+ DiagnosticListener listener,
+ this.compilationUnitElement,
+ this.idGenerator)
+ : this.listener = listener,
+ stringValidator = new StringValidator(listener),
+ interpolationScope = const Link<StringQuoting>();
+
+ bool get currentMemberHasParseError {
+ return !memberErrors.isEmpty && memberErrors.head;
+ }
+
+ void pushQuoting(StringQuoting quoting) {
+ interpolationScope = interpolationScope.prepend(quoting);
+ }
+
+ StringQuoting popQuoting() {
+ StringQuoting result = interpolationScope.head;
+ interpolationScope = interpolationScope.tail;
+ return result;
+ }
+
+ StringNode popLiteralString() {
+ StringNode node = popNode();
+ // TODO(lrn): Handle interpolations in script tags.
+ if (node.isInterpolation) {
+ listener.internalError(node,
+ "String interpolation not supported in library tags.");
+ return null;
+ }
+ return node;
+ }
+
+ bool allowLibraryTags() {
+ // Library tags are only allowed in the library file itself, not
+ // in sourced files.
+ LibraryElement library = compilationUnitElement.implementationLibrary;
+ return !compilationUnitElement.hasMembers &&
+ library.entryCompilationUnit == compilationUnitElement;
+ }
+
+ void endLibraryName(Token libraryKeyword, Token semicolon) {
+ Expression name = popNode();
+ addLibraryTag(new LibraryName(libraryKeyword, name,
+ popMetadata(compilationUnitElement)));
+ }
+
+ void endImport(Token importKeyword, Token deferredKeyword, Token asKeyword,
+ Token semicolon) {
+ NodeList combinators = popNode();
+ bool isDeferred = deferredKeyword != null;
+ Identifier prefix;
+ if (asKeyword != null) {
+ prefix = popNode();
+ }
+ StringNode uri = popLiteralString();
+ addLibraryTag(new Import(importKeyword, uri, prefix, combinators,
+ popMetadata(compilationUnitElement),
+ isDeferred: isDeferred));
+ }
+
+ void endEnum(Token enumKeyword, Token endBrace, int count) {
+ NodeList names = makeNodeList(count, enumKeyword.next.next, endBrace, ",");
+ Identifier name = popNode();
+
+ int id = idGenerator();
+ Element enclosing = compilationUnitElement;
+ pushElement(new EnumClassElementX(name.source, enclosing, id,
+ new Enum(enumKeyword, name, names)));
+ rejectBuiltInIdentifier(name);
+ }
+
+ void endExport(Token exportKeyword, Token semicolon) {
+ NodeList combinators = popNode();
+ StringNode uri = popNode();
+ addLibraryTag(new Export(exportKeyword, uri, combinators,
+ popMetadata(compilationUnitElement)));
+ }
+
+ void endCombinators(int count) {
+ if (0 == count) {
+ pushNode(null);
+ } else {
+ pushNode(makeNodeList(count, null, null, " "));
+ }
+ }
+
+ void endHide(Token hideKeyword) => pushCombinator(hideKeyword);
+
+ void endShow(Token showKeyword) => pushCombinator(showKeyword);
+
+ void pushCombinator(Token keywordToken) {
+ NodeList identifiers = popNode();
+ pushNode(new Combinator(identifiers, keywordToken));
+ }
+
+ void endIdentifierList(int count) {
+ pushNode(makeNodeList(count, null, null, ","));
+ }
+
+ void endTypeList(int count) {
+ pushNode(makeNodeList(count, null, null, ","));
+ }
+
+ void endPart(Token partKeyword, Token semicolon) {
+ StringNode uri = popLiteralString();
+ addLibraryTag(new Part(partKeyword, uri,
+ popMetadata(compilationUnitElement)));
+ }
+
+ void endPartOf(Token partKeyword, Token semicolon) {
+ Expression name = popNode();
+ addPartOfTag(new PartOf(partKeyword, name,
+ popMetadata(compilationUnitElement)));
+ }
+
+ void addPartOfTag(PartOf tag) {
+ compilationUnitElement.setPartOf(tag, listener);
+ }
+
+ void endMetadata(Token beginToken, Token periodBeforeName, Token endToken) {
+ if (periodBeforeName != null) {
+ popNode(); // Discard name.
+ }
+ popNode(); // Discard node (Send or Identifier).
+ pushMetadata(new PartialMetadataAnnotation(beginToken, endToken));
+ }
+
+ void endTopLevelDeclaration(Token token) {
+ if (!metadata.isEmpty) {
+ recoverableError(metadata.head.beginToken,
+ 'Metadata not supported here.');
+ metadata = const Link<MetadataAnnotation>();
+ }
+ }
+
+ void endClassDeclaration(int interfacesCount, Token beginToken,
+ Token extendsKeyword, Token implementsKeyword,
+ Token endToken) {
+ makeNodeList(interfacesCount, implementsKeyword, null, ","); // interfaces
+ popNode(); // superType
+ popNode(); // typeParameters
+ Identifier name = popNode();
+ int id = idGenerator();
+ PartialClassElement element = new PartialClassElement(
+ name.source, beginToken, endToken, compilationUnitElement, id);
+ pushElement(element);
+ rejectBuiltInIdentifier(name);
+ }
+
+ void rejectBuiltInIdentifier(Identifier name) {
+ if (name.token is KeywordToken) {
+ Keyword keyword = (name.token as KeywordToken).keyword;
+ if (!keyword.isPseudo) {
+ recoverableError(name, "Illegal name '${keyword.syntax}'.");
+ }
+ }
+ }
+
+ void endFunctionTypeAlias(Token typedefKeyword, Token endToken) {
+ popNode(); // TODO(karlklose): do not throw away typeVariables.
+ Identifier name = popNode();
+ popNode(); // returnType
+ pushElement(
+ new PartialTypedefElement(
+ name.source, compilationUnitElement, typedefKeyword, endToken));
+ rejectBuiltInIdentifier(name);
+ }
+
+ void endNamedMixinApplication(Token classKeyword,
+ Token implementsKeyword,
+ Token endToken) {
+ NodeList interfaces = (implementsKeyword != null) ? popNode() : null;
+ MixinApplication mixinApplication = popNode();
+ Modifiers modifiers = popNode();
+ NodeList typeParameters = popNode();
+ Identifier name = popNode();
+ NamedMixinApplication namedMixinApplication = new NamedMixinApplication(
+ name, typeParameters, modifiers, mixinApplication, interfaces,
+ classKeyword, endToken);
+
+ int id = idGenerator();
+ Element enclosing = compilationUnitElement;
+ pushElement(new MixinApplicationElementX(name.source, enclosing, id,
+ namedMixinApplication,
+ modifiers));
+ rejectBuiltInIdentifier(name);
+ }
+
+ void endMixinApplication() {
+ NodeList mixins = popNode();
+ TypeAnnotation superclass = popNode();
+ pushNode(new MixinApplication(superclass, mixins));
+ }
+
+ void handleVoidKeyword(Token token) {
+ pushNode(new TypeAnnotation(new Identifier(token), null));
+ }
+
+ void endTopLevelMethod(Token beginToken, Token getOrSet, Token endToken) {
+ bool hasParseError = currentMemberHasParseError;
+ memberErrors = memberErrors.tail;
+ Identifier name = popNode();
+ popNode(); // type
+ Modifiers modifiers = popNode();
+ PartialFunctionElement element = new PartialFunctionElement(
+ name.source, beginToken, getOrSet, endToken,
+ modifiers, compilationUnitElement);
+ element.hasParseError = hasParseError;
+ pushElement(element);
+ }
+
+ void endTopLevelFields(int count, Token beginToken, Token endToken) {
+ bool hasParseError = currentMemberHasParseError;
+ memberErrors = memberErrors.tail;
+ void buildFieldElement(Identifier name, VariableList fields) {
+ pushElement(
+ new FieldElementX(name, compilationUnitElement, fields));
+ }
+ NodeList variables = makeNodeList(count, null, null, ",");
+ popNode(); // type
+ Modifiers modifiers = popNode();
+ buildFieldElements(modifiers, variables, compilationUnitElement,
+ buildFieldElement,
+ beginToken, endToken, hasParseError);
+ }
+
+ void buildFieldElements(Modifiers modifiers,
+ NodeList variables,
+ Element enclosingElement,
+ void buildFieldElement(Identifier name,
+ VariableList fields),
+ Token beginToken, Token endToken,
+ bool hasParseError) {
+ VariableList fields =
+ new PartialFieldList(beginToken, endToken, modifiers, hasParseError);
+ for (Link<Node> variableNodes = variables.nodes;
+ !variableNodes.isEmpty;
+ variableNodes = variableNodes.tail) {
+ Expression initializedIdentifier = variableNodes.head;
+ Identifier identifier = initializedIdentifier.asIdentifier();
+ if (identifier == null) {
+ identifier = initializedIdentifier.asSendSet().selector.asIdentifier();
+ }
+ buildFieldElement(identifier, fields);
+ }
+ }
+
+ void handleIdentifier(Token token) {
+ pushNode(new Identifier(token));
+ }
+
+ void handleQualified(Token period) {
+ Identifier last = popNode();
+ Expression first = popNode();
+ pushNode(new Send(first, last));
+ }
+
+ void handleNoType(Token token) {
+ pushNode(null);
+ }
+
+ void endTypeVariable(Token token) {
+ TypeAnnotation bound = popNode();
+ Identifier name = popNode();
+ pushNode(new TypeVariable(name, bound));
+ rejectBuiltInIdentifier(name);
+ }
+
+ void endTypeVariables(int count, Token beginToken, Token endToken) {
+ pushNode(makeNodeList(count, beginToken, endToken, ','));
+ }
+
+ void handleNoTypeVariables(token) {
+ pushNode(null);
+ }
+
+ void endTypeArguments(int count, Token beginToken, Token endToken) {
+ pushNode(makeNodeList(count, beginToken, endToken, ','));
+ }
+
+ void handleNoTypeArguments(Token token) {
+ pushNode(null);
+ }
+
+ void endType(Token beginToken, Token endToken) {
+ NodeList typeArguments = popNode();
+ Expression typeName = popNode();
+ pushNode(new TypeAnnotation(typeName, typeArguments));
+ }
+
+ void handleParenthesizedExpression(BeginGroupToken token) {
+ Expression expression = popNode();
+ pushNode(new ParenthesizedExpression(expression, token));
+ }
+
+ void handleModifier(Token token) {
+ pushNode(new Identifier(token));
+ }
+
+ void handleModifiers(int count) {
+ if (count == 0) {
+ pushNode(Modifiers.EMPTY);
+ } else {
+ NodeList modifierNodes = makeNodeList(count, null, null, ' ');
+ pushNode(new Modifiers(modifierNodes));
+ }
+ }
+
+ Token expected(String string, Token token) {
+ if (token is ErrorToken) {
+ reportErrorToken(token);
+ } else if (identical(';', string)) {
+ // When a semicolon is missing, it often leads to an error on the
+ // following line. So we try to find the token preceding the semicolon
+ // and report that something is missing *after* it.
+ Token preceding = findPrecedingToken(token);
+ if (preceding == token) {
+ reportError(
+ token, MessageKind.MISSING_TOKEN_BEFORE_THIS, {'token': string});
+ } else {
+ reportError(
+ preceding, MessageKind.MISSING_TOKEN_AFTER_THIS, {'token': string});
+ }
+ return token;
+ } else {
+ reportFatalError(
+ token,
+ MessageTemplate.TEMPLATES[MessageKind.MISSING_TOKEN_BEFORE_THIS]
+ .message({'token': string}, true).toString());
+ }
+ return skipToEof(token);
+ }
+
+ /// Finds the preceding token via the begin token of the last AST node pushed
+ /// on the [nodes] stack.
+ Token findPrecedingToken(Token token) {
+ Token result;
+ Link<Node> nodes = this.nodes;
+ while (!nodes.isEmpty) {
+ result = findPrecedingTokenFromNode(nodes.head, token);
+ if (result != null) {
+ return result;
+ }
+ nodes = nodes.tail;
+ }
+ if (compilationUnitElement != null) {
+ if (compilationUnitElement is CompilationUnitElementX) {
+ CompilationUnitElementX unit = compilationUnitElement;
+ Link<Element> members = unit.localMembers;
+ while (!members.isEmpty) {
+ ElementX member = members.head;
+ DeclarationSite site = member.declarationSite;
+ if (site is PartialElement) {
+ result = findPrecedingTokenFromToken(site.endToken, token);
+ if (result != null) {
+ return result;
+ }
+ }
+ members = members.tail;
+ }
+ result =
+ findPrecedingTokenFromNode(compilationUnitElement.partTag, token);
+ if (result != null) {
+ return result;
+ }
+ }
+ }
+ return token;
+ }
+
+ Token findPrecedingTokenFromNode(Node node, Token token) {
+ if (node != null) {
+ return findPrecedingTokenFromToken(node.getBeginToken(), token);
+ }
+ return null;
+ }
+
+ Token findPrecedingTokenFromToken(Token start, Token token) {
+ if (start != null) {
+ Token current = start;
+ while (current.kind != Tokens.EOF_TOKEN && current.next != token) {
+ current = current.next;
+ }
+ if (current.kind != Tokens.EOF_TOKEN) {
+ return current;
+ }
+ }
+ return null;
+ }
+
+ Token expectedIdentifier(Token token) {
+ if (token is KeywordToken) {
+ reportError(
+ token, MessageKind.EXPECTED_IDENTIFIER_NOT_RESERVED_WORD,
+ {'keyword': token.value});
+ } else if (token is ErrorToken) {
+ reportErrorToken(token);
+ return synthesizeIdentifier(token);
+ } else {
+ reportFatalError(token,
+ "Expected identifier, but got '${token.value}'.");
+ }
+ return token;
+ }
+
+ Token expectedType(Token token) {
+ pushNode(null);
+ if (token is ErrorToken) {
+ reportErrorToken(token);
+ return synthesizeIdentifier(token);
+ } else {
+ reportFatalError(
+ token, "Expected a type, but got '${token.value}'.");
+ return skipToEof(token);
+ }
+ }
+
+ Token expectedExpression(Token token) {
+ if (token is ErrorToken) {
+ reportErrorToken(token);
+ pushNode(new ErrorExpression(token));
+ return token.next;
+ } else {
+ reportFatalError(token,
+ "Expected an expression, but got '${token.value}'.");
+ pushNode(null);
+ return skipToEof(token);
+ }
+ }
+
+ Token unexpected(Token token) {
+ if (token is ErrorToken) {
+ reportErrorToken(token);
+ } else {
+ String message = "Unexpected token '${token.value}'.";
+ if (token.info == Precedence.BAD_INPUT_INFO) {
+ message = token.value;
+ }
+ reportFatalError(token, message);
+ }
+ return skipToEof(token);
+ }
+
+ Token expectedBlockToSkip(Token token) {
+ if (identical(token.stringValue, 'native')) {
+ return native.handleNativeBlockToSkip(this, token);
+ } else {
+ return unexpected(token);
+ }
+ }
+
+ Token expectedFunctionBody(Token token) {
+ if (token is ErrorToken) {
+ reportErrorToken(token);
+ } else {
+ String printString = token.value;
+ reportFatalError(token,
+ "Expected a function body, but got '$printString'.");
+ }
+ return skipToEof(token);
+ }
+
+ Token expectedClassBody(Token token) {
+ if (token is ErrorToken) {
+ reportErrorToken(token);
+ } else {
+ reportFatalError(token,
+ "Expected a class body, but got '${token.value}'.");
+ }
+ return skipToEof(token);
+ }
+
+ Token expectedClassBodyToSkip(Token token) {
+ return unexpected(token);
+ }
+
+ Token expectedDeclaration(Token token) {
+ if (token is ErrorToken) {
+ reportErrorToken(token);
+ } else {
+ reportFatalError(token,
+ "Expected a declaration, but got '${token.value}'.");
+ }
+ return skipToEof(token);
+ }
+
+ Token unmatched(Token token) {
+ if (token is ErrorToken) {
+ reportErrorToken(token);
+ } else {
+ String begin = token.value;
+ String end = closeBraceFor(begin);
+ reportError(
+ token, MessageKind.UNMATCHED_TOKEN, {'begin': begin, 'end': end});
+ }
+ Token next = token.next;
+ while (next is ErrorToken) {
+ next = next.next;
+ }
+ return next;
+ }
+
+ void recoverableError(Spannable node, String message) {
+ // TODO(johnniwinther): Make recoverable errors non-fatal.
+ reportFatalError(node, message);
+ }
+
+ void pushElement(Element element) {
+ popMetadata(element);
+ compilationUnitElement.addMember(element, listener);
+ }
+
+ Link<MetadataAnnotation> popMetadata(ElementX element) {
+ var result = const Link<MetadataAnnotation>();
+ for (Link link = metadata; !link.isEmpty; link = link.tail) {
+ element.addMetadata(link.head);
+ // Reverse the list as is implicitly done by addMetadata.
+ result = result.prepend(link.head);
+ }
+ metadata = const Link<MetadataAnnotation>();
+ return result;
+ }
+
+ void pushMetadata(MetadataAnnotation annotation) {
+ metadata = metadata.prepend(annotation);
+ }
+
+ void addLibraryTag(LibraryTag tag) {
+ if (!allowLibraryTags()) {
+ recoverableError(tag, 'Library tags not allowed here.');
+ }
+ LibraryElementX implementationLibrary =
+ compilationUnitElement.implementationLibrary;
+ implementationLibrary.addTag(tag, listener);
+ }
+
+ void pushNode(Node node) {
+ nodes = nodes.prepend(node);
+ if (VERBOSE) log("push $nodes");
+ }
+
+ Node popNode() {
+ assert(!nodes.isEmpty);
+ Node node = nodes.head;
+ nodes = nodes.tail;
+ if (VERBOSE) log("pop $nodes");
+ return node;
+ }
+
+ void log(message) {
+ print(message);
+ }
+
+ NodeList makeNodeList(int count, Token beginToken, Token endToken,
+ String delimiter) {
+ Link<Node> poppedNodes = const Link<Node>();
+ for (; count > 0; --count) {
+ // This effectively reverses the order of nodes so they end up
+ // in correct (source) order.
+ poppedNodes = poppedNodes.prepend(popNode());
+ }
+ return new NodeList(beginToken, poppedNodes, endToken, delimiter);
+ }
+
+ void beginLiteralString(Token token) {
+ String source = token.value;
+ StringQuoting quoting = StringValidator.quotingFromString(source);
+ pushQuoting(quoting);
+ // Just wrap the token for now. At the end of the interpolation,
+ // when we know how many there are, go back and validate the tokens.
+ pushNode(new LiteralString(token, null));
+ }
+
+ void handleStringPart(Token token) {
+ // Just push an unvalidated token now, and replace it when we know the
+ // end of the interpolation.
+ pushNode(new LiteralString(token, null));
+ }
+
+ void endLiteralString(int count) {
+ StringQuoting quoting = popQuoting();
+
+ Link<StringInterpolationPart> parts =
+ const Link<StringInterpolationPart>();
+ // Parts of the string interpolation are popped in reverse order,
+ // starting with the last literal string part.
+ bool isLast = true;
+ for (int i = 0; i < count; i++) {
+ LiteralString string = popNode();
+ DartString validation =
+ stringValidator.validateInterpolationPart(string.token, quoting,
+ isFirst: false,
+ isLast: isLast);
+ // Replace the unvalidated LiteralString with a new LiteralString
+ // object that has the validation result included.
+ string = new LiteralString(string.token, validation);
+ Expression expression = popNode();
+ parts = parts.prepend(new StringInterpolationPart(expression, string));
+ isLast = false;
+ }
+
+ LiteralString string = popNode();
+ DartString validation =
+ stringValidator.validateInterpolationPart(string.token, quoting,
+ isFirst: true,
+ isLast: isLast);
+ string = new LiteralString(string.token, validation);
+ if (isLast) {
+ pushNode(string);
+ } else {
+ NodeList partNodes = new NodeList(null, parts, null, "");
+ pushNode(new StringInterpolation(string, partNodes));
+ }
+ }
+
+ void handleStringJuxtaposition(int stringCount) {
+ assert(stringCount != 0);
+ Expression accumulator = popNode();
+ stringCount--;
+ while (stringCount > 0) {
+ Expression expression = popNode();
+ accumulator = new StringJuxtaposition(expression, accumulator);
+ stringCount--;
+ }
+ pushNode(accumulator);
+ }
+
+ void beginMember(Token token) {
+ memberErrors = memberErrors.prepend(false);
+ }
+
+ void beginTopLevelMember(Token token) {
+ beginMember(token);
+ }
+
+ void endFields(fieldCount, start, token) {
+ memberErrors = memberErrors.tail;
+ }
+
+ void endMethod(getOrSet, start, token) {
+ memberErrors = memberErrors.tail;
+ }
+
+ void beginFactoryMethod(Token token) {
+ memberErrors = memberErrors.prepend(false);
+ }
+
+ void endFactoryMethod(Token beginToken, Token endToken) {
+ memberErrors = memberErrors.tail;
+ }
+
+ /// Don't call this method. Should only be used as a last resort when there
+ /// is no feasible way to recover from a parser error.
+ void reportFatalError(Spannable spannable, String message) {
+ reportError(spannable, MessageKind.GENERIC, {'text': message});
+ // Some parse errors are infeasible to recover from, so we throw an error.
+ throw new ParserError(message);
+ }
+
+ void reportError(Spannable spannable,
+ MessageKind errorCode,
+ [Map arguments = const {}]) {
+ if (currentMemberHasParseError) return; // Error already reported.
+ if (suppressParseErrors) return;
+ if (!memberErrors.isEmpty) {
+ memberErrors = memberErrors.tail.prepend(true);
+ }
+ listener.reportError(spannable, errorCode, arguments);
+ }
+}
diff --git a/pkg/compiler/lib/src/parser/listener.dart b/pkg/compiler/lib/src/parser/listener.dart
new file mode 100644
index 0000000..5252d46
--- /dev/null
+++ b/pkg/compiler/lib/src/parser/listener.dart
@@ -0,0 +1,793 @@
+// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library dart2js.parser.listener;
+
+import '../diagnostics/messages.dart';
+import '../diagnostics/spannable.dart' show
+ Spannable,
+ SpannableAssertionFailure;
+import '../tokens/precedence_constants.dart' as Precedence show
+ EOF_INFO,
+ IDENTIFIER_INFO;
+import '../tokens/token.dart' show
+ BadInputToken,
+ BeginGroupToken,
+ ErrorToken,
+ StringToken,
+ Token,
+ UnmatchedToken,
+ UnterminatedToken;
+import '../tree/tree.dart';
+
+const bool VERBOSE = false;
+
+/**
+ * A parser event listener that does nothing except throw exceptions
+ * on parser errors.
+ */
+class Listener {
+ set suppressParseErrors(bool value) {
+ }
+
+ void beginArguments(Token token) {
+ }
+
+ void endArguments(int count, Token beginToken, Token endToken) {
+ }
+
+ /// Handle async modifiers `async`, `async*`, `sync`.
+ void handleAsyncModifier(Token asyncToken, Token startToken) {
+ }
+
+ void beginAwaitExpression(Token token) {
+ }
+
+ void endAwaitExpression(Token beginToken, Token endToken) {
+ }
+
+ void beginBlock(Token token) {
+ }
+
+ void endBlock(int count, Token beginToken, Token endToken) {
+ }
+
+ void beginCascade(Token token) {
+ }
+
+ void endCascade() {
+ }
+
+ void beginClassBody(Token token) {
+ }
+
+ void endClassBody(int memberCount, Token beginToken, Token endToken) {
+ }
+
+ void beginClassDeclaration(Token token) {
+ }
+
+ void endClassDeclaration(int interfacesCount, Token beginToken,
+ Token extendsKeyword, Token implementsKeyword,
+ Token endToken) {
+ }
+
+ void beginCombinators(Token token) {
+ }
+
+ void endCombinators(int count) {
+ }
+
+ void beginCompilationUnit(Token token) {
+ }
+
+ void endCompilationUnit(int count, Token token) {
+ }
+
+ void beginConstructorReference(Token start) {
+ }
+
+ void endConstructorReference(Token start, Token periodBeforeName,
+ Token endToken) {
+ }
+
+ void beginDoWhileStatement(Token token) {
+ }
+
+ void endDoWhileStatement(Token doKeyword, Token whileKeyword,
+ Token endToken) {
+ }
+
+ void beginEnum(Token enumKeyword) {
+ }
+
+ void endEnum(Token enumKeyword, Token endBrace, int count) {
+ }
+
+ void beginExport(Token token) {
+ }
+
+ void endExport(Token exportKeyword, Token semicolon) {
+ }
+
+ void beginExpressionStatement(Token token) {
+ }
+
+ void endExpressionStatement(Token token) {
+ }
+
+ void beginFactoryMethod(Token token) {
+ }
+
+ void endFactoryMethod(Token beginToken, Token endToken) {
+ }
+
+ void beginFormalParameter(Token token) {
+ }
+
+ void endFormalParameter(Token thisKeyword) {
+ }
+
+ void handleNoFormalParameters(Token token) {
+ }
+
+ void beginFormalParameters(Token token) {
+ }
+
+ void endFormalParameters(int count, Token beginToken, Token endToken) {
+ }
+
+ void endFields(int count, Token beginToken, Token endToken) {
+ }
+
+ void beginForStatement(Token token) {
+ }
+
+ void endForStatement(int updateExpressionCount,
+ Token beginToken, Token endToken) {
+ }
+
+ void endForIn(Token awaitToken, Token forToken,
+ Token inKeyword, Token endToken) {
+ }
+
+ void beginFunction(Token token) {
+ }
+
+ void endFunction(Token getOrSet, Token endToken) {
+ }
+
+ void beginFunctionDeclaration(Token token) {
+ }
+
+ void endFunctionDeclaration(Token token) {
+ }
+
+ void beginFunctionBody(Token token) {
+ }
+
+ void endFunctionBody(int count, Token beginToken, Token endToken) {
+ }
+
+ void handleNoFunctionBody(Token token) {
+ }
+
+ void skippedFunctionBody(Token token) {
+ }
+
+ void beginFunctionName(Token token) {
+ }
+
+ void endFunctionName(Token token) {
+ }
+
+ void beginFunctionTypeAlias(Token token) {
+ }
+
+ void endFunctionTypeAlias(Token typedefKeyword, Token endToken) {
+ }
+
+ void beginMixinApplication(Token token) {
+ }
+
+ void endMixinApplication() {
+ }
+
+ void beginNamedMixinApplication(Token token) {
+ }
+
+ void endNamedMixinApplication(Token classKeyword,
+ Token implementsKeyword,
+ Token endToken) {
+ }
+
+ void beginHide(Token hideKeyword) {
+ }
+
+ void endHide(Token hideKeyword) {
+ }
+
+ void beginIdentifierList(Token token) {
+ }
+
+ void endIdentifierList(int count) {
+ }
+
+ void beginTypeList(Token token) {
+ }
+
+ void endTypeList(int count) {
+ }
+
+ void beginIfStatement(Token token) {
+ }
+
+ void endIfStatement(Token ifToken, Token elseToken) {
+ }
+
+ void beginImport(Token importKeyword) {
+ }
+
+ void endImport(Token importKeyword, Token DeferredKeyword,
+ Token asKeyword, Token semicolon) {
+ }
+
+ void beginInitializedIdentifier(Token token) {
+ }
+
+ void endInitializedIdentifier() {
+ }
+
+ void beginInitializer(Token token) {
+ }
+
+ void endInitializer(Token assignmentOperator) {
+ }
+
+ void beginInitializers(Token token) {
+ }
+
+ void endInitializers(int count, Token beginToken, Token endToken) {
+ }
+
+ void handleNoInitializers() {
+ }
+
+ void handleLabel(Token token) {
+ }
+
+ void beginLabeledStatement(Token token, int labelCount) {
+ }
+
+ void endLabeledStatement(int labelCount) {
+ }
+
+ void beginLibraryName(Token token) {
+ }
+
+ void endLibraryName(Token libraryKeyword, Token semicolon) {
+ }
+
+ void beginLiteralMapEntry(Token token) {
+ }
+
+ void endLiteralMapEntry(Token colon, Token endToken) {
+ }
+
+ void beginLiteralString(Token token) {
+ }
+
+ void endLiteralString(int interpolationCount) {
+ }
+
+ void handleStringJuxtaposition(int literalCount) {
+ }
+
+ void beginMember(Token token) {
+ }
+
+ void endMethod(Token getOrSet, Token beginToken, Token endToken) {
+ }
+
+ void beginMetadataStar(Token token) {
+ }
+
+ void endMetadataStar(int count, bool forParameter) {
+ }
+
+ void beginMetadata(Token token) {
+ }
+
+ void endMetadata(Token beginToken, Token periodBeforeName, Token endToken) {
+ }
+
+ void beginOptionalFormalParameters(Token token) {
+ }
+
+ void endOptionalFormalParameters(int count,
+ Token beginToken, Token endToken) {
+ }
+
+ void beginPart(Token token) {
+ }
+
+ void endPart(Token partKeyword, Token semicolon) {
+ }
+
+ void beginPartOf(Token token) {
+ }
+
+ void endPartOf(Token partKeyword, Token semicolon) {
+ }
+
+ void beginRedirectingFactoryBody(Token token) {
+ }
+
+ void endRedirectingFactoryBody(Token beginToken, Token endToken) {
+ }
+
+ void beginReturnStatement(Token token) {
+ }
+
+ void endReturnStatement(bool hasExpression,
+ Token beginToken, Token endToken) {
+ }
+
+ void beginSend(Token token) {
+ }
+
+ void endSend(Token token) {
+ }
+
+ void beginShow(Token showKeyword) {
+ }
+
+ void endShow(Token showKeyword) {
+ }
+
+ void beginSwitchStatement(Token token) {
+ }
+
+ void endSwitchStatement(Token switchKeyword, Token endToken) {
+ }
+
+ void beginSwitchBlock(Token token) {
+ }
+
+ void endSwitchBlock(int caseCount, Token beginToken, Token endToken) {
+ }
+
+ void beginLiteralSymbol(Token token) {
+ }
+
+ void endLiteralSymbol(Token hashToken, int identifierCount) {
+ }
+
+ void beginThrowExpression(Token token) {
+ }
+
+ void endThrowExpression(Token throwToken, Token endToken) {
+ }
+
+ void beginRethrowStatement(Token token) {
+ }
+
+ void endRethrowStatement(Token throwToken, Token endToken) {
+ }
+
+ void endTopLevelDeclaration(Token token) {
+ }
+
+ void beginTopLevelMember(Token token) {
+ }
+
+ void endTopLevelFields(int count, Token beginToken, Token endToken) {
+ }
+
+ void endTopLevelMethod(Token beginToken, Token getOrSet, Token endToken) {
+ }
+
+ void beginTryStatement(Token token) {
+ }
+
+ void handleCaseMatch(Token caseKeyword, Token colon) {
+ }
+
+ void handleCatchBlock(Token onKeyword, Token catchKeyword) {
+ }
+
+ void handleFinallyBlock(Token finallyKeyword) {
+ }
+
+ void endTryStatement(int catchCount, Token tryKeyword, Token finallyKeyword) {
+ }
+
+ void endType(Token beginToken, Token endToken) {
+ }
+
+ void beginTypeArguments(Token token) {
+ }
+
+ void endTypeArguments(int count, Token beginToken, Token endToken) {
+ }
+
+ void handleNoTypeArguments(Token token) {
+ }
+
+ void beginTypeVariable(Token token) {
+ }
+
+ void endTypeVariable(Token token) {
+ }
+
+ void beginTypeVariables(Token token) {
+ }
+
+ void endTypeVariables(int count, Token beginToken, Token endToken) {
+ }
+
+ void beginUnnamedFunction(Token token) {
+ }
+
+ void endUnnamedFunction(Token token) {
+ }
+
+ void beginVariablesDeclaration(Token token) {
+ }
+
+ void endVariablesDeclaration(int count, Token endToken) {
+ }
+
+ void beginWhileStatement(Token token) {
+ }
+
+ void endWhileStatement(Token whileKeyword, Token endToken) {
+ }
+
+ void handleAsOperator(Token operathor, Token endToken) {
+ // TODO(ahe): Rename [operathor] to "operator" when VM bug is fixed.
+ }
+
+ void handleAssignmentExpression(Token token) {
+ }
+
+ void handleBinaryExpression(Token token) {
+ }
+
+ void handleConditionalExpression(Token question, Token colon) {
+ }
+
+ void handleConstExpression(Token token) {
+ }
+
+ void handleFunctionTypedFormalParameter(Token token) {
+ }
+
+ void handleIdentifier(Token token) {
+ }
+
+ void handleIndexedExpression(Token openCurlyBracket,
+ Token closeCurlyBracket) {
+ }
+
+ void handleIsOperator(Token operathor, Token not, Token endToken) {
+ // TODO(ahe): Rename [operathor] to "operator" when VM bug is fixed.
+ }
+
+ void handleLiteralBool(Token token) {
+ }
+
+ void handleBreakStatement(bool hasTarget,
+ Token breakKeyword, Token endToken) {
+ }
+
+ void handleContinueStatement(bool hasTarget,
+ Token continueKeyword, Token endToken) {
+ }
+
+ void handleEmptyStatement(Token token) {
+ }
+
+ void handleAssertStatement(Token assertKeyword, Token semicolonToken) {
+ }
+
+ /** Called with either the token containing a double literal, or
+ * an immediately preceding "unary plus" token.
+ */
+ void handleLiteralDouble(Token token) {
+ }
+
+ /** Called with either the token containing an integer literal,
+ * or an immediately preceding "unary plus" token.
+ */
+ void handleLiteralInt(Token token) {
+ }
+
+ void handleLiteralList(int count, Token beginToken, Token constKeyword,
+ Token endToken) {
+ }
+
+ void handleLiteralMap(int count, Token beginToken, Token constKeyword,
+ Token endToken) {
+ }
+
+ void handleLiteralNull(Token token) {
+ }
+
+ void handleModifier(Token token) {
+ }
+
+ void handleModifiers(int count) {
+ }
+
+ void handleNamedArgument(Token colon) {
+ }
+
+ void handleNewExpression(Token token) {
+ }
+
+ void handleNoArguments(Token token) {
+ }
+
+ void handleNoExpression(Token token) {
+ }
+
+ void handleNoType(Token token) {
+ }
+
+ void handleNoTypeVariables(Token token) {
+ }
+
+ void handleOperator(Token token) {
+ }
+
+ void handleOperatorName(Token operatorKeyword, Token token) {
+ }
+
+ void handleParenthesizedExpression(BeginGroupToken token) {
+ }
+
+ void handleQualified(Token period) {
+ }
+
+ void handleStringPart(Token token) {
+ }
+
+ void handleSuperExpression(Token token) {
+ }
+
+ void handleSwitchCase(int labelCount, int expressionCount,
+ Token defaultKeyword, int statementCount,
+ Token firstToken, Token endToken) {
+ }
+
+ void handleThisExpression(Token token) {
+ }
+
+ void handleUnaryPostfixAssignmentExpression(Token token) {
+ }
+
+ void handleUnaryPrefixExpression(Token token) {
+ }
+
+ void handleUnaryPrefixAssignmentExpression(Token token) {
+ }
+
+ void handleValuedFormalParameter(Token equals, Token token) {
+ }
+
+ void handleVoidKeyword(Token token) {
+ }
+
+ void beginYieldStatement(Token token) {
+ }
+
+ void endYieldStatement(Token yieldToken, Token starToken, Token endToken) {
+ }
+
+ Token expected(String string, Token token) {
+ if (token is ErrorToken) {
+ reportErrorToken(token);
+ } else {
+ error("expected '$string', but got '${token.value}'", token);
+ }
+ return skipToEof(token);
+ }
+
+ Token synthesizeIdentifier(Token token) {
+ Token synthesizedToken =
+ new StringToken.fromString(
+ Precedence.IDENTIFIER_INFO, '?', token.charOffset);
+ synthesizedToken.next = token.next;
+ return synthesizedToken;
+ }
+
+ Token expectedIdentifier(Token token) {
+ if (token is ErrorToken) {
+ reportErrorToken(token);
+ } else {
+ error("expected identifier, but got '${token.value}'", token);
+ }
+ return skipToEof(token);
+ }
+
+ Token expectedType(Token token) {
+ if (token is ErrorToken) {
+ reportErrorToken(token);
+ } else {
+ error("expected a type, but got '${token.value}'", token);
+ }
+ return skipToEof(token);
+ }
+
+ Token expectedExpression(Token token) {
+ if (token is ErrorToken) {
+ reportErrorToken(token);
+ } else {
+ error("expected an expression, but got '${token.value}'", token);
+ }
+ return skipToEof(token);
+ }
+
+ Token unexpected(Token token) {
+ if (token is ErrorToken) {
+ reportErrorToken(token);
+ } else {
+ error("unexpected token '${token.value}'", token);
+ }
+ return skipToEof(token);
+ }
+
+ Token expectedBlockToSkip(Token token) {
+ if (token is ErrorToken) {
+ reportErrorToken(token);
+ } else {
+ error("expected a block, but got '${token.value}'", token);
+ }
+ return skipToEof(token);
+ }
+
+ Token expectedFunctionBody(Token token) {
+ if (token is ErrorToken) {
+ reportErrorToken(token);
+ } else {
+ error("expected a function body, but got '${token.value}'", token);
+ }
+ return skipToEof(token);
+ }
+
+ Token expectedClassBody(Token token) {
+ if (token is ErrorToken) {
+ reportErrorToken(token);
+ } else {
+ error("expected a class body, but got '${token.value}'", token);
+ }
+ return skipToEof(token);
+ }
+
+ Token expectedClassBodyToSkip(Token token) {
+ if (token is ErrorToken) {
+ reportErrorToken(token);
+ } else {
+ error("expected a class body, but got '${token.value}'", token);
+ }
+ return skipToEof(token);
+ }
+
+ Token expectedDeclaration(Token token) {
+ if (token is ErrorToken) {
+ reportErrorToken(token);
+ } else {
+ error("expected a declaration, but got '${token.value}'", token);
+ }
+ return skipToEof(token);
+ }
+
+ Token unmatched(Token token) {
+ if (token is ErrorToken) {
+ reportErrorToken(token);
+ } else {
+ error("unmatched '${token.value}'", token);
+ }
+ return skipToEof(token);
+ }
+
+ skipToEof(Token token) {
+ while (!identical(token.info, Precedence.EOF_INFO)) {
+ token = token.next;
+ }
+ return token;
+ }
+
+ void recoverableError(Token token, String message) {
+ error(message, token);
+ }
+
+ void error(String message, Token token) {
+ throw new ParserError("$message @ ${token.charOffset}");
+ }
+
+ void reportError(Spannable spannable,
+ MessageKind messageKind,
+ [Map arguments = const {}]) {
+ MessageTemplate template = MessageTemplate.TEMPLATES[messageKind];
+ String message = template.message(arguments, true).toString();
+ Token token;
+ if (spannable is Token) {
+ token = spannable;
+ } else if (spannable is Node) {
+ token = spannable.getBeginToken();
+ } else {
+ throw new ParserError(message);
+ }
+ recoverableError(token, message);
+ }
+
+ void reportErrorToken(ErrorToken token) {
+ if (token is BadInputToken) {
+ String hex = token.character.toRadixString(16);
+ if (hex.length < 4) {
+ String padding = "0000".substring(hex.length);
+ hex = "$padding$hex";
+ }
+ reportError(
+ token, MessageKind.BAD_INPUT_CHARACTER, {'characterHex': hex});
+ } else if (token is UnterminatedToken) {
+ MessageKind kind;
+ var arguments = const {};
+ switch (token.start) {
+ case '1e':
+ kind = MessageKind.EXPONENT_MISSING;
+ break;
+ case '"':
+ case "'":
+ case '"""':
+ case "'''":
+ case 'r"':
+ case "r'":
+ case 'r"""':
+ case "r'''":
+ kind = MessageKind.UNTERMINATED_STRING;
+ arguments = {'quote': token.start};
+ break;
+ case '0x':
+ kind = MessageKind.HEX_DIGIT_EXPECTED;
+ break;
+ case r'$':
+ kind = MessageKind.MALFORMED_STRING_LITERAL;
+ break;
+ case '/*':
+ kind = MessageKind.UNTERMINATED_COMMENT;
+ break;
+ default:
+ kind = MessageKind.UNTERMINATED_TOKEN;
+ break;
+ }
+ reportError(token, kind, arguments);
+ } else if (token is UnmatchedToken) {
+ String begin = token.begin.value;
+ String end = closeBraceFor(begin);
+ reportError(
+ token, MessageKind.UNMATCHED_TOKEN, {'begin': begin, 'end': end});
+ } else {
+ throw new SpannableAssertionFailure(token, token.assertionMessage);
+ }
+ }
+}
+
+String closeBraceFor(String openBrace) {
+ return const {
+ '(': ')',
+ '[': ']',
+ '{': '}',
+ '<': '>',
+ r'${': '}',
+ }[openBrace];
+}
+
+class ParserError {
+ final String reason;
+ ParserError(this.reason);
+ toString() => reason;
+}
diff --git a/pkg/compiler/lib/src/parser/member_listener.dart b/pkg/compiler/lib/src/parser/member_listener.dart
new file mode 100644
index 0000000..08656d3
--- /dev/null
+++ b/pkg/compiler/lib/src/parser/member_listener.dart
@@ -0,0 +1,175 @@
+// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library dart2js.parser.member_listener;
+
+import '../diagnostics/diagnostic_listener.dart' show
+ DiagnosticListener;
+import '../diagnostics/messages.dart' show
+ MessageKind;
+import '../elements/elements.dart' show
+ Element,
+ ElementKind,
+ Elements,
+ MetadataAnnotation;
+import '../elements/modelx.dart' show
+ ClassElementX,
+ ElementX,
+ FieldElementX,
+ VariableList;
+import '../tokens/token.dart' show
+ Token;
+import '../tree/tree.dart';
+import '../util/util.dart' show
+ Link;
+
+import 'partial_elements.dart' show
+ PartialConstructorElement,
+ PartialFunctionElement,
+ PartialMetadataAnnotation;
+import 'node_listener.dart' show
+ NodeListener;
+
+class MemberListener extends NodeListener {
+ final ClassElementX enclosingClass;
+
+ MemberListener(DiagnosticListener listener,
+ ClassElementX enclosingElement)
+ : this.enclosingClass = enclosingElement,
+ super(listener, enclosingElement.compilationUnit);
+
+ bool isConstructorName(Node nameNode) {
+ if (enclosingClass == null ||
+ enclosingClass.kind != ElementKind.CLASS) {
+ return false;
+ }
+ String name;
+ if (nameNode.asIdentifier() != null) {
+ name = nameNode.asIdentifier().source;
+ } else {
+ Send send = nameNode.asSend();
+ name = send.receiver.asIdentifier().source;
+ }
+ return enclosingClass.name == name;
+ }
+
+ // TODO(johnniwinther): Remove this method.
+ String getMethodNameHack(Node methodName) {
+ Send send = methodName.asSend();
+ if (send == null) {
+ if (isConstructorName(methodName)) return '';
+ return methodName.asIdentifier().source;
+ }
+ Identifier receiver = send.receiver.asIdentifier();
+ Identifier selector = send.selector.asIdentifier();
+ Operator operator = selector.asOperator();
+ if (operator != null) {
+ assert(identical(receiver.source, 'operator'));
+ // TODO(ahe): It is a hack to compare to ')', but it beats
+ // parsing the node.
+ bool isUnary = identical(operator.token.next.next.stringValue, ')');
+ return Elements.constructOperatorName(operator.source, isUnary);
+ } else {
+ if (receiver == null || receiver.source != enclosingClass.name) {
+ listener.reportError(send.receiver,
+ MessageKind.INVALID_CONSTRUCTOR_NAME,
+ {'name': enclosingClass.name});
+ }
+ return selector.source;
+ }
+ }
+
+ void endMethod(Token getOrSet, Token beginToken, Token endToken) {
+ super.endMethod(getOrSet, beginToken, endToken);
+ FunctionExpression method = popNode();
+ pushNode(null);
+ bool isConstructor = isConstructorName(method.name);
+ String name = getMethodNameHack(method.name);
+ Element memberElement;
+ if (isConstructor) {
+ if (getOrSet != null) {
+ recoverableError(getOrSet, 'illegal modifier');
+ }
+ memberElement = new PartialConstructorElement(
+ name, beginToken, endToken,
+ ElementKind.GENERATIVE_CONSTRUCTOR,
+ method.modifiers,
+ enclosingClass);
+ } else {
+ memberElement = new PartialFunctionElement(
+ name, beginToken, getOrSet, endToken,
+ method.modifiers, enclosingClass, hasBody: method.hasBody());
+ }
+ addMember(memberElement);
+ }
+
+ void endFactoryMethod(Token beginToken, Token endToken) {
+ super.endFactoryMethod(beginToken, endToken);
+ FunctionExpression method = popNode();
+ pushNode(null);
+ String name = getMethodNameHack(method.name);
+ Identifier singleIdentifierName = method.name.asIdentifier();
+ if (singleIdentifierName != null && singleIdentifierName.source == name) {
+ if (name != enclosingClass.name) {
+ listener.reportError(singleIdentifierName,
+ MessageKind.INVALID_UNNAMED_CONSTRUCTOR_NAME,
+ {'name': enclosingClass.name});
+ }
+ }
+ Element memberElement = new PartialConstructorElement(
+ name, beginToken, endToken,
+ ElementKind.FUNCTION,
+ method.modifiers,
+ enclosingClass);
+ addMember(memberElement);
+ }
+
+ void endFields(int count, Token beginToken, Token endToken) {
+ bool hasParseError = memberErrors.head;
+ super.endFields(count, beginToken, endToken);
+ VariableDefinitions variableDefinitions = popNode();
+ Modifiers modifiers = variableDefinitions.modifiers;
+ pushNode(null);
+ void buildFieldElement(Identifier name, VariableList fields) {
+ Element element =
+ new FieldElementX(name, enclosingClass, fields);
+ addMember(element);
+ }
+ buildFieldElements(modifiers, variableDefinitions.definitions,
+ enclosingClass,
+ buildFieldElement, beginToken, endToken,
+ hasParseError);
+ }
+
+ void endInitializer(Token assignmentOperator) {
+ pushNode(null); // Super expects an expression, but
+ // ClassElementParser just skips expressions.
+ super.endInitializer(assignmentOperator);
+ }
+
+ void endInitializers(int count, Token beginToken, Token endToken) {
+ pushNode(null);
+ }
+
+ void addMetadata(ElementX memberElement) {
+ for (Link link = metadata; !link.isEmpty; link = link.tail) {
+ memberElement.addMetadata(link.head);
+ }
+ metadata = const Link<MetadataAnnotation>();
+ }
+
+ void addMember(ElementX memberElement) {
+ addMetadata(memberElement);
+ enclosingClass.addMember(memberElement, listener);
+ }
+
+ void endMetadata(Token beginToken, Token periodBeforeName, Token endToken) {
+ popNode(); // Discard arguments.
+ if (periodBeforeName != null) {
+ popNode(); // Discard name.
+ }
+ popNode(); // Discard node (Send or Identifier).
+ pushMetadata(new PartialMetadataAnnotation(beginToken, endToken));
+ }
+}
diff --git a/pkg/compiler/lib/src/parser/node_listener.dart b/pkg/compiler/lib/src/parser/node_listener.dart
new file mode 100644
index 0000000..455f53e
--- /dev/null
+++ b/pkg/compiler/lib/src/parser/node_listener.dart
@@ -0,0 +1,816 @@
+// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library dart2js.parser.node_listener;
+
+import '../diagnostics/diagnostic_listener.dart';
+import '../diagnostics/messages.dart';
+import '../diagnostics/spannable.dart' show
+ Spannable,
+ SpannableAssertionFailure;
+import '../elements/elements.dart' show
+ CompilationUnitElement;
+import '../native/native.dart' as native;
+import '../tokens/precedence_constants.dart' as Precedence show
+ BAD_INPUT_INFO,
+ EOF_INFO,
+ INDEX_INFO;
+import '../tokens/token.dart' show
+ ErrorToken,
+ StringToken,
+ Token;
+import '../tree/tree.dart';
+import '../util/util.dart' show
+ Link;
+
+import 'element_listener.dart' show
+ ElementListener;
+import 'partial_elements.dart' show
+ PartialFunctionElement;
+
+class NodeListener extends ElementListener {
+ NodeListener(
+ DiagnosticListener listener,
+ CompilationUnitElement element)
+ : super(listener, element, null);
+
+ void addLibraryTag(LibraryTag tag) {
+ pushNode(tag);
+ }
+
+ void addPartOfTag(PartOf tag) {
+ pushNode(tag);
+ }
+
+ void endClassDeclaration(int interfacesCount, Token beginToken,
+ Token extendsKeyword, Token implementsKeyword,
+ Token endToken) {
+ NodeList body = popNode();
+ NodeList interfaces =
+ makeNodeList(interfacesCount, implementsKeyword, null, ",");
+ Node supertype = popNode();
+ NodeList typeParameters = popNode();
+ Identifier name = popNode();
+ Modifiers modifiers = popNode();
+ pushNode(new ClassNode(modifiers, name, typeParameters, supertype,
+ interfaces, beginToken, extendsKeyword, body,
+ endToken));
+ }
+
+ void endCompilationUnit(int count, Token token) {
+ pushNode(makeNodeList(count, null, null, '\n'));
+ }
+
+ void endFunctionTypeAlias(Token typedefKeyword, Token endToken) {
+ NodeList formals = popNode();
+ NodeList typeParameters = popNode();
+ Identifier name = popNode();
+ TypeAnnotation returnType = popNode();
+ pushNode(new Typedef(returnType, name, typeParameters, formals,
+ typedefKeyword, endToken));
+ }
+
+ void endNamedMixinApplication(Token classKeyword,
+ Token implementsKeyword,
+ Token endToken) {
+ NodeList interfaces = (implementsKeyword != null) ? popNode() : null;
+ Node mixinApplication = popNode();
+ Modifiers modifiers = popNode();
+ NodeList typeParameters = popNode();
+ Identifier name = popNode();
+ pushNode(new NamedMixinApplication(name, typeParameters,
+ modifiers, mixinApplication,
+ interfaces,
+ classKeyword, endToken));
+ }
+
+ void endEnum(Token enumKeyword, Token endBrace, int count) {
+ NodeList names = makeNodeList(count, enumKeyword.next.next, endBrace, ",");
+ Identifier name = popNode();
+ pushNode(new Enum(enumKeyword, name, names));
+ }
+
+ void endClassBody(int memberCount, Token beginToken, Token endToken) {
+ pushNode(makeNodeList(memberCount, beginToken, endToken, null));
+ }
+
+ void endTopLevelFields(int count, Token beginToken, Token endToken) {
+ NodeList variables = makeNodeList(count, null, endToken, ",");
+ TypeAnnotation type = popNode();
+ Modifiers modifiers = popNode();
+ pushNode(new VariableDefinitions(type, modifiers, variables));
+ }
+
+ void endTopLevelMethod(Token beginToken, Token getOrSet, Token endToken) {
+ popNode(); // body
+ popNode(); // formalParameters
+ Identifier name = popNode();
+ popNode(); // type
+ Modifiers modifiers = popNode();
+ PartialFunctionElement element = new PartialFunctionElement(
+ name.source, beginToken, getOrSet, endToken,
+ modifiers, compilationUnitElement);
+ pushElement(element);
+ }
+
+ void endFormalParameter(Token thisKeyword) {
+ Expression name = popNode();
+ if (thisKeyword != null) {
+ Identifier thisIdentifier = new Identifier(thisKeyword);
+ if (name.asSend() == null) {
+ name = new Send(thisIdentifier, name);
+ } else {
+ name = name.asSend().copyWithReceiver(thisIdentifier, false);
+ }
+ }
+ TypeAnnotation type = popNode();
+ Modifiers modifiers = popNode();
+ NodeList metadata = popNode();
+ pushNode(new VariableDefinitions.forParameter(
+ metadata, type, modifiers, new NodeList.singleton(name)));
+ }
+
+ void endFormalParameters(int count, Token beginToken, Token endToken) {
+ pushNode(makeNodeList(count, beginToken, endToken, ","));
+ }
+
+ void handleNoFormalParameters(Token token) {
+ pushNode(null);
+ }
+
+ void endArguments(int count, Token beginToken, Token endToken) {
+ pushNode(makeNodeList(count, beginToken, endToken, ","));
+ }
+
+ void handleNoArguments(Token token) {
+ pushNode(null);
+ }
+
+ void endConstructorReference(Token start, Token periodBeforeName,
+ Token endToken) {
+ Identifier name = null;
+ if (periodBeforeName != null) {
+ name = popNode();
+ }
+ NodeList typeArguments = popNode();
+ Node classReference = popNode();
+ if (typeArguments != null) {
+ classReference = new TypeAnnotation(classReference, typeArguments);
+ } else {
+ Identifier identifier = classReference.asIdentifier();
+ Send send = classReference.asSend();
+ if (identifier != null) {
+ // TODO(ahe): Should be:
+ // classReference = new Send(null, identifier);
+ classReference = identifier;
+ } else if (send != null) {
+ classReference = send;
+ } else {
+ internalError(node: classReference);
+ }
+ }
+ Node constructor = classReference;
+ if (name != null) {
+ // Either typeName<args>.name or x.y.name.
+ constructor = new Send(classReference, name);
+ }
+ pushNode(constructor);
+ }
+
+ void endRedirectingFactoryBody(Token beginToken,
+ Token endToken) {
+ pushNode(new RedirectingFactoryBody(beginToken, endToken, popNode()));
+ }
+
+ void endReturnStatement(bool hasExpression,
+ Token beginToken, Token endToken) {
+ Expression expression = hasExpression ? popNode() : null;
+ pushNode(new Return(beginToken, endToken, expression));
+ }
+
+ void endYieldStatement(Token yieldToken, Token starToken, Token endToken) {
+ Expression expression = popNode();
+ pushNode(new Yield(yieldToken, starToken, expression, endToken));
+ }
+
+ void endExpressionStatement(Token token) {
+ pushNode(new ExpressionStatement(popNode(), token));
+ }
+
+ void handleOnError(Token token, var errorInformation) {
+ listener.internalError(token, "'${token.value}': ${errorInformation}");
+ }
+
+ Token expectedFunctionBody(Token token) {
+ if (identical(token.stringValue, 'native')) {
+ return native.handleNativeFunctionBody(this, token);
+ } else if (token is ErrorToken) {
+ pushNode(null);
+ reportErrorToken(token);
+ } else {
+ reportFatalError(token,
+ "Expected a function body, but got '${token.value}'.");
+ }
+ return skipToEof(token);
+ }
+
+ Token expectedClassBody(Token token) {
+ if (token is ErrorToken) {
+ reportErrorToken(token);
+ return skipToEof(token);
+ } else {
+ reportFatalError(token,
+ "Expected a class body, but got '${token.value}'.");
+ return skipToEof(token);
+ }
+ }
+
+ void handleLiteralInt(Token token) {
+ pushNode(new LiteralInt(token, (t, e) => handleOnError(t, e)));
+ }
+
+ void handleLiteralDouble(Token token) {
+ pushNode(new LiteralDouble(token, (t, e) => handleOnError(t, e)));
+ }
+
+ void handleLiteralBool(Token token) {
+ pushNode(new LiteralBool(token, (t, e) => handleOnError(t, e)));
+ }
+
+ void handleLiteralNull(Token token) {
+ pushNode(new LiteralNull(token));
+ }
+
+ void endLiteralSymbol(Token hashToken, int identifierCount) {
+ NodeList identifiers = makeNodeList(identifierCount, null, null, '.');
+ pushNode(new LiteralSymbol(hashToken, identifiers));
+ }
+
+ void handleBinaryExpression(Token token) {
+ Node argument = popNode();
+ Node receiver = popNode();
+ String tokenString = token.stringValue;
+ if (identical(tokenString, '.') ||
+ identical(tokenString, '..') ||
+ identical(tokenString, '?.')) {
+ Send argumentSend = argument.asSend();
+ if (argumentSend == null) {
+ // TODO(ahe): The parser should diagnose this problem, not
+ // this listener.
+ reportFatalError(argument,
+ 'Expected an identifier.');
+ }
+ if (argumentSend.receiver != null) internalError(node: argument);
+ if (argument is SendSet) internalError(node: argument);
+ pushNode(argument.asSend().copyWithReceiver(receiver,
+ identical(tokenString, '?.')));
+ } else {
+ NodeList arguments = new NodeList.singleton(argument);
+ pushNode(new Send(receiver, new Operator(token), arguments));
+ }
+ if (identical(tokenString, '===')) {
+ listener.reportError(token, MessageKind.UNSUPPORTED_EQ_EQ_EQ,
+ {'lhs': receiver, 'rhs': argument});
+ }
+ if (identical(tokenString, '!==')) {
+ listener.reportError(token, MessageKind.UNSUPPORTED_BANG_EQ_EQ,
+ {'lhs': receiver, 'rhs': argument});
+ }
+ }
+
+ void beginCascade(Token token) {
+ pushNode(new CascadeReceiver(popNode(), token));
+ }
+
+ void endCascade() {
+ pushNode(new Cascade(popNode()));
+ }
+
+ void handleAsOperator(Token operathor, Token endToken) {
+ TypeAnnotation type = popNode();
+ Expression expression = popNode();
+ NodeList arguments = new NodeList.singleton(type);
+ pushNode(new Send(expression, new Operator(operathor), arguments));
+ }
+
+ void handleAssignmentExpression(Token token) {
+ Node arg = popNode();
+ Node node = popNode();
+ Send send = node.asSend();
+ if (send == null || !(send.isPropertyAccess || send.isIndex)) {
+ reportNotAssignable(node);
+ }
+ if (send.asSendSet() != null) internalError(node: send);
+ NodeList arguments;
+ if (send.isIndex) {
+ Link<Node> link = const Link<Node>().prepend(arg);
+ link = link.prepend(send.arguments.head);
+ arguments = new NodeList(null, link);
+ } else {
+ arguments = new NodeList.singleton(arg);
+ }
+ Operator op = new Operator(token);
+ pushNode(new SendSet(send.receiver, send.selector, op, arguments,
+ send.isConditional));
+ }
+
+ void reportNotAssignable(Node node) {
+ // TODO(ahe): The parser should diagnose this problem, not this
+ // listener.
+ reportFatalError(node,
+ 'Not assignable.');
+ }
+
+ void handleConditionalExpression(Token question, Token colon) {
+ Node elseExpression = popNode();
+ Node thenExpression = popNode();
+ Node condition = popNode();
+ pushNode(new Conditional(
+ condition, thenExpression, elseExpression, question, colon));
+ }
+
+ void endSend(Token token) {
+ NodeList arguments = popNode();
+ Node selector = popNode();
+ // TODO(ahe): Handle receiver.
+ pushNode(new Send(null, selector, arguments));
+ }
+
+ void endFunctionBody(int count, Token beginToken, Token endToken) {
+ if (count == 0 && beginToken == null) {
+ pushNode(new EmptyStatement(endToken));
+ } else {
+ pushNode(new Block(makeNodeList(count, beginToken, endToken, null)));
+ }
+ }
+
+ void handleAsyncModifier(Token asyncToken, Token starToken) {
+ if (asyncToken != null) {
+ pushNode(new AsyncModifier(asyncToken, starToken));
+ } else {
+ pushNode(null);
+ }
+ }
+
+ void skippedFunctionBody(Token token) {
+ pushNode(new Block(new NodeList.empty()));
+ }
+
+ void handleNoFunctionBody(Token token) {
+ pushNode(new EmptyStatement(token));
+ }
+
+ void endFunction(Token getOrSet, Token endToken) {
+ Statement body = popNode();
+ AsyncModifier asyncModifier = popNode();
+ NodeList initializers = popNode();
+ NodeList formals = popNode();
+ // The name can be an identifier or a send in case of named constructors.
+ Expression name = popNode();
+ TypeAnnotation type = popNode();
+ Modifiers modifiers = popNode();
+ pushNode(new FunctionExpression(name, formals, body, type,
+ modifiers, initializers, getOrSet,
+ asyncModifier));
+ }
+
+ void endFunctionDeclaration(Token endToken) {
+ pushNode(new FunctionDeclaration(popNode()));
+ }
+
+ void endVariablesDeclaration(int count, Token endToken) {
+ // TODO(ahe): Pick one name for this concept, either
+ // VariablesDeclaration or VariableDefinitions.
+ NodeList variables = makeNodeList(count, null, endToken, ",");
+ TypeAnnotation type = popNode();
+ Modifiers modifiers = popNode();
+ pushNode(new VariableDefinitions(type, modifiers, variables));
+ }
+
+ void endInitializer(Token assignmentOperator) {
+ Expression initializer = popNode();
+ NodeList arguments =
+ initializer == null ? null : new NodeList.singleton(initializer);
+ Expression name = popNode();
+ Operator op = new Operator(assignmentOperator);
+ pushNode(new SendSet(null, name, op, arguments));
+ }
+
+ void endIfStatement(Token ifToken, Token elseToken) {
+ Statement elsePart = (elseToken == null) ? null : popNode();
+ Statement thenPart = popNode();
+ ParenthesizedExpression condition = popNode();
+ pushNode(new If(condition, thenPart, elsePart, ifToken, elseToken));
+ }
+
+ void endForStatement(int updateExpressionCount,
+ Token beginToken, Token endToken) {
+ Statement body = popNode();
+ NodeList updates = makeNodeList(updateExpressionCount, null, null, ',');
+ Statement condition = popNode();
+ Node initializer = popNode();
+ pushNode(new For(initializer, condition, updates, body, beginToken));
+ }
+
+ void handleNoExpression(Token token) {
+ pushNode(null);
+ }
+
+ void endDoWhileStatement(Token doKeyword, Token whileKeyword,
+ Token endToken) {
+ Expression condition = popNode();
+ Statement body = popNode();
+ pushNode(new DoWhile(body, condition, doKeyword, whileKeyword, endToken));
+ }
+
+ void endWhileStatement(Token whileKeyword, Token endToken) {
+ Statement body = popNode();
+ Expression condition = popNode();
+ pushNode(new While(condition, body, whileKeyword));
+ }
+
+ void endBlock(int count, Token beginToken, Token endToken) {
+ pushNode(new Block(makeNodeList(count, beginToken, endToken, null)));
+ }
+
+ void endThrowExpression(Token throwToken, Token endToken) {
+ Expression expression = popNode();
+ pushNode(new Throw(expression, throwToken, endToken));
+ }
+
+ void endAwaitExpression(Token awaitToken, Token endToken) {
+ Expression expression = popNode();
+ pushNode(new Await(awaitToken, expression));
+ }
+
+ void endRethrowStatement(Token throwToken, Token endToken) {
+ pushNode(new Rethrow(throwToken, endToken));
+ if (identical(throwToken.stringValue, 'throw')) {
+ listener.reportError(throwToken,
+ MessageKind.UNSUPPORTED_THROW_WITHOUT_EXP);
+ }
+ }
+
+ void handleUnaryPrefixExpression(Token token) {
+ pushNode(new Send.prefix(popNode(), new Operator(token)));
+ }
+
+ void handleSuperExpression(Token token) {
+ pushNode(new Identifier(token));
+ }
+
+ void handleThisExpression(Token token) {
+ pushNode(new Identifier(token));
+ }
+
+ void handleUnaryAssignmentExpression(Token token, bool isPrefix) {
+ Node node = popNode();
+ Send send = node.asSend();
+ if (send == null) {
+ reportNotAssignable(node);
+ }
+ if (!(send.isPropertyAccess || send.isIndex)) {
+ reportNotAssignable(node);
+ }
+ if (send.asSendSet() != null) internalError(node: send);
+ Node argument = null;
+ if (send.isIndex) argument = send.arguments.head;
+ Operator op = new Operator(token);
+
+ if (isPrefix) {
+ pushNode(new SendSet.prefix(send.receiver, send.selector, op, argument,
+ send.isConditional));
+ } else {
+ pushNode(new SendSet.postfix(send.receiver, send.selector, op, argument,
+ send.isConditional));
+ }
+ }
+
+ void handleUnaryPostfixAssignmentExpression(Token token) {
+ handleUnaryAssignmentExpression(token, false);
+ }
+
+ void handleUnaryPrefixAssignmentExpression(Token token) {
+ handleUnaryAssignmentExpression(token, true);
+ }
+
+ void endInitializers(int count, Token beginToken, Token endToken) {
+ pushNode(makeNodeList(count, beginToken, null, ','));
+ }
+
+ void handleNoInitializers() {
+ pushNode(null);
+ }
+
+ void endFields(int count, Token beginToken, Token endToken) {
+ NodeList variables = makeNodeList(count, null, endToken, ",");
+ TypeAnnotation type = popNode();
+ Modifiers modifiers = popNode();
+ pushNode(new VariableDefinitions(type, modifiers, variables));
+ }
+
+ void endMethod(Token getOrSet, Token beginToken, Token endToken) {
+ Statement body = popNode();
+ AsyncModifier asyncModifier = popNode();
+ NodeList initializers = popNode();
+ NodeList formalParameters = popNode();
+ Expression name = popNode();
+ TypeAnnotation returnType = popNode();
+ Modifiers modifiers = popNode();
+ pushNode(new FunctionExpression(name, formalParameters, body, returnType,
+ modifiers, initializers, getOrSet,
+ asyncModifier));
+ }
+
+ void handleLiteralMap(int count, Token beginToken, Token constKeyword,
+ Token endToken) {
+ NodeList entries = makeNodeList(count, beginToken, endToken, ',');
+ NodeList typeArguments = popNode();
+ pushNode(new LiteralMap(typeArguments, entries, constKeyword));
+ }
+
+ void endLiteralMapEntry(Token colon, Token endToken) {
+ Expression value = popNode();
+ Expression key = popNode();
+ pushNode(new LiteralMapEntry(key, colon, value));
+ }
+
+ void handleLiteralList(int count, Token beginToken, Token constKeyword,
+ Token endToken) {
+ NodeList elements = makeNodeList(count, beginToken, endToken, ',');
+ pushNode(new LiteralList(popNode(), elements, constKeyword));
+ }
+
+ void handleIndexedExpression(Token openSquareBracket,
+ Token closeSquareBracket) {
+ NodeList arguments =
+ makeNodeList(1, openSquareBracket, closeSquareBracket, null);
+ Node receiver = popNode();
+ Token token = new StringToken.fromString(Precedence.INDEX_INFO, '[]',
+ openSquareBracket.charOffset);
+ Node selector = new Operator(token);
+ pushNode(new Send(receiver, selector, arguments));
+ }
+
+ void handleNewExpression(Token token) {
+ NodeList arguments = popNode();
+ Node name = popNode();
+ pushNode(new NewExpression(token, new Send(null, name, arguments)));
+ }
+
+ void handleConstExpression(Token token) {
+ // [token] carries the 'const' information.
+ handleNewExpression(token);
+ }
+
+ void handleOperator(Token token) {
+ pushNode(new Operator(token));
+ }
+
+ void handleOperatorName(Token operatorKeyword, Token token) {
+ Operator op = new Operator(token);
+ pushNode(new Send(new Identifier(operatorKeyword), op, null));
+ }
+
+ void handleNamedArgument(Token colon) {
+ Expression expression = popNode();
+ Identifier name = popNode();
+ pushNode(new NamedArgument(name, colon, expression));
+ }
+
+ void endOptionalFormalParameters(int count,
+ Token beginToken, Token endToken) {
+ pushNode(makeNodeList(count, beginToken, endToken, ','));
+ }
+
+ void handleFunctionTypedFormalParameter(Token endToken) {
+ NodeList formals = popNode();
+ Identifier name = popNode();
+ TypeAnnotation returnType = popNode();
+ pushNode(null); // Signal "no type" to endFormalParameter.
+ pushNode(new FunctionExpression(name, formals, null, returnType,
+ Modifiers.EMPTY, null, null, null));
+ }
+
+ void handleValuedFormalParameter(Token equals, Token token) {
+ Expression defaultValue = popNode();
+ Expression parameterName = popNode();
+ pushNode(new SendSet(null, parameterName, new Operator(equals),
+ new NodeList.singleton(defaultValue)));
+ }
+
+ void endTryStatement(int catchCount, Token tryKeyword, Token finallyKeyword) {
+ Block finallyBlock = null;
+ if (finallyKeyword != null) {
+ finallyBlock = popNode();
+ }
+ NodeList catchBlocks = makeNodeList(catchCount, null, null, null);
+ Block tryBlock = popNode();
+ pushNode(new TryStatement(tryBlock, catchBlocks, finallyBlock,
+ tryKeyword, finallyKeyword));
+ }
+
+ void handleCaseMatch(Token caseKeyword, Token colon) {
+ pushNode(new CaseMatch(caseKeyword, popNode(), colon));
+ }
+
+ void handleCatchBlock(Token onKeyword, Token catchKeyword) {
+ Block block = popNode();
+ NodeList formals = catchKeyword != null? popNode(): null;
+ TypeAnnotation type = onKeyword != null ? popNode() : null;
+ pushNode(new CatchBlock(type, formals, block, onKeyword, catchKeyword));
+ }
+
+ void endSwitchStatement(Token switchKeyword, Token endToken) {
+ NodeList cases = popNode();
+ ParenthesizedExpression expression = popNode();
+ pushNode(new SwitchStatement(expression, cases, switchKeyword));
+ }
+
+ void endSwitchBlock(int caseCount, Token beginToken, Token endToken) {
+ Link<Node> caseNodes = const Link<Node>();
+ while (caseCount > 0) {
+ SwitchCase switchCase = popNode();
+ caseNodes = caseNodes.prepend(switchCase);
+ caseCount--;
+ }
+ pushNode(new NodeList(beginToken, caseNodes, endToken, null));
+ }
+
+ void handleSwitchCase(int labelCount, int caseCount,
+ Token defaultKeyword, int statementCount,
+ Token firstToken, Token endToken) {
+ NodeList statements = makeNodeList(statementCount, null, null, null);
+ NodeList labelsAndCases =
+ makeNodeList(labelCount + caseCount, null, null, null);
+ pushNode(new SwitchCase(labelsAndCases, defaultKeyword, statements,
+ firstToken));
+ }
+
+ void handleBreakStatement(bool hasTarget,
+ Token breakKeyword, Token endToken) {
+ Identifier target = null;
+ if (hasTarget) {
+ target = popNode();
+ }
+ pushNode(new BreakStatement(target, breakKeyword, endToken));
+ }
+
+ void handleContinueStatement(bool hasTarget,
+ Token continueKeyword, Token endToken) {
+ Identifier target = null;
+ if (hasTarget) {
+ target = popNode();
+ }
+ pushNode(new ContinueStatement(target, continueKeyword, endToken));
+ }
+
+ void handleEmptyStatement(Token token) {
+ pushNode(new EmptyStatement(token));
+ }
+
+ void endFactoryMethod(Token beginToken, Token endToken) {
+ super.endFactoryMethod(beginToken, endToken);
+ Statement body = popNode();
+ AsyncModifier asyncModifier = popNode();
+ NodeList formals = popNode();
+ Node name = popNode();
+
+ // TODO(ahe): Move this parsing to the parser.
+ int modifierCount = 0;
+ Token modifier = beginToken;
+ if (modifier.stringValue == "external") {
+ handleModifier(modifier);
+ modifierCount++;
+ modifier = modifier.next;
+ }
+ if (modifier.stringValue == "const") {
+ handleModifier(modifier);
+ modifierCount++;
+ modifier = modifier.next;
+ }
+ assert(modifier.stringValue == "factory");
+ handleModifier(modifier);
+ modifierCount++;
+ handleModifiers(modifierCount);
+ Modifiers modifiers = popNode();
+
+ pushNode(new FunctionExpression(name, formals, body, null,
+ modifiers, null, null, asyncModifier));
+ }
+
+ void endForIn(Token awaitToken, Token forToken,
+ Token inKeyword, Token endToken) {
+ Statement body = popNode();
+ Expression expression = popNode();
+ Node declaredIdentifier = popNode();
+ if (awaitToken == null) {
+ pushNode(new SyncForIn(declaredIdentifier, expression, body,
+ forToken, inKeyword));
+ } else {
+ pushNode(new AsyncForIn(declaredIdentifier, expression, body, awaitToken,
+ forToken, inKeyword));
+ }
+ }
+
+ void endMetadataStar(int count, bool forParameter) {
+ // TODO(johnniwinther): Handle metadata for all node kinds.
+ if (forParameter) {
+ if (0 == count) {
+ pushNode(null);
+ } else {
+ pushNode(makeNodeList(count, null, null, ' '));
+ }
+ }
+ }
+
+ void endMetadata(Token beginToken, Token periodBeforeName, Token endToken) {
+ NodeList arguments = popNode();
+ if (arguments == null) {
+ // This is a constant expression.
+ Identifier name;
+ if (periodBeforeName != null) {
+ name = popNode();
+ }
+ NodeList typeArguments = popNode();
+ Node receiver = popNode();
+ if (typeArguments != null) {
+ receiver = new TypeAnnotation(receiver, typeArguments);
+ recoverableError(typeArguments,
+ 'Type arguments are not allowed here.');
+ } else {
+ Identifier identifier = receiver.asIdentifier();
+ Send send = receiver.asSend();
+ if (identifier != null) {
+ receiver = new Send(null, identifier);
+ } else if (send == null) {
+ internalError(node: receiver);
+ }
+ }
+ Send send = receiver;
+ if (name != null) {
+ send = new Send(receiver, name);
+ }
+ pushNode(new Metadata(beginToken, send));
+ } else {
+ // This is a const constructor call.
+ endConstructorReference(beginToken, periodBeforeName, endToken);
+ Node constructor = popNode();
+ pushNode(new Metadata(beginToken,
+ new NewExpression(null,
+ new Send(null, constructor, arguments))));
+ }
+ }
+
+ void handleAssertStatement(Token assertKeyword, Token semicolonToken) {
+ NodeList arguments = popNode();
+ Node selector = new Identifier(assertKeyword);
+ Node send = new Send(null, selector, arguments);
+ pushNode(new ExpressionStatement(send, semicolonToken));
+ }
+
+ void endUnnamedFunction(Token token) {
+ Statement body = popNode();
+ AsyncModifier asyncModifier = popNode();
+ NodeList formals = popNode();
+ pushNode(new FunctionExpression(null, formals, body, null,
+ Modifiers.EMPTY, null, null,
+ asyncModifier));
+ }
+
+ void handleIsOperator(Token operathor, Token not, Token endToken) {
+ TypeAnnotation type = popNode();
+ Expression expression = popNode();
+ Node argument;
+ if (not != null) {
+ argument = new Send.prefix(type, new Operator(not));
+ } else {
+ argument = type;
+ }
+
+ NodeList arguments = new NodeList.singleton(argument);
+ pushNode(new Send(expression, new Operator(operathor), arguments));
+ }
+
+ void handleLabel(Token colon) {
+ Identifier name = popNode();
+ pushNode(new Label(name, colon));
+ }
+
+ void endLabeledStatement(int labelCount) {
+ Statement statement = popNode();
+ NodeList labels = makeNodeList(labelCount, null, null, null);
+ pushNode(new LabeledStatement(labels, statement));
+ }
+
+ void log(message) {
+ listener.log(message);
+ }
+
+ void internalError({Token token, Node node}) {
+ // TODO(ahe): This should call listener.internalError.
+ Spannable spannable = (token == null) ? node : token;
+ throw new SpannableAssertionFailure(spannable, 'Internal error in parser.');
+ }
+}
diff --git a/pkg/compiler/lib/src/scanner/parser.dart b/pkg/compiler/lib/src/parser/parser.dart
similarity index 98%
rename from pkg/compiler/lib/src/scanner/parser.dart
rename to pkg/compiler/lib/src/parser/parser.dart
index 66d26bd..68f96bc 100644
--- a/pkg/compiler/lib/src/scanner/parser.dart
+++ b/pkg/compiler/lib/src/parser/parser.dart
@@ -2,7 +2,65 @@
// 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.
-part of scanner;
+library dart2js.parser;
+
+import '../diagnostics/messages.dart' show
+ MessageKind;
+import '../tokens/keyword.dart' show
+ Keyword;
+import '../tokens/precedence.dart' show
+ PrecedenceInfo;
+import '../tokens/precedence_constants.dart' show
+ AS_INFO,
+ ASSIGNMENT_PRECEDENCE,
+ CASCADE_PRECEDENCE,
+ EQUALITY_PRECEDENCE,
+ GT_INFO,
+ GT_GT_INFO,
+ IS_INFO,
+ MINUS_MINUS_INFO,
+ OPEN_PAREN_INFO,
+ OPEN_SQUARE_BRACKET_INFO,
+ PERIOD_INFO,
+ PLUS_PLUS_INFO,
+ POSTFIX_PRECEDENCE,
+ QUESTION_INFO,
+ QUESTION_PERIOD_INFO,
+ RELATIONAL_PRECEDENCE;
+import '../tokens/token.dart' show
+ BeginGroupToken,
+ isUserDefinableOperator,
+ KeywordToken,
+ SymbolToken,
+ Token;
+import '../tokens/token_constants.dart' show
+ BAD_INPUT_TOKEN,
+ COMMA_TOKEN,
+ DOUBLE_TOKEN,
+ EOF_TOKEN,
+ EQ_TOKEN,
+ FUNCTION_TOKEN,
+ HASH_TOKEN,
+ HEXADECIMAL_TOKEN,
+ IDENTIFIER_TOKEN,
+ INT_TOKEN,
+ KEYWORD_TOKEN,
+ LT_TOKEN,
+ OPEN_CURLY_BRACKET_TOKEN,
+ OPEN_PAREN_TOKEN,
+ OPEN_SQUARE_BRACKET_TOKEN,
+ PERIOD_TOKEN,
+ SEMICOLON_TOKEN,
+ STRING_INTERPOLATION_IDENTIFIER_TOKEN,
+ STRING_INTERPOLATION_TOKEN,
+ STRING_TOKEN;
+import '../util/characters.dart' as Characters show
+ $CLOSE_CURLY_BRACKET;
+import '../util/util.dart' show
+ Link;
+
+import 'listener.dart' show
+ Listener;
class FormalParameterType {
final String type;
@@ -452,7 +510,7 @@
Token endGroup = beginGroupToken.endGroup;
if (endGroup == null) {
return listener.unmatched(beginGroupToken);
- } else if (!identical(endGroup.kind, $CLOSE_CURLY_BRACKET)) {
+ } else if (!identical(endGroup.kind, Characters.$CLOSE_CURLY_BRACKET)) {
return listener.unmatched(beginGroupToken);
}
return beginGroupToken.endGroup;
diff --git a/pkg/compiler/lib/src/scanner/parser_task.dart b/pkg/compiler/lib/src/parser/parser_task.dart
similarity index 66%
rename from pkg/compiler/lib/src/scanner/parser_task.dart
rename to pkg/compiler/lib/src/parser/parser_task.dart
index c680a31..a0e900a4 100644
--- a/pkg/compiler/lib/src/scanner/parser_task.dart
+++ b/pkg/compiler/lib/src/parser/parser_task.dart
@@ -2,7 +2,27 @@
// 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.
-part of scanner;
+library dart2js.parser.task;
+
+import '../common/tasks.dart' show
+ CompilerTask;
+import '../compiler.dart' show
+ Compiler;
+import '../diagnostics/invariant.dart' show
+ invariant;
+import '../elements/modelx.dart' show
+ ElementX;
+import '../tokens/token.dart' show
+ Token;
+import '../tree/tree.dart' show
+ Node;
+
+import 'listener.dart' show
+ ParserError;
+import 'node_listener.dart' show
+ NodeListener;
+import 'parser.dart' show
+ Parser;
class ParserTask extends CompilerTask {
ParserTask(Compiler compiler) : super(compiler);
diff --git a/pkg/compiler/lib/src/parser/partial_elements.dart b/pkg/compiler/lib/src/parser/partial_elements.dart
new file mode 100644
index 0000000..0b489a1
--- /dev/null
+++ b/pkg/compiler/lib/src/parser/partial_elements.dart
@@ -0,0 +1,499 @@
+// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library dart2js.parser.partial_elements;
+
+import '../compiler.dart' show
+ Compiler;
+import '../dart_types.dart' show DynamicType;
+import '../diagnostics/diagnostic_listener.dart';
+import '../diagnostics/invariant.dart' show
+ invariant;
+import '../diagnostics/messages.dart';
+import '../elements/elements.dart' show
+ CompilationUnitElement,
+ ConstructorElement,
+ Element,
+ ElementKind,
+ GetterElement,
+ LibraryElement,
+ MetadataAnnotation,
+ MethodElement,
+ SetterElement,
+ STATE_NOT_STARTED,
+ STATE_DONE;
+import '../elements/modelx.dart' show
+ BaseFunctionElementX,
+ ClassElementX,
+ ConstructorElementX,
+ DeclarationSite,
+ ElementX,
+ FieldElementX,
+ GetterElementX,
+ MetadataAnnotationX,
+ MethodElementX,
+ SetterElementX,
+ TypedefElementX,
+ VariableList;
+import '../elements/visitor.dart' show
+ ElementVisitor;
+import '../tokens/token.dart' show
+ BadInputToken,
+ BeginGroupToken,
+ ErrorToken,
+ KeywordToken,
+ StringToken,
+ Token,
+ UnmatchedToken,
+ UnterminatedToken;
+import '../tokens/token_constants.dart' as Tokens show
+ EOF_TOKEN;
+import '../tree/tree.dart';
+
+import 'class_element_parser.dart' show
+ ClassElementParser;
+import 'parser.dart' show
+ Parser;
+import 'listener.dart' show
+ ParserError;
+import 'member_listener.dart' show
+ MemberListener;
+import 'node_listener.dart' show
+ NodeListener;
+
+abstract class PartialElement implements DeclarationSite {
+ Token beginToken;
+ Token endToken;
+
+ bool hasParseError = false;
+
+ bool get isErroneous => hasParseError;
+
+ DeclarationSite get declarationSite => this;
+}
+
+abstract class PartialFunctionMixin implements BaseFunctionElementX {
+ FunctionExpression cachedNode;
+ Modifiers get modifiers;
+ Token beginToken;
+ Token getOrSet;
+ Token endToken;
+
+ /**
+ * The position is computed in the constructor using [findMyName]. Computing
+ * it on demand fails in case tokens are GC'd.
+ */
+ Token _position;
+
+ void init(Token beginToken, Token getOrSet, Token endToken) {
+ this.beginToken = beginToken;
+ this.getOrSet = getOrSet;
+ this.endToken = endToken;
+ _position = ElementX.findNameToken(
+ beginToken,
+ modifiers.isFactory || isGenerativeConstructor,
+ name, enclosingElement.name);
+ }
+
+ bool get hasNode => cachedNode != null;
+
+ FunctionExpression get node {
+ assert(invariant(this, cachedNode != null,
+ message: "Node has not been computed for $this."));
+ return cachedNode;
+ }
+
+ FunctionExpression parseNode(DiagnosticListener listener) {
+ if (cachedNode != null) return cachedNode;
+ parseFunction(Parser p) {
+ if (isClassMember && modifiers.isFactory) {
+ p.parseFactoryMethod(beginToken);
+ } else {
+ p.parseFunction(beginToken, getOrSet);
+ }
+ }
+ cachedNode = parse(listener, this, declarationSite, parseFunction);
+ return cachedNode;
+ }
+
+ Token get position => _position;
+
+ void reusePartialFunctionMixin() {
+ cachedNode = null;
+ }
+
+ DeclarationSite get declarationSite;
+}
+
+abstract class PartialFunctionElement
+ implements PartialElement, PartialFunctionMixin {
+
+ factory PartialFunctionElement(
+ String name,
+ Token beginToken,
+ Token getOrSet,
+ Token endToken,
+ Modifiers modifiers,
+ Element enclosingElement,
+ {bool hasBody: true}) {
+ if (getOrSet == null) {
+ return new PartialMethodElement(
+ name, beginToken, endToken, modifiers,
+ enclosingElement, hasBody: hasBody);
+ } else if (identical(getOrSet.stringValue, 'get')) {
+ return new PartialGetterElement(
+ name, beginToken, getOrSet, endToken, modifiers,
+ enclosingElement, hasBody: hasBody);
+ } else {
+ assert(identical(getOrSet.stringValue, 'set'));
+ return new PartialSetterElement(
+ name, beginToken, getOrSet, endToken, modifiers,
+ enclosingElement, hasBody: hasBody);
+ }
+ }
+
+ PartialFunctionElement copyWithEnclosing(Element enclosing);
+}
+
+
+class PartialMethodElement extends MethodElementX
+ with PartialElement, PartialFunctionMixin
+ implements PartialFunctionElement {
+ PartialMethodElement(String name,
+ Token beginToken,
+ Token endToken,
+ Modifiers modifiers,
+ Element enclosing,
+ {bool hasBody: true})
+ : super(name, ElementKind.FUNCTION, modifiers, enclosing, hasBody) {
+ init(beginToken, null, endToken);
+ }
+
+ void reuseElement() {
+ super.reuseElement();
+ reusePartialFunctionMixin();
+ }
+
+ PartialMethodElement copyWithEnclosing(Element enclosing) {
+ return new PartialMethodElement(
+ name, beginToken, endToken, modifiers, enclosing, hasBody: hasBody);
+ }
+}
+
+class PartialGetterElement extends GetterElementX
+ with PartialElement, PartialFunctionMixin
+ implements GetterElement, PartialFunctionElement {
+ PartialGetterElement(String name,
+ Token beginToken,
+ Token getToken,
+ Token endToken,
+ Modifiers modifiers,
+ Element enclosing,
+ {bool hasBody: true})
+ : super(name, modifiers, enclosing, hasBody) {
+ init(beginToken, getToken, endToken);
+ }
+
+ @override
+ SetterElement get setter => abstractField.setter;
+
+ void reuseElement() {
+ super.reuseElement();
+ reusePartialFunctionMixin();
+ }
+
+ PartialGetterElement copyWithEnclosing(Element enclosing) {
+ return new PartialGetterElement(
+ name, beginToken, getOrSet, endToken, modifiers, enclosing,
+ hasBody: hasBody);
+ }
+}
+
+class PartialSetterElement extends SetterElementX
+ with PartialElement, PartialFunctionMixin
+ implements SetterElement, PartialFunctionElement {
+ PartialSetterElement(String name,
+ Token beginToken,
+ Token setToken,
+ Token endToken,
+ Modifiers modifiers,
+ Element enclosing,
+ {bool hasBody: true})
+ : super(name, modifiers, enclosing, hasBody) {
+ init(beginToken, setToken, endToken);
+ }
+
+ @override
+ GetterElement get getter => abstractField.getter;
+
+ void reuseElement() {
+ super.reuseElement();
+ reusePartialFunctionMixin();
+ }
+
+ PartialSetterElement copyWithEnclosing(Element enclosing) {
+ return new PartialSetterElement(
+ name, beginToken, getOrSet, endToken, modifiers, enclosing,
+ hasBody: hasBody);
+ }
+}
+
+class PartialConstructorElement extends ConstructorElementX
+ with PartialElement, PartialFunctionMixin {
+ PartialConstructorElement(String name,
+ Token beginToken,
+ Token endToken,
+ ElementKind kind,
+ Modifiers modifiers,
+ Element enclosing)
+ : super(name, kind, modifiers, enclosing) {
+ init(beginToken, null, endToken);
+ }
+
+ void reuseElement() {
+ super.reuseElement();
+ reusePartialFunctionMixin();
+ }
+}
+
+class PartialFieldList extends VariableList with PartialElement {
+ PartialFieldList(Token beginToken,
+ Token endToken,
+ Modifiers modifiers,
+ bool hasParseError)
+ : super(modifiers) {
+ super.beginToken = beginToken;
+ super.endToken = endToken;
+ super.hasParseError = hasParseError;
+ }
+
+ VariableDefinitions parseNode(Element element, DiagnosticListener listener) {
+ if (definitions != null) return definitions;
+ listener.withCurrentElement(element, () {
+ definitions = parse(
+ listener, element, declarationSite,
+ (Parser parser) => parser.parseMember(beginToken));
+
+ if (!hasParseError &&
+ !definitions.modifiers.isVar &&
+ !definitions.modifiers.isFinal &&
+ !definitions.modifiers.isConst &&
+ definitions.type == null &&
+ !definitions.isErroneous) {
+ listener.reportError(
+ definitions,
+ MessageKind.GENERIC,
+ { 'text': 'A field declaration must start with var, final, '
+ 'const, or a type annotation.' });
+ }
+ });
+ return definitions;
+ }
+
+ computeType(Element element, Compiler compiler) {
+ if (type != null) return type;
+ // TODO(johnniwinther): Compute this in the resolver.
+ compiler.withCurrentElement(element, () {
+ VariableDefinitions node = parseNode(element, compiler);
+ if (node.type != null) {
+ type = compiler.resolver.resolveTypeAnnotation(element, node.type);
+ } else {
+ type = const DynamicType();
+ }
+ });
+ assert(type != null);
+ return type;
+ }
+}
+
+class PartialTypedefElement extends TypedefElementX with PartialElement {
+
+ PartialTypedefElement(
+ String name,
+ Element enclosing,
+ Token beginToken,
+ Token endToken)
+ : super(name, enclosing) {
+ this.beginToken = beginToken;
+ this.endToken = endToken;
+ }
+
+ Token get token => beginToken;
+
+ Node parseNode(DiagnosticListener listener) {
+ if (cachedNode != null) return cachedNode;
+ cachedNode = parse(
+ listener, this, declarationSite,
+ (p) => p.parseTopLevelDeclaration(token));
+ return cachedNode;
+ }
+
+ Token get position => findMyName(token);
+}
+
+/// A [MetadataAnnotation] which is constructed on demand.
+class PartialMetadataAnnotation extends MetadataAnnotationX
+ implements PartialElement {
+ Token beginToken; // TODO(ahe): Make this final when issue 22065 is fixed.
+
+ final Token tokenAfterEndToken;
+
+ Expression cachedNode;
+
+ bool hasParseError = false;
+
+ PartialMetadataAnnotation(this.beginToken, this.tokenAfterEndToken);
+
+ bool get isErroneous => hasParseError;
+
+ DeclarationSite get declarationSite => this;
+
+ Token get endToken {
+ Token token = beginToken;
+ while (token.kind != Tokens.EOF_TOKEN) {
+ if (identical(token.next, tokenAfterEndToken)) break;
+ token = token.next;
+ }
+ assert(token != null);
+ return token;
+ }
+
+ void set endToken(_) {
+ throw new UnsupportedError("endToken=");
+ }
+
+ Node parseNode(DiagnosticListener listener) {
+ if (cachedNode != null) return cachedNode;
+ var metadata = parse(listener,
+ annotatedElement,
+ declarationSite,
+ (p) => p.parseMetadata(beginToken));
+ if (metadata is Metadata) {
+ cachedNode = metadata.expression;
+ return cachedNode;
+ } else {
+ assert (metadata is ErrorNode);
+ return metadata;
+ }
+ }
+
+ bool get hasNode => cachedNode != null;
+
+ Node get node {
+ assert(invariant(this, hasNode));
+ return cachedNode;
+ }
+}
+
+class PartialClassElement extends ClassElementX with PartialElement {
+ ClassNode cachedNode;
+
+ PartialClassElement(String name,
+ Token beginToken,
+ Token endToken,
+ Element enclosing,
+ int id)
+ : super(name, enclosing, id, STATE_NOT_STARTED) {
+ this.beginToken = beginToken;
+ this.endToken = endToken;
+ }
+
+ void set supertypeLoadState(int state) {
+ assert(state == STATE_NOT_STARTED || state == supertypeLoadState + 1);
+ assert(state <= STATE_DONE);
+ super.supertypeLoadState = state;
+ }
+
+ void set resolutionState(int state) {
+ assert(state == STATE_NOT_STARTED || state == resolutionState + 1);
+ assert(state <= STATE_DONE);
+ super.resolutionState = state;
+ }
+
+ bool get hasNode => cachedNode != null;
+
+ ClassNode get node {
+ assert(invariant(this, cachedNode != null,
+ message: "Node has not been computed for $this."));
+ return cachedNode;
+ }
+
+ ClassNode parseNode(Compiler compiler) {
+ if (cachedNode != null) return cachedNode;
+ compiler.withCurrentElement(this, () {
+ compiler.parser.measure(() {
+ MemberListener listener = new MemberListener(compiler, this);
+ Parser parser = new ClassElementParser(listener);
+ try {
+ Token token = parser.parseTopLevelDeclaration(beginToken);
+ assert(identical(token, endToken.next));
+ cachedNode = listener.popNode();
+ assert(
+ invariant(
+ beginToken, listener.nodes.isEmpty,
+ message: "Non-empty listener stack: ${listener.nodes}"));
+ } on ParserError {
+ // TODO(ahe): Often, a ParserError is thrown while parsing the class
+ // body. This means that the stack actually contains most of the
+ // information synthesized below. Consider rewriting the parser so
+ // endClassDeclaration is called before parsing the class body.
+ Identifier name = new Identifier(findMyName(beginToken));
+ NodeList typeParameters = null;
+ Node supertype = null;
+ NodeList interfaces = listener.makeNodeList(0, null, null, ",");
+ Token extendsKeyword = null;
+ NodeList body = listener.makeNodeList(0, beginToken, endToken, null);
+ cachedNode = new ClassNode(
+ Modifiers.EMPTY, name, typeParameters, supertype, interfaces,
+ beginToken, extendsKeyword, body, endToken);
+ hasParseError = true;
+ }
+ });
+ compiler.patchParser.measure(() {
+ if (isPatched) {
+ // TODO(lrn): Perhaps extract functionality so it doesn't
+ // need compiler.
+ compiler.patchParser.parsePatchClassNode(patch);
+ }
+ });
+ });
+ return cachedNode;
+ }
+
+ Token get position => beginToken;
+
+ // TODO(johnniwinther): Ensure that modifiers are always available.
+ Modifiers get modifiers =>
+ cachedNode != null ? cachedNode.modifiers : Modifiers.EMPTY;
+
+ accept(ElementVisitor visitor, arg) {
+ return visitor.visitClassElement(this, arg);
+ }
+
+ PartialClassElement copyWithEnclosing(CompilationUnitElement enclosing) {
+ return new PartialClassElement(name, beginToken, endToken, enclosing, id);
+ }
+}
+
+Node parse(
+ DiagnosticListener diagnosticListener,
+ ElementX element,
+ PartialElement partial,
+ doParse(Parser parser)) {
+ CompilationUnitElement unit = element.compilationUnit;
+ NodeListener listener = new NodeListener(diagnosticListener, unit);
+ listener.memberErrors = listener.memberErrors.prepend(false);
+ try {
+ if (partial.hasParseError) {
+ listener.suppressParseErrors = true;
+ }
+ doParse(new Parser(listener));
+ } on ParserError catch (e) {
+ partial.hasParseError = true;
+ return new ErrorNode(element.position, e.reason);
+ }
+ Node node = listener.popNode();
+ assert(listener.nodes.isEmpty);
+ return node;
+}
diff --git a/pkg/compiler/lib/src/scanner/partial_parser.dart b/pkg/compiler/lib/src/parser/partial_parser.dart
similarity index 90%
rename from pkg/compiler/lib/src/scanner/partial_parser.dart
rename to pkg/compiler/lib/src/parser/partial_parser.dart
index c6ccbf4..b0f5cd5 100644
--- a/pkg/compiler/lib/src/scanner/partial_parser.dart
+++ b/pkg/compiler/lib/src/parser/partial_parser.dart
@@ -2,7 +2,23 @@
// 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.
-part of scanner;
+library dart2js.parser.partial;
+
+import '../diagnostics/messages.dart' show
+ MessageKind;
+import '../util/characters.dart' as Characters show
+ $CLOSE_CURLY_BRACKET;
+import '../tokens/token.dart' show
+ BeginGroupToken,
+ ErrorToken,
+ Token;
+import '../tokens/token_constants.dart' as Tokens show
+ EOF_TOKEN;
+
+import 'listener.dart' show
+ Listener;
+import 'parser.dart' show
+ Parser;
class PartialParser extends Parser {
PartialParser(Listener listener) : super(listener);
@@ -29,7 +45,7 @@
while (true) {
final kind = token.kind;
final value = token.stringValue;
- if ((identical(kind, EOF_TOKEN)) ||
+ if ((identical(kind, Tokens.EOF_TOKEN)) ||
(identical(value, ';')) ||
(identical(value, ',')) ||
(identical(value, '}')) ||
@@ -97,7 +113,7 @@
Token endGroup = beginGroupToken.endGroup;
if (endGroup == null) {
return listener.unmatched(beginGroupToken);
- } else if (!identical(endGroup.kind, $CLOSE_CURLY_BRACKET)) {
+ } else if (!identical(endGroup.kind, Characters.$CLOSE_CURLY_BRACKET)) {
return listener.unmatched(beginGroupToken);
}
return endGroup;
diff --git a/pkg/compiler/lib/src/patch_parser.dart b/pkg/compiler/lib/src/patch_parser.dart
index 0631b16..0f30084 100644
--- a/pkg/compiler/lib/src/patch_parser.dart
+++ b/pkg/compiler/lib/src/patch_parser.dart
@@ -112,7 +112,7 @@
* element.
*/
-library patchparser;
+library dart2js.patchparser;
import 'dart:async';
@@ -135,8 +135,25 @@
SetterElementX;
import 'library_loader.dart' show
LibraryLoader;
-import 'scanner/scannerlib.dart'; // Scanner, Parsers, Listeners
+import 'parser/listener.dart' show
+ Listener,
+ ParserError;
+import 'parser/element_listener.dart' show
+ ElementListener;
+import 'parser/member_listener.dart' show
+ MemberListener;
+import 'parser/partial_elements.dart' show
+ PartialClassElement;
+import 'parser/partial_parser.dart' show
+ PartialParser;
+import 'parser/parser.dart' show
+ Parser;
+import 'scanner/scanner.dart' show
+ Scanner;
import 'script.dart';
+import 'tokens/token.dart' show
+ StringToken,
+ Token;
import 'util/util.dart';
class PatchParserTask extends CompilerTask {
diff --git a/pkg/compiler/lib/src/resolution/class_members.dart b/pkg/compiler/lib/src/resolution/class_members.dart
index b09c4d9..e049206 100644
--- a/pkg/compiler/lib/src/resolution/class_members.dart
+++ b/pkg/compiler/lib/src/resolution/class_members.dart
@@ -377,7 +377,9 @@
// superMember.declarations. Investigate why.
} else if (cls == inherited.declarer.element) {
// An error should already have been reported.
- assert(invariant(declared.element, compiler.compilationFailed));
+ assert(invariant(declared.element, compiler.compilationFailed,
+ message: "Member $inherited inherited from its "
+ "declaring class: ${cls}."));
continue;
}
diff --git a/pkg/compiler/lib/src/resolution/constructors.dart b/pkg/compiler/lib/src/resolution/constructors.dart
index cff366c..66af813 100644
--- a/pkg/compiler/lib/src/resolution/constructors.dart
+++ b/pkg/compiler/lib/src/resolution/constructors.dart
@@ -415,10 +415,9 @@
}
}
-class ConstructorResolver extends CommonResolverVisitor<Element> {
+class ConstructorResolver extends CommonResolverVisitor<ConstructorResult> {
final ResolverVisitor resolver;
- bool inConstContext;
- DartType type;
+ final bool inConstContext;
ConstructorResolver(Compiler compiler, this.resolver,
{bool this.inConstContext: false})
@@ -430,8 +429,10 @@
throw 'not supported';
}
- ErroneousConstructorElementX failOrReturnErroneousConstructorElement(
+ ConstructorResult reportAndCreateErroneousConstructorElement(
Spannable diagnosticNode,
+ ConstructorResultKind resultKind,
+ DartType type,
Element enclosing,
String name,
MessageKind kind,
@@ -448,171 +449,281 @@
} else {
compiler.reportWarning(diagnosticNode, kind, arguments);
}
- return new ErroneousConstructorElementX(
+ ErroneousElement error = new ErroneousConstructorElementX(
kind, arguments, name, enclosing);
+ if (type == null) {
+ type = new MalformedType(error, null);
+ }
+ return new ConstructorResult(resultKind, error, type);
}
- FunctionElement resolveConstructor(ClassElement cls,
- Node diagnosticNode,
- String constructorName) {
+ ConstructorResult resolveConstructor(
+ InterfaceType type,
+ Node diagnosticNode,
+ String constructorName) {
+ ClassElement cls = type.element;
cls.ensureResolved(compiler);
- Element result = cls.lookupConstructor(constructorName);
+ ConstructorElement constructor = cls.lookupConstructor(constructorName);
// TODO(johnniwinther): Use [Name] for lookup.
if (Name.isPrivateName(constructorName) &&
resolver.enclosingElement.library != cls.library) {
- result = null;
+ constructor = null;
}
- if (result == null) {
- String fullConstructorName = Elements.constructorNameForDiagnostics(
- cls.name,
- constructorName);
- return failOrReturnErroneousConstructorElement(
+ if (constructor == null) {
+ String fullConstructorName =
+ Elements.constructorNameForDiagnostics(cls.name, constructorName);
+ return reportAndCreateErroneousConstructorElement(
diagnosticNode,
+ ConstructorResultKind.UNRESOLVED_CONSTRUCTOR, type,
cls, constructorName,
MessageKind.CANNOT_FIND_CONSTRUCTOR,
{'constructorName': fullConstructorName},
missingConstructor: true);
- } else if (inConstContext && !result.isConst) {
- error(diagnosticNode, MessageKind.CONSTRUCTOR_IS_NOT_CONST);
+ } else if (inConstContext && !constructor.isConst) {
+ compiler.reportError(
+ diagnosticNode, MessageKind.CONSTRUCTOR_IS_NOT_CONST);
+ return new ConstructorResult(
+ ConstructorResultKind.NON_CONSTANT, constructor, type);
+ } else {
+ if (constructor.isGenerativeConstructor) {
+ if (cls.isAbstract) {
+ compiler.reportWarning(
+ diagnosticNode, MessageKind.ABSTRACT_CLASS_INSTANTIATION);
+ registry.registerAbstractClassInstantiation();
+ return new ConstructorResult(
+ ConstructorResultKind.ABSTRACT, constructor, type);
+ } else {
+ return new ConstructorResult(
+ ConstructorResultKind.GENERATIVE, constructor, type);
+ }
+ } else {
+ assert(invariant(diagnosticNode, constructor.isFactoryConstructor,
+ message: "Unexpected constructor $constructor."));
+ return new ConstructorResult(
+ ConstructorResultKind.FACTORY, constructor, type);
+ }
}
- return result;
}
- Element visitNewExpression(NewExpression node) {
- inConstContext = node.isConst;
+ ConstructorResult visitNewExpression(NewExpression node) {
Node selector = node.send.selector;
- Element element = visit(selector);
- assert(invariant(selector, element != null,
- message: 'No element return for $selector.'));
- return finishConstructorReference(element, node.send.selector, node);
+ ConstructorResult result = visit(selector);
+ assert(invariant(selector, result != null,
+ message: 'No result returned for $selector.'));
+ return finishConstructorReference(result, node.send.selector, node);
}
/// Finishes resolution of a constructor reference and records the
/// type of the constructed instance on [expression].
- FunctionElement finishConstructorReference(Element element,
- Node diagnosticNode,
- Node expression) {
- assert(invariant(diagnosticNode, element != null,
- message: 'No element return for $diagnosticNode.'));
+ ConstructorResult finishConstructorReference(
+ ConstructorResult result,
+ Node diagnosticNode,
+ Node expression) {
+ assert(invariant(diagnosticNode, result != null,
+ message: 'No result returned for $diagnosticNode.'));
+
+ if (result.kind != null) {
+ resolver.registry.setType(expression, result.type);
+ return result;
+ }
+
// Find the unnamed constructor if the reference resolved to a
// class.
- if (!Elements.isUnresolved(element) && !element.isConstructor) {
- if (element.isClass) {
- ClassElement cls = element;
- cls.ensureResolved(compiler);
- // The unnamed constructor may not exist, so [e] may become unresolved.
- element = resolveConstructor(cls, diagnosticNode, '');
+ if (result.type != null) {
+ // The unnamed constructor may not exist, so [e] may become unresolved.
+ result = resolveConstructor(result.type, diagnosticNode, '');
+ } else {
+ Element element = result.element;
+ if (element.isErroneous) {
+ result = constructorResultForErroneous(diagnosticNode, element);
} else {
- element = failOrReturnErroneousConstructorElement(
+ result = reportAndCreateErroneousConstructorElement(
diagnosticNode,
+ ConstructorResultKind.INVALID_TYPE, null,
element, element.name,
MessageKind.NOT_A_TYPE, {'node': diagnosticNode});
}
- } else if (element.isErroneous && element is! ErroneousElementX) {
- // Parser error. The error has already been reported.
- element = new ErroneousConstructorElementX(
- MessageKind.NOT_A_TYPE, {'node': diagnosticNode},
- element.name, element);
- registry.registerThrowRuntimeError();
}
-
- if (type == null) {
- if (Elements.isUnresolved(element)) {
- type = const DynamicType();
- } else {
- type = element.enclosingClass.rawType;
- }
- }
- resolver.registry.setType(expression, type);
- return element;
+ resolver.registry.setType(expression, result.type);
+ return result;
}
- Element visitTypeAnnotation(TypeAnnotation node) {
- assert(invariant(node, type == null));
+ ConstructorResult visitTypeAnnotation(TypeAnnotation node) {
// This is not really resolving a type-annotation, but the name of the
// constructor. Therefore we allow deferred types.
- type = resolver.resolveTypeAnnotation(node,
- malformedIsError: inConstContext,
- deferredIsMalformed: false);
+ DartType type = resolver.resolveTypeAnnotation(
+ node,
+ malformedIsError: inConstContext,
+ deferredIsMalformed: false);
registry.registerRequiredType(type, resolver.enclosingElement);
- return type.element;
+ return constructorResultForType(node, type);
}
- Element visitSend(Send node) {
- Element element = visit(node.receiver);
- assert(invariant(node.receiver, element != null,
- message: 'No element return for $node.receiver.'));
- if (Elements.isUnresolved(element)) return element;
+ ConstructorResult visitSend(Send node) {
+ ConstructorResult receiver = visit(node.receiver);
+ assert(invariant(node.receiver, receiver != null,
+ message: 'No result returned for $node.receiver.'));
+ if (receiver.kind != null) {
+ assert(invariant(node, receiver.element.isErroneous,
+ message: "Unexpected prefix result: $receiver."));
+ // We have already found an error.
+ return receiver;
+ }
+
Identifier name = node.selector.asIdentifier();
if (name == null) internalError(node.selector, 'unexpected node');
- if (element.isClass) {
- ClassElement cls = element;
- cls.ensureResolved(compiler);
- return resolveConstructor(cls, name, name.source);
- } else if (element.isPrefix) {
- PrefixElement prefix = element;
- element = prefix.lookupLocalMember(name.source);
- element = Elements.unwrap(element, compiler, node);
- if (element == null) {
- return failOrReturnErroneousConstructorElement(
+ if (receiver.type != null) {
+ if (receiver.type.isInterfaceType) {
+ return resolveConstructor(receiver.type, name, name.source);
+ } else {
+ // TODO(johnniwinther): Update the message for the different types.
+ return reportAndCreateErroneousConstructorElement(
name,
+ ConstructorResultKind.INVALID_TYPE, null,
resolver.enclosingElement, name.source,
- MessageKind.CANNOT_RESOLVE, {'name': name});
- } else if (!element.isClass) {
- return failOrReturnErroneousConstructorElement(
- name,
- resolver.enclosingElement, name.source,
- MessageKind.NOT_A_TYPE, {'node': name},
- isError: true);
+ MessageKind.NOT_A_TYPE, {'node': name});
}
+ } else if (receiver.element.isPrefix) {
+ PrefixElement prefix = receiver.element;
+ Element member = prefix.lookupLocalMember(name.source);
+ return constructorResultForElement(node, name.source, member);
} else {
- internalError(node.receiver, 'unexpected element $element');
+ return internalError(node.receiver, 'unexpected receiver $receiver');
}
- return element;
}
- Element visitIdentifier(Identifier node) {
+ ConstructorResult visitIdentifier(Identifier node) {
String name = node.source;
Element element = resolver.reportLookupErrorIfAny(
lookupInScope(compiler, node, resolver.scope, name), node, name);
registry.useElement(node, element);
// TODO(johnniwinther): Change errors to warnings, cf. 11.11.1.
+ return constructorResultForElement(node, name, element);
+ }
+
+ /// Assumed to be called by [resolveRedirectingFactory].
+ ConstructorResult visitRedirectingFactoryBody(RedirectingFactoryBody node) {
+ Node constructorReference = node.constructorReference;
+ return finishConstructorReference(visit(constructorReference),
+ constructorReference, node);
+ }
+
+ ConstructorResult constructorResultForElement(
+ Node node, String name, Element element) {
+ element = Elements.unwrap(element, compiler, node);
if (element == null) {
- return failOrReturnErroneousConstructorElement(
+ return reportAndCreateErroneousConstructorElement(
node,
+ ConstructorResultKind.INVALID_TYPE, null,
resolver.enclosingElement, name,
MessageKind.CANNOT_RESOLVE,
{'name': name});
} else if (element.isErroneous) {
- return element;
+ return constructorResultForErroneous(node, element);
+ } else if (element.isClass) {
+ ClassElement cls = element;
+ cls.computeType(compiler);
+ return constructorResultForType(node, cls.rawType);
+ } else if (element.isPrefix) {
+ return new ConstructorResult.forElement(element);
} else if (element.isTypedef) {
- element = failOrReturnErroneousConstructorElement(
- node,
- resolver.enclosingElement, name,
- MessageKind.CANNOT_INSTANTIATE_TYPEDEF, {'typedefName': name},
- isError: true);
+ TypedefElement typdef = element;
+ typdef.ensureResolved(compiler);
+ return constructorResultForType(node, typdef.rawType);
} else if (element.isTypeVariable) {
- element = failOrReturnErroneousConstructorElement(
+ TypeVariableElement typeVariableElement = element;
+ return constructorResultForType(node, typeVariableElement.type);
+ } else {
+ return reportAndCreateErroneousConstructorElement(
node,
+ ConstructorResultKind.INVALID_TYPE, null,
resolver.enclosingElement, name,
- MessageKind.CANNOT_INSTANTIATE_TYPE_VARIABLE,
- {'typeVariableName': name},
- isError: true);
- } else if (!element.isClass && !element.isPrefix) {
- element = failOrReturnErroneousConstructorElement(
- node,
- resolver.enclosingElement, name,
- MessageKind.NOT_A_TYPE, {'node': name},
- isError: true);
+ MessageKind.NOT_A_TYPE, {'node': name});
}
- return element;
}
- /// Assumed to be called by [resolveRedirectingFactory].
- Element visitRedirectingFactoryBody(RedirectingFactoryBody node) {
- Node constructorReference = node.constructorReference;
- return finishConstructorReference(visit(constructorReference),
- constructorReference, node);
+ ConstructorResult constructorResultForErroneous(
+ Node node, Element error) {
+ if (error is! ErroneousElementX) {
+ // Parser error. The error has already been reported.
+ error = new ErroneousConstructorElementX(
+ MessageKind.NOT_A_TYPE, {'node': node},
+ error.name, error);
+ registry.registerThrowRuntimeError();
+ }
+ return new ConstructorResult(
+ ConstructorResultKind.INVALID_TYPE,
+ error,
+ new MalformedType(error, null));
+ }
+
+ ConstructorResult constructorResultForType(
+ Node node,
+ DartType type) {
+ String name = type.name;
+ if (type.isMalformed) {
+ return new ConstructorResult(
+ ConstructorResultKind.INVALID_TYPE, type.element, type);
+ } else if (type.isInterfaceType) {
+ return new ConstructorResult.forType(type);
+ } else if (type.isTypedef) {
+ return reportAndCreateErroneousConstructorElement(
+ node,
+ ConstructorResultKind.INVALID_TYPE, type,
+ resolver.enclosingElement, name,
+ MessageKind.CANNOT_INSTANTIATE_TYPEDEF, {'typedefName': name});
+ } else if (type.isTypeVariable) {
+ return reportAndCreateErroneousConstructorElement(
+ node,
+ ConstructorResultKind.INVALID_TYPE, type,
+ resolver.enclosingElement, name,
+ MessageKind.CANNOT_INSTANTIATE_TYPE_VARIABLE,
+ {'typeVariableName': name});
+ }
+ internalError(node, "Unexpected constructor type $type");
+ return null;
+ }
+
+}
+
+enum ConstructorResultKind {
+ GENERATIVE,
+ FACTORY,
+ ABSTRACT,
+ INVALID_TYPE,
+ UNRESOLVED_CONSTRUCTOR,
+ NON_CONSTANT,
+}
+
+class ConstructorResult {
+ final ConstructorResultKind kind;
+ final Element element;
+ final DartType type;
+
+ ConstructorResult(this.kind, this.element, this.type);
+
+ ConstructorResult.forElement(this.element)
+ : kind = null,
+ type = null;
+
+ ConstructorResult.forType(this.type)
+ : kind = null,
+ element = null;
+
+ String toString() {
+ StringBuffer sb = new StringBuffer();
+ sb.write('ConstructorResult(');
+ if (kind != null) {
+ sb.write('kind=$kind,');
+ sb.write('element=$element,');
+ sb.write('type=$type');
+ } else if (element != null) {
+ sb.write('element=$element');
+ } else {
+ sb.write('type=$type');
+ }
+ sb.write(')');
+ return sb.toString();
}
}
diff --git a/pkg/compiler/lib/src/resolution/enum_creator.dart b/pkg/compiler/lib/src/resolution/enum_creator.dart
index 16882dc..02c2c53 100644
--- a/pkg/compiler/lib/src/resolution/enum_creator.dart
+++ b/pkg/compiler/lib/src/resolution/enum_creator.dart
@@ -8,7 +8,11 @@
import '../dart_types.dart';
import '../elements/elements.dart';
import '../elements/modelx.dart';
-import '../scanner/scannerlib.dart';
+import '../tokens/keyword.dart' show
+ Keyword;
+import '../tokens/precedence.dart';
+import '../tokens/precedence_constants.dart' as Precedence;
+import '../tokens/token.dart';
import '../tree/tree.dart';
import '../util/util.dart';
@@ -45,7 +49,8 @@
}
Token stringToken(String text) {
- return new StringToken.fromString(IDENTIFIER_INFO, text, charOffset);
+ return new StringToken.fromString(
+ Precedence.IDENTIFIER_INFO, text, charOffset);
}
Token symbolToken(PrecedenceInfo info) {
@@ -70,16 +75,16 @@
}
NodeList argumentList(List<Node> nodes) {
- return new NodeList(symbolToken(OPEN_PAREN_INFO),
+ return new NodeList(symbolToken(Precedence.OPEN_PAREN_INFO),
linkedList(nodes),
- symbolToken(CLOSE_PAREN_INFO),
+ symbolToken(Precedence.CLOSE_PAREN_INFO),
',');
}
Return returnStatement(Expression expression) {
return new Return(
keywordToken('return'),
- symbolToken(SEMICOLON_INFO),
+ symbolToken(Precedence.SEMICOLON_INFO),
expression);
}
@@ -101,7 +106,7 @@
}
EmptyStatement emptyStatement() {
- return new EmptyStatement(symbolToken(COMMA_INFO));
+ return new EmptyStatement(symbolToken(Precedence.COMMA_INFO));
}
LiteralInt literalInt(int value) {
@@ -118,17 +123,18 @@
LiteralList listLiteral(List<Node> elements, {bool isConst: false}) {
return new LiteralList(
null,
- new NodeList(symbolToken(OPEN_SQUARE_BRACKET_INFO),
+ new NodeList(symbolToken(Precedence.OPEN_SQUARE_BRACKET_INFO),
linkedList(elements),
- symbolToken(CLOSE_SQUARE_BRACKET_INFO),
+ symbolToken(Precedence.CLOSE_SQUARE_BRACKET_INFO),
','),
isConst ? keywordToken('const') : null);
}
Node createDefinition(Identifier name, Expression initializer) {
if (initializer == null) return name;
- return new SendSet(null, name, new Operator(symbolToken(EQ_INFO)),
- new NodeList.singleton(initializer));
+ return new SendSet(null, name,
+ new Operator(symbolToken(Precedence.EQ_INFO)),
+ new NodeList.singleton(initializer));
}
VariableDefinitions initializingFormal(String fieldName) {
@@ -153,20 +159,20 @@
Send indexGet(Expression receiver, Expression index) {
return new Send(receiver,
- new Operator(symbolToken(INDEX_INFO)),
+ new Operator(symbolToken(Precedence.INDEX_INFO)),
new NodeList.singleton(index));
}
LiteralMapEntry mapLiteralEntry(Expression key, Expression value) {
- return new LiteralMapEntry(key, symbolToken(COLON_INFO), value);
+ return new LiteralMapEntry(key, symbolToken(Precedence.COLON_INFO), value);
}
LiteralMap mapLiteral(List<LiteralMapEntry> entries, {bool isConst: false}) {
return new LiteralMap(
null, // Type arguments.
- new NodeList(symbolToken(OPEN_CURLY_BRACKET_INFO),
+ new NodeList(symbolToken(Precedence.OPEN_CURLY_BRACKET_INFO),
linkedList(entries),
- symbolToken(CLOSE_CURLY_BRACKET_INFO),
+ symbolToken(Precedence.CLOSE_CURLY_BRACKET_INFO),
','),
isConst ? keywordToken('const') : null);
}
diff --git a/pkg/compiler/lib/src/resolution/members.dart b/pkg/compiler/lib/src/resolution/members.dart
index 16aa1a2..5b7558b 100644
--- a/pkg/compiler/lib/src/resolution/members.dart
+++ b/pkg/compiler/lib/src/resolution/members.dart
@@ -33,7 +33,7 @@
ParameterElementX,
VariableElementX,
VariableList;
-import '../scanner/scannerlib.dart' show
+import '../tokens/token.dart' show
isUserDefinableOperator;
import '../tree/tree.dart';
import '../util/util.dart' show
@@ -49,7 +49,8 @@
import 'send_structure.dart';
import 'constructors.dart' show
- ConstructorResolver;
+ ConstructorResolver,
+ ConstructorResult;
import 'label_scope.dart' show
StatementScope;
import 'registry.dart' show
@@ -3636,7 +3637,7 @@
bool isConstConstructor = constructor.isConst;
bool isValidAsConstant = isConstConstructor;
ConstructorElement redirectionTarget = resolveRedirectingFactory(
- node, inConstContext: isConstConstructor);
+ node, inConstContext: isConstConstructor).element;
constructor.immediateRedirectionTarget = redirectionTarget;
Node constructorReference = node.constructorReference;
@@ -3814,7 +3815,7 @@
ResolutionResult visitNewExpression(NewExpression node) {
bool isValidAsConstant = true;
- FunctionElement constructor = resolveConstructor(node);
+ ConstructorElement constructor = resolveConstructor(node).element;
final bool isSymbolConstructor = constructor == compiler.symbolConstructor;
final bool isMirrorsUsedConstant =
node.isConst && (constructor == compiler.mirrorsUsedConstructor);
@@ -3856,8 +3857,6 @@
// factory constructors.
registry.registerInstantiatedType(type);
if (constructor.isGenerativeConstructor && cls.isAbstract) {
- warning(node, MessageKind.ABSTRACT_CLASS_INSTANTIATION);
- registry.registerAbstractClassInstantiation();
isValidAsConstant = false;
}
@@ -3993,14 +3992,15 @@
* Note: this function may return an ErroneousFunctionElement instead of
* [:null:], if there is no corresponding constructor, class or library.
*/
- ConstructorElement resolveConstructor(NewExpression node) {
- return node.accept(new ConstructorResolver(compiler, this));
+ ConstructorResult resolveConstructor(NewExpression node) {
+ return node.accept(new ConstructorResolver(
+ compiler, this, inConstContext: node.isConst));
}
- ConstructorElement resolveRedirectingFactory(RedirectingFactoryBody node,
+ ConstructorResult resolveRedirectingFactory(RedirectingFactoryBody node,
{bool inConstContext: false}) {
- return node.accept(new ConstructorResolver(compiler, this,
- inConstContext: inConstContext));
+ return node.accept(new ConstructorResolver(
+ compiler, this, inConstContext: inConstContext));
}
DartType resolveTypeAnnotation(TypeAnnotation node,
diff --git a/pkg/compiler/lib/src/resolution/resolution.dart b/pkg/compiler/lib/src/resolution/resolution.dart
index d10e886..5874251 100644
--- a/pkg/compiler/lib/src/resolution/resolution.dart
+++ b/pkg/compiler/lib/src/resolution/resolution.dart
@@ -39,7 +39,7 @@
TypedefElementX;
import '../enqueue.dart' show
WorldImpact;
-import '../scanner/scannerlib.dart' show
+import '../tokens/token.dart' show
isBinaryOperator,
isMinusOperator,
isTernaryOperator,
diff --git a/pkg/compiler/lib/src/scanner/array_based_scanner.dart b/pkg/compiler/lib/src/scanner/array_based_scanner.dart
index 457be84..49461fb 100644
--- a/pkg/compiler/lib/src/scanner/array_based_scanner.dart
+++ b/pkg/compiler/lib/src/scanner/array_based_scanner.dart
@@ -2,7 +2,35 @@
// 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.
-part of scanner;
+library dart2js.scanner.array_based;
+
+import '../io/source_file.dart' show
+ SourceFile;
+import '../tokens/keyword.dart' show
+ Keyword;
+import '../tokens/precedence.dart' show
+ PrecedenceInfo;
+import '../tokens/precedence_constants.dart' as Precedence show
+ COMMENT_INFO,
+ EOF_INFO;
+import '../tokens/token.dart' show
+ BeginGroupToken,
+ ErrorToken,
+ KeywordToken,
+ SymbolToken,
+ Token;
+import '../tokens/token_constants.dart' as Tokens show
+ LT_TOKEN,
+ OPEN_CURLY_BRACKET_TOKEN,
+ STRING_INTERPOLATION_TOKEN;
+import '../util/characters.dart' show
+ $LF,
+ $STX;
+import '../util/util.dart' show
+ Link;
+
+import 'scanner.dart' show
+ AbstractScanner;
abstract class ArrayBasedScanner extends AbstractScanner {
ArrayBasedScanner(SourceFile file, bool includeComments)
@@ -64,7 +92,7 @@
unmatchedBeginGroup(groupingStack.head);
groupingStack = groupingStack.tail;
}
- tail.next = new SymbolToken(EOF_INFO, tokenStart);
+ tail.next = new SymbolToken(Precedence.EOF_INFO, tokenStart);
tail = tail.next;
// EOF points to itself so there's always infinite look-ahead.
tail.next = tail;
@@ -105,7 +133,7 @@
tail = tail.next;
// { ( [ ${ cannot appear inside a type parameters / arguments.
- if (!identical(info.kind, LT_TOKEN)) discardOpenLt();
+ if (!identical(info.kind, Tokens.LT_TOKEN)) discardOpenLt();
groupingStack = groupingStack.prepend(token);
}
@@ -115,7 +143,7 @@
* '>>' are handled separately bo [appendGt] and [appendGtGt].
*/
int appendEndGroup(PrecedenceInfo info, int openKind) {
- assert(!identical(openKind, LT_TOKEN)); // openKind is < for > and >>
+ assert(!identical(openKind, Tokens.LT_TOKEN)); // openKind is < for > and >>
discardBeginGroupUntil(openKind);
appendPrecedenceToken(info);
Token close = tail;
@@ -124,8 +152,8 @@
}
BeginGroupToken begin = groupingStack.head;
if (!identical(begin.kind, openKind)) {
- assert(begin.kind == STRING_INTERPOLATION_TOKEN &&
- openKind == OPEN_CURLY_BRACKET_TOKEN);
+ assert(begin.kind == Tokens.STRING_INTERPOLATION_TOKEN &&
+ openKind == Tokens.OPEN_CURLY_BRACKET_TOKEN);
// We're ending an interpolated expression.
begin.endGroup = close;
groupingStack = groupingStack.tail;
@@ -149,8 +177,8 @@
if (groupingStack.isEmpty) return;
BeginGroupToken begin = groupingStack.head;
if (openKind == begin.kind) return;
- if (openKind == OPEN_CURLY_BRACKET_TOKEN &&
- begin.kind == STRING_INTERPOLATION_TOKEN) return;
+ if (openKind == Tokens.OPEN_CURLY_BRACKET_TOKEN &&
+ begin.kind == Tokens.STRING_INTERPOLATION_TOKEN) return;
unmatchedBeginGroup(begin);
groupingStack = groupingStack.tail;
}
@@ -164,7 +192,7 @@
void appendGt(PrecedenceInfo info) {
appendPrecedenceToken(info);
if (groupingStack.isEmpty) return;
- if (identical(groupingStack.head.kind, LT_TOKEN)) {
+ if (identical(groupingStack.head.kind, Tokens.LT_TOKEN)) {
groupingStack.head.endGroup = tail;
groupingStack = groupingStack.tail;
}
@@ -178,13 +206,13 @@
void appendGtGt(PrecedenceInfo info) {
appendPrecedenceToken(info);
if (groupingStack.isEmpty) return;
- if (identical(groupingStack.head.kind, LT_TOKEN)) {
+ if (identical(groupingStack.head.kind, Tokens.LT_TOKEN)) {
// Don't assign endGroup: in "T<U<V>>", the '>>' token closes the outer
// '<', the inner '<' is left without endGroup.
groupingStack = groupingStack.tail;
}
if (groupingStack.isEmpty) return;
- if (identical(groupingStack.head.kind, LT_TOKEN)) {
+ if (identical(groupingStack.head.kind, Tokens.LT_TOKEN)) {
groupingStack.head.endGroup = tail;
groupingStack = groupingStack.tail;
}
@@ -192,7 +220,7 @@
void appendComment(start, bool asciiOnly) {
if (!includeComments) return;
- appendSubstringToken(COMMENT_INFO, start, asciiOnly);
+ appendSubstringToken(Precedence.COMMENT_INFO, start, asciiOnly);
}
void appendErrorToken(ErrorToken token) {
@@ -213,7 +241,7 @@
*/
void discardOpenLt() {
while (!groupingStack.isEmpty
- && identical(groupingStack.head.kind, LT_TOKEN)) {
+ && identical(groupingStack.head.kind, Tokens.LT_TOKEN)) {
groupingStack = groupingStack.tail;
}
}
diff --git a/pkg/compiler/lib/src/scanner/class_element_parser.dart b/pkg/compiler/lib/src/scanner/class_element_parser.dart
deleted file mode 100644
index 627b0ad..0000000
--- a/pkg/compiler/lib/src/scanner/class_element_parser.dart
+++ /dev/null
@@ -1,244 +0,0 @@
-// Copyright (c) 2011, 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.
-
-part of scanner;
-
-class ClassElementParser extends PartialParser {
- ClassElementParser(Listener listener) : super(listener);
-
- Token parseClassBody(Token token) => fullParseClassBody(token);
-}
-
-class PartialClassElement extends ClassElementX with PartialElement {
- ClassNode cachedNode;
-
- PartialClassElement(String name,
- Token beginToken,
- Token endToken,
- Element enclosing,
- int id)
- : super(name, enclosing, id, STATE_NOT_STARTED) {
- this.beginToken = beginToken;
- this.endToken = endToken;
- }
-
- void set supertypeLoadState(int state) {
- assert(state == STATE_NOT_STARTED || state == supertypeLoadState + 1);
- assert(state <= STATE_DONE);
- super.supertypeLoadState = state;
- }
-
- void set resolutionState(int state) {
- assert(state == STATE_NOT_STARTED || state == resolutionState + 1);
- assert(state <= STATE_DONE);
- super.resolutionState = state;
- }
-
- bool get hasNode => cachedNode != null;
-
- ClassNode get node {
- assert(invariant(this, cachedNode != null,
- message: "Node has not been computed for $this."));
- return cachedNode;
- }
-
- ClassNode parseNode(Compiler compiler) {
- if (cachedNode != null) return cachedNode;
- compiler.withCurrentElement(this, () {
- compiler.parser.measure(() {
- MemberListener listener = new MemberListener(compiler, this);
- Parser parser = new ClassElementParser(listener);
- try {
- Token token = parser.parseTopLevelDeclaration(beginToken);
- assert(identical(token, endToken.next));
- cachedNode = listener.popNode();
- assert(
- invariant(
- beginToken, listener.nodes.isEmpty,
- message: "Non-empty listener stack: ${listener.nodes}"));
- } on ParserError {
- // TODO(ahe): Often, a ParserError is thrown while parsing the class
- // body. This means that the stack actually contains most of the
- // information synthesized below. Consider rewriting the parser so
- // endClassDeclaration is called before parsing the class body.
- Identifier name = new Identifier(findMyName(beginToken));
- NodeList typeParameters = null;
- Node supertype = null;
- NodeList interfaces = listener.makeNodeList(0, null, null, ",");
- Token extendsKeyword = null;
- NodeList body = listener.makeNodeList(0, beginToken, endToken, null);
- cachedNode = new ClassNode(
- Modifiers.EMPTY, name, typeParameters, supertype, interfaces,
- beginToken, extendsKeyword, body, endToken);
- hasParseError = true;
- }
- });
- compiler.patchParser.measure(() {
- if (isPatched) {
- // TODO(lrn): Perhaps extract functionality so it doesn't
- // need compiler.
- compiler.patchParser.parsePatchClassNode(patch);
- }
- });
- });
- return cachedNode;
- }
-
- Token get position => beginToken;
-
- // TODO(johnniwinther): Ensure that modifiers are always available.
- Modifiers get modifiers =>
- cachedNode != null ? cachedNode.modifiers : Modifiers.EMPTY;
-
- accept(ElementVisitor visitor, arg) {
- return visitor.visitClassElement(this, arg);
- }
-
- PartialClassElement copyWithEnclosing(CompilationUnitElement enclosing) {
- return new PartialClassElement(name, beginToken, endToken, enclosing, id);
- }
-}
-
-class MemberListener extends NodeListener {
- final ClassElementX enclosingClass;
-
- MemberListener(DiagnosticListener listener,
- ClassElementX enclosingElement)
- : this.enclosingClass = enclosingElement,
- super(listener, enclosingElement.compilationUnit);
-
- bool isConstructorName(Node nameNode) {
- if (enclosingClass == null ||
- enclosingClass.kind != ElementKind.CLASS) {
- return false;
- }
- String name;
- if (nameNode.asIdentifier() != null) {
- name = nameNode.asIdentifier().source;
- } else {
- Send send = nameNode.asSend();
- name = send.receiver.asIdentifier().source;
- }
- return enclosingClass.name == name;
- }
-
- // TODO(johnniwinther): Remove this method.
- String getMethodNameHack(Node methodName) {
- Send send = methodName.asSend();
- if (send == null) {
- if (isConstructorName(methodName)) return '';
- return methodName.asIdentifier().source;
- }
- Identifier receiver = send.receiver.asIdentifier();
- Identifier selector = send.selector.asIdentifier();
- Operator operator = selector.asOperator();
- if (operator != null) {
- assert(identical(receiver.source, 'operator'));
- // TODO(ahe): It is a hack to compare to ')', but it beats
- // parsing the node.
- bool isUnary = identical(operator.token.next.next.stringValue, ')');
- return Elements.constructOperatorName(operator.source, isUnary);
- } else {
- if (receiver == null || receiver.source != enclosingClass.name) {
- listener.reportError(send.receiver,
- MessageKind.INVALID_CONSTRUCTOR_NAME,
- {'name': enclosingClass.name});
- }
- return selector.source;
- }
- }
-
- void endMethod(Token getOrSet, Token beginToken, Token endToken) {
- super.endMethod(getOrSet, beginToken, endToken);
- FunctionExpression method = popNode();
- pushNode(null);
- bool isConstructor = isConstructorName(method.name);
- String name = getMethodNameHack(method.name);
- Element memberElement;
- if (isConstructor) {
- if (getOrSet != null) {
- recoverableError(getOrSet, 'illegal modifier');
- }
- memberElement = new PartialConstructorElement(
- name, beginToken, endToken,
- ElementKind.GENERATIVE_CONSTRUCTOR,
- method.modifiers,
- enclosingClass);
- } else {
- memberElement = new PartialFunctionElement(
- name, beginToken, getOrSet, endToken,
- method.modifiers, enclosingClass, hasBody: method.hasBody());
- }
- addMember(memberElement);
- }
-
- void endFactoryMethod(Token beginToken, Token endToken) {
- super.endFactoryMethod(beginToken, endToken);
- FunctionExpression method = popNode();
- pushNode(null);
- String name = getMethodNameHack(method.name);
- Identifier singleIdentifierName = method.name.asIdentifier();
- if (singleIdentifierName != null && singleIdentifierName.source == name) {
- if (name != enclosingClass.name) {
- listener.reportError(singleIdentifierName,
- MessageKind.INVALID_UNNAMED_CONSTRUCTOR_NAME,
- {'name': enclosingClass.name});
- }
- }
- Element memberElement = new PartialConstructorElement(
- name, beginToken, endToken,
- ElementKind.FUNCTION,
- method.modifiers,
- enclosingClass);
- addMember(memberElement);
- }
-
- void endFields(int count, Token beginToken, Token endToken) {
- bool hasParseError = memberErrors.head;
- super.endFields(count, beginToken, endToken);
- VariableDefinitions variableDefinitions = popNode();
- Modifiers modifiers = variableDefinitions.modifiers;
- pushNode(null);
- void buildFieldElement(Identifier name, VariableList fields) {
- Element element =
- new FieldElementX(name, enclosingClass, fields);
- addMember(element);
- }
- buildFieldElements(modifiers, variableDefinitions.definitions,
- enclosingClass,
- buildFieldElement, beginToken, endToken,
- hasParseError);
- }
-
- void endInitializer(Token assignmentOperator) {
- pushNode(null); // Super expects an expression, but
- // ClassElementParser just skips expressions.
- super.endInitializer(assignmentOperator);
- }
-
- void endInitializers(int count, Token beginToken, Token endToken) {
- pushNode(null);
- }
-
- void addMetadata(ElementX memberElement) {
- for (Link link = metadata; !link.isEmpty; link = link.tail) {
- memberElement.addMetadata(link.head);
- }
- metadata = const Link<MetadataAnnotation>();
- }
-
- void addMember(ElementX memberElement) {
- addMetadata(memberElement);
- enclosingClass.addMember(memberElement, listener);
- }
-
- void endMetadata(Token beginToken, Token periodBeforeName, Token endToken) {
- popNode(); // Discard arguments.
- if (periodBeforeName != null) {
- popNode(); // Discard name.
- }
- popNode(); // Discard node (Send or Identifier).
- pushMetadata(new PartialMetadataAnnotation(beginToken, endToken));
- }
-}
diff --git a/pkg/compiler/lib/src/scanner/listener.dart b/pkg/compiler/lib/src/scanner/listener.dart
deleted file mode 100644
index c3299a3..0000000
--- a/pkg/compiler/lib/src/scanner/listener.dart
+++ /dev/null
@@ -1,2610 +0,0 @@
-// Copyright (c) 2012, 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.
-
-part of scanner;
-
-const bool VERBOSE = false;
-
-/**
- * A parser event listener that does nothing except throw exceptions
- * on parser errors.
- */
-class Listener {
- set suppressParseErrors(bool value) {
- }
-
- void beginArguments(Token token) {
- }
-
- void endArguments(int count, Token beginToken, Token endToken) {
- }
-
- /// Handle async modifiers `async`, `async*`, `sync`.
- void handleAsyncModifier(Token asyncToken, Token startToken) {
- }
-
- void beginAwaitExpression(Token token) {
- }
-
- void endAwaitExpression(Token beginToken, Token endToken) {
- }
-
- void beginBlock(Token token) {
- }
-
- void endBlock(int count, Token beginToken, Token endToken) {
- }
-
- void beginCascade(Token token) {
- }
-
- void endCascade() {
- }
-
- void beginClassBody(Token token) {
- }
-
- void endClassBody(int memberCount, Token beginToken, Token endToken) {
- }
-
- void beginClassDeclaration(Token token) {
- }
-
- void endClassDeclaration(int interfacesCount, Token beginToken,
- Token extendsKeyword, Token implementsKeyword,
- Token endToken) {
- }
-
- void beginCombinators(Token token) {
- }
-
- void endCombinators(int count) {
- }
-
- void beginCompilationUnit(Token token) {
- }
-
- void endCompilationUnit(int count, Token token) {
- }
-
- void beginConstructorReference(Token start) {
- }
-
- void endConstructorReference(Token start, Token periodBeforeName,
- Token endToken) {
- }
-
- void beginDoWhileStatement(Token token) {
- }
-
- void endDoWhileStatement(Token doKeyword, Token whileKeyword,
- Token endToken) {
- }
-
- void beginEnum(Token enumKeyword) {
- }
-
- void endEnum(Token enumKeyword, Token endBrace, int count) {
- }
-
- void beginExport(Token token) {
- }
-
- void endExport(Token exportKeyword, Token semicolon) {
- }
-
- void beginExpressionStatement(Token token) {
- }
-
- void endExpressionStatement(Token token) {
- }
-
- void beginFactoryMethod(Token token) {
- }
-
- void endFactoryMethod(Token beginToken, Token endToken) {
- }
-
- void beginFormalParameter(Token token) {
- }
-
- void endFormalParameter(Token thisKeyword) {
- }
-
- void handleNoFormalParameters(Token token) {
- }
-
- void beginFormalParameters(Token token) {
- }
-
- void endFormalParameters(int count, Token beginToken, Token endToken) {
- }
-
- void endFields(int count, Token beginToken, Token endToken) {
- }
-
- void beginForStatement(Token token) {
- }
-
- void endForStatement(int updateExpressionCount,
- Token beginToken, Token endToken) {
- }
-
- void endForIn(Token awaitToken, Token forToken,
- Token inKeyword, Token endToken) {
- }
-
- void beginFunction(Token token) {
- }
-
- void endFunction(Token getOrSet, Token endToken) {
- }
-
- void beginFunctionDeclaration(Token token) {
- }
-
- void endFunctionDeclaration(Token token) {
- }
-
- void beginFunctionBody(Token token) {
- }
-
- void endFunctionBody(int count, Token beginToken, Token endToken) {
- }
-
- void handleNoFunctionBody(Token token) {
- }
-
- void skippedFunctionBody(Token token) {
- }
-
- void beginFunctionName(Token token) {
- }
-
- void endFunctionName(Token token) {
- }
-
- void beginFunctionTypeAlias(Token token) {
- }
-
- void endFunctionTypeAlias(Token typedefKeyword, Token endToken) {
- }
-
- void beginMixinApplication(Token token) {
- }
-
- void endMixinApplication() {
- }
-
- void beginNamedMixinApplication(Token token) {
- }
-
- void endNamedMixinApplication(Token classKeyword,
- Token implementsKeyword,
- Token endToken) {
- }
-
- void beginHide(Token hideKeyword) {
- }
-
- void endHide(Token hideKeyword) {
- }
-
- void beginIdentifierList(Token token) {
- }
-
- void endIdentifierList(int count) {
- }
-
- void beginTypeList(Token token) {
- }
-
- void endTypeList(int count) {
- }
-
- void beginIfStatement(Token token) {
- }
-
- void endIfStatement(Token ifToken, Token elseToken) {
- }
-
- void beginImport(Token importKeyword) {
- }
-
- void endImport(Token importKeyword, Token DeferredKeyword,
- Token asKeyword, Token semicolon) {
- }
-
- void beginInitializedIdentifier(Token token) {
- }
-
- void endInitializedIdentifier() {
- }
-
- void beginInitializer(Token token) {
- }
-
- void endInitializer(Token assignmentOperator) {
- }
-
- void beginInitializers(Token token) {
- }
-
- void endInitializers(int count, Token beginToken, Token endToken) {
- }
-
- void handleNoInitializers() {
- }
-
- void handleLabel(Token token) {
- }
-
- void beginLabeledStatement(Token token, int labelCount) {
- }
-
- void endLabeledStatement(int labelCount) {
- }
-
- void beginLibraryName(Token token) {
- }
-
- void endLibraryName(Token libraryKeyword, Token semicolon) {
- }
-
- void beginLiteralMapEntry(Token token) {
- }
-
- void endLiteralMapEntry(Token colon, Token endToken) {
- }
-
- void beginLiteralString(Token token) {
- }
-
- void endLiteralString(int interpolationCount) {
- }
-
- void handleStringJuxtaposition(int literalCount) {
- }
-
- void beginMember(Token token) {
- }
-
- void endMethod(Token getOrSet, Token beginToken, Token endToken) {
- }
-
- void beginMetadataStar(Token token) {
- }
-
- void endMetadataStar(int count, bool forParameter) {
- }
-
- void beginMetadata(Token token) {
- }
-
- void endMetadata(Token beginToken, Token periodBeforeName, Token endToken) {
- }
-
- void beginOptionalFormalParameters(Token token) {
- }
-
- void endOptionalFormalParameters(int count,
- Token beginToken, Token endToken) {
- }
-
- void beginPart(Token token) {
- }
-
- void endPart(Token partKeyword, Token semicolon) {
- }
-
- void beginPartOf(Token token) {
- }
-
- void endPartOf(Token partKeyword, Token semicolon) {
- }
-
- void beginRedirectingFactoryBody(Token token) {
- }
-
- void endRedirectingFactoryBody(Token beginToken, Token endToken) {
- }
-
- void beginReturnStatement(Token token) {
- }
-
- void endReturnStatement(bool hasExpression,
- Token beginToken, Token endToken) {
- }
-
- void beginSend(Token token) {
- }
-
- void endSend(Token token) {
- }
-
- void beginShow(Token showKeyword) {
- }
-
- void endShow(Token showKeyword) {
- }
-
- void beginSwitchStatement(Token token) {
- }
-
- void endSwitchStatement(Token switchKeyword, Token endToken) {
- }
-
- void beginSwitchBlock(Token token) {
- }
-
- void endSwitchBlock(int caseCount, Token beginToken, Token endToken) {
- }
-
- void beginLiteralSymbol(Token token) {
- }
-
- void endLiteralSymbol(Token hashToken, int identifierCount) {
- }
-
- void beginThrowExpression(Token token) {
- }
-
- void endThrowExpression(Token throwToken, Token endToken) {
- }
-
- void beginRethrowStatement(Token token) {
- }
-
- void endRethrowStatement(Token throwToken, Token endToken) {
- }
-
- void endTopLevelDeclaration(Token token) {
- }
-
- void beginTopLevelMember(Token token) {
- }
-
- void endTopLevelFields(int count, Token beginToken, Token endToken) {
- }
-
- void endTopLevelMethod(Token beginToken, Token getOrSet, Token endToken) {
- }
-
- void beginTryStatement(Token token) {
- }
-
- void handleCaseMatch(Token caseKeyword, Token colon) {
- }
-
- void handleCatchBlock(Token onKeyword, Token catchKeyword) {
- }
-
- void handleFinallyBlock(Token finallyKeyword) {
- }
-
- void endTryStatement(int catchCount, Token tryKeyword, Token finallyKeyword) {
- }
-
- void endType(Token beginToken, Token endToken) {
- }
-
- void beginTypeArguments(Token token) {
- }
-
- void endTypeArguments(int count, Token beginToken, Token endToken) {
- }
-
- void handleNoTypeArguments(Token token) {
- }
-
- void beginTypeVariable(Token token) {
- }
-
- void endTypeVariable(Token token) {
- }
-
- void beginTypeVariables(Token token) {
- }
-
- void endTypeVariables(int count, Token beginToken, Token endToken) {
- }
-
- void beginUnnamedFunction(Token token) {
- }
-
- void endUnnamedFunction(Token token) {
- }
-
- void beginVariablesDeclaration(Token token) {
- }
-
- void endVariablesDeclaration(int count, Token endToken) {
- }
-
- void beginWhileStatement(Token token) {
- }
-
- void endWhileStatement(Token whileKeyword, Token endToken) {
- }
-
- void handleAsOperator(Token operathor, Token endToken) {
- // TODO(ahe): Rename [operathor] to "operator" when VM bug is fixed.
- }
-
- void handleAssignmentExpression(Token token) {
- }
-
- void handleBinaryExpression(Token token) {
- }
-
- void handleConditionalExpression(Token question, Token colon) {
- }
-
- void handleConstExpression(Token token) {
- }
-
- void handleFunctionTypedFormalParameter(Token token) {
- }
-
- void handleIdentifier(Token token) {
- }
-
- void handleIndexedExpression(Token openCurlyBracket,
- Token closeCurlyBracket) {
- }
-
- void handleIsOperator(Token operathor, Token not, Token endToken) {
- // TODO(ahe): Rename [operathor] to "operator" when VM bug is fixed.
- }
-
- void handleLiteralBool(Token token) {
- }
-
- void handleBreakStatement(bool hasTarget,
- Token breakKeyword, Token endToken) {
- }
-
- void handleContinueStatement(bool hasTarget,
- Token continueKeyword, Token endToken) {
- }
-
- void handleEmptyStatement(Token token) {
- }
-
- void handleAssertStatement(Token assertKeyword, Token semicolonToken) {
- }
-
- /** Called with either the token containing a double literal, or
- * an immediately preceding "unary plus" token.
- */
- void handleLiteralDouble(Token token) {
- }
-
- /** Called with either the token containing an integer literal,
- * or an immediately preceding "unary plus" token.
- */
- void handleLiteralInt(Token token) {
- }
-
- void handleLiteralList(int count, Token beginToken, Token constKeyword,
- Token endToken) {
- }
-
- void handleLiteralMap(int count, Token beginToken, Token constKeyword,
- Token endToken) {
- }
-
- void handleLiteralNull(Token token) {
- }
-
- void handleModifier(Token token) {
- }
-
- void handleModifiers(int count) {
- }
-
- void handleNamedArgument(Token colon) {
- }
-
- void handleNewExpression(Token token) {
- }
-
- void handleNoArguments(Token token) {
- }
-
- void handleNoExpression(Token token) {
- }
-
- void handleNoType(Token token) {
- }
-
- void handleNoTypeVariables(Token token) {
- }
-
- void handleOperator(Token token) {
- }
-
- void handleOperatorName(Token operatorKeyword, Token token) {
- }
-
- void handleParenthesizedExpression(BeginGroupToken token) {
- }
-
- void handleQualified(Token period) {
- }
-
- void handleStringPart(Token token) {
- }
-
- void handleSuperExpression(Token token) {
- }
-
- void handleSwitchCase(int labelCount, int expressionCount,
- Token defaultKeyword, int statementCount,
- Token firstToken, Token endToken) {
- }
-
- void handleThisExpression(Token token) {
- }
-
- void handleUnaryPostfixAssignmentExpression(Token token) {
- }
-
- void handleUnaryPrefixExpression(Token token) {
- }
-
- void handleUnaryPrefixAssignmentExpression(Token token) {
- }
-
- void handleValuedFormalParameter(Token equals, Token token) {
- }
-
- void handleVoidKeyword(Token token) {
- }
-
- void beginYieldStatement(Token token) {
- }
-
- void endYieldStatement(Token yieldToken, Token starToken, Token endToken) {
- }
-
- Token expected(String string, Token token) {
- if (token is ErrorToken) {
- reportErrorToken(token);
- } else {
- error("expected '$string', but got '${token.value}'", token);
- }
- return skipToEof(token);
- }
-
- Token synthesizeIdentifier(Token token) {
- Token synthesizedToken =
- new StringToken.fromString(IDENTIFIER_INFO, '?', token.charOffset);
- synthesizedToken.next = token.next;
- return synthesizedToken;
- }
-
- Token expectedIdentifier(Token token) {
- if (token is ErrorToken) {
- reportErrorToken(token);
- } else {
- error("expected identifier, but got '${token.value}'", token);
- }
- return skipToEof(token);
- }
-
- Token expectedType(Token token) {
- if (token is ErrorToken) {
- reportErrorToken(token);
- } else {
- error("expected a type, but got '${token.value}'", token);
- }
- return skipToEof(token);
- }
-
- Token expectedExpression(Token token) {
- if (token is ErrorToken) {
- reportErrorToken(token);
- } else {
- error("expected an expression, but got '${token.value}'", token);
- }
- return skipToEof(token);
- }
-
- Token unexpected(Token token) {
- if (token is ErrorToken) {
- reportErrorToken(token);
- } else {
- error("unexpected token '${token.value}'", token);
- }
- return skipToEof(token);
- }
-
- Token expectedBlockToSkip(Token token) {
- if (token is ErrorToken) {
- reportErrorToken(token);
- } else {
- error("expected a block, but got '${token.value}'", token);
- }
- return skipToEof(token);
- }
-
- Token expectedFunctionBody(Token token) {
- if (token is ErrorToken) {
- reportErrorToken(token);
- } else {
- error("expected a function body, but got '${token.value}'", token);
- }
- return skipToEof(token);
- }
-
- Token expectedClassBody(Token token) {
- if (token is ErrorToken) {
- reportErrorToken(token);
- } else {
- error("expected a class body, but got '${token.value}'", token);
- }
- return skipToEof(token);
- }
-
- Token expectedClassBodyToSkip(Token token) {
- if (token is ErrorToken) {
- reportErrorToken(token);
- } else {
- error("expected a class body, but got '${token.value}'", token);
- }
- return skipToEof(token);
- }
-
- Token expectedDeclaration(Token token) {
- if (token is ErrorToken) {
- reportErrorToken(token);
- } else {
- error("expected a declaration, but got '${token.value}'", token);
- }
- return skipToEof(token);
- }
-
- Token unmatched(Token token) {
- if (token is ErrorToken) {
- reportErrorToken(token);
- } else {
- error("unmatched '${token.value}'", token);
- }
- return skipToEof(token);
- }
-
- skipToEof(Token token) {
- while (!identical(token.info, EOF_INFO)) {
- token = token.next;
- }
- return token;
- }
-
- void recoverableError(Token token, String message) {
- error(message, token);
- }
-
- void error(String message, Token token) {
- throw new ParserError("$message @ ${token.charOffset}");
- }
-
- void reportError(Spannable spannable,
- MessageKind messageKind,
- [Map arguments = const {}]) {
- MessageTemplate template = MessageTemplate.TEMPLATES[messageKind];
- String message = template.message(arguments, true).toString();
- Token token;
- if (spannable is Token) {
- token = spannable;
- } else if (spannable is Node) {
- token = spannable.getBeginToken();
- } else {
- throw new ParserError(message);
- }
- recoverableError(token, message);
- }
-
- void reportErrorToken(ErrorToken token) {
- if (token is BadInputToken) {
- String hex = token.character.toRadixString(16);
- if (hex.length < 4) {
- String padding = "0000".substring(hex.length);
- hex = "$padding$hex";
- }
- reportError(
- token, MessageKind.BAD_INPUT_CHARACTER, {'characterHex': hex});
- } else if (token is UnterminatedToken) {
- MessageKind kind;
- var arguments = const {};
- switch (token.start) {
- case '1e':
- kind = MessageKind.EXPONENT_MISSING;
- break;
- case '"':
- case "'":
- case '"""':
- case "'''":
- case 'r"':
- case "r'":
- case 'r"""':
- case "r'''":
- kind = MessageKind.UNTERMINATED_STRING;
- arguments = {'quote': token.start};
- break;
- case '0x':
- kind = MessageKind.HEX_DIGIT_EXPECTED;
- break;
- case r'$':
- kind = MessageKind.MALFORMED_STRING_LITERAL;
- break;
- case '/*':
- kind = MessageKind.UNTERMINATED_COMMENT;
- break;
- default:
- kind = MessageKind.UNTERMINATED_TOKEN;
- break;
- }
- reportError(token, kind, arguments);
- } else if (token is UnmatchedToken) {
- String begin = token.begin.value;
- String end = closeBraceFor(begin);
- reportError(
- token, MessageKind.UNMATCHED_TOKEN, {'begin': begin, 'end': end});
- } else {
- throw new SpannableAssertionFailure(token, token.assertionMessage);
- }
- }
-}
-
-String closeBraceFor(String openBrace) {
- return const {
- '(': ')',
- '[': ']',
- '{': '}',
- '<': '>',
- r'${': '}',
- }[openBrace];
-}
-
-class ParserError {
- final String reason;
- ParserError(this.reason);
- toString() => reason;
-}
-
-typedef int IdGenerator();
-
-/**
- * A parser event listener designed to work with [PartialParser]. It
- * builds elements representing the top-level declarations found in
- * the parsed compilation unit and records them in
- * [compilationUnitElement].
- */
-class ElementListener extends Listener {
- final IdGenerator idGenerator;
- final DiagnosticListener listener;
- final CompilationUnitElementX compilationUnitElement;
- final StringValidator stringValidator;
- Link<StringQuoting> interpolationScope;
-
- Link<Node> nodes = const Link<Node>();
-
- Link<MetadataAnnotation> metadata = const Link<MetadataAnnotation>();
-
- /// Records a stack of booleans for each member parsed (a stack is used to
- /// support nested members which isn't currently possible, but it also serves
- /// as a simple way to tell we're currently parsing a member). In this case,
- /// member refers to members of a library or a class (but currently, classes
- /// themselves are not considered members). If the top of the stack
- /// (memberErrors.head) is true, the current member has already reported at
- /// least one parse error.
- Link<bool> memberErrors = const Link<bool>();
-
- bool suppressParseErrors = false;
-
- ElementListener(
- DiagnosticListener listener,
- this.compilationUnitElement,
- this.idGenerator)
- : this.listener = listener,
- stringValidator = new StringValidator(listener),
- interpolationScope = const Link<StringQuoting>();
-
- bool get currentMemberHasParseError {
- return !memberErrors.isEmpty && memberErrors.head;
- }
-
- void pushQuoting(StringQuoting quoting) {
- interpolationScope = interpolationScope.prepend(quoting);
- }
-
- StringQuoting popQuoting() {
- StringQuoting result = interpolationScope.head;
- interpolationScope = interpolationScope.tail;
- return result;
- }
-
- StringNode popLiteralString() {
- StringNode node = popNode();
- // TODO(lrn): Handle interpolations in script tags.
- if (node.isInterpolation) {
- listener.internalError(node,
- "String interpolation not supported in library tags.");
- return null;
- }
- return node;
- }
-
- bool allowLibraryTags() {
- // Library tags are only allowed in the library file itself, not
- // in sourced files.
- LibraryElement library = compilationUnitElement.implementationLibrary;
- return !compilationUnitElement.hasMembers &&
- library.entryCompilationUnit == compilationUnitElement;
- }
-
- void endLibraryName(Token libraryKeyword, Token semicolon) {
- Expression name = popNode();
- addLibraryTag(new LibraryName(libraryKeyword, name,
- popMetadata(compilationUnitElement)));
- }
-
- void endImport(Token importKeyword, Token deferredKeyword, Token asKeyword,
- Token semicolon) {
- NodeList combinators = popNode();
- bool isDeferred = deferredKeyword != null;
- Identifier prefix;
- if (asKeyword != null) {
- prefix = popNode();
- }
- StringNode uri = popLiteralString();
- addLibraryTag(new Import(importKeyword, uri, prefix, combinators,
- popMetadata(compilationUnitElement),
- isDeferred: isDeferred));
- }
-
- void endEnum(Token enumKeyword, Token endBrace, int count) {
- NodeList names = makeNodeList(count, enumKeyword.next.next, endBrace, ",");
- Identifier name = popNode();
-
- int id = idGenerator();
- Element enclosing = compilationUnitElement;
- pushElement(new EnumClassElementX(name.source, enclosing, id,
- new Enum(enumKeyword, name, names)));
- rejectBuiltInIdentifier(name);
- }
-
- void endExport(Token exportKeyword, Token semicolon) {
- NodeList combinators = popNode();
- StringNode uri = popNode();
- addLibraryTag(new Export(exportKeyword, uri, combinators,
- popMetadata(compilationUnitElement)));
- }
-
- void endCombinators(int count) {
- if (0 == count) {
- pushNode(null);
- } else {
- pushNode(makeNodeList(count, null, null, " "));
- }
- }
-
- void endHide(Token hideKeyword) => pushCombinator(hideKeyword);
-
- void endShow(Token showKeyword) => pushCombinator(showKeyword);
-
- void pushCombinator(Token keywordToken) {
- NodeList identifiers = popNode();
- pushNode(new Combinator(identifiers, keywordToken));
- }
-
- void endIdentifierList(int count) {
- pushNode(makeNodeList(count, null, null, ","));
- }
-
- void endTypeList(int count) {
- pushNode(makeNodeList(count, null, null, ","));
- }
-
- void endPart(Token partKeyword, Token semicolon) {
- StringNode uri = popLiteralString();
- addLibraryTag(new Part(partKeyword, uri,
- popMetadata(compilationUnitElement)));
- }
-
- void endPartOf(Token partKeyword, Token semicolon) {
- Expression name = popNode();
- addPartOfTag(new PartOf(partKeyword, name,
- popMetadata(compilationUnitElement)));
- }
-
- void addPartOfTag(PartOf tag) {
- compilationUnitElement.setPartOf(tag, listener);
- }
-
- void endMetadata(Token beginToken, Token periodBeforeName, Token endToken) {
- if (periodBeforeName != null) {
- popNode(); // Discard name.
- }
- popNode(); // Discard node (Send or Identifier).
- pushMetadata(new PartialMetadataAnnotation(beginToken, endToken));
- }
-
- void endTopLevelDeclaration(Token token) {
- if (!metadata.isEmpty) {
- recoverableError(metadata.head.beginToken,
- 'Metadata not supported here.');
- metadata = const Link<MetadataAnnotation>();
- }
- }
-
- void endClassDeclaration(int interfacesCount, Token beginToken,
- Token extendsKeyword, Token implementsKeyword,
- Token endToken) {
- makeNodeList(interfacesCount, implementsKeyword, null, ","); // interfaces
- popNode(); // superType
- popNode(); // typeParameters
- Identifier name = popNode();
- int id = idGenerator();
- PartialClassElement element = new PartialClassElement(
- name.source, beginToken, endToken, compilationUnitElement, id);
- pushElement(element);
- rejectBuiltInIdentifier(name);
- }
-
- void rejectBuiltInIdentifier(Identifier name) {
- if (name.token is KeywordToken) {
- Keyword keyword = (name.token as KeywordToken).keyword;
- if (!keyword.isPseudo) {
- recoverableError(name, "Illegal name '${keyword.syntax}'.");
- }
- }
- }
-
- void endFunctionTypeAlias(Token typedefKeyword, Token endToken) {
- popNode(); // TODO(karlklose): do not throw away typeVariables.
- Identifier name = popNode();
- popNode(); // returnType
- pushElement(
- new PartialTypedefElement(
- name.source, compilationUnitElement, typedefKeyword, endToken));
- rejectBuiltInIdentifier(name);
- }
-
- void endNamedMixinApplication(Token classKeyword,
- Token implementsKeyword,
- Token endToken) {
- NodeList interfaces = (implementsKeyword != null) ? popNode() : null;
- MixinApplication mixinApplication = popNode();
- Modifiers modifiers = popNode();
- NodeList typeParameters = popNode();
- Identifier name = popNode();
- NamedMixinApplication namedMixinApplication = new NamedMixinApplication(
- name, typeParameters, modifiers, mixinApplication, interfaces,
- classKeyword, endToken);
-
- int id = idGenerator();
- Element enclosing = compilationUnitElement;
- pushElement(new MixinApplicationElementX(name.source, enclosing, id,
- namedMixinApplication,
- modifiers));
- rejectBuiltInIdentifier(name);
- }
-
- void endMixinApplication() {
- NodeList mixins = popNode();
- TypeAnnotation superclass = popNode();
- pushNode(new MixinApplication(superclass, mixins));
- }
-
- void handleVoidKeyword(Token token) {
- pushNode(new TypeAnnotation(new Identifier(token), null));
- }
-
- void endTopLevelMethod(Token beginToken, Token getOrSet, Token endToken) {
- bool hasParseError = currentMemberHasParseError;
- memberErrors = memberErrors.tail;
- Identifier name = popNode();
- popNode(); // type
- Modifiers modifiers = popNode();
- PartialFunctionElement element = new PartialFunctionElement(
- name.source, beginToken, getOrSet, endToken,
- modifiers, compilationUnitElement);
- element.hasParseError = hasParseError;
- pushElement(element);
- }
-
- void endTopLevelFields(int count, Token beginToken, Token endToken) {
- bool hasParseError = currentMemberHasParseError;
- memberErrors = memberErrors.tail;
- void buildFieldElement(Identifier name, VariableList fields) {
- pushElement(
- new FieldElementX(name, compilationUnitElement, fields));
- }
- NodeList variables = makeNodeList(count, null, null, ",");
- popNode(); // type
- Modifiers modifiers = popNode();
- buildFieldElements(modifiers, variables, compilationUnitElement,
- buildFieldElement,
- beginToken, endToken, hasParseError);
- }
-
- void buildFieldElements(Modifiers modifiers,
- NodeList variables,
- Element enclosingElement,
- void buildFieldElement(Identifier name,
- VariableList fields),
- Token beginToken, Token endToken,
- bool hasParseError) {
- VariableList fields =
- new PartialFieldList(beginToken, endToken, modifiers, hasParseError);
- for (Link<Node> variableNodes = variables.nodes;
- !variableNodes.isEmpty;
- variableNodes = variableNodes.tail) {
- Expression initializedIdentifier = variableNodes.head;
- Identifier identifier = initializedIdentifier.asIdentifier();
- if (identifier == null) {
- identifier = initializedIdentifier.asSendSet().selector.asIdentifier();
- }
- buildFieldElement(identifier, fields);
- }
- }
-
- void handleIdentifier(Token token) {
- pushNode(new Identifier(token));
- }
-
- void handleQualified(Token period) {
- Identifier last = popNode();
- Expression first = popNode();
- pushNode(new Send(first, last));
- }
-
- void handleNoType(Token token) {
- pushNode(null);
- }
-
- void endTypeVariable(Token token) {
- TypeAnnotation bound = popNode();
- Identifier name = popNode();
- pushNode(new TypeVariable(name, bound));
- rejectBuiltInIdentifier(name);
- }
-
- void endTypeVariables(int count, Token beginToken, Token endToken) {
- pushNode(makeNodeList(count, beginToken, endToken, ','));
- }
-
- void handleNoTypeVariables(token) {
- pushNode(null);
- }
-
- void endTypeArguments(int count, Token beginToken, Token endToken) {
- pushNode(makeNodeList(count, beginToken, endToken, ','));
- }
-
- void handleNoTypeArguments(Token token) {
- pushNode(null);
- }
-
- void endType(Token beginToken, Token endToken) {
- NodeList typeArguments = popNode();
- Expression typeName = popNode();
- pushNode(new TypeAnnotation(typeName, typeArguments));
- }
-
- void handleParenthesizedExpression(BeginGroupToken token) {
- Expression expression = popNode();
- pushNode(new ParenthesizedExpression(expression, token));
- }
-
- void handleModifier(Token token) {
- pushNode(new Identifier(token));
- }
-
- void handleModifiers(int count) {
- if (count == 0) {
- pushNode(Modifiers.EMPTY);
- } else {
- NodeList modifierNodes = makeNodeList(count, null, null, ' ');
- pushNode(new Modifiers(modifierNodes));
- }
- }
-
- Token expected(String string, Token token) {
- if (token is ErrorToken) {
- reportErrorToken(token);
- } else if (identical(';', string)) {
- // When a semicolon is missing, it often leads to an error on the
- // following line. So we try to find the token preceding the semicolon
- // and report that something is missing *after* it.
- Token preceding = findPrecedingToken(token);
- if (preceding == token) {
- reportError(
- token, MessageKind.MISSING_TOKEN_BEFORE_THIS, {'token': string});
- } else {
- reportError(
- preceding, MessageKind.MISSING_TOKEN_AFTER_THIS, {'token': string});
- }
- return token;
- } else {
- reportFatalError(
- token,
- MessageTemplate.TEMPLATES[MessageKind.MISSING_TOKEN_BEFORE_THIS]
- .message({'token': string}, true).toString());
- }
- return skipToEof(token);
- }
-
- /// Finds the preceding token via the begin token of the last AST node pushed
- /// on the [nodes] stack.
- Token findPrecedingToken(Token token) {
- Token result;
- Link<Node> nodes = this.nodes;
- while (!nodes.isEmpty) {
- result = findPrecedingTokenFromNode(nodes.head, token);
- if (result != null) {
- return result;
- }
- nodes = nodes.tail;
- }
- if (compilationUnitElement != null) {
- if (compilationUnitElement is CompilationUnitElementX) {
- CompilationUnitElementX unit = compilationUnitElement;
- Link<Element> members = unit.localMembers;
- while (!members.isEmpty) {
- ElementX member = members.head;
- DeclarationSite site = member.declarationSite;
- if (site is PartialElement) {
- result = findPrecedingTokenFromToken(site.endToken, token);
- if (result != null) {
- return result;
- }
- }
- members = members.tail;
- }
- result =
- findPrecedingTokenFromNode(compilationUnitElement.partTag, token);
- if (result != null) {
- return result;
- }
- }
- }
- return token;
- }
-
- Token findPrecedingTokenFromNode(Node node, Token token) {
- if (node != null) {
- return findPrecedingTokenFromToken(node.getBeginToken(), token);
- }
- return null;
- }
-
- Token findPrecedingTokenFromToken(Token start, Token token) {
- if (start != null) {
- Token current = start;
- while (current.kind != EOF_TOKEN && current.next != token) {
- current = current.next;
- }
- if (current.kind != EOF_TOKEN) {
- return current;
- }
- }
- return null;
- }
-
- Token expectedIdentifier(Token token) {
- if (token is KeywordToken) {
- reportError(
- token, MessageKind.EXPECTED_IDENTIFIER_NOT_RESERVED_WORD,
- {'keyword': token.value});
- } else if (token is ErrorToken) {
- reportErrorToken(token);
- return synthesizeIdentifier(token);
- } else {
- reportFatalError(token,
- "Expected identifier, but got '${token.value}'.");
- }
- return token;
- }
-
- Token expectedType(Token token) {
- pushNode(null);
- if (token is ErrorToken) {
- reportErrorToken(token);
- return synthesizeIdentifier(token);
- } else {
- reportFatalError(
- token, "Expected a type, but got '${token.value}'.");
- return skipToEof(token);
- }
- }
-
- Token expectedExpression(Token token) {
- if (token is ErrorToken) {
- reportErrorToken(token);
- pushNode(new ErrorExpression(token));
- return token.next;
- } else {
- reportFatalError(token,
- "Expected an expression, but got '${token.value}'.");
- pushNode(null);
- return skipToEof(token);
- }
- }
-
- Token unexpected(Token token) {
- if (token is ErrorToken) {
- reportErrorToken(token);
- } else {
- String message = "Unexpected token '${token.value}'.";
- if (token.info == BAD_INPUT_INFO) {
- message = token.value;
- }
- reportFatalError(token, message);
- }
- return skipToEof(token);
- }
-
- Token expectedBlockToSkip(Token token) {
- if (identical(token.stringValue, 'native')) {
- return native.handleNativeBlockToSkip(this, token);
- } else {
- return unexpected(token);
- }
- }
-
- Token expectedFunctionBody(Token token) {
- if (token is ErrorToken) {
- reportErrorToken(token);
- } else {
- String printString = token.value;
- reportFatalError(token,
- "Expected a function body, but got '$printString'.");
- }
- return skipToEof(token);
- }
-
- Token expectedClassBody(Token token) {
- if (token is ErrorToken) {
- reportErrorToken(token);
- } else {
- reportFatalError(token,
- "Expected a class body, but got '${token.value}'.");
- }
- return skipToEof(token);
- }
-
- Token expectedClassBodyToSkip(Token token) {
- return unexpected(token);
- }
-
- Token expectedDeclaration(Token token) {
- if (token is ErrorToken) {
- reportErrorToken(token);
- } else {
- reportFatalError(token,
- "Expected a declaration, but got '${token.value}'.");
- }
- return skipToEof(token);
- }
-
- Token unmatched(Token token) {
- if (token is ErrorToken) {
- reportErrorToken(token);
- } else {
- String begin = token.value;
- String end = closeBraceFor(begin);
- reportError(
- token, MessageKind.UNMATCHED_TOKEN, {'begin': begin, 'end': end});
- }
- Token next = token.next;
- while (next is ErrorToken) {
- next = next.next;
- }
- return next;
- }
-
- void recoverableError(Spannable node, String message) {
- // TODO(johnniwinther): Make recoverable errors non-fatal.
- reportFatalError(node, message);
- }
-
- void pushElement(Element element) {
- popMetadata(element);
- compilationUnitElement.addMember(element, listener);
- }
-
- Link<MetadataAnnotation> popMetadata(ElementX element) {
- var result = const Link<MetadataAnnotation>();
- for (Link link = metadata; !link.isEmpty; link = link.tail) {
- element.addMetadata(link.head);
- // Reverse the list as is implicitly done by addMetadata.
- result = result.prepend(link.head);
- }
- metadata = const Link<MetadataAnnotation>();
- return result;
- }
-
- void pushMetadata(MetadataAnnotation annotation) {
- metadata = metadata.prepend(annotation);
- }
-
- void addLibraryTag(LibraryTag tag) {
- if (!allowLibraryTags()) {
- recoverableError(tag, 'Library tags not allowed here.');
- }
- LibraryElementX implementationLibrary =
- compilationUnitElement.implementationLibrary;
- implementationLibrary.addTag(tag, listener);
- }
-
- void pushNode(Node node) {
- nodes = nodes.prepend(node);
- if (VERBOSE) log("push $nodes");
- }
-
- Node popNode() {
- assert(!nodes.isEmpty);
- Node node = nodes.head;
- nodes = nodes.tail;
- if (VERBOSE) log("pop $nodes");
- return node;
- }
-
- void log(message) {
- print(message);
- }
-
- NodeList makeNodeList(int count, Token beginToken, Token endToken,
- String delimiter) {
- Link<Node> poppedNodes = const Link<Node>();
- for (; count > 0; --count) {
- // This effectively reverses the order of nodes so they end up
- // in correct (source) order.
- poppedNodes = poppedNodes.prepend(popNode());
- }
- return new NodeList(beginToken, poppedNodes, endToken, delimiter);
- }
-
- void beginLiteralString(Token token) {
- String source = token.value;
- StringQuoting quoting = StringValidator.quotingFromString(source);
- pushQuoting(quoting);
- // Just wrap the token for now. At the end of the interpolation,
- // when we know how many there are, go back and validate the tokens.
- pushNode(new LiteralString(token, null));
- }
-
- void handleStringPart(Token token) {
- // Just push an unvalidated token now, and replace it when we know the
- // end of the interpolation.
- pushNode(new LiteralString(token, null));
- }
-
- void endLiteralString(int count) {
- StringQuoting quoting = popQuoting();
-
- Link<StringInterpolationPart> parts =
- const Link<StringInterpolationPart>();
- // Parts of the string interpolation are popped in reverse order,
- // starting with the last literal string part.
- bool isLast = true;
- for (int i = 0; i < count; i++) {
- LiteralString string = popNode();
- DartString validation =
- stringValidator.validateInterpolationPart(string.token, quoting,
- isFirst: false,
- isLast: isLast);
- // Replace the unvalidated LiteralString with a new LiteralString
- // object that has the validation result included.
- string = new LiteralString(string.token, validation);
- Expression expression = popNode();
- parts = parts.prepend(new StringInterpolationPart(expression, string));
- isLast = false;
- }
-
- LiteralString string = popNode();
- DartString validation =
- stringValidator.validateInterpolationPart(string.token, quoting,
- isFirst: true,
- isLast: isLast);
- string = new LiteralString(string.token, validation);
- if (isLast) {
- pushNode(string);
- } else {
- NodeList partNodes = new NodeList(null, parts, null, "");
- pushNode(new StringInterpolation(string, partNodes));
- }
- }
-
- void handleStringJuxtaposition(int stringCount) {
- assert(stringCount != 0);
- Expression accumulator = popNode();
- stringCount--;
- while (stringCount > 0) {
- Expression expression = popNode();
- accumulator = new StringJuxtaposition(expression, accumulator);
- stringCount--;
- }
- pushNode(accumulator);
- }
-
- void beginMember(Token token) {
- memberErrors = memberErrors.prepend(false);
- }
-
- void beginTopLevelMember(Token token) {
- beginMember(token);
- }
-
- void endFields(fieldCount, start, token) {
- memberErrors = memberErrors.tail;
- }
-
- void endMethod(getOrSet, start, token) {
- memberErrors = memberErrors.tail;
- }
-
- void beginFactoryMethod(Token token) {
- memberErrors = memberErrors.prepend(false);
- }
-
- void endFactoryMethod(Token beginToken, Token endToken) {
- memberErrors = memberErrors.tail;
- }
-
- /// Don't call this method. Should only be used as a last resort when there
- /// is no feasible way to recover from a parser error.
- void reportFatalError(Spannable spannable, String message) {
- reportError(spannable, MessageKind.GENERIC, {'text': message});
- // Some parse errors are infeasible to recover from, so we throw an error.
- throw new ParserError(message);
- }
-
- void reportError(Spannable spannable,
- MessageKind errorCode,
- [Map arguments = const {}]) {
- if (currentMemberHasParseError) return; // Error already reported.
- if (suppressParseErrors) return;
- if (!memberErrors.isEmpty) {
- memberErrors = memberErrors.tail.prepend(true);
- }
- listener.reportError(spannable, errorCode, arguments);
- }
-}
-
-class NodeListener extends ElementListener {
- NodeListener(
- DiagnosticListener listener,
- CompilationUnitElement element)
- : super(listener, element, null);
-
- void addLibraryTag(LibraryTag tag) {
- pushNode(tag);
- }
-
- void addPartOfTag(PartOf tag) {
- pushNode(tag);
- }
-
- void endClassDeclaration(int interfacesCount, Token beginToken,
- Token extendsKeyword, Token implementsKeyword,
- Token endToken) {
- NodeList body = popNode();
- NodeList interfaces =
- makeNodeList(interfacesCount, implementsKeyword, null, ",");
- Node supertype = popNode();
- NodeList typeParameters = popNode();
- Identifier name = popNode();
- Modifiers modifiers = popNode();
- pushNode(new ClassNode(modifiers, name, typeParameters, supertype,
- interfaces, beginToken, extendsKeyword, body,
- endToken));
- }
-
- void endCompilationUnit(int count, Token token) {
- pushNode(makeNodeList(count, null, null, '\n'));
- }
-
- void endFunctionTypeAlias(Token typedefKeyword, Token endToken) {
- NodeList formals = popNode();
- NodeList typeParameters = popNode();
- Identifier name = popNode();
- TypeAnnotation returnType = popNode();
- pushNode(new Typedef(returnType, name, typeParameters, formals,
- typedefKeyword, endToken));
- }
-
- void endNamedMixinApplication(Token classKeyword,
- Token implementsKeyword,
- Token endToken) {
- NodeList interfaces = (implementsKeyword != null) ? popNode() : null;
- Node mixinApplication = popNode();
- Modifiers modifiers = popNode();
- NodeList typeParameters = popNode();
- Identifier name = popNode();
- pushNode(new NamedMixinApplication(name, typeParameters,
- modifiers, mixinApplication,
- interfaces,
- classKeyword, endToken));
- }
-
- void endEnum(Token enumKeyword, Token endBrace, int count) {
- NodeList names = makeNodeList(count, enumKeyword.next.next, endBrace, ",");
- Identifier name = popNode();
- pushNode(new Enum(enumKeyword, name, names));
- }
-
- void endClassBody(int memberCount, Token beginToken, Token endToken) {
- pushNode(makeNodeList(memberCount, beginToken, endToken, null));
- }
-
- void endTopLevelFields(int count, Token beginToken, Token endToken) {
- NodeList variables = makeNodeList(count, null, endToken, ",");
- TypeAnnotation type = popNode();
- Modifiers modifiers = popNode();
- pushNode(new VariableDefinitions(type, modifiers, variables));
- }
-
- void endTopLevelMethod(Token beginToken, Token getOrSet, Token endToken) {
- popNode(); // body
- popNode(); // formalParameters
- Identifier name = popNode();
- popNode(); // type
- Modifiers modifiers = popNode();
- PartialFunctionElement element = new PartialFunctionElement(
- name.source, beginToken, getOrSet, endToken,
- modifiers, compilationUnitElement);
- pushElement(element);
- }
-
- void endFormalParameter(Token thisKeyword) {
- Expression name = popNode();
- if (thisKeyword != null) {
- Identifier thisIdentifier = new Identifier(thisKeyword);
- if (name.asSend() == null) {
- name = new Send(thisIdentifier, name);
- } else {
- name = name.asSend().copyWithReceiver(thisIdentifier, false);
- }
- }
- TypeAnnotation type = popNode();
- Modifiers modifiers = popNode();
- NodeList metadata = popNode();
- pushNode(new VariableDefinitions.forParameter(
- metadata, type, modifiers, new NodeList.singleton(name)));
- }
-
- void endFormalParameters(int count, Token beginToken, Token endToken) {
- pushNode(makeNodeList(count, beginToken, endToken, ","));
- }
-
- void handleNoFormalParameters(Token token) {
- pushNode(null);
- }
-
- void endArguments(int count, Token beginToken, Token endToken) {
- pushNode(makeNodeList(count, beginToken, endToken, ","));
- }
-
- void handleNoArguments(Token token) {
- pushNode(null);
- }
-
- void endConstructorReference(Token start, Token periodBeforeName,
- Token endToken) {
- Identifier name = null;
- if (periodBeforeName != null) {
- name = popNode();
- }
- NodeList typeArguments = popNode();
- Node classReference = popNode();
- if (typeArguments != null) {
- classReference = new TypeAnnotation(classReference, typeArguments);
- } else {
- Identifier identifier = classReference.asIdentifier();
- Send send = classReference.asSend();
- if (identifier != null) {
- // TODO(ahe): Should be:
- // classReference = new Send(null, identifier);
- classReference = identifier;
- } else if (send != null) {
- classReference = send;
- } else {
- internalError(node: classReference);
- }
- }
- Node constructor = classReference;
- if (name != null) {
- // Either typeName<args>.name or x.y.name.
- constructor = new Send(classReference, name);
- }
- pushNode(constructor);
- }
-
- void endRedirectingFactoryBody(Token beginToken,
- Token endToken) {
- pushNode(new RedirectingFactoryBody(beginToken, endToken, popNode()));
- }
-
- void endReturnStatement(bool hasExpression,
- Token beginToken, Token endToken) {
- Expression expression = hasExpression ? popNode() : null;
- pushNode(new Return(beginToken, endToken, expression));
- }
-
- void endYieldStatement(Token yieldToken, Token starToken, Token endToken) {
- Expression expression = popNode();
- pushNode(new Yield(yieldToken, starToken, expression, endToken));
- }
-
- void endExpressionStatement(Token token) {
- pushNode(new ExpressionStatement(popNode(), token));
- }
-
- void handleOnError(Token token, var errorInformation) {
- listener.internalError(token, "'${token.value}': ${errorInformation}");
- }
-
- Token expectedFunctionBody(Token token) {
- if (identical(token.stringValue, 'native')) {
- return native.handleNativeFunctionBody(this, token);
- } else if (token is ErrorToken) {
- pushNode(null);
- reportErrorToken(token);
- } else {
- reportFatalError(token,
- "Expected a function body, but got '${token.value}'.");
- }
- return skipToEof(token);
- }
-
- Token expectedClassBody(Token token) {
- if (token is ErrorToken) {
- reportErrorToken(token);
- return skipToEof(token);
- } else {
- reportFatalError(token,
- "Expected a class body, but got '${token.value}'.");
- return skipToEof(token);
- }
- }
-
- void handleLiteralInt(Token token) {
- pushNode(new LiteralInt(token, (t, e) => handleOnError(t, e)));
- }
-
- void handleLiteralDouble(Token token) {
- pushNode(new LiteralDouble(token, (t, e) => handleOnError(t, e)));
- }
-
- void handleLiteralBool(Token token) {
- pushNode(new LiteralBool(token, (t, e) => handleOnError(t, e)));
- }
-
- void handleLiteralNull(Token token) {
- pushNode(new LiteralNull(token));
- }
-
- void endLiteralSymbol(Token hashToken, int identifierCount) {
- NodeList identifiers = makeNodeList(identifierCount, null, null, '.');
- pushNode(new LiteralSymbol(hashToken, identifiers));
- }
-
- void handleBinaryExpression(Token token) {
- Node argument = popNode();
- Node receiver = popNode();
- String tokenString = token.stringValue;
- if (identical(tokenString, '.') ||
- identical(tokenString, '..') ||
- identical(tokenString, '?.')) {
- Send argumentSend = argument.asSend();
- if (argumentSend == null) {
- // TODO(ahe): The parser should diagnose this problem, not
- // this listener.
- reportFatalError(argument,
- 'Expected an identifier.');
- }
- if (argumentSend.receiver != null) internalError(node: argument);
- if (argument is SendSet) internalError(node: argument);
- pushNode(argument.asSend().copyWithReceiver(receiver,
- identical(tokenString, '?.')));
- } else {
- NodeList arguments = new NodeList.singleton(argument);
- pushNode(new Send(receiver, new Operator(token), arguments));
- }
- if (identical(tokenString, '===')) {
- listener.reportError(token, MessageKind.UNSUPPORTED_EQ_EQ_EQ,
- {'lhs': receiver, 'rhs': argument});
- }
- if (identical(tokenString, '!==')) {
- listener.reportError(token, MessageKind.UNSUPPORTED_BANG_EQ_EQ,
- {'lhs': receiver, 'rhs': argument});
- }
- }
-
- void beginCascade(Token token) {
- pushNode(new CascadeReceiver(popNode(), token));
- }
-
- void endCascade() {
- pushNode(new Cascade(popNode()));
- }
-
- void handleAsOperator(Token operathor, Token endToken) {
- TypeAnnotation type = popNode();
- Expression expression = popNode();
- NodeList arguments = new NodeList.singleton(type);
- pushNode(new Send(expression, new Operator(operathor), arguments));
- }
-
- void handleAssignmentExpression(Token token) {
- Node arg = popNode();
- Node node = popNode();
- Send send = node.asSend();
- if (send == null || !(send.isPropertyAccess || send.isIndex)) {
- reportNotAssignable(node);
- }
- if (send.asSendSet() != null) internalError(node: send);
- NodeList arguments;
- if (send.isIndex) {
- Link<Node> link = const Link<Node>().prepend(arg);
- link = link.prepend(send.arguments.head);
- arguments = new NodeList(null, link);
- } else {
- arguments = new NodeList.singleton(arg);
- }
- Operator op = new Operator(token);
- pushNode(new SendSet(send.receiver, send.selector, op, arguments,
- send.isConditional));
- }
-
- void reportNotAssignable(Node node) {
- // TODO(ahe): The parser should diagnose this problem, not this
- // listener.
- reportFatalError(node,
- 'Not assignable.');
- }
-
- void handleConditionalExpression(Token question, Token colon) {
- Node elseExpression = popNode();
- Node thenExpression = popNode();
- Node condition = popNode();
- pushNode(new Conditional(
- condition, thenExpression, elseExpression, question, colon));
- }
-
- void endSend(Token token) {
- NodeList arguments = popNode();
- Node selector = popNode();
- // TODO(ahe): Handle receiver.
- pushNode(new Send(null, selector, arguments));
- }
-
- void endFunctionBody(int count, Token beginToken, Token endToken) {
- if (count == 0 && beginToken == null) {
- pushNode(new EmptyStatement(endToken));
- } else {
- pushNode(new Block(makeNodeList(count, beginToken, endToken, null)));
- }
- }
-
- void handleAsyncModifier(Token asyncToken, Token starToken) {
- if (asyncToken != null) {
- pushNode(new AsyncModifier(asyncToken, starToken));
- } else {
- pushNode(null);
- }
- }
-
- void skippedFunctionBody(Token token) {
- pushNode(new Block(new NodeList.empty()));
- }
-
- void handleNoFunctionBody(Token token) {
- pushNode(new EmptyStatement(token));
- }
-
- void endFunction(Token getOrSet, Token endToken) {
- Statement body = popNode();
- AsyncModifier asyncModifier = popNode();
- NodeList initializers = popNode();
- NodeList formals = popNode();
- // The name can be an identifier or a send in case of named constructors.
- Expression name = popNode();
- TypeAnnotation type = popNode();
- Modifiers modifiers = popNode();
- pushNode(new FunctionExpression(name, formals, body, type,
- modifiers, initializers, getOrSet,
- asyncModifier));
- }
-
- void endFunctionDeclaration(Token endToken) {
- pushNode(new FunctionDeclaration(popNode()));
- }
-
- void endVariablesDeclaration(int count, Token endToken) {
- // TODO(ahe): Pick one name for this concept, either
- // VariablesDeclaration or VariableDefinitions.
- NodeList variables = makeNodeList(count, null, endToken, ",");
- TypeAnnotation type = popNode();
- Modifiers modifiers = popNode();
- pushNode(new VariableDefinitions(type, modifiers, variables));
- }
-
- void endInitializer(Token assignmentOperator) {
- Expression initializer = popNode();
- NodeList arguments =
- initializer == null ? null : new NodeList.singleton(initializer);
- Expression name = popNode();
- Operator op = new Operator(assignmentOperator);
- pushNode(new SendSet(null, name, op, arguments));
- }
-
- void endIfStatement(Token ifToken, Token elseToken) {
- Statement elsePart = (elseToken == null) ? null : popNode();
- Statement thenPart = popNode();
- ParenthesizedExpression condition = popNode();
- pushNode(new If(condition, thenPart, elsePart, ifToken, elseToken));
- }
-
- void endForStatement(int updateExpressionCount,
- Token beginToken, Token endToken) {
- Statement body = popNode();
- NodeList updates = makeNodeList(updateExpressionCount, null, null, ',');
- Statement condition = popNode();
- Node initializer = popNode();
- pushNode(new For(initializer, condition, updates, body, beginToken));
- }
-
- void handleNoExpression(Token token) {
- pushNode(null);
- }
-
- void endDoWhileStatement(Token doKeyword, Token whileKeyword,
- Token endToken) {
- Expression condition = popNode();
- Statement body = popNode();
- pushNode(new DoWhile(body, condition, doKeyword, whileKeyword, endToken));
- }
-
- void endWhileStatement(Token whileKeyword, Token endToken) {
- Statement body = popNode();
- Expression condition = popNode();
- pushNode(new While(condition, body, whileKeyword));
- }
-
- void endBlock(int count, Token beginToken, Token endToken) {
- pushNode(new Block(makeNodeList(count, beginToken, endToken, null)));
- }
-
- void endThrowExpression(Token throwToken, Token endToken) {
- Expression expression = popNode();
- pushNode(new Throw(expression, throwToken, endToken));
- }
-
- void endAwaitExpression(Token awaitToken, Token endToken) {
- Expression expression = popNode();
- pushNode(new Await(awaitToken, expression));
- }
-
- void endRethrowStatement(Token throwToken, Token endToken) {
- pushNode(new Rethrow(throwToken, endToken));
- if (identical(throwToken.stringValue, 'throw')) {
- listener.reportError(throwToken,
- MessageKind.UNSUPPORTED_THROW_WITHOUT_EXP);
- }
- }
-
- void handleUnaryPrefixExpression(Token token) {
- pushNode(new Send.prefix(popNode(), new Operator(token)));
- }
-
- void handleSuperExpression(Token token) {
- pushNode(new Identifier(token));
- }
-
- void handleThisExpression(Token token) {
- pushNode(new Identifier(token));
- }
-
- void handleUnaryAssignmentExpression(Token token, bool isPrefix) {
- Node node = popNode();
- Send send = node.asSend();
- if (send == null) {
- reportNotAssignable(node);
- }
- if (!(send.isPropertyAccess || send.isIndex)) {
- reportNotAssignable(node);
- }
- if (send.asSendSet() != null) internalError(node: send);
- Node argument = null;
- if (send.isIndex) argument = send.arguments.head;
- Operator op = new Operator(token);
-
- if (isPrefix) {
- pushNode(new SendSet.prefix(send.receiver, send.selector, op, argument,
- send.isConditional));
- } else {
- pushNode(new SendSet.postfix(send.receiver, send.selector, op, argument,
- send.isConditional));
- }
- }
-
- void handleUnaryPostfixAssignmentExpression(Token token) {
- handleUnaryAssignmentExpression(token, false);
- }
-
- void handleUnaryPrefixAssignmentExpression(Token token) {
- handleUnaryAssignmentExpression(token, true);
- }
-
- void endInitializers(int count, Token beginToken, Token endToken) {
- pushNode(makeNodeList(count, beginToken, null, ','));
- }
-
- void handleNoInitializers() {
- pushNode(null);
- }
-
- void endFields(int count, Token beginToken, Token endToken) {
- NodeList variables = makeNodeList(count, null, endToken, ",");
- TypeAnnotation type = popNode();
- Modifiers modifiers = popNode();
- pushNode(new VariableDefinitions(type, modifiers, variables));
- }
-
- void endMethod(Token getOrSet, Token beginToken, Token endToken) {
- Statement body = popNode();
- AsyncModifier asyncModifier = popNode();
- NodeList initializers = popNode();
- NodeList formalParameters = popNode();
- Expression name = popNode();
- TypeAnnotation returnType = popNode();
- Modifiers modifiers = popNode();
- pushNode(new FunctionExpression(name, formalParameters, body, returnType,
- modifiers, initializers, getOrSet,
- asyncModifier));
- }
-
- void handleLiteralMap(int count, Token beginToken, Token constKeyword,
- Token endToken) {
- NodeList entries = makeNodeList(count, beginToken, endToken, ',');
- NodeList typeArguments = popNode();
- pushNode(new LiteralMap(typeArguments, entries, constKeyword));
- }
-
- void endLiteralMapEntry(Token colon, Token endToken) {
- Expression value = popNode();
- Expression key = popNode();
- pushNode(new LiteralMapEntry(key, colon, value));
- }
-
- void handleLiteralList(int count, Token beginToken, Token constKeyword,
- Token endToken) {
- NodeList elements = makeNodeList(count, beginToken, endToken, ',');
- pushNode(new LiteralList(popNode(), elements, constKeyword));
- }
-
- void handleIndexedExpression(Token openSquareBracket,
- Token closeSquareBracket) {
- NodeList arguments =
- makeNodeList(1, openSquareBracket, closeSquareBracket, null);
- Node receiver = popNode();
- Token token = new StringToken.fromString(INDEX_INFO, '[]',
- openSquareBracket.charOffset);
- Node selector = new Operator(token);
- pushNode(new Send(receiver, selector, arguments));
- }
-
- void handleNewExpression(Token token) {
- NodeList arguments = popNode();
- Node name = popNode();
- pushNode(new NewExpression(token, new Send(null, name, arguments)));
- }
-
- void handleConstExpression(Token token) {
- // [token] carries the 'const' information.
- handleNewExpression(token);
- }
-
- void handleOperator(Token token) {
- pushNode(new Operator(token));
- }
-
- void handleOperatorName(Token operatorKeyword, Token token) {
- Operator op = new Operator(token);
- pushNode(new Send(new Identifier(operatorKeyword), op, null));
- }
-
- void handleNamedArgument(Token colon) {
- Expression expression = popNode();
- Identifier name = popNode();
- pushNode(new NamedArgument(name, colon, expression));
- }
-
- void endOptionalFormalParameters(int count,
- Token beginToken, Token endToken) {
- pushNode(makeNodeList(count, beginToken, endToken, ','));
- }
-
- void handleFunctionTypedFormalParameter(Token endToken) {
- NodeList formals = popNode();
- Identifier name = popNode();
- TypeAnnotation returnType = popNode();
- pushNode(null); // Signal "no type" to endFormalParameter.
- pushNode(new FunctionExpression(name, formals, null, returnType,
- Modifiers.EMPTY, null, null, null));
- }
-
- void handleValuedFormalParameter(Token equals, Token token) {
- Expression defaultValue = popNode();
- Expression parameterName = popNode();
- pushNode(new SendSet(null, parameterName, new Operator(equals),
- new NodeList.singleton(defaultValue)));
- }
-
- void endTryStatement(int catchCount, Token tryKeyword, Token finallyKeyword) {
- Block finallyBlock = null;
- if (finallyKeyword != null) {
- finallyBlock = popNode();
- }
- NodeList catchBlocks = makeNodeList(catchCount, null, null, null);
- Block tryBlock = popNode();
- pushNode(new TryStatement(tryBlock, catchBlocks, finallyBlock,
- tryKeyword, finallyKeyword));
- }
-
- void handleCaseMatch(Token caseKeyword, Token colon) {
- pushNode(new CaseMatch(caseKeyword, popNode(), colon));
- }
-
- void handleCatchBlock(Token onKeyword, Token catchKeyword) {
- Block block = popNode();
- NodeList formals = catchKeyword != null? popNode(): null;
- TypeAnnotation type = onKeyword != null ? popNode() : null;
- pushNode(new CatchBlock(type, formals, block, onKeyword, catchKeyword));
- }
-
- void endSwitchStatement(Token switchKeyword, Token endToken) {
- NodeList cases = popNode();
- ParenthesizedExpression expression = popNode();
- pushNode(new SwitchStatement(expression, cases, switchKeyword));
- }
-
- void endSwitchBlock(int caseCount, Token beginToken, Token endToken) {
- Link<Node> caseNodes = const Link<Node>();
- while (caseCount > 0) {
- SwitchCase switchCase = popNode();
- caseNodes = caseNodes.prepend(switchCase);
- caseCount--;
- }
- pushNode(new NodeList(beginToken, caseNodes, endToken, null));
- }
-
- void handleSwitchCase(int labelCount, int caseCount,
- Token defaultKeyword, int statementCount,
- Token firstToken, Token endToken) {
- NodeList statements = makeNodeList(statementCount, null, null, null);
- NodeList labelsAndCases =
- makeNodeList(labelCount + caseCount, null, null, null);
- pushNode(new SwitchCase(labelsAndCases, defaultKeyword, statements,
- firstToken));
- }
-
- void handleBreakStatement(bool hasTarget,
- Token breakKeyword, Token endToken) {
- Identifier target = null;
- if (hasTarget) {
- target = popNode();
- }
- pushNode(new BreakStatement(target, breakKeyword, endToken));
- }
-
- void handleContinueStatement(bool hasTarget,
- Token continueKeyword, Token endToken) {
- Identifier target = null;
- if (hasTarget) {
- target = popNode();
- }
- pushNode(new ContinueStatement(target, continueKeyword, endToken));
- }
-
- void handleEmptyStatement(Token token) {
- pushNode(new EmptyStatement(token));
- }
-
- void endFactoryMethod(Token beginToken, Token endToken) {
- super.endFactoryMethod(beginToken, endToken);
- Statement body = popNode();
- AsyncModifier asyncModifier = popNode();
- NodeList formals = popNode();
- Node name = popNode();
-
- // TODO(ahe): Move this parsing to the parser.
- int modifierCount = 0;
- Token modifier = beginToken;
- if (modifier.stringValue == "external") {
- handleModifier(modifier);
- modifierCount++;
- modifier = modifier.next;
- }
- if (modifier.stringValue == "const") {
- handleModifier(modifier);
- modifierCount++;
- modifier = modifier.next;
- }
- assert(modifier.stringValue == "factory");
- handleModifier(modifier);
- modifierCount++;
- handleModifiers(modifierCount);
- Modifiers modifiers = popNode();
-
- pushNode(new FunctionExpression(name, formals, body, null,
- modifiers, null, null, asyncModifier));
- }
-
- void endForIn(Token awaitToken, Token forToken,
- Token inKeyword, Token endToken) {
- Statement body = popNode();
- Expression expression = popNode();
- Node declaredIdentifier = popNode();
- if (awaitToken == null) {
- pushNode(new SyncForIn(declaredIdentifier, expression, body,
- forToken, inKeyword));
- } else {
- pushNode(new AsyncForIn(declaredIdentifier, expression, body, awaitToken,
- forToken, inKeyword));
- }
- }
-
- void endMetadataStar(int count, bool forParameter) {
- // TODO(johnniwinther): Handle metadata for all node kinds.
- if (forParameter) {
- if (0 == count) {
- pushNode(null);
- } else {
- pushNode(makeNodeList(count, null, null, ' '));
- }
- }
- }
-
- void endMetadata(Token beginToken, Token periodBeforeName, Token endToken) {
- NodeList arguments = popNode();
- if (arguments == null) {
- // This is a constant expression.
- Identifier name;
- if (periodBeforeName != null) {
- name = popNode();
- }
- NodeList typeArguments = popNode();
- Node receiver = popNode();
- if (typeArguments != null) {
- receiver = new TypeAnnotation(receiver, typeArguments);
- recoverableError(typeArguments,
- 'Type arguments are not allowed here.');
- } else {
- Identifier identifier = receiver.asIdentifier();
- Send send = receiver.asSend();
- if (identifier != null) {
- receiver = new Send(null, identifier);
- } else if (send == null) {
- internalError(node: receiver);
- }
- }
- Send send = receiver;
- if (name != null) {
- send = new Send(receiver, name);
- }
- pushNode(new Metadata(beginToken, send));
- } else {
- // This is a const constructor call.
- endConstructorReference(beginToken, periodBeforeName, endToken);
- Node constructor = popNode();
- pushNode(new Metadata(beginToken,
- new NewExpression(null,
- new Send(null, constructor, arguments))));
- }
- }
-
- void handleAssertStatement(Token assertKeyword, Token semicolonToken) {
- NodeList arguments = popNode();
- Node selector = new Identifier(assertKeyword);
- Node send = new Send(null, selector, arguments);
- pushNode(new ExpressionStatement(send, semicolonToken));
- }
-
- void endUnnamedFunction(Token token) {
- Statement body = popNode();
- AsyncModifier asyncModifier = popNode();
- NodeList formals = popNode();
- pushNode(new FunctionExpression(null, formals, body, null,
- Modifiers.EMPTY, null, null,
- asyncModifier));
- }
-
- void handleIsOperator(Token operathor, Token not, Token endToken) {
- TypeAnnotation type = popNode();
- Expression expression = popNode();
- Node argument;
- if (not != null) {
- argument = new Send.prefix(type, new Operator(not));
- } else {
- argument = type;
- }
-
- NodeList arguments = new NodeList.singleton(argument);
- pushNode(new Send(expression, new Operator(operathor), arguments));
- }
-
- void handleLabel(Token colon) {
- Identifier name = popNode();
- pushNode(new Label(name, colon));
- }
-
- void endLabeledStatement(int labelCount) {
- Statement statement = popNode();
- NodeList labels = makeNodeList(labelCount, null, null, null);
- pushNode(new LabeledStatement(labels, statement));
- }
-
- void log(message) {
- listener.log(message);
- }
-
- void internalError({Token token, Node node}) {
- // TODO(ahe): This should call listener.internalError.
- Spannable spannable = (token == null) ? node : token;
- throw new SpannableAssertionFailure(spannable, 'Internal error in parser.');
- }
-}
-
-abstract class PartialElement implements DeclarationSite {
- Token beginToken;
- Token endToken;
-
- bool hasParseError = false;
-
- bool get isErroneous => hasParseError;
-
- DeclarationSite get declarationSite => this;
-}
-
-abstract class PartialFunctionMixin implements BaseFunctionElementX {
- FunctionExpression cachedNode;
- Modifiers get modifiers;
- Token beginToken;
- Token getOrSet;
- Token endToken;
-
- /**
- * The position is computed in the constructor using [findMyName]. Computing
- * it on demand fails in case tokens are GC'd.
- */
- Token _position;
-
- void init(Token beginToken, Token getOrSet, Token endToken) {
- this.beginToken = beginToken;
- this.getOrSet = getOrSet;
- this.endToken = endToken;
- _position = ElementX.findNameToken(
- beginToken,
- modifiers.isFactory ||
- identical(kind, ElementKind.GENERATIVE_CONSTRUCTOR),
- name, enclosingElement.name);
- }
-
- bool get hasNode => cachedNode != null;
-
- FunctionExpression get node {
- assert(invariant(this, cachedNode != null,
- message: "Node has not been computed for $this."));
- return cachedNode;
- }
-
- FunctionExpression parseNode(DiagnosticListener listener) {
- if (cachedNode != null) return cachedNode;
- parseFunction(Parser p) {
- if (isClassMember && modifiers.isFactory) {
- p.parseFactoryMethod(beginToken);
- } else {
- p.parseFunction(beginToken, getOrSet);
- }
- }
- cachedNode = parse(listener, this, declarationSite, parseFunction);
- return cachedNode;
- }
-
- Token get position => _position;
-
- void reusePartialFunctionMixin() {
- cachedNode = null;
- }
-
- DeclarationSite get declarationSite;
-}
-
-abstract class PartialFunctionElement
- implements PartialElement, PartialFunctionMixin {
-
- factory PartialFunctionElement(
- String name,
- Token beginToken,
- Token getOrSet,
- Token endToken,
- Modifiers modifiers,
- Element enclosingElement,
- {bool hasBody: true}) {
- if (getOrSet == null) {
- return new PartialMethodElement(
- name, beginToken, endToken, modifiers,
- enclosingElement, hasBody: hasBody);
- } else if (identical(getOrSet.stringValue, 'get')) {
- return new PartialGetterElement(
- name, beginToken, getOrSet, endToken, modifiers,
- enclosingElement, hasBody: hasBody);
- } else {
- assert(identical(getOrSet.stringValue, 'set'));
- return new PartialSetterElement(
- name, beginToken, getOrSet, endToken, modifiers,
- enclosingElement, hasBody: hasBody);
- }
- }
-
- PartialFunctionElement copyWithEnclosing(Element enclosing);
-}
-
-
-class PartialMethodElement extends MethodElementX
- with PartialElement, PartialFunctionMixin
- implements PartialFunctionElement {
- PartialMethodElement(String name,
- Token beginToken,
- Token endToken,
- Modifiers modifiers,
- Element enclosing,
- {bool hasBody: true})
- : super(name, ElementKind.FUNCTION, modifiers, enclosing, hasBody) {
- init(beginToken, null, endToken);
- }
-
- void reuseElement() {
- super.reuseElement();
- reusePartialFunctionMixin();
- }
-
- PartialMethodElement copyWithEnclosing(Element enclosing) {
- return new PartialMethodElement(
- name, beginToken, endToken, modifiers, enclosing, hasBody: hasBody);
- }
-}
-
-class PartialGetterElement extends GetterElementX
- with PartialElement, PartialFunctionMixin
- implements GetterElement, PartialFunctionElement {
- PartialGetterElement(String name,
- Token beginToken,
- Token getToken,
- Token endToken,
- Modifiers modifiers,
- Element enclosing,
- {bool hasBody: true})
- : super(name, modifiers, enclosing, hasBody) {
- init(beginToken, getToken, endToken);
- }
-
- @override
- SetterElement get setter => abstractField.setter;
-
- void reuseElement() {
- super.reuseElement();
- reusePartialFunctionMixin();
- }
-
- PartialGetterElement copyWithEnclosing(Element enclosing) {
- return new PartialGetterElement(
- name, beginToken, getOrSet, endToken, modifiers, enclosing,
- hasBody: hasBody);
- }
-}
-
-class PartialSetterElement extends SetterElementX
- with PartialElement, PartialFunctionMixin
- implements SetterElement, PartialFunctionElement {
- PartialSetterElement(String name,
- Token beginToken,
- Token setToken,
- Token endToken,
- Modifiers modifiers,
- Element enclosing,
- {bool hasBody: true})
- : super(name, modifiers, enclosing, hasBody) {
- init(beginToken, setToken, endToken);
- }
-
- @override
- GetterElement get getter => abstractField.getter;
-
- void reuseElement() {
- super.reuseElement();
- reusePartialFunctionMixin();
- }
-
- PartialSetterElement copyWithEnclosing(Element enclosing) {
- return new PartialSetterElement(
- name, beginToken, getOrSet, endToken, modifiers, enclosing,
- hasBody: hasBody);
- }
-}
-
-class PartialConstructorElement extends ConstructorElementX
- with PartialElement, PartialFunctionMixin {
- PartialConstructorElement(String name,
- Token beginToken,
- Token endToken,
- ElementKind kind,
- Modifiers modifiers,
- Element enclosing)
- : super(name, kind, modifiers, enclosing) {
- init(beginToken, null, endToken);
- }
-
- void reuseElement() {
- super.reuseElement();
- reusePartialFunctionMixin();
- }
-}
-
-class PartialFieldList extends VariableList with PartialElement {
- PartialFieldList(Token beginToken,
- Token endToken,
- Modifiers modifiers,
- bool hasParseError)
- : super(modifiers) {
- super.beginToken = beginToken;
- super.endToken = endToken;
- super.hasParseError = hasParseError;
- }
-
- VariableDefinitions parseNode(Element element, DiagnosticListener listener) {
- if (definitions != null) return definitions;
- listener.withCurrentElement(element, () {
- definitions = parse(
- listener, element, declarationSite,
- (Parser parser) => parser.parseMember(beginToken));
-
- if (!hasParseError &&
- !definitions.modifiers.isVar &&
- !definitions.modifiers.isFinal &&
- !definitions.modifiers.isConst &&
- definitions.type == null &&
- !definitions.isErroneous) {
- listener.reportError(
- definitions,
- MessageKind.GENERIC,
- { 'text': 'A field declaration must start with var, final, '
- 'const, or a type annotation.' });
- }
- });
- return definitions;
- }
-
- computeType(Element element, Compiler compiler) {
- if (type != null) return type;
- // TODO(johnniwinther): Compute this in the resolver.
- compiler.withCurrentElement(element, () {
- VariableDefinitions node = parseNode(element, compiler);
- if (node.type != null) {
- type = compiler.resolver.resolveTypeAnnotation(element, node.type);
- } else {
- type = const DynamicType();
- }
- });
- assert(type != null);
- return type;
- }
-}
-
-class PartialTypedefElement extends TypedefElementX with PartialElement {
-
- PartialTypedefElement(
- String name,
- Element enclosing,
- Token beginToken,
- Token endToken)
- : super(name, enclosing) {
- this.beginToken = beginToken;
- this.endToken = endToken;
- }
-
- Token get token => beginToken;
-
- Node parseNode(DiagnosticListener listener) {
- if (cachedNode != null) return cachedNode;
- cachedNode = parse(
- listener, this, declarationSite,
- (p) => p.parseTopLevelDeclaration(token));
- return cachedNode;
- }
-
- Token get position => findMyName(token);
-}
-
-/// A [MetadataAnnotation] which is constructed on demand.
-class PartialMetadataAnnotation extends MetadataAnnotationX
- implements PartialElement {
- Token beginToken; // TODO(ahe): Make this final when issue 22065 is fixed.
-
- final Token tokenAfterEndToken;
-
- Expression cachedNode;
-
- bool hasParseError = false;
-
- PartialMetadataAnnotation(this.beginToken, this.tokenAfterEndToken);
-
- bool get isErroneous => hasParseError;
-
- DeclarationSite get declarationSite => this;
-
- Token get endToken {
- Token token = beginToken;
- while (token.kind != EOF_TOKEN) {
- if (identical(token.next, tokenAfterEndToken)) break;
- token = token.next;
- }
- assert(token != null);
- return token;
- }
-
- void set endToken(_) {
- throw new UnsupportedError("endToken=");
- }
-
- Node parseNode(DiagnosticListener listener) {
- if (cachedNode != null) return cachedNode;
- var metadata = parse(listener,
- annotatedElement,
- declarationSite,
- (p) => p.parseMetadata(beginToken));
- if (metadata is Metadata) {
- cachedNode = metadata.expression;
- return cachedNode;
- } else {
- assert (metadata is ErrorNode);
- return metadata;
- }
- }
-
- bool get hasNode => cachedNode != null;
-
- Node get node {
- assert(invariant(this, hasNode));
- return cachedNode;
- }
-}
-
-Node parse(
- DiagnosticListener diagnosticListener,
- ElementX element,
- PartialElement partial,
- doParse(Parser parser)) {
- CompilationUnitElement unit = element.compilationUnit;
- NodeListener listener = new NodeListener(diagnosticListener, unit);
- listener.memberErrors = listener.memberErrors.prepend(false);
- try {
- if (partial.hasParseError) {
- listener.suppressParseErrors = true;
- }
- doParse(new Parser(listener));
- } on ParserError catch (e) {
- partial.hasParseError = true;
- return new ErrorNode(element.position, e.reason);
- }
- Node node = listener.popNode();
- assert(listener.nodes.isEmpty);
- return node;
-}
diff --git a/pkg/compiler/lib/src/scanner/scanner.dart b/pkg/compiler/lib/src/scanner/scanner.dart
index d9ab312..1a52a64 100644
--- a/pkg/compiler/lib/src/scanner/scanner.dart
+++ b/pkg/compiler/lib/src/scanner/scanner.dart
@@ -2,7 +2,25 @@
// 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.
-part of scanner;
+library dart2js.scanner;
+
+import '../io/source_file.dart' show
+ SourceFile,
+ Utf8BytesSourceFile;
+import '../tokens/keyword.dart' show
+ Keyword,
+ KeywordState;
+import '../tokens/precedence.dart';
+import '../tokens/precedence_constants.dart';
+import '../tokens/token.dart';
+import '../tokens/token_constants.dart';
+import '../util/characters.dart';
+
+import 'string_scanner.dart' show
+ StringScanner;
+import 'utf8_bytes_scanner.dart' show
+ Utf8BytesScanner;
+
abstract class Scanner {
Token tokenize();
diff --git a/pkg/compiler/lib/src/scanner/scanner_task.dart b/pkg/compiler/lib/src/scanner/scanner_task.dart
index 636ee34..cc13bb5 100644
--- a/pkg/compiler/lib/src/scanner/scanner_task.dart
+++ b/pkg/compiler/lib/src/scanner/scanner_task.dart
@@ -2,7 +2,24 @@
// 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.
-part of scanner;
+library dart2js.scanner.task;
+
+import '../common/tasks.dart' show
+ CompilerTask;
+import '../compiler.dart' show
+ Compiler;
+import '../elements/elements.dart' show
+ CompilationUnitElement,
+ LibraryElement;
+import '../script.dart' show
+ Script;
+import '../tokens/token.dart' show
+ Token;
+
+import 'scanner.dart' show
+ Scanner;
+import 'string_scanner.dart' show
+ StringScanner;
class ScannerTask extends CompilerTask {
ScannerTask(Compiler compiler) : super(compiler);
@@ -50,22 +67,3 @@
});
}
}
-
-class DietParserTask extends CompilerTask {
- DietParserTask(Compiler compiler) : super(compiler);
- final String name = 'Diet Parser';
-
- dietParse(CompilationUnitElement compilationUnit, Token tokens) {
- measure(() {
- Function idGenerator = compiler.getNextFreeClassId;
- ElementListener listener =
- new ElementListener(compiler, compilationUnit, idGenerator);
- PartialParser parser = new PartialParser(listener);
- try {
- parser.parseUnit(tokens);
- } on ParserError catch(_) {
- assert(invariant(compilationUnit, compiler.compilationFailed));
- }
- });
- }
-}
diff --git a/pkg/compiler/lib/src/scanner/scannerlib.dart b/pkg/compiler/lib/src/scanner/scannerlib.dart
deleted file mode 100644
index e4058c8..0000000
--- a/pkg/compiler/lib/src/scanner/scannerlib.dart
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library scanner;
-
-import 'dart:collection' show IterableBase, HashSet;
-
-import '../common/tasks.dart' show
- CompilerTask;
-import '../compiler.dart' show
- Compiler;
-import '../dart_types.dart' show DynamicType;
-import '../diagnostics/diagnostic_listener.dart';
-import '../diagnostics/invariant.dart' show
- invariant;
-import '../diagnostics/messages.dart';
-import '../diagnostics/spannable.dart' show
- Spannable,
- SpannableAssertionFailure;
-import '../elements/elements.dart';
-
-import '../elements/modelx.dart' show
- BaseFunctionElementX,
- ClassElementX,
- CompilationUnitElementX,
- ConstructorElementX,
- DeclarationSite,
- ElementX,
- EnumClassElementX,
- FieldElementX,
- GetterElementX,
- MethodElementX,
- LibraryElementX,
- MetadataAnnotationX,
- MixinApplicationElementX,
- SetterElementX,
- TypedefElementX,
- VariableElementX,
- VariableList;
-
-import '../elements/visitor.dart'
- show ElementVisitor;
-import '../native/native.dart' as native;
-import '../string_validator.dart';
-import '../script.dart';
-import '../tree/tree.dart';
-import '../util/characters.dart';
-import '../util/util.dart';
-import '../io/source_file.dart' show SourceFile, Utf8BytesSourceFile;
-import 'dart:convert' show UTF8, UNICODE_BOM_CHARACTER_RUNE;
-
-part 'class_element_parser.dart';
-part 'keyword.dart';
-part 'listener.dart';
-part 'parser.dart';
-part 'parser_task.dart';
-part 'partial_parser.dart';
-part 'scanner.dart';
-part 'scanner_task.dart';
-part 'array_based_scanner.dart';
-part 'utf8_bytes_scanner.dart';
-part 'string_scanner.dart';
-part 'token.dart';
diff --git a/pkg/compiler/lib/src/scanner/string_scanner.dart b/pkg/compiler/lib/src/scanner/string_scanner.dart
index 5a30e43..aec14a0 100644
--- a/pkg/compiler/lib/src/scanner/string_scanner.dart
+++ b/pkg/compiler/lib/src/scanner/string_scanner.dart
@@ -2,7 +2,20 @@
// 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.
-part of scanner;
+library dart2js.scanner.string;
+
+import '../io/source_file.dart' show
+ SourceFile;
+import '../tokens/precedence.dart' show
+ PrecedenceInfo;
+import '../tokens/token.dart' show
+ PrecedenceInfo,
+ StringToken,
+ Token;
+
+import 'array_based_scanner.dart' show
+ ArrayBasedScanner;
+
/**
* Scanner that reads from a String and creates tokens that points to
diff --git a/pkg/compiler/lib/src/scanner/token.dart b/pkg/compiler/lib/src/scanner/token.dart
deleted file mode 100644
index 2dff11e..0000000
--- a/pkg/compiler/lib/src/scanner/token.dart
+++ /dev/null
@@ -1,741 +0,0 @@
-// Copyright (c) 2011, 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.
-
-part of scanner;
-
-const int EOF_TOKEN = 0;
-
-const int KEYWORD_TOKEN = $k;
-const int IDENTIFIER_TOKEN = $a;
-const int BAD_INPUT_TOKEN = $X;
-const int DOUBLE_TOKEN = $d;
-const int INT_TOKEN = $i;
-const int HEXADECIMAL_TOKEN = $x;
-const int STRING_TOKEN = $SQ;
-
-const int AMPERSAND_TOKEN = $AMPERSAND;
-const int BACKPING_TOKEN = $BACKPING;
-const int BACKSLASH_TOKEN = $BACKSLASH;
-const int BANG_TOKEN = $BANG;
-const int BAR_TOKEN = $BAR;
-const int COLON_TOKEN = $COLON;
-const int COMMA_TOKEN = $COMMA;
-const int EQ_TOKEN = $EQ;
-const int GT_TOKEN = $GT;
-const int HASH_TOKEN = $HASH;
-const int OPEN_CURLY_BRACKET_TOKEN = $OPEN_CURLY_BRACKET;
-const int OPEN_SQUARE_BRACKET_TOKEN = $OPEN_SQUARE_BRACKET;
-const int OPEN_PAREN_TOKEN = $OPEN_PAREN;
-const int LT_TOKEN = $LT;
-const int MINUS_TOKEN = $MINUS;
-const int PERIOD_TOKEN = $PERIOD;
-const int PLUS_TOKEN = $PLUS;
-const int QUESTION_TOKEN = $QUESTION;
-const int AT_TOKEN = $AT;
-const int CLOSE_CURLY_BRACKET_TOKEN = $CLOSE_CURLY_BRACKET;
-const int CLOSE_SQUARE_BRACKET_TOKEN = $CLOSE_SQUARE_BRACKET;
-const int CLOSE_PAREN_TOKEN = $CLOSE_PAREN;
-const int SEMICOLON_TOKEN = $SEMICOLON;
-const int SLASH_TOKEN = $SLASH;
-const int TILDE_TOKEN = $TILDE;
-const int STAR_TOKEN = $STAR;
-const int PERCENT_TOKEN = $PERCENT;
-const int CARET_TOKEN = $CARET;
-
-const int STRING_INTERPOLATION_TOKEN = 128;
-const int LT_EQ_TOKEN = STRING_INTERPOLATION_TOKEN + 1;
-const int FUNCTION_TOKEN = LT_EQ_TOKEN + 1;
-const int SLASH_EQ_TOKEN = FUNCTION_TOKEN + 1;
-const int PERIOD_PERIOD_PERIOD_TOKEN = SLASH_EQ_TOKEN + 1;
-const int PERIOD_PERIOD_TOKEN = PERIOD_PERIOD_PERIOD_TOKEN + 1;
-const int EQ_EQ_EQ_TOKEN = PERIOD_PERIOD_TOKEN + 1;
-const int EQ_EQ_TOKEN = EQ_EQ_EQ_TOKEN + 1;
-const int LT_LT_EQ_TOKEN = EQ_EQ_TOKEN + 1;
-const int LT_LT_TOKEN = LT_LT_EQ_TOKEN + 1;
-const int GT_EQ_TOKEN = LT_LT_TOKEN + 1;
-const int GT_GT_EQ_TOKEN = GT_EQ_TOKEN + 1;
-const int INDEX_EQ_TOKEN = GT_GT_EQ_TOKEN + 1;
-const int INDEX_TOKEN = INDEX_EQ_TOKEN + 1;
-const int BANG_EQ_EQ_TOKEN = INDEX_TOKEN + 1;
-const int BANG_EQ_TOKEN = BANG_EQ_EQ_TOKEN + 1;
-const int AMPERSAND_AMPERSAND_TOKEN = BANG_EQ_TOKEN + 1;
-const int AMPERSAND_EQ_TOKEN = AMPERSAND_AMPERSAND_TOKEN + 1;
-const int BAR_BAR_TOKEN = AMPERSAND_EQ_TOKEN + 1;
-const int BAR_EQ_TOKEN = BAR_BAR_TOKEN + 1;
-const int STAR_EQ_TOKEN = BAR_EQ_TOKEN + 1;
-const int PLUS_PLUS_TOKEN = STAR_EQ_TOKEN + 1;
-const int PLUS_EQ_TOKEN = PLUS_PLUS_TOKEN + 1;
-const int MINUS_MINUS_TOKEN = PLUS_EQ_TOKEN + 1;
-const int MINUS_EQ_TOKEN = MINUS_MINUS_TOKEN + 1;
-const int TILDE_SLASH_EQ_TOKEN = MINUS_EQ_TOKEN + 1;
-const int TILDE_SLASH_TOKEN = TILDE_SLASH_EQ_TOKEN + 1;
-const int PERCENT_EQ_TOKEN = TILDE_SLASH_TOKEN + 1;
-const int GT_GT_TOKEN = PERCENT_EQ_TOKEN + 1;
-const int CARET_EQ_TOKEN = GT_GT_TOKEN + 1;
-const int COMMENT_TOKEN = CARET_EQ_TOKEN + 1;
-const int STRING_INTERPOLATION_IDENTIFIER_TOKEN = COMMENT_TOKEN + 1;
-const int QUESTION_PERIOD_TOKEN = STRING_INTERPOLATION_IDENTIFIER_TOKEN + 1;
-const int QUESTION_QUESTION_TOKEN = QUESTION_PERIOD_TOKEN + 1;
-const int QUESTION_QUESTION_EQ_TOKEN = QUESTION_QUESTION_TOKEN + 1;
-
-/**
- * A token that doubles as a linked list.
- */
-abstract class Token implements Spannable {
- /**
- * The character offset of the start of this token within the source text.
- */
- final int charOffset;
-
- Token(this.charOffset);
-
- /**
- * The next token in the token stream.
- */
- Token next;
-
- /**
- * The precedence info for this token. [info] determines the kind and the
- * precedence level of this token.
- *
- * Defined as getter to save a field in the [KeywordToken] subclass.
- */
- PrecedenceInfo get info;
-
- /**
- * The string represented by this token, a substring of the source code.
- *
- * For [StringToken]s the [value] includes the quotes, explicit escapes, etc.
- */
- String get value;
-
- /**
- * For symbol and keyword tokens, returns the string value represented by this
- * token. For [StringToken]s this method returns [:null:].
- *
- * For [SymbolToken]s and [KeywordToken]s, the string value is a compile-time
- * constant originating in the [PrecedenceInfo] or in the [Keyword] instance.
- * This allows testing for keywords and symbols using [:identical:], e.g.,
- * [:identical('class', token.value):].
- *
- * Note that returning [:null:] for string tokens is important to identify
- * symbols and keywords, we cannot use [value] instead. The string literal
- * "$a($b"
- * produces ..., SymbolToken($), StringToken(a), StringToken((), ...
- *
- * After parsing the identifier 'a', the parser tests for a function
- * declaration using [:identical(next.stringValue, '('):], which (rightfully)
- * returns false because stringValue returns [:null:].
- */
- String get stringValue;
-
- /**
- * The kind enum of this token as determined by its [info].
- */
- int get kind => info.kind;
-
- /**
- * The precedence level for this token.
- */
- int get precedence => info.precedence;
-
- /**
- * True if this token is an identifier. Some keywords allowed as identifiers,
- * see implementation in [KeywordToken].
- */
- bool isIdentifier();
-
- /**
- * Returns a textual representation of this token to be used for debugging
- * purposes. The resulting string might contain information about the
- * structure of the token, for example 'StringToken(foo)' for the identifier
- * token 'foo'.
- *
- * Use [value] for the text actually parsed by the token.
- */
- String toString();
-
- /**
- * The number of characters parsed by this token.
- */
- int get charCount {
- if (info == BAD_INPUT_INFO) {
- // This is a token that wraps around an error message. Return 1
- // instead of the size of the length of the error message.
- return 1;
- } else {
- return value.length;
- }
- }
-
- int get hashCode => computeHashCode(charOffset, info, value);
-}
-
-/// A pair of tokens marking the beginning and the end of a span. Use for error
-/// reporting.
-class TokenPair implements Spannable {
- final Token begin;
- final Token end;
-
- TokenPair(this.begin, this.end);
-}
-
-/**
- * A [SymbolToken] represents the symbol in its precendence info.
- * Also used for end of file with EOF_INFO.
- */
-class SymbolToken extends Token {
-
- final PrecedenceInfo info;
-
- SymbolToken(this.info, int charOffset) : super(charOffset);
-
- String get value => info.value;
-
- String get stringValue => info.value;
-
- bool isIdentifier() => false;
-
- String toString() => "SymbolToken($value)";
-}
-
-/**
- * A [BeginGroupToken] represents a symbol that may be the beginning of
- * a pair of brackets, i.e., ( { [ < or ${
- * The [endGroup] token points to the matching closing bracked in case
- * it can be identified during scanning.
- */
-class BeginGroupToken extends SymbolToken {
- Token endGroup;
-
- BeginGroupToken(PrecedenceInfo info, int charOffset)
- : super(info, charOffset);
-}
-
-/**
- * A keyword token.
- */
-class KeywordToken extends Token {
- final Keyword keyword;
-
- KeywordToken(this.keyword, int charOffset) : super(charOffset);
-
- PrecedenceInfo get info => keyword.info;
-
- String get value => keyword.syntax;
-
- String get stringValue => keyword.syntax;
-
- bool isIdentifier() => keyword.isPseudo || keyword.isBuiltIn;
-
- String toString() => "KeywordToken($value)";
-}
-
-abstract class ErrorToken extends Token {
- ErrorToken(int charOffset)
- : super(charOffset);
-
- PrecedenceInfo get info => BAD_INPUT_INFO;
-
- String get value {
- throw new SpannableAssertionFailure(this, assertionMessage);
- }
-
- String get stringValue => null;
-
- bool isIdentifier() => false;
-
- String get assertionMessage;
-}
-
-class BadInputToken extends ErrorToken {
- final int character;
-
- BadInputToken(this.character, int charOffset)
- : super(charOffset);
-
- String toString() => "BadInputToken($character)";
-
- String get assertionMessage {
- return 'Character U+${character.toRadixString(16)} not allowed here.';
- }
-}
-
-class UnterminatedToken extends ErrorToken {
- final String start;
- final int endOffset;
-
- UnterminatedToken(this.start, int charOffset, this.endOffset)
- : super(charOffset);
-
- String toString() => "UnterminatedToken($start)";
-
- String get assertionMessage => "'$start' isn't terminated.";
-
- int get charCount => endOffset - charOffset;
-}
-
-class UnmatchedToken extends ErrorToken {
- final BeginGroupToken begin;
-
- UnmatchedToken(BeginGroupToken begin)
- : this.begin = begin,
- super(begin.charOffset);
-
- String toString() => "UnmatchedToken(${begin.value})";
-
- String get assertionMessage => "'$begin' isn't closed.";
-}
-
-/**
- * A String-valued token. Represents identifiers, string literals,
- * number literals, comments, and error tokens, using the corresponding
- * precedence info.
- */
-class StringToken extends Token {
- /**
- * The length threshold above which substring tokens are computed lazily.
- *
- * For string tokens that are substrings of the program source, the actual
- * substring extraction is performed lazily. This is beneficial because
- * not all scanned code is actually used. For unused parts, the substrings
- * are never computed and allocated.
- */
- static const int LAZY_THRESHOLD = 4;
-
- var /* String | LazySubtring */ valueOrLazySubstring;
-
- final PrecedenceInfo info;
-
- /**
- * Creates a non-lazy string token. If [canonicalize] is true, the string
- * is canonicalized before the token is created.
- */
- StringToken.fromString(this.info, String value, int charOffset,
- {bool canonicalize : false})
- : valueOrLazySubstring = canonicalizedString(value, canonicalize),
- super(charOffset);
-
- /**
- * Creates a lazy string token. If [canonicalize] is true, the string
- * is canonicalized before the token is created.
- */
- StringToken.fromSubstring(this.info, String data, int start, int end,
- int charOffset, {bool canonicalize : false})
- : super(charOffset) {
- int length = end - start;
- if (length <= LAZY_THRESHOLD) {
- valueOrLazySubstring = canonicalizedString(data.substring(start, end),
- canonicalize);
- } else {
- valueOrLazySubstring =
- new LazySubstring(data, start, length, canonicalize);
- }
- }
-
- /**
- * Creates a lazy string token. If [asciiOnly] is false, the byte array
- * is passed through a UTF-8 decoder.
- */
- StringToken.fromUtf8Bytes(this.info, List<int> data, int start, int end,
- bool asciiOnly, int charOffset)
- : super(charOffset) {
- int length = end - start;
- if (length <= LAZY_THRESHOLD) {
- valueOrLazySubstring = decodeUtf8(data, start, end, asciiOnly);
- } else {
- valueOrLazySubstring = new LazySubstring(data, start, length, asciiOnly);
- }
- }
-
- String get value {
- if (valueOrLazySubstring is String) {
- return valueOrLazySubstring;
- } else {
- assert(valueOrLazySubstring is LazySubstring);
- var data = valueOrLazySubstring.data;
- int start = valueOrLazySubstring.start;
- int end = start + valueOrLazySubstring.length;
- if (data is String) {
- valueOrLazySubstring = canonicalizedString(
- data.substring(start, end), valueOrLazySubstring.boolValue);
- } else {
- valueOrLazySubstring = decodeUtf8(
- data, start, end, valueOrLazySubstring.boolValue);
- }
- return valueOrLazySubstring;
- }
- }
-
- /// See [Token.stringValue] for an explanation.
- String get stringValue => null;
-
- bool isIdentifier() => identical(kind, IDENTIFIER_TOKEN);
-
- String toString() => "StringToken($value)";
-
- static final HashSet<String> canonicalizedSubstrings =
- new HashSet<String>();
-
- static String canonicalizedString(String s, bool canonicalize) {
- if (!canonicalize) return s;
- var result = canonicalizedSubstrings.lookup(s);
- if (result != null) return result;
- canonicalizedSubstrings.add(s);
- return s;
- }
-
- static String decodeUtf8(List<int> data, int start, int end, bool asciiOnly) {
- var s;
- if (asciiOnly) {
- s = new String.fromCharCodes(data, start, end);
- } else {
- s = UTF8.decoder.convert(data, start, end);
- }
- return canonicalizedString(s, true);
- }
-}
-
-/**
- * This class represents the necessary information to compute a substring
- * lazily. The substring can either originate from a string or from
- * a [:List<int>:] of UTF-8 bytes.
- */
-abstract class LazySubstring {
- /** The original data, either a string or a List<int> */
- get data;
-
- int get start;
- int get length;
-
- /**
- * If this substring is based on a String, the [boolValue] indicates wheter
- * the resulting substring should be canonicalized.
- *
- * For substrings based on a byte array, the [boolValue] is true if the
- * array only holds ASCII characters. The resulting substring will be
- * canonicalized after decoding.
- */
- bool get boolValue;
-
- LazySubstring.internal();
-
- factory LazySubstring(data, int start, int length, bool b) {
- // See comment on [CompactLazySubstring].
- if (start < 0x100000 && length < 0x200) {
- int fields = (start << 9);
- fields = fields | length;
- fields = fields << 1;
- if (b) fields |= 1;
- return new CompactLazySubstring(data, fields);
- } else {
- return new FullLazySubstring(data, start, length, b);
- }
- }
-}
-
-/**
- * This class encodes [start], [length] and [boolValue] in a single
- * 30 bit integer. It uses 20 bits for [start], which covers source files
- * of 1MB. [length] has 9 bits, which covers 512 characters.
- *
- * The file html_dart2js.dart is currently around 1MB.
- */
-class CompactLazySubstring extends LazySubstring {
- final data;
- final int fields;
-
- CompactLazySubstring(this.data, this.fields) : super.internal();
-
- int get start => fields >> 10;
- int get length => (fields >> 1) & 0x1ff;
- bool get boolValue => (fields & 1) == 1;
-}
-
-class FullLazySubstring extends LazySubstring {
- final data;
- final int start;
- final int length;
- final bool boolValue;
- FullLazySubstring(this.data, this.start, this.length, this.boolValue)
- : super.internal();
-}
-
-bool isUserDefinableOperator(String value) {
- return
- isBinaryOperator(value) ||
- isMinusOperator(value) ||
- isTernaryOperator(value) ||
- isUnaryOperator(value);
-}
-
-bool isUnaryOperator(String value) => identical(value, '~');
-
-bool isBinaryOperator(String value) {
- return
- (identical(value, '==')) ||
- (identical(value, '[]')) ||
- (identical(value, '*')) ||
- (identical(value, '/')) ||
- (identical(value, '%')) ||
- (identical(value, '~/')) ||
- (identical(value, '+')) ||
- (identical(value, '<<')) ||
- (identical(value, '>>')) ||
- (identical(value, '>=')) ||
- (identical(value, '>')) ||
- (identical(value, '<=')) ||
- (identical(value, '<')) ||
- (identical(value, '&')) ||
- (identical(value, '^')) ||
- (identical(value, '|'));
-}
-
-bool isTernaryOperator(String value) => identical(value, '[]=');
-
-bool isMinusOperator(String value) => identical(value, '-');
-
-class PrecedenceInfo {
- final String value;
- final int precedence;
- final int kind;
-
- const PrecedenceInfo(this.value, this.precedence, this.kind);
-
- toString() => 'PrecedenceInfo($value, $precedence, $kind)';
-
- int get hashCode => computeHashCode(value, precedence, kind);
-}
-
-// TODO(ahe): The following are not tokens in Dart.
-const PrecedenceInfo BACKPING_INFO =
- const PrecedenceInfo('`', 0, BACKPING_TOKEN);
-const PrecedenceInfo BACKSLASH_INFO =
- const PrecedenceInfo('\\', 0, BACKSLASH_TOKEN);
-const PrecedenceInfo PERIOD_PERIOD_PERIOD_INFO =
- const PrecedenceInfo('...', 0,
- PERIOD_PERIOD_PERIOD_TOKEN);
-
-/**
- * The cascade operator has the lowest precedence of any operator
- * except assignment.
- */
-const int CASCADE_PRECEDENCE = 2;
-const PrecedenceInfo PERIOD_PERIOD_INFO =
- const PrecedenceInfo('..', CASCADE_PRECEDENCE,
- PERIOD_PERIOD_TOKEN);
-
-const PrecedenceInfo BANG_INFO =
- const PrecedenceInfo('!', 0, BANG_TOKEN);
-const PrecedenceInfo COLON_INFO =
- const PrecedenceInfo(':', 0, COLON_TOKEN);
-const PrecedenceInfo INDEX_INFO =
- const PrecedenceInfo('[]', 0, INDEX_TOKEN);
-const PrecedenceInfo MINUS_MINUS_INFO =
- const PrecedenceInfo('--', POSTFIX_PRECEDENCE,
- MINUS_MINUS_TOKEN);
-const PrecedenceInfo PLUS_PLUS_INFO =
- const PrecedenceInfo('++', POSTFIX_PRECEDENCE,
- PLUS_PLUS_TOKEN);
-const PrecedenceInfo TILDE_INFO =
- const PrecedenceInfo('~', 0, TILDE_TOKEN);
-
-const PrecedenceInfo FUNCTION_INFO =
- const PrecedenceInfo('=>', 0, FUNCTION_TOKEN);
-const PrecedenceInfo HASH_INFO =
- const PrecedenceInfo('#', 0, HASH_TOKEN);
-const PrecedenceInfo INDEX_EQ_INFO =
- const PrecedenceInfo('[]=', 0, INDEX_EQ_TOKEN);
-const PrecedenceInfo SEMICOLON_INFO =
- const PrecedenceInfo(';', 0, SEMICOLON_TOKEN);
-const PrecedenceInfo COMMA_INFO =
- const PrecedenceInfo(',', 0, COMMA_TOKEN);
-
-const PrecedenceInfo AT_INFO =
- const PrecedenceInfo('@', 0, AT_TOKEN);
-
-// Assignment operators.
-const int ASSIGNMENT_PRECEDENCE = 1;
-const PrecedenceInfo AMPERSAND_EQ_INFO =
- const PrecedenceInfo('&=',
- ASSIGNMENT_PRECEDENCE, AMPERSAND_EQ_TOKEN);
-const PrecedenceInfo BAR_EQ_INFO =
- const PrecedenceInfo('|=',
- ASSIGNMENT_PRECEDENCE, BAR_EQ_TOKEN);
-const PrecedenceInfo CARET_EQ_INFO =
- const PrecedenceInfo('^=',
- ASSIGNMENT_PRECEDENCE, CARET_EQ_TOKEN);
-const PrecedenceInfo EQ_INFO =
- const PrecedenceInfo('=',
- ASSIGNMENT_PRECEDENCE, EQ_TOKEN);
-const PrecedenceInfo GT_GT_EQ_INFO =
- const PrecedenceInfo('>>=',
- ASSIGNMENT_PRECEDENCE, GT_GT_EQ_TOKEN);
-const PrecedenceInfo LT_LT_EQ_INFO =
- const PrecedenceInfo('<<=',
- ASSIGNMENT_PRECEDENCE, LT_LT_EQ_TOKEN);
-const PrecedenceInfo MINUS_EQ_INFO =
- const PrecedenceInfo('-=',
- ASSIGNMENT_PRECEDENCE, MINUS_EQ_TOKEN);
-const PrecedenceInfo PERCENT_EQ_INFO =
- const PrecedenceInfo('%=',
- ASSIGNMENT_PRECEDENCE, PERCENT_EQ_TOKEN);
-const PrecedenceInfo PLUS_EQ_INFO =
- const PrecedenceInfo('+=',
- ASSIGNMENT_PRECEDENCE, PLUS_EQ_TOKEN);
-const PrecedenceInfo SLASH_EQ_INFO =
- const PrecedenceInfo('/=',
- ASSIGNMENT_PRECEDENCE, SLASH_EQ_TOKEN);
-const PrecedenceInfo STAR_EQ_INFO =
- const PrecedenceInfo('*=',
- ASSIGNMENT_PRECEDENCE, STAR_EQ_TOKEN);
-const PrecedenceInfo TILDE_SLASH_EQ_INFO =
- const PrecedenceInfo('~/=',
- ASSIGNMENT_PRECEDENCE, TILDE_SLASH_EQ_TOKEN);
-const PrecedenceInfo QUESTION_QUESTION_EQ_INFO =
- const PrecedenceInfo('??=',
- ASSIGNMENT_PRECEDENCE, QUESTION_QUESTION_EQ_TOKEN);
-
-const PrecedenceInfo QUESTION_INFO =
- const PrecedenceInfo('?', 3, QUESTION_TOKEN);
-
-const PrecedenceInfo QUESTION_QUESTION_INFO =
- const PrecedenceInfo('??', 4, QUESTION_QUESTION_TOKEN);
-
-const PrecedenceInfo BAR_BAR_INFO =
- const PrecedenceInfo('||', 5, BAR_BAR_TOKEN);
-
-const PrecedenceInfo AMPERSAND_AMPERSAND_INFO =
- const PrecedenceInfo('&&', 6, AMPERSAND_AMPERSAND_TOKEN);
-
-const PrecedenceInfo BAR_INFO =
- const PrecedenceInfo('|', 9, BAR_TOKEN);
-
-const PrecedenceInfo CARET_INFO =
- const PrecedenceInfo('^', 10, CARET_TOKEN);
-
-const PrecedenceInfo AMPERSAND_INFO =
- const PrecedenceInfo('&', 11, AMPERSAND_TOKEN);
-
-// Equality operators.
-const int EQUALITY_PRECEDENCE = 7;
-const PrecedenceInfo BANG_EQ_EQ_INFO =
- const PrecedenceInfo('!==',
- EQUALITY_PRECEDENCE, BANG_EQ_EQ_TOKEN);
-const PrecedenceInfo BANG_EQ_INFO =
- const PrecedenceInfo('!=',
- EQUALITY_PRECEDENCE, BANG_EQ_TOKEN);
-const PrecedenceInfo EQ_EQ_EQ_INFO =
- const PrecedenceInfo('===',
- EQUALITY_PRECEDENCE, EQ_EQ_EQ_TOKEN);
-const PrecedenceInfo EQ_EQ_INFO =
- const PrecedenceInfo('==',
- EQUALITY_PRECEDENCE, EQ_EQ_TOKEN);
-
-// Relational operators.
-const int RELATIONAL_PRECEDENCE = 8;
-const PrecedenceInfo GT_EQ_INFO =
- const PrecedenceInfo('>=',
- RELATIONAL_PRECEDENCE, GT_EQ_TOKEN);
-const PrecedenceInfo GT_INFO =
- const PrecedenceInfo('>',
- RELATIONAL_PRECEDENCE, GT_TOKEN);
-const PrecedenceInfo IS_INFO =
- const PrecedenceInfo('is',
- RELATIONAL_PRECEDENCE, KEYWORD_TOKEN);
-const PrecedenceInfo AS_INFO =
- const PrecedenceInfo('as',
- RELATIONAL_PRECEDENCE, KEYWORD_TOKEN);
-const PrecedenceInfo LT_EQ_INFO =
- const PrecedenceInfo('<=',
- RELATIONAL_PRECEDENCE, LT_EQ_TOKEN);
-const PrecedenceInfo LT_INFO =
- const PrecedenceInfo('<',
- RELATIONAL_PRECEDENCE, LT_TOKEN);
-
-// Shift operators.
-const PrecedenceInfo GT_GT_INFO =
- const PrecedenceInfo('>>', 12, GT_GT_TOKEN);
-const PrecedenceInfo LT_LT_INFO =
- const PrecedenceInfo('<<', 12, LT_LT_TOKEN);
-
-// Additive operators.
-const PrecedenceInfo MINUS_INFO =
- const PrecedenceInfo('-', 13, MINUS_TOKEN);
-const PrecedenceInfo PLUS_INFO =
- const PrecedenceInfo('+', 13, PLUS_TOKEN);
-
-// Multiplicative operators.
-const PrecedenceInfo PERCENT_INFO =
- const PrecedenceInfo('%', 14, PERCENT_TOKEN);
-const PrecedenceInfo SLASH_INFO =
- const PrecedenceInfo('/', 14, SLASH_TOKEN);
-const PrecedenceInfo STAR_INFO =
- const PrecedenceInfo('*', 14, STAR_TOKEN);
-const PrecedenceInfo TILDE_SLASH_INFO =
- const PrecedenceInfo('~/', 14, TILDE_SLASH_TOKEN);
-
-const int POSTFIX_PRECEDENCE = 15;
-const PrecedenceInfo PERIOD_INFO =
- const PrecedenceInfo('.', POSTFIX_PRECEDENCE,
- PERIOD_TOKEN);
-const PrecedenceInfo QUESTION_PERIOD_INFO =
- const PrecedenceInfo('?.', POSTFIX_PRECEDENCE,
- QUESTION_PERIOD_TOKEN);
-
-const PrecedenceInfo KEYWORD_INFO =
- const PrecedenceInfo('keyword', 0, KEYWORD_TOKEN);
-
-const PrecedenceInfo EOF_INFO =
- const PrecedenceInfo('EOF', 0, EOF_TOKEN);
-
-const PrecedenceInfo IDENTIFIER_INFO =
- const PrecedenceInfo('identifier', 0, IDENTIFIER_TOKEN);
-
-const PrecedenceInfo BAD_INPUT_INFO =
- const PrecedenceInfo('malformed input', 0,
- BAD_INPUT_TOKEN);
-
-const PrecedenceInfo OPEN_PAREN_INFO =
- const PrecedenceInfo('(', POSTFIX_PRECEDENCE,
- OPEN_PAREN_TOKEN);
-
-const PrecedenceInfo CLOSE_PAREN_INFO =
- const PrecedenceInfo(')', 0, CLOSE_PAREN_TOKEN);
-
-const PrecedenceInfo OPEN_CURLY_BRACKET_INFO =
- const PrecedenceInfo('{', 0, OPEN_CURLY_BRACKET_TOKEN);
-
-const PrecedenceInfo CLOSE_CURLY_BRACKET_INFO =
- const PrecedenceInfo('}', 0, CLOSE_CURLY_BRACKET_TOKEN);
-
-const PrecedenceInfo INT_INFO =
- const PrecedenceInfo('int', 0, INT_TOKEN);
-
-const PrecedenceInfo STRING_INFO =
- const PrecedenceInfo('string', 0, STRING_TOKEN);
-
-const PrecedenceInfo OPEN_SQUARE_BRACKET_INFO =
- const PrecedenceInfo('[', POSTFIX_PRECEDENCE,
- OPEN_SQUARE_BRACKET_TOKEN);
-
-const PrecedenceInfo CLOSE_SQUARE_BRACKET_INFO =
- const PrecedenceInfo(']', 0, CLOSE_SQUARE_BRACKET_TOKEN);
-
-const PrecedenceInfo DOUBLE_INFO =
- const PrecedenceInfo('double', 0, DOUBLE_TOKEN);
-
-const PrecedenceInfo STRING_INTERPOLATION_INFO =
- const PrecedenceInfo('\${', 0,
- STRING_INTERPOLATION_TOKEN);
-
-const PrecedenceInfo STRING_INTERPOLATION_IDENTIFIER_INFO =
- const PrecedenceInfo('\$', 0,
- STRING_INTERPOLATION_IDENTIFIER_TOKEN);
-
-const PrecedenceInfo HEXADECIMAL_INFO =
- const PrecedenceInfo('hexadecimal', 0, HEXADECIMAL_TOKEN);
-
-const PrecedenceInfo COMMENT_INFO =
- const PrecedenceInfo('comment', 0, COMMENT_TOKEN);
diff --git a/pkg/compiler/lib/src/scanner/utf8_bytes_scanner.dart b/pkg/compiler/lib/src/scanner/utf8_bytes_scanner.dart
index d919596..4c42bf7 100644
--- a/pkg/compiler/lib/src/scanner/utf8_bytes_scanner.dart
+++ b/pkg/compiler/lib/src/scanner/utf8_bytes_scanner.dart
@@ -2,7 +2,22 @@
// 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.
-part of scanner;
+library dart2js.scanner.utf8;
+
+import 'dart:convert' show
+ UNICODE_BOM_CHARACTER_RUNE,
+ UTF8;
+
+import '../io/source_file.dart' show
+ SourceFile;
+import '../tokens/precedence.dart' show
+ PrecedenceInfo;
+import '../tokens/token.dart' show
+ StringToken,
+ Token;
+
+import 'array_based_scanner.dart' show
+ ArrayBasedScanner;
/**
* Scanner that reads from a UTF-8 encoded list of bytes and creates tokens
diff --git a/pkg/compiler/lib/src/serialization/modelz.dart b/pkg/compiler/lib/src/serialization/modelz.dart
index bd28c0e..a0ba0a8 100644
--- a/pkg/compiler/lib/src/serialization/modelz.dart
+++ b/pkg/compiler/lib/src/serialization/modelz.dart
@@ -33,11 +33,12 @@
TreeElements;
import '../resolution/scope.dart' show
Scope;
-import '../scanner/scannerlib.dart' show
- Token,
- SEMICOLON_INFO;
import '../script.dart';
import '../serialization/constant_serialization.dart';
+import '../tokens/precedence_constants.dart' as Precedence show
+ SEMICOLON_INFO;
+import '../tokens/token.dart' show
+ Token;
import '../tree/tree.dart';
import '../util/util.dart' show
Link,
@@ -484,7 +485,8 @@
Import tag = new Import(
builder.keywordToken('import'),
builder.literalString(library.canonicalUri.toString())
- ..getEndToken().next = builder.symbolToken(SEMICOLON_INFO),
+ ..getEndToken().next =
+ builder.symbolToken(Precedence.SEMICOLON_INFO),
null, // prefix
null, // combinators
null, // metadata
@@ -494,7 +496,8 @@
Export tag = new Export(
builder.keywordToken('export'),
builder.literalString(library.canonicalUri.toString())
- ..getEndToken().next = builder.symbolToken(SEMICOLON_INFO),
+ ..getEndToken().next =
+ builder.symbolToken(Precedence.SEMICOLON_INFO),
null, // combinators
null); // metadata
_libraryDependencies[tag] = library;
diff --git a/pkg/compiler/lib/src/ssa/codegen.dart b/pkg/compiler/lib/src/ssa/codegen.dart
index 998ed36..6a2002c 100644
--- a/pkg/compiler/lib/src/ssa/codegen.dart
+++ b/pkg/compiler/lib/src/ssa/codegen.dart
@@ -1924,7 +1924,6 @@
generateConstant(node.constant, node.sourceInformation);
registry.registerCompileTimeConstant(node.constant);
- backend.constants.addCompileTimeConstantForEmission(node.constant);
}
visitNot(HNot node) {
diff --git a/pkg/compiler/lib/src/string_validator.dart b/pkg/compiler/lib/src/string_validator.dart
index 2968528..7171368 100644
--- a/pkg/compiler/lib/src/string_validator.dart
+++ b/pkg/compiler/lib/src/string_validator.dart
@@ -10,7 +10,7 @@
import 'diagnostics/diagnostic_listener.dart';
import 'diagnostics/messages.dart' show MessageKind;
-import 'scanner/scannerlib.dart' show Token;
+import 'tokens/token.dart' show Token;
import 'tree/tree.dart';
import 'util/characters.dart';
diff --git a/pkg/compiler/lib/src/scanner/keyword.dart b/pkg/compiler/lib/src/tokens/keyword.dart
similarity index 86%
rename from pkg/compiler/lib/src/scanner/keyword.dart
rename to pkg/compiler/lib/src/tokens/keyword.dart
index 804a0ee..ce1bc87 100644
--- a/pkg/compiler/lib/src/scanner/keyword.dart
+++ b/pkg/compiler/lib/src/tokens/keyword.dart
@@ -2,7 +2,17 @@
// 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.
-part of scanner;
+library dart2js.tokens.keywords;
+
+import '../util/characters.dart' as Characters show
+ $a;
+
+import 'precedence.dart' show
+ PrecedenceInfo;
+import 'precedence_constants.dart' as Precedence show
+ AS_INFO,
+ IS_INFO,
+ KEYWORD_INFO;
/**
* A keyword in the Dart programming language.
@@ -44,10 +54,10 @@
// TODO(ahe): Don't think this is a reserved word.
// See: http://dartbug.com/5579
- const Keyword("is", info: IS_INFO),
+ const Keyword("is", info: Precedence.IS_INFO),
const Keyword("abstract", isBuiltIn: true),
- const Keyword("as", info: AS_INFO, isBuiltIn: true),
+ const Keyword("as", info: Precedence.AS_INFO, isBuiltIn: true),
const Keyword("dynamic", isBuiltIn: true),
const Keyword("export", isBuiltIn: true),
const Keyword("external", isBuiltIn: true),
@@ -90,7 +100,7 @@
const Keyword(this.syntax,
{this.isPseudo: false,
this.isBuiltIn: false,
- this.info: KEYWORD_INFO});
+ this.info: Precedence.KEYWORD_INFO});
static Map<String, Keyword> computeKeywordMap() {
Map<String, Keyword> result = new Map<String, Keyword>();
@@ -141,10 +151,10 @@
int c = strings[i].codeUnitAt(start);
if (chunk != c) {
if (chunkStart != -1) {
- assert(result[chunk - $a] == null);
- result[chunk - $a] = computeKeywordStateTable(start + 1, strings,
- chunkStart,
- i - chunkStart);
+ assert(result[chunk - Characters.$a] == null);
+ result[chunk - Characters.$a] =
+ computeKeywordStateTable(
+ start + 1, strings, chunkStart, i - chunkStart);
}
chunkStart = i;
chunk = c;
@@ -152,8 +162,8 @@
}
}
if (chunkStart != -1) {
- assert(result[chunk - $a] == null);
- result[chunk - $a] =
+ assert(result[chunk - Characters.$a] == null);
+ result[chunk - Characters.$a] =
computeKeywordStateTable(start + 1, strings, chunkStart,
offset + length - chunkStart);
} else {
@@ -177,7 +187,7 @@
ArrayKeywordState(List<KeywordState> this.table, String syntax)
: super((syntax == null) ? null : Keyword.keywords[syntax]);
- KeywordState next(int c) => table[c - $a];
+ KeywordState next(int c) => table[c - Characters.$a];
String toString() {
StringBuffer sb = new StringBuffer();
@@ -190,7 +200,8 @@
List<KeywordState> foo = table;
for (int i = 0; i < foo.length; i++) {
if (foo[i] != null) {
- sb.write("${new String.fromCharCodes([i + $a])}: ${foo[i]}; ");
+ sb.write("${new String.fromCharCodes([i + Characters.$a])}: "
+ "${foo[i]}; ");
}
}
sb.write("]");
diff --git a/pkg/compiler/lib/src/tokens/precedence.dart b/pkg/compiler/lib/src/tokens/precedence.dart
new file mode 100644
index 0000000..1183a0b
--- /dev/null
+++ b/pkg/compiler/lib/src/tokens/precedence.dart
@@ -0,0 +1,20 @@
+// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library dart2js.tokens.precedence;
+
+import '../util/util.dart' show
+ computeHashCode;
+
+class PrecedenceInfo {
+ final String value;
+ final int precedence;
+ final int kind;
+
+ const PrecedenceInfo(this.value, this.precedence, this.kind);
+
+ toString() => 'PrecedenceInfo($value, $precedence, $kind)';
+
+ int get hashCode => computeHashCode(value, precedence, kind);
+}
diff --git a/pkg/compiler/lib/src/tokens/precedence_constants.dart b/pkg/compiler/lib/src/tokens/precedence_constants.dart
new file mode 100644
index 0000000..f2e44f2
--- /dev/null
+++ b/pkg/compiler/lib/src/tokens/precedence_constants.dart
@@ -0,0 +1,241 @@
+// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library dart2js.tokens.precedence.constants;
+
+import 'precedence.dart' show
+ PrecedenceInfo;
+import 'token_constants.dart';
+
+// TODO(ahe): The following are not tokens in Dart.
+const PrecedenceInfo BACKPING_INFO =
+ const PrecedenceInfo('`', 0, BACKPING_TOKEN);
+const PrecedenceInfo BACKSLASH_INFO =
+ const PrecedenceInfo('\\', 0, BACKSLASH_TOKEN);
+const PrecedenceInfo PERIOD_PERIOD_PERIOD_INFO =
+ const PrecedenceInfo('...', 0,
+ PERIOD_PERIOD_PERIOD_TOKEN);
+
+/**
+ * The cascade operator has the lowest precedence of any operator
+ * except assignment.
+ */
+const int CASCADE_PRECEDENCE = 2;
+const PrecedenceInfo PERIOD_PERIOD_INFO =
+ const PrecedenceInfo('..', CASCADE_PRECEDENCE,
+ PERIOD_PERIOD_TOKEN);
+
+const PrecedenceInfo BANG_INFO =
+ const PrecedenceInfo('!', 0, BANG_TOKEN);
+const PrecedenceInfo COLON_INFO =
+ const PrecedenceInfo(':', 0, COLON_TOKEN);
+const PrecedenceInfo INDEX_INFO =
+ const PrecedenceInfo('[]', 0, INDEX_TOKEN);
+const PrecedenceInfo MINUS_MINUS_INFO =
+ const PrecedenceInfo('--', POSTFIX_PRECEDENCE,
+ MINUS_MINUS_TOKEN);
+const PrecedenceInfo PLUS_PLUS_INFO =
+ const PrecedenceInfo('++', POSTFIX_PRECEDENCE,
+ PLUS_PLUS_TOKEN);
+const PrecedenceInfo TILDE_INFO =
+ const PrecedenceInfo('~', 0, TILDE_TOKEN);
+
+const PrecedenceInfo FUNCTION_INFO =
+ const PrecedenceInfo('=>', 0, FUNCTION_TOKEN);
+const PrecedenceInfo HASH_INFO =
+ const PrecedenceInfo('#', 0, HASH_TOKEN);
+const PrecedenceInfo INDEX_EQ_INFO =
+ const PrecedenceInfo('[]=', 0, INDEX_EQ_TOKEN);
+const PrecedenceInfo SEMICOLON_INFO =
+ const PrecedenceInfo(';', 0, SEMICOLON_TOKEN);
+const PrecedenceInfo COMMA_INFO =
+ const PrecedenceInfo(',', 0, COMMA_TOKEN);
+
+const PrecedenceInfo AT_INFO =
+ const PrecedenceInfo('@', 0, AT_TOKEN);
+
+// Assignment operators.
+const int ASSIGNMENT_PRECEDENCE = 1;
+const PrecedenceInfo AMPERSAND_EQ_INFO =
+ const PrecedenceInfo('&=',
+ ASSIGNMENT_PRECEDENCE, AMPERSAND_EQ_TOKEN);
+const PrecedenceInfo BAR_EQ_INFO =
+ const PrecedenceInfo('|=',
+ ASSIGNMENT_PRECEDENCE, BAR_EQ_TOKEN);
+const PrecedenceInfo CARET_EQ_INFO =
+ const PrecedenceInfo('^=',
+ ASSIGNMENT_PRECEDENCE, CARET_EQ_TOKEN);
+const PrecedenceInfo EQ_INFO =
+ const PrecedenceInfo('=',
+ ASSIGNMENT_PRECEDENCE, EQ_TOKEN);
+const PrecedenceInfo GT_GT_EQ_INFO =
+ const PrecedenceInfo('>>=',
+ ASSIGNMENT_PRECEDENCE, GT_GT_EQ_TOKEN);
+const PrecedenceInfo LT_LT_EQ_INFO =
+ const PrecedenceInfo('<<=',
+ ASSIGNMENT_PRECEDENCE, LT_LT_EQ_TOKEN);
+const PrecedenceInfo MINUS_EQ_INFO =
+ const PrecedenceInfo('-=',
+ ASSIGNMENT_PRECEDENCE, MINUS_EQ_TOKEN);
+const PrecedenceInfo PERCENT_EQ_INFO =
+ const PrecedenceInfo('%=',
+ ASSIGNMENT_PRECEDENCE, PERCENT_EQ_TOKEN);
+const PrecedenceInfo PLUS_EQ_INFO =
+ const PrecedenceInfo('+=',
+ ASSIGNMENT_PRECEDENCE, PLUS_EQ_TOKEN);
+const PrecedenceInfo SLASH_EQ_INFO =
+ const PrecedenceInfo('/=',
+ ASSIGNMENT_PRECEDENCE, SLASH_EQ_TOKEN);
+const PrecedenceInfo STAR_EQ_INFO =
+ const PrecedenceInfo('*=',
+ ASSIGNMENT_PRECEDENCE, STAR_EQ_TOKEN);
+const PrecedenceInfo TILDE_SLASH_EQ_INFO =
+ const PrecedenceInfo('~/=',
+ ASSIGNMENT_PRECEDENCE, TILDE_SLASH_EQ_TOKEN);
+const PrecedenceInfo QUESTION_QUESTION_EQ_INFO =
+ const PrecedenceInfo('??=',
+ ASSIGNMENT_PRECEDENCE, QUESTION_QUESTION_EQ_TOKEN);
+
+const PrecedenceInfo QUESTION_INFO =
+ const PrecedenceInfo('?', 3, QUESTION_TOKEN);
+
+const PrecedenceInfo QUESTION_QUESTION_INFO =
+ const PrecedenceInfo('??', 4, QUESTION_QUESTION_TOKEN);
+
+const PrecedenceInfo BAR_BAR_INFO =
+ const PrecedenceInfo('||', 5, BAR_BAR_TOKEN);
+
+const PrecedenceInfo AMPERSAND_AMPERSAND_INFO =
+ const PrecedenceInfo('&&', 6, AMPERSAND_AMPERSAND_TOKEN);
+
+const PrecedenceInfo BAR_INFO =
+ const PrecedenceInfo('|', 9, BAR_TOKEN);
+
+const PrecedenceInfo CARET_INFO =
+ const PrecedenceInfo('^', 10, CARET_TOKEN);
+
+const PrecedenceInfo AMPERSAND_INFO =
+ const PrecedenceInfo('&', 11, AMPERSAND_TOKEN);
+
+// Equality operators.
+const int EQUALITY_PRECEDENCE = 7;
+const PrecedenceInfo BANG_EQ_EQ_INFO =
+ const PrecedenceInfo('!==',
+ EQUALITY_PRECEDENCE, BANG_EQ_EQ_TOKEN);
+const PrecedenceInfo BANG_EQ_INFO =
+ const PrecedenceInfo('!=',
+ EQUALITY_PRECEDENCE, BANG_EQ_TOKEN);
+const PrecedenceInfo EQ_EQ_EQ_INFO =
+ const PrecedenceInfo('===',
+ EQUALITY_PRECEDENCE, EQ_EQ_EQ_TOKEN);
+const PrecedenceInfo EQ_EQ_INFO =
+ const PrecedenceInfo('==',
+ EQUALITY_PRECEDENCE, EQ_EQ_TOKEN);
+
+// Relational operators.
+const int RELATIONAL_PRECEDENCE = 8;
+const PrecedenceInfo GT_EQ_INFO =
+ const PrecedenceInfo('>=',
+ RELATIONAL_PRECEDENCE, GT_EQ_TOKEN);
+const PrecedenceInfo GT_INFO =
+ const PrecedenceInfo('>',
+ RELATIONAL_PRECEDENCE, GT_TOKEN);
+const PrecedenceInfo IS_INFO =
+ const PrecedenceInfo('is',
+ RELATIONAL_PRECEDENCE, KEYWORD_TOKEN);
+const PrecedenceInfo AS_INFO =
+ const PrecedenceInfo('as',
+ RELATIONAL_PRECEDENCE, KEYWORD_TOKEN);
+const PrecedenceInfo LT_EQ_INFO =
+ const PrecedenceInfo('<=',
+ RELATIONAL_PRECEDENCE, LT_EQ_TOKEN);
+const PrecedenceInfo LT_INFO =
+ const PrecedenceInfo('<',
+ RELATIONAL_PRECEDENCE, LT_TOKEN);
+
+// Shift operators.
+const PrecedenceInfo GT_GT_INFO =
+ const PrecedenceInfo('>>', 12, GT_GT_TOKEN);
+const PrecedenceInfo LT_LT_INFO =
+ const PrecedenceInfo('<<', 12, LT_LT_TOKEN);
+
+// Additive operators.
+const PrecedenceInfo MINUS_INFO =
+ const PrecedenceInfo('-', 13, MINUS_TOKEN);
+const PrecedenceInfo PLUS_INFO =
+ const PrecedenceInfo('+', 13, PLUS_TOKEN);
+
+// Multiplicative operators.
+const PrecedenceInfo PERCENT_INFO =
+ const PrecedenceInfo('%', 14, PERCENT_TOKEN);
+const PrecedenceInfo SLASH_INFO =
+ const PrecedenceInfo('/', 14, SLASH_TOKEN);
+const PrecedenceInfo STAR_INFO =
+ const PrecedenceInfo('*', 14, STAR_TOKEN);
+const PrecedenceInfo TILDE_SLASH_INFO =
+ const PrecedenceInfo('~/', 14, TILDE_SLASH_TOKEN);
+
+const int POSTFIX_PRECEDENCE = 15;
+const PrecedenceInfo PERIOD_INFO =
+ const PrecedenceInfo('.', POSTFIX_PRECEDENCE,
+ PERIOD_TOKEN);
+const PrecedenceInfo QUESTION_PERIOD_INFO =
+ const PrecedenceInfo('?.', POSTFIX_PRECEDENCE,
+ QUESTION_PERIOD_TOKEN);
+
+const PrecedenceInfo KEYWORD_INFO =
+ const PrecedenceInfo('keyword', 0, KEYWORD_TOKEN);
+
+const PrecedenceInfo EOF_INFO =
+ const PrecedenceInfo('EOF', 0, EOF_TOKEN);
+
+const PrecedenceInfo IDENTIFIER_INFO =
+ const PrecedenceInfo('identifier', 0, IDENTIFIER_TOKEN);
+
+const PrecedenceInfo BAD_INPUT_INFO =
+ const PrecedenceInfo('malformed input', 0,
+ BAD_INPUT_TOKEN);
+
+const PrecedenceInfo OPEN_PAREN_INFO =
+ const PrecedenceInfo('(', POSTFIX_PRECEDENCE,
+ OPEN_PAREN_TOKEN);
+
+const PrecedenceInfo CLOSE_PAREN_INFO =
+ const PrecedenceInfo(')', 0, CLOSE_PAREN_TOKEN);
+
+const PrecedenceInfo OPEN_CURLY_BRACKET_INFO =
+ const PrecedenceInfo('{', 0, OPEN_CURLY_BRACKET_TOKEN);
+
+const PrecedenceInfo CLOSE_CURLY_BRACKET_INFO =
+ const PrecedenceInfo('}', 0, CLOSE_CURLY_BRACKET_TOKEN);
+
+const PrecedenceInfo INT_INFO =
+ const PrecedenceInfo('int', 0, INT_TOKEN);
+
+const PrecedenceInfo STRING_INFO =
+ const PrecedenceInfo('string', 0, STRING_TOKEN);
+
+const PrecedenceInfo OPEN_SQUARE_BRACKET_INFO =
+ const PrecedenceInfo('[', POSTFIX_PRECEDENCE,
+ OPEN_SQUARE_BRACKET_TOKEN);
+
+const PrecedenceInfo CLOSE_SQUARE_BRACKET_INFO =
+ const PrecedenceInfo(']', 0, CLOSE_SQUARE_BRACKET_TOKEN);
+
+const PrecedenceInfo DOUBLE_INFO =
+ const PrecedenceInfo('double', 0, DOUBLE_TOKEN);
+
+const PrecedenceInfo STRING_INTERPOLATION_INFO =
+ const PrecedenceInfo('\${', 0,
+ STRING_INTERPOLATION_TOKEN);
+
+const PrecedenceInfo STRING_INTERPOLATION_IDENTIFIER_INFO =
+ const PrecedenceInfo('\$', 0,
+ STRING_INTERPOLATION_IDENTIFIER_TOKEN);
+
+const PrecedenceInfo HEXADECIMAL_INFO =
+ const PrecedenceInfo('hexadecimal', 0, HEXADECIMAL_TOKEN);
+
+const PrecedenceInfo COMMENT_INFO =
+ const PrecedenceInfo('comment', 0, COMMENT_TOKEN);
diff --git a/pkg/compiler/lib/src/tokens/token.dart b/pkg/compiler/lib/src/tokens/token.dart
new file mode 100644
index 0000000..e656f9e
--- /dev/null
+++ b/pkg/compiler/lib/src/tokens/token.dart
@@ -0,0 +1,442 @@
+// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library dart2js.tokens;
+
+import 'dart:convert' show
+ UTF8;
+import 'dart:collection' show
+ HashSet;
+
+import '../diagnostics/spannable.dart' show
+ Spannable,
+ SpannableAssertionFailure;
+import '../util/util.dart' show
+ computeHashCode;
+
+import 'keyword.dart' show
+ Keyword;
+import 'precedence.dart' show
+ PrecedenceInfo;
+import 'precedence_constants.dart' as Precedence show
+ BAD_INPUT_INFO;
+import 'token_constants.dart' as Tokens show
+ IDENTIFIER_TOKEN;
+
+/**
+ * A token that doubles as a linked list.
+ */
+abstract class Token implements Spannable {
+ /**
+ * The character offset of the start of this token within the source text.
+ */
+ final int charOffset;
+
+ Token(this.charOffset);
+
+ /**
+ * The next token in the token stream.
+ */
+ Token next;
+
+ /**
+ * The precedence info for this token. [info] determines the kind and the
+ * precedence level of this token.
+ *
+ * Defined as getter to save a field in the [KeywordToken] subclass.
+ */
+ PrecedenceInfo get info;
+
+ /**
+ * The string represented by this token, a substring of the source code.
+ *
+ * For [StringToken]s the [value] includes the quotes, explicit escapes, etc.
+ */
+ String get value;
+
+ /**
+ * For symbol and keyword tokens, returns the string value represented by this
+ * token. For [StringToken]s this method returns [:null:].
+ *
+ * For [SymbolToken]s and [KeywordToken]s, the string value is a compile-time
+ * constant originating in the [PrecedenceInfo] or in the [Keyword] instance.
+ * This allows testing for keywords and symbols using [:identical:], e.g.,
+ * [:identical('class', token.value):].
+ *
+ * Note that returning [:null:] for string tokens is important to identify
+ * symbols and keywords, we cannot use [value] instead. The string literal
+ * "$a($b"
+ * produces ..., SymbolToken($), StringToken(a), StringToken((), ...
+ *
+ * After parsing the identifier 'a', the parser tests for a function
+ * declaration using [:identical(next.stringValue, '('):], which (rightfully)
+ * returns false because stringValue returns [:null:].
+ */
+ String get stringValue;
+
+ /**
+ * The kind enum of this token as determined by its [info].
+ */
+ int get kind => info.kind;
+
+ /**
+ * The precedence level for this token.
+ */
+ int get precedence => info.precedence;
+
+ /**
+ * True if this token is an identifier. Some keywords allowed as identifiers,
+ * see implementation in [KeywordToken].
+ */
+ bool isIdentifier();
+
+ /**
+ * Returns a textual representation of this token to be used for debugging
+ * purposes. The resulting string might contain information about the
+ * structure of the token, for example 'StringToken(foo)' for the identifier
+ * token 'foo'.
+ *
+ * Use [value] for the text actually parsed by the token.
+ */
+ String toString();
+
+ /**
+ * The number of characters parsed by this token.
+ */
+ int get charCount {
+ if (info == Precedence.BAD_INPUT_INFO) {
+ // This is a token that wraps around an error message. Return 1
+ // instead of the size of the length of the error message.
+ return 1;
+ } else {
+ return value.length;
+ }
+ }
+
+ int get hashCode => computeHashCode(charOffset, info, value);
+}
+
+/// A pair of tokens marking the beginning and the end of a span. Use for error
+/// reporting.
+class TokenPair implements Spannable {
+ final Token begin;
+ final Token end;
+
+ TokenPair(this.begin, this.end);
+}
+
+/**
+ * A [SymbolToken] represents the symbol in its precendence info.
+ * Also used for end of file with EOF_INFO.
+ */
+class SymbolToken extends Token {
+
+ final PrecedenceInfo info;
+
+ SymbolToken(this.info, int charOffset) : super(charOffset);
+
+ String get value => info.value;
+
+ String get stringValue => info.value;
+
+ bool isIdentifier() => false;
+
+ String toString() => "SymbolToken($value)";
+}
+
+/**
+ * A [BeginGroupToken] represents a symbol that may be the beginning of
+ * a pair of brackets, i.e., ( { [ < or ${
+ * The [endGroup] token points to the matching closing bracked in case
+ * it can be identified during scanning.
+ */
+class BeginGroupToken extends SymbolToken {
+ Token endGroup;
+
+ BeginGroupToken(PrecedenceInfo info, int charOffset)
+ : super(info, charOffset);
+}
+
+/**
+ * A keyword token.
+ */
+class KeywordToken extends Token {
+ final Keyword keyword;
+
+ KeywordToken(this.keyword, int charOffset) : super(charOffset);
+
+ PrecedenceInfo get info => keyword.info;
+
+ String get value => keyword.syntax;
+
+ String get stringValue => keyword.syntax;
+
+ bool isIdentifier() => keyword.isPseudo || keyword.isBuiltIn;
+
+ String toString() => "KeywordToken($value)";
+}
+
+abstract class ErrorToken extends Token {
+ ErrorToken(int charOffset)
+ : super(charOffset);
+
+ PrecedenceInfo get info => Precedence.BAD_INPUT_INFO;
+
+ String get value {
+ throw new SpannableAssertionFailure(this, assertionMessage);
+ }
+
+ String get stringValue => null;
+
+ bool isIdentifier() => false;
+
+ String get assertionMessage;
+}
+
+class BadInputToken extends ErrorToken {
+ final int character;
+
+ BadInputToken(this.character, int charOffset)
+ : super(charOffset);
+
+ String toString() => "BadInputToken($character)";
+
+ String get assertionMessage {
+ return 'Character U+${character.toRadixString(16)} not allowed here.';
+ }
+}
+
+class UnterminatedToken extends ErrorToken {
+ final String start;
+ final int endOffset;
+
+ UnterminatedToken(this.start, int charOffset, this.endOffset)
+ : super(charOffset);
+
+ String toString() => "UnterminatedToken($start)";
+
+ String get assertionMessage => "'$start' isn't terminated.";
+
+ int get charCount => endOffset - charOffset;
+}
+
+class UnmatchedToken extends ErrorToken {
+ final BeginGroupToken begin;
+
+ UnmatchedToken(BeginGroupToken begin)
+ : this.begin = begin,
+ super(begin.charOffset);
+
+ String toString() => "UnmatchedToken(${begin.value})";
+
+ String get assertionMessage => "'$begin' isn't closed.";
+}
+
+/**
+ * A String-valued token. Represents identifiers, string literals,
+ * number literals, comments, and error tokens, using the corresponding
+ * precedence info.
+ */
+class StringToken extends Token {
+ /**
+ * The length threshold above which substring tokens are computed lazily.
+ *
+ * For string tokens that are substrings of the program source, the actual
+ * substring extraction is performed lazily. This is beneficial because
+ * not all scanned code is actually used. For unused parts, the substrings
+ * are never computed and allocated.
+ */
+ static const int LAZY_THRESHOLD = 4;
+
+ var /* String | LazySubtring */ valueOrLazySubstring;
+
+ final PrecedenceInfo info;
+
+ /**
+ * Creates a non-lazy string token. If [canonicalize] is true, the string
+ * is canonicalized before the token is created.
+ */
+ StringToken.fromString(this.info, String value, int charOffset,
+ {bool canonicalize : false})
+ : valueOrLazySubstring = canonicalizedString(value, canonicalize),
+ super(charOffset);
+
+ /**
+ * Creates a lazy string token. If [canonicalize] is true, the string
+ * is canonicalized before the token is created.
+ */
+ StringToken.fromSubstring(this.info, String data, int start, int end,
+ int charOffset, {bool canonicalize : false})
+ : super(charOffset) {
+ int length = end - start;
+ if (length <= LAZY_THRESHOLD) {
+ valueOrLazySubstring = canonicalizedString(data.substring(start, end),
+ canonicalize);
+ } else {
+ valueOrLazySubstring =
+ new LazySubstring(data, start, length, canonicalize);
+ }
+ }
+
+ /**
+ * Creates a lazy string token. If [asciiOnly] is false, the byte array
+ * is passed through a UTF-8 decoder.
+ */
+ StringToken.fromUtf8Bytes(this.info, List<int> data, int start, int end,
+ bool asciiOnly, int charOffset)
+ : super(charOffset) {
+ int length = end - start;
+ if (length <= LAZY_THRESHOLD) {
+ valueOrLazySubstring = decodeUtf8(data, start, end, asciiOnly);
+ } else {
+ valueOrLazySubstring = new LazySubstring(data, start, length, asciiOnly);
+ }
+ }
+
+ String get value {
+ if (valueOrLazySubstring is String) {
+ return valueOrLazySubstring;
+ } else {
+ assert(valueOrLazySubstring is LazySubstring);
+ var data = valueOrLazySubstring.data;
+ int start = valueOrLazySubstring.start;
+ int end = start + valueOrLazySubstring.length;
+ if (data is String) {
+ valueOrLazySubstring = canonicalizedString(
+ data.substring(start, end), valueOrLazySubstring.boolValue);
+ } else {
+ valueOrLazySubstring = decodeUtf8(
+ data, start, end, valueOrLazySubstring.boolValue);
+ }
+ return valueOrLazySubstring;
+ }
+ }
+
+ /// See [Token.stringValue] for an explanation.
+ String get stringValue => null;
+
+ bool isIdentifier() => identical(kind, Tokens.IDENTIFIER_TOKEN);
+
+ String toString() => "StringToken($value)";
+
+ static final HashSet<String> canonicalizedSubstrings =
+ new HashSet<String>();
+
+ static String canonicalizedString(String s, bool canonicalize) {
+ if (!canonicalize) return s;
+ var result = canonicalizedSubstrings.lookup(s);
+ if (result != null) return result;
+ canonicalizedSubstrings.add(s);
+ return s;
+ }
+
+ static String decodeUtf8(List<int> data, int start, int end, bool asciiOnly) {
+ var s;
+ if (asciiOnly) {
+ s = new String.fromCharCodes(data, start, end);
+ } else {
+ s = UTF8.decoder.convert(data, start, end);
+ }
+ return canonicalizedString(s, true);
+ }
+}
+
+/**
+ * This class represents the necessary information to compute a substring
+ * lazily. The substring can either originate from a string or from
+ * a [:List<int>:] of UTF-8 bytes.
+ */
+abstract class LazySubstring {
+ /** The original data, either a string or a List<int> */
+ get data;
+
+ int get start;
+ int get length;
+
+ /**
+ * If this substring is based on a String, the [boolValue] indicates wheter
+ * the resulting substring should be canonicalized.
+ *
+ * For substrings based on a byte array, the [boolValue] is true if the
+ * array only holds ASCII characters. The resulting substring will be
+ * canonicalized after decoding.
+ */
+ bool get boolValue;
+
+ LazySubstring.internal();
+
+ factory LazySubstring(data, int start, int length, bool b) {
+ // See comment on [CompactLazySubstring].
+ if (start < 0x100000 && length < 0x200) {
+ int fields = (start << 9);
+ fields = fields | length;
+ fields = fields << 1;
+ if (b) fields |= 1;
+ return new CompactLazySubstring(data, fields);
+ } else {
+ return new FullLazySubstring(data, start, length, b);
+ }
+ }
+}
+
+/**
+ * This class encodes [start], [length] and [boolValue] in a single
+ * 30 bit integer. It uses 20 bits for [start], which covers source files
+ * of 1MB. [length] has 9 bits, which covers 512 characters.
+ *
+ * The file html_dart2js.dart is currently around 1MB.
+ */
+class CompactLazySubstring extends LazySubstring {
+ final data;
+ final int fields;
+
+ CompactLazySubstring(this.data, this.fields) : super.internal();
+
+ int get start => fields >> 10;
+ int get length => (fields >> 1) & 0x1ff;
+ bool get boolValue => (fields & 1) == 1;
+}
+
+class FullLazySubstring extends LazySubstring {
+ final data;
+ final int start;
+ final int length;
+ final bool boolValue;
+ FullLazySubstring(this.data, this.start, this.length, this.boolValue)
+ : super.internal();
+}
+
+bool isUserDefinableOperator(String value) {
+ return
+ isBinaryOperator(value) ||
+ isMinusOperator(value) ||
+ isTernaryOperator(value) ||
+ isUnaryOperator(value);
+}
+
+bool isUnaryOperator(String value) => identical(value, '~');
+
+bool isBinaryOperator(String value) {
+ return
+ (identical(value, '==')) ||
+ (identical(value, '[]')) ||
+ (identical(value, '*')) ||
+ (identical(value, '/')) ||
+ (identical(value, '%')) ||
+ (identical(value, '~/')) ||
+ (identical(value, '+')) ||
+ (identical(value, '<<')) ||
+ (identical(value, '>>')) ||
+ (identical(value, '>=')) ||
+ (identical(value, '>')) ||
+ (identical(value, '<=')) ||
+ (identical(value, '<')) ||
+ (identical(value, '&')) ||
+ (identical(value, '^')) ||
+ (identical(value, '|'));
+}
+
+bool isTernaryOperator(String value) => identical(value, '[]=');
+
+bool isMinusOperator(String value) => identical(value, '-');
diff --git a/pkg/compiler/lib/src/tokens/token_constants.dart b/pkg/compiler/lib/src/tokens/token_constants.dart
new file mode 100644
index 0000000..c1078f0
--- /dev/null
+++ b/pkg/compiler/lib/src/tokens/token_constants.dart
@@ -0,0 +1,82 @@
+// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library dart2js.tokens.constants;
+
+import '../util/characters.dart';
+
+const int EOF_TOKEN = 0;
+
+const int KEYWORD_TOKEN = $k;
+const int IDENTIFIER_TOKEN = $a;
+const int BAD_INPUT_TOKEN = $X;
+const int DOUBLE_TOKEN = $d;
+const int INT_TOKEN = $i;
+const int HEXADECIMAL_TOKEN = $x;
+const int STRING_TOKEN = $SQ;
+
+const int AMPERSAND_TOKEN = $AMPERSAND;
+const int BACKPING_TOKEN = $BACKPING;
+const int BACKSLASH_TOKEN = $BACKSLASH;
+const int BANG_TOKEN = $BANG;
+const int BAR_TOKEN = $BAR;
+const int COLON_TOKEN = $COLON;
+const int COMMA_TOKEN = $COMMA;
+const int EQ_TOKEN = $EQ;
+const int GT_TOKEN = $GT;
+const int HASH_TOKEN = $HASH;
+const int OPEN_CURLY_BRACKET_TOKEN = $OPEN_CURLY_BRACKET;
+const int OPEN_SQUARE_BRACKET_TOKEN = $OPEN_SQUARE_BRACKET;
+const int OPEN_PAREN_TOKEN = $OPEN_PAREN;
+const int LT_TOKEN = $LT;
+const int MINUS_TOKEN = $MINUS;
+const int PERIOD_TOKEN = $PERIOD;
+const int PLUS_TOKEN = $PLUS;
+const int QUESTION_TOKEN = $QUESTION;
+const int AT_TOKEN = $AT;
+const int CLOSE_CURLY_BRACKET_TOKEN = $CLOSE_CURLY_BRACKET;
+const int CLOSE_SQUARE_BRACKET_TOKEN = $CLOSE_SQUARE_BRACKET;
+const int CLOSE_PAREN_TOKEN = $CLOSE_PAREN;
+const int SEMICOLON_TOKEN = $SEMICOLON;
+const int SLASH_TOKEN = $SLASH;
+const int TILDE_TOKEN = $TILDE;
+const int STAR_TOKEN = $STAR;
+const int PERCENT_TOKEN = $PERCENT;
+const int CARET_TOKEN = $CARET;
+
+const int STRING_INTERPOLATION_TOKEN = 128;
+const int LT_EQ_TOKEN = STRING_INTERPOLATION_TOKEN + 1;
+const int FUNCTION_TOKEN = LT_EQ_TOKEN + 1;
+const int SLASH_EQ_TOKEN = FUNCTION_TOKEN + 1;
+const int PERIOD_PERIOD_PERIOD_TOKEN = SLASH_EQ_TOKEN + 1;
+const int PERIOD_PERIOD_TOKEN = PERIOD_PERIOD_PERIOD_TOKEN + 1;
+const int EQ_EQ_EQ_TOKEN = PERIOD_PERIOD_TOKEN + 1;
+const int EQ_EQ_TOKEN = EQ_EQ_EQ_TOKEN + 1;
+const int LT_LT_EQ_TOKEN = EQ_EQ_TOKEN + 1;
+const int LT_LT_TOKEN = LT_LT_EQ_TOKEN + 1;
+const int GT_EQ_TOKEN = LT_LT_TOKEN + 1;
+const int GT_GT_EQ_TOKEN = GT_EQ_TOKEN + 1;
+const int INDEX_EQ_TOKEN = GT_GT_EQ_TOKEN + 1;
+const int INDEX_TOKEN = INDEX_EQ_TOKEN + 1;
+const int BANG_EQ_EQ_TOKEN = INDEX_TOKEN + 1;
+const int BANG_EQ_TOKEN = BANG_EQ_EQ_TOKEN + 1;
+const int AMPERSAND_AMPERSAND_TOKEN = BANG_EQ_TOKEN + 1;
+const int AMPERSAND_EQ_TOKEN = AMPERSAND_AMPERSAND_TOKEN + 1;
+const int BAR_BAR_TOKEN = AMPERSAND_EQ_TOKEN + 1;
+const int BAR_EQ_TOKEN = BAR_BAR_TOKEN + 1;
+const int STAR_EQ_TOKEN = BAR_EQ_TOKEN + 1;
+const int PLUS_PLUS_TOKEN = STAR_EQ_TOKEN + 1;
+const int PLUS_EQ_TOKEN = PLUS_PLUS_TOKEN + 1;
+const int MINUS_MINUS_TOKEN = PLUS_EQ_TOKEN + 1;
+const int MINUS_EQ_TOKEN = MINUS_MINUS_TOKEN + 1;
+const int TILDE_SLASH_EQ_TOKEN = MINUS_EQ_TOKEN + 1;
+const int TILDE_SLASH_TOKEN = TILDE_SLASH_EQ_TOKEN + 1;
+const int PERCENT_EQ_TOKEN = TILDE_SLASH_TOKEN + 1;
+const int GT_GT_TOKEN = PERCENT_EQ_TOKEN + 1;
+const int CARET_EQ_TOKEN = GT_GT_TOKEN + 1;
+const int COMMENT_TOKEN = CARET_EQ_TOKEN + 1;
+const int STRING_INTERPOLATION_IDENTIFIER_TOKEN = COMMENT_TOKEN + 1;
+const int QUESTION_PERIOD_TOKEN = STRING_INTERPOLATION_IDENTIFIER_TOKEN + 1;
+const int QUESTION_QUESTION_TOKEN = QUESTION_PERIOD_TOKEN + 1;
+const int QUESTION_QUESTION_EQ_TOKEN = QUESTION_QUESTION_TOKEN + 1;
diff --git a/pkg/compiler/lib/src/scanner/token_map.dart b/pkg/compiler/lib/src/tokens/token_map.dart
similarity index 97%
rename from pkg/compiler/lib/src/scanner/token_map.dart
rename to pkg/compiler/lib/src/tokens/token_map.dart
index 8e4c53e..55b4d30 100644
--- a/pkg/compiler/lib/src/scanner/token_map.dart
+++ b/pkg/compiler/lib/src/tokens/token_map.dart
@@ -4,7 +4,7 @@
library dart2js.tokens.token_map;
-import 'scannerlib.dart' show
+import 'token.dart' show
Token;
/**
diff --git a/pkg/compiler/lib/src/tree/nodes.dart b/pkg/compiler/lib/src/tree/nodes.dart
index e239366..56f1f26 100644
--- a/pkg/compiler/lib/src/tree/nodes.dart
+++ b/pkg/compiler/lib/src/tree/nodes.dart
@@ -852,7 +852,9 @@
int get value {
try {
Token valueToken = token;
- if (identical(valueToken.kind, PLUS_TOKEN)) valueToken = valueToken.next;
+ if (identical(valueToken.kind, Tokens.PLUS_TOKEN)) {
+ valueToken = valueToken.next;
+ }
return int.parse(valueToken.value);
} on FormatException catch (ex) {
(this.handler)(token, ex);
@@ -871,7 +873,9 @@
double get value {
try {
Token valueToken = token;
- if (identical(valueToken.kind, PLUS_TOKEN)) valueToken = valueToken.next;
+ if (identical(valueToken.kind, Tokens.PLUS_TOKEN)) {
+ valueToken = valueToken.next;
+ }
return double.parse(valueToken.value);
} on FormatException catch (ex) {
(this.handler)(token, ex);
@@ -1087,7 +1091,7 @@
bool get hasExpression => expression != null;
/// `true` if this return is of the form `=> e;`.
- bool get isArrowBody => beginToken.info == FUNCTION_INFO;
+ bool get isArrowBody => beginToken.info == Precedence.FUNCTION_INFO;
accept(Visitor visitor) => visitor.visitReturn(this);
diff --git a/pkg/compiler/lib/src/tree/tree.dart b/pkg/compiler/lib/src/tree/tree.dart
index 67993f2..d4331b5 100644
--- a/pkg/compiler/lib/src/tree/tree.dart
+++ b/pkg/compiler/lib/src/tree/tree.dart
@@ -9,7 +9,15 @@
import '../diagnostics/spannable.dart' show
Spannable,
SpannableAssertionFailure;
-import '../scanner/scannerlib.dart';
+import '../tokens/precedence_constants.dart' as Precedence show
+ FUNCTION_INFO;
+import '../tokens/token.dart' show
+ BeginGroupToken,
+ Token;
+import '../tokens/token_constants.dart' as Tokens show
+ IDENTIFIER_TOKEN,
+ KEYWORD_TOKEN,
+ PLUS_TOKEN;
import '../util/util.dart';
import '../util/characters.dart';
diff --git a/pkg/compiler/lib/src/tree/unparser.dart b/pkg/compiler/lib/src/tree/unparser.dart
index b7d3109..fd00ba3 100644
--- a/pkg/compiler/lib/src/tree/unparser.dart
+++ b/pkg/compiler/lib/src/tree/unparser.dart
@@ -34,8 +34,8 @@
void addToken(Token token) {
if (token == null) return;
write(token.value);
- if (identical(token.kind, KEYWORD_TOKEN)
- || identical(token.kind, IDENTIFIER_TOKEN)) {
+ if (identical(token.kind, Tokens.KEYWORD_TOKEN)
+ || identical(token.kind, Tokens.IDENTIFIER_TOKEN)) {
write(' ');
}
}
@@ -209,7 +209,7 @@
} else {
visit(send.receiver);
Identifier identifier = send.selector.asIdentifier();
- if (identical(identifier.token.kind, KEYWORD_TOKEN)) {
+ if (identical(identifier.token.kind, Tokens.KEYWORD_TOKEN)) {
write(' ');
} else if (identifier.source == 'negate') {
// TODO(ahe): Remove special case for negate.
@@ -292,13 +292,13 @@
visitLiteralDouble(LiteralDouble node) {
write(node.token.value);
// -Lit is represented as a send.
- if (node.token.kind == PLUS_TOKEN) write(node.token.next.value);
+ if (node.token.kind == Tokens.PLUS_TOKEN) write(node.token.next.value);
}
visitLiteralInt(LiteralInt node) {
write(node.token.value);
// -Lit is represented as a send.
- if (node.token.kind == PLUS_TOKEN) write(node.token.next.value);
+ if (node.token.kind == Tokens.PLUS_TOKEN) write(node.token.next.value);
}
visitLiteralString(LiteralString node) {
diff --git a/pkg/compiler/lib/src/tree_ir/tree_ir_builder.dart b/pkg/compiler/lib/src/tree_ir/tree_ir_builder.dart
index 5e19e04..89b8b19 100644
--- a/pkg/compiler/lib/src/tree_ir/tree_ir_builder.dart
+++ b/pkg/compiler/lib/src/tree_ir/tree_ir_builder.dart
@@ -11,6 +11,7 @@
import '../elements/elements.dart';
import '../cps_ir/cps_ir_nodes.dart' as cps_ir;
import 'tree_ir_nodes.dart';
+import '../constants/values.dart';
typedef Statement NodeCallback(Statement next);
@@ -277,12 +278,6 @@
return prim.accept(this);
}
- /// Translates a condition to a tree expression.
- Expression translateCondition(cps_ir.Condition condition) {
- cps_ir.IsTrue isTrue = condition;
- return getVariableUse(isTrue.value);
- }
-
/************************ INTERIOR EXPRESSIONS ************************/
//
// Visit methods for interior expressions must return a function:
@@ -500,8 +495,20 @@
}
}
+ /// Translates a branch condition to a tree expression.
+ Expression translateCondition(cps_ir.Branch branch) {
+ Expression value = getVariableUse(branch.condition);
+ if (branch.isStrictCheck) {
+ return new ApplyBuiltinOperator(
+ BuiltinOperator.StrictEq,
+ <Expression>[value, new Constant(new TrueConstantValue())]);
+ } else {
+ return value;
+ }
+ }
+
Statement visitBranch(cps_ir.Branch node) {
- Expression condition = translateCondition(node.condition);
+ Expression condition = translateCondition(node);
Statement thenStatement, elseStatement;
cps_ir.Continuation cont = node.trueContinuation.definition;
assert(cont.parameters.isEmpty);
@@ -680,6 +687,5 @@
visitParameter(cps_ir.Parameter node) => unexpectedNode(node);
visitContinuation(cps_ir.Continuation node) => unexpectedNode(node);
visitMutableVariable(cps_ir.MutableVariable node) => unexpectedNode(node);
- visitIsTrue(cps_ir.IsTrue node) => unexpectedNode(node);
}
diff --git a/pkg/compiler/lib/src/types/type_mask.dart b/pkg/compiler/lib/src/types/type_mask.dart
index 9ea82ab..65cf596 100644
--- a/pkg/compiler/lib/src/types/type_mask.dart
+++ b/pkg/compiler/lib/src/types/type_mask.dart
@@ -4,12 +4,78 @@
part of types;
+/// An implementation of a [UniverseReceiverMaskSet] that is consists if an only
+/// increasing set of [TypeMask]s, that is, once a mask is added it cannot be
+/// removed.
+class IncreasingTypeMaskSet extends UniverseReceiverMaskSet {
+ bool isAll = false;
+ Set<TypeMask> _masks;
+
+ @override
+ bool applies(Element element, Selector selector, ClassWorld world) {
+ if (isAll) return true;
+ if (_masks == null) return false;
+ for (TypeMask mask in _masks) {
+ if (mask.canHit(element, selector, world)) return true;
+ }
+ return false;
+ }
+
+ @override
+ bool needsNoSuchMethodHandling(Selector selector, ClassWorld world) {
+ if (isAll) {
+ TypeMask mask =
+ new TypeMask.subclass(world.objectClass, world);
+ return mask.needsNoSuchMethodHandling(selector, world);
+ }
+ for (TypeMask mask in _masks) {
+ if (mask.needsNoSuchMethodHandling(selector, world)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @override
+ bool addReceiverMask(TypeMask mask) {
+ if (isAll) return false;
+ if (mask == null) {
+ isAll = true;
+ _masks = null;
+ return true;
+ }
+ if (_masks == null) {
+ _masks = new Setlet<TypeMask>();
+ }
+ return _masks.add(mask);
+ }
+
+ String toString() {
+ if (isAll) {
+ return '<all>';
+ } else if (_masks != null) {
+ return '$_masks';
+ } else {
+ return '<none>';
+ }
+ }
+}
+
+class TypeMaskStrategy implements ReceiverMaskStrategy {
+ const TypeMaskStrategy();
+
+ @override
+ UniverseReceiverMaskSet createReceiverMaskSet(Selector selector) {
+ return new IncreasingTypeMaskSet();
+ }
+}
+
/**
* A type mask represents a set of contained classes, but the
* operations on it are not guaranteed to be precise and they may
* yield conservative answers that contain too many classes.
*/
-abstract class TypeMask {
+abstract class TypeMask implements ReceiverMask {
factory TypeMask(ClassElement base,
int kind,
bool isNullable,
diff --git a/pkg/compiler/lib/src/universe/function_set.dart b/pkg/compiler/lib/src/universe/function_set.dart
index 0b4b0bc..5f8dedd 100644
--- a/pkg/compiler/lib/src/universe/function_set.dart
+++ b/pkg/compiler/lib/src/universe/function_set.dart
@@ -13,6 +13,8 @@
new Map<String, FunctionSetNode>();
FunctionSet(this.compiler);
+ ClassWorld get classWorld => compiler.world;
+
FunctionSetNode newNode(String name)
=> new FunctionSetNode(name);
@@ -44,30 +46,50 @@
: false;
}
- /**
- * Returns an object that allows iterating over all the functions
- * that may be invoked with the given [selector].
- */
+ /// Returns an object that allows iterating over all the functions
+ /// that may be invoked with the given [selector].
Iterable<Element> filter(Selector selector, TypeMask mask) {
return query(selector, mask).functions;
}
+ /// Returns the mask for the potential receivers of a dynamic call to
+ /// [selector] on [mask].
+ ///
+ /// This will reduce the set of classes in [mask] to a [TypeMask] of the set
+ /// of classes that actually implement the selected member or implement the
+ /// handling 'noSuchMethod' where the selected member is unimplemented.
TypeMask receiverType(Selector selector, TypeMask mask) {
- return query(selector, mask).computeMask(compiler.world);
+ return query(selector, mask).computeMask(classWorld);
}
+ SelectorMask _createSelectorMask(
+ Selector selector, TypeMask mask, ClassWorld classWorld) {
+ return mask != null
+ ? new SelectorMask(selector, mask)
+ : new SelectorMask(selector,
+ new TypeMask.subclass(classWorld.objectClass, classWorld));
+ }
+
+ /// Returns the set of functions that can be the target of a call to
+ /// [selector] on a receiver of type [mask] including 'noSuchMethod' methods
+ /// where applicable.
FunctionSetQuery query(Selector selector, TypeMask mask) {
String name = selector.name;
+ SelectorMask selectorMask = _createSelectorMask(selector, mask, classWorld);
+ SelectorMask noSuchMethodMask =
+ new SelectorMask(Selectors.noSuchMethod_, selectorMask.mask);
FunctionSetNode node = nodes[name];
FunctionSetNode noSuchMethods = nodes[Identifiers.noSuchMethod_];
if (node != null) {
- return node.query(selector, mask, compiler, noSuchMethods);
+ return node.query(
+ selectorMask, classWorld, noSuchMethods, noSuchMethodMask);
}
// If there is no method that matches [selector] we know we can
// only hit [:noSuchMethod:].
- if (noSuchMethods == null) return const FunctionSetQuery(const <Element>[]);
- return noSuchMethods.query(
- Selectors.noSuchMethod_, mask, compiler, null);
+ if (noSuchMethods == null) {
+ return const EmptyFunctionSetQuery();
+ }
+ return noSuchMethods.query(noSuchMethodMask, classWorld);
}
void forEach(Function action) {
@@ -77,6 +99,8 @@
}
}
+/// A selector/mask pair representing the dynamic invocation of [selector] on
+/// a receiver of type [mask].
class SelectorMask {
final Selector selector;
final TypeMask mask;
@@ -86,16 +110,21 @@
: this.selector = selector,
this.mask = mask,
this.hashCode =
- Hashing.mixHashCodeBits(selector.hashCode, mask.hashCode);
+ Hashing.mixHashCodeBits(selector.hashCode, mask.hashCode) {
+ assert(mask != null);
+ }
String get name => selector.name;
bool applies(Element element, ClassWorld classWorld) {
if (!selector.appliesUnnamed(element, classWorld)) return false;
- if (mask == null) return true;
return mask.canHit(element, selector, classWorld);
}
+ bool needsNoSuchMethodHandling(ClassWorld classWorld) {
+ return mask.needsNoSuchMethodHandling(selector, classWorld);
+ }
+
bool operator ==(other) {
if (identical(this, other)) return true;
return selector == other.selector && mask == other.mask;
@@ -104,6 +133,8 @@
String toString() => '($selector,$mask)';
}
+/// A node in the [FunctionSet] caching all [FunctionSetQuery] object for
+/// selectors with the same [name].
class FunctionSetNode {
final String name;
final Map<SelectorMask, FunctionSetQuery> cache =
@@ -164,24 +195,13 @@
elements.forEach(action);
}
- TypeMask getNonNullTypeMaskOfSelector(TypeMask mask, ClassWorld classWorld) {
- // TODO(ngeoffray): We should probably change untyped selector
- // to always be a subclass of Object.
- return mask != null
- ? mask
- : new TypeMask.subclass(classWorld.objectClass, classWorld);
- }
-
- // TODO(johnniwinther): Use [SelectorMask] instead of [Selector] and
- // [TypeMask].
- FunctionSetQuery query(Selector selector,
- TypeMask mask,
- Compiler compiler,
- FunctionSetNode noSuchMethods) {
- mask = getNonNullTypeMaskOfSelector(mask, compiler.world);
- SelectorMask selectorMask = new SelectorMask(selector, mask);
- ClassWorld classWorld = compiler.world;
- assert(selector.name == name);
+ /// Returns the set of functions that can be the target of [selectorMask]
+ /// including no such method handling where applicable.
+ FunctionSetQuery query(SelectorMask selectorMask,
+ ClassWorld classWorld,
+ [FunctionSetNode noSuchMethods,
+ SelectorMask noSuchMethodMask]) {
+ assert(selectorMask.name == name);
FunctionSetQuery result = cache[selectorMask];
if (result != null) return result;
@@ -201,13 +221,10 @@
// If we cannot ensure a method will be found at runtime, we also
// add [noSuchMethod] implementations that apply to [mask] as
// potential targets.
- if (noSuchMethods != null
- && mask.needsNoSuchMethodHandling(selector, classWorld)) {
- FunctionSetQuery noSuchMethodQuery = noSuchMethods.query(
- Selectors.noSuchMethod_,
- mask,
- compiler,
- null);
+ if (noSuchMethods != null &&
+ selectorMask.needsNoSuchMethodHandling(classWorld)) {
+ FunctionSetQuery noSuchMethodQuery =
+ noSuchMethods.query(noSuchMethodMask, classWorld);
if (!noSuchMethodQuery.functions.isEmpty) {
if (functions == null) {
functions = new Setlet<Element>.from(noSuchMethodQuery.functions);
@@ -217,31 +234,43 @@
}
}
cache[selectorMask] = result = (functions != null)
- ? newQuery(functions, selector, mask, compiler)
- : const FunctionSetQuery(const <Element>[]);
+ ? new FullFunctionSetQuery(functions)
+ : const EmptyFunctionSetQuery();
return result;
}
-
- FunctionSetQuery newQuery(Iterable<Element> functions,
- Selector selector,
- TypeMask mask,
- Compiler compiler) {
- return new FullFunctionSetQuery(functions);
- }
}
-class FunctionSetQuery {
- final Iterable<Element> functions;
+/// A set of functions that are the potential targets of all call sites sharing
+/// the same receiver mask and selector.
+abstract class FunctionSetQuery {
+ const FunctionSetQuery();
+
+ /// Compute the type of all potential receivers of this function set.
+ TypeMask computeMask(ClassWorld classWorld);
+
+ /// Returns all potential targets of this function set.
+ Iterable<Element> get functions;
+}
+
+class EmptyFunctionSetQuery implements FunctionSetQuery {
+ const EmptyFunctionSetQuery();
+
+ @override
TypeMask computeMask(ClassWorld classWorld) => const TypeMask.nonNullEmpty();
- const FunctionSetQuery(this.functions);
+
+ @override
+ Iterable<Element> get functions => const <Element>[];
}
-class FullFunctionSetQuery extends FunctionSetQuery {
+class FullFunctionSetQuery implements FunctionSetQuery {
+ @override
+ final Iterable<Element> functions;
+
TypeMask _mask;
- /**
- * Compute the type of all potential receivers of this function set.
- */
+ FullFunctionSetQuery(this.functions);
+
+ @override
TypeMask computeMask(ClassWorld classWorld) {
assert(classWorld.hasAnyStrictSubclass(classWorld.objectClass));
if (_mask != null) return _mask;
@@ -259,6 +288,4 @@
}),
classWorld);
}
-
- FullFunctionSetQuery(functions) : super(functions);
}
diff --git a/pkg/compiler/lib/src/universe/universe.dart b/pkg/compiler/lib/src/universe/universe.dart
index c5da864..4530400 100644
--- a/pkg/compiler/lib/src/universe/universe.dart
+++ b/pkg/compiler/lib/src/universe/universe.dart
@@ -18,8 +18,8 @@
SpannableAssertionFailure;
import '../elements/elements.dart';
import '../dart_types.dart';
-import '../types/types.dart';
import '../tree/tree.dart';
+import '../types/types.dart';
import '../util/util.dart';
import '../world.dart' show
ClassWorld,
@@ -30,7 +30,7 @@
class UniverseSelector {
final Selector selector;
- final TypeMask mask;
+ final ReceiverMask mask;
UniverseSelector(this.selector, this.mask);
@@ -42,57 +42,56 @@
String toString() => '$selector,$mask';
}
-abstract class TypeMaskSet {
+/// A potential receiver for a dynamic call site.
+abstract class ReceiverMask {
+ /// Returns whether [element] is a potential target when being
+ /// invoked on this receiver mask. [selector] is used to ensure library
+ /// privacy is taken into account.
+ bool canHit(Element element, Selector selector, ClassWorld classWorld);
+}
+
+/// A set of potential receivers for the dynamic call sites of the same
+/// selector.
+///
+/// For instance for these calls
+///
+/// new A().foo(a, b);
+/// new B().foo(0, 42);
+///
+/// the receiver mask set for dynamic calls to 'foo' with to positional
+/// arguments will contain receiver masks abstracting `new A()` and `new B()`.
+abstract class ReceiverMaskSet {
+ /// Returns `true` if [selector] applies to any of the potential receivers
+ /// in this set given the closed [world].
bool applies(Element element, Selector selector, ClassWorld world);
- Iterable<TypeMask> get masks;
+
+ /// Returns `true` if any potential receivers in this set given the closed
+ /// [world] have no implementation matching [selector].
+ ///
+ /// For instance for this code snippet
+ ///
+ /// class A {}
+ /// class B { foo() {} }
+ /// m(b) => (b ? new A() : new B()).foo();
+ ///
+ /// the potential receiver `new A()` have no implementation of `foo` and thus
+ /// needs to handle the call though its `noSuchMethod` handler.
+ bool needsNoSuchMethodHandling(Selector selector, ClassWorld world);
}
-/// An implementation of a [TypeMaskSet] that is only increasing, that is, once
-/// a mask is added it cannot be removed.
-class IncreasingTypeMaskSet extends TypeMaskSet {
- bool isAll = false;
- Set<TypeMask> _masks;
-
- bool applies(Element element, Selector selector, ClassWorld world) {
- if (isAll) return true;
- if (_masks == null) return false;
- for (TypeMask mask in _masks) {
- if (mask.canHit(element, selector, world)) return true;
- }
- return false;
- }
-
- bool add(TypeMask mask) {
- if (isAll) return false;
- if (mask == null) {
- isAll = true;
- _masks = null;
- return true;
- }
- if (_masks == null) {
- _masks = new Setlet<TypeMask>();
- }
- return _masks.add(mask);
- }
-
- Iterable<TypeMask> get masks {
- if (isAll) return const [null];
- if (_masks == null) return const [];
- return _masks;
- }
-
- String toString() {
- if (isAll) {
- return '<all>';
- } else if (_masks != null) {
- return '$_masks';
- } else {
- return '<none>';
- }
- }
+/// A mutable [ReceiverMaskSet] used in [Universe].
+abstract class UniverseReceiverMaskSet extends ReceiverMaskSet {
+ /// Adds [mask] to this set of potential receivers. Return `true` if the
+ /// set expanded due to the new mask.
+ bool addReceiverMask(ReceiverMask mask);
}
-
+/// Strategy for computing potential receivers of dynamic call sites.
+abstract class ReceiverMaskStrategy {
+ /// Create a [UniverseReceiverMaskSet] to represent the potential receiver for
+ /// a dynamic call site with [selector].
+ UniverseReceiverMaskSet createReceiverMaskSet(Selector selector);
+}
class Universe {
/// The set of all directly instantiated classes, that is, classes with a
@@ -131,12 +130,12 @@
new Set<FunctionElement>();
final Set<FunctionElement> methodsNeedingSuperGetter =
new Set<FunctionElement>();
- final Map<String, Map<Selector, TypeMaskSet>> _invokedNames =
- <String, Map<Selector, TypeMaskSet>>{};
- final Map<String, Map<Selector, TypeMaskSet>> _invokedGetters =
- <String, Map<Selector, TypeMaskSet>>{};
- final Map<String, Map<Selector, TypeMaskSet>> _invokedSetters =
- <String, Map<Selector, TypeMaskSet>>{};
+ final Map<String, Map<Selector, ReceiverMaskSet>> _invokedNames =
+ <String, Map<Selector, ReceiverMaskSet>>{};
+ final Map<String, Map<Selector, ReceiverMaskSet>> _invokedGetters =
+ <String, Map<Selector, ReceiverMaskSet>>{};
+ final Map<String, Map<Selector, ReceiverMaskSet>> _invokedSetters =
+ <String, Map<Selector, ReceiverMaskSet>>{};
/**
* Fields accessed. Currently only the codegen knows this
@@ -178,6 +177,10 @@
*/
final Set<Element> closurizedMembers = new Set<Element>();
+ final ReceiverMaskStrategy receiverMaskStrategy;
+
+ Universe(this.receiverMaskStrategy);
+
/// All directly instantiated classes, that is, classes with a generative
/// constructor that has been called directly and not only through a
/// super-call.
@@ -239,13 +242,13 @@
});
}
- bool _hasMatchingSelector(Map<Selector, TypeMaskSet> selectors,
+ bool _hasMatchingSelector(Map<Selector, ReceiverMaskSet> selectors,
Element member,
World world) {
if (selectors == null) return false;
for (Selector selector in selectors.keys) {
if (selector.appliesUnnamed(member, world)) {
- TypeMaskSet masks = selectors[selector];
+ ReceiverMaskSet masks = selectors[selector];
if (masks.applies(member, selector, world)) {
return true;
}
@@ -280,46 +283,47 @@
bool _registerNewSelector(
UniverseSelector universeSelector,
- Map<String, Map<Selector, TypeMaskSet>> selectorMap) {
+ Map<String, Map<Selector, ReceiverMaskSet>> selectorMap) {
Selector selector = universeSelector.selector;
String name = selector.name;
- TypeMask mask = universeSelector.mask;
- Map<Selector, TypeMaskSet> selectors = selectorMap.putIfAbsent(
- name, () => new Maplet<Selector, TypeMaskSet>());
- IncreasingTypeMaskSet masks = selectors.putIfAbsent(
- selector, () => new IncreasingTypeMaskSet());
- return masks.add(mask);
+ ReceiverMask mask = universeSelector.mask;
+ Map<Selector, ReceiverMaskSet> selectors = selectorMap.putIfAbsent(
+ name, () => new Maplet<Selector, ReceiverMaskSet>());
+ UniverseReceiverMaskSet masks = selectors.putIfAbsent(
+ selector, () => receiverMaskStrategy.createReceiverMaskSet(selector));
+ return masks.addReceiverMask(mask);
}
- Map<Selector, TypeMaskSet> _asUnmodifiable(Map<Selector, TypeMaskSet> map) {
+ Map<Selector, ReceiverMaskSet> _asUnmodifiable(
+ Map<Selector, ReceiverMaskSet> map) {
if (map == null) return null;
return new UnmodifiableMapView(map);
}
- Map<Selector, TypeMaskSet> invocationsByName(String name) {
+ Map<Selector, ReceiverMaskSet> invocationsByName(String name) {
return _asUnmodifiable(_invokedNames[name]);
}
- Map<Selector, TypeMaskSet> getterInvocationsByName(String name) {
+ Map<Selector, ReceiverMaskSet> getterInvocationsByName(String name) {
return _asUnmodifiable(_invokedGetters[name]);
}
- Map<Selector, TypeMaskSet> setterInvocationsByName(String name) {
+ Map<Selector, ReceiverMaskSet> setterInvocationsByName(String name) {
return _asUnmodifiable(_invokedSetters[name]);
}
void forEachInvokedName(
- f(String name, Map<Selector, TypeMaskSet> selectors)) {
+ f(String name, Map<Selector, ReceiverMaskSet> selectors)) {
_invokedNames.forEach(f);
}
void forEachInvokedGetter(
- f(String name, Map<Selector, TypeMaskSet> selectors)) {
+ f(String name, Map<Selector, ReceiverMaskSet> selectors)) {
_invokedGetters.forEach(f);
}
void forEachInvokedSetter(
- f(String name, Map<Selector, TypeMaskSet> selectors)) {
+ f(String name, Map<Selector, ReceiverMaskSet> selectors)) {
_invokedSetters.forEach(f);
}
diff --git a/pkg/compiler/lib/src/use_unused_api.dart b/pkg/compiler/lib/src/use_unused_api.dart
index 3fbf537..bdb0acf 100644
--- a/pkg/compiler/lib/src/use_unused_api.dart
+++ b/pkg/compiler/lib/src/use_unused_api.dart
@@ -46,7 +46,7 @@
import 'util/util.dart' as util;
import 'world.dart';
-import 'scanner/scannerlib.dart' show
+import 'parser/partial_elements.dart' show
PartialClassElement,
PartialFunctionElement;
diff --git a/pkg/compiler/pubspec.yaml b/pkg/compiler/pubspec.yaml
index ad922d2..fe774b2 100644
--- a/pkg/compiler/pubspec.yaml
+++ b/pkg/compiler/pubspec.yaml
@@ -11,6 +11,8 @@
sdk_library_metadata:
path: ../../sdk/lib/_internal/sdk_library_metadata
dart2js_info: ^0.0.2
+ lookup_map:
+ path: ../lookup_map
# Uncomment if running gclient, so you can depend directly on the downloaded
diff --git a/pkg/dart2js_incremental/lib/diff.dart b/pkg/dart2js_incremental/lib/diff.dart
index a667fad..b0569d1 100644
--- a/pkg/dart2js_incremental/lib/diff.dart
+++ b/pkg/dart2js_incremental/lib/diff.dart
@@ -19,15 +19,19 @@
import 'package:compiler/src/elements/modelx.dart' show
DeclarationSite;
-import 'package:compiler/src/scanner/scannerlib.dart' show
- EOF_TOKEN,
- ErrorToken,
- IDENTIFIER_TOKEN,
- KEYWORD_TOKEN,
+import 'package:compiler/src/parser/partial_elements.dart' show
PartialClassElement,
- PartialElement,
+ PartialElement;
+
+import 'package:compiler/src/tokens/token.dart' show
+ ErrorToken,
Token;
+import 'package:compiler/src/tokens/token_constants.dart' show
+ EOF_TOKEN,
+ IDENTIFIER_TOKEN,
+ KEYWORD_TOKEN;
+
class Difference {
final DeclarationSite before;
final DeclarationSite after;
diff --git a/pkg/dart2js_incremental/lib/library_updater.dart b/pkg/dart2js_incremental/lib/library_updater.dart
index 6120e379..faca103 100644
--- a/pkg/dart2js_incremental/lib/library_updater.dart
+++ b/pkg/dart2js_incremental/lib/library_updater.dart
@@ -27,18 +27,30 @@
import 'package:compiler/src/enqueue.dart' show
EnqueueTask;
-import 'package:compiler/src/scanner/scannerlib.dart' show
- EOF_TOKEN,
- Listener,
- NodeListener,
- Parser,
+import 'package:compiler/src/parser/listener.dart' show
+ Listener;
+
+import 'package:compiler/src/parser/node_listener.dart' show
+ NodeListener;
+
+import 'package:compiler/src/parser/partial_elements.dart' show
PartialClassElement,
PartialElement,
PartialFieldList,
- PartialFunctionElement,
- Scanner,
+ PartialFunctionElement;
+
+import 'package:compiler/src/parser/parser.dart' show
+ Parser;
+
+import 'package:compiler/src/scanner/scanner.dart' show
+ Scanner;
+
+import 'package:compiler/src/tokens/token.dart' show
Token;
+import 'package:compiler/src/tokens/token_constants.dart' show
+ EOF_TOKEN;
+
import 'package:compiler/src/script.dart' show
Script;
diff --git a/pkg/lookup_map/AUTHORS b/pkg/lookup_map/AUTHORS
new file mode 100644
index 0000000..e8063a8
--- /dev/null
+++ b/pkg/lookup_map/AUTHORS
@@ -0,0 +1,6 @@
+# Below is a list of people and organizations that have contributed
+# to the project. Names should be added to the list like so:
+#
+# Name/Organization <email address>
+
+Google Inc.
diff --git a/pkg/lookup_map/CHANGELOG.md b/pkg/lookup_map/CHANGELOG.md
new file mode 100644
index 0000000..cbe7954a
--- /dev/null
+++ b/pkg/lookup_map/CHANGELOG.md
@@ -0,0 +1,4 @@
+# Changelog
+
+## 0.0.1
+- Initial version of `LookupMap`
diff --git a/pkg/lookup_map/LICENSE b/pkg/lookup_map/LICENSE
new file mode 100644
index 0000000..de31e1a
--- /dev/null
+++ b/pkg/lookup_map/LICENSE
@@ -0,0 +1,26 @@
+Copyright 2015, the Dart project authors. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials provided
+ with the distribution.
+ * Neither the name of Google Inc. nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/pkg/lookup_map/README.md b/pkg/lookup_map/README.md
new file mode 100644
index 0000000..73f5a81
--- /dev/null
+++ b/pkg/lookup_map/README.md
@@ -0,0 +1,29 @@
+# Lookup maps
+
+This package contains the definition of `LookupMap`: a simple, but very
+restricted map. The map can only hold constant keys and the only way to use the
+map is to retrieve values with a key you already have. Expect for lookup, any
+other operation in `Map` (like forEach, keys, values, length, etc) is not
+available.
+
+Constant `LookupMap`s are understood by dart2js and can be tree-shaken
+internally: if a key is not used elsewhere in the program, its entry can be
+deleted from the map during compilation without changing the program's behavior.
+Currently dart2js supports tree-shaking keys that are Type literals, and any
+const expression that can only be created with a const constructor. This means
+that primitives, Strings, and constant objects that override the `==` operator
+cannot be tree-shaken.
+
+
+## Examples
+
+`LookupMap` is unlikely going to be useful for individual developers writing
+code by hand. It is mainly intended as a helper utility for frameworks that need
+to autogenerate data and associate it with a type in the program. For example,
+this can be used by a dependency injection system to record how to create
+instances of a given type. A dependency injection framework can store in a
+`LookupMap` all the information it needs for every injectable type in every
+library and package. When compiling a specific application, dart2js can
+tree-shake the data of types that are not used by the application. Similarly,
+this can also be used by serialization/deserialization packages that can store
+in a `LookupMap` the deserialization logic for a given type.
diff --git a/pkg/lookup_map/lib/lookup_map.dart b/pkg/lookup_map/lib/lookup_map.dart
new file mode 100644
index 0000000..609f854
--- /dev/null
+++ b/pkg/lookup_map/lib/lookup_map.dart
@@ -0,0 +1,93 @@
+// Copyright (c) 2015, 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.
+
+/// Defines [LookupMap], a simple map that can be optimized by dart2js.
+library lookup_map;
+
+/// [LookupMap] is a simple, but very restricted map. The map can only hold
+/// constant keys and the only way to use the map is to retrieve values with a
+/// key you already have. Expect for lookup, any other operation in [Map] (like
+/// forEach, keys, values, length, etc) is not available.
+///
+/// Constant [LookupMap]s are understood by dart2js and can be tree-shaken
+/// internally: if a key is not used elsewhere in the program, its entry can be
+/// deleted from the map during compilation without changing the program's
+/// behavior. Currently dart2js supports tree-shaking keys that are `Type`
+/// literals, and any const expression that can only be created with a const
+/// constructor. This means that primitives, Strings, and constant objects that
+/// override the `==` operator cannot be tree-shaken.
+///
+/// Note: [LookupMap] is unlikely going to be useful for individual developers
+/// writing code by hand. It is mainly intended as a helper utility for
+/// frameworks that need to autogenerate data and associate it with a type in
+/// the program. For example, this can be used by a dependency injection system
+/// to record how to create instances of a given type. A dependency injection
+/// framework can store in a [LookupMap] all the information it needs for every
+/// injectable type in every library and package. When compiling a specific
+/// application, dart2js can tree-shake the data of types that are not used by
+/// the application. Similarly, this can also be used by
+/// serialization/deserialization packages that can store in a [LookupMap] the
+/// deserialization logic for a given type.
+class LookupMap<K, V> {
+ /// The key for [LookupMap]s with a single key/value pair.
+ final K _key;
+
+ /// The value for [LookupMap]s with a single key/value pair.
+ final V _value;
+
+ /// List of alternating key-value pairs in the map.
+ final List _entries;
+
+ /// Other maps to which this map delegates lookup operations if the key is not
+ /// found on [entries]. See [LookupMap]'s constructor for details.
+ final List<LookupMap<K, V>> _nestedMaps;
+
+ /// Creates a lookup-map given a list of key-value pair [entries], and
+ /// optionally additional entries from other [LookupMap]s.
+ ///
+ /// When doing a lookup, if the key is not found on [entries]. The lookup will
+ /// be performed in reverse order of the list of [nestedMaps], so a later
+ /// entry for a key shadows previous entries. For example, in:
+ ///
+ /// const map = const LookupMap(const [A, 1],
+ /// const [const LookupMap(const [A, 2, B, 4]),
+ /// const LookupMap(const [A, 3, B, 5]));
+ ///
+ /// `map[A]` returns `1` and `map[B]` returns `5`.
+ ///
+ /// Note: in the future we expect to change [entries] to be a const map
+ /// instead of a list of key-value pairs.
+ // TODO(sigmund): make entries a map once we fix TypeImpl.== (issue #17207).
+ const LookupMap(List entries, [List<LookupMap<K, V>> nestedMaps = const []])
+ : _key = null, _value = null, _entries = entries, _nestedMaps = nestedMaps;
+
+ /// Creates a lookup map with a single key-value pair.
+ const LookupMap.pair(K key, V value)
+ : _key = key, _value = value, _entries = const [], _nestedMaps = const [];
+
+ /// Return the data corresponding to [key].
+ V operator[](K key) {
+ var map = _flatMap[this];
+ if (map == null) {
+ map = {};
+ _addEntriesTo(map);
+ _flatMap[this] = map;
+ }
+ return map[key];
+ }
+
+ /// Add to [map] entries from [nestedMaps] and from [entries] according to the
+ /// precedense order described in [nestedMaps].
+ _addEntriesTo(Map map) {
+ _nestedMaps.forEach((m) => m._addEntriesTo(map));
+ for (var i = 0; i < _entries.length; i += 2) {
+ map[_entries[i]] = _entries[i + 1];
+ }
+ if (_key != null) map[_key] = _value;
+ }
+}
+
+/// An expando that stores a flatten version of a [LookupMap], this is
+/// computed and stored the first time the map is accessed.
+final _flatMap = new Expando('_flat_map');
diff --git a/pkg/lookup_map/pubspec.yaml b/pkg/lookup_map/pubspec.yaml
new file mode 100644
index 0000000..fdc8946
--- /dev/null
+++ b/pkg/lookup_map/pubspec.yaml
@@ -0,0 +1,3 @@
+name: lookup_map
+description: a lookup-only map that can be tree-shaken by dart2js
+version: 0.0.1
diff --git a/runtime/bin/dbg_connection.cc b/runtime/bin/dbg_connection.cc
index 2cc4cd8..6bd0cda 100644
--- a/runtime/bin/dbg_connection.cc
+++ b/runtime/bin/dbg_connection.cc
@@ -198,6 +198,9 @@
msgbuf_->ReadData();
}
if (!msgbuf_->Alive()) {
+ if (trace_debug_protocol) {
+ Log::Print("Debugger is exiting HandleMessages loop.\n");
+ }
return;
}
@@ -344,6 +347,13 @@
}
+void DebuggerConnectionHandler::StopHandler() {
+ if (IsConnected()) {
+ DebuggerConnectionImpl::StopHandler(singleton_handler->debug_fd());
+ }
+}
+
+
void DebuggerConnectionHandler::WaitForConnection() {
ASSERT(handler_lock_ != NULL);
MonitorLocker ml(handler_lock_);
diff --git a/runtime/bin/dbg_connection.h b/runtime/bin/dbg_connection.h
index bd4f4dd..577c30a 100644
--- a/runtime/bin/dbg_connection.h
+++ b/runtime/bin/dbg_connection.h
@@ -51,6 +51,9 @@
// from the client.
static int StartHandler(const char* address, int port_number);
+ // Stops the native thread.
+ static void StopHandler();
+
// Initializes the parts of the debugger which are needed by the vm
// service. This function should only be called when StartHandler
// is not called.
diff --git a/runtime/bin/dbg_connection_android.h b/runtime/bin/dbg_connection_android.h
index 591ee9f..8975294 100644
--- a/runtime/bin/dbg_connection_android.h
+++ b/runtime/bin/dbg_connection_android.h
@@ -16,6 +16,7 @@
class DebuggerConnectionImpl {
public:
static void StartHandler(int port_number);
+ static void StopHandler(intptr_t debug_fd) {}
static intptr_t Send(intptr_t socket, const char* buf, int len);
static intptr_t Receive(intptr_t socket, char* buf, int len);
diff --git a/runtime/bin/dbg_connection_linux.h b/runtime/bin/dbg_connection_linux.h
index 94a9664..fcbd16e 100644
--- a/runtime/bin/dbg_connection_linux.h
+++ b/runtime/bin/dbg_connection_linux.h
@@ -16,6 +16,7 @@
class DebuggerConnectionImpl {
public:
static void StartHandler(int port_number);
+ static void StopHandler(intptr_t debug_fd) {}
static intptr_t Send(intptr_t socket, const char* buf, int len);
static intptr_t Receive(intptr_t socket, char* buf, int len);
diff --git a/runtime/bin/dbg_connection_macos.h b/runtime/bin/dbg_connection_macos.h
index 9665700..064238e 100644
--- a/runtime/bin/dbg_connection_macos.h
+++ b/runtime/bin/dbg_connection_macos.h
@@ -16,6 +16,7 @@
class DebuggerConnectionImpl {
public:
static void StartHandler(int port_number);
+ static void StopHandler(intptr_t debug_fd) {}
static intptr_t Send(intptr_t socket, const char* buf, int len);
static intptr_t Receive(intptr_t socket, char* buf, int len);
diff --git a/runtime/bin/dbg_connection_win.cc b/runtime/bin/dbg_connection_win.cc
index fee02e6c..49bc4a9 100644
--- a/runtime/bin/dbg_connection_win.cc
+++ b/runtime/bin/dbg_connection_win.cc
@@ -8,12 +8,59 @@
#include "bin/dbg_connection.h"
#include "bin/eventhandler.h"
-
+#include "bin/lockers.h"
+#include "bin/log.h"
+#include "bin/thread.h"
namespace dart {
namespace bin {
+Monitor* DebuggerConnectionImpl::handler_monitor_ = new Monitor();
+ThreadId DebuggerConnectionImpl::handler_thread_id_ = Thread::kInvalidThreadId;
+bool DebuggerConnectionImpl::handler_thread_running_ = false;
+
+
+void DebuggerConnectionImpl::NotifyThreadStarted() {
+ MonitorLocker ml(handler_monitor_);
+ ASSERT(!handler_thread_running_);
+ ASSERT(handler_thread_id_ == Thread::kInvalidThreadId);
+ handler_thread_running_ = true;
+ handler_thread_id_ = Thread::GetCurrentThreadId();
+ ml.Notify();
+}
+
+
+void DebuggerConnectionImpl::WaitForThreadStarted() {
+ MonitorLocker ml(handler_monitor_);
+ while (!handler_thread_running_) {
+ ml.Wait();
+ }
+ ASSERT(handler_thread_id_ != Thread::kInvalidThreadId);
+}
+
+
+void DebuggerConnectionImpl::NotifyThreadFinished() {
+ MonitorLocker ml(handler_monitor_);
+ ASSERT(handler_thread_running_);
+ ASSERT(handler_thread_id_ != Thread::kInvalidThreadId);
+ handler_thread_running_ = false;
+ ml.Notify();
+}
+
+
+void DebuggerConnectionImpl::WaitForThreadFinished() {
+ MonitorLocker ml(handler_monitor_);
+ while (handler_thread_running_) {
+ ml.Wait();
+ }
+ ASSERT(handler_thread_id_ != Thread::kInvalidThreadId);
+ Thread::Join(handler_thread_id_);
+ handler_thread_id_ = Thread::kInvalidThreadId;
+}
+
+
void DebuggerConnectionImpl::ThreadEntry(uword args) {
+ NotifyThreadStarted();
ListenSocket* listen_socket =
reinterpret_cast<ListenSocket*>(DebuggerConnectionHandler::listener_fd_);
SOCKET client_socket = accept(listen_socket->socket(), NULL, NULL);
@@ -23,6 +70,7 @@
ClientSocket* socket = new ClientSocket(client_socket);
DebuggerConnectionHandler::AcceptDbgConnection(
reinterpret_cast<intptr_t>(socket));
+ NotifyThreadFinished();
}
@@ -32,6 +80,13 @@
if (result != 0) {
FATAL1("Failed to start debugger connection handler thread: %d\n", result);
}
+ WaitForThreadStarted();
+}
+
+
+void DebuggerConnectionImpl::StopHandler(intptr_t debug_fd) {
+ Send(debug_fd, NULL, 0);
+ WaitForThreadFinished();
}
diff --git a/runtime/bin/dbg_connection_win.h b/runtime/bin/dbg_connection_win.h
index 2a9feb2..8f5d0c6 100644
--- a/runtime/bin/dbg_connection_win.h
+++ b/runtime/bin/dbg_connection_win.h
@@ -5,17 +5,29 @@
#ifndef BIN_DBG_CONNECTION_WIN_H_
#define BIN_DBG_CONNECTION_WIN_H_
+#include "bin/lockers.h"
+#include "bin/thread.h"
+
namespace dart {
namespace bin {
class DebuggerConnectionImpl {
public:
static void StartHandler(int port_number);
+ static void StopHandler(intptr_t debug_fd);
static intptr_t Send(intptr_t socket, const char* buf, int len);
static intptr_t Receive(intptr_t socket, char* buf, int len);
private:
static void ThreadEntry(uword args);
+ static void NotifyThreadStarted();
+ static void WaitForThreadStarted();
+ static void NotifyThreadFinished();
+ static void WaitForThreadFinished();
+
+ static Monitor* handler_monitor_;
+ static ThreadId handler_thread_id_;
+ static bool handler_thread_running_;
};
} // namespace bin
diff --git a/runtime/bin/eventhandler_win.cc b/runtime/bin/eventhandler_win.cc
index db698a3..6e27f82 100644
--- a/runtime/bin/eventhandler_win.cc
+++ b/runtime/bin/eventhandler_win.cc
@@ -121,23 +121,16 @@
pending_read_(NULL),
pending_write_(NULL),
last_error_(NOERROR),
- flags_(0) {
- InitializeCriticalSection(&cs_);
+ flags_(0),
+ read_thread_id_(Thread::kInvalidThreadId),
+ read_thread_starting_(false),
+ read_thread_finished_(false),
+ monitor_(new Monitor()) {
}
Handle::~Handle() {
- DeleteCriticalSection(&cs_);
-}
-
-
-void Handle::Lock() {
- EnterCriticalSection(&cs_);
-}
-
-
-void Handle::Unlock() {
- LeaveCriticalSection(&cs_);
+ delete monitor_;
}
@@ -154,7 +147,7 @@
void Handle::Close() {
- ScopedLock lock(this);
+ MonitorLocker ml(monitor_);
if (!IsClosing()) {
// Close the socket and set the closing state. This close method can be
// called again if this socket has pending IO operations in flight.
@@ -175,28 +168,60 @@
bool Handle::HasPendingRead() {
- ScopedLock lock(this);
+ MonitorLocker ml(monitor_);
return pending_read_ != NULL;
}
bool Handle::HasPendingWrite() {
- ScopedLock lock(this);
+ MonitorLocker ml(monitor_);
return pending_write_ != NULL;
}
-void Handle::ReadComplete(OverlappedBuffer* buffer) {
- ScopedLock lock(this);
- // Currently only one outstanding read at the time.
- ASSERT(pending_read_ == buffer);
- ASSERT(data_ready_ == NULL);
- if (!IsClosing() && !buffer->IsEmpty()) {
- data_ready_ = pending_read_;
- } else {
- OverlappedBuffer::DisposeBuffer(buffer);
+void Handle::WaitForReadThreadStarted() {
+ MonitorLocker ml(monitor_);
+ while (read_thread_starting_) {
+ ml.Wait();
}
- pending_read_ = NULL;
+}
+
+
+void Handle::WaitForReadThreadFinished() {
+ // Join the Reader thread if there is one.
+ ThreadId to_join = Thread::kInvalidThreadId;
+ {
+ MonitorLocker ml(monitor_);
+ if (read_thread_id_ != Thread::kInvalidThreadId) {
+ while (!read_thread_finished_) {
+ ml.Wait();
+ }
+ read_thread_finished_ = false;
+ to_join = read_thread_id_;
+ read_thread_id_ = Thread::kInvalidThreadId;
+ }
+ }
+ if (to_join != Thread::kInvalidThreadId) {
+ Thread::Join(to_join);
+ }
+}
+
+
+void Handle::ReadComplete(OverlappedBuffer* buffer) {
+ WaitForReadThreadStarted();
+ {
+ MonitorLocker ml(monitor_);
+ // Currently only one outstanding read at the time.
+ ASSERT(pending_read_ == buffer);
+ ASSERT(data_ready_ == NULL);
+ if (!IsClosing() && !buffer->IsEmpty()) {
+ data_ready_ = pending_read_;
+ } else {
+ OverlappedBuffer::DisposeBuffer(buffer);
+ }
+ pending_read_ = NULL;
+ }
+ WaitForReadThreadFinished();
}
@@ -206,7 +231,7 @@
void Handle::WriteComplete(OverlappedBuffer* buffer) {
- ScopedLock lock(this);
+ MonitorLocker ml(monitor_);
// Currently only one outstanding write at the time.
ASSERT(pending_write_ == buffer);
OverlappedBuffer::DisposeBuffer(buffer);
@@ -220,7 +245,26 @@
}
+void Handle::NotifyReadThreadStarted() {
+ MonitorLocker ml(monitor_);
+ ASSERT(read_thread_starting_);
+ ASSERT(read_thread_id_ == Thread::kInvalidThreadId);
+ read_thread_id_ = Thread::GetCurrentThreadId();
+ read_thread_starting_ = false;
+ ml.Notify();
+}
+
+void Handle::NotifyReadThreadFinished() {
+ MonitorLocker ml(monitor_);
+ ASSERT(!read_thread_finished_);
+ ASSERT(read_thread_id_ != Thread::kInvalidThreadId);
+ read_thread_finished_ = true;
+ ml.Notify();
+}
+
+
void Handle::ReadSyncCompleteAsync() {
+ NotifyReadThreadStarted();
ASSERT(pending_read_ != NULL);
ASSERT(pending_read_->GetBufferSize() >= kStdOverlappedBufferSize);
@@ -228,9 +272,10 @@
if (GetFileType(handle_) == FILE_TYPE_CHAR) {
buffer_size = kStdOverlappedBufferSize;
}
+ char* buffer_start = pending_read_->GetBufferStart();
DWORD bytes_read = 0;
BOOL ok = ReadFile(handle_,
- pending_read_->GetBufferStart(),
+ buffer_start,
buffer_size,
&bytes_read,
NULL);
@@ -245,11 +290,11 @@
if (!ok) {
FATAL("PostQueuedCompletionStatus failed");
}
+ NotifyReadThreadFinished();
}
bool Handle::IssueRead() {
- ScopedLock lock(this);
ASSERT(type_ != kListenSocket);
ASSERT(pending_read_ == NULL);
OverlappedBuffer* buffer = OverlappedBuffer::AllocateReadBuffer(kBufferSize);
@@ -272,6 +317,7 @@
} else {
// Completing asynchronously through thread.
pending_read_ = buffer;
+ read_thread_starting_ = true;
int result = Thread::Start(ReadFileThread,
reinterpret_cast<uword>(this));
if (result != 0) {
@@ -288,7 +334,7 @@
bool Handle::IssueWrite() {
- ScopedLock lock(this);
+ MonitorLocker ml(monitor_);
ASSERT(type_ != kListenSocket);
ASSERT(completion_port_ != INVALID_HANDLE_VALUE);
ASSERT(pending_write_ != NULL);
@@ -345,7 +391,7 @@
void FileHandle::EnsureInitialized(EventHandlerImplementation* event_handler) {
- ScopedLock lock(this);
+ MonitorLocker ml(monitor_);
event_handler_ = event_handler;
if (SupportsOverlappedIO() && completion_port_ == INVALID_HANDLE_VALUE) {
CreateCompletionPort(event_handler_->completion_port());
@@ -360,7 +406,7 @@
void DirectoryWatchHandle::EnsureInitialized(
EventHandlerImplementation* event_handler) {
- ScopedLock lock(this);
+ MonitorLocker ml(monitor_);
event_handler_ = event_handler;
if (completion_port_ == INVALID_HANDLE_VALUE) {
CreateCompletionPort(event_handler_->completion_port());
@@ -374,7 +420,6 @@
bool DirectoryWatchHandle::IssueRead() {
- ScopedLock lock(this);
// It may have been started before, as we start the directory-handler when
// we create it.
if (pending_read_ != NULL || data_ready_ != NULL) return true;
@@ -399,7 +444,7 @@
void DirectoryWatchHandle::Stop() {
- ScopedLock lock(this);
+ MonitorLocker ml(monitor_);
// Stop the outstanding read, so we can close the handle.
if (pending_read_ != NULL) {
@@ -443,7 +488,7 @@
bool ListenSocket::IssueAccept() {
- ScopedLock lock(this);
+ MonitorLocker ml(monitor_);
// For AcceptEx there needs to be buffer storage for address
// information for two addresses (local and remote address). The
@@ -483,7 +528,7 @@
void ListenSocket::AcceptComplete(OverlappedBuffer* buffer,
HANDLE completion_port) {
- ScopedLock lock(this);
+ MonitorLocker ml(monitor_);
if (!IsClosing()) {
// Update the accepted socket to support the full range of API calls.
SOCKET s = socket();
@@ -544,13 +589,13 @@
bool ListenSocket::CanAccept() {
- ScopedLock lock(this);
+ MonitorLocker ml(monitor_);
return accepted_head_ != NULL;
}
ClientSocket* ListenSocket::Accept() {
- ScopedLock lock(this);
+ MonitorLocker ml(monitor_);
ClientSocket *result = NULL;
@@ -577,7 +622,7 @@
void ListenSocket::EnsureInitialized(
EventHandlerImplementation* event_handler) {
- ScopedLock lock(this);
+ MonitorLocker ml(monitor_);
if (AcceptEx_ == NULL) {
ASSERT(completion_port_ == INVALID_HANDLE_VALUE);
ASSERT(event_handler_ == NULL);
@@ -594,7 +639,7 @@
intptr_t Handle::Available() {
- ScopedLock lock(this);
+ MonitorLocker ml(monitor_);
if (data_ready_ == NULL) return 0;
ASSERT(!data_ready_->IsEmpty());
return data_ready_->GetRemainingLength();
@@ -602,7 +647,7 @@
intptr_t Handle::Read(void* buffer, intptr_t num_bytes) {
- ScopedLock lock(this);
+ MonitorLocker ml(monitor_);
if (data_ready_ == NULL) return 0;
num_bytes = data_ready_->Read(
buffer, Utils::Minimum<intptr_t>(num_bytes, INT_MAX));
@@ -617,7 +662,7 @@
intptr_t Handle::RecvFrom(
void* buffer, intptr_t num_bytes, struct sockaddr* sa, socklen_t sa_len) {
- ScopedLock lock(this);
+ MonitorLocker ml(monitor_);
if (data_ready_ == NULL) return 0;
num_bytes = data_ready_->Read(
buffer, Utils::Minimum<intptr_t>(num_bytes, INT_MAX));
@@ -639,7 +684,7 @@
intptr_t Handle::Write(const void* buffer, intptr_t num_bytes) {
- ScopedLock lock(this);
+ MonitorLocker ml(monitor_);
if (pending_write_ != NULL) return 0;
if (num_bytes > kBufferSize) num_bytes = kBufferSize;
ASSERT(SupportsOverlappedIO());
@@ -656,7 +701,7 @@
intptr_t num_bytes,
struct sockaddr* sa,
socklen_t sa_len) {
- ScopedLock lock(this);
+ MonitorLocker ml(monitor_);
if (pending_write_ != NULL) return 0;
if (num_bytes > kBufferSize) num_bytes = kBufferSize;
ASSERT(SupportsOverlappedIO());
@@ -675,13 +720,14 @@
void StdHandle::RunWriteLoop() {
- write_monitor_->Enter();
+ MonitorLocker ml(monitor_);
write_thread_running_ = true;
+ thread_id_ = Thread::GetCurrentThreadId();
// Notify we have started.
- write_monitor_->Notify();
+ ml.Notify();
while (write_thread_running_) {
- write_monitor_->Wait(Monitor::kNoTimeout);
+ ml.Wait(Monitor::kNoTimeout);
if (pending_write_ != NULL) {
// We woke up and had a pending write. Execute it.
WriteSyncCompleteAsync();
@@ -689,8 +735,7 @@
}
write_thread_exists_ = false;
- write_monitor_->Notify();
- write_monitor_->Exit();
+ ml.Notify();
}
@@ -718,7 +763,7 @@
}
intptr_t StdHandle::Write(const void* buffer, intptr_t num_bytes) {
- ScopedLock lock(this);
+ MonitorLocker ml(monitor_);
if (pending_write_ != NULL) return 0;
if (num_bytes > kBufferSize) num_bytes = kBufferSize;
// In the case of stdout and stderr, OverlappedIO is not supported.
@@ -726,7 +771,6 @@
// This code is actually never exposed to the user, as stdout and stderr is
// not available as a RawSocket, but only wrapped in a Socket.
// Note that we return '0', unless a thread have already completed a write.
- MonitorLocker locker(write_monitor_);
if (thread_wrote_ > 0) {
if (num_bytes > thread_wrote_) num_bytes = thread_wrote_;
thread_wrote_ -= num_bytes;
@@ -734,14 +778,14 @@
}
if (!write_thread_exists_) {
write_thread_exists_ = true;
- int result = Thread::Start(WriteFileThread,
- reinterpret_cast<uword>(this));
+ int result = Thread::Start(
+ WriteFileThread, reinterpret_cast<uword>(this));
if (result != 0) {
FATAL1("Failed to start write file thread %d", result);
}
while (!write_thread_running_) {
// Wait until we the thread is running.
- locker.Wait(Monitor::kNoTimeout);
+ ml.Wait(Monitor::kNoTimeout);
}
}
// Only queue up to INT_MAX bytes.
@@ -749,19 +793,20 @@
// Create buffer and notify thread about the new handle.
pending_write_ = OverlappedBuffer::AllocateWriteBuffer(truncated_bytes);
pending_write_->Write(buffer, truncated_bytes);
- locker.Notify();
+ ml.Notify();
return 0;
}
void StdHandle::DoClose() {
- MonitorLocker locker(write_monitor_);
+ MonitorLocker ml(monitor_);
if (write_thread_exists_) {
write_thread_running_ = false;
- locker.Notify();
+ ml.Notify();
while (write_thread_exists_) {
- locker.Wait(Monitor::kNoTimeout);
+ ml.Wait(Monitor::kNoTimeout);
}
+ Thread::Join(thread_id_);
}
Handle::DoClose();
}
@@ -807,7 +852,7 @@
bool ClientSocket::IssueRead() {
- ScopedLock lock(this);
+ MonitorLocker ml(monitor_);
ASSERT(completion_port_ != INVALID_HANDLE_VALUE);
ASSERT(pending_read_ == NULL);
@@ -836,7 +881,7 @@
bool ClientSocket::IssueWrite() {
- ScopedLock lock(this);
+ MonitorLocker ml(monitor_);
ASSERT(completion_port_ != INVALID_HANDLE_VALUE);
ASSERT(pending_write_ != NULL);
ASSERT(pending_write_->operation() == OverlappedBuffer::kWrite);
@@ -900,7 +945,7 @@
void ClientSocket::EnsureInitialized(
EventHandlerImplementation* event_handler) {
- ScopedLock lock(this);
+ MonitorLocker ml(monitor_);
if (completion_port_ == INVALID_HANDLE_VALUE) {
ASSERT(event_handler_ == NULL);
event_handler_ = event_handler;
@@ -915,7 +960,7 @@
bool DatagramSocket::IssueSendTo(struct sockaddr* sa, socklen_t sa_len) {
- ScopedLock lock(this);
+ MonitorLocker ml(monitor_);
ASSERT(completion_port_ != INVALID_HANDLE_VALUE);
ASSERT(pending_write_ != NULL);
ASSERT(pending_write_->operation() == OverlappedBuffer::kSendTo);
@@ -940,7 +985,7 @@
bool DatagramSocket::IssueRecvFrom() {
- ScopedLock lock(this);
+ MonitorLocker ml(monitor_);
ASSERT(completion_port_ != INVALID_HANDLE_VALUE);
ASSERT(pending_read_ == NULL);
@@ -970,7 +1015,7 @@
void DatagramSocket::EnsureInitialized(
EventHandlerImplementation* event_handler) {
- ScopedLock lock(this);
+ MonitorLocker ml(monitor_);
if (completion_port_ == INVALID_HANDLE_VALUE) {
ASSERT(event_handler_ == NULL);
event_handler_ = event_handler;
@@ -1010,7 +1055,7 @@
reinterpret_cast<ListenSocket*>(handle);
listen_socket->EnsureInitialized(this);
- Handle::ScopedLock lock(listen_socket);
+ MonitorLocker ml(listen_socket->monitor_);
if (IS_COMMAND(msg->data, kReturnTokenCommand)) {
listen_socket->ReturnTokens(msg->dart_port, TOKEN_COUNT(msg->data));
@@ -1040,7 +1085,7 @@
}
} else {
handle->EnsureInitialized(this);
- Handle::ScopedLock lock(handle);
+ MonitorLocker ml(handle->monitor_);
if (IS_COMMAND(msg->data, kReturnTokenCommand)) {
handle->ReturnTokens(msg->dart_port, TOKEN_COUNT(msg->data));
@@ -1114,7 +1159,7 @@
listen_socket->AcceptComplete(buffer, completion_port_);
{
- Handle::ScopedLock lock(listen_socket);
+ MonitorLocker ml(listen_socket->monitor_);
TryDispatchingPendingAccepts(listen_socket);
}
@@ -1278,6 +1323,8 @@
EventHandlerImplementation::EventHandlerImplementation() {
+ startup_monitor_ = new Monitor();
+ handler_thread_id_ = Thread::kInvalidThreadId;
completion_port_ =
CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, NULL, 1);
if (completion_port_ == NULL) {
@@ -1288,6 +1335,8 @@
EventHandlerImplementation::~EventHandlerImplementation() {
+ Thread::Join(handler_thread_id_);
+ delete startup_monitor_;
CloseHandle(completion_port_);
}
@@ -1322,6 +1371,12 @@
EventHandlerImplementation* handler_impl = &handler->delegate_;
ASSERT(handler_impl != NULL);
+ {
+ MonitorLocker ml(handler_impl->startup_monitor_);
+ handler_impl->handler_thread_id_ = Thread::GetCurrentThreadId();
+ ml.Notify();
+ }
+
while (!handler_impl->shutdown_) {
DWORD bytes;
ULONG_PTR key;
@@ -1382,6 +1437,13 @@
FATAL1("Failed to start event handler thread %d", result);
}
+ {
+ MonitorLocker ml(startup_monitor_);
+ while (handler_thread_id_ == Thread::kInvalidThreadId) {
+ ml.Wait();
+ }
+ }
+
// Initialize Winsock32
if (!Socket::Initialize()) {
FATAL("Failed to initialized Windows sockets");
diff --git a/runtime/bin/eventhandler_win.h b/runtime/bin/eventhandler_win.h
index bfd02f9..38509dd 100644
--- a/runtime/bin/eventhandler_win.h
+++ b/runtime/bin/eventhandler_win.h
@@ -165,20 +165,6 @@
kDatagramSocket
};
- class ScopedLock {
- public:
- explicit ScopedLock(Handle* handle)
- : handle_(handle) {
- handle_->Lock();
- }
- ~ScopedLock() {
- handle_->Unlock();
- }
-
- private:
- Handle* handle_;
- };
-
virtual ~Handle();
// Socket interface exposing normal socket operations.
@@ -219,9 +205,6 @@
HANDLE handle() { return handle_; }
- void Lock();
- void Unlock();
-
bool CreateCompletionPort(HANDLE completion_port);
void Close();
@@ -252,6 +235,9 @@
void set_last_error(DWORD last_error) { last_error_ = last_error; }
protected:
+ // For access to monitor_;
+ friend class EventHandlerImplementation;
+
enum Flags {
kClosing = 0,
kCloseRead = 1,
@@ -264,6 +250,7 @@
virtual void HandleIssueError();
+ Monitor* monitor_;
Type type_;
HANDLE handle_;
HANDLE completion_port_;
@@ -275,9 +262,17 @@
DWORD last_error_;
+ ThreadId read_thread_id_;
+ bool read_thread_starting_;
+ bool read_thread_finished_;
+
private:
+ void WaitForReadThreadStarted();
+ void NotifyReadThreadStarted();
+ void WaitForReadThreadFinished();
+ void NotifyReadThreadFinished();
+
int flags_;
- CRITICAL_SECTION cs_; // Critical section protecting this object.
};
@@ -297,17 +292,13 @@
public:
explicit StdHandle(HANDLE handle)
: FileHandle(handle),
+ thread_id_(Thread::kInvalidThreadId),
thread_wrote_(0),
write_thread_exists_(false),
- write_thread_running_(false),
- write_monitor_(new Monitor()) {
+ write_thread_running_(false) {
type_ = kStd;
}
- ~StdHandle() {
- delete write_monitor_;
- }
-
virtual void DoClose();
virtual intptr_t Write(const void* buffer, intptr_t num_bytes);
@@ -315,10 +306,10 @@
void RunWriteLoop();
private:
+ ThreadId thread_id_;
intptr_t thread_wrote_;
bool write_thread_exists_;
bool write_thread_running_;
- Monitor* write_monitor_;
};
@@ -526,6 +517,9 @@
private:
ClientSocket* client_sockets_head_;
+ Monitor* startup_monitor_;
+ ThreadId handler_thread_id_;
+
TimeoutQueue timeout_queue_; // Time for next timeout.
bool shutdown_;
HANDLE completion_port_;
diff --git a/runtime/bin/extensions.h b/runtime/bin/extensions.h
index 2b4e19b..25dbfeb 100644
--- a/runtime/bin/extensions.h
+++ b/runtime/bin/extensions.h
@@ -21,14 +21,14 @@
const char* extension_name,
Dart_Handle parent_library);
- private:
- // The returned string must be freed.
- static char* Concatenate(const char** strings);
-
// Platform-specific implementations.
static void* LoadExtensionLibrary(const char* library_file);
static void* ResolveSymbol(void* lib_handle, const char* symbol);
+ private:
+ // The returned string must be freed.
+ static char* Concatenate(const char** strings);
+
DISALLOW_ALLOCATION();
DISALLOW_IMPLICIT_CONSTRUCTORS(Extensions);
};
diff --git a/runtime/bin/extensions_android.cc b/runtime/bin/extensions_android.cc
index 3d2688b..1b79991 100644
--- a/runtime/bin/extensions_android.cc
+++ b/runtime/bin/extensions_android.cc
@@ -12,6 +12,9 @@
namespace dart {
namespace bin {
+const char* kPrecompiledLibraryName = "libprecompiled.so";
+const char* kPrecompiledSymbolName = "_kInstructionsSnapshot";
+
void* Extensions::LoadExtensionLibrary(const char* library_file) {
return dlopen(library_file, RTLD_LAZY);
}
diff --git a/runtime/bin/extensions_linux.cc b/runtime/bin/extensions_linux.cc
index c42024a..23ee6ed 100644
--- a/runtime/bin/extensions_linux.cc
+++ b/runtime/bin/extensions_linux.cc
@@ -12,6 +12,9 @@
namespace dart {
namespace bin {
+const char* kPrecompiledLibraryName = "libprecompiled.so";
+const char* kPrecompiledSymbolName = "_kInstructionsSnapshot";
+
void* Extensions::LoadExtensionLibrary(const char* library_file) {
return dlopen(library_file, RTLD_LAZY);
}
diff --git a/runtime/bin/extensions_macos.cc b/runtime/bin/extensions_macos.cc
index 814f935..92a5e98 100644
--- a/runtime/bin/extensions_macos.cc
+++ b/runtime/bin/extensions_macos.cc
@@ -12,6 +12,9 @@
namespace dart {
namespace bin {
+const char* kPrecompiledLibraryName = "libprecompiled.dylib";
+const char* kPrecompiledSymbolName = "kInstructionsSnapshot";
+
void* Extensions::LoadExtensionLibrary(const char* library_file) {
return dlopen(library_file, RTLD_LAZY);
}
diff --git a/runtime/bin/extensions_win.cc b/runtime/bin/extensions_win.cc
index 63462ee..8c0a15f 100644
--- a/runtime/bin/extensions_win.cc
+++ b/runtime/bin/extensions_win.cc
@@ -13,6 +13,9 @@
namespace dart {
namespace bin {
+const char* kPrecompiledLibraryName = "precompiled.dll";
+const char* kPrecompiledSymbolName = "_kInstructionsSnapshot";
+
void* Extensions::LoadExtensionLibrary(const char* library_file) {
return LoadLibraryW(StringUtilsWin::Utf8ToWide(library_file));
}
diff --git a/runtime/bin/main.cc b/runtime/bin/main.cc
index 4e2b24a..45fe8b4 100644
--- a/runtime/bin/main.cc
+++ b/runtime/bin/main.cc
@@ -73,7 +73,19 @@
// Global flag that is used to indicate that we want to compile all the
// dart functions before running main and not compile anything thereafter.
-static bool has_precompile = false;
+static bool has_gen_precompiled_snapshot = false;
+
+
+// Global flag that is used to indicate that we want to run from a precompiled
+// snapshot.
+static bool has_run_precompiled_snapshot = false;
+
+
+extern const char* kPrecompiledLibraryName;
+extern const char* kPrecompiledSymbolName;
+static const char* kPrecompiledVmIsolateName = "precompiled.vmisolate";
+static const char* kPrecompiledIsolateName = "precompiled.isolate";
+static const char* kPrecompiledInstructionsName = "precompiled.instructions";
// Global flag that is used to indicate that we want to trace resolution of
@@ -110,6 +122,9 @@
Dart_Cleanup();
+ DebuggerConnectionHandler::StopHandler();
+ // TODO(zra): Stop the EventHandler once thread shutdown is enabled.
+ // EventHandler::Stop();
exit(exit_code);
}
@@ -289,13 +304,33 @@
}
-static bool ProcessPrecompileOption(const char* arg,
- CommandLineOptions* vm_options) {
+static bool ProcessGenPrecompiledSnapshotOption(
+ const char* arg,
+ CommandLineOptions* vm_options) {
ASSERT(arg != NULL);
if (*arg != '\0') {
return false;
}
- has_precompile = true;
+ // Ensure that we are not already running using a full snapshot.
+ if (isolate_snapshot_buffer != NULL) {
+ Log::PrintErr("Precompiled snapshots must be generated with"
+ " dart_no_snapshot.");
+ return false;
+ }
+ has_gen_precompiled_snapshot = true;
+ vm_options->AddArgument("--precompile");
+ return true;
+}
+
+
+static bool ProcessRunPrecompiledSnapshotOption(
+ const char* arg,
+ CommandLineOptions* vm_options) {
+ ASSERT(arg != NULL);
+ if (*arg != '\0') {
+ return false;
+ }
+ has_run_precompiled_snapshot = true;
vm_options->AddArgument("--precompile");
return true;
}
@@ -320,7 +355,7 @@
static bool ProcessGenScriptSnapshotOption(const char* filename,
CommandLineOptions* vm_options) {
if (filename != NULL && strlen(filename) != 0) {
- // Ensure that are already running using a full snapshot.
+ // Ensure that we are already running using a full snapshot.
if (isolate_snapshot_buffer == NULL) {
Log::PrintErr("Script snapshots cannot be generated in this version of"
" dart\n");
@@ -411,7 +446,8 @@
// VM specific options to the standalone dart program.
{ "--break-at=", ProcessBreakpointOption },
{ "--compile_all", ProcessCompileAllOption },
- { "--precompile", ProcessPrecompileOption },
+ { "--gen-precompiled-snapshot", ProcessGenPrecompiledSnapshotOption },
+ { "--run-precompiled-snapshot", ProcessRunPrecompiledSnapshotOption },
{ "--debug", ProcessDebugOption },
{ "--snapshot=", ProcessGenScriptSnapshotOption },
{ "--enable-vm-service", ProcessEnableVmServiceOption },
@@ -645,7 +681,7 @@
*error = strdup(VmService::GetErrorMessage());
return NULL;
}
- if (has_precompile) {
+ if (has_gen_precompiled_snapshot) {
result = Dart_Precompile();
CHECK_RESULT(result);
} else if (has_compile_all) {
@@ -959,6 +995,50 @@
}
+static void WriteSnapshotFile(const char* filename,
+ const uint8_t* buffer,
+ const intptr_t size) {
+ File* file = File::Open(filename, File::kWriteTruncate);
+ ASSERT(file != NULL);
+ if (!file->WriteFully(buffer, size)) {
+ Log::PrintErr("Error: Failed to write snapshot file.\n\n");
+ }
+ delete file;
+}
+
+
+static void ReadSnapshotFile(const char* filename,
+ const uint8_t** buffer) {
+ void* file = DartUtils::OpenFile(filename, false);
+ if (file == NULL) {
+ Log::PrintErr("Error: Failed to open '%s'.\n\n", filename);
+ exit(kErrorExitCode);
+ }
+ intptr_t len = -1;
+ DartUtils::ReadFile(buffer, &len, file);
+ if (*buffer == NULL || len == -1) {
+ Log::PrintErr("Error: Failed to read '%s'.\n\n", filename);
+ exit(kErrorExitCode);
+ }
+ DartUtils::CloseFile(file);
+}
+
+
+static void* LoadLibrarySymbol(const char* libname, const char* symname) {
+ void* library = Extensions::LoadExtensionLibrary(libname);
+ if (library == NULL) {
+ Log::PrintErr("Error: Failed to load library '%s'.\n\n", libname);
+ exit(kErrorExitCode);
+ }
+ void* symbol = Extensions::ResolveSymbol(library, symname);
+ if (symbol == NULL) {
+ Log::PrintErr("Failed to load symbol '%s'\n", symname);
+ exit(kErrorExitCode);
+ }
+ return symbol;
+}
+
+
void main(int argc, char** argv) {
char* script_name;
const int EXTRA_VM_ARGUMENTS = 2;
@@ -1032,8 +1112,16 @@
DebuggerConnectionHandler::InitForVmService();
}
+ const uint8_t* instructions_snapshot = NULL;
+ if (has_run_precompiled_snapshot) {
+ instructions_snapshot = reinterpret_cast<const uint8_t*>(
+ LoadLibrarySymbol(kPrecompiledLibraryName, kPrecompiledSymbolName));
+ ReadSnapshotFile(kPrecompiledVmIsolateName, &vm_isolate_snapshot_buffer);
+ ReadSnapshotFile(kPrecompiledIsolateName, &isolate_snapshot_buffer);
+ }
+
// Initialize the Dart VM.
- if (!Dart_Initialize(vm_isolate_snapshot_buffer, NULL,
+ if (!Dart_Initialize(vm_isolate_snapshot_buffer, instructions_snapshot,
CreateIsolateAndSetup, NULL, NULL, ShutdownIsolate,
DartUtils::OpenFile,
DartUtils::ReadFile,
@@ -1042,6 +1130,9 @@
DartUtils::EntropySource)) {
fprintf(stderr, "%s", "VM initialization failed\n");
fflush(stderr);
+ DebuggerConnectionHandler::StopHandler();
+ // TODO(zra): Stop the EventHandler once thread shutdown is enabled.
+ // EventHandler::Stop();
exit(kErrorExitCode);
}
@@ -1066,6 +1157,9 @@
Log::PrintErr("%s\n", error);
free(error);
delete [] isolate_name;
+ DebuggerConnectionHandler::StopHandler();
+ // TODO(zra): Stop the EventHandler once thread shutdown is enabled.
+ // EventHandler::Stop();
exit((exit_code != 0) ? exit_code : kErrorExitCode);
}
delete [] isolate_name;
@@ -1111,9 +1205,32 @@
ASSERT(!Dart_IsError(builtin_lib));
result = Dart_LibraryImportLibrary(builtin_lib, root_lib, Dart_Null());
- if (has_precompile) {
+ if (has_gen_precompiled_snapshot) {
result = Dart_Precompile();
DartExitOnError(result);
+
+ uint8_t* vm_isolate_buffer = NULL;
+ intptr_t vm_isolate_size = 0;
+ uint8_t* isolate_buffer = NULL;
+ intptr_t isolate_size = 0;
+ uint8_t* instructions_buffer = NULL;
+ intptr_t instructions_size = 0;
+ result = Dart_CreatePrecompiledSnapshot(&vm_isolate_buffer,
+ &vm_isolate_size,
+ &isolate_buffer,
+ &isolate_size,
+ &instructions_buffer,
+ &instructions_size);
+ DartExitOnError(result);
+ WriteSnapshotFile(kPrecompiledVmIsolateName,
+ vm_isolate_buffer,
+ vm_isolate_size);
+ WriteSnapshotFile(kPrecompiledIsolateName,
+ isolate_buffer,
+ isolate_size);
+ WriteSnapshotFile(kPrecompiledInstructionsName,
+ instructions_buffer,
+ instructions_size);
} else if (has_compile_all) {
result = Dart_CompileAll();
DartExitOnError(result);
@@ -1171,6 +1288,10 @@
Dart_Cleanup();
+ DebuggerConnectionHandler::StopHandler();
+ // TODO(zra): Stop the EventHandler once thread shutdown is enabled.
+ // EventHandler::Stop();
+
// Free copied argument strings if converted.
if (argv_converted) {
for (int i = 0; i < argc; i++) free(argv[i]);
diff --git a/runtime/bin/process.cc b/runtime/bin/process.cc
index 2c90c11..242ef1c 100644
--- a/runtime/bin/process.cc
+++ b/runtime/bin/process.cc
@@ -3,6 +3,8 @@
// BSD-style license that can be found in the LICENSE file.
#include "bin/dartutils.h"
+#include "bin/dbg_connection.h"
+#include "bin/eventhandler.h"
#include "bin/io_buffer.h"
#include "bin/platform.h"
#include "bin/process.h"
@@ -218,6 +220,9 @@
DartUtils::GetInt64Value(Dart_GetNativeArgument(args, 0), &status);
Dart_ExitIsolate();
Dart_Cleanup();
+ DebuggerConnectionHandler::StopHandler();
+ // TODO(zra): Stop the EventHandler once thread shutdown is enabled.
+ // EventHandler::Stop();
exit(static_cast<int>(status));
}
diff --git a/runtime/bin/secure_socket.cc b/runtime/bin/secure_socket.cc
index c32301d..0670683 100644
--- a/runtime/bin/secure_socket.cc
+++ b/runtime/bin/secure_socket.cc
@@ -100,14 +100,28 @@
}
+static void FreeSecurityContext(
+ void* isolate_data,
+ Dart_WeakPersistentHandle handle,
+ void* context_pointer) {
+ SSL_CTX* context = static_cast<SSL_CTX*>(context_pointer);
+ SSL_CTX_free(context);
+}
+
+
static void SetSecurityContext(Dart_NativeArguments args,
SSL_CTX* context) {
+ const int approximate_size_of_context = 1500;
Dart_Handle dart_this = ThrowIfError(Dart_GetNativeArgument(args, 0));
ASSERT(Dart_IsInstance(dart_this));
ThrowIfError(Dart_SetNativeInstanceField(
dart_this,
kSecurityContextNativeFieldIndex,
reinterpret_cast<intptr_t>(context)));
+ Dart_NewWeakPersistentHandle(dart_this,
+ context,
+ approximate_size_of_context,
+ FreeSecurityContext);
}
@@ -313,9 +327,6 @@
SSL_CTX_set_cipher_list(context, "HIGH:MEDIUM");
SSL_CTX_set_cipher_list_tls11(context, "HIGH:MEDIUM");
SetSecurityContext(args, context);
- // TODO(whesse): Use WeakPersistentHandle to free the SSL_CTX
- // when the object is GC'd. Also free the alpn_select_cb data pointer,
- // if non-null (allocated in SetAlpnProtocolList).
}
@@ -825,7 +836,9 @@
// TODO(whesse): If this function is called again, free the previous
// protocol_string_copy. It may be better to keep this as a native
// field on the Dart object, since fetching it from the structure is
- // not in the public api. Also free this when the context is destroyed.
+ // not in the public api.
+ // Also free protocol_string_copy when the context is destroyed,
+ // in FreeSecurityContext()
} else {
// The function makes a local copy of protocol_string, which it owns.
if (ssl != NULL) {
@@ -1022,6 +1035,10 @@
SSL_free(ssl_);
ssl_ = NULL;
}
+ if (socket_side_ != NULL) {
+ BIO_free(socket_side_);
+ socket_side_ = NULL;
+ }
for (int i = 0; i < kNumBuffers; ++i) {
Dart_DeletePersistentHandle(dart_buffer_objects_[i]);
delete[] buffers_[i];
diff --git a/runtime/bin/secure_socket.h b/runtime/bin/secure_socket.h
index cd3611a..2af0055 100644
--- a/runtime/bin/secure_socket.h
+++ b/runtime/bin/secure_socket.h
@@ -54,6 +54,7 @@
SSLFilter()
: callback_error(NULL),
ssl_(NULL),
+ socket_side_(NULL),
string_start_(NULL),
string_length_(NULL),
handshake_complete_(NULL),
diff --git a/runtime/include/dart_api.h b/runtime/include/dart_api.h
index 8b9070c..15114a6 100755
--- a/runtime/include/dart_api.h
+++ b/runtime/include/dart_api.h
@@ -852,6 +852,8 @@
*
* \param vm_isolate_snapshot A buffer containing a snapshot of the VM isolate
* or NULL if no snapshot is provided.
+ * \param instructions_snapshot A buffer containing a snapshot of precompiled
+ * instructions, or NULL if no snapshot is provided.
* \param create A function to be called during isolate creation.
* See Dart_IsolateCreateCallback.
* \param interrupt A function to be called when an isolate is interrupted.
@@ -2859,4 +2861,21 @@
*/
DART_EXPORT Dart_Port Dart_ServiceWaitForLoadPort();
+
+/*
+ * ==============
+ * Precompilation
+ * ==============
+ */
+
+
+DART_EXPORT Dart_Handle Dart_Precompile();
+DART_EXPORT Dart_Handle Dart_CreatePrecompiledSnapshot(
+ uint8_t** vm_isolate_snapshot_buffer,
+ intptr_t* vm_isolate_snapshot_size,
+ uint8_t** isolate_snapshot_buffer,
+ intptr_t* isolate_snapshot_size,
+ uint8_t** instructions_snapshot_buffer,
+ intptr_t* instructions_snapshot_size);
+
#endif /* INCLUDE_DART_API_H_ */ /* NOLINT */
diff --git a/runtime/include/dart_native_api.h b/runtime/include/dart_native_api.h
index 5a27249..ea7900d 100644
--- a/runtime/include/dart_native_api.h
+++ b/runtime/include/dart_native_api.h
@@ -159,6 +159,5 @@
* TODO(turnidge): Document.
*/
DART_EXPORT Dart_Handle Dart_CompileAll();
-DART_EXPORT Dart_Handle Dart_Precompile();
#endif /* INCLUDE_DART_NATIVE_API_H_ */ /* NOLINT */
diff --git a/runtime/lib/mirrors.cc b/runtime/lib/mirrors.cc
index d68e758..c1a869a 100644
--- a/runtime/lib/mirrors.cc
+++ b/runtime/lib/mirrors.cc
@@ -109,7 +109,7 @@
static RawInstance* CreateParameterMirrorList(const Function& func,
const Instance& owner_mirror) {
- HANDLESCOPE(Isolate::Current());
+ HANDLESCOPE(Thread::Current());
const intptr_t implicit_param_count = func.NumImplicitParameters();
const intptr_t non_implicit_param_count = func.NumParameters() -
implicit_param_count;
diff --git a/runtime/observatory/lib/src/elements/debugger.dart b/runtime/observatory/lib/src/elements/debugger.dart
index ae16694..f652da1 100644
--- a/runtime/observatory/lib/src/elements/debugger.dart
+++ b/runtime/observatory/lib/src/elements/debugger.dart
@@ -621,7 +621,7 @@
'Set a debugger option.\n'
'\n'
'Known options:\n'
- ' break-on-exceptions # Should the debugger break on exceptions?\n'
+ ' break-on-exception # Should the debugger break on exceptions?\n'
" # ${_boeValues}\n"
' up-is-down # Reverse meaning of up/down commands?\n'
" # ${_boolValues}\n"
diff --git a/runtime/vm/ast.h b/runtime/vm/ast.h
index 32fd18d..7b4ae79 100644
--- a/runtime/vm/ast.h
+++ b/runtime/vm/ast.h
@@ -165,13 +165,15 @@
LocalVariable* saved_try_ctx,
LocalVariable* async_saved_try_ctx,
LocalVariable* outer_saved_try_ctx,
- LocalVariable* outer_async_saved_try_ctx)
+ LocalVariable* outer_async_saved_try_ctx,
+ LocalScope* scope)
: AstNode(token_pos),
expr_(expr),
saved_try_ctx_(saved_try_ctx),
async_saved_try_ctx_(async_saved_try_ctx),
outer_saved_try_ctx_(outer_saved_try_ctx),
- outer_async_saved_try_ctx_(outer_async_saved_try_ctx) { }
+ outer_async_saved_try_ctx_(outer_async_saved_try_ctx),
+ scope_(scope) { }
void VisitChildren(AstNodeVisitor* visitor) const {
expr_->Visit(visitor);
@@ -184,6 +186,7 @@
LocalVariable* outer_async_saved_try_ctx() const {
return outer_async_saved_try_ctx_;
}
+ LocalScope* scope() const { return scope_; }
DECLARE_COMMON_NODE_FUNCTIONS(AwaitNode);
@@ -193,6 +196,7 @@
LocalVariable* async_saved_try_ctx_;
LocalVariable* outer_saved_try_ctx_;
LocalVariable* outer_async_saved_try_ctx_;
+ LocalScope* scope_;
DISALLOW_COPY_AND_ASSIGN(AwaitNode);
};
@@ -209,17 +213,25 @@
// <AwaitMarker> -> ...
class AwaitMarkerNode : public AstNode {
public:
- AwaitMarkerNode() : AstNode(Scanner::kNoSourcePos) { }
+ AwaitMarkerNode(LocalScope* async_scope, LocalScope* await_scope)
+ : AstNode(Scanner::kNoSourcePos),
+ async_scope_(async_scope),
+ await_scope_(await_scope) {
+ ASSERT(async_scope != NULL);
+ ASSERT(await_scope != NULL);
+ await_scope->CaptureLocalVariables(async_scope);
+ }
void VisitChildren(AstNodeVisitor* visitor) const { }
- LocalScope* scope() const { return scope_; }
- void set_scope(LocalScope* scope) { scope_ = scope; }
+ LocalScope* async_scope() const { return async_scope_; }
+ LocalScope* await_scope() const { return await_scope_; }
DECLARE_COMMON_NODE_FUNCTIONS(AwaitMarkerNode);
private:
- LocalScope* scope_;
+ LocalScope* async_scope_;
+ LocalScope* await_scope_;
DISALLOW_COPY_AND_ASSIGN(AwaitMarkerNode);
};
diff --git a/runtime/vm/ast_printer.cc b/runtime/vm/ast_printer.cc
index 4877eac..aa5c29f 100644
--- a/runtime/vm/ast_printer.cc
+++ b/runtime/vm/ast_printer.cc
@@ -191,17 +191,22 @@
void AstPrinter::VisitAwaitNode(AwaitNode* node) {
- VisitGenericAstNode(node);
+ ISL_Print("(*****%s***** (scope \"%p\") ", node->PrettyName(), node->scope());
+ node->VisitChildren(this);
+ ISL_Print(")");
}
void AstPrinter::VisitAwaitMarkerNode(AwaitMarkerNode* node) {
- VisitGenericAstNode(node);
+ ISL_Print("(%s (async_scope \"%p\" await_scope \"%p\"))",
+ node->PrettyName(),
+ node->async_scope(),
+ node->await_scope());
}
void AstPrinter::VisitPrimaryNode(PrimaryNode* node) {
- ISL_Print("*****%s***** \"%s\")",
+ ISL_Print("(*****%s***** \"%s\")",
node->PrettyName(),
node->primary().ToCString());
}
@@ -506,7 +511,7 @@
void AstPrinter::PrintFunctionScope(const ParsedFunction& parsed_function) {
- HANDLESCOPE(Isolate::Current());
+ HANDLESCOPE(parsed_function.thread());
const Function& function = parsed_function.function();
SequenceNode* node_sequence = parsed_function.node_sequence();
ASSERT(node_sequence != NULL);
@@ -558,7 +563,7 @@
void AstPrinter::PrintFunctionNodes(const ParsedFunction& parsed_function) {
- HANDLESCOPE(Isolate::Current());
+ HANDLESCOPE(parsed_function.thread());
SequenceNode* node_sequence = parsed_function.node_sequence();
ASSERT(node_sequence != NULL);
AstPrinter ast_printer;
diff --git a/runtime/vm/ast_transformer.cc b/runtime/vm/ast_transformer.cc
index 11cb61c..76faa89 100644
--- a/runtime/vm/ast_transformer.cc
+++ b/runtime/vm/ast_transformer.cc
@@ -46,12 +46,12 @@
#undef DEFINE_UNREACHABLE
AwaitTransformer::AwaitTransformer(SequenceNode* preamble,
- LocalScope* function_top)
+ LocalScope* async_temp_scope)
: preamble_(preamble),
temp_cnt_(0),
- function_top_(function_top),
+ async_temp_scope_(async_temp_scope),
thread_(Thread::Current()) {
- ASSERT(function_top_ != NULL);
+ ASSERT(async_temp_scope_ != NULL);
}
@@ -62,18 +62,16 @@
LocalVariable* AwaitTransformer::EnsureCurrentTempVar() {
- const char* await_temp_prefix = ":await_temp_var_";
- const String& cnt_str = String::ZoneHandle(
- Z, String::NewFormatted("%s%d", await_temp_prefix, temp_cnt_));
- const String& symbol = String::ZoneHandle(Z, Symbols::New(cnt_str));
+ String& symbol = String::ZoneHandle(Z, String::NewFormatted("%d", temp_cnt_));
+ symbol = Symbols::FromConcat(Symbols::AwaitTempVarPrefix(), symbol);
ASSERT(!symbol.IsNull());
// Look up the variable in the scope used for async temp variables.
- LocalVariable* await_tmp = function_top_->LocalLookupVariable(symbol);
+ LocalVariable* await_tmp = async_temp_scope_->LocalLookupVariable(symbol);
if (await_tmp == NULL) {
// We need a new temp variable; add it to the function's top scope.
await_tmp = new (Z) LocalVariable(
Scanner::kNoSourcePos, symbol, Type::ZoneHandle(Type::DynamicType()));
- function_top_->AddVariable(await_tmp);
+ async_temp_scope_->AddVariable(await_tmp);
// After adding it to the top scope, we can look it up from the preamble.
// The following call includes an ASSERT check.
await_tmp = GetVariableInScope(preamble_->scope(), symbol);
@@ -136,8 +134,8 @@
AstNode* transformed_expr = Transform(node->expr());
LocalVariable* await_temp = AddToPreambleNewTempVar(transformed_expr);
- AwaitMarkerNode* await_marker = new (Z) AwaitMarkerNode();
- await_marker->set_scope(preamble_->scope());
+ AwaitMarkerNode* await_marker =
+ new (Z) AwaitMarkerNode(async_temp_scope_, node->scope());
preamble_->Add(await_marker);
// :result_param = _awaitHelper(
@@ -562,7 +560,7 @@
// added to a scope, and the subsequent nodes that are added to the
// preample can access them.
for (intptr_t i = 0; i < node->num_temps(); i++) {
- function_top_->AddVariable(node->TempAt(i));
+ async_temp_scope_->AddVariable(node->TempAt(i));
AstNode* new_init_val = Transform(node->InitializerAt(i));
preamble_->Add(new(Z) StoreLocalNode(node->token_pos(),
node->TempAt(i),
diff --git a/runtime/vm/ast_transformer.h b/runtime/vm/ast_transformer.h
index 807f7cf..e9f6791 100644
--- a/runtime/vm/ast_transformer.h
+++ b/runtime/vm/ast_transformer.h
@@ -39,7 +39,7 @@
//
class AwaitTransformer : public AstNodeVisitor {
public:
- AwaitTransformer(SequenceNode* preamble, LocalScope* function_top);
+ AwaitTransformer(SequenceNode* preamble, LocalScope* async_temp_scope);
#define DECLARE_VISIT(BaseName) \
virtual void Visit##BaseName##Node(BaseName##Node* node);
@@ -66,7 +66,7 @@
SequenceNode* preamble_;
int32_t temp_cnt_;
AstNode* result_;
- LocalScope* function_top_;
+ LocalScope* async_temp_scope_;
Thread* thread_;
diff --git a/runtime/vm/benchmark_test.cc b/runtime/vm/benchmark_test.cc
index b65d639..ee3ca57 100644
--- a/runtime/vm/benchmark_test.cc
+++ b/runtime/vm/benchmark_test.cc
@@ -353,8 +353,7 @@
char* dart_root = ComputeDart2JSPath(Benchmark::Executable());
char* script = NULL;
if (dart_root != NULL) {
- Isolate* isolate = Isolate::Current();
- HANDLESCOPE(isolate);
+ HANDLESCOPE(thread);
const char* kFormatStr =
"import '%s/pkg/compiler/lib/compiler.dart';";
intptr_t len = OS::SNPrint(NULL, 0, kFormatStr, dart_root) + 1;
@@ -502,8 +501,10 @@
// Write snapshot with object content.
FullSnapshotWriter writer(&vm_isolate_snapshot_buffer,
&isolate_snapshot_buffer,
+ NULL, /* instructions_snapshot_buffer */
&malloc_allocator,
- false /* snapshot_code */);
+ false, /* snapshot_code */
+ true /* vm_isolate_is_symbolic */);
writer.WriteFullSnapshot();
const Snapshot* snapshot = Snapshot::SetupFromBuffer(isolate_snapshot_buffer);
ASSERT(snapshot->kind() == Snapshot::kFull);
@@ -537,8 +538,10 @@
// Write snapshot with object content.
FullSnapshotWriter writer(&vm_isolate_snapshot_buffer,
&isolate_snapshot_buffer,
+ NULL, /* instructions_snapshot_buffer */
&malloc_allocator,
- false /* snapshot_code */);
+ false, /* snapshot_code */
+ true /* vm_isolate_is_symbolic */);
writer.WriteFullSnapshot();
const Snapshot* snapshot = Snapshot::SetupFromBuffer(isolate_snapshot_buffer);
ASSERT(snapshot->kind() == Snapshot::kFull);
@@ -595,12 +598,11 @@
BENCHMARK(SerializeNull) {
const Object& null_object = Object::Handle();
const intptr_t kLoopCount = 1000000;
- Isolate* isolate = Isolate::Current();
uint8_t* buffer;
Timer timer(true, "Serialize Null");
timer.Start();
for (intptr_t i = 0; i < kLoopCount; i++) {
- StackZone zone(isolate);
+ StackZone zone(thread);
MessageWriter writer(&buffer, &message_allocator, true);
writer.WriteMessage(null_object);
intptr_t buffer_len = writer.BytesWritten();
@@ -608,8 +610,7 @@
// Read object back from the snapshot.
MessageSnapshotReader reader(buffer,
buffer_len,
- isolate,
- zone.GetZone());
+ thread);
reader.ReadObject();
}
timer.Stop();
@@ -621,12 +622,11 @@
BENCHMARK(SerializeSmi) {
const Integer& smi_object = Integer::Handle(Smi::New(42));
const intptr_t kLoopCount = 1000000;
- Isolate* isolate = Isolate::Current();
uint8_t* buffer;
Timer timer(true, "Serialize Smi");
timer.Start();
for (intptr_t i = 0; i < kLoopCount; i++) {
- StackZone zone(isolate);
+ StackZone zone(thread);
MessageWriter writer(&buffer, &message_allocator, true);
writer.WriteMessage(smi_object);
intptr_t buffer_len = writer.BytesWritten();
@@ -634,8 +634,7 @@
// Read object back from the snapshot.
MessageSnapshotReader reader(buffer,
buffer_len,
- isolate,
- zone.GetZone());
+ thread);
reader.ReadObject();
}
timer.Stop();
@@ -649,12 +648,11 @@
array_object.SetAt(0, Integer::Handle(Smi::New(42)));
array_object.SetAt(1, Object::Handle());
const intptr_t kLoopCount = 1000000;
- Isolate* isolate = Isolate::Current();
uint8_t* buffer;
Timer timer(true, "Simple Message");
timer.Start();
for (intptr_t i = 0; i < kLoopCount; i++) {
- StackZone zone(isolate);
+ StackZone zone(thread);
MessageWriter writer(&buffer, &malloc_allocator, true);
writer.WriteMessage(array_object);
intptr_t buffer_len = writer.BytesWritten();
@@ -662,8 +660,7 @@
// Read object back from the snapshot.
MessageSnapshotReader reader(buffer,
buffer_len,
- isolate,
- zone.GetZone());
+ thread);
reader.ReadObject();
free(buffer);
}
@@ -687,12 +684,11 @@
Instance& map = Instance::Handle();
map ^= Api::UnwrapHandle(h_result);
const intptr_t kLoopCount = 100;
- Isolate* isolate = Isolate::Current();
uint8_t* buffer;
Timer timer(true, "Large Map");
timer.Start();
for (intptr_t i = 0; i < kLoopCount; i++) {
- StackZone zone(isolate);
+ StackZone zone(thread);
MessageWriter writer(&buffer, &malloc_allocator, true);
writer.WriteMessage(map);
intptr_t buffer_len = writer.BytesWritten();
@@ -700,8 +696,7 @@
// Read object back from the snapshot.
MessageSnapshotReader reader(buffer,
buffer_len,
- isolate,
- zone.GetZone());
+ thread);
reader.ReadObject();
free(buffer);
}
diff --git a/runtime/vm/benchmark_test.h b/runtime/vm/benchmark_test.h
index a91bc01..615965c 100644
--- a/runtime/vm/benchmark_test.h
+++ b/runtime/vm/benchmark_test.h
@@ -34,7 +34,7 @@
#define BENCHMARK_HELPER(name, kind) \
void Dart_Benchmark##name(Benchmark* benchmark); \
static Benchmark kRegister##name(Dart_Benchmark##name, #name, kind); \
- static void Dart_BenchmarkHelper##name(Benchmark* benchmark); \
+ static void Dart_BenchmarkHelper##name(Benchmark* benchmark, Thread* thread);\
void Dart_Benchmark##name(Benchmark* benchmark) { \
FLAG_old_gen_growth_space_ratio = 100; \
BenchmarkIsolateScope __isolate__(benchmark); \
@@ -42,9 +42,9 @@
ASSERT(__thread__->isolate() == benchmark->isolate()); \
StackZone __zone__(__thread__); \
HandleScope __hs__(__thread__); \
- Dart_BenchmarkHelper##name(benchmark); \
+ Dart_BenchmarkHelper##name(benchmark, __thread__); \
} \
- static void Dart_BenchmarkHelper##name(Benchmark* benchmark)
+ static void Dart_BenchmarkHelper##name(Benchmark* benchmark, Thread* thread)
#define BENCHMARK(name) BENCHMARK_HELPER(name, "RunTime")
#define BENCHMARK_SIZE(name) BENCHMARK_HELPER(name, "CodeSize")
diff --git a/runtime/vm/bit_vector_test.cc b/runtime/vm/bit_vector_test.cc
index 4c803d9..d2b7d1a 100644
--- a/runtime/vm/bit_vector_test.cc
+++ b/runtime/vm/bit_vector_test.cc
@@ -8,7 +8,7 @@
namespace dart {
-#define Z Thread::Current()->zone()
+#define Z (thread->zone())
TEST_CASE(BitVector) {
{ BitVector* v = new BitVector(Z, 15);
diff --git a/runtime/vm/bootstrap.cc b/runtime/vm/bootstrap.cc
index a9b9485..912aa1f 100644
--- a/runtime/vm/bootstrap.cc
+++ b/runtime/vm/bootstrap.cc
@@ -253,7 +253,8 @@
RawError* Bootstrap::LoadandCompileScripts() {
- Isolate* isolate = Isolate::Current();
+ Thread* thread = Thread::Current();
+ Isolate* isolate = thread->isolate();
String& uri = String::Handle(isolate);
String& patch_uri = String::Handle(isolate);
String& source = String::Handle(isolate);
@@ -266,7 +267,7 @@
// library tag handler so that we can load all the bootstrap libraries.
isolate->set_library_tag_handler(BootstrapLibraryTagHandler);
- HANDLESCOPE(isolate);
+ HANDLESCOPE(thread);
// Create library objects for all the bootstrap libraries.
for (intptr_t i = 0;
diff --git a/runtime/vm/class_finalizer.cc b/runtime/vm/class_finalizer.cc
index 48bbfce..fc4dfad 100644
--- a/runtime/vm/class_finalizer.cc
+++ b/runtime/vm/class_finalizer.cc
@@ -116,9 +116,10 @@
// a) when bootstrap process completes (VerifyBootstrapClasses).
// b) after the user classes are loaded (dart_api).
bool ClassFinalizer::ProcessPendingClasses() {
- Isolate* isolate = Isolate::Current();
+ Thread* thread = Thread::Current();
+ Isolate* isolate = thread->isolate();
ASSERT(isolate != NULL);
- HANDLESCOPE(isolate);
+ HANDLESCOPE(thread);
ObjectStore* object_store = isolate->object_store();
const Error& error = Error::Handle(isolate, object_store->sticky_error());
if (!error.IsNull()) {
@@ -523,7 +524,7 @@
void ClassFinalizer::FinalizeTypeParameters(
const Class& cls,
- GrowableObjectArray* pending_types) {
+ PendingTypes* pending_types) {
if (FLAG_trace_type_finalization) {
ISL_Print("Finalizing type parameters of '%s'\n",
String::Handle(cls.Name()).ToCString());
@@ -561,7 +562,7 @@
// pending finalization that are mutually recursive with the checked type.
void ClassFinalizer::CheckRecursiveType(const Class& cls,
const Type& type,
- GrowableObjectArray* pending_types) {
+ PendingTypes* pending_types) {
Isolate* isolate = Isolate::Current();
if (FLAG_trace_type_finalization) {
ISL_Print("Checking recursive type '%s': %s\n",
@@ -589,11 +590,10 @@
// The type parameters are not instantiated. Verify that there is no other
// type pending finalization with the same type class, but different
// uninstantiated type parameters.
- Type& pending_type = Type::Handle(isolate);
TypeArguments& pending_arguments = TypeArguments::Handle(isolate);
- const intptr_t num_pending_types = pending_types->Length();
+ const intptr_t num_pending_types = pending_types->length();
for (intptr_t i = num_pending_types - 1; i >= 0; i--) {
- pending_type ^= pending_types->At(i);
+ const Type& pending_type = Type::Cast(pending_types->At(i));
if (FLAG_trace_type_finalization) {
ISL_Print(" Comparing with pending type '%s': %s\n",
String::Handle(pending_type.Name()).ToCString(),
@@ -655,7 +655,7 @@
const TypeArguments& arguments,
intptr_t num_uninitialized_arguments,
Error* bound_error,
- GrowableObjectArray* pending_types,
+ PendingTypes* pending_types,
TrailPtr trail) {
ASSERT(arguments.Length() >= cls.NumTypeArguments());
if (!cls.is_type_finalized()) {
@@ -906,7 +906,7 @@
const Class& cls,
const AbstractType& type,
FinalizationKind finalization,
- GrowableObjectArray* pending_types) {
+ PendingTypes* pending_types) {
// Only the 'root' type of the graph can be canonicalized, after all depending
// types have been bound checked.
ASSERT((pending_types == NULL) || (finalization < kCanonicalize));
@@ -981,10 +981,8 @@
// This type is the root type of the type graph if no pending types queue is
// allocated yet.
const bool is_root_type = (pending_types == NULL);
- GrowableObjectArray& types = GrowableObjectArray::Handle(Z);
if (is_root_type) {
- types = GrowableObjectArray::New();
- pending_types = &types;
+ pending_types = new PendingTypes(Z, 4);
}
// The type class does not need to be finalized in order to finalize the type,
@@ -1120,10 +1118,8 @@
// If we are done finalizing a graph of mutually recursive types, check their
// bounds.
if (is_root_type) {
- Type& type = Type::Handle(Z);
- for (intptr_t i = types.Length() - 1; i >= 0; i--) {
- type ^= types.At(i);
- CheckTypeBounds(cls, type);
+ for (intptr_t i = pending_types->length() - 1; i >= 0; i--) {
+ CheckTypeBounds(cls, Type::Cast(pending_types->At(i)));
if (FLAG_trace_type_finalization && type.IsRecursive()) {
ISL_Print("Done finalizing recursive type '%s': %s\n",
String::Handle(Z, type.Name()).ToCString(),
@@ -2007,7 +2003,7 @@
void ClassFinalizer::ApplyMixinType(const Class& mixin_app_class,
- GrowableObjectArray* pending_types) {
+ PendingTypes* pending_types) {
if (mixin_app_class.is_mixin_type_applied()) {
return;
}
@@ -2227,7 +2223,8 @@
void ClassFinalizer::FinalizeTypesInClass(const Class& cls) {
- HANDLESCOPE(Isolate::Current());
+ Thread* thread = Thread::Current();
+ HANDLESCOPE(thread);
if (cls.is_type_finalized()) {
return;
}
@@ -2360,7 +2357,8 @@
void ClassFinalizer::FinalizeClass(const Class& cls) {
- HANDLESCOPE(Isolate::Current());
+ Thread* thread = Thread::Current();
+ HANDLESCOPE(thread);
if (cls.is_finalized()) {
return;
}
@@ -2990,7 +2988,8 @@
void ClassFinalizer::PrintClassInformation(const Class& cls) {
- HANDLESCOPE(Isolate::Current());
+ Thread* thread = Thread::Current();
+ HANDLESCOPE(thread);
const String& class_name = String::Handle(cls.Name());
ISL_Print("class '%s'", class_name.ToCString());
const Library& library = Library::Handle(cls.library());
diff --git a/runtime/vm/class_finalizer.h b/runtime/vm/class_finalizer.h
index a43689f..0b8d7c5 100644
--- a/runtime/vm/class_finalizer.h
+++ b/runtime/vm/class_finalizer.h
@@ -15,6 +15,8 @@
// finalized.
class ClassFinalizer : public AllStatic {
public:
+ typedef ZoneGrowableHandlePtrArray<const AbstractType> PendingTypes;
+
// Modes for type resolution and finalization. The ordering is relevant.
enum FinalizationKind {
kIgnore, // Type is ignored and replaced by dynamic.
@@ -32,7 +34,7 @@
const Class& cls,
const AbstractType& type,
FinalizationKind finalization,
- GrowableObjectArray* pending_types = NULL);
+ PendingTypes* pending_types = NULL);
// Allocate, finalize, and return a new malformed type as if it was declared
// in class cls at the given token position.
@@ -95,7 +97,7 @@
// Apply the mixin type to the mixin application class.
static void ApplyMixinType(const Class& mixin_app_class,
- GrowableObjectArray* pending_types = NULL);
+ PendingTypes* pending_types = NULL);
private:
static void AllocateEnumValues(const Class& enum_cls);
@@ -130,16 +132,16 @@
static void ResolveSuperTypeAndInterfaces(const Class& cls,
GrowableArray<intptr_t>* visited);
static void FinalizeTypeParameters(const Class& cls,
- GrowableObjectArray* pending_types = NULL);
+ PendingTypes* pending_types = NULL);
static void FinalizeTypeArguments(const Class& cls,
const TypeArguments& arguments,
intptr_t num_uninitialized_arguments,
Error* bound_error,
- GrowableObjectArray* pending_types,
+ PendingTypes* pending_types,
TrailPtr trail);
static void CheckRecursiveType(const Class& cls,
const Type& type,
- GrowableObjectArray* pending_types);
+ PendingTypes* pending_types);
static void CheckTypeBounds(const Class& cls, const Type& type);
static void CheckTypeArgumentBounds(const Class& cls,
const TypeArguments& arguments,
diff --git a/runtime/vm/compiler.cc b/runtime/vm/compiler.cc
index 4ba0378..8b96530 100644
--- a/runtime/vm/compiler.cc
+++ b/runtime/vm/compiler.cc
@@ -212,9 +212,10 @@
}
-static void AddRelatedClassesToList(const Class& cls,
- const GrowableObjectArray& parse_list,
- const GrowableObjectArray& patch_list) {
+static void AddRelatedClassesToList(
+ const Class& cls,
+ GrowableHandlePtrArray<const Class>* parse_list,
+ GrowableHandlePtrArray<const Class>* patch_list) {
Isolate* isolate = Isolate::Current();
Class& parse_class = Class::Handle(isolate);
AbstractType& interface_type = Type::Handle(isolate);
@@ -228,7 +229,7 @@
interface_type ^= interfaces.At(i);
parse_class ^= interface_type.type_class();
if (!parse_class.is_finalized() && !parse_class.is_marked_for_parsing()) {
- parse_list.Add(parse_class);
+ parse_list->Add(parse_class);
parse_class.set_is_marked_for_parsing();
}
}
@@ -239,7 +240,7 @@
parse_class ^= cls.SuperClass();
while (!parse_class.IsNull()) {
if (!parse_class.is_finalized() && !parse_class.is_marked_for_parsing()) {
- parse_list.Add(parse_class);
+ parse_list->Add(parse_class);
parse_class.set_is_marked_for_parsing();
}
parse_class ^= parse_class.SuperClass();
@@ -251,7 +252,7 @@
parse_class ^= cls.patch_class();
if (!parse_class.IsNull()) {
if (!parse_class.is_finalized() && !parse_class.is_marked_for_parsing()) {
- patch_list.Add(parse_class);
+ patch_list->Add(parse_class);
parse_class.set_is_marked_for_parsing();
}
}
@@ -291,20 +292,17 @@
Thread* const thread = Thread::Current();
Isolate* const isolate = thread->isolate();
+ StackZone zone(thread);
// We remember all the classes that are being compiled in these lists. This
// also allows us to reset the marked_for_parsing state in case we see an
// error.
VMTagScope tagScope(thread, VMTag::kCompileClassTagId);
- Class& parse_class = Class::Handle(isolate);
- const GrowableObjectArray& parse_list =
- GrowableObjectArray::Handle(thread->zone(), GrowableObjectArray::New(4));
- const GrowableObjectArray& patch_list =
- GrowableObjectArray::Handle(thread->zone(), GrowableObjectArray::New(4));
+ GrowableHandlePtrArray<const Class> parse_list(thread->zone(), 4);
+ GrowableHandlePtrArray<const Class> patch_list(thread->zone(), 4);
// Parse the class and all the interfaces it implements and super classes.
LongJumpScope jump;
if (setjmp(*jump.Set()) == 0) {
- StackZone zone(thread);
if (FLAG_trace_compiler) {
ISL_Print("Compiling Class %s '%s'\n", "", cls.ToCString());
}
@@ -321,34 +319,33 @@
// to it by AddRelatedClassesToList. It is not OK to hoist
// parse_list.Length() into a local variable and iterate using the local
// variable.
- for (intptr_t i = 0; i < parse_list.Length(); i++) {
- parse_class ^= parse_list.At(i);
- AddRelatedClassesToList(parse_class, parse_list, patch_list);
+ for (intptr_t i = 0; i < parse_list.length(); i++) {
+ AddRelatedClassesToList(parse_list.At(i), &parse_list, &patch_list);
}
// Parse all the classes that have been added above.
- for (intptr_t i = (parse_list.Length() - 1); i >=0 ; i--) {
- parse_class ^= parse_list.At(i);
+ for (intptr_t i = (parse_list.length() - 1); i >=0 ; i--) {
+ const Class& parse_class = parse_list.At(i);
ASSERT(!parse_class.IsNull());
Parser::ParseClass(parse_class);
}
// Parse all the patch classes that have been added above.
- for (intptr_t i = 0; i < patch_list.Length(); i++) {
- parse_class ^= patch_list.At(i);
+ for (intptr_t i = 0; i < patch_list.length(); i++) {
+ const Class& parse_class = patch_list.At(i);
ASSERT(!parse_class.IsNull());
Parser::ParseClass(parse_class);
}
// Finalize these classes.
- for (intptr_t i = (parse_list.Length() - 1); i >=0 ; i--) {
- parse_class ^= parse_list.At(i);
+ for (intptr_t i = (parse_list.length() - 1); i >=0 ; i--) {
+ const Class& parse_class = parse_list.At(i);
ASSERT(!parse_class.IsNull());
ClassFinalizer::FinalizeClass(parse_class);
parse_class.reset_is_marked_for_parsing();
}
- for (intptr_t i = (patch_list.Length() - 1); i >=0 ; i--) {
- parse_class ^= patch_list.At(i);
+ for (intptr_t i = (patch_list.length() - 1); i >=0 ; i--) {
+ const Class& parse_class = patch_list.At(i);
ASSERT(!parse_class.IsNull());
ClassFinalizer::FinalizeClass(parse_class);
parse_class.reset_is_marked_for_parsing();
@@ -357,21 +354,18 @@
return Error::null();
} else {
// Reset the marked for parsing flags.
- for (intptr_t i = 0; i < parse_list.Length(); i++) {
- parse_class ^= parse_list.At(i);
+ for (intptr_t i = 0; i < parse_list.length(); i++) {
+ const Class& parse_class = parse_list.At(i);
if (parse_class.is_marked_for_parsing()) {
parse_class.reset_is_marked_for_parsing();
}
}
- for (intptr_t i = 0; i < patch_list.Length(); i++) {
- parse_class ^= patch_list.At(i);
+ for (intptr_t i = 0; i < patch_list.length(); i++) {
+ const Class& parse_class = patch_list.At(i);
if (parse_class.is_marked_for_parsing()) {
parse_class.reset_is_marked_for_parsing();
}
}
- Thread* const thread = Thread::Current();
- Isolate* const isolate = Isolate::Current();
- StackZone zone(thread);
Error& error = Error::Handle(isolate);
error = isolate->object_store()->sticky_error();
isolate->object_store()->clear_sticky_error();
diff --git a/runtime/vm/coverage.cc b/runtime/vm/coverage.cc
index cef0201..7892e37 100644
--- a/runtime/vm/coverage.cc
+++ b/runtime/vm/coverage.cc
@@ -72,7 +72,6 @@
}
Thread* thread = Thread::Current();
Zone* zone = thread->zone();
- Isolate* isolate = thread->isolate();
// Make sure we have the unoptimized code for this function available.
if (Compiler::EnsureUnoptimizedCode(thread, function) != Error::null()) {
// Ignore the error and this function entirely.
@@ -96,7 +95,7 @@
PcDescriptors::Iterator iter(descriptors,
RawPcDescriptors::kIcCall | RawPcDescriptors::kUnoptStaticCall);
while (iter.MoveNext()) {
- HANDLESCOPE(isolate);
+ HANDLESCOPE(thread);
const ICData* ic_data = (*ic_data_array)[iter.DeoptId()];
if (!ic_data->IsNull()) {
const intptr_t token_pos = iter.TokenPos();
@@ -141,7 +140,8 @@
const JSONArray& jsarr,
CoverageFilter* filter,
bool as_call_sites) {
- Isolate* isolate = Isolate::Current();
+ Thread* thread = Thread::Current();
+ Isolate* isolate = thread->isolate();
if (cls.EnsureIsFinalized(isolate) != Error::null()) {
// Only classes that have been finalized do have a meaningful list of
// functions.
@@ -156,7 +156,7 @@
GrowableArray<intptr_t> pos_to_line;
int i = 0;
while (i < functions.Length()) {
- HANDLESCOPE(isolate);
+ HANDLESCOPE(thread);
function ^= functions.At(i);
script = function.script();
saved_url = script.url();
@@ -201,7 +201,7 @@
// We need to keep rechecking the length of the closures array, as handling
// a closure potentially adds new entries to the end.
while (i < closures.Length()) {
- HANDLESCOPE(isolate);
+ HANDLESCOPE(thread);
function ^= closures.At(i);
script = function.script();
saved_url = script.url();
@@ -248,7 +248,7 @@
JSONStream stream;
PrintJSON(isolate, &stream, NULL, false);
- const char* format = "%s/dart-cov-%" Pd "-%" Pd ".json";
+ const char* format = "%s/dart-cov-%" Pd "-%" Pd64 ".json";
intptr_t pid = OS::ProcessId();
intptr_t len = OS::SNPrint(NULL, 0, format,
FLAG_coverage_dir, pid, isolate->main_port());
diff --git a/runtime/vm/dart.cc b/runtime/vm/dart.cc
index 70b0504..e59c411 100644
--- a/runtime/vm/dart.cc
+++ b/runtime/vm/dart.cc
@@ -113,6 +113,8 @@
ASSERT(thread_pool_ == NULL);
thread_pool_ = new ThreadPool();
{
+ Thread* T = Thread::Current();
+ ASSERT(T != NULL);
ASSERT(vm_isolate_ == NULL);
ASSERT(Flags::Initialized());
const bool is_vm_isolate = true;
@@ -122,9 +124,12 @@
Dart_IsolateFlags api_flags;
vm_flags.CopyTo(&api_flags);
vm_isolate_ = Isolate::Init("vm-isolate", api_flags, is_vm_isolate);
+ // Verify assumptions about executing in the VM isolate.
+ ASSERT(vm_isolate_ == Isolate::Current());
+ ASSERT(vm_isolate_ == Thread::Current()->isolate());
- StackZone zone(vm_isolate_);
- HandleScope handle_scope(vm_isolate_);
+ StackZone zone(T);
+ HandleScope handle_scope(T);
Object::InitNull(vm_isolate_);
ObjectStore::Init(vm_isolate_);
TargetCPUFeatures::InitOnce();
@@ -142,7 +147,8 @@
ASSERT(snapshot->kind() == Snapshot::kFull);
VmIsolateSnapshotReader reader(snapshot->content(),
snapshot->length(),
- zone.GetZone());
+ instructions_snapshot,
+ T);
const Error& error = Error::Handle(reader.ReadVmIsolateSnapshot());
if (!error.IsNull()) {
return error.ToCString();
@@ -240,37 +246,32 @@
RawError* Dart::InitializeIsolate(const uint8_t* snapshot_buffer, void* data) {
// Initialize the new isolate.
- Thread* thread = Thread::Current();
- Isolate* isolate = thread->isolate();
- TIMERSCOPE(thread, time_isolate_initialization);
- TimelineDurationScope tds(isolate,
- isolate->GetIsolateStream(),
- "InitializeIsolate");
+ Thread* T = Thread::Current();
+ Isolate* I = T->isolate();
+ TIMERSCOPE(T, time_isolate_initialization);
+ TimelineDurationScope tds(I, I->GetIsolateStream(), "InitializeIsolate");
tds.SetNumArguments(1);
- tds.CopyArgument(0, "isolateName", isolate->name());
+ tds.CopyArgument(0, "isolateName", I->name());
- ASSERT(isolate != NULL);
- StackZone zone(isolate);
- HandleScope handle_scope(isolate);
+ ASSERT(I != NULL);
+ StackZone zone(T);
+ HandleScope handle_scope(T);
{
- TimelineDurationScope tds(isolate,
- isolate->GetIsolateStream(),
- "ObjectStore::Init");
- ObjectStore::Init(isolate);
+ TimelineDurationScope tds(I, I->GetIsolateStream(), "ObjectStore::Init");
+ ObjectStore::Init(I);
}
// Setup for profiling.
- Profiler::InitProfilingForIsolate(isolate);
+ Profiler::InitProfilingForIsolate(I);
- const Error& error = Error::Handle(Object::Init(isolate));
+ const Error& error = Error::Handle(Object::Init(I));
if (!error.IsNull()) {
return error.raw();
}
if (snapshot_buffer != NULL) {
// Read the snapshot and setup the initial state.
- TimelineDurationScope tds(isolate,
- isolate->GetIsolateStream(),
- "IsolateSnapshotReader");
+ TimelineDurationScope tds(
+ I, I->GetIsolateStream(), "IsolateSnapshotReader");
// TODO(turnidge): Remove once length is not part of the snapshot.
const Snapshot* snapshot = Snapshot::SetupFromBuffer(snapshot_buffer);
if (snapshot == NULL) {
@@ -284,15 +285,15 @@
}
IsolateSnapshotReader reader(snapshot->content(),
snapshot->length(),
- isolate,
- zone.GetZone());
+ Object::instructions_snapshot_buffer(),
+ T);
const Error& error = Error::Handle(reader.ReadFullSnapshot());
if (!error.IsNull()) {
return error.raw();
}
if (FLAG_trace_isolates) {
- isolate->heap()->PrintSizes();
- isolate->megamorphic_cache_table()->PrintSizes();
+ I->heap()->PrintSizes();
+ I->megamorphic_cache_table()->PrintSizes();
}
} else {
// Populate the isolate's symbol table with all symbols from the
@@ -305,41 +306,38 @@
Object::VerifyBuiltinVtables();
{
- TimelineDurationScope tds(isolate,
- isolate->GetIsolateStream(),
- "StubCode::Init");
- StubCode::Init(isolate);
+ TimelineDurationScope tds(I, I->GetIsolateStream(), "StubCode::Init");
+ StubCode::Init(I);
}
- isolate->megamorphic_cache_table()->InitMissHandler();
+ I->megamorphic_cache_table()->InitMissHandler();
if (snapshot_buffer == NULL) {
- if (!isolate->object_store()->PreallocateObjects()) {
- return isolate->object_store()->sticky_error();
+ if (!I->object_store()->PreallocateObjects()) {
+ return I->object_store()->sticky_error();
}
}
- isolate->heap()->EnableGrowthControl();
- isolate->set_init_callback_data(data);
- Api::SetupAcquiredError(isolate);
+ I->heap()->EnableGrowthControl();
+ I->set_init_callback_data(data);
+ Api::SetupAcquiredError(I);
if (FLAG_print_class_table) {
- isolate->class_table()->Print();
+ I->class_table()->Print();
}
- ServiceIsolate::MaybeInjectVMServiceLibrary(isolate);
+ ServiceIsolate::MaybeInjectVMServiceLibrary(I);
ServiceIsolate::SendIsolateStartupMessage();
- isolate->debugger()->NotifyIsolateCreated();
+ I->debugger()->NotifyIsolateCreated();
// Create tag table.
- isolate->set_tag_table(
- GrowableObjectArray::Handle(GrowableObjectArray::New()));
+ I->set_tag_table(GrowableObjectArray::Handle(GrowableObjectArray::New()));
// Set up default UserTag.
const UserTag& default_tag = UserTag::Handle(UserTag::DefaultTag());
- isolate->set_current_tag(default_tag);
+ I->set_current_tag(default_tag);
if (FLAG_keep_code) {
- isolate->set_deoptimized_code_array(
- GrowableObjectArray::Handle(GrowableObjectArray::New()));
+ I->set_deoptimized_code_array(
+ GrowableObjectArray::Handle(GrowableObjectArray::New()));
}
return Error::null();
}
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index 151d669..dcda02a 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -27,6 +27,7 @@
#include "vm/object_store.h"
#include "vm/os_thread.h"
#include "vm/port.h"
+#include "vm/precompiler.h"
#include "vm/profiler.h"
#include "vm/resolver.h"
#include "vm/reusable_handles.h"
@@ -45,6 +46,10 @@
namespace dart {
+// Facilitate quick access to the current zone once we have the curren thread.
+#define Z (T->zone())
+
+
DECLARE_FLAG(bool, load_deferred_eagerly);
DECLARE_FLAG(bool, print_class_table);
DECLARE_FLAG(bool, verify_handles);
@@ -116,15 +121,15 @@
#endif // #if defined(DEBUG).
-static RawInstance* GetListInstance(Isolate* isolate, const Object& obj) {
+static RawInstance* GetListInstance(Zone* zone, const Object& obj) {
if (obj.IsInstance()) {
- const Library& core_lib = Library::Handle(Library::CoreLibrary());
+ const Library& core_lib = Library::Handle(zone, Library::CoreLibrary());
const Class& list_class =
- Class::Handle(core_lib.LookupClass(Symbols::List()));
+ Class::Handle(zone, core_lib.LookupClass(Symbols::List()));
ASSERT(!list_class.IsNull());
const Instance& instance = Instance::Cast(obj);
- const Class& obj_class = Class::Handle(isolate, obj.clazz());
- Error& malformed_type_error = Error::Handle(isolate);
+ const Class& obj_class = Class::Handle(zone, obj.clazz());
+ Error& malformed_type_error = Error::Handle(zone);
if (obj_class.IsSubtypeOf(Object::null_type_arguments(),
list_class,
Object::null_type_arguments(),
@@ -136,15 +141,15 @@
return Instance::null();
}
-static RawInstance* GetMapInstance(Isolate* isolate, const Object& obj) {
+static RawInstance* GetMapInstance(Zone* zone, const Object& obj) {
if (obj.IsInstance()) {
- const Library& core_lib = Library::Handle(Library::CoreLibrary());
+ const Library& core_lib = Library::Handle(zone, Library::CoreLibrary());
const Class& map_class =
Class::Handle(core_lib.LookupClass(Symbols::Map()));
ASSERT(!map_class.IsNull());
const Instance& instance = Instance::Cast(obj);
- const Class& obj_class = Class::Handle(isolate, obj.clazz());
- Error& malformed_type_error = Error::Handle(isolate);
+ const Class& obj_class = Class::Handle(zone, obj.clazz());
+ Error& malformed_type_error = Error::Handle(zone);
if (obj_class.IsSubtypeOf(Object::null_type_arguments(),
map_class,
Object::null_type_arguments(),
@@ -443,25 +448,22 @@
Dart_Handle Api::NewError(const char* format, ...) {
- Thread* thread = Thread::Current();
- Isolate* isolate = thread->isolate();
- Zone* zone = thread->zone();
- DARTSCOPE(isolate);
- CHECK_CALLBACK_STATE(isolate);
+ DARTSCOPE(Thread::Current());
+ CHECK_CALLBACK_STATE(I);
va_list args;
va_start(args, format);
intptr_t len = OS::VSNPrint(NULL, 0, format, args);
va_end(args);
- char* buffer = zone->Alloc<char>(len + 1);
+ char* buffer = Z->Alloc<char>(len + 1);
va_list args2;
va_start(args2, format);
OS::VSNPrint(buffer, (len + 1), format, args2);
va_end(args2);
- const String& message = String::Handle(zone, String::New(buffer));
- return Api::NewHandle(isolate, ApiError::New(message));
+ const String& message = String::Handle(Z, String::New(buffer));
+ return Api::NewHandle(I, ApiError::New(message));
}
@@ -745,14 +747,13 @@
DART_EXPORT const char* Dart_GetError(Dart_Handle handle) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
- const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(handle));
+ DARTSCOPE(Thread::Current());
+ const Object& obj = Object::Handle(Z, Api::UnwrapHandle(handle));
if (obj.IsError()) {
const Error& error = Error::Cast(obj);
const char* str = error.ToErrorCString();
intptr_t len = strlen(str) + 1;
- char* str_copy = Api::TopScope(isolate)->zone()->Alloc<char>(len);
+ char* str_copy = Api::TopScope(I)->zone()->Alloc<char>(len);
strncpy(str_copy, str, len);
// Strip a possible trailing '\n'.
if ((len > 1) && (str_copy[len - 2] == '\n')) {
@@ -766,20 +767,18 @@
DART_EXPORT bool Dart_ErrorHasException(Dart_Handle handle) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
- const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(handle));
+ DARTSCOPE(Thread::Current());
+ const Object& obj = Object::Handle(Z, Api::UnwrapHandle(handle));
return obj.IsUnhandledException();
}
DART_EXPORT Dart_Handle Dart_ErrorGetException(Dart_Handle handle) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
- const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(handle));
+ DARTSCOPE(Thread::Current());
+ const Object& obj = Object::Handle(Z, Api::UnwrapHandle(handle));
if (obj.IsUnhandledException()) {
const UnhandledException& error = UnhandledException::Cast(obj);
- return Api::NewHandle(isolate, error.exception());
+ return Api::NewHandle(I, error.exception());
} else if (obj.IsError()) {
return Api::NewError("This error is not an unhandled exception error.");
} else {
@@ -789,12 +788,11 @@
DART_EXPORT Dart_Handle Dart_ErrorGetStacktrace(Dart_Handle handle) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
- const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(handle));
+ DARTSCOPE(Thread::Current());
+ const Object& obj = Object::Handle(Z, Api::UnwrapHandle(handle));
if (obj.IsUnhandledException()) {
const UnhandledException& error = UnhandledException::Cast(obj);
- return Api::NewHandle(isolate, error.stacktrace());
+ return Api::NewHandle(I, error.stacktrace());
} else if (obj.IsError()) {
return Api::NewError("This error is not an unhandled exception error.");
} else {
@@ -806,32 +804,30 @@
// TODO(turnidge): This clones Api::NewError. I need to use va_copy to
// fix this but not sure if it available on all of our builds.
DART_EXPORT Dart_Handle Dart_NewApiError(const char* error) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
- CHECK_CALLBACK_STATE(isolate);
+ DARTSCOPE(Thread::Current());
+ CHECK_CALLBACK_STATE(I);
- const String& message = String::Handle(isolate, String::New(error));
- return Api::NewHandle(isolate, ApiError::New(message));
+ const String& message = String::Handle(Z, String::New(error));
+ return Api::NewHandle(I, ApiError::New(message));
}
DART_EXPORT Dart_Handle Dart_NewUnhandledExceptionError(Dart_Handle exception) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
- CHECK_CALLBACK_STATE(isolate);
+ DARTSCOPE(Thread::Current());
+ CHECK_CALLBACK_STATE(I);
- Instance& obj = Instance::Handle(isolate);
+ Instance& obj = Instance::Handle(Z);
intptr_t class_id = Api::ClassId(exception);
if ((class_id == kApiErrorCid) || (class_id == kLanguageErrorCid)) {
obj = String::New(::Dart_GetError(exception));
} else {
- obj = Api::UnwrapInstanceHandle(isolate, exception).raw();
+ obj = Api::UnwrapInstanceHandle(I, exception).raw();
if (obj.IsNull()) {
- RETURN_TYPE_ERROR(isolate, exception, Instance);
+ RETURN_TYPE_ERROR(I, exception, Instance);
}
}
- const Stacktrace& stacktrace = Stacktrace::Handle(isolate);
- return Api::NewHandle(isolate, UnhandledException::New(obj, stacktrace));
+ const Stacktrace& stacktrace = Stacktrace::Handle(Z);
+ return Api::NewHandle(I, UnhandledException::New(obj, stacktrace));
}
@@ -883,34 +879,32 @@
DART_EXPORT Dart_Handle Dart_ToString(Dart_Handle object) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
- const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(object));
+ DARTSCOPE(Thread::Current());
+ const Object& obj = Object::Handle(Z, Api::UnwrapHandle(object));
if (obj.IsString()) {
- return Api::NewHandle(isolate, obj.raw());
+ return Api::NewHandle(I, obj.raw());
} else if (obj.IsInstance()) {
- CHECK_CALLBACK_STATE(isolate);
+ CHECK_CALLBACK_STATE(I);
const Instance& receiver = Instance::Cast(obj);
- return Api::NewHandle(isolate, DartLibraryCalls::ToString(receiver));
+ return Api::NewHandle(I, DartLibraryCalls::ToString(receiver));
} else {
- CHECK_CALLBACK_STATE(isolate);
+ CHECK_CALLBACK_STATE(I);
// This is a VM internal object. Call the C++ method of printing.
- return Api::NewHandle(isolate, String::New(obj.ToCString()));
+ return Api::NewHandle(I, String::New(obj.ToCString()));
}
}
DART_EXPORT bool Dart_IdentityEquals(Dart_Handle obj1, Dart_Handle obj2) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
+ DARTSCOPE(Thread::Current());
{
NoSafepointScope no_safepoint_scope;
if (Api::UnwrapHandle(obj1) == Api::UnwrapHandle(obj2)) {
return true;
}
}
- const Object& object1 = Object::Handle(isolate, Api::UnwrapHandle(obj1));
- const Object& object2 = Object::Handle(isolate, Api::UnwrapHandle(obj2));
+ const Object& object1 = Object::Handle(Z, Api::UnwrapHandle(obj1));
+ const Object& object2 = Object::Handle(Z, Api::UnwrapHandle(obj2));
if (object1.IsInstance() && object2.IsInstance()) {
return Instance::Cast(object1).IsIdenticalTo(Instance::Cast(object2));
}
@@ -919,29 +913,27 @@
DART_EXPORT uint64_t Dart_IdentityHash(Dart_Handle obj) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
+ DARTSCOPE(Thread::Current());
- const Object& object = Object::Handle(isolate, Api::UnwrapHandle(obj));
+ const Object& object = Object::Handle(Z, Api::UnwrapHandle(obj));
if (!object.IsInstance() && !object.IsNull()) {
return 0;
}
- const Library& libcore = Library::Handle(isolate, Library::CoreLibrary());
- const String& function_name = String::Handle(isolate,
+ const Library& libcore = Library::Handle(Z, Library::CoreLibrary());
+ const String& function_name = String::Handle(Z,
String::New("identityHashCode"));
const Function& function =
- Function::Handle(isolate,
- libcore.LookupFunctionAllowPrivate(function_name));
+ Function::Handle(Z, libcore.LookupFunctionAllowPrivate(function_name));
if (function.IsNull()) {
UNREACHABLE();
return 0;
}
- const Array& arguments = Array::Handle(isolate, Array::New(1));
+ const Array& arguments = Array::Handle(Z, Array::New(1));
arguments.SetAt(0, object);
const Object& result =
- Object::Handle(isolate, DartEntry::InvokeFunction(function, arguments));
+ Object::Handle(Z, DartEntry::InvokeFunction(function, arguments));
if (result.IsSmi()) {
return Smi::Cast(result).Value();
@@ -986,11 +978,10 @@
DART_EXPORT Dart_PersistentHandle Dart_NewPersistentHandle(Dart_Handle object) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
- ApiState* state = isolate->api_state();
+ DARTSCOPE(Thread::Current());
+ ApiState* state = I->api_state();
ASSERT(state != NULL);
- const Object& old_ref = Object::Handle(isolate, Api::UnwrapHandle(object));
+ const Object& old_ref = Object::Handle(Z, Api::UnwrapHandle(object));
PersistentHandle* new_ref = state->persistent_handles().AllocateHandle();
new_ref->set_raw(old_ref);
return new_ref->apiHandle();
@@ -999,12 +990,11 @@
DART_EXPORT void Dart_SetPersistentHandle(Dart_PersistentHandle obj1,
Dart_Handle obj2) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
- ApiState* state = isolate->api_state();
+ DARTSCOPE(Thread::Current());
+ ApiState* state = I->api_state();
ASSERT(state != NULL);
ASSERT(state->IsValidPersistentHandle(obj1));
- const Object& obj2_ref = Object::Handle(isolate, Api::UnwrapHandle(obj2));
+ const Object& obj2_ref = Object::Handle(Z, Api::UnwrapHandle(obj2));
PersistentHandle* obj1_ref = PersistentHandle::Cast(obj1);
obj1_ref->set_raw(obj2_ref);
}
@@ -1365,18 +1355,18 @@
vm_flags.CopyTo(&api_flags);
flags = &api_flags;
}
- Isolate* isolate = Dart::CreateIsolate(isolate_name, *flags);
+ Isolate* I = Dart::CreateIsolate(isolate_name, *flags);
free(isolate_name);
{
- StackZone zone(isolate);
- HANDLESCOPE(isolate);
+ Thread* T = Thread::Current();
+ StackZone zone(T);
+ HANDLESCOPE(T);
// We enter an API scope here as InitializeIsolate could compile some
// bootstrap library files which call out to a tag handler that may create
// Api Handles when an error is encountered.
Dart_EnterScope();
const Error& error_obj =
- Error::Handle(isolate,
- Dart::InitializeIsolate(snapshot, callback_data));
+ Error::Handle(Z, Dart::InitializeIsolate(snapshot, callback_data));
if (error_obj.IsNull()) {
#if defined(DART_NO_SNAPSHOT)
if (FLAG_check_function_fingerprints) {
@@ -1385,8 +1375,8 @@
#endif // defined(DART_NO_SNAPSHOT).
// We exit the API scope entered above.
Dart_ExitScope();
- START_TIMER(isolate, time_total_runtime);
- return Api::CastIsolate(isolate);
+ START_TIMER(I, time_total_runtime);
+ return Api::CastIsolate(I);
}
*error = strdup(error_obj.ToErrorCString());
// We exit the API scope entered above.
@@ -1398,14 +1388,15 @@
DART_EXPORT void Dart_ShutdownIsolate() {
- Isolate* isolate = Isolate::Current();
- CHECK_ISOLATE(isolate);
+ Thread* T = Thread::Current();
+ Isolate* I = T->isolate();
+ CHECK_ISOLATE(I);
{
- StackZone zone(isolate);
- HandleScope handle_scope(isolate);
+ StackZone zone(T);
+ HandleScope handle_scope(T);
Dart::RunShutdownCallback();
}
- STOP_TIMER(isolate, time_total_runtime);
+ STOP_TIMER(I, time_total_runtime);
Dart::ShutdownIsolate();
}
@@ -1434,9 +1425,8 @@
DART_EXPORT Dart_Handle Dart_DebugName() {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
- return Api::NewHandle(isolate, String::New(isolate->name()));
+ DARTSCOPE(Thread::Current());
+ return Api::NewHandle(I, String::New(I->name()));
}
@@ -1512,10 +1502,8 @@
uint8_t** isolate_snapshot_buffer,
intptr_t* isolate_snapshot_size) {
ASSERT(FLAG_load_deferred_eagerly);
- Thread* thread = Thread::Current();
- Isolate* isolate = thread->isolate();
- DARTSCOPE(isolate);
- TIMERSCOPE(thread, time_creating_snapshot);
+ DARTSCOPE(Thread::Current());
+ TIMERSCOPE(T, time_creating_snapshot);
if (vm_isolate_snapshot_buffer != NULL &&
vm_isolate_snapshot_size == NULL) {
RETURN_NULL_ERROR(vm_isolate_snapshot_size);
@@ -1527,22 +1515,24 @@
RETURN_NULL_ERROR(isolate_snapshot_size);
}
// Finalize all classes if needed.
- Dart_Handle state = Api::CheckAndFinalizePendingClasses(isolate);
+ Dart_Handle state = Api::CheckAndFinalizePendingClasses(I);
if (::Dart_IsError(state)) {
return state;
}
- isolate->heap()->CollectAllGarbage();
+ I->heap()->CollectAllGarbage();
#if defined(DEBUG)
- FunctionVisitor check_canonical(isolate);
- isolate->heap()->IterateObjects(&check_canonical);
+ FunctionVisitor check_canonical(I);
+ I->heap()->IterateObjects(&check_canonical);
#endif // #if defined(DEBUG).
// Since this is only a snapshot the root library should not be set.
- isolate->object_store()->set_root_library(Library::Handle(isolate));
+ I->object_store()->set_root_library(Library::Handle(Z));
FullSnapshotWriter writer(vm_isolate_snapshot_buffer,
isolate_snapshot_buffer,
+ NULL, /* instructions_snapshot_buffer */
ApiReallocate,
- false /* snapshot_code */);
+ false, /* snapshot_code */
+ true /* vm_isolate_is_symbolic */);
writer.WriteFullSnapshot();
*vm_isolate_snapshot_size = writer.VmIsolateSnapshotSize();
*isolate_snapshot_size = writer.IsolateSnapshotSize();
@@ -1553,10 +1543,8 @@
static Dart_Handle createLibrarySnapshot(Dart_Handle library,
uint8_t** buffer,
intptr_t* size) {
- Thread* thread = Thread::Current();
- Isolate* isolate = thread->isolate();
- DARTSCOPE(isolate);
- TIMERSCOPE(thread, time_creating_snapshot);
+ DARTSCOPE(Thread::Current());
+ TIMERSCOPE(T, time_creating_snapshot);
if (buffer == NULL) {
RETURN_NULL_ERROR(buffer);
}
@@ -1564,20 +1552,20 @@
RETURN_NULL_ERROR(size);
}
// Finalize all classes if needed.
- Dart_Handle state = Api::CheckAndFinalizePendingClasses(isolate);
+ Dart_Handle state = Api::CheckAndFinalizePendingClasses(I);
if (::Dart_IsError(state)) {
return state;
}
- Library& lib = Library::Handle(isolate);
+ Library& lib = Library::Handle(Z);
if (library == Dart_Null()) {
- lib ^= isolate->object_store()->root_library();
+ lib ^= I->object_store()->root_library();
} else {
lib ^= Api::UnwrapHandle(library);
}
- isolate->heap()->CollectAllGarbage();
+ I->heap()->CollectAllGarbage();
#if defined(DEBUG)
- FunctionVisitor check_canonical(isolate);
- isolate->heap()->IterateObjects(&check_canonical);
+ FunctionVisitor check_canonical(I);
+ I->heap()->IterateObjects(&check_canonical);
#endif // #if defined(DEBUG).
ScriptSnapshotWriter writer(buffer, ApiReallocate);
writer.WriteScriptSnapshot(lib);
@@ -1660,9 +1648,10 @@
DART_EXPORT Dart_Handle Dart_RunLoop() {
- Isolate* isolate = Isolate::Current();
- CHECK_ISOLATE_SCOPE(isolate);
- CHECK_CALLBACK_STATE(isolate);
+ Thread* T = Thread::Current();
+ Isolate* I = T->isolate();
+ CHECK_ISOLATE_SCOPE(I);
+ CHECK_CALLBACK_STATE(I);
Monitor monitor;
MonitorLocker ml(&monitor);
{
@@ -1671,22 +1660,21 @@
RunLoopData data;
data.monitor = &monitor;
data.done = false;
- isolate->message_handler()->Run(
+ I->message_handler()->Run(
Dart::thread_pool(),
NULL, RunLoopDone, reinterpret_cast<uword>(&data));
while (!data.done) {
ml.Wait();
}
}
- if (isolate->object_store()->sticky_error() != Object::null()) {
- Dart_Handle error = Api::NewHandle(isolate,
- isolate->object_store()->sticky_error());
- isolate->object_store()->clear_sticky_error();
+ if (I->object_store()->sticky_error() != Object::null()) {
+ Dart_Handle error = Api::NewHandle(I, I->object_store()->sticky_error());
+ I->object_store()->clear_sticky_error();
return error;
}
if (FLAG_print_class_table) {
- HANDLESCOPE(isolate);
- isolate->class_table()->Print();
+ HANDLESCOPE(T);
+ I->class_table()->Print();
}
return Api::Success();
}
@@ -1738,12 +1726,11 @@
DART_EXPORT bool Dart_Post(Dart_Port port_id, Dart_Handle handle) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
+ DARTSCOPE(Thread::Current());
if (port_id == ILLEGAL_PORT) {
return false;
}
- const Object& object = Object::Handle(isolate, Api::UnwrapHandle(handle));
+ const Object& object = Object::Handle(Z, Api::UnwrapHandle(handle));
uint8_t* data = NULL;
MessageWriter writer(&data, &allocator, false);
writer.WriteMessage(object);
@@ -1754,26 +1741,24 @@
DART_EXPORT Dart_Handle Dart_NewSendPort(Dart_Port port_id) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
- CHECK_CALLBACK_STATE(isolate);
+ DARTSCOPE(Thread::Current());
+ CHECK_CALLBACK_STATE(I);
if (port_id == ILLEGAL_PORT) {
return Api::NewError("%s: illegal port_id %" Pd64 ".",
CURRENT_FUNC,
port_id);
}
- return Api::NewHandle(isolate, SendPort::New(port_id));
+ return Api::NewHandle(I, SendPort::New(port_id));
}
DART_EXPORT Dart_Handle Dart_SendPortGetId(Dart_Handle port,
Dart_Port* port_id) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
- CHECK_CALLBACK_STATE(isolate);
- const SendPort& send_port = Api::UnwrapSendPortHandle(isolate, port);
+ DARTSCOPE(Thread::Current());
+ CHECK_CALLBACK_STATE(I);
+ const SendPort& send_port = Api::UnwrapSendPortHandle(I, port);
if (send_port.IsNull()) {
- RETURN_TYPE_ERROR(isolate, port, SendPort);
+ RETURN_TYPE_ERROR(I, port, SendPort);
}
if (port_id == NULL) {
RETURN_NULL_ERROR(port_id);
@@ -1869,22 +1854,19 @@
DART_EXPORT Dart_Handle Dart_ObjectEquals(Dart_Handle obj1, Dart_Handle obj2,
bool* value) {
- Thread* thread = Thread::Current();
- Isolate* isolate = thread->isolate();
- Zone* zone = thread->zone();
- DARTSCOPE(isolate);
- CHECK_CALLBACK_STATE(isolate);
+ DARTSCOPE(Thread::Current());
+ CHECK_CALLBACK_STATE(I);
const Instance& expected =
- Instance::CheckedHandle(zone, Api::UnwrapHandle(obj1));
+ Instance::CheckedHandle(Z, Api::UnwrapHandle(obj1));
const Instance& actual =
- Instance::CheckedHandle(zone, Api::UnwrapHandle(obj2));
+ Instance::CheckedHandle(Z, Api::UnwrapHandle(obj2));
const Object& result =
- Object::Handle(zone, DartLibraryCalls::Equals(expected, actual));
+ Object::Handle(Z, DartLibraryCalls::Equals(expected, actual));
if (result.IsBool()) {
*value = Bool::Cast(result).value();
return Api::Success();
} else if (result.IsError()) {
- return Api::NewHandle(isolate, result.raw());
+ return Api::NewHandle(I, result.raw());
} else {
return Api::NewError("Expected boolean result from ==");
}
@@ -1897,13 +1879,12 @@
DART_EXPORT Dart_Handle Dart_ObjectIsType(Dart_Handle object,
Dart_Handle type,
bool* value) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
+ DARTSCOPE(Thread::Current());
- const Type& type_obj = Api::UnwrapTypeHandle(isolate, type);
+ const Type& type_obj = Api::UnwrapTypeHandle(I, type);
if (type_obj.IsNull()) {
*value = false;
- RETURN_TYPE_ERROR(isolate, type, Type);
+ RETURN_TYPE_ERROR(I, type, Type);
}
if (!type_obj.IsFinalized()) {
return Api::NewError(
@@ -1914,13 +1895,13 @@
*value = false;
return Api::Success();
}
- const Instance& instance = Api::UnwrapInstanceHandle(isolate, object);
+ const Instance& instance = Api::UnwrapInstanceHandle(I, object);
if (instance.IsNull()) {
*value = false;
- RETURN_TYPE_ERROR(isolate, object, Instance);
+ RETURN_TYPE_ERROR(I, object, Instance);
}
- CHECK_CALLBACK_STATE(isolate);
- Error& malformed_type_error = Error::Handle(isolate);
+ CHECK_CALLBACK_STATE(I);
+ Error& malformed_type_error = Error::Handle(Z);
*value = instance.IsInstanceOf(type_obj,
Object::null_type_arguments(),
&malformed_type_error);
@@ -1987,18 +1968,16 @@
return true;
}
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
- const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(object));
- return GetListInstance(isolate, obj) != Instance::null();
+ DARTSCOPE(Thread::Current());
+ const Object& obj = Object::Handle(Z, Api::UnwrapHandle(object));
+ return GetListInstance(Z, obj) != Instance::null();
}
DART_EXPORT bool Dart_IsMap(Dart_Handle object) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
- const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(object));
- return GetMapInstance(isolate, obj) != Instance::null();
+ DARTSCOPE(Thread::Current());
+ const Object& obj = Object::Handle(Z, Api::UnwrapHandle(object));
+ return GetMapInstance(Z, obj) != Instance::null();
}
@@ -2061,15 +2040,14 @@
DART_EXPORT bool Dart_IsFuture(Dart_Handle handle) {
TRACE_API_CALL(CURRENT_FUNC);
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
- const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(handle));
+ DARTSCOPE(Thread::Current());
+ const Object& obj = Object::Handle(Z, Api::UnwrapHandle(handle));
if (obj.IsInstance()) {
const Class& future_class =
- Class::Handle(isolate->object_store()->future_class());
+ Class::Handle(I->object_store()->future_class());
ASSERT(!future_class.IsNull());
- const Class& obj_class = Class::Handle(isolate, obj.clazz());
- Error& malformed_type_error = Error::Handle(isolate);
+ const Class& obj_class = Class::Handle(Z, obj.clazz());
+ Error& malformed_type_error = Error::Handle(Z);
bool is_future = obj_class.IsSubtypeOf(Object::null_type_arguments(),
future_class,
Object::null_type_arguments(),
@@ -2084,17 +2062,16 @@
// --- Instances ----
DART_EXPORT Dart_Handle Dart_InstanceGetType(Dart_Handle instance) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
- const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(instance));
+ DARTSCOPE(Thread::Current());
+ const Object& obj = Object::Handle(Z, Api::UnwrapHandle(instance));
if (obj.IsNull()) {
- return Api::NewHandle(isolate, isolate->object_store()->null_type());
+ return Api::NewHandle(I, I->object_store()->null_type());
}
if (!obj.IsInstance()) {
- RETURN_TYPE_ERROR(isolate, instance, Instance);
+ RETURN_TYPE_ERROR(I, instance, Instance);
}
const Type& type = Type::Handle(Instance::Cast(obj).GetType());
- return Api::NewHandle(isolate, type.Canonicalize());
+ return Api::NewHandle(I, type.Canonicalize());
}
@@ -2103,7 +2080,8 @@
DART_EXPORT Dart_Handle Dart_IntegerFitsIntoInt64(Dart_Handle integer,
bool* fits) {
// Fast path for Smis and Mints.
- Isolate* isolate = Isolate::Current();
+ Thread* thread = Thread::Current();
+ Isolate* isolate = thread->isolate();
CHECK_ISOLATE(isolate);
intptr_t class_id = Api::ClassId(integer);
if (class_id == kSmiCid || class_id == kMintCid) {
@@ -2111,7 +2089,7 @@
return Api::Success();
}
// Slow path for Mints and Bigints.
- DARTSCOPE(isolate);
+ DARTSCOPE(thread);
const Integer& int_obj = Api::UnwrapIntegerHandle(isolate, integer);
if (int_obj.IsNull()) {
RETURN_TYPE_ERROR(isolate, integer, Integer);
@@ -2125,14 +2103,15 @@
DART_EXPORT Dart_Handle Dart_IntegerFitsIntoUint64(Dart_Handle integer,
bool* fits) {
// Fast path for Smis.
- Isolate* isolate = Isolate::Current();
+ Thread* thread = Thread::Current();
+ Isolate* isolate = thread->isolate();
CHECK_ISOLATE(isolate);
if (Api::IsSmi(integer)) {
*fits = (Api::SmiValue(integer) >= 0);
return Api::Success();
}
// Slow path for Mints and Bigints.
- DARTSCOPE(isolate);
+ DARTSCOPE(thread);
const Integer& int_obj = Api::UnwrapIntegerHandle(isolate, integer);
if (int_obj.IsNull()) {
RETURN_TYPE_ERROR(isolate, integer, Integer);
@@ -2149,47 +2128,47 @@
DART_EXPORT Dart_Handle Dart_NewInteger(int64_t value) {
// Fast path for Smis.
- Isolate* isolate = Isolate::Current();
+ Thread* thread = Thread::Current();
+ Isolate* isolate = thread->isolate();
CHECK_ISOLATE(isolate);
if (Smi::IsValid(value)) {
- NOHANDLESCOPE(isolate);
+ NOHANDLESCOPE(thread);
return Api::NewHandle(isolate, Smi::New(static_cast<intptr_t>(value)));
}
// Slow path for Mints and Bigints.
- DARTSCOPE(isolate);
+ DARTSCOPE(thread);
CHECK_CALLBACK_STATE(isolate);
return Api::NewHandle(isolate, Integer::New(value));
}
DART_EXPORT Dart_Handle Dart_NewIntegerFromUint64(uint64_t value) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
- CHECK_CALLBACK_STATE(isolate);
- return Api::NewHandle(isolate, Integer::NewFromUint64(value));
+ DARTSCOPE(Thread::Current());
+ CHECK_CALLBACK_STATE(I);
+ return Api::NewHandle(I, Integer::NewFromUint64(value));
}
DART_EXPORT Dart_Handle Dart_NewIntegerFromHexCString(const char* str) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
- CHECK_CALLBACK_STATE(isolate);
- const String& str_obj = String::Handle(isolate, String::New(str));
- return Api::NewHandle(isolate, Integer::New(str_obj));
+ DARTSCOPE(Thread::Current());
+ CHECK_CALLBACK_STATE(I);
+ const String& str_obj = String::Handle(Z, String::New(str));
+ return Api::NewHandle(I, Integer::New(str_obj));
}
DART_EXPORT Dart_Handle Dart_IntegerToInt64(Dart_Handle integer,
int64_t* value) {
// Fast path for Smis.
- Isolate* isolate = Isolate::Current();
+ Thread* thread = Thread::Current();
+ Isolate* isolate = thread->isolate();
CHECK_ISOLATE(isolate);
if (Api::IsSmi(integer)) {
*value = Api::SmiValue(integer);
return Api::Success();
}
// Slow path for Mints and Bigints.
- DARTSCOPE(isolate);
+ DARTSCOPE(thread);
const Integer& int_obj = Api::UnwrapIntegerHandle(isolate, integer);
if (int_obj.IsNull()) {
RETURN_TYPE_ERROR(isolate, integer, Integer);
@@ -2213,7 +2192,8 @@
DART_EXPORT Dart_Handle Dart_IntegerToUint64(Dart_Handle integer,
uint64_t* value) {
// Fast path for Smis.
- Isolate* isolate = Isolate::Current();
+ Thread* thread = Thread::Current();
+ Isolate* isolate = thread->isolate();
CHECK_ISOLATE(isolate);
if (Api::IsSmi(integer)) {
intptr_t smi_value = Api::SmiValue(integer);
@@ -2223,7 +2203,7 @@
}
}
// Slow path for Mints and Bigints.
- DARTSCOPE(isolate);
+ DARTSCOPE(thread);
const Integer& int_obj = Api::UnwrapIntegerHandle(isolate, integer);
if (int_obj.IsNull()) {
RETURN_TYPE_ERROR(isolate, integer, Integer);
@@ -2252,14 +2232,13 @@
DART_EXPORT Dart_Handle Dart_IntegerToHexCString(Dart_Handle integer,
const char** value) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
- const Integer& int_obj = Api::UnwrapIntegerHandle(isolate, integer);
+ DARTSCOPE(Thread::Current());
+ const Integer& int_obj = Api::UnwrapIntegerHandle(I, integer);
if (int_obj.IsNull()) {
- RETURN_TYPE_ERROR(isolate, integer, Integer);
+ RETURN_TYPE_ERROR(I, integer, Integer);
}
if (int_obj.IsSmi() || int_obj.IsMint()) {
- const Bigint& bigint = Bigint::Handle(isolate,
+ const Bigint& bigint = Bigint::Handle(Z,
Bigint::NewFromInt64(int_obj.AsInt64Value()));
*value = bigint.ToHexCString(BigintAllocate);
} else {
@@ -2270,20 +2249,18 @@
DART_EXPORT Dart_Handle Dart_NewDouble(double value) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
- CHECK_CALLBACK_STATE(isolate);
- return Api::NewHandle(isolate, Double::New(value));
+ DARTSCOPE(Thread::Current());
+ CHECK_CALLBACK_STATE(I);
+ return Api::NewHandle(I, Double::New(value));
}
DART_EXPORT Dart_Handle Dart_DoubleValue(Dart_Handle double_obj,
double* value) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
- const Double& obj = Api::UnwrapDoubleHandle(isolate, double_obj);
+ DARTSCOPE(Thread::Current());
+ const Double& obj = Api::UnwrapDoubleHandle(I, double_obj);
if (obj.IsNull()) {
- RETURN_TYPE_ERROR(isolate, double_obj, Double);
+ RETURN_TYPE_ERROR(I, double_obj, Double);
}
*value = obj.value();
return Api::Success();
@@ -2313,11 +2290,10 @@
DART_EXPORT Dart_Handle Dart_BooleanValue(Dart_Handle boolean_obj,
bool* value) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
- const Bool& obj = Api::UnwrapBoolHandle(isolate, boolean_obj);
+ DARTSCOPE(Thread::Current());
+ const Bool& obj = Api::UnwrapBoolHandle(I, boolean_obj);
if (obj.IsNull()) {
- RETURN_TYPE_ERROR(isolate, boolean_obj, Bool);
+ RETURN_TYPE_ERROR(I, boolean_obj, Bool);
}
*value = obj.value();
return Api::Success();
@@ -2341,20 +2317,18 @@
DART_EXPORT Dart_Handle Dart_NewStringFromCString(const char* str) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
+ DARTSCOPE(Thread::Current());
if (str == NULL) {
RETURN_NULL_ERROR(str);
}
- CHECK_CALLBACK_STATE(isolate);
- return Api::NewHandle(isolate, String::New(str));
+ CHECK_CALLBACK_STATE(I);
+ return Api::NewHandle(I, String::New(str));
}
DART_EXPORT Dart_Handle Dart_NewStringFromUTF8(const uint8_t* utf8_array,
intptr_t length) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
+ DARTSCOPE(Thread::Current());
if (utf8_array == NULL && length != 0) {
RETURN_NULL_ERROR(utf8_array);
}
@@ -2363,34 +2337,32 @@
return Api::NewError("%s expects argument 'str' to be valid UTF-8.",
CURRENT_FUNC);
}
- CHECK_CALLBACK_STATE(isolate);
- return Api::NewHandle(isolate, String::FromUTF8(utf8_array, length));
+ CHECK_CALLBACK_STATE(I);
+ return Api::NewHandle(I, String::FromUTF8(utf8_array, length));
}
DART_EXPORT Dart_Handle Dart_NewStringFromUTF16(const uint16_t* utf16_array,
intptr_t length) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
+ DARTSCOPE(Thread::Current());
if (utf16_array == NULL && length != 0) {
RETURN_NULL_ERROR(utf16_array);
}
CHECK_LENGTH(length, String::kMaxElements);
- CHECK_CALLBACK_STATE(isolate);
- return Api::NewHandle(isolate, String::FromUTF16(utf16_array, length));
+ CHECK_CALLBACK_STATE(I);
+ return Api::NewHandle(I, String::FromUTF16(utf16_array, length));
}
DART_EXPORT Dart_Handle Dart_NewStringFromUTF32(const int32_t* utf32_array,
intptr_t length) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
+ DARTSCOPE(Thread::Current());
if (utf32_array == NULL && length != 0) {
RETURN_NULL_ERROR(utf32_array);
}
CHECK_LENGTH(length, String::kMaxElements);
- CHECK_CALLBACK_STATE(isolate);
- return Api::NewHandle(isolate, String::FromUTF32(utf32_array, length));
+ CHECK_CALLBACK_STATE(I);
+ return Api::NewHandle(I, String::FromUTF32(utf32_array, length));
}
@@ -2399,19 +2371,18 @@
intptr_t length,
void* peer,
Dart_PeerFinalizer cback) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
+ DARTSCOPE(Thread::Current());
if (latin1_array == NULL && length != 0) {
RETURN_NULL_ERROR(latin1_array);
}
CHECK_LENGTH(length, String::kMaxElements);
- CHECK_CALLBACK_STATE(isolate);
- return Api::NewHandle(isolate,
+ CHECK_CALLBACK_STATE(I);
+ return Api::NewHandle(I,
String::NewExternal(latin1_array,
length,
peer,
cback,
- SpaceForExternal(isolate, length)));
+ SpaceForExternal(I, length)));
}
@@ -2419,36 +2390,34 @@
intptr_t length,
void* peer,
Dart_PeerFinalizer cback) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
+ DARTSCOPE(Thread::Current());
if (utf16_array == NULL && length != 0) {
RETURN_NULL_ERROR(utf16_array);
}
CHECK_LENGTH(length, String::kMaxElements);
- CHECK_CALLBACK_STATE(isolate);
+ CHECK_CALLBACK_STATE(I);
intptr_t bytes = length * sizeof(*utf16_array);
- return Api::NewHandle(isolate,
+ return Api::NewHandle(I,
String::NewExternal(utf16_array,
length,
peer,
cback,
- SpaceForExternal(isolate, bytes)));
+ SpaceForExternal(I, bytes)));
}
DART_EXPORT Dart_Handle Dart_StringToCString(Dart_Handle object,
const char** cstr) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
+ DARTSCOPE(Thread::Current());
if (cstr == NULL) {
RETURN_NULL_ERROR(cstr);
}
- const String& str_obj = Api::UnwrapStringHandle(isolate, object);
+ const String& str_obj = Api::UnwrapStringHandle(I, object);
if (str_obj.IsNull()) {
- RETURN_TYPE_ERROR(isolate, object, String);
+ RETURN_TYPE_ERROR(I, object, String);
}
intptr_t string_length = Utf8::Length(str_obj);
- char* res = Api::TopScope(isolate)->zone()->Alloc<char>(string_length + 1);
+ char* res = Api::TopScope(I)->zone()->Alloc<char>(string_length + 1);
if (res == NULL) {
return Api::NewError("Unable to allocate memory");
}
@@ -2463,20 +2432,19 @@
DART_EXPORT Dart_Handle Dart_StringToUTF8(Dart_Handle str,
uint8_t** utf8_array,
intptr_t* length) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
+ DARTSCOPE(Thread::Current());
if (utf8_array == NULL) {
RETURN_NULL_ERROR(utf8_array);
}
if (length == NULL) {
RETURN_NULL_ERROR(length);
}
- const String& str_obj = Api::UnwrapStringHandle(isolate, str);
+ const String& str_obj = Api::UnwrapStringHandle(I, str);
if (str_obj.IsNull()) {
- RETURN_TYPE_ERROR(isolate, str, String);
+ RETURN_TYPE_ERROR(I, str, String);
}
intptr_t str_len = Utf8::Length(str_obj);
- *utf8_array = Api::TopScope(isolate)->zone()->Alloc<uint8_t>(str_len);
+ *utf8_array = Api::TopScope(I)->zone()->Alloc<uint8_t>(str_len);
if (*utf8_array == NULL) {
return Api::NewError("Unable to allocate memory");
}
@@ -2489,17 +2457,16 @@
DART_EXPORT Dart_Handle Dart_StringToLatin1(Dart_Handle str,
uint8_t* latin1_array,
intptr_t* length) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
+ DARTSCOPE(Thread::Current());
if (latin1_array == NULL) {
RETURN_NULL_ERROR(latin1_array);
}
if (length == NULL) {
RETURN_NULL_ERROR(length);
}
- const String& str_obj = Api::UnwrapStringHandle(isolate, str);
+ const String& str_obj = Api::UnwrapStringHandle(I, str);
if (str_obj.IsNull() || !str_obj.IsOneByteString()) {
- RETURN_TYPE_ERROR(isolate, str, String);
+ RETURN_TYPE_ERROR(I, str, String);
}
intptr_t str_len = str_obj.Length();
intptr_t copy_len = (str_len > *length) ? *length : str_len;
@@ -2517,11 +2484,10 @@
DART_EXPORT Dart_Handle Dart_StringToUTF16(Dart_Handle str,
uint16_t* utf16_array,
intptr_t* length) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
- const String& str_obj = Api::UnwrapStringHandle(isolate, str);
+ DARTSCOPE(Thread::Current());
+ const String& str_obj = Api::UnwrapStringHandle(I, str);
if (str_obj.IsNull()) {
- RETURN_TYPE_ERROR(isolate, str, String);
+ RETURN_TYPE_ERROR(I, str, String);
}
intptr_t str_len = str_obj.Length();
intptr_t copy_len = (str_len > *length) ? *length : str_len;
@@ -2555,14 +2521,13 @@
intptr_t length,
void* peer,
Dart_PeerFinalizer cback) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
- const String& str_obj = Api::UnwrapStringHandle(isolate, str);
+ DARTSCOPE(Thread::Current());
+ const String& str_obj = Api::UnwrapStringHandle(I, str);
if (str_obj.IsExternal()) {
return str; // String is already an external string.
}
if (str_obj.IsNull()) {
- RETURN_TYPE_ERROR(isolate, str, String);
+ RETURN_TYPE_ERROR(I, str, String);
}
if (array == NULL) {
RETURN_NULL_ERROR(array);
@@ -2599,8 +2564,7 @@
}
return str;
}
- return Api::NewHandle(isolate,
- str_obj.MakeExternal(array, length, peer, cback));
+ return Api::NewHandle(I, str_obj.MakeExternal(array, length, peer, cback));
}
@@ -2631,65 +2595,60 @@
// --- Lists ---
DART_EXPORT Dart_Handle Dart_NewList(intptr_t length) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
+ DARTSCOPE(Thread::Current());
CHECK_LENGTH(length, Array::kMaxElements);
- CHECK_CALLBACK_STATE(isolate);
- return Api::NewHandle(isolate, Array::New(length));
+ CHECK_CALLBACK_STATE(I);
+ return Api::NewHandle(I, Array::New(length));
}
-#define GET_LIST_LENGTH(isolate, type, obj, len) \
- type& array = type::Handle(isolate); \
+#define GET_LIST_LENGTH(zone, type, obj, len) \
+ type& array = type::Handle(zone); \
array ^= obj.raw(); \
*len = array.Length(); \
return Api::Success(); \
DART_EXPORT Dart_Handle Dart_ListLength(Dart_Handle list, intptr_t* len) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
- const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(list));
+ DARTSCOPE(Thread::Current());
+ const Object& obj = Object::Handle(Z, Api::UnwrapHandle(list));
if (obj.IsError()) {
// Pass through errors.
return list;
}
if (obj.IsTypedData()) {
- GET_LIST_LENGTH(isolate, TypedData, obj, len);
+ GET_LIST_LENGTH(Z, TypedData, obj, len);
}
if (obj.IsArray()) {
- GET_LIST_LENGTH(isolate, Array, obj, len);
+ GET_LIST_LENGTH(Z, Array, obj, len);
}
if (obj.IsGrowableObjectArray()) {
- GET_LIST_LENGTH(isolate, GrowableObjectArray, obj, len);
+ GET_LIST_LENGTH(Z, GrowableObjectArray, obj, len);
}
if (obj.IsExternalTypedData()) {
- GET_LIST_LENGTH(isolate, ExternalTypedData, obj, len);
+ GET_LIST_LENGTH(Z, ExternalTypedData, obj, len);
}
- CHECK_CALLBACK_STATE(isolate);
+ CHECK_CALLBACK_STATE(I);
// Now check and handle a dart object that implements the List interface.
- const Instance& instance =
- Instance::Handle(isolate, GetListInstance(isolate, obj));
+ const Instance& instance = Instance::Handle(Z, GetListInstance(Z, obj));
if (instance.IsNull()) {
return Api::NewError("Object does not implement the List interface");
}
- const String& name = String::Handle(Field::GetterName(Symbols::Length()));
+ const String& name = String::Handle(Z, Field::GetterName(Symbols::Length()));
const int kNumArgs = 1;
ArgumentsDescriptor args_desc(
- Array::Handle(ArgumentsDescriptor::New(kNumArgs)));
+ Array::Handle(Z, ArgumentsDescriptor::New(kNumArgs)));
const Function& function =
- Function::Handle(isolate, Resolver::ResolveDynamic(instance,
- name,
- args_desc));
+ Function::Handle(Z, Resolver::ResolveDynamic(instance, name, args_desc));
if (function.IsNull()) {
return Api::NewError("List object does not have a 'length' field.");
}
- const Array& args = Array::Handle(isolate, Array::New(kNumArgs));
+ const Array& args = Array::Handle(Z, Array::New(kNumArgs));
args.SetAt(0, instance); // Set up the receiver as the first argument.
const Object& retval =
- Object::Handle(isolate, DartEntry::InvokeFunction(function, args));
+ Object::Handle(Z, DartEntry::InvokeFunction(function, args));
if (retval.IsSmi()) {
*len = Smi::Cast(retval).Value();
return Api::Success();
@@ -2713,7 +2672,7 @@
return Api::NewError("Length of List object is greater than the "
"maximum value that 'len' parameter can hold");
} else if (retval.IsError()) {
- return Api::NewHandle(isolate, retval.raw());
+ return Api::NewHandle(I, retval.raw());
} else {
return Api::NewError("Length of List object is not an integer");
}
@@ -2729,25 +2688,23 @@
DART_EXPORT Dart_Handle Dart_ListGetAt(Dart_Handle list, intptr_t index) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
- const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(list));
+ DARTSCOPE(Thread::Current());
+ const Object& obj = Object::Handle(Z, Api::UnwrapHandle(list));
if (obj.IsArray()) {
- GET_LIST_ELEMENT(isolate, Array, obj, index);
+ GET_LIST_ELEMENT(I, Array, obj, index);
} else if (obj.IsGrowableObjectArray()) {
- GET_LIST_ELEMENT(isolate, GrowableObjectArray, obj, index);
+ GET_LIST_ELEMENT(I, GrowableObjectArray, obj, index);
} else if (obj.IsError()) {
return list;
} else {
- CHECK_CALLBACK_STATE(isolate);
+ CHECK_CALLBACK_STATE(I);
// Check and handle a dart object that implements the List interface.
- const Instance& instance =
- Instance::Handle(isolate, GetListInstance(isolate, obj));
+ const Instance& instance = Instance::Handle(Z, GetListInstance(Z, obj));
if (!instance.IsNull()) {
- return Api::NewHandle(isolate, Send1Arg(
+ return Api::NewHandle(I, Send1Arg(
instance,
Symbols::IndexToken(),
- Instance::Handle(isolate, Integer::New(index))));
+ Instance::Handle(Z, Integer::New(index))));
}
return Api::NewError("Object does not implement the 'List' interface");
}
@@ -2769,40 +2726,37 @@
intptr_t offset,
intptr_t length,
Dart_Handle* result) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
+ DARTSCOPE(Thread::Current());
if (result == NULL) {
RETURN_NULL_ERROR(result);
}
- const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(list));
+ const Object& obj = Object::Handle(Z, Api::UnwrapHandle(list));
if (obj.IsArray()) {
- GET_LIST_RANGE(isolate, Array, obj, offset, length);
+ GET_LIST_RANGE(I, Array, obj, offset, length);
} else if (obj.IsGrowableObjectArray()) {
- GET_LIST_RANGE(isolate, GrowableObjectArray, obj, offset, length);
+ GET_LIST_RANGE(I, GrowableObjectArray, obj, offset, length);
} else if (obj.IsError()) {
return list;
} else {
- CHECK_CALLBACK_STATE(isolate);
+ CHECK_CALLBACK_STATE(I);
// Check and handle a dart object that implements the List interface.
- const Instance& instance =
- Instance::Handle(isolate, GetListInstance(isolate, obj));
+ const Instance& instance = Instance::Handle(Z, GetListInstance(Z, obj));
if (!instance.IsNull()) {
const intptr_t kNumArgs = 2;
ArgumentsDescriptor args_desc(
Array::Handle(ArgumentsDescriptor::New(kNumArgs)));
- const Function& function = Function::Handle(
- isolate,
+ const Function& function = Function::Handle(Z,
Resolver::ResolveDynamic(instance,
Symbols::AssignIndexToken(),
args_desc));
if (!function.IsNull()) {
const Array& args = Array::Handle(Array::New(kNumArgs));
args.SetAt(0, instance);
- Instance& index = Instance::Handle(isolate);
+ Instance& index = Instance::Handle(Z);
for (intptr_t i = 0; i < length; ++i) {
index = Integer::New(i);
args.SetAt(1, index);
- Dart_Handle value = Api::NewHandle(isolate,
+ Dart_Handle value = Api::NewHandle(I,
DartEntry::InvokeFunction(function, args));
if (::Dart_IsError(value))
return value;
@@ -2816,11 +2770,11 @@
}
-#define SET_LIST_ELEMENT(isolate, type, obj, index, value) \
+#define SET_LIST_ELEMENT(type, obj, index, value) \
const type& array = type::Cast(obj); \
- const Object& value_obj = Object::Handle(isolate, Api::UnwrapHandle(value)); \
+ const Object& value_obj = Object::Handle(Z, Api::UnwrapHandle(value)); \
if (!value_obj.IsNull() && !value_obj.IsInstance()) { \
- RETURN_TYPE_ERROR(isolate, value, Instance); \
+ RETURN_TYPE_ERROR(I, value, Instance); \
} \
if ((index >= 0) && (index < array.Length())) { \
array.SetAt(index, value_obj); \
@@ -2832,45 +2786,40 @@
DART_EXPORT Dart_Handle Dart_ListSetAt(Dart_Handle list,
intptr_t index,
Dart_Handle value) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
- const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(list));
+ DARTSCOPE(Thread::Current());
+ const Object& obj = Object::Handle(Z, Api::UnwrapHandle(list));
// If the list is immutable we call into Dart for the indexed setter to
// get the unsupported operation exception as the result.
if (obj.IsArray() && !Array::Cast(obj).IsImmutable()) {
- SET_LIST_ELEMENT(isolate, Array, obj, index, value);
+ SET_LIST_ELEMENT(Array, obj, index, value);
} else if (obj.IsGrowableObjectArray()) {
- SET_LIST_ELEMENT(isolate, GrowableObjectArray, obj, index, value);
+ SET_LIST_ELEMENT(GrowableObjectArray, obj, index, value);
} else if (obj.IsError()) {
return list;
} else {
- CHECK_CALLBACK_STATE(isolate);
+ CHECK_CALLBACK_STATE(I);
// Check and handle a dart object that implements the List interface.
- const Instance& instance =
- Instance::Handle(isolate, GetListInstance(isolate, obj));
+ const Instance& instance = Instance::Handle(Z, GetListInstance(Z, obj));
if (!instance.IsNull()) {
const intptr_t kNumArgs = 3;
ArgumentsDescriptor args_desc(
Array::Handle(ArgumentsDescriptor::New(kNumArgs)));
- const Function& function = Function::Handle(
- isolate,
+ const Function& function = Function::Handle(Z,
Resolver::ResolveDynamic(instance,
Symbols::AssignIndexToken(),
args_desc));
if (!function.IsNull()) {
- const Integer& index_obj =
- Integer::Handle(isolate, Integer::New(index));
- const Object& value_obj =
- Object::Handle(isolate, Api::UnwrapHandle(value));
+ const Integer& index_obj = Integer::Handle(Z, Integer::New(index));
+ const Object& value_obj = Object::Handle(Z, Api::UnwrapHandle(value));
if (!value_obj.IsNull() && !value_obj.IsInstance()) {
- RETURN_TYPE_ERROR(isolate, value, Instance);
+ RETURN_TYPE_ERROR(I, value, Instance);
}
- const Array& args = Array::Handle(isolate, Array::New(kNumArgs));
+ const Array& args = Array::Handle(Z, Array::New(kNumArgs));
args.SetAt(0, instance);
args.SetAt(1, index_obj);
args.SetAt(2, value_obj);
- return Api::NewHandle(isolate, DartEntry::InvokeFunction(function,
+ return Api::NewHandle(I, DartEntry::InvokeFunction(function,
args));
}
}
@@ -2953,16 +2902,15 @@
}
// TODO(sgjesse): value should always be smaller then 0xff. Add error handling.
-#define GET_LIST_ELEMENT_AS_BYTES(isolate, type, obj, native_array, offset, \
- length) \
+#define GET_LIST_ELEMENT_AS_BYTES(type, obj, native_array, offset, length) \
const type& array = type::Cast(obj); \
if (Utils::RangeCheck(offset, length, array.Length())) { \
- Object& element = Object::Handle(isolate); \
+ Object& element = Object::Handle(Z); \
for (int i = 0; i < length; i++) { \
element = array.At(offset + i); \
if (!element.IsInteger()) { \
- return Api::NewHandle( \
- isolate, ThrowArgumentError("List contains non-int elements")); \
+ return Api::NewHandle(I, \
+ ThrowArgumentError("List contains non-int elements")); \
\
} \
const Integer& integer = Integer::Cast(element); \
@@ -2991,9 +2939,8 @@
intptr_t offset,
uint8_t* native_array,
intptr_t length) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
- const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(list));
+ DARTSCOPE(Thread::Current());
+ const Object& obj = Object::Handle(Z, Api::UnwrapHandle(list));
if (obj.IsTypedData()) {
const TypedData& array = TypedData::Cast(obj);
if (array.ElementSizeInBytes() == 1) {
@@ -3036,48 +2983,38 @@
}
}
if (obj.IsArray()) {
- GET_LIST_ELEMENT_AS_BYTES(isolate,
- Array,
- obj,
- native_array,
- offset,
- length);
+ GET_LIST_ELEMENT_AS_BYTES(Array, obj, native_array, offset, length);
}
if (obj.IsGrowableObjectArray()) {
- GET_LIST_ELEMENT_AS_BYTES(isolate,
- GrowableObjectArray,
- obj,
- native_array,
- offset,
- length);
+ GET_LIST_ELEMENT_AS_BYTES(
+ GrowableObjectArray, obj, native_array, offset, length);
}
if (obj.IsError()) {
return list;
}
- CHECK_CALLBACK_STATE(isolate);
+ CHECK_CALLBACK_STATE(I);
// Check and handle a dart object that implements the List interface.
const Instance& instance =
- Instance::Handle(isolate, GetListInstance(isolate, obj));
+ Instance::Handle(Z, GetListInstance(Z, obj));
if (!instance.IsNull()) {
const int kNumArgs = 2;
ArgumentsDescriptor args_desc(
Array::Handle(ArgumentsDescriptor::New(kNumArgs)));
- const Function& function = Function::Handle(
- isolate,
+ const Function& function = Function::Handle(Z,
Resolver::ResolveDynamic(instance, Symbols::IndexToken(), args_desc));
if (!function.IsNull()) {
- Object& result = Object::Handle(isolate);
- Integer& intobj = Integer::Handle(isolate);
- const Array& args = Array::Handle(isolate, Array::New(kNumArgs));
+ Object& result = Object::Handle(Z);
+ Integer& intobj = Integer::Handle(Z);
+ const Array& args = Array::Handle(Z, Array::New(kNumArgs));
args.SetAt(0, instance); // Set up the receiver as the first argument.
for (int i = 0; i < length; i++) {
- HANDLESCOPE(isolate);
+ HANDLESCOPE(T);
intobj = Integer::New(offset + i);
args.SetAt(1, intobj);
result = DartEntry::InvokeFunction(function, args);
if (result.IsError()) {
- return Api::NewHandle(isolate, result.raw());
+ return Api::NewHandle(I, result.raw());
}
if (!result.IsInteger()) {
return Api::NewError("%s expects the argument 'list' to be "
@@ -3097,10 +3034,9 @@
}
-#define SET_LIST_ELEMENT_AS_BYTES(isolate, type, obj, native_array, offset, \
- length) \
+#define SET_LIST_ELEMENT_AS_BYTES(type, obj, native_array, offset, length) \
const type& array = type::Cast(obj); \
- Integer& integer = Integer::Handle(isolate); \
+ Integer& integer = Integer::Handle(Z); \
if (Utils::RangeCheck(offset, length, array.Length())) { \
for (int i = 0; i < length; i++) { \
integer = Integer::New(native_array[i]); \
@@ -3115,9 +3051,8 @@
intptr_t offset,
uint8_t* native_array,
intptr_t length) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
- const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(list));
+ DARTSCOPE(Thread::Current());
+ const Object& obj = Object::Handle(Z, Api::UnwrapHandle(list));
if (obj.IsTypedData()) {
const TypedData& array = TypedData::Cast(obj);
if (array.ElementSizeInBytes() == 1) {
@@ -3134,52 +3069,41 @@
if (obj.IsArray() && !Array::Cast(obj).IsImmutable()) {
// If the list is immutable we call into Dart for the indexed setter to
// get the unsupported operation exception as the result.
- SET_LIST_ELEMENT_AS_BYTES(isolate,
- Array,
- obj,
- native_array,
- offset,
- length);
+ SET_LIST_ELEMENT_AS_BYTES(Array, obj, native_array, offset, length);
}
if (obj.IsGrowableObjectArray()) {
- SET_LIST_ELEMENT_AS_BYTES(isolate,
- GrowableObjectArray,
- obj,
- native_array,
- offset,
- length);
+ SET_LIST_ELEMENT_AS_BYTES(
+ GrowableObjectArray, obj, native_array, offset, length);
}
if (obj.IsError()) {
return list;
}
- CHECK_CALLBACK_STATE(isolate);
+ CHECK_CALLBACK_STATE(I);
// Check and handle a dart object that implements the List interface.
- const Instance& instance =
- Instance::Handle(isolate, GetListInstance(isolate, obj));
+ const Instance& instance = Instance::Handle(Z, GetListInstance(Z, obj));
if (!instance.IsNull()) {
const int kNumArgs = 3;
ArgumentsDescriptor args_desc(
Array::Handle(ArgumentsDescriptor::New(kNumArgs)));
- const Function& function = Function::Handle(
- isolate,
+ const Function& function = Function::Handle(Z,
Resolver::ResolveDynamic(instance,
Symbols::AssignIndexToken(),
args_desc));
if (!function.IsNull()) {
- Integer& indexobj = Integer::Handle(isolate);
- Integer& valueobj = Integer::Handle(isolate);
- const Array& args = Array::Handle(isolate, Array::New(kNumArgs));
+ Integer& indexobj = Integer::Handle(Z);
+ Integer& valueobj = Integer::Handle(Z);
+ const Array& args = Array::Handle(Z, Array::New(kNumArgs));
args.SetAt(0, instance); // Set up the receiver as the first argument.
for (int i = 0; i < length; i++) {
indexobj = Integer::New(offset + i);
valueobj = Integer::New(native_array[i]);
args.SetAt(1, indexobj);
args.SetAt(2, valueobj);
- const Object& result = Object::Handle(
- isolate, DartEntry::InvokeFunction(function, args));
+ const Object& result = Object::Handle(Z,
+ DartEntry::InvokeFunction(function, args));
if (result.IsError()) {
- return Api::NewHandle(isolate, result.raw());
+ return Api::NewHandle(I, result.raw());
}
}
return Api::Success();
@@ -3192,41 +3116,35 @@
// --- Maps ---
DART_EXPORT Dart_Handle Dart_MapGetAt(Dart_Handle map, Dart_Handle key) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
- CHECK_CALLBACK_STATE(isolate);
- const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(map));
- const Instance& instance =
- Instance::Handle(isolate, GetMapInstance(isolate, obj));
+ DARTSCOPE(Thread::Current());
+ CHECK_CALLBACK_STATE(I);
+ const Object& obj = Object::Handle(Z, Api::UnwrapHandle(map));
+ const Instance& instance = Instance::Handle(Z, GetMapInstance(Z, obj));
if (!instance.IsNull()) {
const Object& key_obj = Object::Handle(Api::UnwrapHandle(key));
if (!(key_obj.IsInstance() || key_obj.IsNull())) {
return Api::NewError("Key is not an instance");
}
- return Api::NewHandle(isolate, Send1Arg(
- instance,
- Symbols::IndexToken(),
- Instance::Cast(key_obj)));
+ return Api::NewHandle(I,
+ Send1Arg(instance, Symbols::IndexToken(), Instance::Cast(key_obj)));
}
return Api::NewError("Object does not implement the 'Map' interface");
}
DART_EXPORT Dart_Handle Dart_MapContainsKey(Dart_Handle map, Dart_Handle key) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
- CHECK_CALLBACK_STATE(isolate);
- const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(map));
- const Instance& instance =
- Instance::Handle(isolate, GetMapInstance(isolate, obj));
+ DARTSCOPE(Thread::Current());
+ CHECK_CALLBACK_STATE(I);
+ const Object& obj = Object::Handle(Z, Api::UnwrapHandle(map));
+ const Instance& instance = Instance::Handle(Z, GetMapInstance(Z, obj));
if (!instance.IsNull()) {
- const Object& key_obj = Object::Handle(Api::UnwrapHandle(key));
+ const Object& key_obj = Object::Handle(Z, Api::UnwrapHandle(key));
if (!(key_obj.IsInstance() || key_obj.IsNull())) {
return Api::NewError("Key is not an instance");
}
- return Api::NewHandle(isolate, Send1Arg(
+ return Api::NewHandle(I, Send1Arg(
instance,
- String::Handle(isolate, String::New("containsKey")),
+ String::Handle(Z, String::New("containsKey")),
Instance::Cast(key_obj)));
}
return Api::NewError("Object does not implement the 'Map' interface");
@@ -3234,19 +3152,17 @@
DART_EXPORT Dart_Handle Dart_MapKeys(Dart_Handle map) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
- CHECK_CALLBACK_STATE(isolate);
- Object& obj = Object::Handle(isolate, Api::UnwrapHandle(map));
- Instance& instance =
- Instance::Handle(isolate, GetMapInstance(isolate, obj));
+ DARTSCOPE(Thread::Current());
+ CHECK_CALLBACK_STATE(I);
+ Object& obj = Object::Handle(Z, Api::UnwrapHandle(map));
+ Instance& instance = Instance::Handle(Z, GetMapInstance(Z, obj));
if (!instance.IsNull()) {
const Object& iterator = Object::Handle(Send0Arg(
- instance, String::Handle(String::New("get:keys"))));
+ instance, String::Handle(Z, String::New("get:keys"))));
if (!iterator.IsInstance()) {
- return Api::NewHandle(isolate, iterator.raw());
+ return Api::NewHandle(I, iterator.raw());
}
- return Api::NewHandle(isolate, Send0Arg(
+ return Api::NewHandle(I, Send0Arg(
Instance::Cast(iterator),
String::Handle(String::New("toList"))));
}
@@ -3462,36 +3378,35 @@
DART_EXPORT Dart_Handle Dart_NewTypedData(Dart_TypedData_Type type,
intptr_t length) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
- CHECK_CALLBACK_STATE(isolate);
+ DARTSCOPE(Thread::Current());
+ CHECK_CALLBACK_STATE(I);
switch (type) {
case Dart_TypedData_kByteData :
- return NewByteData(isolate, length);
+ return NewByteData(I, length);
case Dart_TypedData_kInt8 :
- return NewTypedData(isolate, kTypedDataInt8ArrayCid, length);
+ return NewTypedData(I, kTypedDataInt8ArrayCid, length);
case Dart_TypedData_kUint8 :
- return NewTypedData(isolate, kTypedDataUint8ArrayCid, length);
+ return NewTypedData(I, kTypedDataUint8ArrayCid, length);
case Dart_TypedData_kUint8Clamped :
- return NewTypedData(isolate, kTypedDataUint8ClampedArrayCid, length);
+ return NewTypedData(I, kTypedDataUint8ClampedArrayCid, length);
case Dart_TypedData_kInt16 :
- return NewTypedData(isolate, kTypedDataInt16ArrayCid, length);
+ return NewTypedData(I, kTypedDataInt16ArrayCid, length);
case Dart_TypedData_kUint16 :
- return NewTypedData(isolate, kTypedDataUint16ArrayCid, length);
+ return NewTypedData(I, kTypedDataUint16ArrayCid, length);
case Dart_TypedData_kInt32 :
- return NewTypedData(isolate, kTypedDataInt32ArrayCid, length);
+ return NewTypedData(I, kTypedDataInt32ArrayCid, length);
case Dart_TypedData_kUint32 :
- return NewTypedData(isolate, kTypedDataUint32ArrayCid, length);
+ return NewTypedData(I, kTypedDataUint32ArrayCid, length);
case Dart_TypedData_kInt64 :
- return NewTypedData(isolate, kTypedDataInt64ArrayCid, length);
+ return NewTypedData(I, kTypedDataInt64ArrayCid, length);
case Dart_TypedData_kUint64 :
- return NewTypedData(isolate, kTypedDataUint64ArrayCid, length);
+ return NewTypedData(I, kTypedDataUint64ArrayCid, length);
case Dart_TypedData_kFloat32 :
- return NewTypedData(isolate, kTypedDataFloat32ArrayCid, length);
+ return NewTypedData(I, kTypedDataFloat32ArrayCid, length);
case Dart_TypedData_kFloat64 :
- return NewTypedData(isolate, kTypedDataFloat64ArrayCid, length);
+ return NewTypedData(I, kTypedDataFloat64ArrayCid, length);
case Dart_TypedData_kFloat32x4:
- return NewTypedData(isolate, kTypedDataFloat32x4ArrayCid, length);
+ return NewTypedData(I, kTypedDataFloat32x4ArrayCid, length);
default:
return Api::NewError("%s expects argument 'type' to be of 'TypedData'",
CURRENT_FUNC);
@@ -3505,75 +3420,50 @@
Dart_TypedData_Type type,
void* data,
intptr_t length) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
+ DARTSCOPE(Thread::Current());
if (data == NULL && length != 0) {
RETURN_NULL_ERROR(data);
}
- CHECK_CALLBACK_STATE(isolate);
+ CHECK_CALLBACK_STATE(I);
switch (type) {
case Dart_TypedData_kByteData:
- return NewExternalByteData(isolate, data, length);
+ return NewExternalByteData(I, data, length);
case Dart_TypedData_kInt8:
- return NewExternalTypedData(isolate,
- kExternalTypedDataInt8ArrayCid,
- data,
- length);
+ return NewExternalTypedData(I,
+ kExternalTypedDataInt8ArrayCid, data, length);
case Dart_TypedData_kUint8:
- return NewExternalTypedData(isolate,
- kExternalTypedDataUint8ArrayCid,
- data,
- length);
+ return NewExternalTypedData(I,
+ kExternalTypedDataUint8ArrayCid, data, length);
case Dart_TypedData_kUint8Clamped:
- return NewExternalTypedData(isolate,
- kExternalTypedDataUint8ClampedArrayCid,
- data,
- length);
+ return NewExternalTypedData(I,
+ kExternalTypedDataUint8ClampedArrayCid, data, length);
case Dart_TypedData_kInt16:
- return NewExternalTypedData(isolate,
- kExternalTypedDataInt16ArrayCid,
- data,
- length);
+ return NewExternalTypedData(I,
+ kExternalTypedDataInt16ArrayCid, data, length);
case Dart_TypedData_kUint16:
- return NewExternalTypedData(isolate,
- kExternalTypedDataUint16ArrayCid,
- data,
- length);
+ return NewExternalTypedData(I,
+ kExternalTypedDataUint16ArrayCid, data, length);
case Dart_TypedData_kInt32:
- return NewExternalTypedData(isolate,
- kExternalTypedDataInt32ArrayCid,
- data,
- length);
+ return NewExternalTypedData(I,
+ kExternalTypedDataInt32ArrayCid, data, length);
case Dart_TypedData_kUint32:
- return NewExternalTypedData(isolate,
- kExternalTypedDataUint32ArrayCid,
- data,
- length);
+ return NewExternalTypedData(I,
+ kExternalTypedDataUint32ArrayCid, data, length);
case Dart_TypedData_kInt64:
- return NewExternalTypedData(isolate,
- kExternalTypedDataInt64ArrayCid,
- data,
- length);
+ return NewExternalTypedData(I,
+ kExternalTypedDataInt64ArrayCid, data, length);
case Dart_TypedData_kUint64:
- return NewExternalTypedData(isolate,
- kExternalTypedDataUint64ArrayCid,
- data,
- length);
+ return NewExternalTypedData(I,
+ kExternalTypedDataUint64ArrayCid, data, length);
case Dart_TypedData_kFloat32:
- return NewExternalTypedData(isolate,
- kExternalTypedDataFloat32ArrayCid,
- data,
- length);
+ return NewExternalTypedData(I,
+ kExternalTypedDataFloat32ArrayCid, data, length);
case Dart_TypedData_kFloat64:
- return NewExternalTypedData(isolate,
- kExternalTypedDataFloat64ArrayCid,
- data,
- length);
+ return NewExternalTypedData(I,
+ kExternalTypedDataFloat64ArrayCid, data, length);
case Dart_TypedData_kFloat32x4:
- return NewExternalTypedData(isolate,
- kExternalTypedDataFloat32x4ArrayCid,
- data,
- length);
+ return NewExternalTypedData(I,
+ kExternalTypedDataFloat32x4ArrayCid, data, length);
default:
return Api::NewError("%s expects argument 'type' to be of"
" 'external TypedData'", CURRENT_FUNC);
@@ -3602,16 +3492,15 @@
DART_EXPORT Dart_Handle Dart_NewByteBuffer(Dart_Handle typed_data) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
+ DARTSCOPE(Thread::Current());
intptr_t class_id = Api::ClassId(typed_data);
if (!RawObject::IsExternalTypedDataClassId(class_id) &&
!RawObject::IsTypedDataViewClassId(class_id) &&
!RawObject::IsTypedDataClassId(class_id)) {
- RETURN_TYPE_ERROR(isolate, typed_data, 'TypedData');
+ RETURN_TYPE_ERROR(I, typed_data, 'TypedData');
}
- Object& result = Object::Handle(isolate);
- result = GetByteBufferConstructor(isolate,
+ Object& result = Object::Handle(Z);
+ result = GetByteBufferConstructor(I,
Symbols::_ByteBuffer(),
Symbols::_ByteBufferDot_New(),
1);
@@ -3621,16 +3510,16 @@
ASSERT(!factory.IsGenerativeConstructor());
// Create the argument list.
- const Array& args = Array::Handle(isolate, Array::New(2));
+ const Array& args = Array::Handle(Z, Array::New(2));
// Factories get type arguments.
args.SetAt(0, Object::null_type_arguments());
- const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(typed_data));
+ const Object& obj = Object::Handle(Z, Api::UnwrapHandle(typed_data));
args.SetAt(1, obj);
// Invoke the factory constructor and return the new object.
result = DartEntry::InvokeFunction(factory, args);
ASSERT(result.IsInstance() || result.IsNull() || result.IsError());
- return Api::NewHandle(isolate, result.raw());
+ return Api::NewHandle(I, result.raw());
}
@@ -3671,14 +3560,12 @@
Dart_TypedData_Type* type,
void** data,
intptr_t* len) {
- Thread* thread = Thread::Current();
- Isolate* isolate = thread->isolate();
- DARTSCOPE(isolate);
+ DARTSCOPE(Thread::Current());
intptr_t class_id = Api::ClassId(object);
if (!RawObject::IsExternalTypedDataClassId(class_id) &&
!RawObject::IsTypedDataViewClassId(class_id) &&
!RawObject::IsTypedDataClassId(class_id)) {
- RETURN_TYPE_ERROR(isolate, object, 'TypedData');
+ RETURN_TYPE_ERROR(I, object, 'TypedData');
}
if (type == NULL) {
RETURN_NULL_ERROR(type);
@@ -3698,7 +3585,7 @@
// If it is an external typed data object just return the data field.
if (RawObject::IsExternalTypedDataClassId(class_id)) {
const ExternalTypedData& obj =
- Api::UnwrapExternalTypedDataHandle(isolate, object);
+ Api::UnwrapExternalTypedDataHandle(I, object);
ASSERT(!obj.IsNull());
length = obj.Length();
size_in_bytes = length * ExternalTypedData::ElementSizeInBytes(class_id);
@@ -3706,16 +3593,16 @@
external = true;
} else if (RawObject::IsTypedDataClassId(class_id)) {
// Regular typed data object, set up some GC and API callback guards.
- const TypedData& obj = Api::UnwrapTypedDataHandle(isolate, object);
+ const TypedData& obj = Api::UnwrapTypedDataHandle(I, object);
ASSERT(!obj.IsNull());
length = obj.Length();
size_in_bytes = length * TypedData::ElementSizeInBytes(class_id);
- thread->IncrementNoSafepointScopeDepth();
- START_NO_CALLBACK_SCOPE(isolate);
+ T->IncrementNoSafepointScopeDepth();
+ START_NO_CALLBACK_SCOPE(I);
data_tmp = obj.DataAddr(0);
} else {
ASSERT(RawObject::IsTypedDataViewClassId(class_id));
- const Instance& view_obj = Api::UnwrapInstanceHandle(isolate, object);
+ const Instance& view_obj = Api::UnwrapInstanceHandle(I, object);
ASSERT(!view_obj.IsNull());
Smi& val = Smi::Handle();
val ^= TypedDataView::Length(view_obj);
@@ -3724,8 +3611,8 @@
val ^= TypedDataView::OffsetInBytes(view_obj);
intptr_t offset_in_bytes = val.Value();
const Instance& obj = Instance::Handle(TypedDataView::Data(view_obj));
- thread->IncrementNoSafepointScopeDepth();
- START_NO_CALLBACK_SCOPE(isolate);
+ T->IncrementNoSafepointScopeDepth();
+ START_NO_CALLBACK_SCOPE(I);
if (TypedData::IsTypedData(obj)) {
const TypedData& data_obj = TypedData::Cast(obj);
data_tmp = data_obj.DataAddr(offset_in_bytes);
@@ -3738,12 +3625,12 @@
}
if (FLAG_verify_acquired_data) {
if (external) {
- ASSERT(!isolate->heap()->Contains(reinterpret_cast<uword>(data_tmp)));
+ ASSERT(!I->heap()->Contains(reinterpret_cast<uword>(data_tmp)));
} else {
- ASSERT(isolate->heap()->Contains(reinterpret_cast<uword>(data_tmp)));
+ ASSERT(I->heap()->Contains(reinterpret_cast<uword>(data_tmp)));
}
- const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(object));
- WeakTable* table = isolate->api_state()->acquired_table();
+ const Object& obj = Object::Handle(Z, Api::UnwrapHandle(object));
+ WeakTable* table = I->api_state()->acquired_table();
intptr_t current = table->GetValue(obj.raw());
if (current != 0) {
return Api::NewError("Data was already acquired for this object.");
@@ -3762,22 +3649,20 @@
DART_EXPORT Dart_Handle Dart_TypedDataReleaseData(Dart_Handle object) {
- Thread* thread = Thread::Current();
- Isolate* isolate = thread->isolate();
- DARTSCOPE(isolate);
+ DARTSCOPE(Thread::Current());
intptr_t class_id = Api::ClassId(object);
if (!RawObject::IsExternalTypedDataClassId(class_id) &&
!RawObject::IsTypedDataViewClassId(class_id) &&
!RawObject::IsTypedDataClassId(class_id)) {
- RETURN_TYPE_ERROR(isolate, object, 'TypedData');
+ RETURN_TYPE_ERROR(I, object, 'TypedData');
}
if (!RawObject::IsExternalTypedDataClassId(class_id)) {
- thread->DecrementNoSafepointScopeDepth();
- END_NO_CALLBACK_SCOPE(isolate);
+ T->DecrementNoSafepointScopeDepth();
+ END_NO_CALLBACK_SCOPE(I);
}
if (FLAG_verify_acquired_data) {
- const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(object));
- WeakTable* table = isolate->api_state()->acquired_table();
+ const Object& obj = Object::Handle(Z, Api::UnwrapHandle(object));
+ WeakTable* table = I->api_state()->acquired_table();
intptr_t current = table->GetValue(obj.raw());
if (current == 0) {
return Api::NewError("Data was not acquired for this object.");
@@ -3857,10 +3742,9 @@
Dart_Handle constructor_name,
int number_of_arguments,
Dart_Handle* arguments) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
- CHECK_CALLBACK_STATE(isolate);
- Object& result = Object::Handle(isolate);
+ DARTSCOPE(Thread::Current());
+ CHECK_CALLBACK_STATE(I);
+ Object& result = Object::Handle(Z);
if (number_of_arguments < 0) {
return Api::NewError(
@@ -3871,7 +3755,7 @@
// Get the class to instantiate.
Object& unchecked_type = Object::Handle(Api::UnwrapHandle(type));
if (unchecked_type.IsNull() || !unchecked_type.IsType()) {
- RETURN_TYPE_ERROR(isolate, type, Type);
+ RETURN_TYPE_ERROR(I, type, Type);
}
Type& type_obj = Type::Handle();
type_obj ^= unchecked_type.raw();
@@ -3880,21 +3764,21 @@
"%s expects argument 'type' to be a fully resolved type.",
CURRENT_FUNC);
}
- Class& cls = Class::Handle(isolate, type_obj.type_class());
+ Class& cls = Class::Handle(Z, type_obj.type_class());
TypeArguments& type_arguments =
- TypeArguments::Handle(isolate, type_obj.arguments());
+ TypeArguments::Handle(Z, type_obj.arguments());
- const String& base_constructor_name = String::Handle(isolate, cls.Name());
+ const String& base_constructor_name = String::Handle(Z, cls.Name());
// And get the name of the constructor to invoke.
- String& dot_name = String::Handle(isolate);
+ String& dot_name = String::Handle(Z);
result = Api::UnwrapHandle(constructor_name);
if (result.IsNull()) {
dot_name = Symbols::Dot().raw();
} else if (result.IsString()) {
dot_name = String::Concat(Symbols::Dot(), String::Cast(result));
} else {
- RETURN_TYPE_ERROR(isolate, constructor_name, String);
+ RETURN_TYPE_ERROR(I, constructor_name, String);
}
// Resolve the constructor.
@@ -3906,20 +3790,20 @@
constr_name,
number_of_arguments);
if (result.IsError()) {
- return Api::NewHandle(isolate, result.raw());
+ return Api::NewHandle(I, result.raw());
}
ASSERT(result.IsFunction());
- Function& constructor = Function::Handle(isolate);
+ Function& constructor = Function::Handle(Z);
constructor ^= result.raw();
- Instance& new_object = Instance::Handle(isolate);
+ Instance& new_object = Instance::Handle(Z);
if (constructor.IsRedirectingFactory()) {
ClassFinalizer::ResolveRedirectingFactory(cls, constructor);
Type& redirect_type = Type::Handle(constructor.RedirectionType());
constructor = constructor.RedirectionTarget();
if (constructor.IsNull()) {
ASSERT(redirect_type.IsMalformed());
- return Api::NewHandle(isolate, redirect_type.error());
+ return Api::NewHandle(I, redirect_type.error());
}
if (!redirect_type.IsInstantiated()) {
@@ -3929,7 +3813,7 @@
redirect_type ^= redirect_type.InstantiateFrom(type_arguments,
&bound_error);
if (!bound_error.IsNull()) {
- return Api::NewHandle(isolate, bound_error.raw());
+ return Api::NewHandle(I, bound_error.raw());
}
redirect_type ^= redirect_type.Canonicalize();
}
@@ -3948,7 +3832,7 @@
intptr_t arg_index = 0;
int extra_args = (constructor.IsGenerativeConstructor() ? 2 : 1);
const Array& args =
- Array::Handle(isolate, Array::New(number_of_arguments + extra_args));
+ Array::Handle(Z, Array::New(number_of_arguments + extra_args));
if (constructor.IsGenerativeConstructor()) {
// Constructors get the uninitialized object and a constructor phase.
if (!type_arguments.IsNull()) {
@@ -3958,18 +3842,17 @@
new_object.SetTypeArguments(type_arguments);
}
args.SetAt(arg_index++, new_object);
- args.SetAt(arg_index++,
- Smi::Handle(isolate, Smi::New(Function::kCtorPhaseAll)));
+ args.SetAt(arg_index++, Smi::Handle(Z, Smi::New(Function::kCtorPhaseAll)));
} else {
// Factories get type arguments.
args.SetAt(arg_index++, type_arguments);
}
- Object& argument = Object::Handle(isolate);
+ Object& argument = Object::Handle(Z);
for (int i = 0; i < number_of_arguments; i++) {
argument = Api::UnwrapHandle(arguments[i]);
if (!argument.IsNull() && !argument.IsInstance()) {
if (argument.IsError()) {
- return Api::NewHandle(isolate, argument.raw());
+ return Api::NewHandle(I, argument.raw());
} else {
return Api::NewError(
"%s expects arguments[%d] to be an Instance handle.",
@@ -3982,7 +3865,7 @@
// Invoke the constructor and return the new object.
result = DartEntry::InvokeFunction(constructor, args);
if (result.IsError()) {
- return Api::NewHandle(isolate, result.raw());
+ return Api::NewHandle(I, result.raw());
}
if (constructor.IsGenerativeConstructor()) {
@@ -3991,7 +3874,7 @@
ASSERT(result.IsNull() || result.IsInstance());
new_object ^= result.raw();
}
- return Api::NewHandle(isolate, new_object.raw());
+ return Api::NewHandle(I, new_object.raw());
}
@@ -4022,22 +3905,21 @@
DART_EXPORT Dart_Handle Dart_Allocate(Dart_Handle type) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
- CHECK_CALLBACK_STATE(isolate);
+ DARTSCOPE(Thread::Current());
+ CHECK_CALLBACK_STATE(I);
- const Type& type_obj = Api::UnwrapTypeHandle(isolate, type);
+ const Type& type_obj = Api::UnwrapTypeHandle(I, type);
// Get the class to instantiate.
if (type_obj.IsNull()) {
- RETURN_TYPE_ERROR(isolate, type, Type);
+ RETURN_TYPE_ERROR(I, type, Type);
}
- const Class& cls = Class::Handle(isolate, type_obj.type_class());
- const Error& error = Error::Handle(isolate, cls.EnsureIsFinalized(isolate));
+ const Class& cls = Class::Handle(Z, type_obj.type_class());
+ const Error& error = Error::Handle(Z, cls.EnsureIsFinalized(I));
if (!error.IsNull()) {
// An error occurred, return error object.
- return Api::NewHandle(isolate, error.raw());
+ return Api::NewHandle(I, error.raw());
}
- return Api::NewHandle(isolate, AllocateObject(isolate, cls));
+ return Api::NewHandle(I, AllocateObject(I, cls));
}
@@ -4045,33 +3927,31 @@
Dart_Handle type,
intptr_t num_native_fields,
const intptr_t* native_fields) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
- CHECK_CALLBACK_STATE(isolate);
+ DARTSCOPE(Thread::Current());
+ CHECK_CALLBACK_STATE(I);
- const Type& type_obj = Api::UnwrapTypeHandle(isolate, type);
+ const Type& type_obj = Api::UnwrapTypeHandle(I, type);
// Get the class to instantiate.
if (type_obj.IsNull()) {
- RETURN_TYPE_ERROR(isolate, type, Type);
+ RETURN_TYPE_ERROR(I, type, Type);
}
if (native_fields == NULL) {
RETURN_NULL_ERROR(native_fields);
}
- const Class& cls = Class::Handle(isolate, type_obj.type_class());
- const Error& error = Error::Handle(isolate, cls.EnsureIsFinalized(isolate));
+ const Class& cls = Class::Handle(Z, type_obj.type_class());
+ const Error& error = Error::Handle(Z, cls.EnsureIsFinalized(I));
if (!error.IsNull()) {
// An error occurred, return error object.
- return Api::NewHandle(isolate, error.raw());
+ return Api::NewHandle(I, error.raw());
}
if (num_native_fields != cls.num_native_fields()) {
return Api::NewError(
"%s: invalid number of native fields %" Pd " passed in, expected %d",
CURRENT_FUNC, num_native_fields, cls.num_native_fields());
}
- const Instance& instance = Instance::Handle(isolate,
- AllocateObject(isolate, cls));
+ const Instance& instance = Instance::Handle(Z, AllocateObject(I, cls));
instance.SetNativeFields(num_native_fields, native_fields);
- return Api::NewHandle(isolate, instance.raw());
+ return Api::NewHandle(I, instance.raw());
}
@@ -4105,22 +3985,21 @@
Dart_Handle name,
int number_of_arguments,
Dart_Handle* arguments) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
- CHECK_CALLBACK_STATE(isolate);
+ DARTSCOPE(Thread::Current());
+ CHECK_CALLBACK_STATE(I);
if (number_of_arguments < 0) {
return Api::NewError(
"%s expects argument 'number_of_arguments' to be non-negative.",
CURRENT_FUNC);
}
- const String& constructor_name = Api::UnwrapStringHandle(isolate, name);
+ const String& constructor_name = Api::UnwrapStringHandle(I, name);
if (constructor_name.IsNull()) {
- RETURN_TYPE_ERROR(isolate, name, String);
+ RETURN_TYPE_ERROR(I, name, String);
}
- const Instance& instance = Api::UnwrapInstanceHandle(isolate, object);
+ const Instance& instance = Api::UnwrapInstanceHandle(I, object);
if (instance.IsNull()) {
- RETURN_TYPE_ERROR(isolate, object, Instance);
+ RETURN_TYPE_ERROR(I, object, Instance);
}
// Since we have allocated an object it would mean that the type
@@ -4129,18 +4008,18 @@
// once for the same object.
// Construct name of the constructor to invoke.
- const Type& type_obj = Type::Handle(isolate, instance.GetType());
- const Class& cls = Class::Handle(isolate, type_obj.type_class());
- const String& class_name = String::Handle(isolate, cls.Name());
- const Array& strings = Array::Handle(Array::New(3));
+ const Type& type_obj = Type::Handle(Z, instance.GetType());
+ const Class& cls = Class::Handle(Z, type_obj.type_class());
+ const String& class_name = String::Handle(Z, cls.Name());
+ const Array& strings = Array::Handle(Z, Array::New(3));
strings.SetAt(0, class_name);
strings.SetAt(1, Symbols::Dot());
strings.SetAt(2, constructor_name);
- const String& dot_name = String::Handle(isolate, String::ConcatAll(strings));
+ const String& dot_name = String::Handle(Z, String::ConcatAll(strings));
const TypeArguments& type_arguments =
- TypeArguments::Handle(isolate, type_obj.arguments());
+ TypeArguments::Handle(Z, type_obj.arguments());
const Function& constructor =
- Function::Handle(isolate, cls.LookupFunctionAllowPrivate(dot_name));
+ Function::Handle(Z, cls.LookupFunctionAllowPrivate(dot_name));
const int extra_args = 2;
if (!constructor.IsNull() &&
constructor.IsGenerativeConstructor() &&
@@ -4157,22 +4036,18 @@
instance.SetTypeArguments(type_arguments);
}
Dart_Handle result;
- Array& args = Array::Handle(isolate);
- result = SetupArguments(isolate,
- number_of_arguments,
- arguments,
- extra_args,
- &args);
+ Array& args = Array::Handle(Z);
+ result = SetupArguments(I,
+ number_of_arguments, arguments, extra_args, &args);
if (!::Dart_IsError(result)) {
args.SetAt(0, instance);
- args.SetAt(1, Smi::Handle(isolate, Smi::New(Function::kCtorPhaseAll)));
- const Object& retval = Object::Handle(
- isolate,
+ args.SetAt(1, Smi::Handle(Z, Smi::New(Function::kCtorPhaseAll)));
+ const Object& retval = Object::Handle(Z,
DartEntry::InvokeFunction(constructor, args));
if (retval.IsError()) {
- result = Api::NewHandle(isolate, retval.raw());
+ result = Api::NewHandle(I, retval.raw());
} else {
- result = Api::NewHandle(isolate, instance.raw());
+ result = Api::NewHandle(I, instance.raw());
}
}
return result;
@@ -4187,29 +4062,27 @@
Dart_Handle name,
int number_of_arguments,
Dart_Handle* arguments) {
- Thread* thread = Thread::Current();
- Isolate* isolate = thread->isolate();
- DARTSCOPE(isolate);
- CHECK_CALLBACK_STATE(isolate);
+ DARTSCOPE(Thread::Current());
+ CHECK_CALLBACK_STATE(I);
// TODO(turnidge): This is a bit simplistic. It overcounts when
// other operations (gc, compilation) are active.
- TIMERSCOPE(thread, time_dart_execution);
+ TIMERSCOPE(T, time_dart_execution);
- const String& function_name = Api::UnwrapStringHandle(isolate, name);
+ const String& function_name = Api::UnwrapStringHandle(I, name);
if (function_name.IsNull()) {
- RETURN_TYPE_ERROR(isolate, name, String);
+ RETURN_TYPE_ERROR(I, name, String);
}
if (number_of_arguments < 0) {
return Api::NewError(
"%s expects argument 'number_of_arguments' to be non-negative.",
CURRENT_FUNC);
}
- const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(target));
+ const Object& obj = Object::Handle(Z, Api::UnwrapHandle(target));
if (obj.IsError()) {
return target;
}
Dart_Handle result;
- Array& args = Array::Handle(isolate);
+ Array& args = Array::Handle(Z);
if (obj.IsType()) {
if (!Type::Cast(obj).IsFinalized()) {
return Api::NewError(
@@ -4217,41 +4090,38 @@
CURRENT_FUNC);
}
- const Class& cls = Class::Handle(isolate, Type::Cast(obj).type_class());
- const Function& function = Function::Handle(
- isolate,
+ const Class& cls = Class::Handle(Z, Type::Cast(obj).type_class());
+ const Function& function = Function::Handle(Z,
Resolver::ResolveStaticAllowPrivate(cls,
function_name,
number_of_arguments,
Object::empty_array()));
if (function.IsNull()) {
- const String& cls_name = String::Handle(isolate, cls.Name());
+ const String& cls_name = String::Handle(Z, cls.Name());
return Api::NewError("%s: did not find static method '%s.%s'.",
CURRENT_FUNC,
cls_name.ToCString(),
function_name.ToCString());
}
// Setup args and check for malformed arguments in the arguments list.
- result = SetupArguments(isolate, number_of_arguments, arguments, 0, &args);
+ result = SetupArguments(I, number_of_arguments, arguments, 0, &args);
if (!::Dart_IsError(result)) {
- result = Api::NewHandle(isolate,
- DartEntry::InvokeFunction(function, args));
+ result = Api::NewHandle(I, DartEntry::InvokeFunction(function, args));
}
return result;
} else if (obj.IsNull() || obj.IsInstance()) {
// Since we have allocated an object it would mean that the type of the
// receiver is already resolved and finalized, hence it is not necessary
// to check here.
- Instance& instance = Instance::Handle(isolate);
+ Instance& instance = Instance::Handle(Z);
instance ^= obj.raw();
ArgumentsDescriptor args_desc(
- Array::Handle(ArgumentsDescriptor::New(number_of_arguments + 1)));
- const Function& function = Function::Handle(
- isolate,
+ Array::Handle(Z, ArgumentsDescriptor::New(number_of_arguments + 1)));
+ const Function& function = Function::Handle(Z,
Resolver::ResolveDynamic(instance, function_name, args_desc));
if (function.IsNull()) {
// Setup args and check for malformed arguments in the arguments list.
- result = SetupArguments(isolate,
+ result = SetupArguments(I,
number_of_arguments,
arguments,
1,
@@ -4259,8 +4129,8 @@
if (!::Dart_IsError(result)) {
args.SetAt(0, instance);
const Array& args_descriptor =
- Array::Handle(ArgumentsDescriptor::New(args.Length()));
- result = Api::NewHandle(isolate,
+ Array::Handle(Z, ArgumentsDescriptor::New(args.Length()));
+ result = Api::NewHandle(I,
DartEntry::InvokeNoSuchMethod(instance,
function_name,
args,
@@ -4269,11 +4139,10 @@
return result;
}
// Setup args and check for malformed arguments in the arguments list.
- result = SetupArguments(isolate, number_of_arguments, arguments, 1, &args);
+ result = SetupArguments(I, number_of_arguments, arguments, 1, &args);
if (!::Dart_IsError(result)) {
args.SetAt(0, instance);
- result = Api::NewHandle(isolate,
- DartEntry::InvokeFunction(function, args));
+ result = Api::NewHandle(I, DartEntry::InvokeFunction(function, args));
}
return result;
} else if (obj.IsLibrary()) {
@@ -4288,8 +4157,7 @@
}
const Function& function =
- Function::Handle(isolate,
- lib.LookupFunctionAllowPrivate(function_name));
+ Function::Handle(Z, lib.LookupFunctionAllowPrivate(function_name));
if (function.IsNull()) {
return Api::NewError("%s: did not find top-level function '%s'.",
CURRENT_FUNC,
@@ -4297,7 +4165,7 @@
}
// LookupFunctionAllowPrivate does not check argument arity, so we
// do it here.
- String& error_message = String::Handle();
+ String& error_message = String::Handle(Z);
if (!function.AreValidArgumentCounts(number_of_arguments,
0,
&error_message)) {
@@ -4307,10 +4175,9 @@
error_message.ToCString());
}
// Setup args and check for malformed arguments in the arguments list.
- result = SetupArguments(isolate, number_of_arguments, arguments, 0, &args);
+ result = SetupArguments(I, number_of_arguments, arguments, 0, &args);
if (!::Dart_IsError(result)) {
- result = Api::NewHandle(isolate,
- DartEntry::InvokeFunction(function, args));
+ result = Api::NewHandle(I, DartEntry::InvokeFunction(function, args));
}
return result;
} else {
@@ -4324,12 +4191,11 @@
DART_EXPORT Dart_Handle Dart_InvokeClosure(Dart_Handle closure,
int number_of_arguments,
Dart_Handle* arguments) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
- CHECK_CALLBACK_STATE(isolate);
- const Instance& closure_obj = Api::UnwrapInstanceHandle(isolate, closure);
+ DARTSCOPE(Thread::Current());
+ CHECK_CALLBACK_STATE(I);
+ const Instance& closure_obj = Api::UnwrapInstanceHandle(I, closure);
if (closure_obj.IsNull() || !closure_obj.IsCallable(NULL)) {
- RETURN_TYPE_ERROR(isolate, closure, Instance);
+ RETURN_TYPE_ERROR(I, closure, Instance);
}
if (number_of_arguments < 0) {
return Api::NewError(
@@ -4338,35 +4204,33 @@
}
// Set up arguments to include the closure as the first argument.
- const Array& args = Array::Handle(isolate,
- Array::New(number_of_arguments + 1));
- Object& obj = Object::Handle(isolate);
+ const Array& args = Array::Handle(Z, Array::New(number_of_arguments + 1));
+ Object& obj = Object::Handle(Z);
args.SetAt(0, closure_obj);
for (int i = 0; i < number_of_arguments; i++) {
obj = Api::UnwrapHandle(arguments[i]);
if (!obj.IsNull() && !obj.IsInstance()) {
- RETURN_TYPE_ERROR(isolate, arguments[i], Instance);
+ RETURN_TYPE_ERROR(I, arguments[i], Instance);
}
args.SetAt(i + 1, obj);
}
// Now try to invoke the closure.
- return Api::NewHandle(isolate, DartEntry::InvokeClosure(args));
+ return Api::NewHandle(I, DartEntry::InvokeClosure(args));
}
DART_EXPORT Dart_Handle Dart_GetField(Dart_Handle container, Dart_Handle name) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
- CHECK_CALLBACK_STATE(isolate);
+ DARTSCOPE(Thread::Current());
+ CHECK_CALLBACK_STATE(I);
- const String& field_name = Api::UnwrapStringHandle(isolate, name);
+ const String& field_name = Api::UnwrapStringHandle(I, name);
if (field_name.IsNull()) {
- RETURN_TYPE_ERROR(isolate, name, String);
+ RETURN_TYPE_ERROR(I, name, String);
}
- Field& field = Field::Handle(isolate);
- Function& getter = Function::Handle(isolate);
- const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(container));
+ Field& field = Field::Handle(Z);
+ Function& getter = Function::Handle(Z);
+ const Object& obj = Object::Handle(Z, Api::UnwrapHandle(container));
if (obj.IsNull()) {
return Api::NewError("%s expects argument 'container' to be non-null.",
CURRENT_FUNC);
@@ -4378,21 +4242,21 @@
}
// To access a static field we may need to use the Field or the
// getter Function.
- Class& cls = Class::Handle(isolate, Type::Cast(obj).type_class());
+ Class& cls = Class::Handle(Z, Type::Cast(obj).type_class());
field = cls.LookupStaticField(field_name);
if (field.IsNull() || field.IsUninitialized()) {
const String& getter_name =
- String::Handle(isolate, Field::GetterName(field_name));
+ String::Handle(Z, Field::GetterName(field_name));
getter = cls.LookupStaticFunctionAllowPrivate(getter_name);
}
if (!getter.IsNull()) {
// Invoke the getter and return the result.
- return Api::NewHandle(
- isolate, DartEntry::InvokeFunction(getter, Object::empty_array()));
+ return Api::NewHandle(I,
+ DartEntry::InvokeFunction(getter, Object::empty_array()));
} else if (!field.IsNull()) {
- return Api::NewHandle(isolate, field.value());
+ return Api::NewHandle(I, field.value());
} else {
return Api::NewError("%s: did not find static field '%s'.",
CURRENT_FUNC, field_name.ToCString());
@@ -4403,9 +4267,8 @@
// getter in any superclass and use that function to access the
// field.
const Instance& instance = Instance::Cast(obj);
- Class& cls = Class::Handle(isolate, instance.clazz());
- String& getter_name =
- String::Handle(isolate, Field::GetterName(field_name));
+ Class& cls = Class::Handle(Z, instance.clazz());
+ String& getter_name = String::Handle(Z, Field::GetterName(field_name));
while (!cls.IsNull()) {
getter = cls.LookupDynamicFunctionAllowPrivate(getter_name);
if (!getter.IsNull()) {
@@ -4416,18 +4279,18 @@
// Invoke the getter and return the result.
const int kNumArgs = 1;
- const Array& args = Array::Handle(isolate, Array::New(kNumArgs));
+ const Array& args = Array::Handle(Z, Array::New(kNumArgs));
args.SetAt(0, instance);
if (getter.IsNull()) {
const Array& args_descriptor =
- Array::Handle(ArgumentsDescriptor::New(args.Length()));
- return Api::NewHandle(isolate,
+ Array::Handle(Z, ArgumentsDescriptor::New(args.Length()));
+ return Api::NewHandle(I,
DartEntry::InvokeNoSuchMethod(instance,
getter_name,
args,
args_descriptor));
}
- return Api::NewHandle(isolate, DartEntry::InvokeFunction(getter, args));
+ return Api::NewHandle(I, DartEntry::InvokeFunction(getter, args));
} else if (obj.IsLibrary()) {
// To access a top-level we may need to use the Field or the
@@ -4444,23 +4307,23 @@
if (field.IsNull()) {
// No field found and no ambiguity error. Check for a getter in the lib.
const String& getter_name =
- String::Handle(isolate, Field::GetterName(field_name));
+ String::Handle(Z, Field::GetterName(field_name));
getter = lib.LookupFunctionAllowPrivate(getter_name);
} else if (!field.IsNull() && field.IsUninitialized()) {
// A field was found. Check for a getter in the field's owner classs.
- const Class& cls = Class::Handle(isolate, field.owner());
- const String& getter_name =
- String::Handle(isolate, Field::GetterName(field_name));
+ const Class& cls = Class::Handle(Z, field.owner());
+ const String& getter_name = String::Handle(Z,
+ Field::GetterName(field_name));
getter = cls.LookupStaticFunctionAllowPrivate(getter_name);
}
if (!getter.IsNull()) {
// Invoke the getter and return the result.
- return Api::NewHandle(
- isolate, DartEntry::InvokeFunction(getter, Object::empty_array()));
+ return Api::NewHandle(I,
+ DartEntry::InvokeFunction(getter, Object::empty_array()));
}
if (!field.IsNull()) {
- return Api::NewHandle(isolate, field.value());
+ return Api::NewHandle(I, field.value());
}
return Api::NewError("%s: did not find top-level variable '%s'.",
CURRENT_FUNC, field_name.ToCString());
@@ -4478,26 +4341,25 @@
DART_EXPORT Dart_Handle Dart_SetField(Dart_Handle container,
Dart_Handle name,
Dart_Handle value) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
- CHECK_CALLBACK_STATE(isolate);
+ DARTSCOPE(Thread::Current());
+ CHECK_CALLBACK_STATE(I);
- const String& field_name = Api::UnwrapStringHandle(isolate, name);
+ const String& field_name = Api::UnwrapStringHandle(I, name);
if (field_name.IsNull()) {
- RETURN_TYPE_ERROR(isolate, name, String);
+ RETURN_TYPE_ERROR(I, name, String);
}
// Since null is allowed for value, we don't use UnwrapInstanceHandle.
- const Object& value_obj = Object::Handle(isolate, Api::UnwrapHandle(value));
+ const Object& value_obj = Object::Handle(Z, Api::UnwrapHandle(value));
if (!value_obj.IsNull() && !value_obj.IsInstance()) {
- RETURN_TYPE_ERROR(isolate, value, Instance);
+ RETURN_TYPE_ERROR(I, value, Instance);
}
- Instance& value_instance = Instance::Handle(isolate);
+ Instance& value_instance = Instance::Handle(Z);
value_instance ^= value_obj.raw();
- Field& field = Field::Handle(isolate);
- Function& setter = Function::Handle(isolate);
- const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(container));
+ Field& field = Field::Handle(Z);
+ Function& setter = Function::Handle(Z);
+ const Object& obj = Object::Handle(Z, Api::UnwrapHandle(container));
if (obj.IsNull()) {
return Api::NewError("%s expects argument 'container' to be non-null.",
CURRENT_FUNC);
@@ -4510,24 +4372,23 @@
// To access a static field we may need to use the Field or the
// setter Function.
- Class& cls = Class::Handle(isolate, Type::Cast(obj).type_class());
+ Class& cls = Class::Handle(Z, Type::Cast(obj).type_class());
field = cls.LookupStaticField(field_name);
if (field.IsNull()) {
- String& setter_name =
- String::Handle(isolate, Field::SetterName(field_name));
+ String& setter_name = String::Handle(Z, Field::SetterName(field_name));
setter = cls.LookupStaticFunctionAllowPrivate(setter_name);
}
if (!setter.IsNull()) {
// Invoke the setter and return the result.
const int kNumArgs = 1;
- const Array& args = Array::Handle(isolate, Array::New(kNumArgs));
+ const Array& args = Array::Handle(Z, Array::New(kNumArgs));
args.SetAt(0, value_instance);
- const Object& result =
- Object::Handle(isolate, DartEntry::InvokeFunction(setter, args));
+ const Object& result = Object::Handle(Z,
+ DartEntry::InvokeFunction(setter, args));
if (result.IsError()) {
- return Api::NewHandle(isolate, result.raw());
+ return Api::NewHandle(I, result.raw());
} else {
return Api::Success();
}
@@ -4549,9 +4410,8 @@
// setter in any superclass and use that function to access the
// field.
const Instance& instance = Instance::Cast(obj);
- Class& cls = Class::Handle(isolate, instance.clazz());
- String& setter_name =
- String::Handle(isolate, Field::SetterName(field_name));
+ Class& cls = Class::Handle(Z, instance.clazz());
+ String& setter_name = String::Handle(Z, Field::SetterName(field_name));
while (!cls.IsNull()) {
field = cls.LookupInstanceField(field_name);
if (!field.IsNull() && field.is_final()) {
@@ -4567,19 +4427,18 @@
// Invoke the setter and return the result.
const int kNumArgs = 2;
- const Array& args = Array::Handle(isolate, Array::New(kNumArgs));
+ const Array& args = Array::Handle(Z, Array::New(kNumArgs));
args.SetAt(0, instance);
args.SetAt(1, value_instance);
if (setter.IsNull()) {
const Array& args_descriptor =
- Array::Handle(ArgumentsDescriptor::New(args.Length()));
- return Api::NewHandle(isolate,
- DartEntry::InvokeNoSuchMethod(instance,
- setter_name,
- args,
- args_descriptor));
+ Array::Handle(Z, ArgumentsDescriptor::New(args.Length()));
+ return Api::NewHandle(I, DartEntry::InvokeNoSuchMethod(instance,
+ setter_name,
+ args,
+ args_descriptor));
}
- return Api::NewHandle(isolate, DartEntry::InvokeFunction(setter, args));
+ return Api::NewHandle(I, DartEntry::InvokeFunction(setter, args));
} else if (obj.IsLibrary()) {
// To access a top-level we may need to use the Field or the
@@ -4595,19 +4454,19 @@
field = lib.LookupFieldAllowPrivate(field_name);
if (field.IsNull()) {
const String& setter_name =
- String::Handle(isolate, Field::SetterName(field_name));
+ String::Handle(Z, Field::SetterName(field_name));
setter ^= lib.LookupFunctionAllowPrivate(setter_name);
}
if (!setter.IsNull()) {
// Invoke the setter and return the result.
const int kNumArgs = 1;
- const Array& args = Array::Handle(isolate, Array::New(kNumArgs));
+ const Array& args = Array::Handle(Z, Array::New(kNumArgs));
args.SetAt(0, value_instance);
const Object& result =
- Object::Handle(isolate, DartEntry::InvokeFunction(setter, args));
+ Object::Handle(Z, DartEntry::InvokeFunction(setter, args));
if (result.IsError()) {
- return Api::NewHandle(isolate, result.raw());
+ return Api::NewHandle(I, result.raw());
}
return Api::Success();
}
@@ -4715,30 +4574,29 @@
DART_EXPORT Dart_Handle Dart_CreateNativeWrapperClass(Dart_Handle library,
Dart_Handle name,
int field_count) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
- const String& cls_name = Api::UnwrapStringHandle(isolate, name);
+ DARTSCOPE(Thread::Current());
+ const String& cls_name = Api::UnwrapStringHandle(I, name);
if (cls_name.IsNull()) {
- RETURN_TYPE_ERROR(isolate, name, String);
+ RETURN_TYPE_ERROR(I, name, String);
}
- const Library& lib = Api::UnwrapLibraryHandle(isolate, library);
+ const Library& lib = Api::UnwrapLibraryHandle(I, library);
if (lib.IsNull()) {
- RETURN_TYPE_ERROR(isolate, library, Library);
+ RETURN_TYPE_ERROR(I, library, Library);
}
if (!Utils::IsUint(16, field_count)) {
return Api::NewError(
"Invalid field_count passed to Dart_CreateNativeWrapperClass");
}
- CHECK_CALLBACK_STATE(isolate);
+ CHECK_CALLBACK_STATE(I);
- String& cls_symbol = String::Handle(isolate, Symbols::New(cls_name));
- const Class& cls = Class::Handle(
- isolate, Class::NewNativeWrapper(lib, cls_symbol, field_count));
+ String& cls_symbol = String::Handle(Z, Symbols::New(cls_name));
+ const Class& cls = Class::Handle(Z,
+ Class::NewNativeWrapper(lib, cls_symbol, field_count));
if (cls.IsNull()) {
return Api::NewError(
"Unable to create native wrapper class : already exists");
}
- return Api::NewHandle(isolate, cls.RareType());
+ return Api::NewHandle(I, cls.RareType());
}
@@ -4779,11 +4637,10 @@
DART_EXPORT Dart_Handle Dart_SetNativeInstanceField(Dart_Handle obj,
int index,
intptr_t value) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
- const Instance& instance = Api::UnwrapInstanceHandle(isolate, obj);
+ DARTSCOPE(Thread::Current());
+ const Instance& instance = Api::UnwrapInstanceHandle(I, obj);
if (instance.IsNull()) {
- RETURN_TYPE_ERROR(isolate, obj, Instance);
+ RETURN_TYPE_ERROR(I, obj, Instance);
}
if (!instance.IsValidNativeIndex(index)) {
return Api::NewError(
@@ -5207,22 +5064,19 @@
Dart_Handle source,
intptr_t line_offset,
intptr_t column_offset) {
- Thread* thread = Thread::Current();
- Isolate* isolate = thread->isolate();
- DARTSCOPE(isolate);
- TIMERSCOPE(thread, time_script_loading);
- const String& url_str = Api::UnwrapStringHandle(isolate, url);
+ DARTSCOPE(Thread::Current());
+ TIMERSCOPE(T, time_script_loading);
+ const String& url_str = Api::UnwrapStringHandle(I, url);
if (url_str.IsNull()) {
- RETURN_TYPE_ERROR(isolate, url, String);
+ RETURN_TYPE_ERROR(I, url, String);
}
- const String& source_str = Api::UnwrapStringHandle(isolate, source);
+ const String& source_str = Api::UnwrapStringHandle(I, source);
if (source_str.IsNull()) {
- RETURN_TYPE_ERROR(isolate, source, String);
+ RETURN_TYPE_ERROR(I, source, String);
}
- Library& library =
- Library::Handle(isolate, isolate->object_store()->root_library());
+ Library& library = Library::Handle(Z, I->object_store()->root_library());
if (!library.IsNull()) {
- const String& library_url = String::Handle(isolate, library.url());
+ const String& library_url = String::Handle(Z, library.url());
return Api::NewError("%s: A script has already been loaded from '%s'.",
CURRENT_FUNC, library_url.ToCString());
}
@@ -5234,31 +5088,29 @@
return Api::NewError("%s: argument 'column_offset' must be positive number",
CURRENT_FUNC);
}
- CHECK_CALLBACK_STATE(isolate);
+ CHECK_CALLBACK_STATE(I);
NoHeapGrowthControlScope no_growth_control;
library = Library::New(url_str);
library.set_debuggable(true);
library.Register();
- isolate->object_store()->set_root_library(library);
+ I->object_store()->set_root_library(library);
- const Script& script = Script::Handle(
- isolate, Script::New(url_str, source_str, RawScript::kScriptTag));
+ const Script& script = Script::Handle(Z,
+ Script::New(url_str, source_str, RawScript::kScriptTag));
script.SetLocationOffset(line_offset, column_offset);
Dart_Handle result;
- CompileSource(isolate, library, script, &result);
+ CompileSource(I, library, script, &result);
return result;
}
DART_EXPORT Dart_Handle Dart_LoadScriptFromSnapshot(const uint8_t* buffer,
intptr_t buffer_len) {
- Thread* thread = Thread::Current();
- Isolate* isolate = thread->isolate();
- DARTSCOPE(isolate);
- TIMERSCOPE(thread, time_script_loading);
- StackZone zone(isolate);
+ DARTSCOPE(Thread::Current());
+ TIMERSCOPE(T, time_script_loading);
+ StackZone zone(T);
if (buffer == NULL) {
RETURN_NULL_ERROR(buffer);
}
@@ -5274,28 +5126,24 @@
" which is the expected length in the snapshot.",
CURRENT_FUNC, buffer_len, snapshot->length());
}
- Library& library =
- Library::Handle(isolate, isolate->object_store()->root_library());
+ Library& library = Library::Handle(Z, I->object_store()->root_library());
if (!library.IsNull()) {
- const String& library_url = String::Handle(isolate, library.url());
+ const String& library_url = String::Handle(Z, library.url());
return Api::NewError("%s: A script has already been loaded from '%s'.",
CURRENT_FUNC, library_url.ToCString());
}
- CHECK_CALLBACK_STATE(isolate);
+ CHECK_CALLBACK_STATE(I);
ASSERT(snapshot->kind() == Snapshot::kScript);
- ScriptSnapshotReader reader(snapshot->content(),
- snapshot->length(),
- isolate,
- zone.GetZone());
- const Object& tmp = Object::Handle(isolate, reader.ReadScriptSnapshot());
+ ScriptSnapshotReader reader(snapshot->content(), snapshot->length(), T);
+ const Object& tmp = Object::Handle(Z, reader.ReadScriptSnapshot());
if (tmp.IsError()) {
- return Api::NewHandle(isolate, tmp.raw());
+ return Api::NewHandle(I, tmp.raw());
}
library ^= tmp.raw();
library.set_debuggable(true);
- isolate->object_store()->set_root_library(library);
- return Api::NewHandle(isolate, library.raw());
+ I->object_store()->set_root_library(library);
+ return Api::NewHandle(I, library.raw());
}
@@ -5308,25 +5156,23 @@
DART_EXPORT Dart_Handle Dart_GetClass(Dart_Handle library,
Dart_Handle class_name) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
- const Library& lib = Api::UnwrapLibraryHandle(isolate, library);
+ DARTSCOPE(Thread::Current());
+ const Library& lib = Api::UnwrapLibraryHandle(I, library);
if (lib.IsNull()) {
- RETURN_TYPE_ERROR(isolate, library, Library);
+ RETURN_TYPE_ERROR(I, library, Library);
}
- const String& cls_name = Api::UnwrapStringHandle(isolate, class_name);
+ const String& cls_name = Api::UnwrapStringHandle(I, class_name);
if (cls_name.IsNull()) {
- RETURN_TYPE_ERROR(isolate, class_name, String);
+ RETURN_TYPE_ERROR(I, class_name, String);
}
- const Class& cls = Class::Handle(
- isolate, lib.LookupClassAllowPrivate(cls_name));
+ const Class& cls = Class::Handle(Z, lib.LookupClassAllowPrivate(cls_name));
if (cls.IsNull()) {
// TODO(turnidge): Return null or error in this case?
- const String& lib_name = String::Handle(isolate, lib.name());
+ const String& lib_name = String::Handle(Z, lib.name());
return Api::NewError("Class '%s' not found in library '%s'.",
cls_name.ToCString(), lib_name.ToCString());
}
- return Api::NewHandle(isolate, cls.RareType());
+ return Api::NewHandle(I, cls.RareType());
}
@@ -5334,27 +5180,25 @@
Dart_Handle class_name,
intptr_t number_of_type_arguments,
Dart_Handle* type_arguments) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
+ DARTSCOPE(Thread::Current());
// Validate the input arguments.
- const Library& lib = Api::UnwrapLibraryHandle(isolate, library);
+ const Library& lib = Api::UnwrapLibraryHandle(I, library);
if (lib.IsNull()) {
- RETURN_TYPE_ERROR(isolate, library, Library);
+ RETURN_TYPE_ERROR(I, library, Library);
}
if (!lib.Loaded()) {
return Api::NewError(
"%s expects library argument 'library' to be loaded.",
CURRENT_FUNC);
}
- const String& name_str = Api::UnwrapStringHandle(isolate, class_name);
+ const String& name_str = Api::UnwrapStringHandle(I, class_name);
if (name_str.IsNull()) {
- RETURN_TYPE_ERROR(isolate, class_name, String);
+ RETURN_TYPE_ERROR(I, class_name, String);
}
- const Class& cls =
- Class::Handle(isolate, lib.LookupClassAllowPrivate(name_str));
+ const Class& cls = Class::Handle(Z, lib.LookupClassAllowPrivate(name_str));
if (cls.IsNull()) {
- const String& lib_name = String::Handle(isolate, lib.name());
+ const String& lib_name = String::Handle(Z, lib.name());
return Api::NewError("Type '%s' not found in library '%s'.",
name_str.ToCString(), lib_name.ToCString());
}
@@ -5363,7 +5207,7 @@
return Api::NewError("Invalid number of type arguments specified, "
"got %" Pd " expected 0", number_of_type_arguments);
}
- return Api::NewHandle(isolate, Type::NewNonParameterizedType(cls));
+ return Api::NewHandle(I, Type::NewNonParameterizedType(cls));
}
intptr_t num_expected_type_arguments = cls.NumTypeParameters();
TypeArguments& type_args_obj = TypeArguments::Handle();
@@ -5377,9 +5221,9 @@
number_of_type_arguments,
num_expected_type_arguments);
}
- const Array& array = Api::UnwrapArrayHandle(isolate, *type_arguments);
+ const Array& array = Api::UnwrapArrayHandle(I, *type_arguments);
if (array.IsNull()) {
- RETURN_TYPE_ERROR(isolate, *type_arguments, Array);
+ RETURN_TYPE_ERROR(I, *type_arguments, Array);
}
if (array.Length() != num_expected_type_arguments) {
return Api::NewError("Invalid type arguments specified, expected an "
@@ -5401,59 +5245,55 @@
Type::New(cls, type_args_obj, Scanner::kNoSourcePos));
instantiated_type ^= ClassFinalizer::FinalizeType(
cls, instantiated_type, ClassFinalizer::kCanonicalize);
- return Api::NewHandle(isolate, instantiated_type.raw());
+ return Api::NewHandle(I, instantiated_type.raw());
}
DART_EXPORT Dart_Handle Dart_LibraryUrl(Dart_Handle library) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
- const Library& lib = Api::UnwrapLibraryHandle(isolate, library);
+ DARTSCOPE(Thread::Current());
+ const Library& lib = Api::UnwrapLibraryHandle(I, library);
if (lib.IsNull()) {
- RETURN_TYPE_ERROR(isolate, library, Library);
+ RETURN_TYPE_ERROR(I, library, Library);
}
- const String& url = String::Handle(isolate, lib.url());
+ const String& url = String::Handle(Z, lib.url());
ASSERT(!url.IsNull());
- return Api::NewHandle(isolate, url.raw());
+ return Api::NewHandle(I, url.raw());
}
DART_EXPORT Dart_Handle Dart_LookupLibrary(Dart_Handle url) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
- const String& url_str = Api::UnwrapStringHandle(isolate, url);
+ DARTSCOPE(Thread::Current());
+ const String& url_str = Api::UnwrapStringHandle(I, url);
if (url_str.IsNull()) {
- RETURN_TYPE_ERROR(isolate, url, String);
+ RETURN_TYPE_ERROR(I, url, String);
}
- const Library& library =
- Library::Handle(isolate, Library::LookupLibrary(url_str));
+ const Library& library = Library::Handle(Z, Library::LookupLibrary(url_str));
if (library.IsNull()) {
return Api::NewError("%s: library '%s' not found.",
CURRENT_FUNC, url_str.ToCString());
} else {
- return Api::NewHandle(isolate, library.raw());
+ return Api::NewHandle(I, library.raw());
}
}
DART_EXPORT Dart_Handle Dart_LibraryHandleError(Dart_Handle library_in,
Dart_Handle error_in) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
+ DARTSCOPE(Thread::Current());
- const Library& lib = Api::UnwrapLibraryHandle(isolate, library_in);
+ const Library& lib = Api::UnwrapLibraryHandle(I, library_in);
if (lib.IsNull()) {
- RETURN_TYPE_ERROR(isolate, library_in, Library);
+ RETURN_TYPE_ERROR(I, library_in, Library);
}
- const Instance& err = Api::UnwrapInstanceHandle(isolate, error_in);
+ const Instance& err = Api::UnwrapInstanceHandle(I, error_in);
if (err.IsNull()) {
- RETURN_TYPE_ERROR(isolate, error_in, Instance);
+ RETURN_TYPE_ERROR(I, error_in, Instance);
}
- CHECK_CALLBACK_STATE(isolate);
+ CHECK_CALLBACK_STATE(I);
const GrowableObjectArray& pending_deferred_loads =
- GrowableObjectArray::Handle(
- isolate->object_store()->pending_deferred_loads());
+ GrowableObjectArray::Handle(Z,
+ I->object_store()->pending_deferred_loads());
for (intptr_t i = 0; i < pending_deferred_loads.Length(); i++) {
if (pending_deferred_loads.At(i) == lib.raw()) {
lib.SetLoadError(err);
@@ -5468,17 +5308,15 @@
Dart_Handle source,
intptr_t line_offset,
intptr_t column_offset) {
- Thread* thread = Thread::Current();
- Isolate* isolate = thread->isolate();
- DARTSCOPE(isolate);
- TIMERSCOPE(thread, time_script_loading);
- const String& url_str = Api::UnwrapStringHandle(isolate, url);
+ DARTSCOPE(Thread::Current());
+ TIMERSCOPE(T, time_script_loading);
+ const String& url_str = Api::UnwrapStringHandle(I, url);
if (url_str.IsNull()) {
- RETURN_TYPE_ERROR(isolate, url, String);
+ RETURN_TYPE_ERROR(I, url, String);
}
- const String& source_str = Api::UnwrapStringHandle(isolate, source);
+ const String& source_str = Api::UnwrapStringHandle(I, source);
if (source_str.IsNull()) {
- RETURN_TYPE_ERROR(isolate, source, String);
+ RETURN_TYPE_ERROR(I, source, String);
}
if (line_offset < 0) {
return Api::NewError("%s: argument 'line_offset' must be positive number",
@@ -5488,11 +5326,11 @@
return Api::NewError("%s: argument 'column_offset' must be positive number",
CURRENT_FUNC);
}
- CHECK_CALLBACK_STATE(isolate);
+ CHECK_CALLBACK_STATE(I);
NoHeapGrowthControlScope no_growth_control;
- Library& library = Library::Handle(isolate, Library::LookupLibrary(url_str));
+ Library& library = Library::Handle(Z, Library::LookupLibrary(url_str));
if (library.IsNull()) {
library = Library::New(url_str);
library.Register();
@@ -5504,11 +5342,11 @@
return Api::NewError("%s: library '%s' has already been loaded.",
CURRENT_FUNC, url_str.ToCString());
}
- const Script& script = Script::Handle(
- isolate, Script::New(url_str, source_str, RawScript::kLibraryTag));
+ const Script& script = Script::Handle(Z,
+ Script::New(url_str, source_str, RawScript::kLibraryTag));
script.SetLocationOffset(line_offset, column_offset);
Dart_Handle result;
- CompileSource(isolate, library, script, &result);
+ CompileSource(I, library, script, &result);
// Propagate the error out right now.
if (::Dart_IsError(result)) {
return result;
@@ -5516,8 +5354,8 @@
// If this is the dart:_builtin library, register it with the VM.
if (url_str.Equals("dart:_builtin")) {
- isolate->object_store()->set_builtin_library(library);
- Dart_Handle state = Api::CheckAndFinalizePendingClasses(isolate);
+ I->object_store()->set_builtin_library(library);
+ Dart_Handle state = Api::CheckAndFinalizePendingClasses(I);
if (::Dart_IsError(state)) {
return state;
}
@@ -5529,29 +5367,26 @@
DART_EXPORT Dart_Handle Dart_LibraryImportLibrary(Dart_Handle library,
Dart_Handle import,
Dart_Handle prefix) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
- const Library& library_vm = Api::UnwrapLibraryHandle(isolate, library);
+ DARTSCOPE(Thread::Current());
+ const Library& library_vm = Api::UnwrapLibraryHandle(I, library);
if (library_vm.IsNull()) {
- RETURN_TYPE_ERROR(isolate, library, Library);
+ RETURN_TYPE_ERROR(I, library, Library);
}
- const Library& import_vm = Api::UnwrapLibraryHandle(isolate, import);
+ const Library& import_vm = Api::UnwrapLibraryHandle(I, import);
if (import_vm.IsNull()) {
- RETURN_TYPE_ERROR(isolate, import, Library);
+ RETURN_TYPE_ERROR(I, import, Library);
}
- const Object& prefix_object =
- Object::Handle(isolate, Api::UnwrapHandle(prefix));
+ const Object& prefix_object = Object::Handle(Z, Api::UnwrapHandle(prefix));
const String& prefix_vm = prefix_object.IsNull()
? Symbols::Empty()
: String::Cast(prefix_object);
if (prefix_vm.IsNull()) {
- RETURN_TYPE_ERROR(isolate, prefix, String);
+ RETURN_TYPE_ERROR(I, prefix, String);
}
- CHECK_CALLBACK_STATE(isolate);
+ CHECK_CALLBACK_STATE(I);
- const String& prefix_symbol =
- String::Handle(isolate, Symbols::New(prefix_vm));
- const Namespace& import_ns = Namespace::Handle(
+ const String& prefix_symbol = String::Handle(Z, Symbols::New(prefix_vm));
+ const Namespace& import_ns = Namespace::Handle(Z,
Namespace::New(import_vm, Object::null_array(), Object::null_array()));
if (prefix_vm.Length() == 0) {
library_vm.AddImport(import_ns);
@@ -5575,21 +5410,19 @@
Dart_Handle source,
intptr_t line_offset,
intptr_t column_offset) {
- Thread* thread = Thread::Current();
- Isolate* isolate = thread->isolate();
- DARTSCOPE(isolate);
- TIMERSCOPE(thread, time_script_loading);
- const Library& lib = Api::UnwrapLibraryHandle(isolate, library);
+ DARTSCOPE(Thread::Current());
+ TIMERSCOPE(T, time_script_loading);
+ const Library& lib = Api::UnwrapLibraryHandle(I, library);
if (lib.IsNull()) {
- RETURN_TYPE_ERROR(isolate, library, Library);
+ RETURN_TYPE_ERROR(I, library, Library);
}
- const String& url_str = Api::UnwrapStringHandle(isolate, url);
+ const String& url_str = Api::UnwrapStringHandle(I, url);
if (url_str.IsNull()) {
- RETURN_TYPE_ERROR(isolate, url, String);
+ RETURN_TYPE_ERROR(I, url, String);
}
- const String& source_str = Api::UnwrapStringHandle(isolate, source);
+ const String& source_str = Api::UnwrapStringHandle(I, source);
if (source_str.IsNull()) {
- RETURN_TYPE_ERROR(isolate, source, String);
+ RETURN_TYPE_ERROR(I, source, String);
}
if (line_offset < 0) {
return Api::NewError("%s: argument 'line_offset' must be positive number",
@@ -5599,15 +5432,15 @@
return Api::NewError("%s: argument 'column_offset' must be positive number",
CURRENT_FUNC);
}
- CHECK_CALLBACK_STATE(isolate);
+ CHECK_CALLBACK_STATE(I);
NoHeapGrowthControlScope no_growth_control;
- const Script& script = Script::Handle(
- isolate, Script::New(url_str, source_str, RawScript::kSourceTag));
+ const Script& script = Script::Handle(Z,
+ Script::New(url_str, source_str, RawScript::kSourceTag));
script.SetLocationOffset(line_offset, column_offset);
Dart_Handle result;
- CompileSource(isolate, lib, script, &result);
+ CompileSource(I, lib, script, &result);
return result;
}
@@ -5615,30 +5448,28 @@
DART_EXPORT Dart_Handle Dart_LibraryLoadPatch(Dart_Handle library,
Dart_Handle url,
Dart_Handle patch_source) {
- Thread* thread = Thread::Current();
- Isolate* isolate = thread->isolate();
- DARTSCOPE(isolate);
- TIMERSCOPE(thread, time_script_loading);
- const Library& lib = Api::UnwrapLibraryHandle(isolate, library);
+ DARTSCOPE(Thread::Current());
+ TIMERSCOPE(T, time_script_loading);
+ const Library& lib = Api::UnwrapLibraryHandle(I, library);
if (lib.IsNull()) {
- RETURN_TYPE_ERROR(isolate, library, Library);
+ RETURN_TYPE_ERROR(I, library, Library);
}
- const String& url_str = Api::UnwrapStringHandle(isolate, url);
+ const String& url_str = Api::UnwrapStringHandle(I, url);
if (url_str.IsNull()) {
- RETURN_TYPE_ERROR(isolate, url, String);
+ RETURN_TYPE_ERROR(I, url, String);
}
- const String& source_str = Api::UnwrapStringHandle(isolate, patch_source);
+ const String& source_str = Api::UnwrapStringHandle(I, patch_source);
if (source_str.IsNull()) {
- RETURN_TYPE_ERROR(isolate, patch_source, String);
+ RETURN_TYPE_ERROR(I, patch_source, String);
}
- CHECK_CALLBACK_STATE(isolate);
+ CHECK_CALLBACK_STATE(I);
NoHeapGrowthControlScope no_growth_control;
- const Script& script = Script::Handle(
- isolate, Script::New(url_str, source_str, RawScript::kPatchTag));
+ const Script& script = Script::Handle(Z,
+ Script::New(url_str, source_str, RawScript::kPatchTag));
Dart_Handle result;
- CompileSource(isolate, lib, script, &result);
+ CompileSource(I, lib, script, &result);
return result;
}
@@ -5646,17 +5477,16 @@
// Finalizes classes and invokes Dart core library function that completes
// futures of loadLibrary calls (deferred library loading).
DART_EXPORT Dart_Handle Dart_FinalizeLoading(bool complete_futures) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
- CHECK_CALLBACK_STATE(isolate);
+ DARTSCOPE(Thread::Current());
+ CHECK_CALLBACK_STATE(I);
- isolate->DoneLoading();
+ I->DoneLoading();
// TODO(hausner): move the remaining code below (finalization and
// invoing of _completeDeferredLoads) into Isolate::DoneLoading().
// Finalize all classes if needed.
- Dart_Handle state = Api::CheckAndFinalizePendingClasses(isolate);
+ Dart_Handle state = Api::CheckAndFinalizePendingClasses(I);
if (::Dart_IsError(state)) {
return state;
}
@@ -5666,31 +5496,29 @@
// the new code, the debugger convert them to unresolved source breakpoints.
// The code that completes the futures (invoked below) may call into the
// newly loaded code and trigger one of these breakpoints.
- isolate->debugger()->NotifyDoneLoading();
+ I->debugger()->NotifyDoneLoading();
// Notify mirrors that MirrorSystem.libraries needs to be recomputed.
- const Library& libmirrors =
- Library::Handle(isolate, Library::MirrorsLibrary());
- const Field& dirty_bit = Field::Handle(isolate,
+ const Library& libmirrors = Library::Handle(Z, Library::MirrorsLibrary());
+ const Field& dirty_bit = Field::Handle(Z,
libmirrors.LookupLocalField(String::Handle(String::New("dirty"))));
ASSERT(!dirty_bit.IsNull() && dirty_bit.is_static());
dirty_bit.set_value(Bool::True());
if (complete_futures) {
- const Library& corelib = Library::Handle(isolate, Library::CoreLibrary());
+ const Library& corelib = Library::Handle(Z, Library::CoreLibrary());
const String& function_name =
- String::Handle(isolate, String::New("_completeDeferredLoads"));
- const Function& function =
- Function::Handle(isolate,
- corelib.LookupFunctionAllowPrivate(function_name));
+ String::Handle(Z, String::New("_completeDeferredLoads"));
+ const Function& function = Function::Handle(Z,
+ corelib.LookupFunctionAllowPrivate(function_name));
ASSERT(!function.IsNull());
const Array& args = Array::empty_array();
const Object& res =
- Object::Handle(isolate, DartEntry::InvokeFunction(function, args));
- isolate->object_store()->clear_pending_deferred_loads();
+ Object::Handle(Z, DartEntry::InvokeFunction(function, args));
+ I->object_store()->clear_pending_deferred_loads();
if (res.IsError() || res.IsUnhandledException()) {
- return Api::NewHandle(isolate, res.raw());
+ return Api::NewHandle(I, res.raw());
}
}
return Api::Success();
@@ -5701,11 +5529,10 @@
Dart_Handle library,
Dart_NativeEntryResolver resolver,
Dart_NativeEntrySymbol symbol) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
- const Library& lib = Api::UnwrapLibraryHandle(isolate, library);
+ DARTSCOPE(Thread::Current());
+ const Library& lib = Api::UnwrapLibraryHandle(I, library);
if (lib.IsNull()) {
- RETURN_TYPE_ERROR(isolate, library, Library);
+ RETURN_TYPE_ERROR(I, library, Library);
}
lib.set_native_entry_resolver(resolver);
lib.set_native_entry_symbol_resolver(symbol);
@@ -5827,8 +5654,7 @@
const char* event_kind,
const uint8_t* bytes,
intptr_t bytes_length) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
+ DARTSCOPE(Thread::Current());
if (stream_id == NULL) {
RETURN_NULL_ERROR(stream_id);
}
@@ -5842,7 +5668,7 @@
return Api::NewError("%s expects argument 'bytes_length' to be >= 0.",
CURRENT_FUNC);
}
- Service::SendEmbedderEvent(isolate, stream_id, event_kind,
+ Service::SendEmbedderEvent(I, stream_id, event_kind,
bytes, bytes_length);
return Api::Success();
}
@@ -6044,4 +5870,73 @@
return Api::Success();
}
+
+static void Precompile(Isolate* isolate, Dart_Handle* result) {
+ ASSERT(isolate != NULL);
+ const Error& error = Error::Handle(isolate, Precompiler::CompileAll());
+ if (error.IsNull()) {
+ *result = Api::Success();
+ } else {
+ *result = Api::NewHandle(isolate, error.raw());
+ }
+}
+
+
+DART_EXPORT Dart_Handle Dart_Precompile() {
+ DARTSCOPE(Thread::Current());
+ Dart_Handle result = Api::CheckAndFinalizePendingClasses(I);
+ if (::Dart_IsError(result)) {
+ return result;
+ }
+ CHECK_CALLBACK_STATE(I);
+ Precompile(I, &result);
+ return result;
+}
+
+
+DART_EXPORT Dart_Handle Dart_CreatePrecompiledSnapshot(
+ uint8_t** vm_isolate_snapshot_buffer,
+ intptr_t* vm_isolate_snapshot_size,
+ uint8_t** isolate_snapshot_buffer,
+ intptr_t* isolate_snapshot_size,
+ uint8_t** instructions_snapshot_buffer,
+ intptr_t* instructions_snapshot_size) {
+ ASSERT(FLAG_load_deferred_eagerly);
+ DARTSCOPE(Thread::Current());
+ if (vm_isolate_snapshot_buffer == NULL) {
+ RETURN_NULL_ERROR(vm_isolate_snapshot_buffer);
+ }
+ if (vm_isolate_snapshot_size == NULL) {
+ RETURN_NULL_ERROR(vm_isolate_snapshot_size);
+ }
+ if (isolate_snapshot_buffer == NULL) {
+ RETURN_NULL_ERROR(isolate_snapshot_buffer);
+ }
+ if (isolate_snapshot_size == NULL) {
+ RETURN_NULL_ERROR(isolate_snapshot_size);
+ }
+ if (instructions_snapshot_buffer == NULL) {
+ RETURN_NULL_ERROR(instructions_snapshot_buffer);
+ }
+ if (instructions_snapshot_size == NULL) {
+ RETURN_NULL_ERROR(instructions_snapshot_size);
+ }
+ // Finalize all classes if needed.
+ Dart_Handle state = Api::CheckAndFinalizePendingClasses(I);
+ if (::Dart_IsError(state)) {
+ return state;
+ }
+ I->heap()->CollectAllGarbage();
+ PrecompiledSnapshotWriter writer(vm_isolate_snapshot_buffer,
+ isolate_snapshot_buffer,
+ instructions_snapshot_buffer,
+ ApiReallocate);
+ writer.WriteFullSnapshot();
+ *vm_isolate_snapshot_size = writer.VmIsolateSnapshotSize();
+ *isolate_snapshot_size = writer.IsolateSnapshotSize();
+ *instructions_snapshot_size = writer.InstructionsSnapshotSize();
+
+ return Api::Success();
+}
+
} // namespace dart
diff --git a/runtime/vm/dart_api_impl.h b/runtime/vm/dart_api_impl.h
index 46f85aa..742f80c 100644
--- a/runtime/vm/dart_api_impl.h
+++ b/runtime/vm/dart_api_impl.h
@@ -68,10 +68,11 @@
} \
} while (0)
-#define DARTSCOPE(isolate) \
- Isolate* __temp_isolate__ = (isolate); \
- CHECK_ISOLATE_SCOPE(__temp_isolate__); \
- HANDLESCOPE(__temp_isolate__);
+#define DARTSCOPE(thread) \
+ Thread* T = (thread); \
+ Isolate* I = T->isolate(); \
+ CHECK_ISOLATE_SCOPE(I); \
+ HANDLESCOPE(T);
#define RETURN_TYPE_ERROR(isolate, dart_handle, type) \
diff --git a/runtime/vm/dart_api_impl_test.cc b/runtime/vm/dart_api_impl_test.cc
index 70d59d9..f79106e 100644
--- a/runtime/vm/dart_api_impl_test.cc
+++ b/runtime/vm/dart_api_impl_test.cc
@@ -616,8 +616,7 @@
// Non-instance objects.
{
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
+ DARTSCOPE(Thread::Current());
Dart_Handle lib1 = Dart_LookupLibrary(dart_core);
Dart_Handle lib2 = Dart_LookupLibrary(dart_mirrors);
@@ -662,8 +661,7 @@
// Non-instance objects.
{
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
+ DARTSCOPE(Thread::Current());
Dart_Handle lib1 = Dart_LookupLibrary(dart_core);
Dart_Handle lib2 = Dart_LookupLibrary(dart_mirrors);
@@ -1175,7 +1173,6 @@
TEST_CASE(ExternalStringPretenure) {
- Isolate* isolate = Isolate::Current();
{
Dart_EnterScope();
static const uint8_t big_data8[16*MB] = {0, };
@@ -1206,7 +1203,7 @@
NULL);
EXPECT_VALID(small16);
{
- DARTSCOPE(isolate);
+ DARTSCOPE(Thread::Current());
String& handle = String::Handle();
handle ^= Api::UnwrapHandle(big8);
EXPECT(handle.IsOld());
@@ -1223,7 +1220,6 @@
TEST_CASE(ExternalTypedDataPretenure) {
- Isolate* isolate = Isolate::Current();
{
Dart_EnterScope();
static const int kBigLength = 16*MB/8;
@@ -1241,7 +1237,7 @@
kSmallLength);
EXPECT_VALID(small);
{
- DARTSCOPE(isolate);
+ DARTSCOPE(Thread::Current());
ExternalTypedData& handle = ExternalTypedData::Handle();
handle ^= Api::UnwrapHandle(big);
EXPECT(handle.IsOld());
@@ -2368,7 +2364,7 @@
Dart_EnterScope();
{
EXPECT(state->top_scope() != NULL);
- DARTSCOPE(isolate);
+ DARTSCOPE(Thread::Current());
const String& str1 = String::Handle(String::New("Test String"));
Dart_Handle ref = Api::NewHandle(isolate, str1.raw());
String& str2 = String::Handle();
@@ -2385,7 +2381,8 @@
const char* kTestString1 = "Test String1";
const char* kTestString2 = "Test String2";
TestCase::CreateTestIsolate();
- Isolate* isolate = Isolate::Current();
+ Thread* thread = Thread::Current();
+ Isolate* isolate = thread->isolate();
EXPECT(isolate != NULL);
ApiState* state = isolate->api_state();
EXPECT(state != NULL);
@@ -2393,7 +2390,7 @@
Dart_PersistentHandle handles[2000];
Dart_EnterScope();
{
- DARTSCOPE(isolate);
+ DARTSCOPE(Thread::Current());
Dart_Handle ref1 = Api::NewHandle(isolate, String::New(kTestString1));
for (int i = 0; i < 1000; i++) {
handles[i] = Dart_NewPersistentHandle(ref1);
@@ -2417,8 +2414,8 @@
}
Dart_ExitScope();
{
- StackZone zone(isolate);
- HANDLESCOPE(isolate);
+ StackZone zone(thread);
+ HANDLESCOPE(thread);
for (int i = 0; i < 500; i++) {
String& str = String::Handle();
str ^= PersistentHandle::Cast(handles[i])->raw();
@@ -2455,7 +2452,7 @@
EXPECT(isolate != NULL);
ApiState* state = isolate->api_state();
EXPECT(state != NULL);
- DARTSCOPE(isolate);
+ DARTSCOPE(Thread::Current());
// Start with a known persistent handle.
Dart_PersistentHandle obj1 = Dart_NewPersistentHandle(Dart_True());
@@ -2486,7 +2483,7 @@
EXPECT(isolate != NULL);
ApiState* state = isolate->api_state();
EXPECT(state != NULL);
- DARTSCOPE(isolate);
+ DARTSCOPE(Thread::Current());
String& str = String::Handle();
// Start with a known persistent handle.
@@ -2566,7 +2563,7 @@
Dart_Handle old_ref;
{
Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
+ DARTSCOPE(Thread::Current());
old_ref = Api::NewHandle(isolate, String::New("old string", Heap::kOld));
EXPECT_VALID(old_ref);
}
@@ -2821,8 +2818,8 @@
// After the two scavenges above, 'obj' should now be promoted, hence its
// external size charged to old space.
{
- DARTSCOPE(Isolate::Current());
- String& handle = String::Handle();
+ DARTSCOPE(thread);
+ String& handle = String::Handle(thread->zone());
handle ^= Api::UnwrapHandle(obj);
EXPECT(handle.IsOld());
}
@@ -2932,7 +2929,7 @@
Dart_EnterScope();
{
Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
+ DARTSCOPE(Thread::Current());
Dart_Handle local = Api::NewHandle(
isolate, String::New("strongly reachable", Heap::kOld));
@@ -3174,7 +3171,7 @@
Dart_EnterScope();
{
- DARTSCOPE(isolate);
+ DARTSCOPE(Thread::Current());
// Strong handle to keep the reference set alive.
Dart_Handle local = Api::NewHandle(isolate, String::New("string"));
@@ -3227,7 +3224,7 @@
Dart_EnterScope();
{
Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
+ DARTSCOPE(Thread::Current());
new_pwph = Dart_NewPrologueWeakPersistentHandle(
Api::NewHandle(isolate,
String::New("new space prologue weak", Heap::kNew)),
@@ -3325,7 +3322,7 @@
Dart_EnterScope();
{
Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
+ DARTSCOPE(Thread::Current());
Dart_Handle local = Api::NewHandle(
isolate, String::New("strongly reachable", Heap::kOld));
@@ -3436,7 +3433,7 @@
Dart_EnterScope();
{
Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
+ DARTSCOPE(Thread::Current());
Dart_Handle local = Api::NewHandle(
isolate, String::New("strongly reachable", Heap::kOld));
@@ -3692,15 +3689,16 @@
// scope.
UNIT_TEST_CASE(LocalHandles) {
TestCase::CreateTestIsolate();
- Isolate* isolate = Isolate::Current();
+ Thread* thread = Thread::Current();
+ Isolate* isolate = thread->isolate();
EXPECT(isolate != NULL);
ApiState* state = isolate->api_state();
EXPECT(state != NULL);
ApiLocalScope* scope = state->top_scope();
Dart_Handle handles[300];
{
- StackZone zone(isolate);
- HANDLESCOPE(isolate);
+ StackZone zone(thread);
+ HANDLESCOPE(thread);
Smi& val = Smi::Handle();
// Start a new scope and allocate some local handles.
@@ -4471,7 +4469,7 @@
// Invoke a function which returns an object of type NativeFields.
result = Dart_Invoke(lib, NewString("testMain"), 0, NULL);
EXPECT_VALID(result);
- DARTSCOPE(Isolate::Current());
+ DARTSCOPE(Thread::Current());
Instance& obj = Instance::Handle();
obj ^= Api::UnwrapHandle(result);
const Class& cls = Class::Handle(obj.clazz());
@@ -4541,7 +4539,7 @@
// Invoke a function which returns an object of type NativeFields.
result = Dart_Invoke(lib, NewString("testMain"), 0, NULL);
EXPECT_VALID(result);
- DARTSCOPE(Isolate::Current());
+ DARTSCOPE(Thread::Current());
Instance& obj = Instance::Handle();
obj ^= Api::UnwrapHandle(result);
const Class& cls = Class::Handle(obj.clazz());
@@ -4885,7 +4883,7 @@
" return () {};\n"
"}\n";
Dart_Handle result;
- DARTSCOPE(Isolate::Current());
+ DARTSCOPE(Thread::Current());
// Create a test library and Load up a test script in it.
Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
@@ -4963,7 +4961,7 @@
" };\n"
"}\n";
- DARTSCOPE(Isolate::Current());
+ DARTSCOPE(Thread::Current());
// Create a test library and Load up a test script in it.
Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
@@ -5664,7 +5662,7 @@
" return InvokeClosure.method2(10);\n"
"}\n";
Dart_Handle result;
- DARTSCOPE(Isolate::Current());
+ DARTSCOPE(Thread::Current());
// Create a test library and Load up a test script in it.
Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
@@ -8257,7 +8255,7 @@
Isolate* isolate = Isolate::Current();
Dart_EnterScope();
{
- DARTSCOPE(isolate);
+ DARTSCOPE(Thread::Current());
Dart_Handle str = NewString("a string");
EXPECT_VALID(str);
EXPECT(Dart_IsString(str));
@@ -8330,7 +8328,7 @@
Isolate* isolate = Isolate::Current();
Dart_EnterScope();
{
- DARTSCOPE(isolate);
+ DARTSCOPE(Thread::Current());
Dart_Handle s1 = NewString("s1");
EXPECT_VALID(s1);
EXPECT(Dart_IsString(s1));
@@ -8414,7 +8412,7 @@
isolate->heap()->CollectGarbage(Heap::kNew);
isolate->heap()->CollectGarbage(Heap::kNew);
{
- DARTSCOPE(isolate);
+ DARTSCOPE(Thread::Current());
String& handle = String::Handle();
handle ^= Api::UnwrapHandle(str);
EXPECT(handle.IsOld());
@@ -8467,7 +8465,7 @@
Isolate* isolate = Isolate::Current();
Dart_EnterScope();
{
- DARTSCOPE(isolate);
+ DARTSCOPE(Thread::Current());
Dart_Handle str = Api::NewHandle(isolate, String::New("str", Heap::kOld));
EXPECT_VALID(str);
EXPECT(Dart_IsString(str));
@@ -8543,7 +8541,7 @@
Isolate* isolate = Isolate::Current();
Dart_EnterScope();
{
- DARTSCOPE(isolate);
+ DARTSCOPE(Thread::Current());
Dart_Handle s1 = Api::NewHandle(isolate, String::New("s1", Heap::kOld));
EXPECT_VALID(s1);
EXPECT(Dart_IsString(s1));
diff --git a/runtime/vm/dart_entry.h b/runtime/vm/dart_entry.h
index 9a5b92f..92e8562 100644
--- a/runtime/vm/dart_entry.h
+++ b/runtime/vm/dart_entry.h
@@ -91,6 +91,8 @@
// A cache of VM heap allocated arguments descriptors.
static RawArray* cached_args_descriptors_[kCachedDescriptorCount];
+ friend class FullSnapshotWriter;
+ friend class VmIsolateSnapshotReader;
DISALLOW_COPY_AND_ASSIGN(ArgumentsDescriptor);
};
diff --git a/runtime/vm/debugger_api_impl.cc b/runtime/vm/debugger_api_impl.cc
index 84c245a..9fd26d8 100644
--- a/runtime/vm/debugger_api_impl.cc
+++ b/runtime/vm/debugger_api_impl.cc
@@ -15,6 +15,10 @@
namespace dart {
+// Facilitate quick access to the current zone once we have the curren thread.
+#define Z (T->zone())
+
+
#define UNWRAP_AND_CHECK_PARAM(type, var, param) \
type& var = type::Handle(); \
do { \
@@ -51,32 +55,29 @@
DART_EXPORT intptr_t Dart_CacheObject(Dart_Handle object_in) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
- const Object& obj = Object::Handle(Api::UnwrapHandle(object_in));
+ DARTSCOPE(Thread::Current());
+ const Object& obj = Object::Handle(Z, Api::UnwrapHandle(object_in));
if (obj.IsApiError()) {
return -1;
}
- return isolate->debugger()->CacheObject(obj);
+ return I->debugger()->CacheObject(obj);
}
DART_EXPORT Dart_Handle Dart_GetCachedObject(intptr_t obj_id) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
- if (!isolate->debugger()->IsValidObjectId(obj_id)) {
+ DARTSCOPE(Thread::Current());
+ if (!I->debugger()->IsValidObjectId(obj_id)) {
return Api::NewError("%s: object id %" Pd " is invalid",
CURRENT_FUNC, obj_id);
}
- return Api::NewHandle(isolate, isolate->debugger()->GetCachedObject(obj_id));
+ return Api::NewHandle(I, I->debugger()->GetCachedObject(obj_id));
}
DART_EXPORT Dart_Handle Dart_StackTraceLength(
Dart_StackTrace trace,
intptr_t* length) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
+ DARTSCOPE(Thread::Current());
CHECK_NOT_NULL(length);
CHECK_AND_CAST(DebuggerStackTrace, stack_trace, trace);
*length = stack_trace->Length();
@@ -88,8 +89,7 @@
Dart_StackTrace trace,
int frame_index,
Dart_ActivationFrame* frame) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
+ DARTSCOPE(Thread::Current());
CHECK_NOT_NULL(frame);
CHECK_AND_CAST(DebuggerStackTrace, stack_trace, trace);
if ((frame_index < 0) || (frame_index >= stack_trace->Length())) {
@@ -196,45 +196,41 @@
DART_EXPORT Dart_Handle Dart_SetExceptionPauseInfo(
Dart_ExceptionPauseInfo pause_info) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
- isolate->debugger()->SetExceptionPauseInfo(pause_info);
+ DARTSCOPE(Thread::Current());
+ I->debugger()->SetExceptionPauseInfo(pause_info);
return Api::Success();
}
DART_EXPORT Dart_ExceptionPauseInfo Dart_GetExceptionPauseInfo() {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
- return isolate->debugger()->GetExceptionPauseInfo();
+ DARTSCOPE(Thread::Current());
+ return I->debugger()->GetExceptionPauseInfo();
}
DART_EXPORT Dart_Handle Dart_GetStackTrace(Dart_StackTrace* trace) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
+ DARTSCOPE(Thread::Current());
CHECK_NOT_NULL(trace);
*trace = reinterpret_cast<Dart_StackTrace>(
- isolate->debugger()->CurrentStackTrace());
+ I->debugger()->CurrentStackTrace());
return Api::Success();
}
DART_EXPORT Dart_Handle Dart_GetStackTraceFromError(Dart_Handle handle,
Dart_StackTrace* trace) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
+ DARTSCOPE(Thread::Current());
CHECK_NOT_NULL(trace);
- const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(handle));
+ const Object& obj = Object::Handle(Z, Api::UnwrapHandle(handle));
if (obj.IsUnhandledException()) {
const UnhandledException& error = UnhandledException::Cast(obj);
- Stacktrace& dart_stacktrace = Stacktrace::Handle(isolate);
+ Stacktrace& dart_stacktrace = Stacktrace::Handle(Z);
dart_stacktrace ^= error.stacktrace();
if (dart_stacktrace.IsNull()) {
*trace = NULL;
} else {
*trace = reinterpret_cast<Dart_StackTrace>(
- isolate->debugger()->StackTraceFrom(dart_stacktrace));
+ I->debugger()->StackTraceFrom(dart_stacktrace));
}
return Api::Success();
} else {
@@ -250,14 +246,13 @@
Dart_Handle* script_url,
intptr_t* line_number,
intptr_t* column_number) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
+ DARTSCOPE(Thread::Current());
CHECK_AND_CAST(ActivationFrame, frame, activation_frame);
if (function_name != NULL) {
- *function_name = Api::NewHandle(isolate, frame->QualifiedFunctionName());
+ *function_name = Api::NewHandle(I, frame->QualifiedFunctionName());
}
if (script_url != NULL) {
- *script_url = Api::NewHandle(isolate, frame->SourceUrl());
+ *script_url = Api::NewHandle(I, frame->SourceUrl());
}
if (line_number != NULL) {
*line_number = frame->LineNumber();
@@ -276,19 +271,18 @@
Dart_CodeLocation* location) {
// TODO(hausner): Implement a way to recognize when there
// is no source code for the code in the frame.
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
+ DARTSCOPE(Thread::Current());
CHECK_AND_CAST(ActivationFrame, frame, activation_frame);
if (function_name != NULL) {
- *function_name = Api::NewHandle(isolate, frame->QualifiedFunctionName());
+ *function_name = Api::NewHandle(I, frame->QualifiedFunctionName());
}
if (function != NULL) {
- *function = Api::NewHandle(isolate, frame->function().raw());
+ *function = Api::NewHandle(I, frame->function().raw());
}
if (location != NULL) {
- location->script_url = Api::NewHandle(isolate, frame->SourceUrl());
- const Library& lib = Library::Handle(frame->Library());
+ location->script_url = Api::NewHandle(I, frame->SourceUrl());
+ const Library& lib = Library::Handle(Z, frame->Library());
location->library_id = lib.index();
location->token_pos = frame->TokenPos();
}
@@ -298,8 +292,7 @@
DART_EXPORT Dart_Handle Dart_ActivationFrameGetFramePointer(
Dart_ActivationFrame activation_frame,
uintptr_t* frame_pointer) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
+ DARTSCOPE(Thread::Current());
CHECK_AND_CAST(ActivationFrame, frame, activation_frame);
if (frame_pointer != NULL) {
@@ -310,11 +303,10 @@
DART_EXPORT Dart_Handle Dart_GetFunctionOrigin(Dart_Handle function_in) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
+ DARTSCOPE(Thread::Current());
UNWRAP_AND_CHECK_PARAM(Function, function, function_in);
- const Class& cls = Class::Handle(function.origin());
+ const Class& cls = Class::Handle(Z, function.origin());
if (!cls.IsTopLevel()) {
return Dart_NewInteger(cls.id());
}
@@ -324,21 +316,19 @@
DART_EXPORT Dart_Handle Dart_GetLocalVariables(
Dart_ActivationFrame activation_frame) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
+ DARTSCOPE(Thread::Current());
CHECK_AND_CAST(ActivationFrame, frame, activation_frame);
- return Api::NewHandle(isolate, frame->GetLocalVariables());
+ return Api::NewHandle(I, frame->GetLocalVariables());
}
DART_EXPORT Dart_Handle Dart_SetBreakpoint(
Dart_Handle script_url_in,
intptr_t line_number) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
+ DARTSCOPE(Thread::Current());
UNWRAP_AND_CHECK_PARAM(String, script_url, script_url_in);
- Debugger* debugger = isolate->debugger();
+ Debugger* debugger = I->debugger();
Breakpoint* bpt =
debugger->SetBreakpointAtLine(script_url, line_number);
if (bpt == NULL) {
@@ -350,23 +340,21 @@
DART_EXPORT Dart_Handle Dart_GetBreakpointURL(intptr_t bp_id) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
- Debugger* debugger = isolate->debugger();
+ DARTSCOPE(Thread::Current());
+ Debugger* debugger = I->debugger();
Breakpoint* bpt = debugger->GetBreakpointById(bp_id);
if (bpt == NULL) {
return Api::NewError("%s: breakpoint with id %" Pd " does not exist",
CURRENT_FUNC, bp_id);
}
- return Api::NewHandle(isolate, bpt->bpt_location()->url());
+ return Api::NewHandle(I, bpt->bpt_location()->url());
}
DART_EXPORT Dart_Handle Dart_GetBreakpointLine(intptr_t bp_id) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
- Debugger* debugger = isolate->debugger();
+ DARTSCOPE(Thread::Current());
+ Debugger* debugger = I->debugger();
Breakpoint* bpt = debugger->GetBreakpointById(bp_id);
if (bpt == NULL) {
@@ -381,8 +369,7 @@
Dart_Handle library_in,
Dart_Handle class_name_in,
Dart_Handle function_name_in) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
+ DARTSCOPE(Thread::Current());
UNWRAP_AND_CHECK_PARAM(Library, library, library_in);
UNWRAP_AND_CHECK_PARAM(String, class_name, class_name_in);
UNWRAP_AND_CHECK_PARAM(String, function_name, function_name_in);
@@ -395,7 +382,7 @@
}
// Resolve the breakpoint target function.
- Debugger* debugger = isolate->debugger();
+ Debugger* debugger = I->debugger();
const Function& bp_target = Function::Handle(
debugger->ResolveFunction(library, class_name, function_name));
if (bp_target.IsNull()) {
@@ -421,8 +408,7 @@
Dart_Handle library_in,
Dart_Handle class_name_in,
Dart_Handle function_name_in) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
+ DARTSCOPE(Thread::Current());
UNWRAP_AND_CHECK_PARAM(Library, library, library_in);
UNWRAP_AND_CHECK_PARAM(String, class_name, class_name_in);
UNWRAP_AND_CHECK_PARAM(String, function_name, function_name_in);
@@ -435,7 +421,7 @@
}
// Resolve the breakpoint target function.
- Debugger* debugger = isolate->debugger();
+ Debugger* debugger = I->debugger();
const Function& bp_target = Function::Handle(
debugger->ResolveFunction(library, class_name, function_name));
if (bp_target.IsNull()) {
@@ -447,111 +433,101 @@
function_name.ToCString());
}
- const Error& error =
- Error::Handle(isolate, debugger->OneTimeBreakAtEntry(bp_target));
+ const Error& error = Error::Handle(Z,
+ debugger->OneTimeBreakAtEntry(bp_target));
if (!error.IsNull()) {
- return Api::NewHandle(isolate, error.raw());
+ return Api::NewHandle(I, error.raw());
}
return Api::Success();
}
DART_EXPORT Dart_Handle Dart_RemoveBreakpoint(intptr_t bp_id) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
- isolate->debugger()->RemoveBreakpoint(bp_id);
+ DARTSCOPE(Thread::Current());
+ I->debugger()->RemoveBreakpoint(bp_id);
return Api::Success();
}
DART_EXPORT Dart_Handle Dart_SetStepOver() {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
- isolate->debugger()->SetStepOver();
+ DARTSCOPE(Thread::Current());
+ I->debugger()->SetStepOver();
return Api::Success();
}
DART_EXPORT Dart_Handle Dart_SetStepInto() {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
- isolate->debugger()->SetSingleStep();
+ DARTSCOPE(Thread::Current());
+ I->debugger()->SetSingleStep();
return Api::Success();
}
DART_EXPORT Dart_Handle Dart_SetStepOut() {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
- isolate->debugger()->SetStepOut();
+ DARTSCOPE(Thread::Current());
+ I->debugger()->SetStepOut();
return Api::Success();
}
DART_EXPORT Dart_Handle Dart_GetInstanceFields(Dart_Handle object_in) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
+ DARTSCOPE(Thread::Current());
UNWRAP_AND_CHECK_PARAM(Instance, obj, object_in);
- return Api::NewHandle(isolate, isolate->debugger()->GetInstanceFields(obj));
+ return Api::NewHandle(I, I->debugger()->GetInstanceFields(obj));
}
DART_EXPORT Dart_Handle Dart_GetStaticFields(Dart_Handle target) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
- const Type& type_obj = Api::UnwrapTypeHandle(isolate, target);
+ DARTSCOPE(Thread::Current());
+ const Type& type_obj = Api::UnwrapTypeHandle(I, target);
if (type_obj.IsNull()) {
return Api::NewError("%s expects argument 'target' to be a type",
CURRENT_FUNC);
}
- const Class& cls = Class::Handle(isolate, type_obj.type_class());
- return Api::NewHandle(isolate, isolate->debugger()->GetStaticFields(cls));
+ const Class& cls = Class::Handle(Z, type_obj.type_class());
+ return Api::NewHandle(I, I->debugger()->GetStaticFields(cls));
}
DART_EXPORT Dart_Handle Dart_GetLibraryFields(intptr_t library_id) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
+ DARTSCOPE(Thread::Current());
const Library& lib =
- Library::Handle(isolate, Library::GetLibrary(library_id));
+ Library::Handle(Z, Library::GetLibrary(library_id));
if (lib.IsNull()) {
return Api::NewError("%s: %" Pd " is not a valid library id",
CURRENT_FUNC, library_id);
}
- return Api::NewHandle(isolate, isolate->debugger()->GetLibraryFields(lib));
+ return Api::NewHandle(I, I->debugger()->GetLibraryFields(lib));
}
DART_EXPORT Dart_Handle Dart_GetGlobalVariables(intptr_t library_id) {
- Isolate* isolate = Isolate::Current();
- ASSERT(isolate != NULL);
- DARTSCOPE(isolate);
- const Library& lib = Library::Handle(Library::GetLibrary(library_id));
+ DARTSCOPE(Thread::Current());
+
+ const Library& lib = Library::Handle(Z, Library::GetLibrary(library_id));
if (lib.IsNull()) {
return Api::NewError("%s: %" Pd " is not a valid library id",
CURRENT_FUNC, library_id);
}
- return Api::NewHandle(isolate, isolate->debugger()->GetGlobalFields(lib));
+ return Api::NewHandle(I, I->debugger()->GetGlobalFields(lib));
}
DART_EXPORT Dart_Handle Dart_ActivationFrameEvaluate(
Dart_ActivationFrame activation_frame,
Dart_Handle expr_in) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
+ DARTSCOPE(Thread::Current());
CHECK_AND_CAST(ActivationFrame, frame, activation_frame);
UNWRAP_AND_CHECK_PARAM(String, expr, expr_in);
- return Api::NewHandle(isolate, frame->Evaluate(expr));
+ return Api::NewHandle(I, frame->Evaluate(expr));
}
DART_EXPORT Dart_Handle Dart_EvaluateExpr(Dart_Handle target_in,
Dart_Handle expr_in) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
+ DARTSCOPE(Thread::Current());
- const Object& target = Object::Handle(isolate, Api::UnwrapHandle(target_in));
+ const Object& target = Object::Handle(Z, Api::UnwrapHandle(target_in));
if (target.IsError()) return target_in;
if (target.IsNull()) {
return Api::NewError("%s expects argument 'target' to be non-null",
@@ -560,42 +536,40 @@
UNWRAP_AND_CHECK_PARAM(String, expr, expr_in);
// Type extends Instance, must check first.
if (target.IsType()) {
- const Class& cls = Class::Handle(isolate, Type::Cast(target).type_class());
- return Api::NewHandle(isolate, cls.Evaluate(expr,
- Array::empty_array(),
- Array::empty_array()));
+ const Class& cls = Class::Handle(Z, Type::Cast(target).type_class());
+ return Api::NewHandle(I, cls.Evaluate(expr,
+ Array::empty_array(),
+ Array::empty_array()));
} else if (target.IsInstance()) {
const Instance& inst = Instance::Cast(target);
- return Api::NewHandle(isolate, inst.Evaluate(expr,
- Array::empty_array(),
- Array::empty_array()));
+ return Api::NewHandle(I, inst.Evaluate(expr,
+ Array::empty_array(),
+ Array::empty_array()));
} else if (target.IsLibrary()) {
const Library& lib = Library::Cast(target);
- return Api::NewHandle(isolate, lib.Evaluate(expr,
- Array::empty_array(),
- Array::empty_array()));
+ return Api::NewHandle(I, lib.Evaluate(expr,
+ Array::empty_array(),
+ Array::empty_array()));
} else if (target.IsClass()) {
const Class& cls = Class::Cast(target);
- return Api::NewHandle(isolate, cls.Evaluate(expr,
- Array::empty_array(),
- Array::empty_array()));
+ return Api::NewHandle(I, cls.Evaluate(expr,
+ Array::empty_array(),
+ Array::empty_array()));
}
return Api::NewError("%s: unsupported target type", CURRENT_FUNC);
}
DART_EXPORT Dart_Handle Dart_GetObjClass(Dart_Handle object_in) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
+ DARTSCOPE(Thread::Current());
UNWRAP_AND_CHECK_PARAM(Instance, obj, object_in);
- return Api::NewHandle(isolate, obj.GetType());
+ return Api::NewHandle(I, obj.GetType());
}
DART_EXPORT Dart_Handle Dart_GetObjClassId(Dart_Handle object_in,
intptr_t* class_id) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
+ DARTSCOPE(Thread::Current());
UNWRAP_AND_CHECK_PARAM(Instance, obj, object_in);
CHECK_NOT_NULL(class_id);
*class_id = obj.GetClassId();
@@ -604,19 +578,17 @@
DART_EXPORT Dart_Handle Dart_GetClassFromId(intptr_t class_id) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
- if (!isolate->class_table()->IsValidIndex(class_id)) {
+ DARTSCOPE(Thread::Current());
+ if (!I->class_table()->IsValidIndex(class_id)) {
return Api::NewError("%s: %" Pd " is not a valid class id",
CURRENT_FUNC, class_id);
}
- return Api::NewHandle(isolate, isolate->class_table()->At(class_id));
+ return Api::NewHandle(I, I->class_table()->At(class_id));
}
DART_EXPORT Dart_Handle Dart_GetSupertype(Dart_Handle type_in) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
+ DARTSCOPE(Thread::Current());
UNWRAP_AND_CHECK_PARAM(Type, type, type_in);
if (!type.IsFinalized()) {
@@ -635,7 +607,7 @@
if (type.IsNull()) {
return Dart_Null();
}
- return Api::NewHandle(isolate, type.Canonicalize());
+ return Api::NewHandle(I, type.Canonicalize());
}
// Set up the type arguments array for the super class type.
const Class& super_cls = Class::Handle(cls.SuperClass());
@@ -657,7 +629,7 @@
Type::New(super_cls, super_type_args_array, Scanner::kNoSourcePos));
ASSERT(!instantiated_type.IsNull());
instantiated_type.SetIsFinalized();
- return Api::NewHandle(isolate, instantiated_type.Canonicalize());
+ return Api::NewHandle(I, instantiated_type.Canonicalize());
}
@@ -666,8 +638,7 @@
Dart_Handle* name,
Dart_Handle* signature,
Dart_CodeLocation* location) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
+ DARTSCOPE(Thread::Current());
UNWRAP_AND_CHECK_PARAM(Instance, instance, closure);
CHECK_NOT_NULL(location);
@@ -677,26 +648,26 @@
const Function& func = Function::Handle(Closure::function(instance));
ASSERT(!func.IsNull());
if (name != NULL) {
- *name = Api::NewHandle(isolate, func.QualifiedUserVisibleName());
+ *name = Api::NewHandle(I, func.QualifiedUserVisibleName());
}
if (signature != NULL) {
- *signature = Api::NewHandle(isolate, func.UserVisibleSignature());
+ *signature = Api::NewHandle(I, func.UserVisibleSignature());
}
if (location != NULL) {
if (func.token_pos() >= 0) {
- const Class& cls = Class::Handle(func.origin());
+ const Class& cls = Class::Handle(Z, func.origin());
ASSERT(!cls.IsNull());
- const Library& lib = Library::Handle(isolate, cls.library());
+ const Library& lib = Library::Handle(Z, cls.library());
ASSERT(!lib.IsNull());
// Note func.script() is not the same as cls.script() for eval functions.
- const Script& script = Script::Handle(func.script());
+ const Script& script = Script::Handle(Z, func.script());
ASSERT(!script.IsNull());
- location->script_url = Api::NewHandle(isolate, script.url());
+ location->script_url = Api::NewHandle(I, script.url());
location->library_id = lib.index();
location->token_pos = func.token_pos();
} else {
- location->script_url = Api::NewHandle(isolate, String::null());
+ location->script_url = Api::NewHandle(I, String::null());
location->library_id = -1;
location->token_pos = -1;
}
@@ -711,30 +682,29 @@
intptr_t* library_id,
intptr_t* super_class_id,
Dart_Handle* static_fields) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
- if (!isolate->class_table()->IsValidIndex(cls_id)) {
+ DARTSCOPE(Thread::Current());
+ if (!I->class_table()->IsValidIndex(cls_id)) {
return Api::NewError("%s: %" Pd " is not a valid class id",
CURRENT_FUNC, cls_id);
}
- Class& cls = Class::Handle(isolate, isolate->class_table()->At(cls_id));
+ Class& cls = Class::Handle(Z, I->class_table()->At(cls_id));
if (class_name != NULL) {
- *class_name = Api::NewHandle(isolate, cls.Name());
+ *class_name = Api::NewHandle(I, cls.Name());
}
if (library_id != NULL) {
- const Library& lib = Library::Handle(isolate, cls.library());
+ const Library& lib = Library::Handle(Z, cls.library());
*library_id = lib.index();
}
if (super_class_id != NULL) {
*super_class_id = 0;
- Class& super_cls = Class::Handle(isolate, cls.SuperClass());
+ Class& super_cls = Class::Handle(Z, cls.SuperClass());
if (!super_cls.IsNull()) {
*super_class_id = super_cls.id();
}
}
if (static_fields != NULL) {
*static_fields =
- Api::NewHandle(isolate, isolate->debugger()->GetStaticFields(cls));
+ Api::NewHandle(I, I->debugger()->GetStaticFields(cls));
}
return Api::Success();
}
@@ -743,8 +713,7 @@
DART_EXPORT Dart_Handle Dart_ScriptGetSource(
intptr_t library_id,
Dart_Handle script_url_in) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
+ DARTSCOPE(Thread::Current());
const Library& lib = Library::Handle(Library::GetLibrary(library_id));
if (lib.IsNull()) {
return Api::NewError("%s: %" Pd " is not a valid library id",
@@ -757,15 +726,14 @@
CURRENT_FUNC, script_url.ToCString(),
String::Handle(lib.url()).ToCString());
}
- return Api::NewHandle(isolate, script.Source());
+ return Api::NewHandle(I, script.Source());
}
DART_EXPORT Dart_Handle Dart_ScriptGetTokenInfo(
intptr_t library_id,
Dart_Handle script_url_in) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
+ DARTSCOPE(Thread::Current());
const Library& lib = Library::Handle(Library::GetLibrary(library_id));
if (lib.IsNull()) {
return Api::NewError("%s: %" Pd " is not a valid library id",
@@ -781,14 +749,13 @@
const GrowableObjectArray& info =
GrowableObjectArray::Handle(script.GenerateLineNumberArray());
- return Api::NewHandle(isolate, Array::MakeArray(info));
+ return Api::NewHandle(I, Array::MakeArray(info));
}
DART_EXPORT Dart_Handle Dart_GenerateScriptSource(Dart_Handle library_url_in,
Dart_Handle script_url_in) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
+ DARTSCOPE(Thread::Current());
UNWRAP_AND_CHECK_PARAM(String, library_url, library_url_in);
UNWRAP_AND_CHECK_PARAM(String, script_url, script_url_in);
@@ -805,13 +772,12 @@
library_url.ToCString());
}
- return Api::NewHandle(isolate, script.GenerateSource());
+ return Api::NewHandle(I, script.GenerateSource());
}
DART_EXPORT Dart_Handle Dart_GetScriptURLs(Dart_Handle library_url_in) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
+ DARTSCOPE(Thread::Current());
UNWRAP_AND_CHECK_PARAM(String, library_url, library_url_in);
const Library& library = Library::Handle(Library::LookupLibrary(library_url));
@@ -830,52 +796,47 @@
url = script.url();
script_list.SetAt(i, url);
}
- return Api::NewHandle(isolate, script_list.raw());
+ return Api::NewHandle(I, script_list.raw());
}
DART_EXPORT Dart_Handle Dart_GetLibraryIds() {
- Isolate* isolate = Isolate::Current();
- ASSERT(isolate != NULL);
- DARTSCOPE(isolate);
+ DARTSCOPE(Thread::Current());
const GrowableObjectArray& libs =
- GrowableObjectArray::Handle(isolate->object_store()->libraries());
+ GrowableObjectArray::Handle(Z, I->object_store()->libraries());
int num_libs = libs.Length();
// Create new list and populate with the url of loaded libraries.
Library &lib = Library::Handle();
- const Array& library_id_list = Array::Handle(Array::New(num_libs));
+ const Array& library_id_list = Array::Handle(Z, Array::New(num_libs));
for (int i = 0; i < num_libs; i++) {
lib ^= libs.At(i);
ASSERT(!lib.IsNull());
ASSERT(Smi::IsValid(lib.index()));
library_id_list.SetAt(i, Smi::Handle(Smi::New(lib.index())));
}
- return Api::NewHandle(isolate, library_id_list.raw());
+ return Api::NewHandle(I, library_id_list.raw());
}
DART_EXPORT Dart_Handle Dart_GetLibraryFromId(intptr_t library_id) {
- Isolate* isolate = Isolate::Current();
- ASSERT(isolate != NULL);
- DARTSCOPE(isolate);
- const Library& lib = Library::Handle(Library::GetLibrary(library_id));
+ DARTSCOPE(Thread::Current());
+ const Library& lib = Library::Handle(Z, Library::GetLibrary(library_id));
if (lib.IsNull()) {
return Api::NewError("%s: %" Pd " is not a valid library id",
CURRENT_FUNC, library_id);
}
- return Api::NewHandle(isolate, lib.raw());
+ return Api::NewHandle(I, lib.raw());
}
DART_EXPORT Dart_Handle Dart_LibraryId(Dart_Handle library,
intptr_t* library_id) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
- const Library& lib = Api::UnwrapLibraryHandle(isolate, library);
+ DARTSCOPE(Thread::Current());
+ const Library& lib = Api::UnwrapLibraryHandle(I, library);
if (lib.IsNull()) {
- RETURN_TYPE_ERROR(isolate, library, Library);
+ RETURN_TYPE_ERROR(I, library, Library);
}
if (library_id == NULL) {
RETURN_NULL_ERROR(library_id);
@@ -886,9 +847,7 @@
DART_EXPORT Dart_Handle Dart_GetLibraryImports(intptr_t library_id) {
- Isolate* isolate = Isolate::Current();
- ASSERT(isolate != NULL);
- DARTSCOPE(isolate);
+ DARTSCOPE(Thread::Current());
const Library& lib = Library::Handle(Library::GetLibrary(library_id));
if (lib.IsNull()) {
return Api::NewError("%s: %" Pd " is not a valid library id",
@@ -897,18 +856,18 @@
const GrowableObjectArray& import_list =
GrowableObjectArray::Handle(GrowableObjectArray::New(8));
- String& prefix_name = String::Handle(isolate);
- Library& imported = Library::Handle(isolate);
+ String& prefix_name = String::Handle(Z);
+ Library& imported = Library::Handle(Z);
intptr_t num_imports = lib.num_imports();
for (int i = 0; i < num_imports; i++) {
import_list.Add(prefix_name); // Null prefix name means no prefix.
imported = lib.ImportLibraryAt(i);
ASSERT(!imported.IsNull());
ASSERT(Smi::IsValid(imported.index()));
- import_list.Add(Smi::Handle(Smi::New(imported.index())));
+ import_list.Add(Smi::Handle(Z, Smi::New(imported.index())));
}
LibraryPrefixIterator it(lib);
- LibraryPrefix& prefix = LibraryPrefix::Handle(isolate);
+ LibraryPrefix& prefix = LibraryPrefix::Handle(Z);
while (it.HasNext()) {
prefix = it.GetNext();
prefix_name = prefix.name();
@@ -920,28 +879,24 @@
import_list.Add(Smi::Handle(Smi::New(imported.index())));
}
}
- return Api::NewHandle(isolate, Array::MakeArray(import_list));
+ return Api::NewHandle(I, Array::MakeArray(import_list));
}
DART_EXPORT Dart_Handle Dart_GetLibraryURL(intptr_t library_id) {
- Isolate* isolate = Isolate::Current();
- ASSERT(isolate != NULL);
- DARTSCOPE(isolate);
- const Library& lib = Library::Handle(Library::GetLibrary(library_id));
+ DARTSCOPE(Thread::Current());
+ const Library& lib = Library::Handle(Z, Library::GetLibrary(library_id));
if (lib.IsNull()) {
return Api::NewError("%s: %" Pd " is not a valid library id",
CURRENT_FUNC, library_id);
}
- return Api::NewHandle(isolate, lib.url());
+ return Api::NewHandle(I, lib.url());
}
DART_EXPORT Dart_Handle Dart_GetLibraryDebuggable(intptr_t library_id,
bool* is_debuggable) {
- Isolate* isolate = Isolate::Current();
- ASSERT(isolate != NULL);
- DARTSCOPE(isolate);
+ DARTSCOPE(Thread::Current());
CHECK_NOT_NULL(is_debuggable);
const Library& lib = Library::Handle(Library::GetLibrary(library_id));
if (lib.IsNull()) {
@@ -955,10 +910,8 @@
DART_EXPORT Dart_Handle Dart_SetLibraryDebuggable(intptr_t library_id,
bool is_debuggable) {
- Isolate* isolate = Isolate::Current();
- ASSERT(isolate != NULL);
- DARTSCOPE(isolate);
- const Library& lib = Library::Handle(Library::GetLibrary(library_id));
+ DARTSCOPE(Thread::Current());
+ const Library& lib = Library::Handle(Z, Library::GetLibrary(library_id));
if (lib.IsNull()) {
return Api::NewError("%s: %" Pd " is not a valid library id",
CURRENT_FUNC, library_id);
diff --git a/runtime/vm/find_code_object_test.cc b/runtime/vm/find_code_object_test.cc
index f67b684..96ff8d3 100644
--- a/runtime/vm/find_code_object_test.cc
+++ b/runtime/vm/find_code_object_test.cc
@@ -27,7 +27,7 @@
Isolate* isolate = Isolate::Current();
ASSERT(isolate != NULL);
- StackZone zone(isolate);
+ StackZone zone(thread);
String& url = String::Handle(String::New("dart-test:FindCodeObject"));
String& source = String::Handle();
Script& script = Script::Handle();
diff --git a/runtime/vm/flow_graph_builder.cc b/runtime/vm/flow_graph_builder.cc
index 8214f69..371ec0e 100644
--- a/runtime/vm/flow_graph_builder.cc
+++ b/runtime/vm/flow_graph_builder.cc
@@ -2331,10 +2331,11 @@
// We need to create a new await state which involves:
// * Increase the jump counter. Sanity check against the list of targets.
// * Save the current context for resuming.
- ASSERT(node->scope() != NULL);
- LocalVariable* jump_var = node->scope()->LookupVariable(
+ ASSERT(node->async_scope() != NULL);
+ ASSERT(node->await_scope() != NULL);
+ LocalVariable* jump_var = node->async_scope()->LookupVariable(
Symbols::AwaitJumpVar(), false);
- LocalVariable* ctx_var = node->scope()->LookupVariable(
+ LocalVariable* ctx_var = node->async_scope()->LookupVariable(
Symbols::AwaitContextVar(), false);
ASSERT((jump_var != NULL) && jump_var->is_captured());
ASSERT((ctx_var != NULL) && ctx_var->is_captured());
diff --git a/runtime/vm/growable_array.h b/runtime/vm/growable_array.h
index 88163fb..9023948 100644
--- a/runtime/vm/growable_array.h
+++ b/runtime/vm/growable_array.h
@@ -215,6 +215,10 @@
return operator[](index);
}
+ void SetAt(intptr_t index, const T& t) {
+ array_[index] = &T::ZoneHandle(zone_, t.raw());
+ }
+
intptr_t length() const { return array_.length(); }
const GrowableArray<T*>& growable_array() const { return array_; }
diff --git a/runtime/vm/handles.cc b/runtime/vm/handles.cc
index c053542..7057739 100644
--- a/runtime/vm/handles.cc
+++ b/runtime/vm/handles.cc
@@ -109,11 +109,6 @@
}
-HandleScope::HandleScope(Isolate* isolate) : StackResource(isolate) {
- Initialize();
-}
-
-
HandleScope::~HandleScope() {
ASSERT(thread()->zone() != NULL);
VMHandles* handles = thread()->zone()->handles();
@@ -130,13 +125,8 @@
#if defined(DEBUG)
-NoHandleScope::NoHandleScope(Isolate* isolate) : StackResource(isolate) {
- thread()->IncrementNoHandleScopeDepth();
-}
-
-
-NoHandleScope::NoHandleScope() : StackResource(Thread::Current()) {
- thread()->IncrementNoHandleScopeDepth();
+NoHandleScope::NoHandleScope(Thread* thread) : StackResource(thread) {
+ thread->IncrementNoHandleScopeDepth();
}
diff --git a/runtime/vm/handles.h b/runtime/vm/handles.h
index f86d0bb..343d139 100644
--- a/runtime/vm/handles.h
+++ b/runtime/vm/handles.h
@@ -301,8 +301,6 @@
class HandleScope : public StackResource {
public:
explicit HandleScope(Thread* thread);
- // DEPRECATED: Use Thread version.
- explicit HandleScope(Isolate* isolate);
~HandleScope();
private:
@@ -337,9 +335,6 @@
class NoHandleScope : public StackResource {
public:
explicit NoHandleScope(Thread* thread);
- // DEPRECATED: Use Thread version.
- explicit NoHandleScope(Isolate* isolate);
- NoHandleScope();
~NoHandleScope();
private:
diff --git a/runtime/vm/handles_test.cc b/runtime/vm/handles_test.cc
index cc82f26..b871f97 100644
--- a/runtime/vm/handles_test.cc
+++ b/runtime/vm/handles_test.cc
@@ -49,8 +49,8 @@
static const int kNumHandles = 65;
// Create some scoped handles.
{
- Isolate* isolate = Isolate::Current();
- HANDLESCOPE(isolate);
+ Thread* thread = Thread::Current();
+ HANDLESCOPE(thread);
for (int i = 0; i < kNumHandles; i++) {
const Smi& handle = Smi::Handle(Smi::New(i));
EXPECT(handle.IsSmi());
@@ -59,7 +59,7 @@
EXPECT_EQ((handle_count + kNumHandles), VMHandles::ScopedHandleCount());
// Create lots of scoped handles in a loop with a nested scope.
for (int loop = 0; loop < 1000; loop++) {
- HANDLESCOPE(isolate);
+ HANDLESCOPE(thread);
for (int i = 0; i < 2; i++) {
const Smi& handle = Smi::Handle(Smi::New(i + loop));
EXPECT(handle.IsSmi());
diff --git a/runtime/vm/intermediate_language.cc b/runtime/vm/intermediate_language.cc
index b7bacba..7f4a862 100644
--- a/runtime/vm/intermediate_language.cc
+++ b/runtime/vm/intermediate_language.cc
@@ -1630,7 +1630,9 @@
switch (op_kind()) {
case Token::kNEGATE:
- result = value.ArithmeticOp(Token::kMUL, Smi::Handle(Smi::New(-1)));
+ result = value.ArithmeticOp(Token::kMUL,
+ Smi::Handle(Smi::New(-1)),
+ Heap::kOld);
break;
case Token::kBIT_NOT:
@@ -1675,7 +1677,7 @@
case Token::kADD:
case Token::kSUB:
case Token::kMUL: {
- result = left.ArithmeticOp(op_kind(), right);
+ result = left.ArithmeticOp(op_kind(), right, Heap::kOld);
break;
}
case Token::kSHL:
@@ -3428,50 +3430,52 @@
!num_elements->BoundConstant().IsSmi()) {
return this;
}
- intptr_t length = Smi::Cast(num_elements->BoundConstant()).Value();
- GrowableArray<ConstantInstr*> constants(length);
+ const intptr_t length = Smi::Cast(num_elements->BoundConstant()).Value();
+ Zone* zone = Thread::Current()->zone();
+ GrowableHandlePtrArray<const String> pieces(zone, length);
for (intptr_t i = 0; i < length; i++) {
- constants.Add(NULL);
+ pieces.Add(Object::null_string());
}
+
for (Value::Iterator it(create_array->input_use_list());
!it.Done();
it.Advance()) {
Instruction* curr = it.Current()->instruction();
- if (curr != this) {
- StoreIndexedInstr* store = curr->AsStoreIndexed();
- ASSERT(store != NULL);
- if (store->value()->definition()->IsConstant()) {
- ASSERT(store->index()->BindsToConstant());
- const Object& obj = store->value()->definition()->AsConstant()->value();
- if (obj.IsNumber() || obj.IsString() || obj.IsBool() || obj.IsNull()) {
- constants[Smi::Cast(store->index()->BoundConstant()).Value()] =
- store->value()->definition()->AsConstant();
- } else {
- return this;
- }
+ if (curr == this) continue;
+
+ StoreIndexedInstr* store = curr->AsStoreIndexed();
+ if (!store->index()->BindsToConstant() ||
+ !store->index()->BoundConstant().IsSmi()) {
+ return this;
+ }
+ intptr_t store_index = Smi::Cast(store->index()->BoundConstant()).Value();
+ ASSERT(store_index < length);
+ ASSERT(store != NULL);
+ if (store->value()->definition()->IsConstant()) {
+ ASSERT(store->index()->BindsToConstant());
+ const Object& obj = store->value()->definition()->AsConstant()->value();
+ // TODO(srdjan): Verify if any other types should be converted as well.
+ if (obj.IsString()) {
+ pieces.SetAt(store_index, String::Cast(obj));
+ } else if (obj.IsSmi()) {
+ const char* cstr = obj.ToCString();
+ pieces.SetAt(store_index, String::Handle(zone, String::New(cstr)));
+ } else if (obj.IsBool()) {
+ pieces.SetAt(store_index,
+ Bool::Cast(obj).value() ? Symbols::True() : Symbols::False());
+ } else if (obj.IsNull()) {
+ pieces.SetAt(store_index, Symbols::Null());
} else {
return this;
}
+ } else {
+ return this;
}
}
- // Interpolate string at compile time.
- const Array& array_argument =
- Array::Handle(Array::New(length));
- for (intptr_t i = 0; i < constants.length(); i++) {
- array_argument.SetAt(i, constants[i]->value());
- }
- // Build argument array to pass to the interpolation function.
- const Array& interpolate_arg = Array::Handle(Array::New(1));
- interpolate_arg.SetAt(0, array_argument);
- // Call interpolation function.
- const Object& result = Object::Handle(
- DartEntry::InvokeFunction(CallFunction(), interpolate_arg));
- if (result.IsUnhandledException()) {
- return this;
- }
- ASSERT(result.IsString());
- const String& concatenated =
- String::ZoneHandle(Symbols::New(String::Cast(result)));
+
+ ASSERT(pieces.length() == length);
+ const String& concatenated = String::ZoneHandle(zone,
+ Symbols::FromConcatAll(pieces));
return flow_graph->GetConstant(concatenated);
}
@@ -3518,71 +3522,71 @@
typedef double (*UnaryMathCFunction) (double x);
typedef double (*BinaryMathCFunction) (double x, double y);
-extern const RuntimeEntry kPowRuntimeEntry(
- "libc_pow", reinterpret_cast<RuntimeFunction>(
- static_cast<BinaryMathCFunction>(&pow)), 2, true, true);
+DEFINE_RAW_LEAF_RUNTIME_ENTRY(LibcPow, 2, true /* is_float */,
+ reinterpret_cast<RuntimeFunction>(
+ static_cast<BinaryMathCFunction>(&pow)));
-extern const RuntimeEntry kModRuntimeEntry(
- "DartModulo", reinterpret_cast<RuntimeFunction>(
- static_cast<BinaryMathCFunction>(&DartModulo)), 2, true, true);
+DEFINE_RAW_LEAF_RUNTIME_ENTRY(DartModulo, 2, true /* is_float */,
+ reinterpret_cast<RuntimeFunction>(
+ static_cast<BinaryMathCFunction>(&DartModulo)));
-extern const RuntimeEntry kFloorRuntimeEntry(
- "libc_floor", reinterpret_cast<RuntimeFunction>(
- static_cast<UnaryMathCFunction>(&floor)), 1, true, true);
+DEFINE_RAW_LEAF_RUNTIME_ENTRY(LibcFloor, 1, true /* is_float */,
+ reinterpret_cast<RuntimeFunction>(
+ static_cast<UnaryMathCFunction>(&floor)));
-extern const RuntimeEntry kCeilRuntimeEntry(
- "libc_ceil", reinterpret_cast<RuntimeFunction>(
- static_cast<UnaryMathCFunction>(&ceil)), 1, true, true);
+DEFINE_RAW_LEAF_RUNTIME_ENTRY(LibcCeil, 1, true /* is_float */,
+ reinterpret_cast<RuntimeFunction>(
+ static_cast<UnaryMathCFunction>(&ceil)));
-extern const RuntimeEntry kTruncRuntimeEntry(
- "libc_trunc", reinterpret_cast<RuntimeFunction>(
- static_cast<UnaryMathCFunction>(&trunc)), 1, true, true);
+DEFINE_RAW_LEAF_RUNTIME_ENTRY(LibcTrunc, 1, true /* is_float */,
+ reinterpret_cast<RuntimeFunction>(
+ static_cast<UnaryMathCFunction>(&trunc)));
-extern const RuntimeEntry kRoundRuntimeEntry(
- "libc_round", reinterpret_cast<RuntimeFunction>(
- static_cast<UnaryMathCFunction>(&round)), 1, true, true);
+DEFINE_RAW_LEAF_RUNTIME_ENTRY(LibcRound, 1, true /* is_float */,
+ reinterpret_cast<RuntimeFunction>(
+ static_cast<UnaryMathCFunction>(&round)));
const RuntimeEntry& InvokeMathCFunctionInstr::TargetFunction() const {
switch (recognized_kind_) {
case MethodRecognizer::kDoubleTruncate:
- return kTruncRuntimeEntry;
+ return kLibcTruncRuntimeEntry;
case MethodRecognizer::kDoubleRound:
- return kRoundRuntimeEntry;
+ return kLibcRoundRuntimeEntry;
case MethodRecognizer::kDoubleFloor:
- return kFloorRuntimeEntry;
+ return kLibcFloorRuntimeEntry;
case MethodRecognizer::kDoubleCeil:
- return kCeilRuntimeEntry;
+ return kLibcCeilRuntimeEntry;
case MethodRecognizer::kMathDoublePow:
- return kPowRuntimeEntry;
+ return kLibcPowRuntimeEntry;
case MethodRecognizer::kDoubleMod:
- return kModRuntimeEntry;
+ return kDartModuloRuntimeEntry;
default:
UNREACHABLE();
}
- return kPowRuntimeEntry;
+ return kLibcPowRuntimeEntry;
}
-extern const RuntimeEntry kCosRuntimeEntry(
- "libc_cos", reinterpret_cast<RuntimeFunction>(
- static_cast<UnaryMathCFunction>(&cos)), 1, true, true);
+DEFINE_RAW_LEAF_RUNTIME_ENTRY(LibcCos, 1, true /* is_float */,
+ reinterpret_cast<RuntimeFunction>(
+ static_cast<UnaryMathCFunction>(&cos)));
-extern const RuntimeEntry kSinRuntimeEntry(
- "libc_sin", reinterpret_cast<RuntimeFunction>(
- static_cast<UnaryMathCFunction>(&sin)), 1, true, true);
+DEFINE_RAW_LEAF_RUNTIME_ENTRY(LibcSin, 1, true /* is_float */,
+ reinterpret_cast<RuntimeFunction>(
+ static_cast<UnaryMathCFunction>(&sin)));
const RuntimeEntry& MathUnaryInstr::TargetFunction() const {
switch (kind()) {
case MathUnaryInstr::kSin:
- return kSinRuntimeEntry;
+ return kLibcSinRuntimeEntry;
case MathUnaryInstr::kCos:
- return kCosRuntimeEntry;
+ return kLibcCosRuntimeEntry;
default:
UNREACHABLE();
}
- return kSinRuntimeEntry;
+ return kLibcSinRuntimeEntry;
}
@@ -3598,18 +3602,6 @@
return "";
}
-typedef RawBool* (*CaseInsensitiveCompareUC16Function) (
- RawString* string_raw,
- RawSmi* lhs_index_raw,
- RawSmi* rhs_index_raw,
- RawSmi* length_raw);
-
-
-extern const RuntimeEntry kCaseInsensitiveCompareUC16RuntimeEntry(
- "CaseInsensitiveCompareUC16", reinterpret_cast<RuntimeFunction>(
- static_cast<CaseInsensitiveCompareUC16Function>(
- &IRRegExpMacroAssembler::CaseInsensitiveCompareUC16)), 4, true, false);
-
const RuntimeEntry& CaseInsensitiveCompareUC16Instr::TargetFunction() const {
return kCaseInsensitiveCompareUC16RuntimeEntry;
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index 4d6c56c..bb1fe76 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -95,7 +95,8 @@
"Enable checked mode.");
-// Quick access to the locally defined isolate() method.
+// Quick access to the locally defined thread() and isolate() methods.
+#define T (thread())
#define I (isolate())
#if defined(DEBUG)
@@ -418,9 +419,7 @@
}
// Parse the message.
- MessageSnapshotReader reader(message->data(),
- message->len(),
- I, zone);
+ MessageSnapshotReader reader(message->data(), message->len(), thread);
const Object& msg_obj = Object::Handle(zone, reader.ReadObject());
if (msg_obj.IsError()) {
// An error occurred while reading the message.
@@ -508,28 +507,28 @@
void IsolateMessageHandler::NotifyPauseOnStart() {
if (Service::debug_stream.enabled()) {
- StartIsolateScope start_isolate(isolate());
- StackZone zone(I);
- HandleScope handle_scope(I);
- ServiceEvent pause_event(isolate(), ServiceEvent::kPauseStart);
+ StartIsolateScope start_isolate(I);
+ StackZone zone(T);
+ HandleScope handle_scope(T);
+ ServiceEvent pause_event(I, ServiceEvent::kPauseStart);
Service::HandleEvent(&pause_event);
} else if (FLAG_trace_service) {
OS::Print("vm-service: Dropping event of type PauseStart (%s)\n",
- isolate()->name());
+ I->name());
}
}
void IsolateMessageHandler::NotifyPauseOnExit() {
if (Service::debug_stream.enabled()) {
- StartIsolateScope start_isolate(isolate());
- StackZone zone(I);
- HandleScope handle_scope(I);
- ServiceEvent pause_event(isolate(), ServiceEvent::kPauseExit);
+ StartIsolateScope start_isolate(I);
+ StackZone zone(T);
+ HandleScope handle_scope(T);
+ ServiceEvent pause_event(I, ServiceEvent::kPauseExit);
Service::HandleEvent(&pause_event);
} else if (FLAG_trace_service) {
OS::Print("vm-service: Dropping event of type PauseExit (%s)\n",
- isolate()->name());
+ I->name());
}
}
@@ -1265,6 +1264,7 @@
static bool RunIsolate(uword parameter) {
Isolate* isolate = reinterpret_cast<Isolate*>(parameter);
IsolateSpawnState* state = NULL;
+ Thread* thread = Thread::Current();
{
// TODO(turnidge): Is this locking required here at all anymore?
MutexLocker ml(isolate->mutex());
@@ -1272,8 +1272,9 @@
}
{
StartIsolateScope start_scope(isolate);
- StackZone zone(isolate);
- HandleScope handle_scope(isolate);
+ ASSERT(thread->isolate() == isolate);
+ StackZone zone(thread);
+ HandleScope handle_scope(thread);
// If particular values were requested for this newly spawned isolate, then
// they are set here before the isolate starts executing user code.
@@ -1342,8 +1343,8 @@
const Array& args = Array::Handle(Array::New(7));
args.SetAt(0, SendPort::Handle(SendPort::New(state->parent_port())));
args.SetAt(1, Instance::Handle(func.ImplicitStaticClosure()));
- args.SetAt(2, Instance::Handle(state->BuildArgs(zone.GetZone())));
- args.SetAt(3, Instance::Handle(state->BuildMessage(zone.GetZone())));
+ args.SetAt(2, Instance::Handle(state->BuildArgs(thread)));
+ args.SetAt(3, Instance::Handle(state->BuildMessage(thread)));
args.SetAt(4, is_spawn_uri ? Bool::True() : Bool::False());
args.SetAt(5, ReceivePort::Handle(
ReceivePort::New(isolate->main_port(), true /* control port */)));
@@ -1370,9 +1371,11 @@
{
// Print the error if there is one. This may execute dart code to
// print the exception object, so we need to use a StartIsolateScope.
+ Thread* thread = Thread::Current();
StartIsolateScope start_scope(isolate);
- StackZone zone(isolate);
- HandleScope handle_scope(isolate);
+ ASSERT(thread->isolate() == isolate);
+ StackZone zone(thread);
+ HandleScope handle_scope(thread);
Error& error = Error::Handle();
error = isolate->object_store()->sticky_error();
if (!error.IsNull() && !error.IsUnwindError()) {
@@ -1493,11 +1496,13 @@
}
#endif // DEBUG
+ Thread* thread = Thread::Current();
+
// First, perform higher-level cleanup that may need to allocate.
{
// Ensure we have a zone and handle scope so that we can call VM functions.
- StackZone stack_zone(this);
- HandleScope handle_scope(this);
+ StackZone stack_zone(thread);
+ HandleScope handle_scope(thread);
// Write out the coverage data if collection has been enabled.
CodeCoverage::Write(this);
@@ -1521,8 +1526,8 @@
{
// Ensure we have a zone and handle scope so that we can call VM functions,
// but we no longer allocate new heap objects.
- StackZone stack_zone(this);
- HandleScope handle_scope(this);
+ StackZone stack_zone(thread);
+ HandleScope handle_scope(thread);
NoSafepointScope no_safepoint_scope;
if (compiler_stats_ != NULL) {
@@ -2145,28 +2150,25 @@
}
-template<class T>
-T* Isolate::AllocateReusableHandle() {
- T* handle = reinterpret_cast<T*>(reusable_handles_.AllocateScopedHandle());
- T::initializeHandle(handle, T::null());
+template<class C>
+C* Isolate::AllocateReusableHandle() {
+ C* handle = reinterpret_cast<C*>(reusable_handles_.AllocateScopedHandle());
+ C::initializeHandle(handle, C::null());
return handle;
}
-static RawInstance* DeserializeObject(Isolate* isolate,
- Zone* zone,
+static RawInstance* DeserializeObject(Thread* thread,
uint8_t* obj_data,
intptr_t obj_len) {
if (obj_data == NULL) {
return Instance::null();
}
- MessageSnapshotReader reader(obj_data,
- obj_len,
- isolate,
- zone);
- const Object& obj = Object::Handle(isolate, reader.ReadObject());
+ MessageSnapshotReader reader(obj_data, obj_len, thread);
+ Zone* zone = thread->zone();
+ const Object& obj = Object::Handle(zone, reader.ReadObject());
ASSERT(!obj.IsError());
- Instance& instance = Instance::Handle(isolate);
+ Instance& instance = Instance::Handle(zone);
instance ^= obj.raw(); // Can't use Instance::Cast because may be null.
return instance.raw();
}
@@ -2341,14 +2343,13 @@
}
-RawInstance* IsolateSpawnState::BuildArgs(Zone* zone) {
- return DeserializeObject(isolate_, zone,
- serialized_args_, serialized_args_len_);
+RawInstance* IsolateSpawnState::BuildArgs(Thread* thread) {
+ return DeserializeObject(thread, serialized_args_, serialized_args_len_);
}
-RawInstance* IsolateSpawnState::BuildMessage(Zone* zone) {
- return DeserializeObject(isolate_, zone,
+RawInstance* IsolateSpawnState::BuildMessage(Thread* thread) {
+ return DeserializeObject(thread,
serialized_message_, serialized_message_len_);
}
diff --git a/runtime/vm/isolate.h b/runtime/vm/isolate.h
index 90f97c4..b8e7a4c 100644
--- a/runtime/vm/isolate.h
+++ b/runtime/vm/isolate.h
@@ -1102,8 +1102,8 @@
Isolate::Flags* isolate_flags() { return &isolate_flags_; }
RawObject* ResolveFunction();
- RawInstance* BuildArgs(Zone* zone);
- RawInstance* BuildMessage(Zone* zone);
+ RawInstance* BuildArgs(Thread* thread);
+ RawInstance* BuildMessage(Thread* thread);
void Cleanup();
private:
diff --git a/runtime/vm/message_handler.h b/runtime/vm/message_handler.h
index 78c5f6c..4a939ae 100644
--- a/runtime/vm/message_handler.h
+++ b/runtime/vm/message_handler.h
@@ -184,6 +184,9 @@
virtual void NotifyPauseOnStart() {}
virtual void NotifyPauseOnExit() {}
+ // TODO(iposva): Set a local field before entering MessageHandler methods.
+ Thread* thread() const { return Thread::Current(); }
+
private:
friend class PortMap;
friend class MessageHandlerTestPeer;
diff --git a/runtime/vm/metrics_test.cc b/runtime/vm/metrics_test.cc
index 9082739..cb204b9 100644
--- a/runtime/vm/metrics_test.cc
+++ b/runtime/vm/metrics_test.cc
@@ -46,9 +46,9 @@
Dart_CreateIsolate(
NULL, NULL, bin::isolate_snapshot_buffer, NULL, NULL, NULL);
{
- Isolate* isolate = Isolate::Current();
- StackZone zone(isolate);
- HANDLESCOPE(isolate);
+ Thread* thread = Thread::Current();
+ StackZone zone(thread);
+ HANDLESCOPE(thread);
MyMetric metric;
metric.Init(Isolate::Current(), "a.b.c", "foobar", Metric::kByte);
diff --git a/runtime/vm/mirrors_api_impl.cc b/runtime/vm/mirrors_api_impl.cc
index d775e22..3d83d44 100644
--- a/runtime/vm/mirrors_api_impl.cc
+++ b/runtime/vm/mirrors_api_impl.cc
@@ -19,37 +19,38 @@
namespace dart {
+// Facilitate quick access to the current zone once we have the curren thread.
+#define Z (T->zone())
+
// --- Classes and Interfaces Reflection ---
DART_EXPORT Dart_Handle Dart_TypeName(Dart_Handle object) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
- const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(object));
+ DARTSCOPE(Thread::Current());
+ const Object& obj = Object::Handle(I, Api::UnwrapHandle(object));
if (obj.IsType()) {
const Class& cls = Class::Handle(Type::Cast(obj).type_class());
- return Api::NewHandle(isolate, cls.UserVisibleName());
+ return Api::NewHandle(I, cls.UserVisibleName());
} else {
- RETURN_TYPE_ERROR(isolate, object, Class/Type);
+ RETURN_TYPE_ERROR(I, object, Class/Type);
}
}
DART_EXPORT Dart_Handle Dart_QualifiedTypeName(Dart_Handle object) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
- const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(object));
+ DARTSCOPE(Thread::Current());
+ const Object& obj = Object::Handle(Z, Api::UnwrapHandle(object));
if (obj.IsType() || obj.IsClass()) {
const Class& cls = (obj.IsType()) ?
- Class::Handle(Type::Cast(obj).type_class()) : Class::Cast(obj);
+ Class::Handle(Z, Type::Cast(obj).type_class()) : Class::Cast(obj);
const char* str = cls.ToCString();
if (str == NULL) {
RETURN_NULL_ERROR(str);
}
- CHECK_CALLBACK_STATE(isolate);
- return Api::NewHandle(isolate, String::New(str));
+ CHECK_CALLBACK_STATE(I);
+ return Api::NewHandle(I, String::New(str));
} else {
- RETURN_TYPE_ERROR(isolate, object, Class/Type);
+ RETURN_TYPE_ERROR(I, object, Class/Type);
}
}
@@ -69,25 +70,24 @@
DART_EXPORT Dart_Handle Dart_GetFunctionNames(Dart_Handle target) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
- const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(target));
+ DARTSCOPE(Thread::Current());
+ const Object& obj = Object::Handle(Z, Api::UnwrapHandle(target));
if (obj.IsError()) {
return target;
}
const GrowableObjectArray& names =
- GrowableObjectArray::Handle(isolate, GrowableObjectArray::New());
- Function& func = Function::Handle();
- String& name = String::Handle();
+ GrowableObjectArray::Handle(Z, GrowableObjectArray::New());
+ Function& func = Function::Handle(Z);
+ String& name = String::Handle(Z);
if (obj.IsType()) {
- const Class& cls = Class::Handle(Type::Cast(obj).type_class());
- const Error& error = Error::Handle(isolate, cls.EnsureIsFinalized(isolate));
+ const Class& cls = Class::Handle(Z, Type::Cast(obj).type_class());
+ const Error& error = Error::Handle(Z, cls.EnsureIsFinalized(I));
if (!error.IsNull()) {
- return Api::NewHandle(isolate, error.raw());
+ return Api::NewHandle(I, error.raw());
}
- const Array& func_array = Array::Handle(cls.functions());
+ const Array& func_array = Array::Handle(Z, cls.functions());
// Some special types like 'dynamic' have a null functions list.
if (!func_array.IsNull()) {
@@ -124,27 +124,26 @@
"%s expects argument 'target' to be a class or library.",
CURRENT_FUNC);
}
- return Api::NewHandle(isolate, Array::MakeArray(names));
+ return Api::NewHandle(I, Array::MakeArray(names));
}
DART_EXPORT Dart_Handle Dart_LookupFunction(Dart_Handle target,
Dart_Handle function_name) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
- const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(target));
+ DARTSCOPE(Thread::Current());
+ const Object& obj = Object::Handle(Z, Api::UnwrapHandle(target));
if (obj.IsError()) {
return target;
}
- const String& func_name = Api::UnwrapStringHandle(isolate, function_name);
+ const String& func_name = Api::UnwrapStringHandle(I, function_name);
if (func_name.IsNull()) {
- RETURN_TYPE_ERROR(isolate, function_name, String);
+ RETURN_TYPE_ERROR(I, function_name, String);
}
- Function& func = Function::Handle(isolate);
- String& tmp_name = String::Handle(isolate);
+ Function& func = Function::Handle(Z);
+ String& tmp_name = String::Handle(Z);
if (obj.IsType()) {
- const Class& cls = Class::Handle(Type::Cast(obj).type_class());
+ const Class& cls = Class::Handle(Z, Type::Cast(obj).type_class());
// Case 1. Lookup the unmodified function name.
func = cls.LookupFunctionAllowPrivate(func_name);
@@ -206,60 +205,57 @@
func_kind == RawFunction::kConstructor);
}
#endif
- return Api::NewHandle(isolate, func.raw());
+ return Api::NewHandle(I, func.raw());
}
DART_EXPORT Dart_Handle Dart_FunctionName(Dart_Handle function) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
- const Function& func = Api::UnwrapFunctionHandle(isolate, function);
+ DARTSCOPE(Thread::Current());
+ const Function& func = Api::UnwrapFunctionHandle(I, function);
if (func.IsNull()) {
- RETURN_TYPE_ERROR(isolate, function, Function);
+ RETURN_TYPE_ERROR(I, function, Function);
}
- return Api::NewHandle(isolate, func.UserVisibleName());
+ return Api::NewHandle(I, func.UserVisibleName());
}
DART_EXPORT Dart_Handle Dart_FunctionOwner(Dart_Handle function) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
- const Function& func = Api::UnwrapFunctionHandle(isolate, function);
+ DARTSCOPE(Thread::Current());
+ const Function& func = Api::UnwrapFunctionHandle(I, function);
if (func.IsNull()) {
- RETURN_TYPE_ERROR(isolate, function, Function);
+ RETURN_TYPE_ERROR(I, function, Function);
}
if (func.IsNonImplicitClosureFunction()) {
RawFunction* parent_function = func.parent_function();
- return Api::NewHandle(isolate, parent_function);
+ return Api::NewHandle(I, parent_function);
}
- const Class& owner = Class::Handle(func.Owner());
+ const Class& owner = Class::Handle(Z, func.Owner());
ASSERT(!owner.IsNull());
if (owner.IsTopLevel()) {
// Top-level functions are implemented as members of a hidden class. We hide
// that class here and instead answer the library.
#if defined(DEBUG)
- const Library& lib = Library::Handle(owner.library());
+ const Library& lib = Library::Handle(Z, owner.library());
if (lib.IsNull()) {
ASSERT(owner.IsDynamicClass() || owner.IsVoidClass());
}
#endif
- return Api::NewHandle(isolate, owner.library());
+ return Api::NewHandle(I, owner.library());
} else {
- return Api::NewHandle(isolate, owner.RareType());
+ return Api::NewHandle(I, owner.RareType());
}
}
DART_EXPORT Dart_Handle Dart_FunctionIsStatic(Dart_Handle function,
bool* is_static) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
+ DARTSCOPE(Thread::Current());
if (is_static == NULL) {
RETURN_NULL_ERROR(is_static);
}
- const Function& func = Api::UnwrapFunctionHandle(isolate, function);
+ const Function& func = Api::UnwrapFunctionHandle(I, function);
if (func.IsNull()) {
- RETURN_TYPE_ERROR(isolate, function, Function);
+ RETURN_TYPE_ERROR(I, function, Function);
}
*is_static = func.is_static();
return Api::Success();
@@ -268,14 +264,13 @@
DART_EXPORT Dart_Handle Dart_FunctionIsConstructor(Dart_Handle function,
bool* is_constructor) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
+ DARTSCOPE(Thread::Current());
if (is_constructor == NULL) {
RETURN_NULL_ERROR(is_constructor);
}
- const Function& func = Api::UnwrapFunctionHandle(isolate, function);
+ const Function& func = Api::UnwrapFunctionHandle(I, function);
if (func.IsNull()) {
- RETURN_TYPE_ERROR(isolate, function, Function);
+ RETURN_TYPE_ERROR(I, function, Function);
}
*is_constructor = func.kind() == RawFunction::kConstructor;
return Api::Success();
@@ -284,14 +279,13 @@
DART_EXPORT Dart_Handle Dart_FunctionIsGetter(Dart_Handle function,
bool* is_getter) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
+ DARTSCOPE(Thread::Current());
if (is_getter == NULL) {
RETURN_NULL_ERROR(is_getter);
}
- const Function& func = Api::UnwrapFunctionHandle(isolate, function);
+ const Function& func = Api::UnwrapFunctionHandle(I, function);
if (func.IsNull()) {
- RETURN_TYPE_ERROR(isolate, function, Function);
+ RETURN_TYPE_ERROR(I, function, Function);
}
*is_getter = func.IsGetterFunction();
return Api::Success();
@@ -300,14 +294,13 @@
DART_EXPORT Dart_Handle Dart_FunctionIsSetter(Dart_Handle function,
bool* is_setter) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
+ DARTSCOPE(Thread::Current());
if (is_setter == NULL) {
RETURN_NULL_ERROR(is_setter);
}
- const Function& func = Api::UnwrapFunctionHandle(isolate, function);
+ const Function& func = Api::UnwrapFunctionHandle(I, function);
if (func.IsNull()) {
- RETURN_TYPE_ERROR(isolate, function, Function);
+ RETURN_TYPE_ERROR(I, function, Function);
}
*is_setter = (func.kind() == RawFunction::kSetterFunction);
return Api::Success();
@@ -317,30 +310,28 @@
// --- Libraries Reflection ---
DART_EXPORT Dart_Handle Dart_LibraryName(Dart_Handle library) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
- const Library& lib = Api::UnwrapLibraryHandle(isolate, library);
+ DARTSCOPE(Thread::Current());
+ const Library& lib = Api::UnwrapLibraryHandle(I, library);
if (lib.IsNull()) {
- RETURN_TYPE_ERROR(isolate, library, Library);
+ RETURN_TYPE_ERROR(I, library, Library);
}
- const String& name = String::Handle(isolate, lib.name());
+ const String& name = String::Handle(Z, lib.name());
ASSERT(!name.IsNull());
- return Api::NewHandle(isolate, name.raw());
+ return Api::NewHandle(I, name.raw());
}
DART_EXPORT Dart_Handle Dart_LibraryGetClassNames(Dart_Handle library) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
- const Library& lib = Api::UnwrapLibraryHandle(isolate, library);
+ DARTSCOPE(Thread::Current());
+ const Library& lib = Api::UnwrapLibraryHandle(I, library);
if (lib.IsNull()) {
- RETURN_TYPE_ERROR(isolate, library, Library);
+ RETURN_TYPE_ERROR(I, library, Library);
}
const GrowableObjectArray& names =
- GrowableObjectArray::Handle(isolate, GrowableObjectArray::New());
+ GrowableObjectArray::Handle(Z, GrowableObjectArray::New());
ClassDictionaryIterator it(lib);
- Class& cls = Class::Handle();
- String& name = String::Handle();
+ Class& cls = Class::Handle(Z);
+ String& name = String::Handle(Z);
while (it.HasNext()) {
cls = it.GetNextClass();
if (cls.IsSignatureClass()) {
@@ -356,24 +347,23 @@
names.Add(name);
}
}
- return Api::NewHandle(isolate, Array::MakeArray(names));
+ return Api::NewHandle(I, Array::MakeArray(names));
}
// --- Closures Reflection ---
DART_EXPORT Dart_Handle Dart_ClosureFunction(Dart_Handle closure) {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
- const Instance& closure_obj = Api::UnwrapInstanceHandle(isolate, closure);
+ DARTSCOPE(Thread::Current());
+ const Instance& closure_obj = Api::UnwrapInstanceHandle(I, closure);
if (closure_obj.IsNull() || !closure_obj.IsClosure()) {
- RETURN_TYPE_ERROR(isolate, closure, Instance);
+ RETURN_TYPE_ERROR(I, closure, Instance);
}
ASSERT(ClassFinalizer::AllClassesFinalized());
RawFunction* rf = Closure::function(closure_obj);
- return Api::NewHandle(isolate, rf);
+ return Api::NewHandle(I, rf);
}
} // namespace dart
diff --git a/runtime/vm/native_api_impl.cc b/runtime/vm/native_api_impl.cc
index a668897..da1d099 100644
--- a/runtime/vm/native_api_impl.cc
+++ b/runtime/vm/native_api_impl.cc
@@ -11,7 +11,6 @@
#include "vm/message.h"
#include "vm/native_message_handler.h"
#include "vm/port.h"
-#include "vm/precompiler.h"
namespace dart {
@@ -80,39 +79,15 @@
}
}
-static void Precompile(Isolate* isolate, Dart_Handle* result) {
- ASSERT(isolate != NULL);
- const Error& error = Error::Handle(isolate, Precompiler::CompileAll());
- if (error.IsNull()) {
- *result = Api::Success();
- } else {
- *result = Api::NewHandle(isolate, error.raw());
- }
-}
-
DART_EXPORT Dart_Handle Dart_CompileAll() {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
- Dart_Handle result = Api::CheckAndFinalizePendingClasses(isolate);
+ DARTSCOPE(Thread::Current());
+ Dart_Handle result = Api::CheckAndFinalizePendingClasses(I);
if (::Dart_IsError(result)) {
return result;
}
- CHECK_CALLBACK_STATE(isolate);
- CompileAll(isolate, &result);
- return result;
-}
-
-
-DART_EXPORT Dart_Handle Dart_Precompile() {
- Isolate* isolate = Isolate::Current();
- DARTSCOPE(isolate);
- Dart_Handle result = Api::CheckAndFinalizePendingClasses(isolate);
- if (::Dart_IsError(result)) {
- return result;
- }
- CHECK_CALLBACK_STATE(isolate);
- Precompile(isolate, &result);
+ CHECK_CALLBACK_STATE(I);
+ CompileAll(I, &result);
return result;
}
diff --git a/runtime/vm/native_entry_test.h b/runtime/vm/native_entry_test.h
index 7e51a24..706b4b6 100644
--- a/runtime/vm/native_entry_test.h
+++ b/runtime/vm/native_entry_test.h
@@ -10,9 +10,6 @@
namespace dart {
-DECLARE_RUNTIME_ENTRY(TestSmiSub)
-DECLARE_LEAF_RUNTIME_ENTRY(RawObject*, TestLeafSmiAdd, RawObject*, RawObject*)
-
void TestSmiSub(Dart_NativeArguments args);
void TestSmiSum(Dart_NativeArguments args);
void TestNonNullSmiSum(Dart_NativeArguments args);
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 1d6e33b..86d461a 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -115,6 +115,7 @@
LanguageError* Object::snapshot_writer_error_ = NULL;
LanguageError* Object::branch_offset_error_ = NULL;
Array* Object::vm_isolate_snapshot_object_table_ = NULL;
+const uint8_t* Object::instructions_snapshot_buffer_ = NULL;
RawObject* Object::null_ = reinterpret_cast<RawObject*>(RAW_NULL);
RawClass* Object::class_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
@@ -2103,7 +2104,7 @@
ASSERT(!value.IsNull());
StorePointer(&raw_ptr()->functions_, value.raw());
const intptr_t len = value.Length();
- ClassFunctionsSet set(HashTables::New<ClassFunctionsSet>(len));
+ ClassFunctionsSet set(HashTables::New<ClassFunctionsSet>(len, Heap::kOld));
if (len >= kFunctionLookupHashTreshold) {
Function& func = Function::Handle();
for (intptr_t i = 0; i < len; ++i) {
@@ -4831,7 +4832,8 @@
RawTypeArguments* TypeArguments::InstantiateFrom(
const TypeArguments& instantiator_type_arguments,
Error* bound_error,
- TrailPtr trail) const {
+ TrailPtr trail,
+ Heap::Space space) const {
ASSERT(!IsInstantiated());
if (!instantiator_type_arguments.IsNull() &&
IsUninstantiatedIdentity() &&
@@ -4840,7 +4842,7 @@
}
const intptr_t num_types = Length();
TypeArguments& instantiated_array =
- TypeArguments::Handle(TypeArguments::New(num_types, Heap::kNew));
+ TypeArguments::Handle(TypeArguments::New(num_types, space));
AbstractType& type = AbstractType::Handle();
for (intptr_t i = 0; i < num_types; i++) {
type = TypeAt(i);
@@ -4853,7 +4855,8 @@
if (!type.IsNull() && !type.IsInstantiated()) {
type = type.InstantiateFrom(instantiator_type_arguments,
bound_error,
- trail);
+ trail,
+ space);
}
instantiated_array.SetTypeAt(i, type);
}
@@ -9027,7 +9030,8 @@
if (LoadError() != Instance::null()) {
return LoadError();
}
- Isolate* isolate = Isolate::Current();
+ Thread* thread = Thread::Current();
+ Isolate* isolate = thread->isolate();
ObjectStore* object_store = isolate->object_store();
LibraryLoadErrorSet set(object_store->library_load_error_table());
bool present = false;
@@ -9042,7 +9046,7 @@
Library& lib = Library::Handle(isolate);
Instance& error = Instance::Handle(isolate);
for (intptr_t i = 0; i < num_imp; i++) {
- HANDLESCOPE(isolate);
+ HANDLESCOPE(thread);
lib = ImportLibraryAt(i);
error = lib.TransitiveLoadError();
if (!error.IsNull()) {
@@ -10312,7 +10316,8 @@
RawInstance* LibraryPrefix::LoadError() const {
- Isolate* isolate = Isolate::Current();
+ Thread* thread = Thread::Current();
+ Isolate* isolate = thread->isolate();
ObjectStore* object_store = isolate->object_store();
GrowableObjectArray& libs =
GrowableObjectArray::Handle(isolate, object_store->libraries());
@@ -10324,7 +10329,7 @@
for (int32_t i = 0; i < num_imports(); i++) {
lib = GetLibrary(i);
ASSERT(!lib.IsNull());
- HANDLESCOPE(isolate);
+ HANDLESCOPE(thread);
error = lib.TransitiveLoadError();
if (!error.IsNull()) {
break;
@@ -10980,7 +10985,8 @@
const char* ObjectPool::ToCString() const {
- return "ObjectPool";
+ Zone* zone = Thread::Current()->zone();
+ return zone->PrintToString("ObjectPool len:%" Pd, Length());
}
@@ -11709,7 +11715,7 @@
const char* ExceptionHandlers::ToCString() const {
if (num_entries() == 0) {
- return "No exception handlers\n";
+ return "empty ExceptionHandlers\n";
}
Array& handled_types = Array::Handle();
Type& type = Type::Handle();
@@ -13784,7 +13790,8 @@
result ^= raw;
}
const intptr_t capacity = kInitialCapacity;
- const Array& buckets = Array::Handle(Array::New(kEntryLength * capacity));
+ const Array& buckets = Array::Handle(
+ Array::New(kEntryLength * capacity, Heap::kOld));
ASSERT(Isolate::Current()->megamorphic_cache_table()->miss_handler() != NULL);
const Function& handler = Function::Handle(
Isolate::Current()->megamorphic_cache_table()->miss_handler());
@@ -14188,7 +14195,7 @@
const char* UnhandledException::ToErrorCString() const {
Thread* thread = Thread::Current();
Isolate* isolate = thread->isolate();
- HANDLESCOPE(isolate);
+ HANDLESCOPE(thread);
Object& strtmp = Object::Handle();
const char* exc_str;
if (exception() == isolate->object_store()->out_of_memory()) {
@@ -14921,7 +14928,8 @@
RawAbstractType* AbstractType::InstantiateFrom(
const TypeArguments& instantiator_type_arguments,
Error* bound_error,
- TrailPtr trail) const {
+ TrailPtr trail,
+ Heap::Space space) const {
// AbstractType is an abstract class.
UNREACHABLE();
return NULL;
@@ -15522,7 +15530,9 @@
RawAbstractType* Type::InstantiateFrom(
const TypeArguments& instantiator_type_arguments,
Error* bound_error,
- TrailPtr trail) const {
+ TrailPtr trail,
+ Heap::Space space) const {
+ Zone* zone = Thread::Current()->zone();
ASSERT(IsFinalized() || IsBeingFinalized());
ASSERT(!IsInstantiated());
// Return the uninstantiated type unchanged if malformed. No copy needed.
@@ -15535,7 +15545,7 @@
return raw();
}
// If this type is recursive, we may already be instantiating it.
- Type& instantiated_type = Type::Handle();
+ Type& instantiated_type = Type::Handle(zone);
instantiated_type ^= OnlyBuddyInTrail(trail);
if (!instantiated_type.IsNull()) {
ASSERT(IsRecursive());
@@ -15544,19 +15554,20 @@
// Note that the type class has to be resolved at this time, but not
// necessarily finalized yet. We may be checking bounds at compile time or
// finalizing the type argument vector of a recursive type.
- const Class& cls = Class::Handle(type_class());
+ const Class& cls = Class::Handle(zone, type_class());
// This uninstantiated type is not modified, as it can be instantiated
// with different instantiators. Allocate a new instantiated version of it.
- instantiated_type = Type::New(cls, TypeArguments::Handle(), token_pos());
- TypeArguments& type_arguments = TypeArguments::Handle(arguments());
+ instantiated_type = Type::New(cls, TypeArguments::Handle(zone), token_pos());
+ TypeArguments& type_arguments = TypeArguments::Handle(zone, arguments());
ASSERT(type_arguments.Length() == cls.NumTypeArguments());
if (type_arguments.IsRecursive()) {
AddOnlyBuddyToTrail(&trail, instantiated_type);
}
type_arguments = type_arguments.InstantiateFrom(instantiator_type_arguments,
bound_error,
- trail);
+ trail,
+ space);
instantiated_type.set_arguments(type_arguments);
if (IsFinalized()) {
instantiated_type.SetIsFinalized();
@@ -15963,7 +15974,8 @@
RawTypeRef* TypeRef::InstantiateFrom(
const TypeArguments& instantiator_type_arguments,
Error* bound_error,
- TrailPtr trail) const {
+ TrailPtr trail,
+ Heap::Space space) const {
TypeRef& instantiated_type_ref = TypeRef::Handle();
instantiated_type_ref ^= OnlyBuddyInTrail(trail);
if (!instantiated_type_ref.IsNull()) {
@@ -15973,7 +15985,7 @@
ASSERT(!ref_type.IsTypeRef());
AbstractType& instantiated_ref_type = AbstractType::Handle();
instantiated_ref_type = ref_type.InstantiateFrom(
- instantiator_type_arguments, bound_error, trail);
+ instantiator_type_arguments, bound_error, trail, space);
ASSERT(!instantiated_ref_type.IsTypeRef());
instantiated_type_ref = TypeRef::New(instantiated_ref_type);
AddOnlyBuddyToTrail(&trail, instantiated_type_ref);
@@ -16177,7 +16189,8 @@
RawAbstractType* TypeParameter::InstantiateFrom(
const TypeArguments& instantiator_type_arguments,
Error* bound_error,
- TrailPtr trail) const {
+ TrailPtr trail,
+ Heap::Space space) const {
ASSERT(IsFinalized());
if (instantiator_type_arguments.IsNull()) {
return Type::DynamicType();
@@ -16440,14 +16453,16 @@
RawAbstractType* BoundedType::InstantiateFrom(
const TypeArguments& instantiator_type_arguments,
Error* bound_error,
- TrailPtr trail) const {
+ TrailPtr trail,
+ Heap::Space space) const {
ASSERT(IsFinalized());
AbstractType& bounded_type = AbstractType::Handle(type());
ASSERT(bounded_type.IsFinalized());
if (!bounded_type.IsInstantiated()) {
bounded_type = bounded_type.InstantiateFrom(instantiator_type_arguments,
bound_error,
- trail);
+ trail,
+ space);
// In case types of instantiator_type_arguments are not finalized, then
// the instantiated bounded_type is not finalized either.
// Note that instantiator_type_arguments must have the final length, though.
@@ -16461,7 +16476,8 @@
if (!upper_bound.IsInstantiated()) {
upper_bound = upper_bound.InstantiateFrom(instantiator_type_arguments,
bound_error,
- trail);
+ trail,
+ space);
// Instantiated upper_bound may not be finalized. See comment above.
}
if (bound_error->IsNull()) {
@@ -16852,7 +16868,8 @@
RawInteger* Integer::ArithmeticOp(Token::Kind operation,
- const Integer& other) const {
+ const Integer& other,
+ Heap::Space space) const {
// In 32-bit mode, the result of any operation between two Smis will fit in a
// 32-bit signed result, except the product of two Smis, which will be 64-bit.
// In 64-bit mode, the result of any operation between two Smis will fit in a
@@ -16862,14 +16879,15 @@
const intptr_t right_value = Smi::Value(Smi::RawCast(other.raw()));
switch (operation) {
case Token::kADD:
- return Integer::New(left_value + right_value);
+ return Integer::New(left_value + right_value, space);
case Token::kSUB:
- return Integer::New(left_value - right_value);
+ return Integer::New(left_value - right_value, space);
case Token::kMUL: {
if (Smi::kBits < 32) {
// In 32-bit mode, the product of two Smis fits in a 64-bit result.
return Integer::New(static_cast<int64_t>(left_value) *
- static_cast<int64_t>(right_value));
+ static_cast<int64_t>(right_value),
+ space);
} else {
// In 64-bit mode, the product of two signed integers fits in a
// 64-bit result if the sum of the highest bits of their absolute
@@ -16877,24 +16895,24 @@
ASSERT(sizeof(intptr_t) == sizeof(int64_t));
if ((Utils::HighestBit(left_value) +
Utils::HighestBit(right_value)) < 62) {
- return Integer::New(left_value * right_value);
+ return Integer::New(left_value * right_value, space);
}
}
// Perform a Bigint multiplication below.
break;
}
case Token::kTRUNCDIV:
- return Integer::New(left_value / right_value);
+ return Integer::New(left_value / right_value, space);
case Token::kMOD: {
const intptr_t remainder = left_value % right_value;
if (remainder < 0) {
if (right_value < 0) {
- return Integer::New(remainder - right_value);
+ return Integer::New(remainder - right_value, space);
} else {
- return Integer::New(remainder + right_value);
+ return Integer::New(remainder + right_value, space);
}
}
- return Integer::New(remainder);
+ return Integer::New(remainder, space);
}
default:
UNIMPLEMENTED();
@@ -16907,27 +16925,27 @@
case Token::kADD: {
if (((left_value < 0) != (right_value < 0)) ||
((left_value + right_value) < 0) == (left_value < 0)) {
- return Integer::New(left_value + right_value);
+ return Integer::New(left_value + right_value, space);
}
break;
}
case Token::kSUB: {
if (((left_value < 0) == (right_value < 0)) ||
((left_value - right_value) < 0) == (left_value < 0)) {
- return Integer::New(left_value - right_value);
+ return Integer::New(left_value - right_value, space);
}
break;
}
case Token::kMUL: {
if ((Utils::HighestBit(left_value) +
Utils::HighestBit(right_value)) < 62) {
- return Integer::New(left_value * right_value);
+ return Integer::New(left_value * right_value, space);
}
break;
}
case Token::kTRUNCDIV: {
if ((left_value != Mint::kMinValue) || (right_value != -1)) {
- return Integer::New(left_value / right_value);
+ return Integer::New(left_value / right_value, space);
}
break;
}
@@ -16935,12 +16953,12 @@
const int64_t remainder = left_value % right_value;
if (remainder < 0) {
if (right_value < 0) {
- return Integer::New(remainder - right_value);
+ return Integer::New(remainder - right_value, space);
} else {
- return Integer::New(remainder + right_value);
+ return Integer::New(remainder + right_value, space);
}
}
- return Integer::New(remainder);
+ return Integer::New(remainder, space);
}
default:
UNIMPLEMENTED();
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index a271d16..369f87a 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -488,6 +488,12 @@
return *vm_isolate_snapshot_object_table_;
}
static void InitVmIsolateSnapshotObjectTable(intptr_t len);
+ static const uint8_t* instructions_snapshot_buffer() {
+ return instructions_snapshot_buffer_;
+ }
+ static void set_instructions_snapshot_buffer(const uint8_t* buffer) {
+ instructions_snapshot_buffer_ = buffer;
+ }
static RawClass* class_class() { return class_class_; }
static RawClass* dynamic_class() { return dynamic_class_; }
@@ -813,6 +819,7 @@
static LanguageError* snapshot_writer_error_;
static LanguageError* branch_offset_error_;
static Array* vm_isolate_snapshot_object_table_;
+ static const uint8_t* instructions_snapshot_buffer_;
friend void ClassTable::Register(const Class& cls);
friend void RawObject::Validate(Isolate* isolate) const;
@@ -1650,7 +1657,8 @@
RawTypeArguments* InstantiateFrom(
const TypeArguments& instantiator_type_arguments,
Error* bound_error,
- TrailPtr trail = NULL) const;
+ TrailPtr trail = NULL,
+ Heap::Space space = Heap::kNew) const;
// Runtime instantiation with canonicalization. Not to be used during type
// finalization at compile time.
@@ -5006,7 +5014,8 @@
virtual RawAbstractType* InstantiateFrom(
const TypeArguments& instantiator_type_arguments,
Error* bound_error,
- TrailPtr trail = NULL) const;
+ TrailPtr trail = NULL,
+ Heap::Space space = Heap::kNew) const;
// Return a clone of this unfinalized type or the type itself if it is
// already finalized. Apply recursively to type arguments, i.e. finalized
@@ -5179,7 +5188,8 @@
virtual RawAbstractType* InstantiateFrom(
const TypeArguments& instantiator_type_arguments,
Error* malformed_error,
- TrailPtr trail = NULL) const;
+ TrailPtr trail = NULL,
+ Heap::Space space = Heap::kNew) const;
virtual RawAbstractType* CloneUnfinalized() const;
virtual RawAbstractType* CloneUninstantiated(
const Class& new_owner,
@@ -5300,7 +5310,8 @@
virtual RawTypeRef* InstantiateFrom(
const TypeArguments& instantiator_type_arguments,
Error* bound_error,
- TrailPtr trail = NULL) const;
+ TrailPtr trail = NULL,
+ Heap::Space space = Heap::kNew) const;
virtual RawTypeRef* CloneUninstantiated(
const Class& new_owner,
TrailPtr trail = NULL) const;
@@ -5380,7 +5391,8 @@
virtual RawAbstractType* InstantiateFrom(
const TypeArguments& instantiator_type_arguments,
Error* bound_error,
- TrailPtr trail = NULL) const;
+ TrailPtr trail = NULL,
+ Heap::Space space = Heap::kNew) const;
virtual RawAbstractType* CloneUnfinalized() const;
virtual RawAbstractType* CloneUninstantiated(
const Class& new_owner, TrailPtr trail = NULL) const;
@@ -5464,7 +5476,8 @@
virtual RawAbstractType* InstantiateFrom(
const TypeArguments& instantiator_type_arguments,
Error* bound_error,
- TrailPtr trail = NULL) const;
+ TrailPtr trail = NULL,
+ Heap::Space space = Heap::kNew) const;
virtual RawAbstractType* CloneUnfinalized() const;
virtual RawAbstractType* CloneUninstantiated(
const Class& new_owner, TrailPtr trail = NULL) const;
@@ -5600,7 +5613,9 @@
RawInteger* AsValidInteger() const;
// Returns null to indicate that a bigint operation is required.
- RawInteger* ArithmeticOp(Token::Kind operation, const Integer& other) const;
+ RawInteger* ArithmeticOp(Token::Kind operation,
+ const Integer& other,
+ Heap::Space space = Heap::kNew) const;
RawInteger* BitOp(Token::Kind operation, const Integer& other) const;
// Returns true if the Integer does not fit in a Javascript integer.
@@ -6316,6 +6331,7 @@
friend class Class;
friend class String;
+ friend class Symbols;
friend class ExternalOneByteString;
friend class SnapshotReader;
friend class StringHasher;
@@ -6431,6 +6447,7 @@
friend class Class;
friend class String;
friend class SnapshotReader;
+ friend class Symbols;
};
@@ -6513,6 +6530,7 @@
friend class Class;
friend class String;
friend class SnapshotReader;
+ friend class Symbols;
};
@@ -6591,6 +6609,7 @@
friend class Class;
friend class String;
friend class SnapshotReader;
+ friend class Symbols;
};
diff --git a/runtime/vm/object_graph.cc b/runtime/vm/object_graph.cc
index ad6f861..b32fa20 100644
--- a/runtime/vm/object_graph.cc
+++ b/runtime/vm/object_graph.cc
@@ -255,7 +255,7 @@
public:
// We cannot use a GrowableObjectArray, since we must not trigger GC.
RetainingPathVisitor(RawObject* obj, const Array& path)
- : obj_(obj), path_(path), length_(0) {
+ : thread_(Thread::Current()), obj_(obj), path_(path), length_(0) {
ASSERT(Thread::Current()->no_safepoint_scope_depth() != 0);
}
@@ -281,7 +281,7 @@
return kProceed;
}
} else {
- HANDLESCOPE(Isolate::Current());
+ HANDLESCOPE(thread_);
Object& current = Object::Handle();
Smi& offset_from_parent = Smi::Handle();
do {
@@ -300,6 +300,7 @@
}
private:
+ Thread* thread_;
RawObject* obj_;
const Array& path_;
intptr_t length_;
diff --git a/runtime/vm/object_graph_test.cc b/runtime/vm/object_graph_test.cc
index 00f7768..3e0259a 100644
--- a/runtime/vm/object_graph_test.cc
+++ b/runtime/vm/object_graph_test.cc
@@ -39,7 +39,7 @@
TEST_CASE(ObjectGraph) {
- Isolate* isolate = Isolate::Current();
+ Isolate* isolate = thread->isolate();
// Create a simple object graph with objects a, b, c, d:
// a+->b+->c
// + +
@@ -99,7 +99,7 @@
ObjectGraph graph(isolate);
// A retaining path should end like this: c <- b <- a <- ...
{
- HANDLESCOPE(isolate);
+ HANDLESCOPE(thread);
// Test null, empty, and length 1 array.
intptr_t null_length = graph.RetainingPath(&c, Object::null_array());
intptr_t empty_length = graph.RetainingPath(&c, Object::empty_array());
@@ -110,7 +110,7 @@
EXPECT_LE(3, null_length);
}
{
- HANDLESCOPE(isolate);
+ HANDLESCOPE(thread);
Array& path = Array::Handle(Array::New(6, Heap::kNew));
// Trigger a full GC to increase probability of concurrent tasks.
isolate->heap()->CollectAllGarbage();
diff --git a/runtime/vm/object_test.cc b/runtime/vm/object_test.cc
index a344bb2..5e006a0 100644
--- a/runtime/vm/object_test.cc
+++ b/runtime/vm/object_test.cc
@@ -3333,7 +3333,7 @@
WeakProperty& weak = WeakProperty::Handle();
{
// Weak property and value in new. Key in old.
- HANDLESCOPE(isolate);
+ HANDLESCOPE(thread);
String& key = String::Handle();
key ^= OneByteString::New("key", Heap::kOld);
String& value = String::Handle();
@@ -3351,7 +3351,7 @@
EXPECT(weak.value() != Object::null());
{
// Weak property and value in old. Key in new.
- HANDLESCOPE(isolate);
+ HANDLESCOPE(thread);
String& key = String::Handle();
key ^= OneByteString::New("key", Heap::kNew);
String& value = String::Handle();
@@ -3369,7 +3369,7 @@
EXPECT(weak.value() != Object::null());
{
// Weak property and value in new. Key is a Smi.
- HANDLESCOPE(isolate);
+ HANDLESCOPE(thread);
Integer& key = Integer::Handle();
key ^= Integer::New(31);
String& value = String::Handle();
@@ -3387,7 +3387,7 @@
EXPECT(weak.value() != Object::null());
{
// Weak property and value in old. Key is a Smi.
- HANDLESCOPE(isolate);
+ HANDLESCOPE(thread);
Integer& key = Integer::Handle();
key ^= Integer::New(32);
String& value = String::Handle();
@@ -3405,7 +3405,7 @@
EXPECT(weak.value() != Object::null());
{
// Weak property and value in new. Key in VM isolate.
- HANDLESCOPE(isolate);
+ HANDLESCOPE(thread);
String& value = String::Handle();
value ^= OneByteString::New("value", Heap::kNew);
weak ^= WeakProperty::New(Heap::kNew);
@@ -3422,7 +3422,7 @@
EXPECT(weak.value() != Object::null());
{
// Weak property and value in old. Key in VM isolate.
- HANDLESCOPE(isolate);
+ HANDLESCOPE(thread);
String& value = String::Handle();
value ^= OneByteString::New("value", Heap::kOld);
weak ^= WeakProperty::New(Heap::kOld);
@@ -3447,7 +3447,7 @@
WeakProperty& weak = WeakProperty::Handle();
Array& arr = Array::Handle(Array::New(1));
{
- HANDLESCOPE(isolate);
+ HANDLESCOPE(thread);
String& key = String::Handle();
key ^= OneByteString::New("key");
arr.SetAt(0, key);
@@ -3469,7 +3469,7 @@
String& key = String::Handle();
key ^= OneByteString::New("key");
{
- HANDLESCOPE(isolate);
+ HANDLESCOPE(thread);
String& value = String::Handle();
value ^= OneByteString::New("value");
weak ^= WeakProperty::New();
@@ -3491,7 +3491,7 @@
String& key2 = String::Handle();
key2 ^= OneByteString::New("key2");
{
- HANDLESCOPE(isolate);
+ HANDLESCOPE(thread);
String& value1 = String::Handle();
value1 ^= OneByteString::New("value1");
weak1 ^= WeakProperty::New();
@@ -3518,7 +3518,7 @@
String& key = String::Handle();
key ^= OneByteString::New("key");
{
- HANDLESCOPE(isolate);
+ HANDLESCOPE(thread);
String& value1 = String::Handle();
value1 ^= OneByteString::New("value1");
weak1 ^= WeakProperty::New();
@@ -3544,7 +3544,7 @@
String& key = String::Handle();
key ^= OneByteString::New("key", Heap::kOld);
{
- HANDLESCOPE(isolate);
+ HANDLESCOPE(thread);
String& value = String::Handle();
value ^= OneByteString::New("value", Heap::kOld);
weak ^= WeakProperty::New(Heap::kOld);
@@ -3566,7 +3566,7 @@
String& key2 = String::Handle();
key2 ^= OneByteString::New("key2", Heap::kOld);
{
- HANDLESCOPE(isolate);
+ HANDLESCOPE(thread);
String& value1 = String::Handle();
value1 ^= OneByteString::New("value1", Heap::kOld);
weak1 ^= WeakProperty::New(Heap::kOld);
@@ -3593,7 +3593,7 @@
String& key = String::Handle();
key ^= OneByteString::New("key", Heap::kOld);
{
- HANDLESCOPE(isolate);
+ HANDLESCOPE(thread);
String& value1 = String::Handle();
value1 ^= OneByteString::New("value1", Heap::kOld);
weak1 ^= WeakProperty::New(Heap::kOld);
@@ -3617,7 +3617,7 @@
Isolate* isolate = Isolate::Current();
WeakProperty& weak = WeakProperty::Handle();
{
- HANDLESCOPE(isolate);
+ HANDLESCOPE(thread);
String& key = String::Handle();
key ^= OneByteString::New("key");
String& value = String::Handle();
@@ -3639,7 +3639,7 @@
WeakProperty& weak1 = WeakProperty::Handle();
WeakProperty& weak2 = WeakProperty::Handle();
{
- HANDLESCOPE(isolate);
+ HANDLESCOPE(thread);
String& key = String::Handle();
key ^= OneByteString::New("key");
String& value1 = String::Handle();
@@ -3665,7 +3665,7 @@
Isolate* isolate = Isolate::Current();
WeakProperty& weak = WeakProperty::Handle();
{
- HANDLESCOPE(isolate);
+ HANDLESCOPE(thread);
String& key = String::Handle();
key ^= OneByteString::New("key", Heap::kOld);
String& value = String::Handle();
@@ -3687,7 +3687,7 @@
WeakProperty& weak1 = WeakProperty::Handle();
WeakProperty& weak2 = WeakProperty::Handle();
{
- HANDLESCOPE(isolate);
+ HANDLESCOPE(thread);
String& key = String::Handle();
key ^= OneByteString::New("key", Heap::kOld);
String& value1 = String::Handle();
@@ -4709,4 +4709,76 @@
EXPECT(!iterator.MoveNext());
}
+
+static void CheckConcatAll(const String* data[], intptr_t n) {
+ Zone* zone = Thread::Current()->zone();
+ GrowableHandlePtrArray<const String> pieces(zone, n);
+ const Array& array = Array::Handle(zone, Array::New(n));
+ for (int i = 0; i < n; i++) {
+ pieces.Add(*data[i]);
+ array.SetAt(i, *data[i]);
+ }
+ const String& res1 = String::Handle(zone, Symbols::FromConcatAll(pieces));
+ const String& res2 = String::Handle(zone, String::ConcatAll(array));
+ EXPECT(res1.Equals(res2));
+}
+
+
+TEST_CASE(Symbols_FromConcatAll) {
+ {
+ const String* data[3] = { &Symbols::FallThroughError(),
+ &Symbols::Dot(),
+ &Symbols::isPaused() };
+ CheckConcatAll(data, 3);
+ }
+
+ {
+ const intptr_t kWideCharsLen = 7;
+ uint16_t wide_chars[kWideCharsLen] = { 'H', 'e', 'l', 'l', 'o', 256, '!' };
+ const String& two_str = String::Handle(String::FromUTF16(wide_chars,
+ kWideCharsLen));
+
+ const String* data[3] = { &two_str, &Symbols::Dot(), &two_str };
+ CheckConcatAll(data, 3);
+ }
+
+ {
+ uint8_t characters[] = { 0xF6, 0xF1, 0xE9 };
+ intptr_t len = ARRAY_SIZE(characters);
+
+ const String& str = String::Handle(
+ ExternalOneByteString::New(characters, len, NULL, NULL, Heap::kNew));
+ const String* data[3] = { &str, &Symbols::Dot(), &str };
+ CheckConcatAll(data, 3);
+ }
+
+ {
+ uint16_t characters[] =
+ { 'a', '\n', '\f', '\b', '\t', '\v', '\r', '\\', '$', 'z' };
+ intptr_t len = ARRAY_SIZE(characters);
+
+ const String& str = String::Handle(
+ ExternalTwoByteString::New(characters, len, NULL, NULL, Heap::kNew));
+ const String* data[3] = { &str, &Symbols::Dot(), &str };
+ CheckConcatAll(data, 3);
+ }
+
+ {
+ uint8_t characters1[] = { 0xF6, 0xF1, 0xE9 };
+ intptr_t len1 = ARRAY_SIZE(characters1);
+
+ const String& str1 = String::Handle(
+ ExternalOneByteString::New(characters1, len1, NULL, NULL, Heap::kNew));
+
+ uint16_t characters2[] =
+ { 'a', '\n', '\f', '\b', '\t', '\v', '\r', '\\', '$', 'z' };
+ intptr_t len2 = ARRAY_SIZE(characters2);
+
+ const String& str2 = String::Handle(
+ ExternalTwoByteString::New(characters2, len2, NULL, NULL, Heap::kNew));
+ const String* data[3] = { &str1, &Symbols::Dot(), &str2 };
+ CheckConcatAll(data, 3);
+ }
+}
+
} // namespace dart
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc
index f7e3a27..604e453 100644
--- a/runtime/vm/parser.cc
+++ b/runtime/vm/parser.cc
@@ -2397,8 +2397,9 @@
if (ctor_name.Length() > class_name.Length() + 1) {
// Generating a forwarding call to a named constructor 'C.n'.
// Add the constructor name 'n' to the super constructor.
- ctor_name = String::SubString(ctor_name, class_name.Length() + 1);
- super_ctor_name = String::Concat(super_ctor_name, ctor_name);
+ const intptr_t kLen = class_name.Length() + 1;
+ ctor_name = Symbols::New(ctor_name, kLen, ctor_name.Length() - kLen);
+ super_ctor_name = Symbols::FromConcat(super_ctor_name, ctor_name);
}
}
@@ -2790,13 +2791,14 @@
const intptr_t call_pos = TokenPos();
ConsumeToken();
String& ctor_name = String::Handle(Z, cls.Name());
-
- ctor_name = String::Concat(ctor_name, Symbols::Dot());
+ GrowableHandlePtrArray<const String> pieces(Z, 3);
+ pieces.Add(ctor_name);
+ pieces.Add(Symbols::Dot());
if (CurrentToken() == Token::kPERIOD) {
ConsumeToken();
- ctor_name = String::Concat(ctor_name,
- *ExpectIdentifier("constructor name expected"));
+ pieces.Add(*ExpectIdentifier("constructor name expected"));
}
+ ctor_name = Symbols::FromConcatAll(pieces);
CheckToken(Token::kLPAREN, "parameter list expected");
ArgumentListNode* arguments = new ArgumentListNode(call_pos);
@@ -3489,7 +3491,7 @@
body = CloseSyncGenFunction(generated_body_closure, body);
generated_body_closure.set_end_token_pos(end_token_pos);
} else if (func.IsSyncGenClosure()) {
- body->scope()->RecursivelyCaptureAllVariables();
+ // body is unchanged.
} else if (func.IsAsyncGenerator()) {
body = CloseAsyncGeneratorFunction(generated_body_closure, body);
generated_body_closure.set_end_token_pos(end_token_pos);
@@ -3690,7 +3692,7 @@
ASSERT(method->IsSetter());
expected_num_parameters = (method->has_static) ? 1 : 2;
method->dict_name = &String::ZoneHandle(Z,
- String::Concat(*method->name, Symbols::Equals()));
+ Symbols::FromConcat(*method->name, Symbols::Equals()));
method->name = &String::ZoneHandle(Z, Field::SetterSymbol(*method->name));
}
if ((method->params.num_fixed_parameters != expected_num_parameters) ||
@@ -6318,8 +6320,8 @@
no_args));
// Suspend after the close.
- AwaitMarkerNode* await_marker = new(Z) AwaitMarkerNode();
- await_marker->set_scope(current_block_->scope);
+ AwaitMarkerNode* await_marker =
+ new(Z) AwaitMarkerNode(async_temp_scope_, current_block_->scope);
current_block_->statements->Add(await_marker);
ReturnNode* continuation_ret = new(Z) ReturnNode(try_end_pos);
continuation_ret->set_return_type(ReturnNode::kContinuationTarget);
@@ -6608,6 +6610,8 @@
SequenceNode* Parser::CloseSyncGenFunction(const Function& closure,
SequenceNode* closure_body) {
+ // Explicitly reference variables of the sync generator function from the
+ // closure body in order to mark them as captured.
LocalVariable* existing_var =
closure_body->scope()->LookupVariable(Symbols::AwaitJumpVar(), false);
ASSERT((existing_var != NULL) && existing_var->is_captured());
@@ -6753,11 +6757,9 @@
LocalVariable* await_jump_var = new (Z) LocalVariable(
Scanner::kNoSourcePos, Symbols::AwaitJumpVar(), dynamic_type);
current_block_->scope->AddVariable(await_jump_var);
- current_block_->scope->CaptureVariable(await_jump_var);
LocalVariable* await_ctx_var = new (Z) LocalVariable(
Scanner::kNoSourcePos, Symbols::AwaitContextVar(), dynamic_type);
current_block_->scope->AddVariable(await_ctx_var);
- current_block_->scope->CaptureVariable(await_ctx_var);
}
@@ -6771,19 +6773,15 @@
LocalVariable* async_op_var = new(Z) LocalVariable(
Scanner::kNoSourcePos, Symbols::AsyncOperation(), dynamic_type);
current_block_->scope->AddVariable(async_op_var);
- current_block_->scope->CaptureVariable(async_op_var);
LocalVariable* async_then_callback_var = new(Z) LocalVariable(
Scanner::kNoSourcePos, Symbols::AsyncThenCallback(), dynamic_type);
current_block_->scope->AddVariable(async_then_callback_var);
- current_block_->scope->CaptureVariable(async_then_callback_var);
LocalVariable* async_catch_error_callback_var = new(Z) LocalVariable(
Scanner::kNoSourcePos, Symbols::AsyncCatchErrorCallback(), dynamic_type);
current_block_->scope->AddVariable(async_catch_error_callback_var);
- current_block_->scope->CaptureVariable(async_catch_error_callback_var);
LocalVariable* async_completer = new(Z) LocalVariable(
Scanner::kNoSourcePos, Symbols::AsyncCompleter(), dynamic_type);
current_block_->scope->AddVariable(async_completer);
- current_block_->scope->CaptureVariable(async_completer);
}
@@ -6802,19 +6800,15 @@
LocalVariable* controller_var = new(Z) LocalVariable(
Scanner::kNoSourcePos, Symbols::Controller(), dynamic_type);
current_block_->scope->AddVariable(controller_var);
- current_block_->scope->CaptureVariable(controller_var);
LocalVariable* async_op_var = new(Z) LocalVariable(
Scanner::kNoSourcePos, Symbols::AsyncOperation(), dynamic_type);
current_block_->scope->AddVariable(async_op_var);
- current_block_->scope->CaptureVariable(async_op_var);
LocalVariable* async_then_callback_var = new(Z) LocalVariable(
Scanner::kNoSourcePos, Symbols::AsyncThenCallback(), dynamic_type);
current_block_->scope->AddVariable(async_then_callback_var);
- current_block_->scope->CaptureVariable(async_then_callback_var);
LocalVariable* async_catch_error_callback_var = new(Z) LocalVariable(
Scanner::kNoSourcePos, Symbols::AsyncCatchErrorCallback(), dynamic_type);
current_block_->scope->AddVariable(async_catch_error_callback_var);
- current_block_->scope->CaptureVariable(async_catch_error_callback_var);
}
@@ -6906,8 +6900,8 @@
ASSERT(!closure_func.IsNull());
ASSERT(closure_body != NULL);
- // Make sure the implicit variables of the async generator function
- // are captured.
+ // Explicitly reference variables of the async genenerator function from the
+ // closure body in order to mark them as captured.
LocalVariable* existing_var = closure_body->scope()->LookupVariable(
Symbols::AwaitJumpVar(), false);
ASSERT((existing_var != NULL) && existing_var->is_captured());
@@ -7045,29 +7039,6 @@
SequenceNode* new_body = CloseAsyncGeneratorTryBlock(body);
ASSERT(new_body != NULL);
ASSERT(new_body->scope() != NULL);
-
- // Implicitly mark those variables below as captured. We currently mark all
- // variables of all scopes as captured, but as soon as we do something
- // smarter we rely on these internal variables to be available.
- LocalVariable* existing_var = new_body->scope()->LookupVariable(
- Symbols::AwaitJumpVar(), false);
- ASSERT((existing_var != NULL) && existing_var->is_captured());
- existing_var = new_body->scope()->LookupVariable(
- Symbols::AwaitContextVar(), false);
- ASSERT((existing_var != NULL) && existing_var->is_captured());
- existing_var = new_body->scope()->LookupVariable(
- Symbols::Controller(), false);
- ASSERT((existing_var != NULL) && existing_var->is_captured());
- existing_var = new_body->scope()->LookupVariable(
- Symbols::AsyncOperationParam(), false);
- ASSERT(existing_var != NULL);
- existing_var = new_body->scope()->LookupVariable(
- Symbols::AsyncOperationErrorParam(), false);
- ASSERT(existing_var != NULL);
- existing_var = new_body->scope()->LookupVariable(
- Symbols::AsyncOperationStackTraceParam(), false);
- ASSERT(existing_var != NULL);
- new_body->scope()->RecursivelyCaptureAllVariables();
return new_body;
}
@@ -7107,6 +7078,8 @@
ASSERT(!closure.IsNull());
ASSERT(closure_body != NULL);
+ // Explicitly reference variables of the async function from the
+ // closure body in order to mark them as captured.
LocalVariable* existing_var =
closure_body->scope()->LookupVariable(Symbols::AwaitJumpVar(), false);
ASSERT((existing_var != NULL) && existing_var->is_captured());
@@ -7250,22 +7223,10 @@
SequenceNode* Parser::CloseAsyncClosure(SequenceNode* body) {
// We need a temporary expression to store intermediate return values.
parsed_function()->EnsureExpressionTemp();
- // Implicitly mark those variables below as captured. We currently mark all
- // variables of all scopes as captured (below), but as soon as we do something
- // smarter we rely on these internal variables to be available.
+
SequenceNode* new_body = CloseAsyncTryBlock(body);
ASSERT(new_body != NULL);
ASSERT(new_body->scope() != NULL);
- LocalVariable* existing_var =
- new_body->scope()->LookupVariable(Symbols::AwaitJumpVar(), false);
- ASSERT((existing_var != NULL) && existing_var->is_captured());
- existing_var =
- new_body->scope()->LookupVariable(Symbols::AwaitContextVar(), false);
- ASSERT((existing_var != NULL) && existing_var->is_captured());
- existing_var =
- new_body->scope()->LookupVariable(Symbols::AsyncCompleter(), false);
- ASSERT((existing_var != NULL) && existing_var->is_captured());
- new_body->scope()->RecursivelyCaptureAllVariables();
return new_body;
}
@@ -8542,7 +8503,7 @@
Symbols::AsyncSavedTryCtxVarPrefix().ToCString(),
try_index))));
LocalVariable* var = scope->LocalLookupVariable(async_saved_try_ctx_name);
- ASSERT((var != NULL) && var->is_captured());
+ ASSERT(var != NULL);
return var;
}
@@ -8734,14 +8695,15 @@
new(Z) LoadLocalNode(stream_pos, iterator_var),
Symbols::MoveNext(),
no_args);
+ OpenBlock();
AstNode* await_moveNext =
new(Z) AwaitNode(stream_pos,
iterator_moveNext,
saved_try_ctx,
async_saved_try_ctx,
outer_saved_try_ctx,
- outer_async_saved_try_ctx);
- OpenBlock();
+ outer_async_saved_try_ctx,
+ current_block_->scope);
AwaitTransformer at(current_block_->statements, async_temp_scope_);
await_moveNext = at.Transform(await_moveNext);
SequenceNode* await_preamble = CloseBlock();
@@ -9573,7 +9535,6 @@
Type::ZoneHandle(Z, Type::DynamicType()));
ASSERT(async_temp_scope_ != NULL);
async_temp_scope_->AddVariable(async_saved_try_ctx);
- current_block_->scope->CaptureVariable(async_saved_try_ctx);
ASSERT(saved_try_context != NULL);
current_block_->statements->Add(new(Z) StoreLocalNode(
Scanner::kNoSourcePos,
@@ -9907,8 +9868,8 @@
new(Z) LiteralNode(TokenPos(), Bool::True()));
yield->AddNode(set_is_yield_each);
}
- AwaitMarkerNode* await_marker = new(Z) AwaitMarkerNode();
- await_marker->set_scope(current_block_->scope);
+ AwaitMarkerNode* await_marker =
+ new(Z) AwaitMarkerNode(async_temp_scope_, current_block_->scope);
yield->AddNode(await_marker);
// Return true to indicate that a value has been generated.
ReturnNode* return_true = new(Z) ReturnNode(yield_pos,
@@ -9975,8 +9936,8 @@
new(Z) IfNode(Scanner::kNoSourcePos, add_call, true_branch, NULL);
yield->AddNode(if_is_cancelled);
- AwaitMarkerNode* await_marker = new(Z) AwaitMarkerNode();
- await_marker->set_scope(current_block_->scope);
+ AwaitMarkerNode* await_marker =
+ new(Z) AwaitMarkerNode(async_temp_scope_, current_block_->scope);
yield->AddNode(await_marker);
ReturnNode* continuation_return = new(Z) ReturnNode(yield_pos);
continuation_return->set_return_type(ReturnNode::kContinuationTarget);
@@ -10633,9 +10594,9 @@
// Evaluates the value of the compile time constant expression
// and returns a literal node for the value.
-AstNode* Parser::FoldConstExpr(intptr_t expr_pos, AstNode* expr) {
+LiteralNode* Parser::FoldConstExpr(intptr_t expr_pos, AstNode* expr) {
if (expr->IsLiteralNode()) {
- return expr;
+ return expr->AsLiteralNode();
}
if (expr->EvalConstExpr() == NULL) {
ReportError(expr_pos, "expression is not a valid compile-time constant");
@@ -10882,13 +10843,27 @@
AstNode* expr = ParseExpr(require_compiletime_const, consume_cascades);
return new(Z) ThrowNode(expr_pos, expr, NULL);
}
+
+ if (require_compiletime_const) {
+ // Check whether we already have evaluated a compile-time constant
+ // at this source location.
+ Instance& existing_const = Instance::ZoneHandle(Z);
+ if (GetCachedConstant(expr_pos, &existing_const)) {
+ SkipConditionalExpr();
+ return new(Z) LiteralNode(expr_pos, existing_const);
+ }
+ }
+
AstNode* expr = ParseConditionalExpr();
if (!Token::IsAssignmentOperator(CurrentToken())) {
if ((CurrentToken() == Token::kCASCADE) && consume_cascades) {
return ParseCascades(expr);
}
if (require_compiletime_const) {
- expr = FoldConstExpr(expr_pos, expr);
+ const bool use_cache = !expr->IsLiteralNode();
+ LiteralNode* const_value = FoldConstExpr(expr_pos, expr);
+ if (use_cache) CacheConstantValue(expr_pos, const_value->literal());
+ expr = const_value;
} else {
expr = LiteralIfStaticConst(Z, expr);
}
@@ -10982,7 +10957,8 @@
saved_try_ctx,
async_saved_try_ctx,
outer_saved_try_ctx,
- outer_async_saved_try_ctx);
+ outer_async_saved_try_ctx,
+ current_block_->scope);
} else if (IsPrefixOperator(CurrentToken())) {
Token::Kind unary_op = CurrentToken();
if (unary_op == Token::kSUB) {
@@ -13670,15 +13646,13 @@
if (has_interpolation) {
primary = new(Z) LiteralNode(literal_start, Interpolate(values_list));
} else {
- const Array& strings = Array::Handle(Z, Array::New(values_list.length()));
+ GrowableHandlePtrArray<const String> pieces(Z, values_list.length());
for (int i = 0; i < values_list.length(); i++) {
const Instance& part = values_list[i]->AsLiteralNode()->literal();
ASSERT(part.IsString());
- strings.SetAt(i, String::Cast(part));
+ pieces.Add(String::Cast(part));
}
- String& lit = String::ZoneHandle(Z,
- String::ConcatAll(strings, Heap::kOld));
- lit = Symbols::New(lit);
+ const String& lit = String::ZoneHandle(Z, Symbols::FromConcatAll(pieces));
primary = new(Z) LiteralNode(literal_start, lit);
}
} else {
diff --git a/runtime/vm/parser.h b/runtime/vm/parser.h
index ece2729..f081a7a 100644
--- a/runtime/vm/parser.h
+++ b/runtime/vm/parser.h
@@ -399,7 +399,7 @@
const TypeArguments& type_arguments,
const Function& constructor,
ArgumentListNode* arguments);
- AstNode* FoldConstExpr(intptr_t expr_pos, AstNode* expr);
+ LiteralNode* FoldConstExpr(intptr_t expr_pos, AstNode* expr);
// Support for parsing of scripts.
void ParseTopLevel();
diff --git a/runtime/vm/profiler_service.cc b/runtime/vm/profiler_service.cc
index 1c2c118..abb5bb0 100644
--- a/runtime/vm/profiler_service.cc
+++ b/runtime/vm/profiler_service.cc
@@ -2194,11 +2194,12 @@
}
-void ProfilerService::PrintJSONImpl(Isolate* isolate,
+void ProfilerService::PrintJSONImpl(Thread* thread,
JSONStream* stream,
Profile::TagOrder tag_order,
intptr_t extra_tags,
SampleFilter* filter) {
+ Isolate* isolate = thread->isolate();
// Disable profile interrupts while processing the buffer.
Profiler::EndExecution(isolate);
@@ -2212,8 +2213,8 @@
}
{
- StackZone zone(isolate);
- HANDLESCOPE(isolate);
+ StackZone zone(thread);
+ HANDLESCOPE(thread);
Profile profile(isolate);
profile.Build(filter, tag_order, extra_tags);
profile.PrintJSON(stream);
@@ -2239,9 +2240,10 @@
void ProfilerService::PrintJSON(JSONStream* stream,
Profile::TagOrder tag_order,
intptr_t extra_tags) {
- Isolate* isolate = Isolate::Current();
+ Thread* thread = Thread::Current();
+ Isolate* isolate = thread->isolate();
NoAllocationSampleFilter filter(isolate);
- PrintJSONImpl(isolate, stream, tag_order, extra_tags, &filter);
+ PrintJSONImpl(thread, stream, tag_order, extra_tags, &filter);
}
@@ -2266,9 +2268,10 @@
void ProfilerService::PrintAllocationJSON(JSONStream* stream,
Profile::TagOrder tag_order,
const Class& cls) {
- Isolate* isolate = Isolate::Current();
+ Thread* thread = Thread::Current();
+ Isolate* isolate = thread->isolate();
ClassAllocationSampleFilter filter(isolate, cls);
- PrintJSONImpl(isolate, stream, tag_order, kNoExtraTags, &filter);
+ PrintJSONImpl(thread, stream, tag_order, kNoExtraTags, &filter);
}
diff --git a/runtime/vm/profiler_service.h b/runtime/vm/profiler_service.h
index 7f0b9a3..621db01 100644
--- a/runtime/vm/profiler_service.h
+++ b/runtime/vm/profiler_service.h
@@ -387,7 +387,7 @@
static void ClearSamples();
private:
- static void PrintJSONImpl(Isolate* isolate,
+ static void PrintJSONImpl(Thread* thread,
JSONStream* stream,
Profile::TagOrder tag_order,
intptr_t extra_tags,
diff --git a/runtime/vm/profiler_test.cc b/runtime/vm/profiler_test.cc
index ac7309b..bc43d5f 100644
--- a/runtime/vm/profiler_test.cc
+++ b/runtime/vm/profiler_test.cc
@@ -566,7 +566,7 @@
EXPECT_VALID(lib);
Library& root_library = Library::Handle();
root_library ^= Api::UnwrapHandle(lib);
- Isolate* isolate = Isolate::Current();
+ Isolate* isolate = thread->isolate();
const Class& double_class =
Class::Handle(isolate->object_store()->double_class());
@@ -578,8 +578,8 @@
EXPECT_VALID(result);
{
- StackZone zone(isolate);
- HANDLESCOPE(isolate);
+ StackZone zone(thread);
+ HANDLESCOPE(thread);
Profile profile(isolate);
AllocationFilter filter(isolate, double_class.id());
profile.Build(&filter, Profile::kNoTags);
@@ -592,8 +592,8 @@
EXPECT_VALID(result);
{
- StackZone zone(isolate);
- HANDLESCOPE(isolate);
+ StackZone zone(thread);
+ HANDLESCOPE(thread);
Profile profile(isolate);
AllocationFilter filter(isolate, double_class.id());
profile.Build(&filter, Profile::kNoTags);
@@ -616,8 +616,8 @@
EXPECT_VALID(result);
{
- StackZone zone(isolate);
- HANDLESCOPE(isolate);
+ StackZone zone(thread);
+ HANDLESCOPE(thread);
Profile profile(isolate);
AllocationFilter filter(isolate, double_class.id());
profile.Build(&filter, Profile::kNoTags);
@@ -636,7 +636,7 @@
EXPECT_VALID(lib);
Library& root_library = Library::Handle();
root_library ^= Api::UnwrapHandle(lib);
- Isolate* isolate = Isolate::Current();
+ Isolate* isolate = thread->isolate();
const Class& array_class =
Class::Handle(isolate->object_store()->array_class());
@@ -646,8 +646,8 @@
EXPECT_VALID(result);
{
- StackZone zone(isolate);
- HANDLESCOPE(isolate);
+ StackZone zone(thread);
+ HANDLESCOPE(thread);
Profile profile(isolate);
AllocationFilter filter(isolate, array_class.id());
profile.Build(&filter, Profile::kNoTags);
@@ -660,8 +660,8 @@
EXPECT_VALID(result);
{
- StackZone zone(isolate);
- HANDLESCOPE(isolate);
+ StackZone zone(thread);
+ HANDLESCOPE(thread);
Profile profile(isolate);
AllocationFilter filter(isolate, array_class.id());
profile.Build(&filter, Profile::kNoTags);
@@ -684,8 +684,8 @@
EXPECT_VALID(result);
{
- StackZone zone(isolate);
- HANDLESCOPE(isolate);
+ StackZone zone(thread);
+ HANDLESCOPE(thread);
Profile profile(isolate);
AllocationFilter filter(isolate, array_class.id());
profile.Build(&filter, Profile::kNoTags);
@@ -708,8 +708,8 @@
EXPECT_VALID(result);
{
- StackZone zone(isolate);
- HANDLESCOPE(isolate);
+ StackZone zone(thread);
+ HANDLESCOPE(thread);
Profile profile(isolate);
AllocationFilter filter(isolate, array_class.id());
profile.Build(&filter, Profile::kNoTags);
@@ -743,7 +743,7 @@
EXPECT_VALID(lib);
Library& root_library = Library::Handle();
root_library ^= Api::UnwrapHandle(lib);
- Isolate* isolate = Isolate::Current();
+ Isolate* isolate = thread->isolate();
const Class& context_class =
Class::Handle(Object::context_class());
@@ -753,8 +753,8 @@
EXPECT_VALID(result);
{
- StackZone zone(isolate);
- HANDLESCOPE(isolate);
+ StackZone zone(thread);
+ HANDLESCOPE(thread);
Profile profile(isolate);
AllocationFilter filter(isolate, context_class.id());
profile.Build(&filter, Profile::kNoTags);
@@ -767,8 +767,8 @@
EXPECT_VALID(result);
{
- StackZone zone(isolate);
- HANDLESCOPE(isolate);
+ StackZone zone(thread);
+ HANDLESCOPE(thread);
Profile profile(isolate);
AllocationFilter filter(isolate, context_class.id());
profile.Build(&filter, Profile::kNoTags);
@@ -787,8 +787,8 @@
EXPECT_VALID(result);
{
- StackZone zone(isolate);
- HANDLESCOPE(isolate);
+ StackZone zone(thread);
+ HANDLESCOPE(thread);
Profile profile(isolate);
AllocationFilter filter(isolate, context_class.id());
profile.Build(&filter, Profile::kNoTags);
@@ -818,7 +818,7 @@
EXPECT_VALID(lib);
Library& root_library = Library::Handle();
root_library ^= Api::UnwrapHandle(lib);
- Isolate* isolate = Isolate::Current();
+ Isolate* isolate = thread->isolate();
const Class& class_class =
Class::Handle(Object::class_class());
@@ -830,8 +830,8 @@
EXPECT_VALID(result);
{
- StackZone zone(isolate);
- HANDLESCOPE(isolate);
+ StackZone zone(thread);
+ HANDLESCOPE(thread);
Profile profile(isolate);
AllocationFilter filter(isolate, class_class.id());
filter.set_enable_embedder_ticks(true);
@@ -859,8 +859,8 @@
EXPECT_VALID(result);
{
- StackZone zone(isolate);
- HANDLESCOPE(isolate);
+ StackZone zone(thread);
+ HANDLESCOPE(thread);
Profile profile(isolate);
AllocationFilter filter(isolate, class_class.id());
filter.set_enable_embedder_ticks(true);
@@ -880,7 +880,7 @@
EXPECT_VALID(lib);
Library& root_library = Library::Handle();
root_library ^= Api::UnwrapHandle(lib);
- Isolate* isolate = Isolate::Current();
+ Isolate* isolate = thread->isolate();
const Library& typed_data_library =
Library::Handle(isolate->object_store()->typed_data_library());
@@ -893,8 +893,8 @@
EXPECT_VALID(result);
{
- StackZone zone(isolate);
- HANDLESCOPE(isolate);
+ StackZone zone(thread);
+ HANDLESCOPE(thread);
Profile profile(isolate);
AllocationFilter filter(isolate, float32_list_class.id());
profile.Build(&filter, Profile::kNoTags);
@@ -907,8 +907,8 @@
EXPECT_VALID(result);
{
- StackZone zone(isolate);
- HANDLESCOPE(isolate);
+ StackZone zone(thread);
+ HANDLESCOPE(thread);
Profile profile(isolate);
AllocationFilter filter(isolate, float32_list_class.id());
profile.Build(&filter, Profile::kNoTags);
@@ -933,8 +933,8 @@
EXPECT_VALID(result);
{
- StackZone zone(isolate);
- HANDLESCOPE(isolate);
+ StackZone zone(thread);
+ HANDLESCOPE(thread);
Profile profile(isolate);
AllocationFilter filter(isolate, float32_list_class.id());
profile.Build(&filter, Profile::kNoTags);
@@ -947,8 +947,8 @@
EXPECT_VALID(result);
{
- StackZone zone(isolate);
- HANDLESCOPE(isolate);
+ StackZone zone(thread);
+ HANDLESCOPE(thread);
Profile profile(isolate);
AllocationFilter filter(isolate, float32_list_class.id());
profile.Build(&filter, Profile::kNoTags);
@@ -965,7 +965,7 @@
EXPECT_VALID(lib);
Library& root_library = Library::Handle();
root_library ^= Api::UnwrapHandle(lib);
- Isolate* isolate = Isolate::Current();
+ Isolate* isolate = thread->isolate();
const Class& one_byte_string_class =
Class::Handle(isolate->object_store()->one_byte_string_class());
@@ -977,8 +977,8 @@
EXPECT_VALID(result);
{
- StackZone zone(isolate);
- HANDLESCOPE(isolate);
+ StackZone zone(thread);
+ HANDLESCOPE(thread);
Profile profile(isolate);
AllocationFilter filter(isolate, one_byte_string_class.id());
profile.Build(&filter, Profile::kNoTags);
@@ -991,8 +991,8 @@
EXPECT_VALID(result);
{
- StackZone zone(isolate);
- HANDLESCOPE(isolate);
+ StackZone zone(thread);
+ HANDLESCOPE(thread);
Profile profile(isolate);
AllocationFilter filter(isolate, one_byte_string_class.id());
profile.Build(&filter, Profile::kNoTags);
@@ -1013,8 +1013,8 @@
EXPECT_VALID(result);
{
- StackZone zone(isolate);
- HANDLESCOPE(isolate);
+ StackZone zone(thread);
+ HANDLESCOPE(thread);
Profile profile(isolate);
AllocationFilter filter(isolate, one_byte_string_class.id());
profile.Build(&filter, Profile::kNoTags);
@@ -1027,8 +1027,8 @@
EXPECT_VALID(result);
{
- StackZone zone(isolate);
- HANDLESCOPE(isolate);
+ StackZone zone(thread);
+ HANDLESCOPE(thread);
Profile profile(isolate);
AllocationFilter filter(isolate, one_byte_string_class.id());
profile.Build(&filter, Profile::kNoTags);
@@ -1045,7 +1045,7 @@
EXPECT_VALID(lib);
Library& root_library = Library::Handle();
root_library ^= Api::UnwrapHandle(lib);
- Isolate* isolate = Isolate::Current();
+ Isolate* isolate = thread->isolate();
const Class& one_byte_string_class =
Class::Handle(isolate->object_store()->one_byte_string_class());
@@ -1057,8 +1057,8 @@
EXPECT_VALID(result);
{
- StackZone zone(isolate);
- HANDLESCOPE(isolate);
+ StackZone zone(thread);
+ HANDLESCOPE(thread);
Profile profile(isolate);
AllocationFilter filter(isolate, one_byte_string_class.id());
profile.Build(&filter, Profile::kNoTags);
@@ -1071,8 +1071,8 @@
EXPECT_VALID(result);
{
- StackZone zone(isolate);
- HANDLESCOPE(isolate);
+ StackZone zone(thread);
+ HANDLESCOPE(thread);
Profile profile(isolate);
AllocationFilter filter(isolate, one_byte_string_class.id());
profile.Build(&filter, Profile::kNoTags);
@@ -1097,8 +1097,8 @@
EXPECT_VALID(result);
{
- StackZone zone(isolate);
- HANDLESCOPE(isolate);
+ StackZone zone(thread);
+ HANDLESCOPE(thread);
Profile profile(isolate);
AllocationFilter filter(isolate, one_byte_string_class.id());
profile.Build(&filter, Profile::kNoTags);
@@ -1111,8 +1111,8 @@
EXPECT_VALID(result);
{
- StackZone zone(isolate);
- HANDLESCOPE(isolate);
+ StackZone zone(thread);
+ HANDLESCOPE(thread);
Profile profile(isolate);
AllocationFilter filter(isolate, one_byte_string_class.id());
profile.Build(&filter, Profile::kNoTags);
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index 16d5728..0c4fcf6 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -584,6 +584,7 @@
friend class SizeExcludingClassVisitor; // GetClassId
friend class RetainingPathVisitor; // GetClassId
friend class SkippedCodeFunctions; // StorePointer
+ friend class InstructionsReader; // tags_ check
friend class SnapshotReader;
friend class SnapshotWriter;
friend class String;
@@ -1002,11 +1003,11 @@
RawLocalVarDescriptors* var_descriptors_;
RawArray* inlined_metadata_;
RawArray* comments_;
- // If return_address_info_ is a Smi, it is the offset to the prologue.
- // Else, return_address_info_ is null.
+ // If return_address_metadata_ is a Smi, it is the offset to the prologue.
+ // Else, return_address_metadata_ is null.
RawObject* return_address_metadata_;
RawObject** to() {
- return reinterpret_cast<RawObject**>(&ptr()->comments_);
+ return reinterpret_cast<RawObject**>(&ptr()->return_address_metadata_);
}
uword entry_point_;
@@ -1053,6 +1054,7 @@
Entry* first_entry() { return &ptr()->data()[0]; }
friend class Object;
+ friend class SnapshotReader;
};
@@ -1084,6 +1086,7 @@
friend class MarkingVisitor;
friend class SkippedCodeFunctions;
friend class Function;
+ friend class InstructionsReader;
};
@@ -1141,6 +1144,7 @@
const uint8_t* data() const { OPEN_ARRAY_START(uint8_t, intptr_t); }
friend class Object;
+ friend class SnapshotReader;
};
@@ -1148,9 +1152,8 @@
// PC. The stack map representation consists of a bit map which marks each
// live object index starting from the base of the frame.
//
-// The Stackmap also consists of a link to the code object corresponding to
-// the frame which the stack map is describing. The bit map representation
-// is optimized for dense and small bit maps, without any upper bound.
+// The bit map representation is optimized for dense and small bit maps, without
+// any upper bound.
class RawStackmap : public RawObject {
RAW_HEAP_OBJECT_IMPLEMENTATION(Stackmap);
@@ -1168,6 +1171,8 @@
// Variable length data follows here (bitmap of the stack layout).
uint8_t* data() { OPEN_ARRAY_START(uint8_t, uint8_t); }
const uint8_t* data() const { OPEN_ARRAY_START(uint8_t, uint8_t); }
+
+ friend class SnapshotReader;
};
@@ -1242,6 +1247,7 @@
}
friend class Object;
+ friend class SnapshotReader;
};
@@ -1271,6 +1277,7 @@
HandlerInfo* data() { OPEN_ARRAY_START(HandlerInfo, intptr_t); }
friend class Object;
+ friend class SnapshotReader;
};
@@ -1335,6 +1342,7 @@
friend class Object;
friend class RawClosureData;
+ friend class SnapshotReader;
};
diff --git a/runtime/vm/raw_object_snapshot.cc b/runtime/vm/raw_object_snapshot.cc
index 3bb7b96..ff8c438 100644
--- a/runtime/vm/raw_object_snapshot.cc
+++ b/runtime/vm/raw_object_snapshot.cc
@@ -26,6 +26,18 @@
#define OFFSET_OF_FROM(obj) \
obj.raw()->from() - reinterpret_cast<RawObject**>(obj.raw()->ptr())
+// TODO(18854): Need to assert No GC can happen here, even though
+// allocations may happen.
+#define READ_OBJECT_FIELDS(object, from, to, as_reference) \
+ intptr_t num_flds = (to) - (from); \
+ intptr_t from_offset = OFFSET_OF_FROM(object); \
+ for (intptr_t i = 0; i <= num_flds; i++) { \
+ (*reader->PassiveObjectHandle()) = \
+ reader->ReadObjectImpl(as_reference, object_id, (i + from_offset)); \
+ object.StorePointer(((from) + i), \
+ reader->PassiveObjectHandle()->raw()); \
+ }
+
RawClass* Class::ReadFrom(SnapshotReader* reader,
intptr_t object_id,
intptr_t tags,
@@ -66,16 +78,8 @@
cls.set_state_bits(reader->Read<uint16_t>());
// Set all the object fields.
- // TODO(5411462): Need to assert No GC can happen here, even though
- // allocations may happen.
- intptr_t num_flds = (cls.raw()->to() - cls.raw()->from());
- intptr_t from_offset = OFFSET_OF_FROM(cls);
- for (intptr_t i = 0; i <= num_flds; i++) {
- (*reader->PassiveObjectHandle()) =
- reader->ReadObjectImpl(kAsReference, object_id, (i + from_offset));
- cls.StorePointer((cls.raw()->from() + i),
- reader->PassiveObjectHandle()->raw());
- }
+ READ_OBJECT_FIELDS(cls, cls.raw()->from(), cls.raw()->to(), kAsReference);
+
ASSERT(!cls.IsInFullSnapshot() || (kind == Snapshot::kFull));
} else {
cls ^= reader->ReadClassId(object_id);
@@ -155,15 +159,11 @@
unresolved_class.set_token_pos(reader->Read<int32_t>());
// Set all the object fields.
- // TODO(5411462): Need to assert No GC can happen here, even though
- // allocations may happen.
- intptr_t num_flds = (unresolved_class.raw()->to() -
- unresolved_class.raw()->from());
- for (intptr_t i = 0; i <= num_flds; i++) {
- (*reader->PassiveObjectHandle()) = reader->ReadObjectImpl(kAsReference);
- unresolved_class.StorePointer((unresolved_class.raw()->from() + i),
- reader->PassiveObjectHandle()->raw());
- }
+ READ_OBJECT_FIELDS(unresolved_class,
+ unresolved_class.raw()->from(),
+ unresolved_class.raw()->to(),
+ kAsReference);
+
return unresolved_class.raw();
}
@@ -226,16 +226,7 @@
type.set_type_state(reader->Read<int8_t>());
// Set all the object fields.
- // TODO(5411462): Need to assert No GC can happen here, even though
- // allocations may happen.
- intptr_t num_flds = (type.raw()->to() - type.raw()->from());
- intptr_t from_offset = OFFSET_OF_FROM(type);
- for (intptr_t i = 0; i <= num_flds; i++) {
- (*reader->PassiveObjectHandle()) =
- reader->ReadObjectImpl(kAsReference, object_id, (i + from_offset));
- type.StorePointer((type.raw()->from() + i),
- reader->PassiveObjectHandle()->raw());
- }
+ READ_OBJECT_FIELDS(type, type.raw()->from(), type.raw()->to(), kAsReference);
// Set the canonical bit.
if (!defer_canonicalization && RawObject::IsCanonical(tags)) {
@@ -296,16 +287,9 @@
reader->AddBackRef(object_id, &type_ref, kIsDeserialized);
// Set all the object fields.
- // TODO(5411462): Need to assert No GC can happen here, even though
- // allocations may happen.
- intptr_t num_flds = (type_ref.raw()->to() - type_ref.raw()->from());
- intptr_t from_offset = OFFSET_OF_FROM(type_ref);
- for (intptr_t i = 0; i <= num_flds; i++) {
- (*reader->PassiveObjectHandle()) =
- reader->ReadObjectImpl(kAsReference, object_id, (i + from_offset));
- type_ref.StorePointer((type_ref.raw()->from() + i),
- reader->PassiveObjectHandle()->raw());
- }
+ READ_OBJECT_FIELDS(type_ref,
+ type_ref.raw()->from(), type_ref.raw()->to(),
+ kAsReference);
return type_ref.raw();
}
@@ -346,17 +330,9 @@
type_parameter.set_type_state(reader->Read<int8_t>());
// Set all the object fields.
- // TODO(5411462): Need to assert No GC can happen here, even though
- // allocations may happen.
- intptr_t num_flds = (type_parameter.raw()->to() -
- type_parameter.raw()->from());
- intptr_t from_offset = OFFSET_OF_FROM(type_parameter);
- for (intptr_t i = 0; i <= num_flds; i++) {
- (*reader->PassiveObjectHandle()) =
- reader->ReadObjectImpl(kAsReference, object_id, (i + from_offset));
- type_parameter.StorePointer((type_parameter.raw()->from() + i),
- reader->PassiveObjectHandle()->raw());
- }
+ READ_OBJECT_FIELDS(type_parameter,
+ type_parameter.raw()->from(), type_parameter.raw()->to(),
+ kAsReference);
return type_parameter.raw();
}
@@ -400,17 +376,9 @@
reader->AddBackRef(object_id, &bounded_type, kIsDeserialized);
// Set all the object fields.
- // TODO(5411462): Need to assert No GC can happen here, even though
- // allocations may happen.
- intptr_t num_flds = (bounded_type.raw()->to() -
- bounded_type.raw()->from());
- intptr_t from_offset = OFFSET_OF_FROM(bounded_type);
- for (intptr_t i = 0; i <= num_flds; i++) {
- (*reader->PassiveObjectHandle()) =
- reader->ReadObjectImpl(kAsReference, object_id, (i + from_offset));
- bounded_type.StorePointer((bounded_type.raw()->from() + i),
- reader->PassiveObjectHandle()->raw());
- }
+ READ_OBJECT_FIELDS(bounded_type,
+ bounded_type.raw()->from(), bounded_type.raw()->to(),
+ kAsReference);
return bounded_type.raw();
}
@@ -534,14 +502,8 @@
reader->AddBackRef(object_id, &cls, kIsDeserialized);
// Set all the object fields.
- // TODO(5411462): Need to assert No GC can happen here, even though
- // allocations may happen.
- intptr_t num_flds = (cls.raw()->to() - cls.raw()->from());
- for (intptr_t i = 0; i <= num_flds; i++) {
- (*reader->PassiveObjectHandle()) = reader->ReadObjectImpl(kAsReference);
- cls.StorePointer((cls.raw()->from() + i),
- reader->PassiveObjectHandle()->raw());
- }
+ READ_OBJECT_FIELDS(cls, cls.raw()->from(), cls.raw()->to(), kAsReference);
+
ASSERT(((kind == Snapshot::kScript) &&
!Class::IsInFullSnapshot(cls.source_class())) ||
(kind == Snapshot::kFull));
@@ -581,12 +543,7 @@
reader->AddBackRef(object_id, &data, kIsDeserialized);
// Set all the object fields.
- // TODO(5411462): Need to assert No GC can happen here, even though
- // allocations may happen.
- intptr_t num_flds = (data.raw()->to() - data.raw()->from());
- for (intptr_t i = 0; i <= num_flds; i++) {
- *(data.raw()->from() + i) = reader->ReadObjectImpl(kAsReference);
- }
+ READ_OBJECT_FIELDS(data, data.raw()->from(), data.raw()->to(), kAsReference);
return data.raw();
}
@@ -617,8 +574,6 @@
}
}
- writer->WriteObjectImpl(Object::null(), kAsInlinedObject);
-
// Parent function.
writer->WriteObjectImpl(ptr()->parent_function_, kAsInlinedObject);
@@ -644,16 +599,7 @@
reader->AddBackRef(object_id, &data, kIsDeserialized);
// Set all the object fields.
- // TODO(5411462): Need to assert No GC can happen here, even though
- // allocations may happen.
- intptr_t num_flds = (data.raw()->to() - data.raw()->from());
- intptr_t from_offset = OFFSET_OF_FROM(data);
- for (intptr_t i = 0; i <= num_flds; i++) {
- (*reader->PassiveObjectHandle()) =
- reader->ReadObjectImpl(kAsReference, object_id, (i + from_offset));
- data.StorePointer((data.raw()->from() + i),
- reader->PassiveObjectHandle()->raw());
- }
+ READ_OBJECT_FIELDS(data, data.raw()->from(), data.raw()->to(), kAsReference);
return data.raw();
}
@@ -702,23 +648,18 @@
func.set_optimized_call_site_count(reader->Read<uint16_t>());
// Set all the object fields.
- // TODO(5411462): Need to assert No GC can happen here, even though
- // allocations may happen.
- RawObject** toaddr = reader->snapshot_code() ? func.raw()->to()
- : func.raw()->to_snapshot();
- intptr_t num_flds = toaddr - func.raw()->from();
- intptr_t from_offset = OFFSET_OF_FROM(func);
- for (intptr_t i = 0; i <= num_flds; i++) {
- (*reader->PassiveObjectHandle()) =
- reader->ReadObjectImpl(kAsReference, object_id, (i + from_offset));
- func.StorePointer((func.raw()->from() + i),
- reader->PassiveObjectHandle()->raw());
- }
+ READ_OBJECT_FIELDS(func,
+ func.raw()->from(),
+ reader->snapshot_code() ? func.raw()->to()
+ : func.raw()->to_snapshot(),
+ kAsReference);
if (!reader->snapshot_code()) {
// Initialize all fields that are not part of the snapshot.
func.ClearICDataArray();
func.ClearCode();
+ } else {
+ // TODO(rmacnak): Fix entry_point_.
}
return func.raw();
}
@@ -777,16 +718,9 @@
field.set_kind_bits(reader->Read<uint8_t>());
// Set all the object fields.
- // TODO(5411462): Need to assert No GC can happen here, even though
- // allocations may happen.
- intptr_t num_flds = (field.raw()->to() - field.raw()->from());
- intptr_t from_offset = OFFSET_OF_FROM(field);
- for (intptr_t i = 0; i <= num_flds; i++) {
- (*reader->PassiveObjectHandle()) =
- reader->ReadObjectImpl(kAsReference, object_id, (i + from_offset));
- field.StorePointer((field.raw()->from() + i),
- reader->PassiveObjectHandle()->raw());
- }
+ READ_OBJECT_FIELDS(field,
+ field.raw()->from(), field.raw()->to(),
+ kAsReference);
field.InitializeGuardedListLengthInObjectOffset();
@@ -836,14 +770,9 @@
literal_token.set_kind(token_kind);
// Set all the object fields.
- // TODO(5411462): Need to assert No GC can happen here, even though
- // allocations may happen.
- intptr_t num_flds = (literal_token.raw()->to() - literal_token.raw()->from());
- for (intptr_t i = 0; i <= num_flds; i++) {
- (*reader->PassiveObjectHandle()) = reader->ReadObjectImpl(kAsReference);
- literal_token.StorePointer((literal_token.raw()->from() + i),
- reader->PassiveObjectHandle()->raw());
- }
+ READ_OBJECT_FIELDS(literal_token,
+ literal_token.raw()->from(), literal_token.raw()->to(),
+ kAsReference);
return literal_token.raw();
}
@@ -1124,14 +1053,9 @@
prefix.StoreNonPointer(&prefix.raw_ptr()->is_loaded_, reader->Read<bool>());
// Set all the object fields.
- // TODO(5411462): Need to assert No GC can happen here, even though
- // allocations may happen.
- intptr_t num_flds = (prefix.raw()->to() - prefix.raw()->from());
- for (intptr_t i = 0; i <= num_flds; i++) {
- (*reader->PassiveObjectHandle()) = reader->ReadObjectImpl(kAsReference);
- prefix.StorePointer((prefix.raw()->from() + i),
- reader->PassiveObjectHandle()->raw());
- }
+ READ_OBJECT_FIELDS(prefix,
+ prefix.raw()->from(), prefix.raw()->to(),
+ kAsReference);
return prefix.raw();
}
@@ -1174,14 +1098,7 @@
reader->AddBackRef(object_id, &ns, kIsDeserialized);
// Set all the object fields.
- // TODO(5411462): Need to assert No GC can happen here, even though
- // allocations may happen.
- intptr_t num_flds = (ns.raw()->to() - ns.raw()->from());
- for (intptr_t i = 0; i <= num_flds; i++) {
- (*reader->PassiveObjectHandle()) = reader->ReadObjectImpl(kAsReference);
- ns.StorePointer((ns.raw()->from() + i),
- reader->PassiveObjectHandle()->raw());
- }
+ READ_OBJECT_FIELDS(ns, ns.raw()->from(), ns.raw()->to(), kAsReference);
return ns.raw();
}
@@ -1210,7 +1127,6 @@
intptr_t object_id,
intptr_t tags,
Snapshot::Kind kind) {
- UNREACHABLE(); // Untested.
ASSERT(reader->snapshot_code());
ASSERT(kind == Snapshot::kFull);
@@ -1224,14 +1140,11 @@
result.set_lazy_deopt_pc_offset(reader->Read<int32_t>());
// Set all the object fields.
- // TODO(5411462): Need to assert No GC can happen here, even though
- // allocations may happen.
- intptr_t num_flds = (result.raw()->to() - result.raw()->from());
- for (intptr_t i = 0; i <= num_flds; i++) {
- (*reader->PassiveObjectHandle()) = reader->ReadObjectImpl(kAsReference);
- result.StorePointer((result.raw()->from() + i),
- reader->PassiveObjectHandle()->raw());
- }
+ READ_OBJECT_FIELDS(result,
+ result.raw()->from(), result.raw()->to(),
+ kAsReference);
+
+ // TODO(rmacnak): Fix entry_point_.
return result.raw();
}
@@ -1274,15 +1187,22 @@
intptr_t object_id,
intptr_t tags,
Snapshot::Kind kind) {
- UNREACHABLE(); // Untested.
ASSERT(reader->snapshot_code());
ASSERT(kind == Snapshot::kFull);
- intptr_t id = reader->Read<int32_t>();
+ intptr_t full_tags = static_cast<uword>(reader->Read<intptr_t>());
+ intptr_t offset = reader->Read<int32_t>();
Instructions& result =
Instructions::ZoneHandle(reader->zone(),
- reader->GetInstructionsById(id));
+ reader->GetInstructionsAt(offset, full_tags));
reader->AddBackRef(object_id, &result, kIsDeserialized);
+
+ {
+ // TODO(rmacnak): Drop after calling convention change.
+ Code::CheckedHandle(reader->ReadObjectImpl(kAsReference));
+ ObjectPool::CheckedHandle(reader->ReadObjectImpl(kAsReference));
+ }
+
return result.raw();
}
@@ -1298,11 +1218,23 @@
writer->WriteInlinedObjectHeader(object_id);
writer->WriteVMIsolateObject(kInstructionsCid);
writer->WriteTags(writer->GetObjectTags(this));
+ }
+
+ writer->Write<intptr_t>(writer->GetObjectTags(this)); // For sanity check.
+
+ // Temporarily restore the object header for writing to the text section.
+ // TODO(asiva): Don't mutate object headers during serialization.
+ uword object_tags = writer->GetObjectTags(this);
+ uword snapshot_tags = ptr()->tags_;
+ ptr()->tags_ = object_tags;
+ writer->Write<int32_t>(writer->GetInstructionsId(this));
+ ptr()->tags_ = snapshot_tags;
+
+ {
+ // TODO(rmacnak): Drop after calling convention change.
writer->WriteObjectImpl(ptr()->code_, kAsReference);
writer->WriteObjectImpl(ptr()->object_pool_, kAsReference);
}
-
- writer->Write<int32_t>(writer->GetInstructionsId(this));
}
@@ -1310,7 +1242,6 @@
intptr_t object_id,
intptr_t tags,
Snapshot::Kind kind) {
- UNREACHABLE(); // Untested.
ASSERT(reader->snapshot_code());
ASSERT(kind == Snapshot::kFull);
@@ -1321,15 +1252,15 @@
NEW_OBJECT_WITH_LEN(ObjectPool, length));
reader->AddBackRef(object_id, &result, kIsDeserialized);
- RawTypedData* info_array = result.raw_ptr()->info_array_->ptr();
+ const TypedData& info_array =
+ TypedData::Handle(reader->NewTypedData(kTypedDataInt8ArrayCid, length));
+ result.set_info_array(info_array);
- // Set all the object fields.
- // TODO(5411462): Need to assert No GC can happen here, even though
- // allocations may happen.
+ NoSafepointScope no_safepoint;
for (intptr_t i = 0; i < length; i++) {
ObjectPool::EntryType entry_type =
- static_cast<ObjectPool::EntryType>(reader->Read<uint8_t>());
- info_array->data()[i] = entry_type;
+ static_cast<ObjectPool::EntryType>(reader->Read<int8_t>());
+ *reinterpret_cast<int8_t*>(info_array.DataAddr(i)) = entry_type;
switch (entry_type) {
case ObjectPool::kTaggedObject: {
(*reader->PassiveObjectHandle()) = reader->ReadObjectImpl(kAsReference);
@@ -1377,7 +1308,7 @@
for (intptr_t i = 0; i < length; i++) {
ObjectPool::EntryType entry_type =
static_cast<ObjectPool::EntryType>(info_array->data()[i]);
- writer->Write<uint8_t>(entry_type);
+ writer->Write<int8_t>(entry_type);
Entry& entry = ptr()->data()[i];
switch (entry_type) {
case ObjectPool::kTaggedObject:
@@ -1401,12 +1332,13 @@
intptr_t object_id,
intptr_t tags,
Snapshot::Kind kind) {
- UNREACHABLE(); // Untested.
ASSERT(reader->snapshot_code());
+ ASSERT(kind == Snapshot::kFull);
const int32_t length = reader->Read<int32_t>();
- PcDescriptors& result = PcDescriptors::ZoneHandle(reader->zone(),
- PcDescriptors::New(length));
+ PcDescriptors& result =
+ PcDescriptors::ZoneHandle(reader->zone(),
+ NEW_OBJECT_WITH_LEN(PcDescriptors, length));
reader->AddBackRef(object_id, &result, kIsDeserialized);
if (result.Length() > 0) {
@@ -1424,6 +1356,7 @@
intptr_t object_id,
Snapshot::Kind kind) {
ASSERT(writer->snapshot_code());
+ ASSERT(kind == Snapshot::kFull);
// Write out the serialization header value for this object.
writer->WriteInlinedObjectHeader(object_id);
@@ -1442,19 +1375,19 @@
intptr_t object_id,
intptr_t tags,
Snapshot::Kind kind) {
- UNREACHABLE(); // Untested.
ASSERT(reader->snapshot_code());
+ ASSERT(kind == Snapshot::kFull);
const int32_t length = reader->Read<int32_t>();
- const int32_t register_bit_count = reader->Read<int32_t>();
- const uword pc_offset = reader->Read<uint32_t>();
-
Stackmap& result =
Stackmap::ZoneHandle(reader->zone(),
- Stackmap::New(length, register_bit_count, pc_offset));
+ reader->NewStackmap(length));
reader->AddBackRef(object_id, &result, kIsDeserialized);
- if (result.Length() > 0) {
+ result.SetRegisterBitCount(reader->Read<int32_t>());
+ result.SetPcOffset(reader->Read<uint32_t>());
+
+ if (length > 0) {
NoSafepointScope no_safepoint;
intptr_t len = (result.Length() + 7) / 8;
uint8_t* data = result.UnsafeMutableNonPointer(result.raw_ptr()->data());
@@ -1469,11 +1402,13 @@
intptr_t object_id,
Snapshot::Kind kind) {
ASSERT(writer->snapshot_code());
+ ASSERT(kind == Snapshot::kFull);
// Write out the serialization header value for this object.
writer->WriteInlinedObjectHeader(object_id);
writer->WriteIndexedObject(kStackmapCid);
writer->WriteTags(writer->GetObjectTags(this));
+
writer->Write<int32_t>(ptr()->length_);
writer->Write<int32_t>(ptr()->register_bit_count_);
writer->Write<uint32_t>(ptr()->pc_offset_);
@@ -1489,14 +1424,15 @@
intptr_t object_id,
intptr_t tags,
Snapshot::Kind kind) {
- UNREACHABLE(); // Untested.
ASSERT(reader->snapshot_code());
+ ASSERT(kind == Snapshot::kFull);
const int32_t num_entries = reader->Read<int32_t>();
LocalVarDescriptors& result =
LocalVarDescriptors::ZoneHandle(reader->zone(),
- LocalVarDescriptors::New(num_entries));
+ NEW_OBJECT_WITH_LEN(LocalVarDescriptors,
+ num_entries));
reader->AddBackRef(object_id, &result, kIsDeserialized);
for (intptr_t i = 0; i < num_entries; i++) {
@@ -1521,6 +1457,7 @@
intptr_t object_id,
Snapshot::Kind kind) {
ASSERT(writer->snapshot_code());
+ ASSERT(kind == Snapshot::kFull);
// Write out the serialization header value for this object.
writer->WriteInlinedObjectHeader(object_id);
@@ -1528,7 +1465,7 @@
writer->WriteTags(writer->GetObjectTags(this));
writer->Write<int32_t>(ptr()->num_entries_);
for (intptr_t i = 0; i < ptr()->num_entries_; i++) {
- writer->WriteObjectImpl(ptr()->names()[i], kAsInlinedObject);
+ writer->WriteObjectImpl(ptr()->names()[i], kAsReference);
}
if (ptr()->num_entries_ > 0) {
intptr_t len = ptr()->num_entries_ * sizeof(VarInfo);
@@ -1542,15 +1479,14 @@
intptr_t object_id,
intptr_t tags,
Snapshot::Kind kind) {
- UNREACHABLE(); // Untested.
ASSERT(reader->snapshot_code());
+ ASSERT(kind == Snapshot::kFull);
- // handled_types_data.
- *(reader->ArrayHandle()) ^= reader->ReadObjectImpl(kAsInlinedObject);
-
+ const int32_t num_entries = reader->Read<int32_t>();
ExceptionHandlers& result =
ExceptionHandlers::ZoneHandle(reader->zone(),
- ExceptionHandlers::New(*reader->ArrayHandle()));
+ NEW_OBJECT_WITH_LEN(ExceptionHandlers,
+ num_entries));
reader->AddBackRef(object_id, &result, kIsDeserialized);
if (result.num_entries() > 0) {
@@ -1562,6 +1498,10 @@
reader->ReadBytes(data, len);
}
+ *(reader->ArrayHandle()) ^= reader->ReadObjectImpl(kAsInlinedObject);
+ result.StorePointer(&result.raw_ptr()->handled_types_data_,
+ reader->ArrayHandle()->raw());
+
return result.raw();
}
@@ -1570,18 +1510,21 @@
intptr_t object_id,
Snapshot::Kind kind) {
ASSERT(writer->snapshot_code());
+ ASSERT(kind == Snapshot::kFull);
// Write out the serialization header value for this object.
writer->WriteInlinedObjectHeader(object_id);
writer->WriteIndexedObject(kExceptionHandlersCid);
writer->WriteTags(writer->GetObjectTags(this));
- writer->WriteObjectImpl(ptr()->handled_types_data_, kAsInlinedObject);
+ writer->Write<int32_t>(ptr()->num_entries_);
if (ptr()->num_entries_ > 0) {
intptr_t len = ptr()->num_entries_ * sizeof(HandlerInfo);
uint8_t* data = reinterpret_cast<uint8_t*>(ptr()->data());
writer->WriteBytes(data, len);
}
+
+ writer->WriteObjectImpl(ptr()->handled_types_data_, kAsInlinedObject);
}
@@ -1646,8 +1589,13 @@
// Allocate context object.
bool is_implicit = reader->Read<bool>();
if (is_implicit) {
- ContextScope& context_scope =
- ContextScope::ZoneHandle(ContextScope::New(1, true));
+ ContextScope& context_scope = ContextScope::ZoneHandle();
+ if (kind == Snapshot::kFull) {
+ context_scope = reader->NewContextScope(1);
+ context_scope.set_is_implicit(true);
+ } else {
+ context_scope = ContextScope::New(1, true);
+ }
reader->AddBackRef(object_id, &context_scope, kIsDeserialized);
*reader->TypeHandle() ^= reader->ReadObjectImpl(kAsInlinedObject);
@@ -1699,7 +1647,6 @@
intptr_t object_id,
intptr_t tags,
Snapshot::Kind kind) {
- UNREACHABLE(); // Untested.
ASSERT(reader->snapshot_code());
ASSERT(kind == Snapshot::kFull);
@@ -1710,14 +1657,9 @@
result.set_state_bits(reader->Read<uint32_t>());
// Set all the object fields.
- // TODO(5411462): Need to assert No GC can happen here, even though
- // allocations may happen.
- intptr_t num_flds = (result.raw()->to() - result.raw()->from());
- for (intptr_t i = 0; i <= num_flds; i++) {
- (*reader->PassiveObjectHandle()) = reader->ReadObjectImpl(kAsReference);
- result.StorePointer((result.raw()->from() + i),
- reader->PassiveObjectHandle()->raw());
- }
+ READ_OBJECT_FIELDS(result,
+ result.raw()->from(), result.raw()->to(),
+ kAsReference);
return result.raw();
}
@@ -1750,7 +1692,6 @@
intptr_t object_id,
intptr_t tags,
Snapshot::Kind kind) {
- UNREACHABLE(); // Untested.
ASSERT(reader->snapshot_code());
ASSERT(kind == Snapshot::kFull);
@@ -1762,14 +1703,9 @@
result.set_filled_entry_count(reader->Read<int32_t>());
// Set all the object fields.
- // TODO(5411462): Need to assert No GC can happen here, even though
- // allocations may happen.
- intptr_t num_flds = (result.raw()->to() - result.raw()->from());
- for (intptr_t i = 0; i <= num_flds; i++) {
- (*reader->PassiveObjectHandle()) = reader->ReadObjectImpl(kAsReference);
- result.StorePointer((result.raw()->from() + i),
- reader->PassiveObjectHandle()->raw());
- }
+ READ_OBJECT_FIELDS(result,
+ result.raw()->from(), result.raw()->to(),
+ kAsReference);
return result.raw();
}
@@ -1801,7 +1737,6 @@
intptr_t object_id,
intptr_t tags,
Snapshot::Kind kind) {
- UNREACHABLE(); // Untested.
ASSERT(reader->snapshot_code());
ASSERT(kind == Snapshot::kFull);
@@ -1867,14 +1802,9 @@
reader->AddBackRef(object_id, &api_error, kIsDeserialized);
// Set all the object fields.
- // TODO(5411462): Need to assert No GC can happen here, even though
- // allocations may happen.
- intptr_t num_flds = (api_error.raw()->to() - api_error.raw()->from());
- for (intptr_t i = 0; i <= num_flds; i++) {
- (*reader->PassiveObjectHandle()) = reader->ReadObjectImpl(kAsReference);
- api_error.StorePointer((api_error.raw()->from() + i),
- reader->PassiveObjectHandle()->raw());
- }
+ READ_OBJECT_FIELDS(api_error,
+ api_error.raw()->from(), api_error.raw()->to(),
+ kAsReference);
return api_error.raw();
}
@@ -1914,15 +1844,9 @@
language_error.set_kind(reader->Read<uint8_t>());
// Set all the object fields.
- // TODO(5411462): Need to assert No GC can happen here, even though
- // allocations may happen.
- intptr_t num_flds =
- (language_error.raw()->to() - language_error.raw()->from());
- for (intptr_t i = 0; i <= num_flds; i++) {
- (*reader->PassiveObjectHandle()) = reader->ReadObjectImpl(kAsReference);
- language_error.StorePointer((language_error.raw()->from() + i),
- reader->PassiveObjectHandle()->raw());
- }
+ READ_OBJECT_FIELDS(language_error,
+ language_error.raw()->from(), language_error.raw()->to(),
+ kAsReference);
return language_error.raw();
}
@@ -1959,14 +1883,9 @@
reader->AddBackRef(object_id, &result, kIsDeserialized);
// Set all the object fields.
- // TODO(5411462): Need to assert No GC can happen here, even though
- // allocations may happen.
- intptr_t num_flds = (result.raw()->to() - result.raw()->from());
- for (intptr_t i = 0; i <= num_flds; i++) {
- (*reader->PassiveObjectHandle()) = reader->ReadObjectImpl(kAsReference);
- result.StorePointer((result.raw()->from() + i),
- reader->PassiveObjectHandle()->raw());
- }
+ READ_OBJECT_FIELDS(result,
+ result.raw()->from(), result.raw()->to(),
+ kAsReference);
return result.raw();
}
@@ -2118,14 +2037,7 @@
reader->AddBackRef(object_id, &obj, kIsDeserialized);
// Set all the object fields.
- // TODO(5411462): Need to assert No GC can happen here, even though
- // allocations may happen.
- intptr_t num_flds = (obj.raw()->to() - obj.raw()->from());
- for (intptr_t i = 0; i <= num_flds; i++) {
- (*reader->PassiveObjectHandle()) = reader->ReadObjectImpl(kAsInlinedObject);
- obj.StorePointer(obj.raw()->from() + i,
- reader->PassiveObjectHandle()->raw());
- }
+ READ_OBJECT_FIELDS(obj, obj.raw()->from(), obj.raw()->to(), kAsInlinedObject);
// If it is a canonical constant make it one.
// When reading a full snapshot we don't need to canonicalize the object
@@ -2603,13 +2515,18 @@
LinkedHashMap& map = LinkedHashMap::ZoneHandle(
reader->zone(), LinkedHashMap::null());
- if (kind == Snapshot::kFull || kind == Snapshot::kScript) {
+ if ((kind == Snapshot::kFull && !reader->snapshot_code()) ||
+ kind == Snapshot::kScript) {
// The immutable maps that seed map literals are not yet VM-internal, so
// we don't reach this.
UNREACHABLE();
} else {
// Since the map might contain itself as a key or value, allocate first.
- map = LinkedHashMap::NewUninitialized(HEAP_SPACE(kind));
+ if (kind == Snapshot::kFull) {
+ map = reader->NewLinkedHashMap();
+ } else {
+ map = LinkedHashMap::NewUninitialized(HEAP_SPACE(kind));
+ }
}
reader->AddBackRef(object_id, &map, kIsDeserialized);
@@ -2630,7 +2547,9 @@
Utils::RoundUpToPowerOfTwo(used_data),
static_cast<uintptr_t>(LinkedHashMap::kInitialIndexSize));
Array& data = Array::ZoneHandle(reader->zone(),
- Array::New(data_size, HEAP_SPACE(kind)));
+ NEW_OBJECT_WITH_LEN_SPACE(Array,
+ data_size,
+ kind));
map.SetData(data);
map.SetDeletedKeys(0);
@@ -2654,10 +2573,10 @@
void RawLinkedHashMap::WriteTo(SnapshotWriter* writer,
intptr_t object_id,
Snapshot::Kind kind) {
- if (kind == Snapshot::kFull || kind == Snapshot::kScript) {
+ if ((kind == Snapshot::kFull && !writer->snapshot_code()) ||
+ kind == Snapshot::kScript) {
// The immutable maps that seed map literals are not yet VM-internal, so
// we don't reach this.
- UNREACHABLE();
}
ASSERT(writer != NULL);
@@ -3103,11 +3022,18 @@
intptr_t object_id,
intptr_t tags,
Snapshot::Kind kind) {
+ ASSERT(kind == Snapshot::kMessage || reader->snapshot_code());
+
uint64_t id = reader->Read<uint64_t>();
uint64_t origin_id = reader->Read<uint64_t>();
- SendPort& result = SendPort::ZoneHandle(reader->zone(),
- SendPort::New(id, origin_id));
+ SendPort& result = SendPort::ZoneHandle(reader->zone());
+ if (reader->snapshot_code()) {
+ // TODO(rmacnak): Reset fields in precompiled snapshots and assert
+ // this is unreachable.
+ } else {
+ result = SendPort::New(id, origin_id);
+ }
reader->AddBackRef(object_id, &result, kIsDeserialized);
return result.raw();
}
@@ -3137,19 +3063,14 @@
reader->NewStacktrace());
reader->AddBackRef(object_id, &result, kIsDeserialized);
- // Set all the object fields.
- // TODO(5411462): Need to assert No GC can happen here, even though
- // allocations may happen.
- intptr_t num_flds = (result.raw()->to() - result.raw()->from());
- for (intptr_t i = 0; i <= num_flds; i++) {
- (*reader->PassiveObjectHandle()) = reader->ReadObjectImpl(kAsReference);
- result.StorePointer((result.raw()->from() + i),
- reader->PassiveObjectHandle()->raw());
- }
-
bool expand_inlined = reader->Read<bool>();
result.set_expand_inlined(expand_inlined);
+ // Set all the object fields.
+ READ_OBJECT_FIELDS(result,
+ result.raw()->from(), result.raw()->to(),
+ kAsReference);
+
return result.raw();
}
UNREACHABLE(); // Stacktraces are not sent in a snapshot.
@@ -3172,11 +3093,11 @@
writer->WriteIndexedObject(kStacktraceCid);
writer->WriteTags(writer->GetObjectTags(this));
+ writer->Write(ptr()->expand_inlined_);
+
// Write out all the object pointer fields.
SnapshotWriterVisitor visitor(writer);
visitor.VisitPointers(from(), to());
-
- writer->Write(ptr()->expand_inlined_);
} else {
// Stacktraces are not allowed in other snapshot forms.
writer->SetWriteException(Exceptions::kArgument,
@@ -3246,15 +3167,9 @@
reader->AddBackRef(object_id, &weak_property, kIsDeserialized);
// Set all the object fields.
- // TODO(5411462): Need to assert No GC can happen here, even though
- // allocations may happen.
- intptr_t num_flds = (weak_property.raw()->to() -
- weak_property.raw()->from());
- for (intptr_t i = 0; i <= num_flds; i++) {
- (*reader->PassiveObjectHandle()) = reader->ReadObjectImpl(kAsReference);
- weak_property.StorePointer((weak_property.raw()->from() + i),
- reader->PassiveObjectHandle()->raw());
- }
+ READ_OBJECT_FIELDS(weak_property,
+ weak_property.raw()->from(), weak_property.raw()->to(),
+ kAsReference);
return weak_property.raw();
}
diff --git a/runtime/vm/regexp_assembler_ir.cc b/runtime/vm/regexp_assembler_ir.cc
index 6851926..5704b12 100644
--- a/runtime/vm/regexp_assembler_ir.cc
+++ b/runtime/vm/regexp_assembler_ir.cc
@@ -12,6 +12,7 @@
#include "vm/object_store.h"
#include "vm/regexp.h"
#include "vm/resolver.h"
+#include "vm/runtime_entry.h"
#include "vm/stack_frame.h"
#include "vm/unibrow-inl.h"
#include "vm/unicode.h"
@@ -335,11 +336,10 @@
}
-RawBool* IRRegExpMacroAssembler::CaseInsensitiveCompareUC16(
- RawString* str_raw,
- RawSmi* lhs_index_raw,
- RawSmi* rhs_index_raw,
- RawSmi* length_raw) {
+static RawBool* CaseInsensitiveCompareUC16(RawString* str_raw,
+ RawSmi* lhs_index_raw,
+ RawSmi* rhs_index_raw,
+ RawSmi* length_raw) {
const String& str = String::Handle(str_raw);
const Smi& lhs_index = Smi::Handle(lhs_index_raw);
const Smi& rhs_index = Smi::Handle(rhs_index_raw);
@@ -368,6 +368,11 @@
}
+DEFINE_RAW_LEAF_RUNTIME_ENTRY(
+ CaseInsensitiveCompareUC16, 4, false /* is_float */,
+ reinterpret_cast<RuntimeFunction>(&CaseInsensitiveCompareUC16));
+
+
LocalVariable* IRRegExpMacroAssembler::Parameter(const String& name,
intptr_t index) const {
const Type& local_type = Type::ZoneHandle(Z, Type::DynamicType());
diff --git a/runtime/vm/regexp_assembler_ir.h b/runtime/vm/regexp_assembler_ir.h
index 77d09d5..1bd3930 100644
--- a/runtime/vm/regexp_assembler_ir.h
+++ b/runtime/vm/regexp_assembler_ir.h
@@ -37,14 +37,6 @@
virtual bool CanReadUnaligned();
- // Compares two-byte strings case insensitively.
- // Called from generated RegExp code.
- static RawBool* CaseInsensitiveCompareUC16(
- RawString* str_raw,
- RawSmi* lhs_index_raw,
- RawSmi* rhs_index_raw,
- RawSmi* length_raw);
-
static RawArray* Execute(const Function& function,
const String& input,
const Smi& start_offset,
diff --git a/runtime/vm/runtime_entry.cc b/runtime/vm/runtime_entry.cc
new file mode 100644
index 0000000..f177a10
--- /dev/null
+++ b/runtime/vm/runtime_entry.cc
@@ -0,0 +1,34 @@
+// Copyright (c) 2011, 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.
+
+#include "vm/runtime_entry.h"
+
+#include "vm/object.h"
+#include "vm/symbols.h"
+#include "vm/verifier.h"
+
+namespace dart {
+
+
+// Add function to a class and that class to the class dictionary so that
+// frame walking can be used.
+const Function& RegisterFakeFunction(const char* name, const Code& code) {
+ const String& class_name = String::Handle(Symbols::New("ownerClass"));
+ const Script& script = Script::Handle();
+ const Class& owner_class =
+ Class::Handle(Class::New(class_name, script, Scanner::kNoSourcePos));
+ const String& function_name = String::ZoneHandle(Symbols::New(name));
+ const Function& function = Function::ZoneHandle(
+ Function::New(function_name, RawFunction::kRegularFunction,
+ true, false, false, false, false, owner_class, 0));
+ const Array& functions = Array::Handle(Array::New(1));
+ functions.SetAt(0, function);
+ owner_class.SetFunctions(functions);
+ Library& lib = Library::Handle(Library::CoreLibrary());
+ lib.AddClass(owner_class);
+ function.AttachCode(code);
+ return function;
+}
+
+} // namespace dart
diff --git a/runtime/vm/runtime_entry.h b/runtime/vm/runtime_entry.h
index 2d4790f..97b5623 100644
--- a/runtime/vm/runtime_entry.h
+++ b/runtime/vm/runtime_entry.h
@@ -8,6 +8,7 @@
#include "vm/allocation.h"
#include "vm/flags.h"
#include "vm/native_arguments.h"
+#include "vm/runtime_entry_list.h"
#include "vm/tags.h"
namespace dart {
@@ -18,51 +19,6 @@
typedef void (*RuntimeFunction)(NativeArguments arguments);
-#define RUNTIME_ENTRY_LIST(V) \
- V(AllocateArray) \
- V(AllocateContext) \
- V(AllocateObject) \
- V(BreakpointRuntimeHandler) \
- V(SingleStepHandler) \
- V(CloneContext) \
- V(FixCallersTarget) \
- V(FixAllocationStubTarget) \
- V(InlineCacheMissHandlerOneArg) \
- V(InlineCacheMissHandlerTwoArgs) \
- V(InlineCacheMissHandlerThreeArgs) \
- V(StaticCallMissHandlerOneArg) \
- V(StaticCallMissHandlerTwoArgs) \
- V(Instanceof) \
- V(TypeCheck) \
- V(BadTypeError) \
- V(NonBoolTypeError) \
- V(InstantiateType) \
- V(InstantiateTypeArguments) \
- V(InvokeClosureNoSuchMethod) \
- V(InvokeNoSuchMethodDispatcher) \
- V(MegamorphicCacheMissHandler) \
- V(OptimizeInvokedFunction) \
- V(TraceICCall) \
- V(PatchStaticCall) \
- V(ReThrow) \
- V(StackOverflow) \
- V(Throw) \
- V(TraceFunctionEntry) \
- V(TraceFunctionExit) \
- V(DeoptimizeMaterialize) \
- V(UpdateFieldCid) \
- V(InitStaticField) \
- V(GrowRegExpStack) \
- V(CompileFunction) \
-
-#define LEAF_RUNTIME_ENTRY_LIST(V) \
- V(void, PrintStopMessage, const char*) \
- V(intptr_t, DeoptimizeCopyFrame, uword) \
- V(void, DeoptimizeFillFrame, uword) \
- V(void, StoreBufferBlockProcess, Thread*) \
- V(intptr_t, BigintCompare, RawBigint*, RawBigint*) \
-
-
enum RuntimeFunctionId {
kNoRuntimeFunctionId = -1,
#define DECLARE_ENUM_VALUE(name) \
@@ -99,7 +55,7 @@
intptr_t argument_count() const { return argument_count_; }
bool is_leaf() const { return is_leaf_; }
bool is_float() const { return is_float_; }
- uword GetEntryPoint() const { return reinterpret_cast<uword>(function()); }
+ uword GetEntryPoint() const;
// Generate code to call the runtime entry.
void Call(Assembler* assembler, intptr_t argument_count) const;
@@ -142,7 +98,7 @@
ASSERT(thread == Thread::Current()); \
Isolate* isolate = thread->isolate(); \
StackZone zone(thread); \
- HANDLESCOPE(isolate); \
+ HANDLESCOPE(thread); \
DRT_Helper##name(isolate, thread, zone.GetZone(), arguments); \
} \
VERIFY_ON_TRANSITION; \
@@ -167,6 +123,12 @@
#define END_LEAF_RUNTIME_ENTRY }
+// TODO(rmacnak): Fix alignment issue on simarm and simmips and use
+// DEFINE_LEAF_RUNTIME_ENTRY instead.
+#define DEFINE_RAW_LEAF_RUNTIME_ENTRY(name, argument_count, is_float, func) \
+ extern const RuntimeEntry k##name##RuntimeEntry( \
+ "DFLRT_"#name, func, argument_count, true, is_float) \
+
#define DECLARE_LEAF_RUNTIME_ENTRY(type, name, ...) \
extern const RuntimeEntry k##name##RuntimeEntry; \
extern "C" type DLRT_##name(__VA_ARGS__); \
@@ -185,12 +147,12 @@
uword RuntimeEntry::AddressFromId(RuntimeFunctionId id) {
switch (id) {
#define DEFINE_RUNTIME_CASE(name) \
- case k##name##Id: return reinterpret_cast<uword>(&DRT_##name);
+ case k##name##Id: return k##name##RuntimeEntry.GetEntryPoint();
RUNTIME_ENTRY_LIST(DEFINE_RUNTIME_CASE)
#undef DEFINE_RUNTIME_CASE
#define DEFINE_LEAF_RUNTIME_CASE(type, name, ...) \
- case k##name##Id: return reinterpret_cast<uword>(&DLRT_##name);
+ case k##name##Id: return k##name##RuntimeEntry.GetEntryPoint();
LEAF_RUNTIME_ENTRY_LIST(DEFINE_LEAF_RUNTIME_CASE)
#undef DEFINE_LEAF_RUNTIME_CASE
default:
@@ -202,12 +164,12 @@
RuntimeFunctionId RuntimeEntry::RuntimeFunctionIdFromAddress(uword address) {
#define CHECK_RUNTIME_ADDRESS(name) \
- if (address == reinterpret_cast<uword>(&DRT_##name)) return k##name##Id;
+ if (address == k##name##RuntimeEntry.GetEntryPoint()) return k##name##Id;
RUNTIME_ENTRY_LIST(CHECK_RUNTIME_ADDRESS)
#undef CHECK_RUNTIME_ADDRESS
#define CHECK_LEAF_RUNTIME_ADDRESS(type, name, ...) \
- if (address == reinterpret_cast<uword>(&DLRT_##name)) return k##name##Id;
+ if (address == k##name##RuntimeEntry.GetEntryPoint()) return k##name##Id;
LEAF_RUNTIME_ENTRY_LIST(CHECK_LEAF_RUNTIME_ADDRESS)
#undef CHECK_LEAF_RUNTIME_ADDRESS
return kNoRuntimeFunctionId;
diff --git a/runtime/vm/runtime_entry_arm.cc b/runtime/vm/runtime_entry_arm.cc
index b373811..a2c9d49 100644
--- a/runtime/vm/runtime_entry_arm.cc
+++ b/runtime/vm/runtime_entry_arm.cc
@@ -16,38 +16,42 @@
#define __ assembler->
+uword RuntimeEntry::GetEntryPoint() const {
+ // Compute the effective address. When running under the simulator,
+ // this is a redirection address that forces the simulator to call
+ // into the runtime system.
+ uword entry = reinterpret_cast<uword>(function());
+#if defined(USING_SIMULATOR)
+ // Redirection to leaf runtime calls supports a maximum of 4 arguments passed
+ // in registers (maximum 2 double arguments for leaf float runtime calls).
+ ASSERT(argument_count() >= 0);
+ ASSERT(!is_leaf() ||
+ (!is_float() && (argument_count() <= 4)) ||
+ (argument_count() <= 2));
+ Simulator::CallKind call_kind =
+ is_leaf() ? (is_float() ? Simulator::kLeafFloatRuntimeCall
+ : Simulator::kLeafRuntimeCall)
+ : Simulator::kRuntimeCall;
+ entry =
+ Simulator::RedirectExternalReference(entry, call_kind, argument_count());
+#endif
+ return entry;
+}
+
+
// Generate code to call into the stub which will call the runtime
// function. Input for the stub is as follows:
// SP : points to the arguments and return value array.
// R5 : address of the runtime function to call.
// R4 : number of arguments to the call.
void RuntimeEntry::Call(Assembler* assembler, intptr_t argument_count) const {
- // Compute the effective address. When running under the simulator,
- // this is a redirection address that forces the simulator to call
- // into the runtime system.
- uword entry = GetEntryPoint();
-#if defined(USING_SIMULATOR)
- // Redirection to leaf runtime calls supports a maximum of 4 arguments passed
- // in registers (maximum 2 double arguments for leaf float runtime calls).
- ASSERT(argument_count >= 0);
- ASSERT(!is_leaf() ||
- (!is_float() && (argument_count <= 4)) ||
- (argument_count <= 2));
- Simulator::CallKind call_kind =
- is_leaf() ? (is_float() ? Simulator::kLeafFloatRuntimeCall
- : Simulator::kLeafRuntimeCall)
- : Simulator::kRuntimeCall;
- entry =
- Simulator::RedirectExternalReference(entry, call_kind, argument_count);
-#endif
- ExternalLabel label(entry);
if (is_leaf()) {
ASSERT(argument_count == this->argument_count());
- __ BranchLink(&label, kNotPatchable);
+ __ BranchLinkOffset(THR, Thread::OffsetFromThread(this));
} else {
// Argument count is not checked here, but in the runtime entry for a more
// informative error message.
- __ LoadExternalLabel(R5, &label, kNotPatchable);
+ __ LoadFromOffset(kWord, R5, THR, Thread::OffsetFromThread(this));
__ LoadImmediate(R4, argument_count);
__ BranchLink(*StubCode::CallToRuntime_entry(), kNotPatchable);
}
diff --git a/runtime/vm/runtime_entry_arm64.cc b/runtime/vm/runtime_entry_arm64.cc
index 38dbe43..626d940 100644
--- a/runtime/vm/runtime_entry_arm64.cc
+++ b/runtime/vm/runtime_entry_arm64.cc
@@ -15,29 +15,36 @@
#define __ assembler->
+
+uword RuntimeEntry::GetEntryPoint() const {
+ // Compute the effective address. When running under the simulator,
+ // this is a redirection address that forces the simulator to call
+ // into the runtime system.
+ uword entry = reinterpret_cast<uword>(function());
+#if defined(USING_SIMULATOR)
+ // Redirection to leaf runtime calls supports a maximum of 4 arguments passed
+ // in registers (maximum 2 double arguments for leaf float runtime calls).
+ ASSERT(argument_count() >= 0);
+ ASSERT(!is_leaf() ||
+ (!is_float() && (argument_count() <= 4)) ||
+ (argument_count() <= 2));
+ Simulator::CallKind call_kind =
+ is_leaf() ? (is_float() ? Simulator::kLeafFloatRuntimeCall
+ : Simulator::kLeafRuntimeCall)
+ : Simulator::kRuntimeCall;
+ entry =
+ Simulator::RedirectExternalReference(entry, call_kind, argument_count());
+#endif
+ return entry;
+}
+
+
// Generate code to call into the stub which will call the runtime
// function. Input for the stub is as follows:
// SP : points to the arguments and return value array.
// R5 : address of the runtime function to call.
// R4 : number of arguments to the call.
void RuntimeEntry::Call(Assembler* assembler, intptr_t argument_count) const {
- // Compute the effective address. When running under the simulator,
- // this is a redirection address that forces the simulator to call
- // into the runtime system.
- uword entry = GetEntryPoint();
-#if defined(USING_SIMULATOR)
- // Redirection to leaf runtime calls supports a maximum of 8 arguments passed
- // in registers.
- ASSERT(argument_count >= 0);
- ASSERT(!is_leaf() || (argument_count <= 8));
- Simulator::CallKind call_kind =
- is_leaf() ? (is_float() ? Simulator::kLeafFloatRuntimeCall
- : Simulator::kLeafRuntimeCall)
- : Simulator::kRuntimeCall;
- entry =
- Simulator::RedirectExternalReference(entry, call_kind, argument_count);
-#endif
- ExternalLabel label(entry);
if (is_leaf()) {
ASSERT(argument_count == this->argument_count());
// Since we are entering C++ code, we must restore the C stack pointer from
@@ -49,13 +56,14 @@
__ mov(R26, SP);
__ ReserveAlignedFrameSpace(0);
__ mov(CSP, SP);
- __ BranchLink(&label);
+ __ ldr(TMP, Address(THR, Thread::OffsetFromThread(this)));
+ __ blr(TMP);
__ mov(SP, R26);
__ mov(CSP, R25);
} else {
// Argument count is not checked here, but in the runtime entry for a more
// informative error message.
- __ LoadExternalLabel(R5, &label);
+ __ ldr(R5, Address(THR, Thread::OffsetFromThread(this)));
__ LoadImmediate(R4, argument_count);
__ BranchLink(*StubCode::CallToRuntime_entry());
}
diff --git a/runtime/vm/runtime_entry_ia32.cc b/runtime/vm/runtime_entry_ia32.cc
index 33b0e5a..f16db03 100644
--- a/runtime/vm/runtime_entry_ia32.cc
+++ b/runtime/vm/runtime_entry_ia32.cc
@@ -15,6 +15,11 @@
#define __ assembler->
+uword RuntimeEntry::GetEntryPoint() const {
+ return reinterpret_cast<uword>(function());
+}
+
+
// Generate code to call into the stub which will call the runtime
// function. Input for the stub is as follows:
// For regular runtime calls -
diff --git a/runtime/vm/runtime_entry_list.h b/runtime/vm/runtime_entry_list.h
new file mode 100644
index 0000000..acdb5bf
--- /dev/null
+++ b/runtime/vm/runtime_entry_list.h
@@ -0,0 +1,66 @@
+// Copyright (c) 2011, 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.
+
+#ifndef VM_RUNTIME_ENTRY_LIST_H_
+#define VM_RUNTIME_ENTRY_LIST_H_
+
+namespace dart {
+
+#define RUNTIME_ENTRY_LIST(V) \
+ V(AllocateArray) \
+ V(AllocateContext) \
+ V(AllocateObject) \
+ V(BreakpointRuntimeHandler) \
+ V(SingleStepHandler) \
+ V(CloneContext) \
+ V(FixCallersTarget) \
+ V(FixAllocationStubTarget) \
+ V(InlineCacheMissHandlerOneArg) \
+ V(InlineCacheMissHandlerTwoArgs) \
+ V(InlineCacheMissHandlerThreeArgs) \
+ V(StaticCallMissHandlerOneArg) \
+ V(StaticCallMissHandlerTwoArgs) \
+ V(Instanceof) \
+ V(TypeCheck) \
+ V(BadTypeError) \
+ V(NonBoolTypeError) \
+ V(InstantiateType) \
+ V(InstantiateTypeArguments) \
+ V(InvokeClosureNoSuchMethod) \
+ V(InvokeNoSuchMethodDispatcher) \
+ V(MegamorphicCacheMissHandler) \
+ V(OptimizeInvokedFunction) \
+ V(TraceICCall) \
+ V(PatchStaticCall) \
+ V(ReThrow) \
+ V(StackOverflow) \
+ V(Throw) \
+ V(TraceFunctionEntry) \
+ V(TraceFunctionExit) \
+ V(DeoptimizeMaterialize) \
+ V(UpdateFieldCid) \
+ V(InitStaticField) \
+ V(GrowRegExpStack) \
+ V(CompileFunction) \
+
+#define LEAF_RUNTIME_ENTRY_LIST(V) \
+ V(void, PrintStopMessage, const char*) \
+ V(intptr_t, DeoptimizeCopyFrame, uword) \
+ V(void, DeoptimizeFillFrame, uword) \
+ V(void, StoreBufferBlockProcess, Thread*) \
+ V(intptr_t, BigintCompare, RawBigint*, RawBigint*) \
+ V(double, LibcPow, double, double) \
+ V(double, DartModulo, double, double) \
+ V(double, LibcFloor, double) \
+ V(double, LibcCeil, double) \
+ V(double, LibcTrunc, double) \
+ V(double, LibcRound, double) \
+ V(double, LibcCos, double) \
+ V(double, LibcSin, double) \
+ V(RawBool*, CaseInsensitiveCompareUC16, \
+ RawString*, RawSmi*, RawSmi*, RawSmi*) \
+
+} // namespace dart
+
+#endif // VM_RUNTIME_ENTRY_LIST_H_
diff --git a/runtime/vm/runtime_entry_mips.cc b/runtime/vm/runtime_entry_mips.cc
index e4a5dbf..31970fe 100644
--- a/runtime/vm/runtime_entry_mips.cc
+++ b/runtime/vm/runtime_entry_mips.cc
@@ -16,38 +16,43 @@
#define __ assembler->
+uword RuntimeEntry::GetEntryPoint() const {
+ // Compute the effective address. When running under the simulator,
+ // this is a redirection address that forces the simulator to call
+ // into the runtime system.
+ uword entry = reinterpret_cast<uword>(function());
+#if defined(USING_SIMULATOR)
+ // Redirection to leaf runtime calls supports a maximum of 4 arguments passed
+ // in registers (maximum 2 double arguments for leaf float runtime calls).
+ ASSERT(argument_count() >= 0);
+ ASSERT(!is_leaf() ||
+ (!is_float() && (argument_count() <= 4)) ||
+ (argument_count() <= 2));
+ Simulator::CallKind call_kind =
+ is_leaf() ? (is_float() ? Simulator::kLeafFloatRuntimeCall
+ : Simulator::kLeafRuntimeCall)
+ : Simulator::kRuntimeCall;
+ entry =
+ Simulator::RedirectExternalReference(entry, call_kind, argument_count());
+#endif
+ return entry;
+}
+
+
// Generate code to call into the stub which will call the runtime
// function. Input for the stub is as follows:
// SP : points to the arguments and return value array.
// S5 : address of the runtime function to call.
// S4 : number of arguments to the call.
void RuntimeEntry::Call(Assembler* assembler, intptr_t argument_count) const {
- // Compute the effective address. When running under the simulator,
- // this is a redirection address that forces the simulator to call
- // into the runtime system.
- uword entry = GetEntryPoint();
-#if defined(USING_SIMULATOR)
- // Redirection to leaf runtime calls supports a maximum of 4 arguments passed
- // in registers (maximum 2 double arguments for leaf float runtime calls).
- ASSERT(argument_count >= 0);
- ASSERT(!is_leaf() ||
- (!is_float() && (argument_count <= 4)) ||
- (argument_count <= 2));
- Simulator::CallKind call_kind =
- is_leaf() ? (is_float() ? Simulator::kLeafFloatRuntimeCall
- : Simulator::kLeafRuntimeCall)
- : Simulator::kRuntimeCall;
- entry =
- Simulator::RedirectExternalReference(entry, call_kind, argument_count);
-#endif
- ExternalLabel label(entry);
if (is_leaf()) {
ASSERT(argument_count == this->argument_count());
- __ BranchLink(&label, kNotPatchable);
+ __ lw(T9, Address(THR, Thread::OffsetFromThread(this)));
+ __ jalr(T9);
} else {
// Argument count is not checked here, but in the runtime entry for a more
// informative error message.
- __ LoadExternalLabel(S5, &label, kNotPatchable);
+ __ lw(S5, Address(THR, Thread::OffsetFromThread(this)));
__ LoadImmediate(S4, argument_count);
__ BranchLink(*StubCode::CallToRuntime_entry(), kNotPatchable);
}
diff --git a/runtime/vm/runtime_entry_test.cc b/runtime/vm/runtime_entry_test.cc
deleted file mode 100644
index f02f6f7..0000000
--- a/runtime/vm/runtime_entry_test.cc
+++ /dev/null
@@ -1,65 +0,0 @@
-// Copyright (c) 2011, 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.
-
-#include "vm/runtime_entry.h"
-
-#include "vm/object.h"
-#include "vm/symbols.h"
-#include "vm/verifier.h"
-
-namespace dart {
-
-DECLARE_RUNTIME_ENTRY(TestSmiSub)
-DECLARE_LEAF_RUNTIME_ENTRY(RawObject*, TestLeafSmiAdd, RawObject*, RawObject*)
-
-
-// Add function to a class and that class to the class dictionary so that
-// frame walking can be used.
-const Function& RegisterFakeFunction(const char* name, const Code& code) {
- const String& class_name = String::Handle(Symbols::New("ownerClass"));
- const Script& script = Script::Handle();
- const Class& owner_class =
- Class::Handle(Class::New(class_name, script, Scanner::kNoSourcePos));
- const String& function_name = String::ZoneHandle(Symbols::New(name));
- const Function& function = Function::ZoneHandle(
- Function::New(function_name, RawFunction::kRegularFunction,
- true, false, false, false, false, owner_class, 0));
- const Array& functions = Array::Handle(Array::New(1));
- functions.SetAt(0, function);
- owner_class.SetFunctions(functions);
- Library& lib = Library::Handle(Library::CoreLibrary());
- lib.AddClass(owner_class);
- function.AttachCode(code);
- return function;
-}
-
-
-// A runtime call for test purposes.
-// Arg0: a smi.
-// Arg1: a smi.
-// Result: a smi representing arg0 - arg1.
-DEFINE_RUNTIME_ENTRY(TestSmiSub, 2) {
- const Smi& left = Smi::CheckedHandle(arguments.ArgAt(0));
- const Smi& right = Smi::CheckedHandle(arguments.ArgAt(1));
- // Ignoring overflow in the calculation below.
- intptr_t result = left.Value() - right.Value();
- arguments.SetReturn(Smi::Handle(Smi::New(result)));
-}
-
-
-// A leaf runtime call for test purposes.
-// arg0: a smi.
-// arg1: a smi.
-// returns a smi representing arg0 + arg1.
-DEFINE_LEAF_RUNTIME_ENTRY(RawObject*, TestLeafSmiAdd, 2,
- RawObject* arg0, RawObject* arg1) {
- // Ignoring overflow in the calculation below and using the internal
- // representation of Smi directly without using any handlized code.
- intptr_t result = reinterpret_cast<intptr_t>(arg0) +
- reinterpret_cast<intptr_t>(arg1);
- return reinterpret_cast<RawObject*>(result);
-}
-END_LEAF_RUNTIME_ENTRY
-
-} // namespace dart
diff --git a/runtime/vm/runtime_entry_x64.cc b/runtime/vm/runtime_entry_x64.cc
index a6ff635..c3afdd8 100644
--- a/runtime/vm/runtime_entry_x64.cc
+++ b/runtime/vm/runtime_entry_x64.cc
@@ -15,6 +15,11 @@
#define __ assembler->
+uword RuntimeEntry::GetEntryPoint() const {
+ return reinterpret_cast<uword>(function());
+}
+
+
// Generate code to call into the stub which will call the runtime
// function. Input for the stub is as follows:
// RSP : points to the arguments and return value array.
@@ -23,15 +28,13 @@
void RuntimeEntry::Call(Assembler* assembler, intptr_t argument_count) const {
if (is_leaf()) {
ASSERT(argument_count == this->argument_count());
- ExternalLabel label(GetEntryPoint());
COMPILE_ASSERT(CallingConventions::kVolatileCpuRegisters & (1 << RAX));
- __ LoadExternalLabel(RAX, &label, kNotPatchable);
+ __ movq(RAX, Address(THR, Thread::OffsetFromThread(this)));
__ CallCFunction(RAX);
} else {
// Argument count is not checked here, but in the runtime entry for a more
// informative error message.
- ExternalLabel label(GetEntryPoint());
- __ LoadExternalLabel(RBX, &label, kNotPatchable);
+ __ movq(RBX, Address(THR, Thread::OffsetFromThread(this)));
__ movq(R10, Immediate(argument_count));
__ Call(*StubCode::CallToRuntime_entry());
}
diff --git a/runtime/vm/scopes.cc b/runtime/vm/scopes.cc
index f0c5080..139705a 100644
--- a/runtime/vm/scopes.cc
+++ b/runtime/vm/scopes.cc
@@ -617,19 +617,23 @@
}
-void LocalScope::RecursivelyCaptureAllVariables() {
- for (intptr_t i = 0; i < num_variables(); i++) {
- if ((VariableAt(i)->name().raw() == Symbols::StackTraceVar().raw()) ||
- (VariableAt(i)->name().raw() == Symbols::ExceptionVar().raw()) ||
- (VariableAt(i)->name().raw() == Symbols::SavedTryContextVar().raw())) {
- // Don't capture those variables because the VM expects them to be on the
- // stack.
- continue;
+void LocalScope::CaptureLocalVariables(LocalScope* top_scope) {
+ ASSERT(top_scope->function_level() == function_level());
+ LocalScope* scope = this;
+ while (scope != top_scope->parent()) {
+ for (intptr_t i = 0; i < scope->num_variables(); i++) {
+ LocalVariable* variable = scope->VariableAt(i);
+ if ((variable->name().raw() == Symbols::StackTraceVar().raw()) ||
+ (variable->name().raw() == Symbols::ExceptionVar().raw()) ||
+ (variable->name().raw() == Symbols::SavedTryContextVar().raw())) {
+ // Don't capture those variables because the VM expects them to be on
+ // the stack.
+ continue;
+ }
+ scope->CaptureVariable(variable);
}
- CaptureVariable(VariableAt(i));
+ scope = scope->parent();
}
- if (sibling() != NULL) { sibling()->RecursivelyCaptureAllVariables(); }
- if (child() != NULL) { child()->RecursivelyCaptureAllVariables(); }
}
diff --git a/runtime/vm/scopes.h b/runtime/vm/scopes.h
index b9a2b1a..5faf502 100644
--- a/runtime/vm/scopes.h
+++ b/runtime/vm/scopes.h
@@ -327,9 +327,9 @@
// from this scope and belonging to outer scopes.
RawContextScope* PreserveOuterScope(int current_context_level) const;
- // Recursively traverses all siblings and children and marks all variables as
- // captured.
- void RecursivelyCaptureAllVariables();
+ // Mark all local variables that are accessible from this scope up to
+ // top_scope (included) as captured.
+ void CaptureLocalVariables(LocalScope* top_scope);
// Creates a LocalScope representing the outer scope of a local function to be
// compiled. This outer scope contains the variables captured by the function
diff --git a/runtime/vm/service.cc b/runtime/vm/service.cc
index 5c57b1f..c0959e3 100644
--- a/runtime/vm/service.cc
+++ b/runtime/vm/service.cc
@@ -37,6 +37,9 @@
namespace dart {
+#define Z (T->zone())
+
+
DECLARE_FLAG(bool, trace_service);
DECLARE_FLAG(bool, trace_service_pause_events);
@@ -511,9 +514,9 @@
const Instance& reply_port,
const Instance& id,
const Error& error) {
- Isolate* isolate = Isolate::Current();
- StackZone zone(isolate);
- HANDLESCOPE(isolate);
+ Thread* T = Thread::Current();
+ StackZone zone(T);
+ HANDLESCOPE(T);
JSONStream js;
js.Setup(zone.GetZone(), SendPort::Cast(reply_port).Id(),
id, method_name, parameter_keys, parameter_values);
@@ -524,20 +527,22 @@
}
-void Service::InvokeMethod(Isolate* isolate, const Array& msg) {
- ASSERT(isolate != NULL);
+void Service::InvokeMethod(Isolate* I, const Array& msg) {
+ Thread* T = Thread::Current();
+ ASSERT(I == T->isolate());
+ ASSERT(I != NULL);
ASSERT(!msg.IsNull());
ASSERT(msg.Length() == 6);
{
- StackZone zone(isolate);
- HANDLESCOPE(isolate);
+ StackZone zone(T);
+ HANDLESCOPE(T);
- Instance& reply_port = Instance::Handle(isolate);
- Instance& seq = String::Handle(isolate);
- String& method_name = String::Handle(isolate);
- Array& param_keys = Array::Handle(isolate);
- Array& param_values = Array::Handle(isolate);
+ Instance& reply_port = Instance::Handle(Z);
+ Instance& seq = String::Handle(Z);
+ String& method_name = String::Handle(Z);
+ Array& param_keys = Array::Handle(Z);
+ Array& param_values = Array::Handle(Z);
reply_port ^= msg.At(1);
seq ^= msg.At(2);
method_name ^= msg.At(3);
@@ -589,7 +594,7 @@
js.PostReply();
return;
}
- if (method->entry(isolate, &js)) {
+ if (method->entry(I, &js)) {
js.PostReply();
} else {
// NOTE(turnidge): All message handlers currently return true,
@@ -610,8 +615,8 @@
return;
}
- const Instance& extension_handler =
- Instance::Handle(isolate->LookupServiceExtensionHandler(method_name));
+ const Instance& extension_handler = Instance::Handle(Z,
+ I->LookupServiceExtensionHandler(method_name));
if (!extension_handler.IsNull()) {
ScheduleExtensionHandler(extension_handler,
method_name,
@@ -650,9 +655,10 @@
if (!ServiceIsolate::IsRunning()) {
return;
}
- Isolate* isolate = Isolate::Current();
+ Thread* thread = Thread::Current();
+ Isolate* isolate = thread->isolate();
ASSERT(isolate != NULL);
- HANDLESCOPE(isolate);
+ HANDLESCOPE(thread);
const Array& list = Array::Handle(Array::New(2));
ASSERT(!list.IsNull());
@@ -1478,8 +1484,7 @@
}
MessageSnapshotReader reader(message->data(),
message->len(),
- isolate,
- Thread::Current()->zone());
+ Thread::Current());
const Object& msg_obj = Object::Handle(reader.ReadObject());
msg_obj.PrintJSON(js);
return true;
@@ -1546,6 +1551,9 @@
static bool GetInboundReferences(Isolate* isolate, JSONStream* js) {
+ Thread* thread = Thread::Current();
+ ASSERT(isolate == thread->isolate());
+
const char* target_id = js->LookupParam("targetId");
if (target_id == NULL) {
PrintMissingParamError(js, "targetId");
@@ -1565,7 +1573,7 @@
Object& obj = Object::Handle(isolate);
ObjectIdRing::LookupResult lookup_result;
{
- HANDLESCOPE(isolate);
+ HANDLESCOPE(thread);
obj = LookupHeapObject(isolate, target_id, &lookup_result);
}
if (obj.raw() == Object::sentinel().raw()) {
@@ -1645,6 +1653,9 @@
static bool GetRetainingPath(Isolate* isolate, JSONStream* js) {
+ Thread* thread = Thread::Current();
+ ASSERT(isolate == thread->isolate());
+
const char* target_id = js->LookupParam("targetId");
if (target_id == NULL) {
PrintMissingParamError(js, "targetId");
@@ -1664,7 +1675,7 @@
Object& obj = Object::Handle(isolate);
ObjectIdRing::LookupResult lookup_result;
{
- HANDLESCOPE(isolate);
+ HANDLESCOPE(thread);
obj = LookupHeapObject(isolate, target_id, &lookup_result);
}
if (obj.raw() == Object::sentinel().raw()) {
diff --git a/runtime/vm/service_isolate.cc b/runtime/vm/service_isolate.cc
index 177129d..2068e40 100644
--- a/runtime/vm/service_isolate.cc
+++ b/runtime/vm/service_isolate.cc
@@ -22,6 +22,9 @@
namespace dart {
+#define Z (T->zone())
+
+
DEFINE_FLAG(bool, trace_service, false, "Trace VM service requests.");
DEFINE_FLAG(bool, trace_service_pause_events, false,
"Trace VM service isolate pause events.");
@@ -219,15 +222,16 @@
public:
static void SendIsolateServiceMessage(Dart_NativeArguments args) {
NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
- Isolate* isolate = arguments->thread()->isolate();
- StackZone stack_zone(isolate);
+ Thread* thread = arguments->thread();
+ StackZone stack_zone(thread);
Zone* zone = stack_zone.GetZone(); // Used by GET_NON_NULL_NATIVE_ARGUMENT.
- HANDLESCOPE(isolate);
+ HANDLESCOPE(thread);
GET_NON_NULL_NATIVE_ARGUMENT(SendPort, sp, arguments->NativeArgAt(0));
GET_NON_NULL_NATIVE_ARGUMENT(Array, message, arguments->NativeArgAt(1));
// Set the type of the OOB message.
- message.SetAt(0, Smi::Handle(isolate, Smi::New(Message::kServiceOOBMsg)));
+ message.SetAt(0, Smi::Handle(thread->zone(),
+ Smi::New(Message::kServiceOOBMsg)));
// Serialize message.
uint8_t* data = NULL;
@@ -243,19 +247,20 @@
static void SendRootServiceMessage(Dart_NativeArguments args) {
NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
- Isolate* isolate = arguments->thread()->isolate();
- StackZone stack_zone(isolate);
+ Thread* thread = arguments->thread();
+ StackZone stack_zone(thread);
Zone* zone = stack_zone.GetZone(); // Used by GET_NON_NULL_NATIVE_ARGUMENT.
- HANDLESCOPE(isolate);
+ HANDLESCOPE(thread);
GET_NON_NULL_NATIVE_ARGUMENT(Array, message, arguments->NativeArgAt(0));
Service::HandleRootMessage(message);
}
static void OnStart(Dart_NativeArguments args) {
NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
- Isolate* isolate = arguments->thread()->isolate();
- StackZone zone(isolate);
- HANDLESCOPE(isolate);
+ Thread* thread = arguments->thread();
+ Isolate* isolate = thread->isolate();
+ StackZone zone(thread);
+ HANDLESCOPE(thread);
{
if (FLAG_trace_service) {
OS::Print("vm-service: Booting dart:vmservice library.\n");
@@ -287,9 +292,9 @@
static void OnExit(Dart_NativeArguments args) {
NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
- Isolate* isolate = arguments->thread()->isolate();
- StackZone zone(isolate);
- HANDLESCOPE(isolate);
+ Thread* thread = arguments->thread();
+ StackZone zone(thread);
+ HANDLESCOPE(thread);
{
if (FLAG_trace_service) {
OS::Print("vm-service: processed exit message.\n");
@@ -299,10 +304,10 @@
static void ListenStream(Dart_NativeArguments args) {
NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
- Isolate* isolate = arguments->thread()->isolate();
- StackZone stack_zone(isolate);
+ Thread* thread = arguments->thread();
+ StackZone stack_zone(thread);
Zone* zone = stack_zone.GetZone(); // Used by GET_NON_NULL_NATIVE_ARGUMENT.
- HANDLESCOPE(isolate);
+ HANDLESCOPE(thread);
GET_NON_NULL_NATIVE_ARGUMENT(String, stream_id, arguments->NativeArgAt(0));
bool result = Service::ListenStream(stream_id.ToCString());
arguments->SetReturn(Bool::Get(result));
@@ -310,10 +315,10 @@
static void CancelStream(Dart_NativeArguments args) {
NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
- Isolate* isolate = arguments->thread()->isolate();
- StackZone stack_zone(isolate);
+ Thread* thread = arguments->thread();
+ StackZone stack_zone(thread);
Zone* zone = stack_zone.GetZone(); // Used by GET_NON_NULL_NATIVE_ARGUMENT.
- HANDLESCOPE(isolate);
+ HANDLESCOPE(thread);
GET_NON_NULL_NATIVE_ARGUMENT(String, stream_id, arguments->NativeArgAt(0));
Service::CancelStream(stream_id.ToCString());
}
@@ -424,12 +429,13 @@
if (!IsRunning()) {
return false;
}
- Isolate* isolate = Isolate::Current();
+ Thread* thread = Thread::Current();
+ Isolate* isolate = thread->isolate();
if (IsServiceIsolateDescendant(isolate)) {
return false;
}
ASSERT(isolate != NULL);
- HANDLESCOPE(isolate);
+ HANDLESCOPE(thread);
const String& name = String::Handle(String::New(isolate->name()));
ASSERT(!name.IsNull());
const Array& list = Array::Handle(
@@ -455,12 +461,13 @@
if (!IsRunning()) {
return false;
}
- Isolate* isolate = Isolate::Current();
+ Thread* thread = Thread::Current();
+ Isolate* isolate = thread->isolate();
if (IsServiceIsolateDescendant(isolate)) {
return false;
}
ASSERT(isolate != NULL);
- HANDLESCOPE(isolate);
+ HANDLESCOPE(thread);
const String& name = String::Handle(String::New(isolate->name()));
ASSERT(!name.IsNull());
const Array& list = Array::Handle(
@@ -522,10 +529,12 @@
}
-void ServiceIsolate::MaybeInjectVMServiceLibrary(Isolate* isolate) {
- ASSERT(isolate != NULL);
- ASSERT(isolate->name() != NULL);
- if (!ServiceIsolate::NameEquals(isolate->name())) {
+void ServiceIsolate::MaybeInjectVMServiceLibrary(Isolate* I) {
+ Thread* T = Thread::Current();
+ ASSERT(I == T->isolate());
+ ASSERT(I != NULL);
+ ASSERT(I->name() != NULL);
+ if (!ServiceIsolate::NameEquals(I->name())) {
// Not service isolate.
return;
}
@@ -533,19 +542,19 @@
// Service isolate already exists.
return;
}
- SetServiceIsolate(isolate);
+ SetServiceIsolate(I);
- StackZone zone(isolate);
- HANDLESCOPE(isolate);
+ StackZone zone(T);
+ HANDLESCOPE(T);
// Register dart:vmservice library.
- const String& url_str = String::Handle(Symbols::DartVMService().raw());
- const Library& library = Library::Handle(Library::New(url_str));
+ const String& url_str = String::Handle(Z, Symbols::DartVMService().raw());
+ const Library& library = Library::Handle(Z, Library::New(url_str));
library.Register();
library.set_native_entry_resolver(ServiceNativeResolver);
// Temporarily install our library tag handler.
- isolate->set_library_tag_handler(LibraryTagHandler);
+ I->set_library_tag_handler(LibraryTagHandler);
// Get script source.
const char* resource = NULL;
@@ -553,17 +562,16 @@
intptr_t r = Resources::ResourceLookup(path, &resource);
ASSERT(r != Resources::kNoSuchInstance);
ASSERT(resource != NULL);
- const String& source_str = String::Handle(
+ const String& source_str = String::Handle(Z,
String::FromUTF8(reinterpret_cast<const uint8_t*>(resource), r));
ASSERT(!source_str.IsNull());
- const Script& script = Script::Handle(
- isolate, Script::New(url_str, source_str, RawScript::kLibraryTag));
+ const Script& script = Script::Handle(Z,
+ Script::New(url_str, source_str, RawScript::kLibraryTag));
// Compile script.
Dart_EnterScope(); // Need to enter scope for tag handler.
library.SetLoadInProgress();
- const Error& error = Error::Handle(isolate,
- Compiler::Compile(library, script));
+ const Error& error = Error::Handle(Z, Compiler::Compile(library, script));
if (!error.IsNull()) {
OS::PrintErr("vm-service: Isolate creation error: %s\n",
error.ToErrorCString());
@@ -574,19 +582,22 @@
Dart_ExitScope();
// Uninstall our library tag handler.
- isolate->set_library_tag_handler(NULL);
+ I->set_library_tag_handler(NULL);
}
-void ServiceIsolate::ConstructExitMessageAndCache(Isolate* isolate) {
+void ServiceIsolate::ConstructExitMessageAndCache(Isolate* I) {
// Construct and cache exit message here so we can send it without needing an
// isolate.
- StartIsolateScope iso_scope(isolate);
- StackZone zone(isolate);
- HANDLESCOPE(isolate);
+ StartIsolateScope iso_scope(I);
+ Thread* T = Thread::Current();
+ ASSERT(I == T->isolate());
+ ASSERT(I != NULL);
+ StackZone zone(T);
+ HANDLESCOPE(T);
ASSERT(exit_message_ == NULL);
ASSERT(exit_message_length_ == 0);
- const Array& list = Array::Handle(MakeServiceExitMessage());
+ const Array& list = Array::Handle(Z, MakeServiceExitMessage());
ASSERT(!list.IsNull());
MessageWriter writer(&exit_message_, &allocator, false);
writer.WriteMessage(list);
@@ -662,16 +673,18 @@
protected:
static void ShutdownIsolate(uword parameter) {
- Isolate* isolate = reinterpret_cast<Isolate*>(parameter);
- ASSERT(ServiceIsolate::IsServiceIsolate(isolate));
+ Isolate* I = reinterpret_cast<Isolate*>(parameter);
+ ASSERT(ServiceIsolate::IsServiceIsolate(I));
{
// Print the error if there is one. This may execute dart code to
// print the exception object, so we need to use a StartIsolateScope.
- StartIsolateScope start_scope(isolate);
- StackZone zone(isolate);
- HandleScope handle_scope(isolate);
- Error& error = Error::Handle();
- error = isolate->object_store()->sticky_error();
+ StartIsolateScope start_scope(I);
+ Thread* T = Thread::Current();
+ ASSERT(I == T->isolate());
+ StackZone zone(T);
+ HandleScope handle_scope(T);
+ Error& error = Error::Handle(Z);
+ error = I->object_store()->sticky_error();
if (!error.IsNull()) {
OS::PrintErr("vm-service: Error: %s\n", error.ToErrorCString());
}
@@ -679,7 +692,7 @@
}
{
// Shut the isolate down.
- SwitchIsolateScope switch_scope(isolate);
+ SwitchIsolateScope switch_scope(I);
Dart::ShutdownIsolate();
}
ServiceIsolate::SetServiceIsolate(NULL);
@@ -690,13 +703,15 @@
ServiceIsolate::FinishedExiting();
}
- void RunMain(Isolate* isolate) {
- StartIsolateScope iso_scope(isolate);
- StackZone zone(isolate);
- HANDLESCOPE(isolate);
+ void RunMain(Isolate* I) {
+ StartIsolateScope iso_scope(I);
+ Thread* T = Thread::Current();
+ ASSERT(I == T->isolate());
+ StackZone zone(T);
+ HANDLESCOPE(T);
// Invoke main which will return the loadScriptPort.
- const Library& root_library =
- Library::Handle(isolate, isolate->object_store()->root_library());
+ const Library& root_library = Library::Handle(Z,
+ I->object_store()->root_library());
if (root_library.IsNull()) {
if (FLAG_trace_service) {
OS::Print("vm-service: Embedder did not install a script.");
@@ -705,11 +720,10 @@
return;
}
ASSERT(!root_library.IsNull());
- const String& entry_name = String::Handle(isolate, String::New("main"));
+ const String& entry_name = String::Handle(Z, String::New("main"));
ASSERT(!entry_name.IsNull());
- const Function& entry =
- Function::Handle(isolate,
- root_library.LookupFunctionAllowPrivate(entry_name));
+ const Function& entry = Function::Handle(Z,
+ root_library.LookupFunctionAllowPrivate(entry_name));
if (entry.IsNull()) {
// Service isolate is not supported by embedder.
if (FLAG_trace_service) {
@@ -718,10 +732,8 @@
return;
}
ASSERT(!entry.IsNull());
- const Object& result =
- Object::Handle(isolate,
- DartEntry::InvokeFunction(entry,
- Object::empty_array()));
+ const Object& result = Object::Handle(Z,
+ DartEntry::InvokeFunction(entry, Object::empty_array()));
ASSERT(!result.IsNull());
if (result.IsError()) {
// Service isolate did not initialize properly.
diff --git a/runtime/vm/service_test.cc b/runtime/vm/service_test.cc
index f5fe86f..0bae8ad 100644
--- a/runtime/vm/service_test.cc
+++ b/runtime/vm/service_test.cc
@@ -35,10 +35,8 @@
}
// Parse the message.
- MessageSnapshotReader reader(message->data(),
- message->len(),
- Isolate::Current(),
- Thread::Current()->zone());
+ Thread* thread = Thread::Current();
+ MessageSnapshotReader reader(message->data(), message->len(), thread);
const Object& response_obj = Object::Handle(reader.ReadObject());
String& response = String::Handle();
response ^= response_obj.raw();
diff --git a/runtime/vm/snapshot.cc b/runtime/vm/snapshot.cc
index 415d1ed..5ab4697 100644
--- a/runtime/vm/snapshot.cc
+++ b/runtime/vm/snapshot.cc
@@ -16,6 +16,7 @@
#include "vm/object.h"
#include "vm/object_store.h"
#include "vm/snapshot_ids.h"
+#include "vm/stub_code.h"
#include "vm/symbols.h"
#include "vm/verified_memory.h"
#include "vm/version.h"
@@ -23,7 +24,7 @@
// We currently only expect the Dart mutator to read snapshots.
#define ASSERT_NO_SAFEPOINT_SCOPE() \
isolate()->AssertCurrentThreadIsMutator(); \
- ASSERT(Thread::Current()->no_safepoint_scope_depth() != 0)
+ ASSERT(thread()->no_safepoint_scope_depth() != 0)
namespace dart {
@@ -171,35 +172,41 @@
SnapshotReader::SnapshotReader(
const uint8_t* buffer,
intptr_t size,
+ const uint8_t* instructions_buffer,
Snapshot::Kind kind,
ZoneGrowableArray<BackRefNode>* backward_refs,
- Isolate* isolate,
- Zone* zone)
+ Thread* thread)
: BaseReader(buffer, size),
+ instructions_buffer_(instructions_buffer),
kind_(kind),
- snapshot_code_(false),
- isolate_(isolate),
- zone_(zone),
- heap_(isolate->heap()),
- old_space_(isolate->heap()->old_space()),
- cls_(Class::Handle(isolate)),
- obj_(Object::Handle(isolate)),
- pobj_(PassiveObject::Handle(isolate)),
- array_(Array::Handle(isolate)),
- field_(Field::Handle(isolate)),
- str_(String::Handle(isolate)),
- library_(Library::Handle(isolate)),
- type_(AbstractType::Handle(isolate)),
- type_arguments_(TypeArguments::Handle(isolate)),
- tokens_(Array::Handle(isolate)),
- stream_(TokenStream::Handle(isolate)),
- data_(ExternalTypedData::Handle(isolate)),
- typed_data_(TypedData::Handle(isolate)),
- error_(UnhandledException::Handle(isolate)),
+ snapshot_code_(instructions_buffer != NULL),
+ thread_(thread),
+ zone_(thread->zone()),
+ heap_(isolate()->heap()),
+ old_space_(thread_->isolate()->heap()->old_space()),
+ cls_(Class::Handle(zone_)),
+ obj_(Object::Handle(zone_)),
+ pobj_(PassiveObject::Handle(zone_)),
+ array_(Array::Handle(zone_)),
+ field_(Field::Handle(zone_)),
+ str_(String::Handle(zone_)),
+ library_(Library::Handle(zone_)),
+ type_(AbstractType::Handle(zone_)),
+ type_arguments_(TypeArguments::Handle(zone_)),
+ tokens_(Array::Handle(zone_)),
+ stream_(TokenStream::Handle(zone_)),
+ data_(ExternalTypedData::Handle(zone_)),
+ typed_data_(TypedData::Handle(zone_)),
+ code_(Code::Handle(zone_)),
+ error_(UnhandledException::Handle(zone_)),
max_vm_isolate_object_id_(
(kind == Snapshot::kFull) ?
Object::vm_isolate_snapshot_object_table().Length() : 0),
- backward_references_(backward_refs) {
+ backward_references_(backward_refs),
+ instructions_reader_(NULL) {
+ if (instructions_buffer != NULL) {
+ instructions_reader_ = new InstructionsReader(instructions_buffer);
+ }
}
@@ -304,21 +311,19 @@
void SnapshotReader::SetReadException(const char* msg) {
- Thread* thread = Thread::Current();
- Zone* zone = thread->zone();
- const String& error_str = String::Handle(zone, String::New(msg));
- const Array& args = Array::Handle(zone, Array::New(1));
+ const String& error_str = String::Handle(zone(), String::New(msg));
+ const Array& args = Array::Handle(zone(), Array::New(1));
args.SetAt(0, error_str);
- Object& result = Object::Handle(zone);
- const Library& library = Library::Handle(zone, Library::CoreLibrary());
+ Object& result = Object::Handle(zone());
+ const Library& library = Library::Handle(zone(), Library::CoreLibrary());
result = DartLibraryCalls::InstanceCreate(library,
Symbols::ArgumentError(),
Symbols::Dot(),
args);
- const Stacktrace& stacktrace = Stacktrace::Handle(zone);
+ const Stacktrace& stacktrace = Stacktrace::Handle(zone());
const UnhandledException& error = UnhandledException::Handle(
- zone, UnhandledException::New(Instance::Cast(result), stacktrace));
- thread->long_jump_base()->Jump(1, error);
+ zone(), UnhandledException::New(Instance::Cast(result), stacktrace));
+ thread()->long_jump_base()->Jump(1, error);
}
@@ -328,7 +333,7 @@
bool SnapshotReader::is_vm_isolate() const {
- return isolate_ == Dart::vm_isolate();
+ return isolate() == Dart::vm_isolate();
}
@@ -505,7 +510,9 @@
ASSERT(!cls_.IsNull());
instance_size = cls_.instance_size();
}
- intptr_t next_field_offset = cls_.next_field_offset();
+ intptr_t next_field_offset = Class::IsSignatureClass(cls_.raw())
+ ? Closure::InstanceSize() : cls_.next_field_offset();
+
intptr_t type_argument_field_offset = cls_.type_arguments_field_offset();
ASSERT(next_field_offset > 0);
// Instance::NextFieldOffset() returns the offset of the first field in
@@ -778,6 +785,82 @@
}
+RawObjectPool* SnapshotReader::NewObjectPool(intptr_t len) {
+ ASSERT(kind_ == Snapshot::kFull);
+ ASSERT_NO_SAFEPOINT_SCOPE();
+ RawObjectPool* obj = reinterpret_cast<RawObjectPool*>(
+ AllocateUninitialized(kObjectPoolCid, ObjectPool::InstanceSize(len)));
+ obj->ptr()->length_ = len;
+ return obj;
+}
+
+
+RawLocalVarDescriptors* SnapshotReader::NewLocalVarDescriptors(
+ intptr_t num_entries) {
+ ASSERT(kind_ == Snapshot::kFull);
+ ASSERT_NO_SAFEPOINT_SCOPE();
+ RawLocalVarDescriptors* obj = reinterpret_cast<RawLocalVarDescriptors*>(
+ AllocateUninitialized(kLocalVarDescriptorsCid,
+ LocalVarDescriptors::InstanceSize(num_entries)));
+ obj->ptr()->num_entries_ = num_entries;
+ return obj;
+}
+
+
+RawExceptionHandlers* SnapshotReader::NewExceptionHandlers(
+ intptr_t num_entries) {
+ ASSERT(kind_ == Snapshot::kFull);
+ ASSERT_NO_SAFEPOINT_SCOPE();
+ RawExceptionHandlers* obj = reinterpret_cast<RawExceptionHandlers*>(
+ AllocateUninitialized(kExceptionHandlersCid,
+ ExceptionHandlers::InstanceSize(num_entries)));
+ obj->ptr()->num_entries_ = num_entries;
+ return obj;
+}
+
+
+RawPcDescriptors* SnapshotReader::NewPcDescriptors(intptr_t len) {
+ ASSERT(kind_ == Snapshot::kFull);
+ ASSERT_NO_SAFEPOINT_SCOPE();
+ RawPcDescriptors* obj = reinterpret_cast<RawPcDescriptors*>(
+ AllocateUninitialized(kPcDescriptorsCid,
+ PcDescriptors::InstanceSize(len)));
+ obj->ptr()->length_ = len;
+ return obj;
+}
+
+
+RawStackmap* SnapshotReader::NewStackmap(intptr_t len) {
+ ASSERT(kind_ == Snapshot::kFull);
+ ASSERT_NO_SAFEPOINT_SCOPE();
+ RawStackmap* obj = reinterpret_cast<RawStackmap*>(
+ AllocateUninitialized(kStackmapCid, Stackmap::InstanceSize(len)));
+ obj->ptr()->length_ = len;
+ return obj;
+}
+
+
+RawContextScope* SnapshotReader::NewContextScope(intptr_t num_variables) {
+ ASSERT(kind_ == Snapshot::kFull);
+ ASSERT_NO_SAFEPOINT_SCOPE();
+ RawContextScope* obj = reinterpret_cast<RawContextScope*>(
+ AllocateUninitialized(kContextScopeCid,
+ ContextScope::InstanceSize(num_variables)));
+ obj->ptr()->num_variables_ = num_variables;
+ return obj;
+}
+
+
+RawCode* SnapshotReader::NewCode(intptr_t pointer_offsets_length) {
+ ASSERT(pointer_offsets_length == 0);
+ ASSERT(kind_ == Snapshot::kFull);
+ ASSERT_NO_SAFEPOINT_SCOPE();
+ RawCode* obj = reinterpret_cast<RawCode*>(
+ AllocateUninitialized(kCodeCid, Code::InstanceSize(0)));
+ return obj;
+}
+
+
RawTokenStream* SnapshotReader::NewTokenStream(intptr_t len) {
ASSERT(kind_ == Snapshot::kFull);
ASSERT_NO_SAFEPOINT_SCOPE();
@@ -927,22 +1010,16 @@
}
-RawCode* SnapshotReader::NewCode(intptr_t pointer_offsets_length) {
- ASSERT(pointer_offsets_length == 0);
- ALLOC_NEW_OBJECT(Code);
-}
-
-
-RawObjectPool* SnapshotReader::NewObjectPool(intptr_t length) {
- ALLOC_NEW_OBJECT(ObjectPool);
-}
-
-
RawICData* SnapshotReader::NewICData() {
ALLOC_NEW_OBJECT(ICData);
}
+RawLinkedHashMap* SnapshotReader::NewLinkedHashMap() {
+ ALLOC_NEW_OBJECT(LinkedHashMap);
+}
+
+
RawMegamorphicCache* SnapshotReader::NewMegamorphicCache() {
ALLOC_NEW_OBJECT(MegamorphicCache);
}
@@ -1060,8 +1137,36 @@
}
-RawInstructions* SnapshotReader::GetInstructionsById(int32_t id) {
- // TODO(rmacnak): Read from shared library.
+int32_t InstructionsWriter::GetOffsetFor(RawInstructions* instructions) {
+ // Instructions are allocated with the code alignment and we don't write
+ // anything else in the text section.
+ ASSERT(Utils::IsAligned(stream_.bytes_written(),
+ OS::PreferredCodeAlignment()));
+
+ intptr_t offset = stream_.bytes_written();
+ stream_.WriteBytes(reinterpret_cast<uint8_t*>(instructions) - kHeapObjectTag,
+ instructions->Size());
+ return offset;
+}
+
+
+RawInstructions* InstructionsReader::GetInstructionsAt(int32_t offset,
+ uword expected_tags) {
+ ASSERT(Utils::IsAligned(offset, OS::PreferredCodeAlignment()));
+
+ RawInstructions* result =
+ reinterpret_cast<RawInstructions*>(
+ reinterpret_cast<uword>(buffer_) + offset + kHeapObjectTag);
+
+ uword actual_tags = result->ptr()->tags_;
+ if (actual_tags != expected_tags) {
+ FATAL2("Instructions tag mismatch: expected %" Pd ", saw %" Pd,
+ expected_tags,
+ actual_tags);
+ }
+
+ // TODO(rmacnak): The above contains stale pointers to a Code and an
+ // ObjectPool. Return the actual result after calling convention change.
return Instructions::null();
}
@@ -1076,7 +1181,7 @@
}
ASSERT(SerializedHeaderTag::decode(class_header) == kObjectId);
intptr_t class_id = SerializedHeaderData::decode(class_header);
- ASSERT(IsObjectStoreClassId(class_id));
+ ASSERT(IsObjectStoreClassId(class_id) || IsSingletonClassId(class_id));
return class_id;
}
@@ -1099,7 +1204,7 @@
// read part and return the error object back.
const UnhandledException& error = UnhandledException::Handle(
object_store()->preallocated_unhandled_exception());
- Thread::Current()->long_jump_base()->Jump(1, error);
+ thread()->long_jump_base()->Jump(1, error);
}
VerifiedMemory::Accept(address, size);
@@ -1274,16 +1379,18 @@
}
-VmIsolateSnapshotReader::VmIsolateSnapshotReader(const uint8_t* buffer,
- intptr_t size,
- Zone* zone)
- : SnapshotReader(buffer,
- size,
- Snapshot::kFull,
- new ZoneGrowableArray<BackRefNode>(
- kNumVmIsolateSnapshotReferences),
- Dart::vm_isolate(),
- zone) {
+VmIsolateSnapshotReader::VmIsolateSnapshotReader(
+ const uint8_t* buffer,
+ intptr_t size,
+ const uint8_t* instructions_buffer,
+ Thread* thread)
+ : SnapshotReader(buffer,
+ size,
+ instructions_buffer,
+ Snapshot::kFull,
+ new ZoneGrowableArray<BackRefNode>(
+ kNumVmIsolateSnapshotReferences),
+ thread) {
}
@@ -1296,6 +1403,7 @@
i, *(backrefs->At(i).reference()));
}
ResetBackwardReferenceTable();
+ Object::set_instructions_snapshot_buffer(instructions_buffer_);
}
@@ -1329,6 +1437,29 @@
// only memory.
*(ArrayHandle()) ^= ReadObject();
+
+ if (snapshot_code()) {
+ for (intptr_t i = 0;
+ i < ArgumentsDescriptor::kCachedDescriptorCount;
+ i++) {
+ *(ArrayHandle()) ^= ReadObject();
+ // TODO(rmacnak):
+ // ArgumentsDescriptor::InitOnceFromSnapshot(i, *(ArrayHandle()));
+ }
+
+ ObjectPool::CheckedHandle(ReadObject()); // empty pool
+ PcDescriptors::CheckedHandle(ReadObject()); // empty pc desc
+ LocalVarDescriptors::CheckedHandle(ReadObject()); // empty var desc
+ ExceptionHandlers::CheckedHandle(ReadObject()); // empty exc handlers
+
+#define READ_STUB(name) \
+ *(CodeHandle()) ^= ReadObject();
+ // TODO(rmacnak):
+ // StubCode::name##_entry()->InitOnceFromSnapshot(CodeHandle())
+ VM_STUB_CODE_LIST(READ_STUB);
+#undef READ_STUB
+ }
+
// Validate the class table.
#if defined(DEBUG)
isolate->ValidateClassTable();
@@ -1341,15 +1472,15 @@
IsolateSnapshotReader::IsolateSnapshotReader(const uint8_t* buffer,
intptr_t size,
- Isolate* isolate,
- Zone* zone)
+ const uint8_t* instructions_buffer,
+ Thread* thread)
: SnapshotReader(buffer,
size,
+ instructions_buffer,
Snapshot::kFull,
new ZoneGrowableArray<BackRefNode>(
kNumInitialReferencesInFullSnapshot),
- isolate,
- zone) {
+ thread) {
}
@@ -1360,14 +1491,13 @@
ScriptSnapshotReader::ScriptSnapshotReader(const uint8_t* buffer,
intptr_t size,
- Isolate* isolate,
- Zone* zone)
+ Thread* thread)
: SnapshotReader(buffer,
size,
+ NULL, /* instructions_buffer */
Snapshot::kScript,
new ZoneGrowableArray<BackRefNode>(kNumInitialReferences),
- isolate,
- zone) {
+ thread) {
}
@@ -1378,14 +1508,13 @@
MessageSnapshotReader::MessageSnapshotReader(const uint8_t* buffer,
intptr_t size,
- Isolate* isolate,
- Zone* zone)
+ Thread* thread)
: SnapshotReader(buffer,
size,
+ NULL, /* instructions_buffer */
Snapshot::kMessage,
new ZoneGrowableArray<BackRefNode>(kNumInitialReferences),
- isolate,
- zone) {
+ thread) {
}
@@ -1399,19 +1528,23 @@
ReAlloc alloc,
intptr_t initial_size,
ForwardList* forward_list,
+ InstructionsWriter* instructions_writer,
bool can_send_any_object,
- bool snapshot_code)
+ bool snapshot_code,
+ bool vm_isolate_is_symbolic)
: BaseWriter(buffer, alloc, initial_size),
kind_(kind),
- isolate_(Isolate::Current()),
- object_store_(isolate_->object_store()),
- class_table_(isolate_->class_table()),
+ thread_(Thread::Current()),
+ object_store_(thread_->isolate()->object_store()),
+ class_table_(thread_->isolate()->class_table()),
forward_list_(forward_list),
+ instructions_writer_(instructions_writer),
exception_type_(Exceptions::kNone),
exception_msg_(NULL),
unmarked_objects_(false),
can_send_any_object_(can_send_any_object),
- snapshot_code_(snapshot_code) {
+ snapshot_code_(snapshot_code),
+ vm_isolate_is_symbolic_(vm_isolate_is_symbolic) {
ASSERT(forward_list_ != NULL);
}
@@ -1433,80 +1566,80 @@
object_id = forward_list_->AddObject(rawobj, kIsSerialized); \
Raw##clazz* raw_obj = reinterpret_cast<Raw##clazz*>(rawobj); \
raw_obj->WriteTo(this, object_id, kind()); \
- return; \
+ return true; \
} \
-void SnapshotWriter::HandleVMIsolateObject(RawObject* rawobj) {
+bool SnapshotWriter::HandleVMIsolateObject(RawObject* rawobj) {
// Check if it is a singleton null object.
if (rawobj == Object::null()) {
WriteVMIsolateObject(kNullObject);
- return;
+ return true;
}
// Check if it is a singleton sentinel object.
if (rawobj == Object::sentinel().raw()) {
WriteVMIsolateObject(kSentinelObject);
- return;
+ return true;
}
// Check if it is a singleton sentinel object.
if (rawobj == Object::transition_sentinel().raw()) {
WriteVMIsolateObject(kTransitionSentinelObject);
- return;
+ return true;
}
// Check if it is a singleton empty array object.
if (rawobj == Object::empty_array().raw()) {
WriteVMIsolateObject(kEmptyArrayObject);
- return;
+ return true;
}
// Check if it is a singleton zero array object.
if (rawobj == Object::zero_array().raw()) {
WriteVMIsolateObject(kZeroArrayObject);
- return;
+ return true;
}
// Check if it is a singleton dyanmic Type object.
if (rawobj == Object::dynamic_type()) {
WriteVMIsolateObject(kDynamicType);
- return;
+ return true;
}
// Check if it is a singleton void Type object.
if (rawobj == Object::void_type()) {
WriteVMIsolateObject(kVoidType);
- return;
+ return true;
}
// Check if it is a singleton boolean true object.
if (rawobj == Bool::True().raw()) {
WriteVMIsolateObject(kTrueValue);
- return;
+ return true;
}
// Check if it is a singleton boolean false object.
if (rawobj == Bool::False().raw()) {
WriteVMIsolateObject(kFalseValue);
- return;
+ return true;
}
// Check if it is a singleton extractor parameter types array.
if (rawobj == Object::extractor_parameter_types().raw()) {
WriteVMIsolateObject(kExtractorParameterTypes);
- return;
+ return true;
}
// Check if it is a singleton extractor parameter names array.
if (rawobj == Object::extractor_parameter_names().raw()) {
WriteVMIsolateObject(kExtractorParameterNames);
- return;
+ return true;
}
// Check if it is a singleton empty context scope object.
if (rawobj == Object::empty_context_scope().raw()) {
WriteVMIsolateObject(kEmptyContextScopeObject);
- return;
+ return true;
}
// Check if it is a singleton class object which is shared by
@@ -1518,7 +1651,7 @@
if (IsSingletonClassId(class_id)) {
intptr_t object_id = ObjectIdFromClassId(class_id);
WriteVMIsolateObject(object_id);
- return;
+ return true;
}
}
@@ -1527,14 +1660,14 @@
id = Symbols::LookupVMSymbol(rawobj);
if (id != kInvalidIndex) {
WriteVMIsolateObject(id);
- return;
+ return true;
}
// Check if it is an object from the vm isolate snapshot object table.
id = FindVmSnapshotObject(rawobj);
if (id != kInvalidIndex) {
WriteIndexedObject(id);
- return;
+ return true;
}
} else {
// In the case of script snapshots or for messages we do not use
@@ -1543,7 +1676,7 @@
intptr_t object_id = forward_list_->FindObject(rawobj);
if (object_id != -1) {
WriteIndexedObject(object_id);
- return;
+ return true;
} else {
switch (id) {
VM_OBJECT_CLASS_LIST(VM_OBJECT_WRITE)
@@ -1551,7 +1684,7 @@
object_id = forward_list_->AddObject(rawobj, kIsSerialized);
RawTypedData* raw_obj = reinterpret_cast<RawTypedData*>(rawobj);
raw_obj->WriteTo(this, object_id, kind());
- return;
+ return true;
}
default:
OS::Print("class id = %" Pd "\n", id);
@@ -1560,8 +1693,13 @@
}
}
+ if (!vm_isolate_is_symbolic()) {
+ return false;
+ }
+
const Object& obj = Object::Handle(rawobj);
FATAL1("Unexpected reference to object in VM isolate: %s\n", obj.ToCString());
+ return false;
}
#undef VM_OBJECT_WRITE
@@ -1606,18 +1744,24 @@
FullSnapshotWriter::FullSnapshotWriter(uint8_t** vm_isolate_snapshot_buffer,
uint8_t** isolate_snapshot_buffer,
+ uint8_t** instructions_snapshot_buffer,
ReAlloc alloc,
- bool snapshot_code)
+ bool snapshot_code,
+ bool vm_isolate_is_symbolic)
: isolate_(Isolate::Current()),
vm_isolate_snapshot_buffer_(vm_isolate_snapshot_buffer),
isolate_snapshot_buffer_(isolate_snapshot_buffer),
+ instructions_snapshot_buffer_(instructions_snapshot_buffer),
alloc_(alloc),
vm_isolate_snapshot_size_(0),
isolate_snapshot_size_(0),
+ instructions_snapshot_size_(0),
forward_list_(NULL),
+ instructions_writer_(NULL),
scripts_(Array::Handle(isolate_)),
symbol_table_(Array::Handle(isolate_)),
- snapshot_code_(snapshot_code) {
+ snapshot_code_(snapshot_code),
+ vm_isolate_is_symbolic_(vm_isolate_is_symbolic) {
ASSERT(isolate_snapshot_buffer_ != NULL);
ASSERT(alloc_ != NULL);
ASSERT(isolate_ != NULL);
@@ -1651,6 +1795,12 @@
forward_list_ = new ForwardList(SnapshotWriter::FirstObjectId());
ASSERT(forward_list_ != NULL);
+
+ if (instructions_snapshot_buffer != NULL) {
+ instructions_writer_ = new InstructionsWriter(instructions_snapshot_buffer,
+ alloc,
+ kInitialSize);
+ }
}
@@ -1668,8 +1818,10 @@
alloc_,
kInitialSize,
forward_list_,
+ instructions_writer_,
true, /* can_send_any_object */
- snapshot_code_);
+ snapshot_code_,
+ vm_isolate_is_symbolic_);
// Write full snapshot for the VM isolate.
// Setup for long jump in case there is an exception while writing
// the snapshot.
@@ -1695,8 +1847,26 @@
// read only memory.
writer.WriteObject(scripts_.raw());
- // Write out all forwarded objects.
- writer.WriteForwardedObjects();
+ if (snapshot_code_) {
+ ASSERT(!vm_isolate_is_symbolic_);
+
+ for (intptr_t i = 0;
+ i < ArgumentsDescriptor::kCachedDescriptorCount;
+ i++) {
+ writer.WriteObject(ArgumentsDescriptor::cached_args_descriptors_[i]);
+ }
+
+ writer.WriteObject(Object::empty_object_pool().raw());
+ writer.WriteObject(Object::empty_descriptors().raw());
+ writer.WriteObject(Object::empty_var_descriptors().raw());
+ writer.WriteObject(Object::empty_exception_handlers().raw());
+
+#define WRITE_STUB(name) \
+ writer.WriteObject(StubCode::name##_entry()->code());
+ VM_STUB_CODE_LIST(WRITE_STUB);
+#undef WRITE_STUB
+ }
+
writer.FillHeader(writer.kind());
@@ -1713,8 +1883,10 @@
alloc_,
kInitialSize,
forward_list_,
+ instructions_writer_,
true, /* can_send_any_object */
- snapshot_code_);
+ snapshot_code_,
+ true /* vm_isolate_is_symbolic */);
ObjectStore* object_store = isolate_->object_store();
ASSERT(object_store != NULL);
@@ -1749,22 +1921,50 @@
}
-void FullSnapshotWriter::WriteFullSnapshot() {
- if (vm_isolate_snapshot_buffer() != NULL) {
- WriteVmIsolateSnapshot();
+class WritableVMIsolateScope : StackResource {
+ public:
+ explicit WritableVMIsolateScope(Thread* thread) : StackResource(thread) {
+ Dart::vm_isolate()->heap()->WriteProtect(false);
}
- WriteIsolateFullSnapshot();
+
+ ~WritableVMIsolateScope() {
+ ASSERT(Dart::vm_isolate()->heap()->UsedInWords(Heap::kNew) == 0);
+ Dart::vm_isolate()->heap()->WriteProtect(true);
+ }
+};
+
+
+void FullSnapshotWriter::WriteFullSnapshot() {
+ if (!vm_isolate_is_symbolic_) {
+ // TODO(asiva): Don't mutate object headers during serialization.
+ WritableVMIsolateScope scope(Thread::Current());
+
+ if (vm_isolate_snapshot_buffer() != NULL) {
+ WriteVmIsolateSnapshot();
+ }
+ WriteIsolateFullSnapshot();
+
+ instructions_snapshot_size_ = instructions_writer_->BytesWritten();
+ } else {
+ if (vm_isolate_snapshot_buffer() != NULL) {
+ WriteVmIsolateSnapshot();
+ }
+ WriteIsolateFullSnapshot();
+ }
}
PrecompiledSnapshotWriter::PrecompiledSnapshotWriter(
uint8_t** vm_isolate_snapshot_buffer,
uint8_t** isolate_snapshot_buffer,
+ uint8_t** instructions_snapshot_buffer,
ReAlloc alloc)
: FullSnapshotWriter(vm_isolate_snapshot_buffer,
isolate_snapshot_buffer,
+ instructions_snapshot_buffer,
alloc,
- true /* snapshot_code */) {
+ true, /* snapshot_code */
+ false /* vm_isolate_is_symbolic */) {
}
@@ -1894,8 +2094,7 @@
// Now check if it is an object from the VM isolate (NOTE: premarked objects
// are considered to be objects in the VM isolate). These objects are shared
// by all isolates.
- if (rawobj->IsVMHeapObject()) {
- HandleVMIsolateObject(rawobj);
+ if (rawobj->IsVMHeapObject() && HandleVMIsolateObject(rawobj)) {
return true;
}
@@ -2087,7 +2286,9 @@
#undef SNAPSHOT_WRITE
default: break;
}
- UNREACHABLE();
+
+ const Object& obj = Object::Handle(raw);
+ FATAL1("Unexpected inlined object: %s\n", obj.ToCString());
}
@@ -2218,7 +2419,7 @@
}
// Not a closure of a top level method or static function, throw an
// exception as we do not allow these objects to be serialized.
- HANDLESCOPE(isolate());
+ HANDLESCOPE(thread());
const Class& clazz = Class::Handle(isolate(), cls);
const Function& errorFunc = Function::Handle(isolate(), func);
@@ -2230,7 +2431,7 @@
UnmarkAll(); // Unmark objects now as we are about to print stuff.
intptr_t len = OS::SNPrint(NULL, 0, format,
clazz.ToCString(), errorFunc.ToCString()) + 1;
- char* chars = Thread::Current()->zone()->Alloc<char>(len);
+ char* chars = thread()->zone()->Alloc<char>(len);
OS::SNPrint(chars, len, format, clazz.ToCString(), errorFunc.ToCString());
SetWriteException(Exceptions::kArgument, chars);
}
@@ -2253,13 +2454,13 @@
void SnapshotWriter::CheckForNativeFields(RawClass* cls) {
if (cls->ptr()->num_native_fields_ != 0) {
// We do not allow objects with native fields in an isolate message.
- HANDLESCOPE(isolate());
+ HANDLESCOPE(thread());
const char* format = "Illegal argument in isolate message"
" : (object extends NativeWrapper - %s)";
UnmarkAll(); // Unmark objects now as we are about to print stuff.
const Class& clazz = Class::Handle(isolate(), cls);
intptr_t len = OS::SNPrint(NULL, 0, format, clazz.ToCString()) + 1;
- char* chars = Thread::Current()->zone()->Alloc<char>(len);
+ char* chars = thread()->zone()->Alloc<char>(len);
OS::SNPrint(chars, len, format, clazz.ToCString());
SetWriteException(Exceptions::kArgument, chars);
}
@@ -2283,12 +2484,14 @@
// Check if the instance has native fields and throw an exception if it does.
CheckForNativeFields(cls);
- // Check if object is a closure that is serializable, if the object is a
- // closure that is not serializable this will throw an exception.
- RawFunction* func = IsSerializableClosure(cls, raw);
- if (func != Function::null()) {
- WriteStaticImplicitClosure(object_id, func, tags);
- return;
+ if ((kind() == Snapshot::kMessage) || (kind() == Snapshot::kScript)) {
+ // Check if object is a closure that is serializable, if the object is a
+ // closure that is not serializable this will throw an exception.
+ RawFunction* func = IsSerializableClosure(cls, raw);
+ if (func != Function::null()) {
+ WriteStaticImplicitClosure(object_id, func, tags);
+ return;
+ }
}
// Object is regular dart instance.
@@ -2418,8 +2621,10 @@
alloc,
kInitialSize,
&forward_list_,
+ NULL, /* instructions_writer */
true, /* can_send_any_object */
- false /* snapshot_code */),
+ false, /* snapshot_code */
+ true /* vm_isolate_is_symbolic */),
forward_list_(kMaxPredefinedObjectIds) {
ASSERT(buffer != NULL);
ASSERT(alloc != NULL);
@@ -2473,8 +2678,10 @@
alloc,
kInitialSize,
&forward_list_,
+ NULL, /* instructions_writer */
can_send_any_object,
- false /* snapshot_code */),
+ false, /* snapshot_code */
+ true /* vm_isolate_is_symbolic */),
forward_list_(kMaxPredefinedObjectIds) {
ASSERT(buffer != NULL);
ASSERT(alloc != NULL);
diff --git a/runtime/vm/snapshot.h b/runtime/vm/snapshot.h
index d58490e..d84d3fe 100644
--- a/runtime/vm/snapshot.h
+++ b/runtime/vm/snapshot.h
@@ -39,7 +39,9 @@
class RawClass;
class RawClosureData;
class RawContext;
+class RawContextScope;
class RawDouble;
+class RawExceptionHandlers;
class RawField;
class RawFloat32x4;
class RawFloat64x2;
@@ -54,6 +56,7 @@
class RawLibraryPrefix;
class RawLinkedHashMap;
class RawLiteralToken;
+class RawLocalVarDescriptors;
class RawMegamorphicCache;
class RawMint;
class RawMixinAppType;
@@ -63,11 +66,13 @@
class RawObjectPool;
class RawOneByteString;
class RawPatchClass;
+class RawPcDescriptors;
class RawReceivePort;
class RawRedirectionData;
class RawScript;
class RawSendPort;
class RawSmi;
+class RawStackmap;
class RawStacktrace;
class RawSubtypeTestCache;
class RawTokenStream;
@@ -295,14 +300,33 @@
};
+class InstructionsReader : public ZoneAllocated {
+ public:
+ explicit InstructionsReader(const uint8_t* buffer)
+ : buffer_(buffer) {
+ ASSERT(buffer != NULL);
+ ASSERT(Utils::IsAligned(reinterpret_cast<uword>(buffer),
+ OS::PreferredCodeAlignment()));
+ }
+
+ RawInstructions* GetInstructionsAt(int32_t offset, uword expected_tags);
+
+ private:
+ const uint8_t* buffer_;
+
+ DISALLOW_COPY_AND_ASSIGN(InstructionsReader);
+};
+
+
// Reads a snapshot into objects.
class SnapshotReader : public BaseReader {
public:
+ Thread* thread() const { return thread_; }
Zone* zone() const { return zone_; }
- Isolate* isolate() const { return isolate_; }
+ Isolate* isolate() const { return thread_->isolate(); }
Heap* heap() const { return heap_; }
- ObjectStore* object_store() const { return isolate_->object_store(); }
- ClassTable* class_table() const { return isolate_->class_table(); }
+ ObjectStore* object_store() const { return isolate()->object_store(); }
+ ClassTable* class_table() const { return isolate()->class_table(); }
PassiveObject* PassiveObjectHandle() { return &pobj_; }
Array* ArrayHandle() { return &array_; }
String* StringHandle() { return &str_; }
@@ -312,6 +336,7 @@
TokenStream* StreamHandle() { return &stream_; }
ExternalTypedData* DataHandle() { return &data_; }
TypedData* TypedDataHandle() { return &typed_data_; }
+ Code* CodeHandle() { return &code_; }
Snapshot::Kind kind() const { return kind_; }
bool snapshot_code() const { return snapshot_code_; }
@@ -364,9 +389,15 @@
RawFunction* NewFunction();
RawCode* NewCode(intptr_t pointer_offsets_length);
RawObjectPool* NewObjectPool(intptr_t length);
+ RawPcDescriptors* NewPcDescriptors(intptr_t length);
+ RawLocalVarDescriptors* NewLocalVarDescriptors(intptr_t num_entries);
+ RawExceptionHandlers* NewExceptionHandlers(intptr_t num_entries);
+ RawStackmap* NewStackmap(intptr_t length);
+ RawContextScope* NewContextScope(intptr_t num_variables);
RawICData* NewICData();
RawMegamorphicCache* NewMegamorphicCache();
RawSubtypeTestCache* NewSubtypeTestCache();
+ RawLinkedHashMap* NewLinkedHashMap();
RawField* NewField();
RawLibrary* NewLibrary();
RawLibraryPrefix* NewLibraryPrefix();
@@ -383,15 +414,19 @@
RawObject* NewInteger(int64_t value);
RawStacktrace* NewStacktrace();
- RawInstructions* GetInstructionsById(int32_t id);
+ RawInstructions* GetInstructionsAt(int32_t offset, uword expected_tags) {
+ return instructions_reader_->GetInstructionsAt(offset, expected_tags);
+ }
+
+ const uint8_t* instructions_buffer_;
protected:
SnapshotReader(const uint8_t* buffer,
intptr_t size,
+ const uint8_t* instructions_buffer,
Snapshot::Kind kind,
ZoneGrowableArray<BackRefNode>* backward_references,
- Isolate* isolate,
- Zone* zone);
+ Thread* thread);
~SnapshotReader() { }
ZoneGrowableArray<BackRefNode>* GetBackwardReferenceTable() const {
@@ -466,7 +501,7 @@
Snapshot::Kind kind_; // Indicates type of snapshot(full, script, message).
bool snapshot_code_;
- Isolate* isolate_; // Current isolate.
+ Thread* thread_; // Current thread.
Zone* zone_; // Zone for allocations while reading snapshot.
Heap* heap_; // Heap of the current isolate.
PageSpace* old_space_; // Old space of the current isolate.
@@ -483,9 +518,11 @@
TokenStream& stream_; // Temporary token stream handle.
ExternalTypedData& data_; // Temporary stream data handle.
TypedData& typed_data_; // Temporary typed data handle.
+ Code& code_; // Temporary code handle.
UnhandledException& error_; // Error handle.
intptr_t max_vm_isolate_object_id_;
ZoneGrowableArray<BackRefNode>* backward_references_;
+ InstructionsReader* instructions_reader_;
friend class ApiError;
friend class Array;
@@ -502,6 +539,7 @@
friend class GrowableObjectArray;
friend class ICData;
friend class ImmutableArray;
+ friend class Instructions;
friend class JSRegExp;
friend class LanguageError;
friend class Library;
@@ -533,7 +571,10 @@
class VmIsolateSnapshotReader : public SnapshotReader {
public:
- VmIsolateSnapshotReader(const uint8_t* buffer, intptr_t size, Zone* zone);
+ VmIsolateSnapshotReader(const uint8_t* buffer,
+ intptr_t size,
+ const uint8_t* instructions_buffer,
+ Thread* thread);
~VmIsolateSnapshotReader();
RawApiError* ReadVmIsolateSnapshot();
@@ -547,8 +588,8 @@
public:
IsolateSnapshotReader(const uint8_t* buffer,
intptr_t size,
- Isolate* isolate,
- Zone* zone);
+ const uint8_t* instructions_buffer,
+ Thread* thread);
~IsolateSnapshotReader();
private:
@@ -560,8 +601,7 @@
public:
ScriptSnapshotReader(const uint8_t* buffer,
intptr_t size,
- Isolate* isolate,
- Zone* zone);
+ Thread* thread);
~ScriptSnapshotReader();
private:
@@ -573,8 +613,7 @@
public:
MessageSnapshotReader(const uint8_t* buffer,
intptr_t size,
- Isolate* isolate,
- Zone* zone);
+ Thread* thread);
~MessageSnapshotReader();
private:
@@ -733,6 +772,28 @@
};
+class InstructionsWriter : public ZoneAllocated {
+ public:
+ InstructionsWriter(uint8_t** buffer,
+ ReAlloc alloc,
+ intptr_t initial_size)
+ : stream_(buffer, alloc, initial_size) {
+ ASSERT(buffer != NULL);
+ ASSERT(alloc != NULL);
+ }
+
+ // Size of the snapshot.
+ intptr_t BytesWritten() const { return stream_.bytes_written(); }
+
+ int32_t GetOffsetFor(RawInstructions* instructions);
+
+ private:
+ WriteStream stream_;
+
+ DISALLOW_COPY_AND_ASSIGN(InstructionsWriter);
+};
+
+
class SnapshotWriter : public BaseWriter {
protected:
SnapshotWriter(Snapshot::Kind kind,
@@ -740,8 +801,10 @@
ReAlloc alloc,
intptr_t initial_size,
ForwardList* forward_list,
+ InstructionsWriter* instructions_writer,
bool can_send_any_object,
- bool snapshot_code);
+ bool snapshot_code,
+ bool vm_isolate_is_symbolic);
public:
// Snapshot kind.
@@ -764,6 +827,7 @@
}
bool can_send_any_object() const { return can_send_any_object_; }
bool snapshot_code() const { return snapshot_code_; }
+ bool vm_isolate_is_symbolic() const { return vm_isolate_is_symbolic_; }
void ThrowException(Exceptions::ExceptionType type, const char* msg);
// Write a version string for the snapshot.
@@ -771,7 +835,9 @@
static intptr_t FirstObjectId();
- int32_t GetInstructionsId(RawInstructions* instructions) { return 0; }
+ int32_t GetInstructionsId(RawInstructions* instructions) {
+ return instructions_writer_->GetOffsetFor(instructions);
+ }
protected:
void UnmarkAll() {
@@ -782,7 +848,7 @@
}
bool CheckAndWritePredefinedObject(RawObject* raw);
- void HandleVMIsolateObject(RawObject* raw);
+ bool HandleVMIsolateObject(RawObject* raw);
void WriteClassId(RawClass* cls);
void WriteStaticImplicitClosure(intptr_t object_id,
@@ -819,20 +885,23 @@
forward_list_ = NULL;
}
- Isolate* isolate() const { return isolate_; }
+ Thread* thread() const { return thread_; }
+ Isolate* isolate() const { return thread_->isolate(); }
ObjectStore* object_store() const { return object_store_; }
private:
Snapshot::Kind kind_;
- Isolate* isolate_;
+ Thread* thread_;
ObjectStore* object_store_; // Object store for common classes.
ClassTable* class_table_; // Class table for the class index to class lookup.
ForwardList* forward_list_;
+ InstructionsWriter* instructions_writer_;
Exceptions::ExceptionType exception_type_; // Exception type.
const char* exception_msg_; // Message associated with exception.
bool unmarked_objects_; // True if marked objects have been unmarked.
bool can_send_any_object_; // True if any Dart instance can be sent.
bool snapshot_code_;
+ bool vm_isolate_is_symbolic_;
friend class FullSnapshotWriter;
friend class RawArray;
@@ -868,8 +937,10 @@
static const intptr_t kInitialSize = 64 * KB;
FullSnapshotWriter(uint8_t** vm_isolate_snapshot_buffer,
uint8_t** isolate_snapshot_buffer,
+ uint8_t** instructions_snapshot_buffer,
ReAlloc alloc,
- bool snapshot_code);
+ bool snapshot_code,
+ bool vm_isolate_is_symbolic);
~FullSnapshotWriter();
uint8_t** vm_isolate_snapshot_buffer() {
@@ -889,6 +960,9 @@
intptr_t IsolateSnapshotSize() const {
return isolate_snapshot_size_;
}
+ intptr_t InstructionsSnapshotSize() const {
+ return instructions_snapshot_size_;
+ }
private:
// Writes a snapshot of the VM Isolate.
@@ -900,13 +974,17 @@
Isolate* isolate_;
uint8_t** vm_isolate_snapshot_buffer_;
uint8_t** isolate_snapshot_buffer_;
+ uint8_t** instructions_snapshot_buffer_;
ReAlloc alloc_;
intptr_t vm_isolate_snapshot_size_;
intptr_t isolate_snapshot_size_;
+ intptr_t instructions_snapshot_size_;
ForwardList* forward_list_;
+ InstructionsWriter* instructions_writer_;
Array& scripts_;
Array& symbol_table_;
bool snapshot_code_;
+ bool vm_isolate_is_symbolic_;
DISALLOW_COPY_AND_ASSIGN(FullSnapshotWriter);
};
@@ -916,6 +994,7 @@
public:
PrecompiledSnapshotWriter(uint8_t** vm_isolate_snapshot_buffer,
uint8_t** isolate_snapshot_buffer,
+ uint8_t** instructions_snapshot_buffer,
ReAlloc alloc);
~PrecompiledSnapshotWriter();
};
diff --git a/runtime/vm/snapshot_test.cc b/runtime/vm/snapshot_test.cc
index 9c67df8..56cbfd6 100644
--- a/runtime/vm/snapshot_test.cc
+++ b/runtime/vm/snapshot_test.cc
@@ -152,7 +152,7 @@
TEST_CASE(SerializeNull) {
- StackZone zone(Thread::Current());
+ StackZone zone(thread);
// Write snapshot with object content.
const Object& null_object = Object::Handle();
@@ -162,10 +162,7 @@
intptr_t buffer_len = writer.BytesWritten();
// Read object back from the snapshot.
- MessageSnapshotReader reader(buffer,
- buffer_len,
- Isolate::Current(),
- zone.GetZone());
+ MessageSnapshotReader reader(buffer, buffer_len, thread);
const Object& serialized_object = Object::Handle(reader.ReadObject());
EXPECT(Equals(null_object, serialized_object));
@@ -180,7 +177,7 @@
TEST_CASE(SerializeSmi1) {
- StackZone zone(Thread::Current());
+ StackZone zone(thread);
// Write snapshot with object content.
const Smi& smi = Smi::Handle(Smi::New(124));
@@ -190,10 +187,7 @@
intptr_t buffer_len = writer.BytesWritten();
// Read object back from the snapshot.
- MessageSnapshotReader reader(buffer,
- buffer_len,
- Isolate::Current(),
- zone.GetZone());
+ MessageSnapshotReader reader(buffer, buffer_len, thread);
const Object& serialized_object = Object::Handle(reader.ReadObject());
EXPECT(Equals(smi, serialized_object));
@@ -209,7 +203,7 @@
TEST_CASE(SerializeSmi2) {
- StackZone zone(Thread::Current());
+ StackZone zone(thread);
// Write snapshot with object content.
const Smi& smi = Smi::Handle(Smi::New(-1));
@@ -219,10 +213,7 @@
intptr_t buffer_len = writer.BytesWritten();
// Read object back from the snapshot.
- MessageSnapshotReader reader(buffer,
- buffer_len,
- Isolate::Current(),
- zone.GetZone());
+ MessageSnapshotReader reader(buffer, buffer_len, thread);
const Object& serialized_object = Object::Handle(reader.ReadObject());
EXPECT(Equals(smi, serialized_object));
@@ -246,12 +237,10 @@
{
// Switch to a regular zone, where VM handle allocation is allowed.
- StackZone zone(Thread::Current());
+ Thread* thread = Thread::Current();
+ StackZone zone(thread);
// Read object back from the snapshot.
- MessageSnapshotReader reader(buffer,
- buffer_len,
- Isolate::Current(),
- Thread::Current()->zone());
+ MessageSnapshotReader reader(buffer, buffer_len, thread);
const Object& serialized_object = Object::Handle(reader.ReadObject());
EXPECT(serialized_object.IsMint());
}
@@ -312,7 +301,7 @@
TEST_CASE(SerializeDouble) {
- StackZone zone(Thread::Current());
+ StackZone zone(thread);
// Write snapshot with object content.
const Double& dbl = Double::Handle(Double::New(101.29));
@@ -322,10 +311,7 @@
intptr_t buffer_len = writer.BytesWritten();
// Read object back from the snapshot.
- MessageSnapshotReader reader(buffer,
- buffer_len,
- Isolate::Current(),
- zone.GetZone());
+ MessageSnapshotReader reader(buffer, buffer_len, thread);
const Object& serialized_object = Object::Handle(reader.ReadObject());
EXPECT(Equals(dbl, serialized_object));
@@ -341,7 +327,7 @@
TEST_CASE(SerializeTrue) {
- StackZone zone(Thread::Current());
+ StackZone zone(thread);
// Write snapshot with true object.
const Bool& bl = Bool::True();
@@ -351,10 +337,7 @@
intptr_t buffer_len = writer.BytesWritten();
// Read object back from the snapshot.
- MessageSnapshotReader reader(buffer,
- buffer_len,
- Isolate::Current(),
- zone.GetZone());
+ MessageSnapshotReader reader(buffer, buffer_len, thread);
const Object& serialized_object = Object::Handle(reader.ReadObject());
fprintf(stderr, "%s / %s\n", bl.ToCString(), serialized_object.ToCString());
@@ -372,7 +355,7 @@
TEST_CASE(SerializeFalse) {
- StackZone zone(Thread::Current());
+ StackZone zone(thread);
// Write snapshot with false object.
const Bool& bl = Bool::False();
@@ -382,10 +365,7 @@
intptr_t buffer_len = writer.BytesWritten();
// Read object back from the snapshot.
- MessageSnapshotReader reader(buffer,
- buffer_len,
- Isolate::Current(),
- zone.GetZone());
+ MessageSnapshotReader reader(buffer, buffer_len, thread);
const Object& serialized_object = Object::Handle(reader.ReadObject());
EXPECT(Equals(bl, serialized_object));
@@ -406,8 +386,6 @@
TEST_CASE(SerializeCapability) {
- StackZone zone(Thread::Current());
-
// Write snapshot with object content.
const Capability& capability = Capability::Handle(Capability::New(12345));
uint8_t* buffer;
@@ -416,10 +394,7 @@
intptr_t buffer_len = writer.BytesWritten();
// Read object back from the snapshot.
- MessageSnapshotReader reader(buffer,
- buffer_len,
- Isolate::Current(),
- zone.GetZone());
+ MessageSnapshotReader reader(buffer, buffer_len, thread);
Capability& obj = Capability::Handle();
obj ^= reader.ReadObject();
@@ -438,8 +413,6 @@
TEST_CASE(SerializeBigint) {
- StackZone zone(Thread::Current());
-
// Write snapshot with object content.
const char* cstr = "0x270FFFFFFFFFFFFFD8F0";
const String& str = String::Handle(String::New(cstr));
@@ -451,10 +424,7 @@
intptr_t buffer_len = writer.BytesWritten();
// Read object back from the snapshot.
- MessageSnapshotReader reader(buffer,
- buffer_len,
- Isolate::Current(),
- zone.GetZone());
+ MessageSnapshotReader reader(buffer, buffer_len, thread);
Bigint& obj = Bigint::Handle();
obj ^= reader.ReadObject();
@@ -482,12 +452,10 @@
{
// Switch to a regular zone, where VM handle allocation is allowed.
- StackZone zone(Thread::Current());
+ Thread* thread = Thread::Current();
+ StackZone zone(thread);
// Read object back from the snapshot.
- MessageSnapshotReader reader(buffer,
- buffer_len,
- Isolate::Current(),
- Thread::Current()->zone());
+ MessageSnapshotReader reader(buffer, buffer_len, thread);
Bigint& serialized_bigint = Bigint::Handle();
serialized_bigint ^= reader.ReadObject();
const char* str1 = bigint.ToHexCString(allocator);
@@ -550,10 +518,7 @@
intptr_t buffer_len = writer.BytesWritten();
// Read object back from the snapshot.
- MessageSnapshotReader reader(buffer,
- buffer_len,
- Isolate::Current(),
- Thread::Current()->zone());
+ MessageSnapshotReader reader(buffer, buffer_len, thread);
EXPECT(Object::class_class() == reader.ReadObject());
EXPECT(Object::type_arguments_class() == reader.ReadObject());
EXPECT(Object::function_class() == reader.ReadObject());
@@ -573,7 +538,7 @@
static void TestString(const char* cstr) {
- StackZone zone(Thread::Current());
+ Thread* thread = Thread::Current();
EXPECT(Utf8::IsValid(reinterpret_cast<const uint8_t*>(cstr), strlen(cstr)));
// Write snapshot with object content.
String& str = String::Handle(String::New(cstr));
@@ -583,10 +548,7 @@
intptr_t buffer_len = writer.BytesWritten();
// Read object back from the snapshot.
- MessageSnapshotReader reader(buffer,
- buffer_len,
- Isolate::Current(),
- zone.GetZone());
+ MessageSnapshotReader reader(buffer, buffer_len, thread);
String& serialized_str = String::Handle();
serialized_str ^= reader.ReadObject();
EXPECT(str.Equals(serialized_str));
@@ -617,8 +579,6 @@
TEST_CASE(SerializeArray) {
- StackZone zone(Thread::Current());
-
// Write snapshot with object content.
const int kArrayLength = 10;
Array& array = Array::Handle(Array::New(kArrayLength));
@@ -633,10 +593,7 @@
intptr_t buffer_len = writer.BytesWritten();
// Read object back from the snapshot.
- MessageSnapshotReader reader(buffer,
- buffer_len,
- Isolate::Current(),
- zone.GetZone());
+ MessageSnapshotReader reader(buffer, buffer_len, thread);
Array& serialized_array = Array::Handle();
serialized_array ^= reader.ReadObject();
EXPECT(array.CanonicalizeEquals(serialized_array));
@@ -709,8 +666,6 @@
TEST_CASE(SerializeEmptyArray) {
- StackZone zone(Thread::Current());
-
// Write snapshot with object content.
const int kArrayLength = 0;
Array& array = Array::Handle(Array::New(kArrayLength));
@@ -720,10 +675,7 @@
intptr_t buffer_len = writer.BytesWritten();
// Read object back from the snapshot.
- MessageSnapshotReader reader(buffer,
- buffer_len,
- Isolate::Current(),
- zone.GetZone());
+ MessageSnapshotReader reader(buffer, buffer_len, thread);
Array& serialized_array = Array::Handle();
serialized_array ^= reader.ReadObject();
EXPECT(array.CanonicalizeEquals(serialized_array));
@@ -740,8 +692,6 @@
TEST_CASE(SerializeByteArray) {
- StackZone zone(Thread::Current());
-
// Write snapshot with object content.
const int kTypedDataLength = 256;
TypedData& typed_data = TypedData::Handle(
@@ -755,10 +705,7 @@
intptr_t buffer_len = writer.BytesWritten();
// Read object back from the snapshot.
- MessageSnapshotReader reader(buffer,
- buffer_len,
- Isolate::Current(),
- zone.GetZone());
+ MessageSnapshotReader reader(buffer, buffer_len, thread);
TypedData& serialized_typed_data = TypedData::Handle();
serialized_typed_data ^= reader.ReadObject();
EXPECT(serialized_typed_data.IsTypedData());
@@ -776,54 +723,50 @@
}
-#define TEST_TYPED_ARRAY(darttype, ctype) \
- { \
- StackZone zone(Thread::Current()); \
- const int kArrayLength = 127; \
- TypedData& array = TypedData::Handle( \
- TypedData::New(kTypedData##darttype##ArrayCid, kArrayLength)); \
- intptr_t scale = array.ElementSizeInBytes(); \
- for (int i = 0; i < kArrayLength; i++) { \
- array.Set##darttype((i * scale), i); \
- } \
- uint8_t* buffer; \
- MessageWriter writer(&buffer, &zone_allocator, true); \
- writer.WriteMessage(array); \
- intptr_t buffer_len = writer.BytesWritten(); \
- MessageSnapshotReader reader(buffer, buffer_len, \
- Isolate::Current(), \
- zone.GetZone()); \
- TypedData& serialized_array = TypedData::Handle(); \
- serialized_array ^= reader.ReadObject(); \
- for (int i = 0; i < kArrayLength; i++) { \
- EXPECT_EQ(static_cast<ctype>(i), \
- serialized_array.Get##darttype(i*scale)); \
- } \
+#define TEST_TYPED_ARRAY(darttype, ctype) \
+ { \
+ StackZone zone(thread); \
+ const int kArrayLength = 127; \
+ TypedData& array = TypedData::Handle( \
+ TypedData::New(kTypedData##darttype##ArrayCid, kArrayLength)); \
+ intptr_t scale = array.ElementSizeInBytes(); \
+ for (int i = 0; i < kArrayLength; i++) { \
+ array.Set##darttype((i * scale), i); \
+ } \
+ uint8_t* buffer; \
+ MessageWriter writer(&buffer, &zone_allocator, true); \
+ writer.WriteMessage(array); \
+ intptr_t buffer_len = writer.BytesWritten(); \
+ MessageSnapshotReader reader(buffer, buffer_len, thread); \
+ TypedData& serialized_array = TypedData::Handle(); \
+ serialized_array ^= reader.ReadObject(); \
+ for (int i = 0; i < kArrayLength; i++) { \
+ EXPECT_EQ(static_cast<ctype>(i), \
+ serialized_array.Get##darttype(i*scale)); \
+ } \
}
-#define TEST_EXTERNAL_TYPED_ARRAY(darttype, ctype) \
- { \
- StackZone zone(Thread::Current()); \
- ctype data[] = { 0, 11, 22, 33, 44, 55, 66, 77 }; \
- intptr_t length = ARRAY_SIZE(data); \
- ExternalTypedData& array = ExternalTypedData::Handle( \
- ExternalTypedData::New(kExternalTypedData##darttype##ArrayCid, \
- reinterpret_cast<uint8_t*>(data), length)); \
- intptr_t scale = array.ElementSizeInBytes(); \
- uint8_t* buffer; \
- MessageWriter writer(&buffer, &zone_allocator, true); \
- writer.WriteMessage(array); \
- intptr_t buffer_len = writer.BytesWritten(); \
- MessageSnapshotReader reader(buffer, buffer_len, \
- Isolate::Current(), \
- zone.GetZone()); \
- TypedData& serialized_array = TypedData::Handle(); \
- serialized_array ^= reader.ReadObject(); \
- for (int i = 0; i < length; i++) { \
- EXPECT_EQ(static_cast<ctype>(data[i]), \
- serialized_array.Get##darttype(i*scale)); \
- } \
+#define TEST_EXTERNAL_TYPED_ARRAY(darttype, ctype) \
+ { \
+ StackZone zone(thread); \
+ ctype data[] = { 0, 11, 22, 33, 44, 55, 66, 77 }; \
+ intptr_t length = ARRAY_SIZE(data); \
+ ExternalTypedData& array = ExternalTypedData::Handle( \
+ ExternalTypedData::New(kExternalTypedData##darttype##ArrayCid, \
+ reinterpret_cast<uint8_t*>(data), length)); \
+ intptr_t scale = array.ElementSizeInBytes(); \
+ uint8_t* buffer; \
+ MessageWriter writer(&buffer, &zone_allocator, true); \
+ writer.WriteMessage(array); \
+ intptr_t buffer_len = writer.BytesWritten(); \
+ MessageSnapshotReader reader(buffer, buffer_len, thread); \
+ TypedData& serialized_array = TypedData::Handle(); \
+ serialized_array ^= reader.ReadObject(); \
+ for (int i = 0; i < length; i++) { \
+ EXPECT_EQ(static_cast<ctype>(data[i]), \
+ serialized_array.Get##darttype(i*scale)); \
+ } \
}
@@ -856,8 +799,6 @@
TEST_CASE(SerializeEmptyByteArray) {
- StackZone zone(Thread::Current());
-
// Write snapshot with object content.
const int kTypedDataLength = 0;
TypedData& typed_data = TypedData::Handle(
@@ -868,10 +809,7 @@
intptr_t buffer_len = writer.BytesWritten();
// Read object back from the snapshot.
- MessageSnapshotReader reader(buffer,
- buffer_len,
- Isolate::Current(),
- zone.GetZone());
+ MessageSnapshotReader reader(buffer, buffer_len, thread);
TypedData& serialized_typed_data = TypedData::Handle();
serialized_typed_data ^= reader.ReadObject();
EXPECT(serialized_typed_data.IsTypedData());
@@ -897,8 +835,10 @@
alloc,
kInitialSize,
&forward_list_,
+ NULL, /* test_writer */
true, /* can_send_any_object */
- false /* snapshot_code */),
+ false, /* snapshot_code */
+ true /* vm_isolate_is_symbolic */),
forward_list_(kMaxPredefinedObjectIds) {
ASSERT(buffer != NULL);
ASSERT(alloc != NULL);
@@ -1010,11 +950,8 @@
writer.WriteScript(script);
// Read object back from the snapshot.
- ScriptSnapshotReader reader(buffer,
- writer.BytesWritten(),
- Isolate::Current(),
- Thread::Current()->zone());
- Script& serialized_script = Script::Handle();
+ ScriptSnapshotReader reader(buffer, writer.BytesWritten(), thread);
+ Script& serialized_script = Script::Handle(thread->zone());
serialized_script ^= reader.ReadObject();
// Check if the serialized script object matches the original script.
@@ -1231,13 +1168,13 @@
{
TestIsolateScope __test_isolate__;
- Isolate* isolate = Isolate::Current();
- StackZone zone(isolate);
- HandleScope scope(isolate);
+ Thread* thread = Thread::Current();
+ StackZone zone(thread);
+ HandleScope scope(thread);
// Create a test library and Load up a test script in it.
TestCase::LoadTestScript(kScriptChars, NULL);
- EXPECT_VALID(Api::CheckAndFinalizePendingClasses(isolate));
+ EXPECT_VALID(Api::CheckAndFinalizePendingClasses(thread->isolate()));
timer1.Stop();
OS::PrintErr("Without Snapshot: %" Pd64 "us\n", timer1.TotalElapsedTime());
@@ -1245,8 +1182,10 @@
{
FullSnapshotWriter writer(NULL,
&isolate_snapshot_buffer,
+ NULL, /* instructions_snapshot_buffer */
&malloc_allocator,
- false /* snapshot_code */);
+ false, /* snapshot_code */
+ true);
writer.WriteFullSnapshot();
}
}
@@ -1290,13 +1229,13 @@
{
TestIsolateScope __test_isolate__;
- Isolate* isolate = Isolate::Current();
- StackZone zone(isolate);
- HandleScope scope(isolate);
+ Thread* thread = Thread::Current();
+ StackZone zone(thread);
+ HandleScope scope(thread);
// Create a test library and Load up a test script in it.
Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
- EXPECT_VALID(Api::CheckAndFinalizePendingClasses(isolate));
+ EXPECT_VALID(Api::CheckAndFinalizePendingClasses(thread->isolate()));
timer1.Stop();
OS::PrintErr("Without Snapshot: %" Pd64 "us\n", timer1.TotalElapsedTime());
@@ -1304,8 +1243,10 @@
{
FullSnapshotWriter writer(NULL,
&isolate_snapshot_buffer,
+ NULL, /* instructions_snapshot_buffer */
&malloc_allocator,
- false /* snapshot_code */);
+ false, /* snapshot_code */
+ true /* vm_isolate_is_symbolic */);
writer.WriteFullSnapshot();
}
@@ -1897,7 +1838,7 @@
EXPECT(Dart_IsString(crappy_string_result));
{
- DARTSCOPE(isolate);
+ DARTSCOPE(Thread::Current());
{
StackZone zone(Thread::Current());
@@ -1981,16 +1922,16 @@
"}\n";
TestCase::CreateTestIsolate();
- Isolate* isolate = Isolate::Current();
- EXPECT(isolate != NULL);
+ Thread* thread = Thread::Current();
+ EXPECT(thread->isolate() != NULL);
Dart_EnterScope();
Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
EXPECT_VALID(lib);
{
- DARTSCOPE(isolate);
- StackZone zone(isolate);
+ DARTSCOPE(thread);
+ StackZone zone(thread);
intptr_t buf_len = 0;
{
// Generate a list of nulls from Dart code.
@@ -2105,16 +2046,16 @@
"}\n";
TestCase::CreateTestIsolate();
- Isolate* isolate = Isolate::Current();
- EXPECT(isolate != NULL);
+ Thread* thread = Thread::Current();
+ EXPECT(thread->isolate() != NULL);
Dart_EnterScope();
Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
EXPECT_VALID(lib);
{
- DARTSCOPE(isolate);
- StackZone zone(isolate);
+ DARTSCOPE(thread);
+ StackZone zone(thread);
intptr_t buf_len = 0;
{
// Generate a list of nulls from Dart code.
@@ -2344,16 +2285,16 @@
"}\n";
TestCase::CreateTestIsolate();
- Isolate* isolate = Isolate::Current();
- EXPECT(isolate != NULL);
+ Thread* thread = Thread::Current();
+ EXPECT(thread->isolate() != NULL);
Dart_EnterScope();
Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
EXPECT_VALID(lib);
{
- DARTSCOPE(isolate);
- StackZone zone(isolate);
+ DARTSCOPE(thread);
+ StackZone zone(thread);
intptr_t buf_len = 0;
{
// Generate a list of strings from Dart code.
@@ -2569,16 +2510,16 @@
"}\n";
TestCase::CreateTestIsolate();
- Isolate* isolate = Isolate::Current();
- EXPECT(isolate != NULL);
+ Thread* thread = Thread::Current();
+ EXPECT(thread->isolate() != NULL);
Dart_EnterScope();
Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
EXPECT_VALID(lib);
{
- DARTSCOPE(isolate);
- StackZone zone(isolate);
+ DARTSCOPE(thread);
+ StackZone zone(thread);
intptr_t buf_len = 0;
{
// Generate a list of strings from Dart code.
@@ -2810,16 +2751,16 @@
"}\n";
TestCase::CreateTestIsolate();
- Isolate* isolate = Isolate::Current();
- EXPECT(isolate != NULL);
+ Thread* thread = Thread::Current();
+ EXPECT(thread->isolate() != NULL);
Dart_EnterScope();
Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
EXPECT_VALID(lib);
{
- DARTSCOPE(isolate);
- StackZone zone(isolate);
+ DARTSCOPE(thread);
+ StackZone zone(thread);
intptr_t buf_len = 0;
{
// Generate a list of Uint8Lists from Dart code.
diff --git a/runtime/vm/stub_code_arm64_test.cc b/runtime/vm/stub_code_arm64_test.cc
index 1c93003..eba3949 100644
--- a/runtime/vm/stub_code_arm64_test.cc
+++ b/runtime/vm/stub_code_arm64_test.cc
@@ -36,16 +36,15 @@
// Test calls to stub code which calls into the runtime.
static void GenerateCallToCallRuntimeStub(Assembler* assembler,
- int value1, int value2) {
+ int length) {
const int argc = 2;
- const Smi& smi1 = Smi::ZoneHandle(Smi::New(value1));
- const Smi& smi2 = Smi::ZoneHandle(Smi::New(value2));
+ const Smi& smi_length = Smi::ZoneHandle(Smi::New(length));
__ EnterDartFrame(0);
__ PushObject(Object::null_object()); // Push Null obj for return value.
- __ PushObject(smi1); // Push argument 1 smi1.
- __ PushObject(smi2); // Push argument 2 smi2.
- ASSERT(kTestSmiSubRuntimeEntry.argument_count() == argc);
- __ CallRuntime(kTestSmiSubRuntimeEntry, argc); // Call SmiSub runtime func.
+ __ PushObject(smi_length); // Push argument 1: length.
+ __ PushObject(Object::null_object()); // Push argument 2: type arguments.
+ ASSERT(kAllocateArrayRuntimeEntry.argument_count() == argc);
+ __ CallRuntime(kAllocateArrayRuntimeEntry, argc);
__ add(SP, SP, Operand(argc * kWordSize));
__ Pop(R0); // Pop return value from return slot.
__ LeaveDartFrame();
@@ -56,31 +55,33 @@
TEST_CASE(CallRuntimeStubCode) {
extern const Function& RegisterFakeFunction(const char* name,
const Code& code);
- const int value1 = 10;
- const int value2 = 20;
+ const int length = 10;
const char* kName = "Test_CallRuntimeStubCode";
Assembler _assembler_;
- GenerateCallToCallRuntimeStub(&_assembler_, value1, value2);
+ GenerateCallToCallRuntimeStub(&_assembler_, length);
const Code& code = Code::Handle(Code::FinalizeCode(
*CreateFunction("Test_CallRuntimeStubCode"), &_assembler_));
const Function& function = RegisterFakeFunction(kName, code);
- Smi& result = Smi::Handle();
+ Array& result = Array::Handle();
result ^= DartEntry::InvokeFunction(function, Object::empty_array());
- EXPECT_EQ((value1 - value2), result.Value());
+ EXPECT_EQ(length, result.Length());
}
// Test calls to stub code which calls into a leaf runtime entry.
static void GenerateCallToCallLeafRuntimeStub(Assembler* assembler,
- int value1,
- int value2) {
- const Smi& smi1 = Smi::ZoneHandle(Smi::New(value1));
- const Smi& smi2 = Smi::ZoneHandle(Smi::New(value2));
+ const char* value1,
+ const char* value2) {
+ const Bigint& bigint1 =
+ Bigint::ZoneHandle(Bigint::NewFromCString(value1, Heap::kOld));
+ const Bigint& bigint2 =
+ Bigint::ZoneHandle(Bigint::NewFromCString(value2, Heap::kOld));
__ EnterDartFrame(0);
__ ReserveAlignedFrameSpace(0);
- __ LoadObject(R0, smi1); // Set up argument 1 smi1.
- __ LoadObject(R1, smi2); // Set up argument 2 smi2.
- __ CallRuntime(kTestLeafSmiAddRuntimeEntry, 2); // Call SmiAdd runtime func.
+ __ LoadObject(R0, bigint1); // Set up argument 1 bigint1.
+ __ LoadObject(R1, bigint2); // Set up argument 2 bigint2.
+ __ CallRuntime(kBigintCompareRuntimeEntry, 2);
+ __ SmiTag(R0);
__ LeaveDartFrame();
__ ret(); // Return value is in R0.
}
@@ -89,8 +90,8 @@
TEST_CASE(CallLeafRuntimeStubCode) {
extern const Function& RegisterFakeFunction(const char* name,
const Code& code);
- const int value1 = 10;
- const int value2 = 20;
+ const char* value1 = "0xAAABBCCDDAABBCCDD";
+ const char* value2 = "0xAABBCCDDAABBCCDD";
const char* kName = "Test_CallLeafRuntimeStubCode";
Assembler _assembler_;
GenerateCallToCallLeafRuntimeStub(&_assembler_, value1, value2);
@@ -99,7 +100,7 @@
const Function& function = RegisterFakeFunction(kName, code);
Smi& result = Smi::Handle();
result ^= DartEntry::InvokeFunction(function, Object::empty_array());
- EXPECT_EQ((value1 + value2), result.Value());
+ EXPECT_EQ(1, result.Value());
}
} // namespace dart
diff --git a/runtime/vm/stub_code_arm_test.cc b/runtime/vm/stub_code_arm_test.cc
index ae1ce83..39aa9e6 100644
--- a/runtime/vm/stub_code_arm_test.cc
+++ b/runtime/vm/stub_code_arm_test.cc
@@ -36,16 +36,15 @@
// Test calls to stub code which calls into the runtime.
static void GenerateCallToCallRuntimeStub(Assembler* assembler,
- int value1, int value2) {
+ int length) {
const int argc = 2;
- const Smi& smi1 = Smi::ZoneHandle(Smi::New(value1));
- const Smi& smi2 = Smi::ZoneHandle(Smi::New(value2));
+ const Smi& smi_length = Smi::ZoneHandle(Smi::New(length));
__ EnterDartFrame(0);
__ PushObject(Object::null_object()); // Push Null object for return value.
- __ PushObject(smi1); // Push argument 1 smi1.
- __ PushObject(smi2); // Push argument 2 smi2.
- ASSERT(kTestSmiSubRuntimeEntry.argument_count() == argc);
- __ CallRuntime(kTestSmiSubRuntimeEntry, argc); // Call SmiSub runtime func.
+ __ PushObject(smi_length); // Push argument 1: length.
+ __ PushObject(Object::null_object()); // Push argument 2: type arguments.
+ ASSERT(kAllocateArrayRuntimeEntry.argument_count() == argc);
+ __ CallRuntime(kAllocateArrayRuntimeEntry, argc);
__ AddImmediate(SP, argc * kWordSize);
__ Pop(R0); // Pop return value from return slot.
__ LeaveDartFrame();
@@ -56,31 +55,33 @@
TEST_CASE(CallRuntimeStubCode) {
extern const Function& RegisterFakeFunction(const char* name,
const Code& code);
- const int value1 = 10;
- const int value2 = 20;
+ const int length = 10;
const char* kName = "Test_CallRuntimeStubCode";
Assembler _assembler_;
- GenerateCallToCallRuntimeStub(&_assembler_, value1, value2);
+ GenerateCallToCallRuntimeStub(&_assembler_, length);
const Code& code = Code::Handle(Code::FinalizeCode(
*CreateFunction("Test_CallRuntimeStubCode"), &_assembler_));
const Function& function = RegisterFakeFunction(kName, code);
- Smi& result = Smi::Handle();
+ Array& result = Array::Handle();
result ^= DartEntry::InvokeFunction(function, Object::empty_array());
- EXPECT_EQ((value1 - value2), result.Value());
+ EXPECT_EQ(length, result.Length());
}
// Test calls to stub code which calls into a leaf runtime entry.
static void GenerateCallToCallLeafRuntimeStub(Assembler* assembler,
- int value1,
- int value2) {
- const Smi& smi1 = Smi::ZoneHandle(Smi::New(value1));
- const Smi& smi2 = Smi::ZoneHandle(Smi::New(value2));
+ const char* value1,
+ const char* value2) {
+ const Bigint& bigint1 =
+ Bigint::ZoneHandle(Bigint::NewFromCString(value1, Heap::kOld));
+ const Bigint& bigint2 =
+ Bigint::ZoneHandle(Bigint::NewFromCString(value2, Heap::kOld));
__ EnterDartFrame(0);
__ ReserveAlignedFrameSpace(0);
- __ LoadObject(R0, smi1); // Set up argument 1 smi1.
- __ LoadObject(R1, smi2); // Set up argument 2 smi2.
- __ CallRuntime(kTestLeafSmiAddRuntimeEntry, 2); // Call SmiAdd runtime func.
+ __ LoadObject(R0, bigint1); // Set up argument 1 bigint1.
+ __ LoadObject(R1, bigint2); // Set up argument 2 bigint2.
+ __ CallRuntime(kBigintCompareRuntimeEntry, 2);
+ __ SmiTag(R0);
__ LeaveDartFrame();
__ Ret(); // Return value is in R0.
}
@@ -89,8 +90,8 @@
TEST_CASE(CallLeafRuntimeStubCode) {
extern const Function& RegisterFakeFunction(const char* name,
const Code& code);
- const int value1 = 10;
- const int value2 = 20;
+ const char* value1 = "0xAAABBCCDDAABBCCDD";
+ const char* value2 = "0xAABBCCDDAABBCCDD";
const char* kName = "Test_CallLeafRuntimeStubCode";
Assembler _assembler_;
GenerateCallToCallLeafRuntimeStub(&_assembler_, value1, value2);
@@ -99,7 +100,7 @@
const Function& function = RegisterFakeFunction(kName, code);
Smi& result = Smi::Handle();
result ^= DartEntry::InvokeFunction(function, Object::empty_array());
- EXPECT_EQ((value1 + value2), result.Value());
+ EXPECT_EQ(1, result.Value());
}
} // namespace dart
diff --git a/runtime/vm/stub_code_ia32_test.cc b/runtime/vm/stub_code_ia32_test.cc
index 301259b..1ab200b 100644
--- a/runtime/vm/stub_code_ia32_test.cc
+++ b/runtime/vm/stub_code_ia32_test.cc
@@ -36,16 +36,15 @@
// Test calls to stub code which calls into the runtime.
static void GenerateCallToCallRuntimeStub(Assembler* assembler,
- int value1, int value2) {
+ int length) {
const int argc = 2;
- const Smi& smi1 = Smi::ZoneHandle(Smi::New(value1));
- const Smi& smi2 = Smi::ZoneHandle(Smi::New(value2));
+ const Smi& smi_length = Smi::ZoneHandle(Smi::New(length));
__ enter(Immediate(0));
__ PushObject(Object::null_object()); // Push Null object for return value.
- __ PushObject(smi1); // Push argument 1 smi1.
- __ PushObject(smi2); // Push argument 2 smi2.
- ASSERT(kTestSmiSubRuntimeEntry.argument_count() == argc);
- __ CallRuntime(kTestSmiSubRuntimeEntry, argc); // Call SmiSub runtime func.
+ __ PushObject(smi_length); // Push argument 1: length.
+ __ PushObject(Object::null_object()); // Push argument 2: type arguments.
+ ASSERT(kAllocateArrayRuntimeEntry.argument_count() == argc);
+ __ CallRuntime(kAllocateArrayRuntimeEntry, argc);
__ AddImmediate(ESP, Immediate(argc * kWordSize));
__ popl(EAX); // Pop return value from return slot.
__ leave();
@@ -56,33 +55,35 @@
TEST_CASE(CallRuntimeStubCode) {
extern const Function& RegisterFakeFunction(const char* name,
const Code& code);
- const int value1 = 10;
- const int value2 = 20;
+ const int length = 10;
const char* kName = "Test_CallRuntimeStubCode";
Assembler _assembler_;
- GenerateCallToCallRuntimeStub(&_assembler_, value1, value2);
+ GenerateCallToCallRuntimeStub(&_assembler_, length);
const Code& code = Code::Handle(Code::FinalizeCode(
*CreateFunction("Test_CallRuntimeStubCode"), &_assembler_));
const Function& function = RegisterFakeFunction(kName, code);
- Smi& result = Smi::Handle();
+ Array& result = Array::Handle();
result ^= DartEntry::InvokeFunction(function, Object::empty_array());
- EXPECT_EQ((value1 - value2), result.Value());
+ EXPECT_EQ(length, result.Length());
}
// Test calls to stub code which calls into a leaf runtime entry.
static void GenerateCallToCallLeafRuntimeStub(Assembler* assembler,
- int value1,
- int value2) {
- const Smi& smi1 = Smi::ZoneHandle(Smi::New(value1));
- const Smi& smi2 = Smi::ZoneHandle(Smi::New(value2));
+ const char* value1,
+ const char* value2) {
+ const Bigint& bigint1 =
+ Bigint::ZoneHandle(Bigint::NewFromCString(value1, Heap::kOld));
+ const Bigint& bigint2 =
+ Bigint::ZoneHandle(Bigint::NewFromCString(value2, Heap::kOld));
__ enter(Immediate(0));
__ ReserveAlignedFrameSpace(2 * kWordSize);
- __ LoadObject(EAX, smi1);
- __ movl(Address(ESP, 0), EAX); // Push argument 1 smi1.
- __ LoadObject(EAX, smi2);
- __ movl(Address(ESP, kWordSize), EAX); // Push argument 2 smi2.
- __ CallRuntime(kTestLeafSmiAddRuntimeEntry, 2); // Call SmiAdd runtime func.
+ __ LoadObject(EAX, bigint1);
+ __ movl(Address(ESP, 0), EAX); // Push argument 1 bigint1.
+ __ LoadObject(EAX, bigint2);
+ __ movl(Address(ESP, kWordSize), EAX); // Push argument 2 bigint2.
+ __ CallRuntime(kBigintCompareRuntimeEntry, 2);
+ __ SmiTag(EAX);
__ leave();
__ ret(); // Return value is in EAX.
}
@@ -91,8 +92,8 @@
TEST_CASE(CallLeafRuntimeStubCode) {
extern const Function& RegisterFakeFunction(const char* name,
const Code& code);
- const int value1 = 10;
- const int value2 = 20;
+ const char* value1 = "0xAAABBCCDDAABBCCDD";
+ const char* value2 = "0xAABBCCDDAABBCCDD";
const char* kName = "Test_CallLeafRuntimeStubCode";
Assembler _assembler_;
GenerateCallToCallLeafRuntimeStub(&_assembler_, value1, value2);
@@ -101,7 +102,7 @@
const Function& function = RegisterFakeFunction(kName, code);
Smi& result = Smi::Handle();
result ^= DartEntry::InvokeFunction(function, Object::empty_array());
- EXPECT_EQ((value1 + value2), result.Value());
+ EXPECT_EQ(1, result.Value());
}
} // namespace dart
diff --git a/runtime/vm/stub_code_mips_test.cc b/runtime/vm/stub_code_mips_test.cc
index c01edf5..512baaf 100644
--- a/runtime/vm/stub_code_mips_test.cc
+++ b/runtime/vm/stub_code_mips_test.cc
@@ -36,16 +36,15 @@
// Test calls to stub code which calls into the runtime.
static void GenerateCallToCallRuntimeStub(Assembler* assembler,
- int value1, int value2) {
+ int length) {
const int argc = 2;
- const Smi& smi1 = Smi::ZoneHandle(Smi::New(value1));
- const Smi& smi2 = Smi::ZoneHandle(Smi::New(value2));
+ const Smi& smi_length = Smi::ZoneHandle(Smi::New(length));
__ EnterDartFrame(0);
__ PushObject(Object::null_object()); // Push Null object for return value.
- __ PushObject(smi1); // Push argument 1 smi1.
- __ PushObject(smi2); // Push argument 2 smi2.
- ASSERT(kTestSmiSubRuntimeEntry.argument_count() == argc);
- __ CallRuntime(kTestSmiSubRuntimeEntry, argc); // Call SmiSub runtime func.
+ __ PushObject(smi_length); // Push argument 1: length.
+ __ PushObject(Object::null_object()); // Push argument 2: type arguments.
+ ASSERT(kAllocateArrayRuntimeEntry.argument_count() == argc);
+ __ CallRuntime(kAllocateArrayRuntimeEntry, argc);
__ addiu(SP, SP, Immediate(argc * kWordSize));
__ Pop(V0); // Pop return value from return slot.
__ LeaveDartFrameAndReturn();
@@ -55,31 +54,33 @@
TEST_CASE(CallRuntimeStubCode) {
extern const Function& RegisterFakeFunction(const char* name,
const Code& code);
- const int value1 = 10;
- const int value2 = 20;
+ const int length = 10;
const char* kName = "Test_CallRuntimeStubCode";
Assembler _assembler_;
- GenerateCallToCallRuntimeStub(&_assembler_, value1, value2);
+ GenerateCallToCallRuntimeStub(&_assembler_, length);
const Code& code = Code::Handle(Code::FinalizeCode(
*CreateFunction("Test_CallRuntimeStubCode"), &_assembler_));
const Function& function = RegisterFakeFunction(kName, code);
- Smi& result = Smi::Handle();
+ Array& result = Array::Handle();
result ^= DartEntry::InvokeFunction(function, Object::empty_array());
- EXPECT_EQ((value1 - value2), result.Value());
+ EXPECT_EQ(length, result.Length());
}
// Test calls to stub code which calls into a leaf runtime entry.
static void GenerateCallToCallLeafRuntimeStub(Assembler* assembler,
- int value1,
- int value2) {
- const Smi& smi1 = Smi::ZoneHandle(Smi::New(value1));
- const Smi& smi2 = Smi::ZoneHandle(Smi::New(value2));
+ const char* value1,
+ const char* value2) {
+ const Bigint& bigint1 =
+ Bigint::ZoneHandle(Bigint::NewFromCString(value1, Heap::kOld));
+ const Bigint& bigint2 =
+ Bigint::ZoneHandle(Bigint::NewFromCString(value2, Heap::kOld));
__ EnterDartFrame(0);
__ ReserveAlignedFrameSpace(0);
- __ LoadObject(A0, smi1); // Set up argument 1 smi1.
- __ LoadObject(A1, smi2); // Set up argument 2 smi2.
- __ CallRuntime(kTestLeafSmiAddRuntimeEntry, 2); // Call SmiAdd runtime func.
+ __ LoadObject(A0, bigint1); // Set up argument 1 bigint1.
+ __ LoadObject(A1, bigint2); // Set up argument 2 bigint2.
+ __ CallRuntime(kBigintCompareRuntimeEntry, 2);
+ __ SmiTag(V0);
__ LeaveDartFrameAndReturn(); // Return value is in V0.
}
@@ -87,8 +88,8 @@
TEST_CASE(CallLeafRuntimeStubCode) {
extern const Function& RegisterFakeFunction(const char* name,
const Code& code);
- const int value1 = 10;
- const int value2 = 20;
+ const char* value1 = "0xAAABBCCDDAABBCCDD";
+ const char* value2 = "0xAABBCCDDAABBCCDD";
const char* kName = "Test_CallLeafRuntimeStubCode";
Assembler _assembler_;
GenerateCallToCallLeafRuntimeStub(&_assembler_, value1, value2);
@@ -97,7 +98,7 @@
const Function& function = RegisterFakeFunction(kName, code);
Smi& result = Smi::Handle();
result ^= DartEntry::InvokeFunction(function, Object::empty_array());
- EXPECT_EQ((value1 + value2), result.Value());
+ EXPECT_EQ(1, result.Value());
}
} // namespace dart
diff --git a/runtime/vm/stub_code_x64_test.cc b/runtime/vm/stub_code_x64_test.cc
index d3b94dc..ff020e7 100644
--- a/runtime/vm/stub_code_x64_test.cc
+++ b/runtime/vm/stub_code_x64_test.cc
@@ -36,16 +36,15 @@
// Test calls to stub code which calls into the runtime.
static void GenerateCallToCallRuntimeStub(Assembler* assembler,
- int value1, int value2) {
+ int length) {
const int argc = 2;
- const Smi& smi1 = Smi::ZoneHandle(Smi::New(value1));
- const Smi& smi2 = Smi::ZoneHandle(Smi::New(value2));
+ const Smi& smi_length = Smi::ZoneHandle(Smi::New(length));
__ EnterStubFrame();
__ PushObject(Object::null_object()); // Push Null obj for return value.
- __ PushObject(smi1); // Push argument 1 smi1.
- __ PushObject(smi2); // Push argument 2 smi2.
- ASSERT(kTestSmiSubRuntimeEntry.argument_count() == argc);
- __ CallRuntime(kTestSmiSubRuntimeEntry, argc); // Call SmiSub runtime func.
+ __ PushObject(smi_length); // Push argument 1: length.
+ __ PushObject(Object::null_object()); // Push argument 2: type arguments.
+ ASSERT(kAllocateArrayRuntimeEntry.argument_count() == argc);
+ __ CallRuntime(kAllocateArrayRuntimeEntry, argc);
__ AddImmediate(RSP, Immediate(argc * kWordSize));
__ popq(RAX); // Pop return value from return slot.
__ LeaveStubFrame();
@@ -56,31 +55,33 @@
TEST_CASE(CallRuntimeStubCode) {
extern const Function& RegisterFakeFunction(const char* name,
const Code& code);
- const int value1 = 10;
- const int value2 = 20;
+ const int length = 10;
const char* kName = "Test_CallRuntimeStubCode";
Assembler _assembler_;
- GenerateCallToCallRuntimeStub(&_assembler_, value1, value2);
+ GenerateCallToCallRuntimeStub(&_assembler_, length);
const Code& code = Code::Handle(Code::FinalizeCode(
*CreateFunction("Test_CallRuntimeStubCode"), &_assembler_));
const Function& function = RegisterFakeFunction(kName, code);
- Smi& result = Smi::Handle();
+ Array& result = Array::Handle();
result ^= DartEntry::InvokeFunction(function, Object::empty_array());
- EXPECT_EQ((value1 - value2), result.Value());
+ EXPECT_EQ(length, result.Length());
}
// Test calls to stub code which calls into a leaf runtime entry.
static void GenerateCallToCallLeafRuntimeStub(Assembler* assembler,
- int value1,
- int value2) {
- const Smi& smi1 = Smi::ZoneHandle(Smi::New(value1));
- const Smi& smi2 = Smi::ZoneHandle(Smi::New(value2));
+ const char* value1,
+ const char* value2) {
+ const Bigint& bigint1 =
+ Bigint::ZoneHandle(Bigint::NewFromCString(value1, Heap::kOld));
+ const Bigint& bigint2 =
+ Bigint::ZoneHandle(Bigint::NewFromCString(value2, Heap::kOld));
__ EnterStubFrame();
__ ReserveAlignedFrameSpace(0);
- __ LoadObject(CallingConventions::kArg1Reg, smi1);
- __ LoadObject(CallingConventions::kArg2Reg, smi2);
- __ CallRuntime(kTestLeafSmiAddRuntimeEntry, 2); // Call SmiAdd runtime func.
+ __ LoadObject(CallingConventions::kArg1Reg, bigint1);
+ __ LoadObject(CallingConventions::kArg2Reg, bigint2);
+ __ CallRuntime(kBigintCompareRuntimeEntry, 2);
+ __ SmiTag(RAX);
__ LeaveStubFrame();
__ ret(); // Return value is in RAX.
}
@@ -89,8 +90,8 @@
TEST_CASE(CallLeafRuntimeStubCode) {
extern const Function& RegisterFakeFunction(const char* name,
const Code& code);
- const int value1 = 10;
- const int value2 = 20;
+ const char* value1 = "0xAAABBCCDDAABBCCDD";
+ const char* value2 = "0xAABBCCDDAABBCCDD";
const char* kName = "Test_CallLeafRuntimeStubCode";
Assembler _assembler_;
GenerateCallToCallLeafRuntimeStub(&_assembler_, value1, value2);
@@ -99,7 +100,7 @@
const Function& function = RegisterFakeFunction(kName, code);
Smi& result = Smi::Handle();
result ^= DartEntry::InvokeFunction(function, Object::empty_array());
- EXPECT_EQ((value1 + value2), result.Value());
+ EXPECT_EQ(1, result.Value());
}
} // namespace dart
diff --git a/runtime/vm/symbols.cc b/runtime/vm/symbols.cc
index be08181..c827704 100644
--- a/runtime/vm/symbols.cc
+++ b/runtime/vm/symbols.cc
@@ -394,30 +394,77 @@
// TODO(srdjan): If this becomes performance critical code, consider looking
-// up symbol from pieces instead of concatenating them first into a big string.
+// up symbol from hash of pieces instead of concatenating them first into
+// a string.
RawString* Symbols::FromConcatAll(
const GrowableHandlePtrArray<const String>& strs) {
- GrowableArray<const char*> cchars(strs.length());
- GrowableArray<intptr_t> lengths(strs.length());
+ const intptr_t strs_length = strs.length();
+ GrowableArray<intptr_t> lengths(strs_length);
+
intptr_t len_sum = 0;
- for (intptr_t i = 0; i < strs.length(); i++) {
- const char* to_cstr = strs[i].ToCString();
- intptr_t len = strlen(to_cstr);
- cchars.Add(to_cstr);
- lengths.Add(len);
- len_sum += len;
+ const intptr_t kOneByteChar = 1;
+ intptr_t char_size = kOneByteChar;
+
+ for (intptr_t i = 0; i < strs_length; i++) {
+ const String& str = strs[i];
+ const intptr_t str_len = str.Length();
+ if ((String::kMaxElements - len_sum) < str_len) {
+ Exceptions::ThrowOOM();
+ UNREACHABLE();
+ }
+ len_sum += str_len;
+ lengths.Add(str_len);
+ char_size = Utils::Maximum(char_size, str.CharSize());
}
+ const bool is_one_byte_string = char_size == kOneByteChar;
Zone* zone = Thread::Current()->zone();
- char* buffer = zone->Alloc<char>(len_sum);
- const char* const orig_buffer = buffer;
- for (intptr_t i = 0; i < cchars.length(); i++) {
- intptr_t len = lengths[i];
- strncpy(buffer, cchars[i], len);
- buffer += len;
+ if (is_one_byte_string) {
+ uint8_t* buffer = zone->Alloc<uint8_t>(len_sum);
+ const uint8_t* const orig_buffer = buffer;
+ for (intptr_t i = 0; i < strs_length; i++) {
+ NoSafepointScope no_safepoint;
+ intptr_t str_len = lengths[i];
+ if (str_len > 0) {
+ const String& str = strs[i];
+ ASSERT(str.IsOneByteString() || str.IsExternalOneByteString());
+ const uint8_t* src_p = str.IsOneByteString() ?
+ OneByteString::CharAddr(str, 0) :
+ ExternalOneByteString::CharAddr(str, 0);
+ memmove(buffer, src_p, str_len);
+ buffer += str_len;
+ }
+ }
+ ASSERT(len_sum == buffer - orig_buffer);
+ return Symbols::FromLatin1(orig_buffer, len_sum);
+ } else {
+ uint16_t* buffer = zone->Alloc<uint16_t>(len_sum);
+ const uint16_t* const orig_buffer = buffer;
+ for (intptr_t i = 0; i < strs_length; i++) {
+ NoSafepointScope no_safepoint;
+ intptr_t str_len = lengths[i];
+ if (str_len > 0) {
+ const String& str = strs[i];
+ if (str.IsTwoByteString()) {
+ memmove(buffer, TwoByteString::CharAddr(str, 0), str_len * 2);
+ } else if (str.IsExternalTwoByteString()) {
+ memmove(buffer, ExternalTwoByteString::CharAddr(str, 0), str_len * 2);
+ } else {
+ // One-byte to two-byte string copy.
+ ASSERT(str.IsOneByteString() || str.IsExternalOneByteString());
+ const uint8_t* src_p = str.IsOneByteString() ?
+ OneByteString::CharAddr(str, 0) :
+ ExternalOneByteString::CharAddr(str, 0);
+ for (int n = 0; n < str_len; n++) {
+ buffer[n] = src_p[n];
+ }
+ }
+ buffer += str_len;
+ }
+ }
+ ASSERT(len_sum == buffer - orig_buffer);
+ return Symbols::FromUTF16(orig_buffer, len_sum);
}
- ASSERT(len_sum == buffer - orig_buffer);
- return Symbols::New(orig_buffer, len_sum);
}
diff --git a/runtime/vm/symbols.h b/runtime/vm/symbols.h
index 29682eb..f5f7bbf 100644
--- a/runtime/vm/symbols.h
+++ b/runtime/vm/symbols.h
@@ -115,6 +115,7 @@
V(AsyncErrorWrapperHelper, "_asyncErrorWrapperHelper") \
V(AsyncAwaitHelper, "_awaitHelper") \
V(Await, "await") \
+ V(AwaitTempVarPrefix, ":await_temp_var_") \
V(AwaitContextVar, ":await_ctx_var") \
V(AwaitJumpVar, ":await_jump_var") \
V(Future, "Future") \
diff --git a/runtime/vm/thread.cc b/runtime/vm/thread.cc
index a52c1bc..d0c4651 100644
--- a/runtime/vm/thread.cc
+++ b/runtime/vm/thread.cc
@@ -10,6 +10,7 @@
#include "vm/object.h"
#include "vm/os_thread.h"
#include "vm/profiler.h"
+#include "vm/runtime_entry.h"
#include "vm/stub_code.h"
#include "vm/thread_interrupter.h"
#include "vm/thread_registry.h"
@@ -108,10 +109,22 @@
heap_(NULL),
store_buffer_block_(NULL) {
ClearState();
+
#define DEFAULT_INIT(type_name, member_name, init_expr, default_init_value) \
member_name = default_init_value;
CACHED_CONSTANTS_LIST(DEFAULT_INIT)
#undef DEFAULT_INIT
+
+#define DEFAULT_INIT(name) \
+ name##_entry_point_ = 0;
+RUNTIME_ENTRY_LIST(DEFAULT_INIT)
+#undef DEFAULT_INIT
+
+#define DEFAULT_INIT(returntype, name, ...) \
+ name##_entry_point_ = 0;
+LEAF_RUNTIME_ENTRY_LIST(DEFAULT_INIT)
+#undef DEFAULT_INIT
+
if (init_vm_constants) {
InitVMConstants();
}
@@ -130,6 +143,18 @@
member_name = (init_expr);
CACHED_CONSTANTS_LIST(INIT_VALUE)
#undef INIT_VALUE
+
+#define INIT_VALUE(name) \
+ ASSERT(name##_entry_point_ == 0); \
+ name##_entry_point_ = k##name##RuntimeEntry.GetEntryPoint();
+RUNTIME_ENTRY_LIST(INIT_VALUE)
+#undef INIT_VALUE
+
+#define INIT_VALUE(returntype, name, ...) \
+ ASSERT(name##_entry_point_ == 0); \
+ name##_entry_point_ = k##name##RuntimeEntry.GetEntryPoint();
+LEAF_RUNTIME_ENTRY_LIST(INIT_VALUE)
+#undef INIT_VALUE
}
@@ -326,4 +351,23 @@
return -1;
}
+intptr_t Thread::OffsetFromThread(const RuntimeEntry* runtime_entry) {
+#define COMPUTE_OFFSET(name) \
+ if (runtime_entry->function() == k##name##RuntimeEntry.function()) { \
+ return Thread::name##_entry_point_offset(); \
+ }
+RUNTIME_ENTRY_LIST(COMPUTE_OFFSET)
+#undef COMPUTE_OFFSET
+
+#define COMPUTE_OFFSET(returntype, name, ...) \
+ if (runtime_entry->function() == k##name##RuntimeEntry.function()) { \
+ return Thread::name##_entry_point_offset(); \
+ }
+LEAF_RUNTIME_ENTRY_LIST(COMPUTE_OFFSET)
+#undef COMPUTE_OFFSET
+
+ UNREACHABLE();
+ return -1;
+}
+
} // namespace dart
diff --git a/runtime/vm/thread.h b/runtime/vm/thread.h
index 904d751..9643c33 100644
--- a/runtime/vm/thread.h
+++ b/runtime/vm/thread.h
@@ -8,6 +8,7 @@
#include "vm/globals.h"
#include "vm/os_thread.h"
#include "vm/store_buffer.h"
+#include "vm/runtime_entry_list.h"
namespace dart {
@@ -19,11 +20,11 @@
class Object;
class RawBool;
class RawObject;
+class RuntimeEntry;
class StackResource;
class TimelineEventBlock;
class Zone;
-
// List of VM-global objects/addresses cached in each Thread object.
#define CACHED_VM_OBJECTS_LIST(V) \
V(RawObject*, object_null_, Object::null(), NULL) \
@@ -32,11 +33,11 @@
#define CACHED_ADDRESSES_LIST(V) \
V(uword, update_store_buffer_entry_point_, \
- StubCode::UpdateStoreBuffer_entry()->EntryPoint(), 0)
+ StubCode::UpdateStoreBuffer_entry()->EntryPoint(), 0) \
#define CACHED_CONSTANTS_LIST(V) \
CACHED_VM_OBJECTS_LIST(V) \
- CACHED_ADDRESSES_LIST(V)
+ CACHED_ADDRESSES_LIST(V) \
struct InterruptedThreadState {
ThreadId tid;
@@ -226,8 +227,23 @@
CACHED_CONSTANTS_LIST(DEFINE_OFFSET_METHOD)
#undef DEFINE_OFFSET_METHOD
+#define DEFINE_OFFSET_METHOD(name) \
+ static intptr_t name##_entry_point_offset() { \
+ return OFFSET_OF(Thread, name##_entry_point_); \
+ }
+RUNTIME_ENTRY_LIST(DEFINE_OFFSET_METHOD)
+#undef DEFINE_OFFSET_METHOD
+
+#define DEFINE_OFFSET_METHOD(returntype, name, ...) \
+ static intptr_t name##_entry_point_offset() { \
+ return OFFSET_OF(Thread, name##_entry_point_); \
+ }
+LEAF_RUNTIME_ENTRY_LIST(DEFINE_OFFSET_METHOD)
+#undef DEFINE_OFFSET_METHOD
+
static bool CanLoadFromThread(const Object& object);
static intptr_t OffsetFromThread(const Object& object);
+ static intptr_t OffsetFromThread(const RuntimeEntry* runtime_entry);
TimelineEventBlock* timeline_block() const {
return state_.timeline_block;
@@ -267,6 +283,16 @@
CACHED_CONSTANTS_LIST(DECLARE_MEMBERS)
#undef DECLARE_MEMBERS
+#define DECLARE_MEMBERS(name) \
+ uword name##_entry_point_;
+RUNTIME_ENTRY_LIST(DECLARE_MEMBERS)
+#undef DECLARE_MEMBERS
+
+#define DECLARE_MEMBERS(returntype, name, ...) \
+ uword name##_entry_point_;
+LEAF_RUNTIME_ENTRY_LIST(DECLARE_MEMBERS)
+#undef DECLARE_MEMBERS
+
explicit Thread(bool init_vm_constants = true);
void InitVMConstants();
diff --git a/runtime/vm/thread_test.cc b/runtime/vm/thread_test.cc
index 560aa1c..545ed8a 100644
--- a/runtime/vm/thread_test.cc
+++ b/runtime/vm/thread_test.cc
@@ -385,7 +385,6 @@
// organized by
// - helpers.
TEST_CASE(SafepointTestVM) {
- Thread* thread = Thread::Current();
Isolate* isolate = thread->isolate();
Mutex mutex;
intptr_t expected_count = 0;
@@ -415,7 +414,6 @@
// - main thread, and
// - helpers.
TEST_CASE(SafepointTestVM2) {
- Thread* thread = Thread::Current();
Isolate* isolate = thread->isolate();
Mutex mutex;
intptr_t expected_count = 0;
diff --git a/runtime/vm/timeline_test.cc b/runtime/vm/timeline_test.cc
index 6657e04..8cb358f 100644
--- a/runtime/vm/timeline_test.cc
+++ b/runtime/vm/timeline_test.cc
@@ -322,7 +322,6 @@
TimelineTestHelper::FakeThreadEvent(block_2_0, 2, "E");
TimelineTestHelper::FakeThreadEvent(block_2_0, 2, "F");
- Thread* thread = Thread::Current();
Zone* zone = thread->zone();
Isolate* isolate = thread->isolate();
@@ -440,7 +439,6 @@
TEST_CASE(TimelinePauses_Basic) {
TimelineEventEndlessRecorder* recorder = new TimelineEventEndlessRecorder();
ASSERT(recorder != NULL);
- Thread* thread = Thread::Current();
Zone* zone = thread->zone();
Isolate* isolate = thread->isolate();
ThreadId tid = OSThread::GetCurrentThreadId();
diff --git a/runtime/vm/unit_test.h b/runtime/vm/unit_test.h
index c9c4812..1edeb15 100644
--- a/runtime/vm/unit_test.h
+++ b/runtime/vm/unit_test.h
@@ -30,7 +30,7 @@
// The TEST_CASE macro is used for tests that need an isolate and zone
// in order to test its functionality.
#define TEST_CASE(name) \
- static void Dart_TestHelper##name(); \
+ static void Dart_TestHelper##name(Thread* thread); \
UNIT_TEST_CASE(name) \
{ \
TestIsolateScope __test_isolate__; \
@@ -38,9 +38,9 @@
ASSERT(__thread__->isolate() == __test_isolate__.isolate()); \
StackZone __zone__(__thread__); \
HandleScope __hs__(__thread__); \
- Dart_TestHelper##name(); \
+ Dart_TestHelper##name(__thread__); \
} \
- static void Dart_TestHelper##name()
+ static void Dart_TestHelper##name(Thread* thread)
// The ASSEMBLER_TEST_GENERATE macro is used to generate a unit test
// for the assembler.
diff --git a/runtime/vm/vm_sources.gypi b/runtime/vm/vm_sources.gypi
index e6902f8..6eb0056 100644
--- a/runtime/vm/vm_sources.gypi
+++ b/runtime/vm/vm_sources.gypi
@@ -377,11 +377,12 @@
'ring_buffer.h',
'ring_buffer_test.cc',
'runtime_entry.h',
+ 'runtime_entry_list.h',
'runtime_entry_arm.cc',
'runtime_entry_arm64.cc',
'runtime_entry_ia32.cc',
'runtime_entry_mips.cc',
- 'runtime_entry_test.cc',
+ 'runtime_entry.cc',
'runtime_entry_x64.cc',
'scanner.cc',
'scanner.h',
diff --git a/runtime/vm/zone.h b/runtime/vm/zone.h
index 79591a5..4850e5e 100644
--- a/runtime/vm/zone.h
+++ b/runtime/vm/zone.h
@@ -178,13 +178,15 @@
public:
// Create an empty zone and set is at the current zone for the Thread.
explicit StackZone(Thread* thread) : StackResource(thread), zone_() {
- Initialize();
- }
-
- // DEPRECATED: Use Thread-based interface. During migration, this defaults
- // to using the mutator thread (which must also be the current thread).
- explicit StackZone(Isolate* isolate) : StackResource(isolate), zone_() {
- Initialize();
+#ifdef DEBUG
+ if (FLAG_trace_zones) {
+ OS::PrintErr("*** Starting a new Stack zone 0x%" Px "(0x%" Px ")\n",
+ reinterpret_cast<intptr_t>(this),
+ reinterpret_cast<intptr_t>(&zone_));
+ }
+#endif
+ zone_.Link(thread->zone());
+ thread->set_zone(&zone_);
}
// Delete all memory associated with the zone.
@@ -209,18 +211,6 @@
private:
Zone zone_;
- void Initialize() {
-#ifdef DEBUG
- if (FLAG_trace_zones) {
- OS::PrintErr("*** Starting a new Stack zone 0x%" Px "(0x%" Px ")\n",
- reinterpret_cast<intptr_t>(this),
- reinterpret_cast<intptr_t>(&zone_));
- }
-#endif
- zone_.Link(thread()->zone());
- thread()->set_zone(&zone_);
- }
-
template<typename T> friend class GrowableArray;
template<typename T> friend class ZoneGrowableArray;
diff --git a/runtime/vm/zone_test.cc b/runtime/vm/zone_test.cc
index 9c43743..dceddbf 100644
--- a/runtime/vm/zone_test.cc
+++ b/runtime/vm/zone_test.cc
@@ -18,11 +18,11 @@
#endif
Dart_CreateIsolate(
NULL, NULL, bin::isolate_snapshot_buffer, NULL, NULL, NULL);
- Isolate* isolate = Isolate::Current();
- EXPECT(isolate->current_zone() == NULL);
+ Thread* thread = Thread::Current();
+ EXPECT(thread->zone() == NULL);
{
- StackZone stack_zone(isolate);
- EXPECT(isolate->current_zone() != NULL);
+ StackZone stack_zone(thread);
+ EXPECT(thread->zone() != NULL);
Zone* zone = stack_zone.GetZone();
intptr_t allocated_size = 0;
@@ -69,7 +69,7 @@
allocated_size += (kSegmentSize + kWordSize);
EXPECT_LE(allocated_size, zone->SizeInBytes());
}
- EXPECT(isolate->current_zone() == NULL);
+ EXPECT(thread->zone() == NULL);
Dart_ShutdownIsolate();
}
@@ -80,11 +80,11 @@
#endif
Dart_CreateIsolate(
NULL, NULL, bin::isolate_snapshot_buffer, NULL, NULL, NULL);
- Isolate* isolate = Isolate::Current();
- EXPECT(isolate->current_zone() == NULL);
+ Thread* thread = Thread::Current();
+ EXPECT(thread->zone() == NULL);
{
- StackZone zone(isolate);
- EXPECT(isolate->current_zone() != NULL);
+ StackZone zone(thread);
+ EXPECT(thread->zone() != NULL);
intptr_t allocated_size = 0;
const intptr_t kNumElements = 1000;
@@ -92,7 +92,7 @@
allocated_size += sizeof(uint32_t) * kNumElements;
EXPECT_LE(allocated_size, zone.SizeInBytes());
}
- EXPECT(isolate->current_zone() == NULL);
+ EXPECT(thread->zone() == NULL);
Dart_ShutdownIsolate();
}
@@ -104,11 +104,11 @@
#endif
Dart_CreateIsolate(
NULL, NULL, bin::isolate_snapshot_buffer, NULL, NULL, NULL);
- Isolate* isolate = Isolate::Current();
- EXPECT(isolate->current_zone() == NULL);
+ Thread* thread = Thread::Current();
+ EXPECT(thread->zone() == NULL);
{
- StackZone zone(isolate);
- EXPECT(isolate->current_zone() != NULL);
+ StackZone zone(thread);
+ EXPECT(thread->zone() != NULL);
const intptr_t kNumElements = (kIntptrMax / sizeof(uint32_t)) + 1;
zone.GetZone()->Alloc<uint32_t>(kNumElements);
@@ -123,8 +123,8 @@
#endif
Dart_CreateIsolate(
NULL, NULL, bin::isolate_snapshot_buffer, NULL, NULL, NULL);
- Isolate* isolate = Isolate::Current();
- EXPECT(isolate->current_zone() == NULL);
+ Thread* thread = Thread::Current();
+ EXPECT(thread->zone() == NULL);
static int marker;
class SimpleZoneObject : public ZoneAllocated {
@@ -140,7 +140,7 @@
// Create a few zone allocated objects.
{
- StackZone zone(isolate);
+ StackZone zone(thread);
EXPECT_EQ(0, zone.SizeInBytes());
SimpleZoneObject* first = new SimpleZoneObject();
EXPECT(first != NULL);
@@ -160,7 +160,7 @@
EXPECT_EQ(42, first->slot);
EXPECT_EQ(87, second->slot);
}
- EXPECT(isolate->current_zone() == NULL);
+ EXPECT(thread->zone() == NULL);
Dart_ShutdownIsolate();
}
diff --git a/sdk/bin/dartdoc.bat b/sdk/bin/dartdoc.bat
index 58c2017..c313e7f 100644
--- a/sdk/bin/dartdoc.bat
+++ b/sdk/bin/dartdoc.bat
@@ -14,7 +14,7 @@
set DART=%BIN_DIR%\dart
set SNAPSHOT=%BIN_DIR%\snapshots\dartdoc.dart.snapshot
-"%DART%" --packages="$BIN_DIR/snapshots/resources/dartdoc/.packages" "%SNAPSHOT%" %*
+"%DART%" --packages="%BIN_DIR%/snapshots/resources/dartdoc/.packages" "%SNAPSHOT%" %*
endlocal
diff --git a/site/try/poi/poi.dart b/site/try/poi/poi.dart
index d523f80..b9f7753 100644
--- a/site/try/poi/poi.dart
+++ b/site/try/poi/poi.dart
@@ -60,13 +60,17 @@
import 'package:compiler/src/dart_types.dart' show
DartType;
-import 'package:compiler/src/scanner/scannerlib.dart' show
+import 'package:compiler/src/parser/partial_elements.dart' show
+ PartialClassElement,
+ PartialElement;
+
+import 'package:compiler/src/tokens/token.dart' show
+ Token;
+
+import 'package:compiler/src/tokens/token_constants.dart' show
EOF_TOKEN,
IDENTIFIER_TOKEN,
- KEYWORD_TOKEN,
- PartialClassElement,
- PartialElement,
- Token;
+ KEYWORD_TOKEN;
import 'package:compiler/src/js/js.dart' show
js;
diff --git a/site/try/src/editor.dart b/site/try/src/editor.dart
index 1345404..abe3f3c 100644
--- a/site/try/src/editor.dart
+++ b/site/try/src/editor.dart
@@ -6,12 +6,16 @@
import 'dart:html';
-import 'package:compiler/src/scanner/scannerlib.dart' show
- EOF_TOKEN,
+import 'package:compiler/src/scanner/string_scanner.dart' show
+ StringScanner;
+
+import 'package:compiler/src/tokens/token.dart' show
ErrorToken,
- StringScanner,
Token;
+import 'package:compiler/src/tokens/token_constants.dart' show
+ EOF_TOKEN;
+
import 'ui.dart' show
currentTheme,
hackDiv,
diff --git a/site/try/src/interaction_manager.dart b/site/try/src/interaction_manager.dart
index 2c566e3..89ddf76 100644
--- a/site/try/src/interaction_manager.dart
+++ b/site/try/src/interaction_manager.dart
@@ -21,18 +21,22 @@
import 'dart:collection' show
Queue;
-import 'package:compiler/src/scanner/scannerlib.dart' show
+import 'package:compiler/src/scanner/string_scanner.dart' show
+ StringScanner;
+
+import 'package:compiler/src/tokens/token.dart' show
BeginGroupToken,
- EOF_TOKEN,
ErrorToken,
- STRING_INTERPOLATION_IDENTIFIER_TOKEN,
- STRING_INTERPOLATION_TOKEN,
- STRING_TOKEN,
- StringScanner,
Token,
UnmatchedToken,
UnterminatedToken;
+import 'package:compiler/src/tokens/token_constants.dart' show
+ EOF_TOKEN,
+ STRING_INTERPOLATION_IDENTIFIER_TOKEN,
+ STRING_INTERPOLATION_TOKEN,
+ STRING_TOKEN;
+
import 'package:compiler/src/io/source_file.dart' show
StringSourceFile;
diff --git a/tests/co19/co19-dart2js.status b/tests/co19/co19-dart2js.status
index 0d1832d..019e273 100644
--- a/tests/co19/co19-dart2js.status
+++ b/tests/co19/co19-dart2js.status
@@ -4,8 +4,8 @@
[ $compiler == dart2js ]
Language/12_Expressions/00_Object_Identity/1_Object_Identity_A05_t02: RuntimeError # Issue 1533 (int/double related)
-Language/03_Overview/1_Scoping_A02_t05: CompileTimeError # Issue 21072
-Language/03_Overview/1_Scoping_A02_t06: CompileTimeError # Issue 21072
+Language/03_Overview/1_Scoping_A02_t05: RuntimeError # co19 issue 3
+Language/03_Overview/1_Scoping_A02_t06: RuntimeError # co19 issue 3
Language/03_Overview/1_Scoping_A02_t28: fail # Issue 21092 and co19 issue 713
Language/05_Variables/05_Variables_A05_t01: fail # Issue 21093
Language/05_Variables/05_Variables_A05_t02: fail # Issue 21093
@@ -26,9 +26,6 @@
Language/07_Classes/6_Constructors/1_Generative_Constructors_A13_t01: RuntimeError # compiler cancelled: cannot resolve type T
Language/07_Classes/6_Constructors/1_Generative_Constructors_A13_t01: RuntimeError, OK # co19 issue 258
Language/07_Classes/6_Constructors/1_Generative_Constructors_A20_t02: fail # Issue 13363
-Language/07_Classes/6_Constructors/2_Factories_A08_t02: fail # Issue 21202
-Language/07_Classes/6_Constructors/2_Factories_A10_t02: fail # Issue 21202
-Language/07_Classes/6_Constructors/2_Factories_A10_t03: fail # Issue 21202
Language/10_Generics/09_Generics_A01_t17: fail # Issue 21203
Language/12_Expressions/00_Object_Identity/1_Object_Identity_A02_t02: fail # Issue 11551, also related to issue 563, 18738
Language/12_Expressions/00_Object_Identity/1_Object_Identity_A06_t01: fail # Issue 11551, also related to issue 563, 18738
@@ -36,11 +33,6 @@
Language/12_Expressions/03_Numbers_A01_t06: fail # Issue 21098
Language/12_Expressions/03_Numbers_A01_t09: fail # Issue 21098
Language/12_Expressions/07_Maps_A11_t01: CompileTimeError # Maybe ok. Issue 17207
-Language/12_Expressions/12_Instance_Creation/1_New_A02_t03: fail # Issue 21092 and co19 issue 713
-Language/12_Expressions/12_Instance_Creation/1_New_A02_t05: fail # Issue 21092 and co19 issue 713
-Language/12_Expressions/12_Instance_Creation/1_New_A02_t06: fail # Issue 21092 and co19 issue 713
-Language/12_Expressions/12_Instance_Creation/1_New_A02_t07: fail # Issue 21092 and co19 issue 713
-Language/12_Expressions/12_Instance_Creation/1_New_A06_t15: CompileTimeError # Issue 21092
Language/12_Expressions/12_Instance_Creation/2_Const_A11_t01: fail # Issue 21134 and co19 issue 714
Language/12_Expressions/12_Instance_Creation/2_Const_A11_t03: fail # Issue 21134 and co19 issue 714
Language/12_Expressions/30_Identifier_Reference_A02_t01: fail # Issue 21154
diff --git a/tests/compiler/dart2js/backend_dart/dart_printer_test.dart b/tests/compiler/dart2js/backend_dart/dart_printer_test.dart
index 3ab7e86..801b75d 100644
--- a/tests/compiler/dart2js/backend_dart/dart_printer_test.dart
+++ b/tests/compiler/dart2js/backend_dart/dart_printer_test.dart
@@ -13,7 +13,11 @@
import 'package:compiler/src/diagnostics/diagnostic_listener.dart';
import 'package:compiler/src/diagnostics/messages.dart';
import 'package:compiler/src/diagnostics/spannable.dart' show Spannable;
-import 'package:compiler/src/scanner/scannerlib.dart';
+import 'package:compiler/src/parser/listener.dart';
+import 'package:compiler/src/parser/parser.dart';
+import 'package:compiler/src/scanner/scanner.dart';
+import 'package:compiler/src/tokens/token.dart';
+import 'package:compiler/src/tokens/token_constants.dart';
import 'package:compiler/src/io/source_file.dart';
import 'package:compiler/src/string_validator.dart';
import 'package:compiler/src/tree/tree.dart' show DartString;
diff --git a/tests/compiler/dart2js/exit_code_test.dart b/tests/compiler/dart2js/exit_code_test.dart
index 30c61ac..70b8172 100644
--- a/tests/compiler/dart2js/exit_code_test.dart
+++ b/tests/compiler/dart2js/exit_code_test.dart
@@ -27,7 +27,7 @@
import 'package:compiler/src/null_compiler_output.dart';
import 'package:compiler/src/old_to_new_api.dart';
import 'package:compiler/src/resolution/resolution.dart';
-import 'package:compiler/src/scanner/scannerlib.dart';
+import 'package:compiler/src/scanner/scanner_task.dart';
class TestCompiler extends apiimpl.Compiler {
final String testMarker;
diff --git a/tests/compiler/dart2js/js_backend_cps_ir_closures_test.dart b/tests/compiler/dart2js/js_backend_cps_ir_closures_test.dart
index f5345c0..820be3e 100644
--- a/tests/compiler/dart2js/js_backend_cps_ir_closures_test.dart
+++ b/tests/compiler/dart2js/js_backend_cps_ir_closures_test.dart
@@ -20,10 +20,26 @@
""",
r"""
function(x) {
- var _box_0 = {};
+ P.print(J.getInterceptor$ns(x).$add(x, "1"));
+}"""),
+
+ const TestEntry("""
+main(x) {
+ a() {
+ return x;
+ }
+ x = x + '1';
+ print(a());
+ return a;
+}
+""",
+r"""
+function(x) {
+ var _box_0 = {}, a = new V.main_a(_box_0);
_box_0._captured_x_0 = x;
_box_0._captured_x_0 = J.getInterceptor$ns(x = _box_0._captured_x_0).$add(x, "1");
- P.print(new V.main_a(_box_0).call$0());
+ P.print(a.call$0());
+ return a;
}"""),
const TestEntry("""
@@ -36,7 +52,23 @@
""",
r"""
function(x) {
- P.print(new V.main_a(x).call$0());
+ P.print(x);
+}"""),
+
+ const TestEntry("""
+main(x) {
+ a() {
+ return x;
+ }
+ print(a());
+ return a;
+}
+""",
+r"""
+function(x) {
+ var a = new V.main_a(x);
+ P.print(a.call$0());
+ return a;
}"""),
const TestEntry("""
@@ -49,10 +81,25 @@
""",
r"""
function() {
- var _box_0 = {};
+ P.print(122 + 1);
+}"""),
+
+ const TestEntry("""
+main() {
+ var x = 122;
+ var a = () => x;
+ x = x + 1;
+ print(a());
+ return a;
+}
+""",
+r"""
+function() {
+ var _box_0 = {}, a = new V.main_closure(_box_0);
_box_0._captured_x_0 = 122;
_box_0._captured_x_0 = _box_0._captured_x_0 + 1;
- P.print(new V.main_closure(_box_0).call$0());
+ P.print(a.call$0());
+ return a;
}"""),
const TestEntry("""
@@ -68,10 +115,28 @@
""",
r"""
function() {
- var _box_0 = {};
+ P.print(122 + 1);
+}"""),
+
+ const TestEntry("""
+main() {
+ var x = 122;
+ var a = () {
+ var y = x;
+ return () => y;
+ };
+ x = x + 1;
+ print(a()());
+ return a;
+}
+""",
+r"""
+function() {
+ var _box_0 = {}, a = new V.main_closure(_box_0);
_box_0._captured_x_0 = 122;
_box_0._captured_x_0 = _box_0._captured_x_0 + 1;
- P.print(new V.main_closure(_box_0).call$0().call$0());
+ P.print(a.call$0().call$0());
+ return a;
}"""),
const TestEntry("""
diff --git a/tests/compiler/dart2js/js_backend_cps_ir_operators_test.dart b/tests/compiler/dart2js/js_backend_cps_ir_operators_test.dart
index 97de317..1665195 100644
--- a/tests/compiler/dart2js/js_backend_cps_ir_operators_test.dart
+++ b/tests/compiler/dart2js/js_backend_cps_ir_operators_test.dart
@@ -40,14 +40,14 @@
main() { print(foo && foo); }
""", """
function() {
- P.print(V.foo() ? V.foo() === true : false);
+ P.print(V.foo() ? !!V.foo() : false);
}"""),
const TestEntry("""
get foo => foo;
main() { print(foo || foo); }
""","""
function() {
- P.print(V.foo() ? true : V.foo() === true);
+ P.print(V.foo() ? true : !!V.foo());
}"""),
// Needs interceptor calling convention
diff --git a/tests/compiler/dart2js/lookup_map_test.dart b/tests/compiler/dart2js/lookup_map_test.dart
new file mode 100644
index 0000000..d73bc75
--- /dev/null
+++ b/tests/compiler/dart2js/lookup_map_test.dart
@@ -0,0 +1,261 @@
+// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library tests.dart2js.lookup_map_test;
+
+import 'package:test/test.dart';
+import 'compiler_helper.dart';
+
+main() {
+ test('live entries are kept', () async {
+ String generated = await compileAll(r"""
+ import 'package:lookup_map/lookup_map.dart';
+ class A{}
+ const map = const LookupMap(const [
+ A, "the-text-for-A",
+ ]);
+ main() => print(map[A]);
+ """);
+ expect(generated, contains("the-text-for-A"));
+ });
+
+ test('live entries are kept - single-pair', () async {
+ String generated = await compileAll(r"""
+ import 'package:lookup_map/lookup_map.dart';
+ class A{}
+ const map = const LookupMap.pair(A, "the-text-for-A");
+ main() => print(map[A]);
+ """);
+ expect(generated, contains("the-text-for-A"));
+ });
+
+ test('unused entries are removed', () async {
+ String generated = await compileAll(r"""
+ import 'package:lookup_map/lookup_map.dart';
+ class A{}
+ class B{}
+ const map = const LookupMap(const [
+ A, "the-text-for-A",
+ B, "the-text-for-B",
+ ]);
+ main() => print(map[A]);
+ """);
+ expect(generated, isNot(contains("the-text-for-B")));
+ });
+
+ test('unused entries are removed - nested maps', () async {
+ String generated = await compileAll(r"""
+ import 'package:lookup_map/lookup_map.dart';
+ class A{}
+ class B{}
+ const map = const LookupMap(const [], const [
+ const LookupMap(const [
+ A, "the-text-for-A",
+ B, "the-text-for-B",
+ ]),
+ ]);
+ main() => print(map[A]);
+ """);
+ expect(generated, isNot(contains("the-text-for-B")));
+ });
+
+ test('unused entries are removed - single-pair', () async {
+ String generated = await compileAll(r"""
+ import 'package:lookup_map/lookup_map.dart';
+ class A{}
+ class B{}
+ const map = const LookupMap.pair(A, "the-text-for-A");
+ main() => print(map[A]);
+ """);
+ expect(generated, isNot(contains("the-text-for-B")));
+ });
+
+ test('unused entries are removed - nested single-pair', () async {
+ String generated = await compileAll(r"""
+ import 'package:lookup_map/lookup_map.dart';
+ class A{}
+ class B{}
+ const map = const LookupMap(const [], const [
+ const LookupMap.pair(A, "the-text-for-A"),
+ const LookupMap.pair(B, "the-text-for-B"),
+ ]);
+ main() => print(map[A]);
+ """);
+ expect(generated, isNot(contains("the-text-for-B")));
+ });
+
+ test('works if entries are declared separate from map', () async {
+ String generated = await compileAll(r"""
+ import 'package:lookup_map/lookup_map.dart';
+ class A{}
+ class B{}
+ const entries = const [
+ A, "the-text-for-A",
+ B, "the-text-for-B",
+ ];
+ const map = const LookupMap(entries);
+ main() => print(map[A]);
+ """);
+ expect(generated, isNot(contains("the-text-for-B")));
+ });
+
+ test('escaping entries disable tree-shaking', () async {
+ String generated = await compileAll(r"""
+ import 'package:lookup_map/lookup_map.dart';
+ class A{}
+ class B{}
+ const entries = const [
+ A, "the-text-for-A",
+ B, "the-text-for-B",
+ ];
+ const map = const LookupMap(entries);
+ main() {
+ entries.forEach(print);
+ print(map[A]);
+ }
+ """);
+ expect(generated, contains("the-text-for-B"));
+ });
+
+ test('uses include recursively reachable data', () async {
+ String generated = await compileAll(r"""
+ import 'package:lookup_map/lookup_map.dart';
+ class A{}
+ class B{}
+ class C{}
+ class D{}
+ class E{}
+ const map = const LookupMap(const [
+ A, const ["the-text-for-A", B],
+ B, const ["the-text-for-B", C],
+ C, const ["the-text-for-C"],
+ D, const ["the-text-for-D", E],
+ E, const ["the-text-for-E"],
+ ]);
+ main() => print(map[map[A][1]]);
+ """);
+ expect(generated, contains("the-text-for-A"));
+ expect(generated, contains("the-text-for-B"));
+ expect(generated, contains("the-text-for-C"));
+ expect(generated, isNot(contains("the-text-for-D")));
+ expect(generated, isNot(contains("the-text-for-E")));
+ });
+
+ test('uses are found through newly discovered code', () async {
+ String generated = await compileAll(r"""
+ import 'package:lookup_map/lookup_map.dart';
+ class A{ A(B x);}
+ class B{}
+ class C{}
+ class D{}
+ class E{}
+ createA() => new A(map[B][1]());
+ createB() => new B();
+ const map = const LookupMap(const [
+ A, const ["the-text-for-A", createA],
+ B, const ["the-text-for-B", createB],
+ C, const ["the-text-for-C"],
+ ]);
+ main() => print(map[A][1]());
+ """);
+ expect(generated, contains("the-text-for-A"));
+ expect(generated, contains("the-text-for-B"));
+ expect(generated, isNot(contains("the-text-for-C")));
+ });
+
+ test('generic type allocations are considered used', () async {
+ String generated = await compileAll(r"""
+ import 'package:lookup_map/lookup_map.dart';
+ class A{}
+ class M<T>{ get type => T; }
+ const map = const LookupMap(const [
+ A, "the-text-for-A",
+ ]);
+ main() => print(map[new M<A>().type]);
+ """);
+ expect(generated, contains("the-text-for-A"));
+ });
+
+ test('generics in type signatures are ignored', () async {
+ String generated = await compileAll(r"""
+ import 'package:lookup_map/lookup_map.dart';
+ class A{}
+ class B{}
+ class M<T>{ get type => T; }
+ _factory(M<B> t) => t;
+ const map = const LookupMap(const [
+ A, const ["the-text-for-A", _factory],
+ B, "the-text-for-B",
+ ]);
+ main() => print(map[A]);
+ """);
+ expect(generated, isNot(contains("the-text-for-B")));
+ });
+
+ test('metadata is ignored', () async {
+ String generated = await compileAll(r"""
+ import 'package:lookup_map/lookup_map.dart';
+ class A{ const A(); }
+
+ @A()
+ class M {}
+ const map = const LookupMap(const [
+ A, "the-text-for-A",
+ ]);
+ main() => print(map[M]);
+ """);
+ expect(generated, isNot(contains("the-text-for-A")));
+ });
+
+ test('shared constants used in metadata are ignored', () async {
+ String generated = await compileAll(r"""
+ import 'package:lookup_map/lookup_map.dart';
+ const annot = const B(foo: A);
+
+ @B(foo: annot)
+ class A{ const A(); }
+ class B{ final Type foo; const B({this.foo}); }
+
+ class M {}
+ const map = const LookupMap(const [
+ A, const ["the-text-for-A", annot]
+ ]);
+ main() => print(map[M]);
+ """);
+ expect(generated, isNot(contains("the-text-for-A")));
+ });
+
+ // regression test for a failure when looking up `dynamic` in a generic.
+ test('do not choke on dynamic types', () async {
+ await compileAll(r"""
+ import 'package:lookup_map/lookup_map.dart';
+ class A{}
+ class M<T>{ get type => T; }
+ const map = const LookupMap(const [
+ A, "the-text-for-A",
+ ]);
+ main() => print(map[new M<dynamic>().type]);
+ """);
+ });
+
+
+ test('support subclassing LookupMap', () async {
+ String generated = await compileAll(r"""
+ import 'package:lookup_map/lookup_map.dart';
+ class A{}
+ class B{}
+ class S extends LookupMap {
+ const S(list) : super(list);
+ }
+ const map = const S(const [
+ A, "the-text-for-A",
+ B, "the-text-for-B",
+ ]);
+
+ main() => print(map[A]);
+ """);
+ expect(generated, contains("the-text-for-A"));
+ expect(generated, isNot(contains("the-text-for-B")));
+ });
+}
diff --git a/tests/compiler/dart2js/metadata_test.dart b/tests/compiler/dart2js/metadata_test.dart
index 847f469..b304b4f 100644
--- a/tests/compiler/dart2js/metadata_test.dart
+++ b/tests/compiler/dart2js/metadata_test.dart
@@ -7,7 +7,8 @@
show PrimitiveConstantValue;
import 'package:expect/expect.dart';
import 'compiler_helper.dart';
-import 'parser_helper.dart';
+import 'package:compiler/src/parser/partial_elements.dart' show
+ PartialMetadataAnnotation;
void checkPosition(Spannable spannable, Node node, String source, compiler) {
SourceSpan span = compiler.spanFromSpannable(spannable);
diff --git a/tests/compiler/dart2js/mock_compiler.dart b/tests/compiler/dart2js/mock_compiler.dart
index 2a9a39f..e185712 100644
--- a/tests/compiler/dart2js/mock_compiler.dart
+++ b/tests/compiler/dart2js/mock_compiler.dart
@@ -134,6 +134,8 @@
}
registerSource(Uris.dart_async,
buildLibrarySource(asyncLibrarySource));
+ registerSource(JavaScriptBackend.PACKAGE_LOOKUP_MAP,
+ buildLibrarySource(DEFAULT_LOOKUP_MAP_LIBRARY));
}
String get patchVersion {
diff --git a/tests/compiler/dart2js/mock_libraries.dart b/tests/compiler/dart2js/mock_libraries.dart
index d70afdb..2031cf0 100644
--- a/tests/compiler/dart2js/mock_libraries.dart
+++ b/tests/compiler/dart2js/mock_libraries.dart
@@ -398,3 +398,19 @@
'MirrorSystem': 'class MirrorSystem {}',
'MirrorsUsed': 'class MirrorsUsed {}',
};
+
+const Map<String, String> DEFAULT_LOOKUP_MAP_LIBRARY = const <String, String>{
+ 'LookupMap': r'''
+ class LookupMap<T> {
+ final _key;
+ final _value;
+ final _entries;
+ final _nestedMaps;
+
+ const LookupMap(this._entries, [this._nestedMaps = const []])
+ : _key = null, _value = null;
+
+ const LookupMap.pair(this._key, this._value)
+ : _entries = const [], _nestedMaps = const [];
+ }''',
+};
diff --git a/tests/compiler/dart2js/parser_helper.dart b/tests/compiler/dart2js/parser_helper.dart
index c2d3bdf..da04e38 100644
--- a/tests/compiler/dart2js/parser_helper.dart
+++ b/tests/compiler/dart2js/parser_helper.dart
@@ -8,7 +8,13 @@
import "package:compiler/src/elements/elements.dart";
import "package:compiler/src/tree/tree.dart";
-import "package:compiler/src/scanner/scannerlib.dart";
+import "package:compiler/src/parser/element_listener.dart";
+import "package:compiler/src/parser/node_listener.dart";
+import "package:compiler/src/parser/parser.dart";
+import "package:compiler/src/parser/partial_parser.dart";
+import "package:compiler/src/scanner/string_scanner.dart";
+import "package:compiler/src/tokens/token.dart";
+import "package:compiler/src/tokens/token_constants.dart";
import "package:compiler/src/io/source_file.dart";
import "package:compiler/src/util/util.dart";
@@ -23,8 +29,13 @@
import "package:compiler/src/script.dart";
export "package:compiler/src/diagnostics/diagnostic_listener.dart";
-// TODO(ahe): We should have token library to export instead.
-export "package:compiler/src/scanner/scannerlib.dart";
+export 'package:compiler/src/parser/listener.dart';
+export 'package:compiler/src/parser/node_listener.dart';
+export 'package:compiler/src/parser/parser.dart';
+export 'package:compiler/src/parser/partial_parser.dart';
+export 'package:compiler/src/parser/partial_elements.dart';
+export "package:compiler/src/tokens/token.dart";
+export "package:compiler/src/tokens/token_constants.dart";
class LoggerCanceler implements DiagnosticListener {
void log(message) {
diff --git a/tests/compiler/dart2js/scanner_offset_length_test.dart b/tests/compiler/dart2js/scanner_offset_length_test.dart
index 4c428dd..3eb5bb5 100644
--- a/tests/compiler/dart2js/scanner_offset_length_test.dart
+++ b/tests/compiler/dart2js/scanner_offset_length_test.dart
@@ -3,7 +3,9 @@
// BSD-style license that can be found in the LICENSE file.
import "package:expect/expect.dart";
-import 'package:compiler/src/scanner/scannerlib.dart';
+import 'package:compiler/src/scanner/string_scanner.dart';
+import 'package:compiler/src/tokens/token.dart';
+import 'package:compiler/src/tokens/token_constants.dart';
Token scan(String text) =>
new StringScanner.fromString(text, includeComments: true).tokenize();
diff --git a/tests/compiler/dart2js/scanner_test.dart b/tests/compiler/dart2js/scanner_test.dart
index e3a82fb..453ba42 100644
--- a/tests/compiler/dart2js/scanner_test.dart
+++ b/tests/compiler/dart2js/scanner_test.dart
@@ -3,7 +3,9 @@
// BSD-style license that can be found in the LICENSE file.
import "package:expect/expect.dart";
-import 'package:compiler/src/scanner/scannerlib.dart';
+import 'package:compiler/src/scanner/utf8_bytes_scanner.dart';
+import 'package:compiler/src/tokens/precedence_constants.dart';
+import 'package:compiler/src/tokens/token.dart';
import 'package:compiler/src/util/characters.dart';
import 'dart:typed_data';
diff --git a/tests/compiler/dart2js/unparser2_test.dart b/tests/compiler/dart2js/unparser2_test.dart
index 00a3030..a4a8aed 100644
--- a/tests/compiler/dart2js/unparser2_test.dart
+++ b/tests/compiler/dart2js/unparser2_test.dart
@@ -3,7 +3,10 @@
// BSD-style license that can be found in the LICENSE file.
import "package:expect/expect.dart";
-import "package:compiler/src/scanner/scannerlib.dart";
+import "package:compiler/src/parser/node_listener.dart";
+import "package:compiler/src/parser/parser.dart";
+import "package:compiler/src/scanner/string_scanner.dart";
+import "package:compiler/src/tokens/token.dart";
import "package:compiler/src/tree/tree.dart";
import "package:compiler/src/diagnostics/diagnostic_listener.dart";
diff --git a/tests/compiler/dart2js_extra/lookup_map/dead_entry_single_nested_pairs_test.dart b/tests/compiler/dart2js_extra/lookup_map/dead_entry_single_nested_pairs_test.dart
new file mode 100644
index 0000000..79446f2
--- /dev/null
+++ b/tests/compiler/dart2js_extra/lookup_map/dead_entry_single_nested_pairs_test.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2015, 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:lookup_map/lookup_map.dart';
+import 'package:expect/expect.dart';
+class A{}
+class B{}
+const map = const LookupMap(const [], const [
+ const LookupMap.pair(A, "the-text-for-A"),
+ const LookupMap.pair(B, "the-text-for-B"),
+]);
+
+main() {
+ Expect.equals(map[A], "the-text-for-A");
+}
diff --git a/tests/compiler/dart2js_extra/lookup_map/dead_entry_test.dart b/tests/compiler/dart2js_extra/lookup_map/dead_entry_test.dart
new file mode 100644
index 0000000..c5fb956
--- /dev/null
+++ b/tests/compiler/dart2js_extra/lookup_map/dead_entry_test.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2015, 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:lookup_map/lookup_map.dart';
+import 'package:expect/expect.dart';
+class A{}
+class B{}
+const map = const LookupMap(const [
+ A, "the-text-for-A",
+ B, "the-text-for-B",
+]);
+
+main() {
+ Expect.equals(map[A], "the-text-for-A");
+}
diff --git a/tests/compiler/dart2js_extra/lookup_map/discovered_code_test.dart b/tests/compiler/dart2js_extra/lookup_map/discovered_code_test.dart
new file mode 100644
index 0000000..a20af73
--- /dev/null
+++ b/tests/compiler/dart2js_extra/lookup_map/discovered_code_test.dart
@@ -0,0 +1,23 @@
+// Copyright (c) 2015, 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:lookup_map/lookup_map.dart';
+import 'package:expect/expect.dart';
+
+class A{ A(B x);}
+class B{}
+class C{}
+class D{}
+class E{}
+createA() => new A(map[B][1]());
+createB() => new B();
+const map = const LookupMap(const [
+ A, const ["the-text-for-A", createA],
+ B, const ["the-text-for-B", createB],
+ C, const ["the-text-for-C"],
+]);
+
+main() {
+ Expect.isTrue(map[A][1]() is A);
+}
diff --git a/tests/compiler/dart2js_extra/lookup_map/entries_aside_test.dart b/tests/compiler/dart2js_extra/lookup_map/entries_aside_test.dart
new file mode 100644
index 0000000..6f72418
--- /dev/null
+++ b/tests/compiler/dart2js_extra/lookup_map/entries_aside_test.dart
@@ -0,0 +1,18 @@
+// Copyright (c) 2015, 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:lookup_map/lookup_map.dart';
+import 'package:expect/expect.dart';
+
+class A{}
+class B{}
+const entries = const [
+ A, "the-text-for-A",
+ B, "the-text-for-B",
+];
+const map = const LookupMap(entries );
+
+main() {
+ Expect.equals(map[A], 'the-text-for-A');
+}
diff --git a/tests/compiler/dart2js_extra/lookup_map/escaping_entries_test.dart b/tests/compiler/dart2js_extra/lookup_map/escaping_entries_test.dart
new file mode 100644
index 0000000..30fa3d3
--- /dev/null
+++ b/tests/compiler/dart2js_extra/lookup_map/escaping_entries_test.dart
@@ -0,0 +1,17 @@
+// Copyright (c) 2015, 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:lookup_map/lookup_map.dart';
+import 'package:expect/expect.dart';
+class A{}
+class B{}
+const entries = const [
+ A, "the-text-for-A",
+ B, "the-text-for-B",
+];
+const map = const LookupMap(entries);
+main() {
+ entries.forEach(print);
+ Expect.equals(map[A], 'the-text-for-A');
+}
diff --git a/tests/compiler/dart2js_extra/lookup_map/generic_type_test.dart b/tests/compiler/dart2js_extra/lookup_map/generic_type_test.dart
new file mode 100644
index 0000000..1a2fd6e
--- /dev/null
+++ b/tests/compiler/dart2js_extra/lookup_map/generic_type_test.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2015, 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:lookup_map/lookup_map.dart';
+import 'package:expect/expect.dart';
+
+class A{}
+class M<T>{ get type => T; }
+const map = const LookupMap(const [
+ A, 'the-text-for-A',
+]);
+
+main() {
+ Expect.equals(map[new M<A>().type], 'the-text-for-A');
+}
diff --git a/tests/compiler/dart2js_extra/lookup_map/live_entry_single_pair_test.dart b/tests/compiler/dart2js_extra/lookup_map/live_entry_single_pair_test.dart
new file mode 100644
index 0000000..2954e23
--- /dev/null
+++ b/tests/compiler/dart2js_extra/lookup_map/live_entry_single_pair_test.dart
@@ -0,0 +1,11 @@
+// Copyright (c) 2015, 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:lookup_map/lookup_map.dart';
+import 'package:expect/expect.dart';
+class A{}
+const map = const LookupMap.pair(A, "the-text-for-A");
+main() {
+ Expect.equals(map[A], 'the-text-for-A');
+}
diff --git a/tests/compiler/dart2js_extra/lookup_map/live_entry_test.dart b/tests/compiler/dart2js_extra/lookup_map/live_entry_test.dart
new file mode 100644
index 0000000..aa835a8
--- /dev/null
+++ b/tests/compiler/dart2js_extra/lookup_map/live_entry_test.dart
@@ -0,0 +1,13 @@
+// Copyright (c) 2015, 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:lookup_map/lookup_map.dart';
+import 'package:expect/expect.dart';
+class A{}
+const map = const LookupMap(const [
+ A, "the-text-for-A",
+]);
+main() {
+ Expect.equals(map[A], 'the-text-for-A');
+}
diff --git a/tests/compiler/dart2js_extra/lookup_map/reachable_data_test.dart b/tests/compiler/dart2js_extra/lookup_map/reachable_data_test.dart
new file mode 100644
index 0000000..8e71ea7
--- /dev/null
+++ b/tests/compiler/dart2js_extra/lookup_map/reachable_data_test.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2015, 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:lookup_map/lookup_map.dart';
+import 'package:expect/expect.dart';
+
+class A{}
+class B{}
+class C{}
+class D{}
+class E{}
+const map = const LookupMap(const [
+ A, const ["the-text-for-A", B],
+ B, const ["the-text-for-B", C],
+ C, const ["the-text-for-C"],
+ D, const ["the-text-for-D", E],
+ E, const ["the-text-for-E"],
+]);
+main() {
+ Expect.equals(map[map[A][1]][0], 'the-text-for-B');
+}
diff --git a/tests/compiler/dart2js_extra/lookup_map/subclass_lookup_map_test.dart b/tests/compiler/dart2js_extra/lookup_map/subclass_lookup_map_test.dart
new file mode 100644
index 0000000..ebf7416
--- /dev/null
+++ b/tests/compiler/dart2js_extra/lookup_map/subclass_lookup_map_test.dart
@@ -0,0 +1,19 @@
+// Copyright (c) 2015, 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:lookup_map/lookup_map.dart';
+import 'package:expect/expect.dart';
+class A{}
+class B{}
+class S extends LookupMap {
+ const S(list) : super(list);
+}
+const map = const S(const [
+ A, "the-text-for-A",
+ B, "the-text-for-B",
+]);
+
+main() {
+ Expect.equals(map[A], "the-text-for-A");
+}
diff --git a/tests/corelib/corelib.status b/tests/corelib/corelib.status
index 704bd09..092e399 100644
--- a/tests/corelib/corelib.status
+++ b/tests/corelib/corelib.status
@@ -83,7 +83,7 @@
# and only looks at the first 20 significant digits.
# The Dart VM and the other ECMAScript implementations follow the correct
# IEEE-754 rounding algorithm.
-double_parse_test: Fail, OK
+double_parse_test/02: Fail, OK
[ $runtime == safari || $runtime == safarimobilesim ]
double_round3_test: Fail, OK # Runtime rounds 0.49999999999999994 to 1.
diff --git a/tests/corelib/double_parse_test.dart b/tests/corelib/double_parse_test.dart
index 5fb6e76..6f7e8fb 100644
--- a/tests/corelib/double_parse_test.dart
+++ b/tests/corelib/double_parse_test.dart
@@ -232,26 +232,26 @@
"4555072551893136908362547791869486679949683240497058210285131854"
"51396213837722826145437693412532098591327667236328125",
0.0);
- testParse("0.00000000000000000000000000000000000000000000000000000000000000"
- "0000000000000000000000000000000000000000000000000000000000000000"
- "0000000000000000000000000000000000000000000000000000000000000000"
- "0000000000000000000000000000000000000000000000000000000000000000"
- "0000000000000000000000000000000000000000000000000000000000000000"
- "0000024703282292062327208828439643411068627545332140664243314532"
- "8041234170109088178685677591650492652607243027730579814636067699"
- "1112238669661707327453443265068702897439863329200619332642599205"
- "1806252781222000513169502627641523911022607448403553068808609405"
- "1727798181294290864842608522062097649849550765341204993205100587"
- "2127469658709242016690593998242808606978027857019419997429604579"
- "7572623273334010723772922131119806567715298322567005234345331218"
- "5169920860031716486480793611343761679481328431956040281530986197"
- "8304604971452253283193290744072288902141724247846767401941767720"
- "8561650585989659548591956327689896895290365125294085321852619688"
- "9863888974446146846024033780172178553364579041996676675092137151"
- "9705456298034409473812692774776868254618683783877327369245051207"
- "5931578479504396230612962142122846982018227555473696607567828620"
- "5497859173707553281928994692862033843994140625",
- 5e-324);
+ testParse("0.00000000000000000000000000000000000000000000000000000000000000" /// 03: ok
+ "0000000000000000000000000000000000000000000000000000000000000000" /// 03: ok
+ "0000000000000000000000000000000000000000000000000000000000000000" /// 03: ok
+ "0000000000000000000000000000000000000000000000000000000000000000" /// 03: ok
+ "0000000000000000000000000000000000000000000000000000000000000000" /// 03: ok
+ "0000024703282292062327208828439643411068627545332140664243314532" /// 03: ok
+ "8041234170109088178685677591650492652607243027730579814636067699" /// 03: ok
+ "1112238669661707327453443265068702897439863329200619332642599205" /// 03: ok
+ "1806252781222000513169502627641523911022607448403553068808609405" /// 03: ok
+ "1727798181294290864842608522062097649849550765341204993205100587" /// 03: ok
+ "2127469658709242016690593998242808606978027857019419997429604579" /// 03: ok
+ "7572623273334010723772922131119806567715298322567005234345331218" /// 03: ok
+ "5169920860031716486480793611343761679481328431956040281530986197" /// 03: ok
+ "8304604971452253283193290744072288902141724247846767401941767720" /// 03: ok
+ "8561650585989659548591956327689896895290365125294085321852619688" /// 03: ok
+ "9863888974446146846024033780172178553364579041996676675092137151" /// 03: ok
+ "9705456298034409473812692774776868254618683783877327369245051207" /// 03: ok
+ "5931578479504396230612962142122846982018227555473696607567828620" /// 03: ok
+ "5497859173707553281928994692862033843994140625", /// 03: ok
+ 5e-324); /// 03: ok
testParse("0.00000000000000000000000000000000000000000000000000000000000000"
"0000000000000000000000000000000000000000000000000000000000000000"
"0000000000000000000000000000000000000000000000000000000000000000"
@@ -368,44 +368,44 @@
"8136843040991207538774075715754306035963544889052606784864342758"
"900428165258489343614201061427593231201171875",
5e-324);
- testParse("0.00000000000000000000000000000000000000000000000000000000000000"
- "0000000000000000000000000000000000000000000000000000000000000000"
- "0000000000000000000000000000000000000000000000000000000000000000"
- "0000000000000000000000000000000000000000000000000000000000000000"
- "0000000000000000000000000000000000000000000000000000000000000000"
- "0000074109846876186981626485318930233205854758970392148714663837"
- "8523751013260905313127797949754542453988569694847043168576596389"
- "9850655339096945981621940161728171894510697854671067917687257517"
- "7347315553307795408549809608457500958111373034747658096871009590"
- "9754422710047573078097111189357848386756539987835030152280559340"
- "4659373979179073872386829939581848166016912201945649993128979841"
- "1362062484498678713572180352209017023903285791732520220528974020"
- "8029068540216066123755499834026713000358124864790413857434018755"
- "2090159017259254714629617513415977493871857473787096164563890871"
- "8119841271673056017045493004705269590165763776884908267986972573"
- "3665217655679410725087643375608460039849049721491174630855395563"
- "54188641513168478436313080237596295773983001708984375",
- 1e-323);
- testParse("0.00000000000000000000000000000000000000000000000000000000000000"
- "0000000000000000000000000000000000000000000000000000000000000000"
- "0000000000000000000000000000000000000000000000000000000000000000"
- "0000000000000000000000000000000000000000000000000000000000000000"
- "0000000000000000000000000000000000000000000000000000000000000000"
- "0000074109846876186981626485318930233205873343654412044724850344"
- "8923718677971811461747287833219166123210675953743507352131000861"
- "5508029119022396648780866584046796426383292609958261304514284249"
- "6061610746879932829188941791435548141415672575056325503240888674"
- "0040403932604439422384254107243478095284614859960753370503720954"
- "5808063977144841990843464643012899935961693114687389992568869106"
- "5599267374834247685403237712975952143398358575711517208866987110"
- "6349531233468788347546753834029761025748698485508885182206645314"
- "0639262948657591471263120659283236968907400986955900192071499065"
- "6496581595870337769532410323614883653969318176216473399700896902"
- "4282850500785430600410615352213843786678841324490411560469406158"
- "4550533979841101562169154890806946368370134291387467238490102415"
- "1863156959008792461225924284245693964036455110947393215135657241"
- "099571834741510656385798938572406768798828125",
- 1e-323);
+ testParse("0.00000000000000000000000000000000000000000000000000000000000000" /// 02: ok
+ "0000000000000000000000000000000000000000000000000000000000000000" /// 02: ok
+ "0000000000000000000000000000000000000000000000000000000000000000" /// 02: ok
+ "0000000000000000000000000000000000000000000000000000000000000000" /// 02: ok
+ "0000000000000000000000000000000000000000000000000000000000000000" /// 02: ok
+ "0000074109846876186981626485318930233205854758970392148714663837" /// 02: ok
+ "8523751013260905313127797949754542453988569694847043168576596389" /// 02: ok
+ "9850655339096945981621940161728171894510697854671067917687257517" /// 02: ok
+ "7347315553307795408549809608457500958111373034747658096871009590" /// 02: ok
+ "9754422710047573078097111189357848386756539987835030152280559340" /// 02: ok
+ "4659373979179073872386829939581848166016912201945649993128979841" /// 02: ok
+ "1362062484498678713572180352209017023903285791732520220528974020" /// 02: ok
+ "8029068540216066123755499834026713000358124864790413857434018755" /// 02: ok
+ "2090159017259254714629617513415977493871857473787096164563890871" /// 02: ok
+ "8119841271673056017045493004705269590165763776884908267986972573" /// 02: ok
+ "3665217655679410725087643375608460039849049721491174630855395563" /// 02: ok
+ "54188641513168478436313080237596295773983001708984375", /// 02: ok
+ 1e-323); /// 02: ok
+ testParse("0.00000000000000000000000000000000000000000000000000000000000000" /// 03: ok
+ "0000000000000000000000000000000000000000000000000000000000000000" /// 03: ok
+ "0000000000000000000000000000000000000000000000000000000000000000" /// 03: ok
+ "0000000000000000000000000000000000000000000000000000000000000000" /// 03: ok
+ "0000000000000000000000000000000000000000000000000000000000000000" /// 03: ok
+ "0000074109846876186981626485318930233205873343654412044724850344" /// 03: ok
+ "8923718677971811461747287833219166123210675953743507352131000861" /// 03: ok
+ "5508029119022396648780866584046796426383292609958261304514284249" /// 03: ok
+ "6061610746879932829188941791435548141415672575056325503240888674" /// 03: ok
+ "0040403932604439422384254107243478095284614859960753370503720954" /// 03: ok
+ "5808063977144841990843464643012899935961693114687389992568869106" /// 03: ok
+ "5599267374834247685403237712975952143398358575711517208866987110" /// 03: ok
+ "6349531233468788347546753834029761025748698485508885182206645314" /// 03: ok
+ "0639262948657591471263120659283236968907400986955900192071499065" /// 03: ok
+ "6496581595870337769532410323614883653969318176216473399700896902" /// 03: ok
+ "4282850500785430600410615352213843786678841324490411560469406158" /// 03: ok
+ "4550533979841101562169154890806946368370134291387467238490102415" /// 03: ok
+ "1863156959008792461225924284245693964036455110947393215135657241" /// 03: ok
+ "099571834741510656385798938572406768798828125", /// 03: ok
+ 1e-323); /// 03: ok
testParse("0.00000000000000000000000000000000000000000000000000000000000000"
"0000000000000000000000000000000000000000000000000000000000000000"
"0000000000000000000000000000000000000000000000000000000000000000"
@@ -482,26 +482,26 @@
"0239620254961370692713747131027132020441991845959370908649389667"
"01396213837722826145437693412532098591327667236328125",
1.1125369292536007e-308);
- testParse("0.00000000000000000000000000000000000000000000000000000000000000"
- "0000000000000000000000000000000000000000000000000000000000000000"
- "0000000000000000000000000000000000000000000000000000000000000000"
- "0000000000000000000000000000000000000000000000000000000000000000"
- "0000000000000000000000000000000000000000000000000000011125369292"
- "5360093857793927928947412039400442434185228365340521456608629527"
- "0200315929606120759250932815416474352736201659755028987189999989"
- "3220987486513026766686796443888026815774211444057134206415720396"
- "3510525564718487986029401249963455450110781777556316353975973978"
- "4825173851725161436876623857879887229903814003929524302244972629"
- "6795040225381805100879491255387164751912585073962051947893527710"
- "5170790163081944841764003984818943810636714040207972316616704045"
- "0220895038833513659790739432367709097880422198053807344762226099"
- "3129277744388529754345873069706690065083079768940685222309466301"
- "4235389404255004774284573740536646273496781023858510820692328908"
- "0857253100067390568036719107632515767271783448958607838263400261"
- "9271291212296536333081616208300526650104600844121842238490102415"
- "1863156959008792461225924284245693964036455110947393215135657241"
- "099571834741510656385798938572406768798828125",
- 1.112536929253601e-308);
+ testParse("0.00000000000000000000000000000000000000000000000000000000000000" /// 03: ok
+ "0000000000000000000000000000000000000000000000000000000000000000" /// 03: ok
+ "0000000000000000000000000000000000000000000000000000000000000000" /// 03: ok
+ "0000000000000000000000000000000000000000000000000000000000000000" /// 03: ok
+ "0000000000000000000000000000000000000000000000000000011125369292" /// 03: ok
+ "5360093857793927928947412039400442434185228365340521456608629527" /// 03: ok
+ "0200315929606120759250932815416474352736201659755028987189999989" /// 03: ok
+ "3220987486513026766686796443888026815774211444057134206415720396" /// 03: ok
+ "3510525564718487986029401249963455450110781777556316353975973978" /// 03: ok
+ "4825173851725161436876623857879887229903814003929524302244972629" /// 03: ok
+ "6795040225381805100879491255387164751912585073962051947893527710" /// 03: ok
+ "5170790163081944841764003984818943810636714040207972316616704045" /// 03: ok
+ "0220895038833513659790739432367709097880422198053807344762226099" /// 03: ok
+ "3129277744388529754345873069706690065083079768940685222309466301" /// 03: ok
+ "4235389404255004774284573740536646273496781023858510820692328908" /// 03: ok
+ "0857253100067390568036719107632515767271783448958607838263400261" /// 03: ok
+ "9271291212296536333081616208300526650104600844121842238490102415" /// 03: ok
+ "1863156959008792461225924284245693964036455110947393215135657241" /// 03: ok
+ "099571834741510656385798938572406768798828125", /// 03: ok
+ 1.112536929253601e-308); /// 03: ok
testParse("0.00000000000000000000000000000000000000000000000000000000000000"
"0000000000000000000000000000000000000000000000000000000000000000"
"0000000000000000000000000000000000000000000000000000000000000000"
@@ -560,44 +560,44 @@
"8136843040991207538774075715754306035963544889052606784864342758"
"900428165258489343614201061427593231201171875",
1.112536929253601e-308);
- testParse("0.00000000000000000000000000000000000000000000000000000000000000"
- "0000000000000000000000000000000000000000000000000000000000000000"
- "0000000000000000000000000000000000000000000000000000000000000000"
- "0000000000000000000000000000000000000000000000000000000000000000"
- "0000000000000000000000000000000000000000000000000000011125369292"
- "5360143264358512053601829696279729256322446286636762993074885578"
- "5482848940402484819383308231788212319506475197423260249353326444"
- "4130717265985540087275830129388183546908748591883986098046865342"
- "9694440740018214171090142139290408905547397593746087678853434622"
- "7708807769200010477987555066232823112546765790360487852208850575"
- "8752599546868752897347409845010678425979078962517411943872958339"
- "1841626929078828345647733525524686707077165117383988808631340302"
- "3919811372391502185169818655049136406061931820528945258278945377"
- "2640279824496362807465448266116748919295441238296611971177785355"
- "4605209927839760366494651758097211936470402475783551200969719627"
- "9349765358747644509438842714766105380341358326953487329219653376"
- "04188641513168478436313080237596295773983001708984375",
- 1.1125369292536017e-308);
- testParse("0.00000000000000000000000000000000000000000000000000000000000000"
- "0000000000000000000000000000000000000000000000000000000000000000"
- "0000000000000000000000000000000000000000000000000000000000000000"
- "0000000000000000000000000000000000000000000000000000000000000000"
- "0000000000000000000000000000000000000000000000000000011125369292"
- "5360143264358512053601829696279729256322464871320782889085072085"
- "5882816605113390968002798115252835988728581456319724432907730915"
- "9788091045910990754434756551706808078781343347171179484873892074"
- "8408735933590351591729274322268456088851697134054755085223313705"
- "7994788991756876822274697984118452821074840662486211070432012189"
- "9901289544834521015804044548441730195923859875259151943312847604"
- "6078831819414397317478790886291621826572237901362985796969353392"
- "2240274065644224408961072655052184431452505441247416583051571936"
- "1189383755894699564098951411984008394330984751465415998685393549"
- "2981950252037042118981569077006826000273956875115116332683643956"
- "9967398203853664384761814691371489127171149929952724258833663970"
- "9550533979841101562169154890806946368370134291387467238490102415"
- "1863156959008792461225924284245693964036455110947393215135657241"
- "099571834741510656385798938572406768798828125",
- 1.1125369292536017e-308);
+ testParse("0.00000000000000000000000000000000000000000000000000000000000000" /// 02: ok
+ "0000000000000000000000000000000000000000000000000000000000000000" /// 02: ok
+ "0000000000000000000000000000000000000000000000000000000000000000" /// 02: ok
+ "0000000000000000000000000000000000000000000000000000000000000000" /// 02: ok
+ "0000000000000000000000000000000000000000000000000000011125369292" /// 02: ok
+ "5360143264358512053601829696279729256322446286636762993074885578" /// 02: ok
+ "5482848940402484819383308231788212319506475197423260249353326444" /// 02: ok
+ "4130717265985540087275830129388183546908748591883986098046865342" /// 02: ok
+ "9694440740018214171090142139290408905547397593746087678853434622" /// 02: ok
+ "7708807769200010477987555066232823112546765790360487852208850575" /// 02: ok
+ "8752599546868752897347409845010678425979078962517411943872958339" /// 02: ok
+ "1841626929078828345647733525524686707077165117383988808631340302" /// 02: ok
+ "3919811372391502185169818655049136406061931820528945258278945377" /// 02: ok
+ "2640279824496362807465448266116748919295441238296611971177785355" /// 02: ok
+ "4605209927839760366494651758097211936470402475783551200969719627" /// 02: ok
+ "9349765358747644509438842714766105380341358326953487329219653376" /// 02: ok
+ "04188641513168478436313080237596295773983001708984375", /// 02: ok
+ 1.1125369292536017e-308); /// 02: ok
+ testParse("0.00000000000000000000000000000000000000000000000000000000000000" /// 03: ok
+ "0000000000000000000000000000000000000000000000000000000000000000" /// 03: ok
+ "0000000000000000000000000000000000000000000000000000000000000000" /// 03: ok
+ "0000000000000000000000000000000000000000000000000000000000000000" /// 03: ok
+ "0000000000000000000000000000000000000000000000000000011125369292" /// 03: ok
+ "5360143264358512053601829696279729256322464871320782889085072085" /// 03: ok
+ "5882816605113390968002798115252835988728581456319724432907730915" /// 03: ok
+ "9788091045910990754434756551706808078781343347171179484873892074" /// 03: ok
+ "8408735933590351591729274322268456088851697134054755085223313705" /// 03: ok
+ "7994788991756876822274697984118452821074840662486211070432012189" /// 03: ok
+ "9901289544834521015804044548441730195923859875259151943312847604" /// 03: ok
+ "6078831819414397317478790886291621826572237901362985796969353392" /// 03: ok
+ "2240274065644224408961072655052184431452505441247416583051571936" /// 03: ok
+ "1189383755894699564098951411984008394330984751465415998685393549" /// 03: ok
+ "2981950252037042118981569077006826000273956875115116332683643956" /// 03: ok
+ "9967398203853664384761814691371489127171149929952724258833663970" /// 03: ok
+ "9550533979841101562169154890806946368370134291387467238490102415" /// 03: ok
+ "1863156959008792461225924284245693964036455110947393215135657241" /// 03: ok
+ "099571834741510656385798938572406768798828125", /// 03: ok
+ 1.1125369292536017e-308); /// 03: ok
testParse("0.00000000000000000000000000000000000000000000000000000000000000"
"0000000000000000000000000000000000000000000000000000000000000000"
"0000000000000000000000000000000000000000000000000000000000000000"
@@ -673,26 +673,26 @@
"5924167958029604477064946470184777360934300451421683607013647479"
"51396213837722826145437693412532098591327667236328125",
2.2250738585072014e-308);
- testParse("0.00000000000000000000000000000000000000000000000000000000000000"
- "0000000000000000000000000000000000000000000000000000000000000000"
- "0000000000000000000000000000000000000000000000000000000000000000"
- "0000000000000000000000000000000000000000000000000000000000000000"
- "0000000000000000000000000000000000000000000000000000022250738585"
- "0720163012305563795567615250361241457301819893006892300968851267"
- "7159413856747700265506443097450144218254107162331246067966730043"
- "7501049413401620872340686411548038468172262181270052386775328221"
- "5857650751428906748569733780796363397546806336554745935958399010"
- "2779558910877598836767067734754861955694039806454982002173263865"
- "0888265793071484125840071160815995011874751834533813898637506208"
- "5650354607662094473839557158134613493810593365859440904719070326"
- "6111637871008949721205058253390132503584229153792338745607152721"
- "3679398551625637847181703822407461490506663533450201028923360785"
- "0720758060421709123733732493928588619801419722757153753675075962"
- "6541800803135624352387918446790161107764092054420920536627658074"
- "4271291212296536333081616208300526650104600844121842238490102415"
- "1863156959008792461225924284245693964036455110947393215135657241"
- "099571834741510656385798938572406768798828125",
- 2.225073858507202e-308);
+ testParse("0.00000000000000000000000000000000000000000000000000000000000000" /// 03: ok
+ "0000000000000000000000000000000000000000000000000000000000000000" /// 03: ok
+ "0000000000000000000000000000000000000000000000000000000000000000" /// 03: ok
+ "0000000000000000000000000000000000000000000000000000000000000000" /// 03: ok
+ "0000000000000000000000000000000000000000000000000000022250738585" /// 03: ok
+ "0720163012305563795567615250361241457301819893006892300968851267" /// 03: ok
+ "7159413856747700265506443097450144218254107162331246067966730043" /// 03: ok
+ "7501049413401620872340686411548038468172262181270052386775328221" /// 03: ok
+ "5857650751428906748569733780796363397546806336554745935958399010" /// 03: ok
+ "2779558910877598836767067734754861955694039806454982002173263865" /// 03: ok
+ "0888265793071484125840071160815995011874751834533813898637506208" /// 03: ok
+ "5650354607662094473839557158134613493810593365859440904719070326" /// 03: ok
+ "6111637871008949721205058253390132503584229153792338745607152721" /// 03: ok
+ "3679398551625637847181703822407461490506663533450201028923360785" /// 03: ok
+ "0720758060421709123733732493928588619801419722757153753675075962" /// 03: ok
+ "6541800803135624352387918446790161107764092054420920536627658074" /// 03: ok
+ "4271291212296536333081616208300526650104600844121842238490102415" /// 03: ok
+ "1863156959008792461225924284245693964036455110947393215135657241" /// 03: ok
+ "099571834741510656385798938572406768798828125", /// 03: ok
+ 2.225073858507202e-308); /// 03: ok
testParse("0.00000000000000000000000000000000000000000000000000000000000000"
"0000000000000000000000000000000000000000000000000000000000000000"
"0000000000000000000000000000000000000000000000000000000000000000"
@@ -751,44 +751,44 @@
"8136843040991207538774075715754306035963544889052606784864342758"
"900428165258489343614201061427593231201171875",
2.225073858507202e-308);
- testParse("0.00000000000000000000000000000000000000000000000000000000000000"
- "0000000000000000000000000000000000000000000000000000000000000000"
- "0000000000000000000000000000000000000000000000000000000000000000"
- "0000000000000000000000000000000000000000000000000000000000000000"
- "0000000000000000000000000000000000000000000000000000022250738585"
- "0720212418870147920222032907240528279439037814303133837435107319"
- "2441946867544064325638818513821882185024380699999477330130056498"
- "8410779192874134192929720097048195199306799329096904278406473168"
- "2041565926728632933630474670123316852983422152744517260835859654"
- "5663192828352447877877998943107797838336991592885945552137141811"
- "2845825114558431922307989750439508685941245723089173894616936837"
- "2321191373658977977723286698840356390251044443035457396733706583"
- "9810554204566938246584137476071559811765738776267476659123871999"
- "3190400631733470900301279018817520344719025002806127777791679839"
- "1090578584006464715943810511489154282775041174682194133952466682"
- "5034313061815878293790042053923750720833666932415800027583911188"
- "54188641513168478436313080237596295773983001708984375",
- 2.2250738585072024e-308);
- testParse("0.00000000000000000000000000000000000000000000000000000000000000"
- "0000000000000000000000000000000000000000000000000000000000000000"
- "0000000000000000000000000000000000000000000000000000000000000000"
- "0000000000000000000000000000000000000000000000000000000000000000"
- "0000000000000000000000000000000000000000000000000000022250738585"
- "0720212418870147920222032907240528279439056398987153733445293826"
- "2841914532254970474258308397286505854246486958895941513684460970"
- "4068152972799584860088646519366819731179394084384097665233499900"
- "0755861120300770354269606853101364036287721693053184667205738737"
- "5949174050909314222165141860993427546865066465011668770360303425"
- "3994515112524200040764624453870560455886026635830913894056826102"
- "6558396263994546949554344059607291509746117227014454385071719673"
- "8131016897819660470375391476074607837156312396985947983896498558"
- "1739504563131807656934782164684779819754568515974931805299288032"
- "9467318908203746468430727830398768346578595574013759265666391011"
- "5651945906921898169113014030529134467663458535415036957197921783"
- "4550533979841101562169154890806946368370134291387467238490102415"
- "1863156959008792461225924284245693964036455110947393215135657241"
- "099571834741510656385798938572406768798828125",
- 2.2250738585072024e-308);
+ testParse("0.00000000000000000000000000000000000000000000000000000000000000" /// 03: ok
+ "0000000000000000000000000000000000000000000000000000000000000000" /// 03: ok
+ "0000000000000000000000000000000000000000000000000000000000000000" /// 03: ok
+ "0000000000000000000000000000000000000000000000000000000000000000" /// 03: ok
+ "0000000000000000000000000000000000000000000000000000022250738585" /// 03: ok
+ "0720212418870147920222032907240528279439037814303133837435107319" /// 03: ok
+ "2441946867544064325638818513821882185024380699999477330130056498" /// 03: ok
+ "8410779192874134192929720097048195199306799329096904278406473168" /// 03: ok
+ "2041565926728632933630474670123316852983422152744517260835859654" /// 03: ok
+ "5663192828352447877877998943107797838336991592885945552137141811" /// 03: ok
+ "2845825114558431922307989750439508685941245723089173894616936837" /// 03: ok
+ "2321191373658977977723286698840356390251044443035457396733706583" /// 03: ok
+ "9810554204566938246584137476071559811765738776267476659123871999" /// 03: ok
+ "3190400631733470900301279018817520344719025002806127777791679839" /// 03: ok
+ "1090578584006464715943810511489154282775041174682194133952466682" /// 03: ok
+ "5034313061815878293790042053923750720833666932415800027583911188" /// 03: ok
+ "54188641513168478436313080237596295773983001708984375", /// 03: ok
+ 2.2250738585072024e-308); /// 03: ok
+ testParse("0.00000000000000000000000000000000000000000000000000000000000000" /// 03: ok
+ "0000000000000000000000000000000000000000000000000000000000000000" /// 03: ok
+ "0000000000000000000000000000000000000000000000000000000000000000" /// 03: ok
+ "0000000000000000000000000000000000000000000000000000000000000000" /// 03: ok
+ "0000000000000000000000000000000000000000000000000000022250738585" /// 03: ok
+ "0720212418870147920222032907240528279439056398987153733445293826" /// 03: ok
+ "2841914532254970474258308397286505854246486958895941513684460970" /// 03: ok
+ "4068152972799584860088646519366819731179394084384097665233499900" /// 03: ok
+ "0755861120300770354269606853101364036287721693053184667205738737" /// 03: ok
+ "5949174050909314222165141860993427546865066465011668770360303425" /// 03: ok
+ "3994515112524200040764624453870560455886026635830913894056826102" /// 03: ok
+ "6558396263994546949554344059607291509746117227014454385071719673" /// 03: ok
+ "8131016897819660470375391476074607837156312396985947983896498558" /// 03: ok
+ "1739504563131807656934782164684779819754568515974931805299288032" /// 03: ok
+ "9467318908203746468430727830398768346578595574013759265666391011" /// 03: ok
+ "5651945906921898169113014030529134467663458535415036957197921783" /// 03: ok
+ "4550533979841101562169154890806946368370134291387467238490102415" /// 03: ok
+ "1863156959008792461225924284245693964036455110947393215135657241" /// 03: ok
+ "099571834741510656385798938572406768798828125", /// 03: ok
+ 2.2250738585072024e-308); /// 03: ok
testParse("0.00000000000000000000000000000000000000000000000000000000000000"
"0000000000000000000000000000000000000000000000000000000000000000"
"0000000000000000000000000000000000000000000000000000000000000000"
@@ -862,25 +862,25 @@
"8909645359318233784351199339157645340492308605462312698364257812"
"5",
1.0020841800044864e-292);
- testParse("0.00000000000000000000000000000000000000000000000000000000000000"
- "0000000000000000000000000000000000000000000000000000000000000000"
- "0000000000000000000000000000000000000000000000000000000000000000"
- "0000000000000000000000000000000000000000000000000000000000000000"
- "0000000000000000000000000000000000000100208418000448650025174695"
- "1035150178458809017822159251011531515138151971877843746285762442"
- "8545112214057342269294258292239779301929355259416640067909319649"
- "7365336576866690449490575153391617964764463657240626936945707789"
- "0322677840073401894046998179185686691822730198820493814317137229"
- "5822164306994752582767555905533610628109411569344063803273395309"
- "4016739578124191615155910675820643598048478728683293279406596985"
- "3795142966229399885915374796852136102192598807080147602085351627"
- "7462738186176388661491270541112149644974737467220377156516124492"
- "5297987696655648150350049348782647584189423429523649017245633309"
- "0650703736050481424426844685046761507858235356421727632283550512"
- "9294184882356332903145058239310065886479547694117011957754993659"
- "5152049332041520812604025151794328168042160636342216519487980314"
- "421878240614097350935640662328296457417309284210205078125",
- 1.0020841800044866e-292);
+ testParse("0.00000000000000000000000000000000000000000000000000000000000000" /// 03: ok
+ "0000000000000000000000000000000000000000000000000000000000000000" /// 03: ok
+ "0000000000000000000000000000000000000000000000000000000000000000" /// 03: ok
+ "0000000000000000000000000000000000000000000000000000000000000000" /// 03: ok
+ "0000000000000000000000000000000000000100208418000448650025174695" /// 03: ok
+ "1035150178458809017822159251011531515138151971877843746285762442" /// 03: ok
+ "8545112214057342269294258292239779301929355259416640067909319649" /// 03: ok
+ "7365336576866690449490575153391617964764463657240626936945707789" /// 03: ok
+ "0322677840073401894046998179185686691822730198820493814317137229" /// 03: ok
+ "5822164306994752582767555905533610628109411569344063803273395309" /// 03: ok
+ "4016739578124191615155910675820643598048478728683293279406596985" /// 03: ok
+ "3795142966229399885915374796852136102192598807080147602085351627" /// 03: ok
+ "7462738186176388661491270541112149644974737467220377156516124492" /// 03: ok
+ "5297987696655648150350049348782647584189423429523649017245633309" /// 03: ok
+ "0650703736050481424426844685046761507858235356421727632283550512" /// 03: ok
+ "9294184882356332903145058239310065886479547694117011957754993659" /// 03: ok
+ "5152049332041520812604025151794328168042160636342216519487980314" /// 03: ok
+ "421878240614097350935640662328296457417309284210205078125", /// 03: ok
+ 1.0020841800044866e-292); /// 03: ok
testParse("0.00000000000000000000000000000000000000000000000000000000000000"
"0000000000000000000000000000000000000000000000000000000000000000"
"0000000000000000000000000000000000000000000000000000000000000000"
@@ -936,43 +936,43 @@
"4847950667958479187395974848205671831957839363657783480512019685"
"578121759385902649064359337671703542582690715789794921875",
2.0041683600089726e-292);
- testParse("0.00000000000000000000000000000000000000000000000000000000000000"
- "0000000000000000000000000000000000000000000000000000000000000000"
- "0000000000000000000000000000000000000000000000000000000000000000"
- "0000000000000000000000000000000000000000000000000000000000000000"
- "0000000000000000000000000000000000000200416836000897266674241512"
- "5990092893382710435783708701744713907322363070003179054747514262"
- "7385611700512865061525449421701203817286652851291627374287240329"
- "3753705169156289950978164746871212513772283206234057202629821353"
- "8809538439162226010550634208659737749820025430842192660178060615"
- "3474267718174236120090795958487048484027109406716660005865875254"
- "7540730218997620056025234843183240653494745917236268600971966054"
- "2572750817920844689872038240532666937066187074066929436725783508"
- "0513647350599865639683590212819431367049178252060735656411044144"
- "5314088186163138416702979387974756763836546863081940712096908853"
- "9929165937080868658779320353585122361868059050079309936626251244"
- "0765647609431766215648800660842354659507691394537687301635742187"
- "5",
- 2.004168360008973e-292);
- testParse("0.00000000000000000000000000000000000000000000000000000000000000"
- "0000000000000000000000000000000000000000000000000000000000000000"
- "0000000000000000000000000000000000000000000000000000000000000000"
- "0000000000000000000000000000000000000000000000000000000000000000"
- "0000000000000000000000000000000000000200416836000897266674241512"
- "5990092893382710435783708785442689934124446215379877007119186963"
- "1799271173601405540673717580039876412295823431198128133887844732"
- "7822096271111944266498822575337206743053529154538278267721206728"
- "1206759279588886755511816487266193645578706075743945771432529989"
- "5627720577353214542977288069464672781437627568914207256313896083"
- "6647266336088483105727658239269018534852601546443784653776612265"
- "4362171708319597782738064157144965045964873355636409438294693959"
- "3883447613213167389211587415988230219943616159642947883454256631"
- "7129850578881555219447792913718868827972321214300345663373246010"
- "5887233720340859229642766731751409169335306833113418201122555553"
- "1150187132469865334442659560994775205494930483192386561026478034"
- "5152049332041520812604025151794328168042160636342216519487980314"
- "421878240614097350935640662328296457417309284210205078125",
- 2.004168360008973e-292);
+ testParse("0.00000000000000000000000000000000000000000000000000000000000000" /// 03: ok
+ "0000000000000000000000000000000000000000000000000000000000000000" /// 03: ok
+ "0000000000000000000000000000000000000000000000000000000000000000" /// 03: ok
+ "0000000000000000000000000000000000000000000000000000000000000000" /// 03: ok
+ "0000000000000000000000000000000000000200416836000897266674241512" /// 03: ok
+ "5990092893382710435783708701744713907322363070003179054747514262" /// 03: ok
+ "7385611700512865061525449421701203817286652851291627374287240329" /// 03: ok
+ "3753705169156289950978164746871212513772283206234057202629821353" /// 03: ok
+ "8809538439162226010550634208659737749820025430842192660178060615" /// 03: ok
+ "3474267718174236120090795958487048484027109406716660005865875254" /// 03: ok
+ "7540730218997620056025234843183240653494745917236268600971966054" /// 03: ok
+ "2572750817920844689872038240532666937066187074066929436725783508" /// 03: ok
+ "0513647350599865639683590212819431367049178252060735656411044144" /// 03: ok
+ "5314088186163138416702979387974756763836546863081940712096908853" /// 03: ok
+ "9929165937080868658779320353585122361868059050079309936626251244" /// 03: ok
+ "0765647609431766215648800660842354659507691394537687301635742187" /// 03: ok
+ "5", /// 03: ok
+ 2.004168360008973e-292); /// 03: ok
+ testParse("0.00000000000000000000000000000000000000000000000000000000000000" /// 03: ok
+ "0000000000000000000000000000000000000000000000000000000000000000" /// 03: ok
+ "0000000000000000000000000000000000000000000000000000000000000000" /// 03: ok
+ "0000000000000000000000000000000000000000000000000000000000000000" /// 03: ok
+ "0000000000000000000000000000000000000200416836000897266674241512" /// 03: ok
+ "5990092893382710435783708785442689934124446215379877007119186963" /// 03: ok
+ "1799271173601405540673717580039876412295823431198128133887844732" /// 03: ok
+ "7822096271111944266498822575337206743053529154538278267721206728" /// 03: ok
+ "1206759279588886755511816487266193645578706075743945771432529989" /// 03: ok
+ "5627720577353214542977288069464672781437627568914207256313896083" /// 03: ok
+ "6647266336088483105727658239269018534852601546443784653776612265" /// 03: ok
+ "4362171708319597782738064157144965045964873355636409438294693959" /// 03: ok
+ "3883447613213167389211587415988230219943616159642947883454256631" /// 03: ok
+ "7129850578881555219447792913718868827972321214300345663373246010" /// 03: ok
+ "5887233720340859229642766731751409169335306833113418201122555553" /// 03: ok
+ "1150187132469865334442659560994775205494930483192386561026478034" /// 03: ok
+ "5152049332041520812604025151794328168042160636342216519487980314" /// 03: ok
+ "421878240614097350935640662328296457417309284210205078125", /// 03: ok
+ 2.004168360008973e-292); /// 03: ok
testParse("0.99999999999999988897769753748434595763683319091796875",
0.9999999999999999);
testParse("0.99999999999999988897769753748434595763683319091796879176194859"
@@ -983,12 +983,12 @@
"4809443029054117700758095643512548748358614094344726684993771234"
"576088145773464788135242997668683528900146484375",
0.9999999999999999);
- testParse("0.999999999999999944488848768742172978818416595458984375",
- 1.0);
- testParse("0.99999999999999994448884876874217297881841659545898441676194859"
- "5190556970945882299241904356487451251641385905655273315006228765"
- "423911854226535211864757002331316471099853515625",
- 1.0);
+ testParse("0.999999999999999944488848768742172978818416595458984375", /// 03: ok
+ 1.0); /// 03: ok
+ testParse("0.99999999999999994448884876874217297881841659545898441676194859" /// 03: ok
+ "5190556970945882299241904356487451251641385905655273315006228765" /// 03: ok
+ "423911854226535211864757002331316471099853515625", /// 03: ok
+ 1.0); /// 03: ok
testParse("0.499999999999999944488848768742172978818416595458984375",
0.49999999999999994);
testParse("0.49999999999999994448884876874217297881841659545898439588097429"
@@ -999,12 +999,12 @@
"2404721514527058850379047821756274374179307047172363342496885617"
"2880440728867323940676214988343417644500732421875",
0.49999999999999994);
- testParse("0.4999999999999999722444243843710864894092082977294921875",
- 0.5);
- testParse("0.49999999999999997224442438437108648940920829772949220838097429"
- "7595278485472941149620952178243725625820692952827636657503114382"
- "7119559271132676059323785011656582355499267578125",
- 0.5);
+ testParse("0.4999999999999999722444243843710864894092082977294921875", /// 03: ok
+ 0.5); /// 03: ok
+ testParse("0.49999999999999997224442438437108648940920829772949220838097429" /// 03: ok
+ "7595278485472941149620952178243725625820692952827636657503114382" /// 03: ok
+ "7119559271132676059323785011656582355499267578125", /// 03: ok
+ 0.5); /// 03: ok
testParse("1.9999999999999997779553950749686919152736663818359375",
1.9999999999999998);
testParse("1.99999999999999977795539507496869191527366638183593758352389719"
@@ -1015,12 +1015,12 @@
"9618886058108235401516191287025097496717228188689453369987542469"
"15217629154692957627048599533736705780029296875",
1.9999999999999998);
- testParse("1.99999999999999988897769753748434595763683319091796875",
- 2.0);
- testParse("1.99999999999999988897769753748434595763683319091796883352389719"
- "0381113941891764598483808712974902503282771811310546630012457530"
- "84782370845307042372951400466263294219970703125",
- 2.0);
+ testParse("1.99999999999999988897769753748434595763683319091796875", /// 03: ok
+ 2.0); /// 03: ok
+ testParse("1.99999999999999988897769753748434595763683319091796883352389719" /// 03: ok
+ "0381113941891764598483808712974902503282771811310546630012457530" /// 03: ok
+ "84782370845307042372951400466263294219970703125", /// 03: ok
+ 2.0); /// 03: ok
testParse("4503599627370495.5",
4503599627370495.5);
testParse("4503599627370495.50000000000000000000000000000000000018807909613"
diff --git a/tests/language/language_dart2js.status b/tests/language/language_dart2js.status
index 03eba0f..05eec1c 100644
--- a/tests/language/language_dart2js.status
+++ b/tests/language/language_dart2js.status
@@ -36,7 +36,6 @@
stacktrace_test: Pass, RuntimeError # # Issue 12698
stacktrace_rethrow_nonerror_test: Pass, RuntimeError # Issue 12698
stacktrace_rethrow_error_test: Pass, RuntimeError # Issue 12698
-instantiate_type_variable_test/01: CompileTimeError # Issue 13631
type_variable_conflict_test/01: Fail # Issue 13702
type_variable_conflict_test/02: Fail # Issue 13702
type_variable_conflict_test/03: Fail # Issue 13702
@@ -146,12 +145,9 @@
integer_division_by_zero_test: RuntimeError # Issue 8301
built_in_identifier_prefix_test: CompileTimeError # Issue 6972
number_identity2_test: RuntimeError # Issue 12596
-new_expression_type_args_test/00: CompileTimeError # Issue 5519
-new_expression_type_args_test/01: CompileTimeError # Issue 5519
double_int_to_string_test: RuntimeError # Issue 1533
mint_arithmetic_test: RuntimeError # Issue 1533
left_shift_test: RuntimeError # Issue 1533
-factory_redirection_test/01: CompileTimeError # Issue 12752
bad_override_test/01: CompileTimeError # Issue 11496
bad_override_test/02: CompileTimeError # Issue 11496
constructor_named_arguments_test/01: CompileTimeError # Issue 5519
@@ -292,7 +288,6 @@
await_for_use_local_test: Crash # (await for(var v in s){accum+= v;}): await for
await_future_test: RuntimeError # Please triage this failure.
await_regression_test: RuntimeError # Please triage this failure.
-await_test: RuntimeError # $async$temp1.S is not a function
cha_deopt1_test: Crash # (d.make_u()): deferred access is not implemented
cha_deopt2_test: Crash # (d.make_u()): deferred access is not implemented
cha_deopt3_test: Crash # (d.make_u()): deferred access is not implemented
diff --git a/tests/try/poi/apply_updates_test.dart b/tests/try/poi/apply_updates_test.dart
index 6fc3428..361ee03 100644
--- a/tests/try/poi/apply_updates_test.dart
+++ b/tests/try/poi/apply_updates_test.dart
@@ -11,7 +11,7 @@
LibraryUpdater,
Update;
-import 'package:compiler/src/scanner/scannerlib.dart' show
+import 'package:compiler/src/parser/partial_elements.dart' show
PartialFunctionElement;
import 'package:compiler/src/script.dart' show
diff --git a/tests/try/poi/forget_element_test.dart b/tests/try/poi/forget_element_test.dart
index e1ebd3b..22b61ce 100644
--- a/tests/try/poi/forget_element_test.dart
+++ b/tests/try/poi/forget_element_test.dart
@@ -20,7 +20,7 @@
import 'package:compiler/src/tree/tree.dart' as tree;
-import 'package:compiler/src/scanner/scannerlib.dart' show
+import 'package:compiler/src/parser/partial_elements.dart' show
PartialMetadataAnnotation;
import 'package:compiler/src/elements/visitor.dart' show
diff --git a/tools/VERSION b/tools/VERSION
index aeb856f..5ef9ccf 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 1
MINOR 13
PATCH 0
-PRERELEASE 0
+PRERELEASE 1
PRERELEASE_PATCH 0
diff --git a/tools/create_tarball.py b/tools/create_tarball.py
index f51e4bb..462bd9d 100755
--- a/tools/create_tarball.py
+++ b/tools/create_tarball.py
@@ -41,6 +41,7 @@
# Ignore Git/SVN files, checked-in binaries, backup files, etc..
ignoredPaths = ['tools/testing/bin',
+ 'tools/sdks',
'third_party/7zip', 'third_party/android_tools',
'third_party/clang', 'third_party/d8',
'third_party/firefox_jsshell']
diff --git a/tools/deps/dartium.deps/DEPS b/tools/deps/dartium.deps/DEPS
index 38f937d5..b79b1dc 100644
--- a/tools/deps/dartium.deps/DEPS
+++ b/tools/deps/dartium.deps/DEPS
@@ -238,8 +238,24 @@
"--no_resume",
"--bucket",
"dart-dependencies",
- "-d",
- "-r",
+ "--recursive",
+ "--directory",
"src/dart/tools/testing/bin",
],
})
+hooks.append({
+ "name": "checked_in_dart_sdks",
+ "pattern": ".",
+ "action": [
+ "download_from_google_storage",
+ "--no_auth",
+ "--no_resume",
+ "--bucket",
+ "dart-dependencies",
+ "--recursive",
+ "--auto_platform",
+ "--extract",
+ "--directory",
+ "src/dart/tools/sdks",
+ ],
+})
diff --git a/tools/precompilation/create_instructions_snapshot_assembly.dart b/tools/precompilation/create_instructions_snapshot_assembly.dart
new file mode 100644
index 0000000..98cccb2
--- /dev/null
+++ b/tools/precompilation/create_instructions_snapshot_assembly.dart
@@ -0,0 +1,21 @@
+import 'dart:io';
+
+void main(List<String> args) {
+ print(args[0]);
+ print(args[1]);
+
+ var bytes = new File(args[0]).readAsBytesSync();
+ print(bytes.length);
+
+ var out = new StringBuffer();
+ out.writeln(".text");
+ out.writeln(" .globl _kInstructionsSnapshot");
+ out.writeln("_kInstructionsSnapshot:");
+ out.writeln(" .balign 32, 0");
+ for (var i = 0; i < bytes.length; i++) {
+ var byte = bytes[i];
+ out.writeln(" .byte $byte");
+ }
+
+ new File(args[1]).writeAsString(out.toString());
+}
diff --git a/tools/precompilation/test_linux.sh b/tools/precompilation/test_linux.sh
new file mode 100755
index 0000000..14f7fa4
--- /dev/null
+++ b/tools/precompilation/test_linux.sh
@@ -0,0 +1,17 @@
+#!/bin/bash -ex
+
+# Usage:
+# cd sdk
+# ./tools/precompilation/test_linux.sh
+
+./tools/build.py -mdebug -ax64 runtime
+
+./out/DebugX64/dart_no_snapshot --gen-precompiled-snapshot ~/hello.dart
+
+./out/DebugX64/dart ./tools/precompilation/create_instructions_snapshot_assembly.dart precompiled.instructions precompiled.S
+
+gcc -m64 -c -o precompiled.o precompiled.S
+
+gcc -m64 -shared -Wl,-soname,libprecompiled.so -o libprecompiled.so precompiled.o
+
+LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$PWD" gdb -ex run --args ./out/DebugX64/dart --run-precompiled-snapshot not_used.dart
diff --git a/tools/precompilation/test_macos.sh b/tools/precompilation/test_macos.sh
new file mode 100755
index 0000000..a233004
--- /dev/null
+++ b/tools/precompilation/test_macos.sh
@@ -0,0 +1,15 @@
+#!/bin/bash -ex
+
+# Usage:
+# cd sdk
+# ./tools/precompilation/test_macos.sh
+
+./tools/build.py -mdebug -ax64 runtime
+
+./xcodebuild/DebugX64/dart_no_snapshot --gen-precompiled-snapshot ~/hello.dart
+
+./xcodebuild/DebugX64/dart ./tools/precompilation/create_instructions_snapshot_assembly.dart precompiled.instructions precompiled.S
+
+clang -m64 -dynamiclib -o libprecompiled.dylib precompiled.S
+
+LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$PWD" lldb -- ./xcodebuild/DebugX64/dart --run-precompiled-snapshot not_used.dart
diff --git a/tools/sdks/.gitignore b/tools/sdks/.gitignore
new file mode 100644
index 0000000..2610d85
--- /dev/null
+++ b/tools/sdks/.gitignore
@@ -0,0 +1,6 @@
+/linux/dart-sdk
+/linux/dart-sdk.tar.gz
+/win/dart-sdk
+/win/dart-sdk.tar.gz
+/mac/dart-sdk
+/mac/dart-sdk.tar.gz
diff --git a/tools/sdks/README b/tools/sdks/README
new file mode 100644
index 0000000..f1f1fd3
--- /dev/null
+++ b/tools/sdks/README
@@ -0,0 +1,20 @@
+This directory contains the hashes of tar.gz files uploaded to cloud storage.
+Hooks in the DEPS files run "download_from_google_storage" to download these
+tarfiles, and unpack them. These tar files contain a stable Dart SDK, which
+is used to build the observatory and to run the test scripts.
+
+The hooks use the --auto-platform feature, so that only the SDK for the
+current platform (linux, macos, or windows) is downloaded. This requires
+the subdirectories to have the special names "linux", "win", and "mac", which
+the download script is hardcoded to recognize.
+
+The linux SDK has had two extra dart executables added to the bin directory.
+'dart-mips' and 'dart-arm' are executables compiled to run on mips and arm
+processors, respectively.
+
+To upload new versions of these tar files, use the "upload_to_google_storage"
+tool in depot_tools, and download the new stable SDKs from the dartlang.org
+web page. The mips and arm executables must be copied from the machines that
+build them, and stripped. There should be no need to update these tar files
+for every new stable version of Dart.
+
diff --git a/tools/sdks/linux/dart-sdk.tar.gz.sha1 b/tools/sdks/linux/dart-sdk.tar.gz.sha1
new file mode 100644
index 0000000..b9db509
--- /dev/null
+++ b/tools/sdks/linux/dart-sdk.tar.gz.sha1
@@ -0,0 +1 @@
+e525a9271e840f53382edfab773ad330384d8caa
\ No newline at end of file
diff --git a/tools/sdks/mac/dart-sdk.tar.gz.sha1 b/tools/sdks/mac/dart-sdk.tar.gz.sha1
new file mode 100644
index 0000000..d88e4ae
--- /dev/null
+++ b/tools/sdks/mac/dart-sdk.tar.gz.sha1
@@ -0,0 +1 @@
+b80cd51c9fe293de25273102de5b2721aacc8aba
\ No newline at end of file
diff --git a/tools/sdks/win/dart-sdk.tar.gz.sha1 b/tools/sdks/win/dart-sdk.tar.gz.sha1
new file mode 100644
index 0000000..97a2743
--- /dev/null
+++ b/tools/sdks/win/dart-sdk.tar.gz.sha1
@@ -0,0 +1 @@
+e098625fb19d40c9554f88e3306987c2c5988963
\ No newline at end of file