Use constexpr instead of const in symbol definitions that are obviously constexpr.
[WebKit-https.git] / Source / JavaScriptCore / runtime / JSImmutableButterfly.h
1 /*
2  * Copyright (C) 2018-2019 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 #pragma once
27
28 #include "Butterfly.h"
29 #include "IndexingHeader.h"
30 #include "JSCJSValueInlines.h"
31 #include "JSCell.h"
32 #include "Structure.h"
33 #include "VirtualRegister.h"
34
35 namespace JSC {
36
37 class JSImmutableButterfly : public JSCell {
38     using Base = JSCell;
39
40 public:
41     static constexpr unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
42
43     DECLARE_INFO;
44
45     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype, IndexingType indexingType)
46     {
47         return Structure::create(vm, globalObject, prototype, TypeInfo(JSImmutableButterflyType, StructureFlags), info(), indexingType);
48     }
49
50     ALWAYS_INLINE static JSImmutableButterfly* tryCreate(VM& vm, Structure* structure, unsigned size)
51     {
52         Checked<size_t, RecordOverflow> checkedAllocationSize = allocationSize(size);
53         if (UNLIKELY(checkedAllocationSize.hasOverflowed()))
54             return nullptr;
55
56         void* buffer = tryAllocateCell<JSImmutableButterfly>(vm.heap, checkedAllocationSize.unsafeGet());
57         if (UNLIKELY(!buffer))
58             return nullptr;
59         JSImmutableButterfly* result = new (NotNull, buffer) JSImmutableButterfly(vm, structure, size);
60         result->finishCreation(vm);
61         return result;
62     }
63
64     static JSImmutableButterfly* create(VM& vm, IndexingType indexingType, unsigned length)
65     {
66         auto* array = tryCreate(vm, vm.immutableButterflyStructures[arrayIndexFromIndexingType(indexingType) - NumberOfIndexingShapes].get(), length);
67         RELEASE_ASSERT(array);
68         return array;
69     }
70
71     unsigned publicLength() const { return m_header.publicLength(); }
72     unsigned vectorLength() const { return m_header.vectorLength(); }
73     unsigned length() const { return m_header.publicLength(); }
74
75     Butterfly* toButterfly() const { return bitwise_cast<Butterfly*>(bitwise_cast<char*>(this) + offsetOfData()); }
76     static JSImmutableButterfly* fromButterfly(Butterfly* butterfly) { return bitwise_cast<JSImmutableButterfly*>(bitwise_cast<char*>(butterfly) - offsetOfData()); }
77
78     JSValue get(unsigned index) const
79     {
80         if (!hasDouble(indexingMode()))
81             return toButterfly()->contiguous().at(this, index).get();
82         double value = toButterfly()->contiguousDouble().at(this, index);
83         // Holes are not supported yet.
84         ASSERT(!std::isnan(value));
85         return jsNumber(value);
86     }
87
88     static void visitChildren(JSCell*, SlotVisitor&);
89
90     void copyToArguments(ExecState*, VirtualRegister firstElementDest, unsigned offset, unsigned length);
91
92     template<typename, SubspaceAccess>
93     static CompleteSubspace* subspaceFor(VM& vm)
94     {
95         // We allocate out of the JSValue gigacage as other code expects all butterflies to live there.
96         return &vm.immutableButterflyJSValueGigacageAuxiliarySpace;
97     }
98
99     // Only call this if you just allocated this butterfly.
100     void setIndex(VM& vm, unsigned index, JSValue value)
101     {
102         if (hasDouble(indexingType()))
103             toButterfly()->contiguousDouble().atUnsafe(index) = value.asNumber();
104         else
105             toButterfly()->contiguous().atUnsafe(index).set(vm, this, value);
106     }
107
108     static constexpr size_t offsetOfData()
109     {
110         return WTF::roundUpToMultipleOf<sizeof(WriteBarrier<Unknown>)>(sizeof(JSImmutableButterfly));
111     }
112
113 private:
114     static Checked<size_t, RecordOverflow> allocationSize(Checked<size_t, RecordOverflow> numItems)
115     {
116         return offsetOfData() + numItems * sizeof(WriteBarrier<Unknown>);
117     }
118
119     JSImmutableButterfly(VM& vm, Structure* structure, unsigned length)
120         : Base(vm, structure)
121     {
122         m_header.setVectorLength(length);
123         m_header.setPublicLength(length);
124         if (hasContiguous(indexingType())) {
125             for (unsigned index = 0; index < length; ++index)
126                 toButterfly()->contiguous().at(this, index).setStartingValue(JSValue());
127         }
128     }
129
130     IndexingHeader m_header;
131 };
132
133 } // namespace JSC