]> git.saurik.com Git - apple/javascriptcore.git/blob - runtime/DirectArguments.cpp
JavaScriptCore-7601.1.46.3.tar.gz
[apple/javascriptcore.git] / runtime / DirectArguments.cpp
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 #include "config.h"
27 #include "DirectArguments.h"
28
29 #include "CopyVisitorInlines.h"
30 #include "GenericArgumentsInlines.h"
31 #include "JSCInlines.h"
32
33 namespace JSC {
34
35 STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(DirectArguments);
36
37 const ClassInfo DirectArguments::s_info = { "Arguments", &Base::s_info, 0, CREATE_METHOD_TABLE(DirectArguments) };
38
39 DirectArguments::DirectArguments(VM& vm, Structure* structure, unsigned length, unsigned capacity)
40 : GenericArguments(vm, structure)
41 , m_length(length)
42 , m_minCapacity(capacity)
43 {
44 // When we construct the object from C++ code, we expect the capacity to be at least as large as
45 // length. JIT-allocated DirectArguments objects play evil tricks, though.
46 ASSERT(capacity >= length);
47 }
48
49 DirectArguments* DirectArguments::createUninitialized(
50 VM& vm, Structure* structure, unsigned length, unsigned capacity)
51 {
52 DirectArguments* result =
53 new (NotNull, allocateCell<DirectArguments>(vm.heap, allocationSize(capacity)))
54 DirectArguments(vm, structure, length, capacity);
55 result->finishCreation(vm);
56 return result;
57 }
58
59 DirectArguments* DirectArguments::create(VM& vm, Structure* structure, unsigned length, unsigned capacity)
60 {
61 DirectArguments* result = createUninitialized(vm, structure, length, capacity);
62
63 for (unsigned i = capacity; i--;)
64 result->storage()[i].clear();
65
66 return result;
67 }
68
69 DirectArguments* DirectArguments::createByCopying(ExecState* exec)
70 {
71 VM& vm = exec->vm();
72
73 unsigned length = exec->argumentCount();
74 unsigned capacity = std::max(length, static_cast<unsigned>(exec->codeBlock()->numParameters() - 1));
75 DirectArguments* result = createUninitialized(
76 vm, exec->lexicalGlobalObject()->directArgumentsStructure(), length, capacity);
77
78 for (unsigned i = capacity; i--;)
79 result->storage()[i].set(vm, result, exec->getArgumentUnsafe(i));
80
81 result->callee().set(vm, result, jsCast<JSFunction*>(exec->callee()));
82
83 return result;
84 }
85
86 void DirectArguments::visitChildren(JSCell* thisCell, SlotVisitor& visitor)
87 {
88 DirectArguments* thisObject = static_cast<DirectArguments*>(thisCell);
89 ASSERT_GC_OBJECT_INHERITS(thisObject, info());
90 Base::visitChildren(thisObject, visitor);
91
92 visitor.appendValues(thisObject->storage(), std::max(thisObject->m_length, thisObject->m_minCapacity));
93 visitor.append(&thisObject->m_callee);
94
95 if (thisObject->m_overrides) {
96 visitor.copyLater(
97 thisObject, DirectArgumentsOverridesCopyToken,
98 thisObject->m_overrides.get(), thisObject->overridesSize());
99 }
100 }
101
102 void DirectArguments::copyBackingStore(JSCell* thisCell, CopyVisitor& visitor, CopyToken token)
103 {
104 DirectArguments* thisObject = static_cast<DirectArguments*>(thisCell);
105 ASSERT_GC_OBJECT_INHERITS(thisObject, info());
106
107 RELEASE_ASSERT(token == DirectArgumentsOverridesCopyToken);
108
109 bool* oldOverrides = thisObject->m_overrides.get();
110 if (!oldOverrides)
111 return;
112
113 if (visitor.checkIfShouldCopy(oldOverrides)) {
114 bool* newOverrides = static_cast<bool*>(visitor.allocateNewSpace(thisObject->overridesSize()));
115 memcpy(newOverrides, oldOverrides, thisObject->m_length);
116 thisObject->m_overrides.setWithoutWriteBarrier(newOverrides);
117 visitor.didCopy(oldOverrides, thisObject->overridesSize());
118 }
119 }
120
121 Structure* DirectArguments::createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
122 {
123 return Structure::create(vm, globalObject, prototype, TypeInfo(DirectArgumentsType, StructureFlags), info());
124 }
125
126 void DirectArguments::overrideThings(VM& vm)
127 {
128 RELEASE_ASSERT(!m_overrides);
129
130 putDirect(vm, vm.propertyNames->length, jsNumber(m_length), DontEnum);
131 putDirect(vm, vm.propertyNames->callee, m_callee.get(), DontEnum);
132 putDirect(vm, vm.propertyNames->iteratorSymbol, globalObject()->arrayProtoValuesFunction(), DontEnum);
133
134 void* backingStore;
135 RELEASE_ASSERT(vm.heap.tryAllocateStorage(this, overridesSize(), &backingStore));
136 m_overrides.set(vm, this, static_cast<bool*>(backingStore));
137 for (unsigned i = m_length; i--;)
138 m_overrides.get()[i] = false;
139 }
140
141 void DirectArguments::overrideThingsIfNecessary(VM& vm)
142 {
143 if (!m_overrides)
144 overrideThings(vm);
145 }
146
147 void DirectArguments::overrideArgument(VM& vm, unsigned index)
148 {
149 overrideThingsIfNecessary(vm);
150 m_overrides.get()[index] = true;
151 }
152
153 void DirectArguments::copyToArguments(ExecState* exec, VirtualRegister firstElementDest, unsigned offset, unsigned length)
154 {
155 if (!m_overrides) {
156 unsigned limit = std::min(length + offset, m_length);
157 unsigned i;
158 VirtualRegister start = firstElementDest - offset;
159 for (i = offset; i < limit; ++i)
160 exec->r(start + i) = storage()[i].get();
161 for (; i < length; ++i)
162 exec->r(start + i) = get(exec, i);
163 return;
164 }
165
166 GenericArguments::copyToArguments(exec, firstElementDest, offset, length);
167 }
168
169 unsigned DirectArguments::overridesSize()
170 {
171 // We always allocate something; in the relatively uncommon case of overriding an empty argument we
172 // still allocate so that m_overrides is non-null. We use that to indicate that the other properties
173 // (length, etc) are overridden.
174 return WTF::roundUpToMultipleOf<8>(m_length ? m_length : 1);
175 }
176
177 } // namespace JSC
178