code: public Variable acquireExtra(Type type) {
          Validate.notNull(type);
          Validate.isTrue(type.getSort() != Type.VOID);
          Validate.isTrue(type.getSort() != Type.METHOD);
          
          for (Variable var : extraVars) {
              if (!var.used && var.type.equals(type)) {
                  // We don't want to return the same object because other objects that may still have the existing Variable will now have
                  // them marked as being usable again. Do not want that to be the case. So instead create a new object and return that.
                  extraVars.remove(var);
                  var = new Variable(type, var.index, true);
                  extraVars.add(var);
                  return var;
              }
          }
          
          // Remember that LONG and DOUBLE primitives take up 2 LVT slots (and 2 operand stack slots) -- that's why sometimes we add 2
          int extraSlotLen = (int) extraVars.stream()
                  .mapToInt(x -> x.type.equals(LONG_TYPE) || x.type.equals(DOUBLE_TYPE) ? 2 : 1)
                  .sum();
          Variable var = new Variable(type, extraOffset + extraSlotLen, true);
          extraVars.add(var);
          return var;
      }
docs: Acquire a new variable for use when instrumenting some code within the method this {@link VariableTable} is for.
  @param type type which variable is for
  @return new variable
  @throws NullPointerException if any argument is {@code null}
  @throws IllegalArgumentException if {@code type} is of sort of {@link Type#VOID} or {@link Type#METHOD}