<commit_before>/**
 * Copyright (c) 2012-2013 <NAME>
 * Alle Rechte vorbehalten / All Rights Reserved.  Use is subject to license terms.
 *
 * <https://github.com/anba/es6draft>
 */
package com.github.anba.es6draft.compiler;

import static com.github.anba.es6draft.semantics.StaticSemantics.BoundNames;
import static com.github.anba.es6draft.semantics.StaticSemantics.IsConstantDeclaration;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.objectweb.asm.Type;

import com.github.anba.es6draft.ast.Declaration;
import com.github.anba.es6draft.ast.FunctionDeclaration;
import com.github.anba.es6draft.ast.GeneratorDeclaration;
import com.github.anba.es6draft.compiler.InstructionVisitor.MethodDesc;
import com.github.anba.es6draft.compiler.InstructionVisitor.MethodType;

/**
 * <h1>10 Executable Code and Execution Contexts</h1><br>
 * <h2>10.5 Declaration Binding Instantiation</h2>
 * <ul>
 * <li>10.5.4 Block Declaration Instantiation
 * </ul>
 */
class BlockDeclarationInstantiationGenerator extends DeclarationBindingInstantiationGenerator {
    private static class Methods {
        // class: LexicalEnvironment
        static final MethodDesc LexicalEnvironment_getEnvRec = MethodDesc.create(
                MethodType.Virtual, Types.LexicalEnvironment, "getEnvRec",
                Type.getMethodType(Types.EnvironmentRecord));
    }

    BlockDeclarationInstantiationGenerator(CodeGenerator codegen) {
        super(codegen);
    }

    /**
     * stack: [env] -> [env]
     */
    void generate(Collection<Declaration> declarations, StatementVisitor mv) {
        /* steps 1-2 */
        List<Declaration> functionsToInitialize = new ArrayList<>();

        // stack: [env] -> [env, envRec]
        mv.dup();
        mv.invoke(Methods.LexicalEnvironment_getEnvRec);

        /* step 3 */
        for (Declaration d : declarations) {
            for (String dn : BoundNames(d)) {
                mv.dup();
                if (IsConstantDeclaration(d)) {
                    // FIXME: spec bug (CreateImmutableBinding concrete method of `env`)
                    createImmutableBinding(dn, mv);
                } else {
                    // FIXME: spec bug (CreateMutableBinding concrete method of `env`)
                    createMutableBinding(dn, false, mv);
                }
            }
            if (d instanceof FunctionDeclaration || d instanceof GeneratorDeclaration) {
                functionsToInitialize.add(d);
            }
        }

        // stack: [env, envRec] -> [envRec, env]
        mv.swap();

        /* step 4 */
        for (Declaration f : functionsToInitialize) {
            String fn = BoundName(f);

            // stack: [envRec, env] -> [envRec, env, envRec, env, cx]
            mv.dup2();
            mv.loadExecutionContext();

            // stack: [envRec, env, envRec, env, cx] -> [envRec, env, envRec, fo]
            if (f instanceof FunctionDeclaration) {
                InstantiateFunctionObject((FunctionDeclaration) f, mv);
            } else {
                InstantiateGeneratorObject((GeneratorDeclaration) f, mv);
            }

            // stack: [envRec, env, envRec, fo] -> [envRec, env]
            initialiseBinding(fn, mv);
        }

        // stack: [envRec, env] -> [env]
        mv.swap();
        mv.pop();
    }
}<commit_msg>Avoid unnecessary swap instructions when 'functionsToInitialize' is empty<commit_after>/**
 * Copyright (c) 2012-2013 <NAME>
 * Alle Rechte vorbehalten / All Rights Reserved.  Use is subject to license terms.
 *
 * <https://github.com/anba/es6draft>
 */
package com.github.anba.es6draft.compiler;

import static com.github.anba.es6draft.semantics.StaticSemantics.BoundNames;
import static com.github.anba.es6draft.semantics.StaticSemantics.IsConstantDeclaration;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.objectweb.asm.Type;

import com.github.anba.es6draft.ast.Declaration;
import com.github.anba.es6draft.ast.FunctionDeclaration;
import com.github.anba.es6draft.ast.GeneratorDeclaration;
import com.github.anba.es6draft.compiler.InstructionVisitor.MethodDesc;
import com.github.anba.es6draft.compiler.InstructionVisitor.MethodType;

/**
 * <h1>10 Executable Code and Execution Contexts</h1><br>
 * <h2>10.5 Declaration Binding Instantiation</h2>
 * <ul>
 * <li>10.5.4 Block Declaration Instantiation
 * </ul>
 */
class BlockDeclarationInstantiationGenerator extends DeclarationBindingInstantiationGenerator {
    private static class Methods {
        // class: LexicalEnvironment
        static final MethodDesc LexicalEnvironment_getEnvRec = MethodDesc.create(
                MethodType.Virtual, Types.LexicalEnvironment, "getEnvRec",
                Type.getMethodType(Types.EnvironmentRecord));
    }

    BlockDeclarationInstantiationGenerator(CodeGenerator codegen) {
        super(codegen);
    }

    /**
     * stack: [env] -> [env]
     */
    void generate(Collection<Declaration> declarations, StatementVisitor mv) {
        /* steps 1-2 */
        List<Declaration> functionsToInitialize = new ArrayList<>();

        // stack: [env] -> [env, envRec]
        mv.dup();
        mv.invoke(Methods.LexicalEnvironment_getEnvRec);

        /* step 3 */
        for (Declaration d : declarations) {
            for (String dn : BoundNames(d)) {
                mv.dup();
                if (IsConstantDeclaration(d)) {
                    // FIXME: spec bug (CreateImmutableBinding concrete method of `env`)
                    createImmutableBinding(dn, mv);
                } else {
                    // FIXME: spec bug (CreateMutableBinding concrete method of `env`)
                    createMutableBinding(dn, false, mv);
                }
            }
            if (d instanceof FunctionDeclaration || d instanceof GeneratorDeclaration) {
                functionsToInitialize.add(d);
            }
        }

        if (!functionsToInitialize.isEmpty()) {
            // stack: [env, envRec] -> [envRec, env]
            mv.swap();

            /* step 4 */
            for (Declaration f : functionsToInitialize) {
                String fn = BoundName(f);

                // stack: [envRec, env] -> [envRec, env, envRec, env, cx]
                mv.dup2();
                mv.loadExecutionContext();

                // stack: [envRec, env, envRec, env, cx] -> [envRec, env, envRec, fo]
                if (f instanceof FunctionDeclaration) {
                    InstantiateFunctionObject((FunctionDeclaration) f, mv);
                } else {
                    InstantiateGeneratorObject((GeneratorDeclaration) f, mv);
                }

                // stack: [envRec, env, envRec, fo] -> [envRec, env]
                initialiseBinding(fn, mv);
            }

            // stack: [envRec, env] -> [env]
            mv.swap();
        }

        mv.pop();
    }
}
{'fraction_non_alphanumeric': 0.1132840793857743, 'fraction_numerical': 0.010140518615094886, 'mean_word_length': 2.268939393939394, 'pattern_counts': {'":': 0, '<': 29, '<?xml version=': 0, '>': 43, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2502430', 'n_tokens_mistral': 2002, 'n_tokens_neox': 1885, 'n_words': 421}