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 18 void 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