FunctionNode.java revision 1668:bafd733be429
1/*
2 * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package jdk.nashorn.internal.ir;
27
28import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_PROFILE;
29import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_STRICT;
30import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_TRACE;
31import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_TRACE_ENTEREXIT;
32import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_TRACE_MISSES;
33import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_TRACE_VALUES;
34
35import java.util.Collections;
36import java.util.Iterator;
37import java.util.List;
38import jdk.nashorn.internal.codegen.CompileUnit;
39import jdk.nashorn.internal.codegen.Compiler;
40import jdk.nashorn.internal.codegen.CompilerConstants;
41import jdk.nashorn.internal.codegen.Namespace;
42import jdk.nashorn.internal.codegen.types.Type;
43import jdk.nashorn.internal.ir.annotations.Ignore;
44import jdk.nashorn.internal.ir.annotations.Immutable;
45import jdk.nashorn.internal.ir.visitor.NodeVisitor;
46import jdk.nashorn.internal.parser.Token;
47import jdk.nashorn.internal.runtime.RecompilableScriptFunctionData;
48import jdk.nashorn.internal.runtime.ScriptFunction;
49import jdk.nashorn.internal.runtime.Source;
50import jdk.nashorn.internal.runtime.UserAccessorProperty;
51import jdk.nashorn.internal.runtime.linker.LinkerCallSite;
52
53/**
54 * IR representation for function (or script.)
55 */
56@Immutable
57public final class FunctionNode extends LexicalContextExpression implements Flags<FunctionNode>, CompileUnitHolder {
58    private static final long serialVersionUID = 1L;
59
60    /** Type used for all FunctionNodes */
61    public static final Type FUNCTION_TYPE = Type.typeFor(ScriptFunction.class);
62
63    /** Function kinds */
64    public enum Kind {
65        /** a normal function - nothing special */
66        NORMAL,
67        /** a script function */
68        SCRIPT,
69        /** a getter, @see {@link UserAccessorProperty} */
70        GETTER,
71        /** a setter, @see {@link UserAccessorProperty} */
72        SETTER,
73        /** an arrow function */
74        ARROW,
75        /** a generator function */
76        GENERATOR,
77        /** a module function */
78        MODULE
79    }
80
81    /** Source of entity. */
82    private transient final Source source;
83
84    /**
85     * Opaque object representing parser state at the end of the function. Used when reparsing outer functions
86     * to skip parsing inner functions.
87     */
88    private final Object endParserState;
89
90    /** External function identifier. */
91    @Ignore
92    private final IdentNode ident;
93
94    /** The body of the function node */
95    private final Block body;
96
97    /** Internal function name. */
98    private final String name;
99
100    /** Compilation unit. */
101    private final CompileUnit compileUnit;
102
103    /** Function kind. */
104    private final Kind kind;
105
106    /** List of parameters. */
107    private final List<IdentNode> parameters;
108
109    /** First token of function. **/
110    private final long firstToken;
111
112    /** Last token of function. **/
113    private final long lastToken;
114
115    /** Method's namespace. */
116    private transient final Namespace namespace;
117
118    /** Number of properties of "this" object assigned in this function */
119    @Ignore
120    private final int thisProperties;
121
122    /** Function flags. */
123    private final int flags;
124
125    /** Line number of function start */
126    private final int lineNumber;
127
128    /** Root class for function */
129    private final Class<?> rootClass;
130
131    /** The ES6 module */
132    private final Module module;
133
134    /** The debug flags */
135    private final int debugFlags;
136
137    /** Is anonymous function flag. */
138    public static final int IS_ANONYMOUS                = 1 << 0;
139
140    /** Is the function created in a function declaration (as opposed to a function expression) */
141    public static final int IS_DECLARED                 = 1 << 1;
142
143    /** is this a strict mode function? */
144    public static final int IS_STRICT                   = 1 << 2;
145
146    /** Does the function use the "arguments" identifier ? */
147    public static final int USES_ARGUMENTS              = 1 << 3;
148
149    /** Has this function been split because it was too large? */
150    public static final int IS_SPLIT                    = 1 << 4;
151
152    /** Does the function call eval? If it does, then all variables in this function might be get/set by it and it can
153     * introduce new variables into this function's scope too.*/
154    public static final int HAS_EVAL                    = 1 << 5;
155
156    /** Does a nested function contain eval? If it does, then all variables in this function might be get/set by it. */
157    public static final int HAS_NESTED_EVAL             = 1 << 6;
158
159    /** Does this function have any blocks that create a scope? This is used to determine if the function needs to
160     * have a local variable slot for the scope symbol. */
161    public static final int HAS_SCOPE_BLOCK             = 1 << 7;
162
163    /**
164     * Flag this function as one that defines the identifier "arguments" as a function parameter or nested function
165     * name. This precludes it from needing to have an Arguments object defined as "arguments" local variable. Note that
166     * defining a local variable named "arguments" still requires construction of the Arguments object (see
167     * ECMAScript 5.1 Chapter 10.5).
168     * @see #needsArguments()
169     */
170    public static final int DEFINES_ARGUMENTS           = 1 << 8;
171
172    /** Does this function or any of its descendants use variables from an ancestor function's scope (incl. globals)? */
173    public static final int USES_ANCESTOR_SCOPE         = 1 << 9;
174
175    /** Does this function have nested declarations? */
176    public static final int HAS_FUNCTION_DECLARATIONS   = 1 << 10;
177
178    /** Does this function have optimistic expressions? (If it does, it can undergo deoptimizing recompilation.) */
179    public static final int IS_DEOPTIMIZABLE            = 1 << 11;
180
181    /** Are we vararg, but do we just pass the arguments along to apply or call */
182    public static final int HAS_APPLY_TO_CALL_SPECIALIZATION = 1 << 12;
183
184    /**
185     * Is this function the top-level program?
186     */
187    public static final int IS_PROGRAM                  = 1 << 13;
188
189    /**
190     * Flag indicating whether this function uses the local variable symbol for itself. Only named function expressions
191     * can have this flag set if they reference themselves (e.g. "(function f() { return f })". Declared functions will
192     * use the symbol in their parent scope instead when they reference themselves by name.
193     */
194    public static final int USES_SELF_SYMBOL            = 1 << 14;
195
196    /** Does this function use the "this" keyword? */
197    public static final int USES_THIS                   = 1 << 15;
198
199    /** Is this declared in a dynamic context */
200    public static final int IN_DYNAMIC_CONTEXT          = 1 << 16;
201
202
203    /**
204     * Whether this function needs the callee {@link ScriptFunction} instance passed to its code as a
205     * parameter on invocation. Note that we aren't, in fact using this flag in function nodes.
206     * Rather, it is always calculated (see {@link #needsCallee()}). {@link RecompilableScriptFunctionData}
207     * will, however, cache the value of this flag.
208     */
209    public static final int NEEDS_CALLEE                = 1 << 17;
210
211    /**
212     * Is the function node cached?
213     */
214    public static final int IS_CACHED                   = 1 << 18;
215
216    /**
217     * Does this function contain a super call? (cf. ES6 14.3.5 Static Semantics: HasDirectSuper)
218     */
219    public static final int ES6_HAS_DIRECT_SUPER        = 1 << 19;
220
221    /**
222     * Does this function use the super binding?
223     */
224    public static final int ES6_USES_SUPER              = 1 << 20;
225
226    /**
227     * Is this function a (class or object) method?
228     */
229    public static final int ES6_IS_METHOD               = 1 << 21;
230
231    /**
232     * Is this the constructor method?
233     */
234    public static final int ES6_IS_CLASS_CONSTRUCTOR    = 1 << 22;
235
236    /** Is this the constructor of a subclass (i.e., a class with an extends declaration)? */
237    public static final int ES6_IS_SUBCLASS_CONSTRUCTOR = 1 << 23;
238
239    /** is this a strong mode function? */
240    public static final int ES6_IS_STRONG               = 1 << 24;
241
242    /** Does this function use new.target? */
243    public static final int ES6_USES_NEW_TARGET         = 1 << 25;
244
245    /** Does this function or any nested functions contain an eval? */
246    private static final int HAS_DEEP_EVAL = HAS_EVAL | HAS_NESTED_EVAL;
247
248    /** Does this function need to store all its variables in scope? */
249    public static final int HAS_ALL_VARS_IN_SCOPE = HAS_DEEP_EVAL;
250
251    /** Does this function potentially need "arguments"? Note that this is not a full test, as further negative check of REDEFINES_ARGS is needed. */
252    private static final int MAYBE_NEEDS_ARGUMENTS = USES_ARGUMENTS | HAS_EVAL;
253
254    /** 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. */
255    public static final int NEEDS_PARENT_SCOPE = USES_ANCESTOR_SCOPE | HAS_DEEP_EVAL | IS_PROGRAM;
256
257
258    /**
259     * The following flags are derived from directive comments within this function.
260     * Note that even IS_STRICT is one such flag but that requires special handling.
261     */
262
263    /** parser, print parse tree */
264    public static final int DEBUG_PRINT_PARSE       = 1 << 0;
265    /** parser, print lower parse tree */
266    public static final int DEBUG_PRINT_LOWER_PARSE = 1 << 1;
267    /** parser, print AST */
268    public static final int DEBUG_PRINT_AST         = 1 << 2;
269    /** parser, print lower AST */
270    public static final int DEBUG_PRINT_LOWER_AST   = 1 << 3;
271    /** parser, print symbols */
272    public static final int DEBUG_PRINT_SYMBOLS     = 1 << 4;
273
274    // callsite tracing, profiling within this function
275    /** profile callsites in this function? */
276    public static final int DEBUG_PROFILE           = 1 << 5;
277
278    /** trace callsite enterexit in this function? */
279    public static final int DEBUG_TRACE_ENTEREXIT   = 1 << 6;
280
281    /** trace callsite misses in this function? */
282    public static final int DEBUG_TRACE_MISSES      = 1 << 7;
283
284    /** trace callsite values in this function? */
285    public static final int DEBUG_TRACE_VALUES      = 1 << 8;
286
287    /** extension callsite flags mask */
288    public static final int DEBUG_CALLSITE_FLAGS = DEBUG_PRINT_PARSE |
289            DEBUG_PRINT_LOWER_PARSE | DEBUG_PRINT_AST | DEBUG_PRINT_LOWER_AST |
290            DEBUG_PRINT_SYMBOLS | DEBUG_PROFILE | DEBUG_TRACE_ENTEREXIT |
291            DEBUG_TRACE_MISSES | DEBUG_TRACE_VALUES;
292
293    /** What is the return type of this function? */
294    public 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 endParserState The parser state at the end of the parsing.
313     * @param module     the module
314     * @param debugFlags the debug flags
315     */
316    public FunctionNode(
317        final Source source,
318        final int lineNumber,
319        final long token,
320        final int finish,
321        final long firstToken,
322        final long lastToken,
323        final Namespace namespace,
324        final IdentNode ident,
325        final String name,
326        final List<IdentNode> parameters,
327        final FunctionNode.Kind kind,
328        final int flags,
329        final Block body,
330        final Object endParserState,
331        final Module module,
332        final int debugFlags) {
333        super(token, finish);
334
335        this.source           = source;
336        this.lineNumber       = lineNumber;
337        this.ident            = ident;
338        this.name             = name;
339        this.kind             = kind;
340        this.parameters       = parameters;
341        this.firstToken       = firstToken;
342        this.lastToken        = lastToken;
343        this.namespace        = namespace;
344        this.flags            = flags;
345        this.compileUnit      = null;
346        this.body             = body;
347        this.thisProperties   = 0;
348        this.rootClass        = null;
349        this.endParserState   = endParserState;
350        this.module           = module;
351        this.debugFlags       = debugFlags;
352    }
353
354    private FunctionNode(
355        final FunctionNode functionNode,
356        final long lastToken,
357        final Object endParserState,
358        final int flags,
359        final String name,
360        final Type returnType,
361        final CompileUnit compileUnit,
362        final Block body,
363        final List<IdentNode> parameters,
364        final int thisProperties,
365        final Class<?> rootClass,
366        final Source source, final Namespace namespace) {
367        super(functionNode);
368
369        this.endParserState    = endParserState;
370        this.lineNumber       = functionNode.lineNumber;
371        this.flags            = flags;
372        this.name             = name;
373        this.returnType       = returnType;
374        this.compileUnit      = compileUnit;
375        this.lastToken        = lastToken;
376        this.body             = body;
377        this.parameters       = parameters;
378        this.thisProperties   = thisProperties;
379        this.rootClass        = rootClass;
380        this.source           = source;
381        this.namespace        = namespace;
382
383        // the fields below never change - they are final and assigned in constructor
384        this.ident           = functionNode.ident;
385        this.kind            = functionNode.kind;
386        this.firstToken      = functionNode.firstToken;
387        this.module          = functionNode.module;
388        this.debugFlags      = functionNode.debugFlags;
389    }
390
391    @Override
392    public Node accept(final LexicalContext lc, final NodeVisitor<? extends LexicalContext> visitor) {
393        if (visitor.enterFunctionNode(this)) {
394            return visitor.leaveFunctionNode(setBody(lc, (Block)body.accept(visitor)));
395        }
396        return this;
397    }
398
399    /**
400     * Visits the parameter nodes of this function. Parameters are normally not visited automatically.
401     * @param visitor the visitor to apply to the nodes.
402     * @return a list of parameter nodes, potentially modified from original ones by the visitor.
403     */
404    public List<IdentNode> visitParameters(final NodeVisitor<? extends LexicalContext> visitor) {
405        return Node.accept(visitor, parameters);
406    }
407
408    /**
409     * Get additional callsite flags to be used specific to this function.
410     *
411     * @return callsite flags
412     */
413    public int getCallSiteFlags() {
414        int callsiteFlags = 0;
415        if (getFlag(IS_STRICT)) {
416            callsiteFlags |= CALLSITE_STRICT;
417        }
418
419        // quick check for extension callsite flags turned on by directives.
420        if ((debugFlags & DEBUG_CALLSITE_FLAGS) == 0) {
421            return callsiteFlags;
422        }
423
424        if (getDebugFlag(DEBUG_PROFILE)) {
425            callsiteFlags |= CALLSITE_PROFILE;
426        }
427
428        if (getDebugFlag(DEBUG_TRACE_MISSES)) {
429            callsiteFlags |= CALLSITE_TRACE | CALLSITE_TRACE_MISSES;
430        }
431
432        if (getDebugFlag(DEBUG_TRACE_VALUES)) {
433            callsiteFlags |= CALLSITE_TRACE | CALLSITE_TRACE_ENTEREXIT | CALLSITE_TRACE_VALUES;
434        }
435
436        if (getDebugFlag(DEBUG_TRACE_ENTEREXIT)) {
437            callsiteFlags |= CALLSITE_TRACE | CALLSITE_TRACE_ENTEREXIT;
438        }
439
440        return callsiteFlags;
441    }
442
443    /**
444     * Get the source for this function
445     * @return the source
446     */
447    public Source getSource() {
448        return source;
449    }
450
451    /**
452     * Sets the source and namespace for this function. It can only set a non-null source and namespace for a function
453     * that currently has both a null source and a null namespace. This is used to re-set the source and namespace for
454     * a deserialized function node.
455     * @param source the source for the function.
456     * @param namespace the namespace for the function
457     * @return a new function node with the set source and namespace
458     * @throws IllegalArgumentException if the specified source or namespace is null
459     * @throws IllegalStateException if the function already has either a source or namespace set.
460     */
461    public FunctionNode initializeDeserialized(final Source source, final Namespace namespace) {
462        if (source == null || namespace == null) {
463            throw new IllegalArgumentException();
464        } else if (this.source == source && this.namespace == namespace) {
465            return this;
466        } else if (this.source != null || this.namespace != null) {
467            throw new IllegalStateException();
468        }
469        return new FunctionNode(
470            this,
471            lastToken,
472            endParserState,
473            flags,
474            name,
475            returnType,
476            compileUnit,
477            body,
478            parameters,
479            thisProperties,
480            rootClass, source, namespace);
481    }
482
483    /**
484     * Get the unique ID for this function within the script file.
485     * @return the id
486     */
487    public int getId() {
488        return isProgram() ? -1: Token.descPosition(firstToken);
489    }
490
491    /**
492     * get source name - sourceURL or name derived from Source.
493     *
494     * @return name for the script source
495     */
496    public String getSourceName() {
497        return getSourceName(source);
498    }
499
500    /**
501     * Static source name getter
502     *
503     * @param source the source
504     * @return source name
505     */
506    public static String getSourceName(final Source source) {
507        final String explicitURL = source.getExplicitURL();
508        return explicitURL != null ? explicitURL : source.getName();
509    }
510
511    /**
512     * Function to parse nashorn per-function extension directive comments.
513     *
514     * @param directive nashorn extension directive string
515     * @return integer flag for the given directive.
516     */
517    public static int getDirectiveFlag(final String directive) {
518        switch (directive) {
519            case "nashorn callsite trace enterexit":
520                return DEBUG_TRACE_ENTEREXIT;
521            case "nashorn callsite trace misses":
522                return DEBUG_TRACE_MISSES;
523            case "nashorn callsite trace objects":
524                return DEBUG_TRACE_VALUES;
525            case "nashorn callsite profile":
526                return DEBUG_PROFILE;
527            case "nashorn print parse":
528                return DEBUG_PRINT_PARSE;
529            case "nashorn print lower parse":
530                return DEBUG_PRINT_LOWER_PARSE;
531            case "nashorn print ast":
532                return DEBUG_PRINT_AST;
533            case "nashorn print lower ast":
534                return DEBUG_PRINT_LOWER_AST;
535            case "nashorn print symbols":
536                return DEBUG_PRINT_SYMBOLS;
537            default:
538                // unknown/unsupported directive
539                return 0;
540        }
541    }
542
543    /**
544     * Returns the line number.
545     * @return the line number.
546     */
547    public int getLineNumber() {
548        return lineNumber;
549    }
550
551    /**
552     * Create a unique name in the namespace of this FunctionNode
553     * @param base prefix for name
554     * @return base if no collision exists, otherwise a name prefix with base
555     */
556    public String uniqueName(final String base) {
557        return namespace.uniqueName(base);
558    }
559
560    @Override
561    public void toString(final StringBuilder sb, final boolean printTypes) {
562        sb.append('[').
563            append(returnType).
564            append(']').
565            append(' ');
566
567        sb.append("function");
568
569        if (ident != null) {
570            sb.append(' ');
571            ident.toString(sb, printTypes);
572        }
573
574        sb.append('(');
575
576        for (final Iterator<IdentNode> iter = parameters.iterator(); iter.hasNext(); ) {
577            final IdentNode parameter = iter.next();
578            if (parameter.getSymbol() != null) {
579                sb.append('[').append(parameter.getType()).append(']').append(' ');
580            }
581            parameter.toString(sb, printTypes);
582            if (iter.hasNext()) {
583                sb.append(", ");
584            }
585        }
586
587        sb.append(')');
588    }
589
590    @Override
591    public int getFlags() {
592        return flags;
593    }
594
595    @Override
596    public boolean getFlag(final int flag) {
597        return (flags & flag) != 0;
598    }
599
600    @Override
601    public FunctionNode setFlags(final LexicalContext lc, final int flags) {
602        if (this.flags == flags) {
603            return this;
604        }
605        return Node.replaceInLexicalContext(
606                lc,
607                this,
608                new FunctionNode(
609                        this,
610                        lastToken,
611                        endParserState,
612                        flags,
613                        name,
614                        returnType,
615                        compileUnit,
616                        body,
617                        parameters,
618                        thisProperties,
619                        rootClass, source, namespace));
620    }
621
622    @Override
623    public FunctionNode clearFlag(final LexicalContext lc, final int flag) {
624        return setFlags(lc, flags & ~flag);
625    }
626
627    @Override
628    public FunctionNode setFlag(final LexicalContext lc, final int flag) {
629        return setFlags(lc, flags | flag);
630    }
631
632    /**
633     * Returns the debug flags for this function.
634     *
635     * @return the debug flags
636     */
637    public int getDebugFlags() {
638        return debugFlags;
639    }
640
641    /**
642     * Checks whether a debug flag is set for this function.
643     *
644     * @param debugFlag the debug flag
645     * @return true if the flag is set
646     */
647    public boolean getDebugFlag(final int debugFlag) {
648        return (debugFlags & debugFlag) != 0;
649    }
650
651    /**
652     * Returns true if the function is the top-level program.
653     * @return True if this function node represents the top-level program.
654     */
655    public boolean isProgram() {
656        return getFlag(IS_PROGRAM);
657    }
658
659    /**
660     * Returns true if the function contains at least one optimistic operation (and thus can be deoptimized).
661     * @return true if the function contains at least one optimistic operation (and thus can be deoptimized).
662     */
663    public boolean canBeDeoptimized() {
664        return getFlag(IS_DEOPTIMIZABLE);
665    }
666
667    /**
668     * Check if this function has a call expression for the identifier "eval" (that is, {@code eval(...)}).
669     *
670     * @return true if {@code eval} is called.
671     */
672    public boolean hasEval() {
673        return getFlag(HAS_EVAL);
674    }
675
676    /**
677     * Returns true if a function nested (directly or transitively) within this function {@link #hasEval()}.
678     *
679     * @return true if a nested function calls {@code eval}.
680     */
681    public boolean hasNestedEval() {
682        return getFlag(HAS_NESTED_EVAL);
683    }
684
685    /**
686     * Get the first token for this function
687     * @return the first token
688     */
689    public long getFirstToken() {
690        return firstToken;
691    }
692
693    /**
694     * Check whether this function has nested function declarations
695     * @return true if nested function declarations exist
696     */
697    public boolean hasDeclaredFunctions() {
698        return getFlag(HAS_FUNCTION_DECLARATIONS);
699    }
700
701    /**
702     * Check if this function's generated Java method needs a {@code callee} parameter. Functions that need access to
703     * their parent scope, functions that reference themselves, and non-strict functions that need an Arguments object
704     * (since it exposes {@code arguments.callee} property) will need to have a callee parameter. We also return true
705     * for split functions to make sure symbols slots are the same in the main and split methods.
706     *
707     * A function that has had an apply(this,arguments) turned into a call doesn't need arguments anymore, but still
708     * has to fit the old callsite, thus, we require a dummy callee parameter for those functions as well
709     *
710     * @return true if the function's generated Java method needs a {@code callee} parameter.
711     */
712    public boolean needsCallee() {
713        // NOTE: we only need isSplit() here to ensure that :scope can never drop below slot 2 for splitting array units.
714        return needsParentScope() || usesSelfSymbol() || isSplit() || (needsArguments() && !isStrict()) || hasApplyToCallSpecialization();
715    }
716
717    /**
718     * Return {@code true} if this function makes use of the {@code this} object.
719     *
720     * @return true if function uses {@code this} object
721     */
722    public boolean usesThis() {
723        return getFlag(USES_THIS);
724    }
725
726
727    /**
728     * Return true if function contains an apply to call transform
729     * @return true if this function has transformed apply to call
730     */
731    public boolean hasApplyToCallSpecialization() {
732        return getFlag(HAS_APPLY_TO_CALL_SPECIALIZATION);
733    }
734
735    /**
736     * Get the identifier for this function, this is its symbol.
737     * @return the identifier as an IdentityNode
738     */
739    public IdentNode getIdent() {
740        return ident;
741    }
742
743    /**
744     * Get the function body
745     * @return the function body
746     */
747    public Block getBody() {
748        return body;
749    }
750
751    /**
752     * Reset the function body
753     * @param lc lexical context
754     * @param body new body
755     * @return new function node if body changed, same if not
756     */
757    public FunctionNode setBody(final LexicalContext lc, final Block body) {
758        if (this.body == body) {
759            return this;
760        }
761        return Node.replaceInLexicalContext(
762                lc,
763                this,
764                new FunctionNode(
765                        this,
766                        lastToken,
767                        endParserState,
768                        flags |
769                            (body.needsScope() ?
770                                    FunctionNode.HAS_SCOPE_BLOCK :
771                                    0),
772                        name,
773                        returnType,
774                        compileUnit,
775                        body,
776                        parameters,
777                        thisProperties,
778                        rootClass, source, namespace));
779    }
780
781    /**
782     * Does this function's method needs to be variable arity (gather all script-declared parameters in a final
783     * {@code Object[]} parameter. Functions that need to have the "arguments" object as well as functions that simply
784     * declare too many arguments for JVM to handle with fixed arity will need to be variable arity.
785     * @return true if the Java method in the generated code that implements this function needs to be variable arity.
786     * @see #needsArguments()
787     * @see LinkerCallSite#ARGLIMIT
788     */
789    public boolean isVarArg() {
790        return needsArguments() || parameters.size() > LinkerCallSite.ARGLIMIT;
791    }
792
793    /**
794     * Was this function declared in a dynamic context, i.e. in a with or eval style
795     * chain
796     * @return true if in dynamic context
797     */
798    public boolean inDynamicContext() {
799        return getFlag(IN_DYNAMIC_CONTEXT);
800    }
801
802    /**
803     * Check whether a function would need dynamic scope, which is does if it has
804     * evals and isn't strict.
805     * @return true if dynamic scope is needed
806     */
807    public boolean needsDynamicScope() {
808        // Function has a direct eval in it (so a top-level "var ..." in the eval code can introduce a new
809        // variable into the function's scope), and it isn't strict (as evals in strict functions get an
810        // isolated scope).
811        return hasEval() && !isStrict();
812    }
813
814    /**
815     * Flag this function as declared in a dynamic context
816     * @param lc lexical context
817     * @return new function node, or same if unmodified
818     */
819    public FunctionNode setInDynamicContext(final LexicalContext lc) {
820        return setFlag(lc, IN_DYNAMIC_CONTEXT);
821    }
822
823    /**
824     * Returns true if this function needs to have an Arguments object defined as a local variable named "arguments".
825     * Functions that use "arguments" as identifier and don't define it as a name of a parameter or a nested function
826     * (see ECMAScript 5.1 Chapter 10.5), as well as any function that uses eval or with, or has a nested function that
827     * does the same, will have an "arguments" object. Also, if this function is a script, it will not have an
828     * "arguments" object, because it does not have local variables; rather the Global object will have an explicit
829     * "arguments" property that provides command-line arguments for the script.
830     * @return true if this function needs an arguments object.
831     */
832    public boolean needsArguments() {
833        // uses "arguments" or calls eval, but it does not redefine "arguments", and finally, it's not a script, since
834        // for top-level script, "arguments" is picked up from Context by Global.init() instead.
835        return getFlag(MAYBE_NEEDS_ARGUMENTS) && !getFlag(DEFINES_ARGUMENTS) && !isProgram();
836    }
837
838    /**
839     * Returns true if this function needs access to its parent scope. Functions referencing variables outside their
840     * scope (including global variables), as well as functions that call eval or have a with block, or have nested
841     * functions that call eval or have a with block, will need a parent scope. Top-level script functions also need a
842     * parent scope since they might be used from within eval, and eval will need an externally passed scope.
843     * @return true if the function needs parent scope.
844     */
845    public boolean needsParentScope() {
846        return getFlag(NEEDS_PARENT_SCOPE);
847    }
848
849    /**
850     * Set the number of properties assigned to the this object in this function.
851     * @param lc the current lexical context.
852     * @param thisProperties number of properties
853     * @return a potentially modified function node
854     */
855    public FunctionNode setThisProperties(final LexicalContext lc, final int thisProperties) {
856        if (this.thisProperties == thisProperties) {
857            return this;
858        }
859        return Node.replaceInLexicalContext(
860                lc,
861                this,
862                new FunctionNode(
863                        this,
864                        lastToken,
865                        endParserState,
866                        flags,
867                        name,
868                        returnType,
869                        compileUnit,
870                        body,
871                        parameters,
872                        thisProperties,
873                        rootClass, source, namespace));
874    }
875
876    /**
877     * Get the number of properties assigned to the this object in this function.
878     * @return number of properties
879     */
880    public int getThisProperties() {
881        return thisProperties;
882    }
883
884    /**
885     * Returns true if any of the blocks in this function create their own scope.
886     * @return true if any of the blocks in this function create their own scope.
887     */
888    public boolean hasScopeBlock() {
889        return getFlag(HAS_SCOPE_BLOCK);
890    }
891
892    /**
893     * Return the kind of this function
894     * @see FunctionNode.Kind
895     * @return the kind
896     */
897    public Kind getKind() {
898        return kind;
899    }
900
901    /**
902     * Return the last token for this function's code
903     * @return last token
904     */
905    public long getLastToken() {
906        return lastToken;
907    }
908
909    /**
910     * Returns the end parser state for this function.
911     * @return the end parser state for this function.
912     */
913    public Object getEndParserState() {
914        return endParserState;
915    }
916
917    /**
918     * Get the name of this function
919     * @return the name
920     */
921    public String getName() {
922        return name;
923    }
924
925    /**
926     * Set the internal name for this function
927     * @param lc    lexical context
928     * @param name new name
929     * @return new function node if changed, otherwise the same
930     */
931    public FunctionNode setName(final LexicalContext lc, final String name) {
932        if (this.name.equals(name)) {
933            return this;
934        }
935        return Node.replaceInLexicalContext(
936                lc,
937                this,
938                new FunctionNode(
939                        this,
940                        lastToken,
941                        endParserState,
942                        flags,
943                        name,
944                        returnType,
945                        compileUnit,
946                        body,
947                        parameters,
948                        thisProperties,
949                        rootClass, source, namespace));
950    }
951
952    /**
953     * Check if this function should have all its variables in its own scope. Split sub-functions, and
954     * functions having with and/or eval blocks are such.
955     *
956     * @return true if all variables should be in scope
957     */
958    public boolean allVarsInScope() {
959        return getFlag(HAS_ALL_VARS_IN_SCOPE);
960    }
961
962    /**
963     * Checks if this function is split into several smaller fragments.
964     *
965     * @return true if this function is split into several smaller fragments.
966     */
967    public boolean isSplit() {
968        return getFlag(IS_SPLIT);
969    }
970
971    /**
972     * Get the parameters to this function
973     * @return a list of IdentNodes which represent the function parameters, in order
974     */
975    public List<IdentNode> getParameters() {
976        return Collections.unmodifiableList(parameters);
977    }
978
979    /**
980     * Return the number of parameters to this function
981     * @return the number of parameters
982     */
983    public int getNumOfParams() {
984        return parameters.size();
985    }
986
987    /**
988     * Returns the identifier for a named parameter at the specified position in this function's parameter list.
989     * @param index the parameter's position.
990     * @return the identifier for the requested named parameter.
991     * @throws IndexOutOfBoundsException if the index is invalid.
992     */
993    public IdentNode getParameter(final int index) {
994        return parameters.get(index);
995    }
996
997    /**
998     * Reset the compile unit used to compile this function
999     * @see Compiler
1000     * @param  lc lexical context
1001     * @param  parameters the compile unit
1002     * @return function node or a new one if state was changed
1003     */
1004    public FunctionNode setParameters(final LexicalContext lc, final List<IdentNode> parameters) {
1005        if (this.parameters == parameters) {
1006            return this;
1007        }
1008        return Node.replaceInLexicalContext(
1009                lc,
1010                this,
1011                new FunctionNode(
1012                        this,
1013                        lastToken,
1014                        endParserState,
1015                        flags,
1016                        name,
1017                        returnType,
1018                        compileUnit,
1019                        body,
1020                        parameters,
1021                        thisProperties,
1022                        rootClass, source, namespace));
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    /**
1052     * Returns true if this is a named function expression (that is, it isn't a declared function, it isn't an
1053     * anonymous function expression, and it isn't a program).
1054     * @return true if this is a named function expression
1055     */
1056    public boolean isNamedFunctionExpression() {
1057        return !getFlag(IS_PROGRAM | IS_ANONYMOUS | IS_DECLARED);
1058    }
1059
1060    @Override
1061    public Type getType() {
1062        return FUNCTION_TYPE;
1063    }
1064
1065    @Override
1066    public Type getWidestOperationType() {
1067        return FUNCTION_TYPE;
1068    }
1069
1070    /**
1071     * Get the return type for this function. Return types can be specialized
1072     * if the compiler knows them, but parameters cannot, as they need to go through
1073     * appropriate object conversion
1074     *
1075     * @return the return type
1076     */
1077    public Type getReturnType() {
1078        return returnType;
1079    }
1080
1081    /**
1082     * Set the function return type
1083     * @param lc lexical context
1084     * @param returnType new return type
1085     * @return function node or a new one if state was changed
1086     */
1087    public FunctionNode setReturnType(final LexicalContext lc, final Type returnType) {
1088        //we never bother with object types narrower than objects, that will lead to byte code verification errors
1089        //as for instance even if we know we are returning a string from a method, the code generator will always
1090        //treat it as an object, at least for now
1091        final Type type = returnType.isObject() ? Type.OBJECT : returnType;
1092        if (this.returnType == type) {
1093            return this;
1094        }
1095        return Node.replaceInLexicalContext(
1096            lc,
1097            this,
1098            new FunctionNode(
1099                this,
1100                lastToken,
1101                endParserState,
1102                flags,
1103                name,
1104                type,
1105                compileUnit,
1106                body,
1107                parameters,
1108                thisProperties,
1109                rootClass, source, namespace
1110                ));
1111   }
1112
1113    /**
1114     * Check if the function is generated in strict mode
1115     * @return true if strict mode enabled for function
1116     */
1117    public boolean isStrict() {
1118        return getFlag(IS_STRICT);
1119    }
1120
1121    /**
1122     * Returns true if this function node has been cached.
1123     * @return true if this function node has been cached.
1124     */
1125    public boolean isCached() {
1126        return getFlag(IS_CACHED);
1127    }
1128
1129    /**
1130     * Mark this function node as having been cached.
1131     * @param lc the current lexical context
1132     * @return a function node equivalent to this one, with the flag set.
1133     */
1134    public FunctionNode setCached(final LexicalContext lc) {
1135        return setFlag(lc, IS_CACHED);
1136    }
1137
1138    /**
1139     * Checks if the function is generated in strong mode.
1140     *
1141     * @return true if strong mode enabled for function
1142     */
1143    public boolean isStrong() {
1144        return getFlag(ES6_IS_STRONG);
1145    }
1146
1147    /**
1148     * Checks if this is an ES6 method.
1149     *
1150     * @return true if the ES6 method flag is set
1151     */
1152    public boolean isMethod() {
1153        return getFlag(ES6_IS_METHOD);
1154    }
1155
1156    /**
1157     * Checks if this function uses the ES6 super binding.
1158     *
1159     * @return true if the ES6 super flag is set
1160     */
1161    public boolean usesSuper() {
1162        return getFlag(ES6_USES_SUPER);
1163    }
1164
1165    /**
1166     * Checks if this function directly uses the super binding.
1167     *
1168     * @return true if the ES6 has-direct-super flag is set
1169     */
1170    public boolean hasDirectSuper() {
1171        return getFlag(ES6_HAS_DIRECT_SUPER);
1172    }
1173
1174    /**
1175     * Checks if this is an ES6 class constructor.
1176     *
1177     * @return true if the ES6 class constructor flag is set
1178     */
1179    public boolean isClassConstructor() {
1180        return getFlag(ES6_IS_CLASS_CONSTRUCTOR);
1181    }
1182
1183    /**
1184     * Checks if this is an ES6 subclass constructor.
1185     *
1186     * @return true if the ES6 subclass constructor flag is set
1187     */
1188    public boolean isSubclassConstructor() {
1189        return getFlag(ES6_IS_SUBCLASS_CONSTRUCTOR);
1190    }
1191
1192    /**
1193     * Checks if this function uses the ES6 new-targert.
1194     *
1195     * @return true if the ES6 new-target flag is set
1196     */
1197    public boolean usesNewTarget() {
1198        return getFlag(ES6_USES_NEW_TARGET);
1199    }
1200
1201    /**
1202     * Checks if this is an ES6 module.
1203     *
1204     * @return true if this is an ES6 module
1205     */
1206    public boolean isModule() {
1207        return kind == Kind.MODULE;
1208    }
1209
1210    /**
1211     * Returns the functions's ES6 module.
1212     *
1213     * @return the module, or null if this function is not part of one
1214     */
1215    public Module getModule() {
1216        return module;
1217    }
1218
1219    /**
1220     * Get the compile unit used to compile this function
1221     * @see Compiler
1222     * @return the compile unit
1223     */
1224    @Override
1225    public CompileUnit getCompileUnit() {
1226        return compileUnit;
1227    }
1228
1229    /**
1230     * Reset the compile unit used to compile this function
1231     * @see Compiler
1232     * @param lc lexical context
1233     * @param compileUnit the compile unit
1234     * @return function node or a new one if state was changed
1235     */
1236    public FunctionNode setCompileUnit(final LexicalContext lc, final CompileUnit compileUnit) {
1237        if (this.compileUnit == compileUnit) {
1238            return this;
1239        }
1240        return Node.replaceInLexicalContext(
1241                lc,
1242                this,
1243                new FunctionNode(
1244                        this,
1245                        lastToken,
1246                        endParserState,
1247                        flags,
1248                        name,
1249                        returnType,
1250                        compileUnit,
1251                        body,
1252                        parameters,
1253                        thisProperties,
1254                        rootClass, source, namespace));
1255    }
1256
1257    /**
1258     * Create a temporary variable to the current frame.
1259     *
1260     * @param block that needs the temporary
1261     * @param type  Strong type of symbol.
1262     * @param node  Primary node to use symbol.
1263     *
1264     * @return Symbol used.
1265     */
1266
1267    /**
1268     * Get the symbol for a compiler constant, or null if not available (yet)
1269     * @param cc compiler constant
1270     * @return symbol for compiler constant, or null if not defined yet (for example in Lower)
1271     */
1272    public Symbol compilerConstant(final CompilerConstants cc) {
1273        return body.getExistingSymbol(cc.symbolName());
1274    }
1275
1276    /**
1277     * Get the root class that this function node compiles to
1278     * @return root class
1279     */
1280    public Class<?> getRootClass() {
1281        return rootClass;
1282    }
1283
1284    /**
1285     * Reset the root class that this function is compiled to
1286     * @see Compiler
1287     * @param lc lexical context
1288     * @param rootClass root class
1289     * @return function node or a new one if state was changed
1290     */
1291    public FunctionNode setRootClass(final LexicalContext lc, final Class<?> rootClass) {
1292        if (this.rootClass == rootClass) {
1293            return this;
1294        }
1295        return Node.replaceInLexicalContext(
1296                lc,
1297                this,
1298                new FunctionNode(
1299                        this,
1300                        lastToken,
1301                        endParserState,
1302                        flags,
1303                        name,
1304                        returnType,
1305                        compileUnit,
1306                        body,
1307                        parameters,
1308                        thisProperties,
1309                        rootClass, source, namespace));
1310    }
1311}
1312