]> git.saurik.com Git - apple/javascriptcore.git/blob - runtime/ScopedArguments.h
JavaScriptCore-7601.1.46.3.tar.gz
[apple/javascriptcore.git] / runtime / ScopedArguments.h
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 #ifndef ScopedArguments_h
27 #define ScopedArguments_h
28
29 #include "GenericArguments.h"
30 #include "JSLexicalEnvironment.h"
31
32 namespace JSC {
33
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
39 // lookups.
40 class ScopedArguments : public GenericArguments<ScopedArguments> {
41 private:
42 ScopedArguments(VM&, Structure*, unsigned totalLength);
43 void finishCreation(VM&, JSFunction* callee, ScopedArgumentsTable*, JSLexicalEnvironment*);
44
45 public:
46 // Creates an arguments object but leaves it uninitialized. This is dangerous if we GC right
47 // after allocation.
48 static ScopedArguments* createUninitialized(VM&, Structure*, JSFunction* callee, ScopedArgumentsTable*, JSLexicalEnvironment*, unsigned totalLength);
49
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);
53
54 // Creates an arguments object by copying the arguments from the stack.
55 static ScopedArguments* createByCopying(ExecState*, ScopedArgumentsTable*, JSLexicalEnvironment*);
56
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*);
59
60 static void visitChildren(JSCell*, SlotVisitor&);
61
62 uint32_t internalLength() const
63 {
64 return m_totalLength;
65 }
66
67 uint32_t length(ExecState* exec) const
68 {
69 if (UNLIKELY(m_overrodeThings))
70 return get(exec, exec->propertyNames().length).toUInt32(exec);
71 return internalLength();
72 }
73
74 bool canAccessIndexQuickly(uint32_t i) const
75 {
76 if (i >= m_totalLength)
77 return false;
78 unsigned namedLength = m_table->length();
79 if (i < namedLength)
80 return !!m_table->get(i);
81 return !!overflowStorage()[i - namedLength].get();
82 }
83
84 bool canAccessArgumentIndexQuicklyInDFG(uint32_t i) const
85 {
86 return canAccessIndexQuickly(i);
87 }
88
89 JSValue getIndexQuickly(uint32_t i) const
90 {
91 ASSERT_WITH_SECURITY_IMPLICATION(canAccessIndexQuickly(i));
92 unsigned namedLength = m_table->length();
93 if (i < namedLength)
94 return m_scope->variableAt(m_table->get(i)).get();
95 return overflowStorage()[i - namedLength].get();
96 }
97
98 void setIndexQuickly(VM& vm, uint32_t i, JSValue value)
99 {
100 ASSERT_WITH_SECURITY_IMPLICATION(canAccessIndexQuickly(i));
101 unsigned namedLength = m_table->length();
102 if (i < namedLength)
103 m_scope->variableAt(m_table->get(i)).set(vm, this, value);
104 else
105 overflowStorage()[i - namedLength].set(vm, this, value);
106 }
107
108 WriteBarrier<JSFunction>& callee()
109 {
110 return m_callee;
111 }
112
113 bool overrodeThings() const { return m_overrodeThings; }
114 void overrideThings(VM&);
115 void overrideThingsIfNecessary(VM&);
116 void overrideArgument(VM&, uint32_t index);
117
118 void copyToArguments(ExecState*, VirtualRegister firstElementDest, unsigned offset, unsigned length);
119
120 DECLARE_INFO;
121
122 static Structure* createStructure(VM&, JSGlobalObject*, JSValue prototype);
123
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); }
128
129 static size_t overflowStorageOffset()
130 {
131 return WTF::roundUpToMultipleOf<sizeof(WriteBarrier<Unknown>)>(sizeof(ScopedArguments));
132 }
133
134 static size_t allocationSize(unsigned overflowArgumentsLength)
135 {
136 return overflowStorageOffset() + sizeof(WriteBarrier<Unknown>) * overflowArgumentsLength;
137 }
138
139 private:
140 WriteBarrier<Unknown>* overflowStorage() const
141 {
142 return bitwise_cast<WriteBarrier<Unknown>*>(
143 bitwise_cast<char*>(this) + overflowStorageOffset());
144 }
145
146
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;
152 };
153
154 } // namespace JSC
155
156 #endif // ScopedArguments_h
157