comparison mx/mx_graal.py @ 12764:6cdf3b17316d

mx: rename commands.py as mx_graal.py
author Mick Jordan <mick.jordan@oracle.com>
date Tue, 12 Nov 2013 19:39:25 -0800
parents mx/commands.py@c6b833f7935e
children 6140eda73e6f
comparison
equal deleted inserted replaced
12763:bff24aae4640 12764:6cdf3b17316d
1 #
2 # commands.py - the GraalVM specific commands
3 #
4 # ----------------------------------------------------------------------------------------------------
5 #
6 # Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
7 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
8 #
9 # This code is free software; you can redistribute it and/or modify it
10 # under the terms of the GNU General Public License version 2 only, as
11 # published by the Free Software Foundation.
12 #
13 # This code is distributed in the hope that it will be useful, but WITHOUT
14 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 # version 2 for more details (a copy is included in the LICENSE file that
17 # accompanied this code).
18 #
19 # You should have received a copy of the GNU General Public License version
20 # 2 along with this work; if not, write to the Free Software Foundation,
21 # Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
22 #
23 # Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
24 # or visit www.oracle.com if you need additional information or have any
25 # questions.
26 #
27 # ----------------------------------------------------------------------------------------------------
28
29 import os, sys, shutil, zipfile, tempfile, re, time, datetime, platform, subprocess, multiprocessing
30 from os.path import join, exists, dirname, basename, getmtime
31 from argparse import ArgumentParser, REMAINDER
32 import mx
33 import sanitycheck
34 import itertools
35 import json, textwrap
36
37 # This works because when mx loads this file, it makes sure __file__ gets an absolute path
38 _graal_home = dirname(dirname(__file__))
39
40 """ Used to distinguish an exported GraalVM (see 'mx export'). """
41 _vmSourcesAvailable = exists(join(_graal_home, 'make')) and exists(join(_graal_home, 'src'))
42
43 """ The VMs that can be built and run along with an optional description. Only VMs with a
44 description are listed in the dialogue for setting the default VM (see _get_vm()). """
45 _vmChoices = {
46 'graal' : 'All compilation is performed with Graal. This includes bootstrapping Graal itself unless -XX:-BootstrapGraal is used.',
47 'server' : 'Normal compilation is performed with the tiered system (i.e., client + server), Truffle compilation is performed with Graal. Use this for optimal Truffle performance.',
48 'client' : None, # normal compilation with client compiler, explicit compilation (e.g., by Truffle) with Graal
49 'server-nograal' : None, # all compilation with tiered system (i.e., client + server), Graal omitted
50 'client-nograal' : None, # all compilation with client compiler, Graal omitted
51 'original' : None, # default VM copied from bootstrap JDK
52 }
53
54 """ The VM that will be run by the 'vm' command and built by default by the 'build' command.
55 This can be set via the global '--vm' option or the DEFAULT_VM environment variable.
56 It can also be temporarily set by using of a VM context manager object in a 'with' statement. """
57 _vm = None
58
59 """ The VM builds that will be run by the 'vm' command - default is first in list """
60 _vmbuildChoices = ['product', 'fastdebug', 'debug', 'optimized']
61
62 """ The VM build that will be run by the 'vm' command.
63 This can be set via the global '--vmbuild' option.
64 It can also be temporarily set by using of a VM context manager object in a 'with' statement. """
65 _vmbuild = _vmbuildChoices[0]
66
67 _jacoco = 'off'
68
69 """ The current working directory to switch to before running the VM. """
70 _vm_cwd = None
71
72 """ The base directory in which the JDKs cloned from $JAVA_HOME exist. """
73 _installed_jdks = None
74
75 """ Prefix for running the VM. """
76 _vm_prefix = None
77
78 _make_eclipse_launch = False
79
80 _minVersion = mx.JavaVersion('1.7.0_04')
81
82 def _get_vm():
83 """
84 Gets the configured VM, presenting a dialogue if there is no currently configured VM.
85 """
86 global _vm
87 if _vm:
88 return _vm
89 vm = mx.get_env('DEFAULT_VM')
90 if vm is None:
91 if not sys.stdout.isatty():
92 mx.abort('Need to specify VM with --vm option or DEFAULT_VM environment variable')
93 envPath = join(_graal_home, 'mx', 'env')
94 mx.log('Please select the VM to be executed from the following: ')
95 items = [k for k in _vmChoices.keys() if _vmChoices[k] is not None]
96 descriptions = [_vmChoices[k] for k in _vmChoices.keys() if _vmChoices[k] is not None]
97 vm = mx.select_items(items, descriptions, allowMultiple=False)
98 if mx.ask_yes_no('Persist this choice by adding "DEFAULT_VM=' + vm + '" to ' + envPath, 'y'):
99 with open(envPath, 'a') as fp:
100 print >> fp, 'DEFAULT_VM=' + vm
101 _vm = vm
102 return vm
103
104 """
105 A context manager that can be used with the 'with' statement to set the VM
106 used by all VM executions within the scope of the 'with' statement. For example:
107
108 with VM('server'):
109 dacapo(['pmd'])
110 """
111 class VM:
112 def __init__(self, vm=None, build=None):
113 assert vm is None or vm in _vmChoices.keys()
114 assert build is None or build in _vmbuildChoices
115 self.vm = vm if vm else _vm
116 self.build = build if build else _vmbuild
117 self.previousVm = _vm
118 self.previousBuild = _vmbuild
119
120 def __enter__(self):
121 global _vm, _vmbuild
122 _vm = self.vm
123 _vmbuild = self.build
124
125 def __exit__(self, exc_type, exc_value, traceback):
126 global _vm, _vmbuild
127 _vm = self.previousVm
128 _vmbuild = self.previousBuild
129
130 def _chmodDir(chmodFlags, dirname, fnames):
131 os.chmod(dirname, chmodFlags)
132 for name in fnames:
133 os.chmod(os.path.join(dirname, name), chmodFlags)
134
135 def chmodRecursive(dirname, chmodFlags):
136 os.path.walk(dirname, _chmodDir, chmodFlags)
137
138 def clean(args):
139 """clean the GraalVM source tree"""
140 opts = mx.clean(args, parser=ArgumentParser(prog='mx clean'))
141 if opts.native:
142 def rmIfExists(name):
143 if os.path.isdir(name):
144 shutil.rmtree(name)
145 elif os.path.isfile(name):
146 os.unlink(name)
147
148 rmIfExists(join(_graal_home, 'build'))
149 rmIfExists(join(_graal_home, 'build-nograal'))
150 rmIfExists(_jdksDir())
151 rmIfExists(mx.distribution('GRAAL').path)
152
153 def export(args):
154 """create a GraalVM zip file for distribution"""
155
156 parser = ArgumentParser(prog='mx export')
157 parser.add_argument('--omit-vm-build', action='store_false', dest='vmbuild', help='omit VM build step')
158 parser.add_argument('--omit-dist-init', action='store_false', dest='distInit', help='omit class files and IDE configurations from distribution')
159 parser.add_argument('zipfile', nargs=REMAINDER, metavar='zipfile')
160
161 args = parser.parse_args(args)
162
163 tmp = tempfile.mkdtemp(prefix='tmp', dir=_graal_home)
164 if args.vmbuild:
165 # Make sure the product VM binary is up to date
166 with VM(vmbuild='product'):
167 build([])
168
169 mx.log('Copying Java sources and mx files...')
170 mx.run(('hg archive -I graal -I mx -I mxtool -I mx.sh ' + tmp).split())
171
172 # Copy the GraalVM JDK
173 mx.log('Copying GraalVM JDK...')
174 src = _jdk()
175 dst = join(tmp, basename(src))
176 shutil.copytree(src, dst)
177 zfName = join(_graal_home, 'graalvm-' + mx.get_os() + '.zip')
178 zf = zipfile.ZipFile(zfName, 'w')
179 for root, _, files in os.walk(tmp):
180 for f in files:
181 name = join(root, f)
182 arcname = name[len(tmp) + 1:]
183 zf.write(join(tmp, name), arcname)
184
185 # create class files and IDE configurations
186 if args.distInit:
187 mx.log('Creating class files...')
188 mx.run('mx build'.split(), cwd=tmp)
189 mx.log('Creating IDE configurations...')
190 mx.run('mx ideinit'.split(), cwd=tmp)
191
192 # clean up temp directory
193 mx.log('Cleaning up...')
194 shutil.rmtree(tmp)
195
196 mx.log('Created distribution in ' + zfName)
197
198 def _run_benchmark(args, availableBenchmarks, runBenchmark):
199
200 vmOpts, benchmarksAndOptions = _extract_VM_args(args, useDoubleDash=availableBenchmarks is None)
201
202 if availableBenchmarks is None:
203 harnessArgs = benchmarksAndOptions
204 return runBenchmark(None, harnessArgs, vmOpts)
205
206 if len(benchmarksAndOptions) == 0:
207 mx.abort('at least one benchmark name or "all" must be specified')
208 benchmarks = list(itertools.takewhile(lambda x: not x.startswith('-'), benchmarksAndOptions))
209 harnessArgs = benchmarksAndOptions[len(benchmarks):]
210
211 if 'all' in benchmarks:
212 benchmarks = availableBenchmarks
213 else:
214 for bm in benchmarks:
215 if bm not in availableBenchmarks:
216 mx.abort('unknown benchmark: ' + bm + '\nselect one of: ' + str(availableBenchmarks))
217
218 failed = []
219 for bm in benchmarks:
220 if not runBenchmark(bm, harnessArgs, vmOpts):
221 failed.append(bm)
222
223 if len(failed) != 0:
224 mx.abort('Benchmark failures: ' + str(failed))
225
226 def dacapo(args):
227 """run one or more DaCapo benchmarks"""
228
229 def launcher(bm, harnessArgs, extraVmOpts):
230 return sanitycheck.getDacapo(bm, harnessArgs).test(_get_vm(), extraVmOpts=extraVmOpts)
231
232 _run_benchmark(args, sanitycheck.dacapoSanityWarmup.keys(), launcher)
233
234 def scaladacapo(args):
235 """run one or more Scala DaCapo benchmarks"""
236
237 def launcher(bm, harnessArgs, extraVmOpts):
238 return sanitycheck.getScalaDacapo(bm, harnessArgs).test(_get_vm(), extraVmOpts=extraVmOpts)
239
240 _run_benchmark(args, sanitycheck.dacapoScalaSanityWarmup.keys(), launcher)
241
242 def _arch():
243 machine = platform.uname()[4]
244 if machine in ['amd64', 'AMD64', 'x86_64', 'i86pc']:
245 return 'amd64'
246 if machine in ['sun4v', 'sun4u']:
247 return 'sparcv9'
248 if machine == 'i386' and mx.get_os() == 'darwin':
249 try:
250 # Support for Snow Leopard and earlier version of MacOSX
251 if subprocess.check_output(['sysctl', '-n', 'hw.cpu64bit_capable']).strip() == '1':
252 return 'amd64'
253 except OSError:
254 # sysctl is not available
255 pass
256 mx.abort('unknown or unsupported architecture: os=' + mx.get_os() + ', machine=' + machine)
257
258 def _vmLibDirInJdk(jdk):
259 """
260 Get the directory within a JDK where the server and client
261 subdirectories are located.
262 """
263 if platform.system() == 'Darwin':
264 return join(jdk, 'jre', 'lib')
265 if platform.system() == 'Windows':
266 return join(jdk, 'jre', 'bin')
267 return join(jdk, 'jre', 'lib', _arch())
268
269 def _vmCfgInJdk(jdk):
270 """
271 Get the jvm.cfg file.
272 """
273 if platform.system() == 'Windows':
274 return join(jdk, 'jre', 'lib', _arch(), 'jvm.cfg')
275 return join(_vmLibDirInJdk(jdk), 'jvm.cfg')
276
277 def _jdksDir():
278 return os.path.abspath(join(_installed_jdks if _installed_jdks else _graal_home, 'jdk' + str(mx.java().version)))
279
280 def _handle_missing_VM(bld, vm):
281 mx.log('The ' + bld + ' ' + vm + ' VM has not been created')
282 if sys.stdout.isatty():
283 if mx.ask_yes_no('Build it now', 'y'):
284 with VM(vm, bld):
285 build([])
286 return
287 mx.abort('You need to run "mx --vm ' + vm + ' --vmbuild ' + bld + ' build" to build the selected VM')
288
289 def _jdk(build='product', vmToCheck=None, create=False, installGraalJar=True):
290 """
291 Get the JDK into which Graal is installed, creating it first if necessary.
292 """
293 jdk = join(_jdksDir(), build)
294 if create:
295 srcJdk = mx.java().jdk
296 jdkContents = ['bin', 'include', 'jre', 'lib']
297 if exists(join(srcJdk, 'db')):
298 jdkContents.append('db')
299 if mx.get_os() != 'windows' and exists(join(srcJdk, 'man')):
300 jdkContents.append('man')
301 if not exists(jdk):
302 mx.log('Creating ' + jdk + ' from ' + srcJdk)
303 os.makedirs(jdk)
304 for d in jdkContents:
305 src = join(srcJdk, d)
306 dst = join(jdk, d)
307 if not exists(src):
308 mx.abort('Host JDK directory is missing: ' + src)
309 shutil.copytree(src, dst)
310
311 # Make a copy of the default VM so that this JDK can be
312 # reliably used as the bootstrap for a HotSpot build.
313 jvmCfg = _vmCfgInJdk(jdk)
314 if not exists(jvmCfg):
315 mx.abort(jvmCfg + ' does not exist')
316
317 defaultVM = None
318 jvmCfgLines = []
319 with open(jvmCfg) as f:
320 for line in f:
321 if line.startswith('-') and defaultVM is None:
322 parts = line.split()
323 if len(parts) == 2:
324 assert parts[1] == 'KNOWN', parts[1]
325 defaultVM = parts[0][1:]
326 jvmCfgLines += ['# default VM is a copy of the unmodified ' + defaultVM + ' VM\n']
327 jvmCfgLines += ['-original KNOWN\n']
328 else:
329 # skip lines which we cannot parse (e.g. '-hotspot ALIASED_TO -client')
330 mx.log("WARNING: skipping not parsable line \"" + line + "\"")
331 else:
332 jvmCfgLines += [line]
333
334 assert defaultVM is not None, 'Could not find default VM in ' + jvmCfg
335 if mx.get_os() != 'windows':
336 chmodRecursive(jdk, 0755)
337 shutil.move(join(_vmLibDirInJdk(jdk), defaultVM), join(_vmLibDirInJdk(jdk), 'original'))
338
339
340 with open(jvmCfg, 'w') as fp:
341 for line in jvmCfgLines:
342 fp.write(line)
343
344 # Install a copy of the disassembler library
345 try:
346 hsdis([], copyToDir=_vmLibDirInJdk(jdk))
347 except SystemExit:
348 pass
349 else:
350 if not exists(jdk):
351 if _installed_jdks:
352 mx.log("The selected JDK directory does not (yet) exist: " + jdk)
353 _handle_missing_VM(build, vmToCheck if vmToCheck else 'graal')
354
355 if installGraalJar:
356 _installGraalJarInJdks(mx.distribution('GRAAL'))
357
358 if vmToCheck is not None:
359 jvmCfg = _vmCfgInJdk(jdk)
360 found = False
361 with open(jvmCfg) as f:
362 for line in f:
363 if line.strip() == '-' + vmToCheck + ' KNOWN':
364 found = True
365 break
366 if not found:
367 _handle_missing_VM(build, vmToCheck)
368
369 return jdk
370
371 def _updateInstalledGraalOptionsFile(jdk):
372 graalOptions = join(_graal_home, 'graal.options')
373 jreLibDir = join(jdk, 'jre', 'lib')
374 if exists(graalOptions):
375 shutil.copy(graalOptions, join(jreLibDir, 'graal.options'))
376 else:
377 toDelete = join(jreLibDir, 'graal.options')
378 if exists(toDelete):
379 os.unlink(toDelete)
380
381 def _installGraalJarInJdks(graalDist):
382 graalJar = graalDist.path
383 jdks = _jdksDir()
384 if exists(jdks):
385 for e in os.listdir(jdks):
386 jreLibDir = join(jdks, e, 'jre', 'lib')
387 if exists(jreLibDir):
388 # do a copy and then a move to get atomic updating (on Unix) of graal.jar in the JRE
389 fd, tmp = tempfile.mkstemp(suffix='', prefix='graal.jar', dir=jreLibDir)
390 shutil.copyfile(graalJar, tmp)
391 os.close(fd)
392 shutil.move(tmp, join(jreLibDir, 'graal.jar'))
393
394 # run a command in the windows SDK Debug Shell
395 def _runInDebugShell(cmd, workingDir, logFile=None, findInOutput=None, respondTo=None):
396 if respondTo is None:
397 respondTo = {}
398 newLine = os.linesep
399 startToken = 'RUNINDEBUGSHELL_STARTSEQUENCE'
400 endToken = 'RUNINDEBUGSHELL_ENDSEQUENCE'
401
402 winSDK = mx.get_env('WIN_SDK', 'C:\\Program Files\\Microsoft SDKs\\Windows\\v7.1\\')
403
404 if not exists(winSDK):
405 mx.abort("Could not find Windows SDK : '" + winSDK + "' does not exist")
406
407 if not exists(join(winSDK, 'Bin', 'SetEnv.cmd')):
408 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)")
409
410 p = subprocess.Popen('cmd.exe /E:ON /V:ON /K ""' + winSDK + '/Bin/SetEnv.cmd" & echo ' + startToken + '"', \
411 shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, creationflags=subprocess.CREATE_NEW_PROCESS_GROUP)
412 stdout = p.stdout
413 stdin = p.stdin
414 if logFile:
415 log = open(logFile, 'w')
416 ret = False
417 while True:
418
419 # encoding may be None on windows plattforms
420 if sys.stdout.encoding is None:
421 encoding = 'utf-8'
422 else:
423 encoding = sys.stdout.encoding
424
425 line = stdout.readline().decode(encoding)
426 if logFile:
427 log.write(line.encode('utf-8'))
428 line = line.strip()
429 mx.log(line)
430 if line == startToken:
431 stdin.write('cd /D ' + workingDir + ' & ' + cmd + ' & echo ' + endToken + newLine)
432 for regex in respondTo.keys():
433 match = regex.search(line)
434 if match:
435 stdin.write(respondTo[regex] + newLine)
436 if findInOutput:
437 match = findInOutput.search(line)
438 if match:
439 ret = True
440 if line == endToken:
441 if not findInOutput:
442 stdin.write('echo ERRXXX%errorlevel%' + newLine)
443 else:
444 break
445 if line.startswith('ERRXXX'):
446 if line == 'ERRXXX0':
447 ret = True
448 break
449 stdin.write('exit' + newLine)
450 if logFile:
451 log.close()
452 return ret
453
454 def jdkhome(vm=None):
455 """return the JDK directory selected for the 'vm' command"""
456 build = _vmbuild if _vmSourcesAvailable else 'product'
457 return _jdk(build, installGraalJar=False)
458
459 def print_jdkhome(args, vm=None):
460 """print the JDK directory selected for the 'vm' command"""
461 print jdkhome(vm)
462
463 def buildvars(args):
464 """describe the variables that can be set by the -D option to the 'mx build' commmand"""
465
466 buildVars = {
467 'ALT_BOOTDIR' : 'The location of the bootstrap JDK installation (default: ' + mx.java().jdk + ')',
468 'ALT_OUTPUTDIR' : 'Build directory',
469 'HOTSPOT_BUILD_JOBS' : 'Number of CPUs used by make (default: ' + str(multiprocessing.cpu_count()) + ')',
470 'INSTALL' : 'Install the built VM into the JDK? (default: y)',
471 'ZIP_DEBUGINFO_FILES' : 'Install zipped debug symbols file? (default: 0)',
472 }
473
474 mx.log('HotSpot build variables that can be set by the -D option to "mx build":')
475 mx.log('')
476 for n in sorted(buildVars.iterkeys()):
477 mx.log(n)
478 mx.log(textwrap.fill(buildVars[n], initial_indent=' ', subsequent_indent=' ', width=200))
479
480 mx.log('')
481 mx.log('Note that these variables can be given persistent values in the file ' + join(_graal_home, 'mx', 'env') + ' (see \'mx about\').')
482
483 def build(args, vm=None):
484 """build the VM binary
485
486 The global '--vm' and '--vmbuild' options select which VM type and build target to build."""
487
488 # Override to fail quickly if extra arguments are given
489 # at the end of the command line. This allows for a more
490 # helpful error message.
491 class AP(ArgumentParser):
492 def __init__(self):
493 ArgumentParser.__init__(self, prog='mx build')
494 def parse_args(self, args):
495 result = ArgumentParser.parse_args(self, args)
496 if len(result.remainder) != 0:
497 firstBuildTarget = result.remainder[0]
498 mx.abort('To specify the ' + firstBuildTarget + ' VM build target, you need to use the global "--vmbuild" option. For example:\n' +
499 ' mx --vmbuild ' + firstBuildTarget + ' build')
500 return result
501
502 # Call mx.build to compile the Java sources
503 parser = AP()
504 parser.add_argument('--export-dir', help='directory to which graal.jar and graal.options will be copied', metavar='<path>')
505 parser.add_argument('-D', action='append', help='set a HotSpot build variable (run \'mx buildvars\' to list variables)', metavar='name=value')
506 opts2 = mx.build(['--source', '1.7'] + args, parser=parser)
507 assert len(opts2.remainder) == 0
508
509 if opts2.export_dir is not None:
510 if not exists(opts2.export_dir):
511 os.makedirs(opts2.export_dir)
512 else:
513 assert os.path.isdir(opts2.export_dir), '{} is not a directory'.format(opts2.export_dir)
514
515 shutil.copy(mx.distribution('GRAAL').path, opts2.export_dir)
516 graalOptions = join(_graal_home, 'graal.options')
517 if exists(graalOptions):
518 shutil.copy(graalOptions, opts2.export_dir)
519
520 if not _vmSourcesAvailable or not opts2.native:
521 return
522
523 builds = [_vmbuild]
524
525 if vm is None:
526 vm = _get_vm()
527
528 if vm == 'original':
529 pass
530 elif vm.startswith('server'):
531 buildSuffix = ''
532 elif vm.startswith('client'):
533 buildSuffix = '1'
534 else:
535 assert vm == 'graal', vm
536 buildSuffix = 'graal'
537
538 if _installed_jdks and _installed_jdks != _graal_home:
539 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'):
540 mx.abort(1)
541
542 for build in builds:
543 if build == 'ide-build-target':
544 build = os.environ.get('IDE_BUILD_TARGET', None)
545 if build is None or len(build) == 0:
546 continue
547
548 jdk = _jdk(build, create=True)
549
550 if vm == 'original':
551 if build != 'product':
552 mx.log('only product build of original VM exists')
553 continue
554
555 vmDir = join(_vmLibDirInJdk(jdk), vm)
556 if not exists(vmDir):
557 if mx.get_os() != 'windows':
558 chmodRecursive(jdk, 0755)
559 mx.log('Creating VM directory in JDK7: ' + vmDir)
560 os.makedirs(vmDir)
561
562 def filterXusage(line):
563 if not 'Xusage.txt' in line:
564 sys.stderr.write(line + os.linesep)
565
566 # Check if a build really needs to be done
567 timestampFile = join(vmDir, '.build-timestamp')
568 if opts2.force or not exists(timestampFile):
569 mustBuild = True
570 else:
571 mustBuild = False
572 timestamp = os.path.getmtime(timestampFile)
573 sources = []
574 for d in ['src', 'make']:
575 for root, dirnames, files in os.walk(join(_graal_home, d)):
576 # ignore <graal>/src/share/tools
577 if root == join(_graal_home, 'src', 'share'):
578 dirnames.remove('tools')
579 sources += [join(root, name) for name in files]
580 for f in sources:
581 if len(f) != 0 and os.path.getmtime(f) > timestamp:
582 mustBuild = True
583 break
584
585 if not mustBuild:
586 mx.logv('[all files in src and make directories are older than ' + timestampFile[len(_graal_home) + 1:] + ' - skipping native build]')
587 continue
588
589 if platform.system() == 'Windows':
590 compilelogfile = _graal_home + '/graalCompile.log'
591 mksHome = mx.get_env('MKS_HOME', 'C:\\cygwin\\bin')
592
593 variant = {'client': 'compiler1', 'server': 'compiler2'}.get(vm, vm)
594 project_config = variant + '_' + build
595 _runInDebugShell('msbuild ' + _graal_home + r'\build\vs-amd64\jvm.vcproj /p:Configuration=' + project_config + ' /target:clean', _graal_home)
596 winCompileCmd = r'set HotSpotMksHome=' + mksHome + r'& set OUT_DIR=' + jdk + r'& set JAVA_HOME=' + jdk + r'& set path=%JAVA_HOME%\bin;%path%;%HotSpotMksHome%& cd /D "' + _graal_home + r'\make\windows"& call create.bat ' + _graal_home
597 print(winCompileCmd)
598 winCompileSuccess = re.compile(r"^Writing \.vcxproj file:")
599 if not _runInDebugShell(winCompileCmd, _graal_home, compilelogfile, winCompileSuccess):
600 mx.log('Error executing create command')
601 return
602 winBuildCmd = 'msbuild ' + _graal_home + r'\build\vs-amd64\jvm.vcxproj /p:Configuration=' + project_config + ' /p:Platform=x64'
603 if not _runInDebugShell(winBuildCmd, _graal_home, compilelogfile):
604 mx.log('Error building project')
605 return
606 else:
607 cpus = multiprocessing.cpu_count()
608 runCmd = [mx.gmake_cmd()]
609 runCmd.append(build + buildSuffix)
610 env = os.environ.copy()
611
612 if opts2.D:
613 for nv in opts2.D:
614 name, value = nv.split('=', 1)
615 env[name.strip()] = value
616
617 env.setdefault('ARCH_DATA_MODEL', '64')
618 env.setdefault('LANG', 'C')
619 env.setdefault('HOTSPOT_BUILD_JOBS', str(cpus))
620 env.setdefault('ALT_BOOTDIR', mx.java().jdk)
621 if not mx._opts.verbose:
622 runCmd.append('MAKE_VERBOSE=')
623 env['JAVA_HOME'] = jdk
624 if vm.endswith('nograal'):
625 env['INCLUDE_GRAAL'] = 'false'
626 env.setdefault('ALT_OUTPUTDIR', join(_graal_home, 'build-nograal', mx.get_os()))
627 else:
628 env['INCLUDE_GRAAL'] = 'true'
629 env.setdefault('INSTALL', 'y')
630 if mx.get_os() == 'solaris' :
631 # If using sparcWorks, setup flags to avoid make complaining about CC version
632 cCompilerVersion = subprocess.Popen('CC -V', stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True).stderr.readlines()[0]
633 if cCompilerVersion.startswith('CC: Sun C++') :
634 compilerRev = cCompilerVersion.split(' ')[3]
635 env.setdefault('ENFORCE_COMPILER_REV', compilerRev)
636 env.setdefault('ENFORCE_CC_COMPILER_REV', compilerRev)
637 if build == 'jvmg':
638 # I want ALL the symbols when I'm debugging on Solaris
639 # Some Makefile variable are overloaded by environment variable so we need to explicitely
640 # pass them down in the command line. This one is an example of that.
641 runCmd.append('STRIP_POLICY=no_strip')
642 # This removes the need to unzip the *.diz files before debugging in gdb
643 env.setdefault('ZIP_DEBUGINFO_FILES', '0')
644
645 # Clear these 2 variables as having them set can cause very confusing build problems
646 env.pop('LD_LIBRARY_PATH', None)
647 env.pop('CLASSPATH', None)
648
649 mx.run(runCmd, cwd=join(_graal_home, 'make'), err=filterXusage, env=env)
650
651 jvmCfg = _vmCfgInJdk(jdk)
652 if not exists(jvmCfg):
653 mx.abort(jvmCfg + ' does not exist')
654
655 prefix = '-' + vm + ' '
656 vmKnown = prefix + 'KNOWN\n'
657 lines = []
658 found = False
659 with open(jvmCfg) as f:
660 for line in f:
661 if line.strip() == vmKnown.strip():
662 found = True
663 lines.append(line)
664
665 if not found:
666 mx.log('Appending "' + prefix + 'KNOWN" to ' + jvmCfg)
667 if mx.get_os() != 'windows':
668 os.chmod(jvmCfg, 0755)
669 with open(jvmCfg, 'w') as f:
670 for line in lines:
671 if line.startswith(prefix):
672 line = vmKnown
673 found = True
674 f.write(line)
675 if not found:
676 f.write(vmKnown)
677
678 if exists(timestampFile):
679 os.utime(timestampFile, None)
680 else:
681 file(timestampFile, 'a')
682
683 def vmg(args):
684 """run the debug build of VM selected by the '--vm' option"""
685 return vm(args, vmbuild='debug')
686
687 def vmfg(args):
688 """run the fastdebug build of VM selected by the '--vm' option"""
689 return vm(args, vmbuild='fastdebug')
690
691 def vm(args, vm=None, nonZeroIsFatal=True, out=None, err=None, cwd=None, timeout=None, vmbuild=None):
692 """run the VM selected by the '--vm' option"""
693
694 if vm is None:
695 vm = _get_vm()
696
697 if cwd is None:
698 cwd = _vm_cwd
699 elif _vm_cwd is not None and _vm_cwd != cwd:
700 mx.abort("conflicting working directories: do not set --vmcwd for this command")
701
702 build = vmbuild if vmbuild is not None else _vmbuild if _vmSourcesAvailable else 'product'
703 jdk = _jdk(build, vmToCheck=vm, installGraalJar=False)
704 _updateInstalledGraalOptionsFile(jdk)
705 mx.expand_project_in_args(args)
706 if _make_eclipse_launch:
707 mx.make_eclipse_launch(args, 'graal-' + build, name=None, deps=mx.project('com.oracle.graal.hotspot').all_deps([], True))
708 if len([a for a in args if 'PrintAssembly' in a]) != 0:
709 hsdis([], copyToDir=_vmLibDirInJdk(jdk))
710 if mx.java().debug_port is not None:
711 args = ['-Xdebug', '-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=' + str(mx.java().debug_port)] + args
712 if _jacoco == 'on' or _jacoco == 'append':
713 jacocoagent = mx.library("JACOCOAGENT", True)
714 # Exclude all compiler tests and snippets
715 excludes = ['com.oracle.graal.compiler.tests.*', 'com.oracle.graal.jtt.*']
716 for p in mx.projects():
717 excludes += _find_classes_with_annotations(p, None, ['@Snippet', '@ClassSubstitution', '@Test'], includeInnerClasses=True).keys()
718 excludes += p.find_classes_with_matching_source_line(None, lambda line: 'JaCoCo Exclude' in line, includeInnerClasses=True).keys()
719
720 includes = ['com.oracle.graal.*']
721 agentOptions = {
722 'append' : 'true' if _jacoco == 'append' else 'false',
723 'bootclasspath' : 'true',
724 'includes' : ':'.join(includes),
725 'excludes' : ':'.join(excludes),
726 'destfile' : 'jacoco.exec'
727 }
728 args = ['-javaagent:' + jacocoagent.get_path(True) + '=' + ','.join([k + '=' + v for k, v in agentOptions.items()])] + args
729 if '-d64' not in args:
730 args = ['-d64'] + args
731
732 exe = join(jdk, 'bin', mx.exe_suffix('java'))
733 pfx = _vm_prefix.split() if _vm_prefix is not None else []
734
735 if '-version' in args:
736 ignoredArgs = args[args.index('-version') + 1:]
737 if len(ignoredArgs) > 0:
738 mx.log("Warning: The following options will be ignored by the vm because they come after the '-version' argument: " + ' '.join(ignoredArgs))
739
740 return mx.run(pfx + [exe, '-' + vm] + args, nonZeroIsFatal=nonZeroIsFatal, out=out, err=err, cwd=cwd, timeout=timeout)
741
742 def _find_classes_with_annotations(p, pkgRoot, annotations, includeInnerClasses=False):
743 """
744 Scan the sources of project 'p' for Java source files containing a line starting with 'annotation'
745 (ignoring preceding whitespace) and return the fully qualified class name for each Java
746 source file matched in a list.
747 """
748
749 matches = lambda line : len([a for a in annotations if line == a or line.startswith(a + '(')]) != 0
750 return p.find_classes_with_matching_source_line(pkgRoot, matches, includeInnerClasses)
751
752 def _extract_VM_args(args, allowClasspath=False, useDoubleDash=False):
753 """
754 Partitions a command line into a leading sequence of HotSpot VM options and the rest.
755 """
756 for i in range(0, len(args)):
757 if useDoubleDash:
758 if args[i] == '--':
759 vmArgs = args[:i]
760 remainder = args[i + 1:]
761 return vmArgs, remainder
762 else:
763 if not args[i].startswith('-'):
764 if i != 0 and (args[i - 1] == '-cp' or args[i - 1] == '-classpath'):
765 if not allowClasspath:
766 mx.abort('Cannot supply explicit class path option')
767 else:
768 continue
769 vmArgs = args[:i]
770 remainder = args[i:]
771 return vmArgs, remainder
772
773 return args, []
774
775 def _run_tests(args, harness, annotations, testfile):
776
777
778 vmArgs, tests = _extract_VM_args(args)
779 for t in tests:
780 if t.startswith('-'):
781 mx.abort('VM option ' + t + ' must precede ' + tests[0])
782
783 candidates = []
784 for p in mx.projects_opt_limit_to_suites():
785 if mx.java().javaCompliance < p.javaCompliance:
786 continue
787 candidates += _find_classes_with_annotations(p, None, annotations).keys()
788
789 classes = []
790 if len(tests) == 0:
791 classes = candidates
792 else:
793 for t in tests:
794 found = False
795 for c in candidates:
796 if t in c:
797 found = True
798 classes.append(c)
799 if not found:
800 mx.log('warning: no tests matched by substring "' + t)
801
802 projectscp = mx.classpath([pcp.name for pcp in mx.projects_opt_limit_to_suites() if pcp.javaCompliance <= mx.java().javaCompliance])
803
804 if len(classes) != 0:
805 f_testfile = open(testfile, 'w')
806 for c in classes:
807 f_testfile.write(c + '\n')
808 f_testfile.close()
809 harness(projectscp, vmArgs)
810
811 def _unittest(args, annotations):
812 mxdir = dirname(__file__)
813 name = 'JUnitWrapper'
814 javaSource = join(mxdir, name + '.java')
815 javaClass = join(mxdir, name + '.class')
816 testfile = os.environ.get('MX_TESTFILE', None)
817 if testfile is None:
818 (_, testfile) = tempfile.mkstemp(".testclasses", "graal")
819 os.close(_)
820
821 def harness(projectscp, vmArgs):
822 if not exists(javaClass) or getmtime(javaClass) < getmtime(javaSource):
823 subprocess.check_call([mx.java().javac, '-cp', projectscp, '-d', mxdir, javaSource])
824 if _get_vm() != 'graal':
825 prefixArgs = ['-esa', '-ea']
826 else:
827 prefixArgs = ['-XX:-BootstrapGraal', '-esa', '-ea']
828 with open(testfile) as fp:
829 testclasses = [l.rstrip() for l in fp.readlines()]
830 if len(testclasses) == 1:
831 # Execute Junit directly when one test is being run. This simplifies
832 # replaying the VM execution in a native debugger (e.g., gdb).
833 vm(prefixArgs + vmArgs + ['-cp', projectscp, 'org.junit.runner.JUnitCore'] + testclasses)
834 else:
835 vm(prefixArgs + vmArgs + ['-cp', projectscp + os.pathsep + mxdir, name] + [testfile])
836
837 try:
838 _run_tests(args, harness, annotations, testfile)
839 finally:
840 if os.environ.get('MX_TESTFILE') is None:
841 os.remove(testfile)
842
843 _unittestHelpSuffix = """
844
845 If filters are supplied, only tests whose fully qualified name
846 includes a filter as a substring are run.
847
848 For example, this command line:
849
850 mx unittest -G:Dump= -G:MethodFilter=BC_aload.* -G:+PrintCFG BC_aload
851
852 will run all JUnit test classes that contain 'BC_aload' in their
853 fully qualified name and will pass these options to the VM:
854
855 -G:Dump= -G:MethodFilter=BC_aload.* -G:+PrintCFG
856
857 To get around command line length limitations on some OSes, the
858 JUnit class names to be executed are written to a file that a
859 custom JUnit wrapper reads and passes onto JUnit proper. The
860 MX_TESTFILE environment variable can be set to specify a
861 file which will not be deleted once the unittests are done
862 (unlike the temporary file otherwise used).
863
864 As with all other commands, using the global '-v' before 'unittest'
865 command will cause mx to show the complete command line
866 it uses to run the VM.
867 """
868
869 def unittest(args):
870 """run the JUnit tests (all testcases){0}"""
871
872 _unittest(args, ['@Test', '@LongTest', '@Parameters'])
873
874 def shortunittest(args):
875 """run the JUnit tests (short testcases only){0}"""
876
877 _unittest(args, ['@Test'])
878
879 def longunittest(args):
880 """run the JUnit tests (long testcases only){0}"""
881
882 _unittest(args, ['@LongTest', '@Parameters'])
883
884 def buildvms(args):
885 """build one or more VMs in various configurations"""
886
887 vmsDefault = ','.join(_vmChoices.keys())
888 vmbuildsDefault = ','.join(_vmbuildChoices)
889
890 parser = ArgumentParser(prog='mx buildvms')
891 parser.add_argument('--vms', help='a comma separated list of VMs to build (default: ' + vmsDefault + ')', metavar='<args>', default=vmsDefault)
892 parser.add_argument('--builds', help='a comma separated list of build types (default: ' + vmbuildsDefault + ')', metavar='<args>', default=vmbuildsDefault)
893 parser.add_argument('-n', '--no-check', action='store_true', help='omit running "java -version" after each build')
894 parser.add_argument('-c', '--console', action='store_true', help='send build output to console instead of log file')
895
896 args = parser.parse_args(args)
897 vms = args.vms.split(',')
898 builds = args.builds.split(',')
899
900 allStart = time.time()
901 for v in vms:
902 for vmbuild in builds:
903 if v == 'original' and vmbuild != 'product':
904 continue
905 if not args.console:
906 logFile = join(v + '-' + vmbuild + '.log')
907 log = open(join(_graal_home, logFile), 'wb')
908 start = time.time()
909 mx.log('BEGIN: ' + v + '-' + vmbuild + '\t(see: ' + logFile + ')')
910 # Run as subprocess so that output can be directed to a file
911 subprocess.check_call([sys.executable, '-u', join('mxtool', 'mx.py'), '--vm', v, '--vmbuild',
912 vmbuild, 'build'], cwd=_graal_home, stdout=log, stderr=subprocess.STDOUT)
913 duration = datetime.timedelta(seconds=time.time() - start)
914 mx.log('END: ' + v + '-' + vmbuild + '\t[' + str(duration) + ']')
915 else:
916 with VM(v, vmbuild):
917 build([])
918 if not args.no_check:
919 vmargs = ['-version']
920 if v == 'graal':
921 vmargs.insert(0, '-XX:-BootstrapGraal')
922 vm(vmargs, vm=v, vmbuild=vmbuild)
923 allDuration = datetime.timedelta(seconds=time.time() - allStart)
924 mx.log('TOTAL TIME: ' + '[' + str(allDuration) + ']')
925
926 class Task:
927 def __init__(self, title):
928 self.start = time.time()
929 self.title = title
930 self.end = None
931 self.duration = None
932 mx.log(time.strftime('gate: %d %b %Y %H:%M:%S: BEGIN: ') + title)
933 def stop(self):
934 self.end = time.time()
935 self.duration = datetime.timedelta(seconds=self.end - self.start)
936 mx.log(time.strftime('gate: %d %b %Y %H:%M:%S: END: ') + self.title + ' [' + str(self.duration) + ']')
937 return self
938 def abort(self, codeOrMessage):
939 self.end = time.time()
940 self.duration = datetime.timedelta(seconds=self.end - self.start)
941 mx.log(time.strftime('gate: %d %b %Y %H:%M:%S: ABORT: ') + self.title + ' [' + str(self.duration) + ']')
942 mx.abort(codeOrMessage)
943 return self
944
945 def _basic_gate_body(args, tasks):
946 t = Task('BuildHotSpotGraal: fastdebug,product')
947 buildvms(['--vms', 'graal,server', '--builds', 'fastdebug,product'])
948 tasks.append(t.stop())
949
950 with VM('graal', 'fastdebug'):
951 t = Task('BootstrapWithSystemAssertions:fastdebug')
952 vm(['-esa', '-version'])
953 tasks.append(t.stop())
954
955 with VM('graal', 'product'):
956 t = Task('BootstrapWithGCVerification:product')
957 out = mx.DuplicateSuppressingStream(['VerifyAfterGC:', 'VerifyBeforeGC:']).write
958 vm(['-XX:+UnlockDiagnosticVMOptions', '-XX:+VerifyBeforeGC', '-XX:+VerifyAfterGC', '-version'], out=out)
959 tasks.append(t.stop())
960
961 with VM('graal', 'product'):
962 t = Task('BootstrapWithG1GCVerification:product')
963 out = mx.DuplicateSuppressingStream(['VerifyAfterGC:', 'VerifyBeforeGC:']).write
964 vm(['-XX:+UnlockDiagnosticVMOptions', '-XX:-UseSerialGC', '-XX:+UseG1GC', '-XX:+VerifyBeforeGC', '-XX:+VerifyAfterGC', '-version'], out=out)
965 tasks.append(t.stop())
966
967 with VM('graal', 'product'):
968 t = Task('BootstrapWithRegisterPressure:product')
969 vm(['-G:RegisterPressure=rbx,r11,r10,r14,xmm3,xmm11,xmm14', '-esa', '-version'])
970 tasks.append(t.stop())
971
972 with VM('graal', 'product'):
973 t = Task('BootstrapWithAOTConfiguration:product')
974 vm(['-G:+AOTCompilation', '-G:+VerifyPhases', '-esa', '-version'])
975 tasks.append(t.stop())
976
977 with VM('server', 'product'): # hosted mode
978 t = Task('UnitTests:hosted-product')
979 unittest([])
980 tasks.append(t.stop())
981
982 for vmbuild in ['fastdebug', 'product']:
983 for test in sanitycheck.getDacapos(level=sanitycheck.SanityCheckLevel.Gate, gateBuildLevel=vmbuild):
984 t = Task(str(test) + ':' + vmbuild)
985 if not test.test('graal'):
986 t.abort(test.name + ' Failed')
987 tasks.append(t.stop())
988
989 if args.jacocout is not None:
990 jacocoreport([args.jacocout])
991
992 global _jacoco
993 _jacoco = 'off'
994
995 t = Task('CleanAndBuildIdealGraphVisualizer')
996 mx.run(['ant', '-f', join(_graal_home, 'src', 'share', 'tools', 'IdealGraphVisualizer', 'build.xml'), '-q', 'clean', 'build'])
997 tasks.append(t.stop())
998
999 # Prevent Graal modifications from breaking the standard builds
1000 if args.buildNonGraal:
1001 t = Task('BuildHotSpotVarieties')
1002 buildvms(['--vms', 'client,server', '--builds', 'fastdebug,product'])
1003 buildvms(['--vms', 'server-nograal', '--builds', 'product'])
1004 buildvms(['--vms', 'server-nograal', '--builds', 'optimized'])
1005 tasks.append(t.stop())
1006
1007 for vmbuild in ['product', 'fastdebug']:
1008 for theVm in ['client', 'server']:
1009 with VM(theVm, vmbuild):
1010 t = Task('DaCapo_pmd:' + theVm + ':' + vmbuild)
1011 dacapo(['pmd'])
1012 tasks.append(t.stop())
1013
1014 t = Task('UnitTests:' + theVm + ':' + vmbuild)
1015 unittest(['-XX:CompileCommand=exclude,*::run*', 'graal.api'])
1016 tasks.append(t.stop())
1017
1018
1019 def gate(args, gate_body=_basic_gate_body):
1020 """run the tests used to validate a push
1021
1022 If this command exits with a 0 exit code, then the source code is in
1023 a state that would be accepted for integration into the main repository."""
1024
1025 parser = ArgumentParser(prog='mx gate')
1026 parser.add_argument('-j', '--omit-java-clean', action='store_false', dest='cleanJava', help='omit cleaning Java native code')
1027 parser.add_argument('-n', '--omit-native-clean', action='store_false', dest='cleanNative', help='omit cleaning and building native code')
1028 parser.add_argument('-g', '--only-build-graalvm', action='store_false', dest='buildNonGraal', help='only build the Graal VM')
1029 parser.add_argument('--jacocout', help='specify the output directory for jacoco report')
1030
1031 args = parser.parse_args(args)
1032
1033 global _jacoco
1034
1035 tasks = []
1036 total = Task('Gate')
1037 try:
1038
1039 t = Task('Pylint')
1040 mx.pylint([])
1041 tasks.append(t.stop())
1042
1043 t = Task('Clean')
1044 cleanArgs = []
1045 if not args.cleanNative:
1046 cleanArgs.append('--no-native')
1047 if not args.cleanJava:
1048 cleanArgs.append('--no-java')
1049 clean(cleanArgs)
1050 tasks.append(t.stop())
1051
1052 t = Task('IDEConfigCheck')
1053 mx.ideclean([])
1054 mx.ideinit([])
1055 tasks.append(t.stop())
1056
1057 eclipse_exe = os.environ.get('ECLIPSE_EXE')
1058 if eclipse_exe is not None:
1059 t = Task('CodeFormatCheck')
1060 if mx.eclipseformat(['-e', eclipse_exe]) != 0:
1061 t.abort('Formatter modified files - run "mx eclipseformat", check in changes and repush')
1062 tasks.append(t.stop())
1063
1064 t = Task('Canonicalization Check')
1065 mx.log(time.strftime('%d %b %Y %H:%M:%S - Ensuring mx/projects files are canonicalized...'))
1066 if mx.canonicalizeprojects([]) != 0:
1067 t.abort('Rerun "mx canonicalizeprojects" and check-in the modified mx/projects files.')
1068 tasks.append(t.stop())
1069
1070 t = Task('BuildJava')
1071 build(['--no-native', '--jdt-warning-as-error'])
1072 tasks.append(t.stop())
1073
1074 t = Task('Checkstyle')
1075 if mx.checkstyle([]) != 0:
1076 t.abort('Checkstyle warnings were found')
1077 tasks.append(t.stop())
1078
1079 if exists('jacoco.exec'):
1080 os.unlink('jacoco.exec')
1081
1082 if args.jacocout is not None:
1083 _jacoco = 'append'
1084 else:
1085 _jacoco = 'off'
1086
1087 gate_body(args, tasks)
1088
1089 except KeyboardInterrupt:
1090 total.abort(1)
1091
1092 except BaseException as e:
1093 import traceback
1094 traceback.print_exc()
1095 total.abort(str(e))
1096
1097 total.stop()
1098
1099 mx.log('Gate task times:')
1100 for t in tasks:
1101 mx.log(' ' + str(t.duration) + '\t' + t.title)
1102 mx.log(' =======')
1103 mx.log(' ' + str(total.duration))
1104
1105 def deoptalot(args):
1106 """bootstrap a fastdebug Graal VM with DeoptimizeALot and VerifyOops on
1107
1108 If the first argument is a number, the process will be repeated
1109 this number of times. All other arguments are passed to the VM."""
1110 count = 1
1111 if len(args) > 0 and args[0].isdigit():
1112 count = int(args[0])
1113 del args[0]
1114
1115 for _ in range(count):
1116 if not vm(['-XX:+DeoptimizeALot', '-XX:+VerifyOops'] + args + ['-version'], vmbuild='fastdebug') == 0:
1117 mx.abort("Failed")
1118
1119 def longtests(args):
1120
1121 deoptalot(['15', '-Xmx48m'])
1122
1123 dacapo(['100', 'eclipse', '-esa'])
1124
1125 def gv(args):
1126 """run the Graal Visualizer"""
1127 with open(join(_graal_home, '.graal_visualizer.log'), 'w') as fp:
1128 mx.logv('[Graal Visualizer log is in ' + fp.name + ']')
1129 if not exists(join(_graal_home, 'visualizer', 'build.xml')):
1130 mx.logv('[This initial execution may take a while as the NetBeans platform needs to be downloaded]')
1131 mx.run(['ant', '-f', join(_graal_home, 'visualizer', 'build.xml'), '-l', fp.name, 'run'])
1132
1133 def igv(args):
1134 """run the Ideal Graph Visualizer"""
1135 with open(join(_graal_home, '.ideal_graph_visualizer.log'), 'w') as fp:
1136 mx.logv('[Ideal Graph Visualizer log is in ' + fp.name + ']')
1137 if not exists(join(_graal_home, 'src', 'share', 'tools', 'IdealGraphVisualizer', 'nbplatform')):
1138 mx.logv('[This initial execution may take a while as the NetBeans platform needs to be downloaded]')
1139 mx.run(['ant', '-f', join(_graal_home, 'src', 'share', 'tools', 'IdealGraphVisualizer', 'build.xml'), '-l', fp.name, 'run'])
1140
1141 def bench(args):
1142 """run benchmarks and parse their output for results
1143
1144 Results are JSON formated : {group : {benchmark : score}}."""
1145 resultFile = None
1146 if '-resultfile' in args:
1147 index = args.index('-resultfile')
1148 if index + 1 < len(args):
1149 resultFile = args[index + 1]
1150 del args[index]
1151 del args[index]
1152 else:
1153 mx.abort('-resultfile must be followed by a file name')
1154 vm = _get_vm()
1155 if len(args) is 0:
1156 args = ['all']
1157
1158 vmArgs = [arg for arg in args if arg.startswith('-')]
1159
1160 def benchmarks_in_group(group):
1161 prefix = group + ':'
1162 return [a[len(prefix):] for a in args if a.startswith(prefix)]
1163
1164 results = {}
1165 benchmarks = []
1166 # DaCapo
1167 if ('dacapo' in args or 'all' in args):
1168 benchmarks += sanitycheck.getDacapos(level=sanitycheck.SanityCheckLevel.Benchmark)
1169 else:
1170 dacapos = benchmarks_in_group('dacapo')
1171 for dacapo in dacapos:
1172 if dacapo not in sanitycheck.dacapoSanityWarmup.keys():
1173 mx.abort('Unknown DaCapo : ' + dacapo)
1174 iterations = sanitycheck.dacapoSanityWarmup[dacapo][sanitycheck.SanityCheckLevel.Benchmark]
1175 if (iterations > 0):
1176 benchmarks += [sanitycheck.getDacapo(dacapo, iterations)]
1177
1178 if ('scaladacapo' in args or 'all' in args):
1179 benchmarks += sanitycheck.getScalaDacapos(level=sanitycheck.SanityCheckLevel.Benchmark)
1180 else:
1181 scaladacapos = benchmarks_in_group('scaladacapo')
1182 for scaladacapo in scaladacapos:
1183 if scaladacapo not in sanitycheck.dacapoScalaSanityWarmup.keys():
1184 mx.abort('Unknown Scala DaCapo : ' + scaladacapo)
1185 iterations = sanitycheck.dacapoScalaSanityWarmup[scaladacapo][sanitycheck.SanityCheckLevel.Benchmark]
1186 if (iterations > 0):
1187 benchmarks += [sanitycheck.getScalaDacapo(scaladacapo, ['-n', str(iterations)])]
1188
1189 # Bootstrap
1190 if ('bootstrap' in args or 'all' in args):
1191 benchmarks += sanitycheck.getBootstraps()
1192 # SPECjvm2008
1193 if ('specjvm2008' in args or 'all' in args):
1194 benchmarks += [sanitycheck.getSPECjvm2008(['-ikv', '-wt', '120', '-it', '120'])]
1195 else:
1196 specjvms = benchmarks_in_group('specjvm2008')
1197 for specjvm in specjvms:
1198 benchmarks += [sanitycheck.getSPECjvm2008(['-ikv', '-wt', '120', '-it', '120', specjvm])]
1199
1200 if ('specjbb2005' in args or 'all' in args):
1201 benchmarks += [sanitycheck.getSPECjbb2005()]
1202
1203 if ('specjbb2013' in args): # or 'all' in args //currently not in default set
1204 benchmarks += [sanitycheck.getSPECjbb2013()]
1205
1206 if ('ctw-full' in args):
1207 benchmarks.append(sanitycheck.getCTW(vm, sanitycheck.CTWMode.Full))
1208 if ('ctw-noinline' in args):
1209 benchmarks.append(sanitycheck.getCTW(vm, sanitycheck.CTWMode.NoInline))
1210 if ('ctw-nocomplex' in args):
1211 benchmarks.append(sanitycheck.getCTW(vm, sanitycheck.CTWMode.NoComplex))
1212
1213 for test in benchmarks:
1214 for (groupName, res) in test.bench(vm, extraVmOpts=vmArgs).items():
1215 group = results.setdefault(groupName, {})
1216 group.update(res)
1217 mx.log(json.dumps(results))
1218 if resultFile:
1219 with open(resultFile, 'w') as f:
1220 f.write(json.dumps(results))
1221
1222 def specjvm2008(args):
1223 """run one or more SPECjvm2008 benchmarks"""
1224
1225 def launcher(bm, harnessArgs, extraVmOpts):
1226 return sanitycheck.getSPECjvm2008(harnessArgs + [bm]).bench(_get_vm(), extraVmOpts=extraVmOpts)
1227
1228 availableBenchmarks = set(sanitycheck.specjvm2008Names)
1229 for name in sanitycheck.specjvm2008Names:
1230 parts = name.rsplit('.', 1)
1231 if len(parts) > 1:
1232 assert len(parts) == 2
1233 group = parts[0]
1234 availableBenchmarks.add(group)
1235
1236 _run_benchmark(args, sorted(availableBenchmarks), launcher)
1237
1238 def specjbb2013(args):
1239 """runs the composite SPECjbb2013 benchmark"""
1240
1241 def launcher(bm, harnessArgs, extraVmOpts):
1242 assert bm is None
1243 return sanitycheck.getSPECjbb2013(harnessArgs).bench(_get_vm(), extraVmOpts=extraVmOpts)
1244
1245 _run_benchmark(args, None, launcher)
1246
1247 def specjbb2005(args):
1248 """runs the composite SPECjbb2005 benchmark"""
1249
1250 def launcher(bm, harnessArgs, extraVmOpts):
1251 assert bm is None
1252 return sanitycheck.getSPECjbb2005(harnessArgs).bench(_get_vm(), extraVmOpts=extraVmOpts)
1253
1254 _run_benchmark(args, None, launcher)
1255
1256 def hsdis(args, copyToDir=None):
1257 """download the hsdis library
1258
1259 This is needed to support HotSpot's assembly dumping features.
1260 By default it downloads the Intel syntax version, use the 'att' argument to install AT&T syntax."""
1261 flavor = 'intel'
1262 if 'att' in args:
1263 flavor = 'att'
1264 lib = mx.add_lib_suffix('hsdis-' + _arch())
1265 path = join(_graal_home, 'lib', lib)
1266 if not exists(path):
1267 mx.download(path, ['http://lafo.ssw.uni-linz.ac.at/hsdis/' + flavor + "/" + lib])
1268 if copyToDir is not None and exists(copyToDir):
1269 shutil.copy(path, copyToDir)
1270
1271 def hcfdis(args):
1272 """disassemble HexCodeFiles embedded in text files
1273
1274 Run a tool over the input files to convert all embedded HexCodeFiles
1275 to a disassembled format."""
1276
1277 parser = ArgumentParser(prog='mx hcfdis')
1278 parser.add_argument('-m', '--map', help='address to symbol map applied to disassembler output')
1279 parser.add_argument('files', nargs=REMAINDER, metavar='files...')
1280
1281 args = parser.parse_args(args)
1282
1283 path = join(_graal_home, 'lib', 'hcfdis-1.jar')
1284 if not exists(path):
1285 mx.download(path, ['http://lafo.ssw.uni-linz.ac.at/hcfdis-1.jar'])
1286 mx.run_java(['-jar', path] + args.files)
1287
1288 if args.map is not None:
1289 addressRE = re.compile(r'0[xX]([A-Fa-f0-9]+)')
1290 with open(args.map) as fp:
1291 lines = fp.read().splitlines()
1292 symbols = dict()
1293 for l in lines:
1294 addressAndSymbol = l.split(' ', 1)
1295 if len(addressAndSymbol) == 2:
1296 address, symbol = addressAndSymbol
1297 if address.startswith('0x'):
1298 address = long(address, 16)
1299 symbols[address] = symbol
1300 for f in args.files:
1301 with open(f) as fp:
1302 lines = fp.read().splitlines()
1303 updated = False
1304 for i in range(0, len(lines)):
1305 l = lines[i]
1306 for m in addressRE.finditer(l):
1307 sval = m.group(0)
1308 val = long(sval, 16)
1309 sym = symbols.get(val)
1310 if sym:
1311 l = l.replace(sval, sym)
1312 updated = True
1313 lines[i] = l
1314 if updated:
1315 mx.log('updating ' + f)
1316 with open('new_' + f, "w") as fp:
1317 for l in lines:
1318 print >> fp, l
1319
1320 def jacocoreport(args):
1321 """create a JaCoCo coverage report
1322
1323 Creates the report from the 'jacoco.exec' file in the current directory.
1324 Default output directory is 'coverage', but an alternative can be provided as an argument."""
1325 jacocoreport = mx.library("JACOCOREPORT", True)
1326 out = 'coverage'
1327 if len(args) == 1:
1328 out = args[0]
1329 elif len(args) > 1:
1330 mx.abort('jacocoreport takes only one argument : an output directory')
1331 mx.run_java(['-jar', jacocoreport.get_path(True), '-in', 'jacoco.exec', '-g', join(_graal_home, 'graal'), out])
1332
1333 def sl(args):
1334 """run an SL program"""
1335 vmArgs, slArgs = _extract_VM_args(args)
1336 vm(vmArgs + ['-cp', mx.classpath("com.oracle.truffle.sl"), "com.oracle.truffle.sl.SimpleLanguage"] + slArgs)
1337
1338 def isGraalEnabled(vm):
1339 return vm != 'original' and not vm.endswith('nograal')
1340
1341 def site(args):
1342 """create a website containing javadoc and the project dependency graph"""
1343
1344 return mx.site(['--name', 'Graal',
1345 '--jd', '@-tag', '--jd', '@test:X',
1346 '--jd', '@-tag', '--jd', '@run:X',
1347 '--jd', '@-tag', '--jd', '@bug:X',
1348 '--jd', '@-tag', '--jd', '@summary:X',
1349 '--jd', '@-tag', '--jd', '@vmoption:X',
1350 '--overview', join(_graal_home, 'graal', 'overview.html'),
1351 '--title', 'Graal OpenJDK Project Documentation',
1352 '--dot-output-base', 'projects'] + args)
1353
1354 def mx_init(suite):
1355 commands = {
1356 'build': [build, ''],
1357 'buildvars': [buildvars, ''],
1358 'buildvms': [buildvms, '[-options]'],
1359 'clean': [clean, ''],
1360 'hsdis': [hsdis, '[att]'],
1361 'hcfdis': [hcfdis, ''],
1362 'igv' : [igv, ''],
1363 'jdkhome': [print_jdkhome, ''],
1364 'dacapo': [dacapo, '[VM options] benchmarks...|"all" [DaCapo options]'],
1365 'scaladacapo': [scaladacapo, '[VM options] benchmarks...|"all" [Scala DaCapo options]'],
1366 'specjvm2008': [specjvm2008, '[VM options] benchmarks...|"all" [SPECjvm2008 options]'],
1367 'specjbb2013': [specjbb2013, '[VM options] [-- [SPECjbb2013 options]]'],
1368 'specjbb2005': [specjbb2005, '[VM options] [-- [SPECjbb2005 options]]'],
1369 'gate' : [gate, '[-options]'],
1370 'gv' : [gv, ''],
1371 'bench' : [bench, '[-resultfile file] [all(default)|dacapo|specjvm2008|bootstrap]'],
1372 'unittest' : [unittest, '[VM options] [filters...]', _unittestHelpSuffix],
1373 'longunittest' : [longunittest, '[VM options] [filters...]', _unittestHelpSuffix],
1374 'shortunittest' : [shortunittest, '[VM options] [filters...]', _unittestHelpSuffix],
1375 'jacocoreport' : [jacocoreport, '[output directory]'],
1376 'site' : [site, '[-options]'],
1377 'vm': [vm, '[-options] class [args...]'],
1378 'vmg': [vmg, '[-options] class [args...]'],
1379 'vmfg': [vmfg, '[-options] class [args...]'],
1380 'deoptalot' : [deoptalot, '[n]'],
1381 'longtests' : [longtests, ''],
1382 'sl' : [sl, '[SL args|@VM options]']
1383 }
1384
1385 mx.add_argument('--jacoco', help='instruments com.oracle.* classes using JaCoCo', default='off', choices=['off', 'on', 'append'])
1386 mx.add_argument('--vmcwd', dest='vm_cwd', help='current directory will be changed to <path> before the VM is executed', default=None, metavar='<path>')
1387 mx.add_argument('--installed-jdks', help='the base directory in which the JDKs cloned from $JAVA_HOME exist. ' +
1388 'The VM selected by --vm and --vmbuild options is under this directory (i.e., ' +
1389 join('<path>', '<jdk-version>', '<vmbuild>', 'jre', 'lib', '<vm>', mx.add_lib_prefix(mx.add_lib_suffix('jvm'))) + ')', default=None, metavar='<path>')
1390
1391 if (_vmSourcesAvailable):
1392 mx.add_argument('--vm', action='store', dest='vm', choices=_vmChoices.keys(), help='the VM type to build/run')
1393 mx.add_argument('--vmbuild', action='store', dest='vmbuild', choices=_vmbuildChoices, help='the VM build to build/run (default: ' + _vmbuildChoices[0] + ')')
1394 mx.add_argument('--ecl', action='store_true', dest='make_eclipse_launch', help='create launch configuration for running VM execution(s) in Eclipse')
1395 mx.add_argument('--vmprefix', action='store', dest='vm_prefix', help='prefix for running the VM (e.g. "/usr/bin/gdb --args")', metavar='<prefix>')
1396 mx.add_argument('--gdb', action='store_const', const='/usr/bin/gdb --args', dest='vm_prefix', help='alias for --vmprefix "/usr/bin/gdb --args"')
1397
1398 commands.update({
1399 'export': [export, '[-options] [zipfile]'],
1400 })
1401
1402 mx.update_commands(suite, commands)
1403
1404 def mx_post_parse_cmd_line(opts): #
1405 # TODO _minVersion check could probably be part of a Suite in mx?
1406 if (mx.java().version < _minVersion) :
1407 mx.abort('Requires Java version ' + str(_minVersion) + ' or greater, got version ' + str(mx.java().version))
1408
1409 if (_vmSourcesAvailable):
1410 if hasattr(opts, 'vm') and opts.vm is not None:
1411 global _vm
1412 _vm = opts.vm
1413 if hasattr(opts, 'vmbuild') and opts.vmbuild is not None:
1414 global _vmbuild
1415 _vmbuild = opts.vmbuild
1416 global _make_eclipse_launch
1417 _make_eclipse_launch = getattr(opts, 'make_eclipse_launch', False)
1418 global _jacoco
1419 _jacoco = opts.jacoco
1420 global _vm_cwd
1421 _vm_cwd = opts.vm_cwd
1422 global _installed_jdks
1423 _installed_jdks = opts.installed_jdks
1424 global _vm_prefix
1425 _vm_prefix = opts.vm_prefix
1426
1427 mx.distribution('GRAAL').add_update_listener(_installGraalJarInJdks)