1/*
2 *  Copyright (c) 2010 The WebM project authors. All Rights Reserved.
3 *
4 *  Use of this source code is governed by a BSD-style license
5 *  that can be found in the LICENSE file in the root of the source
6 *  tree. An additional intellectual property rights grant can be found
7 *  in the file PATENTS.  All contributing project authors may
8 *  be found in the AUTHORS file in the root of the source tree.
9 */
10
11
12/* This code is in the public domain.
13** Version: 1.1  Author: Walt Karas
14*/
15
16#include "hmm_intrnl.h"
17
18void U(shrink_chunk)(U(descriptor) *desc, U(size_bau) n_baus_to_shrink)
19{
20    head_record *dummy_end_block = (head_record *)
21                                   BAUS_BACKWARD(desc->end_of_shrinkable_chunk, DUMMY_END_BLOCK_BAUS);
22
23#ifdef HMM_AUDIT_FAIL
24
25    if (dummy_end_block->block_size != 0)
26        /* Chunk does not have valid dummy end block. */
27        HMM_AUDIT_FAIL
28
29#endif
30
31        if (n_baus_to_shrink)
32        {
33            head_record *last_block = (head_record *)
34                                      BAUS_BACKWARD(
35                                          dummy_end_block, dummy_end_block->previous_block_size);
36
37#ifdef HMM_AUDIT_FAIL
38            AUDIT_BLOCK(last_block)
39#endif
40
41            if (last_block == desc->last_freed)
42            {
43                U(size_bau) bs = BLOCK_BAUS(last_block);
44
45                /* Chunk will not be shrunk out of existence if
46                ** 1.  There is at least one allocated block in the chunk
47                **     and the amount to shrink is exactly the size of the
48                **     last block, OR
49                ** 2.  After the last block is shrunk, there will be enough
50                **     BAUs left in it to form a minimal size block. */
51                int chunk_will_survive =
52                    (PREV_BLOCK_BAUS(last_block) && (n_baus_to_shrink == bs)) ||
53                    (n_baus_to_shrink <= (U(size_bau))(bs - MIN_BLOCK_BAUS));
54
55                if (chunk_will_survive ||
56                    (!PREV_BLOCK_BAUS(last_block) &&
57                     (n_baus_to_shrink ==
58                      (U(size_bau))(bs + DUMMY_END_BLOCK_BAUS))))
59                {
60                    desc->last_freed = 0;
61
62                    if (chunk_will_survive)
63                    {
64                        bs -= n_baus_to_shrink;
65
66                        if (bs)
67                        {
68                            /* The last (non-dummy) block was not completely
69                            ** eliminated by the shrink. */
70
71                            last_block->block_size = bs;
72
73                            /* Create new dummy end record.
74                            */
75                            dummy_end_block =
76                                (head_record *) BAUS_FORWARD(last_block, bs);
77                            dummy_end_block->previous_block_size = bs;
78                            dummy_end_block->block_size = 0;
79
80#ifdef HMM_AUDIT_FAIL
81
82                            if (desc->avl_tree_root)
83                                AUDIT_BLOCK(PTR_REC_TO_HEAD(desc->avl_tree_root))
84#endif
85
86                                U(into_free_collection)(desc, last_block);
87                        }
88                        else
89                        {
90                            /* The last (non-dummy) block was completely
91                            ** eliminated by the shrink.  Make its head
92                            ** the new dummy end block.
93                            */
94                            last_block->block_size = 0;
95                            last_block->previous_block_size &= ~HIGH_BIT_BAU_SIZE;
96                        }
97                    }
98                }
99
100#ifdef HMM_AUDIT_FAIL
101                else
102                    HMM_AUDIT_FAIL
103#endif
104                }
105
106#ifdef HMM_AUDIT_FAIL
107            else
108                HMM_AUDIT_FAIL
109#endif
110            }
111}
112