changeset 11296:4e943a311d9c

mx presents a command line dialogue to select the default VM if it is not configured (GRAAL-416) added prompt to build missing VM the first time it is executed cleaner support using 'with' statement for switching the configured VM within a scope
author Doug Simon <doug.simon@oracle.com>
date Tue, 13 Aug 2013 14:23:58 +0200
parents bb70a309a7cf
children dc4cedf73358
files mx/commands.py
diffstat 1 files changed, 120 insertions(+), 60 deletions(-) [+]
line wrap: on
line diff
--- a/mx/commands.py	Tue Aug 13 11:07:08 2013 +0200
+++ b/mx/commands.py	Tue Aug 13 14:23:58 2013 +0200
@@ -39,18 +39,28 @@
 """ Used to distinguish an exported GraalVM (see 'mx export'). """
 _vmSourcesAvailable = exists(join(_graal_home, 'make')) and exists(join(_graal_home, 'src'))
 
-""" The VMs that can be built and run - default is first in list """
-_vmChoices = ['graal', 'server', 'client', 'server-nograal', 'client-nograal', 'original']
+""" The VMs that can be built and run along with an optional description. Only VMs with a
+    description are listed in the dialogue for setting the default VM (see _get_vm()). """
+_vmChoices = {
+    'graal' : 'All compilation is performed with Graal. This includes bootstrapping Graal itself unless -XX:-BootstrapGraal is used.',
+    '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.',
+    'client' : None, # normal compilation with client compiler, explicit compilation (e.g., by Truffle) with Graal
+    'server-nograal' : None, # all compilation with tiered system (i.e., client + server), Graal omitted
+    'client-nograal' : None, # all compilation with client compiler, Graal omitted
+    'original' : None, # default VM copied from bootstrap JDK
+}
 
 """ The VM that will be run by the 'vm' command and built by default by the 'build' command.
-    This can be set via the global '--vm' option. """
-_vm = _vmChoices[0]
+    This can be set via the global '--vm' option or the DEFAULT_VM environment variable.
+    It can also be temporarily set by using of a VM context manager object in a 'with' statement. """
+_vm = None
 
 """ The VM builds that will be run by the 'vm' command - default is first in list """
 _vmbuildChoices = ['product', 'fastdebug', 'debug', 'optimized']
 
 """ The VM build that will be run by the 'vm' command.
-    This can be set via the global '--product', '--fastdebug' and '--debug' options. """
+    This can be set via the global '--product', '--fastdebug' and '--debug' options.
+    It can also be temporarily set by using of a VM context manager object in a 'with' statement. """
 _vmbuild = _vmbuildChoices[0]
 
 _jacoco = 'off'
@@ -65,6 +75,55 @@
 
 _minVersion = mx.JavaVersion('1.7.0_04')
 
+def _get_vm():
+    """
+    Gets the configured VM, presenting a dialogue if there is no currently configured VM.
+    """
+    global _vm
+    if _vm:
+        return _vm
+    vm = mx.get_env('DEFAULT_VM')
+    if vm is None:
+        if not sys.stdout.isatty():
+            mx.abort('Need to specify VM with --vm option or DEFAULT_VM environment variable')
+        envPath = join(_graal_home, 'mx', 'env')
+        mx.log('Please select the VM to be executed from the following: ')
+        items = [k for k in _vmChoices.keys() if _vmChoices[k] is not None]
+        descriptions = [_vmChoices[k] for k in _vmChoices.keys() if _vmChoices[k] is not None]
+        vm = mx.select_items(items, descriptions, allowMultiple=False)
+        answer = raw_input('Persist this choice by adding "DEFAULT_VM=' + vm + '" to ' + envPath + '? [Yn]: ')
+        if not answer.lower().startswith('n'):
+            with open(envPath, 'a') as fp:
+                print >> fp, 'DEFAULT_VM=' + vm
+    _vm = vm
+    return vm
+
+""" 
+A context manager that can be used with the 'with' statement to set the VM
+used by all VM executions within the scope of the 'with' statement. For example:
+
+    with VM('server'):
+        dacapo(['pmd'])
+"""
+class VM:
+    def __init__(self, vm=None, build=None):
+        assert vm is None or vm in _vmChoices.keys()
+        assert build is None or build in _vmbuildChoices
+        self.vm = vm if vm else _vm
+        self.build = build if build else _vmbuild
+        self.previousVm = _vm
+        self.previousBuild = _vmbuild
+        
+    def __enter__(self):
+        global _vm, _vmbuild
+        _vm = self.vm
+        _vmbuild = self.build
+        
+    def __exit__(self, exc_type, exc_value, traceback):
+        global _vm, _vmbuild
+        _vm = self.previousVm
+        _vmbuild = self.previousBuild
+    
 def _chmodDir(chmodFlags, dirname, fnames):
     os.chmod(dirname, chmodFlags)
     for name in fnames:
