]>
Commit | Line | Data |
---|---|---|
93a37866 A |
1 | /* |
2 | * Copyright (C) 2012 Apple Inc. All rights reserved. | |
3 | * | |
4 | * Redistribution and use in source and binary forms, with or without | |
5 | * modification, are permitted provided that the following conditions | |
6 | * are met: | |
7 | * 1. Redistributions of source code must retain the above copyright | |
8 | * notice, this list of conditions and the following disclaimer. | |
9 | * 2. Redistributions in binary form must reproduce the above copyright | |
10 | * notice, this list of conditions and the following disclaimer in the | |
11 | * documentation and/or other materials provided with the distribution. | |
12 | * | |
13 | * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY | |
14 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
15 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
16 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR | |
17 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | |
18 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |
19 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | |
20 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY | |
21 | * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
22 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
23 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
24 | */ | |
25 | ||
26 | #ifndef ButterflyInlines_h | |
27 | #define ButterflyInlines_h | |
28 | ||
29 | #include "ArrayStorage.h" | |
30 | #include "Butterfly.h" | |
31 | #include "CopiedSpaceInlines.h" | |
32 | #include "CopyVisitor.h" | |
33 | #include "VM.h" | |
34 | #include "Structure.h" | |
35 | ||
36 | namespace JSC { | |
37 | ||
38 | inline Butterfly* Butterfly::createUninitialized(VM& vm, size_t preCapacity, size_t propertyCapacity, bool hasIndexingHeader, size_t indexingPayloadSizeInBytes) | |
39 | { | |
40 | void* temp; | |
41 | size_t size = totalSize(preCapacity, propertyCapacity, hasIndexingHeader, indexingPayloadSizeInBytes); | |
42 | RELEASE_ASSERT(vm.heap.tryAllocateStorage(size, &temp)); | |
43 | Butterfly* result = fromBase(temp, preCapacity, propertyCapacity); | |
44 | return result; | |
45 | } | |
46 | ||
47 | inline Butterfly* Butterfly::create(VM& vm, size_t preCapacity, size_t propertyCapacity, bool hasIndexingHeader, const IndexingHeader& indexingHeader, size_t indexingPayloadSizeInBytes) | |
48 | { | |
49 | Butterfly* result = createUninitialized( | |
50 | vm, preCapacity, propertyCapacity, hasIndexingHeader, indexingPayloadSizeInBytes); | |
51 | if (hasIndexingHeader) | |
52 | *result->indexingHeader() = indexingHeader; | |
53 | return result; | |
54 | } | |
55 | ||
56 | inline Butterfly* Butterfly::create(VM& vm, Structure* structure) | |
57 | { | |
58 | return create(vm, 0, structure->outOfLineCapacity(), hasIndexingHeader(structure->indexingType()), IndexingHeader(), 0); | |
59 | } | |
60 | ||
61 | inline Butterfly* Butterfly::createUninitializedDuringCollection(CopyVisitor& visitor, size_t preCapacity, size_t propertyCapacity, bool hasIndexingHeader, size_t indexingPayloadSizeInBytes) | |
62 | { | |
63 | size_t size = totalSize(preCapacity, propertyCapacity, hasIndexingHeader, indexingPayloadSizeInBytes); | |
64 | Butterfly* result = fromBase( | |
65 | visitor.allocateNewSpace(size), | |
66 | preCapacity, propertyCapacity); | |
67 | return result; | |
68 | } | |
69 | ||
70 | inline void* Butterfly::base(Structure* structure) | |
71 | { | |
72 | return base(indexingHeader()->preCapacity(structure), structure->outOfLineCapacity()); | |
73 | } | |
74 | ||
75 | inline Butterfly* Butterfly::growPropertyStorage(VM& vm, size_t preCapacity, size_t oldPropertyCapacity, bool hasIndexingHeader, size_t indexingPayloadSizeInBytes, size_t newPropertyCapacity) | |
76 | { | |
77 | RELEASE_ASSERT(newPropertyCapacity > oldPropertyCapacity); | |
78 | Butterfly* result = createUninitialized( | |
79 | vm, preCapacity, newPropertyCapacity, hasIndexingHeader, indexingPayloadSizeInBytes); | |
80 | memcpy( | |
81 | result->propertyStorage() - oldPropertyCapacity, | |
82 | propertyStorage() - oldPropertyCapacity, | |
83 | totalSize(0, oldPropertyCapacity, hasIndexingHeader, indexingPayloadSizeInBytes)); | |
84 | return result; | |
85 | } | |
86 | ||
87 | inline Butterfly* Butterfly::growPropertyStorage(VM& vm, Structure* structure, size_t oldPropertyCapacity, size_t newPropertyCapacity) | |
88 | { | |
89 | return growPropertyStorage( | |
90 | vm, indexingHeader()->preCapacity(structure), oldPropertyCapacity, | |
91 | hasIndexingHeader(structure->indexingType()), | |
92 | indexingHeader()->indexingPayloadSizeInBytes(structure), newPropertyCapacity); | |
93 | } | |
94 | ||
95 | inline Butterfly* Butterfly::growPropertyStorage(VM& vm, Structure* oldStructure, size_t newPropertyCapacity) | |
96 | { | |
97 | return growPropertyStorage( | |
98 | vm, oldStructure, oldStructure->outOfLineCapacity(), newPropertyCapacity); | |
99 | } | |
100 | ||
101 | inline Butterfly* Butterfly::createOrGrowArrayRight(Butterfly* oldButterfly, VM& vm, Structure* oldStructure, size_t propertyCapacity, bool hadIndexingHeader, size_t oldIndexingPayloadSizeInBytes, size_t newIndexingPayloadSizeInBytes) | |
102 | { | |
103 | if (!oldButterfly) | |
104 | return create(vm, 0, propertyCapacity, true, IndexingHeader(), newIndexingPayloadSizeInBytes); | |
105 | return oldButterfly->growArrayRight(vm, oldStructure, propertyCapacity, hadIndexingHeader, oldIndexingPayloadSizeInBytes, newIndexingPayloadSizeInBytes); | |
106 | } | |
107 | ||
108 | inline Butterfly* Butterfly::growArrayRight(VM& vm, Structure* oldStructure, size_t propertyCapacity, bool hadIndexingHeader, size_t oldIndexingPayloadSizeInBytes, size_t newIndexingPayloadSizeInBytes) | |
109 | { | |
110 | ASSERT_UNUSED(oldStructure, !indexingHeader()->preCapacity(oldStructure)); | |
111 | ASSERT_UNUSED(oldStructure, hadIndexingHeader == hasIndexingHeader(oldStructure->indexingType())); | |
112 | void* theBase = base(0, propertyCapacity); | |
113 | size_t oldSize = totalSize(0, propertyCapacity, hadIndexingHeader, oldIndexingPayloadSizeInBytes); | |
114 | size_t newSize = totalSize(0, propertyCapacity, true, newIndexingPayloadSizeInBytes); | |
115 | if (!vm.heap.tryReallocateStorage(&theBase, oldSize, newSize)) | |
116 | return 0; | |
117 | return fromBase(theBase, 0, propertyCapacity); | |
118 | } | |
119 | ||
120 | inline Butterfly* Butterfly::growArrayRight(VM& vm, Structure* oldStructure, size_t newIndexingPayloadSizeInBytes) | |
121 | { | |
122 | return growArrayRight( | |
123 | vm, oldStructure, oldStructure->outOfLineCapacity(), | |
124 | hasIndexingHeader(oldStructure->indexingType()), | |
125 | indexingHeader()->indexingPayloadSizeInBytes(oldStructure), newIndexingPayloadSizeInBytes); | |
126 | } | |
127 | ||
128 | inline Butterfly* Butterfly::resizeArray(VM& vm, size_t propertyCapacity, bool oldHasIndexingHeader, size_t oldIndexingPayloadSizeInBytes, size_t newPreCapacity, bool newHasIndexingHeader, size_t newIndexingPayloadSizeInBytes) | |
129 | { | |
130 | Butterfly* result = createUninitialized( | |
131 | vm, newPreCapacity, propertyCapacity, newHasIndexingHeader, newIndexingPayloadSizeInBytes); | |
132 | // FIXME: This could be made much more efficient if we used the property size, | |
133 | // not the capacity. | |
134 | void* to = result->propertyStorage() - propertyCapacity; | |
135 | void* from = propertyStorage() - propertyCapacity; | |
136 | size_t size = std::min( | |
137 | totalSize(0, propertyCapacity, oldHasIndexingHeader, oldIndexingPayloadSizeInBytes), | |
138 | totalSize(0, propertyCapacity, newHasIndexingHeader, newIndexingPayloadSizeInBytes)); | |
139 | memcpy(to, from, size); | |
140 | return result; | |
141 | } | |
142 | ||
143 | inline Butterfly* Butterfly::resizeArray(VM& vm, Structure* structure, size_t newPreCapacity, size_t newIndexingPayloadSizeInBytes) | |
144 | { | |
145 | bool hasIndexingHeader = JSC::hasIndexingHeader(structure->indexingType()); | |
146 | return resizeArray( | |
147 | vm, structure->outOfLineCapacity(), hasIndexingHeader, | |
148 | indexingHeader()->indexingPayloadSizeInBytes(structure), newPreCapacity, | |
149 | hasIndexingHeader, newIndexingPayloadSizeInBytes); | |
150 | } | |
151 | ||
152 | inline Butterfly* Butterfly::unshift(Structure* structure, size_t numberOfSlots) | |
153 | { | |
154 | ASSERT(hasArrayStorage(structure->indexingType())); | |
155 | ASSERT(numberOfSlots <= indexingHeader()->preCapacity(structure)); | |
156 | unsigned propertyCapacity = structure->outOfLineCapacity(); | |
157 | // FIXME: It would probably be wise to rewrite this as a loop since (1) we know in which | |
158 | // direction we're moving memory so we don't need the extra check of memmove and (2) we're | |
159 | // moving a small amount of memory in the common case so the throughput of memmove won't | |
160 | // amortize the overhead of calling it. And no, we cannot rely on the C++ compiler to | |
161 | // inline memmove (particularly since the size argument is likely to be variable), nor can | |
162 | // we rely on the compiler to recognize the ordering of the pointer arguments (since | |
163 | // propertyCapacity is variable and could cause wrap-around as far as the compiler knows). | |
164 | memmove( | |
165 | propertyStorage() - numberOfSlots - propertyCapacity, | |
166 | propertyStorage() - propertyCapacity, | |
167 | sizeof(EncodedJSValue) * propertyCapacity + sizeof(IndexingHeader) + ArrayStorage::sizeFor(0)); | |
168 | return IndexingHeader::fromEndOf(propertyStorage() - numberOfSlots)->butterfly(); | |
169 | } | |
170 | ||
171 | inline Butterfly* Butterfly::shift(Structure* structure, size_t numberOfSlots) | |
172 | { | |
173 | ASSERT(hasArrayStorage(structure->indexingType())); | |
174 | unsigned propertyCapacity = structure->outOfLineCapacity(); | |
175 | // FIXME: See comment in unshift(), above. | |
176 | memmove( | |
177 | propertyStorage() - propertyCapacity + numberOfSlots, | |
178 | propertyStorage() - propertyCapacity, | |
179 | sizeof(EncodedJSValue) * propertyCapacity + sizeof(IndexingHeader) + ArrayStorage::sizeFor(0)); | |
180 | return IndexingHeader::fromEndOf(propertyStorage() + numberOfSlots)->butterfly(); | |
181 | } | |
182 | ||
183 | } // namespace JSC | |
184 | ||
185 | #endif // ButterflyInlines_h | |
186 |