/*
 * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package jdk.nashorn.internal.codegen;

import static jdk.nashorn.internal.codegen.ClassEmitter.Flag.PRIVATE;
import static jdk.nashorn.internal.codegen.ClassEmitter.Flag.STATIC;
import static jdk.nashorn.internal.codegen.CompilerConstants.ARGUMENTS;
import static jdk.nashorn.internal.codegen.CompilerConstants.CALLEE;
import static jdk.nashorn.internal.codegen.CompilerConstants.CREATE_PROGRAM_FUNCTION;
import static jdk.nashorn.internal.codegen.CompilerConstants.GET_MAP;
import static jdk.nashorn.internal.codegen.CompilerConstants.GET_STRING;
import static jdk.nashorn.internal.codegen.CompilerConstants.QUICK_PREFIX;
import static jdk.nashorn.internal.codegen.CompilerConstants.REGEX_PREFIX;
import static jdk.nashorn.internal.codegen.CompilerConstants.SCOPE;
import static jdk.nashorn.internal.codegen.CompilerConstants.SPLIT_PREFIX;
import static jdk.nashorn.internal.codegen.CompilerConstants.THIS;
import static jdk.nashorn.internal.codegen.CompilerConstants.VARARGS;
import static jdk.nashorn.internal.codegen.CompilerConstants.interfaceCallNoLookup;
import static jdk.nashorn.internal.codegen.CompilerConstants.methodDescriptor;
import static jdk.nashorn.internal.codegen.CompilerConstants.staticCallNoLookup;
import static jdk.nashorn.internal.codegen.CompilerConstants.typeDescriptor;
import static jdk.nashorn.internal.codegen.CompilerConstants.virtualCallNoLookup;
import static jdk.nashorn.internal.ir.Symbol.HAS_SLOT;
import static jdk.nashorn.internal.ir.Symbol.IS_INTERNAL;
import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT;
import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.isValid;
import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_APPLY_TO_CALL;
import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_DECLARE;
import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_FAST_SCOPE;
import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_OPTIMISTIC;
import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_PROGRAM_POINT_SHIFT;
import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_SCOPE;

import java.io.PrintWriter;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.BitSet;
import java.util.Collection;
import java.util.Collections;
import java.util.Deque;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.function.Supplier;
import jdk.nashorn.internal.AssertsEnabled;
import jdk.nashorn.internal.IntDeque;
import jdk.nashorn.internal.codegen.ClassEmitter.Flag;
import jdk.nashorn.internal.codegen.CompilerConstants.Call;
import jdk.nashorn.internal.codegen.types.ArrayType;
import jdk.nashorn.internal.codegen.types.Type;
import jdk.nashorn.internal.ir.AccessNode;
import jdk.nashorn.internal.ir.BaseNode;
import jdk.nashorn.internal.ir.BinaryNode;
import jdk.nashorn.internal.ir.Block;
import jdk.nashorn.internal.ir.BlockStatement;
import jdk.nashorn.internal.ir.BreakNode;
import jdk.nashorn.internal.ir.CallNode;
import jdk.nashorn.internal.ir.CaseNode;
import jdk.nashorn.internal.ir.CatchNode;
import jdk.nashorn.internal.ir.ContinueNode;
import jdk.nashorn.internal.ir.EmptyNode;
import jdk.nashorn.internal.ir.Expression;
import jdk.nashorn.internal.ir.ExpressionStatement;
import jdk.nashorn.internal.ir.ForNode;
import jdk.nashorn.internal.ir.FunctionNode;
import jdk.nashorn.internal.ir.GetSplitState;
import jdk.nashorn.internal.ir.IdentNode;
import jdk.nashorn.internal.ir.IfNode;
import jdk.nashorn.internal.ir.IndexNode;
import jdk.nashorn.internal.ir.JoinPredecessorExpression;
import jdk.nashorn.internal.ir.JumpStatement;
import jdk.nashorn.internal.ir.JumpToInlinedFinally;
import jdk.nashorn.internal.ir.LabelNode;
import jdk.nashorn.internal.ir.LexicalContext;
import jdk.nashorn.internal.ir.LexicalContextNode;
import jdk.nashorn.internal.ir.LiteralNode;
import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode;
import jdk.nashorn.internal.ir.LiteralNode.PrimitiveLiteralNode;
import jdk.nashorn.internal.ir.LocalVariableConversion;
import jdk.nashorn.internal.ir.LoopNode;
import jdk.nashorn.internal.ir.Node;
import jdk.nashorn.internal.ir.ObjectNode;
import jdk.nashorn.internal.ir.Optimistic;
import jdk.nashorn.internal.ir.PropertyNode;
import jdk.nashorn.internal.ir.ReturnNode;
import jdk.nashorn.internal.ir.RuntimeNode;
import jdk.nashorn.internal.ir.RuntimeNode.Request;
import jdk.nashorn.internal.ir.SetSplitState;
import jdk.nashorn.internal.ir.SplitReturn;
import jdk.nashorn.internal.ir.Splittable;
import jdk.nashorn.internal.ir.Statement;
import jdk.nashorn.internal.ir.SwitchNode;
import jdk.nashorn.internal.ir.Symbol;
import jdk.nashorn.internal.ir.TernaryNode;
import jdk.nashorn.internal.ir.ThrowNode;
import jdk.nashorn.internal.ir.TryNode;
import jdk.nashorn.internal.ir.UnaryNode;
import jdk.nashorn.internal.ir.VarNode;
import jdk.nashorn.internal.ir.WhileNode;
import jdk.nashorn.internal.ir.WithNode;
import jdk.nashorn.internal.ir.visitor.NodeOperatorVisitor;
import jdk.nashorn.internal.ir.visitor.SimpleNodeVisitor;
import jdk.nashorn.internal.objects.Global;
import jdk.nashorn.internal.parser.Lexer.RegexToken;
import jdk.nashorn.internal.parser.TokenType;
import jdk.nashorn.internal.runtime.Context;
import jdk.nashorn.internal.runtime.Debug;
import jdk.nashorn.internal.runtime.ECMAException;
import jdk.nashorn.internal.runtime.JSType;
import jdk.nashorn.internal.runtime.OptimisticReturnFilters;
import jdk.nashorn.internal.runtime.PropertyMap;
import jdk.nashorn.internal.runtime.RecompilableScriptFunctionData;
import jdk.nashorn.internal.runtime.RewriteException;
import jdk.nashorn.internal.runtime.Scope;
import jdk.nashorn.internal.runtime.ScriptEnvironment;
import jdk.nashorn.internal.runtime.ScriptFunction;
import jdk.nashorn.internal.runtime.ScriptObject;
import jdk.nashorn.internal.runtime.ScriptRuntime;
import jdk.nashorn.internal.runtime.Source;
import jdk.nashorn.internal.runtime.Undefined;
import jdk.nashorn.internal.runtime.UnwarrantedOptimismException;
import jdk.nashorn.internal.runtime.arrays.ArrayData;
import jdk.nashorn.internal.runtime.linker.LinkerCallSite;
import jdk.nashorn.internal.runtime.logging.DebugLogger;
import jdk.nashorn.internal.runtime.logging.Loggable;
import jdk.nashorn.internal.runtime.logging.Logger;
import jdk.nashorn.internal.runtime.options.Options;

/**
 * This is the lowest tier of the code generator. It takes lowered ASTs emitted
 * from Lower and emits Java byte code. The byte code emission logic is broken
 * out into MethodEmitter. MethodEmitter works internally with a type stack, and
 * keeps track of the contents of the byte code stack. This way we avoid a large
 * number of special cases on the form
 * <pre>
 * if (type == INT) {
 *     visitInsn(ILOAD, slot);
 * } else if (type == DOUBLE) {
 *     visitInsn(DOUBLE, slot);
 * }
 * </pre>
 * This quickly became apparent when the code generator was generalized to work
 * with all types, and not just numbers or objects.
 * <p>
 * The CodeGenerator visits nodes only once and emits bytecode for them.
 */
