private void generatePrologue()
    {
        if (inDirectCallFunction) {
            int directParameterCount = scriptOrFn.getParamCount();
            // 0 is reserved for function Object 'this'
            // 1 is reserved for context
            // 2 is reserved for parentScope
            // 3 is reserved for script 'this'
            if (firstFreeLocal != 4) Kit.codeBug();
            for (int i = 0; i != directParameterCount; ++i) {
                varRegisters[i] = firstFreeLocal;
                // 3 is 1 for Object parm and 2 for double parm
                firstFreeLocal += 3;
            }
            if (!fnCurrent.getParameterNumberContext()) {
                // make sure that all parameters are objects
                itsForcedObjectParameters = true;
                for (int i = 0; i != directParameterCount; ++i) {
                    short reg = varRegisters[i];
                    cfw.addALoad(reg);
                    cfw.add(ByteCode.GETSTATIC,
                            "java/lang/Void",
                            "TYPE",
                            "Ljava/lang/Class;");
                    int isObjectLabel = cfw.acquireLabel();
                    cfw.add(ByteCode.IF_ACMPNE, isObjectLabel);
                    cfw.addDLoad(reg + 1);
                    addDoubleWrap();
                    cfw.addAStore(reg);
                    cfw.markLabel(isObjectLabel);
                }
            }
        }

        if (fnCurrent != null && !inDirectCallFunction
            && (!compilerEnv.isUseDynamicScope()
                || fnCurrent.fnode.getIgnoreDynamicScope()))
        {
            // Unless we're either in a direct call or using dynamic scope,
            // use the enclosing scope of the function as our variable object.
            cfw.addALoad(funObjLocal);
            cfw.addInvoke(ByteCode.INVOKEINTERFACE,
                          "org/mozilla/javascript/Scriptable",
                          "getParentScope",
                          "()Lorg/mozilla/javascript/Scriptable;");
            cfw.addAStore(variableObjectLocal);
        }

        // reserve 'args[]'
        argsLocal = firstFreeLocal++;
        localsMax = firstFreeLocal;

        // Generate Generator specific prelude
        if (isGenerator) {

            // reserve 'args[]'
            operationLocal = firstFreeLocal++;
            localsMax = firstFreeLocal;

            // Local 3 is a reference to a GeneratorState object. The rest
            // of codegen expects local 3 to be a reference to the thisObj.
            // So move the value in local 3 to generatorStateLocal, and load
            // the saved thisObj from the GeneratorState object.
            cfw.addALoad(thisObjLocal);
            generatorStateLocal = firstFreeLocal++;
            localsMax = firstFreeLocal;
            cfw.add(ByteCode.CHECKCAST, OptRuntime.GeneratorState.CLASS_NAME);
            cfw.add(ByteCode.DUP);
            cfw.addAStore(generatorStateLocal);
            cfw.add(ByteCode.GETFIELD,
                    OptRuntime.GeneratorState.CLASS_NAME,
                    OptRuntime.GeneratorState.thisObj_NAME,
                    OptRuntime.GeneratorState.thisObj_TYPE);
            cfw.addAStore(thisObjLocal);
            
            if (epilogueLabel == -1) {
                epilogueLabel = cfw.acquireLabel();
            }

            ArrayList targets = ((FunctionNode)scriptOrFn).getResumptionPoints();
            if (targets != null) {
                // get resumption point
                generateGetGeneratorResumptionPoint();
  
                // generate dispatch table
                generatorSwitch = cfw.addTableSwitch(0,
                    targets.size() + GENERATOR_START);
                generateCheckForThrowOrClose(-1, false, GENERATOR_START);
            }
        }

        if (fnCurrent == null) {
            // See comments in case Token.REGEXP
            if (scriptOrFn.getRegexpCount() != 0) {
                scriptRegexpLocal = getNewWordLocal();
                codegen.pushRegExpArray(cfw, scriptOrFn, contextLocal,
                                        variableObjectLocal);
                cfw.addAStore(scriptRegexpLocal);
            }
        }

        if (compilerEnv.isGenerateObserverCount())
            saveCurrentCodeOffset();

        if (hasVarsInRegs) {
            // No need to create activation. Pad arguments if need be.
            int parmCount = scriptOrFn.getParamCount();
            if (parmCount > 0 && !inDirectCallFunction) {
                // Set up args array
                // check length of arguments, pad if need be
                cfw.addALoad(argsLocal);
                cfw.add(ByteCode.ARRAYLENGTH);
                cfw.addPush(parmCount);
                int label = cfw.acquireLabel();
                cfw.add(ByteCode.IF_ICMPGE, label);
                cfw.addALoad(argsLocal);
                cfw.addPush(parmCount);
                addScriptRuntimeInvoke("padArguments",
                                       "([Ljava/lang/Object;I"
                                       +")[Ljava/lang/Object;");
                cfw.addAStore(argsLocal);
                cfw.markLabel(label);
            }

            int paramCount = fnCurrent.fnode.getParamCount();
            int varCount = fnCurrent.fnode.getParamAndVarCount();
            boolean [] constDeclarations = fnCurrent.fnode.getParamAndVarConst();

            // REMIND - only need to initialize the vars that don't get a value
            // before the next call and are used in the function
            short firstUndefVar = -1;
            for (int i = 0; i != varCount; ++i) {
                short reg = -1;
                if (i < paramCount) {
                    if (!inDirectCallFunction) {
                        reg = getNewWordLocal();
                        cfw.addALoad(argsLocal);
                        cfw.addPush(i);
                        cfw.add(ByteCode.AALOAD);
                        cfw.addAStore(reg);
                    }
                } else if (fnCurrent.isNumberVar(i)) {
                    reg = getNewWordPairLocal(constDeclarations[i]);
                    cfw.addPush(0.0);
                    cfw.addDStore(reg);
                } else {
                    reg = getNewWordLocal(constDeclarations[i]);
                    if (firstUndefVar == -1) {
                        Codegen.pushUndefined(cfw);
                        firstUndefVar = reg;
                    } else {
                        cfw.addALoad(firstUndefVar);
                    }
                    cfw.addAStore(reg);
                }
                if (reg >= 0) {
                    if (constDeclarations[i]) {
                        cfw.addPush(0);
                        cfw.addIStore(reg + (fnCurrent.isNumberVar(i) ? 2 : 1));
                    }
                    varRegisters[i] = reg;
                }

                // Add debug table entry if we're generating debug info
                if (compilerEnv.isGenerateDebugInfo()) {
                    String name = fnCurrent.fnode.getParamOrVarName(i);
                    String type = fnCurrent.isNumberVar(i)
                                      ? "D" : "Ljava/lang/Object;";
                    int startPC = cfw.getCurrentCodeOffset();
                    if (reg < 0) {
                        reg = varRegisters[i];
                    }
                    cfw.addVariableDescriptor(name, type, startPC, reg);
                }
            }

            // Skip creating activation object.
            return;
        }

        // skip creating activation object for the body of a generator. The
        // activation record required by a generator has already been created
        // in generateGenerator().
        if (isGenerator)
            return;


        String debugVariableName;
        if (fnCurrent != null) {
            debugVariableName = "activation";
            cfw.addALoad(funObjLocal);
            cfw.addALoad(variableObjectLocal);
            cfw.addALoad(argsLocal);
            addScriptRuntimeInvoke("createFunctionActivation",
                                   "(Lorg/mozilla/javascript/NativeFunction;"
                                   +"Lorg/mozilla/javascript/Scriptable;"
                                   +"[Ljava/lang/Object;"
                                   +")Lorg/mozilla/javascript/Scriptable;");
            cfw.addAStore(variableObjectLocal);
            cfw.addALoad(contextLocal);
            cfw.addALoad(variableObjectLocal);
            addScriptRuntimeInvoke("enterActivationFunction",
                                   "(Lorg/mozilla/javascript/Context;"
                                   +"Lorg/mozilla/javascript/Scriptable;"
                                   +")V");
        } else {
            debugVariableName = "global";
            cfw.addALoad(funObjLocal);
            cfw.addALoad(thisObjLocal);
            cfw.addALoad(contextLocal);
            cfw.addALoad(variableObjectLocal);
            cfw.addPush(0); // false to indicate it is not eval script
            addScriptRuntimeInvoke("initScript",
                                   "(Lorg/mozilla/javascript/NativeFunction;"
                                   +"Lorg/mozilla/javascript/Scriptable;"
                                   +"Lorg/mozilla/javascript/Context;"
                                   +"Lorg/mozilla/javascript/Scriptable;"
                                   +"Z"
                                   +")V");
        }

        enterAreaStartLabel = cfw.acquireLabel();
        epilogueLabel = cfw.acquireLabel();
        cfw.markLabel(enterAreaStartLabel);

        generateNestedFunctionInits();

        // default is to generate debug info
        if (compilerEnv.isGenerateDebugInfo()) {
            cfw.addVariableDescriptor(debugVariableName,
                    "Lorg/mozilla/javascript/Scriptable;",
                    cfw.getCurrentCodeOffset(), variableObjectLocal);
        }

        if (fnCurrent == null) {
            // OPT: use dataflow to prove that this assignment is dead
            popvLocal = getNewWordLocal();
            Codegen.pushUndefined(cfw);
            cfw.addAStore(popvLocal);

            int linenum = scriptOrFn.getEndLineno();
            if (linenum != -1)
              cfw.addLineNumberEntry((short)linenum);

        } else {
            if (fnCurrent.itsContainsCalls0) {
                itsZeroArgArray = getNewWordLocal();
                cfw.add(ByteCode.GETSTATIC,
                        "org/mozilla/javascript/ScriptRuntime",
                        "emptyArgs", "[Ljava/lang/Object;");
                cfw.addAStore(itsZeroArgArray);
            }
            if (fnCurrent.itsContainsCalls1) {
                itsOneArgArray = getNewWordLocal();
                cfw.addPush(1);
                cfw.add(ByteCode.ANEWARRAY, "java/lang/Object");
                cfw.addAStore(itsOneArgArray);
            }
        }
    }