In an earlier life I worked on an object-oriented operating system based around reference counting, called intent (you won't have heard of it), and it was horrible. One of the major issues with refcounting is that when you dereference an object, it may be freed then and there... which dereferences any dependent objects... which may be freed... which dereference more objects, etc. So any time you dereference your object, you may end up doing an arbitrary amount of work, which isn't good for real-time performance.
You can usually avoid this by being sensible about when you reference and dereference objects, but now you're effectively doing manual memory management, which slightly defeats the whole point of the exercise.
In our case, we also cocked things up with poor design --- we ended up reffing and dereffing objects a lot, which meant we constantly ran into issues where we needed to deref an object with a lock held, which isn't a good idea. A better designed system wouldn't have done this. Objective C's memory pools work very well: whenever you create an object it gets added to a list, and all objects on the list are dereffed when your app exits to the event loop; so not only do you only need to manually ref objects if you want to keep them until the next event, which is much easier to code for, but the object free overhead all happens at a well-defined point which is usually app idle time.
So while reference counting can help, it still doesn't make the problem go away, and when you're using it you have to remember that you are using it and ensure that your app is designed to cope.
(It's also worth remembering that modern incremental garbage collectors solve the same problem in a different way, and without some of refcounting's problems.)
That is why python will occasionally run a mark and sweep GC even though it says it uses reference counting.
Circular references aren't easy to avoid, sometimes there can be more than 3 levels of indirection. The mental overhead of preventing circular references is often times as high as manually managing memory yourself.
If it was as good as you suggest, every new language would be using reference counting and not occasionally run mark and sweep.
As such, Squirrel enjoys some popularity as (and was indeed created to serve as, by an engineer that had grown frustrated with the experience of embedding Lua in FarCry) a scripting language for video games, being most notably used in some of Valve's newer games, like Left 4 Dead 2, Portal 2, and CS:GO. The rest of the engine code usually dwarves the performance impact of "scripts" in most games, but GC scans can still cause games embedding other scripting languages to miss a frame presentation deadline, resulting in either a nasty tear or a completely missed frame. There are ways that tracing garbage collected languages can attempt to combat this (like incremental GCs), but some engine programmers have decided to accept the throughput cost for the peace of mind that reference counting provides.
EDIT: I had more but HN is silently ignoring some of my edits for some reason. Is there a post length restriction for new users, or have I tripped some kind of bizarre content filter?