StackSlotAllocator.h (3416B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- 2 * vim: set ts=8 sts=2 et sw=2 tw=80: 3 * This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef jit_StackSlotAllocator_h 8 #define jit_StackSlotAllocator_h 9 10 #include "jit/LIR.h" 11 #include "jit/Registers.h" 12 13 namespace js { 14 namespace jit { 15 16 class StackSlotAllocator { 17 js::Vector<uint32_t, 4, SystemAllocPolicy> normalSlots; 18 js::Vector<uint32_t, 4, SystemAllocPolicy> doubleSlots; 19 js::Vector<uint32_t, 4, SystemAllocPolicy> quadSlots; 20 uint32_t height_; 21 22 void addAvailableSlot(uint32_t index) { 23 // Ignoring OOM here (and below) is fine; it just means the stack slot 24 // will be unused. 25 (void)normalSlots.append(index); 26 } 27 void addAvailableDoubleSlot(uint32_t index) { 28 (void)doubleSlots.append(index); 29 } 30 void addAvailableQuadSlot(uint32_t index) { (void)quadSlots.append(index); } 31 32 uint32_t allocateQuadSlot() { 33 // This relies on the fact that any architecture specific 34 // alignment of the stack pointer is done a priori. 35 if (!quadSlots.empty()) { 36 return quadSlots.popCopy(); 37 } 38 if (height_ % 8 != 0) { 39 addAvailableSlot(height_ += 4); 40 } 41 if (height_ % 16 != 0) { 42 addAvailableDoubleSlot(height_ += 8); 43 } 44 return height_ += 16; 45 } 46 uint32_t allocateDoubleSlot() { 47 if (!doubleSlots.empty()) { 48 return doubleSlots.popCopy(); 49 } 50 if (height_ % 8 != 0) { 51 addAvailableSlot(height_ += 4); 52 } 53 return height_ += 8; 54 } 55 uint32_t allocateSlot() { 56 if (!normalSlots.empty()) { 57 return normalSlots.popCopy(); 58 } 59 if (!doubleSlots.empty()) { 60 uint32_t index = doubleSlots.popCopy(); 61 addAvailableSlot(index - 4); 62 return index; 63 } 64 return height_ += 4; 65 } 66 67 public: 68 StackSlotAllocator() : height_(0) {} 69 70 void allocateStackArea(LStackArea* alloc) { 71 uint32_t size = alloc->size(); 72 73 MOZ_ASSERT(size % 4 == 0); 74 switch (alloc->alignment()) { 75 case 8: 76 if ((height_ + size) % 8 != 0) { 77 addAvailableSlot(height_ += 4); 78 } 79 break; 80 default: 81 MOZ_CRASH("unexpected stack results area alignment"); 82 } 83 MOZ_ASSERT((height_ + size) % alloc->alignment() == 0); 84 85 height_ += size; 86 alloc->setBase(height_); 87 } 88 89 uint32_t allocateSlot(LStackSlot::Width width) { 90 switch (width) { 91 case LStackSlot::Word: 92 return allocateSlot(); 93 case LStackSlot::DoubleWord: 94 return allocateDoubleSlot(); 95 case LStackSlot::QuadWord: 96 return allocateQuadSlot(); 97 } 98 MOZ_CRASH("Unknown slot width"); 99 } 100 101 // This method is used by the Simple allocator to free stack slots so that 102 // they can be reused. The Backtracking allocator doesn't call this. 103 void freeSlot(LStackSlot::Width width, uint32_t slot) { 104 switch (width) { 105 case LStackSlot::Word: 106 addAvailableSlot(slot); 107 return; 108 case LStackSlot::DoubleWord: 109 addAvailableDoubleSlot(slot); 110 return; 111 case LStackSlot::QuadWord: 112 addAvailableQuadSlot(slot); 113 return; 114 } 115 MOZ_CRASH("Unknown slot width"); 116 } 117 118 uint32_t stackHeight() const { return height_; } 119 }; 120 121 } // namespace jit 122 } // namespace js 123 124 #endif /* jit_StackSlotAllocator_h */