]> git.saurik.com Git - apple/javascriptcore.git/blame - runtime/DirectArguments.cpp
JavaScriptCore-7601.1.46.3.tar.gz
[apple/javascriptcore.git] / runtime / DirectArguments.cpp
CommitLineData
ed1e77d3
A
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
33namespace JSC {
34
35STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(DirectArguments);
36
37const ClassInfo DirectArguments::s_info = { "Arguments", &Base::s_info, 0, CREATE_METHOD_TABLE(DirectArguments) };
38
39DirectArguments::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
49DirectArguments* 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
59DirectArguments* 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
69DirectArguments* 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
86void 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
102void 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
121Structure* DirectArguments::createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
122{
123 return Structure::create(vm, globalObject, prototype, TypeInfo(DirectArgumentsType, StructureFlags), info());
124}
125
126void 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
141void DirectArguments::overrideThingsIfNecessary(VM& vm)
142{
143 if (!m_overrides)
144 overrideThings(vm);
145}
146
147void DirectArguments::overrideArgument(VM& vm, unsigned index)
148{
149 overrideThingsIfNecessary(vm);
150 m_overrides.get()[index] = true;
151}
152
153void 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
169unsigned 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