[JSC] JSPropertyNameEnumerator could be destructorless.
[WebKit-https.git] / Source / JavaScriptCore / runtime / JSPropertyNameEnumerator.cpp
1 /*
2  * Copyright (C) 2014 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. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "JSPropertyNameEnumerator.h"
28
29 #include "CopiedBlockInlines.h"
30 #include "CopyVisitorInlines.h"
31 #include "JSCInlines.h"
32 #include "StrongInlines.h"
33
34 namespace JSC {
35
36 const ClassInfo JSPropertyNameEnumerator::s_info = { "JSPropertyNameEnumerator", 0, 0, CREATE_METHOD_TABLE(JSPropertyNameEnumerator) };
37
38 JSPropertyNameEnumerator* JSPropertyNameEnumerator::create(VM& vm)
39 {
40     if (!vm.emptyPropertyNameEnumerator.get()) {
41         PropertyNameArray propertyNames(&vm, PropertyNameMode::Strings);
42         vm.emptyPropertyNameEnumerator = Strong<JSCell>(vm, create(vm, 0, 0, 0, propertyNames));
43     }
44     return jsCast<JSPropertyNameEnumerator*>(vm.emptyPropertyNameEnumerator.get());
45 }
46
47 JSPropertyNameEnumerator* JSPropertyNameEnumerator::create(VM& vm, Structure* structure, uint32_t indexedLength, uint32_t numberStructureProperties, PropertyNameArray& propertyNames)
48 {
49     StructureID structureID = structure ? structure->id() : 0;
50     uint32_t inlineCapacity = structure ? structure->inlineCapacity() : 0;
51     JSPropertyNameEnumerator* enumerator = new (NotNull, 
52         allocateCell<JSPropertyNameEnumerator>(vm.heap)) JSPropertyNameEnumerator(vm, structureID, inlineCapacity);
53     enumerator->finishCreation(vm, indexedLength, numberStructureProperties, propertyNames.data());
54     return enumerator;
55 }
56
57 JSPropertyNameEnumerator::JSPropertyNameEnumerator(VM& vm, StructureID structureID, uint32_t inlineCapacity)
58     : JSCell(vm, vm.propertyNameEnumeratorStructure.get())
59     , m_cachedStructureID(structureID)
60     , m_cachedInlineCapacity(inlineCapacity)
61 {
62 }
63
64 void JSPropertyNameEnumerator::finishCreation(VM& vm, uint32_t indexedLength, uint32_t endStructurePropertyIndex, PassRefPtr<PropertyNameArrayData> idents)
65 {
66     Base::finishCreation(vm);
67
68     RefPtr<PropertyNameArrayData> identifiers = idents;
69     PropertyNameArrayData::PropertyNameVector& vector = identifiers->propertyNameVector();
70
71     m_indexedLength = indexedLength;
72     m_endStructurePropertyIndex = endStructurePropertyIndex;
73     m_endGenericPropertyIndex = vector.size();
74
75     if (!vector.isEmpty()) {
76         void* backingStore;
77         RELEASE_ASSERT(vm.heap.tryAllocateStorage(this, vector.size() * sizeof(WriteBarrier<JSString>), &backingStore));
78         WriteBarrier<JSString>* propertyNames = reinterpret_cast<WriteBarrier<JSString>*>(backingStore);
79         m_propertyNames.set(vm, this, propertyNames);
80
81         for (unsigned i = 0; i < vector.size(); ++i)
82             propertyNames[i].set(vm, this, jsString(&vm, vector[i].string()));
83     }
84 }
85
86 void JSPropertyNameEnumerator::visitChildren(JSCell* cell, SlotVisitor& visitor)
87 {
88     Base::visitChildren(cell, visitor);
89     JSPropertyNameEnumerator* thisObject = jsCast<JSPropertyNameEnumerator*>(cell);
90     visitor.append(&thisObject->m_prototypeChain);
91
92     if (thisObject->cachedPropertyNameCount()) {
93         visitor.appendValues(reinterpret_cast<WriteBarrier<Unknown>*>(thisObject->m_propertyNames.getWithoutBarrier()), thisObject->cachedPropertyNameCount());
94         visitor.copyLater(
95             thisObject, JSPropertyNameEnumeratorCopyToken,
96             thisObject->m_propertyNames.getWithoutBarrier(), thisObject->cachedPropertyNameCount() * sizeof(JSString*));
97     }
98 }
99
100 void JSPropertyNameEnumerator::copyBackingStore(JSCell* cell, CopyVisitor& visitor, CopyToken token)
101 {
102     JSPropertyNameEnumerator* thisObject = jsCast<JSPropertyNameEnumerator*>(cell);
103     ASSERT_GC_OBJECT_INHERITS(thisObject, info());
104
105     RELEASE_ASSERT(token == JSPropertyNameEnumeratorCopyToken);
106
107     void* oldPropertyNames = thisObject->m_propertyNames.getWithoutBarrier();
108     if (visitor.checkIfShouldCopy(oldPropertyNames)) {
109         WriteBarrier<JSString>* newPropertyNames = static_cast<WriteBarrier<JSString>*>(visitor.allocateNewSpace(thisObject->cachedPropertyNameCount() * sizeof(WriteBarrier<JSString>)));
110         memcpy(newPropertyNames, oldPropertyNames, thisObject->cachedPropertyNameCount() * sizeof(JSString*));
111         thisObject->m_propertyNames.setWithoutBarrier(newPropertyNames);
112         visitor.didCopy(oldPropertyNames, thisObject->cachedPropertyNameCount() * sizeof(JSString*));
113     }
114 }
115
116 } // namespace JSC