1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 : * vim: set ts=8 sw=4 et tw=78:
3 : *
4 : * ***** BEGIN LICENSE BLOCK *****
5 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 : *
7 : * The contents of this file are subject to the Mozilla Public License Version
8 : * 1.1 (the "License"); you may not use this file except in compliance with
9 : * the License. You may obtain a copy of the License at
10 : * http://www.mozilla.org/MPL/
11 : *
12 : * Software distributed under the License is distributed on an "AS IS" basis,
13 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14 : * for the specific language governing rights and limitations under the
15 : * License.
16 : *
17 : * The Original Code is SpiderMonkey arguments object code.
18 : *
19 : * The Initial Developer of the Original Code is
20 : * the Mozilla Foundation.
21 : * Portions created by the Initial Developer are Copyright (C) 2011
22 : * the Initial Developer. All Rights Reserved.
23 : *
24 : * Contributor(s):
25 : * Jeff Walden <jwalden+code@mit.edu> (original author)
26 : *
27 : * Alternatively, the contents of this file may be used under the terms of
28 : * either of the GNU General Public License Version 2 or later (the "GPL"),
29 : * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
30 : * in which case the provisions of the GPL or the LGPL are applicable instead
31 : * of those above. If you wish to allow use of your version of this file only
32 : * under the terms of either the GPL or the LGPL, and not to allow others to
33 : * use your version of this file under the terms of the MPL, indicate your
34 : * decision by deleting the provisions above and replace them with the notice
35 : * and other provisions required by the GPL or the LGPL. If you do not delete
36 : * the provisions above, a recipient may use your version of this file under
37 : * the terms of any one of the MPL, the GPL or the LGPL.
38 : *
39 : * ***** END LICENSE BLOCK ***** */
40 :
41 : #ifndef ArgumentsObject_inl_h___
42 : #define ArgumentsObject_inl_h___
43 :
44 : #include "ArgumentsObject.h"
45 :
46 : namespace js {
47 :
48 : inline void
49 362440 : ArgumentsObject::initInitialLength(uint32_t length)
50 : {
51 362440 : JS_ASSERT(getFixedSlot(INITIAL_LENGTH_SLOT).isUndefined());
52 362440 : initFixedSlot(INITIAL_LENGTH_SLOT, Int32Value(length << PACKED_BITS_COUNT));
53 362440 : JS_ASSERT((getFixedSlot(INITIAL_LENGTH_SLOT).toInt32() >> PACKED_BITS_COUNT) == int32_t(length));
54 362440 : JS_ASSERT(!hasOverriddenLength());
55 362440 : }
56 :
57 : inline uint32_t
58 2073809 : ArgumentsObject::initialLength() const
59 : {
60 2073809 : uint32_t argc = uint32_t(getFixedSlot(INITIAL_LENGTH_SLOT).toInt32()) >> PACKED_BITS_COUNT;
61 2073809 : JS_ASSERT(argc <= StackSpace::ARGS_LENGTH_MAX);
62 2073809 : return argc;
63 : }
64 :
65 : inline void
66 432 : ArgumentsObject::markLengthOverridden()
67 : {
68 432 : uint32_t v = getFixedSlot(INITIAL_LENGTH_SLOT).toInt32() | LENGTH_OVERRIDDEN_BIT;
69 432 : setFixedSlot(INITIAL_LENGTH_SLOT, Int32Value(v));
70 432 : }
71 :
72 : inline bool
73 807032 : ArgumentsObject::hasOverriddenLength() const
74 : {
75 807032 : const js::Value &v = getFixedSlot(INITIAL_LENGTH_SLOT);
76 807032 : return v.toInt32() & LENGTH_OVERRIDDEN_BIT;
77 : }
78 :
79 : inline void
80 362440 : ArgumentsObject::initData(ArgumentsData *data)
81 : {
82 362440 : JS_ASSERT(getFixedSlot(DATA_SLOT).isUndefined());
83 362440 : initFixedSlot(DATA_SLOT, PrivateValue(data));
84 362440 : }
85 :
86 : inline ArgumentsData *
87 2235971 : ArgumentsObject::data() const
88 : {
89 2235971 : return reinterpret_cast<js::ArgumentsData *>(getFixedSlot(DATA_SLOT).toPrivate());
90 : }
91 :
92 : inline bool
93 1292318 : ArgumentsObject::isElementDeleted(uint32_t i) const
94 : {
95 1292318 : return IsBitArrayElementSet(data()->deletedBits, initialLength(), i);
96 : }
97 :
98 : inline bool
99 213197 : ArgumentsObject::isAnyElementDeleted() const
100 : {
101 213197 : return IsAnyBitArrayElementSet(data()->deletedBits, initialLength());
102 : }
103 :
104 : inline void
105 414 : ArgumentsObject::markElementDeleted(uint32_t i)
106 : {
107 414 : SetBitArrayElement(data()->deletedBits, initialLength(), i);
108 414 : }
109 :
110 : inline const js::Value &
111 1161 : ArgumentsObject::element(uint32_t i) const
112 : {
113 1161 : JS_ASSERT(!isElementDeleted(i));
114 1161 : return data()->slots[i];
115 : }
116 :
117 : inline void
118 693 : ArgumentsObject::setElement(uint32_t i, const js::Value &v)
119 : {
120 693 : JS_ASSERT(!isElementDeleted(i));
121 693 : data()->slots[i] = v;
122 693 : }
123 :
124 : inline bool
125 115946 : ArgumentsObject::getElement(uint32_t i, Value *vp)
126 : {
127 115946 : if (i >= initialLength() || isElementDeleted(i))
128 2571 : return false;
129 :
130 : /*
131 : * If this arguments object has an associated stack frame, that contains
132 : * the canonical argument value. Note that strict arguments objects do not
133 : * alias named arguments and never have a stack frame.
134 : */
135 113375 : StackFrame *fp = maybeStackFrame();
136 113375 : JS_ASSERT_IF(isStrictArguments(), !fp);
137 113375 : if (fp)
138 112530 : *vp = fp->canonicalActualArg(i);
139 : else
140 845 : *vp = element(i);
141 113375 : return true;
142 : }
143 :
144 : namespace detail {
145 :
146 : struct STATIC_SKIP_INFERENCE CopyNonHoleArgsTo
147 : {
148 212847 : CopyNonHoleArgsTo(ArgumentsObject *argsobj, Value *dst) : argsobj(*argsobj), dst(dst) {}
149 : ArgumentsObject &argsobj;
150 : Value *dst;
151 879835 : bool operator()(uint32_t argi, Value *src) {
152 879835 : *dst++ = *src;
153 879835 : return true;
154 : }
155 : };
156 :
157 : } /* namespace detail */
158 :
159 : inline bool
160 213197 : ArgumentsObject::getElements(uint32_t start, uint32_t count, Value *vp)
161 : {
162 213197 : JS_ASSERT(start + count >= start);
163 :
164 213197 : uint32_t length = initialLength();
165 213197 : if (start > length || start + count > length || isAnyElementDeleted())
166 45 : return false;
167 :
168 213152 : StackFrame *fp = maybeStackFrame();
169 :
170 : /* If there's no stack frame for this, argument values are in elements(). */
171 213152 : if (!fp) {
172 305 : const Value *srcbeg = Valueify(data()->slots) + start;
173 305 : const Value *srcend = srcbeg + count;
174 305 : const Value *src = srcbeg;
175 582 : for (Value *dst = vp; src < srcend; ++dst, ++src)
176 277 : *dst = *src;
177 305 : return true;
178 : }
179 :
180 : /* Otherwise, element values are on the stack. */
181 212847 : JS_ASSERT(fp->numActualArgs() <= StackSpace::ARGS_LENGTH_MAX);
182 212847 : return fp->forEachCanonicalActualArg(detail::CopyNonHoleArgsTo(this, vp), start, count);
183 : }
184 :
185 : inline js::StackFrame *
186 701882 : ArgumentsObject::maybeStackFrame() const
187 : {
188 701882 : return reinterpret_cast<js::StackFrame *>(getFixedSlot(STACK_FRAME_SLOT).toPrivate());
189 : }
190 :
191 : inline void
192 1076340 : ArgumentsObject::setStackFrame(StackFrame *frame)
193 : {
194 1076340 : setFixedSlot(STACK_FRAME_SLOT, PrivateValue(frame));
195 1076340 : }
196 :
197 : inline size_t
198 : ArgumentsObject::sizeOfMisc(JSMallocSizeOfFun mallocSizeOf) const
199 : {
200 : return mallocSizeOf(data());
201 : }
202 :
203 : inline const js::Value &
204 1854 : NormalArgumentsObject::callee() const
205 : {
206 1854 : return data()->callee;
207 : }
208 :
209 : inline void
210 0 : NormalArgumentsObject::clearCallee()
211 : {
212 0 : data()->callee.set(compartment(), MagicValue(JS_OVERWRITTEN_CALLEE));
213 0 : }
214 :
215 : } // namespace js
216 :
217 : #endif /* ArgumentsObject_inl_h___ */
|