1 # 2 # ---------------------------------------------------------------------------------------------------- 3 # 4 # Copyright (c) 2007, 2020, Oracle and/or its affiliates. All rights reserved. 5 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 6 # 7 # This code is free software; you can redistribute it and/or modify it 8 # under the terms of the GNU General Public License version 2 only, as 9 # published by the Free Software Foundation. 10 # 11 # This code is distributed in the hope that it will be useful, but WITHOUT 12 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 # version 2 for more details (a copy is included in the LICENSE file that 15 # accompanied this code). 16 # 17 # You should have received a copy of the GNU General Public License version 18 # 2 along with this work; if not, write to the Free Software Foundation, 19 # Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 # 21 # Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 # or visit www.oracle.com if you need additional information or have any 23 # questions. 24 # 25 # ---------------------------------------------------------------------------------------------------- 26 27 import os, shutil, zipfile, re, time, sys, datetime, platform 28 from os.path import join, exists, dirname, isdir 29 from argparse import ArgumentParser, REMAINDER 30 import StringIO 31 import xml.dom.minidom 32 import subprocess 33 34 import mx 35 import mx_gate 36 import mx_unittest 37 38 from mx_gate import Task 39 from mx_unittest import unittest 40 41 _suite = mx.suite('jvmci') 42 43 JVMCI_VERSION = 9 44 45 _JVMCI_JDK_TAG = 'jvmci' 46 47 _minVersion = mx.VersionSpec('1.9') 48 49 # max version (first _unsupported_ version) 50 _untilVersion = None 51 52 _jvmciModes = { 53 'hosted' : ['-XX:+UnlockExperimentalVMOptions', '-XX:+EnableJVMCI'], 54 'jit' : ['-XX:+UnlockExperimentalVMOptions', '-XX:+EnableJVMCI', '-XX:+UseJVMCICompiler'], 55 'disabled' : [] 56 } 57 58 # TODO: can optimized be built without overriding release build? 59 _jdkDebugLevels = ['release', 'fastdebug', 'slowdebug'] 60 61 # TODO: add client once/if it can be built on 64-bit platforms 62 _jdkJvmVariants = ['server', 'client'] 63 64 """ 65 Translation table from mx_jvmci:8 --vmbuild values to mx_jvmci:9 --jdk-debug-level values. 66 """ 67 _legacyVmbuilds = { 68 'product' : 'release', 69 'debug' : 'slowdebug' 70 } 71 72 """ 73 Translates a mx_jvmci:8 --vmbuild value to a mx_jvmci:9 --jdk-debug-level value. 74 """ 75 def _translateLegacyDebugLevel(debugLevel): 76 return _legacyVmbuilds.get(debugLevel, debugLevel) 77 78 """ 79 Translation table from mx_jvmci:8 --vm values to mx_jvmci:9 (--jdk-jvm-variant, --jvmci-mode) tuples. 80 """ 81 _legacyVms = { 82 'jvmci' : ('server', 'jit') 83 } 84 85 """ 86 A VM configuration composed of a JDK debug level, JVM variant and a JVMCI mode. 87 This is also a context manager that can be used with the 'with' statement to set/change 88 a VM configuration within a dynamic scope. For example: 89 90 with ConfiguredJDK(debugLevel='fastdebug'): 91 dacapo(['pmd']) 92 """ 93 class VM: 94 def __init__(self, jvmVariant=None, debugLevel=None, jvmciMode=None): 95 self.update(jvmVariant, debugLevel, jvmciMode) 96 97 def update(self, jvmVariant=None, debugLevel=None, jvmciMode=None): 98 if jvmVariant in _legacyVms: 99 # Backwards compatibility for mx_jvmci:8 API 100 jvmVariant, newJvmciMode = _legacyVms[jvmVariant] 101 if jvmciMode is not None and jvmciMode != newJvmciMode: 102 mx.abort('JVM variant "' + jvmVariant + '" implies JVMCI mode "' + newJvmciMode + 103 '" which conflicts with explicitly specified JVMCI mode of "' + jvmciMode + '"') 104 jvmciMode = newJvmciMode 105 debugLevel = _translateLegacyDebugLevel(debugLevel) 106 assert jvmVariant is None or jvmVariant in _jdkJvmVariants, jvmVariant 107 assert debugLevel is None or debugLevel in _jdkDebugLevels, debugLevel 108 assert jvmciMode is None or jvmciMode in _jvmciModes, jvmciMode 109 self.jvmVariant = jvmVariant or _vm.jvmVariant 110 self.debugLevel = debugLevel or _vm.debugLevel 111 self.jvmciMode = jvmciMode or _vm.jvmciMode 112 113 def __enter__(self): 114 global _vm 115 self.previousVm = _vm 116 _vm = self 117 118 def __exit__(self, exc_type, exc_value, traceback): 119 global _vm 120 _vm = self.previousVm 121 122 _vm = VM(jvmVariant=_jdkJvmVariants[0], debugLevel=_jdkDebugLevels[0], jvmciMode='hosted') 123 124 def get_vm(): 125 """ 126 Gets the configured VM. 127 """ 128 return _vm 129 130 def relativeVmLibDirInJdk(): 131 mxos = mx.get_os() 132 if mxos == 'darwin': 133 return join('lib') 134 if mxos == 'windows' or mxos == 'cygwin': 135 return join('bin') 136 return join('lib', mx.get_arch()) 137 138 def isJVMCIEnabled(vm): 139 assert vm in _jdkJvmVariants 140 return True 141 142 def _makehelp(): 143 return subprocess.check_output([mx.gmake_cmd(), 'help'], cwd=_get_jdk_dir()) 144 145 def _runmake(args): 146 """run the JDK make process 147 148 To build hotspot and import it into the JDK: "mx make hotspot import-hotspot" 149 {0}""" 150 151 jdkBuildDir = _get_jdk_build_dir() 152 if not exists(jdkBuildDir): 153 # JDK10 must be bootstrapped with a JDK9 154 compliance = mx.JavaCompliance('9') 155 jdk9 = mx.get_jdk(compliance.exactMatch, versionDescription=compliance.value) 156 cmd = ['sh', 'configure', '--with-debug-level=' + _vm.debugLevel, '--with-native-debug-symbols=external', '--disable-precompiled-headers', '--enable-jvm-feature-graal', 157 '--with-jvm-variants=' + _vm.jvmVariant, '--disable-warnings-as-errors', '--with-boot-jdk=' + jdk9.home] 158 mx.run(cmd, cwd=_get_jdk_dir()) 159 cmd = [mx.gmake_cmd(), 'CONF=' + _vm.debugLevel] 160 if mx.get_opts().verbose: 161 cmd.append('LOG=debug') 162 cmd.extend(args) 163 if mx.get_opts().use_jdk_image and 'images' not in args: 164 cmd.append('images') 165 166 if not mx.get_opts().verbose: 167 mx.log('--------------- make execution ----------------------') 168 mx.log('Working directory: ' + _get_jdk_dir()) 169 mx.log('Command line: ' + ' '.join(cmd)) 170 mx.log('-----------------------------------------------------') 171 172 mx.run(cmd, cwd=_get_jdk_dir()) 173 174 def _runmultimake(args): 175 """run the JDK make process for one or more configurations""" 176 177 jvmVariantsDefault = ','.join(_jdkJvmVariants) 178 debugLevelsDefault = ','.join(_jdkDebugLevels) 179 180 parser = ArgumentParser(prog='mx multimake') 181 parser.add_argument('--jdk-jvm-variants', '--vms', help='a comma separated list of VMs to build (default: ' + jvmVariantsDefault + ')', metavar='<args>', default=jvmVariantsDefault) 182 parser.add_argument('--jdk-debug-levels', '--builds', help='a comma separated list of JDK debug levels (default: ' + debugLevelsDefault + ')', metavar='<args>', default=debugLevelsDefault) 183 parser.add_argument('-n', '--no-check', action='store_true', help='omit running "java -version" after each build') 184 select = parser.add_mutually_exclusive_group() 185 select.add_argument('-c', '--console', action='store_true', help='send build output to console instead of log files') 186 select.add_argument('-d', '--output-dir', help='directory for log files instead of current working directory', default=os.getcwd(), metavar='<dir>') 187 188 args = parser.parse_args(args) 189 jvmVariants = args.jdk_jvm_variants.split(',') 190 debugLevels = [_translateLegacyDebugLevel(dl) for dl in args.jdk_debug_levels.split(',')] 191 192 allStart = time.time() 193 for jvmVariant in jvmVariants: 194 for debugLevel in debugLevels: 195 if not args.console: 196 logFile = join(mx.ensure_dir_exists(args.output_dir), jvmVariant + '-' + debugLevel + '.log') 197 log = open(logFile, 'wb') 198 start = time.time() 199 mx.log('BEGIN: ' + jvmVariant + '-' + debugLevel + '\t(see: ' + logFile + ')') 200 verbose = ['-v'] if mx.get_opts().verbose else [] 201 # Run as subprocess so that output can be directed to a file 202 cmd = [sys.executable, '-u', mx.__file__] + verbose + ['--jdk-jvm-variant=' + jvmVariant, '--jdk-debug-level=' + debugLevel, 'make'] 203 mx.logv("executing command: " + str(cmd)) 204 subprocess.check_call(cmd, cwd=_suite.dir, stdout=log, stderr=subprocess.STDOUT) 205 duration = datetime.timedelta(seconds=time.time() - start) 206 mx.log('END: ' + jvmVariant + '-' + debugLevel + '\t[' + str(duration) + ']') 207 else: 208 with VM(jvmVariant=jvmVariant, debugLevel=debugLevel): 209 _runmake([]) 210 if not args.no_check: 211 with VM(jvmciMode='jit'): 212 run_vm(['-XX:-BootstrapJVMCI', '-version']) 213 allDuration = datetime.timedelta(seconds=time.time() - allStart) 214 mx.log('TOTAL TIME: ' + '[' + str(allDuration) + ']') 215 216 class HotSpotProject(mx.NativeProject): 217 """ 218 Defines a NativeProject representing the HotSpot binaries built via make. 219 """ 220 def __init__(self, suite, name, deps, workingSets, **args): 221 assert name == 'hotspot' 222 mx.NativeProject.__init__(self, suite, name, "", [], deps, workingSets, None, None, join(suite.mxDir, name)) 223 224 def eclipse_config_up_to_date(self, configZip): 225 # Assume that any change to this module might imply changes to the generated IDE files 226 if configZip.isOlderThan(__file__): 227 return False 228 for _, source in self._get_eclipse_settings_sources().iteritems(): 229 if configZip.isOlderThan(source): 230 return False 231 return True 232 233 def _get_eclipse_settings_sources(self): 234 """ 235 Gets a dictionary from the name of an Eclipse settings file to 236 the file providing its generated content. 237 """ 238 if not hasattr(self, '_eclipse_settings'): 239 esdict = {} 240 templateSettingsDir = join(self.dir, 'templates', 'eclipse', 'settings') 241 if exists(templateSettingsDir): 242 for name in os.listdir(templateSettingsDir): 243 source = join(templateSettingsDir, name) 244 esdict[name] = source 245 self._eclipse_settings = esdict 246 return self._eclipse_settings 247 248 def _eclipseinit(self, files=None, libFiles=None): 249 """ 250 Generates an Eclipse project for each HotSpot build configuration. 251 """ 252 253 roots = [ 254 'cpu', 255 'os', 256 'os_cpu', 257 'share' 258 ] 259 260 for jvmVariant in _jdkJvmVariants: 261 for debugLevel in _jdkDebugLevels: 262 name = jvmVariant + '-' + debugLevel 263 eclProjectDir = join(self.dir, 'eclipse', name) 264 mx.ensure_dir_exists(eclProjectDir) 265 266 out = mx.XMLDoc() 267 out.open('projectDescription') 268 out.element('name', data='hotspot:' + name) 269 out.element('comment', data='') 270 out.element('projects', data='') 271 out.open('buildSpec') 272 out.open('buildCommand') 273 out.element('name', data='org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder') 274 out.element('triggers', data='full,incremental') 275 out.element('arguments', data='') 276 out.close('buildCommand') 277 278 out.close('buildSpec') 279 out.open('natures') 280 out.element('nature', data='org.eclipse.cdt.core.cnature') 281 out.element('nature', data='org.eclipse.cdt.core.ccnature') 282 out.element('nature', data='org.eclipse.cdt.managedbuilder.core.managedBuildNature') 283 out.element('nature', data='org.eclipse.cdt.managedbuilder.core.ScannerConfigNature') 284 out.close('natures') 285 286 if roots: 287 out.open('linkedResources') 288 for r in roots: 289 f = join(_suite.dir, r) 290 out.open('link') 291 out.element('name', data=r) 292 out.element('type', data='2' if isdir(f) else '1') 293 out.element('locationURI', data=mx.get_eclipse_project_rel_locationURI(f, eclProjectDir)) 294 out.close('link') 295 296 out.open('link') 297 out.element('name', data='gensrc') 298 out.element('type', data='2') 299 generated = join(_get_hotspot_build_dir(jvmVariant, debugLevel), 'gensrc') 300 out.element('locationURI', data=mx.get_eclipse_project_rel_locationURI(generated, eclProjectDir)) 301 out.close('link') 302 303 out.close('linkedResources') 304 out.close('projectDescription') 305 projectFile = join(eclProjectDir, '.project') 306 mx.update_file(projectFile, out.xml(indent='\t', newl='\n')) 307 if files: 308 files.append(projectFile) 309 310 cprojectTemplate = join(self.dir, 'templates', 'eclipse', 'cproject') 311 cprojectFile = join(eclProjectDir, '.cproject') 312 with open(cprojectTemplate) as f: 313 content = f.read() 314 mx.update_file(cprojectFile, content) 315 if files: 316 files.append(cprojectFile) 317 318 settingsDir = join(eclProjectDir, ".settings") 319 mx.ensure_dir_exists(settingsDir) 320 for name, source in self._get_eclipse_settings_sources().iteritems(): 321 out = StringIO.StringIO() 322 print >> out, '# GENERATED -- DO NOT EDIT' 323 print >> out, '# Source:', source 324 with open(source) as f: 325 print >> out, f.read() 326 content = out.getvalue() 327 mx.update_file(join(settingsDir, name), content) 328 if files: 329 files.append(join(settingsDir, name)) 330 331 def getBuildTask(self, args): 332 return JDKBuildTask(self, args, _vm.debugLevel, _vm.jvmVariant) 333 334 335 class JDKBuildTask(mx.NativeBuildTask): 336 def __init__(self, project, args, debugLevel, jvmVariant): 337 mx.NativeBuildTask.__init__(self, args, project) 338 self.jvmVariant = jvmVariant 339 self.debugLevel = debugLevel 340 341 def __str__(self): 342 return 'Building JDK[{}, {}]'.format(self.debugLevel, self.jvmVariant) 343 344 def build(self): 345 if mx.get_opts().use_jdk_image: 346 _runmake(['images']) 347 else: 348 _runmake([]) 349 self._newestOutput = None 350 351 def clean(self, forBuild=False): 352 if forBuild: # Let make handle incremental builds 353 return 354 if exists(_get_jdk_build_dir(self.debugLevel)): 355 _runmake(['clean']) 356 self._newestOutput = None 357 358 # Backwards compatibility for mx_jvmci:8 API 359 def buildvms(args): 360 _runmultimake(args) 361 362 def run_vm(args, vm=None, nonZeroIsFatal=True, out=None, err=None, cwd=None, timeout=None, debugLevel=None, vmbuild=None): 363 """run a Java program by executing the java executable in a JVMCI JDK""" 364 jdkTag = mx.get_jdk_option().tag 365 if jdkTag and jdkTag != _JVMCI_JDK_TAG: 366 mx.abort('The "--jdk" option must have the tag "' + _JVMCI_JDK_TAG + '" when running a command requiring a JVMCI VM') 367 jdk = get_jvmci_jdk(debugLevel=debugLevel or _translateLegacyDebugLevel(vmbuild)) 368 return jdk.run_java(args, nonZeroIsFatal=nonZeroIsFatal, out=out, err=err, cwd=cwd, timeout=timeout) 369 370 def _unittest_vm_launcher(vmArgs, mainClass, mainClassArgs): 371 run_vm(vmArgs + [mainClass] + mainClassArgs) 372 373 mx_unittest.set_vm_launcher('JVMCI VM launcher', _unittest_vm_launcher) 374 375 def _jvmci_gate_runner(args, tasks): 376 # Build release server VM now so we can run the unit tests 377 with Task('BuildHotSpotJVMCIHosted: release', tasks) as t: 378 if t: _runmultimake(['--jdk-jvm-variants', 'server', '--jdk-debug-levels', 'release']) 379 380 # Run unit tests in hosted mode 381 with VM(jvmVariant='server', debugLevel='release', jvmciMode='hosted'): 382 with Task('JVMCI UnitTests: hosted-release', tasks) as t: 383 if t: unittest(['--suite', 'jvmci', '--enable-timing', '--verbose', '--fail-fast']) 384 385 # Build the other VM flavors 386 with Task('BuildHotSpotJVMCIOthers: fastdebug', tasks) as t: 387 if t: _runmultimake(['--jdk-jvm-variants', 'server', '--jdk-debug-levels', 'fastdebug']) 388 389 with Task('CleanAndBuildIdealGraphVisualizer', tasks, disableJacoco=True) as t: 390 if t: 391 buildxml = mx._cygpathU2W(join(_suite.dir, 'src', 'share', 'tools', 'IdealGraphVisualizer', 'build.xml')) 392 mx.run(['ant', '-f', buildxml, '-q', 'clean', 'build'], env=_igvBuildEnv()) 393 394 mx_gate.add_gate_runner(_suite, _jvmci_gate_runner) 395 mx_gate.add_gate_argument('-g', '--only-build-jvmci', action='store_false', dest='buildNonJVMCI', help='only build the JVMCI VM') 396 397 def _igvJdk(): 398 v8u20 = mx.VersionSpec("1.8.0_20") 399 v8u40 = mx.VersionSpec("1.8.0_40") 400 v8 = mx.VersionSpec("1.8") 401 def _igvJdkVersionCheck(version): 402 return version >= v8 and (version < v8u20 or version >= v8u40) 403 return mx.get_jdk(_igvJdkVersionCheck, versionDescription='>= 1.8 and < 1.8.0u20 or >= 1.8.0u40', purpose="building & running IGV").home 404 405 def _igvBuildEnv(): 406 # When the http_proxy environment variable is set, convert it to the proxy settings that ant needs 407 env = dict(os.environ) 408 proxy = os.environ.get('http_proxy') 409 if not (proxy is None) and len(proxy) > 0: 410 if '://' in proxy: 411 # Remove the http:// prefix (or any other protocol prefix) 412 proxy = proxy.split('://', 1)[1] 413 # Separate proxy server name and port number 414 proxyName, proxyPort = proxy.split(':', 1) 415 proxyEnv = '-DproxyHost="' + proxyName + '" -DproxyPort=' + proxyPort 416 env['ANT_OPTS'] = proxyEnv 417 418 env['JAVA_HOME'] = _igvJdk() 419 return env 420 421 def igv(args): 422 """run the Ideal Graph Visualizer""" 423 logFile = '.ideal_graph_visualizer.log' 424 with open(join(_suite.dir, logFile), 'w') as fp: 425 mx.logv('[Ideal Graph Visualizer log is in ' + fp.name + ']') 426 nbplatform = join(_suite.dir, 'src', 'share', 'tools', 'IdealGraphVisualizer', 'nbplatform') 427 428 # Remove NetBeans platform if it is earlier than the current supported version 429 if exists(nbplatform): 430 updateTrackingFile = join(nbplatform, 'platform', 'update_tracking', 'org-netbeans-core.xml') 431 if not exists(updateTrackingFile): 432 mx.log('Could not find \'' + updateTrackingFile + '\', removing NetBeans platform') 433 shutil.rmtree(nbplatform) 434 else: 435 dom = xml.dom.minidom.parse(updateTrackingFile) 436 currentVersion = mx.VersionSpec(dom.getElementsByTagName('module_version')[0].getAttribute('specification_version')) 437 supportedVersion = mx.VersionSpec('3.43.1') 438 if currentVersion < supportedVersion: 439 mx.log('Replacing NetBeans platform version ' + str(currentVersion) + ' with version ' + str(supportedVersion)) 440 shutil.rmtree(nbplatform) 441 elif supportedVersion < currentVersion: 442 mx.log('Supported NetBeans version in igv command should be updated to ' + str(currentVersion)) 443 444 if not exists(nbplatform): 445 mx.logv('[This execution may take a while as the NetBeans platform needs to be downloaded]') 446 447 env = _igvBuildEnv() 448 # make the jar for Batik 1.7 available. 449 env['IGV_BATIK_JAR'] = mx.library('BATIK').get_path(True) 450 if mx.run(['ant', '-f', mx._cygpathU2W(join(_suite.dir, 'src', 'share', 'tools', 'IdealGraphVisualizer', 'build.xml')), '-l', mx._cygpathU2W(fp.name), 'run'], env=env, nonZeroIsFatal=False): 451 mx.abort("IGV ant build & launch failed. Check '" + logFile + "'. You can also try to delete 'src/share/tools/IdealGraphVisualizer/nbplatform'.") 452 453 def c1visualizer(args): 454 """run the Cl Compiler Visualizer""" 455 libpath = join(_suite.dir, 'lib') 456 if mx.get_os() == 'windows': 457 executable = join(libpath, 'c1visualizer', 'bin', 'c1visualizer.exe') 458 else: 459 executable = join(libpath, 'c1visualizer', 'bin', 'c1visualizer') 460 461 # Check whether the current C1Visualizer installation is the up-to-date 462 if exists(executable) and not exists(mx.library('C1VISUALIZER_DIST').get_path(resolve=False)): 463 mx.log('Updating C1Visualizer') 464 shutil.rmtree(join(libpath, 'c1visualizer')) 465 466 archive = mx.library('C1VISUALIZER_DIST').get_path(resolve=True) 467 468 if not exists(executable): 469 zf = zipfile.ZipFile(archive, 'r') 470 zf.extractall(libpath) 471 472 if not exists(executable): 473 mx.abort('C1Visualizer binary does not exist: ' + executable) 474 475 if mx.get_os() != 'windows': 476 # Make sure that execution is allowed. The zip file does not always specfiy that correctly 477 os.chmod(executable, 0777) 478 479 mx.run([executable]) 480 481 def hsdis(args, copyToDir=None): 482 """download the hsdis library 483 484 This is needed to support HotSpot's assembly dumping features. 485 By default it downloads the Intel syntax version, use the 'att' argument to install AT&T syntax.""" 486 flavor = 'intel' 487 if 'att' in args: 488 flavor = 'att' 489 lib = mx.add_lib_suffix('hsdis-' + mx.get_arch()) 490 path = join(_suite.dir, 'lib', lib) 491 492 sha1s = { 493 'att/hsdis-amd64.dll' : 'bcbd535a9568b5075ab41e96205e26a2bac64f72', 494 'att/hsdis-amd64.so' : '58919ba085d4ef7a513f25bae75e7e54ee73c049', 495 'intel/hsdis-amd64.dll' : '6a388372cdd5fe905c1a26ced614334e405d1f30', 496 'intel/hsdis-amd64.so' : '844ed9ffed64fe9599638f29a8450c50140e3192', 497 'intel/hsdis-amd64.dylib' : 'fdb13ef0d7d23d93dacaae9c98837bea0d4fc5a2', 498 } 499 500 flavoredLib = flavor + "/" + lib 501 if flavoredLib not in sha1s: 502 mx.logv("hsdis not supported on this plattform or architecture") 503 return 504 505 if not exists(path): 506 sha1 = sha1s[flavoredLib] 507 sha1path = path + '.sha1' 508 mx.download_file_with_sha1('hsdis', path, ['https://lafo.ssw.uni-linz.ac.at/pub/hsdis/' + flavoredLib], sha1, sha1path, True, True, sources=False) 509 if copyToDir is not None and exists(copyToDir): 510 shutil.copy(path, copyToDir) 511 512 def hcfdis(args): 513 """disassemble HexCodeFiles embedded in text files 514 515 Run a tool over the input files to convert all embedded HexCodeFiles 516 to a disassembled format.""" 517 518 parser = ArgumentParser(prog='mx hcfdis') 519 parser.add_argument('-m', '--map', help='address to symbol map applied to disassembler output') 520 parser.add_argument('files', nargs=REMAINDER, metavar='files...') 521 522 args = parser.parse_args(args) 523 524 path = mx.library('HCFDIS').get_path(resolve=True) 525 mx.run_java(['-cp', path, 'com.oracle.max.hcfdis.HexCodeFileDis'] + args.files) 526 527 if args.map is not None: 528 addressRE = re.compile(r'0[xX]([A-Fa-f0-9]+)') 529 with open(args.map) as fp: 530 lines = fp.read().splitlines() 531 symbols = dict() 532 for l in lines: 533 addressAndSymbol = l.split(' ', 1) 534 if len(addressAndSymbol) == 2: 535 address, symbol = addressAndSymbol 536 if address.startswith('0x'): 537 address = long(address, 16) 538 symbols[address] = symbol 539 for f in args.files: 540 with open(f) as fp: 541 lines = fp.read().splitlines() 542 updated = False 543 for i in range(0, len(lines)): 544 l = lines[i] 545 for m in addressRE.finditer(l): 546 sval = m.group(0) 547 val = long(sval, 16) 548 sym = symbols.get(val) 549 if sym: 550 l = l.replace(sval, sym) 551 updated = True 552 lines[i] = l 553 if updated: 554 mx.log('updating ' + f) 555 with open('new_' + f, "w") as fp: 556 for l in lines: 557 print >> fp, l 558 559 def jol(args): 560 """Java Object Layout""" 561 joljar = mx.library('JOL_INTERNALS').get_path(resolve=True) 562 candidates = mx.findclass(args, logToConsole=False, matcher=lambda s, classname: s == classname or classname.endswith('.' + s) or classname.endswith('$' + s)) 563 564 if len(candidates) > 0: 565 candidates = mx.select_items(sorted(candidates)) 566 else: 567 # mx.findclass can be mistaken, don't give up yet 568 candidates = args 569 570 run_vm(['-javaagent:' + joljar, '-cp', os.pathsep.join([mx.classpath(), joljar]), "org.openjdk.jol.MainObjectInternals"] + candidates) 571 572 def _get_openjdk_os(): 573 # See: common/autoconf/platform.m4 574 os = mx.get_os() 575 if 'darwin' in os: 576 os = 'macosx' 577 elif 'linux' in os: 578 os = 'linux' 579 elif 'cygwin' in os or 'mingw' in os: 580 os = 'windows' 581 return os 582 583 def _get_openjdk_cpu(): 584 cpu = mx.get_arch() 585 if cpu == 'amd64': 586 cpu = 'x86_64' 587 return cpu 588 589 def _get_openjdk_os_cpu(): 590 return _get_openjdk_os() + '-' + _get_openjdk_cpu() 591 592 def _get_jdk_dir(): 593 suiteParentDir = dirname(_suite.dir) 594 # suitParentDir is now something like: /some_prefix/jdk10-hs/open/src 595 pathComponents = suiteParentDir.split(os.sep) 596 for i in range(0, len(pathComponents)): 597 if pathComponents[i] in ["open", "src"]: 598 del pathComponents[i:] 599 break 600 return os.path.join(os.sep, *pathComponents) 601 602 def _get_jdk_build_dir(debugLevel=None): 603 """ 604 Gets the directory into which the JDK is built. This directory contains 605 the exploded JDK under jdk/ and the JDK image under images/jdk/. 606 """ 607 if debugLevel is None: 608 debugLevel = _vm.debugLevel 609 name = '{}-{}-{}-{}'.format(_get_openjdk_os_cpu(), 'normal', _vm.jvmVariant, debugLevel) 610 return join(_get_jdk_dir(), 'build', name) 611 612 _jvmci_bootclasspath_prepends = [] 613 614 def _get_hotspot_build_dir(jvmVariant=None, debugLevel=None): 615 """ 616 Gets the directory in which a particular HotSpot configuration is built 617 (e.g., <JDK_REPO_ROOT>/build/macosx-x86_64-normal-server-release/hotspot/variant-<variant>) 618 """ 619 if jvmVariant is None: 620 jvmVariant = _vm.jvmVariant 621 622 name = 'variant-{}'.format(jvmVariant) 623 return join(_get_jdk_build_dir(debugLevel=debugLevel), 'hotspot', name) 624 625 class JVMCI9JDKConfig(mx.JDKConfig): 626 def __init__(self, debugLevel): 627 self.debugLevel = debugLevel 628 jdkBuildDir = _get_jdk_build_dir(debugLevel) 629 jdkDir = join(jdkBuildDir, 'images', 'jdk') if mx.get_opts().use_jdk_image else join(jdkBuildDir, 'jdk') 630 mx.JDKConfig.__init__(self, jdkDir, tag=_JVMCI_JDK_TAG) 631 632 def parseVmArgs(self, args, addDefaultArgs=True): 633 args = mx.expand_project_in_args(args, insitu=False) 634 jacocoArgs = mx_gate.get_jacoco_agent_args() 635 if jacocoArgs: 636 args = jacocoArgs + args 637 638 args = ['-Xbootclasspath/p:' + dep.classpath_repr() for dep in _jvmci_bootclasspath_prepends] + args 639 640 # Remove JVMCI jars from class path. They are only necessary when 641 # compiling with a javac from JDK8 or earlier. 642 cpIndex, cp = mx.find_classpath_arg(args) 643 if cp: 644 excluded = frozenset([dist.path for dist in _suite.dists]) 645 cp = os.pathsep.join([e for e in cp.split(os.pathsep) if e not in excluded]) 646 args[cpIndex] = cp 647 648 if '-version' in args: 649 ignoredArgs = args[args.index('-version') + 1:] 650 if len(ignoredArgs) > 0: 651 mx.log("Warning: The following options will be ignored by the vm because they come after the '-version' argument: " + ' '.join(ignoredArgs)) 652 return self.processArgs(args, addDefaultArgs=addDefaultArgs) 653 654 # Overrides JDKConfig 655 def run_java(self, args, vm=None, nonZeroIsFatal=True, out=None, err=None, cwd=None, timeout=None, env=None, addDefaultArgs=True): 656 if vm is None: 657 vm = 'server' 658 659 args = self.parseVmArgs(args, addDefaultArgs=addDefaultArgs) 660 661 jvmciModeArgs = _jvmciModes[_vm.jvmciMode] 662 cmd = [self.java] + ['-' + vm] + jvmciModeArgs + args 663 return mx.run(cmd, nonZeroIsFatal=nonZeroIsFatal, out=out, err=err, cwd=cwd) 664 665 """ 666 The dict of JVMCI JDKs indexed by debug-level names. 667 """ 668 _jvmci_jdks = {} 669 670 def get_jvmci_jdk(debugLevel=None): 671 """ 672 Gets the JVMCI JDK corresponding to 'debugLevel'. 673 """ 674 if not debugLevel: 675 debugLevel = _vm.debugLevel 676 jdk = _jvmci_jdks.get(debugLevel) 677 if jdk is None: 678 try: 679 jdk = JVMCI9JDKConfig(debugLevel) 680 except mx.JDKConfigException as e: 681 jdkBuildDir = _get_jdk_build_dir(debugLevel) 682 msg = 'Error with the JDK built into {}:\n{}\nTry (re)building it with: mx --jdk-debug-level={} make' 683 if mx.get_opts().use_jdk_image: 684 msg += ' images' 685 mx.abort(msg.format(jdkBuildDir, e.message, debugLevel)) 686 _jvmci_jdks[debugLevel] = jdk 687 return jdk 688 689 class JVMCI9JDKFactory(mx.JDKFactory): 690 def getJDKConfig(self): 691 jdk = get_jvmci_jdk(_vm.debugLevel) 692 return jdk 693 694 def description(self): 695 return "JVMCI JDK" 696 697 mx.update_commands(_suite, { 698 'make': [_runmake, '[args...]', _makehelp], 699 'multimake': [_runmultimake, '[options]'], 700 'c1visualizer' : [c1visualizer, ''], 701 'hsdis': [hsdis, '[att]'], 702 'hcfdis': [hcfdis, ''], 703 'igv' : [igv, ''], 704 'jol' : [jol, ''], 705 'vm': [run_vm, '[-options] class [args...]'], 706 }) 707 708 mx.add_argument('-M', '--jvmci-mode', action='store', choices=sorted(_jvmciModes.viewkeys()), help='the JVM variant type to build/run (default: ' + _vm.jvmciMode + ')') 709 mx.add_argument('--jdk-jvm-variant', '--vm', action='store', choices=_jdkJvmVariants + sorted(_legacyVms.viewkeys()), help='the JVM variant type to build/run (default: ' + _vm.jvmVariant + ')') 710 mx.add_argument('--jdk-debug-level', '--vmbuild', action='store', choices=_jdkDebugLevels + sorted(_legacyVmbuilds.viewkeys()), help='the JDK debug level to build/run (default: ' + _vm.debugLevel + ')') 711 mx.add_argument('-I', '--use-jdk-image', action='store_true', help='build/run JDK image instead of exploded JDK') 712 713 mx.addJDKFactory(_JVMCI_JDK_TAG, mx.JavaCompliance('9'), JVMCI9JDKFactory()) 714 715 def mx_post_parse_cmd_line(opts): 716 mx.set_java_command_default_jdk_tag(_JVMCI_JDK_TAG) 717 718 jdkTag = mx.get_jdk_option().tag 719 720 jvmVariant = None 721 debugLevel = None 722 jvmciMode = None 723 724 if opts.jdk_jvm_variant is not None: 725 jvmVariant = opts.jdk_jvm_variant 726 if jdkTag and jdkTag != _JVMCI_JDK_TAG: 727 mx.warn('Ignoring "--jdk-jvm-variant" option as "--jdk" tag is not "' + _JVMCI_JDK_TAG + '"') 728 729 if opts.jdk_debug_level is not None: 730 debugLevel = _translateLegacyDebugLevel(opts.jdk_debug_level) 731 if jdkTag and jdkTag != _JVMCI_JDK_TAG: 732 mx.warn('Ignoring "--jdk-debug-level" option as "--jdk" tag is not "' + _JVMCI_JDK_TAG + '"') 733 734 if opts.jvmci_mode is not None: 735 jvmciMode = opts.jvmci_mode 736 if jdkTag and jdkTag != _JVMCI_JDK_TAG: 737 mx.warn('Ignoring "--jvmci-mode" option as "--jdk" tag is not "' + _JVMCI_JDK_TAG + '"') 738 739 _vm.update(jvmVariant, debugLevel, jvmciMode)