source: webkit/trunk/JavaScriptCore/kjs/value.cpp@ 2883

Last change on this file since 2883 was 2883, checked in by mjs, 23 years ago

Change ActivationImp to be allocated via the garbage collector
again instead of on the stack. This fixes the following four
regressions but sadly it causes a 6% performance hit. It's
probably possibly to reduce the hit a bit by being smarter about
inlining and the way the marking list variant is implemented, but
I'll look into that later.

  • fixed 3111500 - REGRESSION: crash in "KJS::ScopeChain::mark()" on www.posci.com
  • fixed 3111145 - REGRESSION: reproducible crash in KJS hashtable lookup at time.com
  • fixed 3110897 - REGRESSION: javascript crasher on http://bmwgallery.tripod.com/
  • fixed 3109987 - REGRESSION: Reproducible crash in KJS ObjectImp at live365.com

Also:

  • improved DEBUG_COLLECTOR mode a bit by never giving memory back to the system.
  • kjs/collector.cpp:
  • kjs/context.h:
  • kjs/function.cpp: (ActivationImp::ActivationImp): (ActivationImp::mark): (ActivationImp::createArgumentsObject):
  • kjs/function.h:
  • kjs/internal.cpp: (ContextImp::ContextImp): (ContextImp::mark):
  • kjs/list.cpp:
  • kjs/list.h:
  • kjs/value.cpp: (Value::Value):
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 8.7 KB
Line 
1// -*- c-basic-offset: 2 -*-
2/*
3 * This file is part of the KDE libraries
4 * Copyright (C) 1999-2001 Harri Porten ([email protected])
5 * Copyright (C) 2001 Peter Kelly ([email protected])
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., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
21 *
22 */
23
24#include "value.h"
25#include "object.h"
26#include "types.h"
27#include "interpreter.h"
28
29#include <assert.h>
30#include <math.h>
31#include <stdio.h>
32#include <string.h>
33
34#include "internal.h"
35#include "collector.h"
36#include "operations.h"
37#include "error_object.h"
38#include "nodes.h"
39#include "simple_number.h"
40
41using namespace KJS;
42
43// ----------------------------- ValueImp -------------------------------------
44
45ValueImp::ValueImp() :
46 refcount(0),
47 // Tell the garbage collector that this memory block corresponds to a real object now
48 _flags(VI_CREATED)
49{
50 //fprintf(stderr,"ValueImp::ValueImp %p\n",(void*)this);
51}
52
53ValueImp::~ValueImp()
54{
55 //fprintf(stderr,"ValueImp::~ValueImp %p\n",(void*)this);
56}
57
58void ValueImp::mark()
59{
60 //fprintf(stderr,"ValueImp::mark %p\n",(void*)this);
61 _flags |= VI_MARKED;
62}
63
64bool ValueImp::marked() const
65{
66 // Simple numbers are always considered marked.
67 return SimpleNumber::is(this) || (_flags & VI_MARKED);
68}
69
70void ValueImp::setGcAllowed()
71{
72 //fprintf(stderr,"ValueImp::setGcAllowed %p\n",(void*)this);
73 // simple numbers are never seen by the collector so setting this
74 // flag is irrelevant
75 if (!SimpleNumber::is(this))
76 _flags |= VI_GCALLOWED;
77}
78
79void* ValueImp::operator new(size_t s)
80{
81 return Collector::allocate(s);
82}
83
84void ValueImp::operator delete(void*)
85{
86 // Do nothing. So far.
87}
88
89bool ValueImp::toUInt32(unsigned&) const
90{
91 return false;
92}
93
94// ECMA 9.4
95int ValueImp::toInteger(ExecState *exec) const
96{
97 unsigned i;
98 if (dispatchToUInt32(i))
99 return (int)i;
100 return int(roundValue(exec, Value(const_cast<ValueImp*>(this))));
101}
102
103int ValueImp::toInt32(ExecState *exec) const
104{
105 unsigned i;
106 if (dispatchToUInt32(i))
107 return (int)i;
108
109 double d = roundValue(exec, Value(const_cast<ValueImp*>(this)));
110 double d32 = fmod(d, D32);
111
112 if (d32 >= D32 / 2.0)
113 d32 -= D32;
114
115 return static_cast<int>(d32);
116}
117
118unsigned int ValueImp::toUInt32(ExecState *exec) const
119{
120 unsigned i;
121 if (dispatchToUInt32(i))
122 return i;
123
124 double d = roundValue(exec, Value(const_cast<ValueImp*>(this)));
125 double d32 = fmod(d, D32);
126
127 return static_cast<unsigned int>(d32);
128}
129
130unsigned short ValueImp::toUInt16(ExecState *exec) const
131{
132 unsigned i;
133 if (dispatchToUInt32(i))
134 return (unsigned short)i;
135
136 double d = roundValue(exec, Value(const_cast<ValueImp*>(this)));
137 double d16 = fmod(d, D16);
138
139 return static_cast<unsigned short>(d16);
140}
141
142// Dispatchers for virtual functions, to special-case simple numbers which
143// won't be real pointers.
144
145Type ValueImp::dispatchType() const
146{
147 if (SimpleNumber::is(this))
148 return NumberType;
149 return type();
150}
151
152Value ValueImp::dispatchToPrimitive(ExecState *exec, Type preferredType) const
153{
154 if (SimpleNumber::is(this))
155 return Value(const_cast<ValueImp *>(this));
156 return toPrimitive(exec, preferredType);
157}
158
159bool ValueImp::dispatchToBoolean(ExecState *exec) const
160{
161 if (SimpleNumber::is(this))
162 return SimpleNumber::value(this);
163 return toBoolean(exec);
164}
165
166double ValueImp::dispatchToNumber(ExecState *exec) const
167{
168 if (SimpleNumber::is(this))
169 return SimpleNumber::value(this);
170 return toNumber(exec);
171}
172
173UString ValueImp::dispatchToString(ExecState *exec) const
174{
175 if (SimpleNumber::is(this))
176 return UString::from(SimpleNumber::value(this));
177 return toString(exec);
178}
179
180Object ValueImp::dispatchToObject(ExecState *exec) const
181{
182 if (SimpleNumber::is(this))
183 return static_cast<const NumberImp *>(this)->NumberImp::toObject(exec);
184 return toObject(exec);
185}
186
187bool ValueImp::dispatchToUInt32(unsigned& result) const
188{
189 if (SimpleNumber::is(this)) {
190 long i = SimpleNumber::value(this);
191 if (i < 0)
192 return false;
193 result = (unsigned)i;
194 return true;
195 }
196 return toUInt32(result);
197}
198
199// ------------------------------ Value ----------------------------------------
200
201Value::Value(ValueImp *v)
202{
203 rep = v;
204#if DEBUG_COLLECTOR
205 assert (!(rep && !SimpleNumber::is(rep) && *((uint32_t *)rep) == 0 ));
206 assert (!(rep && !SimpleNumber::is(rep) && rep->_flags & ValueImp::VI_MARKED));
207#endif
208 if (v)
209 {
210 v->ref();
211 //fprintf(stderr, "Value::Value(%p) imp=%p ref=%d\n", this, rep, rep->refcount);
212 v->setGcAllowed();
213 }
214}
215
216Value::Value(const Value &v)
217{
218 rep = v.imp();
219#if DEBUG_COLLECTOR
220 assert (!(rep && !SimpleNumber::is(rep) && *((uint32_t *)rep) == 0 ));
221 assert (!(rep && !SimpleNumber::is(rep) && rep->_flags & ValueImp::VI_MARKED));
222#endif
223 if (rep)
224 {
225 rep->ref();
226 //fprintf(stderr, "Value::Value(%p)(copying %p) imp=%p ref=%d\n", this, &v, rep, rep->refcount);
227 }
228}
229
230Value::~Value()
231{
232 if (rep)
233 {
234 rep->deref();
235 //fprintf(stderr, "Value::~Value(%p) imp=%p ref=%d\n", this, rep, rep->refcount);
236 }
237}
238
239Value& Value::operator=(const Value &v)
240{
241 if (rep) {
242 rep->deref();
243 //fprintf(stderr, "Value::operator=(%p)(copying %p) old imp=%p ref=%d\n", this, &v, rep, rep->refcount);
244 }
245 rep = v.imp();
246 if (rep)
247 {
248 rep->ref();
249 //fprintf(stderr, "Value::operator=(%p)(copying %p) imp=%p ref=%d\n", this, &v, rep, rep->refcount);
250 }
251 return *this;
252}
253
254// ------------------------------ Undefined ------------------------------------
255
256Undefined::Undefined() : Value(UndefinedImp::staticUndefined)
257{
258}
259
260Undefined Undefined::dynamicCast(const Value &v)
261{
262 if (v.isNull() || v.type() != UndefinedType)
263 return Undefined(0);
264
265 return Undefined();
266}
267
268// ------------------------------ Null -----------------------------------------
269
270Null::Null() : Value(NullImp::staticNull)
271{
272}
273
274Null Null::dynamicCast(const Value &v)
275{
276 if (v.isNull() || v.type() != NullType)
277 return Null(0);
278
279 return Null();
280}
281
282// ------------------------------ Boolean --------------------------------------
283
284Boolean::Boolean(bool b)
285 : Value(b ? BooleanImp::staticTrue : BooleanImp::staticFalse)
286{
287}
288
289bool Boolean::value() const
290{
291 assert(rep);
292 return ((BooleanImp*)rep)->value();
293}
294
295Boolean Boolean::dynamicCast(const Value &v)
296{
297 if (v.isNull() || v.type() != BooleanType)
298 return static_cast<BooleanImp*>(0);
299
300 return static_cast<BooleanImp*>(v.imp());
301}
302
303// ------------------------------ String ---------------------------------------
304
305String::String(const UString &s) : Value(new StringImp(s))
306{
307}
308
309UString String::value() const
310{
311 assert(rep);
312 return ((StringImp*)rep)->value();
313}
314
315String String::dynamicCast(const Value &v)
316{
317 if (v.isNull() || v.type() != StringType)
318 return String(0);
319
320 return String(static_cast<StringImp*>(v.imp()));
321}
322
323// ------------------------------ Number ---------------------------------------
324
325Number::Number(int i)
326 : Value(SimpleNumber::fits(i) ? SimpleNumber::make(i) : new NumberImp(static_cast<double>(i))) { }
327
328Number::Number(unsigned int u)
329 : Value(SimpleNumber::fits(u) ? SimpleNumber::make(u) : new NumberImp(static_cast<double>(u))) { }
330
331Number::Number(double d)
332 : Value(SimpleNumber::fits(d) ? SimpleNumber::make((long)d) : (KJS::isNaN(d) ? NumberImp::staticNaN : new NumberImp(d))) { }
333
334Number::Number(long int l)
335 : Value(SimpleNumber::fits(l) ? SimpleNumber::make(l) : new NumberImp(static_cast<double>(l))) { }
336
337Number::Number(long unsigned int l)
338 : Value(SimpleNumber::fits(l) ? SimpleNumber::make(l) : new NumberImp(static_cast<double>(l))) { }
339
340Number Number::dynamicCast(const Value &v)
341{
342 if (v.isNull() || v.type() != NumberType)
343 return Number((NumberImp*)0);
344
345 return Number(static_cast<NumberImp*>(v.imp()));
346}
347
348double Number::value() const
349{
350 if (SimpleNumber::is(rep))
351 return (double)SimpleNumber::value(rep);
352 assert(rep);
353 return ((NumberImp*)rep)->value();
354}
355
356int Number::intValue() const
357{
358 if (SimpleNumber::is(rep))
359 return SimpleNumber::value(rep);
360 return (int)((NumberImp*)rep)->value();
361}
362
363bool Number::isNaN() const
364{
365 return rep == NumberImp::staticNaN;
366}
367
368bool Number::isInf() const
369{
370 if (SimpleNumber::is(rep))
371 return false;
372 return KJS::isInf(((NumberImp*)rep)->value());
373}
Note: See TracBrowser for help on using the repository browser.