comparison mx.graal/mx_graal.py @ 22139:258eaaa98484

Initial split off from monolithic basic-graal repo
author Doug Simon <doug.simon@oracle.com>
date Mon, 06 Jul 2015 14:11:33 +0200
parents 51ceda0cf404
children d5a51a47eb1b
comparison
equal deleted inserted replaced
22138:103f53747955 22139:258eaaa98484
1 #
2 # commands.py - the GraalVM specific commands
3 # 1 #
4 # ---------------------------------------------------------------------------------------------------- 2 # ----------------------------------------------------------------------------------------------------
5 # 3 #
6 # Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved. 4 # Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved.
7 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
24 # or visit www.oracle.com if you need additional information or have any 22 # or visit www.oracle.com if you need additional information or have any
25 # questions. 23 # questions.
26 # 24 #
27 # ---------------------------------------------------------------------------------------------------- 25 # ----------------------------------------------------------------------------------------------------
28 26
29 import os, stat, errno, sys, shutil, zipfile, tarfile, tempfile, re, time, datetime, platform, subprocess, StringIO, socket 27 import os, platform
30 from os.path import join, exists, dirname, basename 28 from os.path import join, exists
31 from argparse import ArgumentParser, REMAINDER
32 from outputparser import OutputParser, ValuesMatcher
33 import xml.dom.minidom
34 import sanitycheck 29 import sanitycheck
35 import itertools 30 import itertools
36 import json, textwrap 31 import json
37 32
38 import mx 33 import mx
39 import mx_unittest 34 import mx_jvmci
40 import mx_findbugs 35 from mx_jvmci import JDKDeployedDist, buildvms, vm, VM, Task, parseVmArgs, get_vm, unittest, ctw, isVMSupported
41 import mx_graal_makefile
42 36
43 _suite = mx.suite('graal') 37 _suite = mx.suite('graal')
44 _graal_home = _suite.dir 38
45 39 _graalDeployedDist = JDKDeployedDist('GRAAL', usesJVMCIClassLoader=True)
46 """ The VMs that can be built and run along with an optional description. Only VMs with a 40 _graalTruffleDeployedDist = JDKDeployedDist('GRAAL_TRUFFLE', usesJVMCIClassLoader=True)
47 description are listed in the dialogue for setting the default VM (see _get_vm()). """ 41
48 _vmChoices = { 42 _graalDeployedDist.postJdkInstall = lambda jdkDir, targetDir: _updateGraalPropertiesFile(join(jdkDir, 'jre', 'lib'))
49 'jvmci' : 'VM triggered compilation is performed with a tiered system (C1 + Graal) and Graal is available for hosted compilation.', 43
50 'server' : 'Normal compilation is performed with a tiered system (C1 + C2) and Graal is available for hosted compilation.', 44 mx_jvmci.jdkDeployedDists += [_graalDeployedDist, _graalTruffleDeployedDist]
51 'client' : None, # VM compilation with client compiler, hosted compilation with Graal 45 mx_jvmci.jacocoIncludes += ['com.oracle.graal.*']
52 'server-nojvmci' : None, # all compilation with tiered system (i.e., client + server), JVMCI omitted 46 mx_jvmci.jacocoExcludedAnnotations += ['@Snippet', '@ClassSubstitution']
53 'client-nojvmci' : None, # all compilation with client compiler, JVMCI omitted
54 'original' : None, # default VM copied from bootstrap JDK
55 'graal' : None, # alias for jvmci
56 'server-nograal' : None, # alias for server-nojvmci
57 'client-nograal' : None, # alias for client-nojvmci
58 }
59
60 """ The VM that will be run by the 'vm' command and built by default by the 'build' command.
61 This can be set via the global '--vm' option or the DEFAULT_VM environment variable.
62 It can also be temporarily set by using of a VM context manager object in a 'with' statement. """
63 _vm = None
64
65 """ The VM builds that will be run by the 'vm' command - default is first in list """
66 _vmbuildChoices = ['product', 'fastdebug', 'debug', 'optimized']
67
68 """ The VM build that will be run by the 'vm' command.
69 This can be set via the global '--vmbuild' option.
70 It can also be temporarily set by using of a VM context manager object in a 'with' statement. """
71 _vmbuild = _vmbuildChoices[0]
72
73 _jacoco = 'off'
74
75 """ The current working directory to switch to before running the VM. """
76 _vm_cwd = None
77
78 """ The base directory in which the JDKs cloned from $JAVA_HOME exist. """
79 _installed_jdks = None
80
81 """ Prefix for running the VM. """
82 _vm_prefix = None
83
84 _make_eclipse_launch = False
85
86 _minVersion = mx.VersionSpec('1.8')
87
88 # max version (first _unsupported_ version)
89 _untilVersion = None
90
91 class JDKDeployedDist:
92 def __init__(self, name, isExtension=False, usesJVMCIClassLoader=False, partOfHotSpot=False):
93 self.name = name
94 self.isExtension = isExtension
95 self.usesJVMCIClassLoader = usesJVMCIClassLoader
96 self.partOfHotSpot = partOfHotSpot # true when this distribution is delivered with HotSpot
97
98 _jdkDeployedDists = [
99 JDKDeployedDist('JVMCI_SERVICE', partOfHotSpot=True),
100 JDKDeployedDist('JVMCI_API', usesJVMCIClassLoader=True, partOfHotSpot=True),
101 JDKDeployedDist('JVMCI_HOTSPOT', usesJVMCIClassLoader=True, partOfHotSpot=True),
102 JDKDeployedDist('GRAAL', usesJVMCIClassLoader=True),
103 JDKDeployedDist('GRAAL_TRUFFLE', usesJVMCIClassLoader=True)
104 ]
105
106 JDK_UNIX_PERMISSIONS_DIR = 0755
107 JDK_UNIX_PERMISSIONS_FILE = 0644
108 JDK_UNIX_PERMISSIONS_EXEC = 0755
109
110 def isVMSupported(vm):
111 if 'client' == vm and len(platform.mac_ver()[0]) != 0:
112 # Client VM not supported: java launcher on Mac OS X translates '-client' to '-server'
113 return False
114 return True
115
116 def _get_vm():
117 """
118 Gets the configured VM, presenting a dialogue if there is no currently configured VM.
119 """
120 global _vm
121 if _vm:
122 return _vm
123 vm = mx.get_env('DEFAULT_VM')
124 envPath = join(_suite.mxDir, 'env')
125 if vm and 'graal' in vm:
126 if exists(envPath):
127 with open(envPath) as fp:
128 if 'DEFAULT_VM=' + vm in fp.read():
129 mx.log('Please update the DEFAULT_VM value in ' + envPath + ' to replace "graal" with "jvmci"')
130 vm = vm.replace('graal', 'jvmci')
131 if vm is None:
132 if not mx.is_interactive():
133 mx.abort('Need to specify VM with --vm option or DEFAULT_VM environment variable')
134 mx.log('Please select the VM to be executed from the following: ')
135 items = [k for k in _vmChoices.keys() if _vmChoices[k] is not None]
136 descriptions = [_vmChoices[k] for k in _vmChoices.keys() if _vmChoices[k] is not None]
137 vm = mx.select_items(items, descriptions, allowMultiple=False)
138 mx.ask_persist_env('DEFAULT_VM', vm)
139 _vm = vm
140 return vm
141
142 """
143 A context manager that can be used with the 'with' statement to set the VM
144 used by all VM executions within the scope of the 'with' statement. For example:
145
146 with VM('server'):
147 dacapo(['pmd'])
148 """
149 class VM:
150 def __init__(self, vm=None, build=None):
151 assert vm is None or vm in _vmChoices.keys()
152 assert build is None or build in _vmbuildChoices
153 self.vm = vm if vm else _vm
154 self.build = build if build else _vmbuild
155 self.previousVm = _vm
156 self.previousBuild = _vmbuild
157
158 def __enter__(self):
159 global _vm, _vmbuild
160 _vm = self.vm
161 _vmbuild = self.build
162
163 def __exit__(self, exc_type, exc_value, traceback):
164 global _vm, _vmbuild
165 _vm = self.previousVm
166 _vmbuild = self.previousBuild
167
168 def chmodRecursive(dirname, chmodFlagsDir):
169 if mx.get_os() == 'windows':
170 return
171
172 def _chmodDir(chmodFlags, dirname, fnames):
173 os.chmod(dirname, chmodFlagsDir)
174
175 os.path.walk(dirname, _chmodDir, chmodFlagsDir)
176
177 def clean(args):
178 """clean the source tree"""
179 opts = mx.clean(args, parser=ArgumentParser(prog='mx clean'))
180
181 if opts.native:
182 def handleRemoveReadonly(func, path, exc):
183 excvalue = exc[1]
184 if mx.get_os() == 'windows' and func in (os.rmdir, os.remove) and excvalue.errno == errno.EACCES:
185 os.chmod(path, stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO) # 0777
186 func(path)
187 else:
188 raise
189
190 def rmIfExists(name):
191 if os.path.isdir(name):
192 shutil.rmtree(name, ignore_errors=False, onerror=handleRemoveReadonly)
193 elif os.path.isfile(name):
194 os.unlink(name)
195
196 rmIfExists(join(_graal_home, 'build'))
197 rmIfExists(join(_graal_home, 'build-nojvmci'))
198 rmIfExists(_jdksDir())
199
200 def export(args):
201 """create archives of builds split by vmbuild and vm"""
202
203 parser = ArgumentParser(prog='mx export')
204 args = parser.parse_args(args)
205
206 # collect data about export
207 infos = dict()
208 infos['timestamp'] = time.time()
209
210 hgcfg = mx.HgConfig()
211 hgcfg.check()
212 infos['revision'] = hgcfg.tip('.') + ('+' if hgcfg.isDirty('.') else '')
213 # TODO: infos['repository']
214
215 infos['jdkversion'] = str(mx.java().version)
216
217 infos['architecture'] = mx.get_arch()
218 infos['platform'] = mx.get_os()
219
220 if mx.get_os != 'windows':
221 pass
222 # infos['ccompiler']
223 # infos['linker']
224
225 infos['hostname'] = socket.gethostname()
226
227 def _writeJson(suffix, properties):
228 d = infos.copy()
229 for k, v in properties.iteritems():
230 assert not d.has_key(k)
231 d[k] = v
232
233 jsonFileName = 'export-' + suffix + '.json'
234 with open(jsonFileName, 'w') as f:
235 print >> f, json.dumps(d)
236 return jsonFileName
237
238
239 def _genFileName(archivtype, middle):
240 idPrefix = infos['revision'] + '_'
241 idSuffix = '.tar.gz'
242 return join(_graal_home, "graalvm_" + archivtype + "_" + idPrefix + middle + idSuffix)
243
244 def _genFileArchPlatformName(archivtype, middle):
245 return _genFileName(archivtype, infos['platform'] + '_' + infos['architecture'] + '_' + middle)
246
247
248 # archive different build types of hotspot
249 for vmBuild in _vmbuildChoices:
250 jdkpath = join(_jdksDir(), vmBuild)
251 if not exists(jdkpath):
252 mx.logv("skipping " + vmBuild)
253 continue
254
255 tarName = _genFileArchPlatformName('basejdk', vmBuild)
256 mx.logv("creating basejdk " + tarName)
257 vmSet = set()
258 with tarfile.open(tarName, 'w:gz') as tar:
259 for root, _, files in os.walk(jdkpath):
260 if basename(root) in _vmChoices.keys():
261 # TODO: add some assert to check path assumption
262 vmSet.add(root)
263 continue
264
265 for f in files:
266 name = join(root, f)
267 # print name
268 tar.add(name, name)
269
270 n = _writeJson("basejdk-" + vmBuild, {'vmbuild' : vmBuild})
271 tar.add(n, n)
272
273 # create a separate archive for each VM
274 for vm in vmSet:
275 bVm = basename(vm)
276 vmTarName = _genFileArchPlatformName('vm', vmBuild + '_' + bVm)
277 mx.logv("creating vm " + vmTarName)
278
279 debugFiles = set()
280 with tarfile.open(vmTarName, 'w:gz') as tar:
281 for root, _, files in os.walk(vm):
282 for f in files:
283 # TODO: mac, windows, solaris?
284 if any(map(f.endswith, [".debuginfo"])):
285 debugFiles.add(f)
286 else:
287 name = join(root, f)
288 # print name
289 tar.add(name, name)
290
291 n = _writeJson("vm-" + vmBuild + "-" + bVm, {'vmbuild' : vmBuild, 'vm' : bVm})
292 tar.add(n, n)
293
294 if len(debugFiles) > 0:
295 debugTarName = _genFileArchPlatformName('debugfilesvm', vmBuild + '_' + bVm)
296 mx.logv("creating debugfilesvm " + debugTarName)
297 with tarfile.open(debugTarName, 'w:gz') as tar:
298 for f in debugFiles:
299 name = join(root, f)
300 # print name
301 tar.add(name, name)
302
303 n = _writeJson("debugfilesvm-" + vmBuild + "-" + bVm, {'vmbuild' : vmBuild, 'vm' : bVm})
304 tar.add(n, n)
305
306 # graal directory
307 graalDirTarName = _genFileName('classfiles', 'javac')
308 mx.logv("creating graal " + graalDirTarName)
309 with tarfile.open(graalDirTarName, 'w:gz') as tar:
310 for root, _, files in os.walk("graal"):
311 for f in [f for f in files if not f.endswith('.java')]:
312 name = join(root, f)
313 # print name
314 tar.add(name, name)
315
316 n = _writeJson("graal", {'javacompiler' : 'javac'})
317 tar.add(n, n)
318
319 47
320 def _run_benchmark(args, availableBenchmarks, runBenchmark): 48 def _run_benchmark(args, availableBenchmarks, runBenchmark):
321 49
322 vmOpts, benchmarksAndOptions = mx.extract_VM_args(args, useDoubleDash=availableBenchmarks is None) 50 vmOpts, benchmarksAndOptions = mx.extract_VM_args(args, useDoubleDash=availableBenchmarks is None)
323 51
347 75
348 def dacapo(args): 76 def dacapo(args):
349 """run one or more DaCapo benchmarks""" 77 """run one or more DaCapo benchmarks"""
350 78
351 def launcher(bm, harnessArgs, extraVmOpts): 79 def launcher(bm, harnessArgs, extraVmOpts):
352 return sanitycheck.getDacapo(bm, harnessArgs).test(_get_vm(), extraVmOpts=extraVmOpts) 80 return sanitycheck.getDacapo(bm, harnessArgs).test(get_vm(), extraVmOpts=extraVmOpts)
353 81
354 _run_benchmark(args, sanitycheck.dacapoSanityWarmup.keys(), launcher) 82 _run_benchmark(args, sanitycheck.dacapoSanityWarmup.keys(), launcher)
355 83
356 def scaladacapo(args): 84 def scaladacapo(args):
357 """run one or more Scala DaCapo benchmarks""" 85 """run one or more Scala DaCapo benchmarks"""
358 86
359 def launcher(bm, harnessArgs, extraVmOpts): 87 def launcher(bm, harnessArgs, extraVmOpts):
360 return sanitycheck.getScalaDacapo(bm, harnessArgs).test(_get_vm(), extraVmOpts=extraVmOpts) 88 return sanitycheck.getScalaDacapo(bm, harnessArgs).test(get_vm(), extraVmOpts=extraVmOpts)
361 89
362 _run_benchmark(args, sanitycheck.dacapoScalaSanityWarmup.keys(), launcher) 90 _run_benchmark(args, sanitycheck.dacapoScalaSanityWarmup.keys(), launcher)
363
364 def _vmLibDirInJdk(jdk):
365 """
366 Get the directory within a JDK where the server and client
367 subdirectories are located.
368 """
369 mxos = mx.get_os()
370 if mxos == 'darwin':
371 return join(jdk, 'jre', 'lib')
372 if mxos == 'windows' or mxos == 'cygwin':
373 return join(jdk, 'jre', 'bin')
374 return join(jdk, 'jre', 'lib', mx.get_arch())
375
376 def _vmJliLibDirs(jdk):
377 """
378 Get the directories within a JDK where the jli library designates to.
379 """
380 mxos = mx.get_os()
381 if mxos == 'darwin':
382 return [join(jdk, 'jre', 'lib', 'jli')]
383 if mxos == 'windows' or mxos == 'cygwin':
384 return [join(jdk, 'jre', 'bin'), join(jdk, 'bin')]
385 return [join(jdk, 'jre', 'lib', mx.get_arch(), 'jli'), join(jdk, 'lib', mx.get_arch(), 'jli')]
386
387 def _vmCfgInJdk(jdk, jvmCfgFile='jvm.cfg'):
388 """
389 Get the jvm.cfg file.
390 """
391 mxos = mx.get_os()
392 if mxos == "windows" or mxos == "cygwin":
393 return join(jdk, 'jre', 'lib', mx.get_arch(), jvmCfgFile)
394 return join(_vmLibDirInJdk(jdk), jvmCfgFile)
395
396 def _jdksDir():
397 return os.path.abspath(join(_installed_jdks if _installed_jdks else _graal_home, 'jdk' + str(mx.java().version)))
398
399 def _handle_missing_VM(bld, vm=None):
400 if not vm:
401 vm = _get_vm()
402 mx.log('The ' + bld + ' ' + vm + ' VM has not been created')
403 if mx.is_interactive():
404 if mx.ask_yes_no('Build it now', 'y'):
405 with VM(vm, bld):
406 build([])
407 return
408 mx.abort('You need to run "mx --vm ' + vm + ' --vmbuild ' + bld + ' build" to build the selected VM')
409
410 def _jdk(build=None, vmToCheck=None, create=False, installJars=True):
411 """
412 Get the JDK into which Graal is installed, creating it first if necessary.
413 """
414 if not build:
415 build = _vmbuild
416 jdk = join(_jdksDir(), build)
417 if create:
418 srcJdk = mx.java().jdk
419 if not exists(jdk):
420 mx.log('Creating ' + jdk + ' from ' + srcJdk)
421 shutil.copytree(srcJdk, jdk)
422
423 # Make a copy of the default VM so that this JDK can be
424 # reliably used as the bootstrap for a HotSpot build.
425 jvmCfg = _vmCfgInJdk(jdk)
426 if not exists(jvmCfg):
427 mx.abort(jvmCfg + ' does not exist')
428
429 defaultVM = None
430 jvmCfgLines = []
431 with open(jvmCfg) as f:
432 for line in f:
433 if line.startswith('-') and defaultVM is None:
434 parts = line.split()
435 if len(parts) == 2:
436 assert parts[1] == 'KNOWN', parts[1]
437 defaultVM = parts[0][1:]
438 jvmCfgLines += ['# default VM is a copy of the unmodified ' + defaultVM + ' VM\n']
439 jvmCfgLines += ['-original KNOWN\n']
440 else:
441 # skip lines which we cannot parse (e.g. '-hotspot ALIASED_TO -client')
442 mx.log("WARNING: skipping not parsable line \"" + line + "\"")
443 else:
444 jvmCfgLines += [line]
445
446 assert defaultVM is not None, 'Could not find default VM in ' + jvmCfg
447 chmodRecursive(jdk, JDK_UNIX_PERMISSIONS_DIR)
448 shutil.move(join(_vmLibDirInJdk(jdk), defaultVM), join(_vmLibDirInJdk(jdk), 'original'))
449
450 if mx.get_os() != 'windows':
451 os.chmod(jvmCfg, JDK_UNIX_PERMISSIONS_FILE)
452 with open(jvmCfg, 'w') as fp:
453 for line in jvmCfgLines:
454 fp.write(line)
455
456 # patch 'release' file (append graalvm revision)
457 releaseFile = join(jdk, 'release')
458 if exists(releaseFile):
459 releaseFileLines = []
460 with open(releaseFile) as f:
461 for line in f:
462 releaseFileLines.append(line)
463
464 if mx.get_os() != 'windows':
465 os.chmod(releaseFile, JDK_UNIX_PERMISSIONS_FILE)
466 with open(releaseFile, 'w') as fp:
467 for line in releaseFileLines:
468 if line.startswith("SOURCE="):
469 try:
470 sourceLine = line[0:-2] # remove last char
471 hgcfg = mx.HgConfig()
472 hgcfg.check()
473 revision = hgcfg.tip('.')[:12] # take first 12 chars
474 fp.write(sourceLine + ' graal:' + revision + '\"\n')
475 except:
476 fp.write(line)
477 else:
478 fp.write(line)
479
480 # Install a copy of the disassembler library
481 try:
482 hsdis([], copyToDir=_vmLibDirInJdk(jdk))
483 except SystemExit:
484 pass
485 else:
486 if not exists(jdk):
487 if _installed_jdks:
488 mx.log("The selected JDK directory does not (yet) exist: " + jdk)
489 _handle_missing_VM(build, vmToCheck)
490
491 if installJars:
492 for jdkDist in _jdkDeployedDists:
493 dist = mx.distribution(jdkDist.name)
494 if exists(dist.path) and jdkDist.partOfHotSpot:
495 _installDistInJdks(jdkDist)
496
497 if vmToCheck is not None:
498 jvmCfg = _vmCfgInJdk(jdk)
499 found = False
500 with open(jvmCfg) as f:
501 for line in f:
502 if line.strip() == '-' + vmToCheck + ' KNOWN':
503 found = True
504 break
505 if not found:
506 _handle_missing_VM(build, vmToCheck)
507
508 return jdk
509
510 def _updateInstalledJVMCIOptionsFile(jdk):
511 jvmciOptions = join(_graal_home, 'jvmci.options')
512 jreLibDir = join(jdk, 'jre', 'lib')
513 if exists(jvmciOptions):
514 shutil.copy(jvmciOptions, join(jreLibDir, 'jvmci.options'))
515 else:
516 toDelete = join(jreLibDir, 'jvmci.options')
517 if exists(toDelete):
518 os.unlink(toDelete)
519
520 def _makeHotspotGeneratedSourcesDir():
521 """
522 Gets the directory containing all the HotSpot sources generated from
523 JVMCI Java sources. This directory will be created if it doesn't yet exist.
524 """
525 hsSrcGenDir = join(mx.project('jdk.internal.jvmci.hotspot').source_gen_dir(), 'hotspot')
526 if not exists(hsSrcGenDir):
527 os.makedirs(hsSrcGenDir)
528 return hsSrcGenDir
529
530 def _copyToJdk(src, dst, permissions=JDK_UNIX_PERMISSIONS_FILE):
531 name = os.path.basename(src)
532 dstLib = join(dst, name)
533 if mx.get_env('SYMLINK_GRAAL_JAR', None) == 'true':
534 # Using symlinks is much faster than copying but may
535 # cause issues if the lib is being updated while
536 # the VM is running.
537 if not os.path.islink(dstLib) or not os.path.realpath(dstLib) == src:
538 if exists(dstLib):
539 os.remove(dstLib)
540 os.symlink(src, dstLib)
541 else:
542 # do a copy and then a move to get atomic updating (on Unix)
543 fd, tmp = tempfile.mkstemp(suffix='', prefix=name, dir=dst)
544 shutil.copyfile(src, tmp)
545 os.close(fd)
546 shutil.move(tmp, dstLib)
547 os.chmod(dstLib, permissions)
548
549 def _extractJVMCIFiles(jdkJars, jvmciJars, servicesDir, optionsDir):
550
551 oldServices = os.listdir(servicesDir) if exists(servicesDir) else os.makedirs(servicesDir)
552 oldOptions = os.listdir(optionsDir) if exists(optionsDir) else os.makedirs(optionsDir)
553
554 jvmciServices = {}
555 optionsFiles = []
556 for jar in jvmciJars:
557 if os.path.isfile(jar):
558 with zipfile.ZipFile(jar) as zf:
559 for member in zf.namelist():
560 if member.startswith('META-INF/jvmci.services/') and member != 'META-INF/jvmci.services/':
561 service = basename(member)
562 assert service != "", member
563 with zf.open(member) as serviceFile:
564 providers = jvmciServices.setdefault(service, [])
565 for line in serviceFile.readlines():
566 line = line.strip()
567 if line:
568 providers.append(line)
569 elif member.startswith('META-INF/jvmci.options/') and member != 'META-INF/jvmci.options/':
570 filename = basename(member)
571 assert filename != "", member
572 targetpath = join(optionsDir, filename)
573 optionsFiles.append(filename)
574 with zf.open(member) as optionsFile, \
575 file(targetpath, "wb") as target:
576 shutil.copyfileobj(optionsFile, target)
577 if oldOptions and filename in oldOptions:
578 oldOptions.remove(filename)
579 for service, providers in jvmciServices.iteritems():
580 fd, tmp = tempfile.mkstemp(prefix=service)
581 f = os.fdopen(fd, 'w+')
582 for provider in providers:
583 f.write(provider + os.linesep)
584 target = join(servicesDir, service)
585 f.close()
586 shutil.move(tmp, target)
587 if oldServices and service in oldServices:
588 oldServices.remove(service)
589 if mx.get_os() != 'windows':
590 os.chmod(target, JDK_UNIX_PERMISSIONS_FILE)
591
592 if mx.is_interactive():
593 for d, files in [(servicesDir, oldServices), (optionsDir, oldOptions)]:
594 if files and mx.ask_yes_no('These files in ' + d + ' look obsolete:\n ' + '\n '.join(files) + '\nDelete them', 'n'):
595 for f in files:
596 path = join(d, f)
597 os.remove(path)
598 mx.log('Deleted ' + path)
599
600 def _updateJVMCIFiles(jdkDir):
601 jreJVMCIDir = join(jdkDir, 'jre', 'lib', 'jvmci')
602 jvmciJars = [join(jreJVMCIDir, e) for e in os.listdir(jreJVMCIDir) if e.endswith('.jar')]
603 jreJVMCIServicesDir = join(jreJVMCIDir, 'services')
604 jreJVMCIOptionsDir = join(jreJVMCIDir, 'options')
605 _extractJVMCIFiles(_getJdkDeployedJars(jdkDir), jvmciJars, jreJVMCIServicesDir, jreJVMCIOptionsDir)
606 91
607 def _updateGraalPropertiesFile(jreLibDir): 92 def _updateGraalPropertiesFile(jreLibDir):
608 """ 93 """
609 Updates (or creates) 'jreLibDir'/jvmci/graal.properties to set/modify the 94 Updates (or creates) 'jreLibDir'/jvmci/graal.properties to set/modify the
610 graal.version property. 95 graal.version property.
611 """ 96 """
612 version = graal_version() 97 version = _suite.release_version()
613 graalProperties = join(jreLibDir, 'jvmci', 'graal.properties') 98 graalProperties = join(jreLibDir, 'jvmci', 'graal.properties')
614 if not exists(graalProperties): 99 if not exists(graalProperties):
615 with open(graalProperties, 'w') as fp: 100 with open(graalProperties, 'w') as fp:
616 print >> fp, 'graal.version=' + version 101 print >> fp, 'graal.version=' + version
617 else: 102 else:
622 content.append('graal.version=' + version) 107 content.append('graal.version=' + version)
623 else: 108 else:
624 content.append(line.rstrip(os.linesep)) 109 content.append(line.rstrip(os.linesep))
625 with open(graalProperties, 'w') as fp: 110 with open(graalProperties, 'w') as fp:
626 fp.write(os.linesep.join(content)) 111 fp.write(os.linesep.join(content))
627
628 def _installDistInJdks(deployableDist):
629 """
630 Installs the jar(s) for a given Distribution into all existing JVMCI JDKs
631 """
632 dist = mx.distribution(deployableDist.name)
633 jdks = _jdksDir()
634 if exists(jdks):
635 for e in os.listdir(jdks):
636 jdkDir = join(jdks, e)
637 jreLibDir = join(jdkDir, 'jre', 'lib')
638 if exists(jreLibDir):
639 if deployableDist.isExtension:
640 targetDir = join(jreLibDir, 'ext')
641 elif deployableDist.usesJVMCIClassLoader:
642 targetDir = join(jreLibDir, 'jvmci')
643 else:
644 targetDir = jreLibDir
645 if not exists(targetDir):
646 os.makedirs(targetDir)
647 _copyToJdk(dist.path, targetDir)
648 if dist.sourcesPath:
649 _copyToJdk(dist.sourcesPath, jdkDir)
650 if deployableDist.usesJVMCIClassLoader:
651 # deploy service files
652 _updateJVMCIFiles(jdkDir)
653 if dist.name == 'GRAAL':
654 _updateGraalPropertiesFile(jreLibDir)
655
656 def _getJdkDeployedJars(jdkDir):
657 """
658 Gets jar paths for all deployed distributions in the context of
659 a given JDK directory.
660 """
661 jreLibDir = join(jdkDir, 'jre', 'lib')
662 jars = []
663 for dist in _jdkDeployedDists:
664 jar = basename(mx.distribution(dist.name).path)
665 if dist.isExtension:
666 jars.append(join(jreLibDir, 'ext', jar))
667 elif dist.usesJVMCIClassLoader:
668 jars.append(join(jreLibDir, 'jvmci', jar))
669 else:
670 jars.append(join(jreLibDir, jar))
671 return jars
672
673
674 # run a command in the windows SDK Debug Shell
675 def _runInDebugShell(cmd, workingDir, logFile=None, findInOutput=None, respondTo=None):
676 if respondTo is None:
677 respondTo = {}
678 newLine = os.linesep
679 startToken = 'RUNINDEBUGSHELL_STARTSEQUENCE'
680 endToken = 'RUNINDEBUGSHELL_ENDSEQUENCE'
681
682 winSDK = mx.get_env('WIN_SDK', 'C:\\Program Files\\Microsoft SDKs\\Windows\\v7.1\\')
683
684 if not exists(mx._cygpathW2U(winSDK)):
685 mx.abort("Could not find Windows SDK : '" + winSDK + "' does not exist")
686
687 winSDKSetEnv = mx._cygpathW2U(join(winSDK, 'Bin', 'SetEnv.cmd'))
688 if not exists(winSDKSetEnv):
689 mx.abort("Invalid Windows SDK path (" + winSDK + ") : could not find Bin/SetEnv.cmd (you can use the WIN_SDK environment variable to specify an other path)")
690
691 wincmd = 'cmd.exe /E:ON /V:ON /K "' + mx._cygpathU2W(winSDKSetEnv) + '"'
692 p = subprocess.Popen(wincmd, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
693 stdout = p.stdout
694 stdin = p.stdin
695 if logFile:
696 log = open(logFile, 'w')
697 ret = False
698
699 def _writeProcess(s):
700 stdin.write(s + newLine)
701
702 _writeProcess("echo " + startToken)
703 while True:
704 # encoding may be None on windows plattforms
705 if sys.stdout.encoding is None:
706 encoding = 'utf-8'
707 else:
708 encoding = sys.stdout.encoding
709
710 line = stdout.readline().decode(encoding)
711 if logFile:
712 log.write(line.encode('utf-8'))
713 line = line.strip()
714 mx.log(line)
715 if line == startToken:
716 _writeProcess('cd /D ' + workingDir + ' & ' + cmd + ' & echo ' + endToken)
717 for regex in respondTo.keys():
718 match = regex.search(line)
719 if match:
720 _writeProcess(respondTo[regex])
721 if findInOutput:
722 match = findInOutput.search(line)
723 if match:
724 ret = True
725 if line == endToken:
726 if not findInOutput:
727 _writeProcess('echo ERRXXX%errorlevel%')
728 else:
729 break
730 if line.startswith('ERRXXX'):
731 if line == 'ERRXXX0':
732 ret = True
733 break
734 _writeProcess("exit")
735 if logFile:
736 log.close()
737 return ret
738
739 def jdkhome(vm=None):
740 """return the JDK directory selected for the 'vm' command"""
741 return _jdk(installJars=False)
742
743 def print_jdkhome(args, vm=None):
744 """print the JDK directory selected for the 'vm' command"""
745 print jdkhome(vm)
746
747 def buildvars(args):
748 """describe the variables that can be set by the -D option to the 'mx build' commmand"""
749
750 buildVars = {
751 'ALT_BOOTDIR' : 'The location of the bootstrap JDK installation (default: ' + mx.java().jdk + ')',
752 'ALT_OUTPUTDIR' : 'Build directory',
753 'HOTSPOT_BUILD_JOBS' : 'Number of CPUs used by make (default: ' + str(mx.cpu_count()) + ')',
754 'INSTALL' : 'Install the built VM into the JDK? (default: y)',
755 'ZIP_DEBUGINFO_FILES' : 'Install zipped debug symbols file? (default: 0)',
756 }
757
758 mx.log('HotSpot build variables that can be set by the -D option to "mx build":')
759 mx.log('')
760 for n in sorted(buildVars.iterkeys()):
761 mx.log(n)
762 mx.log(textwrap.fill(buildVars[n], initial_indent=' ', subsequent_indent=' ', width=200))
763
764 mx.log('')
765 mx.log('Note that these variables can be given persistent values in the file ' + join(_suite.mxDir, 'env') + ' (see \'mx about\').')
766
767 cached_graal_version = None
768
769 def graal_version(dev_suffix='dev'):
770 global cached_graal_version
771
772 if not cached_graal_version:
773 # extract latest release tag for graal
774 try:
775 tags = [x.split() for x in subprocess.check_output(['hg', '-R', _graal_home, 'tags']).split('\n') if x.startswith("graal-")]
776 current_id = subprocess.check_output(['hg', '-R', _graal_home, 'log', '--template', '{rev}\n', '--rev', 'tip']).strip()
777 except:
778 # not a mercurial repository or hg commands are not available.
779 tags = None
780
781 if tags and current_id:
782 sorted_tags = sorted(tags, key=lambda e: [int(x) for x in e[0][len("graal-"):].split('.')], reverse=True)
783 most_recent_tag_name, most_recent_tag_revision = sorted_tags[0]
784 most_recent_tag_id = most_recent_tag_revision[:most_recent_tag_revision.index(":")]
785 most_recent_tag_version = most_recent_tag_name[len("graal-"):]
786
787 # tagged commit is one-off with commit that tags it
788 if int(current_id) - int(most_recent_tag_id) <= 1:
789 cached_graal_version = most_recent_tag_version
790 else:
791 major, minor = map(int, most_recent_tag_version.split('.'))
792 cached_graal_version = str(major) + '.' + str(minor + 1) + '-' + dev_suffix
793 else:
794 cached_graal_version = 'unknown-{0}-{1}'.format(platform.node(), time.strftime('%Y-%m-%d_%H-%M-%S_%Z'))
795
796 return cached_graal_version
797
798 def build(args, vm=None):
799 """build the VM binary
800
801 The global '--vm' and '--vmbuild' options select which VM type and build target to build."""
802
803 # Override to fail quickly if extra arguments are given
804 # at the end of the command line. This allows for a more
805 # helpful error message.
806 class AP(ArgumentParser):
807 def __init__(self):
808 ArgumentParser.__init__(self, prog='mx build')
809 def parse_args(self, args):
810 result = ArgumentParser.parse_args(self, args)
811 if len(result.remainder) != 0:
812 firstBuildTarget = result.remainder[0]
813 mx.abort('To specify the ' + firstBuildTarget + ' VM build target, you need to use the global "--vmbuild" option. For example:\n' +
814 ' mx --vmbuild ' + firstBuildTarget + ' build')
815 return result
816
817 # Call mx.build to compile the Java sources
818 parser = AP()
819 parser.add_argument('-D', action='append', help='set a HotSpot build variable (run \'mx buildvars\' to list variables)', metavar='name=value')
820
821 opts2 = mx.build(['--source', '1.7'] + args, parser=parser)
822 assert len(opts2.remainder) == 0
823
824 if not opts2.native:
825 return
826
827 builds = [_vmbuild]
828
829 if os.environ.get('BUILDING_FROM_IDE', None) == 'true':
830 build = os.environ.get('IDE_BUILD_TARGET', None)
831 if build is None or len(build) == 0:
832 return
833 if build not in _vmbuildChoices:
834 mx.abort('VM build "' + build + '" specified by IDE_BUILD_TARGET environment variable is unknown (must be one of ' +
835 str(_vmbuildChoices) + ')')
836 builds = [build]
837
838 if vm is None:
839 vm = _get_vm()
840
841 if vm == 'original':
842 pass
843 elif vm.startswith('server'):
844 buildSuffix = ''
845 elif vm.startswith('client'):
846 buildSuffix = '1'
847 else:
848 assert vm == 'jvmci', vm
849 buildSuffix = 'jvmci'
850
851 if _installed_jdks and _installed_jdks != _graal_home:
852 if not mx.ask_yes_no("Warning: building while --installed-jdks is set (" + _installed_jdks + ") is not recommanded - are you sure you want to continue", 'n'):
853 mx.abort(1)
854
855 isWindows = platform.system() == 'Windows' or "CYGWIN" in platform.system()
856 for build in builds:
857 installJars = vm != 'original' and (isWindows or not opts2.java)
858 jdk = _jdk(build, create=True, installJars=installJars)
859
860 if vm == 'original':
861 if build != 'product':
862 mx.log('only product build of original VM exists')
863 continue
864
865 if not isVMSupported(vm):
866 mx.log('The ' + vm + ' VM is not supported on this platform - skipping')
867 continue
868
869 vmDir = join(_vmLibDirInJdk(jdk), vm)
870 if not exists(vmDir):
871 chmodRecursive(jdk, JDK_UNIX_PERMISSIONS_DIR)
872 mx.log('Creating VM directory in JDK: ' + vmDir)
873 os.makedirs(vmDir)
874
875 def filterXusage(line):
876 if not 'Xusage.txt' in line:
877 sys.stderr.write(line + os.linesep)
878
879 # Check if a build really needs to be done
880 timestampFile = join(vmDir, '.build-timestamp')
881 if opts2.force or not exists(timestampFile):
882 mustBuild = True
883 else:
884 mustBuild = False
885 timestamp = os.path.getmtime(timestampFile)
886 sources = []
887 for d in ['src', 'make', join('jvmci', 'jdk.internal.jvmci.hotspot', 'src_gen', 'hotspot')]:
888 for root, dirnames, files in os.walk(join(_graal_home, d)):
889 # ignore <graal>/src/share/tools
890 if root == join(_graal_home, 'src', 'share'):
891 dirnames.remove('tools')
892 sources += [join(root, name) for name in files]
893 for f in sources:
894 if len(f) != 0 and os.path.getmtime(f) > timestamp:
895 mustBuild = True
896 break
897
898 if not mustBuild:
899 mx.logv('[all files in src and make directories are older than ' + timestampFile[len(_graal_home) + 1:] + ' - skipping native build]')
900 continue
901
902 if isWindows:
903 t_compilelogfile = mx._cygpathU2W(os.path.join(_graal_home, "graalCompile.log"))
904 mksHome = mx.get_env('MKS_HOME', 'C:\\cygwin\\bin')
905
906 variant = {'client': 'compiler1', 'server': 'compiler2'}.get(vm, vm)
907 project_config = variant + '_' + build
908 t_graal_home = mx._cygpathU2W(_graal_home)
909 _runInDebugShell('msbuild ' + t_graal_home + r'\build\vs-amd64\jvm.vcproj /p:Configuration=' + project_config + ' /target:clean', t_graal_home)
910 winCompileCmd = r'set HotSpotMksHome=' + mksHome + r'& set OUT_DIR=' + mx._cygpathU2W(jdk) + r'& set JAVA_HOME=' + mx._cygpathU2W(jdk) + r'& set path=%JAVA_HOME%\bin;%path%;%HotSpotMksHome%& cd /D "' + t_graal_home + r'\make\windows"& call create.bat ' + t_graal_home
911 print winCompileCmd
912 winCompileSuccess = re.compile(r"^Writing \.vcxproj file:")
913 if not _runInDebugShell(winCompileCmd, t_graal_home, t_compilelogfile, winCompileSuccess):
914 mx.log('Error executing create command')
915 return
916 winBuildCmd = 'msbuild ' + t_graal_home + r'\build\vs-amd64\jvm.vcxproj /p:Configuration=' + project_config + ' /p:Platform=x64'
917 if not _runInDebugShell(winBuildCmd, t_graal_home, t_compilelogfile):
918 mx.log('Error building project')
919 return
920 else:
921 cpus = mx.cpu_count()
922 makeDir = join(_graal_home, 'make')
923 runCmd = [mx.gmake_cmd(), '-C', makeDir]
924
925 env = os.environ.copy()
926
927 # These must be passed as environment variables
928 env.setdefault('LANG', 'C')
929 env['JAVA_HOME'] = jdk
930
931 def setMakeVar(name, default, env=None):
932 """Sets a make variable on the command line to the value
933 of the variable in 'env' with the same name if defined
934 and 'env' is not None otherwise to 'default'
935 """
936 runCmd.append(name + '=' + (env.get(name, default) if env else default))
937
938 if opts2.D:
939 for nv in opts2.D:
940 name, value = nv.split('=', 1)
941 setMakeVar(name.strip(), value)
942
943 setMakeVar('ARCH_DATA_MODEL', '64', env=env)
944 setMakeVar('HOTSPOT_BUILD_JOBS', str(cpus), env=env)
945 setMakeVar('ALT_BOOTDIR', mx.java().jdk, env=env)
946 setMakeVar("EXPORT_PATH", jdk)
947
948 setMakeVar('MAKE_VERBOSE', 'y' if mx._opts.verbose else '')
949 if vm.endswith('nojvmci'):
950 setMakeVar('INCLUDE_JVMCI', 'false')
951 setMakeVar('ALT_OUTPUTDIR', join(_graal_home, 'build-nojvmci', mx.get_os()), env=env)
952 else:
953 version = graal_version()
954 setMakeVar('USER_RELEASE_SUFFIX', 'jvmci-' + version)
955 setMakeVar('INCLUDE_JVMCI', 'true')
956 setMakeVar('INSTALL', 'y', env=env)
957 if mx.get_os() == 'darwin' and platform.mac_ver()[0] != '':
958 # Force use of clang on MacOS
959 setMakeVar('USE_CLANG', 'true')
960 if mx.get_os() == 'solaris':
961 # If using sparcWorks, setup flags to avoid make complaining about CC version
962 cCompilerVersion = subprocess.Popen('CC -V', stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True).stderr.readlines()[0]
963 if cCompilerVersion.startswith('CC: Sun C++'):
964 compilerRev = cCompilerVersion.split(' ')[3]
965 setMakeVar('ENFORCE_COMPILER_REV', compilerRev, env=env)
966 setMakeVar('ENFORCE_CC_COMPILER_REV', compilerRev, env=env)
967 if build == 'jvmg':
968 # We want ALL the symbols when debugging on Solaris
969 setMakeVar('STRIP_POLICY', 'no_strip')
970 # This removes the need to unzip the *.diz files before debugging in gdb
971 setMakeVar('ZIP_DEBUGINFO_FILES', '0', env=env)
972
973 if buildSuffix == "1":
974 setMakeVar("BUILD_CLIENT_ONLY", "true")
975
976 # Clear this variable as having it set can cause very confusing build problems
977 env.pop('CLASSPATH', None)
978
979 # Issue an env prefix that can be used to run the make on the command line
980 if not mx._opts.verbose:
981 mx.log('--------------- make command line ----------------------')
982
983 envPrefix = ' '.join([key + '=' + env[key] for key in env.iterkeys() if not os.environ.has_key(key) or env[key] != os.environ[key]])
984 if len(envPrefix):
985 mx.log('env ' + envPrefix + ' \\')
986
987 runCmd.append(build + buildSuffix)
988 runCmd.append("docs")
989 runCmd.append("export_" + build)
990
991 if not mx._opts.verbose:
992 mx.log(' '.join(runCmd))
993 mx.log('--------------------------------------------------------')
994 mx.run(runCmd, err=filterXusage, env=env)
995
996 jvmCfg = _vmCfgInJdk(jdk)
997 if not exists(jvmCfg):
998 mx.abort(jvmCfg + ' does not exist')
999
1000 prefix = '-' + vm + ' '
1001 vmKnown = prefix + 'KNOWN\n'
1002 lines = []
1003 found = False
1004 with open(jvmCfg) as f:
1005 for line in f:
1006 if line.strip() == vmKnown.strip():
1007 found = True
1008 lines.append(line)
1009
1010 if not found:
1011 mx.log('Prepending "' + prefix + 'KNOWN" to ' + jvmCfg)
1012 if mx.get_os() != 'windows':
1013 os.chmod(jvmCfg, JDK_UNIX_PERMISSIONS_FILE)
1014 with open(jvmCfg, 'w') as f:
1015 written = False
1016 for line in lines:
1017 if line.startswith('#'):
1018 f.write(line)
1019 continue
1020 if not written:
1021 f.write(vmKnown)
1022 if vm == 'jvmci':
1023 # Legacy support
1024 f.write('-graal ALIASED_TO -jvmci\n')
1025 written = True
1026 if line.startswith(prefix):
1027 line = vmKnown
1028 if written:
1029 continue
1030 f.write(line)
1031
1032 for jdkDist in _jdkDeployedDists: # Install non HotSpot distribution
1033 if not jdkDist.partOfHotSpot:
1034 _installDistInJdks(jdkDist)
1035 if exists(timestampFile):
1036 os.utime(timestampFile, None)
1037 else:
1038 file(timestampFile, 'a')
1039
1040 def vmg(args):
1041 """run the debug build of VM selected by the '--vm' option"""
1042 return vm(args, vmbuild='debug')
1043
1044 def vmfg(args):
1045 """run the fastdebug build of VM selected by the '--vm' option"""
1046 return vm(args, vmbuild='fastdebug')
1047
1048 def _parseVmArgs(args, vm=None, cwd=None, vmbuild=None):
1049 """run the VM selected by the '--vm' option"""
1050
1051 if vm is None:
1052 vm = _get_vm()
1053
1054 if not isVMSupported(vm):
1055 mx.abort('The ' + vm + ' is not supported on this platform')
1056
1057 if cwd is None:
1058 cwd = _vm_cwd
1059 elif _vm_cwd is not None and _vm_cwd != cwd:
1060 mx.abort("conflicting working directories: do not set --vmcwd for this command")
1061
1062 build = vmbuild if vmbuild else _vmbuild
1063 jdk = _jdk(build, vmToCheck=vm, installJars=False)
1064 _updateInstalledJVMCIOptionsFile(jdk)
1065 mx.expand_project_in_args(args)
1066 if _make_eclipse_launch:
1067 mx.make_eclipse_launch(_suite, args, 'graal-' + build, name=None, deps=mx.project('com.oracle.graal.hotspot').all_deps([], True))
1068 if _jacoco == 'on' or _jacoco == 'append':
1069 jacocoagent = mx.library("JACOCOAGENT", True)
1070 # Exclude all compiler tests and snippets
1071
1072 includes = ['com.oracle.graal.*', 'jdk.internal.jvmci.*']
1073 baseExcludes = []
1074 for p in mx.projects():
1075 projsetting = getattr(p, 'jacoco', '')
1076 if projsetting == 'exclude':
1077 baseExcludes.append(p.name)
1078 if projsetting == 'include':
1079 includes.append(p.name + '.*')
1080
1081 def _filter(l):
1082 # filter out specific classes which are already covered by a baseExclude package
1083 return [clazz for clazz in l if not any([clazz.startswith(package) for package in baseExcludes])]
1084 excludes = []
1085 for p in mx.projects():
1086 excludes += _filter(_find_classes_with_annotations(p, None, ['@Snippet', '@ClassSubstitution', '@Test'], includeInnerClasses=True).keys())
1087 excludes += _filter(p.find_classes_with_matching_source_line(None, lambda line: 'JaCoCo Exclude' in line, includeInnerClasses=True).keys())
1088
1089 excludes += [package + '.*' for package in baseExcludes]
1090 agentOptions = {
1091 'append' : 'true' if _jacoco == 'append' else 'false',
1092 'bootclasspath' : 'true',
1093 'includes' : ':'.join(includes),
1094 'excludes' : ':'.join(excludes),
1095 'destfile' : 'jacoco.exec'
1096 }
1097 args = ['-javaagent:' + jacocoagent.get_path(True) + '=' + ','.join([k + '=' + v for k, v in agentOptions.items()])] + args
1098 exe = join(jdk, 'bin', mx.exe_suffix('java'))
1099 pfx = _vm_prefix.split() if _vm_prefix is not None else []
1100
1101 if '-version' in args:
1102 ignoredArgs = args[args.index('-version') + 1:]
1103 if len(ignoredArgs) > 0:
1104 mx.log("Warning: The following options will be ignored by the vm because they come after the '-version' argument: " + ' '.join(ignoredArgs))
1105
1106 # Unconditionally prepend truffle.jar to the boot class path.
1107 # This used to be done by the VM itself but was removed to
1108 # separate the VM from Truffle.
1109 truffle_jar = mx.library('TRUFFLE').path
1110 args = ['-Xbootclasspath/p:' + truffle_jar] + args
1111
1112 args = mx.java().processArgs(args)
1113 return (pfx, exe, vm, args, cwd)
1114
1115 def vm(args, vm=None, nonZeroIsFatal=True, out=None, err=None, cwd=None, timeout=None, vmbuild=None):
1116 (pfx_, exe_, vm_, args_, cwd) = _parseVmArgs(args, vm, cwd, vmbuild)
1117 return mx.run(pfx_ + [exe_, '-' + vm_] + args_, nonZeroIsFatal=nonZeroIsFatal, out=out, err=err, cwd=cwd, timeout=timeout)
1118
1119 def _find_classes_with_annotations(p, pkgRoot, annotations, includeInnerClasses=False):
1120 """
1121 Scan the sources of project 'p' for Java source files containing a line starting with 'annotation'
1122 (ignoring preceding whitespace) and return the fully qualified class name for each Java
1123 source file matched in a list.
1124 """
1125
1126 matches = lambda line: len([a for a in annotations if line == a or line.startswith(a + '(')]) != 0
1127 return p.find_classes_with_matching_source_line(pkgRoot, matches, includeInnerClasses)
1128
1129 def _find_classpath_arg(vmArgs):
1130 for index in range(len(vmArgs)):
1131 if vmArgs[index] in ['-cp', '-classpath']:
1132 return index + 1, vmArgs[index + 1]
1133
1134 def unittest(args):
1135 def vmLauncher(vmArgs, mainClass, mainClassArgs):
1136 if isJVMCIEnabled(_get_vm()):
1137 # Remove entries from class path that are in JVMCI loaded jars
1138 cpIndex, cp = _find_classpath_arg(vmArgs)
1139 if cp:
1140 excluded = set()
1141 for jdkDist in _jdkDeployedDists:
1142 dist = mx.distribution(jdkDist.name)
1143 excluded.update([d.output_dir() for d in dist.sorted_deps()])
1144 cp = os.pathsep.join([e for e in cp.split(os.pathsep) if e not in excluded])
1145 vmArgs[cpIndex] = cp
1146
1147 # Run the VM in a mode where application/test classes can
1148 # access JVMCI loaded classes.
1149 vmArgs = ['-XX:-UseJVMCIClassLoader'] + vmArgs
1150
1151 vm(vmArgs + [mainClass] + mainClassArgs)
1152 mx_unittest.unittest(args, vmLauncher=vmLauncher)
1153
1154 def shortunittest(args):
1155 """alias for 'unittest --whitelist test/whitelist_shortunittest.txt'"""
1156
1157 args = ['--whitelist', 'test/whitelist_shortunittest.txt'] + args
1158 unittest(args)
1159 112
1160 def microbench(args): 113 def microbench(args):
1161 """run JMH microbenchmark projects""" 114 """run JMH microbenchmark projects"""
1162 vmArgs, jmhArgs = mx.extract_VM_args(args, useDoubleDash=True) 115 vmArgs, jmhArgs = mx.extract_VM_args(args, useDoubleDash=True)
1163 116
1191 args = ['-cp', cp] 144 args = ['-cp', cp]
1192 if not forking: 145 if not forking:
1193 args += vmArgs 146 args += vmArgs
1194 args += ['org.openjdk.jmh.Main'] 147 args += ['org.openjdk.jmh.Main']
1195 if forking: 148 if forking:
1196 (_, _, jvm, _, _) = _parseVmArgs(vmArgs) 149 (_, _, jvm, _, _) = parseVmArgs(vmArgs)
1197 args += ['--jvmArgsPrepend', ' '.join(['-' + jvm] + vmArgs)] 150 args += ['--jvmArgsPrepend', ' '.join(['-' + jvm] + vmArgs)]
1198 vm(args + jmhArgs) 151 vm(args + jmhArgs)
1199 152
1200 def buildvms(args): 153 def _graal_gate_runner(args, tasks):
1201 """build one or more VMs in various configurations"""
1202
1203 vmsDefault = ','.join(_vmChoices.keys())
1204 vmbuildsDefault = ','.join(_vmbuildChoices)
1205
1206 parser = ArgumentParser(prog='mx buildvms')
1207 parser.add_argument('--vms', help='a comma separated list of VMs to build (default: ' + vmsDefault + ')', metavar='<args>', default=vmsDefault)
1208 parser.add_argument('--builds', help='a comma separated list of build types (default: ' + vmbuildsDefault + ')', metavar='<args>', default=vmbuildsDefault)
1209 parser.add_argument('--check-distributions', action='store_true', dest='check_distributions', help='check built distributions for overlap')
1210 parser.add_argument('-n', '--no-check', action='store_true', help='omit running "java -version" after each build')
1211 parser.add_argument('-c', '--console', action='store_true', help='send build output to console instead of log file')
1212
1213 args = parser.parse_args(args)
1214 vms = args.vms.split(',')
1215 builds = args.builds.split(',')
1216
1217 allStart = time.time()
1218 check_dists_args = ['--check-distributions'] if args.check_distributions else []
1219 for v in vms:
1220 if not isVMSupported(v):
1221 mx.log('The ' + v + ' VM is not supported on this platform - skipping')
1222 continue
1223
1224 for vmbuild in builds:
1225 if v == 'original' and vmbuild != 'product':
1226 continue
1227 if not args.console:
1228 logFile = join(v + '-' + vmbuild + '.log')
1229 log = open(join(_graal_home, logFile), 'wb')
1230 start = time.time()
1231 mx.log('BEGIN: ' + v + '-' + vmbuild + '\t(see: ' + logFile + ')')
1232 verbose = ['-v'] if mx._opts.verbose else []
1233 # Run as subprocess so that output can be directed to a file
1234 cmd = [sys.executable, '-u', join('mxtool', 'mx.py')] + verbose + ['--vm', v, '--vmbuild', vmbuild, 'build'] + check_dists_args
1235 mx.logv("executing command: " + str(cmd))
1236 subprocess.check_call(cmd, cwd=_graal_home, stdout=log, stderr=subprocess.STDOUT)
1237 duration = datetime.timedelta(seconds=time.time() - start)
1238 mx.log('END: ' + v + '-' + vmbuild + '\t[' + str(duration) + ']')
1239 else:
1240 with VM(v, vmbuild):
1241 build(check_dists_args)
1242 if not args.no_check:
1243 vmargs = ['-version']
1244 if v == 'jvmci':
1245 vmargs.insert(0, '-XX:-BootstrapJVMCI')
1246 vm(vmargs, vm=v, vmbuild=vmbuild)
1247 allDuration = datetime.timedelta(seconds=time.time() - allStart)
1248 mx.log('TOTAL TIME: ' + '[' + str(allDuration) + ']')
1249
1250 class Task:
1251 # None or a list of strings. If not None, only tasks whose title
1252 # matches at least one of the substrings in this list will return
1253 # a non-None value from __enter__. The body of a 'with Task(...) as t'
1254 # statement should check 't' and exit immediately if it is None.
1255 filters = None
1256 filtersExclude = False
1257
1258 def __init__(self, title, tasks=None):
1259 self.tasks = tasks
1260 self.title = title
1261 if tasks is not None and Task.filters is not None:
1262 if Task.filtersExclude:
1263 self.skipped = any([f in title for f in Task.filters])
1264 else:
1265 self.skipped = not any([f in title for f in Task.filters])
1266 else:
1267 self.skipped = False
1268 if not self.skipped:
1269 self.start = time.time()
1270 self.end = None
1271 self.duration = None
1272 mx.log(time.strftime('gate: %d %b %Y %H:%M:%S: BEGIN: ') + title)
1273 def __enter__(self):
1274 assert self.tasks is not None, "using Task with 'with' statement requires to pass the tasks list in the constructor"
1275 if self.skipped:
1276 return None
1277 return self
1278 def __exit__(self, exc_type, exc_value, traceback):
1279 if not self.skipped:
1280 self.tasks.append(self.stop())
1281 def stop(self):
1282 self.end = time.time()
1283 self.duration = datetime.timedelta(seconds=self.end - self.start)
1284 mx.log(time.strftime('gate: %d %b %Y %H:%M:%S: END: ') + self.title + ' [' + str(self.duration) + ']')
1285 return self
1286 def abort(self, codeOrMessage):
1287 self.end = time.time()
1288 self.duration = datetime.timedelta(seconds=self.end - self.start)
1289 mx.log(time.strftime('gate: %d %b %Y %H:%M:%S: ABORT: ') + self.title + ' [' + str(self.duration) + ']')
1290 mx.abort(codeOrMessage)
1291 return self
1292
1293 def ctw(args):
1294 """run CompileTheWorld"""
1295
1296 defaultCtwopts = '-Inline'
1297
1298 parser = ArgumentParser(prog='mx ctw')
1299 parser.add_argument('--ctwopts', action='store', help='space separated JVMCI options used for CTW compilations (default: --ctwopts="' + defaultCtwopts + '")', default=defaultCtwopts, metavar='<options>')
1300 parser.add_argument('--jar', action='store', help='jar of classes to compiled instead of rt.jar', metavar='<path>')
1301
1302 args, vmargs = parser.parse_known_args(args)
1303
1304 if args.ctwopts:
1305 vmargs.append('-G:CompileTheWorldConfig=' + args.ctwopts)
1306
1307 if args.jar:
1308 jar = os.path.abspath(args.jar)
1309 else:
1310 jar = join(_jdk(installJars=False), 'jre', 'lib', 'rt.jar')
1311 vmargs.append('-G:CompileTheWorldExcludeMethodFilter=sun.awt.X11.*.*')
1312
1313 vmargs += ['-XX:+CompileTheWorld']
1314 vm_ = _get_vm()
1315 if isJVMCIEnabled(vm_):
1316 if vm_ == 'jvmci':
1317 vmargs += ['-XX:+BootstrapJVMCI']
1318 vmargs += ['-G:CompileTheWorldClasspath=' + jar]
1319 else:
1320 vmargs += ['-Xbootclasspath/p:' + jar]
1321
1322 # suppress menubar and dock when running on Mac; exclude x11 classes as they may cause vm crashes (on Solaris)
1323 vmargs = ['-Djava.awt.headless=true'] + vmargs
1324
1325 vm(vmargs)
1326
1327 def _basic_gate_body(args, tasks):
1328 # Build server-hosted-jvmci now so we can run the unit tests 154 # Build server-hosted-jvmci now so we can run the unit tests
1329 with Task('BuildHotSpotJVMCIHosted: product', tasks) as t: 155 with Task('BuildHotSpotJVMCIHosted: product', tasks) as t:
1330 if t: buildvms(['--vms', 'server', '--builds', 'product', '--check-distributions']) 156 if t: buildvms(['--vms', 'server', '--builds', 'product', '--check-distributions'])
1331 157
1332 # Run unit tests on server-hosted-jvmci 158 # Run unit tests on server-hosted-jvmci
1405 # ensure -Xcomp still works 231 # ensure -Xcomp still works
1406 with VM('jvmci', 'product'): 232 with VM('jvmci', 'product'):
1407 with Task('XCompMode:product', tasks) as t: 233 with Task('XCompMode:product', tasks) as t:
1408 if t: vm(['-Xcomp', '-version']) 234 if t: vm(['-Xcomp', '-version'])
1409 235
1410 if args.jacocout is not None:
1411 jacocoreport([args.jacocout])
1412
1413 global _jacoco
1414 _jacoco = 'off'
1415
1416 with Task('CleanAndBuildIdealGraphVisualizer', tasks) as t:
1417 if t and platform.processor() != 'sparc':
1418 buildxml = mx._cygpathU2W(join(_graal_home, 'src', 'share', 'tools', 'IdealGraphVisualizer', 'build.xml'))
1419 mx.run(['ant', '-f', buildxml, '-q', 'clean', 'build'], env=_igvBuildEnv())
1420
1421 # Prevent JVMCI modifications from breaking the standard builds 236 # Prevent JVMCI modifications from breaking the standard builds
1422 if args.buildNonJVMCI: 237 if args.buildNonJVMCI:
1423 with Task('BuildHotSpotVarieties', tasks) as t:
1424 if t:
1425 buildvms(['--vms', 'client,server', '--builds', 'fastdebug,product'])
1426 if mx.get_os() not in ['windows', 'cygwin']:
1427 buildvms(['--vms', 'server-nojvmci', '--builds', 'product,optimized'])
1428
1429 for vmbuild in ['product', 'fastdebug']: 238 for vmbuild in ['product', 'fastdebug']:
1430 for theVm in ['client', 'server']: 239 for theVm in ['client', 'server']:
1431 if not isVMSupported(theVm): 240 if not isVMSupported(theVm):
1432 mx.log('The ' + theVm + ' VM is not supported on this platform') 241 mx.log('The ' + theVm + ' VM is not supported on this platform')
1433 continue 242 continue
1436 if t: dacapo(['pmd']) 245 if t: dacapo(['pmd'])
1437 246
1438 with Task('UnitTests:' + theVm + ':' + vmbuild, tasks) as t: 247 with Task('UnitTests:' + theVm + ':' + vmbuild, tasks) as t:
1439 if t: unittest(['-XX:CompileCommand=exclude,*::run*', 'graal.api', 'java.test']) 248 if t: unittest(['-XX:CompileCommand=exclude,*::run*', 'graal.api', 'java.test'])
1440 249
1441
1442 def gate(args, gate_body=_basic_gate_body):
1443 """run the tests used to validate a push
1444
1445 If this command exits with a 0 exit code, then the source code is in
1446 a state that would be accepted for integration into the main repository."""
1447
1448 parser = ArgumentParser(prog='mx gate')
1449 parser.add_argument('-j', '--omit-java-clean', action='store_false', dest='cleanJava', help='omit cleaning Java native code')
1450 parser.add_argument('-n', '--omit-native-clean', action='store_false', dest='cleanNative', help='omit cleaning and building native code')
1451 parser.add_argument('-i', '--omit-ide-clean', action='store_false', dest='cleanIde', help='omit cleaning the ide project files')
1452 parser.add_argument('-g', '--only-build-jvmci', action='store_false', dest='buildNonJVMCI', help='only build the JVMCI VM')
1453 parser.add_argument('-t', '--task-filter', help='comma separated list of substrings to select subset of tasks to be run')
1454 parser.add_argument('-x', action='store_true', help='makes --task-filter an exclusion instead of inclusion filter')
1455 parser.add_argument('--jacocout', help='specify the output directory for jacoco report')
1456
1457 args = parser.parse_args(args)
1458
1459 global _jacoco
1460 if args.task_filter:
1461 Task.filters = args.task_filter.split(',')
1462 Task.filtersExclude = args.x
1463 elif args.x:
1464 mx.abort('-x option cannot be used without --task-filter option')
1465
1466 # Force
1467 if not mx._opts.strict_compliance:
1468 mx.log("[gate] forcing strict compliance")
1469 mx._opts.strict_compliance = True
1470
1471 tasks = []
1472 total = Task('Gate')
1473 try:
1474 with Task('Check jvmci.make in sync with suite.py', tasks) as t:
1475 if t:
1476 jvmciMake = join('make', 'jvmci.make')
1477 if mx_graal_makefile.build_makefile(['-o', jvmciMake]) != 0:
1478 t.abort('Rerun "mx makefile -o ' + jvmciMake + ' and check-in the modified ' + jvmciMake)
1479
1480 with Task('Pylint', tasks) as t:
1481 if t: mx.pylint([])
1482
1483 def _clean(name='Clean'):
1484 with Task(name, tasks) as t:
1485 if t:
1486 cleanArgs = []
1487 if not args.cleanNative:
1488 cleanArgs.append('--no-native')
1489 if not args.cleanJava:
1490 cleanArgs.append('--no-java')
1491 clean(cleanArgs)
1492 _clean()
1493
1494 with Task('IDEConfigCheck', tasks) as t:
1495 if t:
1496 if args.cleanIde:
1497 mx.ideclean([])
1498 mx.ideinit([])
1499
1500 eclipse_exe = mx.get_env('ECLIPSE_EXE')
1501 if eclipse_exe is not None:
1502 with Task('CodeFormatCheck', tasks) as t:
1503 if t and mx.eclipseformat(['-e', eclipse_exe]) != 0:
1504 t.abort('Formatter modified files - run "mx eclipseformat", check in changes and repush')
1505
1506 with Task('Canonicalization Check', tasks) as t:
1507 if t:
1508 mx.log(time.strftime('%d %b %Y %H:%M:%S - Ensuring mx/projects files are canonicalized...'))
1509 if mx.canonicalizeprojects([]) != 0:
1510 t.abort('Rerun "mx canonicalizeprojects" and check-in the modified mx/suite*.py files.')
1511
1512 if mx.get_env('JDT'):
1513 with Task('BuildJavaWithEcj', tasks):
1514 if t: build(['-p', '--no-native', '--jdt-warning-as-error'])
1515 _clean('CleanAfterEcjBuild')
1516
1517 with Task('BuildJavaWithJavac', tasks):
1518 if t: build(['-p', '--no-native', '--force-javac'])
1519
1520 with Task('Checkstyle', tasks) as t:
1521 if t and mx.checkstyle([]) != 0:
1522 t.abort('Checkstyle warnings were found')
1523
1524 with Task('Checkheaders', tasks) as t:
1525 if t and checkheaders([]) != 0:
1526 t.abort('Checkheaders warnings were found')
1527
1528 with Task('FindBugs', tasks) as t:
1529 if t and mx_findbugs.findbugs([]) != 0:
1530 t.abort('FindBugs warnings were found')
1531
1532 if exists('jacoco.exec'):
1533 os.unlink('jacoco.exec')
1534
1535 if args.jacocout is not None:
1536 _jacoco = 'append'
1537 else:
1538 _jacoco = 'off'
1539
1540 gate_body(args, tasks)
1541
1542 except KeyboardInterrupt:
1543 total.abort(1)
1544
1545 except BaseException as e:
1546 import traceback
1547 traceback.print_exc()
1548 total.abort(str(e))
1549
1550 total.stop()
1551
1552 mx.log('Gate task times:')
1553 for t in tasks:
1554 mx.log(' ' + str(t.duration) + '\t' + t.title)
1555 mx.log(' =======')
1556 mx.log(' ' + str(total.duration))
1557
1558 if args.task_filter:
1559 Task.filters = None
1560
1561 def deoptalot(args): 250 def deoptalot(args):
1562 """bootstrap a VM with DeoptimizeALot and VerifyOops on 251 """bootstrap a VM with DeoptimizeALot and VerifyOops on
1563 252
1564 If the first argument is a number, the process will be repeated 253 If the first argument is a number, the process will be repeated
1565 this number of times. All other arguments are passed to the VM.""" 254 this number of times. All other arguments are passed to the VM."""
1575 def longtests(args): 264 def longtests(args):
1576 265
1577 deoptalot(['15', '-Xmx48m']) 266 deoptalot(['15', '-Xmx48m'])
1578 267
1579 dacapo(['100', 'eclipse', '-esa']) 268 dacapo(['100', 'eclipse', '-esa'])
1580
1581 def _igvJdk():
1582 v8u20 = mx.VersionSpec("1.8.0_20")
1583 v8u40 = mx.VersionSpec("1.8.0_40")
1584 v8 = mx.VersionSpec("1.8")
1585 def _igvJdkVersionCheck(version):
1586 return version >= v8 and (version < v8u20 or version >= v8u40)
1587 return mx.java(_igvJdkVersionCheck, versionDescription='>= 1.8 and < 1.8.0u20 or >= 1.8.0u40', purpose="building & running IGV").jdk
1588
1589 def _igvBuildEnv():
1590 # When the http_proxy environment variable is set, convert it to the proxy settings that ant needs
1591 env = dict(os.environ)
1592 proxy = os.environ.get('http_proxy')
1593 if not (proxy is None) and len(proxy) > 0:
1594 if '://' in proxy:
1595 # Remove the http:// prefix (or any other protocol prefix)
1596 proxy = proxy.split('://', 1)[1]
1597 # Separate proxy server name and port number
1598 proxyName, proxyPort = proxy.split(':', 1)
1599 proxyEnv = '-DproxyHost="' + proxyName + '" -DproxyPort=' + proxyPort
1600 env['ANT_OPTS'] = proxyEnv
1601
1602 env['JAVA_HOME'] = _igvJdk()
1603 return env
1604
1605 def igv(args):
1606 """run the Ideal Graph Visualizer"""
1607 logFile = '.ideal_graph_visualizer.log'
1608 with open(join(_graal_home, logFile), 'w') as fp:
1609 mx.logv('[Ideal Graph Visualizer log is in ' + fp.name + ']')
1610 nbplatform = join(_graal_home, 'src', 'share', 'tools', 'IdealGraphVisualizer', 'nbplatform')
1611
1612 # Remove NetBeans platform if it is earlier than the current supported version
1613 if exists(nbplatform):
1614 updateTrackingFile = join(nbplatform, 'platform', 'update_tracking', 'org-netbeans-core.xml')
1615 if not exists(updateTrackingFile):
1616 mx.log('Could not find \'' + updateTrackingFile + '\', removing NetBeans platform')
1617 shutil.rmtree(nbplatform)
1618 else:
1619 dom = xml.dom.minidom.parse(updateTrackingFile)
1620 currentVersion = mx.VersionSpec(dom.getElementsByTagName('module_version')[0].getAttribute('specification_version'))
1621 supportedVersion = mx.VersionSpec('3.43.1')
1622 if currentVersion < supportedVersion:
1623 mx.log('Replacing NetBeans platform version ' + str(currentVersion) + ' with version ' + str(supportedVersion))
1624 shutil.rmtree(nbplatform)
1625 elif supportedVersion < currentVersion:
1626 mx.log('Supported NetBeans version in igv command should be updated to ' + str(currentVersion))
1627
1628 if not exists(nbplatform):
1629 mx.logv('[This execution may take a while as the NetBeans platform needs to be downloaded]')
1630
1631 env = _igvBuildEnv()
1632 # make the jar for Batik 1.7 available.
1633 env['IGV_BATIK_JAR'] = mx.library('BATIK').get_path(True)
1634 if mx.run(['ant', '-f', mx._cygpathU2W(join(_graal_home, 'src', 'share', 'tools', 'IdealGraphVisualizer', 'build.xml')), '-l', mx._cygpathU2W(fp.name), 'run'], env=env, nonZeroIsFatal=False):
1635 mx.abort("IGV ant build & launch failed. Check '" + logFile + "'. You can also try to delete 'src/share/tools/IdealGraphVisualizer/nbplatform'.")
1636
1637 def c1visualizer(args):
1638 """run the Cl Compiler Visualizer"""
1639 libpath = join(_graal_home, 'lib')
1640 if mx.get_os() == 'windows':
1641 executable = join(libpath, 'c1visualizer', 'bin', 'c1visualizer.exe')
1642 else:
1643 executable = join(libpath, 'c1visualizer', 'bin', 'c1visualizer')
1644
1645 # Check whether the current C1Visualizer installation is the up-to-date
1646 if exists(executable) and not exists(mx.library('C1VISUALIZER_DIST').get_path(resolve=False)):
1647 mx.log('Updating C1Visualizer')
1648 shutil.rmtree(join(libpath, 'c1visualizer'))
1649
1650 archive = mx.library('C1VISUALIZER_DIST').get_path(resolve=True)
1651
1652 if not exists(executable):
1653 zf = zipfile.ZipFile(archive, 'r')
1654 zf.extractall(libpath)
1655
1656 if not exists(executable):
1657 mx.abort('C1Visualizer binary does not exist: ' + executable)
1658
1659 if mx.get_os() != 'windows':
1660 # Make sure that execution is allowed. The zip file does not always specfiy that correctly
1661 os.chmod(executable, 0777)
1662
1663 mx.run([executable])
1664 269
1665 def bench(args): 270 def bench(args):
1666 """run benchmarks and parse their output for results 271 """run benchmarks and parse their output for results
1667 272
1668 Results are JSON formated : {group : {benchmark : score}}.""" 273 Results are JSON formated : {group : {benchmark : score}}."""
1673 resultFile = args[index + 1] 278 resultFile = args[index + 1]
1674 del args[index] 279 del args[index]
1675 del args[index] 280 del args[index]
1676 else: 281 else:
1677 mx.abort('-resultfile must be followed by a file name') 282 mx.abort('-resultfile must be followed by a file name')
1678 vm = _get_vm() 283 vm = get_vm()
1679 if len(args) is 0: 284 if len(args) is 0:
1680 args = ['all'] 285 args = ['all']
1681 286
1682 vmArgs = [arg for arg in args if arg.startswith('-')] 287 vmArgs = [arg for arg in args if arg.startswith('-')]
1683 288
1739 mx.log(json.dumps(results)) 344 mx.log(json.dumps(results))
1740 if resultFile: 345 if resultFile:
1741 with open(resultFile, 'w') as f: 346 with open(resultFile, 'w') as f:
1742 f.write(json.dumps(results)) 347 f.write(json.dumps(results))
1743 348
1744 def _get_jmh_path():
1745 path = mx.get_env('JMH_BENCHMARKS', None)
1746 if not path:
1747 probe = join(dirname(_graal_home), 'java-benchmarks')
1748 if exists(probe):
1749 path = probe
1750
1751 if not path:
1752 mx.abort("Please set the JMH_BENCHMARKS environment variable to point to the java-benchmarks workspace")
1753 if not exists(path):
1754 mx.abort("The directory denoted by the JMH_BENCHMARKS environment variable does not exist: " + path)
1755 return path
1756
1757 def makejmhdeps(args):
1758 """creates and installs Maven dependencies required by the JMH benchmarks
1759
1760 The dependencies are specified by files named pom.mxdeps in the
1761 JMH directory tree. Each such file contains a list of dependencies
1762 defined in JSON format. For example:
1763
1764 '[{"artifactId" : "compiler.test", "groupId" : "com.oracle.graal", "deps" : ["com.oracle.graal.compiler.test"]}]'
1765
1766 will result in a dependency being installed in the local Maven repository
1767 that can be referenced in a pom.xml file as follows:
1768
1769 <dependency>
1770 <groupId>com.oracle.graal</groupId>
1771 <artifactId>compiler.test</artifactId>
1772 <version>1.0-SNAPSHOT</version>
1773 </dependency>"""
1774
1775 parser = ArgumentParser(prog='mx makejmhdeps')
1776 parser.add_argument('-s', '--settings', help='alternative path for Maven user settings file', metavar='<path>')
1777 parser.add_argument('-p', '--permissive', action='store_true', help='issue note instead of error if a Maven dependency cannot be built due to missing projects/libraries')
1778 args = parser.parse_args(args)
1779
1780 def makejmhdep(artifactId, groupId, deps):
1781 graalSuite = mx.suite("graal")
1782 path = artifactId + '.jar'
1783 if args.permissive:
1784 allDeps = []
1785 for name in deps:
1786 dist = mx.distribution(name, fatalIfMissing=False)
1787 if dist:
1788 allDeps = allDeps + [d.name for d in dist.sorted_deps(transitive=True)]
1789 else:
1790 if not mx.project(name, fatalIfMissing=False):
1791 if not mx.library(name, fatalIfMissing=False):
1792 mx.log('Skipping dependency ' + groupId + '.' + artifactId + ' as ' + name + ' cannot be resolved')
1793 return
1794 allDeps.append(name)
1795 d = mx.Distribution(graalSuite, name=artifactId, path=path, sourcesPath=path, deps=allDeps, mainClass=None, excludedDependencies=[], distDependencies=[], javaCompliance=None)
1796 d.make_archive()
1797 cmd = ['mvn', 'install:install-file', '-DgroupId=' + groupId, '-DartifactId=' + artifactId,
1798 '-Dversion=1.0-SNAPSHOT', '-Dpackaging=jar', '-Dfile=' + d.path]
1799 if not mx._opts.verbose:
1800 cmd.append('-q')
1801 if args.settings:
1802 cmd = cmd + ['-s', args.settings]
1803 mx.run(cmd)
1804 os.unlink(d.path)
1805
1806 jmhPath = _get_jmh_path()
1807 for root, _, filenames in os.walk(jmhPath):
1808 for f in [join(root, n) for n in filenames if n == 'pom.mxdeps']:
1809 mx.logv('[processing ' + f + ']')
1810 try:
1811 with open(f) as fp:
1812 for d in json.load(fp):
1813 artifactId = d['artifactId']
1814 groupId = d['groupId']
1815 deps = d['deps']
1816 makejmhdep(artifactId, groupId, deps)
1817 except ValueError as e:
1818 mx.abort('Error parsing {0}:\n{1}'.format(f, e))
1819
1820 def buildjmh(args):
1821 """build the JMH benchmarks"""
1822
1823 parser = ArgumentParser(prog='mx buildjmh')
1824 parser.add_argument('-s', '--settings', help='alternative path for Maven user settings file', metavar='<path>')
1825 parser.add_argument('-c', action='store_true', dest='clean', help='clean before building')
1826 args = parser.parse_args(args)
1827
1828 jmhPath = _get_jmh_path()
1829 mx.log('JMH benchmarks: ' + jmhPath)
1830
1831 # Ensure the mx injected dependencies are up to date
1832 makejmhdeps(['-p'] + (['-s', args.settings] if args.settings else []))
1833
1834 timestamp = mx.TimeStampFile(join(_suite.mxDir, 'jmh', jmhPath.replace(os.sep, '_') + '.timestamp'))
1835 mustBuild = args.clean
1836 if not mustBuild:
1837 try:
1838 hgfiles = [join(jmhPath, f) for f in subprocess.check_output(['hg', '-R', jmhPath, 'locate']).split('\n')]
1839 mustBuild = timestamp.isOlderThan(hgfiles)
1840 except:
1841 # not a Mercurial repository or hg commands are not available.
1842 mustBuild = True
1843
1844 if mustBuild:
1845 buildOutput = []
1846 def _redirect(x):
1847 if mx._opts.verbose:
1848 mx.log(x[:-1])
1849 else:
1850 buildOutput.append(x)
1851 env = os.environ.copy()
1852 env['JAVA_HOME'] = _jdk(vmToCheck='server')
1853 env['MAVEN_OPTS'] = '-server -XX:-UseJVMCIClassLoader'
1854 mx.log("Building benchmarks...")
1855 cmd = ['mvn']
1856 if args.settings:
1857 cmd = cmd + ['-s', args.settings]
1858 if args.clean:
1859 cmd.append('clean')
1860 cmd.append('package')
1861 retcode = mx.run(cmd, cwd=jmhPath, out=_redirect, env=env, nonZeroIsFatal=False)
1862 if retcode != 0:
1863 mx.log(''.join(buildOutput))
1864 mx.abort(retcode)
1865 timestamp.touch()
1866 else:
1867 mx.logv('[all Mercurial controlled files in ' + jmhPath + ' are older than ' + timestamp.path + ' - skipping build]')
1868
1869 def jmh(args):
1870 """run the JMH benchmarks
1871
1872 This command respects the standard --vm and --vmbuild options
1873 for choosing which VM to run the benchmarks with."""
1874 if '-h' in args:
1875 mx.help_(['jmh'])
1876 mx.abort(1)
1877
1878 vmArgs, benchmarksAndJsons = mx.extract_VM_args(args)
1879 if isJVMCIEnabled(_get_vm()) and '-XX:-UseJVMCIClassLoader' not in vmArgs:
1880 vmArgs = ['-XX:-UseJVMCIClassLoader'] + vmArgs
1881
1882 benchmarks = [b for b in benchmarksAndJsons if not b.startswith('{')]
1883 jmhArgJsons = [b for b in benchmarksAndJsons if b.startswith('{')]
1884 jmhOutDir = join(_suite.mxDir, 'jmh')
1885 if not exists(jmhOutDir):
1886 os.makedirs(jmhOutDir)
1887 jmhOut = join(jmhOutDir, 'jmh.out')
1888 jmhArgs = {'-rff' : jmhOut, '-v' : 'EXTRA' if mx._opts.verbose else 'NORMAL'}
1889
1890 # e.g. '{"-wi" : 20}'
1891 for j in jmhArgJsons:
1892 try:
1893 for n, v in json.loads(j).iteritems():
1894 if v is None:
1895 del jmhArgs[n]
1896 else:
1897 jmhArgs[n] = v
1898 except ValueError as e:
1899 mx.abort('error parsing JSON input: {0}\n{1}'.format(j, e))
1900
1901 jmhPath = _get_jmh_path()
1902 mx.log('Using benchmarks in ' + jmhPath)
1903
1904 matchedSuites = set()
1905 numBench = [0]
1906 for micros in os.listdir(jmhPath):
1907 absoluteMicro = os.path.join(jmhPath, micros)
1908 if not os.path.isdir(absoluteMicro):
1909 continue
1910 if not micros.startswith("micros-"):
1911 mx.logv('JMH: ignored ' + absoluteMicro + " because it doesn't start with 'micros-'")
1912 continue
1913
1914 microJar = os.path.join(absoluteMicro, "target", "microbenchmarks.jar")
1915 if not exists(microJar):
1916 mx.log('Missing ' + microJar + ' - please run "mx buildjmh"')
1917 continue
1918 if benchmarks:
1919 def _addBenchmark(x):
1920 if x.startswith("Benchmark:"):
1921 return
1922 match = False
1923 for b in benchmarks:
1924 match = match or (b in x)
1925
1926 if match:
1927 numBench[0] += 1
1928 matchedSuites.add(micros)
1929
1930 mx.run_java(['-jar', microJar, "-l"], cwd=jmhPath, out=_addBenchmark, addDefaultArgs=False)
1931 else:
1932 matchedSuites.add(micros)
1933
1934 mx.logv("matchedSuites: " + str(matchedSuites))
1935 plural = 's' if not benchmarks or numBench[0] > 1 else ''
1936 number = str(numBench[0]) if benchmarks else "all"
1937 mx.log("Running " + number + " benchmark" + plural + '...')
1938
1939 regex = []
1940 if benchmarks:
1941 regex.append(r".*(" + "|".join(benchmarks) + ").*")
1942
1943 for suite in matchedSuites:
1944 absoluteMicro = os.path.join(jmhPath, suite)
1945 (pfx, exe, vm, forkedVmArgs, _) = _parseVmArgs(vmArgs)
1946 if pfx:
1947 mx.log("JMH ignores prefix: \"" + ' '.join(pfx) + "\"")
1948 javaArgs = ['-jar', os.path.join(absoluteMicro, "target", "microbenchmarks.jar"),
1949 '--jvm', exe,
1950 '--jvmArgs', ' '.join(["-" + vm] + forkedVmArgs)]
1951 for k, v in jmhArgs.iteritems():
1952 javaArgs.append(k)
1953 if len(str(v)):
1954 javaArgs.append(str(v))
1955 mx.run_java(javaArgs + regex, addDefaultArgs=False, cwd=jmhPath)
1956
1957 def specjvm2008(args): 349 def specjvm2008(args):
1958 """run one or more SPECjvm2008 benchmarks""" 350 """run one or more SPECjvm2008 benchmarks"""
1959 351
1960 def launcher(bm, harnessArgs, extraVmOpts): 352 def launcher(bm, harnessArgs, extraVmOpts):
1961 return sanitycheck.getSPECjvm2008(harnessArgs + [bm]).bench(_get_vm(), extraVmOpts=extraVmOpts) 353 return sanitycheck.getSPECjvm2008(harnessArgs + [bm]).bench(get_vm(), extraVmOpts=extraVmOpts)
1962 354
1963 availableBenchmarks = set(sanitycheck.specjvm2008Names) 355 availableBenchmarks = set(sanitycheck.specjvm2008Names)
1964 for name in sanitycheck.specjvm2008Names: 356 for name in sanitycheck.specjvm2008Names:
1965 parts = name.rsplit('.', 1) 357 parts = name.rsplit('.', 1)
1966 if len(parts) > 1: 358 if len(parts) > 1:
1973 def specjbb2013(args): 365 def specjbb2013(args):
1974 """run the composite SPECjbb2013 benchmark""" 366 """run the composite SPECjbb2013 benchmark"""
1975 367
1976 def launcher(bm, harnessArgs, extraVmOpts): 368 def launcher(bm, harnessArgs, extraVmOpts):
1977 assert bm is None 369 assert bm is None
1978 return sanitycheck.getSPECjbb2013(harnessArgs).bench(_get_vm(), extraVmOpts=extraVmOpts) 370 return sanitycheck.getSPECjbb2013(harnessArgs).bench(get_vm(), extraVmOpts=extraVmOpts)
1979 371
1980 _run_benchmark(args, None, launcher) 372 _run_benchmark(args, None, launcher)
1981 373
1982 def specjbb2005(args): 374 def specjbb2005(args):
1983 """run the composite SPECjbb2005 benchmark""" 375 """run the composite SPECjbb2005 benchmark"""
1984 376
1985 def launcher(bm, harnessArgs, extraVmOpts): 377 def launcher(bm, harnessArgs, extraVmOpts):
1986 assert bm is None 378 assert bm is None
1987 return sanitycheck.getSPECjbb2005(harnessArgs).bench(_get_vm(), extraVmOpts=extraVmOpts) 379 return sanitycheck.getSPECjbb2005(harnessArgs).bench(get_vm(), extraVmOpts=extraVmOpts)
1988 380
1989 _run_benchmark(args, None, launcher) 381 _run_benchmark(args, None, launcher)
1990
1991 def hsdis(args, copyToDir=None):
1992 """download the hsdis library
1993
1994 This is needed to support HotSpot's assembly dumping features.
1995 By default it downloads the Intel syntax version, use the 'att' argument to install AT&T syntax."""
1996 flavor = 'intel'
1997 if 'att' in args:
1998 flavor = 'att'
1999 if mx.get_arch() == "sparcv9":
2000 flavor = "sparcv9"
2001 lib = mx.add_lib_suffix('hsdis-' + mx.get_arch())
2002 path = join(_graal_home, 'lib', lib)
2003
2004 sha1s = {
2005 'att/hsdis-amd64.dll' : 'bcbd535a9568b5075ab41e96205e26a2bac64f72',
2006 'att/hsdis-amd64.so' : '58919ba085d4ef7a513f25bae75e7e54ee73c049',
2007 'intel/hsdis-amd64.dll' : '6a388372cdd5fe905c1a26ced614334e405d1f30',
2008 'intel/hsdis-amd64.so' : '844ed9ffed64fe9599638f29a8450c50140e3192',
2009 'intel/hsdis-amd64.dylib' : 'fdb13ef0d7d23d93dacaae9c98837bea0d4fc5a2',
2010 'sparcv9/hsdis-sparcv9.so': '970640a9af0bd63641f9063c11275b371a59ee60',
2011 }
2012
2013 flavoredLib = flavor + "/" + lib
2014 if flavoredLib not in sha1s:
2015 mx.logv("hsdis not supported on this plattform or architecture")
2016 return
2017
2018 if not exists(path):
2019 sha1 = sha1s[flavoredLib]
2020 sha1path = path + '.sha1'
2021 mx.download_file_with_sha1('hsdis', path, ['http://lafo.ssw.uni-linz.ac.at/hsdis/' + flavoredLib], sha1, sha1path, True, True, sources=False)
2022 if copyToDir is not None and exists(copyToDir):
2023 shutil.copy(path, copyToDir)
2024
2025 def hcfdis(args):
2026 """disassemble HexCodeFiles embedded in text files
2027
2028 Run a tool over the input files to convert all embedded HexCodeFiles
2029 to a disassembled format."""
2030
2031 parser = ArgumentParser(prog='mx hcfdis')
2032 parser.add_argument('-m', '--map', help='address to symbol map applied to disassembler output')
2033 parser.add_argument('files', nargs=REMAINDER, metavar='files...')
2034
2035 args = parser.parse_args(args)
2036
2037 path = mx.library('HCFDIS').get_path(resolve=True)
2038 mx.run_java(['-cp', path, 'com.oracle.max.hcfdis.HexCodeFileDis'] + args.files)
2039
2040 if args.map is not None:
2041 addressRE = re.compile(r'0[xX]([A-Fa-f0-9]+)')
2042 with open(args.map) as fp:
2043 lines = fp.read().splitlines()
2044 symbols = dict()
2045 for l in lines:
2046 addressAndSymbol = l.split(' ', 1)
2047 if len(addressAndSymbol) == 2:
2048 address, symbol = addressAndSymbol
2049 if address.startswith('0x'):
2050 address = long(address, 16)
2051 symbols[address] = symbol
2052 for f in args.files:
2053 with open(f) as fp:
2054 lines = fp.read().splitlines()
2055 updated = False
2056 for i in range(0, len(lines)):
2057 l = lines[i]
2058 for m in addressRE.finditer(l):
2059 sval = m.group(0)
2060 val = long(sval, 16)
2061 sym = symbols.get(val)
2062 if sym:
2063 l = l.replace(sval, sym)
2064 updated = True
2065 lines[i] = l
2066 if updated:
2067 mx.log('updating ' + f)
2068 with open('new_' + f, "w") as fp:
2069 for l in lines:
2070 print >> fp, l
2071
2072 def jacocoreport(args):
2073 """create a JaCoCo coverage report
2074
2075 Creates the report from the 'jacoco.exec' file in the current directory.
2076 Default output directory is 'coverage', but an alternative can be provided as an argument."""
2077 jacocoreport = mx.library("JACOCOREPORT", True)
2078 out = 'coverage'
2079 if len(args) == 1:
2080 out = args[0]
2081 elif len(args) > 1:
2082 mx.abort('jacocoreport takes only one argument : an output directory')
2083
2084 includes = ['com.oracle.graal', 'jdk.internal.jvmci']
2085 for p in mx.projects():
2086 projsetting = getattr(p, 'jacoco', '')
2087 if projsetting == 'include':
2088 includes.append(p.name)
2089
2090 includedirs = set()
2091 for p in mx.projects():
2092 projsetting = getattr(p, 'jacoco', '')
2093 if projsetting == 'exclude':
2094 continue
2095 for include in includes:
2096 if include in p.dir:
2097 includedirs.add(p.dir)
2098
2099 for i in includedirs:
2100 bindir = i + '/bin'
2101 if not os.path.exists(bindir):
2102 os.makedirs(bindir)
2103
2104 mx.run_java(['-jar', jacocoreport.get_path(True), '--in', 'jacoco.exec', '--out', out] + sorted(includedirs))
2105
2106 def isJVMCIEnabled(vm):
2107 return vm != 'original' and not vm.endswith('nojvmci')
2108
2109 def jol(args):
2110 """Java Object Layout"""
2111 joljar = mx.library('JOL_INTERNALS').get_path(resolve=True)
2112 candidates = mx.findclass(args, logToConsole=False, matcher=lambda s, classname: s == classname or classname.endswith('.' + s) or classname.endswith('$' + s))
2113
2114 if len(candidates) > 0:
2115 candidates = mx.select_items(sorted(candidates))
2116 else:
2117 # mx.findclass can be mistaken, don't give up yet
2118 candidates = args
2119
2120 vm(['-javaagent:' + joljar, '-cp', os.pathsep.join([mx.classpath(), joljar]), "org.openjdk.jol.MainObjectInternals"] + candidates)
2121
2122 def site(args):
2123 """create a website containing javadoc and the project dependency graph"""
2124
2125 return mx.site(['--name', 'Graal',
2126 '--jd', '@-tag', '--jd', '@test:X',
2127 '--jd', '@-tag', '--jd', '@run:X',
2128 '--jd', '@-tag', '--jd', '@bug:X',
2129 '--jd', '@-tag', '--jd', '@summary:X',
2130 '--jd', '@-tag', '--jd', '@vmoption:X',
2131 '--overview', join(_graal_home, 'graal', 'overview.html'),
2132 '--title', 'Graal OpenJDK Project Documentation',
2133 '--dot-output-base', 'projects'] + args)
2134
2135 def generateZshCompletion(args):
2136 """generate zsh completion for mx"""
2137 try:
2138 from genzshcomp import CompletionGenerator
2139 except ImportError:
2140 mx.abort("install genzshcomp (pip install genzshcomp)")
2141
2142 # need to fake module for the custom mx arg parser, otherwise a check in genzshcomp fails
2143 originalModule = mx._argParser.__module__
2144 mx._argParser.__module__ = "argparse"
2145 generator = CompletionGenerator("mx", mx._argParser)
2146 mx._argParser.__module__ = originalModule
2147
2148 # strip last line and define local variable "ret"
2149 complt = "\n".join(generator.get().split('\n')[0:-1]).replace('context state line', 'context state line ret=1')
2150
2151 # add array of possible subcommands (as they are not part of the argument parser)
2152 complt += '\n ": :->command" \\\n'
2153 complt += ' "*::args:->args" && ret=0\n'
2154 complt += '\n'
2155 complt += 'case $state in\n'
2156 complt += '\t(command)\n'
2157 complt += '\t\tlocal -a main_commands\n'
2158 complt += '\t\tmain_commands=(\n'
2159 for cmd in sorted(mx._commands.iterkeys()):
2160 c, _ = mx._commands[cmd][:2]
2161 doc = c.__doc__
2162 complt += '\t\t\t"{0}'.format(cmd)
2163 if doc:
2164 complt += ':{0}'.format(_fixQuotes(doc.split('\n', 1)[0]))
2165 complt += '"\n'
2166 complt += '\t\t)\n'
2167 complt += '\t\t_describe -t main_commands command main_commands && ret=0\n'
2168 complt += '\t\t;;\n'
2169
2170 complt += '\t(args)\n'
2171 # TODO: improve matcher: if mx args are given, this doesn't work
2172 complt += '\t\tcase $line[1] in\n'
2173 complt += '\t\t\t(vm | vmg | vmfg | unittest | jmh | dacapo | scaladacapo | specjvm2008 | specjbb2013 | specjbb2005)\n'
2174 complt += '\t\t\t\tnoglob \\\n'
2175 complt += '\t\t\t\t\t_arguments -s -S \\\n'
2176 complt += _appendOptions("jvmci", r"G\:")
2177 # TODO: fix -XX:{-,+}Use* flags
2178 complt += _appendOptions("hotspot", r"XX\:")
2179 complt += '\t\t\t\t\t"-version" && ret=0 \n'
2180 complt += '\t\t\t\t;;\n'
2181 complt += '\t\tesac\n'
2182 complt += '\t\t;;\n'
2183 complt += 'esac\n'
2184 complt += '\n'
2185 complt += 'return $ret'
2186 print complt
2187
2188 def _fixQuotes(arg):
2189 return arg.replace('\"', '').replace('\'', '').replace('`', '').replace('{', '\\{').replace('}', '\\}').replace('[', '\\[').replace(']', '\\]')
2190
2191 def _appendOptions(optionType, optionPrefix):
2192 def isBoolean(vmap, field):
2193 return vmap[field] == "Boolean" or vmap[field] == "bool"
2194
2195 def hasDescription(vmap):
2196 return vmap['optDefault'] or vmap['optDoc']
2197
2198 complt = ""
2199 for vmap in _parseVMOptions(optionType):
2200 complt += '\t\t\t\t\t-"'
2201 complt += optionPrefix
2202 if isBoolean(vmap, 'optType'):
2203 complt += '"{-,+}"'
2204 complt += vmap['optName']
2205 if not isBoolean(vmap, 'optType'):
2206 complt += '='
2207 if hasDescription(vmap):
2208 complt += "["
2209 if vmap['optDefault']:
2210 complt += r"(default\: " + vmap['optDefault'] + ")"
2211 if vmap['optDoc']:
2212 complt += _fixQuotes(vmap['optDoc'])
2213 if hasDescription(vmap):
2214 complt += "]"
2215 complt += '" \\\n'
2216 return complt
2217
2218 def _parseVMOptions(optionType):
2219 parser = OutputParser()
2220 # TODO: the optDoc part can wrapped accross multiple lines, currently only the first line will be captured
2221 # TODO: fix matching for float literals
2222 jvmOptions = re.compile(
2223 r"^[ \t]*"
2224 r"(?P<optType>(Boolean|Integer|Float|Double|String|bool|intx|uintx|ccstr|double)) "
2225 r"(?P<optName>[a-zA-Z0-9]+)"
2226 r"[ \t]+=[ \t]*"
2227 r"(?P<optDefault>([\-0-9]+(\.[0-9]+(\.[0-9]+\.[0-9]+))?|false|true|null|Name|sun\.boot\.class\.path))?"
2228 r"[ \t]*"
2229 r"(?P<optDoc>.+)?",
2230 re.MULTILINE)
2231 parser.addMatcher(ValuesMatcher(jvmOptions, {
2232 'optType' : '<optType>',
2233 'optName' : '<optName>',
2234 'optDefault' : '<optDefault>',
2235 'optDoc' : '<optDoc>',
2236 }))
2237
2238 # gather JVMCI options
2239 output = StringIO.StringIO()
2240 vm(['-XX:-BootstrapJVMCI', '-XX:+UnlockDiagnosticVMOptions', '-G:+PrintFlags' if optionType == "jvmci" else '-XX:+PrintFlagsWithComments'],
2241 vm="jvmci",
2242 vmbuild="optimized",
2243 nonZeroIsFatal=False,
2244 out=output.write,
2245 err=subprocess.STDOUT)
2246
2247 valueMap = parser.parse(output.getvalue())
2248 return valueMap
2249
2250 def checkheaders(args):
2251 """check Java source headers against any required pattern"""
2252 failures = {}
2253 for p in mx.projects():
2254 if p.native:
2255 continue
2256
2257 csConfig = join(mx.project(p.checkstyleProj).dir, '.checkstyle_checks.xml')
2258 if not exists(csConfig):
2259 mx.log('Cannot check headers for ' + p.name + ' - ' + csConfig + ' does not exist')
2260 continue
2261 dom = xml.dom.minidom.parse(csConfig)
2262 for module in dom.getElementsByTagName('module'):
2263 if module.getAttribute('name') == 'RegexpHeader':
2264 for prop in module.getElementsByTagName('property'):
2265 if prop.getAttribute('name') == 'header':
2266 value = prop.getAttribute('value')
2267 matcher = re.compile(value, re.MULTILINE)
2268 for sourceDir in p.source_dirs():
2269 for root, _, files in os.walk(sourceDir):
2270 for name in files:
2271 if name.endswith('.java') and name != 'package-info.java':
2272 f = join(root, name)
2273 with open(f) as fp:
2274 content = fp.read()
2275 if not matcher.match(content):
2276 failures[f] = csConfig
2277 for n, v in failures.iteritems():
2278 mx.log('{0}: header does not match RegexpHeader defined in {1}'.format(n, v))
2279 return len(failures)
2280 382
2281 def mx_init(suite): 383 def mx_init(suite):
2282 commands = { 384 commands = {
2283 'build': [build, ''],
2284 'buildjmh': [buildjmh, '[-options]'],
2285 'buildvars': [buildvars, ''],
2286 'buildvms': [buildvms, '[-options]'],
2287 'c1visualizer' : [c1visualizer, ''],
2288 'checkheaders': [checkheaders, ''],
2289 'clean': [clean, ''],
2290 'ctw': [ctw, '[-vmoptions|noinline|nocomplex|full]'],
2291 'export': [export, '[-options] [zipfile]'],
2292 'generateZshCompletion' : [generateZshCompletion, ''],
2293 'hsdis': [hsdis, '[att]'],
2294 'hcfdis': [hcfdis, ''],
2295 'igv' : [igv, ''],
2296 'jdkhome': [print_jdkhome, ''],
2297 'jmh': [jmh, '[VM options] [filters|JMH-args-as-json...]'],
2298 'dacapo': [dacapo, '[VM options] benchmarks...|"all" [DaCapo options]'], 385 'dacapo': [dacapo, '[VM options] benchmarks...|"all" [DaCapo options]'],
2299 'scaladacapo': [scaladacapo, '[VM options] benchmarks...|"all" [Scala DaCapo options]'], 386 'scaladacapo': [scaladacapo, '[VM options] benchmarks...|"all" [Scala DaCapo options]'],
2300 'specjvm2008': [specjvm2008, '[VM options] benchmarks...|"all" [SPECjvm2008 options]'], 387 'specjvm2008': [specjvm2008, '[VM options] benchmarks...|"all" [SPECjvm2008 options]'],
2301 'specjbb2013': [specjbb2013, '[VM options] [-- [SPECjbb2013 options]]'], 388 'specjbb2013': [specjbb2013, '[VM options] [-- [SPECjbb2013 options]]'],
2302 'specjbb2005': [specjbb2005, '[VM options] [-- [SPECjbb2005 options]]'], 389 'specjbb2005': [specjbb2005, '[VM options] [-- [SPECjbb2005 options]]'],
2303 'gate' : [gate, '[-options]'],
2304 'bench' : [bench, '[-resultfile file] [all(default)|dacapo|specjvm2008|bootstrap]'], 390 'bench' : [bench, '[-resultfile file] [all(default)|dacapo|specjvm2008|bootstrap]'],
2305 'microbench' : [microbench, '[VM options] [-- [JMH options]]'], 391 'microbench' : [microbench, '[VM options] [-- [JMH options]]'],
2306 'makejmhdeps' : [makejmhdeps, ''],
2307 'unittest' : [unittest, '[unittest options] [--] [VM options] [filters...]', mx_unittest.unittestHelpSuffix],
2308 'shortunittest' : [shortunittest, '[unittest options] [--] [VM options] [filters...]', mx_unittest.unittestHelpSuffix],
2309 'jacocoreport' : [jacocoreport, '[output directory]'],
2310 'site' : [site, '[-options]'],
2311 'vm': [vm, '[-options] class [args...]'],
2312 'vmg': [vmg, '[-options] class [args...]'],
2313 'vmfg': [vmfg, '[-options] class [args...]'],
2314 'deoptalot' : [deoptalot, '[n]'], 392 'deoptalot' : [deoptalot, '[n]'],
2315 'longtests' : [longtests, ''], 393 'longtests' : [longtests, ''],
2316 'jol' : [jol, ''],
2317 'makefile' : [mx_graal_makefile.build_makefile, 'build makefiles for JDK build'],
2318 } 394 }
2319 395
2320 mx.add_argument('--jacoco', help='instruments com.oracle.* classes using JaCoCo', default='off', choices=['off', 'on', 'append'])
2321 mx.add_argument('--vmcwd', dest='vm_cwd', help='current directory will be changed to <path> before the VM is executed', default=None, metavar='<path>')
2322 mx.add_argument('--installed-jdks', help='the base directory in which the JDKs cloned from $JAVA_HOME exist. ' +
2323 'The VM selected by --vm and --vmbuild options is under this directory (i.e., ' +
2324 join('<path>', '<jdk-version>', '<vmbuild>', 'jre', 'lib', '<vm>', mx.add_lib_prefix(mx.add_lib_suffix('jvm'))) + ')', default=None, metavar='<path>')
2325
2326 mx.add_argument('--vm', action='store', dest='vm', choices=_vmChoices.keys(), help='the VM type to build/run')
2327 mx.add_argument('--vmbuild', action='store', dest='vmbuild', choices=_vmbuildChoices, help='the VM build to build/run (default: ' + _vmbuildChoices[0] + ')')
2328 mx.add_argument('--ecl', action='store_true', dest='make_eclipse_launch', help='create launch configuration for running VM execution(s) in Eclipse')
2329 mx.add_argument('--vmprefix', action='store', dest='vm_prefix', help='prefix for running the VM (e.g. "/usr/bin/gdb --args")', metavar='<prefix>')
2330 mx.add_argument('--gdb', action='store_const', const='/usr/bin/gdb --args', dest='vm_prefix', help='alias for --vmprefix "/usr/bin/gdb --args"')
2331 mx.add_argument('--lldb', action='store_const', const='lldb --', dest='vm_prefix', help='alias for --vmprefix "lldb --"')
2332
2333 mx.update_commands(suite, commands) 396 mx.update_commands(suite, commands)
2334
2335 class JVMCIArchiveParticipant:
2336 def __init__(self, dist):
2337 self.dist = dist
2338 self.jvmciServices = {}
2339
2340 def __opened__(self, arc, srcArc, services):
2341 self.services = services
2342 self.arc = arc
2343 self.expectedOptionsProviders = set()
2344
2345 def __add__(self, arcname, contents):
2346 if arcname.startswith('META-INF/jvmci.services/'):
2347 service = arcname[len('META-INF/jvmci.services/'):]
2348 self.jvmciServices.setdefault(service, []).extend([provider for provider in contents.split('\n')])
2349 return True
2350 if arcname.startswith('META-INF/jvmci.providers/'):
2351 provider = arcname[len('META-INF/jvmci.providers/'):]
2352 for service in contents.split('\n'):
2353 self.jvmciServices.setdefault(service, []).append(provider)
2354 return True
2355 elif arcname.startswith('META-INF/jvmci.options/'):
2356 # Need to create service files for the providers of the
2357 # jdk.internal.jvmci.options.Options service created by
2358 # jdk.internal.jvmci.options.processor.OptionProcessor.
2359 optionsOwner = arcname[len('META-INF/jvmci.options/'):]
2360 provider = optionsOwner + '_Options'
2361 self.expectedOptionsProviders.add(provider.replace('.', '/') + '.class')
2362 self.services.setdefault('jdk.internal.jvmci.options.Options', []).append(provider)
2363 return False
2364
2365 def __addsrc__(self, arcname, contents):
2366 return False
2367
2368 def __closing__(self):
2369 self.expectedOptionsProviders -= set(self.arc.zf.namelist())
2370 assert len(self.expectedOptionsProviders) == 0, 'missing generated Options providers:\n ' + '\n '.join(self.expectedOptionsProviders)
2371 for service, providers in self.jvmciServices.iteritems():
2372 arcname = 'META-INF/jvmci.services/' + service
2373 # Convert providers to a set before printing to remove duplicates
2374 self.arc.zf.writestr(arcname, '\n'.join(frozenset(providers)))
2375
2376 def mx_post_parse_cmd_line(opts): #
2377 # TODO _minVersion check could probably be part of a Suite in mx?
2378 def _versionCheck(version):
2379 return version >= _minVersion and (not _untilVersion or version >= _untilVersion)
2380 versionDesc = ">=" + str(_minVersion)
2381 if _untilVersion:
2382 versionDesc += " and <=" + str(_untilVersion)
2383 mx.java(_versionCheck, versionDescription=versionDesc, defaultJdk=True)
2384
2385 if hasattr(opts, 'vm') and opts.vm is not None:
2386 global _vm
2387 _vm = opts.vm
2388 _vm = _vm.replace('graal', 'jvmci')
2389 if hasattr(opts, 'vmbuild') and opts.vmbuild is not None:
2390 global _vmbuild
2391 _vmbuild = opts.vmbuild
2392 global _make_eclipse_launch
2393 _make_eclipse_launch = getattr(opts, 'make_eclipse_launch', False)
2394 global _jacoco
2395 _jacoco = opts.jacoco
2396 global _vm_cwd
2397 _vm_cwd = opts.vm_cwd
2398 global _installed_jdks
2399 _installed_jdks = opts.installed_jdks
2400 global _vm_prefix
2401 _vm_prefix = opts.vm_prefix
2402
2403 for jdkDist in _jdkDeployedDists:
2404 def _close(jdkDeployable):
2405 def _install(dist):
2406 assert dist.name == jdkDeployable.name, dist.name + "!=" + jdkDeployable.name
2407 if not jdkDist.partOfHotSpot:
2408 _installDistInJdks(jdkDeployable)
2409 return _install
2410 dist = mx.distribution(jdkDist.name)
2411 dist.add_update_listener(_close(jdkDist))
2412 if jdkDist.usesJVMCIClassLoader:
2413 dist.set_archiveparticipant(JVMCIArchiveParticipant(dist))
2414