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 """
  46 Top 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 """
  70 Translation 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 """
  78 Translates a mx_jvmci:8 --vmbuild value to a mx_jvmci:9 --jdk-debug-level value.
  79 """
  80 def _translateLegacyDebugLevel(debugLevel):
  81     return _legacyVmbuilds.get(debugLevel, debugLevel)
  82 
  83 """
  84 Translation 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 """
  91 A VM configuration composed of a JDK debug level, JVM variant and a JVMCI mode.
  92 This is also a context manager that can be used with the 'with' statement to set/change
  93 a VM configuration within a dynamic scope. For example:
  94 
  95     with ConfiguredJDK(debugLevel='fastdebug'):
  96         dacapo(['pmd'])
  97 """
  98 class 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 
 129 def get_vm():
 130     """
 131     Gets the configured VM.
 132     """
 133     return _vm
 134 
 135 def 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 
 143 def isJVMCIEnabled(vm):
 144     assert vm in _jdkJvmVariants
 145     return True
 146 
 147 def _makehelp():
 148     return subprocess.check_output([mx.gmake_cmd(), 'help'], cwd=_jdkSourceRoot)
 149 
 150 def _runmake(args):
 151     """run the JDK make process
 152 
 153 To 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 
 179 def _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 
 221 class 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             'cpu',
 260             'os',
 261             'os_cpu',
 262             'share'
 263         ]
 264 
 265         for jvmVariant in _jdkJvmVariants:
 266             for debugLevel in _jdkDebugLevels:
 267                 name = jvmVariant + '-' + debugLevel
 268                 eclProjectDir = join(self.dir, 'eclipse', name)
 269                 mx.ensure_dir_exists(eclProjectDir)
 270 
 271                 out = mx.XMLDoc()
 272                 out.open('projectDescription')
 273                 out.element('name', data='hotspot:' + name)
 274                 out.element('comment', data='')
 275                 out.element('projects', data='')
 276                 out.open('buildSpec')
 277                 out.open('buildCommand')
 278                 out.element('name', data='org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder')
 279                 out.element('triggers', data='full,incremental')
 280                 out.element('arguments', data='')
 281                 out.close('buildCommand')
 282 
 283                 out.close('buildSpec')
 284                 out.open('natures')
 285                 out.element('nature', data='org.eclipse.cdt.core.cnature')
 286                 out.element('nature', data='org.eclipse.cdt.core.ccnature')
 287                 out.element('nature', data='org.eclipse.cdt.managedbuilder.core.managedBuildNature')
 288                 out.element('nature', data='org.eclipse.cdt.managedbuilder.core.ScannerConfigNature')
 289                 out.close('natures')
 290 
 291                 if roots:
 292                     out.open('linkedResources')
 293                     for r in roots:
 294                         f = join(_suite.dir, r)
 295                         out.open('link')
 296                         out.element('name', data=r)
 297                         out.element('type', data='2' if isdir(f) else '1')
 298                         out.element('locationURI', data=mx.get_eclipse_project_rel_locationURI(f, eclProjectDir))
 299                         out.close('link')
 300 
 301                     out.open('link')
 302                     out.element('name', data='gensrc')
 303                     out.element('type', data='2')
 304                     generated = join(_get_hotspot_build_dir(jvmVariant, debugLevel), 'gensrc')
 305                     out.element('locationURI', data=mx.get_eclipse_project_rel_locationURI(generated, eclProjectDir))
 306                     out.close('link')
 307 
 308                     out.close('linkedResources')
 309                 out.close('projectDescription')
 310                 projectFile = join(eclProjectDir, '.project')
 311                 mx.update_file(projectFile, out.xml(indent='\t', newl='\n'))
 312                 if files:
 313                     files.append(projectFile)
 314 
 315                 cprojectTemplate = join(self.dir, 'templates', 'eclipse', 'cproject')
 316                 cprojectFile = join(eclProjectDir, '.cproject')
 317                 with open(cprojectTemplate) as f:
 318                     content = f.read()
 319                 mx.update_file(cprojectFile, content)
 320                 if files:
 321                     files.append(cprojectFile)
 322 
 323                 settingsDir = join(eclProjectDir, ".settings")
 324                 mx.ensure_dir_exists(settingsDir)
 325                 for name, source in self._get_eclipse_settings_sources().iteritems():
 326                     out = StringIO.StringIO()
 327                     print >> out, '# GENERATED -- DO NOT EDIT'
 328                     print >> out, '# Source:', source
 329                     with open(source) as f:
 330                         print >> out, f.read()
 331                     content = out.getvalue()
 332                     mx.update_file(join(settingsDir, name), content)
 333                     if files:
 334                         files.append(join(settingsDir, name))
 335 
 336     def getBuildTask(self, args):
 337         return JDKBuildTask(self, args, _vm.debugLevel, _vm.jvmVariant)
 338 
 339 
 340 class JDKBuildTask(mx.NativeBuildTask):
 341     def __init__(self, project, args, debugLevel, jvmVariant):
 342         mx.NativeBuildTask.__init__(self, args, project)
 343         self.jvmVariant = jvmVariant
 344         self.debugLevel = debugLevel
 345 
 346     def __str__(self):
 347         return 'Building JDK[{}, {}]'.format(self.debugLevel, self.jvmVariant)
 348 
 349     def build(self):
 350         if mx.get_opts().use_jdk_image:
 351             _runmake(['images'])
 352         else:
 353             _runmake([])
 354         self._newestOutput = None
 355 
 356     def clean(self, forBuild=False):
 357         if forBuild:  # Let make handle incremental builds
 358             return
 359         if exists(_get_jdk_build_dir(self.debugLevel)):
 360             _runmake(['clean'])
 361         self._newestOutput = None
 362 
 363 # Backwards compatibility for mx_jvmci:8 API
 364 def buildvms(args):
 365     _runmultimake(args)
 366 
 367 def run_vm(args, vm=None, nonZeroIsFatal=True, out=None, err=None, cwd=None, timeout=None, debugLevel=None, vmbuild=None):
 368     """run a Java program by executing the java executable in a JVMCI JDK"""
 369     jdkTag = mx.get_jdk_option().tag
 370     if jdkTag and jdkTag != _JVMCI_JDK_TAG:
 371         mx.abort('The "--jdk" option must have the tag "' + _JVMCI_JDK_TAG + '" when running a command requiring a JVMCI VM')
 372     jdk = get_jvmci_jdk(debugLevel=debugLevel or _translateLegacyDebugLevel(vmbuild))
 373     return jdk.run_java(args, nonZeroIsFatal=nonZeroIsFatal, out=out, err=err, cwd=cwd, timeout=timeout)
 374 
 375 def _unittest_vm_launcher(vmArgs, mainClass, mainClassArgs):
 376     run_vm(vmArgs + [mainClass] + mainClassArgs)
 377 
 378 mx_unittest.set_vm_launcher('JVMCI VM launcher', _unittest_vm_launcher)
 379 
 380 def _jvmci_gate_runner(args, tasks):
 381     # Build release server VM now so we can run the unit tests
 382     with Task('BuildHotSpotJVMCIHosted: release', tasks) as t:
 383         if t: _runmultimake(['--jdk-jvm-variants', 'server', '--jdk-debug-levels', 'release'])
 384 
 385     # Run unit tests in hosted mode
 386     with VM(jvmVariant='server', debugLevel='release', jvmciMode='hosted'):
 387         with Task('JVMCI UnitTests: hosted-release', tasks) as t:
 388             if t: unittest(['--suite', 'jvmci', '--enable-timing', '--verbose', '--fail-fast'])
 389 
 390     # Build the other VM flavors
 391     with Task('BuildHotSpotJVMCIOthers: fastdebug', tasks) as t:
 392         if t: _runmultimake(['--jdk-jvm-variants', 'server', '--jdk-debug-levels', 'fastdebug'])
 393 
 394     with Task('CleanAndBuildIdealGraphVisualizer', tasks, disableJacoco=True) as t:
 395         if t and platform.processor() != 'sparc':
 396             buildxml = mx._cygpathU2W(join(_suite.dir, 'src', 'share', 'tools', 'IdealGraphVisualizer', 'build.xml'))
 397             mx.run(['ant', '-f', buildxml, '-q', 'clean', 'build'], env=_igvBuildEnv())
 398 
 399 mx_gate.add_gate_runner(_suite, _jvmci_gate_runner)
 400 mx_gate.add_gate_argument('-g', '--only-build-jvmci', action='store_false', dest='buildNonJVMCI', help='only build the JVMCI VM')
 401 
 402 def _igvJdk():
 403     v8u20 = mx.VersionSpec("1.8.0_20")
 404     v8u40 = mx.VersionSpec("1.8.0_40")
 405     v8 = mx.VersionSpec("1.8")
 406     def _igvJdkVersionCheck(version):
 407         return version >= v8 and (version < v8u20 or version >= v8u40)
 408     return mx.get_jdk(_igvJdkVersionCheck, versionDescription='>= 1.8 and < 1.8.0u20 or >= 1.8.0u40', purpose="building & running IGV").home
 409 
 410 def _igvBuildEnv():
 411         # When the http_proxy environment variable is set, convert it to the proxy settings that ant needs
 412     env = dict(os.environ)
 413     proxy = os.environ.get('http_proxy')
 414     if not (proxy is None) and len(proxy) > 0:
 415         if '://' in proxy:
 416             # Remove the http:// prefix (or any other protocol prefix)
 417             proxy = proxy.split('://', 1)[1]
 418         # Separate proxy server name and port number
 419         proxyName, proxyPort = proxy.split(':', 1)
 420         proxyEnv = '-DproxyHost="' + proxyName + '" -DproxyPort=' + proxyPort
 421         env['ANT_OPTS'] = proxyEnv
 422 
 423     env['JAVA_HOME'] = _igvJdk()
 424     return env
 425 
 426 def igv(args):
 427     """run the Ideal Graph Visualizer"""
 428     logFile = '.ideal_graph_visualizer.log'
 429     with open(join(_suite.dir, logFile), 'w') as fp:
 430         mx.logv('[Ideal Graph Visualizer log is in ' + fp.name + ']')
 431         nbplatform = join(_suite.dir, 'src', 'share', 'tools', 'IdealGraphVisualizer', 'nbplatform')
 432 
 433         # Remove NetBeans platform if it is earlier than the current supported version
 434         if exists(nbplatform):
 435             updateTrackingFile = join(nbplatform, 'platform', 'update_tracking', 'org-netbeans-core.xml')
 436             if not exists(updateTrackingFile):
 437                 mx.log('Could not find \'' + updateTrackingFile + '\', removing NetBeans platform')
 438                 shutil.rmtree(nbplatform)
 439             else:
 440                 dom = xml.dom.minidom.parse(updateTrackingFile)
 441                 currentVersion = mx.VersionSpec(dom.getElementsByTagName('module_version')[0].getAttribute('specification_version'))
 442                 supportedVersion = mx.VersionSpec('3.43.1')
 443                 if currentVersion < supportedVersion:
 444                     mx.log('Replacing NetBeans platform version ' + str(currentVersion) + ' with version ' + str(supportedVersion))
 445                     shutil.rmtree(nbplatform)
 446                 elif supportedVersion < currentVersion:
 447                     mx.log('Supported NetBeans version in igv command should be updated to ' + str(currentVersion))
 448 
 449         if not exists(nbplatform):
 450             mx.logv('[This execution may take a while as the NetBeans platform needs to be downloaded]')
 451 
 452         env = _igvBuildEnv()
 453         # make the jar for Batik 1.7 available.
 454         env['IGV_BATIK_JAR'] = mx.library('BATIK').get_path(True)
 455         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):
 456             mx.abort("IGV ant build & launch failed. Check '" + logFile + "'. You can also try to delete 'src/share/tools/IdealGraphVisualizer/nbplatform'.")
 457 
 458 def c1visualizer(args):
 459     """run the Cl Compiler Visualizer"""
 460     libpath = join(_suite.dir, 'lib')
 461     if mx.get_os() == 'windows':
 462         executable = join(libpath, 'c1visualizer', 'bin', 'c1visualizer.exe')
 463     else:
 464         executable = join(libpath, 'c1visualizer', 'bin', 'c1visualizer')
 465 
 466     # Check whether the current C1Visualizer installation is the up-to-date
 467     if exists(executable) and not exists(mx.library('C1VISUALIZER_DIST').get_path(resolve=False)):
 468         mx.log('Updating C1Visualizer')
 469         shutil.rmtree(join(libpath, 'c1visualizer'))
 470 
 471     archive = mx.library('C1VISUALIZER_DIST').get_path(resolve=True)
 472 
 473     if not exists(executable):
 474         zf = zipfile.ZipFile(archive, 'r')
 475         zf.extractall(libpath)
 476 
 477     if not exists(executable):
 478         mx.abort('C1Visualizer binary does not exist: ' + executable)
 479 
 480     if mx.get_os() != 'windows':
 481         # Make sure that execution is allowed. The zip file does not always specfiy that correctly
 482         os.chmod(executable, 0777)
 483 
 484     mx.run([executable])
 485 
 486 def hsdis(args, copyToDir=None):
 487     """download the hsdis library
 488 
 489     This is needed to support HotSpot's assembly dumping features.
 490     By default it downloads the Intel syntax version, use the 'att' argument to install AT&T syntax."""
 491     flavor = 'intel'
 492     if 'att' in args:
 493         flavor = 'att'
 494     if mx.get_arch() == "sparcv9":
 495         flavor = "sparcv9"
 496     lib = mx.add_lib_suffix('hsdis-' + mx.get_arch())
 497     path = join(_suite.dir, 'lib', lib)
 498 
 499     sha1s = {
 500         'att/hsdis-amd64.dll' : 'bcbd535a9568b5075ab41e96205e26a2bac64f72',
 501         'att/hsdis-amd64.so' : '58919ba085d4ef7a513f25bae75e7e54ee73c049',
 502         'intel/hsdis-amd64.dll' : '6a388372cdd5fe905c1a26ced614334e405d1f30',
 503         'intel/hsdis-amd64.so' : '844ed9ffed64fe9599638f29a8450c50140e3192',
 504         'intel/hsdis-amd64.dylib' : 'fdb13ef0d7d23d93dacaae9c98837bea0d4fc5a2',
 505         'sparcv9/hsdis-sparcv9.so': '970640a9af0bd63641f9063c11275b371a59ee60',
 506     }
 507 
 508     flavoredLib = flavor + "/" + lib
 509     if flavoredLib not in sha1s:
 510         mx.logv("hsdis not supported on this plattform or architecture")
 511         return
 512 
 513     if not exists(path):
 514         sha1 = sha1s[flavoredLib]
 515         sha1path = path + '.sha1'
 516         mx.download_file_with_sha1('hsdis', path, ['https://lafo.ssw.uni-linz.ac.at/pub/hsdis/' + flavoredLib], sha1, sha1path, True, True, sources=False)
 517     if copyToDir is not None and exists(copyToDir):
 518         shutil.copy(path, copyToDir)
 519 
 520 def hcfdis(args):
 521     """disassemble HexCodeFiles embedded in text files
 522 
 523     Run a tool over the input files to convert all embedded HexCodeFiles
 524     to a disassembled format."""
 525 
 526     parser = ArgumentParser(prog='mx hcfdis')
 527     parser.add_argument('-m', '--map', help='address to symbol map applied to disassembler output')
 528     parser.add_argument('files', nargs=REMAINDER, metavar='files...')
 529 
 530     args = parser.parse_args(args)
 531 
 532     path = mx.library('HCFDIS').get_path(resolve=True)
 533     mx.run_java(['-cp', path, 'com.oracle.max.hcfdis.HexCodeFileDis'] + args.files)
 534 
 535     if args.map is not None:
 536         addressRE = re.compile(r'0[xX]([A-Fa-f0-9]+)')
 537         with open(args.map) as fp:
 538             lines = fp.read().splitlines()
 539         symbols = dict()
 540         for l in lines:
 541             addressAndSymbol = l.split(' ', 1)
 542             if len(addressAndSymbol) == 2:
 543                 address, symbol = addressAndSymbol
 544                 if address.startswith('0x'):
 545                     address = long(address, 16)
 546                     symbols[address] = symbol
 547         for f in args.files:
 548             with open(f) as fp:
 549                 lines = fp.read().splitlines()
 550             updated = False
 551             for i in range(0, len(lines)):
 552                 l = lines[i]
 553                 for m in addressRE.finditer(l):
 554                     sval = m.group(0)
 555                     val = long(sval, 16)
 556                     sym = symbols.get(val)
 557                     if sym:
 558                         l = l.replace(sval, sym)
 559                         updated = True
 560                         lines[i] = l
 561             if updated:
 562                 mx.log('updating ' + f)
 563                 with open('new_' + f, "w") as fp:
 564                     for l in lines:
 565                         print >> fp, l
 566 
 567 def jol(args):
 568     """Java Object Layout"""
 569     joljar = mx.library('JOL_INTERNALS').get_path(resolve=True)
 570     candidates = mx.findclass(args, logToConsole=False, matcher=lambda s, classname: s == classname or classname.endswith('.' + s) or classname.endswith('$' + s))
 571 
 572     if len(candidates) > 0:
 573         candidates = mx.select_items(sorted(candidates))
 574     else:
 575         # mx.findclass can be mistaken, don't give up yet
 576         candidates = args
 577 
 578     run_vm(['-javaagent:' + joljar, '-cp', os.pathsep.join([mx.classpath(), joljar]), "org.openjdk.jol.MainObjectInternals"] + candidates)
 579 
 580 def _get_openjdk_os():
 581     # See: common/autoconf/platform.m4
 582     os = mx.get_os()
 583     if 'darwin' in os:
 584         os = 'macosx'
 585     elif 'linux' in os:
 586         os = 'linux'
 587     elif 'solaris' in os:
 588         os = 'solaris'
 589     elif 'cygwin' in os or 'mingw' in os:
 590         os = 'windows'
 591     return os
 592 
 593 def _get_openjdk_cpu():
 594     cpu = mx.get_arch()
 595     if cpu == 'amd64':
 596         cpu = 'x86_64'
 597     elif cpu == 'sparcv9':
 598         cpu = 'sparcv9'
 599     return cpu
 600 
 601 def _get_openjdk_os_cpu():
 602     return _get_openjdk_os() + '-' + _get_openjdk_cpu()
 603 
 604 def _get_jdk_dir():
 605     suiteParentDir = dirname(_suite.dir)
 606     # suitParentDir is now something like: /some_prefix/jdk10-hs/open/src
 607     pathComponents = suiteParentDir.split(os.sep)
 608     for i in range(0, len(pathComponents)):
 609         if pathComponents[i] in ["open", "src"]:
 610             del pathComponents[i:]
 611             break
 612     return os.path.join(os.sep, *pathComponents)
 613 
 614 def _get_jdk_build_dir(debugLevel=None):
 615     """
 616     Gets the directory into which the JDK is built. This directory contains
 617     the exploded JDK under jdk/ and the JDK image under images/jdk/.
 618     """
 619     if debugLevel is None:
 620         debugLevel = _vm.debugLevel
 621     name = '{}-{}-{}-{}'.format(_get_openjdk_os_cpu(), 'normal', _vm.jvmVariant, debugLevel)
 622     return join(_get_jdk_dir(), 'build', name)
 623 
 624 _jvmci_bootclasspath_prepends = []
 625 
 626 def _get_hotspot_build_dir(jvmVariant=None, debugLevel=None):
 627     """
 628     Gets the directory in which a particular HotSpot configuration is built
 629     (e.g., <JDK_REPO_ROOT>/build/macosx-x86_64-normal-server-release/hotspot/variant-<variant>)
 630     """
 631     if jvmVariant is None:
 632         jvmVariant = _vm.jvmVariant
 633 
 634     name = 'variant-{}'.format(jvmVariant)
 635     return join(_get_jdk_build_dir(debugLevel=debugLevel), 'hotspot', name)
 636 
 637 class JVMCI9JDKConfig(mx.JDKConfig):
 638     def __init__(self, debugLevel):
 639         self.debugLevel = debugLevel
 640         jdkBuildDir = _get_jdk_build_dir(debugLevel)
 641         jdkDir = join(jdkBuildDir, 'images', 'jdk') if mx.get_opts().use_jdk_image else join(jdkBuildDir, 'jdk')
 642         mx.JDKConfig.__init__(self, jdkDir, tag=_JVMCI_JDK_TAG)
 643 
 644     def parseVmArgs(self, args, addDefaultArgs=True):
 645         args = mx.expand_project_in_args(args, insitu=False)
 646         jacocoArgs = mx_gate.get_jacoco_agent_args()
 647         if jacocoArgs:
 648             args = jacocoArgs + args
 649 
 650         args = ['-Xbootclasspath/p:' + dep.classpath_repr() for dep in _jvmci_bootclasspath_prepends] + args
 651 
 652         # Remove JVMCI jars from class path. They are only necessary when
 653         # compiling with a javac from JDK8 or earlier.
 654         cpIndex, cp = mx.find_classpath_arg(args)
 655         if cp:
 656             excluded = frozenset([dist.path for dist in _suite.dists])
 657             cp = os.pathsep.join([e for e in cp.split(os.pathsep) if e not in excluded])
 658             args[cpIndex] = cp
 659 
 660         if '-version' in args:
 661             ignoredArgs = args[args.index('-version') + 1:]
 662             if  len(ignoredArgs) > 0:
 663                 mx.log("Warning: The following options will be ignored by the vm because they come after the '-version' argument: " + ' '.join(ignoredArgs))
 664         return self.processArgs(args, addDefaultArgs=addDefaultArgs)
 665 
 666     # Overrides JDKConfig
 667     def run_java(self, args, vm=None, nonZeroIsFatal=True, out=None, err=None, cwd=None, timeout=None, env=None, addDefaultArgs=True):
 668         if vm is None:
 669             vm = 'server'
 670 
 671         args = self.parseVmArgs(args, addDefaultArgs=addDefaultArgs)
 672 
 673         jvmciModeArgs = _jvmciModes[_vm.jvmciMode]
 674         cmd = [self.java] + ['-' + vm] + jvmciModeArgs + args
 675         return mx.run(cmd, nonZeroIsFatal=nonZeroIsFatal, out=out, err=err, cwd=cwd)
 676 
 677 """
 678 The dict of JVMCI JDKs indexed by debug-level names.
 679 """
 680 _jvmci_jdks = {}
 681 
 682 def get_jvmci_jdk(debugLevel=None):
 683     """
 684     Gets the JVMCI JDK corresponding to 'debugLevel'.
 685     """
 686     if not debugLevel:
 687         debugLevel = _vm.debugLevel
 688     jdk = _jvmci_jdks.get(debugLevel)
 689     if jdk is None:
 690         try:
 691             jdk = JVMCI9JDKConfig(debugLevel)
 692         except mx.JDKConfigException as e:
 693             jdkBuildDir = _get_jdk_build_dir(debugLevel)
 694             msg = 'Error with the JDK built into {}:\n{}\nTry (re)building it with: mx --jdk-debug-level={} make'
 695             if mx.get_opts().use_jdk_image:
 696                 msg += ' images'
 697             mx.abort(msg.format(jdkBuildDir, e.message, debugLevel))
 698         _jvmci_jdks[debugLevel] = jdk
 699     return jdk
 700 
 701 class JVMCI9JDKFactory(mx.JDKFactory):
 702     def getJDKConfig(self):
 703         jdk = get_jvmci_jdk(_vm.debugLevel)
 704         return jdk
 705 
 706     def description(self):
 707         return "JVMCI JDK"
 708 
 709 mx.update_commands(_suite, {
 710     'make': [_runmake, '[args...]', _makehelp],
 711     'multimake': [_runmultimake, '[options]'],
 712     'c1visualizer' : [c1visualizer, ''],
 713     'hsdis': [hsdis, '[att]'],
 714     'hcfdis': [hcfdis, ''],
 715     'igv' : [igv, ''],
 716     'jol' : [jol, ''],
 717     'vm': [run_vm, '[-options] class [args...]'],
 718 })
 719 
 720 mx.add_argument('-M', '--jvmci-mode', action='store', choices=sorted(_jvmciModes.viewkeys()), help='the JVM variant type to build/run (default: ' + _vm.jvmciMode + ')')
 721 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 + ')')
 722 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 + ')')
 723 mx.add_argument('-I', '--use-jdk-image', action='store_true', help='build/run JDK image instead of exploded JDK')
 724 
 725 mx.addJDKFactory(_JVMCI_JDK_TAG, mx.JavaCompliance('9'), JVMCI9JDKFactory())
 726 
 727 def mx_post_parse_cmd_line(opts):
 728     mx.set_java_command_default_jdk_tag(_JVMCI_JDK_TAG)
 729 
 730     jdkTag = mx.get_jdk_option().tag
 731 
 732     jvmVariant = None
 733     debugLevel = None
 734     jvmciMode = None
 735 
 736     if opts.jdk_jvm_variant is not None:
 737         jvmVariant = opts.jdk_jvm_variant
 738         if jdkTag and jdkTag != _JVMCI_JDK_TAG:
 739             mx.warn('Ignoring "--jdk-jvm-variant" option as "--jdk" tag is not "' + _JVMCI_JDK_TAG + '"')
 740 
 741     if opts.jdk_debug_level is not None:
 742         debugLevel = _translateLegacyDebugLevel(opts.jdk_debug_level)
 743         if jdkTag and jdkTag != _JVMCI_JDK_TAG:
 744             mx.warn('Ignoring "--jdk-debug-level" option as "--jdk" tag is not "' + _JVMCI_JDK_TAG + '"')
 745 
 746     if opts.jvmci_mode is not None:
 747         jvmciMode = opts.jvmci_mode
 748         if jdkTag and jdkTag != _JVMCI_JDK_TAG:
 749             mx.warn('Ignoring "--jvmci-mode" option as "--jdk" tag is not "' + _JVMCI_JDK_TAG + '"')
 750 
 751     _vm.update(jvmVariant, debugLevel, jvmciMode)