source: webkit/trunk/JavaScriptCore/kjs/Arguments.cpp@ 37450

Last change on this file since 37450 was 37450, checked in by [email protected], 17 years ago

2008-10-09 Cameron Zwarich <[email protected]>

Reviewed by Oliver Hunt.

Bug 21459: REGRESSION (r37324): Safari crashes inside JavaScriptCore while browsing hulu.com
<https://bugs.webkit.org/show_bug.cgi?id=21459>

After r37324, an Arguments object does not mark an associated activation
object. This change was made because Arguments no longer directly used
the activation object in any way. However, if an activation is torn off,
then the backing store of Arguments becomes the register array of the
activation object. Arguments directly marks all of the arguments, but
the activation object is being collected, which causes its register
array to be freed and new memory to be allocated in its place.

Unfortunately, it does not seem possible to reproduce this issue in a
layout test.

  • kjs/Arguments.cpp: (JSC::Arguments::mark):
  • kjs/Arguments.h: (JSC::Arguments::setActivation): (JSC::Arguments::Arguments): (JSC::JSActivation::copyRegisters):
  • Property svn:eol-style set to native
File size: 7.4 KB
Line 
1/*
2 * Copyright (C) 1999-2002 Harri Porten ([email protected])
3 * Copyright (C) 2001 Peter Kelly ([email protected])
4 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
5 * Copyright (C) 2007 Cameron Zwarich ([email protected])
6 * Copyright (C) 2007 Maks Orlovich
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
17 *
18 * You should have received a copy of the GNU Library General Public License
19 * along with this library; see the file COPYING.LIB. If not, write to
20 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 * Boston, MA 02110-1301, USA.
22 *
23 */
24
25#include "config.h"
26#include "Arguments.h"
27
28#include "JSActivation.h"
29#include "JSFunction.h"
30#include "JSGlobalObject.h"
31
32using namespace std;
33
34namespace JSC {
35
36ASSERT_CLASS_FITS_IN_CELL(Arguments);
37
38const ClassInfo Arguments::info = { "Arguments", 0, 0, 0 };
39
40Arguments::~Arguments()
41{
42 if (d->extraArguments != d->extraArgumentsFixedBuffer)
43 delete [] d->extraArguments;
44}
45
46void Arguments::mark()
47{
48 JSObject::mark();
49
50 if (d->registerArray) {
51 for (unsigned i = 0; i < d->numParameters; ++i) {
52 if (!d->registerArray[i].marked())
53 d->registerArray[i].mark();
54 }
55 }
56
57 if (d->extraArguments) {
58 unsigned numExtraArguments = d->numArguments - d->numParameters;
59 for (unsigned i = 0; i < numExtraArguments; ++i) {
60 if (!d->extraArguments[i].marked())
61 d->extraArguments[i].mark();
62 }
63 }
64
65 if (!d->callee->marked())
66 d->callee->mark();
67
68 if (d->activation && !d->activation->marked())
69 d->activation->mark();
70}
71
72void Arguments::fillArgList(ExecState* exec, ArgList& args)
73{
74 if (LIKELY(!d->deletedArguments)) {
75 if (LIKELY(!d->numParameters)) {
76 args.initialize(d->extraArguments, d->numArguments);
77 return;
78 }
79
80 if (d->numParameters == d->numArguments) {
81 args.initialize(&d->registers[d->firstParameterIndex], d->numArguments);
82 return;
83 }
84
85 unsigned parametersLength = min(d->numParameters, d->numArguments);
86 unsigned i = 0;
87 for (; i < parametersLength; ++i)
88 args.append(d->registers[d->firstParameterIndex + i].jsValue(exec));
89 for (; i < d->numArguments; ++i)
90 args.append(d->extraArguments[i - d->numParameters].jsValue(exec));
91 return;
92 }
93
94 unsigned parametersLength = min(d->numParameters, d->numArguments);
95 unsigned i = 0;
96 for (; i < parametersLength; ++i) {
97 if (!d->deletedArguments[i])
98 args.append(d->registers[d->firstParameterIndex + i].jsValue(exec));
99 else
100 args.append(get(exec, i));
101 }
102 for (; i < d->numArguments; ++i) {
103 if (!d->deletedArguments[i])
104 args.append(d->extraArguments[i - d->numParameters].jsValue(exec));
105 else
106 args.append(get(exec, i));
107 }
108}
109
110bool Arguments::getOwnPropertySlot(ExecState* exec, unsigned i, PropertySlot& slot)
111{
112 if (i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) {
113 if (i < d->numParameters) {
114 slot.setRegisterSlot(&d->registers[d->firstParameterIndex + i]);
115 } else
116 slot.setValue(d->extraArguments[i - d->numParameters].jsValue(exec));
117 return true;
118 }
119
120 return JSObject::getOwnPropertySlot(exec, Identifier(exec, UString::from(i)), slot);
121}
122
123bool Arguments::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
124{
125 bool isArrayIndex;
126 unsigned i = propertyName.toArrayIndex(&isArrayIndex);
127 if (isArrayIndex && i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) {
128 if (i < d->numParameters) {
129 slot.setRegisterSlot(&d->registers[d->firstParameterIndex + i]);
130 } else
131 slot.setValue(d->extraArguments[i - d->numParameters].jsValue(exec));
132 return true;
133 }
134
135 if (propertyName == exec->propertyNames().length && LIKELY(!d->overrodeLength)) {
136 slot.setValue(jsNumber(exec, d->numArguments));
137 return true;
138 }
139
140 if (propertyName == exec->propertyNames().callee && LIKELY(!d->overrodeCallee)) {
141 slot.setValue(d->callee);
142 return true;
143 }
144
145 return JSObject::getOwnPropertySlot(exec, propertyName, slot);
146}
147
148void Arguments::put(ExecState* exec, unsigned i, JSValue* value, PutPropertySlot& slot)
149{
150 if (i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) {
151 if (i < d->numParameters)
152 d->registers[d->firstParameterIndex + i] = value;
153 else
154 d->extraArguments[i - d->numParameters] = value;
155 return;
156 }
157
158 JSObject::put(exec, Identifier(exec, UString::from(i)), value, slot);
159}
160
161void Arguments::put(ExecState* exec, const Identifier& propertyName, JSValue* value, PutPropertySlot& slot)
162{
163 bool isArrayIndex;
164 unsigned i = propertyName.toArrayIndex(&isArrayIndex);
165 if (isArrayIndex && i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) {
166 if (i < d->numParameters)
167 d->registers[d->firstParameterIndex + i] = value;
168 else
169 d->extraArguments[i - d->numParameters] = value;
170 return;
171 }
172
173 if (propertyName == exec->propertyNames().length && !d->overrodeLength) {
174 d->overrodeLength = true;
175 putDirect(propertyName, value, DontEnum);
176 return;
177 }
178
179 if (propertyName == exec->propertyNames().callee && !d->overrodeCallee) {
180 d->overrodeCallee = true;
181 putDirect(propertyName, value, DontEnum);
182 return;
183 }
184
185 JSObject::put(exec, propertyName, value, slot);
186}
187
188bool Arguments::deleteProperty(ExecState* exec, unsigned i)
189{
190 if (i < d->numArguments) {
191 if (!d->deletedArguments) {
192 d->deletedArguments.set(new bool[d->numArguments]);
193 memset(d->deletedArguments.get(), 0, sizeof(bool) * d->numArguments);
194 }
195 if (!d->deletedArguments[i]) {
196 d->deletedArguments[i] = true;
197 return true;
198 }
199 }
200
201 return JSObject::deleteProperty(exec, Identifier(exec, UString::from(i)));
202}
203
204bool Arguments::deleteProperty(ExecState* exec, const Identifier& propertyName)
205{
206 bool isArrayIndex;
207 unsigned i = propertyName.toArrayIndex(&isArrayIndex);
208 if (isArrayIndex && i < d->numArguments) {
209 if (!d->deletedArguments) {
210 d->deletedArguments.set(new bool[d->numArguments]);
211 memset(d->deletedArguments.get(), 0, sizeof(bool) * d->numArguments);
212 }
213 if (!d->deletedArguments[i]) {
214 d->deletedArguments[i] = true;
215 return true;
216 }
217 }
218
219 if (propertyName == exec->propertyNames().length && !d->overrodeLength) {
220 d->overrodeLength = true;
221 return true;
222 }
223
224 if (propertyName == exec->propertyNames().callee && !d->overrodeCallee) {
225 d->overrodeCallee = true;
226 return true;
227 }
228
229 return JSObject::deleteProperty(exec, propertyName);
230}
231
232} // namespace JSC
Note: See TracBrowser for help on using the repository browser.