There are several improvements to make:
First, the methods that perform ACL checks in the JcrSession (or AbstractJcrNode eventually get to the AccessControlManagerImpl class, but then to check the ACL permissions that code walks up the parent and calls methods on the parent node. These calls eventually get back the AccessControlManagerImpl class, and this continues until we get to the root. Ideally, all of the ACL checking should be performed within the AccessControlManagerImpl class and should use the CachedNode interfaces to access any persisted information.
Secondly, we could add a method to the CachedNode interface (and implementations) that tracks whether the node even has an ACL child, and this will be kept in the cache as long as the CachedNode. Doing this will make the logic in the AccessControlManagerImpl more efficient for any already-cached nodes – presuming that most nodes will not have an ACL child.
Thirdly, we may want to track in the Session which nodes the session knows it has access to. This may be practical only for READ, but other actions could easily just check. For example, when looking for READ permission, if we could ensure that we only hydrate a JCR Node instance for only those nodes that the session can read, then we'd know immediately if the JCR Node exists then it already has READ permission.