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