]>
Commit | Line | Data |
---|---|---|
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 | ||
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 |