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 620688 : ArgumentsObject::initInitialLength(uint32_t length)
50 : {
51 620688 : JS_ASSERT(getFixedSlot(INITIAL_LENGTH_SLOT).isUndefined());
52 620688 : initFixedSlot(INITIAL_LENGTH_SLOT, Int32Value(length << PACKED_BITS_COUNT));
53 620688 : JS_ASSERT((getFixedSlot(INITIAL_LENGTH_SLOT).toInt32() >> PACKED_BITS_COUNT) == int32_t(length));
54 620688 : JS_ASSERT(!hasOverriddenLength());
55 620688 : }
56 :
57 : inline uint32_t
58 2860858 : ArgumentsObject::initialLength() const
59 : {
60 2860858 : uint32_t argc = uint32_t(getFixedSlot(INITIAL_LENGTH_SLOT).toInt32()) >> PACKED_BITS_COUNT;
61 2860858 : JS_ASSERT(argc <= StackSpace::ARGS_LENGTH_MAX);
62 2860858 : 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 1408593 : ArgumentsObject::hasOverriddenLength() const
74 : {
75 1408593 : const js::Value &v = getFixedSlot(INITIAL_LENGTH_SLOT);
76 1408593 : return v.toInt32() & LENGTH_OVERRIDDEN_BIT;
77 : }
78 :
79 : inline void
80 620688 : ArgumentsObject::initData(ArgumentsData *data)
81 : {
82 620688 : JS_ASSERT(getFixedSlot(DATA_SLOT).isUndefined());
83 620688 : initFixedSlot(DATA_SLOT, PrivateValue(data));
84 620688 : }
85 :
86 : inline ArgumentsData *
87 2592868 : ArgumentsObject::data() const
88 : {
89 2592868 : return reinterpret_cast<js::ArgumentsData *>(getFixedSlot(DATA_SLOT).toPrivate());
90 : }
91 :
92 : inline const js::Value &
93 1340614 : ArgumentsObject::element(uint32_t i) const
94 : {
95 1340614 : JS_ASSERT(i < initialLength());
96 1340614 : return data()->slots[i];
97 : }
98 :
99 : inline const js::Value *
100 5151 : ArgumentsObject::elements() const
101 : {
102 5151 : return Valueify(data()->slots);
103 : }
104 :
105 : inline void
106 684 : ArgumentsObject::setElement(uint32_t i, const js::Value &v)
107 : {
108 684 : JS_ASSERT(i < initialLength());
109 684 : data()->slots[i] = v;
110 684 : }
111 :
112 : inline bool
113 100117 : ArgumentsObject::getElement(uint32_t i, Value *vp)
114 : {
115 100117 : if (i >= initialLength())
116 3700 : return false;
117 :
118 96417 : *vp = element(i);
119 :
120 : /*
121 : * If the argument was overwritten, it could be in any object slot, so we
122 : * can't optimize.
123 : */
124 96417 : if (vp->isMagic(JS_ARGS_HOLE))
125 1015 : return false;
126 :
127 : /*
128 : * If this arguments object has an associated stack frame, that contains
129 : * the canonical argument value. Note that strict arguments objects do not
130 : * alias named arguments and never have a stack frame.
131 : */
132 95402 : StackFrame *fp = maybeStackFrame();
133 95402 : JS_ASSERT_IF(isStrictArguments(), !fp);
134 95402 : if (fp)
135 52598 : *vp = fp->canonicalActualArg(i);
136 95402 : return true;
137 : }
138 :
139 : namespace detail {
140 :
141 : struct STATIC_SKIP_INFERENCE CopyNonHoleArgsTo
142 : {
143 359960 : CopyNonHoleArgsTo(ArgumentsObject *argsobj, Value *dst) : argsobj(*argsobj), dst(dst) {}
144 : ArgumentsObject &argsobj;
145 : Value *dst;
146 1239254 : bool operator()(uint32_t argi, Value *src) {
147 1239254 : if (argsobj.element(argi).isMagic(JS_ARGS_HOLE))
148 18 : return false;
149 1239236 : *dst++ = *src;
150 1239236 : return true;
151 : }
152 : };
153 :
154 : } /* namespace detail */
155 :
156 : inline bool
157 365111 : ArgumentsObject::getElements(uint32_t start, uint32_t count, Value *vp)
158 : {
159 365111 : JS_ASSERT(start + count >= start);
160 :
161 365111 : uint32_t length = initialLength();
162 365111 : if (start > length || start + count > length)
163 0 : return false;
164 :
165 365111 : StackFrame *fp = maybeStackFrame();
166 :
167 : /* If there's no stack frame for this, argument values are in elements(). */
168 365111 : if (!fp) {
169 5151 : const Value *srcbeg = elements() + start;
170 5151 : const Value *srcend = srcbeg + count;
171 5151 : const Value *src = srcbeg;
172 19604 : for (Value *dst = vp; src < srcend; ++dst, ++src) {
173 14480 : if (src->isMagic(JS_ARGS_HOLE))
174 27 : return false;
175 14453 : *dst = *src;
176 : }
177 5124 : return true;
178 : }
179 :
180 : /* Otherwise, element values are on the stack. */
181 359960 : JS_ASSERT(fp->numActualArgs() <= StackSpace::ARGS_LENGTH_MAX);
182 359960 : return fp->forEachCanonicalActualArg(detail::CopyNonHoleArgsTo(this, vp), start, count);
183 : }
184 :
185 : inline js::StackFrame *
186 1101179 : ArgumentsObject::maybeStackFrame() const
187 : {
188 1101179 : return reinterpret_cast<js::StackFrame *>(getFixedSlot(STACK_FRAME_SLOT).toPrivate());
189 : }
190 :
191 : inline void
192 1788504 : ArgumentsObject::setStackFrame(StackFrame *frame)
193 : {
194 1788504 : setFixedSlot(STACK_FRAME_SLOT, PrivateValue(frame));
195 1788504 : }
196 :
197 : inline size_t
198 54 : ArgumentsObject::sizeOfMisc(JSMallocSizeOfFun mallocSizeOf) const
199 : {
200 54 : return mallocSizeOf(data());
201 : }
202 :
203 : inline const js::Value &
204 2148 : NormalArgumentsObject::callee() const
205 : {
206 2148 : return data()->callee;
207 : }
208 :
209 : inline void
210 0 : NormalArgumentsObject::clearCallee()
211 : {
212 0 : data()->callee.set(compartment(), MagicValue(JS_ARGS_HOLE));
213 0 : }
214 :
215 : } // namespace js
216 :
217 : #endif /* ArgumentsObject_inl_h___ */
|