65 /** Is this symbol in scope */ 66 public static final int IS_SCOPE = 1 << 2; 67 /** Is this a this symbol */ 68 public static final int IS_THIS = 1 << 3; 69 /** Is this a let */ 70 public static final int IS_LET = 1 << 4; 71 /** Is this a const */ 72 public static final int IS_CONST = 1 << 5; 73 /** Is this an internal symbol, never represented explicitly in source code */ 74 public static final int IS_INTERNAL = 1 << 6; 75 /** Is this a function self-reference symbol */ 76 public static final int IS_FUNCTION_SELF = 1 << 7; 77 /** Is this a function declaration? */ 78 public static final int IS_FUNCTION_DECLARATION = 1 << 8; 79 /** Is this a program level symbol? */ 80 public static final int IS_PROGRAM_LEVEL = 1 << 9; 81 /** Are this symbols' values stored in local variable slots? */ 82 public static final int HAS_SLOT = 1 << 10; 83 /** Is this symbol known to store an int value ? */ 84 public static final int HAS_INT_VALUE = 1 << 11; 85 /** Is this symbol known to store a long value ? */ 86 public static final int HAS_LONG_VALUE = 1 << 12; 87 /** Is this symbol known to store a double value ? */ 88 public static final int HAS_DOUBLE_VALUE = 1 << 13; 89 /** Is this symbol known to store an object value ? */ 90 public static final int HAS_OBJECT_VALUE = 1 << 14; 91 /** Is this symbol seen a declaration? Used for block scoped LET and CONST symbols only. */ 92 public static final int HAS_BEEN_DECLARED = 1 << 15; 93 94 /** Null or name identifying symbol. */ 95 private final String name; 96 97 /** Symbol flags. */ 98 private int flags; 99 100 /** First bytecode method local variable slot for storing the value(s) of this variable. -1 indicates the variable 101 * is not stored in local variable slots or it is not yet known. */ 102 private transient int firstSlot = -1; 103 104 /** Field number in scope or property; array index in varargs when not using arguments object. */ 105 private transient int fieldIndex = -1; 106 107 /** Number of times this symbol is used in code */ 108 private int useCount; 109 110 /** Debugging option - dump info and stack trace when symbols with given names are manipulated */ 111 private static final Set<String> TRACE_SYMBOLS; 112 private static final Set<String> TRACE_SYMBOLS_STACKTRACE; 239 * @param needsSlot True if symbol needs a slot. 240 * @return the symbol 241 */ 242 public Symbol setNeedsSlot(final boolean needsSlot) { 243 if(needsSlot) { 244 assert !isScope(); 245 flags |= HAS_SLOT; 246 } else { 247 flags &= ~HAS_SLOT; 248 } 249 return this; 250 } 251 252 /** 253 * Return the number of slots required for the symbol. 254 * 255 * @return Number of slots. 256 */ 257 public int slotCount() { 258 return ((flags & HAS_INT_VALUE) == 0 ? 0 : 1) + 259 ((flags & HAS_LONG_VALUE) == 0 ? 0 : 2) + 260 ((flags & HAS_DOUBLE_VALUE) == 0 ? 0 : 2) + 261 ((flags & HAS_OBJECT_VALUE) == 0 ? 0 : 1); 262 } 263 264 private boolean isSlotted() { 265 return firstSlot != -1 && ((flags & HAS_SLOT) != 0); 266 } 267 268 @Override 269 public String toString() { 270 final StringBuilder sb = new StringBuilder(); 271 272 sb.append(name). 273 append(' '); 274 275 if (hasSlot()) { 276 sb.append(' '). 277 append('('). 278 append("slot="). 279 append(firstSlot).append(' '); 280 if((flags & HAS_INT_VALUE) != 0) { sb.append('I'); } 281 if((flags & HAS_LONG_VALUE) != 0) { sb.append('J'); } 282 if((flags & HAS_DOUBLE_VALUE) != 0) { sb.append('D'); } 283 if((flags & HAS_OBJECT_VALUE) != 0) { sb.append('O'); } 284 sb.append(')'); 285 } 286 287 if (isScope()) { 288 if(isGlobal()) { 289 sb.append(" G"); 290 } else { 291 sb.append(" S"); 292 } 293 } 294 295 return sb.toString(); 296 } 297 298 @Override 299 public int compareTo(final Symbol other) { 300 return name.compareTo(other.name); 301 } 556 * @return byte code slot 557 */ 558 public int getFirstSlot() { 559 assert isSlotted(); 560 return firstSlot; 561 } 562 563 /** 564 * Get the index of the bytecode slot for this symbol for storing a value of the specified type. 565 * @param type the requested type 566 * @return byte code slot 567 */ 568 public int getSlot(final Type type) { 569 assert isSlotted(); 570 int typeSlot = firstSlot; 571 if(type.isBoolean() || type.isInteger()) { 572 assert (flags & HAS_INT_VALUE) != 0; 573 return typeSlot; 574 } 575 typeSlot += ((flags & HAS_INT_VALUE) == 0 ? 0 : 1); 576 if(type.isLong()) { 577 assert (flags & HAS_LONG_VALUE) != 0; 578 return typeSlot; 579 } 580 typeSlot += ((flags & HAS_LONG_VALUE) == 0 ? 0 : 2); 581 if(type.isNumber()) { 582 assert (flags & HAS_DOUBLE_VALUE) != 0; 583 return typeSlot; 584 } 585 assert type.isObject(); 586 assert (flags & HAS_OBJECT_VALUE) != 0 : name; 587 return typeSlot + ((flags & HAS_DOUBLE_VALUE) == 0 ? 0 : 2); 588 } 589 590 /** 591 * Returns true if this symbol has a local variable slot for storing a value of specific type. 592 * @param type the type 593 * @return true if this symbol has a local variable slot for storing a value of specific type. 594 */ 595 public boolean hasSlotFor(final Type type) { 596 if(type.isBoolean() || type.isInteger()) { 597 return (flags & HAS_INT_VALUE) != 0; 598 } else if(type.isLong()) { 599 return (flags & HAS_LONG_VALUE) != 0; 600 } else if(type.isNumber()) { 601 return (flags & HAS_DOUBLE_VALUE) != 0; 602 } 603 assert type.isObject(); 604 return (flags & HAS_OBJECT_VALUE) != 0; 605 } 606 607 /** 608 * Marks this symbol as having a local variable slot for storing a value of specific type. 609 * @param type the type 610 */ 611 public void setHasSlotFor(final Type type) { 612 if(type.isBoolean() || type.isInteger()) { 613 setFlag(HAS_INT_VALUE); 614 } else if(type.isLong()) { 615 setFlag(HAS_LONG_VALUE); 616 } else if(type.isNumber()) { 617 setFlag(HAS_DOUBLE_VALUE); 618 } else { 619 assert type.isObject(); 620 setFlag(HAS_OBJECT_VALUE); 621 } 622 } 623 624 /** 625 * Increase the symbol's use count by one. 626 */ 627 public void increaseUseCount() { 628 if (isScope()) { // Avoid dirtying a cache line; we only need the use count for scoped symbols 629 useCount++; 630 } 631 } 632 633 /** 634 * Get the symbol's use count 635 * @return the number of times the symbol is used in code. | 65 /** Is this symbol in scope */ 66 public static final int IS_SCOPE = 1 << 2; 67 /** Is this a this symbol */ 68 public static final int IS_THIS = 1 << 3; 69 /** Is this a let */ 70 public static final int IS_LET = 1 << 4; 71 /** Is this a const */ 72 public static final int IS_CONST = 1 << 5; 73 /** Is this an internal symbol, never represented explicitly in source code */ 74 public static final int IS_INTERNAL = 1 << 6; 75 /** Is this a function self-reference symbol */ 76 public static final int IS_FUNCTION_SELF = 1 << 7; 77 /** Is this a function declaration? */ 78 public static final int IS_FUNCTION_DECLARATION = 1 << 8; 79 /** Is this a program level symbol? */ 80 public static final int IS_PROGRAM_LEVEL = 1 << 9; 81 /** Are this symbols' values stored in local variable slots? */ 82 public static final int HAS_SLOT = 1 << 10; 83 /** Is this symbol known to store an int value ? */ 84 public static final int HAS_INT_VALUE = 1 << 11; 85 /** Is this symbol known to store a double value ? */ 86 public static final int HAS_DOUBLE_VALUE = 1 << 12; 87 /** Is this symbol known to store an object value ? */ 88 public static final int HAS_OBJECT_VALUE = 1 << 13; 89 /** Is this symbol seen a declaration? Used for block scoped LET and CONST symbols only. */ 90 public static final int HAS_BEEN_DECLARED = 1 << 14; 91 92 /** Null or name identifying symbol. */ 93 private final String name; 94 95 /** Symbol flags. */ 96 private int flags; 97 98 /** First bytecode method local variable slot for storing the value(s) of this variable. -1 indicates the variable 99 * is not stored in local variable slots or it is not yet known. */ 100 private transient int firstSlot = -1; 101 102 /** Field number in scope or property; array index in varargs when not using arguments object. */ 103 private transient int fieldIndex = -1; 104 105 /** Number of times this symbol is used in code */ 106 private int useCount; 107 108 /** Debugging option - dump info and stack trace when symbols with given names are manipulated */ 109 private static final Set<String> TRACE_SYMBOLS; 110 private static final Set<String> TRACE_SYMBOLS_STACKTRACE; 237 * @param needsSlot True if symbol needs a slot. 238 * @return the symbol 239 */ 240 public Symbol setNeedsSlot(final boolean needsSlot) { 241 if(needsSlot) { 242 assert !isScope(); 243 flags |= HAS_SLOT; 244 } else { 245 flags &= ~HAS_SLOT; 246 } 247 return this; 248 } 249 250 /** 251 * Return the number of slots required for the symbol. 252 * 253 * @return Number of slots. 254 */ 255 public int slotCount() { 256 return ((flags & HAS_INT_VALUE) == 0 ? 0 : 1) + 257 ((flags & HAS_DOUBLE_VALUE) == 0 ? 0 : 2) + 258 ((flags & HAS_OBJECT_VALUE) == 0 ? 0 : 1); 259 } 260 261 private boolean isSlotted() { 262 return firstSlot != -1 && ((flags & HAS_SLOT) != 0); 263 } 264 265 @Override 266 public String toString() { 267 final StringBuilder sb = new StringBuilder(); 268 269 sb.append(name). 270 append(' '); 271 272 if (hasSlot()) { 273 sb.append(' '). 274 append('('). 275 append("slot="). 276 append(firstSlot).append(' '); 277 if((flags & HAS_INT_VALUE) != 0) { sb.append('I'); } 278 if((flags & HAS_DOUBLE_VALUE) != 0) { sb.append('D'); } 279 if((flags & HAS_OBJECT_VALUE) != 0) { sb.append('O'); } 280 sb.append(')'); 281 } 282 283 if (isScope()) { 284 if(isGlobal()) { 285 sb.append(" G"); 286 } else { 287 sb.append(" S"); 288 } 289 } 290 291 return sb.toString(); 292 } 293 294 @Override 295 public int compareTo(final Symbol other) { 296 return name.compareTo(other.name); 297 } 552 * @return byte code slot 553 */ 554 public int getFirstSlot() { 555 assert isSlotted(); 556 return firstSlot; 557 } 558 559 /** 560 * Get the index of the bytecode slot for this symbol for storing a value of the specified type. 561 * @param type the requested type 562 * @return byte code slot 563 */ 564 public int getSlot(final Type type) { 565 assert isSlotted(); 566 int typeSlot = firstSlot; 567 if(type.isBoolean() || type.isInteger()) { 568 assert (flags & HAS_INT_VALUE) != 0; 569 return typeSlot; 570 } 571 typeSlot += ((flags & HAS_INT_VALUE) == 0 ? 0 : 1); 572 if(type.isNumber()) { 573 assert (flags & HAS_DOUBLE_VALUE) != 0; 574 return typeSlot; 575 } 576 assert type.isObject(); 577 assert (flags & HAS_OBJECT_VALUE) != 0 : name; 578 return typeSlot + ((flags & HAS_DOUBLE_VALUE) == 0 ? 0 : 2); 579 } 580 581 /** 582 * Returns true if this symbol has a local variable slot for storing a value of specific type. 583 * @param type the type 584 * @return true if this symbol has a local variable slot for storing a value of specific type. 585 */ 586 public boolean hasSlotFor(final Type type) { 587 if(type.isBoolean() || type.isInteger()) { 588 return (flags & HAS_INT_VALUE) != 0; 589 } else if(type.isNumber()) { 590 return (flags & HAS_DOUBLE_VALUE) != 0; 591 } 592 assert type.isObject(); 593 return (flags & HAS_OBJECT_VALUE) != 0; 594 } 595 596 /** 597 * Marks this symbol as having a local variable slot for storing a value of specific type. 598 * @param type the type 599 */ 600 public void setHasSlotFor(final Type type) { 601 if(type.isBoolean() || type.isInteger()) { 602 setFlag(HAS_INT_VALUE); 603 } else if(type.isNumber()) { 604 setFlag(HAS_DOUBLE_VALUE); 605 } else { 606 assert type.isObject(); 607 setFlag(HAS_OBJECT_VALUE); 608 } 609 } 610 611 /** 612 * Increase the symbol's use count by one. 613 */ 614 public void increaseUseCount() { 615 if (isScope()) { // Avoid dirtying a cache line; we only need the use count for scoped symbols 616 useCount++; 617 } 618 } 619 620 /** 621 * Get the symbol's use count 622 * @return the number of times the symbol is used in code. |