• Skip to content
  • Skip to link menu
KDE 4.0 API Reference
  • KDE API Reference
  • kdelibs
  • Sitemap
  • Contact Us
 

KJS

JSImmediate.h

Go to the documentation of this file.
00001 /*
00002  *  This file is part of the KDE libraries
00003  *  Copyright (C) 2003, 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
00004  *  Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org)
00005  *
00006  *  This library is free software; you can redistribute it and/or
00007  *  modify it under the terms of the GNU Library General Public
00008  *  License as published by the Free Software Foundation; either
00009  *  version 2 of the License, or (at your option) any later version.
00010  *
00011  *  This library is distributed in the hope that it will be useful,
00012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  *  Library General Public License for more details.
00015  *
00016  *  You should have received a copy of the GNU Library General Public License
00017  *  along with this library; see the file COPYING.LIB.  If not, write to
00018  *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00019  *  Boston, MA 02110-1301, USA.
00020  *
00021  */
00022 
00023 #ifndef KJS_JS_IMMEDIATE_H
00024 #define KJS_JS_IMMEDIATE_H
00025 
00026 #include <kjs/global.h>
00027 #include "JSType.h"
00028 #include <wtf/Assertions.h>
00029 #include <wtf/AlwaysInline.h>
00030 #include <wtf/MathExtras.h>
00031 #ifdef HAVE_STDINT_H
00032 #include <stdint.h>
00033 #endif
00034 #include <stdlib.h>
00035 #include <math.h>
00036 
00037 namespace KJS {
00038 
00039 class ExecState;
00040 class JSObject;
00041 class JSValue;
00042 class UString;
00043 
00044 KJS_EXPORT extern const double NaN;
00045 
00046 /*
00047  * A JSValue*  is either a pointer to a cell (a heap-allocated object) or an immediate (a type-tagged 
00048  * signed int masquerading as a pointer). The low two bits in a JSValue* are available 
00049  * for type tagging because allocator alignment guarantees they will be 00 in cell pointers.
00050  *
00051  * For example, on a 32 bit system:
00052  *
00053  * JSCell*:       XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX                 00
00054  *               [ high 30 bits: pointer address ]  [ low 2 bits -- always 0 ]
00055  *
00056  * JSImmediate:   XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX                 TT
00057  *               [ high 30 bits: signed int ]       [ low 2 bits -- type tag ]
00058  *
00059  * The bit "payload" (the high 30 bits) is a 30 bit signed int for immediate numbers, a flag to distinguish true/false
00060  * and undefined/null.
00061  *
00062  * Notice that the JSType value of NullType is 4, which requires 3 bits to encode. Since we only have 2 bits 
00063  * available for type tagging, we tag the null immediate with UndefinedType, and JSImmediate::type() has 
00064  * to sort them out.
00065  */
00066 
00067 class KJS_EXPORT JSImmediate {
00068 public:
00069     static ALWAYS_INLINE bool isImmediate(const JSValue* v)
00070     {
00071         return getTag(v) != 0;
00072     }
00073     
00074     static ALWAYS_INLINE bool isNumber(const JSValue* v)
00075     {
00076         return (getTag(v) == NumberType);
00077     }
00078     
00079     static ALWAYS_INLINE bool isBoolean(const JSValue* v)
00080     {
00081         return (getTag(v) == BooleanType);
00082     }
00083     
00084     // Since we have room for only 3 unique tags, null and undefined have to share.
00085     static ALWAYS_INLINE bool isUndefinedOrNull(const JSValue* v)
00086     {
00087         return (getTag(v) == UndefinedType);
00088     }
00089 
00090     static JSValue* from(char);
00091     static JSValue* from(signed char);
00092     static JSValue* from(unsigned char);
00093     static JSValue* from(short);
00094     static JSValue* from(unsigned short);
00095     static JSValue* from(int);
00096     static JSValue* from(unsigned);
00097     static JSValue* from(long);
00098     static JSValue* from(unsigned long);
00099     static JSValue* from(long long);
00100     static JSValue* from(unsigned long long);
00101     static JSValue* from(double);
00102 
00103     static ALWAYS_INLINE bool areBothImmediateNumbers(const JSValue* v1, const JSValue* v2)
00104     {
00105         return (reinterpret_cast<uintptr_t>(v1) & reinterpret_cast<uintptr_t>(v2) & TagMask) == NumberType;
00106     }
00107 
00108     static ALWAYS_INLINE JSValue* andImmediateNumbers(const JSValue* v1, const JSValue* v2)
00109     {
00110         ASSERT(areBothImmediateNumbers(v1, v2));
00111         return reinterpret_cast<JSValue*>(reinterpret_cast<uintptr_t>(v1) & reinterpret_cast<uintptr_t>(v2));
00112     }
00113 
00114     static double toDouble(const JSValue*);
00115     static bool toBoolean(const JSValue*);
00116     static JSObject* toObject(const JSValue*, ExecState*);
00117     static UString toString(const JSValue*);
00118     static JSType type(const JSValue*);
00119 
00120     static bool getUInt32(const JSValue*, uint32_t&);
00121     static bool getTruncatedInt32(const JSValue*, int32_t&);
00122     static bool getTruncatedUInt32(const JSValue*, uint32_t&);
00123 
00124     static int32_t getTruncatedInt32(const JSValue*);
00125 
00126     static JSValue* trueImmediate();
00127     static JSValue* falseImmediate();
00128     static JSValue* undefinedImmediate();
00129     static JSValue* nullImmediate();
00130     
00131 private:
00132     static const uintptr_t TagMask = 3; // type tags are 2 bits long
00133 
00134     // Immediate values are restricted to a 30 bit signed value.
00135     static const int minImmediateInt = -(1 << 29);
00136     static const int maxImmediateInt = (1 << 29) - 1;
00137     static const unsigned maxImmediateUInt = maxImmediateInt;
00138     
00139     static ALWAYS_INLINE JSValue* tag(uintptr_t bits, uintptr_t tag)
00140     {
00141         return reinterpret_cast<JSValue*>(bits | tag);
00142     }
00143     
00144     static ALWAYS_INLINE uintptr_t unTag(const JSValue* v)
00145     {
00146         return reinterpret_cast<uintptr_t>(v) & ~TagMask;
00147     }
00148     
00149     static ALWAYS_INLINE uintptr_t getTag(const JSValue* v)
00150     {
00151         return reinterpret_cast<uintptr_t>(v) & TagMask;
00152     }
00153 };
00154 
00155 ALWAYS_INLINE JSValue* JSImmediate::trueImmediate() { return tag(1 << 2, BooleanType); }
00156 ALWAYS_INLINE JSValue* JSImmediate::falseImmediate() { return tag(0, BooleanType); }
00157 ALWAYS_INLINE JSValue* JSImmediate::undefinedImmediate() { return tag(1 << 2, UndefinedType); }
00158 ALWAYS_INLINE JSValue* JSImmediate::nullImmediate() { return tag(0, UndefinedType); }
00159 
00160 ALWAYS_INLINE bool JSImmediate::toBoolean(const JSValue* v)
00161 {
00162     ASSERT(isImmediate(v));
00163     uintptr_t bits = unTag(v);
00164     return (bits != 0) & (JSImmediate::getTag(v) != UndefinedType);
00165 }
00166 
00167 ALWAYS_INLINE JSValue* JSImmediate::from(char i)
00168 {
00169     return tag(i << 2, NumberType);
00170 }
00171 
00172 ALWAYS_INLINE JSValue* JSImmediate::from(signed char i)
00173 {
00174     return tag(i << 2, NumberType);
00175 }
00176 
00177 ALWAYS_INLINE JSValue* JSImmediate::from(unsigned char i)
00178 {
00179     return tag(i << 2, NumberType);
00180 }
00181 
00182 ALWAYS_INLINE JSValue* JSImmediate::from(short i)
00183 {
00184     return tag(i << 2, NumberType);
00185 }
00186 
00187 ALWAYS_INLINE JSValue* JSImmediate::from(unsigned short i)
00188 {
00189     return tag(i << 2, NumberType);
00190 }
00191 
00192 ALWAYS_INLINE JSValue* JSImmediate::from(int i)
00193 {
00194     if ((i < minImmediateInt) || (i > maxImmediateInt))
00195         return 0;
00196     return tag(i << 2, NumberType);
00197 }
00198 
00199 ALWAYS_INLINE JSValue* JSImmediate::from(unsigned i)
00200 {
00201     if (i > maxImmediateUInt)
00202         return 0;
00203     return tag(i << 2, NumberType);
00204 }
00205 
00206 ALWAYS_INLINE JSValue* JSImmediate::from(long i)
00207 {
00208     if ((i < minImmediateInt) || (i > maxImmediateInt))
00209         return 0;
00210     return tag(i << 2, NumberType);
00211 }
00212 
00213 ALWAYS_INLINE JSValue* JSImmediate::from(unsigned long i)
00214 {
00215     if (i > maxImmediateUInt)
00216         return 0;
00217     return tag(i << 2, NumberType);
00218 }
00219 
00220 ALWAYS_INLINE JSValue* JSImmediate::from(long long i)
00221 {
00222     if ((i < minImmediateInt) || (i > maxImmediateInt))
00223         return 0;
00224     return tag(static_cast<uintptr_t>(i) << 2, NumberType);
00225 }
00226 
00227 ALWAYS_INLINE JSValue* JSImmediate::from(unsigned long long i)
00228 {
00229     if (i > maxImmediateUInt)
00230         return 0;
00231     return tag(static_cast<uintptr_t>(i) << 2, NumberType);
00232 }
00233 
00234 ALWAYS_INLINE JSValue* JSImmediate::from(double d)
00235 {
00236     const int intVal = static_cast<int>(d);
00237 
00238     if ((intVal < minImmediateInt) || (intVal > maxImmediateInt))
00239         return 0;
00240 
00241     // Check for data loss from conversion to int.
00242     if ((intVal != d) || (!intVal && signbit(d)))
00243         return 0;
00244 
00245     return tag(intVal << 2, NumberType);
00246 }
00247 
00248 ALWAYS_INLINE int32_t JSImmediate::getTruncatedInt32(const JSValue* v)
00249 {
00250     ASSERT(isNumber(v));
00251     return static_cast<int32_t>(unTag(v)) >> 2;
00252 }
00253 
00254 ALWAYS_INLINE double JSImmediate::toDouble(const JSValue* v)
00255 {
00256     ASSERT(isImmediate(v));
00257     const int32_t i = static_cast<int32_t>(unTag(v)) >> 2;
00258     if (JSImmediate::getTag(v) == UndefinedType && i)
00259         return NaN;
00260     return i;
00261 }
00262 
00263 ALWAYS_INLINE bool JSImmediate::getUInt32(const JSValue* v, uint32_t& i)
00264 {
00265     const int32_t si = static_cast<int32_t>(unTag(v)) >> 2;
00266     i = si;
00267     return isNumber(v) & (si >= 0);
00268 }
00269 
00270 ALWAYS_INLINE bool JSImmediate::getTruncatedInt32(const JSValue* v, int32_t& i)
00271 {
00272     i = static_cast<int32_t>(unTag(v)) >> 2;
00273     return isNumber(v);
00274 }
00275 
00276 ALWAYS_INLINE bool JSImmediate::getTruncatedUInt32(const JSValue* v, uint32_t& i)
00277 {
00278     return getUInt32(v, i);
00279 }
00280 
00281 } // namespace KJS
00282 
00283 #endif

KJS

Skip menu "KJS"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Class Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • KIO
  • KIOSlave
  • KJS
  •   WTF
  • KJSEmbed
  • KNewStuff
  • KParts
  • Kross
  • KUtils
  • Nepomuk
  •   core
  • Phonon
  •   Backend
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.5.4
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal