| /* |
| * 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 |
| } |
| } |