mirror of
https://github.com/dart-lang/sdk
synced 2024-10-04 16:44:59 +00:00
Merge commit 'f56fea3e6389727df2cae5c6feebcdd49437b12a' into analyzer
This commit is contained in:
commit
6d8e14c9db
18
CHANGELOG.md
18
CHANGELOG.md
|
@ -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
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
8
pkg/front_end/testcases/regress/issue_35177.dart
Normal file
8
pkg/front_end/testcases/regress/issue_35177.dart
Normal 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>();
|
||||
}
|
|
@ -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>();
|
||||
}
|
||||
|
|
@ -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>();
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
library;
|
||||
import self as self;
|
||||
|
||||
static method main() → dynamic
|
||||
;
|
|
@ -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>();
|
||||
}
|
|
@ -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>();
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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 {}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 {}
|
||||
|
|
132
pkg/vm/lib/bytecode/nullability_detector.dart
Normal file
132
pkg/vm/lib/bytecode/nullability_detector.dart
Normal 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
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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'
|
||||
];
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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_;
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
//
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
#
|
||||
CHANNEL be
|
||||
MAJOR 2
|
||||
MINOR 1
|
||||
MINOR 2
|
||||
PATCH 0
|
||||
PRERELEASE 0
|
||||
PRERELEASE_PATCH 0
|
||||
|
|
Loading…
Reference in a new issue