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 U(shrink_chunk)18void U(shrink_chunk)(U(descriptor) *desc, U(size_bau) n_baus_to_shrink) { 19 head_record *dummy_end_block = (head_record *) 20 BAUS_BACKWARD(desc->end_of_shrinkable_chunk, DUMMY_END_BLOCK_BAUS); 21 22 #ifdef HMM_AUDIT_FAIL 23 24 if (dummy_end_block->block_size != 0) 25 /* Chunk does not have valid dummy end block. */ 26 HMM_AUDIT_FAIL 27 28 #endif 29 30 if (n_baus_to_shrink) { 31 head_record *last_block = (head_record *) 32 BAUS_BACKWARD( 33 dummy_end_block, dummy_end_block->previous_block_size); 34 35 #ifdef HMM_AUDIT_FAIL 36 AUDIT_BLOCK(last_block) 37 #endif 38 39 if (last_block == desc->last_freed) { 40 U(size_bau) bs = BLOCK_BAUS(last_block); 41 42 /* Chunk will not be shrunk out of existence if 43 ** 1. There is at least one allocated block in the chunk 44 ** and the amount to shrink is exactly the size of the 45 ** last block, OR 46 ** 2. After the last block is shrunk, there will be enough 47 ** BAUs left in it to form a minimal size block. */ 48 int chunk_will_survive = 49 (PREV_BLOCK_BAUS(last_block) && (n_baus_to_shrink == bs)) || 50 (n_baus_to_shrink <= (U(size_bau))(bs - MIN_BLOCK_BAUS)); 51 52 if (chunk_will_survive || 53 (!PREV_BLOCK_BAUS(last_block) && 54 (n_baus_to_shrink == 55 (U(size_bau))(bs + DUMMY_END_BLOCK_BAUS)))) { 56 desc->last_freed = 0; 57 58 if (chunk_will_survive) { 59 bs -= n_baus_to_shrink; 60 61 if (bs) { 62 /* The last (non-dummy) block was not completely 63 ** eliminated by the shrink. */ 64 65 last_block->block_size = bs; 66 67 /* Create new dummy end record. 68 */ 69 dummy_end_block = 70 (head_record *) BAUS_FORWARD(last_block, bs); 71 dummy_end_block->previous_block_size = bs; 72 dummy_end_block->block_size = 0; 73 74 #ifdef HMM_AUDIT_FAIL 75 76 if (desc->avl_tree_root) 77 AUDIT_BLOCK(PTR_REC_TO_HEAD(desc->avl_tree_root)) 78 #endif 79 80 U(into_free_collection)(desc, last_block); 81 } else { 82 /* The last (non-dummy) block was completely 83 ** eliminated by the shrink. Make its head 84 ** the new dummy end block. 85 */ 86 last_block->block_size = 0; 87 last_block->previous_block_size &= ~HIGH_BIT_BAU_SIZE; 88 } 89 } 90 } 91 92 #ifdef HMM_AUDIT_FAIL 93 else 94 HMM_AUDIT_FAIL 95 #endif 96 } 97 98 #ifdef HMM_AUDIT_FAIL 99 else 100 HMM_AUDIT_FAIL 101 #endif 102 } 103 } 104