@@ -172,7 +231,7 @@
 
     # The remainder are VM options
     vmOpts = [arg for arg in args if not arg.startswith('@')]
-    vm = _vm
+    vm = _get_vm()
 
     failed = []
     for (test, n) in numTests.items():
@@ -223,7 +282,7 @@
 
     # The remainder are VM options
     vmOpts = [arg for arg in args if not arg.startswith('@')]
-    vm = _vm;
+    vm = _get_vm()
 
     failed = []
     for (test, n) in numTests.items():
@@ -271,6 +330,15 @@
 def _jdksDir():
     return os.path.abspath(join(_vmdir if _vmdir else _graal_home, 'jdk' + str(mx.java().version)))
 
+def _handle_missing_VM(bld, vm):
+    mx.log('The ' + bld + ' ' + vm + ' VM has not been created')
+    if sys.stdout.isatty():
+        answer = raw_input('Build it now? [Yn]: ')
+        if not answer.lower().startswith('n'):
+            build([bld], vm=vm)
+            return
+    mx.abort('You need to run "mx --vm ' + vm + ' build ' + bld + '" to build the selected VM')
+
 def _jdk(build='product', vmToCheck=None, create=False, installGraalJar=True):
     """
     Get the JDK into which Graal is installed, creating it first if necessary.
@@ -330,8 +398,7 @@
                 pass
     else:
         if not exists(jdk):
-            vmOption = ' --vm ' + vmToCheck if vmToCheck else ''
-            mx.abort('The ' + build + ' VM has not been created - run "mx' + vmOption + ' build ' + build + '"')
+            _handle_missing_VM(build, vmToCheck if vmToCheck else 'graal')
             
     if installGraalJar:
         _installGraalJarInJdks(mx.distribution('GRAAL'))
@@ -345,7 +412,7 @@
                     found = True
                     break
         if not found:
-            mx.abort('The ' + build + ' ' + vmToCheck + ' VM has not been created - run "mx --vm ' + vmToCheck + ' build ' + build + '"')
+            _handle_missing_VM(build, vmToCheck)
         
     return jdk
 
@@ -483,7 +550,7 @@
         builds = ['product']
 
     if vm is None:
-        vm = _vm
+        vm = _get_vm()
 
     if vm == 'original':
         pass
@@ -649,7 +716,7 @@
     """run the VM selected by the '--vm' option"""
 
     if vm is None:
-        vm = _vm
+        vm = _get_vm()
 
     if cwd is None:
         cwd = _workdir
@@ -759,7 +826,7 @@
     def harness(projectscp, vmArgs):
         if not exists(javaClass) or getmtime(javaClass) < getmtime(javaSource):
             subprocess.check_call([mx.java().javac, '-cp', projectscp, '-d', mxdir, javaSource])
-        if not isGraalEnabled(_vm):
+        if not isGraalEnabled(_get_vm()):
             prefixArgs = ['-esa', '-ea']
         else:
             prefixArgs = ['-XX:-BootstrapGraal', '-esa', '-ea']
@@ -824,7 +891,7 @@
 def buildvms(args):
     """build one or more VMs in various configurations"""
 
-    vmsDefault = ','.join(_vmChoices)
+    vmsDefault = ','.join(_vmChoices.keys())
     vmbuildsDefault = ','.join(_vmbuildChoices)
     
     parser = ArgumentParser(prog='mx buildvms');
@@ -852,9 +919,8 @@
                 duration = datetime.timedelta(seconds=time.time() - start)
                 mx.log('END:   ' + v + '-' + vmbuild + '\t[' + str(duration) + ']')
             else:
-                global _vm
-                _vm = v
-                build([vmbuild])
+                with VM(v):
+                    build([vmbuild])
             if not args.no_check:
                 vmargs = ['-version']
                 if v == 'graal':
@@ -896,8 +962,6 @@
 
     args = parser.parse_args(args)
 
-    global _vmbuild
-    global _vm
     global _jacoco
     
     tasks = []
@@ -952,37 +1016,35 @@
         buildvms(['--vms', 'graal,server', '--builds', 'fastdebug,product'])
         tasks.append(t.stop())
 
-        _vmbuild = 'fastdebug'
-        t = Task('BootstrapWithSystemAssertions:fastdebug')
-        vm(['-esa', '-version'])
-        tasks.append(t.stop())
+        with VM('graal', 'fastdebug'):
+            t = Task('BootstrapWithSystemAssertions:fastdebug')
+            vm(['-esa', '-version'])
+            tasks.append(t.stop())
 
-        _vmbuild = 'product'
-        t = Task('BootstrapWithGCVerification:product')
-        vm(['-XX:+UnlockDiagnosticVMOptions', '-XX:+VerifyBeforeGC', '-XX:+VerifyAfterGC', '-version'])
-        tasks.append(t.stop())
+        with VM('graal', 'product'):
+            t = Task('BootstrapWithGCVerification:product')
+            vm(['-XX:+UnlockDiagnosticVMOptions', '-XX:+VerifyBeforeGC', '-XX:+VerifyAfterGC', '-version'])
+            tasks.append(t.stop())
     
-        _vmbuild = 'product'
-        t = Task('BootstrapWithG1GCVerification:product')
-        vm(['-XX:+UnlockDiagnosticVMOptions', '-XX:-UseSerialGC','-XX:+UseG1GC','-XX:+UseNewCode','-XX:+VerifyBeforeGC', '-XX:+VerifyAfterGC', '-version'])
-        tasks.append(t.stop())
+        with VM('graal', 'product'):
+            t = Task('BootstrapWithG1GCVerification:product')
+            vm(['-XX:+UnlockDiagnosticVMOptions', '-XX:-UseSerialGC','-XX:+UseG1GC','-XX:+UseNewCode','-XX:+VerifyBeforeGC', '-XX:+VerifyAfterGC', '-version'])
+            tasks.append(t.stop())
 
-        _vmbuild = 'product'
-        t = Task('BootstrapWithRegisterPressure:product')
-        vm(['-G:RegisterPressure=rbx,r11,r10,r14,xmm3,xmm11,xmm14', '-esa', '-version'])
-        tasks.append(t.stop())
+        with VM('graal', 'product'):
+            t = Task('BootstrapWithRegisterPressure:product')
+            vm(['-G:RegisterPressure=rbx,r11,r10,r14,xmm3,xmm11,xmm14', '-esa', '-version'])
+            tasks.append(t.stop())
 
-        _vmbuild = 'product'
-        t = Task('BootstrapWithAOTConfiguration:product')
-        vm(['-G:+AOTCompilation', '-G:+VerifyPhases', '-esa', '-version'])
-        tasks.append(t.stop())
+        with VM('graal', 'product'):
+            t = Task('BootstrapWithAOTConfiguration:product')
+            vm(['-G:+AOTCompilation', '-G:+VerifyPhases', '-esa', '-version'])
+            tasks.append(t.stop())
 
-        originalVm = _vm
-        _vm = 'server' # hosted mode
-        t = Task('UnitTests:hosted-product')
-        unittest([])
-        tasks.append(t.stop())
-        _vm = originalVm
+        with VM('server', 'product'): # hosted mode
+            t = Task('UnitTests:hosted-product')
+            unittest([])
+            tasks.append(t.stop())
 
         for vmbuild in ['fastdebug', 'product']:
             for test in sanitycheck.getDacapos(level=sanitycheck.SanityCheckLevel.Gate, gateBuildLevel=vmbuild):
@@ -1009,17 +1071,15 @@
             tasks.append(t.stop())
 
             for vmbuild in ['product', 'fastdebug']:
-                _vmbuild = vmbuild
                 for theVm in ['client', 'server']:
-                    _vm = theVm
-
-                    t = Task('DaCapo_pmd:' + theVm + ':' + vmbuild)
-                    dacapo(['pmd'])
-                    tasks.append(t.stop())
-
-                    t = Task('UnitTests:' + theVm + ':' + vmbuild)
-                    unittest(['@-XX:CompileCommand=exclude,*::run*', 'graal.api'])
-                    tasks.append(t.stop())
+                    with VM(theVm, vmbuild):
+                        t = Task('DaCapo_pmd:' + theVm + ':' + vmbuild)
+                        dacapo(['pmd'])
+                        tasks.append(t.stop())
+    
+                        t = Task('UnitTests:' + theVm + ':' + vmbuild)
+                        unittest(['@-XX:CompileCommand=exclude,*::run*', 'graal.api'])
+                        tasks.append(t.stop())
 
     except KeyboardInterrupt:
         total.abort(1)
@@ -1086,7 +1146,7 @@
             del args[index]
         else:
             mx.abort('-resultfile must be followed by a file name')
-    vm = _vm
+    vm = _get_vm()
     if len(args) is 0:
         args = ['all']
     
@@ -1190,7 +1250,7 @@
             mx.abort('-it (Iteration time) needs a numeric value (seconds)')
         vmArgs.remove('-it')
         benchArgs.remove(args[itIdx+1])
-    vm = _vm;
+    vm = _get_vm();
     sanitycheck.getSPECjvm2008(benchArgs, skipCheck, skipValid, wt, it).bench(vm, opts=vmArgs)
     
 def specjbb2013(args):
@@ -1199,7 +1259,7 @@
     All options begining with - will be passed to the vm"""
     benchArgs = [a for a in args if a[0] != '-']
     vmArgs = [a for a in args if a[0] == '-']
