/** * Initialize boot image compiler. * * @param args command line arguments to the bootimage compiler */ protected void initCompiler(String[] args) { try { BaselineCompiler.initOptions(); VM.sysWrite("BootImageCompiler: init (opt compiler)\n"); // Writing a boot image is a little bit special. We're not really // concerned about compile time, but we do care a lot about the quality // and stability of the generated code. Set the options accordingly. OptimizingCompiler.setBootOptions(masterOptions); // Allow further customization by the user. for (int i = 0, n = args.length; i < n; i++) { String arg = args[i]; if (!masterOptions.processAsOption("-X:bc:", arg)) { if (arg.startsWith("exclude=")) { excludePattern = arg.substring(8); } else { VM.sysWrite("BootImageCompiler: Unrecognized argument " + arg + "; ignoring\n"); } } } EdgeCounts.loadCountsFromFileIfAvailable(masterOptions.PROFILE_EDGE_COUNT_INPUT_FILE); OptimizingCompiler.init(masterOptions); } catch (OptimizingCompilerException e) { String msg = "BootImageCompiler: Compiler failed during initialization: " + e + "\n"; if (e.isFatal) { // An unexpected error when building the opt boot image should be fatal e.printStackTrace(); System.exit(VM.EXIT_STATUS_OPT_COMPILER_FAILED); } else { VM.sysWrite(msg); } } }
/** * Compile a method with bytecodes. * * @param method the method to compile * @return the compiled method */ protected CompiledMethod compileMethod(NormalMethod method, TypeReference[] params) { if (method.hasNoOptCompileAnnotation()) { return baselineCompile(method); } else { CompiledMethod cm = null; OptimizingCompilerException escape = new OptimizingCompilerException(false); try { Callbacks.notifyMethodCompile(method, CompiledMethod.OPT); boolean include = match(method); if (!include) { throw escape; } int freeOptimizationPlan = getFreeOptimizationPlan(); OptimizationPlanElement[] optimizationPlan = optimizationPlans.get(freeOptimizationPlan); CompilationPlan cp = new CompilationPlan( method, params, optimizationPlan, null, options.get(freeOptimizationPlan)); cm = OptimizingCompiler.compile(cp); if (VM.BuildForAdaptiveSystem) { /* We can't accurately measure compilation time on Host JVM, so just approximate with DNA */ int compilerId = CompilerDNA.getCompilerConstant(cp.options.getOptLevel()); cm.setCompilationTime((float) CompilerDNA.estimateCompileTime(compilerId, method)); } releaseOptimizationPlan(freeOptimizationPlan); return cm; } catch (OptimizingCompilerException e) { if (e.isFatal) { // An unexpected error when building the opt boot image should be fatal VM.sysWriteln("Error compiling method: " + method); e.printStackTrace(); System.exit(VM.EXIT_STATUS_OPT_COMPILER_FAILED); } else { boolean printMsg = true; if (e instanceof MagicNotImplementedException) { printMsg = !((MagicNotImplementedException) e).isExpected; } if (e == escape) { printMsg = false; } if (printMsg) { if (e.toString().indexOf("method excluded") >= 0) { String msg = "BootImageCompiler: " + method + " excluded from opt-compilation\n"; VM.sysWrite(msg); } else { String msg = "BootImageCompiler: can't optimize \"" + method + "\" (error was: " + e + ")\n"; VM.sysWrite(msg); } } } return baselineCompile(method); } } }
/** Return a string rep of the operand (ie the effective address) */ public String toString() { String addr = (base == null) ? "<0" : "<[" + base + "]"; if (index != null) { addr += "+[" + index; switch (scale) { case 0: addr += "]"; break; case 1: addr += "*2]"; break; case 2: addr += "*4]"; break; case 3: addr += "*8]"; break; default: OptimizingCompilerException.UNREACHABLE(); } } if (!disp.isZero()) { addr += "+" + disp.toInt(); } switch (size) { case 1: addr += ">B"; break; case 2: addr += ">W"; break; case 4: addr += ">DW"; break; case 8: addr += ">QW"; break; case 16: addr += ">PARAGRAPH"; break; default: OptimizingCompilerException.UNREACHABLE(); } if (loc != null && guard != null) { addr += " (" + loc + ", " + guard + ")"; } else if (loc != null) { addr += " (" + loc + ")"; } else if (guard != null) { addr += " (" + guard + ")"; } return addr; }
/** Is a specified condition operand 'safe' to transfer into an FCMP instruction? */ private boolean fpConditionOK(ConditionOperand c) { // FCOMI sets ZF, PF, and CF as follows: // Compare Results ZF PF CF // left > right 0 0 0 // left < right 0 0 1 // left == right 1 0 0 // UNORDERED 1 1 1 switch (c.value) { case ConditionOperand.CMPL_EQUAL: return false; // (ZF == 1) but ordered case ConditionOperand.CMPL_NOT_EQUAL: return false; // (ZF == 0) but unordered case ConditionOperand.CMPG_LESS: return false; // (CF == 1) but ordered case ConditionOperand.CMPG_GREATER_EQUAL: return false; // (CF == 0) but unordered case ConditionOperand.CMPG_LESS_EQUAL: return false; // (CF == 1 || ZF == 1) but ordered case ConditionOperand.CMPG_GREATER: return false; // (CF == 0 && ZF == 0) but unordered case ConditionOperand.CMPL_GREATER: return true; // (CF == 0 && ZF == 0) and ordered case ConditionOperand.CMPL_LESS_EQUAL: return true; // (CF == 1 || ZF == 1) and unordered case ConditionOperand.CMPL_GREATER_EQUAL: return true; // (CF == 0) and ordered case ConditionOperand.CMPL_LESS: return true; // (CF == 1) and unordered default: OptimizingCompilerException.UNREACHABLE(); return false; // keep jikes happy } }
/** * @param type one of INT_VALUE, FLOAT_VALUE, or DOUBLE_VALUE * @return the move operator for a type of value. */ private static Operator getMoveOperator(Register type) { if (type.isNatural()) { return IA32_MOV; } else if (type.isDouble()) { return SSE2_FULL ? IA32_MOVSD : IA32_FMOV; } else if (type.isFloat()) { return SSE2_FULL ? IA32_MOVSS : IA32_FMOV; } else { OptimizingCompilerException.TODO("getMoveOperator: unsupported: " + type); return null; } }
/** * @param type one of INT_VALUE, FLOAT_VALUE, or DOUBLE_VALUE * @return the size of a type of value, in bytes. NOTE: For the purpose of register allocation, an * x87 FLOAT_VALUE is 64 bits! */ private static byte getSizeOfType(Register type) { if (type.isNatural()) { if (VM.BuildFor64Addr && type.isInteger()) { return (byte) BYTES_IN_INT; } else { return (byte) WORDSIZE; } } else if (type.isFloat()) { if (SSE2_FULL) return (byte) BYTES_IN_FLOAT; return (byte) BYTES_IN_DOUBLE; } else if (type.isDouble()) { return (byte) BYTES_IN_DOUBLE; } else { OptimizingCompilerException.TODO("getSizeOfValue: unsupported: " + type); return (byte) -1; } }
/** * Get a constructor object for this compiler phase * * @return exception/null as this phase can't be created */ public Constructor<CompilerPhase> getClassConstructor() { OptimizingCompilerException.UNREACHABLE(); return null; }