docs: 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) {
              // 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();
              }
  
              List<Node> 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);
              }
          }
  
          // Compile RegExp literals if this is a script. For functions
          // this is performed during instantiation in functionInit
          if (fnCurrent == null && scriptOrFn.getRegexpCount() != 0) {
              cfw.addALoad(contextLocal);
              cfw.addInvoke(ByteCode.INVOKESTATIC, codegen.mainClassName,
                            Codegen.REGEXP_INIT_METHOD_NAME,
                            Codegen.REGEXP_INIT_METHOD_SIGNATURE);
          }
  
          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;
          boolean isArrow = false;
          if (scriptOrFn instanceof FunctionNode) {
              isArrow = ((FunctionNode)scriptOrFn).getFunctionType() == FunctionNode.ARROW_FUNCTION;
          }
          if (fnCurrent != null) {
              debugVariableName = "activation";
              cfw.addALoad(funObjLocal);
              cfw.addALoad(variableObjectLocal);
              cfw.addALoad(argsLocal);
              String methodName = isArrow ? "createArrowFunctionActivation" : "createFunctionActivation";
              cfw.addPush(scriptOrFn.isInStrictMode());
              addScriptRuntimeInvoke(methodName,
                                     "(Lorg/mozilla/javascript/NativeFunction;"
                                     +"Lorg/mozilla/javascript/Scriptable;"
                                     +"[Ljava/lang/Object;"
                                     +"Z"
                                     +")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);
              }
          }
      }