PERF: ffill/bfill with non-numpy dtypes
Implement ffill/bfill in terms of 'take', avoiding an object cast.

```
ser = pd.Series(range(10**5), dtype="int64[pyarrow]")
ser[5000] = pd.NA

%timeit ser.ffill()
609 µs ± 25.9 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)  # <- branch
5.49 ms ± 158 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)  # <- main
```

Some of the perf difference is likely due to no longer issuing a PerformanceWarning.
thx @jbrockmendel 