Merge commit 'f56fea3e6389727df2cae5c6feebcdd49437b12a' into analyzer

This commit is contained in:
Paul Berry 2018-11-19 08:24:02 -08:00
commit 6d8e14c9db
32 changed files with 817 additions and 518 deletions

View file

@ -10,6 +10,22 @@
being reported.
## 2.2.0-dev.XX.0
(Add new changes here, and they will be copied to the change section for the
next dev version)
### Language
### Core library changes
### Dart VM
### Tool Changes
#### Pub
#### Other Tools
## 2.2.0-dev.0.0
### Dart for the Web
@ -19,7 +35,7 @@
for testing and it is no longer supported. `--categories=Server` continues to
work at this time but it is deprecated, please use `--server-mode` instead.
## 2.1.0 - 2018-10-31
## 2.1.0 - 2018-11-15
This is a minor version release. The team's focus was mostly on improving
performance and stability after the large changes in Dart 2.0.0. Notable

View file

@ -21,6 +21,7 @@ import shutil
import stat
import subprocess
import sys
from gn_helpers import ToGNString
@ -63,9 +64,14 @@ def SetEnvironmentAndGetRuntimeDllDirs():
win_sdk = toolchain_data['win8sdk']
wdk = toolchain_data['wdk']
# TODO(scottmg): The order unfortunately matters in these. They should be
# split into separate keys for x86 and x64. (See CopyDlls call below).
# split into separate keys for x64/x86/arm64. (See CopyDlls call below).
# http://crbug.com/345992
vs_runtime_dll_dirs = toolchain_data['runtime_dirs']
# The number of runtime_dirs in the toolchain_data was two (x64/x86) but
# changed to three (x64/x86/arm64) and this code needs to handle both
# possibilities, which can change independently from this code.
if len(vs_runtime_dll_dirs) == 2:
vs_runtime_dll_dirs.append('Arm64Unused')
os.environ['GYP_MSVS_OVERRIDE_PATH'] = toolchain
os.environ['GYP_MSVS_VERSION'] = version
@ -87,9 +93,12 @@ def SetEnvironmentAndGetRuntimeDllDirs():
# directory ensures that they are available when needed.
bitness = platform.architecture()[0]
# When running 64-bit python the x64 DLLs will be in System32
# ARM64 binaries will not be available in the system directories because we
# don't build on ARM64 machines.
x64_path = 'System32' if bitness == '64bit' else 'Sysnative'
x64_path = os.path.join(os.path.expandvars('%windir%'), x64_path)
vs_runtime_dll_dirs = [x64_path, os.path.expandvars('%windir%/SysWOW64')]
vs_runtime_dll_dirs = [x64_path, os.path.expandvars('%windir%/SysWOW64'),
'Arm64Unused']
return vs_runtime_dll_dirs
@ -141,7 +150,6 @@ def DetectVisualStudioPath():
raise Exception(('Visual Studio version %s (from GYP_MSVS_VERSION)'
' not supported. Supported versions are: %s') % (
version_as_year, ', '.join(year_to_version.keys())))
version = year_to_version[version_as_year]
if version_as_year == '2017':
# The VC++ 2017 install location needs to be located using COM instead of
# the registry. For details see:
@ -201,16 +209,21 @@ def _CopyUCRTRuntime(target_dir, source_dir, target_cpu, dll_pattern, suffix):
os.environ.get('WINDOWSSDKDIR',
os.path.expandvars('%ProgramFiles(x86)%'
'\\Windows Kits\\10')))
ucrt_dll_dirs = os.path.join(win_sdk_dir, 'Redist', 'ucrt', 'DLLs',
target_cpu)
ucrt_files = glob.glob(os.path.join(ucrt_dll_dirs, 'api-ms-win-*.dll'))
assert len(ucrt_files) > 0
for ucrt_src_file in ucrt_files:
file_part = os.path.basename(ucrt_src_file)
ucrt_dst_file = os.path.join(target_dir, file_part)
_CopyRuntimeImpl(ucrt_dst_file, ucrt_src_file, False)
_CopyRuntimeImpl(os.path.join(target_dir, 'ucrtbase' + suffix),
os.path.join(source_dir, 'ucrtbase' + suffix))
# ARM64 doesn't have a redist for the ucrt DLLs because they are always
# present in the OS.
if target_cpu != 'arm64':
ucrt_dll_dirs = os.path.join(win_sdk_dir, 'Redist', 'ucrt', 'DLLs',
target_cpu)
ucrt_files = glob.glob(os.path.join(ucrt_dll_dirs, 'api-ms-win-*.dll'))
assert len(ucrt_files) > 0
for ucrt_src_file in ucrt_files:
file_part = os.path.basename(ucrt_src_file)
ucrt_dst_file = os.path.join(target_dir, file_part)
_CopyRuntimeImpl(ucrt_dst_file, ucrt_src_file, False)
# We must copy ucrtbase.dll for x64/x86, and ucrtbased.dll for all CPU types.
if target_cpu != 'arm64' or not suffix.startswith('.'):
_CopyRuntimeImpl(os.path.join(target_dir, 'ucrtbase' + suffix),
os.path.join(source_dir, 'ucrtbase' + suffix))
def FindVCToolsRoot():
@ -249,6 +262,7 @@ def _CopyPGORuntime(target_dir, target_cpu):
# from HostX86/x86.
pgo_x86_runtime_dir = os.path.join(pgo_runtime_root, 'HostX86', 'x86')
pgo_x64_runtime_dir = os.path.join(pgo_runtime_root, 'HostX64', 'x64')
pgo_arm64_runtime_dir = os.path.join(pgo_runtime_root, 'arm64')
else:
raise Exception('Unexpected toolchain version: %s.' % env_version)
@ -261,8 +275,10 @@ def _CopyPGORuntime(target_dir, target_cpu):
source = os.path.join(pgo_x86_runtime_dir, runtime)
elif target_cpu == 'x64':
source = os.path.join(pgo_x64_runtime_dir, runtime)
elif target_cpu == 'arm64':
source = os.path.join(pgo_arm64_runtime_dir, runtime)
else:
raise NotImplementedError("Unexpected target_cpu value: " + target_cpu)
raise NotImplementedError('Unexpected target_cpu value: ' + target_cpu)
if not os.path.exists(source):
raise Exception('Unable to find %s.' % source)
_CopyRuntimeImpl(os.path.join(target_dir, runtime), source)
@ -271,7 +287,7 @@ def _CopyPGORuntime(target_dir, target_cpu):
def _CopyRuntime(target_dir, source_dir, target_cpu, debug):
"""Copy the VS runtime DLLs, only if the target doesn't exist, but the target
directory does exist. Handles VS 2015 and VS 2017."""
suffix = "d.dll" if debug else ".dll"
suffix = 'd.dll' if debug else '.dll'
# VS 2017 uses the same CRT DLLs as VS 2015.
_CopyUCRTRuntime(target_dir, source_dir, target_cpu, '%s140' + suffix,
suffix)
@ -290,8 +306,15 @@ def CopyDlls(target_dir, configuration, target_cpu):
if not vs_runtime_dll_dirs:
return
x64_runtime, x86_runtime = vs_runtime_dll_dirs
runtime_dir = x64_runtime if target_cpu == 'x64' else x86_runtime
x64_runtime, x86_runtime, arm64_runtime = vs_runtime_dll_dirs
if target_cpu == 'x64':
runtime_dir = x64_runtime
elif target_cpu == 'x86':
runtime_dir = x86_runtime
elif target_cpu == 'arm64':
runtime_dir = arm64_runtime
else:
raise Exception('Unknown target_cpu: ' + target_cpu)
_CopyRuntime(target_dir, runtime_dir, target_cpu, debug=False)
if configuration == 'Debug':
_CopyRuntime(target_dir, runtime_dir, target_cpu, debug=True)
@ -424,7 +447,7 @@ def Update(force=False):
def NormalizePath(path):
while path.endswith("\\"):
while path.endswith('\\'):
path = path[:-1]
return path
@ -476,4 +499,4 @@ def main():
if __name__ == '__main__':
sys.exit(main())
sys.exit(main())

