/**
* Construct a parser.
*
* @param env script environment
* @param source source to parse
* @param errors error manager
* @param strict parser created with strict mode enabled.
* @param lineOffset line offset to start counting lines from
* @param log debug logger if one is needed
*/
public Parser(final ScriptEnvironment env,final Source source,final ErrorManager errors,final boolean strict,final int lineOffset,final DebugLogger log) {
super(source,errors,strict,lineOffset);
this.env = env;
this.namespace = new Namespace(env.getNamespace());
this.scripting = env._scripting;
if (this.scripting) {
this.lineInfoReceiver = new Lexer.LineInfoReceiver() {
@Override
public void lineInfo(final int receiverLine,final int receiverLinePosition) {
// update the parser maintained line information
Parser.this.line = receiverLine;
Parser.this.linePosition = receiverLinePosition;
}
};
} else {
// non-scripting mode script can't have multi-line literals
this.lineInfoReceiver = null;
}
this.log = log == null ? DebugLogger.disABLED_LOGGER : log;
}
CompiledFunction(final MethodHandle invoker,final MethodHandle constructor,final int flags,final MethodType callSiteType,final Specialization specialization,final DebugLogger log) {
this.specialization = specialization;
if (specialization != null && specialization.isOptimistic()) {
/*
* An optimistic builtin with isOptimistic=true works like any optimistic generated function,i.e. it
* can throw unwarranted optimism exceptions. As native functions trivially can't have parts of them
* regenerated as restof methods,this only works if the methods are atomic/functional in their behavior
* and doesn't modify state before an UOE can be thrown. If they aren't,we can reexecute a wider version
* of the same builtin in a recompilation handler for FinalScriptFunctionData. There are several
* candidate methods in Native* that would benefit from this,but I haven't had time to implement any
* of them currently. In order to fit in with the relinking framework,the current thinking is
* that the methods still take a program point to fit in with other optimistic functions,but
* it is set to "first",which is the beginning of the method. The relinker can tell the difference
* between builtin and JavaScript functions. This might change. Todo
*/
this.invoker = MH.insertArguments(invoker,invoker.type().parameterCount() - 1,UnwarrantedOptimismException.FirsT_PROGRAM_POINT);
throw new AssertionError("Optimistic (UnwarrantedOptimismException throwing) builtin functions are currently not in use");
}
this.invoker = invoker;
this.constructor = constructor;
this.flags = flags;
this.callSiteType = callSiteType;
this.log = log;
}
private boolean hasApplies(final FunctionNode functionNode) {
try {
functionNode.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
@Override
public boolean enterFunctionNode(final FunctionNode fn) {
return fn == functionNode;
}
@Override
public boolean enterCallNode(final CallNode callNode) {
if (isApply(callNode)) {
throw HAS_APPLIES;
}
return true;
}
});
} catch (final AppliesFoundException e) {
return true;
}
log.fine("There are no applies in ",DebugLogger.quote(functionNode.getName())," - nothing to do.");
return false; // no applies
}
项目:openjdk-jdk10
文件:Parser.java
/**
* Construct a parser.
*
* @param env script environment
* @param source source to parse
* @param errors error manager
* @param strict parser created with strict mode enabled.
* @param lineOffset line offset to start counting lines from
* @param log debug logger if one is needed
*/
public Parser(final ScriptEnvironment env,lineOffset);
this.lc = new ParserContext();
this.defaultNames = new arraydeque<>();
this.env = env;
this.namespace = new Namespace(env.getNamespace());
this.scripting = env._scripting;
if (this.scripting) {
this.lineInfoReceiver = new Lexer.LineInfoReceiver() {
@Override
public void lineInfo(final int receiverLine,final int receiverLinePosition) {
// update the parser maintained line information
Parser.this.line = receiverLine;
Parser.this.linePosition = receiverLinePosition;
}
};
} else {
// non-scripting mode script can't have multi-line literals
this.lineInfoReceiver = null;
}
this.log = log == null ? DebugLogger.disABLED_LOGGER : log;
}
项目:openjdk-jdk10
文件:ApplySpecialization.java
private boolean hasApplies(final FunctionNode functionNode) {
try {
functionNode.accept(new SimpleNodeVisitor() {
@Override
public boolean enterFunctionNode(final FunctionNode fn) {
return fn == functionNode;
}
@Override
public boolean enterCallNode(final CallNode callNode) {
if (isApply(callNode)) {
throw HAS_APPLIES;
}
return true;
}
});
} catch (final AppliesFoundException e) {
return true;
}
log.fine("There are no applies in "," - nothing to do.");
return false; // no applies
}
private DebugLogger ensureInitialized(final Context context) {
//lazy init,as there is not necessarily a context available when
//a ScriptEnvironment gets initialize
if (isEnabled() && log == null) {
log = initLogger(context);
if (log.isEnabled()) {
this.timesupplier = new Timesupplier();
Runtime.getRuntime().addShutdownHook(
new Thread() {
@Override
public void run() {
//System.err.println because the context and the output streams may be gone
//when the shutdown hook executes
final StringBuilder sb = new StringBuilder();
for (final String str : timesupplier.getStrings()) {
sb.append('[').
append(Timing.getLoggerName()).
append("] ").
append(str).
append('\n');
}
System.err.print(sb);
}
});
}
}
return log;
}
private void logRecompile(final String reason,final FunctionNode fn,final MethodType type,final Map<Integer,Type> ipp) {
if (log.isEnabled()) {
log.info(reason,DebugLogger.quote(fn.getName())," signature: ",type);
log.indent();
for (final String str : toStringInvalidations(ipp)) {
log.fine(str);
}
log.unindent();
}
}
/**
* Tracer that is applied before a value is returned from the traced function. It will output the return
* value and its class
*
* @param value return value for filter
* @return return value unmodified
*/
static Object traceReturn(final DebugLogger logger,final Object value) {
final String str = " return" +
(VOID_TAG.equals(value) ?
";" :
" " + stripName(value) + "; // [type=" + (value == null ? "null]" : stripName(value.getClass()) + ']'));
if (logger == null) {
err(str);
} else if (logger.isEnabled()) {
logger.log(TRACE_LEVEL,str);
}
return value;
}
/**
* Tracer that is applied before a function is called,printing the arguments
*
* @param tag tag to start the debug printout string
* @param paramStart param index to start outputting from
* @param args arguments to the function
*/
static void traceArgs(final DebugLogger logger,final String tag,final int paramStart,final Object... args) {
final StringBuilder sb = new StringBuilder();
sb.append(tag);
for (int i = paramStart; i < args.length; i++) {
if (i == paramStart) {
sb.append(" => args: ");
}
sb.append('\'').
append(stripName(argString(args[i]))).
append('\'').
append(' ').
append('[').
append("type=").
append(args[i] == null ? "null" : stripName(args[i].getClass())).
append(']');
if (i + 1 < args.length) {
sb.append(",");
}
}
if (logger == null) {
err(sb.toString());
} else {
logger.log(TRACE_LEVEL,sb);
}
stacktrace(logger);
}
private static void stacktrace(final DebugLogger logger) {
if (!PRINT_STACKTRACE) {
return;
}
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
final PrintStream ps = new PrintStream(baos);
new Throwable().printstacktrace(ps);
final String st = baos.toString();
if (logger == null) {
err(st);
} else {
logger.log(TRACE_LEVEL,st);
}
}
/**
* Add a debug printout to a method handle,tracing parameters and return values
*
* @param logger a specific logger to which to write the output
* @param level level over which to print
* @param mh method handle to trace
* @param paramStart first param to print/trace
* @param printReturnValue should we print/trace return value if available?
* @param tag start of trace message
* @return traced method handle
*/
public static MethodHandle addDebugPrintout(final DebugLogger logger,final Level level,final MethodHandle mh,final boolean printReturnValue,final Object tag) {
final MethodType type = mh.type();
//if there is no logger,or if it's set to log only coarser events
//than the trace level,skip and return
if (logger != null && logger.levelCoarserThan(level)) {
return mh;
}
assert TRACE != null;
MethodHandle trace = MethodHandles.insertArguments(TRACE,logger,tag,paramStart);
trace = MethodHandles.foldArguments(
mh,trace.asCollector(
Object[].class,type.parameterCount()).
asType(type.changeReturnType(void.class)));
final Class<?> retType = type.returnType();
if (printReturnValue) {
if (retType != void.class) {
final MethodHandle traceReturn = MethodHandles.insertArguments(TRACE_RETURN,logger);
trace = MethodHandles.filterReturnValue(trace,traceReturn.asType(
traceReturn.type().changeParameterType(0,retType).changeReturnType(retType)));
} else {
trace = MethodHandles.filterReturnValue(trace,MethodHandles.insertArguments(TRACE_RETURN_VOID,logger));
}
}
return trace;
}
private static DebugLogger getLogger() {
try {
return Context.getContext().getLogger(RecompilableScriptFunctionData.class);
} catch (final Exception e) {
e.printstacktrace();
return DebugLogger.disABLED_LOGGER;
}
}
@Override
public DebugLogger initLogger(final Context ctxt) {
final boolean optimisticTypes = env._optimistic_types;
final boolean lazyCompilation = env._lazy_compilation;
return ctxt.getLogger(this.getClass(),new Consumer<DebugLogger>() {
@Override
public void accept(final DebugLogger newLogger) {
if (!lazyCompilation) {
newLogger.warning("WARNING: Running with lazy compilation switched off. This is not a default setting.");
}
newLogger.warning("Optimistic types are ",optimisticTypes ? "ENABLED." : "disABLED.");
}
});
}
@Override
public Node leaveCallNode(final CallNode callNode) {
//apply needs to be a global symbol or we don't allow it
final List<IdentNode> newParams = explodedArguments.peek();
if (isApply(callNode)) {
final List<Expression> newArgs = new ArrayList<>();
for (final Expression arg : callNode.getArgs()) {
if (arg instanceof IdentNode && ARGUMENTS.equals(((IdentNode)arg).getName())) {
newArgs.addAll(newParams);
} else {
newArgs.add(arg);
}
}
changed.add(lc.getCurrentFunction().getId());
final CallNode newCallNode = callNode.setArgs(newArgs).setIsApplyToCall();
if (log.isEnabled()) {
log.fine("Transformed ",callNode," from apply to call => ",newCallNode," in ",DebugLogger.quote(lc.getCurrentFunction().getName()));
}
return newCallNode;
}
return callNode;
}
项目:openjdk-jdk10
文件:Timing.java
private DebugLogger ensureInitialized(final Context context) {
//lazy init,as there is not necessarily a context available when
//a ScriptEnvironment gets initialize
if (isEnabled() && log == null) {
log = initLogger(context);
if (log.isEnabled()) {
this.timesupplier = new Timesupplier();
Runtime.getRuntime().addShutdownHook(
new Thread() {
@Override
public void run() {
//System.err.println because the context and the output streams may be gone
//when the shutdown hook executes
final StringBuilder sb = new StringBuilder();
for (final String str : timesupplier.getStrings()) {
sb.append('[').
append(Timing.getLoggerName()).
append("] ").
append(str).
append('\n');
}
System.err.print(sb);
}
});
}
}
return log;
}
项目:openjdk-jdk10
文件:CompiledFunction.java
private void logRecompile(final String reason,type);
log.indent();
for (final String str : toStringInvalidations(ipp)) {
log.fine(str);
}
log.unindent();
}
}
项目:openjdk-jdk10
文件:MethodHandleFactory.java
/**
* Tracer that is applied before a value is returned from the traced function. It will output the return
* value and its class
*
* @param value return value for filter
* @return return value unmodified
*/
static Object traceReturn(final DebugLogger logger,final Object value) {
final String str = " return" +
(VOID_TAG.equals(value) ?
";" :
" " + stripName(value) + "; // [type=" + (value == null ? "null]" : stripName(value.getClass()) + ']'));
if (logger == null) {
err(str);
} else if (logger.isEnabled()) {
logger.log(TRACE_LEVEL,str);
}
return value;
}
项目:openjdk-jdk10
文件:MethodHandleFactory.java
/**
* Tracer that is applied before a function is called,final Object... args) {
final StringBuilder sb = new StringBuilder();
sb.append(tag);
for (int i = paramStart; i < args.length; i++) {
if (i == paramStart) {
sb.append(" => args: ");
}
sb.append('\'').
append(stripName(argString(args[i]))).
append('\'').
append(' ').
append('[').
append("type=").
append(args[i] == null ? "null" : stripName(args[i].getClass())).
append(']');
if (i + 1 < args.length) {
sb.append(",sb);
}
stacktrace(logger);
}
项目:openjdk-jdk10
文件:MethodHandleFactory.java
private static void stacktrace(final DebugLogger logger) {
if (!PRINT_STACKTRACE) {
return;
}
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
final PrintStream ps = new PrintStream(baos);
new Throwable().printstacktrace(ps);
final String st = baos.toString();
if (logger == null) {
err(st);
} else {
logger.log(TRACE_LEVEL,st);
}
}
项目:openjdk-jdk10
文件:MethodHandleFactory.java
/**
* Add a debug printout to a method handle,skip and return
if (logger == null || !logger.isLoggable(level)) {
return mh;
}
assert TRACE != null;
MethodHandle trace = MethodHandles.insertArguments(TRACE,trace.asCollector(
Object[].class,type.parameterCount()).
asType(type.changeReturnType(void.class)));
final Class<?> retType = type.returnType();
if (printReturnValue) {
if (retType != void.class) {
final MethodHandle traceReturn = MethodHandles.insertArguments(TRACE_RETURN,traceReturn.asType(
traceReturn.type().changeParameterType(0,logger));
}
}
return trace;
}
@Override
public DebugLogger getLogger() {
return log;
}
@Override
public DebugLogger initLogger(final Context context) {
return context.getLogger(this.getClass());
}
@Override
public DebugLogger getLogger() {
return log;
}
@Override
public DebugLogger initLogger(final Context context) {
return DebugLogger.disABLED_LOGGER;
}
private synchronized Class<?> compile(final Source source,final ErrorManager errMan,final boolean strict) {
// start with no errors,no warnings.
errMan.reset();
Class<?> script = findCachedClass(source);
if (script != null) {
final DebugLogger log = getLogger(Compiler.class);
if (log.isEnabled()) {
log.fine(new RuntimeEvent<>(Level.INFO,source),"Code cache hit for ",source," avoiding recompile.");
}
return script;
}
StoredScript storedScript = null;
FunctionNode functionNode = null;
// We only use the code store here if optimistic types are disabled. With optimistic types,initial compilation
// just creates a thin wrapper,and actual code is stored per function in RecompilableScriptFunctionData.
final boolean useCodeStore = codeStore != null && !env._parse_only && !env._optimistic_types;
final String cacheKey = useCodeStore ? CodeStore.getCacheKey(0,null) : null;
if (useCodeStore) {
storedScript = codeStore.load(source,cacheKey);
}
if (storedScript == null) {
functionNode = new Parser(env,errMan,getLogger(Parser.class)).parse();
if (errMan.hasErrors()) {
return null;
}
if (env._print_ast || functionNode.getFlag(FunctionNode.IS_PRINT_AST)) {
getErr().println(new ASTWriter(functionNode));
}
if (env._print_parse || functionNode.getFlag(FunctionNode.IS_PRINT_PARSE)) {
getErr().println(new PrintVisitor(functionNode,true,false));
}
}
if (env._parse_only) {
return null;
}
final URL url = source.getURL();
final ScriptLoader loader = env._loader_per_compile ? createNewLoader() : scriptLoader;
final CodeSource cs = new CodeSource(url,(CodeSigner[])null);
final CodeInstaller<ScriptEnvironment> installer = new ContextCodeInstaller(this,loader,cs);
if (storedScript == null) {
final CompilationPhases phases = Compiler.CompilationPhases.COMPILE_ALL;
final Compiler compiler = new Compiler(
this,env,installer,strict | functionNode.isstrict());
final FunctionNode compiledFunction = compiler.compile(functionNode,phases);
if (errMan.hasErrors()) {
return null;
}
script = compiledFunction.getRootClass();
compiler.persistClassInfo(cacheKey,compiledFunction);
} else {
Compiler.updateCompilationId(storedScript.getCompilationId());
script = install(storedScript,installer);
}
cacheClass(source,script);
return script;
}
private static void debug(final Object... msg) {
final DebugLogger logger = getLoggerStatic();
if (logger != null) {
logger.info(msg);
}
}
private static DebugLogger getLoggerStatic() {
final Context context = Context.getContextTrustedOrNull();
return context == null ? null : context.getLogger(Source.class);
}
@Override
public DebugLogger initLogger(final Context context) {
return context.getLogger(this.getClass());
}
@Override
public DebugLogger getLogger() {
return initLogger(Context.getContextTrusted());
}
项目:openjdk-jdk10
文件:CodeGenerator.java
@Override
public DebugLogger getLogger() {
return log;
}
@Override
public DebugLogger initLogger(final Context ctxt) {
return ctxt.getLogger(this.getClass());
}
项目:openjdk-jdk10
文件:ObjectClassGenerator.java
@Override
public DebugLogger initLogger(final Context ctxt) {
return ctxt.getLogger(this.getClass());
}
@Override
public DebugLogger initLogger(final Context context) {
return context.getLogger(this.getClass());
}
@Override
public DebugLogger getLogger() {
return log;
}
CompiledFunction(final MethodHandle invoker,final Specialization specialization) {
this(invoker,constructor,null,specialization,DebugLogger.disABLED_LOGGER);
}
@Override
public DebugLogger initLogger(final Context context) {
log = context.getLogger(getClass());
return log;
}
@Override
public DebugLogger getLogger() {
return log;
}
static void traceReturnVoid(final DebugLogger logger) {
traceReturn(logger,VOID_TAG);
}
@Override
public DebugLogger initLogger(final Context context) {
return this.log = context.getLogger(this.getClass());
}
@Override
public DebugLogger getLogger() {
return log;
}