/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is the JavaScript 2 Prototype. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1998 * the Initial Developer. All Rights Reserved. * * Contributor(s): * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ #ifndef js2value_h___ #define js2value_h___ /* * Type tags stored in the low bits of a js2val. */ #define JS2VAL_OBJECT 0x0 /* untagged reference to object */ #define JS2VAL_INT 0x1 /* tagged 31-bit integer value */ #define JS2VAL_DOUBLE 0x2 /* tagged reference to double */ #define JS2VAL_LONG 0x4 /* tagged reference to long */ #define JS2VAL_ULONG 0x6 /* tagged reference to unsigned long */ #define JS2VAL_FLOAT 0x8 /* tagged reference to float */ #define JS2VAL_STRING 0xA /* tagged reference to string */ #define JS2VAL_BOOLEAN 0xC /* tagged boolean value */ #define JS2VAL_UNINITIALIZED 0x80 /* reserve this object reference value as an indication that a variable has yet to be initialized */ #define JS2VAL_IS_INITIALIZED(v) (v != JS2VAL_UNINITIALIZED) #define JS2VAL_IS_UNINITIALIZED(v) (v == JS2VAL_UNINITIALIZED) #define JS2VAL_INACCESSIBLE 0x90 /* reserve this object reference value as an indication that a variable has yet to become available */ #define JS2VAL_IS_ACCESSIBLE(v) (v != JS2VAL_INACCESSIBLE) #define JS2VAL_IS_INACCESSIBLE(v) (v == JS2VAL_INACCESSIBLE) #define JS2VAL_FUTUREVALUE 0xA0 /* reserve this object reference value as an indication that a variable has to have it's initializer run */ #define JS2VAL_IS_FUTURE(v) (v == JS2VAL_FUTUREVALUE) #define JS2VAL_IS_SPECIALREF(v) (v && ((v | 0xF0) == 0xF0)) /* Type tag bitfield length and derived macros. */ #define JS2VAL_TAGBITS 4 #define JS2VAL_TAGMASK JS_BITMASK(JS2VAL_TAGBITS) #define JS2VAL_TAG(v) ((v) & JS2VAL_TAGMASK) #define JS2VAL_SETTAG(v,t) ((v) | (t)) #define JS2VAL_CLRTAG(v) ((v) & ~(js2val)JS2VAL_TAGMASK) #define JS2VAL_ALIGN JS_BIT(JS2VAL_TAGBITS) #define JS2VAL_INT_POW2(n) ((js2val)1 << (n)) #define JS2VAL_INT_MIN ((js2val)1 - JS2VAL_INT_POW2(30)) #define JS2VAL_INT_MAX (JS2VAL_INT_POW2(30) - 1) #define INT_TO_JS2VAL(i) (((js2val)(i) << 1) | JS2VAL_INT) #define JS2VAL_TO_INT(v) ((int32)(v) >> 1) #define INT_FITS_IN_JS2VAL(i) ((uint32)((i)+JS2VAL_INT_MAX) <= 2*JS2VAL_INT_MAX) #define INT_FITS_IN_JSVAL(i) ((jsuint)((i)+JSVAL_INT_MAX) <= 2*JSVAL_INT_MAX) #define LONG_IS_INT(x) (JSLL_CMP((x), >, -20) && JSLL_CMP(20, >, (x))) #define ULONG_IS_INT(x) (JSLL_CMP(JS2VAL_INT_MAX, >, (x))) #define JS2VAL_VOID INT_TO_JS2VAL(0 - JS2VAL_INT_POW2(30)) #define JS2VAL_NULL OBJECT_TO_JS2VAL(0) #define JS2VAL_FALSE BOOLEAN_TO_JS2VAL(false) #define JS2VAL_TRUE BOOLEAN_TO_JS2VAL(true) #define JS2VAL_ZERO INT_TO_JS2VAL(0) /* Predicates for type testing. */ #define JS2VAL_IS_OBJECT(v) ((JS2VAL_TAG(v) == JS2VAL_OBJECT) && !JS2VAL_IS_SPECIALREF(v)) // XXX think about some way of making this faster... #define JS2VAL_IS_NUMBER(v) (JS2VAL_IS_INT(v) || JS2VAL_IS_DOUBLE(v) || JS2VAL_IS_LONG(v) || JS2VAL_IS_ULONG(v) || JS2VAL_IS_FLOAT(v)) #define JS2VAL_IS_INT(v) (((v) & JS2VAL_INT) && (v) != JS2VAL_VOID) #define JS2VAL_IS_DOUBLE(v) (JS2VAL_TAG(v) == JS2VAL_DOUBLE) #define JS2VAL_IS_STRING(v) (JS2VAL_TAG(v) == JS2VAL_STRING) #define JS2VAL_IS_BOOLEAN(v) (JS2VAL_TAG(v) == JS2VAL_BOOLEAN) #define JS2VAL_IS_NULL(v) ((v) == JS2VAL_NULL) #define JS2VAL_IS_VOID(v) ((v) == JS2VAL_VOID) #define JS2VAL_IS_PRIMITIVE(v) (!JS2VAL_IS_OBJECT(v) || JS2VAL_IS_NULL(v)) #define JS2VAL_IS_LONG(v) (JS2VAL_TAG(v) == JS2VAL_LONG) #define JS2VAL_IS_ULONG(v) (JS2VAL_TAG(v) == JS2VAL_ULONG) #define JS2VAL_IS_FLOAT(v) (JS2VAL_TAG(v) == JS2VAL_FLOAT) /* Objects, strings, and doubles are GC'ed. */ #define JS2VAL_IS_GCTHING(v) (!((v) & JS2VAL_INT) && !JS2VAL_IS_BOOLEAN(v)) #define JS2VAL_TO_GCTHING(v) ((void *)JS2VAL_CLRTAG(v)) #define JS2VAL_TO_OBJECT(v) ((JS2Object *)JS2VAL_TO_GCTHING(v)) #define JS2VAL_TO_DOUBLE(v) ((float64 *)JS2VAL_TO_GCTHING(v)) #define JS2VAL_TO_STRING(v) ((String *)JS2VAL_TO_GCTHING(v)) #define JS2VAL_TO_LONG(v) ((int64 *)JS2VAL_TO_GCTHING(v)) #define JS2VAL_TO_ULONG(v) ((uint64 *)JS2VAL_TO_GCTHING(v)) #define JS2VAL_TO_FLOAT(v) ((float32 *)JS2VAL_TO_GCTHING(v)) #define OBJECT_TO_JS2VAL(obj) ((js2val)(obj)) #define DOUBLE_TO_JS2VAL(dp) JS2VAL_SETTAG((js2val)(dp), JS2VAL_DOUBLE) #define STRING_TO_JS2VAL(str) JS2VAL_SETTAG((js2val)(str), JS2VAL_STRING) #define LONG_TO_JS2VAL(dp) JS2VAL_SETTAG((js2val)(dp), JS2VAL_LONG) #define ULONG_TO_JS2VAL(dp) JS2VAL_SETTAG((js2val)(dp), JS2VAL_ULONG) #define FLOAT_TO_JS2VAL(dp) JS2VAL_SETTAG((js2val)(dp), JS2VAL_FLOAT) /* Convert between boolean and js2val. */ #define JS2VAL_TO_BOOLEAN(v) (((v) >> JS2VAL_TAGBITS) != 0) #define BOOLEAN_TO_JS2VAL(b) JS2VAL_SETTAG((js2val)(b) << JS2VAL_TAGBITS, \ JS2VAL_BOOLEAN) #ifdef IS_LITTLE_ENDIAN #define JSDOUBLE_HI32(x) (((uint32 *)&(x))[1]) #define JSDOUBLE_LO32(x) (((uint32 *)&(x))[0]) #else #define JSDOUBLE_HI32(x) (((uint32 *)&(x))[0]) #define JSDOUBLE_LO32(x) (((uint32 *)&(x))[1]) #endif #define JSDOUBLE_HI32_SIGNBIT 0x80000000 #define JSDOUBLE_HI32_EXPMASK 0x7ff00000 #define JSDOUBLE_HI32_MANTMASK 0x000fffff #define JSDOUBLE_IS_NaN(x) \ ((JSDOUBLE_HI32(x) & JSDOUBLE_HI32_EXPMASK) == JSDOUBLE_HI32_EXPMASK && \ (JSDOUBLE_LO32(x) || (JSDOUBLE_HI32(x) & JSDOUBLE_HI32_MANTMASK))) #define JSDOUBLE_IS_INFINITE(x) \ ((JSDOUBLE_HI32(x) & ~JSDOUBLE_HI32_SIGNBIT) == JSDOUBLE_HI32_EXPMASK && \ !JSDOUBLE_LO32(x)) #define JSDOUBLE_IS_FINITE(x) \ ((JSDOUBLE_HI32(x) & JSDOUBLE_HI32_EXPMASK) != JSDOUBLE_HI32_EXPMASK) #define JSDOUBLE_IS_POSZERO(d) (JSDOUBLE_HI32(d) == 0 && JSDOUBLE_LO32(d) == 0) #define JSDOUBLE_IS_NEGZERO(d) (JSDOUBLE_HI32(d) == JSDOUBLE_HI32_SIGNBIT && \ JSDOUBLE_LO32(d) == 0) /* * JSDOUBLE_IS_INT first checks that d is neither NaN nor infinite, to avoid * raising SIGFPE on platforms such as Alpha Linux, then (only if the cast is * safe) leaves i as (jsint)d. This also avoid anomalous NaN floating point * comparisons under MSVC. */ #define JSDOUBLE_IS_INT(d, i) (JSDOUBLE_IS_FINITE(d) \ && !JSDOUBLE_IS_NEGZERO(d) \ && ((d) == (i = (int32)(d)))) #define JS2VAL_IS_UNDEFINED(v) JS2VAL_IS_VOID(v) #define JS2VAL_UNDEFINED JS2VAL_VOID typedef uint32 js2val; enum Phase { CompilePhase, RunPhase }; // XXX where should these be? typedef uint8 AccessSet; enum Access { ReadAccess = 0x1, WriteAccess = 0x2, ReadWriteAccess = ReadAccess | WriteAccess}; typedef std::vector ValueList; #endif