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.
26 #ifndef ScopedArguments_h
27 #define ScopedArguments_h
29 #include "GenericArguments.h"
30 #include "JSLexicalEnvironment.h"
34 // This is an Arguments-class object that we create when you say "arguments" inside a function,
35 // and one or more of the arguments may be captured in the function's activation. The function
36 // will copy its formally declared arguments into the activation and then create this object. This
37 // object will store the overflow arguments, if there are any. This object will use the symbol
38 // table's ScopedArgumentsTable and the activation, or its overflow storage, to handle all indexed
40 class ScopedArguments
: public GenericArguments
<ScopedArguments
> {
42 ScopedArguments(VM
&, Structure
*, unsigned totalLength
);
43 void finishCreation(VM
&, JSFunction
* callee
, ScopedArgumentsTable
*, JSLexicalEnvironment
*);
46 // Creates an arguments object but leaves it uninitialized. This is dangerous if we GC right
48 static ScopedArguments
* createUninitialized(VM
&, Structure
*, JSFunction
* callee
, ScopedArgumentsTable
*, JSLexicalEnvironment
*, unsigned totalLength
);
50 // Creates an arguments object and initializes everything to the empty value. Use this if you
51 // cannot guarantee that you'll immediately initialize all of the elements.
52 static ScopedArguments
* create(VM
&, Structure
*, JSFunction
* callee
, ScopedArgumentsTable
*, JSLexicalEnvironment
*, unsigned totalLength
);
54 // Creates an arguments object by copying the arguments from the stack.
55 static ScopedArguments
* createByCopying(ExecState
*, ScopedArgumentsTable
*, JSLexicalEnvironment
*);
57 // Creates an arguments object by copying the arguments from a well-defined stack location.
58 static ScopedArguments
* createByCopyingFrom(VM
&, Structure
*, Register
* argumentsStart
, unsigned totalLength
, JSFunction
* callee
, ScopedArgumentsTable
*, JSLexicalEnvironment
*);
60 static void visitChildren(JSCell
*, SlotVisitor
&);
62 uint32_t internalLength() const
67 uint32_t length(ExecState
* exec
) const
69 if (UNLIKELY(m_overrodeThings
))
70 return get(exec
, exec
->propertyNames().length
).toUInt32(exec
);
71 return internalLength();
74 bool canAccessIndexQuickly(uint32_t i
) const
76 if (i
>= m_totalLength
)
78 unsigned namedLength
= m_table
->length();
80 return !!m_table
->get(i
);
81 return !!overflowStorage()[i
- namedLength
].get();
84 bool canAccessArgumentIndexQuicklyInDFG(uint32_t i
) const
86 return canAccessIndexQuickly(i
);
89 JSValue
getIndexQuickly(uint32_t i
) const
91 ASSERT_WITH_SECURITY_IMPLICATION(canAccessIndexQuickly(i
));
92 unsigned namedLength
= m_table
->length();
94 return m_scope
->variableAt(m_table
->get(i
)).get();
95 return overflowStorage()[i
- namedLength
].get();
98 void setIndexQuickly(VM
& vm
, uint32_t i
, JSValue value
)
100 ASSERT_WITH_SECURITY_IMPLICATION(canAccessIndexQuickly(i
));
101 unsigned namedLength
= m_table
->length();
103 m_scope
->variableAt(m_table
->get(i
)).set(vm
, this, value
);
105 overflowStorage()[i
- namedLength
].set(vm
, this, value
);
108 WriteBarrier
<JSFunction
>& callee()
113 bool overrodeThings() const { return m_overrodeThings
; }
114 void overrideThings(VM
&);
115 void overrideThingsIfNecessary(VM
&);
116 void overrideArgument(VM
&, uint32_t index
);
118 void copyToArguments(ExecState
*, VirtualRegister firstElementDest
, unsigned offset
, unsigned length
);
122 static Structure
* createStructure(VM
&, JSGlobalObject
*, JSValue prototype
);
124 static ptrdiff_t offsetOfOverrodeThings() { return OBJECT_OFFSETOF(ScopedArguments
, m_overrodeThings
); }
125 static ptrdiff_t offsetOfTotalLength() { return OBJECT_OFFSETOF(ScopedArguments
, m_totalLength
); }
126 static ptrdiff_t offsetOfTable() { return OBJECT_OFFSETOF(ScopedArguments
, m_table
); }
127 static ptrdiff_t offsetOfScope() { return OBJECT_OFFSETOF(ScopedArguments
, m_scope
); }
129 static size_t overflowStorageOffset()
131 return WTF::roundUpToMultipleOf
<sizeof(WriteBarrier
<Unknown
>)>(sizeof(ScopedArguments
));
134 static size_t allocationSize(unsigned overflowArgumentsLength
)
136 return overflowStorageOffset() + sizeof(WriteBarrier
<Unknown
>) * overflowArgumentsLength
;
140 WriteBarrier
<Unknown
>* overflowStorage() const
142 return bitwise_cast
<WriteBarrier
<Unknown
>*>(
143 bitwise_cast
<char*>(this) + overflowStorageOffset());
147 bool m_overrodeThings
; // True if length, callee, and caller are fully materialized in the object.
148 unsigned m_totalLength
; // The length of declared plus overflow arguments.
149 WriteBarrier
<JSFunction
> m_callee
;
150 WriteBarrier
<ScopedArgumentsTable
> m_table
;
151 WriteBarrier
<JSLexicalEnvironment
> m_scope
;
156 #endif // ScopedArguments_h