blob: 48e9be0a269b569d2cd17e4e81e75ca861024798 [file] [log] [blame]
fpizlo@apple.comda834ae2015-03-26 04:28:43 +00001/*
fpizlo@apple.coma3304942018-01-26 00:05:57 +00002 * Copyright (C) 2015-2018 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").
fpizlo@apple.com04b4cea2018-04-04 17:55:44 +000041//
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.
utatane.tea@gmail.com64e3d772018-03-07 17:18:49 +000044class DirectArguments final : public GenericArguments<DirectArguments> {
fpizlo@apple.comda834ae2015-03-26 04:28:43 +000045private:
fpizlo@apple.com04b4cea2018-04-04 17:55:44 +000046 DirectArguments(VM&, Structure*, unsigned length, unsigned capacity);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +000047
48public:
fpizlo@apple.com25c19832017-08-11 20:08:33 +000049 template<typename CellType>
fpizlo@apple.com04b4cea2018-04-04 17:55:44 +000050 static CompleteSubspace* subspaceFor(VM& vm)
fpizlo@apple.com25c19832017-08-11 20:08:33 +000051 {
52 RELEASE_ASSERT(!CellType::needsDestruction);
fpizlo@apple.com04b4cea2018-04-04 17:55:44 +000053 return &vm.jsValueGigacageCellSpace;
fpizlo@apple.com25c19832017-08-11 20:08:33 +000054 }
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 {
fpizlo@apple.com04b4cea2018-04-04 17:55:44 +000072 return m_length;
fpizlo@apple.comda834ae2015-03-26 04:28:43 +000073 }
74
75 uint32_t length(ExecState* exec) const
76 {
mark.lam@apple.com23e96242017-09-09 16:21:45 +000077 if (UNLIKELY(m_mappedArguments)) {
78 VM& vm = exec->vm();
mark.lam@apple.com135cad52017-09-11 06:23:39 +000079 auto scope = DECLARE_THROW_SCOPE(vm);
80 JSValue value = get(exec, vm.propertyNames->length);
81 RETURN_IF_EXCEPTION(scope, 0);
82 scope.release();
83 return value.toUInt32(exec);
mark.lam@apple.com23e96242017-09-09 16:21:45 +000084 }
fpizlo@apple.com04b4cea2018-04-04 17:55:44 +000085 return m_length;
fpizlo@apple.comda834ae2015-03-26 04:28:43 +000086 }
87
commit-queue@webkit.org812d82a2016-12-24 21:26:22 +000088 bool isMappedArgument(uint32_t i) const
fpizlo@apple.comda834ae2015-03-26 04:28:43 +000089 {
fpizlo@apple.com04b4cea2018-04-04 17:55:44 +000090 return i < m_length && (!m_mappedArguments || !m_mappedArguments[i]);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +000091 }
benjamin@webkit.org75cbd6a2015-06-05 05:20:45 +000092
commit-queue@webkit.org812d82a2016-12-24 21:26:22 +000093 bool isMappedArgumentInDFG(uint32_t i) const
benjamin@webkit.org75cbd6a2015-06-05 05:20:45 +000094 {
fpizlo@apple.com04b4cea2018-04-04 17:55:44 +000095 return i < m_length && !overrodeThings();
benjamin@webkit.org75cbd6a2015-06-05 05:20:45 +000096 }
fpizlo@apple.com04b4cea2018-04-04 17:55:44 +000097
fpizlo@apple.comda834ae2015-03-26 04:28:43 +000098 JSValue getIndexQuickly(uint32_t i) const
99 {
commit-queue@webkit.org812d82a2016-12-24 21:26:22 +0000100 ASSERT_WITH_SECURITY_IMPLICATION(isMappedArgument(i));
fpizlo@apple.com04b4cea2018-04-04 17:55:44 +0000101 return const_cast<DirectArguments*>(this)->storage()[i].get();
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000102 }
103
104 void setIndexQuickly(VM& vm, uint32_t i, JSValue value)
105 {
commit-queue@webkit.org812d82a2016-12-24 21:26:22 +0000106 ASSERT_WITH_SECURITY_IMPLICATION(isMappedArgument(i));
fpizlo@apple.com04b4cea2018-04-04 17:55:44 +0000107 storage()[i].set(vm, this, value);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000108 }
109
fpizlo@apple.com92acb5a2018-03-22 02:15:44 +0000110 JSFunction* callee()
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000111 {
fpizlo@apple.com92acb5a2018-03-22 02:15:44 +0000112 return m_callee.get();
113 }
114
115 void setCallee(VM& vm, JSFunction* function)
116 {
117 m_callee.set(vm, this, function);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000118 }
119
120 WriteBarrier<Unknown>& argument(DirectArgumentsOffset offset)
121 {
122 ASSERT(offset);
fpizlo@apple.com04b4cea2018-04-04 17:55:44 +0000123 ASSERT_WITH_SECURITY_IMPLICATION(offset.offset() < std::max(m_length, m_minCapacity));
124 return storage()[offset.offset()];
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000125 }
126
127 // Methods intended for use by the GenericArguments mixin.
commit-queue@webkit.org812d82a2016-12-24 21:26:22 +0000128 bool overrodeThings() const { return !!m_mappedArguments; }
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000129 void overrideThings(VM&);
130 void overrideThingsIfNecessary(VM&);
commit-queue@webkit.org812d82a2016-12-24 21:26:22 +0000131 void unmapArgument(VM&, unsigned index);
132
133 void initModifiedArgumentsDescriptorIfNecessary(VM& vm)
134 {
fpizlo@apple.com04b4cea2018-04-04 17:55:44 +0000135 GenericArguments<DirectArguments>::initModifiedArgumentsDescriptorIfNecessary(vm, m_length);
commit-queue@webkit.org812d82a2016-12-24 21:26:22 +0000136 }
137
138 void setModifiedArgumentDescriptor(VM& vm, unsigned index)
139 {
fpizlo@apple.com04b4cea2018-04-04 17:55:44 +0000140 GenericArguments<DirectArguments>::setModifiedArgumentDescriptor(vm, index, m_length);
commit-queue@webkit.org812d82a2016-12-24 21:26:22 +0000141 }
142
143 bool isModifiedArgumentDescriptor(unsigned index)
144 {
fpizlo@apple.com04b4cea2018-04-04 17:55:44 +0000145 return GenericArguments<DirectArguments>::isModifiedArgumentDescriptor(index, m_length);
commit-queue@webkit.org812d82a2016-12-24 21:26:22 +0000146 }
147
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000148 void copyToArguments(ExecState*, VirtualRegister firstElementDest, unsigned offset, unsigned length);
149
150 DECLARE_INFO;
151
152 static Structure* createStructure(VM&, JSGlobalObject*, JSValue prototype);
153
154 static ptrdiff_t offsetOfCallee() { return OBJECT_OFFSETOF(DirectArguments, m_callee); }
fpizlo@apple.com04b4cea2018-04-04 17:55:44 +0000155 static ptrdiff_t offsetOfLength() { return OBJECT_OFFSETOF(DirectArguments, m_length); }
156 static ptrdiff_t offsetOfMinCapacity() { return OBJECT_OFFSETOF(DirectArguments, m_minCapacity); }
commit-queue@webkit.org812d82a2016-12-24 21:26:22 +0000157 static ptrdiff_t offsetOfMappedArguments() { return OBJECT_OFFSETOF(DirectArguments, m_mappedArguments); }
158 static ptrdiff_t offsetOfModifiedArgumentsDescriptor() { return OBJECT_OFFSETOF(DirectArguments, m_modifiedArgumentsDescriptor); }
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000159
fpizlo@apple.com04b4cea2018-04-04 17:55:44 +0000160 static size_t storageOffset()
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000161 {
fpizlo@apple.com04b4cea2018-04-04 17:55:44 +0000162 return WTF::roundUpToMultipleOf<sizeof(WriteBarrier<Unknown>)>(sizeof(DirectArguments));
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000163 }
164
fpizlo@apple.com04b4cea2018-04-04 17:55:44 +0000165 static size_t offsetOfSlot(Checked<size_t> index)
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000166 {
fpizlo@apple.com04b4cea2018-04-04 17:55:44 +0000167 return (storageOffset() + sizeof(WriteBarrier<Unknown>) * index).unsafeGet();
168 }
169
170 static size_t allocationSize(Checked<size_t> capacity)
171 {
172 return offsetOfSlot(capacity);
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000173 }
174
175private:
fpizlo@apple.com04b4cea2018-04-04 17:55:44 +0000176 WriteBarrier<Unknown>* storage()
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000177 {
fpizlo@apple.com04b4cea2018-04-04 17:55:44 +0000178 return bitwise_cast<WriteBarrier<Unknown>*>(bitwise_cast<char*>(this) + storageOffset());
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000179 }
180
commit-queue@webkit.org812d82a2016-12-24 21:26:22 +0000181 unsigned mappedArgumentsSize();
fpizlo@apple.comda834ae2015-03-26 04:28:43 +0000182
183 WriteBarrier<JSFunction> m_callee;
fpizlo@apple.com04b4cea2018-04-04 17:55:44 +0000184 uint32_t m_length; // Always the actual length of captured arguments and never what was stored into the length property.
185 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 +0000186 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 +0000187};
188
189} // namespace JSC