# HG changeset patch # User Doug Simon # Date 1406806976 -7200 # Node ID d3fec84757edbd4bf10eb04014bcda688d3c02c0 # Parent 68deb37eed70c940597f7c013465094abe79c8cb improved generated sources up-to-date check by using SHA1 digests diff -r 68deb37eed70 -r d3fec84757ed mx/mx_graal.py --- a/mx/mx_graal.py Thu Jul 31 12:00:23 2014 +0200 +++ b/mx/mx_graal.py Thu Jul 31 13:42:56 2014 +0200 @@ -30,6 +30,7 @@ from os.path import join, exists, dirname, basename from argparse import ArgumentParser, RawDescriptionHelpFormatter, REMAINDER from outputparser import OutputParser, ValuesMatcher +import hashlib import mx import xml.dom.minidom import sanitycheck @@ -486,39 +487,71 @@ os.unlink(toDelete) def _makeHotspotGeneratedSourcesDir(): + """ + Gets the directory containing all the HotSpot sources generated from + Graal Java sources. This directory will be created if it doesn't yet exist. + """ hsSrcGenDir = join(mx.project('com.oracle.graal.hotspot').source_gen_dir(), 'hotspot') if not exists(hsSrcGenDir): os.makedirs(hsSrcGenDir) return hsSrcGenDir +def _update_graalRuntime_inline_hpp(dist): + """ + (Re)generates graalRuntime.inline.hpp based on a given distribution + that transitively represents all the input for the generation process. -def _update_graalRuntime_inline_hpp(jars): + A SHA1 digest is computed for all generated content and is written to + graalRuntime.inline.hpp as well as stored in a generated class + that is appended to the dist.path jar. At runtime, these two digests + are checked for consistency. + """ + p = mx.project('com.oracle.graal.hotspot.sourcegen') mainClass = 'com.oracle.graal.hotspot.sourcegen.GenGraalRuntimeInlineHpp' if exists(join(p.output_dir(), mainClass.replace('.', os.sep) + '.class')): - graalRuntime_inline_hpp = join(_makeHotspotGeneratedSourcesDir(), 'graalRuntime.inline.hpp') + genSrcDir = _makeHotspotGeneratedSourcesDir() + graalRuntime_inline_hpp = join(genSrcDir, 'graalRuntime.inline.hpp') + cp = os.pathsep.join([mx.distribution(d).path for d in dist.distDependencies] + [dist.path, p.output_dir()]) tmp = StringIO.StringIO() - mx.run_java(['-cp', '{}{}{}'.format(os.pathsep.join(jars), os.pathsep, p.output_dir()), mainClass], out=tmp.write) + mx.run_java(['-cp', cp, mainClass], out=tmp.write) + + # Compute SHA1 for currently generated graalRuntime.inline.hpp content + # and all other generated sources in genSrcDir + d = hashlib.sha1() + d.update(tmp.getvalue()) + for e in os.listdir(genSrcDir): + if e != 'graalRuntime.inline.hpp': + with open(join(genSrcDir, e)) as fp: + d.update(fp.read()) + sha1 = d.hexdigest() + + # Add SHA1 to end of graalRuntime.inline.hpp + print >> tmp, '' + print >> tmp, 'const char* GraalRuntime::_generated_sources_sha1 = "' + sha1 + '";' + mx.update_file(graalRuntime_inline_hpp, tmp.getvalue()) -def _checkVMIsNewerThanGeneratedSources(jdk, vm, bld): - if isGraalEnabled(vm) and (not _installed_jdks or _installed_jdks == _graal_home): - vmLib = mx.TimeStampFile(join(_vmLibDirInJdk(jdk), vm, mx.add_lib_prefix(mx.add_lib_suffix('jvm')))) - for name in ['graalRuntime.inline.hpp', 'HotSpotVMConfig.inline.hpp']: - genSrc = join(_makeHotspotGeneratedSourcesDir(), name) - if vmLib.isOlderThan(genSrc): - mx.log('The VM ' + vmLib.path + ' is older than ' + genSrc) - mx.abort('You need to run "mx --vm ' + vm + ' --vmbuild ' + bld + ' build"') + # Store SHA1 in generated Java class and append class to specified jar + javaSource = join(_graal_home, 'GeneratedSourcesSha1.java') + javaClass = join(_graal_home, 'GeneratedSourcesSha1.class') + with open (javaSource, 'w') as fp: + print >> fp, 'class GeneratedSourcesSha1 { private static final String value = "' + sha1 + '"; }' + subprocess.check_call([mx.java().javac, '-d', _graal_home, javaSource], stderr=subprocess.PIPE, stdout=subprocess.PIPE) + zf = zipfile.ZipFile(dist.path, 'a') + with open(javaClass, 'rb') as fp: + zf.writestr(os.path.basename(javaClass), fp.read()) + zf.close() + os.unlink(javaSource) + os.unlink(javaClass) def _installDistInJdks(dist): """ Installs the jar(s) for a given Distribution into all existing Graal JDKs """ - distJar = dist.path if dist.name == 'GRAAL_TRUFFLE': - jars = [mx.distribution(d).path for d in dist.distDependencies] + [distJar] - _update_graalRuntime_inline_hpp(jars) + _update_graalRuntime_inline_hpp(dist) jdks = _jdksDir() if exists(jdks): @@ -544,7 +577,7 @@ shutil.move(tmp, dstJar) os.chmod(dstJar, JDK_UNIX_PERMISSIONS_FILE) - install(distJar, jreLibDir) + install(dist.path, jreLibDir) if dist.sourcesPath: install(dist.sourcesPath, join(jdks, e)) @@ -920,7 +953,6 @@ build = vmbuild if vmbuild is not None else _vmbuild if _vmSourcesAvailable else 'product' jdk = _jdk(build, vmToCheck=vm, installJars=False) _updateInstalledGraalOptionsFile(jdk) - _checkVMIsNewerThanGeneratedSources(jdk, vm, build) mx.expand_project_in_args(args) if _make_eclipse_launch: mx.make_eclipse_launch(args, 'graal-' + build, name=None, deps=mx.project('com.oracle.graal.hotspot').all_deps([], True)) diff -r 68deb37eed70 -r d3fec84757ed src/share/vm/graal/graalRuntime.cpp --- a/src/share/vm/graal/graalRuntime.cpp Thu Jul 31 12:00:23 2014 +0200 +++ b/src/share/vm/graal/graalRuntime.cpp Thu Jul 31 13:42:56 2014 +0200 @@ -663,9 +663,26 @@ return JNIHandles::make_local((oop) result.get_jobject()); JVM_END +void GraalRuntime::check_generated_sources_sha1(TRAPS) { + TempNewSymbol name = SymbolTable::new_symbol("GeneratedSourcesSha1", CHECK_ABORT); + KlassHandle klass = load_required_class(name); + fieldDescriptor fd; + if (!InstanceKlass::cast(klass())->find_field(vmSymbols::value_name(), vmSymbols::string_signature(), true, &fd)) { + THROW_MSG(vmSymbols::java_lang_NoSuchFieldError(), "GeneratedSourcesSha1.value"); + } + + Symbol* value = java_lang_String::as_symbol(klass->java_mirror()->obj_field(fd.offset()), CHECK); + if (!value->equals(_generated_sources_sha1)) { + char buf[200]; + jio_snprintf(buf, sizeof(buf), "Generated sources SHA1 check failed (%s != %s) - need to rebuild the VM", value->as_C_string(), _generated_sources_sha1); + THROW_MSG(vmSymbols::java_lang_InternalError(), buf); + } +} + Handle GraalRuntime::get_HotSpotGraalRuntime() { if (JNIHandles::resolve(_HotSpotGraalRuntime_instance) == NULL) { Thread* THREAD = Thread::current(); + check_generated_sources_sha1(CHECK_ABORT_(Handle())); TempNewSymbol name = SymbolTable::new_symbol("com/oracle/graal/hotspot/HotSpotGraalRuntime", CHECK_ABORT_(Handle())); KlassHandle klass = load_required_class(name); TempNewSymbol runtime = SymbolTable::new_symbol("runtime", CHECK_ABORT_(Handle())); diff -r 68deb37eed70 -r d3fec84757ed src/share/vm/graal/graalRuntime.hpp --- a/src/share/vm/graal/graalRuntime.hpp Thu Jul 31 12:00:23 2014 +0200 +++ b/src/share/vm/graal/graalRuntime.hpp Thu Jul 31 13:42:56 2014 +0200 @@ -33,6 +33,7 @@ static jobject _HotSpotGraalRuntime_instance; static address _external_deopt_i2c_entry; + static const char* _generated_sources_sha1; /** * Reads the OptionValue object from a specified static field. @@ -101,6 +102,11 @@ */ static Handle create_Service(const char* name, TRAPS); + /** + * Checks that _generated_sources_sha1 equals GeneratedSourcesSha1.value. + */ + static void check_generated_sources_sha1(TRAPS); + public: static void initialize_natives(JNIEnv *env, jclass c2vmClass);