FunctionNode.java revision 1152:5f6a840fc19d
1139749Simp/* 274429Sorion * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 374429Sorion * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 474429Sorion * 574429Sorion * This code is free software; you can redistribute it and/or modify it 674429Sorion * under the terms of the GNU General Public License version 2 only, as 774429Sorion * published by the Free Software Foundation. Oracle designates this 874429Sorion * particular file as subject to the "Classpath" exception as provided 974429Sorion * by Oracle in the LICENSE file that accompanied this code. 1074429Sorion * 1174429Sorion * This code is distributed in the hope that it will be useful, but WITHOUT 1274429Sorion * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1374429Sorion * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1474429Sorion * version 2 for more details (a copy is included in the LICENSE file that 1574429Sorion * accompanied this code). 1674429Sorion * 1774429Sorion * You should have received a copy of the GNU General Public License version 1874429Sorion * 2 along with this work; if not, write to the Free Software Foundation, 1974429Sorion * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 2074429Sorion * 2174429Sorion * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 2274429Sorion * or visit www.oracle.com if you need additional information or have any 2374429Sorion * questions. 2474429Sorion */ 25192919Sjoel 26192919Sjoelpackage jdk.nashorn.internal.ir; 27192919Sjoel 2874429Sorionimport static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_PROFILE; 2974429Sorionimport static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_STRICT; 3074429Sorionimport static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_TRACE; 3182180Scgimport static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_TRACE_ENTEREXIT; 3274429Sorionimport static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_TRACE_MISSES; 33193640Sariffimport static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_TRACE_VALUES; 34193640Sariff 35193640Sariffimport java.util.Collections; 36193640Sariffimport java.util.EnumSet; 3774429Sorionimport java.util.Iterator; 3874429Sorionimport java.util.List; 3974429Sorionimport jdk.nashorn.internal.AssertsEnabled; 40119287Simpimport jdk.nashorn.internal.codegen.CompileUnit; 41119287Simpimport jdk.nashorn.internal.codegen.Compiler; 4274429Sorionimport jdk.nashorn.internal.codegen.CompilerConstants; 4374429Sorionimport jdk.nashorn.internal.codegen.Namespace; 4474429Sorionimport jdk.nashorn.internal.codegen.types.Type; 4582180Scgimport jdk.nashorn.internal.ir.annotations.Ignore; 4682180Scgimport jdk.nashorn.internal.ir.annotations.Immutable; 4774429Sorionimport jdk.nashorn.internal.ir.visitor.NodeVisitor; 4874429Sorionimport jdk.nashorn.internal.parser.Token; 4974429Sorionimport jdk.nashorn.internal.runtime.RecompilableScriptFunctionData; 5074429Sorionimport jdk.nashorn.internal.runtime.ScriptFunction; 5184771Sorionimport jdk.nashorn.internal.runtime.Source; 5284771Sorionimport jdk.nashorn.internal.runtime.UserAccessorProperty; 5374429Sorionimport jdk.nashorn.internal.runtime.linker.LinkerCallSite; 5474429Sorion 5574429Sorion/** 5674429Sorion * IR representation for function (or script.) 5774429Sorion */ 5874429Sorion@Immutable 5974429Sorionpublic final class FunctionNode extends LexicalContextExpression implements Flags<FunctionNode>, CompileUnitHolder { 6074429Sorion private static final long serialVersionUID = 1L; 6174429Sorion 6274429Sorion /** Type used for all FunctionNodes */ 6374429Sorion public static final Type FUNCTION_TYPE = Type.typeFor(ScriptFunction.class); 6474429Sorion 6574429Sorion /** Function kinds */ 6674763Scg public enum Kind { 6774763Scg /** a normal function - nothing special */ 6874571Sorion NORMAL, 6974429Sorion /** a script function */ 7074429Sorion SCRIPT, 7174429Sorion /** a getter, @see {@link UserAccessorProperty} */ 7274429Sorion GETTER, 7374429Sorion /** a setter, @see {@link UserAccessorProperty} */ 7474429Sorion SETTER 7574429Sorion } 7674429Sorion 7774429Sorion /** Compilation states available */ 7874429Sorion public enum CompilationState { 7974429Sorion /** compiler is ready */ 8074429Sorion INITIALIZED, 8174429Sorion /** method has been parsed */ 8274429Sorion PARSED, 8374429Sorion /** method has been parsed */ 8474429Sorion PARSE_ERROR, 8574429Sorion /** constant folding pass */ 8674429Sorion CONSTANT_FOLDED, 8774429Sorion /** method has been lowered */ 8874429Sorion LOWERED, 8974429Sorion /** program points have been assigned to unique locations */ 9074429Sorion PROGRAM_POINTS_ASSIGNED, 9174429Sorion /** any transformations of builtins have taken place, e.g. apply=>call */ 9274429Sorion BUILTINS_TRANSFORMED, 9374429Sorion /** method has been split */ 9474429Sorion SPLIT, 9574429Sorion /** method has had symbols assigned */ 9674429Sorion SYMBOLS_ASSIGNED, 9774429Sorion /** computed scope depths for symbols */ 9884771Sorion SCOPE_DEPTHS_COMPUTED, 9984771Sorion /** method has had types calculated*/ 10084771Sorion OPTIMISTIC_TYPES_ASSIGNED, 10174429Sorion /** method has had types calculated */ 10274429Sorion LOCAL_VARIABLE_TYPES_CALCULATED, 10374429Sorion /** compile units reused (optional) */ 10474429Sorion COMPILE_UNITS_REUSED, 10574429Sorion /** method has been emitted to bytecode */ 106193640Sariff BYTECODE_GENERATED, 107193640Sariff /** method has been installed */ 108193640Sariff BYTECODE_INSTALLED 109193640Sariff } 11074429Sorion 11174429Sorion /** Source of entity. */ 11274429Sorion private transient final Source source; 11374763Scg 11474429Sorion /** 11574429Sorion * Opaque object representing parser state at the end of the function. Used when reparsing outer functions 11674429Sorion * to skip parsing inner functions. 11774429Sorion */ 11874429Sorion private final Object endParserState; 11974429Sorion 12074429Sorion /** External function identifier. */ 12174797Scg @Ignore 12274429Sorion private final IdentNode ident; 12374429Sorion 12474429Sorion /** The body of the function node */ 12574429Sorion private final Block body; 12674429Sorion 12774797Scg /** Internal function name. */ 12874429Sorion private final String name; 12974429Sorion 13074429Sorion /** Compilation unit. */ 13174429Sorion private final CompileUnit compileUnit; 13274429Sorion 13374429Sorion /** Function kind. */ 13474429Sorion private final Kind kind; 13574429Sorion 13674429Sorion /** List of parameters. */ 13774429Sorion private final List<IdentNode> parameters; 13874429Sorion 13974797Scg /** First token of function. **/ 14074429Sorion private final long firstToken; 14174797Scg 14274429Sorion /** Last token of function. **/ 14374429Sorion private final long lastToken; 14474429Sorion 14574429Sorion /** Method's namespace. */ 14674429Sorion private transient final Namespace namespace; 14774429Sorion 14874429Sorion /** Current compilation state */ 14974429Sorion @Ignore 15074429Sorion private final EnumSet<CompilationState> compilationState; 15174797Scg 15274429Sorion /** Number of properties of "this" object assigned in this function */ 15374797Scg @Ignore 15474429Sorion private final int thisProperties; 15574429Sorion 15674429Sorion /** Function flags. */ 15774429Sorion private final int flags; 15874429Sorion 15974429Sorion /** Line number of function start */ 16074429Sorion private final int lineNumber; 16174429Sorion 16274429Sorion /** Root class for function */ 16374429Sorion private final Class<?> rootClass; 16474429Sorion 16574429Sorion /** Is anonymous function flag. */ 16674429Sorion public static final int IS_ANONYMOUS = 1 << 0; 16774429Sorion 16874429Sorion /** Is the function created in a function declaration (as opposed to a function expression) */ 16974797Scg public static final int IS_DECLARED = 1 << 1; 17074797Scg 17174429Sorion /** is this a strict mode function? */ 17274429Sorion public static final int IS_STRICT = 1 << 2; 17374429Sorion 17474429Sorion /** Does the function use the "arguments" identifier ? */ 17574429Sorion public static final int USES_ARGUMENTS = 1 << 3; 17674429Sorion 17774429Sorion /** Has this function been split because it was too large? */ 17874429Sorion public static final int IS_SPLIT = 1 << 4; 17974429Sorion 18074429Sorion /** Does the function call eval? If it does, then all variables in this function might be get/set by it and it can 18174429Sorion * introduce new variables into this function's scope too.*/ 18274429Sorion public static final int HAS_EVAL = 1 << 5; 18374429Sorion 18474429Sorion /** Does a nested function contain eval? If it does, then all variables in this function might be get/set by it. */ 18574429Sorion public static final int HAS_NESTED_EVAL = 1 << 6; 18674429Sorion 18774429Sorion /** Does this function have any blocks that create a scope? This is used to determine if the function needs to 18874429Sorion * have a local variable slot for the scope symbol. */ 18974429Sorion public static final int HAS_SCOPE_BLOCK = 1 << 7; 19074429Sorion 19174763Scg /** 19274429Sorion * Flag this function as one that defines the identifier "arguments" as a function parameter or nested function 19374429Sorion * name. This precludes it from needing to have an Arguments object defined as "arguments" local variable. Note that 19474429Sorion * defining a local variable named "arguments" still requires construction of the Arguments object (see 19574797Scg * ECMAScript 5.1 Chapter 10.5). 19674429Sorion * @see #needsArguments() 19774429Sorion */ 19874429Sorion public static final int DEFINES_ARGUMENTS = 1 << 8; 19974429Sorion 20074429Sorion /** Does this function or any of its descendants use variables from an ancestor function's scope (incl. globals)? */ 201168847Sariff public static final int USES_ANCESTOR_SCOPE = 1 << 9; 20274429Sorion 20374429Sorion /** Does this function have nested declarations? */ 20474429Sorion public static final int HAS_FUNCTION_DECLARATIONS = 1 << 10; 20574429Sorion 206193640Sariff /** Does this function have optimistic expressions? (If it does, it can undergo deoptimizing recompilation.) */ 20774429Sorion public static final int IS_DEOPTIMIZABLE = 1 << 11; 20874429Sorion 20974429Sorion /** Are we vararg, but do we just pass the arguments along to apply or call */ 21074429Sorion public static final int HAS_APPLY_TO_CALL_SPECIALIZATION = 1 << 12; 21174429Sorion 21274429Sorion /** 21374763Scg * Is this function the top-level program? 21474429Sorion */ 21574429Sorion public static final int IS_PROGRAM = 1 << 13; 21674429Sorion 21774429Sorion /** 21874429Sorion * Flag indicating whether this function uses the local variable symbol for itself. Only named function expressions 219193640Sariff * can have this flag set if they reference themselves (e.g. "(function f() { return f })". Declared functions will 22074429Sorion * use the symbol in their parent scope instead when they reference themselves by name. 22174429Sorion */ 22274429Sorion public static final int USES_SELF_SYMBOL = 1 << 14; 22384771Sorion 22474429Sorion /** Does this function use the "this" keyword? */ 22574429Sorion public static final int USES_THIS = 1 << 15; 22684771Sorion 22774429Sorion /** Is this declared in a dynamic context */ 22874429Sorion public static final int IN_DYNAMIC_CONTEXT = 1 << 16; 22982835Sorion 23074429Sorion /** 23174429Sorion * The following flags are derived from directive comments within this function. 23274429Sorion * Note that even IS_STRICT is one such flag but that requires special handling. 23374429Sorion */ 23474429Sorion 23574429Sorion /** parser, print parse tree */ 23674429Sorion public static final int IS_PRINT_PARSE = 1 << 17; 23774429Sorion /** parser, print lower parse tree */ 238193640Sariff public static final int IS_PRINT_LOWER_PARSE = 1 << 18; 23974429Sorion /** parser, print AST */ 24074429Sorion public static final int IS_PRINT_AST = 1 << 19; 24174429Sorion /** parser, print lower AST */ 24274429Sorion public static final int IS_PRINT_LOWER_AST = 1 << 20; 243193640Sariff /** parser, print symbols */ 24474429Sorion public static final int IS_PRINT_SYMBOLS = 1 << 21; 24574429Sorion 24674429Sorion // callsite tracing, profiling within this function 24774429Sorion /** profile callsites in this function? */ 24874429Sorion public static final int IS_PROFILE = 1 << 22; 24974429Sorion 25074429Sorion /** trace callsite enterexit in this function? */ 25174429Sorion public static final int IS_TRACE_ENTEREXIT = 1 << 23; 25274429Sorion 25374429Sorion /** trace callsite misses in this function? */ 25474429Sorion public static final int IS_TRACE_MISSES = 1 << 24; 25574797Scg 25674429Sorion /** trace callsite values in this function? */ 25774429Sorion public static final int IS_TRACE_VALUES = 1 << 25; 25874429Sorion 25974429Sorion /** 26074429Sorion * Whether this function needs the callee {@link ScriptFunction} instance passed to its code as a 26174429Sorion * parameter on invocation. Note that we aren't, in fact using this flag in function nodes. 26274429Sorion * Rather, it is always calculated (see {@link #needsCallee()}). {@link RecompilableScriptFunctionData} 26374429Sorion * will, however, cache the value of this flag. 26474429Sorion */ 26574429Sorion public static final int NEEDS_CALLEE = 1 << 26; 26674429Sorion 26774429Sorion /** extension callsite flags mask */ 26874429Sorion public static final int EXTENSION_CALLSITE_FLAGS = IS_PRINT_PARSE | 26974429Sorion IS_PRINT_LOWER_PARSE | IS_PRINT_AST | IS_PRINT_LOWER_AST | 27074429Sorion IS_PRINT_SYMBOLS | IS_PROFILE | IS_TRACE_ENTEREXIT | 27174429Sorion IS_TRACE_MISSES | IS_TRACE_VALUES; 27274429Sorion 27374429Sorion /** Does this function or any nested functions contain an eval? */ 27474429Sorion private static final int HAS_DEEP_EVAL = HAS_EVAL | HAS_NESTED_EVAL; 27574429Sorion 27674429Sorion /** Does this function need to store all its variables in scope? */ 27774429Sorion private static final int HAS_ALL_VARS_IN_SCOPE = HAS_DEEP_EVAL; 27874429Sorion 27974429Sorion /** Does this function potentially need "arguments"? Note that this is not a full test, as further negative check of REDEFINES_ARGS is needed. */ 28074797Scg private static final int MAYBE_NEEDS_ARGUMENTS = USES_ARGUMENTS | HAS_EVAL; 28174429Sorion 28274429Sorion /** Does this function need the parent scope? It needs it if either it or its descendants use variables from it, or have a deep eval, or it's the program. */ 28374429Sorion public static final int NEEDS_PARENT_SCOPE = USES_ANCESTOR_SCOPE | HAS_DEEP_EVAL | IS_PROGRAM; 28474429Sorion 28574797Scg /** What is the return type of this function? */ 28674429Sorion private Type returnType = Type.UNKNOWN; 28774429Sorion 28874429Sorion /** 28974429Sorion * Constructor 29074429Sorion * 29174429Sorion * @param source the source 29274429Sorion * @param lineNumber line number 29374429Sorion * @param token token 29474429Sorion * @param finish finish 29574429Sorion * @param firstToken first token of the function node (including the function declaration) 29674429Sorion * @param lastToken lastToken 29774429Sorion * @param namespace the namespace 29874429Sorion * @param ident the identifier 29974429Sorion * @param name the name of the function 30074429Sorion * @param parameters parameter list 30174429Sorion * @param kind kind of function as in {@link FunctionNode.Kind} 30274429Sorion * @param flags initial flags 30374797Scg * @param body body of the function 30474429Sorion * @param state The initial state from the parser. Must be one of {@link CompilationState#PARSED} and {@link CompilationState#PARSE_ERROR} 30574429Sorion * @param endParserState The parser state at the end of the parsing. 30674429Sorion */ 30774429Sorion public FunctionNode( 30874429Sorion final Source source, 30974429Sorion final int lineNumber, 31074429Sorion final long token, 31174429Sorion final int finish, 31274797Scg final long firstToken, 31374429Sorion final long lastToken, 31474429Sorion final Namespace namespace, 31574429Sorion final IdentNode ident, 31674429Sorion final String name, 31774429Sorion final List<IdentNode> parameters, 31874429Sorion final FunctionNode.Kind kind, 31974429Sorion final int flags, 32074429Sorion final Block body, 32174429Sorion final CompilationState state, 32274429Sorion final Object endParserState) { 32374429Sorion super(token, finish); 32474429Sorion 32574429Sorion this.source = source; 32674429Sorion this.lineNumber = lineNumber; 32774429Sorion this.ident = ident; 32874429Sorion this.name = name; 32974429Sorion this.kind = kind; 33074429Sorion this.parameters = parameters; 33174429Sorion this.firstToken = firstToken; 33274429Sorion this.lastToken = lastToken; 333111183Scognet this.namespace = namespace; 33474429Sorion this.compilationState = EnumSet.of(CompilationState.INITIALIZED, state); 33574429Sorion this.flags = flags; 33674429Sorion this.compileUnit = null; 33774429Sorion this.body = body; 33874429Sorion this.thisProperties = 0; 33974429Sorion this.rootClass = null; 34074429Sorion this.endParserState = endParserState; 34174429Sorion } 34274429Sorion 34374429Sorion private FunctionNode( 34474429Sorion final FunctionNode functionNode, 345170521Sariff final long lastToken, 34674429Sorion final Object endParserState, 34774429Sorion final int flags, 34874429Sorion final String name, 34974429Sorion final Type returnType, 35074429Sorion final CompileUnit compileUnit, 35174429Sorion final EnumSet<CompilationState> compilationState, 35274429Sorion final Block body, 35374429Sorion final List<IdentNode> parameters, 35474429Sorion final int thisProperties, 35574429Sorion final Class<?> rootClass, 356193640Sariff final Source source, Namespace namespace) { 35774429Sorion super(functionNode); 35874429Sorion 35974429Sorion this.endParserState = endParserState; 36074429Sorion this.lineNumber = functionNode.lineNumber; 36174429Sorion this.flags = flags; 36274429Sorion this.name = name; 36374429Sorion this.returnType = returnType; 36474429Sorion this.compileUnit = compileUnit; 36574797Scg this.lastToken = lastToken; 36674429Sorion this.compilationState = compilationState; 36774429Sorion this.body = body; 36874429Sorion this.parameters = parameters; 36974429Sorion this.thisProperties = thisProperties; 37074429Sorion this.rootClass = rootClass; 37174429Sorion this.source = source; 37274429Sorion this.namespace = namespace; 37374429Sorion 37474429Sorion // the fields below never change - they are final and assigned in constructor 37574429Sorion this.ident = functionNode.ident; 37674429Sorion this.kind = functionNode.kind; 377193640Sariff this.firstToken = functionNode.firstToken; 37874429Sorion } 37974429Sorion 38074429Sorion @Override 38174429Sorion public Node accept(final LexicalContext lc, final NodeVisitor<? extends LexicalContext> visitor) { 38274429Sorion if (visitor.enterFunctionNode(this)) { 38374429Sorion return visitor.leaveFunctionNode(setBody(lc, (Block)body.accept(visitor))); 38474797Scg } 38574429Sorion return this; 38674429Sorion } 38774429Sorion 38874429Sorion /** 38974429Sorion * Visits the parameter nodes of this function. Parameters are normally not visited automatically. 39074429Sorion * @param visitor the visitor to apply to the nodes. 39174429Sorion * @return a list of parameter nodes, potentially modified from original ones by the visitor. 39274429Sorion */ 39374429Sorion public List<IdentNode> visitParameters(final NodeVisitor<? extends LexicalContext> visitor) { 39474429Sorion return Node.accept(visitor, parameters); 39574429Sorion } 39674797Scg 39774429Sorion /** 39874429Sorion * Get additional callsite flags to be used specific to this function. 39974429Sorion * 40074429Sorion * @return callsite flags 40174429Sorion */ 40274429Sorion public int getCallSiteFlags() { 40374429Sorion int callsiteFlags = 0; 40474429Sorion if (getFlag(IS_STRICT)) { 40574429Sorion callsiteFlags |= CALLSITE_STRICT; 40674429Sorion } 40774429Sorion 40874429Sorion // quick check for extension callsite flags turned on by directives. 409111183Scognet if ((flags & EXTENSION_CALLSITE_FLAGS) == 0) { 41074429Sorion return callsiteFlags; 41174429Sorion } 41274429Sorion 41374429Sorion if (getFlag(IS_PROFILE)) { 41474429Sorion callsiteFlags |= CALLSITE_PROFILE; 41574429Sorion } 41674429Sorion 41774429Sorion if (getFlag(IS_TRACE_MISSES)) { 41874429Sorion callsiteFlags |= CALLSITE_TRACE | CALLSITE_TRACE_MISSES; 41974429Sorion } 42074429Sorion 42174429Sorion if (getFlag(IS_TRACE_VALUES)) { 422170521Sariff callsiteFlags |= CALLSITE_TRACE | CALLSITE_TRACE_ENTEREXIT | CALLSITE_TRACE_VALUES; 42374429Sorion } 42474429Sorion 42574429Sorion if (getFlag(IS_TRACE_ENTEREXIT)) { 42674429Sorion callsiteFlags |= CALLSITE_TRACE | CALLSITE_TRACE_ENTEREXIT; 42774429Sorion } 42874429Sorion 42974429Sorion return callsiteFlags; 43074429Sorion } 43174429Sorion 43274429Sorion /** 433193640Sariff * Get the source for this function 43474429Sorion * @return the source 43574429Sorion */ 43674429Sorion public Source getSource() { 43774429Sorion return source; 43874429Sorion } 43974429Sorion 44074797Scg /** 44174429Sorion * Sets the source and namespace for this function. It can only set a non-null source and namespace for a function 44274429Sorion * that currently has both a null source and a null namespace. This is used to re-set the source and namespace for 44374429Sorion * a deserialized function node. 44474429Sorion * @param source the source for the function. 44574429Sorion * @param namespace the namespace for the function 44674429Sorion * @return a new function node with the set source and namespace 44774429Sorion * @throws IllegalArgumentException if the specified source or namespace is null 44874429Sorion * @throws IllegalStateException if the function already has either a source or namespace set. 44974429Sorion */ 45074429Sorion public FunctionNode initializeDeserialized(final Source source, final Namespace namespace) { 45174429Sorion if (source == null || namespace == null) { 45274429Sorion throw new IllegalArgumentException(); 45374429Sorion } else if (this.source == source && this.namespace == namespace) { 454193640Sariff return this; 45574429Sorion } else if (this.source != null || this.namespace != null) { 45674429Sorion throw new IllegalStateException(); 45774429Sorion } 45874429Sorion return new FunctionNode( 45974429Sorion this, 46074429Sorion lastToken, 46174429Sorion endParserState, 46274429Sorion flags, 46374429Sorion name, 46474429Sorion returnType, 46574429Sorion compileUnit, 46674429Sorion compilationState, 46774429Sorion body, 46874429Sorion parameters, 46974429Sorion thisProperties, 47074429Sorion rootClass, source, namespace); 47174429Sorion } 47274429Sorion 47374429Sorion /** 47474429Sorion * Get the unique ID for this function within the script file. 47574429Sorion * @return the id 47674429Sorion */ 47774429Sorion public int getId() { 47874429Sorion return isProgram() ? -1: Token.descPosition(firstToken); 47974429Sorion } 48074429Sorion 48174429Sorion /** 48274429Sorion * get source name - sourceURL or name derived from Source. 48374429Sorion * 48474429Sorion * @return name for the script source 48574797Scg */ 48674429Sorion public String getSourceName() { 48774429Sorion return getSourceName(source); 48874429Sorion } 48974429Sorion 49074429Sorion /** 49174429Sorion * Static source name getter 49274429Sorion * 49374429Sorion * @param source the source 49474429Sorion * @return source name 49574429Sorion */ 49674429Sorion public static String getSourceName(final Source source) { 49774429Sorion final String explicitURL = source.getExplicitURL(); 49874429Sorion return explicitURL != null ? explicitURL : source.getName(); 49974429Sorion } 50074797Scg 50174429Sorion /** 50274429Sorion * Function to parse nashorn per-function extension directive comments. 50374429Sorion * 50474429Sorion * @param directive nashorn extension directive string 50574429Sorion * @return integer flag for the given directive. 50674797Scg */ 50774429Sorion public static int getDirectiveFlag(final String directive) { 50874429Sorion switch (directive) { 50974797Scg case "nashorn callsite trace enterexit": 51074429Sorion return IS_TRACE_ENTEREXIT; 51174429Sorion case "nashorn callsite trace misses": 51274797Scg return IS_TRACE_MISSES; 51374429Sorion case "nashorn callsite trace objects": 51474429Sorion return IS_TRACE_VALUES; 51574429Sorion case "nashorn callsite profile": 51674429Sorion return IS_PROFILE; 51774429Sorion case "nashorn print parse": 51874797Scg return IS_PRINT_PARSE; 51974429Sorion case "nashorn print lower parse": 52074429Sorion return IS_PRINT_LOWER_PARSE; 52174763Scg case "nashorn print ast": 52274429Sorion return IS_PRINT_AST; 52374429Sorion case "nashorn print lower ast": 52474429Sorion return IS_PRINT_LOWER_AST; 52574429Sorion case "nashorn print symbols": 52674429Sorion return IS_PRINT_SYMBOLS; 52774429Sorion default: 52874429Sorion // unknown/unsupported directive 52974429Sorion return 0; 53074429Sorion } 53174429Sorion } 53274429Sorion 53374429Sorion /** 53474429Sorion * Returns the line number. 53574429Sorion * @return the line number. 53674429Sorion */ 53774429Sorion public int getLineNumber() { 53874429Sorion return lineNumber; 53974763Scg } 54074429Sorion 54174429Sorion /** 54274429Sorion * Get the compilation state of this function 54374429Sorion * @return the compilation state 54474429Sorion */ 545193640Sariff public EnumSet<CompilationState> getState() { 54674763Scg return compilationState; 54774429Sorion } 54874429Sorion 54974429Sorion /** 55074429Sorion * Check whether this FunctionNode has reached a give CompilationState. 55174429Sorion * 55274429Sorion * @param state the state to check for 55374429Sorion * @return true of the node is in the given state 55474429Sorion */ 55574429Sorion public boolean hasState(final EnumSet<CompilationState> state) { 55674429Sorion return !AssertsEnabled.assertsEnabled() || compilationState.containsAll(state); 55774429Sorion } 558127218Smarcel 55974429Sorion /** 56074429Sorion * Add a state to the total CompilationState of this node, e.g. if 56174429Sorion * FunctionNode has been lowered, the compiler will add 56274429Sorion * {@code CompilationState#LOWERED} to the state vector 56374429Sorion * 56474429Sorion * @param lc lexical context 56574429Sorion * @param state {@link CompilationState} to add 566193640Sariff * @return function node or a new one if state was changed 56774429Sorion */ 56874429Sorion public FunctionNode setState(final LexicalContext lc, final CompilationState state) { 56974429Sorion if (!AssertsEnabled.assertsEnabled() || this.compilationState.contains(state)) { 57074429Sorion return this; 57174429Sorion } 57274429Sorion final EnumSet<CompilationState> newState = EnumSet.copyOf(this.compilationState); 57374429Sorion newState.add(state); 57474429Sorion return setCompilationState(lc, newState); 57574429Sorion } 57674429Sorion 57774797Scg /** 57874429Sorion * Copy a compilation state from an original function to this function. Used when creating synthetic 57974797Scg * function nodes by the splitter. 58074429Sorion * 58174429Sorion * @param lc lexical context 58274429Sorion * @param original the original function node to copy compilation state from 58374429Sorion * @return function node or a new one if state was changed 58474429Sorion */ 58574429Sorion public FunctionNode copyCompilationState(final LexicalContext lc, final FunctionNode original) { 58674429Sorion final EnumSet<CompilationState> origState = original.compilationState; 58774429Sorion if (!AssertsEnabled.assertsEnabled() || this.compilationState.containsAll(origState)) { 58874797Scg return this; 58974429Sorion } 59074429Sorion final EnumSet<CompilationState> newState = EnumSet.copyOf(this.compilationState); 59174429Sorion newState.addAll(origState); 59274429Sorion return setCompilationState(lc, newState); 59374429Sorion } 59474429Sorion 59574429Sorion private FunctionNode setCompilationState(final LexicalContext lc, final EnumSet<CompilationState> compilationState) { 59674797Scg return Node.replaceInLexicalContext( 59774429Sorion lc, 59874429Sorion this, 59974429Sorion new FunctionNode( 60074429Sorion this, 60174429Sorion lastToken, 60274429Sorion endParserState, 60374429Sorion flags, 60474429Sorion name, 60574429Sorion returnType, 60674429Sorion compileUnit, 60774429Sorion compilationState, 60874429Sorion body, 60974429Sorion parameters, 61074429Sorion thisProperties, 61174429Sorion rootClass, source, namespace)); 61274429Sorion } 61374797Scg 61474429Sorion 61574429Sorion /** 61674429Sorion * Create a unique name in the namespace of this FunctionNode 61774429Sorion * @param base prefix for name 61874429Sorion * @return base if no collision exists, otherwise a name prefix with base 61974429Sorion */ 62074429Sorion public String uniqueName(final String base) { 62174429Sorion return namespace.uniqueName(base); 62274429Sorion } 62374429Sorion 62474429Sorion @Override 62574429Sorion public void toString(final StringBuilder sb, final boolean printTypes) { 62674429Sorion sb.append('['). 62774429Sorion append(returnType). 62874429Sorion append(']'). 62974429Sorion append(' '); 63074797Scg 63174429Sorion sb.append("function"); 63274429Sorion 63374429Sorion if (ident != null) { 63474797Scg sb.append(' '); 63574429Sorion ident.toString(sb, printTypes); 63674429Sorion } 63774429Sorion 63874429Sorion sb.append('('); 63974429Sorion 64074429Sorion for (final Iterator<IdentNode> iter = parameters.iterator(); iter.hasNext(); ) { 64174429Sorion final IdentNode parameter = iter.next(); 64274429Sorion if (parameter.getSymbol() != null) { 64374429Sorion sb.append('[').append(parameter.getType()).append(']').append(' '); 64474429Sorion } 64574429Sorion parameter.toString(sb, printTypes); 64674429Sorion if (iter.hasNext()) { 64774429Sorion sb.append(", "); 64874429Sorion } 64974429Sorion } 65074429Sorion 65174429Sorion sb.append(')'); 65274429Sorion } 65374429Sorion 65474429Sorion @Override 65574429Sorion public int getFlags() { 65674429Sorion return flags; 65774429Sorion } 65874429Sorion 65974429Sorion @Override 66074429Sorion public boolean getFlag(final int flag) { 66174429Sorion return (flags & flag) != 0; 66274429Sorion } 66374429Sorion 66474429Sorion @Override 66574429Sorion public FunctionNode setFlags(final LexicalContext lc, final int flags) { 66674429Sorion if (this.flags == flags) { 66774429Sorion return this; 66874429Sorion } 66974429Sorion return Node.replaceInLexicalContext( 67074429Sorion lc, 67174429Sorion this, 67274429Sorion new FunctionNode( 67374429Sorion this, 67474429Sorion lastToken, 67574429Sorion endParserState, 67674429Sorion flags, 67774797Scg name, 67874429Sorion returnType, 67974429Sorion compileUnit, 68074429Sorion compilationState, 68174797Scg body, 68274429Sorion parameters, 68374429Sorion thisProperties, 68474429Sorion rootClass, source, namespace)); 68574429Sorion } 68674429Sorion 68774429Sorion @Override 68874429Sorion public FunctionNode clearFlag(final LexicalContext lc, final int flag) { 68974429Sorion return setFlags(lc, flags & ~flag); 69074429Sorion } 69174429Sorion 69274429Sorion @Override 69374429Sorion public FunctionNode setFlag(final LexicalContext lc, final int flag) { 69474429Sorion return setFlags(lc, flags | flag); 69574429Sorion } 69674429Sorion 69774797Scg /** 69874429Sorion * Returns true if the function is the top-level program. 69974429Sorion * @return True if this function node represents the top-level program. 70074797Scg */ 70174429Sorion public boolean isProgram() { 70274429Sorion return getFlag(IS_PROGRAM); 70374797Scg } 70474429Sorion 70574429Sorion /** 70674429Sorion * Returns true if the function contains at least one optimistic operation (and thus can be deoptimized). 70774429Sorion * @return true if the function contains at least one optimistic operation (and thus can be deoptimized). 70874429Sorion */ 70974429Sorion public boolean canBeDeoptimized() { 71074429Sorion return getFlag(IS_DEOPTIMIZABLE); 71174429Sorion } 71274429Sorion 71374429Sorion /** 71474429Sorion * Check if this function has a call expression for the identifier "eval" (that is, {@code eval(...)}). 715142890Simp * 71674429Sorion * @return true if {@code eval} is called. 71774429Sorion */ 71874429Sorion public boolean hasEval() { 71974429Sorion return getFlag(HAS_EVAL); 72074429Sorion } 72174429Sorion 72274429Sorion /** 72374429Sorion * Returns true if a function nested (directly or transitively) within this function {@link #hasEval()}. 72474429Sorion * 72574429Sorion * @return true if a nested function calls {@code eval}. 72682835Sorion */ 72774429Sorion public boolean hasNestedEval() { 728170873Sariff return getFlag(HAS_NESTED_EVAL); 72974429Sorion } 73074429Sorion 731254263Sscottl /** 73274429Sorion * Get the first token for this function 73374429Sorion * @return the first token 73474429Sorion */ 73574429Sorion public long getFirstToken() { 73674429Sorion return firstToken; 73774429Sorion } 73874429Sorion 73974797Scg /** 74074429Sorion * Check whether this function has nested function declarations 74174429Sorion * @return true if nested function declarations exist 74274797Scg */ 74374429Sorion public boolean hasDeclaredFunctions() { 74474429Sorion return getFlag(HAS_FUNCTION_DECLARATIONS); 74574429Sorion } 74674429Sorion 74774429Sorion /** 74874429Sorion * Check if this function's generated Java method needs a {@code callee} parameter. Functions that need access to 74974429Sorion * their parent scope, functions that reference themselves, and non-strict functions that need an Arguments object 75074429Sorion * (since it exposes {@code arguments.callee} property) will need to have a callee parameter. We also return true 75174429Sorion * for split functions to make sure symbols slots are the same in the main and split methods. 75274429Sorion * 75374429Sorion * A function that has had an apply(this,arguments) turned into a call doesn't need arguments anymore, but still 75474429Sorion * has to fit the old callsite, thus, we require a dummy callee parameter for those functions as well 75574429Sorion * 75674429Sorion * @return true if the function's generated Java method needs a {@code callee} parameter. 75774429Sorion */ 75874429Sorion public boolean needsCallee() { 75974429Sorion // NOTE: we only need isSplit() here to ensure that :scope can never drop below slot 2 for splitting array units. 76074429Sorion return needsParentScope() || usesSelfSymbol() || isSplit() || (needsArguments() && !isStrict()) || hasOptimisticApplyToCall(); 76174429Sorion } 76274429Sorion 76374429Sorion /** 76474429Sorion * Return {@code true} if this function makes use of the {@code this} object. 76574797Scg * 766166917Sariff * @return true if function uses {@code this} object 76774429Sorion */ 76874429Sorion public boolean usesThis() { 76974429Sorion return getFlag(USES_THIS); 77074429Sorion } 77184771Sorion 772166904Snetchild 773166904Snetchild /** 77474429Sorion * Return true if function contains an apply to call transform 77574429Sorion * @return true if this function has transformed apply to call 77674429Sorion */ 77784771Sorion public boolean hasOptimisticApplyToCall() { 77874797Scg return getFlag(HAS_APPLY_TO_CALL_SPECIALIZATION); 779117126Sscottl } 780117126Sscottl 78174429Sorion /** 78274429Sorion * Get the identifier for this function, this is its symbol. 78374429Sorion * @return the identifier as an IdentityNode 78474429Sorion */ 78574429Sorion public IdentNode getIdent() { 78674429Sorion return ident; 78774429Sorion } 78874429Sorion 78974429Sorion /** 79074429Sorion * Get the function body 79174429Sorion * @return the function body 79274429Sorion */ 79374797Scg public Block getBody() { 79474429Sorion return body; 79574429Sorion } 79674429Sorion 79774429Sorion /** 79874429Sorion * Reset the function body 79974429Sorion * @param lc lexical context 80074429Sorion * @param body new body 80174797Scg * @return new function node if body changed, same if not 80274429Sorion */ 80374429Sorion public FunctionNode setBody(final LexicalContext lc, final Block body) { 80474429Sorion if (this.body == body) { 80574429Sorion return this; 80682835Sorion } 80782835Sorion return Node.replaceInLexicalContext( 80882835Sorion lc, 80982835Sorion this, 81082835Sorion new FunctionNode( 81182835Sorion this, 81282835Sorion lastToken, 81382835Sorion endParserState, 81482835Sorion flags | 81582835Sorion (body.needsScope() ? 81682835Sorion FunctionNode.HAS_SCOPE_BLOCK : 81782835Sorion 0), 81882835Sorion name, 81982835Sorion returnType, 82082835Sorion compileUnit, 82174429Sorion compilationState, 82274429Sorion body, 82374429Sorion parameters, 82482835Sorion thisProperties, 82574429Sorion rootClass, source, namespace)); 82674797Scg } 82774429Sorion 82874429Sorion /** 82974429Sorion * Does this function's method needs to be variable arity (gather all script-declared parameters in a final 83074429Sorion * {@code Object[]} parameter. Functions that need to have the "arguments" object as well as functions that simply 83174429Sorion * declare too many arguments for JVM to handle with fixed arity will need to be variable arity. 83274429Sorion * @return true if the Java method in the generated code that implements this function needs to be variable arity. 83374429Sorion * @see #needsArguments() 83474429Sorion * @see LinkerCallSite#ARGLIMIT 83574797Scg */ 83674429Sorion public boolean isVarArg() { 83774429Sorion return needsArguments() || parameters.size() > LinkerCallSite.ARGLIMIT; 83874429Sorion } 83974429Sorion 84074429Sorion /** 84174429Sorion * Was this function declared in a dynamic context, i.e. in a with or eval style 84274429Sorion * chain 84374429Sorion * @return true if in dynamic context 84474429Sorion */ 84574429Sorion public boolean inDynamicContext() { 84674429Sorion return getFlag(IN_DYNAMIC_CONTEXT); 84774429Sorion } 84874429Sorion 84974429Sorion /** 85074429Sorion * Check whether a function would need dynamic scope, which is does if it has 85174797Scg * evals and isn't strict. 85274429Sorion * @return true if dynamic scope is needed 85374429Sorion */ 85474797Scg public boolean needsDynamicScope() { 85574429Sorion // Function has a direct eval in it (so a top-level "var ..." in the eval code can introduce a new 85674429Sorion // variable into the function's scope), and it isn't strict (as evals in strict functions get an 85774429Sorion // isolated scope). 85874429Sorion return hasEval() && !isStrict(); 85974429Sorion } 86074429Sorion 86174429Sorion /** 86274429Sorion * Flag this function as declared in a dynamic context 86374429Sorion * @param lc lexical context 86474429Sorion * @return new function node, or same if unmodified 86574429Sorion */ 86674429Sorion public FunctionNode setInDynamicContext(final LexicalContext lc) { 86774429Sorion return setFlag(lc, IN_DYNAMIC_CONTEXT); 86874429Sorion } 86974429Sorion 87074429Sorion /** 87174429Sorion * Returns true if this function needs to have an Arguments object defined as a local variable named "arguments". 87274429Sorion * Functions that use "arguments" as identifier and don't define it as a name of a parameter or a nested function 87374429Sorion * (see ECMAScript 5.1 Chapter 10.5), as well as any function that uses eval or with, or has a nested function that 87474429Sorion * does the same, will have an "arguments" object. Also, if this function is a script, it will not have an 87574429Sorion * "arguments" object, because it does not have local variables; rather the Global object will have an explicit 87674429Sorion * "arguments" property that provides command-line arguments for the script. 87774429Sorion * @return true if this function needs an arguments object. 87874429Sorion */ 87974429Sorion public boolean needsArguments() { 88074429Sorion // uses "arguments" or calls eval, but it does not redefine "arguments", and finally, it's not a script, since 881126695Smatk // for top-level script, "arguments" is picked up from Context by Global.init() instead. 882126695Smatk return getFlag(MAYBE_NEEDS_ARGUMENTS) && !getFlag(DEFINES_ARGUMENTS) && !isProgram(); 88374429Sorion } 88474429Sorion 88574429Sorion /** 88674429Sorion * Returns true if this function needs access to its parent scope. Functions referencing variables outside their 88774429Sorion * scope (including global variables), as well as functions that call eval or have a with block, or have nested 88874429Sorion * functions that call eval or have a with block, will need a parent scope. Top-level script functions also need a 88974797Scg * parent scope since they might be used from within eval, and eval will need an externally passed scope. 89074797Scg * @return true if the function needs parent scope. 89174429Sorion */ 89274797Scg public boolean needsParentScope() { 89374429Sorion return getFlag(NEEDS_PARENT_SCOPE); 89474797Scg } 89574429Sorion 89674429Sorion /** 89774429Sorion * Set the number of properties assigned to the this object in this function. 89874429Sorion * @param lc the current lexical context. 89974429Sorion * @param thisProperties number of properties 90074429Sorion * @return a potentially modified function node 90174429Sorion */ 90274429Sorion public FunctionNode setThisProperties(final LexicalContext lc, final int thisProperties) { 90374429Sorion if (this.thisProperties == thisProperties) { 90474429Sorion return this; 90574429Sorion } 90674429Sorion return Node.replaceInLexicalContext( 90774429Sorion lc, 90874429Sorion this, 90974429Sorion new FunctionNode( 91074429Sorion this, 91174429Sorion lastToken, 91274429Sorion endParserState, 91374429Sorion flags, 91474429Sorion name, 91574429Sorion returnType, 91674429Sorion compileUnit, 91774429Sorion compilationState, 91874429Sorion body, 91974429Sorion parameters, 92074429Sorion thisProperties, 92174429Sorion rootClass, source, namespace)); 92274429Sorion } 92374429Sorion 92474429Sorion /** 92574429Sorion * Get the number of properties assigned to the this object in this function. 92674429Sorion * @return number of properties 92774429Sorion */ 92874429Sorion public int getThisProperties() { 92974429Sorion return thisProperties; 93074429Sorion } 93174429Sorion 93274429Sorion /** 93374429Sorion * Returns true if any of the blocks in this function create their own scope. 93474429Sorion * @return true if any of the blocks in this function create their own scope. 93574429Sorion */ 93674429Sorion public boolean hasScopeBlock() { 93774429Sorion return getFlag(HAS_SCOPE_BLOCK); 93874429Sorion } 93974429Sorion 94074429Sorion /** 94182180Scg * Return the kind of this function 94274429Sorion * @see FunctionNode.Kind 94374429Sorion * @return the kind 94485443Sjhb */ 945132236Stanimura public Kind getKind() { 94685443Sjhb return kind; 947 } 948 949 /** 950 * Return the last token for this function's code 951 * @return last token 952 */ 953 public long getLastToken() { 954 return lastToken; 955 } 956 957 /** 958 * Returns the end parser state for this function. 959 * @return the end parser state for this function. 960 */ 961 public Object getEndParserState() { 962 return endParserState; 963 } 964 965 /** 966 * Get the name of this function 967 * @return the name 968 */ 969 public String getName() { 970 return name; 971 } 972 973 /** 974 * Set the internal name for this function 975 * @param lc lexical context 976 * @param name new name 977 * @return new function node if changed, otherwise the same 978 */ 979 public FunctionNode setName(final LexicalContext lc, final String name) { 980 if (this.name.equals(name)) { 981 return this; 982 } 983 return Node.replaceInLexicalContext( 984 lc, 985 this, 986 new FunctionNode( 987 this, 988 lastToken, 989 endParserState, 990 flags, 991 name, 992 returnType, 993 compileUnit, 994 compilationState, 995 body, 996 parameters, 997 thisProperties, 998 rootClass, source, namespace)); 999 } 1000 1001 /** 1002 * Check if this function should have all its variables in its own scope. Split sub-functions, and 1003 * functions having with and/or eval blocks are such. 1004 * 1005 * @return true if all variables should be in scope 1006 */ 1007 public boolean allVarsInScope() { 1008 return getFlag(HAS_ALL_VARS_IN_SCOPE); 1009 } 1010 1011 /** 1012 * Checks if this function is split into several smaller fragments. 1013 * 1014 * @return true if this function is split into several smaller fragments. 1015 */ 1016 public boolean isSplit() { 1017 return getFlag(IS_SPLIT); 1018 } 1019 1020 /** 1021 * Get the parameters to this function 1022 * @return a list of IdentNodes which represent the function parameters, in order 1023 */ 1024 public List<IdentNode> getParameters() { 1025 return Collections.unmodifiableList(parameters); 1026 } 1027 1028 /** 1029 * Returns the identifier for a named parameter at the specified position in this function's parameter list. 1030 * @param index the parameter's position. 1031 * @return the identifier for the requested named parameter. 1032 * @throws IndexOutOfBoundsException if the index is invalid. 1033 */ 1034 public IdentNode getParameter(final int index) { 1035 return parameters.get(index); 1036 } 1037 1038 /** 1039 * Reset the compile unit used to compile this function 1040 * @see Compiler 1041 * @param lc lexical context 1042 * @param parameters the compile unit 1043 * @return function node or a new one if state was changed 1044 */ 1045 public FunctionNode setParameters(final LexicalContext lc, final List<IdentNode> parameters) { 1046 if (this.parameters == parameters) { 1047 return this; 1048 } 1049 return Node.replaceInLexicalContext( 1050 lc, 1051 this, 1052 new FunctionNode( 1053 this, 1054 lastToken, 1055 endParserState, 1056 flags, 1057 name, 1058 returnType, 1059 compileUnit, 1060 compilationState, 1061 body, 1062 parameters, 1063 thisProperties, 1064 rootClass, source, namespace)); 1065 } 1066 1067 /** 1068 * Check if this function is created as a function declaration (as opposed to function expression) 1069 * @return true if function is declared. 1070 */ 1071 public boolean isDeclared() { 1072 return getFlag(IS_DECLARED); 1073 } 1074 1075 /** 1076 * Check if this function is anonymous 1077 * @return true if function is anonymous 1078 */ 1079 public boolean isAnonymous() { 1080 return getFlag(IS_ANONYMOUS); 1081 } 1082 1083 /** 1084 * Does this function use its self symbol - this is needed only for self-referencing named function expressions. 1085 * Self-referencing declared functions won't have this flag set, as they can access their own symbol through the 1086 * scope (since they're bound to the symbol with their name in their enclosing scope). 1087 * @return true if this function node is a named function expression that uses the symbol for itself. 1088 */ 1089 public boolean usesSelfSymbol() { 1090 return getFlag(USES_SELF_SYMBOL); 1091 } 1092 1093 /** 1094 * Returns true if this is a named function expression (that is, it isn't a declared function, it isn't an 1095 * anonymous function expression, and it isn't a program). 1096 * @return true if this is a named function expression 1097 */ 1098 public boolean isNamedFunctionExpression() { 1099 return !getFlag(IS_PROGRAM | IS_ANONYMOUS | IS_DECLARED); 1100 } 1101 1102 @Override 1103 public Type getType() { 1104 return FUNCTION_TYPE; 1105 } 1106 1107 @Override 1108 public Type getWidestOperationType() { 1109 return FUNCTION_TYPE; 1110 } 1111 1112 /** 1113 * Get the return type for this function. Return types can be specialized 1114 * if the compiler knows them, but parameters cannot, as they need to go through 1115 * appropriate object conversion 1116 * 1117 * @return the return type 1118 */ 1119 public Type getReturnType() { 1120 return returnType; 1121 } 1122 1123 /** 1124 * Set the function return type 1125 * @param lc lexical context 1126 * @param returnType new return type 1127 * @return function node or a new one if state was changed 1128 */ 1129 public FunctionNode setReturnType(final LexicalContext lc, final Type returnType) { 1130 //we never bother with object types narrower than objects, that will lead to byte code verification errors 1131 //as for instance even if we know we are returning a string from a method, the code generator will always 1132 //treat it as an object, at least for now 1133 final Type type = returnType.isObject() ? Type.OBJECT : returnType; 1134 if (this.returnType == type) { 1135 return this; 1136 } 1137 return Node.replaceInLexicalContext( 1138 lc, 1139 this, 1140 new FunctionNode( 1141 this, 1142 lastToken, 1143 endParserState, 1144 flags, 1145 name, 1146 type, 1147 compileUnit, 1148 compilationState, 1149 body, 1150 parameters, 1151 thisProperties, 1152 rootClass, source, namespace 1153 )); 1154 } 1155 1156 /** 1157 * Check if the function is generated in strict mode 1158 * @return true if strict mode enabled for function 1159 */ 1160 public boolean isStrict() { 1161 return getFlag(IS_STRICT); 1162 } 1163 1164 /** 1165 * Get the compile unit used to compile this function 1166 * @see Compiler 1167 * @return the compile unit 1168 */ 1169 @Override 1170 public CompileUnit getCompileUnit() { 1171 return compileUnit; 1172 } 1173 1174 /** 1175 * Reset the compile unit used to compile this function 1176 * @see Compiler 1177 * @param lc lexical context 1178 * @param compileUnit the compile unit 1179 * @return function node or a new one if state was changed 1180 */ 1181 public FunctionNode setCompileUnit(final LexicalContext lc, final CompileUnit compileUnit) { 1182 if (this.compileUnit == compileUnit) { 1183 return this; 1184 } 1185 return Node.replaceInLexicalContext( 1186 lc, 1187 this, 1188 new FunctionNode( 1189 this, 1190 lastToken, 1191 endParserState, 1192 flags, 1193 name, 1194 returnType, 1195 compileUnit, 1196 compilationState, 1197 body, 1198 parameters, 1199 thisProperties, 1200 rootClass, source, namespace)); 1201 } 1202 1203 /** 1204 * Create a temporary variable to the current frame. 1205 * 1206 * @param block that needs the temporary 1207 * @param type Strong type of symbol. 1208 * @param node Primary node to use symbol. 1209 * 1210 * @return Symbol used. 1211 */ 1212 1213 /** 1214 * Get the symbol for a compiler constant, or null if not available (yet) 1215 * @param cc compiler constant 1216 * @return symbol for compiler constant, or null if not defined yet (for example in Lower) 1217 */ 1218 public Symbol compilerConstant(final CompilerConstants cc) { 1219 return body.getExistingSymbol(cc.symbolName()); 1220 } 1221 1222 /** 1223 * Get the root class that this function node compiles to 1224 * @return root class 1225 */ 1226 public Class<?> getRootClass() { 1227 return rootClass; 1228 } 1229 1230 /** 1231 * Reset the root class that this function is compiled to 1232 * @see Compiler 1233 * @param lc lexical context 1234 * @param rootClass root class 1235 * @return function node or a new one if state was changed 1236 */ 1237 public FunctionNode setRootClass(final LexicalContext lc, final Class<?> rootClass) { 1238 if (this.rootClass == rootClass) { 1239 return this; 1240 } 1241 return Node.replaceInLexicalContext( 1242 lc, 1243 this, 1244 new FunctionNode( 1245 this, 1246 lastToken, 1247 endParserState, 1248 flags, 1249 name, 1250 returnType, 1251 compileUnit, 1252 compilationState, 1253 body, 1254 parameters, 1255 thisProperties, 1256 rootClass, source, namespace)); 1257 } 1258} 1259