# HG changeset patch # User Thomas Wuerthinger # Date 1432841214 -7200 # Node ID fad97102875561c0cecb2da155cdf0a1bc3cdaa8 # Parent 54933d47cfa40192251ac927347a92d4554f8ccd# Parent 4b3b38415adf974774952abb69b359053d6f0018 Merge. diff -r 54933d47cfa4 -r fad971028755 graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CompilationResult.java --- a/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CompilationResult.java Thu May 28 21:25:21 2015 +0200 +++ b/graal/com.oracle.graal.api.code/src/com/oracle/graal/api/code/CompilationResult.java Thu May 28 21:26:54 2015 +0200 @@ -602,11 +602,10 @@ } /** - * Gets a fixed-size {@linkplain Arrays#asList(Object...) view} of the assumptions made during - * compilation. + * Gets the assumptions made during compilation. */ - public Collection getAssumptions() { - return assumptions == null ? Collections.emptyList() : Arrays.asList(assumptions); + public Assumption[] getAssumptions() { + return assumptions; } /** @@ -641,15 +640,14 @@ } /** - * Gets a fixed-size {@linkplain Arrays#asList(Object...) view} of the methods whose bytecodes - * were used as input to the compilation. + * Gets the methods whose bytecodes were used as input to the compilation. * * @return {@code null} if the compilation did not record method dependencies otherwise the * methods whose bytecodes were used as input to the compilation with the first element * being the root method of the compilation */ - public Collection getMethods() { - return methods == null ? null : Arrays.asList(methods); + public ResolvedJavaMethod[] getMethods() { + return methods; } public DataSection getDataSection() { diff -r 54933d47cfa4 -r fad971028755 graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/LineNumberTableImpl.java diff -r 54933d47cfa4 -r fad971028755 graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/LocalImpl.java diff -r 54933d47cfa4 -r fad971028755 graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/LocalVariableTableImpl.java diff -r 54933d47cfa4 -r fad971028755 graal/com.oracle.graal.asm.test/src/com/oracle/graal/asm/test/AssemblerTest.java --- a/graal/com.oracle.graal.asm.test/src/com/oracle/graal/asm/test/AssemblerTest.java Thu May 28 21:25:21 2015 +0200 +++ b/graal/com.oracle.graal.asm.test/src/com/oracle/graal/asm/test/AssemblerTest.java Thu May 28 21:26:54 2015 +0200 @@ -63,6 +63,7 @@ CompilationResult compResult = new CompilationResult(); byte[] targetCode = test.generateCode(compResult, codeCache.getTarget(), registerConfig, cc); compResult.setTargetCode(targetCode, targetCode.length); + compResult.setTotalFrameSize(0); InstalledCode code = codeCache.addMethod(method, compResult, null, null); diff -r 54933d47cfa4 -r fad971028755 graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java --- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java Thu May 28 21:25:21 2015 +0200 +++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java Thu May 28 21:26:54 2015 +0200 @@ -1269,20 +1269,23 @@ assert inputVal.getKind().getStackKind() == Kind.Int; LIRKind resultKind = LIRKind.derive(inputVal); - OperandSize resultSize; if (toBits > 32) { resultKind = resultKind.changeType(Kind.Long); - resultSize = QWORD; } else { resultKind = resultKind.changeType(Kind.Int); - resultSize = DWORD; } + /* + * Always emit DWORD operations, even if the resultKind is Long. On AMD64, all DWORD + * operations implicitly set the upper half of the register to 0, which is what we want + * anyway. Compared to the QWORD oparations, the encoding of the DWORD operations is + * sometimes one byte shorter. + */ switch (fromBits) { case 8: - return emitConvertOp(resultKind, MOVZXB, resultSize, inputVal); + return emitConvertOp(resultKind, MOVZXB, DWORD, inputVal); case 16: - return emitConvertOp(resultKind, MOVZX, resultSize, inputVal); + return emitConvertOp(resultKind, MOVZX, DWORD, inputVal); case 32: return emitConvertOp(resultKind, MOV, DWORD, inputVal); } diff -r 54933d47cfa4 -r fad971028755 graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/GraalOptions.java --- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/GraalOptions.java Thu May 28 21:25:21 2015 +0200 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/GraalOptions.java Thu May 28 21:26:54 2015 +0200 @@ -327,7 +327,7 @@ @Option(help = "Enable expensive assertions", type = OptionType.Debug) public static final OptionValue DetailedAsserts = new StableOptionValue() { @Override - protected Boolean initialValue() { + protected Boolean defaultValue() { boolean enabled = false; // turn detailed assertions on when the general assertions are on (misusing the assert keyword for this) assert (enabled = true) == true; diff -r 54933d47cfa4 -r fad971028755 graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/alloc/RegisterAllocationConfig.java --- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/alloc/RegisterAllocationConfig.java Thu May 28 21:25:21 2015 +0200 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/alloc/RegisterAllocationConfig.java Thu May 28 21:26:54 2015 +0200 @@ -36,6 +36,36 @@ */ public class RegisterAllocationConfig { + public static final class AllocatableRegisters { + public final Register[] allocatableRegisters; + public final int minRegisterNumber; + public final int maxRegisterNumber; + + public AllocatableRegisters(Register[] allocatableRegisters, int minRegisterNumber, int maxRegisterNumber) { + this.allocatableRegisters = allocatableRegisters; + this.minRegisterNumber = minRegisterNumber; + this.maxRegisterNumber = maxRegisterNumber; + assert verify(allocatableRegisters, minRegisterNumber, maxRegisterNumber); + } + + private static boolean verify(Register[] allocatableRegisters, int minRegisterNumber, int maxRegisterNumber) { + int min = Integer.MAX_VALUE; + int max = Integer.MIN_VALUE; + for (Register reg : allocatableRegisters) { + int number = reg.number; + if (number < min) { + min = number; + } + if (number > max) { + max = number; + } + } + assert minRegisterNumber == min; + assert maxRegisterNumber == max; + return true; + } + } + public static final String ALL_REGISTERS = ""; private static Register findRegister(String name, Register[] all) { @@ -47,7 +77,7 @@ throw new IllegalArgumentException("register " + name + " is not allocatable"); } - private static Register[] initAllocatable(Register[] registers) { + protected Register[] initAllocatable(Register[] registers) { if (RegisterPressure.getValue() != null && !RegisterPressure.getValue().equals(ALL_REGISTERS)) { String[] names = RegisterPressure.getValue().split(","); Register[] regs = new Register[names.length]; @@ -60,11 +90,12 @@ return registers; } - private final RegisterConfig registerConfig; - private final Map categorized = new HashMap<>(); + protected final RegisterConfig registerConfig; + private final Map categorized = new HashMap<>(); private Register[] cachedRegisters; public RegisterAllocationConfig(RegisterConfig registerConfig) { + assert registerConfig != null; this.registerConfig = registerConfig; } @@ -72,17 +103,19 @@ * Gets the set of registers that can be used by the register allocator for a value of a * particular kind. */ - public Register[] getAllocatableRegisters(PlatformKind kind) { + public AllocatableRegisters getAllocatableRegisters(PlatformKind kind) { PlatformKind.Key key = kind.getKey(); if (categorized.containsKey(key)) { - Register[] val = categorized.get(key); + AllocatableRegisters val = categorized.get(key); return val; } - - Register[] ret = registerConfig.filterAllocatableRegisters(kind, getAllocatableRegisters()); + AllocatableRegisters ret = createAllocatableRegisters(registerConfig.filterAllocatableRegisters(kind, getAllocatableRegisters())); categorized.put(key, ret); return ret; + } + protected AllocatableRegisters createAllocatableRegisters(Register[] registers) { + return new AllocatableRegisters(registers, registers[0].number, registers[registers.length - 1].number); } /** diff -r 54933d47cfa4 -r fad971028755 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java Thu May 28 21:25:21 2015 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/GraalCompiler.java Thu May 28 21:26:54 2015 +0200 @@ -300,7 +300,7 @@ } try (Scope s = Debug.scope("LIRStages", nodeLirGen, lir)) { - return emitLowLevel(target, codeEmittingOrder, linearScanOrder, lirGenRes, lirGen, lirSuites); + return emitLowLevel(target, codeEmittingOrder, linearScanOrder, lirGenRes, lirGen, lirSuites, backend.newRegisterAllocationConfig(registerConfig)); } catch (Throwable e) { throw Debug.handle(e); } @@ -310,11 +310,11 @@ } public static > LIRGenerationResult emitLowLevel(TargetDescription target, List codeEmittingOrder, List linearScanOrder, LIRGenerationResult lirGenRes, - LIRGeneratorTool lirGen, LIRSuites lirSuites) { + LIRGeneratorTool lirGen, LIRSuites lirSuites, RegisterAllocationConfig registerAllocationConfig) { PreAllocationOptimizationContext preAllocOptContext = new PreAllocationOptimizationContext(lirGen); lirSuites.getPreAllocationOptimizationStage().apply(target, lirGenRes, codeEmittingOrder, linearScanOrder, preAllocOptContext); - AllocationContext allocContext = new AllocationContext(lirGen.getSpillMoveFactory()); + AllocationContext allocContext = new AllocationContext(lirGen.getSpillMoveFactory(), registerAllocationConfig); lirSuites.getAllocationStage().apply(target, lirGenRes, codeEmittingOrder, linearScanOrder, allocContext); PostAllocationOptimizationContext postAllocOptContext = new PostAllocationOptimizationContext(lirGen); diff -r 54933d47cfa4 -r fad971028755 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/Backend.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/Backend.java Thu May 28 21:25:21 2015 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/Backend.java Thu May 28 21:26:54 2015 +0200 @@ -27,6 +27,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.asm.*; import com.oracle.graal.compiler.common.*; +import com.oracle.graal.compiler.common.alloc.*; import com.oracle.graal.compiler.gen.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.asm.*; @@ -82,6 +83,8 @@ */ public abstract FrameMapBuilder newFrameMapBuilder(RegisterConfig registerConfig); + public abstract RegisterAllocationConfig newRegisterAllocationConfig(RegisterConfig registerConfig); + public abstract FrameMap newFrameMap(RegisterConfig registerConfig); public abstract LIRGeneratorTool newLIRGenerator(CallingConvention cc, LIRGenerationResult lirGenRes); diff -r 54933d47cfa4 -r fad971028755 graal/com.oracle.graal.graphbuilderconf/src/com/oracle/graal/graphbuilderconf/IntrinsicContext.java diff -r 54933d47cfa4 -r fad971028755 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java Thu May 28 21:25:21 2015 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotBackend.java Thu May 28 21:26:54 2015 +0200 @@ -36,6 +36,7 @@ import com.oracle.graal.asm.*; import com.oracle.graal.asm.amd64.*; import com.oracle.graal.asm.amd64.AMD64Assembler.ConditionFlag; +import com.oracle.graal.compiler.common.alloc.*; import com.oracle.graal.compiler.gen.*; import com.oracle.graal.compiler.target.*; import com.oracle.graal.hotspot.*; @@ -324,4 +325,10 @@ } } + @Override + public RegisterAllocationConfig newRegisterAllocationConfig(RegisterConfig registerConfig) { + RegisterConfig registerConfigNonNull = registerConfig == null ? getCodeCache().getRegisterConfig() : registerConfig; + return new AMD64HotSpotRegisterAllocationConfig(registerConfigNonNull); + } + } diff -r 54933d47cfa4 -r fad971028755 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRegisterAllocationConfig.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotRegisterAllocationConfig.java Thu May 28 21:26:54 2015 +0200 @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.hotspot.amd64; + +import static com.oracle.graal.amd64.AMD64.*; + +import java.util.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.compiler.common.alloc.*; + +class AMD64HotSpotRegisterAllocationConfig extends RegisterAllocationConfig { + /** + * Specify priority of register selection within phases of register allocation. Highest priority + * is first. A useful heuristic is to give registers a low priority when they are required by + * machine instructions, like EAX and EDX on I486, and choose no-save registers before + * save-on-call, & save-on-call before save-on-entry. Registers which participate in fixed + * calling sequences should come last. Registers which are used as pairs must fall on an even + * boundary. + * + * Adopted from x86_64.ad. + */ + // @formatter:off + static final Register[] registerAllocationOrder = { + r10, r11, r8, r9, r12, rcx, rbx, rdi, rdx, rsi, rax, rbp, r13, r14, /*r15,*/ /*rsp,*/ + xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, + xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15 + }; + // @formatter:on + + public AMD64HotSpotRegisterAllocationConfig(RegisterConfig registerConfig) { + super(registerConfig); + } + + @Override + protected Register[] initAllocatable(Register[] registers) { + BitSet regMap = new BitSet(registerConfig.getAllocatableRegisters().length); + Register[] regs = super.initAllocatable(registers); + for (Register reg : regs) { + regMap.set(reg.number); + } + + Register[] allocatableRegisters = new Register[regs.length]; + int i = 0; + for (Register reg : registerAllocationOrder) { + if (regMap.get(reg.number)) { + allocatableRegisters[i++] = reg; + } + } + + assert i == allocatableRegisters.length; + return allocatableRegisters; + } + + @Override + protected AllocatableRegisters createAllocatableRegisters(Register[] registers) { + int min = Integer.MAX_VALUE; + int max = Integer.MIN_VALUE; + for (Register reg : registers) { + int number = reg.number; + if (number < min) { + min = number; + } + if (number > max) { + max = number; + } + } + assert min < max; + return new AllocatableRegisters(registers, min, max); + } +} diff -r 54933d47cfa4 -r fad971028755 graal/com.oracle.graal.hotspot.loader/src/com/oracle/graal/hotspot/loader/Factory.java --- a/graal/com.oracle.graal.hotspot.loader/src/com/oracle/graal/hotspot/loader/Factory.java Thu May 28 21:25:21 2015 +0200 +++ b/graal/com.oracle.graal.hotspot.loader/src/com/oracle/graal/hotspot/loader/Factory.java Thu May 28 21:26:54 2015 +0200 @@ -28,7 +28,7 @@ /** * Utility to create and register a separate class loader for loading Graal classes (i.e., those in - * found in lib/graal/graal*.jar). + * found in jars in lib/graal). */ public class Factory { @@ -69,7 +69,7 @@ List urls = new ArrayList<>(); for (String fileName : graal.list()) { - if (fileName.startsWith("graal") && fileName.endsWith(".jar")) { + if (fileName.endsWith(".jar")) { File file = new File(graal, fileName); if (file.isDirectory()) { continue; diff -r 54933d47cfa4 -r fad971028755 graal/com.oracle.graal.hotspot.sourcegen/src/com/oracle/graal/hotspot/sourcegen/GenGraalRuntimeInlineHpp.java --- a/graal/com.oracle.graal.hotspot.sourcegen/src/com/oracle/graal/hotspot/sourcegen/GenGraalRuntimeInlineHpp.java Thu May 28 21:25:21 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,225 +0,0 @@ -/* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.hotspot.sourcegen; - -import java.io.*; -import java.lang.reflect.*; -import java.util.*; -import java.util.stream.*; -import java.util.zip.*; - -import com.oracle.graal.api.runtime.*; -import com.oracle.graal.compiler.common.*; -import com.oracle.graal.options.*; - -/** - * Command line utility for generating the source code of {@code graalRuntime.inline.hpp}. The - * generated code is comprised of: - *
    - *
  • {@code -G} command line option parsing {@linkplain #genSetOption(PrintStream) helper}
  • - *
- * - * The purpose of the generated code is to avoid executing Graal related Java code as much as - * possible during initialization of the Graal runtime. Future solutions such as some kind of AOT - * system may make such a mechanism redundant in terms of minimizing Graal's impact on VM startup - * time. - * - * The input for the generation is all classes that implement {@link Service} or contain fields - * annotated by {@link Option}. As such, the code generation process must be executed with a class - * path including all Graal jars that contains such classes. Currently, this is - * {@code graal-truffle.jar}. - */ -public class GenGraalRuntimeInlineHpp { - - public static class GraalJars implements Iterable { - private final List jars = new ArrayList<>(2); - - public GraalJars() { - String classPath = System.getProperty("java.class.path"); - for (String e : classPath.split(File.pathSeparator)) { - if (e.endsWith(File.separatorChar + "graal.jar") || e.endsWith(File.separatorChar + "graal-truffle.jar")) { - try { - jars.add(new ZipFile(e)); - } catch (IOException ioe) { - throw new InternalError(ioe); - } - } - } - if (jars.size() != 2) { - throw new InternalError("Could not find graal.jar or graal-truffle.jar on class path: " + classPath); - } - } - - public Iterator iterator() { - Stream entries = jars.stream().flatMap(ZipFile::stream); - return entries.iterator(); - } - - public InputStream getInputStream(String classFilePath) throws IOException { - for (ZipFile jar : jars) { - ZipEntry entry = jar.getEntry(classFilePath); - if (entry != null) { - return jar.getInputStream(entry); - } - } - return null; - } - } - - private static final GraalJars graalJars = new GraalJars(); - - public static void main(String[] args) { - PrintStream out = System.out; - try { - genSetOption(out); - } catch (Throwable t) { - t.printStackTrace(out); - } - out.flush(); - } - - /** - * Generates code for {@code GraalRuntime::set_option()} and - * {@code GraalRuntime::set_option_bool()}. - */ - private static void genSetOption(PrintStream out) throws Exception { - SortedMap options = getOptions(); - - Set lengths = new TreeSet<>(); - for (String s : options.keySet()) { - lengths.add(s.length()); - } - lengths.add("PrintFlags".length()); - - out.println("bool GraalRuntime::set_option_bool(KlassHandle hotSpotOptionsClass, char* name, size_t name_len, char value, TRAPS) {"); - out.println(" bool check_only = hotSpotOptionsClass.is_null();"); - genMatchers(out, lengths, options, true); - out.println(" return false;"); - out.println("}"); - out.println("bool GraalRuntime::set_option(KlassHandle hotSpotOptionsClass, char* name, size_t name_len, const char* value, TRAPS) {"); - out.println(" bool check_only = hotSpotOptionsClass.is_null();"); - genMatchers(out, lengths, options, false); - out.println(" return false;"); - out.println("}"); - } - - protected static void genMatchers(PrintStream out, Set lengths, SortedMap options, boolean isBoolean) throws Exception { - out.println(" switch (name_len) {"); - for (int len : lengths) { - boolean printedCase = false; - - // The use of strncmp is required (instead of strcmp) as the option name will not be - // null terminated for = style options. - if (len == "PrintFlags".length() && isBoolean) { - printedCase = true; - out.println(" case " + len + ":"); - out.printf(" if (strncmp(name, \"PrintFlags\", %d) == 0) {%n", len); - out.println(" if (value == '+') {"); - out.println(" if (check_only) {"); - out.println(" TempNewSymbol name = SymbolTable::new_symbol(\"Lcom/oracle/graal/hotspot/HotSpotOptions;\", CHECK_(true));"); - out.println(" hotSpotOptionsClass = SystemDictionary::resolve_or_fail(name, true, CHECK_(true));"); - out.println(" }"); - out.println(" set_option_helper(hotSpotOptionsClass, name, name_len, Handle(), '?', Handle(), 0L);"); - out.println(" }"); - out.println(" return true;"); - out.println(" }"); - } - for (Map.Entry e : options.entrySet()) { - OptionDescriptor desc = e.getValue(); - if (e.getKey().length() == len && ((desc.getType() == Boolean.class) == isBoolean)) { - if (!printedCase) { - printedCase = true; - out.println(" case " + len + ":"); - } - out.printf(" if (strncmp(name, \"%s\", %d) == 0) {%n", e.getKey(), len); - Class declaringClass = desc.getDeclaringClass(); - if (isBoolean) { - out.printf(" Handle option = get_OptionValue(\"L%s;\", \"%s\", \"L%s;\", CHECK_(true));%n", toInternalName(declaringClass), desc.getFieldName(), - toInternalName(getFieldType(desc))); - out.println(" if (!check_only) {"); - out.println(" set_option_helper(hotSpotOptionsClass, name, name_len, option, value, Handle(), 0L);"); - out.println(" }"); - } else if (desc.getType() == String.class) { - out.println(" check_required_value(name, name_len, value, CHECK_(true));"); - out.printf(" Handle option = get_OptionValue(\"L%s;\", \"%s\", \"L%s;\", CHECK_(true));%n", toInternalName(declaringClass), desc.getFieldName(), - toInternalName(getFieldType(desc))); - out.println(" if (!check_only) {"); - out.println(" Handle stringValue = java_lang_String::create_from_str(value, CHECK_(true));"); - out.println(" set_option_helper(hotSpotOptionsClass, name, name_len, option, 's', stringValue, 0L);"); - out.println(" }"); - } else { - char spec = getPrimitiveSpecChar(desc); - out.println(" jlong primitiveValue = parse_primitive_option_value('" + spec + "', name, name_len, value, CHECK_(true));"); - out.println(" if (!check_only) {"); - out.printf(" Handle option = get_OptionValue(\"L%s;\", \"%s\", \"L%s;\", CHECK_(true));%n", toInternalName(declaringClass), desc.getFieldName(), - toInternalName(getFieldType(desc))); - out.println(" set_option_helper(hotSpotOptionsClass, name, name_len, option, '" + spec + "', Handle(), primitiveValue);"); - out.println(" }"); - } - out.println(" return true;"); - out.println(" }"); - } - } - } - out.println(" }"); - } - - @SuppressWarnings("unchecked") - static SortedMap getOptions() throws Exception { - Field field = Class.forName("com.oracle.graal.hotspot.HotSpotOptionsLoader").getDeclaredField("options"); - field.setAccessible(true); - SortedMap options = (SortedMap) field.get(null); - - Set> checked = new HashSet<>(); - for (final OptionDescriptor option : options.values()) { - Class cls = option.getDeclaringClass(); - OptionsVerifier.checkClass(cls, option, checked, graalJars); - } - return options; - } - - private static Class getFieldType(OptionDescriptor desc) throws Exception { - return desc.getDeclaringClass().getDeclaredField(desc.getFieldName()).getType(); - } - - private static String toInternalName(Class c) { - return c.getName().replace('.', '/'); - } - - /** - * @see HotSpotOptions#setOption(String, OptionValue, char, String, long) - */ - @SuppressWarnings("javadoc") - private static char getPrimitiveSpecChar(OptionDescriptor desc) { - if (desc.getType() == Integer.class) { - return 'i'; - } - if (desc.getType() == Float.class) { - return 'f'; - } - if (desc.getType() == Double.class) { - return 'd'; - } - throw GraalInternalError.shouldNotReachHere("Unexpected primitive option type: " + desc.getType().getName()); - } -} diff -r 54933d47cfa4 -r fad971028755 graal/com.oracle.graal.hotspot.sourcegen/src/com/oracle/graal/hotspot/sourcegen/OptionsVerifier.java --- a/graal/com.oracle.graal.hotspot.sourcegen/src/com/oracle/graal/hotspot/sourcegen/OptionsVerifier.java Thu May 28 21:25:21 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,185 +0,0 @@ -/* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.hotspot.sourcegen; - -import static java.lang.String.*; - -import java.io.*; -import java.lang.reflect.*; -import java.util.*; - -import jdk.internal.org.objectweb.asm.*; -import jdk.internal.org.objectweb.asm.Type; - -import com.oracle.graal.hotspot.sourcegen.GenGraalRuntimeInlineHpp.GraalJars; -import com.oracle.graal.options.*; - -/** - * A {@link ClassVisitor} that verifies a class declaring one or more {@linkplain OptionValue - * options} has a class initializer that only initializes the option(s). This sanity check mitigates - * the possibility of an option value being used before the code that sets the value (e.g., from the - * command line) has been executed. - */ -final class OptionsVerifier extends ClassVisitor { - - public static void checkClass(Class cls, OptionDescriptor option, Set> checked, GraalJars graalJars) throws IOException { - if (!checked.contains(cls)) { - checked.add(cls); - Class superclass = cls.getSuperclass(); - if (superclass != null && !superclass.equals(Object.class)) { - checkClass(superclass, option, checked, graalJars); - } - - String classFilePath = cls.getName().replace('.', '/') + ".class"; - ClassReader cr = new ClassReader(Objects.requireNonNull(graalJars.getInputStream(classFilePath), "Could not find class file for " + cls.getName())); - - ClassVisitor cv = new OptionsVerifier(cls, option); - cr.accept(cv, 0); - } - } - - /** - * The option field context of the verification. - */ - private final OptionDescriptor option; - - /** - * The class in which {@link #option} is declared or a super-class of that class. This is the - * class whose {@code } method is being verified. - */ - private final Class cls; - - /** - * Source file context for error reporting. - */ - String sourceFile = null; - - /** - * Line number for error reporting. - */ - int lineNo = -1; - - final Class[] boxingTypes = {Boolean.class, Byte.class, Short.class, Character.class, Integer.class, Float.class, Long.class, Double.class}; - - private static Class resolve(String name) { - try { - return Class.forName(name.replace('/', '.')); - } catch (ClassNotFoundException e) { - throw new InternalError(e); - } - } - - OptionsVerifier(Class cls, OptionDescriptor desc) { - super(Opcodes.ASM5); - this.cls = cls; - this.option = desc; - } - - @Override - public void visitSource(String source, String debug) { - this.sourceFile = source; - } - - void verify(boolean condition, String message) { - if (!condition) { - error(message); - } - } - - void error(String message) { - String errorMessage = format("%s:%d: Illegal code in %s. which may be executed when %s.%s is initialized:%n%n %s%n%n" + "The recommended solution is to move " + option.getName() + - " into a separate class (e.g., %s.Options).%n", sourceFile, lineNo, cls.getSimpleName(), option.getDeclaringClass().getSimpleName(), option.getName(), message, - option.getDeclaringClass().getSimpleName()); - throw new InternalError(errorMessage); - - } - - @Override - public MethodVisitor visitMethod(int access, String name, String d, String signature, String[] exceptions) { - if (name.equals("")) { - return new MethodVisitor(Opcodes.ASM5) { - - @Override - public void visitLineNumber(int line, Label start) { - lineNo = line; - } - - @Override - public void visitFieldInsn(int opcode, String owner, String fieldName, String fieldDesc) { - if (opcode == Opcodes.PUTFIELD || opcode == Opcodes.PUTSTATIC) { - verify(resolve(owner).equals(option.getDeclaringClass()), format("store to field %s.%s", resolve(owner).getSimpleName(), fieldName)); - verify(opcode != Opcodes.PUTFIELD, format("store to non-static field %s.%s", resolve(owner).getSimpleName(), fieldName)); - } - } - - private Executable resolveMethod(String owner, String methodName, String methodDesc) { - Class declaringClass = resolve(owner); - if (methodName.equals("")) { - for (Constructor c : declaringClass.getDeclaredConstructors()) { - if (methodDesc.equals(Type.getConstructorDescriptor(c))) { - return c; - } - } - } else { - Type[] argumentTypes = Type.getArgumentTypes(methodDesc); - for (Method m : declaringClass.getDeclaredMethods()) { - if (m.getName().equals(methodName)) { - if (Arrays.equals(argumentTypes, Type.getArgumentTypes(m))) { - if (Type.getReturnType(methodDesc).equals(Type.getReturnType(m))) { - return m; - } - } - } - } - } - throw new NoSuchMethodError(declaringClass + "." + methodName + methodDesc); - } - - /** - * Checks whether a given method is allowed to be called. - */ - private boolean checkInvokeTarget(Executable method) { - Class holder = method.getDeclaringClass(); - if (method instanceof Constructor) { - if (OptionValue.class.isAssignableFrom(holder)) { - return true; - } - } else if (Arrays.asList(boxingTypes).contains(holder)) { - return method.getName().equals("valueOf"); - } else if (method.getDeclaringClass().equals(Class.class)) { - return method.getName().equals("desiredAssertionStatus"); - } - return false; - } - - @Override - public void visitMethodInsn(int opcode, String owner, String methodName, String methodDesc, boolean itf) { - Executable callee = resolveMethod(owner, methodName, methodDesc); - verify(checkInvokeTarget(callee), "invocation of " + callee); - } - }; - } else { - return null; - } - } -} diff -r 54933d47cfa4 -r fad971028755 graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java --- a/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java Thu May 28 21:25:21 2015 +0200 +++ b/graal/com.oracle.graal.hotspot.sparc/src/com/oracle/graal/hotspot/sparc/SPARCHotSpotBackend.java Thu May 28 21:26:54 2015 +0200 @@ -40,6 +40,7 @@ import com.oracle.graal.asm.sparc.*; import com.oracle.graal.asm.sparc.SPARCMacroAssembler.ScratchRegister; import com.oracle.graal.asm.sparc.SPARCMacroAssembler.Setx; +import com.oracle.graal.compiler.common.alloc.*; import com.oracle.graal.compiler.common.cfg.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.meta.*; @@ -377,4 +378,10 @@ return overlap; } } + + @Override + public RegisterAllocationConfig newRegisterAllocationConfig(RegisterConfig registerConfig) { + RegisterConfig registerConfigNonNull = registerConfig == null ? getCodeCache().getRegisterConfig() : registerConfig; + return new RegisterAllocationConfig(registerConfigNonNull); + } } diff -r 54933d47cfa4 -r fad971028755 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java Thu May 28 21:25:21 2015 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompilationTask.java Thu May 28 21:26:54 2015 +0200 @@ -29,7 +29,6 @@ import static com.oracle.graal.compiler.common.UnsafeAccess.*; import static com.oracle.graal.debug.Debug.*; import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; -import static com.oracle.graal.hotspot.InitTimer.*; import static com.oracle.graal.hotspot.meta.HotSpotSuitesProvider.*; import static com.oracle.graal.nodes.StructuredGraph.*; @@ -61,15 +60,6 @@ //JaCoCo Exclude public class CompilationTask { - - static { - try (InitTimer t = timer("initialize CompilationTask")) { - // Must be first to ensure any options accessed by the rest of the class - // initializer are initialized from the command line. - HotSpotOptions.initialize(); - } - } - private static final DebugMetric BAILOUTS = Debug.metric("Bailouts"); private final HotSpotBackend backend; diff -r 54933d47cfa4 -r fad971028755 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompileTheWorld.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompileTheWorld.java Thu May 28 21:25:21 2015 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/CompileTheWorld.java Thu May 28 21:26:54 2015 +0200 @@ -40,7 +40,6 @@ import com.oracle.graal.bytecode.*; import com.oracle.graal.compiler.*; import com.oracle.graal.compiler.CompilerThreadFactory.DebugConfigAccess; -import com.oracle.graal.compiler.common.*; import com.oracle.graal.debug.*; import com.oracle.graal.debug.internal.*; import com.oracle.graal.hotspot.meta.*; @@ -120,14 +119,12 @@ * * @param options a space separated set of option value settings with each option setting in * a format compatible with - * {@link HotSpotOptions#parseOption(String, OptionConsumer)}. Ignored if null. + * {@link OptionUtils#parseOption(String, OptionConsumer)}. Ignored if null. */ public Config(String options) { if (options != null) { for (String option : options.split("\\s+")) { - if (!HotSpotOptions.parseOption(option, this)) { - throw new GraalInternalError("Invalid option specified: %s", option); - } + OptionUtils.parseOption(option, this); } } } @@ -213,7 +210,7 @@ */ public void compile() throws Throwable { // By default only report statistics for the CTW threads themselves - if (GraalDebugConfig.DebugValueThreadFilter.hasInitialValue()) { + if (GraalDebugConfig.DebugValueThreadFilter.hasDefaultValue()) { GraalDebugConfig.DebugValueThreadFilter.setValue("^CompileTheWorld"); } diff -r 54933d47cfa4 -r fad971028755 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotCompiledCode.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotCompiledCode.java Thu May 28 21:25:21 2015 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotCompiledCode.java Thu May 28 21:26:54 2015 +0200 @@ -36,6 +36,8 @@ import com.oracle.graal.api.code.CompilationResult.JumpTable; import com.oracle.graal.api.code.CompilationResult.Mark; import com.oracle.graal.api.code.CompilationResult.Site; +import com.oracle.graal.api.meta.Assumptions.Assumption; +import com.oracle.graal.api.meta.*; /** * A {@link CompilationResult} with additional HotSpot-specific information required for installing @@ -43,16 +45,28 @@ */ public abstract class HotSpotCompiledCode { - public final CompilationResult comp; - public final Site[] sites; public final ExceptionHandler[] exceptionHandlers; public final Comment[] comments; + public final Assumption[] assumptions; + + public final byte[] targetCode; + public final int targetCodeSize; public final byte[] dataSection; public final int dataSectionAlignment; public final DataPatch[] dataSectionPatches; + public final int totalFrameSize; + public final int customStackAreaOffset; + + /** + * The list of the methods whose bytecodes were used as input to the compilation. If + * {@code null}, then the compilation did not record method dependencies. Otherwise, the first + * element of this array is the root method of the compilation. + */ + public final ResolvedJavaMethod[] methods; + public static class Comment { public final String text; @@ -65,7 +79,6 @@ } public HotSpotCompiledCode(CompilationResult compResult) { - this.comp = compResult; sites = getSortedSites(compResult); if (compResult.getExceptionHandlers().isEmpty()) { exceptionHandlers = null; @@ -90,8 +103,12 @@ comments[i] = new Comment(annotation.position, text); } } + assumptions = compResult.getAssumptions(); assert validateFrames(); + targetCode = compResult.getTargetCode(); + targetCodeSize = compResult.getTargetCodeSize(); + DataSection data = compResult.getDataSection(); data.finalizeLayout(); dataSection = new byte[data.getSectionSize()]; @@ -102,6 +119,11 @@ dataSectionAlignment = data.getSectionAlignment(); dataSectionPatches = patchBuilder.build().toArray(len -> new DataPatch[len]); + + totalFrameSize = compResult.getTotalFrameSize(); + customStackAreaOffset = compResult.getCustomStackAreaOffset(); + + methods = compResult.getMethods(); } /** diff -r 54933d47cfa4 -r fad971028755 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotCompiledRuntimeStub.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotCompiledRuntimeStub.java Thu May 28 21:25:21 2015 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotCompiledRuntimeStub.java Thu May 28 21:26:54 2015 +0200 @@ -53,7 +53,7 @@ // Stubs cannot be recompiled so they cannot be compiled with // assumptions and there is no point in recording evol_method dependencies - assert compResult.getAssumptions().isEmpty() : "stubs should not use assumptions: " + this; + assert compResult.getAssumptions() == null : "stubs should not use assumptions: " + this; assert compResult.getMethods() == null : "stubs should not record evol_method dependencies: " + this; for (DataPatch data : compResult.getDataPatches()) { diff -r 54933d47cfa4 -r fad971028755 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java Thu May 28 21:25:21 2015 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotGraalRuntime.java Thu May 28 21:26:54 2015 +0200 @@ -65,10 +65,6 @@ private static final HotSpotGraalRuntime instance; static { - try (InitTimer t = timer("initialize HotSpotOptions")) { - HotSpotOptions.initialize(); - } - try (InitTimer t = timer("HotSpotGraalRuntime.")) { instance = new HotSpotGraalRuntime(); } diff -r 54933d47cfa4 -r fad971028755 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptions.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptions.java Thu May 28 21:25:21 2015 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptions.java Thu May 28 21:26:54 2015 +0200 @@ -23,13 +23,11 @@ package com.oracle.graal.hotspot; import static com.oracle.graal.compiler.GraalDebugConfig.*; -import static com.oracle.graal.hotspot.HotSpotOptionsLoader.*; -import static java.lang.Double.*; +import static com.oracle.graal.options.OptionsLoader.*; import com.oracle.graal.api.runtime.*; import com.oracle.graal.debug.*; import com.oracle.graal.options.*; -import com.oracle.graal.options.OptionUtils.OptionConsumer; //JaCoCo Exclude @@ -41,14 +39,7 @@ private static final String GRAAL_OPTION_PREFIX = "-G:"; - /** - * Parses the Graal specific options specified to HotSpot (e.g., on the command line). - */ - private static native void parseVMOptions(); - static { - parseVMOptions(); - assert !Debug.Initialization.isDebugInitialized() : "The class " + Debug.class.getName() + " must not be initialized before the Graal runtime has been initialized. " + "This can be fixed by placing a call to " + Graal.class.getName() + ".runtime() on the path that triggers initialization of " + Debug.class.getName(); if (areDebugScopePatternsEnabled()) { @@ -65,57 +56,9 @@ } } - /** - * Ensures {@link HotSpotOptions} is initialized. - */ - public static void initialize() { + static void printFlags() { + OptionUtils.printFlags(options, GRAAL_OPTION_PREFIX); } - /** - * Helper for the VM code called by {@link #parseVMOptions()}. - * - * @param name the name of a parsed option - * @param option the object encapsulating the option - * @param spec specification of boolean option value, type of option value or action to take - */ - static void setOption(String name, OptionValue option, char spec, String stringValue, long primitiveValue) { - switch (spec) { - case '+': - option.setValue(Boolean.TRUE); - break; - case '-': - option.setValue(Boolean.FALSE); - break; - case '?': - OptionUtils.printFlags(options, GRAAL_OPTION_PREFIX); - break; - case ' ': - OptionUtils.printNoMatchMessage(options, name, GRAAL_OPTION_PREFIX); - break; - case 'i': - option.setValue((int) primitiveValue); - break; - case 'f': - option.setValue((float) longBitsToDouble(primitiveValue)); - break; - case 'd': - option.setValue(longBitsToDouble(primitiveValue)); - break; - case 's': - option.setValue(stringValue); - break; - } - } - - /** - * Parses a given option value specification. - * - * @param option the specification of an option and its value - * @param setter the object to notify of the parsed option and value. If null, the - * {@link OptionValue#setValue(Object)} method of the specified option is called - * instead. - */ - public static boolean parseOption(String option, OptionConsumer setter) { - return OptionUtils.parseOption(options, option, GRAAL_OPTION_PREFIX, setter); - } + public native Object getOptionValue(String optionName); } diff -r 54933d47cfa4 -r fad971028755 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptionsLoader.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/HotSpotOptionsLoader.java Thu May 28 21:25:21 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.hotspot; - -import java.util.*; - -import com.oracle.graal.api.runtime.*; -import com.oracle.graal.options.*; - -/** - * Helper class for separating loading of options from option initialization at runtime. - */ -class HotSpotOptionsLoader { - static final SortedMap options = new TreeMap<>(); - - /** - * Initializes {@link #options} from {@link Options} services. - */ - static { - for (Options opts : Services.load(Options.class)) { - for (OptionDescriptor desc : opts) { - if (isHotSpotOption(desc)) { - String name = desc.getName(); - OptionDescriptor existing = options.put(name, desc); - assert existing == null : "Option named \"" + name + "\" has multiple definitions: " + existing.getLocation() + " and " + desc.getLocation(); - } - } - } - } - - /** - * Determines if a given option is a HotSpot command line option. - */ - private static boolean isHotSpotOption(OptionDescriptor desc) { - return desc.getClass().getName().startsWith("com.oracle.graal"); - } -} diff -r 54933d47cfa4 -r fad971028755 graal/com.oracle.graal.java/src/com/oracle/graal/java/FrameStateBuilder.java diff -r 54933d47cfa4 -r fad971028755 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LinearScan.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LinearScan.java Thu May 28 21:25:21 2015 +0200 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LinearScan.java Thu May 28 21:26:54 2015 +0200 @@ -621,13 +621,14 @@ return attributes(asRegister(operand)).isCallerSave(); } - > void allocate(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder, SpillMoveFactory spillMoveFactory) { + > void allocate(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder, SpillMoveFactory spillMoveFactory, + RegisterAllocationConfig registerAllocationConfig) { /* * This is the point to enable debug logging for the whole register allocation. */ try (Indent indent = Debug.logAndIndent("LinearScan allocate")) { - AllocationContext context = new AllocationContext(spillMoveFactory); + AllocationContext context = new AllocationContext(spillMoveFactory, registerAllocationConfig); createLifetimeAnalysisPhase().apply(target, lirGenRes, codeEmittingOrder, linearScanOrder, context, false); diff -r 54933d47cfa4 -r fad971028755 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LinearScanAssignLocationsPhase.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LinearScanAssignLocationsPhase.java Thu May 28 21:25:21 2015 +0200 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LinearScanAssignLocationsPhase.java Thu May 28 21:26:54 2015 +0200 @@ -30,6 +30,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.alloc.*; import com.oracle.graal.compiler.common.cfg.*; import com.oracle.graal.debug.*; import com.oracle.graal.lir.*; @@ -51,7 +52,8 @@ } @Override - protected > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder, SpillMoveFactory spillMoveFactory) { + protected > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder, SpillMoveFactory spillMoveFactory, + RegisterAllocationConfig registerAllocationConfig) { assignLocations(); } diff -r 54933d47cfa4 -r fad971028755 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LinearScanEliminateSpillMovePhase.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LinearScanEliminateSpillMovePhase.java Thu May 28 21:25:21 2015 +0200 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LinearScanEliminateSpillMovePhase.java Thu May 28 21:26:54 2015 +0200 @@ -30,6 +30,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.alloc.*; import com.oracle.graal.compiler.common.cfg.*; import com.oracle.graal.debug.*; import com.oracle.graal.lir.*; @@ -57,7 +58,8 @@ } @Override - protected > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder, SpillMoveFactory spillMoveFactory) { + protected > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder, SpillMoveFactory spillMoveFactory, + RegisterAllocationConfig registerAllocationConfig) { eliminateSpillMoves(); } diff -r 54933d47cfa4 -r fad971028755 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LinearScanLifetimeAnalysisPhase.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LinearScanLifetimeAnalysisPhase.java Thu May 28 21:25:21 2015 +0200 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LinearScanLifetimeAnalysisPhase.java Thu May 28 21:26:54 2015 +0200 @@ -61,7 +61,8 @@ } @Override - protected > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder, SpillMoveFactory spillMoveFactory) { + protected > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder, SpillMoveFactory spillMoveFactory, + RegisterAllocationConfig registerAllocationConfig) { numberInstructions(); allocator.printLir("Before register allocation", true); computeLocalLiveSets(); diff -r 54933d47cfa4 -r fad971028755 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LinearScanOptimizeSpillPositionPhase.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LinearScanOptimizeSpillPositionPhase.java Thu May 28 21:25:21 2015 +0200 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LinearScanOptimizeSpillPositionPhase.java Thu May 28 21:26:54 2015 +0200 @@ -29,6 +29,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.alloc.*; import com.oracle.graal.compiler.common.cfg.*; import com.oracle.graal.debug.*; import com.oracle.graal.lir.*; @@ -50,7 +51,8 @@ } @Override - protected > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder, SpillMoveFactory spillMoveFactory) { + protected > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder, SpillMoveFactory spillMoveFactory, + RegisterAllocationConfig registerAllocationConfig) { optimizeSpillPosition(); allocator.printIntervals("After optimize spill position"); } diff -r 54933d47cfa4 -r fad971028755 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LinearScanPhase.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LinearScanPhase.java Thu May 28 21:25:21 2015 +0200 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LinearScanPhase.java Thu May 28 21:26:54 2015 +0200 @@ -48,14 +48,15 @@ }); @Override - protected > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder, SpillMoveFactory spillMoveFactory) { + protected > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder, SpillMoveFactory spillMoveFactory, + RegisterAllocationConfig registerAllocationConfig) { final LinearScan allocator; if (LinearScanPhase.SSA_LSRA.getValue()) { - allocator = new SSALinearScan(target, lirGenRes, spillMoveFactory, new RegisterAllocationConfig(lirGenRes.getFrameMapBuilder().getRegisterConfig())); + allocator = new SSALinearScan(target, lirGenRes, spillMoveFactory, registerAllocationConfig); } else { - allocator = new LinearScan(target, lirGenRes, spillMoveFactory, new RegisterAllocationConfig(lirGenRes.getFrameMapBuilder().getRegisterConfig())); + allocator = new LinearScan(target, lirGenRes, spillMoveFactory, registerAllocationConfig); } - allocator.allocate(target, lirGenRes, codeEmittingOrder, linearScanOrder, spillMoveFactory); + allocator.allocate(target, lirGenRes, codeEmittingOrder, linearScanOrder, spillMoveFactory, registerAllocationConfig); } } diff -r 54933d47cfa4 -r fad971028755 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LinearScanRegisterAllocationPhase.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LinearScanRegisterAllocationPhase.java Thu May 28 21:25:21 2015 +0200 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LinearScanRegisterAllocationPhase.java Thu May 28 21:26:54 2015 +0200 @@ -25,6 +25,7 @@ import java.util.*; import com.oracle.graal.api.code.*; +import com.oracle.graal.compiler.common.alloc.*; import com.oracle.graal.compiler.common.cfg.*; import com.oracle.graal.debug.*; import com.oracle.graal.lir.gen.*; @@ -40,7 +41,8 @@ } @Override - protected > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder, SpillMoveFactory spillMoveFactory) { + protected > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder, SpillMoveFactory spillMoveFactory, + RegisterAllocationConfig registerAllocationConfig) { allocator.printIntervals("Before register allocation"); allocateRegisters(); allocator.printIntervals("After register allocation"); diff -r 54933d47cfa4 -r fad971028755 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LinearScanResolveDataFlowPhase.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LinearScanResolveDataFlowPhase.java Thu May 28 21:25:21 2015 +0200 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LinearScanResolveDataFlowPhase.java Thu May 28 21:26:54 2015 +0200 @@ -27,6 +27,7 @@ import java.util.*; import com.oracle.graal.api.code.*; +import com.oracle.graal.compiler.common.alloc.*; import com.oracle.graal.compiler.common.cfg.*; import com.oracle.graal.debug.*; import com.oracle.graal.lir.*; @@ -48,7 +49,8 @@ } @Override - protected > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder, SpillMoveFactory spillMoveFactory) { + protected > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder, SpillMoveFactory spillMoveFactory, + RegisterAllocationConfig registerAllocationConfig) { resolveDataFlow(); } diff -r 54933d47cfa4 -r fad971028755 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LinearScanWalker.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LinearScanWalker.java Thu May 28 21:25:21 2015 +0200 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LinearScanWalker.java Thu May 28 21:26:54 2015 +0200 @@ -30,6 +30,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.alloc.RegisterAllocationConfig.*; import com.oracle.graal.compiler.common.cfg.*; import com.oracle.graal.compiler.common.util.*; import com.oracle.graal.debug.*; @@ -50,6 +51,10 @@ private MoveResolver moveResolver; // for ordering spill moves + private int minReg; + + private int maxReg; + /** * Only 10% of the lists in {@link #spillIntervals} are actually used. But when they are used, * they can grow quite long. The maximum length observed was 45 (all numbers taken from a @@ -95,10 +100,22 @@ } } + int maxRegisterNumber() { + return maxReg; + } + + int minRegisterNumber() { + return minReg; + } + + boolean isRegisterInRange(int reg) { + return reg >= minRegisterNumber() && reg <= maxRegisterNumber(); + } + void excludeFromUse(Interval i) { Value location = i.location(); int i1 = asRegister(location).number; - if (i1 >= availableRegs[0].number && i1 <= availableRegs[availableRegs.length - 1].number) { + if (isRegisterInRange(i1)) { usePos[i1] = 0; } } @@ -107,7 +124,7 @@ if (usePos != -1) { assert usePos != 0 : "must use excludeFromUse to set usePos to 0"; int i = asRegister(interval.location()).number; - if (i >= availableRegs[0].number && i <= availableRegs[availableRegs.length - 1].number) { + if (isRegisterInRange(i)) { if (this.usePos[i] > usePos) { this.usePos[i] = usePos; } @@ -126,7 +143,7 @@ void setBlockPos(Interval i, int blockPos) { if (blockPos != -1) { int reg = asRegister(i.location()).number; - if (reg >= availableRegs[0].number && reg <= availableRegs[availableRegs.length - 1].number) { + if (isRegisterInRange(reg)) { if (this.blockPos[reg] > blockPos) { this.blockPos[reg] = blockPos; } @@ -696,8 +713,7 @@ Register minFullReg = null; Register maxPartialReg = null; - for (int i = 0; i < availableRegs.length; ++i) { - Register availableReg = availableRegs[i]; + for (Register availableReg : availableRegs) { int number = availableReg.number; if (usePos[number] >= intervalTo) { // this register is free for the full interval @@ -858,7 +874,10 @@ } void initVarsForAlloc(Interval interval) { - availableRegs = allocator.regAllocConfig.getAllocatableRegisters(interval.kind().getPlatformKind()); + AllocatableRegisters allocatableRegisters = allocator.regAllocConfig.getAllocatableRegisters(interval.kind().getPlatformKind()); + availableRegs = allocatableRegisters.allocatableRegisters; + minReg = allocatableRegisters.minRegisterNumber; + maxReg = allocatableRegisters.maxRegisterNumber; } static boolean isMove(LIRInstruction op, Interval from, Interval to) { diff -r 54933d47cfa4 -r fad971028755 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LocationMarker.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LocationMarker.java Thu May 28 21:25:21 2015 +0200 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/alloc/lsra/LocationMarker.java Thu May 28 21:26:54 2015 +0200 @@ -28,6 +28,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.alloc.*; import com.oracle.graal.compiler.common.cfg.*; import com.oracle.graal.debug.*; import com.oracle.graal.lir.*; @@ -53,7 +54,8 @@ } @Override - protected > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder, SpillMoveFactory spillMoveFactory) { + protected > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder, SpillMoveFactory spillMoveFactory, + RegisterAllocationConfig registerAllocationConfig) { new Marker(lirGenRes.getLIR(), lirGenRes.getFrameMap()).build(); } diff -r 54933d47cfa4 -r fad971028755 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/AllocationPhase.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/AllocationPhase.java Thu May 28 21:25:21 2015 +0200 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/phases/AllocationPhase.java Thu May 28 21:26:54 2015 +0200 @@ -25,26 +25,29 @@ import java.util.*; import com.oracle.graal.api.code.*; +import com.oracle.graal.compiler.common.alloc.*; import com.oracle.graal.compiler.common.cfg.*; import com.oracle.graal.lir.gen.*; -import com.oracle.graal.lir.gen.LIRGeneratorTool.*; +import com.oracle.graal.lir.gen.LIRGeneratorTool.SpillMoveFactory; public abstract class AllocationPhase extends LIRPhase { public static final class AllocationContext { private final SpillMoveFactory spillMoveFactory; + private final RegisterAllocationConfig registerAllocationConfig; - public AllocationContext(SpillMoveFactory spillMoveFactory) { + public AllocationContext(SpillMoveFactory spillMoveFactory, RegisterAllocationConfig registerAllocationConfig) { this.spillMoveFactory = spillMoveFactory; + this.registerAllocationConfig = registerAllocationConfig; } } @Override protected final > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder, AllocationContext context) { - run(target, lirGenRes, codeEmittingOrder, linearScanOrder, context.spillMoveFactory); + run(target, lirGenRes, codeEmittingOrder, linearScanOrder, context.spillMoveFactory, context.registerAllocationConfig); } protected abstract > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder, - SpillMoveFactory spillMoveFactory); + SpillMoveFactory spillMoveFactory, RegisterAllocationConfig registerAllocationConfig); } diff -r 54933d47cfa4 -r fad971028755 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/stackslotalloc/LSStackSlotAllocator.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/stackslotalloc/LSStackSlotAllocator.java Thu May 28 21:25:21 2015 +0200 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/stackslotalloc/LSStackSlotAllocator.java Thu May 28 21:26:54 2015 +0200 @@ -30,6 +30,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.alloc.*; import com.oracle.graal.compiler.common.cfg.*; import com.oracle.graal.debug.*; import com.oracle.graal.debug.Debug.Scope; @@ -69,7 +70,8 @@ private static final DebugTimer AssignSlotsTimer = Debug.timer("LSStackSlotAllocator[AssignSlots]"); @Override - protected > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder, SpillMoveFactory spillMoveFactory) { + protected > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder, SpillMoveFactory spillMoveFactory, + RegisterAllocationConfig registerAllocationConfig) { lirGenRes.buildFrameMap(this); } diff -r 54933d47cfa4 -r fad971028755 graal/com.oracle.graal.lir/src/com/oracle/graal/lir/stackslotalloc/SimpleStackSlotAllocator.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/stackslotalloc/SimpleStackSlotAllocator.java Thu May 28 21:25:21 2015 +0200 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/stackslotalloc/SimpleStackSlotAllocator.java Thu May 28 21:26:54 2015 +0200 @@ -28,6 +28,7 @@ import com.oracle.graal.api.code.*; import com.oracle.graal.compiler.common.*; +import com.oracle.graal.compiler.common.alloc.*; import com.oracle.graal.compiler.common.cfg.*; import com.oracle.graal.debug.*; import com.oracle.graal.debug.Debug.Scope; @@ -40,7 +41,8 @@ public class SimpleStackSlotAllocator extends AllocationPhase implements StackSlotAllocator { @Override - protected > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder, SpillMoveFactory spillMoveFactory) { + protected > void run(TargetDescription target, LIRGenerationResult lirGenRes, List codeEmittingOrder, List linearScanOrder, SpillMoveFactory spillMoveFactory, + RegisterAllocationConfig registerAllocationConfig) { lirGenRes.buildFrameMap(this); } diff -r 54933d47cfa4 -r fad971028755 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GraphDecoder.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GraphDecoder.java Thu May 28 21:25:21 2015 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/GraphDecoder.java Thu May 28 21:26:54 2015 +0200 @@ -962,7 +962,7 @@ return true; } else if (node instanceof Invoke) { - assert node instanceof InvokeNode || node instanceof InvokeWithExceptionNode : "The only two Invoke node classes"; + assert node instanceof InvokeNode || node instanceof InvokeWithExceptionNode : "The only two Invoke node classes. Got " + node.getClass(); assert direct : "Invoke and InvokeWithException only have direct successor and input edges"; if (edges.type() == Edges.Type.Successors) { assert edges.getCount() == (node instanceof InvokeWithExceptionNode ? 2 : 1) : "InvokeNode has one successor (next); InvokeWithExceptionNode has two successors (next, exceptionEdge)"; diff -r 54933d47cfa4 -r fad971028755 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/memory/AbstractMemoryCheckpoint.java diff -r 54933d47cfa4 -r fad971028755 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/memory/AbstractWriteNode.java diff -r 54933d47cfa4 -r fad971028755 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/memory/Access.java diff -r 54933d47cfa4 -r fad971028755 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/memory/FixedAccessNode.java diff -r 54933d47cfa4 -r fad971028755 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/memory/FloatableAccessNode.java diff -r 54933d47cfa4 -r fad971028755 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/memory/FloatingAccessNode.java diff -r 54933d47cfa4 -r fad971028755 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/memory/FloatingReadNode.java diff -r 54933d47cfa4 -r fad971028755 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/memory/HeapAccess.java diff -r 54933d47cfa4 -r fad971028755 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/memory/MemoryAccess.java diff -r 54933d47cfa4 -r fad971028755 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/memory/MemoryAnchorNode.java diff -r 54933d47cfa4 -r fad971028755 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/memory/MemoryCheckpoint.java diff -r 54933d47cfa4 -r fad971028755 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/memory/MemoryMap.java diff -r 54933d47cfa4 -r fad971028755 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/memory/MemoryMapNode.java diff -r 54933d47cfa4 -r fad971028755 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/memory/MemoryNode.java diff -r 54933d47cfa4 -r fad971028755 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/memory/MemoryPhiNode.java diff -r 54933d47cfa4 -r fad971028755 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/memory/ReadNode.java diff -r 54933d47cfa4 -r fad971028755 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/memory/WriteNode.java diff -r 54933d47cfa4 -r fad971028755 graal/com.oracle.graal.options.processor/src/com/oracle/graal/options/processor/GraalJars.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.options.processor/src/com/oracle/graal/options/processor/GraalJars.java Thu May 28 21:26:54 2015 +0200 @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.options.processor; + +import java.io.*; +import java.util.*; +import java.util.stream.*; +import java.util.zip.*; + +public class GraalJars implements Iterable { + private final List jars = new ArrayList<>(2); + + public GraalJars() { + String classPath = System.getProperty("java.class.path"); + for (String e : classPath.split(File.pathSeparator)) { + if (e.endsWith(File.separatorChar + "graal.jar") || e.endsWith(File.separatorChar + "graal-truffle.jar")) { + try { + jars.add(new ZipFile(e)); + } catch (IOException ioe) { + throw new InternalError(ioe); + } + } + } + if (jars.size() != 2) { + throw new InternalError("Could not find graal.jar or graal-truffle.jar on class path: " + classPath); + } + } + + public Iterator iterator() { + Stream entries = jars.stream().flatMap(ZipFile::stream); + return entries.iterator(); + } + + public InputStream getInputStream(String classFilePath) throws IOException { + for (ZipFile jar : jars) { + ZipEntry entry = jar.getEntry(classFilePath); + if (entry != null) { + return jar.getInputStream(entry); + } + } + return null; + } +} diff -r 54933d47cfa4 -r fad971028755 graal/com.oracle.graal.options.processor/src/com/oracle/graal/options/processor/OptionProcessor.java --- a/graal/com.oracle.graal.options.processor/src/com/oracle/graal/options/processor/OptionProcessor.java Thu May 28 21:25:21 2015 +0200 +++ b/graal/com.oracle.graal.options.processor/src/com/oracle/graal/options/processor/OptionProcessor.java Thu May 28 21:26:54 2015 +0200 @@ -211,6 +211,7 @@ try { createProviderFile(pkg, optionsClassName, originatingElements); + createOptionsFile(info, pkg, topDeclaringClass.toString(), originatingElements); } catch (IOException e) { processingEnv.getMessager().printMessage(Kind.ERROR, e.getMessage(), info.topDeclaringType); } @@ -224,6 +225,53 @@ writer.close(); } + private void createOptionsFile(OptionsInfo info, String pkg, String relativeName, Element... originatingElements) throws IOException { + String filename = "META-INF/options/" + pkg + "." + relativeName; + FileObject file = processingEnv.getFiler().createResource(StandardLocation.CLASS_OUTPUT, "", filename, originatingElements); + PrintWriter writer = new PrintWriter(new OutputStreamWriter(file.openOutputStream(), "UTF-8")); + Types types = processingEnv.getTypeUtils(); + for (OptionInfo option : info.options) { + String help = option.help; + if (help.indexOf('\t') >= 0 || help.indexOf('\r') >= 0 || help.indexOf('\n') >= 0) { + processingEnv.getMessager().printMessage(Kind.WARNING, "Option help should not contain '\\t', '\\r' or '\\n'", option.field); + help = help.replace('\t', ' ').replace('\n', ' ').replace('\r', ' '); + } + try { + char optionTypeToChar = optionTypeToChar(option); + String fqDeclaringClass = className(types.erasure(option.field.getEnclosingElement().asType())); + String fqFieldType = className(types.erasure(option.field.asType())); + writer.printf("%s\t%s\t%s\t%s\t%s%n", option.name, optionTypeToChar, help, fqDeclaringClass, fqFieldType); + } catch (IllegalArgumentException iae) { + } + } + writer.close(); + } + + private String className(TypeMirror t) { + DeclaredType dt = (DeclaredType) t; + return processingEnv.getElementUtils().getBinaryName((TypeElement) dt.asElement()).toString(); + } + + private char optionTypeToChar(OptionInfo option) { + switch (option.type) { + case "Boolean": + return 'z'; + case "Integer": + return 'i'; + case "Long": + return 'j'; + case "Float": + return 'f'; + case "Double": + return 'd'; + case "String": + return 's'; + default: + processingEnv.getMessager().printMessage(Kind.ERROR, "Unsoported option type: " + option.type, option.field); + throw new IllegalArgumentException(); + } + } + protected PrintWriter createSourceFile(String pkg, String relativeName, Filer filer, Element... originatingElements) { try { // Ensure Unix line endings to comply with Graal code style guide checked by Checkstyle diff -r 54933d47cfa4 -r fad971028755 graal/com.oracle.graal.options.processor/src/com/oracle/graal/options/processor/OptionsVerifier.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.options.processor/src/com/oracle/graal/options/processor/OptionsVerifier.java Thu May 28 21:26:54 2015 +0200 @@ -0,0 +1,184 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.options.processor; + +import static java.lang.String.*; + +import java.io.*; +import java.lang.reflect.*; +import java.util.*; + +import jdk.internal.org.objectweb.asm.*; +import jdk.internal.org.objectweb.asm.Type; + +import com.oracle.graal.options.*; + +/** + * A {@link ClassVisitor} that verifies a class declaring one or more {@linkplain OptionValue + * options} has a class initializer that only initializes the option(s). This sanity check mitigates + * the possibility of an option value being used before the code that sets the value (e.g., from the + * command line) has been executed. + */ +final class OptionsVerifier extends ClassVisitor { + + public static void checkClass(Class cls, OptionDescriptor option, Set> checked, GraalJars graalJars) throws IOException { + if (!checked.contains(cls)) { + checked.add(cls); + Class superclass = cls.getSuperclass(); + if (superclass != null && !superclass.equals(Object.class)) { + checkClass(superclass, option, checked, graalJars); + } + + String classFilePath = cls.getName().replace('.', '/') + ".class"; + ClassReader cr = new ClassReader(Objects.requireNonNull(graalJars.getInputStream(classFilePath), "Could not find class file for " + cls.getName())); + + ClassVisitor cv = new OptionsVerifier(cls, option); + cr.accept(cv, 0); + } + } + + /** + * The option field context of the verification. + */ + private final OptionDescriptor option; + + /** + * The class in which {@link #option} is declared or a super-class of that class. This is the + * class whose {@code } method is being verified. + */ + private final Class cls; + + /** + * Source file context for error reporting. + */ + String sourceFile = null; + + /** + * Line number for error reporting. + */ + int lineNo = -1; + + final Class[] boxingTypes = {Boolean.class, Byte.class, Short.class, Character.class, Integer.class, Float.class, Long.class, Double.class}; + + private static Class resolve(String name) { + try { + return Class.forName(name.replace('/', '.')); + } catch (ClassNotFoundException e) { + throw new InternalError(e); + } + } + + OptionsVerifier(Class cls, OptionDescriptor desc) { + super(Opcodes.ASM5); + this.cls = cls; + this.option = desc; + } + + @Override + public void visitSource(String source, String debug) { + this.sourceFile = source; + } + + void verify(boolean condition, String message) { + if (!condition) { + error(message); + } + } + + void error(String message) { + String errorMessage = format("%s:%d: Illegal code in %s. which may be executed when %s.%s is initialized:%n%n %s%n%n" + "The recommended solution is to move " + option.getName() + + " into a separate class (e.g., %s.Options).%n", sourceFile, lineNo, cls.getSimpleName(), option.getDeclaringClass().getSimpleName(), option.getName(), message, + option.getDeclaringClass().getSimpleName()); + throw new InternalError(errorMessage); + + } + + @Override + public MethodVisitor visitMethod(int access, String name, String d, String signature, String[] exceptions) { + if (name.equals("")) { + return new MethodVisitor(Opcodes.ASM5) { + + @Override + public void visitLineNumber(int line, Label start) { + lineNo = line; + } + + @Override + public void visitFieldInsn(int opcode, String owner, String fieldName, String fieldDesc) { + if (opcode == Opcodes.PUTFIELD || opcode == Opcodes.PUTSTATIC) { + verify(resolve(owner).equals(option.getDeclaringClass()), format("store to field %s.%s", resolve(owner).getSimpleName(), fieldName)); + verify(opcode != Opcodes.PUTFIELD, format("store to non-static field %s.%s", resolve(owner).getSimpleName(), fieldName)); + } + } + + private Executable resolveMethod(String owner, String methodName, String methodDesc) { + Class declaringClass = resolve(owner); + if (methodName.equals("")) { + for (Constructor c : declaringClass.getDeclaredConstructors()) { + if (methodDesc.equals(Type.getConstructorDescriptor(c))) { + return c; + } + } + } else { + Type[] argumentTypes = Type.getArgumentTypes(methodDesc); + for (Method m : declaringClass.getDeclaredMethods()) { + if (m.getName().equals(methodName)) { + if (Arrays.equals(argumentTypes, Type.getArgumentTypes(m))) { + if (Type.getReturnType(methodDesc).equals(Type.getReturnType(m))) { + return m; + } + } + } + } + } + throw new NoSuchMethodError(declaringClass + "." + methodName + methodDesc); + } + + /** + * Checks whether a given method is allowed to be called. + */ + private boolean checkInvokeTarget(Executable method) { + Class holder = method.getDeclaringClass(); + if (method instanceof Constructor) { + if (OptionValue.class.isAssignableFrom(holder)) { + return true; + } + } else if (Arrays.asList(boxingTypes).contains(holder)) { + return method.getName().equals("valueOf"); + } else if (method.getDeclaringClass().equals(Class.class)) { + return method.getName().equals("desiredAssertionStatus"); + } + return false; + } + + @Override + public void visitMethodInsn(int opcode, String owner, String methodName, String methodDesc, boolean itf) { + Executable callee = resolveMethod(owner, methodName, methodDesc); + verify(checkInvokeTarget(callee), "invocation of " + callee); + } + }; + } else { + return null; + } + } +} diff -r 54933d47cfa4 -r fad971028755 graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionUtils.java --- a/graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionUtils.java Thu May 28 21:25:21 2015 +0200 +++ b/graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionUtils.java Thu May 28 21:26:54 2015 +0200 @@ -34,24 +34,19 @@ * Parses a given option value specification. * * @param option the specification of an option and its value - * @param setter the object to notify of the parsed option and value. If null, the - * {@link OptionValue#setValue(Object)} method of the specified option is called - * instead. + * @param setter the object to notify of the parsed option and value. */ - public static boolean parseOption(SortedMap options, String option, String prefix, OptionConsumer setter) { + public static void parseOption(String option, OptionConsumer setter) { + SortedMap options = OptionsLoader.options; + Objects.requireNonNull(setter); if (option.length() == 0) { - return false; + return; } Object value = null; String optionName = null; String valueString = null; - if (option.equals("+PrintFlags")) { - printFlags(options, prefix); - return true; - } - char first = option.charAt(0); if (first == '+' || first == '-') { optionName = option.substring(1); @@ -69,21 +64,18 @@ OptionDescriptor desc = options.get(optionName); if (desc == null) { - printNoMatchMessage(options, optionName, prefix); - return false; + throw new IllegalArgumentException("Option '" + optionName + "' not found"); } Class optionType = desc.getType(); if (value == null) { if (optionType == Boolean.TYPE || optionType == Boolean.class) { - System.err.println("Value for boolean option '" + optionName + "' must use '" + prefix + "+" + optionName + "' or '" + prefix + "-" + optionName + "' format"); - return false; + throw new IllegalArgumentException("Boolean option '" + optionName + "' must use +/- prefix"); } if (valueString == null) { - System.err.println("Value for option '" + optionName + "' must use '" + prefix + optionName + "=' format"); - return false; + throw new IllegalArgumentException("Missing value for non-boolean option '" + optionName + "' must use " + optionName + "= format"); } if (optionType == Float.class) { @@ -96,28 +88,16 @@ value = Long.valueOf(parseLong(valueString)); } else if (optionType == String.class) { value = valueString; + } else { + throw new IllegalArgumentException("Wrong value for option '" + optionName + "'"); } } else { if (optionType != Boolean.class) { - System.err.println("Value for option '" + optionName + "' must use '" + prefix + optionName + "=' format"); - return false; + throw new IllegalArgumentException("Non-boolean option '" + optionName + "' can not use +/- prefix. Use " + optionName + "= format"); } } - if (value != null) { - if (setter != null) { - setter.set(desc, value); - } else { - OptionValue optionValue = desc.getOptionValue(); - optionValue.setValue(value); - // System.err.println("Set option " + desc.getName() + " to " + value); - } - } else { - System.err.println("Wrong value \"" + valueString + "\" for option " + optionName); - return false; - } - - return true; + setter.set(desc, value); } private static long parseLong(String v) { @@ -141,27 +121,6 @@ return Long.parseLong(valueString) * scale; } - public static void printNoMatchMessage(SortedMap options, String optionName, String prefix) { - OptionDescriptor desc = options.get(optionName); - if (desc != null) { - if (desc.getType() == Boolean.class) { - System.err.println("Boolean option " + optionName + " must be prefixed with '+' or '-'"); - } else { - System.err.println(desc.getType().getSimpleName() + " option " + optionName + " must not be prefixed with '+' or '-'"); - } - } else { - System.err.println("Could not find option " + optionName + " (use " + prefix + "+PrintFlags to see options)"); - List matches = fuzzyMatch(options, optionName); - if (!matches.isEmpty()) { - System.err.println("Did you mean one of the following?"); - for (OptionDescriptor match : matches) { - boolean isBoolean = match.getType() == Boolean.class; - System.err.println(String.format(" %s%s%s", isBoolean ? "(+/-)" : "", match.getName(), isBoolean ? "" : "=")); - } - } - } - } - /** * Wraps some given text to one or more lines of a given maximum width. * @@ -220,38 +179,4 @@ System.exit(0); } - - /** - * Compute string similarity based on Dice's coefficient. - * - * Ported from str_similar() in globals.cpp. - */ - static float stringSimiliarity(String str1, String str2) { - int hit = 0; - for (int i = 0; i < str1.length() - 1; ++i) { - for (int j = 0; j < str2.length() - 1; ++j) { - if ((str1.charAt(i) == str2.charAt(j)) && (str1.charAt(i + 1) == str2.charAt(j + 1))) { - ++hit; - break; - } - } - } - return 2.0f * hit / (str1.length() + str2.length()); - } - - private static final float FUZZY_MATCH_THRESHOLD = 0.7F; - - /** - * Returns the set of options that fuzzy match a given option name. - */ - private static List fuzzyMatch(SortedMap options, String optionName) { - List matches = new ArrayList<>(); - for (Map.Entry e : options.entrySet()) { - float score = stringSimiliarity(e.getKey(), optionName); - if (score >= FUZZY_MATCH_THRESHOLD) { - matches.add(e.getValue()); - } - } - return matches; - } } diff -r 54933d47cfa4 -r fad971028755 graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionValue.java --- a/graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionValue.java Thu May 28 21:25:21 2015 +0200 +++ b/graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionValue.java Thu May 28 21:26:54 2015 +0200 @@ -30,7 +30,6 @@ * An option value. */ public class OptionValue { - /** * Temporarily changes the value for an option. The {@linkplain OptionValue#getValue() value} of * {@code option} is set to {@code value} until {@link OverrideScope#close()} is called on the @@ -138,7 +137,7 @@ overrideScopeTL.set(overrideScope); } - private T initialValue; + private T defaultValue; /** * The raw option value. @@ -164,29 +163,30 @@ @SuppressWarnings("unchecked") public OptionValue(T value) { - this.initialValue = value; - this.value = (T) UNINITIALIZED; + this.defaultValue = value; + this.value = (T) DEFAULT; addToHistogram(this); } + private static final Object DEFAULT = "DEFAULT"; private static final Object UNINITIALIZED = "UNINITIALIZED"; /** * Creates an uninitialized option value for a subclass that initializes itself - * {@link #initialValue() lazily}. + * {@link #defaultValue() lazily}. */ @SuppressWarnings("unchecked") protected OptionValue() { - this.initialValue = (T) UNINITIALIZED; - this.value = (T) UNINITIALIZED; + this.defaultValue = (T) UNINITIALIZED; + this.value = (T) DEFAULT; addToHistogram(this); } /** - * Lazy initialization of value. + * Lazy initialization of default value. */ - protected T initialValue() { - throw new InternalError("Uninitialized option value must override initialValue()"); + protected T defaultValue() { + throw new InternalError("Option without a default value value must override defaultValue()"); } /** @@ -223,27 +223,19 @@ * {@link #setValue(Object)} or registering {@link OverrideScope}s. Therefore, it is also not * affected by options set on the command line. */ - public T getInitialValue() { - if (initialValue == UNINITIALIZED) { - initialValue = initialValue(); + public T getDefaultValue() { + if (defaultValue == UNINITIALIZED) { + defaultValue = defaultValue(); } - return initialValue; + return defaultValue; } /** * Returns true if the option has the same value that was set in the source code. */ - public boolean hasInitialValue() { - if (!(this instanceof StableOptionValue)) { - OverrideScope overrideScope = getOverrideScope(); - if (overrideScope != null) { - T override = overrideScope.getOverride(this); - if (override != null) { - return false; - } - } - } - return value == UNINITIALIZED || Objects.equals(value, getInitialValue()); + public boolean hasDefaultValue() { + getValue(); // ensure initialized + return value == DEFAULT || Objects.equals(value, getDefaultValue()); } /** @@ -262,10 +254,10 @@ } } } - if (value != UNINITIALIZED) { + if (value != DEFAULT) { return value; } else { - return getInitialValue(); + return getDefaultValue(); } } @@ -285,10 +277,10 @@ overrideScope.getOverrides(this, (Collection) values); } } - if (value != UNINITIALIZED) { + if (value != DEFAULT) { values.add(value); } else { - values.add(getInitialValue()); + values.add(getDefaultValue()); } return values; } diff -r 54933d47cfa4 -r fad971028755 graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionsLoader.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.options/src/com/oracle/graal/options/OptionsLoader.java Thu May 28 21:26:54 2015 +0200 @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.options; + +import java.util.*; + +import com.oracle.graal.api.runtime.*; + +/** + * Helper class used to load option descriptors. Only to be used in the slow-path. + */ +public class OptionsLoader { + public static final SortedMap options = new TreeMap<>(); + + /** + * Initializes {@link #options} from {@link Options} services. + */ + static { + for (Options opts : Services.load(Options.class)) { + for (OptionDescriptor desc : opts) { + String name = desc.getName(); + OptionDescriptor existing = options.put(name, desc); + assert existing == null : "Option named \"" + name + "\" has multiple definitions: " + existing.getLocation() + " and " + desc.getLocation(); + } + } + } +} diff -r 54933d47cfa4 -r fad971028755 graal/com.oracle.graal.options/src/com/oracle/graal/options/StableOptionValue.java --- a/graal/com.oracle.graal.options/src/com/oracle/graal/options/StableOptionValue.java Thu May 28 21:25:21 2015 +0200 +++ b/graal/com.oracle.graal.options/src/com/oracle/graal/options/StableOptionValue.java Thu May 28 21:26:54 2015 +0200 @@ -42,7 +42,7 @@ /** * Creates an uninitialized stable option value for a subclass that initializes itself - * {@link #initialValue() lazily}. + * {@link #defaultValue() lazily}. */ public StableOptionValue() { } diff -r 54933d47cfa4 -r fad971028755 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MethodHandleNode.java diff -r 54933d47cfa4 -r fad971028755 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ResolvedMethodHandleCallTargetNode.java diff -r 54933d47cfa4 -r fad971028755 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/TruffleCompiler.java diff -r 54933d47cfa4 -r fad971028755 graal/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/instrument/AdvancedInstrumentTest.java diff -r 54933d47cfa4 -r fad971028755 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/AdvancedInstrumentResultListener.java diff -r 54933d47cfa4 -r fad971028755 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/AdvancedInstrumentRoot.java diff -r 54933d47cfa4 -r fad971028755 graal/com.oracle.truffle.api/src/com/oracle/truffle/api/instrument/AdvancedInstrumentRootFactory.java diff -r 54933d47cfa4 -r fad971028755 make/Makefile --- a/make/Makefile Thu May 28 21:25:21 2015 +0200 +++ b/make/Makefile Thu May 28 21:26:54 2015 +0200 @@ -638,6 +638,9 @@ $(EXPORT_JRE_LIB_GRAAL_SERVICES_DIR)/%: $(SHARED_DIR)/services/% $(install-file) +$(EXPORT_JRE_LIB_GRAAL_OPTIONS_DIR)/%: $(SHARED_DIR)/options/% + $(install-file) + $(EXPORT_INCLUDE_DIR)/%: $(HS_SRC_DIR)/share/vm/code/% $(install-file) diff -r 54933d47cfa4 -r fad971028755 make/defs.make --- a/make/defs.make Thu May 28 21:25:21 2015 +0200 +++ b/make/defs.make Thu May 28 21:26:54 2015 +0200 @@ -370,5 +370,41 @@ EXPORT_LIST += $(EXPORT_JRE_LIB_GRAAL_SERVICES_DIR)/com.oracle.graal.truffle.hotspot.nfi.RawNativeCallNodeFactory EXPORT_LIST += $(EXPORT_JRE_LIB_GRAAL_SERVICES_DIR)/com.oracle.graal.truffle.OptimizedCallTargetInstrumentationFactory +EXPORT_LIST += $(EXPORT_JRE_LIB_GRAAL_OPTIONS_DIR)/com.oracle.graal.compiler.common.GraalOptions +EXPORT_LIST += $(EXPORT_JRE_LIB_GRAAL_OPTIONS_DIR)/com.oracle.graal.compiler.GraalCompiler +EXPORT_LIST += $(EXPORT_JRE_LIB_GRAAL_OPTIONS_DIR)/com.oracle.graal.compiler.GraalDebugConfig +EXPORT_LIST += $(EXPORT_JRE_LIB_GRAAL_OPTIONS_DIR)/com.oracle.graal.compiler.phases.HighTier +EXPORT_LIST += $(EXPORT_JRE_LIB_GRAAL_OPTIONS_DIR)/com.oracle.graal.compiler.phases.LowTier +EXPORT_LIST += $(EXPORT_JRE_LIB_GRAAL_OPTIONS_DIR)/com.oracle.graal.graph.Graph +EXPORT_LIST += $(EXPORT_JRE_LIB_GRAAL_OPTIONS_DIR)/com.oracle.graal.hotspot.CompileTheWorld +EXPORT_LIST += $(EXPORT_JRE_LIB_GRAAL_OPTIONS_DIR)/com.oracle.graal.hotspot.debug.BenchmarkCounters +EXPORT_LIST += $(EXPORT_JRE_LIB_GRAAL_OPTIONS_DIR)/com.oracle.graal.hotspot.HotSpotBackend +EXPORT_LIST += $(EXPORT_JRE_LIB_GRAAL_OPTIONS_DIR)/com.oracle.graal.hotspot.HotSpotGraalRuntime +EXPORT_LIST += $(EXPORT_JRE_LIB_GRAAL_OPTIONS_DIR)/com.oracle.graal.hotspot.replacements.InstanceOfSnippets +EXPORT_LIST += $(EXPORT_JRE_LIB_GRAAL_OPTIONS_DIR)/com.oracle.graal.hotspot.replacements.MonitorSnippets +EXPORT_LIST += $(EXPORT_JRE_LIB_GRAAL_OPTIONS_DIR)/com.oracle.graal.hotspot.replacements.NewObjectSnippets +EXPORT_LIST += $(EXPORT_JRE_LIB_GRAAL_OPTIONS_DIR)/com.oracle.graal.java.AbstractBytecodeParser +EXPORT_LIST += $(EXPORT_JRE_LIB_GRAAL_OPTIONS_DIR)/com.oracle.graal.lir.alloc.lsra.LinearScan +EXPORT_LIST += $(EXPORT_JRE_LIB_GRAAL_OPTIONS_DIR)/com.oracle.graal.lir.alloc.lsra.LocationMarker +EXPORT_LIST += $(EXPORT_JRE_LIB_GRAAL_OPTIONS_DIR)/com.oracle.graal.lir.alloc.lsra.OptimizingLinearScanWalker +EXPORT_LIST += $(EXPORT_JRE_LIB_GRAAL_OPTIONS_DIR)/com.oracle.graal.lir.constopt.ConstantLoadOptimization +EXPORT_LIST += $(EXPORT_JRE_LIB_GRAAL_OPTIONS_DIR)/com.oracle.graal.lir.gen.LIRGenerator +EXPORT_LIST += $(EXPORT_JRE_LIB_GRAAL_OPTIONS_DIR)/com.oracle.graal.lir.phases.LIRPhase +EXPORT_LIST += $(EXPORT_JRE_LIB_GRAAL_OPTIONS_DIR)/com.oracle.graal.lir.phases.PostAllocationOptimizationStage +EXPORT_LIST += $(EXPORT_JRE_LIB_GRAAL_OPTIONS_DIR)/com.oracle.graal.lir.ssa.SSADestructionPhase +EXPORT_LIST += $(EXPORT_JRE_LIB_GRAAL_OPTIONS_DIR)/com.oracle.graal.lir.stackslotalloc.LSStackSlotAllocator +EXPORT_LIST += $(EXPORT_JRE_LIB_GRAAL_OPTIONS_DIR)/com.oracle.graal.loop.LoopPolicies +EXPORT_LIST += $(EXPORT_JRE_LIB_GRAAL_OPTIONS_DIR)/com.oracle.graal.phases.common.DeadCodeEliminationPhase +EXPORT_LIST += $(EXPORT_JRE_LIB_GRAAL_OPTIONS_DIR)/com.oracle.graal.phases.common.inlining.InliningPhase +EXPORT_LIST += $(EXPORT_JRE_LIB_GRAAL_OPTIONS_DIR)/com.oracle.graal.phases.tiers.Suites +EXPORT_LIST += $(EXPORT_JRE_LIB_GRAAL_OPTIONS_DIR)/com.oracle.graal.printer.NoDeadCodeVerifyHandler +EXPORT_LIST += $(EXPORT_JRE_LIB_GRAAL_OPTIONS_DIR)/com.oracle.graal.replacements.StandardGraphBuilderPlugins +EXPORT_LIST += $(EXPORT_JRE_LIB_GRAAL_OPTIONS_DIR)/com.oracle.graal.truffle.PartialEvaluator +EXPORT_LIST += $(EXPORT_JRE_LIB_GRAAL_OPTIONS_DIR)/com.oracle.graal.truffle.TruffleCompilerOptions +EXPORT_LIST += $(EXPORT_JRE_LIB_GRAAL_OPTIONS_DIR)/com.oracle.graal.virtual.phases.ea.PartialEscapePhase +EXPORT_LIST += $(EXPORT_JRE_LIB_GRAAL_OPTIONS_DIR)/com.oracle.graal.lir.asm.CompilationResultBuilder +EXPORT_LIST += $(EXPORT_JRE_LIB_GRAAL_OPTIONS_DIR)/com.oracle.graal.java.GraphBuilderPhase + + .PHONY: $(HS_ALT_MAKE)/defs.make diff -r 54933d47cfa4 -r fad971028755 mx/mx_graal.py --- a/mx/mx_graal.py Thu May 28 21:25:21 2015 +0200 +++ b/mx/mx_graal.py Thu May 28 21:26:54 2015 +0200 @@ -30,7 +30,6 @@ 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 @@ -520,62 +519,6 @@ 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. - - 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')): - 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', mx._separatedCygpathU2W(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()) - - # Store SHA1 in generated Java class and append class to specified jar - javaPackageName = 'com.oracle.graal.hotspot.sourcegen' - javaClassName = javaPackageName + '.GeneratedSourcesSha1' - javaSource = join(_graal_home, 'GeneratedSourcesSha1.java') - javaClass = join(_graal_home, javaClassName.replace('.', os.path.sep) + '.class') - with open(javaSource, 'w') as fp: - print >> fp, 'package ' + javaPackageName + ';' - print >> fp, 'class GeneratedSourcesSha1 { private static final String value = "' + sha1 + '"; }' - subprocess.check_call([mx.java().javac, '-d', mx._cygpathU2W(_graal_home), mx._cygpathU2W(javaSource)], stderr=subprocess.PIPE, stdout=subprocess.PIPE) - zf = zipfile.ZipFile(dist.path, 'a') - with open(javaClass, 'rb') as fp: - zf.writestr(javaClassName.replace('.', '/') + '.class', fp.read()) - zf.close() - os.unlink(javaSource) - os.unlink(javaClass) - javaClassParent = os.path.dirname(javaClass) - while len(os.listdir(javaClassParent)) == 0: - os.rmdir(javaClassParent) - javaClassParent = os.path.dirname(javaClassParent) - def _copyToJdk(src, dst, permissions=JDK_UNIX_PERMISSIONS_FILE): name = os.path.basename(src) dstLib = join(dst, name) @@ -666,27 +609,41 @@ filtered.append(className) return filtered -def _extractGraalServiceFiles(graalJars, destination, cleanDestination=True): +def _extractGraalFiles(graalJars, servicesDir, optionsDir, cleanDestination=True): if cleanDestination: - if exists(destination): - shutil.rmtree(destination) - os.makedirs(destination) + if exists(servicesDir): + shutil.rmtree(servicesDir) + if exists(optionsDir): + shutil.rmtree(optionsDir) + if not exists(servicesDir): + os.makedirs(servicesDir) + if not exists(optionsDir): + os.makedirs(optionsDir) servicesMap = {} + optionsFiles = [] for jar in graalJars: if os.path.isfile(jar): with zipfile.ZipFile(jar) as zf: for member in zf.namelist(): - if not member.startswith('META-INF/services'): - continue - serviceName = basename(member) - # we don't handle directories - assert serviceName and member == 'META-INF/services/' + serviceName - with zf.open(member) as serviceFile: - serviceImpls = servicesMap.setdefault(serviceName, []) - for line in serviceFile.readlines(): - line = line.strip() - if line: - serviceImpls.append(line) + if member.startswith('META-INF/services'): + serviceName = basename(member) + # we don't handle directories + assert serviceName and member == 'META-INF/services/' + serviceName + with zf.open(member) as serviceFile: + serviceImpls = servicesMap.setdefault(serviceName, []) + for line in serviceFile.readlines(): + line = line.strip() + if line: + serviceImpls.append(line) + elif member.startswith('META-INF/options'): + filename = basename(member) + # we don't handle directories + assert filename and member == 'META-INF/options/' + filename + targetpath = join(optionsDir, filename) + optionsFiles.append(filename) + with zf.open(member) as optionsFile, \ + file(targetpath, "wb") as target: + shutil.copyfileobj(optionsFile, target) graalServices = _filterGraalService(servicesMap.keys(), graalJars) for serviceName in graalServices: serviceImpls = servicesMap[serviceName] @@ -694,18 +651,19 @@ f = os.fdopen(fd, 'w+') for serviceImpl in serviceImpls: f.write(serviceImpl + os.linesep) - target = join(destination, serviceName) + target = join(servicesDir, serviceName) f.close() shutil.move(tmp, target) if mx.get_os() != 'windows': os.chmod(target, JDK_UNIX_PERMISSIONS_FILE) - return graalServices - -def _updateGraalServiceFiles(jdkDir): + return (graalServices, optionsFiles) + +def _updateGraalFiles(jdkDir): jreGraalDir = join(jdkDir, 'jre', 'lib', 'graal') graalJars = [join(jreGraalDir, e) for e in os.listdir(jreGraalDir) if e.startswith('graal') and e.endswith('.jar')] jreGraalServicesDir = join(jreGraalDir, 'services') - _extractGraalServiceFiles(graalJars, jreGraalServicesDir) + jreGraalOptionsDir = join(jreGraalDir, 'options') + _extractGraalFiles(graalJars, jreGraalServicesDir, jreGraalOptionsDir) @@ -715,17 +673,7 @@ """ dist = mx.distribution(deployableDist.name) - - if dist.name == 'GRAAL_TRUFFLE': - # The content in graalRuntime.inline.hpp is generated from Graal - # classes that implement com.oracle.graal.api.runtime.Service - # or contain com.oracle.graal.options.Option annotated fields. - # Since GRAAL_TRUFFLE is the leaf most distribution containing - # such classes, the generation is triggered when GRAAL_TRUFFLE - # is (re)built. - _update_graalRuntime_inline_hpp(dist) jdks = _jdksDir() - if exists(jdks): for e in os.listdir(jdks): jdkDir = join(jdks, e) @@ -744,7 +692,7 @@ _copyToJdk(dist.sourcesPath, jdkDir) if deployableDist.isGraalClassLoader: # deploy service files - _updateGraalServiceFiles(jdkDir) + _updateGraalFiles(jdkDir) # run a command in the windows SDK Debug Shell def _runInDebugShell(cmd, workingDir, logFile=None, findInOutput=None, respondTo=None): @@ -919,11 +867,15 @@ if defLine not in defs: mx.abort('Missing following line in ' + defsPath + '\n' + defLine) shutil.copy(dist.path, opts2.export_dir) - services = _extractGraalServiceFiles(graalJars, join(opts2.export_dir, 'services')) + services, optionsFiles = _extractGraalFiles(graalJars, join(opts2.export_dir, 'services'), join(opts2.export_dir, 'options')) for service in services: defLine = 'EXPORT_LIST += $(EXPORT_JRE_LIB_GRAAL_SERVICES_DIR)/' + service if defLine not in defs: mx.abort('Missing following line in ' + defsPath + ' for service from ' + dist.name + '\n' + defLine) + for optionsFile in optionsFiles: + defLine = 'EXPORT_LIST += $(EXPORT_JRE_LIB_GRAAL_OPTIONS_DIR)/' + optionsFile + if defLine not in defs: + mx.abort('Missing following line in ' + defsPath + ' for options from ' + dist.name + '\n' + defLine) graalOptions = join(_graal_home, 'graal.options') if exists(graalOptions): shutil.copy(graalOptions, opts2.export_dir) @@ -1766,7 +1718,7 @@ # Force if not mx._opts.strict_compliance: - mx.log("[gate] foring strict compliance") + mx.log("[gate] forcing strict compliance") mx._opts.strict_compliance = True tasks = [] diff -r 54933d47cfa4 -r fad971028755 mx/suite.py --- a/mx/suite.py Thu May 28 21:25:21 2015 +0200 +++ b/mx/suite.py Thu May 28 21:26:54 2015 +0200 @@ -326,15 +326,6 @@ "workingSets" : "Graal,HotSpot", }, - "com.oracle.graal.hotspot.sourcegen" : { - "subDir" : "graal", - "sourceDirs" : ["src"], - "dependencies" : ["com.oracle.graal.hotspot"], - "checkstyle" : "com.oracle.graal.graph", - "javaCompliance" : "1.8", - "workingSets" : "Graal,HotSpot", - }, - "com.oracle.graal.hotspot.jfr" : { "subDir" : "graal", "sourceDirs" : ["src"], @@ -403,6 +394,9 @@ "com.oracle.graal.options" : { "subDir" : "graal", "sourceDirs" : ["src"], + "dependencies" : [ + "com.oracle.graal.api.runtime", + ], "checkstyle" : "com.oracle.graal.graph", "javaCompliance" : "1.8", "workingSets" : "Graal", @@ -457,7 +451,6 @@ "com.oracle.graal.nodeinfo", "com.oracle.graal.compiler.common", "com.oracle.graal.api.collections", - "com.oracle.graal.api.runtime", "FINDBUGS", ], "javaCompliance" : "1.8", diff -r 54933d47cfa4 -r fad971028755 mxtool/mx.py --- a/mxtool/mx.py Thu May 28 21:25:21 2015 +0200 +++ b/mxtool/mx.py Thu May 28 21:26:54 2015 +0200 @@ -1681,7 +1681,7 @@ self.add_argument('--user-home', help='users home directory', metavar='', default=os.path.expanduser('~')) self.add_argument('--java-home', help='primary JDK directory (must be JDK 7 or later)', metavar='') self.add_argument('--extra-java-homes', help='secondary JDK directories separated by "' + os.pathsep + '"', metavar='') - self.add_argument('--strict-compliance', action='store_true', dest='strict_compliance', help='Projects of a certain compliance will only be built with a JDK of this exact compliance', default=False) + self.add_argument('--strict-compliance', action='store_true', dest='strict_compliance', help='Projects with an explicit compliance will only be built if a JDK exactly matching the compliance is available', default=False) self.add_argument('--ignore-project', action='append', dest='ignored_projects', help='name of project to ignore', metavar='', default=[]) self.add_argument('--kill-with-sigquit', action='store_true', dest='killwithsigquit', help='send sigquit first before killing child processes') if get_os() != 'windows': diff -r 54933d47cfa4 -r fad971028755 src/share/vm/classfile/systemDictionary.hpp --- a/src/share/vm/classfile/systemDictionary.hpp Thu May 28 21:25:21 2015 +0200 +++ b/src/share/vm/classfile/systemDictionary.hpp Thu May 28 21:26:54 2015 +0200 @@ -225,7 +225,6 @@ GRAAL_ONLY(do_klass(DebugInfo_klass, com_oracle_graal_api_code_DebugInfo, Graal)) \ GRAAL_ONLY(do_klass(RegisterSaveLayout_klass, com_oracle_graal_api_code_RegisterSaveLayout, Graal)) \ GRAAL_ONLY(do_klass(BytecodeFrame_klass, com_oracle_graal_api_code_BytecodeFrame, Graal)) \ - GRAAL_ONLY(do_klass(CompilationResult_klass, com_oracle_graal_api_code_CompilationResult, Graal)) \ GRAAL_ONLY(do_klass(CompilationResult_Call_klass, com_oracle_graal_api_code_CompilationResult_Call, Graal)) \ GRAAL_ONLY(do_klass(CompilationResult_ConstantReference_klass, com_oracle_graal_api_code_CompilationResult_ConstantReference, Graal)) \ GRAAL_ONLY(do_klass(CompilationResult_DataPatch_klass, com_oracle_graal_api_code_CompilationResult_DataPatch, Graal)) \ diff -r 54933d47cfa4 -r fad971028755 src/share/vm/classfile/vmSymbols.hpp --- a/src/share/vm/classfile/vmSymbols.hpp Thu May 28 21:25:21 2015 +0200 +++ b/src/share/vm/classfile/vmSymbols.hpp Thu May 28 21:26:54 2015 +0200 @@ -334,7 +334,6 @@ GRAAL_ONLY(template(com_oracle_graal_api_meta_Assumptions_NoFinalizableSubclass, "com/oracle/graal/api/meta/Assumptions$NoFinalizableSubclass")) \ GRAAL_ONLY(template(com_oracle_graal_api_meta_Assumptions_ConcreteMethod, "com/oracle/graal/api/meta/Assumptions$ConcreteMethod")) \ GRAAL_ONLY(template(com_oracle_graal_api_meta_Assumptions_CallSiteTargetValue,"com/oracle/graal/api/meta/Assumptions$CallSiteTargetValue")) \ - GRAAL_ONLY(template(com_oracle_graal_api_code_CompilationResult, "com/oracle/graal/api/code/CompilationResult")) \ GRAAL_ONLY(template(com_oracle_graal_api_code_CompilationResult_Call, "com/oracle/graal/api/code/CompilationResult$Call")) \ GRAAL_ONLY(template(com_oracle_graal_api_code_CompilationResult_ConstantReference, "com/oracle/graal/api/code/CompilationResult$ConstantReference")) \ GRAAL_ONLY(template(com_oracle_graal_api_code_CompilationResult_DataPatch, "com/oracle/graal/api/code/CompilationResult$DataPatch")) \ diff -r 54933d47cfa4 -r fad971028755 src/share/vm/graal/graalCodeInstaller.cpp --- a/src/share/vm/graal/graalCodeInstaller.cpp Thu May 28 21:25:21 2015 +0200 +++ b/src/share/vm/graal/graalCodeInstaller.cpp Thu May 28 21:26:54 2015 +0200 @@ -390,7 +390,7 @@ CompilerThread* compilerThread = thread->is_Compiler_thread() ? thread->as_CompilerThread() : NULL; _oop_recorder = new OopRecorder(&_arena, true); _dependencies = new Dependencies(&_arena, _oop_recorder, compilerThread != NULL ? compilerThread->log() : NULL); - objArrayHandle assumptions = CompilationResult::assumptions(HotSpotCompiledCode::comp(compiled_code)); + objArrayHandle assumptions = HotSpotCompiledCode::assumptions(compiled_code); if (!assumptions.is_null()) { int length = assumptions->length(); for (int i = 0; i < length; ++i) { @@ -413,7 +413,7 @@ } } } - objArrayHandle methods = CompilationResult::methods(HotSpotCompiledCode::comp(compiled_code)); + objArrayHandle methods = HotSpotCompiledCode::methods(compiled_code); if (!methods.is_null()) { int length = methods->length(); for (int i = 0; i < length; ++i) { @@ -483,7 +483,6 @@ } void CodeInstaller::initialize_fields(oop compiled_code) { - Handle comp_result = HotSpotCompiledCode::comp(compiled_code); if (compiled_code->is_a(HotSpotCompiledNmethod::klass())) { Handle hotspotJavaMethod = HotSpotCompiledNmethod::method(compiled_code); methodHandle method = getMethodFromHotSpotMethod(hotspotJavaMethod()); @@ -497,10 +496,10 @@ _sites_handle = JNIHandles::make_local(HotSpotCompiledCode::sites(compiled_code)); _exception_handlers_handle = JNIHandles::make_local(HotSpotCompiledCode::exceptionHandlers(compiled_code)); - _code_handle = JNIHandles::make_local(CompilationResult::targetCode(comp_result)); - _code_size = CompilationResult::targetCodeSize(comp_result); - _total_frame_size = CompilationResult::totalFrameSize(comp_result); - _custom_stack_area_offset = CompilationResult::customStackAreaOffset(comp_result); + _code_handle = JNIHandles::make_local(HotSpotCompiledCode::targetCode(compiled_code)); + _code_size = HotSpotCompiledCode::targetCodeSize(compiled_code); + _total_frame_size = HotSpotCompiledCode::totalFrameSize(compiled_code); + _custom_stack_area_offset = HotSpotCompiledCode::customStackAreaOffset(compiled_code); // Pre-calculate the constants section size. This is required for PC-relative addressing. _data_section_handle = JNIHandles::make_local(HotSpotCompiledCode::dataSection(compiled_code)); diff -r 54933d47cfa4 -r fad971028755 src/share/vm/graal/graalCompilerToVM.cpp --- a/src/share/vm/graal/graalCompilerToVM.cpp Thu May 28 21:25:21 2015 +0200 +++ b/src/share/vm/graal/graalCompilerToVM.cpp Thu May 28 21:26:54 2015 +0200 @@ -502,7 +502,6 @@ assert(installed_code_handle->is_a(InstalledCode::klass()), "wrong type"); InstalledCode::set_address(installed_code_handle, (jlong) cb); InstalledCode::set_version(installed_code_handle, InstalledCode::version(installed_code_handle) + 1); - oop comp_result = HotSpotCompiledCode::comp(compiled_code_handle); if (installed_code_handle->is_a(HotSpotInstalledCode::klass())) { HotSpotInstalledCode::set_size(installed_code_handle, cb->size()); HotSpotInstalledCode::set_codeStart(installed_code_handle, (jlong) cb->code_begin()); diff -r 54933d47cfa4 -r fad971028755 src/share/vm/graal/graalHashtable.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/vm/graal/graalHashtable.cpp Thu May 28 21:26:54 2015 +0200 @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include "graal/graalHashtable.hpp" + +template bool GraalHashtable::add(V value, bool replace) { + K key = get_key(value); + unsigned int hash = compute_hash(key); + unsigned int index = hash_to_index(hash); + for (GraalHashtableEntry* e = bucket(index); e != NULL; e = e->next()) { + if (key_equals(get_key(e->literal_addr()), key)) { + if (replace) { + e->set_literal(value); + } + return false; + } + } + GraalHashtableEntry* e = new GraalHashtableEntry(value); + e->set_next(_buckets[index]); + _buckets[index] = e; + ++_number_of_entries; + return true; +} + +template V* GraalHashtable::get(K key) { + unsigned int index = index_for(key); + for (GraalHashtableEntry* e = bucket(index); e != NULL; e = e->next()) { + if (key_equals(get_key(e->literal_addr()), key)) { + return e->literal_addr(); + } + } + return NULL; +} + +template void GraalHashtable::for_each(ValueClosure* closure) { + for (size_t i = 0; i < table_size(); ++i) { + for (GraalHashtableEntry* e = bucket(i); e != NULL && !closure->is_aborted(); e = e->next()) { + closure->do_value(e->literal_addr()); + } + } +} + +template GraalHashtable::~GraalHashtable() { + for (size_t i = 0; i < table_size(); ++i) { + GraalHashtableEntry* e = bucket(i); + while (e != NULL) { + GraalHashtableEntry* current = e; + e = e->next(); + delete current; + } + } + FREE_C_HEAP_ARRAY(GraalHashtableEntry*, _buckets, mtCompiler); +} + +// Instantiation +#include "graal/graalOptions.hpp" +template class GraalHashtable; +template class GraalHashtable; diff -r 54933d47cfa4 -r fad971028755 src/share/vm/graal/graalHashtable.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/vm/graal/graalHashtable.hpp Thu May 28 21:26:54 2015 +0200 @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#ifndef SHARE_VM_GRAAL_GRAAL_HASHTABLE_HPP +#define SHARE_VM_GRAAL_GRAAL_HASHTABLE_HPP + +#include "memory/allocation.hpp" +#include "memory/allocation.inline.hpp" + +// based on hashtable.hpp + +template class GraalHashtableEntry : public CHeapObj { + friend class VMStructs; +private: + T _literal; // ref to item in table. + GraalHashtableEntry* _next; // Link to next element in the linked list for this bucket + +public: + GraalHashtableEntry(T literal) : _literal(literal), _next(NULL) {} + + T literal() { + return _literal; + } + + void set_literal(T value) { + _literal = value; + } + + T* literal_addr() { + return &_literal; + } + + GraalHashtableEntry* next() const { + return _next; + } + + void set_next(GraalHashtableEntry* next) { + _next = next; + } +}; + +template +class ValueClosure : public StackObj { + bool _abort; +protected: + void abort() { _abort = true; } +public: + ValueClosure() : _abort(false) {} + virtual void do_value(V* value) = 0; + bool is_aborted() { return _abort; } +}; + +template class GraalHashtable : public CHeapObj { + friend class VMStructs; +private: + // Instance variables + unsigned int _table_size; + GraalHashtableEntry** _buckets; + unsigned int _number_of_entries; + +public: + GraalHashtable(size_t size) : _table_size(size), _number_of_entries(0) { + _buckets = NEW_C_HEAP_ARRAY(GraalHashtableEntry*, table_size(), mtCompiler); + for (size_t i = 0; i < table_size(); ++i) { + _buckets[i] = NULL; + } + } + virtual ~GraalHashtable(); + +private: + // Bucket handling + unsigned int hash_to_index(unsigned int full_hash) { + unsigned int h = full_hash % _table_size; + assert(h >= 0 && h < _table_size, "Illegal hash value"); + return h; + } + + unsigned int index_for(K key) { + return hash_to_index(compute_hash(key)); + } + + size_t entry_size() { + return sizeof(V); + } + + size_t table_size() { return _table_size; } + + GraalHashtableEntry* bucket(unsigned int index) { + return _buckets[index]; + } + + bool add(V v, bool replace); + +protected: + virtual unsigned int compute_hash(K key) = 0; + virtual bool key_equals(K k1, K k2) = 0; + virtual K get_key(V value) = 0; + virtual K get_key(V* value) = 0; + +public: + /** + * Tries to insert the value in the hash table. Returns false if an entry with the same key already exists. + * In this case it does *not* replace the existing entry. + */ + bool add(V v) { return add(v, false); } + /** + * Inserts the value in the hash table. Returns false if an entry with the same key already exists. + * In this case it replaces the existing entry. + */ + bool put(V v) { return add(v, true); } + V* get(K k); + void for_each(ValueClosure* closure); + int number_of_entries() { return _number_of_entries; } + +}; + +#endif // SHARE_VM_GRAAL_GRAAL_HASHTABLE_HPP diff -r 54933d47cfa4 -r fad971028755 src/share/vm/graal/graalJavaAccess.hpp --- a/src/share/vm/graal/graalJavaAccess.hpp Thu May 28 21:25:21 2015 +0200 +++ b/src/share/vm/graal/graalJavaAccess.hpp Thu May 28 21:26:54 2015 +0200 @@ -68,13 +68,18 @@ boolean_field(HotSpotNmethod, isDefault) \ end_class \ start_class(HotSpotCompiledCode) \ - oop_field(HotSpotCompiledCode, comp, "Lcom/oracle/graal/api/code/CompilationResult;") \ objArrayOop_field(HotSpotCompiledCode, sites, "[Lcom/oracle/graal/api/code/CompilationResult$Site;") \ objArrayOop_field(HotSpotCompiledCode, exceptionHandlers, "[Lcom/oracle/graal/api/code/CompilationResult$ExceptionHandler;") \ objArrayOop_field(HotSpotCompiledCode, comments, "[Lcom/oracle/graal/hotspot/HotSpotCompiledCode$Comment;") \ + objArrayOop_field(HotSpotCompiledCode, assumptions, "[Lcom/oracle/graal/api/meta/Assumptions$Assumption;") \ + typeArrayOop_field(HotSpotCompiledCode, targetCode, "[B") \ + int_field(HotSpotCompiledCode, targetCodeSize) \ typeArrayOop_field(HotSpotCompiledCode, dataSection, "[B") \ int_field(HotSpotCompiledCode, dataSectionAlignment) \ objArrayOop_field(HotSpotCompiledCode, dataSectionPatches, "[Lcom/oracle/graal/api/code/CompilationResult$DataPatch;") \ + int_field(HotSpotCompiledCode, totalFrameSize) \ + int_field(HotSpotCompiledCode, customStackAreaOffset) \ + objArrayOop_field(HotSpotCompiledCode, methods, "[Lcom/oracle/graal/api/meta/ResolvedJavaMethod;") \ end_class \ start_class(HotSpotCompiledCode_Comment) \ oop_field(HotSpotCompiledCode_Comment, text, "Ljava/lang/String;") \ @@ -93,14 +98,6 @@ start_class(HotSpotForeignCallLinkageImpl) \ long_field(HotSpotForeignCallLinkageImpl, address) \ end_class \ - start_class(CompilationResult) \ - int_field(CompilationResult, totalFrameSize) \ - int_field(CompilationResult, customStackAreaOffset) \ - typeArrayOop_field(CompilationResult, targetCode, "[B") \ - objArrayOop_field(CompilationResult, assumptions, "[Lcom/oracle/graal/api/meta/Assumptions$Assumption;") \ - objArrayOop_field(CompilationResult, methods, "[Lcom/oracle/graal/api/meta/ResolvedJavaMethod;") \ - int_field(CompilationResult, targetCodeSize) \ - end_class \ start_class(Assumptions_NoFinalizableSubclass) \ oop_field(Assumptions_NoFinalizableSubclass, receiverType, "Lcom/oracle/graal/api/meta/ResolvedJavaType;") \ end_class \ diff -r 54933d47cfa4 -r fad971028755 src/share/vm/graal/graalOptions.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/vm/graal/graalOptions.cpp Thu May 28 21:26:54 2015 +0200 @@ -0,0 +1,241 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include "precompiled.hpp" +#include "graal/graalOptions.hpp" +#include "graal/graalRuntime.hpp" +#include "runtime/arguments.hpp" +#include "utilities/hashtable.inline.hpp" + +class OptionsParseClosure : public ParseClosure { + OptionsTable* _table; +public: + OptionsParseClosure(OptionsTable* table) : _table(table) {} + void do_line(char* line) { + char* idx = strchr(line, '\t'); + if (idx == NULL) { + warn_and_abort("invalid format: could not find first tab"); + return; + } + *idx = '\0'; + char* name = line; + line = idx + 1; + idx = strchr(line, '\t'); + if (idx == NULL) { + warn_and_abort("invalid format: could not find second tab"); + return; + } + *idx = '\0'; + if (strlen(line) != 1) { + warn_and_abort("invalid format: type should be 1 char long"); + return; + } + char typeChar = *line; + line = idx + 1; + idx = strchr(line, '\t'); + if (idx == NULL) { + warn_and_abort("invalid format: could not find third tab"); + return; + } + *idx = '\0'; + char* help = line; + line = idx + 1; + idx = strchr(line, '\t'); + if (idx == NULL) { + warn_and_abort("invalid format: could not find fourth tab"); + return; + } + *idx = '\0'; + char* declaringClass = line; + line = idx + 1; + char* fieldClass = line; + OptionType type; + switch(typeChar) { + case 's': + type = _string; + break; + case 'i': + type = _int; + break; + case 'j': + type = _long; + break; + case 'f': + type = _float; + break; + case 'd': + type = _double; + break; + case 'z': + type = _boolean; + break; + default: + warn_and_abort("unkown type"); + return; + } + char* name2 = NEW_C_HEAP_ARRAY(char, (strlen(name) + 1 + strlen(help) + 1 + strlen(declaringClass) + 1 + strlen(fieldClass) + 1), mtCompiler); + char* help2 = name2 + strlen(name) + 1; + char* declaringClass2 = help2 + strlen(help) + 1; + char* fieldClass2 = declaringClass2 + strlen(declaringClass) + 1; + strcpy(name2, name); + strcpy(help2, help); + strcpy(declaringClass2, declaringClass); + strcpy(fieldClass2, fieldClass); + OptionDesc desc = {name2, help2, type, declaringClass2, fieldClass2}; + if (!_table->add(desc)) { + warn_and_abort("duplicate option"); + return; + } + } +}; + +class FreeNamesClosure : public ValueClosure { + void do_value(OptionDesc* desc) { + FREE_C_HEAP_ARRAY(char, desc->name, mtCompiler); + } +}; + +OptionsTable::~OptionsTable() { + FreeNamesClosure closure; + for_each(&closure); +} + +OptionsTable* OptionsTable::load_options() { + OptionsTable* table = new OptionsTable(); + // Add PrintFlags option manually + OptionDesc printFlagsDesc; + printFlagsDesc.name = PRINT_FLAGS_ARG; + printFlagsDesc.type = _boolean; + printFlagsDesc.help = PRINT_FLAGS_HELP; + printFlagsDesc.declaringClass = NULL; + printFlagsDesc.fieldClass = NULL; + table->add(printFlagsDesc); + + char optionsDir[JVM_MAXPATHLEN]; + const char* fileSep = os::file_separator(); + jio_snprintf(optionsDir, sizeof(optionsDir), "%s%slib%sgraal%soptions", + Arguments::get_java_home(), fileSep, fileSep, fileSep); + DIR* dir = os::opendir(optionsDir); + if (dir != NULL) { + struct dirent *entry; + char *dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(optionsDir), mtInternal); + OptionsParseClosure closure(table); + while ((entry = os::readdir(dir, (dirent *) dbuf)) != NULL && !closure.is_aborted()) { + const char* name = entry->d_name; + char optionFilePath[JVM_MAXPATHLEN]; + jio_snprintf(optionFilePath, sizeof(optionFilePath), "%s%s%s",optionsDir, fileSep, name); + GraalRuntime::parse_lines(optionFilePath, &closure, false); + } + FREE_C_HEAP_ARRAY(char, dbuf, mtInternal); + os::closedir(dir); + if (closure.is_aborted()) { + delete table; + return NULL; + } + return table; + } + // TODO(gd) should this be silent? + warning("Could not open graal options directory (%s)",optionsDir); + return table; +} + +OptionDesc* OptionsTable::get(const char* name, size_t arglen) { + char nameOnly[256]; + guarantee(arglen < 256, "Max supported option name len is 256"); + strncpy(nameOnly, name, arglen); + nameOnly[arglen] = '\0'; + return GraalHashtable::get(nameOnly); +} + +// Compute string similarity based on Dice's coefficient +static float str_similar(const char* str1, const char* str2) { + size_t len1 = strlen(str1); + size_t len2 = strlen(str2); + + if (len1 == 0 || len2 == 0) { + return 0; + } + + int hits = 0; + for (size_t i = 0; i < len1 - 1; ++i) { + for (size_t j = 0; j < len2 -1; ++j) { + if ((str1[i] == str2[j]) && (str1[i+1] == str2[j+1])) { + ++hits; + break; + } + } + } + + size_t total = len1 + len2; + return 2.0f * (float) hits / (float) total; +} + +float VMOptionsFuzzyMatchSimilarity = 0.7f; + +class FuzzyMatchClosure : public ValueClosure { + OptionDesc* _match; + float _max_score; + const char* _name; +public: + FuzzyMatchClosure(const char* name) : _name(name), _match(NULL), _max_score(-1) {} + void do_value(OptionDesc* value) { + float score = str_similar(value->name, _name); + if (score > VMOptionsFuzzyMatchSimilarity && score > _max_score) { + _max_score = score; + _match = value; + } + } + OptionDesc* get_match() { + return _match; + } +}; + +OptionDesc * OptionsTable::fuzzy_match(const char* name, size_t length) { + FuzzyMatchClosure closure(name); + for_each(&closure); + return closure.get_match(); +} + +class FreeStringsClosure : public ValueClosure { + void do_value(OptionValue* value) { + if (value->desc.type == _string) { + FREE_C_HEAP_ARRAY(char, value->string_value, mtCompiler); + } + } +}; + +OptionsValueTable::~OptionsValueTable() { + FreeStringsClosure closure; + for_each(&closure); + delete _table; +} + + + +OptionValue* OptionsValueTable::get(const char* name, size_t arglen) { + char nameOnly[256]; + guarantee(arglen < 256, "Max supported option name len is 256"); + strncpy(nameOnly, name, arglen); + nameOnly[arglen] = '\0'; + return GraalHashtable::get(nameOnly); +} diff -r 54933d47cfa4 -r fad971028755 src/share/vm/graal/graalOptions.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/vm/graal/graalOptions.hpp Thu May 28 21:26:54 2015 +0200 @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#ifndef SHARE_VM_GRAAL_GRAAL_OPTIONS_HPP +#define SHARE_VM_GRAAL_GRAAL_OPTIONS_HPP + +#include "memory/allocation.hpp" +#include "utilities/exceptions.hpp" +#include "graal/graalHashtable.hpp" + +#define PRINT_FLAGS_ARG "PrintFlags" +#define PRINT_FLAGS_HELP "Prints all Graal flags (similar to XX's PrintFlagsFinal)" + +enum OptionType { + _string, + _int, + _long, + _float, + _double, + _boolean +}; + +struct OptionDesc { + const char* name; + const char* help; + OptionType type; + const char* declaringClass; + const char* fieldClass; +}; + +inline unsigned int compute_string_hash(const char *s, int n) { + unsigned int val = 0; + while (--n >= 0) { + val = *s++ + 31 * val; + } + return val; +} + +class OptionsTable : public GraalHashtable { +protected: + unsigned int compute_hash(const char* key) { return compute_string_hash(key, strlen(key)); } + bool key_equals(const char* k1, const char* k2) { return strcmp(k1, k2) == 0; } + const char* get_key(OptionDesc value) { return value.name; } ; + const char* get_key(OptionDesc* value) { return value->name; } ; +public: + OptionsTable() : GraalHashtable(100) {} + ~OptionsTable(); + using GraalHashtable::get; + OptionDesc* get(const char* name, size_t arglen); + OptionDesc * fuzzy_match(const char* name, size_t length); + + static OptionsTable* load_options(); +}; + +struct OptionValue { + OptionDesc desc; + union { + const char* string_value; + jint int_value; + jlong long_value; + jfloat float_value; + jdouble double_value; + jboolean boolean_value; + }; +}; + +class OptionsValueTable : public GraalHashtable { + OptionsTable* _table; +protected: + unsigned int compute_hash(const char* key) { return compute_string_hash(key, strlen(key)); } + bool key_equals(const char* k1, const char* k2) { return strcmp(k1, k2) == 0; } + const char* get_key(OptionValue value) { return value.desc.name; } ; + const char* get_key(OptionValue* value) { return value->desc.name; } ; +public: + OptionsValueTable(OptionsTable* table) : _table(table), GraalHashtable(100) {} + ~OptionsValueTable(); + using GraalHashtable::get; + OptionValue* get(const char* name, size_t arglen); + OptionsTable* options_table() { return _table; } +}; + + +#endif // SHARE_VM_GRAAL_GRAAL_OPTIONS_HPP diff -r 54933d47cfa4 -r fad971028755 src/share/vm/graal/graalRuntime.cpp --- a/src/share/vm/graal/graalRuntime.cpp Thu May 28 21:25:21 2015 +0200 +++ b/src/share/vm/graal/graalRuntime.cpp Thu May 28 21:26:54 2015 +0200 @@ -37,6 +37,7 @@ #include "runtime/arguments.hpp" #include "runtime/reflection.hpp" #include "utilities/debug.hpp" +#include "utilities/defaultStream.hpp" jobject GraalRuntime::_HotSpotGraalRuntime_instance = NULL; bool GraalRuntime::_HotSpotGraalRuntime_initialized = false; @@ -625,6 +626,11 @@ SystemDictionary::initialize_wk_klasses_through(SystemDictionary::LAST_GRAAL_WKID, scan, CHECK); JVM_END +// boolean com.oracle.graal.hotspot.HotSpotOptions.isCITimingEnabled() +JVM_ENTRY(jboolean, JVM_IsCITimingEnabled(JNIEnv *env, jclass c)) + return CITime || CITimeEach; +JVM_END + // private static GraalRuntime Graal.initializeRuntime() JVM_ENTRY(jobject, JVM_GetGraalRuntime(JNIEnv *env, jclass c)) GraalRuntime::initialize_HotSpotGraalRuntime(); @@ -665,26 +671,9 @@ return JNIHandles::make_local(THREAD, (oop) result.get_jobject()); JVM_END -void GraalRuntime::check_generated_sources_sha1(TRAPS) { - TempNewSymbol name = SymbolTable::new_symbol("com/oracle/graal/hotspot/sourcegen/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::callInitializer(const char* className, const char* methodName, const char* returnType) { guarantee(!_HotSpotGraalRuntime_initialized, "cannot reinitialize HotSpotGraalRuntime"); Thread* THREAD = Thread::current(); - check_generated_sources_sha1(CHECK_ABORT_(Handle())); TempNewSymbol name = SymbolTable::new_symbol(className, CHECK_ABORT_(Handle())); KlassHandle klass = load_required_class(name); @@ -725,14 +714,6 @@ GraalRuntime::initialize_natives(env, c2vmClass); JVM_END -// private static void HotSpotOptions.parseVMOptions() -JVM_ENTRY(void, JVM_ParseGraalOptions(JNIEnv *env, jclass c)) - HandleMark hm; - KlassHandle hotSpotOptionsClass(THREAD, java_lang_Class::as_Klass(JNIHandles::resolve_non_null(c))); - GraalRuntime::parse_arguments(hotSpotOptionsClass, CHECK); -JVM_END - - void GraalRuntime::ensure_graal_class_loader_is_initialized() { // This initialization code is guarded by a static pointer to the Factory class. // Once it is non-null, the Graal class loader and well known Graal classes are @@ -771,235 +752,316 @@ *((jboolean *) addr) = (jboolean) UseGraalClassLoader; klass->initialize(CHECK_ABORT); _FactoryKlass = klass(); + assert(!UseGraalClassLoader || SystemDictionary::graal_loader() != NULL, "Graal classloader should have been initialized"); } } -jint GraalRuntime::check_arguments(TRAPS) { - KlassHandle nullHandle; - parse_arguments(nullHandle, THREAD); - if (HAS_PENDING_EXCEPTION) { - // Errors in parsing Graal arguments cause exceptions. - // We now load and initialize HotSpotOptions which in turn - // causes argument parsing to be redone with better error messages. - CLEAR_PENDING_EXCEPTION; - TempNewSymbol name = SymbolTable::new_symbol("Lcom/oracle/graal/hotspot/HotSpotOptions;", CHECK_ABORT_(JNI_ERR)); - instanceKlassHandle hotSpotOptionsClass = resolve_or_fail(name, CHECK_ABORT_(JNI_ERR)); - - parse_arguments(hotSpotOptionsClass, THREAD); - assert(HAS_PENDING_EXCEPTION, "must be"); +OptionsValueTable* GraalRuntime::parse_arguments() { + OptionsTable* table = OptionsTable::load_options(); + if (table == NULL) { + return NULL; + } - ResourceMark rm; - Handle exception = PENDING_EXCEPTION; - CLEAR_PENDING_EXCEPTION; - oop message = java_lang_Throwable::message(exception); - if (message != NULL) { - tty->print_cr("Error parsing Graal options: %s", java_lang_String::as_utf8_string(message)); - } else { - call_printStackTrace(exception, THREAD); - } - return JNI_ERR; - } - return JNI_OK; -} - -void GraalRuntime::parse_arguments(KlassHandle hotSpotOptionsClass, TRAPS) { - ResourceMark rm(THREAD); + OptionsValueTable* options = new OptionsValueTable(table); // Process option overrides from graal.options first - parse_graal_options_file(hotSpotOptionsClass, CHECK); + parse_graal_options_file(options); // Now process options on the command line int numOptions = Arguments::num_graal_args(); for (int i = 0; i < numOptions; i++) { char* arg = Arguments::graal_args_array()[i]; - parse_argument(hotSpotOptionsClass, arg, CHECK); + if (!parse_argument(options, arg)) { + delete options; + return NULL; + } } + return options; } -void GraalRuntime::check_required_value(const char* name, size_t name_len, const char* value, TRAPS) { - if (value == NULL) { - char buf[200]; - jio_snprintf(buf, sizeof(buf), "Must use '-G:%.*s=' format for %.*s option", name_len, name, name_len, name); - THROW_MSG(vmSymbols::java_lang_InternalError(), buf); +void not_found(OptionsTable* table, const char* argname, size_t namelen) { + jio_fprintf(defaultStream::error_stream(),"Unrecognized VM option '%.*s'\n", namelen, argname); + OptionDesc* fuzzy_matched = table->fuzzy_match(argname, strlen(argname)); + if (fuzzy_matched != NULL) { + jio_fprintf(defaultStream::error_stream(), + "Did you mean '%s%s%s'?\n", + (fuzzy_matched->type == _boolean) ? "(+/-)" : "", + fuzzy_matched->name, + (fuzzy_matched->type == _boolean) ? "" : "="); } } -void GraalRuntime::parse_argument(KlassHandle hotSpotOptionsClass, char* arg, TRAPS) { - ensure_graal_class_loader_is_initialized(); +bool GraalRuntime::parse_argument(OptionsValueTable* options, const char* arg) { + OptionsTable* table = options->options_table(); char first = arg[0]; - char* name; + const char* name; size_t name_len; - bool recognized = true; if (first == '+' || first == '-') { name = arg + 1; - name_len = strlen(name); - recognized = set_option_bool(hotSpotOptionsClass, name, name_len, first, CHECK); + OptionDesc* optionDesc = table->get(name); + if (optionDesc == NULL) { + not_found(table, name, strlen(name)); + return false; + } + if (optionDesc->type != _boolean) { + jio_fprintf(defaultStream::error_stream(), "Unexpected +/- setting in VM option '%s'\n", name); + return false; + } + OptionValue value; + value.desc = *optionDesc; + value.boolean_value = first == '+'; + options->put(value); + return true; } else { - char* sep = strchr(arg, '='); + const char* sep = strchr(arg, '='); name = arg; - char* value = NULL; + const char* value = NULL; if (sep != NULL) { name_len = sep - name; value = sep + 1; } else { name_len = strlen(name); } - recognized = set_option(hotSpotOptionsClass, name, name_len, value, CHECK); - } - - if (!recognized) { - bool throw_err = hotSpotOptionsClass.is_null(); - if (!hotSpotOptionsClass.is_null()) { - set_option_helper(hotSpotOptionsClass, name, name_len, Handle(), ' ', Handle(), 0L); - if (!HAS_PENDING_EXCEPTION) { - throw_err = true; - } + OptionDesc* optionDesc = table->get(name, name_len); + if (optionDesc == NULL) { + not_found(table, name, name_len); + return false; } - - if (throw_err) { - char buf[200]; - jio_snprintf(buf, sizeof(buf), "Unrecognized Graal option %.*s", name_len, name); - THROW_MSG(vmSymbols::java_lang_InternalError(), buf); + if (optionDesc->type == _boolean) { + jio_fprintf(defaultStream::error_stream(), "Missing +/- setting for VM option '%s'\n", name); + return false; + } + if (value == NULL) { + jio_fprintf(defaultStream::error_stream(), "Must use '-G:%.*s=' format for %.*s option", name_len, name, name_len, name); + return false; } - } -} - -void GraalRuntime::parse_graal_options_file(KlassHandle hotSpotOptionsClass, TRAPS) { - const char* home = Arguments::get_java_home(); - size_t path_len = strlen(home) + strlen("/lib/graal.options") + 1; - char* path = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, path_len); - char sep = os::file_separator()[0]; - sprintf(path, "%s%clib%cgraal.options", home, sep, sep); - - struct stat st; - if (os::stat(path, &st) == 0) { - int file_handle = os::open(path, 0, 0); - if (file_handle != -1) { - char* buffer = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, st.st_size); - int num_read = (int) os::read(file_handle, (char*) buffer, st.st_size); - if (num_read == -1) { - warning("Error reading file %s due to %s", path, strerror(errno)); - } else if (num_read != st.st_size) { - warning("Only read %d of " SIZE_FORMAT " bytes from %s", num_read, (size_t) st.st_size, path); + OptionValue optionValue; + optionValue.desc = *optionDesc; + char* check; + errno = 0; + switch(optionDesc->type) { + case _int: { + long int int_value = ::strtol(value, &check, 10); + if (*check != '\0' || errno == ERANGE || int_value > max_jint || int_value < min_jint) { + jio_fprintf(defaultStream::error_stream(), "Expected int value for VM option '%s'\n", name); + return false; + } + optionValue.int_value = int_value; + break; + } + case _long: { + long long int long_value = ::strtoll(value, &check, 10); + if (*check != '\0' || errno == ERANGE || long_value > max_jlong || long_value < min_jlong) { + jio_fprintf(defaultStream::error_stream(), "Expected long value for VM option '%s'\n", name); + return false; + } + optionValue.long_value = long_value; + break; } - os::close(file_handle); - if (num_read == st.st_size) { - char* line = buffer; - int lineNo = 1; - while (line - buffer < num_read) { - char* nl = strchr(line, '\n'); - if (nl != NULL) { - *nl = '\0'; - } - parse_argument(hotSpotOptionsClass, line, THREAD); - if (HAS_PENDING_EXCEPTION) { - warning("Error in %s:%d", path, lineNo); - return; - } - if (nl != NULL) { - line = nl + 1; - lineNo++; - } else { - // File without newline at the end - break; - } + case _float: { + optionValue.float_value = ::strtof(value, &check); + if (*check != '\0' || errno == ERANGE) { + jio_fprintf(defaultStream::error_stream(), "Expected float value for VM option '%s'\n", name); + return false; + } + break; + } + case _double: { + optionValue.double_value = ::strtod(value, &check); + if (*check != '\0' || errno == ERANGE) { + jio_fprintf(defaultStream::error_stream(), "Expected double value for VM option '%s'\n", name); + return false; } + break; } - } else { - warning("Error opening file %s due to %s", path, strerror(errno)); + case _string: { + char* copy = NEW_C_HEAP_ARRAY(char, strlen(value) + 1, mtCompiler); + strcpy(copy, value); + optionValue.string_value = copy; + break; + } + default: + ShouldNotReachHere(); } + options->put(optionValue); + return true; } } -jlong GraalRuntime::parse_primitive_option_value(char spec, const char* name, size_t name_len, const char* value, TRAPS) { - check_required_value(name, name_len, value, CHECK_(0L)); - union { - jint i; - jlong l; - double d; - } uu; - uu.l = 0L; - char dummy; - switch (spec) { - case 'd': - case 'f': { - if (sscanf(value, "%lf%c", &uu.d, &dummy) == 1) { - return uu.l; - } - break; +class GraalOptionParseClosure : public ParseClosure { + OptionsValueTable* _options; +public: + GraalOptionParseClosure(OptionsValueTable* options) : _options(options) {} + void do_line(char* line) { + if (!GraalRuntime::parse_argument(_options, line)) { + warn("There was an error parsing an argument. Skipping it."); } - case 'i': { - if (sscanf(value, "%d%c", &uu.i, &dummy) == 1) { - return (jlong)uu.i; - } - break; - } - default: - ShouldNotReachHere(); } - ResourceMark rm(THREAD); - char buf[200]; - bool missing = strlen(value) == 0; - if (missing) { - jio_snprintf(buf, sizeof(buf), "Missing %s value for Graal option %.*s", (spec == 'i' ? "numeric" : "float/double"), name_len, name); - } else { - jio_snprintf(buf, sizeof(buf), "Invalid %s value for Graal option %.*s: %s", (spec == 'i' ? "numeric" : "float/double"), name_len, name, value); - } - THROW_MSG_(vmSymbols::java_lang_InternalError(), buf, 0L); +}; + +void GraalRuntime::parse_graal_options_file(OptionsValueTable* options) { + const char* home = Arguments::get_java_home(); + size_t path_len = strlen(home) + strlen("/lib/graal.options") + 1; + char path[JVM_MAXPATHLEN]; + char sep = os::file_separator()[0]; + jio_snprintf(path, JVM_MAXPATHLEN, "%s%clib%cgraal.options", home, sep, sep); + GraalOptionParseClosure closure(options); + parse_lines(path, &closure, false); } -void GraalRuntime::set_option_helper(KlassHandle hotSpotOptionsClass, char* name, size_t name_len, Handle option, jchar spec, Handle stringValue, jlong primitiveValue) { - Thread* THREAD = Thread::current(); - Handle name_handle; - if (name != NULL) { - if (strlen(name) > name_len) { - // Temporarily replace '=' with NULL to create the Java string for the option name - char save = name[name_len]; - name[name_len] = '\0'; - name_handle = java_lang_String::create_from_str(name, THREAD); - name[name_len] = '='; - if (HAS_PENDING_EXCEPTION) { - return; +#define CHECK_WARN_ABORT_(message) THREAD); \ + if (HAS_PENDING_EXCEPTION) { \ + warning(message); \ + char buf[512]; \ + jio_snprintf(buf, 512, "Uncaught exception at %s:%d", __FILE__, __LINE__); \ + GraalRuntime::abort_on_pending_exception(PENDING_EXCEPTION, buf); \ + return; \ + } \ + (void)(0 + +class SetOptionClosure : public ValueClosure { + Thread* _thread; +public: + SetOptionClosure(TRAPS) : _thread(THREAD) {} + void do_value(OptionValue* optionValue) { + TRAPS = _thread; + const char* declaringClass = optionValue->desc.declaringClass; + if (declaringClass == NULL) { + // skip PrintFlags pseudo-option + return; + } + const char* fieldName = optionValue->desc.name; + const char* fieldClass = optionValue->desc.fieldClass; + + size_t fieldSigLen = 2 + strlen(fieldClass); + char* fieldSig = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, fieldSigLen + 1); + jio_snprintf(fieldSig, fieldSigLen + 1, "L%s;", fieldClass); + for (size_t i = 0; i < fieldSigLen; ++i) { + if (fieldSig[i] == '.') { + fieldSig[i] = '/'; + } + } + fieldSig[fieldSigLen] = '\0'; + size_t declaringClassLen = strlen(declaringClass); + char* declaringClassBinary = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, declaringClassLen + 1); + for (size_t i = 0; i < declaringClassLen; ++i) { + if (declaringClass[i] == '.') { + declaringClassBinary[i] = '/'; + } else { + declaringClassBinary[i] = declaringClass[i]; } - } else { - assert(strlen(name) == name_len, "must be"); - name_handle = java_lang_String::create_from_str(name, CHECK); + } + declaringClassBinary[declaringClassLen] = '\0'; + + TempNewSymbol name = SymbolTable::new_symbol(declaringClassBinary, CHECK_WARN_ABORT_("Declaring class could not be found")); + Klass* klass = GraalRuntime::resolve_or_null(name, CHECK_WARN_ABORT_("Declaring class could not be resolved")); + + if (klass == NULL) { + warning("Declaring class for option %s could not be resolved", declaringClass); + abort(); + return; + } + + // The class has been loaded so the field and signature should already be in the symbol + // table. If they're not there, the field doesn't exist. + TempNewSymbol fieldname = SymbolTable::probe(fieldName, (int)strlen(fieldName)); + TempNewSymbol signame = SymbolTable::probe(fieldSig, (int)fieldSigLen); + if (fieldname == NULL || signame == NULL) { + warning("Symbols for field for option %s not found (in %s)", fieldName, declaringClass); + abort(); + return; + } + // Make sure class is initialized before handing id's out to fields + klass->initialize(CHECK_WARN_ABORT_("Error while initializing declaring class for option")); + + fieldDescriptor fd; + if (!InstanceKlass::cast(klass)->find_field(fieldname, signame, true, &fd)) { + warning("Field for option %s not found (in %s)", fieldName, declaringClass); + abort(); + return; + } + oop value; + switch(optionValue->desc.type) { + case _boolean: { + jvalue jv; + jv.z = optionValue->boolean_value; + value = java_lang_boxing_object::create(T_BOOLEAN, &jv, THREAD); + break; + } + case _int: { + jvalue jv; + jv.i = optionValue->int_value; + value = java_lang_boxing_object::create(T_INT, &jv, THREAD); + break; + } + case _long: { + jvalue jv; + jv.j = optionValue->long_value; + value = java_lang_boxing_object::create(T_LONG, &jv, THREAD); + break; + } + case _float: { + jvalue jv; + jv.f = optionValue->float_value; + value = java_lang_boxing_object::create(T_FLOAT, &jv, THREAD); + break; + } + case _double: { + jvalue jv; + jv.d = optionValue->double_value; + value = java_lang_boxing_object::create(T_DOUBLE, &jv, THREAD); + break; + } + case _string: + value = java_lang_String::create_from_str(optionValue->string_value, THREAD)(); + break; + default: + ShouldNotReachHere(); + } + + oop optionValueOop = klass->java_mirror()->obj_field(fd.offset()); + + if (optionValueOop == NULL) { + warning("Option field was null, can not set %s", fieldName); + abort(); + return; + } + + if (!InstanceKlass::cast(optionValueOop->klass())->find_field(vmSymbols::value_name(), vmSymbols::object_signature(), false, &fd)) { + warning("'Object value' field not found in option class %s, can not set option %s", fieldClass, fieldName); + abort(); + return; + } + + optionValueOop->obj_field_put(fd.offset(), value); + } +}; + +void GraalRuntime::set_options(OptionsValueTable* options, TRAPS) { + ensure_graal_class_loader_is_initialized(); + { + ResourceMark rm; + SetOptionClosure closure(THREAD); + options->for_each(&closure); + if (closure.is_aborted()) { + vm_abort(false); } } + OptionValue* printFlags = options->get(PRINT_FLAGS_ARG); + if (printFlags != NULL && printFlags->boolean_value) { + print_flags_helper(CHECK_ABORT); + } +} - TempNewSymbol setOption = SymbolTable::new_symbol("setOption", CHECK); - TempNewSymbol sig = SymbolTable::new_symbol("(Ljava/lang/String;Lcom/oracle/graal/options/OptionValue;CLjava/lang/String;J)V", CHECK); +void GraalRuntime::print_flags_helper(TRAPS) { + // TODO(gd) write this in C++? + HandleMark hm(THREAD); + TempNewSymbol name = SymbolTable::new_symbol("com/oracle/graal/hotspot/HotSpotOptions", CHECK_ABORT); + KlassHandle hotSpotOptionsClass = load_required_class(name); + TempNewSymbol setOption = SymbolTable::new_symbol("printFlags", CHECK); JavaValue result(T_VOID); JavaCallArguments args; - args.push_oop(name_handle()); - args.push_oop(option()); - args.push_int(spec); - args.push_oop(stringValue()); - args.push_long(primitiveValue); - JavaCalls::call_static(&result, hotSpotOptionsClass, setOption, sig, &args, CHECK); -} - -Handle GraalRuntime::get_OptionValue(const char* declaringClass, const char* fieldName, const char* fieldSig, TRAPS) { - TempNewSymbol name = SymbolTable::new_symbol(declaringClass, CHECK_NH); - Klass* klass = resolve_or_fail(name, CHECK_NH); - - // The class has been loaded so the field and signature should already be in the symbol - // table. If they're not there, the field doesn't exist. - TempNewSymbol fieldname = SymbolTable::probe(fieldName, (int)strlen(fieldName)); - TempNewSymbol signame = SymbolTable::probe(fieldSig, (int)strlen(fieldSig)); - if (fieldname == NULL || signame == NULL) { - THROW_MSG_(vmSymbols::java_lang_NoSuchFieldError(), (char*) fieldName, Handle()); - } - // Make sure class is initialized before handing id's out to fields - klass->initialize(CHECK_NH); - - fieldDescriptor fd; - if (!InstanceKlass::cast(klass)->find_field(fieldname, signame, true, &fd)) { - THROW_MSG_(vmSymbols::java_lang_NoSuchFieldError(), (char*) fieldName, Handle()); - } - - Handle ret = klass->java_mirror()->obj_field(fd.offset()); - return ret; + JavaCalls::call_static(&result, hotSpotOptionsClass, setOption, vmSymbols::void_method_signature(), &args, CHECK); } Handle GraalRuntime::create_Service(const char* name, TRAPS) { @@ -1074,18 +1136,12 @@ return klass; } -Handle GraalRuntime::get_service_impls(KlassHandle serviceKlass, TRAPS) { - const char* home = Arguments::get_java_home(); - const char* serviceName = serviceKlass->external_name(); - size_t path_len = strlen(home) + strlen("/lib/graal/services/") + strlen(serviceName) + 1; - char* path = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, path_len); - char sep = os::file_separator()[0]; - sprintf(path, "%s%clib%cgraal%cservices%c%s", home, sep, sep, sep, sep, serviceName); +void GraalRuntime::parse_lines(char* path, ParseClosure* closure, bool warnStatFailure) { struct stat st; - if (os::stat(path, &st) == 0) { + if (os::stat(path, &st) == 0 && (st.st_mode & S_IFREG) == S_IFREG) { // exists & is regular file int file_handle = os::open(path, 0, 0); if (file_handle != -1) { - char* buffer = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, st.st_size + 1); + char* buffer = NEW_C_HEAP_ARRAY(char, st.st_size + 1, mtInternal); int num_read = (int) os::read(file_handle, (char*) buffer, st.st_size); if (num_read == -1) { warning("Error reading file %s due to %s", path, strerror(errno)); @@ -1093,11 +1149,12 @@ warning("Only read %d of " SIZE_FORMAT " bytes from %s", num_read, (size_t) st.st_size, path); } os::close(file_handle); + closure->set_filename(path); if (num_read == st.st_size) { buffer[num_read] = '\0'; - GrowableArray* implNames = new GrowableArray(); + char* line = buffer; - while (line - buffer < num_read) { + while (line - buffer < num_read && !closure->is_aborted()) { // find line end (\r, \n or \r\n) char* nextline = NULL; char* cr = strchr(line, '\r'); @@ -1125,13 +1182,7 @@ *end = '\0'; // skip comments and empty lines if (*line != '#' && strlen(line) > 0) { - // Turn all '.'s into '/'s - for (size_t index = 0; line[index] != '\0'; index++) { - if (line[index] == '.') { - line[index] = '/'; - } - } - implNames->append(line); + closure->parse_line(line); } if (nextline != NULL) { line = nextline; @@ -1140,23 +1191,55 @@ break; } } - - objArrayOop servicesOop = oopFactory::new_objArray(serviceKlass(), implNames->length(), CHECK_NH); - objArrayHandle services(THREAD, servicesOop); - for (int i = 0; i < implNames->length(); ++i) { - char* implName = implNames->at(i); - Handle service = create_Service(implName, CHECK_NH); - services->obj_at_put(i, service()); - } - return services; } + FREE_C_HEAP_ARRAY(char, buffer, mtInternal); } else { warning("Error opening file %s due to %s", path, strerror(errno)); } - } else { - warning("Error opening file %s due to %s", path, strerror(errno)); + } else if (warnStatFailure) { + warning("Could not stat file %s due to %s", path, strerror(errno)); } - return Handle(); } -#include "graalRuntime.inline.hpp" +class ServiceParseClosure : public ParseClosure { + GrowableArray _implNames; +public: + ServiceParseClosure() : _implNames() {} + void do_line(char* line) { + size_t lineLen = strlen(line); + char* implName = NEW_C_HEAP_ARRAY(char, lineLen + 1, mtCompiler); // TODO (gd) i'm leaking + // Turn all '.'s into '/'s + for (size_t index = 0; index < lineLen; ++index) { + if (line[index] == '.') { + implName[index] = '/'; + } else { + implName[index] = line[index]; + } + } + implName[lineLen] = '\0'; + _implNames.append(implName); + } + GrowableArray* implNames() {return &_implNames;} +}; + + +Handle GraalRuntime::get_service_impls(KlassHandle serviceKlass, TRAPS) { + const char* home = Arguments::get_java_home(); + const char* serviceName = serviceKlass->external_name(); + size_t path_len = strlen(home) + strlen("/lib/graal/services/") + strlen(serviceName) + 1; + char* path = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, path_len); + char sep = os::file_separator()[0]; + sprintf(path, "%s%clib%cgraal%cservices%c%s", home, sep, sep, sep, sep, serviceName); + ServiceParseClosure closure; + parse_lines(path, &closure, true); // TODO(gd) cache parsing results? + + GrowableArray* implNames = closure.implNames(); + objArrayOop servicesOop = oopFactory::new_objArray(serviceKlass(), implNames->length(), CHECK_NH); + objArrayHandle services(THREAD, servicesOop); + for (int i = 0; i < implNames->length(); ++i) { + char* implName = implNames->at(i); + Handle service = create_Service(implName, CHECK_NH); + services->obj_at_put(i, service()); + } + return services; +} diff -r 54933d47cfa4 -r fad971028755 src/share/vm/graal/graalRuntime.hpp --- a/src/share/vm/graal/graalRuntime.hpp Thu May 28 21:25:21 2015 +0200 +++ b/src/share/vm/graal/graalRuntime.hpp Thu May 28 21:26:54 2015 +0200 @@ -27,91 +27,49 @@ #include "interpreter/interpreter.hpp" #include "memory/allocation.hpp" #include "runtime/deoptimization.hpp" +#include "graal/graalOptions.hpp" + +class ParseClosure : public StackObj { + int _lineNo; + char* _filename; + bool _abort; +protected: + void abort() { _abort = true; } + void warn_and_abort(const char* message) { + warn(message); + abort(); + } + void warn(const char* message) { + warning("Error at line %d while parsing %s: %s", _lineNo, _filename == NULL ? "?" : _filename, message); + } + public: + ParseClosure() : _lineNo(0), _filename(NULL), _abort(false) {} + void parse_line(char* line) { + _lineNo++; + do_line(line); + } + virtual void do_line(char* line) = 0; + int lineNo() { return _lineNo; } + bool is_aborted() { return _abort; } + void set_filename(char* path) {_filename = path; _lineNo = 0;} +}; class GraalRuntime: public CHeapObj { private: - static jobject _HotSpotGraalRuntime_instance; static bool _HotSpotGraalRuntime_initialized; - static const char* _generated_sources_sha1; static bool _shutdown_called; /** - * Reads the OptionValue object from a specified static field. - * - * @throws LinkageError if the field could not be resolved - */ - static Handle get_OptionValue(const char* declaringClass, const char* fieldName, const char* fieldSig, TRAPS); - - /** - * Parses the string form of a numeric, float or double option into a jlong (using raw bits for floats/doubles). - * - * @param spec 'i', 'f' or 'd' (see HotSpotOptions.setOption()) - * @param name option name - * @param name_len length of option name - * @param value string value to parse - * @throws InternalError if value could not be parsed according to spec - */ - static jlong parse_primitive_option_value(char spec, const char* name, size_t name_len, const char* value, TRAPS); - - /** * Loads default option value overrides from a /lib/graal.options if it exists. Each * line in this file must have the format of a Graal command line option without the * leading "-G:" prefix. These option values are set prior to processing of any Graal * options present on the command line. */ - static void parse_graal_options_file(KlassHandle hotSpotOptionsClass, TRAPS); - - /** - * Parses a given argument and sets the denoted Graal option. - * - * @throws InternalError if there was a problem parsing or setting the option - */ - static void parse_argument(KlassHandle hotSpotOptionsClass, char* arg, TRAPS); - - /** - * Searches for a Boolean Graal option denoted by a given name and sets it value. - * - * The definition of this method is in graalRuntime.inline.hpp - * which is generated by com.oracle.graal.hotspot.sourcegen.GenGraalRuntimeInlineHpp. - * - * @param hotSpotOptionsClass the HotSpotOptions klass or NULL if only checking for valid option - * @param name option name - * @param name_len length of option name - * @param value '+' to set the option, '-' to reset the option - * @returns true if the option was found - * @throws InternalError if there was a problem setting the option's value - */ - static bool set_option_bool(KlassHandle hotSpotOptionsClass, char* name, size_t name_len, char value, TRAPS); + static void parse_graal_options_file(OptionsValueTable* options); - /** - * Searches for a Graal option denoted by a given name and sets it value. - * - * The definition of this method is in graalRuntime.inline.hpp - * which is generated by com.oracle.graal.hotspot.sourcegen.GenGraalRuntimeInlineHpp. - * - * @param hotSpotOptionsClass the HotSpotOptions klass or NULL if only checking for valid option - * @param name option name - * @param name_len length of option name - * @returns true if the option was found - * @throws InternalError if there was a problem setting the option's value - */ - static bool set_option(KlassHandle hotSpotOptionsClass, char* name, size_t name_len, const char* value, TRAPS); - - /** - * Raises an InternalError for an option that expects a value but was specified without a "=" prefix. - */ - static void check_required_value(const char* name, size_t name_len, const char* value, TRAPS); - - /** - * Java call to HotSpotOptions.setOption(String name, OptionValue option, char spec, String stringValue, long primitiveValue) - * - * @param name option name - * @param name_len length of option name - */ - static void set_option_helper(KlassHandle hotSpotOptionsClass, char* name, size_t name_len, Handle option, jchar spec, Handle stringValue, jlong primitiveValue); - + static void print_flags_helper(TRAPS); /** * Instantiates a service object, calls its default constructor and returns it. * @@ -119,12 +77,17 @@ */ static Handle create_Service(const char* name, TRAPS); + public: + /** - * Checks that _generated_sources_sha1 equals GeneratedSourcesSha1.value. + * Parses the Graal specific VM options that were presented by the launcher and sets + * the relevants Java fields. */ - static void check_generated_sources_sha1(TRAPS); + static OptionsValueTable* parse_arguments(); - public: + static bool parse_argument(OptionsValueTable* options, const char* arg); + + static void set_options(OptionsValueTable* options, TRAPS); /** * Ensures that the Graal class loader is initialized and the well known Graal classes are loaded. @@ -171,12 +134,11 @@ * Given an interface representing a Graal service (i.e. sub-interface of * com.oracle.graal.api.runtime.Service), gets an array of objects, one per * known implementation of the service. - * - * The definition of this method is in graalRuntime.inline.hpp - * which is generated by com.oracle.graal.hotspot.sourcegen.GenGraalRuntimeInlineHpp. */ static Handle get_service_impls(KlassHandle serviceKlass, TRAPS); + static void parse_lines(char* path, ParseClosure* closure, bool warnStatFailure); + /** * Aborts the VM due to an unexpected exception. */ @@ -222,20 +184,6 @@ static BufferBlob* initialize_buffer_blob(); - /** - * Checks that all Graal specific VM options presented by the launcher are recognized - * and formatted correctly. To set relevant Java fields from the option, parse_arguments() - * must be called. This method makes no Java calls apart from creating exception objects - * if there is an errors in the Graal options. - */ - static jint check_arguments(TRAPS); - - /** - * Parses the JVMCI specific VM options that were presented by the launcher and sets - * the relevants Java fields. - */ - static void parse_arguments(KlassHandle hotSpotOptionsClass, TRAPS); - static BasicType kindToBasicType(jchar ch); // The following routines are all called from compiled Graal code diff -r 54933d47cfa4 -r fad971028755 src/share/vm/prims/nativeLookup.cpp --- a/src/share/vm/prims/nativeLookup.cpp Thu May 28 21:25:21 2015 +0200 +++ b/src/share/vm/prims/nativeLookup.cpp Thu May 28 21:26:54 2015 +0200 @@ -133,7 +133,7 @@ jobject JNICALL JVM_GetGraalServiceImpls(JNIEnv *env, jclass c, jclass serviceClass); jobject JNICALL JVM_CreateTruffleRuntime(JNIEnv *env, jclass c); jobject JNICALL JVM_CreateNativeFunctionInterface(JNIEnv *env, jclass c); - jboolean JNICALL JVM_ParseGraalOptions(JNIEnv *env, jclass hotspotOptionsClass); + jboolean JNICALL JVM_IsCITimingEnabled(JNIEnv *env); #ifdef COMPILERGRAAL void JNICALL JVM_PrintAndResetGraalCompRate(JNIEnv *env, jclass c); #endif @@ -155,7 +155,7 @@ { CC"Java_com_oracle_truffle_api_Truffle_createRuntime", NULL, FN_PTR(JVM_CreateTruffleRuntime) }, { CC"Java_com_oracle_nfi_NativeFunctionInterfaceRuntime_createInterface", NULL, FN_PTR(JVM_CreateNativeFunctionInterface) }, { CC"Java_com_oracle_graal_hotspot_bridge_CompilerToVMImpl_init", NULL, FN_PTR(JVM_InitializeGraalNatives) }, - { CC"Java_com_oracle_graal_hotspot_HotSpotOptions_parseVMOptions", NULL, FN_PTR(JVM_ParseGraalOptions) }, + { CC"Java_com_oracle_graal_hotspot_HotSpotOptions_isCITimingEnabled", NULL, FN_PTR(JVM_IsCITimingEnabled) }, #endif }; diff -r 54933d47cfa4 -r fad971028755 src/share/vm/runtime/arguments.cpp --- a/src/share/vm/runtime/arguments.cpp Thu May 28 21:25:21 2015 +0200 +++ b/src/share/vm/runtime/arguments.cpp Thu May 28 21:26:54 2015 +0200 @@ -3617,7 +3617,7 @@ #ifdef GRAAL if (!UseGraalClassLoader) { - // Append lib/graal/graal*.jar to boot class path + // Append lib/graal/*.jar to boot class path char graalDir[JVM_MAXPATHLEN]; const char* fileSep = os::file_separator(); jio_snprintf(graalDir, sizeof(graalDir), "%s%slib%sgraal", Arguments::get_java_home(), fileSep, fileSep); @@ -3628,9 +3628,7 @@ while ((entry = os::readdir(dir, (dirent *) dbuf)) != NULL) { const char* name = entry->d_name; const char* ext = name + strlen(name) - 4; - if (ext > name && strcmp(ext, ".jar") == 0 - && strlen(name) > strlen("graal") - && strncmp(name, "graal", strlen("graal")) == 0) { + if (ext > name && strcmp(ext, ".jar") == 0) { char fileName[JVM_MAXPATHLEN]; jio_snprintf(fileName, sizeof(fileName), "%s%s%s", graalDir, fileSep, name); scp_p->add_suffix(fileName); diff -r 54933d47cfa4 -r fad971028755 src/share/vm/runtime/thread.cpp --- a/src/share/vm/runtime/thread.cpp Thu May 28 21:25:21 2015 +0200 +++ b/src/share/vm/runtime/thread.cpp Thu May 28 21:26:54 2015 +0200 @@ -3395,6 +3395,13 @@ jint parse_result = Arguments::parse(args); if (parse_result != JNI_OK) return parse_result; +#ifdef GRAAL + OptionsValueTable* options = GraalRuntime::parse_arguments(); + if (options == NULL) { + return JNI_ERR; + } +#endif + os::init_before_ergo(); jint ergo_result = Arguments::apply_ergo(); @@ -3703,11 +3710,7 @@ } #ifdef GRAAL - status = GraalRuntime::check_arguments(main_thread); - if (status != JNI_OK) { - *canTryAgain = false; // don't let caller call JNI_CreateJavaVM again - return status; - } + GraalRuntime::set_options(options, main_thread); #endif // initialize compiler(s)