Version 2.19.0-61.0.dev
Merge commit 'a6f56aec88ddbfec4589997cc03a85b924b5f8e2' into 'dev'
diff --git a/build/find_depot_tools.py b/build/find_depot_tools.py
new file mode 100644
index 0000000..903fc25
--- /dev/null
+++ b/build/find_depot_tools.py
@@ -0,0 +1,81 @@
+#!/usr/bin/env python3
+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# For Dart/Flutter developers:
+# This file is copied from Chromium:
+# https://cs.chromium.org/chromium/src/build/find_depot_tools.py
+# When updating replace reference to python on the first line with python3.
+#
+"""Small utility function to find depot_tools and add it to the python path.
+
+Will throw an ImportError exception if depot_tools can't be found since it
+imports breakpad.
+
+This can also be used as a standalone script to print out the depot_tools
+directory location.
+"""
+
+from __future__ import print_function
+
+import os
+import sys
+
+
+# Path to //src
+SRC = os.path.abspath(os.path.join(os.path.dirname(__file__), os.pardir))
+
+
+def IsRealDepotTools(path):
+ expanded_path = os.path.expanduser(path)
+ return os.path.isfile(os.path.join(expanded_path, 'gclient.py'))
+
+
+def add_depot_tools_to_path():
+ """Search for depot_tools and add it to sys.path."""
+ # First, check if we have a DEPS'd in "depot_tools".
+ deps_depot_tools = os.path.join(SRC, 'third_party', 'depot_tools')
+ if IsRealDepotTools(deps_depot_tools):
+ # Put the pinned version at the start of the sys.path, in case there
+ # are other non-pinned versions already on the sys.path.
+ sys.path.insert(0, deps_depot_tools)
+ return deps_depot_tools
+
+ # Then look if depot_tools is already in PYTHONPATH.
+ for i in sys.path:
+ if i.rstrip(os.sep).endswith('depot_tools') and IsRealDepotTools(i):
+ return i
+ # Then look if depot_tools is in PATH, common case.
+ for i in os.environ['PATH'].split(os.pathsep):
+ if IsRealDepotTools(i):
+ sys.path.append(i.rstrip(os.sep))
+ return i
+ # Rare case, it's not even in PATH, look upward up to root.
+ root_dir = os.path.dirname(os.path.abspath(__file__))
+ previous_dir = os.path.abspath(__file__)
+ while root_dir and root_dir != previous_dir:
+ i = os.path.join(root_dir, 'depot_tools')
+ if IsRealDepotTools(i):
+ sys.path.append(i)
+ return i
+ previous_dir = root_dir
+ root_dir = os.path.dirname(root_dir)
+ print('Failed to find depot_tools', file=sys.stderr)
+ return None
+
+DEPOT_TOOLS_PATH = add_depot_tools_to_path()
+
+# pylint: disable=W0611
+import breakpad
+
+
+def main():
+ if DEPOT_TOOLS_PATH is None:
+ return 1
+ print(DEPOT_TOOLS_PATH)
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/build/toolchain/win/BUILD.gn b/build/toolchain/win/BUILD.gn
index d70d49e..bc54953 100644
--- a/build/toolchain/win/BUILD.gn
+++ b/build/toolchain/win/BUILD.gn
@@ -146,9 +146,10 @@
}
tool("solink") {
- dllname = "{{root_out_dir}}/{{target_output_name}}{{output_extension}}" # e.g. foo.dll
- libname =
- "{{root_out_dir}}/{{target_output_name}}{{output_extension}}.lib" # e.g. foo.dll.lib
+ dllname = "{{root_out_dir}}/{{target_output_name}}{{output_extension}}" # e.g.
+ # foo.dll
+ libname = "{{root_out_dir}}/{{target_output_name}}{{output_extension}}.lib" # e.g.
+ # foo.dll.lib
rspfile = "${dllname}.rsp"
link_command = "$python_path $tool_wrapper_path link-wrapper $env False link.exe /nologo /IMPLIB:$libname /DLL /OUT:$dllname /PDB:${dllname}.pdb @$rspfile"
@@ -175,7 +176,9 @@
}
tool("solink_module") {
- dllname = "{{output_dir}}/{{target_output_name}}{{output_extension}}" # e.g. foo.dll
+ dllname =
+ "{{output_dir}}/{{target_output_name}}{{output_extension}}" # e.g.
+ # foo.dll
pdbname = "${dllname}.pdb"
rspfile = "${dllname}.rsp"
@@ -230,8 +233,7 @@
}
tool("copy") {
- command =
- "$python_path $tool_wrapper_path recursive-mirror {{source}} {{output}}"
+ command = "$python_path $tool_wrapper_path recursive-mirror {{source}} {{output}}"
description = "COPY {{source}} {{output}}"
}
}
@@ -246,7 +248,9 @@
visual_studio_path,
windows_sdk_path,
visual_studio_runtime_dirs,
+ "win",
toolchain_arch,
+ "environment." + toolchain_arch,
],
"scope")
diff --git a/build/toolchain/win/setup_toolchain.py b/build/toolchain/win/setup_toolchain.py
index 10b878a..e680ba0 100644
--- a/build/toolchain/win/setup_toolchain.py
+++ b/build/toolchain/win/setup_toolchain.py
@@ -10,63 +10,183 @@
# win tool. The script assumes that the root build directory is the current dir
# and the files will be written to the current directory.
+from __future__ import print_function
+
import errno
+import json
import os
import re
import subprocess
import sys
+sys.path.append(os.path.join(os.path.dirname(__file__), os.pardir, os.pardir))
+import gn_helpers
+
+SCRIPT_DIR = os.path.dirname(__file__)
def _ExtractImportantEnvironment(output_of_set):
"""Extracts environment variables required for the toolchain to run from
a textual dump output by the cmd.exe 'set' command."""
envvars_to_save = (
+ 'cipd_cache_dir', # needed by vpython
+ 'homedrive', # needed by vpython
+ 'homepath', # needed by vpython
'goma_.*', # TODO(scottmg): This is ugly, but needed for goma.
'include',
'lib',
'libpath',
+ 'luci_context', # needed by vpython
'path',
'pathext',
'systemroot',
'temp',
'tmp',
+ 'userprofile', # needed by vpython
+ 'vpython_virtualenv_root' # needed by vpython
)
env = {}
+ # This occasionally happens and leads to misleading SYSTEMROOT error messages
+ # if not caught here.
+ if output_of_set.count('=') == 0:
+ raise Exception('Invalid output_of_set. Value is:\n%s' % output_of_set)
for line in output_of_set.splitlines():
for envvar in envvars_to_save:
- if re.match(envvar + '=', line.decode().lower()):
- var, setting = line.decode().split('=', 1)
+ if re.match(envvar + '=', line.lower()):
+ var, setting = line.split('=', 1)
if envvar == 'path':
- # Our own rules (for running gyp-win-tool) and other actions in
- # Chromium rely on python being in the path. Add the path to this
- # python here so that if it's not in the path when ninja is run
- # later, python will still be found.
+ # Our own rules and actions in Chromium rely on python being in the
+ # path. Add the path to this python here so that if it's not in the
+ # path when ninja is run later, python will still be found.
setting = os.path.dirname(sys.executable) + os.pathsep + setting
+ if envvar in ['include', 'lib']:
+ # Make sure that the include and lib paths point to directories that
+ # exist. This ensures a (relatively) clear error message if the
+ # required SDK is not installed.
+ for part in setting.split(';'):
+ if not os.path.exists(part) and len(part) != 0:
+ raise Exception(
+ 'Path "%s" from environment variable "%s" does not exist. '
+ 'Make sure the necessary SDK is installed.' % (part, envvar))
env[var.upper()] = setting
break
- for required in ('SYSTEMROOT', 'TEMP', 'TMP'):
- if required not in env:
- raise Exception('Environment variable "%s" '
- 'required to be set to valid path' % required)
+ if sys.platform in ('win32', 'cygwin'):
+ for required in ('SYSTEMROOT', 'TEMP', 'TMP'):
+ if required not in env:
+ raise Exception('Environment variable "%s" '
+ 'required to be set to valid path' % required)
return env
-def _SetupScript(target_cpu, sdk_dir):
- """Returns a command (with arguments) to be used to set up the
- environment."""
+def _DetectVisualStudioPath():
+ """Return path to the installed Visual Studio.
+ """
+
+ # Use the code in build/vs_toolchain.py to avoid duplicating code.
+ chromium_dir = os.path.abspath(os.path.join(SCRIPT_DIR, '..', '..', '..'))
+ sys.path.append(os.path.join(chromium_dir, 'build'))
+ import vs_toolchain
+ return vs_toolchain.DetectVisualStudioPath()
+
+
+def _LoadEnvFromBat(args):
+ """Given a bat command, runs it and returns env vars set by it."""
+ args = args[:]
+ args.extend(('&&', 'set'))
+ popen = subprocess.Popen(
+ args, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+ variables, _ = popen.communicate()
+ if popen.returncode != 0:
+ raise Exception('"%s" failed with error %d' % (args, popen.returncode))
+ return variables.decode(errors='ignore')
+
+
+def _LoadToolchainEnv(cpu, toolchain_root, sdk_dir, target_store):
+ """Returns a dictionary with environment variables that must be set while
+ running binaries from the toolchain (e.g. INCLUDE and PATH for cl.exe)."""
# Check if we are running in the SDK command line environment and use
- # the setup script from the SDK if so.
- assert target_cpu in ('x86', 'x64', 'arm64')
+ # the setup script from the SDK if so. |cpu| should be either
+ # 'x86' or 'x64' or 'arm' or 'arm64'.
+ assert cpu in ('x86', 'x64', 'arm', 'arm64')
if bool(int(os.environ.get('DEPOT_TOOLS_WIN_TOOLCHAIN', 1))) and sdk_dir:
- return [os.path.normpath(os.path.join(sdk_dir, 'Bin/SetEnv.Cmd')),
- '/' + target_cpu]
+ # Load environment from json file.
+ env = os.path.normpath(os.path.join(sdk_dir, 'bin/SetEnv.%s.json' % cpu))
+ env = json.load(open(env))['env']
+ if env['VSINSTALLDIR'] == [["..", "..\\"]]:
+ # Old-style paths were relative to the win_sdk\bin directory.
+ json_relative_dir = os.path.join(sdk_dir, 'bin')
+ else:
+ # New-style paths are relative to the toolchain directory.
+ json_relative_dir = toolchain_root
+ for k in env:
+ entries = [os.path.join(*([json_relative_dir] + e)) for e in env[k]]
+ # clang-cl wants INCLUDE to be ;-separated even on non-Windows,
+ # lld-link wants LIB to be ;-separated even on non-Windows. Path gets :.
+ # The separator for INCLUDE here must match the one used in main() below.
+ sep = os.pathsep if k == 'PATH' else ';'
+ env[k] = sep.join(entries)
+ # PATH is a bit of a special case, it's in addition to the current PATH.
+ env['PATH'] = env['PATH'] + os.pathsep + os.environ['PATH']
+ # Augment with the current env to pick up TEMP and friends.
+ for k in os.environ:
+ if k not in env:
+ env[k] = os.environ[k]
+
+ varlines = []
+ for k in sorted(env.keys()):
+ varlines.append('%s=%s' % (str(k), str(env[k])))
+ variables = '\n'.join(varlines)
+
+ # Check that the json file contained the same environment as the .cmd file.
+ if sys.platform in ('win32', 'cygwin'):
+ script = os.path.normpath(os.path.join(sdk_dir, 'Bin/SetEnv.cmd'))
+ arg = '/' + cpu
+ json_env = _ExtractImportantEnvironment(variables)
+ cmd_env = _ExtractImportantEnvironment(_LoadEnvFromBat([script, arg]))
+ assert _LowercaseDict(json_env) == _LowercaseDict(cmd_env)
else:
+ if 'GYP_MSVS_OVERRIDE_PATH' not in os.environ:
+ os.environ['GYP_MSVS_OVERRIDE_PATH'] = _DetectVisualStudioPath()
# We only support x64-hosted tools.
- # TODO(scottmg|dpranke): Non-depot_tools toolchain: need to get Visual
- # Studio install location from registry.
- return [os.path.normpath(os.path.join(os.environ['GYP_MSVS_OVERRIDE_PATH'],
- 'VC/Auxiliary/Build/vcvarsall.bat')),
- 'amd64_x86' if target_cpu == 'x86' else 'amd64']
+ script_path = os.path.normpath(os.path.join(
+ os.environ['GYP_MSVS_OVERRIDE_PATH'],
+ 'VC/vcvarsall.bat'))
+ if not os.path.exists(script_path):
+ # vcvarsall.bat for VS 2017 fails if run after running vcvarsall.bat from
+ # VS 2013 or VS 2015. Fix this by clearing the vsinstalldir environment
+ # variable. Since vcvarsall.bat appends to the INCLUDE, LIB, and LIBPATH
+ # environment variables we need to clear those to avoid getting double
+ # entries when vcvarsall.bat has been run before gn gen. vcvarsall.bat
+ # also adds to PATH, but there is no clean way of clearing that and it
+ # doesn't seem to cause problems.
+ if 'VSINSTALLDIR' in os.environ:
+ del os.environ['VSINSTALLDIR']
+ if 'INCLUDE' in os.environ:
+ del os.environ['INCLUDE']
+ if 'LIB' in os.environ:
+ del os.environ['LIB']
+ if 'LIBPATH' in os.environ:
+ del os.environ['LIBPATH']
+ other_path = os.path.normpath(os.path.join(
+ os.environ['GYP_MSVS_OVERRIDE_PATH'],
+ 'VC/Auxiliary/Build/vcvarsall.bat'))
+ if not os.path.exists(other_path):
+ raise Exception('%s is missing - make sure VC++ tools are installed.' %
+ script_path)
+ script_path = other_path
+ cpu_arg = "amd64"
+ if (cpu != 'x64'):
+ # x64 is default target CPU thus any other CPU requires a target set
+ cpu_arg += '_' + cpu
+ args = [script_path, cpu_arg, ]
+ # Store target must come before any SDK version declaration
+ if (target_store):
+ args.append('store')
+ # Explicitly specifying the SDK version to build with to avoid accidentally
+ # building with a new and untested SDK. This should stay in sync with the
+ # packaged toolchain in build/vs_toolchain.py.
+ args.append('10.0.20348.0')
+ variables = _LoadEnvFromBat(args)
+ return _ExtractImportantEnvironment(variables)
def _FormatAsEnvironmentBlock(envvar_dict):
@@ -81,76 +201,114 @@
return block
-def _CopyTool(source_path):
- """Copies the given tool to the current directory, including a warning not
- to edit it."""
- with open(source_path) as source_file:
- tool_source = source_file.readlines()
+def _LowercaseDict(d):
+ """Returns a copy of `d` with both key and values lowercased.
- # Add header and write it out to the current directory (which should be the
- # root build dir).
- with open("gyp-win-tool", 'w') as tool_file:
- tool_file.write(''.join([tool_source[0],
- '# Generated by setup_toolchain.py do not edit.\n']
- + tool_source[1:]))
+ Args:
+ d: dict to lowercase (e.g. {'A': 'BcD'}).
+
+ Returns:
+ A dict with both keys and values lowercased (e.g.: {'a': 'bcd'}).
+ """
+ return {k.lower(): d[k].lower() for k in d}
+
+
+def FindFileInEnvList(env, env_name, separator, file_name, optional=False):
+ parts = env[env_name].split(separator)
+ for path in parts:
+ if os.path.exists(os.path.join(path, file_name)):
+ return os.path.realpath(path)
+ assert optional, "%s is not found in %s:\n%s\nCheck if it is installed." % (
+ file_name, env_name, '\n'.join(parts))
+ return ''
def main():
- if len(sys.argv) != 5:
+ if len(sys.argv) != 7:
print('Usage setup_toolchain.py '
'<visual studio path> <win sdk path> '
- '<runtime dirs> <target_cpu>')
+ '<runtime dirs> <target_os> <target_cpu> '
+ '<environment block name|none>')
sys.exit(2)
+ # toolchain_root and win_sdk_path are only read if the hermetic Windows
+ # toolchain is set, that is if DEPOT_TOOLS_WIN_TOOLCHAIN is not set to 0.
+ # With the hermetic Windows toolchain, the visual studio path in argv[1]
+ # is the root of the Windows toolchain directory.
+ toolchain_root = sys.argv[1]
win_sdk_path = sys.argv[2]
- runtime_dirs = sys.argv[3]
- target_cpu = sys.argv[4]
- cpus = ('x86', 'x64', 'arm64')
+ runtime_dirs = sys.argv[3]
+ target_os = sys.argv[4]
+ target_cpu = sys.argv[5]
+ environment_block_name = sys.argv[6]
+ if (environment_block_name == 'none'):
+ environment_block_name = ''
+
+ if (target_os == 'winuwp'):
+ target_store = True
+ else:
+ target_store = False
+
+ cpus = ('x86', 'x64', 'arm', 'arm64')
assert target_cpu in cpus
vc_bin_dir = ''
+ include = ''
+ lib = ''
# TODO(scottmg|goma): Do we need an equivalent of
# ninja_use_custom_environment_files?
+ def relflag(s): # Make s relative to builddir when cwd and sdk on same drive.
+ try:
+ return os.path.relpath(s).replace('\\', '/')
+ except ValueError:
+ return s
+
+ def q(s): # Quote s if it contains spaces or other weird characters.
+ return s if re.match(r'^[a-zA-Z0-9._/\\:-]*$', s) else '"' + s + '"'
+
for cpu in cpus:
- # Extract environment variables for subprocesses.
- args = _SetupScript(cpu, win_sdk_path)
- args.extend(('&&', 'set'))
- popen = subprocess.Popen(
- args, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
- stdout_data, stderr_data = popen.communicate()
- if popen.returncode != 0:
- print('Error, got returncode:', popen.returncode)
- print('## stdout:')
- print(stdout_data)
- print('## stderr:')
- print(stderr_data)
- sys.exit(2)
- env = _ExtractImportantEnvironment(stdout_data)
- env['PATH'] = runtime_dirs + ';' + env['PATH']
-
if cpu == target_cpu:
- for path in env['PATH'].split(os.pathsep):
- if os.path.exists(os.path.join(path, 'cl.exe')):
- vc_bin_dir = os.path.realpath(path)
- break
+ # Extract environment variables for subprocesses.
+ env = _LoadToolchainEnv(cpu, toolchain_root, win_sdk_path, target_store)
+ env['PATH'] = runtime_dirs + os.pathsep + env['PATH']
- # The Windows SDK include directories must be first. They both have a sal.h,
- # and the SDK one is newer and the SDK uses some newer features from it not
- # present in the Visual Studio one.
+ vc_bin_dir = FindFileInEnvList(env, 'PATH', os.pathsep, 'cl.exe')
- if win_sdk_path:
- additional_includes = ('{sdk_dir}\\Include\\shared;' +
- '{sdk_dir}\\Include\\um;' +
- '{sdk_dir}\\Include\\winrt;').format(
- sdk_dir=win_sdk_path)
- env['INCLUDE'] = additional_includes + env['INCLUDE']
- env_block = _FormatAsEnvironmentBlock(env)
- with open('environment.' + cpu, 'wb') as f:
- f.write(env_block.encode())
+ # The separator for INCLUDE here must match the one used in
+ # _LoadToolchainEnv() above.
+ include = [p.replace('"', r'\"') for p in env['INCLUDE'].split(';') if p]
+ include = list(map(relflag, include))
- assert vc_bin_dir
- print('vc_bin_dir = "%s"' % vc_bin_dir)
+ lib = [p.replace('"', r'\"') for p in env['LIB'].split(';') if p]
+ lib = list(map(relflag, lib))
+
+ include_I = ' '.join([q('/I' + i) for i in include])
+ include_imsvc = ' '.join([q('-imsvc' + i) for i in include])
+ libpath_flags = ' '.join([q('-libpath:' + i) for i in lib])
+
+ if (environment_block_name != ''):
+ env_block = _FormatAsEnvironmentBlock(env)
+ with open(environment_block_name, 'w') as f:
+ f.write(env_block)
+
+ print('vc_bin_dir = ' + gn_helpers.ToGNString(vc_bin_dir))
+ assert include_I
+ print('include_flags_I = ' + gn_helpers.ToGNString(include_I))
+ assert include_imsvc
+ if bool(int(os.environ.get('DEPOT_TOOLS_WIN_TOOLCHAIN', 1))) and win_sdk_path:
+ print('include_flags_imsvc = ' +
+ gn_helpers.ToGNString(q('/winsysroot' + relflag(toolchain_root))))
+ else:
+ print('include_flags_imsvc = ' + gn_helpers.ToGNString(include_imsvc))
+ print('paths = ' + gn_helpers.ToGNString(env['PATH']))
+ assert libpath_flags
+ print('libpath_flags = ' + gn_helpers.ToGNString(libpath_flags))
+ if bool(int(os.environ.get('DEPOT_TOOLS_WIN_TOOLCHAIN', 1))) and win_sdk_path:
+ print('libpath_lldlink_flags = ' +
+ gn_helpers.ToGNString(q('/winsysroot:' + relflag(toolchain_root))))
+ else:
+ print('libpath_lldlink_flags = ' + gn_helpers.ToGNString(libpath_flags))
if __name__ == '__main__':
diff --git a/build/vs_toolchain.py b/build/vs_toolchain.py
index 6314e5e..9b0a7c8 100644
--- a/build/vs_toolchain.py
+++ b/build/vs_toolchain.py
@@ -1,18 +1,14 @@
#!/usr/bin/env python3
-#
# Copyright 2014 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-
+#
# For Dart/Flutter developers:
-# This file keeps the MSVC toolchain up-to-date for Google developers.
-# It is copied from Chromium:
+# This file is copied from Chromium:
# https://cs.chromium.org/chromium/src/build/vs_toolchain.py
-# with modifications that update paths, and remove dependencies on gyp.
-# To update to a new MSVC toolchain, copy the updated script from the Chromium
-# tree, and edit to make it work in the Dart tree by updating paths in the original script.
-
-
+# When updating replace reference to python on the first line with python3.
+#
+from __future__ import print_function
import collections
import glob
@@ -26,21 +22,47 @@
import subprocess
import sys
-
from gn_helpers import ToGNString
+# VS 2019 16.61 with 10.0.20348.0 SDK, 10.0.19041 version of Debuggers
+# with ARM64 libraries and UWP support.
+# See go/chromium-msvc-toolchain for instructions about how to update the
+# toolchain.
+#
+# When updating the toolchain, consider the following areas impacted by the
+# toolchain version:
+#
+# * //base/win/windows_version.cc NTDDI preprocessor check
+# Triggers a compiler error if the available SDK is older than the minimum.
+# * //build/config/win/BUILD.gn NTDDI_VERSION value
+# Affects the availability of APIs in the toolchain headers.
+# * //docs/windows_build_instructions.md mentions of VS or Windows SDK.
+# Keeps the document consistent with the toolchain version.
+TOOLCHAIN_HASH = '1023ce2e82'
+
script_dir = os.path.dirname(os.path.realpath(__file__))
json_data_file = os.path.join(script_dir, 'win_toolchain.json')
-sys.path.insert(0, os.path.join(script_dir, '..', 'tools'))
-
# VS versions are listed in descending order of priority (highest first).
+# The first version is assumed by this script to be the one that is packaged,
+# which makes a difference for the arm64 runtime.
MSVS_VERSIONS = collections.OrderedDict([
- ('2017', '15.0'),
- ('2019', '16.0'),
- ('2022', '17.0'),
+ ('2019', '16.0'), # Default and packaged version of Visual Studio.
+ ('2022', '17.0'),
+ ('2017', '15.0'),
])
+# List of preferred VC toolset version based on MSVS
+# Order is not relevant for this dictionary.
+MSVC_TOOLSET_VERSION = {
+ '2022': 'VC143',
+ '2019': 'VC142',
+ '2017': 'VC141',
+}
+
+def _HostIsWindows():
+ """Returns True if running on a Windows host (including under cygwin)."""
+ return sys.platform in ('win32', 'cygwin')
def SetEnvironmentAndGetRuntimeDllDirs():
"""Sets up os.environ to use the depot_tools VS toolchain with gyp, and
@@ -56,7 +78,7 @@
bool(int(os.environ.get('DEPOT_TOOLS_WIN_TOOLCHAIN', '1')))
# When running on a non-Windows host, only do this if the SDK has explicitly
# been downloaded before (in which case json_data_file will exist).
- if ((sys.platform in ('win32', 'cygwin') or os.path.exists(json_data_file))
+ if ((_HostIsWindows() or os.path.exists(json_data_file))
and depot_tools_win_toolchain):
if ShouldUpdateToolchain():
if len(sys.argv) > 1 and sys.argv[1] == 'update':
@@ -71,8 +93,6 @@
toolchain = toolchain_data['path']
version = toolchain_data['version']
win_sdk = toolchain_data.get('win_sdk')
- if not win_sdk:
- 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 x64/x86/arm64. (See CopyDlls call below).
@@ -85,7 +105,6 @@
vs_runtime_dll_dirs.append('Arm64Unused')
os.environ['GYP_MSVS_OVERRIDE_PATH'] = toolchain
- os.environ['GYP_MSVS_VERSION'] = version
os.environ['WINDOWSSDKDIR'] = win_sdk
os.environ['WDK_DIR'] = wdk
@@ -95,8 +114,6 @@
elif sys.platform == 'win32' and not depot_tools_win_toolchain:
if not 'GYP_MSVS_OVERRIDE_PATH' in os.environ:
os.environ['GYP_MSVS_OVERRIDE_PATH'] = DetectVisualStudioPath()
- if not 'GYP_MSVS_VERSION' in os.environ:
- os.environ['GYP_MSVS_VERSION'] = GetVisualStudioVersion()
# When using an installed toolchain these files aren't needed in the output
# directory in order to run binaries locally, but they are needed in order
@@ -126,12 +143,12 @@
contents of the registry key's value, or None on failure. Throws
ImportError if _winreg is unavailable.
"""
- import winreg
+ import _winreg
try:
root, subkey = key.split('\\', 1)
assert root == 'HKLM' # Only need HKLM for now.
- with winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, subkey) as hkey:
- return winreg.QueryValueEx(hkey, value)[0]
+ with _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, subkey) as hkey:
+ return _winreg.QueryValueEx(hkey, value)[0]
except WindowsError:
return None
@@ -146,31 +163,38 @@
def GetVisualStudioVersion():
"""Return best available version of Visual Studio.
"""
-
- env_version = os.environ.get('GYP_MSVS_VERSION')
- if env_version:
- return env_version
-
supported_versions = list(MSVS_VERSIONS.keys())
# VS installed in depot_tools for Googlers
if bool(int(os.environ.get('DEPOT_TOOLS_WIN_TOOLCHAIN', '1'))):
- return list(supported_versions)[0]
+ return supported_versions[0]
# VS installed in system for external developers
supported_versions_str = ', '.join('{} ({})'.format(v,k)
- for k,v in list(MSVS_VERSIONS.items()))
+ for k,v in MSVS_VERSIONS.items())
available_versions = []
for version in supported_versions:
- for path in (
- os.environ.get('vs%s_install' % version),
- os.path.expandvars('%ProgramFiles(x86)%' +
- '/Microsoft Visual Studio/%s' % version),
- os.path.expandvars('%ProgramFiles%' +
- '/Microsoft Visual Studio/%s' % version)):
- if path and os.path.exists(path):
- available_versions.append(version)
- break
+ # Checking vs%s_install environment variables.
+ # For example, vs2019_install could have the value
+ # "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community".
+ # Only vs2017_install, vs2019_install and vs2022_install are supported.
+ path = os.environ.get('vs%s_install' % version)
+ if path and os.path.exists(path):
+ available_versions.append(version)
+ break
+ # Detecting VS under possible paths.
+ if version >= '2022':
+ program_files_path_variable = '%ProgramFiles%'
+ else:
+ program_files_path_variable = '%ProgramFiles(x86)%'
+ path = os.path.expandvars(program_files_path_variable +
+ '/Microsoft Visual Studio/%s' % version)
+ if path and any(
+ os.path.exists(os.path.join(path, edition))
+ for edition in ('Enterprise', 'Professional', 'Community', 'Preview',
+ 'BuildTools')):
+ available_versions.append(version)
+ break
if not available_versions:
raise Exception('No supported Visual Studio can be found.'
@@ -179,7 +203,7 @@
def DetectVisualStudioPath():
- """Return path to the GYP_MSVS_VERSION of Visual Studio.
+ """Return path to the installed Visual Studio.
"""
# Note that this code is used from
@@ -190,18 +214,30 @@
# the registry. For details see:
# https://blogs.msdn.microsoft.com/heaths/2016/09/15/changes-to-visual-studio-15-setup/
# For now we use a hardcoded default with an environment variable override.
- possible_install_paths = (
- os.path.expandvars('%s/Microsoft Visual Studio/%s/%s' %
- (program_path_var, version_as_year, product))
- for program_path_var in ('%ProgramFiles%', '%ProgramFiles(x86)%')
- for product in ('Enterprise', 'Professional', 'Community', 'Preview'))
- for path in (
- os.environ.get('vs%s_install' % version_as_year), *possible_install_paths):
+ if version_as_year >= '2022':
+ program_files_path_variable = '%ProgramFiles%'
+ else:
+ program_files_path_variable = '%ProgramFiles(x86)%'
+ for path in (os.environ.get('vs%s_install' % version_as_year),
+ os.path.expandvars(program_files_path_variable +
+ '/Microsoft Visual Studio/%s/Enterprise' %
+ version_as_year),
+ os.path.expandvars(program_files_path_variable +
+ '/Microsoft Visual Studio/%s/Professional' %
+ version_as_year),
+ os.path.expandvars(program_files_path_variable +
+ '/Microsoft Visual Studio/%s/Community' %
+ version_as_year),
+ os.path.expandvars(program_files_path_variable +
+ '/Microsoft Visual Studio/%s/Preview' %
+ version_as_year),
+ os.path.expandvars(program_files_path_variable +
+ '/Microsoft Visual Studio/%s/BuildTools' %
+ version_as_year)):
if path and os.path.exists(path):
return path
- raise Exception('Visual Studio Version %s (from GYP_MSVS_VERSION)'
- ' not found.' % version_as_year)
+ raise Exception('Visual Studio Version %s not found.' % version_as_year)
def _CopyRuntimeImpl(target, source, verbose=True):
@@ -243,21 +279,30 @@
list_of_str_versions.sort(key=to_number_sequence, reverse=True)
-def _CopyUCRTRuntime(target_dir, source_dir, target_cpu, dll_pattern, suffix):
+
+def _CopyUCRTRuntime(target_dir, source_dir, target_cpu, suffix):
"""Copy both the msvcp and vccorlib runtime DLLs, only if the target doesn't
exist, but the target directory does exist."""
if target_cpu == 'arm64':
# Windows ARM64 VCRuntime is located at {toolchain_root}/VC/Redist/MSVC/
- # {x.y.z}/[debug_nonredist/]arm64/Microsoft.VC141.CRT/.
+ # {x.y.z}/[debug_nonredist/]arm64/Microsoft.VC14x.CRT/.
+ # Select VC toolset directory based on Visual Studio version
vc_redist_root = FindVCRedistRoot()
if suffix.startswith('.'):
+ vc_toolset_dir = 'Microsoft.{}.CRT' \
+ .format(MSVC_TOOLSET_VERSION[GetVisualStudioVersion()])
source_dir = os.path.join(vc_redist_root,
- 'arm64', 'Microsoft.VC141.CRT')
+ 'arm64', vc_toolset_dir)
else:
+ vc_toolset_dir = 'Microsoft.{}.DebugCRT' \
+ .format(MSVC_TOOLSET_VERSION[GetVisualStudioVersion()])
source_dir = os.path.join(vc_redist_root, 'debug_nonredist',
- 'arm64', 'Microsoft.VC141.DebugCRT')
- for file_part in ('msvcp', 'vccorlib', 'vcruntime'):
- dll = dll_pattern % file_part
+ 'arm64', vc_toolset_dir)
+ file_parts = ('msvcp140', 'vccorlib140', 'vcruntime140')
+ if target_cpu == 'x64' and GetVisualStudioVersion() != '2017':
+ file_parts = file_parts + ('vcruntime140_1', )
+ for file_part in file_parts:
+ dll = file_part + suffix
target = os.path.join(target_dir, dll)
source = os.path.join(source_dir, dll)
_CopyRuntimeImpl(target, source)
@@ -317,14 +362,13 @@
assert ('GYP_MSVS_OVERRIDE_PATH' in os.environ)
vc_component_msvc_root = os.path.join(os.environ['GYP_MSVS_OVERRIDE_PATH'],
'VC', component, 'MSVC')
- vc_component_msvc_contents = os.listdir(vc_component_msvc_root)
+ vc_component_msvc_contents = glob.glob(
+ os.path.join(vc_component_msvc_root, '14.*'))
# Select the most recent toolchain if there are several.
_SortByHighestVersionNumberFirst(vc_component_msvc_contents)
for directory in vc_component_msvc_contents:
- if not os.path.isdir(os.path.join(vc_component_msvc_root, directory)):
- continue
- if re.match(r'14\.\d+\.\d+', directory):
- return os.path.join(vc_component_msvc_root, directory)
+ if os.path.isdir(directory):
+ return directory
raise Exception('Unable to find the VC %s directory.' % component)
@@ -342,8 +386,7 @@
directory does exist. Handles VS 2015, 2017 and 2019."""
suffix = 'd.dll' if debug else '.dll'
# VS 2015, 2017 and 2019 use the same CRT DLLs.
- _CopyUCRTRuntime(target_dir, source_dir, target_cpu, '%s140' + suffix,
- suffix)
+ _CopyUCRTRuntime(target_dir, source_dir, target_cpu, suffix)
def CopyDlls(target_dir, configuration, target_cpu):
@@ -394,17 +437,20 @@
# List of debug files that should be copied, the first element of the tuple is
# the name of the file and the second indicates if it's optional.
debug_files = [('dbghelp.dll', False), ('dbgcore.dll', True)]
+ # The UCRT is not a redistributable component on arm64.
+ if target_cpu != 'arm64':
+ debug_files.extend([('api-ms-win-downlevel-kernel32-l2-1-0.dll', False),
+ ('api-ms-win-eventing-provider-l1-1-0.dll', False)])
for debug_file, is_optional in debug_files:
full_path = os.path.join(win_sdk_dir, 'Debuggers', target_cpu, debug_file)
if not os.path.exists(full_path):
if is_optional:
continue
else:
- # TODO(crbug.com/773476): remove version requirement.
- raise Exception('%s not found in "%s"\r\nYou must install the '
- '"Debugging Tools for Windows" feature from the Windows'
- ' 10 SDK.'
- % (debug_file, full_path))
+ raise Exception('%s not found in "%s"\r\nYou must install '
+ 'Windows 10 SDK version 10.0.20348.0 including the '
+ '"Debugging Tools for Windows" feature.' %
+ (debug_file, full_path))
target_path = os.path.join(target_dir, debug_file)
_CopyRuntimeImpl(target_path, full_path)
@@ -412,17 +458,10 @@
def _GetDesiredVsToolchainHashes():
"""Load a list of SHA1s corresponding to the toolchains that we want installed
to build with."""
- env_version = GetVisualStudioVersion()
- if env_version == '2017':
- # VS 2017 Update 9 (15.9.12) with 10.0.18362 SDK, 10.0.17763 version of
- # Debuggers, and 10.0.17134 version of d3dcompiler_47.dll, with ARM64
- # libraries.
- toolchain_hash = '418b3076791776573a815eb298c8aa590307af63'
- # Third parties that do not have access to the canonical toolchain can map
- # canonical toolchain version to their own toolchain versions.
- toolchain_hash_mapping_key = 'GYP_MSVS_HASH_%s' % toolchain_hash
- return [os.environ.get(toolchain_hash_mapping_key, toolchain_hash)]
- raise Exception('Unsupported VS version %s' % env_version)
+ # Third parties that do not have access to the canonical toolchain can map
+ # canonical toolchain version to their own toolchain versions.
+ toolchain_hash_mapping_key = 'GYP_MSVS_HASH_%s' % TOOLCHAIN_HASH
+ return [os.environ.get(toolchain_hash_mapping_key, TOOLCHAIN_HASH)]
def ShouldUpdateToolchain():
@@ -453,8 +492,7 @@
depot_tools_win_toolchain = \
bool(int(os.environ.get('DEPOT_TOOLS_WIN_TOOLCHAIN', '1')))
- if ((sys.platform in ('win32', 'cygwin') or force) and
- depot_tools_win_toolchain):
+ if (_HostIsWindows() or force) and depot_tools_win_toolchain:
import find_depot_tools
depot_tools_path = find_depot_tools.add_depot_tools_to_path()
@@ -482,9 +520,6 @@
subprocess.check_call([
ciopfs, '-o', 'use_ino', toolchain_dir + '.ciopfs', toolchain_dir])
- # Necessary so that get_toolchain_if_necessary.py will put the VS toolkit
- # in the correct directory.
- os.environ['GYP_MSVS_VERSION'] = GetVisualStudioVersion()
get_toolchain_args = [
sys.executable,
os.path.join(depot_tools_path,
diff --git a/runtime/vm/compiler/backend/block_builder.h b/runtime/vm/compiler/backend/block_builder.h
index 4a36631..4566280 100644
--- a/runtime/vm/compiler/backend/block_builder.h
+++ b/runtime/vm/compiler/backend/block_builder.h
@@ -24,8 +24,7 @@
flow_graph->inlining_id())),
entry_(entry),
current_(entry),
- dummy_env_(
- new Environment(0, 0, 0, flow_graph->parsed_function(), nullptr)) {
+ dummy_env_(new Environment(0, 0, 0, flow_graph->function(), nullptr)) {
// Some graph transformations use environments from block entries.
entry->SetEnvironment(dummy_env_);
}
diff --git a/runtime/vm/compiler/backend/il.cc b/runtime/vm/compiler/backend/il.cc
index e7f9172..5330a4e 100644
--- a/runtime/vm/compiler/backend/il.cc
+++ b/runtime/vm/compiler/backend/il.cc
@@ -5867,9 +5867,9 @@
intptr_t fixed_parameter_count,
intptr_t lazy_deopt_pruning_count,
const ParsedFunction& parsed_function) {
- Environment* env =
- new (zone) Environment(definitions.length(), fixed_parameter_count,
- lazy_deopt_pruning_count, parsed_function, NULL);
+ Environment* env = new (zone)
+ Environment(definitions.length(), fixed_parameter_count,
+ lazy_deopt_pruning_count, parsed_function.function(), NULL);
for (intptr_t i = 0; i < definitions.length(); ++i) {
env->values_.Add(new (zone) Value(definitions[i]));
}
@@ -5882,9 +5882,9 @@
Environment* Environment::DeepCopy(Zone* zone, intptr_t length) const {
ASSERT(length <= values_.length());
- Environment* copy = new (zone) Environment(
- length, fixed_parameter_count_, LazyDeoptPruneCount(), parsed_function_,
- (outer_ == NULL) ? NULL : outer_->DeepCopy(zone));
+ Environment* copy = new (zone)
+ Environment(length, fixed_parameter_count_, LazyDeoptPruneCount(),
+ function_, (outer_ == NULL) ? NULL : outer_->DeepCopy(zone));
copy->SetDeoptId(DeoptIdBits::decode(bitfield_));
copy->SetLazyDeoptToBeforeDeoptId(LazyDeoptToBeforeDeoptId());
if (locations_ != NULL) {
@@ -6355,16 +6355,10 @@
intptr_t deopt_id,
MethodRecognizer::Kind recognized_kind,
const InstructionSource& source)
- : PureDefinition(source, deopt_id),
- inputs_(inputs),
+ : VariadicDefinition(inputs, source, deopt_id),
recognized_kind_(recognized_kind),
token_pos_(source.token_pos) {
ASSERT(inputs_->length() == ArgumentCountFor(recognized_kind_));
- for (intptr_t i = 0; i < inputs_->length(); ++i) {
- ASSERT((*inputs)[i] != NULL);
- (*inputs)[i]->set_instruction(this);
- (*inputs)[i]->set_use_index(i);
- }
}
intptr_t InvokeMathCFunctionInstr::ArgumentCountFor(
@@ -6599,7 +6593,7 @@
}
// Moves for arguments.
- compiler::ffi::FrameRebase rebase(zone_, /*old_base=*/FPREG,
+ compiler::ffi::FrameRebase rebase(compiler->zone(), /*old_base=*/FPREG,
/*new_base=*/saved_fp,
/*stack_delta=*/0);
intptr_t def_index = 0;
@@ -6627,7 +6621,8 @@
: arg_target.IsMultiple() ? *arg_target.AsMultiple().locations()[i]
: arg_target.IsPointerToMemory()
? arg_target.AsPointerToMemory().pointer_location()
- : /*arg_target.IsStack()*/ arg_target.Split(zone_, num_defs, i);
+ : /*arg_target.IsStack()*/ arg_target.Split(compiler->zone(),
+ num_defs, i);
ConstantTemporaryAllocator temp_alloc(temp0);
if (origin.IsConstant()) {
@@ -6692,8 +6687,8 @@
// TypedData/Pointer data pointed to in temp.
const auto& dst = compiler::ffi::NativeRegistersLocation(
- zone_, pointer_loc.payload_type(), pointer_loc.container_type(),
- temp0);
+ compiler->zone(), pointer_loc.payload_type(),
+ pointer_loc.container_type(), temp0);
compiler->EmitNativeMove(dst, pointer_loc, &temp_alloc);
__ LoadField(temp0,
compiler::FieldAddress(
@@ -6715,8 +6710,8 @@
__ MoveRegister(temp0, SPREG);
__ AddImmediate(temp0, sp_offset);
const auto& src = compiler::ffi::NativeRegistersLocation(
- zone_, pointer_loc.payload_type(), pointer_loc.container_type(),
- temp0);
+ compiler->zone(), pointer_loc.payload_type(),
+ pointer_loc.container_type(), temp0);
__ Comment("pointer_loc %s <- src %s", pointer_loc.ToCString(),
src.ToCString());
compiler->EmitNativeMove(pointer_loc, src, &temp_alloc);
@@ -7001,21 +6996,15 @@
}
CCallInstr::CCallInstr(
- Zone* zone,
const compiler::ffi::NativeCallingConvention& native_calling_convention,
InputsArray* inputs)
- : Definition(DeoptId::kNone),
- zone_(zone),
- native_calling_convention_(native_calling_convention),
- inputs_(inputs) {
+ : VariadicDefinition(inputs, DeoptId::kNone),
+ native_calling_convention_(native_calling_convention) {
#ifdef DEBUG
const intptr_t num_inputs =
native_calling_convention.argument_locations().length() + 1;
ASSERT(num_inputs == inputs->length());
#endif
- for (intptr_t i = 0, n = inputs_->length(); i < n; ++i) {
- SetInputAt(i, (*inputs_)[i]);
- }
}
Representation CCallInstr::RequiredInputRepresentation(intptr_t idx) const {
@@ -7037,7 +7026,7 @@
}
ConstantTemporaryAllocator temp_alloc(temp0);
- compiler::ffi::FrameRebase rebase(zone_, /*old_base=*/FPREG,
+ compiler::ffi::FrameRebase rebase(compiler->zone(), /*old_base=*/FPREG,
/*new_base=*/saved_fp,
/*stack_delta=*/0);
diff --git a/runtime/vm/compiler/backend/il.h b/runtime/vm/compiler/backend/il.h
index af9f8b1..a9e3066 100644
--- a/runtime/vm/compiler/backend/il.h
+++ b/runtime/vm/compiler/backend/il.h
@@ -1488,7 +1488,7 @@
// predecessors. Targets are all other basic block entries. The types
// enforce edge-split form---joins are forbidden as the successors of
// branches.
-class BlockEntryInstr : public Instruction {
+class BlockEntryInstr : public TemplateInstruction<0, NoThrow> {
public:
virtual intptr_t PredecessorCount() const = 0;
virtual BlockEntryInstr* PredecessorAt(intptr_t index) const = 0;
@@ -1558,12 +1558,6 @@
GrowableArray<BlockEntryInstr*>* preorder,
GrowableArray<intptr_t>* parent);
- virtual intptr_t InputCount() const { return 0; }
- virtual Value* InputAt(intptr_t i) const {
- UNREACHABLE();
- return NULL;
- }
-
virtual bool CanBecomeDeoptimizationTarget() const {
// BlockEntry environment is copied to Goto and Branch instructions
// when we insert new blocks targeting this block.
@@ -1574,8 +1568,6 @@
virtual bool HasUnknownSideEffects() const { return false; }
- virtual bool MayThrow() const { return false; }
-
intptr_t try_index() const { return try_index_; }
void set_try_index(intptr_t index) { try_index_ = index; }
@@ -1629,7 +1621,7 @@
intptr_t try_index,
intptr_t deopt_id,
intptr_t stack_depth)
- : Instruction(deopt_id),
+ : TemplateInstruction(deopt_id),
block_id_(block_id),
try_index_(try_index),
stack_depth_(stack_depth),
@@ -1642,8 +1634,6 @@
BitVector* block_marks);
private:
- virtual void RawSetInputAt(intptr_t i, Value* value) { UNREACHABLE(); }
-
virtual void ClearPredecessors() = 0;
virtual void AddPredecessor(BlockEntryInstr* predecessor) = 0;
@@ -2253,17 +2243,6 @@
}
}
- static bool Parse(const char* str, AliasIdentity* out) {
-#define VALUE_CASE(name, val) \
- if (strcmp(str, #name) == 0) { \
- out->value_ = k##name; \
- return true; \
- }
- FOR_EACH_ALIAS_IDENTITY_VALUE(VALUE_CASE)
-#undef VALUE_CASE
- return false;
- }
-
bool IsUnknown() const { return value_ == kUnknown; }
bool IsAliased() const { return value_ == kAliased; }
bool IsNotAliased() const { return (value_ & kNotAliased) != 0; }
@@ -2553,18 +2532,67 @@
virtual void RawSetInputAt(intptr_t i, Value* value) { inputs_[i] = value; }
};
-class PhiInstr : public Definition {
+class VariadicDefinition : public Definition {
public:
- PhiInstr(JoinEntryInstr* block, intptr_t num_inputs)
- : block_(block),
- inputs_(num_inputs),
- representation_(kTagged),
- is_alive_(false),
- is_receiver_(kUnknownReceiver) {
- for (intptr_t i = 0; i < num_inputs; ++i) {
- inputs_.Add(NULL);
+ explicit VariadicDefinition(InputsArray* inputs,
+ intptr_t deopt_id = DeoptId::kNone)
+ : Definition(deopt_id), inputs_(inputs) {
+ for (intptr_t i = 0, n = inputs_->length(); i < n; ++i) {
+ SetInputAt(i, (*inputs_)[i]);
}
}
+ VariadicDefinition(InputsArray* inputs,
+ const InstructionSource& source,
+ intptr_t deopt_id = DeoptId::kNone)
+ : Definition(source, deopt_id), inputs_(inputs) {
+ for (intptr_t i = 0, n = inputs_->length(); i < n; ++i) {
+ SetInputAt(i, (*inputs_)[i]);
+ }
+ }
+
+ intptr_t InputCount() const { return inputs_->length(); }
+ Value* InputAt(intptr_t i) const { return (*inputs_)[i]; }
+
+ protected:
+ InputsArray* inputs_;
+
+ private:
+ void RawSetInputAt(intptr_t i, Value* value) { (*inputs_)[i] = value; }
+};
+
+class VariadicDefinitionWithEmbeddedInputs : public Definition {
+ public:
+ explicit VariadicDefinitionWithEmbeddedInputs(
+ const intptr_t num_inputs,
+ intptr_t deopt_id = DeoptId::kNone)
+ : Definition(deopt_id), inputs_(num_inputs) {
+ inputs_.EnsureLength(num_inputs, nullptr);
+ }
+ VariadicDefinitionWithEmbeddedInputs(const intptr_t num_inputs,
+ const InstructionSource& source,
+ intptr_t deopt_id = DeoptId::kNone)
+ : Definition(source, deopt_id), inputs_(num_inputs) {
+ inputs_.EnsureLength(num_inputs, nullptr);
+ }
+
+ intptr_t InputCount() const { return inputs_.length(); }
+ Value* InputAt(intptr_t i) const { return inputs_[i]; }
+
+ protected:
+ GrowableArray<Value*> inputs_;
+
+ private:
+ void RawSetInputAt(intptr_t i, Value* value) { inputs_[i] = value; }
+};
+
+class PhiInstr : public VariadicDefinitionWithEmbeddedInputs {
+ public:
+ PhiInstr(JoinEntryInstr* block, intptr_t num_inputs)
+ : VariadicDefinitionWithEmbeddedInputs(num_inputs),
+ block_(block),
+ representation_(kTagged),
+ is_alive_(false),
+ is_receiver_(kUnknownReceiver) {}
// Get the block entry for that instruction.
virtual BlockEntryInstr* GetBlock() { return block(); }
@@ -2573,10 +2601,6 @@
virtual CompileType ComputeType() const;
virtual bool RecomputeType();
- intptr_t InputCount() const { return inputs_.length(); }
-
- Value* InputAt(intptr_t i) const { return inputs_[i]; }
-
virtual bool ComputeCanDeoptimize() const { return false; }
virtual bool HasUnknownSideEffects() const { return false; }
@@ -2644,10 +2668,7 @@
// predecessors.
friend class ConstantPropagator;
- void RawSetInputAt(intptr_t i, Value* value) { inputs_[i] = value; }
-
JoinEntryInstr* block_;
- GrowableArray<Value*> inputs_;
Representation representation_;
BitVector* reaching_defs_ = nullptr;
bool is_alive_;
@@ -2663,7 +2684,7 @@
// (0 is the very first parameter, 1 is next and so on). When [base_reg] is
// set to SPREG, value [index] needs to be reversed (0 is the very last
// parameter, 1 is next and so on) to get the sp relative position.
-class ParameterInstr : public Definition {
+class ParameterInstr : public TemplateDefinition<0, NoThrow> {
public:
ParameterInstr(intptr_t index,
intptr_t param_offset,
@@ -2687,12 +2708,6 @@
virtual BlockEntryInstr* GetBlock() { return block_; }
void set_block(BlockEntryInstr* block) { block_ = block; }
- intptr_t InputCount() const { return 0; }
- Value* InputAt(intptr_t i) const {
- UNREACHABLE();
- return NULL;
- }
-
virtual Representation representation() const { return representation_; }
virtual Representation RequiredInputRepresentation(intptr_t index) const {
@@ -2711,13 +2726,9 @@
virtual CompileType ComputeType() const;
- virtual bool MayThrow() const { return false; }
-
PRINT_OPERANDS_TO_SUPPORT
private:
- virtual void RawSetInputAt(intptr_t i, Value* value) { UNREACHABLE(); }
-
const intptr_t index_;
// The offset (in words) of the last slot of the parameter, relative
@@ -2739,7 +2750,7 @@
// NativeEntryInstr::EmitNativeCode for more details.
//
// TOOD(33549): Unify with ParameterInstr.
-class NativeParameterInstr : public Definition {
+class NativeParameterInstr : public TemplateDefinition<0, NoThrow> {
public:
NativeParameterInstr(const compiler::ffi::CallbackMarshaller& marshaller,
intptr_t def_index)
@@ -2751,12 +2762,6 @@
return marshaller_.RepInFfiCall(def_index_);
}
- intptr_t InputCount() const { return 0; }
- Value* InputAt(intptr_t i) const {
- UNREACHABLE();
- return NULL;
- }
-
virtual bool ComputeCanDeoptimize() const { return false; }
virtual bool HasUnknownSideEffects() const { return false; }
@@ -2764,13 +2769,9 @@
// TODO(sjindel): We can make this more precise.
virtual CompileType ComputeType() const { return CompileType::Dynamic(); }
- virtual bool MayThrow() const { return false; }
-
PRINT_OPERANDS_TO_SUPPORT
private:
- virtual void RawSetInputAt(intptr_t i, Value* value) { UNREACHABLE(); }
-
const compiler::ffi::CallbackMarshaller& marshaller_;
const intptr_t def_index_;
@@ -4013,23 +4014,19 @@
};
template <intptr_t kExtraInputs>
-class TemplateDartCall : public Definition {
+class TemplateDartCall : public VariadicDefinition {
public:
TemplateDartCall(intptr_t deopt_id,
intptr_t type_args_len,
const Array& argument_names,
InputsArray* inputs,
const InstructionSource& source)
- : Definition(source, deopt_id),
+ : VariadicDefinition(inputs, source, deopt_id),
type_args_len_(type_args_len),
argument_names_(argument_names),
- inputs_(inputs),
token_pos_(source.token_pos) {
ASSERT(argument_names.IsZoneHandle() || argument_names.InVMIsolateHeap());
ASSERT(inputs_->length() >= kExtraInputs);
- for (intptr_t i = 0, n = inputs_->length(); i < n; ++i) {
- SetInputAt(i, (*inputs_)[i]);
- }
}
inline StringPtr Selector();
@@ -4037,8 +4034,6 @@
virtual bool MayThrow() const { return true; }
virtual bool CanCallDart() const { return true; }
- virtual intptr_t InputCount() const { return inputs_->length(); }
- virtual Value* InputAt(intptr_t i) const { return inputs_->At(i); }
virtual bool ComputeCanDeoptimize() const { return false; }
virtual bool ComputeCanDeoptimizeAfterCall() const {
return !CompilerState::Current().is_aot();
@@ -4095,13 +4090,8 @@
}
private:
- virtual void RawSetInputAt(intptr_t i, Value* value) {
- (*inputs_)[i] = value;
- }
-
intptr_t type_args_len_;
const Array& argument_names_;
- InputsArray* inputs_;
PushArgumentsArray* push_arguments_ = nullptr;
TokenPosition token_pos_;
@@ -5063,17 +5053,17 @@
class DropTempsInstr : public Definition {
public:
DropTempsInstr(intptr_t num_temps, Value* value)
- : num_temps_(num_temps), value_(NULL) {
- if (value != NULL) {
+ : num_temps_(num_temps), has_input_(value != nullptr) {
+ if (has_input_) {
SetInputAt(0, value);
}
}
DECLARE_INSTRUCTION(DropTemps)
- virtual intptr_t InputCount() const { return value_ != NULL ? 1 : 0; }
+ virtual intptr_t InputCount() const { return has_input_ ? 1 : 0; }
virtual Value* InputAt(intptr_t i) const {
- ASSERT((value_ != NULL) && (i == 0));
+ ASSERT(has_input_ && (i == 0));
return value_;
}
@@ -5097,10 +5087,14 @@
PRINT_OPERANDS_TO_SUPPORT
private:
- virtual void RawSetInputAt(intptr_t i, Value* value) { value_ = value; }
+ virtual void RawSetInputAt(intptr_t i, Value* value) {
+ ASSERT(has_input_);
+ value_ = value;
+ }
const intptr_t num_temps_;
- Value* value_;
+ const bool has_input_;
+ Value* value_ = nullptr;
DISALLOW_COPY_AND_ASSIGN(DropTempsInstr);
};
@@ -5194,8 +5188,8 @@
class NativeCallInstr : public TemplateDartCall<0> {
public:
- NativeCallInstr(const String* name,
- const Function* function,
+ NativeCallInstr(const String& name,
+ const Function& function,
bool link_lazily,
const InstructionSource& source,
InputsArray* args)
@@ -5207,14 +5201,14 @@
is_auto_scope_(true),
link_lazily_(link_lazily),
token_pos_(source.token_pos) {
- ASSERT(name->IsZoneHandle());
- ASSERT(function->IsZoneHandle());
+ ASSERT(name.IsZoneHandle());
+ ASSERT(function.IsZoneHandle());
}
DECLARE_INSTRUCTION(NativeCall)
- const String& native_name() const { return *native_name_; }
- const Function& function() const { return *function_; }
+ const String& native_name() const { return native_name_; }
+ const Function& function() const { return function_; }
NativeFunction native_c_function() const { return native_c_function_; }
bool is_bootstrap_native() const { return is_bootstrap_native_; }
bool is_auto_scope() const { return is_auto_scope_; }
@@ -5240,8 +5234,8 @@
void set_is_bootstrap_native(bool value) { is_bootstrap_native_ = value; }
void set_is_auto_scope(bool value) { is_auto_scope_ = value; }
- const String* native_name_;
- const Function* function_;
+ const String& native_name_;
+ const Function& function_;
NativeFunction native_c_function_;
bool is_bootstrap_native_;
bool is_auto_scope_;
@@ -5260,22 +5254,17 @@
// - The arguments to the native call, marshalled in IL as far as possible.
// - The argument address.
// - A TypedData for the return value to populate in machine code (optional).
-class FfiCallInstr : public Definition {
+class FfiCallInstr : public VariadicDefinitionWithEmbeddedInputs {
public:
- FfiCallInstr(Zone* zone,
- intptr_t deopt_id,
+ FfiCallInstr(intptr_t deopt_id,
const compiler::ffi::CallMarshaller& marshaller,
bool is_leaf)
- : Definition(deopt_id),
- zone_(zone),
+ : VariadicDefinitionWithEmbeddedInputs(
+ marshaller.NumDefinitions() + 1 +
+ (marshaller.PassTypedData() ? 1 : 0),
+ deopt_id),
marshaller_(marshaller),
- inputs_(marshaller.NumDefinitions() + 1 +
- (marshaller.PassTypedData() ? 1 : 0)),
- is_leaf_(is_leaf) {
- inputs_.FillWith(
- nullptr, 0,
- marshaller.NumDefinitions() + 1 + (marshaller.PassTypedData() ? 1 : 0));
- }
+ is_leaf_(is_leaf) {}
DECLARE_INSTRUCTION(FfiCall)
@@ -5288,8 +5277,6 @@
return marshaller_.NumDefinitions() + 1;
}
- virtual intptr_t InputCount() const { return inputs_.length(); }
- virtual Value* InputAt(intptr_t i) const { return inputs_[i]; }
virtual bool MayThrow() const {
// By Dart_PropagateError.
return true;
@@ -5320,8 +5307,6 @@
PRINT_OPERANDS_TO_SUPPORT
private:
- virtual void RawSetInputAt(intptr_t i, Value* value) { inputs_[i] = value; }
-
LocationSummary* MakeLocationSummaryInternal(Zone* zone,
bool is_optimizing,
const RegList temps) const;
@@ -5338,21 +5323,16 @@
const Register temp0,
const Register temp1);
- Zone* const zone_;
const compiler::ffi::CallMarshaller& marshaller_;
-
- GrowableArray<Value*> inputs_;
-
bool is_leaf_;
DISALLOW_COPY_AND_ASSIGN(FfiCallInstr);
};
// Has the target address in a register passed as the last input in IL.
-class CCallInstr : public Definition {
+class CCallInstr : public VariadicDefinition {
public:
CCallInstr(
- Zone* zone,
const compiler::ffi::NativeCallingConvention& native_calling_convention,
InputsArray* inputs);
@@ -5366,8 +5346,6 @@
return native_calling_convention_.argument_locations().length();
}
- virtual intptr_t InputCount() const { return inputs_->length(); }
- virtual Value* InputAt(intptr_t i) const { return inputs_->At(i); }
virtual bool MayThrow() const { return false; }
virtual bool ComputeCanDeoptimize() const { return false; }
@@ -5386,13 +5364,7 @@
PRINT_OPERANDS_TO_SUPPORT
private:
- virtual void RawSetInputAt(intptr_t i, Value* value) {
- (*inputs_)[i] = value;
- }
-
- Zone* const zone_;
const compiler::ffi::NativeCallingConvention& native_calling_convention_;
- InputsArray* inputs_;
DISALLOW_COPY_AND_ASSIGN(CCallInstr);
};
@@ -6392,11 +6364,12 @@
Value* type_arguments = nullptr)
: AllocationInstr(source, deopt_id),
cls_(cls),
+ has_type_arguments_(type_arguments != nullptr),
type_arguments_(type_arguments) {
ASSERT(cls.IsZoneHandle());
ASSERT(!cls.IsNull());
- ASSERT((cls.NumTypeArguments() > 0) == (type_arguments != nullptr));
- if (type_arguments != nullptr) {
+ ASSERT((cls.NumTypeArguments() > 0) == has_type_arguments_);
+ if (has_type_arguments_) {
SetInputAt(kTypeArgumentsPos, type_arguments);
type_arguments_slot_ =
&Slot::GetTypeArgumentsSlotFor(Thread::Current(), cls);
@@ -6409,11 +6382,9 @@
const Class& cls() const { return cls_; }
Value* type_arguments() const { return type_arguments_; }
- virtual intptr_t InputCount() const {
- return (type_arguments_ != nullptr) ? 1 : 0;
- }
+ virtual intptr_t InputCount() const { return has_type_arguments_ ? 1 : 0; }
virtual Value* InputAt(intptr_t i) const {
- ASSERT(type_arguments_ != nullptr && i == kTypeArgumentsPos);
+ ASSERT(has_type_arguments_ && i == kTypeArgumentsPos);
return type_arguments_;
}
@@ -6435,12 +6406,12 @@
private:
virtual void RawSetInputAt(intptr_t i, Value* value) {
- ASSERT((type_arguments_ != nullptr) && (i == kTypeArgumentsPos));
- ASSERT(value != nullptr);
+ ASSERT(has_type_arguments_ && (i == kTypeArgumentsPos));
type_arguments_ = value;
}
const Class& cls_;
+ const bool has_type_arguments_;
Value* type_arguments_;
const Slot* type_arguments_slot_ = nullptr;
@@ -6529,26 +6500,22 @@
// This instruction captures the state of the object which had its allocation
// removed during the AllocationSinking pass.
// It does not produce any real code only deoptimization information.
-class MaterializeObjectInstr : public Definition {
+class MaterializeObjectInstr : public VariadicDefinition {
public:
MaterializeObjectInstr(AllocationInstr* allocation,
const Class& cls,
intptr_t num_elements,
const ZoneGrowableArray<const Slot*>& slots,
ZoneGrowableArray<Value*>* values)
- : allocation_(allocation),
+ : VariadicDefinition(values),
+ allocation_(allocation),
cls_(cls),
num_elements_(num_elements),
slots_(slots),
- values_(values),
locations_(nullptr),
visited_for_liveness_(false),
registers_remapped_(false) {
- ASSERT(slots_.length() == values_->length());
- for (intptr_t i = 0; i < InputCount(); i++) {
- InputAt(i)->set_instruction(this);
- InputAt(i)->set_use_index(i);
- }
+ ASSERT(slots_.length() == values->length());
}
AllocationInstr* allocation() const { return allocation_; }
@@ -6564,10 +6531,6 @@
DECLARE_INSTRUCTION(MaterializeObject)
- virtual intptr_t InputCount() const { return values_->length(); }
-
- virtual Value* InputAt(intptr_t i) const { return (*values_)[i]; }
-
// SelectRepresentations pass is run once more while MaterializeObject
// instructions are still in the graph. To avoid any redundant boxing
// operations inserted by that pass we should indicate that this
@@ -6594,15 +6557,10 @@
PRINT_OPERANDS_TO_SUPPORT
private:
- virtual void RawSetInputAt(intptr_t i, Value* value) {
- (*values_)[i] = value;
- }
-
AllocationInstr* allocation_;
const Class& cls_;
intptr_t num_elements_;
const ZoneGrowableArray<const Slot*>& slots_;
- ZoneGrowableArray<Value*>* values_;
Location* locations_;
bool visited_for_liveness_;
@@ -8692,7 +8650,7 @@
};
// TODO(sjindel): Replace with FFICallInstr.
-class InvokeMathCFunctionInstr : public PureDefinition {
+class InvokeMathCFunctionInstr : public VariadicDefinition {
public:
InvokeMathCFunctionInstr(ZoneGrowableArray<Value*>* inputs,
intptr_t deopt_id,
@@ -8726,9 +8684,8 @@
virtual intptr_t DeoptimizationTarget() const { return GetDeoptId(); }
- virtual intptr_t InputCount() const { return inputs_->length(); }
-
- virtual Value* InputAt(intptr_t i) const { return (*inputs_)[i]; }
+ virtual bool AllowsCSE() const { return true; }
+ virtual bool HasUnknownSideEffects() const { return false; }
virtual bool AttributesEqual(const Instruction& other) const {
auto const other_invoke = other.AsInvokeMathCFunction();
@@ -8744,11 +8701,6 @@
PRINT_OPERANDS_TO_SUPPORT
private:
- virtual void RawSetInputAt(intptr_t i, Value* value) {
- (*inputs_)[i] = value;
- }
-
- ZoneGrowableArray<Value*>* inputs_;
const MethodRecognizer::Kind recognized_kind_;
const TokenPosition token_pos_;
@@ -9853,7 +9805,7 @@
return count;
}
- const Function& function() const { return parsed_function_.function(); }
+ const Function& function() const { return function_; }
Environment* DeepCopy(Zone* zone) const { return DeepCopy(zone, Length()); }
@@ -9893,14 +9845,14 @@
Environment(intptr_t length,
intptr_t fixed_parameter_count,
intptr_t lazy_deopt_pruning_count,
- const ParsedFunction& parsed_function,
+ const Function& function,
Environment* outer)
: values_(length),
fixed_parameter_count_(fixed_parameter_count),
bitfield_(DeoptIdBits::encode(DeoptId::kNone) |
LazyDeoptToBeforeDeoptId::encode(false) |
LazyDeoptPruningBits::encode(lazy_deopt_pruning_count)),
- parsed_function_(parsed_function),
+ function_(function),
outer_(outer) {}
void SetDeoptId(intptr_t deopt_id) {
@@ -9919,7 +9871,7 @@
// Deoptimization id associated with this environment. Only set for
// outer environments.
uintptr_t bitfield_;
- const ParsedFunction& parsed_function_;
+ const Function& function_;
Environment* outer_;
DISALLOW_COPY_AND_ASSIGN(Environment);
diff --git a/runtime/vm/compiler/backend/il_test.cc b/runtime/vm/compiler/backend/il_test.cc
index d004834..8ae38a1 100644
--- a/runtime/vm/compiler/backend/il_test.cc
+++ b/runtime/vm/compiler/backend/il_test.cc
@@ -961,7 +961,7 @@
FlowGraph* flow_graph = pipeline->RunPasses({CompilerPass::kComputeSSA});
// Make an FfiCall based on ffi_trampoline that calls our native function.
- auto ffi_call = new FfiCallInstr(zone, DeoptId::kNone, marshaller, is_leaf);
+ auto ffi_call = new FfiCallInstr(DeoptId::kNone, marshaller, is_leaf);
RELEASE_ASSERT(ffi_call->InputCount() == 1);
// TargetAddress is the function pointer called.
const Representation address_repr =
diff --git a/runtime/vm/compiler/frontend/kernel_to_il.cc b/runtime/vm/compiler/frontend/kernel_to_il.cc
index 1e3707e..66de960 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.cc
+++ b/runtime/vm/compiler/frontend/kernel_to_il.cc
@@ -394,9 +394,8 @@
const compiler::ffi::CallMarshaller& marshaller) {
Fragment body;
- FfiCallInstr* const call =
- new (Z) FfiCallInstr(Z, GetNextDeoptId(), marshaller,
- parsed_function_->function().FfiIsLeaf());
+ FfiCallInstr* const call = new (Z) FfiCallInstr(
+ GetNextDeoptId(), marshaller, parsed_function_->function().FfiIsLeaf());
for (intptr_t i = call->InputCount() - 1; i >= 0; --i) {
call->SetInputAt(i, Pop());
@@ -419,8 +418,7 @@
for (intptr_t i = num_arguments - 1; i >= 0; --i) {
(*arguments)[i] = Pop();
}
- auto* const call =
- new (Z) CCallInstr(Z, native_calling_convention, arguments);
+ auto* const call = new (Z) CCallInstr(native_calling_convention, arguments);
Push(call);
body <<= call;
@@ -559,15 +557,15 @@
return instructions;
}
-Fragment FlowGraphBuilder::NativeCall(const String* name,
- const Function* function) {
+Fragment FlowGraphBuilder::NativeCall(const String& name,
+ const Function& function) {
InlineBailout("kernel::FlowGraphBuilder::NativeCall");
const intptr_t num_args =
- function->NumParameters() + (function->IsGeneric() ? 1 : 0);
+ function.NumParameters() + (function.IsGeneric() ? 1 : 0);
InputsArray* arguments = GetArguments(num_args);
NativeCallInstr* call = new (Z)
NativeCallInstr(name, function, FLAG_link_natives_lazily,
- InstructionSource(function->end_token_pos()), arguments);
+ InstructionSource(function.end_token_pos()), arguments);
Push(call);
return Fragment(call);
}
@@ -838,7 +836,7 @@
for (intptr_t i = 0; i < function.NumParameters(); ++i) {
body += LoadLocal(parsed_function_->RawParameterVariable(i));
}
- body += NativeCall(&name, &function);
+ body += NativeCall(name, function);
// We typecheck results of native calls for type safety.
body +=
Return(TokenPosition::kNoSource, /* omit_result_type_check = */ false);
diff --git a/runtime/vm/compiler/frontend/kernel_to_il.h b/runtime/vm/compiler/frontend/kernel_to_il.h
index b184503..045750e 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.h
+++ b/runtime/vm/compiler/frontend/kernel_to_il.h
@@ -197,7 +197,7 @@
Fragment StoreLateField(const Field& field,
LocalVariable* instance,
LocalVariable* setter_value);
- Fragment NativeCall(const String* name, const Function* function);
+ Fragment NativeCall(const String& name, const Function& function);
Fragment Return(
TokenPosition position,
bool omit_result_type_check = false,
diff --git a/tools/VERSION b/tools/VERSION
index 98ebbad..1145bf5 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 19
PATCH 0
-PRERELEASE 60
+PRERELEASE 61
PRERELEASE_PATCH 0
\ No newline at end of file