/* * Copyright (c) 2010 The WebM project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ /* This code is in the public domain. ** Version: 1.1 Author: Walt Karas */ #include "hmm_intrnl.h" void U(shrink_chunk)(U(descriptor) *desc, U(size_bau) n_baus_to_shrink) { head_record *dummy_end_block = (head_record *) BAUS_BACKWARD(desc->end_of_shrinkable_chunk, DUMMY_END_BLOCK_BAUS); #ifdef HMM_AUDIT_FAIL if (dummy_end_block->block_size != 0) /* Chunk does not have valid dummy end block. */ HMM_AUDIT_FAIL #endif if (n_baus_to_shrink) { head_record *last_block = (head_record *) BAUS_BACKWARD( dummy_end_block, dummy_end_block->previous_block_size); #ifdef HMM_AUDIT_FAIL AUDIT_BLOCK(last_block) #endif if (last_block == desc->last_freed) { U(size_bau) bs = BLOCK_BAUS(last_block); /* Chunk will not be shrunk out of existence if ** 1. There is at least one allocated block in the chunk ** and the amount to shrink is exactly the size of the ** last block, OR ** 2. After the last block is shrunk, there will be enough ** BAUs left in it to form a minimal size block. */ int chunk_will_survive = (PREV_BLOCK_BAUS(last_block) && (n_baus_to_shrink == bs)) || (n_baus_to_shrink <= (U(size_bau))(bs - MIN_BLOCK_BAUS)); if (chunk_will_survive || (!PREV_BLOCK_BAUS(last_block) && (n_baus_to_shrink == (U(size_bau))(bs + DUMMY_END_BLOCK_BAUS)))) { desc->last_freed = 0; if (chunk_will_survive) { bs -= n_baus_to_shrink; if (bs) { /* The last (non-dummy) block was not completely ** eliminated by the shrink. */ last_block->block_size = bs; /* Create new dummy end record. */ dummy_end_block = (head_record *) BAUS_FORWARD(last_block, bs); dummy_end_block->previous_block_size = bs; dummy_end_block->block_size = 0; #ifdef HMM_AUDIT_FAIL if (desc->avl_tree_root) AUDIT_BLOCK(PTR_REC_TO_HEAD(desc->avl_tree_root)) #endif U(into_free_collection)(desc, last_block); } else { /* The last (non-dummy) block was completely ** eliminated by the shrink. Make its head ** the new dummy end block. */ last_block->block_size = 0; last_block->previous_block_size &= ~HIGH_BIT_BAU_SIZE; } } } #ifdef HMM_AUDIT_FAIL else HMM_AUDIT_FAIL #endif } #ifdef HMM_AUDIT_FAIL else HMM_AUDIT_FAIL #endif } }