blob: 97cc2ac62310fe204f4a37acb3be6d43f653c960 [file] [log] [blame]
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001/*
fpizlo@apple.comc206913b2017-08-07 21:31:49 +00002 * Copyright (C) 2015-2017 Apple Inc. All rights reserved.
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00003 *
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
ryanhaddad@apple.com22104f52016-09-28 17:08:17 +000026#pragma once
fpizlo@apple.comda834ae2015-03-26 04:28:43 +000027
fpizlo@apple.comc206913b2017-08-07 21:31:49 +000028#include "CagedBarrierPtr.h"
fpizlo@apple.comda834ae2015-03-26 04:28:43 +000029#include "DirectArgumentsOffset.h"
30#include "GenericArguments.h"
fpizlo@apple.comc206913b2017-08-07 21:31:49 +000031#include <wtf/CagedPtr.h>
fpizlo@apple.comda834ae2015-03-26 04:28:43 +000032
33namespace JSC {
34
35// This is an Arguments-class object that we create when you say "arguments" inside a function,
36// and none of the arguments are captured in the function's activation. The function will copy all
37// of its arguments into this object, and all subsequent accesses to the arguments will go through
38// this object thereafter. Special support is in place for mischevious events like the arguments
39// being deleted (something like "delete arguments[0]") or reconfigured (broadly, we say deletions
40// and reconfigurations mean that the respective argument was "overridden").
41//
42// To speed allocation, this object will hold all of the arguments in-place. The arguments as well
43// as a table of flags saying which arguments were overridden.
44class DirectArguments : public GenericArguments<DirectArguments> {
45private:
46 DirectArguments(VM&, Structure*, unsigned length, unsigned capacity);
47
48public:
fpizlo@apple.com25c19832017-08-11 20:08:33 +000049 template<typename CellType>
50 static Subspace* subspaceFor(VM& vm)
51 {
52 RELEASE_ASSERT(!CellType::needsDestruction);
53 return &vm.jsValueGigacageCellSpace;
54 }
55
fpizlo@apple.comda834ae2015-03-26 04:28:43 +000056 // Creates an arguments object but leaves it uninitialized. This is dangerous if we GC right
57 // after allocation.
58 static DirectArguments* createUninitialized(VM&, Structure*, unsigned length, unsigned capacity);
59
60 // Creates an arguments object and initializes everything to the empty value. Use this if you
61 // cannot guarantee that you'll immediately initialize all of the elements.
62 static DirectArguments* create(VM&, Structure*, unsigned length, unsigned capacity);
63
64 // Creates an arguments object by copying the argumnets from the stack.
65 static DirectArguments* createByCopying(ExecState*);
commit-queue@webkit.org00eb52f2016-03-01 02:07:12 +000066
67 static size_t estimatedSize(JSCell*);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +000068 static void visitChildren(JSCell*, SlotVisitor&);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +000069
70 uint32_t internalLength() const
71 {
72 return m_length;
73 }
74
75 uint32_t length(ExecState* exec) const
76 {
commit-queue@webkit.org812d82a2016-12-24 21:26:22 +000077 if (UNLIKELY(m_mappedArguments))
fpizlo@apple.comda834ae2015-03-26 04:28:43 +000078 return get(exec, exec->propertyNames().length).toUInt32(exec);
79 return m_length;
80 }
81
commit-queue@webkit.org812d82a2016-12-24 21:26:22 +000082 bool isMappedArgument(uint32_t i) const
fpizlo@apple.comda834ae2015-03-26 04:28:43 +000083 {
fpizlo@apple.comc206913b2017-08-07 21:31:49 +000084 return i < m_length && (!m_mappedArguments || !m_mappedArguments[i]);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +000085 }
benjamin@webkit.org75cbd6a2015-06-05 05:20:45 +000086
commit-queue@webkit.org812d82a2016-12-24 21:26:22 +000087 bool isMappedArgumentInDFG(uint32_t i) const
benjamin@webkit.org75cbd6a2015-06-05 05:20:45 +000088 {
89 return i < m_length && !overrodeThings();
90 }
91
fpizlo@apple.comda834ae2015-03-26 04:28:43 +000092 JSValue getIndexQuickly(uint32_t i) const
93 {
commit-queue@webkit.org812d82a2016-12-24 21:26:22 +000094 ASSERT_WITH_SECURITY_IMPLICATION(isMappedArgument(i));
fpizlo@apple.comda834ae2015-03-26 04:28:43 +000095 return const_cast<DirectArguments*>(this)->storage()[i].get();
96 }
97
98 void setIndexQuickly(VM& vm, uint32_t i, JSValue value)
99 {
commit-queue@webkit.org812d82a2016-12-24 21:26:22 +0000100 ASSERT_WITH_SECURITY_IMPLICATION(isMappedArgument(i));
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000101 storage()[i].set(vm, this, value);
102 }
103
104 WriteBarrier<JSFunction>& callee()
105 {
106 return m_callee;
107 }
108
109 WriteBarrier<Unknown>& argument(DirectArgumentsOffset offset)
110 {
111 ASSERT(offset);
112 ASSERT_WITH_SECURITY_IMPLICATION(offset.offset() < std::max(m_length, m_minCapacity));
113 return storage()[offset.offset()];
114 }
115
116 // Methods intended for use by the GenericArguments mixin.
commit-queue@webkit.org812d82a2016-12-24 21:26:22 +0000117 bool overrodeThings() const { return !!m_mappedArguments; }
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000118 void overrideThings(VM&);
119 void overrideThingsIfNecessary(VM&);
commit-queue@webkit.org812d82a2016-12-24 21:26:22 +0000120 void unmapArgument(VM&, unsigned index);
121
122 void initModifiedArgumentsDescriptorIfNecessary(VM& vm)
123 {
124 GenericArguments<DirectArguments>::initModifiedArgumentsDescriptorIfNecessary(vm, m_length);
125 }
126
127 void setModifiedArgumentDescriptor(VM& vm, unsigned index)
128 {
129 GenericArguments<DirectArguments>::setModifiedArgumentDescriptor(vm, index, m_length);
130 }
131
132 bool isModifiedArgumentDescriptor(unsigned index)
133 {
134 return GenericArguments<DirectArguments>::isModifiedArgumentDescriptor(index, m_length);
135 }
136
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000137 void copyToArguments(ExecState*, VirtualRegister firstElementDest, unsigned offset, unsigned length);
138
139 DECLARE_INFO;
140
141 static Structure* createStructure(VM&, JSGlobalObject*, JSValue prototype);
142
143 static ptrdiff_t offsetOfCallee() { return OBJECT_OFFSETOF(DirectArguments, m_callee); }
144 static ptrdiff_t offsetOfLength() { return OBJECT_OFFSETOF(DirectArguments, m_length); }
145 static ptrdiff_t offsetOfMinCapacity() { return OBJECT_OFFSETOF(DirectArguments, m_minCapacity); }
commit-queue@webkit.org812d82a2016-12-24 21:26:22 +0000146 static ptrdiff_t offsetOfMappedArguments() { return OBJECT_OFFSETOF(DirectArguments, m_mappedArguments); }
147 static ptrdiff_t offsetOfModifiedArgumentsDescriptor() { return OBJECT_OFFSETOF(DirectArguments, m_modifiedArgumentsDescriptor); }
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000148
149 static size_t storageOffset()
150 {
151 return WTF::roundUpToMultipleOf<sizeof(WriteBarrier<Unknown>)>(sizeof(DirectArguments));
152 }
153
oliver@apple.com26d90af2017-04-13 23:13:41 +0000154 static size_t offsetOfSlot(Checked<size_t> index)
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000155 {
oliver@apple.com26d90af2017-04-13 23:13:41 +0000156 return (storageOffset() + sizeof(WriteBarrier<Unknown>) * index).unsafeGet();
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000157 }
158
oliver@apple.com26d90af2017-04-13 23:13:41 +0000159 static size_t allocationSize(Checked<size_t> capacity)
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000160 {
161 return offsetOfSlot(capacity);
162 }
163
164private:
165 WriteBarrier<Unknown>* storage()
166 {
fpizlo@apple.com25c19832017-08-11 20:08:33 +0000167 return bitwise_cast<WriteBarrier<Unknown>*>(bitwise_cast<char*>(Gigacage::caged(Gigacage::JSValue, this)) + storageOffset());
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000168 }
169
commit-queue@webkit.org812d82a2016-12-24 21:26:22 +0000170 unsigned mappedArgumentsSize();
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000171
172 WriteBarrier<JSFunction> m_callee;
173 uint32_t m_length; // Always the actual length of captured arguments and never what was stored into the length property.
174 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.
fpizlo@apple.comc206913b2017-08-07 21:31:49 +0000175 CagedBarrierPtr<Gigacage::Primitive, bool> m_mappedArguments; // If non-null, it means that length, callee, and caller are fully materialized properties.
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000176};
177
178} // namespace JSC