public Accessor optimizeSetAccessor(ParserContext pCtx, char[] property, int start, int offset, Object ctx,
                                      Object thisRef, VariableResolverFactory factory, boolean rootThisRef,
                                      Object value, Class ingressType) {
    this.expr = property;
    this.start = this.cursor = start;
    this.end = start + offset;
    this.length = start + offset;

    this.first = true;
    this.ingressType = ingressType;

    compiledInputs = new ArrayList<ExecutableStatement>();

    this.pCtx = pCtx;
    this.ctx = ctx;
    this.thisRef = thisRef;
    this.variableFactory = factory;

    char[] root = null;

    PropertyVerifier verifier = new PropertyVerifier(property, this.pCtx = pCtx);

    int split = findLastUnion();

    if (split != -1) {
      root = subset(property, 0, split);
    }

    AccessorNode rootAccessor = null;

    _initJIT2();

    if (root != null) {
      int _length = this.length;
      int _end = this.end;
      char[] _expr = this.expr;

      this.length = end = (this.expr = root).length;

      // run the compiler but don't finish building.
      deferFinish = true;
      noinit = true;

      compileAccessor();
      ctx = this.val;

      this.expr = _expr;
      this.cursor = start + root.length + 1;
      this.length = _length - root.length - 1;
      this.end = this.cursor + this.length;
    }
    else {
      assert debug("ALOAD 1");
      mv.visitVarInsn(ALOAD, 1);
    }

    try {

      skipWhitespace();

      if (collection) {
        int st = cursor;
        whiteSpaceSkip();

        if (st == end)
          throw new PropertyAccessException("unterminated '['", expr, start, pCtx);

        if (scanTo(']'))
          throw new PropertyAccessException("unterminated '['", expr, start, pCtx);

        String ex = new String(expr, st, cursor - st).trim();

        assert debug("CHECKCAST " + ctx.getClass().getName());
        mv.visitTypeInsn(CHECKCAST, getInternalName(ctx.getClass()));


        if (ctx instanceof Map) {
          if (MVEL.COMPILER_OPT_ALLOW_OVERRIDE_ALL_PROPHANDLING && hasPropertyHandler(Map.class)) {
            propHandlerByteCodePut(ex, ctx, Map.class, value);
          }
          else {
            //noinspection unchecked
            ((Map) ctx).put(eval(ex, ctx, variableFactory), convert(value, returnType = verifier.analyze()));

            writeLiteralOrSubexpression(subCompileExpression(ex.toCharArray(), pCtx));

            assert debug("ALOAD 4");
            mv.visitVarInsn(ALOAD, 4);

            if (value != null && returnType != value.getClass()) {
              dataConversion(returnType);
              checkcast(returnType);
            }

            assert debug("INVOKEINTERFACE Map.put");
            mv.visitMethodInsn(INVOKEINTERFACE, "java/util/Map", "put",
                "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");

            assert debug("POP");
            mv.visitInsn(POP);

            assert debug("ALOAD 4");
            mv.visitVarInsn(ALOAD, 4);
          }
        }
        else if (ctx instanceof List) {
          if (MVEL.COMPILER_OPT_ALLOW_OVERRIDE_ALL_PROPHANDLING && hasPropertyHandler(List.class)) {
            propHandlerByteCodePut(ex, ctx, List.class, value);
          }
          else {
            //noinspection unchecked
            ((List) ctx).set(eval(ex, ctx, variableFactory, Integer.class),
                convert(value, returnType = verifier.analyze()));

            writeLiteralOrSubexpression(subCompileExpression(ex.toCharArray(), pCtx));
            unwrapPrimitive(int.class);

            assert debug("ALOAD 4");
            mv.visitVarInsn(ALOAD, 4);

            if (value != null && !value.getClass().isAssignableFrom(returnType)) {
              dataConversion(returnType);
              checkcast(returnType);
            }

            assert debug("INVOKEINTERFACE List.set");
            mv.visitMethodInsn(INVOKEINTERFACE, "java/util/List", "set", "(ILjava/lang/Object;)Ljava/lang/Object;");

            assert debug("ALOAD 4");
            mv.visitVarInsn(ALOAD, 4);
          }
        }
        else if (MVEL.COMPILER_OPT_ALLOW_OVERRIDE_ALL_PROPHANDLING && hasPropertyHandler(ctx.getClass())) {
          propHandlerByteCodePut(ex, ctx, ctx.getClass(), value);
        }
        else if (ctx.getClass().isArray()) {
          if (MVEL.COMPILER_OPT_ALLOW_OVERRIDE_ALL_PROPHANDLING && hasPropertyHandler(Array.class)) {
            propHandlerByteCodePut(ex, ctx, Array.class, value);
          }
          else {
            Class type = getBaseComponentType(ctx.getClass());

            Object idx = eval(ex, ctx, variableFactory);

            writeLiteralOrSubexpression(subCompileExpression(ex.toCharArray(), pCtx), int.class);
            if (!(idx instanceof Integer)) {
              dataConversion(Integer.class);
              idx = DataConversion.convert(idx, Integer.class);
              unwrapPrimitive(int.class);
            }

            assert debug("ALOAD 4");
            mv.visitVarInsn(ALOAD, 4);

            if (type.isPrimitive()) unwrapPrimitive(type);
            else if (!type.equals(value.getClass())) {
              dataConversion(type);
            }

            arrayStore(type);

            //noinspection unchecked
            Array.set(ctx, (Integer) idx, convert(value, type));

            assert debug("ALOAD 4");
            mv.visitVarInsn(ALOAD, 4);
          }
        }
        else {
          throw new PropertyAccessException("cannot bind to collection property: " + new String(expr)
              + ": not a recognized collection type: " + ctx.getClass(), expr, start, pCtx);
        }

        deferFinish = false;
        noinit = false;

        _finishJIT();

        try {
          deferFinish = false;
          return _initializeAccessor();
        }
        catch (Exception e) {
          throw new CompileException("could not generate accessor", expr, start, e);
        }
      }

      String tk = new String(expr, this.cursor, this.length);
      Member member = getFieldOrWriteAccessor(ctx.getClass(), tk, value == null ? null : ingressType);

      if (GlobalListenerFactory.hasSetListeners()) {
        mv.visitVarInsn(ALOAD, 1);
        mv.visitLdcInsn(tk);
        mv.visitVarInsn(ALOAD, 3);
        mv.visitVarInsn(ALOAD, 4);
        mv.visitMethodInsn(INVOKESTATIC, NAMESPACE + "integration/GlobalListenerFactory",
            "notifySetListeners", "(Ljava/lang/Object;Ljava/lang/String;L" + NAMESPACE
            + "integration/VariableResolverFactory;Ljava/lang/Object;)V");

        GlobalListenerFactory.notifySetListeners(ctx, tk, variableFactory, value);
      }

      if (member instanceof Field) {
        checkcast(ctx.getClass());

        Field fld = (Field) member;

        Label jmp = null;
        Label jmp2 = new Label();

        if (fld.getType().isPrimitive()) {
          assert debug("ASTORE 5");
          mv.visitVarInsn(ASTORE, 5);

          assert debug("ALOAD 4");
          mv.visitVarInsn(ALOAD, 4);

          if (value == null) value = PropertyTools.getPrimitiveInitialValue(fld.getType());

          jmp = new Label();
          assert debug("IFNOTNULL jmp");
          mv.visitJumpInsn(IFNONNULL, jmp);

          assert debug("ALOAD 5");
          mv.visitVarInsn(ALOAD, 5);

          assert debug("ICONST_0");
          mv.visitInsn(ICONST_0);

          assert debug("PUTFIELD " + getInternalName(fld.getDeclaringClass()) + "." + tk);
          mv.visitFieldInsn(PUTFIELD, getInternalName(fld.getDeclaringClass()), tk, getDescriptor(fld.getType()));

          assert debug("GOTO jmp2");
          mv.visitJumpInsn(GOTO, jmp2);

          assert debug("jmp:");
          mv.visitLabel(jmp);

          assert debug("ALOAD 5");
          mv.visitVarInsn(ALOAD, 5);

          assert debug("ALOAD 4");
          mv.visitVarInsn(ALOAD, 4);

          unwrapPrimitive(fld.getType());
        }
        else {
          assert debug("ALOAD 4");
          mv.visitVarInsn(ALOAD, 4);
          checkcast(fld.getType());
        }

        if (jmp == null && value != null && !fld.getType().isAssignableFrom(value.getClass())) {
          if (!canConvert(fld.getType(), value.getClass())) {
            throw new CompileException("cannot convert type: "
                + value.getClass() + ": to " + fld.getType(), expr, start);
          }

          dataConversion(fld.getType());
          fld.set(ctx, convert(value, fld.getType()));
        }
        else {
          fld.set(ctx, value);
        }

        assert debug("PUTFIELD " + getInternalName(fld.getDeclaringClass()) + "." + tk);
        mv.visitFieldInsn(PUTFIELD, getInternalName(fld.getDeclaringClass()), tk, getDescriptor(fld.getType()));

        assert debug("jmp2:");
        mv.visitLabel(jmp2);

        assert debug("ALOAD 4");
        mv.visitVarInsn(ALOAD, 4);

      }
      else if (member != null) {
        assert debug("CHECKCAST " + getInternalName(ctx.getClass()));
        mv.visitTypeInsn(CHECKCAST, getInternalName(ctx.getClass()));

        Method meth = (Method) member;

        assert debug("ALOAD 4");
        mv.visitVarInsn(ALOAD, 4);

        Class targetType = meth.getParameterTypes()[0];

        Label jmp;
        Label jmp2 = new Label();
        if (value != null && !targetType.isAssignableFrom(value.getClass())) {
          if (!canConvert(targetType, value.getClass())) {
            throw new CompileException("cannot convert type: "
                + value.getClass() + ": to " + meth.getParameterTypes()[0], expr, start);
          }

          dataConversion(getWrapperClass(targetType));
          if (targetType.isPrimitive()) {
            unwrapPrimitive(targetType);
          }
          else checkcast(targetType);
          meth.invoke(ctx, convert(value, meth.getParameterTypes()[0]));
        }
        else {
          if (targetType.isPrimitive()) {

            if (value == null) value = PropertyTools.getPrimitiveInitialValue(targetType);

            jmp = new Label();
            assert debug("IFNOTNULL jmp");
            mv.visitJumpInsn(IFNONNULL, jmp);

            assert debug("ICONST_0");
            mv.visitInsn(ICONST_0);

            assert debug("INVOKEVIRTUAL " + getInternalName(meth.getDeclaringClass()) + "." + meth.getName());
            mv.visitMethodInsn(INVOKEVIRTUAL, getInternalName(meth.getDeclaringClass()), meth.getName(),
                getMethodDescriptor(meth));

            assert debug("GOTO jmp2");
            mv.visitJumpInsn(GOTO, jmp2);

            assert debug("jmp:");
            mv.visitLabel(jmp);

            assert debug("ALOAD 4");
            mv.visitVarInsn(ALOAD, 4);

            unwrapPrimitive(targetType);
          }
          else {
            checkcast(targetType);
          }

          meth.invoke(ctx, value);
        }

        assert debug("INVOKEVIRTUAL " + getInternalName(meth.getDeclaringClass()) + "." + meth.getName());
        mv.visitMethodInsn(INVOKEVIRTUAL, getInternalName(meth.getDeclaringClass()), meth.getName(),
            getMethodDescriptor(meth));

        assert debug("jmp2:");
        mv.visitLabel(jmp2);

        assert debug("ALOAD 4");
        mv.visitVarInsn(ALOAD, 4);
      }
      else if (ctx instanceof Map) {
        assert debug("CHECKCAST " + getInternalName(ctx.getClass()));
        mv.visitTypeInsn(CHECKCAST, getInternalName(ctx.getClass()));

        assert debug("LDC '" + tk + "'");
        mv.visitLdcInsn(tk);

        assert debug("ALOAD 4");
        mv.visitVarInsn(ALOAD, 4);

        assert debug("INVOKEINTERFACE java/util/Map.put");
        mv.visitMethodInsn(INVOKEINTERFACE, "java/util/Map", "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");

        assert debug("ALOAD 4");
        mv.visitVarInsn(ALOAD, 4);

        //noinspection unchecked
        ((Map) ctx).put(tk, value);
      }
      else {
        throw new PropertyAccessException("could not access property (" + tk + ") in: "
            + ingressType.getName(), expr, start, pCtx);
      }
    }
    catch (InvocationTargetException e) {
      throw new PropertyAccessException("could not access property", expr, start, e, pCtx);
    }
    catch (IllegalAccessException e) {
      throw new PropertyAccessException("could not access property", expr, start, e, pCtx);
    }

    try {
      deferFinish = false;
      noinit = false;

      _finishJIT();
      return _initializeAccessor();
    }
    catch (Exception e) {

      throw new CompileException("could not generate accessor", expr, start, e);
    }
  }