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)