< prev index next >

src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/FunctionNode.java

Print this page




  52 
  53 /**
  54  * IR representation for function (or script.)
  55  */
  56 @Immutable
  57 public 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     }
  74 
  75     /** Source of entity. */
  76     private transient final Source source;
  77 
  78     /**
  79      * Opaque object representing parser state at the end of the function. Used when reparsing outer functions
  80      * to skip parsing inner functions.
  81      */
  82     private final Object endParserState;
  83 
  84     /** External function identifier. */
  85     @Ignore
  86     private final IdentNode ident;
  87 
  88     /** The body of the function node */
  89     private final Block body;
  90 
  91     /** Internal function name. */
  92     private final String name;


 105 
 106     /** Last token of function. **/
 107     private final long lastToken;
 108 
 109     /** Method's namespace. */
 110     private transient final Namespace namespace;
 111 
 112     /** Number of properties of "this" object assigned in this function */
 113     @Ignore
 114     private final int thisProperties;
 115 
 116     /** Function flags. */
 117     private final int flags;
 118 
 119     /** Line number of function start */
 120     private final int lineNumber;
 121 
 122     /** Root class for function */
 123     private final Class<?> rootClass;
 124 






 125     /** Is anonymous function flag. */
 126     public static final int IS_ANONYMOUS                = 1 << 0;
 127 
 128     /** Is the function created in a function declaration (as opposed to a function expression) */
 129     public static final int IS_DECLARED                 = 1 << 1;
 130 
 131     /** is this a strict mode function? */
 132     public static final int IS_STRICT                   = 1 << 2;
 133 
 134     /** Does the function use the "arguments" identifier ? */
 135     public static final int USES_ARGUMENTS              = 1 << 3;
 136 
 137     /** Has this function been split because it was too large? */
 138     public static final int IS_SPLIT                    = 1 << 4;
 139 
 140     /** Does the function call eval? If it does, then all variables in this function might be get/set by it and it can
 141      * introduce new variables into this function's scope too.*/
 142     public static final int HAS_EVAL                    = 1 << 5;
 143 
 144     /** Does a nested function contain eval? If it does, then all variables in this function might be get/set by it. */


 170     public static final int HAS_APPLY_TO_CALL_SPECIALIZATION = 1 << 12;
 171 
 172     /**
 173      * Is this function the top-level program?
 174      */
 175     public static final int IS_PROGRAM = 1 << 13;
 176 
 177     /**
 178      * Flag indicating whether this function uses the local variable symbol for itself. Only named function expressions
 179      * can have this flag set if they reference themselves (e.g. "(function f() { return f })". Declared functions will
 180      * use the symbol in their parent scope instead when they reference themselves by name.
 181      */
 182     public static final int USES_SELF_SYMBOL = 1 << 14;
 183 
 184     /** Does this function use the "this" keyword? */
 185     public static final int USES_THIS = 1 << 15;
 186 
 187     /** Is this declared in a dynamic context */
 188     public static final int IN_DYNAMIC_CONTEXT = 1 << 16;
 189 
 190     /**
 191      * The following flags are derived from directive comments within this function.
 192      * Note that even IS_STRICT is one such flag but that requires special handling.
 193      */
 194 
 195     /** parser, print parse tree */
 196     public static final int IS_PRINT_PARSE       = 1 << 17;
 197     /** parser, print lower parse tree */
 198     public static final int IS_PRINT_LOWER_PARSE = 1 << 18;
 199     /** parser, print AST */
 200     public static final int IS_PRINT_AST         = 1 << 19;
 201     /** parser, print lower AST */
 202     public static final int IS_PRINT_LOWER_AST   = 1 << 20;
 203     /** parser, print symbols */
 204     public static final int IS_PRINT_SYMBOLS     = 1 << 21;
 205 
 206     // callsite tracing, profiling within this function
 207     /** profile callsites in this function? */
 208     public static final int IS_PROFILE         = 1 << 22;
 209 
 210     /** trace callsite enterexit in this function? */
 211     public static final int IS_TRACE_ENTEREXIT = 1 << 23;
 212 
 213     /** trace callsite misses in this function? */
 214     public static final int IS_TRACE_MISSES    = 1 << 24;
 215 
 216     /** trace callsite values in this function? */
 217     public static final int IS_TRACE_VALUES    = 1 << 25;
 218 
 219     /**
 220      * Whether this function needs the callee {@link ScriptFunction} instance passed to its code as a
 221      * parameter on invocation. Note that we aren't, in fact using this flag in function nodes.
 222      * Rather, it is always calculated (see {@link #needsCallee()}). {@link RecompilableScriptFunctionData}
 223      * will, however, cache the value of this flag.
 224      */
 225     public static final int NEEDS_CALLEE       = 1 << 26;
 226 
 227     /**
 228      * Is the function node cached?
 229      */
 230     public static final int IS_CACHED = 1 << 27;
 231 
 232     /** extension callsite flags mask */
 233     public static final int EXTENSION_CALLSITE_FLAGS = IS_PRINT_PARSE |
 234         IS_PRINT_LOWER_PARSE | IS_PRINT_AST | IS_PRINT_LOWER_AST |
 235         IS_PRINT_SYMBOLS | IS_PROFILE | IS_TRACE_ENTEREXIT |
 236         IS_TRACE_MISSES | IS_TRACE_VALUES;























 237 
 238     /** Does this function or any nested functions contain an eval? */
 239     private static final int HAS_DEEP_EVAL = HAS_EVAL | HAS_NESTED_EVAL;
 240 
 241     /** Does this function need to store all its variables in scope? */
 242     public static final int HAS_ALL_VARS_IN_SCOPE = HAS_DEEP_EVAL;
 243 
 244     /** Does this function potentially need "arguments"? Note that this is not a full test, as further negative check of REDEFINES_ARGS is needed. */
 245     private static final int MAYBE_NEEDS_ARGUMENTS = USES_ARGUMENTS | HAS_EVAL;
 246 
 247     /** 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. */
 248     public static final int NEEDS_PARENT_SCOPE = USES_ANCESTOR_SCOPE | HAS_DEEP_EVAL | IS_PROGRAM;
 249 




































 250     /** What is the return type of this function? */
 251     private Type returnType = Type.UNKNOWN;
 252 
 253     /**
 254      * Constructor
 255      *
 256      * @param source     the source
 257      * @param lineNumber line number
 258      * @param token      token
 259      * @param finish     finish
 260      * @param firstToken first token of the function node (including the function declaration)
 261      * @param lastToken  lastToken
 262      * @param namespace  the namespace
 263      * @param ident      the identifier
 264      * @param name       the name of the function
 265      * @param parameters parameter list
 266      * @param kind       kind of function as in {@link FunctionNode.Kind}
 267      * @param flags      initial flags
 268      * @param body       body of the function
 269      * @param endParserState The parser state at the end of the parsing.


 270      */
 271     public FunctionNode(
 272         final Source source,
 273         final int lineNumber,
 274         final long token,
 275         final int finish,
 276         final long firstToken,
 277         final long lastToken,
 278         final Namespace namespace,
 279         final IdentNode ident,
 280         final String name,
 281         final List<IdentNode> parameters,
 282         final FunctionNode.Kind kind,
 283         final int flags,
 284         final Block body,
 285         final Object endParserState) {


 286         super(token, finish);
 287 
 288         this.source           = source;
 289         this.lineNumber       = lineNumber;
 290         this.ident            = ident;
 291         this.name             = name;
 292         this.kind             = kind;
 293         this.parameters       = parameters;
 294         this.firstToken       = firstToken;
 295         this.lastToken        = lastToken;
 296         this.namespace        = namespace;
 297         this.flags            = flags;
 298         this.compileUnit      = null;
 299         this.body             = body;
 300         this.thisProperties   = 0;
 301         this.rootClass        = null;
 302         this.endParserState    = endParserState;


 303     }
 304 
 305     private FunctionNode(
 306         final FunctionNode functionNode,
 307         final long lastToken,
 308         final Object endParserState,
 309         final int flags,
 310         final String name,
 311         final Type returnType,
 312         final CompileUnit compileUnit,
 313         final Block body,
 314         final List<IdentNode> parameters,
 315         final int thisProperties,
 316         final Class<?> rootClass,
 317         final Source source, final Namespace namespace) {
 318         super(functionNode);
 319 
 320         this.endParserState    = endParserState;
 321         this.lineNumber       = functionNode.lineNumber;
 322         this.flags            = flags;
 323         this.name             = name;
 324         this.returnType       = returnType;
 325         this.compileUnit      = compileUnit;
 326         this.lastToken        = lastToken;
 327         this.body             = body;
 328         this.parameters       = parameters;
 329         this.thisProperties   = thisProperties;
 330         this.rootClass        = rootClass;
 331         this.source           = source;
 332         this.namespace        = namespace;
 333 
 334         // the fields below never change - they are final and assigned in constructor
 335         this.ident           = functionNode.ident;
 336         this.kind            = functionNode.kind;
 337         this.firstToken      = functionNode.firstToken;


 338     }
 339 
 340     @Override
 341     public Node accept(final LexicalContext lc, final NodeVisitor<? extends LexicalContext> visitor) {
 342         if (visitor.enterFunctionNode(this)) {
 343             return visitor.leaveFunctionNode(setBody(lc, (Block)body.accept(visitor)));
 344         }
 345         return this;
 346     }
 347 
 348     /**
 349      * Visits the parameter nodes of this function. Parameters are normally not visited automatically.
 350      * @param visitor the visitor to apply to the nodes.
 351      * @return a list of parameter nodes, potentially modified from original ones by the visitor.
 352      */
 353     public List<IdentNode> visitParameters(final NodeVisitor<? extends LexicalContext> visitor) {
 354         return Node.accept(visitor, parameters);
 355     }
 356 
 357     /**
 358      * Get additional callsite flags to be used specific to this function.
 359      *
 360      * @return callsite flags
 361      */
 362     public int getCallSiteFlags() {
 363         int callsiteFlags = 0;
 364         if (getFlag(IS_STRICT)) {
 365             callsiteFlags |= CALLSITE_STRICT;
 366         }
 367 
 368         // quick check for extension callsite flags turned on by directives.
 369         if ((flags & EXTENSION_CALLSITE_FLAGS) == 0) {
 370             return callsiteFlags;
 371         }
 372 
 373         if (getFlag(IS_PROFILE)) {
 374             callsiteFlags |= CALLSITE_PROFILE;
 375         }
 376 
 377         if (getFlag(IS_TRACE_MISSES)) {
 378             callsiteFlags |= CALLSITE_TRACE | CALLSITE_TRACE_MISSES;
 379         }
 380 
 381         if (getFlag(IS_TRACE_VALUES)) {
 382             callsiteFlags |= CALLSITE_TRACE | CALLSITE_TRACE_ENTEREXIT | CALLSITE_TRACE_VALUES;
 383         }
 384 
 385         if (getFlag(IS_TRACE_ENTEREXIT)) {
 386             callsiteFlags |= CALLSITE_TRACE | CALLSITE_TRACE_ENTEREXIT;
 387         }
 388 
 389         return callsiteFlags;
 390     }
 391 
 392     /**
 393      * Get the source for this function
 394      * @return the source
 395      */
 396     public Source getSource() {
 397         return source;
 398     }
 399 
 400     /**
 401      * Sets the source and namespace for this function. It can only set a non-null source and namespace for a function
 402      * that currently has both a null source and a null namespace. This is used to re-set the source and namespace for
 403      * a deserialized function node.
 404      * @param source the source for the function.
 405      * @param namespace the namespace for the function


 449     /**
 450      * Static source name getter
 451      *
 452      * @param source the source
 453      * @return source name
 454      */
 455     public static String getSourceName(final Source source) {
 456         final String explicitURL = source.getExplicitURL();
 457         return explicitURL != null ? explicitURL : source.getName();
 458     }
 459 
 460     /**
 461      * Function to parse nashorn per-function extension directive comments.
 462      *
 463      * @param directive nashorn extension directive string
 464      * @return integer flag for the given directive.
 465      */
 466     public static int getDirectiveFlag(final String directive) {
 467         switch (directive) {
 468             case "nashorn callsite trace enterexit":
 469                 return IS_TRACE_ENTEREXIT;
 470             case "nashorn callsite trace misses":
 471                 return IS_TRACE_MISSES;
 472             case "nashorn callsite trace objects":
 473                 return IS_TRACE_VALUES;
 474             case "nashorn callsite profile":
 475                 return IS_PROFILE;
 476             case "nashorn print parse":
 477                 return IS_PRINT_PARSE;
 478             case "nashorn print lower parse":
 479                 return IS_PRINT_LOWER_PARSE;
 480             case "nashorn print ast":
 481                 return IS_PRINT_AST;
 482             case "nashorn print lower ast":
 483                 return IS_PRINT_LOWER_AST;
 484             case "nashorn print symbols":
 485                 return IS_PRINT_SYMBOLS;
 486             default:
 487                 // unknown/unsupported directive
 488                 return 0;
 489         }
 490     }
 491 
 492     /**
 493      * Returns the line number.
 494      * @return the line number.
 495      */
 496     public int getLineNumber() {
 497         return lineNumber;
 498     }
 499 
 500     /**
 501      * Create a unique name in the namespace of this FunctionNode
 502      * @param base prefix for name
 503      * @return base if no collision exists, otherwise a name prefix with base
 504      */
 505     public String uniqueName(final String base) {


 562                         name,
 563                         returnType,
 564                         compileUnit,
 565                         body,
 566                         parameters,
 567                         thisProperties,
 568                         rootClass, source, namespace));
 569     }
 570 
 571     @Override
 572     public FunctionNode clearFlag(final LexicalContext lc, final int flag) {
 573         return setFlags(lc, flags & ~flag);
 574     }
 575 
 576     @Override
 577     public FunctionNode setFlag(final LexicalContext lc, final int flag) {
 578         return setFlags(lc, flags | flag);
 579     }
 580 
 581     /**



















 582      * Returns true if the function is the top-level program.
 583      * @return True if this function node represents the top-level program.
 584      */
 585     public boolean isProgram() {
 586         return getFlag(IS_PROGRAM);
 587     }
 588 
 589     /**
 590      * Returns true if the function contains at least one optimistic operation (and thus can be deoptimized).
 591      * @return true if the function contains at least one optimistic operation (and thus can be deoptimized).
 592      */
 593     public boolean canBeDeoptimized() {
 594         return getFlag(IS_DEOPTIMIZABLE);
 595     }
 596 
 597     /**
 598      * Check if this function has a call expression for the identifier "eval" (that is, {@code eval(...)}).
 599      *
 600      * @return true if {@code eval} is called.
 601      */


