001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one
003     * or more contributor license agreements. See the NOTICE file
004     * distributed with this work for additional information
005     * regarding copyright ownership. The ASF licenses this file
006     * to you under the Apache License, Version 2.0 (the  "License");
007     * you may not use this file except in compliance with the License.
008     * You may obtain a copy of the License at
009     *
010     *     http://www.apache.org/licenses/LICENSE-2.0
011     *
012     * Unless required by applicable law or agreed to in writing, software
013     * distributed under the License is distributed on an "AS IS" BASIS,
014     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015     * See the License for the specific language governing permissions and
016     * limitations under the License.
017     */
018    /*
019     * $Id: SlotAllocator.java 468649 2006-10-28 07:00:55Z minchau $
020     */
021    
022    package org.apache.xalan.xsltc.compiler.util;
023    
024    import org.apache.bcel.generic.LocalVariableGen;
025    import org.apache.bcel.generic.Type;
026    
027    /**
028     * @author Jacek Ambroziak
029     */
030    final class SlotAllocator {
031    
032        private int   _firstAvailableSlot;
033        private int   _size = 8;
034        private int   _free = 0;
035        private int[] _slotsTaken = new int[_size];
036        
037        public void initialize(LocalVariableGen[] vars) {
038            final int length = vars.length;
039            int slot = 0, size, index;
040    
041            for (int i = 0; i < length; i++) {
042                size  = vars[i].getType().getSize();
043                index = vars[i].getIndex();
044                slot  = Math.max(slot, index + size);
045            }
046            _firstAvailableSlot = slot;
047        }
048    
049        public int allocateSlot(Type type) {
050            final int size = type.getSize();
051            final int limit = _free;
052            int slot = _firstAvailableSlot, where = 0;
053    
054            if (_free + size > _size) {
055                final int[] array = new int[_size *= 2];
056                for (int j = 0; j < limit; j++)
057                    array[j] = _slotsTaken[j];
058                _slotsTaken = array;
059            }
060    
061            while (where < limit) {
062                if (slot + size <= _slotsTaken[where]) {
063                    // insert
064                    for (int j = limit - 1; j >= where; j--)
065                        _slotsTaken[j + size] = _slotsTaken[j];
066                    break;
067                }
068                else {
069                    slot = _slotsTaken[where++] + 1;
070                }
071            }
072            
073            for (int j = 0; j < size; j++)
074                _slotsTaken[where + j] = slot + j;
075            
076            _free += size;
077            return slot;
078        }
079    
080        public void releaseSlot(LocalVariableGen lvg) {
081            final int size = lvg.getType().getSize();
082            final int slot = lvg.getIndex();
083            final int limit = _free;
084            
085            for (int i = 0; i < limit; i++) {
086                if (_slotsTaken[i] == slot) {
087                    int j = i + size;
088                    while (j < limit) {
089                        _slotsTaken[i++] = _slotsTaken[j++];
090                    }
091                    _free -= size;
092                    return;
093                }
094            }
095            String state = "Variable slot allocation error"+
096                           "(size="+size+", slot="+slot+", limit="+limit+")";
097            ErrorMsg err = new ErrorMsg(ErrorMsg.INTERNAL_ERR, state);
098            throw new Error(err.toString());
099        }
100    }