1 // -*- c-basic-offset: 2 -*-
3 * This file is part of the KDE libraries
4 * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
5 * Copyright (C) 2001 Peter Kelly (pmk@post.com)
6 * Copyright (C) 2003 Apple Computer, Inc.
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.
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.
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., 59 Temple Place - Suite 330,
21 * Boston, MA 02111-1307, USA.
28 #include "interpreter.h"
36 #include "collector.h"
37 #include "operations.h"
38 #include "error_object.h"
40 #include "simple_number.h"
44 // ----------------------------- ValueImp -------------------------------------
46 #if !USE_CONSERVATIVE_GC
47 ValueImp::ValueImp() :
49 // Tell the garbage collector that this memory block corresponds to a real object now
52 //fprintf(stderr,"ValueImp::ValueImp %p\n",(void*)this);
57 //fprintf(stderr,"ValueImp::~ValueImp %p\n",(void*)this);
61 #if TEST_CONSERVATIVE_GC
62 static bool conservativeMark = false;
64 void ValueImp::useConservativeMark(bool use)
66 conservativeMark = use;
72 //fprintf(stderr,"ValueImp::mark %p\n",(void*)this);
73 #if USE_CONSERVATIVE_GC
75 #elif TEST_CONSERVATIVE_GC
76 if (conservativeMark) {
77 _flags |= VI_CONSERVATIVE_MARKED;
79 if (!(_flags & VI_CONSERVATIVE_MARKED)) {
80 printf("Conservative collector missed ValueImp 0x%x. refcount %d, protect count %d\n", (int)this, refcount, ProtectedValues::getProtectCount(this));
89 bool ValueImp::marked() const
91 // Simple numbers are always considered marked.
92 #if USE_CONSERVATIVE_GC
93 return SimpleNumber::is(this) || _marked;
94 #elif TEST_CONSERVATIVE_GC
95 if (conservativeMark) {
96 return SimpleNumber::is(this) || (_flags & VI_CONSERVATIVE_MARKED);
98 return SimpleNumber::is(this) || (_flags & VI_MARKED);
101 return SimpleNumber::is(this) || (_flags & VI_MARKED);
105 #if !USE_CONSERVATIVE_GC
106 void ValueImp::setGcAllowed()
108 //fprintf(stderr,"ValueImp::setGcAllowed %p\n",(void*)this);
109 // simple numbers are never seen by the collector so setting this
110 // flag is irrelevant
111 if (!SimpleNumber::is(this))
112 _flags |= VI_GCALLOWED;
116 void* ValueImp::operator new(size_t s)
118 return Collector::allocate(s);
121 void ValueImp::operator delete(void*)
123 // Do nothing. So far.
126 bool ValueImp::toUInt32(unsigned&) const
132 double ValueImp::toInteger(ExecState *exec) const
135 if (dispatchToUInt32(i))
137 return roundValue(exec, Value(const_cast<ValueImp*>(this)));
140 int32_t ValueImp::toInt32(ExecState *exec) const
143 if (dispatchToUInt32(i))
146 double d = roundValue(exec, Value(const_cast<ValueImp*>(this)));
147 if (isNaN(d) || isInf(d))
149 double d32 = fmod(d, D32);
151 if (d32 >= D32 / 2.0)
153 else if (d32 < -D32 / 2.0)
156 return static_cast<int32_t>(d32);
159 uint32_t ValueImp::toUInt32(ExecState *exec) const
162 if (dispatchToUInt32(i))
165 double d = roundValue(exec, Value(const_cast<ValueImp*>(this)));
166 if (isNaN(d) || isInf(d))
168 double d32 = fmod(d, D32);
173 return static_cast<uint32_t>(d32);
176 uint16_t ValueImp::toUInt16(ExecState *exec) const
179 if (dispatchToUInt32(i))
182 double d = roundValue(exec, Value(const_cast<ValueImp*>(this)));
183 if (isNaN(d) || isInf(d))
185 double d16 = fmod(d, D16);
190 return static_cast<uint16_t>(d16);
193 // Dispatchers for virtual functions, to special-case simple numbers which
194 // won't be real pointers.
196 Type ValueImp::dispatchType() const
198 if (SimpleNumber::is(this))
203 Value ValueImp::dispatchToPrimitive(ExecState *exec, Type preferredType) const
205 if (SimpleNumber::is(this))
206 return Value(const_cast<ValueImp *>(this));
207 return toPrimitive(exec, preferredType);
210 bool ValueImp::dispatchToBoolean(ExecState *exec) const
212 if (SimpleNumber::is(this))
213 return SimpleNumber::value(this);
214 return toBoolean(exec);
217 double ValueImp::dispatchToNumber(ExecState *exec) const
219 if (SimpleNumber::is(this))
220 return SimpleNumber::value(this);
221 return toNumber(exec);
224 UString ValueImp::dispatchToString(ExecState *exec) const
226 if (SimpleNumber::is(this))
227 return UString::from(SimpleNumber::value(this));
228 return toString(exec);
231 Object ValueImp::dispatchToObject(ExecState *exec) const
233 if (SimpleNumber::is(this))
234 return static_cast<const NumberImp *>(this)->NumberImp::toObject(exec);
235 return toObject(exec);
238 bool ValueImp::dispatchToUInt32(uint32_t& result) const
240 if (SimpleNumber::is(this)) {
241 long i = SimpleNumber::value(this);
247 return toUInt32(result);
250 // ------------------------------ Value ----------------------------------------
252 #if !USE_CONSERVATIVE_GC
254 Value::Value(ValueImp *v)
258 assert (!(rep && !SimpleNumber::is(rep) && *((uint32_t *)rep) == 0 ));
259 assert (!(rep && !SimpleNumber::is(rep) && rep->_flags & ValueImp::VI_MARKED));
264 //fprintf(stderr, "Value::Value(%p) imp=%p ref=%d\n", this, rep, rep->refcount);
269 Value::Value(const Value &v)
273 assert (!(rep && !SimpleNumber::is(rep) && *((uint32_t *)rep) == 0 ));
274 assert (!(rep && !SimpleNumber::is(rep) && rep->_flags & ValueImp::VI_MARKED));
279 //fprintf(stderr, "Value::Value(%p)(copying %p) imp=%p ref=%d\n", this, &v, rep, rep->refcount);
288 //fprintf(stderr, "Value::~Value(%p) imp=%p ref=%d\n", this, rep, rep->refcount);
292 Value& Value::operator=(const Value &v)
296 //fprintf(stderr, "Value::operator=(%p)(copying %p) old imp=%p ref=%d\n", this, &v, rep, rep->refcount);
302 //fprintf(stderr, "Value::operator=(%p)(copying %p) imp=%p ref=%d\n", this, &v, rep, rep->refcount);
308 // ------------------------------ Undefined ------------------------------------
310 Undefined::Undefined() : Value(UndefinedImp::staticUndefined)
314 Undefined Undefined::dynamicCast(const Value &v)
316 if (v.isNull() || v.type() != UndefinedType)
322 // ------------------------------ Null -----------------------------------------
324 Null::Null() : Value(NullImp::staticNull)
328 Null Null::dynamicCast(const Value &v)
330 if (v.isNull() || v.type() != NullType)
336 // ------------------------------ Boolean --------------------------------------
338 Boolean::Boolean(bool b)
339 : Value(b ? BooleanImp::staticTrue : BooleanImp::staticFalse)
343 bool Boolean::value() const
346 return ((BooleanImp*)rep)->value();
349 Boolean Boolean::dynamicCast(const Value &v)
351 if (v.isNull() || v.type() != BooleanType)
352 return static_cast<BooleanImp*>(0);
354 return static_cast<BooleanImp*>(v.imp());
357 // ------------------------------ String ---------------------------------------
359 String::String(const UString &s) : Value(new StringImp(s))
363 UString String::value() const
366 return ((StringImp*)rep)->value();
369 String String::dynamicCast(const Value &v)
371 if (v.isNull() || v.type() != StringType)
374 return String(static_cast<StringImp*>(v.imp()));
377 // ------------------------------ Number ---------------------------------------
379 Number::Number(int i)
380 : Value(SimpleNumber::fits(i) ? SimpleNumber::make(i) : new NumberImp(static_cast<double>(i))) { }
382 Number::Number(unsigned int u)
383 : Value(SimpleNumber::fits(u) ? SimpleNumber::make(u) : new NumberImp(static_cast<double>(u))) { }
385 Number::Number(double d)
386 : Value(SimpleNumber::fits(d) ? SimpleNumber::make((long)d) : (KJS::isNaN(d) ? NumberImp::staticNaN : new NumberImp(d))) { }
388 Number::Number(long int l)
389 : Value(SimpleNumber::fits(l) ? SimpleNumber::make(l) : new NumberImp(static_cast<double>(l))) { }
391 Number::Number(long unsigned int l)
392 : Value(SimpleNumber::fits(l) ? SimpleNumber::make(l) : new NumberImp(static_cast<double>(l))) { }
394 Number Number::dynamicCast(const Value &v)
396 if (v.isNull() || v.type() != NumberType)
397 return Number((NumberImp*)0);
399 return Number(static_cast<NumberImp*>(v.imp()));
402 double Number::value() const
404 if (SimpleNumber::is(rep))
405 return (double)SimpleNumber::value(rep);
407 return ((NumberImp*)rep)->value();
410 int Number::intValue() const
412 if (SimpleNumber::is(rep))
413 return SimpleNumber::value(rep);
414 return (int)((NumberImp*)rep)->value();
417 bool Number::isNaN() const
419 return rep == NumberImp::staticNaN;
422 bool Number::isInf() const
424 if (SimpleNumber::is(rep))
426 return KJS::isInf(((NumberImp*)rep)->value());