| OLD | NEW | 
|---|
| 1 // Copyright (c) 2011, Google Inc. | 1 // Copyright (c) 2011, Google Inc. | 
| 2 // All rights reserved. | 2 // 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 are | 5 // modification, are permitted provided that the following conditions are | 
| 6 // met: | 6 // met: | 
| 7 // | 7 // | 
| 8 //     * Redistributions of source code must retain the above copyright | 8 //     * 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 //     * Redistributions in binary form must reproduce the above | 10 //     * Redistributions in binary form must reproduce the above | 
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 55 // For both types of lists: when a pop operation is performed on a non | 55 // For both types of lists: when a pop operation is performed on a non | 
| 56 // empty list, the new list head becomes that which is pointed to by | 56 // empty list, the new list head becomes that which is pointed to by | 
| 57 // the former head's |next| pointer.  If the list is doubly linked, the | 57 // the former head's |next| pointer.  If the list is doubly linked, the | 
| 58 // new head |previous| pointer gets changed from pointing to the former | 58 // new head |previous| pointer gets changed from pointing to the former | 
| 59 // head to NULL. | 59 // head to NULL. | 
| 60 | 60 | 
| 61 | 61 | 
| 62 #include <limits> | 62 #include <limits> | 
| 63 #include <stddef.h> | 63 #include <stddef.h> | 
| 64 #include "free_list.h" | 64 #include "free_list.h" | 
| 65 #include "system-alloc.h" |  | 
| 66 | 65 | 
| 67 #if defined(TCMALLOC_USE_DOUBLYLINKED_FREELIST) | 66 #if defined(TCMALLOC_USE_DOUBLYLINKED_FREELIST) | 
| 68 | 67 | 
| 69 using tcmalloc::kCrash; |  | 
| 70 |  | 
| 71 // TODO(jar): We should use C++ rather than a macro here. |  | 
| 72 #define MEMORY_CHECK(v1, v2) \ |  | 
| 73   if (v1 != v2) Log(kCrash, __FILE__, __LINE__, "Memory corruption detected.") |  | 
| 74 |  | 
| 75 namespace { |  | 
| 76 void EnsureNonLoop(void* node, void* next) { |  | 
| 77   // We only have time to do minimal checking.  We don't traverse the list, but |  | 
| 78   // only look for an immediate loop (cycle back to ourself). |  | 
| 79   if (node != next) return; |  | 
| 80   Log(kCrash, __FILE__, __LINE__, "Circular loop in list detected: ", next); |  | 
| 81 } |  | 
| 82 |  | 
| 83 inline void* MaskPtr(void* p) { |  | 
| 84   // Maximize ASLR entropy and guarantee the result is an invalid address. |  | 
| 85   const uintptr_t mask = ~(reinterpret_cast<uintptr_t>(TCMalloc_SystemAlloc) |  | 
| 86                            >> 13); |  | 
| 87   return reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(p) ^ mask); |  | 
| 88 } |  | 
| 89 |  | 
| 90 inline void* UnmaskPtr(void* p) { |  | 
| 91   return MaskPtr(p); |  | 
| 92 } |  | 
| 93 |  | 
| 94 // Returns value of the |previous| pointer w/out running a sanity |  | 
| 95 // check. |  | 
| 96 inline void *FL_Previous_No_Check(void *t) { |  | 
| 97   return UnmaskPtr(reinterpret_cast<void**>(t)[1]); |  | 
| 98 } |  | 
| 99 |  | 
| 100 // Returns value of the |next| pointer w/out running a sanity check. |  | 
| 101 inline void *FL_Next_No_Check(void *t) { |  | 
| 102   return UnmaskPtr(reinterpret_cast<void**>(t)[0]); |  | 
| 103 } |  | 
| 104 |  | 
| 105 void *FL_Previous(void *t) { |  | 
| 106   void *previous = FL_Previous_No_Check(t); |  | 
| 107   if (previous) { |  | 
| 108     MEMORY_CHECK(FL_Next_No_Check(previous), t); |  | 
| 109   } |  | 
| 110   return previous; |  | 
| 111 } |  | 
| 112 |  | 
| 113 inline void FL_SetPrevious(void *t, void *n) { |  | 
| 114   EnsureNonLoop(t, n); |  | 
| 115   reinterpret_cast<void**>(t)[1] = MaskPtr(n); |  | 
| 116 } |  | 
| 117 |  | 
| 118 inline void FL_SetNext(void *t, void *n) { |  | 
| 119   EnsureNonLoop(t, n); |  | 
| 120   reinterpret_cast<void**>(t)[0] = MaskPtr(n); |  | 
| 121 } |  | 
| 122 |  | 
| 123 } // namespace |  | 
| 124 |  | 
| 125 namespace tcmalloc { | 68 namespace tcmalloc { | 
| 126 | 69 | 
| 127 void *FL_Next(void *t) { |  | 
| 128   void *next = FL_Next_No_Check(t); |  | 
| 129   if (next) { |  | 
| 130     MEMORY_CHECK(FL_Previous_No_Check(next), t); |  | 
| 131   } |  | 
| 132   return next; |  | 
| 133 } |  | 
| 134 |  | 
| 135 // Makes the element at |t| a singleton doubly linked list. |  | 
| 136 void FL_Init(void *t) { |  | 
| 137   FL_SetPrevious(t, NULL); |  | 
| 138   FL_SetNext(t, NULL); |  | 
| 139 } |  | 
| 140 |  | 
| 141 // Pushes element to a linked list whose first element is at |  | 
| 142 // |*list|. When this call returns, |list| will point to the new head |  | 
| 143 // of the linked list. |  | 
| 144 void FL_Push(void **list, void *element) { |  | 
| 145   void *old = *list; |  | 
| 146   if (old == NULL) { // Builds singleton list. |  | 
| 147     FL_Init(element); |  | 
| 148   } else { |  | 
| 149     ASSERT(FL_Previous_No_Check(old) == NULL); |  | 
| 150     FL_SetNext(element, old); |  | 
| 151     FL_SetPrevious(old, element); |  | 
| 152     FL_SetPrevious(element, NULL); |  | 
| 153   } |  | 
| 154   *list = element; |  | 
| 155 } |  | 
| 156 |  | 
| 157 // Pops the top element off the linked list whose first element is at |  | 
| 158 // |*list|, and updates |*list| to point to the next element in the |  | 
| 159 // list.  Returns the address of the element that was removed from the |  | 
| 160 // linked list.  |list| must not be NULL. |  | 
| 161 void *FL_Pop(void **list) { |  | 
| 162   void *result = *list; |  | 
| 163   ASSERT(FL_Previous_No_Check(result) == NULL); |  | 
| 164   *list = FL_Next(result); |  | 
| 165   if (*list != NULL) { |  | 
| 166     FL_SetPrevious(*list, NULL); |  | 
| 167   } |  | 
| 168   return result; |  | 
| 169 } |  | 
| 170 |  | 
| 171 // Remove |n| elements from linked list at whose first element is at | 70 // Remove |n| elements from linked list at whose first element is at | 
| 172 // |*head|.  |head| will be modified to point to the new head. | 71 // |*head|.  |head| will be modified to point to the new head. | 
| 173 // |start| will point to the first node of the range, |end| will point | 72 // |start| will point to the first node of the range, |end| will point | 
| 174 // to the last node in the range. |n| must be <= FL_Size(|*head|) | 73 // to the last node in the range. |n| must be <= FL_Size(|*head|) | 
| 175 // If |n| > 0, |head| must not be NULL. | 74 // If |n| > 0, |head| must not be NULL. | 
| 176 void FL_PopRange(void **head, int n, void **start, void **end) { | 75 void FL_PopRange(void **head, int n, void **start, void **end) { | 
| 177   if (n == 0) { | 76   if (n == 0) { | 
| 178     *start = NULL; | 77     *start = NULL; | 
| 179     *end = NULL; | 78     *end = NULL; | 
| 180     return; | 79     return; | 
| (...skipping 20 matching lines...) Expand all  Loading... | 
| 201   if (!start) return; | 100   if (!start) return; | 
| 202 | 101 | 
| 203   // Sanity checking of ends of list to push is done by calling | 102   // Sanity checking of ends of list to push is done by calling | 
| 204   // FL_Next and FL_Previous. | 103   // FL_Next and FL_Previous. | 
| 205   FL_Next(start); | 104   FL_Next(start); | 
| 206   FL_Previous(end); | 105   FL_Previous(end); | 
| 207   ASSERT(FL_Previous_No_Check(start) == NULL); | 106   ASSERT(FL_Previous_No_Check(start) == NULL); | 
| 208   ASSERT(FL_Next_No_Check(end) == NULL); | 107   ASSERT(FL_Next_No_Check(end) == NULL); | 
| 209 | 108 | 
| 210   if (*head) { | 109   if (*head) { | 
| 211     MEMORY_CHECK(FL_Previous_No_Check(*head), NULL); | 110     FL_EqualityCheck(FL_Previous_No_Check(*head), (void*)NULL, | 
|  | 111                      __FILE__, __LINE__); | 
| 212     FL_SetNext(end, *head); | 112     FL_SetNext(end, *head); | 
| 213     FL_SetPrevious(*head, end); | 113     FL_SetPrevious(*head, end); | 
| 214   } | 114   } | 
| 215   *head = start; | 115   *head = start; | 
| 216 } | 116 } | 
| 217 | 117 | 
| 218 // Calculates the size of the list that begins at |head|. | 118 // Calculates the size of the list that begins at |head|. | 
| 219 size_t FL_Size(void *head){ | 119 size_t FL_Size(void *head){ | 
| 220   int count = 0; | 120   int count = 0; | 
| 221   if (head) { | 121   if (head) { | 
| 222     MEMORY_CHECK(FL_Previous_No_Check(head), NULL); | 122     FL_EqualityCheck(FL_Previous_No_Check(head), (void*)NULL, | 
|  | 123                      __FILE__, __LINE__); | 
| 223   } | 124   } | 
| 224   while (head) { | 125   while (head) { | 
| 225     count++; | 126     count++; | 
| 226     head = FL_Next(head); | 127     head = FL_Next(head); | 
| 227   } | 128   } | 
| 228   return count; | 129   return count; | 
| 229 } | 130 } | 
| 230 | 131 | 
| 231 } // namespace tcmalloc | 132 } // namespace tcmalloc | 
| 232 | 133 | 
| 233 #else | 134 #else | 
| 234 #include "linked_list.h" // for SLL_SetNext | 135 #include "linked_list.h" // for SLL_SetNext | 
| 235 | 136 | 
| 236 namespace { | 137 namespace { | 
| 237 | 138 | 
| 238 inline void FL_SetNext(void *t, void *n) { | 139 inline void FL_SetNext(void *t, void *n) { | 
| 239   tcmalloc::SLL_SetNext(t,n); | 140   tcmalloc::SLL_SetNext(t,n); | 
| 240 } | 141 } | 
| 241 | 142 | 
| 242 } | 143 } | 
| 243 | 144 | 
| 244 #endif // TCMALLOC_USE_DOUBLYLINKED_FREELIST | 145 #endif // TCMALLOC_USE_DOUBLYLINKED_FREELIST | 
| OLD | NEW | 
|---|