root/core/atom.h

/* [<][>][^][v][top][bottom][index][help] */

INCLUDED FROM


/* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*- */
/* vi: set ts=4 sw=4 expandtab: (add to ~/.vimrc: set modeline modelines=5) */
/* ***** 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 [Open Source Virtual Machine.].
 *
 * The Initial Developer of the Original Code is
 * Adobe System Incorporated.
 * Portions created by the Initial Developer are Copyright (C) 2004-2006
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *   Adobe AS3 Team
 *
 * 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 __avmplus_atom__
#define __avmplus_atom__


namespace avmplus
{
    // Atom should really be an intptr_t, but doing so can cause problematic compiles
    // because some platforms define intptr_t as an int64, and some as a long, which
    // create different overload possibilities in a few cases. Ideally, Atom should
    // be a unique pointer type (as it is in TT) but for now, avoid the code churn
    // by defining it the "old" way
    //
    // math friendly pointer (64 bits in LP 64 systems)
    #if defined (_MSC_VER) && (_MSC_VER >= 1300)
        #define AVMPLUS_TYPE_IS_POINTER_SIZED __w64
    #else
        #define AVMPLUS_TYPE_IS_POINTER_SIZED
    #endif
    #ifdef AVMPLUS_64BIT
    typedef AVMPLUS_TYPE_IS_POINTER_SIZED int64_t Atom;
    #else
    typedef AVMPLUS_TYPE_IS_POINTER_SIZED int32_t Atom;
    #endif

    /**
     * The AtomConstants namespace defines constants for
     * manipulating atoms.
     *
     * The atom is a primitive value in ActionScript.  Since
     * ActionScript is a dynamically typed language, an atom can
     * belong to one of several types: null, undefined, number,
     * integer, string, boolean, object reference.
     *
     * Atoms are encoded with care to take up the minimum
     * possible space.  An atom is represented by a 32-bit
     * integer, with the bottom 3 bits indicating the type.
     *
     *      32 bit atom
     *
     *  31             16 15     8 7   3 210
     *  dddddddd dddddddd dddddddd ddddd TTT
     *
     *  TTT
     *  000  - untagged
     *  001  object
     *  010  string
     *  011  namespace
     *  100  undefined
     *  101  boolean
     *  110  integer
     *  111  double
     *
     *  - using last 3 bits means allocations must be 8-byte aligned.
     *  - related types are 1 bit apart, e.g. int/double
     *
     *  kInteger atoms are used to represent integer values from -2^28..2^28-1,
     *  regardless of whether the context implies int, uint, or Number.
     *  If a number doesn't fit into that range it is stored as a kDoubleType
     *
     */
    namespace AtomConstants
    {
        /**
         * @name Atom types
         * These are the type values that appear in the bottom
         * 3 bits of an atom.
         */
        /*@{*/
        // cannot use 0 as tag, breaks atomWriteBarrier
        const Atom kUnusedAtomTag = 0;
        const Atom kObjectType    = 1;  // null=1
        const Atom kStringType    = 2;  // null=2
        const Atom kNamespaceType = 3;  // null=3
        const Atom kSpecialType   = 4;  // undefined=4
        const Atom kBooleanType   = 5;  // false=5 true=13
        const Atom kIntptrType    = 6;
        const Atom kDoubleType    = 7;
        /*@}*/

        /*
        other things you can do with math on atoms

        isNull          (unsigned)a < 4
        isUndefined     a == undefinedAtom
        isSpecial       (unsigned)a <= 4
        isNumber        a & 6 == 6

                            ^8  jlt(a<8)    ^2      jle(a<=4)
        true        1110  0110  t           1100    f
        false       0110  1110  f           0100    t
        undefined   0100  1100  f           0110    f
        */

        /**
         * @name Special atom values
         * These are the atoms for undefined, null, true
         * and false.
         */
        /*@{*/
        // there is no single null atom.  use isNull() to test, or
        // one of the following typed null atoms.  if you must, use NULL (0).
        const Atom nullObjectAtom = kObjectType|0;
        const Atom nullStringAtom = kStringType|0;
        const Atom nullNsAtom     = kNamespaceType|0;
        const Atom undefinedAtom  = kSpecialType|0; // 0x03
        const Atom trueAtom       = kBooleanType|0x08; // 0x0D
        const Atom falseAtom      = kBooleanType|0x00; // 0x05
        const Atom zeroIntAtom    = Atom(kIntptrType|0);

        // used in unreachable "return" clauses as a self-documenting invalid value.
        const Atom unreachableAtom = kUnusedAtomTag;
        /*@}*/

    }