@Logger(name="codegen")
final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContext> implements Loggable {

    private static final Type SCOPE_TYPE = Type.typeFor(ScriptObject.class);

    private static final String GLOBAL_OBJECT = Type.getInternalName(Global.class);

    private static final Call CREATE_REWRITE_EXCEPTION = CompilerConstants.staticCallNoLookup(RewriteException.class,
            "create", RewriteException.class, UnwarrantedOptimismException.class, Object[].class, String[].class);
    private static final Call CREATE_REWRITE_EXCEPTION_REST_OF = CompilerConstants.staticCallNoLookup(RewriteException.class,
            "create", RewriteException.class, UnwarrantedOptimismException.class, Object[].class, String[].class, int[].class);

    private static final Call ENSURE_INT = CompilerConstants.staticCallNoLookup(OptimisticReturnFilters.class,
            "ensureInt", int.class, Object.class, int.class);
    private static final Call ENSURE_NUMBER = CompilerConstants.staticCallNoLookup(OptimisticReturnFilters.class,
            "ensureNumber", double.class, Object.class, int.class);

    private static final Call CREATE_FUNCTION_OBJECT = CompilerConstants.staticCallNoLookup(ScriptFunction.class,
            "create", ScriptFunction.class, Object[].class, int.class, ScriptObject.class);
    private static final Call CREATE_FUNCTION_OBJECT_NO_SCOPE = CompilerConstants.staticCallNoLookup(ScriptFunction.class,
            "create", ScriptFunction.class, Object[].class, int.class);

    private static final Call TO_NUMBER_FOR_EQ = CompilerConstants.staticCallNoLookup(JSType.class,
            "toNumberForEq", double.class, Object.class);
    private static final Call TO_NUMBER_FOR_STRICT_EQ = CompilerConstants.staticCallNoLookup(JSType.class,
            "toNumberForStrictEq", double.class, Object.class);


    private static final Class<?> ITERATOR_CLASS = Iterator.class;
    static {
        assert ITERATOR_CLASS == CompilerConstants.ITERATOR_PREFIX.type();
    }
    private static final Type ITERATOR_TYPE = Type.typeFor(ITERATOR_CLASS);
    private static final Type EXCEPTION_TYPE = Type.typeFor(CompilerConstants.EXCEPTION_PREFIX.type());

    private static final Integer INT_ZERO = Integer.valueOf(0);

    /** Constant data & installation. The only reason the compiler keeps this is because it is assigned
     *  by reflection in class installation */
    private final Compiler compiler;

    /** Is the current code submitted by 'eval' call? */
    private final boolean evalCode;

    /** Call site flags given to the code generator to be used for all generated call sites */
    private final int callSiteFlags;

    /** How many regexp fields have been emitted */
    private int regexFieldCount;

    /** Line number for last statement. If we encounter a new line number, line number bytecode information
     *  needs to be generated */
    private int lastLineNumber = -1;

    /** When should we stop caching regexp expressions in fields to limit bytecode size? */
    private static final int MAX_REGEX_FIELDS = 2 * 1024;

    /** Current method emitter */
    private MethodEmitter method;

    /** Current compile unit */
    private CompileUnit unit;

    private final DebugLogger log;

    /** From what size should we use spill instead of fields for JavaScript objects? */
    static final int OBJECT_SPILL_THRESHOLD = Options.getIntProperty("nashorn.spill.threshold", 256);

    private final Set<String> emittedMethods = new HashSet<>();

    // Function Id -> ContinuationInfo. Used by compilation of rest-of function only.
    private ContinuationInfo continuationInfo;

    private final Deque<Label> scopeEntryLabels = new ArrayDeque<>();

    private static final Label METHOD_BOUNDARY = new Label("");
    private final Deque<Label> catchLabels = new ArrayDeque<>();
    // Number of live locals on entry to (and thus also break from) labeled blocks.
    private final IntDeque labeledBlockBreakLiveLocals = new IntDeque();

    //is this a rest of compilation
    private final int[] continuationEntryPoints;

    /**
     * Constructor.
     *
     * @param compiler
     */
    CodeGenerator(final Compiler compiler, final int[] continuationEntryPoints) {
        super(new CodeGeneratorLexicalContext());
        this.compiler                = compiler;
        this.evalCode                = compiler.getSource().isEvalCode();
        this.continuationEntryPoints = continuationEntryPoints;
        this.callSiteFlags           = compiler.getScriptEnvironment()._callsite_flags;
        this.log                     = initLogger(compiler.getContext());
    }

    @Override
    public DebugLogger getLogger() {
        return log;
    }

    @Override
    public DebugLogger initLogger(final Context context) {
        return context.getLogger(this.getClass());
    }

    /**
     * Gets the call site flags, adding the strict flag if the current function
     * being generated is in strict mode
     *
     * @return the correct flags for a call site in the current function
     */
    int getCallSiteFlags() {
        return lc.getCurrentFunction().getCallSiteFlags() | callSiteFlags;
    }

    /**
     * Gets the flags for a scope call site.
     * @param symbol a scope symbol
     * @return the correct flags for the scope call site
     */
    private int getScopeCallSiteFlags(final Symbol symbol) {
        assert symbol.isScope();
        final int flags = getCallSiteFlags() | CALLSITE_SCOPE;
        if (isEvalCode() && symbol.isGlobal()) {
            return flags; // Don't set fast-scope flag on non-declared globals in eval code - see JDK-8077955.
        }
        return isFastScope(symbol) ? flags | CALLSITE_FAST_SCOPE : flags;
    }

    /**
     * Are we generating code for 'eval' code?
     * @return true if currently compiled code is 'eval' code.
     */
    boolean isEvalCode() {
        return evalCode;
    }

    /**
     * Are we using dual primitive/object field representation?
     * @return true if using dual field representation, false for object-only fields
     */
    boolean useDualFields() {
        return compiler.getContext().useDualFields();
    }

    /**
     * Load an identity node
     *
     * @param identNode an identity node to load
     * @return the method generator used
     */
    private MethodEmitter loadIdent(final IdentNode identNode, final TypeBounds resultBounds) {
        checkTemporalDeadZone(identNode);
        final Symbol symbol = identNode.getSymbol();

        if (!symbol.isScope()) {
            final Type type = identNode.getType();
            if(type == Type.UNDEFINED) {
                return method.loadUndefined(resultBounds.widest);
            }

            assert symbol.hasSlot() || symbol.isParam();
            return method.load(identNode);
        }

        assert identNode.getSymbol().isScope() : identNode + " is not in scope!";
        final int flags = getScopeCallSiteFlags(symbol);
        if (isFastScope(symbol)) {
            // Only generate shared scope getter for fast-scope symbols so we know we can dial in correct scope.
            if (symbol.getUseCount() > SharedScopeCall.FAST_SCOPE_GET_THRESHOLD && !identNode.isOptimistic()) {
                // As shared scope vars are only used with non-optimistic identifiers, we switch from using TypeBounds to
                // just a single definitive type, resultBounds.widest.
                new OptimisticOperation(identNode, TypeBounds.OBJECT) {
                    @Override
                    void loadStack() {
                        method.loadCompilerConstant(SCOPE);
                    }

                    @Override
                    void consumeStack() {
                        loadSharedScopeVar(resultBounds.widest, symbol, flags);
                    }
                }.emit();
            } else {
                new LoadFastScopeVar(identNode, resultBounds, flags).emit();
            }
        } else {
            //slow scope load, we have no proto depth
            new LoadScopeVar(identNode, resultBounds, flags).emit();
        }

        return method;
    }

    // Any access to LET and CONST variables before their declaration must throw ReferenceError.
    // This is called the temporal dead zone (TDZ). See https://gist.github.com/rwaldron/f0807a758aa03bcdd58a
    private void checkTemporalDeadZone(final IdentNode identNode) {
        if (identNode.isDead()) {
            method.load(identNode.getSymbol().getName()).invoke(ScriptRuntime.THROW_REFERENCE_ERROR);
        }
    }

    // Runtime check for assignment to ES6 const
    private void checkAssignTarget(final Expression expression) {
        if (expression instanceof IdentNode && ((IdentNode)expression).getSymbol().isConst()) {
            method.load(((IdentNode)expression).getSymbol().getName()).invoke(ScriptRuntime.THROW_CONST_TYPE_ERROR);
        }
    }

    private boolean isRestOf() {
        return continuationEntryPoints != null;
    }

    private boolean isCurrentContinuationEntryPoint(final int programPoint) {
        return isRestOf() && getCurrentContinuationEntryPoint() == programPoint;
    }

    private int[] getContinuationEntryPoints() {
        return isRestOf() ? continuationEntryPoints : null;
    }

    private int getCurrentContinuationEntryPoint() {
        return isRestOf() ? continuationEntryPoints[0] : INVALID_PROGRAM_POINT;
    }

    private boolean isContinuationEntryPoint(final int programPoint) {
        if (isRestOf()) {
            assert continuationEntryPoints != null;
            for (final int cep : continuationEntryPoints) {
                if (cep == programPoint) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * Check if this symbol can be accessed directly with a putfield or getfield or dynamic load
     *
     * @param symbol symbol to check for fast scope
     * @return true if fast scope
     */
    private boolean isFastScope(final Symbol symbol) {
        if (!symbol.isScope()) {
            return false;
        }

        if (!lc.inDynamicScope()) {
            // If there's no with or eval in context, and the symbol is marked as scoped, it is fast scoped. Such a
            // symbol must either be global, or its defining block must need scope.
            assert symbol.isGlobal() || lc.getDefiningBlock(symbol).needsScope() : symbol.getName();
            return true;
        }

        if (symbol.isGlobal()) {
            // Shortcut: if there's a with or eval in context, globals can't be fast scoped
            return false;
        }

        // Otherwise, check if there's a dynamic scope between use of the symbol and its definition
        final String name = symbol.getName();
        boolean previousWasBlock = false;
        for (final Iterator<LexicalContextNode> it = lc.getAllNodes(); it.hasNext();) {
            final LexicalContextNode node = it.next();
            if (node instanceof Block) {
                // If this block defines the symbol, then we can fast scope the symbol.
                final Block block = (Block)node;
                if (block.getExistingSymbol(name) == symbol) {
                    assert block.needsScope();
                    return true;
                }
                previousWasBlock = true;
            } else {
                if (node instanceof WithNode && previousWasBlock || node instanceof FunctionNode && ((FunctionNode)node).needsDynamicScope()) {
                    // If we hit a scope that can have symbols introduced into it at run time before finding the defining
                    // block, the symbol can't be fast scoped. A WithNode only counts if we've immediately seen a block
                    // before - its block. Otherwise, we are currently processing the WithNode's expression, and that's
                    // obviously not subjected to introducing new symbols.
                    return false;
                }
                previousWasBlock = false;
            }
        }
        // Should've found the symbol defined in a block
        throw new AssertionError();
    }

    private MethodEmitter loadSharedScopeVar(final Type valueType, final Symbol symbol, final int flags) {
        assert isFastScope(symbol);
        method.load(getScopeProtoDepth(lc.getCurrentBlock(), symbol));
        return lc.getScopeGet(unit, symbol, valueType, flags).generateInvoke(method);
    }

    private class LoadScopeVar extends OptimisticOperation {
        final IdentNode identNode;
        private final int flags;

        LoadScopeVar(final IdentNode identNode, final TypeBounds resultBounds, final int flags) {
            super(identNode, resultBounds);
            this.identNode = identNode;
            this.flags = flags;
        }

        @Override
        void loadStack() {
            method.loadCompilerConstant(SCOPE);
            getProto();
        }

        void getProto() {
            //empty
        }

        @Override
        void consumeStack() {
            // If this is either __FILE__, __DIR__, or __LINE__ then load the property initially as Object as we'd convert
            // it anyway for replaceLocationPropertyPlaceholder.
            if(identNode.isCompileTimePropertyName()) {
                method.dynamicGet(Type.OBJECT, identNode.getSymbol().getName(), flags, identNode.isFunction(), false);
                replaceCompileTimeProperty();
            } else {
                dynamicGet(identNode.getSymbol().getName(), flags, identNode.isFunction(), false);
            }
        }
    }

    private class LoadFastScopeVar extends LoadScopeVar {
        LoadFastScopeVar(final IdentNode identNode, final TypeBounds resultBounds, final int flags) {
            super(identNode, resultBounds, flags);
        }

        @Override
        void getProto() {
            loadFastScopeProto(identNode.getSymbol(), false);
        }
    }

    private MethodEmitter storeFastScopeVar(final Symbol symbol, final int flags) {
        loadFastScopeProto(symbol, true);
        method.dynamicSet(symbol.getName(), flags, false);
        return method;
    }

    private int getScopeProtoDepth(final Block startingBlock, final Symbol symbol) {
        //walk up the chain from starting block and when we bump into the current function boundary, add the external
        //information.
        final FunctionNode fn   = lc.getCurrentFunction();
        final int externalDepth = compiler.getScriptFunctionData(fn.getId()).getExternalSymbolDepth(symbol.getName());

        //count the number of scopes from this place to the start of the function

        final int internalDepth = FindScopeDepths.findInternalDepth(lc, fn, startingBlock, symbol);
        final int scopesToStart = FindScopeDepths.findScopesToStart(lc, fn, startingBlock);
        int depth = 0;
        if (internalDepth == -1) {
            depth = scopesToStart + externalDepth;
        } else {
            assert internalDepth <= scopesToStart;
            depth = internalDepth;
        }

        return depth;
    }

    private void loadFastScopeProto(final Symbol symbol, final boolean swap) {
        final int depth = getScopeProtoDepth(lc.getCurrentBlock(), symbol);
        assert depth != -1 : "Couldn't find scope depth for symbol " + symbol.getName() + " in " + lc.getCurrentFunction();
        if (depth > 0) {
            if (swap) {
                method.swap();
            }
            for (int i = 0; i < depth; i++) {
                method.invoke(ScriptObject.GET_PROTO);
            }
            if (swap) {
                method.swap();
            }
        }
    }

    /**
     * Generate code that loads this node to the stack, not constraining its type
     *
     * @param expr node to load
     *
     * @return the method emitter used
     */
    private MethodEmitter loadExpressionUnbounded(final Expression expr) {
        return loadExpression(expr, TypeBounds.UNBOUNDED);
    }

    private MethodEmitter loadExpressionAsObject(final Expression expr) {
        return loadExpression(expr, TypeBounds.OBJECT);
    }

    MethodEmitter loadExpressionAsBoolean(final Expression expr) {
        return loadExpression(expr, TypeBounds.BOOLEAN);
    }

    // Test whether conversion from source to target involves a call of ES 9.1 ToPrimitive
    // with possible side effects from calling an object's toString or valueOf methods.
    private static boolean noToPrimitiveConversion(final Type source, final Type target) {
        // Object to boolean conversion does not cause ToPrimitive call
        return source.isJSPrimitive() || !target.isJSPrimitive() || target.isBoolean();
    }

    MethodEmitter loadBinaryOperands(final BinaryNode binaryNode) {
        return loadBinaryOperands(binaryNode.lhs(), binaryNode.rhs(), TypeBounds.UNBOUNDED.notWiderThan(binaryNode.getWidestOperandType()), false, false);
    }

    private MethodEmitter loadBinaryOperands(final Expression lhs, final Expression rhs, final TypeBounds explicitOperandBounds, final boolean baseAlreadyOnStack, final boolean forceConversionSeparation) {
        // ECMAScript 5.1 specification (sections 11.5-11.11 and 11.13) prescribes that when evaluating a binary
        // expression "LEFT op RIGHT", the order of operations must be: LOAD LEFT, LOAD RIGHT, CONVERT LEFT, CONVERT
        // RIGHT, EXECUTE OP. Unfortunately, doing it in this order defeats potential optimizations that arise when we
        // can combine a LOAD with a CONVERT operation (e.g. use a dynamic getter with the conversion target type as its
        // return value). What we do here is reorder LOAD RIGHT and CONVERT LEFT when possible; it is possible only when
        // we can prove that executing CONVERT LEFT can't have a side effect that changes the value of LOAD RIGHT.
        // Basically, if we know that either LEFT already is a primitive value, or does not have to be converted to
        // a primitive value, or RIGHT is an expression that loads without side effects, then we can do the
        // reordering and collapse LOAD/CONVERT into a single operation; otherwise we need to do the more costly
        // separate operations to preserve specification semantics.

        // Operands' load type should not be narrower than the narrowest of the individual operand types, nor narrower
        // than the lower explicit bound, but it should also not be wider than
        final Type lhsType = undefinedToNumber(lhs.getType());
        final Type rhsType = undefinedToNumber(rhs.getType());
        final Type narrowestOperandType = Type.narrowest(Type.widest(lhsType, rhsType), explicitOperandBounds.widest);
        final TypeBounds operandBounds = explicitOperandBounds.notNarrowerThan(narrowestOperandType);
        if (noToPrimitiveConversion(lhsType, explicitOperandBounds.widest) || rhs.isLocal()) {
            // Can reorder. We might still need to separate conversion, but at least we can do it with reordering
            if (forceConversionSeparation) {
                // Can reorder, but can't move conversion into the operand as the operation depends on operands
                // exact types for its overflow guarantees. E.g. with {L}{%I}expr1 {L}* {L}{%I}expr2 we are not allowed
                // to merge {L}{%I} into {%L}, as that can cause subsequent overflows; test for JDK-8058610 contains
                // concrete cases where this could happen.
                final TypeBounds safeConvertBounds = TypeBounds.UNBOUNDED.notNarrowerThan(narrowestOperandType);
                loadExpression(lhs, safeConvertBounds, baseAlreadyOnStack);
                method.convert(operandBounds.within(method.peekType()));
                loadExpression(rhs, safeConvertBounds, false);
                method.convert(operandBounds.within(method.peekType()));
            } else {
                // Can reorder and move conversion into the operand. Combine load and convert into single operations.
                loadExpression(lhs, operandBounds, baseAlreadyOnStack);
                loadExpression(rhs, operandBounds, false);
            }
        } else {
            // Can't reorder. Load and convert separately.
            final TypeBounds safeConvertBounds = TypeBounds.UNBOUNDED.notNarrowerThan(narrowestOperandType);
            loadExpression(lhs, safeConvertBounds, baseAlreadyOnStack);
            final Type lhsLoadedType = method.peekType();
            loadExpression(rhs, safeConvertBounds, false);
            final Type convertedLhsType = operandBounds.within(method.peekType());
            if (convertedLhsType != lhsLoadedType) {
                // Do it conditionally, so that if conversion is a no-op we don't introduce a SWAP, SWAP.
                method.swap().convert(convertedLhsType).swap();
            }
            method.convert(operandBounds.within(method.peekType()));
        }
        assert Type.generic(method.peekType()) == operandBounds.narrowest;
        assert Type.generic(method.peekType(1)) == operandBounds.narrowest;

        return method;
    }

    /**
     * Similar to {@link #loadBinaryOperands(BinaryNode)} but used specifically for loading operands of
     * relational and equality comparison operators where at least one argument is non-object. (When both
     * arguments are objects, we use {@link ScriptRuntime#EQ(Object, Object)}, {@link ScriptRuntime#LT(Object, Object)}
     * etc. methods instead. Additionally, {@code ScriptRuntime} methods are used for strict (in)equality comparison
     * of a boolean to anything that isn't a boolean.) This method handles the special case where one argument
     * is an object and another is a primitive. Naively, these could also be delegated to {@code ScriptRuntime} methods
     * by boxing the primitive. However, in all such cases the comparison is performed on numeric values, so it is
     * possible to strength-reduce the operation by taking the number value of the object argument instead and
     * comparing that to the primitive value ("primitive" will always be int, long, double, or boolean, and booleans
     * compare as ints in these cases, so they're essentially numbers too). This method will emit code for loading
     * arguments for such strength-reduced comparison. When both arguments are primitives, it just delegates to
     * {@link #loadBinaryOperands(BinaryNode)}.
     *
     * @param cmp the comparison operation for which the operands need to be loaded on stack.
     * @return the current method emitter.
     */
    MethodEmitter loadComparisonOperands(final BinaryNode cmp) {
        final Expression lhs = cmp.lhs();
        final Expression rhs = cmp.rhs();
        final Type lhsType = lhs.getType();
        final Type rhsType = rhs.getType();

        // Only used when not both are object, for that we have ScriptRuntime.LT etc.
        assert !(lhsType.isObject() && rhsType.isObject());

        if (lhsType.isObject() || rhsType.isObject()) {
            // We can reorder CONVERT LEFT and LOAD RIGHT only if either the left is a primitive, or the right
            // is a local. This is more strict than loadBinaryNode reorder criteria, as it can allow JS primitive
            // types too (notably: String is a JS primitive, but not a JVM primitive). We disallow String otherwise
            // we would prematurely convert it to number when comparing to an optimistic expression, e.g. in
            // "Hello" === String("Hello") the RHS starts out as an optimistic-int function call. If we allowed
            // reordering, we'd end up with ToNumber("Hello") === {I%}String("Hello") that is obviously incorrect.
            final boolean canReorder = lhsType.isPrimitive() || rhs.isLocal();
            // If reordering is allowed, and we're using a relational operator (that is, <, <=, >, >=) and not an
            // (in)equality operator, then we encourage combining of LOAD and CONVERT into a single operation.
            // This is because relational operators' semantics prescribes vanilla ToNumber() conversion, while
            // (in)equality operators need the specialized JSType.toNumberFor[Strict]Equals. E.g. in the code snippet
            // "i < obj.size" (where i is primitive and obj.size is statically an object), ".size" will thus be allowed
            // to compile as:
            //   invokedynamic dyn:getProp|getElem|getMethod:size(Object;)D
            // instead of the more costly:
            //   invokedynamic dyn:getProp|getElem|getMethod:size(Object;)Object
            //   invokestatic JSType.toNumber(Object)D
            // Note also that even if this is allowed, we're only using it on operands that are non-optimistic, as
            // otherwise the logic for determining effective optimistic-ness would turn an optimistic double return
            // into a freely coercible one, which would be wrong.
            final boolean canCombineLoadAndConvert = canReorder && cmp.isRelational();

            // LOAD LEFT
            loadExpression(lhs, canCombineLoadAndConvert && !lhs.isOptimistic() ? TypeBounds.NUMBER : TypeBounds.UNBOUNDED);

            final Type lhsLoadedType = method.peekType();
            final TokenType tt = cmp.tokenType();
            if (canReorder) {
                // Can reorder CONVERT LEFT and LOAD RIGHT
                emitObjectToNumberComparisonConversion(method, tt);
                loadExpression(rhs, canCombineLoadAndConvert && !rhs.isOptimistic() ? TypeBounds.NUMBER : TypeBounds.UNBOUNDED);
            } else {
                // Can't reorder CONVERT LEFT and LOAD RIGHT
                loadExpression(rhs, TypeBounds.UNBOUNDED);
                if (lhsLoadedType != Type.NUMBER) {
                    method.swap();
                    emitObjectToNumberComparisonConversion(method, tt);
                    method.swap();
                }
            }

            // CONVERT RIGHT
            emitObjectToNumberComparisonConversion(method, tt);
            return method;
        }
        // For primitive operands, just don't do anything special.
        return loadBinaryOperands(cmp);
    }

    private static void emitObjectToNumberComparisonConversion(final MethodEmitter method, final TokenType tt) {
        switch(tt) {
        case EQ:
        case NE:
            if (method.peekType().isObject()) {
                TO_NUMBER_FOR_EQ.invoke(method);
                return;
            }
            break;
        case EQ_STRICT:
        case NE_STRICT:
            if (method.peekType().isObject()) {
                TO_NUMBER_FOR_STRICT_EQ.invoke(method);
                return;
            }
            break;
        default:
            break;
        }
        method.convert(Type.NUMBER);
    }

    private static final Type undefinedToNumber(final Type type) {
        return type == Type.UNDEFINED ? Type.NUMBER : type;
    }

    private static final class TypeBounds {
        final Type narrowest;
        final Type widest;

        static final TypeBounds UNBOUNDED = new TypeBounds(Type.UNKNOWN, Type.OBJECT);
        static final TypeBounds INT = exact(Type.INT);
        static final TypeBounds NUMBER = exact(Type.NUMBER);
        static final TypeBounds OBJECT = exact(Type.OBJECT);
        static final TypeBounds BOOLEAN = exact(Type.BOOLEAN);

        static TypeBounds exact(final Type type) {
            return new TypeBounds(type, type);
        }

        TypeBounds(final Type narrowest, final Type widest) {
            assert widest    != null && widest    != Type.UNDEFINED && widest != Type.UNKNOWN : widest;
            assert narrowest != null && narrowest != Type.UNDEFINED : narrowest;
            assert !narrowest.widerThan(widest) : narrowest + " wider than " + widest;
            assert !widest.narrowerThan(narrowest);
            this.narrowest = Type.generic(narrowest);
            this.widest = Type.generic(widest);
        }

        TypeBounds notNarrowerThan(final Type type) {
            return maybeNew(Type.narrowest(Type.widest(narrowest, type), widest), widest);
        }

        TypeBounds notWiderThan(final Type type) {
            return maybeNew(Type.narrowest(narrowest, type), Type.narrowest(widest, type));
        }

        boolean canBeNarrowerThan(final Type type) {
            return narrowest.narrowerThan(type);
        }

        TypeBounds maybeNew(final Type newNarrowest, final Type newWidest) {
            if(newNarrowest == narrowest && newWidest == widest) {
                return this;
            }
            return new TypeBounds(newNarrowest, newWidest);
        }

        TypeBounds booleanToInt() {
            return maybeNew(CodeGenerator.booleanToInt(narrowest), CodeGenerator.booleanToInt(widest));
        }

        TypeBounds objectToNumber() {
            return maybeNew(CodeGenerator.objectToNumber(narrowest), CodeGenerator.objectToNumber(widest));
        }

        Type within(final Type type) {
            if(type.narrowerThan(narrowest)) {
                return narrowest;
            }
            if(type.widerThan(widest)) {
                return widest;
            }
            return type;
        }

        @Override
        public String toString() {
            return "[" + narrowest + ", " + widest + "]";
        }
    }

    private static Type booleanToInt(final Type t) {
        return t == Type.BOOLEAN ? Type.INT : t;
    }

    private static Type objectToNumber(final Type t) {
        return t.isObject() ? Type.NUMBER : t;
    }

    MethodEmitter loadExpressionAsType(final Expression expr, final Type type) {
        if(type == Type.BOOLEAN) {
            return loadExpressionAsBoolean(expr);
        } else if(type == Type.UNDEFINED) {
            assert expr.getType() == Type.UNDEFINED;
            return loadExpressionAsObject(expr);
        }
        // having no upper bound preserves semantics of optimistic operations in the expression (by not having them
        // converted early) and then applies explicit conversion afterwards.
        return loadExpression(expr, TypeBounds.UNBOUNDED.notNarrowerThan(type)).convert(type);
    }

    private MethodEmitter loadExpression(final Expression expr, final TypeBounds resultBounds) {
        return loadExpression(expr, resultBounds, false);
    }

    /**
     * Emits code for evaluating an expression and leaving its value on top of the stack, narrowing or widening it if
     * necessary.
     * @param expr the expression to load
     * @param resultBounds the incoming type bounds. The value on the top of the stack is guaranteed to not be of narrower
     * type than the narrowest bound, or wider type than the widest bound after it is loaded.
     * @param baseAlreadyOnStack true if the base of an access or index node is already on the stack. Used to avoid
     * double evaluation of bases in self-assignment expressions to access and index nodes. {@code Type.OBJECT} is used
     * to indicate the widest possible type.
     * @return the method emitter
     */
    private MethodEmitter loadExpression(final Expression expr, final TypeBounds resultBounds, final boolean baseAlreadyOnStack) {

        /*
         * The load may be of type IdentNode, e.g. "x", AccessNode, e.g. "x.y"
         * or IndexNode e.g. "x[y]". Both AccessNodes and IndexNodes are
         * BaseNodes and the logic for loading the base object is reused
         */
        final CodeGenerator codegen = this;

        final boolean isCurrentDiscard = codegen.lc.isCurrentDiscard(expr);
        expr.accept(new NodeOperatorVisitor<LexicalContext>(new LexicalContext()) {
            @Override
            public boolean enterIdentNode(final IdentNode identNode) {
                loadIdent(identNode, resultBounds);
                return false;
            }

            @Override
            public boolean enterAccessNode(final AccessNode accessNode) {
                new OptimisticOperation(accessNode, resultBounds) {
                    @Override
                    void loadStack() {
                        if (!baseAlreadyOnStack) {
                            loadExpressionAsObject(accessNode.getBase());
                        }
                        assert method.peekType().isObject();
                    }
                    @Override
                    void consumeStack() {
                        final int flags = getCallSiteFlags();
                        dynamicGet(accessNode.getProperty(), flags, accessNode.isFunction(), accessNode.isIndex());
                    }
                }.emit(baseAlreadyOnStack ? 1 : 0);
                return false;
            }

            @Override
            public boolean enterIndexNode(final IndexNode indexNode) {
                new OptimisticOperation(indexNode, resultBounds) {
                    @Override
                    void loadStack() {
                        if (!baseAlreadyOnStack) {
                            loadExpressionAsObject(indexNode.getBase());
                            loadExpressionUnbounded(indexNode.getIndex());
                        }
                    }
                    @Override
                    void consumeStack() {
                        final int flags = getCallSiteFlags();
                        dynamicGetIndex(flags, indexNode.isFunction());
                    }
                }.emit(baseAlreadyOnStack ? 2 : 0);
                return false;
            }

            @Override
            public boolean enterFunctionNode(final FunctionNode functionNode) {
                // function nodes will always leave a constructed function object on stack, no need to load the symbol
                // separately as in enterDefault()
                lc.pop(functionNode);
                functionNode.accept(codegen);
                // NOTE: functionNode.accept() will produce a different FunctionNode that we discard. This incidentally
                // doesn't cause problems as we're never touching FunctionNode again after it's visited here - codegen
                // is the last element in the compilation pipeline, the AST it produces is not used externally. So, we
                // re-push the original functionNode.
                lc.push(functionNode);
                return false;
            }

            @Override
            public boolean enterASSIGN(final BinaryNode binaryNode) {
                checkAssignTarget(binaryNode.lhs());
                loadASSIGN(binaryNode);
                return false;
            }

            @Override
            public boolean enterASSIGN_ADD(final BinaryNode binaryNode) {
                checkAssignTarget(binaryNode.lhs());
                loadASSIGN_ADD(binaryNode);
                return false;
            }

            @Override
            public boolean enterASSIGN_BIT_AND(final BinaryNode binaryNode) {
                checkAssignTarget(binaryNode.lhs());
                loadASSIGN_BIT_AND(binaryNode);
                return false;
            }

            @Override
            public boolean enterASSIGN_BIT_OR(final BinaryNode binaryNode) {
                checkAssignTarget(binaryNode.lhs());
                loadASSIGN_BIT_OR(binaryNode);
                return false;
            }

            @Override
            public boolean enterASSIGN_BIT_XOR(final BinaryNode binaryNode) {
                checkAssignTarget(binaryNode.lhs());
                loadASSIGN_BIT_XOR(binaryNode);
                return false;
            }

            @Override
            public boolean enterASSIGN_DIV(final BinaryNode binaryNode) {
                checkAssignTarget(binaryNode.lhs());
                loadASSIGN_DIV(binaryNode);
                return false;
            }

            @Override
            public boolean enterASSIGN_MOD(final BinaryNode binaryNode) {
                checkAssignTarget(binaryNode.lhs());
                loadASSIGN_MOD(binaryNode);
                return false;
            }

            @Override
            public boolean enterASSIGN_MUL(final BinaryNode binaryNode) {
                checkAssignTarget(binaryNode.lhs());
                loadASSIGN_MUL(binaryNode);
                return false;
            }

            @Override
            public boolean enterASSIGN_SAR(final BinaryNode binaryNode) {
                checkAssignTarget(binaryNode.lhs());
                loadASSIGN_SAR(binaryNode);
                return false;
            }

            @Override
            public boolean enterASSIGN_SHL(final BinaryNode binaryNode) {
                checkAssignTarget(binaryNode.lhs());
                loadASSIGN_SHL(binaryNode);
                return false;
            }

            @Override
            public boolean enterASSIGN_SHR(final BinaryNode binaryNode) {
                checkAssignTarget(binaryNode.lhs());
                loadASSIGN_SHR(binaryNode);
                return false;
            }

            @Override
            public boolean enterASSIGN_SUB(final BinaryNode binaryNode) {
                checkAssignTarget(binaryNode.lhs());
                loadASSIGN_SUB(binaryNode);
                return false;
            }

            @Override
            public boolean enterCallNode(final CallNode callNode) {
                return loadCallNode(callNode, resultBounds);
            }

            @Override
            public boolean enterLiteralNode(final LiteralNode<?> literalNode) {
                loadLiteral(literalNode, resultBounds);
                return false;
            }

            @Override
            public boolean enterTernaryNode(final TernaryNode ternaryNode) {
                loadTernaryNode(ternaryNode, resultBounds);
                return false;
            }

            @Override
            public boolean enterADD(final BinaryNode binaryNode) {
                loadADD(binaryNode, resultBounds);
                return false;
            }

            @Override
            public boolean enterSUB(final UnaryNode unaryNode) {
                loadSUB(unaryNode, resultBounds);
                return false;
            }

            @Override
            public boolean enterSUB(final BinaryNode binaryNode) {
                loadSUB(binaryNode, resultBounds);
                return false;
            }

            @Override
            public boolean enterMUL(final BinaryNode binaryNode) {
                loadMUL(binaryNode, resultBounds);
                return false;
            }

            @Override
            public boolean enterDIV(final BinaryNode binaryNode) {
                loadDIV(binaryNode, resultBounds);
                return false;
            }

            @Override
            public boolean enterMOD(final BinaryNode binaryNode) {
                loadMOD(binaryNode, resultBounds);
                return false;
            }

            @Override
            public boolean enterSAR(final BinaryNode binaryNode) {
                loadSAR(binaryNode);
                return false;
            }

            @Override
            public boolean enterSHL(final BinaryNode binaryNode) {
                loadSHL(binaryNode);
                return false;
            }

            @Override
            public boolean enterSHR(final BinaryNode binaryNode) {
                loadSHR(binaryNode);
                return false;
            }

            @Override
            public boolean enterCOMMALEFT(final BinaryNode binaryNode) {
                loadCOMMALEFT(binaryNode, resultBounds);
                return false;
            }

            @Override
            public boolean enterCOMMARIGHT(final BinaryNode binaryNode) {
                loadCOMMARIGHT(binaryNode, resultBounds);
                return false;
            }

            @Override
            public boolean enterAND(final BinaryNode binaryNode) {
                loadAND_OR(binaryNode, resultBounds, true);
                return false;
            }

            @Override
            public boolean enterOR(final BinaryNode binaryNode) {
                loadAND_OR(binaryNode, resultBounds, false);
                return false;
            }

            @Override
            public boolean enterNOT(final UnaryNode unaryNode) {
                loadNOT(unaryNode);
                return false;
            }

            @Override
            public boolean enterADD(final UnaryNode unaryNode) {
                loadADD(unaryNode, resultBounds);
                return false;
            }

            @Override
            public boolean enterBIT_NOT(final UnaryNode unaryNode) {
                loadBIT_NOT(unaryNode);
                return false;
            }

            @Override
            public boolean enterBIT_AND(final BinaryNode binaryNode) {
                loadBIT_AND(binaryNode);
                return false;
            }

            @Override
            public boolean enterBIT_OR(final BinaryNode binaryNode) {
                loadBIT_OR(binaryNode);
                return false;
            }

            @Override
            public boolean enterBIT_XOR(final BinaryNode binaryNode) {
                loadBIT_XOR(binaryNode);
                return false;
            }

            @Override
            public boolean enterVOID(final UnaryNode unaryNode) {
                loadVOID(unaryNode, resultBounds);
                return false;
            }

            @Override
            public boolean enterEQ(final BinaryNode binaryNode) {
                loadCmp(binaryNode, Condition.EQ);
                return false;
            }

            @Override
            public boolean enterEQ_STRICT(final BinaryNode binaryNode) {
                loadCmp(binaryNode, Condition.EQ);
                return false;
            }

            @Override
            public boolean enterGE(final BinaryNode binaryNode) {
                loadCmp(binaryNode, Condition.GE);
                return false;
            }

            @Override
            public boolean enterGT(final BinaryNode binaryNode) {
                loadCmp(binaryNode, Condition.GT);
                return false;
            }

            @Override
            public boolean enterLE(final BinaryNode binaryNode) {
                loadCmp(binaryNode, Condition.LE);
                return false;
            }

            @Override
            public boolean enterLT(final BinaryNode binaryNode) {
                loadCmp(binaryNode, Condition.LT);
                return false;
            }

            @Override
            public boolean enterNE(final BinaryNode binaryNode) {
                loadCmp(binaryNode, Condition.NE);
                return false;
            }

            @Override
            public boolean enterNE_STRICT(final BinaryNode binaryNode) {
                loadCmp(binaryNode, Condition.NE);
                return false;
            }

            @Override
            public boolean enterObjectNode(final ObjectNode objectNode) {
                loadObjectNode(objectNode);
                return false;
            }

            @Override
            public boolean enterRuntimeNode(final RuntimeNode runtimeNode) {
                loadRuntimeNode(runtimeNode);
                return false;
            }

            @Override
            public boolean enterNEW(final UnaryNode unaryNode) {
                loadNEW(unaryNode);
                return false;
            }

            @Override
            public boolean enterDECINC(final UnaryNode unaryNode) {
                checkAssignTarget(unaryNode.getExpression());
                loadDECINC(unaryNode);
                return false;
            }

            @Override
            public boolean enterJoinPredecessorExpression(final JoinPredecessorExpression joinExpr) {
                loadMaybeDiscard(joinExpr, joinExpr.getExpression(), resultBounds);
                return false;
            }

            @Override
            public boolean enterGetSplitState(final GetSplitState getSplitState) {
                method.loadScope();
                method.invoke(Scope.GET_SPLIT_STATE);
                return false;
            }

            @Override
            public boolean enterDefault(final Node otherNode) {
                // Must have handled all expressions that can legally be encountered.
                throw new AssertionError(otherNode.getClass().getName());
            }
        });
        if(!isCurrentDiscard) {
            coerceStackTop(resultBounds);
        }
        return method;
    }

    private MethodEmitter coerceStackTop(final TypeBounds typeBounds) {
        return method.convert(typeBounds.within(method.peekType()));
    }

    /**
     * Closes any still open entries for this block's local variables in the bytecode local variable table.
     *
     * @param block block containing symbols.
     */
    private void closeBlockVariables(final Block block) {
        for (final Symbol symbol : block.getSymbols()) {
            if (symbol.isBytecodeLocal()) {
                method.closeLocalVariable(symbol, block.getBreakLabel());
            }
        }
    }

    @Override
    public boolean enterBlock(final Block block) {
        final Label entryLabel = block.getEntryLabel();
        if (entryLabel.isBreakTarget()) {
            // Entry label is a break target only for an inlined finally block.
            assert !method.isReachable();
            method.breakLabel(entryLabel, lc.getUsedSlotCount());
        } else {
            method.label(entryLabel);
        }
        if(!method.isReachable()) {
            return false;
        }
        if(lc.isFunctionBody() && emittedMethods.contains(lc.getCurrentFunction().getName())) {
            return false;
        }
        initLocals(block);

        assert lc.getUsedSlotCount() == method.getFirstTemp();
        return true;
    }

    boolean useOptimisticTypes() {
        return !lc.inSplitNode() && compiler.useOptimisticTypes();
    }

    @Override
    public Node leaveBlock(final Block block) {
        popBlockScope(block);
        method.beforeJoinPoint(block);

        closeBlockVariables(block);
        lc.releaseSlots();
        assert !method.isReachable() || (lc.isFunctionBody() ? 0 : lc.getUsedSlotCount()) == method.getFirstTemp() :
            "reachable="+method.isReachable() +
            " isFunctionBody=" + lc.isFunctionBody() +
            " usedSlotCount=" + lc.getUsedSlotCount() +
            " firstTemp=" + method.getFirstTemp();

        return block;
    }

    private void popBlockScope(final Block block) {
        final Label breakLabel = block.getBreakLabel();

        if(!block.needsScope() || lc.isFunctionBody()) {
            emitBlockBreakLabel(breakLabel);
            return;
        }

        final Label beginTryLabel = scopeEntryLabels.pop();
        final Label recoveryLabel = new Label("block_popscope_catch");
        emitBlockBreakLabel(breakLabel);
        final boolean bodyCanThrow = breakLabel.isAfter(beginTryLabel);
        if(bodyCanThrow) {
            method._try(beginTryLabel, breakLabel, recoveryLabel);
        }

        Label afterCatchLabel = null;

        if(method.isReachable()) {
            popScope();
            if(bodyCanThrow) {
                afterCatchLabel = new Label("block_after_catch");
                method._goto(afterCatchLabel);
            }
        }

        if(bodyCanThrow) {
            assert !method.isReachable();
            method._catch(recoveryLabel);
            popScopeException();
            method.athrow();
        }
        if(afterCatchLabel != null) {
            method.label(afterCatchLabel);
        }
    }

    private void emitBlockBreakLabel(final Label breakLabel) {
        // TODO: this is totally backwards. Block should not be breakable, LabelNode should be breakable.
        final LabelNode labelNode = lc.getCurrentBlockLabelNode();
        if(labelNode != null) {
            // Only have conversions if we're reachable
            assert labelNode.getLocalVariableConversion() == null || method.isReachable();
            method.beforeJoinPoint(labelNode);
            method.breakLabel(breakLabel, labeledBlockBreakLiveLocals.pop());
        } else {
            method.label(breakLabel);
        }
    }

    private void popScope() {
        popScopes(1);
    }

    /**
     * Pop scope as part of an exception handler. Similar to {@code popScope()} but also takes care of adjusting the
     * number of scopes that needs to be popped in case a rest-of continuation handler encounters an exception while
     * performing a ToPrimitive conversion.
     */
    private void popScopeException() {
        popScope();
        final ContinuationInfo ci = getContinuationInfo();
        if(ci != null) {
            final Label catchLabel = ci.catchLabel;
            if(catchLabel != METHOD_BOUNDARY && catchLabel == catchLabels.peek()) {
                ++ci.exceptionScopePops;
            }
        }
    }

    private void popScopesUntil(final LexicalContextNode until) {
        popScopes(lc.getScopeNestingLevelTo(until));
    }

    private void popScopes(final int count) {
        if(count == 0) {
            return;
        }
        assert count > 0; // together with count == 0 check, asserts nonnegative count
        if (!method.hasScope()) {
            // We can sometimes invoke this method even if the method has no slot for the scope object. Typical example:
            // for(;;) { with({}) { break; } }. WithNode normally creates a scope, but if it uses no identifiers and
            // nothing else forces creation of a scope in the method, we just won't have the :scope local variable.
            return;
        }
        method.loadCompilerConstant(SCOPE);
        for(int i = 0; i < count; ++i) {
            method.invoke(ScriptObject.GET_PROTO);
        }
        method.storeCompilerConstant(SCOPE);
    }

    @Override
    public boolean enterBreakNode(final BreakNode breakNode) {
        return enterJumpStatement(breakNode);
    }

    @Override
    public boolean enterJumpToInlinedFinally(final JumpToInlinedFinally jumpToInlinedFinally) {
        return enterJumpStatement(jumpToInlinedFinally);
    }

    private boolean enterJumpStatement(final JumpStatement jump) {
        if(!method.isReachable()) {
            return false;
        }
        enterStatement(jump);

        method.beforeJoinPoint(jump);
        popScopesUntil(jump.getPopScopeLimit(lc));
        final Label targetLabel = jump.getTargetLabel(lc);
        targetLabel.markAsBreakTarget();
        method._goto(targetLabel);

        return false;
    }

    private int loadArgs(final List<Expression> args) {
        final int argCount = args.size();
        // arg have already been converted to objects here.
        if (argCount > LinkerCallSite.ARGLIMIT) {
            loadArgsArray(args);
            return 1;
        }

        for (final Expression arg : args) {
            assert arg != null;
            loadExpressionUnbounded(arg);
        }
        return argCount;
    }

    private boolean loadCallNode(final CallNode callNode, final TypeBounds resultBounds) {
        lineNumber(callNode.getLineNumber());

        final List<Expression> args = callNode.getArgs();
        final Expression function = callNode.getFunction();
        final Block currentBlock = lc.getCurrentBlock();
        final CodeGeneratorLexicalContext codegenLexicalContext = lc;

        function.accept(new SimpleNodeVisitor() {
            private MethodEmitter sharedScopeCall(final IdentNode identNode, final int flags) {
                final Symbol symbol = identNode.getSymbol();
                final boolean isFastScope = isFastScope(symbol);
                new OptimisticOperation(callNode, resultBounds) {
                    @Override
                    void loadStack() {
                        method.loadCompilerConstant(SCOPE);
                        if (isFastScope) {
                            method.load(getScopeProtoDepth(currentBlock, symbol));
                        } else {
                            method.load(-1); // Bypass fast-scope code in shared callsite
                        }
                        loadArgs(args);
                    }
                    @Override
                    void consumeStack() {
                        final Type[] paramTypes = method.getTypesFromStack(args.size());
                        // We have trouble finding e.g. in Type.typeFor(asm.Type) because it can't see the Context class
                        // loader, so we need to weaken reference signatures to Object.
                        for(int i = 0; i < paramTypes.length; ++i) {
                            paramTypes[i] = Type.generic(paramTypes[i]);
                        }
                        // As shared scope calls are only used in non-optimistic compilation, we switch from using
                        // TypeBounds to just a single definitive type, resultBounds.widest.
                        final SharedScopeCall scopeCall = codegenLexicalContext.getScopeCall(unit, symbol,
                                identNode.getType(), resultBounds.widest, paramTypes, flags);
                        scopeCall.generateInvoke(method);
                    }
                }.emit();
                return method;
            }

            private void scopeCall(final IdentNode ident, final int flags) {
                new OptimisticOperation(callNode, resultBounds) {
                    int argsCount;
                    @Override
                    void loadStack() {
                        loadExpressionAsObject(ident); // foo() makes no sense if foo == 3
                        // ScriptFunction will see CALLSITE_SCOPE and will bind scope accordingly.
                        method.loadUndefined(Type.OBJECT); //the 'this'
                        argsCount = loadArgs(args);
                    }
                    @Override
                    void consumeStack() {
                        dynamicCall(2 + argsCount, flags, ident.getName());
                    }
                }.emit();
            }

            private void evalCall(final IdentNode ident, final int flags) {
                final Label invoke_direct_eval  = new Label("invoke_direct_eval");
                final Label is_not_eval  = new Label("is_not_eval");
                final Label eval_done = new Label("eval_done");

                new OptimisticOperation(callNode, resultBounds) {
                    int argsCount;
                    @Override
                    void loadStack() {
                        /*
                         * We want to load 'eval' to check if it is indeed global builtin eval.
                         * If this eval call is inside a 'with' statement, dyn:getMethod|getProp|getElem
                         * would be generated if ident is a "isFunction". But, that would result in a
                         * bound function from WithObject. We don't want that as bound function as that
                         * won't be detected as builtin eval. So, we make ident as "not a function" which
                         * results in "dyn:getProp|getElem|getMethod" being generated and so WithObject
                         * would return unbounded eval function.
                         *
                         * Example:
                         *
                         *  var global = this;
                         *  function func() {
                         *      with({ eval: global.eval) { eval("var x = 10;") }
                         *  }
                         */
                        loadExpressionAsObject(ident.setIsNotFunction()); // Type.OBJECT as foo() makes no sense if foo == 3
                        globalIsEval();
                        method.ifeq(is_not_eval);

                        // Load up self (scope).
                        method.loadCompilerConstant(SCOPE);
                        final List<Expression> evalArgs = callNode.getEvalArgs().getArgs();
                        // load evaluated code
                        loadExpressionAsObject(evalArgs.get(0));
                        // load second and subsequent args for side-effect
                        final int numArgs = evalArgs.size();
                        for (int i = 1; i < numArgs; i++) {
                            loadAndDiscard(evalArgs.get(i));
                        }
                        method._goto(invoke_direct_eval);

                        method.label(is_not_eval);
                        // load this time but with dyn:getMethod|getProp|getElem
                        loadExpressionAsObject(ident); // Type.OBJECT as foo() makes no sense if foo == 3
                        // This is some scope 'eval' or global eval replaced by user
                        // but not the built-in ECMAScript 'eval' function call
                        method.loadNull();
                        argsCount = loadArgs(callNode.getArgs());
                    }

                    @Override
                    void consumeStack() {
                        // Ordinary call
                        dynamicCall(2 + argsCount, flags, "eval");
                        method._goto(eval_done);

                        method.label(invoke_direct_eval);
                        // Special/extra 'eval' arguments. These can be loaded late (in consumeStack) as we know none of
                        // them can ever be optimistic.
                        method.loadCompilerConstant(THIS);
                        method.load(callNode.getEvalArgs().getLocation());
                        method.load(CodeGenerator.this.lc.getCurrentFunction().isStrict());
                        // direct call to Global.directEval
                        globalDirectEval();
                        convertOptimisticReturnValue();
                        coerceStackTop(resultBounds);
                    }
                }.emit();

                method.label(eval_done);
            }

            @Override
            public boolean enterIdentNode(final IdentNode node) {
                final Symbol symbol = node.getSymbol();

                if (symbol.isScope()) {
                    final int flags = getScopeCallSiteFlags(symbol);
                    final int useCount = symbol.getUseCount();

                    // Threshold for generating shared scope callsite is lower for fast scope symbols because we know
                    // we can dial in the correct scope. However, we also need to enable it for non-fast scopes to
                    // support huge scripts like mandreel.js.
                    if (callNode.isEval()) {
                        evalCall(node, flags);
                    } else if (useCount <= SharedScopeCall.FAST_SCOPE_CALL_THRESHOLD
                            || !isFastScope(symbol) && useCount <= SharedScopeCall.SLOW_SCOPE_CALL_THRESHOLD
                            || CodeGenerator.this.lc.inDynamicScope()
                            || callNode.isOptimistic()) {
                        scopeCall(node, flags);
                    } else {
                        sharedScopeCall(node, flags);
                    }
                    assert method.peekType().equals(resultBounds.within(callNode.getType())) : method.peekType() + " != " + resultBounds + "(" + callNode.getType() + ")";
                } else {
                    enterDefault(node);
                }

                return false;
            }

            @Override
            public boolean enterAccessNode(final AccessNode node) {
                //check if this is an apply to call node. only real applies, that haven't been
                //shadowed from their way to the global scope counts

                //call nodes have program points.

                final int flags = getCallSiteFlags() | (callNode.isApplyToCall() ? CALLSITE_APPLY_TO_CALL : 0);

                new OptimisticOperation(callNode, resultBounds) {
                    int argCount;
                    @Override
                    void loadStack() {
                        loadExpressionAsObject(node.getBase());
                        method.dup();
                        // NOTE: not using a nested OptimisticOperation on this dynamicGet, as we expect to get back
                        // a callable object. Nobody in their right mind would optimistically type this call site.
                        assert !node.isOptimistic();
                        method.dynamicGet(node.getType(), node.getProperty(), flags, true, node.isIndex());
                        method.swap();
                        argCount = loadArgs(args);
                    }
                    @Override
                    void consumeStack() {
                        dynamicCall(2 + argCount, flags, node.toString(false));
                    }
                }.emit();

                return false;
            }

            @Override
            public boolean enterFunctionNode(final FunctionNode origCallee) {
                new OptimisticOperation(callNode, resultBounds) {
                    FunctionNode callee;
                    int argsCount;
                    @Override
                    void loadStack() {
                        callee = (FunctionNode)origCallee.accept(CodeGenerator.this);
                        if (callee.isStrict()) { // "this" is undefined
                            method.loadUndefined(Type.OBJECT);
                        } else { // get global from scope (which is the self)
                            globalInstance();
                        }
                        argsCount = loadArgs(args);
                    }

                    @Override
                    void consumeStack() {
                        dynamicCall(2 + argsCount, getCallSiteFlags(), null);
                    }
                }.emit();
                return false;
            }

            @Override
            public boolean enterIndexNode(final IndexNode node) {
                new OptimisticOperation(callNode, resultBounds) {
                    int argsCount;
                    @Override
                    void loadStack() {
                        loadExpressionAsObject(node.getBase());
                        method.dup();
                        final Type indexType = node.getIndex().getType();
                        if (indexType.isObject() || indexType.isBoolean()) {
                            loadExpressionAsObject(node.getIndex()); //TODO boolean
                        } else {
                            loadExpressionUnbounded(node.getIndex());
                        }
                        // NOTE: not using a nested OptimisticOperation on this dynamicGetIndex, as we expect to get
                        // back a callable object. Nobody in their right mind would optimistically type this call site.
                        assert !node.isOptimistic();
                        method.dynamicGetIndex(node.getType(), getCallSiteFlags(), true);
                        method.swap();
                        argsCount = loadArgs(args);
                    }
                    @Override
                    void consumeStack() {
                        dynamicCall(2 + argsCount, getCallSiteFlags(), node.toString(false));
                    }
                }.emit();
                return false;
            }

            @Override
            protected boolean enterDefault(final Node node) {
                new OptimisticOperation(callNode, resultBounds) {
                    int argsCount;
                    @Override
                    void loadStack() {
                        // Load up function.
                        loadExpressionAsObject(function); //TODO, e.g. booleans can be used as functions
                        method.loadUndefined(Type.OBJECT); // ScriptFunction will figure out the correct this when it sees CALLSITE_SCOPE
                        argsCount = loadArgs(args);
                        }
                        @Override
                        void consumeStack() {
                            final int flags = getCallSiteFlags() | CALLSITE_SCOPE;
                            dynamicCall(2 + argsCount, flags, node.toString(false));
                        }
                }.emit();
                return false;
            }
        });

        return false;
    }

    /**
     * Returns the flags with optimistic flag and program point removed.
     * @param flags the flags that need optimism stripped from them.
     * @return flags without optimism
     */
    static int nonOptimisticFlags(final int flags) {
        return flags & ~(CALLSITE_OPTIMISTIC | -1 << CALLSITE_PROGRAM_POINT_SHIFT);
    }

    @Override
    public boolean enterContinueNode(final ContinueNode continueNode) {
        return enterJumpStatement(continueNode);
    }

    @Override
    public boolean enterEmptyNode(final EmptyNode emptyNode) {
        // Don't even record the line number, it's irrelevant as there's no code.
        return false;
    }

    @Override
    public boolean enterExpressionStatement(final ExpressionStatement expressionStatement) {
        if(!method.isReachable()) {
            return false;
        }
        enterStatement(expressionStatement);

        loadAndDiscard(expressionStatement.getExpression());
        assert method.getStackSize() == 0 : "stack not empty in " + expressionStatement;

        return false;
    }

    @Override
    public boolean enterBlockStatement(final BlockStatement blockStatement) {
        if(!method.isReachable()) {
            return false;
        }
        enterStatement(blockStatement);

        blockStatement.getBlock().accept(this);

        return false;
    }

    @Override
    public boolean enterForNode(final ForNode forNode) {
        if(!method.isReachable()) {
            return false;
        }
        enterStatement(forNode);
        if (forNode.isForIn()) {
            enterForIn(forNode);
        } else {
            final Expression init = forNode.getInit();
            if (init != null) {
                loadAndDiscard(init);
            }
            enterForOrWhile(forNode, forNode.getModify());
        }

        return false;
    }

    private void enterForIn(final ForNode forNode) {
        loadExpression(forNode.getModify(), TypeBounds.OBJECT);
        method.invoke(forNode.isForEach() ? ScriptRuntime.TO_VALUE_ITERATOR : ScriptRuntime.TO_PROPERTY_ITERATOR);
        final Symbol iterSymbol = forNode.getIterator();
        final int iterSlot = iterSymbol.getSlot(Type.OBJECT);
        method.store(iterSymbol, ITERATOR_TYPE);

        method.beforeJoinPoint(forNode);

        final Label continueLabel = forNode.getContinueLabel();
        final Label breakLabel    = forNode.getBreakLabel();

        method.label(continueLabel);
        method.load(ITERATOR_TYPE, iterSlot);
        method.invoke(interfaceCallNoLookup(ITERATOR_CLASS, "hasNext", boolean.class));
        final JoinPredecessorExpression test = forNode.getTest();
        final Block body = forNode.getBody();
        if(LocalVariableConversion.hasLiveConversion(test)) {
            final Label afterConversion = new Label("for_in_after_test_conv");
            method.ifne(afterConversion);
            method.beforeJoinPoint(test);
            method._goto(breakLabel);
            method.label(afterConversion);
        } else {
            method.ifeq(breakLabel);
        }

        new Store<Expression>(forNode.getInit()) {
            @Override
            protected void storeNonDiscard() {
                // This expression is neither part of a discard, nor needs to be left on the stack after it was
                // stored, so we override storeNonDiscard to be a no-op.
            }

            @Override
            protected void evaluate() {
                new OptimisticOperation((Optimistic)forNode.getInit(), TypeBounds.UNBOUNDED) {
                    @Override
                    void loadStack() {
                        method.load(ITERATOR_TYPE, iterSlot);
                    }

                    @Override
                    void consumeStack() {
                        method.invoke(interfaceCallNoLookup(ITERATOR_CLASS, "next", Object.class));
                        convertOptimisticReturnValue();
                    }
                }.emit();
            }
        }.store();
        body.accept(this);

        if(method.isReachable()) {
            method._goto(continueLabel);
        }
        method.label(breakLabel);
    }

    /**
     * Initialize the slots in a frame to undefined.
     *
     * @param block block with local vars.
     */
    private void initLocals(final Block block) {
        lc.onEnterBlock(block);

        final boolean isFunctionBody = lc.isFunctionBody();
        final FunctionNode function = lc.getCurrentFunction();
        if (isFunctionBody) {
            initializeMethodParameters(function);
            if(!function.isVarArg()) {
                expandParameterSlots(function);
            }
            if (method.hasScope()) {
                if (function.needsParentScope()) {
                    method.loadCompilerConstant(CALLEE);
                    method.invoke(ScriptFunction.GET_SCOPE);
                } else {
                    assert function.hasScopeBlock();
                    method.loadNull();
                }
                method.storeCompilerConstant(SCOPE);
            }
            if (function.needsArguments()) {
                initArguments(function);
            }
        }

        /*
         * Determine if block needs scope, if not, just do initSymbols for this block.
         */
        if (block.needsScope()) {
            /*
             * Determine if function is varargs and consequently variables have to
             * be in the scope.
             */
            final boolean varsInScope = function.allVarsInScope();

            // TODO for LET we can do better: if *block* does not contain any eval/with, we don't need its vars in scope.

            final boolean hasArguments = function.needsArguments();
            final List<MapTuple<Symbol>> tuples = new ArrayList<>();
            final Iterator<IdentNode> paramIter = function.getParameters().iterator();
            for (final Symbol symbol : block.getSymbols()) {
                if (symbol.isInternal() || symbol.isThis()) {
                    continue;
                }

                if (symbol.isVar()) {
                    assert !varsInScope || symbol.isScope();
                    if (varsInScope || symbol.isScope()) {
                        assert symbol.isScope()   : "scope for " + symbol + " should have been set in Lower already " + function.getName();
                        assert !symbol.hasSlot()  : "slot for " + symbol + " should have been removed in Lower already" + function.getName();

                        //this tuple will not be put fielded, as it has no value, just a symbol
                        tuples.add(new MapTuple<Symbol>(symbol.getName(), symbol, null));
                    } else {
                        assert symbol.hasSlot() || symbol.slotCount() == 0 : symbol + " should have a slot only, no scope";
                    }
                } else if (symbol.isParam() && (varsInScope || hasArguments || symbol.isScope())) {
                    assert symbol.isScope()   : "scope for " + symbol + " should have been set in AssignSymbols already " + function.getName() + " varsInScope="+varsInScope+" hasArguments="+hasArguments+" symbol.isScope()=" + symbol.isScope();
                    assert !(hasArguments && symbol.hasSlot())  : "slot for " + symbol + " should have been removed in Lower already " + function.getName();

                    final Type   paramType;
                    final Symbol paramSymbol;

                    if (hasArguments) {
                        assert !symbol.hasSlot()  : "slot for " + symbol + " should have been removed in Lower already ";
                        paramSymbol = null;
                        paramType   = null;
                    } else {
                        paramSymbol = symbol;
                        // NOTE: We're relying on the fact here that Block.symbols is a LinkedHashMap, hence it will
                        // return symbols in the order they were defined, and parameters are defined in the same order
                        // they appear in the function. That's why we can have a single pass over the parameter list
                        // with an iterator, always just scanning forward for the next parameter that matches the symbol
                        // name.
                        for(;;) {
                            final IdentNode nextParam = paramIter.next();
                            if(nextParam.getName().equals(symbol.getName())) {
                                paramType = nextParam.getType();
                                break;
                            }
                        }
                    }

                    tuples.add(new MapTuple<Symbol>(symbol.getName(), symbol, paramType, paramSymbol) {
                        //this symbol will be put fielded, we can't initialize it as undefined with a known type
                        @Override
                        public Class<?> getValueType() {
                            if (!useDualFields() ||  value == null || paramType == null || paramType.isBoolean()) {
                                return Object.class;
                            }
                            return paramType.getTypeClass();
                        }
                    });
                }
            }

            /*
             * Create a new object based on the symbols and values, generate
             * bootstrap code for object
             */
            new FieldObjectCreator<Symbol>(this, tuples, true, hasArguments) {
                @Override
                protected void loadValue(final Symbol value, final Type type) {
                    method.load(value, type);
                }
            }.makeObject(method);
            // program function: merge scope into global
            if (isFunctionBody && function.isProgram()) {
                method.invoke(ScriptRuntime.MERGE_SCOPE);
            }

            method.storeCompilerConstant(SCOPE);
            if(!isFunctionBody) {
                // Function body doesn't need a try/catch to restore scope, as it'd be a dead store anyway. Allowing it
                // actually causes issues with UnwarrantedOptimismException handlers as ASM will sort this handler to
                // the top of the exception handler table, so it'll be triggered instead of the UOE handlers.
                final Label scopeEntryLabel = new Label("scope_entry");
                scopeEntryLabels.push(scopeEntryLabel);
                method.label(scopeEntryLabel);
            }
        } else if (isFunctionBody && function.isVarArg()) {
            // Since we don't have a scope, parameters didn't get assigned array indices by the FieldObjectCreator, so
            // we need to assign them separately here.
            int nextParam = 0;
            for (final IdentNode param : function.getParameters()) {
                param.getSymbol().setFieldIndex(nextParam++);
            }
        }

        // Debugging: print symbols? @see --print-symbols flag
        printSymbols(block, function, (isFunctionBody ? "Function " : "Block in ") + (function.getIdent() == null ? "<anonymous>" : function.getIdent().getName()));
    }

    /**
     * Incoming method parameters are always declared on method entry; declare them in the local variable table.
     * @param function function for which code is being generated.
     */
    private void initializeMethodParameters(final FunctionNode function) {
        final Label functionStart = new Label("fn_start");
        method.label(functionStart);
        int nextSlot = 0;
        if(function.needsCallee()) {
            initializeInternalFunctionParameter(CALLEE, function, functionStart, nextSlot++);
        }
        initializeInternalFunctionParameter(THIS, function, functionStart, nextSlot++);
        if(function.isVarArg()) {
            initializeInternalFunctionParameter(VARARGS, function, functionStart, nextSlot++);
        } else {
            for(final IdentNode param: function.getParameters()) {
                final Symbol symbol = param.getSymbol();
                if(symbol.isBytecodeLocal()) {
                    method.initializeMethodParameter(symbol, param.getType(), functionStart);
                }
            }
        }
    }

    private void initializeInternalFunctionParameter(final CompilerConstants cc, final FunctionNode fn, final Label functionStart, final int slot) {
        final Symbol symbol = initializeInternalFunctionOrSplitParameter(cc, fn, functionStart, slot);
        // Internal function params (:callee, this, and :varargs) are never expanded to multiple slots
        assert symbol.getFirstSlot() == slot;
    }

    private Symbol initializeInternalFunctionOrSplitParameter(final CompilerConstants cc, final FunctionNode fn, final Label functionStart, final int slot) {
        final Symbol symbol = fn.getBody().getExistingSymbol(cc.symbolName());
        final Type type = Type.typeFor(cc.type());
        method.initializeMethodParameter(symbol, type, functionStart);
        method.onLocalStore(type, slot);
        return symbol;
    }

    /**
     * Parameters come into the method packed into local variable slots next to each other. Nashorn on the other hand
     * can use 1-6 slots for a local variable depending on all the types it needs to store. When this method is invoked,
     * the symbols are already allocated such wider slots, but the values are still in tightly packed incoming slots,
     * and we need to spread them into their new locations.
     * @param function the function for which parameter-spreading code needs to be emitted
     */
    private void expandParameterSlots(final FunctionNode function) {
        final List<IdentNode> parameters = function.getParameters();
        // Calculate the total number of incoming parameter slots
        int currentIncomingSlot = function.needsCallee() ? 2 : 1;
        for(final IdentNode parameter: parameters) {
            currentIncomingSlot += parameter.getType().getSlots();
        }
        // Starting from last parameter going backwards, move the parameter values into their new slots.
        for(int i = parameters.size(); i-- > 0;) {
            final IdentNode parameter = parameters.get(i);
            final Type parameterType = parameter.getType();
            final int typeWidth = parameterType.getSlots();
            currentIncomingSlot -= typeWidth;
            final Symbol symbol = parameter.getSymbol();
            final int slotCount = symbol.slotCount();
            assert slotCount > 0;
            // Scoped parameters must not hold more than one value
            assert symbol.isBytecodeLocal() || slotCount == typeWidth;

            // Mark it as having its value stored into it by the method invocation.
            method.onLocalStore(parameterType, currentIncomingSlot);
            if(currentIncomingSlot != symbol.getSlot(parameterType)) {
                method.load(parameterType, currentIncomingSlot);
                method.store(symbol, parameterType);
            }
        }
    }

    private void initArguments(final FunctionNode function) {
        method.loadCompilerConstant(VARARGS);
        if (function.needsCallee()) {
            method.loadCompilerConstant(CALLEE);
        } else {
            // If function is strict mode, "arguments.callee" is not populated, so we don't necessarily need the
            // caller.
            assert function.isStrict();
            method.loadNull();
        }
        method.load(function.getParameters().size());
        globalAllocateArguments();
        method.storeCompilerConstant(ARGUMENTS);
    }

    private boolean skipFunction(final FunctionNode functionNode) {
        final ScriptEnvironment env = compiler.getScriptEnvironment();
        final boolean lazy = env._lazy_compilation;
        final boolean onDemand = compiler.isOnDemandCompilation();

        // If this is on-demand or lazy compilation, don't compile a nested (not topmost) function.
        if((onDemand || lazy) && lc.getOutermostFunction() != functionNode) {
            return true;
        }

        // If lazy compiling with optimistic types, don't compile the program eagerly either. It will soon be
        // invalidated anyway. In presence of a class cache, this further means that an obsoleted program version
        // lingers around. Also, currently loading previously persisted optimistic types information only works if
        // we're on-demand compiling a function, so with this strategy the :program method can also have the warmup
        // benefit of using previously persisted types.
        //
        // NOTE that this means the first compiled class will effectively just have a :createProgramFunction method, and
        // the RecompilableScriptFunctionData (RSFD) object in its constants array. It won't even have the :program
        // method. This is by design. It does mean that we're wasting one compiler execution (and we could minimize this
        // by just running it up to scope depth calculation, which creates the RSFDs and then this limited codegen).
        // We could emit an initial separate compile unit with the initial version of :program in it to better utilize
        // the compilation pipeline, but that would need more invasive changes, as currently the assumption that
        // :program is emitted into the first compilation unit of the function lives in many places.
        return !onDemand && lazy && env._optimistic_types && functionNode.isProgram();
    }

    @Override
    public boolean enterFunctionNode(final FunctionNode functionNode) {
        if (skipFunction(functionNode)) {
            // In case we are not generating code for the function, we must create or retrieve the function object and
            // load it on the stack here.
            newFunctionObject(functionNode, false);
            return false;
        }

        final String fnName = functionNode.getName();

        // NOTE: we only emit the method for a function with the given name once. We can have multiple functions with
        // the same name as a result of inlining finally blocks. However, in the future -- with type specialization,
        // notably -- we might need to check for both name *and* signature. Of course, even that might not be
        // sufficient; the function might have a code dependency on the type of the variables in its enclosing scopes,
        // and the type of such a variable can be different in catch and finally blocks. So, in the future we will have
        // to decide to either generate a unique method for each inlined copy of the function, maybe figure out its
        // exact type closure and deduplicate based on that, or just decide that functions in finally blocks aren't
        // worth it, and generate one method with most generic type closure.
        if (!emittedMethods.contains(fnName)) {
            log.info("=== BEGIN ", fnName);

            assert functionNode.getCompileUnit() != null : "no compile unit for " + fnName + " " + Debug.id(functionNode);
            unit = lc.pushCompileUnit(functionNode.getCompileUnit());
            assert lc.hasCompileUnits();

            final ClassEmitter classEmitter = unit.getClassEmitter();
            pushMethodEmitter(isRestOf() ? classEmitter.restOfMethod(functionNode) : classEmitter.method(functionNode));
            method.setPreventUndefinedLoad();
            if(useOptimisticTypes()) {
                lc.pushUnwarrantedOptimismHandlers();
            }

            // new method - reset last line number
            lastLineNumber = -1;

            method.begin();

            if (isRestOf()) {
                assert continuationInfo == null;
                continuationInfo = new ContinuationInfo();
                method.gotoLoopStart(continuationInfo.getHandlerLabel());
            }
        }

        return true;
    }

    private void pushMethodEmitter(final MethodEmitter newMethod) {
        method = lc.pushMethodEmitter(newMethod);
        catchLabels.push(METHOD_BOUNDARY);
    }

    private void popMethodEmitter() {
        method = lc.popMethodEmitter(method);
        assert catchLabels.peek() == METHOD_BOUNDARY;
        catchLabels.pop();
    }

    @Override
    public Node leaveFunctionNode(final FunctionNode functionNode) {
        try {
            final boolean markOptimistic;
            if (emittedMethods.add(functionNode.getName())) {
                markOptimistic = generateUnwarrantedOptimismExceptionHandlers(functionNode);
                generateContinuationHandler();
                method.end(); // wrap up this method
                unit   = lc.popCompileUnit(functionNode.getCompileUnit());
                popMethodEmitter();
                log.info("=== END ", functionNode.getName());
            } else {
                markOptimistic = false;
            }

            FunctionNode newFunctionNode = functionNode;
            if (markOptimistic) {
                newFunctionNode = newFunctionNode.setFlag(lc, FunctionNode.IS_DEOPTIMIZABLE);
            }

            newFunctionObject(newFunctionNode, true);
            return newFunctionNode;
        } catch (final Throwable t) {
            Context.printStackTrace(t);
            final VerifyError e = new VerifyError("Code generation bug in \"" + functionNode.getName() + "\": likely stack misaligned: " + t + " " + functionNode.getSource().getName());
            e.initCause(t);
            throw e;
        }
    }

    @Override
    public boolean enterIfNode(final IfNode ifNode) {
        if(!method.isReachable()) {
            return false;
        }
        enterStatement(ifNode);

        final Expression test = ifNode.getTest();
        final Block pass = ifNode.getPass();
        final Block fail = ifNode.getFail();

        if (Expression.isAlwaysTrue(test)) {
            loadAndDiscard(test);
            pass.accept(this);
            return false;
        } else if (Expression.isAlwaysFalse(test)) {
            loadAndDiscard(test);
            if (fail != null) {
                fail.accept(this);
            }
            return false;
        }

        final boolean hasFailConversion = LocalVariableConversion.hasLiveConversion(ifNode);

        final Label failLabel  = new Label("if_fail");
        final Label afterLabel = (fail == null && !hasFailConversion) ? null : new Label("if_done");

        emitBranch(test, failLabel, false);

        pass.accept(this);
        if(method.isReachable() && afterLabel != null) {
            method._goto(afterLabel); //don't fallthru to fail block
        }
        method.label(failLabel);

        if (fail != null) {
            fail.accept(this);
        } else if(hasFailConversion) {
            method.beforeJoinPoint(ifNode);
        }

        if(afterLabel != null && afterLabel.isReachable()) {
            method.label(afterLabel);
        }

        return false;
    }

    private void emitBranch(final Expression test, final Label label, final boolean jumpWhenTrue) {
        new BranchOptimizer(this, method).execute(test, label, jumpWhenTrue);
    }

    private void enterStatement(final Statement statement) {
        lineNumber(statement);
    }

    private void lineNumber(final Statement statement) {
        lineNumber(statement.getLineNumber());
    }

    private void lineNumber(final int lineNumber) {
        if (lineNumber != lastLineNumber && lineNumber != Node.NO_LINE_NUMBER) {
            method.lineNumber(lineNumber);
            lastLineNumber = lineNumber;
        }
    }

    int getLastLineNumber() {
        return lastLineNumber;
    }

    /**
     * Load a list of nodes as an array of a specific type
     * The array will contain the visited nodes.
     *
     * @param arrayLiteralNode the array of contents
     * @param arrayType        the type of the array, e.g. ARRAY_NUMBER or ARRAY_OBJECT
     */
    private void loadArray(final ArrayLiteralNode arrayLiteralNode, final ArrayType arrayType) {
        assert arrayType == Type.INT_ARRAY || arrayType == Type.NUMBER_ARRAY || arrayType == Type.OBJECT_ARRAY;

        final Expression[]     nodes    = arrayLiteralNode.getValue();
        final Object           presets  = arrayLiteralNode.getPresets();
        final int[]            postsets = arrayLiteralNode.getPostsets();
        final List<Splittable.SplitRange> ranges   = arrayLiteralNode.getSplitRanges();

        loadConstant(presets);

        final Type elementType = arrayType.getElementType();

        if (ranges != null) {

            loadSplitLiteral(new SplitLiteralCreator() {
                @Override
                public void populateRange(final MethodEmitter method, final Type type, final int slot, final int start, final int end) {
                    for (int i = start; i < end; i++) {
                        method.load(type, slot);
                        storeElement(nodes, elementType, postsets[i]);
                    }
                    method.load(type, slot);
                }
            }, ranges, arrayType);

            return;
        }

        if(postsets.length > 0) {
            final int arraySlot = method.getUsedSlotsWithLiveTemporaries();
            method.storeTemp(arrayType, arraySlot);
            for (final int postset : postsets) {
                method.load(arrayType, arraySlot);
                storeElement(nodes, elementType, postset);
            }
            method.load(arrayType, arraySlot);
        }
    }

    private void storeElement(final Expression[] nodes, final Type elementType, final int index) {
        method.load(index);

        final Expression element = nodes[index];

        if (element == null) {
            method.loadEmpty(elementType);
        } else {
            loadExpressionAsType(element, elementType);
        }

        method.arraystore();
    }

    private MethodEmitter loadArgsArray(final List<Expression> args) {
        final Object[] array = new Object[args.size()];
        loadConstant(array);

        for (int i = 0; i < args.size(); i++) {
            method.dup();
            method.load(i);
            loadExpression(args.get(i), TypeBounds.OBJECT); // variable arity methods always take objects
            method.arraystore();
        }

        return method;
    }

    /**
     * Load a constant from the constant array. This is only public to be callable from the objects
     * subpackage. Do not call directly.
     *
     * @param string string to load
     */
    void loadConstant(final String string) {
        final String       unitClassName = unit.getUnitClassName();
        final ClassEmitter classEmitter  = unit.getClassEmitter();
        final int          index         = compiler.getConstantData().add(string);

        method.load(index);
        method.invokestatic(unitClassName, GET_STRING.symbolName(), methodDescriptor(String.class, int.class));
        classEmitter.needGetConstantMethod(String.class);
    }

    /**
     * Load a constant from the constant array. This is only public to be callable from the objects
     * subpackage. Do not call directly.
     *
     * @param object object to load
     */
    void loadConstant(final Object object) {
        loadConstant(object, unit, method);
    }

    private void loadConstant(final Object object, final CompileUnit compileUnit, final MethodEmitter methodEmitter) {
        final String       unitClassName = compileUnit.getUnitClassName();
        final ClassEmitter classEmitter  = compileUnit.getClassEmitter();
        final int          index         = compiler.getConstantData().add(object);
        final Class<?>     cls           = object.getClass();

        if (cls == PropertyMap.class) {
            methodEmitter.load(index);
            methodEmitter.invokestatic(unitClassName, GET_MAP.symbolName(), methodDescriptor(PropertyMap.class, int.class));
            classEmitter.needGetConstantMethod(PropertyMap.class);
        } else if (cls.isArray()) {
            methodEmitter.load(index);
            final String methodName = ClassEmitter.getArrayMethodName(cls);
            methodEmitter.invokestatic(unitClassName, methodName, methodDescriptor(cls, int.class));
            classEmitter.needGetConstantMethod(cls);
        } else {
            methodEmitter.loadConstants().load(index).arrayload();
            if (object instanceof ArrayData) {
                methodEmitter.checkcast(ArrayData.class);
                methodEmitter.invoke(virtualCallNoLookup(ArrayData.class, "copy", ArrayData.class));
            } else if (cls != Object.class) {
                methodEmitter.checkcast(cls);
            }
        }
    }

    private void loadConstantsAndIndex(final Object object, final MethodEmitter methodEmitter) {
        methodEmitter.loadConstants().load(compiler.getConstantData().add(object));
    }

    // literal values
    private void loadLiteral(final LiteralNode<?> node, final TypeBounds resultBounds) {
        final Object value = node.getValue();

        if (value == null) {
            method.loadNull();
        } else if (value instanceof Undefined) {
            method.loadUndefined(resultBounds.within(Type.OBJECT));
        } else if (value instanceof String) {
            final String string = (String)value;

            if (string.length() > MethodEmitter.LARGE_STRING_THRESHOLD / 3) { // 3 == max bytes per encoded char
                loadConstant(string);
            } else {
                method.load(string);
            }
        } else if (value instanceof RegexToken) {
            loadRegex((RegexToken)value);
        } else if (value instanceof Boolean) {
            method.load((Boolean)value);
        } else if (value instanceof Integer) {
            if(!resultBounds.canBeNarrowerThan(Type.OBJECT)) {
                method.load((Integer)value);
                method.convert(Type.OBJECT);
            } else if(!resultBounds.canBeNarrowerThan(Type.NUMBER)) {
                method.load(((Integer)value).doubleValue());
            } else {
                method.load((Integer)value);
            }
        } else if (value instanceof Double) {
            if(!resultBounds.canBeNarrowerThan(Type.OBJECT)) {
                method.load((Double)value);
                method.convert(Type.OBJECT);
            } else {
                method.load((Double)value);
            }
        } else if (node instanceof ArrayLiteralNode) {
            final ArrayLiteralNode arrayLiteral = (ArrayLiteralNode)node;
            final ArrayType atype = arrayLiteral.getArrayType();
            loadArray(arrayLiteral, atype);
            globalAllocateArray(atype);
        } else {
            throw new UnsupportedOperationException("Unknown literal for " + node.getClass() + " " + value.getClass() + " " + value);
        }
    }

    private MethodEmitter loadRegexToken(final RegexToken value) {
        method.load(value.getExpression());
        method.load(value.getOptions());
        return globalNewRegExp();
    }

    private MethodEmitter loadRegex(final RegexToken regexToken) {
        if (regexFieldCount > MAX_REGEX_FIELDS) {
            return loadRegexToken(regexToken);
        }
        // emit field
        final String       regexName    = lc.getCurrentFunction().uniqueName(REGEX_PREFIX.symbolName());
        final ClassEmitter classEmitter = unit.getClassEmitter();

        classEmitter.field(EnumSet.of(PRIVATE, STATIC), regexName, Object.class);
        regexFieldCount++;

        // get field, if null create new regex, finally clone regex object
        method.getStatic(unit.getUnitClassName(), regexName, typeDescriptor(Object.class));
        method.dup();
        final Label cachedLabel = new Label("cached");
        method.ifnonnull(cachedLabel);

        method.pop();
        loadRegexToken(regexToken);
        method.dup();
        method.putStatic(unit.getUnitClassName(), regexName, typeDescriptor(Object.class));

        method.label(cachedLabel);
        globalRegExpCopy();

        return method;
    }

    /**
     * Check if a property value contains a particular program point
     * @param value value
     * @param pp    program point
     * @return true if it's there.
     */
    private static boolean propertyValueContains(final Expression value, final int pp) {
        return new Supplier<Boolean>() {
            boolean contains;

            @Override
            public Boolean get() {
                value.accept(new SimpleNodeVisitor() {
                    @Override
                    public boolean enterFunctionNode(final FunctionNode functionNode) {
                        return false;
                    }

                    @Override
                    public boolean enterDefault(final Node node) {
                        if (contains) {
                            return false;
                        }
                        if (node instanceof Optimistic && ((Optimistic)node).getProgramPoint() == pp) {
                            contains = true;
                            return false;
                        }
                        return true;
                    }
                });

                return contains;
            }
        }.get();
    }

    private void loadObjectNode(final ObjectNode objectNode) {
        final List<PropertyNode> elements = objectNode.getElements();

        final List<MapTuple<Expression>> tuples = new ArrayList<>();
        final List<PropertyNode> gettersSetters = new ArrayList<>();
        final int ccp = getCurrentContinuationEntryPoint();
        final List<Splittable.SplitRange> ranges = objectNode.getSplitRanges();

        Expression protoNode = null;
        boolean restOfProperty = false;

        for (final PropertyNode propertyNode : elements) {
            final Expression value = propertyNode.getValue();
            final String key = propertyNode.getKeyName();
            // Just use a pseudo-symbol. We just need something non null; use the name and zero flags.
            final Symbol symbol = value == null ? null : new Symbol(key, 0);

            if (value == null) {
                gettersSetters.add(propertyNode);
            } else if (propertyNode.getKey() instanceof IdentNode &&
                       key.equals(ScriptObject.PROTO_PROPERTY_NAME)) {
                // ES6 draft compliant __proto__ inside object literal
                // Identifier key and name is __proto__
                protoNode = value;
                continue;
            }

            restOfProperty |=
                value != null &&
                isValid(ccp) &&
                propertyValueContains(value, ccp);

            //for literals, a value of null means object type, i.e. the value null or getter setter function
            //(I think)
            final Class<?> valueType = (!useDualFields() || value == null || value.getType().isBoolean()) ? Object.class : value.getType().getTypeClass();
            tuples.add(new MapTuple<Expression>(key, symbol, Type.typeFor(valueType), value) {
                @Override
                public Class<?> getValueType() {
                    return type.getTypeClass();
                }
            });
        }

        final ObjectCreator<?> oc;
        if (elements.size() > OBJECT_SPILL_THRESHOLD) {
            oc = new SpillObjectCreator(this, tuples);
        } else {
            oc = new FieldObjectCreator<Expression>(this, tuples) {
                @Override
                protected void loadValue(final Expression node, final Type type) {
                    // Use generic type in order to avoid conversion between object types
                    loadExpressionAsType(node, Type.generic(type));
                }};
        }

        if (ranges != null) {
            oc.createObject(method);
            loadSplitLiteral(oc, ranges, Type.typeFor(oc.getAllocatorClass()));
        } else {
            oc.makeObject(method);
        }

        //if this is a rest of method and our continuation point was found as one of the values
        //in the properties above, we need to reset the map to oc.getMap() in the continuation
        //handler
        if (restOfProperty) {
            final ContinuationInfo ci = getContinuationInfo();
            ci.setObjectLiteralMap(method.getStackSize(), oc.getMap());
        }

        method.dup();
        if (protoNode != null) {
            loadExpressionAsObject(protoNode);
            // take care of { __proto__: 34 } or some such!
            method.convert(Type.OBJECT);
            method.invoke(ScriptObject.SET_PROTO_FROM_LITERAL);
        } else {
            method.invoke(ScriptObject.SET_GLOBAL_OBJECT_PROTO);
        }

        for (final PropertyNode propertyNode : gettersSetters) {
            final FunctionNode getter = propertyNode.getGetter();
            final FunctionNode setter = propertyNode.getSetter();

            assert getter != null || setter != null;

            method.dup().loadKey(propertyNode.getKey());
            if (getter == null) {
                method.loadNull();
            } else {
                getter.accept(this);
            }

            if (setter == null) {
                method.loadNull();
            } else {
                setter.accept(this);
            }

            method.invoke(ScriptObject.SET_USER_ACCESSORS);
        }
    }

    @Override
    public boolean enterReturnNode(final ReturnNode returnNode) {
        if(!method.isReachable()) {
            return false;
        }
        enterStatement(returnNode);

        final Type returnType = lc.getCurrentFunction().getReturnType();

        final Expression expression = returnNode.getExpression();
        if (expression != null) {
            loadExpressionUnbounded(expression);
        } else {
            method.loadUndefined(returnType);
        }

        method._return(returnType);

        return false;
    }

    private boolean undefinedCheck(final RuntimeNode runtimeNode, final List<Expression> args) {
        final Request request = runtimeNode.getRequest();

        if (!Request.isUndefinedCheck(request)) {
            return false;
        }

        final Expression lhs = args.get(0);
        final Expression rhs = args.get(1);

        final Symbol lhsSymbol = lhs instanceof IdentNode ? ((IdentNode)lhs).getSymbol() : null;
        final Symbol rhsSymbol = rhs instanceof IdentNode ? ((IdentNode)rhs).getSymbol() : null;
        // One must be a "undefined" identifier, otherwise we can't get here
        assert lhsSymbol != null || rhsSymbol != null;

        final Symbol undefinedSymbol;
        if (isUndefinedSymbol(lhsSymbol)) {
            undefinedSymbol = lhsSymbol;
        } else {
            assert isUndefinedSymbol(rhsSymbol);
            undefinedSymbol = rhsSymbol;
        }

        assert undefinedSymbol != null; //remove warning
        if (!undefinedSymbol.isScope()) {
            return false; //disallow undefined as local var or parameter
        }

        if (lhsSymbol == undefinedSymbol && lhs.getType().isPrimitive()) {
            //we load the undefined first. never mind, because this will deoptimize anyway
            return false;
        }

        if(isDeoptimizedExpression(lhs)) {
            // This is actually related to "lhs.getType().isPrimitive()" above: any expression being deoptimized in
            // the current chain of rest-of compilations used to have a type narrower than Object (so it was primitive).
            // We must not perform undefined check specialization for them, as then we'd violate the basic rule of
            // "Thou shalt not alter the stack shape between a deoptimized method and any of its (transitive) rest-ofs."
            return false;
        }

        //make sure that undefined has not been overridden or scoped as a local var
        //between us and global
        if (!compiler.isGlobalSymbol(lc.getCurrentFunction(), "undefined")) {
            return false;
        }

        final boolean isUndefinedCheck = request == Request.IS_UNDEFINED;
        final Expression expr = undefinedSymbol == lhsSymbol ? rhs : lhs;
        if (expr.getType().isPrimitive()) {
            loadAndDiscard(expr); //throw away lhs, but it still needs to be evaluated for side effects, even if not in scope, as it can be optimistic
            method.load(!isUndefinedCheck);
        } else {
            final Label checkTrue  = new Label("ud_check_true");
            final Label end        = new Label("end");
            loadExpressionAsObject(expr);
            method.loadUndefined(Type.OBJECT);
            method.if_acmpeq(checkTrue);
            method.load(!isUndefinedCheck);
            method._goto(end);
            method.label(checkTrue);
            method.load(isUndefinedCheck);
            method.label(end);
        }

        return true;
    }

    private static boolean isUndefinedSymbol(final Symbol symbol) {
        return symbol != null && "undefined".equals(symbol.getName());
    }

    private static boolean isNullLiteral(final Node node) {
        return node instanceof LiteralNode<?> && ((LiteralNode<?>) node).isNull();
    }

    private boolean nullCheck(final RuntimeNode runtimeNode, final List<Expression> args) {
        final Request request = runtimeNode.getRequest();

        if (!Request.isEQ(request) && !Request.isNE(request)) {
            return false;
        }

        assert args.size() == 2 : "EQ or NE or TYPEOF need two args";

        Expression lhs = args.get(0);
        Expression rhs = args.get(1);

        if (isNullLiteral(lhs)) {
            final Expression tmp = lhs;
            lhs = rhs;
            rhs = tmp;
        }

        if (!isNullLiteral(rhs)) {
            return false;
        }

        if (!lhs.getType().isObject()) {
            return false;
        }

        if(isDeoptimizedExpression(lhs)) {
            // This is actually related to "!lhs.getType().isObject()" above: any expression being deoptimized in
            // the current chain of rest-of compilations used to have a type narrower than Object. We must not
            // perform null check specialization for them, as then we'd no longer be loading aconst_null on stack
            // and thus violate the basic rule of "Thou shalt not alter the stack shape between a deoptimized
            // method and any of its (transitive) rest-ofs."
            // NOTE also that if we had a representation for well-known constants (e.g. null, 0, 1, -1, etc.) in
            // Label$Stack.localLoads then this wouldn't be an issue, as we would never (somewhat ridiculously)
            // allocate a temporary local to hold the result of aconst_null before attempting an optimistic
            // operation.
            return false;
        }

        // this is a null literal check, so if there is implicit coercion
        // involved like {D}x=null, we will fail - this is very rare
        final Label trueLabel  = new Label("trueLabel");
        final Label falseLabel = new Label("falseLabel");
        final Label endLabel   = new Label("end");

        loadExpressionUnbounded(lhs);    //lhs
        final Label popLabel;
        if (!Request.isStrict(request)) {
            method.dup(); //lhs lhs
            popLabel = new Label("pop");
        } else {
            popLabel = null;
        }

        if (Request.isEQ(request)) {
            method.ifnull(!Request.isStrict(request) ? popLabel : trueLabel);
            if (!Request.isStrict(request)) {
                method.loadUndefined(Type.OBJECT);
                method.if_acmpeq(trueLabel);
            }
            method.label(falseLabel);
            method.load(false);
            method._goto(endLabel);
            if (!Request.isStrict(request)) {
                method.label(popLabel);
                method.pop();
            }
            method.label(trueLabel);
            method.load(true);
            method.label(endLabel);
        } else if (Request.isNE(request)) {
            method.ifnull(!Request.isStrict(request) ? popLabel : falseLabel);
            if (!Request.isStrict(request)) {
                method.loadUndefined(Type.OBJECT);
                method.if_acmpeq(falseLabel);
            }
            method.label(trueLabel);
            method.load(true);
            method._goto(endLabel);
            if (!Request.isStrict(request)) {
                method.label(popLabel);
                method.pop();
            }
            method.label(falseLabel);
            method.load(false);
            method.label(endLabel);
        }

        assert runtimeNode.getType().isBoolean();
        method.convert(runtimeNode.getType());

        return true;
    }

    /**
     * Was this expression or any of its subexpressions deoptimized in the current recompilation chain of rest-of methods?
     * @param rootExpr the expression being tested
     * @return true if the expression or any of its subexpressions was deoptimized in the current recompilation chain.
     */
    private boolean isDeoptimizedExpression(final Expression rootExpr) {
        if(!isRestOf()) {
            return false;
        }
        return new Supplier<Boolean>() {
            boolean contains;
            @Override
            public Boolean get() {
                rootExpr.accept(new SimpleNodeVisitor() {
                    @Override
                    public boolean enterFunctionNode(final FunctionNode functionNode) {
                        return false;
                    }
                    @Override
                    public boolean enterDefault(final Node node) {
                        if(!contains && node instanceof Optimistic) {
                            final int pp = ((Optimistic)node).getProgramPoint();
                            contains = isValid(pp) && isContinuationEntryPoint(pp);
                        }
                        return !contains;
                    }
                });
                return contains;
            }
        }.get();
    }

    private void loadRuntimeNode(final RuntimeNode runtimeNode) {
        final List<Expression> args = new ArrayList<>(runtimeNode.getArgs());
        if (nullCheck(runtimeNode, args)) {
           return;
        } else if(undefinedCheck(runtimeNode, args)) {
            return;
        }
        // Revert a false undefined check to a strict equality check
        final RuntimeNode newRuntimeNode;
        final Request request = runtimeNode.getRequest();
        if (Request.isUndefinedCheck(request)) {
            newRuntimeNode = runtimeNode.setRequest(request == Request.IS_UNDEFINED ? Request.EQ_STRICT : Request.NE_STRICT);
        } else {
            newRuntimeNode = runtimeNode;
        }

        for (final Expression arg : args) {
            loadExpression(arg, TypeBounds.OBJECT);
        }

        method.invokestatic(
                CompilerConstants.className(ScriptRuntime.class),
                newRuntimeNode.getRequest().toString(),
                new FunctionSignature(
                    false,
                    false,
                    newRuntimeNode.getType(),
                    args.size()).toString());

        method.convert(newRuntimeNode.getType());
    }

    private void defineCommonSplitMethodParameters() {
        defineSplitMethodParameter(0, CALLEE);
        defineSplitMethodParameter(1, THIS);
        defineSplitMethodParameter(2, SCOPE);
    }

    private void defineSplitMethodParameter(final int slot, final CompilerConstants cc) {
        defineSplitMethodParameter(slot, Type.typeFor(cc.type()));
    }

    private void defineSplitMethodParameter(final int slot, final Type type) {
        method.defineBlockLocalVariable(slot, slot + type.getSlots());
        method.onLocalStore(type, slot);
    }

    private void loadSplitLiteral(final SplitLiteralCreator creator, final List<Splittable.SplitRange> ranges, final Type literalType) {
        assert ranges != null;

        // final Type literalType = Type.typeFor(literalClass);
        final MethodEmitter savedMethod     = method;
        final FunctionNode  currentFunction = lc.getCurrentFunction();

        for (final Splittable.SplitRange splitRange : ranges) {
            unit = lc.pushCompileUnit(splitRange.getCompileUnit());

            assert unit != null;
            final String className = unit.getUnitClassName();
            final String name      = currentFunction.uniqueName(SPLIT_PREFIX.symbolName());
            final Class<?> clazz   = literalType.getTypeClass();
            final String signature = methodDescriptor(clazz, ScriptFunction.class, Object.class, ScriptObject.class, clazz);

            pushMethodEmitter(unit.getClassEmitter().method(EnumSet.of(Flag.PUBLIC, Flag.STATIC), name, signature));

            method.setFunctionNode(currentFunction);
            method.begin();

            defineCommonSplitMethodParameters();
            defineSplitMethodParameter(CompilerConstants.SPLIT_ARRAY_ARG.slot(), literalType);

            // NOTE: when this is no longer needed, SplitIntoFunctions will no longer have to add IS_SPLIT
            // to synthetic functions, and FunctionNode.needsCallee() will no longer need to test for isSplit().
            final int literalSlot = fixScopeSlot(currentFunction, 3);

            lc.enterSplitNode();

            creator.populateRange(method, literalType, literalSlot, splitRange.getLow(), splitRange.getHigh());

            method._return();
            lc.exitSplitNode();
            method.end();
            lc.releaseSlots();
            popMethodEmitter();

            assert method == savedMethod;
            method.loadCompilerConstant(CALLEE).swap();
            method.loadCompilerConstant(THIS).swap();
            method.loadCompilerConstant(SCOPE).swap();
            method.invokestatic(className, name, signature);

            unit = lc.popCompileUnit(unit);
        }
    }

    private int fixScopeSlot(final FunctionNode functionNode, final int extraSlot) {
        // TODO hack to move the scope to the expected slot (needed because split methods reuse the same slots as the root method)
        final int actualScopeSlot = functionNode.compilerConstant(SCOPE).getSlot(SCOPE_TYPE);
        final int defaultScopeSlot = SCOPE.slot();
        int newExtraSlot = extraSlot;
        if (actualScopeSlot != defaultScopeSlot) {
            if (actualScopeSlot == extraSlot) {
                newExtraSlot = extraSlot + 1;
                method.defineBlockLocalVariable(newExtraSlot, newExtraSlot + 1);
                method.load(Type.OBJECT, extraSlot);
                method.storeHidden(Type.OBJECT, newExtraSlot);
            } else {
                method.defineBlockLocalVariable(actualScopeSlot, actualScopeSlot + 1);
            }
            method.load(SCOPE_TYPE, defaultScopeSlot);
            method.storeCompilerConstant(SCOPE);
        }
        return newExtraSlot;
    }

    @Override
    public boolean enterSplitReturn(final SplitReturn splitReturn) {
        if (method.isReachable()) {
            method.loadUndefined(lc.getCurrentFunction().getReturnType())._return();
        }
        return false;
    }

    @Override
    public boolean enterSetSplitState(final SetSplitState setSplitState) {
        if (method.isReachable()) {
            method.setSplitState(setSplitState.getState());
        }
        return false;
    }

    @Override
    public boolean enterSwitchNode(final SwitchNode switchNode) {
        if(!method.isReachable()) {
            return false;
        }
        enterStatement(switchNode);

        final Expression     expression  = switchNode.getExpression();
        final List<CaseNode> cases       = switchNode.getCases();

        if (cases.isEmpty()) {
            // still evaluate expression for side-effects.
            loadAndDiscard(expression);
            return false;
        }

        final CaseNode defaultCase       = switchNode.getDefaultCase();
        final Label    breakLabel        = switchNode.getBreakLabel();
        final int      liveLocalsOnBreak = method.getUsedSlotsWithLiveTemporaries();

        if (defaultCase != null && cases.size() == 1) {
            // default case only
            assert cases.get(0) == defaultCase;
            loadAndDiscard(expression);
            defaultCase.getBody().accept(this);
            method.breakLabel(breakLabel, liveLocalsOnBreak);
            return false;
        }

        // NOTE: it can still change in the tableswitch/lookupswitch case if there's no default case
        // but we need to add a synthetic default case for local variable conversions
        Label defaultLabel = defaultCase != null ? defaultCase.getEntry() : breakLabel;
        final boolean hasSkipConversion = LocalVariableConversion.hasLiveConversion(switchNode);

        if (switchNode.isUniqueInteger()) {
            // Tree for sorting values.
            final TreeMap<Integer, Label> tree = new TreeMap<>();

            // Build up sorted tree.
            for (final CaseNode caseNode : cases) {
                final Node test = caseNode.getTest();

                if (test != null) {
                    final Integer value = (Integer)((LiteralNode<?>)test).getValue();
                    final Label   entry = caseNode.getEntry();

                    // Take first duplicate.
                    if (!tree.containsKey(value)) {
                        tree.put(value, entry);
                    }
                }
            }

            // Copy values and labels to arrays.
            final int       size   = tree.size();
            final Integer[] values = tree.keySet().toArray(new Integer[size]);
            final Label[]   labels = tree.values().toArray(new Label[size]);

            // Discern low, high and range.
            final int lo    = values[0];
            final int hi    = values[size - 1];
            final long range = (long)hi - (long)lo + 1;

            // Find an unused value for default.
            int deflt = Integer.MIN_VALUE;
            for (final int value : values) {
                if (deflt == value) {
                    deflt++;
                } else if (deflt < value) {
                    break;
                }
            }

            // Load switch expression.
            loadExpressionUnbounded(expression);
            final Type type = expression.getType();

            // If expression not int see if we can convert, if not use deflt to trigger default.
            if (!type.isInteger()) {
                method.load(deflt);
                final Class<?> exprClass = type.getTypeClass();
                method.invoke(staticCallNoLookup(ScriptRuntime.class, "switchTagAsInt", int.class, exprClass.isPrimitive()? exprClass : Object.class, int.class));
            }

            if(hasSkipConversion) {
                assert defaultLabel == breakLabel;
                defaultLabel = new Label("switch_skip");
            }
            // TABLESWITCH needs (range + 3) 32-bit values; LOOKUPSWITCH needs ((size * 2) + 2). Choose the one with
            // smaller representation, favor TABLESWITCH when they're equal size.
            if (range + 1 <= (size * 2) && range <= Integer.MAX_VALUE) {
                final Label[] table = new Label[(int)range];
                Arrays.fill(table, defaultLabel);
                for (int i = 0; i < size; i++) {
                    final int value = values[i];
                    table[value - lo] = labels[i];
                }

                method.tableswitch(lo, hi, defaultLabel, table);
            } else {
                final int[] ints = new int[size];
                for (int i = 0; i < size; i++) {
                    ints[i] = values[i];
                }

                method.lookupswitch(defaultLabel, ints, labels);
            }
            // This is a synthetic "default case" used in absence of actual default case, created if we need to apply
            // local variable conversions if neither case is taken.
            if(hasSkipConversion) {
                method.label(defaultLabel);
                method.beforeJoinPoint(switchNode);
                method._goto(breakLabel);
            }
        } else {
            final Symbol tagSymbol = switchNode.getTag();
            // TODO: we could have non-object tag
            final int tagSlot = tagSymbol.getSlot(Type.OBJECT);
            loadExpressionAsObject(expression);
            method.store(tagSymbol, Type.OBJECT);

            for (final CaseNode caseNode : cases) {
                final Expression test = caseNode.getTest();

                if (test != null) {
                    method.load(Type.OBJECT, tagSlot);
                    loadExpressionAsObject(test);
                    method.invoke(ScriptRuntime.EQ_STRICT);
                    method.ifne(caseNode.getEntry());
                }
            }

            if (defaultCase != null) {
                method._goto(defaultLabel);
            } else {
                method.beforeJoinPoint(switchNode);
                method._goto(breakLabel);
            }
        }

        // First case is only reachable through jump
        assert !method.isReachable();

        for (final CaseNode caseNode : cases) {
            final Label fallThroughLabel;
            if(caseNode.getLocalVariableConversion() != null && method.isReachable()) {
                fallThroughLabel = new Label("fallthrough");
                method._goto(fallThroughLabel);
            } else {
                fallThroughLabel = null;
            }
            method.label(caseNode.getEntry());
            method.beforeJoinPoint(caseNode);
            if(fallThroughLabel != null) {
                method.label(fallThroughLabel);
            }
            caseNode.getBody().accept(this);
        }

        method.breakLabel(breakLabel, liveLocalsOnBreak);

        return false;
    }

    @Override
    public boolean enterThrowNode(final ThrowNode throwNode) {
        if(!method.isReachable()) {
            return false;
        }
        enterStatement(throwNode);

        if (throwNode.isSyntheticRethrow()) {
            method.beforeJoinPoint(throwNode);

            //do not wrap whatever this is in an ecma exception, just rethrow it
            final IdentNode exceptionExpr = (IdentNode)throwNode.getExpression();
            final Symbol exceptionSymbol = exceptionExpr.getSymbol();
            method.load(exceptionSymbol, EXCEPTION_TYPE);
            method.checkcast(EXCEPTION_TYPE.getTypeClass());
            method.athrow();
            return false;
        }

        final Source     source     = getCurrentSource();
        final Expression expression = throwNode.getExpression();
        final int        position   = throwNode.position();
        final int        line       = throwNode.getLineNumber();
        final int        column     = source.getColumn(position);

        // NOTE: we first evaluate the expression, and only after it was evaluated do we create the new ECMAException
        // object and then somewhat cumbersomely move it beneath the evaluated expression on the stack. The reason for
        // this is that if expression is optimistic (or contains an optimistic subexpression), we'd potentially access
        // the not-yet-<init>ialized object on the stack from the UnwarrantedOptimismException handler, and bytecode
        // verifier forbids that.
        loadExpressionAsObject(expression);

        method.load(source.getName());
        method.load(line);
        method.load(column);
        method.invoke(ECMAException.CREATE);

        method.beforeJoinPoint(throwNode);
        method.athrow();

        return false;
    }

    private Source getCurrentSource() {
        return lc.getCurrentFunction().getSource();
    }

    @Override
    public boolean enterTryNode(final TryNode tryNode) {
        if(!method.isReachable()) {
            return false;
        }
        enterStatement(tryNode);

        final Block       body        = tryNode.getBody();
        final List<Block> catchBlocks = tryNode.getCatchBlocks();
        final Symbol      vmException = tryNode.getException();
        final Label       entry       = new Label("try");
        final Label       recovery    = new Label("catch");
        final Label       exit        = new Label("end_try");
        final Label       skip        = new Label("skip");

        method.canThrow(recovery);
        // Effect any conversions that might be observed at the entry of the catch node before entering the try node.
        // This is because even the first instruction in the try block must be presumed to be able to transfer control
        // to the catch block. Note that this doesn't kill the original values; in this regard it works a lot like
        // conversions of assignments within the try block.
        method.beforeTry(tryNode, recovery);
        method.label(entry);
        catchLabels.push(recovery);
        try {
            body.accept(this);
        } finally {
            assert catchLabels.peek() == recovery;
            catchLabels.pop();
        }

        method.label(exit);
        final boolean bodyCanThrow = exit.isAfter(entry);
        if(!bodyCanThrow) {
            // The body can't throw an exception; don't even bother emitting the catch handlers, they're all dead code.
            return false;
        }

        method._try(entry, exit, recovery, Throwable.class);

        if (method.isReachable()) {
            method._goto(skip);
        }

        for (final Block inlinedFinally : tryNode.getInlinedFinallies()) {
            TryNode.getLabelledInlinedFinallyBlock(inlinedFinally).accept(this);
            // All inlined finallies end with a jump or a return
            assert !method.isReachable();
        }


        method._catch(recovery);
        method.store(vmException, EXCEPTION_TYPE);

        final int catchBlockCount = catchBlocks.size();
        final Label afterCatch = new Label("after_catch");
        for (int i = 0; i < catchBlockCount; i++) {
            assert method.isReachable();
            final Block catchBlock = catchBlocks.get(i);

            // Because of the peculiarities of the flow control, we need to use an explicit push/enterBlock/leaveBlock
            // here.
            lc.push(catchBlock);
            enterBlock(catchBlock);

            final CatchNode  catchNode          = (CatchNode)catchBlocks.get(i).getStatements().get(0);
            final IdentNode  exception          = catchNode.getException();
            final Expression exceptionCondition = catchNode.getExceptionCondition();
            final Block      catchBody          = catchNode.getBody();

            new Store<IdentNode>(exception) {
                @Override
                protected void storeNonDiscard() {
                    // This expression is neither part of a discard, nor needs to be left on the stack after it was
                    // stored, so we override storeNonDiscard to be a no-op.
                }

                @Override
                protected void evaluate() {
                    if (catchNode.isSyntheticRethrow()) {
                        method.load(vmException, EXCEPTION_TYPE);
                        return;
                    }
                    /*
                     * If caught object is an instance of ECMAException, then
                     * bind obj.thrown to the script catch var. Or else bind the
                     * caught object itself to the script catch var.
                     */
                    final Label notEcmaException = new Label("no_ecma_exception");
                    method.load(vmException, EXCEPTION_TYPE).dup()._instanceof(ECMAException.class).ifeq(notEcmaException);
                    method.checkcast(ECMAException.class); //TODO is this necessary?
                    method.getField(ECMAException.THROWN);
                    method.label(notEcmaException);
                }
            }.store();

            final boolean isConditionalCatch = exceptionCondition != null;
            final Label nextCatch;
            if (isConditionalCatch) {
                loadExpressionAsBoolean(exceptionCondition);
                nextCatch = new Label("next_catch");
                nextCatch.markAsBreakTarget();
                method.ifeq(nextCatch);
            } else {
                nextCatch = null;
            }

            catchBody.accept(this);
            leaveBlock(catchBlock);
            lc.pop(catchBlock);
            if(nextCatch != null) {
                if(method.isReachable()) {
                    method._goto(afterCatch);
                }
                method.breakLabel(nextCatch, lc.getUsedSlotCount());
            }
        }

        // afterCatch could be the same as skip, except that we need to establish that the vmException is dead.
        method.label(afterCatch);
        if(method.isReachable()) {
            method.markDeadLocalVariable(vmException);
        }
        method.label(skip);

        // Finally body is always inlined elsewhere so it doesn't need to be emitted
        assert tryNode.getFinallyBody() == null;

        return false;
    }

    @Override
    public boolean enterVarNode(final VarNode varNode) {
        if(!method.isReachable()) {
            return false;
        }
        final Expression init = varNode.getInit();
        final IdentNode identNode = varNode.getName();
        final Symbol identSymbol = identNode.getSymbol();
        assert identSymbol != null : "variable node " + varNode + " requires a name with a symbol";
        final boolean needsScope = identSymbol.isScope();

        if (init == null) {
            if (needsScope && varNode.isBlockScoped()) {
                // block scoped variables need a DECLARE flag to signal end of temporal dead zone (TDZ)
                method.loadCompilerConstant(SCOPE);
                method.loadUndefined(Type.OBJECT);
                final int flags = getScopeCallSiteFlags(identSymbol) | (varNode.isBlockScoped() ? CALLSITE_DECLARE : 0);
                assert isFastScope(identSymbol);
                storeFastScopeVar(identSymbol, flags);
            }
            return false;
        }

        enterStatement(varNode);
        assert method != null;

        if (needsScope) {
            method.loadCompilerConstant(SCOPE);
        }

        if (needsScope) {
            loadExpressionUnbounded(init);
            // block scoped variables need a DECLARE flag to signal end of temporal dead zone (TDZ)
            final int flags = getScopeCallSiteFlags(identSymbol) | (varNode.isBlockScoped() ? CALLSITE_DECLARE : 0);
            if (isFastScope(identSymbol)) {
                storeFastScopeVar(identSymbol, flags);
            } else {
                method.dynamicSet(identNode.getName(), flags, false);
            }
        } else {
            final Type identType = identNode.getType();
            if(identType == Type.UNDEFINED) {
                // The initializer is either itself undefined (explicit assignment of undefined to undefined),
                // or the left hand side is a dead variable.
                assert init.getType() == Type.UNDEFINED || identNode.getSymbol().slotCount() == 0;
                loadAndDiscard(init);
                return false;
            }
            loadExpressionAsType(init, identType);
            storeIdentWithCatchConversion(identNode, identType);
        }

        return false;
    }

    private void storeIdentWithCatchConversion(final IdentNode identNode, final Type type) {
        // Assignments happening in try/catch blocks need to ensure that they also store a possibly wider typed value
        // that will be live at the exit from the try block
        final LocalVariableConversion conversion = identNode.getLocalVariableConversion();
        final Symbol symbol = identNode.getSymbol();
        if(conversion != null && conversion.isLive()) {
            assert symbol == conversion.getSymbol();
            assert symbol.isBytecodeLocal();
            // Only a single conversion from the target type to the join type is expected.
            assert conversion.getNext() == null;
            assert conversion.getFrom() == type;
            // We must propagate potential type change to the catch block
            final Label catchLabel = catchLabels.peek();
            assert catchLabel != METHOD_BOUNDARY; // ident conversion only exists in try blocks
            assert catchLabel.isReachable();
            final Type joinType = conversion.getTo();
            final Label.Stack catchStack = catchLabel.getStack();
            final int joinSlot = symbol.getSlot(joinType);
            // With nested try/catch blocks (incl. synthetic ones for finally), we can have a supposed conversion for
            // the exception symbol in the nested catch, but it isn't live in the outer catch block, so prevent doing
            // conversions for it. E.g. in "try { try { ... } catch(e) { e = 1; } } catch(e2) { ... }", we must not
            // introduce an I->O conversion on "e = 1" assignment as "e" is not live in "catch(e2)".
            if(catchStack.getUsedSlotsWithLiveTemporaries() > joinSlot) {
                method.dup();
                method.convert(joinType);
                method.store(symbol, joinType);
                catchLabel.getStack().onLocalStore(joinType, joinSlot, true);
                method.canThrow(catchLabel);
                // Store but keep the previous store live too.
                method.store(symbol, type, false);
                return;
            }
        }

        method.store(symbol, type, true);
    }

    @Override
    public boolean enterWhileNode(final WhileNode whileNode) {
        if(!method.isReachable()) {
            return false;
        }
        if(whileNode.isDoWhile()) {
            enterDoWhile(whileNode);
        } else {
            enterStatement(whileNode);
            enterForOrWhile(whileNode, null);
        }
        return false;
    }

    private void enterForOrWhile(final LoopNode loopNode, final JoinPredecessorExpression modify) {
        // NOTE: the usual pattern for compiling test-first loops is "GOTO test; body; test; IFNE body". We use the less
        // conventional "test; IFEQ break; body; GOTO test; break;". It has one extra unconditional GOTO in each repeat
        // of the loop, but it's not a problem for modern JIT compilers. We do this because our local variable type
        // tracking is unfortunately not really prepared for out-of-order execution, e.g. compiling the following
        // contrived but legal JavaScript code snippet would fail because the test changes the type of "i" from object
        // to double: var i = {valueOf: function() { return 1} }; while(--i >= 0) { ... }
        // Instead of adding more complexity to the local variable type tracking, we instead choose to emit this
        // different code shape.
        final int liveLocalsOnBreak = method.getUsedSlotsWithLiveTemporaries();
        final JoinPredecessorExpression test = loopNode.getTest();
        if(Expression.isAlwaysFalse(test)) {
            loadAndDiscard(test);
            return;
        }

        method.beforeJoinPoint(loopNode);

        final Label continueLabel = loopNode.getContinueLabel();
        final Label repeatLabel = modify != null ? new Label("for_repeat") : continueLabel;
        method.label(repeatLabel);
        final int liveLocalsOnContinue = method.getUsedSlotsWithLiveTemporaries();

        final Block   body                  = loopNode.getBody();
        final Label   breakLabel            = loopNode.getBreakLabel();
        final boolean testHasLiveConversion = test != null && LocalVariableConversion.hasLiveConversion(test);

        if(Expression.isAlwaysTrue(test)) {
            if(test != null) {
                loadAndDiscard(test);
                if(testHasLiveConversion) {
                    method.beforeJoinPoint(test);
                }
            }
        } else if (test != null) {
            if (testHasLiveConversion) {
                emitBranch(test.getExpression(), body.getEntryLabel(), true);
                method.beforeJoinPoint(test);
                method._goto(breakLabel);
            } else {
                emitBranch(test.getExpression(), breakLabel, false);
            }
        }

        body.accept(this);
        if(repeatLabel != continueLabel) {
            emitContinueLabel(continueLabel, liveLocalsOnContinue);
        }

        if (loopNode.hasPerIterationScope() && lc.getCurrentBlock().needsScope()) {
            // ES6 for loops with LET init need a new scope for each iteration. We just create a shallow copy here.
            method.loadCompilerConstant(SCOPE);
            method.invoke(virtualCallNoLookup(ScriptObject.class, "copy", ScriptObject.class));
            method.storeCompilerConstant(SCOPE);
        }

        if(method.isReachable()) {
            if(modify != null) {
                lineNumber(loopNode);
                loadAndDiscard(modify);
                method.beforeJoinPoint(modify);
            }
            method._goto(repeatLabel);
        }

        method.breakLabel(breakLabel, liveLocalsOnBreak);
    }

    private void emitContinueLabel(final Label continueLabel, final int liveLocals) {
        final boolean reachable = method.isReachable();
        method.breakLabel(continueLabel, liveLocals);
        // If we reach here only through a continue statement (e.g. body does not exit normally) then the
        // continueLabel can have extra non-temp symbols (e.g. exception from a try/catch contained in the body). We
        // must make sure those are thrown away.
        if(!reachable) {
            method.undefineLocalVariables(lc.getUsedSlotCount(), false);
        }
    }

    private void enterDoWhile(final WhileNode whileNode) {
        final int liveLocalsOnContinueOrBreak = method.getUsedSlotsWithLiveTemporaries();
        method.beforeJoinPoint(whileNode);

        final Block body = whileNode.getBody();
        body.accept(this);

        emitContinueLabel(whileNode.getContinueLabel(), liveLocalsOnContinueOrBreak);
        if(method.isReachable()) {
            lineNumber(whileNode);
            final JoinPredecessorExpression test = whileNode.getTest();
            final Label bodyEntryLabel = body.getEntryLabel();
            final boolean testHasLiveConversion = LocalVariableConversion.hasLiveConversion(test);
            if(Expression.isAlwaysFalse(test)) {
                loadAndDiscard(test);
                if(testHasLiveConversion) {
                    method.beforeJoinPoint(test);
                }
            } else if(testHasLiveConversion) {
                // If we have conversions after the test in do-while, they need to be effected on both branches.
                final Label beforeExit = new Label("do_while_preexit");
                emitBranch(test.getExpression(), beforeExit, false);
                method.beforeJoinPoint(test);
                method._goto(bodyEntryLabel);
                method.label(beforeExit);
                method.beforeJoinPoint(test);
            } else {
                emitBranch(test.getExpression(), bodyEntryLabel, true);
            }
        }
        method.breakLabel(whileNode.getBreakLabel(), liveLocalsOnContinueOrBreak);
    }


    @Override
    public boolean enterWithNode(final WithNode withNode) {
        if(!method.isReachable()) {
            return false;
        }
        enterStatement(withNode);
        final Expression expression = withNode.getExpression();
        final Block      body       = withNode.getBody();

        // It is possible to have a "pathological" case where the with block does not reference *any* identifiers. It's
        // pointless, but legal. In that case, if nothing else in the method forced the assignment of a slot to the
        // scope object, its' possible that it won't have a slot assigned. In this case we'll only evaluate expression
        // for its side effect and visit the body, and not bother opening and closing a WithObject.
        final boolean hasScope = method.hasScope();

        if (hasScope) {
            method.loadCompilerConstant(SCOPE);
        }

        loadExpressionAsObject(expression);

        final Label tryLabel;
        if (hasScope) {
            // Construct a WithObject if we have a scope
            method.invoke(ScriptRuntime.OPEN_WITH);
            method.storeCompilerConstant(SCOPE);
            tryLabel = new Label("with_try");
            method.label(tryLabel);
        } else {
            // We just loaded the expression for its side effect and to check
            // for null or undefined value.
            globalCheckObjectCoercible();
            tryLabel = null;
        }

        // Always process body
        body.accept(this);

        if (hasScope) {
            // Ensure we always close the WithObject
            final Label endLabel   = new Label("with_end");
            final Label catchLabel = new Label("with_catch");
            final Label exitLabel  = new Label("with_exit");

            method.label(endLabel);
            // Somewhat conservatively presume that if the body is not empty, it can throw an exception. In any case,
            // we must prevent trying to emit a try-catch for empty range, as it causes a verification error.
            final boolean bodyCanThrow = endLabel.isAfter(tryLabel);
            if(bodyCanThrow) {
                method._try(tryLabel, endLabel, catchLabel);
            }

            final boolean reachable = method.isReachable();
            if(reachable) {
                popScope();
                if(bodyCanThrow) {
                    method._goto(exitLabel);
                }
            }

            if(bodyCanThrow) {
                method._catch(catchLabel);
                popScopeException();
                method.athrow();
                if(reachable) {
                    method.label(exitLabel);
                }
            }
        }
        return false;
    }

    private void loadADD(final UnaryNode unaryNode, final TypeBounds resultBounds) {
        loadExpression(unaryNode.getExpression(), resultBounds.booleanToInt().notWiderThan(Type.NUMBER));
        if(method.peekType() == Type.BOOLEAN) {
            // It's a no-op in bytecode, but we must make sure it is treated as an int for purposes of type signatures
            method.convert(Type.INT);
        }
    }

    private void loadBIT_NOT(final UnaryNode unaryNode) {
        loadExpression(unaryNode.getExpression(), TypeBounds.INT).load(-1).xor();
    }

    private void loadDECINC(final UnaryNode unaryNode) {
        final Expression operand     = unaryNode.getExpression();
        final Type       type        = unaryNode.getType();
        final TypeBounds typeBounds  = new TypeBounds(type, Type.NUMBER);
        final TokenType  tokenType   = unaryNode.tokenType();
        final boolean    isPostfix   = tokenType == TokenType.DECPOSTFIX || tokenType == TokenType.INCPOSTFIX;
        final boolean    isIncrement = tokenType == TokenType.INCPREFIX || tokenType == TokenType.INCPOSTFIX;

        assert !type.isObject();

        new SelfModifyingStore<UnaryNode>(unaryNode, operand) {

            private void loadRhs() {
                loadExpression(operand, typeBounds, true);
            }

            @Override
            protected void evaluate() {
                if(isPostfix) {
                    loadRhs();
                } else {
                    new OptimisticOperation(unaryNode, typeBounds) {
                        @Override
                        void loadStack() {
                            loadRhs();
                            loadMinusOne();
                        }
                        @Override
                        void consumeStack() {
                            doDecInc(getProgramPoint());
                        }
                    }.emit(getOptimisticIgnoreCountForSelfModifyingExpression(operand));
                }
            }

            @Override
            protected void storeNonDiscard() {
                super.storeNonDiscard();
                if (isPostfix) {
                    new OptimisticOperation(unaryNode, typeBounds) {
                        @Override
                        void loadStack() {
                            loadMinusOne();
                        }
                        @Override
                        void consumeStack() {
                            doDecInc(getProgramPoint());
                        }
                    }.emit(1); // 1 for non-incremented result on the top of the stack pushed in evaluate()
                }
            }

            private void loadMinusOne() {
                if (type.isInteger()) {
                    method.load(isIncrement ? 1 : -1);
                } else {
                    method.load(isIncrement ? 1.0 : -1.0);
                }
            }

            private void doDecInc(final int programPoint) {
                method.add(programPoint);
            }
        }.store();
    }

    private static int getOptimisticIgnoreCountForSelfModifyingExpression(final Expression target) {
        return target instanceof AccessNode ? 1 : target instanceof IndexNode ? 2 : 0;
    }

    private void loadAndDiscard(final Expression expr) {
        // TODO: move checks for discarding to actual expression load code (e.g. as we do with void). That way we might
        // be able to eliminate even more checks.
        if(expr instanceof PrimitiveLiteralNode | isLocalVariable(expr)) {
            assert !lc.isCurrentDiscard(expr);
            // Don't bother evaluating expressions without side effects. Typical usage is "void 0" for reliably generating
            // undefined.
            return;
        }

        lc.pushDiscard(expr);
        loadExpression(expr, TypeBounds.UNBOUNDED);
        if (lc.popDiscardIfCurrent(expr)) {
            assert !expr.isAssignment();
            // NOTE: if we had a way to load with type void, we could avoid popping
            method.pop();
        }
    }

    /**
     * Loads the expression with the specified type bounds, but if the parent expression is the current discard,
     * then instead loads and discards the expression.
     * @param parent the parent expression that's tested for being the current discard
     * @param expr the expression that's either normally loaded or discard-loaded
     * @param resultBounds result bounds for when loading the expression normally
     */
    private void loadMaybeDiscard(final Expression parent, final Expression expr, final TypeBounds resultBounds) {
        loadMaybeDiscard(lc.popDiscardIfCurrent(parent), expr, resultBounds);
    }

    /**
     * Loads the expression with the specified type bounds, or loads and discards the expression, depending on the
     * value of the discard flag. Useful as a helper for expressions with control flow where you often can't combine
     * testing for being the current discard and loading the subexpressions.
     * @param discard if true, the expression is loaded and discarded
     * @param expr the expression that's either normally loaded or discard-loaded
     * @param resultBounds result bounds for when loading the expression normally
     */
    private void loadMaybeDiscard(final boolean discard, final Expression expr, final TypeBounds resultBounds) {
        if (discard) {
            loadAndDiscard(expr);
        } else {
            loadExpression(expr, resultBounds);
        }
    }

    private void loadNEW(final UnaryNode unaryNode) {
        final CallNode callNode = (CallNode)unaryNode.getExpression();
        final List<Expression> args   = callNode.getArgs();

        final Expression func = callNode.getFunction();
        // Load function reference.
        loadExpressionAsObject(func); // must detect type error

        method.dynamicNew(1 + loadArgs(args), getCallSiteFlags(), func.toString(false));
    }

    private void loadNOT(final UnaryNode unaryNode) {
        final Expression expr = unaryNode.getExpression();
        if(expr instanceof UnaryNode && expr.isTokenType(TokenType.NOT)) {
            // !!x is idiomatic boolean cast in JavaScript
            loadExpressionAsBoolean(((UnaryNode)expr).getExpression());
        } else {
            final Label trueLabel  = new Label("true");
            final Label afterLabel = new Label("after");

            emitBranch(expr, trueLabel, true);
            method.load(true);
            method._goto(afterLabel);
            method.label(trueLabel);
            method.load(false);
            method.label(afterLabel);
        }
    }

    private void loadSUB(final UnaryNode unaryNode, final TypeBounds resultBounds) {
        final Type type = unaryNode.getType();
        assert type.isNumeric();
        final TypeBounds numericBounds = resultBounds.booleanToInt();
        new OptimisticOperation(unaryNode, numericBounds) {
            @Override
            void loadStack() {
                final Expression expr = unaryNode.getExpression();
                loadExpression(expr, numericBounds.notWiderThan(Type.NUMBER));
            }
            @Override
            void consumeStack() {
                // Must do an explicit conversion to the operation's type when it's double so that we correctly handle
                // negation of an int 0 to a double -0. With this, we get the correct negation of a local variable after
                // it deoptimized, e.g. "iload_2; i2d; dneg". Without this, we get "iload_2; ineg; i2d".
                if(type.isNumber()) {
                    method.convert(type);
                }
                method.neg(getProgramPoint());
            }
        }.emit();
    }

    public void loadVOID(final UnaryNode unaryNode, final TypeBounds resultBounds) {
        loadAndDiscard(unaryNode.getExpression());
        if (!lc.popDiscardIfCurrent(unaryNode)) {
            method.loadUndefined(resultBounds.widest);
        }
    }

    public void loadADD(final BinaryNode binaryNode, final TypeBounds resultBounds) {
        new OptimisticOperation(binaryNode, resultBounds) {
            @Override
            void loadStack() {
                final TypeBounds operandBounds;
                final boolean isOptimistic = isValid(getProgramPoint());
                boolean forceConversionSeparation = false;
                if(isOptimistic) {
                    operandBounds = new TypeBounds(binaryNode.getType(), Type.OBJECT);
                } else {
                    // Non-optimistic, non-FP +. Allow it to overflow.
                    final Type widestOperationType = binaryNode.getWidestOperationType();
                    operandBounds = new TypeBounds(Type.narrowest(binaryNode.getWidestOperandType(), resultBounds.widest), widestOperationType);
                    forceConversionSeparation = widestOperationType.narrowerThan(resultBounds.widest);
                }
                loadBinaryOperands(binaryNode.lhs(), binaryNode.rhs(), operandBounds, false, forceConversionSeparation);
            }

            @Override
            void consumeStack() {
                method.add(getProgramPoint());
            }
        }.emit();
    }

    private void loadAND_OR(final BinaryNode binaryNode, final TypeBounds resultBounds, final boolean isAnd) {
        final Type narrowestOperandType = Type.widestReturnType(binaryNode.lhs().getType(), binaryNode.rhs().getType());

        final boolean isCurrentDiscard = lc.popDiscardIfCurrent(binaryNode);

        final Label skip = new Label("skip");
        if(narrowestOperandType == Type.BOOLEAN) {
            // optimize all-boolean logical expressions
            final Label onTrue = new Label("andor_true");
            emitBranch(binaryNode, onTrue, true);
            if (isCurrentDiscard) {
                method.label(onTrue);
            } else {
                method.load(false);
                method._goto(skip);
                method.label(onTrue);
                method.load(true);
                method.label(skip);
            }
            return;
        }

        final TypeBounds outBounds = resultBounds.notNarrowerThan(narrowestOperandType);
        final JoinPredecessorExpression lhs = (JoinPredecessorExpression)binaryNode.lhs();
        final boolean lhsConvert = LocalVariableConversion.hasLiveConversion(lhs);
        final Label evalRhs = lhsConvert ? new Label("eval_rhs") : null;

        loadExpression(lhs, outBounds);
        if (!isCurrentDiscard) {
            method.dup();
        }
        method.convert(Type.BOOLEAN);
        if (isAnd) {
            if(lhsConvert) {
                method.ifne(evalRhs);
            } else {
                method.ifeq(skip);
            }
        } else if(lhsConvert) {
            method.ifeq(evalRhs);
        } else {
            method.ifne(skip);
        }

        if(lhsConvert) {
            method.beforeJoinPoint(lhs);
            method._goto(skip);
            method.label(evalRhs);
        }

        if (!isCurrentDiscard) {
            method.pop();
        }
        final JoinPredecessorExpression rhs = (JoinPredecessorExpression)binaryNode.rhs();
        loadMaybeDiscard(isCurrentDiscard, rhs, outBounds);
        method.beforeJoinPoint(rhs);
        method.label(skip);
    }

    private static boolean isLocalVariable(final Expression lhs) {
        return lhs instanceof IdentNode && isLocalVariable((IdentNode)lhs);
    }

    private static boolean isLocalVariable(final IdentNode lhs) {
        return lhs.getSymbol().isBytecodeLocal();
    }

    // NOTE: does not use resultBounds as the assignment is driven by the type of the RHS
    private void loadASSIGN(final BinaryNode binaryNode) {
        final Expression lhs = binaryNode.lhs();
        final Expression rhs = binaryNode.rhs();

        final Type rhsType = rhs.getType();
        // Detect dead assignments
        if(lhs instanceof IdentNode) {
            final Symbol symbol = ((IdentNode)lhs).getSymbol();
            if(!symbol.isScope() && !symbol.hasSlotFor(rhsType) && lc.popDiscardIfCurrent(binaryNode)) {
                loadAndDiscard(rhs);
                method.markDeadLocalVariable(symbol);
                return;
            }
        }

        new Store<BinaryNode>(binaryNode, lhs) {
            @Override
            protected void evaluate() {
                // NOTE: we're loading with "at least as wide as" so optimistic operations on the right hand side
                // remain optimistic, and then explicitly convert to the required type if needed.
                loadExpressionAsType(rhs, rhsType);
            }
        }.store();
    }

    /**
     * Binary self-assignment that can be optimistic: +=, -=, *=, and /=.
     */
    private abstract class BinaryOptimisticSelfAssignment extends SelfModifyingStore<BinaryNode> {

        /**
         * Constructor
         *
         * @param node the assign op node
         */
        BinaryOptimisticSelfAssignment(final BinaryNode node) {
            super(node, node.lhs());
        }

        protected abstract void op(OptimisticOperation oo);

        @Override
        protected void evaluate() {
            final Expression lhs = assignNode.lhs();
            final Expression rhs = assignNode.rhs();
            final Type widestOperationType = assignNode.getWidestOperationType();
            final TypeBounds bounds = new TypeBounds(assignNode.getType(), widestOperationType);
            new OptimisticOperation(assignNode, bounds) {
                @Override
                void loadStack() {
                    final boolean forceConversionSeparation;
                    if (isValid(getProgramPoint()) || widestOperationType == Type.NUMBER) {
                        forceConversionSeparation = false;
                    } else {
                        final Type operandType = Type.widest(booleanToInt(objectToNumber(lhs.getType())), booleanToInt(objectToNumber(rhs.getType())));
                        forceConversionSeparation = operandType.narrowerThan(widestOperationType);
                    }
                    loadBinaryOperands(lhs, rhs, bounds, true, forceConversionSeparation);
                }
                @Override
                void consumeStack() {
                    op(this);
                }
            }.emit(getOptimisticIgnoreCountForSelfModifyingExpression(lhs));
            method.convert(assignNode.getType());
        }
    }

    /**
     * Non-optimistic binary self-assignment operation. Basically, everything except +=, -=, *=, and /=.
     */
    private abstract class BinarySelfAssignment extends SelfModifyingStore<BinaryNode> {
        BinarySelfAssignment(final BinaryNode node) {
            super(node, node.lhs());
        }

        protected abstract void op();

        @Override
        protected void evaluate() {
            loadBinaryOperands(assignNode.lhs(), assignNode.rhs(), TypeBounds.UNBOUNDED.notWiderThan(assignNode.getWidestOperandType()), true, false);
            op();
        }
    }

    private void loadASSIGN_ADD(final BinaryNode binaryNode) {
        new BinaryOptimisticSelfAssignment(binaryNode) {
            @Override
            protected void op(final OptimisticOperation oo) {
                assert !(binaryNode.getType().isObject() && oo.isOptimistic);
                method.add(oo.getProgramPoint());
            }
        }.store();
    }

    private void loadASSIGN_BIT_AND(final BinaryNode binaryNode) {
        new BinarySelfAssignment(binaryNode) {
            @Override
            protected void op() {
                method.and();
            }
        }.store();
    }

    private void loadASSIGN_BIT_OR(final BinaryNode binaryNode) {
        new BinarySelfAssignment(binaryNode) {
            @Override
            protected void op() {
                method.or();
            }
        }.store();
    }

    private void loadASSIGN_BIT_XOR(final BinaryNode binaryNode) {
        new BinarySelfAssignment(binaryNode) {
            @Override
            protected void op() {
                method.xor();
            }
        }.store();
    }

    private void loadASSIGN_DIV(final BinaryNode binaryNode) {
        new BinaryOptimisticSelfAssignment(binaryNode) {
            @Override
            protected void op(final OptimisticOperation oo) {
                method.div(oo.getProgramPoint());
            }
        }.store();
    }

    private void loadASSIGN_MOD(final BinaryNode binaryNode) {
        new BinaryOptimisticSelfAssignment(binaryNode) {
            @Override
            protected void op(final OptimisticOperation oo) {
                method.rem(oo.getProgramPoint());
            }
        }.store();
    }

    private void loadASSIGN_MUL(final BinaryNode binaryNode) {
        new BinaryOptimisticSelfAssignment(binaryNode) {
            @Override
            protected void op(final OptimisticOperation oo) {
                method.mul(oo.getProgramPoint());
            }
        }.store();
    }

    private void loadASSIGN_SAR(final BinaryNode binaryNode) {
        new BinarySelfAssignment(binaryNode) {
            @Override
            protected void op() {
                method.sar();
            }
        }.store();
    }

    private void loadASSIGN_SHL(final BinaryNode binaryNode) {
        new BinarySelfAssignment(binaryNode) {
            @Override
            protected void op() {
                method.shl();
            }
        }.store();
    }

    private void loadASSIGN_SHR(final BinaryNode binaryNode) {
        new SelfModifyingStore<BinaryNode>(binaryNode, binaryNode.lhs()) {
            @Override
            protected void evaluate() {
                new OptimisticOperation(assignNode, new TypeBounds(Type.INT, Type.NUMBER)) {
                    @Override
                    void loadStack() {
                        assert assignNode.getWidestOperandType() == Type.INT;
                        if (isRhsZero(binaryNode)) {
                            loadExpression(binaryNode.lhs(), TypeBounds.INT, true);
                        } else {
                            loadBinaryOperands(binaryNode.lhs(), binaryNode.rhs(), TypeBounds.INT, true, false);
                            method.shr();
                        }
                    }

                    @Override
                    void consumeStack() {
                        if (isOptimistic(binaryNode)) {
                            toUint32Optimistic(binaryNode.getProgramPoint());
                        } else {
                            toUint32Double();
                        }
                    }
                }.emit(getOptimisticIgnoreCountForSelfModifyingExpression(binaryNode.lhs()));
                method.convert(assignNode.getType());
            }
        }.store();
    }

    private void doSHR(final BinaryNode binaryNode) {
        new OptimisticOperation(binaryNode, new TypeBounds(Type.INT, Type.NUMBER)) {
            @Override
            void loadStack() {
                if (isRhsZero(binaryNode)) {
                    loadExpressionAsType(binaryNode.lhs(), Type.INT);
                } else {
                    loadBinaryOperands(binaryNode);
                    method.shr();
                }
            }

            @Override
            void consumeStack() {
                if (isOptimistic(binaryNode)) {
                    toUint32Optimistic(binaryNode.getProgramPoint());
                } else {
                    toUint32Double();
                }
            }
        }.emit();

    }

    private void toUint32Optimistic(final int programPoint) {
        method.load(programPoint);
        JSType.TO_UINT32_OPTIMISTIC.invoke(method);
    }

    private void toUint32Double() {
        JSType.TO_UINT32_DOUBLE.invoke(method);
    }

    private void loadASSIGN_SUB(final BinaryNode binaryNode) {
        new BinaryOptimisticSelfAssignment(binaryNode) {
            @Override
            protected void op(final OptimisticOperation oo) {
                method.sub(oo.getProgramPoint());
            }
        }.store();
    }

    /**
     * Helper class for binary arithmetic ops
     */
    private abstract class BinaryArith {
        protected abstract void op(int programPoint);

        protected void evaluate(final BinaryNode node, final TypeBounds resultBounds) {
            final TypeBounds numericBounds = resultBounds.booleanToInt().objectToNumber();
            new OptimisticOperation(node, numericBounds) {
                @Override
                void loadStack() {
                    final TypeBounds operandBounds;
                    boolean forceConversionSeparation = false;
                    if(numericBounds.narrowest == Type.NUMBER) {
                        // Result should be double always. Propagate it into the operands so we don't have lots of I2D
                        // and L2D after operand evaluation.
                        assert numericBounds.widest == Type.NUMBER;
                        operandBounds = numericBounds;
                    } else {
                        final boolean isOptimistic = isValid(getProgramPoint());
                        if(isOptimistic || node.isTokenType(TokenType.DIV) || node.isTokenType(TokenType.MOD)) {
                            operandBounds = new TypeBounds(node.getType(), Type.NUMBER);
                        } else {
                            // Non-optimistic, non-FP subtraction or multiplication. Allow them to overflow.
                            operandBounds = new TypeBounds(Type.narrowest(node.getWidestOperandType(),
                                    numericBounds.widest), Type.NUMBER);
                            forceConversionSeparation = true;
                        }
                    }
                    loadBinaryOperands(node.lhs(), node.rhs(), operandBounds, false, forceConversionSeparation);
                }

                @Override
                void consumeStack() {
                    op(getProgramPoint());
                }
            }.emit();
        }
    }

    private void loadBIT_AND(final BinaryNode binaryNode) {
        loadBinaryOperands(binaryNode);
        method.and();
    }

    private void loadBIT_OR(final BinaryNode binaryNode) {
        // Optimize x|0 to (int)x
        if (isRhsZero(binaryNode)) {
            loadExpressionAsType(binaryNode.lhs(), Type.INT);
        } else {
            loadBinaryOperands(binaryNode);
            method.or();
        }
    }

    private static boolean isRhsZero(final BinaryNode binaryNode) {
        final Expression rhs = binaryNode.rhs();
        return rhs instanceof LiteralNode && INT_ZERO.equals(((LiteralNode<?>)rhs).getValue());
    }

    private void loadBIT_XOR(final BinaryNode binaryNode) {
        loadBinaryOperands(binaryNode);
        method.xor();
    }

    private void loadCOMMARIGHT(final BinaryNode binaryNode, final TypeBounds resultBounds) {
        loadAndDiscard(binaryNode.lhs());
        loadMaybeDiscard(binaryNode, binaryNode.rhs(), resultBounds);
    }

    private void loadCOMMALEFT(final BinaryNode binaryNode, final TypeBounds resultBounds) {
        loadMaybeDiscard(binaryNode, binaryNode.lhs(), resultBounds);
        loadAndDiscard(binaryNode.rhs());
    }

    private void loadDIV(final BinaryNode binaryNode, final TypeBounds resultBounds) {
        new BinaryArith() {
            @Override
            protected void op(final int programPoint) {
                method.div(programPoint);
            }
        }.evaluate(binaryNode, resultBounds);
    }

    private void loadCmp(final BinaryNode binaryNode, final Condition cond) {
        loadComparisonOperands(binaryNode);

        final Label trueLabel  = new Label("trueLabel");
        final Label afterLabel = new Label("skip");

        method.conditionalJump(cond, trueLabel);

        method.load(Boolean.FALSE);
        method._goto(afterLabel);
        method.label(trueLabel);
        method.load(Boolean.TRUE);
        method.label(afterLabel);
    }

    private void loadMOD(final BinaryNode binaryNode, final TypeBounds resultBounds) {
        new BinaryArith() {
            @Override
            protected void op(final int programPoint) {
                method.rem(programPoint);
            }
        }.evaluate(binaryNode, resultBounds);
    }

    private void loadMUL(final BinaryNode binaryNode, final TypeBounds resultBounds) {
        new BinaryArith() {
            @Override
            protected void op(final int programPoint) {
                method.mul(programPoint);
            }
        }.evaluate(binaryNode, resultBounds);
    }

    private void loadSAR(final BinaryNode binaryNode) {
        loadBinaryOperands(binaryNode);
        method.sar();
    }

    private void loadSHL(final BinaryNode binaryNode) {
        loadBinaryOperands(binaryNode);
        method.shl();
    }

    private void loadSHR(final BinaryNode binaryNode) {
        doSHR(binaryNode);
    }

    private void loadSUB(final BinaryNode binaryNode, final TypeBounds resultBounds) {
        new BinaryArith() {
            @Override
            protected void op(final int programPoint) {
                method.sub(programPoint);
            }
        }.evaluate(binaryNode, resultBounds);
    }

    @Override
    public boolean enterLabelNode(final LabelNode labelNode) {
        labeledBlockBreakLiveLocals.push(lc.getUsedSlotCount());
        return true;
    }

    @Override
    protected boolean enterDefault(final Node node) {
        throw new AssertionError("Code generator entered node of type " + node.getClass().getName());
    }

    private void loadTernaryNode(final TernaryNode ternaryNode, final TypeBounds resultBounds) {
        final Expression test = ternaryNode.getTest();
        final JoinPredecessorExpression trueExpr  = ternaryNode.getTrueExpression();
        final JoinPredecessorExpression falseExpr = ternaryNode.getFalseExpression();

        final Label falseLabel = new Label("ternary_false");
        final Label exitLabel  = new Label("ternary_exit");

        final Type outNarrowest = Type.narrowest(resultBounds.widest, Type.generic(Type.widestReturnType(trueExpr.getType(), falseExpr.getType())));
        final TypeBounds outBounds = resultBounds.notNarrowerThan(outNarrowest);

        emitBranch(test, falseLabel, false);

        final boolean isCurrentDiscard = lc.popDiscardIfCurrent(ternaryNode);
        loadMaybeDiscard(isCurrentDiscard, trueExpr.getExpression(), outBounds);
        assert isCurrentDiscard || Type.generic(method.peekType()) == outBounds.narrowest;
        method.beforeJoinPoint(trueExpr);
        method._goto(exitLabel);
        method.label(falseLabel);
        loadMaybeDiscard(isCurrentDiscard, falseExpr.getExpression(), outBounds);
        assert isCurrentDiscard || Type.generic(method.peekType()) == outBounds.narrowest;
        method.beforeJoinPoint(falseExpr);
        method.label(exitLabel);
    }

    /**
     * Generate all shared scope calls generated during codegen.
     */
    void generateScopeCalls() {
        for (final SharedScopeCall scopeAccess : lc.getScopeCalls()) {
            scopeAccess.generateScopeCall();
        }
    }

    /**
     * Debug code used to print symbols
     *
     * @param block the block we are in
     * @param function the function we are in
     * @param ident identifier for block or function where applicable
     */
    private void printSymbols(final Block block, final FunctionNode function, final String ident) {
        if (compiler.getScriptEnvironment()._print_symbols || function.getFlag(FunctionNode.IS_PRINT_SYMBOLS)) {
            final PrintWriter out = compiler.getScriptEnvironment().getErr();
            out.println("[BLOCK in '" + ident + "']");
            if (!block.printSymbols(out)) {
                out.println("<no symbols>");
            }
            out.println();
        }
    }


    /**
     * The difference between a store and a self modifying store is that
     * the latter may load part of the target on the stack, e.g. the base
     * of an AccessNode or the base and index of an IndexNode. These are used
     * both as target and as an extra source. Previously it was problematic
     * for self modifying stores if the target/lhs didn't belong to one
     * of three trivial categories: IdentNode, AcessNodes, IndexNodes. In that
     * case it was evaluated and tagged as "resolved", which meant at the second
     * time the lhs of this store was read (e.g. in a = a (second) + b for a += b,
     * it would be evaluated to a nop in the scope and cause stack underflow
     *
     * see NASHORN-703
     *
     * @param <T>
     */
    private abstract class SelfModifyingStore<T extends Expression> extends Store<T> {
        protected SelfModifyingStore(final T assignNode, final Expression target) {
            super(assignNode, target);
        }

        @Override
        protected boolean isSelfModifying() {
            return true;
        }
    }

    /**
     * Helper class to generate stores
     */
    private abstract class Store<T extends Expression> {

        /** An assignment node, e.g. x += y */
        protected final T assignNode;

        /** The target node to store to, e.g. x */
        private final Expression target;

        /** How deep on the stack do the arguments go if this generates an indy call */
        private int depth;

        /** If we have too many arguments, we need temporary storage, this is stored in 'quick' */
        private IdentNode quick;

        /**
         * Constructor
         *
         * @param assignNode the node representing the whole assignment
         * @param target     the target node of the assignment (destination)
         */
        protected Store(final T assignNode, final Expression target) {
            this.assignNode = assignNode;
            this.target = target;
        }

        /**
         * Constructor
         *
         * @param assignNode the node representing the whole assignment
         */
        protected Store(final T assignNode) {
            this(assignNode, assignNode);
        }

        /**
         * Is this a self modifying store operation, e.g. *= or ++
         * @return true if self modifying store
         */
        protected boolean isSelfModifying() {
            return false;
        }

        private void prologue() {
            /*
             * This loads the parts of the target, e.g base and index. they are kept
             * on the stack throughout the store and used at the end to execute it
             */

            target.accept(new SimpleNodeVisitor() {
                @Override
                public boolean enterIdentNode(final IdentNode node) {
                    if (node.getSymbol().isScope()) {
                        method.loadCompilerConstant(SCOPE);
                        depth += Type.SCOPE.getSlots();
                        assert depth == 1;
                    }
                    return false;
                }

                private void enterBaseNode() {
                    assert target instanceof BaseNode : "error - base node " + target + " must be instanceof BaseNode";
                    final BaseNode   baseNode = (BaseNode)target;
                    final Expression base     = baseNode.getBase();

                    loadExpressionAsObject(base);
                    depth += Type.OBJECT.getSlots();
                    assert depth == 1;

                    if (isSelfModifying()) {
                        method.dup();
                    }
                }

                @Override
                public boolean enterAccessNode(final AccessNode node) {
                    enterBaseNode();
                    return false;
                }

                @Override
                public boolean enterIndexNode(final IndexNode node) {
                    enterBaseNode();

                    final Expression index = node.getIndex();
                    if (!index.getType().isNumeric()) {
                        // could be boolean here as well
                        loadExpressionAsObject(index);
                    } else {
                        loadExpressionUnbounded(index);
                    }
                    depth += index.getType().getSlots();

                    if (isSelfModifying()) {
                        //convert "base base index" to "base index base index"
                        method.dup(1);
                    }

                    return false;
                }

            });
        }

        /**
         * Generates an extra local variable, always using the same slot, one that is available after the end of the
         * frame.
         *
         * @param type the type of the variable
         *
         * @return the quick variable
         */
        private IdentNode quickLocalVariable(final Type type) {
            final String name = lc.getCurrentFunction().uniqueName(QUICK_PREFIX.symbolName());
            final Symbol symbol = new Symbol(name, IS_INTERNAL | HAS_SLOT);
            symbol.setHasSlotFor(type);
            symbol.setFirstSlot(lc.quickSlot(type));

            final IdentNode quickIdent = IdentNode.createInternalIdentifier(symbol).setType(type);

            return quickIdent;
        }

        // store the result that "lives on" after the op, e.g. "i" in i++ postfix.
        protected void storeNonDiscard() {
            if (lc.popDiscardIfCurrent(assignNode)) {
                assert assignNode.isAssignment();
                return;
            }

            if (method.dup(depth) == null) {
                method.dup();
                final Type quickType = method.peekType();
                this.quick = quickLocalVariable(quickType);
                final Symbol quickSymbol = quick.getSymbol();
                method.storeTemp(quickType, quickSymbol.getFirstSlot());
            }
        }

        private void epilogue() {
            /**
             * Take the original target args from the stack and use them
             * together with the value to be stored to emit the store code
             *
             * The case that targetSymbol is in scope (!hasSlot) and we actually
             * need to do a conversion on non-equivalent types exists, but is
             * very rare. See for example test/script/basic/access-specializer.js
             */
            target.accept(new SimpleNodeVisitor() {
                @Override
                protected boolean enterDefault(final Node node) {
                    throw new AssertionError("Unexpected node " + node + " in store epilogue");
                }

                @Override
                public boolean enterIdentNode(final IdentNode node) {
                    final Symbol symbol = node.getSymbol();
                    assert symbol != null;
                    if (symbol.isScope()) {
                        final int flags = getScopeCallSiteFlags(symbol);
                        if (isFastScope(symbol)) {
                            storeFastScopeVar(symbol, flags);
                        } else {
                            method.dynamicSet(node.getName(), flags, false);
                        }
                    } else {
                        final Type storeType = assignNode.getType();
                        assert storeType != Type.LONG;
                        if (symbol.hasSlotFor(storeType)) {
                            // Only emit a convert for a store known to be live; converts for dead stores can
                            // give us an unnecessary ClassCastException.
                            method.convert(storeType);
                        }
                        storeIdentWithCatchConversion(node, storeType);
                    }
                    return false;

                }

                @Override
                public boolean enterAccessNode(final AccessNode node) {
                    method.dynamicSet(node.getProperty(), getCallSiteFlags(), node.isIndex());
                    return false;
                }

                @Override
                public boolean enterIndexNode(final IndexNode node) {
                    method.dynamicSetIndex(getCallSiteFlags());
                    return false;
                }
            });


            // whatever is on the stack now is the final answer
        }

        protected abstract void evaluate();

        void store() {
            if (target instanceof IdentNode) {
                checkTemporalDeadZone((IdentNode)target);
            }
            prologue();
            evaluate(); // leaves an operation of whatever the operationType was on the stack
            storeNonDiscard();
            epilogue();
            if (quick != null) {
                method.load(quick);
            }
        }
    }

    private void newFunctionObject(final FunctionNode functionNode, final boolean addInitializer) {
        assert lc.peek() == functionNode;

        final RecompilableScriptFunctionData data = compiler.getScriptFunctionData(functionNode.getId());

        if (functionNode.isProgram() && !compiler.isOnDemandCompilation()) {
            final MethodEmitter createFunction = functionNode.getCompileUnit().getClassEmitter().method(
                    EnumSet.of(Flag.PUBLIC, Flag.STATIC), CREATE_PROGRAM_FUNCTION.symbolName(),
                    ScriptFunction.class, ScriptObject.class);
            createFunction.begin();
            loadConstantsAndIndex(data, createFunction);
            createFunction.load(SCOPE_TYPE, 0);
            createFunction.invoke(CREATE_FUNCTION_OBJECT);
            createFunction._return();
            createFunction.end();
        }

        if (addInitializer && !compiler.isOnDemandCompilation()) {
            functionNode.getCompileUnit().addFunctionInitializer(data, functionNode);
        }

        // We don't emit a ScriptFunction on stack for the outermost compiled function (as there's no code being
        // generated in its outer context that'd need it as a callee).
        if (lc.getOutermostFunction() == functionNode) {
            return;
        }

        loadConstantsAndIndex(data, method);

        if (functionNode.needsParentScope()) {
            method.loadCompilerConstant(SCOPE);
            method.invoke(CREATE_FUNCTION_OBJECT);
        } else {
            method.invoke(CREATE_FUNCTION_OBJECT_NO_SCOPE);
        }
    }

    // calls on Global class.
    private MethodEmitter globalInstance() {
        return method.invokestatic(GLOBAL_OBJECT, "instance", "()L" + GLOBAL_OBJECT + ';');
    }

    private MethodEmitter globalAllocateArguments() {
        return method.invokestatic(GLOBAL_OBJECT, "allocateArguments", methodDescriptor(ScriptObject.class, Object[].class, Object.class, int.class));
    }

    private MethodEmitter globalNewRegExp() {
        return method.invokestatic(GLOBAL_OBJECT, "newRegExp", methodDescriptor(Object.class, String.class, String.class));
    }

    private MethodEmitter globalRegExpCopy() {
        return method.invokestatic(GLOBAL_OBJECT, "regExpCopy", methodDescriptor(Object.class, Object.class));
    }

    private MethodEmitter globalAllocateArray(final ArrayType type) {
        //make sure the native array is treated as an array type
        return method.invokestatic(GLOBAL_OBJECT, "allocate", "(" + type.getDescriptor() + ")Ljdk/nashorn/internal/objects/NativeArray;");
    }

    private MethodEmitter globalIsEval() {
        return method.invokestatic(GLOBAL_OBJECT, "isEval", methodDescriptor(boolean.class, Object.class));
    }

    private MethodEmitter globalReplaceLocationPropertyPlaceholder() {
        return method.invokestatic(GLOBAL_OBJECT, "replaceLocationPropertyPlaceholder", methodDescriptor(Object.class, Object.class, Object.class));
    }

    private MethodEmitter globalCheckObjectCoercible() {
        return method.invokestatic(GLOBAL_OBJECT, "checkObjectCoercible", methodDescriptor(void.class, Object.class));
    }

    private MethodEmitter globalDirectEval() {
        return method.invokestatic(GLOBAL_OBJECT, "directEval",
                methodDescriptor(Object.class, Object.class, Object.class, Object.class, Object.class, boolean.class));
    }

    private abstract class OptimisticOperation {
        private final boolean isOptimistic;
        // expression and optimistic are the same reference
        private final Expression expression;
        private final Optimistic optimistic;
        private final TypeBounds resultBounds;

        OptimisticOperation(final Optimistic optimistic, final TypeBounds resultBounds) {
            this.optimistic = optimistic;
            this.expression = (Expression)optimistic;
            this.resultBounds = resultBounds;
            this.isOptimistic = isOptimistic(optimistic) && useOptimisticTypes() &&
                    // Operation is only effectively optimistic if its type, after being coerced into the result bounds
                    // is narrower than the upper bound.
                    resultBounds.within(Type.generic(((Expression)optimistic).getType())).narrowerThan(resultBounds.widest);
        }

        MethodEmitter emit() {
            return emit(0);
        }

        MethodEmitter emit(final int ignoredArgCount) {
            final int     programPoint                  = optimistic.getProgramPoint();
            final boolean optimisticOrContinuation      = isOptimistic || isContinuationEntryPoint(programPoint);
            final boolean currentContinuationEntryPoint = isCurrentContinuationEntryPoint(programPoint);
            final int     stackSizeOnEntry              = method.getStackSize() - ignoredArgCount;

            // First store the values on the stack opportunistically into local variables. Doing it before loadStack()
            // allows us to not have to pop/load any arguments that are pushed onto it by loadStack() in the second
            // storeStack().
            storeStack(ignoredArgCount, optimisticOrContinuation);

            // Now, load the stack
            loadStack();

            // Now store the values on the stack ultimately into local variables. In vast majority of cases, this is
            // (aside from creating the local types map) a no-op, as the first opportunistic stack store will already
            // store all variables. However, there can be operations in the loadStack() that invalidate some of the
            // stack stores, e.g. in "x[i] = x[++i]", "++i" will invalidate the already stored value for "i". In such
            // unfortunate cases this second storeStack() will restore the invariant that everything on the stack is
            // stored into a local variable, although at the cost of doing a store/load on the loaded arguments as well.
            final int liveLocalsCount = storeStack(method.getStackSize() - stackSizeOnEntry, optimisticOrContinuation);
            assert optimisticOrContinuation == (liveLocalsCount != -1);

            final Label beginTry;
            final Label catchLabel;
            final Label afterConsumeStack = isOptimistic || currentContinuationEntryPoint ? new Label("after_consume_stack") : null;
            if(isOptimistic) {
                beginTry = new Label("try_optimistic");
                final String catchLabelName = (afterConsumeStack == null ? "" : afterConsumeStack.toString()) + "_handler";
                catchLabel = new Label(catchLabelName);
                method.label(beginTry);
            } else {
                beginTry = catchLabel = null;
            }

            consumeStack();

            if(isOptimistic) {
                method._try(beginTry, afterConsumeStack, catchLabel, UnwarrantedOptimismException.class);
            }

            if(isOptimistic || currentContinuationEntryPoint) {
                method.label(afterConsumeStack);

                final int[] localLoads = method.getLocalLoadsOnStack(0, stackSizeOnEntry);
                assert everyStackValueIsLocalLoad(localLoads) : Arrays.toString(localLoads) + ", " + stackSizeOnEntry + ", " + ignoredArgCount;
                final List<Type> localTypesList = method.getLocalVariableTypes();
                final int usedLocals = method.getUsedSlotsWithLiveTemporaries();
                final List<Type> localTypes = method.getWidestLiveLocals(localTypesList.subList(0, usedLocals));
                assert everyLocalLoadIsValid(localLoads, usedLocals) : Arrays.toString(localLoads) + " ~ " + localTypes;

                if(isOptimistic) {
                    addUnwarrantedOptimismHandlerLabel(localTypes, catchLabel);
                }
                if(currentContinuationEntryPoint) {
                    final ContinuationInfo ci = getContinuationInfo();
                    assert ci != null : "no continuation info found for " + lc.getCurrentFunction();
                    assert !ci.hasTargetLabel(); // No duplicate program points
                    ci.setTargetLabel(afterConsumeStack);
                    ci.getHandlerLabel().markAsOptimisticContinuationHandlerFor(afterConsumeStack);
                    // Can't rely on targetLabel.stack.localVariableTypes.length, as it can be higher due to effectively
                    // dead local variables.
                    ci.lvarCount = localTypes.size();
                    ci.setStackStoreSpec(localLoads);
                    ci.setStackTypes(Arrays.copyOf(method.getTypesFromStack(method.getStackSize()), stackSizeOnEntry));
                    assert ci.getStackStoreSpec().length == ci.getStackTypes().length;
                    ci.setReturnValueType(method.peekType());
                    ci.lineNumber = getLastLineNumber();
                    ci.catchLabel = catchLabels.peek();
                }
            }
            return method;
        }

        /**
         * Stores the current contents of the stack into local variables so they are not lost before invoking something that
         * can result in an {@code UnwarantedOptimizationException}.
         * @param ignoreArgCount the number of topmost arguments on stack to ignore when deciding on the shape of the catch
         * block. Those are used in the situations when we could not place the call to {@code storeStack} early enough
         * (before emitting code for pushing the arguments that the optimistic call will pop). This is admittedly a
         * deficiency in the design of the code generator when it deals with self-assignments and we should probably look
         * into fixing it.
         * @return types of the significant local variables after the stack was stored (types for local variables used
         * for temporary storage of ignored arguments are not returned).
         * @param optimisticOrContinuation if false, this method should not execute
         * a label for a catch block for the {@code UnwarantedOptimizationException}, suitable for capturing the
         * currently live local variables, tailored to their types.
         */
        private int storeStack(final int ignoreArgCount, final boolean optimisticOrContinuation) {
            if(!optimisticOrContinuation) {
                return -1; // NOTE: correct value to return is lc.getUsedSlotCount(), but it wouldn't be used anyway
            }

            final int stackSize = method.getStackSize();
            final Type[] stackTypes = method.getTypesFromStack(stackSize);
            final int[] localLoadsOnStack = method.getLocalLoadsOnStack(0, stackSize);
            final int usedSlots = method.getUsedSlotsWithLiveTemporaries();

            final int firstIgnored = stackSize - ignoreArgCount;
            // Find the first value on the stack (from the bottom) that is not a load from a local variable.
            int firstNonLoad = 0;
            while(firstNonLoad < firstIgnored && localLoadsOnStack[firstNonLoad] != Label.Stack.NON_LOAD) {
                firstNonLoad++;
            }

            // Only do the store/load if first non-load is not an ignored argument. Otherwise, do nothing and return
            // the number of used slots as the number of live local variables.
            if(firstNonLoad >= firstIgnored) {
                return usedSlots;
            }

            // Find the number of new temporary local variables that we need; it's the number of values on the stack that
            // are not direct loads of existing local variables.
            int tempSlotsNeeded = 0;
            for(int i = firstNonLoad; i < stackSize; ++i) {
                if(localLoadsOnStack[i] == Label.Stack.NON_LOAD) {
                    tempSlotsNeeded += stackTypes[i].getSlots();
                }
            }

            // Ensure all values on the stack that weren't directly loaded from a local variable are stored in a local
            // variable. We're starting from highest local variable index, so that in case ignoreArgCount > 0 the ignored
            // ones end up at the end of the local variable table.
            int lastTempSlot = usedSlots + tempSlotsNeeded;
            int ignoreSlotCount = 0;
            for(int i = stackSize; i -- > firstNonLoad;) {
                final int loadSlot = localLoadsOnStack[i];
                if(loadSlot == Label.Stack.NON_LOAD) {
                    final Type type = stackTypes[i];
                    final int slots = type.getSlots();
                    lastTempSlot -= slots;
                    if(i >= firstIgnored) {
                        ignoreSlotCount += slots;
                    }
                    method.storeTemp(type, lastTempSlot);
                } else {
                    method.pop();
                }
            }
            assert lastTempSlot == usedSlots; // used all temporary locals

            final List<Type> localTypesList = method.getLocalVariableTypes();

            // Load values back on stack.
            for(int i = firstNonLoad; i < stackSize; ++i) {
                final int loadSlot = localLoadsOnStack[i];
                final Type stackType = stackTypes[i];
                final boolean isLoad = loadSlot != Label.Stack.NON_LOAD;
                final int lvarSlot = isLoad ? loadSlot : lastTempSlot;
                final Type lvarType = localTypesList.get(lvarSlot);
                method.load(lvarType, lvarSlot);
                if(isLoad) {
                    // Conversion operators (I2L etc.) preserve "load"-ness of the value despite the fact that, in the
                    // strict sense they are creating a derived value from the loaded value. This special behavior of
                    // on-stack conversion operators is necessary to accommodate for differences in local variable types
                    // after deoptimization; having a conversion operator throw away "load"-ness would create different
                    // local variable table shapes between optimism-failed code and its deoptimized rest-of method).
                    // After we load the value back, we need to redo the conversion to the stack type if stack type is
                    // different.
                    // NOTE: this would only strictly be necessary for widening conversions (I2L, L2D, I2D), and not for
                    // narrowing ones (L2I, D2L, D2I) as only widening conversions are the ones that can get eliminated
                    // in a deoptimized method, as their original input argument got widened. Maybe experiment with
                    // throwing away "load"-ness for narrowing conversions in MethodEmitter.convert()?
                    method.convert(stackType);
                } else {
                    // temporary stores never needs a convert, as their type is always the same as the stack type.
                    assert lvarType == stackType;
                    lastTempSlot += lvarType.getSlots();
                }
            }
            // used all temporaries
            assert lastTempSlot == usedSlots + tempSlotsNeeded;

            return lastTempSlot - ignoreSlotCount;
        }

        private void addUnwarrantedOptimismHandlerLabel(final List<Type> localTypes, final Label label) {
            final String lvarTypesDescriptor = getLvarTypesDescriptor(localTypes);
            final Map<String, Collection<Label>> unwarrantedOptimismHandlers = lc.getUnwarrantedOptimismHandlers();
            Collection<Label> labels = unwarrantedOptimismHandlers.get(lvarTypesDescriptor);
            if(labels == null) {
                labels = new LinkedList<>();
                unwarrantedOptimismHandlers.put(lvarTypesDescriptor, labels);
            }
            method.markLabelAsOptimisticCatchHandler(label, localTypes.size());
            labels.add(label);
        }

        abstract void loadStack();

        // Make sure that whatever indy call site you emit from this method uses {@code getCallSiteFlagsOptimistic(node)}
        // or otherwise ensure optimistic flag is correctly set in the call site, otherwise it doesn't make much sense
        // to use OptimisticExpression for emitting it.
        abstract void consumeStack();

        /**
         * Emits the correct dynamic getter code. Normally just delegates to method emitter, except when the target
         * expression is optimistic, and the desired type is narrower than the optimistic type. In that case, it'll emit a
         * dynamic getter with its original optimistic type, and explicitly insert a narrowing conversion. This way we can
         * preserve the optimism of the values even if they're subsequently immediately coerced into a narrower type. This
         * is beneficial because in this case we can still presume that since the original getter was optimistic, the
         * conversion has no side effects.
         * @param name the name of the property being get
         * @param flags call site flags
         * @param isMethod whether we're preferably retrieving a function
         * @return the current method emitter
         */
        MethodEmitter dynamicGet(final String name, final int flags, final boolean isMethod, final boolean isIndex) {
            if(isOptimistic) {
                return method.dynamicGet(getOptimisticCoercedType(), name, getOptimisticFlags(flags), isMethod, isIndex);
            }
            return method.dynamicGet(resultBounds.within(expression.getType()), name, nonOptimisticFlags(flags), isMethod, isIndex);
        }

        MethodEmitter dynamicGetIndex(final int flags, final boolean isMethod) {
            if(isOptimistic) {
                return method.dynamicGetIndex(getOptimisticCoercedType(), getOptimisticFlags(flags), isMethod);
            }
            return method.dynamicGetIndex(resultBounds.within(expression.getType()), nonOptimisticFlags(flags), isMethod);
        }

        MethodEmitter dynamicCall(final int argCount, final int flags, final String msg) {
            if (isOptimistic) {
                return method.dynamicCall(getOptimisticCoercedType(), argCount, getOptimisticFlags(flags), msg);
            }
            return method.dynamicCall(resultBounds.within(expression.getType()), argCount, nonOptimisticFlags(flags), msg);
        }

        int getOptimisticFlags(final int flags) {
            return flags | CALLSITE_OPTIMISTIC | (optimistic.getProgramPoint() << CALLSITE_PROGRAM_POINT_SHIFT); //encode program point in high bits
        }

        int getProgramPoint() {
            return isOptimistic ? optimistic.getProgramPoint() : INVALID_PROGRAM_POINT;
        }

        void convertOptimisticReturnValue() {
            if (isOptimistic) {
                final Type optimisticType = getOptimisticCoercedType();
                if(!optimisticType.isObject()) {
                    method.load(optimistic.getProgramPoint());
                    if(optimisticType.isInteger()) {
                        method.invoke(ENSURE_INT);
                    } else if(optimisticType.isNumber()) {
                        method.invoke(ENSURE_NUMBER);
                    } else {
                        throw new AssertionError(optimisticType);
                    }
                }
            }
        }

        void replaceCompileTimeProperty() {
            final IdentNode identNode = (IdentNode)expression;
            final String name = identNode.getSymbol().getName();
            if (CompilerConstants.__FILE__.name().equals(name)) {
                replaceCompileTimeProperty(getCurrentSource().getName());
            } else if (CompilerConstants.__DIR__.name().equals(name)) {
                replaceCompileTimeProperty(getCurrentSource().getBase());
            } else if (CompilerConstants.__LINE__.name().equals(name)) {
                replaceCompileTimeProperty(getCurrentSource().getLine(identNode.position()));
            }
        }

        /**
         * When an ident with name __FILE__, __DIR__, or __LINE__ is loaded, we'll try to look it up as any other
         * identifier. However, if it gets all the way up to the Global object, it will send back a special value that
         * represents a placeholder for these compile-time location properties. This method will generate code that loads
         * the value of the compile-time location property and then invokes a method in Global that will replace the
         * placeholder with the value. Effectively, if the symbol for these properties is defined anywhere in the lexical
         * scope, they take precedence, but if they aren't, then they resolve to the compile-time location property.
         * @param propertyValue the actual value of the property
         */
        private void replaceCompileTimeProperty(final Object propertyValue) {
            assert method.peekType().isObject();
            if(propertyValue instanceof String || propertyValue == null) {
                method.load((String)propertyValue);
            } else if(propertyValue instanceof Integer) {
                method.load(((Integer)propertyValue).intValue());
                method.convert(Type.OBJECT);
            } else {
                throw new AssertionError();
            }
            globalReplaceLocationPropertyPlaceholder();
            convertOptimisticReturnValue();
        }

        /**
         * Returns the type that should be used as the return type of the dynamic invocation that is emitted as the code
         * for the current optimistic operation. If the type bounds is exact boolean or narrower than the expression's
         * optimistic type, then the optimistic type is returned, otherwise the coercing type. Effectively, this method
         * allows for moving the coercion into the optimistic type when it won't adversely affect the optimistic
         * evaluation semantics, and for preserving the optimistic type and doing a separate coercion when it would
         * affect it.
         * @return
         */
        private Type getOptimisticCoercedType() {
            final Type optimisticType = expression.getType();
            assert resultBounds.widest.widerThan(optimisticType);
            final Type narrowest = resultBounds.narrowest;

            if(narrowest.isBoolean() || narrowest.narrowerThan(optimisticType)) {
                assert !optimisticType.isObject();
                return optimisticType;
            }
            assert !narrowest.isObject();
            return narrowest;
        }
    }

    private static boolean isOptimistic(final Optimistic optimistic) {
        if(!optimistic.canBeOptimistic()) {
            return false;
        }
        final Expression expr = (Expression)optimistic;
        return expr.getType().narrowerThan(expr.getWidestOperationType());
    }

    private static boolean everyLocalLoadIsValid(final int[] loads, final int localCount) {
        for (final int load : loads) {
            if(load < 0 || load >= localCount) {
                return false;
            }
        }
        return true;
    }

    private static boolean everyStackValueIsLocalLoad(final int[] loads) {
        for (final int load : loads) {
            if(load == Label.Stack.NON_LOAD) {
                return false;
            }
        }
        return true;
    }

    private String getLvarTypesDescriptor(final List<Type> localVarTypes) {
        final int count = localVarTypes.size();
        final StringBuilder desc = new StringBuilder(count);
        for(int i = 0; i < count;) {
            i += appendType(desc, localVarTypes.get(i));
        }
        return method.markSymbolBoundariesInLvarTypesDescriptor(desc.toString());
    }

    private static int appendType(final StringBuilder b, final Type t) {
        b.append(t.getBytecodeStackType());
        return t.getSlots();
    }

    private static int countSymbolsInLvarTypeDescriptor(final String lvarTypeDescriptor) {
        int count = 0;
        for(int i = 0; i < lvarTypeDescriptor.length(); ++i) {
            if(Character.isUpperCase(lvarTypeDescriptor.charAt(i))) {
                ++count;
            }
        }
        return count;

    }
    /**
     * Generates all the required {@code UnwarrantedOptimismException} handlers for the current function. The employed
     * strategy strives to maximize code reuse. Every handler constructs an array to hold the local variables, then
     * fills in some trailing part of the local variables (those for which it has a unique suffix in the descriptor),
     * then jumps to a handler for a prefix that's shared with other handlers. A handler that fills up locals up to
     * position 0 will not jump to a prefix handler (as it has no prefix), but instead end with constructing and
     * throwing a {@code RewriteException}. Since we lexicographically sort the entries, we only need to check every
     * entry to its immediately preceding one for longest matching prefix.
     * @return true if there is at least one exception handler
     */
    private boolean generateUnwarrantedOptimismExceptionHandlers(final FunctionNode fn) {
        if(!useOptimisticTypes()) {
            return false;
        }

        // Take the mapping of lvarSpecs -> labels, and turn them into a descending lexicographically sorted list of
        // handler specifications.
        final Map<String, Collection<Label>> unwarrantedOptimismHandlers = lc.popUnwarrantedOptimismHandlers();
        if(unwarrantedOptimismHandlers.isEmpty()) {
            return false;
        }

        method.lineNumber(0);

        final List<OptimismExceptionHandlerSpec> handlerSpecs = new ArrayList<>(unwarrantedOptimismHandlers.size() * 4/3);
        for(final String spec: unwarrantedOptimismHandlers.keySet()) {
            handlerSpecs.add(new OptimismExceptionHandlerSpec(spec, true));
        }
        Collections.sort(handlerSpecs, Collections.reverseOrder());

        // Map of local variable specifications to labels for populating the array for that local variable spec.
        final Map<String, Label> delegationLabels = new HashMap<>();

        // Do everything in a single pass over the handlerSpecs list. Note that the list can actually grow as we're
        // passing through it as we might add new prefix handlers into it, so can't hoist size() outside of the loop.
        for(int handlerIndex = 0; handlerIndex < handlerSpecs.size(); ++handlerIndex) {
            final OptimismExceptionHandlerSpec spec = handlerSpecs.get(handlerIndex);
            final String lvarSpec = spec.lvarSpec;
            if(spec.catchTarget) {
                assert !method.isReachable();
                // Start a catch block and assign the labels for this lvarSpec with it.
                method._catch(unwarrantedOptimismHandlers.get(lvarSpec));
                // This spec is a catch target, so emit array creation code. The length of the array is the number of
                // symbols - the number of uppercase characters.
                method.load(countSymbolsInLvarTypeDescriptor(lvarSpec));
                method.newarray(Type.OBJECT_ARRAY);
            }
            if(spec.delegationTarget) {
                // If another handler can delegate to this handler as its prefix, then put a jump target here for the
                // shared code (after the array creation code, which is never shared).
                method.label(delegationLabels.get(lvarSpec)); // label must exist
            }

            final boolean lastHandler = handlerIndex == handlerSpecs.size() - 1;

            int lvarIndex;
            final int firstArrayIndex;
            final int firstLvarIndex;
            Label delegationLabel;
            final String commonLvarSpec;
            if(lastHandler) {
                // Last handler block, doesn't delegate to anything.
                lvarIndex = 0;
                firstLvarIndex = 0;
                firstArrayIndex = 0;
                delegationLabel = null;
                commonLvarSpec = null;
            } else {
                // Not yet the last handler block, will definitely delegate to another handler; let's figure out which
                // one. It can be an already declared handler further down the list, or it might need to declare a new
                // prefix handler.

                // Since we're lexicographically ordered, the common prefix handler is defined by the common prefix of
                // this handler and the next handler on the list.
                final int nextHandlerIndex = handlerIndex + 1;
                final String nextLvarSpec = handlerSpecs.get(nextHandlerIndex).lvarSpec;
                commonLvarSpec = commonPrefix(lvarSpec, nextLvarSpec);
                // We don't chop symbols in half
                assert Character.isUpperCase(commonLvarSpec.charAt(commonLvarSpec.length() - 1));

                // Let's find if we already have a declaration for such handler, or we need to insert it.
                {
                    boolean addNewHandler = true;
                    int commonHandlerIndex = nextHandlerIndex;
                    for(; commonHandlerIndex < handlerSpecs.size(); ++commonHandlerIndex) {
                        final OptimismExceptionHandlerSpec forwardHandlerSpec = handlerSpecs.get(commonHandlerIndex);
                        final String forwardLvarSpec = forwardHandlerSpec.lvarSpec;
                        if(forwardLvarSpec.equals(commonLvarSpec)) {
                            // We already have a handler for the common prefix.
                            addNewHandler = false;
                            // Make sure we mark it as a delegation target.
                            forwardHandlerSpec.delegationTarget = true;
                            break;
                        } else if(!forwardLvarSpec.startsWith(commonLvarSpec)) {
                            break;
                        }
                    }
                    if(addNewHandler) {
                        // We need to insert a common prefix handler. Note handlers created with catchTarget == false
                        // will automatically have delegationTarget == true (because that's the only reason for their
                        // existence).
                        handlerSpecs.add(commonHandlerIndex, new OptimismExceptionHandlerSpec(commonLvarSpec, false));
                    }
                }

                firstArrayIndex = countSymbolsInLvarTypeDescriptor(commonLvarSpec);
                lvarIndex = 0;
                for(int j = 0; j < commonLvarSpec.length(); ++j) {
                    lvarIndex += CodeGeneratorLexicalContext.getTypeForSlotDescriptor(commonLvarSpec.charAt(j)).getSlots();
                }
                firstLvarIndex = lvarIndex;

                // Create a delegation label if not already present
                delegationLabel = delegationLabels.get(commonLvarSpec);
                if(delegationLabel == null) {
                    // uo_pa == "unwarranted optimism, populate array"
                    delegationLabel = new Label("uo_pa_" + commonLvarSpec);
                    delegationLabels.put(commonLvarSpec, delegationLabel);
                }
            }

            // Load local variables handled by this handler on stack
            int args = 0;
            boolean symbolHadValue = false;
            for(int typeIndex = commonLvarSpec == null ? 0 : commonLvarSpec.length(); typeIndex < lvarSpec.length(); ++typeIndex) {
                final char typeDesc = lvarSpec.charAt(typeIndex);
                final Type lvarType = CodeGeneratorLexicalContext.getTypeForSlotDescriptor(typeDesc);
                if (!lvarType.isUnknown()) {
                    method.load(lvarType, lvarIndex);
                    symbolHadValue = true;
                    args++;
                } else if(typeDesc == 'U' && !symbolHadValue) {
                    // Symbol boundary with undefined last value. Check if all previous values for this symbol were also
                    // undefined; if so, emit one explicit Undefined. This serves to ensure that we're emiting exactly
                    // one value for every symbol that uses local slots. While we could in theory ignore symbols that
                    // are undefined (in other words, dead) at the point where this exception was thrown, unfortunately
                    // we can't do it in practice. The reason for this is that currently our liveness analysis is
                    // coarse (it can determine whether a symbol has not been read with a particular type anywhere in
                    // the function being compiled, but that's it), and a symbol being promoted to Object due to a
                    // deoptimization will suddenly show up as "live for Object type", and previously dead U->O
                    // conversions on loop entries will suddenly become alive in the deoptimized method which will then
                    // expect a value for that slot in its continuation handler. If we had precise liveness analysis, we
                    // could go back to excluding known dead symbols from the payload of the RewriteException.
                    if(method.peekType() == Type.UNDEFINED) {
                        method.dup();
                    } else {
                        method.loadUndefined(Type.OBJECT);
                    }
                    args++;
                }
                if(Character.isUpperCase(typeDesc)) {
                    // Reached symbol boundary; reset flag for the next symbol.
                    symbolHadValue = false;
                }
                lvarIndex += lvarType.getSlots();
            }
            assert args > 0;
            // Delegate actual storing into array to an array populator utility method.
            //on the stack:
            // object array to be populated
            // start index
            // a lot of types
            method.dynamicArrayPopulatorCall(args + 1, firstArrayIndex);
            if(delegationLabel != null) {
                // We cascade to a prefix handler to fill out the rest of the local variables and throw the
                // RewriteException.
                assert !lastHandler;
                assert commonLvarSpec != null;
                // Must undefine the local variables that we have already processed for the sake of correct join on the
                // delegate label
                method.undefineLocalVariables(firstLvarIndex, true);
                final OptimismExceptionHandlerSpec nextSpec = handlerSpecs.get(handlerIndex + 1);
                // If the delegate immediately follows, and it's not a catch target (so it doesn't have array setup
                // code) don't bother emitting a jump, as we'd just jump to the next instruction.
                if(!nextSpec.lvarSpec.equals(commonLvarSpec) || nextSpec.catchTarget) {
                    method._goto(delegationLabel);
                }
            } else {
                assert lastHandler;
                // Nothing to delegate to, so this handler must create and throw the RewriteException.
                // At this point we have the UnwarrantedOptimismException and the Object[] with local variables on
                // stack. We need to create a RewriteException, push two references to it below the constructor
                // arguments, invoke the constructor, and throw the exception.
                loadConstant(getByteCodeSymbolNames(fn));
                if (isRestOf()) {
                    loadConstant(getContinuationEntryPoints());
                    method.invoke(CREATE_REWRITE_EXCEPTION_REST_OF);
                } else {
                    method.invoke(CREATE_REWRITE_EXCEPTION);
                }
                method.athrow();
            }
        }
        return true;
    }

    private static String[] getByteCodeSymbolNames(final FunctionNode fn) {
        // Only names of local variables on the function level are captured. This information is used to reduce
        // deoptimizations, so as much as we can capture will help. We rely on the fact that function wide variables are
        // all live all the time, so the array passed to rewrite exception contains one element for every slotted symbol
        // here.
        final List<String> names = new ArrayList<>();
        for (final Symbol symbol: fn.getBody().getSymbols()) {
            if (symbol.hasSlot()) {
                if (symbol.isScope()) {
                    // slot + scope can only be true for parameters
                    assert symbol.isParam();
                    names.add(null);
                } else {
                    names.add(symbol.getName());
                }
            }
        }
        return names.toArray(new String[names.size()]);
    }

    private static String commonPrefix(final String s1, final String s2) {
        final int l1 = s1.length();
        final int l = Math.min(l1, s2.length());
        int lms = -1; // last matching symbol
        for(int i = 0; i < l; ++i) {
            final char c1 = s1.charAt(i);
            if(c1 != s2.charAt(i)) {
                return s1.substring(0, lms + 1);
            } else if(Character.isUpperCase(c1)) {
                lms = i;
            }
        }
        return l == l1 ? s1 : s2;
    }

    private static class OptimismExceptionHandlerSpec implements Comparable<OptimismExceptionHandlerSpec> {
        private final String lvarSpec;
        private final boolean catchTarget;
        private boolean delegationTarget;

        OptimismExceptionHandlerSpec(final String lvarSpec, final boolean catchTarget) {
            this.lvarSpec = lvarSpec;
            this.catchTarget = catchTarget;
            if(!catchTarget) {
                delegationTarget = true;
            }
        }

        @Override
        public int compareTo(final OptimismExceptionHandlerSpec o) {
            return lvarSpec.compareTo(o.lvarSpec);
        }

        @Override
        public String toString() {
            final StringBuilder b = new StringBuilder(64).append("[HandlerSpec ").append(lvarSpec);
            if(catchTarget) {
                b.append(", catchTarget");
            }
            if(delegationTarget) {
                b.append(", delegationTarget");
            }
            return b.append("]").toString();
        }
    }

    private static class ContinuationInfo {
        private final Label handlerLabel;
        private Label targetLabel; // Label for the target instruction.
        int lvarCount;
        // Indices of local variables that need to be loaded on the stack when this node completes
        private int[] stackStoreSpec;
        // Types of values loaded on the stack
        private Type[] stackTypes;
        // If non-null, this node should perform the requisite type conversion
        private Type returnValueType;
        // If we are in the middle of an object literal initialization, we need to update the property maps
        private Map<Integer, PropertyMap> objectLiteralMaps;
        // The line number at the continuation point
        private int lineNumber;
        // The active catch label, in case the continuation point is in a try/catch block
        private Label catchLabel;
        // The number of scopes that need to be popped before control is transferred to the catch label.
        private int exceptionScopePops;

        ContinuationInfo() {
            this.handlerLabel = new Label("continuation_handler");
        }

        Label getHandlerLabel() {
            return handlerLabel;
        }

        boolean hasTargetLabel() {
            return targetLabel != null;
        }

        Label getTargetLabel() {
            return targetLabel;
        }

        void setTargetLabel(final Label targetLabel) {
            this.targetLabel = targetLabel;
        }

        int[] getStackStoreSpec() {
            return stackStoreSpec.clone();
        }

        void setStackStoreSpec(final int[] stackStoreSpec) {
            this.stackStoreSpec = stackStoreSpec;
        }

        Type[] getStackTypes() {
            return stackTypes.clone();
        }

        void setStackTypes(final Type[] stackTypes) {
            this.stackTypes = stackTypes;
        }

        Type getReturnValueType() {
            return returnValueType;
        }

        void setReturnValueType(final Type returnValueType) {
            this.returnValueType = returnValueType;
        }

        void setObjectLiteralMap(final int objectLiteralStackDepth, final PropertyMap objectLiteralMap) {
            if (objectLiteralMaps == null) {
                objectLiteralMaps = new HashMap<>();
            }
            objectLiteralMaps.put(objectLiteralStackDepth, objectLiteralMap);
        }

        PropertyMap getObjectLiteralMap(final int stackDepth) {
            return objectLiteralMaps == null ? null : objectLiteralMaps.get(stackDepth);
        }

        @Override
        public String toString() {
             return "[localVariableTypes=" + targetLabel.getStack().getLocalVariableTypesCopy() + ", stackStoreSpec=" +
                     Arrays.toString(stackStoreSpec) + ", returnValueType=" + returnValueType + "]";
        }
    }

    private ContinuationInfo getContinuationInfo() {
        return continuationInfo;
    }

    private void generateContinuationHandler() {
        if (!isRestOf()) {
            return;
        }

        final ContinuationInfo ci = getContinuationInfo();
        method.label(ci.getHandlerLabel());

        // There should never be an exception thrown from the continuation handler, but in case there is (meaning,
        // Nashorn has a bug), then line number 0 will be an indication of where it came from (line numbers are Uint16).
        method.lineNumber(0);

        final Label.Stack stack = ci.getTargetLabel().getStack();
        final List<Type> lvarTypes = stack.getLocalVariableTypesCopy();
        final BitSet symbolBoundary = stack.getSymbolBoundaryCopy();
        final int lvarCount = ci.lvarCount;

        final Type rewriteExceptionType = Type.typeFor(RewriteException.class);
        // Store the RewriteException into an unused local variable slot.
        method.load(rewriteExceptionType, 0);
        method.storeTemp(rewriteExceptionType, lvarCount);
        // Get local variable array
        method.load(rewriteExceptionType, 0);
        method.invoke(RewriteException.GET_BYTECODE_SLOTS);
        // Store local variables. Note that deoptimization might introduce new value types for existing local variables,
        // so we must use both liveLocals and symbolBoundary, as in some cases (when the continuation is inside of a try
        // block) we need to store the incoming value into multiple slots. The optimism exception handlers will have
        // exactly one array element for every symbol that uses bytecode storage. If in the originating method the value
        // was undefined, there will be an explicit Undefined value in the array.
        int arrayIndex = 0;
        for(int lvarIndex = 0; lvarIndex < lvarCount;) {
            final Type lvarType = lvarTypes.get(lvarIndex);
            if(!lvarType.isUnknown()) {
                method.dup();
                method.load(arrayIndex).arrayload();
                final Class<?> typeClass = lvarType.getTypeClass();
                // Deoptimization in array initializers can cause arrays to undergo component type widening
                if(typeClass == long[].class) {
                    method.load(rewriteExceptionType, lvarCount);
                    method.invoke(RewriteException.TO_LONG_ARRAY);
                } else if(typeClass == double[].class) {
                    method.load(rewriteExceptionType, lvarCount);
                    method.invoke(RewriteException.TO_DOUBLE_ARRAY);
                } else if(typeClass == Object[].class) {
                    method.load(rewriteExceptionType, lvarCount);
                    method.invoke(RewriteException.TO_OBJECT_ARRAY);
                } else {
                    if(!(typeClass.isPrimitive() || typeClass == Object.class)) {
                        // NOTE: this can only happen with dead stores. E.g. for the program "1; []; f();" in which the
                        // call to f() will deoptimize the call site, but it'll expect :return to have the type
                        // NativeArray. However, in the more optimal version, :return's only live type is int, therefore
                        // "{O}:return = []" is a dead store, and the variable will be sent into the continuation as
                        // Undefined, however NativeArray can't hold Undefined instance.
                        method.loadType(Type.getInternalName(typeClass));
                        method.invoke(RewriteException.INSTANCE_OR_NULL);
                    }
                    method.convert(lvarType);
                }
                method.storeHidden(lvarType, lvarIndex, false);
            }
            final int nextLvarIndex = lvarIndex + lvarType.getSlots();
            if(symbolBoundary.get(nextLvarIndex - 1)) {
                ++arrayIndex;
            }
            lvarIndex = nextLvarIndex;
        }
        if (AssertsEnabled.assertsEnabled()) {
            method.load(arrayIndex);
            method.invoke(RewriteException.ASSERT_ARRAY_LENGTH);
        } else {
            method.pop();
        }

        final int[]   stackStoreSpec = ci.getStackStoreSpec();
        final Type[]  stackTypes     = ci.getStackTypes();
        final boolean isStackEmpty   = stackStoreSpec.length == 0;
        int replacedObjectLiteralMaps = 0;
        if(!isStackEmpty) {
            // Load arguments on the stack
            for(int i = 0; i < stackStoreSpec.length; ++i) {
                final int slot = stackStoreSpec[i];
                method.load(lvarTypes.get(slot), slot);
                method.convert(stackTypes[i]);
                // stack: s0=object literal being initialized
                // change map of s0 so that the property we are initializing when we failed
                // is now ci.returnValueType
                final PropertyMap map = ci.getObjectLiteralMap(i);
                if (map != null) {
                    method.dup();
                    assert ScriptObject.class.isAssignableFrom(method.peekType().getTypeClass()) : method.peekType().getTypeClass() + " is not a script object";
                    loadConstant(map);
                    method.invoke(ScriptObject.SET_MAP);
                    replacedObjectLiteralMaps++;
                }
            }
        }
        // Must have emitted the code for replacing all object literal maps
        assert ci.objectLiteralMaps == null || ci.objectLiteralMaps.size() == replacedObjectLiteralMaps;
        // Load RewriteException back.
        method.load(rewriteExceptionType, lvarCount);
        // Get rid of the stored reference
        method.loadNull();
        method.storeHidden(Type.OBJECT, lvarCount);
        // Mark it dead
        method.markDeadSlots(lvarCount, Type.OBJECT.getSlots());

        // Load return value on the stack
        method.invoke(RewriteException.GET_RETURN_VALUE);

        final Type returnValueType = ci.getReturnValueType();

        // Set up an exception handler for primitive type conversion of return value if needed
        boolean needsCatch = false;
        final Label targetCatchLabel = ci.catchLabel;
        Label _try = null;
        if(returnValueType.isPrimitive()) {
            // If the conversion throws an exception, we want to report the line number of the continuation point.
            method.lineNumber(ci.lineNumber);

            if(targetCatchLabel != METHOD_BOUNDARY) {
                _try = new Label("");
                method.label(_try);
                needsCatch = true;
            }
        }

        // Convert return value
        method.convert(returnValueType);

        final int scopePopCount = needsCatch ? ci.exceptionScopePops : 0;

        // Declare a try/catch for the conversion. If no scopes need to be popped until the target catch block, just
        // jump into it. Otherwise, we'll need to create a scope-popping catch block below.
        final Label catchLabel = scopePopCount > 0 ? new Label("") : targetCatchLabel;
        if(needsCatch) {
            final Label _end_try = new Label("");
            method.label(_end_try);
            method._try(_try, _end_try, catchLabel);
        }

        // Jump to continuation point
        method._goto(ci.getTargetLabel());

        // Make a scope-popping exception delegate if needed
        if(catchLabel != targetCatchLabel) {
            method.lineNumber(0);
            assert scopePopCount > 0;
            method._catch(catchLabel);
            popScopes(scopePopCount);
            method.uncheckedGoto(targetCatchLabel);
        }
    }

    /**
     * Interface implemented by object creators that support splitting over multiple methods.
     */
    interface SplitLiteralCreator {
        /**
         * Generate code to populate a range of the literal object. A reference to the object
         * should be left on the stack when the method terminates.
         *
         * @param method the method emitter
         * @param type the type of the literal object
         * @param slot the local slot containing the literal object
         * @param start the start index (inclusive)
         * @param end the end index (exclusive)
         */
        void populateRange(MethodEmitter method, Type type, int slot, int start, int end);
    }
}
