22676086cb86ac3d1741c75b2c5969e36e4e6518
[WebKit-https.git] / JavaScriptCore / kjs / value.cpp
1 // -*- c-basic-offset: 2 -*-
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.
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., 59 Temple Place - Suite 330,
21  *  Boston, MA 02111-1307, USA.
22  *
23  */
24
25 #include "value.h"
26 #include "object.h"
27 #include "types.h"
28 #include "interpreter.h"
29
30 #include <assert.h>
31 #include <math.h>
32 #include <stdio.h>
33 #include <string.h>
34
35 #include "internal.h"
36 #include "collector.h"
37 #include "operations.h"
38 #include "error_object.h"
39 #include "nodes.h"
40 #include "simple_number.h"
41
42 using namespace KJS;
43
44 // ----------------------------- ValueImp -------------------------------------
45
46 #if !USE_CONSERVATIVE_GC
47 ValueImp::ValueImp() :
48   refcount(0),
49   // Tell the garbage collector that this memory block corresponds to a real object now
50   _flags(VI_CREATED)
51 {
52   //fprintf(stderr,"ValueImp::ValueImp %p\n",(void*)this);
53 }
54
55 ValueImp::~ValueImp()
56 {
57   //fprintf(stderr,"ValueImp::~ValueImp %p\n",(void*)this);
58 }
59 #endif
60
61 #if TEST_CONSERVATIVE_GC
62 static bool conservativeMark = false;
63
64 void ValueImp::useConservativeMark(bool use)
65 {
66   conservativeMark = use;
67 }
68 #endif
69
70 void ValueImp::mark()
71 {
72   //fprintf(stderr,"ValueImp::mark %p\n",(void*)this);
73 #if USE_CONSERVATIVE_GC
74   _marked = true;
75 #elif TEST_CONSERVATIVE_GC
76   if (conservativeMark) {
77     _flags |= VI_CONSERVATIVE_MARKED;
78   } else {
79     if (!(_flags | VI_CONSERVATIVE_MARKED)) {
80       printf("Conservative collector missed ValueImp 0x%x.\n", (int)this);
81     }
82     _flags |= VI_MARKED;
83   }
84 #else
85   _flags |= VI_MARKED;
86 #endif
87 }
88
89 bool ValueImp::marked() const
90 {
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);
97   } else {
98     return SimpleNumber::is(this) || (_flags & VI_MARKED);
99   }
100 #else
101   return SimpleNumber::is(this) || (_flags & VI_MARKED);
102 #endif
103 }
104
105 #if !USE_CONSERVATIVE_GC
106 void ValueImp::setGcAllowed()
107 {
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;
113 }
114 #endif
115
116 void* ValueImp::operator new(size_t s)
117 {
118   return Collector::allocate(s);
119 }
120
121 void ValueImp::operator delete(void*)
122 {
123   // Do nothing. So far.
124 }
125
126 bool ValueImp::toUInt32(unsigned&) const
127 {
128   return false;
129 }
130
131 // ECMA 9.4
132 double ValueImp::toInteger(ExecState *exec) const
133 {
134   uint32_t i;
135   if (dispatchToUInt32(i))
136     return i;
137   return roundValue(exec, Value(const_cast<ValueImp*>(this)));
138 }
139
140 int32_t ValueImp::toInt32(ExecState *exec) const
141 {
142   uint32_t i;
143   if (dispatchToUInt32(i))
144     return i;
145
146   double d = roundValue(exec, Value(const_cast<ValueImp*>(this)));
147   if (isNaN(d) || isInf(d))
148     return 0;
149   double d32 = fmod(d, D32);
150
151   if (d32 >= D32 / 2.0)
152     d32 -= D32;
153   else if (d32 < -D32 / 2.0)
154     d32 += D32;
155
156   return static_cast<int32_t>(d32);
157 }
158
159 uint32_t ValueImp::toUInt32(ExecState *exec) const
160 {
161   uint32_t i;
162   if (dispatchToUInt32(i))
163     return i;
164
165   double d = roundValue(exec, Value(const_cast<ValueImp*>(this)));
166   if (isNaN(d) || isInf(d))
167     return 0;
168   double d32 = fmod(d, D32);
169
170   if (d32 < 0)
171     d32 += D32;
172
173   return static_cast<uint32_t>(d32);
174 }
175
176 uint16_t ValueImp::toUInt16(ExecState *exec) const
177 {
178   uint32_t i;
179   if (dispatchToUInt32(i))
180     return i;
181
182   double d = roundValue(exec, Value(const_cast<ValueImp*>(this)));
183   if (isNaN(d) || isInf(d))
184     return 0;
185   double d16 = fmod(d, D16);
186
187   if (d16 < 0)
188     d16 += D16;
189
190   return static_cast<uint16_t>(d16);
191 }
192
193 // Dispatchers for virtual functions, to special-case simple numbers which
194 // won't be real pointers.
195
196 Type ValueImp::dispatchType() const
197 {
198   if (SimpleNumber::is(this))
199     return NumberType;
200   return type();
201 }
202
203 Value ValueImp::dispatchToPrimitive(ExecState *exec, Type preferredType) const
204 {
205   if (SimpleNumber::is(this))
206     return Value(const_cast<ValueImp *>(this));
207   return toPrimitive(exec, preferredType);
208 }
209
210 bool ValueImp::dispatchToBoolean(ExecState *exec) const
211 {
212   if (SimpleNumber::is(this))
213     return SimpleNumber::value(this);
214   return toBoolean(exec);
215 }
216
217 double ValueImp::dispatchToNumber(ExecState *exec) const
218 {
219   if (SimpleNumber::is(this))
220     return SimpleNumber::value(this);
221   return toNumber(exec);
222 }
223
224 UString ValueImp::dispatchToString(ExecState *exec) const
225 {
226   if (SimpleNumber::is(this))
227     return UString::from(SimpleNumber::value(this));
228   return toString(exec);
229 }
230
231 Object ValueImp::dispatchToObject(ExecState *exec) const
232 {
233   if (SimpleNumber::is(this))
234     return static_cast<const NumberImp *>(this)->NumberImp::toObject(exec);
235   return toObject(exec);
236 }
237
238 bool ValueImp::dispatchToUInt32(uint32_t& result) const
239 {
240   if (SimpleNumber::is(this)) {
241     long i = SimpleNumber::value(this);
242     if (i < 0)
243       return false;
244     result = i;
245     return true;
246   }
247   return toUInt32(result);
248 }
249
250 // ------------------------------ Value ----------------------------------------
251
252 #if !USE_CONSERVATIVE_GC
253
254 Value::Value(ValueImp *v)
255 {
256   rep = v;
257 #if DEBUG_COLLECTOR
258   assert (!(rep && !SimpleNumber::is(rep) && *((uint32_t *)rep) == 0 ));
259   assert (!(rep && !SimpleNumber::is(rep) && rep->_flags & ValueImp::VI_MARKED));
260 #endif
261   if (v)
262   {
263     v->ref();
264     //fprintf(stderr, "Value::Value(%p) imp=%p ref=%d\n", this, rep, rep->refcount);
265     v->setGcAllowed();
266   }
267 }
268
269 Value::Value(const Value &v)
270 {
271   rep = v.imp();
272 #if DEBUG_COLLECTOR
273   assert (!(rep && !SimpleNumber::is(rep) && *((uint32_t *)rep) == 0 ));
274   assert (!(rep && !SimpleNumber::is(rep) && rep->_flags & ValueImp::VI_MARKED));
275 #endif
276   if (rep)
277   {
278     rep->ref();
279     //fprintf(stderr, "Value::Value(%p)(copying %p) imp=%p ref=%d\n", this, &v, rep, rep->refcount);
280   }
281 }
282
283 Value::~Value()
284 {
285   if (rep)
286   {
287     rep->deref();
288     //fprintf(stderr, "Value::~Value(%p) imp=%p ref=%d\n", this, rep, rep->refcount);
289   }
290 }
291
292 Value& Value::operator=(const Value &v)
293 {
294   if (rep) {
295     rep->deref();
296     //fprintf(stderr, "Value::operator=(%p)(copying %p) old imp=%p ref=%d\n", this, &v, rep, rep->refcount);
297   }
298   rep = v.imp();
299   if (rep)
300   {
301     rep->ref();
302     //fprintf(stderr, "Value::operator=(%p)(copying %p) imp=%p ref=%d\n", this, &v, rep, rep->refcount);
303   }
304   return *this;
305 }
306 #endif
307
308 // ------------------------------ Undefined ------------------------------------
309
310 Undefined::Undefined() : Value(UndefinedImp::staticUndefined)
311 {
312 }
313
314 Undefined Undefined::dynamicCast(const Value &v)
315 {
316   if (v.isNull() || v.type() != UndefinedType)
317     return Undefined(0);
318
319   return Undefined();
320 }
321
322 // ------------------------------ Null -----------------------------------------
323
324 Null::Null() : Value(NullImp::staticNull)
325 {
326 }
327
328 Null Null::dynamicCast(const Value &v)
329 {
330   if (v.isNull() || v.type() != NullType)
331     return Null(0);
332
333   return Null();
334 }
335
336 // ------------------------------ Boolean --------------------------------------
337
338 Boolean::Boolean(bool b)
339   : Value(b ? BooleanImp::staticTrue : BooleanImp::staticFalse)
340 {
341 }
342
343 bool Boolean::value() const
344 {
345   assert(rep);
346   return ((BooleanImp*)rep)->value();
347 }
348
349 Boolean Boolean::dynamicCast(const Value &v)
350 {
351   if (v.isNull() || v.type() != BooleanType)
352     return static_cast<BooleanImp*>(0);
353
354   return static_cast<BooleanImp*>(v.imp());
355 }
356
357 // ------------------------------ String ---------------------------------------
358
359 String::String(const UString &s) : Value(new StringImp(s))
360 {
361 }
362
363 UString String::value() const
364 {
365   assert(rep);
366   return ((StringImp*)rep)->value();
367 }
368
369 String String::dynamicCast(const Value &v)
370 {
371   if (v.isNull() || v.type() != StringType)
372     return String(0);
373
374   return String(static_cast<StringImp*>(v.imp()));
375 }
376
377 // ------------------------------ Number ---------------------------------------
378
379 Number::Number(int i)
380   : Value(SimpleNumber::fits(i) ? SimpleNumber::make(i) : new NumberImp(static_cast<double>(i))) { }
381
382 Number::Number(unsigned int u)
383   : Value(SimpleNumber::fits(u) ? SimpleNumber::make(u) : new NumberImp(static_cast<double>(u))) { }
384
385 Number::Number(double d)
386   : Value(SimpleNumber::fits(d) ? SimpleNumber::make((long)d) : (KJS::isNaN(d) ? NumberImp::staticNaN : new NumberImp(d))) { }
387
388 Number::Number(long int l)
389   : Value(SimpleNumber::fits(l) ? SimpleNumber::make(l) : new NumberImp(static_cast<double>(l))) { }
390
391 Number::Number(long unsigned int l)
392   : Value(SimpleNumber::fits(l) ? SimpleNumber::make(l) : new NumberImp(static_cast<double>(l))) { }
393
394 Number Number::dynamicCast(const Value &v)
395 {
396   if (v.isNull() || v.type() != NumberType)
397     return Number((NumberImp*)0);
398
399   return Number(static_cast<NumberImp*>(v.imp()));
400 }
401
402 double Number::value() const
403 {
404   if (SimpleNumber::is(rep))
405     return (double)SimpleNumber::value(rep);
406   assert(rep);
407   return ((NumberImp*)rep)->value();
408 }
409
410 int Number::intValue() const
411 {
412   if (SimpleNumber::is(rep))
413     return SimpleNumber::value(rep);
414   return (int)((NumberImp*)rep)->value();
415 }
416
417 bool Number::isNaN() const
418 {
419   return rep == NumberImp::staticNaN;
420 }
421
422 bool Number::isInf() const
423 {
424   if (SimpleNumber::is(rep))
425     return false;
426   return KJS::isInf(((NumberImp*)rep)->value());
427 }