View Javadoc
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_ICMPNE;
47  import static jdk.internal.org.objectweb.asm.Opcodes.INSTANCEOF;
48  import static jdk.internal.org.objectweb.asm.Opcodes.INVOKEINTERFACE;
49  import static jdk.internal.org.objectweb.asm.Opcodes.INVOKESPECIAL;
50  import static jdk.internal.org.objectweb.asm.Opcodes.INVOKESTATIC;
51  import static jdk.internal.org.objectweb.asm.Opcodes.INVOKEVIRTUAL;
52  import static jdk.internal.org.objectweb.asm.Opcodes.NEW;
53  import static jdk.internal.org.objectweb.asm.Opcodes.PUTFIELD;
54  import static jdk.internal.org.objectweb.asm.Opcodes.PUTSTATIC;
55  import static jdk.internal.org.objectweb.asm.Opcodes.RETURN;
56  import static jdk.nashorn.internal.codegen.CompilerConstants.ARGUMENTS;
57  import static jdk.nashorn.internal.codegen.CompilerConstants.CONSTANTS;
58  import static jdk.nashorn.internal.codegen.CompilerConstants.SCOPE;
59  import static jdk.nashorn.internal.codegen.CompilerConstants.THIS;
60  import static jdk.nashorn.internal.codegen.CompilerConstants.THIS_DEBUGGER;
61  import static jdk.nashorn.internal.codegen.CompilerConstants.VARARGS;
62  import static jdk.nashorn.internal.codegen.CompilerConstants.className;
63  import static jdk.nashorn.internal.codegen.CompilerConstants.constructorNoLookup;
64  import static jdk.nashorn.internal.codegen.CompilerConstants.methodDescriptor;
65  import static jdk.nashorn.internal.codegen.CompilerConstants.staticField;
66  import static jdk.nashorn.internal.codegen.CompilerConstants.virtualCallNoLookup;
67  
68  import java.io.PrintStream;
69  import java.lang.reflect.Array;
70  import java.util.EnumSet;
71  import java.util.List;
72  import jdk.internal.dynalink.support.NameCodec;
73  import jdk.internal.org.objectweb.asm.Handle;
74  import jdk.internal.org.objectweb.asm.MethodVisitor;
75  import jdk.nashorn.internal.codegen.ClassEmitter.Flag;
76  import jdk.nashorn.internal.codegen.CompilerConstants.Call;
77  import jdk.nashorn.internal.codegen.CompilerConstants.FieldAccess;
78  import jdk.nashorn.internal.codegen.types.ArrayType;
79  import jdk.nashorn.internal.codegen.types.BitwiseType;
80  import jdk.nashorn.internal.codegen.types.NumericType;
81  import jdk.nashorn.internal.codegen.types.Type;
82  import jdk.nashorn.internal.ir.FunctionNode;
83  import jdk.nashorn.internal.ir.IdentNode;
84  import jdk.nashorn.internal.ir.LexicalContext;
85  import jdk.nashorn.internal.ir.LiteralNode;
86  import jdk.nashorn.internal.ir.RuntimeNode;
87  import jdk.nashorn.internal.ir.Symbol;
88  import jdk.nashorn.internal.runtime.ArgumentSetter;
89  import jdk.nashorn.internal.runtime.Debug;
90  import jdk.nashorn.internal.runtime.DebugLogger;
91  import jdk.nashorn.internal.runtime.JSType;
92  import jdk.nashorn.internal.runtime.ScriptEnvironment;
93  import jdk.nashorn.internal.runtime.ScriptObject;
94  import jdk.nashorn.internal.runtime.linker.Bootstrap;
95  import jdk.nashorn.internal.runtime.options.Options;
96  
97  /**
98   * This is the main function responsible for emitting method code
99   * in a class. It maintains a type stack and keeps track of control
100  * flow to make sure that the registered instructions don't violate
101  * byte code verification.
102  *
103  * Running Nashorn with -ea will assert as soon as a type stack
104  * becomes corrupt, for easier debugging
105  *
106  * Running Nashorn with -Dnashorn.codegen.debug=true will print
107  * all generated bytecode and labels to stderr, for easier debugging,
108  * including bytecode stack contents
109  */
110 public class MethodEmitter implements Emitter {
111     /** The ASM MethodVisitor we are plugged into */
112     private final MethodVisitor method;
113 
114     /** Current type stack for current evaluation */
115     private Label.Stack stack;
116 
117     /** Parent classEmitter representing the class of this method */
118     private final ClassEmitter classEmitter;
119 
120     /** FunctionNode representing this method, or null if none exists */
121     protected FunctionNode functionNode;
122 
123     /** Check whether this emitter ever has a function return point */
124     private boolean hasReturn;
125 
126     /** The script environment */
127     private final ScriptEnvironment env;
128 
129     /** Threshold in chars for when string constants should be split */
130     static final int LARGE_STRING_THRESHOLD = 32 * 1024;
131 
132     /** Debug flag, should we dump all generated bytecode along with stacks? */
133     private static final DebugLogger LOG   = new DebugLogger("codegen", "nashorn.codegen.debug");
134     private static final boolean     DEBUG = LOG.isEnabled();
135 
136     /** dump stack on a particular line, or -1 if disabled */
137     private static final int DEBUG_TRACE_LINE;
138 
139     static {
140         final String tl = Options.getStringProperty("nashorn.codegen.debug.trace", "-1");
141         int line = -1;
142         try {
143             line = Integer.parseInt(tl);
144         } catch (final NumberFormatException e) {
145             //fallthru
146         }
147         DEBUG_TRACE_LINE = line;
148     }
149 
150     /** Bootstrap for normal indy:s */
151     private static final Handle LINKERBOOTSTRAP  = new Handle(H_INVOKESTATIC, Bootstrap.BOOTSTRAP.className(), Bootstrap.BOOTSTRAP.name(), Bootstrap.BOOTSTRAP.descriptor());
152 
153     /** Bootstrap for runtime node indy:s */
154     private static final Handle RUNTIMEBOOTSTRAP = new Handle(H_INVOKESTATIC, RuntimeCallSite.BOOTSTRAP.className(), RuntimeCallSite.BOOTSTRAP.name(), RuntimeCallSite.BOOTSTRAP.descriptor());
155 
156     /**
157      * Constructor - internal use from ClassEmitter only
158      * @see ClassEmitter#method
159      *
160      * @param classEmitter the class emitter weaving the class this method is in
161      * @param method       a method visitor
162      */
163     MethodEmitter(final ClassEmitter classEmitter, final MethodVisitor method) {
164         this(classEmitter, method, null);
165     }
166 
167     /**
168      * Constructor - internal use from ClassEmitter only
169      * @see ClassEmitter#method
170      *
171      * @param classEmitter the class emitter weaving the class this method is in
172      * @param method       a method visitor
173      * @param functionNode a function node representing this method
174      */
175     MethodEmitter(final ClassEmitter classEmitter, final MethodVisitor method, final FunctionNode functionNode) {
176         this.env          = classEmitter.getEnv();
177         this.classEmitter = classEmitter;
178         this.method       = method;
179         this.functionNode = functionNode;
180         this.stack        = null;
181     }
182 
183     /**
184      * Begin a method
185      * @see Emitter
186      */
187     @Override
188     public void begin() {
189         classEmitter.beginMethod(this);
190         newStack();
191         method.visitCode();
192     }
193 
194     /**
195      * End a method
196      * @see Emitter
197      */
198     @Override
199     public void end() {
200         method.visitMaxs(0, 0);
201         method.visitEnd();
202 
203         classEmitter.endMethod(this);
204     }
205 
206     private void newStack() {
207         stack = new Label.Stack();
208     }
209 
210     @Override
211     public String toString() {
212         return "methodEmitter: " + (functionNode == null ? method : functionNode.getName()).toString() + ' ' + Debug.id(this);
213     }
214 
215     /**
216      * Push a type to the existing stack
217      * @param type the type
218      */
219     private void pushType(final Type type) {
220         if (type != null) {
221             stack.push(type);
222         }
223     }
224 
225     /**
226      * Pop a type from the existing stack
227      *
228      * @param expected expected type - will assert if wrong
229      *
230      * @return the type that was retrieved
231      */
232     private Type popType(final Type expected) {
233         final Type type = stack.pop();
234         assert type.isObject() && expected.isObject() ||
235             type.isEquivalentTo(expected) : type + " is not compatible with " + expected;
236         return type;
237     }
238 
239     /**
240      * Pop a type from the existing stack, no matter what it is.
241      *
242      * @return the type
243      */
244     private Type popType() {
245         return stack.pop();
246     }
247 
248     /**
249      * Pop a type from the existing stack, ensuring that it is numeric,
250      * assert if not
251      *
252      * @return the type
253      */
254     private NumericType popNumeric() {
255         final Type type = stack.pop();
256         assert type.isNumeric() : type + " is not numeric";
257         return (NumericType)type;
258     }
259 
260     /**
261      * Pop a type from the existing stack, ensuring that it is an integer type
262      * (integer or long), assert if not
263      *
264      * @return the type
265      */
266     private BitwiseType popInteger() {
267         final Type type = stack.pop();
268         assert type.isInteger() || type.isLong() : type + " is not an integer or long";
269         return (BitwiseType)type;
270     }
271 
272     /**
273      * Pop a type from the existing stack, ensuring that it is an array type,
274      * assert if not
275      *
276      * @return the type
277      */
278     private ArrayType popArray() {
279         final Type type = stack.pop();
280         assert type.isArray() : type;
281         return (ArrayType)type;
282     }
283 
284     /**
285      * Peek a given number of slots from the top of the stack and return the
286      * type in that slot
287      *
288      * @param pos the number of positions from the top, 0 is the top element
289      *
290      * @return the type at position "pos" on the stack
291      */
292     final Type peekType(final int pos) {
293         return stack.peek(pos);
294     }
295 
296     /**
297      * Peek at the type at the top of the stack
298      *
299      * @return the type at the top of the stack
300      */
301     final Type peekType() {
302         return stack.peek();
303     }
304 
305     /**
306      * Generate code a for instantiating a new object and push the
307      * object type on the stack
308      *
309      * @param classDescriptor class descriptor for the object type
310      *
311      * @return the method emitter
312      */
313     MethodEmitter _new(final String classDescriptor) {
314         debug("new", classDescriptor);
315         method.visitTypeInsn(NEW, classDescriptor);
316         pushType(Type.OBJECT);
317         return this;
318     }
319 
320     /**
321      * Generate code a for instantiating a new object and push the
322      * object type on the stack
323      *
324      * @param clazz class type to instatiate
325      *
326      * @return the method emitter
327      */
328     MethodEmitter _new(final Class<?> clazz) {
329         return _new(className(clazz));
330     }
331 
332     /**
333      * Generate code to call the empty constructor for a class
334      *
335      * @param clazz class type to instatiate
336      *
337      * @return the method emitter
338      */
339     MethodEmitter newInstance(final Class<?> clazz) {
340         return invoke(constructorNoLookup(clazz));
341     }
342 
343     /**
344      * Perform a dup, that is, duplicate the top element and
345      * push the duplicate down a given number of positions
346      * on the stack. This is totally type agnostic.
347      *
348      * @param depth the depth on which to put the copy
349      *
350      * @return the method emitter, or null if depth is illegal and
351      *  has no instruction equivalent.
352      */
353     MethodEmitter dup(final int depth) {
354         if (peekType().dup(method, depth) == null) {
355             return null;
356         }
357 
358         debug("dup", depth);
359 
360         switch (depth) {
361         case 0:
362             pushType(peekType());
363             break;
364         case 1: {
365             final Type p0 = popType();
366             final Type p1 = popType();
367             pushType(p0);
368             pushType(p1);
369             pushType(p0);
370             break;
371         }
372         case 2: {
373             final Type p0 = popType();
374             final Type p1 = popType();
375             final Type p2 = popType();
376             pushType(p0);
377             pushType(p2);
378             pushType(p1);
379             pushType(p0);
380             break;
381         }
382         default:
383             assert false : "illegal dup depth = " + depth;
384             return null;
385         }
386 
387         return this;
388     }
389 
390     /**
391      * Perform a dup2, that is, duplicate the top element if it
392      * is a category 2 type, or two top elements if they are category
393      * 1 types, and push them on top of the stack
394      *
395      * @return the method emitter
396      */
397     MethodEmitter dup2() {
398         debug("dup2");
399 
400         if (peekType().isCategory2()) {
401             pushType(peekType());
402         } else {
403             final Type type = get2();
404             pushType(type);
405             pushType(type);
406             pushType(type);
407             pushType(type);
408         }
409         method.visitInsn(DUP2);
410         return this;
411     }
412 
413     /**
414      * Duplicate the top element on the stack and push it
415      *
416      * @return the method emitter
417      */
418     MethodEmitter dup() {
419         return dup(0);
420     }
421 
422     /**
423      * Pop the top element of the stack and throw it away
424      *
425      * @return the method emitter
426      */
427     MethodEmitter pop() {
428         debug("pop", peekType());
429         popType().pop(method);
430         return this;
431     }
432 
433     /**
434      * Pop the top element of the stack if category 2 type, or the two
435      * top elements of the stack if category 1 types
436      *
437      * @return the method emitter
438      */
439     MethodEmitter pop2() {
440         if (peekType().isCategory2()) {
441             popType();
442         } else {
443             get2n();
444         }
445         return this;
446     }
447 
448     /**
449      * Swap the top two elements of the stack. This is totally
450      * type agnostic and works for all types
451      *
452      * @return the method emitter
453      */
454     MethodEmitter swap() {
455         debug("swap");
456 
457         final Type p0 = popType();
458         final Type p1 = popType();
459         p0.swap(method, p1);
460 
461         pushType(p0);
462         pushType(p1);
463         debug("after ", p0, p1);
464         return this;
465     }
466 
467     /**
468      * Add a local variable. This is a nop if the symbol has no slot
469      *
470      * @param symbol symbol for the local variable
471      * @param start  start of scope
472      * @param end    end of scope
473      */
474     void localVariable(final Symbol symbol, final Label start, final Label end) {
475         if (!symbol.hasSlot()) {
476             return;
477         }
478 
479         String name = symbol.getName();
480 
481         if (name.equals(THIS.symbolName())) {
482             name = THIS_DEBUGGER.symbolName();
483         }
484 
485         method.visitLocalVariable(name, symbol.getSymbolType().getDescriptor(), null, start.getLabel(), end.getLabel(), symbol.getSlot());
486     }
487 
488     /**
489      * Create a new string builder, call the constructor and push the instance to the stack.
490      *
491      * @return the method emitter
492      */
493     MethodEmitter newStringBuilder() {
494         return invoke(constructorNoLookup(StringBuilder.class)).dup();
495     }
496 
497     /**
498      * Pop a string and a StringBuilder from the top of the stack and call the append
499      * function of the StringBuilder, appending the string. Pushes the StringBuilder to
500      * the stack when finished.
501      *
502      * @return the method emitter
503      */
504     MethodEmitter stringBuilderAppend() {
505         convert(Type.STRING);
506         return invoke(virtualCallNoLookup(StringBuilder.class, "append", StringBuilder.class, String.class));
507     }
508 
509     /**
510      * Pops two integer types from the stack, performs a bitwise and and pushes
511      * the result
512      *
513      * @return the method emitter
514      */
515     MethodEmitter and() {
516         debug("and");
517         pushType(get2i().and(method));
518         return this;
519     }
520 
521     /**
522      * Pops two integer types from the stack, performs a bitwise or and pushes
523      * the result
524      *
525      * @return the method emitter
526      */
527     MethodEmitter or() {
528         debug("or");
529         pushType(get2i().or(method));
530         return this;
531     }
532 
533     /**
534      * Pops two integer types from the stack, performs a bitwise xor and pushes
535      * the result
536      *
537      * @return the method emitter
538      */
539     MethodEmitter xor() {
540         debug("xor");
541         pushType(get2i().xor(method));
542         return this;
543     }
544 
545     /**
546      * Pops two integer types from the stack, performs a bitwise logic shift right and pushes
547      * the result. The shift count, the first element, must be INT.
548      *
549      * @return the method emitter
550      */
551     MethodEmitter shr() {
552         debug("shr");
553         popType(Type.INT);
554         pushType(popInteger().shr(method));
555         return this;
556     }
557 
558     /**
559      * Pops two integer types from the stack, performs a bitwise shift left and and pushes
560      * the result. The shift count, the first element, must be INT.
561      *
562      * @return the method emitter
563      */
564     MethodEmitter shl() {
565         debug("shl");
566         popType(Type.INT);
567         pushType(popInteger().shl(method));
568         return this;
569     }
570 
571     /**
572      * Pops two integer types from the stack, performs a bitwise arithetic shift right and pushes
573      * the result. The shift count, the first element, must be INT.
574      *
575      * @return the method emitter
576      */
577     MethodEmitter sar() {
578         debug("sar");
579         popType(Type.INT);
580         pushType(popInteger().sar(method));
581         return this;
582     }
583 
584     /**
585      * Pops a numeric type from the stack, negates it and pushes the result
586      *
587      * @return the method emitter
588      */
589     MethodEmitter neg() {
590         debug("neg");
591         pushType(popNumeric().neg(method));
592         return this;
593     }
594 
595     /**
596      * Add label for the start of a catch block and push the exception to the
597      * stack
598      *
599      * @param recovery label pointing to start of catch block
600      */
601     void _catch(final Label recovery) {
602         stack.clear();
603         stack.push(Type.OBJECT);
604         label(recovery);
605     }
606 
607     /**
608      * Start a try/catch block.
609      *
610      * @param entry          start label for try
611      * @param exit           end label for try
612      * @param recovery       start label for catch
613      * @param typeDescriptor type descriptor for exception
614      */
615     void _try(final Label entry, final Label exit, final Label recovery, final String typeDescriptor) {
616         method.visitTryCatchBlock(entry.getLabel(), exit.getLabel(), recovery.getLabel(), typeDescriptor);
617     }
618 
619     /**
620      * Start a try/catch block.
621      *
622      * @param entry    start label for try
623      * @param exit     end label for try
624      * @param recovery start label for catch
625      * @param clazz    exception class
626      */
627     void _try(final Label entry, final Label exit, final Label recovery, final Class<?> clazz) {
628         method.visitTryCatchBlock(entry.getLabel(), exit.getLabel(), recovery.getLabel(), CompilerConstants.className(clazz));
629     }
630 
631     /**
632      * Start a try/catch block. The catch is "Throwable" - i.e. catch-all
633      *
634      * @param entry    start label for try
635      * @param exit     end label for try
636      * @param recovery start label for catch
637      */
638     void _try(final Label entry, final Label exit, final Label recovery) {
639         _try(entry, exit, recovery, (String)null);
640     }
641 
642 
643     /**
644      * Load the constants array
645      * @return this method emitter
646      */
647     MethodEmitter loadConstants() {
648         getStatic(classEmitter.getUnitClassName(), CONSTANTS.symbolName(), CONSTANTS.descriptor());
649         assert peekType().isArray() : peekType();
650         return this;
651     }
652 
653     /**
654      * Push the undefined value for the given type, i.e.
655      * UNDEFINED or UNDEFINEDNUMBER. Currently we have no way of
656      * representing UNDEFINED for INTs and LONGs, so they are not
657      * allowed to be local variables (yet)
658      *
659      * @param type the type for which to push UNDEFINED
660      * @return the method emitter
661      */
662     MethodEmitter loadUndefined(final Type type) {
663         debug("load undefined ", type);
664         pushType(type.loadUndefined(method));
665         return this;
666     }
667 
668     /**
669      * Push the empty value for the given type, i.e. EMPTY.
670      *
671      * @param type the type
672      * @return the method emitter
673      */
674     MethodEmitter loadEmpty(final Type type) {
675         debug("load empty ", type);
676         pushType(type.loadEmpty(method));
677         return this;
678     }
679 
680     /**
681      * Push null to stack
682      *
683      * @return the method emitter
684      */
685     MethodEmitter loadNull() {
686         debug("aconst_null");
687         pushType(Type.OBJECT.ldc(method, null));
688         return this;
689     }
690 
691     /**
692      * Push a handle representing this class top stack
693      *
694      * @param className name of the class
695      *
696      * @return the method emitter
697      */
698     MethodEmitter loadType(final String className) {
699         debug("load type", className);
700         method.visitLdcInsn(jdk.internal.org.objectweb.asm.Type.getObjectType(className));
701         pushType(Type.OBJECT);
702         return this;
703     }
704 
705     /**
706      * Push a boolean constant to the stack.
707      *
708      * @param b value of boolean
709      *
710      * @return the method emitter
711      */
712     MethodEmitter load(final boolean b) {
713         debug("load boolean", b);
714         pushType(Type.BOOLEAN.ldc(method, b));
715         return this;
716     }
717 
718     /**
719      * Push an int constant to the stack
720      *
721      * @param i value of the int
722      *
723      * @return the method emitter
724      */
725     MethodEmitter load(final int i) {
726         debug("load int", i);
727         pushType(Type.INT.ldc(method, i));
728         return this;
729     }
730 
731     /**
732      * Push a double constant to the stack
733      *
734      * @param d value of the double
735      *
736      * @return the method emitter
737      */
738     MethodEmitter load(final double d) {
739         debug("load double", d);
740         pushType(Type.NUMBER.ldc(method, d));
741         return this;
742     }
743 
744     /**
745      * Push an long constant to the stack
746      *
747      * @param l value of the long
748      *
749      * @return the method emitter
750      */
751     MethodEmitter load(final long l) {
752         debug("load long", l);
753         pushType(Type.LONG.ldc(method, l));
754         return this;
755     }
756 
757     /**
758      * Fetch the length of an array.
759      * @return Array length.
760      */
761     MethodEmitter arraylength() {
762         debug("arraylength");
763         popType(Type.OBJECT);
764         pushType(Type.OBJECT_ARRAY.arraylength(method));
765         return this;
766     }
767 
768     /**
769      * Push a String constant to the stack
770      *
771      * @param s value of the String
772      *
773      * @return the method emitter
774      */
775     MethodEmitter load(final String s) {
776         debug("load string", s);
777 
778         if (s == null) {
779             loadNull();
780             return this;
781         }
782 
783         //NASHORN-142 - split too large string
784         final int length = s.length();
785         if (length > LARGE_STRING_THRESHOLD) {
786 
787             _new(StringBuilder.class);
788             dup();
789             load(length);
790             invoke(constructorNoLookup(StringBuilder.class, int.class));
791 
792             for (int n = 0; n < length; n += LARGE_STRING_THRESHOLD) {
793                 final String part = s.substring(n, Math.min(n + LARGE_STRING_THRESHOLD, length));
794                 load(part);
795                 stringBuilderAppend();
796             }
797 
798             invoke(virtualCallNoLookup(StringBuilder.class, "toString", String.class));
799 
800             return this;
801         }
802 
803         pushType(Type.OBJECT.ldc(method, s));
804         return this;
805     }
806 
807     /**
808      * Push a local variable to the stack. If the symbol representing
809      * the local variable doesn't have a slot, this is a NOP
810      *
811      * @param symbol the symbol representing the local variable.
812      *
813      * @return the method emitter
814      */
815     MethodEmitter load(final Symbol symbol) {
816         assert symbol != null;
817         if (symbol.hasSlot()) {
818             final int slot = symbol.getSlot();
819             debug("load symbol", symbol.getName(), " slot=", slot);
820             final Type type = symbol.getSymbolType().load(method, slot);
821             pushType(type == Type.OBJECT && symbol.isThis() ? Type.THIS : type);
822         } else if (symbol.isParam()) {
823             assert !symbol.isScope();
824             assert functionNode.isVarArg() : "Non-vararg functions have slotted parameters";
825             final int index = symbol.getFieldIndex();
826             if (functionNode.needsArguments()) {
827                 // ScriptObject.getArgument(int) on arguments
828                 debug("load symbol", symbol.getName(), " arguments index=", index);
829                 loadCompilerConstant(ARGUMENTS);
830                 load(index);
831                 ScriptObject.GET_ARGUMENT.invoke(this);
832             } else {
833                 // array load from __varargs__
834                 debug("load symbol", symbol.getName(), " array index=", index);
835                 loadCompilerConstant(VARARGS);
836                 load(symbol.getFieldIndex());
837                 arrayload();
838             }
839         }
840         return this;
841     }
842 
843     /**
844      * Push a local variable to the stack, given an explicit bytecode slot
845      * This is used e.g. for stub generation where we know where items like
846      * "this" and "scope" reside.
847      *
848      * @param type  the type of the variable
849      * @param slot  the slot the variable is in
850      *
851      * @return the method emitter
852      */
853     MethodEmitter load(final Type type, final int slot) {
854         debug("explicit load", type, slot);
855         final Type loadType = type.load(method, slot);
856         pushType(loadType == Type.OBJECT && isThisSlot(slot) ? Type.THIS : loadType);
857         return this;
858     }
859 
860     private boolean isThisSlot(final int slot) {
861         if (functionNode == null) {
862             return slot == CompilerConstants.JAVA_THIS.slot();
863         }
864         final int thisSlot = compilerConstant(THIS).getSlot();
865         assert !functionNode.needsCallee() || thisSlot == 1; // needsCallee -> thisSlot == 1
866         assert functionNode.needsCallee() || thisSlot == 0; // !needsCallee -> thisSlot == 0
867         return slot == thisSlot;
868     }
869 
870     /**
871      * Push a method handle to the stack
872      *
873      * @param className  class name
874      * @param methodName method name
875      * @param descName   descriptor
876      * @param flags      flags that describe this handle, e.g. invokespecial new, or invoke virtual
877      *
878      * @return the method emitter
879      */
880     MethodEmitter loadHandle(final String className, final String methodName, final String descName, final EnumSet<Flag> flags) {
881         debug("load handle ");
882         pushType(Type.OBJECT.ldc(method, new Handle(Flag.getValue(flags), className, methodName, descName)));
883         return this;
884     }
885 
886     private Symbol compilerConstant(final CompilerConstants cc) {
887         return functionNode.getBody().getExistingSymbol(cc.symbolName());
888     }
889 
890     /**
891      * True if this method has a slot allocated for the scope variable (meaning, something in the method actually needs
892      * the scope).
893      * @return if this method has a slot allocated for the scope variable.
894      */
895     boolean hasScope() {
896         return compilerConstant(SCOPE).hasSlot();
897     }
898 
899     MethodEmitter loadCompilerConstant(final CompilerConstants cc) {
900         final Symbol symbol = compilerConstant(cc);
901         if (cc == SCOPE && peekType() == Type.SCOPE) {
902             dup();
903             return this;
904         }
905         return load(symbol);
906     }
907 
908     void storeCompilerConstant(final CompilerConstants cc) {
909         final Symbol symbol = compilerConstant(cc);
910         debug("store compiler constant ", symbol);
911         store(symbol);
912     }
913 
914     /**
915      * Load an element from an array, determining type automatically
916      * @return the method emitter
917      */
918     MethodEmitter arrayload() {
919         debug("Xaload");
920         popType(Type.INT);
921         pushType(popArray().aload(method));
922         return this;
923     }
924 
925     /**
926      * Pop a value, an index and an array from the stack and store
927      * the value at the given index in the array.
928      */
929     void arraystore() {
930         debug("Xastore");
931         final Type value = popType();
932         final Type index = popType(Type.INT);
933         assert index.isInteger() : "array index is not integer, but " + index;
934         final ArrayType array = popArray();
935 
936         assert value.isEquivalentTo(array.getElementType()) : "Storing "+value+" into "+array;
937         assert array.isObject();
938         array.astore(method);
939     }
940 
941     /**
942      * Pop a value from the stack and store it in a local variable represented
943      * by the given symbol. If the symbol has no slot, this is a NOP
944      *
945      * @param symbol symbol to store stack to
946      */
947     void store(final Symbol symbol) {
948         assert symbol != null : "No symbol to store";
949         if (symbol.hasSlot()) {
950             final int slot = symbol.getSlot();
951             debug("store symbol", symbol.getName(), " slot=", slot);
952             popType(symbol.getSymbolType()).store(method, slot);
953         } else if (symbol.isParam()) {
954             assert !symbol.isScope();
955             assert functionNode.isVarArg() : "Non-vararg functions have slotted parameters";
956             final int index = symbol.getFieldIndex();
957             if (functionNode.needsArguments()) {
958                 debug("store symbol", symbol.getName(), " arguments index=", index);
959                 loadCompilerConstant(ARGUMENTS);
960                 load(index);
961                 ArgumentSetter.SET_ARGUMENT.invoke(this);
962             } else {
963                 // varargs without arguments object - just do array store to __varargs__
964                 debug("store symbol", symbol.getName(), " array index=", index);
965                 loadCompilerConstant(VARARGS);
966                 load(index);
967                 ArgumentSetter.SET_ARRAY_ELEMENT.invoke(this);
968             }
969         }
970     }
971 
972     /**
973      * Pop a value from the stack and store it in a given local variable
974      * slot.
975      *
976      * @param type the type to pop
977      * @param slot the slot
978      */
979     void store(final Type type, final int slot) {
980         popType(type);
981         type.store(method, slot);
982     }
983 
984     /**
985      * Increment/Decrement a local integer by the given value.
986      *
987      * @param slot the int slot
988      * @param increment the amount to increment
989      */
990     void iinc(final int slot, final int increment) {
991         debug("iinc");
992         method.visitIincInsn(slot, increment);
993     }
994 
995     /**
996      * Pop an exception object from the stack and generate code
997      * for throwing it
998      */
999     public void athrow() {
1000         debug("athrow");
1001         final Type receiver = popType(Type.OBJECT);
1002         assert receiver.isObject();
1003         method.visitInsn(ATHROW);
1004         stack = null;
1005     }
1006 
1007     /**
1008      * Pop an object from the stack and perform an instanceof
1009      * operation, given a classDescriptor to compare it to.
1010      * Push the boolean result 1/0 as an int to the stack
1011      *
1012      * @param classDescriptor descriptor of the class to type check against
1013      *
1014      * @return the method emitter
1015      */
1016     MethodEmitter _instanceof(final String classDescriptor) {
1017         debug("instanceof", classDescriptor);
1018         popType(Type.OBJECT);
1019         method.visitTypeInsn(INSTANCEOF, classDescriptor);
1020         pushType(Type.INT);
1021         return this;
1022     }
1023 
1024     /**
1025      * Pop an object from the stack and perform an instanceof
1026      * operation, given a classDescriptor to compare it to.
1027      * Push the boolean result 1/0 as an int to the stack
1028      *
1029      * @param clazz the type to check instanceof against
1030      *
1031      * @return the method emitter
1032      */
1033     MethodEmitter _instanceof(final Class<?> clazz) {
1034         return _instanceof(CompilerConstants.className(clazz));
1035     }
1036 
1037     /**
1038      * Perform a checkcast operation on the object at the top of the
1039      * stack.
1040      *
1041      * @param classDescriptor descriptor of the class to type check against
1042      *
1043      * @return the method emitter
1044      */
1045     MethodEmitter checkcast(final String classDescriptor) {
1046         debug("checkcast", classDescriptor);
1047         assert peekType().isObject();
1048         method.visitTypeInsn(CHECKCAST, classDescriptor);
1049         return this;
1050     }
1051 
1052     /**
1053      * Perform a checkcast operation on the object at the top of the
1054      * stack.
1055      *
1056      * @param clazz class to checkcast against
1057      *
1058      * @return the method emitter
1059      */
1060     MethodEmitter checkcast(final Class<?> clazz) {
1061         return checkcast(CompilerConstants.className(clazz));
1062     }
1063 
1064     /**
1065      * Instantiate a new array given a length that is popped
1066      * from the stack and the array type
1067      *
1068      * @param arrayType the type of the array
1069      *
1070      * @return the method emitter
1071      */
1072     MethodEmitter newarray(final ArrayType arrayType) {
1073         debug("newarray ", "arrayType=", arrayType);
1074         popType(Type.INT); //LENGTH
1075         pushType(arrayType.newarray(method));
1076         return this;
1077     }
1078 
1079     /**
1080      * Instantiate a multidimensional array with a given number of dimensions.
1081      * On the stack are dim lengths of the sub arrays.
1082      *
1083      * @param arrayType type of the array
1084      * @param dims      number of dimensions
1085      *
1086      * @return the method emitter
1087      */
1088     MethodEmitter multinewarray(final ArrayType arrayType, final int dims) {
1089         debug("multianewarray ", arrayType, dims);
1090         for (int i = 0; i < dims; i++) {
1091             popType(Type.INT); //LENGTH
1092         }
1093         pushType(arrayType.newarray(method, dims));
1094         return this;
1095     }
1096 
1097     /**
1098      * Helper function to pop and type check the appropriate arguments
1099      * from the stack given a method signature
1100      *
1101      * @param signature method signature
1102      *
1103      * @return return type of method
1104      */
1105     private Type fixParamStack(final String signature) {
1106         final Type[] params = Type.getMethodArguments(signature);
1107         for (int i = params.length - 1; i >= 0; i--) {
1108             popType(params[i]);
1109         }
1110         final Type returnType = Type.getMethodReturnType(signature);
1111         return returnType;
1112     }
1113 
1114     /**
1115      * Generate an invocation to a Call structure
1116      * @see CompilerConstants
1117      *
1118      * @param call the call object
1119      *
1120      * @return the method emitter
1121      */
1122     MethodEmitter invoke(final Call call) {
1123         return call.invoke(this);
1124     }
1125 
1126     private MethodEmitter invoke(final int opcode, final String className, final String methodName, final String methodDescriptor, final boolean hasReceiver) {
1127         final Type returnType = fixParamStack(methodDescriptor);
1128 
1129         if (hasReceiver) {
1130             popType(Type.OBJECT);
1131         }
1132 
1133         method.visitMethodInsn(opcode, className, methodName, methodDescriptor);
1134 
1135         if (returnType != null) {
1136             pushType(returnType);
1137         }
1138 
1139         return this;
1140     }
1141 
1142     /**
1143      * Pop receiver from stack, perform an invoke special
1144      *
1145      * @param className        class name
1146      * @param methodName       method name
1147      * @param methodDescriptor descriptor
1148      *
1149      * @return the method emitter
1150      */
1151     MethodEmitter invokespecial(final String className, final String methodName, final String methodDescriptor) {
1152         debug("invokespecial", className, ".", methodName, methodDescriptor);
1153         return invoke(INVOKESPECIAL, className, methodName, methodDescriptor, true);
1154     }
1155 
1156     /**
1157      * Pop receiver from stack, perform an invoke virtual, push return value if any
1158      *
1159      * @param className        class name
1160      * @param methodName       method name
1161      * @param methodDescriptor descriptor
1162      *
1163      * @return the method emitter
1164      */
1165     MethodEmitter invokevirtual(final String className, final String methodName, final String methodDescriptor) {
1166         debug("invokevirtual", className, ".", methodName, methodDescriptor, " ", stack);
1167         return invoke(INVOKEVIRTUAL, className, methodName, methodDescriptor, true);
1168     }
1169 
1170     /**
1171      * Perform an invoke static and push the return value if any
1172      *
1173      * @param className        class name
1174      * @param methodName       method name
1175      * @param methodDescriptor descriptor
1176      *
1177      * @return the method emitter
1178      */
1179     MethodEmitter invokestatic(final String className, final String methodName, final String methodDescriptor) {
1180         debug("invokestatic", className, ".", methodName, methodDescriptor);
1181         invoke(INVOKESTATIC, className, methodName, methodDescriptor, false);
1182         return this;
1183     }
1184 
1185     /**
1186      * Perform an invoke static and replace the return type if we know better, e.g. Global.allocate
1187      * that allocates an array should return an ObjectArray type as a NativeArray counts as that
1188      *
1189      * @param className        class name
1190      * @param methodName       method name
1191      * @param methodDescriptor descriptor
1192      * @param returnType       return type override
1193      *
1194      * @return the method emitter
1195      */
1196     MethodEmitter invokeStatic(final String className, final String methodName, final String methodDescriptor, final Type returnType) {
1197         invokestatic(className, methodName, methodDescriptor);
1198         popType();
1199         pushType(returnType);
1200         return this;
1201     }
1202 
1203     /**
1204      * Pop receiver from stack, perform an invoke interface and push return value if any
1205      *
1206      * @param className        class name
1207      * @param methodName       method name
1208      * @param methodDescriptor descriptor
1209      *
1210      * @return the method emitter
1211      */
1212     MethodEmitter invokeinterface(final String className, final String methodName, final String methodDescriptor) {
1213         debug("invokeinterface", className, ".", methodName, methodDescriptor);
1214         return invoke(INVOKEINTERFACE, className, methodName, methodDescriptor, true);
1215     }
1216 
1217     static jdk.internal.org.objectweb.asm.Label[] getLabels(final Label... table) {
1218         final jdk.internal.org.objectweb.asm.Label[] internalLabels = new jdk.internal.org.objectweb.asm.Label[table.length];
1219         for (int i = 0; i < table.length; i++) {
1220             internalLabels[i] = table[i].getLabel();
1221         }
1222         return internalLabels;
1223     }
1224 
1225     /**
1226      * Generate a lookup switch, popping the switch value from the stack
1227      *
1228      * @param defaultLabel default label
1229      * @param values       case values for the table
1230      * @param table        default label
1231      */
1232     void lookupswitch(final Label defaultLabel, final int[] values, final Label... table) {//Collection<Label> table) {
1233         debug("lookupswitch", peekType());
1234         popType(Type.INT);
1235         method.visitLookupSwitchInsn(defaultLabel.getLabel(), values, getLabels(table));
1236     }
1237 
1238     /**
1239      * Generate a table switch
1240      * @param lo            low value
1241      * @param hi            high value
1242      * @param defaultLabel  default label
1243      * @param table         label table
1244      */
1245     void tableswitch(final int lo, final int hi, final Label defaultLabel, final Label... table) {
1246         debug("tableswitch", peekType());
1247         popType(Type.INT);
1248         method.visitTableSwitchInsn(lo, hi, defaultLabel.getLabel(), getLabels(table));
1249     }
1250 
1251     /**
1252      * Abstraction for performing a conditional jump of any type
1253      *
1254      * @see MethodEmitter.Condition
1255      *
1256      * @param cond      the condition to test
1257      * @param trueLabel the destination label is condition is true
1258      */
1259     void conditionalJump(final Condition cond, final Label trueLabel) {
1260         conditionalJump(cond, cond != Condition.GT && cond != Condition.GE, trueLabel);
1261     }
1262 
1263     /**
1264      * Abstraction for performing a conditional jump of any type,
1265      * including a dcmpg/dcmpl semantic for doubles.
1266      *
1267      * @param cond      the condition to test
1268      * @param isCmpG    is this a dcmpg for numbers, false if it's a dcmpl
1269      * @param trueLabel the destination label if condition is true
1270      */
1271     void conditionalJump(final Condition cond, final boolean isCmpG, final Label trueLabel) {
1272         if (peekType().isCategory2()) {
1273             debug("[ld]cmp isCmpG=", isCmpG);
1274             pushType(get2n().cmp(method, isCmpG));
1275             jump(Condition.toUnary(cond), trueLabel, 1);
1276         } else {
1277             debug("if", cond);
1278             jump(Condition.toBinary(cond, peekType().isObject()), trueLabel, 2);
1279         }
1280     }
1281 
1282     MethodEmitter registerReturn() {
1283         setHasReturn();
1284         return this;
1285     }
1286 
1287     void setHasReturn() {
1288         this.hasReturn = true;
1289     }
1290 
1291     /**
1292      * Perform a non void return, popping the type from the stack
1293      *
1294      * @param type the type for the return
1295      */
1296     void _return(final Type type) {
1297         debug("return", type);
1298         assert stack.size() == 1 : "Only return value on stack allowed at return point - depth=" + stack.size() + " stack = " + stack;
1299         final Type stackType = peekType();
1300         if (!Type.areEquivalent(type, stackType)) {
1301             convert(type);
1302         }
1303         popType(type)._return(method);
1304         stack = null;
1305     }
1306 
1307     /**
1308      * Perform a return using the stack top value as the guide for the type
1309      */
1310     void _return() {
1311         _return(peekType());
1312     }
1313 
1314     /**
1315      * Perform a void return.
1316      */
1317     void returnVoid() {
1318         debug("return [void]");
1319         assert stack.isEmpty() : stack;
1320         method.visitInsn(RETURN);
1321         stack = null;
1322     }
1323 
1324     /**
1325      * Goto, possibly when splitting is taking place. If
1326      * a splitNode exists, we need to handle the case that the
1327      * jump target is another method
1328      *
1329      * @param label destination label
1330      */
1331     void splitAwareGoto(final LexicalContext lc, final Label label) {
1332         _goto(label);
1333     }
1334 
1335     /**
1336      * Perform a comparison of two number types that are popped from the stack
1337      *
1338      * @param isCmpG is this a dcmpg semantic, false if it's a dcmpl semantic
1339      *
1340      * @return the method emitter
1341      */
1342     MethodEmitter cmp(final boolean isCmpG) {
1343         pushType(get2n().cmp(method, isCmpG));
1344         return this;
1345     }
1346 
1347     /**
1348      * Helper function for jumps, conditional or not
1349      * @param opcode  opcode for jump
1350      * @param label   destination
1351      * @param n       elements on stack to compare, 0-2
1352      */
1353     private void jump(final int opcode, final Label label, final int n) {
1354         for (int i = 0; i < n; i++) {
1355             assert peekType().isInteger() || peekType().isBoolean() || peekType().isObject() : "expecting integer type or object for jump, but found " + peekType();
1356             popType();
1357         }
1358         mergeStackTo(label);
1359         method.visitJumpInsn(opcode, label.getLabel());
1360     }
1361 
1362     /**
1363      * Generate an if_acmpeq
1364      *
1365      * @param label label to true case
1366      */
1367     void if_acmpeq(final Label label) {
1368         debug("if_acmpeq", label);
1369         jump(IF_ACMPEQ, label, 2);
1370     }
1371 
1372     /**
1373      * Generate an if_acmpne
1374      *
1375      * @param label label to true case
1376      */
1377     void if_acmpne(final Label label) {
1378         debug("if_acmpne", label);
1379         jump(IF_ACMPNE, label, 2);
1380     }
1381 
1382     /**
1383      * Generate an ifnull
1384      *
1385      * @param label label to true case
1386      */
1387     void ifnull(final Label label) {
1388         debug("ifnull", label);
1389         jump(IFNULL, label, 1);
1390     }
1391 
1392     /**
1393      * Generate an ifnonnull
1394      *
1395      * @param label label to true case
1396      */
1397     void ifnonnull(final Label label) {
1398         debug("ifnonnull", label);
1399         jump(IFNONNULL, label, 1);
1400     }
1401 
1402     /**
1403      * Generate an ifeq
1404      *
1405      * @param label label to true case
1406      */
1407     void ifeq(final Label label) {
1408         debug("ifeq ", label);
1409         jump(IFEQ, label, 1);
1410     }
1411 
1412     /**
1413      * Generate an if_icmpeq
1414      *
1415      * @param label label to true case
1416      */
1417     void if_icmpeq(final Label label) {
1418         debug("if_icmpeq", label);
1419         jump(IF_ICMPEQ, label, 2);
1420     }
1421 
1422     /**
1423      * Generate an if_ne
1424      *
1425      * @param label label to true case
1426      */
1427     void ifne(final Label label) {
1428         debug("ifne", label);
1429         jump(IFNE, label, 1);
1430     }
1431 
1432     /**
1433      * Generate an if_icmpne
1434      *
1435      * @param label label to true case
1436      */
1437     void if_icmpne(final Label label) {
1438         debug("if_icmpne", label);
1439         jump(IF_ICMPNE, label, 2);
1440     }
1441 
1442     /**
1443      * Generate an iflt
1444      *
1445      * @param label label to true case
1446      */
1447     void iflt(final Label label) {
1448         debug("iflt", label);
1449         jump(IFLT, label, 1);
1450     }
1451 
1452     /**
1453      * Generate an ifle
1454      *
1455      * @param label label to true case
1456      */
1457     void ifle(final Label label) {
1458         debug("ifle", label);
1459         jump(IFLE, label, 1);
1460     }
1461 
1462     /**
1463      * Generate an ifgt
1464      *
1465      * @param label label to true case
1466      */
1467     void ifgt(final Label label) {
1468         debug("ifgt", label);
1469         jump(IFGT, label, 1);
1470     }
1471 
1472     /**
1473      * Generate an ifge
1474      *
1475      * @param label label to true case
1476      */
1477     void ifge(final Label label) {
1478         debug("ifge", label);
1479         jump(IFGE, label, 1);
1480     }
1481 
1482     /**
1483      * Unconditional jump to a label
1484      *
1485      * @param label destination label
1486      */
1487     void _goto(final Label label) {
1488         //debug("goto", label);
1489         jump(GOTO, label, 0);
1490         stack = null; //whoever reaches the point after us provides the stack, because we don't
1491     }
1492 
1493     /**
1494      * Examine two stacks and make sure they are of the same size and their
1495      * contents are equivalent to each other
1496      * @param s0 first stack
1497      * @param s1 second stack
1498      *
1499      * @return true if stacks are equivalent, false otherwise
1500      */
1501     /**
1502      * A join in control flow - helper function that makes sure all entry stacks
1503      * discovered for the join point so far are equivalent
1504      *
1505      * MergeStack: we are about to enter a label. If its stack, label.getStack() is null
1506      * we have never been here before. Then we are expected to carry a stack with us.
1507      *
1508      * @param label label
1509      */
1510     private void mergeStackTo(final Label label) {
1511         //sometimes we can do a merge stack without having a stack - i.e. when jumping ahead to dead code
1512         //see NASHORN-73. So far we had been saved by the line number nodes. This should have been fixed
1513         //by Lower removing everything after an unconditionally executed terminating statement OR a break
1514         //or continue in a block. Previously code left over after breaks and continues was still there
1515         //and caused bytecode to be generated - which crashed on stack not being there, as the merge
1516         //was not in fact preceeded by a visit. Furthermore, this led to ASM putting out its NOP NOP NOP
1517         //ATHROW sequences instead of no code being generated at all. This should now be fixed.
1518         assert stack != null : label + " entered with no stack. deadcode that remains?";
1519 
1520         final Label.Stack labelStack = label.getStack();
1521         if (labelStack == null) {
1522             label.setStack(stack.copy());
1523             return;
1524         }
1525         assert stack.isEquivalentTo(labelStack) : "stacks " + stack + " is not equivalent with " + labelStack + " at join point";
1526     }
1527 
1528     /**
1529      * Register a new label, enter it here.
1530      *
1531      * @param label the label
1532      */
1533     void label(final Label label) {
1534         /*
1535          * If stack == null, this means that we came here not through a fallthrough.
1536          * E.g. a label after an athrow. Then we create a new stack if one doesn't exist
1537          * for this location already.
1538          */
1539         if (stack == null) {
1540             stack = label.getStack();
1541             if (stack == null) {
1542                 newStack();
1543             }
1544         }
1545         debug_label(label);
1546 
1547         mergeStackTo(label); //we have to merge our stack to whatever is in the label
1548 
1549         method.visitLabel(label.getLabel());
1550     }
1551 
1552     /**
1553      * Pop element from stack, convert to given type
1554      *
1555      * @param to type to convert to
1556      *
1557      * @return the method emitter
1558      */
1559     MethodEmitter convert(final Type to) {
1560         final Type type = peekType().convert(method, to);
1561         if (type != null) {
1562             if (!peekType().isEquivalentTo(to)) {
1563                 debug("convert", peekType(), "->", to);
1564             }
1565             popType();
1566             pushType(type);
1567         }
1568         return this;
1569     }
1570 
1571     /**
1572      * Helper function - expect two types that are equivalent
1573      *
1574      * @return common type
1575      */
1576     private Type get2() {
1577         final Type p0 = popType();
1578         final Type p1 = popType();
1579         assert p0.isEquivalentTo(p1) : "expecting equivalent types on stack but got " + p0 + " and " + p1;
1580         return p0;
1581     }
1582 
1583     /**
1584      * Helper function - expect two types that are integer types and equivalent
1585      *
1586      * @return common type
1587      */
1588     private BitwiseType get2i() {
1589         final BitwiseType p0 = popInteger();
1590         final BitwiseType p1 = popInteger();
1591         assert p0.isEquivalentTo(p1) : "expecting equivalent types on stack but got " + p0 + " and " + p1;
1592         return p0;
1593     }
1594 
1595     /**
1596      * Helper function - expect two types that are numbers and equivalent
1597      *
1598      * @return common type
1599      */
1600     private NumericType get2n() {
1601         final NumericType p0 = popNumeric();
1602         final NumericType p1 = popNumeric();
1603         assert p0.isEquivalentTo(p1) : "expecting equivalent types on stack but got " + p0 + " and " + p1;
1604         return p0;
1605     }
1606 
1607     /**
1608      * Pop two numbers, perform addition and push result
1609      *
1610      * @return the method emitter
1611      */
1612     MethodEmitter add() {
1613         debug("add");
1614         pushType(get2().add(method));
1615         return this;
1616     }
1617 
1618     /**
1619      * Pop two numbers, perform subtraction and push result
1620      *
1621      * @return the method emitter
1622      */
1623     MethodEmitter sub() {
1624         debug("sub");
1625         pushType(get2n().sub(method));
1626         return this;
1627     }
1628 
1629     /**
1630      * Pop two numbers, perform multiplication and push result
1631      *
1632      * @return the method emitter
1633      */
1634     MethodEmitter mul() {
1635         debug("mul ");
1636         pushType(get2n().mul(method));
1637         return this;
1638     }
1639 
1640     /**
1641      * Pop two numbers, perform division and push result
1642      *
1643      * @return the method emitter
1644      */
1645     MethodEmitter div() {
1646         debug("div");
1647         pushType(get2n().div(method));
1648         return this;
1649     }
1650 
1651     /**
1652      * Pop two numbers, calculate remainder and push result
1653      *
1654      * @return the method emitter
1655      */
1656     MethodEmitter rem() {
1657         debug("rem");
1658         pushType(get2n().rem(method));
1659         return this;
1660     }
1661 
1662     /**
1663      * Retrieve the top <tt>count</tt> types on the stack without modifying it.
1664      *
1665      * @param count number of types to return
1666      * @return array of Types
1667      */
1668     protected Type[] getTypesFromStack(final int count) {
1669         final Type[] types = new Type[count];
1670         int pos = 0;
1671         for (int i = count - 1; i >= 0; i--) {
1672             types[i] = stack.peek(pos++);
1673         }
1674 
1675         return types;
1676     }
1677 
1678     /**
1679      * Helper function to generate a function signature based on stack contents
1680      * and argument count and return type
1681      *
1682      * @param returnType return type
1683      * @param argCount   argument count
1684      *
1685      * @return function signature for stack contents
1686      */
1687     private String getDynamicSignature(final Type returnType, final int argCount) {
1688         final Type[]         paramTypes = new Type[argCount];
1689 
1690         int pos = 0;
1691         for (int i = argCount - 1; i >= 0; i--) {
1692             paramTypes[i] = stack.peek(pos++);
1693         }
1694         final String descriptor = Type.getMethodDescriptor(returnType, paramTypes);
1695         for (int i = 0; i < argCount; i++) {
1696             popType(paramTypes[argCount - i - 1]);
1697         }
1698 
1699         return descriptor;
1700     }
1701 
1702     /**
1703      * Generate a dynamic new
1704      *
1705      * @param argCount  number of arguments
1706      * @param flags     callsite flags
1707      *
1708      * @return the method emitter
1709      */
1710     MethodEmitter dynamicNew(final int argCount, final int flags) {
1711         debug("dynamic_new", "argcount=", argCount);
1712         final String signature = getDynamicSignature(Type.OBJECT, argCount);
1713         method.visitInvokeDynamicInsn("dyn:new", signature, LINKERBOOTSTRAP, flags);
1714         pushType(Type.OBJECT); //TODO fix result type
1715         return this;
1716     }
1717 
1718     /**
1719      * Generate a dynamic call
1720      *
1721      * @param returnType return type
1722      * @param argCount   number of arguments
1723      * @param flags      callsite flags
1724      *
1725      * @return the method emitter
1726      */
1727     MethodEmitter dynamicCall(final Type returnType, final int argCount, final int flags) {
1728         debug("dynamic_call", "args=", argCount, "returnType=", returnType);
1729         final String signature = getDynamicSignature(returnType, argCount); // +1 because the function itself is the 1st parameter for dynamic calls (what you call - call target)
1730         debug("   signature", signature);
1731         method.visitInvokeDynamicInsn("dyn:call", signature, LINKERBOOTSTRAP, flags);
1732         pushType(returnType);
1733 
1734         return this;
1735     }
1736 
1737     /**
1738      * Generate a dynamic call for a runtime node
1739      *
1740      * @param name       tag for the invoke dynamic for this runtime node
1741      * @param returnType return type
1742      * @param request    RuntimeNode request
1743      *
1744      * @return the method emitter
1745      */
1746     MethodEmitter dynamicRuntimeCall(final String name, final Type returnType, final RuntimeNode.Request request) {
1747         debug("dynamic_runtime_call", name, "args=", request.getArity(), "returnType=", returnType);
1748         final String signature = getDynamicSignature(returnType, request.getArity());
1749         debug("   signature", signature);
1750         method.visitInvokeDynamicInsn(name, signature, RUNTIMEBOOTSTRAP);
1751         pushType(returnType);
1752 
1753         return this;
1754     }
1755 
1756     /**
1757      * Generate dynamic getter. Pop scope from stack. Push result
1758      *
1759      * @param valueType type of the value to set
1760      * @param name      name of property
1761      * @param flags     call site flags
1762      * @param isMethod  should it prefer retrieving methods
1763      *
1764      * @return the method emitter
1765      */
1766     MethodEmitter dynamicGet(final Type valueType, final String name, final int flags, final boolean isMethod) {
1767         debug("dynamic_get", name, valueType);
1768 
1769         Type type = valueType;
1770         if (type.isObject() || type.isBoolean()) {
1771             type = Type.OBJECT; //promote e.g strings to object generic setter
1772         }
1773 
1774         popType(Type.SCOPE);
1775         method.visitInvokeDynamicInsn((isMethod ? "dyn:getMethod|getProp|getElem:" : "dyn:getProp|getElem|getMethod:") +
1776                 NameCodec.encode(name), Type.getMethodDescriptor(type, Type.OBJECT), LINKERBOOTSTRAP, flags);
1777 
1778         pushType(type);
1779 
1780         convert(valueType); //most probably a nop
1781 
1782         return this;
1783     }
1784 
1785     /**
1786      * Generate dynamic setter. Pop receiver and property from stack.
1787      *
1788      * @param valueType the type of the value to set
1789      * @param name      name of property
1790      * @param flags     call site flags
1791      */
1792      void dynamicSet(final String name, final int flags) {
1793         debug("dynamic_set", name, peekType());
1794 
1795         Type type = peekType();
1796         if (type.isObject() || type.isBoolean()) { //promote strings to objects etc
1797             type = Type.OBJECT;
1798             convert(Type.OBJECT); //TODO bad- until we specialize boolean setters,
1799         }
1800         popType(type);
1801         popType(Type.SCOPE);
1802 
1803         method.visitInvokeDynamicInsn("dyn:setProp|setElem:" + NameCodec.encode(name), methodDescriptor(void.class, Object.class, type.getTypeClass()), LINKERBOOTSTRAP, flags);
1804     }
1805 
1806      /**
1807      * Dynamic getter for indexed structures. Pop index and receiver from stack,
1808      * generate appropriate signatures based on types
1809      *
1810      * @param result result type for getter
1811      * @param flags call site flags for getter
1812      * @param isMethod should it prefer retrieving methods
1813      *
1814      * @return the method emitter
1815      */
1816     MethodEmitter dynamicGetIndex(final Type result, final int flags, final boolean isMethod) {
1817         debug("dynamic_get_index", peekType(1), "[", peekType(), "]");
1818 
1819         Type resultType = result;
1820         if (result.isBoolean()) {
1821             resultType = Type.OBJECT; // INT->OBJECT to avoid another dimension of cross products in the getters. TODO
1822         }
1823 
1824         Type index = peekType();
1825         if (index.isObject() || index.isBoolean()) {
1826             index = Type.OBJECT; //e.g. string->object
1827             convert(Type.OBJECT);
1828         }
1829         popType();
1830 
1831         popType(Type.OBJECT);
1832 
1833         final String signature = Type.getMethodDescriptor(resultType, Type.OBJECT /*e.g STRING->OBJECT*/, index);
1834 
1835         method.visitInvokeDynamicInsn(isMethod ? "dyn:getMethod|getElem|getProp" : "dyn:getElem|getProp|getMethod",
1836                 signature, LINKERBOOTSTRAP, flags);
1837         pushType(resultType);
1838 
1839         if (result.isBoolean()) {
1840             convert(Type.BOOLEAN);
1841         }
1842 
1843         return this;
1844     }
1845 
1846     /**
1847      * Dynamic setter for indexed structures. Pop value, index and receiver from
1848      * stack, generate appropriate signature based on types
1849      *
1850      * @param flags call site flags for setter
1851      */
1852     void dynamicSetIndex(final int flags) {
1853         debug("dynamic_set_index", peekType(2), "[", peekType(1), "] =", peekType());
1854 
1855         Type value = peekType();
1856         if (value.isObject() || value.isBoolean()) {
1857             value = Type.OBJECT; //e.g. STRING->OBJECT - one descriptor for all object types
1858             convert(Type.OBJECT);
1859         }
1860         popType();
1861 
1862         Type index = peekType();
1863         if (index.isObject() || index.isBoolean()) {
1864             index = Type.OBJECT; //e.g. string->object
1865             convert(Type.OBJECT);
1866         }
1867         popType(index);
1868 
1869         final Type receiver = popType(Type.OBJECT);
1870         assert receiver.isObject();
1871 
1872         method.visitInvokeDynamicInsn("dyn:setElem|setProp", methodDescriptor(void.class, receiver.getTypeClass(), index.getTypeClass(), value.getTypeClass()), LINKERBOOTSTRAP, flags);
1873     }
1874 
1875     /**
1876      * Load a key value in the proper form.
1877      *
1878      * @param key
1879      */
1880     //TODO move this and break it apart
1881     MethodEmitter loadKey(final Object key) {
1882         if (key instanceof IdentNode) {
1883             method.visitLdcInsn(((IdentNode) key).getName());
1884         } else if (key instanceof LiteralNode) {
1885             method.visitLdcInsn(((LiteralNode<?>)key).getString());
1886         } else {
1887             method.visitLdcInsn(JSType.toString(key));
1888         }
1889         pushType(Type.OBJECT); //STRING
1890         return this;
1891     }
1892 
1893      @SuppressWarnings("fallthrough")
1894      private static Type fieldType(final String desc) {
1895          switch (desc) {
1896          case "Z":
1897          case "B":
1898          case "C":
1899          case "S":
1900          case "I":
1901              return Type.INT;
1902          case "F":
1903              assert false;
1904          case "D":
1905              return Type.NUMBER;
1906          case "J":
1907              return Type.LONG;
1908          default:
1909              assert desc.startsWith("[") || desc.startsWith("L") : desc + " is not an object type";
1910              switch (desc.charAt(0)) {
1911              case 'L':
1912                  return Type.OBJECT;
1913              case '[':
1914                  return Type.typeFor(Array.newInstance(fieldType(desc.substring(1)).getTypeClass(), 0).getClass());
1915              default:
1916                  assert false;
1917              }
1918              return Type.OBJECT;
1919          }
1920      }
1921 
1922      /**
1923       * Generate get for a field access
1924       *
1925       * @param fa the field access
1926       *
1927       * @return the method emitter
1928       */
1929     MethodEmitter getField(final FieldAccess fa) {
1930         return fa.get(this);
1931     }
1932 
1933      /**
1934       * Generate set for a field access
1935       *
1936       * @param fa the field access
1937       */
1938     void putField(final FieldAccess fa) {
1939         fa.put(this);
1940     }
1941 
1942     /**
1943      * Get the value of a non-static field, pop the receiver from the stack,
1944      * push value to the stack
1945      *
1946      * @param className        class
1947      * @param fieldName        field name
1948      * @param fieldDescriptor  field descriptor
1949      *
1950      * @return the method emitter
1951      */
1952     MethodEmitter getField(final String className, final String fieldName, final String fieldDescriptor) {
1953         debug("getfield", "receiver=", peekType(), className, ".", fieldName, fieldDescriptor);
1954         final Type receiver = popType();
1955         assert receiver.isObject();
1956         method.visitFieldInsn(GETFIELD, className, fieldName, fieldDescriptor);
1957         pushType(fieldType(fieldDescriptor));
1958         return this;
1959     }
1960 
1961     /**
1962      * Get the value of a static field, push it to the stack
1963      *
1964      * @param className        class
1965      * @param fieldName        field name
1966      * @param fieldDescriptor  field descriptor
1967      *
1968      * @return the method emitter
1969      */
1970     MethodEmitter getStatic(final String className, final String fieldName, final String fieldDescriptor) {
1971         debug("getstatic", className, ".", fieldName, ".", fieldDescriptor);
1972         method.visitFieldInsn(GETSTATIC, className, fieldName, fieldDescriptor);
1973         pushType(fieldType(fieldDescriptor));
1974         return this;
1975     }
1976 
1977     /**
1978      * Pop value and field from stack and write to a non-static field
1979      *
1980      * @param className       class
1981      * @param fieldName       field name
1982      * @param fieldDescriptor field descriptor
1983      */
1984     void putField(final String className, final String fieldName, final String fieldDescriptor) {
1985         debug("putfield", "receiver=", peekType(1), "value=", peekType());
1986         popType(fieldType(fieldDescriptor));
1987         popType(Type.OBJECT);
1988         method.visitFieldInsn(PUTFIELD, className, fieldName, fieldDescriptor);
1989     }
1990 
1991     /**
1992      * Pop value from stack and write to a static field
1993      *
1994      * @param className       class
1995      * @param fieldName       field name
1996      * @param fieldDescriptor field descriptor
1997      */
1998     void putStatic(final String className, final String fieldName, final String fieldDescriptor) {
1999         debug("putfield", "value=", peekType());
2000         popType(fieldType(fieldDescriptor));
2001         method.visitFieldInsn(PUTSTATIC, className, fieldName, fieldDescriptor);
2002     }
2003 
2004     /**
2005      * Register line number at a label
2006      *
2007      * @param line  line number
2008      * @param label label
2009      */
2010     void lineNumber(final int line) {
2011         if (env._debug_lines) {
2012             debug_label("[LINE]", line);
2013             final jdk.internal.org.objectweb.asm.Label l = new jdk.internal.org.objectweb.asm.Label();
2014             method.visitLabel(l);
2015             method.visitLineNumber(line, l);
2016         }
2017     }
2018 
2019     /*
2020      * Debugging below
2021      */
2022 
2023     private final FieldAccess ERR_STREAM       = staticField(System.class, "err", PrintStream.class);
2024     private final Call        PRINT            = virtualCallNoLookup(PrintStream.class, "print", void.class, Object.class);
2025     private final Call        PRINTLN          = virtualCallNoLookup(PrintStream.class, "println", void.class, Object.class);
2026     private final Call        PRINT_STACKTRACE = virtualCallNoLookup(Throwable.class, "printStackTrace", void.class);
2027 
2028     /**
2029      * Emit a System.err.print statement of whatever is on top of the bytecode stack
2030      */
2031      void print() {
2032          getField(ERR_STREAM);
2033          swap();
2034          convert(Type.OBJECT);
2035          invoke(PRINT);
2036      }
2037 
2038     /**
2039      * Emit a System.err.println statement of whatever is on top of the bytecode stack
2040      */
2041      void println() {
2042          getField(ERR_STREAM);
2043          swap();
2044          convert(Type.OBJECT);
2045          invoke(PRINTLN);
2046      }
2047 
2048      /**
2049       * Emit a System.err.print statement
2050       * @param string string to print
2051       */
2052      void print(final String string) {
2053          getField(ERR_STREAM);
2054          load(string);
2055          invoke(PRINT);
2056      }
2057 
2058      /**
2059       * Emit a System.err.println statement
2060       * @param string string to print
2061       */
2062      void println(final String string) {
2063          getField(ERR_STREAM);
2064          load(string);
2065          invoke(PRINTLN);
2066      }
2067 
2068      /**
2069       * Print a stacktrace to S
2070       */
2071      void stacktrace() {
2072          _new(Throwable.class);
2073          dup();
2074          invoke(constructorNoLookup(Throwable.class));
2075          invoke(PRINT_STACKTRACE);
2076      }
2077 
2078     private static int linePrefix = 0;
2079 
2080     /**
2081      * Debug function that outputs generated bytecode and stack contents
2082      *
2083      * @param args debug information to print
2084      */
2085     private void debug(final Object... args) {
2086         if (DEBUG) {
2087             debug(30, args);
2088         }
2089     }
2090 
2091     /**
2092      * Debug function that outputs generated bytecode and stack contents
2093      * for a label - indentation is currently the only thing that differs
2094      *
2095      * @param args debug information to print
2096      */
2097     private void debug_label(final Object... args) {
2098         if (DEBUG) {
2099             debug(22, args);
2100         }
2101     }
2102 
2103     private void debug(final int padConstant, final Object... args) {
2104         if (DEBUG) {
2105             final StringBuilder sb = new StringBuilder();
2106             int pad;
2107 
2108             sb.append('#');
2109             sb.append(++linePrefix);
2110 
2111             pad = 5 - sb.length();
2112             while (pad > 0) {
2113                 sb.append(' ');
2114                 pad--;
2115             }
2116 
2117             if (stack != null && !stack.isEmpty()) {
2118                 sb.append("{");
2119                 sb.append(stack.size());
2120                 sb.append(":");
2121                 for (int pos = 0; pos < stack.size(); pos++) {
2122                     final Type t = stack.peek(pos);
2123 
2124                     if (t == Type.SCOPE) {
2125                         sb.append("scope");
2126                     } else if (t == Type.THIS) {
2127                         sb.append("this");
2128                     } else if (t.isObject()) {
2129                         String desc = t.getDescriptor();
2130                         int i;
2131                         for (i = 0; desc.charAt(i) == '[' && i < desc.length(); i++) {
2132                             sb.append('[');
2133                         }
2134                         desc = desc.substring(i);
2135                         final int slash = desc.lastIndexOf('/');
2136                         if (slash != -1) {
2137                             desc = desc.substring(slash + 1, desc.length() - 1);
2138                         }
2139                         if ("Object".equals(desc)) {
2140                             sb.append('O');
2141                         } else {
2142                             sb.append(desc);
2143                         }
2144                     } else {
2145                         sb.append(t.getDescriptor());
2146                     }
2147 
2148                     if (pos + 1 < stack.size()) {
2149                         sb.append(' ');
2150                     }
2151                 }
2152                 sb.append('}');
2153                 sb.append(' ');
2154             }
2155 
2156             pad = padConstant - sb.length();
2157             while (pad > 0) {
2158                 sb.append(' ');
2159                 pad--;
2160             }
2161 
2162             for (final Object arg : args) {
2163                 sb.append(arg);
2164                 sb.append(' ');
2165             }
2166 
2167             if (env != null) { //early bootstrap code doesn't have inited context yet
2168                 LOG.info(sb);
2169                 if (DEBUG_TRACE_LINE == linePrefix) {
2170                     new Throwable().printStackTrace(LOG.getOutputStream());
2171                 }
2172             }
2173         }
2174     }
2175 
2176     /**
2177      * Set the current function node being emitted
2178      * @param functionNode the function node
2179      */
2180     void setFunctionNode(final FunctionNode functionNode) {
2181         this.functionNode = functionNode;
2182     }
2183 
2184     boolean hasReturn() {
2185         return hasReturn;
2186     }
2187 
2188     List<Label> getExternalTargets() {
2189         return null;
2190     }
2191 
2192 }