private boolean executeInstructions(
      Map<Integer, Object> staticRegs,
      MethodBody body,
      ABC abc,
      AVM2Code code,
      LocalDataArea localData,
      int idx,
      int endIdx,
      ExecutionResult result,
      AVM2Instruction inlineIns)
      throws InterruptedException {
    int instructionsProcessed = 0;

    FixItemCounterStack stack = (FixItemCounterStack) localData.operandStack;
    Set<Long> refs = code.getImportantOffsets(body);
    boolean modified = false;
    while (true) {
      if (idx > endIdx) {
        break;
      }

      if (instructionsProcessed > executionLimit) {
        break;
      }

      AVM2Instruction ins = code.code.get(idx);
      if (instructionsProcessed > 0 && refs.contains(ins.getOffset())) {
        break;
      }

      modified = modified | code.inlineJumpExit();
      InstructionDefinition def = ins.definition;
      if (inlineIns == ins) {
        if (def instanceof SetLocalTypeIns) {
          int regId = ((SetLocalTypeIns) def).getRegisterId(ins);
          staticRegs.put(regId, localData.localRegisters.get(regId));
          code.replaceInstruction(
              idx, new AVM2Instruction(0, DeobfuscatePopIns.getInstance(), null), body);
          modified = true;
        }
      }
      if (def instanceof GetLocalTypeIns) {
        int regId = ((GetLocalTypeIns) def).getRegisterId(ins);
        if (staticRegs.containsKey(regId)) {
          AVM2Instruction pushins = abc.constants.makePush(staticRegs.get(regId));
          if (pushins == null) {
            break;
          }

          code.replaceInstruction(idx, pushins, body);
          modified = true;
          ins = pushins;
          def = ins.definition;
        }
      }

      if (def instanceof NewFunctionIns
          && idx + 1 < code.code.size()
          && code.code.get(idx + 1).definition instanceof PopIns) {
        code.removeInstruction(idx + 1, body);
        code.removeInstruction(idx, body);
        modified = true;
        continue;
      }

      boolean ok = false;
      // todo: honfika: order by statistics
      if (def.isNotCompileTimeSupported()
          || def instanceof PushByteIns
          || def instanceof PushShortIns
          || def instanceof PushIntIns
          || def instanceof PushDoubleIns
          || def instanceof PushStringIns
          || def instanceof PushNullIns
          || def instanceof PushUndefinedIns
          || def instanceof PushFalseIns
          || def instanceof PushTrueIns
          || def instanceof DupIns
          || def instanceof SwapIns
          || def instanceof AddIns
          || def instanceof AddIIns
          || def instanceof SubtractIns
          || def instanceof SubtractIIns
          || def instanceof ModuloIns
          || def instanceof MultiplyIns
          || def instanceof MultiplyIIns //
          || def instanceof DivideIns //
          || def instanceof BitAndIns
          || def instanceof BitXorIns
          || def instanceof BitOrIns
          || def instanceof LShiftIns
          || def instanceof RShiftIns
          || def instanceof URShiftIns
          || def instanceof EqualsIns
          || def instanceof NotIns
          || def instanceof NegateIns //
          || def instanceof NegateIIns //
          || def instanceof IncrementIns //
          || def instanceof IncrementIIns //
          || def instanceof DecrementIns //
          || def instanceof DecrementIIns //
          || def instanceof IfTypeIns
          || def instanceof JumpIns
          || def instanceof EqualsIns
          || def instanceof LessEqualsIns
          || def instanceof GreaterEqualsIns
          || def instanceof GreaterThanIns
          || def instanceof LessThanIns
          || def instanceof StrictEqualsIns
          || def instanceof PopIns
          || def instanceof GetLocalTypeIns
          || def instanceof SetLocalTypeIns
          || def instanceof NewFunctionIns
          || def instanceof CoerceOrConvertTypeIns) {
        ok = true;
      }

      if (!ok) {
        break;
      }

      if (!(def instanceof NewFunctionIns)) {
        // do not throw EmptyStackException, much faster
        int requiredStackSize = def.getStackPopCount(ins, abc);
        if (stack.size() < requiredStackSize) {
          break;
        }

        if (requiredStackSize > 0 && !def.isNotCompileTimeSupported()) {
          boolean notCompileTime = false;
          for (int i = 0; i < requiredStackSize; i++) {
            if (stack.peek(i + 1) == NotCompileTime.INSTANCE) {
              notCompileTime = true;
              break;
            }
          }

          if (notCompileTime) {
            break;
          }
        }

        if (localData.scopeStack.size() < -def.getScopeStackDelta(ins, abc)) {
          break;
        }

        boolean supported;
        try {
          localData.jump = null;
          supported = def.execute(localData, abc.constants, ins);
        } catch (AVM2ExecutionException ex) {
          supported = false;
        }

        if (!supported) {
          break;
        }
      }

      boolean ifed = false;
      if (def instanceof IfTypeIns && !(def instanceof JumpIns)) {
        long address = ins.getTargetAddress();
        int nidx = code.adr2pos(address);
        AVM2Instruction tarIns = code.code.get(nidx);

        // Some IfType instructions need more than 1 operand, we must pop out all of them
        int stackCount = -def.getStackDelta(ins, abc);

        if (localData.jump != null) {
          // System.err.println("replacing " + ins + " on " + idx + " with jump");
          AVM2Instruction jumpIns = new AVM2Instruction(0, AVM2Instructions.Jump, new int[] {0});
          // jumpIns.operands[0] = ins.operands[0] /*- ins.getBytes().length*/ +
          // jumpIns.getBytes().length;
          code.replaceInstruction(idx, jumpIns, body);
          jumpIns.operands[0] =
              (int) (tarIns.getOffset() - jumpIns.getOffset() - jumpIns.getBytesLength());
          for (int s = 0; s < stackCount; s++) {
            code.insertInstruction(
                idx,
                new AVM2Instruction(ins.getOffset(), DeobfuscatePopIns.getInstance(), null),
                true,
                body);
          }

          idx = code.adr2pos(jumpIns.getTargetAddress());
        } else {
          // System.err.println("replacing " + ins + " on " + idx + " with pop");
          code.replaceInstruction(
              idx,
              new AVM2Instruction(ins.getOffset(), DeobfuscatePopIns.getInstance(), null),
              body);
          for (int s = 1 /*first is replaced*/; s < stackCount; s++) {
            code.insertInstruction(
                idx,
                new AVM2Instruction(ins.getOffset(), DeobfuscatePopIns.getInstance(), null),
                true,
                body);
          }
          // ins.definition = DeobfuscatePopIns.getInstance();
          idx++;
        }

        modified = true;
        ifed = true;
      } else {
        idx++;
      }

      instructionsProcessed++;

      if (result != null && stack.allItemsFixed()) {
        result.idx = idx == code.code.size() ? idx - 1 : idx;
        result.instructionsProcessed = instructionsProcessed;
        result.stack.clear();
        result.stack.addAll(stack);
      }

      if (ifed) {
        break;
      }

      if (localData.jump != null) {
        idx = code.adr2pos(localData.jump);

        if (idx == -1) {
          throw new TranslateException("Jump target not found: " + localData.jump);
        }
      }
    }

    return modified;
  }