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 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', '--with-jvm-features=graal', 157 '--with-jvm-variants=' + _vm.jvmVariant, '--disable-warnings-as-errors', '--with-boot-jdk=' + jdk9.home, '--with-jvm-features=graal'] 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 and platform.processor() != 'sparc': 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 if mx.get_arch() == "sparcv9": 490 flavor = "sparcv9" 491 lib = mx.add_lib_suffix('hsdis-' + mx.get_arch()) 492 path = join(_suite.dir, 'lib', lib) 493 494 sha1s = { 495 'att/hsdis-amd64.dll' : 'bcbd535a9568b5075ab41e96205e26a2bac64f72', 496 'att/hsdis-amd64.so' : '58919ba085d4ef7a513f25bae75e7e54ee73c049', 497 'intel/hsdis-amd64.dll' : '6a388372cdd5fe905c1a26ced614334e405d1f30', 498 'intel/hsdis-amd64.so' : '844ed9ffed64fe9599638f29a8450c50140e3192', 499 'intel/hsdis-amd64.dylib' : 'fdb13ef0d7d23d93dacaae9c98837bea0d4fc5a2', 500 'sparcv9/hsdis-sparcv9.so': '970640a9af0bd63641f9063c11275b371a59ee60', 501 } 502 503 flavoredLib = flavor + "/" + lib 504 if flavoredLib not in sha1s: 505 mx.logv("hsdis not supported on this plattform or architecture") 506 return 507 508 if not exists(path): 509 sha1 = sha1s[flavoredLib] 510 sha1path = path + '.sha1' 511 mx.download_file_with_sha1('hsdis', path, ['https://lafo.ssw.uni-linz.ac.at/pub/hsdis/' + flavoredLib], sha1, sha1path, True, True, sources=False) 512 if copyToDir is not None and exists(copyToDir): 513 shutil.copy(path, copyToDir) 514 515 def hcfdis(args): 516 """disassemble HexCodeFiles embedded in text files 517 518 Run a tool over the input files to convert all embedded HexCodeFiles 519 to a disassembled format.""" 520 521 parser = ArgumentParser(prog='mx hcfdis') 522 parser.add_argument('-m', '--map', help='address to symbol map applied to disassembler output') 523 parser.add_argument('files', nargs=REMAINDER, metavar='files...') 524 525 args = parser.parse_args(args) 526 527 path = mx.library('HCFDIS').get_path(resolve=True) 528 mx.run_java(['-cp', path, 'com.oracle.max.hcfdis.HexCodeFileDis'] + args.files) 529 530 if args.map is not None: 531 addressRE = re.compile(r'0[xX]([A-Fa-f0-9]+)') 532 with open(args.map) as fp: 533 lines = fp.read().splitlines() 534 symbols = dict() 535 for l in lines: 536 addressAndSymbol = l.split(' ', 1) 537 if len(addressAndSymbol) == 2: 538 address, symbol = addressAndSymbol 539 if address.startswith('0x'): 540 address = long(address, 16) 541 symbols[address] = symbol 542 for f in args.files: 543 with open(f) as fp: 544 lines = fp.read().splitlines() 545 updated = False 546 for i in range(0, len(lines)): 547 l = lines[i] 548 for m in addressRE.finditer(l): 549 sval = m.group(0) 550 val = long(sval, 16) 551 sym = symbols.get(val) 552 if sym: 553 l = l.replace(sval, sym) 554 updated = True 555 lines[i] = l 556 if updated: 557 mx.log('updating ' + f) 558 with open('new_' + f, "w") as fp: 559 for l in lines: 560 print >> fp, l 561 562 def jol(args): 563 """Java Object Layout""" 564 joljar = mx.library('JOL_INTERNALS').get_path(resolve=True) 565 candidates = mx.findclass(args, logToConsole=False, matcher=lambda s, classname: s == classname or classname.endswith('.' + s) or classname.endswith('$' + s)) 566 567 if len(candidates) > 0: 568 candidates = mx.select_items(sorted(candidates)) 569 else: 570 # mx.findclass can be mistaken, don't give up yet 571 candidates = args 572 573 run_vm(['-javaagent:' + joljar, '-cp', os.pathsep.join([mx.classpath(), joljar]), "org.openjdk.jol.MainObjectInternals"] + candidates) 574 575 def _get_openjdk_os(): 576 # See: common/autoconf/platform.m4 577 os = mx.get_os() 578 if 'darwin' in os: 579 os = 'macosx' 580 elif 'linux' in os: 581 os = 'linux' 582 elif 'solaris' in os: 583 os = 'solaris' 584 elif 'cygwin' in os or 'mingw' in os: 585 os = 'windows' 586 return os 587 588 def _get_openjdk_cpu(): 589 cpu = mx.get_arch() 590 if cpu == 'amd64': 591 cpu = 'x86_64' 592 elif cpu == 'sparcv9': 593 cpu = 'sparcv9' 594 return cpu 595 596 def _get_openjdk_os_cpu(): 597 return _get_openjdk_os() + '-' + _get_openjdk_cpu() 598 599 def _get_jdk_dir(): 600 suiteParentDir = dirname(_suite.dir) 601 # suitParentDir is now something like: /some_prefix/jdk10-hs/open/src 602 pathComponents = suiteParentDir.split(os.sep) 603 for i in range(0, len(pathComponents)): 604 if pathComponents[i] in ["open", "src"]: 605 del pathComponents[i:] 606 break 607 return os.path.join(os.sep, *pathComponents) 608 609 def _get_jdk_build_dir(debugLevel=None): 610 """ 611 Gets the directory into which the JDK is built. This directory contains 612 the exploded JDK under jdk/ and the JDK image under images/jdk/. 613 """ 614 if debugLevel is None: 615 debugLevel = _vm.debugLevel 616 name = '{}-{}-{}-{}'.format(_get_openjdk_os_cpu(), 'normal', _vm.jvmVariant, debugLevel) 617 return join(_get_jdk_dir(), 'build', name) 618 619 _jvmci_bootclasspath_prepends = [] 620 621 def _get_hotspot_build_dir(jvmVariant=None, debugLevel=None): 622 """ 623 Gets the directory in which a particular HotSpot configuration is built 624 (e.g., <JDK_REPO_ROOT>/build/macosx-x86_64-normal-server-release/hotspot/variant-<variant>) 625 """ 626 if jvmVariant is None: 627 jvmVariant = _vm.jvmVariant 628 629 name = 'variant-{}'.format(jvmVariant) 630 return join(_get_jdk_build_dir(debugLevel=debugLevel), 'hotspot', name) 631 632 class JVMCI9JDKConfig(mx.JDKConfig): 633 def __init__(self, debugLevel): 634 self.debugLevel = debugLevel 635 jdkBuildDir = _get_jdk_build_dir(debugLevel) 636 jdkDir = join(jdkBuildDir, 'images', 'jdk') if mx.get_opts().use_jdk_image else join(jdkBuildDir, 'jdk') 637 mx.JDKConfig.__init__(self, jdkDir, tag=_JVMCI_JDK_TAG) 638 639 def parseVmArgs(self, args, addDefaultArgs=True): 640 args = mx.expand_project_in_args(args, insitu=False) 641 jacocoArgs = mx_gate.get_jacoco_agent_args() 642 if jacocoArgs: 643 args = jacocoArgs + args 644 645 args = ['-Xbootclasspath/p:' + dep.classpath_repr() for dep in _jvmci_bootclasspath_prepends] + args 646 647 # Remove JVMCI jars from class path. They are only necessary when 648 # compiling with a javac from JDK8 or earlier. 649 cpIndex, cp = mx.find_classpath_arg(args) 650 if cp: 651 excluded = frozenset([dist.path for dist in _suite.dists]) 652 cp = os.pathsep.join([e for e in cp.split(os.pathsep) if e not in excluded]) 653 args[cpIndex] = cp 654 655 if '-version' in args: 656 ignoredArgs = args[args.index('-version') + 1:] 657 if len(ignoredArgs) > 0: 658 mx.log("Warning: The following options will be ignored by the vm because they come after the '-version' argument: " + ' '.join(ignoredArgs)) 659 return self.processArgs(args, addDefaultArgs=addDefaultArgs) 660 661 # Overrides JDKConfig 662 def run_java(self, args, vm=None, nonZeroIsFatal=True, out=None, err=None, cwd=None, timeout=None, env=None, addDefaultArgs=True): 663 if vm is None: 664 vm = 'server' 665 666 args = self.parseVmArgs(args, addDefaultArgs=addDefaultArgs) 667 668 jvmciModeArgs = _jvmciModes[_vm.jvmciMode] 669 cmd = [self.java] + ['-' + vm] + jvmciModeArgs + args 670 return mx.run(cmd, nonZeroIsFatal=nonZeroIsFatal, out=out, err=err, cwd=cwd) 671 672 """ 673 The dict of JVMCI JDKs indexed by debug-level names. 674 """ 675 _jvmci_jdks = {} 676 677 def get_jvmci_jdk(debugLevel=None): 678 """ 679 Gets the JVMCI JDK corresponding to 'debugLevel'. 680 """ 681 if not debugLevel: 682 debugLevel = _vm.debugLevel 683 jdk = _jvmci_jdks.get(debugLevel) 684 if jdk is None: 685 try: 686 jdk = JVMCI9JDKConfig(debugLevel) 687 except mx.JDKConfigException as e: 688 jdkBuildDir = _get_jdk_build_dir(debugLevel) 689 msg = 'Error with the JDK built into {}:\n{}\nTry (re)building it with: mx --jdk-debug-level={} make' 690 if mx.get_opts().use_jdk_image: 691 msg += ' images' 692 mx.abort(msg.format(jdkBuildDir, e.message, debugLevel)) 693 _jvmci_jdks[debugLevel] = jdk 694 return jdk 695 696 class JVMCI9JDKFactory(mx.JDKFactory): 697 def getJDKConfig(self): 698 jdk = get_jvmci_jdk(_vm.debugLevel) 699 return jdk 700 701 def description(self): 702 return "JVMCI JDK" 703 704 mx.update_commands(_suite, { 705 'make': [_runmake, '[args...]', _makehelp], 706 'multimake': [_runmultimake, '[options]'], 707 'c1visualizer' : [c1visualizer, ''], 708 'hsdis': [hsdis, '[att]'], 709 'hcfdis': [hcfdis, ''], 710 'igv' : [igv, ''], 711 'jol' : [jol, ''], 712 'vm': [run_vm, '[-options] class [args...]'], 713 }) 714 715 mx.add_argument('-M', '--jvmci-mode', action='store', choices=sorted(_jvmciModes.viewkeys()), help='the JVM variant type to build/run (default: ' + _vm.jvmciMode + ')') 716 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 + ')') 717 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 + ')') 718 mx.add_argument('-I', '--use-jdk-image', action='store_true', help='build/run JDK image instead of exploded JDK') 719 720 mx.addJDKFactory(_JVMCI_JDK_TAG, mx.JavaCompliance('9'), JVMCI9JDKFactory()) 721 722 def mx_post_parse_cmd_line(opts): 723 mx.set_java_command_default_jdk_tag(_JVMCI_JDK_TAG) 724 725 jdkTag = mx.get_jdk_option().tag 726 727 jvmVariant = None 728 debugLevel = None 729 jvmciMode = None 730 731 if opts.jdk_jvm_variant is not None: 732 jvmVariant = opts.jdk_jvm_variant 733 if jdkTag and jdkTag != _JVMCI_JDK_TAG: 734 mx.warn('Ignoring "--jdk-jvm-variant" option as "--jdk" tag is not "' + _JVMCI_JDK_TAG + '"') 735 736 if opts.jdk_debug_level is not None: 737 debugLevel = _translateLegacyDebugLevel(opts.jdk_debug_level) 738 if jdkTag and jdkTag != _JVMCI_JDK_TAG: 739 mx.warn('Ignoring "--jdk-debug-level" option as "--jdk" tag is not "' + _JVMCI_JDK_TAG + '"') 740 741 if opts.jvmci_mode is not None: 742 jvmciMode = opts.jvmci_mode 743 if jdkTag and jdkTag != _JVMCI_JDK_TAG: 744 mx.warn('Ignoring "--jvmci-mode" option as "--jdk" tag is not "' + _JVMCI_JDK_TAG + '"') 745 746 _vm.update(jvmVariant, debugLevel, jvmciMode)