1048         return getFlag(IS_STRICT);
1049     }
1050 
1051     /**
1052      * Returns true if this function node has been cached.
1053      * @return true if this function node has been cached.
1054      */
1055     public boolean isCached() {
1056         return getFlag(IS_CACHED);
1057     }
1058 
1059     /**
1060      * Mark this function node as having been cached.
1061      * @param lc the current lexical context
1062      * @return a function node equivalent to this one, with the flag set.
1063      */
1064     public FunctionNode setCached(final LexicalContext lc) {
1065         return setFlag(lc, IS_CACHED);
1066     }
1067 
















































































1068 
1069     /**
1070      * Get the compile unit used to compile this function
1071      * @see Compiler
1072      * @return the compile unit
1073      */
1074     @Override
1075     public CompileUnit getCompileUnit() {
1076         return compileUnit;
1077     }
1078 
1079     /**
1080      * Reset the compile unit used to compile this function
1081      * @see Compiler
1082      * @param lc lexical context
1083      * @param compileUnit the compile unit
1084      * @return function node or a new one if state was changed
1085      */
1086     public FunctionNode setCompileUnit(final LexicalContext lc, final CompileUnit compileUnit) {
1087         if (this.compileUnit == compileUnit) {




  52 
  53 /**
  54  * IR representation for function (or script.)
  55  */
  56 @Immutable
  57 public 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;


 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. */


 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


 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) {


 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      */


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) {


< prev index next >