FunctionNode.java revision 1068:34ef988d5959
119026Sjulian/*
219026Sjulian * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
319026Sjulian * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
419026Sjulian *
519026Sjulian * This code is free software; you can redistribute it and/or modify it
619026Sjulian * under the terms of the GNU General Public License version 2 only, as
719026Sjulian * published by the Free Software Foundation.  Oracle designates this
819026Sjulian * particular file as subject to the "Classpath" exception as provided
919026Sjulian * by Oracle in the LICENSE file that accompanied this code.
1019026Sjulian *
1119026Sjulian * This code is distributed in the hope that it will be useful, but WITHOUT
1219026Sjulian * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1319026Sjulian * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1419026Sjulian * version 2 for more details (a copy is included in the LICENSE file that
1519026Sjulian * accompanied this code).
1619026Sjulian *
1719026Sjulian * You should have received a copy of the GNU General Public License version
1819026Sjulian * 2 along with this work; if not, write to the Free Software Foundation,
1919026Sjulian * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
2019026Sjulian *
2119026Sjulian * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2219026Sjulian * or visit www.oracle.com if you need additional information or have any
2319026Sjulian * questions.
2419026Sjulian */
2519026Sjulian
2650476Speterpackage jdk.nashorn.internal.ir;
2723462Sjmg
286894Sdufaultimport static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_PROFILE;
296894Sdufaultimport static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_STRICT;
3079538Sruimport static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_TRACE;
316894Sdufaultimport static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_TRACE_ENTEREXIT;
326894Sdufaultimport static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_TRACE_MISSES;
3313479Swollmanimport static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_TRACE_VALUES;
346894Sdufaultimport java.util.Collections;
3556467Sasmodaiimport java.util.EnumSet;
366894Sdufaultimport java.util.Iterator;
376894Sdufaultimport java.util.List;
3813479Swollmanimport java.util.function.Function;
3979727Sschweikhimport jdk.nashorn.internal.AssertsEnabled;
4013479Swollmanimport jdk.nashorn.internal.codegen.CompileUnit;
41117011Sruimport jdk.nashorn.internal.codegen.Compiler;
42117011Sruimport jdk.nashorn.internal.codegen.CompilerConstants;
4313479Swollmanimport jdk.nashorn.internal.codegen.Namespace;
4413479Swollmanimport jdk.nashorn.internal.codegen.types.Type;
456894Sdufaultimport jdk.nashorn.internal.ir.annotations.Ignore;
466894Sdufaultimport jdk.nashorn.internal.ir.annotations.Immutable;
4713479Swollmanimport jdk.nashorn.internal.ir.visitor.NodeVisitor;
4813479Swollmanimport jdk.nashorn.internal.parser.Token;
4913479Swollmanimport jdk.nashorn.internal.runtime.RecompilableScriptFunctionData;
506894Sdufaultimport jdk.nashorn.internal.runtime.ScriptFunction;
516894Sdufaultimport jdk.nashorn.internal.runtime.Source;
5250073Skenimport jdk.nashorn.internal.runtime.UserAccessorProperty;
536894Sdufaultimport jdk.nashorn.internal.runtime.linker.LinkerCallSite;
546894Sdufault
556894Sdufault/**
5650073Sken * IR representation for function (or script.)
5713479Swollman */
5850073Sken@Immutable
5913479Swollmanpublic final class FunctionNode extends LexicalContextExpression implements Flags<FunctionNode>, CompileUnitHolder {
6050073Sken    private static final long serialVersionUID = 1L;
6150073Sken
6250073Sken    /** Type used for all FunctionNodes */
6313479Swollman    public static final Type FUNCTION_TYPE = Type.typeFor(ScriptFunction.class);
64131530Sru
65131530Sru    /** Function kinds */
66119893Sru    public enum Kind {
67213573Suqs        /** a normal function - nothing special */
6850073Sken        NORMAL,
6950073Sken        /** a script function */
706894Sdufault        SCRIPT,
71117011Sru        /** a getter, @see {@link UserAccessorProperty} */
72117011Sru        GETTER,
7350073Sken        /** a setter, @see {@link UserAccessorProperty} */
7450073Sken        SETTER
7550073Sken    }
76117011Sru
77117011Sru    /** Compilation states available */
7850073Sken    public enum CompilationState {
7913479Swollman        /** compiler is ready */
8013479Swollman        INITIALIZED,
8113479Swollman        /** method has been parsed */
8213479Swollman        PARSED,
8373233Sru        /** method has been parsed */
8413479Swollman        PARSE_ERROR,
856894Sdufault        /** constant folding pass */
86204705Smav        CONSTANT_FOLDED,
876894Sdufault        /** method has been lowered */
886894Sdufault        LOWERED,
896894Sdufault        /** program points have been assigned to unique locations */
9079727Sschweikh        PROGRAM_POINTS_ASSIGNED,
9117784Smpp        /** any transformations of builtins have taken place, e.g. apply=&gt;call */
92        BUILTINS_TRANSFORMED,
93        /** method has been split */
94        SPLIT,
95        /** method has had symbols assigned */
96        SYMBOLS_ASSIGNED,
97        /** computed scope depths for symbols */
98        SCOPE_DEPTHS_COMPUTED,
99        /** method has had types calculated*/
100        OPTIMISTIC_TYPES_ASSIGNED,
101        /** method has had types calculated */
102        LOCAL_VARIABLE_TYPES_CALCULATED,
103        /** compile units reused (optional) */
104        COMPILE_UNITS_REUSED,
105        /** method has been emitted to bytecode */
106        BYTECODE_GENERATED,
107        /** method has been installed */
108        BYTECODE_INSTALLED
109    }
110
111    /** Source of entity. */
112    private final Source source;
113
114    /**
115     * Opaque object representing parser state at the end of the function. Used when reparsing outer functions
116     * to skip parsing inner functions.
117     */
118    private final Object endParserState;
119
120    /** External function identifier. */
121    @Ignore
122    private final IdentNode ident;
123
124    /** The body of the function node */
125    private final Block body;
126
127    /** Internal function name. */
128    private final String name;
129
130    /** Compilation unit. */
131    private final CompileUnit compileUnit;
132
133    /** Function kind. */
134    private final Kind kind;
135
136    /** List of parameters. */
137    private final List<IdentNode> parameters;
138
139    /** First token of function. **/
140    private final long firstToken;
141
142    /** Last token of function. **/
143    private final long lastToken;
144
145    /** Method's namespace. */
146    private final Namespace namespace;
147
148    /** Current compilation state */
149    @Ignore
150    private final EnumSet<CompilationState> compilationState;
151
152    /** Number of properties of "this" object assigned in this function */
153    @Ignore
154    private final int thisProperties;
155
156    /** Function flags. */
157    private final int flags;
158
159    /** Line number of function start */
160    private final int lineNumber;
161
162    /** Root class for function */
163    private final Class<?> rootClass;
164
165    /** Is anonymous function flag. */
166    public static final int IS_ANONYMOUS                = 1 << 0;
167
168    /** Is the function created in a function declaration (as opposed to a function expression) */
169    public static final int IS_DECLARED                 = 1 << 1;
170
171    /** is this a strict mode function? */
172    public static final int IS_STRICT                   = 1 << 2;
173
174    /** Does the function use the "arguments" identifier ? */
175    public static final int USES_ARGUMENTS              = 1 << 3;
176
177    /** Has this function been split because it was too large? */
178    public static final int IS_SPLIT                    = 1 << 4;
179
180    /** Does the function call eval? If it does, then all variables in this function might be get/set by it and it can
181     * introduce new variables into this function's scope too.*/
182    public static final int HAS_EVAL                    = 1 << 5;
183
184    /** Does a nested function contain eval? If it does, then all variables in this function might be get/set by it. */
185    public static final int HAS_NESTED_EVAL             = 1 << 6;
186
187    /** Does this function have any blocks that create a scope? This is used to determine if the function needs to
188     * have a local variable slot for the scope symbol. */
189    public static final int HAS_SCOPE_BLOCK             = 1 << 7;
190
191    /**
192     * Flag this function as one that defines the identifier "arguments" as a function parameter or nested function
193     * name. This precludes it from needing to have an Arguments object defined as "arguments" local variable. Note that
194     * defining a local variable named "arguments" still requires construction of the Arguments object (see
195     * ECMAScript 5.1 Chapter 10.5).
196     * @see #needsArguments()
197     */
198    public static final int DEFINES_ARGUMENTS           = 1 << 8;
199
200    /** Does this function or any of its descendants use variables from an ancestor function's scope (incl. globals)? */
201    public static final int USES_ANCESTOR_SCOPE         = 1 << 9;
202
203    /** Does this function have nested declarations? */
204    public static final int HAS_FUNCTION_DECLARATIONS   = 1 << 10;
205
206    /** Does this function have optimistic expressions? (If it does, it can undergo deoptimizing recompilation.) */
207    public static final int IS_DEOPTIMIZABLE            = 1 << 11;
208
209    /** Are we vararg, but do we just pass the arguments along to apply or call */
210    public static final int HAS_APPLY_TO_CALL_SPECIALIZATION = 1 << 12;
211
212    /** Does this function explicitly use the {@link CompilerConstants#RETURN} symbol? Some functions are known to
213     * always use the return symbol, namely a function that is a program (as it must track its last executed expression
214     * statement's value) as well as functions that are split (to communicate return values from inner to outer
215     * partitions). Other functions normally don't use the return symbol (so we optimize away its slot), except in some
216     * very special cases, e.g. when containing a return statement in a finally block. These special cases set this
217     * flag. */
218    public static final int USES_RETURN_SYMBOL = 1 << 13;
219
220    /**
221     * Is this function the top-level program?
222     */
223    public static final int IS_PROGRAM = 1 << 14;
224
225    /**
226     * Flag indicating whether this function uses the local variable symbol for itself. Only named function expressions
227     * can have this flag set if they reference themselves (e.g. "(function f() { return f })". Declared functions will
228     * use the symbol in their parent scope instead when they reference themselves by name.
229     */
230    public static final int USES_SELF_SYMBOL = 1 << 15;
231
232    /** Does this function use the "this" keyword? */
233    public static final int USES_THIS = 1 << 16;
234
235    /** Is this declared in a dynamic context */
236    public static final int IN_DYNAMIC_CONTEXT = 1 << 17;
237
238    /**
239     * The following flags are derived from directive comments within this function.
240     * Note that even IS_STRICT is one such flag but that requires special handling.
241     */
242
243    /** parser, print parse tree */
244    public static final int IS_PRINT_PARSE       = 1 << 18;
245    /** parser, print lower parse tree */
246    public static final int IS_PRINT_LOWER_PARSE = 1 << 19;
247    /** parser, print AST */
248    public static final int IS_PRINT_AST         = 1 << 20;
249    /** parser, print lower AST */
250    public static final int IS_PRINT_LOWER_AST   = 1 << 21;
251    /** parser, print symbols */
252    public static final int IS_PRINT_SYMBOLS     = 1 << 22;
253
254    // callsite tracing, profiling within this function
255    /** profile callsites in this function? */
256    public static final int IS_PROFILE         = 1 << 23;
257
258    /** trace callsite enterexit in this function? */
259    public static final int IS_TRACE_ENTEREXIT = 1 << 24;
260
261    /** trace callsite misses in this function? */
262    public static final int IS_TRACE_MISSES    = 1 << 25;
263
264    /** trace callsite values in this function? */
265    public static final int IS_TRACE_VALUES    = 1 << 26;
266
267    /**
268     * Whether this function needs the callee {@link ScriptFunction} instance passed to its code as a
269     * parameter on invocation. Note that we aren't, in fact using this flag in function nodes.
270     * Rather, it is always calculated (see {@link #needsCallee()}). {@link RecompilableScriptFunctionData}
271     * will, however, cache the value of this flag.
272     */
273    public static final int NEEDS_CALLEE       = 1 << 27;
274
275    /** extension callsite flags mask */
276    public static final int EXTENSION_CALLSITE_FLAGS = IS_PRINT_PARSE |
277        IS_PRINT_LOWER_PARSE | IS_PRINT_AST | IS_PRINT_LOWER_AST |
278        IS_PRINT_SYMBOLS | IS_PROFILE | IS_TRACE_ENTEREXIT |
279        IS_TRACE_MISSES | IS_TRACE_VALUES;
280
281    /** Does this function or any nested functions contain an eval? */
282    private static final int HAS_DEEP_EVAL = HAS_EVAL | HAS_NESTED_EVAL;
283
284    /** Does this function need to store all its variables in scope? */
285    private static final int HAS_ALL_VARS_IN_SCOPE = HAS_DEEP_EVAL;
286
287    /** Does this function potentially need "arguments"? Note that this is not a full test, as further negative check of REDEFINES_ARGS is needed. */
288    private static final int MAYBE_NEEDS_ARGUMENTS = USES_ARGUMENTS | HAS_EVAL;
289
290    /** 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. */
291    private static final int NEEDS_PARENT_SCOPE = USES_ANCESTOR_SCOPE | HAS_DEEP_EVAL;
292
293    /** What is the return type of this function? */
294    private Type returnType = Type.UNKNOWN;
295
296    /**
297     * Constructor
298     *
299     * @param source     the source
300     * @param lineNumber line number
301     * @param token      token
302     * @param finish     finish
303     * @param firstToken first token of the function node (including the function declaration)
304     * @param lastToken  lastToken
305     * @param namespace  the namespace
306     * @param ident      the identifier
307     * @param name       the name of the function
308     * @param parameters parameter list
309     * @param kind       kind of function as in {@link FunctionNode.Kind}
310     * @param flags      initial flags
311     * @param body       body of the function
312     * @param state      The initial state from the parser. Must be one of {@link CompilationState#PARSED} and {@link CompilationState#PARSE_ERROR}
313     * @param endParserState The parser state at the end of the parsing.
314     */
315    public FunctionNode(
316        final Source source,
317        final int lineNumber,
318        final long token,
319        final int finish,
320        final long firstToken,
321        final long lastToken,
322        final Namespace namespace,
323        final IdentNode ident,
324        final String name,
325        final List<IdentNode> parameters,
326        final FunctionNode.Kind kind,
327        final int flags,
328        final Block body,
329        final CompilationState state,
330        final Object endParserState) {
331        super(token, finish);
332
333        this.source           = source;
334        this.lineNumber       = lineNumber;
335        this.ident            = ident;
336        this.name             = name;
337        this.kind             = kind;
338        this.parameters       = parameters;
339        this.firstToken       = firstToken;
340        this.lastToken        = lastToken;
341        this.namespace        = namespace;
342        this.compilationState = EnumSet.of(CompilationState.INITIALIZED, state);
343        this.flags            = flags;
344        this.compileUnit      = null;
345        this.body             = body;
346        this.thisProperties   = 0;
347        this.rootClass        = null;
348        this.endParserState    = endParserState;
349    }
350
351    private FunctionNode(
352        final FunctionNode functionNode,
353        final long lastToken,
354        final Object endParserState,
355        final int flags,
356        final String name,
357        final Type returnType,
358        final CompileUnit compileUnit,
359        final EnumSet<CompilationState> compilationState,
360        final Block body,
361        final List<IdentNode> parameters,
362        final int thisProperties,
363        final Class<?> rootClass) {
364        super(functionNode);
365
366        this.endParserState    = endParserState;
367        this.lineNumber       = functionNode.lineNumber;
368        this.flags            = flags;
369        this.name             = name;
370        this.returnType       = returnType;
371        this.compileUnit      = compileUnit;
372        this.lastToken        = lastToken;
373        this.compilationState = compilationState;
374        this.body             = body;
375        this.parameters       = parameters;
376        this.thisProperties   = thisProperties;
377        this.rootClass        = rootClass;
378
379        // the fields below never change - they are final and assigned in constructor
380        this.source          = functionNode.source;
381        this.ident           = functionNode.ident;
382        this.namespace       = functionNode.namespace;
383        this.kind            = functionNode.kind;
384        this.firstToken      = functionNode.firstToken;
385    }
386
387    @Override
388    public Node accept(final LexicalContext lc, final NodeVisitor<? extends LexicalContext> visitor) {
389        if (visitor.enterFunctionNode(this)) {
390            return visitor.leaveFunctionNode(setBody(lc, (Block)body.accept(visitor)));
391        }
392        return this;
393    }
394
395    /**
396     * Visits the parameter nodes of this function. Parameters are normally not visited automatically.
397     * @param visitor the visitor to apply to the nodes.
398     * @return a list of parameter nodes, potentially modified from original ones by the visitor.
399     */
400    public List<IdentNode> visitParameters(final NodeVisitor<? extends LexicalContext> visitor) {
401        return Node.accept(visitor, parameters);
402    }
403
404    /**
405     * Get additional callsite flags to be used specific to this function.
406     *
407     * @return callsite flags
408     */
409    public int getCallSiteFlags() {
410        int callsiteFlags = 0;
411        if (getFlag(IS_STRICT)) {
412            callsiteFlags |= CALLSITE_STRICT;
413        }
414
415        // quick check for extension callsite flags turned on by directives.
416        if ((flags & EXTENSION_CALLSITE_FLAGS) == 0) {
417            return callsiteFlags;
418        }
419
420        if (getFlag(IS_PROFILE)) {
421            callsiteFlags |= CALLSITE_PROFILE;
422        }
423
424        if (getFlag(IS_TRACE_MISSES)) {
425            callsiteFlags |= CALLSITE_TRACE | CALLSITE_TRACE_MISSES;
426        }
427
428        if (getFlag(IS_TRACE_VALUES)) {
429            callsiteFlags |= CALLSITE_TRACE | CALLSITE_TRACE_ENTEREXIT | CALLSITE_TRACE_VALUES;
430        }
431
432        if (getFlag(IS_TRACE_ENTEREXIT)) {
433            callsiteFlags |= CALLSITE_TRACE | CALLSITE_TRACE_ENTEREXIT;
434        }
435
436        return callsiteFlags;
437    }
438
439    /**
440     * Get the source for this function
441     * @return the source
442     */
443    public Source getSource() {
444        return source;
445    }
446
447    /**
448     * Get the unique ID for this function within the script file.
449     * @return the id
450     */
451    public int getId() {
452        return isProgram() ? -1: Token.descPosition(firstToken);
453    }
454
455    /**
456     * get source name - sourceURL or name derived from Source.
457     *
458     * @return name for the script source
459     */
460    public String getSourceName() {
461        return getSourceName(source);
462    }
463
464    /**
465     * Static source name getter
466     *
467     * @param source the source
468     * @return source name
469     */
470    public static String getSourceName(final Source source) {
471        final String explicitURL = source.getExplicitURL();
472        return explicitURL != null ? explicitURL : source.getName();
473    }
474
475    /**
476     * Function to parse nashorn per-function extension directive comments.
477     *
478     * @param directive nashorn extension directive string
479     * @return integer flag for the given directive.
480     */
481    public static int getDirectiveFlag(final String directive) {
482        switch (directive) {
483            case "nashorn callsite trace enterexit":
484                return IS_TRACE_ENTEREXIT;
485            case "nashorn callsite trace misses":
486                return IS_TRACE_MISSES;
487            case "nashorn callsite trace objects":
488                return IS_TRACE_VALUES;
489            case "nashorn callsite profile":
490                return IS_PROFILE;
491            case "nashorn print parse":
492                return IS_PRINT_PARSE;
493            case "nashorn print lower parse":
494                return IS_PRINT_LOWER_PARSE;
495            case "nashorn print ast":
496                return IS_PRINT_AST;
497            case "nashorn print lower ast":
498                return IS_PRINT_LOWER_AST;
499            case "nashorn print symbols":
500                return IS_PRINT_SYMBOLS;
501            default:
502                // unknown/unsupported directive
503                return 0;
504        }
505    }
506
507    /**
508     * Returns the line number.
509     * @return the line number.
510     */
511    public int getLineNumber() {
512        return lineNumber;
513    }
514
515    /**
516     * Get the compilation state of this function
517     * @return the compilation state
518     */
519    public EnumSet<CompilationState> getState() {
520        return compilationState;
521    }
522
523    /**
524     * Check whether this FunctionNode has reached a give CompilationState.
525     *
526     * @param state the state to check for
527     * @return true of the node is in the given state
528     */
529    public boolean hasState(final EnumSet<CompilationState> state) {
530        return !AssertsEnabled.assertsEnabled() || compilationState.containsAll(state);
531    }
532
533    /**
534     * Add a state to the total CompilationState of this node, e.g. if
535     * FunctionNode has been lowered, the compiler will add
536     * {@code CompilationState#LOWERED} to the state vector
537     *
538     * @param lc lexical context
539     * @param state {@link CompilationState} to add
540     * @return function node or a new one if state was changed
541     */
542    public FunctionNode setState(final LexicalContext lc, final CompilationState state) {
543        if (!AssertsEnabled.assertsEnabled() || this.compilationState.contains(state)) {
544            return this;
545        }
546        final EnumSet<CompilationState> newState = EnumSet.copyOf(this.compilationState);
547        newState.add(state);
548        return Node.replaceInLexicalContext(
549                lc,
550                this,
551                new FunctionNode(
552                        this,
553                        lastToken,
554                        endParserState,
555                        flags,
556                        name,
557                        returnType,
558                        compileUnit,
559                        newState,
560                        body,
561                        parameters,
562                        thisProperties,
563                        rootClass));
564    }
565
566    /**
567     * Create a unique name in the namespace of this FunctionNode
568     * @param base prefix for name
569     * @return base if no collision exists, otherwise a name prefix with base
570     */
571    public String uniqueName(final String base) {
572        return namespace.uniqueName(base);
573    }
574
575    @Override
576    public void toString(final StringBuilder sb, final boolean printTypes) {
577        sb.append('[').
578            append(returnType).
579            append(']').
580            append(' ');
581
582        sb.append("function");
583
584        if (ident != null) {
585            sb.append(' ');
586            ident.toString(sb, printTypes);
587        }
588
589        sb.append('(');
590
591        for (final Iterator<IdentNode> iter = parameters.iterator(); iter.hasNext(); ) {
592            final IdentNode parameter = iter.next();
593            if (parameter.getSymbol() != null) {
594                sb.append('[').append(parameter.getType()).append(']').append(' ');
595            }
596            parameter.toString(sb, printTypes);
597            if (iter.hasNext()) {
598                sb.append(", ");
599            }
600        }
601
602        sb.append(')');
603    }
604
605    @Override
606    public int getFlags() {
607        return flags;
608    }
609
610    @Override
611    public boolean getFlag(final int flag) {
612        return (flags & flag) != 0;
613    }
614
615    @Override
616    public FunctionNode setFlags(final LexicalContext lc, final int flags) {
617        if (this.flags == flags) {
618            return this;
619        }
620        return Node.replaceInLexicalContext(
621                lc,
622                this,
623                new FunctionNode(
624                        this,
625                        lastToken,
626                        endParserState,
627                        flags,
628                        name,
629                        returnType,
630                        compileUnit,
631                        compilationState,
632                        body,
633                        parameters,
634                        thisProperties,
635                        rootClass));
636    }
637
638    @Override
639    public FunctionNode clearFlag(final LexicalContext lc, final int flag) {
640        return setFlags(lc, flags & ~flag);
641    }
642
643    @Override
644    public FunctionNode setFlag(final LexicalContext lc, final int flag) {
645        return setFlags(lc, flags | flag);
646    }
647
648    /**
649     * Returns true if the function is the top-level program.
650     * @return True if this function node represents the top-level program.
651     */
652    public boolean isProgram() {
653        return getFlag(IS_PROGRAM);
654    }
655
656    /**
657     * Returns true if the function contains at least one optimistic operation (and thus can be deoptimized).
658     * @return true if the function contains at least one optimistic operation (and thus can be deoptimized).
659     */
660    public boolean canBeDeoptimized() {
661        return getFlag(IS_DEOPTIMIZABLE);
662    }
663
664    /**
665     * Check if this function has a call expression for the identifier "eval" (that is, {@code eval(...)}).
666     *
667     * @return true if {@code eval} is called.
668     */
669    public boolean hasEval() {
670        return getFlag(HAS_EVAL);
671    }
672
673    /**
674     * Returns true if a function nested (directly or transitively) within this function {@link #hasEval()}.
675     *
676     * @return true if a nested function calls {@code eval}.
677     */
678    public boolean hasNestedEval() {
679        return getFlag(HAS_NESTED_EVAL);
680    }
681
682    /**
683     * Get the first token for this function
684     * @return the first token
685     */
686    public long getFirstToken() {
687        return firstToken;
688    }
689
690    /**
691     * Check whether this function has nested function declarations
692     * @return true if nested function declarations exist
693     */
694    public boolean hasDeclaredFunctions() {
695        return getFlag(HAS_FUNCTION_DECLARATIONS);
696    }
697
698    /**
699     * Check if this function's generated Java method needs a {@code callee} parameter. Functions that need access to
700     * their parent scope, functions that reference themselves, and non-strict functions that need an Arguments object
701     * (since it exposes {@code arguments.callee} property) will need to have a callee parameter. We also return true
702     * for split functions to make sure symbols slots are the same in the main and split methods.
703     *
704     * A function that has had an apply(this,arguments) turned into a call doesn't need arguments anymore, but still
705     * has to fit the old callsite, thus, we require a dummy callee parameter for those functions as well
706     *
707     * @return true if the function's generated Java method needs a {@code callee} parameter.
708     */
709    public boolean needsCallee() {
710        return needsParentScope() || usesSelfSymbol() || isSplit() || (needsArguments() && !isStrict()) || hasOptimisticApplyToCall();
711    }
712
713    /**
714     * Check if this function uses the return symbol
715     * @return true if uses the return symbol
716     */
717    public boolean usesReturnSymbol() {
718        return isProgram() || isSplit() || getFlag(USES_RETURN_SYMBOL);
719    }
720
721    /**
722     * Return {@code true} if this function makes use of the {@code this} object.
723     *
724     * @return true if function uses {@code this} object
725     */
726    public boolean usesThis() {
727        return getFlag(USES_THIS);
728    }
729
730
731    /**
732     * Return true if function contains an apply to call transform
733     * @return true if this function has transformed apply to call
734     */
735    public boolean hasOptimisticApplyToCall() {
736        return getFlag(HAS_APPLY_TO_CALL_SPECIALIZATION);
737    }
738
739    /**
740     * Get the identifier for this function, this is its symbol.
741     * @return the identifier as an IdentityNode
742     */
743    public IdentNode getIdent() {
744        return ident;
745    }
746
747    /**
748     * Get the function body
749     * @return the function body
750     */
751    public Block getBody() {
752        return body;
753    }
754
755    /**
756     * Reset the function body
757     * @param lc lexical context
758     * @param body new body
759     * @return new function node if body changed, same if not
760     */
761    public FunctionNode setBody(final LexicalContext lc, final Block body) {
762        if (this.body == body) {
763            return this;
764        }
765        return Node.replaceInLexicalContext(
766                lc,
767                this,
768                new FunctionNode(
769                        this,
770                        lastToken,
771                        endParserState,
772                        flags |
773                            (body.needsScope() ?
774                                    FunctionNode.HAS_SCOPE_BLOCK :
775                                    0),
776                        name,
777                        returnType,
778                        compileUnit,
779                        compilationState,
780                        body,
781                        parameters,
782                        thisProperties,
783                        rootClass));
784    }
785
786    /**
787     * Does this function's method needs to be variable arity (gather all script-declared parameters in a final
788     * {@code Object[]} parameter. Functions that need to have the "arguments" object as well as functions that simply
789     * declare too many arguments for JVM to handle with fixed arity will need to be variable arity.
790     * @return true if the Java method in the generated code that implements this function needs to be variable arity.
791     * @see #needsArguments()
792     * @see LinkerCallSite#ARGLIMIT
793     */
794    public boolean isVarArg() {
795        return needsArguments() || parameters.size() > LinkerCallSite.ARGLIMIT;
796    }
797
798    /**
799     * Was this function declared in a dynamic context, i.e. in a with or eval style
800     * chain
801     * @return true if in dynamic context
802     */
803    public boolean inDynamicContext() {
804        return getFlag(IN_DYNAMIC_CONTEXT);
805    }
806
807    /**
808     * Check whether a function would need dynamic scope, which is does if it has
809     * evals and isn't strict.
810     * @return true if dynamic scope is needed
811     */
812    public boolean needsDynamicScope() {
813        // Function has a direct eval in it (so a top-level "var ..." in the eval code can introduce a new
814        // variable into the function's scope), and it isn't strict (as evals in strict functions get an
815        // isolated scope).
816        return hasEval() && !isStrict();
817    }
818
819    /**
820     * Flag this function as declared in a dynamic context
821     * @param lc lexical context
822     * @return new function node, or same if unmodified
823     */
824    public FunctionNode setInDynamicContext(final LexicalContext lc) {
825        return setFlag(lc, IN_DYNAMIC_CONTEXT);
826    }
827
828    /**
829     * Returns true if this function needs to have an Arguments object defined as a local variable named "arguments".
830     * Functions that use "arguments" as identifier and don't define it as a name of a parameter or a nested function
831     * (see ECMAScript 5.1 Chapter 10.5), as well as any function that uses eval or with, or has a nested function that
832     * does the same, will have an "arguments" object. Also, if this function is a script, it will not have an
833     * "arguments" object, because it does not have local variables; rather the Global object will have an explicit
834     * "arguments" property that provides command-line arguments for the script.
835     * @return true if this function needs an arguments object.
836     */
837    public boolean needsArguments() {
838        // uses "arguments" or calls eval, but it does not redefine "arguments", and finally, it's not a script, since
839        // for top-level script, "arguments" is picked up from Context by Global.init() instead.
840        return getFlag(MAYBE_NEEDS_ARGUMENTS) && !getFlag(DEFINES_ARGUMENTS) && !isProgram();
841    }
842
843    /**
844     * Returns true if this function needs access to its parent scope. Functions referencing variables outside their
845     * scope (including global variables), as well as functions that call eval or have a with block, or have nested
846     * functions that call eval or have a with block, will need a parent scope. Top-level script functions also need a
847     * parent scope since they might be used from within eval, and eval will need an externally passed scope.
848     * @return true if the function needs parent scope.
849     */
850    public boolean needsParentScope() {
851        return getFlag(NEEDS_PARENT_SCOPE) || isProgram();
852    }
853
854    /**
855     * Set the number of properties assigned to the this object in this function.
856     * @param lc the current lexical context.
857     * @param thisProperties number of properties
858     * @return a potentially modified function node
859     */
860    public FunctionNode setThisProperties(final LexicalContext lc, final int thisProperties) {
861        if (this.thisProperties == thisProperties) {
862            return this;
863        }
864        return Node.replaceInLexicalContext(
865                lc,
866                this,
867                new FunctionNode(
868                        this,
869                        lastToken,
870                        endParserState,
871                        flags,
872                        name,
873                        returnType,
874                        compileUnit,
875                        compilationState,
876                        body,
877                        parameters,
878                        thisProperties,
879                        rootClass));
880    }
881
882    /**
883     * Get the number of properties assigned to the this object in this function.
884     * @return number of properties
885     */
886    public int getThisProperties() {
887        return thisProperties;
888    }
889
890    /**
891     * Returns true if any of the blocks in this function create their own scope.
892     * @return true if any of the blocks in this function create their own scope.
893     */
894    public boolean hasScopeBlock() {
895        return getFlag(HAS_SCOPE_BLOCK);
896    }
897
898    /**
899     * Return the kind of this function
900     * @see FunctionNode.Kind
901     * @return the kind
902     */
903    public Kind getKind() {
904        return kind;
905    }
906
907    /**
908     * Return the last token for this function's code
909     * @return last token
910     */
911    public long getLastToken() {
912        return lastToken;
913    }
914
915    /**
916     * Returns the end parser state for this function.
917     * @return the end parser state for this function.
918     */
919    public Object getEndParserState() {
920        return endParserState;
921    }
922
923    /**
924     * Get the name of this function
925     * @return the name
926     */
927    public String getName() {
928        return name;
929    }
930
931    /**
932     * Set the internal name for this function
933     * @param lc    lexical context
934     * @param name new name
935     * @return new function node if changed, otherwise the same
936     */
937    public FunctionNode setName(final LexicalContext lc, final String name) {
938        if (this.name.equals(name)) {
939            return this;
940        }
941        return Node.replaceInLexicalContext(
942                lc,
943                this,
944                new FunctionNode(
945                        this,
946                        lastToken,
947                        endParserState,
948                        flags,
949                        name,
950                        returnType,
951                        compileUnit,
952                        compilationState,
953                        body,
954                        parameters,
955                        thisProperties,
956                        rootClass));
957    }
958
959    /**
960     * Check if this function should have all its variables in its own scope. Split sub-functions, and
961     * functions having with and/or eval blocks are such.
962     *
963     * @return true if all variables should be in scope
964     */
965    public boolean allVarsInScope() {
966        return getFlag(HAS_ALL_VARS_IN_SCOPE);
967    }
968
969    /**
970     * Checks if this function is a sub-function generated by splitting a larger one
971     *
972     * @return true if this function is split from a larger one
973     */
974    public boolean isSplit() {
975        return getFlag(IS_SPLIT);
976    }
977
978    /**
979     * Get the parameters to this function
980     * @return a list of IdentNodes which represent the function parameters, in order
981     */
982    public List<IdentNode> getParameters() {
983        return Collections.unmodifiableList(parameters);
984    }
985
986    /**
987     * Returns the identifier for a named parameter at the specified position in this function's parameter list.
988     * @param index the parameter's position.
989     * @return the identifier for the requested named parameter.
990     * @throws IndexOutOfBoundsException if the index is invalid.
991     */
992    public IdentNode getParameter(final int index) {
993        return parameters.get(index);
994    }
995
996    /**
997     * Reset the compile unit used to compile this function
998     * @see Compiler
999     * @param  lc lexical context
1000     * @param  parameters the compile unit
1001     * @return function node or a new one if state was changed
1002     */
1003    public FunctionNode setParameters(final LexicalContext lc, final List<IdentNode> parameters) {
1004        if (this.parameters == parameters) {
1005            return this;
1006        }
1007        return Node.replaceInLexicalContext(
1008                lc,
1009                this,
1010                new FunctionNode(
1011                        this,
1012                        lastToken,
1013                        endParserState,
1014                        flags,
1015                        name,
1016                        returnType,
1017                        compileUnit,
1018                        compilationState,
1019                        body,
1020                        parameters,
1021                        thisProperties,
1022                        rootClass));
1023    }
1024
1025    /**
1026     * Check if this function is created as a function declaration (as opposed to function expression)
1027     * @return true if function is declared.
1028     */
1029    public boolean isDeclared() {
1030        return getFlag(IS_DECLARED);
1031    }
1032
1033    /**
1034     * Check if this function is anonymous
1035     * @return true if function is anonymous
1036     */
1037    public boolean isAnonymous() {
1038        return getFlag(IS_ANONYMOUS);
1039    }
1040
1041    /**
1042     * Does this function use its self symbol - this is needed only for self-referencing named function expressions.
1043     * Self-referencing declared functions won't have this flag set, as they can access their own symbol through the
1044     * scope (since they're bound to the symbol with their name in their enclosing scope).
1045     * @return true if this function node is a named function expression that uses the symbol for itself.
1046     */
1047    public boolean usesSelfSymbol() {
1048        return getFlag(USES_SELF_SYMBOL);
1049    }
1050
1051    @Override
1052    public Type getType(final Function<Symbol, Type> localVariableTypes) {
1053        return FUNCTION_TYPE;
1054    }
1055
1056    @Override
1057    public Type getWidestOperationType() {
1058        return FUNCTION_TYPE;
1059    }
1060
1061    /**
1062     * Get the return type for this function. Return types can be specialized
1063     * if the compiler knows them, but parameters cannot, as they need to go through
1064     * appropriate object conversion
1065     *
1066     * @return the return type
1067     */
1068    public Type getReturnType() {
1069        return returnType;
1070    }
1071
1072    /**
1073     * Set the function return type
1074     * @param lc lexical context
1075     * @param returnType new return type
1076     * @return function node or a new one if state was changed
1077     */
1078    public FunctionNode setReturnType(final LexicalContext lc, final Type returnType) {
1079        //we never bother with object types narrower than objects, that will lead to byte code verification errors
1080        //as for instance even if we know we are returning a string from a method, the code generator will always
1081        //treat it as an object, at least for now
1082        final Type type = returnType.isObject() ? Type.OBJECT : returnType;
1083        if (this.returnType == type) {
1084            return this;
1085        }
1086        return Node.replaceInLexicalContext(
1087            lc,
1088            this,
1089            new FunctionNode(
1090                this,
1091                lastToken,
1092                endParserState,
1093                flags,
1094                name,
1095                type,
1096                compileUnit,
1097                compilationState,
1098                body,
1099                parameters,
1100                thisProperties,
1101                rootClass
1102                ));
1103   }
1104
1105    /**
1106     * Check if the function is generated in strict mode
1107     * @return true if strict mode enabled for function
1108     */
1109    public boolean isStrict() {
1110        return getFlag(IS_STRICT);
1111    }
1112
1113    /**
1114     * Get the compile unit used to compile this function
1115     * @see Compiler
1116     * @return the compile unit
1117     */
1118    @Override
1119    public CompileUnit getCompileUnit() {
1120        return compileUnit;
1121    }
1122
1123    /**
1124     * Reset the compile unit used to compile this function
1125     * @see Compiler
1126     * @param lc lexical context
1127     * @param compileUnit the compile unit
1128     * @return function node or a new one if state was changed
1129     */
1130    public FunctionNode setCompileUnit(final LexicalContext lc, final CompileUnit compileUnit) {
1131        if (this.compileUnit == compileUnit) {
1132            return this;
1133        }
1134        return Node.replaceInLexicalContext(
1135                lc,
1136                this,
1137                new FunctionNode(
1138                        this,
1139                        lastToken,
1140                        endParserState,
1141                        flags,
1142                        name,
1143                        returnType,
1144                        compileUnit,
1145                        compilationState,
1146                        body,
1147                        parameters,
1148                        thisProperties,
1149                        rootClass));
1150    }
1151
1152    /**
1153     * Create a temporary variable to the current frame.
1154     *
1155     * @param block that needs the temporary
1156     * @param type  Strong type of symbol.
1157     * @param node  Primary node to use symbol.
1158     *
1159     * @return Symbol used.
1160     */
1161
1162    /**
1163     * Get the symbol for a compiler constant, or null if not available (yet)
1164     * @param cc compiler constant
1165     * @return symbol for compiler constant, or null if not defined yet (for example in Lower)
1166     */
1167    public Symbol compilerConstant(final CompilerConstants cc) {
1168        return body.getExistingSymbol(cc.symbolName());
1169    }
1170
1171    /**
1172     * Get the root class that this function node compiles to
1173     * @return root class
1174     */
1175    public Class<?> getRootClass() {
1176        return rootClass;
1177    }
1178
1179    /**
1180     * Reset the root class that this function is compiled to
1181     * @see Compiler
1182     * @param lc lexical context
1183     * @param rootClass root class
1184     * @return function node or a new one if state was changed
1185     */
1186    public FunctionNode setRootClass(final LexicalContext lc, final Class<?> rootClass) {
1187        if (this.rootClass == rootClass) {
1188            return this;
1189        }
1190        return Node.replaceInLexicalContext(
1191                lc,
1192                this,
1193                new FunctionNode(
1194                        this,
1195                        lastToken,
1196                        endParserState,
1197                        flags,
1198                        name,
1199                        returnType,
1200                        compileUnit,
1201                        compilationState,
1202                        body,
1203                        parameters,
1204                        thisProperties,
1205                        rootClass));
1206    }
1207}
1208