mirror of https://github.com/axmolengine/axmol.git
Updated spidermonkey-win32 to FF14.0.1.
This commit is contained in:
parent
5b89e8d410
commit
bbf3c4843a
|
@ -0,0 +1,91 @@
|
|||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=4 sw=4 et tw=99 ft=cpp:
|
||||
*
|
||||
* ***** 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 SpiderMonkey JavaScript engine.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Terrence Cole <terrence@mozilla.com>
|
||||
*
|
||||
* 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 BitArray_h__
|
||||
#define BitArray_h__
|
||||
|
||||
#include "jstypes.h"
|
||||
|
||||
#include "js/TemplateLib.h"
|
||||
|
||||
namespace js {
|
||||
|
||||
template <size_t nbits>
|
||||
class BitArray {
|
||||
private:
|
||||
uintptr_t map[nbits / JS_BITS_PER_WORD + (nbits % JS_BITS_PER_WORD == 0 ? 0 : 1)];
|
||||
|
||||
public:
|
||||
void clear(bool value) {
|
||||
if (value)
|
||||
memset(map, 0xFF, sizeof(map));
|
||||
else
|
||||
memset(map, 0, sizeof(map));
|
||||
}
|
||||
|
||||
inline bool get(size_t offset) const {
|
||||
uintptr_t index, mask;
|
||||
getMarkWordAndMask(offset, &index, &mask);
|
||||
return map[index] & mask;
|
||||
}
|
||||
|
||||
inline void set(size_t offset) {
|
||||
uintptr_t index, mask;
|
||||
getMarkWordAndMask(offset, &index, &mask);
|
||||
map[index] |= mask;
|
||||
}
|
||||
|
||||
inline void unset(size_t offset) {
|
||||
uintptr_t index, mask;
|
||||
getMarkWordAndMask(offset, &index, &mask);
|
||||
map[index] &= ~mask;
|
||||
}
|
||||
|
||||
private:
|
||||
inline void getMarkWordAndMask(size_t offset,
|
||||
uintptr_t *indexp, uintptr_t *maskp) const {
|
||||
*indexp = offset >> tl::FloorLog2<JS_BITS_PER_WORD>::result;
|
||||
*maskp = uintptr_t(1) << (offset & (JS_BITS_PER_WORD - 1));
|
||||
}
|
||||
};
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
#endif
|
|
@ -0,0 +1,523 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sw=4 et tw=78:
|
||||
*
|
||||
* ***** 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 SpiderMonkey global object code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* the Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of 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 jsgc_barrier_h___
|
||||
#define jsgc_barrier_h___
|
||||
|
||||
#include "jsapi.h"
|
||||
#include "jscell.h"
|
||||
|
||||
#include "js/HashTable.h"
|
||||
|
||||
/*
|
||||
* A write barrier is a mechanism used by incremental or generation GCs to
|
||||
* ensure that every value that needs to be marked is marked. In general, the
|
||||
* write barrier should be invoked whenever a write can cause the set of things
|
||||
* traced through by the GC to change. This includes:
|
||||
* - writes to object properties
|
||||
* - writes to array slots
|
||||
* - writes to fields like JSObject::shape_ that we trace through
|
||||
* - writes to fields in private data, like JSGenerator::obj
|
||||
* - writes to non-markable fields like JSObject::private that point to
|
||||
* markable data
|
||||
* The last category is the trickiest. Even though the private pointers does not
|
||||
* point to a GC thing, changing the private pointer may change the set of
|
||||
* objects that are traced by the GC. Therefore it needs a write barrier.
|
||||
*
|
||||
* Every barriered write should have the following form:
|
||||
* <pre-barrier>
|
||||
* obj->field = value; // do the actual write
|
||||
* <post-barrier>
|
||||
* The pre-barrier is used for incremental GC and the post-barrier is for
|
||||
* generational GC.
|
||||
*
|
||||
* PRE-BARRIER
|
||||
*
|
||||
* To understand the pre-barrier, let's consider how incremental GC works. The
|
||||
* GC itself is divided into "slices". Between each slice, JS code is allowed to
|
||||
* run. Each slice should be short so that the user doesn't notice the
|
||||
* interruptions. In our GC, the structure of the slices is as follows:
|
||||
*
|
||||
* 1. ... JS work, which leads to a request to do GC ...
|
||||
* 2. [first GC slice, which performs all root marking and possibly more marking]
|
||||
* 3. ... more JS work is allowed to run ...
|
||||
* 4. [GC mark slice, which runs entirely in drainMarkStack]
|
||||
* 5. ... more JS work ...
|
||||
* 6. [GC mark slice, which runs entirely in drainMarkStack]
|
||||
* 7. ... more JS work ...
|
||||
* 8. [GC marking finishes; sweeping done non-incrementally; GC is done]
|
||||
* 9. ... JS continues uninterrupted now that GC is finishes ...
|
||||
*
|
||||
* Of course, there may be a different number of slices depending on how much
|
||||
* marking is to be done.
|
||||
*
|
||||
* The danger inherent in this scheme is that the JS code in steps 3, 5, and 7
|
||||
* might change the heap in a way that causes the GC to collect an object that
|
||||
* is actually reachable. The write barrier prevents this from happening. We use
|
||||
* a variant of incremental GC called "snapshot at the beginning." This approach
|
||||
* guarantees the invariant that if an object is reachable in step 2, then we
|
||||
* will mark it eventually. The name comes from the idea that we take a
|
||||
* theoretical "snapshot" of all reachable objects in step 2; all objects in
|
||||
* that snapshot should eventually be marked. (Note that the write barrier
|
||||
* verifier code takes an actual snapshot.)
|
||||
*
|
||||
* The basic correctness invariant of a snapshot-at-the-beginning collector is
|
||||
* that any object reachable at the end of the GC (step 9) must either:
|
||||
* (1) have been reachable at the beginning (step 2) and thus in the snapshot
|
||||
* (2) or must have been newly allocated, in steps 3, 5, or 7.
|
||||
* To deal with case (2), any objects allocated during an incremental GC are
|
||||
* automatically marked black.
|
||||
*
|
||||
* This strategy is actually somewhat conservative: if an object becomes
|
||||
* unreachable between steps 2 and 8, it would be safe to collect it. We won't,
|
||||
* mainly for simplicity. (Also, note that the snapshot is entirely
|
||||
* theoretical. We don't actually do anything special in step 2 that we wouldn't
|
||||
* do in a non-incremental GC.
|
||||
*
|
||||
* It's the pre-barrier's job to maintain the snapshot invariant. Consider the
|
||||
* write "obj->field = value". Let the prior value of obj->field be
|
||||
* value0. Since it's possible that value0 may have been what obj->field
|
||||
* contained in step 2, when the snapshot was taken, the barrier marks
|
||||
* value0. Note that it only does this if we're in the middle of an incremental
|
||||
* GC. Since this is rare, the cost of the write barrier is usually just an
|
||||
* extra branch.
|
||||
*
|
||||
* In practice, we implement the pre-barrier differently based on the type of
|
||||
* value0. E.g., see JSObject::writeBarrierPre, which is used if obj->field is
|
||||
* a JSObject*. It takes value0 as a parameter.
|
||||
*
|
||||
* POST-BARRIER
|
||||
*
|
||||
* These are not yet implemented. Once we get generational GC, they will allow
|
||||
* us to keep track of pointers from non-nursery space into the nursery.
|
||||
*
|
||||
* IMPLEMENTATION DETAILS
|
||||
*
|
||||
* Since it would be awkward to change every write to memory into a function
|
||||
* call, this file contains a bunch of C++ classes and templates that use
|
||||
* operator overloading to take care of barriers automatically. In many cases,
|
||||
* all that's necessary to make some field be barriered is to replace
|
||||
* Type *field;
|
||||
* with
|
||||
* HeapPtr<Type> field;
|
||||
* There are also special classes HeapValue and HeapId, which barrier js::Value
|
||||
* and jsid, respectively.
|
||||
*
|
||||
* One additional note: not all object writes need to be barriered. Writes to
|
||||
* newly allocated objects do not need a barrier as long as the GC is not
|
||||
* allowed to run in between the allocation and the write. In these cases, we
|
||||
* use the "obj->field.init(value)" method instead of "obj->field = value".
|
||||
* We use the init naming idiom in many places to signify that a field is being
|
||||
* assigned for the first time, and that no GCs have taken place between the
|
||||
* object allocation and the assignment.
|
||||
*/
|
||||
|
||||
struct JSXML;
|
||||
|
||||
namespace js {
|
||||
|
||||
template<class T, typename Unioned = uintptr_t>
|
||||
class HeapPtr
|
||||
{
|
||||
union {
|
||||
T *value;
|
||||
Unioned other;
|
||||
};
|
||||
|
||||
public:
|
||||
HeapPtr() : value(NULL) {}
|
||||
explicit HeapPtr(T *v) : value(v) { post(); }
|
||||
explicit HeapPtr(const HeapPtr<T> &v) : value(v.value) { post(); }
|
||||
|
||||
~HeapPtr() { pre(); }
|
||||
|
||||
/* Use this to install a ptr into a newly allocated object. */
|
||||
void init(T *v) {
|
||||
JS_ASSERT(!IsPoisonedPtr<T>(v));
|
||||
value = v;
|
||||
post();
|
||||
}
|
||||
|
||||
/* Use to set the pointer to NULL. */
|
||||
void clear() {
|
||||
pre();
|
||||
value = NULL;
|
||||
}
|
||||
|
||||
/* Use this if the automatic coercion to T* isn't working. */
|
||||
T *get() const { return value; }
|
||||
|
||||
/*
|
||||
* Use these if you want to change the value without invoking the barrier.
|
||||
* Obviously this is dangerous unless you know the barrier is not needed.
|
||||
*/
|
||||
T **unsafeGet() { return &value; }
|
||||
void unsafeSet(T *v) { value = v; }
|
||||
|
||||
Unioned *unsafeGetUnioned() { return &other; }
|
||||
|
||||
HeapPtr<T, Unioned> &operator=(T *v) {
|
||||
pre();
|
||||
JS_ASSERT(!IsPoisonedPtr<T>(v));
|
||||
value = v;
|
||||
post();
|
||||
return *this;
|
||||
}
|
||||
|
||||
HeapPtr<T, Unioned> &operator=(const HeapPtr<T> &v) {
|
||||
pre();
|
||||
JS_ASSERT(!IsPoisonedPtr<T>(v.value));
|
||||
value = v.value;
|
||||
post();
|
||||
return *this;
|
||||
}
|
||||
|
||||
T &operator*() const { return *value; }
|
||||
T *operator->() const { return value; }
|
||||
|
||||
operator T*() const { return value; }
|
||||
|
||||
private:
|
||||
void pre() { T::writeBarrierPre(value); }
|
||||
void post() { T::writeBarrierPost(value, (void *)&value); }
|
||||
|
||||
/* Make this friend so it can access pre() and post(). */
|
||||
template<class T1, class T2>
|
||||
friend inline void
|
||||
BarrieredSetPair(JSCompartment *comp,
|
||||
HeapPtr<T1> &v1, T1 *val1,
|
||||
HeapPtr<T2> &v2, T2 *val2);
|
||||
};
|
||||
|
||||
/*
|
||||
* This is a hack for RegExpStatics::updateFromMatch. It allows us to do two
|
||||
* barriers with only one branch to check if we're in an incremental GC.
|
||||
*/
|
||||
template<class T1, class T2>
|
||||
static inline void
|
||||
BarrieredSetPair(JSCompartment *comp,
|
||||
HeapPtr<T1> &v1, T1 *val1,
|
||||
HeapPtr<T2> &v2, T2 *val2)
|
||||
{
|
||||
if (T1::needWriteBarrierPre(comp)) {
|
||||
v1.pre();
|
||||
v2.pre();
|
||||
}
|
||||
v1.unsafeSet(val1);
|
||||
v2.unsafeSet(val2);
|
||||
v1.post();
|
||||
v2.post();
|
||||
}
|
||||
|
||||
struct Shape;
|
||||
class BaseShape;
|
||||
namespace types { struct TypeObject; }
|
||||
|
||||
typedef HeapPtr<JSAtom> HeapPtrAtom;
|
||||
typedef HeapPtr<JSObject> HeapPtrObject;
|
||||
typedef HeapPtr<JSFunction> HeapPtrFunction;
|
||||
typedef HeapPtr<JSString> HeapPtrString;
|
||||
typedef HeapPtr<JSScript> HeapPtrScript;
|
||||
typedef HeapPtr<Shape> HeapPtrShape;
|
||||
typedef HeapPtr<BaseShape> HeapPtrBaseShape;
|
||||
typedef HeapPtr<types::TypeObject> HeapPtrTypeObject;
|
||||
typedef HeapPtr<JSXML> HeapPtrXML;
|
||||
|
||||
/* Useful for hashtables with a HeapPtr as key. */
|
||||
template<class T>
|
||||
struct HeapPtrHasher
|
||||
{
|
||||
typedef HeapPtr<T> Key;
|
||||
typedef T *Lookup;
|
||||
|
||||
static HashNumber hash(Lookup obj) { return DefaultHasher<T *>::hash(obj); }
|
||||
static bool match(const Key &k, Lookup l) { return k.get() == l; }
|
||||
};
|
||||
|
||||
/* Specialized hashing policy for HeapPtrs. */
|
||||
template <class T>
|
||||
struct DefaultHasher< HeapPtr<T> >: HeapPtrHasher<T> { };
|
||||
|
||||
class EncapsulatedValue
|
||||
{
|
||||
protected:
|
||||
Value value;
|
||||
|
||||
/*
|
||||
* Ensure that EncapsulatedValue is not constructable, except by our
|
||||
* implementations.
|
||||
*/
|
||||
EncapsulatedValue() MOZ_DELETE;
|
||||
EncapsulatedValue(const EncapsulatedValue &v) MOZ_DELETE;
|
||||
EncapsulatedValue &operator=(const Value &v) MOZ_DELETE;
|
||||
EncapsulatedValue &operator=(const EncapsulatedValue &v) MOZ_DELETE;
|
||||
|
||||
EncapsulatedValue(const Value &v) : value(v) {}
|
||||
~EncapsulatedValue() {}
|
||||
|
||||
public:
|
||||
const Value &get() const { return value; }
|
||||
Value *unsafeGet() { return &value; }
|
||||
operator const Value &() const { return value; }
|
||||
|
||||
bool isUndefined() const { return value.isUndefined(); }
|
||||
bool isNull() const { return value.isNull(); }
|
||||
bool isBoolean() const { return value.isBoolean(); }
|
||||
bool isTrue() const { return value.isTrue(); }
|
||||
bool isFalse() const { return value.isFalse(); }
|
||||
bool isNumber() const { return value.isNumber(); }
|
||||
bool isInt32() const { return value.isInt32(); }
|
||||
bool isDouble() const { return value.isDouble(); }
|
||||
bool isString() const { return value.isString(); }
|
||||
bool isObject() const { return value.isObject(); }
|
||||
bool isMagic(JSWhyMagic why) const { return value.isMagic(why); }
|
||||
bool isGCThing() const { return value.isGCThing(); }
|
||||
bool isMarkable() const { return value.isMarkable(); }
|
||||
|
||||
bool toBoolean() const { return value.toBoolean(); }
|
||||
double toNumber() const { return value.toNumber(); }
|
||||
int32_t toInt32() const { return value.toInt32(); }
|
||||
double toDouble() const { return value.toDouble(); }
|
||||
JSString *toString() const { return value.toString(); }
|
||||
JSObject &toObject() const { return value.toObject(); }
|
||||
JSObject *toObjectOrNull() const { return value.toObjectOrNull(); }
|
||||
void *toGCThing() const { return value.toGCThing(); }
|
||||
|
||||
JSGCTraceKind gcKind() const { return value.gcKind(); }
|
||||
|
||||
uint64_t asRawBits() const { return value.asRawBits(); }
|
||||
|
||||
#ifdef DEBUG
|
||||
JSWhyMagic whyMagic() const { return value.whyMagic(); }
|
||||
#endif
|
||||
|
||||
static inline void writeBarrierPre(const Value &v);
|
||||
static inline void writeBarrierPre(JSCompartment *comp, const Value &v);
|
||||
|
||||
protected:
|
||||
inline void pre();
|
||||
inline void pre(JSCompartment *comp);
|
||||
};
|
||||
|
||||
class HeapValue : public EncapsulatedValue
|
||||
{
|
||||
public:
|
||||
explicit inline HeapValue();
|
||||
explicit inline HeapValue(const Value &v);
|
||||
explicit inline HeapValue(const HeapValue &v);
|
||||
inline ~HeapValue();
|
||||
|
||||
inline void init(const Value &v);
|
||||
inline void init(JSCompartment *comp, const Value &v);
|
||||
|
||||
inline HeapValue &operator=(const Value &v);
|
||||
inline HeapValue &operator=(const HeapValue &v);
|
||||
|
||||
/*
|
||||
* This is a faster version of operator=. Normally, operator= has to
|
||||
* determine the compartment of the value before it can decide whether to do
|
||||
* the barrier. If you already know the compartment, it's faster to pass it
|
||||
* in.
|
||||
*/
|
||||
inline void set(JSCompartment *comp, const Value &v);
|
||||
|
||||
static inline void writeBarrierPost(const Value &v, void *addr);
|
||||
static inline void writeBarrierPost(JSCompartment *comp, const Value &v, void *addr);
|
||||
|
||||
private:
|
||||
inline void post();
|
||||
inline void post(JSCompartment *comp);
|
||||
};
|
||||
|
||||
class HeapSlot : public EncapsulatedValue
|
||||
{
|
||||
/*
|
||||
* Operator= is not valid for HeapSlot because is must take the object and
|
||||
* slot offset to provide to the post/generational barrier.
|
||||
*/
|
||||
inline HeapSlot &operator=(const Value &v) MOZ_DELETE;
|
||||
inline HeapSlot &operator=(const HeapValue &v) MOZ_DELETE;
|
||||
inline HeapSlot &operator=(const HeapSlot &v) MOZ_DELETE;
|
||||
|
||||
public:
|
||||
explicit inline HeapSlot() MOZ_DELETE;
|
||||
explicit inline HeapSlot(JSObject *obj, uint32_t slot, const Value &v);
|
||||
explicit inline HeapSlot(JSObject *obj, uint32_t slot, const HeapSlot &v);
|
||||
inline ~HeapSlot();
|
||||
|
||||
inline void init(JSObject *owner, uint32_t slot, const Value &v);
|
||||
inline void init(JSCompartment *comp, JSObject *owner, uint32_t slot, const Value &v);
|
||||
|
||||
inline void set(JSObject *owner, uint32_t slot, const Value &v);
|
||||
inline void set(JSCompartment *comp, JSObject *owner, uint32_t slot, const Value &v);
|
||||
|
||||
static inline void writeBarrierPost(JSObject *obj, uint32_t slot);
|
||||
static inline void writeBarrierPost(JSCompartment *comp, JSObject *obj, uint32_t slotno);
|
||||
|
||||
private:
|
||||
inline void post(JSObject *owner, uint32_t slot);
|
||||
inline void post(JSCompartment *comp, JSObject *owner, uint32_t slot);
|
||||
};
|
||||
|
||||
/*
|
||||
* NOTE: This is a placeholder for bug 619558.
|
||||
*
|
||||
* Run a post write barrier that encompasses multiple contiguous slots in a
|
||||
* single step.
|
||||
*/
|
||||
static inline void
|
||||
SlotRangeWriteBarrierPost(JSCompartment *comp, JSObject *obj, uint32_t start, uint32_t count)
|
||||
{
|
||||
}
|
||||
|
||||
static inline const Value *
|
||||
Valueify(const EncapsulatedValue *array)
|
||||
{
|
||||
JS_STATIC_ASSERT(sizeof(HeapValue) == sizeof(Value));
|
||||
JS_STATIC_ASSERT(sizeof(HeapSlot) == sizeof(Value));
|
||||
return (const Value *)array;
|
||||
}
|
||||
|
||||
class HeapSlotArray
|
||||
{
|
||||
HeapSlot *array;
|
||||
|
||||
public:
|
||||
HeapSlotArray(HeapSlot *array) : array(array) {}
|
||||
|
||||
operator const Value *() const { return Valueify(array); }
|
||||
operator HeapSlot *() const { return array; }
|
||||
|
||||
HeapSlotArray operator +(int offset) const { return HeapSlotArray(array + offset); }
|
||||
HeapSlotArray operator +(uint32_t offset) const { return HeapSlotArray(array + offset); }
|
||||
};
|
||||
|
||||
class HeapId
|
||||
{
|
||||
jsid value;
|
||||
|
||||
public:
|
||||
explicit HeapId() : value(JSID_VOID) {}
|
||||
explicit inline HeapId(jsid id);
|
||||
|
||||
inline ~HeapId();
|
||||
|
||||
inline void init(jsid id);
|
||||
|
||||
inline HeapId &operator=(jsid id);
|
||||
inline HeapId &operator=(const HeapId &v);
|
||||
|
||||
bool operator==(jsid id) const { return value == id; }
|
||||
bool operator!=(jsid id) const { return value != id; }
|
||||
|
||||
jsid get() const { return value; }
|
||||
jsid *unsafeGet() { return &value; }
|
||||
operator jsid() const { return value; }
|
||||
|
||||
private:
|
||||
inline void pre();
|
||||
inline void post();
|
||||
|
||||
HeapId(const HeapId &v);
|
||||
};
|
||||
|
||||
/*
|
||||
* Incremental GC requires that weak pointers have read barriers. This is mostly
|
||||
* an issue for empty shapes stored in JSCompartment. The problem happens when,
|
||||
* during an incremental GC, some JS code stores one of the compartment's empty
|
||||
* shapes into an object already marked black. Normally, this would not be a
|
||||
* problem, because the empty shape would have been part of the initial snapshot
|
||||
* when the GC started. However, since this is a weak pointer, it isn't. So we
|
||||
* may collect the empty shape even though a live object points to it. To fix
|
||||
* this, we mark these empty shapes black whenever they get read out.
|
||||
*/
|
||||
template<class T>
|
||||
class ReadBarriered
|
||||
{
|
||||
T *value;
|
||||
|
||||
public:
|
||||
ReadBarriered() : value(NULL) {}
|
||||
ReadBarriered(T *value) : value(value) {}
|
||||
|
||||
T *get() const {
|
||||
if (!value)
|
||||
return NULL;
|
||||
T::readBarrier(value);
|
||||
return value;
|
||||
}
|
||||
|
||||
operator T*() const { return get(); }
|
||||
|
||||
T &operator*() const { return *get(); }
|
||||
T *operator->() const { return get(); }
|
||||
|
||||
T *unsafeGet() { return value; }
|
||||
|
||||
void set(T *v) { value = v; }
|
||||
|
||||
operator bool() { return !!value; }
|
||||
};
|
||||
|
||||
class ReadBarrieredValue
|
||||
{
|
||||
Value value;
|
||||
|
||||
public:
|
||||
ReadBarrieredValue() : value(UndefinedValue()) {}
|
||||
ReadBarrieredValue(const Value &value) : value(value) {}
|
||||
|
||||
inline const Value &get() const;
|
||||
inline operator const Value &() const;
|
||||
|
||||
inline JSObject &toObject() const;
|
||||
};
|
||||
|
||||
namespace tl {
|
||||
|
||||
template <class T> struct IsPostBarrieredType<HeapPtr<T> > {
|
||||
static const bool result = true; };
|
||||
template <> struct IsPostBarrieredType<HeapSlot> { static const bool result = true; };
|
||||
template <> struct IsPostBarrieredType<HeapValue> { static const bool result = true; };
|
||||
template <> struct IsPostBarrieredType<HeapId> { static const bool result = true; };
|
||||
|
||||
} /* namespace tl */
|
||||
} /* namespace js */
|
||||
|
||||
#endif /* jsgc_barrier_h___ */
|
|
@ -0,0 +1,351 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sw=4 et tw=78:
|
||||
*
|
||||
* ***** 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 SpiderMonkey global object code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* the Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2012
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of 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 jsgc_root_h__
|
||||
#define jsgc_root_h__
|
||||
|
||||
#include "jspubtd.h"
|
||||
|
||||
#include "js/Utility.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
namespace JS {
|
||||
|
||||
/*
|
||||
* Moving GC Stack Rooting
|
||||
*
|
||||
* A moving GC may change the physical location of GC allocated things, even
|
||||
* when they are rooted, updating all pointers to the thing to refer to its new
|
||||
* location. The GC must therefore know about all live pointers to a thing,
|
||||
* not just one of them, in order to behave correctly.
|
||||
*
|
||||
* The classes below are used to root stack locations whose value may be held
|
||||
* live across a call that can trigger GC (i.e. a call which might allocate any
|
||||
* GC things). For a code fragment such as:
|
||||
*
|
||||
* Foo();
|
||||
* ... = obj->lastProperty();
|
||||
*
|
||||
* If Foo() can trigger a GC, the stack location of obj must be rooted to
|
||||
* ensure that the GC does not move the JSObject referred to by obj without
|
||||
* updating obj's location itself. This rooting must happen regardless of
|
||||
* whether there are other roots which ensure that the object itself will not
|
||||
* be collected.
|
||||
*
|
||||
* If Foo() cannot trigger a GC, and the same holds for all other calls made
|
||||
* between obj's definitions and its last uses, then no rooting is required.
|
||||
*
|
||||
* Several classes are available for rooting stack locations. All are templated
|
||||
* on the type T of the value being rooted, for which RootMethods<T> must
|
||||
* have an instantiation.
|
||||
*
|
||||
* - Root<T> roots an existing stack allocated variable or other location of
|
||||
* type T. This is typically used either when a variable only needs to be
|
||||
* rooted on certain rare paths, or when a function takes a bare GC thing
|
||||
* pointer as an argument and needs to root it. In the latter case a
|
||||
* Handle<T> is generally preferred, see below.
|
||||
*
|
||||
* - RootedVar<T> declares a variable of type T, whose value is always rooted.
|
||||
*
|
||||
* - Handle<T> is a const reference to a Root<T> or RootedVar<T>. Handles are
|
||||
* coerced automatically from such a Root<T> or RootedVar<T>. Functions which
|
||||
* take GC things or values as arguments and need to root those arguments
|
||||
* should generally replace those arguments with handles and avoid any
|
||||
* explicit rooting. This has two benefits. First, when several such
|
||||
* functions call each other then redundant rooting of multiple copies of the
|
||||
* GC thing can be avoided. Second, if the caller does not pass a rooted
|
||||
* value a compile error will be generated, which is quicker and easier to
|
||||
* fix than when relying on a separate rooting analysis.
|
||||
*/
|
||||
|
||||
template <typename T> class Root;
|
||||
template <typename T> class RootedVar;
|
||||
|
||||
template <typename T>
|
||||
struct RootMethods { };
|
||||
|
||||
/*
|
||||
* Reference to a stack location rooted for GC. See the "Moving GC Stack
|
||||
* Rooting" comment above.
|
||||
*/
|
||||
template <typename T>
|
||||
class Handle
|
||||
{
|
||||
public:
|
||||
/* Copy handles of different types, with implicit coercion. */
|
||||
template <typename S> Handle(Handle<S> handle) {
|
||||
testAssign<S>();
|
||||
ptr = reinterpret_cast<const T *>(handle.address());
|
||||
}
|
||||
|
||||
/* Get a handle from a rooted stack location, with implicit coercion. */
|
||||
template <typename S> inline Handle(const Root<S> &root);
|
||||
template <typename S> inline Handle(const RootedVar<S> &root);
|
||||
|
||||
const T *address() { return ptr; }
|
||||
|
||||
operator T () { return value(); }
|
||||
T operator ->() { return value(); }
|
||||
|
||||
private:
|
||||
const T *ptr;
|
||||
T value() { return *ptr; }
|
||||
|
||||
template <typename S>
|
||||
void testAssign() {
|
||||
#ifdef DEBUG
|
||||
T a = RootMethods<T>::initial();
|
||||
S b = RootMethods<S>::initial();
|
||||
a = b;
|
||||
(void)a;
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
typedef Handle<JSObject*> HandleObject;
|
||||
typedef Handle<JSFunction*> HandleFunction;
|
||||
typedef Handle<JSString*> HandleString;
|
||||
typedef Handle<jsid> HandleId;
|
||||
typedef Handle<Value> HandleValue;
|
||||
|
||||
template <typename T>
|
||||
struct RootMethods<T *>
|
||||
{
|
||||
static T *initial() { return NULL; }
|
||||
static ThingRootKind kind() { return T::rootKind(); }
|
||||
static bool poisoned(T *v) { return IsPoisonedPtr(v); }
|
||||
};
|
||||
|
||||
/*
|
||||
* Root a stack location holding a GC thing. This takes a stack pointer
|
||||
* and ensures that throughout its lifetime the referenced variable
|
||||
* will remain pinned against a moving GC.
|
||||
*
|
||||
* It is important to ensure that the location referenced by a Root is
|
||||
* initialized, as otherwise the GC may try to use the the uninitialized value.
|
||||
* It is generally preferable to use either RootedVar for local variables, or
|
||||
* Handle for arguments.
|
||||
*/
|
||||
template <typename T>
|
||||
class Root
|
||||
{
|
||||
public:
|
||||
Root(JSContext *cx_, const T *ptr
|
||||
JS_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||
{
|
||||
#ifdef JSGC_ROOT_ANALYSIS
|
||||
ContextFriendFields *cx = ContextFriendFields::get(cx_);
|
||||
|
||||
ThingRootKind kind = RootMethods<T>::kind();
|
||||
this->stack = reinterpret_cast<Root<T>**>(&cx->thingGCRooters[kind]);
|
||||
this->prev = *stack;
|
||||
*stack = this;
|
||||
#endif
|
||||
|
||||
JS_ASSERT(!RootMethods<T>::poisoned(*ptr));
|
||||
|
||||
this->ptr = ptr;
|
||||
|
||||
JS_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
}
|
||||
|
||||
~Root()
|
||||
{
|
||||
#ifdef JSGC_ROOT_ANALYSIS
|
||||
JS_ASSERT(*stack == this);
|
||||
*stack = prev;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef JSGC_ROOT_ANALYSIS
|
||||
Root<T> *previous() { return prev; }
|
||||
#endif
|
||||
|
||||
const T *address() const { return ptr; }
|
||||
|
||||
private:
|
||||
|
||||
#ifdef JSGC_ROOT_ANALYSIS
|
||||
Root<T> **stack, *prev;
|
||||
#endif
|
||||
const T *ptr;
|
||||
|
||||
JS_DECL_USE_GUARD_OBJECT_NOTIFIER
|
||||
};
|
||||
|
||||
template<typename T> template <typename S>
|
||||
inline
|
||||
Handle<T>::Handle(const Root<S> &root)
|
||||
{
|
||||
testAssign<S>();
|
||||
ptr = reinterpret_cast<const T *>(root.address());
|
||||
}
|
||||
|
||||
typedef Root<JSObject*> RootObject;
|
||||
typedef Root<JSFunction*> RootFunction;
|
||||
typedef Root<JSString*> RootString;
|
||||
typedef Root<jsid> RootId;
|
||||
typedef Root<Value> RootValue;
|
||||
|
||||
/*
|
||||
* Mark a stack location as a root for the rooting analysis, without actually
|
||||
* rooting it in release builds. This should only be used for stack locations
|
||||
* of GC things that cannot be relocated by a garbage collection, and that
|
||||
* are definitely reachable via another path.
|
||||
*/
|
||||
class SkipRoot
|
||||
{
|
||||
#if defined(DEBUG) && defined(JSGC_ROOT_ANALYSIS)
|
||||
|
||||
SkipRoot **stack, *prev;
|
||||
const uint8_t *start;
|
||||
const uint8_t *end;
|
||||
|
||||
public:
|
||||
template <typename T>
|
||||
SkipRoot(JSContext *cx_, const T *ptr
|
||||
JS_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||
{
|
||||
ContextFriendFields *cx = ContextFriendFields::get(cx_);
|
||||
|
||||
this->stack = &cx->skipGCRooters;
|
||||
this->prev = *stack;
|
||||
*stack = this;
|
||||
this->start = (const uint8_t *) ptr;
|
||||
this->end = this->start + sizeof(T);
|
||||
JS_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
}
|
||||
|
||||
~SkipRoot()
|
||||
{
|
||||
JS_ASSERT(*stack == this);
|
||||
*stack = prev;
|
||||
}
|
||||
|
||||
SkipRoot *previous() { return prev; }
|
||||
|
||||
bool contains(const uint8_t *v, size_t len) {
|
||||
return v >= start && v + len <= end;
|
||||
}
|
||||
|
||||
#else /* DEBUG && JSGC_ROOT_ANALYSIS */
|
||||
|
||||
public:
|
||||
template <typename T>
|
||||
SkipRoot(JSContext *cx, const T *ptr
|
||||
JS_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||
{
|
||||
JS_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
}
|
||||
|
||||
#endif /* DEBUG && JSGC_ROOT_ANALYSIS */
|
||||
|
||||
JS_DECL_USE_GUARD_OBJECT_NOTIFIER
|
||||
};
|
||||
|
||||
/* Make a local variable which stays rooted throughout its lifetime. */
|
||||
template <typename T>
|
||||
class RootedVar
|
||||
{
|
||||
public:
|
||||
RootedVar(JSContext *cx)
|
||||
: ptr(RootMethods<T>::initial()), root(cx, &ptr)
|
||||
{}
|
||||
|
||||
RootedVar(JSContext *cx, T initial)
|
||||
: ptr(initial), root(cx, &ptr)
|
||||
{}
|
||||
|
||||
operator T () const { return ptr; }
|
||||
T operator ->() const { return ptr; }
|
||||
T * address() { return &ptr; }
|
||||
const T * address() const { return &ptr; }
|
||||
T & reference() { return ptr; }
|
||||
T raw() { return ptr; }
|
||||
|
||||
/*
|
||||
* This method is only necessary due to an obscure C++98 requirement (that
|
||||
* there be an accessible, usable copy constructor when passing a temporary
|
||||
* to an implicitly-called constructor for use with a const-ref parameter).
|
||||
* (Head spinning yet?) We can remove this when we build the JS engine
|
||||
* with -std=c++11.
|
||||
*/
|
||||
operator Handle<T> () const { return Handle<T>(*this); }
|
||||
|
||||
T & operator =(T value)
|
||||
{
|
||||
JS_ASSERT(!RootMethods<T>::poisoned(value));
|
||||
ptr = value;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
T & operator =(const RootedVar &value)
|
||||
{
|
||||
ptr = value;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
private:
|
||||
T ptr;
|
||||
Root<T> root;
|
||||
|
||||
RootedVar() MOZ_DELETE;
|
||||
RootedVar(const RootedVar &) MOZ_DELETE;
|
||||
};
|
||||
|
||||
template <typename T> template <typename S>
|
||||
inline
|
||||
Handle<T>::Handle(const RootedVar<S> &root)
|
||||
{
|
||||
testAssign<S>();
|
||||
ptr = reinterpret_cast<const T *>(root.address());
|
||||
}
|
||||
|
||||
typedef RootedVar<JSObject*> RootedVarObject;
|
||||
typedef RootedVar<JSFunction*> RootedVarFunction;
|
||||
typedef RootedVar<JSString*> RootedVarString;
|
||||
typedef RootedVar<jsid> RootedVarId;
|
||||
typedef RootedVar<Value> RootedVarValue;
|
||||
|
||||
} /* namespace JS */
|
||||
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* jsgc_root_h___ */
|
|
@ -0,0 +1,192 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sw=4 et tw=78:
|
||||
*
|
||||
* ***** 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 SpiderMonkey JavaScript engine.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* the Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of 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 jsgc_statistics_h___
|
||||
#define jsgc_statistics_h___
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "jsfriendapi.h"
|
||||
#include "jspubtd.h"
|
||||
#include "jsutil.h"
|
||||
|
||||
struct JSCompartment;
|
||||
|
||||
namespace js {
|
||||
namespace gcstats {
|
||||
|
||||
enum Phase {
|
||||
PHASE_GC_BEGIN,
|
||||
PHASE_WAIT_BACKGROUND_THREAD,
|
||||
PHASE_PURGE,
|
||||
PHASE_MARK,
|
||||
PHASE_MARK_ROOTS,
|
||||
PHASE_MARK_DELAYED,
|
||||
PHASE_MARK_OTHER,
|
||||
PHASE_FINALIZE_START,
|
||||
PHASE_SWEEP,
|
||||
PHASE_SWEEP_COMPARTMENTS,
|
||||
PHASE_SWEEP_OBJECT,
|
||||
PHASE_SWEEP_STRING,
|
||||
PHASE_SWEEP_SCRIPT,
|
||||
PHASE_SWEEP_SHAPE,
|
||||
PHASE_DISCARD_CODE,
|
||||
PHASE_DISCARD_ANALYSIS,
|
||||
PHASE_DISCARD_TI,
|
||||
PHASE_SWEEP_TYPES,
|
||||
PHASE_CLEAR_SCRIPT_ANALYSIS,
|
||||
PHASE_FINALIZE_END,
|
||||
PHASE_DESTROY,
|
||||
PHASE_GC_END,
|
||||
|
||||
PHASE_LIMIT
|
||||
};
|
||||
|
||||
enum Stat {
|
||||
STAT_NEW_CHUNK,
|
||||
STAT_DESTROY_CHUNK,
|
||||
|
||||
STAT_LIMIT
|
||||
};
|
||||
|
||||
class StatisticsSerializer;
|
||||
|
||||
struct Statistics {
|
||||
Statistics(JSRuntime *rt);
|
||||
~Statistics();
|
||||
|
||||
void beginPhase(Phase phase);
|
||||
void endPhase(Phase phase);
|
||||
|
||||
void beginSlice(int collectedCount, int compartmentCount, gcreason::Reason reason);
|
||||
void endSlice();
|
||||
|
||||
void reset(const char *reason) { slices.back().resetReason = reason; }
|
||||
void nonincremental(const char *reason) { nonincrementalReason = reason; }
|
||||
|
||||
void count(Stat s) {
|
||||
JS_ASSERT(s < STAT_LIMIT);
|
||||
counts[s]++;
|
||||
}
|
||||
|
||||
jschar *formatMessage();
|
||||
jschar *formatJSON(uint64_t timestamp);
|
||||
|
||||
private:
|
||||
JSRuntime *runtime;
|
||||
|
||||
int64_t startupTime;
|
||||
|
||||
FILE *fp;
|
||||
bool fullFormat;
|
||||
|
||||
int collectedCount;
|
||||
int compartmentCount;
|
||||
const char *nonincrementalReason;
|
||||
|
||||
struct SliceData {
|
||||
SliceData(gcreason::Reason reason, int64_t start)
|
||||
: reason(reason), resetReason(NULL), start(start)
|
||||
{
|
||||
PodArrayZero(phaseTimes);
|
||||
}
|
||||
|
||||
gcreason::Reason reason;
|
||||
const char *resetReason;
|
||||
int64_t start, end;
|
||||
int64_t phaseTimes[PHASE_LIMIT];
|
||||
|
||||
int64_t duration() const { return end - start; }
|
||||
};
|
||||
|
||||
Vector<SliceData, 8, SystemAllocPolicy> slices;
|
||||
|
||||
/* Most recent time when the given phase started. */
|
||||
int64_t phaseStarts[PHASE_LIMIT];
|
||||
|
||||
/* Total time in a given phase for this GC. */
|
||||
int64_t phaseTimes[PHASE_LIMIT];
|
||||
|
||||
/* Total time in a given phase over all GCs. */
|
||||
int64_t phaseTotals[PHASE_LIMIT];
|
||||
|
||||
/* Number of events of this type for this GC. */
|
||||
unsigned int counts[STAT_LIMIT];
|
||||
|
||||
/* Allocated space before the GC started. */
|
||||
size_t preBytes;
|
||||
|
||||
void beginGC();
|
||||
void endGC();
|
||||
|
||||
int64_t gcDuration();
|
||||
void printStats();
|
||||
bool formatData(StatisticsSerializer &ss, uint64_t timestamp);
|
||||
|
||||
double computeMMU(int64_t resolution);
|
||||
};
|
||||
|
||||
struct AutoGCSlice {
|
||||
AutoGCSlice(Statistics &stats, int collectedCount, int compartmentCount, gcreason::Reason reason
|
||||
JS_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||
: stats(stats)
|
||||
{
|
||||
JS_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
stats.beginSlice(collectedCount, compartmentCount, reason);
|
||||
}
|
||||
~AutoGCSlice() { stats.endSlice(); }
|
||||
|
||||
Statistics &stats;
|
||||
JS_DECL_USE_GUARD_OBJECT_NOTIFIER
|
||||
};
|
||||
|
||||
struct AutoPhase {
|
||||
AutoPhase(Statistics &stats, Phase phase JS_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||
: stats(stats), phase(phase) { JS_GUARD_OBJECT_NOTIFIER_INIT; stats.beginPhase(phase); }
|
||||
~AutoPhase() { stats.endPhase(phase); }
|
||||
|
||||
Statistics &stats;
|
||||
Phase phase;
|
||||
JS_DECL_USE_GUARD_OBJECT_NOTIFIER
|
||||
};
|
||||
|
||||
} /* namespace gcstats */
|
||||
} /* namespace js */
|
||||
|
||||
#endif /* jsgc_statistics_h___ */
|
|
@ -58,11 +58,11 @@
|
|||
|
||||
/* Define to 1 if the <endian.h> header is present and
|
||||
useable. See jscpucfg.h. */
|
||||
#define JS_HAVE_ENDIAN_H 1
|
||||
/* #undef JS_HAVE_ENDIAN_H */
|
||||
|
||||
/* Define to 1 if the <machine/endian.h> header is present and
|
||||
useable. See jscpucfg.h. */
|
||||
#define JS_HAVE_MACHINE_ENDIAN_H 1
|
||||
/* #undef JS_HAVE_MACHINE_ENDIAN_H */
|
||||
|
||||
/* Define to 1 if the <sys/isa_defs.h> header is present and
|
||||
useable. See jscpucfg.h. */
|
||||
|
@ -73,11 +73,11 @@
|
|||
|
||||
/* Define to 1 if the N-byte __intN types are defined by the
|
||||
compiler. */
|
||||
/* #undef JS_HAVE___INTN */
|
||||
#define JS_HAVE___INTN 1
|
||||
|
||||
/* Define to 1 if #including <stddef.h> provides definitions for
|
||||
intptr_t and uintptr_t. */
|
||||
/* #undef JS_STDDEF_H_HAS_INTPTR_T */
|
||||
#define JS_STDDEF_H_HAS_INTPTR_T 1
|
||||
|
||||
/* Define to 1 if #including <crtdefs.h> provides definitions for
|
||||
intptr_t and uintptr_t. */
|
||||
|
@ -90,7 +90,7 @@
|
|||
/* #undef JS_INT32_TYPE */
|
||||
/* #undef JS_INT64_TYPE */
|
||||
/* #undef JS_INTPTR_TYPE */
|
||||
//#define JS_BYTES_PER_WORD 4
|
||||
/* #undef JS_BYTES_PER_WORD */
|
||||
|
||||
/* Some mozilla code uses JS-friend APIs that depend on JS_METHODJIT being
|
||||
correct. */
|
||||
|
|
|
@ -0,0 +1,381 @@
|
|||
/* -*- Mode: C; tab-width: 8; 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 Mozilla Communicator client code, released
|
||||
* March 31, 1998.
|
||||
*
|
||||
* 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 of 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 ***** */
|
||||
|
||||
/*
|
||||
* This is the JavaScript error message file.
|
||||
*
|
||||
* The format for each JS error message is:
|
||||
*
|
||||
* MSG_DEF(<SYMBOLIC_NAME>, <ERROR_NUMBER>, <ARGUMENT_COUNT>, <EXCEPTION_NAME>,
|
||||
* <FORMAT_STRING>)
|
||||
*
|
||||
* where ;
|
||||
* <SYMBOLIC_NAME> is a legal C identifer that will be used in the
|
||||
* JS engine source.
|
||||
*
|
||||
* <ERROR_NUMBER> is an unique integral value identifying this error.
|
||||
*
|
||||
* <ARGUMENT_COUNT> is an integer literal specifying the total number of
|
||||
* replaceable arguments in the following format string.
|
||||
*
|
||||
* <EXCEPTION_NAME> is an exception index from the enum in jsexn.c;
|
||||
* JSEXN_NONE for none. The given exception index will be raised by the
|
||||
* engine when the corresponding error occurs.
|
||||
*
|
||||
* <FORMAT_STRING> is a string literal, optionally containing sequences
|
||||
* {X} where X is an integer representing the argument number that will
|
||||
* be replaced with a string value when the error is reported.
|
||||
*
|
||||
* e.g.
|
||||
*
|
||||
* MSG_DEF(JSMSG_NOT_A_SUBSPECIES, 73, JSEXN_NONE, 2,
|
||||
* "{0} is not a member of the {1} family")
|
||||
*
|
||||
* can be used:
|
||||
*
|
||||
* JS_ReportErrorNumber(JSMSG_NOT_A_SUBSPECIES, "Rhino", "Monkey");
|
||||
*
|
||||
* to report:
|
||||
*
|
||||
* "Rhino is not a member of the Monkey family"
|
||||
*
|
||||
* When removing MSG_DEFs, convert them to JSMSG_UNUSED<n> placeholders:
|
||||
*
|
||||
* MSG_DEF(JSMSG_UNUSED7, 7, 0, JSEXN_NONE, "")
|
||||
*
|
||||
* Before adding a new MSG_DEF at the end, look for existing JSMSG_UNUSED<n>
|
||||
* free index placeholders in the middle of the list.
|
||||
*/
|
||||
|
||||
MSG_DEF(JSMSG_NOT_AN_ERROR, 0, 0, JSEXN_NONE, "<Error #0 is reserved>")
|
||||
MSG_DEF(JSMSG_NOT_DEFINED, 1, 1, JSEXN_REFERENCEERR, "{0} is not defined")
|
||||
MSG_DEF(JSMSG_INACTIVE, 2, 0, JSEXN_INTERNALERR, "nothing active on context")
|
||||
MSG_DEF(JSMSG_MORE_ARGS_NEEDED, 3, 3, JSEXN_TYPEERR, "{0} requires more than {1} argument{2}")
|
||||
MSG_DEF(JSMSG_BAD_CHAR, 4, 1, JSEXN_INTERNALERR, "invalid format character {0}")
|
||||
MSG_DEF(JSMSG_BAD_TYPE, 5, 1, JSEXN_TYPEERR, "unknown type {0}")
|
||||
MSG_DEF(JSMSG_ALLOC_OVERFLOW, 6, 0, JSEXN_INTERNALERR, "allocation size overflow")
|
||||
MSG_DEF(JSMSG_MISSING_HEXDIGITS, 7, 0, JSEXN_SYNTAXERR, "missing hexadecimal digits after '0x'")
|
||||
MSG_DEF(JSMSG_INCOMPATIBLE_PROTO, 8, 3, JSEXN_TYPEERR, "{0}.prototype.{1} called on incompatible {2}")
|
||||
MSG_DEF(JSMSG_NO_CONSTRUCTOR, 9, 1, JSEXN_TYPEERR, "{0} has no constructor")
|
||||
MSG_DEF(JSMSG_CANT_ALIAS, 10, 3, JSEXN_TYPEERR, "can't alias {0} to {1} in class {2}")
|
||||
MSG_DEF(JSMSG_NOT_SCRIPTED_FUNCTION, 11, 1, JSEXN_TYPEERR, "{0} is not a scripted function")
|
||||
MSG_DEF(JSMSG_BAD_SORT_ARG, 12, 0, JSEXN_TYPEERR, "invalid Array.prototype.sort argument")
|
||||
MSG_DEF(JSMSG_BAD_ATOMIC_NUMBER, 13, 1, JSEXN_INTERNALERR, "internal error: no index for atom {0}")
|
||||
MSG_DEF(JSMSG_TOO_MANY_LITERALS, 14, 0, JSEXN_INTERNALERR, "too many literals")
|
||||
MSG_DEF(JSMSG_CANT_WATCH, 15, 1, JSEXN_TYPEERR, "can't watch non-native objects of class {0}")
|
||||
MSG_DEF(JSMSG_STACK_UNDERFLOW, 16, 2, JSEXN_INTERNALERR, "internal error compiling {0}: stack underflow at pc {1}")
|
||||
MSG_DEF(JSMSG_NEED_DIET, 17, 1, JSEXN_INTERNALERR, "{0} too large")
|
||||
MSG_DEF(JSMSG_TOO_MANY_LOCAL_ROOTS, 18, 0, JSEXN_ERR, "out of local root space")
|
||||
MSG_DEF(JSMSG_READ_ONLY, 19, 1, JSEXN_TYPEERR, "{0} is read-only")
|
||||
MSG_DEF(JSMSG_BAD_FORMAL, 20, 0, JSEXN_SYNTAXERR, "malformed formal parameter")
|
||||
MSG_DEF(JSMSG_CANT_DELETE, 21, 1, JSEXN_TYPEERR, "property {0} is non-configurable and can't be deleted")
|
||||
MSG_DEF(JSMSG_NOT_FUNCTION, 22, 1, JSEXN_TYPEERR, "{0} is not a function")
|
||||
MSG_DEF(JSMSG_NOT_CONSTRUCTOR, 23, 1, JSEXN_TYPEERR, "{0} is not a constructor")
|
||||
MSG_DEF(JSMSG_INVALID_DATE, 24, 0, JSEXN_RANGEERR, "invalid date")
|
||||
MSG_DEF(JSMSG_TOO_DEEP, 25, 1, JSEXN_INTERNALERR, "{0} nested too deeply")
|
||||
MSG_DEF(JSMSG_OVER_RECURSED, 26, 0, JSEXN_INTERNALERR, "too much recursion")
|
||||
MSG_DEF(JSMSG_IN_NOT_OBJECT, 27, 1, JSEXN_TYPEERR, "invalid 'in' operand {0}")
|
||||
MSG_DEF(JSMSG_BAD_NEW_RESULT, 28, 1, JSEXN_TYPEERR, "invalid new expression result {0}")
|
||||
MSG_DEF(JSMSG_BAD_SHARP_DEF, 29, 1, JSEXN_ERR, "invalid sharp variable definition #{0}=")
|
||||
MSG_DEF(JSMSG_BAD_SHARP_USE, 30, 1, JSEXN_ERR, "invalid sharp variable use #{0}#")
|
||||
MSG_DEF(JSMSG_BAD_INSTANCEOF_RHS, 31, 1, JSEXN_TYPEERR, "invalid 'instanceof' operand {0}")
|
||||
MSG_DEF(JSMSG_BAD_BYTECODE, 32, 1, JSEXN_INTERNALERR, "unimplemented JavaScript bytecode {0}")
|
||||
MSG_DEF(JSMSG_BAD_RADIX, 33, 0, JSEXN_RANGEERR, "radix must be an integer at least 2 and no greater than 36")
|
||||
MSG_DEF(JSMSG_PAREN_BEFORE_LET, 34, 0, JSEXN_SYNTAXERR, "missing ( before let head")
|
||||
MSG_DEF(JSMSG_CANT_CONVERT, 35, 1, JSEXN_ERR, "can't convert {0} to an integer")
|
||||
MSG_DEF(JSMSG_CYCLIC_VALUE, 36, 1, JSEXN_TYPEERR, "cyclic {0} value")
|
||||
MSG_DEF(JSMSG_COMPILE_EXECED_SCRIPT, 37, 0, JSEXN_TYPEERR, "can't compile over a script that is currently executing")
|
||||
MSG_DEF(JSMSG_CANT_CONVERT_TO, 38, 2, JSEXN_TYPEERR, "can't convert {0} to {1}")
|
||||
MSG_DEF(JSMSG_NO_PROPERTIES, 39, 1, JSEXN_TYPEERR, "{0} has no properties")
|
||||
MSG_DEF(JSMSG_CANT_FIND_CLASS, 40, 1, JSEXN_TYPEERR, "can't find class id {0}")
|
||||
MSG_DEF(JSMSG_DEAD_OBJECT, 41, 0, JSEXN_TYPEERR, "can't access dead object")
|
||||
MSG_DEF(JSMSG_BYTECODE_TOO_BIG, 42, 2, JSEXN_INTERNALERR, "bytecode {0} too large (limit {1})")
|
||||
MSG_DEF(JSMSG_UNKNOWN_FORMAT, 43, 1, JSEXN_INTERNALERR, "unknown bytecode format {0}")
|
||||
MSG_DEF(JSMSG_TOO_MANY_CON_ARGS, 44, 0, JSEXN_SYNTAXERR, "too many constructor arguments")
|
||||
MSG_DEF(JSMSG_TOO_MANY_FUN_ARGS, 45, 0, JSEXN_SYNTAXERR, "too many function arguments")
|
||||
MSG_DEF(JSMSG_BAD_QUANTIFIER, 46, 0, JSEXN_SYNTAXERR, "invalid quantifier")
|
||||
MSG_DEF(JSMSG_MIN_TOO_BIG, 47, 1, JSEXN_SYNTAXERR, "overlarge minimum {0}")
|
||||
MSG_DEF(JSMSG_MAX_TOO_BIG, 48, 1, JSEXN_SYNTAXERR, "overlarge maximum {0}")
|
||||
MSG_DEF(JSMSG_OUT_OF_ORDER, 49, 1, JSEXN_SYNTAXERR, "maximum {0} less than minimum")
|
||||
MSG_DEF(JSMSG_BAD_DESTRUCT_DECL, 50, 0, JSEXN_SYNTAXERR, "missing = in destructuring declaration")
|
||||
MSG_DEF(JSMSG_BAD_DESTRUCT_ASS, 51, 0, JSEXN_REFERENCEERR, "invalid destructuring assignment operator")
|
||||
MSG_DEF(JSMSG_PAREN_AFTER_LET, 52, 0, JSEXN_SYNTAXERR, "missing ) after let head")
|
||||
MSG_DEF(JSMSG_CURLY_AFTER_LET, 53, 0, JSEXN_SYNTAXERR, "missing } after let block")
|
||||
MSG_DEF(JSMSG_MISSING_PAREN, 54, 0, JSEXN_SYNTAXERR, "unterminated parenthetical")
|
||||
MSG_DEF(JSMSG_UNTERM_CLASS, 55, 1, JSEXN_SYNTAXERR, "unterminated character class {0}")
|
||||
MSG_DEF(JSMSG_TRAILING_SLASH, 56, 0, JSEXN_SYNTAXERR, "trailing \\ in regular expression")
|
||||
MSG_DEF(JSMSG_BAD_CLASS_RANGE, 57, 0, JSEXN_SYNTAXERR, "invalid range in character class")
|
||||
MSG_DEF(JSMSG_BAD_REGEXP_FLAG, 58, 1, JSEXN_SYNTAXERR, "invalid regular expression flag {0}")
|
||||
MSG_DEF(JSMSG_NO_INPUT, 59, 5, JSEXN_SYNTAXERR, "no input for /{0}/{1}{2}{3}{4}")
|
||||
MSG_DEF(JSMSG_CANT_OPEN, 60, 2, JSEXN_ERR, "can't open {0}: {1}")
|
||||
MSG_DEF(JSMSG_TOO_MANY_FUN_APPLY_ARGS, 61, 0, JSEXN_RANGEERR, "arguments array passed to Function.prototype.apply is too large")
|
||||
MSG_DEF(JSMSG_UNMATCHED_RIGHT_PAREN, 62, 0, JSEXN_SYNTAXERR, "unmatched ) in regular expression")
|
||||
MSG_DEF(JSMSG_TOO_BIG_TO_ENCODE, 63, 0, JSEXN_INTERNALERR, "data are to big to encode")
|
||||
MSG_DEF(JSMSG_UNUSED64, 64, 0, JSEXN_NONE, "")
|
||||
MSG_DEF(JSMSG_UNUSED65, 65, 0, JSEXN_NONE, "")
|
||||
MSG_DEF(JSMSG_UNUSED66, 66, 0, JSEXN_NONE, "")
|
||||
MSG_DEF(JSMSG_UNUSED67, 67, 0, JSEXN_NONE, "")
|
||||
MSG_DEF(JSMSG_BAD_SCRIPT_MAGIC, 68, 0, JSEXN_INTERNALERR, "bad script XDR magic number")
|
||||
MSG_DEF(JSMSG_PAREN_BEFORE_FORMAL, 69, 0, JSEXN_SYNTAXERR, "missing ( before formal parameters")
|
||||
MSG_DEF(JSMSG_MISSING_FORMAL, 70, 0, JSEXN_SYNTAXERR, "missing formal parameter")
|
||||
MSG_DEF(JSMSG_PAREN_AFTER_FORMAL, 71, 0, JSEXN_SYNTAXERR, "missing ) after formal parameters")
|
||||
MSG_DEF(JSMSG_CURLY_BEFORE_BODY, 72, 0, JSEXN_SYNTAXERR, "missing { before function body")
|
||||
MSG_DEF(JSMSG_CURLY_AFTER_BODY, 73, 0, JSEXN_SYNTAXERR, "missing } after function body")
|
||||
MSG_DEF(JSMSG_PAREN_BEFORE_COND, 74, 0, JSEXN_SYNTAXERR, "missing ( before condition")
|
||||
MSG_DEF(JSMSG_PAREN_AFTER_COND, 75, 0, JSEXN_SYNTAXERR, "missing ) after condition")
|
||||
MSG_DEF(JSMSG_DESTRUCT_DUP_ARG, 76, 0, JSEXN_SYNTAXERR, "duplicate argument is mixed with destructuring pattern")
|
||||
MSG_DEF(JSMSG_NAME_AFTER_DOT, 77, 0, JSEXN_SYNTAXERR, "missing name after . operator")
|
||||
MSG_DEF(JSMSG_BRACKET_IN_INDEX, 78, 0, JSEXN_SYNTAXERR, "missing ] in index expression")
|
||||
MSG_DEF(JSMSG_XML_WHOLE_PROGRAM, 79, 0, JSEXN_SYNTAXERR, "XML can't be the whole program")
|
||||
MSG_DEF(JSMSG_PAREN_BEFORE_SWITCH, 80, 0, JSEXN_SYNTAXERR, "missing ( before switch expression")
|
||||
MSG_DEF(JSMSG_PAREN_AFTER_SWITCH, 81, 0, JSEXN_SYNTAXERR, "missing ) after switch expression")
|
||||
MSG_DEF(JSMSG_CURLY_BEFORE_SWITCH, 82, 0, JSEXN_SYNTAXERR, "missing { before switch body")
|
||||
MSG_DEF(JSMSG_COLON_AFTER_CASE, 83, 0, JSEXN_SYNTAXERR, "missing : after case label")
|
||||
MSG_DEF(JSMSG_WHILE_AFTER_DO, 84, 0, JSEXN_SYNTAXERR, "missing while after do-loop body")
|
||||
MSG_DEF(JSMSG_PAREN_AFTER_FOR, 85, 0, JSEXN_SYNTAXERR, "missing ( after for")
|
||||
MSG_DEF(JSMSG_SEMI_AFTER_FOR_INIT, 86, 0, JSEXN_SYNTAXERR, "missing ; after for-loop initializer")
|
||||
MSG_DEF(JSMSG_SEMI_AFTER_FOR_COND, 87, 0, JSEXN_SYNTAXERR, "missing ; after for-loop condition")
|
||||
MSG_DEF(JSMSG_PAREN_AFTER_FOR_CTRL, 88, 0, JSEXN_SYNTAXERR, "missing ) after for-loop control")
|
||||
MSG_DEF(JSMSG_CURLY_BEFORE_TRY, 89, 0, JSEXN_SYNTAXERR, "missing { before try block")
|
||||
MSG_DEF(JSMSG_CURLY_AFTER_TRY, 90, 0, JSEXN_SYNTAXERR, "missing } after try block")
|
||||
MSG_DEF(JSMSG_PAREN_BEFORE_CATCH, 91, 0, JSEXN_SYNTAXERR, "missing ( before catch")
|
||||
MSG_DEF(JSMSG_CATCH_IDENTIFIER, 92, 0, JSEXN_SYNTAXERR, "missing identifier in catch")
|
||||
MSG_DEF(JSMSG_PAREN_AFTER_CATCH, 93, 0, JSEXN_SYNTAXERR, "missing ) after catch")
|
||||
MSG_DEF(JSMSG_CURLY_BEFORE_CATCH, 94, 0, JSEXN_SYNTAXERR, "missing { before catch block")
|
||||
MSG_DEF(JSMSG_CURLY_AFTER_CATCH, 95, 0, JSEXN_SYNTAXERR, "missing } after catch block")
|
||||
MSG_DEF(JSMSG_CURLY_BEFORE_FINALLY, 96, 0, JSEXN_SYNTAXERR, "missing { before finally block")
|
||||
MSG_DEF(JSMSG_CURLY_AFTER_FINALLY, 97, 0, JSEXN_SYNTAXERR, "missing } after finally block")
|
||||
MSG_DEF(JSMSG_CATCH_OR_FINALLY, 98, 0, JSEXN_SYNTAXERR, "missing catch or finally after try")
|
||||
MSG_DEF(JSMSG_PAREN_BEFORE_WITH, 99, 0, JSEXN_SYNTAXERR, "missing ( before with-statement object")
|
||||
MSG_DEF(JSMSG_PAREN_AFTER_WITH, 100, 0, JSEXN_SYNTAXERR, "missing ) after with-statement object")
|
||||
MSG_DEF(JSMSG_CURLY_IN_COMPOUND, 101, 0, JSEXN_SYNTAXERR, "missing } in compound statement")
|
||||
MSG_DEF(JSMSG_NO_VARIABLE_NAME, 102, 0, JSEXN_SYNTAXERR, "missing variable name")
|
||||
MSG_DEF(JSMSG_COLON_IN_COND, 103, 0, JSEXN_SYNTAXERR, "missing : in conditional expression")
|
||||
MSG_DEF(JSMSG_PAREN_AFTER_ARGS, 104, 0, JSEXN_SYNTAXERR, "missing ) after argument list")
|
||||
MSG_DEF(JSMSG_BRACKET_AFTER_LIST, 105, 0, JSEXN_SYNTAXERR, "missing ] after element list")
|
||||
MSG_DEF(JSMSG_COLON_AFTER_ID, 106, 0, JSEXN_SYNTAXERR, "missing : after property id")
|
||||
MSG_DEF(JSMSG_CURLY_AFTER_LIST, 107, 0, JSEXN_SYNTAXERR, "missing } after property list")
|
||||
MSG_DEF(JSMSG_PAREN_IN_PAREN, 108, 0, JSEXN_SYNTAXERR, "missing ) in parenthetical")
|
||||
MSG_DEF(JSMSG_SEMI_BEFORE_STMNT, 109, 0, JSEXN_SYNTAXERR, "missing ; before statement")
|
||||
MSG_DEF(JSMSG_NO_RETURN_VALUE, 110, 1, JSEXN_TYPEERR, "function {0} does not always return a value")
|
||||
MSG_DEF(JSMSG_DUPLICATE_FORMAL, 111, 1, JSEXN_SYNTAXERR, "duplicate formal argument {0}")
|
||||
MSG_DEF(JSMSG_EQUAL_AS_ASSIGN, 112, 0, JSEXN_SYNTAXERR, "test for equality (==) mistyped as assignment (=)?")
|
||||
MSG_DEF(JSMSG_OPTIMIZED_CLOSURE_LEAK, 113, 0, JSEXN_INTERNALERR, "can't access optimized closure")
|
||||
MSG_DEF(JSMSG_TOO_MANY_DEFAULTS, 114, 0, JSEXN_SYNTAXERR, "more than one switch default")
|
||||
MSG_DEF(JSMSG_TOO_MANY_CASES, 115, 0, JSEXN_INTERNALERR, "too many switch cases")
|
||||
MSG_DEF(JSMSG_BAD_SWITCH, 116, 0, JSEXN_SYNTAXERR, "invalid switch statement")
|
||||
MSG_DEF(JSMSG_BAD_FOR_LEFTSIDE, 117, 0, JSEXN_SYNTAXERR, "invalid for/in left-hand side")
|
||||
MSG_DEF(JSMSG_CATCH_AFTER_GENERAL, 118, 0, JSEXN_SYNTAXERR, "catch after unconditional catch")
|
||||
MSG_DEF(JSMSG_CATCH_WITHOUT_TRY, 119, 0, JSEXN_SYNTAXERR, "catch without try")
|
||||
MSG_DEF(JSMSG_FINALLY_WITHOUT_TRY, 120, 0, JSEXN_SYNTAXERR, "finally without try")
|
||||
MSG_DEF(JSMSG_LABEL_NOT_FOUND, 121, 0, JSEXN_SYNTAXERR, "label not found")
|
||||
MSG_DEF(JSMSG_TOUGH_BREAK, 122, 0, JSEXN_SYNTAXERR, "unlabeled break must be inside loop or switch")
|
||||
MSG_DEF(JSMSG_BAD_CONTINUE, 123, 0, JSEXN_SYNTAXERR, "continue must be inside loop")
|
||||
MSG_DEF(JSMSG_BAD_RETURN_OR_YIELD, 124, 1, JSEXN_SYNTAXERR, "{0} not in function")
|
||||
MSG_DEF(JSMSG_BAD_LABEL, 125, 0, JSEXN_SYNTAXERR, "invalid label")
|
||||
MSG_DEF(JSMSG_DUPLICATE_LABEL, 126, 0, JSEXN_SYNTAXERR, "duplicate label")
|
||||
MSG_DEF(JSMSG_VAR_HIDES_ARG, 127, 1, JSEXN_TYPEERR, "variable {0} redeclares argument")
|
||||
MSG_DEF(JSMSG_BAD_VAR_INIT, 128, 0, JSEXN_SYNTAXERR, "invalid variable initialization")
|
||||
MSG_DEF(JSMSG_BAD_LEFTSIDE_OF_ASS, 129, 0, JSEXN_REFERENCEERR, "invalid assignment left-hand side")
|
||||
MSG_DEF(JSMSG_BAD_OPERAND, 130, 1, JSEXN_SYNTAXERR, "invalid {0} operand")
|
||||
MSG_DEF(JSMSG_BAD_PROP_ID, 131, 0, JSEXN_SYNTAXERR, "invalid property id")
|
||||
MSG_DEF(JSMSG_RESERVED_ID, 132, 1, JSEXN_SYNTAXERR, "{0} is a reserved identifier")
|
||||
MSG_DEF(JSMSG_SYNTAX_ERROR, 133, 0, JSEXN_SYNTAXERR, "syntax error")
|
||||
MSG_DEF(JSMSG_BAD_SHARP_VAR_DEF, 134, 0, JSEXN_SYNTAXERR, "invalid sharp variable definition")
|
||||
MSG_DEF(JSMSG_BAD_PROTOTYPE, 135, 1, JSEXN_TYPEERR, "'prototype' property of {0} is not an object")
|
||||
MSG_DEF(JSMSG_MISSING_EXPONENT, 136, 0, JSEXN_SYNTAXERR, "missing exponent")
|
||||
MSG_DEF(JSMSG_OUT_OF_MEMORY, 137, 0, JSEXN_ERR, "out of memory")
|
||||
MSG_DEF(JSMSG_UNTERMINATED_STRING, 138, 0, JSEXN_SYNTAXERR, "unterminated string literal")
|
||||
MSG_DEF(JSMSG_TOO_MANY_PARENS, 139, 0, JSEXN_INTERNALERR, "too many parentheses in regular expression")
|
||||
MSG_DEF(JSMSG_UNTERMINATED_COMMENT, 140, 0, JSEXN_SYNTAXERR, "unterminated comment")
|
||||
MSG_DEF(JSMSG_UNTERMINATED_REGEXP, 141, 0, JSEXN_SYNTAXERR, "unterminated regular expression literal")
|
||||
MSG_DEF(JSMSG_BAD_CLONE_FUNOBJ_SCOPE, 142, 0, JSEXN_TYPEERR, "bad cloned function scope chain")
|
||||
MSG_DEF(JSMSG_SHARPVAR_TOO_BIG, 143, 0, JSEXN_SYNTAXERR, "overlarge sharp variable number")
|
||||
MSG_DEF(JSMSG_ILLEGAL_CHARACTER, 144, 0, JSEXN_SYNTAXERR, "illegal character")
|
||||
MSG_DEF(JSMSG_BAD_OCTAL, 145, 1, JSEXN_SYNTAXERR, "{0} is not a legal ECMA-262 octal constant")
|
||||
MSG_DEF(JSMSG_BAD_INDIRECT_CALL, 146, 1, JSEXN_EVALERR, "function {0} must be called directly, and not by way of a function of another name")
|
||||
MSG_DEF(JSMSG_UNCAUGHT_EXCEPTION, 147, 1, JSEXN_INTERNALERR, "uncaught exception: {0}")
|
||||
MSG_DEF(JSMSG_INVALID_BACKREF, 148, 0, JSEXN_SYNTAXERR, "non-octal digit in an escape sequence that doesn't match a back-reference")
|
||||
MSG_DEF(JSMSG_BAD_BACKREF, 149, 0, JSEXN_SYNTAXERR, "back-reference exceeds number of capturing parentheses")
|
||||
MSG_DEF(JSMSG_PRECISION_RANGE, 150, 1, JSEXN_RANGEERR, "precision {0} out of range")
|
||||
MSG_DEF(JSMSG_BAD_GETTER_OR_SETTER, 151, 1, JSEXN_TYPEERR, "invalid {0} usage")
|
||||
MSG_DEF(JSMSG_BAD_ARRAY_LENGTH, 152, 0, JSEXN_RANGEERR, "invalid array length")
|
||||
MSG_DEF(JSMSG_CANT_DESCRIBE_PROPS, 153, 1, JSEXN_TYPEERR, "can't describe non-native properties of class {0}")
|
||||
MSG_DEF(JSMSG_BAD_APPLY_ARGS, 154, 1, JSEXN_TYPEERR, "second argument to Function.prototype.{0} must be an array")
|
||||
MSG_DEF(JSMSG_REDECLARED_VAR, 155, 2, JSEXN_TYPEERR, "redeclaration of {0} {1}")
|
||||
MSG_DEF(JSMSG_UNDECLARED_VAR, 156, 1, JSEXN_REFERENCEERR, "assignment to undeclared variable {0}")
|
||||
MSG_DEF(JSMSG_ANON_NO_RETURN_VALUE, 157, 0, JSEXN_TYPEERR, "anonymous function does not always return a value")
|
||||
MSG_DEF(JSMSG_DEPRECATED_USAGE, 158, 1, JSEXN_REFERENCEERR, "deprecated {0} usage")
|
||||
MSG_DEF(JSMSG_BAD_URI, 159, 0, JSEXN_URIERR, "malformed URI sequence")
|
||||
MSG_DEF(JSMSG_GETTER_ONLY, 160, 0, JSEXN_TYPEERR, "setting a property that has only a getter")
|
||||
MSG_DEF(JSMSG_IDSTART_AFTER_NUMBER, 161, 0, JSEXN_SYNTAXERR, "identifier starts immediately after numeric literal")
|
||||
MSG_DEF(JSMSG_UNDEFINED_PROP, 162, 1, JSEXN_REFERENCEERR, "reference to undefined property {0}")
|
||||
MSG_DEF(JSMSG_USELESS_EXPR, 163, 0, JSEXN_TYPEERR, "useless expression")
|
||||
MSG_DEF(JSMSG_REDECLARED_PARAM, 164, 1, JSEXN_TYPEERR, "redeclaration of formal parameter {0}")
|
||||
MSG_DEF(JSMSG_NEWREGEXP_FLAGGED, 165, 0, JSEXN_TYPEERR, "can't supply flags when constructing one RegExp from another")
|
||||
MSG_DEF(JSMSG_RESERVED_SLOT_RANGE, 166, 0, JSEXN_RANGEERR, "reserved slot index out of range")
|
||||
MSG_DEF(JSMSG_CANT_DECODE_PRINCIPALS, 167, 0, JSEXN_INTERNALERR, "can't decode JSPrincipals")
|
||||
MSG_DEF(JSMSG_CANT_SEAL_OBJECT, 168, 1, JSEXN_ERR, "can't seal {0} objects")
|
||||
MSG_DEF(JSMSG_TOO_MANY_CATCH_VARS, 169, 0, JSEXN_SYNTAXERR, "too many catch variables")
|
||||
MSG_DEF(JSMSG_BAD_XML_MARKUP, 170, 0, JSEXN_SYNTAXERR, "invalid XML markup")
|
||||
MSG_DEF(JSMSG_BAD_XML_CHARACTER, 171, 0, JSEXN_SYNTAXERR, "illegal XML character")
|
||||
MSG_DEF(JSMSG_BAD_DEFAULT_XML_NAMESPACE,172,0,JSEXN_SYNTAXERR, "invalid default XML namespace")
|
||||
MSG_DEF(JSMSG_BAD_XML_NAME_SYNTAX, 173, 0, JSEXN_SYNTAXERR, "invalid XML name")
|
||||
MSG_DEF(JSMSG_BRACKET_AFTER_ATTR_EXPR,174, 0, JSEXN_SYNTAXERR, "missing ] after attribute expression")
|
||||
MSG_DEF(JSMSG_NESTING_GENERATOR, 175, 1, JSEXN_TYPEERR, "already executing generator {0}")
|
||||
MSG_DEF(JSMSG_CURLY_IN_XML_EXPR, 176, 0, JSEXN_SYNTAXERR, "missing } in XML expression")
|
||||
MSG_DEF(JSMSG_BAD_XML_NAMESPACE, 177, 1, JSEXN_TYPEERR, "invalid XML namespace {0}")
|
||||
MSG_DEF(JSMSG_BAD_XML_ATTR_NAME, 178, 1, JSEXN_TYPEERR, "invalid XML attribute name {0}")
|
||||
MSG_DEF(JSMSG_BAD_XML_NAME, 179, 1, JSEXN_TYPEERR, "invalid XML name {0}")
|
||||
MSG_DEF(JSMSG_BAD_XML_CONVERSION, 180, 1, JSEXN_TYPEERR, "can't convert {0} to XML")
|
||||
MSG_DEF(JSMSG_BAD_XMLLIST_CONVERSION, 181, 1, JSEXN_TYPEERR, "can't convert {0} to XMLList")
|
||||
MSG_DEF(JSMSG_BAD_GENERATOR_SEND, 182, 1, JSEXN_TYPEERR, "attempt to send {0} to newborn generator")
|
||||
MSG_DEF(JSMSG_NO_ASSIGN_IN_XML_ATTR, 183, 0, JSEXN_SYNTAXERR, "missing = in XML attribute")
|
||||
MSG_DEF(JSMSG_BAD_XML_ATTR_VALUE, 184, 0, JSEXN_SYNTAXERR, "invalid XML attribute value")
|
||||
MSG_DEF(JSMSG_XML_TAG_NAME_MISMATCH, 185, 1, JSEXN_SYNTAXERR, "XML tag name mismatch (expected {0})")
|
||||
MSG_DEF(JSMSG_BAD_XML_TAG_SYNTAX, 186, 0, JSEXN_SYNTAXERR, "invalid XML tag syntax")
|
||||
MSG_DEF(JSMSG_BAD_XML_LIST_SYNTAX, 187, 0, JSEXN_SYNTAXERR, "invalid XML list syntax")
|
||||
MSG_DEF(JSMSG_INCOMPATIBLE_METHOD, 188, 3, JSEXN_TYPEERR, "{0} {1} called on incompatible {2}")
|
||||
MSG_DEF(JSMSG_CANT_SET_XML_ATTRS, 189, 0, JSEXN_INTERNALERR, "can't set XML property attributes")
|
||||
MSG_DEF(JSMSG_END_OF_XML_SOURCE, 190, 0, JSEXN_SYNTAXERR, "unexpected end of XML source")
|
||||
MSG_DEF(JSMSG_END_OF_XML_ENTITY, 191, 0, JSEXN_SYNTAXERR, "unexpected end of XML entity")
|
||||
MSG_DEF(JSMSG_BAD_XML_QNAME, 192, 0, JSEXN_SYNTAXERR, "invalid XML qualified name")
|
||||
MSG_DEF(JSMSG_BAD_FOR_EACH_LOOP, 193, 0, JSEXN_SYNTAXERR, "invalid for each loop")
|
||||
MSG_DEF(JSMSG_BAD_XMLLIST_PUT, 194, 1, JSEXN_TYPEERR, "can't set property {0} in XMLList")
|
||||
MSG_DEF(JSMSG_UNKNOWN_XML_ENTITY, 195, 1, JSEXN_TYPEERR, "unknown XML entity {0}")
|
||||
MSG_DEF(JSMSG_BAD_XML_NCR, 196, 1, JSEXN_TYPEERR, "malformed XML character {0}")
|
||||
MSG_DEF(JSMSG_UNDEFINED_XML_NAME, 197, 1, JSEXN_REFERENCEERR, "reference to undefined XML name {0}")
|
||||
MSG_DEF(JSMSG_DUPLICATE_XML_ATTR, 198, 1, JSEXN_TYPEERR, "duplicate XML attribute {0}")
|
||||
MSG_DEF(JSMSG_TOO_MANY_LOCALS, 199, 0, JSEXN_SYNTAXERR, "too many local variables")
|
||||
MSG_DEF(JSMSG_ARRAY_INIT_TOO_BIG, 200, 0, JSEXN_INTERNALERR, "array initialiser too large")
|
||||
MSG_DEF(JSMSG_REGEXP_TOO_COMPLEX, 201, 0, JSEXN_INTERNALERR, "regular expression too complex")
|
||||
MSG_DEF(JSMSG_BUFFER_TOO_SMALL, 202, 0, JSEXN_INTERNALERR, "buffer too small")
|
||||
MSG_DEF(JSMSG_BAD_SURROGATE_CHAR, 203, 1, JSEXN_TYPEERR, "bad surrogate character {0}")
|
||||
MSG_DEF(JSMSG_UTF8_CHAR_TOO_LARGE, 204, 1, JSEXN_TYPEERR, "UTF-8 character {0} too large")
|
||||
MSG_DEF(JSMSG_MALFORMED_UTF8_CHAR, 205, 1, JSEXN_TYPEERR, "malformed UTF-8 character sequence at offset {0}")
|
||||
MSG_DEF(JSMSG_USER_DEFINED_ERROR, 206, 0, JSEXN_ERR, "JS_ReportError was called")
|
||||
MSG_DEF(JSMSG_WRONG_CONSTRUCTOR, 207, 1, JSEXN_TYPEERR, "wrong constructor called for {0}")
|
||||
MSG_DEF(JSMSG_BAD_GENERATOR_RETURN, 208, 1, JSEXN_TYPEERR, "generator function {0} returns a value")
|
||||
MSG_DEF(JSMSG_BAD_ANON_GENERATOR_RETURN, 209, 0, JSEXN_TYPEERR, "anonymous generator function returns a value")
|
||||
MSG_DEF(JSMSG_NAME_AFTER_FOR_PAREN, 210, 0, JSEXN_SYNTAXERR, "missing name after for (")
|
||||
MSG_DEF(JSMSG_IN_AFTER_FOR_NAME, 211, 0, JSEXN_SYNTAXERR, "missing 'in' or 'of' after for")
|
||||
MSG_DEF(JSMSG_BAD_TRAP_RETURN_VALUE, 212, 2, JSEXN_TYPEERR,"trap {1} for {0} returned a primitive value")
|
||||
MSG_DEF(JSMSG_KEYWORD_NOT_NS, 213, 0, JSEXN_SYNTAXERR, "keyword is used as namespace")
|
||||
MSG_DEF(JSMSG_BAD_GENERATOR_YIELD, 214, 1, JSEXN_TYPEERR, "yield from closing generator {0}")
|
||||
MSG_DEF(JSMSG_BAD_GENERATOR_SYNTAX, 215, 1, JSEXN_SYNTAXERR, "{0} expression must be parenthesized")
|
||||
MSG_DEF(JSMSG_ARRAY_COMP_LEFTSIDE, 216, 0, JSEXN_SYNTAXERR, "invalid array comprehension left-hand side")
|
||||
MSG_DEF(JSMSG_NON_XML_FILTER, 217, 1, JSEXN_TYPEERR, "XML filter is applied to non-XML value {0}")
|
||||
MSG_DEF(JSMSG_EMPTY_ARRAY_REDUCE, 218, 0, JSEXN_TYPEERR, "reduce of empty array with no initial value")
|
||||
MSG_DEF(JSMSG_NON_LIST_XML_METHOD, 219, 2, JSEXN_TYPEERR, "can't call {0} method on an XML list with {1} elements")
|
||||
MSG_DEF(JSMSG_BAD_DELETE_OPERAND, 220, 0, JSEXN_REFERENCEERR, "invalid delete operand")
|
||||
MSG_DEF(JSMSG_BAD_INCOP_OPERAND, 221, 0, JSEXN_REFERENCEERR, "invalid increment/decrement operand")
|
||||
MSG_DEF(JSMSG_UNEXPECTED_TYPE, 222, 2, JSEXN_TYPEERR, "{0} is {1}")
|
||||
MSG_DEF(JSMSG_LET_DECL_NOT_IN_BLOCK, 223, 0, JSEXN_SYNTAXERR, "let declaration not directly within block")
|
||||
MSG_DEF(JSMSG_BAD_OBJECT_INIT, 224, 0, JSEXN_SYNTAXERR, "invalid object initializer")
|
||||
MSG_DEF(JSMSG_CANT_SET_ARRAY_ATTRS, 225, 0, JSEXN_INTERNALERR, "can't set attributes on indexed array properties")
|
||||
MSG_DEF(JSMSG_EVAL_ARITY, 226, 0, JSEXN_TYPEERR, "eval accepts only one parameter")
|
||||
MSG_DEF(JSMSG_MISSING_FUN_ARG, 227, 2, JSEXN_TYPEERR, "missing argument {0} when calling function {1}")
|
||||
MSG_DEF(JSMSG_JSON_BAD_PARSE, 228, 1, JSEXN_SYNTAXERR, "JSON.parse: {0}")
|
||||
MSG_DEF(JSMSG_JSON_BAD_STRINGIFY, 229, 0, JSEXN_ERR, "JSON.stringify")
|
||||
MSG_DEF(JSMSG_NOT_CALLABLE_OR_UNDEFINED, 230, 0, JSEXN_TYPEERR, "value is not a function or undefined")
|
||||
MSG_DEF(JSMSG_NOT_NONNULL_OBJECT, 231, 0, JSEXN_TYPEERR, "value is not a non-null object")
|
||||
MSG_DEF(JSMSG_DEPRECATED_OCTAL, 232, 0, JSEXN_SYNTAXERR, "octal literals and octal escape sequences are deprecated")
|
||||
MSG_DEF(JSMSG_STRICT_CODE_WITH, 233, 0, JSEXN_SYNTAXERR, "strict mode code may not contain 'with' statements")
|
||||
MSG_DEF(JSMSG_DUPLICATE_PROPERTY, 234, 1, JSEXN_SYNTAXERR, "property name {0} appears more than once in object literal")
|
||||
MSG_DEF(JSMSG_DEPRECATED_DELETE_OPERAND, 235, 0, JSEXN_SYNTAXERR, "applying the 'delete' operator to an unqualified name is deprecated")
|
||||
MSG_DEF(JSMSG_DEPRECATED_ASSIGN, 236, 1, JSEXN_SYNTAXERR, "assignment to {0} is deprecated")
|
||||
MSG_DEF(JSMSG_BAD_BINDING, 237, 1, JSEXN_SYNTAXERR, "redefining {0} is deprecated")
|
||||
MSG_DEF(JSMSG_INVALID_DESCRIPTOR, 238, 0, JSEXN_TYPEERR, "property descriptors must not specify a value or be writable when a getter or setter has been specified")
|
||||
MSG_DEF(JSMSG_OBJECT_NOT_EXTENSIBLE, 239, 1, JSEXN_TYPEERR, "{0} is not extensible")
|
||||
MSG_DEF(JSMSG_CANT_REDEFINE_PROP, 240, 1, JSEXN_TYPEERR, "can't redefine non-configurable property '{0}'")
|
||||
MSG_DEF(JSMSG_CANT_APPEND_TO_ARRAY, 241, 0, JSEXN_TYPEERR, "can't add elements past the end of an array if its length property is unwritable")
|
||||
MSG_DEF(JSMSG_CANT_DEFINE_ARRAY_LENGTH,242, 0, JSEXN_INTERNALERR, "defining the length property on an array is not currently supported")
|
||||
MSG_DEF(JSMSG_CANT_DEFINE_ARRAY_INDEX,243, 0, JSEXN_TYPEERR, "can't define array index property")
|
||||
MSG_DEF(JSMSG_TYPED_ARRAY_BAD_INDEX, 244, 0, JSEXN_ERR, "invalid or out-of-range index")
|
||||
MSG_DEF(JSMSG_TYPED_ARRAY_NEGATIVE_ARG, 245, 1, JSEXN_ERR, "argument {0} must be >= 0")
|
||||
MSG_DEF(JSMSG_TYPED_ARRAY_BAD_ARGS, 246, 0, JSEXN_ERR, "invalid arguments")
|
||||
MSG_DEF(JSMSG_CSP_BLOCKED_FUNCTION, 247, 0, JSEXN_ERR, "call to Function() blocked by CSP")
|
||||
MSG_DEF(JSMSG_BAD_GET_SET_FIELD, 248, 1, JSEXN_TYPEERR, "property descriptor's {0} field is neither undefined nor a function")
|
||||
MSG_DEF(JSMSG_BAD_PROXY_FIX, 249, 0, JSEXN_TYPEERR, "proxy was fixed while executing the handler")
|
||||
MSG_DEF(JSMSG_INVALID_EVAL_SCOPE_ARG, 250, 0, JSEXN_EVALERR, "invalid eval scope argument")
|
||||
MSG_DEF(JSMSG_ACCESSOR_WRONG_ARGS, 251, 3, JSEXN_SYNTAXERR, "{0} functions must have {1} argument{2}")
|
||||
MSG_DEF(JSMSG_THROW_TYPE_ERROR, 252, 0, JSEXN_TYPEERR, "'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them")
|
||||
MSG_DEF(JSMSG_BAD_TOISOSTRING_PROP, 253, 0, JSEXN_TYPEERR, "toISOString property is not callable")
|
||||
MSG_DEF(JSMSG_BAD_PARSE_NODE, 254, 0, JSEXN_INTERNALERR, "bad parse node")
|
||||
MSG_DEF(JSMSG_NOT_EXPECTED_TYPE, 255, 3, JSEXN_TYPEERR, "{0}: expected {1}, got {2}")
|
||||
MSG_DEF(JSMSG_CALLER_IS_STRICT, 256, 0, JSEXN_TYPEERR, "access to strict mode caller function is censored")
|
||||
MSG_DEF(JSMSG_NEED_DEBUG_MODE, 257, 0, JSEXN_ERR, "function can be called only in debug mode")
|
||||
MSG_DEF(JSMSG_STRICT_CODE_LET_EXPR_STMT, 258, 0, JSEXN_ERR, "strict mode code may not contain unparenthesized let expression statements")
|
||||
MSG_DEF(JSMSG_CANT_CHANGE_EXTENSIBILITY, 259, 0, JSEXN_TYPEERR, "can't change object's extensibility")
|
||||
MSG_DEF(JSMSG_SC_BAD_SERIALIZED_DATA, 260, 1, JSEXN_INTERNALERR, "bad serialized structured data ({0})")
|
||||
MSG_DEF(JSMSG_SC_UNSUPPORTED_TYPE, 261, 0, JSEXN_TYPEERR, "unsupported type for structured data")
|
||||
MSG_DEF(JSMSG_SC_RECURSION, 262, 0, JSEXN_INTERNALERR, "recursive object")
|
||||
MSG_DEF(JSMSG_CANT_WRAP_XML_OBJECT, 263, 0, JSEXN_TYPEERR, "can't wrap XML objects")
|
||||
MSG_DEF(JSMSG_BAD_CLONE_VERSION, 264, 0, JSEXN_ERR, "unsupported structured clone version")
|
||||
MSG_DEF(JSMSG_CANT_CLONE_OBJECT, 265, 0, JSEXN_TYPEERR, "can't clone object")
|
||||
MSG_DEF(JSMSG_NON_NATIVE_SCOPE, 266, 0, JSEXN_TYPEERR, "non-native scope object")
|
||||
MSG_DEF(JSMSG_STRICT_FUNCTION_STATEMENT, 267, 0, JSEXN_SYNTAXERR, "in strict mode code, functions may be declared only at top level or immediately within another function")
|
||||
MSG_DEF(JSMSG_INVALID_FOR_IN_INIT, 268, 0, JSEXN_SYNTAXERR, "for-in loop let declaration may not have an initializer")
|
||||
MSG_DEF(JSMSG_CLEARED_SCOPE, 269, 0, JSEXN_TYPEERR, "attempt to run compile-and-go script on a cleared scope")
|
||||
MSG_DEF(JSMSG_MALFORMED_ESCAPE, 270, 1, JSEXN_SYNTAXERR, "malformed {0} character escape sequence")
|
||||
MSG_DEF(JSMSG_BAD_GENEXP_BODY, 271, 1, JSEXN_SYNTAXERR, "illegal use of {0} in generator expression")
|
||||
MSG_DEF(JSMSG_XML_PROTO_FORBIDDEN, 272, 0, JSEXN_TYPEERR, "can't set prototype of an object to an XML value")
|
||||
MSG_DEF(JSMSG_UNNAMED_FUNCTION_STMT, 273, 0, JSEXN_SYNTAXERR, "function statement requires a name")
|
||||
MSG_DEF(JSMSG_CCW_REQUIRED, 274, 1, JSEXN_TYPEERR, "{0}: argument must be an object from a different compartment")
|
||||
MSG_DEF(JSMSG_DEBUG_BAD_RESUMPTION, 275, 0, JSEXN_TYPEERR, "debugger resumption value must be undefined, {throw: val}, {return: val}, or null")
|
||||
MSG_DEF(JSMSG_ASSIGN_FUNCTION_OR_NULL, 276, 1, JSEXN_TYPEERR, "value assigned to {0} must be a function or null")
|
||||
MSG_DEF(JSMSG_DEBUG_NOT_LIVE, 277, 1, JSEXN_ERR, "{0} is not live")
|
||||
MSG_DEF(JSMSG_DEBUG_OBJECT_WRONG_OWNER, 278, 0, JSEXN_TYPEERR, "Debugger.Object belongs to a different Debugger")
|
||||
MSG_DEF(JSMSG_DEBUG_OBJECT_PROTO, 279, 0, JSEXN_TYPEERR, "Debugger.Object.prototype is not a valid Debugger.Object")
|
||||
MSG_DEF(JSMSG_DEBUG_LOOP, 280, 0, JSEXN_TYPEERR, "cannot debug an object in same compartment as debugger or a compartment that is already debugging the debugger")
|
||||
MSG_DEF(JSMSG_DEBUG_NOT_IDLE, 281, 0, JSEXN_ERR, "can't start debugging: a debuggee script is on the stack")
|
||||
MSG_DEF(JSMSG_DEBUG_BAD_OFFSET, 282, 0, JSEXN_TYPEERR, "invalid script offset")
|
||||
MSG_DEF(JSMSG_DEBUG_BAD_LINE, 283, 0, JSEXN_TYPEERR, "invalid line number")
|
||||
MSG_DEF(JSMSG_DEBUG_NOT_DEBUGGING, 284, 0, JSEXN_ERR, "can't set breakpoint: script global is not a debuggee")
|
||||
MSG_DEF(JSMSG_DEBUG_COMPARTMENT_MISMATCH, 285, 2, JSEXN_TYPEERR, "{0}: descriptor .{1} property is an object in a different compartment than the target object")
|
||||
MSG_DEF(JSMSG_DEBUG_NOT_SCRIPT_FRAME, 286, 0, JSEXN_ERR, "stack frame is not running JavaScript code")
|
||||
MSG_DEF(JSMSG_CANT_WATCH_PROP, 287, 0, JSEXN_TYPEERR, "properties whose names are objects can't be watched")
|
||||
MSG_DEF(JSMSG_CSP_BLOCKED_EVAL, 288, 0, JSEXN_ERR, "call to eval() blocked by CSP")
|
||||
MSG_DEF(JSMSG_DEBUG_NO_SCOPE_OBJECT, 289, 0, JSEXN_TYPEERR, "declarative Environments don't have binding objects")
|
||||
MSG_DEF(JSMSG_EMPTY_CONSEQUENT, 290, 0, JSEXN_SYNTAXERR, "mistyped ; after conditional?")
|
||||
MSG_DEF(JSMSG_NOT_ITERABLE, 291, 1, JSEXN_TYPEERR, "{0} is not iterable")
|
||||
MSG_DEF(JSMSG_QUERY_LINE_WITHOUT_URL, 292, 0, JSEXN_TYPEERR, "findScripts query object has 'line' property, but no 'url' property")
|
||||
MSG_DEF(JSMSG_QUERY_INNERMOST_WITHOUT_LINE_URL, 293, 0, JSEXN_TYPEERR, "findScripts query object has 'innermost' property without both 'url' and 'line' properties")
|
||||
MSG_DEF(JSMSG_DEBUG_VARIABLE_NOT_FOUND, 294, 0, JSEXN_TYPEERR, "variable not found in environment")
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,92 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** 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 Mozilla Communicator client code, released
|
||||
* March 31, 1998.
|
||||
*
|
||||
* 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 of 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 ***** */
|
||||
|
||||
/*
|
||||
* This section typedefs the old 'native' types to the new <stdint.h> types.
|
||||
* These redefinitions are provided solely to allow JSAPI users to more easily
|
||||
* transition to <stdint.h> types. They are not to be used in the JSAPI, and
|
||||
* new JSAPI user code should not use them. This mapping file may eventually
|
||||
* be removed from SpiderMonkey, so don't depend on it in the long run.
|
||||
*/
|
||||
|
||||
/*
|
||||
* BEWARE: Comity with other implementers of these types is not guaranteed.
|
||||
* Indeed, if you use this header and third-party code defining these
|
||||
* types, *expect* to encounter either compile errors or link errors,
|
||||
* depending how these types are used and on the order of inclusion.
|
||||
* It is safest to use only the JSAPI <stdint.h>-style types,
|
||||
* customizing those types using MOZ_CUSTOM_STDINT_H if necessary.
|
||||
*/
|
||||
#ifndef PROTYPES_H
|
||||
#define PROTYPES_H
|
||||
|
||||
#include "mozilla/StandardInteger.h"
|
||||
|
||||
#include "js-config.h"
|
||||
|
||||
typedef uint8_t uint8;
|
||||
typedef uint16_t uint16;
|
||||
typedef uint32_t uint32;
|
||||
typedef uint64_t uint64;
|
||||
|
||||
/*
|
||||
* On AIX 4.3, sys/inttypes.h (which is included by sys/types.h, a very
|
||||
* common header file) defines the types int8, int16, int32, and int64.
|
||||
* So we don't define these four types here to avoid conflicts in case
|
||||
* the code also includes sys/types.h.
|
||||
*/
|
||||
#if defined(AIX) && defined(HAVE_SYS_INTTYPES_H)
|
||||
#include <sys/inttypes.h>
|
||||
#else
|
||||
typedef int8_t int8;
|
||||
typedef int16_t int16;
|
||||
typedef int32_t int32;
|
||||
typedef int64_t int64;
|
||||
#endif /* AIX && HAVE_SYS_INTTYPES_H */
|
||||
|
||||
typedef uint8_t JSUint8;
|
||||
typedef uint16_t JSUint16;
|
||||
typedef uint32_t JSUint32;
|
||||
typedef uint64_t JSUint64;
|
||||
|
||||
typedef int8_t JSInt8;
|
||||
typedef int16_t JSInt16;
|
||||
typedef int32_t JSInt32;
|
||||
typedef int64_t JSInt64;
|
||||
|
||||
#endif /* !defined(PROTYPES_H) */
|
|
@ -0,0 +1,190 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sw=4 et tw=99 ft=cpp:
|
||||
*
|
||||
* ***** 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 about:memory glue.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Ms2ger <ms2ger@gmail.com>.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* 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 js_MemoryMetrics_h
|
||||
#define js_MemoryMetrics_h
|
||||
|
||||
/*
|
||||
* These declarations are not within jsapi.h because they are highly likely
|
||||
* to change in the future. Depend on them at your own risk.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "jsalloc.h"
|
||||
#include "jspubtd.h"
|
||||
|
||||
#include "js/Utility.h"
|
||||
#include "js/Vector.h"
|
||||
|
||||
namespace JS {
|
||||
|
||||
/* Data for tracking analysis/inference memory usage. */
|
||||
struct TypeInferenceSizes
|
||||
{
|
||||
size_t scripts;
|
||||
size_t objects;
|
||||
size_t tables;
|
||||
size_t temporary;
|
||||
};
|
||||
|
||||
struct CompartmentStats
|
||||
{
|
||||
CompartmentStats() {
|
||||
memset(this, 0, sizeof(*this));
|
||||
}
|
||||
|
||||
void *extra;
|
||||
size_t gcHeapArenaHeaders;
|
||||
size_t gcHeapArenaPadding;
|
||||
size_t gcHeapArenaUnused;
|
||||
|
||||
size_t gcHeapObjectsNonFunction;
|
||||
size_t gcHeapObjectsFunction;
|
||||
size_t gcHeapStrings;
|
||||
size_t gcHeapShapesTree;
|
||||
size_t gcHeapShapesDict;
|
||||
size_t gcHeapShapesBase;
|
||||
size_t gcHeapScripts;
|
||||
size_t gcHeapTypeObjects;
|
||||
size_t gcHeapXML;
|
||||
|
||||
size_t objectSlots;
|
||||
size_t objectElements;
|
||||
size_t objectMisc;
|
||||
size_t stringChars;
|
||||
size_t shapesExtraTreeTables;
|
||||
size_t shapesExtraDictTables;
|
||||
size_t shapesExtraTreeShapeKids;
|
||||
size_t shapesCompartmentTables;
|
||||
size_t scriptData;
|
||||
|
||||
#ifdef JS_METHODJIT
|
||||
size_t mjitCode;
|
||||
size_t mjitData;
|
||||
#endif
|
||||
TypeInferenceSizes typeInferenceSizes;
|
||||
};
|
||||
|
||||
struct RuntimeStats
|
||||
{
|
||||
RuntimeStats(JSMallocSizeOfFun mallocSizeOf)
|
||||
: runtimeObject(0)
|
||||
, runtimeAtomsTable(0)
|
||||
, runtimeContexts(0)
|
||||
, runtimeNormal(0)
|
||||
, runtimeTemporary(0)
|
||||
, runtimeRegexpCode(0)
|
||||
, runtimeStackCommitted(0)
|
||||
, runtimeGCMarker(0)
|
||||
, gcHeapChunkTotal(0)
|
||||
, gcHeapChunkCleanUnused(0)
|
||||
, gcHeapChunkDirtyUnused(0)
|
||||
, gcHeapChunkCleanDecommitted(0)
|
||||
, gcHeapChunkDirtyDecommitted(0)
|
||||
, gcHeapArenaUnused(0)
|
||||
, gcHeapChunkAdmin(0)
|
||||
, gcHeapUnusedPercentage(0)
|
||||
, totalObjects(0)
|
||||
, totalShapes(0)
|
||||
, totalScripts(0)
|
||||
, totalStrings(0)
|
||||
#ifdef JS_METHODJIT
|
||||
, totalMjit(0)
|
||||
#endif
|
||||
, totalTypeInference(0)
|
||||
, totalAnalysisTemp(0)
|
||||
, compartmentStatsVector()
|
||||
, currCompartmentStats(NULL)
|
||||
, mallocSizeOf(mallocSizeOf)
|
||||
{}
|
||||
|
||||
size_t runtimeObject;
|
||||
size_t runtimeAtomsTable;
|
||||
size_t runtimeContexts;
|
||||
size_t runtimeNormal;
|
||||
size_t runtimeTemporary;
|
||||
size_t runtimeRegexpCode;
|
||||
size_t runtimeStackCommitted;
|
||||
size_t runtimeGCMarker;
|
||||
size_t gcHeapChunkTotal;
|
||||
size_t gcHeapChunkCleanUnused;
|
||||
size_t gcHeapChunkDirtyUnused;
|
||||
size_t gcHeapChunkCleanDecommitted;
|
||||
size_t gcHeapChunkDirtyDecommitted;
|
||||
size_t gcHeapArenaUnused;
|
||||
size_t gcHeapChunkAdmin;
|
||||
size_t gcHeapUnusedPercentage;
|
||||
size_t totalObjects;
|
||||
size_t totalShapes;
|
||||
size_t totalScripts;
|
||||
size_t totalStrings;
|
||||
#ifdef JS_METHODJIT
|
||||
size_t totalMjit;
|
||||
#endif
|
||||
size_t totalTypeInference;
|
||||
size_t totalAnalysisTemp;
|
||||
|
||||
js::Vector<CompartmentStats, 0, js::SystemAllocPolicy> compartmentStatsVector;
|
||||
CompartmentStats *currCompartmentStats;
|
||||
|
||||
JSMallocSizeOfFun mallocSizeOf;
|
||||
|
||||
virtual void initExtraCompartmentStats(JSCompartment *c, CompartmentStats *cstats) = 0;
|
||||
};
|
||||
|
||||
#ifdef JS_THREADSAFE
|
||||
|
||||
extern JS_PUBLIC_API(bool)
|
||||
CollectRuntimeStats(JSRuntime *rt, RuntimeStats *rtStats);
|
||||
|
||||
extern JS_PUBLIC_API(int64_t)
|
||||
GetExplicitNonHeapForRuntime(JSRuntime *rt, JSMallocSizeOfFun mallocSizeOf);
|
||||
|
||||
#endif /* JS_THREADSAFE */
|
||||
|
||||
extern JS_PUBLIC_API(size_t)
|
||||
SystemCompartmentCount(const JSRuntime *rt);
|
||||
|
||||
extern JS_PUBLIC_API(size_t)
|
||||
UserCompartmentCount(const JSRuntime *rt);
|
||||
|
||||
} // namespace JS
|
||||
|
||||
#endif // js_MemoryMetrics_h
|
|
@ -0,0 +1,185 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sw=4 et tw=99 ft=cpp:
|
||||
*
|
||||
* ***** 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 Mozilla SpiderMonkey JavaScript code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* the Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Luke Wagner <luke@mozilla.com>
|
||||
*
|
||||
* 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 js_template_lib_h__
|
||||
#define js_template_lib_h__
|
||||
|
||||
#include "jstypes.h"
|
||||
|
||||
/*
|
||||
* Library of reusable template meta-functions (that is, functions on types and
|
||||
* compile-time values). Meta-functions are placed inside the 'tl' namespace to
|
||||
* avoid conflict with non-meta functions that logically have the same name
|
||||
* (e.g., js::tl::Min vs. js::Min).
|
||||
*/
|
||||
|
||||
namespace js {
|
||||
namespace tl {
|
||||
|
||||
/* Compute min/max/clamp. */
|
||||
template <size_t i, size_t j> struct Min {
|
||||
static const size_t result = i < j ? i : j;
|
||||
};
|
||||
template <size_t i, size_t j> struct Max {
|
||||
static const size_t result = i > j ? i : j;
|
||||
};
|
||||
template <size_t i, size_t min, size_t max> struct Clamp {
|
||||
static const size_t result = i < min ? min : (i > max ? max : i);
|
||||
};
|
||||
|
||||
/* Compute x^y. */
|
||||
template <size_t x, size_t y> struct Pow {
|
||||
static const size_t result = x * Pow<x, y - 1>::result;
|
||||
};
|
||||
template <size_t x> struct Pow<x,0> {
|
||||
static const size_t result = 1;
|
||||
};
|
||||
|
||||
/* Compute floor(log2(i)). */
|
||||
template <size_t i> struct FloorLog2 {
|
||||
static const size_t result = 1 + FloorLog2<i / 2>::result;
|
||||
};
|
||||
template <> struct FloorLog2<0> { /* Error */ };
|
||||
template <> struct FloorLog2<1> { static const size_t result = 0; };
|
||||
|
||||
/* Compute ceiling(log2(i)). */
|
||||
template <size_t i> struct CeilingLog2 {
|
||||
static const size_t result = FloorLog2<2 * i - 1>::result;
|
||||
};
|
||||
|
||||
/* Round up to the nearest power of 2. */
|
||||
template <size_t i> struct RoundUpPow2 {
|
||||
static const size_t result = size_t(1) << CeilingLog2<i>::result;
|
||||
};
|
||||
template <> struct RoundUpPow2<0> {
|
||||
static const size_t result = 1;
|
||||
};
|
||||
|
||||
/* Compute the number of bits in the given unsigned type. */
|
||||
template <class T> struct BitSize {
|
||||
static const size_t result = sizeof(T) * JS_BITS_PER_BYTE;
|
||||
};
|
||||
|
||||
/* Allow Assertions by only including the 'result' typedef if 'true'. */
|
||||
template <bool> struct StaticAssert {};
|
||||
template <> struct StaticAssert<true> { typedef int result; };
|
||||
|
||||
/* Boolean test for whether two types are the same. */
|
||||
template <class T, class U> struct IsSameType {
|
||||
static const bool result = false;
|
||||
};
|
||||
template <class T> struct IsSameType<T,T> {
|
||||
static const bool result = true;
|
||||
};
|
||||
|
||||
/*
|
||||
* Produce an N-bit mask, where N <= BitSize<size_t>::result. Handle the
|
||||
* language-undefined edge case when N = BitSize<size_t>::result.
|
||||
*/
|
||||
template <size_t N> struct NBitMask {
|
||||
typedef typename StaticAssert<N < BitSize<size_t>::result>::result _;
|
||||
static const size_t result = (size_t(1) << N) - 1;
|
||||
};
|
||||
template <> struct NBitMask<BitSize<size_t>::result> {
|
||||
static const size_t result = size_t(-1);
|
||||
};
|
||||
|
||||
/*
|
||||
* For the unsigned integral type size_t, compute a mask M for N such that
|
||||
* for all X, !(X & M) implies X * N will not overflow (w.r.t size_t)
|
||||
*/
|
||||
template <size_t N> struct MulOverflowMask {
|
||||
static const size_t result =
|
||||
~NBitMask<BitSize<size_t>::result - CeilingLog2<N>::result>::result;
|
||||
};
|
||||
template <> struct MulOverflowMask<0> { /* Error */ };
|
||||
template <> struct MulOverflowMask<1> { static const size_t result = 0; };
|
||||
|
||||
/*
|
||||
* Generate a mask for T such that if (X & sUnsafeRangeSizeMask), an X-sized
|
||||
* array of T's is big enough to cause a ptrdiff_t overflow when subtracting
|
||||
* a pointer to the end of the array from the beginning.
|
||||
*/
|
||||
template <class T> struct UnsafeRangeSizeMask {
|
||||
/*
|
||||
* The '2' factor means the top bit is clear, sizeof(T) converts from
|
||||
* units of elements to bytes.
|
||||
*/
|
||||
static const size_t result = MulOverflowMask<2 * sizeof(T)>::result;
|
||||
};
|
||||
|
||||
/* Return T stripped of any const-ness. */
|
||||
template <class T> struct StripConst { typedef T result; };
|
||||
template <class T> struct StripConst<const T> { typedef T result; };
|
||||
|
||||
/*
|
||||
* Traits class for identifying POD types. Until C++0x, there is no automatic
|
||||
* way to detect PODs, so for the moment it is done manually.
|
||||
*/
|
||||
template <class T> struct IsPodType { static const bool result = false; };
|
||||
template <> struct IsPodType<char> { static const bool result = true; };
|
||||
template <> struct IsPodType<signed char> { static const bool result = true; };
|
||||
template <> struct IsPodType<unsigned char> { static const bool result = true; };
|
||||
template <> struct IsPodType<short> { static const bool result = true; };
|
||||
template <> struct IsPodType<unsigned short> { static const bool result = true; };
|
||||
template <> struct IsPodType<int> { static const bool result = true; };
|
||||
template <> struct IsPodType<unsigned int> { static const bool result = true; };
|
||||
template <> struct IsPodType<long> { static const bool result = true; };
|
||||
template <> struct IsPodType<unsigned long> { static const bool result = true; };
|
||||
template <> struct IsPodType<long long> { static const bool result = true; };
|
||||
template <> struct IsPodType<unsigned long long> { static const bool result = true; };
|
||||
template <> struct IsPodType<bool> { static const bool result = true; };
|
||||
template <> struct IsPodType<float> { static const bool result = true; };
|
||||
template <> struct IsPodType<double> { static const bool result = true; };
|
||||
template <> struct IsPodType<wchar_t> { static const bool result = true; };
|
||||
template <typename T> struct IsPodType<T *> { static const bool result = true; };
|
||||
|
||||
template <bool cond, typename T, T v1, T v2> struct If { static const T result = v1; };
|
||||
template <typename T, T v1, T v2> struct If<false, T, v1, v2> { static const T result = v2; };
|
||||
|
||||
/*
|
||||
* Traits class for identifying types that are implicitly barriered.
|
||||
*/
|
||||
template <class T> struct IsPostBarrieredType { static const bool result = false; };
|
||||
|
||||
} /* namespace tl */
|
||||
} /* namespace js */
|
||||
|
||||
#endif /* js_template_lib_h__ */
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,121 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sw=4 et tw=99 ft=cpp:
|
||||
*
|
||||
* ***** 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 Mozilla SpiderMonkey JavaScript 1.9 code, released
|
||||
* July 16, 2009.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* the Mozilla Corporation.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of 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 jsalloc_h_
|
||||
#define jsalloc_h_
|
||||
|
||||
#include "jspubtd.h"
|
||||
#include "jsutil.h"
|
||||
|
||||
namespace js {
|
||||
|
||||
/*
|
||||
* Allocation policies. These model the concept:
|
||||
* - public copy constructor, assignment, destructor
|
||||
* - void *malloc_(size_t)
|
||||
* Responsible for OOM reporting on NULL return value.
|
||||
* - void *realloc_(size_t)
|
||||
* Responsible for OOM reporting on NULL return value.
|
||||
* The *used* bytes of the previous buffer is passed in
|
||||
* (rather than the old allocation size), in addition to
|
||||
* the *new* allocation size requested.
|
||||
* - void free_(void *)
|
||||
* - reportAllocOverflow()
|
||||
* Called on overflow before the container returns NULL.
|
||||
*/
|
||||
|
||||
/* Policy for using system memory functions and doing no error reporting. */
|
||||
class SystemAllocPolicy
|
||||
{
|
||||
public:
|
||||
void *malloc_(size_t bytes) { return js_malloc(bytes); }
|
||||
void *realloc_(void *p, size_t oldBytes, size_t bytes) { return js_realloc(p, bytes); }
|
||||
void free_(void *p) { js_free(p); }
|
||||
void reportAllocOverflow() const {}
|
||||
};
|
||||
|
||||
/*
|
||||
* Allocation policy that calls the system memory functions and reports errors
|
||||
* to the context. Since the JSContext given on construction is stored for
|
||||
* the lifetime of the container, this policy may only be used for containers
|
||||
* whose lifetime is a shorter than the given JSContext.
|
||||
*
|
||||
* FIXME bug 647103 - rewrite this in terms of temporary allocation functions,
|
||||
* not the system ones.
|
||||
*/
|
||||
class TempAllocPolicy
|
||||
{
|
||||
JSContext *const cx;
|
||||
|
||||
/*
|
||||
* Non-inline helper to call JSRuntime::onOutOfMemory with minimal
|
||||
* code bloat.
|
||||
*/
|
||||
JS_FRIEND_API(void *) onOutOfMemory(void *p, size_t nbytes);
|
||||
|
||||
public:
|
||||
TempAllocPolicy(JSContext *cx) : cx(cx) {}
|
||||
|
||||
JSContext *context() const {
|
||||
return cx;
|
||||
}
|
||||
|
||||
void *malloc_(size_t bytes) {
|
||||
void *p = js_malloc(bytes);
|
||||
if (JS_UNLIKELY(!p))
|
||||
p = onOutOfMemory(NULL, bytes);
|
||||
return p;
|
||||
}
|
||||
|
||||
void *realloc_(void *p, size_t oldBytes, size_t bytes) {
|
||||
void *p2 = js_realloc(p, bytes);
|
||||
if (JS_UNLIKELY(!p2))
|
||||
p2 = onOutOfMemory(p2, bytes);
|
||||
return p2;
|
||||
}
|
||||
|
||||
void free_(void *p) {
|
||||
js_free(p);
|
||||
}
|
||||
|
||||
JS_FRIEND_API(void) reportAllocOverflow() const;
|
||||
};
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
#endif /* jsalloc_h_ */
|
|
@ -1 +1 @@
|
|||
7a4bee3a76685b0cfa5b2c0a1e36332f7ed22e49
|
||||
e71bf3943ff22eeb475acd419c7005556859f6c4
|
|
@ -0,0 +1,489 @@
|
|||
/* -*- Mode: C++; tab-width: 8; 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 Mozilla Communicator client code, released
|
||||
* March 31, 1998.
|
||||
*
|
||||
* 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 of 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 jsatom_h___
|
||||
#define jsatom_h___
|
||||
|
||||
#include <stddef.h>
|
||||
#include "jsversion.h"
|
||||
#include "jsalloc.h"
|
||||
#include "jsapi.h"
|
||||
#include "jsprvtd.h"
|
||||
#include "jshash.h"
|
||||
#include "jspubtd.h"
|
||||
#include "jslock.h"
|
||||
|
||||
#include "gc/Barrier.h"
|
||||
#include "js/HashTable.h"
|
||||
|
||||
struct JSIdArray {
|
||||
int length;
|
||||
js::HeapId vector[1]; /* actually, length jsid words */
|
||||
};
|
||||
|
||||
/* Engine-internal extensions of jsid */
|
||||
|
||||
static JS_ALWAYS_INLINE jsid
|
||||
JSID_FROM_BITS(size_t bits)
|
||||
{
|
||||
jsid id;
|
||||
JSID_BITS(id) = bits;
|
||||
return id;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE jsid
|
||||
ATOM_TO_JSID(JSAtom *atom)
|
||||
{
|
||||
JS_ASSERT(((size_t)atom & 0x7) == 0);
|
||||
return JSID_FROM_BITS((size_t)atom);
|
||||
}
|
||||
|
||||
/* All strings stored in jsids are atomized. */
|
||||
static JS_ALWAYS_INLINE JSBool
|
||||
JSID_IS_ATOM(jsid id)
|
||||
{
|
||||
return JSID_IS_STRING(id);
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE JSBool
|
||||
JSID_IS_ATOM(jsid id, JSAtom *atom)
|
||||
{
|
||||
return JSID_BITS(id) == JSID_BITS(ATOM_TO_JSID(atom));
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE JSAtom *
|
||||
JSID_TO_ATOM(jsid id)
|
||||
{
|
||||
return (JSAtom *)JSID_TO_STRING(id);
|
||||
}
|
||||
|
||||
extern jsid
|
||||
js_CheckForStringIndex(jsid id);
|
||||
|
||||
JS_STATIC_ASSERT(sizeof(JSHashNumber) == 4);
|
||||
JS_STATIC_ASSERT(sizeof(jsid) == JS_BYTES_PER_WORD);
|
||||
|
||||
namespace js {
|
||||
|
||||
static JS_ALWAYS_INLINE JSHashNumber
|
||||
HashId(jsid id)
|
||||
{
|
||||
JS_ASSERT(js_CheckForStringIndex(id) == id);
|
||||
JSHashNumber n =
|
||||
#if JS_BYTES_PER_WORD == 4
|
||||
JSHashNumber(JSID_BITS(id));
|
||||
#elif JS_BYTES_PER_WORD == 8
|
||||
JSHashNumber(JSID_BITS(id)) ^ JSHashNumber(JSID_BITS(id) >> 32);
|
||||
#else
|
||||
# error "Unsupported configuration"
|
||||
#endif
|
||||
return n * JS_GOLDEN_RATIO;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE Value
|
||||
IdToValue(jsid id)
|
||||
{
|
||||
if (JSID_IS_STRING(id))
|
||||
return StringValue(JSID_TO_STRING(id));
|
||||
if (JS_LIKELY(JSID_IS_INT(id)))
|
||||
return Int32Value(JSID_TO_INT(id));
|
||||
if (JS_LIKELY(JSID_IS_OBJECT(id)))
|
||||
return ObjectValue(*JSID_TO_OBJECT(id));
|
||||
JS_ASSERT(JSID_IS_DEFAULT_XML_NAMESPACE(id) || JSID_IS_VOID(id));
|
||||
return UndefinedValue();
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE jsval
|
||||
IdToJsval(jsid id)
|
||||
{
|
||||
return IdToValue(id);
|
||||
}
|
||||
|
||||
template<>
|
||||
struct DefaultHasher<jsid>
|
||||
{
|
||||
typedef jsid Lookup;
|
||||
static HashNumber hash(const Lookup &l) {
|
||||
JS_ASSERT(l == js_CheckForStringIndex(l));
|
||||
return HashNumber(JSID_BITS(l));
|
||||
}
|
||||
static bool match(const jsid &id, const Lookup &l) {
|
||||
JS_ASSERT(l == js_CheckForStringIndex(l));
|
||||
return id == l;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#if JS_BYTES_PER_WORD == 4
|
||||
# define ATOM_HASH(atom) ((JSHashNumber)(atom) >> 2)
|
||||
#elif JS_BYTES_PER_WORD == 8
|
||||
# define ATOM_HASH(atom) (((JSHashNumber)(uintptr_t)(atom) >> 3) ^ \
|
||||
(JSHashNumber)((uintptr_t)(atom) >> 32))
|
||||
#else
|
||||
# error "Unsupported configuration"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Return a printable, lossless char[] representation of a string-type atom.
|
||||
* The lifetime of the result matches the lifetime of bytes.
|
||||
*/
|
||||
extern const char *
|
||||
js_AtomToPrintableString(JSContext *cx, JSAtom *atom, JSAutoByteString *bytes);
|
||||
|
||||
namespace js {
|
||||
|
||||
/* Compute a hash function from chars/length. */
|
||||
inline uint32_t
|
||||
HashChars(const jschar *chars, size_t length)
|
||||
{
|
||||
uint32_t h = 0;
|
||||
for (; length; chars++, length--)
|
||||
h = JS_ROTATE_LEFT32(h, 4) ^ *chars;
|
||||
return h;
|
||||
}
|
||||
|
||||
class AtomStateEntry
|
||||
{
|
||||
uintptr_t bits;
|
||||
|
||||
static const uintptr_t NO_TAG_MASK = uintptr_t(-1) - 1;
|
||||
|
||||
public:
|
||||
AtomStateEntry() : bits(0) {}
|
||||
AtomStateEntry(const AtomStateEntry &other) : bits(other.bits) {}
|
||||
AtomStateEntry(JSAtom *ptr, bool tagged)
|
||||
: bits(uintptr_t(ptr) | uintptr_t(tagged))
|
||||
{
|
||||
JS_ASSERT((uintptr_t(ptr) & 0x1) == 0);
|
||||
}
|
||||
|
||||
bool isTagged() const {
|
||||
return bits & 0x1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Non-branching code sequence. Note that the const_cast is safe because
|
||||
* the hash function doesn't consider the tag to be a portion of the key.
|
||||
*/
|
||||
void setTagged(bool enabled) const {
|
||||
const_cast<AtomStateEntry *>(this)->bits |= uintptr_t(enabled);
|
||||
}
|
||||
|
||||
JSAtom *asPtr() const;
|
||||
};
|
||||
|
||||
struct AtomHasher
|
||||
{
|
||||
struct Lookup
|
||||
{
|
||||
const jschar *chars;
|
||||
size_t length;
|
||||
const JSAtom *atom; /* Optional. */
|
||||
|
||||
Lookup(const jschar *chars, size_t length) : chars(chars), length(length), atom(NULL) {}
|
||||
inline Lookup(const JSAtom *atom);
|
||||
};
|
||||
|
||||
static HashNumber hash(const Lookup &l) { return HashChars(l.chars, l.length); }
|
||||
static inline bool match(const AtomStateEntry &entry, const Lookup &lookup);
|
||||
};
|
||||
|
||||
typedef HashSet<AtomStateEntry, AtomHasher, SystemAllocPolicy> AtomSet;
|
||||
|
||||
/*
|
||||
* On encodings:
|
||||
*
|
||||
* - Some string functions have an optional FlationCoding argument that allow
|
||||
* the caller to force CESU-8 encoding handling.
|
||||
* - Functions that don't take a FlationCoding base their NormalEncoding
|
||||
* behavior on the js_CStringsAreUTF8 value. NormalEncoding is either raw
|
||||
* (simple zero-extension) or UTF-8 depending on js_CStringsAreUTF8.
|
||||
* - Functions that explicitly state their encoding do not use the
|
||||
* js_CStringsAreUTF8 value.
|
||||
*
|
||||
* CESU-8 (Compatibility Encoding Scheme for UTF-16: 8-bit) is a variant of
|
||||
* UTF-8 that allows us to store any wide character string as a narrow
|
||||
* character string. For strings containing mostly ascii, it saves space.
|
||||
* http://www.unicode.org/reports/tr26/
|
||||
*/
|
||||
|
||||
enum FlationCoding
|
||||
{
|
||||
NormalEncoding,
|
||||
CESU8Encoding
|
||||
};
|
||||
|
||||
class PropertyName;
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
struct JSAtomState
|
||||
{
|
||||
js::AtomSet atoms;
|
||||
|
||||
/*
|
||||
* From this point until the end of struct definition the struct must
|
||||
* contain only js::PropertyName fields. We use this to access the storage
|
||||
* occupied by the common atoms in js_FinishCommonAtoms.
|
||||
*
|
||||
* js_common_atom_names defined in jsatom.cpp contains C strings for atoms
|
||||
* in the order of atom fields here. Therefore you must update that array
|
||||
* if you change member order here.
|
||||
*/
|
||||
|
||||
/* The rt->emptyString atom, see jsstr.c's js_InitRuntimeStringState. */
|
||||
js::PropertyName *emptyAtom;
|
||||
|
||||
/*
|
||||
* Literal value and type names.
|
||||
* NB: booleanAtoms must come right before typeAtoms!
|
||||
*/
|
||||
js::PropertyName *booleanAtoms[2];
|
||||
js::PropertyName *typeAtoms[JSTYPE_LIMIT];
|
||||
js::PropertyName *nullAtom;
|
||||
|
||||
/* Standard class constructor or prototype names. */
|
||||
js::PropertyName *classAtoms[JSProto_LIMIT];
|
||||
|
||||
/* Various built-in or commonly-used atoms, pinned on first context. */
|
||||
#define DEFINE_ATOM(id, text) js::PropertyName *id##Atom;
|
||||
#define DEFINE_PROTOTYPE_ATOM(id) js::PropertyName *id##Atom;
|
||||
#define DEFINE_KEYWORD_ATOM(id) js::PropertyName *id##Atom;
|
||||
#include "jsatom.tbl"
|
||||
#undef DEFINE_ATOM
|
||||
#undef DEFINE_PROTOTYPE_ATOM
|
||||
#undef DEFINE_KEYWORD_ATOM
|
||||
|
||||
/* Less frequently used atoms, pinned lazily by JS_ResolveStandardClass. */
|
||||
struct {
|
||||
js::PropertyName *XMLListAtom;
|
||||
js::PropertyName *decodeURIAtom;
|
||||
js::PropertyName *decodeURIComponentAtom;
|
||||
js::PropertyName *defineGetterAtom;
|
||||
js::PropertyName *defineSetterAtom;
|
||||
js::PropertyName *encodeURIAtom;
|
||||
js::PropertyName *encodeURIComponentAtom;
|
||||
js::PropertyName *escapeAtom;
|
||||
js::PropertyName *hasOwnPropertyAtom;
|
||||
js::PropertyName *isFiniteAtom;
|
||||
js::PropertyName *isNaNAtom;
|
||||
js::PropertyName *isPrototypeOfAtom;
|
||||
js::PropertyName *isXMLNameAtom;
|
||||
js::PropertyName *lookupGetterAtom;
|
||||
js::PropertyName *lookupSetterAtom;
|
||||
js::PropertyName *parseFloatAtom;
|
||||
js::PropertyName *parseIntAtom;
|
||||
js::PropertyName *propertyIsEnumerableAtom;
|
||||
js::PropertyName *unescapeAtom;
|
||||
js::PropertyName *unevalAtom;
|
||||
js::PropertyName *unwatchAtom;
|
||||
js::PropertyName *watchAtom;
|
||||
} lazy;
|
||||
|
||||
static const size_t commonAtomsOffset;
|
||||
static const size_t lazyAtomsOffset;
|
||||
|
||||
void clearLazyAtoms() {
|
||||
memset(&lazy, 0, sizeof(lazy));
|
||||
}
|
||||
|
||||
void junkAtoms() {
|
||||
#ifdef DEBUG
|
||||
memset(commonAtomsStart(), JS_FREE_PATTERN, sizeof(*this) - commonAtomsOffset);
|
||||
#endif
|
||||
}
|
||||
|
||||
JSAtom **commonAtomsStart() {
|
||||
return reinterpret_cast<JSAtom **>(&emptyAtom);
|
||||
}
|
||||
|
||||
void checkStaticInvariants();
|
||||
};
|
||||
|
||||
extern bool
|
||||
AtomIsInterned(JSContext *cx, JSAtom *atom);
|
||||
|
||||
#define ATOM(name) cx->runtime->atomState.name##Atom
|
||||
|
||||
#define COMMON_ATOM_INDEX(name) \
|
||||
((offsetof(JSAtomState, name##Atom) - JSAtomState::commonAtomsOffset) \
|
||||
/ sizeof(JSAtom*))
|
||||
#define COMMON_TYPE_ATOM_INDEX(type) \
|
||||
((offsetof(JSAtomState, typeAtoms[type]) - JSAtomState::commonAtomsOffset)\
|
||||
/ sizeof(JSAtom*))
|
||||
|
||||
#define ATOM_OFFSET(name) offsetof(JSAtomState, name##Atom)
|
||||
#define OFFSET_TO_ATOM(rt,off) (*(JSAtom **)((char*)&(rt)->atomState + (off)))
|
||||
#define CLASS_ATOM_OFFSET(name) offsetof(JSAtomState, classAtoms[JSProto_##name])
|
||||
#define CLASS_ATOM(cx,name) ((cx)->runtime->atomState.classAtoms[JSProto_##name])
|
||||
|
||||
extern const char *const js_common_atom_names[];
|
||||
extern const size_t js_common_atom_count;
|
||||
|
||||
/*
|
||||
* Macros to access C strings for JSType and boolean literals.
|
||||
*/
|
||||
#define JS_BOOLEAN_STR(type) (js_common_atom_names[1 + (type)])
|
||||
#define JS_TYPE_STR(type) (js_common_atom_names[1 + 2 + (type)])
|
||||
|
||||
/* Type names. */
|
||||
extern const char js_object_str[];
|
||||
extern const char js_undefined_str[];
|
||||
|
||||
/* Well-known predefined C strings. */
|
||||
#define JS_PROTO(name,code,init) extern const char js_##name##_str[];
|
||||
#include "jsproto.tbl"
|
||||
#undef JS_PROTO
|
||||
|
||||
#define DEFINE_ATOM(id, text) extern const char js_##id##_str[];
|
||||
#define DEFINE_PROTOTYPE_ATOM(id)
|
||||
#define DEFINE_KEYWORD_ATOM(id)
|
||||
#include "jsatom.tbl"
|
||||
#undef DEFINE_ATOM
|
||||
#undef DEFINE_PROTOTYPE_ATOM
|
||||
#undef DEFINE_KEYWORD_ATOM
|
||||
|
||||
#if JS_HAS_GENERATORS
|
||||
extern const char js_close_str[];
|
||||
extern const char js_send_str[];
|
||||
#endif
|
||||
|
||||
/* Constant strings that are not atomized. */
|
||||
extern const char js_getter_str[];
|
||||
extern const char js_setter_str[];
|
||||
|
||||
/*
|
||||
* Initialize atom state. Return true on success, false on failure to allocate
|
||||
* memory. The caller must zero rt->atomState before calling this function and
|
||||
* only call it after js_InitGC successfully returns.
|
||||
*/
|
||||
extern JSBool
|
||||
js_InitAtomState(JSRuntime *rt);
|
||||
|
||||
/*
|
||||
* Free and clear atom state including any interned string atoms. This
|
||||
* function must be called before js_FinishGC.
|
||||
*/
|
||||
extern void
|
||||
js_FinishAtomState(JSRuntime *rt);
|
||||
|
||||
/*
|
||||
* Atom tracing and garbage collection hooks.
|
||||
*/
|
||||
|
||||
namespace js {
|
||||
|
||||
extern void
|
||||
MarkAtomState(JSTracer *trc, bool markAll);
|
||||
|
||||
extern void
|
||||
SweepAtomState(JSRuntime *rt);
|
||||
|
||||
extern bool
|
||||
InitCommonAtoms(JSContext *cx);
|
||||
|
||||
extern void
|
||||
FinishCommonAtoms(JSRuntime *rt);
|
||||
|
||||
/* N.B. must correspond to boolean tagging behavior. */
|
||||
enum InternBehavior
|
||||
{
|
||||
DoNotInternAtom = false,
|
||||
InternAtom = true
|
||||
};
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
extern JSAtom *
|
||||
js_Atomize(JSContext *cx, const char *bytes, size_t length,
|
||||
js::InternBehavior ib = js::DoNotInternAtom,
|
||||
js::FlationCoding fc = js::NormalEncoding);
|
||||
|
||||
extern JSAtom *
|
||||
js_AtomizeChars(JSContext *cx, const jschar *chars, size_t length,
|
||||
js::InternBehavior ib = js::DoNotInternAtom);
|
||||
|
||||
extern JSAtom *
|
||||
js_AtomizeString(JSContext *cx, JSString *str, js::InternBehavior ib = js::DoNotInternAtom);
|
||||
|
||||
/*
|
||||
* Return an existing atom for the given char array or null if the char
|
||||
* sequence is currently not atomized.
|
||||
*/
|
||||
extern JSAtom *
|
||||
js_GetExistingStringAtom(JSContext *cx, const jschar *chars, size_t length);
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
extern JS_FRIEND_API(void)
|
||||
js_DumpAtoms(JSContext *cx, FILE *fp);
|
||||
|
||||
#endif
|
||||
|
||||
inline bool
|
||||
js_ValueToAtom(JSContext *cx, const js::Value &v, JSAtom **atomp);
|
||||
|
||||
inline bool
|
||||
js_ValueToStringId(JSContext *cx, const js::Value &v, jsid *idp);
|
||||
|
||||
inline bool
|
||||
js_InternNonIntElementId(JSContext *cx, JSObject *obj, const js::Value &idval,
|
||||
jsid *idp);
|
||||
inline bool
|
||||
js_InternNonIntElementId(JSContext *cx, JSObject *obj, const js::Value &idval,
|
||||
jsid *idp, js::Value *vp);
|
||||
|
||||
namespace js {
|
||||
|
||||
/*
|
||||
* For all unmapped atoms recorded in al, add a mapping from the atom's index
|
||||
* to its address. map->length must already be set to the number of atoms in
|
||||
* the list and map->vector must point to pre-allocated memory.
|
||||
*/
|
||||
extern void
|
||||
InitAtomMap(JSContext *cx, AtomIndexMap *indices, HeapPtrAtom *atoms);
|
||||
|
||||
template<XDRMode mode>
|
||||
bool
|
||||
XDRAtom(XDRState<mode> *xdr, JSAtom **atomp);
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
#endif /* jsatom_h___ */
|
|
@ -0,0 +1,125 @@
|
|||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* vim: set sw=4 ts=8 et tw=80 ft=c: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/*
|
||||
* Declare pre-interned atoms for easy use by SpiderMonkey's C++ code.
|
||||
* These entries define two things, where <id> is the macros' first
|
||||
* argument:
|
||||
*
|
||||
* - js::PropertyName *<id>Atom: a member of JSAtomState pointing to the
|
||||
* atom itself. Usually accessed as cx->runtime->atomState.<id>Atom.
|
||||
*
|
||||
* - const char js_<id>_str[]: a global within SpiderMonkey, holding the
|
||||
* atom's name. Some macros skip this, because it's already defined
|
||||
* elsewhere.
|
||||
*
|
||||
* DEFINE_ATOM(id, name)
|
||||
* Define an atom whose JavaScript string's value is |name|.
|
||||
*
|
||||
* DEFINE_PROTOTYPE_ATOM(id)
|
||||
* Define an atom whose name is the same as one of those defined in
|
||||
* jsproto.tbl. The code that processes that has already declared and
|
||||
* defined the js_<id>_str global, so this defines only the JSAtomState
|
||||
* member.
|
||||
*
|
||||
* DEFINE_KEYWORD_ATOM(id)
|
||||
* Define an atom whose name is the same as one of those defined in
|
||||
* jskeyword.tbl. The code that processes that has already declared and
|
||||
* defined the js_<id>_str global, so this defines only the JSAtomState
|
||||
* member.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
DEFINE_ATOM(anonymous, "anonymous")
|
||||
DEFINE_ATOM(apply, "apply")
|
||||
DEFINE_ATOM(arguments, "arguments")
|
||||
DEFINE_ATOM(arity, "arity")
|
||||
DEFINE_ATOM(BYTES_PER_ELEMENT, "BYTES_PER_ELEMENT")
|
||||
DEFINE_ATOM(call, "call")
|
||||
DEFINE_ATOM(callee, "callee")
|
||||
DEFINE_ATOM(caller, "caller")
|
||||
DEFINE_ATOM(classPrototype, "prototype")
|
||||
DEFINE_ATOM(constructor, "constructor")
|
||||
DEFINE_ATOM(each, "each")
|
||||
DEFINE_ATOM(eval, "eval")
|
||||
DEFINE_ATOM(fileName, "fileName")
|
||||
DEFINE_ATOM(get, "get")
|
||||
DEFINE_ATOM(global, "global")
|
||||
DEFINE_ATOM(ignoreCase, "ignoreCase")
|
||||
DEFINE_ATOM(index, "index")
|
||||
DEFINE_ATOM(input, "input")
|
||||
DEFINE_ATOM(toISOString, "toISOString")
|
||||
DEFINE_ATOM(iterator, "__iterator__")
|
||||
DEFINE_ATOM(join, "join")
|
||||
DEFINE_ATOM(lastIndex, "lastIndex")
|
||||
DEFINE_ATOM(length, "length")
|
||||
DEFINE_ATOM(lineNumber, "lineNumber")
|
||||
DEFINE_ATOM(message, "message")
|
||||
DEFINE_ATOM(multiline, "multiline")
|
||||
DEFINE_ATOM(name, "name")
|
||||
DEFINE_ATOM(next, "next")
|
||||
DEFINE_ATOM(noSuchMethod, "__noSuchMethod__")
|
||||
DEFINE_ATOM(objectNull, "[object Null]")
|
||||
DEFINE_ATOM(objectUndefined, "[object Undefined]")
|
||||
DEFINE_ATOM(of, "of")
|
||||
DEFINE_ATOM(proto, "__proto__")
|
||||
DEFINE_ATOM(set, "set")
|
||||
DEFINE_ATOM(source, "source")
|
||||
DEFINE_ATOM(stack, "stack")
|
||||
DEFINE_ATOM(sticky, "sticky")
|
||||
DEFINE_ATOM(toGMTString, "toGMTString")
|
||||
DEFINE_ATOM(toLocaleString, "toLocaleString")
|
||||
DEFINE_ATOM(toSource, "toSource")
|
||||
DEFINE_ATOM(toString, "toString")
|
||||
DEFINE_ATOM(toUTCString, "toUTCString")
|
||||
DEFINE_ATOM(valueOf, "valueOf")
|
||||
DEFINE_ATOM(toJSON, "toJSON")
|
||||
DEFINE_ATOM(void0, "(void 0)")
|
||||
DEFINE_ATOM(enumerable, "enumerable")
|
||||
DEFINE_ATOM(configurable, "configurable")
|
||||
DEFINE_ATOM(writable, "writable")
|
||||
DEFINE_ATOM(value, "value")
|
||||
DEFINE_ATOM(test, "test")
|
||||
DEFINE_ATOM(useStrict, "use strict")
|
||||
DEFINE_ATOM(loc, "loc")
|
||||
DEFINE_ATOM(line, "line")
|
||||
DEFINE_ATOM(Infinity, "Infinity")
|
||||
DEFINE_ATOM(NaN, "NaN")
|
||||
DEFINE_ATOM(builder, "builder")
|
||||
|
||||
#if JS_HAS_XML_SUPPORT
|
||||
DEFINE_ATOM(etago, "</")
|
||||
DEFINE_ATOM(namespace, "namespace")
|
||||
DEFINE_ATOM(ptagc, "/>")
|
||||
DEFINE_ATOM(qualifier, "::")
|
||||
DEFINE_ATOM(space, " ")
|
||||
DEFINE_ATOM(stago, "<")
|
||||
DEFINE_ATOM(star, "*")
|
||||
DEFINE_ATOM(starQualifier, "*::")
|
||||
DEFINE_ATOM(tagc, ">")
|
||||
DEFINE_ATOM(xml, "xml")
|
||||
DEFINE_ATOM(functionNamespaceURI, "@mozilla.org/js/function")
|
||||
#endif
|
||||
|
||||
DEFINE_PROTOTYPE_ATOM(Proxy)
|
||||
DEFINE_ATOM(getOwnPropertyDescriptor, "getOwnPropertyDescriptor")
|
||||
DEFINE_ATOM(getPropertyDescriptor, "getPropertyDescriptor")
|
||||
DEFINE_ATOM(defineProperty, "defineProperty")
|
||||
DEFINE_KEYWORD_ATOM(delete)
|
||||
DEFINE_ATOM(getOwnPropertyNames, "getOwnPropertyNames")
|
||||
DEFINE_ATOM(enumerate, "enumerate")
|
||||
DEFINE_ATOM(fix, "fix")
|
||||
DEFINE_ATOM(has, "has")
|
||||
DEFINE_ATOM(hasOwn, "hasOwn")
|
||||
DEFINE_ATOM(keys, "keys")
|
||||
DEFINE_ATOM(iterate, "iterate")
|
||||
DEFINE_PROTOTYPE_ATOM(WeakMap)
|
||||
DEFINE_ATOM(byteLength, "byteLength")
|
||||
DEFINE_KEYWORD_ATOM(return)
|
||||
DEFINE_KEYWORD_ATOM(throw)
|
||||
DEFINE_ATOM(url, "url")
|
||||
DEFINE_ATOM(innermost, "innermost")
|
|
@ -0,0 +1,119 @@
|
|||
/* -*- Mode: C++; tab-width: 8; 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 SpiderMonkey code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Gregor Wagner <anygregor@gmail.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of 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 jscell_h___
|
||||
#define jscell_h___
|
||||
|
||||
#include "jspubtd.h"
|
||||
|
||||
struct JSCompartment;
|
||||
|
||||
namespace js {
|
||||
namespace gc {
|
||||
|
||||
struct ArenaHeader;
|
||||
struct Chunk;
|
||||
|
||||
/* The GC allocation kinds. */
|
||||
enum AllocKind {
|
||||
FINALIZE_OBJECT0,
|
||||
FINALIZE_OBJECT0_BACKGROUND,
|
||||
FINALIZE_OBJECT2,
|
||||
FINALIZE_OBJECT2_BACKGROUND,
|
||||
FINALIZE_OBJECT4,
|
||||
FINALIZE_OBJECT4_BACKGROUND,
|
||||
FINALIZE_OBJECT8,
|
||||
FINALIZE_OBJECT8_BACKGROUND,
|
||||
FINALIZE_OBJECT12,
|
||||
FINALIZE_OBJECT12_BACKGROUND,
|
||||
FINALIZE_OBJECT16,
|
||||
FINALIZE_OBJECT16_BACKGROUND,
|
||||
FINALIZE_OBJECT_LAST = FINALIZE_OBJECT16_BACKGROUND,
|
||||
FINALIZE_SCRIPT,
|
||||
FINALIZE_SHAPE,
|
||||
FINALIZE_BASE_SHAPE,
|
||||
FINALIZE_TYPE_OBJECT,
|
||||
#if JS_HAS_XML_SUPPORT
|
||||
FINALIZE_XML,
|
||||
#endif
|
||||
FINALIZE_SHORT_STRING,
|
||||
FINALIZE_STRING,
|
||||
FINALIZE_EXTERNAL_STRING,
|
||||
FINALIZE_LAST = FINALIZE_EXTERNAL_STRING
|
||||
};
|
||||
|
||||
static const unsigned FINALIZE_LIMIT = FINALIZE_LAST + 1;
|
||||
static const unsigned FINALIZE_OBJECT_LIMIT = FINALIZE_OBJECT_LAST + 1;
|
||||
|
||||
/*
|
||||
* Live objects are marked black. How many other additional colors are available
|
||||
* depends on the size of the GCThing. Objects marked gray are eligible for
|
||||
* cycle collection.
|
||||
*/
|
||||
static const uint32_t BLACK = 0;
|
||||
static const uint32_t GRAY = 1;
|
||||
|
||||
/*
|
||||
* A GC cell is the base class for all GC things.
|
||||
*/
|
||||
struct Cell {
|
||||
static const size_t CellShift = 3;
|
||||
static const size_t CellSize = size_t(1) << CellShift;
|
||||
static const size_t CellMask = CellSize - 1;
|
||||
|
||||
inline uintptr_t address() const;
|
||||
inline ArenaHeader *arenaHeader() const;
|
||||
inline Chunk *chunk() const;
|
||||
inline AllocKind getAllocKind() const;
|
||||
|
||||
JS_ALWAYS_INLINE bool isMarked(uint32_t color = BLACK) const;
|
||||
JS_ALWAYS_INLINE bool markIfUnmarked(uint32_t color = BLACK) const;
|
||||
JS_ALWAYS_INLINE void unmark(uint32_t color) const;
|
||||
|
||||
inline JSCompartment *compartment() const;
|
||||
|
||||
#ifdef DEBUG
|
||||
inline bool isAligned() const;
|
||||
#endif
|
||||
};
|
||||
|
||||
} /* namespace gc */
|
||||
} /* namespace js */
|
||||
|
||||
#endif /* jscell_h___ */
|
|
@ -0,0 +1,429 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=4 sw=4 et tw=79 ft=cpp:
|
||||
*
|
||||
* ***** 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 SpiderMonkey JavaScript engine.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2009
|
||||
* 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 jsclass_h__
|
||||
#define jsclass_h__
|
||||
/*
|
||||
* A JSClass acts as a vtable for JS objects that allows JSAPI clients to
|
||||
* control various aspects of the behavior of an object like property lookup.
|
||||
* js::Class is an engine-private extension that allows more control over
|
||||
* object behavior and, e.g., allows custom slow layout.
|
||||
*/
|
||||
#include "jsapi.h"
|
||||
#include "jsprvtd.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
namespace js {
|
||||
|
||||
class PropertyName;
|
||||
class SpecialId;
|
||||
|
||||
static JS_ALWAYS_INLINE jsid
|
||||
SPECIALID_TO_JSID(const SpecialId &sid);
|
||||
|
||||
/*
|
||||
* We partition the ways to refer to a property into three: by an index
|
||||
* (uint32_t); by a string whose characters do not represent an index
|
||||
* (PropertyName, see vm/String.h); and by various special values.
|
||||
*
|
||||
* Special values are encoded using SpecialId, which is layout-compatible but
|
||||
* non-interconvertible with jsid. A SpecialId may be: an object (used by E4X
|
||||
* and perhaps eventually by Harmony-proposed private names); JSID_VOID, which
|
||||
* does not occur in JS scripts but may be used to indicate the absence of a
|
||||
* valid identifier; or JS_DEFAULT_XML_NAMESPACE_ID, if E4X is enabled.
|
||||
*/
|
||||
|
||||
class SpecialId {
|
||||
uintptr_t bits;
|
||||
|
||||
/* Needs access to raw bits. */
|
||||
friend JS_ALWAYS_INLINE jsid SPECIALID_TO_JSID(const SpecialId &sid);
|
||||
|
||||
static const uintptr_t TYPE_VOID = JSID_TYPE_VOID;
|
||||
static const uintptr_t TYPE_OBJECT = JSID_TYPE_OBJECT;
|
||||
static const uintptr_t TYPE_DEFAULT_XML_NAMESPACE = JSID_TYPE_DEFAULT_XML_NAMESPACE;
|
||||
static const uintptr_t TYPE_MASK = JSID_TYPE_MASK;
|
||||
|
||||
SpecialId(uintptr_t bits) : bits(bits) { }
|
||||
|
||||
public:
|
||||
SpecialId() : bits(TYPE_VOID) { }
|
||||
|
||||
/* Object-valued */
|
||||
|
||||
SpecialId(JSObject &obj)
|
||||
: bits(uintptr_t(&obj) | TYPE_OBJECT)
|
||||
{
|
||||
JS_ASSERT(&obj != NULL);
|
||||
JS_ASSERT((uintptr_t(&obj) & TYPE_MASK) == 0);
|
||||
}
|
||||
|
||||
bool isObject() const {
|
||||
return (bits & TYPE_MASK) == TYPE_OBJECT && bits != TYPE_OBJECT;
|
||||
}
|
||||
|
||||
JSObject *toObject() const {
|
||||
JS_ASSERT(isObject());
|
||||
return reinterpret_cast<JSObject *>(bits & ~TYPE_MASK);
|
||||
}
|
||||
|
||||
/* Empty */
|
||||
|
||||
static SpecialId empty() {
|
||||
SpecialId sid(TYPE_OBJECT);
|
||||
JS_ASSERT(sid.isEmpty());
|
||||
return sid;
|
||||
}
|
||||
|
||||
bool isEmpty() const {
|
||||
return bits == TYPE_OBJECT;
|
||||
}
|
||||
|
||||
/* Void */
|
||||
|
||||
static SpecialId voidId() {
|
||||
SpecialId sid(TYPE_VOID);
|
||||
JS_ASSERT(sid.isVoid());
|
||||
return sid;
|
||||
}
|
||||
|
||||
bool isVoid() const {
|
||||
return bits == TYPE_VOID;
|
||||
}
|
||||
|
||||
/* Default XML namespace */
|
||||
|
||||
static SpecialId defaultXMLNamespace() {
|
||||
SpecialId sid(TYPE_DEFAULT_XML_NAMESPACE);
|
||||
JS_ASSERT(sid.isDefaultXMLNamespace());
|
||||
return sid;
|
||||
}
|
||||
|
||||
bool isDefaultXMLNamespace() const {
|
||||
return bits == TYPE_DEFAULT_XML_NAMESPACE;
|
||||
}
|
||||
};
|
||||
|
||||
static JS_ALWAYS_INLINE jsid
|
||||
SPECIALID_TO_JSID(const SpecialId &sid)
|
||||
{
|
||||
jsid id;
|
||||
JSID_BITS(id) = sid.bits;
|
||||
JS_ASSERT_IF(sid.isObject(), JSID_IS_OBJECT(id) && JSID_TO_OBJECT(id) == sid.toObject());
|
||||
JS_ASSERT_IF(sid.isVoid(), JSID_IS_VOID(id));
|
||||
JS_ASSERT_IF(sid.isEmpty(), JSID_IS_EMPTY(id));
|
||||
JS_ASSERT_IF(sid.isDefaultXMLNamespace(), JSID_IS_DEFAULT_XML_NAMESPACE(id));
|
||||
return id;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE bool
|
||||
JSID_IS_SPECIAL(jsid id)
|
||||
{
|
||||
return JSID_IS_OBJECT(id) || JSID_IS_EMPTY(id) || JSID_IS_VOID(id) ||
|
||||
JSID_IS_DEFAULT_XML_NAMESPACE(id);
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE SpecialId
|
||||
JSID_TO_SPECIALID(jsid id)
|
||||
{
|
||||
JS_ASSERT(JSID_IS_SPECIAL(id));
|
||||
if (JSID_IS_OBJECT(id))
|
||||
return SpecialId(*JSID_TO_OBJECT(id));
|
||||
if (JSID_IS_EMPTY(id))
|
||||
return SpecialId::empty();
|
||||
if (JSID_IS_VOID(id))
|
||||
return SpecialId::voidId();
|
||||
JS_ASSERT(JSID_IS_DEFAULT_XML_NAMESPACE(id));
|
||||
return SpecialId::defaultXMLNamespace();
|
||||
}
|
||||
|
||||
/* js::Class operation signatures. */
|
||||
|
||||
typedef JSBool
|
||||
(* LookupGenericOp)(JSContext *cx, JSObject *obj, jsid id, JSObject **objp,
|
||||
JSProperty **propp);
|
||||
typedef JSBool
|
||||
(* LookupPropOp)(JSContext *cx, JSObject *obj, PropertyName *name, JSObject **objp,
|
||||
JSProperty **propp);
|
||||
typedef JSBool
|
||||
(* LookupElementOp)(JSContext *cx, JSObject *obj, uint32_t index, JSObject **objp,
|
||||
JSProperty **propp);
|
||||
typedef JSBool
|
||||
(* LookupSpecialOp)(JSContext *cx, JSObject *obj, SpecialId sid, JSObject **objp,
|
||||
JSProperty **propp);
|
||||
typedef JSBool
|
||||
(* DefineGenericOp)(JSContext *cx, JSObject *obj, jsid id, const Value *value,
|
||||
PropertyOp getter, StrictPropertyOp setter, unsigned attrs);
|
||||
typedef JSBool
|
||||
(* DefinePropOp)(JSContext *cx, JSObject *obj, PropertyName *name, const Value *value,
|
||||
PropertyOp getter, StrictPropertyOp setter, unsigned attrs);
|
||||
typedef JSBool
|
||||
(* DefineElementOp)(JSContext *cx, JSObject *obj, uint32_t index, const Value *value,
|
||||
PropertyOp getter, StrictPropertyOp setter, unsigned attrs);
|
||||
typedef JSBool
|
||||
(* DefineSpecialOp)(JSContext *cx, JSObject *obj, SpecialId sid, const Value *value,
|
||||
PropertyOp getter, StrictPropertyOp setter, unsigned attrs);
|
||||
typedef JSBool
|
||||
(* GenericIdOp)(JSContext *cx, JSObject *obj, JSObject *receiver, jsid id, Value *vp);
|
||||
typedef JSBool
|
||||
(* PropertyIdOp)(JSContext *cx, JSObject *obj, JSObject *receiver, PropertyName *name, Value *vp);
|
||||
typedef JSBool
|
||||
(* ElementIdOp)(JSContext *cx, JSObject *obj, JSObject *receiver, uint32_t index, Value *vp);
|
||||
typedef JSBool
|
||||
(* ElementIfPresentOp)(JSContext *cx, JSObject *obj, JSObject *receiver, uint32_t index, Value *vp, bool* present);
|
||||
typedef JSBool
|
||||
(* SpecialIdOp)(JSContext *cx, JSObject *obj, JSObject *receiver, SpecialId sid, Value *vp);
|
||||
typedef JSBool
|
||||
(* StrictGenericIdOp)(JSContext *cx, JSObject *obj, jsid id, Value *vp, JSBool strict);
|
||||
typedef JSBool
|
||||
(* StrictPropertyIdOp)(JSContext *cx, JSObject *obj, PropertyName *name, Value *vp, JSBool strict);
|
||||
typedef JSBool
|
||||
(* StrictElementIdOp)(JSContext *cx, JSObject *obj, uint32_t index, Value *vp, JSBool strict);
|
||||
typedef JSBool
|
||||
(* StrictSpecialIdOp)(JSContext *cx, JSObject *obj, SpecialId sid, Value *vp, JSBool strict);
|
||||
typedef JSBool
|
||||
(* GenericAttributesOp)(JSContext *cx, JSObject *obj, jsid id, unsigned *attrsp);
|
||||
typedef JSBool
|
||||
(* PropertyAttributesOp)(JSContext *cx, JSObject *obj, PropertyName *name, unsigned *attrsp);
|
||||
typedef JSBool
|
||||
(* ElementAttributesOp)(JSContext *cx, JSObject *obj, uint32_t index, unsigned *attrsp);
|
||||
typedef JSBool
|
||||
(* SpecialAttributesOp)(JSContext *cx, JSObject *obj, SpecialId sid, unsigned *attrsp);
|
||||
typedef JSBool
|
||||
(* DeletePropertyOp)(JSContext *cx, JSObject *obj, PropertyName *name, Value *vp, JSBool strict);
|
||||
typedef JSBool
|
||||
(* DeleteElementOp)(JSContext *cx, JSObject *obj, uint32_t index, Value *vp, JSBool strict);
|
||||
typedef JSBool
|
||||
(* DeleteSpecialOp)(JSContext *cx, JSObject *obj, SpecialId sid, Value *vp, JSBool strict);
|
||||
typedef JSType
|
||||
(* TypeOfOp)(JSContext *cx, JSObject *obj);
|
||||
|
||||
/*
|
||||
* Prepare to make |obj| non-extensible; in particular, fully resolve its properties.
|
||||
* On error, return false.
|
||||
* If |obj| is now ready to become non-extensible, set |*fixed| to true and return true.
|
||||
* If |obj| refuses to become non-extensible, set |*fixed| to false and return true; the
|
||||
* caller will throw an appropriate error.
|
||||
*/
|
||||
typedef JSBool
|
||||
(* FixOp)(JSContext *cx, JSObject *obj, bool *fixed, AutoIdVector *props);
|
||||
|
||||
typedef JSObject *
|
||||
(* ObjectOp)(JSContext *cx, JSObject *obj);
|
||||
typedef void
|
||||
(* FinalizeOp)(FreeOp *fop, JSObject *obj);
|
||||
typedef void
|
||||
(* ClearOp)(JSContext *cx, JSObject *obj);
|
||||
|
||||
#define JS_CLASS_MEMBERS \
|
||||
const char *name; \
|
||||
uint32_t flags; \
|
||||
\
|
||||
/* Mandatory non-null function pointer members. */ \
|
||||
JSPropertyOp addProperty; \
|
||||
JSPropertyOp delProperty; \
|
||||
JSPropertyOp getProperty; \
|
||||
JSStrictPropertyOp setProperty; \
|
||||
JSEnumerateOp enumerate; \
|
||||
JSResolveOp resolve; \
|
||||
JSConvertOp convert; \
|
||||
FinalizeOp finalize; \
|
||||
\
|
||||
/* Optionally non-null members start here. */ \
|
||||
JSCheckAccessOp checkAccess; \
|
||||
JSNative call; \
|
||||
JSNative construct; \
|
||||
JSHasInstanceOp hasInstance; \
|
||||
JSTraceOp trace
|
||||
|
||||
/*
|
||||
* The helper struct to measure the size of JS_CLASS_MEMBERS to know how much
|
||||
* we have to padd js::Class to match the size of JSClass;
|
||||
*/
|
||||
struct ClassSizeMeasurement
|
||||
{
|
||||
JS_CLASS_MEMBERS;
|
||||
};
|
||||
|
||||
struct ClassExtension
|
||||
{
|
||||
JSEqualityOp equality;
|
||||
JSObjectOp outerObject;
|
||||
JSObjectOp innerObject;
|
||||
JSIteratorOp iteratorObject;
|
||||
void *unused;
|
||||
|
||||
/*
|
||||
* isWrappedNative is true only if the class is an XPCWrappedNative.
|
||||
* WeakMaps use this to override the wrapper disposal optimization.
|
||||
*/
|
||||
bool isWrappedNative;
|
||||
};
|
||||
|
||||
#define JS_NULL_CLASS_EXT {NULL,NULL,NULL,NULL,NULL,false}
|
||||
|
||||
struct ObjectOps
|
||||
{
|
||||
LookupGenericOp lookupGeneric;
|
||||
LookupPropOp lookupProperty;
|
||||
LookupElementOp lookupElement;
|
||||
LookupSpecialOp lookupSpecial;
|
||||
DefineGenericOp defineGeneric;
|
||||
DefinePropOp defineProperty;
|
||||
DefineElementOp defineElement;
|
||||
DefineSpecialOp defineSpecial;
|
||||
GenericIdOp getGeneric;
|
||||
PropertyIdOp getProperty;
|
||||
ElementIdOp getElement;
|
||||
ElementIfPresentOp getElementIfPresent; /* can be null */
|
||||
SpecialIdOp getSpecial;
|
||||
StrictGenericIdOp setGeneric;
|
||||
StrictPropertyIdOp setProperty;
|
||||
StrictElementIdOp setElement;
|
||||
StrictSpecialIdOp setSpecial;
|
||||
GenericAttributesOp getGenericAttributes;
|
||||
PropertyAttributesOp getPropertyAttributes;
|
||||
ElementAttributesOp getElementAttributes;
|
||||
SpecialAttributesOp getSpecialAttributes;
|
||||
GenericAttributesOp setGenericAttributes;
|
||||
PropertyAttributesOp setPropertyAttributes;
|
||||
ElementAttributesOp setElementAttributes;
|
||||
SpecialAttributesOp setSpecialAttributes;
|
||||
DeletePropertyOp deleteProperty;
|
||||
DeleteElementOp deleteElement;
|
||||
DeleteSpecialOp deleteSpecial;
|
||||
|
||||
JSNewEnumerateOp enumerate;
|
||||
TypeOfOp typeOf;
|
||||
FixOp fix;
|
||||
ObjectOp thisObject;
|
||||
ClearOp clear;
|
||||
};
|
||||
|
||||
#define JS_NULL_OBJECT_OPS \
|
||||
{NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, \
|
||||
NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL, \
|
||||
NULL,NULL,NULL,NULL,NULL,NULL}
|
||||
|
||||
struct Class
|
||||
{
|
||||
JS_CLASS_MEMBERS;
|
||||
ClassExtension ext;
|
||||
ObjectOps ops;
|
||||
uint8_t pad[sizeof(JSClass) - sizeof(ClassSizeMeasurement) -
|
||||
sizeof(ClassExtension) - sizeof(ObjectOps)];
|
||||
|
||||
/* Class is not native and its map is not a scope. */
|
||||
static const uint32_t NON_NATIVE = JSCLASS_INTERNAL_FLAG2;
|
||||
|
||||
bool isNative() const {
|
||||
return !(flags & NON_NATIVE);
|
||||
}
|
||||
|
||||
bool hasPrivate() const {
|
||||
return !!(flags & JSCLASS_HAS_PRIVATE);
|
||||
}
|
||||
};
|
||||
|
||||
JS_STATIC_ASSERT(offsetof(JSClass, name) == offsetof(Class, name));
|
||||
JS_STATIC_ASSERT(offsetof(JSClass, flags) == offsetof(Class, flags));
|
||||
JS_STATIC_ASSERT(offsetof(JSClass, addProperty) == offsetof(Class, addProperty));
|
||||
JS_STATIC_ASSERT(offsetof(JSClass, delProperty) == offsetof(Class, delProperty));
|
||||
JS_STATIC_ASSERT(offsetof(JSClass, getProperty) == offsetof(Class, getProperty));
|
||||
JS_STATIC_ASSERT(offsetof(JSClass, setProperty) == offsetof(Class, setProperty));
|
||||
JS_STATIC_ASSERT(offsetof(JSClass, enumerate) == offsetof(Class, enumerate));
|
||||
JS_STATIC_ASSERT(offsetof(JSClass, resolve) == offsetof(Class, resolve));
|
||||
JS_STATIC_ASSERT(offsetof(JSClass, convert) == offsetof(Class, convert));
|
||||
JS_STATIC_ASSERT(offsetof(JSClass, finalize) == offsetof(Class, finalize));
|
||||
JS_STATIC_ASSERT(offsetof(JSClass, checkAccess) == offsetof(Class, checkAccess));
|
||||
JS_STATIC_ASSERT(offsetof(JSClass, call) == offsetof(Class, call));
|
||||
JS_STATIC_ASSERT(offsetof(JSClass, construct) == offsetof(Class, construct));
|
||||
JS_STATIC_ASSERT(offsetof(JSClass, hasInstance) == offsetof(Class, hasInstance));
|
||||
JS_STATIC_ASSERT(offsetof(JSClass, trace) == offsetof(Class, trace));
|
||||
JS_STATIC_ASSERT(sizeof(JSClass) == sizeof(Class));
|
||||
|
||||
static JS_ALWAYS_INLINE JSClass *
|
||||
Jsvalify(Class *c)
|
||||
{
|
||||
return (JSClass *)c;
|
||||
}
|
||||
static JS_ALWAYS_INLINE const JSClass *
|
||||
Jsvalify(const Class *c)
|
||||
{
|
||||
return (const JSClass *)c;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE Class *
|
||||
Valueify(JSClass *c)
|
||||
{
|
||||
return (Class *)c;
|
||||
}
|
||||
static JS_ALWAYS_INLINE const Class *
|
||||
Valueify(const JSClass *c)
|
||||
{
|
||||
return (const Class *)c;
|
||||
}
|
||||
|
||||
/*
|
||||
* Enumeration describing possible values of the [[Class]] internal property
|
||||
* value of objects.
|
||||
*/
|
||||
enum ESClassValue {
|
||||
ESClass_Array, ESClass_Number, ESClass_String, ESClass_Boolean, ESClass_RegExp
|
||||
};
|
||||
|
||||
/*
|
||||
* Return whether the given object has the given [[Class]] internal property
|
||||
* value. Beware, this query says nothing about the js::Class of the JSObject
|
||||
* so the caller must not assume anything about obj's representation (e.g., obj
|
||||
* may be a proxy).
|
||||
*/
|
||||
inline bool
|
||||
ObjectClassIs(JSObject &obj, ESClassValue classValue, JSContext *cx);
|
||||
|
||||
/* Just a helper that checks v.isObject before calling ObjectClassIs. */
|
||||
inline bool
|
||||
IsObjectWithClass(const Value &v, ESClassValue classValue, JSContext *cx);
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* jsclass_h__ */
|
|
@ -0,0 +1,139 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** 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 Mozilla Communicator client code, released
|
||||
* March 31, 1998.
|
||||
*
|
||||
* 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 of 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 jsclist_h___
|
||||
#define jsclist_h___
|
||||
|
||||
#include "jstypes.h"
|
||||
|
||||
/*
|
||||
** Circular linked list
|
||||
*/
|
||||
typedef struct JSCListStr {
|
||||
struct JSCListStr *next;
|
||||
struct JSCListStr *prev;
|
||||
} JSCList;
|
||||
|
||||
/*
|
||||
** Insert element "_e" into the list, before "_l".
|
||||
*/
|
||||
#define JS_INSERT_BEFORE(_e,_l) \
|
||||
JS_BEGIN_MACRO \
|
||||
(_e)->next = (_l); \
|
||||
(_e)->prev = (_l)->prev; \
|
||||
(_l)->prev->next = (_e); \
|
||||
(_l)->prev = (_e); \
|
||||
JS_END_MACRO
|
||||
|
||||
/*
|
||||
** Insert element "_e" into the list, after "_l".
|
||||
*/
|
||||
#define JS_INSERT_AFTER(_e,_l) \
|
||||
JS_BEGIN_MACRO \
|
||||
(_e)->next = (_l)->next; \
|
||||
(_e)->prev = (_l); \
|
||||
(_l)->next->prev = (_e); \
|
||||
(_l)->next = (_e); \
|
||||
JS_END_MACRO
|
||||
|
||||
/*
|
||||
** Return the element following element "_e"
|
||||
*/
|
||||
#define JS_NEXT_LINK(_e) \
|
||||
((_e)->next)
|
||||
/*
|
||||
** Return the element preceding element "_e"
|
||||
*/
|
||||
#define JS_PREV_LINK(_e) \
|
||||
((_e)->prev)
|
||||
|
||||
/*
|
||||
** Append an element "_e" to the end of the list "_l"
|
||||
*/
|
||||
#define JS_APPEND_LINK(_e,_l) JS_INSERT_BEFORE(_e,_l)
|
||||
|
||||
/*
|
||||
** Insert an element "_e" at the head of the list "_l"
|
||||
*/
|
||||
#define JS_INSERT_LINK(_e,_l) JS_INSERT_AFTER(_e,_l)
|
||||
|
||||
/* Return the head/tail of the list */
|
||||
#define JS_LIST_HEAD(_l) (_l)->next
|
||||
#define JS_LIST_TAIL(_l) (_l)->prev
|
||||
|
||||
/*
|
||||
** Remove the element "_e" from it's circular list.
|
||||
*/
|
||||
#define JS_REMOVE_LINK(_e) \
|
||||
JS_BEGIN_MACRO \
|
||||
(_e)->prev->next = (_e)->next; \
|
||||
(_e)->next->prev = (_e)->prev; \
|
||||
JS_END_MACRO
|
||||
|
||||
/*
|
||||
** Remove the element "_e" from it's circular list. Also initializes the
|
||||
** linkage.
|
||||
*/
|
||||
#define JS_REMOVE_AND_INIT_LINK(_e) \
|
||||
JS_BEGIN_MACRO \
|
||||
(_e)->prev->next = (_e)->next; \
|
||||
(_e)->next->prev = (_e)->prev; \
|
||||
(_e)->next = (_e); \
|
||||
(_e)->prev = (_e); \
|
||||
JS_END_MACRO
|
||||
|
||||
/*
|
||||
** Return non-zero if the given circular list "_l" is empty, zero if the
|
||||
** circular list is not empty
|
||||
*/
|
||||
#define JS_CLIST_IS_EMPTY(_l) \
|
||||
((_l)->next == (_l))
|
||||
|
||||
/*
|
||||
** Initialize a circular list
|
||||
*/
|
||||
#define JS_INIT_CLIST(_l) \
|
||||
JS_BEGIN_MACRO \
|
||||
(_l)->next = (_l); \
|
||||
(_l)->prev = (_l); \
|
||||
JS_END_MACRO
|
||||
|
||||
#define JS_INIT_STATIC_CLIST(_l) \
|
||||
{(_l), (_l)}
|
||||
|
||||
#endif /* jsclist_h___ */
|
|
@ -42,50 +42,113 @@
|
|||
|
||||
#define JS_HAVE_LONG_LONG
|
||||
|
||||
#if defined(XP_WIN) || defined(XP_OS2) || defined(WINCE)
|
||||
|
||||
#if defined(_WIN64)
|
||||
|
||||
#if defined(_M_X64) || defined(_M_AMD64) || defined(_AMD64_)
|
||||
#define IS_LITTLE_ENDIAN 1
|
||||
#undef IS_BIG_ENDIAN
|
||||
#define JS_BYTES_PER_DOUBLE 8L
|
||||
#define JS_BYTES_PER_WORD 8L
|
||||
#define JS_BITS_PER_WORD_LOG2 6
|
||||
#define JS_ALIGN_OF_POINTER 8L
|
||||
#else /* !(defined(_M_X64) || defined(_M_AMD64) || defined(_AMD64_)) */
|
||||
#error "CPU type is unknown"
|
||||
#endif /* !(defined(_M_X64) || defined(_M_AMD64) || defined(_AMD64_)) */
|
||||
# if defined(_M_X64) || defined(_M_AMD64) || defined(_AMD64_)
|
||||
# define IS_LITTLE_ENDIAN 1
|
||||
# undef IS_BIG_ENDIAN
|
||||
# define JS_BYTES_PER_DOUBLE 8
|
||||
# define JS_BYTES_PER_WORD 8
|
||||
# define JS_BITS_PER_WORD_LOG2 6
|
||||
# define JS_ALIGN_OF_POINTER 8
|
||||
# else /* !(defined(_M_X64) || defined(_M_AMD64) || defined(_AMD64_)) */
|
||||
# error "CPU type is unknown"
|
||||
# endif /* !(defined(_M_X64) || defined(_M_AMD64) || defined(_AMD64_)) */
|
||||
|
||||
#elif defined(_WIN32) || defined(XP_OS2) || defined(WINCE)
|
||||
#elif defined(_WIN32) || defined(XP_OS2)
|
||||
|
||||
#ifdef __WATCOMC__
|
||||
#define HAVE_VA_LIST_AS_ARRAY 1
|
||||
#endif
|
||||
# ifdef __WATCOMC__
|
||||
# define HAVE_VA_LIST_AS_ARRAY 1
|
||||
# endif
|
||||
|
||||
#define IS_LITTLE_ENDIAN 1
|
||||
#undef IS_BIG_ENDIAN
|
||||
#define JS_BYTES_PER_DOUBLE 8L
|
||||
#define JS_BYTES_PER_WORD 4L
|
||||
#define JS_BITS_PER_WORD_LOG2 5
|
||||
#define JS_ALIGN_OF_POINTER 4L
|
||||
# define IS_LITTLE_ENDIAN 1
|
||||
# undef IS_BIG_ENDIAN
|
||||
# define JS_BYTES_PER_DOUBLE 8
|
||||
# define JS_BYTES_PER_WORD 4
|
||||
# define JS_BITS_PER_WORD_LOG2 5
|
||||
# define JS_ALIGN_OF_POINTER 4
|
||||
|
||||
#endif /* _WIN32 || XP_OS2 || WINCE*/
|
||||
#elif defined(__APPLE__)
|
||||
# if __LITTLE_ENDIAN__
|
||||
# define IS_LITTLE_ENDIAN 1
|
||||
# undef IS_BIG_ENDIAN
|
||||
# elif __BIG_ENDIAN__
|
||||
# undef IS_LITTLE_ENDIAN
|
||||
# define IS_BIG_ENDIAN 1
|
||||
# endif
|
||||
|
||||
#elif defined(XP_UNIX) || defined(XP_BEOS)
|
||||
#elif defined(JS_HAVE_ENDIAN_H)
|
||||
# include <endian.h>
|
||||
|
||||
#error "This file is supposed to be auto-generated on UNIX platforms, but the"
|
||||
#error "static version for Mac and Windows platforms is being used."
|
||||
#error "Something's probably wrong with paths/headers/dependencies/Makefiles."
|
||||
# if defined(__BYTE_ORDER)
|
||||
# if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
# define IS_LITTLE_ENDIAN 1
|
||||
# undef IS_BIG_ENDIAN
|
||||
# elif __BYTE_ORDER == __BIG_ENDIAN
|
||||
# undef IS_LITTLE_ENDIAN
|
||||
# define IS_BIG_ENDIAN 1
|
||||
# endif
|
||||
# else /* !defined(__BYTE_ORDER) */
|
||||
# error "endian.h does not define __BYTE_ORDER. Cannot determine endianness."
|
||||
# endif
|
||||
|
||||
#else
|
||||
/* BSDs */
|
||||
#elif defined(JS_HAVE_MACHINE_ENDIAN_H)
|
||||
# include <sys/types.h>
|
||||
# include <machine/endian.h>
|
||||
|
||||
#error "Must define one of XP_BEOS, XP_OS2, XP_WIN, or XP_UNIX"
|
||||
# if defined(_BYTE_ORDER)
|
||||
# if _BYTE_ORDER == _LITTLE_ENDIAN
|
||||
# define IS_LITTLE_ENDIAN 1
|
||||
# undef IS_BIG_ENDIAN
|
||||
# elif _BYTE_ORDER == _BIG_ENDIAN
|
||||
# undef IS_LITTLE_ENDIAN
|
||||
# define IS_BIG_ENDIAN 1
|
||||
# endif
|
||||
# else /* !defined(_BYTE_ORDER) */
|
||||
# error "machine/endian.h does not define _BYTE_ORDER. Cannot determine endianness."
|
||||
# endif
|
||||
|
||||
#elif defined(JS_HAVE_SYS_ISA_DEFS_H)
|
||||
# include <sys/isa_defs.h>
|
||||
|
||||
# if defined(_BIG_ENDIAN)
|
||||
# undef IS_LITTLE_ENDIAN
|
||||
# define IS_BIG_ENDIAN 1
|
||||
# elif defined(_LITTLE_ENDIAN)
|
||||
# define IS_LITTLE_ENDIAN 1
|
||||
# undef IS_BIG_ENDIAN
|
||||
# else /* !defined(_LITTLE_ENDIAN) */
|
||||
# error "sys/isa_defs.h does not define _BIG_ENDIAN or _LITTLE_ENDIAN. Cannot determine endianness."
|
||||
# endif
|
||||
# if !defined(JS_STACK_GROWTH_DIRECTION)
|
||||
# if defined(_STACK_GROWS_UPWARD)
|
||||
# define JS_STACK_GROWTH_DIRECTION (1)
|
||||
# elif defined(_STACK_GROWS_DOWNWARD)
|
||||
# define JS_STACK_GROWTH_DIRECTION (-1)
|
||||
# endif
|
||||
# endif
|
||||
|
||||
#elif defined(__sparc) || defined(__sparc__) || \
|
||||
defined(_POWER) || defined(__powerpc__) || \
|
||||
defined(__ppc__) || defined(__hppa) || \
|
||||
defined(_MIPSEB) || defined(_BIG_ENDIAN)
|
||||
/* IA64 running HP-UX will have _BIG_ENDIAN defined.
|
||||
* IA64 running Linux will have endian.h and be handled above.
|
||||
*/
|
||||
# undef IS_LITTLE_ENDIAN
|
||||
# define IS_BIG_ENDIAN 1
|
||||
|
||||
#else /* !defined(__sparc) && !defined(__sparc__) && ... */
|
||||
# error "Cannot determine endianness of your platform. Please add support to jscpucfg.h."
|
||||
#endif
|
||||
|
||||
#ifndef JS_STACK_GROWTH_DIRECTION
|
||||
#define JS_STACK_GROWTH_DIRECTION (-1)
|
||||
# ifdef __hppa
|
||||
# define JS_STACK_GROWTH_DIRECTION (1)
|
||||
# else
|
||||
# define JS_STACK_GROWTH_DIRECTION (-1)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#endif /* js_cpucfg___ */
|
||||
|
|
|
@ -0,0 +1,556 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sw=4 et tw=99:
|
||||
*
|
||||
* ***** 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 Mozilla Communicator client code, released
|
||||
* March 31, 1998.
|
||||
*
|
||||
* 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):
|
||||
* Nick Fitzgerald <nfitzgerald@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of 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 jsdbgapi_h___
|
||||
#define jsdbgapi_h___
|
||||
/*
|
||||
* JS debugger API.
|
||||
*/
|
||||
#include "jsapi.h"
|
||||
#include "jsprvtd.h"
|
||||
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
||||
extern JS_PUBLIC_API(JSCrossCompartmentCall *)
|
||||
JS_EnterCrossCompartmentCallScript(JSContext *cx, JSScript *target);
|
||||
|
||||
extern JS_PUBLIC_API(JSCrossCompartmentCall *)
|
||||
JS_EnterCrossCompartmentCallStackFrame(JSContext *cx, JSStackFrame *target);
|
||||
|
||||
#ifdef __cplusplus
|
||||
JS_END_EXTERN_C
|
||||
|
||||
namespace JS {
|
||||
|
||||
class JS_PUBLIC_API(AutoEnterScriptCompartment)
|
||||
{
|
||||
protected:
|
||||
JSCrossCompartmentCall *call;
|
||||
|
||||
public:
|
||||
AutoEnterScriptCompartment() : call(NULL) {}
|
||||
|
||||
bool enter(JSContext *cx, JSScript *target);
|
||||
|
||||
bool entered() const { return call != NULL; }
|
||||
|
||||
~AutoEnterScriptCompartment() {
|
||||
if (call && call != reinterpret_cast<JSCrossCompartmentCall*>(1))
|
||||
JS_LeaveCrossCompartmentCall(call);
|
||||
}
|
||||
};
|
||||
|
||||
class JS_PUBLIC_API(AutoEnterFrameCompartment) : public AutoEnterScriptCompartment
|
||||
{
|
||||
public:
|
||||
bool enter(JSContext *cx, JSStackFrame *target);
|
||||
};
|
||||
|
||||
} /* namespace JS */
|
||||
|
||||
#ifdef DEBUG
|
||||
JS_FRIEND_API(void) js_DumpValue(const js::Value &val);
|
||||
JS_FRIEND_API(void) js_DumpId(jsid id);
|
||||
JS_FRIEND_API(void) js_DumpStackFrame(JSContext *cx, js::StackFrame *start = NULL);
|
||||
#endif
|
||||
JS_FRIEND_API(void) js_DumpBacktrace(JSContext *cx);
|
||||
|
||||
JS_BEGIN_EXTERN_C
|
||||
#endif
|
||||
|
||||
extern JS_PUBLIC_API(JSString *)
|
||||
JS_DecompileScript(JSContext *cx, JSScript *script, const char *name, unsigned indent);
|
||||
|
||||
/*
|
||||
* Currently, we only support runtime-wide debugging. In the future, we should
|
||||
* be able to support compartment-wide debugging.
|
||||
*/
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_SetRuntimeDebugMode(JSRuntime *rt, JSBool debug);
|
||||
|
||||
/*
|
||||
* Debug mode is a compartment-wide mode that enables a debugger to attach
|
||||
* to and interact with running methodjit-ed frames. In particular, it causes
|
||||
* every function to be compiled as if an eval was present (so eval-in-frame)
|
||||
* can work, and it ensures that functions can be re-JITed for other debug
|
||||
* features. In general, it is not safe to interact with frames that were live
|
||||
* before debug mode was enabled. For this reason, it is also not safe to
|
||||
* enable debug mode while frames are live.
|
||||
*/
|
||||
|
||||
/* Get current state of debugging mode. */
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_GetDebugMode(JSContext *cx);
|
||||
|
||||
/*
|
||||
* Turn on/off debugging mode for a single compartment. This should only be
|
||||
* used when no code from this compartment is running or on the stack in any
|
||||
* thread.
|
||||
*/
|
||||
JS_FRIEND_API(JSBool)
|
||||
JS_SetDebugModeForCompartment(JSContext *cx, JSCompartment *comp, JSBool debug);
|
||||
|
||||
/*
|
||||
* Turn on/off debugging mode for a context's compartment.
|
||||
*/
|
||||
JS_FRIEND_API(JSBool)
|
||||
JS_SetDebugMode(JSContext *cx, JSBool debug);
|
||||
|
||||
/* Turn on single step mode. */
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_SetSingleStepMode(JSContext *cx, JSScript *script, JSBool singleStep);
|
||||
|
||||
/* The closure argument will be marked. */
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_SetTrap(JSContext *cx, JSScript *script, jsbytecode *pc,
|
||||
JSTrapHandler handler, jsval closure);
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_ClearTrap(JSContext *cx, JSScript *script, jsbytecode *pc,
|
||||
JSTrapHandler *handlerp, jsval *closurep);
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_ClearScriptTraps(JSContext *cx, JSScript *script);
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_ClearAllTrapsForCompartment(JSContext *cx);
|
||||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_SetInterrupt(JSRuntime *rt, JSInterruptHook handler, void *closure);
|
||||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_ClearInterrupt(JSRuntime *rt, JSInterruptHook *handlerp, void **closurep);
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_SetWatchPoint(JSContext *cx, JSObject *obj, jsid id,
|
||||
JSWatchPointHandler handler, JSObject *closure);
|
||||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_ClearWatchPoint(JSContext *cx, JSObject *obj, jsid id,
|
||||
JSWatchPointHandler *handlerp, JSObject **closurep);
|
||||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_ClearWatchPointsForObject(JSContext *cx, JSObject *obj);
|
||||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_ClearAllWatchPoints(JSContext *cx);
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
extern JS_PUBLIC_API(unsigned)
|
||||
JS_PCToLineNumber(JSContext *cx, JSScript *script, jsbytecode *pc);
|
||||
|
||||
extern JS_PUBLIC_API(jsbytecode *)
|
||||
JS_LineNumberToPC(JSContext *cx, JSScript *script, unsigned lineno);
|
||||
|
||||
extern JS_PUBLIC_API(jsbytecode *)
|
||||
JS_EndPC(JSContext *cx, JSScript *script);
|
||||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_GetLinePCs(JSContext *cx, JSScript *script,
|
||||
unsigned startLine, unsigned maxLines,
|
||||
unsigned* count, unsigned** lines, jsbytecode*** pcs);
|
||||
|
||||
extern JS_PUBLIC_API(unsigned)
|
||||
JS_GetFunctionArgumentCount(JSContext *cx, JSFunction *fun);
|
||||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_FunctionHasLocalNames(JSContext *cx, JSFunction *fun);
|
||||
|
||||
/*
|
||||
* N.B. The mark is in the context temp pool and thus the caller must take care
|
||||
* to call JS_ReleaseFunctionLocalNameArray in a LIFO manner (wrt to any other
|
||||
* call that may use the temp pool.
|
||||
*/
|
||||
extern JS_PUBLIC_API(uintptr_t *)
|
||||
JS_GetFunctionLocalNameArray(JSContext *cx, JSFunction *fun, void **markp);
|
||||
|
||||
extern JS_PUBLIC_API(JSAtom *)
|
||||
JS_LocalNameToAtom(uintptr_t w);
|
||||
|
||||
extern JS_PUBLIC_API(JSString *)
|
||||
JS_AtomKey(JSAtom *atom);
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_ReleaseFunctionLocalNameArray(JSContext *cx, void *mark);
|
||||
|
||||
extern JS_PUBLIC_API(JSScript *)
|
||||
JS_GetFunctionScript(JSContext *cx, JSFunction *fun);
|
||||
|
||||
extern JS_PUBLIC_API(JSNative)
|
||||
JS_GetFunctionNative(JSContext *cx, JSFunction *fun);
|
||||
|
||||
extern JS_PUBLIC_API(JSPrincipals *)
|
||||
JS_GetScriptPrincipals(JSScript *script);
|
||||
|
||||
extern JS_PUBLIC_API(JSPrincipals *)
|
||||
JS_GetScriptOriginPrincipals(JSScript *script);
|
||||
|
||||
/*
|
||||
* Stack Frame Iterator
|
||||
*
|
||||
* Used to iterate through the JS stack frames to extract
|
||||
* information from the frames.
|
||||
*/
|
||||
|
||||
extern JS_PUBLIC_API(JSStackFrame *)
|
||||
JS_FrameIterator(JSContext *cx, JSStackFrame **iteratorp);
|
||||
|
||||
extern JS_PUBLIC_API(JSScript *)
|
||||
JS_GetFrameScript(JSContext *cx, JSStackFrame *fp);
|
||||
|
||||
extern JS_PUBLIC_API(jsbytecode *)
|
||||
JS_GetFramePC(JSContext *cx, JSStackFrame *fp);
|
||||
|
||||
extern JS_PUBLIC_API(void *)
|
||||
JS_GetFrameAnnotation(JSContext *cx, JSStackFrame *fp);
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_SetFrameAnnotation(JSContext *cx, JSStackFrame *fp, void *annotation);
|
||||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_IsScriptFrame(JSContext *cx, JSStackFrame *fp);
|
||||
|
||||
extern JS_PUBLIC_API(JSObject *)
|
||||
JS_GetFrameScopeChain(JSContext *cx, JSStackFrame *fp);
|
||||
|
||||
extern JS_PUBLIC_API(JSObject *)
|
||||
JS_GetFrameCallObject(JSContext *cx, JSStackFrame *fp);
|
||||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_GetFrameThis(JSContext *cx, JSStackFrame *fp, jsval *thisv);
|
||||
|
||||
extern JS_PUBLIC_API(JSFunction *)
|
||||
JS_GetFrameFunction(JSContext *cx, JSStackFrame *fp);
|
||||
|
||||
extern JS_PUBLIC_API(JSObject *)
|
||||
JS_GetFrameFunctionObject(JSContext *cx, JSStackFrame *fp);
|
||||
|
||||
JS_PUBLIC_API(JSFunction *)
|
||||
JS_GetScriptFunction(JSContext *cx, JSScript *script);
|
||||
|
||||
extern JS_PUBLIC_API(JSObject *)
|
||||
JS_GetParentOrScopeChain(JSContext *cx, JSObject *obj);
|
||||
|
||||
/* XXXrginda Initially published with typo */
|
||||
#define JS_IsContructorFrame JS_IsConstructorFrame
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_IsConstructorFrame(JSContext *cx, JSStackFrame *fp);
|
||||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_IsDebuggerFrame(JSContext *cx, JSStackFrame *fp);
|
||||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_IsGlobalFrame(JSContext *cx, JSStackFrame *fp);
|
||||
|
||||
extern JS_PUBLIC_API(jsval)
|
||||
JS_GetFrameReturnValue(JSContext *cx, JSStackFrame *fp);
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_SetFrameReturnValue(JSContext *cx, JSStackFrame *fp, jsval rval);
|
||||
|
||||
/**
|
||||
* Return fp's callee function object (fp->callee) if it has one. Note that
|
||||
* this API cannot fail. A null return means "no callee": fp is a global or
|
||||
* eval-from-global frame, not a call frame.
|
||||
*/
|
||||
extern JS_PUBLIC_API(JSObject *)
|
||||
JS_GetFrameCalleeObject(JSContext *cx, JSStackFrame *fp);
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
extern JS_PUBLIC_API(const char *)
|
||||
JS_GetScriptFilename(JSContext *cx, JSScript *script);
|
||||
|
||||
extern JS_PUBLIC_API(const jschar *)
|
||||
JS_GetScriptSourceMap(JSContext *cx, JSScript *script);
|
||||
|
||||
extern JS_PUBLIC_API(unsigned)
|
||||
JS_GetScriptBaseLineNumber(JSContext *cx, JSScript *script);
|
||||
|
||||
extern JS_PUBLIC_API(unsigned)
|
||||
JS_GetScriptLineExtent(JSContext *cx, JSScript *script);
|
||||
|
||||
extern JS_PUBLIC_API(JSVersion)
|
||||
JS_GetScriptVersion(JSContext *cx, JSScript *script);
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
/*
|
||||
* Hook setters for script creation and destruction, see jsprvtd.h for the
|
||||
* typedefs. These macros provide binary compatibility and newer, shorter
|
||||
* synonyms.
|
||||
*/
|
||||
#define JS_SetNewScriptHook JS_SetNewScriptHookProc
|
||||
#define JS_SetDestroyScriptHook JS_SetDestroyScriptHookProc
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_SetNewScriptHook(JSRuntime *rt, JSNewScriptHook hook, void *callerdata);
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_SetDestroyScriptHook(JSRuntime *rt, JSDestroyScriptHook hook,
|
||||
void *callerdata);
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_EvaluateUCInStackFrame(JSContext *cx, JSStackFrame *fp,
|
||||
const jschar *chars, unsigned length,
|
||||
const char *filename, unsigned lineno,
|
||||
jsval *rval);
|
||||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_EvaluateInStackFrame(JSContext *cx, JSStackFrame *fp,
|
||||
const char *bytes, unsigned length,
|
||||
const char *filename, unsigned lineno,
|
||||
jsval *rval);
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
typedef struct JSPropertyDesc {
|
||||
jsval id; /* primary id, atomized string, or int */
|
||||
jsval value; /* property value */
|
||||
uint8_t flags; /* flags, see below */
|
||||
uint8_t spare; /* unused */
|
||||
uint16_t slot; /* argument/variable slot */
|
||||
jsval alias; /* alias id if JSPD_ALIAS flag */
|
||||
} JSPropertyDesc;
|
||||
|
||||
#define JSPD_ENUMERATE 0x01 /* visible to for/in loop */
|
||||
#define JSPD_READONLY 0x02 /* assignment is error */
|
||||
#define JSPD_PERMANENT 0x04 /* property cannot be deleted */
|
||||
#define JSPD_ALIAS 0x08 /* property has an alias id */
|
||||
#define JSPD_ARGUMENT 0x10 /* argument to function */
|
||||
#define JSPD_VARIABLE 0x20 /* local variable in function */
|
||||
#define JSPD_EXCEPTION 0x40 /* exception occurred fetching the property, */
|
||||
/* value is exception */
|
||||
#define JSPD_ERROR 0x80 /* native getter returned JS_FALSE without */
|
||||
/* throwing an exception */
|
||||
|
||||
typedef struct JSPropertyDescArray {
|
||||
uint32_t length; /* number of elements in array */
|
||||
JSPropertyDesc *array; /* alloc'd by Get, freed by Put */
|
||||
} JSPropertyDescArray;
|
||||
|
||||
typedef struct JSScopeProperty JSScopeProperty;
|
||||
|
||||
extern JS_PUBLIC_API(JSScopeProperty *)
|
||||
JS_PropertyIterator(JSObject *obj, JSScopeProperty **iteratorp);
|
||||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_GetPropertyDesc(JSContext *cx, JSObject *obj, JSScopeProperty *shape,
|
||||
JSPropertyDesc *pd);
|
||||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_GetPropertyDescArray(JSContext *cx, JSObject *obj, JSPropertyDescArray *pda);
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_PutPropertyDescArray(JSContext *cx, JSPropertyDescArray *pda);
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_SetDebuggerHandler(JSRuntime *rt, JSDebuggerHandler hook, void *closure);
|
||||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_SetSourceHandler(JSRuntime *rt, JSSourceHandler handler, void *closure);
|
||||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_SetExecuteHook(JSRuntime *rt, JSInterpreterHook hook, void *closure);
|
||||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_SetCallHook(JSRuntime *rt, JSInterpreterHook hook, void *closure);
|
||||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_SetThrowHook(JSRuntime *rt, JSThrowHook hook, void *closure);
|
||||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_SetDebugErrorHook(JSRuntime *rt, JSDebugErrorHook hook, void *closure);
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
extern JS_PUBLIC_API(size_t)
|
||||
JS_GetObjectTotalSize(JSContext *cx, JSObject *obj);
|
||||
|
||||
extern JS_PUBLIC_API(size_t)
|
||||
JS_GetFunctionTotalSize(JSContext *cx, JSFunction *fun);
|
||||
|
||||
extern JS_PUBLIC_API(size_t)
|
||||
JS_GetScriptTotalSize(JSContext *cx, JSScript *script);
|
||||
|
||||
/*
|
||||
* Return true if obj is a "system" object, that is, one created by
|
||||
* JS_NewSystemObject with the system flag set and not JS_NewObject.
|
||||
*
|
||||
* What "system" means is up to the API client.
|
||||
*/
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_IsSystemObject(JSContext *cx, JSObject *obj);
|
||||
|
||||
/*
|
||||
* Mark an object as being a system object. This should be called immediately
|
||||
* after allocating the object. A system object is an object for which
|
||||
* JS_IsSystemObject returns true.
|
||||
*/
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_MakeSystemObject(JSContext *cx, JSObject *obj);
|
||||
|
||||
/************************************************************************/
|
||||
|
||||
extern JS_FRIEND_API(void)
|
||||
js_RevertVersion(JSContext *cx);
|
||||
|
||||
extern JS_PUBLIC_API(const JSDebugHooks *)
|
||||
JS_GetGlobalDebugHooks(JSRuntime *rt);
|
||||
|
||||
/**
|
||||
* Start any profilers that are available and have been configured on for this
|
||||
* platform. This is NOT thread safe.
|
||||
*
|
||||
* The profileName is used by some profilers to describe the current profiling
|
||||
* run. It may be used for part of the filename of the output, but the
|
||||
* specifics depend on the profiler. Many profilers will ignore it. Passing in
|
||||
* NULL is legal; some profilers may use it to output to stdout or similar.
|
||||
*
|
||||
* Returns true if no profilers fail to start.
|
||||
*/
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_StartProfiling(const char *profileName);
|
||||
|
||||
/**
|
||||
* Stop any profilers that were previously started with JS_StartProfiling.
|
||||
* Returns true if no profilers fail to stop.
|
||||
*/
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_StopProfiling(const char *profileName);
|
||||
|
||||
/**
|
||||
* Write the current profile data to the given file, if applicable to whatever
|
||||
* profiler is being used.
|
||||
*/
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_DumpProfile(const char *outfile, const char *profileName);
|
||||
|
||||
/**
|
||||
* Pause currently active profilers (only supported by some profilers). Returns
|
||||
* whether any profilers failed to pause. (Profilers that do not support
|
||||
* pause/resume do not count.)
|
||||
*/
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_PauseProfilers(const char *profileName);
|
||||
|
||||
/**
|
||||
* Resume suspended profilers
|
||||
*/
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_ResumeProfilers(const char *profileName);
|
||||
|
||||
/**
|
||||
* Add various profiling-related functions as properties of the given object.
|
||||
*/
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_DefineProfilingFunctions(JSContext *cx, JSObject *obj);
|
||||
|
||||
/* Defined in vm/Debugger.cpp. */
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_DefineDebuggerObject(JSContext *cx, JSObject *obj);
|
||||
|
||||
/**
|
||||
* The profiling API calls are not able to report errors, so they use a
|
||||
* thread-unsafe global memory buffer to hold the last error encountered. This
|
||||
* should only be called after something returns false.
|
||||
*/
|
||||
JS_PUBLIC_API(const char *)
|
||||
JS_UnsafeGetLastProfilingError();
|
||||
|
||||
#ifdef MOZ_CALLGRIND
|
||||
|
||||
extern JS_FRIEND_API(JSBool)
|
||||
js_StopCallgrind();
|
||||
|
||||
extern JS_FRIEND_API(JSBool)
|
||||
js_StartCallgrind();
|
||||
|
||||
extern JS_FRIEND_API(JSBool)
|
||||
js_DumpCallgrind(const char *outfile);
|
||||
|
||||
#endif /* MOZ_CALLGRIND */
|
||||
|
||||
#ifdef MOZ_VTUNE
|
||||
|
||||
extern JS_FRIEND_API(bool)
|
||||
js_StartVtune(const char *profileName);
|
||||
|
||||
extern JS_FRIEND_API(bool)
|
||||
js_StopVtune();
|
||||
|
||||
extern JS_FRIEND_API(bool)
|
||||
js_PauseVtune();
|
||||
|
||||
extern JS_FRIEND_API(bool)
|
||||
js_ResumeVtune();
|
||||
|
||||
#endif /* MOZ_VTUNE */
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_DumpBytecode(JSContext *cx, JSScript *script);
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_DumpCompartmentBytecode(JSContext *cx);
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_DumpPCCounts(JSContext *cx, JSScript *script);
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_DumpCompartmentPCCounts(JSContext *cx);
|
||||
|
||||
extern JS_PUBLIC_API(JSObject *)
|
||||
JS_UnwrapObject(JSObject *obj);
|
||||
|
||||
/* Call the context debug handler on the topmost scripted frame. */
|
||||
extern JS_FRIEND_API(JSBool)
|
||||
js_CallContextDebugHandler(JSContext *cx);
|
||||
|
||||
JS_END_EXTERN_C
|
||||
|
||||
#endif /* jsdbgapi_h___ */
|
|
@ -0,0 +1,636 @@
|
|||
/* -*- Mode: C; tab-width: 8; 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 Mozilla JavaScript code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1999-2001
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Brendan Eich <brendan@mozilla.org> (Original Author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of 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 jsdhash_h___
|
||||
#define jsdhash_h___
|
||||
|
||||
/*
|
||||
* Double hashing, a la Knuth 6.
|
||||
*
|
||||
* Try to keep this file in sync with xpcom/glue/pldhash.h.
|
||||
*/
|
||||
#include "jstypes.h"
|
||||
#include "jsutil.h"
|
||||
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
||||
#if defined(__GNUC__) && defined(__i386__) && (__GNUC__ >= 3) && !defined(XP_OS2)
|
||||
#define JS_DHASH_FASTCALL __attribute__ ((regparm (3),stdcall))
|
||||
#elif defined(XP_WIN)
|
||||
#define JS_DHASH_FASTCALL __fastcall
|
||||
#else
|
||||
#define JS_DHASH_FASTCALL
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_XXXbrendan
|
||||
#define JS_DHASHMETER 1
|
||||
#endif
|
||||
|
||||
/* Table size limit, do not equal or exceed (see min&maxAlphaFrac, below). */
|
||||
#undef JS_DHASH_SIZE_LIMIT
|
||||
#define JS_DHASH_SIZE_LIMIT JS_BIT(24)
|
||||
|
||||
/* Minimum table size, or gross entry count (net is at most .75 loaded). */
|
||||
#ifndef JS_DHASH_MIN_SIZE
|
||||
#define JS_DHASH_MIN_SIZE 16
|
||||
#elif (JS_DHASH_MIN_SIZE & (JS_DHASH_MIN_SIZE - 1)) != 0
|
||||
#error "JS_DHASH_MIN_SIZE must be a power of two!"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Multiplicative hash uses an unsigned 32 bit integer and the golden ratio,
|
||||
* expressed as a fixed-point 32-bit fraction.
|
||||
*/
|
||||
#define JS_DHASH_BITS 32
|
||||
#define JS_DHASH_GOLDEN_RATIO 0x9E3779B9U
|
||||
|
||||
/* Primitive and forward-struct typedefs. */
|
||||
typedef uint32_t JSDHashNumber;
|
||||
typedef struct JSDHashEntryHdr JSDHashEntryHdr;
|
||||
typedef struct JSDHashEntryStub JSDHashEntryStub;
|
||||
typedef struct JSDHashTable JSDHashTable;
|
||||
typedef struct JSDHashTableOps JSDHashTableOps;
|
||||
|
||||
/*
|
||||
* Table entry header structure.
|
||||
*
|
||||
* In order to allow in-line allocation of key and value, we do not declare
|
||||
* either here. Instead, the API uses const void *key as a formal parameter.
|
||||
* The key need not be stored in the entry; it may be part of the value, but
|
||||
* need not be stored at all.
|
||||
*
|
||||
* Callback types are defined below and grouped into the JSDHashTableOps
|
||||
* structure, for single static initialization per hash table sub-type.
|
||||
*
|
||||
* Each hash table sub-type should nest the JSDHashEntryHdr structure at the
|
||||
* front of its particular entry type. The keyHash member contains the result
|
||||
* of multiplying the hash code returned from the hashKey callback (see below)
|
||||
* by JS_DHASH_GOLDEN_RATIO, then constraining the result to avoid the magic 0
|
||||
* and 1 values. The stored keyHash value is table size invariant, and it is
|
||||
* maintained automatically by JS_DHashTableOperate -- users should never set
|
||||
* it, and its only uses should be via the entry macros below.
|
||||
*
|
||||
* The JS_DHASH_ENTRY_IS_LIVE macro tests whether entry is neither free nor
|
||||
* removed. An entry may be either busy or free; if busy, it may be live or
|
||||
* removed. Consumers of this API should not access members of entries that
|
||||
* are not live.
|
||||
*
|
||||
* However, use JS_DHASH_ENTRY_IS_BUSY for faster liveness testing of entries
|
||||
* returned by JS_DHashTableOperate, as JS_DHashTableOperate never returns a
|
||||
* non-live, busy (i.e., removed) entry pointer to its caller. See below for
|
||||
* more details on JS_DHashTableOperate's calling rules.
|
||||
*/
|
||||
struct JSDHashEntryHdr {
|
||||
JSDHashNumber keyHash; /* every entry must begin like this */
|
||||
};
|
||||
|
||||
#define JS_DHASH_ENTRY_IS_FREE(entry) ((entry)->keyHash == 0)
|
||||
#define JS_DHASH_ENTRY_IS_BUSY(entry) (!JS_DHASH_ENTRY_IS_FREE(entry))
|
||||
#define JS_DHASH_ENTRY_IS_LIVE(entry) ((entry)->keyHash >= 2)
|
||||
|
||||
/*
|
||||
* A JSDHashTable is currently 8 words (without the JS_DHASHMETER overhead)
|
||||
* on most architectures, and may be allocated on the stack or within another
|
||||
* structure or class (see below for the Init and Finish functions to use).
|
||||
*
|
||||
* To decide whether to use double hashing vs. chaining, we need to develop a
|
||||
* trade-off relation, as follows:
|
||||
*
|
||||
* Let alpha be the load factor, esize the entry size in words, count the
|
||||
* entry count, and pow2 the power-of-two table size in entries.
|
||||
*
|
||||
* (JSDHashTable overhead) > (JSHashTable overhead)
|
||||
* (unused table entry space) > (malloc and .next overhead per entry) +
|
||||
* (buckets overhead)
|
||||
* (1 - alpha) * esize * pow2 > 2 * count + pow2
|
||||
*
|
||||
* Notice that alpha is by definition (count / pow2):
|
||||
*
|
||||
* (1 - alpha) * esize * pow2 > 2 * alpha * pow2 + pow2
|
||||
* (1 - alpha) * esize > 2 * alpha + 1
|
||||
*
|
||||
* esize > (1 + 2 * alpha) / (1 - alpha)
|
||||
*
|
||||
* This assumes both tables must keep keyHash, key, and value for each entry,
|
||||
* where key and value point to separately allocated strings or structures.
|
||||
* If key and value can be combined into one pointer, then the trade-off is:
|
||||
*
|
||||
* esize > (1 + 3 * alpha) / (1 - alpha)
|
||||
*
|
||||
* If the entry value can be a subtype of JSDHashEntryHdr, rather than a type
|
||||
* that must be allocated separately and referenced by an entry.value pointer
|
||||
* member, and provided key's allocation can be fused with its entry's, then
|
||||
* k (the words wasted per entry with chaining) is 4.
|
||||
*
|
||||
* To see these curves, feed gnuplot input like so:
|
||||
*
|
||||
* gnuplot> f(x,k) = (1 + k * x) / (1 - x)
|
||||
* gnuplot> plot [0:.75] f(x,2), f(x,3), f(x,4)
|
||||
*
|
||||
* For k of 2 and a well-loaded table (alpha > .5), esize must be more than 4
|
||||
* words for chaining to be more space-efficient than double hashing.
|
||||
*
|
||||
* Solving for alpha helps us decide when to shrink an underloaded table:
|
||||
*
|
||||
* esize > (1 + k * alpha) / (1 - alpha)
|
||||
* esize - alpha * esize > 1 + k * alpha
|
||||
* esize - 1 > (k + esize) * alpha
|
||||
* (esize - 1) / (k + esize) > alpha
|
||||
*
|
||||
* alpha < (esize - 1) / (esize + k)
|
||||
*
|
||||
* Therefore double hashing should keep alpha >= (esize - 1) / (esize + k),
|
||||
* assuming esize is not too large (in which case, chaining should probably be
|
||||
* used for any alpha). For esize=2 and k=3, we want alpha >= .2; for esize=3
|
||||
* and k=2, we want alpha >= .4. For k=4, esize could be 6, and alpha >= .5
|
||||
* would still obtain. See the JS_DHASH_MIN_ALPHA macro further below.
|
||||
*
|
||||
* The current implementation uses a configurable lower bound on alpha, which
|
||||
* defaults to .25, when deciding to shrink the table (while still respecting
|
||||
* JS_DHASH_MIN_SIZE).
|
||||
*
|
||||
* Note a qualitative difference between chaining and double hashing: under
|
||||
* chaining, entry addresses are stable across table shrinks and grows. With
|
||||
* double hashing, you can't safely hold an entry pointer and use it after an
|
||||
* ADD or REMOVE operation, unless you sample table->generation before adding
|
||||
* or removing, and compare the sample after, dereferencing the entry pointer
|
||||
* only if table->generation has not changed.
|
||||
*
|
||||
* The moral of this story: there is no one-size-fits-all hash table scheme,
|
||||
* but for small table entry size, and assuming entry address stability is not
|
||||
* required, double hashing wins.
|
||||
*/
|
||||
struct JSDHashTable {
|
||||
const JSDHashTableOps *ops; /* virtual operations, see below */
|
||||
void *data; /* ops- and instance-specific data */
|
||||
int16_t hashShift; /* multiplicative hash shift */
|
||||
uint8_t maxAlphaFrac; /* 8-bit fixed point max alpha */
|
||||
uint8_t minAlphaFrac; /* 8-bit fixed point min alpha */
|
||||
uint32_t entrySize; /* number of bytes in an entry */
|
||||
uint32_t entryCount; /* number of entries in table */
|
||||
uint32_t removedCount; /* removed entry sentinels in table */
|
||||
uint32_t generation; /* entry storage generation number */
|
||||
char *entryStore; /* entry storage */
|
||||
#ifdef JS_DHASHMETER
|
||||
struct JSDHashStats {
|
||||
uint32_t searches; /* total number of table searches */
|
||||
uint32_t steps; /* hash chain links traversed */
|
||||
uint32_t hits; /* searches that found key */
|
||||
uint32_t misses; /* searches that didn't find key */
|
||||
uint32_t lookups; /* number of JS_DHASH_LOOKUPs */
|
||||
uint32_t addMisses; /* adds that miss, and do work */
|
||||
uint32_t addOverRemoved; /* adds that recycled a removed entry */
|
||||
uint32_t addHits; /* adds that hit an existing entry */
|
||||
uint32_t addFailures; /* out-of-memory during add growth */
|
||||
uint32_t removeHits; /* removes that hit, and do work */
|
||||
uint32_t removeMisses; /* useless removes that miss */
|
||||
uint32_t removeFrees; /* removes that freed entry directly */
|
||||
uint32_t removeEnums; /* removes done by Enumerate */
|
||||
uint32_t grows; /* table expansions */
|
||||
uint32_t shrinks; /* table contractions */
|
||||
uint32_t compresses; /* table compressions */
|
||||
uint32_t enumShrinks; /* contractions after Enumerate */
|
||||
} stats;
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
* Size in entries (gross, not net of free and removed sentinels) for table.
|
||||
* We store hashShift rather than sizeLog2 to optimize the collision-free case
|
||||
* in SearchTable.
|
||||
*/
|
||||
#define JS_DHASH_TABLE_SIZE(table) JS_BIT(JS_DHASH_BITS - (table)->hashShift)
|
||||
|
||||
/*
|
||||
* Table space at entryStore is allocated and freed using these callbacks.
|
||||
* The allocator should return null on error only (not if called with nbytes
|
||||
* equal to 0; but note that jsdhash.c code will never call with 0 nbytes).
|
||||
*/
|
||||
typedef void *
|
||||
(* JSDHashAllocTable)(JSDHashTable *table, uint32_t nbytes);
|
||||
|
||||
typedef void
|
||||
(* JSDHashFreeTable) (JSDHashTable *table, void *ptr);
|
||||
|
||||
/*
|
||||
* Compute the hash code for a given key to be looked up, added, or removed
|
||||
* from table. A hash code may have any JSDHashNumber value.
|
||||
*/
|
||||
typedef JSDHashNumber
|
||||
(* JSDHashHashKey) (JSDHashTable *table, const void *key);
|
||||
|
||||
/*
|
||||
* Compare the key identifying entry in table with the provided key parameter.
|
||||
* Return JS_TRUE if keys match, JS_FALSE otherwise.
|
||||
*/
|
||||
typedef JSBool
|
||||
(* JSDHashMatchEntry)(JSDHashTable *table, const JSDHashEntryHdr *entry,
|
||||
const void *key);
|
||||
|
||||
/*
|
||||
* Copy the data starting at from to the new entry storage at to. Do not add
|
||||
* reference counts for any strong references in the entry, however, as this
|
||||
* is a "move" operation: the old entry storage at from will be freed without
|
||||
* any reference-decrementing callback shortly.
|
||||
*/
|
||||
typedef void
|
||||
(* JSDHashMoveEntry)(JSDHashTable *table, const JSDHashEntryHdr *from,
|
||||
JSDHashEntryHdr *to);
|
||||
|
||||
/*
|
||||
* Clear the entry and drop any strong references it holds. This callback is
|
||||
* invoked during a JS_DHASH_REMOVE operation (see below for operation codes),
|
||||
* but only if the given key is found in the table.
|
||||
*/
|
||||
typedef void
|
||||
(* JSDHashClearEntry)(JSDHashTable *table, JSDHashEntryHdr *entry);
|
||||
|
||||
/*
|
||||
* Called when a table (whether allocated dynamically by itself, or nested in
|
||||
* a larger structure, or allocated on the stack) is finished. This callback
|
||||
* allows table->ops-specific code to finalize table->data.
|
||||
*/
|
||||
typedef void
|
||||
(* JSDHashFinalize) (JSDHashTable *table);
|
||||
|
||||
/*
|
||||
* Initialize a new entry, apart from keyHash. This function is called when
|
||||
* JS_DHashTableOperate's JS_DHASH_ADD case finds no existing entry for the
|
||||
* given key, and must add a new one. At that point, entry->keyHash is not
|
||||
* set yet, to avoid claiming the last free entry in a severely overloaded
|
||||
* table.
|
||||
*/
|
||||
typedef JSBool
|
||||
(* JSDHashInitEntry)(JSDHashTable *table, JSDHashEntryHdr *entry,
|
||||
const void *key);
|
||||
|
||||
/*
|
||||
* Finally, the "vtable" structure for JSDHashTable. The first eight hooks
|
||||
* must be provided by implementations; they're called unconditionally by the
|
||||
* generic jsdhash.c code. Hooks after these may be null.
|
||||
*
|
||||
* Summary of allocation-related hook usage with C++ placement new emphasis:
|
||||
* allocTable Allocate raw bytes with malloc, no ctors run.
|
||||
* freeTable Free raw bytes with free, no dtors run.
|
||||
* initEntry Call placement new using default key-based ctor.
|
||||
* Return JS_TRUE on success, JS_FALSE on error.
|
||||
* moveEntry Call placement new using copy ctor, run dtor on old
|
||||
* entry storage.
|
||||
* clearEntry Run dtor on entry.
|
||||
* finalize Stub unless table->data was initialized and needs to
|
||||
* be finalized.
|
||||
*
|
||||
* Note the reason why initEntry is optional: the default hooks (stubs) clear
|
||||
* entry storage: On successful JS_DHashTableOperate(tbl, key, JS_DHASH_ADD),
|
||||
* the returned entry pointer addresses an entry struct whose keyHash member
|
||||
* has been set non-zero, but all other entry members are still clear (null).
|
||||
* JS_DHASH_ADD callers can test such members to see whether the entry was
|
||||
* newly created by the JS_DHASH_ADD call that just succeeded. If placement
|
||||
* new or similar initialization is required, define an initEntry hook. Of
|
||||
* course, the clearEntry hook must zero or null appropriately.
|
||||
*
|
||||
* XXX assumes 0 is null for pointer types.
|
||||
*/
|
||||
struct JSDHashTableOps {
|
||||
/* Mandatory hooks. All implementations must provide these. */
|
||||
JSDHashAllocTable allocTable;
|
||||
JSDHashFreeTable freeTable;
|
||||
JSDHashHashKey hashKey;
|
||||
JSDHashMatchEntry matchEntry;
|
||||
JSDHashMoveEntry moveEntry;
|
||||
JSDHashClearEntry clearEntry;
|
||||
JSDHashFinalize finalize;
|
||||
|
||||
/* Optional hooks start here. If null, these are not called. */
|
||||
JSDHashInitEntry initEntry;
|
||||
};
|
||||
|
||||
/*
|
||||
* Default implementations for the above ops.
|
||||
*/
|
||||
extern JS_PUBLIC_API(void *)
|
||||
JS_DHashAllocTable(JSDHashTable *table, uint32_t nbytes);
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_DHashFreeTable(JSDHashTable *table, void *ptr);
|
||||
|
||||
extern JS_PUBLIC_API(JSDHashNumber)
|
||||
JS_DHashStringKey(JSDHashTable *table, const void *key);
|
||||
|
||||
/* A minimal entry contains a keyHash header and a void key pointer. */
|
||||
struct JSDHashEntryStub {
|
||||
JSDHashEntryHdr hdr;
|
||||
const void *key;
|
||||
};
|
||||
|
||||
extern JS_PUBLIC_API(JSDHashNumber)
|
||||
JS_DHashVoidPtrKeyStub(JSDHashTable *table, const void *key);
|
||||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_DHashMatchEntryStub(JSDHashTable *table,
|
||||
const JSDHashEntryHdr *entry,
|
||||
const void *key);
|
||||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_DHashMatchStringKey(JSDHashTable *table,
|
||||
const JSDHashEntryHdr *entry,
|
||||
const void *key);
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_DHashMoveEntryStub(JSDHashTable *table,
|
||||
const JSDHashEntryHdr *from,
|
||||
JSDHashEntryHdr *to);
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_DHashClearEntryStub(JSDHashTable *table, JSDHashEntryHdr *entry);
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_DHashFreeStringKey(JSDHashTable *table, JSDHashEntryHdr *entry);
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_DHashFinalizeStub(JSDHashTable *table);
|
||||
|
||||
/*
|
||||
* If you use JSDHashEntryStub or a subclass of it as your entry struct, and
|
||||
* if your entries move via memcpy and clear via memset(0), you can use these
|
||||
* stub operations.
|
||||
*/
|
||||
extern JS_PUBLIC_API(const JSDHashTableOps *)
|
||||
JS_DHashGetStubOps(void);
|
||||
|
||||
/*
|
||||
* Dynamically allocate a new JSDHashTable using malloc, initialize it using
|
||||
* JS_DHashTableInit, and return its address. Return null on malloc failure.
|
||||
* Note that the entry storage at table->entryStore will be allocated using
|
||||
* the ops->allocTable callback.
|
||||
*/
|
||||
extern JS_PUBLIC_API(JSDHashTable *)
|
||||
JS_NewDHashTable(const JSDHashTableOps *ops, void *data, uint32_t entrySize,
|
||||
uint32_t capacity);
|
||||
|
||||
/*
|
||||
* Finalize table's data, free its entry storage (via table->ops->freeTable),
|
||||
* and return the memory starting at table to the malloc heap.
|
||||
*/
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_DHashTableDestroy(JSDHashTable *table);
|
||||
|
||||
/*
|
||||
* Initialize table with ops, data, entrySize, and capacity. Capacity is a
|
||||
* guess for the smallest table size at which the table will usually be less
|
||||
* than 75% loaded (the table will grow or shrink as needed; capacity serves
|
||||
* only to avoid inevitable early growth from JS_DHASH_MIN_SIZE).
|
||||
*/
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_DHashTableInit(JSDHashTable *table, const JSDHashTableOps *ops, void *data,
|
||||
uint32_t entrySize, uint32_t capacity);
|
||||
|
||||
/*
|
||||
* Set maximum and minimum alpha for table. The defaults are 0.75 and .25.
|
||||
* maxAlpha must be in [0.5, 0.9375] for the default JS_DHASH_MIN_SIZE; or if
|
||||
* MinSize=JS_DHASH_MIN_SIZE <= 256, in [0.5, (float)(MinSize-1)/MinSize]; or
|
||||
* else in [0.5, 255.0/256]. minAlpha must be in [0, maxAlpha / 2), so that
|
||||
* we don't shrink on the very next remove after growing a table upon adding
|
||||
* an entry that brings entryCount past maxAlpha * tableSize.
|
||||
*/
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_DHashTableSetAlphaBounds(JSDHashTable *table,
|
||||
float maxAlpha,
|
||||
float minAlpha);
|
||||
|
||||
/*
|
||||
* Call this macro with k, the number of pointer-sized words wasted per entry
|
||||
* under chaining, to compute the minimum alpha at which double hashing still
|
||||
* beats chaining.
|
||||
*/
|
||||
#define JS_DHASH_MIN_ALPHA(table, k) \
|
||||
((float)((table)->entrySize / sizeof(void *) - 1) \
|
||||
/ ((table)->entrySize / sizeof(void *) + (k)))
|
||||
|
||||
/*
|
||||
* Default max/min alpha, and macros to compute the value for the |capacity|
|
||||
* parameter to JS_NewDHashTable and JS_DHashTableInit, given default or any
|
||||
* max alpha, such that adding entryCount entries right after initializing the
|
||||
* table will not require a reallocation (so JS_DHASH_ADD can't fail for those
|
||||
* JS_DHashTableOperate calls).
|
||||
*
|
||||
* NB: JS_DHASH_CAP is a helper macro meant for use only in JS_DHASH_CAPACITY.
|
||||
* Don't use it directly!
|
||||
*/
|
||||
#define JS_DHASH_DEFAULT_MAX_ALPHA 0.75
|
||||
#define JS_DHASH_DEFAULT_MIN_ALPHA 0.25
|
||||
|
||||
#define JS_DHASH_CAP(entryCount, maxAlpha) \
|
||||
((uint32_t)((double)(entryCount) / (maxAlpha)))
|
||||
|
||||
#define JS_DHASH_CAPACITY(entryCount, maxAlpha) \
|
||||
(JS_DHASH_CAP(entryCount, maxAlpha) + \
|
||||
(((JS_DHASH_CAP(entryCount, maxAlpha) * (uint8_t)(0x100 * (maxAlpha))) \
|
||||
>> 8) < (entryCount)))
|
||||
|
||||
#define JS_DHASH_DEFAULT_CAPACITY(entryCount) \
|
||||
JS_DHASH_CAPACITY(entryCount, JS_DHASH_DEFAULT_MAX_ALPHA)
|
||||
|
||||
/*
|
||||
* Finalize table's data, free its entry storage using table->ops->freeTable,
|
||||
* and leave its members unchanged from their last live values (which leaves
|
||||
* pointers dangling). If you want to burn cycles clearing table, it's up to
|
||||
* your code to call memset.
|
||||
*/
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_DHashTableFinish(JSDHashTable *table);
|
||||
|
||||
/*
|
||||
* To consolidate keyHash computation and table grow/shrink code, we use a
|
||||
* single entry point for lookup, add, and remove operations. The operation
|
||||
* codes are declared here, along with codes returned by JSDHashEnumerator
|
||||
* functions, which control JS_DHashTableEnumerate's behavior.
|
||||
*/
|
||||
typedef enum JSDHashOperator {
|
||||
JS_DHASH_LOOKUP = 0, /* lookup entry */
|
||||
JS_DHASH_ADD = 1, /* add entry */
|
||||
JS_DHASH_REMOVE = 2, /* remove entry, or enumerator says remove */
|
||||
JS_DHASH_NEXT = 0, /* enumerator says continue */
|
||||
JS_DHASH_STOP = 1 /* enumerator says stop */
|
||||
} JSDHashOperator;
|
||||
|
||||
/*
|
||||
* To lookup a key in table, call:
|
||||
*
|
||||
* entry = JS_DHashTableOperate(table, key, JS_DHASH_LOOKUP);
|
||||
*
|
||||
* If JS_DHASH_ENTRY_IS_BUSY(entry) is true, key was found and it identifies
|
||||
* entry. If JS_DHASH_ENTRY_IS_FREE(entry) is true, key was not found.
|
||||
*
|
||||
* To add an entry identified by key to table, call:
|
||||
*
|
||||
* entry = JS_DHashTableOperate(table, key, JS_DHASH_ADD);
|
||||
*
|
||||
* If entry is null upon return, then either the table is severely overloaded,
|
||||
* and memory can't be allocated for entry storage via table->ops->allocTable;
|
||||
* Or if table->ops->initEntry is non-null, the table->ops->initEntry op may
|
||||
* have returned false.
|
||||
*
|
||||
* Otherwise, entry->keyHash has been set so that JS_DHASH_ENTRY_IS_BUSY(entry)
|
||||
* is true, and it is up to the caller to initialize the key and value parts
|
||||
* of the entry sub-type, if they have not been set already (i.e. if entry was
|
||||
* not already in the table, and if the optional initEntry hook was not used).
|
||||
*
|
||||
* To remove an entry identified by key from table, call:
|
||||
*
|
||||
* (void) JS_DHashTableOperate(table, key, JS_DHASH_REMOVE);
|
||||
*
|
||||
* If key's entry is found, it is cleared (via table->ops->clearEntry) and
|
||||
* the entry is marked so that JS_DHASH_ENTRY_IS_FREE(entry). This operation
|
||||
* returns null unconditionally; you should ignore its return value.
|
||||
*/
|
||||
extern JS_PUBLIC_API(JSDHashEntryHdr *) JS_DHASH_FASTCALL
|
||||
JS_DHashTableOperate(JSDHashTable *table, const void *key, JSDHashOperator op);
|
||||
|
||||
/*
|
||||
* Remove an entry already accessed via LOOKUP or ADD.
|
||||
*
|
||||
* NB: this is a "raw" or low-level routine, intended to be used only where
|
||||
* the inefficiency of a full JS_DHashTableOperate (which rehashes in order
|
||||
* to find the entry given its key) is not tolerable. This function does not
|
||||
* shrink the table if it is underloaded. It does not update stats #ifdef
|
||||
* JS_DHASHMETER, either.
|
||||
*/
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_DHashTableRawRemove(JSDHashTable *table, JSDHashEntryHdr *entry);
|
||||
|
||||
/*
|
||||
* Enumerate entries in table using etor:
|
||||
*
|
||||
* count = JS_DHashTableEnumerate(table, etor, arg);
|
||||
*
|
||||
* JS_DHashTableEnumerate calls etor like so:
|
||||
*
|
||||
* op = etor(table, entry, number, arg);
|
||||
*
|
||||
* where number is a zero-based ordinal assigned to live entries according to
|
||||
* their order in table->entryStore.
|
||||
*
|
||||
* The return value, op, is treated as a set of flags. If op is JS_DHASH_NEXT,
|
||||
* then continue enumerating. If op contains JS_DHASH_REMOVE, then clear (via
|
||||
* table->ops->clearEntry) and free entry. Then we check whether op contains
|
||||
* JS_DHASH_STOP; if so, stop enumerating and return the number of live entries
|
||||
* that were enumerated so far. Return the total number of live entries when
|
||||
* enumeration completes normally.
|
||||
*
|
||||
* If etor calls JS_DHashTableOperate on table with op != JS_DHASH_LOOKUP, it
|
||||
* must return JS_DHASH_STOP; otherwise undefined behavior results.
|
||||
*
|
||||
* If any enumerator returns JS_DHASH_REMOVE, table->entryStore may be shrunk
|
||||
* or compressed after enumeration, but before JS_DHashTableEnumerate returns.
|
||||
* Such an enumerator therefore can't safely set aside entry pointers, but an
|
||||
* enumerator that never returns JS_DHASH_REMOVE can set pointers to entries
|
||||
* aside, e.g., to avoid copying live entries into an array of the entry type.
|
||||
* Copying entry pointers is cheaper, and safe so long as the caller of such a
|
||||
* "stable" Enumerate doesn't use the set-aside pointers after any call either
|
||||
* to PL_DHashTableOperate, or to an "unstable" form of Enumerate, which might
|
||||
* grow or shrink entryStore.
|
||||
*
|
||||
* If your enumerator wants to remove certain entries, but set aside pointers
|
||||
* to other entries that it retains, it can use JS_DHashTableRawRemove on the
|
||||
* entries to be removed, returning JS_DHASH_NEXT to skip them. Likewise, if
|
||||
* you want to remove entries, but for some reason you do not want entryStore
|
||||
* to be shrunk or compressed, you can call JS_DHashTableRawRemove safely on
|
||||
* the entry being enumerated, rather than returning JS_DHASH_REMOVE.
|
||||
*/
|
||||
typedef JSDHashOperator
|
||||
(* JSDHashEnumerator)(JSDHashTable *table, JSDHashEntryHdr *hdr, uint32_t number, void *arg);
|
||||
|
||||
extern JS_PUBLIC_API(uint32_t)
|
||||
JS_DHashTableEnumerate(JSDHashTable *table, JSDHashEnumerator etor, void *arg);
|
||||
|
||||
typedef size_t
|
||||
(* JSDHashSizeOfEntryExcludingThisFun)(JSDHashEntryHdr *hdr,
|
||||
JSMallocSizeOfFun mallocSizeOf,
|
||||
void *arg);
|
||||
|
||||
/**
|
||||
* Measure the size of the table's entry storage, and if
|
||||
* |sizeOfEntryExcludingThis| is non-NULL, measure the size of things pointed
|
||||
* to by entries. Doesn't measure |ops| because it's often shared between
|
||||
* tables, nor |data| because it's opaque.
|
||||
*/
|
||||
extern JS_PUBLIC_API(size_t)
|
||||
JS_DHashTableSizeOfExcludingThis(const JSDHashTable *table,
|
||||
JSDHashSizeOfEntryExcludingThisFun sizeOfEntryExcludingThis,
|
||||
JSMallocSizeOfFun mallocSizeOf,
|
||||
void *arg = NULL);
|
||||
|
||||
/**
|
||||
* Like JS_DHashTableSizeOfExcludingThis, but includes sizeof(*this).
|
||||
*/
|
||||
extern JS_PUBLIC_API(size_t)
|
||||
JS_DHashTableSizeOfIncludingThis(const JSDHashTable *table,
|
||||
JSDHashSizeOfEntryExcludingThisFun sizeOfEntryExcludingThis,
|
||||
JSMallocSizeOfFun mallocSizeOf,
|
||||
void *arg = NULL);
|
||||
|
||||
#ifdef DEBUG
|
||||
/**
|
||||
* Mark a table as immutable for the remainder of its lifetime. This
|
||||
* changes the implementation from ASSERTing one set of invariants to
|
||||
* ASSERTing a different set.
|
||||
*
|
||||
* When a table is NOT marked as immutable, the table implementation
|
||||
* asserts that the table is not mutated from its own callbacks. It
|
||||
* assumes the caller protects the table from being accessed on multiple
|
||||
* threads simultaneously.
|
||||
*
|
||||
* When the table is marked as immutable, the re-entry assertions will
|
||||
* no longer trigger erroneously due to multi-threaded access. Instead,
|
||||
* mutations will cause assertions.
|
||||
*/
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_DHashMarkTableImmutable(JSDHashTable *table);
|
||||
#endif
|
||||
|
||||
#ifdef JS_DHASHMETER
|
||||
#include <stdio.h>
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_DHashTableDumpMeter(JSDHashTable *table, JSDHashEnumerator dump, FILE *fp);
|
||||
#endif
|
||||
|
||||
JS_END_EXTERN_C
|
||||
|
||||
#endif /* jsdhash_h___ */
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,153 @@
|
|||
/* -*- Mode: C; tab-width: 8; 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 Mozilla Communicator client code, released
|
||||
* March 31, 1998.
|
||||
*
|
||||
* 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 of 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 jshash_h___
|
||||
#define jshash_h___
|
||||
|
||||
/*
|
||||
* API to portable hash table code.
|
||||
*/
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include "jstypes.h"
|
||||
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
||||
typedef uint32_t JSHashNumber;
|
||||
typedef struct JSHashEntry JSHashEntry;
|
||||
typedef struct JSHashTable JSHashTable;
|
||||
|
||||
#define JS_HASH_BITS 32
|
||||
#define JS_GOLDEN_RATIO 0x9E3779B9U
|
||||
|
||||
typedef JSHashNumber (* JSHashFunction)(const void *key);
|
||||
typedef int (* JSHashComparator)(const void *v1, const void *v2);
|
||||
typedef int (* JSHashEnumerator)(JSHashEntry *he, int i, void *arg);
|
||||
|
||||
/* Flag bits in JSHashEnumerator's return value */
|
||||
#define HT_ENUMERATE_NEXT 0 /* continue enumerating entries */
|
||||
#define HT_ENUMERATE_STOP 1 /* stop enumerating entries */
|
||||
#define HT_ENUMERATE_REMOVE 2 /* remove and free the current entry */
|
||||
|
||||
typedef struct JSHashAllocOps {
|
||||
void * (*allocTable)(void *pool, size_t size);
|
||||
void (*freeTable)(void *pool, void *item, size_t size);
|
||||
JSHashEntry * (*allocEntry)(void *pool, const void *key);
|
||||
void (*freeEntry)(void *pool, JSHashEntry *he, unsigned flag);
|
||||
} JSHashAllocOps;
|
||||
|
||||
#define HT_FREE_VALUE 0 /* just free the entry's value */
|
||||
#define HT_FREE_ENTRY 1 /* free value and entire entry */
|
||||
|
||||
struct JSHashEntry {
|
||||
JSHashEntry *next; /* hash chain linkage */
|
||||
JSHashNumber keyHash; /* key hash function result */
|
||||
const void *key; /* ptr to opaque key */
|
||||
void *value; /* ptr to opaque value */
|
||||
};
|
||||
|
||||
struct JSHashTable {
|
||||
JSHashEntry **buckets; /* vector of hash buckets */
|
||||
uint32_t nentries; /* number of entries in table */
|
||||
uint32_t shift; /* multiplicative hash shift */
|
||||
JSHashFunction keyHash; /* key hash function */
|
||||
JSHashComparator keyCompare; /* key comparison function */
|
||||
JSHashComparator valueCompare; /* value comparison function */
|
||||
JSHashAllocOps *allocOps; /* allocation operations */
|
||||
void *allocPriv; /* allocation private data */
|
||||
#ifdef JS_HASHMETER
|
||||
uint32_t nlookups; /* total number of lookups */
|
||||
uint32_t nsteps; /* number of hash chains traversed */
|
||||
uint32_t ngrows; /* number of table expansions */
|
||||
uint32_t nshrinks; /* number of table contractions */
|
||||
#endif
|
||||
};
|
||||
|
||||
/*
|
||||
* Create a new hash table.
|
||||
* If allocOps is null, use default allocator ops built on top of malloc().
|
||||
*/
|
||||
extern JS_PUBLIC_API(JSHashTable *)
|
||||
JS_NewHashTable(uint32_t n, JSHashFunction keyHash,
|
||||
JSHashComparator keyCompare, JSHashComparator valueCompare,
|
||||
JSHashAllocOps *allocOps, void *allocPriv);
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_HashTableDestroy(JSHashTable *ht);
|
||||
|
||||
/* Low level access methods */
|
||||
extern JS_PUBLIC_API(JSHashEntry **)
|
||||
JS_HashTableRawLookup(JSHashTable *ht, JSHashNumber keyHash, const void *key);
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern JS_PUBLIC_API(JSHashEntry *)
|
||||
JS_HashTableRawAdd(JSHashTable *ht, JSHashEntry **&hep, JSHashNumber keyHash,
|
||||
const void *key, void *value);
|
||||
#endif
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_HashTableRawRemove(JSHashTable *ht, JSHashEntry **hep, JSHashEntry *he);
|
||||
|
||||
/* Higher level access methods */
|
||||
extern JS_PUBLIC_API(JSHashEntry *)
|
||||
JS_HashTableAdd(JSHashTable *ht, const void *key, void *value);
|
||||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_HashTableRemove(JSHashTable *ht, const void *key);
|
||||
|
||||
extern JS_PUBLIC_API(int)
|
||||
JS_HashTableEnumerateEntries(JSHashTable *ht, JSHashEnumerator f, void *arg);
|
||||
|
||||
extern JS_PUBLIC_API(void *)
|
||||
JS_HashTableLookup(JSHashTable *ht, const void *key);
|
||||
|
||||
extern JS_PUBLIC_API(int)
|
||||
JS_HashTableDump(JSHashTable *ht, JSHashEnumerator dump, FILE *fp);
|
||||
|
||||
/* General-purpose C string hash function. */
|
||||
extern JS_PUBLIC_API(JSHashNumber)
|
||||
JS_HashString(const void *key);
|
||||
|
||||
/* Stub function just returns v1 == v2 */
|
||||
extern JS_PUBLIC_API(int)
|
||||
JS_CompareValues(const void *v1, const void *v2);
|
||||
|
||||
JS_END_EXTERN_C
|
||||
|
||||
#endif /* jshash_h___ */
|
|
@ -1,144 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** 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 Mozilla SpiderMonkey JavaScript 1.9 code, released
|
||||
* May 28, 2008.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Jim Blandy <jimb@mozilla.org>
|
||||
* Portions created by the Initial Developer are Copyright (C) 2009
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of 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 jsinttypes_h___
|
||||
#define jsinttypes_h___
|
||||
|
||||
#include "js-config.h"
|
||||
|
||||
/*
|
||||
* Types:
|
||||
* JSInt<N>, JSUint<N> (for <N> = 8, 16, 32, and 64)
|
||||
* JSIntPtr, JSUIntPtr
|
||||
*
|
||||
* JSInt<N> and JSUint<N> are signed and unsigned types known to be
|
||||
* <N> bits long. Note that neither JSInt8 nor JSUInt8 is necessarily
|
||||
* equivalent to a plain "char".
|
||||
*
|
||||
* JSIntPtr and JSUintPtr are signed and unsigned types capable of
|
||||
* holding an object pointer.
|
||||
*
|
||||
* Use these types in public SpiderMonkey header files, not the
|
||||
* corresponding types from the C standard <stdint.h> header. Windows
|
||||
* doesn't support <stdint.h>, and Microsoft says it has no plans to
|
||||
* do so in the future; this means that projects that embed
|
||||
* SpiderMonkey often take matters into their own hands and define the
|
||||
* standard types themselves. If we define them in our public
|
||||
* headers, our definitions may conflict with embedders' (see bug
|
||||
* 479258). The JS* types are in our namespace, and can be used
|
||||
* without troubling anyone.
|
||||
*
|
||||
* Internal SpiderMonkey code wishing to use the type names ISO C
|
||||
* defines in the standard header <stdint.h> can #include
|
||||
* "jsstdint.h", which provides those types regardless of whether
|
||||
* <stdint.h> itself is available.
|
||||
*/
|
||||
|
||||
#if defined(JS_HAVE_STDINT_H) || \
|
||||
defined(JS_SYS_TYPES_H_DEFINES_EXACT_SIZE_TYPES)
|
||||
|
||||
#if defined(JS_HAVE_STDINT_H)
|
||||
#include <stdint.h>
|
||||
#else
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
typedef int8_t JSInt8;
|
||||
typedef int16_t JSInt16;
|
||||
typedef int32_t JSInt32;
|
||||
typedef int64_t JSInt64;
|
||||
typedef intptr_t JSIntPtr;
|
||||
|
||||
typedef uint8_t JSUint8;
|
||||
typedef uint16_t JSUint16;
|
||||
typedef uint32_t JSUint32;
|
||||
typedef uint64_t JSUint64;
|
||||
typedef uintptr_t JSUintPtr;
|
||||
|
||||
#else
|
||||
|
||||
#if defined(JS_HAVE___INTN)
|
||||
|
||||
typedef __int8 JSInt8;
|
||||
typedef __int16 JSInt16;
|
||||
typedef __int32 JSInt32;
|
||||
typedef __int64 JSInt64;
|
||||
|
||||
typedef unsigned __int8 JSUint8;
|
||||
typedef unsigned __int16 JSUint16;
|
||||
typedef unsigned __int32 JSUint32;
|
||||
typedef unsigned __int64 JSUint64;
|
||||
|
||||
#elif defined(JS_INT8_TYPE)
|
||||
|
||||
typedef signed JS_INT8_TYPE JSInt8;
|
||||
typedef signed JS_INT16_TYPE JSInt16;
|
||||
typedef signed JS_INT32_TYPE JSInt32;
|
||||
typedef signed JS_INT64_TYPE JSInt64;
|
||||
|
||||
typedef unsigned JS_INT8_TYPE JSUint8;
|
||||
typedef unsigned JS_INT16_TYPE JSUint16;
|
||||
typedef unsigned JS_INT32_TYPE JSUint32;
|
||||
typedef unsigned JS_INT64_TYPE JSUint64;
|
||||
|
||||
#else
|
||||
#error "couldn't find exact-width integer types"
|
||||
#endif
|
||||
|
||||
/* Microsoft Visual C/C++ defines intptr_t and uintptr_t in <stddef.h>. */
|
||||
#if defined(JS_STDDEF_H_HAS_INTPTR_T)
|
||||
#include <stddef.h>
|
||||
typedef intptr_t JSIntPtr;
|
||||
typedef uintptr_t JSUintPtr;
|
||||
|
||||
/* Windows Mobile defines intptr_t and uintptr_t in <crtdefs.h>. Why not? */
|
||||
#elif defined(JS_CRTDEFS_H_HAS_INTPTR_T)
|
||||
#include <crtdefs.h>
|
||||
typedef intptr_t JSIntPtr;
|
||||
typedef uintptr_t JSUintPtr;
|
||||
|
||||
/* Failing that, the configure script will have found something. */
|
||||
#elif defined(JS_INTPTR_TYPE)
|
||||
typedef signed JS_INTPTR_TYPE JSIntPtr;
|
||||
typedef unsigned JS_INTPTR_TYPE JSUintPtr;
|
||||
|
||||
#else
|
||||
#error "couldn't find pointer-sized integer types"
|
||||
#endif
|
||||
|
||||
#endif /* JS_HAVE_STDINT_H */
|
||||
|
||||
#endif /* jsinttypes_h___ */
|
|
@ -0,0 +1,87 @@
|
|||
/* -*- Mode: C++; tab-width: 8; 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 Mozilla Communicator client code, released
|
||||
* March 31, 1998.
|
||||
*
|
||||
* 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 of 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 jslock_h__
|
||||
#define jslock_h__
|
||||
|
||||
#include "jsapi.h"
|
||||
|
||||
#ifdef JS_THREADSAFE
|
||||
|
||||
# include "pratom.h"
|
||||
# include "prlock.h"
|
||||
# include "prcvar.h"
|
||||
# include "prthread.h"
|
||||
# include "prinit.h"
|
||||
|
||||
# define JS_ATOMIC_INCREMENT(p) PR_ATOMIC_INCREMENT((PRInt32 *)(p))
|
||||
# define JS_ATOMIC_DECREMENT(p) PR_ATOMIC_DECREMENT((PRInt32 *)(p))
|
||||
# define JS_ATOMIC_ADD(p,v) PR_ATOMIC_ADD((PRInt32 *)(p), (PRInt32)(v))
|
||||
# define JS_ATOMIC_SET(p,v) PR_ATOMIC_SET((PRInt32 *)(p), (PRInt32)(v))
|
||||
|
||||
#else /* JS_THREADSAFE */
|
||||
|
||||
# define JS_ATOMIC_INCREMENT(p) (++*(p))
|
||||
# define JS_ATOMIC_DECREMENT(p) (--*(p))
|
||||
# define JS_ATOMIC_ADD(p,v) (*(p) += (v))
|
||||
# define JS_ATOMIC_SET(p,v) (*(p) = (v))
|
||||
|
||||
#endif /* JS_THREADSAFE */
|
||||
|
||||
namespace js {
|
||||
|
||||
class AutoAtomicIncrement
|
||||
{
|
||||
int32_t *p;
|
||||
JS_DECL_USE_GUARD_OBJECT_NOTIFIER
|
||||
|
||||
public:
|
||||
AutoAtomicIncrement(int32_t *p JS_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||
: p(p) {
|
||||
JS_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
JS_ATOMIC_INCREMENT(p);
|
||||
}
|
||||
|
||||
~AutoAtomicIncrement() {
|
||||
JS_ATOMIC_DECREMENT(p);
|
||||
}
|
||||
};
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
#endif /* jslock_h___ */
|
|
@ -1,167 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** 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 Mozilla Communicator client code, released
|
||||
* March 31, 1998.
|
||||
*
|
||||
* 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 of 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 ***** */
|
||||
|
||||
/*
|
||||
** File: jslong.h
|
||||
** Description: Portable access to 64 bit numerics
|
||||
**
|
||||
** Long-long (64-bit signed integer type) support. Some C compilers
|
||||
** don't support 64 bit integers yet, so we use these macros to
|
||||
** support both machines that do and don't.
|
||||
**/
|
||||
#ifndef jslong_h___
|
||||
#define jslong_h___
|
||||
|
||||
#include "jstypes.h"
|
||||
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
||||
#define JSLL_INIT(hi, lo) ((((JSInt64)(hi)) << 32) + (JSInt64)(lo))
|
||||
|
||||
/***********************************************************************
|
||||
** MACROS: JSLL_*
|
||||
** DESCRIPTION:
|
||||
** The following macros define portable access to the 64 bit
|
||||
** math facilities.
|
||||
**
|
||||
***********************************************************************/
|
||||
|
||||
/***********************************************************************
|
||||
** MACROS: JSLL_<relational operators>
|
||||
**
|
||||
** JSLL_IS_ZERO Test for zero
|
||||
** JSLL_EQ Test for equality
|
||||
** JSLL_NE Test for inequality
|
||||
** JSLL_GE_ZERO Test for zero or positive
|
||||
** JSLL_CMP Compare two values
|
||||
***********************************************************************/
|
||||
#define JSLL_IS_ZERO(a) ((a) == 0)
|
||||
#define JSLL_EQ(a, b) ((a) == (b))
|
||||
#define JSLL_NE(a, b) ((a) != (b))
|
||||
#define JSLL_GE_ZERO(a) ((a) >= 0)
|
||||
#define JSLL_CMP(a, op, b) ((JSInt64)(a) op (JSInt64)(b))
|
||||
#define JSLL_UCMP(a, op, b) ((JSUint64)(a) op (JSUint64)(b))
|
||||
|
||||
/***********************************************************************
|
||||
** MACROS: JSLL_<logical operators>
|
||||
**
|
||||
** JSLL_AND Logical and
|
||||
** JSLL_OR Logical or
|
||||
** JSLL_XOR Logical exclusion
|
||||
** JSLL_OR2 A disgusting deviation
|
||||
** JSLL_NOT Negation (one's compliment)
|
||||
***********************************************************************/
|
||||
#define JSLL_AND(r, a, b) ((r) = (a) & (b))
|
||||
#define JSLL_OR(r, a, b) ((r) = (a) | (b))
|
||||
#define JSLL_XOR(r, a, b) ((r) = (a) ^ (b))
|
||||
#define JSLL_OR2(r, a) ((r) = (r) | (a))
|
||||
#define JSLL_NOT(r, a) ((r) = ~(a))
|
||||
|
||||
/***********************************************************************
|
||||
** MACROS: JSLL_<mathematical operators>
|
||||
**
|
||||
** JSLL_NEG Negation (two's compliment)
|
||||
** JSLL_ADD Summation (two's compliment)
|
||||
** JSLL_SUB Difference (two's compliment)
|
||||
***********************************************************************/
|
||||
#define JSLL_NEG(r, a) ((r) = -(a))
|
||||
#define JSLL_ADD(r, a, b) ((r) = (a) + (b))
|
||||
#define JSLL_SUB(r, a, b) ((r) = (a) - (b))
|
||||
|
||||
/***********************************************************************
|
||||
** MACROS: JSLL_<mathematical operators>
|
||||
**
|
||||
** JSLL_MUL Product (two's compliment)
|
||||
** JSLL_DIV Quotient (two's compliment)
|
||||
** JSLL_MOD Modulus (two's compliment)
|
||||
***********************************************************************/
|
||||
#define JSLL_MUL(r, a, b) ((r) = (a) * (b))
|
||||
#define JSLL_DIV(r, a, b) ((r) = (a) / (b))
|
||||
#define JSLL_MOD(r, a, b) ((r) = (a) % (b))
|
||||
|
||||
/***********************************************************************
|
||||
** MACROS: JSLL_<shifting operators>
|
||||
**
|
||||
** JSLL_SHL Shift left [0..64] bits
|
||||
** JSLL_SHR Shift right [0..64] bits with sign extension
|
||||
** JSLL_USHR Unsigned shift right [0..64] bits
|
||||
** JSLL_ISHL Signed shift left [0..64] bits
|
||||
***********************************************************************/
|
||||
#define JSLL_SHL(r, a, b) ((r) = (JSInt64)(a) << (b))
|
||||
#define JSLL_SHR(r, a, b) ((r) = (JSInt64)(a) >> (b))
|
||||
#define JSLL_USHR(r, a, b) ((r) = (JSUint64)(a) >> (b))
|
||||
#define JSLL_ISHL(r, a, b) ((r) = (JSInt64)(a) << (b))
|
||||
|
||||
/***********************************************************************
|
||||
** MACROS: JSLL_<conversion operators>
|
||||
**
|
||||
** JSLL_L2I Convert to signed 32 bit
|
||||
** JSLL_L2UI Convert to unsigned 32 bit
|
||||
** JSLL_L2F Convert to floating point
|
||||
** JSLL_L2D Convert to floating point
|
||||
** JSLL_I2L Convert signed to 64 bit
|
||||
** JSLL_UI2L Convert unsigned to 64 bit
|
||||
** JSLL_F2L Convert float to 64 bit
|
||||
** JSLL_D2L Convert float to 64 bit
|
||||
***********************************************************************/
|
||||
#define JSLL_L2I(i, l) ((i) = (JSInt32)(l))
|
||||
#define JSLL_L2UI(ui, l) ((ui) = (JSUint32)(l))
|
||||
#define JSLL_L2F(f, l) ((f) = (JSFloat64)(l))
|
||||
#define JSLL_L2D(d, l) ((d) = (JSFloat64)(l))
|
||||
|
||||
#define JSLL_I2L(l, i) ((l) = (JSInt64)(i))
|
||||
#define JSLL_UI2L(l, ui) ((l) = (JSInt64)(ui))
|
||||
#define JSLL_F2L(l, f) ((l) = (JSInt64)(f))
|
||||
#define JSLL_D2L(l, d) ((l) = (JSInt64)(d))
|
||||
|
||||
/***********************************************************************
|
||||
** MACROS: JSLL_UDIVMOD
|
||||
** DESCRIPTION:
|
||||
** Produce both a quotient and a remainder given an unsigned
|
||||
** INPUTS: JSUint64 a: The dividend of the operation
|
||||
** JSUint64 b: The quotient of the operation
|
||||
** OUTPUTS: JSUint64 *qp: pointer to quotient
|
||||
** JSUint64 *rp: pointer to remainder
|
||||
***********************************************************************/
|
||||
#define JSLL_UDIVMOD(qp, rp, a, b) \
|
||||
(*(qp) = ((JSUint64)(a) / (b)), \
|
||||
*(rp) = ((JSUint64)(a) % (b)))
|
||||
|
||||
JS_END_EXTERN_C
|
||||
|
||||
#endif /* jslong_h___ */
|
|
@ -1,6 +1,4 @@
|
|||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
/* ***** 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
|
||||
|
@ -13,15 +11,15 @@
|
|||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Mozilla Communicator client code, released
|
||||
* March 31, 1998.
|
||||
* The Original Code is SpiderMonkey JSON.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998-1999
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Robert Sayre <sayrer@gmail.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
|
@ -37,19 +35,39 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef jscompat_h___
|
||||
#define jscompat_h___
|
||||
/*
|
||||
* Compatibility glue for various NSPR versions. We must always define int8,
|
||||
* int16, jsword, and so on to minimize differences with js/ref, no matter what
|
||||
* the NSPR typedef names may be.
|
||||
*/
|
||||
#include "jstypes.h"
|
||||
#include "jslong.h"
|
||||
#ifndef json_h___
|
||||
#define json_h___
|
||||
|
||||
typedef JSIntn intN;
|
||||
typedef JSUintn uintN;
|
||||
typedef JSUword jsuword;
|
||||
typedef JSWord jsword;
|
||||
typedef float float32;
|
||||
#endif /* jscompat_h___ */
|
||||
#include "jsprvtd.h"
|
||||
#include "jspubtd.h"
|
||||
|
||||
#include "js/Vector.h"
|
||||
|
||||
#define JSON_MAX_DEPTH 2048
|
||||
#define JSON_PARSER_BUFSIZE 1024
|
||||
|
||||
extern JSObject *
|
||||
js_InitJSONClass(JSContext *cx, JSObject *obj);
|
||||
|
||||
extern JSBool
|
||||
js_Stringify(JSContext *cx, js::Value *vp, JSObject *replacer, js::Value space,
|
||||
js::StringBuffer &sb);
|
||||
|
||||
/*
|
||||
* The type of JSON decoding to perform. Strict decoding is to-the-spec;
|
||||
* legacy decoding accepts a few non-JSON syntaxes historically accepted by the
|
||||
* implementation. (Full description of these deviations is deliberately
|
||||
* omitted.) New users should use strict decoding rather than legacy decoding,
|
||||
* as legacy decoding might be removed at a future time.
|
||||
*/
|
||||
enum DecodingMode { STRICT, LEGACY };
|
||||
|
||||
namespace js {
|
||||
|
||||
extern JS_FRIEND_API(JSBool)
|
||||
ParseJSONWithReviver(JSContext *cx, const jschar *chars, size_t length, const Value &filter,
|
||||
Value *vp, DecodingMode decodingMode = STRICT);
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
#endif /* json_h___ */
|
|
@ -1,198 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** 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 Mozilla Communicator client code, released
|
||||
* March 31, 1998.
|
||||
*
|
||||
* 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 of 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 ***** */
|
||||
|
||||
/*
|
||||
* This section typedefs the old 'native' types to the new PR<type>s.
|
||||
* These definitions are scheduled to be eliminated at the earliest
|
||||
* possible time. The NSPR API is implemented and documented using
|
||||
* the new definitions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Note that we test for PROTYPES_H, not JSOTYPES_H. This is to avoid
|
||||
* double-definitions of scalar types such as uint32, if NSPR's
|
||||
* protypes.h is also included.
|
||||
*/
|
||||
#ifndef PROTYPES_H
|
||||
#define PROTYPES_H
|
||||
|
||||
#ifdef XP_BEOS
|
||||
/* BeOS defines most int types in SupportDefs.h (int8, uint8, int16,
|
||||
* uint16, int32, uint32, int64, uint64), so in the interest of
|
||||
* not conflicting with other definitions elsewhere we have to skip the
|
||||
* #ifdef jungle below, duplicate some definitions, and do our stuff.
|
||||
*/
|
||||
#include <SupportDefs.h>
|
||||
|
||||
typedef JSUintn uintn;
|
||||
#ifndef _XP_Core_
|
||||
typedef JSIntn intn;
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
/* SVR4 typedef of uint is commonly found on UNIX machines. */
|
||||
#ifdef XP_UNIX
|
||||
#include <sys/types.h>
|
||||
#else
|
||||
typedef JSUintn uint;
|
||||
#endif
|
||||
|
||||
typedef JSUintn uintn;
|
||||
typedef JSUint64 uint64;
|
||||
typedef JSUint32 uint32;
|
||||
typedef JSUint16 uint16;
|
||||
typedef JSUint8 uint8;
|
||||
|
||||
#ifndef _XP_Core_
|
||||
typedef JSIntn intn;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* On AIX 4.3, sys/inttypes.h (which is included by sys/types.h, a very
|
||||
* common header file) defines the types int8, int16, int32, and int64.
|
||||
* So we don't define these four types here to avoid conflicts in case
|
||||
* the code also includes sys/types.h.
|
||||
*/
|
||||
#if defined(AIX) && defined(HAVE_SYS_INTTYPES_H)
|
||||
#include <sys/inttypes.h>
|
||||
#elif defined(__SUNPRO_C) || defined(__SUNPRO_CC)
|
||||
typedef JSInt64 int64;
|
||||
|
||||
/* Explicit signed keyword for bitfield types is required. */
|
||||
/* Some compilers may treat them as unsigned without it. */
|
||||
typedef signed int int32;
|
||||
typedef signed short int16;
|
||||
typedef signed char int8;
|
||||
#else
|
||||
typedef JSInt64 int64;
|
||||
|
||||
/* /usr/include/model.h on HP-UX defines int8, int16, and int32 */
|
||||
typedef JSInt32 int32;
|
||||
typedef JSInt16 int16;
|
||||
typedef JSInt8 int8;
|
||||
#endif /* AIX && HAVE_SYS_INTTYPES_H */
|
||||
|
||||
#endif /* XP_BEOS */
|
||||
|
||||
typedef JSFloat64 float64;
|
||||
|
||||
/* Re: jsbit.h */
|
||||
#define TEST_BIT JS_TEST_BIT
|
||||
#define SET_BIT JS_SET_BIT
|
||||
#define CLEAR_BIT JS_CLEAR_BIT
|
||||
|
||||
/* Re: prarena.h->plarena.h */
|
||||
#define PRArena PLArena
|
||||
#define PRArenaPool PLArenaPool
|
||||
#define PRArenaStats PLArenaStats
|
||||
#define PR_ARENA_ALIGN PL_ARENA_ALIGN
|
||||
#define PR_INIT_ARENA_POOL PL_INIT_ARENA_POOL
|
||||
#define PR_ARENA_ALLOCATE PL_ARENA_ALLOCATE
|
||||
#define PR_ARENA_GROW PL_ARENA_GROW
|
||||
#define PR_ARENA_MARK PL_ARENA_MARK
|
||||
#define PR_CLEAR_UNUSED PL_CLEAR_UNUSED
|
||||
#define PR_CLEAR_ARENA PL_CLEAR_ARENA
|
||||
#define PR_ARENA_RELEASE PL_ARENA_RELEASE
|
||||
#define PR_COUNT_ARENA PL_COUNT_ARENA
|
||||
#define PR_ARENA_DESTROY PL_ARENA_DESTROY
|
||||
#define PR_InitArenaPool PL_InitArenaPool
|
||||
#define PR_FreeArenaPool PL_FreeArenaPool
|
||||
#define PR_FinishArenaPool PL_FinishArenaPool
|
||||
#define PR_CompactArenaPool PL_CompactArenaPool
|
||||
#define PR_ArenaFinish PL_ArenaFinish
|
||||
#define PR_ArenaAllocate PL_ArenaAllocate
|
||||
#define PR_ArenaGrow PL_ArenaGrow
|
||||
#define PR_ArenaRelease PL_ArenaRelease
|
||||
#define PR_ArenaCountAllocation PL_ArenaCountAllocation
|
||||
#define PR_ArenaCountInplaceGrowth PL_ArenaCountInplaceGrowth
|
||||
#define PR_ArenaCountGrowth PL_ArenaCountGrowth
|
||||
#define PR_ArenaCountRelease PL_ArenaCountRelease
|
||||
#define PR_ArenaCountRetract PL_ArenaCountRetract
|
||||
|
||||
/* Re: prevent.h->plevent.h */
|
||||
#define PREvent PLEvent
|
||||
#define PREventQueue PLEventQueue
|
||||
#define PR_CreateEventQueue PL_CreateEventQueue
|
||||
#define PR_DestroyEventQueue PL_DestroyEventQueue
|
||||
#define PR_GetEventQueueMonitor PL_GetEventQueueMonitor
|
||||
#define PR_ENTER_EVENT_QUEUE_MONITOR PL_ENTER_EVENT_QUEUE_MONITOR
|
||||
#define PR_EXIT_EVENT_QUEUE_MONITOR PL_EXIT_EVENT_QUEUE_MONITOR
|
||||
#define PR_PostEvent PL_PostEvent
|
||||
#define PR_PostSynchronousEvent PL_PostSynchronousEvent
|
||||
#define PR_GetEvent PL_GetEvent
|
||||
#define PR_EventAvailable PL_EventAvailable
|
||||
#define PREventFunProc PLEventFunProc
|
||||
#define PR_MapEvents PL_MapEvents
|
||||
#define PR_RevokeEvents PL_RevokeEvents
|
||||
#define PR_ProcessPendingEvents PL_ProcessPendingEvents
|
||||
#define PR_WaitForEvent PL_WaitForEvent
|
||||
#define PR_EventLoop PL_EventLoop
|
||||
#define PR_GetEventQueueSelectFD PL_GetEventQueueSelectFD
|
||||
#define PRHandleEventProc PLHandleEventProc
|
||||
#define PRDestroyEventProc PLDestroyEventProc
|
||||
#define PR_InitEvent PL_InitEvent
|
||||
#define PR_GetEventOwner PL_GetEventOwner
|
||||
#define PR_HandleEvent PL_HandleEvent
|
||||
#define PR_DestroyEvent PL_DestroyEvent
|
||||
#define PR_DequeueEvent PL_DequeueEvent
|
||||
#define PR_GetMainEventQueue PL_GetMainEventQueue
|
||||
|
||||
/* Re: prhash.h->plhash.h */
|
||||
#define PRHashEntry PLHashEntry
|
||||
#define PRHashTable PLHashTable
|
||||
#define PRHashNumber PLHashNumber
|
||||
#define PRHashFunction PLHashFunction
|
||||
#define PRHashComparator PLHashComparator
|
||||
#define PRHashEnumerator PLHashEnumerator
|
||||
#define PRHashAllocOps PLHashAllocOps
|
||||
#define PR_NewHashTable PL_NewHashTable
|
||||
#define PR_HashTableDestroy PL_HashTableDestroy
|
||||
#define PR_HashTableRawLookup PL_HashTableRawLookup
|
||||
#define PR_HashTableRawAdd PL_HashTableRawAdd
|
||||
#define PR_HashTableRawRemove PL_HashTableRawRemove
|
||||
#define PR_HashTableAdd PL_HashTableAdd
|
||||
#define PR_HashTableRemove PL_HashTableRemove
|
||||
#define PR_HashTableEnumerateEntries PL_HashTableEnumerateEntries
|
||||
#define PR_HashTableLookup PL_HashTableLookup
|
||||
#define PR_HashTableDump PL_HashTableDump
|
||||
#define PR_HashString PL_HashString
|
||||
#define PR_CompareStrings PL_CompareStrings
|
||||
#define PR_CompareValues PL_CompareValues
|
||||
|
||||
#endif /* !defined(PROTYPES_H) */
|
|
@ -0,0 +1,163 @@
|
|||
/* -*- 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 mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* the Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Zack Weinberg <zweinberg@mozilla.com> (original author)
|
||||
*
|
||||
* 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 jsperf_h___
|
||||
#define jsperf_h___
|
||||
|
||||
#include "jsapi.h"
|
||||
|
||||
namespace JS {
|
||||
|
||||
/*
|
||||
* JS::PerfMeasurement is a generic way to access detailed performance
|
||||
* measurement APIs provided by your operating system. The details of
|
||||
* exactly how this works and what can be measured are highly
|
||||
* system-specific, but this interface is (one hopes) implementable
|
||||
* on top of all of them.
|
||||
*
|
||||
* To use this API, create a PerfMeasurement object, passing its
|
||||
* constructor a bitmask indicating which events you are interested
|
||||
* in. Thereafter, Start() zeroes all counters and starts timing;
|
||||
* Stop() stops timing again; and the counters for the events you
|
||||
* requested are available as data values after calling Stop(). The
|
||||
* object may be reused for many measurements.
|
||||
*/
|
||||
class JS_FRIEND_API(PerfMeasurement)
|
||||
{
|
||||
protected:
|
||||
// Implementation-specific data, if any.
|
||||
void* impl;
|
||||
|
||||
public:
|
||||
/*
|
||||
* Events that may be measured. Taken directly from the list of
|
||||
* "generalized hardware performance event types" in the Linux
|
||||
* perf_event API, plus some of the "software events".
|
||||
*/
|
||||
enum EventMask {
|
||||
CPU_CYCLES = 0x00000001,
|
||||
INSTRUCTIONS = 0x00000002,
|
||||
CACHE_REFERENCES = 0x00000004,
|
||||
CACHE_MISSES = 0x00000008,
|
||||
BRANCH_INSTRUCTIONS = 0x00000010,
|
||||
BRANCH_MISSES = 0x00000020,
|
||||
BUS_CYCLES = 0x00000040,
|
||||
PAGE_FAULTS = 0x00000080,
|
||||
MAJOR_PAGE_FAULTS = 0x00000100,
|
||||
CONTEXT_SWITCHES = 0x00000200,
|
||||
CPU_MIGRATIONS = 0x00000400,
|
||||
|
||||
ALL = 0x000007ff,
|
||||
NUM_MEASURABLE_EVENTS = 11
|
||||
};
|
||||
|
||||
/*
|
||||
* Bitmask of events that will be measured when this object is
|
||||
* active (between Start() and Stop()). This may differ from the
|
||||
* bitmask passed to the constructor if the platform does not
|
||||
* support measuring all of the requested events.
|
||||
*/
|
||||
const EventMask eventsMeasured;
|
||||
|
||||
/*
|
||||
* Counters for each measurable event.
|
||||
* Immediately after one of these objects is created, all of the
|
||||
* counters for enabled events will be zero, and all of the
|
||||
* counters for disabled events will be uint64_t(-1).
|
||||
*/
|
||||
uint64_t cpu_cycles;
|
||||
uint64_t instructions;
|
||||
uint64_t cache_references;
|
||||
uint64_t cache_misses;
|
||||
uint64_t branch_instructions;
|
||||
uint64_t branch_misses;
|
||||
uint64_t bus_cycles;
|
||||
uint64_t page_faults;
|
||||
uint64_t major_page_faults;
|
||||
uint64_t context_switches;
|
||||
uint64_t cpu_migrations;
|
||||
|
||||
/*
|
||||
* Prepare to measure the indicated set of events. If not all of
|
||||
* the requested events can be measured on the current platform,
|
||||
* then the eventsMeasured bitmask will only include the subset of
|
||||
* |toMeasure| corresponding to the events that can be measured.
|
||||
*/
|
||||
PerfMeasurement(EventMask toMeasure);
|
||||
|
||||
/* Done with this set of measurements, tear down OS-level state. */
|
||||
~PerfMeasurement();
|
||||
|
||||
/* Start a measurement cycle. */
|
||||
void start();
|
||||
|
||||
/*
|
||||
* End a measurement cycle, and for each enabled counter, add the
|
||||
* number of measured events of that type to the appropriate
|
||||
* visible variable.
|
||||
*/
|
||||
void stop();
|
||||
|
||||
/* Reset all enabled counters to zero. */
|
||||
void reset();
|
||||
|
||||
/*
|
||||
* True if this platform supports measuring _something_, i.e. it's
|
||||
* not using the stub implementation.
|
||||
*/
|
||||
static bool canMeasureSomething();
|
||||
};
|
||||
|
||||
/* Inject a Javascript wrapper around the above C++ class into the
|
||||
* Javascript object passed as an argument (this will normally be a
|
||||
* global object). The JS-visible API is identical to the C++ API.
|
||||
*/
|
||||
extern JS_FRIEND_API(JSObject*)
|
||||
RegisterPerfMeasurement(JSContext *cx, JSObject *global);
|
||||
|
||||
/*
|
||||
* Given a jsval which contains an instance of the aforementioned
|
||||
* wrapper class, extract the C++ object. Returns NULL if the
|
||||
* jsval is not an instance of the wrapper.
|
||||
*/
|
||||
extern JS_FRIEND_API(PerfMeasurement*)
|
||||
ExtractPerfMeasurement(jsval wrapper);
|
||||
|
||||
} // namespace JS
|
||||
|
||||
#endif // jsperf_h___
|
|
@ -0,0 +1,115 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** 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 Mozilla Communicator client code, released
|
||||
* March 31, 1998.
|
||||
*
|
||||
* 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 of 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 jsprf_h___
|
||||
#define jsprf_h___
|
||||
|
||||
/*
|
||||
** API for PR printf like routines. Supports the following formats
|
||||
** %d - decimal
|
||||
** %u - unsigned decimal
|
||||
** %x - unsigned hex
|
||||
** %X - unsigned uppercase hex
|
||||
** %o - unsigned octal
|
||||
** %hd, %hu, %hx, %hX, %ho - 16-bit versions of above
|
||||
** %ld, %lu, %lx, %lX, %lo - 32-bit versions of above
|
||||
** %lld, %llu, %llx, %llX, %llo - 64 bit versions of above
|
||||
** %s - string
|
||||
** %hs - 16-bit version of above (only available if js_CStringsAreUTF8)
|
||||
** %c - character
|
||||
** %hc - 16-bit version of above (only available if js_CStringsAreUTF8)
|
||||
** %p - pointer (deals with machine dependent pointer size)
|
||||
** %f - float
|
||||
** %g - float
|
||||
*/
|
||||
#include "jstypes.h"
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
||||
/*
|
||||
** sprintf into a fixed size buffer. Guarantees that a NUL is at the end
|
||||
** of the buffer. Returns the length of the written output, NOT including
|
||||
** the NUL, or (uint32_t)-1 if an error occurs.
|
||||
*/
|
||||
extern JS_PUBLIC_API(uint32_t) JS_snprintf(char *out, uint32_t outlen, const char *fmt, ...);
|
||||
|
||||
/*
|
||||
** sprintf into a malloc'd buffer. Return a pointer to the malloc'd
|
||||
** buffer on success, NULL on failure. Call "JS_smprintf_free" to release
|
||||
** the memory returned.
|
||||
*/
|
||||
extern JS_PUBLIC_API(char*) JS_smprintf(const char *fmt, ...);
|
||||
|
||||
/*
|
||||
** Free the memory allocated, for the caller, by JS_smprintf
|
||||
*/
|
||||
extern JS_PUBLIC_API(void) JS_smprintf_free(char *mem);
|
||||
|
||||
/*
|
||||
** "append" sprintf into a malloc'd buffer. "last" is the last value of
|
||||
** the malloc'd buffer. sprintf will append data to the end of last,
|
||||
** growing it as necessary using realloc. If last is NULL, JS_sprintf_append
|
||||
** will allocate the initial string. The return value is the new value of
|
||||
** last for subsequent calls, or NULL if there is a malloc failure.
|
||||
*/
|
||||
extern JS_PUBLIC_API(char*) JS_sprintf_append(char *last, const char *fmt, ...);
|
||||
|
||||
/*
|
||||
** sprintf into a function. The function "f" is called with a string to
|
||||
** place into the output. "arg" is an opaque pointer used by the stuff
|
||||
** function to hold any state needed to do the storage of the output
|
||||
** data. The return value is a count of the number of characters fed to
|
||||
** the stuff function, or (uint32_t)-1 if an error occurs.
|
||||
*/
|
||||
typedef int (*JSStuffFunc)(void *arg, const char *s, uint32_t slen);
|
||||
|
||||
extern JS_PUBLIC_API(uint32_t) JS_sxprintf(JSStuffFunc f, void *arg, const char *fmt, ...);
|
||||
|
||||
/*
|
||||
** va_list forms of the above.
|
||||
*/
|
||||
extern JS_PUBLIC_API(uint32_t) JS_vsnprintf(char *out, uint32_t outlen, const char *fmt, va_list ap);
|
||||
extern JS_PUBLIC_API(char*) JS_vsmprintf(const char *fmt, va_list ap);
|
||||
extern JS_PUBLIC_API(char*) JS_vsprintf_append(char *last, const char *fmt, va_list ap);
|
||||
extern JS_PUBLIC_API(uint32_t) JS_vsxprintf(JSStuffFunc f, void *arg, const char *fmt, va_list ap);
|
||||
|
||||
JS_END_EXTERN_C
|
||||
|
||||
#endif /* jsprf_h___ */
|
|
@ -50,20 +50,14 @@
|
|||
# define XMLFILTER_INIT js_InitNullClass
|
||||
#endif
|
||||
|
||||
#if JS_HAS_GENERATORS
|
||||
# define GENERATOR_INIT js_InitIteratorClasses
|
||||
#else
|
||||
# define GENERATOR_INIT js_InitNullClass
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Enumerator codes in the second column must not change -- they are part of
|
||||
* the JS XDR API. Client modules including jsproto.tbl should consider
|
||||
* wrapping the inclusion with JS_BEGIN_EXTERN_C and JS_END_EXTERN_C.
|
||||
*/
|
||||
JS_PROTO(Null, 0, js_InitNullClass)
|
||||
JS_PROTO(Object, 1, js_InitFunctionAndObjectClasses)
|
||||
JS_PROTO(Function, 2, js_InitFunctionAndObjectClasses)
|
||||
JS_PROTO(Object, 1, js_InitObjectClass)
|
||||
JS_PROTO(Function, 2, js_InitFunctionClass)
|
||||
JS_PROTO(Array, 3, js_InitArrayClass)
|
||||
JS_PROTO(Boolean, 4, js_InitBooleanClass)
|
||||
JS_PROTO(JSON, 5, js_InitJSONClass)
|
||||
|
@ -75,33 +69,32 @@ JS_PROTO(RegExp, 10, js_InitRegExpClass)
|
|||
JS_PROTO(XML, 11, XML_INIT)
|
||||
JS_PROTO(Namespace, 12, NAMESPACE_INIT)
|
||||
JS_PROTO(QName, 13, QNAME_INIT)
|
||||
JS_PROTO(Reflect, 14, js_InitReflectClass)
|
||||
JS_PROTO(ASTNode, 15, js_InitReflectClass)
|
||||
JS_PROTO(Error, 16, js_InitExceptionClasses)
|
||||
JS_PROTO(InternalError, 17, js_InitExceptionClasses)
|
||||
JS_PROTO(EvalError, 18, js_InitExceptionClasses)
|
||||
JS_PROTO(RangeError, 19, js_InitExceptionClasses)
|
||||
JS_PROTO(ReferenceError, 20, js_InitExceptionClasses)
|
||||
JS_PROTO(SyntaxError, 21, js_InitExceptionClasses)
|
||||
JS_PROTO(TypeError, 22, js_InitExceptionClasses)
|
||||
JS_PROTO(URIError, 23, js_InitExceptionClasses)
|
||||
JS_PROTO(Generator, 24, GENERATOR_INIT)
|
||||
JS_PROTO(Iterator, 25, js_InitIteratorClasses)
|
||||
JS_PROTO(StopIteration, 26, js_InitIteratorClasses)
|
||||
JS_PROTO(ArrayBuffer, 27, js_InitTypedArrayClasses)
|
||||
JS_PROTO(Int8Array, 28, js_InitTypedArrayClasses)
|
||||
JS_PROTO(Uint8Array, 29, js_InitTypedArrayClasses)
|
||||
JS_PROTO(Int16Array, 30, js_InitTypedArrayClasses)
|
||||
JS_PROTO(Uint16Array, 31, js_InitTypedArrayClasses)
|
||||
JS_PROTO(Int32Array, 32, js_InitTypedArrayClasses)
|
||||
JS_PROTO(Uint32Array, 33, js_InitTypedArrayClasses)
|
||||
JS_PROTO(Float32Array, 34, js_InitTypedArrayClasses)
|
||||
JS_PROTO(Float64Array, 35, js_InitTypedArrayClasses)
|
||||
JS_PROTO(Uint8ClampedArray, 36, js_InitTypedArrayClasses)
|
||||
JS_PROTO(Proxy, 37, js_InitProxyClass)
|
||||
JS_PROTO(AnyName, 38, js_InitNullClass)
|
||||
JS_PROTO(Error, 14, js_InitExceptionClasses)
|
||||
JS_PROTO(InternalError, 15, js_InitExceptionClasses)
|
||||
JS_PROTO(EvalError, 16, js_InitExceptionClasses)
|
||||
JS_PROTO(RangeError, 17, js_InitExceptionClasses)
|
||||
JS_PROTO(ReferenceError, 18, js_InitExceptionClasses)
|
||||
JS_PROTO(SyntaxError, 19, js_InitExceptionClasses)
|
||||
JS_PROTO(TypeError, 20, js_InitExceptionClasses)
|
||||
JS_PROTO(URIError, 21, js_InitExceptionClasses)
|
||||
JS_PROTO(Iterator, 22, js_InitIteratorClasses)
|
||||
JS_PROTO(StopIteration, 23, js_InitIteratorClasses)
|
||||
JS_PROTO(ArrayBuffer, 24, js_InitTypedArrayClasses)
|
||||
JS_PROTO(Int8Array, 25, js_InitTypedArrayClasses)
|
||||
JS_PROTO(Uint8Array, 26, js_InitTypedArrayClasses)
|
||||
JS_PROTO(Int16Array, 27, js_InitTypedArrayClasses)
|
||||
JS_PROTO(Uint16Array, 28, js_InitTypedArrayClasses)
|
||||
JS_PROTO(Int32Array, 29, js_InitTypedArrayClasses)
|
||||
JS_PROTO(Uint32Array, 30, js_InitTypedArrayClasses)
|
||||
JS_PROTO(Float32Array, 31, js_InitTypedArrayClasses)
|
||||
JS_PROTO(Float64Array, 32, js_InitTypedArrayClasses)
|
||||
JS_PROTO(Uint8ClampedArray, 33, js_InitTypedArrayClasses)
|
||||
JS_PROTO(Proxy, 34, js_InitProxyClass)
|
||||
JS_PROTO(AnyName, 35, js_InitNullClass)
|
||||
JS_PROTO(WeakMap, 36, js_InitWeakMapClass)
|
||||
JS_PROTO(Map, 37, js_InitMapClass)
|
||||
JS_PROTO(Set, 38, js_InitSetClass)
|
||||
|
||||
#undef XML_INIT
|
||||
#undef NAMESPACE_INIT
|
||||
#undef QNAME_INIT
|
||||
#undef GENERATOR_INIT
|
||||
|
|
|
@ -0,0 +1,239 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=4 sw=4 et tw=99:
|
||||
*
|
||||
* ***** 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 Mozilla SpiderMonkey JavaScript 1.9 code, released
|
||||
* May 28, 2008.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Foundation
|
||||
* Portions created by the Initial Developer are Copyright (C) 2009
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Andreas Gal <gal@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of 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 jsproxy_h___
|
||||
#define jsproxy_h___
|
||||
|
||||
#include "jsapi.h"
|
||||
#include "jsfriendapi.h"
|
||||
|
||||
namespace js {
|
||||
|
||||
/* Base class for all C++ proxy handlers. */
|
||||
class JS_FRIEND_API(ProxyHandler) {
|
||||
void *mFamily;
|
||||
public:
|
||||
explicit ProxyHandler(void *family);
|
||||
virtual ~ProxyHandler();
|
||||
|
||||
/* ES5 Harmony fundamental proxy traps. */
|
||||
virtual bool getPropertyDescriptor(JSContext *cx, JSObject *proxy, jsid id, bool set,
|
||||
PropertyDescriptor *desc) = 0;
|
||||
virtual bool getOwnPropertyDescriptor(JSContext *cx, JSObject *proxy, jsid id, bool set,
|
||||
PropertyDescriptor *desc) = 0;
|
||||
virtual bool defineProperty(JSContext *cx, JSObject *proxy, jsid id,
|
||||
PropertyDescriptor *desc) = 0;
|
||||
virtual bool getOwnPropertyNames(JSContext *cx, JSObject *proxy, AutoIdVector &props) = 0;
|
||||
virtual bool delete_(JSContext *cx, JSObject *proxy, jsid id, bool *bp) = 0;
|
||||
virtual bool enumerate(JSContext *cx, JSObject *proxy, AutoIdVector &props) = 0;
|
||||
virtual bool fix(JSContext *cx, JSObject *proxy, Value *vp) = 0;
|
||||
|
||||
/* ES5 Harmony derived proxy traps. */
|
||||
virtual bool has(JSContext *cx, JSObject *proxy, jsid id, bool *bp);
|
||||
virtual bool hasOwn(JSContext *cx, JSObject *proxy, jsid id, bool *bp);
|
||||
virtual bool get(JSContext *cx, JSObject *proxy, JSObject *receiver, jsid id, Value *vp);
|
||||
virtual bool set(JSContext *cx, JSObject *proxy, JSObject *receiver, jsid id, bool strict,
|
||||
Value *vp);
|
||||
virtual bool keys(JSContext *cx, JSObject *proxy, AutoIdVector &props);
|
||||
virtual bool iterate(JSContext *cx, JSObject *proxy, unsigned flags, Value *vp);
|
||||
|
||||
/* Spidermonkey extensions. */
|
||||
virtual bool call(JSContext *cx, JSObject *proxy, unsigned argc, Value *vp);
|
||||
virtual bool construct(JSContext *cx, JSObject *proxy, unsigned argc, Value *argv, Value *rval);
|
||||
virtual bool nativeCall(JSContext *cx, JSObject *proxy, Class *clasp, Native native, CallArgs args);
|
||||
virtual bool hasInstance(JSContext *cx, JSObject *proxy, const Value *vp, bool *bp);
|
||||
virtual JSType typeOf(JSContext *cx, JSObject *proxy);
|
||||
virtual bool objectClassIs(JSObject *obj, ESClassValue classValue, JSContext *cx);
|
||||
virtual JSString *obj_toString(JSContext *cx, JSObject *proxy);
|
||||
virtual JSString *fun_toString(JSContext *cx, JSObject *proxy, unsigned indent);
|
||||
virtual bool regexp_toShared(JSContext *cx, JSObject *proxy, RegExpGuard *g);
|
||||
virtual bool defaultValue(JSContext *cx, JSObject *obj, JSType hint, Value *vp);
|
||||
virtual bool iteratorNext(JSContext *cx, JSObject *proxy, Value *vp);
|
||||
virtual void finalize(JSFreeOp *fop, JSObject *proxy);
|
||||
virtual void trace(JSTracer *trc, JSObject *proxy);
|
||||
virtual bool getElementIfPresent(JSContext *cx, JSObject *obj, JSObject *receiver,
|
||||
uint32_t index, Value *vp, bool *present);
|
||||
|
||||
virtual bool isOuterWindow() {
|
||||
return false;
|
||||
}
|
||||
|
||||
inline void *family() {
|
||||
return mFamily;
|
||||
}
|
||||
};
|
||||
|
||||
/* Dispatch point for handlers that executes the appropriate C++ or scripted traps. */
|
||||
class Proxy {
|
||||
public:
|
||||
/* ES5 Harmony fundamental proxy traps. */
|
||||
static bool getPropertyDescriptor(JSContext *cx, JSObject *proxy, jsid id, bool set,
|
||||
PropertyDescriptor *desc);
|
||||
static bool getPropertyDescriptor(JSContext *cx, JSObject *proxy, jsid id, bool set, Value *vp);
|
||||
static bool getOwnPropertyDescriptor(JSContext *cx, JSObject *proxy, jsid id, bool set,
|
||||
PropertyDescriptor *desc);
|
||||
static bool getOwnPropertyDescriptor(JSContext *cx, JSObject *proxy, jsid id, bool set,
|
||||
Value *vp);
|
||||
static bool defineProperty(JSContext *cx, JSObject *proxy, jsid id, PropertyDescriptor *desc);
|
||||
static bool defineProperty(JSContext *cx, JSObject *proxy, jsid id, const Value &v);
|
||||
static bool getOwnPropertyNames(JSContext *cx, JSObject *proxy, AutoIdVector &props);
|
||||
static bool delete_(JSContext *cx, JSObject *proxy, jsid id, bool *bp);
|
||||
static bool enumerate(JSContext *cx, JSObject *proxy, AutoIdVector &props);
|
||||
static bool fix(JSContext *cx, JSObject *proxy, Value *vp);
|
||||
|
||||
/* ES5 Harmony derived proxy traps. */
|
||||
static bool has(JSContext *cx, JSObject *proxy, jsid id, bool *bp);
|
||||
static bool hasOwn(JSContext *cx, JSObject *proxy, jsid id, bool *bp);
|
||||
static bool get(JSContext *cx, JSObject *proxy, JSObject *receiver, jsid id, Value *vp);
|
||||
static bool getElementIfPresent(JSContext *cx, JSObject *proxy, JSObject *receiver,
|
||||
uint32_t index, Value *vp, bool *present);
|
||||
static bool set(JSContext *cx, JSObject *proxy, JSObject *receiver, jsid id, bool strict,
|
||||
Value *vp);
|
||||
static bool keys(JSContext *cx, JSObject *proxy, AutoIdVector &props);
|
||||
static bool iterate(JSContext *cx, JSObject *proxy, unsigned flags, Value *vp);
|
||||
|
||||
/* Spidermonkey extensions. */
|
||||
static bool call(JSContext *cx, JSObject *proxy, unsigned argc, Value *vp);
|
||||
static bool construct(JSContext *cx, JSObject *proxy, unsigned argc, Value *argv, Value *rval);
|
||||
static bool nativeCall(JSContext *cx, JSObject *proxy, Class *clasp, Native native, CallArgs args);
|
||||
static bool hasInstance(JSContext *cx, JSObject *proxy, const Value *vp, bool *bp);
|
||||
static JSType typeOf(JSContext *cx, JSObject *proxy);
|
||||
static bool objectClassIs(JSObject *obj, ESClassValue classValue, JSContext *cx);
|
||||
static JSString *obj_toString(JSContext *cx, JSObject *proxy);
|
||||
static JSString *fun_toString(JSContext *cx, JSObject *proxy, unsigned indent);
|
||||
static bool regexp_toShared(JSContext *cx, JSObject *proxy, RegExpGuard *g);
|
||||
static bool defaultValue(JSContext *cx, JSObject *obj, JSType hint, Value *vp);
|
||||
static bool iteratorNext(JSContext *cx, JSObject *proxy, Value *vp);
|
||||
};
|
||||
|
||||
inline bool IsObjectProxyClass(const Class *clasp)
|
||||
{
|
||||
return clasp == &js::ObjectProxyClass || clasp == &js::OuterWindowProxyClass;
|
||||
}
|
||||
|
||||
inline bool IsFunctionProxyClass(const Class *clasp)
|
||||
{
|
||||
return clasp == &js::FunctionProxyClass;
|
||||
}
|
||||
|
||||
inline bool IsObjectProxy(const JSObject *obj)
|
||||
{
|
||||
return IsObjectProxyClass(GetObjectClass(obj));
|
||||
}
|
||||
|
||||
inline bool IsFunctionProxy(const JSObject *obj)
|
||||
{
|
||||
return IsFunctionProxyClass(GetObjectClass(obj));
|
||||
}
|
||||
|
||||
inline bool IsProxy(const JSObject *obj)
|
||||
{
|
||||
Class *clasp = GetObjectClass(obj);
|
||||
return IsObjectProxyClass(clasp) || IsFunctionProxyClass(clasp);
|
||||
}
|
||||
|
||||
/* Shared between object and function proxies. */
|
||||
const uint32_t JSSLOT_PROXY_HANDLER = 0;
|
||||
const uint32_t JSSLOT_PROXY_PRIVATE = 1;
|
||||
const uint32_t JSSLOT_PROXY_EXTRA = 2;
|
||||
/* Function proxies only. */
|
||||
const uint32_t JSSLOT_PROXY_CALL = 4;
|
||||
const uint32_t JSSLOT_PROXY_CONSTRUCT = 5;
|
||||
|
||||
inline ProxyHandler *
|
||||
GetProxyHandler(const JSObject *obj)
|
||||
{
|
||||
JS_ASSERT(IsProxy(obj));
|
||||
return (ProxyHandler *) GetReservedSlot(obj, JSSLOT_PROXY_HANDLER).toPrivate();
|
||||
}
|
||||
|
||||
inline const Value &
|
||||
GetProxyPrivate(const JSObject *obj)
|
||||
{
|
||||
JS_ASSERT(IsProxy(obj));
|
||||
return GetReservedSlot(obj, JSSLOT_PROXY_PRIVATE);
|
||||
}
|
||||
|
||||
inline const Value &
|
||||
GetProxyExtra(const JSObject *obj, size_t n)
|
||||
{
|
||||
JS_ASSERT(IsProxy(obj));
|
||||
return GetReservedSlot(obj, JSSLOT_PROXY_EXTRA + n);
|
||||
}
|
||||
|
||||
inline void
|
||||
SetProxyExtra(JSObject *obj, size_t n, const Value &extra)
|
||||
{
|
||||
JS_ASSERT(IsProxy(obj));
|
||||
JS_ASSERT(n <= 1);
|
||||
SetReservedSlot(obj, JSSLOT_PROXY_EXTRA + n, extra);
|
||||
}
|
||||
|
||||
|
||||
inline void
|
||||
SetProxyHandler(JSObject *obj, ProxyHandler *handler)
|
||||
{
|
||||
JS_ASSERT(IsProxy(obj));
|
||||
SetReservedSlot(obj, JSSLOT_PROXY_HANDLER, PrivateValue(handler));
|
||||
}
|
||||
|
||||
inline void
|
||||
SetProxyPrivate(JSObject *obj, const Value &value)
|
||||
{
|
||||
JS_ASSERT(IsProxy(obj));
|
||||
SetReservedSlot(obj, JSSLOT_PROXY_PRIVATE, value);
|
||||
}
|
||||
|
||||
JS_FRIEND_API(JSObject *)
|
||||
NewProxyObject(JSContext *cx, ProxyHandler *handler, const Value &priv,
|
||||
JSObject *proto, JSObject *parent,
|
||||
JSObject *call = NULL, JSObject *construct = NULL);
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
||||
extern JS_FRIEND_API(JSObject *)
|
||||
js_InitProxyClass(JSContext *cx, JSObject *obj);
|
||||
|
||||
JS_END_EXTERN_C
|
||||
|
||||
#endif
|
|
@ -0,0 +1,455 @@
|
|||
/* -*- Mode: C++; tab-width: 8; 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 Mozilla Communicator client code, released
|
||||
* March 31, 1998.
|
||||
*
|
||||
* 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 of 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 jsprvtd_h___
|
||||
#define jsprvtd_h___
|
||||
/*
|
||||
* JS private typename definitions.
|
||||
*
|
||||
* This header is included only in other .h files, for convenience and for
|
||||
* simplicity of type naming. The alternative for structures is to use tags,
|
||||
* which are named the same as their typedef names (legal in C/C++, and less
|
||||
* noisy than suffixing the typedef name with "Struct" or "Str"). Instead,
|
||||
* all .h files that include this file may use the same typedef name, whether
|
||||
* declaring a pointer to struct type, or defining a member of struct type.
|
||||
*
|
||||
* A few fundamental scalar types are defined here too. Neither the scalar
|
||||
* nor the struct typedefs should change much, therefore the nearly-global
|
||||
* make dependency induced by this file should not prove painful.
|
||||
*/
|
||||
|
||||
#include "jsapi.h"
|
||||
#include "jsutil.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include "js/HashTable.h"
|
||||
#include "js/Vector.h"
|
||||
#endif
|
||||
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
||||
/*
|
||||
* Convenience constants.
|
||||
*/
|
||||
#define JS_BITS_PER_UINT32_LOG2 5
|
||||
#define JS_BITS_PER_UINT32 32
|
||||
|
||||
/* The alignment required of objects stored in GC arenas. */
|
||||
static const unsigned JS_GCTHING_ALIGN = 8;
|
||||
static const unsigned JS_GCTHING_ZEROBITS = 3;
|
||||
|
||||
/* Scalar typedefs. */
|
||||
typedef uint8_t jsbytecode;
|
||||
typedef uint8_t jssrcnote;
|
||||
typedef uintptr_t jsatomid;
|
||||
|
||||
/* Struct typedefs. */
|
||||
typedef struct JSArgumentFormatMap JSArgumentFormatMap;
|
||||
typedef struct JSGCThing JSGCThing;
|
||||
typedef struct JSGenerator JSGenerator;
|
||||
typedef struct JSNativeEnumerator JSNativeEnumerator;
|
||||
typedef struct JSProperty JSProperty;
|
||||
typedef struct JSSharpObjectMap JSSharpObjectMap;
|
||||
typedef struct JSTryNote JSTryNote;
|
||||
|
||||
/* Friend "Advanced API" typedefs. */
|
||||
typedef struct JSAtomState JSAtomState;
|
||||
typedef struct JSCodeSpec JSCodeSpec;
|
||||
typedef struct JSPrinter JSPrinter;
|
||||
typedef struct JSStackHeader JSStackHeader;
|
||||
typedef struct JSSubString JSSubString;
|
||||
typedef struct JSSpecializedNative JSSpecializedNative;
|
||||
typedef struct JSXML JSXML;
|
||||
|
||||
/*
|
||||
* Template declarations.
|
||||
*
|
||||
* jsprvtd.h can be included in both C and C++ translation units. For C++, it
|
||||
* may possibly be wrapped in an extern "C" block which does not agree with
|
||||
* templates.
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
|
||||
extern "C++" {
|
||||
|
||||
class JSDependentString;
|
||||
class JSExtensibleString;
|
||||
class JSExternalString;
|
||||
class JSLinearString;
|
||||
class JSFixedString;
|
||||
class JSStaticAtom;
|
||||
class JSRope;
|
||||
class JSAtom;
|
||||
class JSWrapper;
|
||||
|
||||
namespace js {
|
||||
|
||||
struct ArgumentsData;
|
||||
struct Class;
|
||||
|
||||
class RegExpGuard;
|
||||
class RegExpObject;
|
||||
class RegExpObjectBuilder;
|
||||
class RegExpShared;
|
||||
class RegExpStatics;
|
||||
class MatchPairs;
|
||||
class PropertyName;
|
||||
|
||||
namespace detail { class RegExpCode; }
|
||||
|
||||
enum RegExpFlag
|
||||
{
|
||||
IgnoreCaseFlag = 0x01,
|
||||
GlobalFlag = 0x02,
|
||||
MultilineFlag = 0x04,
|
||||
StickyFlag = 0x08,
|
||||
|
||||
NoFlags = 0x00,
|
||||
AllFlags = 0x0f
|
||||
};
|
||||
|
||||
enum RegExpExecType
|
||||
{
|
||||
RegExpExec,
|
||||
RegExpTest
|
||||
};
|
||||
|
||||
class ExecuteArgsGuard;
|
||||
class InvokeFrameGuard;
|
||||
class InvokeArgsGuard;
|
||||
class StringBuffer;
|
||||
|
||||
class FrameRegs;
|
||||
class StackFrame;
|
||||
class StackSegment;
|
||||
class StackSpace;
|
||||
class ContextStack;
|
||||
class FrameRegsIter;
|
||||
class CallReceiver;
|
||||
class CallArgs;
|
||||
|
||||
struct BytecodeEmitter;
|
||||
struct Definition;
|
||||
struct FunctionBox;
|
||||
struct ObjectBox;
|
||||
struct ParseNode;
|
||||
struct Parser;
|
||||
class TokenStream;
|
||||
struct Token;
|
||||
struct TokenPos;
|
||||
struct TokenPtr;
|
||||
struct TreeContext;
|
||||
class UpvarCookie;
|
||||
|
||||
class Proxy;
|
||||
class ProxyHandler;
|
||||
class Wrapper;
|
||||
class CrossCompartmentWrapper;
|
||||
|
||||
class TempAllocPolicy;
|
||||
class RuntimeAllocPolicy;
|
||||
|
||||
class GlobalObject;
|
||||
|
||||
template <typename K,
|
||||
typename V,
|
||||
size_t InlineElems>
|
||||
class InlineMap;
|
||||
|
||||
class LifoAlloc;
|
||||
|
||||
class BaseShape;
|
||||
class UnownedBaseShape;
|
||||
struct Shape;
|
||||
struct EmptyShape;
|
||||
class ShapeKindArray;
|
||||
class Bindings;
|
||||
|
||||
struct StackBaseShape;
|
||||
struct StackShape;
|
||||
|
||||
class MultiDeclRange;
|
||||
class ParseMapPool;
|
||||
class DefnOrHeader;
|
||||
typedef InlineMap<JSAtom *, Definition *, 24> AtomDefnMap;
|
||||
typedef InlineMap<JSAtom *, jsatomid, 24> AtomIndexMap;
|
||||
typedef InlineMap<JSAtom *, DefnOrHeader, 24> AtomDOHMap;
|
||||
typedef Vector<UpvarCookie, 8> UpvarCookies;
|
||||
|
||||
class Breakpoint;
|
||||
class BreakpointSite;
|
||||
class Debugger;
|
||||
class WatchpointMap;
|
||||
|
||||
/*
|
||||
* Env is the type of what ES5 calls "lexical environments" (runtime
|
||||
* activations of lexical scopes). This is currently just JSObject, and is
|
||||
* implemented by Call, Block, With, and DeclEnv objects, among others--but
|
||||
* environments and objects are really two different concepts.
|
||||
*/
|
||||
typedef JSObject Env;
|
||||
|
||||
typedef JSNative Native;
|
||||
typedef JSPropertyOp PropertyOp;
|
||||
typedef JSStrictPropertyOp StrictPropertyOp;
|
||||
typedef JSPropertyDescriptor PropertyDescriptor;
|
||||
|
||||
namespace analyze {
|
||||
|
||||
struct LifetimeVariable;
|
||||
class LoopAnalysis;
|
||||
class ScriptAnalysis;
|
||||
class SlotValue;
|
||||
class SSAValue;
|
||||
class SSAUseChain;
|
||||
|
||||
} /* namespace analyze */
|
||||
|
||||
namespace types {
|
||||
|
||||
class TypeSet;
|
||||
struct TypeCallsite;
|
||||
struct TypeObject;
|
||||
struct TypeCompartment;
|
||||
|
||||
} /* namespace types */
|
||||
|
||||
typedef JS::Handle<Shape*> HandleShape;
|
||||
typedef JS::Handle<BaseShape*> HandleBaseShape;
|
||||
typedef JS::Handle<types::TypeObject*> HandleTypeObject;
|
||||
typedef JS::Handle<JSAtom*> HandleAtom;
|
||||
typedef JS::Handle<PropertyName*> HandlePropertyName;
|
||||
|
||||
typedef JS::Root<Shape*> RootShape;
|
||||
typedef JS::Root<BaseShape*> RootBaseShape;
|
||||
typedef JS::Root<types::TypeObject*> RootTypeObject;
|
||||
typedef JS::Root<JSAtom*> RootAtom;
|
||||
typedef JS::Root<PropertyName*> RootPropertyName;
|
||||
|
||||
typedef JS::RootedVar<Shape*> RootedVarShape;
|
||||
typedef JS::RootedVar<BaseShape*> RootedVarBaseShape;
|
||||
typedef JS::RootedVar<types::TypeObject*> RootedVarTypeObject;
|
||||
typedef JS::RootedVar<JSAtom*> RootedVarAtom;
|
||||
typedef JS::RootedVar<PropertyName*> RootedVarPropertyName;
|
||||
|
||||
enum XDRMode {
|
||||
XDR_ENCODE,
|
||||
XDR_DECODE
|
||||
};
|
||||
|
||||
template <XDRMode mode>
|
||||
class XDRState;
|
||||
|
||||
class FreeOp;
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
namespace JSC {
|
||||
|
||||
class ExecutableAllocator;
|
||||
|
||||
} /* namespace JSC */
|
||||
|
||||
namespace WTF {
|
||||
|
||||
class BumpPointerAllocator;
|
||||
|
||||
} /* namespace WTF */
|
||||
|
||||
} /* export "C++" */
|
||||
|
||||
#else
|
||||
|
||||
typedef struct JSAtom JSAtom;
|
||||
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/* "Friend" types used by jscntxt.h and jsdbgapi.h. */
|
||||
typedef enum JSTrapStatus {
|
||||
JSTRAP_ERROR,
|
||||
JSTRAP_CONTINUE,
|
||||
JSTRAP_RETURN,
|
||||
JSTRAP_THROW,
|
||||
JSTRAP_LIMIT
|
||||
} JSTrapStatus;
|
||||
|
||||
typedef JSTrapStatus
|
||||
(* JSTrapHandler)(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval,
|
||||
jsval closure);
|
||||
|
||||
typedef JSTrapStatus
|
||||
(* JSInterruptHook)(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval,
|
||||
void *closure);
|
||||
|
||||
typedef JSTrapStatus
|
||||
(* JSDebuggerHandler)(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval,
|
||||
void *closure);
|
||||
|
||||
typedef JSTrapStatus
|
||||
(* JSThrowHook)(JSContext *cx, JSScript *script, jsbytecode *pc, jsval *rval,
|
||||
void *closure);
|
||||
|
||||
typedef JSBool
|
||||
(* JSWatchPointHandler)(JSContext *cx, JSObject *obj, jsid id, jsval old,
|
||||
jsval *newp, void *closure);
|
||||
|
||||
/* called just after script creation */
|
||||
typedef void
|
||||
(* JSNewScriptHook)(JSContext *cx,
|
||||
const char *filename, /* URL of script */
|
||||
unsigned lineno, /* first line */
|
||||
JSScript *script,
|
||||
JSFunction *fun,
|
||||
void *callerdata);
|
||||
|
||||
/* called just before script destruction */
|
||||
typedef void
|
||||
(* JSDestroyScriptHook)(JSFreeOp *fop,
|
||||
JSScript *script,
|
||||
void *callerdata);
|
||||
|
||||
typedef void
|
||||
(* JSSourceHandler)(const char *filename, unsigned lineno, const jschar *str,
|
||||
size_t length, void **listenerTSData, void *closure);
|
||||
|
||||
/*
|
||||
* This hook captures high level script execution and function calls (JS or
|
||||
* native). It is used by JS_SetExecuteHook to hook top level scripts and by
|
||||
* JS_SetCallHook to hook function calls. It will get called twice per script
|
||||
* or function call: just before execution begins and just after it finishes.
|
||||
* In both cases the 'current' frame is that of the executing code.
|
||||
*
|
||||
* The 'before' param is JS_TRUE for the hook invocation before the execution
|
||||
* and JS_FALSE for the invocation after the code has run.
|
||||
*
|
||||
* The 'ok' param is significant only on the post execution invocation to
|
||||
* signify whether or not the code completed 'normally'.
|
||||
*
|
||||
* The 'closure' param is as passed to JS_SetExecuteHook or JS_SetCallHook
|
||||
* for the 'before'invocation, but is whatever value is returned from that
|
||||
* invocation for the 'after' invocation. Thus, the hook implementor *could*
|
||||
* allocate a structure in the 'before' invocation and return a pointer to that
|
||||
* structure. The pointer would then be handed to the hook for the 'after'
|
||||
* invocation. Alternately, the 'before' could just return the same value as
|
||||
* in 'closure' to cause the 'after' invocation to be called with the same
|
||||
* 'closure' value as the 'before'.
|
||||
*
|
||||
* Returning NULL in the 'before' hook will cause the 'after' hook *not* to
|
||||
* be called.
|
||||
*/
|
||||
typedef void *
|
||||
(* JSInterpreterHook)(JSContext *cx, JSStackFrame *fp, JSBool before,
|
||||
JSBool *ok, void *closure);
|
||||
|
||||
typedef JSBool
|
||||
(* JSDebugErrorHook)(JSContext *cx, const char *message, JSErrorReport *report,
|
||||
void *closure);
|
||||
|
||||
typedef struct JSDebugHooks {
|
||||
JSInterruptHook interruptHook;
|
||||
void *interruptHookData;
|
||||
JSNewScriptHook newScriptHook;
|
||||
void *newScriptHookData;
|
||||
JSDestroyScriptHook destroyScriptHook;
|
||||
void *destroyScriptHookData;
|
||||
JSDebuggerHandler debuggerHandler;
|
||||
void *debuggerHandlerData;
|
||||
JSSourceHandler sourceHandler;
|
||||
void *sourceHandlerData;
|
||||
JSInterpreterHook executeHook;
|
||||
void *executeHookData;
|
||||
JSInterpreterHook callHook;
|
||||
void *callHookData;
|
||||
JSThrowHook throwHook;
|
||||
void *throwHookData;
|
||||
JSDebugErrorHook debugErrorHook;
|
||||
void *debugErrorHookData;
|
||||
} JSDebugHooks;
|
||||
|
||||
/* js::ObjectOps function pointer typedefs. */
|
||||
|
||||
/*
|
||||
* Look for id in obj and its prototype chain, returning false on error or
|
||||
* exception, true on success. On success, return null in *propp if id was
|
||||
* not found. If id was found, return the first object searching from obj
|
||||
* along its prototype chain in which id names a direct property in *objp, and
|
||||
* return a non-null, opaque property pointer in *propp.
|
||||
*
|
||||
* If JSLookupPropOp succeeds and returns with *propp non-null, that pointer
|
||||
* may be passed as the prop parameter to a JSAttributesOp, as a short-cut
|
||||
* that bypasses id re-lookup.
|
||||
*/
|
||||
typedef JSBool
|
||||
(* JSLookupPropOp)(JSContext *cx, JSObject *obj, jsid id, JSObject **objp,
|
||||
JSProperty **propp);
|
||||
|
||||
/*
|
||||
* Get or set attributes of the property obj[id]. Return false on error or
|
||||
* exception, true with current attributes in *attrsp.
|
||||
*/
|
||||
typedef JSBool
|
||||
(* JSAttributesOp)(JSContext *cx, JSObject *obj, jsid id, unsigned *attrsp);
|
||||
|
||||
/*
|
||||
* A generic type for functions mapping an object to another object, or null
|
||||
* if an error or exception was thrown on cx.
|
||||
*/
|
||||
typedef JSObject *
|
||||
(* JSObjectOp)(JSContext *cx, JSObject *obj);
|
||||
|
||||
/*
|
||||
* Hook that creates an iterator object for a given object. Returns the
|
||||
* iterator object or null if an error or exception was thrown on cx.
|
||||
*/
|
||||
typedef JSObject *
|
||||
(* JSIteratorOp)(JSContext *cx, JSObject *obj, JSBool keysonly);
|
||||
|
||||
/*
|
||||
* The following determines whether JS_EncodeCharacters and JS_DecodeBytes
|
||||
* treat char[] as utf-8 or simply as bytes that need to be inflated/deflated.
|
||||
*/
|
||||
#ifdef JS_C_STRINGS_ARE_UTF8
|
||||
# define js_CStringsAreUTF8 JS_TRUE
|
||||
#else
|
||||
extern JSBool js_CStringsAreUTF8;
|
||||
#endif
|
||||
|
||||
JS_END_EXTERN_C
|
||||
|
||||
#endif /* jsprvtd_h___ */
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
|
@ -39,28 +39,66 @@
|
|||
|
||||
#ifndef jspubtd_h___
|
||||
#define jspubtd_h___
|
||||
|
||||
/*
|
||||
* JS public API typedefs.
|
||||
*/
|
||||
#include "jstypes.h"
|
||||
#include "jscompat.h"
|
||||
#include "jsval.h"
|
||||
|
||||
/*
|
||||
* Allow headers to reference JS::Value without #including the whole jsapi.h.
|
||||
* Unfortunately, typedefs (hence jsval) cannot be declared.
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
namespace JS { class Value; }
|
||||
#endif
|
||||
|
||||
/*
|
||||
* In release builds, jsid is defined to be an integral type. This
|
||||
* prevents many bugs from being caught at compile time. E.g.:
|
||||
*
|
||||
* jsid id = ...
|
||||
* if (id == JS_TRUE) // error
|
||||
* ...
|
||||
*
|
||||
* size_t n = id; // error
|
||||
*
|
||||
* To catch more errors, jsid is given a struct type in C++ debug builds.
|
||||
* Struct assignment and (in C++) operator== allow correct code to be mostly
|
||||
* oblivious to the change. This feature can be explicitly disabled in debug
|
||||
* builds by defining JS_NO_JSVAL_JSID_STRUCT_TYPES.
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
|
||||
# if defined(DEBUG) && !defined(JS_NO_JSVAL_JSID_STRUCT_TYPES)
|
||||
# define JS_USE_JSID_STRUCT_TYPES
|
||||
# endif
|
||||
|
||||
# ifdef JS_USE_JSID_STRUCT_TYPES
|
||||
struct jsid
|
||||
{
|
||||
size_t asBits;
|
||||
bool operator==(jsid rhs) const { return asBits == rhs.asBits; }
|
||||
bool operator!=(jsid rhs) const { return asBits != rhs.asBits; }
|
||||
};
|
||||
# define JSID_BITS(id) (id.asBits)
|
||||
# else /* defined(JS_USE_JSID_STRUCT_TYPES) */
|
||||
typedef ptrdiff_t jsid;
|
||||
# define JSID_BITS(id) (id)
|
||||
# endif /* defined(JS_USE_JSID_STRUCT_TYPES) */
|
||||
#else /* defined(__cplusplus) */
|
||||
typedef ptrdiff_t jsid;
|
||||
# define JSID_BITS(id) (id)
|
||||
#endif
|
||||
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
||||
/* Scalar typedefs. */
|
||||
typedef JSInt32 jsint;
|
||||
typedef JSUint32 jsuint;
|
||||
typedef float64 jsdouble;
|
||||
typedef JSInt32 jsrefcount; /* PRInt32 if JS_THREADSAFE, see jslock.h */
|
||||
|
||||
#ifdef WIN32
|
||||
typedef wchar_t jschar;
|
||||
#else
|
||||
typedef JSUint16 jschar;
|
||||
typedef uint16_t jschar;
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Run-time version enumeration. See jsversion.h for compile-time counterparts
|
||||
* to these values that may be selected by the JS_VERSION macro, and tested by
|
||||
|
@ -143,477 +181,130 @@ typedef enum JSIterateOp {
|
|||
JSENUMERATE_DESTROY
|
||||
} JSIterateOp;
|
||||
|
||||
/* See JSVAL_TRACE_KIND and JSTraceCallback in jsapi.h. */
|
||||
typedef enum {
|
||||
JSTRACE_OBJECT,
|
||||
JSTRACE_STRING,
|
||||
JSTRACE_SCRIPT,
|
||||
|
||||
/*
|
||||
* Trace kinds internal to the engine. The embedding can only them if it
|
||||
* implements JSTraceCallback.
|
||||
*/
|
||||
#if JS_HAS_XML_SUPPORT
|
||||
JSTRACE_XML,
|
||||
#endif
|
||||
JSTRACE_SHAPE,
|
||||
JSTRACE_BASE_SHAPE,
|
||||
JSTRACE_TYPE_OBJECT,
|
||||
JSTRACE_LAST = JSTRACE_TYPE_OBJECT
|
||||
} JSGCTraceKind;
|
||||
|
||||
/* Struct typedefs. */
|
||||
typedef struct JSClass JSClass;
|
||||
typedef struct JSConstDoubleSpec JSConstDoubleSpec;
|
||||
typedef struct JSContext JSContext;
|
||||
typedef struct JSErrorReport JSErrorReport;
|
||||
typedef struct JSFunction JSFunction;
|
||||
typedef struct JSFunctionSpec JSFunctionSpec;
|
||||
typedef struct JSTracer JSTracer;
|
||||
typedef struct JSIdArray JSIdArray;
|
||||
typedef struct JSPropertyDescriptor JSPropertyDescriptor;
|
||||
typedef struct JSPropertySpec JSPropertySpec;
|
||||
typedef struct JSObjectMap JSObjectMap;
|
||||
typedef struct JSRuntime JSRuntime;
|
||||
typedef struct JSStackFrame JSStackFrame;
|
||||
typedef struct JSXDRState JSXDRState;
|
||||
typedef struct JSExceptionState JSExceptionState;
|
||||
typedef struct JSLocaleCallbacks JSLocaleCallbacks;
|
||||
typedef struct JSSecurityCallbacks JSSecurityCallbacks;
|
||||
typedef struct JSONParser JSONParser;
|
||||
typedef struct JSCompartment JSCompartment;
|
||||
typedef struct JSCrossCompartmentCall JSCrossCompartmentCall;
|
||||
typedef struct JSStructuredCloneWriter JSStructuredCloneWriter;
|
||||
typedef struct JSStructuredCloneReader JSStructuredCloneReader;
|
||||
typedef struct JSStructuredCloneCallbacks JSStructuredCloneCallbacks;
|
||||
typedef struct JSClass JSClass;
|
||||
typedef struct JSCompartment JSCompartment;
|
||||
typedef struct JSConstDoubleSpec JSConstDoubleSpec;
|
||||
typedef struct JSContext JSContext;
|
||||
typedef struct JSCrossCompartmentCall JSCrossCompartmentCall;
|
||||
typedef struct JSErrorReport JSErrorReport;
|
||||
typedef struct JSExceptionState JSExceptionState;
|
||||
typedef struct JSFunction JSFunction;
|
||||
typedef struct JSFunctionSpec JSFunctionSpec;
|
||||
typedef struct JSIdArray JSIdArray;
|
||||
typedef struct JSLocaleCallbacks JSLocaleCallbacks;
|
||||
typedef struct JSObject JSObject;
|
||||
typedef struct JSObjectMap JSObjectMap;
|
||||
typedef struct JSPrincipals JSPrincipals;
|
||||
typedef struct JSPropertyDescriptor JSPropertyDescriptor;
|
||||
typedef struct JSPropertyName JSPropertyName;
|
||||
typedef struct JSPropertySpec JSPropertySpec;
|
||||
typedef struct JSRuntime JSRuntime;
|
||||
typedef struct JSSecurityCallbacks JSSecurityCallbacks;
|
||||
typedef struct JSStackFrame JSStackFrame;
|
||||
typedef struct JSScript JSScript;
|
||||
typedef struct JSStructuredCloneCallbacks JSStructuredCloneCallbacks;
|
||||
typedef struct JSStructuredCloneReader JSStructuredCloneReader;
|
||||
typedef struct JSStructuredCloneWriter JSStructuredCloneWriter;
|
||||
typedef struct JSTracer JSTracer;
|
||||
|
||||
#ifdef __cplusplus
|
||||
typedef class JSWrapper JSWrapper;
|
||||
typedef class JSCrossCompartmentWrapper JSCrossCompartmentWrapper;
|
||||
#endif
|
||||
|
||||
/* JSClass (and js::ObjectOps where appropriate) function pointer typedefs. */
|
||||
|
||||
/*
|
||||
* Add, delete, or get a property named by id in obj. Note the jsid id
|
||||
* type -- id may be a string (Unicode property identifier) or an int (element
|
||||
* index). The *vp out parameter, on success, is the new property value after
|
||||
* an add or get. After a successful delete, *vp is JSVAL_FALSE iff
|
||||
* obj[id] can't be deleted (because it's permanent).
|
||||
*/
|
||||
typedef JSBool
|
||||
(* JSPropertyOp)(JSContext *cx, JSObject *obj, jsid id, jsval *vp);
|
||||
|
||||
/*
|
||||
* Set a property named by id in obj, treating the assignment as strict
|
||||
* mode code if strict is true. Note the jsid id type -- id may be a string
|
||||
* (Unicode property identifier) or an int (element index). The *vp out
|
||||
* parameter, on success, is the new property value after the
|
||||
* set.
|
||||
*/
|
||||
typedef JSBool
|
||||
(* JSStrictPropertyOp)(JSContext *cx, JSObject *obj, jsid id, JSBool strict, jsval *vp);
|
||||
|
||||
/*
|
||||
* This function type is used for callbacks that enumerate the properties of
|
||||
* a JSObject. The behavior depends on the value of enum_op:
|
||||
*
|
||||
* JSENUMERATE_INIT
|
||||
* A new, opaque iterator state should be allocated and stored in *statep.
|
||||
* (You can use PRIVATE_TO_JSVAL() to tag the pointer to be stored).
|
||||
*
|
||||
* The number of properties that will be enumerated should be returned as
|
||||
* an integer jsval in *idp, if idp is non-null, and provided the number of
|
||||
* enumerable properties is known. If idp is non-null and the number of
|
||||
* enumerable properties can't be computed in advance, *idp should be set
|
||||
* to JSVAL_ZERO.
|
||||
*
|
||||
* JSENUMERATE_INIT_ALL
|
||||
* Used identically to JSENUMERATE_INIT, but exposes all properties of the
|
||||
* object regardless of enumerability.
|
||||
*
|
||||
* JSENUMERATE_NEXT
|
||||
* A previously allocated opaque iterator state is passed in via statep.
|
||||
* Return the next jsid in the iteration using *idp. The opaque iterator
|
||||
* state pointed at by statep is destroyed and *statep is set to JSVAL_NULL
|
||||
* if there are no properties left to enumerate.
|
||||
*
|
||||
* JSENUMERATE_DESTROY
|
||||
* Destroy the opaque iterator state previously allocated in *statep by a
|
||||
* call to this function when enum_op was JSENUMERATE_INIT or
|
||||
* JSENUMERATE_INIT_ALL.
|
||||
*
|
||||
* The return value is used to indicate success, with a value of JS_FALSE
|
||||
* indicating failure.
|
||||
*/
|
||||
typedef JSBool
|
||||
(* JSNewEnumerateOp)(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
|
||||
jsval *statep, jsid *idp);
|
||||
|
||||
/*
|
||||
* The old-style JSClass.enumerate op should define all lazy properties not
|
||||
* yet reflected in obj.
|
||||
*/
|
||||
typedef JSBool
|
||||
(* JSEnumerateOp)(JSContext *cx, JSObject *obj);
|
||||
|
||||
/*
|
||||
* Resolve a lazy property named by id in obj by defining it directly in obj.
|
||||
* Lazy properties are those reflected from some peer native property space
|
||||
* (e.g., the DOM attributes for a given node reflected as obj) on demand.
|
||||
*
|
||||
* JS looks for a property in an object, and if not found, tries to resolve
|
||||
* the given id. If resolve succeeds, the engine looks again in case resolve
|
||||
* defined obj[id]. If no such property exists directly in obj, the process
|
||||
* is repeated with obj's prototype, etc.
|
||||
*
|
||||
* NB: JSNewResolveOp provides a cheaper way to resolve lazy properties.
|
||||
*/
|
||||
typedef JSBool
|
||||
(* JSResolveOp)(JSContext *cx, JSObject *obj, jsid id);
|
||||
|
||||
/*
|
||||
* Like JSResolveOp, but flags provide contextual information as follows:
|
||||
*
|
||||
* JSRESOLVE_QUALIFIED a qualified property id: obj.id or obj[id], not id
|
||||
* JSRESOLVE_ASSIGNING obj[id] is on the left-hand side of an assignment
|
||||
* JSRESOLVE_DETECTING 'if (o.p)...' or similar detection opcode sequence
|
||||
* JSRESOLVE_DECLARING var, const, or function prolog declaration opcode
|
||||
* JSRESOLVE_CLASSNAME class name used when constructing
|
||||
*
|
||||
* The *objp out parameter, on success, should be null to indicate that id
|
||||
* was not resolved; and non-null, referring to obj or one of its prototypes,
|
||||
* if id was resolved.
|
||||
*
|
||||
* This hook instead of JSResolveOp is called via the JSClass.resolve member
|
||||
* if JSCLASS_NEW_RESOLVE is set in JSClass.flags.
|
||||
*
|
||||
* Setting JSCLASS_NEW_RESOLVE and JSCLASS_NEW_RESOLVE_GETS_START further
|
||||
* extends this hook by passing in the starting object on the prototype chain
|
||||
* via *objp. Thus a resolve hook implementation may define the property id
|
||||
* being resolved in the object in which the id was first sought, rather than
|
||||
* in a prototype object whose class led to the resolve hook being called.
|
||||
*
|
||||
* When using JSCLASS_NEW_RESOLVE_GETS_START, the resolve hook must therefore
|
||||
* null *objp to signify "not resolved". With only JSCLASS_NEW_RESOLVE and no
|
||||
* JSCLASS_NEW_RESOLVE_GETS_START, the hook can assume *objp is null on entry.
|
||||
* This is not good practice, but enough existing hook implementations count
|
||||
* on it that we can't break compatibility by passing the starting object in
|
||||
* *objp without a new JSClass flag.
|
||||
*/
|
||||
typedef JSBool
|
||||
(* JSNewResolveOp)(JSContext *cx, JSObject *obj, jsid id, uintN flags,
|
||||
JSObject **objp);
|
||||
|
||||
/*
|
||||
* Convert obj to the given type, returning true with the resulting value in
|
||||
* *vp on success, and returning false on error or exception.
|
||||
*/
|
||||
typedef JSBool
|
||||
(* JSConvertOp)(JSContext *cx, JSObject *obj, JSType type, jsval *vp);
|
||||
|
||||
/*
|
||||
* Delegate typeof to an object so it can cloak a primitive or another object.
|
||||
*/
|
||||
typedef JSType
|
||||
(* JSTypeOfOp)(JSContext *cx, JSObject *obj);
|
||||
|
||||
/*
|
||||
* Finalize obj, which the garbage collector has determined to be unreachable
|
||||
* from other live objects or from GC roots. Obviously, finalizers must never
|
||||
* store a reference to obj.
|
||||
*/
|
||||
typedef void
|
||||
(* JSFinalizeOp)(JSContext *cx, JSObject *obj);
|
||||
|
||||
/*
|
||||
* Used by JS_AddExternalStringFinalizer and JS_RemoveExternalStringFinalizer
|
||||
* to extend and reduce the set of string types finalized by the GC.
|
||||
*/
|
||||
typedef void
|
||||
(* JSStringFinalizeOp)(JSContext *cx, JSString *str);
|
||||
|
||||
/*
|
||||
* JSClass.checkAccess type: check whether obj[id] may be accessed per mode,
|
||||
* returning false on error/exception, true on success with obj[id]'s last-got
|
||||
* value in *vp, and its attributes in *attrsp. As for JSPropertyOp above, id
|
||||
* is either a string or an int jsval.
|
||||
*/
|
||||
typedef JSBool
|
||||
(* JSCheckAccessOp)(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode,
|
||||
jsval *vp);
|
||||
|
||||
/*
|
||||
* Encode or decode an object, given an XDR state record representing external
|
||||
* data. See jsxdrapi.h.
|
||||
*/
|
||||
typedef JSBool
|
||||
(* JSXDRObjectOp)(JSXDRState *xdr, JSObject **objp);
|
||||
|
||||
/*
|
||||
* Check whether v is an instance of obj. Return false on error or exception,
|
||||
* true on success with JS_TRUE in *bp if v is an instance of obj, JS_FALSE in
|
||||
* *bp otherwise.
|
||||
*/
|
||||
typedef JSBool
|
||||
(* JSHasInstanceOp)(JSContext *cx, JSObject *obj, const jsval *v, JSBool *bp);
|
||||
|
||||
/*
|
||||
* Deprecated function type for JSClass.mark. All new code should define
|
||||
* JSTraceOp instead to ensure the traversal of traceable things stored in
|
||||
* the native structures.
|
||||
*/
|
||||
typedef uint32
|
||||
(* JSMarkOp)(JSContext *cx, JSObject *obj, void *arg);
|
||||
|
||||
/*
|
||||
* Function type for trace operation of the class called to enumerate all
|
||||
* traceable things reachable from obj's private data structure. For each such
|
||||
* thing, a trace implementation must call
|
||||
*
|
||||
* JS_CallTracer(trc, thing, kind);
|
||||
*
|
||||
* or one of its convenience macros as described in jsapi.h.
|
||||
*
|
||||
* JSTraceOp implementation can assume that no other threads mutates object
|
||||
* state. It must not change state of the object or corresponding native
|
||||
* structures. The only exception for this rule is the case when the embedding
|
||||
* needs a tight integration with GC. In that case the embedding can check if
|
||||
* the traversal is a part of the marking phase through calling
|
||||
* JS_IsGCMarkingTracer and apply a special code like emptying caches or
|
||||
* marking its native structures.
|
||||
*
|
||||
* To define the tracer for a JSClass, the implementation must add
|
||||
* JSCLASS_MARK_IS_TRACE to class flags and use JS_CLASS_TRACE(method)
|
||||
* macro below to convert JSTraceOp to JSMarkOp when initializing or
|
||||
* assigning JSClass.mark field.
|
||||
*/
|
||||
typedef void
|
||||
(* JSTraceOp)(JSTracer *trc, JSObject *obj);
|
||||
|
||||
#if defined __GNUC__ && __GNUC__ >= 4 && !defined __cplusplus
|
||||
# define JS_CLASS_TRACE(method) \
|
||||
(__builtin_types_compatible_p(JSTraceOp, __typeof(&(method))) \
|
||||
? (JSMarkOp)(method) \
|
||||
: js_WrongTypeForClassTracer)
|
||||
|
||||
extern JSMarkOp js_WrongTypeForClassTracer;
|
||||
|
||||
class JSFlatString;
|
||||
class JSString;
|
||||
#else
|
||||
# define JS_CLASS_TRACE(method) ((JSMarkOp)(method))
|
||||
typedef struct JSFlatString JSFlatString;
|
||||
typedef struct JSString JSString;
|
||||
#endif /* !__cplusplus */
|
||||
|
||||
#ifdef JS_THREADSAFE
|
||||
typedef struct PRCallOnceType JSCallOnceType;
|
||||
#else
|
||||
typedef JSBool JSCallOnceType;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Tracer callback, called for each traceable thing directly referenced by a
|
||||
* particular object or runtime structure. It is the callback responsibility
|
||||
* to ensure the traversal of the full object graph via calling eventually
|
||||
* JS_TraceChildren on the passed thing. In this case the callback must be
|
||||
* prepared to deal with cycles in the traversal graph.
|
||||
*
|
||||
* kind argument is one of JSTRACE_OBJECT, JSTRACE_STRING or a tag denoting
|
||||
* internal implementation-specific traversal kind. In the latter case the only
|
||||
* operations on thing that the callback can do is to call JS_TraceChildren or
|
||||
* DEBUG-only JS_PrintTraceThingInfo.
|
||||
*/
|
||||
typedef void
|
||||
(* JSTraceCallback)(JSTracer *trc, void *thing, uint32 kind);
|
||||
|
||||
/*
|
||||
* DEBUG only callback that JSTraceOp implementation can provide to return
|
||||
* a string describing the reference traced with JS_CallTracer.
|
||||
*/
|
||||
typedef void
|
||||
(* JSTraceNamePrinter)(JSTracer *trc, char *buf, size_t bufsize);
|
||||
|
||||
typedef JSBool
|
||||
(* JSEqualityOp)(JSContext *cx, JSObject *obj, const jsval *v, JSBool *bp);
|
||||
|
||||
/*
|
||||
* Typedef for native functions called by the JS VM.
|
||||
*
|
||||
* See jsapi.h, the JS_CALLEE, JS_THIS, etc. macros.
|
||||
*/
|
||||
|
||||
typedef JSBool
|
||||
(* JSNative)(JSContext *cx, uintN argc, jsval *vp);
|
||||
|
||||
/* Callbacks and their arguments. */
|
||||
|
||||
typedef enum JSContextOp {
|
||||
JSCONTEXT_NEW,
|
||||
JSCONTEXT_DESTROY
|
||||
} JSContextOp;
|
||||
|
||||
/*
|
||||
* The possible values for contextOp when the runtime calls the callback are:
|
||||
* JSCONTEXT_NEW JS_NewContext successfully created a new JSContext
|
||||
* instance. The callback can initialize the instance as
|
||||
* required. If the callback returns false, the instance
|
||||
* will be destroyed and JS_NewContext returns null. In
|
||||
* this case the callback is not called again.
|
||||
* JSCONTEXT_DESTROY One of JS_DestroyContext* methods is called. The
|
||||
* callback may perform its own cleanup and must always
|
||||
* return true.
|
||||
* Any other value For future compatibility the callback must do nothing
|
||||
* and return true in this case.
|
||||
*/
|
||||
typedef JSBool
|
||||
(* JSContextCallback)(JSContext *cx, uintN contextOp);
|
||||
|
||||
#ifndef JS_THREADSAFE
|
||||
typedef void
|
||||
(* JSHeartbeatCallback)(JSRuntime *rt);
|
||||
#endif
|
||||
|
||||
typedef enum JSGCStatus {
|
||||
JSGC_BEGIN,
|
||||
JSGC_END,
|
||||
JSGC_MARK_END,
|
||||
JSGC_FINALIZE_END
|
||||
} JSGCStatus;
|
||||
|
||||
typedef JSBool
|
||||
(* JSGCCallback)(JSContext *cx, JSGCStatus status);
|
||||
|
||||
/*
|
||||
* Generic trace operation that calls JS_CallTracer on each traceable thing
|
||||
* stored in data.
|
||||
*/
|
||||
typedef void
|
||||
(* JSTraceDataOp)(JSTracer *trc, void *data);
|
||||
|
||||
typedef JSBool
|
||||
(* JSOperationCallback)(JSContext *cx);
|
||||
|
||||
typedef void
|
||||
(* JSErrorReporter)(JSContext *cx, const char *message, JSErrorReport *report);
|
||||
|
||||
/*
|
||||
* Possible exception types. These types are part of a JSErrorFormatString
|
||||
* structure. They define which error to throw in case of a runtime error.
|
||||
* JSEXN_NONE marks an unthrowable error.
|
||||
*/
|
||||
typedef enum JSExnType {
|
||||
JSEXN_NONE = -1,
|
||||
JSEXN_ERR,
|
||||
JSEXN_INTERNALERR,
|
||||
JSEXN_EVALERR,
|
||||
JSEXN_RANGEERR,
|
||||
JSEXN_REFERENCEERR,
|
||||
JSEXN_SYNTAXERR,
|
||||
JSEXN_TYPEERR,
|
||||
JSEXN_URIERR,
|
||||
JSEXN_LIMIT
|
||||
} JSExnType;
|
||||
|
||||
typedef struct JSErrorFormatString {
|
||||
/* The error format string (UTF-8 if js_CStringsAreUTF8). */
|
||||
const char *format;
|
||||
|
||||
/* The number of arguments to expand in the formatted error message. */
|
||||
uint16 argCount;
|
||||
|
||||
/* One of the JSExnType constants above. */
|
||||
int16 exnType;
|
||||
} JSErrorFormatString;
|
||||
|
||||
typedef const JSErrorFormatString *
|
||||
(* JSErrorCallback)(void *userRef, const char *locale,
|
||||
const uintN errorNumber);
|
||||
|
||||
#ifdef va_start
|
||||
#define JS_ARGUMENT_FORMATTER_DEFINED 1
|
||||
|
||||
typedef JSBool
|
||||
(* JSArgumentFormatter)(JSContext *cx, const char *format, JSBool fromJS,
|
||||
jsval **vpp, va_list *app);
|
||||
#endif
|
||||
|
||||
typedef JSBool
|
||||
(* JSLocaleToUpperCase)(JSContext *cx, JSString *src, jsval *rval);
|
||||
|
||||
typedef JSBool
|
||||
(* JSLocaleToLowerCase)(JSContext *cx, JSString *src, jsval *rval);
|
||||
|
||||
typedef JSBool
|
||||
(* JSLocaleCompare)(JSContext *cx, JSString *src1, JSString *src2,
|
||||
jsval *rval);
|
||||
|
||||
typedef JSBool
|
||||
(* JSLocaleToUnicode)(JSContext *cx, const char *src, jsval *rval);
|
||||
|
||||
/*
|
||||
* Security protocol types.
|
||||
*/
|
||||
typedef struct JSPrincipals JSPrincipals;
|
||||
|
||||
/*
|
||||
* XDR-encode or -decode a principals instance, based on whether xdr->mode is
|
||||
* JSXDR_ENCODE, in which case *principalsp should be encoded; or JSXDR_DECODE,
|
||||
* in which case implementations must return a held (via JSPRINCIPALS_HOLD),
|
||||
* non-null *principalsp out parameter. Return true on success, false on any
|
||||
* error, which the implementation must have reported.
|
||||
*/
|
||||
typedef JSBool
|
||||
(* JSPrincipalsTranscoder)(JSXDRState *xdr, JSPrincipals **principalsp);
|
||||
|
||||
/*
|
||||
* Return a weak reference to the principals associated with obj, possibly via
|
||||
* the immutable parent chain leading from obj to a top-level container (e.g.,
|
||||
* a window object in the DOM level 0). If there are no principals associated
|
||||
* with obj, return null. Therefore null does not mean an error was reported;
|
||||
* in no event should an error be reported or an exception be thrown by this
|
||||
* callback's implementation.
|
||||
*/
|
||||
typedef JSPrincipals *
|
||||
(* JSObjectPrincipalsFinder)(JSContext *cx, JSObject *obj);
|
||||
|
||||
/*
|
||||
* Used to check if a CSP instance wants to disable eval() and friends.
|
||||
* See js_CheckCSPPermitsJSAction() in jsobj.
|
||||
*/
|
||||
typedef JSBool
|
||||
(* JSCSPEvalChecker)(JSContext *cx);
|
||||
|
||||
/*
|
||||
* Callback used to ask the embedding for the cross compartment wrapper handler
|
||||
* that implements the desired prolicy for this kind of object in the
|
||||
* destination compartment.
|
||||
*/
|
||||
typedef JSObject *
|
||||
(* JSWrapObjectCallback)(JSContext *cx, JSObject *obj, JSObject *proto, JSObject *parent,
|
||||
uintN flags);
|
||||
|
||||
/*
|
||||
* Callback used by the wrap hook to ask the embedding to prepare an object
|
||||
* for wrapping in a context. This might include unwrapping other wrappers
|
||||
* or even finding a more suitable object for the new compartment.
|
||||
*/
|
||||
typedef JSObject *
|
||||
(* JSPreWrapCallback)(JSContext *cx, JSObject *scope, JSObject *obj, uintN flags);
|
||||
|
||||
typedef enum {
|
||||
JSCOMPARTMENT_NEW, /* XXX Does it make sense to have a NEW? */
|
||||
JSCOMPARTMENT_DESTROY
|
||||
} JSCompartmentOp;
|
||||
|
||||
typedef JSBool
|
||||
(* JSCompartmentCallback)(JSContext *cx, JSCompartment *compartment, uintN compartmentOp);
|
||||
|
||||
/*
|
||||
* Read structured data from the reader r. This hook is used to read a value
|
||||
* previously serialized by a call to the WriteStructuredCloneOp hook.
|
||||
*
|
||||
* tag and data are the pair of uint32 values from the header. The callback may
|
||||
* use the JS_Read* APIs to read any other relevant parts of the object from
|
||||
* the reader r. closure is any value passed to the JS_ReadStructuredClone
|
||||
* function. Return the new object on success, NULL on error/exception.
|
||||
*/
|
||||
typedef JSObject *(*ReadStructuredCloneOp)(JSContext *cx, JSStructuredCloneReader *r,
|
||||
uint32 tag, uint32 data, void *closure);
|
||||
|
||||
/*
|
||||
* Structured data serialization hook. The engine can write primitive values,
|
||||
* Objects, Arrays, Dates, RegExps, TypedArrays, and ArrayBuffers. Any other
|
||||
* type of object requires application support. This callback must first use
|
||||
* the JS_WriteUint32Pair API to write an object header, passing a value
|
||||
* greater than JS_SCTAG_USER to the tag parameter. Then it can use the
|
||||
* JS_Write* APIs to write any other relevant parts of the value v to the
|
||||
* writer w. closure is any value passed to the JS_WriteStructuredCLone function.
|
||||
*
|
||||
* Return true on success, false on error/exception.
|
||||
*/
|
||||
typedef JSBool (*WriteStructuredCloneOp)(JSContext *cx, JSStructuredCloneWriter *w,
|
||||
JSObject *obj, void *closure);
|
||||
|
||||
/*
|
||||
* This is called when JS_WriteStructuredClone finds that the object to be
|
||||
* written is recursive. To follow HTML5, the application must throw a
|
||||
* DATA_CLONE_ERR DOMException. errorid is always JS_SCERR_RECURSION.
|
||||
*/
|
||||
typedef void (*StructuredCloneErrorOp)(JSContext *cx, uint32 errorid);
|
||||
typedef JSBool (*JSInitCallback)(void);
|
||||
|
||||
JS_END_EXTERN_C
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
namespace JS {
|
||||
|
||||
template <typename T>
|
||||
class Root;
|
||||
|
||||
class SkipRoot;
|
||||
|
||||
enum ThingRootKind
|
||||
{
|
||||
THING_ROOT_OBJECT,
|
||||
THING_ROOT_SHAPE,
|
||||
THING_ROOT_BASE_SHAPE,
|
||||
THING_ROOT_TYPE_OBJECT,
|
||||
THING_ROOT_STRING,
|
||||
THING_ROOT_SCRIPT,
|
||||
THING_ROOT_ID,
|
||||
THING_ROOT_VALUE,
|
||||
THING_ROOT_LIMIT
|
||||
};
|
||||
|
||||
struct ContextFriendFields {
|
||||
JSRuntime *const runtime;
|
||||
|
||||
ContextFriendFields(JSRuntime *rt)
|
||||
: runtime(rt) { }
|
||||
|
||||
static const ContextFriendFields *get(const JSContext *cx) {
|
||||
return reinterpret_cast<const ContextFriendFields *>(cx);
|
||||
}
|
||||
|
||||
static ContextFriendFields *get(JSContext *cx) {
|
||||
return reinterpret_cast<ContextFriendFields *>(cx);
|
||||
}
|
||||
|
||||
#ifdef JSGC_ROOT_ANALYSIS
|
||||
|
||||
/*
|
||||
* Stack allocated GC roots for stack GC heap pointers, which may be
|
||||
* overwritten if moved during a GC.
|
||||
*/
|
||||
Root<void*> *thingGCRooters[THING_ROOT_LIMIT];
|
||||
|
||||
#ifdef DEBUG
|
||||
/*
|
||||
* Stack allocated list of stack locations which hold non-relocatable
|
||||
* GC heap pointers (where the target is rooted somewhere else) or integer
|
||||
* values which may be confused for GC heap pointers. These are used to
|
||||
* suppress false positives which occur when a rooting analysis treats the
|
||||
* location as holding a relocatable pointer, but have no other effect on
|
||||
* GC behavior.
|
||||
*/
|
||||
SkipRoot *skipGCRooters;
|
||||
#endif
|
||||
|
||||
#endif /* JSGC_ROOT_ANALYSIS */
|
||||
};
|
||||
|
||||
} /* namespace JS */
|
||||
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* jspubtd_h___ */
|
||||
|
|
|
@ -54,7 +54,9 @@
|
|||
#ifndef jstypes_h___
|
||||
#define jstypes_h___
|
||||
|
||||
#include <stddef.h>
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/Util.h"
|
||||
|
||||
#include "js-config.h"
|
||||
|
||||
/***********************************************************************
|
||||
|
@ -78,78 +80,11 @@
|
|||
**
|
||||
***********************************************************************/
|
||||
|
||||
#define DEFINE_LOCAL_CLASS_OF_STATIC_FUNCTION(Name) class Name
|
||||
|
||||
#if defined(WIN32) || defined(XP_OS2)
|
||||
|
||||
/* These also work for __MWERKS__ */
|
||||
# define JS_EXTERN_API(__type) extern __declspec(dllexport) __type
|
||||
# define JS_EXPORT_API(__type) __declspec(dllexport) __type
|
||||
# define JS_EXTERN_DATA(__type) extern __declspec(dllexport) __type
|
||||
# define JS_EXPORT_DATA(__type) __declspec(dllexport) __type
|
||||
|
||||
#elif defined(__SYMBIAN32__)
|
||||
|
||||
# define JS_EXTERN_API(__type) extern EXPORT_C __type
|
||||
# define JS_EXPORT_API(__type) EXPORT_C __type
|
||||
# define JS_EXTERN_DATA(__type) extern EXPORT_C __type
|
||||
# define JS_EXPORT_DATA(__type) EXPORT_C __type
|
||||
|
||||
#else /* Unix */
|
||||
|
||||
# ifdef HAVE_VISIBILITY_ATTRIBUTE
|
||||
# define JS_EXTERNAL_VIS __attribute__((visibility ("default")))
|
||||
# if defined(__GNUC__) && __GNUC__ <= 4 && __GNUC_MINOR__ < 5
|
||||
/*
|
||||
* GCC wrongly produces a warning when a type with hidden visibility
|
||||
* (e.g. js::Value) is a member of a local class of a static function.
|
||||
* This is apparently fixed with GCC 4.5 and above. See:
|
||||
*
|
||||
* http://gcc.gnu.org/bugzilla/show_bug.cgi?id=40145.
|
||||
*/
|
||||
# undef DEFINE_LOCAL_CLASS_OF_STATIC_FUNCTION
|
||||
# define DEFINE_LOCAL_CLASS_OF_STATIC_FUNCTION(Name) class __attribute__((visibility ("hidden"))) Name
|
||||
# endif
|
||||
# elif defined(__SUNPRO_C) || defined(__SUNPRO_CC)
|
||||
# define JS_EXTERNAL_VIS __global
|
||||
# else
|
||||
# define JS_EXTERNAL_VIS
|
||||
# endif
|
||||
|
||||
# define JS_EXTERN_API(__type) extern JS_EXTERNAL_VIS __type
|
||||
# define JS_EXPORT_API(__type) JS_EXTERNAL_VIS __type
|
||||
# define JS_EXTERN_DATA(__type) extern JS_EXTERNAL_VIS __type
|
||||
# define JS_EXPORT_DATA(__type) JS_EXTERNAL_VIS __type
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
# if defined(__MWERKS__) || defined(__GNUC__)
|
||||
# define JS_IMPORT_API(__x) __x
|
||||
# else
|
||||
# define JS_IMPORT_API(__x) __declspec(dllimport) __x
|
||||
# endif
|
||||
#elif defined(XP_OS2)
|
||||
# define JS_IMPORT_API(__x) __declspec(dllimport) __x
|
||||
#elif defined(__SYMBIAN32__)
|
||||
# define JS_IMPORT_API(__x) IMPORT_C __x
|
||||
#else
|
||||
# define JS_IMPORT_API(__x) JS_EXPORT_API (__x)
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) && !defined(__MWERKS__)
|
||||
# define JS_IMPORT_DATA(__x) __declspec(dllimport) __x
|
||||
#elif defined(XP_OS2)
|
||||
# define JS_IMPORT_DATA(__x) __declspec(dllimport) __x
|
||||
#elif defined(__SYMBIAN32__)
|
||||
# if defined(__CW32__)
|
||||
# define JS_IMPORT_DATA(__x) __declspec(dllimport) __x
|
||||
# else
|
||||
# define JS_IMPORT_DATA(__x) IMPORT_C __x
|
||||
# endif
|
||||
#else
|
||||
# define JS_IMPORT_DATA(__x) JS_EXPORT_DATA (__x)
|
||||
#endif
|
||||
#define JS_EXTERN_API(type) extern MOZ_EXPORT_API(type)
|
||||
#define JS_EXPORT_API(type) MOZ_EXPORT_API(type)
|
||||
#define JS_EXPORT_DATA(type) MOZ_EXPORT_DATA(type)
|
||||
#define JS_IMPORT_API(type) MOZ_IMPORT_API(type)
|
||||
#define JS_IMPORT_DATA(type) MOZ_IMPORT_DATA(type)
|
||||
|
||||
/*
|
||||
* The linkage of JS API functions differs depending on whether the file is
|
||||
|
@ -158,20 +93,14 @@
|
|||
* should not. STATIC_JS_API is used to build JS as a static library.
|
||||
*/
|
||||
#if defined(STATIC_JS_API)
|
||||
|
||||
# define JS_PUBLIC_API(t) t
|
||||
# define JS_PUBLIC_DATA(t) t
|
||||
|
||||
# define JS_PUBLIC_API(t) t
|
||||
# define JS_PUBLIC_DATA(t) t
|
||||
#elif defined(EXPORT_JS_API) || defined(STATIC_EXPORTABLE_JS_API)
|
||||
|
||||
# define JS_PUBLIC_API(t) JS_EXPORT_API(t)
|
||||
# define JS_PUBLIC_DATA(t) JS_EXPORT_DATA(t)
|
||||
|
||||
# define JS_PUBLIC_API(t) MOZ_EXPORT_API(t)
|
||||
# define JS_PUBLIC_DATA(t) MOZ_EXPORT_DATA(t)
|
||||
#else
|
||||
|
||||
# define JS_PUBLIC_API(t) JS_IMPORT_API(t)
|
||||
# define JS_PUBLIC_DATA(t) JS_IMPORT_DATA(t)
|
||||
|
||||
# define JS_PUBLIC_API(t) MOZ_IMPORT_API(t)
|
||||
# define JS_PUBLIC_DATA(t) MOZ_IMPORT_DATA(t)
|
||||
#endif
|
||||
|
||||
#define JS_FRIEND_API(t) JS_PUBLIC_API(t)
|
||||
|
@ -188,37 +117,15 @@
|
|||
#endif
|
||||
|
||||
#ifndef JS_INLINE
|
||||
# if defined __cplusplus
|
||||
# define JS_INLINE inline
|
||||
# elif defined _MSC_VER
|
||||
# define JS_INLINE __inline
|
||||
# elif defined __GNUC__
|
||||
# define JS_INLINE __inline__
|
||||
# else
|
||||
# define JS_INLINE inline
|
||||
# endif
|
||||
#define JS_INLINE MOZ_INLINE
|
||||
#endif
|
||||
|
||||
#ifndef JS_ALWAYS_INLINE
|
||||
# if defined DEBUG
|
||||
# define JS_ALWAYS_INLINE JS_INLINE
|
||||
# elif defined _MSC_VER
|
||||
# define JS_ALWAYS_INLINE __forceinline
|
||||
# elif defined __GNUC__
|
||||
# define JS_ALWAYS_INLINE __attribute__((always_inline)) JS_INLINE
|
||||
# else
|
||||
# define JS_ALWAYS_INLINE JS_INLINE
|
||||
# endif
|
||||
#define JS_ALWAYS_INLINE MOZ_ALWAYS_INLINE
|
||||
#endif
|
||||
|
||||
#ifndef JS_NEVER_INLINE
|
||||
# if defined _MSC_VER
|
||||
# define JS_NEVER_INLINE __declspec(noinline)
|
||||
# elif defined __GNUC__
|
||||
# define JS_NEVER_INLINE __attribute__((noinline))
|
||||
# else
|
||||
# define JS_NEVER_INLINE
|
||||
# endif
|
||||
#define JS_NEVER_INLINE MOZ_NEVER_INLINE
|
||||
#endif
|
||||
|
||||
#ifndef JS_WARN_UNUSED_RESULT
|
||||
|
@ -229,25 +136,6 @@
|
|||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef NS_STATIC_CHECKING
|
||||
/*
|
||||
* Attributes for static analysis. Functions declared with JS_REQUIRES_STACK
|
||||
* always have a valid cx->fp and can access it freely. Other functions can
|
||||
* access cx->fp only after calling a function that "forces" the stack
|
||||
* (i.e. lazily instantiates it as needed).
|
||||
*/
|
||||
# define JS_REQUIRES_STACK __attribute__((user("JS_REQUIRES_STACK")))
|
||||
# define JS_FORCES_STACK __attribute__((user("JS_FORCES_STACK")))
|
||||
/*
|
||||
* Skip the JS_REQUIRES_STACK analysis within functions with this annotation.
|
||||
*/
|
||||
# define JS_IGNORE_STACK __attribute__((user("JS_IGNORE_STACK")))
|
||||
#else
|
||||
# define JS_REQUIRES_STACK
|
||||
# define JS_FORCES_STACK
|
||||
# define JS_IGNORE_STACK
|
||||
#endif
|
||||
|
||||
/***********************************************************************
|
||||
** MACROS: JS_BEGIN_MACRO
|
||||
** JS_END_MACRO
|
||||
|
@ -271,17 +159,8 @@
|
|||
** DESCRIPTION:
|
||||
** Macro shorthands for conditional C++ extern block delimiters.
|
||||
***********************************************************************/
|
||||
#ifdef __cplusplus
|
||||
|
||||
# define JS_BEGIN_EXTERN_C extern "C" {
|
||||
# define JS_END_EXTERN_C }
|
||||
|
||||
#else
|
||||
|
||||
# define JS_BEGIN_EXTERN_C
|
||||
# define JS_END_EXTERN_C
|
||||
|
||||
#endif
|
||||
#define JS_BEGIN_EXTERN_C MOZ_BEGIN_EXTERN_C
|
||||
#define JS_END_EXTERN_C MOZ_END_EXTERN_C
|
||||
|
||||
/***********************************************************************
|
||||
** MACROS: JS_BIT
|
||||
|
@ -289,7 +168,7 @@
|
|||
** DESCRIPTION:
|
||||
** Bit masking macros. XXX n must be <= 31 to be portable
|
||||
***********************************************************************/
|
||||
#define JS_BIT(n) ((JSUint32)1 << (n))
|
||||
#define JS_BIT(n) ((uint32_t)1 << (n))
|
||||
#define JS_BITMASK(n) (JS_BIT(n) - 1)
|
||||
|
||||
/***********************************************************************
|
||||
|
@ -305,14 +184,7 @@
|
|||
#define JS_MIN(x,y) ((x)<(y)?(x):(y))
|
||||
#define JS_MAX(x,y) ((x)>(y)?(x):(y))
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# include "jscpucfg.h" /* We can't auto-detect MSVC configuration */
|
||||
# if _MSC_VER < 1400
|
||||
# define NJ_NO_VARIADIC_MACROS
|
||||
# endif
|
||||
#else
|
||||
# include "jsautocfg.h" /* Use auto-detected configuration */
|
||||
#endif
|
||||
#include "jscpucfg.h"
|
||||
|
||||
/*
|
||||
* Define JS_64BIT iff we are building in an environment with 64-bit
|
||||
|
@ -323,11 +195,21 @@
|
|||
# define JS_64BIT
|
||||
# endif
|
||||
#elif defined(__GNUC__)
|
||||
# ifdef __x86_64__
|
||||
/* Additional GCC defines are when running on Solaris, AIX, and HPUX */
|
||||
# if defined(__x86_64__) || defined(__sparcv9) || \
|
||||
defined(__64BIT__) || defined(__LP64__)
|
||||
# define JS_64BIT
|
||||
# endif
|
||||
#elif defined(__SUNPRO_C) || defined(__SUNPRO_CC)
|
||||
# ifdef __x86_64
|
||||
#elif defined(__SUNPRO_C) || defined(__SUNPRO_CC) /* Sun Studio C/C++ */
|
||||
# if defined(__x86_64) || defined(__sparcv9)
|
||||
# define JS_64BIT
|
||||
# endif
|
||||
#elif defined(__xlc__) || defined(__xlC__) /* IBM XL C/C++ */
|
||||
# if defined(__64BIT__)
|
||||
# define JS_64BIT
|
||||
# endif
|
||||
#elif defined(__HP_cc) || defined(__HP_aCC) /* HP-UX cc/aCC */
|
||||
# if defined(__LP64__)
|
||||
# define JS_64BIT
|
||||
# endif
|
||||
#else
|
||||
|
@ -335,53 +217,8 @@
|
|||
#endif
|
||||
|
||||
|
||||
#include "jsinttypes.h"
|
||||
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
||||
/************************************************************************
|
||||
** TYPES: JSUintn
|
||||
** JSIntn
|
||||
** DESCRIPTION:
|
||||
** The JSIntn types are most appropriate for automatic variables. They are
|
||||
** guaranteed to be at least 16 bits, though various architectures may
|
||||
** define them to be wider (e.g., 32 or even 64 bits). These types are
|
||||
** never valid for fields of a structure.
|
||||
************************************************************************/
|
||||
|
||||
typedef int JSIntn;
|
||||
typedef unsigned int JSUintn;
|
||||
|
||||
/************************************************************************
|
||||
** TYPES: JSFloat64
|
||||
** DESCRIPTION:
|
||||
** NSPR's floating point type is always 64 bits.
|
||||
************************************************************************/
|
||||
typedef double JSFloat64;
|
||||
|
||||
/************************************************************************
|
||||
** TYPES: JSSize
|
||||
** DESCRIPTION:
|
||||
** A type for representing the size of objects.
|
||||
************************************************************************/
|
||||
typedef size_t JSSize;
|
||||
|
||||
/************************************************************************
|
||||
** TYPES: JSPtrDiff
|
||||
** DESCRIPTION:
|
||||
** A type for pointer difference. Variables of this type are suitable
|
||||
** for storing a pointer or pointer sutraction.
|
||||
************************************************************************/
|
||||
typedef ptrdiff_t JSPtrdiff;
|
||||
|
||||
/************************************************************************
|
||||
** TYPES: JSUptrdiff
|
||||
** DESCRIPTION:
|
||||
** A type for pointer difference. Variables of this type are suitable
|
||||
** for storing a pointer or pointer sutraction.
|
||||
************************************************************************/
|
||||
typedef JSUintPtr JSUptrdiff;
|
||||
|
||||
/************************************************************************
|
||||
** TYPES: JSBool
|
||||
** DESCRIPTION:
|
||||
|
@ -390,30 +227,9 @@ typedef JSUintPtr JSUptrdiff;
|
|||
** 'if (bool)', 'while (!bool)', '(bool) ? x : y' etc., to test booleans
|
||||
** just as you would C int-valued conditions.
|
||||
************************************************************************/
|
||||
typedef JSIntn JSBool;
|
||||
#define JS_TRUE (JSIntn)1
|
||||
#define JS_FALSE (JSIntn)0
|
||||
/*
|
||||
** Special: JS_NEITHER is used by the tracer to have tri-state booleans.
|
||||
** This should not be used in new code.
|
||||
*/
|
||||
#define JS_NEITHER (JSIntn)2
|
||||
|
||||
/************************************************************************
|
||||
** TYPES: JSPackedBool
|
||||
** DESCRIPTION:
|
||||
** Use JSPackedBool within structs where bitfields are not desireable
|
||||
** but minimum and consistent overhead matters.
|
||||
************************************************************************/
|
||||
typedef JSUint8 JSPackedBool;
|
||||
|
||||
/*
|
||||
** A JSWord is an integer that is the same size as a void*
|
||||
*/
|
||||
typedef JSIntPtr JSWord;
|
||||
typedef JSUintPtr JSUword;
|
||||
|
||||
#include "jsotypes.h"
|
||||
typedef int JSBool;
|
||||
#define JS_TRUE (int)1
|
||||
#define JS_FALSE (int)0
|
||||
|
||||
/***********************************************************************
|
||||
** MACROS: JS_LIKELY
|
||||
|
|
|
@ -44,377 +44,165 @@
|
|||
#ifndef jsutil_h___
|
||||
#define jsutil_h___
|
||||
|
||||
#include "jstypes.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "mozilla/Attributes.h"
|
||||
|
||||
JS_BEGIN_EXTERN_C
|
||||
#include "js/Utility.h"
|
||||
|
||||
/*
|
||||
* JS_Assert is present even in release builds, for the benefit of applications
|
||||
* that build DEBUG and link against a non-DEBUG SpiderMonkey library.
|
||||
*/
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_Assert(const char *s, const char *file, JSIntn ln);
|
||||
/* Forward declarations. */
|
||||
struct JSContext;
|
||||
|
||||
#define JS_CRASH_UNLESS(__cond) \
|
||||
JS_BEGIN_MACRO \
|
||||
if (!(__cond)) { \
|
||||
*(int *)(uintptr_t)0xccadbeef = 0; \
|
||||
((void(*)())0)(); /* More reliable, but doesn't say CCADBEEF */ \
|
||||
} \
|
||||
JS_END_MACRO
|
||||
static JS_ALWAYS_INLINE void *
|
||||
js_memcpy(void *dst_, const void *src_, size_t len)
|
||||
{
|
||||
char *dst = (char *) dst_;
|
||||
const char *src = (const char *) src_;
|
||||
JS_ASSERT_IF(dst >= src, (size_t) (dst - src) >= len);
|
||||
JS_ASSERT_IF(src >= dst, (size_t) (src - dst) >= len);
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
#define JS_ASSERT(expr) \
|
||||
((expr) ? (void)0 : JS_Assert(#expr, __FILE__, __LINE__))
|
||||
|
||||
#define JS_ASSERT_IF(cond, expr) \
|
||||
((!(cond) || (expr)) ? (void)0 : JS_Assert(#expr, __FILE__, __LINE__))
|
||||
|
||||
#define JS_NOT_REACHED(reason) \
|
||||
JS_Assert(reason, __FILE__, __LINE__)
|
||||
|
||||
#define JS_ALWAYS_TRUE(expr) JS_ASSERT(expr)
|
||||
|
||||
#define JS_ALWAYS_FALSE(expr) JS_ASSERT(!(expr))
|
||||
|
||||
# ifdef JS_THREADSAFE
|
||||
# define JS_THREADSAFE_ASSERT(expr) JS_ASSERT(expr)
|
||||
# else
|
||||
# define JS_THREADSAFE_ASSERT(expr) ((void) 0)
|
||||
# endif
|
||||
|
||||
#else
|
||||
|
||||
#define JS_ASSERT(expr) ((void) 0)
|
||||
#define JS_ASSERT_IF(cond,expr) ((void) 0)
|
||||
#define JS_NOT_REACHED(reason)
|
||||
#define JS_ALWAYS_TRUE(expr) ((void) (expr))
|
||||
#define JS_ALWAYS_FALSE(expr) ((void) (expr))
|
||||
#define JS_THREADSAFE_ASSERT(expr) ((void) 0)
|
||||
|
||||
#endif /* defined(DEBUG) */
|
||||
|
||||
/*
|
||||
* Compile-time assert. "cond" must be a constant expression.
|
||||
* The macro can be used only in places where an "extern" declaration is
|
||||
* allowed.
|
||||
*/
|
||||
|
||||
#ifdef __SUNPRO_CC
|
||||
/*
|
||||
* Sun Studio C++ compiler has a bug
|
||||
* "sizeof expression not accepted as size of array parameter"
|
||||
* It happens when js_static_assert() function is declared inside functions.
|
||||
* The bug number is 6688515. It is not public yet.
|
||||
* Therefore, for Sun Studio, declare js_static_assert as an array instead.
|
||||
*/
|
||||
#define JS_STATIC_ASSERT(cond) extern char js_static_assert[(cond) ? 1 : -1]
|
||||
#else
|
||||
#ifdef __COUNTER__
|
||||
#define JS_STATIC_ASSERT_GLUE1(x,y) x##y
|
||||
#define JS_STATIC_ASSERT_GLUE(x,y) JS_STATIC_ASSERT_GLUE1(x,y)
|
||||
#define JS_STATIC_ASSERT(cond) \
|
||||
typedef int JS_STATIC_ASSERT_GLUE(js_static_assert, __COUNTER__)[(cond) ? 1 : -1]
|
||||
#else
|
||||
#define JS_STATIC_ASSERT(cond) extern void js_static_assert(int arg[(cond) ? 1 : -1])
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define JS_STATIC_ASSERT_IF(cond, expr) JS_STATIC_ASSERT(!(cond) || (expr))
|
||||
|
||||
/*
|
||||
* Abort the process in a non-graceful manner. This will cause a core file,
|
||||
* call to the debugger or other moral equivalent as well as causing the
|
||||
* entire process to stop.
|
||||
*/
|
||||
extern JS_PUBLIC_API(void) JS_Abort(void);
|
||||
|
||||
#ifdef DEBUG
|
||||
# define JS_BASIC_STATS 1
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_brendan
|
||||
# define JS_SCOPE_DEPTH_METER 1
|
||||
#endif
|
||||
|
||||
#ifdef JS_BASIC_STATS
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
typedef struct JSBasicStats {
|
||||
uint32 num;
|
||||
uint32 max;
|
||||
double sum;
|
||||
double sqsum;
|
||||
uint32 logscale; /* logarithmic scale: 0 (linear), 2, 10 */
|
||||
uint32 hist[11];
|
||||
} JSBasicStats;
|
||||
|
||||
#define JS_INIT_STATIC_BASIC_STATS {0,0,0,0,0,{0,0,0,0,0,0,0,0,0,0,0}}
|
||||
#define JS_BASIC_STATS_INIT(bs) memset((bs), 0, sizeof(JSBasicStats))
|
||||
|
||||
#define JS_BASIC_STATS_ACCUM(bs,val) \
|
||||
JS_BasicStatsAccum(bs, val)
|
||||
|
||||
#define JS_MeanAndStdDevBS(bs,sigma) \
|
||||
JS_MeanAndStdDev((bs)->num, (bs)->sum, (bs)->sqsum, sigma)
|
||||
|
||||
extern void
|
||||
JS_BasicStatsAccum(JSBasicStats *bs, uint32 val);
|
||||
|
||||
extern double
|
||||
JS_MeanAndStdDev(uint32 num, double sum, double sqsum, double *sigma);
|
||||
|
||||
extern void
|
||||
JS_DumpBasicStats(JSBasicStats *bs, const char *title, FILE *fp);
|
||||
|
||||
extern void
|
||||
JS_DumpHistogram(JSBasicStats *bs, FILE *fp);
|
||||
|
||||
#else
|
||||
|
||||
#define JS_BASIC_STATS_ACCUM(bs,val) /* nothing */
|
||||
|
||||
#endif /* JS_BASIC_STATS */
|
||||
|
||||
|
||||
#if defined(DEBUG_notme) && defined(XP_UNIX)
|
||||
|
||||
typedef struct JSCallsite JSCallsite;
|
||||
|
||||
struct JSCallsite {
|
||||
uint32 pc;
|
||||
char *name;
|
||||
const char *library;
|
||||
int offset;
|
||||
JSCallsite *parent;
|
||||
JSCallsite *siblings;
|
||||
JSCallsite *kids;
|
||||
void *handy;
|
||||
};
|
||||
|
||||
extern JS_FRIEND_API(JSCallsite *)
|
||||
JS_Backtrace(int skip);
|
||||
|
||||
extern JS_FRIEND_API(void)
|
||||
JS_DumpBacktrace(JSCallsite *trace);
|
||||
#endif
|
||||
|
||||
#if defined JS_USE_CUSTOM_ALLOCATOR
|
||||
|
||||
#include "jscustomallocator.h"
|
||||
|
||||
#else
|
||||
|
||||
static JS_INLINE void* js_malloc(size_t bytes) {
|
||||
return malloc(bytes);
|
||||
return memcpy(dst, src, len);
|
||||
}
|
||||
|
||||
static JS_INLINE void* js_calloc(size_t bytes) {
|
||||
return calloc(bytes, 1);
|
||||
}
|
||||
|
||||
static JS_INLINE void* js_realloc(void* p, size_t bytes) {
|
||||
return realloc(p, bytes);
|
||||
}
|
||||
|
||||
static JS_INLINE void js_free(void* p) {
|
||||
free(p);
|
||||
}
|
||||
#endif/* JS_USE_CUSTOM_ALLOCATOR */
|
||||
|
||||
JS_END_EXTERN_C
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
/*
|
||||
* Using vanilla new/new[] is unsafe in SpiderMonkey because they throw on
|
||||
* failure instead of returning NULL, which is what SpiderMonkey expects.
|
||||
* js_new()/js_array_new() should be used instead, and memory allocated with
|
||||
* them should be deallocated with js_delete()/js_array_delete().
|
||||
*
|
||||
* If you have a class with a private constructor or destructor, you can
|
||||
* make js_new/js_delete a friend. This can be fiddly, and the interaction of
|
||||
* template functions, friend functions and namespaces can overwhelm even
|
||||
* modern compilers. Manual inlining is probably easier.
|
||||
*
|
||||
* (If you're wondering why we can't just use the 'nothrow' variant of
|
||||
* new/new[], it's because we want to mediate *all* allocations within
|
||||
* SpiderMonkey, to satisfy any embedders using JS_USE_CUSTOM_ALLOCATOR.)
|
||||
*/
|
||||
|
||||
#define JS_NEW_BODY(t, parms) \
|
||||
void *memory = js_malloc(sizeof(t)); \
|
||||
return memory ? new(memory) t parms : NULL;
|
||||
|
||||
template <class T>
|
||||
JS_ALWAYS_INLINE T *js_new() {
|
||||
JS_NEW_BODY(T, ())
|
||||
}
|
||||
|
||||
template <class T, class P1>
|
||||
JS_ALWAYS_INLINE T *js_new(const P1 &p1) {
|
||||
JS_NEW_BODY(T, (p1))
|
||||
}
|
||||
|
||||
template <class T, class P1, class P2>
|
||||
JS_ALWAYS_INLINE T *js_new(const P1 &p1, const P2 &p2) {
|
||||
JS_NEW_BODY(T, (p1, p2))
|
||||
}
|
||||
|
||||
template <class T, class P1, class P2, class P3>
|
||||
JS_ALWAYS_INLINE T *js_new(const P1 &p1, const P2 &p2, const P3 &p3) {
|
||||
JS_NEW_BODY(T, (p1, p2, p3))
|
||||
}
|
||||
|
||||
template <class T, class P1, class P2, class P3, class P4>
|
||||
JS_ALWAYS_INLINE T *js_new(const P1 &p1, const P2 &p2, const P3 &p3, const P4 &p4) {
|
||||
JS_NEW_BODY(T, (p1, p2, p3, p4))
|
||||
}
|
||||
|
||||
/* ...add additional js_new()s as necessary... */
|
||||
|
||||
#undef JS_NEW_BODY
|
||||
|
||||
template <class T>
|
||||
JS_ALWAYS_INLINE void js_delete(T *p) {
|
||||
if (p) {
|
||||
p->~T();
|
||||
js_free(p);
|
||||
}
|
||||
}
|
||||
|
||||
static const int JSMinAlignment = 8;
|
||||
|
||||
template <class T>
|
||||
JS_ALWAYS_INLINE T *js_array_new(size_t n) {
|
||||
/* The length is stored just before the vector memory. */
|
||||
uint64 numBytes64 = uint64(JSMinAlignment) + uint64(sizeof(T)) * uint64(n);
|
||||
size_t numBytes = size_t(numBytes64);
|
||||
if (numBytes64 != numBytes) {
|
||||
JS_ASSERT(0); /* we want to know if this happens in debug builds */
|
||||
return NULL;
|
||||
}
|
||||
void *memory = js_malloc(numBytes);
|
||||
if (!memory)
|
||||
return NULL;
|
||||
*(size_t *)memory = n;
|
||||
memory = (void*)(uintptr_t(memory) + JSMinAlignment);
|
||||
return new(memory) T[n];
|
||||
}
|
||||
|
||||
template <class T>
|
||||
JS_ALWAYS_INLINE void js_array_delete(T *p) {
|
||||
if (p) {
|
||||
void* p0 = (void *)(uintptr_t(p) - JSMinAlignment);
|
||||
size_t n = *(size_t *)p0;
|
||||
for (size_t i = 0; i < n; i++)
|
||||
(p + i)->~T();
|
||||
js_free(p0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The following classes are designed to cause assertions to detect
|
||||
* inadvertent use of guard objects as temporaries. In other words,
|
||||
* when we have a guard object whose only purpose is its constructor and
|
||||
* destructor (and is never otherwise referenced), the intended use
|
||||
* might be:
|
||||
* JSAutoTempValueRooter tvr(cx, 1, &val);
|
||||
* but is is easy to accidentally write:
|
||||
* JSAutoTempValueRooter(cx, 1, &val);
|
||||
* which compiles just fine, but runs the destructor well before the
|
||||
* intended time.
|
||||
*
|
||||
* They work by adding (#ifdef DEBUG) an additional parameter to the
|
||||
* guard object's constructor, with a default value, so that users of
|
||||
* the guard object's API do not need to do anything. The default value
|
||||
* of this parameter is a temporary object. C++ (ISO/IEC 14882:1998),
|
||||
* section 12.2 [class.temporary], clauses 4 and 5 seem to assume a
|
||||
* guarantee that temporaries are destroyed in the reverse of their
|
||||
* construction order, but I actually can't find a statement that that
|
||||
* is true in the general case (beyond the two specific cases mentioned
|
||||
* there). However, it seems to be true.
|
||||
*
|
||||
* These classes are intended to be used only via the macros immediately
|
||||
* below them:
|
||||
* JS_DECL_USE_GUARD_OBJECT_NOTIFIER declares (ifdef DEBUG) a member
|
||||
* variable, and should be put where a declaration of a private
|
||||
* member variable would be placed.
|
||||
* JS_GUARD_OBJECT_NOTIFIER_PARAM should be placed at the end of the
|
||||
* parameters to each constructor of the guard object; it declares
|
||||
* (ifdef DEBUG) an additional parameter.
|
||||
* JS_GUARD_OBJECT_NOTIFIER_INIT is a statement that belongs in each
|
||||
* constructor. It uses the parameter declared by
|
||||
* JS_GUARD_OBJECT_NOTIFIER_PARAM.
|
||||
*/
|
||||
#ifdef DEBUG
|
||||
class JSGuardObjectNotifier
|
||||
{
|
||||
private:
|
||||
bool* mStatementDone;
|
||||
public:
|
||||
JSGuardObjectNotifier() : mStatementDone(NULL) {}
|
||||
|
||||
~JSGuardObjectNotifier() {
|
||||
*mStatementDone = true;
|
||||
}
|
||||
|
||||
void setStatementDone(bool *aStatementDone) {
|
||||
mStatementDone = aStatementDone;
|
||||
}
|
||||
};
|
||||
|
||||
class JSGuardObjectNotificationReceiver
|
||||
{
|
||||
private:
|
||||
bool mStatementDone;
|
||||
public:
|
||||
JSGuardObjectNotificationReceiver() : mStatementDone(false) {}
|
||||
|
||||
~JSGuardObjectNotificationReceiver() {
|
||||
/*
|
||||
* Assert that the guard object was not used as a temporary.
|
||||
* (Note that this assert might also fire if Init is not called
|
||||
* because the guard object's implementation is not using the
|
||||
* above macros correctly.)
|
||||
*/
|
||||
JS_ASSERT(mStatementDone);
|
||||
}
|
||||
|
||||
void Init(const JSGuardObjectNotifier &aNotifier) {
|
||||
/*
|
||||
* aNotifier is passed as a const reference so that we can pass a
|
||||
* temporary, but we really intend it as non-const
|
||||
*/
|
||||
const_cast<JSGuardObjectNotifier&>(aNotifier).
|
||||
setStatementDone(&mStatementDone);
|
||||
}
|
||||
};
|
||||
|
||||
#define JS_DECL_USE_GUARD_OBJECT_NOTIFIER \
|
||||
JSGuardObjectNotificationReceiver _mCheckNotUsedAsTemporary;
|
||||
#define JS_GUARD_OBJECT_NOTIFIER_PARAM \
|
||||
, const JSGuardObjectNotifier& _notifier = JSGuardObjectNotifier()
|
||||
#define JS_GUARD_OBJECT_NOTIFIER_PARAM0 \
|
||||
const JSGuardObjectNotifier& _notifier = JSGuardObjectNotifier()
|
||||
#define JS_GUARD_OBJECT_NOTIFIER_INIT \
|
||||
JS_BEGIN_MACRO _mCheckNotUsedAsTemporary.Init(_notifier); JS_END_MACRO
|
||||
|
||||
#else /* defined(DEBUG) */
|
||||
|
||||
#define JS_DECL_USE_GUARD_OBJECT_NOTIFIER
|
||||
#define JS_GUARD_OBJECT_NOTIFIER_PARAM
|
||||
#define JS_GUARD_OBJECT_NOTIFIER_PARAM0
|
||||
#define JS_GUARD_OBJECT_NOTIFIER_INIT JS_BEGIN_MACRO JS_END_MACRO
|
||||
|
||||
#endif /* !defined(DEBUG) */
|
||||
|
||||
namespace js {
|
||||
|
||||
template <class T>
|
||||
struct AlignmentTestStruct
|
||||
{
|
||||
char c;
|
||||
T t;
|
||||
};
|
||||
|
||||
/* This macro determines the alignment requirements of a type. */
|
||||
#define JS_ALIGNMENT_OF(t_) \
|
||||
(sizeof(js::AlignmentTestStruct<t_>) - sizeof(t_))
|
||||
|
||||
template <class T>
|
||||
class AlignedPtrAndFlag
|
||||
{
|
||||
uintptr_t bits;
|
||||
|
||||
public:
|
||||
AlignedPtrAndFlag(T *t, bool flag) {
|
||||
JS_ASSERT((uintptr_t(t) & 1) == 0);
|
||||
bits = uintptr_t(t) | uintptr_t(flag);
|
||||
}
|
||||
|
||||
T *ptr() const {
|
||||
return (T *)(bits & ~uintptr_t(1));
|
||||
}
|
||||
|
||||
bool flag() const {
|
||||
return (bits & 1) != 0;
|
||||
}
|
||||
|
||||
void setPtr(T *t) {
|
||||
JS_ASSERT((uintptr_t(t) & 1) == 0);
|
||||
bits = uintptr_t(t) | uintptr_t(flag());
|
||||
}
|
||||
|
||||
void setFlag() {
|
||||
bits |= 1;
|
||||
}
|
||||
|
||||
void unsetFlag() {
|
||||
bits &= ~uintptr_t(1);
|
||||
}
|
||||
|
||||
void set(T *t, bool flag) {
|
||||
JS_ASSERT((uintptr_t(t) & 1) == 0);
|
||||
bits = uintptr_t(t) | flag;
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
static inline void
|
||||
Reverse(T *beg, T *end)
|
||||
{
|
||||
while (beg != end) {
|
||||
if (--end == beg)
|
||||
return;
|
||||
T tmp = *beg;
|
||||
*beg = *end;
|
||||
*end = tmp;
|
||||
++beg;
|
||||
}
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static inline T *
|
||||
Find(T *beg, T *end, const T &v)
|
||||
{
|
||||
for (T *p = beg; p != end; ++p) {
|
||||
if (*p == v)
|
||||
return p;
|
||||
}
|
||||
return end;
|
||||
}
|
||||
|
||||
template <class Container>
|
||||
static inline typename Container::ElementType *
|
||||
Find(Container &c, const typename Container::ElementType &v)
|
||||
{
|
||||
return Find(c.begin(), c.end(), v);
|
||||
}
|
||||
|
||||
template <typename InputIterT, typename CallableT>
|
||||
void
|
||||
ForEach(InputIterT begin, InputIterT end, CallableT f)
|
||||
{
|
||||
for (; begin != end; ++begin)
|
||||
f(*begin);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static inline T
|
||||
Min(T t1, T t2)
|
||||
{
|
||||
return t1 < t2 ? t1 : t2;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static inline T
|
||||
Max(T t1, T t2)
|
||||
{
|
||||
return t1 > t2 ? t1 : t2;
|
||||
}
|
||||
|
||||
/* Allows a const variable to be initialized after its declaration. */
|
||||
template <class T>
|
||||
static T&
|
||||
InitConst(const T &t)
|
||||
{
|
||||
return const_cast<T &>(t);
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
JS_ALWAYS_INLINE T &
|
||||
ImplicitCast(U &u)
|
||||
{
|
||||
T &t = u;
|
||||
return t;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
class AutoScopedAssign
|
||||
{
|
||||
private:
|
||||
JS_DECL_USE_GUARD_OBJECT_NOTIFIER
|
||||
T *addr;
|
||||
T old;
|
||||
|
||||
public:
|
||||
AutoScopedAssign(T *addr, const T &value JS_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||
: addr(addr), old(*addr)
|
||||
{
|
||||
JS_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
*addr = value;
|
||||
}
|
||||
|
||||
~AutoScopedAssign() { *addr = old; }
|
||||
};
|
||||
|
||||
template <class T>
|
||||
JS_ALWAYS_INLINE static void
|
||||
PodZero(T *t)
|
||||
|
@ -426,7 +214,14 @@ template <class T>
|
|||
JS_ALWAYS_INLINE static void
|
||||
PodZero(T *t, size_t nelem)
|
||||
{
|
||||
memset(t, 0, nelem * sizeof(T));
|
||||
/*
|
||||
* This function is often called with 'nelem' small; we use an
|
||||
* inline loop instead of calling 'memset' with a non-constant
|
||||
* length. The compiler should inline the memset call with constant
|
||||
* size, though.
|
||||
*/
|
||||
for (T *end = t + nelem; t != end; ++t)
|
||||
memset(t, 0, sizeof(T));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -446,6 +241,13 @@ PodArrayZero(T (&t)[N])
|
|||
memset(t, 0, N * sizeof(T));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
JS_ALWAYS_INLINE static void
|
||||
PodAssign(T *dst, const T *src)
|
||||
{
|
||||
js_memcpy((char *) dst, (const char *) src, sizeof(T));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
JS_ALWAYS_INLINE static void
|
||||
PodCopy(T *dst, const T *src, size_t nelem)
|
||||
|
@ -455,15 +257,232 @@ PodCopy(T *dst, const T *src, size_t nelem)
|
|||
JS_ASSERT_IF(src >= dst, size_t(src - dst) >= nelem);
|
||||
|
||||
if (nelem < 128) {
|
||||
/*
|
||||
* Avoid using operator= in this loop, as it may have been
|
||||
* intentionally deleted by the POD type.
|
||||
*/
|
||||
for (const T *srcend = src + nelem; src != srcend; ++src, ++dst)
|
||||
*dst = *src;
|
||||
PodAssign(dst, src);
|
||||
} else {
|
||||
memcpy(dst, src, nelem * sizeof(T));
|
||||
}
|
||||
}
|
||||
|
||||
} /* namespace js */
|
||||
template <class T>
|
||||
JS_ALWAYS_INLINE static bool
|
||||
PodEqual(T *one, T *two, size_t len)
|
||||
{
|
||||
if (len < 128) {
|
||||
T *p1end = one + len;
|
||||
for (T *p1 = one, *p2 = two; p1 != p1end; ++p1, ++p2) {
|
||||
if (*p1 != *p2)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif /* defined(__cplusplus) */
|
||||
return !memcmp(one, two, len * sizeof(T));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
JS_ALWAYS_INLINE static void
|
||||
Swap(T &t, T &u)
|
||||
{
|
||||
T tmp(Move(t));
|
||||
t = Move(u);
|
||||
u = Move(tmp);
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE static size_t
|
||||
UnsignedPtrDiff(const void *bigger, const void *smaller)
|
||||
{
|
||||
return size_t(bigger) - size_t(smaller);
|
||||
}
|
||||
|
||||
/*
|
||||
* Ordinarily, a function taking a JSContext* 'cx' parameter reports errors on
|
||||
* the context. In some cases, functions optionally report and indicate this by
|
||||
* taking a nullable 'maybecx' parameter. In some cases, though, a function
|
||||
* always needs a 'cx', but optionally reports. This option is presented by the
|
||||
* MaybeReportError.
|
||||
*/
|
||||
enum MaybeReportError { REPORT_ERROR = true, DONT_REPORT_ERROR = false };
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* A bit array is an array of bits represented by an array of words (size_t). */
|
||||
|
||||
static inline unsigned
|
||||
NumWordsForBitArrayOfLength(size_t length)
|
||||
{
|
||||
return (length + (JS_BITS_PER_WORD - 1)) / JS_BITS_PER_WORD;
|
||||
}
|
||||
|
||||
static inline unsigned
|
||||
BitArrayIndexToWordIndex(size_t length, size_t bitIndex)
|
||||
{
|
||||
unsigned wordIndex = bitIndex / JS_BITS_PER_WORD;
|
||||
JS_ASSERT(wordIndex < length);
|
||||
return wordIndex;
|
||||
}
|
||||
|
||||
static inline size_t
|
||||
BitArrayIndexToWordMask(size_t i)
|
||||
{
|
||||
return size_t(1) << (i % JS_BITS_PER_WORD);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
IsBitArrayElementSet(size_t *array, size_t length, size_t i)
|
||||
{
|
||||
return array[BitArrayIndexToWordIndex(length, i)] & BitArrayIndexToWordMask(i);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
IsAnyBitArrayElementSet(size_t *array, size_t length)
|
||||
{
|
||||
unsigned numWords = NumWordsForBitArrayOfLength(length);
|
||||
for (unsigned i = 0; i < numWords; ++i) {
|
||||
if (array[i])
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline void
|
||||
SetBitArrayElement(size_t *array, size_t length, size_t i)
|
||||
{
|
||||
array[BitArrayIndexToWordIndex(length, i)] |= BitArrayIndexToWordMask(i);
|
||||
}
|
||||
|
||||
static inline void
|
||||
ClearBitArrayElement(size_t *array, size_t length, size_t i)
|
||||
{
|
||||
array[BitArrayIndexToWordIndex(length, i)] &= ~BitArrayIndexToWordMask(i);
|
||||
}
|
||||
|
||||
static inline void
|
||||
ClearAllBitArrayElements(size_t *array, size_t length)
|
||||
{
|
||||
for (unsigned i = 0; i < length; ++i)
|
||||
array[i] = 0;
|
||||
}
|
||||
|
||||
} /* namespace js */
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/*
|
||||
* JS_ROTATE_LEFT32
|
||||
*
|
||||
* There is no rotate operation in the C Language so the construct (a << 4) |
|
||||
* (a >> 28) is used instead. Most compilers convert this to a rotate
|
||||
* instruction but some versions of MSVC don't without a little help. To get
|
||||
* MSVC to generate a rotate instruction, we have to use the _rotl intrinsic
|
||||
* and use a pragma to make _rotl inline.
|
||||
*
|
||||
* MSVC in VS2005 will do an inline rotate instruction on the above construct.
|
||||
*/
|
||||
#if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_AMD64) || \
|
||||
defined(_M_X64))
|
||||
#include <stdlib.h>
|
||||
#pragma intrinsic(_rotl)
|
||||
#define JS_ROTATE_LEFT32(a, bits) _rotl(a, bits)
|
||||
#else
|
||||
#define JS_ROTATE_LEFT32(a, bits) (((a) << (bits)) | ((a) >> (32 - (bits))))
|
||||
#endif
|
||||
|
||||
/* Static control-flow checks. */
|
||||
#ifdef NS_STATIC_CHECKING
|
||||
/* Trigger a control flow check to make sure that code flows through label */
|
||||
inline __attribute__ ((unused)) void MUST_FLOW_THROUGH(const char *label) {}
|
||||
|
||||
/* Avoid unused goto-label warnings. */
|
||||
# define MUST_FLOW_LABEL(label) goto label; label:
|
||||
|
||||
#else
|
||||
# define MUST_FLOW_THROUGH(label) ((void) 0)
|
||||
# define MUST_FLOW_LABEL(label)
|
||||
#endif
|
||||
|
||||
/* Crash diagnostics */
|
||||
#ifdef DEBUG
|
||||
# define JS_CRASH_DIAGNOSTICS 1
|
||||
#endif
|
||||
#ifdef JS_CRASH_DIAGNOSTICS
|
||||
# define JS_POISON(p, val, size) memset((p), (val), (size))
|
||||
# define JS_OPT_ASSERT(expr) \
|
||||
((expr) ? (void)0 : MOZ_Assert(#expr, __FILE__, __LINE__))
|
||||
# define JS_OPT_ASSERT_IF(cond, expr) \
|
||||
((!(cond) || (expr)) ? (void)0 : MOZ_Assert(#expr, __FILE__, __LINE__))
|
||||
#else
|
||||
# define JS_POISON(p, val, size) ((void) 0)
|
||||
# define JS_OPT_ASSERT(expr) ((void) 0)
|
||||
# define JS_OPT_ASSERT_IF(cond, expr) ((void) 0)
|
||||
#endif
|
||||
|
||||
/* Basic stats */
|
||||
#ifdef DEBUG
|
||||
# define JS_BASIC_STATS 1
|
||||
#endif
|
||||
#ifdef JS_BASIC_STATS
|
||||
# include <stdio.h>
|
||||
typedef struct JSBasicStats {
|
||||
uint32_t num;
|
||||
uint32_t max;
|
||||
double sum;
|
||||
double sqsum;
|
||||
uint32_t logscale; /* logarithmic scale: 0 (linear), 2, 10 */
|
||||
uint32_t hist[11];
|
||||
} JSBasicStats;
|
||||
# define JS_INIT_STATIC_BASIC_STATS {0,0,0,0,0,{0,0,0,0,0,0,0,0,0,0,0}}
|
||||
# define JS_BASIC_STATS_INIT(bs) memset((bs), 0, sizeof(JSBasicStats))
|
||||
# define JS_BASIC_STATS_ACCUM(bs,val) \
|
||||
JS_BasicStatsAccum(bs, val)
|
||||
# define JS_MeanAndStdDevBS(bs,sigma) \
|
||||
JS_MeanAndStdDev((bs)->num, (bs)->sum, (bs)->sqsum, sigma)
|
||||
extern void
|
||||
JS_BasicStatsAccum(JSBasicStats *bs, uint32_t val);
|
||||
extern double
|
||||
JS_MeanAndStdDev(uint32_t num, double sum, double sqsum, double *sigma);
|
||||
extern void
|
||||
JS_DumpBasicStats(JSBasicStats *bs, const char *title, FILE *fp);
|
||||
extern void
|
||||
JS_DumpHistogram(JSBasicStats *bs, FILE *fp);
|
||||
#else
|
||||
# define JS_BASIC_STATS_ACCUM(bs,val)
|
||||
#endif
|
||||
|
||||
/* A jsbitmap_t is a long integer that can be used for bitmaps. */
|
||||
typedef size_t jsbitmap;
|
||||
#define JS_TEST_BIT(_map,_bit) ((_map)[(_bit)>>JS_BITS_PER_WORD_LOG2] & \
|
||||
((jsbitmap)1<<((_bit)&(JS_BITS_PER_WORD-1))))
|
||||
#define JS_SET_BIT(_map,_bit) ((_map)[(_bit)>>JS_BITS_PER_WORD_LOG2] |= \
|
||||
((jsbitmap)1<<((_bit)&(JS_BITS_PER_WORD-1))))
|
||||
#define JS_CLEAR_BIT(_map,_bit) ((_map)[(_bit)>>JS_BITS_PER_WORD_LOG2] &= \
|
||||
~((jsbitmap)1<<((_bit)&(JS_BITS_PER_WORD-1))))
|
||||
|
||||
/* Wrapper for various macros to stop warnings coming from their expansions. */
|
||||
#if defined(__clang__)
|
||||
# define JS_SILENCE_UNUSED_VALUE_IN_EXPR(expr) \
|
||||
JS_BEGIN_MACRO \
|
||||
_Pragma("clang diagnostic push") \
|
||||
_Pragma("clang diagnostic ignored \"-Wunused-value\"") \
|
||||
expr; \
|
||||
_Pragma("clang diagnostic pop") \
|
||||
JS_END_MACRO
|
||||
#elif (__GNUC__ >= 5) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
|
||||
# define JS_SILENCE_UNUSED_VALUE_IN_EXPR(expr) \
|
||||
JS_BEGIN_MACRO \
|
||||
_Pragma("GCC diagnostic push") \
|
||||
_Pragma("GCC diagnostic ignored \"-Wunused-but-set-variable\"") \
|
||||
expr; \
|
||||
_Pragma("GCC diagnostic pop") \
|
||||
JS_END_MACRO
|
||||
#else
|
||||
# define JS_SILENCE_UNUSED_VALUE_IN_EXPR(expr) \
|
||||
JS_BEGIN_MACRO \
|
||||
expr; \
|
||||
JS_END_MACRO
|
||||
#endif
|
||||
|
||||
#endif /* jsutil_h___ */
|
||||
|
|
|
@ -39,13 +39,14 @@
|
|||
|
||||
#ifndef jsvalimpl_h__
|
||||
#define jsvalimpl_h__
|
||||
|
||||
/*
|
||||
* JS value implementation details for operations on jsval and jsid.
|
||||
* Embeddings should not rely on any of the definitions in this file. For a
|
||||
* description of the value representation and the engine-internal C++ value
|
||||
* interface, js::Value, see jsvalue.h.
|
||||
* Implementation details for js::Value in jsapi.h.
|
||||
*/
|
||||
#include "jsutil.h"
|
||||
|
||||
#include "mozilla/FloatingPoint.h"
|
||||
|
||||
#include "js/Utility.h"
|
||||
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
||||
|
@ -53,7 +54,7 @@ JS_BEGIN_EXTERN_C
|
|||
* Try to get jsvals 64-bit aligned. We could almost assert that all values are
|
||||
* aligned, but MSVC and GCC occasionally break alignment.
|
||||
*/
|
||||
#ifdef __GNUC__
|
||||
#if defined(__GNUC__) || defined(__xlc__) || defined(__xlC__)
|
||||
# define JSVAL_ALIGNMENT __attribute__((aligned (8)))
|
||||
#elif defined(_MSC_VER)
|
||||
/*
|
||||
|
@ -63,6 +64,8 @@ JS_BEGIN_EXTERN_C
|
|||
# define JSVAL_ALIGNMENT
|
||||
#elif defined(__SUNPRO_C) || defined(__SUNPRO_CC)
|
||||
# define JSVAL_ALIGNMENT
|
||||
#elif defined(__HP_cc) || defined(__HP_aCC)
|
||||
# define JSVAL_ALIGNMENT
|
||||
#endif
|
||||
|
||||
#if JS_BITS_PER_WORD == 64
|
||||
|
@ -74,22 +77,18 @@ JS_BEGIN_EXTERN_C
|
|||
* nice symbolic type tags, however we can only do this when we can force the
|
||||
* underlying type of the enum to be the desired size.
|
||||
*/
|
||||
#if defined(__cplusplus) && !defined(__SUNPRO_CC)
|
||||
#if defined(__cplusplus) && !defined(__SUNPRO_CC) && !defined(__xlC__)
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
# define JS_ENUM_HEADER(id, type) enum id : type
|
||||
# define JS_ENUM_MEMBER(id, type, value) id = (type)value,
|
||||
# define JS_LAST_ENUM_MEMBER(id, type, value) id = (type)value
|
||||
# define JS_ENUM_FOOTER(id)
|
||||
#else
|
||||
# define JS_ENUM_HEADER(id, type) enum id
|
||||
# define JS_ENUM_MEMBER(id, type, value) id = (type)value,
|
||||
# define JS_LAST_ENUM_MEMBER(id, type, value) id = (type)value
|
||||
# define JS_ENUM_FOOTER(id) __attribute__((packed))
|
||||
#endif
|
||||
|
||||
/* Remember to propagate changes to the C defines below. */
|
||||
JS_ENUM_HEADER(JSValueType, uint8)
|
||||
JS_ENUM_HEADER(JSValueType, uint8_t)
|
||||
{
|
||||
JSVAL_TYPE_DOUBLE = 0x00,
|
||||
JSVAL_TYPE_INT32 = 0x01,
|
||||
|
@ -100,15 +99,9 @@ JS_ENUM_HEADER(JSValueType, uint8)
|
|||
JSVAL_TYPE_NULL = 0x06,
|
||||
JSVAL_TYPE_OBJECT = 0x07,
|
||||
|
||||
/* The below types never appear in a jsval; they are only used in tracing. */
|
||||
|
||||
JSVAL_TYPE_NONFUNOBJ = 0x57,
|
||||
JSVAL_TYPE_FUNOBJ = 0x67,
|
||||
|
||||
JSVAL_TYPE_STRORNULL = 0x97,
|
||||
JSVAL_TYPE_OBJORNULL = 0x98,
|
||||
|
||||
JSVAL_TYPE_BOXED = 0x99
|
||||
/* These never appear in a jsval; they are only provided as an out-of-band value. */
|
||||
JSVAL_TYPE_UNKNOWN = 0x20,
|
||||
JSVAL_TYPE_MISSING = 0x21
|
||||
} JS_ENUM_FOOTER(JSValueType);
|
||||
|
||||
JS_STATIC_ASSERT(sizeof(JSValueType) == 1);
|
||||
|
@ -116,9 +109,9 @@ JS_STATIC_ASSERT(sizeof(JSValueType) == 1);
|
|||
#if JS_BITS_PER_WORD == 32
|
||||
|
||||
/* Remember to propagate changes to the C defines below. */
|
||||
JS_ENUM_HEADER(JSValueTag, uint32)
|
||||
JS_ENUM_HEADER(JSValueTag, uint32_t)
|
||||
{
|
||||
JSVAL_TAG_CLEAR = 0xFFFF0000,
|
||||
JSVAL_TAG_CLEAR = 0xFFFFFF80,
|
||||
JSVAL_TAG_INT32 = JSVAL_TAG_CLEAR | JSVAL_TYPE_INT32,
|
||||
JSVAL_TAG_UNDEFINED = JSVAL_TAG_CLEAR | JSVAL_TYPE_UNDEFINED,
|
||||
JSVAL_TAG_STRING = JSVAL_TAG_CLEAR | JSVAL_TYPE_STRING,
|
||||
|
@ -133,7 +126,7 @@ JS_STATIC_ASSERT(sizeof(JSValueTag) == 4);
|
|||
#elif JS_BITS_PER_WORD == 64
|
||||
|
||||
/* Remember to propagate changes to the C defines below. */
|
||||
JS_ENUM_HEADER(JSValueTag, uint32)
|
||||
JS_ENUM_HEADER(JSValueTag, uint32_t)
|
||||
{
|
||||
JSVAL_TAG_MAX_DOUBLE = 0x1FFF0,
|
||||
JSVAL_TAG_INT32 = JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_INT32,
|
||||
|
@ -145,75 +138,70 @@ JS_ENUM_HEADER(JSValueTag, uint32)
|
|||
JSVAL_TAG_OBJECT = JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_OBJECT
|
||||
} JS_ENUM_FOOTER(JSValueTag);
|
||||
|
||||
JS_STATIC_ASSERT(sizeof(JSValueTag) == sizeof(uint32));
|
||||
JS_STATIC_ASSERT(sizeof(JSValueTag) == sizeof(uint32_t));
|
||||
|
||||
JS_ENUM_HEADER(JSValueShiftedTag, uint64)
|
||||
JS_ENUM_HEADER(JSValueShiftedTag, uint64_t)
|
||||
{
|
||||
JSVAL_SHIFTED_TAG_MAX_DOUBLE = ((((uint64)JSVAL_TAG_MAX_DOUBLE) << JSVAL_TAG_SHIFT) | 0xFFFFFFFF),
|
||||
JSVAL_SHIFTED_TAG_INT32 = (((uint64)JSVAL_TAG_INT32) << JSVAL_TAG_SHIFT),
|
||||
JSVAL_SHIFTED_TAG_UNDEFINED = (((uint64)JSVAL_TAG_UNDEFINED) << JSVAL_TAG_SHIFT),
|
||||
JSVAL_SHIFTED_TAG_STRING = (((uint64)JSVAL_TAG_STRING) << JSVAL_TAG_SHIFT),
|
||||
JSVAL_SHIFTED_TAG_BOOLEAN = (((uint64)JSVAL_TAG_BOOLEAN) << JSVAL_TAG_SHIFT),
|
||||
JSVAL_SHIFTED_TAG_MAGIC = (((uint64)JSVAL_TAG_MAGIC) << JSVAL_TAG_SHIFT),
|
||||
JSVAL_SHIFTED_TAG_NULL = (((uint64)JSVAL_TAG_NULL) << JSVAL_TAG_SHIFT),
|
||||
JSVAL_SHIFTED_TAG_OBJECT = (((uint64)JSVAL_TAG_OBJECT) << JSVAL_TAG_SHIFT)
|
||||
JSVAL_SHIFTED_TAG_MAX_DOUBLE = ((((uint64_t)JSVAL_TAG_MAX_DOUBLE) << JSVAL_TAG_SHIFT) | 0xFFFFFFFF),
|
||||
JSVAL_SHIFTED_TAG_INT32 = (((uint64_t)JSVAL_TAG_INT32) << JSVAL_TAG_SHIFT),
|
||||
JSVAL_SHIFTED_TAG_UNDEFINED = (((uint64_t)JSVAL_TAG_UNDEFINED) << JSVAL_TAG_SHIFT),
|
||||
JSVAL_SHIFTED_TAG_STRING = (((uint64_t)JSVAL_TAG_STRING) << JSVAL_TAG_SHIFT),
|
||||
JSVAL_SHIFTED_TAG_BOOLEAN = (((uint64_t)JSVAL_TAG_BOOLEAN) << JSVAL_TAG_SHIFT),
|
||||
JSVAL_SHIFTED_TAG_MAGIC = (((uint64_t)JSVAL_TAG_MAGIC) << JSVAL_TAG_SHIFT),
|
||||
JSVAL_SHIFTED_TAG_NULL = (((uint64_t)JSVAL_TAG_NULL) << JSVAL_TAG_SHIFT),
|
||||
JSVAL_SHIFTED_TAG_OBJECT = (((uint64_t)JSVAL_TAG_OBJECT) << JSVAL_TAG_SHIFT)
|
||||
} JS_ENUM_FOOTER(JSValueShiftedTag);
|
||||
|
||||
JS_STATIC_ASSERT(sizeof(JSValueShiftedTag) == sizeof(uint64));
|
||||
JS_STATIC_ASSERT(sizeof(JSValueShiftedTag) == sizeof(uint64_t));
|
||||
|
||||
#endif
|
||||
|
||||
#else /* defined(__cplusplus) */
|
||||
|
||||
typedef uint8 JSValueType;
|
||||
#define JSVAL_TYPE_DOUBLE ((uint8)0x00)
|
||||
#define JSVAL_TYPE_INT32 ((uint8)0x01)
|
||||
#define JSVAL_TYPE_UNDEFINED ((uint8)0x02)
|
||||
#define JSVAL_TYPE_BOOLEAN ((uint8)0x03)
|
||||
#define JSVAL_TYPE_MAGIC ((uint8)0x04)
|
||||
#define JSVAL_TYPE_STRING ((uint8)0x05)
|
||||
#define JSVAL_TYPE_NULL ((uint8)0x06)
|
||||
#define JSVAL_TYPE_OBJECT ((uint8)0x07)
|
||||
#define JSVAL_TYPE_NONFUNOBJ ((uint8)0x57)
|
||||
#define JSVAL_TYPE_FUNOBJ ((uint8)0x67)
|
||||
#define JSVAL_TYPE_STRORNULL ((uint8)0x97)
|
||||
#define JSVAL_TYPE_OBJORNULL ((uint8)0x98)
|
||||
#define JSVAL_TYPE_BOXED ((uint8)0x99)
|
||||
#define JSVAL_TYPE_UNINITIALIZED ((uint8)0xcd)
|
||||
typedef uint8_t JSValueType;
|
||||
#define JSVAL_TYPE_DOUBLE ((uint8_t)0x00)
|
||||
#define JSVAL_TYPE_INT32 ((uint8_t)0x01)
|
||||
#define JSVAL_TYPE_UNDEFINED ((uint8_t)0x02)
|
||||
#define JSVAL_TYPE_BOOLEAN ((uint8_t)0x03)
|
||||
#define JSVAL_TYPE_MAGIC ((uint8_t)0x04)
|
||||
#define JSVAL_TYPE_STRING ((uint8_t)0x05)
|
||||
#define JSVAL_TYPE_NULL ((uint8_t)0x06)
|
||||
#define JSVAL_TYPE_OBJECT ((uint8_t)0x07)
|
||||
#define JSVAL_TYPE_UNKNOWN ((uint8_t)0x20)
|
||||
|
||||
#if JS_BITS_PER_WORD == 32
|
||||
|
||||
typedef uint32 JSValueTag;
|
||||
#define JSVAL_TAG_CLEAR ((uint32)(0xFFFF0000))
|
||||
#define JSVAL_TAG_INT32 ((uint32)(JSVAL_TAG_CLEAR | JSVAL_TYPE_INT32))
|
||||
#define JSVAL_TAG_UNDEFINED ((uint32)(JSVAL_TAG_CLEAR | JSVAL_TYPE_UNDEFINED))
|
||||
#define JSVAL_TAG_STRING ((uint32)(JSVAL_TAG_CLEAR | JSVAL_TYPE_STRING))
|
||||
#define JSVAL_TAG_BOOLEAN ((uint32)(JSVAL_TAG_CLEAR | JSVAL_TYPE_BOOLEAN))
|
||||
#define JSVAL_TAG_MAGIC ((uint32)(JSVAL_TAG_CLEAR | JSVAL_TYPE_MAGIC))
|
||||
#define JSVAL_TAG_NULL ((uint32)(JSVAL_TAG_CLEAR | JSVAL_TYPE_NULL))
|
||||
#define JSVAL_TAG_OBJECT ((uint32)(JSVAL_TAG_CLEAR | JSVAL_TYPE_OBJECT))
|
||||
typedef uint32_t JSValueTag;
|
||||
#define JSVAL_TAG_CLEAR ((uint32_t)(0xFFFFFF80))
|
||||
#define JSVAL_TAG_INT32 ((uint32_t)(JSVAL_TAG_CLEAR | JSVAL_TYPE_INT32))
|
||||
#define JSVAL_TAG_UNDEFINED ((uint32_t)(JSVAL_TAG_CLEAR | JSVAL_TYPE_UNDEFINED))
|
||||
#define JSVAL_TAG_STRING ((uint32_t)(JSVAL_TAG_CLEAR | JSVAL_TYPE_STRING))
|
||||
#define JSVAL_TAG_BOOLEAN ((uint32_t)(JSVAL_TAG_CLEAR | JSVAL_TYPE_BOOLEAN))
|
||||
#define JSVAL_TAG_MAGIC ((uint32_t)(JSVAL_TAG_CLEAR | JSVAL_TYPE_MAGIC))
|
||||
#define JSVAL_TAG_NULL ((uint32_t)(JSVAL_TAG_CLEAR | JSVAL_TYPE_NULL))
|
||||
#define JSVAL_TAG_OBJECT ((uint32_t)(JSVAL_TAG_CLEAR | JSVAL_TYPE_OBJECT))
|
||||
|
||||
#elif JS_BITS_PER_WORD == 64
|
||||
|
||||
typedef uint32 JSValueTag;
|
||||
#define JSVAL_TAG_MAX_DOUBLE ((uint32)(0x1FFF0))
|
||||
#define JSVAL_TAG_INT32 (uint32)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_INT32)
|
||||
#define JSVAL_TAG_UNDEFINED (uint32)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_UNDEFINED)
|
||||
#define JSVAL_TAG_STRING (uint32)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_STRING)
|
||||
#define JSVAL_TAG_BOOLEAN (uint32)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_BOOLEAN)
|
||||
#define JSVAL_TAG_MAGIC (uint32)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_MAGIC)
|
||||
#define JSVAL_TAG_NULL (uint32)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_NULL)
|
||||
#define JSVAL_TAG_OBJECT (uint32)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_OBJECT)
|
||||
typedef uint32_t JSValueTag;
|
||||
#define JSVAL_TAG_MAX_DOUBLE ((uint32_t)(0x1FFF0))
|
||||
#define JSVAL_TAG_INT32 (uint32_t)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_INT32)
|
||||
#define JSVAL_TAG_UNDEFINED (uint32_t)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_UNDEFINED)
|
||||
#define JSVAL_TAG_STRING (uint32_t)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_STRING)
|
||||
#define JSVAL_TAG_BOOLEAN (uint32_t)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_BOOLEAN)
|
||||
#define JSVAL_TAG_MAGIC (uint32_t)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_MAGIC)
|
||||
#define JSVAL_TAG_NULL (uint32_t)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_NULL)
|
||||
#define JSVAL_TAG_OBJECT (uint32_t)(JSVAL_TAG_MAX_DOUBLE | JSVAL_TYPE_OBJECT)
|
||||
|
||||
typedef uint64 JSValueShiftedTag;
|
||||
#define JSVAL_SHIFTED_TAG_MAX_DOUBLE ((((uint64)JSVAL_TAG_MAX_DOUBLE) << JSVAL_TAG_SHIFT) | 0xFFFFFFFF)
|
||||
#define JSVAL_SHIFTED_TAG_INT32 (((uint64)JSVAL_TAG_INT32) << JSVAL_TAG_SHIFT)
|
||||
#define JSVAL_SHIFTED_TAG_UNDEFINED (((uint64)JSVAL_TAG_UNDEFINED) << JSVAL_TAG_SHIFT)
|
||||
#define JSVAL_SHIFTED_TAG_STRING (((uint64)JSVAL_TAG_STRING) << JSVAL_TAG_SHIFT)
|
||||
#define JSVAL_SHIFTED_TAG_BOOLEAN (((uint64)JSVAL_TAG_BOOLEAN) << JSVAL_TAG_SHIFT)
|
||||
#define JSVAL_SHIFTED_TAG_MAGIC (((uint64)JSVAL_TAG_MAGIC) << JSVAL_TAG_SHIFT)
|
||||
#define JSVAL_SHIFTED_TAG_NULL (((uint64)JSVAL_TAG_NULL) << JSVAL_TAG_SHIFT)
|
||||
#define JSVAL_SHIFTED_TAG_OBJECT (((uint64)JSVAL_TAG_OBJECT) << JSVAL_TAG_SHIFT)
|
||||
typedef uint64_t JSValueShiftedTag;
|
||||
#define JSVAL_SHIFTED_TAG_MAX_DOUBLE ((((uint64_t)JSVAL_TAG_MAX_DOUBLE) << JSVAL_TAG_SHIFT) | 0xFFFFFFFF)
|
||||
#define JSVAL_SHIFTED_TAG_INT32 (((uint64_t)JSVAL_TAG_INT32) << JSVAL_TAG_SHIFT)
|
||||
#define JSVAL_SHIFTED_TAG_UNDEFINED (((uint64_t)JSVAL_TAG_UNDEFINED) << JSVAL_TAG_SHIFT)
|
||||
#define JSVAL_SHIFTED_TAG_STRING (((uint64_t)JSVAL_TAG_STRING) << JSVAL_TAG_SHIFT)
|
||||
#define JSVAL_SHIFTED_TAG_BOOLEAN (((uint64_t)JSVAL_TAG_BOOLEAN) << JSVAL_TAG_SHIFT)
|
||||
#define JSVAL_SHIFTED_TAG_MAGIC (((uint64_t)JSVAL_TAG_MAGIC) << JSVAL_TAG_SHIFT)
|
||||
#define JSVAL_SHIFTED_TAG_NULL (((uint64_t)JSVAL_TAG_NULL) << JSVAL_TAG_SHIFT)
|
||||
#define JSVAL_SHIFTED_TAG_OBJECT (((uint64_t)JSVAL_TAG_OBJECT) << JSVAL_TAG_SHIFT)
|
||||
|
||||
#endif /* JS_BITS_PER_WORD */
|
||||
#endif /* defined(__cplusplus) && !defined(__SUNPRO_CC) */
|
||||
|
@ -222,8 +210,6 @@ typedef uint64 JSValueShiftedTag;
|
|||
#define JSVAL_UPPER_EXCL_TYPE_OF_PRIMITIVE_SET JSVAL_TYPE_OBJECT
|
||||
#define JSVAL_UPPER_INCL_TYPE_OF_NUMBER_SET JSVAL_TYPE_INT32
|
||||
#define JSVAL_LOWER_INCL_TYPE_OF_PTR_PAYLOAD_SET JSVAL_TYPE_MAGIC
|
||||
#define JSVAL_UPPER_INCL_TYPE_OF_VALUE_SET JSVAL_TYPE_OBJECT
|
||||
#define JSVAL_UPPER_INCL_TYPE_OF_BOXABLE_SET JSVAL_TYPE_FUNOBJ
|
||||
|
||||
#if JS_BITS_PER_WORD == 32
|
||||
|
||||
|
@ -239,12 +225,11 @@ typedef uint64 JSValueShiftedTag;
|
|||
#define JSVAL_PAYLOAD_MASK 0x00007FFFFFFFFFFFLL
|
||||
#define JSVAL_TAG_MASK 0xFFFF800000000000LL
|
||||
#define JSVAL_TYPE_TO_TAG(type) ((JSValueTag)(JSVAL_TAG_MAX_DOUBLE | (type)))
|
||||
#define JSVAL_TYPE_TO_SHIFTED_TAG(type) (((uint64)JSVAL_TYPE_TO_TAG(type)) << JSVAL_TAG_SHIFT)
|
||||
#define JSVAL_TYPE_TO_SHIFTED_TAG(type) (((uint64_t)JSVAL_TYPE_TO_TAG(type)) << JSVAL_TAG_SHIFT)
|
||||
|
||||
#define JSVAL_LOWER_INCL_SHIFTED_TAG_OF_OBJ_OR_NULL_SET JSVAL_SHIFTED_TAG_NULL
|
||||
#define JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_PRIMITIVE_SET JSVAL_SHIFTED_TAG_OBJECT
|
||||
#define JSVAL_UPPER_EXCL_SHIFTED_TAG_OF_NUMBER_SET JSVAL_SHIFTED_TAG_UNDEFINED
|
||||
#define JSVAL_LOWER_INCL_SHIFTED_TAG_OF_PTR_PAYLOAD_SET JSVAL_SHIFTED_TAG_MAGIC
|
||||
#define JSVAL_LOWER_INCL_SHIFTED_TAG_OF_GCTHING_SET JSVAL_SHIFTED_TAG_STRING
|
||||
|
||||
#endif /* JS_BITS_PER_WORD */
|
||||
|
@ -252,9 +237,8 @@ typedef uint64 JSValueShiftedTag;
|
|||
typedef enum JSWhyMagic
|
||||
{
|
||||
JS_ARRAY_HOLE, /* a hole in a dense array */
|
||||
JS_ARGS_HOLE, /* a hole in the args object's array */
|
||||
JS_NATIVE_ENUMERATE, /* indicates that a custom enumerate hook forwarded
|
||||
* to js_Enumerate, which really means the object can be
|
||||
* to JS_EnumerateState, which really means the object can be
|
||||
* enumerated like a native object. */
|
||||
JS_NO_ITER_VALUE, /* there is not a pending iterator value */
|
||||
JS_GENERATOR_CLOSING, /* exception value thrown when closing a generator */
|
||||
|
@ -262,114 +246,124 @@ typedef enum JSWhyMagic
|
|||
JS_THIS_POISON, /* used in debug builds to catch tracing errors */
|
||||
JS_ARG_POISON, /* used in debug builds to catch tracing errors */
|
||||
JS_SERIALIZE_NO_NODE, /* an empty subnode in the AST serializer */
|
||||
JS_LAZY_ARGUMENTS, /* lazy arguments value on the stack */
|
||||
JS_UNASSIGNED_ARGUMENTS, /* the initial value of callobj.arguments */
|
||||
JS_OPTIMIZED_ARGUMENTS, /* optimized-away 'arguments' value */
|
||||
JS_IS_CONSTRUCTING, /* magic value passed to natives to indicate construction */
|
||||
JS_OVERWRITTEN_CALLEE, /* arguments.callee has been overwritten */
|
||||
JS_GENERIC_MAGIC /* for local use */
|
||||
} JSWhyMagic;
|
||||
|
||||
typedef struct JSString JSString;
|
||||
typedef struct JSFlatString JSFlatString;
|
||||
typedef struct JSObject JSObject;
|
||||
|
||||
#if defined(IS_LITTLE_ENDIAN)
|
||||
# if JS_BITS_PER_WORD == 32
|
||||
typedef union jsval_layout
|
||||
{
|
||||
uint64 asBits;
|
||||
uint64_t asBits;
|
||||
struct {
|
||||
union {
|
||||
int32 i32;
|
||||
uint32 u32;
|
||||
int32_t i32;
|
||||
uint32_t u32;
|
||||
JSBool boo;
|
||||
JSString *str;
|
||||
JSObject *obj;
|
||||
void *ptr;
|
||||
JSWhyMagic why;
|
||||
jsuword word;
|
||||
size_t word;
|
||||
} payload;
|
||||
JSValueTag tag;
|
||||
} s;
|
||||
double asDouble;
|
||||
void *asPtr;
|
||||
} jsval_layout;
|
||||
} JSVAL_ALIGNMENT jsval_layout;
|
||||
# elif JS_BITS_PER_WORD == 64
|
||||
typedef union jsval_layout
|
||||
{
|
||||
uint64 asBits;
|
||||
uint64_t asBits;
|
||||
#if (!defined(_WIN64) && defined(__cplusplus))
|
||||
/* MSVC does not pack these correctly :-( */
|
||||
struct {
|
||||
uint64 payload47 : 47;
|
||||
uint64_t payload47 : 47;
|
||||
JSValueTag tag : 17;
|
||||
} debugView;
|
||||
#endif
|
||||
struct {
|
||||
union {
|
||||
int32 i32;
|
||||
uint32 u32;
|
||||
int32_t i32;
|
||||
uint32_t u32;
|
||||
JSWhyMagic why;
|
||||
jsuword word;
|
||||
} payload;
|
||||
} s;
|
||||
double asDouble;
|
||||
void *asPtr;
|
||||
} jsval_layout;
|
||||
size_t asWord;
|
||||
} JSVAL_ALIGNMENT jsval_layout;
|
||||
# endif /* JS_BITS_PER_WORD */
|
||||
#else /* defined(IS_LITTLE_ENDIAN) */
|
||||
# if JS_BITS_PER_WORD == 32
|
||||
typedef union jsval_layout
|
||||
{
|
||||
uint64 asBits;
|
||||
uint64_t asBits;
|
||||
struct {
|
||||
JSValueTag tag;
|
||||
union {
|
||||
int32 i32;
|
||||
uint32 u32;
|
||||
int32_t i32;
|
||||
uint32_t u32;
|
||||
JSBool boo;
|
||||
JSString *str;
|
||||
JSObject *obj;
|
||||
void *ptr;
|
||||
JSWhyMagic why;
|
||||
jsuword word;
|
||||
size_t word;
|
||||
} payload;
|
||||
} s;
|
||||
double asDouble;
|
||||
void *asPtr;
|
||||
} jsval_layout;
|
||||
} JSVAL_ALIGNMENT jsval_layout;
|
||||
# elif JS_BITS_PER_WORD == 64
|
||||
typedef union jsval_layout
|
||||
{
|
||||
uint64 asBits;
|
||||
uint64_t asBits;
|
||||
struct {
|
||||
JSValueTag tag : 17;
|
||||
uint64 payload47 : 47;
|
||||
uint64_t payload47 : 47;
|
||||
} debugView;
|
||||
struct {
|
||||
uint32_t padding;
|
||||
union {
|
||||
int32 i32;
|
||||
uint32 u32;
|
||||
int32_t i32;
|
||||
uint32_t u32;
|
||||
JSWhyMagic why;
|
||||
} payload;
|
||||
} s;
|
||||
double asDouble;
|
||||
void *asPtr;
|
||||
} jsval_layout;
|
||||
size_t asWord;
|
||||
} JSVAL_ALIGNMENT jsval_layout;
|
||||
# endif /* JS_BITS_PER_WORD */
|
||||
#endif /* defined(IS_LITTLE_ENDIAN) */
|
||||
|
||||
JS_STATIC_ASSERT(sizeof(jsval_layout) == 8);
|
||||
|
||||
#if JS_BITS_PER_WORD == 32
|
||||
|
||||
/*
|
||||
* N.B. GCC, in some but not all cases, chooses to emit signed comparison of
|
||||
* JSValueTag even though its underlying type has been forced to be uint32.
|
||||
* Thus, all comparisons should explicitly cast operands to uint32.
|
||||
* JSValueTag even though its underlying type has been forced to be uint32_t.
|
||||
* Thus, all comparisons should explicitly cast operands to uint32_t.
|
||||
*/
|
||||
|
||||
#define BUILD_JSVAL(tag, payload) \
|
||||
((((uint64)(uint32)(tag)) << 32) | (uint32)(payload))
|
||||
static JS_ALWAYS_INLINE jsval_layout
|
||||
BUILD_JSVAL(JSValueTag tag, uint32_t payload)
|
||||
{
|
||||
jsval_layout l;
|
||||
l.asBits = (((uint64_t)(uint32_t)tag) << 32) | payload;
|
||||
return l;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE JSBool
|
||||
JSVAL_IS_DOUBLE_IMPL(jsval_layout l)
|
||||
{
|
||||
return (uint32)l.s.tag <= (uint32)JSVAL_TAG_CLEAR;
|
||||
return (uint32_t)l.s.tag <= (uint32_t)JSVAL_TAG_CLEAR;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE jsval_layout
|
||||
|
@ -387,14 +381,14 @@ JSVAL_IS_INT32_IMPL(jsval_layout l)
|
|||
return l.s.tag == JSVAL_TAG_INT32;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE int32
|
||||
static JS_ALWAYS_INLINE int32_t
|
||||
JSVAL_TO_INT32_IMPL(jsval_layout l)
|
||||
{
|
||||
return l.s.payload.i32;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE jsval_layout
|
||||
INT32_TO_JSVAL_IMPL(int32 i)
|
||||
INT32_TO_JSVAL_IMPL(int32_t i)
|
||||
{
|
||||
jsval_layout l;
|
||||
l.s.tag = JSVAL_TAG_INT32;
|
||||
|
@ -407,7 +401,7 @@ JSVAL_IS_NUMBER_IMPL(jsval_layout l)
|
|||
{
|
||||
JSValueTag tag = l.s.tag;
|
||||
JS_ASSERT(tag != JSVAL_TAG_CLEAR);
|
||||
return (uint32)tag <= (uint32)JSVAL_UPPER_INCL_TAG_OF_NUMBER_SET;
|
||||
return (uint32_t)tag <= (uint32_t)JSVAL_UPPER_INCL_TAG_OF_NUMBER_SET;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE JSBool
|
||||
|
@ -454,6 +448,7 @@ static JS_ALWAYS_INLINE jsval_layout
|
|||
BOOLEAN_TO_JSVAL_IMPL(JSBool b)
|
||||
{
|
||||
jsval_layout l;
|
||||
JS_ASSERT(b == JS_TRUE || b == JS_FALSE);
|
||||
l.s.tag = JSVAL_TAG_BOOLEAN;
|
||||
l.s.payload.boo = b;
|
||||
return l;
|
||||
|
@ -465,13 +460,6 @@ JSVAL_IS_MAGIC_IMPL(jsval_layout l)
|
|||
return l.s.tag == JSVAL_TAG_MAGIC;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE JSObject *
|
||||
MAGIC_JSVAL_TO_OBJECT_OR_NULL_IMPL(jsval_layout l)
|
||||
{
|
||||
JS_ASSERT(JSVAL_IS_MAGIC_IMPL(l));
|
||||
return l.s.payload.obj;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE JSBool
|
||||
JSVAL_IS_OBJECT_IMPL(jsval_layout l)
|
||||
{
|
||||
|
@ -481,14 +469,14 @@ JSVAL_IS_OBJECT_IMPL(jsval_layout l)
|
|||
static JS_ALWAYS_INLINE JSBool
|
||||
JSVAL_IS_PRIMITIVE_IMPL(jsval_layout l)
|
||||
{
|
||||
return (uint32)l.s.tag < (uint32)JSVAL_UPPER_EXCL_TAG_OF_PRIMITIVE_SET;
|
||||
return (uint32_t)l.s.tag < (uint32_t)JSVAL_UPPER_EXCL_TAG_OF_PRIMITIVE_SET;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE JSBool
|
||||
JSVAL_IS_OBJECT_OR_NULL_IMPL(jsval_layout l)
|
||||
{
|
||||
JS_ASSERT((uint32)l.s.tag <= (uint32)JSVAL_TAG_OBJECT);
|
||||
return (uint32)l.s.tag >= (uint32)JSVAL_LOWER_INCL_TAG_OF_OBJ_OR_NULL_SET;
|
||||
JS_ASSERT((uint32_t)l.s.tag <= (uint32_t)JSVAL_TAG_OBJECT);
|
||||
return (uint32_t)l.s.tag >= (uint32_t)JSVAL_LOWER_INCL_TAG_OF_OBJ_OR_NULL_SET;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE JSObject *
|
||||
|
@ -517,7 +505,7 @@ static JS_ALWAYS_INLINE jsval_layout
|
|||
PRIVATE_PTR_TO_JSVAL_IMPL(void *ptr)
|
||||
{
|
||||
jsval_layout l;
|
||||
JS_ASSERT(((uint32)ptr & 1) == 0);
|
||||
JS_ASSERT(((uint32_t)ptr & 1) == 0);
|
||||
l.s.tag = (JSValueTag)0;
|
||||
l.s.payload.ptr = ptr;
|
||||
JS_ASSERT(JSVAL_IS_DOUBLE_IMPL(l));
|
||||
|
@ -534,7 +522,7 @@ static JS_ALWAYS_INLINE JSBool
|
|||
JSVAL_IS_GCTHING_IMPL(jsval_layout l)
|
||||
{
|
||||
/* gcc sometimes generates signed < without explicit casts. */
|
||||
return (uint32)l.s.tag >= (uint32)JSVAL_LOWER_INCL_TAG_OF_GCTHING_SET;
|
||||
return (uint32_t)l.s.tag >= (uint32_t)JSVAL_LOWER_INCL_TAG_OF_GCTHING_SET;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE void *
|
||||
|
@ -549,16 +537,73 @@ JSVAL_IS_TRACEABLE_IMPL(jsval_layout l)
|
|||
return l.s.tag == JSVAL_TAG_STRING || l.s.tag == JSVAL_TAG_OBJECT;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE uint32
|
||||
static JS_ALWAYS_INLINE uint32_t
|
||||
JSVAL_TRACE_KIND_IMPL(jsval_layout l)
|
||||
{
|
||||
return (uint32)(JSBool)JSVAL_IS_STRING_IMPL(l);
|
||||
return (uint32_t)(JSBool)JSVAL_IS_STRING_IMPL(l);
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE JSBool
|
||||
JSVAL_IS_SPECIFIC_INT32_IMPL(jsval_layout l, int32_t i32)
|
||||
{
|
||||
return l.s.tag == JSVAL_TAG_INT32 && l.s.payload.i32 == i32;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE JSBool
|
||||
JSVAL_IS_SPECIFIC_BOOLEAN(jsval_layout l, JSBool b)
|
||||
{
|
||||
return (l.s.tag == JSVAL_TAG_BOOLEAN) && (l.s.payload.boo == b);
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE jsval_layout
|
||||
MAGIC_TO_JSVAL_IMPL(JSWhyMagic why)
|
||||
{
|
||||
jsval_layout l;
|
||||
l.s.tag = JSVAL_TAG_MAGIC;
|
||||
l.s.payload.why = why;
|
||||
return l;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE JSBool
|
||||
JSVAL_SAME_TYPE_IMPL(jsval_layout lhs, jsval_layout rhs)
|
||||
{
|
||||
JSValueTag ltag = lhs.s.tag, rtag = rhs.s.tag;
|
||||
return ltag == rtag || (ltag < JSVAL_TAG_CLEAR && rtag < JSVAL_TAG_CLEAR);
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE jsval_layout
|
||||
PRIVATE_UINT32_TO_JSVAL_IMPL(uint32_t ui)
|
||||
{
|
||||
jsval_layout l;
|
||||
l.s.tag = (JSValueTag)0;
|
||||
l.s.payload.u32 = ui;
|
||||
JS_ASSERT(JSVAL_IS_DOUBLE_IMPL(l));
|
||||
return l;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE uint32_t
|
||||
JSVAL_TO_PRIVATE_UINT32_IMPL(jsval_layout l)
|
||||
{
|
||||
return l.s.payload.u32;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE JSValueType
|
||||
JSVAL_EXTRACT_NON_DOUBLE_TYPE_IMPL(jsval_layout l)
|
||||
{
|
||||
uint32_t type = l.s.tag & 0xF;
|
||||
JS_ASSERT(type > JSVAL_TYPE_DOUBLE);
|
||||
return (JSValueType)type;
|
||||
}
|
||||
|
||||
#elif JS_BITS_PER_WORD == 64
|
||||
|
||||
#define BUILD_JSVAL(tag, payload) \
|
||||
((((uint64)(uint32)(tag)) << JSVAL_TAG_SHIFT) | (payload))
|
||||
static JS_ALWAYS_INLINE jsval_layout
|
||||
BUILD_JSVAL(JSValueTag tag, uint64_t payload)
|
||||
{
|
||||
jsval_layout l;
|
||||
l.asBits = (((uint64_t)(uint32_t)tag) << JSVAL_TAG_SHIFT) | payload;
|
||||
return l;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE JSBool
|
||||
JSVAL_IS_DOUBLE_IMPL(jsval_layout l)
|
||||
|
@ -578,20 +623,20 @@ DOUBLE_TO_JSVAL_IMPL(double d)
|
|||
static JS_ALWAYS_INLINE JSBool
|
||||
JSVAL_IS_INT32_IMPL(jsval_layout l)
|
||||
{
|
||||
return (uint32)(l.asBits >> JSVAL_TAG_SHIFT) == JSVAL_TAG_INT32;
|
||||
return (uint32_t)(l.asBits >> JSVAL_TAG_SHIFT) == JSVAL_TAG_INT32;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE int32
|
||||
static JS_ALWAYS_INLINE int32_t
|
||||
JSVAL_TO_INT32_IMPL(jsval_layout l)
|
||||
{
|
||||
return (int32)l.asBits;
|
||||
return (int32_t)l.asBits;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE jsval_layout
|
||||
INT32_TO_JSVAL_IMPL(int32 i32)
|
||||
INT32_TO_JSVAL_IMPL(int32_t i32)
|
||||
{
|
||||
jsval_layout l;
|
||||
l.asBits = ((uint64)(uint32)i32) | JSVAL_SHIFTED_TAG_INT32;
|
||||
l.asBits = ((uint64_t)(uint32_t)i32) | JSVAL_SHIFTED_TAG_INT32;
|
||||
return l;
|
||||
}
|
||||
|
||||
|
@ -610,14 +655,14 @@ JSVAL_IS_UNDEFINED_IMPL(jsval_layout l)
|
|||
static JS_ALWAYS_INLINE JSBool
|
||||
JSVAL_IS_STRING_IMPL(jsval_layout l)
|
||||
{
|
||||
return (uint32)(l.asBits >> JSVAL_TAG_SHIFT) == JSVAL_TAG_STRING;
|
||||
return (uint32_t)(l.asBits >> JSVAL_TAG_SHIFT) == JSVAL_TAG_STRING;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE jsval_layout
|
||||
STRING_TO_JSVAL_IMPL(JSString *str)
|
||||
{
|
||||
jsval_layout l;
|
||||
uint64 strBits = (uint64)str;
|
||||
uint64_t strBits = (uint64_t)str;
|
||||
JS_ASSERT(str);
|
||||
JS_ASSERT((strBits >> JSVAL_TAG_SHIFT) == 0);
|
||||
l.asBits = strBits | JSVAL_SHIFTED_TAG_STRING;
|
||||
|
@ -633,7 +678,7 @@ JSVAL_TO_STRING_IMPL(jsval_layout l)
|
|||
static JS_ALWAYS_INLINE JSBool
|
||||
JSVAL_IS_BOOLEAN_IMPL(jsval_layout l)
|
||||
{
|
||||
return (uint32)(l.asBits >> JSVAL_TAG_SHIFT) == JSVAL_TAG_BOOLEAN;
|
||||
return (uint32_t)(l.asBits >> JSVAL_TAG_SHIFT) == JSVAL_TAG_BOOLEAN;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE JSBool
|
||||
|
@ -646,7 +691,8 @@ static JS_ALWAYS_INLINE jsval_layout
|
|||
BOOLEAN_TO_JSVAL_IMPL(JSBool b)
|
||||
{
|
||||
jsval_layout l;
|
||||
l.asBits = ((uint64)(uint32)b) | JSVAL_SHIFTED_TAG_BOOLEAN;
|
||||
JS_ASSERT(b == JS_TRUE || b == JS_FALSE);
|
||||
l.asBits = ((uint64_t)(uint32_t)b) | JSVAL_SHIFTED_TAG_BOOLEAN;
|
||||
return l;
|
||||
}
|
||||
|
||||
|
@ -656,15 +702,6 @@ JSVAL_IS_MAGIC_IMPL(jsval_layout l)
|
|||
return (l.asBits >> JSVAL_TAG_SHIFT) == JSVAL_TAG_MAGIC;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE JSObject *
|
||||
MAGIC_JSVAL_TO_OBJECT_OR_NULL_IMPL(jsval_layout l)
|
||||
{
|
||||
uint64 ptrBits = l.asBits & JSVAL_PAYLOAD_MASK;
|
||||
JS_ASSERT(JSVAL_IS_MAGIC_IMPL(l));
|
||||
JS_ASSERT((ptrBits >> JSVAL_TAG_SHIFT) == 0);
|
||||
return (JSObject *)ptrBits;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE JSBool
|
||||
JSVAL_IS_PRIMITIVE_IMPL(jsval_layout l)
|
||||
{
|
||||
|
@ -688,7 +725,7 @@ JSVAL_IS_OBJECT_OR_NULL_IMPL(jsval_layout l)
|
|||
static JS_ALWAYS_INLINE JSObject *
|
||||
JSVAL_TO_OBJECT_IMPL(jsval_layout l)
|
||||
{
|
||||
uint64 ptrBits = l.asBits & JSVAL_PAYLOAD_MASK;
|
||||
uint64_t ptrBits = l.asBits & JSVAL_PAYLOAD_MASK;
|
||||
JS_ASSERT((ptrBits & 0x7) == 0);
|
||||
return (JSObject *)ptrBits;
|
||||
}
|
||||
|
@ -697,7 +734,7 @@ static JS_ALWAYS_INLINE jsval_layout
|
|||
OBJECT_TO_JSVAL_IMPL(JSObject *obj)
|
||||
{
|
||||
jsval_layout l;
|
||||
uint64 objBits = (uint64)obj;
|
||||
uint64_t objBits = (uint64_t)obj;
|
||||
JS_ASSERT(obj);
|
||||
JS_ASSERT((objBits >> JSVAL_TAG_SHIFT) == 0);
|
||||
l.asBits = objBits | JSVAL_SHIFTED_TAG_OBJECT;
|
||||
|
@ -719,7 +756,7 @@ JSVAL_IS_GCTHING_IMPL(jsval_layout l)
|
|||
static JS_ALWAYS_INLINE void *
|
||||
JSVAL_TO_GCTHING_IMPL(jsval_layout l)
|
||||
{
|
||||
uint64 ptrBits = l.asBits & JSVAL_PAYLOAD_MASK;
|
||||
uint64_t ptrBits = l.asBits & JSVAL_PAYLOAD_MASK;
|
||||
JS_ASSERT((ptrBits & 0x7) == 0);
|
||||
return (void *)ptrBits;
|
||||
}
|
||||
|
@ -730,17 +767,17 @@ JSVAL_IS_TRACEABLE_IMPL(jsval_layout l)
|
|||
return JSVAL_IS_GCTHING_IMPL(l) && !JSVAL_IS_NULL_IMPL(l);
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE uint32
|
||||
static JS_ALWAYS_INLINE uint32_t
|
||||
JSVAL_TRACE_KIND_IMPL(jsval_layout l)
|
||||
{
|
||||
return (uint32)(JSBool)!(JSVAL_IS_OBJECT_IMPL(l));
|
||||
return (uint32_t)(JSBool)!(JSVAL_IS_OBJECT_IMPL(l));
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE jsval_layout
|
||||
PRIVATE_PTR_TO_JSVAL_IMPL(void *ptr)
|
||||
{
|
||||
jsval_layout l;
|
||||
uint64 ptrBits = (uint64)ptr;
|
||||
uint64_t ptrBits = (uint64_t)ptr;
|
||||
JS_ASSERT((ptrBits & 1) == 0);
|
||||
l.asBits = ptrBits >> 1;
|
||||
JS_ASSERT(JSVAL_IS_DOUBLE_IMPL(l));
|
||||
|
@ -754,7 +791,59 @@ JSVAL_TO_PRIVATE_PTR_IMPL(jsval_layout l)
|
|||
return (void *)(l.asBits << 1);
|
||||
}
|
||||
|
||||
#endif
|
||||
static JS_ALWAYS_INLINE JSBool
|
||||
JSVAL_IS_SPECIFIC_INT32_IMPL(jsval_layout l, int32_t i32)
|
||||
{
|
||||
return l.asBits == (((uint64_t)(uint32_t)i32) | JSVAL_SHIFTED_TAG_INT32);
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE JSBool
|
||||
JSVAL_IS_SPECIFIC_BOOLEAN(jsval_layout l, JSBool b)
|
||||
{
|
||||
return l.asBits == (((uint64_t)(uint32_t)b) | JSVAL_SHIFTED_TAG_BOOLEAN);
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE jsval_layout
|
||||
MAGIC_TO_JSVAL_IMPL(JSWhyMagic why)
|
||||
{
|
||||
jsval_layout l;
|
||||
l.asBits = ((uint64_t)(uint32_t)why) | JSVAL_SHIFTED_TAG_MAGIC;
|
||||
return l;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE JSBool
|
||||
JSVAL_SAME_TYPE_IMPL(jsval_layout lhs, jsval_layout rhs)
|
||||
{
|
||||
uint64_t lbits = lhs.asBits, rbits = rhs.asBits;
|
||||
return (lbits <= JSVAL_SHIFTED_TAG_MAX_DOUBLE && rbits <= JSVAL_SHIFTED_TAG_MAX_DOUBLE) ||
|
||||
(((lbits ^ rbits) & 0xFFFF800000000000LL) == 0);
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE jsval_layout
|
||||
PRIVATE_UINT32_TO_JSVAL_IMPL(uint32_t ui)
|
||||
{
|
||||
jsval_layout l;
|
||||
l.asBits = (uint64_t)ui;
|
||||
JS_ASSERT(JSVAL_IS_DOUBLE_IMPL(l));
|
||||
return l;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE uint32_t
|
||||
JSVAL_TO_PRIVATE_UINT32_IMPL(jsval_layout l)
|
||||
{
|
||||
JS_ASSERT((l.asBits >> 32) == 0);
|
||||
return (uint32_t)l.asBits;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE JSValueType
|
||||
JSVAL_EXTRACT_NON_DOUBLE_TYPE_IMPL(jsval_layout l)
|
||||
{
|
||||
uint64_t type = (l.asBits >> JSVAL_TAG_SHIFT) & 0xF;
|
||||
JS_ASSERT(type > JSVAL_TYPE_DOUBLE);
|
||||
return (JSValueType)type;
|
||||
}
|
||||
|
||||
#endif /* JS_BITS_PER_WORD */
|
||||
|
||||
static JS_ALWAYS_INLINE double
|
||||
JS_CANONICALIZE_NAN(double d)
|
||||
|
@ -767,65 +856,11 @@ JS_CANONICALIZE_NAN(double d)
|
|||
return d;
|
||||
}
|
||||
|
||||
/* See JS_USE_JSVAL_JSID_STRUCT_TYPES comment in jsapi.h. */
|
||||
#if defined(DEBUG) && !defined(JS_NO_JSVAL_JSID_STRUCT_TYPES)
|
||||
# define JS_USE_JSVAL_JSID_STRUCT_TYPES
|
||||
#endif
|
||||
|
||||
#ifdef JS_USE_JSVAL_JSID_STRUCT_TYPES
|
||||
|
||||
typedef JSVAL_ALIGNMENT jsval_layout jsval;
|
||||
typedef struct jsid { size_t asBits; } jsid;
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C++"
|
||||
{
|
||||
static JS_ALWAYS_INLINE bool
|
||||
operator==(jsid lhs, jsid rhs)
|
||||
{
|
||||
return lhs.asBits == rhs.asBits;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE bool
|
||||
operator!=(jsid lhs, jsid rhs)
|
||||
{
|
||||
return lhs.asBits != rhs.asBits;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE bool
|
||||
operator==(jsval lhs, jsval rhs)
|
||||
{
|
||||
return lhs.asBits == rhs.asBits;
|
||||
}
|
||||
|
||||
static JS_ALWAYS_INLINE bool
|
||||
operator!=(jsval lhs, jsval rhs)
|
||||
{
|
||||
return lhs.asBits != rhs.asBits;
|
||||
}
|
||||
}
|
||||
# endif /* defined(__cplusplus) */
|
||||
|
||||
/* Internal helper macros */
|
||||
#define JSVAL_BITS(v) ((v).asBits)
|
||||
#define JSVAL_FROM_LAYOUT(l) (l)
|
||||
#define IMPL_TO_JSVAL(v) (v)
|
||||
#define JSID_BITS(id) ((id).asBits)
|
||||
|
||||
#else /* defined(JS_USE_JSVAL_JSID_STRUCT_TYPES) */
|
||||
|
||||
/* Use different primitive types so overloading works. */
|
||||
typedef JSVAL_ALIGNMENT uint64 jsval;
|
||||
typedef ptrdiff_t jsid;
|
||||
|
||||
/* Internal helper macros */
|
||||
#define JSVAL_BITS(v) (v)
|
||||
#define JSVAL_FROM_LAYOUT(l) ((l).asBits)
|
||||
#define IMPL_TO_JSVAL(v) ((v).asBits)
|
||||
#define JSID_BITS(id) (id)
|
||||
|
||||
#endif /* defined(JS_USE_JSVAL_JSID_STRUCT_TYPES) */
|
||||
|
||||
JS_END_EXTERN_C
|
||||
|
||||
#ifdef __cplusplus
|
||||
static jsval_layout JSVAL_TO_IMPL(JS::Value);
|
||||
static JS::Value IMPL_TO_JSVAL(jsval_layout);
|
||||
#endif
|
||||
|
||||
#endif /* jsvalimpl_h__ */
|
||||
|
|
|
@ -79,24 +79,19 @@
|
|||
JS_VERSION == JS_VERSION_ECMA_3_TEST
|
||||
|
||||
#define JS_HAS_STR_HTML_HELPERS 0 /* has str.anchor, str.bold, etc. */
|
||||
#define JS_HAS_PERL_SUBSTR 0 /* has str.substr */
|
||||
#if JS_VERSION == JS_VERSION_ECMA_3_TEST
|
||||
#define JS_HAS_OBJ_PROTO_PROP 1 /* has o.__proto__ etc. */
|
||||
#else
|
||||
#define JS_HAS_OBJ_PROTO_PROP 0 /* has o.__proto__ etc. */
|
||||
#endif
|
||||
#define JS_HAS_OBJ_WATCHPOINT 0 /* has o.watch and o.unwatch */
|
||||
#define JS_HAS_SHARP_VARS 0 /* has #n=, #n# for object literals */
|
||||
#define JS_HAS_XDR 0 /* has XDR API and internal support */
|
||||
#define JS_HAS_TOSOURCE 0 /* has Object/Array toSource method */
|
||||
#define JS_HAS_CATCH_GUARD 0 /* has exception handling catch guard */
|
||||
#define JS_HAS_SPARSE_ARRAYS 0 /* array methods preserve empty elems */
|
||||
#define JS_HAS_UNEVAL 0 /* has uneval() top-level function */
|
||||
#define JS_HAS_CONST 0 /* has JS2 const as alternative var */
|
||||
#define JS_HAS_FUN_EXPR_STMT 0 /* has function expression statement */
|
||||
#define JS_HAS_NO_SUCH_METHOD 0 /* has o.__noSuchMethod__ handler */
|
||||
#define JS_HAS_XML_SUPPORT 0 /* has ECMAScript for XML support */
|
||||
#define JS_HAS_ARRAY_EXTRAS 0 /* has indexOf and Lispy extras */
|
||||
#define JS_HAS_GENERATORS 0 /* has yield in generator function */
|
||||
#define JS_HAS_BLOCK_SCOPE 0 /* has block scope via let/arraycomp */
|
||||
#define JS_HAS_DESTRUCTURING 0 /* has [a,b] = ... or {p:a,q:b} = ... */
|
||||
|
@ -110,20 +105,15 @@
|
|||
#elif JS_VERSION == 150
|
||||
|
||||
#define JS_HAS_STR_HTML_HELPERS 1 /* has str.anchor, str.bold, etc. */
|
||||
#define JS_HAS_PERL_SUBSTR 1 /* has str.substr */
|
||||
#define JS_HAS_OBJ_PROTO_PROP 1 /* has o.__proto__ etc. */
|
||||
#define JS_HAS_OBJ_WATCHPOINT 1 /* has o.watch and o.unwatch */
|
||||
#define JS_HAS_SHARP_VARS 1 /* has #n=, #n# for object literals */
|
||||
#define JS_HAS_XDR 1 /* has XDR API and internal support */
|
||||
#define JS_HAS_TOSOURCE 1 /* has Object/Array toSource method */
|
||||
#define JS_HAS_CATCH_GUARD 1 /* has exception handling catch guard */
|
||||
#define JS_HAS_SPARSE_ARRAYS 0 /* array methods preserve empty elems */
|
||||
#define JS_HAS_UNEVAL 1 /* has uneval() top-level function */
|
||||
#define JS_HAS_CONST 1 /* has JS2 const as alternative var */
|
||||
#define JS_HAS_FUN_EXPR_STMT 1 /* has function expression statement */
|
||||
#define JS_HAS_NO_SUCH_METHOD 1 /* has o.__noSuchMethod__ handler */
|
||||
#define JS_HAS_XML_SUPPORT 0 /* has ECMAScript for XML support */
|
||||
#define JS_HAS_ARRAY_EXTRAS 0 /* has indexOf and Lispy extras */
|
||||
#define JS_HAS_GENERATORS 0 /* has yield in generator function */
|
||||
#define JS_HAS_BLOCK_SCOPE 0 /* has block scope via let/arraycomp */
|
||||
#define JS_HAS_DESTRUCTURING 0 /* has [a,b] = ... or {p:a,q:b} = ... */
|
||||
|
@ -133,20 +123,15 @@
|
|||
#elif JS_VERSION == 160
|
||||
|
||||
#define JS_HAS_STR_HTML_HELPERS 1 /* has str.anchor, str.bold, etc. */
|
||||
#define JS_HAS_PERL_SUBSTR 1 /* has str.substr */
|
||||
#define JS_HAS_OBJ_PROTO_PROP 1 /* has o.__proto__ etc. */
|
||||
#define JS_HAS_OBJ_WATCHPOINT 1 /* has o.watch and o.unwatch */
|
||||
#define JS_HAS_SHARP_VARS 1 /* has #n=, #n# for object literals */
|
||||
#define JS_HAS_XDR 1 /* has XDR API and internal support */
|
||||
#define JS_HAS_TOSOURCE 1 /* has Object/Array toSource method */
|
||||
#define JS_HAS_CATCH_GUARD 1 /* has exception handling catch guard */
|
||||
#define JS_HAS_SPARSE_ARRAYS 0 /* array methods preserve empty elems */
|
||||
#define JS_HAS_UNEVAL 1 /* has uneval() top-level function */
|
||||
#define JS_HAS_CONST 1 /* has JS2 const as alternative var */
|
||||
#define JS_HAS_FUN_EXPR_STMT 1 /* has function expression statement */
|
||||
#define JS_HAS_NO_SUCH_METHOD 1 /* has o.__noSuchMethod__ handler */
|
||||
#define JS_HAS_XML_SUPPORT 1 /* has ECMAScript for XML support */
|
||||
#define JS_HAS_ARRAY_EXTRAS 1 /* has indexOf and Lispy extras */
|
||||
#define JS_HAS_GENERATORS 0 /* has yield in generator function */
|
||||
#define JS_HAS_BLOCK_SCOPE 0 /* has block scope via let/arraycomp */
|
||||
#define JS_HAS_DESTRUCTURING 0 /* has [a,b] = ... or {p:a,q:b} = ... */
|
||||
|
@ -156,20 +141,15 @@
|
|||
#elif JS_VERSION == 170
|
||||
|
||||
#define JS_HAS_STR_HTML_HELPERS 1 /* has str.anchor, str.bold, etc. */
|
||||
#define JS_HAS_PERL_SUBSTR 1 /* has str.substr */
|
||||
#define JS_HAS_OBJ_PROTO_PROP 1 /* has o.__proto__ etc. */
|
||||
#define JS_HAS_OBJ_WATCHPOINT 1 /* has o.watch and o.unwatch */
|
||||
#define JS_HAS_SHARP_VARS 1 /* has #n=, #n# for object literals */
|
||||
#define JS_HAS_XDR 1 /* has XDR API and internal support */
|
||||
#define JS_HAS_TOSOURCE 1 /* has Object/Array toSource method */
|
||||
#define JS_HAS_CATCH_GUARD 1 /* has exception handling catch guard */
|
||||
#define JS_HAS_SPARSE_ARRAYS 0 /* array methods preserve empty elems */
|
||||
#define JS_HAS_UNEVAL 1 /* has uneval() top-level function */
|
||||
#define JS_HAS_CONST 1 /* has JS2 const as alternative var */
|
||||
#define JS_HAS_FUN_EXPR_STMT 1 /* has function expression statement */
|
||||
#define JS_HAS_NO_SUCH_METHOD 1 /* has o.__noSuchMethod__ handler */
|
||||
#define JS_HAS_XML_SUPPORT 1 /* has ECMAScript for XML support */
|
||||
#define JS_HAS_ARRAY_EXTRAS 1 /* has indexOf and Lispy extras */
|
||||
#define JS_HAS_GENERATORS 1 /* has yield in generator function */
|
||||
#define JS_HAS_BLOCK_SCOPE 1 /* has block scope via let/arraycomp */
|
||||
#define JS_HAS_DESTRUCTURING 1 /* has [a,b] = ... or {p:a,q:b} = ... */
|
||||
|
@ -179,20 +159,15 @@
|
|||
#elif 180 <= JS_VERSION && JS_VERSION <= 185
|
||||
|
||||
#define JS_HAS_STR_HTML_HELPERS 1 /* has str.anchor, str.bold, etc. */
|
||||
#define JS_HAS_PERL_SUBSTR 1 /* has str.substr */
|
||||
#define JS_HAS_OBJ_PROTO_PROP 1 /* has o.__proto__ etc. */
|
||||
#define JS_HAS_OBJ_WATCHPOINT 1 /* has o.watch and o.unwatch */
|
||||
#define JS_HAS_SHARP_VARS 1 /* has #n=, #n# for object literals */
|
||||
#define JS_HAS_XDR 1 /* has XDR API and internal support */
|
||||
#define JS_HAS_TOSOURCE 1 /* has Object/Array toSource method */
|
||||
#define JS_HAS_CATCH_GUARD 1 /* has exception handling catch guard */
|
||||
#define JS_HAS_SPARSE_ARRAYS 0 /* array methods preserve empty elems */
|
||||
#define JS_HAS_UNEVAL 1 /* has uneval() top-level function */
|
||||
#define JS_HAS_CONST 1 /* has JS2 const as alternative var */
|
||||
#define JS_HAS_FUN_EXPR_STMT 1 /* has function expression statement */
|
||||
#define JS_HAS_NO_SUCH_METHOD 1 /* has o.__noSuchMethod__ handler */
|
||||
#define JS_HAS_XML_SUPPORT 1 /* has ECMAScript for XML support */
|
||||
#define JS_HAS_ARRAY_EXTRAS 1 /* has indexOf and Lispy extras */
|
||||
#define JS_HAS_GENERATORS 1 /* has yield in generator function */
|
||||
#define JS_HAS_BLOCK_SCOPE 1 /* has block scope via let/arraycomp */
|
||||
#define JS_HAS_DESTRUCTURING 2 /* has [a,b] = ... or {p:a,q:b} = ... */
|
||||
|
@ -219,3 +194,13 @@
|
|||
* support likely to be made opt-in at some future time.
|
||||
*/
|
||||
#define OLD_GETTER_SETTER_METHODS 1
|
||||
|
||||
/* A kill-switch for bug 586842. Embedders shouldn't touch this! */
|
||||
#define USE_NEW_OBJECT_REPRESENTATION 0
|
||||
|
||||
#if USE_NEW_OBJECT_REPRESENTATION
|
||||
# define NEW_OBJECT_REPRESENTATION_ONLY() ((void)0)
|
||||
#else
|
||||
# define NEW_OBJECT_REPRESENTATION_ONLY() \
|
||||
MOZ_NOT_REACHED("don't call this! to be used in the new object representation")
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,285 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=4 sw=4 et tw=99:
|
||||
*
|
||||
* ***** 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 Mozilla SpiderMonkey JavaScript 1.9 code, released
|
||||
* May 28, 2008.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Foundation
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Andreas Gal <gal@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of 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 jswrapper_h___
|
||||
#define jswrapper_h___
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
|
||||
#include "jsapi.h"
|
||||
#include "jsproxy.h"
|
||||
|
||||
namespace js {
|
||||
|
||||
class DummyFrameGuard;
|
||||
|
||||
/* Base class that just implements no-op forwarding methods for fundamental
|
||||
* traps. This is meant to be used as a base class for ProxyHandlers that
|
||||
* want transparent forwarding behavior but don't want to use the derived
|
||||
* traps and other baggage of js::Wrapper.
|
||||
*/
|
||||
class JS_FRIEND_API(AbstractWrapper) : public ProxyHandler
|
||||
{
|
||||
unsigned mFlags;
|
||||
public:
|
||||
unsigned flags() const { return mFlags; }
|
||||
|
||||
explicit AbstractWrapper(unsigned flags);
|
||||
|
||||
/* ES5 Harmony fundamental wrapper traps. */
|
||||
virtual bool getPropertyDescriptor(JSContext *cx, JSObject *wrapper, jsid id, bool set,
|
||||
PropertyDescriptor *desc) MOZ_OVERRIDE;
|
||||
virtual bool getOwnPropertyDescriptor(JSContext *cx, JSObject *wrapper, jsid id, bool set,
|
||||
PropertyDescriptor *desc) MOZ_OVERRIDE;
|
||||
virtual bool defineProperty(JSContext *cx, JSObject *wrapper, jsid id,
|
||||
PropertyDescriptor *desc) MOZ_OVERRIDE;
|
||||
virtual bool getOwnPropertyNames(JSContext *cx, JSObject *wrapper, AutoIdVector &props) MOZ_OVERRIDE;
|
||||
virtual bool delete_(JSContext *cx, JSObject *wrapper, jsid id, bool *bp) MOZ_OVERRIDE;
|
||||
virtual bool enumerate(JSContext *cx, JSObject *wrapper, AutoIdVector &props) MOZ_OVERRIDE;
|
||||
virtual bool fix(JSContext *cx, JSObject *wrapper, Value *vp) MOZ_OVERRIDE;
|
||||
|
||||
/* Policy enforcement traps.
|
||||
*
|
||||
* enter() allows the policy to specify whether the caller may perform |act|
|
||||
* on the underlying object's |id| property. In the case when |act| is CALL,
|
||||
* |id| is generally JSID_VOID.
|
||||
*
|
||||
* leave() allows the policy to undo various scoped state changes taken in
|
||||
* enter(). If enter() succeeds, leave() must be called upon completion of
|
||||
* the approved action.
|
||||
*
|
||||
* The |act| parameter to enter() specifies the action being performed. GET,
|
||||
* SET, and CALL are self-explanatory, but PUNCTURE requires more explanation:
|
||||
*
|
||||
* GET and SET allow for a very fine-grained security membrane, through
|
||||
* which access can be granted or denied on a per-property, per-object, and
|
||||
* per-action basis. Sometimes though, we just want to asks if we can access
|
||||
* _everything_ behind the wrapper barrier. For example, when the structured
|
||||
* clone algorithm runs up against a cross-compartment wrapper, it needs to
|
||||
* know whether it can enter the compartment and keep cloning, or whether it
|
||||
* should throw. This is the role of PUNCTURE.
|
||||
*
|
||||
* PUNCTURE allows the policy to specify whether the wrapper barrier may
|
||||
* be lifted - that is to say, whether the caller is allowed to access
|
||||
* anything that the wrapped object could access. This is a very powerful
|
||||
* permission, and thus should generally be denied for security wrappers
|
||||
* except under very special circumstances. When |act| is PUNCTURE, |id|
|
||||
* should be JSID_VOID.
|
||||
* */
|
||||
enum Action { GET, SET, CALL, PUNCTURE };
|
||||
virtual bool enter(JSContext *cx, JSObject *wrapper, jsid id, Action act, bool *bp);
|
||||
virtual void leave(JSContext *cx, JSObject *wrapper);
|
||||
|
||||
static JSObject *wrappedObject(const JSObject *wrapper);
|
||||
static AbstractWrapper *wrapperHandler(const JSObject *wrapper);
|
||||
};
|
||||
|
||||
/* No-op wrapper handler base class. */
|
||||
class JS_FRIEND_API(Wrapper) : public AbstractWrapper
|
||||
{
|
||||
public:
|
||||
explicit Wrapper(unsigned flags);
|
||||
|
||||
typedef enum { PermitObjectAccess, PermitPropertyAccess, DenyAccess } Permission;
|
||||
|
||||
virtual ~Wrapper();
|
||||
|
||||
/* ES5 Harmony derived wrapper traps. */
|
||||
virtual bool has(JSContext *cx, JSObject *wrapper, jsid id, bool *bp) MOZ_OVERRIDE;
|
||||
virtual bool hasOwn(JSContext *cx, JSObject *wrapper, jsid id, bool *bp) MOZ_OVERRIDE;
|
||||
virtual bool get(JSContext *cx, JSObject *wrapper, JSObject *receiver, jsid id, Value *vp) MOZ_OVERRIDE;
|
||||
virtual bool set(JSContext *cx, JSObject *wrapper, JSObject *receiver, jsid id, bool strict,
|
||||
Value *vp) MOZ_OVERRIDE;
|
||||
virtual bool keys(JSContext *cx, JSObject *wrapper, AutoIdVector &props) MOZ_OVERRIDE;
|
||||
virtual bool iterate(JSContext *cx, JSObject *wrapper, unsigned flags, Value *vp) MOZ_OVERRIDE;
|
||||
|
||||
/* Spidermonkey extensions. */
|
||||
virtual bool call(JSContext *cx, JSObject *wrapper, unsigned argc, Value *vp) MOZ_OVERRIDE;
|
||||
virtual bool construct(JSContext *cx, JSObject *wrapper, unsigned argc, Value *argv, Value *rval) MOZ_OVERRIDE;
|
||||
virtual bool nativeCall(JSContext *cx, JSObject *wrapper, Class *clasp, Native native, CallArgs args) MOZ_OVERRIDE;
|
||||
virtual bool hasInstance(JSContext *cx, JSObject *wrapper, const Value *vp, bool *bp) MOZ_OVERRIDE;
|
||||
virtual JSType typeOf(JSContext *cx, JSObject *proxy) MOZ_OVERRIDE;
|
||||
virtual bool objectClassIs(JSObject *obj, ESClassValue classValue, JSContext *cx) MOZ_OVERRIDE;
|
||||
virtual JSString *obj_toString(JSContext *cx, JSObject *wrapper) MOZ_OVERRIDE;
|
||||
virtual JSString *fun_toString(JSContext *cx, JSObject *wrapper, unsigned indent) MOZ_OVERRIDE;
|
||||
virtual bool regexp_toShared(JSContext *cx, JSObject *proxy, RegExpGuard *g) MOZ_OVERRIDE;
|
||||
virtual bool defaultValue(JSContext *cx, JSObject *wrapper, JSType hint, Value *vp) MOZ_OVERRIDE;
|
||||
virtual bool iteratorNext(JSContext *cx, JSObject *wrapper, Value *vp) MOZ_OVERRIDE;
|
||||
|
||||
virtual void trace(JSTracer *trc, JSObject *wrapper) MOZ_OVERRIDE;
|
||||
|
||||
using AbstractWrapper::Action;
|
||||
|
||||
static Wrapper singleton;
|
||||
|
||||
static JSObject *New(JSContext *cx, JSObject *obj, JSObject *proto, JSObject *parent,
|
||||
Wrapper *handler);
|
||||
|
||||
using AbstractWrapper::wrappedObject;
|
||||
using AbstractWrapper::wrapperHandler;
|
||||
|
||||
enum {
|
||||
CROSS_COMPARTMENT = 1 << 0,
|
||||
LAST_USED_FLAG = CROSS_COMPARTMENT
|
||||
};
|
||||
|
||||
static void *getWrapperFamily();
|
||||
};
|
||||
|
||||
/* Base class for all cross compartment wrapper handlers. */
|
||||
class JS_FRIEND_API(CrossCompartmentWrapper) : public Wrapper
|
||||
{
|
||||
public:
|
||||
CrossCompartmentWrapper(unsigned flags);
|
||||
|
||||
virtual ~CrossCompartmentWrapper();
|
||||
|
||||
/* ES5 Harmony fundamental wrapper traps. */
|
||||
virtual bool getPropertyDescriptor(JSContext *cx, JSObject *wrapper, jsid id, bool set,
|
||||
PropertyDescriptor *desc) MOZ_OVERRIDE;
|
||||
virtual bool getOwnPropertyDescriptor(JSContext *cx, JSObject *wrapper, jsid id, bool set,
|
||||
PropertyDescriptor *desc) MOZ_OVERRIDE;
|
||||
virtual bool defineProperty(JSContext *cx, JSObject *wrapper, jsid id,
|
||||
PropertyDescriptor *desc) MOZ_OVERRIDE;
|
||||
virtual bool getOwnPropertyNames(JSContext *cx, JSObject *wrapper, AutoIdVector &props) MOZ_OVERRIDE;
|
||||
virtual bool delete_(JSContext *cx, JSObject *wrapper, jsid id, bool *bp) MOZ_OVERRIDE;
|
||||
virtual bool enumerate(JSContext *cx, JSObject *wrapper, AutoIdVector &props) MOZ_OVERRIDE;
|
||||
|
||||
/* ES5 Harmony derived wrapper traps. */
|
||||
virtual bool has(JSContext *cx, JSObject *wrapper, jsid id, bool *bp) MOZ_OVERRIDE;
|
||||
virtual bool hasOwn(JSContext *cx, JSObject *wrapper, jsid id, bool *bp) MOZ_OVERRIDE;
|
||||
virtual bool get(JSContext *cx, JSObject *wrapper, JSObject *receiver, jsid id, Value *vp) MOZ_OVERRIDE;
|
||||
virtual bool set(JSContext *cx, JSObject *wrapper, JSObject *receiver, jsid id, bool strict,
|
||||
Value *vp) MOZ_OVERRIDE;
|
||||
virtual bool keys(JSContext *cx, JSObject *wrapper, AutoIdVector &props) MOZ_OVERRIDE;
|
||||
virtual bool iterate(JSContext *cx, JSObject *wrapper, unsigned flags, Value *vp) MOZ_OVERRIDE;
|
||||
|
||||
/* Spidermonkey extensions. */
|
||||
virtual bool call(JSContext *cx, JSObject *wrapper, unsigned argc, Value *vp) MOZ_OVERRIDE;
|
||||
virtual bool construct(JSContext *cx, JSObject *wrapper, unsigned argc, Value *argv, Value *rval) MOZ_OVERRIDE;
|
||||
virtual bool nativeCall(JSContext *cx, JSObject *wrapper, Class *clasp, Native native, CallArgs args) MOZ_OVERRIDE;
|
||||
virtual bool hasInstance(JSContext *cx, JSObject *wrapper, const Value *vp, bool *bp) MOZ_OVERRIDE;
|
||||
virtual JSString *obj_toString(JSContext *cx, JSObject *wrapper) MOZ_OVERRIDE;
|
||||
virtual JSString *fun_toString(JSContext *cx, JSObject *wrapper, unsigned indent) MOZ_OVERRIDE;
|
||||
virtual bool defaultValue(JSContext *cx, JSObject *wrapper, JSType hint, Value *vp) MOZ_OVERRIDE;
|
||||
virtual bool iteratorNext(JSContext *cx, JSObject *wrapper, Value *vp);
|
||||
|
||||
virtual void trace(JSTracer *trc, JSObject *wrapper) MOZ_OVERRIDE;
|
||||
|
||||
static CrossCompartmentWrapper singleton;
|
||||
};
|
||||
|
||||
/*
|
||||
* Base class for security wrappers. A security wrapper is potentially hiding
|
||||
* all or part of some wrapped object thus SecurityWrapper defaults to denying
|
||||
* access to the wrappee. This is the opposite of Wrapper which tries to be
|
||||
* completely transparent.
|
||||
*
|
||||
* NB: Currently, only a few ProxyHandler operations are overridden to deny
|
||||
* access, relying on derived SecurityWrapper to block access when necessary.
|
||||
*/
|
||||
template <class Base>
|
||||
class JS_FRIEND_API(SecurityWrapper) : public Base
|
||||
{
|
||||
public:
|
||||
SecurityWrapper(unsigned flags);
|
||||
|
||||
virtual bool nativeCall(JSContext *cx, JSObject *wrapper, Class *clasp, Native native, CallArgs args) MOZ_OVERRIDE;
|
||||
virtual bool objectClassIs(JSObject *obj, ESClassValue classValue, JSContext *cx) MOZ_OVERRIDE;
|
||||
virtual bool regexp_toShared(JSContext *cx, JSObject *proxy, RegExpGuard *g) MOZ_OVERRIDE;
|
||||
};
|
||||
|
||||
typedef SecurityWrapper<Wrapper> SameCompartmentSecurityWrapper;
|
||||
typedef SecurityWrapper<CrossCompartmentWrapper> CrossCompartmentSecurityWrapper;
|
||||
|
||||
/*
|
||||
* A hacky class that lets a friend force a fake frame. We must already be
|
||||
* in the compartment of |target| when we enter the forced frame.
|
||||
*/
|
||||
class JS_FRIEND_API(ForceFrame)
|
||||
{
|
||||
public:
|
||||
JSContext * const context;
|
||||
JSObject * const target;
|
||||
private:
|
||||
DummyFrameGuard *frame;
|
||||
|
||||
public:
|
||||
ForceFrame(JSContext *cx, JSObject *target);
|
||||
~ForceFrame();
|
||||
bool enter();
|
||||
};
|
||||
|
||||
extern JSObject *
|
||||
TransparentObjectWrapper(JSContext *cx, JSObject *obj, JSObject *wrappedProto, JSObject *parent,
|
||||
unsigned flags);
|
||||
|
||||
// Proxy family for wrappers. Public so that IsWrapper() can be fully inlined by
|
||||
// jsfriendapi users.
|
||||
extern JS_FRIEND_DATA(int) sWrapperFamily;
|
||||
|
||||
inline bool
|
||||
IsWrapper(const JSObject *obj)
|
||||
{
|
||||
return IsProxy(obj) && GetProxyHandler(obj)->family() == &sWrapperFamily;
|
||||
}
|
||||
|
||||
// Given a JSObject, returns that object stripped of wrappers. If
|
||||
// stopAtOuter is true, then this returns the outer window if it was
|
||||
// previously wrapped. Otherwise, this returns the first object for
|
||||
// which JSObject::isWrapper returns false.
|
||||
JS_FRIEND_API(JSObject *) UnwrapObject(JSObject *obj, bool stopAtOuter = true,
|
||||
unsigned *flagsp = NULL);
|
||||
|
||||
// Given a JSObject, returns that object stripped of wrappers. At each stage,
|
||||
// the security wrapper has the opportunity to veto the unwrap. Since checked
|
||||
// code should never be unwrapping outer window wrappers, we always stop at
|
||||
// outer windows.
|
||||
JS_FRIEND_API(JSObject *) UnwrapObjectChecked(JSContext *cx, JSObject *obj);
|
||||
|
||||
bool IsCrossCompartmentWrapper(const JSObject *obj);
|
||||
|
||||
void
|
||||
NukeCrossCompartmentWrapper(JSObject *wrapper);
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
#endif
|
|
@ -0,0 +1,386 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: set ts=8 sw=4 et tw=99 ft=cpp:
|
||||
*
|
||||
* ***** 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 Mozilla Code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Jeff Walden <jwalden+code@mit.edu>
|
||||
*
|
||||
* 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 ***** */
|
||||
|
||||
/* Implementations of runtime and static assertion macros for C and C++. */
|
||||
|
||||
#ifndef mozilla_Assertions_h_
|
||||
#define mozilla_Assertions_h_
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/Types.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#ifndef WIN32
|
||||
# include <signal.h>
|
||||
#endif
|
||||
#ifdef ANDROID
|
||||
# include <android/log.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* MOZ_STATIC_ASSERT may be used to assert a condition *at compile time*. This
|
||||
* can be useful when you make certain assumptions about what must hold for
|
||||
* optimal, or even correct, behavior. For example, you might assert that the
|
||||
* size of a struct is a multiple of the target architecture's word size:
|
||||
*
|
||||
* struct S { ... };
|
||||
* MOZ_STATIC_ASSERT(sizeof(S) % sizeof(size_t) == 0,
|
||||
* "S should be a multiple of word size for efficiency");
|
||||
*
|
||||
* This macro can be used in any location where both an extern declaration and a
|
||||
* typedef could be used.
|
||||
*
|
||||
* Be aware of the gcc 4.2 concerns noted further down when writing patches that
|
||||
* use this macro, particularly if a patch only bounces on OS X.
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
# if defined(__clang__)
|
||||
# ifndef __has_extension
|
||||
# define __has_extension __has_feature /* compatibility, for older versions of clang */
|
||||
# endif
|
||||
# if __has_extension(cxx_static_assert)
|
||||
# define MOZ_STATIC_ASSERT(cond, reason) static_assert((cond), reason)
|
||||
# endif
|
||||
# elif defined(__GNUC__)
|
||||
# if (defined(__GXX_EXPERIMENTAL_CXX0X__) || __cplusplus >= 201103L) && \
|
||||
(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))
|
||||
# define MOZ_STATIC_ASSERT(cond, reason) static_assert((cond), reason)
|
||||
# endif
|
||||
# elif defined(_MSC_VER)
|
||||
# if _MSC_VER >= 1600 /* MSVC 10 */
|
||||
# define MOZ_STATIC_ASSERT(cond, reason) static_assert((cond), reason)
|
||||
# endif
|
||||
# elif defined(__HP_aCC)
|
||||
# if __HP_aCC >= 62500 && defined(_HP_CXX0x_SOURCE)
|
||||
# define MOZ_STATIC_ASSERT(cond, reason) static_assert((cond), reason)
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
#ifndef MOZ_STATIC_ASSERT
|
||||
# define MOZ_STATIC_ASSERT_GLUE1(x, y) x##y
|
||||
# define MOZ_STATIC_ASSERT_GLUE(x, y) MOZ_STATIC_ASSERT_GLUE1(x, y)
|
||||
# if defined(__SUNPRO_CC)
|
||||
/*
|
||||
* The Sun Studio C++ compiler is buggy when declaring, inside a function,
|
||||
* another extern'd function with an array argument whose length contains a
|
||||
* sizeof, triggering the error message "sizeof expression not accepted as
|
||||
* size of array parameter". This bug (6688515, not public yet) would hit
|
||||
* defining moz_static_assert as a function, so we always define an extern
|
||||
* array for Sun Studio.
|
||||
*
|
||||
* We include the line number in the symbol name in a best-effort attempt
|
||||
* to avoid conflicts (see below).
|
||||
*/
|
||||
# define MOZ_STATIC_ASSERT(cond, reason) \
|
||||
extern char MOZ_STATIC_ASSERT_GLUE(moz_static_assert, __LINE__)[(cond) ? 1 : -1]
|
||||
# elif defined(__COUNTER__)
|
||||
/*
|
||||
* If there was no preferred alternative, use a compiler-agnostic version.
|
||||
*
|
||||
* Note that the non-__COUNTER__ version has a bug in C++: it can't be used
|
||||
* in both |extern "C"| and normal C++ in the same translation unit. (Alas
|
||||
* |extern "C"| isn't allowed in a function.) The only affected compiler
|
||||
* we really care about is gcc 4.2. For that compiler and others like it,
|
||||
* we include the line number in the function name to do the best we can to
|
||||
* avoid conflicts. These should be rare: a conflict would require use of
|
||||
* MOZ_STATIC_ASSERT on the same line in separate files in the same
|
||||
* translation unit, *and* the uses would have to be in code with
|
||||
* different linkage, *and* the first observed use must be in C++-linkage
|
||||
* code.
|
||||
*/
|
||||
# define MOZ_STATIC_ASSERT(cond, reason) \
|
||||
typedef int MOZ_STATIC_ASSERT_GLUE(moz_static_assert, __COUNTER__)[(cond) ? 1 : -1]
|
||||
# else
|
||||
# define MOZ_STATIC_ASSERT(cond, reason) \
|
||||
extern void MOZ_STATIC_ASSERT_GLUE(moz_static_assert, __LINE__)(int arg[(cond) ? 1 : -1])
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#define MOZ_STATIC_ASSERT_IF(cond, expr, reason) MOZ_STATIC_ASSERT(!(cond) || (expr), reason)
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if defined(WIN32)
|
||||
/*
|
||||
* We used to call DebugBreak() on Windows, but amazingly, it causes
|
||||
* the MSVS 2010 debugger not to be able to recover a call stack.
|
||||
*/
|
||||
# define MOZ_CRASH() \
|
||||
do { \
|
||||
*((volatile int *) NULL) = 123; \
|
||||
exit(3); \
|
||||
} while (0)
|
||||
#elif defined(ANDROID)
|
||||
/*
|
||||
* On Android, raise(SIGABRT) is handled asynchronously. Seg fault now
|
||||
* so we crash immediately and capture the current call stack. We need
|
||||
* to specifically use the global namespace in the C++ case.
|
||||
*/
|
||||
# ifdef __cplusplus
|
||||
# define MOZ_CRASH() \
|
||||
do { \
|
||||
*((volatile int *) NULL) = 123; \
|
||||
::abort(); \
|
||||
} while (0)
|
||||
# else
|
||||
# define MOZ_CRASH() \
|
||||
do { \
|
||||
*((volatile int *) NULL) = 123; \
|
||||
abort(); \
|
||||
} while (0)
|
||||
# endif
|
||||
#elif defined(__APPLE__)
|
||||
/*
|
||||
* On Mac OS X, Breakpad ignores signals. Only real Mach exceptions are
|
||||
* trapped.
|
||||
*/
|
||||
# define MOZ_CRASH() \
|
||||
do { \
|
||||
*((volatile int *) NULL) = 123; \
|
||||
raise(SIGABRT); /* In case above statement gets nixed by the optimizer. */ \
|
||||
} while (0)
|
||||
#else
|
||||
# define MOZ_CRASH() \
|
||||
do { \
|
||||
raise(SIGABRT); /* To continue from here in GDB: "signal 0". */ \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
|
||||
extern MFBT_API(void)
|
||||
MOZ_Assert(const char* s, const char* file, int ln);
|
||||
|
||||
static MOZ_ALWAYS_INLINE void
|
||||
MOZ_OutputAssertMessage(const char* s, const char *file, int ln)
|
||||
{
|
||||
#ifdef ANDROID
|
||||
__android_log_print(ANDROID_LOG_FATAL, "MOZ_Assert",
|
||||
"Assertion failure: %s, at %s:%d\n", s, file, ln);
|
||||
#else
|
||||
fprintf(stderr, "Assertion failure: %s, at %s:%d\n", s, file, ln);
|
||||
fflush(stderr);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* MOZ_ASSERT(expr [, explanation-string]) asserts that |expr| must be truthy in
|
||||
* debug builds. If it is, execution continues. Otherwise, an error message
|
||||
* including the expression and the explanation-string (if provided) is printed,
|
||||
* an attempt is made to invoke any existing debugger, and execution halts.
|
||||
* MOZ_ASSERT is fatal: no recovery is possible. Do not assert a condition
|
||||
* which can correctly be falsy.
|
||||
*
|
||||
* The optional explanation-string, if provided, must be a string literal
|
||||
* explaining the assertion. It is intended for use with assertions whose
|
||||
* correctness or rationale is non-obvious, and for assertions where the "real"
|
||||
* condition being tested is best described prosaically. Don't provide an
|
||||
* explanation if it's not actually helpful.
|
||||
*
|
||||
* // No explanation needed: pointer arguments often must not be NULL.
|
||||
* MOZ_ASSERT(arg);
|
||||
*
|
||||
* // An explanation can be helpful to explain exactly how we know an
|
||||
* // assertion is valid.
|
||||
* MOZ_ASSERT(state == WAITING_FOR_RESPONSE,
|
||||
* "given that <thingA> and <thingB>, we must have...");
|
||||
*
|
||||
* // Or it might disambiguate multiple identical (save for their location)
|
||||
* // assertions of the same expression.
|
||||
* MOZ_ASSERT(getSlot(PRIMITIVE_THIS_SLOT).isUndefined(),
|
||||
* "we already set [[PrimitiveThis]] for this Boolean object");
|
||||
* MOZ_ASSERT(getSlot(PRIMITIVE_THIS_SLOT).isUndefined(),
|
||||
* "we already set [[PrimitiveThis]] for this String object");
|
||||
*
|
||||
* MOZ_ASSERT has no effect in non-debug builds. It is designed to catch bugs
|
||||
* *only* during debugging, not "in the field".
|
||||
*/
|
||||
#ifdef DEBUG
|
||||
/* First the single-argument form. */
|
||||
# define MOZ_ASSERT_HELPER1(expr) \
|
||||
do { \
|
||||
if (!(expr)) { \
|
||||
MOZ_OutputAssertMessage(#expr, __FILE__, __LINE__); \
|
||||
MOZ_CRASH(); \
|
||||
} \
|
||||
} while (0)
|
||||
/* Now the two-argument form. */
|
||||
# define MOZ_ASSERT_HELPER2(expr, explain) \
|
||||
do { \
|
||||
if (!(expr)) { \
|
||||
MOZ_OutputAssertMessage(#expr " (" explain ")", __FILE__, __LINE__); \
|
||||
MOZ_CRASH(); \
|
||||
} \
|
||||
} while (0)
|
||||
/* And now, helper macrology up the wazoo. */
|
||||
/*
|
||||
* Count the number of arguments passed to MOZ_ASSERT, very carefully
|
||||
* tiptoeing around an MSVC bug where it improperly expands __VA_ARGS__ as a
|
||||
* single token in argument lists. See these URLs for details:
|
||||
*
|
||||
* http://connect.microsoft.com/VisualStudio/feedback/details/380090/variadic-macro-replacement
|
||||
* http://cplusplus.co.il/2010/07/17/variadic-macro-to-count-number-of-arguments/#comment-644
|
||||
*/
|
||||
# define MOZ_COUNT_ASSERT_ARGS_IMPL2(_1, _2, count, ...) \
|
||||
count
|
||||
# define MOZ_COUNT_ASSERT_ARGS_IMPL(args) \
|
||||
MOZ_COUNT_ASSERT_ARGS_IMPL2 args
|
||||
# define MOZ_COUNT_ASSERT_ARGS(...) \
|
||||
MOZ_COUNT_ASSERT_ARGS_IMPL((__VA_ARGS__, 2, 1, 0))
|
||||
/* Pick the right helper macro to invoke. */
|
||||
# define MOZ_ASSERT_CHOOSE_HELPER2(count) MOZ_ASSERT_HELPER##count
|
||||
# define MOZ_ASSERT_CHOOSE_HELPER1(count) MOZ_ASSERT_CHOOSE_HELPER2(count)
|
||||
# define MOZ_ASSERT_CHOOSE_HELPER(count) MOZ_ASSERT_CHOOSE_HELPER1(count)
|
||||
/* The actual macro. */
|
||||
# define MOZ_ASSERT_GLUE(x, y) x y
|
||||
# define MOZ_ASSERT(...) \
|
||||
MOZ_ASSERT_GLUE(MOZ_ASSERT_CHOOSE_HELPER(MOZ_COUNT_ASSERT_ARGS(__VA_ARGS__)), \
|
||||
(__VA_ARGS__))
|
||||
#else
|
||||
# define MOZ_ASSERT(...) do { } while(0)
|
||||
#endif /* DEBUG */
|
||||
|
||||
/*
|
||||
* MOZ_ASSERT_IF(cond1, cond2) is equivalent to MOZ_ASSERT(cond2) if cond1 is
|
||||
* true.
|
||||
*
|
||||
* MOZ_ASSERT_IF(isPrime(num), num == 2 || isOdd(num));
|
||||
*
|
||||
* As with MOZ_ASSERT, MOZ_ASSERT_IF has effect only in debug builds. It is
|
||||
* designed to catch bugs during debugging, not "in the field".
|
||||
*/
|
||||
#ifdef DEBUG
|
||||
# define MOZ_ASSERT_IF(cond, expr) \
|
||||
do { \
|
||||
if (cond) \
|
||||
MOZ_ASSERT(expr); \
|
||||
} while (0)
|
||||
#else
|
||||
# define MOZ_ASSERT_IF(cond, expr) do { } while (0)
|
||||
#endif
|
||||
|
||||
/* MOZ_NOT_REACHED_MARKER() expands (in compilers which support it) to an
|
||||
* expression which states that it is undefined behavior for the compiler to
|
||||
* reach this point. Most code should probably use the higher level
|
||||
* MOZ_NOT_REACHED (which expands to this when appropriate).
|
||||
*/
|
||||
#if defined(__clang__)
|
||||
# define MOZ_NOT_REACHED_MARKER() __builtin_unreachable()
|
||||
#elif defined(__GNUC__)
|
||||
# if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)
|
||||
# define MOZ_NOT_REACHED_MARKER() __builtin_unreachable()
|
||||
# endif
|
||||
#elif defined(_MSC_VER)
|
||||
# define MOZ_NOT_REACHED_MARKER() __assume(0)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* MOZ_NOT_REACHED(reason) indicates that the given point can't be reached
|
||||
* during execution: simply reaching that point in execution is a bug. It takes
|
||||
* as an argument an error message indicating the reason why that point should
|
||||
* not have been reachable.
|
||||
*
|
||||
* // ...in a language parser...
|
||||
* void handle(BooleanLiteralNode node)
|
||||
* {
|
||||
* if (node.isTrue())
|
||||
* handleTrueLiteral();
|
||||
* else if (node.isFalse())
|
||||
* handleFalseLiteral();
|
||||
* else
|
||||
* MOZ_NOT_REACHED("boolean literal that's not true or false?");
|
||||
* }
|
||||
*/
|
||||
#if defined(MOZ_NOT_REACHED_MARKER)
|
||||
# if defined(DEBUG)
|
||||
# define MOZ_NOT_REACHED(reason) do { \
|
||||
MOZ_Assert(reason, __FILE__, __LINE__); \
|
||||
MOZ_NOT_REACHED_MARKER(); \
|
||||
} while (0)
|
||||
# else
|
||||
# define MOZ_NOT_REACHED(reason) MOZ_NOT_REACHED_MARKER()
|
||||
# endif
|
||||
#else
|
||||
# if defined(__GNUC__)
|
||||
/*
|
||||
* On older versions of gcc we need to call a noreturn function to mark the
|
||||
* code as unreachable. Since what we want is an unreachable version of
|
||||
* MOZ_Assert, we use an asm label
|
||||
* (http://gcc.gnu.org/onlinedocs/gcc-4.6.2/gcc/Asm-Labels.html) to create
|
||||
* a new declaration to the same symbol. MOZ_ASSERT_NR should only be
|
||||
* used via this macro, as it is a very specific hack to older versions of
|
||||
* gcc.
|
||||
*/
|
||||
# define MOZ_GETASMPREFIX2(X) #X
|
||||
# define MOZ_GETASMPREFIX(X) MOZ_GETASMPREFIX2(X)
|
||||
# define MOZ_ASMPREFIX MOZ_GETASMPREFIX(__USER_LABEL_PREFIX__)
|
||||
extern MOZ_NORETURN MFBT_API(void)
|
||||
MOZ_ASSERT_NR(const char* s, const char* file, int ln) \
|
||||
asm (MOZ_ASMPREFIX "MOZ_Assert");
|
||||
|
||||
# define MOZ_NOT_REACHED(reason) MOZ_ASSERT_NR(reason, __FILE__, __LINE__)
|
||||
# elif defined(DEBUG)
|
||||
# define MOZ_NOT_REACHED(reason) MOZ_Assert(reason, __FILE__, __LINE__)
|
||||
# else
|
||||
# define MOZ_NOT_REACHED(reason) ((void)0)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* MOZ_ALWAYS_TRUE(expr) and MOZ_ALWAYS_FALSE(expr) always evaluate the provided
|
||||
* expression, in debug builds and in release builds both. Then, in debug
|
||||
* builds only, the value of the expression is asserted either true or false
|
||||
* using MOZ_ASSERT.
|
||||
*/
|
||||
#ifdef DEBUG
|
||||
# define MOZ_ALWAYS_TRUE(expr) MOZ_ASSERT((expr))
|
||||
# define MOZ_ALWAYS_FALSE(expr) MOZ_ASSERT(!(expr))
|
||||
#else
|
||||
# define MOZ_ALWAYS_TRUE(expr) ((void)(expr))
|
||||
# define MOZ_ALWAYS_FALSE(expr) ((void)(expr))
|
||||
#endif
|
||||
|
||||
#endif /* mozilla_Assertions_h_ */
|
|
@ -0,0 +1,344 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sw=4 et tw=99 ft=cpp:
|
||||
*
|
||||
* ***** 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 Mozilla Code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Jeff Walden <jwalden+code@mit.edu> (original author)
|
||||
*
|
||||
* 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 ***** */
|
||||
|
||||
/* Implementations of various class and method modifier attributes. */
|
||||
|
||||
#ifndef mozilla_Attributes_h_
|
||||
#define mozilla_Attributes_h_
|
||||
|
||||
/*
|
||||
* This header does not include any other headers so that it can be included by
|
||||
* code that is (only currently) mfbt-incompatible.
|
||||
*/
|
||||
|
||||
/*
|
||||
* MOZ_INLINE is a macro which expands to tell the compiler that the method
|
||||
* decorated with it should be inlined. This macro is usable from C and C++
|
||||
* code, even though C89 does not support the |inline| keyword. The compiler
|
||||
* may ignore this directive if it chooses.
|
||||
*/
|
||||
#if defined(__cplusplus)
|
||||
# define MOZ_INLINE inline
|
||||
#elif defined(_MSC_VER)
|
||||
# define MOZ_INLINE __inline
|
||||
#elif defined(__GNUC__)
|
||||
# define MOZ_INLINE __inline__
|
||||
#else
|
||||
# define MOZ_INLINE inline
|
||||
#endif
|
||||
|
||||
/*
|
||||
* MOZ_ALWAYS_INLINE is a macro which expands to tell the compiler that the
|
||||
* method decorated with it must be inlined, even if the compiler thinks
|
||||
* otherwise. This is only a (much) stronger version of the MOZ_INLINE hint:
|
||||
* compilers are not guaranteed to respect it (although they're much more likely
|
||||
* to do so).
|
||||
*/
|
||||
#if defined(DEBUG)
|
||||
# define MOZ_ALWAYS_INLINE MOZ_INLINE
|
||||
#elif defined(_MSC_VER)
|
||||
# define MOZ_ALWAYS_INLINE __forceinline
|
||||
#elif defined(__GNUC__)
|
||||
# define MOZ_ALWAYS_INLINE __attribute__((always_inline)) MOZ_INLINE
|
||||
#else
|
||||
# define MOZ_ALWAYS_INLINE MOZ_INLINE
|
||||
#endif
|
||||
|
||||
/*
|
||||
* g++ requires -std=c++0x or -std=gnu++0x to support C++11 functionality
|
||||
* without warnings (functionality used by the macros below). These modes are
|
||||
* detectable by checking whether __GXX_EXPERIMENTAL_CXX0X__ is defined or, more
|
||||
* standardly, by checking whether __cplusplus has a C++11 or greater value.
|
||||
* Current versions of g++ do not correctly set __cplusplus, so we check both
|
||||
* for forward compatibility.
|
||||
*/
|
||||
#if defined(__clang__)
|
||||
/*
|
||||
* Per Clang documentation, "Note that marketing version numbers should not
|
||||
* be used to check for language features, as different vendors use different
|
||||
* numbering schemes. Instead, use the feature checking macros."
|
||||
*/
|
||||
# ifndef __has_extension
|
||||
# define __has_extension __has_feature /* compatibility, for older versions of clang */
|
||||
# endif
|
||||
# if __has_extension(cxx_deleted_functions)
|
||||
# define MOZ_HAVE_CXX11_DELETE
|
||||
# endif
|
||||
# if __has_extension(cxx_override_control)
|
||||
# define MOZ_HAVE_CXX11_OVERRIDE
|
||||
# define MOZ_HAVE_CXX11_FINAL final
|
||||
# endif
|
||||
# if __has_attribute(noinline)
|
||||
# define MOZ_HAVE_NEVER_INLINE __attribute__((noinline))
|
||||
# endif
|
||||
# if __has_attribute(noreturn)
|
||||
# define MOZ_HAVE_NORETURN __attribute__((noreturn))
|
||||
# endif
|
||||
#elif defined(__GNUC__)
|
||||
# if defined(__GXX_EXPERIMENTAL_CXX0X__) || __cplusplus >= 201103L
|
||||
# if __GNUC__ > 4
|
||||
# define MOZ_HAVE_CXX11_DELETE
|
||||
# define MOZ_HAVE_CXX11_OVERRIDE
|
||||
# define MOZ_HAVE_CXX11_FINAL final
|
||||
# elif __GNUC__ == 4
|
||||
# if __GNUC_MINOR__ >= 7
|
||||
# define MOZ_HAVE_CXX11_OVERRIDE
|
||||
# define MOZ_HAVE_CXX11_FINAL final
|
||||
# endif
|
||||
# if __GNUC_MINOR__ >= 4
|
||||
# define MOZ_HAVE_CXX11_DELETE
|
||||
# endif
|
||||
# endif
|
||||
# else
|
||||
/* __final is a non-C++11 GCC synonym for 'final', per GCC r176655. */
|
||||
# if __GNUC__ > 4
|
||||
# define MOZ_HAVE_CXX11_FINAL __final
|
||||
# elif __GNUC__ == 4
|
||||
# if __GNUC_MINOR__ >= 7
|
||||
# define MOZ_HAVE_CXX11_FINAL __final
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
# define MOZ_HAVE_NEVER_INLINE __attribute__((noinline))
|
||||
# define MOZ_HAVE_NORETURN __attribute__((noreturn))
|
||||
#elif defined(_MSC_VER)
|
||||
# if _MSC_VER >= 1400
|
||||
# define MOZ_HAVE_CXX11_OVERRIDE
|
||||
/* MSVC currently spells "final" as "sealed". */
|
||||
# define MOZ_HAVE_CXX11_FINAL sealed
|
||||
# endif
|
||||
# define MOZ_HAVE_NEVER_INLINE __declspec(noinline)
|
||||
# define MOZ_HAVE_NORETURN __declspec(noreturn)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* MOZ_NEVER_INLINE is a macro which expands to tell the compiler that the
|
||||
* method decorated with it must never be inlined, even if the compiler would
|
||||
* otherwise choose to inline the method. Compilers aren't absolutely
|
||||
* guaranteed to support this, but most do.
|
||||
*/
|
||||
#if defined(MOZ_HAVE_NEVER_INLINE)
|
||||
# define MOZ_NEVER_INLINE MOZ_HAVE_NEVER_INLINE
|
||||
#else
|
||||
# define MOZ_NEVER_INLINE /* no support */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* MOZ_NORETURN, specified at the start of a function declaration, indicates
|
||||
* that the given function does not return. (The function definition does not
|
||||
* need to be annotated.)
|
||||
*
|
||||
* MOZ_NORETURN void abort(const char* msg);
|
||||
*
|
||||
* This modifier permits the compiler to optimize code assuming a call to such a
|
||||
* function will never return. It also enables the compiler to avoid spurious
|
||||
* warnings about not initializing variables, or about any other seemingly-dodgy
|
||||
* operations performed after the function returns.
|
||||
*
|
||||
* This modifier does not affect the corresponding function's linking behavior.
|
||||
*/
|
||||
#if defined(MOZ_HAVE_NORETURN)
|
||||
# define MOZ_NORETURN MOZ_HAVE_NORETURN
|
||||
#else
|
||||
# define MOZ_NORETURN /* no support */
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
/*
|
||||
* MOZ_DELETE, specified immediately prior to the ';' terminating an undefined-
|
||||
* method declaration, attempts to delete that method from the corresponding
|
||||
* class. An attempt to use the method will always produce an error *at compile
|
||||
* time* (instead of sometimes as late as link time) when this macro can be
|
||||
* implemented. For example, you can use MOZ_DELETE to produce classes with no
|
||||
* implicit copy constructor or assignment operator:
|
||||
*
|
||||
* struct NonCopyable
|
||||
* {
|
||||
* private:
|
||||
* NonCopyable(const NonCopyable& other) MOZ_DELETE;
|
||||
* void operator=(const NonCopyable& other) MOZ_DELETE;
|
||||
* };
|
||||
*
|
||||
* If MOZ_DELETE can't be implemented for the current compiler, use of the
|
||||
* annotated method will still cause an error, but the error might occur at link
|
||||
* time in some cases rather than at compile time.
|
||||
*
|
||||
* MOZ_DELETE relies on C++11 functionality not universally implemented. As a
|
||||
* backstop, method declarations using MOZ_DELETE should be private.
|
||||
*/
|
||||
#if defined(MOZ_HAVE_CXX11_DELETE)
|
||||
# define MOZ_DELETE = delete
|
||||
#else
|
||||
# define MOZ_DELETE /* no support */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* MOZ_OVERRIDE explicitly indicates that a virtual member function in a class
|
||||
* overrides a member function of a base class, rather than potentially being a
|
||||
* new member function. MOZ_OVERRIDE should be placed immediately before the
|
||||
* ';' terminating the member function's declaration, or before '= 0;' if the
|
||||
* member function is pure. If the member function is defined in the class
|
||||
* definition, it should appear before the opening brace of the function body.
|
||||
*
|
||||
* class Base
|
||||
* {
|
||||
* public:
|
||||
* virtual void f() = 0;
|
||||
* };
|
||||
* class Derived1 : public Base
|
||||
* {
|
||||
* public:
|
||||
* virtual void f() MOZ_OVERRIDE;
|
||||
* };
|
||||
* class Derived2 : public Base
|
||||
* {
|
||||
* public:
|
||||
* virtual void f() MOZ_OVERRIDE = 0;
|
||||
* };
|
||||
* class Derived3 : public Base
|
||||
* {
|
||||
* public:
|
||||
* virtual void f() MOZ_OVERRIDE { }
|
||||
* };
|
||||
*
|
||||
* In compilers supporting C++11 override controls, MOZ_OVERRIDE *requires* that
|
||||
* the function marked with it override a member function of a base class: it
|
||||
* is a compile error if it does not. Otherwise MOZ_OVERRIDE does not affect
|
||||
* semantics and merely documents the override relationship to the reader (but
|
||||
* of course must still be used correctly to not break C++11 compilers).
|
||||
*/
|
||||
#if defined(MOZ_HAVE_CXX11_OVERRIDE)
|
||||
# define MOZ_OVERRIDE override
|
||||
#else
|
||||
# define MOZ_OVERRIDE /* no support */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* MOZ_FINAL indicates that some functionality cannot be overridden through
|
||||
* inheritance. It can be used to annotate either classes/structs or virtual
|
||||
* member functions.
|
||||
*
|
||||
* To annotate a class/struct with MOZ_FINAL, place MOZ_FINAL immediately after
|
||||
* the name of the class, before the list of classes from which it derives (if
|
||||
* any) and before its opening brace. MOZ_FINAL must not be used to annotate
|
||||
* unnamed classes or structs. (With some compilers, and with C++11 proper, the
|
||||
* underlying expansion is ambiguous with specifying a class name.)
|
||||
*
|
||||
* class Base MOZ_FINAL
|
||||
* {
|
||||
* public:
|
||||
* Base();
|
||||
* ~Base();
|
||||
* virtual void f() { }
|
||||
* };
|
||||
* // This will be an error in some compilers:
|
||||
* class Derived : public Base
|
||||
* {
|
||||
* public:
|
||||
* ~Derived() { }
|
||||
* };
|
||||
*
|
||||
* One particularly common reason to specify MOZ_FINAL upon a class is to tell
|
||||
* the compiler that it's not dangerous for it to have a non-virtual destructor
|
||||
* yet have one or more virtual functions, silencing the warning it might emit
|
||||
* in this case. Suppose Base above weren't annotated with MOZ_FINAL. Because
|
||||
* ~Base() is non-virtual, an attempt to delete a Derived* through a Base*
|
||||
* wouldn't call ~Derived(), so any cleanup ~Derived() might do wouldn't happen.
|
||||
* (Formally C++ says behavior is undefined, but compilers will likely just call
|
||||
* ~Base() and not ~Derived().) Specifying MOZ_FINAL tells the compiler that
|
||||
* it's safe for the destructor to be non-virtual.
|
||||
*
|
||||
* In compilers implementing final controls, it is an error to inherit from a
|
||||
* class annotated with MOZ_FINAL. In other compilers it serves only as
|
||||
* documentation.
|
||||
*
|
||||
* To annotate a virtual member function with MOZ_FINAL, place MOZ_FINAL
|
||||
* immediately before the ';' terminating the member function's declaration, or
|
||||
* before '= 0;' if the member function is pure. If the member function is
|
||||
* defined in the class definition, it should appear before the opening brace of
|
||||
* the function body. (This placement is identical to that for MOZ_OVERRIDE.
|
||||
* If both are used, they should appear in the order 'MOZ_FINAL MOZ_OVERRIDE'
|
||||
* for consistency.)
|
||||
*
|
||||
* class Base
|
||||
* {
|
||||
* public:
|
||||
* virtual void f() MOZ_FINAL;
|
||||
* };
|
||||
* class Derived
|
||||
* {
|
||||
* public:
|
||||
* // This will be an error in some compilers:
|
||||
* virtual void f();
|
||||
* };
|
||||
*
|
||||
* In compilers implementing final controls, it is an error for a derived class
|
||||
* to override a method annotated with MOZ_FINAL. In other compilers it serves
|
||||
* only as documentation.
|
||||
*/
|
||||
#if defined(MOZ_HAVE_CXX11_FINAL)
|
||||
# define MOZ_FINAL MOZ_HAVE_CXX11_FINAL
|
||||
#else
|
||||
# define MOZ_FINAL /* no support */
|
||||
#endif
|
||||
|
||||
/**
|
||||
* MOZ_WARN_UNUSED_RESULT tells the compiler to emit a warning if a function's
|
||||
* return value is not used by the caller.
|
||||
*
|
||||
* Place this attribute at the very beginning of a function definition. For
|
||||
* example, write
|
||||
*
|
||||
* MOZ_WARN_UNUSED_RESULT int foo();
|
||||
*
|
||||
* or
|
||||
*
|
||||
* MOZ_WARN_UNUSED_RESULT int foo() { return 42; }
|
||||
*/
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
# define MOZ_WARN_UNUSED_RESULT __attribute__ ((warn_unused_result))
|
||||
#else
|
||||
# define MOZ_WARN_UNUSED_RESULT
|
||||
#endif
|
||||
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* mozilla_Attributes_h_ */
|
|
@ -0,0 +1,232 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/*
|
||||
* A counting Bloom filter implementation. This allows consumers to
|
||||
* do fast probabilistic "is item X in set Y?" testing which will
|
||||
* never answer "no" when the correct answer is "yes" (but might
|
||||
* incorrectly answer "yes" when the correct answer is "no").
|
||||
*/
|
||||
|
||||
#ifndef mozilla_BloomFilter_h_
|
||||
#define mozilla_BloomFilter_h_
|
||||
|
||||
#include "mozilla/Likely.h"
|
||||
#include "mozilla/StandardInteger.h"
|
||||
#include "mozilla/Util.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
/*
|
||||
* This class implements a counting Bloom filter as described at
|
||||
* <http://en.wikipedia.org/wiki/Bloom_filter#Counting_filters>, with
|
||||
* 8-bit counters. This allows quick probabilistic answers to the
|
||||
* question "is object X in set Y?" where the contents of Y might not
|
||||
* be time-invariant. The probabilistic nature of the test means that
|
||||
* sometimes the answer will be "yes" when it should be "no". If the
|
||||
* answer is "no", then X is guaranteed not to be in Y.
|
||||
*
|
||||
* The filter is parametrized on KeySize, which is the size of the key
|
||||
* generated by each of hash functions used by the filter, in bits,
|
||||
* and the type of object T being added and removed. T must implement
|
||||
* a |uint32_t hash() const| method which returns a uint32_t hash key
|
||||
* that will be used to generate the two separate hash functions for
|
||||
* the Bloom filter. This hash key MUST be well-distributed for good
|
||||
* results! KeySize is not allowed to be larger than 16.
|
||||
*
|
||||
* The filter uses exactly 2**KeySize bytes of memory. From now on we
|
||||
* will refer to the memory used by the filter as M.
|
||||
*
|
||||
* The expected rate of incorrect "yes" answers depends on M and on
|
||||
* the number N of objects in set Y. As long as N is small compared
|
||||
* to M, the rate of such answers is expected to be approximately
|
||||
* 4*(N/M)**2 for this filter. In practice, if Y has a few hundred
|
||||
* elements then using a KeySize of 12 gives a reasonably low
|
||||
* incorrect answer rate. A KeySize of 12 has the additional benefit
|
||||
* of using exactly one page for the filter in typical hardware
|
||||
* configurations.
|
||||
*/
|
||||
|
||||
template<unsigned KeySize, class T>
|
||||
class BloomFilter {
|
||||
/*
|
||||
* A counting Bloom filter with 8-bit counters. For now we assume
|
||||
* that having two hash functions is enough, but we may revisit that
|
||||
* decision later.
|
||||
*
|
||||
* The filter uses an array with 2**KeySize entries.
|
||||
*
|
||||
* Assuming a well-distributed hash function, a Bloom filter with
|
||||
* array size M containing N elements and
|
||||
* using k hash function has expected false positive rate exactly
|
||||
*
|
||||
* $ (1 - (1 - 1/M)^{kN})^k $
|
||||
*
|
||||
* because each array slot has a
|
||||
*
|
||||
* $ (1 - 1/M)^{kN} $
|
||||
*
|
||||
* chance of being 0, and the expected false positive rate is the
|
||||
* probability that all of the k hash functions will hit a nonzero
|
||||
* slot.
|
||||
*
|
||||
* For reasonable assumptions (M large, kN large, which should both
|
||||
* hold if we're worried about false positives) about M and kN this
|
||||
* becomes approximately
|
||||
*
|
||||
* $$ (1 - \exp(-kN/M))^k $$
|
||||
*
|
||||
* For our special case of k == 2, that's $(1 - \exp(-2N/M))^2$,
|
||||
* or in other words
|
||||
*
|
||||
* $$ N/M = -0.5 * \ln(1 - \sqrt(r)) $$
|
||||
*
|
||||
* where r is the false positive rate. This can be used to compute
|
||||
* the desired KeySize for a given load N and false positive rate r.
|
||||
*
|
||||
* If N/M is assumed small, then the false positive rate can
|
||||
* further be approximated as 4*N^2/M^2. So increasing KeySize by
|
||||
* 1, which doubles M, reduces the false positive rate by about a
|
||||
* factor of 4, and a false positive rate of 1% corresponds to
|
||||
* about M/N == 20.
|
||||
*
|
||||
* What this means in practice is that for a few hundred keys using a
|
||||
* KeySize of 12 gives false positive rates on the order of 0.25-4%.
|
||||
*
|
||||
* Similarly, using a KeySize of 10 would lead to a 4% false
|
||||
* positive rate for N == 100 and to quite bad false positive
|
||||
* rates for larger N.
|
||||
*/
|
||||
public:
|
||||
BloomFilter() {
|
||||
MOZ_STATIC_ASSERT(KeySize <= keyShift, "KeySize too big");
|
||||
|
||||
// Should we have a custom operator new using calloc instead and
|
||||
// require that we're allocated via the operator?
|
||||
clear();
|
||||
}
|
||||
|
||||
/*
|
||||
* Clear the filter. This should be done before reusing it, because
|
||||
* just removing all items doesn't clear counters that hit the upper
|
||||
* bound.
|
||||
*/
|
||||
void clear();
|
||||
|
||||
/*
|
||||
* Add an item to the filter.
|
||||
*/
|
||||
void add(const T* t);
|
||||
|
||||
/*
|
||||
* Remove an item from the filter.
|
||||
*/
|
||||
void remove(const T* t);
|
||||
|
||||
/*
|
||||
* Check whether the filter might contain an item. This can
|
||||
* sometimes return true even if the item is not in the filter,
|
||||
* but will never return false for items that are actually in the
|
||||
* filter.
|
||||
*/
|
||||
bool mightContain(const T* t) const;
|
||||
|
||||
/*
|
||||
* Methods for add/remove/contain when we already have a hash computed
|
||||
*/
|
||||
void add(uint32_t hash);
|
||||
void remove(uint32_t hash);
|
||||
bool mightContain(uint32_t hash) const;
|
||||
|
||||
private:
|
||||
static const size_t arraySize = (1 << KeySize);
|
||||
static const uint32_t keyMask = (1 << KeySize) - 1;
|
||||
static const uint32_t keyShift = 16;
|
||||
|
||||
static uint32_t hash1(uint32_t hash) { return hash & keyMask; }
|
||||
static uint32_t hash2(uint32_t hash) { return (hash >> keyShift) & keyMask; }
|
||||
|
||||
uint8_t& firstSlot(uint32_t hash) { return counters[hash1(hash)]; }
|
||||
uint8_t& secondSlot(uint32_t hash) { return counters[hash2(hash)]; }
|
||||
const uint8_t& firstSlot(uint32_t hash) const { return counters[hash1(hash)]; }
|
||||
const uint8_t& secondSlot(uint32_t hash) const { return counters[hash2(hash)]; }
|
||||
|
||||
static bool full(const uint8_t& slot) { return slot == UINT8_MAX; }
|
||||
|
||||
uint8_t counters[arraySize];
|
||||
};
|
||||
|
||||
template<unsigned KeySize, class T>
|
||||
inline void
|
||||
BloomFilter<KeySize, T>::clear()
|
||||
{
|
||||
memset(counters, 0, arraySize);
|
||||
}
|
||||
|
||||
template<unsigned KeySize, class T>
|
||||
inline void
|
||||
BloomFilter<KeySize, T>::add(uint32_t hash)
|
||||
{
|
||||
uint8_t& slot1 = firstSlot(hash);
|
||||
if (MOZ_LIKELY(!full(slot1)))
|
||||
++slot1;
|
||||
|
||||
uint8_t& slot2 = secondSlot(hash);
|
||||
if (MOZ_LIKELY(!full(slot2)))
|
||||
++slot2;
|
||||
}
|
||||
|
||||
template<unsigned KeySize, class T>
|
||||
MOZ_ALWAYS_INLINE void
|
||||
BloomFilter<KeySize, T>::add(const T* t)
|
||||
{
|
||||
uint32_t hash = t->hash();
|
||||
return add(hash);
|
||||
}
|
||||
|
||||
template<unsigned KeySize, class T>
|
||||
inline void
|
||||
BloomFilter<KeySize, T>::remove(uint32_t hash)
|
||||
{
|
||||
// If the slots are full, we don't know whether we bumped them to be
|
||||
// there when we added or not, so just leave them full.
|
||||
uint8_t& slot1 = firstSlot(hash);
|
||||
if (MOZ_LIKELY(!full(slot1)))
|
||||
--slot1;
|
||||
|
||||
uint8_t& slot2 = secondSlot(hash);
|
||||
if (MOZ_LIKELY(!full(slot2)))
|
||||
--slot2;
|
||||
}
|
||||
|
||||
template<unsigned KeySize, class T>
|
||||
MOZ_ALWAYS_INLINE void
|
||||
BloomFilter<KeySize, T>::remove(const T* t)
|
||||
{
|
||||
uint32_t hash = t->hash();
|
||||
remove(hash);
|
||||
}
|
||||
|
||||
template<unsigned KeySize, class T>
|
||||
MOZ_ALWAYS_INLINE bool
|
||||
BloomFilter<KeySize, T>::mightContain(uint32_t hash) const
|
||||
{
|
||||
// Check that all the slots for this hash contain something
|
||||
return firstSlot(hash) && secondSlot(hash);
|
||||
}
|
||||
|
||||
template<unsigned KeySize, class T>
|
||||
MOZ_ALWAYS_INLINE bool
|
||||
BloomFilter<KeySize, T>::mightContain(const T* t) const
|
||||
{
|
||||
uint32_t hash = t->hash();
|
||||
return mightContain(hash);
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* mozilla_BloomFilter_h_ */
|
|
@ -0,0 +1,254 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* Various predicates and operations on IEEE-754 floating point types. */
|
||||
|
||||
#ifndef mozilla_FloatingPoint_h_
|
||||
#define mozilla_FloatingPoint_h_
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/StandardInteger.h"
|
||||
|
||||
/*
|
||||
* It's reasonable to ask why we have this header at all. Don't isnan,
|
||||
* copysign, the built-in comparison operators, and the like solve these
|
||||
* problems? Unfortunately, they don't. We've found that various compilers
|
||||
* (MSVC, MSVC when compiling with PGO, and GCC on OS X, at least) miscompile
|
||||
* the standard methods in various situations, so we can't use them. Some of
|
||||
* these compilers even have problems compiling seemingly reasonable bitwise
|
||||
* algorithms! But with some care we've found algorithms that seem to not
|
||||
* trigger those compiler bugs.
|
||||
*
|
||||
* For the aforementioned reasons, be very wary of making changes to any of
|
||||
* these algorithms. If you must make changes, keep a careful eye out for
|
||||
* compiler bustage, particularly PGO-specific bustage.
|
||||
*
|
||||
* Some users require that this file be C-compatible. Unfortunately, this means
|
||||
* no mozilla namespace to contain everything, no detail namespace clarifying
|
||||
* MozDoublePun to be an internal data structure, and so on.
|
||||
*/
|
||||
|
||||
/*
|
||||
* These implementations all assume |double| is a 64-bit double format number
|
||||
* type, compatible with the IEEE-754 standard. C/C++ don't require this to be
|
||||
* the case. But we required this in implementations of these algorithms that
|
||||
* preceded this header, so we shouldn't break anything if we continue doing so.
|
||||
*/
|
||||
MOZ_STATIC_ASSERT(sizeof(double) == sizeof(uint64_t), "double must be 64 bits");
|
||||
|
||||
/*
|
||||
* Constant expressions in C can't refer to consts, unfortunately, so #define
|
||||
* these rather than use |const uint64_t|.
|
||||
*/
|
||||
#define MOZ_DOUBLE_SIGN_BIT 0x8000000000000000ULL
|
||||
#define MOZ_DOUBLE_EXPONENT_BITS 0x7ff0000000000000ULL
|
||||
#define MOZ_DOUBLE_SIGNIFICAND_BITS 0x000fffffffffffffULL
|
||||
|
||||
#define MOZ_DOUBLE_EXPONENT_BIAS 1023
|
||||
#define MOZ_DOUBLE_EXPONENT_SHIFT 52
|
||||
|
||||
MOZ_STATIC_ASSERT((MOZ_DOUBLE_SIGN_BIT & MOZ_DOUBLE_EXPONENT_BITS) == 0,
|
||||
"sign bit doesn't overlap exponent bits");
|
||||
MOZ_STATIC_ASSERT((MOZ_DOUBLE_SIGN_BIT & MOZ_DOUBLE_SIGNIFICAND_BITS) == 0,
|
||||
"sign bit doesn't overlap significand bits");
|
||||
MOZ_STATIC_ASSERT((MOZ_DOUBLE_EXPONENT_BITS & MOZ_DOUBLE_SIGNIFICAND_BITS) == 0,
|
||||
"exponent bits don't overlap significand bits");
|
||||
|
||||
MOZ_STATIC_ASSERT((MOZ_DOUBLE_SIGN_BIT | MOZ_DOUBLE_EXPONENT_BITS | MOZ_DOUBLE_SIGNIFICAND_BITS)
|
||||
== ~(uint64_t)0,
|
||||
"all bits accounted for");
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This union is NOT a public data structure, and it is not to be used outside
|
||||
* this file!
|
||||
*/
|
||||
union MozDoublePun {
|
||||
/*
|
||||
* Every way to pun the bits of a double introduces an additional layer of
|
||||
* complexity, across a multitude of platforms, architectures, and ABIs.
|
||||
* Use *only* uint64_t to reduce complexity. Don't add new punning here
|
||||
* without discussion!
|
||||
*/
|
||||
uint64_t u;
|
||||
double d;
|
||||
};
|
||||
|
||||
/** Determines whether a double is NaN. */
|
||||
static MOZ_ALWAYS_INLINE int
|
||||
MOZ_DOUBLE_IS_NaN(double d)
|
||||
{
|
||||
union MozDoublePun pun;
|
||||
pun.d = d;
|
||||
|
||||
/*
|
||||
* A double is NaN if all exponent bits are 1 and the significand contains at
|
||||
* least one non-zero bit.
|
||||
*/
|
||||
return (pun.u & MOZ_DOUBLE_EXPONENT_BITS) == MOZ_DOUBLE_EXPONENT_BITS &&
|
||||
(pun.u & MOZ_DOUBLE_SIGNIFICAND_BITS) != 0;
|
||||
}
|
||||
|
||||
/** Determines whether a double is +Infinity or -Infinity. */
|
||||
static MOZ_ALWAYS_INLINE int
|
||||
MOZ_DOUBLE_IS_INFINITE(double d)
|
||||
{
|
||||
union MozDoublePun pun;
|
||||
pun.d = d;
|
||||
|
||||
/* Infinities have all exponent bits set to 1 and an all-0 significand. */
|
||||
return (pun.u & ~MOZ_DOUBLE_SIGN_BIT) == MOZ_DOUBLE_EXPONENT_BITS;
|
||||
}
|
||||
|
||||
/** Determines whether a double is not NaN or infinite. */
|
||||
static MOZ_ALWAYS_INLINE int
|
||||
MOZ_DOUBLE_IS_FINITE(double d)
|
||||
{
|
||||
union MozDoublePun pun;
|
||||
pun.d = d;
|
||||
|
||||
/*
|
||||
* NaN and Infinities are the only non-finite doubles, and both have all
|
||||
* exponent bits set to 1.
|
||||
*/
|
||||
return (pun.u & MOZ_DOUBLE_EXPONENT_BITS) != MOZ_DOUBLE_EXPONENT_BITS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether a double is negative. It is an error to call this method
|
||||
* on a double which is NaN.
|
||||
*/
|
||||
static MOZ_ALWAYS_INLINE int
|
||||
MOZ_DOUBLE_IS_NEGATIVE(double d)
|
||||
{
|
||||
union MozDoublePun pun;
|
||||
pun.d = d;
|
||||
|
||||
MOZ_ASSERT(!MOZ_DOUBLE_IS_NaN(d), "NaN does not have a sign");
|
||||
|
||||
/* The sign bit is set if the double is negative. */
|
||||
return (pun.u & MOZ_DOUBLE_SIGN_BIT) != 0;
|
||||
}
|
||||
|
||||
/** Determines whether a double represents -0. */
|
||||
static MOZ_ALWAYS_INLINE int
|
||||
MOZ_DOUBLE_IS_NEGATIVE_ZERO(double d)
|
||||
{
|
||||
union MozDoublePun pun;
|
||||
pun.d = d;
|
||||
|
||||
/* Only the sign bit is set if the double is -0. */
|
||||
return pun.u == MOZ_DOUBLE_SIGN_BIT;
|
||||
}
|
||||
|
||||
/** Returns the exponent portion of the double. */
|
||||
static MOZ_ALWAYS_INLINE int_fast16_t
|
||||
MOZ_DOUBLE_EXPONENT(double d)
|
||||
{
|
||||
union MozDoublePun pun;
|
||||
pun.d = d;
|
||||
|
||||
/*
|
||||
* The exponent component of a double is an unsigned number, biased from its
|
||||
* actual value. Subtract the bias to retrieve the actual exponent.
|
||||
*/
|
||||
return (int_fast16_t)((pun.u & MOZ_DOUBLE_EXPONENT_BITS) >> MOZ_DOUBLE_EXPONENT_SHIFT) -
|
||||
MOZ_DOUBLE_EXPONENT_BIAS;
|
||||
}
|
||||
|
||||
/** Returns +Infinity. */
|
||||
static MOZ_ALWAYS_INLINE double
|
||||
MOZ_DOUBLE_POSITIVE_INFINITY()
|
||||
{
|
||||
union MozDoublePun pun;
|
||||
|
||||
/*
|
||||
* Positive infinity has all exponent bits set, sign bit set to 0, and no
|
||||
* significand.
|
||||
*/
|
||||
pun.u = MOZ_DOUBLE_EXPONENT_BITS;
|
||||
return pun.d;
|
||||
}
|
||||
|
||||
/** Returns -Infinity. */
|
||||
static MOZ_ALWAYS_INLINE double
|
||||
MOZ_DOUBLE_NEGATIVE_INFINITY()
|
||||
{
|
||||
union MozDoublePun pun;
|
||||
|
||||
/*
|
||||
* Negative infinity has all exponent bits set, sign bit set to 1, and no
|
||||
* significand.
|
||||
*/
|
||||
pun.u = MOZ_DOUBLE_SIGN_BIT | MOZ_DOUBLE_EXPONENT_BITS;
|
||||
return pun.d;
|
||||
}
|
||||
|
||||
/** Constructs a NaN value with the specified sign bit and significand bits. */
|
||||
static MOZ_ALWAYS_INLINE double
|
||||
MOZ_DOUBLE_SPECIFIC_NaN(int signbit, uint64_t significand)
|
||||
{
|
||||
union MozDoublePun pun;
|
||||
|
||||
MOZ_ASSERT(signbit == 0 || signbit == 1);
|
||||
MOZ_ASSERT((significand & ~MOZ_DOUBLE_SIGNIFICAND_BITS) == 0);
|
||||
MOZ_ASSERT(significand & MOZ_DOUBLE_SIGNIFICAND_BITS);
|
||||
|
||||
pun.u = (signbit ? MOZ_DOUBLE_SIGN_BIT : 0) |
|
||||
MOZ_DOUBLE_EXPONENT_BITS |
|
||||
significand;
|
||||
MOZ_ASSERT(MOZ_DOUBLE_IS_NaN(pun.d));
|
||||
return pun.d;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes a NaN value. Do not use this method if you depend upon a particular
|
||||
* NaN value being returned.
|
||||
*/
|
||||
static MOZ_ALWAYS_INLINE double
|
||||
MOZ_DOUBLE_NaN()
|
||||
{
|
||||
return MOZ_DOUBLE_SPECIFIC_NaN(0, 0xfffffffffffffULL);
|
||||
}
|
||||
|
||||
/** Computes the smallest non-zero positive double value. */
|
||||
static MOZ_ALWAYS_INLINE double
|
||||
MOZ_DOUBLE_MIN_VALUE()
|
||||
{
|
||||
union MozDoublePun pun;
|
||||
pun.u = 1;
|
||||
return pun.d;
|
||||
}
|
||||
|
||||
/** Computes a 32-bit hash of the given double. */
|
||||
static MOZ_ALWAYS_INLINE uint32_t
|
||||
MOZ_HASH_DOUBLE(double d)
|
||||
{
|
||||
union MozDoublePun pun;
|
||||
pun.d = d;
|
||||
|
||||
return ((uint32_t)(pun.u >> 32)) ^ ((uint32_t)(pun.u));
|
||||
}
|
||||
|
||||
static MOZ_ALWAYS_INLINE int
|
||||
MOZ_DOUBLE_IS_INT32(double d, int32_t* i)
|
||||
{
|
||||
/*
|
||||
* XXX Casting a double that doesn't truncate to int32_t, to int32_t, induces
|
||||
* undefined behavior. We should definitely fix this (bug 744965), but as
|
||||
* apparently it "works" in practice, it's not a pressing concern now.
|
||||
*/
|
||||
return !MOZ_DOUBLE_IS_NEGATIVE_ZERO(d) && d == (*i = (int32_t)d);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* mozilla_FloatingPoint_h_ */
|
|
@ -0,0 +1,182 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* vim: set ts=8 sw=4 et tw=99 ft=cpp: */
|
||||
/* ***** 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 mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* the Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* L. David Baron <dbaron@dbaron.org>, Mozilla Corporation (original author)
|
||||
* Ms2ger <ms2ger@gmail.com>
|
||||
*
|
||||
* 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 ***** */
|
||||
|
||||
/* Implementation of macros to ensure correct use of RAII Auto* objects. */
|
||||
|
||||
#ifndef mozilla_GuardObjects_h
|
||||
#define mozilla_GuardObjects_h
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/Types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
namespace mozilla {
|
||||
namespace detail {
|
||||
/*
|
||||
* The following classes are designed to cause assertions to detect
|
||||
* inadvertent use of guard objects as temporaries. In other words,
|
||||
* when we have a guard object whose only purpose is its constructor and
|
||||
* destructor (and is never otherwise referenced), the intended use
|
||||
* might be:
|
||||
*
|
||||
* AutoRestore savePainting(mIsPainting);
|
||||
*
|
||||
* but is is easy to accidentally write:
|
||||
*
|
||||
* AutoRestore(mIsPainting);
|
||||
*
|
||||
* which compiles just fine, but runs the destructor well before the
|
||||
* intended time.
|
||||
*
|
||||
* They work by adding (#ifdef DEBUG) an additional parameter to the
|
||||
* guard object's constructor, with a default value, so that users of
|
||||
* the guard object's API do not need to do anything. The default value
|
||||
* of this parameter is a temporary object. C++ (ISO/IEC 14882:1998),
|
||||
* section 12.2 [class.temporary], clauses 4 and 5 seem to assume a
|
||||
* guarantee that temporaries are destroyed in the reverse of their
|
||||
* construction order, but I actually can't find a statement that that
|
||||
* is true in the general case (beyond the two specific cases mentioned
|
||||
* there). However, it seems to be true.
|
||||
*
|
||||
* These classes are intended to be used only via the macros immediately
|
||||
* below them:
|
||||
*
|
||||
* MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER declares (ifdef DEBUG) a member
|
||||
* variable, and should be put where a declaration of a private
|
||||
* member variable would be placed.
|
||||
* MOZ_GUARD_OBJECT_NOTIFIER_PARAM should be placed at the end of the
|
||||
* parameters to each constructor of the guard object; it declares
|
||||
* (ifdef DEBUG) an additional parameter. (But use the *_ONLY_PARAM
|
||||
* variant for constructors that take no other parameters.)
|
||||
* MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL should likewise be used in
|
||||
* the implementation of such constructors when they are not inline.
|
||||
* MOZ_GUARD_OBJECT_NOTIFIER_PARAM_TO_PARENT should be used in
|
||||
* the implementation of such constructors to pass the parameter to
|
||||
* a base class that also uses these macros
|
||||
* MOZ_GUARD_OBJECT_NOTIFIER_INIT is a statement that belongs in each
|
||||
* constructor. It uses the parameter declared by
|
||||
* MOZ_GUARD_OBJECT_NOTIFIER_PARAM.
|
||||
*
|
||||
* For more details, and examples of using these macros, see
|
||||
* https://developer.mozilla.org/en/Using_RAII_classes_in_Mozilla
|
||||
*/
|
||||
class MOZ_EXPORT_API(GuardObjectNotifier)
|
||||
{
|
||||
private:
|
||||
bool* statementDone;
|
||||
|
||||
public:
|
||||
GuardObjectNotifier() : statementDone(NULL) {}
|
||||
|
||||
~GuardObjectNotifier() {
|
||||
*statementDone = true;
|
||||
}
|
||||
|
||||
void setStatementDone(bool* statementIsDone) {
|
||||
statementDone = statementIsDone;
|
||||
}
|
||||
};
|
||||
|
||||
class MOZ_EXPORT_API(GuardObjectNotificationReceiver)
|
||||
{
|
||||
private:
|
||||
bool statementDone;
|
||||
|
||||
public:
|
||||
GuardObjectNotificationReceiver() : statementDone(false) {}
|
||||
|
||||
~GuardObjectNotificationReceiver() {
|
||||
/*
|
||||
* Assert that the guard object was not used as a temporary.
|
||||
* (Note that this assert might also fire if init is not called
|
||||
* because the guard object's implementation is not using the
|
||||
* above macros correctly.)
|
||||
*/
|
||||
MOZ_ASSERT(statementDone);
|
||||
}
|
||||
|
||||
void init(const GuardObjectNotifier& constNotifier) {
|
||||
/*
|
||||
* constNotifier is passed as a const reference so that we can pass a
|
||||
* temporary, but we really intend it as non-const.
|
||||
*/
|
||||
GuardObjectNotifier& notifier = const_cast<GuardObjectNotifier&>(constNotifier);
|
||||
notifier.setStatementDone(&statementDone);
|
||||
}
|
||||
};
|
||||
|
||||
} /* namespace detail */
|
||||
} /* namespace mozilla */
|
||||
|
||||
#endif /* DEBUG */
|
||||
|
||||
#ifdef DEBUG
|
||||
# define MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER \
|
||||
mozilla::detail::GuardObjectNotificationReceiver _mCheckNotUsedAsTemporary;
|
||||
# define MOZ_GUARD_OBJECT_NOTIFIER_PARAM \
|
||||
, const mozilla::detail::GuardObjectNotifier& _notifier = \
|
||||
mozilla::detail::GuardObjectNotifier()
|
||||
# define MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM \
|
||||
const mozilla::detail::GuardObjectNotifier& _notifier = \
|
||||
mozilla::detail::GuardObjectNotifier()
|
||||
# define MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL \
|
||||
, const mozilla::detail::GuardObjectNotifier& _notifier
|
||||
# define MOZ_GUARD_OBJECT_NOTIFIER_PARAM_TO_PARENT \
|
||||
, _notifier
|
||||
# define MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM_TO_PARENT \
|
||||
_notifier
|
||||
# define MOZ_GUARD_OBJECT_NOTIFIER_INIT \
|
||||
do { _mCheckNotUsedAsTemporary.init(_notifier); } while (0)
|
||||
#else
|
||||
# define MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
|
||||
# define MOZ_GUARD_OBJECT_NOTIFIER_PARAM
|
||||
# define MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM
|
||||
# define MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL
|
||||
# define MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM_TO_PARENT
|
||||
# define MOZ_GUARD_OBJECT_NOTIFIER_PARAM_TO_PARENT
|
||||
# define MOZ_GUARD_OBJECT_NOTIFIER_INIT do { } while (0)
|
||||
#endif
|
||||
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* mozilla_GuardObjects_h */
|
|
@ -0,0 +1,350 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: set ts=8 sw=4 et tw=99 ft=cpp:
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* Utilities for hashing */
|
||||
|
||||
/*
|
||||
* This file exports functions for hashing data down to a 32-bit value,
|
||||
* including:
|
||||
*
|
||||
* - HashString Hash a char* or uint16_t/wchar_t* of known or unknown
|
||||
* length.
|
||||
*
|
||||
* - HashBytes Hash a byte array of known length.
|
||||
*
|
||||
* - HashGeneric Hash one or more values. Currently, we support uint32_t,
|
||||
* types which can be implicitly cast to uint32_t, data
|
||||
* pointers, and function pointers.
|
||||
*
|
||||
* - AddToHash Add one or more values to the given hash. This supports the
|
||||
* same list of types as HashGeneric.
|
||||
*
|
||||
*
|
||||
* You can chain these functions together to hash complex objects. For example:
|
||||
*
|
||||
* class ComplexObject {
|
||||
* char* str;
|
||||
* uint32_t uint1, uint2;
|
||||
* void (*callbackFn)();
|
||||
*
|
||||
* uint32_t Hash() {
|
||||
* uint32_t hash = HashString(str);
|
||||
* hash = AddToHash(hash, uint1, uint2);
|
||||
* return AddToHash(hash, callbackFn);
|
||||
* }
|
||||
* };
|
||||
*
|
||||
* If you want to hash an nsAString or nsACString, use the HashString functions
|
||||
* in nsHashKey.h.
|
||||
*/
|
||||
|
||||
#ifndef mozilla_HashFunctions_h_
|
||||
#define mozilla_HashFunctions_h_
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/StandardInteger.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
namespace mozilla {
|
||||
|
||||
/**
|
||||
* The golden ratio as a 32-bit fixed-point value.
|
||||
*/
|
||||
static const uint32_t GoldenRatioU32 = 0x9E3779B9U;
|
||||
|
||||
inline uint32_t
|
||||
RotateBitsLeft32(uint32_t value, uint8_t bits)
|
||||
{
|
||||
MOZ_ASSERT(bits < 32);
|
||||
return (value << bits) | (value >> (32 - bits));
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
|
||||
inline uint32_t
|
||||
AddU32ToHash(uint32_t hash, uint32_t value)
|
||||
{
|
||||
/*
|
||||
* This is the meat of all our hash routines. This hash function is not
|
||||
* particularly sophisticated, but it seems to work well for our mostly
|
||||
* plain-text inputs. Implementation notes follow.
|
||||
*
|
||||
* Our use of the golden ratio here is arbitrary; we could pick almost any
|
||||
* number which:
|
||||
*
|
||||
* * is odd (because otherwise, all our hash values will be even)
|
||||
*
|
||||
* * has a reasonably-even mix of 1's and 0's (consider the extreme case
|
||||
* where we multiply by 0x3 or 0xeffffff -- this will not produce good
|
||||
* mixing across all bits of the hash).
|
||||
*
|
||||
* The rotation length of 5 is also arbitrary, although an odd number is again
|
||||
* preferable so our hash explores the whole universe of possible rotations.
|
||||
*
|
||||
* Finally, we multiply by the golden ratio *after* xor'ing, not before.
|
||||
* Otherwise, if |hash| is 0 (as it often is for the beginning of a message),
|
||||
* the expression
|
||||
*
|
||||
* (GoldenRatioU32 * RotateBitsLeft(hash, 5)) |xor| value
|
||||
*
|
||||
* evaluates to |value|.
|
||||
*
|
||||
* (Number-theoretic aside: Because any odd number |m| is relatively prime to
|
||||
* our modulus (2^32), the list
|
||||
*
|
||||
* [x * m (mod 2^32) for 0 <= x < 2^32]
|
||||
*
|
||||
* has no duplicate elements. This means that multiplying by |m| does not
|
||||
* cause us to skip any possible hash values.
|
||||
*
|
||||
* It's also nice if |m| has large-ish order mod 2^32 -- that is, if the
|
||||
* smallest k such that m^k == 1 (mod 2^32) is large -- so we can safely
|
||||
* multiply our hash value by |m| a few times without negating the
|
||||
* multiplicative effect. Our golden ratio constant has order 2^29, which is
|
||||
* more than enough for our purposes.)
|
||||
*/
|
||||
return GoldenRatioU32 * (RotateBitsLeft32(hash, 5) ^ value);
|
||||
}
|
||||
|
||||
/**
|
||||
* AddUintptrToHash takes sizeof(uintptr_t) as a template parameter.
|
||||
*/
|
||||
template<size_t PtrSize>
|
||||
inline uint32_t
|
||||
AddUintptrToHash(uint32_t hash, uintptr_t value);
|
||||
|
||||
template<>
|
||||
inline uint32_t
|
||||
AddUintptrToHash<4>(uint32_t hash, uintptr_t value)
|
||||
{
|
||||
return AddU32ToHash(hash, static_cast<uint32_t>(value));
|
||||
}
|
||||
|
||||
template<>
|
||||
inline uint32_t
|
||||
AddUintptrToHash<8>(uint32_t hash, uintptr_t value)
|
||||
{
|
||||
/*
|
||||
* The static cast to uint64_t below is necessary because this function
|
||||
* sometimes gets compiled on 32-bit platforms (yes, even though it's a
|
||||
* template and we never call this particular override in a 32-bit build). If
|
||||
* we do value >> 32 on a 32-bit machine, we're shifting a 32-bit uintptr_t
|
||||
* right 32 bits, and the compiler throws an error.
|
||||
*/
|
||||
uint32_t v1 = static_cast<uint32_t>(value);
|
||||
uint32_t v2 = static_cast<uint32_t>(static_cast<uint64_t>(value) >> 32);
|
||||
return AddU32ToHash(AddU32ToHash(hash, v1), v2);
|
||||
}
|
||||
|
||||
} /* namespace detail */
|
||||
|
||||
/**
|
||||
* AddToHash takes a hash and some values and returns a new hash based on the
|
||||
* inputs.
|
||||
*
|
||||
* Currently, we support hashing uint32_t's, values which we can implicitly
|
||||
* convert to uint32_t, data pointers, and function pointers.
|
||||
*/
|
||||
template<typename A>
|
||||
MOZ_WARN_UNUSED_RESULT
|
||||
inline uint32_t
|
||||
AddToHash(uint32_t hash, A a)
|
||||
{
|
||||
/*
|
||||
* Try to convert |A| to uint32_t implicitly. If this works, great. If not,
|
||||
* we'll error out.
|
||||
*/
|
||||
return detail::AddU32ToHash(hash, a);
|
||||
}
|
||||
|
||||
template<typename A>
|
||||
MOZ_WARN_UNUSED_RESULT
|
||||
inline uint32_t
|
||||
AddToHash(uint32_t hash, A* a)
|
||||
{
|
||||
/*
|
||||
* You might think this function should just take a void*. But then we'd only
|
||||
* catch data pointers and couldn't handle function pointers.
|
||||
*/
|
||||
|
||||
MOZ_STATIC_ASSERT(sizeof(a) == sizeof(uintptr_t),
|
||||
"Strange pointer!");
|
||||
|
||||
return detail::AddUintptrToHash<sizeof(uintptr_t)>(hash, uintptr_t(a));
|
||||
}
|
||||
|
||||
template<typename A, typename B>
|
||||
MOZ_WARN_UNUSED_RESULT
|
||||
uint32_t
|
||||
AddToHash(uint32_t hash, A a, B b)
|
||||
{
|
||||
return AddToHash(AddToHash(hash, a), b);
|
||||
}
|
||||
|
||||
template<typename A, typename B, typename C>
|
||||
MOZ_WARN_UNUSED_RESULT
|
||||
uint32_t
|
||||
AddToHash(uint32_t hash, A a, B b, C c)
|
||||
{
|
||||
return AddToHash(AddToHash(hash, a, b), c);
|
||||
}
|
||||
|
||||
template<typename A, typename B, typename C, typename D>
|
||||
MOZ_WARN_UNUSED_RESULT
|
||||
uint32_t
|
||||
AddToHash(uint32_t hash, A a, B b, C c, D d)
|
||||
{
|
||||
return AddToHash(AddToHash(hash, a, b, c), d);
|
||||
}
|
||||
|
||||
template<typename A, typename B, typename C, typename D, typename E>
|
||||
MOZ_WARN_UNUSED_RESULT
|
||||
uint32_t
|
||||
AddToHash(uint32_t hash, A a, B b, C c, D d, E e)
|
||||
{
|
||||
return AddToHash(AddToHash(hash, a, b, c, d), e);
|
||||
}
|
||||
|
||||
/**
|
||||
* The HashGeneric class of functions let you hash one or more values.
|
||||
*
|
||||
* If you want to hash together two values x and y, calling HashGeneric(x, y) is
|
||||
* much better than calling AddToHash(x, y), because AddToHash(x, y) assumes
|
||||
* that x has already been hashed.
|
||||
*/
|
||||
template<typename A>
|
||||
MOZ_WARN_UNUSED_RESULT
|
||||
inline uint32_t
|
||||
HashGeneric(A a)
|
||||
{
|
||||
return AddToHash(0, a);
|
||||
}
|
||||
|
||||
template<typename A, typename B>
|
||||
MOZ_WARN_UNUSED_RESULT
|
||||
inline uint32_t
|
||||
HashGeneric(A a, B b)
|
||||
{
|
||||
return AddToHash(0, a, b);
|
||||
}
|
||||
|
||||
template<typename A, typename B, typename C>
|
||||
MOZ_WARN_UNUSED_RESULT
|
||||
inline uint32_t
|
||||
HashGeneric(A a, B b, C c)
|
||||
{
|
||||
return AddToHash(0, a, b, c);
|
||||
}
|
||||
|
||||
template<typename A, typename B, typename C, typename D>
|
||||
MOZ_WARN_UNUSED_RESULT
|
||||
inline uint32_t
|
||||
HashGeneric(A a, B b, C c, D d)
|
||||
{
|
||||
return AddToHash(0, a, b, c, d);
|
||||
}
|
||||
|
||||
template<typename A, typename B, typename C, typename D, typename E>
|
||||
MOZ_WARN_UNUSED_RESULT
|
||||
inline uint32_t
|
||||
HashGeneric(A a, B b, C c, D d, E e)
|
||||
{
|
||||
return AddToHash(0, a, b, c, d, e);
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<typename T>
|
||||
uint32_t
|
||||
HashUntilZero(const T* str)
|
||||
{
|
||||
uint32_t hash = 0;
|
||||
for (T c; (c = *str); str++)
|
||||
hash = AddToHash(hash, c);
|
||||
return hash;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
uint32_t
|
||||
HashKnownLength(const T* str, size_t length)
|
||||
{
|
||||
uint32_t hash = 0;
|
||||
for (size_t i = 0; i < length; i++)
|
||||
hash = AddToHash(hash, str[i]);
|
||||
return hash;
|
||||
}
|
||||
|
||||
} /* namespace detail */
|
||||
|
||||
/**
|
||||
* The HashString overloads below do just what you'd expect.
|
||||
*
|
||||
* If you have the string's length, you might as well call the overload which
|
||||
* includes the length. It may be marginally faster.
|
||||
*/
|
||||
MOZ_WARN_UNUSED_RESULT
|
||||
inline uint32_t
|
||||
HashString(const char* str)
|
||||
{
|
||||
return detail::HashUntilZero(str);
|
||||
}
|
||||
|
||||
MOZ_WARN_UNUSED_RESULT
|
||||
inline uint32_t
|
||||
HashString(const char* str, size_t length)
|
||||
{
|
||||
return detail::HashKnownLength(str, length);
|
||||
}
|
||||
|
||||
MOZ_WARN_UNUSED_RESULT
|
||||
inline uint32_t
|
||||
HashString(const uint16_t* str)
|
||||
{
|
||||
return detail::HashUntilZero(str);
|
||||
}
|
||||
|
||||
MOZ_WARN_UNUSED_RESULT
|
||||
inline uint32_t
|
||||
HashString(const uint16_t* str, size_t length)
|
||||
{
|
||||
return detail::HashKnownLength(str, length);
|
||||
}
|
||||
|
||||
/*
|
||||
* On Windows, wchar_t (PRUnichar) is not the same as uint16_t, even though it's
|
||||
* the same width!
|
||||
*/
|
||||
#ifdef WIN32
|
||||
MOZ_WARN_UNUSED_RESULT
|
||||
inline uint32_t
|
||||
HashString(const wchar_t* str)
|
||||
{
|
||||
return detail::HashUntilZero(str);
|
||||
}
|
||||
|
||||
MOZ_WARN_UNUSED_RESULT
|
||||
inline uint32_t
|
||||
HashString(const wchar_t* str, size_t length)
|
||||
{
|
||||
return detail::HashKnownLength(str, length);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Hash some number of bytes.
|
||||
*
|
||||
* This hash walks word-by-word, rather than byte-by-byte, so you won't get the
|
||||
* same result out of HashBytes as you would out of HashString.
|
||||
*/
|
||||
MOZ_WARN_UNUSED_RESULT
|
||||
extern MFBT_API(uint32_t)
|
||||
HashBytes(const void* bytes, size_t length);
|
||||
|
||||
} /* namespace mozilla */
|
||||
#endif /* __cplusplus */
|
||||
#endif /* mozilla_HashFunctions_h_ */
|
|
@ -0,0 +1,21 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/*
|
||||
* MOZ_LIKELY and MOZ_UNLIKELY macros to hint to the compiler how a
|
||||
* boolean predicate should be branch-predicted.
|
||||
*/
|
||||
|
||||
#ifndef Likely_h_
|
||||
#define Likely_h_
|
||||
|
||||
#if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ > 2))
|
||||
# define MOZ_LIKELY(x) (__builtin_expect((x), 1))
|
||||
# define MOZ_UNLIKELY(x) (__builtin_expect((x), 0))
|
||||
#else
|
||||
# define MOZ_LIKELY(x) (x)
|
||||
# define MOZ_UNLIKELY(x) (x)
|
||||
#endif
|
||||
|
||||
#endif /* Likely_h_ */
|
|
@ -0,0 +1,434 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=4 sw=4 tw=80 et cin:
|
||||
*
|
||||
* ***** 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 Mozilla Code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation
|
||||
* Portions created by the Initial Developer are Copyright (C) 2012
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Justin Lebar <justin.lebar@gmail.com>
|
||||
*
|
||||
* 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 ***** */
|
||||
|
||||
/* A type-safe doubly-linked list class. */
|
||||
|
||||
/*
|
||||
* The classes LinkedList<T> and LinkedListElement<T> together form a
|
||||
* convenient, type-safe doubly-linked list implementation.
|
||||
*
|
||||
* The class T which will be inserted into the linked list must inherit from
|
||||
* LinkedListElement<T>. A given object may be in only one linked list at a
|
||||
* time.
|
||||
*
|
||||
* For example, you might use LinkedList in a simple observer list class as
|
||||
* follows.
|
||||
*
|
||||
* class Observer : public LinkedListElement<Observer>
|
||||
* {
|
||||
* void observe(char* topic) { ... }
|
||||
* };
|
||||
*
|
||||
* class ObserverContainer
|
||||
* {
|
||||
* private:
|
||||
* LinkedList<ElemType> list;
|
||||
*
|
||||
* public:
|
||||
*
|
||||
* void addObserver(Observer* observer)
|
||||
* {
|
||||
* // Will assert if |observer| is part of another list.
|
||||
* list.insertBack(observer);
|
||||
* }
|
||||
*
|
||||
* void removeObserver(Observer* observer)
|
||||
* {
|
||||
* // Will assert if |observer| is not part of some list.
|
||||
* observer.remove();
|
||||
* }
|
||||
*
|
||||
* void notifyObservers(char* topic)
|
||||
* {
|
||||
* for (Observer* o = list.getFirst();
|
||||
* o != NULL;
|
||||
* o = o->getNext()) {
|
||||
* o->Observe(topic);
|
||||
* }
|
||||
* }
|
||||
* };
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef mozilla_LinkedList_h_
|
||||
#define mozilla_LinkedList_h_
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
template<typename T>
|
||||
class LinkedList;
|
||||
|
||||
template<typename T>
|
||||
class LinkedListElement
|
||||
{
|
||||
/*
|
||||
* It's convenient that we return NULL when getNext() or getPrevious() hits
|
||||
* the end of the list, but doing so costs an extra word of storage in each
|
||||
* linked list node (to keep track of whether |this| is the sentinel node)
|
||||
* and a branch on this value in getNext/getPrevious.
|
||||
*
|
||||
* We could get rid of the extra word of storage by shoving the "is
|
||||
* sentinel" bit into one of the pointers, although this would, of course,
|
||||
* have performance implications of its own.
|
||||
*
|
||||
* But the goal here isn't to win an award for the fastest or slimmest
|
||||
* linked list; rather, we want a *convenient* linked list. So we won't
|
||||
* waste time guessing which micro-optimization strategy is best.
|
||||
*
|
||||
*
|
||||
* Speaking of unnecessary work, it's worth addressing here why we wrote
|
||||
* mozilla::LinkedList in the first place, instead of using stl::list.
|
||||
*
|
||||
* The key difference between mozilla::LinkedList and stl::list is that
|
||||
* mozilla::LinkedList stores the prev/next pointers in the object itself,
|
||||
* while stl::list stores the prev/next pointers in a list element which
|
||||
* itself points to the object being stored.
|
||||
*
|
||||
* mozilla::LinkedList's approach makes it harder to store an object in more
|
||||
* than one list. But the upside is that you can call next() / prev() /
|
||||
* remove() directly on the object. With stl::list, you'd need to store a
|
||||
* pointer to its iterator in the object in order to accomplish this. Not
|
||||
* only would this waste space, but you'd have to remember to update that
|
||||
* pointer every time you added or removed the object from a list.
|
||||
*
|
||||
* In-place, constant-time removal is a killer feature of doubly-linked
|
||||
* lists, and supporting this painlessly was a key design criterion.
|
||||
*/
|
||||
|
||||
private:
|
||||
LinkedListElement* next;
|
||||
LinkedListElement* prev;
|
||||
const bool isSentinel;
|
||||
|
||||
public:
|
||||
LinkedListElement()
|
||||
: next(this)
|
||||
, prev(this)
|
||||
, isSentinel(false)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the next element in the list, or NULL if this is the last element in
|
||||
* the list.
|
||||
*/
|
||||
T* getNext()
|
||||
{
|
||||
return next->asT();
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the previous element in the list, or NULL if this is the first element
|
||||
* in the list.
|
||||
*/
|
||||
T* getPrevious()
|
||||
{
|
||||
return prev->asT();
|
||||
}
|
||||
|
||||
/*
|
||||
* Insert elem after this element in the list. |this| must be part of a
|
||||
* linked list when you call setNext(); otherwise, this method will assert.
|
||||
*/
|
||||
void setNext(T* elem)
|
||||
{
|
||||
MOZ_ASSERT(isInList());
|
||||
setNextUnsafe(elem);
|
||||
}
|
||||
|
||||
/*
|
||||
* Insert elem before this element in the list. |this| must be part of a
|
||||
* linked list when you call setPrevious(); otherwise, this method will
|
||||
* assert.
|
||||
*/
|
||||
void setPrevious(T* elem)
|
||||
{
|
||||
MOZ_ASSERT(isInList());
|
||||
setPreviousUnsafe(elem);
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove this element from the list which contains it. If this element is
|
||||
* not currently part of a linked list, this method asserts.
|
||||
*/
|
||||
void remove()
|
||||
{
|
||||
MOZ_ASSERT(isInList());
|
||||
|
||||
prev->next = next;
|
||||
next->prev = prev;
|
||||
next = this;
|
||||
prev = this;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return true if |this| part is of a linked list, and false otherwise.
|
||||
*/
|
||||
bool isInList()
|
||||
{
|
||||
MOZ_ASSERT((next == this) == (prev == this));
|
||||
return next != this;
|
||||
}
|
||||
|
||||
private:
|
||||
LinkedListElement& operator=(const LinkedList<T>& other) MOZ_DELETE;
|
||||
LinkedListElement(const LinkedList<T>& other) MOZ_DELETE;
|
||||
|
||||
friend class LinkedList<T>;
|
||||
|
||||
enum NodeKind {
|
||||
NODE_KIND_NORMAL,
|
||||
NODE_KIND_SENTINEL
|
||||
};
|
||||
|
||||
LinkedListElement(NodeKind nodeKind)
|
||||
: next(this)
|
||||
, prev(this)
|
||||
, isSentinel(nodeKind == NODE_KIND_SENTINEL)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* Return |this| cast to T* if we're a normal node, or return NULL if we're
|
||||
* a sentinel node.
|
||||
*/
|
||||
T* asT()
|
||||
{
|
||||
if (isSentinel)
|
||||
return NULL;
|
||||
|
||||
return static_cast<T*>(this);
|
||||
}
|
||||
|
||||
/*
|
||||
* Insert elem after this element, but don't check that this element is in
|
||||
* the list. This is called by LinkedList::insertFront().
|
||||
*/
|
||||
void setNextUnsafe(T* elem)
|
||||
{
|
||||
LinkedListElement *listElem = static_cast<LinkedListElement*>(elem);
|
||||
MOZ_ASSERT(!listElem->isInList());
|
||||
|
||||
listElem->next = this->next;
|
||||
listElem->prev = this;
|
||||
this->next->prev = listElem;
|
||||
this->next = listElem;
|
||||
}
|
||||
|
||||
/*
|
||||
* Insert elem before this element, but don't check that this element is in
|
||||
* the list. This is called by LinkedList::insertBack().
|
||||
*/
|
||||
void setPreviousUnsafe(T* elem)
|
||||
{
|
||||
LinkedListElement<T>* listElem = static_cast<LinkedListElement<T>*>(elem);
|
||||
MOZ_ASSERT(!listElem->isInList());
|
||||
|
||||
listElem->next = this;
|
||||
listElem->prev = this->prev;
|
||||
this->prev->next = listElem;
|
||||
this->prev = listElem;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class LinkedList
|
||||
{
|
||||
private:
|
||||
LinkedListElement<T> sentinel;
|
||||
|
||||
public:
|
||||
LinkedList& operator=(const LinkedList<T>& other) MOZ_DELETE;
|
||||
LinkedList(const LinkedList<T>& other) MOZ_DELETE;
|
||||
|
||||
LinkedList()
|
||||
: sentinel(LinkedListElement<T>::NODE_KIND_SENTINEL)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* Add elem to the front of the list.
|
||||
*/
|
||||
void insertFront(T* elem)
|
||||
{
|
||||
/* Bypass setNext()'s this->isInList() assertion. */
|
||||
sentinel.setNextUnsafe(elem);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add elem to the back of the list.
|
||||
*/
|
||||
void insertBack(T* elem)
|
||||
{
|
||||
sentinel.setPreviousUnsafe(elem);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the first element of the list, or NULL if the list is empty.
|
||||
*/
|
||||
T* getFirst()
|
||||
{
|
||||
return sentinel.getNext();
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the last element of the list, or NULL if the list is empty.
|
||||
*/
|
||||
T* getLast()
|
||||
{
|
||||
return sentinel.getPrevious();
|
||||
}
|
||||
|
||||
/*
|
||||
* Get and remove the first element of the list. If the list is empty,
|
||||
* return NULL.
|
||||
*/
|
||||
T* popFirst()
|
||||
{
|
||||
T* ret = sentinel.getNext();
|
||||
if (ret)
|
||||
static_cast<LinkedListElement<T>*>(ret)->remove();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get and remove the last element of the list. If the list is empty,
|
||||
* return NULL.
|
||||
*/
|
||||
T* popLast()
|
||||
{
|
||||
T* ret = sentinel.getPrevious();
|
||||
if (ret)
|
||||
static_cast<LinkedListElement<T>*>(ret)->remove();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return true if the list is empty, or false otherwise.
|
||||
*/
|
||||
bool isEmpty()
|
||||
{
|
||||
return !sentinel.isInList();
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove all the elements from the list.
|
||||
*
|
||||
* This runs in time linear to the list's length, because we have to mark
|
||||
* each element as not in the list.
|
||||
*/
|
||||
void clear()
|
||||
{
|
||||
while (popFirst())
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* In a debug build, make sure that the list is sane (no cycles, consistent
|
||||
* next/prev pointers, only one sentinel). Has no effect in release builds.
|
||||
*/
|
||||
void debugAssertIsSane()
|
||||
{
|
||||
#ifdef DEBUG
|
||||
/*
|
||||
* Check for cycles in the forward singly-linked list using the
|
||||
* tortoise/hare algorithm.
|
||||
*/
|
||||
for (LinkedListElement<T>* slow = sentinel.next,
|
||||
* fast1 = sentinel.next->next,
|
||||
* fast2 = sentinel.next->next->next;
|
||||
slow != sentinel && fast1 != sentinel && fast2 != sentinel;
|
||||
slow = slow->next,
|
||||
fast1 = fast2->next,
|
||||
fast2 = fast1->next) {
|
||||
|
||||
MOZ_ASSERT(slow != fast1);
|
||||
MOZ_ASSERT(slow != fast2);
|
||||
}
|
||||
|
||||
/* Check for cycles in the backward singly-linked list. */
|
||||
for (LinkedListElement<T>* slow = sentinel.prev,
|
||||
* fast1 = sentinel.prev->prev,
|
||||
* fast2 = sentinel.prev->prev->prev;
|
||||
slow != sentinel && fast1 != sentinel && fast2 != sentinel;
|
||||
slow = slow->prev,
|
||||
fast1 = fast2->prev,
|
||||
fast2 = fast1->prev) {
|
||||
|
||||
MOZ_ASSERT(slow != fast1);
|
||||
MOZ_ASSERT(slow != fast2);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check that |sentinel| is the only node in the list with
|
||||
* isSentinel == true.
|
||||
*/
|
||||
for (LinkedListElement<T>* elem = sentinel.next;
|
||||
elem != sentinel;
|
||||
elem = elem->next) {
|
||||
|
||||
MOZ_ASSERT(!elem->isSentinel);
|
||||
}
|
||||
|
||||
/* Check that the next/prev pointers match up. */
|
||||
LinkedListElement<T>* prev = sentinel;
|
||||
LinkedListElement<T>* cur = sentinel.next;
|
||||
do {
|
||||
MOZ_ASSERT(cur->prev == prev);
|
||||
MOZ_ASSERT(prev->next == cur);
|
||||
|
||||
prev = cur;
|
||||
cur = cur->next;
|
||||
} while (cur != sentinel);
|
||||
#endif /* ifdef DEBUG */
|
||||
}
|
||||
};
|
||||
|
||||
} /* namespace mozilla */
|
||||
|
||||
#endif /* ifdef __cplusplus */
|
||||
#endif /* ifdef mozilla_LinkedList_h_ */
|
|
@ -0,0 +1,247 @@
|
|||
// ISO C9x compliant stdint.h for Microsoft Visual Studio
|
||||
// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124
|
||||
//
|
||||
// Copyright (c) 2006-2008 Alexander Chemeris
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. The name of the author may be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _MSC_VER // [
|
||||
#error "Use this header only with Microsoft Visual C++ compilers!"
|
||||
#endif // _MSC_VER ]
|
||||
|
||||
#ifndef _MSC_STDINT_H_ // [
|
||||
#define _MSC_STDINT_H_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
// For Visual Studio 6 in C++ mode and for many Visual Studio versions when
|
||||
// compiling for ARM we should wrap <wchar.h> include with 'extern "C++" {}'
|
||||
// or compiler give many errors like this:
|
||||
// error C2733: second C linkage of overloaded function 'wmemchr' not allowed
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
# include <wchar.h>
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
// Define _W64 macros to mark types changing their size, like intptr_t.
|
||||
#ifndef _W64
|
||||
# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300
|
||||
# define _W64 __w64
|
||||
# else
|
||||
# define _W64
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
// 7.18.1 Integer types
|
||||
|
||||
// 7.18.1.1 Exact-width integer types
|
||||
|
||||
// Visual Studio 6 and Embedded Visual C++ 4 doesn't
|
||||
// realize that, e.g. char has the same size as __int8
|
||||
// so we give up on __intX for them.
|
||||
#if (_MSC_VER < 1300)
|
||||
typedef signed char int8_t;
|
||||
typedef signed short int16_t;
|
||||
typedef signed int int32_t;
|
||||
typedef unsigned char uint8_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef unsigned int uint32_t;
|
||||
#else
|
||||
typedef signed __int8 int8_t;
|
||||
typedef signed __int16 int16_t;
|
||||
typedef signed __int32 int32_t;
|
||||
typedef unsigned __int8 uint8_t;
|
||||
typedef unsigned __int16 uint16_t;
|
||||
typedef unsigned __int32 uint32_t;
|
||||
#endif
|
||||
typedef signed __int64 int64_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
|
||||
|
||||
// 7.18.1.2 Minimum-width integer types
|
||||
typedef int8_t int_least8_t;
|
||||
typedef int16_t int_least16_t;
|
||||
typedef int32_t int_least32_t;
|
||||
typedef int64_t int_least64_t;
|
||||
typedef uint8_t uint_least8_t;
|
||||
typedef uint16_t uint_least16_t;
|
||||
typedef uint32_t uint_least32_t;
|
||||
typedef uint64_t uint_least64_t;
|
||||
|
||||
// 7.18.1.3 Fastest minimum-width integer types
|
||||
typedef int8_t int_fast8_t;
|
||||
typedef int32_t int_fast16_t;
|
||||
typedef int32_t int_fast32_t;
|
||||
typedef int64_t int_fast64_t;
|
||||
typedef uint8_t uint_fast8_t;
|
||||
typedef uint32_t uint_fast16_t;
|
||||
typedef uint32_t uint_fast32_t;
|
||||
typedef uint64_t uint_fast64_t;
|
||||
|
||||
// 7.18.1.4 Integer types capable of holding object pointers
|
||||
#ifdef _WIN64 // [
|
||||
typedef signed __int64 intptr_t;
|
||||
typedef unsigned __int64 uintptr_t;
|
||||
#else // _WIN64 ][
|
||||
typedef _W64 signed int intptr_t;
|
||||
typedef _W64 unsigned int uintptr_t;
|
||||
#endif // _WIN64 ]
|
||||
|
||||
// 7.18.1.5 Greatest-width integer types
|
||||
typedef int64_t intmax_t;
|
||||
typedef uint64_t uintmax_t;
|
||||
|
||||
|
||||
// 7.18.2 Limits of specified-width integer types
|
||||
|
||||
#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259
|
||||
|
||||
// 7.18.2.1 Limits of exact-width integer types
|
||||
#define INT8_MIN ((int8_t)_I8_MIN)
|
||||
#define INT8_MAX _I8_MAX
|
||||
#define INT16_MIN ((int16_t)_I16_MIN)
|
||||
#define INT16_MAX _I16_MAX
|
||||
#define INT32_MIN ((int32_t)_I32_MIN)
|
||||
#define INT32_MAX _I32_MAX
|
||||
#define INT64_MIN ((int64_t)_I64_MIN)
|
||||
#define INT64_MAX _I64_MAX
|
||||
#define UINT8_MAX _UI8_MAX
|
||||
#define UINT16_MAX _UI16_MAX
|
||||
#define UINT32_MAX _UI32_MAX
|
||||
#define UINT64_MAX _UI64_MAX
|
||||
|
||||
// 7.18.2.2 Limits of minimum-width integer types
|
||||
#define INT_LEAST8_MIN INT8_MIN
|
||||
#define INT_LEAST8_MAX INT8_MAX
|
||||
#define INT_LEAST16_MIN INT16_MIN
|
||||
#define INT_LEAST16_MAX INT16_MAX
|
||||
#define INT_LEAST32_MIN INT32_MIN
|
||||
#define INT_LEAST32_MAX INT32_MAX
|
||||
#define INT_LEAST64_MIN INT64_MIN
|
||||
#define INT_LEAST64_MAX INT64_MAX
|
||||
#define UINT_LEAST8_MAX UINT8_MAX
|
||||
#define UINT_LEAST16_MAX UINT16_MAX
|
||||
#define UINT_LEAST32_MAX UINT32_MAX
|
||||
#define UINT_LEAST64_MAX UINT64_MAX
|
||||
|
||||
// 7.18.2.3 Limits of fastest minimum-width integer types
|
||||
#define INT_FAST8_MIN INT8_MIN
|
||||
#define INT_FAST8_MAX INT8_MAX
|
||||
#define INT_FAST16_MIN INT16_MIN
|
||||
#define INT_FAST16_MAX INT16_MAX
|
||||
#define INT_FAST32_MIN INT32_MIN
|
||||
#define INT_FAST32_MAX INT32_MAX
|
||||
#define INT_FAST64_MIN INT64_MIN
|
||||
#define INT_FAST64_MAX INT64_MAX
|
||||
#define UINT_FAST8_MAX UINT8_MAX
|
||||
#define UINT_FAST16_MAX UINT16_MAX
|
||||
#define UINT_FAST32_MAX UINT32_MAX
|
||||
#define UINT_FAST64_MAX UINT64_MAX
|
||||
|
||||
// 7.18.2.4 Limits of integer types capable of holding object pointers
|
||||
#ifdef _WIN64 // [
|
||||
# define INTPTR_MIN INT64_MIN
|
||||
# define INTPTR_MAX INT64_MAX
|
||||
# define UINTPTR_MAX UINT64_MAX
|
||||
#else // _WIN64 ][
|
||||
# define INTPTR_MIN INT32_MIN
|
||||
# define INTPTR_MAX INT32_MAX
|
||||
# define UINTPTR_MAX UINT32_MAX
|
||||
#endif // _WIN64 ]
|
||||
|
||||
// 7.18.2.5 Limits of greatest-width integer types
|
||||
#define INTMAX_MIN INT64_MIN
|
||||
#define INTMAX_MAX INT64_MAX
|
||||
#define UINTMAX_MAX UINT64_MAX
|
||||
|
||||
// 7.18.3 Limits of other integer types
|
||||
|
||||
#ifdef _WIN64 // [
|
||||
# define PTRDIFF_MIN _I64_MIN
|
||||
# define PTRDIFF_MAX _I64_MAX
|
||||
#else // _WIN64 ][
|
||||
# define PTRDIFF_MIN _I32_MIN
|
||||
# define PTRDIFF_MAX _I32_MAX
|
||||
#endif // _WIN64 ]
|
||||
|
||||
#define SIG_ATOMIC_MIN INT_MIN
|
||||
#define SIG_ATOMIC_MAX INT_MAX
|
||||
|
||||
#ifndef SIZE_MAX // [
|
||||
# ifdef _WIN64 // [
|
||||
# define SIZE_MAX _UI64_MAX
|
||||
# else // _WIN64 ][
|
||||
# define SIZE_MAX _UI32_MAX
|
||||
# endif // _WIN64 ]
|
||||
#endif // SIZE_MAX ]
|
||||
|
||||
// WCHAR_MIN and WCHAR_MAX are also defined in <wchar.h>
|
||||
#ifndef WCHAR_MIN // [
|
||||
# define WCHAR_MIN 0
|
||||
#endif // WCHAR_MIN ]
|
||||
#ifndef WCHAR_MAX // [
|
||||
# define WCHAR_MAX _UI16_MAX
|
||||
#endif // WCHAR_MAX ]
|
||||
|
||||
#define WINT_MIN 0
|
||||
#define WINT_MAX _UI16_MAX
|
||||
|
||||
#endif // __STDC_LIMIT_MACROS ]
|
||||
|
||||
|
||||
// 7.18.4 Limits of other integer types
|
||||
|
||||
#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260
|
||||
|
||||
// 7.18.4.1 Macros for minimum-width integer constants
|
||||
|
||||
#define INT8_C(val) val##i8
|
||||
#define INT16_C(val) val##i16
|
||||
#define INT32_C(val) val##i32
|
||||
#define INT64_C(val) val##i64
|
||||
|
||||
#define UINT8_C(val) val##ui8
|
||||
#define UINT16_C(val) val##ui16
|
||||
#define UINT32_C(val) val##ui32
|
||||
#define UINT64_C(val) val##ui64
|
||||
|
||||
// 7.18.4.2 Macros for greatest-width integer constants
|
||||
#define INTMAX_C INT64_C
|
||||
#define UINTMAX_C UINT64_C
|
||||
|
||||
#endif // __STDC_CONSTANT_MACROS ]
|
||||
|
||||
|
||||
#endif // _MSC_STDINT_H_ ]
|
|
@ -0,0 +1,283 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sw=4 et tw=99 ft=cpp:
|
||||
*
|
||||
* ***** 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 Mozilla Code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Jeff Walden <jwalden+code@mit.edu> (original author)
|
||||
*
|
||||
* 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 ***** */
|
||||
|
||||
/*
|
||||
* Implements a smart pointer asserted to remain within a range specified at
|
||||
* construction.
|
||||
*/
|
||||
|
||||
#ifndef mozilla_RangedPtr_h_
|
||||
#define mozilla_RangedPtr_h_
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/Util.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
/*
|
||||
* RangedPtr is a smart pointer restricted to an address range specified at
|
||||
* creation. The pointer (and any smart pointers derived from it) must remain
|
||||
* within the range [start, end] (inclusive of end to facilitate use as
|
||||
* sentinels). Dereferencing or indexing into the pointer (or pointers derived
|
||||
* from it) must remain within the range [start, end). All the standard pointer
|
||||
* operators are defined on it; in debug builds these operations assert that the
|
||||
* range specified at construction is respected.
|
||||
*
|
||||
* In theory passing a smart pointer instance as an argument can be slightly
|
||||
* slower than passing a T* (due to ABI requirements for passing structs versus
|
||||
* passing pointers), if the method being called isn't inlined. If you are in
|
||||
* extremely performance-critical code, you may want to be careful using this
|
||||
* smart pointer as an argument type.
|
||||
*
|
||||
* RangedPtr<T> intentionally does not implicitly convert to T*. Use get() to
|
||||
* explicitly convert to T*. Keep in mind that the raw pointer of course won't
|
||||
* implement bounds checking in debug builds.
|
||||
*/
|
||||
template <typename T>
|
||||
class RangedPtr
|
||||
{
|
||||
T* ptr;
|
||||
|
||||
#ifdef DEBUG
|
||||
T* const rangeStart;
|
||||
T* const rangeEnd;
|
||||
#endif
|
||||
|
||||
void checkSanity() {
|
||||
MOZ_ASSERT(rangeStart <= ptr);
|
||||
MOZ_ASSERT(ptr <= rangeEnd);
|
||||
}
|
||||
|
||||
/* Creates a new pointer for |ptr|, restricted to this pointer's range. */
|
||||
RangedPtr<T> create(T *ptr) const {
|
||||
#ifdef DEBUG
|
||||
return RangedPtr<T>(ptr, rangeStart, rangeEnd);
|
||||
#else
|
||||
return RangedPtr<T>(ptr, NULL, size_t(0));
|
||||
#endif
|
||||
}
|
||||
|
||||
public:
|
||||
RangedPtr(T* p, T* start, T* end)
|
||||
: ptr(p)
|
||||
#ifdef DEBUG
|
||||
, rangeStart(start), rangeEnd(end)
|
||||
#endif
|
||||
{
|
||||
MOZ_ASSERT(rangeStart <= rangeEnd);
|
||||
checkSanity();
|
||||
}
|
||||
RangedPtr(T* p, T* start, size_t length)
|
||||
: ptr(p)
|
||||
#ifdef DEBUG
|
||||
, rangeStart(start), rangeEnd(start + length)
|
||||
#endif
|
||||
{
|
||||
MOZ_ASSERT(length <= size_t(-1) / sizeof(T));
|
||||
MOZ_ASSERT(uintptr_t(rangeStart) + length * sizeof(T) >= uintptr_t(rangeStart));
|
||||
checkSanity();
|
||||
}
|
||||
|
||||
/* Equivalent to RangedPtr(p, p, length). */
|
||||
RangedPtr(T* p, size_t length)
|
||||
: ptr(p)
|
||||
#ifdef DEBUG
|
||||
, rangeStart(p), rangeEnd(p + length)
|
||||
#endif
|
||||
{
|
||||
MOZ_ASSERT(length <= size_t(-1) / sizeof(T));
|
||||
MOZ_ASSERT(uintptr_t(rangeStart) + length * sizeof(T) >= uintptr_t(rangeStart));
|
||||
checkSanity();
|
||||
}
|
||||
|
||||
/* Equivalent to RangedPtr(arr, arr, N). */
|
||||
template<size_t N>
|
||||
RangedPtr(T arr[N])
|
||||
: ptr(arr)
|
||||
#ifdef DEBUG
|
||||
, rangeStart(arr), rangeEnd(arr + N)
|
||||
#endif
|
||||
{
|
||||
checkSanity();
|
||||
}
|
||||
|
||||
T* get() const {
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/*
|
||||
* You can only assign one RangedPtr into another if the two pointers have
|
||||
* the same valid range:
|
||||
*
|
||||
* char arr1[] = "hi";
|
||||
* char arr2[] = "bye";
|
||||
* RangedPtr<char> p1(arr1, 2);
|
||||
* p1 = RangedPtr<char>(arr1 + 1, arr1, arr1 + 2); // works
|
||||
* p1 = RangedPtr<char>(arr2, 3); // asserts
|
||||
*/
|
||||
RangedPtr<T>& operator=(const RangedPtr<T>& other) {
|
||||
MOZ_ASSERT(rangeStart == other.rangeStart);
|
||||
MOZ_ASSERT(rangeEnd == other.rangeEnd);
|
||||
ptr = other.ptr;
|
||||
checkSanity();
|
||||
return *this;
|
||||
}
|
||||
|
||||
RangedPtr<T> operator+(size_t inc) {
|
||||
MOZ_ASSERT(inc <= size_t(-1) / sizeof(T));
|
||||
MOZ_ASSERT(ptr + inc > ptr);
|
||||
return create(ptr + inc);
|
||||
}
|
||||
|
||||
RangedPtr<T> operator-(size_t dec) {
|
||||
MOZ_ASSERT(dec <= size_t(-1) / sizeof(T));
|
||||
MOZ_ASSERT(ptr - dec < ptr);
|
||||
return create(ptr - dec);
|
||||
}
|
||||
|
||||
/*
|
||||
* You can assign a raw pointer into a RangedPtr if the raw pointer is
|
||||
* within the range specified at creation.
|
||||
*/
|
||||
template <typename U>
|
||||
RangedPtr<T>& operator=(U* p) {
|
||||
*this = create(p);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
RangedPtr<T>& operator=(const RangedPtr<U>& p) {
|
||||
MOZ_ASSERT(rangeStart <= p.ptr);
|
||||
MOZ_ASSERT(p.ptr <= rangeEnd);
|
||||
ptr = p.ptr;
|
||||
checkSanity();
|
||||
return *this;
|
||||
}
|
||||
|
||||
RangedPtr<T>& operator++() {
|
||||
return (*this += 1);
|
||||
}
|
||||
|
||||
RangedPtr<T> operator++(int) {
|
||||
RangedPtr<T> rcp = *this;
|
||||
++*this;
|
||||
return rcp;
|
||||
}
|
||||
|
||||
RangedPtr<T>& operator--() {
|
||||
return (*this -= 1);
|
||||
}
|
||||
|
||||
RangedPtr<T> operator--(int) {
|
||||
RangedPtr<T> rcp = *this;
|
||||
--*this;
|
||||
return rcp;
|
||||
}
|
||||
|
||||
RangedPtr<T>& operator+=(size_t inc) {
|
||||
this->operator=<T>(*this + inc);
|
||||
return *this;
|
||||
}
|
||||
|
||||
RangedPtr<T>& operator-=(size_t dec) {
|
||||
this->operator=<T>(*this - dec);
|
||||
return *this;
|
||||
}
|
||||
|
||||
T& operator[](int index) const {
|
||||
MOZ_ASSERT(size_t(index > 0 ? index : -index) <= size_t(-1) / sizeof(T));
|
||||
return *create(ptr + index);
|
||||
}
|
||||
|
||||
T& operator*() const {
|
||||
return *ptr;
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
bool operator==(const RangedPtr<U>& other) const {
|
||||
return ptr == other.ptr;
|
||||
}
|
||||
template <typename U>
|
||||
bool operator!=(const RangedPtr<U>& other) const {
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
template<typename U>
|
||||
bool operator==(const U* u) const {
|
||||
return ptr == u;
|
||||
}
|
||||
template<typename U>
|
||||
bool operator!=(const U* u) const {
|
||||
return !(*this == u);
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
bool operator<(const RangedPtr<U>& other) const {
|
||||
return ptr < other.ptr;
|
||||
}
|
||||
template <typename U>
|
||||
bool operator<=(const RangedPtr<U>& other) const {
|
||||
return ptr <= other.ptr;
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
bool operator>(const RangedPtr<U>& other) const {
|
||||
return ptr > other.ptr;
|
||||
}
|
||||
template <typename U>
|
||||
bool operator>=(const RangedPtr<U>& other) const {
|
||||
return ptr >= other.ptr;
|
||||
}
|
||||
|
||||
size_t operator-(const RangedPtr<T>& other) const {
|
||||
MOZ_ASSERT(ptr >= other.ptr);
|
||||
return PointerRangeSize(other.ptr, ptr);
|
||||
}
|
||||
|
||||
private:
|
||||
RangedPtr() MOZ_DELETE;
|
||||
T* operator&() MOZ_DELETE;
|
||||
operator T*() const MOZ_DELETE;
|
||||
};
|
||||
|
||||
} /* namespace mozilla */
|
||||
|
||||
#endif /* mozilla_RangedPtr_h_ */
|
|
@ -0,0 +1,443 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sw=4 et tw=99 ft=cpp:
|
||||
*
|
||||
* ***** 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 Mozilla Code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Chris Jones <jones.chris.g@gmail.com>
|
||||
*
|
||||
* 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 ***** */
|
||||
|
||||
/* Helpers for defining and using refcounted objects. */
|
||||
|
||||
#ifndef mozilla_RefPtr_h_
|
||||
#define mozilla_RefPtr_h_
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
template<typename T> class RefCounted;
|
||||
template<typename T> class RefPtr;
|
||||
template<typename T> class TemporaryRef;
|
||||
template<typename T> class OutParamRef;
|
||||
template<typename T> OutParamRef<T> byRef(RefPtr<T>&);
|
||||
|
||||
/**
|
||||
* RefCounted<T> is a sort of a "mixin" for a class T. RefCounted
|
||||
* manages, well, refcounting for T, and because RefCounted is
|
||||
* parameterized on T, RefCounted<T> can call T's destructor directly.
|
||||
* This means T doesn't need to have a virtual dtor and so doesn't
|
||||
* need a vtable.
|
||||
*
|
||||
* RefCounted<T> is created with refcount == 0. Newly-allocated
|
||||
* RefCounted<T> must immediately be assigned to a RefPtr to make the
|
||||
* refcount > 0. It's an error to allocate and free a bare
|
||||
* RefCounted<T>, i.e. outside of the RefPtr machinery. Attempts to
|
||||
* do so will abort DEBUG builds.
|
||||
*
|
||||
* Live RefCounted<T> have refcount > 0. The lifetime (refcounts) of
|
||||
* live RefCounted<T> are controlled by RefPtr<T> and
|
||||
* RefPtr<super/subclass of T>. Upon a transition from refcounted==1
|
||||
* to 0, the RefCounted<T> "dies" and is destroyed. The "destroyed"
|
||||
* state is represented in DEBUG builds by refcount==-0xdead. This
|
||||
* state distinguishes use-before-ref (refcount==0) from
|
||||
* use-after-destroy (refcount==-0xdead).
|
||||
*/
|
||||
template<typename T>
|
||||
class RefCounted
|
||||
{
|
||||
friend class RefPtr<T>;
|
||||
|
||||
public:
|
||||
RefCounted() : refCnt(0) { }
|
||||
~RefCounted() { MOZ_ASSERT(refCnt == -0xdead); }
|
||||
|
||||
// Compatibility with nsRefPtr.
|
||||
void AddRef() {
|
||||
MOZ_ASSERT(refCnt >= 0);
|
||||
++refCnt;
|
||||
}
|
||||
|
||||
void Release() {
|
||||
MOZ_ASSERT(refCnt > 0);
|
||||
if (0 == --refCnt) {
|
||||
#ifdef DEBUG
|
||||
refCnt = -0xdead;
|
||||
#endif
|
||||
delete static_cast<T*>(this);
|
||||
}
|
||||
}
|
||||
|
||||
// Compatibility with wtf::RefPtr.
|
||||
void ref() { AddRef(); }
|
||||
void deref() { Release(); }
|
||||
int refCount() const { return refCnt; }
|
||||
bool hasOneRef() const {
|
||||
MOZ_ASSERT(refCnt > 0);
|
||||
return refCnt == 1;
|
||||
}
|
||||
|
||||
private:
|
||||
int refCnt;
|
||||
};
|
||||
|
||||
/**
|
||||
* RefPtr points to a refcounted thing that has AddRef and Release
|
||||
* methods to increase/decrease the refcount, respectively. After a
|
||||
* RefPtr<T> is assigned a T*, the T* can be used through the RefPtr
|
||||
* as if it were a T*.
|
||||
*
|
||||
* A RefPtr can forget its underlying T*, which results in the T*
|
||||
* being wrapped in a temporary object until the T* is either
|
||||
* re-adopted from or released by the temporary.
|
||||
*/
|
||||
template<typename T>
|
||||
class RefPtr
|
||||
{
|
||||
// To allow them to use unref()
|
||||
friend class TemporaryRef<T>;
|
||||
friend class OutParamRef<T>;
|
||||
|
||||
struct dontRef {};
|
||||
|
||||
public:
|
||||
RefPtr() : ptr(0) { }
|
||||
RefPtr(const RefPtr& o) : ptr(ref(o.ptr)) {}
|
||||
RefPtr(const TemporaryRef<T>& o) : ptr(o.drop()) {}
|
||||
RefPtr(T* t) : ptr(ref(t)) {}
|
||||
|
||||
template<typename U>
|
||||
RefPtr(const RefPtr<U>& o) : ptr(ref(o.get())) {}
|
||||
|
||||
~RefPtr() { unref(ptr); }
|
||||
|
||||
RefPtr& operator=(const RefPtr& o) {
|
||||
assign(ref(o.ptr));
|
||||
return *this;
|
||||
}
|
||||
RefPtr& operator=(const TemporaryRef<T>& o) {
|
||||
assign(o.drop());
|
||||
return *this;
|
||||
}
|
||||
RefPtr& operator=(T* t) {
|
||||
assign(ref(t));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename U>
|
||||
RefPtr& operator=(const RefPtr<U>& o) {
|
||||
assign(ref(o.get()));
|
||||
return *this;
|
||||
}
|
||||
|
||||
TemporaryRef<T> forget() {
|
||||
T* tmp = ptr;
|
||||
ptr = 0;
|
||||
return TemporaryRef<T>(tmp, dontRef());
|
||||
}
|
||||
|
||||
T* get() const { return ptr; }
|
||||
operator T*() const { return ptr; }
|
||||
T* operator->() const { return ptr; }
|
||||
T& operator*() const { return *ptr; }
|
||||
template<typename U>
|
||||
operator TemporaryRef<U>() { return TemporaryRef<U>(ptr); }
|
||||
|
||||
private:
|
||||
void assign(T* t) {
|
||||
unref(ptr);
|
||||
ptr = t;
|
||||
}
|
||||
|
||||
T* ptr;
|
||||
|
||||
static MOZ_ALWAYS_INLINE T* ref(T* t) {
|
||||
if (t) {
|
||||
t->AddRef();
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
static MOZ_ALWAYS_INLINE void unref(T* t) {
|
||||
if (t) {
|
||||
t->Release();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* TemporaryRef<T> represents an object that holds a temporary
|
||||
* reference to a T. TemporaryRef objects can't be manually ref'd or
|
||||
* unref'd (being temporaries, not lvalues), so can only relinquish
|
||||
* references to other objects, or unref on destruction.
|
||||
*/
|
||||
template<typename T>
|
||||
class TemporaryRef
|
||||
{
|
||||
// To allow it to construct TemporaryRef from a bare T*
|
||||
friend class RefPtr<T>;
|
||||
|
||||
typedef typename RefPtr<T>::dontRef dontRef;
|
||||
|
||||
public:
|
||||
TemporaryRef(T* t) : ptr(RefPtr<T>::ref(t)) {}
|
||||
TemporaryRef(const TemporaryRef& o) : ptr(o.drop()) {}
|
||||
|
||||
template<typename U>
|
||||
TemporaryRef(const TemporaryRef<U>& o) : ptr(o.drop()) {}
|
||||
|
||||
~TemporaryRef() { RefPtr<T>::unref(ptr); }
|
||||
|
||||
T* drop() const {
|
||||
T* tmp = ptr;
|
||||
ptr = 0;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
private:
|
||||
TemporaryRef(T* t, const dontRef&) : ptr(t) {}
|
||||
|
||||
mutable T* ptr;
|
||||
|
||||
TemporaryRef();
|
||||
TemporaryRef& operator=(const TemporaryRef&);
|
||||
};
|
||||
|
||||
/**
|
||||
* OutParamRef is a wrapper that tracks a refcounted pointer passed as
|
||||
* an outparam argument to a function. OutParamRef implements COM T**
|
||||
* outparam semantics: this requires the callee to AddRef() the T*
|
||||
* returned through the T** outparam on behalf of the caller. This
|
||||
* means the caller (through OutParamRef) must Release() the old
|
||||
* object contained in the tracked RefPtr. It's OK if the callee
|
||||
* returns the same T* passed to it through the T** outparam, as long
|
||||
* as the callee obeys the COM discipline.
|
||||
*
|
||||
* Prefer returning TemporaryRef<T> from functions over creating T**
|
||||
* outparams and passing OutParamRef<T> to T**. Prefer RefPtr<T>*
|
||||
* outparams over T** outparams.
|
||||
*/
|
||||
template<typename T>
|
||||
class OutParamRef
|
||||
{
|
||||
friend OutParamRef byRef<T>(RefPtr<T>&);
|
||||
|
||||
public:
|
||||
~OutParamRef() {
|
||||
RefPtr<T>::unref(refPtr.ptr);
|
||||
refPtr.ptr = tmp;
|
||||
}
|
||||
|
||||
operator T**() { return &tmp; }
|
||||
|
||||
private:
|
||||
OutParamRef(RefPtr<T>& p) : refPtr(p), tmp(p.get()) {}
|
||||
|
||||
RefPtr<T>& refPtr;
|
||||
T* tmp;
|
||||
|
||||
OutParamRef() MOZ_DELETE;
|
||||
OutParamRef& operator=(const OutParamRef&) MOZ_DELETE;
|
||||
};
|
||||
|
||||
/**
|
||||
* byRef cooperates with OutParamRef to implement COM outparam semantics.
|
||||
*/
|
||||
template<typename T>
|
||||
OutParamRef<T>
|
||||
byRef(RefPtr<T>& ptr)
|
||||
{
|
||||
return OutParamRef<T>(ptr);
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_RefPtr_h_
|
||||
|
||||
|
||||
#if 0
|
||||
|
||||
// Command line that builds these tests
|
||||
//
|
||||
// cp RefPtr.h test.cc && g++ -g -Wall -pedantic -DDEBUG -o test test.cc && ./test
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
struct Foo : public RefCounted<Foo>
|
||||
{
|
||||
Foo() : dead(false) { }
|
||||
~Foo() {
|
||||
MOZ_ASSERT(!dead);
|
||||
dead = true;
|
||||
numDestroyed++;
|
||||
}
|
||||
|
||||
bool dead;
|
||||
static int numDestroyed;
|
||||
};
|
||||
int Foo::numDestroyed;
|
||||
|
||||
struct Bar : public Foo { };
|
||||
|
||||
TemporaryRef<Foo>
|
||||
NewFoo()
|
||||
{
|
||||
return RefPtr<Foo>(new Foo());
|
||||
}
|
||||
|
||||
TemporaryRef<Foo>
|
||||
NewBar()
|
||||
{
|
||||
return new Bar();
|
||||
}
|
||||
|
||||
void
|
||||
GetNewFoo(Foo** f)
|
||||
{
|
||||
*f = new Bar();
|
||||
// Kids, don't try this at home
|
||||
(*f)->AddRef();
|
||||
}
|
||||
|
||||
void
|
||||
GetPassedFoo(Foo** f)
|
||||
{
|
||||
// Kids, don't try this at home
|
||||
(*f)->AddRef();
|
||||
}
|
||||
|
||||
void
|
||||
GetNewFoo(RefPtr<Foo>* f)
|
||||
{
|
||||
*f = new Bar();
|
||||
}
|
||||
|
||||
void
|
||||
GetPassedFoo(RefPtr<Foo>* f)
|
||||
{}
|
||||
|
||||
TemporaryRef<Foo>
|
||||
GetNullFoo()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char** argv)
|
||||
{
|
||||
// This should blow up
|
||||
// Foo* f = new Foo(); delete f;
|
||||
|
||||
MOZ_ASSERT(0 == Foo::numDestroyed);
|
||||
{
|
||||
RefPtr<Foo> f = new Foo();
|
||||
MOZ_ASSERT(f->refCount() == 1);
|
||||
}
|
||||
MOZ_ASSERT(1 == Foo::numDestroyed);
|
||||
|
||||
{
|
||||
RefPtr<Foo> f1 = NewFoo();
|
||||
RefPtr<Foo> f2(NewFoo());
|
||||
MOZ_ASSERT(1 == Foo::numDestroyed);
|
||||
}
|
||||
MOZ_ASSERT(3 == Foo::numDestroyed);
|
||||
|
||||
{
|
||||
RefPtr<Foo> b = NewBar();
|
||||
MOZ_ASSERT(3 == Foo::numDestroyed);
|
||||
}
|
||||
MOZ_ASSERT(4 == Foo::numDestroyed);
|
||||
|
||||
{
|
||||
RefPtr<Foo> f1;
|
||||
{
|
||||
f1 = new Foo();
|
||||
RefPtr<Foo> f2(f1);
|
||||
RefPtr<Foo> f3 = f2;
|
||||
MOZ_ASSERT(4 == Foo::numDestroyed);
|
||||
}
|
||||
MOZ_ASSERT(4 == Foo::numDestroyed);
|
||||
}
|
||||
MOZ_ASSERT(5 == Foo::numDestroyed);
|
||||
|
||||
{
|
||||
RefPtr<Foo> f = new Foo();
|
||||
f.forget();
|
||||
MOZ_ASSERT(6 == Foo::numDestroyed);
|
||||
}
|
||||
|
||||
{
|
||||
RefPtr<Foo> f = new Foo();
|
||||
GetNewFoo(byRef(f));
|
||||
MOZ_ASSERT(7 == Foo::numDestroyed);
|
||||
}
|
||||
MOZ_ASSERT(8 == Foo::numDestroyed);
|
||||
|
||||
{
|
||||
RefPtr<Foo> f = new Foo();
|
||||
GetPassedFoo(byRef(f));
|
||||
MOZ_ASSERT(8 == Foo::numDestroyed);
|
||||
}
|
||||
MOZ_ASSERT(9 == Foo::numDestroyed);
|
||||
|
||||
{
|
||||
RefPtr<Foo> f = new Foo();
|
||||
GetNewFoo(&f);
|
||||
MOZ_ASSERT(10 == Foo::numDestroyed);
|
||||
}
|
||||
MOZ_ASSERT(11 == Foo::numDestroyed);
|
||||
|
||||
{
|
||||
RefPtr<Foo> f = new Foo();
|
||||
GetPassedFoo(&f);
|
||||
MOZ_ASSERT(11 == Foo::numDestroyed);
|
||||
}
|
||||
MOZ_ASSERT(12 == Foo::numDestroyed);
|
||||
|
||||
{
|
||||
RefPtr<Foo> f1 = new Bar();
|
||||
}
|
||||
MOZ_ASSERT(13 == Foo::numDestroyed);
|
||||
|
||||
{
|
||||
RefPtr<Foo> f = GetNullFoo();
|
||||
MOZ_ASSERT(13 == Foo::numDestroyed);
|
||||
}
|
||||
MOZ_ASSERT(13 == Foo::numDestroyed);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,224 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* A number of structures to simplify scope-based RAII management. */
|
||||
|
||||
#ifndef mozilla_Scoped_h_
|
||||
#define mozilla_Scoped_h_
|
||||
|
||||
/*
|
||||
* Resource Acquisition Is Initialization is a programming idiom used
|
||||
* to write robust code that is able to deallocate resources properly,
|
||||
* even in presence of execution errors or exceptions that need to be
|
||||
* propagated. The Scoped* classes defined in this header perform the
|
||||
* deallocation of the resource they hold once program execution
|
||||
* reaches the end of the scope for which they have been defined.
|
||||
*
|
||||
* This header provides the following RAII classes:
|
||||
*
|
||||
* - |ScopedFreePtr| - a container for a pointer, that automatically calls
|
||||
* |free()| at the end of the scope;
|
||||
* - |ScopedDeletePtr| - a container for a pointer, that automatically calls
|
||||
* |delete| at the end of the scope;
|
||||
* - |ScopedDeleteArray| - a container for a pointer to an array, that
|
||||
* automatically calls |delete[]| at the end of the scope.
|
||||
*
|
||||
* The general scenario for each of the RAII classes is the following:
|
||||
*
|
||||
* ScopedClass foo(create_value());
|
||||
* // ... In this scope, |foo| is defined. Use |foo.get()| or |foo.rwget()|
|
||||
* to access the value.
|
||||
* // ... In case of |return| or |throw|, |foo| is deallocated automatically.
|
||||
* // ... If |foo| needs to be returned or stored, use |foo.forget()|
|
||||
*
|
||||
* Note that the RAII classes defined in this header do _not_ perform any form
|
||||
* of reference-counting or garbage-collection. These classes have exactly two
|
||||
* behaviors:
|
||||
* - if |forget()| has not been called, the resource is always deallocated at
|
||||
* the end of the scope;
|
||||
* - if |forget()| has been called, any control on the resource is unbound
|
||||
* and the resource is not deallocated by the class.
|
||||
*
|
||||
*
|
||||
* Extension:
|
||||
*
|
||||
* In addition, this header provides class |Scoped| and macro |SCOPED_TEMPLATE|
|
||||
* to simplify the definition of RAII classes for other scenarios. These macros
|
||||
* have been used to automatically close file descriptors/file handles when
|
||||
* reaching the end of the scope, graphics contexts, etc.
|
||||
*/
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/GuardObjects.h"
|
||||
|
||||
/*
|
||||
* Scoped is a helper to create RAII wrappers
|
||||
* Type argument |Traits| is expected to have the following structure:
|
||||
*
|
||||
* struct Traits {
|
||||
* // Define the type of the value stored in the wrapper
|
||||
* typedef value_type type;
|
||||
* // Returns the value corresponding to the uninitialized or freed state
|
||||
* const static type empty();
|
||||
* // Release resources corresponding to the wrapped value
|
||||
* // This function is responsible for not releasing an |empty| value
|
||||
* const static void release(type);
|
||||
* }
|
||||
*/
|
||||
template <typename Traits>
|
||||
class Scoped
|
||||
{
|
||||
public:
|
||||
typedef typename Traits::type Resource;
|
||||
|
||||
explicit Scoped(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM)
|
||||
: value(Traits::empty())
|
||||
{
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
}
|
||||
explicit Scoped(const Resource& value
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||
: value(value)
|
||||
{
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
}
|
||||
~Scoped() {
|
||||
Traits::release(value);
|
||||
}
|
||||
|
||||
// Constant getter
|
||||
operator const Resource&() const { return value; }
|
||||
const Resource& operator->() const { return value; }
|
||||
const Resource& get() const { return value; }
|
||||
// Non-constant getter.
|
||||
Resource& rwget() { return value; }
|
||||
|
||||
/*
|
||||
* Forget the resource.
|
||||
*
|
||||
* Once |forget| has been called, the |Scoped| is neutralized, i.e. it will
|
||||
* have no effect at destruction (unless it is reset to another resource by
|
||||
* |operator=|).
|
||||
*
|
||||
* @return The original resource.
|
||||
*/
|
||||
Resource forget() {
|
||||
Resource tmp = value;
|
||||
value = Traits::empty();
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/*
|
||||
* Perform immediate clean-up of this |Scoped|.
|
||||
*
|
||||
* If this |Scoped| is currently empty, this method has no effect.
|
||||
*/
|
||||
void dispose() {
|
||||
Traits::release(value);
|
||||
value = Traits::empty();
|
||||
}
|
||||
|
||||
bool operator==(const Resource& other) const {
|
||||
return value == other;
|
||||
}
|
||||
|
||||
/*
|
||||
* Replace the resource with another resource.
|
||||
*
|
||||
* Calling |operator=| has the side-effect of triggering clean-up. If you do
|
||||
* not want to trigger clean-up, you should first invoke |forget|.
|
||||
*
|
||||
* @return this
|
||||
*/
|
||||
Scoped<Traits>& operator=(const Resource& other) {
|
||||
return reset(other);
|
||||
}
|
||||
Scoped<Traits>& reset(const Resource& other) {
|
||||
Traits::release(value);
|
||||
value = other;
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
explicit Scoped(const Scoped<Traits>& value) MOZ_DELETE;
|
||||
Scoped<Traits>& operator=(const Scoped<Traits>& value) MOZ_DELETE;
|
||||
|
||||
private:
|
||||
Resource value;
|
||||
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
|
||||
};
|
||||
|
||||
/*
|
||||
* SCOPED_TEMPLATE defines a templated class derived from Scoped
|
||||
* This allows to implement templates such as ScopedFreePtr.
|
||||
*
|
||||
* @param name The name of the class to define.
|
||||
* @param Traits A struct implementing clean-up. See the implementations
|
||||
* for more details.
|
||||
*/
|
||||
#define SCOPED_TEMPLATE(name, Traits) \
|
||||
template <typename Type> \
|
||||
struct name : public Scoped<Traits<Type> > \
|
||||
{ \
|
||||
typedef Scoped<Traits<Type> > Super; \
|
||||
typedef typename Super::Resource Resource; \
|
||||
name& operator=(Resource ptr) { \
|
||||
Super::operator=(ptr); \
|
||||
return *this; \
|
||||
} \
|
||||
explicit name(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM) \
|
||||
: Super(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM_TO_PARENT) \
|
||||
{} \
|
||||
explicit name(Resource ptr \
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_PARAM) \
|
||||
: Super(ptr MOZ_GUARD_OBJECT_NOTIFIER_PARAM_TO_PARENT) \
|
||||
{} \
|
||||
private: \
|
||||
explicit name(name& source) MOZ_DELETE; \
|
||||
name& operator=(name& source) MOZ_DELETE; \
|
||||
};
|
||||
|
||||
/*
|
||||
* ScopedFreePtr is a RAII wrapper for pointers that need to be free()d.
|
||||
*
|
||||
* struct S { ... };
|
||||
* ScopedFreePtr<S> foo = malloc(sizeof(S));
|
||||
* ScopedFreePtr<char> bar = strdup(str);
|
||||
*/
|
||||
template <typename T>
|
||||
struct ScopedFreePtrTraits
|
||||
{
|
||||
typedef T* type;
|
||||
static T* empty() { return NULL; }
|
||||
static void release(T* ptr) { free(ptr); }
|
||||
};
|
||||
SCOPED_TEMPLATE(ScopedFreePtr, ScopedFreePtrTraits)
|
||||
|
||||
/*
|
||||
* ScopedDeletePtr is a RAII wrapper for pointers that need to be deleted.
|
||||
*
|
||||
* struct S { ... };
|
||||
* ScopedDeletePtr<S> foo = new S();
|
||||
*/
|
||||
template <typename T>
|
||||
struct ScopedDeletePtrTraits : public ScopedFreePtrTraits<T> {
|
||||
static void release(T* ptr) { delete ptr; }
|
||||
};
|
||||
SCOPED_TEMPLATE(ScopedDeletePtr, ScopedDeletePtrTraits)
|
||||
|
||||
/*
|
||||
* ScopedDeleteArray is a RAII wrapper for pointers that need to be delete[]ed.
|
||||
*
|
||||
* struct S { ... };
|
||||
* ScopedDeleteArray<S> foo = new S[42];
|
||||
*/
|
||||
template <typename T>
|
||||
struct ScopedDeleteArrayTraits : public ScopedFreePtrTraits<T>
|
||||
{
|
||||
static void release(T* ptr) { delete [] ptr; }
|
||||
};
|
||||
SCOPED_TEMPLATE(ScopedDeleteArray, ScopedDeleteArrayTraits)
|
||||
|
||||
|
||||
#endif // mozilla_Scoped_h_
|
|
@ -0,0 +1,78 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sw=4 et tw=99 ft=cpp:
|
||||
*
|
||||
* ***** 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 Mozilla Code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Jeff Walden <jwalden+code@mit.edu> (original author)
|
||||
*
|
||||
* 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 ***** */
|
||||
|
||||
/* Implements the C99 <stdint.h> interface for C and C++ code. */
|
||||
|
||||
#ifndef mozilla_StandardInteger_h_
|
||||
#define mozilla_StandardInteger_h_
|
||||
|
||||
/*
|
||||
* The C99 standard header <stdint.h> exposes typedefs for common fixed-width
|
||||
* integer types. It would be feasible to simply #include <stdint.h>, but
|
||||
* MSVC++ versions prior to 2010 don't provide <stdint.h>. We could solve this
|
||||
* by reimplementing <stdint.h> for MSVC++ 2008 and earlier. But then we reach
|
||||
* a second problem: our custom <stdint.h> might conflict with a <stdint.h>
|
||||
* defined by an embedder already looking to work around the MSVC++ <stdint.h>
|
||||
* absence.
|
||||
*
|
||||
* We address these issues in this manner:
|
||||
*
|
||||
* 1. If the preprocessor macro MOZ_CUSTOM_STDINT_H is defined to a path to a
|
||||
* custom <stdint.h> implementation, we will #include it. Embedders using
|
||||
* a custom <stdint.h> must define this macro to an implementation that
|
||||
* will work with their embedding.
|
||||
* 2. Otherwise, if we are compiling with a an MSVC++ version without
|
||||
* <stdint.h>, #include our custom <stdint.h> reimplementation.
|
||||
* 3. Otherwise, #include the standard <stdint.h> provided by the compiler.
|
||||
*
|
||||
* Note that we can't call this file "stdint.h" or something case-insensitively
|
||||
* equal to "stdint.h" because then MSVC (and other compilers on
|
||||
* case-insensitive file systems) will include this file, rather than the system
|
||||
* stdint.h, when we ask for <stdint.h> below.
|
||||
*/
|
||||
#if defined(MOZ_CUSTOM_STDINT_H)
|
||||
# include MOZ_CUSTOM_STDINT_H
|
||||
#elif defined(_MSC_VER) && _MSC_VER < 1600
|
||||
# include "mozilla/MSStdInt.h"
|
||||
#else
|
||||
# include <stdint.h>
|
||||
#endif
|
||||
|
||||
#endif /* mozilla_StandardInteger_h_ */
|
|
@ -0,0 +1,170 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sw=4 et tw=99 ft=cpp:
|
||||
*
|
||||
* ***** 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 Mozilla Code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* 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 ***** */
|
||||
|
||||
/* mfbt foundational types and macros. */
|
||||
|
||||
#ifndef mozilla_Types_h_
|
||||
#define mozilla_Types_h_
|
||||
|
||||
/*
|
||||
* This header must be valid C and C++, includable by code embedding either
|
||||
* SpiderMonkey or Gecko.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Expose all the integer types defined in C99's <stdint.h> (and the integer
|
||||
* limit and constant macros, if compiling C code or if compiling C++ code and
|
||||
* the right __STDC_*_MACRO has been defined for each). These are all usable
|
||||
* throughout mfbt code, and throughout Mozilla code more generally.
|
||||
*/
|
||||
#include "mozilla/StandardInteger.h"
|
||||
|
||||
/* Also expose size_t. */
|
||||
#include <stddef.h>
|
||||
|
||||
/* Implement compiler and linker macros needed for APIs. */
|
||||
|
||||
/*
|
||||
* MOZ_EXPORT_API is used to declare and define a method which is externally
|
||||
* visible to users of the current library. It encapsulates various decorations
|
||||
* needed to properly export the method's symbol. MOZ_EXPORT_DATA serves the
|
||||
* same purpose for data.
|
||||
*
|
||||
* api.h:
|
||||
* extern MOZ_EXPORT_API(int) MeaningOfLife(void);
|
||||
* extern MOZ_EXPORT_DATA(int) LuggageCombination;
|
||||
*
|
||||
* api.c:
|
||||
* MOZ_EXPORT_API(int) MeaningOfLife(void) { return 42; }
|
||||
* MOZ_EXPORT_DATA(int) LuggageCombination = 12345;
|
||||
*
|
||||
* If you are merely sharing a method across files, just use plain |extern|.
|
||||
* These macros are designed for use by library interfaces -- not for normal
|
||||
* methods or data used cross-file.
|
||||
*/
|
||||
#if defined(WIN32) || defined(XP_OS2)
|
||||
# define MOZ_EXPORT_API(type) __declspec(dllexport) type
|
||||
# define MOZ_EXPORT_DATA(type) __declspec(dllexport) type
|
||||
#else /* Unix */
|
||||
# ifdef HAVE_VISIBILITY_ATTRIBUTE
|
||||
# define MOZ_EXTERNAL_VIS __attribute__((visibility("default")))
|
||||
# elif defined(__SUNPRO_C) || defined(__SUNPRO_CC)
|
||||
# define MOZ_EXTERNAL_VIS __global
|
||||
# else
|
||||
# define MOZ_EXTERNAL_VIS
|
||||
# endif
|
||||
# define MOZ_EXPORT_API(type) MOZ_EXTERNAL_VIS type
|
||||
# define MOZ_EXPORT_DATA(type) MOZ_EXTERNAL_VIS type
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Whereas implementers use MOZ_EXPORT_API and MOZ_EXPORT_DATA to declare and
|
||||
* define library symbols, users use MOZ_IMPORT_API and MOZ_IMPORT_DATA to
|
||||
* access them. Most often the implementer of the library will expose an API
|
||||
* macro which expands to either the export or import version of the macro,
|
||||
* depending upon the compilation mode.
|
||||
*/
|
||||
#ifdef _WIN32
|
||||
# if defined(__MWERKS__)
|
||||
# define MOZ_IMPORT_API(x) x
|
||||
# else
|
||||
# define MOZ_IMPORT_API(x) __declspec(dllimport) x
|
||||
# endif
|
||||
#elif defined(XP_OS2)
|
||||
# define MOZ_IMPORT_API(x) __declspec(dllimport) x
|
||||
#else
|
||||
# define MOZ_IMPORT_API(x) MOZ_EXPORT_API(x)
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) && !defined(__MWERKS__)
|
||||
# define MOZ_IMPORT_DATA(x) __declspec(dllimport) x
|
||||
#elif defined(XP_OS2)
|
||||
# define MOZ_IMPORT_DATA(x) __declspec(dllimport) x
|
||||
#else
|
||||
# define MOZ_IMPORT_DATA(x) MOZ_EXPORT_DATA(x)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Consistent with the above comment, the MFBT_API and MFBT_DATA macros expose
|
||||
* export mfbt declarations when building mfbt, and they expose import mfbt
|
||||
* declarations when using mfbt.
|
||||
*/
|
||||
#if defined(IMPL_MFBT)
|
||||
# define MFBT_API(type) MOZ_EXPORT_API(type)
|
||||
# define MFBT_DATA(type) MOZ_EXPORT_DATA(type)
|
||||
#else
|
||||
/*
|
||||
* When mozglue is linked in the program, we need the MFBT API symbols
|
||||
* to be weak.
|
||||
*/
|
||||
# if defined(MOZ_GLUE_IN_PROGRAM)
|
||||
# define MFBT_API(type) __attribute__((weak)) MOZ_IMPORT_API(type)
|
||||
# define MFBT_DATA(type) __attribute__((weak)) MOZ_IMPORT_DATA(type)
|
||||
# else
|
||||
# define MFBT_API(type) MOZ_IMPORT_API(type)
|
||||
# define MFBT_DATA(type) MOZ_IMPORT_DATA(type)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* C symbols in C++ code must be declared immediately within |extern "C"|
|
||||
* blocks. However, in C code, they need not be declared specially. This
|
||||
* difference is abstracted behind the MOZ_BEGIN_EXTERN_C and MOZ_END_EXTERN_C
|
||||
* macros, so that the user need not know whether he is being used in C or C++
|
||||
* code.
|
||||
*
|
||||
* MOZ_BEGIN_EXTERN_C
|
||||
*
|
||||
* extern MOZ_EXPORT_API(int) MostRandomNumber(void);
|
||||
* ...other declarations...
|
||||
*
|
||||
* MOZ_END_EXTERN_C
|
||||
*
|
||||
* This said, it is preferable to just use |extern "C"| in C++ header files for
|
||||
* its greater clarity.
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
# define MOZ_BEGIN_EXTERN_C extern "C" {
|
||||
# define MOZ_END_EXTERN_C }
|
||||
#else
|
||||
# define MOZ_BEGIN_EXTERN_C
|
||||
# define MOZ_END_EXTERN_C
|
||||
#endif
|
||||
|
||||
#endif /* mozilla_Types_h_ */
|
|
@ -0,0 +1,364 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sw=4 et tw=99 ft=cpp:
|
||||
*
|
||||
* ***** 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 Mozilla Code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation
|
||||
* Portions created by the Initial Developer are Copyright (C) 2011
|
||||
* 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 ***** */
|
||||
|
||||
/*
|
||||
* Miscellaneous uncategorized functionality. Please add new functionality to
|
||||
* new headers, or to other appropriate existing headers, not here.
|
||||
*/
|
||||
|
||||
#ifndef mozilla_Util_h_
|
||||
#define mozilla_Util_h_
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/Types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
/**
|
||||
* DebugOnly contains a value of type T, but only in debug builds. In
|
||||
* release builds, it does not contain a value. This helper is
|
||||
* intended to be used along with ASSERT()-style macros, allowing one
|
||||
* to write
|
||||
*
|
||||
* DebugOnly<bool> check = Func();
|
||||
* ASSERT(check);
|
||||
*
|
||||
* more concisely than declaring |check| conditional on #ifdef DEBUG,
|
||||
* but also without allocating storage space for |check| in release
|
||||
* builds.
|
||||
*
|
||||
* DebugOnly instances can only be coerced to T in debug builds; in
|
||||
* release builds, they don't have a value so type coercion is not
|
||||
* well defined.
|
||||
*/
|
||||
template <typename T>
|
||||
struct DebugOnly
|
||||
{
|
||||
#ifdef DEBUG
|
||||
T value;
|
||||
|
||||
DebugOnly() {}
|
||||
DebugOnly(const T& other) : value(other) {}
|
||||
DebugOnly(const DebugOnly& other) : value(other.value) {}
|
||||
DebugOnly& operator=(const T& rhs) {
|
||||
value = rhs;
|
||||
return *this;
|
||||
}
|
||||
void operator++(int) {
|
||||
value++;
|
||||
}
|
||||
void operator--(int) {
|
||||
value--;
|
||||
}
|
||||
|
||||
operator T&() { return value; }
|
||||
operator const T&() const { return value; }
|
||||
|
||||
T& operator->() { return value; }
|
||||
|
||||
#else
|
||||
DebugOnly() {}
|
||||
DebugOnly(const T&) {}
|
||||
DebugOnly(const DebugOnly&) {}
|
||||
DebugOnly& operator=(const T&) { return *this; }
|
||||
void operator++(int) {}
|
||||
void operator--(int) {}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* DebugOnly must always have a destructor or else it will
|
||||
* generate "unused variable" warnings, exactly what it's intended
|
||||
* to avoid!
|
||||
*/
|
||||
~DebugOnly() {}
|
||||
};
|
||||
|
||||
/*
|
||||
* This class, and the corresponding macro MOZ_ALIGNOF, figure out how many
|
||||
* bytes of alignment a given type needs.
|
||||
*/
|
||||
template<class T>
|
||||
struct AlignmentFinder
|
||||
{
|
||||
private:
|
||||
struct Aligner
|
||||
{
|
||||
char c;
|
||||
T t;
|
||||
};
|
||||
|
||||
public:
|
||||
static const int alignment = sizeof(Aligner) - sizeof(T);
|
||||
};
|
||||
|
||||
#define MOZ_ALIGNOF(T) mozilla::AlignmentFinder<T>::alignment
|
||||
|
||||
/*
|
||||
* Declare the MOZ_ALIGNED_DECL macro for declaring aligned types.
|
||||
*
|
||||
* For instance,
|
||||
*
|
||||
* MOZ_ALIGNED_DECL(char arr[2], 8);
|
||||
*
|
||||
* will declare a two-character array |arr| aligned to 8 bytes.
|
||||
*/
|
||||
|
||||
#if defined(__GNUC__)
|
||||
# define MOZ_ALIGNED_DECL(_type, _align) \
|
||||
_type __attribute__((aligned(_align)))
|
||||
#elif defined(_MSC_VER)
|
||||
# define MOZ_ALIGNED_DECL(_type, _align) \
|
||||
__declspec(align(_align)) _type
|
||||
#else
|
||||
# warning "We don't know how to align variables on this compiler."
|
||||
# define MOZ_ALIGNED_DECL(_type, _align) _type
|
||||
#endif
|
||||
|
||||
/*
|
||||
* AlignedElem<N> is a structure whose alignment is guaranteed to be at least N bytes.
|
||||
*
|
||||
* We support 1, 2, 4, 8, and 16-bit alignment.
|
||||
*/
|
||||
template<size_t align>
|
||||
struct AlignedElem;
|
||||
|
||||
/*
|
||||
* We have to specialize this template because GCC doesn't like __attribute__((aligned(foo))) where
|
||||
* foo is a template parameter.
|
||||
*/
|
||||
|
||||
template<>
|
||||
struct AlignedElem<1>
|
||||
{
|
||||
MOZ_ALIGNED_DECL(uint8_t elem, 1);
|
||||
};
|
||||
|
||||
template<>
|
||||
struct AlignedElem<2>
|
||||
{
|
||||
MOZ_ALIGNED_DECL(uint8_t elem, 2);
|
||||
};
|
||||
|
||||
template<>
|
||||
struct AlignedElem<4>
|
||||
{
|
||||
MOZ_ALIGNED_DECL(uint8_t elem, 4);
|
||||
};
|
||||
|
||||
template<>
|
||||
struct AlignedElem<8>
|
||||
{
|
||||
MOZ_ALIGNED_DECL(uint8_t elem, 8);
|
||||
};
|
||||
|
||||
template<>
|
||||
struct AlignedElem<16>
|
||||
{
|
||||
MOZ_ALIGNED_DECL(uint8_t elem, 16);
|
||||
};
|
||||
|
||||
/*
|
||||
* This utility pales in comparison to Boost's aligned_storage. The utility
|
||||
* simply assumes that uint64_t is enough alignment for anyone. This may need
|
||||
* to be extended one day...
|
||||
*
|
||||
* As an important side effect, pulling the storage into this template is
|
||||
* enough obfuscation to confuse gcc's strict-aliasing analysis into not giving
|
||||
* false negatives when we cast from the char buffer to whatever type we've
|
||||
* constructed using the bytes.
|
||||
*/
|
||||
template <size_t nbytes>
|
||||
struct AlignedStorage
|
||||
{
|
||||
union U {
|
||||
char bytes[nbytes];
|
||||
uint64_t _;
|
||||
} u;
|
||||
|
||||
const void *addr() const { return u.bytes; }
|
||||
void *addr() { return u.bytes; }
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct AlignedStorage2
|
||||
{
|
||||
union U {
|
||||
char bytes[sizeof(T)];
|
||||
uint64_t _;
|
||||
} u;
|
||||
|
||||
const T *addr() const { return (const T *)u.bytes; }
|
||||
T *addr() { return (T *)(void *)u.bytes; }
|
||||
};
|
||||
|
||||
/*
|
||||
* Small utility for lazily constructing objects without using dynamic storage.
|
||||
* When a Maybe<T> is constructed, it is |empty()|, i.e., no value of T has
|
||||
* been constructed and no T destructor will be called when the Maybe<T> is
|
||||
* destroyed. Upon calling |construct|, a T object will be constructed with the
|
||||
* given arguments and that object will be destroyed when the owning Maybe<T>
|
||||
* is destroyed.
|
||||
*
|
||||
* N.B. GCC seems to miss some optimizations with Maybe and may generate extra
|
||||
* branches/loads/stores. Use with caution on hot paths.
|
||||
*/
|
||||
template <class T>
|
||||
class Maybe
|
||||
{
|
||||
AlignedStorage2<T> storage;
|
||||
bool constructed;
|
||||
|
||||
T &asT() { return *storage.addr(); }
|
||||
|
||||
explicit Maybe(const Maybe &other);
|
||||
const Maybe &operator=(const Maybe &other);
|
||||
|
||||
public:
|
||||
Maybe() { constructed = false; }
|
||||
~Maybe() { if (constructed) asT().~T(); }
|
||||
|
||||
bool empty() const { return !constructed; }
|
||||
|
||||
void construct() {
|
||||
MOZ_ASSERT(!constructed);
|
||||
new(storage.addr()) T();
|
||||
constructed = true;
|
||||
}
|
||||
|
||||
template <class T1>
|
||||
void construct(const T1 &t1) {
|
||||
MOZ_ASSERT(!constructed);
|
||||
new(storage.addr()) T(t1);
|
||||
constructed = true;
|
||||
}
|
||||
|
||||
template <class T1, class T2>
|
||||
void construct(const T1 &t1, const T2 &t2) {
|
||||
MOZ_ASSERT(!constructed);
|
||||
new(storage.addr()) T(t1, t2);
|
||||
constructed = true;
|
||||
}
|
||||
|
||||
template <class T1, class T2, class T3>
|
||||
void construct(const T1 &t1, const T2 &t2, const T3 &t3) {
|
||||
MOZ_ASSERT(!constructed);
|
||||
new(storage.addr()) T(t1, t2, t3);
|
||||
constructed = true;
|
||||
}
|
||||
|
||||
template <class T1, class T2, class T3, class T4>
|
||||
void construct(const T1 &t1, const T2 &t2, const T3 &t3, const T4 &t4) {
|
||||
MOZ_ASSERT(!constructed);
|
||||
new(storage.addr()) T(t1, t2, t3, t4);
|
||||
constructed = true;
|
||||
}
|
||||
|
||||
T *addr() {
|
||||
MOZ_ASSERT(constructed);
|
||||
return &asT();
|
||||
}
|
||||
|
||||
T &ref() {
|
||||
MOZ_ASSERT(constructed);
|
||||
return asT();
|
||||
}
|
||||
|
||||
const T &ref() const {
|
||||
MOZ_ASSERT(constructed);
|
||||
return const_cast<Maybe *>(this)->asT();
|
||||
}
|
||||
|
||||
void destroy() {
|
||||
ref().~T();
|
||||
constructed = false;
|
||||
}
|
||||
|
||||
void destroyIfConstructed() {
|
||||
if (!empty())
|
||||
destroy();
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* Safely subtract two pointers when it is known that end >= begin. This avoids
|
||||
* the common compiler bug that if (size_t(end) - size_t(begin)) has the MSB
|
||||
* set, the unsigned subtraction followed by right shift will produce -1, or
|
||||
* size_t(-1), instead of the real difference.
|
||||
*/
|
||||
template <class T>
|
||||
MOZ_ALWAYS_INLINE size_t
|
||||
PointerRangeSize(T* begin, T* end)
|
||||
{
|
||||
MOZ_ASSERT(end >= begin);
|
||||
return (size_t(end) - size_t(begin)) / sizeof(T);
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute the length of an array with constant length. (Use of this method
|
||||
* with a non-array pointer will not compile.)
|
||||
*
|
||||
* Beware of the implicit trailing '\0' when using this with string constants.
|
||||
*/
|
||||
template<typename T, size_t N>
|
||||
size_t
|
||||
ArrayLength(T (&arr)[N])
|
||||
{
|
||||
return N;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute the address one past the last element of a constant-length array.
|
||||
*
|
||||
* Beware of the implicit trailing '\0' when using this with string constants.
|
||||
*/
|
||||
template<typename T, size_t N>
|
||||
T*
|
||||
ArrayEnd(T (&arr)[N])
|
||||
{
|
||||
return arr + ArrayLength(arr);
|
||||
}
|
||||
|
||||
} /* namespace mozilla */
|
||||
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* mozilla_Util_h_ */
|
|
@ -1 +0,0 @@
|
|||
23b6d1cc9b79e8890ecdb5843796b10e55db6e8d
|
|
@ -1 +0,0 @@
|
|||
a407df409ccdefc38d313c212faffd512787940f
|
|
@ -0,0 +1 @@
|
|||
a63c014d165a6c8390f07040db1cb55d588edd53
|
|
@ -0,0 +1 @@
|
|||
7fd7d46ae368602d9da448188c2ccdde3d43b984
|
Loading…
Reference in New Issue