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=>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