2 * Copyright (C) 2015 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
27 #include "DirectArguments.h"
29 #include "CopyVisitorInlines.h"
30 #include "GenericArgumentsInlines.h"
31 #include "JSCInlines.h"
35 STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(DirectArguments
);
37 const ClassInfo
DirectArguments::s_info
= { "Arguments", &Base::s_info
, 0, CREATE_METHOD_TABLE(DirectArguments
) };
39 DirectArguments::DirectArguments(VM
& vm
, Structure
* structure
, unsigned length
, unsigned capacity
)
40 : GenericArguments(vm
, structure
)
42 , m_minCapacity(capacity
)
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
);
49 DirectArguments
* DirectArguments::createUninitialized(
50 VM
& vm
, Structure
* structure
, unsigned length
, unsigned capacity
)
52 DirectArguments
* result
=
53 new (NotNull
, allocateCell
<DirectArguments
>(vm
.heap
, allocationSize(capacity
)))
54 DirectArguments(vm
, structure
, length
, capacity
);
55 result
->finishCreation(vm
);
59 DirectArguments
* DirectArguments::create(VM
& vm
, Structure
* structure
, unsigned length
, unsigned capacity
)
61 DirectArguments
* result
= createUninitialized(vm
, structure
, length
, capacity
);
63 for (unsigned i
= capacity
; i
--;)
64 result
->storage()[i
].clear();
69 DirectArguments
* DirectArguments::createByCopying(ExecState
* exec
)
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
);
78 for (unsigned i
= capacity
; i
--;)
79 result
->storage()[i
].set(vm
, result
, exec
->getArgumentUnsafe(i
));
81 result
->callee().set(vm
, result
, jsCast
<JSFunction
*>(exec
->callee()));
86 void DirectArguments::visitChildren(JSCell
* thisCell
, SlotVisitor
& visitor
)
88 DirectArguments
* thisObject
= static_cast<DirectArguments
*>(thisCell
);
89 ASSERT_GC_OBJECT_INHERITS(thisObject
, info());
90 Base::visitChildren(thisObject
, visitor
);
92 visitor
.appendValues(thisObject
->storage(), std::max(thisObject
->m_length
, thisObject
->m_minCapacity
));
93 visitor
.append(&thisObject
->m_callee
);
95 if (thisObject
->m_overrides
) {
97 thisObject
, DirectArgumentsOverridesCopyToken
,
98 thisObject
->m_overrides
.get(), thisObject
->overridesSize());
102 void DirectArguments::copyBackingStore(JSCell
* thisCell
, CopyVisitor
& visitor
, CopyToken token
)
104 DirectArguments
* thisObject
= static_cast<DirectArguments
*>(thisCell
);
105 ASSERT_GC_OBJECT_INHERITS(thisObject
, info());
107 RELEASE_ASSERT(token
== DirectArgumentsOverridesCopyToken
);
109 bool* oldOverrides
= thisObject
->m_overrides
.get();
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());
121 Structure
* DirectArguments::createStructure(VM
& vm
, JSGlobalObject
* globalObject
, JSValue prototype
)
123 return Structure::create(vm
, globalObject
, prototype
, TypeInfo(DirectArgumentsType
, StructureFlags
), info());
126 void DirectArguments::overrideThings(VM
& vm
)
128 RELEASE_ASSERT(!m_overrides
);
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
);
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;
141 void DirectArguments::overrideThingsIfNecessary(VM
& vm
)
147 void DirectArguments::overrideArgument(VM
& vm
, unsigned index
)
149 overrideThingsIfNecessary(vm
);
150 m_overrides
.get()[index
] = true;
153 void DirectArguments::copyToArguments(ExecState
* exec
, VirtualRegister firstElementDest
, unsigned offset
, unsigned length
)
156 unsigned limit
= std::min(length
+ offset
, m_length
);
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
);
166 GenericArguments::copyToArguments(exec
, firstElementDest
, offset
, length
);
169 unsigned DirectArguments::overridesSize()
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);