private void beginInit() {
    ClassVisitor cv = getClassVisitor();

    initMethod = new SkinnyMethodAdapter(cv, ACC_PUBLIC, "<init>", sig(Void.TYPE), null, null);
    initMethod.start();
    initMethod.aload(THIS);
    initMethod.invokespecial(p(AbstractScript.class), "<init>", sig(Void.TYPE));

    // JRUBY-3014: make __FILE__ dynamically determined at load time, but
    // we provide a reasonable default here
    initMethod.aload(THIS);
    initMethod.ldc(getSourcename());
    initMethod.putfield(getClassname(), "filename", ci(String.class));
  }
  public void endScript(boolean generateLoad, boolean generateMain) {
    // add Script#run impl, used for running this script with a specified threadcontext and self
    // root method of a script is always in __file__ method
    String methodName = "__file__";

    String loadSig = sig(IRubyObject.class, ThreadContext.class, IRubyObject.class, boolean.class);

    if (generateLoad || generateMain) {
      // the load method is used for loading as a top-level script, and prepares appropriate scoping
      // around the code
      SkinnyMethodAdapter method =
          new SkinnyMethodAdapter(getClassVisitor(), ACC_PUBLIC, "load", loadSig, null, null);
      method.start();

      // invoke __file__ with threadcontext, self, args (null), and block (null)
      Label tryBegin = new Label();
      Label tryFinally = new Label();

      method.label(tryBegin);
      method.aload(THREADCONTEXT_INDEX);
      String scopeNames = Helpers.encodeScope(topLevelScope);
      method.ldc(scopeNames);
      method.iload(SELF_INDEX + 1);
      method.invokestatic(
          p(Helpers.class),
          "preLoad",
          sig(StaticScope.class, ThreadContext.class, String.class, boolean.class));

      // store root scope
      method.aload(THIS);
      method.swap();
      method.invokevirtual(
          p(AbstractScript.class), "setRootScope", sig(void.class, StaticScope.class));

      method.aload(THIS);
      method.aload(THREADCONTEXT_INDEX);
      method.aload(SELF_INDEX);
      method.getstatic(p(IRubyObject.class), "NULL_ARRAY", ci(IRubyObject[].class));
      method.getstatic(p(Block.class), "NULL_BLOCK", ci(Block.class));

      method.invokestatic(getClassname(), methodName, getStaticMethodSignature(getClassname(), 4));
      method.aload(THREADCONTEXT_INDEX);
      method.invokestatic(p(Helpers.class), "postLoad", sig(void.class, ThreadContext.class));
      method.areturn();

      method.label(tryFinally);
      method.aload(THREADCONTEXT_INDEX);
      method.invokestatic(p(Helpers.class), "postLoad", sig(void.class, ThreadContext.class));
      method.athrow();

      method.trycatch(tryBegin, tryFinally, tryFinally, null);

      method.end();
    }

    if (generateMain) {
      // add main impl, used for detached or command-line execution of this script with a new
      // runtime
      // root method of a script is always in stub0, method0
      SkinnyMethodAdapter method =
          new SkinnyMethodAdapter(
              getClassVisitor(),
              ACC_PUBLIC | ACC_STATIC,
              "main",
              sig(Void.TYPE, params(String[].class)),
              null,
              null);
      method.start();

      // init script filename to simple class name in case we don't assign it (null ClassLoader)
      method.ldc(getClassname().replaceAll("\\\\.", "/"));
      method.astore(1);

      // new instance to invoke run against
      method.newobj(getClassname());
      method.dup();
      method.invokespecial(getClassname(), "<init>", sig(Void.TYPE));

      // guard against null classloader
      method.ldc(Type.getType("L" + getClassname() + ";"));
      method.invokevirtual(p(Class.class), "getClassLoader", sig(ClassLoader.class));
      Label skip = new Label();
      method.ifnull(skip);

      // set filename for the loaded script class (JRUBY-4825)
      method.dup();
      method.ldc(Type.getType("L" + getClassname() + ";"));
      method.invokevirtual(p(Class.class), "getClassLoader", sig(ClassLoader.class));
      method.ldc(getClassname() + ".class");
      method.invokevirtual(p(ClassLoader.class), "getResource", sig(URL.class, String.class));
      method.invokevirtual(p(Object.class), "toString", sig(String.class));
      method.astore(1);
      method.aload(1);
      method.invokevirtual(p(AbstractScript.class), "setFilename", sig(void.class, String.class));

      // ifnull ClassLoader
      method.label(skip);

      // instance config for the script run
      method.newobj(p(RubyInstanceConfig.class));
      method.dup();
      method.invokespecial(p(RubyInstanceConfig.class), "<init>", "()V");

      // set argv from main's args
      method.dup();
      method.aload(0);
      method.invokevirtual(p(RubyInstanceConfig.class), "setArgv", sig(void.class, String[].class));

      // set script filename ($0)
      method.dup();
      method.aload(1);
      method.invokevirtual(
          p(RubyInstanceConfig.class), "setScriptFileName", sig(void.class, String.class));

      // invoke run with threadcontext and topself
      method.invokestatic(p(Ruby.class), "newInstance", sig(Ruby.class, RubyInstanceConfig.class));
      method.dup();

      method.invokevirtual(RUBY, "getCurrentContext", sig(ThreadContext.class));
      method.swap();
      method.invokevirtual(RUBY, "getTopSelf", sig(IRubyObject.class));
      method.ldc(false);

      method.invokevirtual(getClassname(), "load", loadSig);
      method.voidreturn();
      method.end();
    }

    getCacheCompiler().finish();

    endInit();
    endClassInit();
  }