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 
  26 package jdk.nashorn.internal.codegen;
  27 
  28 import static jdk.internal.org.objectweb.asm.Opcodes.ATHROW;
  29 import static jdk.internal.org.objectweb.asm.Opcodes.CHECKCAST;
  30 import static jdk.internal.org.objectweb.asm.Opcodes.DUP2;
  31 import static jdk.internal.org.objectweb.asm.Opcodes.GETFIELD;
  32 import static jdk.internal.org.objectweb.asm.Opcodes.GETSTATIC;
  33 import static jdk.internal.org.objectweb.asm.Opcodes.GOTO;
  34 import static jdk.internal.org.objectweb.asm.Opcodes.H_INVOKESTATIC;
  35 import static jdk.internal.org.objectweb.asm.Opcodes.IFEQ;
  36 import static jdk.internal.org.objectweb.asm.Opcodes.IFGE;
  37 import static jdk.internal.org.objectweb.asm.Opcodes.IFGT;
  38 import static jdk.internal.org.objectweb.asm.Opcodes.IFLE;
  39 import static jdk.internal.org.objectweb.asm.Opcodes.IFLT;
  40 import static jdk.internal.org.objectweb.asm.Opcodes.IFNE;
  41 import static jdk.internal.org.objectweb.asm.Opcodes.IFNONNULL;
  42 import static jdk.internal.org.objectweb.asm.Opcodes.IFNULL;
  43 import static jdk.internal.org.objectweb.asm.Opcodes.IF_ACMPEQ;
  44 import static jdk.internal.org.objectweb.asm.Opcodes.IF_ACMPNE;
  45 import static jdk.internal.org.objectweb.asm.Opcodes.IF_ICMPEQ;
  46 import static jdk.internal.org.objectweb.asm.Opcodes.IF_ICMPGE;
  47 import static jdk.internal.org.objectweb.asm.Opcodes.IF_ICMPGT;
  48 import static jdk.internal.org.objectweb.asm.Opcodes.IF_ICMPLE;
  49 import static jdk.internal.org.objectweb.asm.Opcodes.IF_ICMPLT;
  50 import static jdk.internal.org.objectweb.asm.Opcodes.IF_ICMPNE;
  51 import static jdk.internal.org.objectweb.asm.Opcodes.INSTANCEOF;
  52 import static jdk.internal.org.objectweb.asm.Opcodes.INVOKEINTERFACE;
  53 import static jdk.internal.org.objectweb.asm.Opcodes.INVOKESPECIAL;
  54 import static jdk.internal.org.objectweb.asm.Opcodes.INVOKESTATIC;
  55 import static jdk.internal.org.objectweb.asm.Opcodes.INVOKEVIRTUAL;
  56 import static jdk.internal.org.objectweb.asm.Opcodes.NEW;
  57 import static jdk.internal.org.objectweb.asm.Opcodes.PUTFIELD;
  58 import static jdk.internal.org.objectweb.asm.Opcodes.PUTSTATIC;
  59 import static jdk.internal.org.objectweb.asm.Opcodes.RETURN;
  60 import static jdk.nashorn.internal.codegen.CompilerConstants.ARGUMENTS;
  61 import static jdk.nashorn.internal.codegen.CompilerConstants.CONSTANTS;
  62 import static jdk.nashorn.internal.codegen.CompilerConstants.SCOPE;
  63 import static jdk.nashorn.internal.codegen.CompilerConstants.THIS;
  64 import static jdk.nashorn.internal.codegen.CompilerConstants.THIS_DEBUGGER;
  65 import static jdk.nashorn.internal.codegen.CompilerConstants.VARARGS;
  66 import static jdk.nashorn.internal.codegen.CompilerConstants.className;
  67 import static jdk.nashorn.internal.codegen.CompilerConstants.constructorNoLookup;
  68 import static jdk.nashorn.internal.codegen.CompilerConstants.methodDescriptor;
  69 import static jdk.nashorn.internal.codegen.CompilerConstants.staticField;
  70 import static jdk.nashorn.internal.codegen.CompilerConstants.virtualCallNoLookup;
  71 import static jdk.nashorn.internal.codegen.ObjectClassGenerator.PRIMITIVE_FIELD_TYPE;
  72 import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_OPTIMISTIC;
  73 import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_PROGRAM_POINT_SHIFT;
  74 
  75 import java.io.PrintStream;
  76 import java.lang.reflect.Array;
  77 import java.util.Collection;
  78 import java.util.EnumSet;
  79 import java.util.IdentityHashMap;
  80 import java.util.List;
  81 import java.util.Map;
  82 import jdk.internal.dynalink.support.NameCodec;
  83 import jdk.internal.org.objectweb.asm.Handle;
  84 import jdk.internal.org.objectweb.asm.MethodVisitor;
  85 import jdk.nashorn.internal.codegen.ClassEmitter.Flag;
  86 import jdk.nashorn.internal.codegen.CompilerConstants.Call;
  87 import jdk.nashorn.internal.codegen.CompilerConstants.FieldAccess;
  88 import jdk.nashorn.internal.codegen.types.ArrayType;
  89 import jdk.nashorn.internal.codegen.types.BitwiseType;
  90 import jdk.nashorn.internal.codegen.types.NumericType;
  91 import jdk.nashorn.internal.codegen.types.Type;
  92 import jdk.nashorn.internal.ir.FunctionNode;
  93 import jdk.nashorn.internal.ir.IdentNode;
  94 import jdk.nashorn.internal.ir.JoinPredecessor;
  95 import jdk.nashorn.internal.ir.LiteralNode;
  96 import jdk.nashorn.internal.ir.LocalVariableConversion;
  97 import jdk.nashorn.internal.ir.RuntimeNode;
  98 import jdk.nashorn.internal.ir.Symbol;
  99 import jdk.nashorn.internal.ir.TryNode;
 100 import jdk.nashorn.internal.objects.NativeArray;
 101 import jdk.nashorn.internal.runtime.ArgumentSetter;
 102 import jdk.nashorn.internal.runtime.Context;
 103 import jdk.nashorn.internal.runtime.Debug;
 104 import jdk.nashorn.internal.runtime.JSType;
 105 import jdk.nashorn.internal.runtime.RewriteException;
 106 import jdk.nashorn.internal.runtime.Scope;
 107 import jdk.nashorn.internal.runtime.ScriptObject;
 108 import jdk.nashorn.internal.runtime.ScriptRuntime;
 109 import jdk.nashorn.internal.runtime.UnwarrantedOptimismException;
 110 import jdk.nashorn.internal.runtime.linker.Bootstrap;
 111 import jdk.nashorn.internal.runtime.logging.DebugLogger;
 112 import jdk.nashorn.internal.runtime.options.Options;
 113 
 114 /**
 115  * This is the main function responsible for emitting method code
 116  * in a class. It maintains a type stack and keeps track of control
 117  * flow to make sure that the registered instructions don't violate
 118  * byte code verification.
 119  *
 120  * Running Nashorn with -ea will assert as soon as a type stack
 121  * becomes corrupt, for easier debugging
 122  *
 123  * Running Nashorn with -Dnashorn.codegen.debug=true will print
 124  * all generated bytecode and labels to stderr, for easier debugging,
 125  * including bytecode stack contents
 126  */
 127 public class MethodEmitter implements Emitter {
 128     /** The ASM MethodVisitor we are plugged into */
 129     private final MethodVisitor method;
 130 
 131     /** Parent classEmitter representing the class of this method */
 132     private final ClassEmitter classEmitter;
 133 
 134     /** FunctionNode representing this method, or null if none exists */
 135     protected FunctionNode functionNode;
 136 
 137     /** Current type stack for current evaluation */
 138     private Label.Stack stack;
 139 
 140     /** Check whether this emitter ever has a function return point */
 141     private boolean hasReturn;
 142 
 143     private boolean preventUndefinedLoad;
 144 
 145     /**
 146      * Map of live local variable definitions.
 147      */
 148     private final Map<Symbol, LocalVariableDef> localVariableDefs = new IdentityHashMap<>();
 149 
 150     /** The context */
 151     private final Context context;
 152 
 153     /** Threshold in chars for when string constants should be split */
 154     static final int LARGE_STRING_THRESHOLD = 32 * 1024;
 155 
 156     /** Debug flag, should we dump all generated bytecode along with stacks? */
 157     private final DebugLogger log;
 158     private final boolean     debug;
 159 
 160     /** dump stack on a particular line, or -1 if disabled */
 161     private static final int DEBUG_TRACE_LINE;
 162 
 163     static {
 164         final String tl = Options.getStringProperty("nashorn.codegen.debug.trace", "-1");
 165         int line = -1;
 166         try {
 167             line = Integer.parseInt(tl);
 168         } catch (final NumberFormatException e) {
 169             //fallthru
 170         }
 171         DEBUG_TRACE_LINE = line;
 172     }
 173 
 174     /** Bootstrap for normal indy:s */
 175     private static final Handle LINKERBOOTSTRAP  = new Handle(H_INVOKESTATIC, Bootstrap.BOOTSTRAP.className(), Bootstrap.BOOTSTRAP.name(), Bootstrap.BOOTSTRAP.descriptor());
 176 
 177     /** Bootstrap for runtime node indy:s */
 178     private static final Handle RUNTIMEBOOTSTRAP = new Handle(H_INVOKESTATIC, RuntimeCallSite.BOOTSTRAP.className(), RuntimeCallSite.BOOTSTRAP.name(), RuntimeCallSite.BOOTSTRAP.descriptor());
 179 
 180     /** Bootstrap for array populators */
 181     private static final Handle POPULATE_ARRAY_BOOTSTRAP = new Handle(H_INVOKESTATIC, RewriteException.BOOTSTRAP.className(), RewriteException.BOOTSTRAP.name(), RewriteException.BOOTSTRAP.descriptor());
 182 
 183     /**
 184      * Constructor - internal use from ClassEmitter only
 185      * @see ClassEmitter#method
 186      *
 187      * @param classEmitter the class emitter weaving the class this method is in
 188      * @param method       a method visitor
 189      */
 190     MethodEmitter(final ClassEmitter classEmitter, final MethodVisitor method) {
 191         this(classEmitter, method, null);
 192     }
 193 
 194     /**
 195      * Constructor - internal use from ClassEmitter only
 196      * @see ClassEmitter#method
 197      *
 198      * @param classEmitter the class emitter weaving the class this method is in
 199      * @param method       a method visitor
 200      * @param functionNode a function node representing this method
 201      */
 202     MethodEmitter(final ClassEmitter classEmitter, final MethodVisitor method, final FunctionNode functionNode) {
 203         this.context      = classEmitter.getContext();
 204         this.classEmitter = classEmitter;
 205         this.method       = method;
 206         this.functionNode = functionNode;
 207         this.stack        = null;
 208         this.log          = context.getLogger(CodeGenerator.class);
 209         this.debug        = log.isEnabled();
 210     }
 211 
 212     /**
 213      * Begin a method
 214      * @see Emitter
 215      */
 216     @Override
 217     public void begin() {
 218         classEmitter.beginMethod(this);
 219         newStack();
 220         method.visitCode();
 221     }
 222 
 223     /**
 224      * End a method
 225      * @see Emitter
 226      */
 227     @Override
 228     public void end() {
 229         method.visitMaxs(0, 0);
 230         method.visitEnd();
 231 
 232         classEmitter.endMethod(this);
 233     }
 234 
 235     boolean isReachable() {
 236         return stack != null;
 237     }
 238 
 239     private void doesNotContinueSequentially() {
 240         stack = null;
 241     }
 242 
 243     private void newStack() {
 244         stack = new Label.Stack();
 245     }
 246 
 247     @Override
 248     public String toString() {
 249         return "methodEmitter: " + (functionNode == null ? method : functionNode.getName()).toString() + ' ' + Debug.id(this);
 250     }
 251 
 252     /**
 253      * Push a type to the existing stack
 254      * @param type the type
 255      */
 256     void pushType(final Type type) {
 257         if (type != null) {
 258             stack.push(type);
 259         }
 260     }
 261 
 262     /**
 263      * Pop a type from the existing stack
 264      *
 265      * @param expected expected type - will assert if wrong
 266      *
 267      * @return the type that was retrieved
 268      */
 269     private Type popType(final Type expected) {
 270         final Type type = popType();
 271         assert type.isObject() && expected.isObject() ||
 272             type.isEquivalentTo(expected) : type + " is not compatible with " + expected;
 273         return type;
 274     }
 275 
 276     /**
 277      * Pop a type from the existing stack, no matter what it is.
 278      *
 279      * @return the type
 280      */
 281     private Type popType() {
 282         return stack.pop();
 283     }
 284 
 285     /**
 286      * Pop a type from the existing stack, ensuring that it is numeric. Boolean type is popped as int type.
 287      *
 288      * @return the type
 289      */
 290     private NumericType popNumeric() {
 291         final Type type = popType();
 292         if(type.isBoolean()) {
 293             // Booleans are treated as int for purposes of arithmetic operations
 294             return Type.INT;
 295         }
 296         assert type.isNumeric();
 297         return (NumericType)type;
 298     }
 299 
 300     /**
 301      * Pop a type from the existing stack, ensuring that it is an integer type
 302      * (integer or long). Boolean type is popped as int type.
 303      *
 304      * @return the type
 305      */
 306     private BitwiseType popBitwise() {
 307         final Type type = popType();
 308         if(type == Type.BOOLEAN) {
 309             return Type.INT;
 310         }
 311         return (BitwiseType)type;
 312     }
 313 
 314     private BitwiseType popInteger() {
 315         final Type type = popType();
 316         if(type == Type.BOOLEAN) {
 317             return Type.INT;
 318         }
 319         assert type == Type.INT;
 320         return (BitwiseType)type;
 321     }
 322 
 323     /**
 324      * Pop a type from the existing stack, ensuring that it is an array type,
 325      * assert if not
 326      *
 327      * @return the type
 328      */
 329     private ArrayType popArray() {
 330         final Type type = popType();
 331         assert type.isArray() : type;
 332         return (ArrayType)type;
 333     }
 334 
 335     /**
 336      * Peek a given number of slots from the top of the stack and return the
 337      * type in that slot
 338      *
 339      * @param pos the number of positions from the top, 0 is the top element
 340      *
 341      * @return the type at position "pos" on the stack
 342      */
 343     final Type peekType(final int pos) {
 344         return stack.peek(pos);
 345     }
 346 
 347     /**
 348      * Peek at the type at the top of the stack
 349      *
 350      * @return the type at the top of the stack
 351      */
 352     final Type peekType() {
 353         return stack.peek();
 354     }
 355 
 356     /**
 357      * Generate code a for instantiating a new object and push the
 358      * object type on the stack
 359      *
 360      * @param classDescriptor class descriptor for the object type
 361      * @param type the type of the new object
 362      *
 363      * @return the method emitter
 364      */
 365     MethodEmitter _new(final String classDescriptor, final Type type) {
 366         debug("new", classDescriptor);
 367         method.visitTypeInsn(NEW, classDescriptor);
 368         pushType(type);
 369         return this;
 370     }
 371 
 372     /**
 373      * Generate code a for instantiating a new object and push the
 374      * object type on the stack
 375      *
 376      * @param clazz class type to instatiate
 377      *
 378      * @return the method emitter
 379      */
 380     MethodEmitter _new(final Class<?> clazz) {
 381         return _new(className(clazz), Type.typeFor(clazz));
 382     }
 383 
 384     /**
 385      * Generate code to call the empty constructor for a class
 386      *
 387      * @param clazz class type to instatiate
 388      *
 389      * @return the method emitter
 390      */
 391     MethodEmitter newInstance(final Class<?> clazz) {
 392         return invoke(constructorNoLookup(clazz));
 393     }
 394 
 395     /**
 396      * Perform a dup, that is, duplicate the top element and
 397      * push the duplicate down a given number of positions
 398      * on the stack. This is totally type agnostic.
 399      *
 400      * @param depth the depth on which to put the copy
 401      *
 402      * @return the method emitter, or null if depth is illegal and
 403      *  has no instruction equivalent.
 404      */
 405     MethodEmitter dup(final int depth) {
 406         if (peekType().dup(method, depth) == null) {
 407             return null;
 408         }
 409 
 410         debug("dup", depth);
 411 
 412         switch (depth) {
 413         case 0: {
 414             final int l0 = stack.getTopLocalLoad();
 415             pushType(peekType());
 416             stack.markLocalLoad(l0);
 417             break;
 418         }
 419         case 1: {
 420             final int l0 = stack.getTopLocalLoad();
 421             final Type p0 = popType();
 422             final int l1 = stack.getTopLocalLoad();
 423             final Type p1 = popType();
 424             pushType(p0);
 425             stack.markLocalLoad(l0);
 426             pushType(p1);
 427             stack.markLocalLoad(l1);
 428             pushType(p0);
 429             stack.markLocalLoad(l0);
 430             break;
 431         }
 432         case 2: {
 433             final int l0 = stack.getTopLocalLoad();
 434             final Type p0 = popType();
 435             final int l1 = stack.getTopLocalLoad();
 436             final Type p1 = popType();
 437             final int l2 = stack.getTopLocalLoad();
 438             final Type p2 = popType();
 439             pushType(p0);
 440             stack.markLocalLoad(l0);
 441             pushType(p2);
 442             stack.markLocalLoad(l2);
 443             pushType(p1);
 444             stack.markLocalLoad(l1);
 445             pushType(p0);
 446             stack.markLocalLoad(l0);
 447             break;
 448         }
 449         default:
 450             assert false : "illegal dup depth = " + depth;
 451             return null;
 452         }
 453 
 454         return this;
 455     }
 456 
 457     /**
 458      * Perform a dup2, that is, duplicate the top element if it
 459      * is a category 2 type, or two top elements if they are category
 460      * 1 types, and push them on top of the stack
 461      *
 462      * @return the method emitter
 463      */
 464     MethodEmitter dup2() {
 465         debug("dup2");
 466 
 467         if (peekType().isCategory2()) {
 468             final int l0 = stack.getTopLocalLoad();
 469             pushType(peekType());
 470             stack.markLocalLoad(l0);
 471         } else {
 472             final int l0 = stack.getTopLocalLoad();
 473             final Type p0 = popType();
 474             final int l1 = stack.getTopLocalLoad();
 475             final Type p1 = popType();
 476             pushType(p0);
 477             stack.markLocalLoad(l0);
 478             pushType(p1);
 479             stack.markLocalLoad(l1);
 480             pushType(p0);
 481             stack.markLocalLoad(l0);
 482             pushType(p1);
 483             stack.markLocalLoad(l1);
 484         }
 485         method.visitInsn(DUP2);
 486         return this;
 487     }
 488 
 489     /**
 490      * Duplicate the top element on the stack and push it
 491      *
 492      * @return the method emitter
 493      */
 494     MethodEmitter dup() {
 495         return dup(0);
 496     }
 497 
 498     /**
 499      * Pop the top element of the stack and throw it away
 500      *
 501      * @return the method emitter
 502      */
 503     MethodEmitter pop() {
 504         debug("pop", peekType());
 505         popType().pop(method);
 506         return this;
 507     }
 508 
 509     /**
 510      * Pop the top element of the stack if category 2 type, or the two
 511      * top elements of the stack if category 1 types
 512      *
 513      * @return the method emitter
 514      */
 515     MethodEmitter pop2() {
 516         if (peekType().isCategory2()) {
 517             popType();
 518         } else {
 519             get2n();
 520         }
 521         return this;
 522     }
 523 
 524     /**
 525      * Swap the top two elements of the stack. This is totally
 526      * type agnostic and works for all types
 527      *
 528      * @return the method emitter
 529      */
 530     MethodEmitter swap() {
 531         debug("swap");
 532 
 533         final int l0 = stack.getTopLocalLoad();
 534         final Type p0 = popType();
 535         final int l1 = stack.getTopLocalLoad();
 536         final Type p1 = popType();
 537         p0.swap(method, p1);
 538 
 539         pushType(p0);
 540         stack.markLocalLoad(l0);
 541         pushType(p1);
 542         stack.markLocalLoad(l1);
 543         return this;
 544     }
 545 
 546     void pack() {
 547         final Type type = peekType();
 548         if (type.isInteger()) {
 549             convert(PRIMITIVE_FIELD_TYPE);
 550         } else if (type.isLong()) {
 551             //nop
 552         } else if (type.isNumber()) {
 553             invokestatic("java/lang/Double", "doubleToRawLongBits", "(D)J");
 554         } else {
 555             assert false : type + " cannot be packed!";
 556         }
 557         //all others are nops, objects aren't packed
 558     }
 559 
 560     /**
 561      * Initializes a bytecode method parameter
 562      * @param symbol the symbol for the parameter
 563      * @param type the type of the parameter
 564      * @param start the label for the start of the method
 565      */
 566     void initializeMethodParameter(final Symbol symbol, final Type type, final Label start) {
 567         assert symbol.isBytecodeLocal();
 568         localVariableDefs.put(symbol, new LocalVariableDef(start.getLabel(), type));
 569     }
 570 
 571     /**
 572      * Create a new string builder, call the constructor and push the instance to the stack.
 573      *
 574      * @return the method emitter
 575      */
 576     MethodEmitter newStringBuilder() {
 577         return invoke(constructorNoLookup(StringBuilder.class)).dup();
 578     }
 579 
 580     /**
 581      * Pop a string and a StringBuilder from the top of the stack and call the append
 582      * function of the StringBuilder, appending the string. Pushes the StringBuilder to
 583      * the stack when finished.
 584      *
 585      * @return the method emitter
 586      */
 587     MethodEmitter stringBuilderAppend() {
 588         convert(Type.STRING);
 589         return invoke(virtualCallNoLookup(StringBuilder.class, "append", StringBuilder.class, String.class));
 590     }
 591 
 592     /**
 593      * Pops two integer types from the stack, performs a bitwise and and pushes
 594      * the result
 595      *
 596      * @return the method emitter
 597      */
 598     MethodEmitter and() {
 599         debug("and");
 600         pushType(get2i().and(method));
 601         return this;
 602     }
 603 
 604     /**
 605      * Pops two integer types from the stack, performs a bitwise or and pushes
 606      * the result
 607      *
 608      * @return the method emitter
 609      */
 610     MethodEmitter or() {
 611         debug("or");
 612         pushType(get2i().or(method));
 613         return this;
 614     }
 615 
 616     /**
 617      * Pops two integer types from the stack, performs a bitwise xor and pushes
 618      * the result
 619      *
 620      * @return the method emitter
 621      */
 622     MethodEmitter xor() {
 623         debug("xor");
 624         pushType(get2i().xor(method));
 625         return this;
 626     }
 627 
 628     /**
 629      * Pops two integer types from the stack, performs a bitwise logic shift right and pushes
 630      * the result. The shift count, the first element, must be INT.
 631      *
 632      * @return the method emitter
 633      */
 634     MethodEmitter shr() {
 635         debug("shr");
 636         popInteger();
 637         pushType(popBitwise().shr(method));
 638         return this;
 639     }
 640 
 641     /**
 642      * Pops two integer types from the stack, performs a bitwise shift left and and pushes
 643      * the result. The shift count, the first element, must be INT.
 644      *
 645      * @return the method emitter
 646      */
 647     MethodEmitter shl() {
 648         debug("shl");
 649         popInteger();
 650         pushType(popBitwise().shl(method));
 651         return this;
 652     }
 653 
 654     /**
 655      * Pops two integer types from the stack, performs a bitwise arithmetic shift right and pushes
 656      * the result. The shift count, the first element, must be INT.
 657      *
 658      * @return the method emitter
 659      */
 660     MethodEmitter sar() {
 661         debug("sar");
 662         popInteger();
 663         pushType(popBitwise().sar(method));
 664         return this;
 665     }
 666 
 667     /**
 668      * Pops a numeric type from the stack, negates it and pushes the result
 669      *
 670      * @return the method emitter
 671      */
 672     MethodEmitter neg(final int programPoint) {
 673         debug("neg");
 674         pushType(popNumeric().neg(method, programPoint));
 675         return this;
 676     }
 677 
 678     /**
 679      * Add label for the start of a catch block and push the exception to the
 680      * stack
 681      *
 682      * @param recovery label pointing to start of catch block
 683      */
 684     void _catch(final Label recovery) {
 685         // While in JVM a catch block can be reached through normal control flow, our code generator never does this,
 686         // so we might as well presume there's no stack on entry.
 687         assert stack == null;
 688         recovery.onCatch();
 689         label(recovery);
 690         beginCatchBlock();
 691     }
 692 
 693     /**
 694      * Add any number of labels for the start of a catch block and push the exception to the
 695      * stack
 696      *
 697      * @param recoveries labels pointing to start of catch block
 698      */
 699     void _catch(final Collection<Label> recoveries) {
 700         assert stack == null;
 701         for(final Label l: recoveries) {
 702             label(l);
 703         }
 704         beginCatchBlock();
 705     }
 706 
 707     private void beginCatchBlock() {
 708         // It can happen that the catch label wasn't marked as reachable. They are marked as reachable if there's an
 709         // assignment in the try block, but it's possible that there was none.
 710         if(!isReachable()) {
 711             newStack();
 712         }
 713         pushType(Type.typeFor(Throwable.class));
 714     }
 715     /**
 716      * Start a try/catch block.
 717      *
 718      * @param entry          start label for try
 719      * @param exit           end label for try
 720      * @param recovery       start label for catch
 721      * @param typeDescriptor type descriptor for exception
 722      * @param isOptimismHandler true if this is a hander for {@code UnwarrantedOptimismException}. Normally joining on a
 723      * catch handler kills temporary variables, but optimism handlers are an exception, as they need to capture
 724      * temporaries as well, so they must remain live.
 725      */
 726     private void _try(final Label entry, final Label exit, final Label recovery, final String typeDescriptor, final boolean isOptimismHandler) {
 727         recovery.joinFromTry(entry.getStack(), isOptimismHandler);
 728         method.visitTryCatchBlock(entry.getLabel(), exit.getLabel(), recovery.getLabel(), typeDescriptor);
 729     }
 730 
 731     /**
 732      * Start a try/catch block.
 733      *
 734      * @param entry    start label for try
 735      * @param exit     end label for try
 736      * @param recovery start label for catch
 737      * @param clazz    exception class
 738      */
 739     void _try(final Label entry, final Label exit, final Label recovery, final Class<?> clazz) {
 740         _try(entry, exit, recovery, CompilerConstants.className(clazz), clazz == UnwarrantedOptimismException.class);
 741     }
 742 
 743     /**
 744      * Start a try/catch block. The catch is "Throwable" - i.e. catch-all
 745      *
 746      * @param entry    start label for try
 747      * @param exit     end label for try
 748      * @param recovery start label for catch
 749      */
 750     void _try(final Label entry, final Label exit, final Label recovery) {
 751         _try(entry, exit, recovery, (String)null, false);
 752     }
 753 
 754     void markLabelAsOptimisticCatchHandler(final Label label, final int liveLocalCount) {
 755         label.markAsOptimisticCatchHandler(stack, liveLocalCount);
 756     }
 757 
 758     /**
 759      * Load the constants array
 760      * @return this method emitter
 761      */
 762     MethodEmitter loadConstants() {
 763         getStatic(classEmitter.getUnitClassName(), CONSTANTS.symbolName(), CONSTANTS.descriptor());
 764         assert peekType().isArray() : peekType();
 765         return this;
 766     }
 767 
 768     /**
 769      * Push the undefined value for the given type, i.e.
 770      * UNDEFINED or UNDEFINEDNUMBER. Currently we have no way of
 771      * representing UNDEFINED for INTs and LONGs, so they are not
 772      * allowed to be local variables (yet)
 773      *
 774      * @param type the type for which to push UNDEFINED
 775      * @return the method emitter
 776      */
 777     MethodEmitter loadUndefined(final Type type) {
 778         debug("load undefined ", type);
 779         pushType(type.loadUndefined(method));
 780         return this;
 781     }
 782 
 783     MethodEmitter loadForcedInitializer(final Type type) {
 784         debug("load forced initializer ", type);
 785         pushType(type.loadForcedInitializer(method));
 786         return this;
 787     }
 788 
 789     /**
 790      * Push the empty value for the given type, i.e. EMPTY.
 791      *
 792      * @param type the type
 793      * @return the method emitter
 794      */
 795     MethodEmitter loadEmpty(final Type type) {
 796         debug("load empty ", type);
 797         pushType(type.loadEmpty(method));
 798         return this;
 799     }
 800 
 801     /**
 802      * Push null to stack
 803      *
 804      * @return the method emitter
 805      */
 806     MethodEmitter loadNull() {
 807         debug("aconst_null");
 808         pushType(Type.OBJECT.ldc(method, null));
 809         return this;
 810     }
 811 
 812     /**
 813      * Push a handle representing this class top stack
 814      *
 815      * @param className name of the class
 816      *
 817      * @return the method emitter
 818      */
 819     MethodEmitter loadType(final String className) {
 820         debug("load type", className);
 821         method.visitLdcInsn(jdk.internal.org.objectweb.asm.Type.getObjectType(className));
 822         pushType(Type.OBJECT);
 823         return this;
 824     }
 825 
 826     /**
 827      * Push a boolean constant to the stack.
 828      *
 829      * @param b value of boolean
 830      *
 831      * @return the method emitter
 832      */
 833     MethodEmitter load(final boolean b) {
 834         debug("load boolean", b);
 835         pushType(Type.BOOLEAN.ldc(method, b));
 836         return this;
 837     }
 838 
 839     /**
 840      * Push an int constant to the stack
 841      *
 842      * @param i value of the int
 843      *
 844      * @return the method emitter
 845      */
 846     MethodEmitter load(final int i) {
 847         debug("load int", i);
 848         pushType(Type.INT.ldc(method, i));
 849         return this;
 850     }
 851 
 852     /**
 853      * Push a double constant to the stack
 854      *
 855      * @param d value of the double
 856      *
 857      * @return the method emitter
 858      */
 859     MethodEmitter load(final double d) {
 860         debug("load double", d);
 861         pushType(Type.NUMBER.ldc(method, d));
 862         return this;
 863     }
 864 
 865     /**
 866      * Push an long constant to the stack
 867      *
 868      * @param l value of the long
 869      *
 870      * @return the method emitter
 871      */
 872     MethodEmitter load(final long l) {
 873         debug("load long", l);
 874         pushType(Type.LONG.ldc(method, l));
 875         return this;
 876     }
 877 
 878     /**
 879      * Fetch the length of an array.
 880      * @return Array length.
 881      */
 882     MethodEmitter arraylength() {
 883         debug("arraylength");
 884         popType(Type.OBJECT);
 885         pushType(Type.OBJECT_ARRAY.arraylength(method));
 886         return this;
 887     }
 888 
 889     /**
 890      * Push a String constant to the stack
 891      *
 892      * @param s value of the String
 893      *
 894      * @return the method emitter
 895      */
 896     MethodEmitter load(final String s) {
 897         debug("load string", s);
 898 
 899         if (s == null) {
 900             loadNull();
 901             return this;
 902         }
 903 
 904         //NASHORN-142 - split too large string
 905         final int length = s.length();
 906         if (length > LARGE_STRING_THRESHOLD) {
 907 
 908             _new(StringBuilder.class);
 909             dup();
 910             load(length);
 911             invoke(constructorNoLookup(StringBuilder.class, int.class));
 912 
 913             for (int n = 0; n < length; n += LARGE_STRING_THRESHOLD) {
 914                 final String part = s.substring(n, Math.min(n + LARGE_STRING_THRESHOLD, length));
 915                 load(part);
 916                 stringBuilderAppend();
 917             }
 918 
 919             invoke(virtualCallNoLookup(StringBuilder.class, "toString", String.class));
 920 
 921             return this;
 922         }
 923 
 924         pushType(Type.OBJECT.ldc(method, s));
 925         return this;
 926     }
 927 
 928     /**
 929      * Pushes the value of an identifier to the stack. If the identifier does not represent a local variable or a
 930      * parameter, this will be a no-op.
 931      *
 932      * @param ident the identifier for the variable being loaded.
 933      *
 934      * @return the method emitter
 935      */
 936     MethodEmitter load(final IdentNode ident) {
 937         return load(ident.getSymbol(), ident.getType());
 938     }
 939 
 940     /**
 941      * Pushes the value of the symbol to the stack with the specified type. No type conversion is being performed, and
 942      * the type is only being used if the symbol addresses a local variable slot. The value of the symbol is loaded if
 943      * it addresses a local variable slot, or it is a parameter (in which case it can also be loaded from a vararg array
 944      * or the arguments object). If it is neither, the operation is a no-op.
 945      *
 946      * @param symbol the symbol addressing the value being loaded
 947      * @param type the presumed type of the value when it is loaded from a local variable slot
 948      * @return the method emitter
 949      */
 950     MethodEmitter load(final Symbol symbol, final Type type) {
 951         assert symbol != null;
 952         if (symbol.hasSlot()) {
 953             final int slot = symbol.getSlot(type);
 954             debug("load symbol", symbol.getName(), " slot=", slot, "type=", type);
 955             load(type, slot);
 956            // _try(new Label("dummy"), new Label("dummy2"), recovery);
 957            // method.visitTryCatchBlock(new Label(), arg1, arg2, arg3);
 958         } else if (symbol.isParam()) {
 959             assert functionNode.isVarArg() : "Non-vararg functions have slotted parameters";
 960             final int index = symbol.getFieldIndex();
 961             if (functionNode.needsArguments()) {
 962                 // ScriptObject.getArgument(int) on arguments
 963                 debug("load symbol", symbol.getName(), " arguments index=", index);
 964                 loadCompilerConstant(ARGUMENTS);
 965                 load(index);
 966                 ScriptObject.GET_ARGUMENT.invoke(this);
 967             } else {
 968                 // array load from __varargs__
 969                 debug("load symbol", symbol.getName(), " array index=", index);
 970                 loadCompilerConstant(VARARGS);
 971                 load(symbol.getFieldIndex());
 972                 arrayload();
 973             }
 974         }
 975         return this;
 976     }
 977 
 978     /**
 979      * Push a local variable to the stack, given an explicit bytecode slot.
 980      * This is used e.g. for stub generation where we know where items like
 981      * "this" and "scope" reside.
 982      *
 983      * @param type  the type of the variable
 984      * @param slot  the slot the variable is in
 985      *
 986      * @return the method emitter
 987      */
 988     MethodEmitter load(final Type type, final int slot) {
 989         debug("explicit load", type, slot);
 990         final Type loadType = type.load(method, slot);
 991         assert loadType != null;
 992         pushType(loadType == Type.OBJECT && isThisSlot(slot) ? Type.THIS : loadType);
 993         assert !preventUndefinedLoad || (slot < stack.localVariableTypes.size() && stack.localVariableTypes.get(slot) != Type.UNKNOWN)
 994             : "Attempted load of uninitialized slot " + slot + " (as type " + type + ")";
 995         stack.markLocalLoad(slot);
 996         return this;
 997     }
 998 
 999     private boolean isThisSlot(final int slot) {
1000         if (functionNode == null) {
1001             return slot == CompilerConstants.JAVA_THIS.slot();
1002         }
1003         final int thisSlot = getCompilerConstantSymbol(THIS).getSlot(Type.OBJECT);
1004         assert !functionNode.needsCallee() || thisSlot == 1; // needsCallee -> thisSlot == 1
1005         assert functionNode.needsCallee() || thisSlot == 0; // !needsCallee -> thisSlot == 0
1006         return slot == thisSlot;
1007     }
1008 
1009     /**
1010      * Push a method handle to the stack
1011      *
1012      * @param className  class name
1013      * @param methodName method name
1014      * @param descName   descriptor
1015      * @param flags      flags that describe this handle, e.g. invokespecial new, or invoke virtual
1016      *
1017      * @return the method emitter
1018      */
1019     MethodEmitter loadHandle(final String className, final String methodName, final String descName, final EnumSet<Flag> flags) {
1020         debug("load handle ");
1021         pushType(Type.OBJECT.ldc(method, new Handle(Flag.getValue(flags), className, methodName, descName)));
1022         return this;
1023     }
1024 
1025     private Symbol getCompilerConstantSymbol(final CompilerConstants cc) {
1026         return functionNode.getBody().getExistingSymbol(cc.symbolName());
1027     }
1028 
1029     /**
1030      * True if this method has a slot allocated for the scope variable (meaning, something in the method actually needs
1031      * the scope).
1032      * @return if this method has a slot allocated for the scope variable.
1033      */
1034     boolean hasScope() {
1035         return getCompilerConstantSymbol(SCOPE).hasSlot();
1036     }
1037 
1038     MethodEmitter loadCompilerConstant(final CompilerConstants cc) {
1039         return loadCompilerConstant(cc, null);
1040     }
1041 
1042     MethodEmitter loadCompilerConstant(final CompilerConstants cc, final Type type) {
1043         if (cc == SCOPE && peekType() == Type.SCOPE) {
1044             dup();
1045             return this;
1046         }
1047         return load(getCompilerConstantSymbol(cc), type != null ? type : getCompilerConstantType(cc));
1048     }
1049 
1050     MethodEmitter loadScope() {
1051         return loadCompilerConstant(SCOPE).checkcast(Scope.class);
1052     }
1053 
1054     MethodEmitter setSplitState(final int state) {
1055         return loadScope().load(state).invoke(Scope.SET_SPLIT_STATE);
1056     }
1057 
1058     void storeCompilerConstant(final CompilerConstants cc) {
1059         storeCompilerConstant(cc, null);
1060     }
1061 
1062     void storeCompilerConstant(final CompilerConstants cc, final Type type) {
1063         final Symbol symbol = getCompilerConstantSymbol(cc);
1064         if(!symbol.hasSlot()) {
1065             return;
1066         }
1067         debug("store compiler constant ", symbol);
1068         store(symbol, type != null ? type : getCompilerConstantType(cc));
1069     }
1070 
1071     private static Type getCompilerConstantType(final CompilerConstants cc) {
1072         final Class<?> constantType = cc.type();
1073         assert constantType != null;
1074         return Type.typeFor(constantType);
1075     }
1076 
1077     /**
1078      * Load an element from an array, determining type automatically
1079      * @return the method emitter
1080      */
1081     MethodEmitter arrayload() {
1082         debug("Xaload");
1083         popType(Type.INT);
1084         pushType(popArray().aload(method));
1085         return this;
1086     }
1087 
1088     /**
1089      * Pop a value, an index and an array from the stack and store
1090      * the value at the given index in the array.
1091      */
1092     void arraystore() {
1093         debug("Xastore");
1094         final Type value = popType();
1095         final Type index = popType(Type.INT);
1096         assert index.isInteger() : "array index is not integer, but " + index;
1097         final ArrayType array = popArray();
1098 
1099         assert value.isEquivalentTo(array.getElementType()) : "Storing "+value+" into "+array;
1100         assert array.isObject();
1101         array.astore(method);
1102     }
1103 
1104     /**
1105      * Pop a value from the stack and store it in a local variable represented
1106      * by the given identifier. If the symbol has no slot, this is a NOP
1107      *
1108      * @param ident identifier to store stack to
1109      */
1110     void store(final IdentNode ident) {
1111         final Type type = ident.getType();
1112         final Symbol symbol = ident.getSymbol();
1113         if(type == Type.UNDEFINED) {
1114             assert peekType() == Type.UNDEFINED;
1115             store(symbol, Type.OBJECT);
1116         } else {
1117             store(symbol, type);
1118         }
1119     }
1120 
1121     /**
1122      * Represents a definition of a local variable with a type. Used for local variable table building.
1123      */
1124     private static class LocalVariableDef {
1125         // The start label from where this definition lives.
1126         private final jdk.internal.org.objectweb.asm.Label label;
1127         // The currently live type of the local variable.
1128         private final Type type;
1129 
1130         LocalVariableDef(final jdk.internal.org.objectweb.asm.Label label, final Type type) {
1131             this.label = label;
1132             this.type = type;
1133         }
1134 
1135     }
1136 
1137     void closeLocalVariable(final Symbol symbol, final Label label) {
1138         final LocalVariableDef def = localVariableDefs.get(symbol);
1139         if(def != null) {
1140             endLocalValueDef(symbol, def, label.getLabel());
1141         }
1142         if(isReachable()) {
1143             markDeadLocalVariable(symbol);
1144         }
1145     }
1146 
1147     void markDeadLocalVariable(final Symbol symbol) {
1148         if(!symbol.isDead()) {
1149             markDeadSlots(symbol.getFirstSlot(), symbol.slotCount());
1150         }
1151     }
1152 
1153     void markDeadSlots(final int firstSlot, final int slotCount) {
1154         stack.markDeadLocalVariables(firstSlot, slotCount);
1155     }
1156 
1157     private void endLocalValueDef(final Symbol symbol, final LocalVariableDef def, final jdk.internal.org.objectweb.asm.Label label) {
1158         String name = symbol.getName();
1159         if (name.equals(THIS.symbolName())) {
1160             name = THIS_DEBUGGER.symbolName();
1161         }
1162         method.visitLocalVariable(name, def.type.getDescriptor(), null, def.label, label, symbol.getSlot(def.type));
1163     }
1164 
1165     void store(final Symbol symbol, final Type type) {
1166         store(symbol, type, true);
1167     }
1168 
1169     /**
1170      * Pop a value from the stack and store it in a variable denoted by the given symbol. The variable should be either
1171      * a local variable, or a function parameter (and not a scoped variable). For local variables, this method will also
1172      * do the bookeeping of the local variable table as well as mark values in all alternative slots for the symbol as
1173      * dead. In this regard it differs from {@link #storeHidden(Type, int)}.
1174      *
1175      * @param symbol the symbol to store into.
1176      * @param type the type to store
1177      * @param onlySymbolLiveValue if true, this is the sole live value for the symbol. If false, currently live values should
1178      * be kept live.
1179      */
1180     void store(final Symbol symbol, final Type type, final boolean onlySymbolLiveValue) {
1181         assert symbol != null : "No symbol to store";
1182         if (symbol.hasSlot()) {
1183             final boolean isLiveType = symbol.hasSlotFor(type);
1184             final LocalVariableDef existingDef = localVariableDefs.get(symbol);
1185             if(existingDef == null || existingDef.type != type) {
1186                 final jdk.internal.org.objectweb.asm.Label here = new jdk.internal.org.objectweb.asm.Label();
1187                 if(isLiveType) {
1188                     final LocalVariableDef newDef = new LocalVariableDef(here, type);
1189                     localVariableDefs.put(symbol, newDef);
1190                 }
1191                 method.visitLabel(here);
1192                 if(existingDef != null) {
1193                     endLocalValueDef(symbol, existingDef, here);
1194                 }
1195             }
1196             if(isLiveType) {
1197                 final int slot = symbol.getSlot(type);
1198                 debug("store symbol", symbol.getName(), " type=", type, " slot=", slot);
1199                 storeHidden(type, slot, onlySymbolLiveValue);
1200             } else {
1201                 if(onlySymbolLiveValue) {
1202                     markDeadLocalVariable(symbol);
1203                 }
1204                 debug("dead store symbol ", symbol.getName(), " type=", type);
1205                 pop();
1206             }
1207         } else if (symbol.isParam()) {
1208             assert !symbol.isScope();
1209             assert functionNode.isVarArg() : "Non-vararg functions have slotted parameters";
1210             final int index = symbol.getFieldIndex();
1211             if (functionNode.needsArguments()) {
1212                 convert(Type.OBJECT);
1213                 debug("store symbol", symbol.getName(), " arguments index=", index);
1214                 loadCompilerConstant(ARGUMENTS);
1215                 load(index);
1216                 ArgumentSetter.SET_ARGUMENT.invoke(this);
1217             } else {
1218                 convert(Type.OBJECT);
1219                 // varargs without arguments object - just do array store to __varargs__
1220                 debug("store symbol", symbol.getName(), " array index=", index);
1221                 loadCompilerConstant(VARARGS);
1222                 load(index);
1223                 ArgumentSetter.SET_ARRAY_ELEMENT.invoke(this);
1224             }
1225         } else {
1226             debug("dead store symbol ", symbol.getName(), " type=", type);
1227             pop();
1228         }
1229     }
1230 
1231     /**
1232      * Pop a value from the stack and store it in a local variable slot. Note that in contrast with
1233      * {@link #store(Symbol, Type)}, this method does not adjust the local variable table, nor marks slots for
1234      * alternative value types for the symbol as being dead. For that reason, this method is usually not called
1235      * directly. Notable exceptions are temporary internal locals (e.g. quick store, last-catch-condition, etc.) that
1236      * are not desired to show up in the local variable table.
1237      *
1238      * @param type the type to pop
1239      * @param slot the slot
1240      */
1241     void storeHidden(final Type type, final int slot) {
1242         storeHidden(type, slot, true);
1243     }
1244 
1245     void storeHidden(final Type type, final int slot, final boolean onlyLiveSymbolValue) {
1246         explicitStore(type, slot);
1247         stack.onLocalStore(type, slot, onlyLiveSymbolValue);
1248     }
1249 
1250     void storeTemp(final Type type, final int slot) {
1251         explicitStore(type, slot);
1252         defineTemporaryLocalVariable(slot, slot + type.getSlots());
1253         onLocalStore(type, slot);
1254     }
1255 
1256     void onLocalStore(final Type type, final int slot) {
1257         stack.onLocalStore(type, slot, true);
1258     }
1259 
1260     private void explicitStore(final Type type, final int slot) {
1261         assert slot != -1;
1262         debug("explicit store", type, slot);
1263         popType(type);
1264         type.store(method, slot);
1265     }
1266 
1267     /**
1268      * Marks a range of slots as belonging to a defined local variable. The slots will start out with no live value
1269      * in them.
1270      * @param fromSlot first slot, inclusive.
1271      * @param toSlot last slot, exclusive.
1272      */
1273     void defineBlockLocalVariable(final int fromSlot, final int toSlot) {
1274         stack.defineBlockLocalVariable(fromSlot, toSlot);
1275     }
1276 
1277     /**
1278      * Marks a range of slots as belonging to a defined temporary local variable. The slots will start out with no
1279      * live value in them.
1280      * @param fromSlot first slot, inclusive.
1281      * @param toSlot last slot, exclusive.
1282      */
1283     void defineTemporaryLocalVariable(final int fromSlot, final int toSlot) {
1284         stack.defineTemporaryLocalVariable(fromSlot, toSlot);
1285     }
1286 
1287     /**
1288      * Defines a new temporary local variable and returns its allocated index.
1289      * @param width the required width (in slots) for the new variable.
1290      * @return the bytecode slot index where the newly allocated local begins.
1291      */
1292     int defineTemporaryLocalVariable(final int width) {
1293         return stack.defineTemporaryLocalVariable(width);
1294     }
1295 
1296     void undefineLocalVariables(final int fromSlot, final boolean canTruncateSymbol) {
1297         if(isReachable()) {
1298             stack.undefineLocalVariables(fromSlot, canTruncateSymbol);
1299         }
1300     }
1301 
1302     List<Type> getLocalVariableTypes() {
1303         return stack.localVariableTypes;
1304     }
1305 
1306     List<Type> getWidestLiveLocals(final List<Type> localTypes) {
1307         return stack.getWidestLiveLocals(localTypes);
1308     }
1309 
1310     String markSymbolBoundariesInLvarTypesDescriptor(final String lvarDescriptor) {
1311         return stack.markSymbolBoundariesInLvarTypesDescriptor(lvarDescriptor);
1312     }
1313 
1314     /**
1315      * Increment/Decrement a local integer by the given value.
1316      *
1317      * @param slot the int slot
1318      * @param increment the amount to increment
1319      */
1320     void iinc(final int slot, final int increment) {
1321         debug("iinc");
1322         method.visitIincInsn(slot, increment);
1323     }
1324 
1325     /**
1326      * Pop an exception object from the stack and generate code
1327      * for throwing it
1328      */
1329     public void athrow() {
1330         debug("athrow");
1331         final Type receiver = popType(Type.OBJECT);
1332         assert Throwable.class.isAssignableFrom(receiver.getTypeClass()) : receiver.getTypeClass();
1333         method.visitInsn(ATHROW);
1334         doesNotContinueSequentially();
1335     }
1336 
1337     /**
1338      * Pop an object from the stack and perform an instanceof
1339      * operation, given a classDescriptor to compare it to.
1340      * Push the boolean result 1/0 as an int to the stack
1341      *
1342      * @param classDescriptor descriptor of the class to type check against
1343      *
1344      * @return the method emitter
1345      */
1346     MethodEmitter _instanceof(final String classDescriptor) {
1347         debug("instanceof", classDescriptor);
1348         popType(Type.OBJECT);
1349         method.visitTypeInsn(INSTANCEOF, classDescriptor);
1350         pushType(Type.INT);
1351         return this;
1352     }
1353 
1354     /**
1355      * Pop an object from the stack and perform an instanceof
1356      * operation, given a classDescriptor to compare it to.
1357      * Push the boolean result 1/0 as an int to the stack
1358      *
1359      * @param clazz the type to check instanceof against
1360      *
1361      * @return the method emitter
1362      */
1363     MethodEmitter _instanceof(final Class<?> clazz) {
1364         return _instanceof(CompilerConstants.className(clazz));
1365     }
1366 
1367     /**
1368      * Perform a checkcast operation on the object at the top of the
1369      * stack.
1370      *
1371      * @param classDescriptor descriptor of the class to type check against
1372      *
1373      * @return the method emitter
1374      */
1375     MethodEmitter checkcast(final String classDescriptor) {
1376         debug("checkcast", classDescriptor);
1377         assert peekType().isObject();
1378         method.visitTypeInsn(CHECKCAST, classDescriptor);
1379         return this;
1380     }
1381 
1382     /**
1383      * Perform a checkcast operation on the object at the top of the
1384      * stack.
1385      *
1386      * @param clazz class to checkcast against
1387      *
1388      * @return the method emitter
1389      */
1390     MethodEmitter checkcast(final Class<?> clazz) {
1391         return checkcast(CompilerConstants.className(clazz));
1392     }
1393 
1394     /**
1395      * Instantiate a new array given a length that is popped
1396      * from the stack and the array type
1397      *
1398      * @param arrayType the type of the array
1399      *
1400      * @return the method emitter
1401      */
1402     MethodEmitter newarray(final ArrayType arrayType) {
1403         debug("newarray ", "arrayType=", arrayType);
1404         popType(Type.INT); //LENGTH
1405         pushType(arrayType.newarray(method));
1406         return this;
1407     }
1408 
1409     /**
1410      * Instantiate a multidimensional array with a given number of dimensions.
1411      * On the stack are dim lengths of the sub arrays.
1412      *
1413      * @param arrayType type of the array
1414      * @param dims      number of dimensions
1415      *
1416      * @return the method emitter
1417      */
1418     MethodEmitter multinewarray(final ArrayType arrayType, final int dims) {
1419         debug("multianewarray ", arrayType, dims);
1420         for (int i = 0; i < dims; i++) {
1421             popType(Type.INT); //LENGTH
1422         }
1423         pushType(arrayType.newarray(method, dims));
1424         return this;
1425     }
1426 
1427     /**
1428      * Helper function to pop and type check the appropriate arguments
1429      * from the stack given a method signature
1430      *
1431      * @param signature method signature
1432      *
1433      * @return return type of method
1434      */
1435     private Type fixParamStack(final String signature) {
1436         final Type[] params = Type.getMethodArguments(signature);
1437         for (int i = params.length - 1; i >= 0; i--) {
1438             popType(params[i]);
1439         }
1440         final Type returnType = Type.getMethodReturnType(signature);
1441         return returnType;
1442     }
1443 
1444     /**
1445      * Generate an invocation to a Call structure
1446      * @see CompilerConstants
1447      *
1448      * @param call the call object
1449      *
1450      * @return the method emitter
1451      */
1452     MethodEmitter invoke(final Call call) {
1453         return call.invoke(this);
1454     }
1455 
1456     private MethodEmitter invoke(final int opcode, final String className, final String methodName, final String methodDescriptor, final boolean hasReceiver) {
1457         final Type returnType = fixParamStack(methodDescriptor);
1458 
1459         if (hasReceiver) {
1460             popType(Type.OBJECT);
1461         }
1462 
1463         method.visitMethodInsn(opcode, className, methodName, methodDescriptor, opcode == INVOKEINTERFACE);
1464 
1465         if (returnType != null) {
1466             pushType(returnType);
1467         }
1468 
1469         return this;
1470     }
1471 
1472     /**
1473      * Pop receiver from stack, perform an invoke special
1474      *
1475      * @param className        class name
1476      * @param methodName       method name
1477      * @param methodDescriptor descriptor
1478      *
1479      * @return the method emitter
1480      */
1481     MethodEmitter invokespecial(final String className, final String methodName, final String methodDescriptor) {
1482         debug("invokespecial", className, ".", methodName, methodDescriptor);
1483         return invoke(INVOKESPECIAL, className, methodName, methodDescriptor, true);
1484     }
1485 
1486     /**
1487      * Pop receiver from stack, perform an invoke virtual, push return value if any
1488      *
1489      * @param className        class name
1490      * @param methodName       method name
1491      * @param methodDescriptor descriptor
1492      *
1493      * @return the method emitter
1494      */
1495     MethodEmitter invokevirtual(final String className, final String methodName, final String methodDescriptor) {
1496         debug("invokevirtual", className, ".", methodName, methodDescriptor, " ", stack);
1497         return invoke(INVOKEVIRTUAL, className, methodName, methodDescriptor, true);
1498     }
1499 
1500     /**
1501      * Perform an invoke static and push the return value if any
1502      *
1503      * @param className        class name
1504      * @param methodName       method name
1505      * @param methodDescriptor descriptor
1506      *
1507      * @return the method emitter
1508      */
1509     MethodEmitter invokestatic(final String className, final String methodName, final String methodDescriptor) {
1510         debug("invokestatic", className, ".", methodName, methodDescriptor);
1511         invoke(INVOKESTATIC, className, methodName, methodDescriptor, false);
1512         return this;
1513     }
1514 
1515     /**
1516      * Perform an invoke static and replace the return type if we know better, e.g. Global.allocate
1517      * that allocates an array should return an ObjectArray type as a NativeArray counts as that
1518      *
1519      * @param className        class name
1520      * @param methodName       method name
1521      * @param methodDescriptor descriptor
1522      * @param returnType       return type override
1523      *
1524      * @return the method emitter
1525      */
1526     MethodEmitter invokestatic(final String className, final String methodName, final String methodDescriptor, final Type returnType) {
1527         invokestatic(className, methodName, methodDescriptor);
1528         popType();
1529         pushType(returnType);
1530         return this;
1531     }
1532 
1533     /**
1534      * Pop receiver from stack, perform an invoke interface and push return value if any
1535      *
1536      * @param className        class name
1537      * @param methodName       method name
1538      * @param methodDescriptor descriptor
1539      *
1540      * @return the method emitter
1541      */
1542     MethodEmitter invokeinterface(final String className, final String methodName, final String methodDescriptor) {
1543         debug("invokeinterface", className, ".", methodName, methodDescriptor);
1544         return invoke(INVOKEINTERFACE, className, methodName, methodDescriptor, true);
1545     }
1546 
1547     static jdk.internal.org.objectweb.asm.Label[] getLabels(final Label... table) {
1548         final jdk.internal.org.objectweb.asm.Label[] internalLabels = new jdk.internal.org.objectweb.asm.Label[table.length];
1549         for (int i = 0; i < table.length; i++) {
1550             internalLabels[i] = table[i].getLabel();
1551         }
1552         return internalLabels;
1553     }
1554 
1555     /**
1556      * Generate a lookup switch, popping the switch value from the stack
1557      *
1558      * @param defaultLabel default label
1559      * @param values       case values for the table
1560      * @param table        default label
1561      */
1562     void lookupswitch(final Label defaultLabel, final int[] values, final Label... table) {//Collection<Label> table) {
1563         debug("lookupswitch", peekType());
1564         adjustStackForSwitch(defaultLabel, table);
1565         method.visitLookupSwitchInsn(defaultLabel.getLabel(), values, getLabels(table));
1566         doesNotContinueSequentially();
1567     }
1568 
1569     /**
1570      * Generate a table switch
1571      * @param lo            low value
1572      * @param hi            high value
1573      * @param defaultLabel  default label
1574      * @param table         label table
1575      */
1576     void tableswitch(final int lo, final int hi, final Label defaultLabel, final Label... table) {
1577         debug("tableswitch", peekType());
1578         adjustStackForSwitch(defaultLabel, table);
1579         method.visitTableSwitchInsn(lo, hi, defaultLabel.getLabel(), getLabels(table));
1580         doesNotContinueSequentially();
1581     }
1582 
1583     private void adjustStackForSwitch(final Label defaultLabel, final Label... table) {
1584         popType(Type.INT);
1585         joinTo(defaultLabel);
1586         for(final Label label: table) {
1587             joinTo(label);
1588         }
1589     }
1590 
1591     /**
1592      * Abstraction for performing a conditional jump of any type
1593      *
1594      * @see MethodEmitter.Condition
1595      *
1596      * @param cond      the condition to test
1597      * @param trueLabel the destination label is condition is true
1598      */
1599     void conditionalJump(final Condition cond, final Label trueLabel) {
1600         conditionalJump(cond, cond != Condition.GT && cond != Condition.GE, trueLabel);
1601     }
1602 
1603     /**
1604      * Abstraction for performing a conditional jump of any type,
1605      * including a dcmpg/dcmpl semantic for doubles.
1606      *
1607      * @param cond      the condition to test
1608      * @param isCmpG    is this a dcmpg for numbers, false if it's a dcmpl
1609      * @param trueLabel the destination label if condition is true
1610      */
1611     void conditionalJump(final Condition cond, final boolean isCmpG, final Label trueLabel) {
1612         if (peekType().isCategory2()) {
1613             debug("[ld]cmp isCmpG=", isCmpG);
1614             pushType(get2n().cmp(method, isCmpG));
1615             jump(Condition.toUnary(cond), trueLabel, 1);
1616         } else {
1617             debug("if", cond);
1618             jump(Condition.toBinary(cond, peekType().isObject()), trueLabel, 2);
1619         }
1620     }
1621 
1622     MethodEmitter registerReturn() {
1623         setHasReturn();
1624         return this;
1625     }
1626 
1627     void setHasReturn() {
1628         this.hasReturn = true;
1629     }
1630 
1631     /**
1632      * Perform a non void return, popping the type from the stack
1633      *
1634      * @param type the type for the return
1635      */
1636     void _return(final Type type) {
1637         debug("return", type);
1638         assert stack.size() == 1 : "Only return value on stack allowed at return point - depth=" + stack.size() + " stack = " + stack;
1639         final Type stackType = peekType();
1640         if (!Type.areEquivalent(type, stackType)) {
1641             convert(type);
1642         }
1643         popType(type)._return(method);
1644         doesNotContinueSequentially();
1645     }
1646 
1647     /**
1648      * Perform a return using the stack top value as the guide for the type
1649      */
1650     void _return() {
1651         _return(peekType());
1652     }
1653 
1654     /**
1655      * Perform a void return.
1656      */
1657     void returnVoid() {
1658         debug("return [void]");
1659         assert stack.isEmpty() : stack;
1660         method.visitInsn(RETURN);
1661         doesNotContinueSequentially();
1662     }
1663 
1664     /**
1665      * Perform a comparison of two number types that are popped from the stack
1666      *
1667      * @param isCmpG is this a dcmpg semantic, false if it's a dcmpl semantic
1668      *
1669      * @return the method emitter
1670      */
1671     MethodEmitter cmp(final boolean isCmpG) {
1672         pushType(get2n().cmp(method, isCmpG));
1673         return this;
1674     }
1675 
1676     /**
1677      * Helper function for jumps, conditional or not
1678      * @param opcode  opcode for jump
1679      * @param label   destination
1680      * @param n       elements on stack to compare, 0-2
1681      */
1682     private void jump(final int opcode, final Label label, final int n) {
1683         for (int i = 0; i < n; i++) {
1684             assert peekType().isInteger() || peekType().isBoolean() || peekType().isObject() : "expecting integer type or object for jump, but found " + peekType();
1685             popType();
1686         }
1687         joinTo(label);
1688         method.visitJumpInsn(opcode, label.getLabel());
1689     }
1690 
1691     /**
1692      * Generate an if_acmpeq
1693      *
1694      * @param label label to true case
1695      */
1696     void if_acmpeq(final Label label) {
1697         debug("if_acmpeq", label);
1698         jump(IF_ACMPEQ, label, 2);
1699     }
1700 
1701     /**
1702      * Generate an if_acmpne
1703      *
1704      * @param label label to true case
1705      */
1706     void if_acmpne(final Label label) {
1707         debug("if_acmpne", label);
1708         jump(IF_ACMPNE, label, 2);
1709     }
1710 
1711     /**
1712      * Generate an ifnull
1713      *
1714      * @param label label to true case
1715      */
1716     void ifnull(final Label label) {
1717         debug("ifnull", label);
1718         jump(IFNULL, label, 1);
1719     }
1720 
1721     /**
1722      * Generate an ifnonnull
1723      *
1724      * @param label label to true case
1725      */
1726     void ifnonnull(final Label label) {
1727         debug("ifnonnull", label);
1728         jump(IFNONNULL, label, 1);
1729     }
1730 
1731     /**
1732      * Generate an ifeq
1733      *
1734      * @param label label to true case
1735      */
1736     void ifeq(final Label label) {
1737         debug("ifeq ", label);
1738         jump(IFEQ, label, 1);
1739     }
1740 
1741     /**
1742      * Generate an if_icmpeq
1743      *
1744      * @param label label to true case
1745      */
1746     void if_icmpeq(final Label label) {
1747         debug("if_icmpeq", label);
1748         jump(IF_ICMPEQ, label, 2);
1749     }
1750 
1751     /**
1752      * Generate an if_ne
1753      *
1754      * @param label label to true case
1755      */
1756     void ifne(final Label label) {
1757         debug("ifne", label);
1758         jump(IFNE, label, 1);
1759     }
1760 
1761     /**
1762      * Generate an if_icmpne
1763      *
1764      * @param label label to true case
1765      */
1766     void if_icmpne(final Label label) {
1767         debug("if_icmpne", label);
1768         jump(IF_ICMPNE, label, 2);
1769     }
1770 
1771     /**
1772      * Generate an iflt
1773      *
1774      * @param label label to true case
1775      */
1776     void iflt(final Label label) {
1777         debug("iflt", label);
1778         jump(IFLT, label, 1);
1779     }
1780 
1781     /**
1782      * Generate an if_icmplt
1783      *
1784      * @param label label to true case
1785      */
1786     void if_icmplt(final Label label) {
1787         debug("if_icmplt", label);
1788         jump(IF_ICMPLT, label, 2);
1789     }
1790 
1791     /**
1792      * Generate an ifle
1793      *
1794      * @param label label to true case
1795      */
1796     void ifle(final Label label) {
1797         debug("ifle", label);
1798         jump(IFLE, label, 1);
1799     }
1800 
1801     /**
1802      * Generate an if_icmple
1803      *
1804      * @param label label to true case
1805      */
1806     void if_icmple(final Label label) {
1807         debug("if_icmple", label);
1808         jump(IF_ICMPLE, label, 2);
1809     }
1810 
1811     /**
1812      * Generate an ifgt
1813      *
1814      * @param label label to true case
1815      */
1816     void ifgt(final Label label) {
1817         debug("ifgt", label);
1818         jump(IFGT, label, 1);
1819     }
1820 
1821     /**
1822      * Generate an if_icmpgt
1823      *
1824      * @param label label to true case
1825      */
1826     void if_icmpgt(final Label label) {
1827         debug("if_icmpgt", label);
1828         jump(IF_ICMPGT, label, 2);
1829     }
1830 
1831     /**
1832      * Generate an ifge
1833      *
1834      * @param label label to true case
1835      */
1836     void ifge(final Label label) {
1837         debug("ifge", label);
1838         jump(IFGE, label, 1);
1839     }
1840 
1841     /**
1842      * Generate an if_icmpge
1843      *
1844      * @param label label to true case
1845      */
1846     void if_icmpge(final Label label) {
1847         debug("if_icmpge", label);
1848         jump(IF_ICMPGE, label, 2);
1849     }
1850 
1851     /**
1852      * Unconditional jump to a label
1853      *
1854      * @param label destination label
1855      */
1856     void _goto(final Label label) {
1857         debug("goto", label);
1858         jump(GOTO, label, 0);
1859         doesNotContinueSequentially(); //whoever reaches the point after us provides the stack, because we don't
1860     }
1861 
1862     /**
1863      * Unconditional jump to the start label of a loop. It differs from ordinary {@link #_goto(Label)} in that it will
1864      * preserve the current label stack, as the next instruction after the goto is loop body that the loop will come
1865      * back to. Also used to jump at the start label of the continuation handler, as it behaves much like a loop test in
1866      * the sense that after it is evaluated, it also jumps backwards.
1867      *
1868      * @param loopStart start label of a loop
1869      */
1870     void gotoLoopStart(final Label loopStart) {
1871         debug("goto (loop)", loopStart);
1872         jump(GOTO, loopStart, 0);
1873     }
1874 
1875     /**
1876      * Unconditional jump without any control flow and data flow testing. You should not normally use this method when
1877      * generating code, except if you're very sure that you know what you're doing. Normally only used for the
1878      * admittedly torturous control flow of continuation handler plumbing.
1879      * @param target the target of the jump
1880      */
1881     void uncheckedGoto(final Label target) {
1882         method.visitJumpInsn(GOTO, target.getLabel());
1883     }
1884 
1885     /**
1886      * Potential transfer of control to a catch block.
1887      *
1888      * @param catchLabel destination catch label
1889      */
1890     void canThrow(final Label catchLabel) {
1891         catchLabel.joinFromTry(stack, false);
1892     }
1893 
1894     /**
1895      * A join in control flow - helper function that makes sure all entry stacks
1896      * discovered for the join point so far are equivalent
1897      *
1898      * MergeStack: we are about to enter a label. If its stack, label.getStack() is null
1899      * we have never been here before. Then we are expected to carry a stack with us.
1900      *
1901      * @param label label
1902      */
1903     private void joinTo(final Label label) {
1904         assert isReachable();
1905         label.joinFrom(stack);
1906     }
1907 
1908     /**
1909      * Register a new label, enter it here.
1910      * @param label
1911      */
1912     void label(final Label label) {
1913         breakLabel(label, -1);
1914     }
1915 
1916     /**
1917      * Register a new break target label, enter it here.
1918      *
1919      * @param label the label
1920      * @param liveLocals the number of live locals at this label
1921      */
1922     void breakLabel(final Label label, final int liveLocals) {
1923         if (!isReachable()) {
1924             // If we emit a label, and the label's stack is null, it must not be reachable.
1925             assert (label.getStack() == null) != label.isReachable();
1926         } else {
1927             joinTo(label);
1928         }
1929         // Use label's stack as we might have no stack.
1930         final Label.Stack labelStack = label.getStack();
1931         stack = labelStack == null ? null : labelStack.clone();
1932         if(stack != null && label.isBreakTarget() && liveLocals != -1) {
1933             // This has to be done because we might not have another frame to provide us with its firstTemp if the label
1934             // is only reachable through a break or continue statement; also in this case, the frame can actually
1935             // give us a higher number of live locals, e.g. if it comes from a catch. Typical example:
1936             // for(;;) { try{ throw 0; } catch(e) { break; } }.
1937             // Since the for loop can only be exited through the break in the catch block, it'll bring with it the
1938             // "e" as a live local, and we need to trim it off here.
1939             assert stack.firstTemp >= liveLocals;
1940             stack.firstTemp = liveLocals;
1941         }
1942         debug_label(label);
1943         method.visitLabel(label.getLabel());
1944     }
1945 
1946     /**
1947      * Pop element from stack, convert to given type
1948      *
1949      * @param to type to convert to
1950      *
1951      * @return the method emitter
1952      */
1953     MethodEmitter convert(final Type to) {
1954         final Type from = peekType();
1955         final Type type = from.convert(method, to);
1956         if (type != null) {
1957             if (!from.isEquivalentTo(to)) {
1958                 debug("convert", from, "->", to);
1959             }
1960             if (type != from) {
1961                 final int l0 = stack.getTopLocalLoad();
1962                 popType();
1963                 pushType(type);
1964                 // NOTE: conversions from a primitive type are considered to preserve the "load" property of the value
1965                 // on the stack. Otherwise we could introduce temporary locals in a deoptimized rest-of (e.g. doing an
1966                 // "i < x.length" where "i" is int and ".length" gets deoptimized to long would end up converting i to
1967                 // long with "ILOAD i; I2L; LSTORE tmp; LLOAD tmp;"). Such additional temporary would cause an error
1968                 // when restoring the state of the function for rest-of execution, as the not-yet deoptimized variant
1969                 // would have the (now invalidated) assumption that "x.length" is an int, so it wouldn't have the I2L,
1970                 // and therefore neither the subsequent LSTORE tmp; LLOAD tmp;. By making sure conversions from a
1971                 // primitive type don't erase the "load" information, we don't introduce temporaries in the deoptimized
1972                 // rest-of that didn't exist in the more optimistic version that triggered the deoptimization.
1973                 // NOTE: as a more general observation, we could theoretically track the operations required to
1974                 // reproduce any stack value as long as they are all local loads, constant loads, and stack operations.
1975                 // We won't go there in the current system
1976                 if(!from.isObject()) {
1977                     stack.markLocalLoad(l0);
1978                 }
1979             }
1980         }
1981         return this;
1982     }
1983 
1984     /**
1985      * Helper function - expect two types that are equivalent
1986      *
1987      * @return common type
1988      */
1989     private Type get2() {
1990         final Type p0 = popType();
1991         final Type p1 = popType();
1992         assert p0.isEquivalentTo(p1) : "expecting equivalent types on stack but got " + p0 + " and " + p1;
1993         return p0;
1994     }
1995 
1996     /**
1997      * Helper function - expect two types that are integer types and equivalent
1998      *
1999      * @return common type
2000      */
2001     private BitwiseType get2i() {
2002         final BitwiseType p0 = popBitwise();
2003         final BitwiseType p1 = popBitwise();
2004         assert p0.isEquivalentTo(p1) : "expecting equivalent types on stack but got " + p0 + " and " + p1;
2005         return p0;
2006     }
2007 
2008     /**
2009      * Helper function - expect two types that are numbers and equivalent
2010      *
2011      * @return common type
2012      */
2013     private NumericType get2n() {
2014         final NumericType p0 = popNumeric();
2015         final NumericType p1 = popNumeric();
2016         assert p0.isEquivalentTo(p1) : "expecting equivalent types on stack but got " + p0 + " and " + p1;
2017         return p0;
2018     }
2019 
2020     /**
2021      * Pop two numbers, perform addition and push result
2022      *
2023      * @return the method emitter
2024      */
2025     MethodEmitter add(final int programPoint) {
2026         debug("add");
2027         pushType(get2().add(method, programPoint));
2028         return this;
2029     }
2030 
2031     /**
2032      * Pop two numbers, perform subtraction and push result
2033      *
2034      * @return the method emitter
2035      */
2036     MethodEmitter sub(final int programPoint) {
2037         debug("sub");
2038         pushType(get2n().sub(method, programPoint));
2039         return this;
2040     }
2041 
2042     /**
2043      * Pop two numbers, perform multiplication and push result
2044      *
2045      * @return the method emitter
2046      */
2047     MethodEmitter mul(final int programPoint) {
2048         debug("mul ");
2049         pushType(get2n().mul(method, programPoint));
2050         return this;
2051     }
2052 
2053     /**
2054      * Pop two numbers, perform division and push result
2055      *
2056      * @return the method emitter
2057      */
2058     MethodEmitter div(final int programPoint) {
2059         debug("div");
2060         pushType(get2n().div(method, programPoint));
2061         return this;
2062     }
2063 
2064     /**
2065      * Pop two numbers, calculate remainder and push result
2066      *
2067      * @return the method emitter
2068      */
2069     MethodEmitter rem(final int programPoint) {
2070         debug("rem");
2071         pushType(get2n().rem(method, programPoint));
2072         return this;
2073     }
2074 
2075     /**
2076      * Retrieve the top <tt>count</tt> types on the stack without modifying it.
2077      *
2078      * @param count number of types to return
2079      * @return array of Types
2080      */
2081     protected Type[] getTypesFromStack(final int count) {
2082         return stack.getTopTypes(count);
2083     }
2084 
2085     int[] getLocalLoadsOnStack(final int from, final int to) {
2086         return stack.getLocalLoads(from, to);
2087     }
2088 
2089     int getStackSize() {
2090         return stack.size();
2091     }
2092 
2093     int getFirstTemp() {
2094         return stack.firstTemp;
2095     }
2096 
2097     int getUsedSlotsWithLiveTemporaries() {
2098         return stack.getUsedSlotsWithLiveTemporaries();
2099     }
2100 
2101     /**
2102      * Helper function to generate a function signature based on stack contents
2103      * and argument count and return type
2104      *
2105      * @param returnType return type
2106      * @param argCount   argument count
2107      *
2108      * @return function signature for stack contents
2109      */
2110     private String getDynamicSignature(final Type returnType, final int argCount) {
2111         final Type[]         paramTypes = new Type[argCount];
2112 
2113         int pos = 0;
2114         for (int i = argCount - 1; i >= 0; i--) {
2115             Type pt = stack.peek(pos++);
2116             // "erase" specific ScriptObject subtype info - except for NativeArray.
2117             // NativeArray is used for array/List/Deque conversion for Java calls.
2118             if (ScriptObject.class.isAssignableFrom(pt.getTypeClass()) &&
2119                 !NativeArray.class.isAssignableFrom(pt.getTypeClass())) {
2120                 pt = Type.SCRIPT_OBJECT;
2121             }
2122             paramTypes[i] = pt;
2123         }
2124         final String descriptor = Type.getMethodDescriptor(returnType, paramTypes);
2125         for (int i = 0; i < argCount; i++) {
2126             popType(paramTypes[argCount - i - 1]);
2127         }
2128 
2129         return descriptor;
2130     }
2131 
2132     MethodEmitter invalidateSpecialName(final String name) {
2133         switch (name) {
2134         case "apply":
2135         case "call":
2136             debug("invalidate_name", "name=", name);
2137             load("Function");
2138             invoke(ScriptRuntime.INVALIDATE_RESERVED_BUILTIN_NAME);
2139             break;
2140         default:
2141             break;
2142         }
2143         return this;
2144     }
2145 
2146     /**
2147      * Generate a dynamic new
2148      *
2149      * @param argCount  number of arguments
2150      * @param flags     callsite flags
2151      *
2152      * @return the method emitter
2153      */
2154     MethodEmitter dynamicNew(final int argCount, final int flags) {
2155         assert !isOptimistic(flags);
2156         debug("dynamic_new", "argcount=", argCount);
2157         final String signature = getDynamicSignature(Type.OBJECT, argCount);
2158         method.visitInvokeDynamicInsn("dyn:new", signature, LINKERBOOTSTRAP, flags);
2159         pushType(Type.OBJECT); //TODO fix result type
2160         return this;
2161     }
2162 
2163     /**
2164      * Generate a dynamic call
2165      *
2166      * @param returnType return type
2167      * @param argCount   number of arguments
2168      * @param flags      callsite flags
2169      *
2170      * @return the method emitter
2171      */
2172     MethodEmitter dynamicCall(final Type returnType, final int argCount, final int flags) {
2173         debug("dynamic_call", "args=", argCount, "returnType=", returnType);
2174         final String signature = getDynamicSignature(returnType, argCount); // +1 because the function itself is the 1st parameter for dynamic calls (what you call - call target)
2175         debug("   signature", signature);
2176         method.visitInvokeDynamicInsn("dyn:call", signature, LINKERBOOTSTRAP, flags);
2177         pushType(returnType);
2178 
2179         return this;
2180     }
2181 
2182     MethodEmitter dynamicArrayPopulatorCall(final int argCount, final int startIndex) {
2183         debug("populate_array", "args=", argCount, "startIndex=", startIndex);
2184         final String signature = getDynamicSignature(Type.OBJECT_ARRAY, argCount);
2185         method.visitInvokeDynamicInsn("populateArray", signature, POPULATE_ARRAY_BOOTSTRAP, startIndex);
2186         pushType(Type.OBJECT_ARRAY);
2187         return this;
2188     }
2189 
2190     /**
2191      * Generate a dynamic call for a runtime node
2192      *
2193      * @param name       tag for the invoke dynamic for this runtime node
2194      * @param returnType return type
2195      * @param request    RuntimeNode request
2196      *
2197      * @return the method emitter
2198      */
2199     MethodEmitter dynamicRuntimeCall(final String name, final Type returnType, final RuntimeNode.Request request) {
2200         debug("dynamic_runtime_call", name, "args=", request.getArity(), "returnType=", returnType);
2201         final String signature = getDynamicSignature(returnType, request.getArity());
2202         debug("   signature", signature);
2203         method.visitInvokeDynamicInsn(name, signature, RUNTIMEBOOTSTRAP);
2204         pushType(returnType);
2205 
2206         return this;
2207     }
2208 
2209     /**
2210      * Generate dynamic getter. Pop scope from stack. Push result
2211      *
2212      * @param valueType type of the value to set
2213      * @param name      name of property
2214      * @param flags     call site flags
2215      * @param isMethod  should it prefer retrieving methods
2216      *
2217      * @return the method emitter
2218      */
2219     MethodEmitter dynamicGet(final Type valueType, final String name, final int flags, final boolean isMethod) {
2220         debug("dynamic_get", name, valueType, getProgramPoint(flags));
2221 
2222         Type type = valueType;
2223         if (type.isObject() || type.isBoolean()) {
2224             type = Type.OBJECT; //promote e.g strings to object generic setter
2225         }
2226 
2227         popType(Type.SCOPE);
2228         method.visitInvokeDynamicInsn((isMethod ? "dyn:getMethod|getProp|getElem:" : "dyn:getProp|getElem|getMethod:") +
2229                 NameCodec.encode(name), Type.getMethodDescriptor(type, Type.OBJECT), LINKERBOOTSTRAP, flags);
2230 
2231         pushType(type);
2232         convert(valueType); //most probably a nop
2233 
2234         return this;
2235     }
2236 
2237     /**
2238      * Generate dynamic setter. Pop receiver and property from stack.
2239      *
2240      * @param name  name of property
2241      * @param flags call site flags
2242      */
2243      void dynamicSet(final String name, final int flags) {
2244          assert !isOptimistic(flags);
2245          debug("dynamic_set", name, peekType());
2246 
2247         Type type = peekType();
2248         if (type.isObject() || type.isBoolean()) { //promote strings to objects etc
2249             type = Type.OBJECT;
2250             convert(Type.OBJECT); //TODO bad- until we specialize boolean setters,
2251         }
2252         popType(type);
2253         popType(Type.SCOPE);
2254 
2255         method.visitInvokeDynamicInsn("dyn:setProp|setElem:" + NameCodec.encode(name), methodDescriptor(void.class, Object.class, type.getTypeClass()), LINKERBOOTSTRAP, flags);
2256     }
2257 
2258      /**
2259      * Dynamic getter for indexed structures. Pop index and receiver from stack,
2260      * generate appropriate signatures based on types
2261      *
2262      * @param result result type for getter
2263      * @param flags call site flags for getter
2264      * @param isMethod should it prefer retrieving methods
2265      *
2266      * @return the method emitter
2267      */
2268     MethodEmitter dynamicGetIndex(final Type result, final int flags, final boolean isMethod) {
2269         assert result.getTypeClass().isPrimitive() || result.getTypeClass() == Object.class;
2270         debug("dynamic_get_index", peekType(1), "[", peekType(), "]", getProgramPoint(flags));
2271 
2272         Type resultType = result;
2273         if (result.isBoolean()) {
2274             resultType = Type.OBJECT; // INT->OBJECT to avoid another dimension of cross products in the getters. TODO
2275         }
2276 
2277         Type index = peekType();
2278         if (index.isObject() || index.isBoolean()) {
2279             index = Type.OBJECT; //e.g. string->object
2280             convert(Type.OBJECT);
2281         }
2282         popType();
2283 
2284         popType(Type.OBJECT);
2285 
2286         final String signature = Type.getMethodDescriptor(resultType, Type.OBJECT /*e.g STRING->OBJECT*/, index);
2287 
2288         method.visitInvokeDynamicInsn(isMethod ? "dyn:getMethod|getElem|getProp" : "dyn:getElem|getProp|getMethod", signature, LINKERBOOTSTRAP, flags);
2289         pushType(resultType);
2290 
2291         if (result.isBoolean()) {
2292             convert(Type.BOOLEAN);
2293         }
2294 
2295         return this;
2296     }
2297 
2298     private static String getProgramPoint(final int flags) {
2299         if((flags & CALLSITE_OPTIMISTIC) == 0) {
2300             return "";
2301         }
2302         return "pp=" + String.valueOf((flags & (-1 << CALLSITE_PROGRAM_POINT_SHIFT)) >> CALLSITE_PROGRAM_POINT_SHIFT);
2303     }
2304 
2305     /**
2306      * Dynamic setter for indexed structures. Pop value, index and receiver from
2307      * stack, generate appropriate signature based on types
2308      *
2309      * @param flags call site flags for setter
2310      */
2311     void dynamicSetIndex(final int flags) {
2312         assert !isOptimistic(flags);
2313         debug("dynamic_set_index", peekType(2), "[", peekType(1), "] =", peekType());
2314 
2315         Type value = peekType();
2316         if (value.isObject() || value.isBoolean()) {
2317             value = Type.OBJECT; //e.g. STRING->OBJECT - one descriptor for all object types
2318             convert(Type.OBJECT);
2319         }
2320         popType();
2321 
2322         Type index = peekType();
2323         if (index.isObject() || index.isBoolean()) {
2324             index = Type.OBJECT; //e.g. string->object
2325             convert(Type.OBJECT);
2326         }
2327         popType(index);
2328 
2329         final Type receiver = popType(Type.OBJECT);
2330         assert receiver.isObject();
2331 
2332         method.visitInvokeDynamicInsn("dyn:setElem|setProp", methodDescriptor(void.class, receiver.getTypeClass(), index.getTypeClass(), value.getTypeClass()), LINKERBOOTSTRAP, flags);
2333     }
2334 
2335     /**
2336      * Load a key value in the proper form.
2337      *
2338      * @param key
2339      */
2340     //TODO move this and break it apart
2341     MethodEmitter loadKey(final Object key) {
2342         if (key instanceof IdentNode) {
2343             method.visitLdcInsn(((IdentNode) key).getName());
2344         } else if (key instanceof LiteralNode) {
2345             method.visitLdcInsn(((LiteralNode<?>)key).getString());
2346         } else {
2347             method.visitLdcInsn(JSType.toString(key));
2348         }
2349         pushType(Type.OBJECT); //STRING
2350         return this;
2351     }
2352 
2353      @SuppressWarnings("fallthrough")
2354      private static Type fieldType(final String desc) {
2355          switch (desc) {
2356          case "Z":
2357          case "B":
2358          case "C":
2359          case "S":
2360          case "I":
2361              return Type.INT;
2362          case "F":
2363              assert false;
2364          case "D":
2365              return Type.NUMBER;
2366          case "J":
2367              return Type.LONG;
2368          default:
2369              assert desc.startsWith("[") || desc.startsWith("L") : desc + " is not an object type";
2370              switch (desc.charAt(0)) {
2371              case 'L':
2372                  return Type.OBJECT;
2373              case '[':
2374                  return Type.typeFor(Array.newInstance(fieldType(desc.substring(1)).getTypeClass(), 0).getClass());
2375              default:
2376                  assert false;
2377              }
2378              return Type.OBJECT;
2379          }
2380      }
2381 
2382      /**
2383       * Generate get for a field access
2384       *
2385       * @param fa the field access
2386       *
2387       * @return the method emitter
2388       */
2389     MethodEmitter getField(final FieldAccess fa) {
2390         return fa.get(this);
2391     }
2392 
2393      /**
2394       * Generate set for a field access
2395       *
2396       * @param fa the field access
2397       */
2398     void putField(final FieldAccess fa) {
2399         fa.put(this);
2400     }
2401 
2402     /**
2403      * Get the value of a non-static field, pop the receiver from the stack,
2404      * push value to the stack
2405      *
2406      * @param className        class
2407      * @param fieldName        field name
2408      * @param fieldDescriptor  field descriptor
2409      *
2410      * @return the method emitter
2411      */
2412     MethodEmitter getField(final String className, final String fieldName, final String fieldDescriptor) {
2413         debug("getfield", "receiver=", peekType(), className, ".", fieldName, fieldDescriptor);
2414         final Type receiver = popType();
2415         assert receiver.isObject();
2416         method.visitFieldInsn(GETFIELD, className, fieldName, fieldDescriptor);
2417         pushType(fieldType(fieldDescriptor));
2418         return this;
2419     }
2420 
2421     /**
2422      * Get the value of a static field, push it to the stack
2423      *
2424      * @param className        class
2425      * @param fieldName        field name
2426      * @param fieldDescriptor  field descriptor
2427      *
2428      * @return the method emitter
2429      */
2430     MethodEmitter getStatic(final String className, final String fieldName, final String fieldDescriptor) {
2431         debug("getstatic", className, ".", fieldName, ".", fieldDescriptor);
2432         method.visitFieldInsn(GETSTATIC, className, fieldName, fieldDescriptor);
2433         pushType(fieldType(fieldDescriptor));
2434         return this;
2435     }
2436 
2437     /**
2438      * Pop value and field from stack and write to a non-static field
2439      *
2440      * @param className       class
2441      * @param fieldName       field name
2442      * @param fieldDescriptor field descriptor
2443      */
2444     void putField(final String className, final String fieldName, final String fieldDescriptor) {
2445         debug("putfield", "receiver=", peekType(1), "value=", peekType());
2446         popType(fieldType(fieldDescriptor));
2447         popType(Type.OBJECT);
2448         method.visitFieldInsn(PUTFIELD, className, fieldName, fieldDescriptor);
2449     }
2450 
2451     /**
2452      * Pop value from stack and write to a static field
2453      *
2454      * @param className       class
2455      * @param fieldName       field name
2456      * @param fieldDescriptor field descriptor
2457      */
2458     void putStatic(final String className, final String fieldName, final String fieldDescriptor) {
2459         debug("putfield", "value=", peekType());
2460         popType(fieldType(fieldDescriptor));
2461         method.visitFieldInsn(PUTSTATIC, className, fieldName, fieldDescriptor);
2462     }
2463 
2464     /**
2465      * Register line number at a label
2466      *
2467      * @param line  line number
2468      */
2469     void lineNumber(final int line) {
2470         if (context.getEnv()._debug_lines) {
2471             debug_label("[LINE]", line);
2472             final jdk.internal.org.objectweb.asm.Label l = new jdk.internal.org.objectweb.asm.Label();
2473             method.visitLabel(l);
2474             method.visitLineNumber(line, l);
2475         }
2476     }
2477 
2478     void beforeJoinPoint(final JoinPredecessor joinPredecessor) {
2479         LocalVariableConversion next = joinPredecessor.getLocalVariableConversion();
2480         while(next != null) {
2481             final Symbol symbol = next.getSymbol();
2482             if(next.isLive()) {
2483                 emitLocalVariableConversion(next, true);
2484             } else {
2485                 markDeadLocalVariable(symbol);
2486             }
2487             next = next.getNext();
2488         }
2489     }
2490 
2491     void beforeTry(final TryNode tryNode, final Label recovery) {
2492         LocalVariableConversion next = tryNode.getLocalVariableConversion();
2493         while(next != null) {
2494             if(next.isLive()) {
2495                 final Type to = emitLocalVariableConversion(next, false);
2496                 recovery.getStack().onLocalStore(to, next.getSymbol().getSlot(to), true);
2497             }
2498             next = next.getNext();
2499         }
2500     }
2501 
2502     private Type emitLocalVariableConversion(final LocalVariableConversion conversion, final boolean onlySymbolLiveValue) {
2503         final Type from = conversion.getFrom();
2504         final Type to = conversion.getTo();
2505         final Symbol symbol = conversion.getSymbol();
2506         assert symbol.isBytecodeLocal();
2507         if(from == Type.UNDEFINED) {
2508             loadUndefined(to);
2509         } else {
2510             load(symbol, from).convert(to);
2511         }
2512         store(symbol, to, onlySymbolLiveValue);
2513         return to;
2514     }
2515 
2516     /*
2517      * Debugging below
2518      */
2519 
2520     private final FieldAccess ERR_STREAM       = staticField(System.class, "err", PrintStream.class);
2521     private final Call        PRINT            = virtualCallNoLookup(PrintStream.class, "print", void.class, Object.class);
2522     private final Call        PRINTLN          = virtualCallNoLookup(PrintStream.class, "println", void.class, Object.class);
2523     private final Call        PRINT_STACKTRACE = virtualCallNoLookup(Throwable.class, "printStackTrace", void.class);
2524 
2525     /**
2526      * Emit a System.err.print statement of whatever is on top of the bytecode stack
2527      */
2528      void print() {
2529          getField(ERR_STREAM);
2530          swap();
2531          convert(Type.OBJECT);
2532          invoke(PRINT);
2533      }
2534 
2535     /**
2536      * Emit a System.err.println statement of whatever is on top of the bytecode stack
2537      */
2538      void println() {
2539          getField(ERR_STREAM);
2540          swap();
2541          convert(Type.OBJECT);
2542          invoke(PRINTLN);
2543      }
2544 
2545      /**
2546       * Emit a System.err.print statement
2547       * @param string string to print
2548       */
2549      void print(final String string) {
2550          getField(ERR_STREAM);
2551          load(string);
2552          invoke(PRINT);
2553      }
2554 
2555      /**
2556       * Emit a System.err.println statement
2557       * @param string string to print
2558       */
2559      void println(final String string) {
2560          getField(ERR_STREAM);
2561          load(string);
2562          invoke(PRINTLN);
2563      }
2564 
2565      /**
2566       * Print a stacktrace to S
2567       */
2568      void stacktrace() {
2569          _new(Throwable.class);
2570          dup();
2571          invoke(constructorNoLookup(Throwable.class));
2572          invoke(PRINT_STACKTRACE);
2573      }
2574 
2575     private static int linePrefix = 0;
2576 
2577     /**
2578      * Debug function that outputs generated bytecode and stack contents
2579      *
2580      * @param args debug information to print
2581      */
2582     @SuppressWarnings("unused")
2583     private void debug(final Object... args) {
2584         if (debug) {
2585             debug(30, args);
2586         }
2587     }
2588 
2589     private void debug(final String arg) {
2590         if (debug) {
2591             debug(30, arg);
2592         }
2593     }
2594 
2595     private void debug(final Object arg0, final Object arg1) {
2596         if (debug) {
2597             debug(30, new Object[] { arg0, arg1 });
2598         }
2599     }
2600 
2601     private void debug(final Object arg0, final Object arg1, final Object arg2) {
2602         if (debug) {
2603             debug(30, new Object[] { arg0, arg1, arg2 });
2604         }
2605     }
2606 
2607     private void debug(final Object arg0, final Object arg1, final Object arg2, final Object arg3) {
2608         if (debug) {
2609             debug(30, new Object[] { arg0, arg1, arg2, arg3 });
2610         }
2611     }
2612 
2613     private void debug(final Object arg0, final Object arg1, final Object arg2, final Object arg3, final Object arg4) {
2614         if (debug) {
2615             debug(30, new Object[] { arg0, arg1, arg2, arg3, arg4 });
2616         }
2617     }
2618 
2619     private void debug(final Object arg0, final Object arg1, final Object arg2, final Object arg3, final Object arg4, final Object arg5) {
2620         if (debug) {
2621             debug(30, new Object[] { arg0, arg1, arg2, arg3, arg4, arg5 });
2622         }
2623     }
2624 
2625     private void debug(final Object arg0, final Object arg1, final Object arg2, final Object arg3, final Object arg4, final Object arg5, final Object arg6) {
2626         if (debug) {
2627             debug(30, new Object[] { arg0, arg1, arg2, arg3, arg4, arg5, arg6 });
2628         }
2629     }
2630 
2631     /**
2632      * Debug function that outputs generated bytecode and stack contents
2633      * for a label - indentation is currently the only thing that differs
2634      *
2635      * @param args debug information to print
2636      */
2637     private void debug_label(final Object... args) {
2638         if (debug) {
2639             debug(22, args);
2640         }
2641     }
2642 
2643     private void debug(final int padConstant, final Object... args) {
2644         if (debug) {
2645             final StringBuilder sb = new StringBuilder();
2646             int pad;
2647 
2648             sb.append('#');
2649             sb.append(++linePrefix);
2650 
2651             pad = 5 - sb.length();
2652             while (pad > 0) {
2653                 sb.append(' ');
2654                 pad--;
2655             }
2656 
2657             if (isReachable() && !stack.isEmpty()) {
2658                 sb.append("{");
2659                 sb.append(stack.size());
2660                 sb.append(":");
2661                 for (int pos = 0; pos < stack.size(); pos++) {
2662                     final Type t = stack.peek(pos);
2663 
2664                     if (t == Type.SCOPE) {
2665                         sb.append("scope");
2666                     } else if (t == Type.THIS) {
2667                         sb.append("this");
2668                     } else if (t.isObject()) {
2669                         String desc = t.getDescriptor();
2670                         int i;
2671                         for (i = 0; desc.charAt(i) == '[' && i < desc.length(); i++) {
2672                             sb.append('[');
2673                         }
2674                         desc = desc.substring(i);
2675                         final int slash = desc.lastIndexOf('/');
2676                         if (slash != -1) {
2677                             desc = desc.substring(slash + 1, desc.length() - 1);
2678                         }
2679                         if ("Object".equals(desc)) {
2680                             sb.append('O');
2681                         } else {
2682                             sb.append(desc);
2683                         }
2684                     } else {
2685                         sb.append(t.getDescriptor());
2686                     }
2687                     final int loadIndex = stack.localLoads[stack.sp - 1 - pos];
2688                     if(loadIndex != Label.Stack.NON_LOAD) {
2689                         sb.append('(').append(loadIndex).append(')');
2690                     }
2691                     if (pos + 1 < stack.size()) {
2692                         sb.append(' ');
2693                     }
2694                 }
2695                 sb.append('}');
2696                 sb.append(' ');
2697             }
2698 
2699             pad = padConstant - sb.length();
2700             while (pad > 0) {
2701                 sb.append(' ');
2702                 pad--;
2703             }
2704 
2705             for (final Object arg : args) {
2706                 sb.append(arg);
2707                 sb.append(' ');
2708             }
2709 
2710             if (context.getEnv() != null) { //early bootstrap code doesn't have inited context yet
2711                 log.info(sb);
2712                 if (DEBUG_TRACE_LINE == linePrefix) {
2713                     new Throwable().printStackTrace(log.getOutputStream());
2714                 }
2715             }
2716         }
2717     }
2718 
2719     /**
2720      * Set the current function node being emitted
2721      * @param functionNode the function node
2722      */
2723     void setFunctionNode(final FunctionNode functionNode) {
2724         this.functionNode = functionNode;
2725     }
2726 
2727     boolean hasReturn() {
2728         return hasReturn;
2729     }
2730 
2731     /**
2732      * Invoke to enforce assertions preventing load from a local variable slot that's known to not have been written to.
2733      * Used by CodeGenerator, as it strictly enforces tracking of stores. Simpler uses of MethodEmitter, e.g. those
2734      * for creating initializers for structure  classes, array getters, etc. don't have strict tracking of stores,
2735      * therefore they would fail if they had this assertion turned on.
2736      */
2737     void setPreventUndefinedLoad() {
2738         this.preventUndefinedLoad = true;
2739     }
2740 
2741     private static boolean isOptimistic(final int flags) {
2742         return (flags & CALLSITE_OPTIMISTIC) != 0;
2743     }
2744 }