TreeNode<V> putTreeVal(int h, int k, V v) {
        boolean searched = false;
        for (TreeNode<V> p = root; ; ) {
          int dir, ph;
          if (p == null) {
            first = root = new TreeNode<>(h, k, v, null, null);
            break;
          }
          else if ((ph = p.hash) > h) {
            dir = -1;
          }
          else if (ph < h) {
            dir = 1;
          }
          else if (p.key == k) {
            return p;
          }
          else {
            if (!searched) {
              TreeNode<V> q, ch;
              searched = true;
              if (((ch = p.left) != null &&
                   (q = ch.findTreeNode(h, k)) != null) ||
                  ((ch = p.right) != null &&
                   (q = ch.findTreeNode(h, k)) != null)) {
                return q;
              }
            }
            dir = 0;
          }

          TreeNode<V> xp = p;
          if ((p = (dir <= 0) ? p.left : p.right) == null) {
            TreeNode<V> x, f = first;
            first = x = new TreeNode<>(h, k, v, f, xp);
            if (f != null) {
              f.prev = x;
            }
            if (dir <= 0) {
              xp.left = x;
            }
            else {
              xp.right = x;
            }
            if (!xp.red) {
              x.red = true;
            }
            else {
              lockRoot();
              try {
                root = balanceInsertion(root, x);
              }
              finally {
                unlockRoot();
              }
            }
            break;
          }
        }
        assert checkInvariants(root);
        return null;
      }
TreeNode<V> putTreeVal(int h, int k, V v)