View file

@ -948,6 +948,25 @@ class SimpleParserTest_Fasta extends FastaParserTestCase
@reflectiveTest
class StatementParserTest_Fasta extends FastaParserTestCase
with StatementParserTestMixin {
void test_35177() {
ExpressionStatement statement = parseStatement('(f)()<int>();');
FunctionExpressionInvocation funct1 = statement.expression;
NodeList<TypeAnnotation> typeArgs = funct1.typeArguments.arguments;
expect(typeArgs, hasLength(1));
TypeName typeName = typeArgs[0];
expect(typeName.name.name, 'int');
expect(funct1.argumentList.arguments, hasLength(0));
FunctionExpressionInvocation funct2 = funct1.function;
expect(funct2.typeArguments, isNull);
expect(funct2.argumentList.arguments, hasLength(0));
ParenthesizedExpression expression = funct2.function;
SimpleIdentifier identifier = expression.expression;
expect(identifier.name, 'f');
}
void test_invalid_typeArg_34850() {
var unit = parseCompilationUnit('foo Future<List<int>> bar() {}', errors: [
expectedError(ParserErrorCode.EXPECTED_TOKEN, 11, 4),

View file

@ -3941,6 +3941,7 @@ class Parser {
listener.handleNoTypeArguments(next);
}
token = parseArguments(token);
listener.handleSend(beginToken, token);
typeArg = computeMethodTypeArguments(token);
if (typeArg != noTypeParamOrArg) {
// For example a(b)<T>(c), where token is before '<'.
@ -3948,7 +3949,6 @@ class Parser {
assert(optional('(', token.next));
}
next = token.next;
listener.handleSend(beginToken, next);
} else {
break;
}

View file

@ -106,6 +106,7 @@ regress/issue_32972: RuntimeError
regress/issue_33452: RuntimeError # Test has an intentional error
regress/issue_34225: RuntimeError
regress/issue_34563: RuntimeError # Test execution after recovery
regress/issue_35177: RuntimeError
runtime_checks/implicit_downcast_constructor_initializer: RuntimeError # Test exercises strong mode semantics
runtime_checks/implicit_downcast_do: RuntimeError # Test exercises strong mode semantics
runtime_checks/implicit_downcast_for_condition: RuntimeError # Test exercises strong mode semantics

View file

@ -0,0 +1,8 @@
// Copyright (c) 2018, 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.
main() {
dynamic Function() f;
(f)()<int>();
}

View file

@ -0,0 +1,9 @@
library;
import self as self;
import "dart:core" as core;
static method main() → dynamic {
() → dynamic f;
f.call().call<core::int>();
}

View file

@ -0,0 +1,9 @@
library;
import self as self;
import "dart:core" as core;
static method main() → dynamic {
() → dynamic f;
f.call().call<core::int>();
}

View file

@ -0,0 +1,5 @@
library;
import self as self;
static method main() → dynamic
;

View file

@ -0,0 +1,8 @@
library;
import self as self;
import "dart:core" as core;
static method main() → dynamic {
() → dynamic f;
f.call().call<core::int>();
}

View file

@ -0,0 +1,8 @@
library;
import self as self;
import "dart:core" as core;
static method main() → dynamic {
() → dynamic f;
f.call().call<core::int>();
}

View file

@ -132,6 +132,7 @@ regress/issue_32972: TypeCheckError
regress/issue_33452: RuntimeError # Test has an intentional error
regress/issue_34225: RuntimeError
regress/issue_34563: RuntimeError # Test execution after recovery
regress/issue_35177: RuntimeError
runtime_checks_new/contravariant_generic_return_with_compound_assign_implicit_downcast: RuntimeError
runtime_checks_new/mixin_forwarding_stub_field: TypeCheckError
runtime_checks_new/mixin_forwarding_stub_getter: TypeCheckError

View file

@ -317,8 +317,8 @@ class BytecodeAssembler {
emitWord(_encode0(Opcode.kStoreContextParent));
}
void emitStoreContextVar(int rd) {
emitWord(_encodeD(Opcode.kStoreContextVar, rd));
void emitStoreContextVar(int ra, int rd) {
emitWord(_encodeAD(Opcode.kStoreContextVar, ra, rd));
}
void emitLoadFieldTOS(int rd) {
@ -333,8 +333,8 @@ class BytecodeAssembler {
emitWord(_encode0(Opcode.kLoadContextParent));
}
void emitLoadContextVar(int rd) {
emitWord(_encodeD(Opcode.kLoadContextVar, rd));
void emitLoadContextVar(int ra, int rd) {
emitWord(_encodeAD(Opcode.kLoadContextVar, ra, rd));
}
void emitBooleanNegateTOS() {
@ -359,12 +359,12 @@ class BytecodeAssembler {
emitWord(_encodeA(Opcode.kSetFrame, ra));
}
void emitAllocateContext(int rd) {
emitWord(_encodeD(Opcode.kAllocateContext, rd));
void emitAllocateContext(int ra, int rd) {
emitWord(_encodeAD(Opcode.kAllocateContext, ra, rd));
}
void emitCloneContext(int rd) {
emitWord(_encodeD(Opcode.kCloneContext, rd));
void emitCloneContext(int ra, int rd) {
emitWord(_encodeAD(Opcode.kCloneContext, ra, rd));
}
void emitMoveSpecial(SpecialIndex ra, int rx) {

View file

@ -173,17 +173,17 @@ const Map<Opcode, Format> BytecodeFormats = const {
Opcode.kCreateArrayTOS: const Format(
Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
Opcode.kAllocateContext: const Format(
Encoding.kD, const [Operand.imm, Operand.none, Operand.none]),
Encoding.kAD, const [Operand.imm, Operand.imm, Operand.none]),
Opcode.kCloneContext: const Format(
Encoding.kD, const [Operand.imm, Operand.none, Operand.none]),
Encoding.kAD, const [Operand.imm, Operand.imm, Operand.none]),
Opcode.kLoadContextParent: const Format(
Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
Opcode.kStoreContextParent: const Format(
Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
Opcode.kLoadContextVar: const Format(
Encoding.kD, const [Operand.imm, Operand.none, Operand.none]),
Encoding.kAD, const [Operand.imm, Operand.imm, Operand.none]),
Opcode.kStoreContextVar: const Format(
Encoding.kD, const [Operand.imm, Operand.none, Operand.none]),
Encoding.kAD, const [Operand.imm, Operand.imm, Operand.none]),
Opcode.kPushConstant: const Format(
Encoding.kD, const [Operand.lit, Operand.none, Operand.none]),
Opcode.kPushNull: const Format(
@ -347,6 +347,9 @@ const int localVariableIndexLimit = 1 << 15;
// Captured variables are referenced using 16-bit unsigned operands.
const int capturedVariableIndexLimit = 1 << 16;
// Context IDs are referenced using 8-bit unsigned operands.
const int contextIdLimit = 1 << 8;
// Base class for exceptions thrown when certain limit of bytecode
// format is exceeded.
abstract class BytecodeLimitExceededException {}

View file

@ -27,6 +27,7 @@ import 'constant_pool.dart';
import 'dbc.dart';
import 'exceptions.dart';
import 'local_vars.dart' show LocalVariables;
import 'nullability_detector.dart' show NullabilityDetector;
import 'recognized_methods.dart' show RecognizedMethods;
import '../constants_error_reporter.dart' show ForwardConstantEvaluationErrors;
import '../metadata/bytecode.dart';
@ -80,6 +81,7 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
final ErrorReporter errorReporter;
final BytecodeMetadataRepository metadata = new BytecodeMetadataRepository();
final RecognizedMethods recognizedMethods;
NullabilityDetector nullabilityDetector;
Class enclosingClass;
Member enclosingMember;
@ -119,6 +121,7 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
this.useFutureBytecodeFormat,
this.errorReporter)
: recognizedMethods = new RecognizedMethods(typeEnvironment) {
nullabilityDetector = new NullabilityDetector(recognizedMethods);
component.addMetadataRepository(metadata);
}
@ -631,7 +634,8 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
void _genLoadVar(VariableDeclaration v, {int currentContextLevel}) {
if (locals.isCaptured(v)) {
_genPushContextForVariable(v, currentContextLevel: currentContextLevel);
asm.emitLoadContextVar(locals.getVarIndexInContext(v));
asm.emitLoadContextVar(
locals.getVarContextId(v), locals.getVarIndexInContext(v));
} else {
asm.emitPush(locals.getVarIndexInFrame(v));
}
@ -647,7 +651,8 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
// If variable is captured, context should be pushed before value.
void _genStoreVar(VariableDeclaration variable) {
if (locals.isCaptured(variable)) {
asm.emitStoreContextVar(locals.getVarIndexInContext(variable));
asm.emitStoreContextVar(locals.getVarContextId(variable),
locals.getVarIndexInContext(variable));
} else {
asm.emitPopLocal(locals.getVarIndexInFrame(variable));
}
@ -661,7 +666,9 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
negated = true;
}
_generateNode(condition);
asm.emitAssertBoolean(0);
if (nullabilityDetector.isNullable(condition)) {
asm.emitAssertBoolean(0);
}
return negated;
}
@ -1421,7 +1428,7 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
void _allocateContextIfNeeded() {
final int contextSize = locals.currentContextSize;
if (contextSize > 0) {
asm.emitAllocateContext(contextSize);
asm.emitAllocateContext(locals.currentContextId, contextSize);
if (locals.currentContextLevel > 0) {
_genDupTOS(locals.scratchVarIndexInFrame);
@ -2461,7 +2468,8 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
if (locals.currentContextSize > 0) {
asm.emitPush(locals.contextVarIndexInFrame);
asm.emitCloneContext(locals.currentContextSize);
asm.emitCloneContext(
locals.currentContextId, locals.currentContextSize);
asm.emitPopLocal(locals.contextVarIndexInFrame);
}
@ -2844,11 +2852,7 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
} else {
asm.emitPushNull();
}
if (isCaptured) {
asm.emitStoreContextVar(locals.getVarIndexInContext(node));
} else {
asm.emitPopLocal(locals.getVarIndexInFrame(node));
}
_genStoreVar(node);
}
}

View file

@ -63,6 +63,7 @@ class LocalVariables {
int get currentContextSize => _currentScope.contextSize;
int get currentContextLevel => _currentScope.contextLevel;
int get currentContextId => _currentScope.contextId;
int get contextLevelAtEntry =>
_currentFrame.contextLevelAtEntry ??
@ -74,6 +75,12 @@ class LocalVariables {
return v.scope.contextLevel;
}
int getVarContextId(VariableDeclaration variable) {
final v = _getVarDesc(variable);
assert(v.isCaptured);
return v.scope.contextId;
}
int get closureVarIndexInFrame => getVarIndexInFrame(_currentFrame
.closureVar ??
(throw 'Closure variable is not declared in ${_currentFrame.function}'));
@ -257,6 +264,7 @@ class Scope {
int contextUsed = 0;
int contextSize = 0;
int contextLevel;
int contextId;
Scope(this.parent, this.frame, this.loopDepth);
@ -699,6 +707,7 @@ class _Allocator extends RecursiveVisitor<Null> {
Scope _currentScope;
Frame _currentFrame;
int _contextIdCounter = 0;
_Allocator(this.locals);
@ -738,6 +747,7 @@ class _Allocator extends RecursiveVisitor<Null> {
assert(_currentScope.contextOwner == null);
assert(_currentScope.contextLevel == null);
assert(_currentScope.contextId == null);
final int parentContextLevel =
_currentScope.parent != null ? _currentScope.parent.contextLevel : -1;
@ -763,8 +773,13 @@ class _Allocator extends RecursiveVisitor<Null> {
if (_currentScope.contextOwner == _currentScope) {
_currentScope.contextLevel = parentContextLevel + 1;
_currentScope.contextId = _contextIdCounter++;
if (_currentScope.contextId >= contextIdLimit) {
throw new ContextIdOverflowException();
}
} else {
_currentScope.contextLevel = _currentScope.contextOwner.contextLevel;
_currentScope.contextId = _currentScope.contextOwner.contextId;
}
} else {
_currentScope.contextLevel = parentContextLevel;
@ -1147,3 +1162,5 @@ class _Allocator extends RecursiveVisitor<Null> {
class LocalVariableIndexOverflowException
extends BytecodeLimitExceededException {}
class ContextIdOverflowException extends BytecodeLimitExceededException {}

View file

@ -0,0 +1,132 @@
// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
library vm.bytecode.nullability_detector;
import 'package:kernel/ast.dart';
import 'dbc.dart';
import 'recognized_methods.dart' show RecognizedMethods;
class NullabilityDetector {
final _IsNullableVisitor _isNullableVisitor;
NullabilityDetector(RecognizedMethods recognizedMethods)
: _isNullableVisitor = new _IsNullableVisitor(recognizedMethods);
bool isNullable(Expression expr) => expr.accept(_isNullableVisitor);
}
class _IsNullableVisitor extends ExpressionVisitor<bool> {
final RecognizedMethods recognizedMethods;
_IsNullableVisitor(this.recognizedMethods);
@override
bool defaultExpression(Expression node) => true;
@override
bool visitNullLiteral(NullLiteral node) => true;
// All basic literals except NullLiteral are non-nullable.
@override
bool defaultBasicLiteral(BasicLiteral node) => false;
@override
bool visitVariableGet(VariableGet node) {
final v = node.variable;
if ((v.isConst || v.isFinal) && v.initializer != null) {
return v.initializer.accept(this);
}
return true;
}
@override
bool visitVariableSet(VariableSet node) => node.value.accept(this);
@override
bool visitMethodInvocation(MethodInvocation node) {
final Opcode opcode = recognizedMethods.specializedBytecodeFor(node);
if (opcode != null) {
return !_nonNullableBytecodeInstructions.contains(opcode);
}
return true;
}
@override
bool visitConstructorInvocation(ConstructorInvocation node) => false;
@override
bool visitNot(Not node) => false;
@override
bool visitLogicalExpression(LogicalExpression node) => false;
@override
bool visitConditionalExpression(ConditionalExpression node) =>
node.then.accept(this) || node.otherwise.accept(this);
@override
bool visitStringConcatenation(StringConcatenation node) => false;
@override
bool visitIsExpression(IsExpression node) => false;
@override
bool visitAsExpression(AsExpression node) => node.operand.accept(this);
@override
bool visitSymbolLiteral(SymbolLiteral node) => false;
@override
bool visitTypeLiteral(TypeLiteral node) => false;
@override
bool visitThisExpression(ThisExpression node) => false;
@override
bool visitRethrow(Rethrow node) => false;
@override
bool visitThrow(Throw node) => false;
@override
bool visitListLiteral(ListLiteral node) => false;
@override
bool visitMapLiteral(MapLiteral node) => false;
@override
bool visitFunctionExpression(FunctionExpression node) => false;
@override
bool visitConstantExpression(ConstantExpression node) =>
node.constant is NullConstant;
@override
bool visitLet(Let node) => node.body.accept(this);
@override
bool visitInstantiation(Instantiation node) => false;
}
final _nonNullableBytecodeInstructions = new Set<Opcode>.from([
Opcode.kBooleanNegateTOS,
Opcode.kEqualsNull,
Opcode.kNegateInt,
Opcode.kAddInt,
Opcode.kSubInt,
Opcode.kMulInt,
Opcode.kTruncDivInt,
Opcode.kModInt,
Opcode.kBitAndInt,
Opcode.kBitOrInt,
Opcode.kBitXorInt,
Opcode.kShlInt,
Opcode.kShrInt,
Opcode.kCompareIntEq,
Opcode.kCompareIntGt,
Opcode.kCompareIntLt,
Opcode.kCompareIntGe,
Opcode.kCompareIntLe,
]);

File diff suppressed because it is too large Load diff

View file

@ -119,7 +119,6 @@ Bytecode (version: stable) {
PushConstant CP#0
PushStatic CP#0
EqualsNull
AssertBoolean 0
JumpIfFalse L1
Allocate CP#1
StoreLocal r1
@ -294,12 +293,10 @@ Bytecode (version: stable) {
PushConstant CP#0
PushStatic CP#0
EqualsNull
AssertBoolean 0
JumpIfFalse L1
PushConstant CP#1
PushStatic CP#1
EqualsNull
AssertBoolean 0
BooleanNegateTOS
PopLocal r0
Jump L2
@ -308,7 +305,6 @@ L1:
PopLocal r0
L2:
Push r0
AssertBoolean 0
JumpIfFalse L3
PushConstant CP#1
PushStatic CP#1
@ -493,7 +489,6 @@ L1:
PopLocal r1
L2:
Push r1
AssertBoolean 0
JumpIfTrue L3
PushConstant CP#0
PushStatic CP#0
@ -507,7 +502,6 @@ L3:
PopLocal r0
L4:
Push r0
AssertBoolean 0
JumpIfFalse L5
PushConstant CP#0
PushStatic CP#0
@ -575,7 +569,6 @@ Bytecode (version: stable) {
PushConstant CP#0
PushStatic CP#0
EqualsNull
AssertBoolean 0
JumpIfFalse L1
PushConstant CP#1
PushStatic CP#1

View file

@ -187,11 +187,11 @@ Bytecode (version: stable) {
Entry 5
CheckStack 0
CheckFunctionTypeArgs 2, r0
AllocateContext 1
AllocateContext 0, 1
PopLocal r1
Push r1
Push FP[-5]
StoreContextVar 0
StoreContextVar 0, 0
Allocate CP#31
StoreLocal r4
Push r4
@ -290,7 +290,7 @@ Closure CP#12 {
Push r3
PushInt 0
Push r1
LoadContextVar 0
LoadContextVar 0, 0
LoadTypeArgumentsField CP#15
PushNull
InstantiateType CP#14
@ -298,7 +298,7 @@ Closure CP#12 {
Push r3
PushInt 1
Push r1
LoadContextVar 0
LoadContextVar 0, 0
LoadTypeArgumentsField CP#15
PushNull
InstantiateType CP#16
@ -345,7 +345,7 @@ Closure CP#12 {
IndirectStaticCall 1, CP#25
Drop1
Push r1
LoadContextVar 0
LoadContextVar 0, 0
LoadTypeArgumentsField CP#15
Push r0
InstantiateTypeArgumentsTOS 0, CP#27
@ -385,7 +385,7 @@ L2:
StoreLocal r4
Push r4
Push r1
LoadContextVar 0
LoadContextVar 0, 0
LoadTypeArgumentsField CP#15
StoreFieldTOS CP#32
Push r4
@ -437,7 +437,7 @@ L2:
StoreLocal r4
Push r4
Push r1
LoadContextVar 0
LoadContextVar 0, 0
LoadTypeArgumentsField CP#15
StoreFieldTOS CP#32
Push r4
@ -506,19 +506,19 @@ ConstantPool {
Bytecode (version: stable) {
Entry 5
CheckStack 0
AllocateContext 4
AllocateContext 0, 4
PopLocal r0
Push r0
Push FP[-5]
StoreContextVar 0
StoreContextVar 0, 0
Push r0
PushInt 1
StoreContextVar 1
StoreContextVar 0, 1
PushInt 2
PopLocal r2
Push r0
PushInt 3
StoreContextVar 2
StoreContextVar 0, 2
Allocate CP#10
StoreLocal r4
Push r4
@ -550,18 +550,18 @@ Bytecode (version: stable) {
IndirectStaticCall 1, CP#7
Drop1
Push r0
LoadContextVar 2
LoadContextVar 0, 2
PushConstant CP#27
IndirectStaticCall 1, CP#7
Drop1
Push r0
LoadContextVar 1
LoadContextVar 0, 1
PushConstant CP#28
IndirectStaticCall 1, CP#7
Drop1
Push r0
PushInt 42
StoreContextVar 3
StoreContextVar 0, 3
Allocate CP#10
StoreLocal r3
Push r3
@ -631,19 +631,19 @@ Closure CP#6 {
LoadContextParent
Push r0
LoadContextParent
LoadContextVar 1
LoadContextVar 0, 1
PushInt 2
AddInt
StoreContextVar 2
StoreContextVar 0, 2
Push r0
Push r0
LoadContextParent
LoadContextVar 0
LoadContextVar 0, 0
InstanceCall 1, CP#8
Push r0
LoadContextVar 0
LoadContextVar 1, 0
AddInt
StoreContextVar 1
StoreContextVar 1, 1
PushNull
ReturnTOS
@ -655,7 +655,7 @@ Closure CP#0 {
Push FP[-6]
LoadFieldTOS CP#1
PopLocal r0
AllocateContext 2
AllocateContext 1, 2
StoreLocal r1
Push r1
Push r0
@ -663,7 +663,7 @@ Closure CP#0 {
PopLocal r0
Push r0
Push FP[-5]
StoreContextVar 0
StoreContextVar 1, 0
Push FP[-5]
PushConstant CP#3
PushNull
@ -674,20 +674,19 @@ Closure CP#0 {
Push r0
LoadContextParent
Push r0
LoadContextVar 0
LoadContextVar 1, 0
PushInt 1
AddInt
StoreContextVar 1
StoreContextVar 0, 1
Push r0
LoadContextParent
LoadContextVar 1
LoadContextVar 0, 1
PushInt 5
CompareIntGt
AssertBoolean 0
JumpIfFalse L1
Push r0
PushInt 4
StoreContextVar 1
StoreContextVar 1, 1
Allocate CP#10
StoreLocal r2
Push r2
@ -710,7 +709,7 @@ Closure CP#0 {
InstanceCall 1, CP#20
Drop1
Push r0
LoadContextVar 1
LoadContextVar 1, 1
PushConstant CP#21
IndirectStaticCall 1, CP#7
Drop1
@ -727,9 +726,9 @@ Closure CP#29 {
LoadFieldTOS CP#1
PopLocal r0
Push r0
LoadContextVar 0
LoadContextVar 0, 0
Push r0
LoadContextVar 3
LoadContextVar 0, 3
InstanceCall 2, CP#30
Drop1
PushNull
@ -793,11 +792,11 @@ ConstantPool {
Bytecode (version: stable) {
Entry 5
CheckStack 0
AllocateContext 1
AllocateContext 0, 1
PopLocal r0
Push r0
PushInt 0
StoreContextVar 0
StoreContextVar 0, 0
PushConstant CP#0
StoreLocal r3
Push r3
@ -816,7 +815,7 @@ Bytecode (version: stable) {
PushConstant CP#3
IndirectStaticCall 2, CP#1
PopLocal r4
AllocateContext 1
AllocateContext 1, 1
StoreLocal r1
Push r1
Push r0
@ -824,14 +823,13 @@ Bytecode (version: stable) {
PopLocal r0
Push r0
PushInt 0
StoreContextVar 0
StoreContextVar 1, 0
L2:
CheckStack 1
Push r0
LoadContextVar 0
LoadContextVar 1, 0
PushInt 10
CompareIntLt
AssertBoolean 0
JumpIfFalse L1
Push r2
Allocate CP#8
@ -874,15 +872,15 @@ L2:
InstanceCall 2, CP#24
Drop1
Push r0
CloneContext 1
CloneContext 1, 1
PopLocal r0
Push r0
Push r0
LoadContextVar 0
LoadContextVar 1, 0
PushInt 1
AddInt
StoreLocal r3
StoreContextVar 0
StoreContextVar 1, 0
Push r3
Drop1
Jump L2
@ -930,10 +928,10 @@ Closure CP#4 {
LoadFieldTOS CP#5
PopLocal r0
Push r0
LoadContextVar 0
LoadContextVar 1, 0
Push r0
LoadContextParent
LoadContextVar 0
LoadContextVar 0, 0
AddInt
ReturnTOS
@ -956,9 +954,9 @@ Closure CP#19 {
Push FP[-5]
Push r0
LoadContextParent
LoadContextVar 0
LoadContextVar 0, 0
AddInt
StoreContextVar 0
StoreContextVar 1, 0
PushNull
ReturnTOS
@ -986,12 +984,12 @@ L2:
Push r2
InstanceCall 1, CP#2
JumpIfFalse L1
AllocateContext 1
AllocateContext 0, 1
PopLocal r0
Push r0
Push r2
InstanceCall 1, CP#3
StoreContextVar 0
StoreContextVar 0, 0
Allocate CP#8
StoreLocal r4
Push r4
@ -1014,7 +1012,7 @@ L2:
InstanceCall 1, CP#18
Drop1
Push r0
LoadContextVar 0
LoadContextVar 0, 0
PushConstant CP#19
IndirectStaticCall 1, CP#0
Drop1
@ -1056,10 +1054,10 @@ Closure CP#4 {
PopLocal r0
Push r0
Push r0
LoadContextVar 0
LoadContextVar 0, 0
PushInt 1
AddInt
StoreContextVar 0
StoreContextVar 0, 0
PushNull
ReturnTOS
@ -1097,11 +1095,11 @@ ConstantPool {
Bytecode (version: stable) {
Entry 3
CheckStack 0
AllocateContext 1
AllocateContext 0, 1
PopLocal r0
Push r0
Push FP[-5]
StoreContextVar 0
StoreContextVar 0, 0
Push FP[-5]
PushConstant CP#0
Push FP[-6]
@ -1157,7 +1155,7 @@ Closure CP#4 {
LoadFieldTOS CP#5
PopLocal r0
Push r0
LoadContextVar 0
LoadContextVar 0, 0
ReturnTOS
}
@ -1169,11 +1167,11 @@ Closure CP#4 {
Bytecode (version: stable) {
Entry 4
CheckStack 0
AllocateContext 1
AllocateContext 0, 1
PopLocal r0
Push r0
PushInt 5
StoreContextVar 0
StoreContextVar 0, 0
Allocate CP#7
StoreLocal r3
Push r3
@ -1197,7 +1195,7 @@ Bytecode (version: stable) {
InstanceCall 2, CP#18
Drop1
Push r0
LoadContextVar 0
LoadContextVar 0, 0
ReturnTOS
}
ConstantPool {
@ -1236,10 +1234,10 @@ Closure CP#0 {
Drop1
Push r0
Push r0
LoadContextVar 0
LoadContextVar 0, 0
Push FP[-5]
AddInt
StoreContextVar 0
StoreContextVar 0, 0
PushNull
ReturnTOS

View file

@ -16,7 +16,6 @@ L2:
Push FP[-5]
InstanceCall 1, CP#1
CompareIntLt
AssertBoolean 0
JumpIfFalse L1
Push r0
Push FP[-5]
@ -60,13 +59,11 @@ L3:
Push r1
PushInt 0
CompareIntGe
AssertBoolean 0
JumpIfFalse L1
Push r1
Push FP[-5]
InstanceCall 1, CP#1
CompareIntGe
AssertBoolean 0
JumpIfFalse L2
Jump L1
L2:
@ -118,12 +115,10 @@ L4:
Push FP[-5]
InstanceCall 1, CP#1
CompareIntLt
AssertBoolean 0
JumpIfFalse L1
Push r1
PushInt 0
CompareIntLt
AssertBoolean 0
JumpIfFalse L2
Jump L3
L2:
@ -176,7 +171,6 @@ L2:
Push FP[-5]
InstanceCall 1, CP#1
CompareIntLt
AssertBoolean 0
JumpIfFalse L1
Push r0
Push FP[-5]
@ -234,7 +228,6 @@ L1:
Push FP[-5]
InstanceCall 1, CP#3
CompareIntLt
AssertBoolean 0
JumpIfTrue L1
Push r0
ReturnTOS

View file

@ -229,17 +229,17 @@ ConstantPool {
Bytecode (version: stable) {
Entry 7
CheckStack 0
AllocateContext 3
AllocateContext 0, 3
PopLocal r0
Push r0
PushInt 1
StoreContextVar 0
StoreContextVar 0, 0
Push r0
PopLocal r2
Try #0 start:
Push r0
PushInt 2
StoreContextVar 1
StoreContextVar 0, 1
Allocate CP#9
StoreLocal r5
Push r5
@ -262,7 +262,7 @@ Try #0 start:
InstanceCall 1, CP#19
Drop1
Push r0
LoadContextVar 1
LoadContextVar 0, 1
PushConstant CP#20
IndirectStaticCall 1, CP#4
Drop1
@ -278,7 +278,7 @@ Try #0 handler:
PopLocal r4
Push r0
Push r3
StoreContextVar 2
StoreContextVar 0, 2
PushNull
PushInt 4
CreateArrayTOS
@ -298,7 +298,7 @@ Try #0 handler:
Push r5
PushInt 3
Push r0
LoadContextVar 2
LoadContextVar 0, 2
StoreIndexedTOS
PushConstant CP#23
IndirectStaticCall 1, CP#4
@ -397,13 +397,13 @@ Try #0 handler:
Push r2
PopLocal r4
Push r0
LoadContextVar 0
LoadContextVar 0, 0
PushConstant CP#7
IndirectStaticCall 1, CP#4
Drop1
Push r0
PushInt 3
StoreContextVar 1
StoreContextVar 0, 1
Jump L1
L1:
PushNull
@ -457,7 +457,7 @@ Try #0 handler:
Push r5
PushInt 3
Push r0
LoadContextVar 2
LoadContextVar 0, 2
StoreIndexedTOS
PushConstant CP#33
IndirectStaticCall 1, CP#4
@ -623,13 +623,11 @@ L5:
Push r0
PushInt 10
CompareIntLt
AssertBoolean 0
JumpIfFalse L1
Try #0 start:
Push r0
PushInt 5
CompareIntGt
AssertBoolean 0
JumpIfFalse L2
Jump L3
L2:
@ -668,7 +666,7 @@ L1:
ReturnTOS
}
ExceptionsTable {
try-index 0, outer -1, start 10, end 17, handler 17, needs-stack-trace, types [CP#0]
try-index 0, outer -1, start 9, end 15, handler 15, needs-stack-trace, types [CP#0]
}
ConstantPool {
[0] = Type dynamic
@ -694,13 +692,13 @@ ConstantPool {
Bytecode (version: stable) {
Entry 9
CheckStack 0
AllocateContext 2
AllocateContext 0, 2
PopLocal r0
Push r0
Push FP[-5]
StoreContextVar 0
StoreContextVar 0, 0
Push r0
LoadContextVar 0
LoadContextVar 0, 0
PopLocal r2
Push r2
PushInt 1
@ -721,7 +719,7 @@ Try #0 start:
Drop1
Push r0
PushInt 3
StoreContextVar 1
StoreContextVar 0, 1
Push r0
PopLocal r5
Try #1 start:
@ -854,12 +852,12 @@ Closure CP#8 {
LoadFieldTOS CP#9
PopLocal r0
Push r0
LoadContextVar 0
LoadContextVar 0, 0
PushConstant CP#11
IndirectStaticCall 1, CP#4
Drop1
Push r0
LoadContextVar 1
LoadContextVar 0, 1
PushConstant CP#12
IndirectStaticCall 1, CP#4
Drop1
@ -907,11 +905,11 @@ Closure CP#8 {
Bytecode (version: stable) {
Entry 6
CheckStack 0
AllocateContext 1
AllocateContext 0, 1
PopLocal r0
Push r0
PushInt 11
StoreContextVar 0
StoreContextVar 0, 0
PushNull
PopLocal r2
Push r0
@ -944,7 +942,7 @@ Try #0 handler:
MoveSpecial exception, r3
MoveSpecial stackTrace, r4
Push r0
LoadContextVar 0
LoadContextVar 0, 0
PushConstant CP#26
IndirectStaticCall 1, CP#3
Drop1
@ -958,7 +956,7 @@ L1:
Push r3
PopLocal r0
Push r0
LoadContextVar 0
LoadContextVar 0, 0
PushConstant CP#28
IndirectStaticCall 1, CP#3
Drop1
@ -1013,7 +1011,7 @@ Closure CP#0 {
LoadFieldTOS CP#1
PopLocal r0
Push r0
LoadContextVar 0
LoadContextVar 0, 0
PushConstant CP#4
IndirectStaticCall 1, CP#3
Drop1
@ -1048,7 +1046,7 @@ Try #1 handler:
MoveSpecial exception, r4
MoveSpecial stackTrace, r5
Push r0
LoadContextVar 0
LoadContextVar 0, 0
PushConstant CP#10
IndirectStaticCall 1, CP#3
Drop1
@ -1059,7 +1057,7 @@ L2:
Push r4
PopLocal r0
Push r0
LoadContextVar 0
LoadContextVar 0, 0
PushConstant CP#11
IndirectStaticCall 1, CP#3
Drop1
@ -1084,7 +1082,7 @@ Try #2 handler:
MoveSpecial exception, r4
MoveSpecial stackTrace, r5
Push r0
LoadContextVar 0
LoadContextVar 0, 0
PushConstant CP#13
IndirectStaticCall 1, CP#3
Drop1
@ -1095,7 +1093,7 @@ L3:
Push r4
PopLocal r0
Push r0
LoadContextVar 0
LoadContextVar 0, 0
PushConstant CP#14
IndirectStaticCall 1, CP#3
Drop1

View file

@ -107,7 +107,6 @@ Bytecode (version: stable) {
PushNull
PushConstant CP#1
InstanceCall 4, CP#3
AssertBoolean 0
JumpIfFalse L1
PushConstant CP#4
PushConstant CP#6
@ -120,7 +119,6 @@ L1:
PushNull
PushConstant CP#7
InstanceCall 4, CP#8
AssertBoolean 0
JumpIfFalse L2
PushConstant CP#9
PushConstant CP#10
@ -177,7 +175,6 @@ Bytecode (version: stable) {
Push r0
PushConstant CP#0
InstanceCall 4, CP#2
AssertBoolean 0
JumpIfFalse L1
PushConstant CP#3
PushConstant CP#5
@ -190,7 +187,6 @@ L1:
Push r0
PushConstant CP#7
InstanceCall 4, CP#8
AssertBoolean 0
JumpIfFalse L2
PushConstant CP#9
PushConstant CP#10
@ -334,7 +330,6 @@ Bytecode (version: stable) {
Push FP[-5]
PushConstant CP#0
InstanceCall 2, CP#2
AssertBoolean 0
JumpIfFalse L1
PushConstant CP#3
PushConstant CP#5
@ -346,7 +341,6 @@ L1:
PushNull
PushConstant CP#6
InstanceCall 4, CP#8
AssertBoolean 0
JumpIfFalse L2
PushConstant CP#9
PushConstant CP#10

View file

@ -50,18 +50,18 @@ where
--dart-top : sets DART_TOP explicitly through command line
--mode1 : m1
--mode2 : m2, and values one of
jit-[debug-]ia32 = Dart JIT (ia32)
jit-[debug-]x64 = Dart JIT (x64)
jit-[debug-]arm32 = Dart JIT (simarm)
jit-[debug-]arm64 = Dart JIT (simarm64)
jit-[debug-]dbc = Dart JIT (simdbc)
jit-[debug-]dbc64 = Dart JIT (simdbc64)
aot-[debug-]x64 = Dart AOT (x64)
aot-[debug-]arm64 = Dart AOT (simarm64)
kbc-int-[debug-]x64 = Dart KBC (interpreted bytecode)
kbc-mix-[debug-]x64 = Dart KBC (mixed-mode bytecode)
kbc-cmp-[debug-]x64 = Dart KBC (compiled bytecode)
js = dart2js + JS
jit-[opt-][debug-]ia32 = Dart JIT (ia32)
jit-[opt-][debug-]x64 = Dart JIT (x64)
jit-[opt-][debug-]arm32 = Dart JIT (simarm)
jit-[opt-][debug-]arm64 = Dart JIT (simarm64)
jit-[opt-][debug-]dbc = Dart JIT (simdbc)
jit-[opt-][debug-]dbc64 = Dart JIT (simdbc64)
aot-[debug-]x64 = Dart AOT (x64)
aot-[debug-]arm64 = Dart AOT (simarm64)
kbc-int-[debug-]x64 = Dart KBC (interpreted bytecode)
kbc-mix-[debug-]x64 = Dart KBC (mixed-mode bytecode)
kbc-cmp-[debug-]x64 = Dart KBC (compiled bytecode)
js = dart2js + JS
If no modes are given, a random JIT and/or AOT combination is used.

View file

@ -51,8 +51,11 @@ abstract class TestRunner {
// Factory.
static TestRunner getTestRunner(
String mode, String top, String tmp, Map<String, String> env) {
if (mode.startsWith('jit-opt'))
return new TestRunnerJIT(
getTag(mode), top, tmp, env, ['--optimization_counter_threshold=1']);
if (mode.startsWith('jit'))
return new TestRunnerJIT(getTag(mode), top, tmp, env);
return new TestRunnerJIT(getTag(mode), top, tmp, env, []);
if (mode.startsWith('aot'))
return new TestRunnerAOT(getTag(mode), top, tmp, env);
if (mode.startsWith('kbc'))
@ -81,21 +84,24 @@ abstract class TestRunner {
/// Concrete test runner of Dart JIT.
class TestRunnerJIT implements TestRunner {
TestRunnerJIT(String tag, String top, String tmp, Map<String, String> e) {
description = 'JIT-${tag}';
TestRunnerJIT(String tag, String top, String tmp, Map<String, String> e,
List<String> extra_flags) {
description = extra_flags.length == 0 ? 'JIT-${tag}' : 'JIT-OPT-${tag}';
dart = '$top/out/$tag/dart';
fileName = '$tmp/fuzz.dart';
env = e;
cmd = [dart] + extra_flags + [fileName];
}
TestResult run() {
return runCommand([dart, fileName], env);
return runCommand(cmd, env);
}
String description;
String dart;
String fileName;
Map<String, String> env;
List<String> cmd;
}
/// Concrete test runner of Dart AOT.
@ -167,8 +173,8 @@ class TestRunnerKBC implements TestRunner {
String dill;
String dart;
String fileName;
List<String> cmd;
Map<String, String> env;
List<String> cmd;
}
/// Concrete test runner of Dart2JS.
@ -446,7 +452,7 @@ class DartFuzzTestSession {
// Random when not set.
if (mode == null || mode == '') {
// Pick a mode at random (cluster), different from other.
const cluster_modes = 20;
int cluster_modes = modes.length - 3;
Random rand = new Random();
do {
mode = modes[rand.nextInt(cluster_modes)];
@ -475,6 +481,18 @@ class DartFuzzTestSession {
// Supported modes.
static const List<String> modes = [
// Cluster options:
'jit-opt-debug-ia32',
'jit-opt-debug-x64',
'jit-opt-debug-arm32',
'jit-opt-debug-arm64',
'jit-opt-debug-dbc',
'jit-opt-debug-dbc64',
'jit-opt-ia32',
'jit-opt-x64',
'jit-opt-arm32',
'jit-opt-arm64',
'jit-opt-dbc',
'jit-opt-dbc64',
'jit-debug-ia32',
'jit-debug-x64',
'jit-debug-arm32',
@ -496,8 +514,8 @@ class DartFuzzTestSession {
'kbc-cmp-x64',
'kbc-mix-x64',
// Times out often:
'aot-arm64',
'aot-debug-arm64',
'aot-arm64',
// Too many divergences (due to arithmetic):
'js'
];

View file

@ -34,7 +34,8 @@ T* PutIfAbsent(Thread* thread,
return array->At(index);
}
LocalVariable* CompilerState::GetDummyCapturedVariable(intptr_t index) {
LocalVariable* CompilerState::GetDummyCapturedVariable(intptr_t context_id,
intptr_t index) {
return PutIfAbsent<LocalVariable>(
thread(), &dummy_captured_vars_, index, [&]() {
Zone* const Z = thread()->zone();
@ -52,6 +53,7 @@ LocalVariable* CompilerState::GetDummyCapturedVariable(intptr_t index) {
}
const GrowableArray<LocalVariable*>& CompilerState::GetDummyContextVariables(
intptr_t context_id,
intptr_t num_context_variables) {
return PutIfAbsent<LocalScope>(
thread(), &dummy_scopes_, num_context_variables,
@ -63,7 +65,7 @@ const GrowableArray<LocalVariable*>& CompilerState::GetDummyContextVariables(
scope->set_context_level(0);
for (intptr_t i = 0; i < num_context_variables; i++) {
LocalVariable* var = GetDummyCapturedVariable(i);
LocalVariable* var = GetDummyCapturedVariable(context_id, i);
scope->AddVariable(var);
scope->AddContextVariable(var);
}

View file

@ -87,16 +87,20 @@ class CompilerState : public StackResource {
void set_slot_cache(SlotCache* cache) { slot_cache_ = cache; }
// Create a dummy list of local variables representing a context object
// with the given number of captured variables.
// with the given number of captured variables and given ID.
//
// Used during bytecode to IL translation because AllocateContext and
// CloneContext IL instructions need a list of local varaibles and bytecode
// does not record this information.
//
// TODO(vegorov): create context classes for distinct context IDs and
// populate them with slots without creating variables.
const GrowableArray<LocalVariable*>& GetDummyContextVariables(
intptr_t context_id,
intptr_t num_context_variables);
// Create a dummy LocalVariable that represents a captured local variable
// at the given index.
// at the given index in the context with given ID.
//
// Used during bytecode to IL translation because StoreInstanceField and
// LoadField IL instructions need Slot, which can only be created from a
@ -104,7 +108,9 @@ class CompilerState : public StackResource {
//
// This function returns the same variable when it is called with the
// same index.
LocalVariable* GetDummyCapturedVariable(intptr_t index);
//
// TODO(vegorov): disambiguate slots for different context IDs.
LocalVariable* GetDummyCapturedVariable(intptr_t context_id, intptr_t index);
private:
CHA cha_;

View file

@ -781,8 +781,11 @@ void BytecodeFlowGraphBuilder::BuildAllocateContext() {
UNIMPLEMENTED(); // TODO(alexmarkov): interpreter
}
const intptr_t context_id = DecodeOperandA().value();
const intptr_t num_context_vars = DecodeOperandD().value();
auto& context_variables = CompilerState::Current().GetDummyContextVariables(
DecodeOperandD().value());
context_id, num_context_vars);
code_ += B->AllocateContext(context_variables);
}
@ -792,8 +795,11 @@ void BytecodeFlowGraphBuilder::BuildCloneContext() {
}
LoadStackSlots(1);
const intptr_t context_id = DecodeOperandA().value();
const intptr_t num_context_vars = DecodeOperandD().value();
auto& context_variables = CompilerState::Current().GetDummyContextVariables(
DecodeOperandD().value());
context_id, num_context_vars);
CloneContextInstr* clone_instruction = new (Z) CloneContextInstr(
TokenPosition::kNoSource, Pop(), context_variables, B->GetNextDeoptId());
code_ <<= clone_instruction;
@ -885,12 +891,11 @@ void BytecodeFlowGraphBuilder::BuildStoreContextVar() {
}
LoadStackSlots(2);
Operand var_index = DecodeOperandD();
const intptr_t context_id = DecodeOperandA().value();
const intptr_t var_index = DecodeOperandD().value();
// TODO(alexmarkov) provide context_id in bytecode to disambiguate variables
// in different contexts
auto var =
CompilerState::Current().GetDummyCapturedVariable(var_index.value());
CompilerState::Current().GetDummyCapturedVariable(context_id, var_index);
code_ += B->StoreInstanceField(
position_, Slot::GetContextVariableSlotFor(thread(), *var));
}
@ -901,12 +906,11 @@ void BytecodeFlowGraphBuilder::BuildLoadContextVar() {
}
LoadStackSlots(1);
Operand var_index = DecodeOperandD();
const intptr_t context_id = DecodeOperandA().value();
const intptr_t var_index = DecodeOperandD().value();
// TODO(alexmarkov) provide context_id in bytecode to disambiguate variables
// in different contexts
auto var =
CompilerState::Current().GetDummyCapturedVariable(var_index.value());
CompilerState::Current().GetDummyCapturedVariable(context_id, var_index);
code_ += B->LoadNativeField(Slot::GetContextVariableSlotFor(thread(), *var));
}

View file

@ -155,13 +155,18 @@ namespace dart {
//
// Allocate array of length SP[0] with type arguments SP[-1].
//
// - AllocateContext D
// - AllocateContext A, D
//
// Allocate Context object assuming for D context variables.
// Allocate Context object holding D context variables.
// A is a static ID of the context. Static ID of a context may be used to
// disambiguate accesses to different context objects.
// Context objects with the same ID should have the same number of
// context variables.
//
// - CloneContext D
// - CloneContext A, D
//
// Clone Context object stored in TOS assuming it has D context variables.
// Clone Context object SP[0] holding D context variables.
// A is a static ID of the context. Cloned context has the same ID.
//
// - LoadContextParent
//
@ -171,13 +176,15 @@ namespace dart {
//
// Store context SP[0] into `parent` field of context SP[-1].
//
// - LoadContextVar D
// - LoadContextVar A, D
//
// Load value from context SP[0] at index D.
// A is a static ID of the context.
//
// - StoreContextVar D
// - StoreContextVar A, D
//
// Store value SP[0] into context SP[-1] at index D.
// A is a static ID of the context.
//
// - PushConstant D
//

View file

@ -8,8 +8,10 @@ import "dart:collection" show LinkedHashSet;
import "package:expect/expect.dart";
const Object d = 3.5;
void main() {
var o //
var o //
= <int>{1: 1} //# 01: compile-time error
= <int, int, int>{} //# 02: compile-time error
= <int, int, int>{1} //# 03: compile-time error
@ -18,38 +20,52 @@ void main() {
= const <int, int, int>{1} //# 06: compile-time error
= const <int, int>{1} //# 07: compile-time error
= const {Duration(seconds: 0)} // Overrides ==. //# 08: compile-time error
= {4.2} // Overrides ==. //# 09: compile-time error
= {d} // Overrides ==. //# 10: compile-time error
= {,} //# 11: compile-time error
= {1,,} //# 12: compile-time error
= {1,,1} //# 13: compile-time error
;
Expect.isNull(o); // Should be unreachable with a value.
Set<int> s //
= {"not int"} //# 09: compile-time error
= {4.2} //# 10: compile-time error
= {1: 1} //# 11: compile-time error
= {{}} //# 12: compile-time error
= <Object>{} // Exact type. //# 13: compile-time error
= {"not int"} //# 14: compile-time error
= {4.2} //# 15: compile-time error
= {1: 1} //# 16: compile-time error
= {{}} //# 17: compile-time error
= <Object>{} // Exact type. //# 18: compile-time error
;
Expect.isNull(s);
Set<Set<Object>> ss //
= {{1: 1}} //# 14: compile-time error
= {<int, int>{}} //# 15: compile-time error
= {<int>{1: 1}} //# 16: compile-time error
= const {ss} //# 17: compile-time error
= {{1: 1}} //# 19: compile-time error
= {<int, int>{}} //# 20: compile-time error
= {<int>{1: 1}} //# 21: compile-time error
= const {ss} //# 22: compile-time error
;
Expect.isNull(ss);
HashSet<int> hs //
= {} // Exact type is LinkedHashSet //# 18: compile-time error
= {} // Exact type is LinkedHashSet //# 23: compile-time error
;
Expect.isNull(hs);
LinkedHashSet<int> lhs //
= const {} // exact type is Set //# 19: compile-time error
= const {} // exact type is Set //# 24: compile-time error
;
Expect.isNull(lhs);
LinkedHashSet<LinkedHashSet<int>> lhs2 //
= {const {}} // exact type LHS<Set>. // 20: compile-time error
= {const {}} // exact type LHS<Set>. //# 25: compile-time error
;
Expect.isNull(lhs2);
<T>(x) {
// Type constants are allowed, type variables are not.
var o //
= const {T} //# 26: compile-time error
= const {x} //# 27: compile-time error
;
Expect.isNull(o);
}<int>(42);
}

View file

@ -115,6 +115,16 @@ void test<S extends Set<num>, I extends Iterable<num>>() {
set = {{1}, {}}; // Set<Object>
Expect.type<Set<Object>>(x);
Expect.notType<Set<Set<Object>>>(x);
// Trailing comma.
Iterable<Object> i;
i = {1,};
Expect.type<Set<Object>>(i);
Expect.equals(1, i.length);
o = {1, 2, 3,};
Expect.type<Set<int>>(o);
Expect.equals(3, o.length);
}
class Equality {

View file

@ -25,7 +25,7 @@
#
CHANNEL be
MAJOR 2
MINOR 1
MINOR 2
PATCH 0
PRERELEASE 0
PRERELEASE_PATCH 0