00001 // Copyright 2008 the V8 project authors. All rights reserved. 00002 // Redistribution and use in source and binary forms, with or without 00003 // modification, are permitted provided that the following conditions are 00004 // met: 00005 // 00006 // * Redistributions of source code must retain the above copyright 00007 // notice, this list of conditions and the following disclaimer. 00008 // * Redistributions in binary form must reproduce the above 00009 // copyright notice, this list of conditions and the following 00010 // disclaimer in the documentation and/or other materials provided 00011 // with the distribution. 00012 // * Neither the name of Google Inc. nor the names of its 00013 // contributors may be used to endorse or promote products derived 00014 // from this software without specific prior written permission. 00015 // 00016 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 00017 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 00018 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 00019 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 00020 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 00021 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 00022 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 00023 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 00024 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00025 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 00026 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00027 00028 #include <stdlib.h> 00029 00030 #include "v8.h" 00031 00032 namespace v8 { namespace internal { 00033 00034 00035 void* Malloced::New(size_t size) { 00036 ASSERT(NativeAllocationChecker::allocation_allowed()); 00037 void* result = malloc(size); 00038 if (result == NULL) V8::FatalProcessOutOfMemory("Malloced operator new"); 00039 return result; 00040 } 00041 00042 00043 void Malloced::Delete(void* p) { 00044 free(p); 00045 } 00046 00047 00048 void Malloced::FatalProcessOutOfMemory() { 00049 V8::FatalProcessOutOfMemory("Out of memory"); 00050 } 00051 00052 00053 #ifdef DEBUG 00054 00055 static void* invalid = static_cast<void*>(NULL); 00056 00057 void* Embedded::operator new(size_t size) { 00058 UNREACHABLE(); 00059 return invalid; 00060 } 00061 00062 00063 void Embedded::operator delete(void* p) { 00064 UNREACHABLE(); 00065 } 00066 00067 00068 void* AllStatic::operator new(size_t size) { 00069 UNREACHABLE(); 00070 return invalid; 00071 } 00072 00073 00074 void AllStatic::operator delete(void* p) { 00075 UNREACHABLE(); 00076 } 00077 00078 #endif 00079 00080 00081 char* StrDup(const char* str) { 00082 int length = strlen(str); 00083 char* result = NewArray<char>(length + 1); 00084 memcpy(result, str, length * kCharSize); 00085 result[length] = '\0'; 00086 return result; 00087 } 00088 00089 00090 int NativeAllocationChecker::allocation_disallowed_ = 0; 00091 00092 00093 PreallocatedStorage PreallocatedStorage::in_use_list_(0); 00094 PreallocatedStorage PreallocatedStorage::free_list_(0); 00095 bool PreallocatedStorage::preallocated_ = false; 00096 00097 00098 void PreallocatedStorage::Init(size_t size) { 00099 ASSERT(free_list_.next_ == &free_list_); 00100 ASSERT(free_list_.previous_ == &free_list_); 00101 PreallocatedStorage* free_chunk = 00102 reinterpret_cast<PreallocatedStorage*>(new char[size]); 00103 free_list_.next_ = free_list_.previous_ = free_chunk; 00104 free_chunk->next_ = free_chunk->previous_ = &free_list_; 00105 free_chunk->size_ = size - sizeof(PreallocatedStorage); 00106 preallocated_ = true; 00107 } 00108 00109 00110 void* PreallocatedStorage::New(size_t size) { 00111 if (!preallocated_) { 00112 return FreeStoreAllocationPolicy::New(size); 00113 } 00114 ASSERT(free_list_.next_ != &free_list_); 00115 ASSERT(free_list_.previous_ != &free_list_); 00116 size = (size + kPointerSize - 1) & ~(kPointerSize - 1); 00117 // Search for exact fit. 00118 for (PreallocatedStorage* storage = free_list_.next_; 00119 storage != &free_list_; 00120 storage = storage->next_) { 00121 if (storage->size_ == size) { 00122 storage->Unlink(); 00123 storage->LinkTo(&in_use_list_); 00124 return reinterpret_cast<void*>(storage + 1); 00125 } 00126 } 00127 // Search for first fit. 00128 for (PreallocatedStorage* storage = free_list_.next_; 00129 storage != &free_list_; 00130 storage = storage->next_) { 00131 if (storage->size_ >= size + sizeof(PreallocatedStorage)) { 00132 storage->Unlink(); 00133 storage->LinkTo(&in_use_list_); 00134 PreallocatedStorage* left_over = 00135 reinterpret_cast<PreallocatedStorage*>( 00136 reinterpret_cast<char*>(storage + 1) + size); 00137 left_over->size_ = storage->size_ - size - sizeof(PreallocatedStorage); 00138 ASSERT(size + left_over->size_ + sizeof(PreallocatedStorage) == 00139 storage->size_); 00140 storage->size_ = size; 00141 left_over->LinkTo(&free_list_); 00142 return reinterpret_cast<void*>(storage + 1); 00143 } 00144 } 00145 // Allocation failure. 00146 ASSERT(false); 00147 return NULL; 00148 } 00149 00150 00151 // We don't attempt to coalesce. 00152 void PreallocatedStorage::Delete(void* p) { 00153 if (p == NULL) { 00154 return; 00155 } 00156 if (!preallocated_) { 00157 FreeStoreAllocationPolicy::Delete(p); 00158 return; 00159 } 00160 PreallocatedStorage* storage = reinterpret_cast<PreallocatedStorage*>(p) - 1; 00161 ASSERT(storage->next_->previous_ == storage); 00162 ASSERT(storage->previous_->next_ == storage); 00163 storage->Unlink(); 00164 storage->LinkTo(&free_list_); 00165 } 00166 00167 00168 void PreallocatedStorage::LinkTo(PreallocatedStorage* other) { 00169 next_ = other->next_; 00170 other->next_->previous_ = this; 00171 previous_ = other; 00172 other->next_ = this; 00173 } 00174 00175 00176 void PreallocatedStorage::Unlink() { 00177 next_->previous_ = previous_; 00178 previous_->next_ = next_; 00179 } 00180 00181 00182 PreallocatedStorage::PreallocatedStorage(size_t size) 00183 : size_(size) { 00184 previous_ = next_ = this; 00185 } 00186 00187 } } // namespace v8::internal