#ifdef AVMPLUS_64BIT
    // in 64-bit builds, integer atoms can hold a 53-bit signed value.
    // (this is so that integer values can be interchanged with doubles with no loss of precision)
    const intptr_t atomMinIntValue = -(1LL<<53);
    const intptr_t atomMaxIntValue = (1LL<<53)-1;
#else
    // in 32-bit builds, integer atoms can hold a 29-bit signed value.
    const intptr_t atomMinIntValue = -(1L<<29);
    const intptr_t atomMaxIntValue = (1L<<29)-1;
#endif

    // sadly, these generate better code than the inlines in atom-inlines.h
    #define atomKind(a)     ((Atom)((uintptr_t(a) & 7)))
    #define atomPtr(a)      ((void*)(uintptr_t(a) & ~7))

    #define ISNULL(a) (((uintptr)a) < (uintptr)kSpecialType)

    // returns true if atom type is int.
    // Note that this DOES NOT imply that the Atom's value will
    // fit into an int32 (or a uint32); an integer atom's value
    // will always fit into an intptr_t, which may be more than
    // an int32 (or uint32) will hold on 64-bit architectures.
    bool            atomIsIntptr(Atom atom);

    // return true iff both atoms are of the given type. sometimes this is slightly
    // faster than calling atomIs(b1)&&atomIs(b2). (And yes, "atomIsBoth" is poor
    // grammar in English, but follows the "atomIsXXX -> bool" pattern)
    bool            atomIsBothIntptr(Atom atom1, Atom atom2);

    // if the atom is kIntptrType and will fit into an int32_t, return true
    // if the atom is kIntptrType and will NOT fit into an int32_t, return false
    // if the atom is not kIntptrType, assert
    bool            atomCanBeInt32(Atom atom);
    // if the atom is kIntptrType and will fit into an uint32_t, return true
    // if the atom is kIntptrType and will NOT fit into an uint32_t, return false
    // if the atom is not kIntptrType, assert
    bool            atomCanBeUint32(Atom atom);

    // getters to obtain the value.
    // these getters require that the type of the Atom be *exactly* what is requested;
    // no coercion is done (e.g., calling getDouble() on a Atom containing TypeInt will assert).
    intptr_t        atomGetIntptr(Atom atom);

    // if the given intptr can fit into an kIntptrType atom, return true.
    // if not (the magnitude is too large/small), return false.
    // WARNING: do not pass an (unsigned) uintptr_t value; you may get incorrect results.
    bool            atomIsValidIntptrValue(const intptr_t i);

    // if the given uintptr can fit into an kIntptrType atom, return true.
    // if not (the magnitude is too large/small), return false.
    // WARNING: do not pass a (signed) intptr_t value; you may get incorrect results.
    bool            atomIsValidIntptrValue_u(const uintptr_t u);

    // macro for profiling the frequencies of different Atom tags.
    // Must include vprof.h.  usage:   tagprof("histogram for my_atom", my_atom);
    #ifdef DOPROF
    #  define tagprof(n,v) _nhprof(n, uintptr_t(v)&7, 8, 0, 1, 2, 3, 4, 5, 6, 7)
    #else
    #  define tagprof(n,v)
    #endif

}

#endif // __avmplus_atom__

/* [<][>][^][v][top][bottom][index][help] */