| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2010 Google Inc. All rights reserved. | 2 * Copyright (C) 2010 Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
| 6 * are met: | 6 * are met: |
| 7 * | 7 * |
| 8 * 1. Redistributions of source code must retain the above copyright | 8 * 1. Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * 2. Redistributions in binary form must reproduce the above copyright | 10 * 2. Redistributions in binary form must reproduce the above copyright |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 46 | 46 |
| 47 ~AudioArray() | 47 ~AudioArray() |
| 48 { | 48 { |
| 49 fastFree(m_allocation); | 49 fastFree(m_allocation); |
| 50 } | 50 } |
| 51 | 51 |
| 52 // It's OK to call allocate() multiple times, but data will *not* be copied
from an initial allocation | 52 // It's OK to call allocate() multiple times, but data will *not* be copied
from an initial allocation |
| 53 // if re-allocated. Allocations are zero-initialized. | 53 // if re-allocated. Allocations are zero-initialized. |
| 54 void allocate(size_t n) | 54 void allocate(size_t n) |
| 55 { | 55 { |
| 56 // Although n is a size_t, its true limit is max unsigned because we use
unsigned in zeroRange() |
| 57 // and copyToRange(). Also check for integer overflow. |
| 58 if (n > std::numeric_limits<unsigned>::max() / sizeof(T)) |
| 59 CRASH(); |
| 60 |
| 61 unsigned initialSize = sizeof(T) * n; |
| 62 |
| 56 // 16-byte alignment for 128bit SIMD. | 63 // 16-byte alignment for 128bit SIMD. |
| 57 const size_t alignment = 16; | 64 const size_t alignment = 16; |
| 58 | 65 |
| 59 if (m_allocation) | 66 if (m_allocation) |
| 60 fastFree(m_allocation); | 67 fastFree(m_allocation); |
| 61 | 68 |
| 62 bool isAllocationGood = false; | 69 bool isAllocationGood = false; |
| 63 | 70 |
| 64 while (!isAllocationGood) { | 71 while (!isAllocationGood) { |
| 65 // Initially we try to allocate the exact size, but if it's not alig
ned | 72 // Initially we try to allocate the exact size, but if it's not alig
ned |
| 66 // then we'll have to reallocate and from then on allocate extra. | 73 // then we'll have to reallocate and from then on allocate extra. |
| 67 static size_t extraAllocationBytes = 0; | 74 static size_t extraAllocationBytes = 0; |
| 68 | 75 |
| 69 T* allocation = static_cast<T*>(fastMalloc(sizeof(T) * n + extraAllo
cationBytes)); | 76 // Again, check for integer overflow. |
| 77 if (initialSize + extraAllocationBytes < initialSize) |
| 78 CRASH(); |
| 79 |
| 80 T* allocation = static_cast<T*>(fastMalloc(initialSize + extraAlloca
tionBytes)); |
| 81 if (!allocation) |
| 82 CRASH(); |
| 70 T* alignedData = alignedAddress(allocation, alignment); | 83 T* alignedData = alignedAddress(allocation, alignment); |
| 71 | 84 |
| 72 if (alignedData == allocation || extraAllocationBytes == alignment)
{ | 85 if (alignedData == allocation || extraAllocationBytes == alignment)
{ |
| 73 m_allocation = allocation; | 86 m_allocation = allocation; |
| 74 m_alignedData = alignedData; | 87 m_alignedData = alignedData; |
| 75 m_size = n; | 88 m_size = n; |
| 76 isAllocationGood = true; | 89 isAllocationGood = true; |
| 77 zero(); | 90 zero(); |
| 78 } else { | 91 } else { |
| 79 extraAllocationBytes = alignment; // always allocate extra after
the first alignment failure. | 92 extraAllocationBytes = alignment; // always allocate extra after
the first alignment failure. |
| 80 fastFree(allocation); | 93 fastFree(allocation); |
| 81 } | 94 } |
| 82 } | 95 } |
| 83 } | 96 } |
| 84 | 97 |
| 85 T* data() { return m_alignedData; } | 98 T* data() { return m_alignedData; } |
| 86 const T* data() const { return m_alignedData; } | 99 const T* data() const { return m_alignedData; } |
| 87 size_t size() const { return m_size; } | 100 size_t size() const { return m_size; } |
| 88 | 101 |
| 89 T& at(size_t i) | 102 T& at(size_t i) |
| 90 { | 103 { |
| 104 // Note that although it is a size_t, m_size is now guaranteed to be |
| 105 // no greater than max unsigned. This guarantee is enforced in allocate(
). |
| 91 ASSERT(i < size()); | 106 ASSERT(i < size()); |
| 92 return data()[i]; | 107 return data()[i]; |
| 93 } | 108 } |
| 94 | 109 |
| 95 T& operator[](size_t i) { return at(i); } | 110 T& operator[](size_t i) { return at(i); } |
| 96 | 111 |
| 97 void zero() { memset(this->data(), 0, sizeof(T) * this->size()); } | 112 void zero() |
| 113 { |
| 114 // This multiplication is made safe by the check in allocate(). |
| 115 memset(this->data(), 0, sizeof(T) * this->size()); |
| 116 } |
| 98 | 117 |
| 99 void zeroRange(unsigned start, unsigned end) | 118 void zeroRange(unsigned start, unsigned end) |
| 100 { | 119 { |
| 101 bool isSafe = (start <= end) && (end <= this->size()); | 120 bool isSafe = (start <= end) && (end <= this->size()); |
| 102 ASSERT(isSafe); | 121 ASSERT(isSafe); |
| 103 if (!isSafe) | 122 if (!isSafe) |
| 104 return; | 123 return; |
| 105 | 124 |
| 125 // This expression cannot overflow because end - start cannot be |
| 126 // greater than m_size, which is safe due to the check in allocate(). |
| 106 memset(this->data() + start, 0, sizeof(T) * (end - start)); | 127 memset(this->data() + start, 0, sizeof(T) * (end - start)); |
| 107 } | 128 } |
| 108 | 129 |
| 109 void copyToRange(T* sourceData, unsigned start, unsigned end) | 130 void copyToRange(T* sourceData, unsigned start, unsigned end) |
| 110 { | 131 { |
| 111 bool isSafe = (start <= end) && (end <= this->size()); | 132 bool isSafe = (start <= end) && (end <= this->size()); |
| 112 ASSERT(isSafe); | 133 ASSERT(isSafe); |
| 113 if (!isSafe) | 134 if (!isSafe) |
| 114 return; | 135 return; |
| 115 | 136 |
| 137 // This expression cannot overflow because end - start cannot be |
| 138 // greater than m_size, which is safe due to the check in allocate(). |
| 116 memcpy(this->data() + start, sourceData, sizeof(T) * (end - start)); | 139 memcpy(this->data() + start, sourceData, sizeof(T) * (end - start)); |
| 117 } | 140 } |
| 118 | 141 |
| 119 private: | 142 private: |
| 120 static T* alignedAddress(T* address, intptr_t alignment) | 143 static T* alignedAddress(T* address, intptr_t alignment) |
| 121 { | 144 { |
| 122 intptr_t value = reinterpret_cast<intptr_t>(address); | 145 intptr_t value = reinterpret_cast<intptr_t>(address); |
| 123 return reinterpret_cast<T*>((value + alignment - 1) & ~(alignment - 1)); | 146 return reinterpret_cast<T*>((value + alignment - 1) & ~(alignment - 1)); |
| 124 } | 147 } |
| 125 | 148 |
| 126 T* m_allocation; | 149 T* m_allocation; |
| 127 T* m_alignedData; | 150 T* m_alignedData; |
| 128 size_t m_size; | 151 size_t m_size; |
| 129 }; | 152 }; |
| 130 | 153 |
| 131 typedef AudioArray<float> AudioFloatArray; | 154 typedef AudioArray<float> AudioFloatArray; |
| 132 typedef AudioArray<double> AudioDoubleArray; | 155 typedef AudioArray<double> AudioDoubleArray; |
| 133 | 156 |
| 134 } // WebCore | 157 } // WebCore |
| 135 | 158 |
| 136 #endif // AudioArray_h | 159 #endif // AudioArray_h |
| OLD | NEW |