-    vm = _vm;
+    vm = _get_vm();
     sanitycheck.getSPECjbb2013(benchArgs).bench(vm, opts=vmArgs)
 
 def specjbb2005(args):
@@ -1208,7 +1268,7 @@
         All options begining with - will be passed to the vm"""
     benchArgs = [a for a in args if a[0] != '-']
     vmArgs = [a for a in args if a[0] == '-']
-    vm = _vm;
+    vm = _get_vm();
     sanitycheck.getSPECjbb2005(benchArgs).bench(vm, opts=vmArgs)
 
 def hsdis(args, copyToDir=None):
@@ -1339,7 +1399,7 @@
     mx.add_argument('--vmdir', help='specify where the directory in which the vms should be', default=None)
 
     if (_vmSourcesAvailable):
-        mx.add_argument('--vm', action='store', dest='vm', default='graal', choices=_vmChoices, help='the VM to build/run (default: ' + _vmChoices[0] + ')')
+        mx.add_argument('--vm', action='store', dest='vm', choices=_vmChoices.keys(), help='the VM to build/run')
         for c in _vmbuildChoices:
             mx.add_argument('--' + c, action='store_const', dest='vmbuild', const=c, help='select the ' + c + ' build of the VM')
         mx.add_argument('--ecl', action='store_true', dest='make_eclipse_launch', help='create launch configuration for running VM execution(s) in Eclipse')