Version 0.6.7.0 .
svn merge -r 25115:25191 https://dart.googlecode.com/svn/branches/bleeding_edge trunk
git-svn-id: http://dart.googlecode.com/svn/trunk@25194 260f80e4-7a28-3924-810f-c04153c831b5
diff --git a/pkg/analyzer_experimental/lib/src/generated/ast.dart b/pkg/analyzer_experimental/lib/src/generated/ast.dart
index 833edbb..42a3cc7 100644
--- a/pkg/analyzer_experimental/lib/src/generated/ast.dart
+++ b/pkg/analyzer_experimental/lib/src/generated/ast.dart
@@ -15497,6 +15497,9 @@
* @return the element that was found
*/
ASTNode searchWithin(ASTNode node) {
+ if (node == null) {
+ return null;
+ }
try {
node.accept(this);
} on NodeLocator_NodeFoundException catch (exception) {
@@ -16946,7 +16949,11 @@
BreakStatement visitBreakStatement(BreakStatement node) => new BreakStatement.full(node.keyword, clone2(node.label), node.semicolon);
CascadeExpression visitCascadeExpression(CascadeExpression node) => new CascadeExpression.full(clone2(node.target), clone3(node.cascadeSections));
CatchClause visitCatchClause(CatchClause node) => new CatchClause.full(node.onKeyword, clone2(node.exceptionType), node.catchKeyword, node.leftParenthesis, clone2(node.exceptionParameter), node.comma, clone2(node.stackTraceParameter), node.rightParenthesis, clone2(node.body));
- ClassDeclaration visitClassDeclaration(ClassDeclaration node) => new ClassDeclaration.full(clone2(node.documentationComment), clone3(node.metadata), node.abstractKeyword, node.classKeyword, clone2(node.name), clone2(node.typeParameters), clone2(node.extendsClause), clone2(node.withClause), clone2(node.implementsClause), node.leftBracket, clone3(node.members), node.rightBracket);
+ ClassDeclaration visitClassDeclaration(ClassDeclaration node) {
+ ClassDeclaration copy = new ClassDeclaration.full(clone2(node.documentationComment), clone3(node.metadata), node.abstractKeyword, node.classKeyword, clone2(node.name), clone2(node.typeParameters), clone2(node.extendsClause), clone2(node.withClause), clone2(node.implementsClause), node.leftBracket, clone3(node.members), node.rightBracket);
+ copy.nativeClause = clone2(node.nativeClause);
+ return copy;
+ }
ClassTypeAlias visitClassTypeAlias(ClassTypeAlias node) => new ClassTypeAlias.full(clone2(node.documentationComment), clone3(node.metadata), node.keyword, clone2(node.name), clone2(node.typeParameters), node.equals, node.abstractKeyword, clone2(node.superclass), clone2(node.withClause), clone2(node.implementsClause), node.semicolon);
Comment visitComment(Comment node) {
if (node.isDocumentation) {
diff --git a/pkg/analyzer_experimental/lib/src/generated/element.dart b/pkg/analyzer_experimental/lib/src/generated/element.dart
index d822866..6effbfe 100644
--- a/pkg/analyzer_experimental/lib/src/generated/element.dart
+++ b/pkg/analyzer_experimental/lib/src/generated/element.dart
@@ -5719,7 +5719,7 @@
}
String get displayName {
String name = this.name;
- if (name == null) {
+ if (name == null || name.length == 0) {
List<Type2> normalParameterTypes = this.normalParameterTypes;
List<Type2> optionalParameterTypes = this.optionalParameterTypes;
Map<String, Type2> namedParameterTypes = this.namedParameterTypes;
@@ -6563,11 +6563,15 @@
if (argumentTypes.length != parameterTypes.length) {
throw new IllegalArgumentException("argumentTypes.length (${argumentTypes.length}) != parameterTypes.length (${parameterTypes.length})");
}
- if (argumentTypes.length == 0) {
+ if (argumentTypes.length == 0 || _typeArguments.length == 0) {
+ return this;
+ }
+ List<Type2> newTypeArguments = TypeImpl.substitute(_typeArguments, argumentTypes, parameterTypes);
+ if (JavaArrays.equals(newTypeArguments, _typeArguments)) {
return this;
}
InterfaceTypeImpl newType = new InterfaceTypeImpl.con1(element);
- newType.typeArguments = TypeImpl.substitute(_typeArguments, argumentTypes, parameterTypes);
+ newType.typeArguments = newTypeArguments;
return newType;
}
void appendTo(JavaStringBuilder builder) {
diff --git a/pkg/analyzer_experimental/lib/src/generated/engine.dart b/pkg/analyzer_experimental/lib/src/generated/engine.dart
index 8bc9ce1..d1658b1 100644
--- a/pkg/analyzer_experimental/lib/src/generated/engine.dart
+++ b/pkg/analyzer_experimental/lib/src/generated/engine.dart
@@ -1109,7 +1109,11 @@
state = state._nextState;
}
;
- return CacheState.INVALID;
+ if (identical(descriptor, DartEntry.RESOLUTION_ERRORS) || identical(descriptor, DartEntry.RESOLVED_UNIT) || identical(descriptor, DartEntry.HINTS)) {
+ return CacheState.INVALID;
+ } else {
+ throw new IllegalArgumentException("Invalid descriptor: ${descriptor}");
+ }
}
Object getValue(DataDescriptor descriptor) {
if (identical(descriptor, DartEntry.ELEMENT)) {
@@ -1311,9 +1315,11 @@
}
if (_parsedUnitState != CacheState.VALID) {
_parsedUnit = unit;
+ _parsedUnitState = CacheState.VALID;
}
if (_parseErrorsState != CacheState.VALID) {
_parseErrors = errors == null ? AnalysisError.NO_ERRORS : errors;
+ _parseErrorsState = CacheState.VALID;
}
}
void setState(DataDescriptor<Object> descriptor, CacheState state) {
@@ -4964,10 +4970,12 @@
*/
class ResolutionEraser extends GeneralizingASTVisitor<Object> {
Object visitAssignmentExpression(AssignmentExpression node) {
+ node.staticElement = null;
node.element = null;
return super.visitAssignmentExpression(node);
}
Object visitBinaryExpression(BinaryExpression node) {
+ node.staticElement = null;
node.element = null;
return super.visitBinaryExpression(node);
}
@@ -4980,6 +4988,7 @@
return super.visitConstructorDeclaration(node);
}
Object visitConstructorName(ConstructorName node) {
+ node.staticElement = null;
node.element = null;
return super.visitConstructorName(node);
}
@@ -4997,34 +5006,42 @@
return super.visitFunctionExpression(node);
}
Object visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
+ node.staticElement = null;
node.element = null;
return super.visitFunctionExpressionInvocation(node);
}
Object visitIndexExpression(IndexExpression node) {
+ node.staticElement = null;
node.element = null;
return super.visitIndexExpression(node);
}
Object visitInstanceCreationExpression(InstanceCreationExpression node) {
+ node.staticElement = null;
node.element = null;
return super.visitInstanceCreationExpression(node);
}
Object visitPostfixExpression(PostfixExpression node) {
+ node.staticElement = null;
node.element = null;
return super.visitPostfixExpression(node);
}
Object visitPrefixExpression(PrefixExpression node) {
+ node.staticElement = null;
node.element = null;
return super.visitPrefixExpression(node);
}
Object visitRedirectingConstructorInvocation(RedirectingConstructorInvocation node) {
+ node.staticElement = null;
node.element = null;
return super.visitRedirectingConstructorInvocation(node);
}
Object visitSimpleIdentifier(SimpleIdentifier node) {
+ node.staticElement = null;
node.element = null;
return super.visitSimpleIdentifier(node);
}
Object visitSuperConstructorInvocation(SuperConstructorInvocation node) {
+ node.staticElement = null;
node.element = null;
return super.visitSuperConstructorInvocation(node);
}
diff --git a/pkg/analyzer_experimental/lib/src/generated/error.dart b/pkg/analyzer_experimental/lib/src/generated/error.dart
index 4f53646..9729ec5 100644
--- a/pkg/analyzer_experimental/lib/src/generated/error.dart
+++ b/pkg/analyzer_experimental/lib/src/generated/error.dart
@@ -2617,18 +2617,6 @@
static final StaticWarningCode TYPE_PARAMETER_REFERENCED_BY_STATIC = new StaticWarningCode('TYPE_PARAMETER_REFERENCED_BY_STATIC', 62, "Static members cannot reference type parameters");
/**
- * 15.1 Static Types: A type <i>T</i> is malformed iff: * <i>T</i> has the form <i>id</i> or the
- * form <i>prefix.id</i>, and in the enclosing lexical scope, the name <i>id</i> (respectively
- * <i>prefix.id</i>) does not denote a type. * <i>T</i> denotes a type variable in the
- * enclosing lexical scope, but occurs in the signature or body of a static member. *
- * <i>T</i> is a parameterized type of the form <i>G<S<sub>1</sub>, .., S<sub>n</sub>></i>,
- * and <i>G</i> is malformed.
- *
- * Any use of a malformed type gives rise to a static warning.
- */
- static final StaticWarningCode TYPE_VARIABLE_IN_STATIC_SCOPE = new StaticWarningCode('TYPE_VARIABLE_IN_STATIC_SCOPE', 63, "");
-
- /**
* 12.15.3 Static Invocation: A static method invocation <i>i</i> has the form
* <i>C.m(a<sub>1</sub>, …, a<sub>n</sub>, x<sub>n+1</sub>: a<sub>n+1</sub>, …
* x<sub>n+k</sub>: a<sub>n+k</sub>)</i>. It is a static warning if <i>C</i> does not denote a
@@ -2636,12 +2624,12 @@
*
* @param undefinedClassName the name of the undefined class
*/
- static final StaticWarningCode UNDEFINED_CLASS = new StaticWarningCode('UNDEFINED_CLASS', 64, "Undefined class '%s'");
+ static final StaticWarningCode UNDEFINED_CLASS = new StaticWarningCode('UNDEFINED_CLASS', 63, "Undefined class '%s'");
/**
* Same as [UNDEFINED_CLASS], but to catch using "boolean" instead of "bool".
*/
- static final StaticWarningCode UNDEFINED_CLASS_BOOLEAN = new StaticWarningCode('UNDEFINED_CLASS_BOOLEAN', 65, "Undefined class 'boolean'; did you mean 'bool'?");
+ static final StaticWarningCode UNDEFINED_CLASS_BOOLEAN = new StaticWarningCode('UNDEFINED_CLASS_BOOLEAN', 64, "Undefined class 'boolean'; did you mean 'bool'?");
/**
* 12.17 Getter Invocation: It is a static warning if there is no class <i>C</i> in the enclosing
@@ -2651,7 +2639,7 @@
* @param getterName the name of the getter
* @param enclosingType the name of the enclosing type where the getter is being looked for
*/
- static final StaticWarningCode UNDEFINED_GETTER = new StaticWarningCode('UNDEFINED_GETTER', 66, "There is no such getter '%s' in '%s'");
+ static final StaticWarningCode UNDEFINED_GETTER = new StaticWarningCode('UNDEFINED_GETTER', 65, "There is no such getter '%s' in '%s'");
/**
* 12.30 Identifier Reference: It is as static warning if an identifier expression of the form
@@ -2659,7 +2647,7 @@
* setter) or variable initializer and there is no declaration <i>d</i> with name <i>id</i> in the
* lexical scope enclosing the expression.
*/
- static final StaticWarningCode UNDEFINED_IDENTIFIER = new StaticWarningCode('UNDEFINED_IDENTIFIER', 67, "Undefined name '%s'");
+ static final StaticWarningCode UNDEFINED_IDENTIFIER = new StaticWarningCode('UNDEFINED_IDENTIFIER', 66, "Undefined name '%s'");
/**
* 12.14.2 Binding Actuals to Formals: Furthermore, each <i>q<sub>i</sub></i>, <i>1<=i<=l</i>,
@@ -2668,7 +2656,7 @@
*
* @param name the name of the requested named parameter
*/
- static final StaticWarningCode UNDEFINED_NAMED_PARAMETER = new StaticWarningCode('UNDEFINED_NAMED_PARAMETER', 68, "The named parameter '%s' is not defined");
+ static final StaticWarningCode UNDEFINED_NAMED_PARAMETER = new StaticWarningCode('UNDEFINED_NAMED_PARAMETER', 67, "The named parameter '%s' is not defined");
/**
* 12.18 Assignment: It is as static warning if an assignment of the form <i>v = e</i> occurs
@@ -2683,7 +2671,7 @@
* @param setterName the name of the getter
* @param enclosingType the name of the enclosing type where the setter is being looked for
*/
- static final StaticWarningCode UNDEFINED_SETTER = new StaticWarningCode('UNDEFINED_SETTER', 69, "There is no such setter '%s' in '%s'");
+ static final StaticWarningCode UNDEFINED_SETTER = new StaticWarningCode('UNDEFINED_SETTER', 68, "There is no such setter '%s' in '%s'");
/**
* 12.15.3 Static Invocation: It is a static warning if <i>C</i> does not declare a static method
@@ -2692,7 +2680,7 @@
* @param methodName the name of the method
* @param enclosingType the name of the enclosing type where the method is being looked for
*/
- static final StaticWarningCode UNDEFINED_STATIC_METHOD_OR_GETTER = new StaticWarningCode('UNDEFINED_STATIC_METHOD_OR_GETTER', 70, "There is no such static method '%s' in '%s'");
+ static final StaticWarningCode UNDEFINED_STATIC_METHOD_OR_GETTER = new StaticWarningCode('UNDEFINED_STATIC_METHOD_OR_GETTER', 69, "There is no such static method '%s' in '%s'");
static final List<StaticWarningCode> values = [
AMBIGUOUS_IMPORT,
ARGUMENT_TYPE_NOT_ASSIGNABLE,
@@ -2757,7 +2745,6 @@
SWITCH_EXPRESSION_NOT_ASSIGNABLE,
TYPE_TEST_NON_TYPE,
TYPE_PARAMETER_REFERENCED_BY_STATIC,
- TYPE_VARIABLE_IN_STATIC_SCOPE,
UNDEFINED_CLASS,
UNDEFINED_CLASS_BOOLEAN,
UNDEFINED_GETTER,
diff --git a/pkg/analyzer_experimental/lib/src/generated/parser.dart b/pkg/analyzer_experimental/lib/src/generated/parser.dart
index 16b9b5a..c406289 100644
--- a/pkg/analyzer_experimental/lib/src/generated/parser.dart
+++ b/pkg/analyzer_experimental/lib/src/generated/parser.dart
@@ -1588,7 +1588,7 @@
return parseInitializedIdentifierList(commentAndMetadata, modifiers.staticKeyword, validateModifiersForField(modifiers), returnType);
}
}
- if (isOperator(peek())) {
+ if (isOperator(_currentToken)) {
validateModifiersForOperator(modifiers);
return parseOperator(commentAndMetadata, modifiers.externalKeyword, returnType);
}
@@ -1605,7 +1605,7 @@
validateModifiersForOperator(modifiers);
return parseOperator(commentAndMetadata, modifiers.externalKeyword, null);
} else if (!matchesIdentifier()) {
- if (isOperator(peek())) {
+ if (isOperator(_currentToken)) {
validateModifiersForOperator(modifiers);
return parseOperator(commentAndMetadata, modifiers.externalKeyword, null);
}
@@ -1642,7 +1642,7 @@
if (matches5(TokenType.CLOSE_CURLY_BRACKET)) {
return parseInitializedIdentifierList(commentAndMetadata, modifiers.staticKeyword, validateModifiersForField(modifiers), type);
}
- if (isOperator(peek())) {
+ if (isOperator(_currentToken)) {
validateModifiersForOperator(modifiers);
return parseOperator(commentAndMetadata, modifiers.externalKeyword, type);
}
diff --git a/pkg/analyzer_experimental/lib/src/generated/resolver.dart b/pkg/analyzer_experimental/lib/src/generated/resolver.dart
index 8672e0d..3891934 100644
--- a/pkg/analyzer_experimental/lib/src/generated/resolver.dart
+++ b/pkg/analyzer_experimental/lib/src/generated/resolver.dart
@@ -8012,7 +8012,7 @@
* @param library the library being tested
* @return `true` if the library is 'dart:html'
*/
- bool isHtmlLibrary(LibraryElement library) => library.name == "dart.dom.html";
+ bool isHtmlLibrary(LibraryElement library) => library != null && "dart.dom.html" == library.name;
/**
* Return `true` if the given node is not a type literal.
@@ -11577,15 +11577,6 @@
return true;
}
}
- List<PropertyAccessorElement> propertyAccessorElts = superclassElement.accessors;
- for (PropertyAccessorElement accessorElt in propertyAccessorElts) {
- if (accessorElt.name == executableElementName && accessorElt.isStatic) {
- _errorReporter.reportError2(StaticWarningCode.INSTANCE_METHOD_NAME_COLLIDES_WITH_SUPERCLASS_STATIC, errorNameTarget, [
- executableElementName,
- accessorElt.enclosingElement.displayName]);
- return true;
- }
- }
List<MethodElement> methodElements = superclassElement.methods;
for (MethodElement methodElement in methodElements) {
if (methodElement.name == executableElementName && methodElement.isStatic) {
@@ -13376,18 +13367,26 @@
* Check to make sure that all similarly typed accessors are of the same type (including inherited
* accessors).
*
- * @param node The accessor currently being visited.
+ * @param node the accessor currently being visited
+ * @return `true` if and only if an error code is generated on the passed node
*/
- void checkForMismatchedAccessorTypes(Declaration accessorDeclaration, String accessorTextName) {
- PropertyAccessorElement counterpartAccessor = null;
+ bool checkForMismatchedAccessorTypes(Declaration accessorDeclaration, String accessorTextName) {
ExecutableElement accessorElement = accessorDeclaration.element as ExecutableElement;
if (accessorElement is! PropertyAccessorElement) {
- return;
+ return false;
}
+ PropertyAccessorElement counterpartAccessor = null;
PropertyAccessorElement propertyAccessorElement = accessorElement as PropertyAccessorElement;
- counterpartAccessor = propertyAccessorElement.correspondingSetter;
+ if (propertyAccessorElement.isGetter) {
+ counterpartAccessor = propertyAccessorElement.correspondingSetter;
+ } else {
+ counterpartAccessor = propertyAccessorElement.correspondingGetter;
+ if (counterpartAccessor != null && identical(counterpartAccessor.enclosingElement, propertyAccessorElement.enclosingElement)) {
+ return false;
+ }
+ }
if (counterpartAccessor == null) {
- return;
+ return false;
}
Type2 getterType = null;
Type2 setterType = null;
@@ -13404,7 +13403,9 @@
accessorTextName,
setterType.displayName,
getterType.displayName]);
+ return true;
}
+ return false;
}
/**
diff --git a/pkg/analyzer_experimental/lib/src/generated/sdk.dart b/pkg/analyzer_experimental/lib/src/generated/sdk.dart
index e93c87b..364d40a 100644
--- a/pkg/analyzer_experimental/lib/src/generated/sdk.dart
+++ b/pkg/analyzer_experimental/lib/src/generated/sdk.dart
@@ -332,9 +332,8 @@
* Return the source representing the library with the given `dart:` URI, or `null` if
* the given URI does not denote a library in this SDK.
*
- * @param contentCache the content cache used to access the contents of the mapped source
* @param dartUri the URI of the library to be returned
* @return the source representing the specified library
*/
- Source mapDartUri(ContentCache contentCache, String dartUri);
+ Source mapDartUri(String dartUri);
}
\ No newline at end of file
diff --git a/pkg/analyzer_experimental/lib/src/generated/sdk_io.dart b/pkg/analyzer_experimental/lib/src/generated/sdk_io.dart
index 3ea00d4..143b072 100644
--- a/pkg/analyzer_experimental/lib/src/generated/sdk_io.dart
+++ b/pkg/analyzer_experimental/lib/src/generated/sdk_io.dart
@@ -316,12 +316,12 @@
* @return `true` if the Dartium binary is available
*/
bool get isDartiumInstalled => dartiumExecutable != null;
- Source mapDartUri(ContentCache contentCache, String dartUri) {
+ Source mapDartUri(String dartUri) {
SdkLibrary library = getSdkLibrary(dartUri);
if (library == null) {
return null;
}
- return new FileBasedSource.con2(contentCache, new JavaFile.relative(libraryDirectory, library.path), UriKind.DART_URI);
+ return new FileBasedSource.con2(_analysisContext.sourceFactory.contentCache, new JavaFile.relative(libraryDirectory, library.path), UriKind.DART_URI);
}
/**
diff --git a/pkg/analyzer_experimental/lib/src/generated/source.dart b/pkg/analyzer_experimental/lib/src/generated/source.dart
index 560625c..e6463ff 100644
--- a/pkg/analyzer_experimental/lib/src/generated/source.dart
+++ b/pkg/analyzer_experimental/lib/src/generated/source.dart
@@ -737,7 +737,7 @@
if (!isDartUri(uri)) {
return null;
}
- return _sdk.mapDartUri(contentCache, uri.toString());
+ return _sdk.mapDartUri(uri.toString());
}
}
/**
diff --git a/pkg/analyzer_experimental/lib/src/services/formatter_impl.dart b/pkg/analyzer_experimental/lib/src/services/formatter_impl.dart
index d92be2b0..c778711 100644
--- a/pkg/analyzer_experimental/lib/src/services/formatter_impl.dart
+++ b/pkg/analyzer_experimental/lib/src/services/formatter_impl.dart
@@ -51,7 +51,6 @@
message = 'an analysis error occured during format';
String toString() => 'FormatterException: $message';
-
}
/// Specifies the kind of code snippet to format.
@@ -87,6 +86,8 @@
final FormatterOptions options;
final errors = <AnalysisError>[];
+ LineInfo lineInfo;
+
CodeFormatterImpl(this.options);
String format(CodeKind kind, String source, {int offset, int end,
@@ -98,7 +99,7 @@
var node = parse(kind, start);
checkForErrors();
- var formatter = new SourceVisitor(options);
+ var formatter = new SourceVisitor(options, lineInfo);
node.accept(formatter);
return formatter.writer.toString();
@@ -130,7 +131,9 @@
Token tokenize(String source) {
var scanner = new StringScanner(null, source, this);
- return scanner.tokenize();
+ var token = scanner.tokenize();
+ lineInfo = new LineInfo(scanner.lineStarts);
+ return token;
}
}
@@ -143,9 +146,11 @@
/// The writer to which the source is to be written.
SourceWriter writer;
+ LineInfo lineInfo;
+
/// Initialize a newly created visitor to write source code representing
/// the visited nodes to the given [writer].
- SourceVisitor(FormatterOptions options) :
+ SourceVisitor(FormatterOptions options, this.lineInfo) :
writer = new SourceWriter(indentCount: options.initialIndentationLevel,
lineSeparator: options.lineSeparator);
@@ -293,7 +298,10 @@
var prefix = scriptTag == null ? '' : ' ';
visitPrefixedList(prefix, directives, ' ');
prefix = scriptTag == null && directives.isEmpty ? '' : ' ';
- visitPrefixedList(prefix, node.declarations, ' ');
+ visitPrefixedListWithBlanks(prefix, node.declarations);
+
+ //TODO(pquitslund): move this?
+ writer.newline();
}
visitConditionalExpression(ConditionalExpression node) {
@@ -646,6 +654,11 @@
visitPrefixed(' ', node.expression);
}
+ visitNativeClause(NativeClause node) {
+ writer.print('native ');
+ visit(node.name);
+ }
+
visitNativeFunctionBody(NativeFunctionBody node) {
writer.print('native ');
visit(node.stringLiteral);
@@ -942,4 +955,29 @@
}
}
+ /// Print a list of [nodes], preserving blank lines between nodes.
+ visitPrefixedListWithBlanks(String prefix,
+ NodeList<ASTNode> nodes) {
+ if (nodes != null) {
+ var size = nodes.length;
+ if (size > 0) {
+ writer.print(prefix);
+ for (var i = 0; i < size; i++) {
+ if (i > 0) {
+ // Emit blanks lines
+ var lastLine =
+ lineInfo.getLocation(nodes[i-1].endToken.offset).lineNumber;
+ var currentLine =
+ lineInfo.getLocation(nodes[i].beginToken.offset).lineNumber;
+ var blanks = currentLine - lastLine;
+ for (var i = 0; i < blanks; i++) {
+ writer.newline();
+ }
+ }
+ nodes[i].accept(this);
+ }
+ }
+ }
+ }
+
}
\ No newline at end of file
diff --git a/pkg/analyzer_experimental/test/generated/ast_test.dart b/pkg/analyzer_experimental/test/generated/ast_test.dart
index 5163120..ba2c406 100644
--- a/pkg/analyzer_experimental/test/generated/ast_test.dart
+++ b/pkg/analyzer_experimental/test/generated/ast_test.dart
@@ -16,26 +16,30 @@
import 'test_support.dart';
import 'scanner_test.dart' show TokenFactory;
class NodeLocatorTest extends ParserTestCase {
- void test_offset() {
+ void test_range() {
+ CompilationUnit unit = ParserTestCase.parseCompilationUnit("library myLib;", []);
+ assertLocate2(unit, 4, 10, LibraryDirective);
+ }
+ void test_searchWithin_null() {
+ NodeLocator locator = new NodeLocator.con2(0, 0);
+ JUnitTestCase.assertNull(locator.searchWithin(null));
+ }
+ void test_searchWithin_offset() {
CompilationUnit unit = ParserTestCase.parseCompilationUnit("library myLib;", []);
assertLocate(unit, 10, SimpleIdentifier);
}
- void test_offsetAfterNode() {
+ void test_searchWithin_offsetAfterNode() {
CompilationUnit unit = ParserTestCase.parseCompilationUnit(EngineTestCase.createSource(["class A {}", "class B {}"]), []);
NodeLocator locator = new NodeLocator.con2(1024, 1024);
ASTNode node = locator.searchWithin(unit.declarations[0]);
JUnitTestCase.assertNull(node);
}
- void test_offsetBeforeNode() {
+ void test_searchWithin_offsetBeforeNode() {
CompilationUnit unit = ParserTestCase.parseCompilationUnit(EngineTestCase.createSource(["class A {}", "class B {}"]), []);
NodeLocator locator = new NodeLocator.con2(0, 0);
ASTNode node = locator.searchWithin(unit.declarations[1]);
JUnitTestCase.assertNull(node);
}
- void test_range() {
- CompilationUnit unit = ParserTestCase.parseCompilationUnit("library myLib;", []);
- assertLocate2(unit, 4, 10, LibraryDirective);
- }
void assertLocate(CompilationUnit unit, int offset, Type expectedClass) {
assertLocate2(unit, offset, offset, expectedClass);
}
@@ -43,28 +47,33 @@
NodeLocator locator = new NodeLocator.con2(start, end);
ASTNode node = locator.searchWithin(unit);
JUnitTestCase.assertNotNull(node);
+ JUnitTestCase.assertSame(node, locator.foundNode);
JUnitTestCase.assertTrueMsg("Node starts after range", node.offset <= start);
JUnitTestCase.assertTrueMsg("Node ends before range", node.offset + node.length > end);
EngineTestCase.assertInstanceOf(expectedClass, node);
}
static dartSuite() {
_ut.group('NodeLocatorTest', () {
- _ut.test('test_offset', () {
- final __test = new NodeLocatorTest();
- runJUnitTest(__test, __test.test_offset);
- });
- _ut.test('test_offsetAfterNode', () {
- final __test = new NodeLocatorTest();
- runJUnitTest(__test, __test.test_offsetAfterNode);
- });
- _ut.test('test_offsetBeforeNode', () {
- final __test = new NodeLocatorTest();
- runJUnitTest(__test, __test.test_offsetBeforeNode);
- });
_ut.test('test_range', () {
final __test = new NodeLocatorTest();
runJUnitTest(__test, __test.test_range);
});
+ _ut.test('test_searchWithin_null', () {
+ final __test = new NodeLocatorTest();
+ runJUnitTest(__test, __test.test_searchWithin_null);
+ });
+ _ut.test('test_searchWithin_offset', () {
+ final __test = new NodeLocatorTest();
+ runJUnitTest(__test, __test.test_searchWithin_offset);
+ });
+ _ut.test('test_searchWithin_offsetAfterNode', () {
+ final __test = new NodeLocatorTest();
+ runJUnitTest(__test, __test.test_searchWithin_offsetAfterNode);
+ });
+ _ut.test('test_searchWithin_offsetBeforeNode', () {
+ final __test = new NodeLocatorTest();
+ runJUnitTest(__test, __test.test_searchWithin_offsetBeforeNode);
+ });
});
}
}
@@ -350,6 +359,7 @@
static NamedExpression namedExpression(Label label, Expression expression) => new NamedExpression.full(label, expression);
static NamedExpression namedExpression2(String label, Expression expression) => namedExpression(label2(label), expression);
static DefaultFormalParameter namedFormalParameter(NormalFormalParameter parameter, Expression expression) => new DefaultFormalParameter.full(parameter, ParameterKind.NAMED, expression == null ? null : TokenFactory.token3(TokenType.COLON), expression);
+ static NativeClause nativeClause(String nativeCode) => new NativeClause.full(TokenFactory.token2("native"), string2(nativeCode));
static NativeFunctionBody nativeFunctionBody(String nativeMethodName) => new NativeFunctionBody.full(TokenFactory.token2("native"), string2(nativeMethodName), TokenFactory.token3(TokenType.SEMICOLON));
static NullLiteral nullLiteral() => new NullLiteral.full(TokenFactory.token(Keyword.NULL));
static ParenthesizedExpression parenthesizedExpression(Expression expression) => new ParenthesizedExpression.full(TokenFactory.token3(TokenType.OPEN_PAREN), expression, TokenFactory.token3(TokenType.CLOSE_PAREN));
@@ -364,6 +374,7 @@
static PropertyAccess propertyAccess2(Expression target, String propertyName) => new PropertyAccess.full(target, TokenFactory.token3(TokenType.PERIOD), identifier3(propertyName));
static RedirectingConstructorInvocation redirectingConstructorInvocation(List<Expression> arguments) => redirectingConstructorInvocation2(null, arguments);
static RedirectingConstructorInvocation redirectingConstructorInvocation2(String constructorName, List<Expression> arguments) => new RedirectingConstructorInvocation.full(TokenFactory.token(Keyword.THIS), constructorName == null ? null : TokenFactory.token3(TokenType.PERIOD), constructorName == null ? null : identifier3(constructorName), argumentList(arguments));
+ static RethrowExpression rethrowExpression() => new RethrowExpression.full(TokenFactory.token(Keyword.RETHROW));
static ReturnStatement returnStatement() => returnStatement2(null);
static ReturnStatement returnStatement2(Expression expression) => new ReturnStatement.full(TokenFactory.token(Keyword.RETURN), expression, TokenFactory.token3(TokenType.SEMICOLON));
static ScriptTag scriptTag(String scriptTag2) => new ScriptTag.full(TokenFactory.token2(scriptTag2));
@@ -1872,6 +1883,9 @@
void test_visitNamedFormalParameter() {
assertSource("var a : 0", ASTFactory.namedFormalParameter(ASTFactory.simpleFormalParameter(Keyword.VAR, "a"), ASTFactory.integer(0)));
}
+ void test_visitNativeClause() {
+ assertSource("native 'code'", ASTFactory.nativeClause("code"));
+ }
void test_visitNativeFunctionBody() {
assertSource("native 'str';", ASTFactory.nativeFunctionBody("str"));
}
@@ -1908,6 +1922,9 @@
void test_visitRedirectingConstructorInvocation_unnamed() {
assertSource("this()", ASTFactory.redirectingConstructorInvocation([]));
}
+ void test_visitRethrowExpression() {
+ assertSource("rethrow", ASTFactory.rethrowExpression());
+ }
void test_visitReturnStatement_expression() {
assertSource("return a;", ASTFactory.returnStatement2(ASTFactory.identifier3("a")));
}
@@ -2828,6 +2845,10 @@
final __test = new ToSourceVisitorTest();
runJUnitTest(__test, __test.test_visitNamedFormalParameter);
});
+ _ut.test('test_visitNativeClause', () {
+ final __test = new ToSourceVisitorTest();
+ runJUnitTest(__test, __test.test_visitNativeClause);
+ });
_ut.test('test_visitNativeFunctionBody', () {
final __test = new ToSourceVisitorTest();
runJUnitTest(__test, __test.test_visitNativeFunctionBody);
@@ -2876,6 +2897,10 @@
final __test = new ToSourceVisitorTest();
runJUnitTest(__test, __test.test_visitRedirectingConstructorInvocation_unnamed);
});
+ _ut.test('test_visitRethrowExpression', () {
+ final __test = new ToSourceVisitorTest();
+ runJUnitTest(__test, __test.test_visitRethrowExpression);
+ });
_ut.test('test_visitReturnStatement_expression', () {
final __test = new ToSourceVisitorTest();
runJUnitTest(__test, __test.test_visitReturnStatement_expression);
diff --git a/pkg/analyzer_experimental/test/generated/element_test.dart b/pkg/analyzer_experimental/test/generated/element_test.dart
index 7cd1a48..23b15b9 100644
--- a/pkg/analyzer_experimental/test/generated/element_test.dart
+++ b/pkg/analyzer_experimental/test/generated/element_test.dart
@@ -341,6 +341,19 @@
void test_creation() {
JUnitTestCase.assertNotNull(new InterfaceTypeImpl.con1(ElementFactory.classElement2("A", [])));
}
+ void test_getAccessors() {
+ ClassElementImpl typeElement = ElementFactory.classElement2("A", []);
+ PropertyAccessorElement getterG = ElementFactory.getterElement("g", false, null);
+ PropertyAccessorElement getterH = ElementFactory.getterElement("h", false, null);
+ typeElement.accessors = <PropertyAccessorElement> [getterG, getterH];
+ InterfaceTypeImpl type = new InterfaceTypeImpl.con1(typeElement);
+ JUnitTestCase.assertEquals(2, type.accessors.length);
+ }
+ void test_getAccessors_empty() {
+ ClassElementImpl typeElement = ElementFactory.classElement2("A", []);
+ InterfaceTypeImpl type = new InterfaceTypeImpl.con1(typeElement);
+ JUnitTestCase.assertEquals(0, type.accessors.length);
+ }
void test_getElement() {
ClassElementImpl typeElement = ElementFactory.classElement2("A", []);
InterfaceTypeImpl type = new InterfaceTypeImpl.con1(typeElement);
@@ -623,6 +636,19 @@
InterfaceType typeA = classA.type;
JUnitTestCase.assertNull(typeA.getMethod("m"));
}
+ void test_getMethods() {
+ ClassElementImpl typeElement = ElementFactory.classElement2("A", []);
+ MethodElementImpl methodOne = ElementFactory.methodElement("one", null, []);
+ MethodElementImpl methodTwo = ElementFactory.methodElement("two", null, []);
+ typeElement.methods = <MethodElement> [methodOne, methodTwo];
+ InterfaceTypeImpl type = new InterfaceTypeImpl.con1(typeElement);
+ JUnitTestCase.assertEquals(2, type.methods.length);
+ }
+ void test_getMethods_empty() {
+ ClassElementImpl typeElement = ElementFactory.classElement2("A", []);
+ InterfaceTypeImpl type = new InterfaceTypeImpl.con1(typeElement);
+ JUnitTestCase.assertEquals(0, type.methods.length);
+ }
void test_getMixins_nonParameterized() {
ClassElementImpl classA = ElementFactory.classElement2("A", []);
InterfaceType typeA = classA.type;
@@ -710,6 +736,11 @@
InterfaceType type = ElementFactory.classElement2("A", []).type;
EngineTestCase.assertLength(0, type.typeArguments);
}
+ void test_hashCode() {
+ ClassElement classA = ElementFactory.classElement2("A", []);
+ InterfaceType typeA = classA.type;
+ JUnitTestCase.assertFalse(0 == typeA.hashCode);
+ }
void test_isDirectSupertypeOf_extends() {
ClassElement classA = ElementFactory.classElement2("A", []);
ClassElement classB = ElementFactory.classElement("B", classA.type, []);
@@ -1143,6 +1174,16 @@
EngineTestCase.assertLength(1, resultArguments);
JUnitTestCase.assertEquals(argumentType, resultArguments[0]);
}
+ void test_substitute_exception() {
+ try {
+ ClassElementImpl classA = ElementFactory.classElement2("A", []);
+ InterfaceTypeImpl type = new InterfaceTypeImpl.con1(classA);
+ InterfaceType argumentType = ElementFactory.classElement2("B", []).type;
+ type.substitute2(<Type2> [argumentType], <Type2> []);
+ JUnitTestCase.fail("Expected to encounter exception, argument and parameter type array lengths not equal.");
+ } catch (e) {
+ }
+ }
void test_substitute_notEqual() {
ClassElementImpl classA = ElementFactory.classElement2("A", []);
TypeVariableElementImpl parameterElement = new TypeVariableElementImpl(ASTFactory.identifier3("E"));
@@ -1207,6 +1248,14 @@
final __test = new InterfaceTypeImplTest();
runJUnitTest(__test, __test.test_creation);
});
+ _ut.test('test_getAccessors', () {
+ final __test = new InterfaceTypeImplTest();
+ runJUnitTest(__test, __test.test_getAccessors);
+ });
+ _ut.test('test_getAccessors_empty', () {
+ final __test = new InterfaceTypeImplTest();
+ runJUnitTest(__test, __test.test_getAccessors_empty);
+ });
_ut.test('test_getElement', () {
final __test = new InterfaceTypeImplTest();
runJUnitTest(__test, __test.test_getElement);
@@ -1315,6 +1364,14 @@
final __test = new InterfaceTypeImplTest();
runJUnitTest(__test, __test.test_getMethod_unimplemented);
});
+ _ut.test('test_getMethods', () {
+ final __test = new InterfaceTypeImplTest();
+ runJUnitTest(__test, __test.test_getMethods);
+ });
+ _ut.test('test_getMethods_empty', () {
+ final __test = new InterfaceTypeImplTest();
+ runJUnitTest(__test, __test.test_getMethods_empty);
+ });
_ut.test('test_getMixins_nonParameterized', () {
final __test = new InterfaceTypeImplTest();
runJUnitTest(__test, __test.test_getMixins_nonParameterized);
@@ -1347,6 +1404,10 @@
final __test = new InterfaceTypeImplTest();
runJUnitTest(__test, __test.test_getTypeArguments_empty);
});
+ _ut.test('test_hashCode', () {
+ final __test = new InterfaceTypeImplTest();
+ runJUnitTest(__test, __test.test_hashCode);
+ });
_ut.test('test_isDirectSupertypeOf_extends', () {
final __test = new InterfaceTypeImplTest();
runJUnitTest(__test, __test.test_isDirectSupertypeOf_extends);
@@ -1527,6 +1588,10 @@
final __test = new InterfaceTypeImplTest();
runJUnitTest(__test, __test.test_substitute_equal);
});
+ _ut.test('test_substitute_exception', () {
+ final __test = new InterfaceTypeImplTest();
+ runJUnitTest(__test, __test.test_substitute_exception);
+ });
_ut.test('test_substitute_notEqual', () {
final __test = new InterfaceTypeImplTest();
runJUnitTest(__test, __test.test_substitute_notEqual);
@@ -2194,8 +2259,21 @@
((library.definingCompilationUnit as CompilationUnitElementImpl)).types = <ClassElement> [classElement];
JUnitTestCase.assertTrue(classElement.isAccessibleIn(library));
}
+ void test_SORT_BY_OFFSET() {
+ ClassElementImpl classElementA = ElementFactory.classElement2("A", []);
+ classElementA.nameOffset = 1;
+ ClassElementImpl classElementB = ElementFactory.classElement2("B", []);
+ classElementB.nameOffset = 2;
+ JUnitTestCase.assertEquals(0, Element.SORT_BY_OFFSET(classElementA, classElementA));
+ JUnitTestCase.assertTrue(Element.SORT_BY_OFFSET(classElementA, classElementB) < 0);
+ JUnitTestCase.assertTrue(Element.SORT_BY_OFFSET(classElementB, classElementA) > 0);
+ }
static dartSuite() {
_ut.group('ElementImplTest', () {
+ _ut.test('test_SORT_BY_OFFSET', () {
+ final __test = new ElementImplTest();
+ runJUnitTest(__test, __test.test_SORT_BY_OFFSET);
+ });
_ut.test('test_equals', () {
final __test = new ElementImplTest();
runJUnitTest(__test, __test.test_equals);
@@ -2261,7 +2339,7 @@
}
void test_isSubtypeOf_baseCase_classFunction() {
ClassElementImpl functionElement = ElementFactory.classElement2("Function", []);
- InterfaceTypeImpl functionType = new InterfaceTypeImpl_19(functionElement);
+ InterfaceTypeImpl functionType = new InterfaceTypeImpl_20(functionElement);
FunctionType f = ElementFactory.functionElement("f").type;
JUnitTestCase.assertTrue(f.isSubtypeOf(functionType));
}
@@ -2721,8 +2799,8 @@
});
}
}
-class InterfaceTypeImpl_19 extends InterfaceTypeImpl {
- InterfaceTypeImpl_19(ClassElement arg0) : super.con1(arg0);
+class InterfaceTypeImpl_20 extends InterfaceTypeImpl {
+ InterfaceTypeImpl_20(ClassElement arg0) : super.con1(arg0);
bool get isDartCoreFunction => true;
}
main() {
diff --git a/pkg/analyzer_experimental/test/generated/parser_test.dart b/pkg/analyzer_experimental/test/generated/parser_test.dart
index abe510f..2cb648e 100644
--- a/pkg/analyzer_experimental/test/generated/parser_test.dart
+++ b/pkg/analyzer_experimental/test/generated/parser_test.dart
@@ -3757,7 +3757,7 @@
* @throws Exception if the method could not be invoked or throws an exception
*/
String computeStringValue(String lexeme) {
- AnalysisErrorListener listener = new AnalysisErrorListener_20();
+ AnalysisErrorListener listener = new AnalysisErrorListener_21();
Parser parser = new Parser(null, listener);
return invokeParserMethodImpl(parser, "computeStringValue", <Object> [lexeme], null) as String;
}
@@ -5965,7 +5965,7 @@
});
}
}
-class AnalysisErrorListener_20 implements AnalysisErrorListener {
+class AnalysisErrorListener_21 implements AnalysisErrorListener {
void onError(AnalysisError event) {
JUnitTestCase.fail("Unexpected compilation error: ${event.message} (${event.offset}, ${event.length})");
}
@@ -7585,12 +7585,6 @@
void fail_varAndType_parameter() {
ParserTestCase.parse5("parseFormalParameterList", "(var int x)", [ParserErrorCode.VAR_AND_TYPE]);
}
- void fail_voidVariable_initializer() {
- ParserTestCase.parseStatement("void x = 0;", [ParserErrorCode.VOID_VARIABLE]);
- }
- void fail_voidVariable_noInitializer() {
- ParserTestCase.parseStatement("void x;", [ParserErrorCode.VOID_VARIABLE]);
- }
void test_abstractClassMember_constructor() {
ParserTestCase.parse4("parseClassMember", <Object> ["C"], "abstract C.c();", [ParserErrorCode.ABSTRACT_CLASS_MEMBER]);
}
@@ -7772,6 +7766,15 @@
void test_expectedToken_commaMissingInArgumentList() {
ParserTestCase.parse5("parseArgumentList", "(x, y z)", [ParserErrorCode.EXPECTED_TOKEN]);
}
+ void test_expectedToken_parseStatement_afterVoid() {
+ ParserTestCase.parseStatement("void}", [
+ ParserErrorCode.EXPECTED_TOKEN,
+ ParserErrorCode.MISSING_IDENTIFIER]);
+ }
+ void test_expectedToken_semicolonAfterTypedef() {
+ Token token = TokenFactory.token(Keyword.TYPEDEF);
+ ParserTestCase.parse4("parseClassTypeAlias", <Object> [emptyCommentAndMetadata(), token], "A = B", [ParserErrorCode.EXPECTED_TOKEN]);
+ }
void test_expectedToken_semicolonMissingAfterExpression() {
ParserTestCase.parseStatement("x", [ParserErrorCode.EXPECTED_TOKEN]);
}
@@ -8027,6 +8030,11 @@
void test_missingIdentifier_afterOperator() {
ParserTestCase.parse5("parseMultiplicativeExpression", "1 *", [ParserErrorCode.MISSING_IDENTIFIER]);
}
+ void test_missingIdentifier_beforeClosingCurly() {
+ ParserTestCase.parse4("parseClassMember", <Object> ["C"], "int}", [
+ ParserErrorCode.MISSING_IDENTIFIER,
+ ParserErrorCode.EXPECTED_TOKEN]);
+ }
void test_missingIdentifier_functionDeclaration_returnTypeWithoutName() {
ParserTestCase.parse5("parseFunctionDeclarationStatement", "A<T> () {}", [ParserErrorCode.MISSING_IDENTIFIER]);
}
@@ -8043,6 +8051,15 @@
void test_missingKeywordOperator() {
ParserTestCase.parse4("parseOperator", <Object> [emptyCommentAndMetadata(), null, null], "+(x) {}", [ParserErrorCode.MISSING_KEYWORD_OPERATOR]);
}
+ void test_missingKeywordOperator_parseClassMember() {
+ ParserTestCase.parse4("parseClassMember", <Object> ["C"], "+() {}", [ParserErrorCode.MISSING_KEYWORD_OPERATOR]);
+ }
+ void test_missingKeywordOperator_parseClassMember_afterTypeName() {
+ ParserTestCase.parse4("parseClassMember", <Object> ["C"], "int +() {}", [ParserErrorCode.MISSING_KEYWORD_OPERATOR]);
+ }
+ void test_missingKeywordOperator_parseClassMember_afterVoid() {
+ ParserTestCase.parse4("parseClassMember", <Object> ["C"], "void +() {}", [ParserErrorCode.MISSING_KEYWORD_OPERATOR]);
+ }
void test_missingNameInLibraryDirective() {
CompilationUnit unit = ParserTestCase.parseCompilationUnit("library;", [ParserErrorCode.MISSING_NAME_IN_LIBRARY_DIRECTIVE]);
JUnitTestCase.assertNotNull(unit);
@@ -8051,6 +8068,12 @@
CompilationUnit unit = ParserTestCase.parseCompilationUnit("part of;", [ParserErrorCode.MISSING_NAME_IN_PART_OF_DIRECTIVE]);
JUnitTestCase.assertNotNull(unit);
}
+ void test_missingStatement() {
+ ParserTestCase.parseStatement("is", [ParserErrorCode.MISSING_STATEMENT]);
+ }
+ void test_missingStatement_afterVoid() {
+ ParserTestCase.parseStatement("void;", [ParserErrorCode.MISSING_STATEMENT]);
+ }
void test_missingTerminatorForParameterGroup_named() {
ParserTestCase.parse5("parseFormalParameterList", "(a, {b: 0)", [ParserErrorCode.MISSING_TERMINATOR_FOR_PARAMETER_GROUP]);
}
@@ -8075,6 +8098,12 @@
void test_mixedParameterGroups_positionalNamed() {
ParserTestCase.parse5("parseFormalParameterList", "(a, [b], {c})", [ParserErrorCode.MIXED_PARAMETER_GROUPS]);
}
+ void test_multipleExtendsClauses() {
+ ParserTestCase.parseCompilationUnit("class A extends B extends C {}", [ParserErrorCode.MULTIPLE_EXTENDS_CLAUSES]);
+ }
+ void test_multipleImplementsClauses() {
+ ParserTestCase.parseCompilationUnit("class A implements B implements C {}", [ParserErrorCode.MULTIPLE_IMPLEMENTS_CLAUSES]);
+ }
void test_multipleLibraryDirectives() {
ParserTestCase.parseCompilationUnit("library l; library m;", [ParserErrorCode.MULTIPLE_LIBRARY_DIRECTIVES]);
}
@@ -8090,6 +8119,9 @@
void test_multipleVariablesInForEach() {
ParserTestCase.parse5("parseForStatement", "for (int a, b in foo) {}", [ParserErrorCode.MULTIPLE_VARIABLES_IN_FOR_EACH]);
}
+ void test_multipleWithClauses() {
+ ParserTestCase.parseCompilationUnit("class A extends B with C with D {}", [ParserErrorCode.MULTIPLE_WITH_CLAUSES]);
+ }
void test_namedParameterOutsideGroup() {
ParserTestCase.parse5("parseFormalParameterList", "(a, b : 0)", [ParserErrorCode.NAMED_PARAMETER_OUTSIDE_GROUP]);
}
@@ -8122,6 +8154,12 @@
void test_optionalAfterNormalParameters_positional() {
ParserTestCase.parseCompilationUnit("f([a], b) {}", [ParserErrorCode.NORMAL_BEFORE_OPTIONAL_PARAMETERS]);
}
+ void test_parseCascadeSection_missingIdentifier() {
+ MethodInvocation methodInvocation = ParserTestCase.parse5("parseCascadeSection", "..()", [ParserErrorCode.MISSING_IDENTIFIER]);
+ JUnitTestCase.assertNull(methodInvocation.target);
+ JUnitTestCase.assertEquals("", methodInvocation.methodName.name);
+ EngineTestCase.assertSize(0, methodInvocation.argumentList.arguments);
+ }
void test_positionalAfterNamedArgument() {
ParserTestCase.parse5("parseArgumentList", "(x: 1, 2)", [ParserErrorCode.POSITIONAL_AFTER_NAMED_ARGUMENT]);
}
@@ -8227,15 +8265,37 @@
void test_varTypedef() {
ParserTestCase.parseCompilationUnit("var typedef F();", [ParserErrorCode.VAR_TYPEDEF]);
}
- void test_voidField_initializer() {
- ParserTestCase.parse4("parseClassMember", <Object> ["C"], "void x = 0;", [ParserErrorCode.VOID_VARIABLE]);
- }
- void test_voidField_noInitializer() {
- ParserTestCase.parse4("parseClassMember", <Object> ["C"], "void x;", [ParserErrorCode.VOID_VARIABLE]);
- }
void test_voidParameter() {
ParserTestCase.parse5("parseNormalFormalParameter", "void a)", [ParserErrorCode.VOID_PARAMETER]);
}
+ void test_voidVariable_parseClassMember_initializer() {
+ ParserTestCase.parse4("parseClassMember", <Object> ["C"], "void x = 0;", [ParserErrorCode.VOID_VARIABLE]);
+ }
+ void test_voidVariable_parseClassMember_noInitializer() {
+ ParserTestCase.parse4("parseClassMember", <Object> ["C"], "void x;", [ParserErrorCode.VOID_VARIABLE]);
+ }
+ void test_voidVariable_parseCompilationUnit_initializer() {
+ ParserTestCase.parseCompilationUnit("void x = 0;", [ParserErrorCode.VOID_VARIABLE]);
+ }
+ void test_voidVariable_parseCompilationUnit_noInitializer() {
+ ParserTestCase.parseCompilationUnit("void x;", [ParserErrorCode.VOID_VARIABLE]);
+ }
+ void test_voidVariable_parseCompilationUnitMember_initializer() {
+ ParserTestCase.parse4("parseCompilationUnitMember", <Object> [emptyCommentAndMetadata()], "void a = 0;", [ParserErrorCode.VOID_VARIABLE]);
+ }
+ void test_voidVariable_parseCompilationUnitMember_noInitializer() {
+ ParserTestCase.parse4("parseCompilationUnitMember", <Object> [emptyCommentAndMetadata()], "void a;", [ParserErrorCode.VOID_VARIABLE]);
+ }
+ void test_voidVariable_statement_initializer() {
+ ParserTestCase.parseStatement("void x = 0;", [
+ ParserErrorCode.VOID_VARIABLE,
+ ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE]);
+ }
+ void test_voidVariable_statement_noInitializer() {
+ ParserTestCase.parseStatement("void x;", [
+ ParserErrorCode.VOID_VARIABLE,
+ ParserErrorCode.MISSING_CONST_FINAL_VAR_OR_TYPE]);
+ }
void test_withBeforeExtends() {
ParserTestCase.parseCompilationUnit("class A with B extends C {}", [ParserErrorCode.WITH_BEFORE_EXTENDS]);
}
@@ -8492,6 +8552,14 @@
final __test = new ErrorParserTest();
runJUnitTest(__test, __test.test_expectedToken_commaMissingInArgumentList);
});
+ _ut.test('test_expectedToken_parseStatement_afterVoid', () {
+ final __test = new ErrorParserTest();
+ runJUnitTest(__test, __test.test_expectedToken_parseStatement_afterVoid);
+ });
+ _ut.test('test_expectedToken_semicolonAfterTypedef', () {
+ final __test = new ErrorParserTest();
+ runJUnitTest(__test, __test.test_expectedToken_semicolonAfterTypedef);
+ });
_ut.test('test_expectedToken_semicolonMissingAfterExpression', () {
final __test = new ErrorParserTest();
runJUnitTest(__test, __test.test_expectedToken_semicolonMissingAfterExpression);
@@ -8820,6 +8888,10 @@
final __test = new ErrorParserTest();
runJUnitTest(__test, __test.test_missingIdentifier_afterOperator);
});
+ _ut.test('test_missingIdentifier_beforeClosingCurly', () {
+ final __test = new ErrorParserTest();
+ runJUnitTest(__test, __test.test_missingIdentifier_beforeClosingCurly);
+ });
_ut.test('test_missingIdentifier_functionDeclaration_returnTypeWithoutName', () {
final __test = new ErrorParserTest();
runJUnitTest(__test, __test.test_missingIdentifier_functionDeclaration_returnTypeWithoutName);
@@ -8840,6 +8912,18 @@
final __test = new ErrorParserTest();
runJUnitTest(__test, __test.test_missingKeywordOperator);
});
+ _ut.test('test_missingKeywordOperator_parseClassMember', () {
+ final __test = new ErrorParserTest();
+ runJUnitTest(__test, __test.test_missingKeywordOperator_parseClassMember);
+ });
+ _ut.test('test_missingKeywordOperator_parseClassMember_afterTypeName', () {
+ final __test = new ErrorParserTest();
+ runJUnitTest(__test, __test.test_missingKeywordOperator_parseClassMember_afterTypeName);
+ });
+ _ut.test('test_missingKeywordOperator_parseClassMember_afterVoid', () {
+ final __test = new ErrorParserTest();
+ runJUnitTest(__test, __test.test_missingKeywordOperator_parseClassMember_afterVoid);
+ });
_ut.test('test_missingNameInLibraryDirective', () {
final __test = new ErrorParserTest();
runJUnitTest(__test, __test.test_missingNameInLibraryDirective);
@@ -8848,6 +8932,14 @@
final __test = new ErrorParserTest();
runJUnitTest(__test, __test.test_missingNameInPartOfDirective);
});
+ _ut.test('test_missingStatement', () {
+ final __test = new ErrorParserTest();
+ runJUnitTest(__test, __test.test_missingStatement);
+ });
+ _ut.test('test_missingStatement_afterVoid', () {
+ final __test = new ErrorParserTest();
+ runJUnitTest(__test, __test.test_missingStatement_afterVoid);
+ });
_ut.test('test_missingTerminatorForParameterGroup_named', () {
final __test = new ErrorParserTest();
runJUnitTest(__test, __test.test_missingTerminatorForParameterGroup_named);
@@ -8880,6 +8972,14 @@
final __test = new ErrorParserTest();
runJUnitTest(__test, __test.test_mixedParameterGroups_positionalNamed);
});
+ _ut.test('test_multipleExtendsClauses', () {
+ final __test = new ErrorParserTest();
+ runJUnitTest(__test, __test.test_multipleExtendsClauses);
+ });
+ _ut.test('test_multipleImplementsClauses', () {
+ final __test = new ErrorParserTest();
+ runJUnitTest(__test, __test.test_multipleImplementsClauses);
+ });
_ut.test('test_multipleLibraryDirectives', () {
final __test = new ErrorParserTest();
runJUnitTest(__test, __test.test_multipleLibraryDirectives);
@@ -8900,6 +9000,10 @@
final __test = new ErrorParserTest();
runJUnitTest(__test, __test.test_multipleVariablesInForEach);
});
+ _ut.test('test_multipleWithClauses', () {
+ final __test = new ErrorParserTest();
+ runJUnitTest(__test, __test.test_multipleWithClauses);
+ });
_ut.test('test_namedParameterOutsideGroup', () {
final __test = new ErrorParserTest();
runJUnitTest(__test, __test.test_namedParameterOutsideGroup);
@@ -8940,6 +9044,10 @@
final __test = new ErrorParserTest();
runJUnitTest(__test, __test.test_optionalAfterNormalParameters_positional);
});
+ _ut.test('test_parseCascadeSection_missingIdentifier', () {
+ final __test = new ErrorParserTest();
+ runJUnitTest(__test, __test.test_parseCascadeSection_missingIdentifier);
+ });
_ut.test('test_positionalAfterNamedArgument', () {
final __test = new ErrorParserTest();
runJUnitTest(__test, __test.test_positionalAfterNamedArgument);
@@ -9072,18 +9180,42 @@
final __test = new ErrorParserTest();
runJUnitTest(__test, __test.test_varTypedef);
});
- _ut.test('test_voidField_initializer', () {
- final __test = new ErrorParserTest();
- runJUnitTest(__test, __test.test_voidField_initializer);
- });
- _ut.test('test_voidField_noInitializer', () {
- final __test = new ErrorParserTest();
- runJUnitTest(__test, __test.test_voidField_noInitializer);
- });
_ut.test('test_voidParameter', () {
final __test = new ErrorParserTest();
runJUnitTest(__test, __test.test_voidParameter);
});
+ _ut.test('test_voidVariable_parseClassMember_initializer', () {
+ final __test = new ErrorParserTest();
+ runJUnitTest(__test, __test.test_voidVariable_parseClassMember_initializer);
+ });
+ _ut.test('test_voidVariable_parseClassMember_noInitializer', () {
+ final __test = new ErrorParserTest();
+ runJUnitTest(__test, __test.test_voidVariable_parseClassMember_noInitializer);
+ });
+ _ut.test('test_voidVariable_parseCompilationUnitMember_initializer', () {
+ final __test = new ErrorParserTest();
+ runJUnitTest(__test, __test.test_voidVariable_parseCompilationUnitMember_initializer);
+ });
+ _ut.test('test_voidVariable_parseCompilationUnitMember_noInitializer', () {
+ final __test = new ErrorParserTest();
+ runJUnitTest(__test, __test.test_voidVariable_parseCompilationUnitMember_noInitializer);
+ });
+ _ut.test('test_voidVariable_parseCompilationUnit_initializer', () {
+ final __test = new ErrorParserTest();
+ runJUnitTest(__test, __test.test_voidVariable_parseCompilationUnit_initializer);
+ });
+ _ut.test('test_voidVariable_parseCompilationUnit_noInitializer', () {
+ final __test = new ErrorParserTest();
+ runJUnitTest(__test, __test.test_voidVariable_parseCompilationUnit_noInitializer);
+ });
+ _ut.test('test_voidVariable_statement_initializer', () {
+ final __test = new ErrorParserTest();
+ runJUnitTest(__test, __test.test_voidVariable_statement_initializer);
+ });
+ _ut.test('test_voidVariable_statement_noInitializer', () {
+ final __test = new ErrorParserTest();
+ runJUnitTest(__test, __test.test_voidVariable_statement_noInitializer);
+ });
_ut.test('test_withBeforeExtends', () {
final __test = new ErrorParserTest();
runJUnitTest(__test, __test.test_withBeforeExtends);
diff --git a/pkg/analyzer_experimental/test/generated/resolver_test.dart b/pkg/analyzer_experimental/test/generated/resolver_test.dart
index 89d8c51..6087c87 100644
--- a/pkg/analyzer_experimental/test/generated/resolver_test.dart
+++ b/pkg/analyzer_experimental/test/generated/resolver_test.dart
@@ -2142,13 +2142,7 @@
assertNoErrors();
verify([source]);
}
- void test_nonBoolExpression_assert_bool() {
- Source source = addSource(EngineTestCase.createSource(["f() {", " assert(true);", "}"]));
- resolve(source);
- assertNoErrors();
- verify([source]);
- }
- void test_nonBoolExpression_assert_functionType() {
+ void test_nonBoolExpression_functionType() {
Source source = addSource(EngineTestCase.createSource([
"bool makeAssertion() => true;",
"f() {",
@@ -2158,6 +2152,12 @@
assertNoErrors();
verify([source]);
}
+ void test_nonBoolExpression_interfaceType() {
+ Source source = addSource(EngineTestCase.createSource(["f() {", " assert(true);", "}"]));
+ resolve(source);
+ assertNoErrors();
+ verify([source]);
+ }
void test_nonConstantDefaultValue_function_named() {
Source source = addSource(EngineTestCase.createSource(["f({x : 2 + 3}) {}"]));
resolve(source);
@@ -3527,13 +3527,13 @@
final __test = new NonErrorResolverTest();
runJUnitTest(__test, __test.test_newWithUndefinedConstructorDefault);
});
- _ut.test('test_nonBoolExpression_assert_bool', () {
+ _ut.test('test_nonBoolExpression_functionType', () {
final __test = new NonErrorResolverTest();
- runJUnitTest(__test, __test.test_nonBoolExpression_assert_bool);
+ runJUnitTest(__test, __test.test_nonBoolExpression_functionType);
});
- _ut.test('test_nonBoolExpression_assert_functionType', () {
+ _ut.test('test_nonBoolExpression_interfaceType', () {
final __test = new NonErrorResolverTest();
- runJUnitTest(__test, __test.test_nonBoolExpression_assert_functionType);
+ runJUnitTest(__test, __test.test_nonBoolExpression_interfaceType);
});
_ut.test('test_nonConstCaseExpression', () {
final __test = new NonErrorResolverTest();
@@ -4001,6 +4001,19 @@
assertErrors([StaticTypeWarningCode.INACCESSIBLE_SETTER]);
verify([source]);
}
+ void fail_invocationOfNonFunction_staticInSuperclass() {
+ Source source = addSource(EngineTestCase.createSource([
+ "class A {",
+ " static void a() {}",
+ "}",
+ "",
+ "class B extends A {",
+ " void b() { a(); }",
+ "}"]));
+ resolve(source);
+ assertErrors([StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION]);
+ verify([source]);
+ }
void test_inconsistentMethodInheritance_paramCount() {
Source source = addSource(EngineTestCase.createSource([
"abstract class A {",
@@ -4173,7 +4186,17 @@
assertErrors([StaticTypeWarningCode.NON_BOOL_CONDITION]);
verify([source]);
}
- void test_nonBoolExpression() {
+ void test_nonBoolExpression_functionType() {
+ Source source = addSource(EngineTestCase.createSource([
+ "int makeAssertion() => 1;",
+ "f() {",
+ " assert(makeAssertion);",
+ "}"]));
+ resolve(source);
+ assertErrors([StaticTypeWarningCode.NON_BOOL_EXPRESSION]);
+ verify([source]);
+ }
+ void test_nonBoolExpression_interfaceType() {
Source source = addSource(EngineTestCase.createSource(["f() {", " assert(0);", "}"]));
resolve(source);
assertErrors([StaticTypeWarningCode.NON_BOOL_EXPRESSION]);
@@ -4624,9 +4647,13 @@
final __test = new StaticTypeWarningCodeTest();
runJUnitTest(__test, __test.test_nonBoolCondition_while);
});
- _ut.test('test_nonBoolExpression', () {
+ _ut.test('test_nonBoolExpression_functionType', () {
final __test = new StaticTypeWarningCodeTest();
- runJUnitTest(__test, __test.test_nonBoolExpression);
+ runJUnitTest(__test, __test.test_nonBoolExpression_functionType);
+ });
+ _ut.test('test_nonBoolExpression_interfaceType', () {
+ final __test = new StaticTypeWarningCodeTest();
+ runJUnitTest(__test, __test.test_nonBoolExpression_interfaceType);
});
_ut.test('test_nonTypeAsTypeArgument_notAType', () {
final __test = new StaticTypeWarningCodeTest();
@@ -7455,7 +7482,13 @@
assertErrors([CompileTimeErrorCode.INITIALIZING_FORMAL_FOR_NON_EXISTANT_FIELD]);
verify([source]);
}
- void test_initializingFormalForNonExistantField_static() {
+ void test_initializingFormalForNonExistantField_synthetic() {
+ Source source = addSource(EngineTestCase.createSource(["class A {", " int get x => 1;", " A(this.x) {}", "}"]));
+ resolve(source);
+ assertErrors([CompileTimeErrorCode.INITIALIZING_FORMAL_FOR_NON_EXISTANT_FIELD]);
+ verify([source]);
+ }
+ void test_initializingFormalForStaticField() {
Source source = addSource(EngineTestCase.createSource(["class A {", " static int x;", " A([this.x]) {}", "}"]));
resolve(source);
assertErrors([CompileTimeErrorCode.INITIALIZING_FORMAL_FOR_STATIC_FIELD]);
@@ -9387,9 +9420,13 @@
final __test = new CompileTimeErrorCodeTest();
runJUnitTest(__test, __test.test_initializingFormalForNonExistantField_optional);
});
- _ut.test('test_initializingFormalForNonExistantField_static', () {
+ _ut.test('test_initializingFormalForNonExistantField_synthetic', () {
final __test = new CompileTimeErrorCodeTest();
- runJUnitTest(__test, __test.test_initializingFormalForNonExistantField_static);
+ runJUnitTest(__test, __test.test_initializingFormalForNonExistantField_synthetic);
+ });
+ _ut.test('test_initializingFormalForStaticField', () {
+ final __test = new CompileTimeErrorCodeTest();
+ runJUnitTest(__test, __test.test_initializingFormalForStaticField);
});
_ut.test('test_instanceMemberAccessFromStatic_field', () {
final __test = new CompileTimeErrorCodeTest();
@@ -10046,6 +10083,12 @@
List<Expression> _unresolvedExpressions = new List<Expression>();
/**
+ * A list containing all of the AST Expression nodes for which a propagated type was computed but
+ * where that type was not more specific than the static type.
+ */
+ List<Expression> _invalidlyPropagatedExpressions = new List<Expression>();
+
+ /**
* A list containing all of the AST TypeName nodes that were not resolved.
*/
List<TypeName> _unresolvedTypes = new List<TypeName>();
@@ -10056,6 +10099,11 @@
int _resolvedExpressionCount = 0;
/**
+ * Counter for the number of Expression nodes visited that have propagated type information.
+ */
+ int _propagatedExpressionCount = 0;
+
+ /**
* Counter for the number of TypeName nodes visited that are resolved.
*/
int _resolvedTypeCount = 0;
@@ -10065,20 +10113,14 @@
*/
void assertResolved() {
if (!_unresolvedExpressions.isEmpty || !_unresolvedTypes.isEmpty) {
- int unresolvedExpressionCount = _unresolvedExpressions.length;
- int unresolvedTypeCount = _unresolvedTypes.length;
PrintStringWriter writer = new PrintStringWriter();
- writer.print("Failed to associate types with nodes: ");
- writer.print(unresolvedExpressionCount);
- writer.print("/");
- writer.print(_resolvedExpressionCount + unresolvedExpressionCount);
- writer.print(" Expressions and ");
- writer.print(unresolvedTypeCount);
- writer.print("/");
- writer.print(_resolvedTypeCount + unresolvedTypeCount);
- writer.println(" TypeNames.");
+ int unresolvedTypeCount = _unresolvedTypes.length;
if (unresolvedTypeCount > 0) {
- writer.println("TypeNames:");
+ writer.print("Failed to resolve ");
+ writer.print(unresolvedTypeCount);
+ writer.print(" of ");
+ writer.print(_resolvedTypeCount + unresolvedTypeCount);
+ writer.println(" type names:");
for (TypeName identifier in _unresolvedTypes) {
writer.print(" ");
writer.print(identifier.toString());
@@ -10089,15 +10131,42 @@
writer.println(")");
}
}
+ int unresolvedExpressionCount = _unresolvedExpressions.length;
if (unresolvedExpressionCount > 0) {
- writer.println("Expressions:");
- for (Expression identifier in _unresolvedExpressions) {
+ writer.println("Failed to resolve ");
+ writer.print(unresolvedExpressionCount);
+ writer.print(" of ");
+ writer.print(_resolvedExpressionCount + unresolvedExpressionCount);
+ writer.println(" expressions:");
+ for (Expression expression in _unresolvedExpressions) {
writer.print(" ");
- writer.print(identifier.toString());
+ writer.print(expression.toString());
writer.print(" (");
- writer.print(getFileName(identifier));
+ writer.print(getFileName(expression));
writer.print(" : ");
- writer.print(identifier.offset);
+ writer.print(expression.offset);
+ writer.println(")");
+ }
+ }
+ int invalidlyPropagatedExpressionCount = _invalidlyPropagatedExpressions.length;
+ if (invalidlyPropagatedExpressionCount > 0) {
+ writer.println("Incorrectly propagated ");
+ writer.print(invalidlyPropagatedExpressionCount);
+ writer.print(" of ");
+ writer.print(_propagatedExpressionCount);
+ writer.println(" expressions:");
+ for (Expression expression in _invalidlyPropagatedExpressions) {
+ writer.print(" ");
+ writer.print(expression.toString());
+ writer.print(" [");
+ writer.print(expression.staticType.displayName);
+ writer.print(", ");
+ writer.print(expression.propagatedType.displayName);
+ writer.println("]");
+ writer.print(" ");
+ writer.print(getFileName(expression));
+ writer.print(" : ");
+ writer.print(expression.offset);
writer.println(")");
}
}
@@ -10110,10 +10179,18 @@
Object visitExportDirective(ExportDirective node) => null;
Object visitExpression(Expression node) {
node.visitChildren(this);
- if (node.staticType == null) {
+ Type2 staticType = node.staticType;
+ if (staticType == null) {
_unresolvedExpressions.add(node);
} else {
_resolvedExpressionCount++;
+ Type2 propagatedType = node.propagatedType;
+ if (propagatedType != null) {
+ _propagatedExpressionCount++;
+ if (!propagatedType.isMoreSpecificThan(staticType)) {
+ _invalidlyPropagatedExpressions.add(node);
+ }
+ }
}
return null;
}
@@ -13945,8 +14022,13 @@
if (!node.operator.isUserDefinableOperator) {
return null;
}
+ Type2 operandType = node.leftOperand.staticType;
+ if (operandType == null || operandType.isDynamic) {
+ return null;
+ }
return checkResolved2(node, node.element, MethodElement);
}
+ Object visitCommentReference(CommentReference node) => null;
Object visitCompilationUnit(CompilationUnit node) {
node.visitChildren(this);
return checkResolved2(node, node.element, CompilationUnitElement);
@@ -13961,7 +14043,7 @@
}
Object visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
node.visitChildren(this);
- return checkResolved2(node, node.element, FunctionElement);
+ return null;
}
Object visitImportDirective(ImportDirective node) {
checkResolved2(node, node.element, ImportElement);
@@ -13973,9 +14055,14 @@
}
Object visitIndexExpression(IndexExpression node) {
node.visitChildren(this);
+ Type2 targetType = node.realTarget.staticType;
+ if (targetType == null || targetType.isDynamic) {
+ return null;
+ }
return checkResolved2(node, node.element, MethodElement);
}
Object visitLibraryDirective(LibraryDirective node) => checkResolved2(node, node.element, LibraryElement);
+ Object visitNamedExpression(NamedExpression node) => node.expression.accept(this);
Object visitPartDirective(PartDirective node) => checkResolved2(node, node.element, CompilationUnitElement);
Object visitPartOfDirective(PartOfDirective node) => checkResolved2(node, node.element, LibraryElement);
Object visitPostfixExpression(PostfixExpression node) {
@@ -13983,27 +14070,61 @@
if (!node.operator.isUserDefinableOperator) {
return null;
}
+ Type2 operandType = node.operand.staticType;
+ if (operandType == null || operandType.isDynamic) {
+ return null;
+ }
return checkResolved2(node, node.element, MethodElement);
}
+ Object visitPrefixedIdentifier(PrefixedIdentifier node) {
+ SimpleIdentifier prefix = node.prefix;
+ prefix.accept(this);
+ Type2 prefixType = prefix.staticType;
+ if (prefixType == null || prefixType.isDynamic) {
+ return null;
+ }
+ return checkResolved(node, node.element);
+ }
Object visitPrefixExpression(PrefixExpression node) {
node.visitChildren(this);
if (!node.operator.isUserDefinableOperator) {
return null;
}
+ Type2 operandType = node.operand.staticType;
+ if (operandType == null || operandType.isDynamic) {
+ return null;
+ }
return checkResolved2(node, node.element, MethodElement);
}
+ Object visitPropertyAccess(PropertyAccess node) {
+ Expression target = node.realTarget;
+ target.accept(this);
+ Type2 targetType = target.staticType;
+ if (targetType == null || targetType.isDynamic) {
+ return null;
+ }
+ return node.propertyName.accept(this);
+ }
Object visitSimpleIdentifier(SimpleIdentifier node) {
if (node.name == "void") {
return null;
}
+ ASTNode parent = node.parent;
+ if (parent is MethodInvocation) {
+ MethodInvocation invocation = (parent as MethodInvocation);
+ if (identical(invocation.methodName, node)) {
+ Expression target = invocation.realTarget;
+ Type2 targetType = target == null ? null : target.staticType;
+ if (targetType == null || targetType.isDynamic) {
+ return null;
+ }
+ }
+ }
return checkResolved(node, node.element);
}
Object checkResolved(ASTNode node, Element element) => checkResolved2(node, element, null);
Object checkResolved2(ASTNode node, Element element, Type expectedClass) {
if (element == null) {
- if (node.parent is CommentReference) {
- return null;
- }
if (_knownExceptions == null || !_knownExceptions.contains(node)) {
_unresolvedNodes.add(node);
}
@@ -15187,7 +15308,7 @@
void test_define_duplicate() {
LibraryElement definingLibrary2 = createTestLibrary();
GatheringErrorListener errorListener2 = new GatheringErrorListener();
- Scope rootScope = new Scope_17(definingLibrary2, errorListener2);
+ Scope rootScope = new Scope_18(definingLibrary2, errorListener2);
EnclosedScope scope = new EnclosedScope(rootScope);
VariableElement element1 = ElementFactory.localVariableElement(ASTFactory.identifier3("v1"));
VariableElement element2 = ElementFactory.localVariableElement(ASTFactory.identifier3("v1"));
@@ -15198,7 +15319,7 @@
void test_define_normal() {
LibraryElement definingLibrary3 = createTestLibrary();
GatheringErrorListener errorListener3 = new GatheringErrorListener();
- Scope rootScope = new Scope_18(definingLibrary3, errorListener3);
+ Scope rootScope = new Scope_19(definingLibrary3, errorListener3);
EnclosedScope outerScope = new EnclosedScope(rootScope);
EnclosedScope innerScope = new EnclosedScope(outerScope);
VariableElement element1 = ElementFactory.localVariableElement(ASTFactory.identifier3("v1"));
@@ -15220,18 +15341,18 @@
});
}
}
-class Scope_17 extends Scope {
+class Scope_18 extends Scope {
LibraryElement definingLibrary2;
GatheringErrorListener errorListener2;
- Scope_17(this.definingLibrary2, this.errorListener2) : super();
+ Scope_18(this.definingLibrary2, this.errorListener2) : super();
LibraryElement get definingLibrary => definingLibrary2;
AnalysisErrorListener get errorListener => errorListener2;
Element lookup3(Identifier identifier, String name, LibraryElement referencingLibrary) => null;
}
-class Scope_18 extends Scope {
+class Scope_19 extends Scope {
LibraryElement definingLibrary3;
GatheringErrorListener errorListener3;
- Scope_18(this.definingLibrary3, this.errorListener3) : super();
+ Scope_19(this.definingLibrary3, this.errorListener3) : super();
LibraryElement get definingLibrary => definingLibrary3;
AnalysisErrorListener get errorListener => errorListener3;
Element lookup3(Identifier identifier, String name, LibraryElement referencingLibrary) => null;
diff --git a/pkg/analyzer_experimental/test/services/formatter_test.dart b/pkg/analyzer_experimental/test/services/formatter_test.dart
index 145aef6..41e5379 100644
--- a/pkg/analyzer_experimental/test/services/formatter_test.dart
+++ b/pkg/analyzer_experimental/test/services/formatter_test.dart
@@ -26,7 +26,7 @@
'class A {\n'
'}',
'class A {\n'
- '}'
+ '}\n'
);
});
@@ -35,7 +35,7 @@
'class A { \n'
'}',
'class A {\n'
- '}'
+ '}\n'
);
});
@@ -44,7 +44,7 @@
'class A {\n'
' }',
'class A {\n'
- '}'
+ '}\n'
);
});
@@ -53,7 +53,7 @@
' class A {\n'
'}',
'class A {\n'
- '}'
+ '}\n'
);
});
@@ -66,7 +66,7 @@
'class A {\n'
' void x() {\n'
' }\n'
- '}'
+ '}\n'
);
});
@@ -79,7 +79,7 @@
' static bool x() {\n'
' return true;\n'
' }\n'
- '}'
+ '}\n'
);
});
@@ -90,7 +90,7 @@
' }',
'class A {\n'
' int x() => 42 + 3;\n'
- '}'
+ '}\n'
);
});
@@ -110,10 +110,37 @@
' return false;\n'
' }\n'
' }\n'
- '}'
+ '}\n'
);
});
+ test('CU (multiple members)', () {
+ expectCUFormatsTo(
+ 'class A {\n'
+ '}\n'
+ 'class B {\n'
+ '}\n',
+ 'class A {\n'
+ '}\n'
+ 'class B {\n'
+ '}\n'
+ );
+ });
+
+ test('CU (multiple members w/blanks)', () {
+ expectCUFormatsTo(
+ 'class A {\n'
+ '}\n\n'
+ 'class B {\n'
+ '}\n',
+ 'class A {\n'
+ '}\n\n'
+ 'class B {\n'
+ '}\n'
+ );
+ });
+
+
test('stmt', () {
expectStmtFormatsTo(
'if (true){\n'
diff --git a/pkg/barback/lib/src/phase.dart b/pkg/barback/lib/src/phase.dart
index b4efbc7..e16f94b 100644
--- a/pkg/barback/lib/src/phase.dart
+++ b/pkg/barback/lib/src/phase.dart
@@ -141,11 +141,21 @@
///
/// Passes their outputs to the next phase.
Future _processTransforms() {
- var dirtyTransforms = _transforms.where((transform) => transform.isDirty);
+ // Convert this to a list so we can safely modify _transforms while
+ // iterating over it.
+ var dirtyTransforms = _transforms.where((transform) => transform.isDirty)
+ .toList();
if (dirtyTransforms.isEmpty) return null;
- return Future.wait(dirtyTransforms.map((transform) => transform.apply()))
- .then((transformOutputs) {
+ return Future.wait(dirtyTransforms.map((transform) {
+ if (inputs.containsKey(transform.primary.id)) return transform.apply();
+
+ // If the primary input for the transform has been removed, get rid of it
+ // and all its outputs.
+ _transforms.remove(transform);
+ return new Future.value(
+ new TransformOutputs(new AssetSet(), transform.outputs));
+ })).then((transformOutputs) {
// Collect all of the outputs. Since the transforms are run in parallel,
// we have to be careful here to ensure that the result is deterministic
// and not influenced by the order that transforms complete.
diff --git a/pkg/barback/lib/src/transform_node.dart b/pkg/barback/lib/src/transform_node.dart
index b17c9a5..84e42c0 100644
--- a/pkg/barback/lib/src/transform_node.dart
+++ b/pkg/barback/lib/src/transform_node.dart
@@ -43,6 +43,7 @@
/// The outputs created by this transform the last time it was run.
///
/// Used to tell if an output was removed in a later run.
+ Set<AssetId> get outputs => _outputs;
var _outputs = new Set<AssetId>();
TransformNode(this.phase, this._transformer, this.primary);
diff --git a/pkg/barback/test/package_graph/source_test.dart b/pkg/barback/test/package_graph/source_test.dart
index 0367d88..0185679 100644
--- a/pkg/barback/test/package_graph/source_test.dart
+++ b/pkg/barback/test/package_graph/source_test.dart
@@ -17,6 +17,7 @@
initGraph(["app|foo.txt"]);
updateSources(["app|foo.txt"]);
expectAsset("app|foo.txt");
+ buildShouldSucceed();
});
test("doesn't get an unknown source", () {
@@ -49,6 +50,7 @@
updateSources(["app|foo.txt"]);
expectAsset("app|foo.txt");
+ buildShouldSucceed();
});
test("doesn't get a removed source", () {
@@ -56,12 +58,14 @@
updateSources(["app|foo.txt"]);
expectAsset("app|foo.txt");
+ buildShouldSucceed();
schedule(() {
removeSources(["app|foo.txt"]);
});
expectNoAsset("app|foo.txt");
+ buildShouldSucceed();
});
test("collapses redundant updates", () {
@@ -77,6 +81,7 @@
});
expectAsset("app|foo.blab", "foo.blab");
+ buildShouldSucceed();
schedule(() {
expect(transformer.numRuns, equals(1));
@@ -92,6 +97,7 @@
});
expectNoAsset("app|foo.txt");
+ buildShouldSucceed();
});
test("an update cancels out a removal", () {
@@ -103,6 +109,7 @@
});
expectAsset("app|foo.txt");
+ buildShouldSucceed();
});
test("restarts a build if a source is updated while sources are loading", () {
diff --git a/pkg/barback/test/package_graph/transform_test.dart b/pkg/barback/test/package_graph/transform_test.dart
index ceabe21..bcb7c33 100644
--- a/pkg/barback/test/package_graph/transform_test.dart
+++ b/pkg/barback/test/package_graph/transform_test.dart
@@ -19,6 +19,7 @@
]});
updateSources(["app|foo.blub"]);
expectAsset("app|foo.blab", "foo.blab");
+ buildShouldSucceed();
});
test("gets a transformed asset with the same path", () {
@@ -27,6 +28,7 @@
]});
updateSources(["app|foo.blub"]);
expectAsset("app|foo.blub", "foo.blub");
+ buildShouldSucceed();
});
test("doesn't find an output from a later phase", () {
@@ -36,6 +38,7 @@
]});
updateSources(["app|foo.a"]);
expectNoAsset("app|foo.c");
+ buildShouldSucceed();
});
test("doesn't find an output from the same phase", () {
@@ -48,6 +51,7 @@
updateSources(["app|foo.a"]);
expectAsset("app|foo.b", "foo.b");
expectNoAsset("app|foo.c");
+ buildShouldSucceed();
});
test("finds the latest output before the transformer's phase", () {
@@ -61,6 +65,7 @@
]});
updateSources(["app|foo.blub"]);
expectAsset("app|foo.done", "foo.blub.done");
+ buildShouldSucceed();
});
test("applies multiple transformations to an asset", () {
@@ -78,6 +83,7 @@
]});
updateSources(["app|foo.a"]);
expectAsset("app|foo.k", "foo.b.c.d.e.f.g.h.i.j.k");
+ buildShouldSucceed();
});
test("only runs a transform once for all of its outputs", () {
@@ -87,6 +93,7 @@
expectAsset("app|foo.a", "foo.a");
expectAsset("app|foo.b", "foo.b");
expectAsset("app|foo.c", "foo.c");
+ buildShouldSucceed();
schedule(() {
expect(transformer.numRuns, equals(1));
});
@@ -118,6 +125,7 @@
expectAsset("app|foo.a", "foo.a");
expectAsset("app|foo.b", "foo.b");
+ buildShouldSucceed();
});
test("does not reapply transform when inputs are not modified", () {
@@ -127,6 +135,7 @@
expectAsset("app|foo.blab", "foo.blab");
expectAsset("app|foo.blab", "foo.blab");
expectAsset("app|foo.blab", "foo.blab");
+ buildShouldSucceed();
schedule(() {
expect(transformer.numRuns, equals(1));
@@ -142,18 +151,21 @@
});
expectAsset("app|foo.blab", "foo.blab");
+ buildShouldSucceed();
schedule(() {
updateSources(["app|foo.blub"]);
});
expectAsset("app|foo.blab", "foo.blab");
+ buildShouldSucceed();
schedule(() {
updateSources(["app|foo.blub"]);
});
expectAsset("app|foo.blab", "foo.blab");
+ buildShouldSucceed();
schedule(() {
expect(transformer.numRuns, equals(3));
@@ -171,6 +183,7 @@
updateSources(["app|a.txt", "app|a.inc", "app|b.inc"]);
expectAsset("app|a.out", "ab");
+ buildShouldSucceed();
// Remove the dependency on the non-primary input.
schedule(() {
@@ -180,6 +193,7 @@
// Process it again.
expectAsset("app|a.out", "a");
+ buildShouldSucceed();
// Now touch the removed input. It should not trigger another build.
schedule(() {
@@ -187,6 +201,7 @@
});
expectAsset("app|a.out", "a");
+ buildShouldSucceed();
schedule(() {
expect(transformer.numRuns, equals(2));
@@ -202,6 +217,7 @@
expectAsset("app|a.out", "spread txt");
expectAsset("app|b.out", "spread txt");
+ buildShouldSucceed();
});
test("does not rebuild transforms that don't use modified source", () {
@@ -219,6 +235,7 @@
expectAsset("app|foo.aaa", "foo.aa.aaa");
expectAsset("app|foo.bbb", "foo.bb.bbb");
+ buildShouldSucceed();
schedule(() {
updateSources(["app|foo.a"]);
@@ -226,6 +243,7 @@
expectAsset("app|foo.aaa", "foo.aa.aaa");
expectAsset("app|foo.bbb", "foo.bb.bbb");
+ buildShouldSucceed();
schedule(() {
expect(aa.numRuns, equals(2));
@@ -241,12 +259,14 @@
updateSources(["app|foo.txt"]);
expectAsset("app|foo.out", "foo.out");
+ buildShouldSucceed();
schedule(() {
removeSources(["app|foo.txt"]);
});
expectNoAsset("app|foo.out");
+ buildShouldSucceed();
});
test("reapplies a transform when a non-primary input changes", () {
@@ -257,6 +277,7 @@
updateSources(["app|a.txt", "app|a.inc"]);
expectAsset("app|a.out", "a");
+ buildShouldSucceed();
schedule(() {
modifyAsset("app|a.inc", "after");
@@ -264,6 +285,7 @@
});
expectAsset("app|a.out", "after");
+ buildShouldSucceed();
});
test("restarts processing if a change occurs during processing", () {
@@ -289,6 +311,7 @@
});
expectAsset("app|foo.out", "foo.out");
+ buildShouldSucceed();
schedule(() {
expect(transformer.numRuns, equals(2));
@@ -309,6 +332,7 @@
expectAsset("app|a.out", "spread a");
expectAsset("app|b.out", "spread b");
expectAsset("app|shared.out", "spread a");
+ buildShouldSucceed();
// Now switch their contents so that "shared.out" will be output by "b.b"'s
// transformer.
@@ -321,6 +345,7 @@
expectAsset("app|a.out", "spread a");
expectAsset("app|b.out", "spread b");
expectAsset("app|shared.out", "spread b");
+ buildShouldSucceed();
});
test("restarts before finishing later phases when a change occurs", () {
@@ -349,6 +374,7 @@
expectAsset("app|foo.out", "foo.int.out");
expectAsset("app|bar.out", "bar.int.out");
+ buildShouldSucceed();
schedule(() {
// Should only have run each transform once for each primary.
diff --git a/pkg/docgen/lib/docgen.dart b/pkg/docgen/lib/docgen.dart
index f88df54..5d0b391 100644
--- a/pkg/docgen/lib/docgen.dart
+++ b/pkg/docgen/lib/docgen.dart
@@ -50,6 +50,9 @@
/// Resolves reference links in doc comments.
markdown.Resolver linkResolver;
+/// Index of all the qualified names documented.
+Set<String> qualifiedNameIndex = new Set<String>();
+
/**
* Docgen constructor initializes the link resolver for markdown parsing.
* Also initializes the command line arguments.
@@ -217,6 +220,9 @@
// to read in.
_writeToFile(listDir('docs').join('\n').replaceAll('docs/', ''),
'library_list.txt');
+ // Outputs all the qualified names documented. This will help generate search
+ // results.
+ _writeToFile(qualifiedNameIndex.join('\n'), 'index.txt');
}
Library generateLibrary(dart2js.Dart2JsLibraryMirror library,
@@ -302,7 +308,7 @@
_currentMember = mirror;
data[mirrorName] = new Variable(mirrorName, mirror.isFinal,
mirror.isStatic, mirror.type.qualifiedName, _getComment(mirror),
- _getAnnotations(mirror));
+ _getAnnotations(mirror), mirror.qualifiedName);
}
});
return data;
@@ -324,7 +330,8 @@
if (includePrivate || !mirror.isPrivate) {
var method = new Method(mirrorName, mirror.isStatic,
mirror.returnType.qualifiedName, _getComment(mirror),
- _getParameters(mirror.parameters), _getAnnotations(mirror));
+ _getParameters(mirror.parameters), _getAnnotations(mirror),
+ mirror.qualifiedName);
_currentMember = mirror;
if (mirror.isSetter) {
setters[mirrorName] = method;
@@ -337,15 +344,17 @@
} else if (mirror.isRegularMethod) {
methods[mirrorName] = method;
} else {
- throw new StateError('${mirror.qualifiedName} - no method type match');
+ throw new ArgumentError('$mirrorName - no method type match');
}
}
});
- return {'setters' : setters,
- 'getters' : getters,
- 'constructors' : constructors,
- 'operators' : operators,
- 'methods' : methods};
+ return {
+ 'setters': setters,
+ 'getters': getters,
+ 'constructors': constructors,
+ 'operators': operators,
+ 'methods': methods
+ };
}
/**
@@ -353,22 +362,43 @@
*/
Map<String, Class> _getClasses(Map<String, ClassMirror> mirrorMap,
bool includePrivate) {
- var data = {};
+
+ var abstractClasses = {};
+ var classes = {};
+ var typedefs = {};
+ var errors = {};
+
mirrorMap.forEach((String mirrorName, ClassMirror mirror) {
if (includePrivate || !mirror.isPrivate) {
- _currentClass = mirror;
var superclass = (mirror.superclass != null) ?
mirror.superclass.qualifiedName : '';
var interfaces =
mirror.superinterfaces.map((interface) => interface.qualifiedName);
- data[mirrorName] = new Class(mirrorName, superclass, mirror.isAbstract,
- mirror.isTypedef, _getComment(mirror), interfaces.toList(),
- _getVariables(mirror.variables, includePrivate),
+ var clazz = new Class(mirrorName, superclass, _getComment(mirror),
+ interfaces.toList(), _getVariables(mirror.variables, includePrivate),
_getMethods(mirror.methods, includePrivate),
- _getAnnotations(mirror));
+ _getAnnotations(mirror), mirror.qualifiedName);
+ _currentClass = mirror;
+
+ if (isError(mirror.qualifiedName)) {
+ errors[mirrorName] = clazz;
+ } else if (mirror.isTypedef) {
+ typedefs[mirrorName] = clazz;
+ } else if (mirror.isAbstract) {
+ abstractClasses[mirrorName] = clazz;
+ } else if (mirror.isClass) {
+ classes[mirrorName] = clazz;
+ } else {
+ throw new ArgumentError('$mirrorName - no class type match. ');
+ }
}
});
- return data;
+ return {
+ 'abstract': abstractClasses,
+ 'class': classes,
+ 'typedef': typedefs,
+ 'error': errors
+ };
}
/**
@@ -417,10 +447,24 @@
return outputMap;
}
+bool isError(String qualifiedName) {
+ return qualifiedName.toLowerCase().contains('error') ||
+ qualifiedName.toLowerCase().contains('exception');
+}
+
+/**
+ * A class representing all programming constructs, like library or class.
+ */
+class Indexable {
+ Indexable(String qualifiedName) {
+ qualifiedNameIndex.add(qualifiedName);
+ }
+}
+
/**
* A class containing contents of a Dart library.
*/
-class Library {
+class Library extends Indexable {
/// Documentation comment with converted markdown.
String comment;
@@ -436,8 +480,10 @@
String name;
- Library(this.name, this.comment, this.variables,
- this.functions, this.classes);
+ Library(name, this.comment, this.variables,
+ this.functions, this.classes) : super(name) {
+ this.name = name;
+ }
/// Generates a map describing the [Library] object.
Map toMap() {
@@ -455,7 +501,7 @@
* A class containing contents of a Dart class.
*/
// TODO(tmandel): Figure out how to do typedefs (what is needed)
-class Class {
+class Class extends Indexable {
/// Documentation comment with converted markdown.
String comment;
@@ -471,15 +517,13 @@
String name;
String superclass;
- bool isAbstract;
- bool isTypedef;
/// List of the meta annotations on the class.
List<String> annotations;
- Class(this.name, this.superclass, this.isAbstract, this.isTypedef,
- this.comment, this.interfaces, this.variables, this.methods,
- this.annotations);
+ Class(this.name, this.superclass, this.comment, this.interfaces,
+ this.variables, this.methods, this.annotations,
+ String qualifiedName) : super(qualifiedName) {}
/// Generates a map describing the [Class] object.
Map toMap() {
@@ -487,8 +531,6 @@
classMap['name'] = name;
classMap['comment'] = comment;
classMap['superclass'] = superclass;
- classMap['abstract'] = isAbstract.toString();
- classMap['typedef'] = isTypedef.toString();
classMap['implements'] = new List.from(interfaces);
classMap['variables'] = recurseMap(variables);
classMap['methods'] = recurseMap(methods);
@@ -500,7 +542,7 @@
/**
* A class containing properties of a Dart variable.
*/
-class Variable {
+class Variable extends Indexable {
/// Documentation comment with converted markdown.
String comment;
@@ -514,7 +556,7 @@
List<String> annotations;
Variable(this.name, this.isFinal, this.isStatic, this.type, this.comment,
- this.annotations);
+ this.annotations, String qualifiedName) : super(qualifiedName);
/// Generates a map describing the [Variable] object.
Map toMap() {
@@ -532,7 +574,7 @@
/**
* A class containing properties of a Dart method.
*/
-class Method {
+class Method extends Indexable {
/// Documentation comment with converted markdown.
String comment;
@@ -548,7 +590,8 @@
List<String> annotations;
Method(this.name, this.isStatic, this.returnType, this.comment,
- this.parameters, this.annotations);
+ this.parameters, this.annotations, String qualifiedName)
+ : super(qualifiedName);
/// Generates a map describing the [Method] object.
Map toMap() {
diff --git a/pkg/docgen/test/single_library_test.dart b/pkg/docgen/test/single_library_test.dart
index f00ddc4..6ff1539 100644
--- a/pkg/docgen/test/single_library_test.dart
+++ b/pkg/docgen/test/single_library_test.dart
@@ -54,7 +54,11 @@
includePrivate: true);
expect(library is Library, isTrue);
- var classes = library.classes.values;
+ var classTypes = library.classes.values;
+ expect(classTypes.every((e) => e is Map), isTrue);
+
+ var classes = [];
+ classTypes.forEach((e) => classes.addAll(e.values));
expect(classes.every((e) => e is Class), isTrue);
var classMethodTypes = [];
diff --git a/pkg/fixnum/lib/src/int32.dart b/pkg/fixnum/lib/src/int32.dart
index 02eb213..6c8a6f4 100644
--- a/pkg/fixnum/lib/src/int32.dart
+++ b/pkg/fixnum/lib/src/int32.dart
@@ -20,7 +20,7 @@
* The minimum positive value attainable by an [int32], namely
* -2147483648.
*/
- static int32 MIN_VALUE = const int32._internal(0x80000000);
+ static int32 MIN_VALUE = const int32._internal(-0x80000000);
/**
* An [int32] constant equal to 0.
diff --git a/pkg/fixnum/pubspec.yaml b/pkg/fixnum/pubspec.yaml
index bdb079c..c582394 100644
--- a/pkg/fixnum/pubspec.yaml
+++ b/pkg/fixnum/pubspec.yaml
@@ -1,5 +1,6 @@
name: fixnum
-author: "Dart Team <misc@dartlang.org>"
+author: Dart Team <misc@dartlang.org>
+description: Library for 32- and 64-bit fixed size integers.
homepage: http://www.dartlang.org
-description: >
- Library for 32- and 64-bit fixed size integers.
+dev_dependencies:
+ unittest: any
diff --git a/pkg/fixnum/test/int_32_test.dart b/pkg/fixnum/test/int_32_test.dart
index 407f2a0..77a6b27 100644
--- a/pkg/fixnum/test/int_32_test.dart
+++ b/pkg/fixnum/test/int_32_test.dart
@@ -3,157 +3,234 @@
// BSD-style license that can be found in the LICENSE file.
library int32test;
-import "package:expect/expect.dart";
import 'package:fixnum/fixnum.dart';
+import 'package:unittest/unittest.dart';
void main() {
- Expect.equals("0", new int32.fromInt(0).toString());
- Expect.equals("1", new int32.fromInt(1).toString());
- Expect.equals("-1", new int32.fromInt(-1).toString());
- Expect.equals("1000", new int32.fromInt(1000).toString());
- Expect.equals("-1000", new int32.fromInt(-1000).toString());
- Expect.equals("2147483647", new int32.fromInt(2147483647).toString());
- Expect.equals("-2147483648", new int32.fromInt(2147483648).toString());
- Expect.equals("-2147483647", new int32.fromInt(2147483649).toString());
- Expect.equals("-2147483646", new int32.fromInt(2147483650).toString());
- Expect.equals("-2147483648", new int32.fromInt(-2147483648).toString());
- Expect.equals("2147483647", new int32.fromInt(-2147483649).toString());
- Expect.equals("2147483646", new int32.fromInt(-2147483650).toString());
+ group("arithmetic operators", () {
+ int32 n1 = new int32.fromInt(1234);
+ int32 n2 = new int32.fromInt(9876);
+ int32 n3 = new int32.fromInt(-1234);
+ int32 n4 = new int32.fromInt(-9876);
+ int32 n5 = new int32.fromInt(0x12345678);
+ int32 n6 = new int32.fromInt(0x22222222);
- Expect.equals("-1", new int32.fromInt(-1).toHexString());
- Expect.equals("-1", (new int32.fromInt(-1) >> 8).toHexString());
- Expect.equals("-100", (new int32.fromInt(-1) << 8).toHexString());
- Expect.equals("ffffff",
- new int32.fromInt(-1).shiftRightUnsigned(8).toHexString());
+ test("+", () {
+ expect(n1 + n2, new int32.fromInt(11110));
+ expect(n3 + n2, new int32.fromInt(8642));
+ expect(n3 + n4, new int32.fromInt(-11110));
+ expect(int32.MAX_VALUE + 1, int32.MIN_VALUE);
+ expect(() => new int32.fromInt(17) + null, throws);
+ });
- Expect.equals("123456789", new int32.fromInt(123456789).toString());
- Expect.equals("75bcd15", new int32.fromInt(123456789).toHexString());
- Expect.equals("223101104124", new int32.fromInt(123456789).toRadixString(5));
+ test("-", () {
+ expect(n1 - n2, new int32.fromInt(-8642));
+ expect(n3 - n2, new int32.fromInt(-11110));
+ expect(n3 - n4, new int32.fromInt(8642));
+ expect(int32.MIN_VALUE - 1, int32.MAX_VALUE);
+ expect(() => new int32.fromInt(17) - null, throws);
+ });
- try {
- new int32.fromInt(17) >> -1;
- Expect.fail("x >> -1 should throw ArgumentError");
- } on ArgumentError catch (e) {
- }
+ test("unary -", () {
+ expect(-n1, new int32.fromInt(-1234));
+ expect(-int32.ZERO, int32.ZERO);
+ });
- try {
- new int32.fromInt(17) << -1;
- Expect.fail("x >> -1 should throw ArgumentError");
- } on ArgumentError catch (e) {
- }
+ test("*", () {
+ expect(n1 * n2, new int32.fromInt(12186984));
+ expect(n2 * n3, new int32.fromInt(-12186984));
+ expect(n3 * n3, new int32.fromInt(1522756));
+ expect(n3 * n2, new int32.fromInt(-12186984));
+ expect(new int32.fromInt(0x12345678) * new int32.fromInt(0x22222222),
+ new int32.fromInt(-899716112));
+ expect((new int32.fromInt(123456789) * new int32.fromInt(987654321)),
+ new int32.fromInt(-67153019));
+ expect(new int32.fromInt(0x12345678) * new int64.fromInt(0x22222222),
+ new int64.fromInts(0x026D60DC, 0xCA5F6BF0));
+ expect((new int32.fromInt(123456789) * 987654321),
+ new int32.fromInt(-67153019));
+ expect(() => new int32.fromInt(17) * null, throws);
+ });
- try {
- new int32.fromInt(17).shiftRightUnsigned(-1);
- Expect.fail("x >> -1 should throw ArgumentError");
- } on ArgumentError catch (e) {
- }
+ test("~/", () {
+ expect(new int32.fromInt(829893893) ~/ new int32.fromInt(1919),
+ new int32.fromInt(432461));
+ expect(new int32.fromInt(0x12345678) ~/ new int32.fromInt(0x22),
+ new int32.fromInt(0x12345678 ~/ 0x22));
+ expect(new int32.fromInt(829893893) ~/ new int64.fromInt(1919),
+ new int32.fromInt(432461));
+ expect(new int32.fromInt(0x12345678) ~/ new int64.fromInt(0x22),
+ new int32.fromInt(0x12345678 ~/ 0x22));
+ expect(new int32.fromInt(829893893) ~/ 1919, new int32.fromInt(432461));
+ expect(() => new int32.fromInt(17) ~/ int32.ZERO, throws);
+ expect(() => new int32.fromInt(17) ~/ null, throws);
+ });
- // wraparound
- Expect.equals("-67153019", (new int32.fromInt(123456789) *
- new int32.fromInt(987654321)).toString());
- Expect.equals("121932631112635269", (new int64.fromInt(123456789) *
- new int32.fromInt(987654321)).toString());
- Expect.equals("121932631112635269", (new int32.fromInt(123456789) *
- new int64.fromInt(987654321)).toString());
- Expect.equals("121932631112635269", (new int64.fromInt(123456789) *
- new int64.fromInt(987654321)).toString());
+ test("%", () {
+ expect(new int32.fromInt(0x12345678) % new int32.fromInt(0x22),
+ new int32.fromInt(0x12345678 % 0x22));
+ expect(new int32.fromInt(0x12345678) % new int64.fromInt(0x22),
+ new int32.fromInt(0x12345678 % 0x22));
+ expect(() => new int32.fromInt(17) % null, throws);
+ });
- Expect.equals("432461",
- (new int32.fromInt(829893893) ~/ new int32.fromInt(1919)).toString());
- Expect.equals("432461",
- (new int32.fromInt(829893893) ~/ new int64.fromInt(1919)).toString());
- Expect.equals("432461",
- (new int64.fromInt(829893893) ~/ new int32.fromInt(1919)).toString());
- Expect.equals("432461",
- (new int64.fromInt(829893893) ~/ new int64.fromInt(1919)).toString());
- Expect.equals("432461",
- (new int32.fromInt(829893893) ~/ 1919).toString());
- Expect.equals("432461",
- (new int64.fromInt(829893893) ~/ 1919).toString());
+ test("remainder", () {
+ expect(new int32.fromInt(0x12345678).remainder(new int32.fromInt(0x22)),
+ new int32.fromInt(0x12345678.remainder(0x22)));
+ expect(new int32.fromInt(0x12345678).remainder(new int32.fromInt(-0x22)),
+ new int32.fromInt(0x12345678.remainder(-0x22)));
+ expect(new int32.fromInt(-0x12345678).remainder(new int32.fromInt(-0x22)),
+ new int32.fromInt(-0x12345678.remainder(-0x22)));
+ expect(new int32.fromInt(-0x12345678).remainder(new int32.fromInt(0x22)),
+ new int32.fromInt(-0x12345678.remainder(0x22)));
+ expect(new int32.fromInt(0x12345678).remainder(new int64.fromInt(0x22)),
+ new int32.fromInt(0x12345678.remainder(0x22)));
+ expect(() => new int32.fromInt(17).remainder(null), throws);
+ });
+ });
- Expect.isTrue(new int32.fromInt(12345) == 12345);
- Expect.isTrue(new int32.fromInt(12345) == new int32.fromInt(12345));
- Expect.isTrue(new int64.fromInt(12345) == new int32.fromInt(12345));
+ group("comparison operators", () {
+ test("<", () {
+ expect(new int32.fromInt(17) < new int32.fromInt(18), true);
+ expect(new int32.fromInt(17) < new int32.fromInt(17), false);
+ expect(new int32.fromInt(17) < new int32.fromInt(16), false);
+ expect(int32.MIN_VALUE < int32.MAX_VALUE, true);
+ expect(int32.MAX_VALUE < int32.MIN_VALUE, false);
+ expect(() => new int32.fromInt(17) < null, throws);
+ });
- Expect.equals(new int32.fromInt(~0x12345678),
- ~(new int32.fromInt(0x12345678)));
- Expect.equals(new int64.fromInt(-0x12345678),
- -(new int32.fromInt(0x12345678)));
+ test("<=", () {
+ expect(new int32.fromInt(17) <= new int32.fromInt(18), true);
+ expect(new int32.fromInt(17) <= new int32.fromInt(17), true);
+ expect(new int32.fromInt(17) <= new int32.fromInt(16), false);
+ expect(int32.MIN_VALUE <= int32.MAX_VALUE, true);
+ expect(int32.MAX_VALUE <= int32.MIN_VALUE, false);
+ expect(() => new int32.fromInt(17) <= null, throws);
+ });
- Expect.equals(new int32.fromInt(0x12345678 & 0x22222222),
- new int32.fromInt(0x12345678) & new int32.fromInt(0x22222222));
- Expect.equals(new int64.fromInt(0x12345678 & 0x22222222),
- new int32.fromInt(0x12345678) & new int64.fromInt(0x22222222));
- Expect.equals(new int32.fromInt(0x12345678 | 0x22222222),
- new int32.fromInt(0x12345678) | new int32.fromInt(0x22222222));
- Expect.equals(new int64.fromInt(0x12345678 | 0x22222222),
- new int32.fromInt(0x12345678) | new int64.fromInt(0x22222222));
- Expect.equals(new int32.fromInt(0x12345678 ^ 0x22222222),
- new int32.fromInt(0x12345678) ^ new int32.fromInt(0x22222222));
- Expect.equals(new int64.fromInt(0x12345678 ^ 0x22222222),
- new int32.fromInt(0x12345678) ^ new int64.fromInt(0x22222222));
+ test("==", () {
+ expect(new int32.fromInt(17) == new int32.fromInt(18), false);
+ expect(new int32.fromInt(17) == new int32.fromInt(17), true);
+ expect(new int32.fromInt(17) == new int32.fromInt(16), false);
+ expect(int32.MIN_VALUE == int32.MAX_VALUE, false);
+ expect(new int32.fromInt(17) == null, false);
+ });
- Expect.equals(new int32.fromInt(0x12345678 + 0x22222222),
- new int32.fromInt(0x12345678) + new int32.fromInt(0x22222222));
- Expect.equals(new int64.fromInt(0x12345678 + 0x22222222),
- new int32.fromInt(0x12345678) + new int64.fromInt(0x22222222));
- Expect.equals(new int32.fromInt(0x12345678 - 0x22222222),
- new int32.fromInt(0x12345678) - new int32.fromInt(0x22222222));
- Expect.equals(new int64.fromInt(0x12345678 - 0x22222222),
- new int32.fromInt(0x12345678) - new int64.fromInt(0x22222222));
- Expect.equals(new int32.fromInt(-899716112),
- new int32.fromInt(0x12345678) * new int32.fromInt(0x22222222));
- Expect.equals(new int64.fromInts(0x026D60DC, 0xCA5F6BF0),
- new int32.fromInt(0x12345678) * new int64.fromInt(0x22222222));
- Expect.equals(new int32.fromInt(0x12345678 % 0x22),
- new int32.fromInt(0x12345678) % new int32.fromInt(0x22));
- Expect.equals(new int32.fromInt(0x12345678 % 0x22),
- new int32.fromInt(0x12345678) % new int64.fromInt(0x22));
- Expect.equals(new int32.fromInt(0x12345678.remainder(0x22)),
- new int32.fromInt(0x12345678).remainder(new int32.fromInt(0x22)));
- Expect.equals(new int32.fromInt(0x12345678.remainder(-0x22)),
- new int32.fromInt(0x12345678).remainder(new int32.fromInt(-0x22)));
- Expect.equals(new int32.fromInt(-0x12345678.remainder(-0x22)),
- new int32.fromInt(-0x12345678).remainder(new int32.fromInt(-0x22)));
- Expect.equals(new int32.fromInt(-0x12345678.remainder(0x22)),
- new int32.fromInt(-0x12345678).remainder(new int32.fromInt(0x22)));
- Expect.equals(new int32.fromInt(0x12345678.remainder(0x22)),
- new int32.fromInt(0x12345678).remainder(new int64.fromInt(0x22)));
- Expect.equals(new int32.fromInt(0x12345678 ~/ 0x22),
- new int32.fromInt(0x12345678) ~/ new int32.fromInt(0x22));
- Expect.equals(new int32.fromInt(0x12345678 ~/ 0x22),
- new int32.fromInt(0x12345678) ~/ new int64.fromInt(0x22));
+ test(">=", () {
+ expect(new int32.fromInt(17) >= new int32.fromInt(18), false);
+ expect(new int32.fromInt(17) >= new int32.fromInt(17), true);
+ expect(new int32.fromInt(17) >= new int32.fromInt(16), true);
+ expect(int32.MIN_VALUE >= int32.MAX_VALUE, false);
+ expect(int32.MAX_VALUE >= int32.MIN_VALUE, true);
+ expect(() => new int32.fromInt(17) >= null, throws);
+ });
- Expect.equals(new int32.fromInt(0x12345678 >> 7),
- new int32.fromInt(0x12345678) >> 7);
- Expect.equals(new int32.fromInt(0x12345678 << 7),
- new int32.fromInt(0x12345678) << 7);
- Expect.equals(new int32.fromInt(0x12345678 >> 7),
- new int32.fromInt(0x12345678).shiftRightUnsigned(7));
+ test(">", () {
+ expect(new int32.fromInt(17) > new int32.fromInt(18), false);
+ expect(new int32.fromInt(17) > new int32.fromInt(17), false);
+ expect(new int32.fromInt(17) > new int32.fromInt(16), true);
+ expect(int32.MIN_VALUE > int32.MAX_VALUE, false);
+ expect(int32.MAX_VALUE > int32.MIN_VALUE, true);
+ expect(() => new int32.fromInt(17) > null, throws);
+ });
+ });
- try {
- new int32.fromInt(17) < null;
- Expect.fail("x < null should throw ArgumentError");
- } on ArgumentError catch (e) {
- }
+ group("bitwise operators", () {
+ test("&", () {
+ expect(new int32.fromInt(0x12345678) & new int32.fromInt(0x22222222),
+ new int32.fromInt(0x12345678 & 0x22222222));
+ expect(new int32.fromInt(0x12345678) & new int64.fromInt(0x22222222),
+ new int64.fromInt(0x12345678 & 0x22222222));
+ expect(() => new int32.fromInt(17) & null, throwsArgumentError);
+ });
- try {
- new int32.fromInt(17) <= null;
- Expect.fail("x <= null should throw ArgumentError");
- } on ArgumentError catch (e) {
- }
+ test("|", () {
+ expect(new int32.fromInt(0x12345678) | new int32.fromInt(0x22222222),
+ new int32.fromInt(0x12345678 | 0x22222222));
+ expect(new int32.fromInt(0x12345678) | new int64.fromInt(0x22222222),
+ new int64.fromInt(0x12345678 | 0x22222222));
+ expect(() => new int32.fromInt(17) | null, throws);
+ });
- try {
- new int32.fromInt(17) > null;
- Expect.fail("x > null should throw ArgumentError");
- } on ArgumentError catch (e) {
- }
+ test("^", () {
+ expect(new int32.fromInt(0x12345678) ^ new int32.fromInt(0x22222222),
+ new int32.fromInt(0x12345678 ^ 0x22222222));
+ expect(new int32.fromInt(0x12345678) ^ new int64.fromInt(0x22222222),
+ new int64.fromInt(0x12345678 ^ 0x22222222));
+ expect(() => new int32.fromInt(17) ^ null, throws);
+ });
- try {
- new int32.fromInt(17) < null;
- Expect.fail("x >= null should throw ArgumentError");
- } on ArgumentError catch (e) {
- }
+ test("~", () {
+ expect(~(new int32.fromInt(0x12345678)), new int32.fromInt(~0x12345678));
+ expect(-(new int32.fromInt(0x12345678)), new int64.fromInt(-0x12345678));
+ });
+ });
- Expect.isFalse(new int32.fromInt(17) == null);
+ group("bitshift operators", () {
+ test("<<", () {
+ expect(new int32.fromInt(0x12345678) << 7,
+ new int32.fromInt(0x12345678 << 7));
+ expect(() => new int32.fromInt(17) << -1, throwsArgumentError);
+ expect(() => new int32.fromInt(17) << null, throws);
+ });
+
+ test(">>", () {
+ expect(new int32.fromInt(0x12345678) >> 7,
+ new int32.fromInt(0x12345678 >> 7));
+ expect(() => new int32.fromInt(17) >> -1, throwsArgumentError);
+ expect(() => new int32.fromInt(17) >> null, throws);
+ });
+
+ test("shiftRightUnsigned", () {
+ expect(new int32.fromInt(0x12345678).shiftRightUnsigned(7),
+ new int32.fromInt(0x12345678 >> 7));
+ expect(() => (new int32.fromInt(17).shiftRightUnsigned(-1)),
+ throwsArgumentError);
+ expect(() => (new int32.fromInt(17).shiftRightUnsigned(null)), throws);
+ });
+ });
+
+ group("type conversions", () {
+ expect(new int32.fromInt(17).toInt(), 17);
+ expect(new int32.fromInt(-17).toInt(), -17);
+ expect(new int32.fromInt(17).toInt32(), new int32.fromInt(17));
+ expect(new int32.fromInt(-17).toInt32(), new int32.fromInt(-17));
+ expect(new int32.fromInt(17).toInt64(), new int64.fromInt(17));
+ expect(new int32.fromInt(-17).toInt64(), new int64.fromInt(-17));
+ });
+
+ group("string representation", () {
+ test("toString", () {
+ expect(new int32.fromInt(0).toString(), "0");
+ expect(new int32.fromInt(1).toString(), "1");
+ expect(new int32.fromInt(-1).toString(), "-1");
+ expect(new int32.fromInt(1000).toString(), "1000");
+ expect(new int32.fromInt(-1000).toString(), "-1000");
+ expect(new int32.fromInt(123456789).toString(), "123456789");
+ expect(new int32.fromInt(2147483647).toString(), "2147483647");
+ expect(new int32.fromInt(2147483648).toString(), "-2147483648");
+ expect(new int32.fromInt(2147483649).toString(), "-2147483647");
+ expect(new int32.fromInt(2147483650).toString(), "-2147483646");
+ expect(new int32.fromInt(-2147483648).toString(), "-2147483648");
+ expect(new int32.fromInt(-2147483649).toString(), "2147483647");
+ expect(new int32.fromInt(-2147483650).toString(), "2147483646");
+ });
+ });
+
+ group("toHexString", () {
+ test("returns hexadecimal string representation", () {
+ expect(new int32.fromInt(-1).toHexString(), "-1");
+ expect((new int32.fromInt(-1) >> 8).toHexString(), "-1");
+ expect((new int32.fromInt(-1) << 8).toHexString(), "-100");
+ expect(new int32.fromInt(123456789).toHexString(), "75bcd15");
+ expect(new int32.fromInt(-1).shiftRightUnsigned(8).toHexString(),
+ "ffffff");
+ });
+ });
+
+ group("toRadixString", () {
+ test("returns base n string representation", () {
+ expect(new int32.fromInt(123456789).toRadixString(5), "223101104124");
+ });
+ });
}
diff --git a/pkg/fixnum/test/int_64_test.dart b/pkg/fixnum/test/int_64_test.dart
index 8aa3e5b..fddb409 100644
--- a/pkg/fixnum/test/int_64_test.dart
+++ b/pkg/fixnum/test/int_64_test.dart
@@ -3,605 +3,581 @@
// BSD-style license that can be found in the LICENSE file.
library int64test;
-import "package:expect/expect.dart";
import 'package:fixnum/fixnum.dart';
+import 'package:unittest/unittest.dart';
void main() {
- testAdditive();
- testBitOps();
- testComparisons();
- testConversions();
- testDiv();
- testFactorial();
- testMinMax();
- testMod();
- testMultiplicative();
- testNegate();
- testShift();
- testToHexString();
- testToString();
-}
-
-void testAdditive() {
- {
+ group("arithmetic operators", () {
int64 n1 = new int64.fromInt(1234);
int64 n2 = new int64.fromInt(9876);
- Expect.equals(new int64.fromInt(11110), n1 + n2);
- Expect.equals(new int64.fromInt(-8642), n1 - n2);
- }
+ int64 n3 = new int64.fromInt(-1234);
+ int64 n4 = new int64.fromInt(-9876);
+ int64 n5 = new int64.fromInts(0x12345678, 0xabcdabcd);
+ int64 n6 = new int64.fromInts(0x77773333, 0x22224444);
- {
- int64 n1 = new int64.fromInt(-1234);
- int64 n2 = new int64.fromInt(9876);
- Expect.equals(new int64.fromInt(8642), n1 + n2);
- Expect.equals(new int64.fromInt(-11110), n1 - n2);
- }
+ test("+", () {
+ expect(n1 + n2, new int64.fromInt(11110));
+ expect(n3 + n2, new int64.fromInt(8642));
+ expect(n3 + n4, new int64.fromInt(-11110));
+ expect(n5 + n6, new int64.fromInts(0x89ab89ab, 0xcdeff011));
+ expect(int64.MAX_VALUE + 1, int64.MIN_VALUE);
+ });
- {
- int64 n1 = new int64.fromInt(-1234);
- int64 n2 = new int64.fromInt(-9876);
- Expect.equals(new int64.fromInt(-11110), n1 + n2);
- Expect.equals(new int64.fromInt(8642), n1 - n2);
- }
+ test("-", () {
+ expect(n1 - n2, new int64.fromInt(-8642));
+ expect(n3 - n2, new int64.fromInt(-11110));
+ expect(n3 - n4, new int64.fromInt(8642));
+ expect(n5 - n6, new int64.fromInts(0x9abd2345, 0x89ab6789));
+ expect(int64.MIN_VALUE - 1, int64.MAX_VALUE);
+ });
- {
- int64 n1 = new int64.fromInts(0x12345678, 0xabcdabcd);
- int64 n2 = new int64.fromInts(0x77773333, 0x22224444);
- Expect.equals(new int64.fromInts(0x89ab89ab, 0xcdeff011), n1 + n2);
- Expect.equals(new int64.fromInts(0x9abd2345, 0x89ab6789), n1 - n2);
- }
-}
+ test("unary -", () {
+ expect(-n1, new int64.fromInt(-1234));
+ expect(-int64.ZERO, int64.ZERO);
+ });
-void testBitOps() {
- {
+ test("*", () {
+ expect(new int64.fromInt(1111) * new int64.fromInt(3),
+ new int64.fromInt(3333));
+ expect(new int64.fromInt(1111) * new int64.fromInt(-3),
+ new int64.fromInt(-3333));
+ expect(new int64.fromInt(-1111) * new int64.fromInt(3),
+ new int64.fromInt(-3333));
+ expect(new int64.fromInt(-1111) * new int64.fromInt(-3),
+ new int64.fromInt(3333));
+ expect(new int64.fromInt(100) * new int64.fromInt(0),
+ new int64.fromInt(0));
+
+ expect(new int64.fromInts(0x12345678, 0x12345678) *
+ new int64.fromInts(0x1234, 0x12345678),
+ new int64.fromInts(0x7ff63f7c, 0x1df4d840));
+ expect(new int64.fromInts(0xf2345678, 0x12345678) *
+ new int64.fromInts(0x1234, 0x12345678),
+ new int64.fromInts(0x7ff63f7c, 0x1df4d840));
+ expect(new int64.fromInts(0xf2345678, 0x12345678) *
+ new int64.fromInts(0xffff1234, 0x12345678),
+ new int64.fromInts(0x297e3f7c, 0x1df4d840));
+
+ // RHS int32
+ expect((new int64.fromInt(123456789) * new int32.fromInt(987654321)),
+ new int64.fromInts(0x1b13114, 0xfbff5385));
+ expect((new int64.fromInt(123456789) * new int32.fromInt(987654321)),
+ new int64.fromInts(0x1b13114, 0xfbff5385));
+
+ // Wraparound
+ expect((new int64.fromInt(123456789) * new int64.fromInt(987654321)),
+ new int64.fromInts(0x1b13114, 0xfbff5385));
+
+ expect(int64.MIN_VALUE * new int64.fromInt(2), new int64.fromInt(0));
+ expect(int64.MIN_VALUE * new int64.fromInt(1), int64.MIN_VALUE);
+ expect(int64.MIN_VALUE * new int64.fromInt(-1), int64.MIN_VALUE);
+ });
+
+ test("~/", () {
+ int64 deadBeef = new int64.fromInts(0xDEADBEEF, 0xDEADBEEF);
+ int64 ten = new int64.fromInt(10);
+
+ expect(deadBeef ~/ ten, new int64.fromInts(0xfcaaf97e, 0x63115fe5));
+ expect(int64.ONE ~/ int64.TWO, int64.ZERO);
+ expect(int64.MAX_VALUE ~/ int64.TWO,
+ new int64.fromInts(0x3fffffff, 0xffffffff));
+ expect(int64.ZERO ~/ new int64.fromInt(1000), int64.ZERO);
+ expect(int64.MIN_VALUE ~/ int64.MIN_VALUE, int64.ONE);
+ expect(new int64.fromInt(1000) ~/ int64.MIN_VALUE, int64.ZERO);
+ expect(int64.MIN_VALUE ~/ new int64.fromInt(8192),
+ new int64.fromInt(-1125899906842624));
+ expect(int64.MIN_VALUE ~/ new int64.fromInt(8193),
+ new int64.fromInt(-1125762484664320));
+ expect(new int64.fromInt(-1000) ~/ new int64.fromInt(8192), int64.ZERO);
+ expect(new int64.fromInt(-1000) ~/ new int64.fromInt(8193), int64.ZERO);
+ expect(new int64.fromInt(-1000000000) ~/ new int64.fromInt(8192),
+ new int64.fromInt(-122070));
+ expect(new int64.fromInt(-1000000000) ~/ new int64.fromInt(8193),
+ new int64.fromInt(-122055));
+ expect(new int64.fromInt(1000000000) ~/ new int64.fromInt(8192),
+ new int64.fromInt(122070));
+ expect(new int64.fromInt(1000000000) ~/ new int64.fromInt(8193),
+ new int64.fromInt(122055));
+ expect(int64.MAX_VALUE ~/ new int64.fromInts(0x00000000, 0x00000400),
+ new int64.fromInts(0x1fffff, 0xffffffff));
+ expect(int64.MAX_VALUE ~/ new int64.fromInts(0x00000000, 0x00040000),
+ new int64.fromInts(0x1fff, 0xffffffff));
+ expect(int64.MAX_VALUE ~/ new int64.fromInts(0x00000000, 0x04000000),
+ new int64.fromInts(0x1f, 0xffffffff));
+ expect(int64.MAX_VALUE ~/ new int64.fromInts(0x00000004, 0x00000000),
+ new int64.fromInt(536870911));
+ expect(int64.MAX_VALUE ~/ new int64.fromInts(0x00000400, 0x00000000),
+ new int64.fromInt(2097151));
+ expect(int64.MAX_VALUE ~/ new int64.fromInts(0x00040000, 0x00000000),
+ new int64.fromInt(8191));
+ expect(int64.MAX_VALUE ~/ new int64.fromInts(0x04000000, 0x00000000),
+ new int64.fromInt(31));
+ expect(int64.MAX_VALUE ~/ new int64.fromInts(0x00000000, 0x00000300),
+ new int64.fromInts(0x2AAAAA, 0xAAAAAAAA));
+ expect(int64.MAX_VALUE ~/ new int64.fromInts(0x00000000, 0x30000000),
+ new int64.fromInts(0x2, 0xAAAAAAAA));
+ expect(int64.MAX_VALUE ~/ new int64.fromInts(0x00300000, 0x00000000),
+ new int64.fromInt(0x2AA));
+ expect(int64.MAX_VALUE ~/ new int64.fromInt(0x123456),
+ new int64.fromInts(0x708, 0x002E9501));
+ expect(int64.MAX_VALUE % new int64.fromInt(0x123456),
+ new int64.fromInt(0x3BDA9));
+ expect(new int64.fromInt(5) ~/ new int64.fromInt(5),
+ new int64.fromInt(1));
+ expect(new int64.fromInt(1000) ~/ new int64.fromInt(3),
+ new int64.fromInt(333));
+ expect(new int64.fromInt(1000) ~/ new int64.fromInt(-3),
+ new int64.fromInt(-333));
+ expect(new int64.fromInt(-1000) ~/ new int64.fromInt(3),
+ new int64.fromInt(-333));
+ expect(new int64.fromInt(-1000) ~/ new int64.fromInt(-3),
+ new int64.fromInt(333));
+ expect(new int64.fromInt(3) ~/ new int64.fromInt(1000),
+ new int64.fromInt(0));
+ expect(new int64.fromInts( 0x12345678, 0x12345678) ~/
+ new int64.fromInts(0x0, 0x123),
+ new int64.fromInts(0x1003d0, 0xe84f5ae8));
+ expect(new int64.fromInts(0x12345678, 0x12345678) ~/
+ new int64.fromInts(0x1234, 0x12345678),
+ new int64.fromInts(0x0, 0x10003));
+ expect(new int64.fromInts(0xf2345678, 0x12345678) ~/
+ new int64.fromInts(0x1234, 0x12345678),
+ new int64.fromInts(0xffffffff, 0xffff3dfe));
+ expect(new int64.fromInts(0xf2345678, 0x12345678) ~/
+ new int64.fromInts(0xffff1234, 0x12345678),
+ new int64.fromInts(0x0, 0xeda));
+ expect(new int64.fromInt(829893893) ~/ new int32.fromInt(1919),
+ new int32.fromInt(432461));
+ expect(new int64.fromInt(829893893) ~/ new int64.fromInt(1919),
+ new int32.fromInt(432461));
+ expect(new int64.fromInt(829893893) ~/ 1919,
+ new int32.fromInt(432461));
+ expect(() => new int64.fromInt(1) ~/ new int64.fromInt(0),
+ throwsA(new isInstanceOf<IntegerDivisionByZeroException>()));
+ expect(int64.MIN_VALUE ~/ new int64.fromInt(2),
+ new int64.fromInts(0xc0000000, 0x00000000));
+ expect(int64.MIN_VALUE ~/ new int64.fromInt(1), int64.MIN_VALUE);
+ expect(int64.MIN_VALUE ~/ new int64.fromInt(-1), int64.MIN_VALUE);
+ expect(() => new int64.fromInt(17) ~/ int64.ZERO, throws);
+ expect(() => new int64.fromInt(17) ~/ null, throws);
+ });
+
+ test("%", () {
+ // Define % as Euclidean mod, with positive result for all arguments
+ expect(int64.ZERO % new int64.fromInt(1000), new int64.fromInt(0));
+ expect(int64.MIN_VALUE % int64.MIN_VALUE, new int64.fromInt(0));
+ expect(new int64.fromInt(1000) % int64.MIN_VALUE,
+ new int64.fromInt(1000));
+ expect(int64.MIN_VALUE % new int64.fromInt(8192), new int64.fromInt(0));
+ expect(int64.MIN_VALUE % new int64.fromInt(8193),
+ new int64.fromInt(6145));
+ expect(new int64.fromInt(-1000) % new int64.fromInt(8192),
+ new int64.fromInt(7192));
+ expect(new int64.fromInt(-1000) % new int64.fromInt(8193),
+ new int64.fromInt(7193));
+ expect(new int64.fromInt(-1000000000) % new int64.fromInt(8192),
+ new int64.fromInt(5632));
+ expect(new int64.fromInt(-1000000000) % new int64.fromInt(8193),
+ new int64.fromInt(4808));
+ expect(new int64.fromInt(1000000000) % new int64.fromInt(8192),
+ new int64.fromInt(2560));
+ expect(new int64.fromInt(1000000000) % new int64.fromInt(8193),
+ new int64.fromInt(3385));
+ expect(int64.MAX_VALUE % new int64.fromInts(0x00000000, 0x00000400),
+ new int64.fromInts(0x0, 0x3ff));
+ expect(int64.MAX_VALUE % new int64.fromInts(0x00000000, 0x00040000),
+ new int64.fromInts(0x0, 0x3ffff));
+ expect(int64.MAX_VALUE % new int64.fromInts(0x00000000, 0x04000000),
+ new int64.fromInts(0x0, 0x3ffffff));
+ expect(int64.MAX_VALUE % new int64.fromInts(0x00000004, 0x00000000),
+ new int64.fromInts(0x3, 0xffffffff));
+ expect(int64.MAX_VALUE % new int64.fromInts(0x00000400, 0x00000000),
+ new int64.fromInts(0x3ff, 0xffffffff));
+ expect(int64.MAX_VALUE % new int64.fromInts(0x00040000, 0x00000000),
+ new int64.fromInts(0x3ffff, 0xffffffff));
+ expect(int64.MAX_VALUE % new int64.fromInts(0x04000000, 0x00000000),
+ new int64.fromInts(0x3ffffff, 0xffffffff));
+ expect(new int64.fromInt(0x12345678).remainder(new int64.fromInt(0x22)),
+ new int64.fromInt(0x12345678.remainder(0x22)));
+ expect(new int64.fromInt(0x12345678).remainder(new int64.fromInt(-0x22)),
+ new int64.fromInt(0x12345678.remainder(-0x22)));
+ expect(new int64.fromInt(-0x12345678).remainder(new int64.fromInt(-0x22)),
+ new int64.fromInt(-0x12345678.remainder(-0x22)));
+ expect(new int64.fromInt(-0x12345678).remainder(new int64.fromInt(0x22)),
+ new int64.fromInt(-0x12345678.remainder(0x22)));
+ expect(new int32.fromInt(0x12345678).remainder(new int64.fromInt(0x22)),
+ new int64.fromInt(0x12345678.remainder(0x22)));
+ });
+ });
+
+ group("comparison operators", () {
+ int64 largeNeg = new int64.fromInts(0x82341234, 0x0);
+ int64 largePos = new int64.fromInts(0x12341234, 0x0);
+ int64 largePosPlusOne = largePos + new int64.fromInt(1);
+
+ test("<", () {
+ expect(new int64.fromInt(10) < new int64.fromInt(11), true);
+ expect(new int64.fromInt(10) < new int64.fromInt(10), false);
+ expect(new int64.fromInt(12) < new int64.fromInt(11), false);
+ expect(new int64.fromInt(-10) < new int64.fromInt(-11), false);
+ expect(int64.MIN_VALUE < new int64.fromInt(0), true);
+ expect(largeNeg < largePos, true);
+ expect(largePos < largePosPlusOne, true);
+ expect(largePos < largePos, false);
+ expect(largePosPlusOne < largePos, false);
+ expect(int64.MIN_VALUE < int64.MAX_VALUE, true);
+ expect(int64.MAX_VALUE < int64.MIN_VALUE, false);
+ expect(() => new int64.fromInt(17) < null, throwsArgumentError);
+ });
+
+ test("<=", () {
+ expect(new int64.fromInt(10) <= new int64.fromInt(11), true);
+ expect(new int64.fromInt(10) <= new int64.fromInt(10), true);
+ expect(new int64.fromInt(12) <= new int64.fromInt(11), false);
+ expect(new int64.fromInt(-10) <= new int64.fromInt(-11), false);
+ expect(new int64.fromInt(-10) <= new int64.fromInt(-10), true);
+ expect(largeNeg <= largePos, true);
+ expect(largePos <= largeNeg, false);
+ expect(largePos <= largePosPlusOne, true);
+ expect(largePos <= largePos, true);
+ expect(largePosPlusOne <= largePos, false);
+ expect(int64.MIN_VALUE <= int64.MAX_VALUE, true);
+ expect(int64.MAX_VALUE <= int64.MIN_VALUE, false);
+ expect(() => new int64.fromInt(17) <= null, throwsArgumentError);
+ });
+
+ test("==", () {
+ expect(new int64.fromInt(10) == new int64.fromInt(11), false);
+ expect(new int64.fromInt(10) == new int64.fromInt(10), true);
+ expect(new int64.fromInt(12) == new int64.fromInt(11), false);
+ expect(new int64.fromInt(-10) == new int64.fromInt(-10), true);
+ expect(new int64.fromInt(-10) != new int64.fromInt(-10), false);
+ expect(largePos == largePos, true);
+ expect(largePos == largePosPlusOne, false);
+ expect(largePosPlusOne == largePos, false);
+ expect(int64.MIN_VALUE == int64.MAX_VALUE, false);
+ expect(new int64.fromInt(17) == null, false);
+ });
+
+ test(">=", () {
+ expect(new int64.fromInt(10) >= new int64.fromInt(11), false);
+ expect(new int64.fromInt(10) >= new int64.fromInt(10), true);
+ expect(new int64.fromInt(12) >= new int64.fromInt(11), true);
+ expect(new int64.fromInt(-10) >= new int64.fromInt(-11), true);
+ expect(new int64.fromInt(-10) >= new int64.fromInt(-10), true);
+ expect(largePos >= largeNeg, true);
+ expect(largeNeg >= largePos, false);
+ expect(largePos >= largePosPlusOne, false);
+ expect(largePos >= largePos, true);
+ expect(largePosPlusOne >= largePos, true);
+ expect(int64.MIN_VALUE >= int64.MAX_VALUE, false);
+ expect(int64.MAX_VALUE >= int64.MIN_VALUE, true);
+ expect(() => new int64.fromInt(17) >= null, throwsArgumentError);
+ });
+
+ test(">", () {
+ expect(new int64.fromInt(10) > new int64.fromInt(11), false);
+ expect(new int64.fromInt(10) > new int64.fromInt(10), false);
+ expect(new int64.fromInt(12) > new int64.fromInt(11), true);
+ expect(new int64.fromInt(-10) > new int64.fromInt(-11), true);
+ expect(new int64.fromInt(10) > new int64.fromInt(-11), true);
+ expect(new int64.fromInt(-10) > new int64.fromInt(11), false);
+ expect(largePos > largeNeg, true);
+ expect(largeNeg > largePos, false);
+ expect(largePos > largePosPlusOne, false);
+ expect(largePos > largePos, false);
+ expect(largePosPlusOne > largePos, true);
+ expect(new int64.fromInt(0) > int64.MIN_VALUE, true);
+ expect(int64.MIN_VALUE > int64.MAX_VALUE, false);
+ expect(int64.MAX_VALUE > int64.MIN_VALUE, true);
+ expect(() => new int64.fromInt(17) > null, throwsArgumentError);
+ });
+ });
+
+ group("bitwise operators", () {
int64 n1 = new int64.fromInt(1234);
int64 n2 = new int64.fromInt(9876);
+ int64 n3 = new int64.fromInt(-1234);
+ int64 n4 = new int64.fromInt(0x1234) << 32;
+ int64 n5 = new int64.fromInt(0x9876) << 32;
- Expect.equals(new int64.fromInt(1168), n1 & n2);
- Expect.equals(new int64.fromInt(9942), n1 | n2);
- Expect.equals(new int64.fromInt(8774), n1 ^ n2);
- Expect.equals(new int64.fromInt(-1235), ~n1);
- Expect.equals(new int64.fromInt(-9877), ~n2);
- }
+ test("&", () {
+ expect(n1 & n2, new int64.fromInt(1168));
+ expect(n3 & n2, new int64.fromInt(8708));
+ expect(n4 & n5, new int64.fromInt(0x1034) << 32);
+ expect(() => n1 & null, throws);
+ });
- {
- int64 n1 = new int64.fromInt(-1234);
- int64 n2 = new int64.fromInt(9876);
- Expect.equals(new int64.fromInt(8708), n1 & n2);
- Expect.equals(new int64.fromInt(-66), n1 | n2);
- Expect.equals(new int64.fromInt(-8774), n1 ^ n2);
- Expect.equals(new int64.fromInt(1233), ~n1);
- Expect.equals(new int64.fromInt(-9877), ~n2);
- }
+ test("|", () {
+ expect(n1 | n2, new int64.fromInt(9942));
+ expect(n3 | n2, new int64.fromInt(-66));
+ expect(n4 | n5, new int64.fromInt(0x9a76) << 32);
+ expect(() => n1 | null, throws);
+ });
- {
- int64 n1 = new int64.fromInt(0x1234) << 32;
- int64 n2 = new int64.fromInt(0x9876) << 32;
- Expect.equals(new int64.fromInt(0x1034) << 32, n1 & n2);
- Expect.equals(new int64.fromInt(0x9a76) << 32, n1 | n2);
- Expect.equals(new int64.fromInt(0x8a42) << 32, n1 ^ n2);
- Expect.equals(new int64.fromInts(0xffffedcb, 0xffffffff), ~n1);
- Expect.equals(new int64.fromInts(0xffff6789, 0xffffffff), ~n2);
- }
-}
+ test("^", () {
+ expect(n1 ^ n2, new int64.fromInt(8774));
+ expect(n3 ^ n2, new int64.fromInt(-8774));
+ expect(n4 ^ n5, new int64.fromInt(0x8a42) << 32);
+ expect(() => n1 ^ null, throws);
+ });
-void testComparisons() {
- Expect.isTrue(new int64.fromInt(10) < new int64.fromInt(11));
- Expect.isTrue(new int64.fromInt(10) <= new int64.fromInt(11));
- Expect.isTrue(!(new int64.fromInt(10) == new int64.fromInt(11)));
- Expect.isTrue(!(new int64.fromInt(10) >= new int64.fromInt(11)));
- Expect.isTrue(!(new int64.fromInt(10) > new int64.fromInt(11)));
+ test("~", () {
+ expect(-new int64.fromInt(1), new int64.fromInt(-1));
+ expect(-new int64.fromInt(-1), new int64.fromInt(1));
+ expect(-int64.MIN_VALUE, int64.MIN_VALUE);
- Expect.isTrue(!(new int64.fromInt(10) < new int64.fromInt(10)));
- Expect.isTrue(new int64.fromInt(10) <= new int64.fromInt(10));
- Expect.isTrue(new int64.fromInt(10) == new int64.fromInt(10));
- Expect.isTrue(new int64.fromInt(10) >= new int64.fromInt(10));
- Expect.isTrue(!(new int64.fromInt(10) > new int64.fromInt(10)));
+ expect(~n1, new int64.fromInt(-1235));
+ expect(~n2, new int64.fromInt(-9877));
+ expect(~n3, new int64.fromInt(1233));
+ expect(~n4, new int64.fromInts(0xffffedcb, 0xffffffff));
+ expect(~n5, new int64.fromInts(0xffff6789, 0xffffffff));
+ });
+ });
- Expect.isTrue(!(new int64.fromInt(12) < new int64.fromInt(11)));
- Expect.isTrue(!(new int64.fromInt(12) <= new int64.fromInt(11)));
- Expect.isTrue(!(new int64.fromInt(12) == new int64.fromInt(11)));
- Expect.isTrue(new int64.fromInt(12) >= new int64.fromInt(11));
- Expect.isTrue(new int64.fromInt(12) > new int64.fromInt(11));
+ group("bitshift operators", () {
+ test("<<", () {
+ expect(new int64.fromInts(0x12341234, 0x45674567) << 10,
+ new int64.fromInts(0xd048d115, 0x9d159c00));
+ expect(new int64.fromInts(0x92341234, 0x45674567) << 10,
+ new int64.fromInts(0xd048d115, 0x9d159c00));
+ expect(new int64.fromInt(-1) << 5, new int64.fromInt(-32));
+ expect(new int64.fromInt(-1) << 0, new int64.fromInt(-1));
+ expect(() => new int64.fromInt(17) << -1, throwsArgumentError);
+ expect(() => new int64.fromInt(17) << null, throws);
+ });
- Expect.isTrue(new int64.fromInt(-10) > new int64.fromInt(-11));
- Expect.isTrue(new int64.fromInt(10) > new int64.fromInt(-11));
- Expect.isTrue(!(new int64.fromInt(-10) > new int64.fromInt(11)));
- Expect.isTrue(new int64.fromInt(-10) >= new int64.fromInt(-11));
- Expect.isTrue(new int64.fromInt(-10) >= new int64.fromInt(-10));
- Expect.isTrue(!(new int64.fromInt(-10) < new int64.fromInt(-11)));
- Expect.isTrue(!(new int64.fromInt(-10) <= new int64.fromInt(-11)));
- Expect.isTrue(new int64.fromInt(-10) <= new int64.fromInt(-10));
- Expect.isTrue(new int64.fromInt(-10) == new int64.fromInt(-10));
- Expect.isTrue(!(new int64.fromInt(-10) != new int64.fromInt(-10)));
+ test(">>", () {
+ expect((int64.MIN_VALUE >> 13).toString(), "-1125899906842624");
+ expect(new int64.fromInts(0x12341234, 0x45674567) >> 10,
+ new int64.fromInts(0x48d04, 0x8d1159d1));
+ expect(new int64.fromInts(0x92341234, 0x45674567) >> 10,
+ new int64.fromInts(0xffe48d04, 0x8d1159d1));
+ expect(new int64.fromInts(0xFFFFFFF, 0xFFFFFFFF) >> 34,
+ new int64.fromInt(67108863));
+ for (int n = 0; n <= 66; n++) {
+ expect(new int64.fromInt(-1) >> n, new int64.fromInt(-1));
+ }
+ expect(new int64.fromInts(0x72345678, 0x9abcdef0) >> 8,
+ new int64.fromInts(0x00723456, 0x789abcde));
+ expect(new int64.fromInts(0x72345678, 0x9abcdef0) >> 16,
+ new int64.fromInts(0x00007234, 0x56789abc));
+ expect(new int64.fromInts(0x72345678, 0x9abcdef0) >> 24,
+ new int64.fromInts(0x00000072, 0x3456789a));
+ expect(new int64.fromInts(0x72345678, 0x9abcdef0) >> 28,
+ new int64.fromInts(0x00000007, 0x23456789));
+ expect(new int64.fromInts(0x72345678, 0x9abcdef0) >> 32,
+ new int64.fromInts(0x00000000, 0x72345678));
+ expect(new int64.fromInts(0x72345678, 0x9abcdef0) >> 36,
+ new int64.fromInts(0x00000000, 0x07234567));
+ expect(new int64.fromInts(0x72345678, 0x9abcdef0) >> 40,
+ new int64.fromInts(0x00000000, 0x00723456));
+ expect(new int64.fromInts(0x72345678, 0x9abcde00) >> 44,
+ new int64.fromInts(0x00000000, 0x00072345));
+ expect(new int64.fromInts(0x72345678, 0x9abcdef0) >> 48,
+ new int64.fromInts(0x00000000, 0x00007234));
+ expect(new int64.fromInts(0x92345678, 0x9abcdef0) >> 8,
+ new int64.fromInts(0xff923456, 0x789abcde));
+ expect(new int64.fromInts(0x92345678, 0x9abcdef0) >> 16,
+ new int64.fromInts(0xffff9234, 0x56789abc));
+ expect(new int64.fromInts(0x92345678, 0x9abcdef0) >> 24,
+ new int64.fromInts(0xffffff92, 0x3456789a));
+ expect(new int64.fromInts(0x92345678, 0x9abcdef0) >> 28,
+ new int64.fromInts(0xfffffff9, 0x23456789));
+ expect(new int64.fromInts(0x92345678, 0x9abcdef0) >> 32,
+ new int64.fromInts(0xffffffff, 0x92345678));
+ expect(new int64.fromInts(0x92345678, 0x9abcdef0) >> 36,
+ new int64.fromInts(0xffffffff, 0xf9234567));
+ expect(new int64.fromInts(0x92345678, 0x9abcdef0) >> 40,
+ new int64.fromInts(0xffffffff, 0xff923456));
+ expect(new int64.fromInts(0x92345678, 0x9abcdef0) >> 44,
+ new int64.fromInts(0xffffffff, 0xfff92345));
+ expect(new int64.fromInts(0x92345678, 0x9abcdef0) >> 48,
+ new int64.fromInts(0xffffffff, 0xffff9234));
+ expect(() => new int64.fromInt(17) >> -1, throwsArgumentError);
+ expect(() => new int64.fromInt(17) >> null, throws);
+ });
- // the following three comparisons cannot be implemented by
- // subtracting the arguments, because the subtraction causes an overflow
- int64 largeNeg = new int64.fromInts(0x82341234, 0x0);
- int64 largePos = new int64.fromInts(0x12341234, 0x0);
- Expect.isTrue(largeNeg < largePos);
+ test("shiftRightUnsigned", () {
+ expect(new int64.fromInts(0x12341234, 0x45674567).shiftRightUnsigned(10),
+ new int64.fromInts(0x48d04, 0x8d1159d1));
+ expect(new int64.fromInts(0x92341234, 0x45674567).shiftRightUnsigned(10),
+ new int64.fromInts(0x248d04, 0x8d1159d1));
+ expect(new int64.fromInts(0x72345678, 0x9abcdef0).shiftRightUnsigned(8),
+ new int64.fromInts(0x00723456, 0x789abcde));
+ expect(new int64.fromInts(0x72345678, 0x9abcdef0).shiftRightUnsigned(16),
+ new int64.fromInts(0x00007234, 0x56789abc));
+ expect(new int64.fromInts(0x72345678, 0x9abcdef0).shiftRightUnsigned(24),
+ new int64.fromInts(0x00000072, 0x3456789a));
+ expect(new int64.fromInts(0x72345678, 0x9abcdef0).shiftRightUnsigned(28),
+ new int64.fromInts(0x00000007, 0x23456789));
+ expect(new int64.fromInts(0x72345678, 0x9abcdef0).shiftRightUnsigned(32),
+ new int64.fromInts(0x00000000, 0x72345678));
+ expect(new int64.fromInts(0x72345678, 0x9abcdef0).shiftRightUnsigned(36),
+ new int64.fromInts(0x00000000, 0x07234567));
+ expect(new int64.fromInts(0x72345678, 0x9abcdef0).shiftRightUnsigned(40),
+ new int64.fromInts(0x00000000, 0x00723456));
+ expect(new int64.fromInts(0x72345678, 0x9abcde00).shiftRightUnsigned(44),
+ new int64.fromInts(0x00000000, 0x00072345));
+ expect(new int64.fromInts(0x72345678, 0x9abcdef0).shiftRightUnsigned(48),
+ new int64.fromInts(0x00000000, 0x00007234));
+ expect(new int64.fromInts(0x92345678, 0x9abcdef0).shiftRightUnsigned(8),
+ new int64.fromInts(0x00923456, 0x789abcde));
+ expect(new int64.fromInts(0x92345678, 0x9abcdef0).shiftRightUnsigned(16),
+ new int64.fromInts(0x00009234, 0x56789abc));
+ expect(new int64.fromInts(0x92345678, 0x9abcdef0).shiftRightUnsigned(24),
+ new int64.fromInts(0x00000092, 0x3456789a));
+ expect(new int64.fromInts(0x92345678, 0x9abcdef0).shiftRightUnsigned(28),
+ new int64.fromInts(0x00000009, 0x23456789));
+ expect(new int64.fromInts(0x92345678, 0x9abcdef0).shiftRightUnsigned(32),
+ new int64.fromInts(0x00000000, 0x92345678));
+ expect(new int64.fromInts(0x92345678, 0x9abcdef0).shiftRightUnsigned(36),
+ new int64.fromInts(0x00000000, 0x09234567));
+ expect(new int64.fromInts(0x92345678, 0x9abcdef0).shiftRightUnsigned(40),
+ new int64.fromInts(0x00000000, 0x00923456));
+ expect(new int64.fromInts(0x92345678, 0x9abcdef0).shiftRightUnsigned(44),
+ new int64.fromInts(0x00000000, 0x00092345));
+ expect(new int64.fromInts(0x00000000, 0x00009234),
+ new int64.fromInts(0x92345678, 0x9abcdef0).shiftRightUnsigned(48));
+ expect(() => new int64.fromInt(17).shiftRightUnsigned(-1),
+ throwsArgumentError);
+ expect(() => new int64.fromInt(17).shiftRightUnsigned(null), throws);
+ });
- Expect.isTrue(int64.MIN_VALUE < new int64.fromInt(0));
- Expect.isTrue(new int64.fromInt(0) > int64.MIN_VALUE);
+ test("overflow", () {
+ expect((new int64.fromInt(1) << 63) >> 1,
+ -new int64.fromInts(0x40000000, 0x00000000));
+ expect((new int64.fromInt(-1) << 32) << 32, new int64.fromInt(0));
+ expect(int64.MIN_VALUE << 0, int64.MIN_VALUE);
+ expect(int64.MIN_VALUE << 1, new int64.fromInt(0));
+ expect((-new int64.fromInts(8, 0)) >> 1,
+ new int64.fromInts(0xfffffffc, 0x00000000));
+ expect((-new int64.fromInts(8, 0)).shiftRightUnsigned(1),
+ new int64.fromInts(0x7ffffffc, 0x0));
+ });
+ });
- int64 largePosPlusOne = largePos + new int64.fromInt(1);
+ group("type conversions", () {
+ test("toInt", () {
+ expect(new int64.fromInt(0).toInt(), 0);
+ expect(new int64.fromInt(100).toInt(), 100);
+ expect(new int64.fromInt(-100).toInt(), -100);
+ expect(new int64.fromInt(2147483647).toInt(), 2147483647);
+ expect(new int64.fromInt(2147483648).toInt(), 2147483648);
+ expect(new int64.fromInt(-2147483647).toInt(), -2147483647);
+ expect(new int64.fromInt(-2147483648).toInt(), -2147483648);
+ expect(new int64.fromInt(4503599627370495).toInt(), 4503599627370495);
+ expect(new int64.fromInt(4503599627370496).toInt(), 4503599627370496);
+ expect(new int64.fromInt(-4503599627370495).toInt(), -4503599627370495);
+ expect(new int64.fromInt(-4503599627370496).toInt(), -4503599627370496);
+ });
- Expect.isTrue(largePos < largePosPlusOne);
- Expect.isTrue(largePos <= largePosPlusOne);
- Expect.isTrue(!(largePos == largePosPlusOne));
- Expect.isTrue(!(largePos >= largePosPlusOne));
- Expect.isTrue(!(largePos > largePosPlusOne));
+ test("toInt32", () {
+ expect(new int64.fromInt(0).toInt32(), new int32.fromInt(0));
+ expect(new int64.fromInt(1).toInt32(), new int32.fromInt(1));
+ expect(new int64.fromInt(-1).toInt32(), new int32.fromInt(-1));
+ expect(new int64.fromInt(2147483647).toInt32(),
+ new int32.fromInt(2147483647));
+ expect(new int64.fromInt(2147483648).toInt32(),
+ new int32.fromInt(-2147483648));
+ expect(new int64.fromInt(2147483649).toInt32(),
+ new int32.fromInt(-2147483647));
+ expect(new int64.fromInt(2147483650).toInt32(),
+ new int32.fromInt(-2147483646));
+ expect(new int64.fromInt(-2147483648).toInt32(),
+ new int32.fromInt(-2147483648));
+ expect(new int64.fromInt(-2147483649).toInt32(),
+ new int32.fromInt(2147483647));
+ expect(new int64.fromInt(-2147483650).toInt32(),
+ new int32.fromInt(2147483646));
+ expect(new int64.fromInt(-2147483651).toInt32(),
+ new int32.fromInt(2147483645));
+ });
+ });
- Expect.isTrue(!(largePos < largePos));
- Expect.isTrue(largePos <= largePos);
- Expect.isTrue(largePos == largePos);
- Expect.isTrue(largePos >= largePos);
- Expect.isTrue(!(largePos > largePos));
-
- Expect.isTrue(!(largePosPlusOne < largePos));
- Expect.isTrue(!(largePosPlusOne <= largePos));
- Expect.isTrue(!(largePosPlusOne == largePos));
- Expect.isTrue(largePosPlusOne >= largePos);
- Expect.isTrue(largePosPlusOne > largePos);
-
- try {
- new int64.fromInt(17) < null;
- Expect.fail("x < null should throw ArgumentError");
- } on ArgumentError catch (e) {
- }
-
- try {
- new int64.fromInt(17) <= null;
- Expect.fail("x <= null should throw ArgumentError");
- } on ArgumentError catch (e) {
- }
-
- try {
- new int64.fromInt(17) > null;
- Expect.fail("x > null should throw ArgumentError");
- } on ArgumentError catch (e) {
- }
-
- try {
- new int64.fromInt(17) < null;
- Expect.fail("x >= null should throw ArgumentError");
- } on ArgumentError catch (e) {
- }
-
- Expect.isFalse(new int64.fromInt(17) == null);
-}
-
-void testConversions() {
- Expect.equals(0, new int64.fromInt(0).toInt());
- Expect.equals(100, new int64.fromInt(100).toInt());
- Expect.equals(-100, new int64.fromInt(-100).toInt());
- Expect.equals(2147483647, new int64.fromInt(2147483647).toInt());
- Expect.equals(2147483648, new int64.fromInt(2147483648).toInt());
- Expect.equals(-2147483647, new int64.fromInt(-2147483647).toInt());
- Expect.equals(-2147483648, new int64.fromInt(-2147483648).toInt());
- Expect.equals(4503599627370495, new int64.fromInt(4503599627370495).toInt());
- Expect.equals(4503599627370496, new int64.fromInt(4503599627370496).toInt());
- Expect.equals(-4503599627370495,
- new int64.fromInt(-4503599627370495).toInt());
- Expect.equals(-4503599627370496,
- new int64.fromInt(-4503599627370496).toInt());
-
- Expect.equals(new int32.fromInt(0), new int64.fromInt(0).toInt32());
- Expect.equals(new int32.fromInt(1), new int64.fromInt(1).toInt32());
- Expect.equals(new int32.fromInt(-1), new int64.fromInt(-1).toInt32());
- Expect.equals(new int32.fromInt(2147483647),
- new int64.fromInt(2147483647).toInt32());
- Expect.equals(new int32.fromInt(-2147483648),
- new int64.fromInt(2147483648).toInt32());
- Expect.equals(new int32.fromInt(-2147483647),
- new int64.fromInt(2147483649).toInt32());
- Expect.equals(new int32.fromInt(-2147483646),
- new int64.fromInt(2147483650).toInt32());
-
- Expect.equals(new int32.fromInt(-2147483648),
- new int64.fromInt(-2147483648).toInt32());
- Expect.equals(new int32.fromInt(2147483647),
- new int64.fromInt(-2147483649).toInt32());
- Expect.equals(new int32.fromInt(2147483646),
- new int64.fromInt(-2147483650).toInt32());
- Expect.equals(new int32.fromInt(2147483645),
- new int64.fromInt(-2147483651).toInt32());
-}
-
-void testDiv() {
- int64 deadBeef = new int64.fromInts(0xDEADBEEF, 0xDEADBEEF);
- int64 ten = new int64.fromInt(10);
- Expect.equals(new int64.fromInts(0xfcaaf97e, 0x63115fe5), deadBeef ~/ ten);
- Expect.equals(int64.ZERO, int64.ONE ~/ int64.TWO);
- Expect.equals(new int64.fromInts(0x3fffffff, 0xffffffff),
- int64.MAX_VALUE ~/ int64.TWO);
-
- Expect.equals(int64.ZERO, int64.ZERO ~/ new int64.fromInt(1000));
- Expect.equals(int64.ONE, int64.MIN_VALUE ~/ int64.MIN_VALUE);
- Expect.equals(int64.ZERO, new int64.fromInt(1000) ~/ int64.MIN_VALUE);
-
- Expect.equals("-1125899906842624",
- (int64.MIN_VALUE ~/ new int64.fromInt(8192)).toString());
- Expect.equals("-1125762484664320",
- (int64.MIN_VALUE ~/ new int64.fromInt(8193)).toString());
- Expect.equals(int64.ZERO,
- new int64.fromInt(-1000) ~/ new int64.fromInt(8192));
- Expect.equals(int64.ZERO,
- new int64.fromInt(-1000) ~/ new int64.fromInt(8193));
- Expect.equals(new int64.fromInt(-122070),
- new int64.fromInt(-1000000000) ~/ new int64.fromInt(8192));
- Expect.equals(new int64.fromInt(-122055),
- new int64.fromInt(-1000000000) ~/ new int64.fromInt(8193));
- Expect.equals(new int64.fromInt(122070),
- new int64.fromInt(1000000000) ~/ new int64.fromInt(8192));
- Expect.equals(new int64.fromInt(122055),
- new int64.fromInt(1000000000) ~/ new int64.fromInt(8193));
-
- Expect.equals(new int64.fromInts(0x1fffff, 0xffffffff),
- int64.MAX_VALUE ~/ new int64.fromInts(0x00000000, 0x00000400));
- Expect.equals(new int64.fromInts(0x1fff, 0xffffffff),
- int64.MAX_VALUE ~/ new int64.fromInts(0x00000000, 0x00040000));
- Expect.equals(new int64.fromInts(0x1f, 0xffffffff),
- int64.MAX_VALUE ~/ new int64.fromInts(0x00000000, 0x04000000));
- Expect.equals(new int64.fromInt(536870911),
- int64.MAX_VALUE ~/ new int64.fromInts(0x00000004, 0x00000000));
- Expect.equals(new int64.fromInt(2097151),
- int64.MAX_VALUE ~/ new int64.fromInts(0x00000400, 0x00000000));
- Expect.equals(new int64.fromInt(8191),
- int64.MAX_VALUE ~/ new int64.fromInts(0x00040000, 0x00000000));
- Expect.equals(new int64.fromInt(31),
- int64.MAX_VALUE ~/ new int64.fromInts(0x04000000, 0x00000000));
-
- Expect.equals(new int64.fromInts(0x2AAAAA, 0xAAAAAAAA),
- int64.MAX_VALUE ~/ new int64.fromInts(0x00000000, 0x00000300));
- Expect.equals(new int64.fromInts(0x2, 0xAAAAAAAA),
- int64.MAX_VALUE ~/ new int64.fromInts(0x00000000, 0x30000000));
- Expect.equals(new int64.fromInt(0x2AA),
- int64.MAX_VALUE ~/ new int64.fromInts(0x00300000, 0x00000000));
-
- Expect.equals(new int64.fromInts(0x708, 0x002E9501),
- int64.MAX_VALUE ~/ new int64.fromInt(0x123456));
- Expect.equals(new int64.fromInt(0x3BDA9),
- int64.MAX_VALUE % new int64.fromInt(0x123456));
-}
-
-void testFactorial() {
-
- int64 _fact(int64 n) {
- if (n.isZero) {
- return new int64.fromInt(1);
- } else {
- return n * _fact(n - new int64.fromInt(1));
+ test("JavaScript 53-bit integer boundary", () {
+ int64 _factorial(int64 n) {
+ if (n.isZero) {
+ return new int64.fromInt(1);
+ } else {
+ return n * _factorial(n - new int64.fromInt(1));
+ }
}
- }
+ int64 fact18 = _factorial(new int64.fromInt(18));
+ int64 fact17 = _factorial(new int64.fromInt(17));
+ expect(fact18 ~/ fact17, new int64.fromInt(18));
+ });
- int64 fact18 = _fact(new int64.fromInt(18));
- int64 fact17 = _fact(new int64.fromInt(17));
- Expect.equals(new int64.fromInt(18), fact18 ~/ fact17);
-}
+ test("min, max values", () {
+ expect(new int64.fromInt(1) << 63, int64.MIN_VALUE);
+ expect(-(int64.MIN_VALUE + new int64.fromInt(1)), int64.MAX_VALUE);
+ });
-void testMinMax() {
- Expect.equals(int64.MIN_VALUE, new int64.fromInt(1) << 63);
- Expect.equals(int64.MAX_VALUE, -(int64.MIN_VALUE + new int64.fromInt(1)));
-}
+ group("string representation", () {
+ test("toString", () {
+ expect(new int64.fromInt(0).toString(), "0");
+ expect(new int64.fromInt(1).toString(), "1");
+ expect(new int64.fromInt(-1).toString(), "-1");
+ expect(new int64.fromInt(-10).toString(), "-10");
+ expect(int64.MIN_VALUE.toString(), "-9223372036854775808");
+ expect(int64.MAX_VALUE.toString(), "9223372036854775807");
-// Define % as Euclidean mod, with positive result for all arguments
-void testMod() {
- Expect.equals(new int64.fromInt(0), int64.ZERO % new int64.fromInt(1000));
- Expect.equals(new int64.fromInt(0), int64.MIN_VALUE % int64.MIN_VALUE);
- Expect.equals(new int64.fromInt(1000),
- new int64.fromInt(1000) % int64.MIN_VALUE);
- Expect.equals(new int64.fromInt(0),
- int64.MIN_VALUE % new int64.fromInt(8192));
- Expect.equals(new int64.fromInt(6145),
- int64.MIN_VALUE % new int64.fromInt(8193));
+ int top = 922337201;
+ int bottom = 967490662;
+ int64 fullnum = (new int64.fromInt(1000000000) * new int64.fromInt(top)) +
+ new int64.fromInt(bottom);
+ expect(fullnum.toString(), "922337201967490662");
+ expect((-fullnum).toString(), "-922337201967490662");
+ expect(new int64.fromInt(123456789).toString(), "123456789");
+ });
- Expect.equals(new int64.fromInt(7192),
- new int64.fromInt(-1000) % new int64.fromInt(8192));
- Expect.equals(new int64.fromInt(7193),
- new int64.fromInt(-1000) % new int64.fromInt(8193));
- Expect.equals(new int64.fromInt(5632),
- new int64.fromInt(-1000000000) % new int64.fromInt(8192));
- Expect.equals(new int64.fromInt(4808),
- new int64.fromInt(-1000000000) % new int64.fromInt(8193));
- Expect.equals(new int64.fromInt(2560),
- new int64.fromInt(1000000000) % new int64.fromInt(8192));
- Expect.equals(new int64.fromInt(3385),
- new int64.fromInt(1000000000) % new int64.fromInt(8193));
+ test("toHexString", () {
+ int64 deadbeef12341234 = new int64.fromInts(0xDEADBEEF, 0x12341234);
+ expect(int64.ZERO.toHexString(), "0");
+ expect(deadbeef12341234.toHexString(), "DEADBEEF12341234");
+ expect(new int64.fromInts(0x17678A7, 0xDEF01234).toHexString(),
+ "17678A7DEF01234");
+ expect(new int64.fromInt(123456789).toHexString(), "75BCD15");
+ });
- Expect.equals(new int64.fromInts(0x0, 0x3ff),
- int64.MAX_VALUE % new int64.fromInts(0x00000000, 0x00000400));
- Expect.equals(new int64.fromInts(0x0, 0x3ffff),
- int64.MAX_VALUE % new int64.fromInts(0x00000000, 0x00040000));
- Expect.equals(new int64.fromInts(0x0, 0x3ffffff),
- int64.MAX_VALUE % new int64.fromInts(0x00000000, 0x04000000));
- Expect.equals(new int64.fromInts(0x3, 0xffffffff),
- int64.MAX_VALUE % new int64.fromInts(0x00000004, 0x00000000));
- Expect.equals(new int64.fromInts(0x3ff, 0xffffffff),
- int64.MAX_VALUE % new int64.fromInts(0x00000400, 0x00000000));
- Expect.equals(new int64.fromInts(0x3ffff, 0xffffffff),
- int64.MAX_VALUE % new int64.fromInts(0x00040000, 0x00000000));
- Expect.equals(new int64.fromInts(0x3ffffff, 0xffffffff),
- int64.MAX_VALUE % new int64.fromInts(0x04000000, 0x00000000));
-
- Expect.equals(new int64.fromInt(0x12345678.remainder(0x22)),
- new int64.fromInt(0x12345678).remainder(new int64.fromInt(0x22)));
- Expect.equals(new int64.fromInt(0x12345678.remainder(-0x22)),
- new int64.fromInt(0x12345678).remainder(new int64.fromInt(-0x22)));
- Expect.equals(new int64.fromInt(-0x12345678.remainder(-0x22)),
- new int64.fromInt(-0x12345678).remainder(new int64.fromInt(-0x22)));
- Expect.equals(new int64.fromInt(-0x12345678.remainder(0x22)),
- new int64.fromInt(-0x12345678).remainder(new int64.fromInt(0x22)));
- Expect.equals(new int64.fromInt(0x12345678.remainder(0x22)),
- new int32.fromInt(0x12345678).remainder(new int64.fromInt(0x22)));
-}
-
-void testMultiplicative() {
- Expect.equals(new int64.fromInt(3333),
- new int64.fromInt(1111) * new int64.fromInt(3));
- Expect.equals(new int64.fromInt(-3333),
- new int64.fromInt(1111) * new int64.fromInt(-3));
- Expect.equals(new int64.fromInt(-3333),
- new int64.fromInt(-1111) * new int64.fromInt(3));
- Expect.equals(new int64.fromInt(3333),
- new int64.fromInt(-1111) * new int64.fromInt(-3));
- Expect.equals(new int64.fromInt(0),
- new int64.fromInt(100) * new int64.fromInt(0));
-
- Expect.equals(new int64.fromInts(0x7ff63f7c, 0x1df4d840),
- new int64.fromInts(0x12345678, 0x12345678) *
- new int64.fromInts(0x1234, 0x12345678));
- Expect.equals(new int64.fromInts(0x7ff63f7c, 0x1df4d840),
- new int64.fromInts(0xf2345678, 0x12345678) *
- new int64.fromInts(0x1234, 0x12345678));
- Expect.equals(new int64.fromInts(0x297e3f7c, 0x1df4d840),
- new int64.fromInts(0xf2345678, 0x12345678) *
- new int64.fromInts(0xffff1234, 0x12345678));
-
- Expect.equals(new int64.fromInt(0), int64.MIN_VALUE * new int64.fromInt(2));
- Expect.equals(int64.MIN_VALUE, int64.MIN_VALUE * new int64.fromInt(1));
- Expect.equals(int64.MIN_VALUE, int64.MIN_VALUE * new int64.fromInt(-1));
-
- Expect.equals(new int64.fromInt(1), new int64.fromInt(5) ~/
- new int64.fromInt(5));
- Expect.equals(new int64.fromInt(333), new int64.fromInt(1000) ~/
- new int64.fromInt(3));
- Expect.equals(new int64.fromInt(-333), new int64.fromInt(1000) ~/
- new int64.fromInt(-3));
- Expect.equals(new int64.fromInt(-333), new int64.fromInt(-1000) ~/
- new int64.fromInt(3));
- Expect.equals(new int64.fromInt(333), new int64.fromInt(-1000) ~/
- new int64.fromInt(-3));
- Expect.equals(new int64.fromInt(0), new int64.fromInt(3) ~/
- new int64.fromInt(1000));
- Expect.equals(new int64.fromInts(0x1003d0, 0xe84f5ae8), new int64.fromInts(
- 0x12345678, 0x12345678) ~/ new int64.fromInts(0x0, 0x123));
- Expect.equals(new int64.fromInts(0x0, 0x10003), new int64.fromInts(
- 0x12345678, 0x12345678) ~/ new int64.fromInts(0x1234, 0x12345678));
- Expect.equals(new int64.fromInts(0xffffffff, 0xffff3dfe),
- new int64.fromInts(0xf2345678, 0x12345678) ~/
- new int64.fromInts(0x1234, 0x12345678));
- Expect.equals(new int64.fromInts(0x0, 0xeda), new int64.fromInts(0xf2345678,
- 0x12345678) ~/ new int64.fromInts(0xffff1234, 0x12345678));
-
- try {
- new int64.fromInt(1) ~/ new int64.fromInt(0);
- Expect.fail("Expected an IntegerDivisionByZeroException");
- } on IntegerDivisionByZeroException catch (e) {
- }
-
- Expect.equals(new int64.fromInts(0xc0000000, 0x00000000),
- int64.MIN_VALUE ~/ new int64.fromInt(2));
- Expect.equals(int64.MIN_VALUE, int64.MIN_VALUE ~/
- new int64.fromInt(1));
- Expect.equals(int64.MIN_VALUE, int64.MIN_VALUE ~/
- new int64.fromInt(-1));
-}
-
-void testNegate() {
- Expect.equals(new int64.fromInt(-1), -new int64.fromInt(1));
- Expect.equals(new int64.fromInt(1), -new int64.fromInt(-1));
- Expect.equals(int64.MIN_VALUE, -int64.MIN_VALUE);
-}
-
-void testShift() {
- Expect.equals("-1125899906842624", (int64.MIN_VALUE >> 13).toString());
- Expect.equals(new int64.fromInts(0xd048d115, 0x9d159c00),
- new int64.fromInts(0x12341234, 0x45674567) << 10);
- Expect.equals(new int64.fromInts(0x48d04, 0x8d1159d1),
- new int64.fromInts(0x12341234, 0x45674567) >> 10);
- Expect.equals(new int64.fromInts(0x48d04, 0x8d1159d1),
- new int64.fromInts(0x12341234, 0x45674567).shiftRightUnsigned(10));
- Expect.equals(new int64.fromInts(0xd048d115, 0x9d159c00),
- new int64.fromInts(0x92341234, 0x45674567) << 10);
- Expect.equals(new int64.fromInts(0xffe48d04, 0x8d1159d1),
- new int64.fromInts(0x92341234, 0x45674567) >> 10);
- Expect.equals(new int64.fromInt(67108863),
- new int64.fromInts(0xFFFFFFF, 0xFFFFFFFF) >> 34);
- Expect.equals(new int64.fromInts(0x248d04, 0x8d1159d1),
- new int64.fromInts(0x92341234, 0x45674567).shiftRightUnsigned(10));
-
- for (int n = 0; n <= 66; n++) {
- Expect.equals(new int64.fromInt(-1), new int64.fromInt(-1) >> n);
- }
-
- Expect.equals(new int64.fromInt(-32), new int64.fromInt(-1) << 5);
- Expect.equals(new int64.fromInt(-1), new int64.fromInt(-1) << 0);
- Expect.equals(-new int64.fromInts(0x40000000, 0x00000000),
- (new int64.fromInt(1) << 63) >> 1);
- Expect.equals(new int64.fromInt(0), (new int64.fromInt(-1) << 32) << 32);
- Expect.equals(int64.MIN_VALUE, int64.MIN_VALUE << 0);
- Expect.equals(new int64.fromInt(0), int64.MIN_VALUE << 1);
- Expect.equals(new int64.fromInts(0xfffffffc, 0x00000000),
- (-new int64.fromInts(8, 0)) >> 1);
- Expect.equals(new int64.fromInts(0x7ffffffc, 0x0),
- (-new int64.fromInts(8, 0)).shiftRightUnsigned(1));
-
- Expect.equals(new int64.fromInts(0x00723456, 0x789abcde),
- new int64.fromInts(0x72345678, 0x9abcdef0) >> 8);
- Expect.equals(new int64.fromInts(0x00007234, 0x56789abc),
- new int64.fromInts(0x72345678, 0x9abcdef0) >> 16);
- Expect.equals(new int64.fromInts(0x00000072, 0x3456789a),
- new int64.fromInts(0x72345678, 0x9abcdef0) >> 24);
- Expect.equals(new int64.fromInts(0x00000007, 0x23456789),
- new int64.fromInts(0x72345678, 0x9abcdef0) >> 28);
- Expect.equals(new int64.fromInts(0x00000000, 0x72345678),
- new int64.fromInts(0x72345678, 0x9abcdef0) >> 32);
- Expect.equals(new int64.fromInts(0x00000000, 0x07234567),
- new int64.fromInts(0x72345678, 0x9abcdef0) >> 36);
- Expect.equals(new int64.fromInts(0x00000000, 0x00723456),
- new int64.fromInts(0x72345678, 0x9abcdef0) >> 40);
- Expect.equals(new int64.fromInts(0x00000000, 0x00072345),
- new int64.fromInts(0x72345678, 0x9abcde00) >> 44);
- Expect.equals(new int64.fromInts(0x00000000, 0x00007234),
- new int64.fromInts(0x72345678, 0x9abcdef0) >> 48);
-
- Expect.equals(new int64.fromInts(0x00723456, 0x789abcde),
- new int64.fromInts(0x72345678, 0x9abcdef0).shiftRightUnsigned(8));
- Expect.equals(new int64.fromInts(0x00007234, 0x56789abc),
- new int64.fromInts(0x72345678, 0x9abcdef0).shiftRightUnsigned(16));
- Expect.equals(new int64.fromInts(0x00000072, 0x3456789a),
- new int64.fromInts(0x72345678, 0x9abcdef0).shiftRightUnsigned(24));
- Expect.equals(new int64.fromInts(0x00000007, 0x23456789),
- new int64.fromInts(0x72345678, 0x9abcdef0).shiftRightUnsigned(28));
- Expect.equals(new int64.fromInts(0x00000000, 0x72345678),
- new int64.fromInts(0x72345678, 0x9abcdef0).shiftRightUnsigned(32));
- Expect.equals(new int64.fromInts(0x00000000, 0x07234567),
- new int64.fromInts(0x72345678, 0x9abcdef0).shiftRightUnsigned(36));
- Expect.equals(new int64.fromInts(0x00000000, 0x00723456),
- new int64.fromInts(0x72345678, 0x9abcdef0).shiftRightUnsigned(40));
- Expect.equals(new int64.fromInts(0x00000000, 0x00072345),
- new int64.fromInts(0x72345678, 0x9abcde00).shiftRightUnsigned(44));
- Expect.equals(new int64.fromInts(0x00000000, 0x00007234),
- new int64.fromInts(0x72345678, 0x9abcdef0).shiftRightUnsigned(48));
-
- Expect.equals(new int64.fromInts(0xff923456, 0x789abcde),
- new int64.fromInts(0x92345678, 0x9abcdef0) >> 8);
- Expect.equals(new int64.fromInts(0xffff9234, 0x56789abc),
- new int64.fromInts(0x92345678, 0x9abcdef0) >> 16);
-
- Expect.equals(new int64.fromInts(0xffffff92, 0x3456789a),
- new int64.fromInts(0x92345678, 0x9abcdef0) >> 24);
- Expect.equals(new int64.fromInts(0xfffffff9, 0x23456789),
- new int64.fromInts(0x92345678, 0x9abcdef0) >> 28);
- Expect.equals(new int64.fromInts(0xffffffff, 0x92345678),
- new int64.fromInts(0x92345678, 0x9abcdef0) >> 32);
- Expect.equals(new int64.fromInts(0xffffffff, 0xf9234567),
- new int64.fromInts(0x92345678, 0x9abcdef0) >> 36);
- Expect.equals(new int64.fromInts(0xffffffff, 0xff923456),
- new int64.fromInts(0x92345678, 0x9abcdef0) >> 40);
- Expect.equals(new int64.fromInts(0xffffffff, 0xfff92345),
- new int64.fromInts(0x92345678, 0x9abcdef0) >> 44);
- Expect.equals(new int64.fromInts(0xffffffff, 0xffff9234),
- new int64.fromInts(0x92345678, 0x9abcdef0) >> 48);
-
- Expect.equals(new int64.fromInts(0x00923456, 0x789abcde),
- new int64.fromInts(0x92345678, 0x9abcdef0).shiftRightUnsigned(8));
- Expect.equals(new int64.fromInts(0x00009234, 0x56789abc),
- new int64.fromInts(0x92345678, 0x9abcdef0).shiftRightUnsigned(16));
- Expect.equals(new int64.fromInts(0x00000092, 0x3456789a),
- new int64.fromInts(0x92345678, 0x9abcdef0).shiftRightUnsigned(24));
- Expect.equals(new int64.fromInts(0x00000009, 0x23456789),
- new int64.fromInts(0x92345678, 0x9abcdef0).shiftRightUnsigned(28));
- Expect.equals(new int64.fromInts(0x00000000, 0x92345678),
- new int64.fromInts(0x92345678, 0x9abcdef0).shiftRightUnsigned(32));
- Expect.equals(new int64.fromInts(0x00000000, 0x09234567),
- new int64.fromInts(0x92345678, 0x9abcdef0).shiftRightUnsigned(36));
- Expect.equals(new int64.fromInts(0x00000000, 0x00923456),
- new int64.fromInts(0x92345678, 0x9abcdef0).shiftRightUnsigned(40));
- Expect.equals(new int64.fromInts(0x00000000, 0x00092345),
- new int64.fromInts(0x92345678, 0x9abcdef0).shiftRightUnsigned(44));
- Expect.equals(new int64.fromInts(0x00000000, 0x00009234),
- new int64.fromInts(0x92345678, 0x9abcdef0).shiftRightUnsigned(48));
-
- try {
- new int64.fromInt(17) >> -1;
- Expect.fail("x >> -1 should throw ArgumentError");
- } on ArgumentError catch (e) {
- }
-
- try {
- new int64.fromInt(17) << -1;
- Expect.fail("x >> -1 should throw ArgumentError");
- } on ArgumentError catch (e) {
- }
-
- try {
- new int64.fromInt(17).shiftRightUnsigned(-1);
- Expect.fail("x >> -1 should throw ArgumentError");
- } on ArgumentError catch (e) {
- }
-
-}
-
-void testToHexString() {
- int64 deadbeef12341234 = new int64.fromInts(0xDEADBEEF, 0x12341234);
- Expect.equals("0", int64.ZERO.toHexString());
- Expect.equals("DEADBEEF12341234", deadbeef12341234.toHexString());
-}
-
-void testToString() {
- Expect.equals("0", new int64.fromInt(0).toString());
- Expect.equals("1", new int64.fromInt(1).toString());
- Expect.equals("-1", new int64.fromInt(-1).toString());
- Expect.equals("-10", new int64.fromInt(-10).toString());
- Expect.equals("-9223372036854775808", int64.MIN_VALUE.toString());
- Expect.equals("9223372036854775807", int64.MAX_VALUE.toString());
-
- int top = 922337201;
- int bottom = 967490662;
- int64 fullnum = (new int64.fromInt(1000000000) * new int64.fromInt(top)) +
- new int64.fromInt(bottom);
-
- Expect.equals("922337201967490662", fullnum.toString());
- Expect.equals("-922337201967490662", (-fullnum).toString());
-
- Expect.equals("17678A7DEF01234",
- new int64.fromInts(0x17678A7, 0xDEF01234).toHexString());
-
- Expect.equals("123456789", new int64.fromInt(123456789).toString());
- Expect.equals("75BCD15", new int64.fromInt(123456789).toHexString());
- Expect.equals("223101104124", new int64.fromInt(123456789).toRadixString(5));
-
- Expect.equals(
- "-1000000000000000000000000000000000000000000000000000000000000000",
- int64.MIN_VALUE.toRadixString(2));
- Expect.equals("-2021110011022210012102010021220101220222",
- int64.MIN_VALUE.toRadixString(3));
- Expect.equals("-20000000000000000000000000000000",
- int64.MIN_VALUE.toRadixString(4));
- Expect.equals("-1104332401304422434310311213",
- int64.MIN_VALUE.toRadixString(5));
- Expect.equals("-1540241003031030222122212", int64.MIN_VALUE.toRadixString(6));
- Expect.equals("-22341010611245052052301", int64.MIN_VALUE.toRadixString(7));
- Expect.equals("-1000000000000000000000", int64.MIN_VALUE.toRadixString(8));
- Expect.equals("-67404283172107811828", int64.MIN_VALUE.toRadixString(9));
- Expect.equals("-9223372036854775808", int64.MIN_VALUE.toRadixString(10));
- Expect.equals("-1728002635214590698", int64.MIN_VALUE.toRadixString(11));
- Expect.equals("-41A792678515120368", int64.MIN_VALUE.toRadixString(12));
- Expect.equals("-10B269549075433C38", int64.MIN_VALUE.toRadixString(13));
- Expect.equals("-4340724C6C71DC7A8", int64.MIN_VALUE.toRadixString(14));
- Expect.equals("-160E2AD3246366808", int64.MIN_VALUE.toRadixString(15));
- Expect.equals("-8000000000000000", int64.MIN_VALUE.toRadixString(16));
-
- Expect.equals(
- "111111111111111111111111111111111111111111111111111111111111111",
- int64.MAX_VALUE.toRadixString(2));
- Expect.equals("2021110011022210012102010021220101220221",
- int64.MAX_VALUE.toRadixString(3));
- Expect.equals("13333333333333333333333333333333",
- int64.MAX_VALUE.toRadixString(4));
- Expect.equals("1104332401304422434310311212",
- int64.MAX_VALUE.toRadixString(5));
- Expect.equals("1540241003031030222122211", int64.MAX_VALUE.toRadixString(6));
- Expect.equals("22341010611245052052300", int64.MAX_VALUE.toRadixString(7));
- Expect.equals("777777777777777777777", int64.MAX_VALUE.toRadixString(8));
- Expect.equals("67404283172107811827", int64.MAX_VALUE.toRadixString(9));
- Expect.equals("9223372036854775807", int64.MAX_VALUE.toRadixString(10));
- Expect.equals("1728002635214590697", int64.MAX_VALUE.toRadixString(11));
- Expect.equals("41A792678515120367", int64.MAX_VALUE.toRadixString(12));
- Expect.equals("10B269549075433C37", int64.MAX_VALUE.toRadixString(13));
- Expect.equals("4340724C6C71DC7A7", int64.MAX_VALUE.toRadixString(14));
- Expect.equals("160E2AD3246366807", int64.MAX_VALUE.toRadixString(15));
- Expect.equals("7FFFFFFFFFFFFFFF", int64.MAX_VALUE.toRadixString(16));
+ test("toRadixString", () {
+ expect(new int64.fromInt(123456789).toRadixString(5), "223101104124");
+ expect(int64.MIN_VALUE.toRadixString(2),
+ "-1000000000000000000000000000000000000000000000000000000000000000");
+ expect(int64.MIN_VALUE.toRadixString(3),
+ "-2021110011022210012102010021220101220222");
+ expect(int64.MIN_VALUE.toRadixString(4),
+ "-20000000000000000000000000000000");
+ expect(int64.MIN_VALUE.toRadixString(5), "-1104332401304422434310311213");
+ expect(int64.MIN_VALUE.toRadixString(6), "-1540241003031030222122212");
+ expect(int64.MIN_VALUE.toRadixString(7), "-22341010611245052052301");
+ expect(int64.MIN_VALUE.toRadixString(8), "-1000000000000000000000");
+ expect(int64.MIN_VALUE.toRadixString(9), "-67404283172107811828");
+ expect(int64.MIN_VALUE.toRadixString(10), "-9223372036854775808");
+ expect(int64.MIN_VALUE.toRadixString(11), "-1728002635214590698");
+ expect(int64.MIN_VALUE.toRadixString(12), "-41A792678515120368");
+ expect(int64.MIN_VALUE.toRadixString(13), "-10B269549075433C38");
+ expect(int64.MIN_VALUE.toRadixString(14), "-4340724C6C71DC7A8");
+ expect(int64.MIN_VALUE.toRadixString(15), "-160E2AD3246366808");
+ expect(int64.MIN_VALUE.toRadixString(16), "-8000000000000000");
+ expect(int64.MAX_VALUE.toRadixString(2),
+ "111111111111111111111111111111111111111111111111111111111111111");
+ expect(int64.MAX_VALUE.toRadixString(3),
+ "2021110011022210012102010021220101220221");
+ expect(int64.MAX_VALUE.toRadixString(4),
+ "13333333333333333333333333333333");
+ expect(int64.MAX_VALUE.toRadixString(5), "1104332401304422434310311212");
+ expect(int64.MAX_VALUE.toRadixString(6), "1540241003031030222122211");
+ expect(int64.MAX_VALUE.toRadixString(7), "22341010611245052052300");
+ expect(int64.MAX_VALUE.toRadixString(8), "777777777777777777777");
+ expect(int64.MAX_VALUE.toRadixString(9), "67404283172107811827");
+ expect(int64.MAX_VALUE.toRadixString(10), "9223372036854775807");
+ expect(int64.MAX_VALUE.toRadixString(11), "1728002635214590697");
+ expect(int64.MAX_VALUE.toRadixString(12), "41A792678515120367");
+ expect(int64.MAX_VALUE.toRadixString(13), "10B269549075433C37");
+ expect(int64.MAX_VALUE.toRadixString(14), "4340724C6C71DC7A7");
+ expect(int64.MAX_VALUE.toRadixString(15), "160E2AD3246366807");
+ expect(int64.MAX_VALUE.toRadixString(16), "7FFFFFFFFFFFFFFF");
+ });
+ });
}
diff --git a/pkg/fixnum/test/int_64_vm_test.dart b/pkg/fixnum/test/int_64_vm_test.dart
deleted file mode 100644
index b0a40a7..0000000
--- a/pkg/fixnum/test/int_64_vm_test.dart
+++ /dev/null
@@ -1,331 +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.
-
-// A test to compare the results of the fixnum library with the Dart VM
-
-library int64vmtest;
-
-import "package:expect/expect.dart";
-import 'dart:math' as math;
-
-part 'package:fixnum/src/int32.dart';
-part 'package:fixnum/src/int64.dart';
-part 'package:fixnum/src/intx.dart';
-
-final random = new math.Random();
-
-void main() {
- int64VMTest test = new int64VMTest();
- test.doTestBinary(new BinaryOp("&", (a, b) => a & b));
- test.doTestBinary(new BinaryOp("|", (a, b) => a | b));
- test.doTestBinary(new BinaryOp("^", (a, b) => a ^ b));
- test.doTestBinary(new BinaryOp("+", (a, b) => a + b));
- test.doTestBinary(new BinaryOp("-", (a, b) => a - b));
- test.doTestBinary(new BinaryOp("*", (a, b) => a * b));
- test.doTestUnary(new UnaryOp("-", (a) => -a));
- test.doTestUnary(new UnaryOp("~", (a) => ~a));
- test.doTestShift(new ShiftOp("<<", (a, n) => a << (n & 63)));
- test.doTestShift(new ShiftOp(">>", (a, n) => a >> (n & 63)));
- test.doTestBoolean(new BooleanOp("compareTo", (a, b) => a.compareTo(b)));
- test.doTestBoolean(new BooleanOp("==", (a, b) => a == b));
- test.doTestBoolean(new BooleanOp("!=", (a, b) => a != b));
- test.doTestBoolean(new BooleanOp("<", (a, b) => a < b));
- test.doTestBoolean(new BooleanOp("<=", (a, b) => a <= b));
- test.doTestBoolean(new BooleanOp(">", (a, b) => a > b));
- test.doTestBoolean(new BooleanOp(">=", (a, b) => a >= b));
- test.doTestBinary(new BinaryOp("%", (a, b) => a % b));
- test.doTestBinary(new BinaryOp("~/", (a, b) => a ~/ b));
- test.doTestBinary(new BinaryOp("remainder", (a, b) => a.remainder(b)));
-}
-
-const int DISCARD = 0;
-
-int64 _randomInt64() {
- int i = 0;
- for (int b = 0; b < 64; b++) {
- double rand = random.nextDouble();
- for (int j = 0; j < DISCARD; j++) {
- rand = random.nextDouble();
- }
- i = (i << 1) | ((rand > 0.5) ? 1 : 0);
- }
- return new int64.fromInt(i);
-}
-
-int _randomInt(int n) {
- double rand = random.nextDouble();
- for (int i = 0; i < DISCARD; i++) {
- rand = random.nextDouble();
- }
- return (rand * n).floor();
-}
-
-class Op {
- String name;
- Function op;
-
- Op(String this.name, Function this.op);
-
- // Truncate x to a value in the range [-2^63, 2^63 - 1]
- int trunc64(int x) {
- int trunc = x & 0xffffffffffffffff;
- if ((trunc & 0x8000000000000000) != 0) {
- trunc -= 18446744073709551616; // 2^64
- }
- return trunc;
- }
-}
-
-class UnaryOp extends Op {
- UnaryOp(String name, Function op) : super(name, op);
- int ref(int val) => trunc64(op(val));
- int64 test(int64 val) => op(val);
-}
-
-class BinaryOp extends Op {
- BinaryOp(String name, Function op) : super(name, op);
- int ref(int val0, int val1) => trunc64(op(val0, val1));
- int64 test(int64 val0, int64 val1) => op(val0, val1);
-}
-
-class BooleanOp extends Op {
- BooleanOp(String name, Function op) : super(name, op);
- bool ref(int val0, int val1) => op(val0, val1);
- bool test(int64 val0, int64 val1) => op(val0, val1);
-}
-
-class ShiftOp extends Op {
- ShiftOp(String name, Function op) : super(name, op);
- int ref(int val0, int shift) => trunc64(op(val0, shift));
- int64 test(int64 val0, int shift) => op(val0, shift);
-}
-
-class int64VMTest {
- static const int BASE_VALUES = 32;
- static const int RANDOM_TESTS = 32;
- List<int64> TEST_VALUES;
-
- int64VMTest() {
- Set<int64> testSet = new Set<int64>();
- for (int i = 0; i < BASE_VALUES; i++) {
- testSet.add(new int64.fromInt(i));
- testSet.add(new int64.fromInt(-i));
-
- testSet.add(int64.MIN_VALUE + i);
- testSet.add(int64.MAX_VALUE - i);
-
- testSet.add(new int64.fromInt(i << int64._BITS ~/ 2));
- testSet.add(new int64.fromInt(i << int64._BITS));
- testSet.add(new int64.fromInt(i << (3 * int64._BITS) ~/ 2));
- testSet.add(new int64.fromInt(i << 2 * int64._BITS));
- testSet.add(new int64.fromInt(i << (5 * int64._BITS) ~/ 2));
- }
-
- int64 one = new int64.fromInt(1);
- int64 three = new int64.fromInt(3);
- int64 ones = int64.parseHex("1111111111111111");
- int64 tens = int64.parseHex("1010101010101010");
- int64 oh_ones = int64.parseHex("0101010101010101");
- int64 digits = int64.parseHex("123456789ABCDEFF");
- for (int i = 0; i < 16; i++) {
- testSet.add(ones * i);
- testSet.add(~(ones * i));
- testSet.add(-(ones * i));
- testSet.add(tens * i);
- testSet.add(~(tens * i));
- testSet.add(-(tens * i));
- testSet.add(oh_ones * i);
- testSet.add(~(oh_ones * i));
- testSet.add(-(oh_ones * i));
- testSet.add(digits * i);
- testSet.add(~(digits * i));
- testSet.add(-(digits * i));
- }
-
- for (int i = 0; i < 64; i += 4) {
- testSet.add(one << i);
- testSet.add(~(one << i));
- testSet.add(digits >> i);
- testSet.add(-(digits >> i));
-
- // Powers of two and nearby numbers
- testSet.add(one << i);
- for (int j = 1; j <= 16; j++) {
- testSet.add((one << i) + j);
- testSet.add(-((one << i) + j));
- testSet.add(~((one << i) + j));
- testSet.add((one << i) - j);
- testSet.add(-((one << i) - j));
- testSet.add(~((one << i) - j));
- testSet.add((three << i) + j);
- testSet.add(-((three << i) + j));
- testSet.add(~((three << i) + j));
- testSet.add((three << i) - j);
- testSet.add(-((three << i) - j));
- testSet.add(~((three << i) - j));
- }
- }
-
- for (int a = 0; a < 19; a++) {
- // Math.pow(10, a)
- int pow = 1;
- for (int j = 0; j < a; j++) {
- pow *= 10;
- }
- testSet.add(new int64.fromInt(pow));
- }
-
- TEST_VALUES = new List<int64>(testSet.length);
- int index = 0;
- for (int64 val in testSet) {
- TEST_VALUES[index++] = val;
- }
-
- print("VALUES.length = $index");
- }
-
- void _doTestUnary(UnaryOp op, int64 val) {
- int ref = op.ref(val.toInt());
- int64 result64 = op.test(val);
- int result = result64.toInt();
- if (ref != result) {
- Expect.fail("${op.name}: val = $val");
- }
- }
-
- void doTestUnary(UnaryOp op) {
- print("Testing operator ${op.name}");
- for (int i = 0; i < TEST_VALUES.length; i++) {
- _doTestUnary(op, TEST_VALUES[i]);
- }
- for (int i = 0; i < RANDOM_TESTS; i++) {
- int64 randomLong = _randomInt64();
- _doTestUnary(op, randomLong);
- }
- }
-
- void _doTestBinary(BinaryOp op, int64 val0, int64 val1) {
- // print("Test val0 = $val0, val1 = $val1");
- var refException = null;
- int ref = -1;
- try {
- ref = op.ref(val0.toInt(), val1.toInt());
- } on Exception catch (e) {
- refException = e;
- }
- var testException = null;
- int result = -2;
- int64 result64;
- try {
- int64 val0_save = new int64._copy(val0);
- int64 val1_save = new int64._copy(val1);
- result64 = op.test(val0, val1);
- result = result64.toInt();
- if (val0 != val0_save) {
- print(
- "Test altered first argument val0 = $val0, val0_save = $val0_save");
- }
- if (val1 != val1_save) {
- print("Test altered second argument");
- }
- } on Exception catch (e) {
- testException = e;
- }
- if (testException is IntegerDivisionByZeroException &&
- refException is IntegerDivisionByZeroException) {
- } else if (testException != null || refException != null) {
- Expect.fail("${op.name}: val0 = $val0, val1 = $val1, "
- "testException = $testException, refException = $refException");
- return;
- } else if (ref != result) {
- if ("%" == op.name && ref < 0) {
- // print("Dart VM bug: ${op.name}: val0 = $val0, val1 = $val1, "
- // "ref = $ref, result64 = $result64, result = $result");
- } else {
- Expect.fail("${op.name}: val0 = $val0, val1 = $val1, "
- "ref = $ref, result64 = $result64, result = $result");
- }
- }
- }
-
- void doTestBinary(BinaryOp op) {
- print("Testing operator ${op.name}");
- for (int i = 0; i < TEST_VALUES.length; i++) {
- int64 randomLong = _randomInt64();
- _doTestBinary(op, TEST_VALUES[i], randomLong);
- _doTestBinary(op, randomLong, TEST_VALUES[i]);
- for (int j = 0; j < TEST_VALUES.length; j++) {
- _doTestBinary(op, TEST_VALUES[i], TEST_VALUES[j]);
- }
- }
- for (int i = 0; i < RANDOM_TESTS; i++) {
- int64 longVal0 = _randomInt64();
- int64 longVal1 = _randomInt64();
- if (_randomInt(20) == 0) {
- if (_randomInt(2) == 0) {
- longVal1 = longVal0;
- } else {
- longVal1 = -longVal0;
- }
- }
- _doTestBinary(op, longVal0, longVal1);
- }
- }
-
- void _doTestBoolean(BooleanOp op, int64 val0, int64 val1) {
- bool ref = op.ref(val0.toInt(), val1.toInt());
- bool result = op.test(val0, val1);
- if (ref != result) {
- Expect.fail("${op.name}: val0 = $val0, val1 = $val1");
- }
- }
-
- void doTestBoolean(BooleanOp op) {
- print("Testing operator ${op.name}");
- for (int i = 0; i < TEST_VALUES.length; i++) {
- int64 randomLong = _randomInt64();
- _doTestBoolean(op, TEST_VALUES[i], randomLong);
- _doTestBoolean(op, randomLong, TEST_VALUES[i]);
- for (int j = 0; j < TEST_VALUES.length; j++) {
- _doTestBoolean(op, TEST_VALUES[i], TEST_VALUES[j]);
- }
- }
- for (int i = 0; i < RANDOM_TESTS; i++) {
- int64 longVal0 = _randomInt64();
- int64 longVal1 = _randomInt64();
- if (_randomInt(20) == 0) {
- if (_randomInt(2) == 0) {
- longVal1 = longVal0;
- } else {
- longVal1 = -longVal0;
- }
- }
- _doTestBoolean(op, longVal0, longVal1);
- }
- }
-
- void _doTestShift(ShiftOp op, int64 val, int shift) {
- int ref = op.ref(val.toInt(), shift);
- int64 result64 = op.test(val, shift);
- int result = result64.toInt();
- if (ref != result) {
- Expect.fail("${op.name}: val = $val, shift = $shift");
- }
- }
-
- void doTestShift(ShiftOp op) {
- print("Testing operator ${op.name}");
- for (int i = 0; i < TEST_VALUES.length; i++) {
- for (int shift = -64; shift <= 64; shift++) {
- _doTestShift(op, TEST_VALUES[i], shift);
- }
- }
- for (int i = 0; i < RANDOM_TESTS; i++) {
- int64 randomLong = _randomInt64();
- for (int shift = -64; shift <= 64; shift++) {
- _doTestShift(op, randomLong, shift);
- }
- }
- }
-}
diff --git a/pkg/path/lib/path.dart b/pkg/path/lib/path.dart
index 25ce0e6..1d83c00 100644
--- a/pkg/path/lib/path.dart
+++ b/pkg/path/lib/path.dart
@@ -109,7 +109,7 @@
/// Gets the part of [path] before the last separator.
///
/// path.dirname('path/to/foo.dart'); // -> 'path/to'
-/// path.dirname('path/to'); // -> 'to'
+/// path.dirname('path/to'); // -> 'path'
///
/// Trailing separators are ignored.
///
diff --git a/pkg/pkg.status b/pkg/pkg.status
index 0a89418..a3edba3 100644
--- a/pkg/pkg.status
+++ b/pkg/pkg.status
@@ -2,13 +2,6 @@
# 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.
-# Run this test manually to verify that the fixnum library produces
-# the same results as native ints on a set of directed and random inputs.
-# Skip it when running automated tests because it times out. This
-# test only makes sense on runtimes that support 64-bit integer
-# arithmetic natively, i.e., the VM.
-fixnum/test/int_64_vm_test: Skip
-
# Don't run any test-like files that show up in packages directories. It
# shouldn't be necessary to run "pub install" in these packages, but if you do
# it shouldn't break the tests.
diff --git a/pkg/unittest/lib/compact_vm_config.dart b/pkg/unittest/lib/compact_vm_config.dart
index b2bbc59..97c120a 100644
--- a/pkg/unittest/lib/compact_vm_config.dart
+++ b/pkg/unittest/lib/compact_vm_config.dart
@@ -12,8 +12,10 @@
import 'dart:async';
import 'dart:io';
+import 'dart:isolate';
import 'unittest.dart';
+import 'src/utils.dart';
import 'vm_config.dart';
const String _GREEN = '\u001b[32m';
@@ -23,11 +25,16 @@
const int MAX_LINE = 80;
class CompactVMConfiguration extends VMConfiguration {
+ // The VM won't shut down if a receive port is open. Use this to make sure
+ // we correctly wait for asynchronous tests.
+ ReceivePort _receivePort;
+
DateTime _start;
int _pass = 0;
int _fail = 0;
void onInit() {
+ _receivePort = new ReceivePort();
// Override and don't call the superclass onInit() to avoid printing the
// "unittest-suite-..." boilerplate.
}
@@ -51,11 +58,11 @@
_progressLine(_start, _pass, _fail, test.description);
print('');
if (test.message != '') {
- print(_indent(test.message));
+ print(indent(test.message));
}
- if (test.stackTrace != null && test.stackTrace != '') {
- print(_indent(test.stackTrace));
+ if (test.stackTrace != null) {
+ print(indent(test.stackTrace.toString()));
}
}
}
@@ -64,14 +71,11 @@
// Override and don't call the superclass onDone() to avoid printing the
// "unittest-suite-..." boilerplate.
Future.wait([stdout.close(), stderr.close()]).then((_) {
+ _receivePort.close();
exit(success ? 0 : 1);
});
}
- String _indent(String str) {
- return str.split("\n").map((line) => " $line").join("\n");
- }
-
void onSummary(int passed, int failed, int errors, List<TestCase> results,
String uncaughtError) {
var success = false;
diff --git a/pkg/unittest/lib/html_config.dart b/pkg/unittest/lib/html_config.dart
index 303afb6..86123cf 100644
--- a/pkg/unittest/lib/html_config.dart
+++ b/pkg/unittest/lib/html_config.dart
@@ -80,7 +80,9 @@
</tr>''';
if (test_.stackTrace != null) {
- html = '$html<tr><td></td><td colspan="2"><pre>${_htmlEscape(test_.stackTrace)}</pre></td></tr>';
+ html = '$html<tr><td></td><td colspan="2"><pre>' +
+ _htmlEscape(test_.stackTrace.toString()) +
+ '</pre></td></tr>';
}
return html;
diff --git a/pkg/unittest/lib/html_enhanced_config.dart b/pkg/unittest/lib/html_enhanced_config.dart
index 2fd2fa3..5cc5fe5 100644
--- a/pkg/unittest/lib/html_enhanced_config.dart
+++ b/pkg/unittest/lib/html_enhanced_config.dart
@@ -270,7 +270,8 @@
'${test_.description}. ${_htmlEscape(test_.message)}');
if (test_.stackTrace != null) {
- addRowElement('', '', '<pre>${_htmlEscape(test_.stackTrace)}</pre>');
+ addRowElement('', '',
+ '<pre>${_htmlEscape(test_.stackTrace.toString())}</pre>');
}
}
diff --git a/pkg/unittest/lib/interactive_html_config.dart b/pkg/unittest/lib/interactive_html_config.dart
index 9d43d09..b962e1e 100644
--- a/pkg/unittest/lib/interactive_html_config.dart
+++ b/pkg/unittest/lib/interactive_html_config.dart
@@ -20,6 +20,9 @@
import 'dart:html';
import 'dart:async';
import 'dart:math';
+
+import 'package:stack_trace/stack_trace.dart';
+
import 'unittest.dart';
/** The messages exchanged between parent and child. */
@@ -152,17 +155,25 @@
}
/**
- * Get the elapsed time for the test, anbd post the test result
- * back to the parent window. If the test failed due to an exception
- * the stack is posted back too (before the test result).
+ * Get the elapsed time for the test, and post the test result back to the
+ * parent window. If the test failed due to an exception the stack is posted
+ * back too (before the test result).
*/
void onTestResult(TestCase testCase) {
super.onTestResult(testCase);
DateTime end = new DateTime.now();
int elapsed = end.difference(_testStarts[testCase.id]).inMilliseconds;
if (testCase.stackTrace != null) {
+ var message = json.stringify(testCase.stackTrace.frames.map((frame) {
+ return <String>{
+ "uri": frame.uri.toString(),
+ "line": frame.line,
+ "column": frame.column,
+ "member": frame.member
+ };
+ }).toList());
_parentWindow.postMessage(
- _Message.text(_Message.STACK, elapsed, testCase.stackTrace), '*');
+ _Message.text(_Message.STACK, elapsed, message), '*');
}
_parentWindow.postMessage(
_Message.text(testCase.result, elapsed, testCase.message), '*');
@@ -185,7 +196,7 @@
/** The stack that was posted back from the child, if any. */
- String _stack;
+ Trace _stack;
int _testTime;
/**
@@ -233,7 +244,13 @@
if (msg.messageType == _Message.LOG) {
logMessage(e.data);
} else if (msg.messageType == _Message.STACK) {
- _stack = msg.body;
+ _stack = new Trace(json.parse(msg.body).map((frame) {
+ return new Frame(
+ Uri.parse(frame['uri']),
+ frame['line'],
+ frame['column'],
+ frame['member']);
+ }));
} else {
_testTime = msg.elapsed;
logMessage(_Message.text(_Message.LOG, _testTime, 'Complete'));
diff --git a/pkg/unittest/lib/src/config.dart b/pkg/unittest/lib/src/config.dart
index 490ef80..a08ee16 100644
--- a/pkg/unittest/lib/src/config.dart
+++ b/pkg/unittest/lib/src/config.dart
@@ -55,8 +55,8 @@
// If stopTestOnExpectFailure is false, we need to capture failures, which
// we do with this List.
- List _testLogBuffer = new List();
-
+ final _testLogBuffer = <Pair<String, Trace>>[];
+
/**
* The constructor sets up a failure handler for [expect] that redirects
* [expect] failures to [onExpectFailure].
@@ -99,24 +99,25 @@
if (!stopTestOnExpectFailure && _testLogBuffer.length > 0) {
// Write the message/stack pairs up to the last pairs.
var reason = new StringBuffer();
- for (var i = 0; i < _testLogBuffer.length - 2; i += 2) {
- reason.write(_testLogBuffer[i]);
+ for (var reasonAndTrace in
+ _testLogBuffer.take(_testLogBuffer.length - 1)) {
+ reason.write(reasonAndTrace.first);
reason.write('\n');
- reason.write(_formatStack(_testLogBuffer[i+1]));
+ reason.write(reasonAndTrace.last);
reason.write('\n');
}
+ var lastReasonAndTrace = _testLogBuffer.last;
// Write the last message.
- reason.write(_testLogBuffer[_testLogBuffer.length - 2]);
+ reason.write(lastReasonAndTrace.first);
if (testCase.result == PASS) {
testCase._result = FAIL;
testCase._message = reason.toString();
// Use the last stack as the overall failure stack.
- testCase._stackTrace =
- _formatStack(_testLogBuffer[_testLogBuffer.length - 1]);
+ testCase._stackTrace = lastReasonAndTrace.last;
} else {
// Add the last stack to the message; we have a further stack
// caused by some other failure.
- reason.write(_formatStack(_testLogBuffer[_testLogBuffer.length - 1]));
+ reason.write(lastReasonAndTrace.last);
reason.write('\n');
// Add the existing reason to the end of the expect log to
// create the final message.
@@ -150,11 +151,11 @@
if (stopTestOnExpectFailure) {
throw new TestFailure(reason);
} else {
- _testLogBuffer.add(reason);
try {
throw '';
} catch (_, stack) {
- _testLogBuffer.add(stack);
+ _testLogBuffer.add(
+ new Pair<String, Trace>(reason, new Trace.from(stack)));
}
}
}
@@ -170,12 +171,12 @@
result.write("\n");
if (testCase.message != '') {
- result.write(_indent(testCase.message));
+ result.write(indent(testCase.message));
result.write("\n");
}
- if (testCase.stackTrace != null && testCase.stackTrace != '') {
- result.write(_indent(testCase.stackTrace));
+ if (testCase.stackTrace != null) {
+ result.write(indent(testCase.stackTrace.toString()));
result.write("\n");
}
return result.toString();
@@ -228,17 +229,10 @@
}
}
- String _indent(String str) {
- // TODO(nweiz): Use this simpler code once issue 2980 is fixed.
- // return str.replaceAll(new RegExp("^", multiLine: true), " ");
-
- return str.split("\n").map((line) => " $line").join("\n");
- }
-
/** Handle errors that happen outside the tests. */
// TODO(vsm): figure out how to expose the stack trace here
// Currently e.message works in dartium, but not in dartc.
- void handleExternalError(e, String message, [String stack = '']) =>
+ void handleExternalError(e, String message, [stack]) =>
_reportTestError('$message\nCaught $e', stack);
_postMessage(String message) {
diff --git a/pkg/unittest/lib/src/test_case.dart b/pkg/unittest/lib/src/test_case.dart
index ad5bd6a..e28d21f 100644
--- a/pkg/unittest/lib/src/test_case.dart
+++ b/pkg/unittest/lib/src/test_case.dart
@@ -41,9 +41,9 @@
*/
String get result => _result;
- String _stackTrace;
+ Trace _stackTrace;
/** Stack trace associated with this test, or [null] if it succeeded. */
- String get stackTrace => _stackTrace;
+ Trace get stackTrace => _stackTrace;
/** The group (or groups) under which this test is running. */
final String currentGroup;
@@ -69,7 +69,6 @@
Function _errorHandler(String stage) => (e) {
var stack = getAttachedStackTrace(e);
- stack = (stack == null) ? '' : '$stack';
if (result == null || result == PASS) {
if (e is TestFailure) {
fail("$e", stack);
@@ -122,9 +121,9 @@
// Set the results, notify the config, and return true if this
// is the first time the result is being set.
- void _setResult(String testResult, String messageText, String stack) {
+ void _setResult(String testResult, String messageText, stack) {
_message = messageText;
- _stackTrace = _formatStack(stack);
+ _stackTrace = _getTrace(stack);
if (result == null) {
_result = testResult;
_config.onTestResult(this);
@@ -134,9 +133,7 @@
}
}
- void _complete(String testResult,
- [String messageText = '',
- String stack = '']) {
+ void _complete(String testResult, [String messageText = '', stack]) {
if (runningTime == null) {
// The startTime can be `null` if an error happened during setup. In this
// case we simply report a running time of 0.
@@ -158,8 +155,7 @@
_complete(PASS);
}
- void fail(String messageText, [String stack = '']) {
- assert(stack != null);
+ void fail(String messageText, [stack]) {
if (result != null) {
String newMessage = (result == PASS)
? 'Test failed after initially passing: $messageText'
@@ -171,8 +167,7 @@
}
}
- void error(String messageText, [String stack = '']) {
- assert(stack != null);
+ void error(String messageText, [stack]) {
_complete(ERROR, messageText, stack);
}
diff --git a/pkg/unittest/lib/src/utils.dart b/pkg/unittest/lib/src/utils.dart
index 6442ac4..e10c597 100644
--- a/pkg/unittest/lib/src/utils.dart
+++ b/pkg/unittest/lib/src/utils.dart
@@ -46,3 +46,24 @@
return ch;
}
+/** Indent each line in [str] by two spaces. */
+String indent(String str) =>
+ str.replaceAll(new RegExp("^", multiLine: true), " ");
+
+/** A pair of values. */
+class Pair<E, F> {
+ E first;
+ F last;
+
+ Pair(this.first, this.last);
+
+ String toString() => '($first, $last)';
+
+ bool operator==(other) {
+ if (other is! Pair) return false;
+ return other.first == first && other.last == last;
+ }
+
+ int get hashCode => first.hashCode ^ last.hashCode;
+}
+
diff --git a/pkg/unittest/lib/unittest.dart b/pkg/unittest/lib/unittest.dart
index ec78877..7b134e9 100644
--- a/pkg/unittest/lib/unittest.dart
+++ b/pkg/unittest/lib/unittest.dart
@@ -173,6 +173,9 @@
import 'matcher.dart';
export 'matcher.dart';
+import 'package:stack_trace/stack_trace.dart';
+
+import 'src/utils.dart';
part 'src/config.dart';
part 'src/test_case.dart';
@@ -453,7 +456,7 @@
testCase.error(
'Callback ${id}called ($actualCalls) after test case '
'${testCase.description} has already been marked as '
- '${testCase.result}.', '');
+ '${testCase.result}.');
}
return false;
} else if (maxExpectedCalls >= 0 && actualCalls > maxExpectedCalls) {
@@ -674,7 +677,7 @@
* Utility function that can be used to notify the test framework that an
* error was caught outside of this library.
*/
-void _reportTestError(String msg, String trace) {
+void _reportTestError(String msg, trace) {
if (_currentTestCaseIndex < testCases.length) {
final testCase = testCases[_currentTestCaseIndex];
testCase.error(msg, trace);
@@ -751,7 +754,6 @@
* Registers that an exception was caught for the current test.
*/
void _registerException(TestCase testCase, e, [trace]) {
- trace = trace == null ? '' : trace.toString();
String message = (e is TestFailure) ? e.message : 'Caught $e';
if (testCase.result == null) {
testCase.fail(message, trace);
@@ -864,85 +866,31 @@
typedef dynamic TestFunction();
/**
- * A flag that controls whether we hide unittest details in exception stacks.
+ * A flag that controls whether we hide unittest and core library details in
+ * exception stacks.
+ *
* Useful to disable when debugging unittest or matcher customizations.
*/
bool formatStacks = true;
-// Stack formatting utility. Strips extraneous content from a stack trace.
-// Stack frame lines are parsed with a regexp, which has been tested
-// in Chrome, Firefox and the VM. If a line fails to be parsed it is
-// included in the output to be conservative.
-//
-// The output stack consists of everything after the call to TestCase._run.
-// If we see an 'expect' in the frame we will prune everything above that
-// as well.
-final _frameRegExp = new RegExp(
- r'^\s*' // Skip leading spaces.
- r'(?:' // Group of choices for the prefix.
- r'(?:#\d+\s*)|' // Skip VM's #<frameNumber>.
- r'(?:at )|' // Skip Firefox's 'at '.
- r'(?:))' // Other environments have nothing here.
- r'(.+)' // Extract the function/method.
- r'\s*[@\(]' // Skip space and @ or (.
- r'(' // This group of choices is for the source file.
- r'(?:.+:\/\/.+\/[^:]*)|' // Handle file:// or http:// URLs.
- r'(?:dart:[^:]*)|' // Handle dart:<lib>.
- r'(?:package:[^:]*)' // Handle package:<path>
- r'):([:\d]+)[\)]?$'); // Get the line number and optional column number.
-
-String _formatStack(stack) {
- if (!formatStacks) return "$stack";
- var lines;
- if (stack is StackTrace) {
- lines = stack.toString().split('\n');
- } else if (stack is String) {
- lines = stack.split('\n');
+/** Returns a Trace object from a StackTrace object or a String. */
+Trace _getTrace(stack) {
+ Trace trace;
+ if (stack == null) return null;
+ if (stack is String) {
+ trace = new Trace.parse(stack);
+ } else if (stack is StackTrace) {
+ trace = new Trace.from(stack);
} else {
- return stack.toString();
+ throw new Exception('Invalid stack type ${stack.runtimeType} for $stack.');
}
- // Calculate the max width of first column so we can
- // pad to align the second columns.
- int padding = lines.fold(0, (n, line) {
- var match = _frameRegExp.firstMatch(line);
- if (match == null) return n;
- return max(n, match[1].length + 1);
- });
+ if (!formatStacks) return trace;
- // We remove all entries that have a location in unittest.
- // We strip out anything before _nextBatch too.
- var sb = new StringBuffer();
- for (var i = 0; i < lines.length; i++) {
- var line = lines[i];
- if (line == '') continue;
- var match = _frameRegExp.firstMatch(line);
- if (match == null) {
- sb.write(line);
- sb.write('\n');
- } else {
- var member = match[1];
- var location = match[2];
- var position = match[3];
- if (member.indexOf('TestCase._runTest') >= 0) {
- // Don't include anything after this.
- break;
- } else if (member.indexOf('expect') >= 0) {
- // It looks like this was an expect() failure;
- // drop all the frames up to here.
- sb.clear();
- } else {
- sb.write(member);
- // Pad second column to a fixed position.
- for (var j = 0; j <= padding - member.length; j++) {
- sb.write(' ');
- }
- sb.write(location);
- sb.write(' ');
- sb.write(position);
- sb.write('\n');
- }
- }
- }
- return sb.toString();
+ // Format the stack trace by removing everything above TestCase._runTest,
+ // which is usually going to be irrelevant. Also fold together unittest and
+ // core library calls so only the function the user called is visible.
+ return new Trace(trace.frames.takeWhile((frame) {
+ return frame.package != 'unittest' || frame.member != 'TestCase._runTest';
+ })).terse.foldFrames((frame) => frame.package == 'unittest' || frame.isCore);
}
diff --git a/pkg/unittest/pubspec.yaml b/pkg/unittest/pubspec.yaml
index f9051e3..ecaba6d 100644
--- a/pkg/unittest/pubspec.yaml
+++ b/pkg/unittest/pubspec.yaml
@@ -6,4 +6,4 @@
A library for writing dart unit tests.
dependencies:
meta: any
-
+ stack_trace: any
diff --git a/runtime/include/dart_debugger_api.h b/runtime/include/dart_debugger_api.h
index 76f7940..36249ff 100755
--- a/runtime/include/dart_debugger_api.h
+++ b/runtime/include/dart_debugger_api.h
@@ -553,7 +553,7 @@
/**
* Returns an array containing all static field names and values of
- * the given class \cls.
+ * the given type \target.
*
* Requires there to be a current isolate.
*
@@ -563,7 +563,7 @@
* values at offset 2*n+1. Field values may also be a handle to an
* error object if an error was encountered evaluating the field.
*/
-DART_EXPORT Dart_Handle Dart_GetStaticFields(Dart_Handle cls);
+DART_EXPORT Dart_Handle Dart_GetStaticFields(Dart_Handle target);
/**
diff --git a/runtime/lib/errors_patch.dart b/runtime/lib/errors_patch.dart
index 7016190..f14a504 100644
--- a/runtime/lib/errors_patch.dart
+++ b/runtime/lib/errors_patch.dart
@@ -6,9 +6,7 @@
/* patch */ static String _objectToString(Object object) {
return Object._toString(object);
}
-}
-patch class StackTraceOnThrow {
// TODO(11680): implement stackTrace on Error.
/* patch */ StackTrace get stackTrace => null;
}
@@ -175,7 +173,7 @@
}
}
-class _FiftyThreeBitOverflowError extends Error with StackTraceOnThrow {
+class _FiftyThreeBitOverflowError extends Error {
final Object _value;
_FiftyThreeBitOverflowError(this._value);
diff --git a/runtime/lib/mirrors.cc b/runtime/lib/mirrors.cc
index 1cb1c74..b8b3546 100644
--- a/runtime/lib/mirrors.cc
+++ b/runtime/lib/mirrors.cc
@@ -96,52 +96,6 @@
}
-static void FreeVMReference(Dart_WeakPersistentHandle weak_ref, void* data) {
- Dart_PersistentHandle perm_handle =
- reinterpret_cast<Dart_PersistentHandle>(data);
- Dart_DeletePersistentHandle(perm_handle);
- Dart_DeleteWeakPersistentHandle(weak_ref);
-}
-
-
-static Dart_Handle CreateVMReference(Dart_Handle handle) {
- // Create the VMReference object.
- Dart_Handle cls_name = NewString("VMReference");
- Dart_Handle type = Dart_GetType(MirrorLib(), cls_name, 0, NULL);
- if (Dart_IsError(type)) {
- return type;
- }
- Dart_Handle vm_ref = Dart_New(type, Dart_Null(), 0, NULL);
- if (Dart_IsError(vm_ref)) {
- return vm_ref;
- }
-
- // Allocate a persistent handle.
- Dart_PersistentHandle perm_handle = Dart_NewPersistentHandle(handle);
- ASSERT(perm_handle != NULL);
-
- // Store the persistent handle in the VMReference.
- intptr_t perm_handle_value = reinterpret_cast<intptr_t>(perm_handle);
- Dart_Handle result =
- Dart_SetNativeInstanceField(vm_ref, 0, perm_handle_value);
- if (Dart_IsError(result)) {
- Dart_DeletePersistentHandle(perm_handle);
- return result;
- }
-
- // Create a weak reference. We use the callback to be informed when
- // the VMReference is collected, so we can release the persistent
- // handle.
- void* perm_handle_data = reinterpret_cast<void*>(perm_handle);
- Dart_WeakPersistentHandle weak_ref =
- Dart_NewWeakPersistentHandle(vm_ref, perm_handle_data, FreeVMReference);
- ASSERT(weak_ref != NULL);
-
- // Success.
- return vm_ref;
-}
-
-
// TODO(11742): Remove once there are no more users of the Dart_Handle-based
// VMReferences.
static Dart_Handle CreateMirrorReference(Dart_Handle handle) {
@@ -417,6 +371,7 @@
}
Dart_Handle args[] = {
+ CreateMirrorReference(type_var),
type_var_name,
owner_mirror,
CreateLazyMirror(upper_bound),
@@ -481,6 +436,7 @@
}
Dart_Handle args[] = {
+ CreateMirrorReference(cls),
cls_name,
owner_mirror,
CreateLazyMirror(referent),
@@ -496,10 +452,10 @@
Dart_Handle owner_mirror);
-static Dart_Handle CreateClassMirror(Dart_Handle intf,
- Dart_Handle intf_name,
- Dart_Handle lib,
- Dart_Handle lib_mirror) {
+static Dart_Handle CreateClassMirrorUsingApi(Dart_Handle intf,
+ Dart_Handle intf_name,
+ Dart_Handle lib,
+ Dart_Handle lib_mirror) {
ASSERT(Dart_IsClass(intf));
if (Dart_ClassIsTypedef(intf)) {
// This class is actually a typedef. Represent it specially in
@@ -541,7 +497,6 @@
Dart_Handle args[] = {
CreateMirrorReference(intf),
- CreateVMReference(intf),
Dart_Null(), // "name"
Dart_NewBoolean(Dart_IsClass(intf)),
lib_mirror,
@@ -557,8 +512,8 @@
}
-static Dart_Handle CreateMethodMirror(Dart_Handle func,
- Dart_Handle owner_mirror) {
+static Dart_Handle CreateMethodMirrorUsingApi(Dart_Handle func,
+ Dart_Handle owner_mirror) {
// TODO(11742): Unwrapping is needed until the whole method is converted.
Isolate* isolate = Isolate::Current();
DARTSCOPE(isolate);
@@ -599,7 +554,7 @@
static Dart_Handle CreateVariableMirror(Dart_Handle var,
Dart_Handle var_name,
- Dart_Handle lib_mirror) {
+ Dart_Handle owner_mirror) {
ASSERT(Dart_IsVariable(var));
Dart_Handle cls_name = NewString("_LocalVariableMirrorImpl");
Dart_Handle type = Dart_GetType(MirrorLib(), cls_name, 0, NULL);
@@ -625,8 +580,9 @@
}
Dart_Handle args[] = {
+ CreateMirrorReference(var),
var_name,
- lib_mirror,
+ owner_mirror,
CreateLazyMirror(var_type),
Dart_NewBoolean(is_static),
Dart_NewBoolean(is_final),
@@ -657,7 +613,7 @@
return intf;
}
Dart_Handle intf_mirror =
- CreateClassMirror(intf, intf_name, owner, owner_mirror);
+ CreateClassMirrorUsingApi(intf, intf_name, owner, owner_mirror);
if (Dart_IsError(intf_mirror)) {
return intf_mirror;
}
@@ -701,7 +657,7 @@
continue;
}
- Dart_Handle func_mirror = CreateMethodMirror(func, owner_mirror);
+ Dart_Handle func_mirror = CreateMethodMirrorUsingApi(func, owner_mirror);
if (Dart_IsError(func_mirror)) {
return func_mirror;
}
@@ -745,7 +701,7 @@
continue;
}
- Dart_Handle func_mirror = CreateMethodMirror(func, owner_mirror);
+ Dart_Handle func_mirror = CreateMethodMirrorUsingApi(func, owner_mirror);
if (Dart_IsError(func_mirror)) {
return func_mirror;
}
@@ -833,7 +789,7 @@
}
-static Dart_Handle CreateLibraryMirror(Dart_Handle lib) {
+static Dart_Handle CreateLibraryMirrorUsingApi(Dart_Handle lib) {
Dart_Handle cls_name = NewString("_LocalLibraryMirrorImpl");
Dart_Handle type = Dart_GetType(MirrorLib(), cls_name, 0, NULL);
if (Dart_IsError(type)) {
@@ -849,7 +805,6 @@
}
Dart_Handle args[] = {
CreateMirrorReference(lib),
- CreateVMReference(lib),
Dart_LibraryName(lib),
Dart_LibraryUrl(lib),
member_map,
@@ -888,7 +843,7 @@
if (Dart_IsError(lib)) {
return lib;
}
- Dart_Handle lib_mirror = CreateLibraryMirror(lib);
+ Dart_Handle lib_mirror = CreateLibraryMirrorUsingApi(lib);
if (Dart_IsError(lib_mirror)) {
return lib_mirror;
}
@@ -948,7 +903,6 @@
Dart_Handle object_class = Dart_GetClass(CoreLib(), NewString("Object"));
Dart_Handle args[] = {
- CreateVMReference(Dart_Null()),
CreateLazyMirror(object_class),
Dart_Null(),
};
@@ -990,12 +944,11 @@
// TODO(turnidge): Pass the function owner here. This will require
// us to support functions in CreateLazyMirror.
Dart_Handle func_mirror =
- CreateMethodMirror(func, Dart_Null());
+ CreateMethodMirrorUsingApi(func, Dart_Null());
if (Dart_IsError(func_mirror)) {
return func_mirror;
}
Dart_Handle args[] = {
- CreateVMReference(instance),
CreateLazyMirror(instance_cls),
instance,
func_mirror,
@@ -1009,7 +962,6 @@
return type;
}
Dart_Handle args[] = {
- CreateVMReference(instance),
CreateLazyMirror(instance_cls),
instance,
};
@@ -1018,6 +970,75 @@
}
+static RawInstance* CreateClassMirror(const Class& cls,
+ const Instance& owner_mirror) {
+ Dart_EnterScope();
+ Isolate* isolate = Isolate::Current();
+ Dart_Handle cls_handle = Api::NewHandle(isolate, cls.raw());
+ if (Dart_IsError(cls_handle)) {
+ Dart_PropagateError(cls_handle);
+ }
+ Dart_Handle name_handle = Api::NewHandle(isolate, cls.Name());
+ if (Dart_IsError(name_handle)) {
+ Dart_PropagateError(name_handle);
+ }
+ Dart_Handle lib_handle = Api::NewHandle(isolate, cls.library());
+ if (Dart_IsError(lib_handle)) {
+ Dart_PropagateError(lib_handle);
+ }
+ Dart_Handle lib_mirror = CreateLibraryMirrorUsingApi(lib_handle);
+ if (Dart_IsError(lib_mirror)) {
+ Dart_PropagateError(lib_mirror);
+ }
+ // TODO(11742): At some point the handle calls will be replaced by inlined
+ // functionality.
+ Dart_Handle result = CreateClassMirrorUsingApi(cls_handle,
+ name_handle,
+ lib_handle,
+ lib_mirror);
+ if (Dart_IsError(result)) {
+ Dart_PropagateError(result);
+ }
+ const Instance& retvalue = Api::UnwrapInstanceHandle(isolate, result);
+ Dart_ExitScope();
+ return retvalue.raw();
+}
+
+
+static RawInstance* CreateLibraryMirror(const Library& lib) {
+ Dart_EnterScope();
+ Isolate* isolate = Isolate::Current();
+ Dart_Handle lib_handle = Api::NewHandle(isolate, lib.raw());
+ // TODO(11742): At some point the handle calls will be replaced by inlined
+ // functionality.
+ Dart_Handle result = CreateLibraryMirrorUsingApi(lib_handle);
+ if (Dart_IsError(result)) {
+ Dart_PropagateError(result);
+ }
+ const Instance& retvalue = Api::UnwrapInstanceHandle(isolate, result);
+ Dart_ExitScope();
+ return retvalue.raw();
+}
+
+
+static RawInstance* CreateMethodMirror(const Function& func,
+ const Instance& owner_mirror) {
+ Dart_EnterScope();
+ Isolate* isolate = Isolate::Current();
+ Dart_Handle func_handle = Api::NewHandle(isolate, func.raw());
+ Dart_Handle owner_handle = Api::NewHandle(isolate, owner_mirror.raw());
+ // TODO(11742): At some point the handle calls will be replaced by inlined
+ // functionality.
+ Dart_Handle result = CreateMethodMirrorUsingApi(func_handle, owner_handle);
+ if (Dart_IsError(result)) {
+ Dart_PropagateError(result);
+ }
+ const Instance& retvalue = Api::UnwrapInstanceHandle(isolate, result);
+ Dart_ExitScope();
+ return retvalue.raw();
+}
+
+
void NATIVE_ENTRY_FUNCTION(Mirrors_makeLocalMirrorSystem)(
Dart_NativeArguments args) {
Dart_EnterScope();
@@ -1065,14 +1086,14 @@
if (Dart_IsError(lib_handle)) {
Dart_PropagateError(lib_handle);
}
- Dart_Handle lib_mirror = CreateLibraryMirror(lib_handle);
+ Dart_Handle lib_mirror = CreateLibraryMirrorUsingApi(lib_handle);
if (Dart_IsError(lib_mirror)) {
Dart_PropagateError(lib_mirror);
}
- Dart_Handle result = CreateClassMirror(cls_handle,
- name_handle,
- lib_handle,
- lib_mirror);
+ Dart_Handle result = CreateClassMirrorUsingApi(cls_handle,
+ name_handle,
+ lib_handle,
+ lib_mirror);
if (Dart_IsError(result)) {
Dart_PropagateError(result);
}
@@ -1080,18 +1101,25 @@
Dart_ExitScope();
}
-void NATIVE_ENTRY_FUNCTION(Mirrors_metadata)(Dart_NativeArguments args) {
- Dart_EnterScope();
- Dart_Handle mirror = Dart_GetNativeArgument(args, 0);
- Dart_Handle reflectee = UnwrapMirror(mirror);
- Dart_Handle result = Dart_GetMetadata(reflectee);
- if (Dart_IsError(result)) {
- Dart_PropagateError(result);
+DEFINE_NATIVE_ENTRY(DeclarationMirror_metadata, 1) {
+ const MirrorReference& decl_ref =
+ MirrorReference::CheckedHandle(arguments->NativeArgAt(0));
+ const Object& decl = Object::Handle(decl_ref.referent());
+
+ Class& klass = Class::Handle();
+ if (decl.IsClass()) {
+ klass ^= decl.raw();
+ } else if (decl.IsFunction()) {
+ klass = Function::Cast(decl).origin();
+ } else if (decl.IsField()) {
+ klass = Field::Cast(decl).origin();
+ } else {
+ return Object::empty_array().raw();
}
- ASSERT(Dart_IsList(result));
- Dart_SetReturnValue(args, result);
- Dart_ExitScope();
+
+ const Library& library = Library::Handle(klass.library());
+ return library.GetMetadata(decl);
}
@@ -1791,4 +1819,21 @@
return func.UserVisibleName();
}
+
+DEFINE_NATIVE_ENTRY(MethodMirror_owner, 1) {
+ const MirrorReference& func_ref =
+ MirrorReference::CheckedHandle(arguments->NativeArgAt(0));
+ Function& func = Function::Handle();
+ func ^= func_ref.referent();
+ if (func.IsNonImplicitClosureFunction()) {
+ return CreateMethodMirror(Function::Handle(
+ func.parent_function()), Instance::Handle());
+ }
+ const Class& owner = Class::Handle(func.Owner());
+ if (owner.IsTopLevel()) {
+ return CreateLibraryMirror(Library::Handle(owner.library()));
+ }
+ return CreateClassMirror(owner, Instance::Handle());
+}
+
} // namespace dart
diff --git a/runtime/lib/mirrors_impl.dart b/runtime/lib/mirrors_impl.dart
index 838af66..542e6e8 100644
--- a/runtime/lib/mirrors_impl.dart
+++ b/runtime/lib/mirrors_impl.dart
@@ -70,8 +70,8 @@
return result;
}
-List<InstanceMirror> _metadata(mirror)
- native 'Mirrors_metadata';
+List _metadata(reflectee)
+ native 'DeclarationMirror_metadata';
// This will verify the argument types, unwrap them, and ensure we have a fixed
// array.
@@ -164,24 +164,9 @@
String toString() => "IsolateMirror on '$debugName'";
}
-// A VMReference is used to hold a reference to a VM-internal object,
-// which can include things like libraries, classes, etc.
-class VMReference extends NativeFieldWrapperClass1 {
-}
-
-abstract class _LocalVMObjectMirrorImpl extends _LocalMirrorImpl {
- _LocalVMObjectMirrorImpl(this._reference) {}
-
- // For now, all VMObjects hold a VMReference. We could consider
- // storing the Object reference itself here if the object is a Dart
- // language objects (except for objects of type VMReference, of
- // course).
- VMReference _reference;
-}
-
-abstract class _LocalObjectMirrorImpl extends _LocalVMObjectMirrorImpl
+abstract class _LocalObjectMirrorImpl extends _LocalMirrorImpl
implements ObjectMirror {
- _LocalObjectMirrorImpl(this._reflectee, ref) : super(ref) {}
+ _LocalObjectMirrorImpl(this._reflectee);
final _reflectee; // May be a MirrorReference or an ordinary object.
@@ -275,9 +260,8 @@
// TODO(ahe): This is a hack, see delegate below.
static Function _invokeOnClosure;
- _LocalInstanceMirrorImpl(ref,
- this._type,
- reflectee) : super(reflectee, ref) {}
+ _LocalInstanceMirrorImpl(this._type,
+ reflectee) : super(reflectee) {}
var _type;
ClassMirror get type {
@@ -321,10 +305,9 @@
class _LocalClosureMirrorImpl extends _LocalInstanceMirrorImpl
implements ClosureMirror {
- _LocalClosureMirrorImpl(ref,
- type,
+ _LocalClosureMirrorImpl(type,
reflectee,
- this.function) : super(ref, type, reflectee) {}
+ this.function) : super(type, reflectee) {}
final MethodMirror function;
@@ -404,7 +387,6 @@
class _LocalClassMirrorImpl extends _LocalObjectMirrorImpl
implements ClassMirror {
_LocalClassMirrorImpl(reflectee,
- ref,
String simpleName,
this.isClass,
this._owner,
@@ -418,7 +400,7 @@
this.members = _convertStringToSymbolMap(members),
this.constructors = _convertStringToSymbolMap(constructors),
this.typeVariables = _convertStringToSymbolMap(typeVariables),
- super(reflectee, ref);
+ super(reflectee);
Symbol _simpleName;
Symbol get simpleName {
@@ -582,10 +564,11 @@
}
}
- // get the metadata objects, convert them into InstanceMirrors using
- // reflect() and then make them into a Dart list
- List<InstanceMirror> get metadata => _metadata(this).map(reflect).toList();
-
+ List<InstanceMirror> get metadata {
+ // Get the metadata objects, convert them into InstanceMirrors using
+ // reflect() and then make them into a Dart list.
+ return _metadata(_reflectee).map(reflect).toList(growable:false);
+ }
static _name(reflectee)
native "ClassMirror_name";
@@ -617,12 +600,11 @@
class _LocalFunctionTypeMirrorImpl extends _LocalClassMirrorImpl
implements FunctionTypeMirror {
- _LocalFunctionTypeMirrorImpl(ref,
+ _LocalFunctionTypeMirrorImpl(reflectee,
simpleName,
this._returnType,
this.parameters)
- : super(null,
- ref,
+ : super(reflectee,
simpleName,
true,
null,
@@ -646,6 +628,17 @@
String toString() => "FunctionTypeMirror on '${_n(simpleName)}'";
}
+abstract class _LocalDeclarationMirrorImpl extends _LocalMirrorImpl
+ implements DeclarationMirror {
+ _LocalDeclarationMirrorImpl(this._reflectee);
+ final _MirrorReference _reflectee;
+
+ List<InstanceMirror> get metadata {
+ // Get the metadata objects, convert them into InstanceMirrors using
+ // reflect() and then make them into a Dart list.
+ return _metadata(_reflectee).map(reflect).toList(growable:false);
+ }
+}
class _LazyTypeVariableMirror {
_LazyTypeVariableMirror(String variableName, this._owner)
@@ -660,12 +653,14 @@
final _LazyTypeMirror _owner;
}
-class _LocalTypeVariableMirrorImpl extends _LocalMirrorImpl
+class _LocalTypeVariableMirrorImpl extends _LocalDeclarationMirrorImpl
implements TypeVariableMirror {
- _LocalTypeVariableMirrorImpl(String simpleName,
+ _LocalTypeVariableMirrorImpl(reflectee,
+ String simpleName,
this._owner,
this._upperBound)
- : this.simpleName = _s(simpleName);
+ : this.simpleName = _s(simpleName),
+ super(reflectee);
final Symbol simpleName;
@@ -702,20 +697,23 @@
return _upperBound;
}
- // get the metadata objects, convert them into InstanceMirrors using
- // reflect() and then make them into a Dart list
- List<InstanceMirror> get metadata => _metadata(this).map(reflect).toList();
+ List<InstanceMirror> get metadata {
+ throw new UnimplementedError(
+ 'TypeVariableMirror.metadata is not implemented');
+ }
String toString() => "TypeVariableMirror on '${_n(simpleName)}'";
}
-class _LocalTypedefMirrorImpl extends _LocalMirrorImpl
+class _LocalTypedefMirrorImpl extends _LocalDeclarationMirrorImpl
implements TypedefMirror {
- _LocalTypedefMirrorImpl(String simpleName,
+ _LocalTypedefMirrorImpl(reflectee,
+ String simpleName,
this._owner,
this._referent)
- : this.simpleName = _s(simpleName);
+ : this.simpleName = _s(simpleName),
+ super(reflectee);
final Symbol simpleName;
@@ -769,14 +767,13 @@
class _LocalLibraryMirrorImpl extends _LocalObjectMirrorImpl
implements LibraryMirror {
_LocalLibraryMirrorImpl(reflectee,
- ref,
String simpleName,
String url,
Map<String, Mirror> members)
: this.simpleName = _s(simpleName),
this.members = _convertStringToSymbolMap(members),
this.uri = Uri.parse(url),
- super(reflectee, ref);
+ super(reflectee);
final Symbol simpleName;
@@ -846,9 +843,11 @@
return _variables;
}
- // get the metadata objects, convert them into InstanceMirrors using
- // reflect() and then make them into a Dart list
- List<InstanceMirror> get metadata => _metadata(this).map(reflect).toList();
+ List<InstanceMirror> get metadata {
+ // Get the metadata objects, convert them into InstanceMirrors using
+ // reflect() and then make them into a Dart list.
+ return _metadata(_reflectee).map(reflect).toList(growable:false);
+ }
String toString() => "LibraryMirror on '${_n(simpleName)}'";
@@ -862,9 +861,9 @@
native 'LibraryMirror_invokeSetter';
}
-class _LocalMethodMirrorImpl extends _LocalMirrorImpl
+class _LocalMethodMirrorImpl extends _LocalDeclarationMirrorImpl
implements MethodMirror {
- _LocalMethodMirrorImpl(this._reflectee,
+ _LocalMethodMirrorImpl(reflectee,
this._owner,
this.parameters,
this._returnType,
@@ -876,9 +875,7 @@
this.isConstConstructor,
this.isGenerativeConstructor,
this.isRedirectingConstructor,
- this.isFactoryConstructor);
-
- final _MirrorReference _reflectee;
+ this.isFactoryConstructor) : super(reflectee);
Symbol _simpleName = null;
Symbol get simpleName {
@@ -898,6 +895,12 @@
var _owner;
DeclarationMirror get owner {
+ // For nested closures it is possible, that the mirror for the owner has not
+ // been created yet.
+ if (_owner == null) {
+ _owner = _MethodMirror_owner(_reflectee);
+ }
+ // TODO(11897): This will go away, as soon as lazy mirrors go away.
if (_owner is! Mirror) {
_owner = _owner.resolve(mirrors);
}
@@ -966,27 +969,25 @@
final bool isRedirectingConstructor;
final bool isFactoryConstructor;
- List<InstanceMirror> get metadata {
- owner; // ensure owner is computed
- // get the metadata objects, convert them into InstanceMirrors using
- // reflect() and then make them into a Dart list
- return _metadata(this).map(reflect).toList();
- }
-
String toString() => "MethodMirror on '${_n(simpleName)}'";
static String _MethodMirror_name(reflectee)
native "MethodMirror_name";
+
+ static dynamic _MethodMirror_owner(reflectee)
+ native "MethodMirror_owner";
}
-class _LocalVariableMirrorImpl extends _LocalMirrorImpl
+class _LocalVariableMirrorImpl extends _LocalDeclarationMirrorImpl
implements VariableMirror {
- _LocalVariableMirrorImpl(String simpleName,
+ _LocalVariableMirrorImpl(reflectee,
+ String simpleName,
this._owner,
this._type,
this.isStatic,
this.isFinal)
- : this.simpleName = _s(simpleName);
+ : this.simpleName = _s(simpleName),
+ super(reflectee);
final Symbol simpleName;
@@ -1030,20 +1031,13 @@
final bool isStatic;
final bool isFinal;
- List<InstanceMirror> get metadata {
- owner; // ensure owner is computed
- // get the metadata objects, convert them into InstanceMirrors using
- // reflect() and then make them into a Dart list
- return _metadata(this).map(reflect).toList();
- }
-
String toString() => "VariableMirror on '${_n(simpleName)}'";
}
class _LocalParameterMirrorImpl extends _LocalVariableMirrorImpl
implements ParameterMirror {
_LocalParameterMirrorImpl(type, this.isOptional)
- : super('<TODO:unnamed>', null, type, false, false) {}
+ : super(null, '<TODO:unnamed>', null, type, false, false) {}
final bool isOptional;
@@ -1056,6 +1050,12 @@
throw new UnimplementedError(
'ParameterMirror.hasDefaultValue is not implemented');
}
+
+ // TODO(11418): Implement.
+ List<InstanceMirror> get metadata {
+ throw new UnimplementedError(
+ 'ParameterMirror.metadata is not implemented');
+ }
}
class _SpecialTypeMirrorImpl extends _LocalMirrorImpl
@@ -1129,7 +1129,13 @@
static ClassMirror makeLocalClassMirror(Type key)
native "Mirrors_makeLocalClassMirror";
+ static Expando<ClassMirror> _classMirrorCache = new Expando("ClassMirror");
static ClassMirror reflectClass(Type key) {
- return makeLocalClassMirror(key);
+ var classMirror = _classMirrorCache[key];
+ if (classMirror == null) {
+ classMirror = makeLocalClassMirror(key);
+ _classMirrorCache[key] = classMirror;
+ }
+ return classMirror;
}
}
diff --git a/runtime/tests/vm/dart/isolate_mirror_local_test.dart b/runtime/tests/vm/dart/isolate_mirror_local_test.dart
index f76089e..e166e10 100644
--- a/runtime/tests/vm/dart/isolate_mirror_local_test.dart
+++ b/runtime/tests/vm/dart/isolate_mirror_local_test.dart
@@ -327,11 +327,11 @@
Expect.equals(const Symbol('dart.core.OutOfMemoryError'),
oom_cls.qualifiedName);
Expect.isFalse(oom_cls.isPrivate);
- Expect.equals(const Symbol('Error'), oom_cls.superclass.simpleName);
+ Expect.equals(const Symbol('Object'), oom_cls.superclass.simpleName);
Expect.isTrue(oom_cls.defaultFactory == null);
Expect.equals(const Symbol('dart.core'), oom_cls.owner.simpleName);
Expect.isTrue(oom_cls.isClass);
- Expect.isTrue(oom_cls.superinterfaces.isEmpty);
+ Expect.equals(const Symbol('Error'), oom_cls.superinterfaces[0].simpleName);
// TODO(ahe): toString() test disabled for now as Symbols are 100% opaque.
// Expect.equals("ClassMirror on 'OutOfMemoryError'",
// oom_cls.toString());
diff --git a/runtime/vm/assembler_arm.cc b/runtime/vm/assembler_arm.cc
index 8faef96..5e4bfe6 100644
--- a/runtime/vm/assembler_arm.cc
+++ b/runtime/vm/assembler_arm.cc
@@ -1279,6 +1279,11 @@
}
+void Assembler::vmovq(QRegister qd, QRegister qm) {
+ EmitSIMDqqq(B21 | B8 | B4, kByte, qd, qm, qm);
+}
+
+
void Assembler::vaddqi(OperandSize sz,
QRegister qd, QRegister qn, QRegister qm) {
EmitSIMDqqq(B11, sz, qd, qn, qm);
@@ -1312,12 +1317,107 @@
}
+void Assembler::veorq(QRegister qd, QRegister qn, QRegister qm) {
+ EmitSIMDqqq(B24 | B8 | B4, kByte, qd, qn, qm);
+}
+
+
+void Assembler::vorrq(QRegister qd, QRegister qn, QRegister qm) {
+ EmitSIMDqqq(B21 | B8 | B4, kByte, qd, qn, qm);
+}
+
+
+void Assembler::vornq(QRegister qd, QRegister qn, QRegister qm) {
+ EmitSIMDqqq(B21 | B20 | B8 | B4, kByte, qd, qn, qm);
+}
+
+
+void Assembler::vdup(OperandSize sz, QRegister qd, DRegister dm, int idx) {
+ ASSERT((sz != kDWord) && (sz != kSWord) && (sz != kWordPair));
+ int code = 0;
+
+ switch (sz) {
+ case kByte:
+ case kUnsignedByte: {
+ ASSERT((idx >= 0) && (idx < 8));
+ code = 1 | (idx << 1);
+ break;
+ }
+ case kHalfword:
+ case kUnsignedHalfword: {
+ ASSERT((idx >= 0) && (idx < 4));
+ code = 2 | (idx << 2);
+ break;
+ }
+ case kWord:
+ case kUnsignedWord: {
+ ASSERT((idx >= 0) && (idx < 2));
+ code = 4 | (idx << 3);
+ break;
+ }
+ default: {
+ break;
+ }
+ }
+
+ EmitSIMDddd(B24 | B23 | B11 | B10 | B6, kWordPair,
+ static_cast<DRegister>(qd * 2),
+ static_cast<DRegister>(code & 0xf),
+ dm);
+}
+
+
void Assembler::vtbl(DRegister dd, DRegister dn, int len, DRegister dm) {
ASSERT((len >= 1) && (len <= 4));
EmitSIMDddd(B24 | B23 | B11 | ((len - 1) * B8), kWordPair, dd, dn, dm);
}
+void Assembler::vceqqi(OperandSize sz,
+ QRegister qd, QRegister qn, QRegister qm) {
+ EmitSIMDqqq(B24 | B11 | B4, sz, qd, qn, qm);
+}
+
+
+void Assembler::vceqqs(QRegister qd, QRegister qn, QRegister qm) {
+ EmitSIMDqqq(B11 | B10 | B9, kSWord, qd, qn, qm);
+}
+
+
+void Assembler::vcgeqi(OperandSize sz,
+ QRegister qd, QRegister qn, QRegister qm) {
+ EmitSIMDqqq(B9 | B8 | B4, sz, qd, qn, qm);
+}
+
+
+void Assembler::vcugeqi(OperandSize sz,
+ QRegister qd, QRegister qn, QRegister qm) {
+ EmitSIMDqqq(B24 | B9 | B8 | B4, sz, qd, qn, qm);
+}
+
+
+void Assembler::vcgeqs(QRegister qd, QRegister qn, QRegister qm) {
+ EmitSIMDqqq(B24 | B11 | B10 | B9, kSWord, qd, qn, qm);
+}
+
+
+void Assembler::vcgtqi(OperandSize sz,
+ QRegister qd, QRegister qn, QRegister qm) {
+ EmitSIMDqqq(B9 | B8, sz, qd, qn, qm);
+}
+
+
+void Assembler::vcugtqi(OperandSize sz,
+ QRegister qd, QRegister qn, QRegister qm) {
+ EmitSIMDqqq(B24 | B9 | B8, sz, qd, qn, qm);
+}
+
+
+void Assembler::vcgtqs(QRegister qd, QRegister qn, QRegister qm) {
+ EmitSIMDqqq(B24 | B21 | B11 | B10 | B9, kSWord, qd, qn, qm);
+}
+
+
void Assembler::svc(uint32_t imm24, Condition cond) {
ASSERT(cond != kNoCondition);
ASSERT(imm24 < (1 << 24));
diff --git a/runtime/vm/assembler_arm.h b/runtime/vm/assembler_arm.h
index e07eab0..ece3212 100644
--- a/runtime/vm/assembler_arm.h
+++ b/runtime/vm/assembler_arm.h
@@ -255,10 +255,6 @@
encoding_ = so.encoding() | am | (static_cast<uint32_t>(rn) << kRnShift);
}
- bool Equals(const Address& other) {
- return (encoding_ == other.encoding_) && (kind_ == other.kind_);
- }
-
static bool CanHoldLoadOffset(OperandSize type,
int32_t offset,
int32_t* offset_mask);
@@ -448,6 +444,7 @@
void vmovrrd(Register rt, Register rt2, DRegister dm, Condition cond = AL);
void vmovs(SRegister sd, SRegister sm, Condition cond = AL);
void vmovd(DRegister dd, DRegister dm, Condition cond = AL);
+ void vmovq(QRegister qd, QRegister qm);
// Returns false if the immediate cannot be encoded.
bool vmovs(SRegister sd, float s_imm, Condition cond = AL);
@@ -486,6 +483,18 @@
void vmlsd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL);
void vdivs(SRegister sd, SRegister sn, SRegister sm, Condition cond = AL);
void vdivd(DRegister dd, DRegister dn, DRegister dm, Condition cond = AL);
+ void veorq(QRegister qd, QRegister qn, QRegister qm);
+ void vorrq(QRegister qd, QRegister qn, QRegister qm);
+ void vornq(QRegister qd, QRegister qn, QRegister qm);
+
+ void vceqqi(OperandSize sz, QRegister qd, QRegister qn, QRegister qm);
+ void vceqqs(QRegister qd, QRegister qn, QRegister qm);
+ void vcgeqi(OperandSize sz, QRegister qd, QRegister qn, QRegister qm);
+ void vcugeqi(OperandSize sz, QRegister qd, QRegister qn, QRegister qm);
+ void vcgeqs(QRegister qd, QRegister qn, QRegister qm);
+ void vcgtqi(OperandSize sz, QRegister qd, QRegister qn, QRegister qm);
+ void vcugtqi(OperandSize sz, QRegister qd, QRegister qn, QRegister qm);
+ void vcgtqs(QRegister qd, QRegister qn, QRegister qm);
void vabss(SRegister sd, SRegister sm, Condition cond = AL);
void vabsd(DRegister dd, DRegister dm, Condition cond = AL);
@@ -511,6 +520,10 @@
void vcmpdz(DRegister dd, Condition cond = AL);
void vmstat(Condition cond = AL); // VMRS APSR_nzcv, FPSCR
+ // Duplicates the operand of size sz at index idx from dm to all elements of
+ // qd. This is a special case of vtbl.
+ void vdup(OperandSize sz, QRegister qd, DRegister dm, int idx);
+
// Each byte of dm is an index into the table of bytes formed by concatenating
// a list of 'length' registers starting with dn. The result is placed in dd.
void vtbl(DRegister dd, DRegister dn, int length, DRegister dm);
diff --git a/runtime/vm/assembler_arm_test.cc b/runtime/vm/assembler_arm_test.cc
index d1d5b03..f44a564 100644
--- a/runtime/vm/assembler_arm_test.cc
+++ b/runtime/vm/assembler_arm_test.cc
@@ -2333,6 +2333,597 @@
}
+ASSEMBLER_TEST_GENERATE(Veorq, assembler) {
+ if (CPUFeatures::neon_supported()) {
+ // Q0
+ __ LoadImmediate(R0, 0xaaaaaaab);
+ __ vmovsr(S0, R0);
+ __ vmovsr(S1, R0);
+ __ vmovsr(S2, R0);
+ __ vmovsr(S3, R0);
+
+ // Q1
+ __ LoadImmediate(R0, 0x55555555);
+ __ vmovsr(S4, R0);
+ __ vmovsr(S5, R0);
+ __ vmovsr(S6, R0);
+ __ vmovsr(S7, R0);
+
+ // Q2 = -2 -2 -2 -2
+ __ veorq(Q2, Q1, Q0);
+
+ __ vmovrs(R0, S8);
+ __ vmovrs(R1, S9);
+ __ vmovrs(R2, S10);
+ __ vmovrs(R3, S11);
+
+ __ add(R0, R0, ShifterOperand(R1));
+ __ add(R0, R0, ShifterOperand(R2));
+ __ add(R0, R0, ShifterOperand(R3));
+ __ bx(LR);
+ } else {
+ __ LoadImmediate(R0, -8);
+ __ bx(LR);
+ }
+}
+
+
+ASSEMBLER_TEST_RUN(Veorq, test) {
+ EXPECT(test != NULL);
+ typedef int (*Tst)();
+ EXPECT_EQ(-8, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(Vornq, assembler) {
+ if (CPUFeatures::neon_supported()) {
+ // Q0
+ __ LoadImmediate(R0, 0xfffffff0);
+ __ vmovsr(S0, R0);
+ __ vmovsr(S1, R0);
+ __ vmovsr(S2, R0);
+ __ vmovsr(S3, R0);
+
+ // Q1
+ __ LoadImmediate(R0, 0);
+ __ vmovsr(S4, R0);
+ __ vmovsr(S5, R0);
+ __ vmovsr(S6, R0);
+ __ vmovsr(S7, R0);
+
+ // Q2 = 15 15 15 15
+ __ vornq(Q2, Q1, Q0);
+
+ __ vmovrs(R0, S8);
+ __ vmovrs(R1, S9);
+ __ vmovrs(R2, S10);
+ __ vmovrs(R3, S11);
+
+ __ add(R0, R0, ShifterOperand(R1));
+ __ add(R0, R0, ShifterOperand(R2));
+ __ add(R0, R0, ShifterOperand(R3));
+ __ bx(LR);
+ } else {
+ __ LoadImmediate(R0, 60);
+ __ bx(LR);
+ }
+}
+
+
+ASSEMBLER_TEST_RUN(Vornq, test) {
+ EXPECT(test != NULL);
+ typedef int (*Tst)();
+ EXPECT_EQ(60, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(Vorrq, assembler) {
+ if (CPUFeatures::neon_supported()) {
+ // Q0
+ __ LoadImmediate(R0, 0xaaaaaaaa);
+ __ vmovsr(S0, R0);
+ __ vmovsr(S1, R0);
+ __ vmovsr(S2, R0);
+ __ vmovsr(S3, R0);
+
+ // Q1
+ __ LoadImmediate(R0, 0x55555555);
+ __ vmovsr(S4, R0);
+ __ vmovsr(S5, R0);
+ __ vmovsr(S6, R0);
+ __ vmovsr(S7, R0);
+
+ // Q2 = -1 -1 -1 -1
+ __ vorrq(Q2, Q1, Q0);
+
+ __ vmovrs(R0, S8);
+ __ vmovrs(R1, S9);
+ __ vmovrs(R2, S10);
+ __ vmovrs(R3, S11);
+
+ __ add(R0, R0, ShifterOperand(R1));
+ __ add(R0, R0, ShifterOperand(R2));
+ __ add(R0, R0, ShifterOperand(R3));
+ __ bx(LR);
+ } else {
+ __ LoadImmediate(R0, -4);
+ __ bx(LR);
+ }
+}
+
+
+ASSEMBLER_TEST_RUN(Vorrq, test) {
+ EXPECT(test != NULL);
+ typedef int (*Tst)();
+ EXPECT_EQ(-4, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(Vmovq, assembler) {
+ if (CPUFeatures::neon_supported()) {
+ // Q0
+ __ LoadSImmediate(S0, 1.0);
+ __ vmovs(S1, S0);
+ __ vmovs(S2, S0);
+ __ vmovs(S3, S0);
+
+ // Q0
+ __ LoadSImmediate(S4, -1.0);
+ __ vmovs(S5, S0);
+ __ vmovs(S6, S0);
+ __ vmovs(S7, S0);
+
+ // Q1 = Q2
+ __ vmovq(Q1, Q0);
+
+ __ vadds(S4, S4, S5);
+ __ vadds(S4, S4, S6);
+ __ vadds(S4, S4, S7);
+ __ vcvtis(S0, S4);
+ __ vmovrs(R0, S0);
+
+ __ bx(LR);
+ } else {
+ __ LoadImmediate(R0, 4);
+ __ bx(LR);
+ }
+}
+
+
+ASSEMBLER_TEST_RUN(Vmovq, test) {
+ EXPECT(test != NULL);
+ typedef int (*Tst)();
+ EXPECT_EQ(4, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(Vdupb, assembler) {
+ if (CPUFeatures::neon_supported()) {
+ __ LoadImmediate(R0, 0x00000000);
+ __ LoadImmediate(R1, 0x00ff0000);
+ __ vmovsr(S4, R0);
+ __ vmovsr(S5, R1);
+
+ // Should copy 0xff to each byte of Q0.
+ __ vdup(kByte, Q0, D2, 6);
+
+ __ vmovrs(R0, S0);
+ __ vmovrs(R1, S1);
+ __ vmovrs(R2, S2);
+ __ vmovrs(R3, S3);
+
+ __ add(R0, R0, ShifterOperand(R1));
+ __ add(R0, R0, ShifterOperand(R2));
+ __ add(R0, R0, ShifterOperand(R3));
+ __ bx(LR);
+ } else {
+ __ LoadImmediate(R0, -4);
+ __ bx(LR);
+ }
+}
+
+
+ASSEMBLER_TEST_RUN(Vdupb, test) {
+ EXPECT(test != NULL);
+ typedef int (*Tst)();
+ EXPECT_EQ(-4, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(Vduph, assembler) {
+ if (CPUFeatures::neon_supported()) {
+ __ LoadImmediate(R0, 0xffff0000);
+ __ LoadImmediate(R1, 0x00000000);
+ __ vmovsr(S4, R0);
+ __ vmovsr(S5, R1);
+
+ // Should copy 0xff to each byte of Q0.
+ __ vdup(kHalfword, Q0, D2, 1);
+
+ __ vmovrs(R0, S0);
+ __ vmovrs(R1, S1);
+ __ vmovrs(R2, S2);
+ __ vmovrs(R3, S3);
+
+ __ add(R0, R0, ShifterOperand(R1));
+ __ add(R0, R0, ShifterOperand(R2));
+ __ add(R0, R0, ShifterOperand(R3));
+ __ bx(LR);
+ } else {
+ __ LoadImmediate(R0, -4);
+ __ bx(LR);
+ }
+}
+
+
+ASSEMBLER_TEST_RUN(Vduph, test) {
+ EXPECT(test != NULL);
+ typedef int (*Tst)();
+ EXPECT_EQ(-4, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(Vdupw, assembler) {
+ if (CPUFeatures::neon_supported()) {
+ __ LoadImmediate(R0, 0x00000000);
+ __ LoadImmediate(R1, 0xffffffff);
+ __ vmovsr(S4, R0);
+ __ vmovsr(S5, R1);
+
+ // Should copy 0xff to each byte of Q0.
+ __ vdup(kWord, Q0, D2, 1);
+
+ __ vmovrs(R0, S0);
+ __ vmovrs(R1, S1);
+ __ vmovrs(R2, S2);
+ __ vmovrs(R3, S3);
+
+ __ add(R0, R0, ShifterOperand(R1));
+ __ add(R0, R0, ShifterOperand(R2));
+ __ add(R0, R0, ShifterOperand(R3));
+ __ bx(LR);
+ } else {
+ __ LoadImmediate(R0, -4);
+ __ bx(LR);
+ }
+}
+
+
+ASSEMBLER_TEST_RUN(Vdupw, test) {
+ EXPECT(test != NULL);
+ typedef int (*Tst)();
+ EXPECT_EQ(-4, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(Vceqqi32, assembler) {
+ if (CPUFeatures::neon_supported()) {
+ __ mov(R0, ShifterOperand(1));
+ __ vmovsr(S0, R0);
+ __ mov(R0, ShifterOperand(2));
+ __ vmovsr(S1, R0);
+ __ mov(R0, ShifterOperand(3));
+ __ vmovsr(S2, R0);
+ __ mov(R0, ShifterOperand(4));
+ __ vmovsr(S3, R0);
+ __ mov(R0, ShifterOperand(1));
+ __ vmovsr(S4, R0);
+ __ mov(R0, ShifterOperand(20));
+ __ vmovsr(S5, R0);
+ __ mov(R0, ShifterOperand(3));
+ __ vmovsr(S6, R0);
+ __ mov(R0, ShifterOperand(40));
+ __ vmovsr(S7, R0);
+
+ __ vceqqi(kWord, Q2, Q1, Q0);
+
+ __ vmovrs(R0, S8);
+ __ vmovrs(R1, S9);
+ __ vmovrs(R2, S10);
+ __ vmovrs(R3, S11);
+
+ __ add(R0, R0, ShifterOperand(R1));
+ __ add(R0, R0, ShifterOperand(R2));
+ __ add(R0, R0, ShifterOperand(R3));
+ __ bx(LR);
+ } else {
+ __ LoadImmediate(R0, -2);
+ __ bx(LR);
+ }
+}
+
+
+ASSEMBLER_TEST_RUN(Vceqqi32, test) {
+ EXPECT(test != NULL);
+ typedef int (*Tst)();
+ EXPECT_EQ(-2, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(Vceqqs, assembler) {
+ if (CPUFeatures::neon_supported()) {
+ __ LoadSImmediate(S0, 1.0);
+ __ LoadSImmediate(S1, 2.0);
+ __ LoadSImmediate(S2, 3.0);
+ __ LoadSImmediate(S3, 4.0);
+ __ LoadSImmediate(S4, 1.0);
+ __ LoadSImmediate(S5, 4.0);
+ __ LoadSImmediate(S6, 3.0);
+ __ LoadSImmediate(S7, 8.0);
+
+ __ vceqqs(Q2, Q1, Q0);
+
+ __ vmovrs(R0, S8);
+ __ vmovrs(R1, S9);
+ __ vmovrs(R2, S10);
+ __ vmovrs(R3, S11);
+
+ __ add(R0, R0, ShifterOperand(R1));
+ __ add(R0, R0, ShifterOperand(R2));
+ __ add(R0, R0, ShifterOperand(R3));
+ __ bx(LR);
+ } else {
+ __ LoadImmediate(R0, -2);
+ __ bx(LR);
+ }
+}
+
+
+ASSEMBLER_TEST_RUN(Vceqqs, test) {
+ EXPECT(test != NULL);
+ typedef int (*Tst)();
+ EXPECT_EQ(-2, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(Vcgeqi32, assembler) {
+ if (CPUFeatures::neon_supported()) {
+ __ mov(R0, ShifterOperand(1));
+ __ vmovsr(S0, R0);
+ __ mov(R0, ShifterOperand(2));
+ __ vmovsr(S1, R0);
+ __ mov(R0, ShifterOperand(3));
+ __ vmovsr(S2, R0);
+ __ mov(R0, ShifterOperand(4));
+ __ vmovsr(S3, R0);
+ __ mov(R0, ShifterOperand(1));
+ __ vmovsr(S4, R0);
+ __ mov(R0, ShifterOperand(1));
+ __ vmovsr(S5, R0);
+ __ mov(R0, ShifterOperand(3));
+ __ vmovsr(S6, R0);
+ __ mov(R0, ShifterOperand(1));
+ __ vmovsr(S7, R0);
+
+ __ vcgeqi(kWord, Q2, Q1, Q0);
+
+ __ vmovrs(R0, S8);
+ __ vmovrs(R1, S9);
+ __ vmovrs(R2, S10);
+ __ vmovrs(R3, S11);
+
+ __ add(R0, R0, ShifterOperand(R1));
+ __ add(R0, R0, ShifterOperand(R2));
+ __ add(R0, R0, ShifterOperand(R3));
+ __ bx(LR);
+ } else {
+ __ LoadImmediate(R0, -2);
+ __ bx(LR);
+ }
+}
+
+
+ASSEMBLER_TEST_RUN(Vcgeqi32, test) {
+ EXPECT(test != NULL);
+ typedef int (*Tst)();
+ EXPECT_EQ(-2, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(Vcugeqi32, assembler) {
+ if (CPUFeatures::neon_supported()) {
+ __ mov(R0, ShifterOperand(1));
+ __ vmovsr(S0, R0);
+ __ mov(R0, ShifterOperand(2));
+ __ vmovsr(S1, R0);
+ __ mov(R0, ShifterOperand(3));
+ __ vmovsr(S2, R0);
+ __ mov(R0, ShifterOperand(4));
+ __ vmovsr(S3, R0);
+ __ LoadImmediate(R0, -1);
+ __ vmovsr(S4, R0);
+ __ mov(R0, ShifterOperand(1));
+ __ vmovsr(S5, R0);
+ __ LoadImmediate(R0, -3);
+ __ vmovsr(S6, R0);
+ __ mov(R0, ShifterOperand(1));
+ __ vmovsr(S7, R0);
+
+ __ vcugeqi(kWord, Q2, Q1, Q0);
+
+ __ vmovrs(R0, S8);
+ __ vmovrs(R1, S9);
+ __ vmovrs(R2, S10);
+ __ vmovrs(R3, S11);
+
+ __ add(R0, R0, ShifterOperand(R1));
+ __ add(R0, R0, ShifterOperand(R2));
+ __ add(R0, R0, ShifterOperand(R3));
+ __ bx(LR);
+ } else {
+ __ LoadImmediate(R0, -2);
+ __ bx(LR);
+ }
+}
+
+
+ASSEMBLER_TEST_RUN(Vcugeqi32, test) {
+ EXPECT(test != NULL);
+ typedef int (*Tst)();
+ EXPECT_EQ(-2, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(Vcgeqs, assembler) {
+ if (CPUFeatures::neon_supported()) {
+ __ LoadSImmediate(S0, 1.0);
+ __ LoadSImmediate(S1, 2.0);
+ __ LoadSImmediate(S2, 3.0);
+ __ LoadSImmediate(S3, 4.0);
+ __ LoadSImmediate(S4, 1.0);
+ __ LoadSImmediate(S5, 1.0);
+ __ LoadSImmediate(S6, 3.0);
+ __ LoadSImmediate(S7, 1.0);
+
+ __ vcgeqs(Q2, Q1, Q0);
+
+ __ vmovrs(R0, S8);
+ __ vmovrs(R1, S9);
+ __ vmovrs(R2, S10);
+ __ vmovrs(R3, S11);
+
+ __ add(R0, R0, ShifterOperand(R1));
+ __ add(R0, R0, ShifterOperand(R2));
+ __ add(R0, R0, ShifterOperand(R3));
+ __ bx(LR);
+ } else {
+ __ LoadImmediate(R0, -2);
+ __ bx(LR);
+ }
+}
+
+
+ASSEMBLER_TEST_RUN(Vcgeqs, test) {
+ EXPECT(test != NULL);
+ typedef int (*Tst)();
+ EXPECT_EQ(-2, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(Vcgtqi32, assembler) {
+ if (CPUFeatures::neon_supported()) {
+ __ mov(R0, ShifterOperand(1));
+ __ vmovsr(S0, R0);
+ __ mov(R0, ShifterOperand(2));
+ __ vmovsr(S1, R0);
+ __ mov(R0, ShifterOperand(3));
+ __ vmovsr(S2, R0);
+ __ mov(R0, ShifterOperand(4));
+ __ vmovsr(S3, R0);
+ __ mov(R0, ShifterOperand(2));
+ __ vmovsr(S4, R0);
+ __ mov(R0, ShifterOperand(1));
+ __ vmovsr(S5, R0);
+ __ mov(R0, ShifterOperand(4));
+ __ vmovsr(S6, R0);
+ __ mov(R0, ShifterOperand(1));
+ __ vmovsr(S7, R0);
+
+ __ vcgtqi(kWord, Q2, Q1, Q0);
+
+ __ vmovrs(R0, S8);
+ __ vmovrs(R1, S9);
+ __ vmovrs(R2, S10);
+ __ vmovrs(R3, S11);
+
+ __ add(R0, R0, ShifterOperand(R1));
+ __ add(R0, R0, ShifterOperand(R2));
+ __ add(R0, R0, ShifterOperand(R3));
+ __ bx(LR);
+ } else {
+ __ LoadImmediate(R0, -2);
+ __ bx(LR);
+ }
+}
+
+
+ASSEMBLER_TEST_RUN(Vcgtqi32, test) {
+ EXPECT(test != NULL);
+ typedef int (*Tst)();
+ EXPECT_EQ(-2, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(Vcugtqi32, assembler) {
+ if (CPUFeatures::neon_supported()) {
+ __ mov(R0, ShifterOperand(1));
+ __ vmovsr(S0, R0);
+ __ mov(R0, ShifterOperand(2));
+ __ vmovsr(S1, R0);
+ __ mov(R0, ShifterOperand(3));
+ __ vmovsr(S2, R0);
+ __ mov(R0, ShifterOperand(4));
+ __ vmovsr(S3, R0);
+ __ LoadImmediate(R0, -1);
+ __ vmovsr(S4, R0);
+ __ mov(R0, ShifterOperand(1));
+ __ vmovsr(S5, R0);
+ __ LoadImmediate(R0, -3);
+ __ vmovsr(S6, R0);
+ __ mov(R0, ShifterOperand(1));
+ __ vmovsr(S7, R0);
+
+ __ vcugtqi(kWord, Q2, Q1, Q0);
+
+ __ vmovrs(R0, S8);
+ __ vmovrs(R1, S9);
+ __ vmovrs(R2, S10);
+ __ vmovrs(R3, S11);
+
+ __ add(R0, R0, ShifterOperand(R1));
+ __ add(R0, R0, ShifterOperand(R2));
+ __ add(R0, R0, ShifterOperand(R3));
+ __ bx(LR);
+ } else {
+ __ LoadImmediate(R0, -2);
+ __ bx(LR);
+ }
+}
+
+
+ASSEMBLER_TEST_RUN(Vcugtqi32, test) {
+ EXPECT(test != NULL);
+ typedef int (*Tst)();
+ EXPECT_EQ(-2, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+}
+
+
+ASSEMBLER_TEST_GENERATE(Vcgtqs, assembler) {
+ if (CPUFeatures::neon_supported()) {
+ __ LoadSImmediate(S0, 1.0);
+ __ LoadSImmediate(S1, 2.0);
+ __ LoadSImmediate(S2, 3.0);
+ __ LoadSImmediate(S3, 4.0);
+ __ LoadSImmediate(S4, 2.0);
+ __ LoadSImmediate(S5, 1.0);
+ __ LoadSImmediate(S6, 4.0);
+ __ LoadSImmediate(S7, 1.0);
+
+ __ vcgtqs(Q2, Q1, Q0);
+
+ __ vmovrs(R0, S8);
+ __ vmovrs(R1, S9);
+ __ vmovrs(R2, S10);
+ __ vmovrs(R3, S11);
+
+ __ add(R0, R0, ShifterOperand(R1));
+ __ add(R0, R0, ShifterOperand(R2));
+ __ add(R0, R0, ShifterOperand(R3));
+ __ bx(LR);
+ } else {
+ __ LoadImmediate(R0, -2);
+ __ bx(LR);
+ }
+}
+
+
+ASSEMBLER_TEST_RUN(Vcgtqs, test) {
+ EXPECT(test != NULL);
+ typedef int (*Tst)();
+ EXPECT_EQ(-2, EXECUTE_TEST_CODE_INT32(Tst, test->entry()));
+}
+
+
// Called from assembler_test.cc.
// LR: return address.
// R0: context.
diff --git a/runtime/vm/assembler_ia32.h b/runtime/vm/assembler_ia32.h
index df68c46..6702842 100644
--- a/runtime/vm/assembler_ia32.h
+++ b/runtime/vm/assembler_ia32.h
@@ -81,7 +81,7 @@
return *this;
}
- bool Equals(const Operand& other) {
+ bool Equals(const Operand& other) const {
if (length_ != other.length_) return false;
for (uint8_t i = 0; i < length_; i++) {
if (encoding_[i] != other.encoding_[i]) return false;
diff --git a/runtime/vm/assembler_mips.h b/runtime/vm/assembler_mips.h
index bb2bb35..91fa899 100644
--- a/runtime/vm/assembler_mips.h
+++ b/runtime/vm/assembler_mips.h
@@ -70,10 +70,6 @@
Register base() const { return base_; }
int32_t offset() const { return offset_; }
- bool Equals(const Address& other) {
- return (base_ == other.base_) && (offset_ == other.offset_);
- }
-
private:
Register base_;
int32_t offset_;
diff --git a/runtime/vm/assembler_x64.h b/runtime/vm/assembler_x64.h
index 919b1c5..4d82ceb 100644
--- a/runtime/vm/assembler_x64.h
+++ b/runtime/vm/assembler_x64.h
@@ -91,7 +91,7 @@
return *this;
}
- bool Equals(const Operand& other) {
+ bool Equals(const Operand& other) const {
if (length_ != other.length_) return false;
if (rex_ != other.rex_) return false;
for (uint8_t i = 0; i < length_; i++) {
diff --git a/runtime/vm/bootstrap_natives.h b/runtime/vm/bootstrap_natives.h
index 99008cb..d7912dc 100644
--- a/runtime/vm/bootstrap_natives.h
+++ b/runtime/vm/bootstrap_natives.h
@@ -239,7 +239,6 @@
V(Mirrors_makeLocalInstanceMirror, 1) \
V(Mirrors_makeLocalClassMirror, 1) \
V(Mirrors_makeLocalMirrorSystem, 0) \
- V(Mirrors_metadata, 1) \
V(InstanceMirror_invoke, 4) \
V(InstanceMirror_invokeGetter, 3) \
V(InstanceMirror_invokeSetter, 4) \
@@ -252,7 +251,9 @@
V(LibraryMirror_invoke, 4) \
V(LibraryMirror_invokeGetter, 3) \
V(LibraryMirror_invokeSetter, 4) \
+ V(DeclarationMirror_metadata, 1) \
V(MethodMirror_name, 1) \
+ V(MethodMirror_owner, 1) \
V(GrowableObjectArray_allocate, 2) \
V(GrowableObjectArray_getIndexed, 2) \
V(GrowableObjectArray_setIndexed, 3) \
diff --git a/runtime/vm/class_finalizer.cc b/runtime/vm/class_finalizer.cc
index a996ff6..7c69615 100644
--- a/runtime/vm/class_finalizer.cc
+++ b/runtime/vm/class_finalizer.cc
@@ -1257,9 +1257,9 @@
// Copy the type parameters of the super and mixin classes to the
-// mixin application class. Change type arguments of super type to
-// refer to the respective type parameters of the mixin application
-// class.
+// mixin application class. Change type arguments of super type and of
+// interfaces to refer to the respective type parameters of the mixin
+// application class.
void ClassFinalizer::CloneTypeParameters(const Class& mixapp_class) {
ASSERT(mixapp_class.NumTypeParameters() == 0);
@@ -1318,6 +1318,7 @@
// TODO(hausner): May need to handle BoundedType here.
ASSERT(super_type.IsType());
Type::Cast(super_type).set_arguments(super_type_args);
+ ASSERT(!super_type.IsFinalized());
}
// Second, clone the type parameters of the mixin class.
@@ -1328,6 +1329,8 @@
if (num_mixin_parameters > 0) {
const TypeArguments& mixin_params =
TypeArguments::Handle(mixin_class.type_parameters());
+ const TypeArguments& interface_type_args = TypeArguments::Handle(
+ TypeArguments::New(num_mixin_parameters));
for (int i = 0; i < num_mixin_parameters; i++) {
param ^= mixin_params.TypeAt(i);
param_name = param.name();
@@ -1347,8 +1350,21 @@
param_bound,
param.token_pos());
cloned_type_params.SetTypeAt(cloned_index, cloned_param);
+ interface_type_args.SetTypeAt(i, cloned_param);
cloned_index++;
}
+
+ // Lastly, change the type arguments of the single interface type to
+ // refer to the cloned type parameters of the mixin application class.
+ Array& interface_types = Array::Handle(mixapp_class.interfaces());
+ ASSERT(interface_types.Length() == 1);
+ AbstractType& interface_type = AbstractType::Handle();
+ interface_type ^= interface_types.At(0);
+ ASSERT(interface_type.IsResolved());
+ // TODO(hausner): May need to handle BoundedType here.
+ ASSERT(interface_type.IsType());
+ Type::Cast(interface_type).set_arguments(interface_type_args);
+ ASSERT(!interface_type.IsFinalized());
}
mixapp_class.set_type_parameters(cloned_type_params);
}
@@ -1362,7 +1378,7 @@
if (FLAG_trace_class_finalization) {
OS::Print("Applying mixin type '%s' to '%s' at pos %"Pd"\n",
- String::Handle(mixin_cls.Name()).ToCString(),
+ String::Handle(mixin_type.Name()).ToCString(),
cls.ToCString(),
cls.token_pos());
}
@@ -1383,7 +1399,8 @@
CloneTypeParameters(cls);
if (FLAG_trace_class_finalization) {
- OS::Print("done mixin type appl %s %s extending '%s'\n",
+ OS::Print("Done applying mixin type '%s' to class %s %s extending '%s'\n",
+ String::Handle(mixin_type.Name()).ToCString(),
String::Handle(cls.Name()).ToCString(),
TypeArguments::Handle(cls.type_parameters()).ToCString(),
AbstractType::Handle(cls.super_type()).ToCString());
diff --git a/runtime/vm/code_generator.cc b/runtime/vm/code_generator.cc
index 8efe89c..7294784 100644
--- a/runtime/vm/code_generator.cc
+++ b/runtime/vm/code_generator.cc
@@ -905,8 +905,7 @@
static RawFunction* InlineCacheMissHandler(
const GrowableArray<const Instance*>& args,
- const ICData& ic_data,
- const Array& args_descriptor_array) {
+ const ICData& ic_data) {
const Instance& receiver = *args[0];
const Code& target_code =
Code::Handle(ResolveCompileInstanceCallTarget(receiver, ic_data));
@@ -963,19 +962,17 @@
// site.
// Arg0: Receiver object.
// Arg1: IC data object.
-// Arg2: Arguments descriptor array.
// Returns: target function with compiled code or null.
// Modifies the instance call to hold the updated IC data array.
-DEFINE_RUNTIME_ENTRY(InlineCacheMissHandlerOneArg, 3) {
+DEFINE_RUNTIME_ENTRY(InlineCacheMissHandlerOneArg, 2) {
ASSERT(arguments.ArgCount() ==
kInlineCacheMissHandlerOneArgRuntimeEntry.argument_count());
const Instance& receiver = Instance::CheckedHandle(arguments.ArgAt(0));
const ICData& ic_data = ICData::CheckedHandle(arguments.ArgAt(1));
- const Array& arg_desc_array = Array::CheckedHandle(arguments.ArgAt(2));
GrowableArray<const Instance*> args(1);
args.Add(&receiver);
const Function& result =
- Function::Handle(InlineCacheMissHandler(args, ic_data, arg_desc_array));
+ Function::Handle(InlineCacheMissHandler(args, ic_data));
arguments.SetReturn(result);
}
@@ -985,21 +982,19 @@
// Arg0: Receiver object.
// Arg1: Argument after receiver.
// Arg2: IC data object.
-// Arg3: Arguments descriptor array.
// Returns: target function with compiled code or null.
// Modifies the instance call to hold the updated IC data array.
-DEFINE_RUNTIME_ENTRY(InlineCacheMissHandlerTwoArgs, 4) {
+DEFINE_RUNTIME_ENTRY(InlineCacheMissHandlerTwoArgs, 3) {
ASSERT(arguments.ArgCount() ==
kInlineCacheMissHandlerTwoArgsRuntimeEntry.argument_count());
const Instance& receiver = Instance::CheckedHandle(arguments.ArgAt(0));
const Instance& other = Instance::CheckedHandle(arguments.ArgAt(1));
const ICData& ic_data = ICData::CheckedHandle(arguments.ArgAt(2));
- const Array& arg_desc_array = Array::CheckedHandle(arguments.ArgAt(3));
GrowableArray<const Instance*> args(2);
args.Add(&receiver);
args.Add(&other);
const Function& result =
- Function::Handle(InlineCacheMissHandler(args, ic_data, arg_desc_array));
+ Function::Handle(InlineCacheMissHandler(args, ic_data));
arguments.SetReturn(result);
}
@@ -1010,23 +1005,21 @@
// Arg1: Argument after receiver.
// Arg2: Second argument after receiver.
// Arg3: IC data object.
-// Arg4: Arguments descriptor array.
// Returns: target function with compiled code or null.
// Modifies the instance call to hold the updated IC data array.
-DEFINE_RUNTIME_ENTRY(InlineCacheMissHandlerThreeArgs, 5) {
+DEFINE_RUNTIME_ENTRY(InlineCacheMissHandlerThreeArgs, 4) {
ASSERT(arguments.ArgCount() ==
kInlineCacheMissHandlerThreeArgsRuntimeEntry.argument_count());
const Instance& receiver = Instance::CheckedHandle(arguments.ArgAt(0));
const Instance& arg1 = Instance::CheckedHandle(arguments.ArgAt(1));
const Instance& arg2 = Instance::CheckedHandle(arguments.ArgAt(2));
const ICData& ic_data = ICData::CheckedHandle(arguments.ArgAt(3));
- const Array& arg_desc_array = Array::CheckedHandle(arguments.ArgAt(4));
GrowableArray<const Instance*> args(3);
args.Add(&receiver);
args.Add(&arg1);
args.Add(&arg2);
const Function& result =
- Function::Handle(InlineCacheMissHandler(args, ic_data, arg_desc_array));
+ Function::Handle(InlineCacheMissHandler(args, ic_data));
arguments.SetReturn(result);
}
diff --git a/runtime/vm/compiler.cc b/runtime/vm/compiler.cc
index a0dc2814..6cf9ce2 100644
--- a/runtime/vm/compiler.cc
+++ b/runtime/vm/compiler.cc
@@ -450,7 +450,9 @@
// Attempt to sink allocations of temporary non-escaping objects to
// the deoptimization path.
AllocationSinking* sinking = NULL;
- if (FLAG_allocation_sinking) {
+ if (FLAG_allocation_sinking &&
+ (flow_graph->graph_entry()->SuccessorCount() == 1)) {
+ // TODO(fschneider): Support allocation sinking with try-catch.
sinking = new AllocationSinking(flow_graph);
sinking->Optimize();
}
diff --git a/runtime/vm/debugger_api_impl.cc b/runtime/vm/debugger_api_impl.cc
index 718cd5d..b3c3739 100644
--- a/runtime/vm/debugger_api_impl.cc
+++ b/runtime/vm/debugger_api_impl.cc
@@ -445,10 +445,22 @@
}
-DART_EXPORT Dart_Handle Dart_GetStaticFields(Dart_Handle cls_in) {
+DART_EXPORT Dart_Handle Dart_GetStaticFields(Dart_Handle target) {
Isolate* isolate = Isolate::Current();
DARTSCOPE(isolate);
- UNWRAP_AND_CHECK_PARAM(Class, cls, cls_in);
+ const Object& obj = Object::Handle(isolate, Api::UnwrapHandle(target));
+ // For backwards compatibility we allow class objects to be passed in
+ // for now. This needs to be removed once all code that uses class
+ // objects is removed.
+ Class& cls = Class::Handle();
+ if (obj.IsType()) {
+ cls = Type::Cast(obj).type_class();
+ } else if (obj.IsClass()) {
+ cls = Class::Cast(obj).raw();
+ } else {
+ return Api::NewError("%s expects argument 'target' to be a type.",
+ CURRENT_FUNC);
+ }
return Api::NewHandle(isolate, isolate->debugger()->GetStaticFields(cls));
}
diff --git a/runtime/vm/disassembler_arm.cc b/runtime/vm/disassembler_arm.cc
index d3dd288..078d0a3 100644
--- a/runtime/vm/disassembler_arm.cc
+++ b/runtime/vm/disassembler_arm.cc
@@ -458,8 +458,23 @@
ASSERT(STRING_STARTS_WITH(format, "imm12_4"));
immed16 = instr->BkptField();
} else {
- ASSERT(STRING_STARTS_WITH(format, "imm4_12"));
- immed16 = instr->MovwField();
+ ASSERT(format[3] == '4');
+ if (format[5] == 'v') {
+ ASSERT(STRING_STARTS_WITH(format, "imm4_vdup"));
+ int32_t idx = -1;
+ int32_t imm4 = instr->Bits(16, 4);
+ if ((imm4 & 1) != 0) idx = imm4 >> 1;
+ else if ((imm4 & 2) != 0) idx = imm4 >> 2;
+ else if ((imm4 & 4) != 0) idx = imm4 >> 3;
+ buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
+ remaining_size_in_buffer(),
+ "%d",
+ idx);
+ return 9;
+ } else {
+ ASSERT(STRING_STARTS_WITH(format, "imm4_12"));
+ immed16 = instr->MovwField();
+ }
}
buffer_pos_ += OS::SNPrint(current_position_in_buffer(),
remaining_size_in_buffer(),
@@ -1307,6 +1322,56 @@
} else if ((instr->Bits(8, 4) == 13) && (instr->Bit(4) == 1) &&
(instr->Bits(23, 2) == 2) && (instr->Bit(21) == 0)) {
Format(instr, "vmulqs 'qd, 'qn, 'qm");
+ } else if ((instr->Bits(8, 4) == 1) && (instr->Bit(4) == 1) &&
+ (instr->Bits(20, 2) == 0) && (instr->Bits(23, 2) == 2)) {
+ Format(instr, "veorq 'qd, 'qn, 'qm");
+ } else if ((instr->Bits(8, 4) == 1) && (instr->Bit(4) == 1) &&
+ (instr->Bits(20, 2) == 3) && (instr->Bits(23, 2) == 0)) {
+ Format(instr, "vornq 'qd, 'qn, 'qm");
+ } else if ((instr->Bits(8, 4) == 1) && (instr->Bit(4) == 1) &&
+ (instr->Bits(20, 2) == 2) && (instr->Bits(23, 2) == 0)) {
+ if (instr->QmField() == instr->QnField()) {
+ Format(instr, "vmovq 'qd, 'qm");
+ } else {
+ Format(instr, "vorrq 'qd, 'qm");
+ }
+ } else if ((instr->Bits(8, 4) == 12) && (instr->Bit(4) == 0) &&
+ (instr->Bits(20, 2) == 3) && (instr->Bits(23, 2) == 3) &&
+ (instr->Bit(7) == 0)) {
+ int32_t imm4 = instr->Bits(16, 4);
+ if (imm4 & 1) {
+ Format(instr, "vdupb 'qd, 'dm['imm4_vdup]");
+ } else if (imm4 & 2) {
+ Format(instr, "vduph 'qd, 'dm['imm4_vdup]");
+ } else if (imm4 & 4) {
+ Format(instr, "vdupw 'qd, 'dm['imm4_vdup]");
+ } else {
+ Unknown(instr);
+ }
+ } else if ((instr->Bits(8, 4) == 8) && (instr->Bit(4) == 1) &&
+ (instr->Bits(23, 2) == 2)) {
+ Format(instr, "vceqq'sz 'qd, 'qn, 'qm");
+ } else if ((instr->Bits(8, 4) == 14) && (instr->Bit(4) == 0) &&
+ (instr->Bits(20, 2) == 0) && (instr->Bits(23, 2) == 0)) {
+ Format(instr, "vceqqs 'qd, 'qn, 'qm");
+ } else if ((instr->Bits(8, 4) == 3) && (instr->Bit(4) == 1) &&
+ (instr->Bits(23, 2) == 0)) {
+ Format(instr, "vcgeq'sz 'qd, 'qn, 'qm");
+ } else if ((instr->Bits(8, 4) == 3) && (instr->Bit(4) == 1) &&
+ (instr->Bits(23, 2) == 2)) {
+ Format(instr, "vcugeq'sz 'qd, 'qn, 'qm");
+ } else if ((instr->Bits(8, 4) == 14) && (instr->Bit(4) == 0) &&
+ (instr->Bits(20, 2) == 0) && (instr->Bits(23, 2) == 2)) {
+ Format(instr, "vcgeqs 'qd, 'qn, 'qm");
+ } else if ((instr->Bits(8, 4) == 3) && (instr->Bit(4) == 0) &&
+ (instr->Bits(23, 2) == 0)) {
+ Format(instr, "vcgtq'sz 'qd, 'qn, 'qm");
+ } else if ((instr->Bits(8, 4) == 3) && (instr->Bit(4) == 0) &&
+ (instr->Bits(23, 2) == 2)) {
+ Format(instr, "vcugtq'sz 'qd, 'qn, 'qm");
+ } else if ((instr->Bits(8, 4) == 14) && (instr->Bit(4) == 0) &&
+ (instr->Bits(20, 2) == 2) && (instr->Bits(23, 2) == 2)) {
+ Format(instr, "vcgtqs 'qd, 'qn, 'qm");
} else {
Unknown(instr);
}
diff --git a/runtime/vm/flow_graph_compiler.h b/runtime/vm/flow_graph_compiler.h
index 55fc965..8ee48ca 100644
--- a/runtime/vm/flow_graph_compiler.h
+++ b/runtime/vm/flow_graph_compiler.h
@@ -95,6 +95,8 @@
void StoreObject(const Address& dst, const Object& obj);
void Exchange(Register reg, const Address& mem);
void Exchange(const Address& mem1, const Address& mem2);
+ void Exchange(Register reg, intptr_t stack_offset);
+ void Exchange(intptr_t stack_offset1, intptr_t stack_offset2);
FlowGraphCompiler* compiler_;
@@ -467,7 +469,7 @@
void EmitFrameEntry();
- void EmitTrySyncMove(Address dest, Location loc, bool* push_emitted);
+ void EmitTrySyncMove(intptr_t dest_offset, Location loc, bool* push_emitted);
void AddStaticCallTarget(const Function& function);
diff --git a/runtime/vm/flow_graph_compiler_arm.cc b/runtime/vm/flow_graph_compiler_arm.cc
index 82deb39..01b166f 100644
--- a/runtime/vm/flow_graph_compiler_arm.cc
+++ b/runtime/vm/flow_graph_compiler_arm.cc
@@ -735,10 +735,7 @@
}
-// TODO(regis): Pass an offset instead of an Address to avoid addressing
-// mode restrictions and remove Operand::Equals() on IA32/X64 and
-// Address::Equals() on ARM/MIPS.
-void FlowGraphCompiler::EmitTrySyncMove(Address dest,
+void FlowGraphCompiler::EmitTrySyncMove(intptr_t dest_offset,
Location loc,
bool* push_emitted) {
if (loc.IsConstant()) {
@@ -747,23 +744,23 @@
*push_emitted = true;
}
__ LoadObject(R0, loc.constant());
- __ str(R0, dest);
+ __ StoreToOffset(kWord, R0, FP, dest_offset);
} else if (loc.IsRegister()) {
if (*push_emitted && (loc.reg() == R0)) {
__ ldr(R0, Address(SP, 0));
- __ str(R0, dest);
+ __ StoreToOffset(kWord, R0, FP, dest_offset);
} else {
- __ str(loc.reg(), dest);
+ __ StoreToOffset(kWord, loc.reg(), FP, dest_offset);
}
} else {
- Address src = loc.ToStackSlotAddress();
- if (!src.Equals(dest)) {
+ const intptr_t src_offset = loc.ToStackSlotOffset();
+ if (src_offset != dest_offset) {
if (!*push_emitted) {
__ Push(R0);
*push_emitted = true;
}
- __ ldr(R0, src);
- __ str(R0, dest);
+ __ LoadFromOffset(kWord, R0, FP, src_offset);
+ __ StoreToOffset(kWord, R0, FP, dest_offset);
}
}
}
@@ -784,8 +781,7 @@
for (; i < num_non_copied_params; ++i) {
if ((*idefs)[i]->IsConstant()) continue; // Common constants
Location loc = env->LocationAt(i);
- Address dest(FP, (param_base - i) * kWordSize);
- EmitTrySyncMove(dest, loc, &push_emitted);
+ EmitTrySyncMove((param_base - i) * kWordSize, loc, &push_emitted);
}
// Process locals. Skip exception_var and stacktrace_var.
@@ -797,8 +793,7 @@
if (i == ex_idx || i == st_idx) continue;
if ((*idefs)[i]->IsConstant()) continue;
Location loc = env->LocationAt(i);
- Address dest(FP, (local_base - i) * kWordSize);
- EmitTrySyncMove(dest, loc, &push_emitted);
+ EmitTrySyncMove((local_base - i) * kWordSize, loc, &push_emitted);
// Update safepoint bitmap to indicate that the target location
// now contains a pointer.
instr->locs()->stack_bitmap()->Set(i - num_non_copied_params, true);
@@ -1703,41 +1698,69 @@
__ mov(destination.reg(), ShifterOperand(source.reg()));
} else {
ASSERT(destination.IsStackSlot());
- __ str(source.reg(), destination.ToStackSlotAddress());
+ const intptr_t dest_offset = destination.ToStackSlotOffset();
+ __ StoreToOffset(kWord, source.reg(), FP, dest_offset);
}
} else if (source.IsStackSlot()) {
if (destination.IsRegister()) {
- __ ldr(destination.reg(), source.ToStackSlotAddress());
+ const intptr_t source_offset = source.ToStackSlotOffset();
+ __ LoadFromOffset(kWord, destination.reg(), FP, source_offset);
} else {
ASSERT(destination.IsStackSlot());
- MoveMemoryToMemory(destination.ToStackSlotAddress(),
- source.ToStackSlotAddress());
+ const intptr_t source_offset = source.ToStackSlotOffset();
+ const intptr_t dest_offset = destination.ToStackSlotOffset();
+ __ LoadFromOffset(kWord, TMP, FP, source_offset);
+ __ StoreToOffset(kWord, TMP, FP, dest_offset);
}
} else if (source.IsFpuRegister()) {
if (destination.IsFpuRegister()) {
- DRegister dst = EvenDRegisterOf(destination.fpu_reg());
- DRegister src = EvenDRegisterOf(source.fpu_reg());
- __ vmovd(dst, src);
+ __ vmovq(destination.fpu_reg(), source.fpu_reg());
} else {
if (destination.IsDoubleStackSlot()) {
+ const intptr_t dest_offset = destination.ToStackSlotOffset();
DRegister src = EvenDRegisterOf(source.fpu_reg());
- __ vstrd(src, destination.ToStackSlotAddress());
+ __ StoreDToOffset(src, FP, dest_offset);
} else {
ASSERT(destination.IsQuadStackSlot());
- UNIMPLEMENTED();
+ const intptr_t dest_offset = destination.ToStackSlotOffset();
+ DRegister dsrc0 = EvenDRegisterOf(source.fpu_reg());
+ DRegister dsrc1 = OddDRegisterOf(source.fpu_reg());
+ // TODO(zra): Write and use {Load,Store}Q{From,To}Offset(), which can
+ // use a single vld1/vst1 instruction.
+ __ StoreDToOffset(dsrc0, FP, dest_offset);
+ __ StoreDToOffset(dsrc1, FP, dest_offset + 2*kWordSize);
}
}
} else if (source.IsDoubleStackSlot()) {
if (destination.IsFpuRegister()) {
+ const intptr_t dest_offset = source.ToStackSlotOffset();
DRegister dst = EvenDRegisterOf(destination.fpu_reg());
- __ vldrd(dst, source.ToStackSlotAddress());
+ __ LoadDFromOffset(dst, FP, dest_offset);
} else {
ASSERT(destination.IsDoubleStackSlot());
- __ vldrd(DTMP, source.ToStackSlotAddress());
- __ vstrd(DTMP, destination.ToStackSlotAddress());
+ const intptr_t source_offset = source.ToStackSlotOffset();
+ const intptr_t dest_offset = destination.ToStackSlotOffset();
+ __ LoadDFromOffset(DTMP, FP, source_offset);
+ __ StoreDToOffset(DTMP, FP, dest_offset);
}
} else if (source.IsQuadStackSlot()) {
- UNIMPLEMENTED();
+ if (destination.IsFpuRegister()) {
+ const intptr_t dest_offset = source.ToStackSlotOffset();
+ DRegister dst0 = EvenDRegisterOf(destination.fpu_reg());
+ DRegister dst1 = OddDRegisterOf(destination.fpu_reg());
+ __ LoadDFromOffset(dst0, FP, dest_offset);
+ __ LoadDFromOffset(dst1, FP, dest_offset + 2*kWordSize);
+ } else {
+ ASSERT(destination.IsQuadStackSlot());
+ const intptr_t source_offset = source.ToStackSlotOffset();
+ const intptr_t dest_offset = destination.ToStackSlotOffset();
+ DRegister dtmp0 = DTMP;
+ DRegister dtmp1 = OddDRegisterOf(QTMP);
+ __ LoadDFromOffset(dtmp0, FP, source_offset);
+ __ LoadDFromOffset(dtmp1, FP, source_offset + 2*kWordSize);
+ __ StoreDToOffset(dtmp0, FP, dest_offset);
+ __ StoreDToOffset(dtmp1, FP, dest_offset + 2*kWordSize);
+ }
} else {
ASSERT(source.IsConstant());
if (destination.IsRegister()) {
@@ -1745,7 +1768,9 @@
__ LoadObject(destination.reg(), constant);
} else {
ASSERT(destination.IsStackSlot());
- StoreObject(destination.ToStackSlotAddress(), source.constant());
+ const intptr_t dest_offset = destination.ToStackSlotOffset();
+ __ LoadObject(TMP, source.constant());
+ __ StoreToOffset(kWord, TMP, FP, dest_offset);
}
}
@@ -1765,11 +1790,11 @@
__ mov(source.reg(), ShifterOperand(destination.reg()));
__ mov(destination.reg(), ShifterOperand(IP));
} else if (source.IsRegister() && destination.IsStackSlot()) {
- Exchange(source.reg(), destination.ToStackSlotAddress());
+ Exchange(source.reg(), destination.ToStackSlotOffset());
} else if (source.IsStackSlot() && destination.IsRegister()) {
- Exchange(destination.reg(), source.ToStackSlotAddress());
+ Exchange(destination.reg(), source.ToStackSlotOffset());
} else if (source.IsStackSlot() && destination.IsStackSlot()) {
- Exchange(destination.ToStackSlotAddress(), source.ToStackSlotAddress());
+ Exchange(source.ToStackSlotOffset(), destination.ToStackSlotOffset());
} else if (source.IsFpuRegister() && destination.IsFpuRegister()) {
DRegister dst = EvenDRegisterOf(destination.fpu_reg());
DRegister src = EvenDRegisterOf(source.fpu_reg());
@@ -1786,27 +1811,27 @@
QRegister qreg = source.IsFpuRegister() ? source.fpu_reg()
: destination.fpu_reg();
DRegister reg = EvenDRegisterOf(qreg);
- const Address& slot_address = source.IsFpuRegister()
- ? destination.ToStackSlotAddress()
- : source.ToStackSlotAddress();
+ const intptr_t slot_offset = source.IsFpuRegister()
+ ? destination.ToStackSlotOffset()
+ : source.ToStackSlotOffset();
if (double_width) {
- __ vldrd(DTMP, slot_address);
- __ vstrd(reg, slot_address);
+ __ LoadDFromOffset(DTMP, FP, slot_offset);
+ __ StoreDToOffset(reg, FP, slot_offset);
__ vmovd(reg, DTMP);
} else {
UNIMPLEMENTED();
}
} else if (source.IsDoubleStackSlot() && destination.IsDoubleStackSlot()) {
- const Address& source_slot_address = source.ToStackSlotAddress();
- const Address& destination_slot_address = destination.ToStackSlotAddress();
+ const intptr_t source_offset = source.ToStackSlotOffset();
+ const intptr_t dest_offset = destination.ToStackSlotOffset();
ScratchFpuRegisterScope ensure_scratch(this, QTMP);
DRegister scratch = EvenDRegisterOf(ensure_scratch.reg());
- __ vldrd(DTMP, source_slot_address);
- __ vldrd(scratch, destination_slot_address);
- __ vstrd(DTMP, destination_slot_address);
- __ vstrd(scratch, source_slot_address);
+ __ LoadDFromOffset(DTMP, FP, source_offset);
+ __ LoadDFromOffset(scratch, FP, dest_offset);
+ __ StoreDToOffset(DTMP, FP, dest_offset);
+ __ StoreDToOffset(scratch, FP, source_offset);
} else if (source.IsQuadStackSlot() && destination.IsQuadStackSlot()) {
UNIMPLEMENTED();
} else {
@@ -1844,20 +1869,34 @@
}
+// Do not call or implement this function. Instead, use the form below that
+// uses an offset from the frame pointer instead of an Address.
void ParallelMoveResolver::Exchange(Register reg, const Address& mem) {
- ASSERT(reg != IP);
- __ mov(IP, ShifterOperand(reg));
- __ ldr(reg, mem);
- __ str(IP, mem);
+ UNREACHABLE();
}
+// Do not call or implement this function. Instead, use the form below that
+// uses offsets from the frame pointer instead of Addresses.
void ParallelMoveResolver::Exchange(const Address& mem1, const Address& mem2) {
+ UNREACHABLE();
+}
+
+
+void ParallelMoveResolver::Exchange(Register reg, intptr_t stack_offset) {
+ __ mov(TMP, ShifterOperand(reg));
+ __ LoadFromOffset(kWord, reg, FP, stack_offset);
+ __ StoreToOffset(kWord, TMP, FP, stack_offset);
+}
+
+
+void ParallelMoveResolver::Exchange(intptr_t stack_offset1,
+ intptr_t stack_offset2) {
ScratchRegisterScope ensure_scratch(this, IP);
- __ ldr(ensure_scratch.reg(), mem1);
- __ ldr(IP, mem2);
- __ str(ensure_scratch.reg(), mem2);
- __ str(IP, mem1);
+ __ LoadFromOffset(kWord, ensure_scratch.reg(), FP, stack_offset1);
+ __ LoadFromOffset(kWord, TMP, FP, stack_offset2);
+ __ StoreToOffset(kWord, ensure_scratch.reg(), FP, stack_offset2);
+ __ StoreToOffset(kWord, TMP, FP, stack_offset1);
}
diff --git a/runtime/vm/flow_graph_compiler_ia32.cc b/runtime/vm/flow_graph_compiler_ia32.cc
index eab9bcf..6683c36 100644
--- a/runtime/vm/flow_graph_compiler_ia32.cc
+++ b/runtime/vm/flow_graph_compiler_ia32.cc
@@ -756,9 +756,10 @@
}
-void FlowGraphCompiler::EmitTrySyncMove(Address dest,
+void FlowGraphCompiler::EmitTrySyncMove(intptr_t dest_offset,
Location loc,
bool* push_emitted) {
+ const Address dest(EBP, dest_offset);
if (loc.IsConstant()) {
if (!*push_emitted) {
__ pushl(EAX);
@@ -802,8 +803,7 @@
for (; i < num_non_copied_params; ++i) {
if ((*idefs)[i]->IsConstant()) continue; // Common constants
Location loc = env->LocationAt(i);
- Address dest(EBP, (param_base - i) * kWordSize);
- EmitTrySyncMove(dest, loc, &push_emitted);
+ EmitTrySyncMove((param_base - i) * kWordSize, loc, &push_emitted);
}
// Process locals. Skip exception_var and stacktrace_var.
@@ -815,8 +815,7 @@
if (i == ex_idx || i == st_idx) continue;
if ((*idefs)[i]->IsConstant()) continue;
Location loc = env->LocationAt(i);
- Address dest(EBP, (local_base - i) * kWordSize);
- EmitTrySyncMove(dest, loc, &push_emitted);
+ EmitTrySyncMove((local_base - i) * kWordSize, loc, &push_emitted);
// Update safepoint bitmap to indicate that the target location
// now contains a pointer.
instr->locs()->stack_bitmap()->Set(i - num_non_copied_params, true);
@@ -1901,6 +1900,17 @@
}
+void ParallelMoveResolver::Exchange(Register reg, intptr_t stack_offset) {
+ UNREACHABLE();
+}
+
+
+void ParallelMoveResolver::Exchange(intptr_t stack_offset1,
+ intptr_t stack_offset2) {
+ UNREACHABLE();
+}
+
+
void ParallelMoveResolver::SpillScratch(Register reg) {
__ pushl(reg);
}
diff --git a/runtime/vm/flow_graph_compiler_mips.cc b/runtime/vm/flow_graph_compiler_mips.cc
index 114c060..2a5f44f 100644
--- a/runtime/vm/flow_graph_compiler_mips.cc
+++ b/runtime/vm/flow_graph_compiler_mips.cc
@@ -762,7 +762,7 @@
// TODO(regis): Pass an offset instead of an Address to avoid addressing
// mode restrictions and remove Operand::Equals() on IA32/X64 and
// Address::Equals() on ARM/MIPS.
-void FlowGraphCompiler::EmitTrySyncMove(Address dest,
+void FlowGraphCompiler::EmitTrySyncMove(intptr_t dest_offset,
Location loc,
bool* push_emitted) {
if (loc.IsConstant()) {
@@ -771,23 +771,23 @@
*push_emitted = true;
}
__ LoadObject(T0, loc.constant());
- __ sw(T0, dest);
+ __ StoreToOffset(T0, FP, dest_offset);
} else if (loc.IsRegister()) {
if (*push_emitted && loc.reg() == T0) {
__ lw(T0, Address(SP, 0));
- __ sw(T0, dest);
+ __ StoreToOffset(T0, FP, dest_offset);
} else {
- __ sw(loc.reg(), dest);
+ __ StoreToOffset(loc.reg(), FP, dest_offset);
}
} else {
- Address src = loc.ToStackSlotAddress();
- if (!src.Equals(dest)) {
+ const intptr_t src_offset = loc.ToStackSlotOffset();
+ if (src_offset != dest_offset) {
if (!*push_emitted) {
__ Push(T0);
*push_emitted = true;
}
- __ lw(T0, src);
- __ sw(T0, dest);
+ __ LoadFromOffset(T0, FP, src_offset);
+ __ StoreToOffset(T0, FP, dest_offset);
}
}
}
@@ -808,8 +808,7 @@
for (; i < num_non_copied_params; ++i) {
if ((*idefs)[i]->IsConstant()) continue; // Common constants
Location loc = env->LocationAt(i);
- Address dest(FP, (param_base - i) * kWordSize);
- EmitTrySyncMove(dest, loc, &push_emitted);
+ EmitTrySyncMove((param_base - i) * kWordSize, loc, &push_emitted);
}
// Process locals. Skip exception_var and stacktrace_var.
@@ -821,8 +820,7 @@
if (i == ex_idx || i == st_idx) continue;
if ((*idefs)[i]->IsConstant()) continue;
Location loc = env->LocationAt(i);
- Address dest(FP, (local_base - i) * kWordSize);
- EmitTrySyncMove(dest, loc, &push_emitted);
+ EmitTrySyncMove((local_base - i) * kWordSize, loc, &push_emitted);
// Update safepoint bitmap to indicate that the target location
// now contains a pointer.
instr->locs()->stack_bitmap()->Set(i - num_non_copied_params, true);
@@ -1807,34 +1805,40 @@
void ParallelMoveResolver::EmitMove(int index) {
- __ TraceSimMsg("ParallelMoveResolver::EmitMove");
MoveOperands* move = moves_[index];
const Location source = move->src();
const Location destination = move->dest();
+ __ TraceSimMsg("ParallelMoveResolver::EmitMove");
if (source.IsRegister()) {
if (destination.IsRegister()) {
__ mov(destination.reg(), source.reg());
} else {
ASSERT(destination.IsStackSlot());
- __ sw(source.reg(), destination.ToStackSlotAddress());
+ const intptr_t dest_offset = destination.ToStackSlotOffset();
+ __ StoreToOffset(source.reg(), FP, dest_offset);
}
} else if (source.IsStackSlot()) {
if (destination.IsRegister()) {
- __ lw(destination.reg(), source.ToStackSlotAddress());
+ const intptr_t source_offset = source.ToStackSlotOffset();
+ __ LoadFromOffset(destination.reg(), FP, source_offset);
} else {
ASSERT(destination.IsStackSlot());
- MoveMemoryToMemory(destination.ToStackSlotAddress(),
- source.ToStackSlotAddress());
+ const intptr_t source_offset = source.ToStackSlotOffset();
+ const intptr_t dest_offset = destination.ToStackSlotOffset();
+ __ LoadFromOffset(TMP, FP, source_offset);
+ __ StoreToOffset(TMP, FP, dest_offset);
}
} else if (source.IsFpuRegister()) {
if (destination.IsFpuRegister()) {
- __ movd(destination.fpu_reg(), source.fpu_reg());
+ DRegister dst = destination.fpu_reg();
+ DRegister src = source.fpu_reg();
+ __ movd(dst, src);
} else {
if (destination.IsDoubleStackSlot()) {
- const Address& addr = destination.ToStackSlotAddress();
- int32_t offset = addr.offset();
- __ StoreDToOffset(source.fpu_reg(), FP, offset);
+ const intptr_t dest_offset = destination.ToStackSlotOffset();
+ DRegister src = source.fpu_reg();
+ __ StoreDToOffset(src, FP, dest_offset);
} else {
ASSERT(destination.IsQuadStackSlot());
UNIMPLEMENTED();
@@ -1842,18 +1846,15 @@
}
} else if (source.IsDoubleStackSlot()) {
if (destination.IsFpuRegister()) {
- const Address &addr = source.ToStackSlotAddress();
- const Register base = addr.base();
- const int32_t offset = addr.offset();
- __ LoadDFromOffset(destination.fpu_reg(), base, offset);
+ const intptr_t dest_offset = source.ToStackSlotOffset();
+ DRegister dst = destination.fpu_reg();
+ __ LoadDFromOffset(dst, FP, dest_offset);
} else {
ASSERT(destination.IsDoubleStackSlot());
- const Address& saddr = source.ToStackSlotAddress();
- const Address& daddr = destination.ToStackSlotAddress();
- int32_t soffset = saddr.offset();
- int32_t doffset = daddr.offset();
- __ LoadDFromOffset(FpuTMP, FP, soffset);
- __ StoreDToOffset(FpuTMP, FP, doffset);
+ const intptr_t source_offset = source.ToStackSlotOffset();
+ const intptr_t dest_offset = destination.ToStackSlotOffset();
+ __ LoadDFromOffset(DTMP, FP, source_offset);
+ __ StoreDToOffset(DTMP, FP, dest_offset);
}
} else if (source.IsQuadStackSlot()) {
UNIMPLEMENTED();
@@ -1864,7 +1865,9 @@
__ LoadObject(destination.reg(), constant);
} else {
ASSERT(destination.IsStackSlot());
- StoreObject(destination.ToStackSlotAddress(), source.constant());
+ const intptr_t dest_offset = destination.ToStackSlotOffset();
+ __ LoadObject(TMP, source.constant());
+ __ StoreToOffset(TMP, FP, dest_offset);
}
}
@@ -1873,27 +1876,28 @@
void ParallelMoveResolver::EmitSwap(int index) {
- __ TraceSimMsg("ParallelMoveResolver::EmitSwap");
MoveOperands* move = moves_[index];
const Location source = move->src();
const Location destination = move->dest();
if (source.IsRegister() && destination.IsRegister()) {
- ASSERT(source.reg() != TMP1);
- ASSERT(destination.reg() != TMP1);
- __ mov(TMP1, source.reg());
+ ASSERT(source.reg() != TMP);
+ ASSERT(destination.reg() != TMP);
+ __ mov(TMP, source.reg());
__ mov(source.reg(), destination.reg());
- __ mov(destination.reg(), TMP1);
+ __ mov(destination.reg(), TMP);
} else if (source.IsRegister() && destination.IsStackSlot()) {
- Exchange(source.reg(), destination.ToStackSlotAddress());
+ Exchange(source.reg(), destination.ToStackSlotOffset());
} else if (source.IsStackSlot() && destination.IsRegister()) {
- Exchange(destination.reg(), source.ToStackSlotAddress());
+ Exchange(destination.reg(), source.ToStackSlotOffset());
} else if (source.IsStackSlot() && destination.IsStackSlot()) {
- Exchange(destination.ToStackSlotAddress(), source.ToStackSlotAddress());
+ Exchange(source.ToStackSlotOffset(), destination.ToStackSlotOffset());
} else if (source.IsFpuRegister() && destination.IsFpuRegister()) {
- __ movd(FpuTMP, source.fpu_reg());
- __ movd(source.fpu_reg(), destination.fpu_reg());
- __ movd(destination.fpu_reg(), FpuTMP);
+ DRegister dst = destination.fpu_reg();
+ DRegister src = source.fpu_reg();
+ __ movd(DTMP, src);
+ __ movd(src, dst);
+ __ movd(dst, DTMP);
} else if (source.IsFpuRegister() || destination.IsFpuRegister()) {
ASSERT(destination.IsDoubleStackSlot() ||
destination.IsQuadStackSlot() ||
@@ -1903,32 +1907,27 @@
source.IsDoubleStackSlot();
DRegister reg = source.IsFpuRegister() ? source.fpu_reg()
: destination.fpu_reg();
- const Address& slot_address = source.IsFpuRegister()
- ? destination.ToStackSlotAddress()
- : source.ToStackSlotAddress();
+ const intptr_t slot_offset = source.IsFpuRegister()
+ ? destination.ToStackSlotOffset()
+ : source.ToStackSlotOffset();
if (double_width) {
- const Register base = slot_address.base();
- const int32_t offset = slot_address.offset();
- __ LoadDFromOffset(FpuTMP, base, offset);
- __ StoreDToOffset(reg, base, offset);
- __ movd(reg, FpuTMP);
+ __ LoadDFromOffset(DTMP, FP, slot_offset);
+ __ StoreDToOffset(reg, FP, slot_offset);
+ __ movd(reg, DTMP);
} else {
UNIMPLEMENTED();
}
} else if (source.IsDoubleStackSlot() && destination.IsDoubleStackSlot()) {
- const Address& source_slot_address = source.ToStackSlotAddress();
- const Address& destination_slot_address = destination.ToStackSlotAddress();
- const Register sbase = source_slot_address.base();
- const int32_t soffset = source_slot_address.offset();
- const Register dbase = destination_slot_address.base();
- const int32_t doffset = destination_slot_address.offset();
+ const intptr_t source_offset = source.ToStackSlotOffset();
+ const intptr_t dest_offset = destination.ToStackSlotOffset();
- ScratchFpuRegisterScope ensure_scratch(this, FpuTMP);
- __ LoadDFromOffset(FpuTMP, sbase, soffset);
- __ LoadDFromOffset(ensure_scratch.reg(), dbase, doffset);
- __ StoreDToOffset(FpuTMP, dbase, doffset);
- __ StoreDToOffset(ensure_scratch.reg(), sbase, soffset);
+ ScratchFpuRegisterScope ensure_scratch(this, DTMP);
+ DRegister scratch = ensure_scratch.reg();
+ __ LoadDFromOffset(DTMP, FP, source_offset);
+ __ LoadDFromOffset(scratch, FP, dest_offset);
+ __ StoreDToOffset(DTMP, FP, dest_offset);
+ __ StoreDToOffset(scratch, FP, source_offset);
} else if (source.IsQuadStackSlot() && destination.IsQuadStackSlot()) {
UNIMPLEMENTED();
} else {
@@ -1968,22 +1967,34 @@
}
+// Do not call or implement this function. Instead, use the form below that
+// uses an offset from the frame pointer instead of an Address.
void ParallelMoveResolver::Exchange(Register reg, const Address& mem) {
- __ TraceSimMsg("ParallelMoveResolver::Exchange ra");
- ASSERT(reg != TMP1);
- __ mov(TMP1, reg);
- __ lw(reg, mem);
- __ sw(TMP1, mem);
+ UNREACHABLE();
}
+// Do not call or implement this function. Instead, use the form below that
+// uses offsets from the frame pointer instead of Addresses.
void ParallelMoveResolver::Exchange(const Address& mem1, const Address& mem2) {
- __ TraceSimMsg("ParallelMoveResolver::Exchange aa");
- ScratchRegisterScope ensure_scratch(this, TMP1);
- __ lw(ensure_scratch.reg(), mem1);
- __ lw(TMP1, mem2);
- __ sw(ensure_scratch.reg(), mem2);
- __ sw(TMP1, mem1);
+ UNREACHABLE();
+}
+
+
+void ParallelMoveResolver::Exchange(Register reg, intptr_t stack_offset) {
+ __ mov(TMP, reg);
+ __ LoadFromOffset(reg, FP, stack_offset);
+ __ StoreToOffset(TMP, FP, stack_offset);
+}
+
+
+void ParallelMoveResolver::Exchange(intptr_t stack_offset1,
+ intptr_t stack_offset2) {
+ ScratchRegisterScope ensure_scratch(this, TMP);
+ __ LoadFromOffset(ensure_scratch.reg(), FP, stack_offset1);
+ __ LoadFromOffset(TMP, FP, stack_offset2);
+ __ StoreToOffset(ensure_scratch.reg(), FP, stack_offset2);
+ __ StoreToOffset(TMP, FP, stack_offset1);
}
diff --git a/runtime/vm/flow_graph_compiler_x64.cc b/runtime/vm/flow_graph_compiler_x64.cc
index b2f730c..22e25a9 100644
--- a/runtime/vm/flow_graph_compiler_x64.cc
+++ b/runtime/vm/flow_graph_compiler_x64.cc
@@ -749,9 +749,10 @@
}
-void FlowGraphCompiler::EmitTrySyncMove(Address dest,
+void FlowGraphCompiler::EmitTrySyncMove(intptr_t dest_offset,
Location loc,
bool* push_emitted) {
+ const Address dest(RBP, dest_offset);
if (loc.IsConstant()) {
if (!*push_emitted) {
__ pushq(RAX);
@@ -794,8 +795,7 @@
for (; i < num_non_copied_params; ++i) {
if ((*idefs)[i]->IsConstant()) continue; // Common constants
Location loc = env->LocationAt(i);
- Address dest(RBP, (param_base - i) * kWordSize);
- EmitTrySyncMove(dest, loc, &push_emitted);
+ EmitTrySyncMove((param_base - i) * kWordSize, loc, &push_emitted);
}
// Process locals. Skip exception_var and stacktrace_var.
@@ -807,8 +807,7 @@
if (i == ex_idx || i == st_idx) continue;
if ((*idefs)[i]->IsConstant()) continue;
Location loc = env->LocationAt(i);
- Address dest(RBP, (local_base - i) * kWordSize);
- EmitTrySyncMove(dest, loc, &push_emitted);
+ EmitTrySyncMove((local_base - i) * kWordSize, loc, &push_emitted);
// Update safepoint bitmap to indicate that the target location
// now contains a pointer.
instr->locs()->stack_bitmap()->Set(i - num_non_copied_params, true);
@@ -1880,6 +1879,17 @@
}
+void ParallelMoveResolver::Exchange(Register reg, intptr_t stack_offset) {
+ UNREACHABLE();
+}
+
+
+void ParallelMoveResolver::Exchange(intptr_t stack_offset1,
+ intptr_t stack_offset2) {
+ UNREACHABLE();
+}
+
+
void ParallelMoveResolver::SpillScratch(Register reg) {
__ pushq(reg);
}
diff --git a/runtime/vm/intermediate_language_arm.cc b/runtime/vm/intermediate_language_arm.cc
index ae18cca..87fba15 100644
--- a/runtime/vm/intermediate_language_arm.cc
+++ b/runtime/vm/intermediate_language_arm.cc
@@ -56,7 +56,8 @@
__ PushObject(value.constant());
} else {
ASSERT(value.IsStackSlot());
- __ ldr(IP, value.ToStackSlotAddress());
+ const intptr_t value_offset = value.ToStackSlotOffset();
+ __ LoadFromOffset(kWord, IP, FP, value_offset);
__ Push(IP);
}
}
@@ -1203,7 +1204,9 @@
if ((representation() == kUnboxedDouble) ||
(representation() == kUnboxedMint) ||
(representation() == kUnboxedFloat32x4)) {
- DRegister result = EvenDRegisterOf(locs()->out().fpu_reg());
+ QRegister result = locs()->out().fpu_reg();
+ DRegister dresult0 = EvenDRegisterOf(result);
+ DRegister dresult1 = OddDRegisterOf(result);
switch (class_id()) {
case kTypedDataInt32ArrayCid:
UNIMPLEMENTED();
@@ -1217,16 +1220,18 @@
__ add(index.reg(), index.reg(), ShifterOperand(array));
element_address = Address(index.reg(), 0);
__ vldrs(STMP, element_address);
- __ vcvtds(result, STMP);
+ __ vcvtds(dresult0, STMP);
break;
case kTypedDataFloat64ArrayCid:
// vldrd does not support indexed addressing.
__ add(index.reg(), index.reg(), ShifterOperand(array));
element_address = Address(index.reg(), 0);
- __ vldrd(result, element_address);
+ __ vldrd(dresult0, element_address);
break;
case kTypedDataFloat32x4ArrayCid:
- UNIMPLEMENTED();
+ __ add(index.reg(), index.reg(), ShifterOperand(array));
+ __ LoadDFromOffset(dresult0, index.reg(), 0);
+ __ LoadDFromOffset(dresult1, index.reg(), 2*kWordSize);
break;
}
return;
@@ -1485,9 +1490,15 @@
__ StoreDToOffset(in2, index.reg(), 0);
break;
}
- case kTypedDataFloat32x4ArrayCid:
- UNIMPLEMENTED();
+ case kTypedDataFloat32x4ArrayCid: {
+ QRegister in = locs()->in(2).fpu_reg();
+ DRegister din0 = EvenDRegisterOf(in);
+ DRegister din1 = OddDRegisterOf(in);
+ __ add(index.reg(), index.reg(), ShifterOperand(array));
+ __ StoreDToOffset(din0, index.reg(), 0);
+ __ StoreDToOffset(din1, index.reg(), 2*kWordSize);
break;
+ }
default:
UNREACHABLE();
}
@@ -2668,46 +2679,211 @@
LocationSummary* BoxFloat32x4Instr::MakeLocationSummary() const {
- UNIMPLEMENTED();
- return NULL;
+ const intptr_t kNumInputs = 1;
+ const intptr_t kNumTemps = 0;
+ LocationSummary* summary =
+ new LocationSummary(kNumInputs,
+ kNumTemps,
+ LocationSummary::kCallOnSlowPath);
+ summary->set_in(0, Location::RequiresFpuRegister());
+ summary->set_out(Location::RequiresRegister());
+ return summary;
}
+class BoxFloat32x4SlowPath : public SlowPathCode {
+ public:
+ explicit BoxFloat32x4SlowPath(BoxFloat32x4Instr* instruction)
+ : instruction_(instruction) { }
+
+ virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
+ __ Comment("BoxFloat32x4SlowPath");
+ __ Bind(entry_label());
+ const Class& float32x4_class = compiler->float32x4_class();
+ const Code& stub =
+ Code::Handle(StubCode::GetAllocationStubForClass(float32x4_class));
+ const ExternalLabel label(float32x4_class.ToCString(), stub.EntryPoint());
+
+ LocationSummary* locs = instruction_->locs();
+ locs->live_registers()->Remove(locs->out());
+
+ compiler->SaveLiveRegisters(locs);
+ compiler->GenerateCall(Scanner::kDummyTokenIndex, // No token position.
+ &label,
+ PcDescriptors::kOther,
+ locs);
+ __ mov(locs->out().reg(), ShifterOperand(R0));
+ compiler->RestoreLiveRegisters(locs);
+
+ __ b(exit_label());
+ }
+
+ private:
+ BoxFloat32x4Instr* instruction_;
+};
+
+
void BoxFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
- UNIMPLEMENTED();
+ BoxFloat32x4SlowPath* slow_path = new BoxFloat32x4SlowPath(this);
+ compiler->AddSlowPathCode(slow_path);
+
+ Register out_reg = locs()->out().reg();
+ QRegister value = locs()->in(0).fpu_reg();
+ DRegister value_even = EvenDRegisterOf(value);
+ DRegister value_odd = OddDRegisterOf(value);
+
+ __ TryAllocate(compiler->float32x4_class(),
+ slow_path->entry_label(),
+ out_reg);
+ __ Bind(slow_path->exit_label());
+
+ __ StoreDToOffset(value_even, out_reg,
+ Float32x4::value_offset() - kHeapObjectTag);
+ __ StoreDToOffset(value_odd, out_reg,
+ Float32x4::value_offset() + 2*kWordSize - kHeapObjectTag);
}
LocationSummary* UnboxFloat32x4Instr::MakeLocationSummary() const {
- UNIMPLEMENTED();
- return NULL;
+ const intptr_t value_cid = value()->Type()->ToCid();
+ const intptr_t kNumInputs = 1;
+ const intptr_t kNumTemps = value_cid == kFloat32x4Cid ? 0 : 1;
+ LocationSummary* summary =
+ new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
+ summary->set_in(0, Location::RequiresRegister());
+ if (kNumTemps > 0) {
+ ASSERT(kNumTemps == 1);
+ summary->set_temp(0, Location::RequiresRegister());
+ }
+ summary->set_out(Location::RequiresFpuRegister());
+ return summary;
}
void UnboxFloat32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
- UNIMPLEMENTED();
+ const intptr_t value_cid = value()->Type()->ToCid();
+ const Register value = locs()->in(0).reg();
+ const QRegister result = locs()->out().fpu_reg();
+
+ if (value_cid != kFloat32x4Cid) {
+ const Register temp = locs()->temp(0).reg();
+ Label* deopt = compiler->AddDeoptStub(deopt_id_, kDeoptCheckClass);
+ __ tst(value, ShifterOperand(kSmiTagMask));
+ __ b(deopt, EQ);
+ __ CompareClassId(value, kFloat32x4Cid, temp);
+ __ b(deopt, NE);
+ }
+
+ const DRegister result_even = EvenDRegisterOf(result);
+ const DRegister result_odd = OddDRegisterOf(result);
+ __ LoadDFromOffset(result_even, value,
+ Float32x4::value_offset() - kHeapObjectTag);
+ __ LoadDFromOffset(result_odd, value,
+ Float32x4::value_offset() + 2*kWordSize - kHeapObjectTag);
}
LocationSummary* BoxUint32x4Instr::MakeLocationSummary() const {
- UNIMPLEMENTED();
- return NULL;
+ const intptr_t kNumInputs = 1;
+ const intptr_t kNumTemps = 0;
+ LocationSummary* summary =
+ new LocationSummary(kNumInputs,
+ kNumTemps,
+ LocationSummary::kCallOnSlowPath);
+ summary->set_in(0, Location::RequiresFpuRegister());
+ summary->set_out(Location::RequiresRegister());
+ return summary;
}
+class BoxUint32x4SlowPath : public SlowPathCode {
+ public:
+ explicit BoxUint32x4SlowPath(BoxUint32x4Instr* instruction)
+ : instruction_(instruction) { }
+
+ virtual void EmitNativeCode(FlowGraphCompiler* compiler) {
+ __ Comment("BoxUint32x4SlowPath");
+ __ Bind(entry_label());
+ const Class& uint32x4_class = compiler->uint32x4_class();
+ const Code& stub =
+ Code::Handle(StubCode::GetAllocationStubForClass(uint32x4_class));
+ const ExternalLabel label(uint32x4_class.ToCString(), stub.EntryPoint());
+
+ LocationSummary* locs = instruction_->locs();
+ locs->live_registers()->Remove(locs->out());
+
+ compiler->SaveLiveRegisters(locs);
+ compiler->GenerateCall(Scanner::kDummyTokenIndex, // No token position.
+ &label,
+ PcDescriptors::kOther,
+ locs);
+ __ mov(locs->out().reg(), ShifterOperand(R0));
+ compiler->RestoreLiveRegisters(locs);
+
+ __ b(exit_label());
+ }
+
+ private:
+ BoxUint32x4Instr* instruction_;
+};
+
+
void BoxUint32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
- UNIMPLEMENTED();
+ BoxUint32x4SlowPath* slow_path = new BoxUint32x4SlowPath(this);
+ compiler->AddSlowPathCode(slow_path);
+
+ Register out_reg = locs()->out().reg();
+ QRegister value = locs()->in(0).fpu_reg();
+ DRegister value_even = EvenDRegisterOf(value);
+ DRegister value_odd = OddDRegisterOf(value);
+
+ __ TryAllocate(compiler->uint32x4_class(),
+ slow_path->entry_label(),
+ out_reg);
+ __ Bind(slow_path->exit_label());
+ __ StoreDToOffset(value_even, out_reg,
+ Uint32x4::value_offset() - kHeapObjectTag);
+ __ StoreDToOffset(value_odd, out_reg,
+ Uint32x4::value_offset() + 2*kWordSize - kHeapObjectTag);
}
LocationSummary* UnboxUint32x4Instr::MakeLocationSummary() const {
- UNIMPLEMENTED();
- return NULL;
+ const intptr_t value_cid = value()->Type()->ToCid();
+ const intptr_t kNumInputs = 1;
+ const intptr_t kNumTemps = value_cid == kUint32x4Cid ? 0 : 1;
+ LocationSummary* summary =
+ new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
+ summary->set_in(0, Location::RequiresRegister());
+ if (kNumTemps > 0) {
+ ASSERT(kNumTemps == 1);
+ summary->set_temp(0, Location::RequiresRegister());
+ }
+ summary->set_out(Location::RequiresFpuRegister());
+ return summary;
}
void UnboxUint32x4Instr::EmitNativeCode(FlowGraphCompiler* compiler) {
- UNIMPLEMENTED();
+ const intptr_t value_cid = value()->Type()->ToCid();
+ const Register value = locs()->in(0).reg();
+ const QRegister result = locs()->out().fpu_reg();
+
+ if (value_cid != kUint32x4Cid) {
+ const Register temp = locs()->temp(0).reg();
+ Label* deopt = compiler->AddDeoptStub(deopt_id_, kDeoptCheckClass);
+ __ tst(value, ShifterOperand(kSmiTagMask));
+ __ b(deopt, EQ);
+ __ CompareClassId(value, kUint32x4Cid, temp);
+ __ b(deopt, NE);
+ }
+
+ const DRegister result_even = EvenDRegisterOf(result);
+ const DRegister result_odd = OddDRegisterOf(result);
+ __ LoadDFromOffset(result_even, value,
+ Uint32x4::value_offset() - kHeapObjectTag);
+ __ LoadDFromOffset(result_odd, value,
+ Uint32x4::value_offset() + 2*kWordSize - kHeapObjectTag);
}
@@ -2738,57 +2914,159 @@
LocationSummary* BinaryFloat32x4OpInstr::MakeLocationSummary() const {
- UNIMPLEMENTED();
- return NULL;
+ const intptr_t kNumInputs = 2;
+ const intptr_t kNumTemps = 0;
+ LocationSummary* summary =
+ new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
+ summary->set_in(0, Location::RequiresFpuRegister());
+ summary->set_in(1, Location::RequiresFpuRegister());
+ summary->set_out(Location::RequiresFpuRegister());
+ return summary;
}
void BinaryFloat32x4OpInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- UNIMPLEMENTED();
+ QRegister left = locs()->in(0).fpu_reg();
+ QRegister right = locs()->in(1).fpu_reg();
+ QRegister result = locs()->out().fpu_reg();
+
+ switch (op_kind()) {
+ case Token::kADD: __ vaddqs(result, left, right); break;
+ case Token::kSUB: __ vsubqs(result, left, right); break;
+ case Token::kMUL: __ vmulqs(result, left, right); break;
+ // TODO(zra): Two options for division. Either use vdiv piecewise, or do
+ // vrecpeqs followed by vmulqs.
+ case Token::kDIV: UNIMPLEMENTED(); break;
+ default: UNREACHABLE();
+ }
}
LocationSummary* Float32x4ShuffleInstr::MakeLocationSummary() const {
- UNIMPLEMENTED();
- return NULL;
+ const intptr_t kNumInputs = 1;
+ const intptr_t kNumTemps = 0;
+ LocationSummary* summary =
+ new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
+ summary->set_in(0, Location::RequiresFpuRegister());
+ summary->set_out(Location::RequiresFpuRegister());
+ return summary;
}
void Float32x4ShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- UNIMPLEMENTED();
+ QRegister value = locs()->in(0).fpu_reg();
+ QRegister result = locs()->out().fpu_reg();
+ DRegister dresult0 = EvenDRegisterOf(result);
+ SRegister sresult0 = EvenSRegisterOf(dresult0);
+
+ DRegister dvalue0 = EvenDRegisterOf(value);
+ DRegister dvalue1 = OddDRegisterOf(value);
+
+ // For these cases the vdup instruction requires fewer
+ // instructions. For arbitrary shuffles, vtbl will be needed.
+ switch (op_kind()) {
+ case MethodRecognizer::kFloat32x4ShuffleXXXX:
+ __ vdup(kWord, result, dvalue0, 0);
+ break;
+ case MethodRecognizer::kFloat32x4ShuffleYYYY:
+ __ vdup(kWord, result, dvalue0, 1);
+ break;
+ case MethodRecognizer::kFloat32x4ShuffleZZZZ:
+ __ vdup(kWord, result, dvalue1, 0);
+ break;
+ case MethodRecognizer::kFloat32x4ShuffleWWWW:
+ __ vdup(kWord, result, dvalue1, 1);
+ break;
+ case MethodRecognizer::kFloat32x4ShuffleX:
+ __ vdup(kWord, result, dvalue0, 0);
+ __ vcvtds(dresult0, sresult0);
+ break;
+ case MethodRecognizer::kFloat32x4ShuffleY:
+ __ vdup(kWord, result, dvalue0, 1);
+ __ vcvtds(dresult0, sresult0);
+ break;
+ case MethodRecognizer::kFloat32x4ShuffleZ:
+ __ vdup(kWord, result, dvalue1, 0);
+ __ vcvtds(dresult0, sresult0);
+ break;
+ case MethodRecognizer::kFloat32x4ShuffleW:
+ __ vdup(kWord, result, dvalue1, 1);
+ __ vcvtds(dresult0, sresult0);
+ break;
+ default: UNREACHABLE();
+ }
}
LocationSummary* Float32x4ConstructorInstr::MakeLocationSummary() const {
- UNIMPLEMENTED();
- return NULL;
+ const intptr_t kNumInputs = 4;
+ const intptr_t kNumTemps = 0;
+ LocationSummary* summary =
+ new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
+ summary->set_in(0, Location::RequiresFpuRegister());
+ summary->set_in(1, Location::RequiresFpuRegister());
+ summary->set_in(2, Location::RequiresFpuRegister());
+ summary->set_in(3, Location::RequiresFpuRegister());
+ summary->set_out(Location::RequiresFpuRegister());
+ return summary;
}
void Float32x4ConstructorInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- UNIMPLEMENTED();
+ QRegister q0 = locs()->in(0).fpu_reg();
+ QRegister q1 = locs()->in(1).fpu_reg();
+ QRegister q2 = locs()->in(2).fpu_reg();
+ QRegister q3 = locs()->in(3).fpu_reg();
+ QRegister r = locs()->out().fpu_reg();
+
+ DRegister dr0 = EvenDRegisterOf(r);
+ DRegister dr1 = OddDRegisterOf(r);
+
+ __ vcvtsd(EvenSRegisterOf(dr0), EvenDRegisterOf(q0));
+ __ vcvtsd(OddSRegisterOf(dr0), EvenDRegisterOf(q1));
+ __ vcvtsd(EvenSRegisterOf(dr1), EvenDRegisterOf(q2));
+ __ vcvtsd(OddSRegisterOf(dr1), EvenDRegisterOf(q3));
}
LocationSummary* Float32x4ZeroInstr::MakeLocationSummary() const {
- UNIMPLEMENTED();
- return NULL;
+ const intptr_t kNumInputs = 0;
+ const intptr_t kNumTemps = 0;
+ LocationSummary* summary =
+ new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
+ summary->set_out(Location::RequiresFpuRegister());
+ return summary;
}
void Float32x4ZeroInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- UNIMPLEMENTED();
+ QRegister q = locs()->out().fpu_reg();
+ __ veorq(q, q, q);
}
LocationSummary* Float32x4SplatInstr::MakeLocationSummary() const {
- UNIMPLEMENTED();
- return NULL;
+ const intptr_t kNumInputs = 1;
+ const intptr_t kNumTemps = 0;
+ LocationSummary* summary =
+ new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
+ summary->set_in(0, Location::RequiresFpuRegister());
+ summary->set_out(Location::RequiresFpuRegister());
+ return summary;
}
void Float32x4SplatInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
- UNIMPLEMENTED();
+ QRegister value = locs()->in(0).fpu_reg();
+ QRegister result = locs()->out().fpu_reg();
+
+ DRegister dvalue0 = EvenDRegisterOf(value);
+
+ // Convert to Float32.
+ __ vcvtsd(STMP, dvalue0);
+
+ // Splat across all lanes.
+ __ vdup(kWord, result, DTMP, 0);
}
diff --git a/runtime/vm/intermediate_language_mips.cc b/runtime/vm/intermediate_language_mips.cc
index 6f379eb..6b8b215 100644
--- a/runtime/vm/intermediate_language_mips.cc
+++ b/runtime/vm/intermediate_language_mips.cc
@@ -57,7 +57,8 @@
__ PushObject(value.constant());
} else {
ASSERT(value.IsStackSlot());
- __ lw(TMP, value.ToStackSlotAddress());
+ const intptr_t value_offset = value.ToStackSlotOffset();
+ __ LoadFromOffset(TMP, FP, value_offset);
__ Push(TMP);
}
}
diff --git a/runtime/vm/locations.cc b/runtime/vm/locations.cc
index 6d36d4d..23ab978 100644
--- a/runtime/vm/locations.cc
+++ b/runtime/vm/locations.cc
@@ -87,8 +87,6 @@
}
-// TODO(regis): Remove all occurences of Address in the architecture independent
-// portion of the vm.
Address Location::ToStackSlotAddress() const {
const intptr_t index = stack_index();
if (index < 0) {
@@ -101,6 +99,18 @@
}
+intptr_t Location::ToStackSlotOffset() const {
+ const intptr_t index = stack_index();
+ if (index < 0) {
+ const intptr_t offset = (kParamEndSlotFromFp - index) * kWordSize;
+ return offset;
+ } else {
+ const intptr_t offset = (kFirstLocalSlotFromFp - index) * kWordSize;
+ return offset;
+ }
+}
+
+
const char* Location::Name() const {
switch (kind()) {
case kInvalid: return "?";
diff --git a/runtime/vm/locations.h b/runtime/vm/locations.h
index d74b91c..24bf0a0 100644
--- a/runtime/vm/locations.h
+++ b/runtime/vm/locations.h
@@ -284,6 +284,9 @@
// Return a memory operand for stack slot locations.
Address ToStackSlotAddress() const;
+ // Returns the offset from the frame pointer for stack slot locations.
+ intptr_t ToStackSlotOffset() const;
+
// Constants.
static Location RegisterOrConstant(Value* value);
static Location RegisterOrSmiConstant(Value* value);
diff --git a/runtime/vm/simulator_arm.cc b/runtime/vm/simulator_arm.cc
index 9fdb01e..ad2fc20 100644
--- a/runtime/vm/simulator_arm.cc
+++ b/runtime/vm/simulator_arm.cc
@@ -2914,9 +2914,15 @@
int8_t* s8d_8 = reinterpret_cast<int8_t*>(&s8d);
int8_t* s8n_8 = reinterpret_cast<int8_t*>(&s8n);
int8_t* s8m_8 = reinterpret_cast<int8_t*>(&s8m);
+ uint8_t* s8n_u8 = reinterpret_cast<uint8_t*>(&s8n);
+ uint8_t* s8m_u8 = reinterpret_cast<uint8_t*>(&s8m);
int16_t* s8d_16 = reinterpret_cast<int16_t*>(&s8d);
int16_t* s8n_16 = reinterpret_cast<int16_t*>(&s8n);
int16_t* s8m_16 = reinterpret_cast<int16_t*>(&s8m);
+ uint16_t* s8n_u16 = reinterpret_cast<uint16_t*>(&s8n);
+ uint16_t* s8m_u16 = reinterpret_cast<uint16_t*>(&s8m);
+ int32_t* s8n_32 = reinterpret_cast<int32_t*>(&s8n);
+ int32_t* s8m_32 = reinterpret_cast<int32_t*>(&s8m);
int64_t* s8d_64 = reinterpret_cast<int64_t*>(&s8d);
int64_t* s8n_64 = reinterpret_cast<int64_t*>(&s8n);
int64_t* s8m_64 = reinterpret_cast<int64_t*>(&s8m);
@@ -3007,6 +3013,188 @@
for (int i = 0; i < 4; i++) {
s8d.data_[i].f = s8n.data_[i].f * s8m.data_[i].f;
}
+ } else if ((instr->Bits(8, 4) == 1) && (instr->Bit(4) == 1) &&
+ (instr->Bits(20, 2) == 0) && (instr->Bits(23, 2) == 2)) {
+ // Format(instr, "veorq 'qd, 'qn, 'qm");
+ for (int i = 0; i < 4; i++) {
+ s8d.data_[i].u = s8n.data_[i].u ^ s8m.data_[i].u;
+ }
+ } else if ((instr->Bits(8, 4) == 1) && (instr->Bit(4) == 1) &&
+ (instr->Bits(20, 2) == 3) && (instr->Bits(23, 2) == 0)) {
+ // Format(instr, "vornq 'qd, 'qn, 'qm");
+ for (int i = 0; i < 4; i++) {
+ s8d.data_[i].u = s8n.data_[i].u | ~s8m.data_[i].u;
+ }
+ } else if ((instr->Bits(8, 4) == 1) && (instr->Bit(4) == 1) &&
+ (instr->Bits(20, 2) == 2) && (instr->Bits(23, 2) == 0)) {
+ if (qm == qn) {
+ // Format(instr, "vmovq 'qd, 'qm");
+ for (int i = 0; i < 4; i++) {
+ s8d.data_[i].u = s8m.data_[i].u;
+ }
+ } else {
+ // Format(instr, "vorrq 'qd, 'qm");
+ for (int i = 0; i < 4; i++) {
+ s8d.data_[i].u = s8n.data_[i].u | s8m.data_[i].u;
+ }
+ }
+ } else if ((instr->Bits(8, 4) == 12) && (instr->Bit(4) == 0) &&
+ (instr->Bits(20, 2) == 3) && (instr->Bits(23, 2) == 3) &&
+ (instr->Bit(7) == 0)) {
+ DRegister dm = instr->DmField();
+ int64_t dm_value = get_dregister_bits(dm);
+ int32_t imm4 = instr->Bits(16, 4);
+ int32_t idx;
+ if ((imm4 & 1) != 0) {
+ // Format(instr, "vdupb 'qd, 'dm['imm4_vdup]");
+ int8_t* dm_b = reinterpret_cast<int8_t*>(&dm_value);
+ idx = imm4 >> 1;
+ int8_t val = dm_b[idx];
+ for (int i = 0; i < 16; i++) {
+ s8d_8[i] = val;
+ }
+ } else if ((imm4 & 2) != 0) {
+ // Format(instr, "vduph 'qd, 'dm['imm4_vdup]");
+ int16_t* dm_h = reinterpret_cast<int16_t*>(&dm_value);
+ idx = imm4 >> 2;
+ int16_t val = dm_h[idx];
+ for (int i = 0; i < 8; i++) {
+ s8d_16[i] = val;
+ }
+ } else if ((imm4 & 4) != 0) {
+ // Format(instr, "vdupw 'qd, 'dm['imm4_vdup]");
+ int32_t* dm_w = reinterpret_cast<int32_t*>(&dm_value);
+ idx = imm4 >> 3;
+ int32_t val = dm_w[idx];
+ for (int i = 0; i < 4; i++) {
+ s8d.data_[i].u = val;
+ }
+ } else {
+ UnimplementedInstruction(instr);
+ }
+ } else if ((instr->Bits(8, 4) == 8) && (instr->Bit(4) == 1) &&
+ (instr->Bits(23, 2) == 2)) {
+ // Format(instr, "vceqq'sz 'qd, 'qn, 'qm");
+ const int size = instr->Bits(20, 2);
+ if (size == 0) {
+ for (int i = 0; i < 16; i++) {
+ s8d_8[i] = s8n_8[i] == s8m_8[i] ? 0xff : 0;
+ }
+ } else if (size == 1) {
+ for (int i = 0; i < 8; i++) {
+ s8d_16[i] = s8n_16[i] == s8m_16[i] ? 0xffff : 0;
+ }
+ } else if (size == 2) {
+ for (int i = 0; i < 4; i++) {
+ s8d.data_[i].u = s8n.data_[i].u == s8m.data_[i].u ? 0xffffffff : 0;
+ }
+ } else if (size == 3) {
+ UnimplementedInstruction(instr);
+ } else {
+ UNREACHABLE();
+ }
+ } else if ((instr->Bits(8, 4) == 14) && (instr->Bit(4) == 0) &&
+ (instr->Bits(20, 2) == 0) && (instr->Bits(23, 2) == 0)) {
+ // Format(instr, "vceqqs 'qd, 'qn, 'qm");
+ for (int i = 0; i < 4; i++) {
+ s8d.data_[i].u = s8n.data_[i].f == s8m.data_[i].f ? 0xffffffff : 0;
+ }
+ } else if ((instr->Bits(8, 4) == 3) && (instr->Bit(4) == 1) &&
+ (instr->Bits(23, 2) == 0)) {
+ // Format(instr, "vcgeq'sz 'qd, 'qn, 'qm");
+ const int size = instr->Bits(20, 2);
+ if (size == 0) {
+ for (int i = 0; i < 16; i++) {
+ s8d_8[i] = s8n_8[i] >= s8m_8[i] ? 0xff : 0;
+ }
+ } else if (size == 1) {
+ for (int i = 0; i < 8; i++) {
+ s8d_16[i] = s8n_16[i] >= s8m_16[i] ? 0xffff : 0;
+ }
+ } else if (size == 2) {
+ for (int i = 0; i < 4; i++) {
+ s8d.data_[i].u = s8n_32[i] >= s8m_32[i] ? 0xffffffff : 0;
+ }
+ } else if (size == 3) {
+ UnimplementedInstruction(instr);
+ } else {
+ UNREACHABLE();
+ }
+ } else if ((instr->Bits(8, 4) == 3) && (instr->Bit(4) == 1) &&
+ (instr->Bits(23, 2) == 2)) {
+ // Format(instr, "vcugeq'sz 'qd, 'qn, 'qm");
+ const int size = instr->Bits(20, 2);
+ if (size == 0) {
+ for (int i = 0; i < 16; i++) {
+ s8d_8[i] = s8n_u8[i] >= s8m_u8[i] ? 0xff : 0;
+ }
+ } else if (size == 1) {
+ for (int i = 0; i < 8; i++) {
+ s8d_16[i] = s8n_u16[i] >= s8m_u16[i] ? 0xffff : 0;
+ }
+ } else if (size == 2) {
+ for (int i = 0; i < 4; i++) {
+ s8d.data_[i].u = s8n.data_[i].u >= s8m.data_[i].u ? 0xffffffff : 0;
+ }
+ } else if (size == 3) {
+ UnimplementedInstruction(instr);
+ } else {
+ UNREACHABLE();
+ }
+ } else if ((instr->Bits(8, 4) == 14) && (instr->Bit(4) == 0) &&
+ (instr->Bits(20, 2) == 0) && (instr->Bits(23, 2) == 2)) {
+ // Format(instr, "vcgeqs 'qd, 'qn, 'qm");
+ for (int i = 0; i < 4; i++) {
+ s8d.data_[i].u = s8n.data_[i].f >= s8m.data_[i].f ? 0xffffffff : 0;
+ }
+ } else if ((instr->Bits(8, 4) == 3) && (instr->Bit(4) == 0) &&
+ (instr->Bits(23, 2) == 0)) {
+ // Format(instr, "vcgtq'sz 'qd, 'qn, 'qm");
+ const int size = instr->Bits(20, 2);
+ if (size == 0) {
+ for (int i = 0; i < 16; i++) {
+ s8d_8[i] = s8n_8[i] > s8m_8[i] ? 0xff : 0;
+ }
+ } else if (size == 1) {
+ for (int i = 0; i < 8; i++) {
+ s8d_16[i] = s8n_16[i] > s8m_16[i] ? 0xffff : 0;
+ }
+ } else if (size == 2) {
+ for (int i = 0; i < 4; i++) {
+ s8d.data_[i].u = s8n_32[i] > s8m_32[i] ? 0xffffffff : 0;
+ }
+ } else if (size == 3) {
+ UnimplementedInstruction(instr);
+ } else {
+ UNREACHABLE();
+ }
+ } else if ((instr->Bits(8, 4) == 3) && (instr->Bit(4) == 0) &&
+ (instr->Bits(23, 2) == 2)) {
+ // Format(instr, "vcugtq'sz 'qd, 'qn, 'qm");
+ const int size = instr->Bits(20, 2);
+ if (size == 0) {
+ for (int i = 0; i < 16; i++) {
+ s8d_8[i] = s8n_u8[i] > s8m_u8[i] ? 0xff : 0;
+ }
+ } else if (size == 1) {
+ for (int i = 0; i < 8; i++) {
+ s8d_16[i] = s8n_u16[i] > s8m_u16[i] ? 0xffff : 0;
+ }
+ } else if (size == 2) {
+ for (int i = 0; i < 4; i++) {
+ s8d.data_[i].u = s8n.data_[i].u > s8m.data_[i].u ? 0xffffffff : 0;
+ }
+ } else if (size == 3) {
+ UnimplementedInstruction(instr);
+ } else {
+ UNREACHABLE();
+ }
+ } else if ((instr->Bits(8, 4) == 14) && (instr->Bit(4) == 0) &&
+ (instr->Bits(20, 2) == 2) && (instr->Bits(23, 2) == 2)) {
+ // Format(instr, "vcgtqs 'qd, 'qn, 'qm");
+ for (int i = 0; i < 4; i++) {
+ s8d.data_[i].u = s8n.data_[i].f > s8m.data_[i].f ? 0xffffffff : 0;
+ }
} else {
UnimplementedInstruction(instr);
}
@@ -3031,7 +3219,6 @@
table[i] = 0;
}
-
int64_t dm_value = get_dregister_bits(dm);
int64_t result;
int8_t* dm_bytes = reinterpret_cast<int8_t*>(&dm_value);
diff --git a/runtime/vm/stub_code_arm.cc b/runtime/vm/stub_code_arm.cc
index ec602d6..c7c1787 100644
--- a/runtime/vm/stub_code_arm.cc
+++ b/runtime/vm/stub_code_arm.cc
@@ -1468,8 +1468,8 @@
__ LoadFromOffset(kWord, IP, R7, -i * kWordSize);
__ Push(IP);
}
- // Pass IC data object and arguments descriptor array.
- __ PushList((1 << R4) | (1 << R5));
+ // Pass IC data object.
+ __ Push(R5);
if (num_args == 1) {
__ CallRuntime(kInlineCacheMissHandlerOneArgRuntimeEntry);
@@ -1480,9 +1480,8 @@
} else {
UNIMPLEMENTED();
}
- // Remove the call arguments pushed earlier, including the IC data object
- // and the arguments descriptor array.
- __ Drop(num_args + 2);
+ // Remove the call arguments pushed earlier, including the IC data object.
+ __ Drop(num_args + 1);
// Pop returned code object into R0 (null if not found).
// Restore arguments descriptor array and IC data array.
__ PopList((1 << R0) | (1 << R4) | (1 << R5));
diff --git a/runtime/vm/stub_code_ia32.cc b/runtime/vm/stub_code_ia32.cc
index e033ba5..ef24ad8 100644
--- a/runtime/vm/stub_code_ia32.cc
+++ b/runtime/vm/stub_code_ia32.cc
@@ -1519,7 +1519,6 @@
__ pushl(EBX);
}
__ pushl(ECX); // Pass IC data object.
- __ pushl(EDX); // Pass arguments descriptor array.
if (num_args == 1) {
__ CallRuntime(kInlineCacheMissHandlerOneArgRuntimeEntry);
} else if (num_args == 2) {
@@ -1529,9 +1528,8 @@
} else {
UNIMPLEMENTED();
}
- // Remove the call arguments pushed earlier, including the IC data object
- // and the arguments descriptor array.
- for (intptr_t i = 0; i < num_args + 2; i++) {
+ // Remove the call arguments pushed earlier, including the IC data object.
+ for (intptr_t i = 0; i < num_args + 1; i++) {
__ popl(EAX);
}
__ popl(EAX); // Pop returned code object into EAX (null if not found).
diff --git a/runtime/vm/stub_code_mips.cc b/runtime/vm/stub_code_mips.cc
index 25578d5..0881c59 100644
--- a/runtime/vm/stub_code_mips.cc
+++ b/runtime/vm/stub_code_mips.cc
@@ -1655,7 +1655,7 @@
__ EnterStubFrame();
// Preserve IC data object and arguments descriptor array and
// setup space on stack for result (target code object).
- int num_slots = num_args + 5;
+ int num_slots = num_args + 4;
__ addiu(SP, SP, Immediate(-num_slots * kWordSize));
__ sw(S5, Address(SP, (num_slots - 1) * kWordSize));
__ sw(S4, Address(SP, (num_slots - 2) * kWordSize));
@@ -1666,9 +1666,8 @@
__ lw(TMP1, Address(T1, -i * kWordSize));
__ sw(TMP1, Address(SP, (num_slots - i - 4) * kWordSize));
}
- // Pass IC data object and arguments descriptor array.
+ // Pass IC data object.
__ sw(S5, Address(SP, (num_slots - num_args - 4) * kWordSize));
- __ sw(S4, Address(SP, (num_slots - num_args - 5) * kWordSize));
if (num_args == 1) {
__ CallRuntime(kInlineCacheMissHandlerOneArgRuntimeEntry);
diff --git a/runtime/vm/stub_code_x64.cc b/runtime/vm/stub_code_x64.cc
index 14c3010..e222c70 100644
--- a/runtime/vm/stub_code_x64.cc
+++ b/runtime/vm/stub_code_x64.cc
@@ -1500,7 +1500,6 @@
__ pushq(RCX);
}
__ pushq(RBX); // Pass IC data object.
- __ pushq(R10); // Pass arguments descriptor array.
if (num_args == 1) {
__ CallRuntime(kInlineCacheMissHandlerOneArgRuntimeEntry);
} else if (num_args == 2) {
@@ -1510,9 +1509,8 @@
} else {
UNIMPLEMENTED();
}
- // Remove the call arguments pushed earlier, including the IC data object
- // and the arguments descriptor array.
- for (intptr_t i = 0; i < num_args + 2; i++) {
+ // Remove the call arguments pushed earlier, including the IC data object.
+ for (intptr_t i = 0; i < num_args + 1; i++) {
__ popq(RAX);
}
__ popq(RAX); // Pop returned code object into RAX (null if not found).
diff --git a/sdk/lib/_internal/compiler/implementation/closure.dart b/sdk/lib/_internal/compiler/implementation/closure.dart
index 2fd29da..a10ccbd 100644
--- a/sdk/lib/_internal/compiler/implementation/closure.dart
+++ b/sdk/lib/_internal/compiler/implementation/closure.dart
@@ -42,6 +42,8 @@
// cache. One for given node and one for each nested closure.
if (node is FunctionExpression) {
translator.translateFunction(element, node);
+ } else if (element.isSynthesized) {
+ return new ClosureClassMap(null, null, null, new ThisElement(element));
} else {
// Must be the lazy initializer of a static.
assert(node is SendSet);
diff --git a/sdk/lib/_internal/compiler/implementation/compile_time_constants.dart b/sdk/lib/_internal/compiler/implementation/compile_time_constants.dart
index 79c9a27..610114e 100644
--- a/sdk/lib/_internal/compiler/implementation/compile_time_constants.dart
+++ b/sdk/lib/_internal/compiler/implementation/compile_time_constants.dart
@@ -689,7 +689,7 @@
compiler.analyzeElement(constructor.declaration);
InterfaceType type = elements.getType(node);
- if ( constructor.isRedirectingFactory) {
+ if (constructor.isRedirectingFactory) {
type = constructor.computeTargetType(compiler, type);
}
@@ -704,7 +704,7 @@
List<Constant> arguments = evaluateArgumentsToConstructor(
node, selector, send.arguments, constructor);
ConstructorEvaluator evaluator =
- new ConstructorEvaluator(node, constructor, handler, compiler);
+ new ConstructorEvaluator(constructor, handler, compiler);
evaluator.evaluateConstructorFieldValues(arguments);
List<Constant> jsNewArguments = evaluator.buildJsNewArguments(classElement);
@@ -761,8 +761,7 @@
*
* Invariant: [constructor] must be an implementation element.
*/
- ConstructorEvaluator(Node node,
- FunctionElement constructor,
+ ConstructorEvaluator(FunctionElement constructor,
ConstantHandler handler,
Compiler compiler)
: this.constructor = constructor,
@@ -772,7 +771,7 @@
compiler.resolver.resolveMethodElement(constructor.declaration),
compiler,
isConst: true) {
- assert(invariant(node, constructor.isImplementation));
+ assert(invariant(constructor, constructor.isImplementation));
}
Constant visitSend(Send send) {
@@ -828,15 +827,10 @@
});
}
- void evaluateSuperOrRedirectSend(Node currentNode,
- Selector selector,
- Link<Node> arguments,
+ void evaluateSuperOrRedirectSend(List<Constant> compiledArguments,
FunctionElement targetConstructor) {
- List<Constant> compiledArguments = evaluateArgumentsToConstructor(
- currentNode, selector, arguments, targetConstructor);
-
ConstructorEvaluator evaluator = new ConstructorEvaluator(
- currentNode, targetConstructor, handler, compiler);
+ targetConstructor, handler, compiler);
evaluator.evaluateConstructorFieldValues(compiledArguments);
// Copy over the fieldValues from the super/redirect-constructor.
// No need to go through [updateFieldValue] because the
@@ -849,6 +843,21 @@
* the [fieldValues] map.
*/
void evaluateConstructorInitializers() {
+ if (constructor.isSynthesized) {
+ List<Constant> compiledArguments = <Constant>[];
+
+ Function compileArgument = (element) => definitions[element];
+ Function compileConstant = handler.compileConstant;
+ FunctionElement target = constructor.targetConstructor.implementation;
+ Selector.addForwardingElementArgumentsToList(constructor,
+ compiledArguments,
+ target,
+ compileArgument,
+ compileConstant,
+ compiler);
+ evaluateSuperOrRedirectSend(compiledArguments, target);
+ return;
+ }
FunctionExpression functionNode = constructor.parseNode(compiler);
NodeList initializerList = functionNode.initializers;
@@ -862,11 +871,10 @@
if (link.head is !SendSet) {
// A super initializer or constructor redirection.
Send call = link.head;
- FunctionElement targetConstructor = elements[call];
- Selector selector = elements.getSelector(call);
- Link<Node> arguments = call.arguments;
- evaluateSuperOrRedirectSend(
- call, selector, arguments, targetConstructor);
+ FunctionElement target = elements[call];
+ List<Constant> compiledArguments = evaluateArgumentsToConstructor(
+ call, elements.getSelector(call), call.arguments, target);
+ evaluateSuperOrRedirectSend(compiledArguments, target);
foundSuperOrRedirect = true;
} else {
// A field initializer.
@@ -897,11 +905,9 @@
compiler.internalError("no default constructor available",
node: functionNode);
}
-
- evaluateSuperOrRedirectSend(functionNode,
- selector,
- const Link<Node>(),
- targetConstructor);
+ List<Constant> compiledArguments = evaluateArgumentsToConstructor(
+ functionNode, selector, const Link<Node>(), targetConstructor);
+ evaluateSuperOrRedirectSend(compiledArguments, targetConstructor);
}
}
}
diff --git a/sdk/lib/_internal/compiler/implementation/compiler.dart b/sdk/lib/_internal/compiler/implementation/compiler.dart
index 5ceb7d3..c301271 100644
--- a/sdk/lib/_internal/compiler/implementation/compiler.dart
+++ b/sdk/lib/_internal/compiler/implementation/compiler.dart
@@ -968,13 +968,7 @@
if (element.isClass()) {
ClassElement cls = element;
cls.ensureResolved(this);
- cls.forEachLocalMember((e) {
- if (e.isSynthesized) {
- // TODO(ahe): Work-around for http://dartbug.com/11205.
- if (e.getLibrary().isPlatformLibrary) return;
- }
- world.addToWorkList(e);
- });
+ cls.forEachLocalMember(enqueuer.resolution.addToWorkList);
world.registerInstantiatedClass(element, globalDependencies);
} else {
world.addToWorkList(element);
@@ -1048,15 +1042,15 @@
TreeElements analyzeElement(Element element) {
assert(invariant(element, element.isDeclaration));
- assert(!element.isForwardingConstructor);
ResolutionEnqueuer world = enqueuer.resolution;
TreeElements elements = world.getCachedElements(element);
if (elements != null) return elements;
assert(parser != null);
Node tree = parser.parse(element);
- validator.validate(tree);
+ assert(invariant(element, !element.isSynthesized || tree == null));
+ if (tree != null) validator.validate(tree);
elements = resolver.resolve(element);
- if (elements != null && !analyzeSignaturesOnly) {
+ if (tree != null && elements != null && !analyzeSignaturesOnly) {
// Only analyze nodes with a corresponding [TreeElements].
checker.check(elements);
}
diff --git a/sdk/lib/_internal/compiler/implementation/dart_backend/backend.dart b/sdk/lib/_internal/compiler/implementation/dart_backend/backend.dart
index d086c19..4c29888 100644
--- a/sdk/lib/_internal/compiler/implementation/dart_backend/backend.dart
+++ b/sdk/lib/_internal/compiler/implementation/dart_backend/backend.dart
@@ -240,7 +240,7 @@
for (final element in resolvedElements.keys) {
if (!element.isConstructor()) continue;
Link<Element> optionalParameters =
- element.functionSignature.optionalParameters;
+ element.computeSignature(compiler).optionalParameters;
for (final optional in optionalParameters) {
if (optional.kind != ElementKind.FIELD_PARAMETER) continue;
fixedMemberNames.add(optional.name.slowToString());
@@ -356,7 +356,8 @@
// and then overwrite necessary parts.
var classNode = classElement.parseNode(compiler);
SynthesizedConstructorElementX constructor =
- new SynthesizedConstructorElementX(classElement);
+ new SynthesizedConstructorElementX(
+ classElement.name, null, classElement);
constructor.type = new FunctionType(
constructor,
compiler.types.voidType,
diff --git a/sdk/lib/_internal/compiler/implementation/dart_backend/placeholder_collector.dart b/sdk/lib/_internal/compiler/implementation/dart_backend/placeholder_collector.dart
index 01cdbe9..d816a0b 100644
--- a/sdk/lib/_internal/compiler/implementation/dart_backend/placeholder_collector.dart
+++ b/sdk/lib/_internal/compiler/implementation/dart_backend/placeholder_collector.dart
@@ -381,7 +381,7 @@
// Do not forget to rename them as well.
FunctionElement constructorFunction = constructor;
Link<Element> optionalParameters =
- constructorFunction.functionSignature.optionalParameters;
+ constructorFunction.computeSignature(compiler).optionalParameters;
for (final argument in send.argumentsNode) {
NamedArgument named = argument.asNamedArgument();
if (named == null) continue;
diff --git a/sdk/lib/_internal/compiler/implementation/deferred_load.dart b/sdk/lib/_internal/compiler/implementation/deferred_load.dart
index b39e475..b20faed 100644
--- a/sdk/lib/_internal/compiler/implementation/deferred_load.dart
+++ b/sdk/lib/_internal/compiler/implementation/deferred_load.dart
@@ -240,6 +240,7 @@
compiler.enqueuer.resolution.getCachedElements(element);
if (elements == null) return new LinkedHashSet<Element>();
Node node = element.parseNode(compiler);
+ if (node == null) return new LinkedHashSet<Element>();
var collector = new DependencyCollector(elements, compiler);
node.accept(collector);
collector.dependencies.addAll(elements.otherDependencies);
diff --git a/sdk/lib/_internal/compiler/implementation/elements/elements.dart b/sdk/lib/_internal/compiler/implementation/elements/elements.dart
index f367345..7703b26 100644
--- a/sdk/lib/_internal/compiler/implementation/elements/elements.dart
+++ b/sdk/lib/_internal/compiler/implementation/elements/elements.dart
@@ -845,11 +845,7 @@
void addMember(Element element, DiagnosticListener listener);
void addToScope(Element element, DiagnosticListener listener);
- /**
- * Add a synthetic nullary constructor if there are no other
- * constructors.
- */
- void addDefaultConstructorIfNeeded(Compiler compiler);
+ void setDefaultConstructor(FunctionElement constructor, Compiler compiler);
void addBackendMember(Element element);
void reverseBackendMembers();
diff --git a/sdk/lib/_internal/compiler/implementation/elements/modelx.dart b/sdk/lib/_internal/compiler/implementation/elements/modelx.dart
index 76b16e4..c2791c8 100644
--- a/sdk/lib/_internal/compiler/implementation/elements/modelx.dart
+++ b/sdk/lib/_internal/compiler/implementation/elements/modelx.dart
@@ -1398,63 +1398,31 @@
* constructors for mixin applications.
*/
class SynthesizedConstructorElementX extends FunctionElementX {
- /// The target constructor if this synthetic constructor is a forwarding
- /// constructor in a mixin application.
- final FunctionElement target;
+ final FunctionElement superMember;
- SynthesizedConstructorElementX(Element enclosing)
- : super(enclosing.name, ElementKind.GENERATIVE_CONSTRUCTOR,
- Modifiers.EMPTY, enclosing),
- target = null;
+ SynthesizedConstructorElementX(SourceString name,
+ this.superMember,
+ Element enclosing)
+ : super(name,
+ ElementKind.GENERATIVE_CONSTRUCTOR,
+ Modifiers.EMPTY,
+ enclosing);
- SynthesizedConstructorElementX.forDefault(Element enclosing,
- Compiler compiler)
- : super(const SourceString(''), ElementKind.GENERATIVE_CONSTRUCTOR,
- Modifiers.EMPTY, enclosing),
- target = null {
- // TODO(karlklose): get rid of the fake AST.
- type = new FunctionType(this,
- compiler.types.voidType,
- const Link<DartType>(),
- const Link<DartType>(),
- const Link<SourceString>(),
- const Link<DartType>());
- cachedNode = new FunctionExpression(
- new Identifier(enclosing.position()),
- new NodeList.empty(),
- new Block(new NodeList.empty()),
- null, Modifiers.EMPTY, null, null);
- }
-
- /**
- * Create synthetic constructor that directly forwards to a constructor in the
- * super class of a mixin application.
- *
- * In a mixin application `Base with M`, any constructor defined in `Base` is
- * available as if they were a constructor defined in the mixin application
- * with the same formal parameters that calls the constructor in the super
- * class via a `super` initializer (see Ch. 9.1 in the specification).
- */
- SynthesizedConstructorElementX.forwarding(SourceString name, this.target,
- Element enclosing)
- : super(name, ElementKind.GENERATIVE_CONSTRUCTOR, Modifiers.EMPTY,
- enclosing);
+ SynthesizedConstructorElementX.forDefault(superMember, Element enclosing)
+ : this(const SourceString(''), superMember, enclosing);
Token position() => enclosingElement.position();
bool get isSynthesized => true;
- bool get isForwardingConstructor => target != null;
-
- FunctionElement get targetConstructor => target;
+ FunctionElement get targetConstructor => superMember;
FunctionSignature computeSignature(compiler) {
- if (target != null) {
- return target.computeSignature(compiler);
- } else {
- assert(cachedNode != null);
- return super.computeSignature(compiler);
+ if (superMember.isErroneous()) {
+ return compiler.objectClass.localLookup(
+ const SourceString('')).computeSignature(compiler);
}
+ return superMember.computeSignature(compiler);
}
get declaration => this;
@@ -1604,13 +1572,6 @@
return this;
}
- void addDefaultConstructorIfNeeded(Compiler compiler) {
- if (hasConstructor) return;
- FunctionElement constructor =
- new SynthesizedConstructorElementX.forDefault(this, compiler);
- setDefaultConstructor(constructor, compiler);
- }
-
void setDefaultConstructor(FunctionElement constructor, Compiler compiler);
void addBackendMember(Element member) {
diff --git a/sdk/lib/_internal/compiler/implementation/enqueue.dart b/sdk/lib/_internal/compiler/implementation/enqueue.dart
index 77a146a..353897d 100644
--- a/sdk/lib/_internal/compiler/implementation/enqueue.dart
+++ b/sdk/lib/_internal/compiler/implementation/enqueue.dart
@@ -105,12 +105,6 @@
void addToWorkList(Element element) {
assert(invariant(element, element.isDeclaration));
if (element.isForeign(compiler)) return;
-
- if (element.isForwardingConstructor) {
- addToWorkList(element.targetConstructor);
- return;
- }
-
internalAddToWorkList(element);
}
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart b/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart
index 281a07a..3a9154a 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart
@@ -1387,7 +1387,7 @@
void generateFunctionTypeSignature(Element method, FunctionType type) {
assert(method.isImplementation);
- String thisAccess = 'this';
+ jsAst.Expression thisAccess = new jsAst.This();
Node node = method.parseNode(compiler);
ClosureClassMap closureData =
compiler.closureToClassMapper.closureMappingCache[node];
@@ -1397,14 +1397,13 @@
if (thisElement != null) {
assert(thisElement.hasFixedBackendName());
String thisName = thisElement.fixedBackendName();
- thisAccess = 'this.$thisName';
+ thisAccess = js('this')[js.string(thisName)];
}
}
RuntimeTypes rti = backend.rti;
- String encoding = rti.getSignatureEncoding(type, () => '$thisAccess');
+ jsAst.Expression encoding = rti.getSignatureEncoding(type, thisAccess);
String operatorSignature = namer.operatorSignature();
- builder.addProperty(operatorSignature,
- new jsAst.LiteralExpression(encoding));
+ builder.addProperty(operatorSignature, encoding);
}
void generateSubstitution(Element other, {bool emitNull: false}) {
@@ -1412,11 +1411,9 @@
jsAst.Expression expression;
bool needsNativeCheck = nativeEmitter.requiresNativeIsCheck(other);
if (other.kind == ElementKind.CLASS) {
- String substitution = rti.getSupertypeSubstitution(classElement, other,
- alwaysGenerateFunction: true);
- if (substitution != null) {
- expression = new jsAst.LiteralExpression(substitution);
- } else if (emitNull || needsNativeCheck) {
+ expression = rti.getSupertypeSubstitution(
+ classElement, other, alwaysGenerateFunction: true);
+ if (expression == null && (emitNull || needsNativeCheck)) {
expression = new jsAst.LiteralNull();
}
}
@@ -1444,15 +1441,20 @@
buffer.write('$holder.${namer.operatorIs(cls)}$_=${_}true$N');
Substitution substitution = check.substitution;
if (substitution != null) {
- String body = substitution.getCode(rti, false);
- buffer.write('$holder.${namer.substitutionName(cls)}$_=${_}$body$N');
+ CodeBuffer body =
+ jsAst.prettyPrint(substitution.getCode(rti, false), compiler);
+ buffer.write('$holder.${namer.substitutionName(cls)}$_=${_}');
+ buffer.write(body);
+ buffer.write('$N');
}
};
}
void addSignature(FunctionType type) {
- String encoding = rti.getTypeEncoding(type);
- buffer.add('${namer.signatureName(type)}$_=${_}$encoding$N');
+ jsAst.Expression encoding = rti.getTypeEncoding(type);
+ buffer.add('${namer.signatureName(type)}$_=${_}');
+ buffer.write(jsAst.prettyPrint(encoding, compiler));
+ buffer.add('$N');
}
checkedNonGenericFunctionTypes.forEach(addSignature);
@@ -2262,11 +2264,11 @@
RuntimeTypes rti = backend.rti;
// [:() => null:] is dummy encoding of [this] which is never needed for
// the encoding of the type of the static [method].
- String encoding = rti.getSignatureEncoding(methodType, () => 'null');
+ jsAst.Expression encoding =
+ rti.getSignatureEncoding(methodType, js('null'));
String operatorSignature = namer.operatorSignature();
// TODO(johnniwinther): Make MiniJsParser support function expressions.
- closureBuilder.addProperty(operatorSignature,
- new jsAst.LiteralExpression(encoding));
+ closureBuilder.addProperty(operatorSignature, encoding);
}
void emitIsFunctionTypeTest(FunctionType functionType) {
@@ -2401,11 +2403,10 @@
addParameterStubs(callElement, boundClosureBuilder.addProperty);
void emitFunctionTypeSignature(Element method, FunctionType methodType) {
- String encoding = backend.rti.getSignatureEncoding(
- methodType, () => 'this.${fieldNames[0]}');
+ jsAst.Expression encoding = backend.rti.getSignatureEncoding(
+ methodType, js('this')[fieldNames[0]]);
String operatorSignature = namer.operatorSignature();
- boundClosureBuilder.addProperty(operatorSignature,
- new jsAst.LiteralExpression(encoding));
+ boundClosureBuilder.addProperty(operatorSignature, encoding);
}
void emitIsFunctionTypeTest(FunctionType functionType) {
@@ -3423,7 +3424,7 @@
if (!backend.retainMetadataOf(element)) return code;
return compiler.withCurrentElement(element, () {
List<int> metadata = <int>[];
- FunctionSignature signature = element.functionSignature;
+ FunctionSignature signature = element.computeSignature(compiler);
if (element.isConstructor()) {
metadata.add(reifyType(element.getEnclosingClass().thisType));
} else {
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/runtime_types.dart b/sdk/lib/_internal/compiler/implementation/js_backend/runtime_types.dart
index 73e31a1..3f21597 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/runtime_types.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/runtime_types.dart
@@ -12,7 +12,7 @@
Iterator<ClassElement> get iterator;
}
-typedef String VariableSubstitution(TypeVariableType variable);
+typedef jsAst.Expression OnVariableCallback(TypeVariableType variable);
class RuntimeTypes {
final Compiler compiler;
@@ -421,7 +421,6 @@
return (variables.isEmpty == arguments.isEmpty);
}
- // TODO(karlklose): rewrite to use js.Expressions.
/**
* Compute a JavaScript expression that describes the necessary substitution
* for type arguments in a subtype test.
@@ -436,8 +435,10 @@
* 3) A function mapping the type variables of the object to be checked to
* a list expression.
*/
- String getSupertypeSubstitution(ClassElement cls, ClassElement check,
- {bool alwaysGenerateFunction: false}) {
+ jsAst.Expression getSupertypeSubstitution(
+ ClassElement cls,
+ ClassElement check,
+ {bool alwaysGenerateFunction: false}) {
Substitution substitution = getSubstitution(cls, check);
if (substitution != null) {
return substitution.getCode(this, alwaysGenerateFunction);
@@ -462,11 +463,6 @@
{ bool alwaysGenerateFunction: false }) {
if (isTrivialSubstitution(cls, check)) return null;
- bool usesTypeVariables = false;
- String onVariable(TypeVariableType v) {
- usesTypeVariables = true;
- return v.toString();
- };
InterfaceType type = cls.computeType(compiler);
InterfaceType target = type.asInstanceOf(check);
Link<DartType> typeVariables;
@@ -483,61 +479,71 @@
}
}
- String getSubstitutionRepresentation(Link<DartType> types,
- VariableSubstitution variableName) {
- String code = types.toList(growable: false)
- .map((type) => _getTypeRepresentation(type, variableName))
- .join(', ');
- return '[$code]';
+ jsAst.Expression getSubstitutionRepresentation(
+ Link<DartType> types,
+ OnVariableCallback onVariable) {
+ List<jsAst.ArrayElement> elements = <jsAst.ArrayElement>[];
+ int index = 0;
+ for (; !types.isEmpty; types = types.tail, index++) {
+ jsAst.Expression representation =
+ _getTypeRepresentation(types.head, onVariable);
+ elements.add(new jsAst.ArrayElement(index, representation));
+ }
+ return new jsAst.ArrayInitializer(index, elements);
}
- String getTypeEncoding(DartType type,
- {bool alwaysGenerateFunction: false}) {
+ jsAst.Expression getTypeEncoding(DartType type,
+ {bool alwaysGenerateFunction: false}) {
ClassElement contextClass = Types.getClassContext(type);
- String onVariable(TypeVariableType v) {
- return v.toString();
+ jsAst.Expression onVariable(TypeVariableType v) {
+ return new jsAst.VariableUse(v.name.slowToString());
};
- String encoding = _getTypeRepresentation(type, onVariable);
+ jsAst.Expression encoding = _getTypeRepresentation(type, onVariable);
if (contextClass == null && !alwaysGenerateFunction) {
return encoding;
} else {
- String parameters = contextClass != null
- ? contextClass.typeVariables.toList().join(', ')
- : '';
- return 'function ($parameters) { return $encoding; }';
+ List<String> parameters = const <String>[];
+ if (contextClass != null) {
+ parameters = contextClass.typeVariables.toList().map((type) {
+ return type.toString();
+ }).toList();
+ }
+ return js.fun(parameters, js.return_(encoding));
}
}
- String getSignatureEncoding(DartType type, String generateThis()) {
+ jsAst.Expression getSignatureEncoding(DartType type, jsAst.Expression this_) {
ClassElement contextClass = Types.getClassContext(type);
- String encoding = getTypeEncoding(type, alwaysGenerateFunction: true);
+ jsAst.Expression encoding =
+ getTypeEncoding(type, alwaysGenerateFunction: true);
if (contextClass != null) {
- String this_ = generateThis();
JavaScriptBackend backend = compiler.backend;
String computeSignature =
backend.namer.getName(backend.getComputeSignature());
String contextName = backend.namer.getName(contextClass);
- return 'function () {'
- ' return ${backend.namer.GLOBAL_OBJECT}.'
- '$computeSignature($encoding, $this_, "$contextName"); '
- '}';
+ List<jsAst.Expression> arguments =
+ <jsAst.Expression>[encoding, this_, js.string(contextName)];
+ return js.fun([], js.return_(
+ new jsAst.Call(
+ js(backend.namer.GLOBAL_OBJECT)[js.string(computeSignature)],
+ arguments)));
} else {
return encoding;
}
}
- String getTypeRepresentation(DartType type, VariableSubstitution onVariable) {
+ String getTypeRepresentation(DartType type, OnVariableCallback onVariable) {
// Create a type representation. For type variables call the original
// callback for side effects and return a template placeholder.
- return _getTypeRepresentation(type, (variable) {
+ jsAst.Expression representation = _getTypeRepresentation(type, (variable) {
onVariable(variable);
- return '#';
+ return new jsAst.LiteralString('#');
});
+ return jsAst.prettyPrint(representation, compiler).buffer.toString();
}
- // TODO(karlklose): rewrite to use js.Expressions.
- String _getTypeRepresentation(DartType type,
- VariableSubstitution onVariable) {
+ jsAst.Expression _getTypeRepresentation(DartType type,
+ OnVariableCallback onVariable) {
return representationGenerator.getTypeRepresentation(type, onVariable);
}
@@ -559,12 +565,9 @@
}
}
-typedef String OnVariableCallback(TypeVariableType type);
-
class TypeRepresentationGenerator extends DartTypeVisitor {
final Compiler compiler;
OnVariableCallback onVariable;
- StringBuffer builder;
JavaScriptBackend get backend => compiler.backend;
Namer get namer => backend.namer;
@@ -575,104 +578,95 @@
* Creates a type representation for [type]. [onVariable] is called to provide
* the type representation for type variables.
*/
- String getTypeRepresentation(DartType type, OnVariableCallback onVariable) {
+ jsAst.Expression getTypeRepresentation(DartType type,
+ OnVariableCallback onVariable) {
this.onVariable = onVariable;
- builder = new StringBuffer();
- visit(type);
- String typeRepresentation = builder.toString();
- builder = null;
+ jsAst.Expression representation = visit(type);
this.onVariable = null;
- return typeRepresentation;
+ return representation;
}
- String getJsName(Element element) {
- return namer.isolateAccess(backend.getImplementationClass(element));
+ jsAst.Expression getJavaScriptClassName(Element element) {
+ return js(namer.isolateAccess(backend.getImplementationClass(element)));
}
visit(DartType type) {
- type.unalias(compiler).accept(this, null);
+ return type.unalias(compiler).accept(this, null);
}
visitTypeVariableType(TypeVariableType type, _) {
- builder.write(onVariable(type));
+ return onVariable(type);
}
visitDynamicType(DynamicType type, _) {
- builder.write('null');
+ return js('null');
}
visitInterfaceType(InterfaceType type, _) {
- String name = getJsName(type.element);
- if (type.isRaw) {
- builder.write(name);
- } else {
- builder.write('[');
- builder.write(name);
- builder.write(', ');
- visitList(type.typeArguments);
- builder.write(']');
- }
+ jsAst.Expression name = getJavaScriptClassName(type.element);
+ return type.isRaw ? name : visitList(type.typeArguments, head: name);
}
- visitList(Link<DartType> types) {
- bool first = true;
- for (Link<DartType> link = types; !link.isEmpty; link = link.tail) {
- if (!first) {
- builder.write(', ');
- }
- visit(link.head);
- first = false;
+ jsAst.Expression visitList(Link<DartType> types, {jsAst.Expression head}) {
+ int index = 0;
+ List<jsAst.ArrayElement> elements = <jsAst.ArrayElement>[];
+ if (head != null) {
+ elements.add(new jsAst.ArrayElement(0, head));
+ index++;
}
+ for (Link<DartType> link = types; !link.isEmpty; link = link.tail) {
+ elements.add(new jsAst.ArrayElement(index++, visit(link.head)));
+ }
+ return new jsAst.ArrayInitializer(elements.length, elements);
}
visitFunctionType(FunctionType type, _) {
- builder.write('{${namer.functionTypeTag()}:'
- ' "${namer.getFunctionTypeName(type)}"');
+ List<jsAst.Property> properties = <jsAst.Property>[];
+
+ void addProperty(String name, jsAst.Expression value) {
+ properties.add(new jsAst.Property(js.string(name), value));
+ }
+
+ jsAst.LiteralString name = js.string(namer.getFunctionTypeName(type));
+ addProperty(namer.functionTypeTag(), name);
if (type.returnType.isVoid) {
- builder.write(', ${namer.functionTypeVoidReturnTag()}: true');
+ addProperty(namer.functionTypeVoidReturnTag(), js('true'));
} else if (!type.returnType.isDynamic) {
- builder.write(', ${namer.functionTypeReturnTypeTag()}: ');
- visit(type.returnType);
+ addProperty(namer.functionTypeReturnTypeTag(), visit(type.returnType));
}
if (!type.parameterTypes.isEmpty) {
- builder.write(', ${namer.functionTypeRequiredParametersTag()}: [');
- visitList(type.parameterTypes);
- builder.write(']');
+ addProperty(namer.functionTypeRequiredParametersTag(),
+ visitList(type.parameterTypes));
}
if (!type.optionalParameterTypes.isEmpty) {
- builder.write(', ${namer.functionTypeOptionalParametersTag()}: [');
- visitList(type.optionalParameterTypes);
- builder.write(']');
+ addProperty(namer.functionTypeOptionalParametersTag(),
+ visitList(type.optionalParameterTypes));
}
if (!type.namedParameterTypes.isEmpty) {
- builder.write(', ${namer.functionTypeNamedParametersTag()}: {');
- bool first = true;
+ List<jsAst.Property> namedArguments = <jsAst.Property>[];
Link<SourceString> names = type.namedParameters;
Link<DartType> types = type.namedParameterTypes;
while (!types.isEmpty) {
assert(!names.isEmpty);
- if (!first) {
- builder.write(', ');
- }
- builder.write('${names.head.slowToString()}: ');
- visit(types.head);
- first = false;
+ jsAst.Expression name = js.string(names.head.slowToString());
+ namedArguments.add(new jsAst.Property(name, visit(types.head)));
names = names.tail;
types = types.tail;
}
- builder.write('}');
+ addProperty(namer.functionTypeNamedParametersTag(),
+ new jsAst.ObjectInitializer(namedArguments));
}
- builder.write('}');
+ return new jsAst.ObjectInitializer(properties);
}
visitMalformedType(MalformedType type, _) {
// Treat malformed types as dynamic at runtime.
- builder.write('null');
+ return js('null');
}
visitVoidType(VoidType type, _) {
// TODO(ahe): Reify void type ("null" means "dynamic").
- builder.write('null');
+ return js('null');
}
visitType(DartType type, _) {
@@ -814,19 +808,24 @@
Substitution.function(this.arguments, this.parameters)
: isFunction = true;
- String getCode(RuntimeTypes rti, bool ensureIsFunction) {
- String variableName(TypeVariableType variable) {
- return variable.name.slowToString();
+ jsAst.Expression getCode(RuntimeTypes rti, bool ensureIsFunction) {
+ jsAst.Expression declaration(TypeVariableType variable) {
+ return new jsAst.Parameter(variable.name.slowToString());
}
- String code = rti.getSubstitutionRepresentation(arguments, variableName);
+ jsAst.Expression use(TypeVariableType variable) {
+ return new jsAst.VariableUse(variable.name.slowToString());
+ }
+
+ jsAst.Expression value =
+ rti.getSubstitutionRepresentation(arguments, use);
if (isFunction) {
- String formals = parameters.toList().map(variableName).join(', ');
- return 'function ($formals) { return $code; }';
+ List<String> formals = parameters.toList().map(declaration).toList();
+ return js.fun(formals, js.return_(value));
} else if (ensureIsFunction) {
- return 'function () { return $code; }';
+ return js.fun([], js.return_(value));
} else {
- return code;
+ return value;
}
}
}
diff --git a/sdk/lib/_internal/compiler/implementation/resolution/members.dart b/sdk/lib/_internal/compiler/implementation/resolution/members.dart
index 3868400..12f9cae 100644
--- a/sdk/lib/_internal/compiler/implementation/resolution/members.dart
+++ b/sdk/lib/_internal/compiler/implementation/resolution/members.dart
@@ -339,6 +339,14 @@
assert(isConstructor);
return elements;
}
+ if (element.isSynthesized) {
+ Element target = element.targetConstructor;
+ if (!target.isErroneous()) {
+ compiler.enqueuer.resolution.registerStaticUse(
+ element.targetConstructor);
+ }
+ return new TreeElementMapping(element);
+ }
if (element.isPatched) {
checkMatchingPatchSignatures(element, element.patch);
element = element.patch;
@@ -1143,13 +1151,14 @@
MessageKind kind = isImplicitSuperCall
? MessageKind.CANNOT_RESOLVE_CONSTRUCTOR_FOR_IMPLICIT
: MessageKind.CANNOT_RESOLVE_CONSTRUCTOR;
- error(diagnosticNode, kind, {'constructorName': fullConstructorName});
+ visitor.compiler.reportErrorCode(
+ diagnosticNode, kind, {'constructorName': fullConstructorName});
} else {
if (!call.applies(lookedupConstructor, visitor.compiler)) {
MessageKind kind = isImplicitSuperCall
? MessageKind.NO_MATCHING_CONSTRUCTOR_FOR_IMPLICIT
: MessageKind.NO_MATCHING_CONSTRUCTOR;
- error(diagnosticNode, kind);
+ visitor.compiler.reportErrorCode(diagnosticNode, kind);
}
}
}
@@ -2535,7 +2544,9 @@
{ // This entire block is temporary code per the above TODO.
FunctionElement targetImplementation = redirectionTarget.implementation;
FunctionExpression function = targetImplementation.parseNode(compiler);
- if (function.body != null && function.body.asReturn() != null
+ if (function != null
+ && function.body != null
+ && function.body.asReturn() != null
&& function.body.asReturn().isRedirectingFactoryBody) {
unimplemented(node.expression, 'redirecting to redirecting factory');
}
@@ -3272,7 +3283,21 @@
element.interfaces = resolveInterfaces(node.interfaces, node.superclass);
calculateAllSupertypes(element);
- element.addDefaultConstructorIfNeeded(compiler);
+ if (!element.hasConstructor) {
+ Element superMember =
+ element.superclass.localLookup(const SourceString(''));
+ if (superMember == null || !superMember.isGenerativeConstructor()) {
+ MessageKind kind = MessageKind.CANNOT_FIND_CONSTRUCTOR;
+ Map arguments = {'constructorName': const SourceString('')};
+ compiler.reportErrorCode(node, kind, arguments);
+ superMember = new ErroneousElementX(
+ kind, arguments, const SourceString(''), element);
+ compiler.backend.registerThrowNoSuchMethod(mapping);
+ }
+ FunctionElement constructor =
+ new SynthesizedConstructorElementX.forDefault(superMember, element);
+ element.setDefaultConstructor(constructor, compiler);
+ }
return element.computeType(compiler);
}
@@ -3316,11 +3341,11 @@
constructor.computeSignature(compiler).parameterCount == 0;
}
- FunctionElement createForwardingConstructor(FunctionElement constructor,
- ClassElement target) {
- return new SynthesizedConstructorElementX.forwarding(constructor.name,
- constructor,
- target);
+ FunctionElement createForwardingConstructor(FunctionElement target,
+ ClassElement enclosing) {
+ return new SynthesizedConstructorElementX(target.name,
+ target,
+ enclosing);
}
void doApplyMixinTo(MixinApplicationElement mixinApplication,
@@ -3359,20 +3384,11 @@
// because they are now hidden by the mixin application.
ClassElement superclass = supertype.element;
superclass.forEachLocalMember((Element member) {
- if (!member.isConstructor()) return;
- if (member.isSynthesized && !member.isForwardingConstructor) return;
- if (isDefaultConstructor(member)) return;
- assert(invariant(node, !member.isFactoryConstructor(),
- message: 'mixins cannot have factory constructors'));
- // Skip forwarding constructors and use their target.
- FunctionElement constructor =
- member.isForwardingConstructor ? member.targetConstructor : member;
- assert(invariant(node, !constructor.isForwardingConstructor));
+ if (!member.isGenerativeConstructor()) return;
FunctionElement forwarder =
- createForwardingConstructor(constructor, mixinApplication);
+ createForwardingConstructor(member, mixinApplication);
mixinApplication.addConstructor(forwarder);
});
- mixinApplication.addDefaultConstructorIfNeeded(compiler);
calculateAllSupertypes(mixinApplication);
}
@@ -3467,32 +3483,63 @@
return result;
}
+ /**
+ * Compute the list of all supertypes.
+ *
+ * The elements of this list are ordered as follows: first the supertype that
+ * the class extends, then the implemented interfaces, and then the supertypes
+ * of these. The class [Object] appears only once, at the end of the list.
+ *
+ * For example, for a class `class C extends S implements I1, I2`, we compute
+ * supertypes(C) = [S, I1, I2] ++ supertypes(S) ++ supertypes(I1)
+ * ++ supertypes(I2),
+ * where ++ stands for list concatenation.
+ *
+ * This order makes sure that if a class implements an interface twice with
+ * different type arguments, the type used in the most specific class comes
+ * first.
+ */
void calculateAllSupertypes(ClassElement cls) {
// TODO(karlklose): Check if type arguments match, if a class
// element occurs more than once in the supertypes.
if (cls.allSupertypes != null) return;
final DartType supertype = cls.supertype;
if (supertype != null) {
- var allSupertypes = new LinkBuilder<DartType>();
+ LinkBuilder<DartType> allSupertypes = new LinkBuilder<DartType>();
+
+ void add(DartType type) {
+ if (type.element != compiler.objectClass) {
+ allSupertypes.addLast(type);
+ }
+ }
+
+ add(supertype);
+ for (Link<DartType> interfaces = cls.interfaces;
+ !interfaces.isEmpty;
+ interfaces = interfaces.tail) {
+ add(interfaces.head);
+ }
addAllSupertypes(allSupertypes, supertype);
for (Link<DartType> interfaces = cls.interfaces;
!interfaces.isEmpty;
interfaces = interfaces.tail) {
addAllSupertypes(allSupertypes, interfaces.head);
}
+
+ allSupertypes.addLast(compiler.objectClass.rawType);
cls.allSupertypes = allSupertypes.toLink();
} else {
assert(identical(cls, compiler.objectClass));
cls.allSupertypes = const Link<DartType>();
}
- }
+ }
/**
- * Adds [type] and all supertypes of [type] to [builder] while substituting
- * type variables.
+ * Adds [type] and all supertypes of [type] to [allSupertypes] while
+ * substituting type variables.
*/
- void addAllSupertypes(LinkBuilder<DartType> builder, InterfaceType type) {
- builder.addLast(type);
+ void addAllSupertypes(LinkBuilder<DartType> allSupertypes,
+ InterfaceType type) {
Link<DartType> typeArguments = type.typeArguments;
ClassElement classElement = type.element;
Link<DartType> typeVariables = classElement.typeVariables;
@@ -3502,7 +3549,10 @@
"during resolution of $element"));
while (!supertypes.isEmpty) {
DartType supertype = supertypes.head;
- builder.addLast(supertype.subst(typeArguments, typeVariables));
+ if (supertype.element != compiler.objectClass) {
+ DartType substituted = supertype.subst(typeArguments, typeVariables);
+ allSupertypes.addLast(substituted);
+ }
supertypes = supertypes.tail;
}
}
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/builder.dart b/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
index b46ef2b..466a9c5 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
@@ -212,7 +212,7 @@
* Invariant: [function] must be an implementation element.
*/
void startFunction(Element element, Expression node) {
- assert(invariant(node, element.isImplementation));
+ assert(invariant(element, element.isImplementation));
Compiler compiler = builder.compiler;
closureData = compiler.closureToClassMapper.computeClosureToClassMapping(
element, node, builder.elements);
@@ -1271,6 +1271,8 @@
return false;
}
+ if (element.isSynthesized) return true;
+
if (cachedCanBeInlined == true) return cachedCanBeInlined;
int numParameters = function.functionSignature.parameterCount;
@@ -1346,37 +1348,19 @@
*
* Invariant: [constructors] must contain only implementation elements.
*/
- void inlineSuperOrRedirect(FunctionElement constructor,
- Selector selector,
- Link<Node> arguments,
+ void inlineSuperOrRedirect(FunctionElement callee,
+ List<HInstruction> compiledArguments,
List<FunctionElement> constructors,
Map<Element, HInstruction> fieldValues,
- FunctionElement inlinedFromElement,
- Node callNode) {
- constructor = constructor.implementation;
- compiler.withCurrentElement(constructor, () {
- constructors.add(constructor);
-
- List<HInstruction> compiledArguments = new List<HInstruction>();
- bool succeeded =
- inlinedFrom(inlinedFromElement,
- () => addStaticSendArgumentsToList(selector,
- arguments,
- constructor,
- compiledArguments));
- if (!succeeded) {
- // Non-matching super and redirects are compile-time errors and thus
- // checked by the resolver.
- compiler.internalError(
- "Parameters and arguments didn't match for super/redirect call",
- element: constructor);
- }
-
- ClassElement enclosingClass = constructor.getEnclosingClass();
+ FunctionElement caller) {
+ callee = callee.implementation;
+ compiler.withCurrentElement(callee, () {
+ constructors.add(callee);
+ ClassElement enclosingClass = callee.getEnclosingClass();
if (backend.classNeedsRti(enclosingClass)) {
// If [enclosingClass] needs RTI, we have to give a value to its
// type parameters.
- ClassElement currentClass = inlinedFromElement.getEnclosingClass();
+ ClassElement currentClass = caller.getEnclosingClass();
// For a super constructor call, the type is the supertype of
// [currentClass]. For a redirecting constructor, the type is
// the current type. [InterfaceType.asInstanceOf] takes care
@@ -1384,8 +1368,9 @@
InterfaceType type = currentClass.thisType.asInstanceOf(enclosingClass);
Link<DartType> typeVariables = enclosingClass.typeVariables;
type.typeArguments.forEach((DartType argument) {
- localsHandler.updateLocal(typeVariables.head.element,
- analyzeTypeArgument(argument, callNode));
+ localsHandler.updateLocal(
+ typeVariables.head.element,
+ analyzeTypeArgument(argument));
typeVariables = typeVariables.tail;
});
// If the supertype is a raw type, we need to set to null the
@@ -1399,13 +1384,13 @@
}
}
- inlinedFrom(constructor, () {
- buildFieldInitializers(constructor.enclosingElement.implementation,
+ inlinedFrom(callee, () {
+ buildFieldInitializers(callee.enclosingElement.implementation,
fieldValues);
});
int index = 0;
- FunctionSignature params = constructor.computeSignature(compiler);
+ FunctionSignature params = callee.computeSignature(compiler);
params.orderedForEachParameter((Element parameter) {
HInstruction argument = compiledArguments[index++];
// Because we are inlining the initializer, we must update
@@ -1423,19 +1408,15 @@
// Build the initializers in the context of the new constructor.
TreeElements oldElements = elements;
- if (constructor.isForwardingConstructor) {
- constructor = constructor.targetConstructor;
- }
- elements =
- compiler.enqueuer.resolution.getCachedElements(constructor);
+ elements = compiler.enqueuer.resolution.getCachedElements(callee);
ClosureClassMap oldClosureData = localsHandler.closureData;
- Node node = constructor.parseNode(compiler);
+ Node node = callee.parseNode(compiler);
ClosureClassMap newClosureData =
compiler.closureToClassMapper.computeClosureToClassMapping(
- constructor, node, elements);
+ callee, node, elements);
localsHandler.closureData = newClosureData;
- localsHandler.enterScope(node, constructor);
- buildInitializers(constructor, constructors, fieldValues);
+ localsHandler.enterScope(node, callee);
+ buildInitializers(callee, constructors, fieldValues);
localsHandler.closureData = oldClosureData;
elements = oldElements;
});
@@ -1455,30 +1436,56 @@
List<FunctionElement> constructors,
Map<Element, HInstruction> fieldValues) {
assert(invariant(constructor, constructor.isImplementation));
+ if (constructor.isSynthesized) {
+ List<HInstruction> arguments = <HInstruction>[];
+ HInstruction compileArgument(Element element) {
+ return localsHandler.readLocal(element);
+ }
+
+ Element target = constructor.targetConstructor.implementation;
+ Selector.addForwardingElementArgumentsToList(
+ constructor,
+ arguments,
+ target,
+ compileArgument,
+ handleConstantForOptionalParameter,
+ compiler);
+ inlineSuperOrRedirect(
+ target,
+ arguments,
+ constructors,
+ fieldValues,
+ constructor);
+ return;
+ }
FunctionExpression functionNode = constructor.parseNode(compiler);
bool foundSuperOrRedirect = false;
-
if (functionNode.initializers != null) {
Link<Node> initializers = functionNode.initializers.nodes;
for (Link<Node> link = initializers; !link.isEmpty; link = link.tail) {
assert(link.head is Send);
if (link.head is !SendSet) {
// A super initializer or constructor redirection.
+ foundSuperOrRedirect = true;
Send call = link.head;
assert(Initializers.isSuperConstructorCall(call) ||
Initializers.isConstructorRedirect(call));
- FunctionElement target = elements[call];
+ FunctionElement target = elements[call].implementation;
Selector selector = elements.getSelector(call);
Link<Node> arguments = call.arguments;
+ List<HInstruction> compiledArguments = new List<HInstruction>();
+ inlinedFrom(constructor, () {
+ addStaticSendArgumentsToList(selector,
+ arguments,
+ target,
+ compiledArguments);
+ });
inlineSuperOrRedirect(target,
- selector,
- arguments,
+ compiledArguments,
constructors,
fieldValues,
- constructor,
- call);
- foundSuperOrRedirect = true;
+ constructor);
} else {
// A field initializer.
SendSet init = link.head;
@@ -1507,13 +1514,18 @@
if (target == null) {
compiler.internalError("no default constructor available");
}
+ List<HInstruction> arguments = <HInstruction>[];
+ selector.addArgumentsToList(const Link<Node>(),
+ arguments,
+ target.implementation,
+ null,
+ handleConstantForOptionalParameter,
+ compiler);
inlineSuperOrRedirect(target,
- selector,
- const Link<Node>(),
+ arguments,
constructors,
fieldValues,
- constructor,
- functionNode);
+ constructor);
}
}
}
@@ -2914,10 +2926,6 @@
return pop();
}
- if (element.isForwardingConstructor) {
- element = element.targetConstructor;
- }
-
return selector.addArgumentsToList(arguments,
list,
element,
@@ -3371,8 +3379,8 @@
*
* Invariant: [argument] must not be malformed in checked mode.
*/
- HInstruction analyzeTypeArgument(DartType argument, Node currentNode) {
- assert(invariant(currentNode,
+ HInstruction analyzeTypeArgument(DartType argument) {
+ assert(invariant(currentElement,
!compiler.enableTypeAssertions || !argument.isMalformed,
message: '$argument is malformed in checked mode'));
if (argument == compiler.types.dynamicType || argument.isMalformed) {
@@ -3398,7 +3406,7 @@
if (!type.isRaw) {
List<HInstruction> inputs = <HInstruction>[];
type.typeArguments.forEach((DartType argument) {
- inputs.add(analyzeTypeArgument(argument, currentNode));
+ inputs.add(analyzeTypeArgument(argument));
});
callSetRuntimeTypeInfo(type.element, inputs, newObject);
}
@@ -3461,13 +3469,6 @@
Element constructor = elements[send];
Selector selector = elements.getSelector(send);
- if (constructor.isForwardingConstructor) {
- compiler.unimplemented('forwarded constructor in named mixin application',
- element: constructor.getEnclosingClass());
- }
- if (compiler.enqueuer.resolution.getCachedElements(constructor) == null) {
- compiler.internalError("Unresolved element: $constructor", node: send);
- }
FunctionElement functionElement = constructor;
constructor = functionElement.redirectionTarget;
@@ -3508,7 +3509,7 @@
if (backend.classNeedsRti(cls)) {
Link<DartType> typeVariable = cls.typeVariables;
type.typeArguments.forEach((DartType argument) {
- inputs.add(analyzeTypeArgument(argument, send));
+ inputs.add(analyzeTypeArgument(argument));
typeVariable = typeVariable.tail;
});
// Also add null to non-provided type variables to call the
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart b/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart
index e522e72..496c2e4 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart
@@ -18,21 +18,28 @@
js.Fun buildJavaScriptFunction(FunctionElement element,
List<js.Parameter> parameters,
js.Block body) {
- FunctionExpression expression =
- element.implementation.parseNode(backend.compiler);
js.Fun result = new js.Fun(parameters, body);
// TODO(johnniwinther): remove the 'element.patch' hack.
Element sourceElement = element.patch == null ? element : element.patch;
SourceFile sourceFile = sourceElement.getCompilationUnit().script.file;
+ Node expression =
+ element.implementation.parseNode(backend.compiler);
+ Token beginToken;
+ Token endToken;
+ if (expression == null) {
+ // Synthesized node. Use the enclosing element for the location.
+ beginToken = endToken = element.position();
+ } else {
+ beginToken = expression.getBeginToken();
+ endToken = expression.getEndToken();
+ }
// TODO(podivilov): find the right sourceFile here and remove offset checks
// below.
- if (expression.getBeginToken().charOffset < sourceFile.text.length) {
- result.sourcePosition = new SourceFileLocation(
- sourceFile, expression.getBeginToken());
+ if (beginToken.charOffset < sourceFile.text.length) {
+ result.sourcePosition = new SourceFileLocation(sourceFile, beginToken);
}
- if (expression.getEndToken().charOffset < sourceFile.text.length) {
- result.endSourcePosition = new SourceFileLocation(
- sourceFile, expression.getEndToken());
+ if (endToken.charOffset < sourceFile.text.length) {
+ result.endSourcePosition = new SourceFileLocation(sourceFile, endToken);
}
return result;
}
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart b/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart
index f8ef54e..44ef282 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart
@@ -620,26 +620,28 @@
}
HInstruction visitFieldGet(HFieldGet node) {
+ var receiver = node.receiver;
if (node.element == backend.jsIndexableLength) {
- if (node.receiver is HInvokeStatic) {
+ if (receiver is HInvokeStatic) {
// Try to recognize the length getter with input
// [:new List(int):].
- HInvokeStatic call = node.receiver;
- Element element = call.element;
+ Element element = receiver.element;
// TODO(ngeoffray): checking if the second input is an integer
// should not be necessary but it currently makes it easier for
// other optimizations to reason about a fixed length constructor
// that we know takes an int.
if (element == compiler.unnamedListConstructor
- && call.inputs.length == 1
- && call.inputs[0].isInteger()) {
- return call.inputs[0];
+ && receiver.inputs.length == 1
+ && receiver.inputs[0].isInteger()) {
+ return receiver.inputs[0];
}
- } else if (node.receiver.isConstantList() ||
- node.receiver.isConstantString()) {
- var instruction = node.receiver;
- return graph.addConstantInt(
- instruction.constant.length, compiler);
+ } else if (receiver.isConstantList() || receiver.isConstantString()) {
+ return graph.addConstantInt(receiver.constant.length, compiler);
+ } else {
+ var type = receiver.instructionType.computeMask(compiler);
+ if (type.isContainer && type.length != null) {
+ return graph.addConstantInt(type.length, compiler);
+ }
}
}
return node;
diff --git a/sdk/lib/_internal/compiler/implementation/types/concrete_types_inferrer.dart b/sdk/lib/_internal/compiler/implementation/types/concrete_types_inferrer.dart
index dd1935b..7b016b8 100644
--- a/sdk/lib/_internal/compiler/implementation/types/concrete_types_inferrer.dart
+++ b/sdk/lib/_internal/compiler/implementation/types/concrete_types_inferrer.dart
@@ -1365,7 +1365,7 @@
});
// handle initializing formals
- element.functionSignature.forEachParameter((param) {
+ element.computeSignature(compiler).forEachParameter((param) {
if (param.kind == ElementKind.FIELD_PARAMETER) {
FieldParameterElement fieldParam = param;
augmentFieldType(fieldParam.fieldElement,
@@ -1383,7 +1383,7 @@
new TypeInferrerVisitor(elements, element, this, environment);
bool foundSuperOrRedirect = false;
- if (tree.initializers != null) {
+ if (tree != null && tree.initializers != null) {
// we look for a possible call to super in the initializer list
for (final init in tree.initializers) {
init.accept(visitor);
@@ -1416,7 +1416,7 @@
}
}
- tree.accept(visitor);
+ if (tree != null) tree.accept(visitor);
return singletonConcreteType(new ClassBaseType(enclosingClass));
}
diff --git a/sdk/lib/_internal/compiler/implementation/types/container_tracer.dart b/sdk/lib/_internal/compiler/implementation/types/container_tracer.dart
index 92f69e7..156042e 100644
--- a/sdk/lib/_internal/compiler/implementation/types/container_tracer.dart
+++ b/sdk/lib/_internal/compiler/implementation/types/container_tracer.dart
@@ -79,6 +79,60 @@
'checkGrowable',
]);
+Set<String> doNotChangeLengthSelectorsSet = new Set<String>.from(
+ const <String>[
+ // From Object.
+ '==',
+ 'hashCode',
+ 'toString',
+ 'noSuchMethod',
+ 'runtimeType',
+
+ // From Iterable.
+ 'iterator',
+ 'map',
+ 'where',
+ 'expand',
+ 'contains',
+ 'forEach',
+ 'reduce',
+ 'fold',
+ 'every',
+ 'join',
+ 'any',
+ 'toList',
+ 'toSet',
+ 'length',
+ 'isEmpty',
+ 'isNotEmpty',
+ 'take',
+ 'takeWhile',
+ 'skip',
+ 'skipWhile',
+ 'first',
+ 'last',
+ 'single',
+ 'firstWhere',
+ 'lastWhere',
+ 'singleWhere',
+ 'elementAt',
+
+ // From List.
+ '[]',
+ 'length',
+ 'reversed',
+ 'sort',
+ 'indexOf',
+ 'lastIndexOf',
+ 'sublist',
+ 'getRange',
+ 'asMap',
+
+ // From JSArray.
+ 'checkMutable',
+ 'checkGrowable',
+ ]);
+
bool _VERBOSE = false;
/**
@@ -98,8 +152,7 @@
internal.concreteTypes.values.forEach((ContainerTypeMask mask) {
// The element type has already been set for const containers.
if (mask.elementType != null) return;
- mask.elementType = new TracerForConcreteContainer(
- mask, this, compiler, inferrer).run();
+ new TracerForConcreteContainer(mask, this, compiler, inferrer).run();
});
});
}
@@ -112,6 +165,7 @@
final Compiler compiler;
final ContainerTracer tracer;
final SimpleTypesInferrer inferrer;
+ final ContainerTypeMask mask;
final Node analyzedNode;
final Element startElement;
@@ -138,6 +192,8 @@
static const int MAX_ANALYSIS_COUNT = 11;
TypeMask potentialType;
+ int potentialLength;
+ bool isLengthTrackingDisabled = false;
bool continueAnalyzing = true;
TracerForConcreteContainer(ContainerTypeMask mask,
@@ -145,9 +201,10 @@
this.compiler,
this.inferrer)
: analyzedNode = mask.allocationNode,
- startElement = mask.allocationElement;
+ startElement = mask.allocationElement,
+ this.mask = mask;
- TypeMask run() {
+ void run() {
int analysisCount = 0;
workList.add(startElement);
while (!workList.isEmpty) {
@@ -161,11 +218,20 @@
analysisCount++;
}
- if (!continueAnalyzing) return compiler.typesTask.dynamicType;
+ if (!continueAnalyzing) {
+ if (mask.forwardTo == compiler.typesTask.fixedListType) {
+ mask.length = potentialLength;
+ }
+ mask.elementType = compiler.typesTask.dynamicType;
+ return;
+ }
// [potentialType] can be null if we did not find any instruction
// that adds elements to the list.
- if (potentialType == null) return new TypeMask.nonNullEmpty();
+ if (potentialType == null) {
+ mask.elementType = new TypeMask.nonNullEmpty();
+ return;
+ }
// Walk over the found constraints and update the type according
// to the selectors of these constraints.
@@ -176,11 +242,26 @@
inferrer.getTypeOfSelector(constraint), compiler);
}
if (_VERBOSE) {
- print('$potentialType for $analyzedNode $startElement');
+ print('$potentialType and $potentialLength '
+ 'for $analyzedNode $startElement');
}
- return potentialType;
+ mask.elementType = potentialType;
+ mask.length = potentialLength;
}
+ void disableLengthTracking() {
+ if (mask.forwardTo == compiler.typesTask.fixedListType) {
+ // Bogus update to a fixed list.
+ return;
+ }
+ isLengthTrackingDisabled = true;
+ potentialLength = null;
+ }
+
+ void setPotentialLength(int value) {
+ if (isLengthTrackingDisabled) return;
+ potentialLength = value;
+ }
void unionPotentialTypeWith(TypeMask newType) {
assert(newType != null);
@@ -360,12 +441,17 @@
}
TypeMask visitLiteralList(LiteralList node) {
- if (node.isConst()) return compiler.typesTask.constListType;
+ if (node.isConst()) {
+ return inferrer.internal.concreteTypes[node];
+ }
if (tracer.couldBeTheList(node)) {
escaping = true;
+ int length = 0;
for (Node element in node.elements.nodes) {
tracer.unionPotentialTypeWith(visit(element));
+ length++;
}
+ tracer.setPotentialLength(length);
} else {
node.visitChildren(this);
}
@@ -465,7 +551,7 @@
}
} else if (isReceiver) {
if (setterSelector.name == const SourceString('length')) {
- // Changing the length.
+ tracer.disableLengthTracking();
tracer.unionPotentialTypeWith(compiler.typesTask.nullType);
}
} else if (isValueEscaping) {
@@ -532,24 +618,32 @@
if (tracer.couldBeTheList(node)) {
escaping = true;
}
- return compiler.typesTask.growableListType;
+ return inferrer.internal.concreteTypes[node];
} else if (Elements.isFixedListConstructorCall(element, node, compiler)) {
- tracer.unionPotentialTypeWith(compiler.typesTask.nullType);
visitArguments(node.arguments, element);
if (tracer.couldBeTheList(node)) {
+ tracer.unionPotentialTypeWith(compiler.typesTask.nullType);
escaping = true;
+ LiteralInt length = node.arguments.head.asLiteralInt();
+ if (length != null) {
+ tracer.setPotentialLength(length.value);
+ }
}
- return compiler.typesTask.fixedListType;
+ return inferrer.internal.concreteTypes[node];
} else if (Elements.isFilledListConstructorCall(element, node, compiler)) {
if (tracer.couldBeTheList(node)) {
escaping = true;
visit(node.arguments.head);
TypeMask fillWithType = visit(node.arguments.tail.head);
tracer.unionPotentialTypeWith(fillWithType);
+ LiteralInt length = node.arguments.head.asLiteralInt();
+ if (length != null) {
+ tracer.setPotentialLength(length.value);
+ }
} else {
visitArguments(node.arguments, element);
}
- return compiler.typesTask.fixedListType;
+ return inferrer.internal.concreteTypes[node];
}
bool isEscaping = visitArguments(node.arguments, element);
@@ -639,6 +733,9 @@
} else if (!node.isPropertyAccess) {
visitArguments(node.arguments, selector);
}
+ if (isReceiver && !doNotChangeLengthSelectorsSet.contains(selectorName)) {
+ tracer.disableLengthTracking();
+ }
if (tracer.couldBeTheList(selector)) {
escaping = true;
}
diff --git a/sdk/lib/_internal/compiler/implementation/types/container_type_mask.dart b/sdk/lib/_internal/compiler/implementation/types/container_type_mask.dart
index f9fc659..79281c0 100644
--- a/sdk/lib/_internal/compiler/implementation/types/container_type_mask.dart
+++ b/sdk/lib/_internal/compiler/implementation/types/container_type_mask.dart
@@ -8,8 +8,9 @@
/// that nullable ContainerTypeMask and non-nullable ContainerTypeMask
/// share the same [ElementTypeHolder].
class ElementTypeHolder {
- // This field will be set after global analysis.
+ // These fields will be set after global analysis.
TypeMask elementType;
+ int length;
int get hashCode => elementType.hashCode;
}
@@ -36,6 +37,10 @@
void set elementType(TypeMask mask) {
holder.elementType = mask;
}
+ int get length => holder.length;
+ void set length(int length) {
+ holder.length = length;
+ }
ContainerTypeMask(this.forwardTo,
this.allocationNode,
diff --git a/sdk/lib/_internal/compiler/implementation/types/inferrer_visitor.dart b/sdk/lib/_internal/compiler/implementation/types/inferrer_visitor.dart
index eb82a47..d357a35 100644
--- a/sdk/lib/_internal/compiler/implementation/types/inferrer_visitor.dart
+++ b/sdk/lib/_internal/compiler/implementation/types/inferrer_visitor.dart
@@ -52,12 +52,73 @@
}
/**
+ * A variable scope holds types for variables. It has a link to a
+ * parent scope, but never changes the types in that parent. Instead,
+ * updates to locals of a parent scope are put in the current scope.
+ * The inferrer makes sure updates get merged into the parent scope,
+ * once the control flow block has been visited.
+ */
+class VariableScope {
+ Map<Element, TypeMask> variables;
+
+ /// The parent of this scope. Null for the root scope.
+ final VariableScope parent;
+
+ /// The block level of this scope. Starts at 0 for the root scope.
+ final int blockLevel;
+
+ VariableScope([parent])
+ : this.variables = null,
+ this.parent = parent,
+ this.blockLevel = parent == null ? 0 : parent.blockLevel + 1;
+
+ VariableScope.deepCopyOf(VariableScope other)
+ : variables = other.variables == null
+ ? null
+ : new Map<Element, TypeMask>.from(other.variables),
+ blockLevel = other.blockLevel,
+ parent = other.parent == null
+ ? null
+ : new VariableScope.deepCopyOf(other.parent);
+
+ TypeMask operator [](Element variable) {
+ TypeMask result;
+ if (variables == null || (result = variables[variable]) == null) {
+ return parent == null ? null : parent[variable];
+ }
+ return result;
+ }
+
+ void operator []=(Element variable, TypeMask mask) {
+ assert(mask != null);
+ if (variables == null) {
+ variables = new Map<Element, TypeMask>();
+ }
+ variables[variable] = mask;
+ }
+
+ void forEachOwnLocal(void f(Element element, TypeMask mask)) {
+ if (variables == null) return;
+ variables.forEach(f);
+ }
+
+ void remove(Element element) {
+ variables.remove(element);
+ }
+
+ String toString() {
+ String rest = parent == null ? "null" : parent.toString();
+ return '$blockLevel: $variables $rest';
+ }
+}
+
+/**
* Placeholder for inferred types of local variables.
*/
class LocalsHandler {
final Compiler compiler;
final TypesInferrer inferrer;
- final Map<Element, TypeMask> locals;
+ final VariableScope locals;
final Map<Element, Element> capturedAndBoxed;
final Map<Element, TypeMask> fieldsInitializedInConstructor;
final bool inTryBlock;
@@ -70,13 +131,14 @@
}
LocalsHandler(this.inferrer, this.compiler)
- : locals = new Map<Element, TypeMask>(),
+ : locals = new VariableScope(),
capturedAndBoxed = new Map<Element, Element>(),
fieldsInitializedInConstructor = new Map<Element, TypeMask>(),
inTryBlock = false,
isThisExposed = true;
+
LocalsHandler.from(LocalsHandler other, {bool inTryBlock: false})
- : locals = new Map<Element, TypeMask>.from(other.locals),
+ : locals = new VariableScope(other.locals),
capturedAndBoxed = new Map<Element, Element>.from(
other.capturedAndBoxed),
fieldsInitializedInConstructor = new Map<Element, TypeMask>.from(
@@ -86,6 +148,17 @@
compiler = other.compiler,
isThisExposed = other.isThisExposed;
+ LocalsHandler.deepCopyOf(LocalsHandler other)
+ : locals = new VariableScope.deepCopyOf(other.locals),
+ capturedAndBoxed = new Map<Element, Element>.from(
+ other.capturedAndBoxed),
+ fieldsInitializedInConstructor = new Map<Element, TypeMask>.from(
+ other.fieldsInitializedInConstructor),
+ inTryBlock = other.inTryBlock,
+ inferrer = other.inferrer,
+ compiler = other.compiler,
+ isThisExposed = other.isThisExposed;
+
TypeMask use(Element local) {
if (capturedAndBoxed.containsKey(local)) {
return inferrer.getTypeOfElement(capturedAndBoxed[local]);
@@ -119,31 +192,43 @@
* whether the merge changed one of the variables types in [first].
*/
bool merge(LocalsHandler other, {bool discardIfAborts: true}) {
+ VariableScope currentOther = other.locals;
+ assert(currentOther != locals);
bool changed = false;
- List<Element> toRemove = <Element>[];
- // Iterating over a map and just updating its entries is OK.
- locals.forEach((Element local, TypeMask oldType) {
- TypeMask otherType = other.locals[local];
- bool isCaptured = capturedAndBoxed.containsKey(local);
- if (otherType == null) {
- if (!isCaptured) {
- // If [local] is not in the other map and is not captured
- // and boxed, we know it is not a
- // local we want to keep. For example, in an if/else, we don't
- // want to keep variables declared in the if or in the else
- // branch at the merge point.
- toRemove.add(local);
+ // Iterate over all updates in the other handler until we reach
+ // the block level of this handler. We know that [VariableScope]s
+ // that are lower in block level, are the same.
+ do {
+ currentOther.forEachOwnLocal((Element local, TypeMask otherType) {
+ TypeMask myType = locals[local];
+ if (myType == null) return;
+ bool isCaptured = capturedAndBoxed.containsKey(local);
+ if (!isCaptured && aborts && discardIfAborts) {
+ locals[local] = otherType;
+ } else if (!isCaptured && other.aborts && discardIfAborts) {
+ // Don't do anything.
+ } else {
+ TypeMask type = computeLUB(myType, otherType, compiler);
+ if (type != myType) {
+ changed = true;
+ }
+ locals[local] = type;
}
- return;
- }
- if (!isCaptured && aborts && discardIfAborts) {
- locals[local] = otherType;
- } else if (!isCaptured && other.aborts && discardIfAborts) {
- // Don't do anything.
- } else {
- TypeMask type = computeLUB(oldType, otherType, compiler);
- if (type != oldType) changed = true;
- locals[local] = type;
+ });
+ currentOther = currentOther.parent;
+ } while (currentOther != null
+ && currentOther.blockLevel >= locals.blockLevel);
+
+ List<Element> toRemove = <Element>[];
+ locals.forEachOwnLocal((Element local, _) {
+ bool isCaptured = capturedAndBoxed.containsKey(local);
+ if (other.locals[local] == null && !isCaptured) {
+ // If [local] is not in the other map and is not captured
+ // and boxed, we know it is not a
+ // local we want to keep. For example, in an if/else, we don't
+ // want to keep variables declared in the if or in the else
+ // branch at the merge point.
+ toRemove.add(local);
}
});
@@ -159,7 +244,7 @@
capturedAndBoxed[local] = field;
// If [element] is not in our [locals], we need to update it.
// Otherwise, we have already computed the LUB of it.
- if (locals[local] == null) {
+ if (locals[local] == null && other.locals[local] != null) {
locals[local] = other.locals[local];
}
});
@@ -394,21 +479,25 @@
visit(node.receiver);
accumulateIsChecks = oldAccumulateIsChecks;
if (!accumulateIsChecks) isChecks = null;
- LocalsHandler saved = new LocalsHandler.from(locals);
+ LocalsHandler saved = locals;
+ locals = new LocalsHandler.from(locals);
updateIsChecks(isChecks, usePositive: true);
visit(node.arguments.head);
- locals.merge(saved);
+ saved.merge(locals);
+ locals = saved;
return compiler.typesTask.boolType;
} else if (const SourceString("||") == op.source) {
conditionIsSimple = false;
visit(node.receiver);
- LocalsHandler saved = new LocalsHandler.from(locals);
+ LocalsHandler saved = locals;
+ locals = new LocalsHandler.from(locals);
updateIsChecks(isChecks, usePositive: false);
bool oldAccumulateIsChecks = accumulateIsChecks;
accumulateIsChecks = false;
visit(node.arguments.head);
accumulateIsChecks = oldAccumulateIsChecks;
- locals.merge(saved);
+ saved.merge(locals);
+ locals = saved;
return compiler.typesTask.boolType;
} else if (const SourceString("!") == op.source) {
bool oldAccumulateIsChecks = accumulateIsChecks;
@@ -446,7 +535,8 @@
TypeMask visitConditional(Conditional node) {
List<Send> tests = <Send>[];
bool simpleCondition = handleCondition(node.condition, tests);
- LocalsHandler saved = new LocalsHandler.from(locals);
+ LocalsHandler saved = locals;
+ locals = new LocalsHandler.from(locals);
updateIsChecks(tests, usePositive: true);
TypeMask firstType = visit(node.thenExpression);
LocalsHandler thenLocals = locals;
@@ -491,7 +581,8 @@
TypeMask visitIf(If node) {
List<Send> tests = <Send>[];
bool simpleCondition = handleCondition(node.condition, tests);
- LocalsHandler saved = new LocalsHandler.from(locals);
+ LocalsHandler saved = locals;
+ locals = new LocalsHandler.from(locals);
updateIsChecks(tests, usePositive: true);
visit(node.thenPart);
LocalsHandler thenLocals = locals;
@@ -537,7 +628,8 @@
TargetElement target = elements[node];
setupBreaksAndContinues(target);
do {
- LocalsHandler saved = new LocalsHandler.from(locals);
+ LocalsHandler saved = locals;
+ locals = new LocalsHandler.from(locals);
logic();
changed = saved.merge(locals);
locals = saved;
@@ -585,7 +677,8 @@
saved.merge(locals);
locals = saved;
for (Node catchBlock in node.catchBlocks) {
- saved = new LocalsHandler.from(locals);
+ saved = locals;
+ locals = new LocalsHandler.from(locals);
visit(catchBlock);
saved.merge(locals);
locals = saved;
@@ -651,15 +744,19 @@
TypeMask visitBreakStatement(BreakStatement node) {
TargetElement target = elements[node];
- breaksFor[target].add(locals);
locals.seenBreakOrContinue = true;
+ // Do a deep-copy of the locals, because the code following the
+ // break will change them.
+ breaksFor[target].add(new LocalsHandler.deepCopyOf(locals));
return compiler.typesTask.dynamicType;
}
TypeMask visitContinueStatement(ContinueStatement node) {
TargetElement target = elements[node];
- continuesFor[target].add(locals);
locals.seenBreakOrContinue = true;
+ // Do a deep-copy of the locals, because the code following the
+ // continue will change them.
+ continuesFor[target].add(new LocalsHandler.deepCopyOf(locals));
return compiler.typesTask.dynamicType;
}
@@ -695,7 +792,8 @@
do {
changed = false;
for (Node switchCase in node.cases) {
- LocalsHandler saved = new LocalsHandler.from(locals);
+ LocalsHandler saved = locals;
+ locals = new LocalsHandler.from(locals);
visit(switchCase);
changed = saved.merge(locals, discardIfAborts: false) || changed;
locals = saved;
@@ -706,24 +804,26 @@
clearBreaksAndContinues(target);
});
} else {
- LocalsHandler saved = new LocalsHandler.from(locals);
- // If there is a default case, the current values of the local
- // variable might be overwritten, so we don't need the current
- // [locals] for the join block.
- LocalsHandler result = Elements.switchStatementHasDefault(node)
- ? null
- : new LocalsHandler.from(locals);
+ LocalsHandler saved = locals;
+ List<LocalsHandler> localsToMerge = <LocalsHandler>[];
- for (Node switchCase in node.cases) {
- locals = new LocalsHandler.from(saved);
- visit(switchCase);
- if (result == null) {
- result = locals;
+ for (SwitchCase switchCase in node.cases) {
+ if (switchCase.isDefaultCase) {
+ // If there is a default case, the current values of the local
+ // variable might be overwritten, so we don't need the current
+ // [locals] for the join block.
+ locals = saved;
+ visit(switchCase);
} else {
- result.merge(locals, discardIfAborts: false);
+ locals = new LocalsHandler.from(saved);
+ visit(switchCase);
+ localsToMerge.add(locals);
}
}
- locals = result;
+ for (LocalsHandler handler in localsToMerge) {
+ saved.merge(handler, discardIfAborts: false);
+ }
+ locals = saved;
}
clearBreaksAndContinues(elements[node]);
// In case there is a default in the switch we discard the
diff --git a/sdk/lib/_internal/compiler/implementation/types/simple_types_inferrer.dart b/sdk/lib/_internal/compiler/implementation/types/simple_types_inferrer.dart
index 6b49b54..2a0c230 100644
--- a/sdk/lib/_internal/compiler/implementation/types/simple_types_inferrer.dart
+++ b/sdk/lib/_internal/compiler/implementation/types/simple_types_inferrer.dart
@@ -571,9 +571,6 @@
}
bool analyze(Element element) {
- if (element.isForwardingConstructor) {
- element = element.targetConstructor;
- }
SimpleTypeInferrerVisitor visitor =
new SimpleTypeInferrerVisitor(element, compiler, this);
TypeMask returnType = visitor.run();
@@ -1439,10 +1436,16 @@
locals.update(element, parameterType);
}
});
- visitingInitializers = true;
- visit(node.initializers);
- visitingInitializers = false;
- visit(node.body);
+ if (analyzedElement.isSynthesized) {
+ // Use the enclosing class of the synthesized constructor as
+ // the location for the initialized fields.
+ node = analyzedElement.enclosingElement.parseNode(compiler);
+ } else {
+ visitingInitializers = true;
+ visit(node.initializers);
+ visitingInitializers = false;
+ visit(node.body);
+ }
ClassElement cls = analyzedElement.getEnclosingClass();
if (!isConstructorRedirect) {
// Iterate over all instance fields, and give a null type to
@@ -1540,10 +1543,13 @@
ContainerTypeMask container = new ContainerTypeMask(
inferrer.constListType, node, outermostElement);
TypeMask elementType = new TypeMask.nonNullEmpty();
+ int length = 0;
for (Node element in node.elements.nodes) {
+ length++;
elementType = computeLUB(elementType, visit(element), compiler);
}
container.elementType = elementType;
+ container.length = length;
return container;
});
} else {
diff --git a/sdk/lib/_internal/compiler/implementation/universe/universe.dart b/sdk/lib/_internal/compiler/implementation/universe/universe.dart
index db18031..5f76676 100644
--- a/sdk/lib/_internal/compiler/implementation/universe/universe.dart
+++ b/sdk/lib/_internal/compiler/implementation/universe/universe.dart
@@ -376,7 +376,7 @@
* of an argument located in [arguments].
*
* [compileConstant] is a function that returns a compiled constant
- * of an optional argument that is not in [arguments.
+ * of an optional argument that is not in [arguments].
*
* Returns [:true:] if the selector and the [element] match; [:false:]
* otherwise.
@@ -429,6 +429,79 @@
return true;
}
+ /**
+ * Fills [list] with the arguments in the order expected by
+ * [callee], and where [caller] is a synthesized element
+ *
+ * [compileArgument] is a function that returns a compiled version
+ * of a parameter of [callee].
+ *
+ * [compileConstant] is a function that returns a compiled constant
+ * of an optional argument that is not in the parameters of [callee].
+ *
+ * Returns [:true:] if the signature of the [caller] matches the
+ * signature of the [callee], [:false:] otherwise.
+ */
+ static bool addForwardingElementArgumentsToList(
+ FunctionElement caller,
+ List list,
+ FunctionElement callee,
+ compileArgument(Element element),
+ compileConstant(Element element),
+ Compiler compiler) {
+
+ FunctionSignature signature = caller.computeSignature(compiler);
+ Map mapping = new Map();
+
+ // TODO(ngeoffray): This is a hack that fakes up AST nodes, so
+ // that we can call [addArgumentsToList].
+ Link computeCallNodesFromParameters() {
+ LinkBuilder builder = new LinkBuilder();
+ signature.forEachRequiredParameter((Element element) {
+ Node node = element.parseNode(compiler);
+ mapping[node] = element;
+ builder.addLast(node);
+ });
+ if (signature.optionalParametersAreNamed) {
+ signature.forEachOptionalParameter((Element element) {
+ Node node = element.parseNode(compiler);
+ mapping[node] = element;
+ builder.addLast(new NamedArgument(null, null, node));
+ });
+ } else {
+ signature.forEachOptionalParameter((Element element) {
+ Node node = element.parseNode(compiler);
+ mapping[node] = element;
+ builder.addLast(node);
+ });
+ }
+ return builder.toLink();
+ }
+
+ internalCompileArgument(Node node) => compileArgument(mapping[node]);
+
+ Link<Node> nodes = computeCallNodesFromParameters();
+
+ // Synthesize a selector for the call.
+ // TODO(ngeoffray): Should the resolver do it instead?
+ List<SourceString> namedParameters;
+ if (signature.optionalParametersAreNamed) {
+ namedParameters =
+ signature.optionalParameters.toList().map((e) => e.name).toList();
+ }
+ Selector selector = new Selector.call(callee.name,
+ caller.getLibrary(),
+ signature.parameterCount,
+ namedParameters);
+
+ return selector.addArgumentsToList(nodes,
+ list,
+ callee,
+ internalCompileArgument,
+ compileConstant,
+ compiler);
+ }
+
static bool sameNames(List<SourceString> first, List<SourceString> second) {
for (int i = 0; i < first.length; i++) {
if (first[i] != second[i]) return false;
diff --git a/sdk/lib/_internal/lib/core_patch.dart b/sdk/lib/_internal/lib/core_patch.dart
index 7306375..9d44abf 100644
--- a/sdk/lib/_internal/lib/core_patch.dart
+++ b/sdk/lib/_internal/lib/core_patch.dart
@@ -114,13 +114,12 @@
patch static String _objectToString(Object object) {
return Primitives.objectToString(object);
}
-}
-patch class StackTraceOnThrow {
- // TODO(11681): implement stackTrace on thrown Error.
+ // TODO(11681): implement stackTrace in error object.
patch StackTrace get stackTrace => null;
}
+
// Patch for DateTime implementation.
patch class DateTime {
patch DateTime._internal(int year,
diff --git a/sdk/lib/_internal/lib/js_helper.dart b/sdk/lib/_internal/lib/js_helper.dart
index 52324fb..32835bf 100644
--- a/sdk/lib/_internal/lib/js_helper.dart
+++ b/sdk/lib/_internal/lib/js_helper.dart
@@ -1486,7 +1486,7 @@
/**
* Error thrown when a runtime error occurs.
*/
-class RuntimeError extends Error with StackTraceOnThrow {
+class RuntimeError extends Error {
final message;
RuntimeError(this.message);
String toString() => "RuntimeError: $message";
diff --git a/sdk/lib/_internal/pub/lib/src/source/hosted.dart b/sdk/lib/_internal/pub/lib/src/source/hosted.dart
index f65a56a..aec150c 100644
--- a/sdk/lib/_internal/pub/lib/src/source/hosted.dart
+++ b/sdk/lib/_internal/pub/lib/src/source/hosted.dart
@@ -31,7 +31,11 @@
/// Gets the default URL for the package server for hosted dependencies.
static String get defaultUrl {
var url = io.Platform.environment["PUB_HOSTED_URL"];
- if (url != null) return url;
+ if (url != null) {
+ log.fine("Got server $url from PUB_HOSTED_URL.");
+ return url;
+ }
+
return "https://pub.dartlang.org";
}
diff --git a/sdk/lib/_internal/pub/test/install/switch_source_test.dart b/sdk/lib/_internal/pub/test/install/switch_source_test.dart
index 428292e..6ca3981 100644
--- a/sdk/lib/_internal/pub/test/install/switch_source_test.dart
+++ b/sdk/lib/_internal/pub/test/install/switch_source_test.dart
@@ -12,6 +12,8 @@
main() {
initConfig();
integration('re-installs a package if its source has changed', () {
+ servePackages([packageMap("foo", "1.2.3")]);
+
d.dir('foo', [
d.libDir('foo', 'foo 0.0.1'),
d.libPubspec('foo', '0.0.1')
@@ -22,7 +24,6 @@
pubInstall();
d.packagesDir({"foo": "0.0.1"}).validate();
- servePackages([packageMap("foo", "1.2.3")]);
d.appDir([dependencyMap("foo", "any")]).create();
pubInstall();
diff --git a/sdk/lib/_internal/pub/test/test_pub.dart b/sdk/lib/_internal/pub/test/test_pub.dart
index f1b66b7..5d1afcf 100644
--- a/sdk/lib/_internal/pub/test/test_pub.dart
+++ b/sdk/lib/_internal/pub/test/test_pub.dart
@@ -91,6 +91,8 @@
void serve([List<d.Descriptor> contents]) {
var baseDir = d.dir("serve-dir", contents);
+ _hasServer = true;
+
schedule(() {
return _closeServer().then((_) {
return SafeHttpServer.bind("localhost", 0).then((server) {
@@ -144,6 +146,9 @@
return sleep(10);
}
+/// `true` if the current test spins up an HTTP server.
+bool _hasServer = false;
+
/// The [d.DirectoryDescriptor] describing the server layout of `/api/packages`
/// on the test server.
///
@@ -458,6 +463,16 @@
environment['_PUB_TEST_TOKEN_ENDPOINT'] =
tokenEndpoint.toString();
}
+
+ // If there is a server running, tell pub what its URL is so hosted
+ // dependencies will look there.
+ if (_hasServer) {
+ return port.then((p) {
+ environment['PUB_HOSTED_URL'] = "http://localhost:$p";
+ return environment;
+ });
+ }
+
return environment;
});
@@ -609,8 +624,7 @@
/// Describes a map representing a dependency on a package in the package
/// repository.
Map dependencyMap(String name, [String versionConstraint]) {
- var url = port.then((p) => "http://localhost:$p");
- var dependency = {"hosted": {"name": name, "url": url}};
+ var dependency = {"hosted": name};
if (versionConstraint != null) dependency["version"] = versionConstraint;
return dependency;
}
diff --git a/sdk/lib/core/errors.dart b/sdk/lib/core/errors.dart
index 6f01ce0..f61cdfe 100644
--- a/sdk/lib/core/errors.dart
+++ b/sdk/lib/core/errors.dart
@@ -5,8 +5,6 @@
part of dart.core;
class Error {
- const Error();
-
/**
* Safely convert a value to a [String] description.
*
@@ -33,33 +31,13 @@
external static String _objectToString(Object object);
- /**
- * The stack trace of `this` error. May be null.
- */
- StackTrace get stackTrace => null;
-}
-
-/**
- * Captures the stack trace when thrown.
- */
-class StackTraceOnThrow {
- /**
- * Captures the current stack-trace when thrown.
- *
- * Classes extending or mixing-in this class will automatically have a stack
- * trace captured the first time they are thrown. This stack trace is returned
- * by the [stackTrace] getter.
- *
- * Throwing the object again will not cause overwrite the first stack trace,
- * so bjects that are `StackTraceOnThrow` instances should not be reused.
- */
external StackTrace get stackTrace;
}
/**
* Error thrown by the runtime system when an assert statement fails.
*/
-class AssertionError extends Error with StackTraceOnThrow {
+class AssertionError extends Error {
}
/**
@@ -71,13 +49,13 @@
/**
* Error thrown by the runtime system when a cast operation fails.
*/
-class CastError extends Error with StackTraceOnThrow {
+class CastError extends Error {
}
/**
* Error thrown when attempting to throw [:null:].
*/
-class NullThrownError extends Error with StackTraceOnThrow {
+class NullThrownError extends Error {
NullThrownError();
String toString() => "Throw of null.";
}
@@ -85,7 +63,7 @@
/**
* Error thrown when a function is passed an unacceptable argument.
*/
-class ArgumentError extends Error with StackTraceOnThrow {
+class ArgumentError extends Error {
final message;
/** The [message] describes the erroneous argument. */
@@ -132,12 +110,12 @@
* of a switch) without meeting a break or similar end of the control
* flow.
*/
-class FallThroughError extends Error with StackTraceOnThrow {
+class FallThroughError extends Error {
+ FallThroughError();
}
-class AbstractClassInstantiationError
- extends Error with StackTraceOnThrow {
+class AbstractClassInstantiationError extends Error {
final String _className;
AbstractClassInstantiationError(String this._className);
String toString() => "Cannot instantiate abstract class: '$_className'";
@@ -146,7 +124,7 @@
/**
* Error thrown by the default implementation of [:noSuchMethod:] on [Object].
*/
-class NoSuchMethodError extends Error with StackTraceOnThrow {
+class NoSuchMethodError extends Error {
final Object _receiver;
final String _memberName;
final List _arguments;
@@ -184,7 +162,7 @@
* This [Error] is thrown when an instance cannot implement one of the methods
* in its signature.
*/
-class UnsupportedError extends Error with StackTraceOnThrow {
+class UnsupportedError extends Error {
final String message;
UnsupportedError(this.message);
String toString() => "Unsupported operation: $message";
@@ -201,8 +179,7 @@
* an [UnsupportedError] instead. This error is only intended for
* use during development.
*/
-class UnimplementedError
- extends Error with StackTraceOnThrow implements UnsupportedError {
+class UnimplementedError extends Error implements UnsupportedError {
final String message;
UnimplementedError([String this.message]);
String toString() => (this.message != null
@@ -217,7 +194,7 @@
* This is a generic error used for a variety of different erroneous
* actions. The message should be descriptive.
*/
-class StateError extends Error with StackTraceOnThrow {
+class StateError extends Error {
final String message;
StateError(this.message);
String toString() => "Bad state: $message";
@@ -231,7 +208,7 @@
* ([Iterable] or similar collection of values) should declare which operations
* are allowed during an iteration.
*/
-class ConcurrentModificationError extends Error with StackTraceOnThrow {
+class ConcurrentModificationError extends Error {
/** The object that was modified in an incompatible way. */
final Object modifiedObject;
@@ -247,15 +224,19 @@
}
-class OutOfMemoryError extends Error {
+class OutOfMemoryError implements Error {
const OutOfMemoryError();
String toString() => "Out of Memory";
+
+ StackTrace get stackTrace => null;
}
-class StackOverflowError extends Error {
+class StackOverflowError implements Error {
const StackOverflowError();
String toString() => "Stack Overflow";
+
+ StackTrace get stackTrace => null;
}
/**
@@ -265,7 +246,7 @@
* the first time it is read. If evaluating the initializer expression causes
* another read of the variable, this error is thrown.
*/
-class CyclicInitializationError extends Error with StackTraceOnThrow {
+class CyclicInitializationError extends Error {
final String variableName;
CyclicInitializationError([this.variableName]);
String toString() => variableName == null
diff --git a/sdk/lib/html/dart2js/html_dart2js.dart b/sdk/lib/html/dart2js/html_dart2js.dart
index 1733d9e..2870931 100644
--- a/sdk/lib/html/dart2js/html_dart2js.dart
+++ b/sdk/lib/html/dart2js/html_dart2js.dart
@@ -63,6 +63,7 @@
// Workaround for tags like <cite> that lack their own Element subclass --
// Dart issue 1990.
class _HTMLElement extends Element native "HTMLElement" {
+ factory _HTMLElement() { throw new UnsupportedError("Not supported"); }
}
// Support for Send/ReceivePortSync.
diff --git a/sdk/lib/json/json.dart b/sdk/lib/json/json.dart
index 79e5aba..28d3df9 100644
--- a/sdk/lib/json/json.dart
+++ b/sdk/lib/json/json.dart
@@ -16,7 +16,7 @@
* [cause] field. If the call returns an object that isn't directly
* serializable, the [cause] will be null.
*/
-class JsonUnsupportedObjectError extends Error with StackTraceOnThrow {
+class JsonUnsupportedObjectError extends Error {
/** The object that could not be serialized. */
final unsupportedObject;
/** The exception thrown by object's [:toJson:] method, if any. */
diff --git a/tests/co19/co19-analyzer.status b/tests/co19/co19-analyzer.status
index 2820b5f..aaea30a 100644
--- a/tests/co19/co19-analyzer.status
+++ b/tests/co19/co19-analyzer.status
@@ -89,11 +89,6 @@
Language/03_Overview/1_Scoping_A02_t07: fail, OK
Language/12_Statements/04_Local_Function_Declaration_A01_t01: fail, OK
-# co19 issue #417, 'if', 'while' and 'do-while' don't create scope
-Language/03_Overview/1_Scoping_A02_t11: fail, OK
-Language/03_Overview/1_Scoping_A02_t12: fail, OK
-Language/03_Overview/1_Scoping_A02_t16: fail, OK
-
# co19 issue #420, 'throw' without exception; deprecated; rethrow should be used
Language/11_Expressions/08_Throw_A05_t01: fail, OK
Language/11_Expressions/08_Throw_A05_t02: fail, OK
diff --git a/tests/compiler/dart2js/analyze_api_test.dart b/tests/compiler/dart2js/analyze_api_test.dart
index 2df61b1..ec291dd 100644
--- a/tests/compiler/dart2js/analyze_api_test.dart
+++ b/tests/compiler/dart2js/analyze_api_test.dart
@@ -4,7 +4,6 @@
library analyze_api;
-import "package:expect/expect.dart";
import '../../../sdk/lib/_internal/libraries.dart';
import 'analyze_helper.dart';
diff --git a/tests/compiler/dart2js/cpa_inference_test.dart b/tests/compiler/dart2js/cpa_inference_test.dart
index 1171906..d6e1a83 100644
--- a/tests/compiler/dart2js/cpa_inference_test.dart
+++ b/tests/compiler/dart2js/cpa_inference_test.dart
@@ -160,7 +160,9 @@
}
class bool {}
class String {}
- class Object {}
+ class Object {
+ Object();
+ }
class Function {}
abstract class List<E> {
factory List([int length]) {}
diff --git a/tests/compiler/dart2js/dart_backend_test.dart b/tests/compiler/dart2js/dart_backend_test.dart
index 112f0fa..aa5a70f 100644
--- a/tests/compiler/dart2js/dart_backend_test.dart
+++ b/tests/compiler/dart2js/dart_backend_test.dart
@@ -14,7 +14,9 @@
const coreLib = r'''
library corelib;
-class Object {}
+class Object {
+ Object();
+}
class bool {}
class num {}
class int extends num {}
diff --git a/tests/compiler/dart2js/list_tracer2_test.dart b/tests/compiler/dart2js/list_tracer2_test.dart
new file mode 100644
index 0000000..0bc6126
--- /dev/null
+++ b/tests/compiler/dart2js/list_tracer2_test.dart
@@ -0,0 +1,38 @@
+// Copyright (c) 2013, 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.
+
+// We used to always nullify the element type of a list we are tracing in
+// the presence of a fixed length list constructor call.
+
+import 'package:expect/expect.dart';
+import
+ '../../../sdk/lib/_internal/compiler/implementation/types/types.dart'
+ show ContainerTypeMask, TypeMask;
+
+import 'compiler_helper.dart';
+import 'parser_helper.dart';
+
+
+const String TEST = r'''
+var myList = [42];
+main() {
+ var a = new List(42);
+ return myList[0];
+}
+''';
+
+void main() {
+ Uri uri = new Uri(scheme: 'source');
+ var compiler = compilerFor(TEST, uri);
+ compiler.runCompiler(uri);
+ var typesInferrer = compiler.typesTask.typesInferrer;
+
+ checkType(String name, type) {
+ var element = findElement(compiler, name);
+ ContainerTypeMask mask = typesInferrer.getTypeOfElement(element);
+ Expect.equals(type, mask.elementType.simplify(compiler), name);
+ }
+
+ checkType('myList', compiler.typesTask.intType);
+}
diff --git a/tests/compiler/dart2js/list_tracer_length_test.dart b/tests/compiler/dart2js/list_tracer_length_test.dart
new file mode 100644
index 0000000..2a48ef5
--- /dev/null
+++ b/tests/compiler/dart2js/list_tracer_length_test.dart
@@ -0,0 +1,80 @@
+// Copyright (c) 2013, 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:expect/expect.dart";
+import 'compiler_helper.dart';
+
+const String TEST1 = r"""
+var a = [42];
+main() {
+ return a[0];
+}
+""";
+
+String TEST2(selectorName, args) {
+ return """
+var a = [42];
+main() {
+ a.$selectorName($args);
+ return a[0];
+}
+""";
+}
+
+const String TEST3 = r"""
+var a = new List(42);
+main() {
+ return a[0];
+}
+""";
+
+const String TEST4 = r"""
+var a = new List(0);
+main() {
+ return a[0];
+}
+""";
+
+const String TEST5 = r"""
+var a = [42];
+main() {
+ a.length = 54;
+ return a[0];
+}
+""";
+
+// Test that the order in which we visit the methods will not bring
+// back a length after it has been disabled.
+const String TEST6 = r"""
+foo(b) {
+ var a = [42];
+ doIt(a);
+ return a[0];
+}
+
+doIt(a) {
+ a.clear();
+ foo(a);
+}
+main() {
+ foo(null);
+}
+""";
+
+void checkRangeError(String test, {bool hasRangeError}) {
+ String generated = compileAll(test);
+ Expect.equals(hasRangeError, generated.contains('ioore'));
+}
+
+main() {
+ checkRangeError(TEST1, hasRangeError: false);
+ checkRangeError(TEST2('insert', 'null, null'), hasRangeError: true);
+ checkRangeError(TEST2('add', 'null'), hasRangeError: true);
+ checkRangeError(TEST2('clear', ''), hasRangeError: true);
+ checkRangeError(TEST2('toString', ''), hasRangeError: false);
+ checkRangeError(TEST3, hasRangeError: false);
+ checkRangeError(TEST4, hasRangeError: true);
+ checkRangeError(TEST5, hasRangeError: true);
+ checkRangeError(TEST6, hasRangeError: true);
+}
diff --git a/tests/compiler/dart2js/mock_compiler.dart b/tests/compiler/dart2js/mock_compiler.dart
index 3510801..cf84f928 100644
--- a/tests/compiler/dart2js/mock_compiler.dart
+++ b/tests/compiler/dart2js/mock_compiler.dart
@@ -177,6 +177,7 @@
class bool {}
class String implements Pattern {}
class Object {
+ Object();
operator ==(other) { return true; }
get hashCode => throw "Object.hashCode not implemented.";
String toString() { return null; }
diff --git a/tests/compiler/dart2js/resolver_test.dart b/tests/compiler/dart2js/resolver_test.dart
index 1902d65..c8fc25c 100644
--- a/tests/compiler/dart2js/resolver_test.dart
+++ b/tests/compiler/dart2js/resolver_test.dart
@@ -75,6 +75,43 @@
testIndexedOperator();
testIncrementsAndDecrements();
testOverrideHashCodeCheck();
+ testSupertypeOrder();
+}
+
+testSupertypeOrder() {
+ MockCompiler compiler = new MockCompiler();
+ compiler.parseScript("""
+class I1 {}
+class I2 {}
+class J1 extends K1 {}
+class J2 implements K2 {}
+class K1 {}
+class K2 {}
+class L1 {}
+class A implements I1, I2 {}
+class B extends A implements J1, J2 {}
+class C extends B implements L1 {}
+""");
+ compiler.resolveStatement("C c;");
+ ClassElement classA = compiler.mainApp.find(buildSourceString("A"));
+ ClassElement classB = compiler.mainApp.find(buildSourceString("B"));
+ ClassElement classC = compiler.mainApp.find(buildSourceString("C"));
+ Expect.equals('[ I2, I1, Object ]', classA.allSupertypes.toString());
+ Expect.equals('[ A, J2, J1, I2, I1, K2, K1, Object ]',
+ classB.allSupertypes.toString());
+ Expect.equals('[ B, L1, A, J2, J1, I2, I1, K2, K1, Object ]',
+ classC.allSupertypes.toString());
+
+ compiler = new MockCompiler();
+ compiler.parseScript("""
+class X<T> {}
+class Foo extends X<Foo> {}
+class Bar extends Foo implements X<Bar> {}
+""");
+ compiler.resolveStatement("Bar bar;");
+ ClassElement classBar = compiler.mainApp.find(buildSourceString("Bar"));
+ Expect.equals('[ Foo, X<Bar>, X<Foo>, Object ]',
+ classBar.allSupertypes.toString());
}
testTypeVariables() {
@@ -599,9 +636,11 @@
FunctionElement mainElement = compiler.mainApp.find(MAIN);
compiler.resolver.resolve(mainElement);
Expect.equals(0, compiler.warnings.length);
- Expect.equals(1, compiler.errors.length);
+ Expect.equals(2, compiler.errors.length);
Expect.equals(MessageKind.CYCLIC_CLASS_HIERARCHY,
compiler.errors[0].message.kind);
+ Expect.equals(MessageKind.CANNOT_FIND_CONSTRUCTOR,
+ compiler.errors[1].message.kind);
compiler = new MockCompiler();
compiler.parseScript("""abstract class A extends B {}
@@ -643,7 +682,7 @@
supertypes = aElement.allSupertypes;
// Object is once per inheritance path, that is from both A and I.
Expect.equals(<String>['A<int>', 'B<bool, String>', 'I<bool, List<String>>',
- 'Object', 'Object'].toString(),
+ 'Object'].toString(),
asSortedStrings(supertypes).toString());
compiler = new MockCompiler();
diff --git a/tests/compiler/dart2js/size_test.dart b/tests/compiler/dart2js/size_test.dart
index 3d6fd7b..446a6dc 100644
--- a/tests/compiler/dart2js/size_test.dart
+++ b/tests/compiler/dart2js/size_test.dart
@@ -8,7 +8,9 @@
const String TEST = "main() => [];";
const String DEFAULT_CORELIB_WITH_LIST = r'''
- class Object {}
+ class Object {
+ Object();
+ }
class bool {}
abstract class List {}
class num {}
diff --git a/tests/compiler/dart2js/type_representation_test.dart b/tests/compiler/dart2js/type_representation_test.dart
index 1c946ee..001a030 100644
--- a/tests/compiler/dart2js/type_representation_test.dart
+++ b/tests/compiler/dart2js/type_representation_test.dart
@@ -7,6 +7,7 @@
import 'package:expect/expect.dart';
import 'type_test_helper.dart';
import '../../../sdk/lib/_internal/compiler/implementation/dart_types.dart';
+import '../../../sdk/lib/_internal/compiler/implementation/js/js.dart';
import '../../../sdk/lib/_internal/compiler/implementation/elements/elements.dart'
show Element, ClassElement;
import '../../../sdk/lib/_internal/compiler/implementation/js_backend/js_backend.dart'
@@ -34,12 +35,24 @@
TypeRepresentationGenerator typeRepresentation =
new TypeRepresentationGenerator(env.compiler);
- String onVariable(TypeVariableType type) => type.name.slowToString();
+
+ Expression onVariable(TypeVariableType variable) {
+ return new VariableUse(variable.name.slowToString());
+ }
+
+ String stringify(Expression expression) {
+ return prettyPrint(expression, env.compiler).buffer.toString();
+ }
void expect(String expectedRepresentation, DartType type) {
- String foundRepresentation =
+ Expression expression =
typeRepresentation.getTypeRepresentation(type, onVariable);
- Expect.stringEquals(expectedRepresentation, foundRepresentation);
+ Expect.stringEquals(expectedRepresentation, stringify(expression));
+ }
+
+ String getJsName(ClassElement cls) {
+ Expression name = typeRepresentation.getJavaScriptClassName(cls);
+ return stringify(name);
}
JavaScriptBackend backend = env.compiler.backend;
@@ -62,15 +75,15 @@
DartType dynamic_ = env['dynamic'];
DartType Typedef_ = env['Typedef'];
- String List_rep = typeRepresentation.getJsName(List_);
- String List_E_rep = onVariable(List_E);
- String Map_rep = typeRepresentation.getJsName(Map_);
- String Map_K_rep = onVariable(Map_K);
- String Map_V_rep = onVariable(Map_V);
+ String List_rep = getJsName(List_);
+ String List_E_rep = stringify(onVariable(List_E));
+ String Map_rep = getJsName(Map_);
+ String Map_K_rep = stringify(onVariable(Map_K));
+ String Map_V_rep = stringify(onVariable(Map_V));
- String Object_rep = typeRepresentation.getJsName(Object_.element);
- String int_rep = typeRepresentation.getJsName(int_.element);
- String String_rep = typeRepresentation.getJsName(String_.element);
+ String Object_rep = getJsName(Object_.element);
+ String int_rep = getJsName(int_.element);
+ String String_rep = getJsName(String_.element);
expect('$int_rep', int_);
expect('$String_rep', String_);
diff --git a/tests/compiler/dart2js/value_range_test.dart b/tests/compiler/dart2js/value_range_test.dart
index 940b615..eff5ad8 100644
--- a/tests/compiler/dart2js/value_range_test.dart
+++ b/tests/compiler/dart2js/value_range_test.dart
@@ -209,7 +209,9 @@
abstract class double extends num { }
class bool {}
class String {}
- class Object {}
+ class Object {
+ Object();
+ }
class Type {}
class Function {}
class List {
diff --git a/tests/compiler/dart2js_extra/dart2js_extra.status b/tests/compiler/dart2js_extra/dart2js_extra.status
index dc665bb..2a81416 100644
--- a/tests/compiler/dart2js_extra/dart2js_extra.status
+++ b/tests/compiler/dart2js_extra/dart2js_extra.status
@@ -8,7 +8,6 @@
typed_locals_test: Fail
no_such_method_test: Fail # Wrong Invocation.memberName.
-deferred_semantics_test/none: Fail # TODO(ahe): Multitest cannot use import.
constant_javascript_semantics4_test: Fail, OK
[ $runtime == ff || $jscl ]
diff --git a/tests/html/html.status b/tests/html/html.status
index 5a76fb9..4852e32 100644
--- a/tests/html/html.status
+++ b/tests/html/html.status
@@ -50,6 +50,9 @@
touchevent_test/supported: Fail
+xhr_test: Pass, Fail # Issue 11884
+xhr_cross_origin_test: Pass, Fail # Issue 11884
+
[ $runtime == chrome || $runtime == chromeOnAndroid || $runtime == drt || $runtime == safari ]
audiocontext_test: Skip # Issue 9322
diff --git a/tests/isolate/isolate.status b/tests/isolate/isolate.status
index 3f441b4..ab28e12 100644
--- a/tests/isolate/isolate.status
+++ b/tests/isolate/isolate.status
@@ -127,7 +127,7 @@
isolate_stress_test: Pass, Timeout # http://dartbug.com/10697
[ $compiler == dart2js && ( $runtime == drt || $runtime == chrome ) ]
-isolate_stress_test: Pass, Timeout # issue 11648
+isolate_stress_test: Pass, Crash, Timeout # issue 11648
[ $arch == arm || $arch == simarm ]
*: Skip
diff --git a/tests/language/const_constructor_mixin_test.dart b/tests/language/const_constructor_mixin_test.dart
new file mode 100644
index 0000000..832be8c
--- /dev/null
+++ b/tests/language/const_constructor_mixin_test.dart
@@ -0,0 +1,18 @@
+// Copyright (c) 2013, 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.
+
+class Mixin {
+}
+
+class A {
+ const A(foo);
+}
+
+class B extends A with Mixin {
+ const B(foo) : super(foo);
+}
+
+main() {
+ var a = const B(42);
+}
diff --git a/tests/language/inference_mixin_field_test.dart b/tests/language/inference_mixin_field_test.dart
new file mode 100644
index 0000000..9669846
--- /dev/null
+++ b/tests/language/inference_mixin_field_test.dart
@@ -0,0 +1,28 @@
+// Copyright (c) 2013, 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:expect/expect.dart";
+
+class Mixin {
+ var field;
+ createIt() {
+ if (field == null) field = 42;
+ }
+}
+
+class A {
+ A(foo);
+}
+
+class B extends A with Mixin {
+ // Because [super] references a synthesized constructor, dart2js
+ // used to not see the null assignment to it.
+ B(foo) : super(foo);
+}
+
+main() {
+ var a = new B(42);
+ a.createIt();
+ Expect.equals(42, a.field);
+}
diff --git a/tests/language/language.status b/tests/language/language.status
index 0c2d5300..a04ad53 100644
--- a/tests/language/language.status
+++ b/tests/language/language.status
@@ -16,13 +16,11 @@
# 3) Update the language/src directory with the updated test.
[ $compiler == dart2dart ]
-mixin_type_parameters_simple_test: Fail, Crash # issue 11803
mixin_super_constructor_named_test: Fail
mixin_super_constructor_positionals_test: Fail
const_constructor_super_test/01: fail
[ $compiler == none ]
-mixin_type_parameters_simple_test: Fail, Crash # issue 11803
mixin_super_constructor_named_test: Fail
mixin_super_constructor_positionals_test: Fail
built_in_identifier_prefix_test: Fail # http://dartbug.com/6970
@@ -73,6 +71,8 @@
closures_initializer_test: Crash # issue 8847
closures_initializer2_test: Crash # issue 8847
+mixin_forwarding_constructor2_test: Fail # Issue 11888
+mixin_typedef_constructor_test: Fail # Issue 11888
[ $compiler == none && $unchecked ]
@@ -142,7 +142,10 @@
# Mixins fail on the VM.
mixin_mixin_test: Fail # VM issue
mixin_issue10216_2_test: Fail # VM issue
+mixin_forwarding_constructor2_test: Fail # Issue 11888
+mixin_typedef_constructor_test: Fail # Issue 11888
+mixin_with_two_implicit_constructors_test: Fail # Issue 11889
# Malformed types not handled as unresolved:
import_core_prefix_test: Fail
diff --git a/tests/language/language_analyzer.status b/tests/language/language_analyzer.status
index acbbb4c..8e01e1e 100644
--- a/tests/language/language_analyzer.status
+++ b/tests/language/language_analyzer.status
@@ -5,6 +5,8 @@
[ $compiler == dartanalyzer ]
#argument_definition_test/01: fail # issue 11565 (passing for the wrong reason)
+illegal_invocation_test/01: fail # Issue: 11892
+
# test issue 11581, it is not warning to call dynamic
call_through_getter_test: fail
@@ -170,9 +172,6 @@
block_scope_test: fail
lazy_static3_test: fail
-# test issue 10752, there are 'implicit' scopes for 'if', 'while' and 'do-while'
-implicit_scope_test: fail
-
# test issue 10889, "throw" requires expression, "rethrow" should be used instead
execute_finally10_test: fail
execute_finally11_test: fail
diff --git a/tests/language/mixin_forwarding_constructor1_test.dart b/tests/language/mixin_forwarding_constructor1_test.dart
new file mode 100644
index 0000000..b0e97ab
--- /dev/null
+++ b/tests/language/mixin_forwarding_constructor1_test.dart
@@ -0,0 +1,31 @@
+// Copyright (c) 2013, 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:expect/expect.dart";
+
+abstract class Mixin1 {
+ var mixin1Field = 1;
+}
+
+abstract class Mixin2 {
+ var mixin2Field = 2;
+}
+
+class A {
+ var superField;
+ A(foo) : superField = foo;
+}
+
+class B extends A with Mixin1, Mixin2 {
+ var field = 4;
+ B(unused) : super(3);
+}
+
+main() {
+ var b = new B(null);
+ Expect.equals(1, b.mixin1Field);
+ Expect.equals(2, b.mixin2Field);
+ Expect.equals(3, b.superField);
+ Expect.equals(4, b.field);
+}
diff --git a/tests/language/mixin_forwarding_constructor2_test.dart b/tests/language/mixin_forwarding_constructor2_test.dart
new file mode 100644
index 0000000..1178196
--- /dev/null
+++ b/tests/language/mixin_forwarding_constructor2_test.dart
@@ -0,0 +1,30 @@
+// Copyright (c) 2013, 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:expect/expect.dart";
+
+abstract class Mixin1 {
+ var mixin1Field = 1;
+}
+
+abstract class Mixin2 {
+ var mixin2Field = 2;
+}
+
+class A {
+ var superField;
+ A([this.superField = 3]);
+}
+
+class B extends A with Mixin1, Mixin2 {
+ var field = 4;
+}
+
+main() {
+ var b = new B();
+ Expect.equals(1, b.mixin1Field);
+ Expect.equals(2, b.mixin2Field);
+ Expect.equals(3, b.superField);
+ Expect.equals(4, b.field);
+}
diff --git a/tests/language/mixin_typedef_constructor_test.dart b/tests/language/mixin_typedef_constructor_test.dart
new file mode 100644
index 0000000..01735bd
--- /dev/null
+++ b/tests/language/mixin_typedef_constructor_test.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2013, 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:expect/expect.dart";
+
+class A {
+ var field;
+ A(this.field);
+}
+
+class Mixin {
+ var mixinField = 54;
+}
+
+typedef MyClass = A with Mixin;
+
+main() {
+ var a = new MyClass(42);
+ Expect.equals(42, a.field);
+ Expect.equals(54, a.mixinField);
+}
diff --git a/tests/language/mixin_with_two_implicit_constructors_test.dart b/tests/language/mixin_with_two_implicit_constructors_test.dart
new file mode 100644
index 0000000..16c3606
--- /dev/null
+++ b/tests/language/mixin_with_two_implicit_constructors_test.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2013, 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:expect/expect.dart";
+
+class A {
+ var field;
+ A.bar() : field = 1;
+ A() : field = 2;
+}
+
+class Mixin {
+}
+
+class B extends A with Mixin {
+}
+
+main() {
+ Expect.equals(2, new B().field);
+ Expect.throws(() => new B.bar(), (e) => e is NoSuchMethodError);
+}
diff --git a/tests/language/try_catch_optimized2_test.dart b/tests/language/try_catch_optimized2_test.dart
new file mode 100644
index 0000000..d383a7f
--- /dev/null
+++ b/tests/language/try_catch_optimized2_test.dart
@@ -0,0 +1,31 @@
+// Copyright (c) 2013, 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.
+// VMOptions=--optimization-counter-threshold=10 --no-use-osr
+
+import "package:expect/expect.dart";
+
+// Test allocation sinking with optimized try-catch.
+
+bar() { // Should not be inlined.
+ try {
+ } finally { }
+}
+
+foo(a) {
+ var r = 0;
+ for (var i in a) {
+ r += i;
+ }
+ try {
+ bar();
+ } finally {
+ }
+ return r;
+}
+
+main() {
+ var a = [1,2,3];
+ for (var i = 0; i < 20; i++) foo(a);
+ Expect.equals(6, foo(a));
+}
diff --git a/tests/lib/analyzer/analyze_library.status b/tests/lib/analyzer/analyze_library.status
index 227e5c6..20a7804 100644
--- a/tests/lib/analyzer/analyze_library.status
+++ b/tests/lib/analyzer/analyze_library.status
@@ -3,7 +3,6 @@
# BSD-style license that can be found in the LICENSE file.
[ $compiler == dart2analyzer ]
-lib/async/async: fail
lib/core/core: fail
lib/typed_data/typed_data: fail
lib/io/io: fail
diff --git a/tests/lib/analyzer/analyze_tests.status b/tests/lib/analyzer/analyze_tests.status
index 6348c8b..9b23190 100644
--- a/tests/lib/analyzer/analyze_tests.status
+++ b/tests/lib/analyzer/analyze_tests.status
@@ -30,6 +30,9 @@
# pkg issue https://code.google.com/p/dart/issues/detail?id=11856
standalone/io/secure_socket_renegotiate_test: fail
+# https://code.google.com/p/dart/issues/detail?id=11647
+standalone/package/package_isolate_test: fail
+
[ $compiler == dart2analyzer ]
53bit_overflow_literal_test/01: fail, ok
@@ -58,3 +61,6 @@
# pkg issue https://code.google.com/p/dart/issues/detail?id=11856
standalone/io/secure_socket_renegotiate_test: fail
+
+# https://code.google.com/p/dart/issues/detail?id=11647
+standalone/package/package_isolate_test: fail
diff --git a/tests/lib/lib.status b/tests/lib/lib.status
index b443409..0e75568 100644
--- a/tests/lib/lib.status
+++ b/tests/lib/lib.status
@@ -108,7 +108,6 @@
[ $arch == arm || $arch == simarm ]
typed_data/float32x4_unbox_regress_test: Crash # Unimplemented
-typed_data/float32x4_unbox_phi_test: Crash # Unimplemented
typed_data/float32x4_list_test: Crash # Unimplemented
typed_data/float32x4_test: Crash # Unimplemented
diff --git a/tests/lib/typed_data/float32x4_unbox_phi_test.dart b/tests/lib/typed_data/float32x4_unbox_phi_test.dart
index 008d9c9..34c85ef 100644
--- a/tests/lib/typed_data/float32x4_unbox_phi_test.dart
+++ b/tests/lib/typed_data/float32x4_unbox_phi_test.dart
@@ -1,7 +1,7 @@
// Copyright (c) 2013, 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.
-// VMOptions=--deoptimization_counter_threshold=1000
+// VMOptions=--deoptimization_counter_threshold=1000 --optimization-counter-threshold=10
// Library tag to be able to run in html test framework.
library float32x4_unbox_regress_test;
@@ -23,7 +23,7 @@
for (int i = 0; i < floatList.length; i++) {
floatList[i] = i.toDouble();
}
- for (int i = 0; i < 2000; i++) {
+ for (int i = 0; i < 20; i++) {
double r = testUnboxPhi(list);
Expect.equals(780.0, r);
}
diff --git a/tests/standalone/standalone.status b/tests/standalone/standalone.status
index cf1d4c3..c678bcd 100644
--- a/tests/standalone/standalone.status
+++ b/tests/standalone/standalone.status
@@ -73,8 +73,12 @@
# This is runtime test.
io/process_exit_negative_test: Skip
+# https://code.google.com/p/dart/issues/detail?id=11647
+package/package_isolate_test: fail
+
[ $compiler == dart2analyzer ]
53bit_overflow_literal_test/01: fail, ok
+package/package_isolate_test: fail # issue 11647
# test issue https://code.google.com/p/dart/issues/detail?id=11518
io/file_constructor_test: fail
@@ -91,6 +95,9 @@
# This is runtime test.
io/process_exit_negative_test: Skip
+# https://code.google.com/p/dart/issues/detail?id=11647
+package/package_isolate_test: fail
+
[ $compiler == dart2js ]
number_identity_test: Skip # Bigints and int/double diff. not supported.
typed_data_test: Skip # dart:typed_data support needed.
diff --git a/tests/utils/dummy_compiler_test.dart b/tests/utils/dummy_compiler_test.dart
index acc3501..f341977 100644
--- a/tests/utils/dummy_compiler_test.dart
+++ b/tests/utils/dummy_compiler_test.dart
@@ -20,6 +20,7 @@
source = """
library core;
class Object {
+ Object();
operator==(other) {}
get hashCode => throw 'Object.hashCode not implemented.';
}
diff --git a/tests/utils/recursive_import_test.dart b/tests/utils/recursive_import_test.dart
index fc7bd93..f827089 100644
--- a/tests/utils/recursive_import_test.dart
+++ b/tests/utils/recursive_import_test.dart
@@ -10,7 +10,8 @@
const CORE_LIB = """
library core;
-class Object{
+class Object {
+ Object();
operator==(other) {}
}
class bool {}
diff --git a/tools/VERSION b/tools/VERSION
index 9d22974..9a50ffe 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -1,4 +1,4 @@
MAJOR 0
MINOR 6
-BUILD 6
+BUILD 7
PATCH 0
diff --git a/tools/coverage.dart b/tools/coverage.dart
index cc12e94..3f51f00 100644
--- a/tools/coverage.dart
+++ b/tools/coverage.dart
@@ -24,6 +24,7 @@
// Whether or not to print the debugger wire messages on the console.
var verboseWire = false;
+var debugger = null;
class Program {
static int numBps = 0;
@@ -33,17 +34,19 @@
// Takes a JSON Debugger response and increments the count for
// the source position.
- static void recordBp(Debugger debugger, Map<String,dynamic> msg) {
+ static void recordBp(Map<String,dynamic> msg) {
// Progress indicator.
if (++numBps % 1000 == 0) print(numBps);
var location = msg["params"]["location"];
if (location == null) return;
String url = location["url"];
assert(url != null);
+ int libId = location["libraryId"];
+ assert(libId != null);
int tokenPos = location["tokenOffset"];;
Source s = sources[url];
if (s == null) {
- debugger.GetLineNumberTable(url);
+ debugger.getLineNumberTable(url, libId);
s = new Source(url);
sources[url] = s;
}
@@ -146,6 +149,47 @@
}
+class GetLibrariesCmd {
+ Map msg;
+ GetLibrariesCmd(int isolateId) {
+ msg = { "id": 0,
+ "command": "getLibraries",
+ "params": { "isolateId" : isolateId } };
+ }
+
+ void handleResponse(Map response) {
+ List libs = response["result"]["libraries"];
+ for (var lib in libs) {
+ String url = lib["url"];
+ int libraryId = lib["id"];
+ bool enable = !url.startsWith("dart:") && !url.startsWith("package:");
+ if (enable) {
+ print("Enable stepping for '$url'");
+ debugger.enableDebugging(libraryId, true);
+ }
+ }
+ }
+}
+
+
+class SetLibraryPropertiesCmd {
+ Map msg;
+ SetLibraryPropertiesCmd(int isolateId, int libraryId, bool enableDebugging) {
+ // Note that in the debugger protocol, boolean values true and false
+ // must be sent as string literals.
+ msg = { "id": 0,
+ "command": "setLibraryProperties",
+ "params": { "isolateId" : isolateId,
+ "libraryId": libraryId,
+ "debuggingEnabled": "$enableDebugging" } };
+ }
+
+ void handleResponse(Map response) {
+ // Nothing to do.
+ }
+}
+
+
class Debugger {
// Debug target process properties.
Process targetProcess;
@@ -157,7 +201,7 @@
// Data collected from debug target.
Map currentMessage = null; // Currently handled message sent by target.
var outstandingCommand = null;
- var queuedCommand = null;
+ var queuedCommands = new List();
String scriptUrl = null;
bool shutdownEventSeen = false;
int isolateId = 0;
@@ -221,9 +265,12 @@
if (libraryId == null) {
libraryId = msg["params"]["location"]["libraryId"];
assert(libraryId != null);
+ // This is the first paused event we got. Get all libraries from
+ // the debugger so we can turn on debugging events for them.
+ getLibraries();
}
if (msg["params"]["reason"] == "breakpoint") {
- Program.recordBp(this, msg);
+ Program.recordBp(msg);
}
} else {
error("Error: unknown debugger event received");
@@ -280,8 +327,7 @@
return;
}
if (isPaused && (outstandingCommand == null)) {
- var cmd = queuedCommand;
- queuedCommand = null;
+ var cmd = queuedCommands.length > 0 ? queuedCommands.removeAt(0) : null;
if (cmd == null) {
cmd = new StepCmd(isolateId);
isPaused = false;
@@ -302,11 +348,18 @@
socket.write(jsonMsg);
}
- void GetLineNumberTable(String url) {
- assert(queuedCommand == null);
- queuedCommand = new GetLineTableCmd(isolateId, libraryId, url);
+ void getLineNumberTable(String url, int libId) {
+ queuedCommands.add(new GetLineTableCmd(isolateId, libId, url));
+ }
+
+ void getLibraries() {
+ queuedCommands.add(new GetLibrariesCmd(isolateId));
}
+ void enableDebugging(libraryId, enable) {
+ queuedCommands.add(new SetLibraryPropertiesCmd(isolateId, libraryId, enable));
+ }
+
bool get errorsDetected => errors.length > 0;
// Record error message.
@@ -490,6 +543,6 @@
Process.start(options.executable, targetOpts).then((Process process) {
process.stdin.close();
- var debugger = new Debugger(process);
+ debugger = new Debugger(process);
});
}
diff --git a/tools/dom/templates/html/dart2js/html_dart2js.darttemplate b/tools/dom/templates/html/dart2js/html_dart2js.darttemplate
index a3c0333..4a94db8 100644
--- a/tools/dom/templates/html/dart2js/html_dart2js.darttemplate
+++ b/tools/dom/templates/html/dart2js/html_dart2js.darttemplate
@@ -88,6 +88,7 @@
// Workaround for tags like <cite> that lack their own Element subclass --
// Dart issue 1990.
class _HTMLElement extends Element native "HTMLElement" {
+ factory _HTMLElement() { throw new UnsupportedError("Not supported"); }
}
// Support for Send/ReceivePortSync.
diff --git a/tools/publish_all_pkgs.py b/tools/publish_all_pkgs.py
index 729d9a1..2e3d181 100644
--- a/tools/publish_all_pkgs.py
+++ b/tools/publish_all_pkgs.py
@@ -29,7 +29,7 @@
os.path.join('sdk', 'lib', '_internal', 'compiler'))
for pkg in pkgs_to_publish:
- print "Publishing " + pkg
+ print "\n\nPublishing [32m%s[0m:\n-------------------------------" % pkg
subprocess.call(['python', 'tools/publish_pkg.py', pkg])
if __name__ == '__main__':
diff --git a/tools/testing/dart/multitest.dart b/tools/testing/dart/multitest.dart
index 11e5ce1..1159a8a 100644
--- a/tools/testing/dart/multitest.dart
+++ b/tools/testing/dart/multitest.dart
@@ -150,14 +150,12 @@
// Find all relative imports and copy them into the dir that contains
// the generated tests.
-Set<Path> _findAllRelativeImports(Path topLibrary) {
+Set<String> _findAllRelativeImports(Path topLibrary) {
Set<Path> toSearch = new Set<Path>.from([topLibrary]);
- Set<Path> foundImports = new Set<Path>();
+ Set<String> foundImports = new Set<String>();
Path libraryDir = topLibrary.directoryPath;
- // Matches #import( or #source( followed by " or ' followed by anything
- // except dart:, dart-ext: or /, at the beginning of a line.
RegExp relativeImportRegExp = new RegExp(
- '^#(import|source)[(]["\'](?!(dart:|dart-ext:|/))([^"\']*)["\']');
+ '^(import|part)\\s+["\'](?!(dart:|dart-ext:|package:|/))([^"\']*)["\']');
while (!toSearch.isEmpty) {
var thisPass = toSearch;
toSearch = new Set<Path>();
@@ -167,7 +165,7 @@
Match match = relativeImportRegExp.firstMatch(line);
if (match != null) {
Path relativePath = new Path(match.group(3));
- if (foundImports.contains(relativePath)) {
+ if (foundImports.contains(relativePath.toString())) {
continue;
}
if (relativePath.toString().contains('..')) {
@@ -177,7 +175,7 @@
print("relative paths containing .. are not allowed.");
exit(1);
}
- foundImports.add(relativePath);
+ foundImports.add(relativePath.toString());
toSearch.add(libraryDir.join(relativePath));
}
}
@@ -198,9 +196,10 @@
assert(targetDir != null);
// Copy all the relative imports of the multitest.
- Set<Path> importsToCopy = _findAllRelativeImports(filePath);
+ Set<String> importsToCopy = _findAllRelativeImports(filePath);
List<Future> futureCopies = [];
- for (Path importPath in importsToCopy) {
+ for (String relativeImport in importsToCopy) {
+ Path importPath = new Path(relativeImport);
// Make sure the target directory exists.
Path importDir = importPath.directoryPath;
if (!importDir.isEmpty) {
diff --git a/utils/testrunner/standard_test_runner.dart b/utils/testrunner/standard_test_runner.dart
index dddc2fd..89fcc2f 100644
--- a/utils/testrunner/standard_test_runner.dart
+++ b/utils/testrunner/standard_test_runner.dart
@@ -199,7 +199,7 @@
List<TestCase> results, String uncaughtError) {
TestCase test = results[0];
parentPort.send([test.result, test.runningTime.inMilliseconds,
- test.message, test.stackTrace]);
+ test.message, test.stackTrace.toString()]);
}
}