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