source: webkit/trunk/JavaScriptCore/kjs/internal.cpp@ 20204

Last change on this file since 20204 was 20043, checked in by bdash, 18 years ago

2007-03-07 Anrong Hu <[email protected]>

Reviewed by Maciej.

Fix http://bugs.webkit.org/show_bug.cgi?id=12535
Bug 12535: Stack-optimizing compilers can trick GC into freeing in-use objects

  • kjs/internal.cpp: (KJS::StringImp::toObject): Copy val onto the stack so it is not subject to garbage collection.
  • Property svn:eol-style set to native
File size: 6.6 KB
Line 
1/*
2 * This file is part of the KDE libraries
3 * Copyright (C) 1999-2002 Harri Porten ([email protected])
4 * Copyright (C) 2001 Peter Kelly ([email protected])
5 * Copyright (C) 2004 Apple Computer, Inc.
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
16 *
17 * You should have received a copy of the GNU Library General Public License
18 * along with this library; see the file COPYING.LIB. If not, write to
19 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 * Boston, MA 02110-1301, USA.
21 *
22 */
23
24#include "config.h"
25#include "internal.h"
26
27#include "array_object.h"
28#include "bool_object.h"
29#include "collector.h"
30#include "context.h"
31#include "date_object.h"
32#include "debugger.h"
33#include "error_object.h"
34#include "function_object.h"
35#include "lexer.h"
36#include "math_object.h"
37#include "nodes.h"
38#include "number_object.h"
39#include "object.h"
40#include "object_object.h"
41#include "operations.h"
42#include "regexp_object.h"
43#include "string_object.h"
44#include <assert.h>
45#include <wtf/HashMap.h>
46#include <wtf/HashSet.h>
47#include <wtf/Vector.h>
48#include <math.h>
49#include <stdio.h>
50
51namespace KJS {
52
53#if PLATFORM(WIN_OS)
54#define copysign _copysign
55#endif
56
57// ------------------------------ StringImp ------------------------------------
58
59JSValue *StringImp::toPrimitive(ExecState *, JSType) const
60{
61 return const_cast<StringImp *>(this);
62}
63
64bool StringImp::toBoolean(ExecState *) const
65{
66 return (val.size() > 0);
67}
68
69double StringImp::toNumber(ExecState *) const
70{
71 return val.toDouble();
72}
73
74UString StringImp::toString(ExecState *) const
75{
76 return val;
77}
78
79JSObject *StringImp::toObject(ExecState *exec) const
80{
81 // Put the reference onto the stack so it is not subject to garbage collection.
82 // <http://bugs.webkit.org/show_bug.cgi?id=12535>
83 UString valCopy = val;
84
85 return new StringInstance(exec->lexicalInterpreter()->builtinStringPrototype(), valCopy);
86}
87
88// ------------------------------ NumberImp ------------------------------------
89
90JSValue *NumberImp::toPrimitive(ExecState *, JSType) const
91{
92 return const_cast<NumberImp *>(this);
93}
94
95bool NumberImp::toBoolean(ExecState *) const
96{
97 return val < 0.0 || val > 0.0; // false for NaN
98}
99
100double NumberImp::toNumber(ExecState *) const
101{
102 return val;
103}
104
105UString NumberImp::toString(ExecState *) const
106{
107 if (val == 0.0) // +0.0 or -0.0
108 return "0";
109 return UString::from(val);
110}
111
112JSObject *NumberImp::toObject(ExecState *exec) const
113{
114 List args;
115 args.append(const_cast<NumberImp*>(this));
116 return static_cast<JSObject *>(exec->lexicalInterpreter()->builtinNumber()->construct(exec,args));
117}
118
119// FIXME: We can optimize this to work like JSValue::getUInt32. I'm ignoring it for now
120// because it never shows up on profiles.
121bool NumberImp::getUInt32(uint32_t& uint32) const
122{
123 uint32 = (uint32_t)val;
124 return (double)uint32 == val;
125}
126
127// --------------------------- GetterSetterImp ---------------------------------
128void GetterSetterImp::mark()
129{
130 JSCell::mark();
131
132 if (getter && !getter->marked())
133 getter->mark();
134 if (setter && !setter->marked())
135 setter->mark();
136}
137
138JSValue *GetterSetterImp::toPrimitive(ExecState*, JSType) const
139{
140 assert(false);
141 return jsNull();
142}
143
144bool GetterSetterImp::toBoolean(ExecState*) const
145{
146 assert(false);
147 return false;
148}
149
150double GetterSetterImp::toNumber(ExecState *) const
151{
152 assert(false);
153 return 0.0;
154}
155
156UString GetterSetterImp::toString(ExecState *) const
157{
158 assert(false);
159 return UString::null();
160}
161
162JSObject *GetterSetterImp::toObject(ExecState *exec) const
163{
164 assert(false);
165 return jsNull()->toObject(exec);
166}
167
168// ------------------------------ LabelStack -----------------------------------
169
170bool LabelStack::push(const Identifier &id)
171{
172 if (contains(id))
173 return false;
174
175 StackElem *newtos = new StackElem;
176 newtos->id = id;
177 newtos->prev = tos;
178 tos = newtos;
179 return true;
180}
181
182bool LabelStack::contains(const Identifier &id) const
183{
184 if (id.isEmpty())
185 return true;
186
187 for (StackElem *curr = tos; curr; curr = curr->prev)
188 if (curr->id == id)
189 return true;
190
191 return false;
192}
193
194// ------------------------------ InternalFunctionImp --------------------------
195
196const ClassInfo InternalFunctionImp::info = {"Function", 0, 0, 0};
197
198InternalFunctionImp::InternalFunctionImp()
199{
200}
201
202InternalFunctionImp::InternalFunctionImp(FunctionPrototype* funcProto)
203 : JSObject(funcProto)
204{
205}
206
207InternalFunctionImp::InternalFunctionImp(FunctionPrototype* funcProto, const Identifier& name)
208 : JSObject(funcProto)
209 , m_name(name)
210{
211}
212
213bool InternalFunctionImp::implementsCall() const
214{
215 return true;
216}
217
218bool InternalFunctionImp::implementsHasInstance() const
219{
220 return true;
221}
222
223// ------------------------------ global functions -----------------------------
224
225double roundValue(ExecState *exec, JSValue *v)
226{
227 double d = v->toNumber(exec);
228 double ad = fabs(d);
229 if (ad == 0 || isNaN(d) || isInf(d))
230 return d;
231 return copysign(floor(ad), d);
232}
233
234#ifndef NDEBUG
235#include <stdio.h>
236void printInfo(ExecState *exec, const char *s, JSValue *o, int lineno)
237{
238 if (!o)
239 fprintf(stderr, "KJS: %s: (null)", s);
240 else {
241 JSValue *v = o;
242
243 UString name;
244 switch (v->type()) {
245 case UnspecifiedType:
246 name = "Unspecified";
247 break;
248 case UndefinedType:
249 name = "Undefined";
250 break;
251 case NullType:
252 name = "Null";
253 break;
254 case BooleanType:
255 name = "Boolean";
256 break;
257 case StringType:
258 name = "String";
259 break;
260 case NumberType:
261 name = "Number";
262 break;
263 case ObjectType:
264 name = static_cast<JSObject *>(v)->className();
265 if (name.isNull())
266 name = "(unknown class)";
267 break;
268 case GetterSetterType:
269 name = "GetterSetter";
270 break;
271 }
272 UString vString = v->toString(exec);
273 if ( vString.size() > 50 )
274 vString = vString.substr( 0, 50 ) + "...";
275 // Can't use two UString::ascii() in the same fprintf call
276 CString tempString( vString.cstring() );
277
278 fprintf(stderr, "KJS: %s: %s : %s (%p)",
279 s, tempString.c_str(), name.ascii(), (void*)v);
280
281 if (lineno >= 0)
282 fprintf(stderr, ", line %d\n",lineno);
283 else
284 fprintf(stderr, "\n");
285 }
286}
287#endif
288
289}
Note: See TracBrowser for help on using the repository browser.