]> git.saurik.com Git - apple/javascriptcore.git/blob - runtime/DirectArguments.h
JavaScriptCore-7601.1.46.3.tar.gz
[apple/javascriptcore.git] / runtime / DirectArguments.h
1 /*
2 * Copyright (C) 2015 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 DirectArguments_h
27 #define DirectArguments_h
28
29 #include "DirectArgumentsOffset.h"
30 #include "GenericArguments.h"
31
32 namespace JSC {
33
34 // This is an Arguments-class object that we create when you say "arguments" inside a function,
35 // and none of the arguments are captured in the function's activation. The function will copy all
36 // of its arguments into this object, and all subsequent accesses to the arguments will go through
37 // this object thereafter. Special support is in place for mischevious events like the arguments
38 // being deleted (something like "delete arguments[0]") or reconfigured (broadly, we say deletions
39 // and reconfigurations mean that the respective argument was "overridden").
40 //
41 // To speed allocation, this object will hold all of the arguments in-place. The arguments as well
42 // as a table of flags saying which arguments were overridden.
43 class DirectArguments : public GenericArguments<DirectArguments> {
44 private:
45 DirectArguments(VM&, Structure*, unsigned length, unsigned capacity);
46
47 public:
48 // Creates an arguments object but leaves it uninitialized. This is dangerous if we GC right
49 // after allocation.
50 static DirectArguments* createUninitialized(VM&, Structure*, unsigned length, unsigned capacity);
51
52 // Creates an arguments object and initializes everything to the empty value. Use this if you
53 // cannot guarantee that you'll immediately initialize all of the elements.
54 static DirectArguments* create(VM&, Structure*, unsigned length, unsigned capacity);
55
56 // Creates an arguments object by copying the argumnets from the stack.
57 static DirectArguments* createByCopying(ExecState*);
58
59 static void visitChildren(JSCell*, SlotVisitor&);
60 static void copyBackingStore(JSCell*, CopyVisitor&, CopyToken);
61
62 uint32_t internalLength() const
63 {
64 return m_length;
65 }
66
67 uint32_t length(ExecState* exec) const
68 {
69 if (UNLIKELY(m_overrides))
70 return get(exec, exec->propertyNames().length).toUInt32(exec);
71 return m_length;
72 }
73
74 bool canAccessIndexQuickly(uint32_t i) const
75 {
76 return i < m_length && (!m_overrides || !m_overrides.get()[i]);
77 }
78
79 bool canAccessArgumentIndexQuicklyInDFG(uint32_t i) const
80 {
81 return i < m_length && !overrodeThings();
82 }
83
84 JSValue getIndexQuickly(uint32_t i) const
85 {
86 ASSERT_WITH_SECURITY_IMPLICATION(canAccessIndexQuickly(i));
87 return const_cast<DirectArguments*>(this)->storage()[i].get();
88 }
89
90 void setIndexQuickly(VM& vm, uint32_t i, JSValue value)
91 {
92 ASSERT_WITH_SECURITY_IMPLICATION(canAccessIndexQuickly(i));
93 storage()[i].set(vm, this, value);
94 }
95
96 WriteBarrier<JSFunction>& callee()
97 {
98 return m_callee;
99 }
100
101 WriteBarrier<Unknown>& argument(DirectArgumentsOffset offset)
102 {
103 ASSERT(offset);
104 ASSERT_WITH_SECURITY_IMPLICATION(offset.offset() < std::max(m_length, m_minCapacity));
105 return storage()[offset.offset()];
106 }
107
108 // Methods intended for use by the GenericArguments mixin.
109 bool overrodeThings() const { return !!m_overrides; }
110 void overrideThings(VM&);
111 void overrideThingsIfNecessary(VM&);
112 void overrideArgument(VM&, unsigned index);
113
114 void copyToArguments(ExecState*, VirtualRegister firstElementDest, unsigned offset, unsigned length);
115
116 DECLARE_INFO;
117
118 static Structure* createStructure(VM&, JSGlobalObject*, JSValue prototype);
119
120 static ptrdiff_t offsetOfCallee() { return OBJECT_OFFSETOF(DirectArguments, m_callee); }
121 static ptrdiff_t offsetOfLength() { return OBJECT_OFFSETOF(DirectArguments, m_length); }
122 static ptrdiff_t offsetOfMinCapacity() { return OBJECT_OFFSETOF(DirectArguments, m_minCapacity); }
123 static ptrdiff_t offsetOfOverrides() { return OBJECT_OFFSETOF(DirectArguments, m_overrides); }
124
125 static size_t storageOffset()
126 {
127 return WTF::roundUpToMultipleOf<sizeof(WriteBarrier<Unknown>)>(sizeof(DirectArguments));
128 }
129
130 static size_t offsetOfSlot(uint32_t index)
131 {
132 return storageOffset() + sizeof(WriteBarrier<Unknown>) * index;
133 }
134
135 static size_t allocationSize(uint32_t capacity)
136 {
137 return offsetOfSlot(capacity);
138 }
139
140 private:
141 WriteBarrier<Unknown>* storage()
142 {
143 return bitwise_cast<WriteBarrier<Unknown>*>(bitwise_cast<char*>(this) + storageOffset());
144 }
145
146 unsigned overridesSize();
147
148 WriteBarrier<JSFunction> m_callee;
149 uint32_t m_length; // Always the actual length of captured arguments and never what was stored into the length property.
150 uint32_t m_minCapacity; // The max of this and length determines the capacity of this object. It may be the actual capacity, or maybe something smaller. We arrange it this way to be kind to the JITs.
151 CopyWriteBarrier<bool> m_overrides; // If non-null, it means that length, callee, and caller are fully materialized properties.
152 };
153
154 } // namespace JSC
155
156 #endif // DirectArguments_h
157